/// Executes a test program's list operation. /// /// This method is intended to be called within a subprocess and is expected /// to terminate execution either by exec(2)ing the test program or by /// exiting with a failure. /// /// \param test_program The test program to execute. /// \param vars User-provided variables to pass to the test program. void engine::atf_interface::exec_list(const model::test_program& test_program, const config::properties_map& vars) const { utils::setenv("__RUNNING_INSIDE_ATF_RUN", "internal-yes-value"); process::args_vector args; for (config::properties_map::const_iterator iter = vars.begin(); iter != vars.end(); ++iter) { args.push_back(F("-v%s=%s") % (*iter).first % (*iter).second); } args.push_back("-l"); try { process::exec_unsafe(test_program.absolute_path(), args); } catch (const process::system_error& e) { if (e.original_errno() == EACCES) ::_exit(exit_eacces); else if (e.original_errno() == ENOENT) ::_exit(exit_enoent); else if (e.original_errno() == ENOEXEC) ::_exit(exit_enoexec); throw; } }
/// Puts a test program into the database. /// /// \pre The test program has not been put yet. /// \post The test program is stored into the database with a new identifier. /// /// \param test_program The test program to put. /// /// \return The identifier of the inserted test program. /// /// \throw error If there is any problem when talking to the database. int64_t store::write_transaction::put_test_program( const model::test_program& test_program) { try { const int64_t metadata_id = put_metadata( _pimpl->_db, test_program.get_metadata()); sqlite::statement stmt = _pimpl->_db.create_statement( "INSERT INTO test_programs (absolute_path, " " root, relative_path, test_suite_name, " " metadata_id, interface) " "VALUES (:absolute_path, :root, :relative_path, " " :test_suite_name, :metadata_id, :interface)"); stmt.bind(":absolute_path", test_program.absolute_path().str()); // TODO(jmmv): The root is not necessarily absolute. We need to ensure // that we can recover the absolute path of the test program. Maybe we // need to change the test_program to always ensure root is absolute? stmt.bind(":root", test_program.root().str()); stmt.bind(":relative_path", test_program.relative_path().str()); stmt.bind(":test_suite_name", test_program.test_suite_name()); stmt.bind(":metadata_id", metadata_id); stmt.bind(":interface", test_program.interface_name()); stmt.step_without_results(); return _pimpl->_db.last_insert_rowid(); } catch (const sqlite::error& e) { throw error(e.what()); } }
/// Executes a test cleanup routine of the test program. /// /// This method is intended to be called within a subprocess and is expected /// to terminate execution either by exec(2)ing the test program or by /// exiting with a failure. /// /// \param test_program The test program to execute. /// \param test_case_name Name of the test case to invoke. /// \param vars User-provided variables to pass to the test program. /// \param unused_control_directory Directory where the interface may place /// control files. void engine::atf_interface::exec_cleanup( const model::test_program& test_program, const std::string& test_case_name, const config::properties_map& vars, const fs::path& UTILS_UNUSED_PARAM(control_directory)) const { utils::setenv("__RUNNING_INSIDE_ATF_RUN", "internal-yes-value"); process::args_vector args; for (config::properties_map::const_iterator iter = vars.begin(); iter != vars.end(); ++iter) { args.push_back(F("-v%s=%s") % (*iter).first % (*iter).second); } args.push_back(F("%s:cleanup") % test_case_name); process::exec(test_program.absolute_path(), args); }