The branch main has been updated by igoro:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=939fec44a79323ba06cf0ad60d4b69300a8abbc6

commit 939fec44a79323ba06cf0ad60d4b69300a8abbc6
Author:     Igor Ostapenko <ig...@freebsd.org>
AuthorDate: 2025-08-16 23:04:15 +0000
Commit:     Igor Ostapenko <ig...@freebsd.org>
CommitDate: 2025-08-16 23:19:43 +0000

    kyua: Improve required_kmods metadata
    
    - Make it platform agnostic
    - Separate FreeBSD related code
    - Fix tests
    - Make it report all non-loaded modules instead of the first occurrence
      only
    - Update kyuafile.5 man page
    
    Reviewed by:    ngie
    MFC after:      2 weeks
    Pull Request:   https://github.com/freebsd/kyua/pull/270
---
 contrib/kyua/doc/kyuafile.5.in                    | 10 ++++
 contrib/kyua/drivers/report_junit_test.cpp        |  3 ++
 contrib/kyua/engine/atf_list.cpp                  |  2 -
 contrib/kyua/engine/requirements.cpp              | 57 +++++++++++------------
 contrib/kyua/engine/requirements.hpp              | 26 +++++++++++
 contrib/kyua/integration/cmd_report_junit_test.sh |  4 ++
 contrib/kyua/integration/cmd_report_test.sh       |  1 +
 contrib/kyua/model/metadata.cpp                   | 16 +++----
 contrib/kyua/model/metadata.hpp                   |  4 --
 contrib/kyua/model/metadata_test.cpp              |  6 ++-
 contrib/kyua/model/test_case_test.cpp             |  2 +-
 contrib/kyua/model/test_program_test.cpp          |  8 ++--
 contrib/kyua/os/freebsd/main.cpp                  | 11 +++++
 contrib/kyua/os/freebsd/reqs_checker_kmods.cpp    | 50 ++++++++++++++++++++
 contrib/kyua/os/freebsd/reqs_checker_kmods.hpp    | 54 +++++++++++++++++++++
 usr.bin/kyua/Makefile                             |  3 +-
 16 files changed, 203 insertions(+), 54 deletions(-)

diff --git a/contrib/kyua/doc/kyuafile.5.in b/contrib/kyua/doc/kyuafile.5.in
index ae1e4fe40e32..43f00816d407 100644
--- a/contrib/kyua/doc/kyuafile.5.in
+++ b/contrib/kyua/doc/kyuafile.5.in
@@ -290,6 +290,16 @@ it can run.
 .Pp
 ATF:
 .Va require.files
+.It Va required_kmods
+Whitespace-separated list of kernel module names that the test requires to
+be loaded before it can run.
+This requirement checking is platform-dependent.
+It is ignored for a non-supported platform.
+Supported platforms:
+.Fx .
+.Pp
+ATF:
+.Va require.kmods
 .It Va required_memory
 Amount of physical memory that the test needs to run successfully.
 .Pp
diff --git a/contrib/kyua/drivers/report_junit_test.cpp 
b/contrib/kyua/drivers/report_junit_test.cpp
index 0f009c6befd3..1c0929c0fef2 100644
--- a/contrib/kyua/drivers/report_junit_test.cpp
+++ b/contrib/kyua/drivers/report_junit_test.cpp
@@ -70,6 +70,7 @@ static const char* const default_metadata =
     "required_configs is empty\n"
     "required_disk_space = 0\n"
     "required_files is empty\n"
+    "required_kmods is empty\n"
     "required_memory = 0\n"
     "required_programs is empty\n"
     "required_user is empty\n"
@@ -89,6 +90,7 @@ static const char* const overriden_metadata =
     "required_configs is empty\n"
     "required_disk_space = 0\n"
     "required_files is empty\n"
+    "required_kmods is empty\n"
     "required_memory = 0\n"
     "required_programs is empty\n"
     "required_user is empty\n"
