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 46 namespace config = utils::config; 47 namespace fs = utils::fs; 48 namespace scheduler = engine::scheduler; 49 50 using 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. 65 drivers::debug_test::result 66 drivers::debug_test::drive(engine::debugger_ptr debugger, 67 const fs::path& kyuafile_path, 68 const optional< fs::path > build_root, 69 const engine::test_filter& filter, 70 const config::tree& user_config, 71 const fs::path& stdout_path, 72 const fs::path& stderr_path) 73 { 74 scheduler::scheduler_handle handle = scheduler::setup(); 75 76 const engine::kyuafile kyuafile = engine::kyuafile::load( 77 kyuafile_path, build_root, user_config, handle); 78 std::set< engine::test_filter > filters; 79 filters.insert(filter); 80 81 engine::scanner scanner(kyuafile.test_programs(), filters); 82 optional< engine::scan_result > match; 83 while (!match && !scanner.done()) { 84 match = scanner.yield(); 85 } 86 if (!match) { 87 throw std::runtime_error(F("Unknown test case '%s'") % filter.str()); 88 } else if (!scanner.done()) { 89 throw std::runtime_error(F("The filter '%s' matches more than one test " 90 "case") % filter.str()); 91 } 92 INV(match && scanner.done()); 93 const model::test_program_ptr test_program = match.get().first; 94 const std::string& test_case_name = match.get().second; 95 96 const model::test_case test_case = test_program->find(test_case_name); 97 if (debugger) 98 test_case.attach_debugger(debugger); 99 100 scheduler::result_handle_ptr result_handle = handle.debug_test( 101 test_program, test_case_name, user_config, 102 stdout_path, stderr_path); 103 const scheduler::test_result_handle* test_result_handle = 104 dynamic_cast< const scheduler::test_result_handle* >( 105 result_handle.get()); 106 const model::test_result test_result = test_result_handle->test_result(); 107 result_handle->cleanup(); 108 109 handle.check_interrupt(); 110 handle.cleanup(); 111 112 return result(engine::test_filter( 113 test_program->relative_path(), test_case_name), test_result); 114 } 115