1// Copyright 2011 The Kyua Authors. 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: 7// 8// * Redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer. 10// * Redistributions in binary form must reproduce the above copyright 11// notice, this list of conditions and the following disclaimer in the 12// documentation and/or other materials provided with the distribution. 13// * Neither the name of Google Inc. nor the names of its contributors 14// may be used to endorse or promote products derived from this software 15// without specific prior written permission. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29#include "drivers/debug_test.hpp" 30 31#include <stdexcept> 32#include <utility> 33 34#include "engine/filters.hpp" 35#include "engine/kyuafile.hpp" 36#include "engine/scanner.hpp" 37#include "engine/scheduler.hpp" 38#include "model/test_case.hpp" 39#include "model/test_program.hpp" 40#include "model/test_result.hpp" 41#include "utils/defs.hpp" 42#include "utils/format/macros.hpp" 43#include "utils/fs/auto_cleaners.hpp" 44#include "utils/optional.ipp" 45 46namespace config = utils::config; 47namespace fs = utils::fs; 48namespace scheduler = engine::scheduler; 49 50using utils::optional; 51 52 53/// Executes the operation. 54/// 55/// \param kyuafile_path The path to the Kyuafile to be loaded. 56/// \param build_root If not none, path to the built test programs. 57/// \param filter The test case filter to locate the test to debug. 58/// \param user_config The end-user configuration properties. 59/// \param stdout_path The name of the file into which to store the test case 60/// stdout. 61/// \param stderr_path The name of the file into which to store the test case 62/// stderr. 63/// 64/// \returns A structure with all results computed by this driver. 65drivers::debug_test::result 66drivers::debug_test::drive(const fs::path& kyuafile_path, 67 const optional< fs::path > build_root, 68 const engine::test_filter& filter, 69 const config::tree& user_config, 70 const fs::path& stdout_path, 71 const fs::path& stderr_path) 72{ 73 scheduler::scheduler_handle handle = scheduler::setup(); 74 75 const engine::kyuafile kyuafile = engine::kyuafile::load( 76 kyuafile_path, build_root, user_config, handle); 77 std::set< engine::test_filter > filters; 78 filters.insert(filter); 79 80 engine::scanner scanner(kyuafile.test_programs(), filters); 81 optional< engine::scan_result > match; 82 while (!match && !scanner.done()) { 83 match = scanner.yield(); 84 } 85 if (!match) { 86 throw std::runtime_error(F("Unknown test case '%s'") % filter.str()); 87 } else if (!scanner.done()) { 88 throw std::runtime_error(F("The filter '%s' matches more than one test " 89 "case") % filter.str()); 90 } 91 INV(match && scanner.done()); 92 const model::test_program_ptr test_program = match.get().first; 93 const std::string& test_case_name = match.get().second; 94 95 scheduler::result_handle_ptr result_handle = handle.debug_test( 96 test_program, test_case_name, user_config, 97 stdout_path, stderr_path); 98 const scheduler::test_result_handle* test_result_handle = 99 dynamic_cast< const scheduler::test_result_handle* >( 100 result_handle.get()); 101 const model::test_result test_result = test_result_handle->test_result(); 102 result_handle->cleanup(); 103 104 handle.check_interrupt(); 105 handle.cleanup(); 106 107 return result(engine::test_filter( 108 test_program->relative_path(), test_case_name), test_result); 109} 110