@@ -228,6 +230,7 @@ ATF_TEST_CASE_BODY(junit_metadata__overrides)
         + "required_configs = config1\n"
         + "required_disk_space = 456\n"
         + "required_files = file1\n"
+        + "required_kmods is empty\n"
         + "required_memory = 123\n"
         + "required_programs = prog1\n"
         + "required_user = root\n"
diff --git a/contrib/kyua/engine/atf_list.cpp b/contrib/kyua/engine/atf_list.cpp
index e0c4170605d1..5c74a80be913 100644
--- a/contrib/kyua/engine/atf_list.cpp
+++ b/contrib/kyua/engine/atf_list.cpp
@@ -133,10 +133,8 @@ engine::parse_atf_metadata(const model::properties_map& 
props)
                 mdbuilder.set_string("required_disk_space", value);
             } else if (name == "require.files") {
                 mdbuilder.set_string("required_files", value);
-#ifdef __FreeBSD__
             } else if (name == "require.kmods") {
                 mdbuilder.set_string("required_kmods", value);
-#endif
             } else if (name == "require.machine") {
                 mdbuilder.set_string("allowed_platforms", value);
             } else if (name == "require.memory") {
diff --git a/contrib/kyua/engine/requirements.cpp 
b/contrib/kyua/engine/requirements.cpp
index dff43e531a57..d5838b83f33a 100644
--- a/contrib/kyua/engine/requirements.cpp
+++ b/contrib/kyua/engine/requirements.cpp
@@ -41,10 +41,6 @@
 #include "utils/sanity.hpp"
 #include "utils/units.hpp"
 
-#ifdef __FreeBSD__
-#include <libutil.h>
-#endif
-
 namespace config = utils::config;
 namespace fs = utils::fs;
 namespace passwd = utils::passwd;
@@ -224,26 +220,6 @@ check_required_programs(const model::paths_set& 
required_programs)
 }
 
 
-#ifdef __FreeBSD__
-/// Checks if all required kmods are loaded.
-///
-/// \param required_programs Set of kmods.
-///
-/// \return Empty if the required kmods are all loaded or an error
-/// message otherwise.
-static std::string
-check_required_kmods(const model::strings_set& required_kmods)
-{
-    for (model::strings_set::const_iterator iter = required_kmods.begin();
-         iter != required_kmods.end(); iter++) {
-        if (!kld_isloaded((*iter).c_str()))
-            return F("Required kmod '%s' not loaded") % *iter;
-    }
-    return "";
-}
-#endif
-
-
 /// Checks if the current system has the specified amount of memory.
 ///
 /// \param required_memory Amount of required physical memory, or zero if not
@@ -289,9 +265,29 @@ check_required_disk_space(const units::bytes& 
required_disk_space,
 }
 
 
+/// List of registered extra requirement checkers.
+///
+/// Use register_reqs_checker() to add an entry to this global list.
+static std::vector< std::shared_ptr< engine::reqs_checker > > _reqs_checkers;
+
+
 }  // anonymous namespace
 
 
+const std::vector< std::shared_ptr< engine::reqs_checker > >
+engine::reqs_checkers()
+{
+    return _reqs_checkers;
+}
+
+void
+engine::register_reqs_checker(
+    const std::shared_ptr< engine::reqs_checker > checker)
+{
+    _reqs_checkers.push_back(checker);
+}
+
+
 /// Checks if all the requirements specified by the test case are met.
 ///
 /// \param md The test metadata.
