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(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