/// Sets the list of test cases of the test program. /// /// \param test_cases_ The new list of test cases. void set_test_cases(const model::test_cases_map& test_cases_) { for (model::test_cases_map::const_iterator iter = test_cases_.begin(); iter != test_cases_.end(); ++iter) { const std::string& name = (*iter).first; const model::test_case& test_case = (*iter).second; PRE_MSG(name == test_case.name(), F("The test case '%s' has been registered with the " "non-matching name '%s'") % name % test_case.name()); test_cases.insert(model::test_cases_map::value_type( name, test_case.apply_metadata_defaults(&md))); } INV(test_cases.size() == test_cases_.size()); }
/// Retrieves the list of test cases from a test program. /// /// This operation is currently synchronous. /// /// This operation should never throw. Any errors during the processing of the /// test case list are subsumed into a single test case in the return value that /// represents the failed retrieval. /// /// \param test_program The test program from which to obtain the list of test /// cases. /// \param user_config User-provided configuration variables. /// /// \return The list of test cases. model::test_cases_map scheduler::scheduler_handle::list_tests( const model::test_program* test_program, const config::tree& user_config) { _pimpl->generic.check_interrupt(); const std::shared_ptr< scheduler::interface > interface = find_interface( test_program->interface_name()); try { const executor::exec_handle exec_handle = _pimpl->generic.spawn( list_test_cases(interface, test_program, user_config), list_timeout, none); executor::exit_handle exit_handle = _pimpl->generic.wait(exec_handle); const model::test_cases_map test_cases = interface->parse_list( exit_handle.status(), exit_handle.stdout_file(), exit_handle.stderr_file()); exit_handle.cleanup(); if (test_cases.empty()) throw std::runtime_error("Empty test cases list"); return test_cases; } catch (const std::runtime_error& e) { // TODO(jmmv): This is a very ugly workaround for the fact that we // cannot report failures at the test-program level. LW(F("Failed to load test cases list: %s") % e.what()); model::test_cases_map fake_test_cases; fake_test_cases.insert(model::test_cases_map::value_type( "__test_cases_list__", model::test_case( "__test_cases_list__", "Represents the correct processing of the test cases list", model::test_result(model::test_result_broken, e.what())))); return fake_test_cases; } }
/// Constructor. /// /// \param interface_name_ Name of the test program interface. /// \param binary_ The name of the test program binary relative to root_. /// \param root_ The root of the test suite containing the test program. /// \param test_suite_name_ The name of the test suite this program /// belongs to. /// \param md_ Metadata of the test program. /// \param test_cases_ The collection of test cases in the test program. impl(const std::string& interface_name_, const fs::path& binary_, const fs::path& root_, const std::string& test_suite_name_, const model::metadata& md_, const model::test_cases_map& test_cases_) : interface_name(interface_name_), binary(binary_), root(root_), test_suite_name(test_suite_name_), md(md_), test_cases(test_cases_) { PRE_MSG(!binary.is_absolute(), F("The program '%s' must be relative to the root of the test " "suite '%s'") % binary % root); for (model::test_cases_map::const_iterator iter = test_cases.begin(); iter != test_cases.end(); ++iter) { PRE_MSG((*iter).first == (*iter).second.name(), F("The test case '%s' has been registered with the " "non-matching name '%s'") % (*iter).first % (*iter).second.name()); } }