@@ -336,12 +332,6 @@ engine::check_reqs(const model::metadata& md, const 
config::tree& cfg,
     if (!reason.empty())
         return reason;
 
-#ifdef __FreeBSD__
-    reason = check_required_kmods(md.required_kmods());
-    if (!reason.empty())
-        return reason;
-#endif
-
     reason = check_required_memory(md.required_memory());
     if (!reason.empty())
         return reason;
@@ -351,6 +341,13 @@ engine::check_reqs(const model::metadata& md, const 
config::tree& cfg,
     if (!reason.empty())
         return reason;
 
+    // Iterate over extra checkers registered.
+    for (auto& checker : engine::reqs_checkers()) {
+        reason = checker->exec(md, cfg, test_suite, work_directory);
+        if (!reason.empty())
+            return reason;
+    }
+
     INV(reason.empty());
     return reason;
 }
diff --git a/contrib/kyua/engine/requirements.hpp 
b/contrib/kyua/engine/requirements.hpp
index a36a938b3034..92e80c5122aa 100644
--- a/contrib/kyua/engine/requirements.hpp
+++ b/contrib/kyua/engine/requirements.hpp
@@ -44,6 +44,32 @@ namespace engine {
 std::string check_reqs(const model::metadata&, const utils::config::tree&,
                        const std::string&, const utils::fs::path&);
 
+/// Abstract interface of a requirement checker.
+class reqs_checker {
+public:
+    /// Constructor.
+    reqs_checker() {}
+
+    /// Destructor.
+    virtual ~reqs_checker() {}
+
+    /// Run the checker.
+    virtual std::string exec(const model::metadata&,
+                             const utils::config::tree&,
+                             const std::string&,
+                             const utils::fs::path&) const = 0;
+};
+
+/// Register an extra requirement checker.
+///
+/// \param checker A requirement checker.
+void register_reqs_checker(const std::shared_ptr< reqs_checker > checker);
+
+/// Returns the list of registered extra requirement checkers.
+///
+/// \return A vector of pointers to extra requirement checkers.
+const std::vector< std::shared_ptr< reqs_checker > > reqs_checkers();
+
 
 }  // namespace engine
 
diff --git a/contrib/kyua/integration/cmd_report_junit_test.sh 
b/contrib/kyua/integration/cmd_report_junit_test.sh
index d86228acf7e5..49b8c5790167 100644
--- a/contrib/kyua/integration/cmd_report_junit_test.sh
+++ b/contrib/kyua/integration/cmd_report_junit_test.sh
@@ -104,6 +104,7 @@ is_exclusive = false
 required_configs is empty
 required_disk_space = 0
 required_files is empty
+required_kmods is empty
 required_memory = 0
 required_programs is empty
 required_user is empty
@@ -144,6 +145,7 @@ is_exclusive = false
 required_configs is empty
 required_disk_space = 0
 required_files is empty
+required_kmods is empty
 required_memory = 0
 required_programs is empty
 required_user is empty
@@ -222,6 +224,7 @@ is_exclusive = false
 required_configs is empty
 required_disk_space = 0
 required_files is empty
+required_kmods is empty
 required_memory = 0
 required_programs is empty
 required_user is empty
@@ -262,6 +265,7 @@ is_exclusive = false
 required_configs is empty
 required_disk_space = 0
 required_files is empty
+required_kmods is empty
 required_memory = 0
 required_programs is empty
 required_user is empty
diff --git a/contrib/kyua/integration/cmd_report_test.sh 
b/contrib/kyua/integration/cmd_report_test.sh
index 8b2b97f9cb4a..1fc1932d3c47 100644
--- a/contrib/kyua/integration/cmd_report_test.sh
+++ b/contrib/kyua/integration/cmd_report_test.sh
@@ -258,6 +258,7 @@ Metadata:
     required_configs is empty
     required_disk_space = 0
     required_files is empty
+    required_kmods is empty
     required_memory = 0
     required_programs is empty
     required_user is empty
diff --git a/contrib/kyua/model/metadata.cpp b/contrib/kyua/model/metadata.cpp
index a5a9a1315964..afb31435a238 100644
--- a/contrib/kyua/model/metadata.cpp
+++ b/contrib/kyua/model/metadata.cpp
@@ -256,9 +256,7 @@ init_tree(config::tree& tree)
     tree.define< bytes_node >("required_disk_space");
     tree.define< paths_set_node >("required_files");
     tree.define< bytes_node >("required_memory");
-#ifdef __FreeBSD__
     tree.define< config::strings_set_node >("required_kmods");
-#endif
     tree.define< paths_set_node >("required_programs");
     tree.define< user_node >("required_user");
     tree.define< delta_node >("timeout");
@@ -285,9 +283,7 @@ set_defaults(config::tree& tree)
     tree.set< bytes_node >("required_disk_space", units::bytes(0));
     tree.set< paths_set_node >("required_files", model::paths_set());
     tree.set< bytes_node >("required_memory", units::bytes(0));
-#ifdef __FreeBSD__
     tree.set< config::strings_set_node >("required_kmods", 
model::strings_set());
-#endif
     tree.set< paths_set_node >("required_programs", model::paths_set());
     tree.set< user_node >("required_user", "");
     // TODO(jmmv): We shouldn't be setting a default timeout like this.  See
@@ -603,20 +599,20 @@ model::metadata::required_memory(void) const
 }
 
 
