xref: /src/contrib/kyua/drivers/debug_test.cpp (revision 6b8222793fbb4c0e162232716bc454dad31b709f)
108334c51SBrooks Davis // Copyright 2011 The Kyua Authors.
208334c51SBrooks Davis // All rights reserved.
308334c51SBrooks Davis //
408334c51SBrooks Davis // Redistribution and use in source and binary forms, with or without
508334c51SBrooks Davis // modification, are permitted provided that the following conditions are
608334c51SBrooks Davis // met:
708334c51SBrooks Davis //
808334c51SBrooks Davis // * Redistributions of source code must retain the above copyright
908334c51SBrooks Davis //   notice, this list of conditions and the following disclaimer.
1008334c51SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
1108334c51SBrooks Davis //   notice, this list of conditions and the following disclaimer in the
1208334c51SBrooks Davis //   documentation and/or other materials provided with the distribution.
1308334c51SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
1408334c51SBrooks Davis //   may be used to endorse or promote products derived from this software
1508334c51SBrooks Davis //   without specific prior written permission.
1608334c51SBrooks Davis //
1708334c51SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1808334c51SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1908334c51SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2008334c51SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2108334c51SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2208334c51SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2308334c51SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2408334c51SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2508334c51SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2608334c51SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2708334c51SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2808334c51SBrooks Davis 
2908334c51SBrooks Davis #include "drivers/debug_test.hpp"
3008334c51SBrooks Davis 
3108334c51SBrooks Davis #include <stdexcept>
3208334c51SBrooks Davis #include <utility>
3308334c51SBrooks Davis 
3408334c51SBrooks Davis #include "engine/filters.hpp"
3508334c51SBrooks Davis #include "engine/kyuafile.hpp"
3608334c51SBrooks Davis #include "engine/scanner.hpp"
3708334c51SBrooks Davis #include "engine/scheduler.hpp"
3808334c51SBrooks Davis #include "model/test_case.hpp"
3908334c51SBrooks Davis #include "model/test_program.hpp"
4008334c51SBrooks Davis #include "model/test_result.hpp"
4108334c51SBrooks Davis #include "utils/defs.hpp"
4208334c51SBrooks Davis #include "utils/format/macros.hpp"
4308334c51SBrooks Davis #include "utils/fs/auto_cleaners.hpp"
4408334c51SBrooks Davis #include "utils/optional.ipp"
4508334c51SBrooks Davis 
4608334c51SBrooks Davis namespace config = utils::config;
4708334c51SBrooks Davis namespace fs = utils::fs;
4808334c51SBrooks Davis namespace scheduler = engine::scheduler;
4908334c51SBrooks Davis 
5008334c51SBrooks Davis using utils::optional;
5108334c51SBrooks Davis 
5208334c51SBrooks Davis 
5308334c51SBrooks Davis /// Executes the operation.
5408334c51SBrooks Davis ///
5508334c51SBrooks Davis /// \param kyuafile_path The path to the Kyuafile to be loaded.
5608334c51SBrooks Davis /// \param build_root If not none, path to the built test programs.
5708334c51SBrooks Davis /// \param filter The test case filter to locate the test to debug.
5808334c51SBrooks Davis /// \param user_config The end-user configuration properties.
5908334c51SBrooks Davis /// \param stdout_path The name of the file into which to store the test case
6008334c51SBrooks Davis ///     stdout.
6108334c51SBrooks Davis /// \param stderr_path The name of the file into which to store the test case
6208334c51SBrooks Davis ///     stderr.
6308334c51SBrooks Davis ///
6408334c51SBrooks Davis /// \returns A structure with all results computed by this driver.
6508334c51SBrooks Davis drivers::debug_test::result
drive(engine::debugger_ptr debugger,const fs::path & kyuafile_path,const optional<fs::path> build_root,const engine::test_filter & filter,const config::tree & user_config,const fs::path & stdout_path,const fs::path & stderr_path)666b822279SIgor Ostapenko drivers::debug_test::drive(engine::debugger_ptr debugger,
676b822279SIgor Ostapenko                            const fs::path& kyuafile_path,
6808334c51SBrooks Davis                            const optional< fs::path > build_root,
6908334c51SBrooks Davis                            const engine::test_filter& filter,
7008334c51SBrooks Davis                            const config::tree& user_config,
7108334c51SBrooks Davis                            const fs::path& stdout_path,
7208334c51SBrooks Davis                            const fs::path& stderr_path)
7308334c51SBrooks Davis {
7408334c51SBrooks Davis     scheduler::scheduler_handle handle = scheduler::setup();
7508334c51SBrooks Davis 
7608334c51SBrooks Davis     const engine::kyuafile kyuafile = engine::kyuafile::load(
7708334c51SBrooks Davis         kyuafile_path, build_root, user_config, handle);
7808334c51SBrooks Davis     std::set< engine::test_filter > filters;
7908334c51SBrooks Davis     filters.insert(filter);
8008334c51SBrooks Davis 
8108334c51SBrooks Davis     engine::scanner scanner(kyuafile.test_programs(), filters);
8208334c51SBrooks Davis     optional< engine::scan_result > match;
8308334c51SBrooks Davis     while (!match && !scanner.done()) {
8408334c51SBrooks Davis         match = scanner.yield();
8508334c51SBrooks Davis     }
8608334c51SBrooks Davis     if (!match) {
8708334c51SBrooks Davis         throw std::runtime_error(F("Unknown test case '%s'") % filter.str());
8808334c51SBrooks Davis     } else if (!scanner.done()) {
8908334c51SBrooks Davis         throw std::runtime_error(F("The filter '%s' matches more than one test "
9008334c51SBrooks Davis                                  "case") % filter.str());
9108334c51SBrooks Davis     }
9208334c51SBrooks Davis     INV(match && scanner.done());
9308334c51SBrooks Davis     const model::test_program_ptr test_program = match.get().first;
9408334c51SBrooks Davis     const std::string& test_case_name = match.get().second;
9508334c51SBrooks Davis 
966b822279SIgor Ostapenko     const model::test_case test_case = test_program->find(test_case_name);
976b822279SIgor Ostapenko     if (debugger)
986b822279SIgor Ostapenko         test_case.attach_debugger(debugger);
996b822279SIgor Ostapenko 
10008334c51SBrooks Davis     scheduler::result_handle_ptr result_handle = handle.debug_test(
10108334c51SBrooks Davis         test_program, test_case_name, user_config,
10208334c51SBrooks Davis         stdout_path, stderr_path);
10308334c51SBrooks Davis     const scheduler::test_result_handle* test_result_handle =
10408334c51SBrooks Davis         dynamic_cast< const scheduler::test_result_handle* >(
10508334c51SBrooks Davis             result_handle.get());
10608334c51SBrooks Davis     const model::test_result test_result = test_result_handle->test_result();
10708334c51SBrooks Davis     result_handle->cleanup();
10808334c51SBrooks Davis 
10908334c51SBrooks Davis     handle.check_interrupt();
11008334c51SBrooks Davis     handle.cleanup();
11108334c51SBrooks Davis 
11208334c51SBrooks Davis     return result(engine::test_filter(
11308334c51SBrooks Davis         test_program->relative_path(), test_case_name), test_result);
11408334c51SBrooks Davis }
115