diff --git a/contrib/kyua/os/freebsd/main.cpp b/contrib/kyua/cli/cmd_prepare.hpp copy from contrib/kyua/os/freebsd/main.cpp copy to contrib/kyua/cli/cmd_prepare.hpp --- a/contrib/kyua/os/freebsd/main.cpp +++ b/contrib/kyua/cli/cmd_prepare.hpp @@ -26,29 +26,28 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "os/freebsd/main.hpp" - -#include "engine/execenv/execenv.hpp" -#include "os/freebsd/execenv_jail_manager.hpp" - -namespace execenv = engine::execenv; - -/// FreeBSD related features initialization. -/// -/// \param argc The number of arguments passed on the command line. -/// \param argv NULL-terminated array containing the command line arguments. -/// -/// \return 0 on success, some other integer on error. -/// -/// \throw std::exception This throws any uncaught exception. Such exceptions -/// are bugs, but we let them propagate so that the runtime will abort and -/// dump core. -int -freebsd::main(const int, const char* const* const) +/// \file cli/cmd_prepare.hpp +/// Provides the cmd_prepare class. + +#if !defined(CLI_CMD_PREPARE_HPP) +#define CLI_CMD_PREPARE_HPP + +#include "cli/common.hpp" + +namespace cli { + + +/// Implementation of the "prepare" subcommand. +class cmd_prepare : public cli_command { - execenv::register_execenv( - std::shared_ptr< execenv::manager >(new freebsd::execenv_jail_manager()) - ); +public: + cmd_prepare(void); + + int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&, + const utils::config::tree&); +}; + + +} // namespace cli - return 0; -} +#endif // !defined(CLI_CMD_PREPARE_HPP) diff --git a/contrib/kyua/os/freebsd/main.cpp b/contrib/kyua/cli/cmd_prepare.cpp copy from contrib/kyua/os/freebsd/main.cpp copy to contrib/kyua/cli/cmd_prepare.cpp --- a/contrib/kyua/os/freebsd/main.cpp +++ b/contrib/kyua/cli/cmd_prepare.cpp @@ -26,29 +26,51 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "os/freebsd/main.hpp" +#include "cli/cmd_prepare.hpp" -#include "engine/execenv/execenv.hpp" -#include "os/freebsd/execenv_jail_manager.hpp" +#include "cli/common.ipp" +#include "engine/rr/rr.hpp" +#include "utils/cmdline/options.hpp" -namespace execenv = engine::execenv; +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace rr = engine::rr; -/// FreeBSD related features initialization. -/// -/// \param argc The number of arguments passed on the command line. -/// \param argv NULL-terminated array containing the command line arguments. +using cli::cmd_prepare; + + +/// Default constructor for cmd_prepare. +cmd_prepare::cmd_prepare(void) : cli_command( + "prepare", "[resolver-name ...]", 0, -1, + "Prepare env and resolve requirements before testing") +{ + add_option(kyuafile_option); + add_option(build_root_option); + add_option(cmdline::bool_option('n', "dry-run", "Do not alter the system")); +} + + +/// Entry point for the "prepare" subcommand. /// -/// \return 0 on success, some other integer on error. +/// \param ui Object to interact with the I/O of the program. +/// \param cmdline Representation of the command line to the subcommand. +/// \param user_config The runtime configuration of the program. /// -/// \throw std::exception This throws any uncaught exception. Such exceptions -/// are bugs, but we let them propagate so that the runtime will abort and -/// dump core. +/// \return 0 if successful, 1 otherwise. int -freebsd::main(const int, const char* const* const) +cmd_prepare::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline, + const config::tree& user_config) { - execenv::register_execenv( - std::shared_ptr< execenv::manager >(new freebsd::execenv_jail_manager()) - ); + // List available resolvers + if (cmdline.arguments().empty()) { + for (auto r : rr::resolvers()) { + ui->out(r->name(), false); + ui->out("\t\t\t", false); + ui->out(r->description()); + } + return EXIT_SUCCESS; + } - return 0; + // Or run specified ones + return rr::run(cmdline.arguments(), ui, cmdline, user_config); } diff --git a/contrib/kyua/cli/main.cpp b/contrib/kyua/cli/main.cpp --- a/contrib/kyua/cli/main.cpp +++ b/contrib/kyua/cli/main.cpp @@ -49,6 +49,7 @@ #include "cli/cmd_debug.hpp" #include "cli/cmd_help.hpp" #include "cli/cmd_list.hpp" +#include "cli/cmd_prepare.hpp" #include "cli/cmd_report.hpp" #include "cli/cmd_report_html.hpp" #include "cli/cmd_report_junit.hpp" @@ -191,6 +192,7 @@ commands.insert(new cli::cmd_debug(), "Workspace"); commands.insert(new cli::cmd_list(), "Workspace"); + commands.insert(new cli::cmd_prepare(), "Workspace"); commands.insert(new cli::cmd_test(), "Workspace"); commands.insert(new cli::cmd_report(), "Reporting"); diff --git a/contrib/kyua/engine/atf_list.cpp b/contrib/kyua/engine/atf_list.cpp --- a/contrib/kyua/engine/atf_list.cpp +++ b/contrib/kyua/engine/atf_list.cpp @@ -129,6 +129,8 @@ mdbuilder.set_string("required_configs", value); } else if (name == "require.files") { mdbuilder.set_string("required_files", value); + } else if (name == "require.kmods") { + mdbuilder.set_string("required_kmods", value); } else if (name == "require.machine") { mdbuilder.set_string("allowed_platforms", value); } else if (name == "require.memory") { diff --git a/contrib/kyua/engine/rr/rr.hpp b/contrib/kyua/engine/rr/rr.hpp new file mode 100644 --- /dev/null +++ b/contrib/kyua/engine/rr/rr.hpp @@ -0,0 +1,107 @@ +// Copyright 2024 The Kyua Authors. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/rr/rr.hpp +/// Requirement resolver subsystem interface. + +#if !defined(ENGINE_RR_RR_HPP) +#define ENGINE_RR_RR_HPP + +#include +#include + +#include "utils/cmdline/parser.ipp" +#include "utils/cmdline/ui.hpp" +#include "utils/config/tree.ipp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; + + +namespace engine { +namespace rr { + + +/// Abstract interface of a requirement resolver. +class interface { +public: + /// Constructor. + interface() {} + + /// Destructor. + virtual ~interface() {} + + /// Returns name of the resolver. + virtual const std::string& name() const = 0; + + /// Returns short description of the resolver. + virtual const std::string& description() const = 0; + + /// Runs the requirement resolver. + /// + /// \param ui Object to interact with the I/O of the program. + /// \param cmdline Representation of the command line to the subcommand. + /// \param user_config The runtime configuration of the program. + /// + /// \return 0 to indicate success. + virtual int exec(cmdline::ui* ui, + const cmdline::parsed_cmdline& cmdline, + const config::tree& user_config) const = 0; +}; + + +/// Registers a requirement resolver. +/// +/// \param resolver A requirement resolver. +void register_resolver(const std::shared_ptr< interface > resolver); + + +/// Returns the list of registered requirement resolvers. +/// +/// \return A vector of pointers to requirement resolvers. +const std::vector< std::shared_ptr< interface > > resolvers(); + + +/// Run named resolvers. +/// +/// \param resolver_names Names of resolvers to run. +/// \param ui Object to interact with the I/O of the program. +/// \param cmdline Representation of the command line to the subcommand. +/// \param user_config The runtime configuration of the program. +/// +/// \return 0 to indicate success. +int run(const std::vector< std::string >& resolver_names, + cmdline::ui* ui, + const cmdline::parsed_cmdline& cmdline, + const config::tree& user_config); + + +} // namespace rr +} // namespace engine + +#endif // !defined(ENGINE_RR_RR_HPP) diff --git a/contrib/kyua/os/freebsd/main.cpp b/contrib/kyua/engine/rr/rr.cpp copy from contrib/kyua/os/freebsd/main.cpp copy to contrib/kyua/engine/rr/rr.cpp --- a/contrib/kyua/os/freebsd/main.cpp +++ b/contrib/kyua/engine/rr/rr.cpp @@ -26,29 +26,58 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "os/freebsd/main.hpp" +#include "engine/rr/rr.hpp" -#include "engine/execenv/execenv.hpp" -#include "os/freebsd/execenv_jail_manager.hpp" +#include "engine/rr/rr_all.hpp" -namespace execenv = engine::execenv; +namespace rr = engine::rr; -/// FreeBSD related features initialization. -/// -/// \param argc The number of arguments passed on the command line. -/// \param argv NULL-terminated array containing the command line arguments. -/// -/// \return 0 on success, some other integer on error. + +/// List of registered execution environments, except default host one. /// -/// \throw std::exception This throws any uncaught exception. Such exceptions -/// are bugs, but we let them propagate so that the runtime will abort and -/// dump core. +/// Use register_execenv() to add an entry to this global list. +static std::vector< std::shared_ptr< rr::interface > > _resolvers = { + std::shared_ptr< rr::interface >(new rr::rr_all()) +}; + + +void +rr::register_resolver(const std::shared_ptr< interface > resolver) +{ + _resolvers.push_back(resolver); +} + + +const std::vector< std::shared_ptr< rr::interface > > +rr::resolvers() +{ + return _resolvers; +} + + int -freebsd::main(const int, const char* const* const) +rr::run(const std::vector< std::string >& resolver_names, + cmdline::ui* ui, + const cmdline::parsed_cmdline& cmdline, + const config::tree& user_config) { - execenv::register_execenv( - std::shared_ptr< execenv::manager >(new freebsd::execenv_jail_manager()) - ); + for (auto rname : resolver_names) { + std::shared_ptr< rr::interface > resolver = nullptr; + for (auto r : rr::resolvers()) + if (r->name() == rname) { + resolver = r; + break; + } + + if (resolver == nullptr) { + ui->out(F("Unknown requirement resolver: %s") % rname); + return EXIT_FAILURE; + } + + if (resolver->exec(ui, cmdline, user_config) != EXIT_SUCCESS) + // suppress the actual code -- main limits possible exit codes + return EXIT_FAILURE; + } - return 0; + return EXIT_SUCCESS; } diff --git a/contrib/kyua/os/freebsd/main.cpp b/contrib/kyua/engine/rr/rr_all.hpp copy from contrib/kyua/os/freebsd/main.cpp copy to contrib/kyua/engine/rr/rr_all.hpp --- a/contrib/kyua/os/freebsd/main.cpp +++ b/contrib/kyua/engine/rr/rr_all.hpp @@ -26,29 +26,28 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "os/freebsd/main.hpp" - -#include "engine/execenv/execenv.hpp" -#include "os/freebsd/execenv_jail_manager.hpp" - -namespace execenv = engine::execenv; - -/// FreeBSD related features initialization. -/// -/// \param argc The number of arguments passed on the command line. -/// \param argv NULL-terminated array containing the command line arguments. -/// -/// \return 0 on success, some other integer on error. -/// -/// \throw std::exception This throws any uncaught exception. Such exceptions -/// are bugs, but we let them propagate so that the runtime will abort and -/// dump core. -int -freebsd::main(const int, const char* const* const) -{ - execenv::register_execenv( - std::shared_ptr< execenv::manager >(new freebsd::execenv_jail_manager()) - ); - - return 0; -} +/// \file engine/rr/rr_all.hpp +/// The requirement resolver which runs all resolvers. + +#if !defined(ENGINE_RR_RR_ALL_HPP) +#define ENGINE_RR_RR_ALL_HPP + +#include "engine/rr/rr.hpp" + +namespace engine { +namespace rr { + + +class rr_all : public rr::interface { +public: + const std::string& name() const; + const std::string& description() const; + int exec(cmdline::ui*, const cmdline::parsed_cmdline&, + const config::tree&) const; +}; + + +} // namespace rr +} // namespace engine + +#endif // !defined(ENGINE_RR_RR_ALL_HPP) diff --git a/contrib/kyua/os/freebsd/main.cpp b/contrib/kyua/engine/rr/rr_all.cpp copy from contrib/kyua/os/freebsd/main.cpp copy to contrib/kyua/engine/rr/rr_all.cpp --- a/contrib/kyua/os/freebsd/main.cpp +++ b/contrib/kyua/engine/rr/rr_all.cpp @@ -26,29 +26,40 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "os/freebsd/main.hpp" - -#include "engine/execenv/execenv.hpp" -#include "os/freebsd/execenv_jail_manager.hpp" - -namespace execenv = engine::execenv; - -/// FreeBSD related features initialization. -/// -/// \param argc The number of arguments passed on the command line. -/// \param argv NULL-terminated array containing the command line arguments. -/// -/// \return 0 on success, some other integer on error. -/// -/// \throw std::exception This throws any uncaught exception. Such exceptions -/// are bugs, but we let them propagate so that the runtime will abort and -/// dump core. +#include "engine/rr/rr_all.hpp" + +static const std::string _name = "all"; +static const std::string _description = "Run all preparations"; + +namespace rr = engine::rr; + + +const std::string& +rr::rr_all::name() const +{ + return _name; +} + + +const std::string& +rr::rr_all::description() const +{ + return _description; +} + + int -freebsd::main(const int, const char* const* const) +rr::rr_all::exec(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline, + const config::tree& user_config) const { - execenv::register_execenv( - std::shared_ptr< execenv::manager >(new freebsd::execenv_jail_manager()) - ); + for (auto r : rr::resolvers()) { + if (r->name() == this->name()) + continue; + + int error = r->exec(ui, cmdline, user_config); + if (error != EXIT_SUCCESS) + return error; + } - return 0; + return EXIT_SUCCESS; } diff --git a/contrib/kyua/model/metadata.hpp b/contrib/kyua/model/metadata.hpp --- a/contrib/kyua/model/metadata.hpp +++ b/contrib/kyua/model/metadata.hpp @@ -75,6 +75,7 @@ const strings_set& required_configs(void) const; const utils::units::bytes& required_disk_space(void) const; const paths_set& required_files(void) const; + const strings_set& required_kmods(void) const; const utils::units::bytes& required_memory(void) const; const paths_set& required_programs(void) const; const std::string& required_user(void) const; @@ -120,6 +121,7 @@ metadata_builder& set_required_configs(const strings_set&); metadata_builder& set_required_disk_space(const utils::units::bytes&); metadata_builder& set_required_files(const paths_set&); + metadata_builder& set_required_kmods(const strings_set&); metadata_builder& set_required_memory(const utils::units::bytes&); metadata_builder& set_required_programs(const paths_set&); metadata_builder& set_required_user(const std::string&); diff --git a/contrib/kyua/model/metadata.cpp b/contrib/kyua/model/metadata.cpp --- a/contrib/kyua/model/metadata.cpp +++ b/contrib/kyua/model/metadata.cpp @@ -255,6 +255,7 @@ tree.define< config::strings_set_node >("required_configs"); tree.define< bytes_node >("required_disk_space"); tree.define< paths_set_node >("required_files"); + tree.define< config::strings_set_node >("required_kmods"); tree.define< bytes_node >("required_memory"); tree.define< paths_set_node >("required_programs"); tree.define< user_node >("required_user"); @@ -281,6 +282,7 @@ model::strings_set()); tree.set< bytes_node >("required_disk_space", units::bytes(0)); tree.set< paths_set_node >("required_files", model::paths_set()); + tree.set< config::strings_set_node >("required_kmods", model::strings_set()); tree.set< bytes_node >("required_memory", units::bytes(0)); tree.set< paths_set_node >("required_programs", model::paths_set()); tree.set< user_node >("required_user", ""); @@ -583,6 +585,22 @@ } +/// Returns the list of kernel modules needed by the test. +/// +/// \return Set of kernel module names. +const model::strings_set& +model::metadata::required_kmods(void) const +{ + if (_pimpl->props.is_set("required_kmods")) { + return _pimpl->props.lookup< config::strings_set_node >( + "required_kmods"); + } else { + return get_defaults().lookup< config::strings_set_node >( + "required_kmods"); + } +} + + /// Returns the amount of memory required by the test. /// /// \return Number of bytes, or 0 if this does not apply. diff --git a/contrib/kyua/os/freebsd/main.cpp b/contrib/kyua/os/freebsd/main.cpp --- a/contrib/kyua/os/freebsd/main.cpp +++ b/contrib/kyua/os/freebsd/main.cpp @@ -31,7 +31,12 @@ #include "engine/execenv/execenv.hpp" #include "os/freebsd/execenv_jail_manager.hpp" +#include "engine/rr/rr.hpp" +#include "os/freebsd/rr_kmods.hpp" + namespace execenv = engine::execenv; +namespace rr = engine::rr; + /// FreeBSD related features initialization. /// @@ -50,5 +55,9 @@ std::shared_ptr< execenv::manager >(new freebsd::execenv_jail_manager()) ); +#ifdef __FreeBSD__ + rr::register_resolver(std::shared_ptr< rr::interface >(new freebsd::rr_kmods())); +#endif + return 0; } diff --git a/contrib/kyua/os/freebsd/main.cpp b/contrib/kyua/os/freebsd/rr_kmods.hpp copy from contrib/kyua/os/freebsd/main.cpp copy to contrib/kyua/os/freebsd/rr_kmods.hpp --- a/contrib/kyua/os/freebsd/main.cpp +++ b/contrib/kyua/os/freebsd/rr_kmods.hpp @@ -26,29 +26,29 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "os/freebsd/main.hpp" - -#include "engine/execenv/execenv.hpp" -#include "os/freebsd/execenv_jail_manager.hpp" - -namespace execenv = engine::execenv; - -/// FreeBSD related features initialization. -/// -/// \param argc The number of arguments passed on the command line. -/// \param argv NULL-terminated array containing the command line arguments. -/// -/// \return 0 on success, some other integer on error. -/// -/// \throw std::exception This throws any uncaught exception. Such exceptions -/// are bugs, but we let them propagate so that the runtime will abort and -/// dump core. -int -freebsd::main(const int, const char* const* const) -{ - execenv::register_execenv( - std::shared_ptr< execenv::manager >(new freebsd::execenv_jail_manager()) - ); - - return 0; -} +/// \file os/freebsd/rr_kmods.hpp +/// FreeBSD requirement resolver of required_kmods. + +#if !defined(FREEBSD_RR_KMODS_HPP) +#define FREEBSD_RR_KMODS_HPP + +#include "engine/rr/rr.hpp" + +namespace rr = engine::rr; + + +namespace freebsd { + + +class rr_kmods : public rr::interface { +public: + const std::string& name() const; + const std::string& description() const; + int exec(cmdline::ui*, const cmdline::parsed_cmdline&, + const config::tree&) const; +}; + + +} // namespace freebsd + +#endif // !defined(FREEBSD_RR_KMODS_HPP) diff --git a/contrib/kyua/os/freebsd/rr_kmods.cpp b/contrib/kyua/os/freebsd/rr_kmods.cpp new file mode 100644 --- /dev/null +++ b/contrib/kyua/os/freebsd/rr_kmods.cpp @@ -0,0 +1,139 @@ +// Copyright 2024 The Kyua Authors. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "os/freebsd/rr_kmods.hpp" + +#include "cli/common.hpp" +#include "drivers/list_tests.hpp" +#include "engine/filters.hpp" +#include "model/metadata.hpp" +#include "model/test_case.hpp" +#include "model/test_program.hpp" + +// FreeBSD kldload syscall +extern "C" { +#include +#include +} + + +namespace { + + +static const std::string _name = "kmods"; +static const std::string _description = "FreeBSD: kldload modules declared using required_kmods metadata"; + + +/// Hooks for list_tests to examine test cases as they come. +class list_hooks : public drivers::list_tests::base_hooks { + /// Collected names of required kernel modules. + std::set< std::string >& _modules; + +public: + /// Initializes the hooks. + /// + /// \param modules_ The set of modules to fill. + list_hooks(std::set< std::string >& modules_) : + _modules(modules_) + { + } + + /// Examine a test case as soon as it is found. + /// + /// \param test_program The test program containing the test case. + /// \param test_case_name The name of the located test case. + void + got_test_case(const model::test_program& test_program, + const std::string& test_case_name) + { + auto test_case = test_program.find(test_case_name); + auto kmods = test_case.get_metadata().required_kmods(); + _modules.insert(kmods.begin(), kmods.end()); + } +}; + + +} // anonymous namespace + + +namespace freebsd { + + +const std::string& +rr_kmods::name() const +{ + return _name; +} + + +const std::string& +rr_kmods::description() const +{ + return _description; +} + + +int +rr_kmods::exec(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline, + const config::tree& user_config) const +{ + // Collect required modules + std::set< std::string > modules; + list_hooks hooks(modules); + const std::set< engine::test_filter > nofilters; + const drivers::list_tests::result result = drivers::list_tests::drive( + cli::kyuafile_path(cmdline), cli::build_root_path(cmdline), + nofilters, user_config, hooks); + + // Nothing to do + if (modules.empty()) + return EXIT_SUCCESS; + + // Announce the work + ui->out("kldload", false); + for (auto m : modules) + ui->out(F(" %s") % m, false); + ui->out(""); + + if (cmdline.has_option("dry-run")) + return EXIT_SUCCESS; + + // Load the modules + for (auto m : modules) { + if (::kldload(m.c_str()) != -1 || errno == EEXIST) + continue; + ui->err(F("kldload %s: ") % m, false); + ui->err(strerror(errno)); + return errno; + } + + return EXIT_SUCCESS; +} + + +} // namespace freebsd diff --git a/usr.bin/kyua/Makefile b/usr.bin/kyua/Makefile --- a/usr.bin/kyua/Makefile +++ b/usr.bin/kyua/Makefile @@ -129,10 +129,13 @@ engine/tap_parser.cpp \ engine/scheduler.cpp \ engine/execenv/execenv.cpp \ - engine/execenv/execenv_host.cpp + engine/execenv/execenv_host.cpp \ + engine/rr/rr.cpp \ + engine/rr/rr_all.cpp SRCS+= os/freebsd/execenv_jail_manager.cpp \ - os/freebsd/main.cpp + os/freebsd/main.cpp \ + os/freebsd/rr_kmods.cpp SRCS+= store/dbtypes.cpp \ store/exceptions.cpp \ @@ -157,6 +160,7 @@ cli/cmd_debug.cpp \ cli/cmd_help.cpp \ cli/cmd_list.cpp \ + cli/cmd_prepare.cpp \ cli/cmd_report.cpp \ cli/cmd_report_html.cpp \ cli/cmd_report_junit.cpp \