-#ifdef __FreeBSD__
-/// Returns the list of kmods needed by the test.
+/// Returns the list of kernel modules needed by the test.
 ///
-/// \return Set of strings.
+/// \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");
+        return _pimpl->props.lookup< config::strings_set_node >(
+            "required_kmods");
     } else {
-       return get_defaults().lookup< config::strings_set_node 
>("required_kmods");
+        return get_defaults().lookup< config::strings_set_node >(
+            "required_kmods");
     }
 }
-#endif
 
 
 /// Returns the list of programs needed by the test.
diff --git a/contrib/kyua/model/metadata.hpp b/contrib/kyua/model/metadata.hpp
index 8af6c7c161af..eee7eaf0f7c4 100644
--- a/contrib/kyua/model/metadata.hpp
+++ b/contrib/kyua/model/metadata.hpp
@@ -76,9 +76,7 @@ public:
     const utils::units::bytes& required_disk_space(void) const;
     const paths_set& required_files(void) const;
     const utils::units::bytes& required_memory(void) const;
-#ifdef __FreeBSD__
     const strings_set& required_kmods(void) const;
-#endif
     const paths_set& required_programs(void) const;
     const std::string& required_user(void) const;
     const utils::datetime::delta& timeout(void) const;
@@ -124,9 +122,7 @@ public:
     metadata_builder& set_required_disk_space(const utils::units::bytes&);
     metadata_builder& set_required_files(const paths_set&);
     metadata_builder& set_required_memory(const utils::units::bytes&);
-#ifdef __FreeBSD__
     metadata_builder& set_required_kmods(const strings_set&);
-#endif
     metadata_builder& set_required_programs(const paths_set&);
     metadata_builder& set_required_user(const std::string&);
     metadata_builder& set_string(const std::string&, const std::string&);
diff --git a/contrib/kyua/model/metadata_test.cpp 
b/contrib/kyua/model/metadata_test.cpp
index b4c3dff5b029..bdb1d3655c33 100644
--- a/contrib/kyua/model/metadata_test.cpp
+++ b/contrib/kyua/model/metadata_test.cpp
@@ -57,6 +57,7 @@ ATF_TEST_CASE_BODY(defaults)
     ATF_REQUIRE(md.required_configs().empty());
     ATF_REQUIRE_EQ(units::bytes(0), md.required_disk_space());
     ATF_REQUIRE(md.required_files().empty());
+    ATF_REQUIRE(md.required_kmods().empty());
     ATF_REQUIRE_EQ(units::bytes(0), md.required_memory());
     ATF_REQUIRE(md.required_programs().empty());
     ATF_REQUIRE(md.required_user().empty());
@@ -322,6 +323,7 @@ ATF_TEST_CASE_BODY(to_properties)
     props["required_configs"] = "";
     props["required_disk_space"] = "0";
     props["required_files"] = "bar foo";
+    props["required_kmods"] = "";
     props["required_memory"] = "1.00K";
     props["required_programs"] = "";
     props["required_user"] = "";
@@ -412,7 +414,7 @@ ATF_TEST_CASE_BODY(output__defaults)
                    "has_cleanup='false', is_exclusive='false', "
                    "required_configs='', "
                    "required_disk_space='0', required_files='', "
-                   "required_memory='0', "
+                   "required_kmods='', required_memory='0', "
                    "required_programs='', required_user='', timeout='300'}",
                    str.str());
 }
@@ -435,7 +437,7 @@ ATF_TEST_CASE_BODY(output__some_values)
         "has_cleanup='false', is_exclusive='true', "
         "required_configs='', "
         "required_disk_space='0', required_files='bar foo', "
-        "required_memory='1.00K', "
+        "required_kmods='', required_memory='1.00K', "
         "required_programs='', required_user='', timeout='300'}",
         str.str());
 }
diff --git a/contrib/kyua/model/test_case_test.cpp 
b/contrib/kyua/model/test_case_test.cpp
index 1e2597d1501e..29df7ee35863 100644
--- a/contrib/kyua/model/test_case_test.cpp
+++ b/contrib/kyua/model/test_case_test.cpp
@@ -204,7 +204,7 @@ ATF_TEST_CASE_BODY(test_case__output)
         "has_cleanup='false', "
         "is_exclusive='false', "
         "required_configs='', required_disk_space='0', required_files='', "
-        "required_memory='0', "
+        "required_kmods='', required_memory='0', "
         "required_programs='', required_user='', timeout='300'}}",
         str.str());
 }
diff --git a/contrib/kyua/model/test_program_test.cpp 
b/contrib/kyua/model/test_program_test.cpp
index ddfbc430387c..f7a84d770fc0 100644
--- a/contrib/kyua/model/test_program_test.cpp
+++ b/contrib/kyua/model/test_program_test.cpp
@@ -547,7 +547,7 @@ check_output__no_test_cases(void)
         "description='', execenv='', execenv_jail_params='', "
         "has_cleanup='false', is_exclusive='false', "
         "required_configs='', required_disk_space='0', required_files='', "
-        "required_memory='0', "
+        "required_kmods='', required_memory='0', "
         "required_programs='', required_user='', timeout='300'}, "
         "test_cases=map()}",
         str.str());
@@ -597,7 +597,7 @@ check_output__some_test_cases(void)
         "description='', execenv='', execenv_jail_params='', "
         "has_cleanup='false', is_exclusive='false', "
         "required_configs='', required_disk_space='0', required_files='', "
-        "required_memory='0', "
+        "required_kmods='', required_memory='0', "
         "required_programs='', required_user='', timeout='300'}, "
         "test_cases=map("
         "another-name=test_case{name='another-name', "
@@ -605,14 +605,14 @@ check_output__some_test_cases(void)
         "description='', execenv='', execenv_jail_params='', "
         "has_cleanup='false', is_exclusive='false', "
         "required_configs='', required_disk_space='0', required_files='', "
-        "required_memory='0', "
+        "required_kmods='', required_memory='0', "
         "required_programs='', required_user='', timeout='300'}}, "
         "the-name=test_case{name='the-name', "
         "metadata=metadata{allowed_architectures='a', allowed_platforms='foo', 
"
         "custom.bar='baz', description='', execenv='', execenv_jail_params='', 
"
         "has_cleanup='false', is_exclusive='false', "
         "required_configs='', required_disk_space='0', required_files='', "
-        "required_memory='0', "
+        "required_kmods='', required_memory='0', "
         "required_programs='', required_user='', timeout='300'}})}",
         str.str());
 }
diff --git a/contrib/kyua/os/freebsd/main.cpp b/contrib/kyua/os/freebsd/main.cpp
index 13e5dcf0e023..700284b64b78 100644
--- a/contrib/kyua/os/freebsd/main.cpp
+++ b/contrib/kyua/os/freebsd/main.cpp
@@ -31,6 +31,9 @@
 #include "engine/execenv/execenv.hpp"
 #include "os/freebsd/execenv_jail_manager.hpp"
 
+#include "engine/requirements.hpp"
+#include "os/freebsd/reqs_checker_kmods.hpp"
+
 namespace execenv = engine::execenv;
 
 /// FreeBSD related features initialization.
@@ -50,5 +53,13 @@ freebsd::main(const int, const char* const* const)
         std::shared_ptr< execenv::manager >(new 
freebsd::execenv_jail_manager())
     );
 
+#ifdef __FreeBSD__
+    engine::register_reqs_checker(
+        std::shared_ptr< engine::reqs_checker >(
+            new freebsd::reqs_checker_kmods()
+        )
+    );
+#endif
+
     return 0;
 }
diff --git a/contrib/kyua/os/freebsd/reqs_checker_kmods.cpp 
b/contrib/kyua/os/freebsd/reqs_checker_kmods.cpp
new file mode 100644
index 000000000000..3ae3446a7815
--- /dev/null
+++ b/contrib/kyua/os/freebsd/reqs_checker_kmods.cpp
@@ -0,0 +1,50 @@
+// Copyright 2025 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/reqs_checker_kmods.hpp"
+
+#include "model/metadata.hpp"
+
+extern "C" {
+#include "libutil.h"
+}
+
+std::string
+freebsd::reqs_checker_kmods::exec(const model::metadata& md,
+                                  const utils::config::tree&,
+                                  const std::string&,
+                                  const utils::fs::path&) const
+{
+    std::string reason = "";
+    for (auto& kmod : md.required_kmods())
+        if (!::kld_isloaded((kmod).c_str()))
+            reason += " " + kmod;
+    if (!reason.empty())
+        reason = "Required kmods are not loaded:" + reason + ".";
+    return reason;
+}
diff --git a/contrib/kyua/os/freebsd/reqs_checker_kmods.hpp 
b/contrib/kyua/os/freebsd/reqs_checker_kmods.hpp
new file mode 100644
index 000000000000..8c7c69e35d07
--- /dev/null
+++ b/contrib/kyua/os/freebsd/reqs_checker_kmods.hpp
@@ -0,0 +1,54 @@
+// Copyright 2025 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 os/freebsd/reqs_checker_kmods.hpp
+/// FreeBSD kernel module requirement checker.
+
+#if !defined(FREEBSD_REQS_CHECKER_KMODS)
+#define FREEBSD_REQS_CHECKER_KMODS
+
+#include "engine/requirements.hpp"
+#include "model/metadata_fwd.hpp"
+#include "utils/config/tree_fwd.hpp"
+#include "utils/fs/path_fwd.hpp"
+
+namespace freebsd {
+
+
+class reqs_checker_kmods : public engine::reqs_checker {
+public:
+    std::string exec(const model::metadata&,
+                     const utils::config::tree&,
+                     const std::string&,
+                     const utils::fs::path&) const;
+};
+
+
+}  // namespace freebsd
+
+#endif  // !defined(FREEBSD_REQS_CHECKER_KMODS)
diff --git a/usr.bin/kyua/Makefile b/usr.bin/kyua/Makefile
index a4f95f1106d9..daefedbf8bca 100644
--- a/usr.bin/kyua/Makefile
+++ b/usr.bin/kyua/Makefile
@@ -129,7 +129,8 @@ SRCS+=      engine/atf.cpp                  \
        engine/execenv/execenv_host.cpp
 
 SRCS+= os/freebsd/execenv_jail_manager.cpp     \
-       os/freebsd/main.cpp
+       os/freebsd/main.cpp                     \
+       os/freebsd/reqs_checker_kmods.cpp
 
 SRCS+= store/dbtypes.cpp               \
        store/exceptions.cpp            \

Reply via email to