Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F159263725
D55859.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D55859.diff
View Options
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
@@ -143,6 +143,10 @@
mdbuilder.set_string("required_programs", value);
} else if (name == "require.user") {
mdbuilder.set_string("required_user", value);
+ } else if (name == "setup") {
+ mdbuilder.set_string("setup", value);
+ } else if (name == "teardown") {
+ mdbuilder.set_string("teardown", value);
} else if (name == "timeout") {
mdbuilder.set_string("timeout", value);
} else if (name.length() > 2 && name.substr(0, 2) == "X-") {
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
@@ -79,6 +79,8 @@
const strings_set& required_kmods(void) const;
const paths_set& required_programs(void) const;
const std::string& required_user(void) const;
+ const std::string& setup(void) const;
+ const std::string& teardown(void) const;
const utils::datetime::delta& timeout(void) const;
model::properties_map to_properties(void) const;
@@ -125,7 +127,9 @@
metadata_builder& set_required_kmods(const strings_set&);
metadata_builder& set_required_programs(const paths_set&);
metadata_builder& set_required_user(const std::string&);
+ metadata_builder& set_setup(const std::string&);
metadata_builder& set_string(const std::string&, const std::string&);
+ metadata_builder& set_teardown(const std::string&);
metadata_builder& set_timeout(const utils::datetime::delta&);
metadata build(void) const;
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
@@ -259,6 +259,8 @@
tree.define< config::strings_set_node >("required_kmods");
tree.define< paths_set_node >("required_programs");
tree.define< user_node >("required_user");
+ tree.define< config::string_node >("setup");
+ tree.define< config::string_node >("teardown");
tree.define< delta_node >("timeout");
}
@@ -286,6 +288,8 @@
tree.set< config::strings_set_node >("required_kmods", model::strings_set());
tree.set< paths_set_node >("required_programs", model::paths_set());
tree.set< user_node >("required_user", "");
+ tree.set< config::string_node >("setup", ".setup");
+ tree.set< config::string_node >("teardown", ".teardown");
// TODO(jmmv): We shouldn't be setting a default timeout like this. See
// Issue 5 for details.
tree.set< delta_node >("timeout", datetime::delta(300, 0));
@@ -643,6 +647,34 @@
}
+/// Returns setup file name with args.
+///
+/// \return The file name with optional args.
+const std::string&
+model::metadata::setup(void) const
+{
+ if (_pimpl->props.is_set("setup")) {
+ return _pimpl->props.lookup< config::string_node >("setup");
+ } else {
+ return get_defaults().lookup< config::string_node >("setup");
+ }
+}
+
+
+/// Returns teardown file name with args.
+///
+/// \return The file name with optional args.
+const std::string&
+model::metadata::teardown(void) const
+{
+ if (_pimpl->props.is_set("teardown")) {
+ return _pimpl->props.lookup< config::string_node >("teardown");
+ } else {
+ return get_defaults().lookup< config::string_node >("teardown");
+ }
+}
+
+
/// Returns the timeout of the test.
///
/// \return A time delta; should be compared to default_timeout to see if it has
@@ -1104,6 +1136,21 @@
}
+/// Sets setup file name with optional args.
+///
+/// \param name The name of the file.
+///
+/// \return A reference to this builder.
+///
+/// \throw model::error If the value is invalid.
+model::metadata_builder&
+model::metadata_builder::set_setup(const std::string& name)
+{
+ set< config::string_node >(_pimpl->props, "setup", name);
+ return *this;
+}
+
+
/// Sets a metadata property by name from its textual representation.
///
/// \param key The property to set.
@@ -1128,6 +1175,21 @@
}
+/// Sets teardown file name with optional args.
+///
+/// \param name The name of the file.
+///
+/// \return A reference to this builder.
+///
+/// \throw model::error If the value is invalid.
+model::metadata_builder&
+model::metadata_builder::set_teardown(const std::string& name)
+{
+ set< config::string_node >(_pimpl->props, "teardown", name);
+ return *this;
+}
+
+
/// Sets the timeout of the test.
///
/// \param timeout The timeout to set.
diff --git a/contrib/kyua/model/test_program.hpp b/contrib/kyua/model/test_program.hpp
--- a/contrib/kyua/model/test_program.hpp
+++ b/contrib/kyua/model/test_program.hpp
@@ -43,6 +43,7 @@
#include "model/test_case_fwd.hpp"
#include "utils/fs/path_fwd.hpp"
#include "utils/noncopyable.hpp"
+#include "utils/optional_fwd.hpp"
namespace model {
@@ -72,6 +73,9 @@
const model::test_case& find(const std::string&) const;
virtual const model::test_cases_map& test_cases(void) const;
+ utils::optional< utils::fs::path >
+ test_case_setup_file(const std::string&) const;
+ std::string test_case_setup_args(const std::string&) const;
bool operator==(const test_program&) const;
bool operator!=(const test_program&) const;
diff --git a/contrib/kyua/model/test_program.cpp b/contrib/kyua/model/test_program.cpp
--- a/contrib/kyua/model/test_program.cpp
+++ b/contrib/kyua/model/test_program.cpp
@@ -38,13 +38,16 @@
#include "utils/format/containers.ipp"
#include "utils/format/macros.hpp"
#include "utils/fs/path.hpp"
+#include "utils/fs/operations.hpp"
#include "utils/noncopyable.hpp"
+#include "utils/optional.ipp"
#include "utils/sanity.hpp"
#include "utils/text/operations.ipp"
namespace fs = utils::fs;
namespace text = utils::text;
+using utils::optional;
using utils::none;
@@ -236,6 +239,59 @@
}
+/// Gets the path of test case's setup file.
+///
+/// \return The path identified, or none if not found.
+optional< fs::path >
+model::test_program::test_case_setup_file(const std::string& test_case) const
+{
+ const model::test_case& tc = find(test_case);
+
+ std::string name;
+ std::istringstream iss( tc.get_metadata().setup() );
+ iss >> name;
+
+ if (name.empty() || name.size() < 2)
+ return none;
+
+ if (name[0] == '.' && name[1] != '.' && name[1] != '/') {
+ fs::path path(absolute_path().str() + name);
+ if (fs::exists(path))
+ return utils::make_optional(path);
+ else
+ return none;
+ }
+
+ fs::path path = root() / name;
+ if (fs::exists(path))
+ return utils::make_optional(path);
+ else
+ return none;
+}
+
+
+/// Gets the args string for the setup file.
+///
+/// \return The argument string.
+std::string
+model::test_program::test_case_setup_args(const std::string& test_case) const
+{
+ const model::test_case& tc = find(test_case);
+
+ std::string name;
+ std::istringstream iss( tc.get_metadata().setup() );
+ iss >> name;
+
+ if (name.empty() || name.size() < 2)
+ return "";
+
+ std::string args;
+ std::getline(iss, args);
+
+ return args;
+}
+
+
/// Sets the list of test cases of the test program.
///
/// This can only be called once and it may only be called from within
diff --git a/contrib/kyua/os/freebsd/execenv_jail.cpp b/contrib/kyua/os/freebsd/execenv_jail.cpp
--- a/contrib/kyua/os/freebsd/execenv_jail.cpp
+++ b/contrib/kyua/os/freebsd/execenv_jail.cpp
@@ -52,6 +52,16 @@
jail.make_name(_test_program.absolute_path(), _test_case_name),
test_case.get_metadata().execenv_jail_params()
);
+
+ auto setup_file = _test_program.test_case_setup_file(_test_case_name);
+ if (!setup_file)
+ return;
+ jail.jexec(
+ jail.make_name(_test_program.absolute_path(), _test_case_name),
+ "KYUA_TESTDIR=" + _test_program.root().str(),
+ setup_file.get(),
+ _test_program.test_case_setup_args(_test_case_name)
+ );
}
diff --git a/contrib/kyua/os/freebsd/utils/jail.hpp b/contrib/kyua/os/freebsd/utils/jail.hpp
--- a/contrib/kyua/os/freebsd/utils/jail.hpp
+++ b/contrib/kyua/os/freebsd/utils/jail.hpp
@@ -51,6 +51,10 @@
const std::string& test_case_name);
void create(const std::string& jail_name,
const std::string& jail_params);
+ void jexec(const std::string& jail_name,
+ const std::string& env,
+ const fs::path& program,
+ const std::string& program_args);
void exec(const std::string& jail_name,
const fs::path& program,
const args_vector& args) throw() UTILS_NORETURN;
diff --git a/contrib/kyua/os/freebsd/utils/jail.cpp b/contrib/kyua/os/freebsd/utils/jail.cpp
--- a/contrib/kyua/os/freebsd/utils/jail.cpp
+++ b/contrib/kyua/os/freebsd/utils/jail.cpp
@@ -46,6 +46,7 @@
#include <fstream>
#include <iostream>
+#include <sstream>
#include <regex>
#include "model/metadata.hpp"
@@ -227,6 +228,64 @@
}
+/// Prepares and runs jexec.
+///
+/// \param jail_name Name of the jail.
+/// \param program Program path.
+/// \param args Argument vector.
+void
+jail::jexec(const std::string& jail_name,
+ const std::string& env,
+ const fs::path& program,
+ const std::string& program_args)
+{
+ args_vector av;
+
+ // pass work dir prepared by kyua
+ char cwd[PATH_MAX];
+ if (::getcwd(cwd, sizeof(cwd)) == NULL) {
+ std::cerr << "jail::exec: getcwd() errors: "
+ << strerror(errno) << ".\n";
+ std::exit(EXIT_FAILURE);
+ }
+ av.push_back("-d");
+ av.push_back(std::string(cwd));
+
+ // pass env pairs
+ std::istringstream pairs(env);
+ std::string pair;
+ while (pairs >> pair) {
+ av.push_back("-e");
+ av.push_back(pair);
+ }
+
+ // target jail name
+ av.push_back(jail_name);
+
+ // program
+ av.push_back(program.str());
+
+ // program arguments
+ std::istringstream args(program_args);
+ std::string word;
+ while (args >> word)
+ av.push_back(word);
+
+ // invoke jexec
+ std::unique_ptr< process::child > child = child::fork_capture(
+ run(fs::path("/usr/sbin/jexec"), av));
+ process::status status = child->wait();
+
+ std::cerr << child->output().rdbuf();
+
+ // expect success
+ if (status.exited() && status.exitstatus() == EXIT_SUCCESS)
+ return;
+
+ std::exit(EXIT_FAILURE);
+}
+
+
/// Executes an external binary in a jail and replaces the current process.
///
/// \param jail_name Name of the jail to run within.
diff --git a/tests/sys/netpfil/pf/Makefile b/tests/sys/netpfil/pf/Makefile
--- a/tests/sys/netpfil/pf/Makefile
+++ b/tests/sys/netpfil/pf/Makefile
@@ -7,6 +7,7 @@
anchor \
counters \
debug \
+ demo \
divert-to \
dup \
ether \
@@ -75,6 +76,9 @@
TEST_METADATA+= execenv="jail"
TEST_METADATA+= execenv_jail_params="vnet allow.raw_sockets allow.read_msgbuf"
+${PACKAGE}SCRIPTS+= demo.setup \
+ demo.atfsh_like_setup
+
${PACKAGE}FILES+= \
bsnmpd.conf \
CVE-2019-5597.py \
diff --git a/tests/sys/netpfil/pf/demo.atfsh_like_setup b/tests/sys/netpfil/pf/demo.atfsh_like_setup
new file mode 100644
--- /dev/null
+++ b/tests/sys/netpfil/pf/demo.atfsh_like_setup
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+. $KYUA_TESTDIR/../../common/vnet.subr
+vnet_init
+
+epair=$(vnet_mkepair)
+ifconfig ${epair}a 192.0.2.1/24 up
+
+vnet_mkjail alcatraz ${epair}b
+jexec alcatraz ifconfig ${epair}b 192.0.2.100/24 up
diff --git a/tests/sys/netpfil/pf/demo.setup b/tests/sys/netpfil/pf/demo.setup
new file mode 100644
--- /dev/null
+++ b/tests/sys/netpfil/pf/demo.setup
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# A setup file is provided with KYUA_TESTDIR to locate common scripts, etc.
+echo "setup file KYUA_TESTDIR: $KYUA_TESTDIR"
+
+# A setup file is running within test case's temporary directory,
+# so that it could communicate details with the test: names, PIDs, IDs, etc
+echo "setup file PWD: $(pwd)"
+
+# A setup file might be provided with optional args
+echo "setup file args: $*"
+
+# Actual setup example
+addr1="${1:-192.0.2.239}"
+ifconfig lo0 $addr1/24 up
+echo $addr1 > ./addr1
+
diff --git a/tests/sys/netpfil/pf/demo.sh b/tests/sys/netpfil/pf/demo.sh
new file mode 100644
--- /dev/null
+++ b/tests/sys/netpfil/pf/demo.sh
@@ -0,0 +1,41 @@
+atf_test_case "one"
+one_head()
+{
+ atf_set descr 'One'
+ atf_set require.user root
+}
+one_body()
+{
+ atf_check -s exit:0 -o ignore ping -c1 192.0.2.239
+}
+
+atf_test_case "two"
+two_head()
+{
+ atf_set descr 'Two'
+ atf_set require.user root
+ atf_set setup '.setup 192.0.2.1'
+}
+two_body()
+{
+ atf_check -s exit:0 -o ignore ping -c1 192.0.2.1
+}
+
+atf_test_case "three"
+three_head()
+{
+ atf_set descr 'Three'
+ atf_set require.user root
+ atf_set setup .atfsh_like_setup
+}
+three_body()
+{
+ atf_check -s exit:0 -o ignore ping -c1 192.0.2.100
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case "one"
+ atf_add_test_case "two"
+ atf_add_test_case "three"
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jun 13, 1:51 AM (10 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33918548
Default Alt Text
D55859.diff (12 KB)
Attached To
Mode
D55859: kyua: Add external setup and teardown mechanism
Attached
Detach File
Event Timeline
Log In to Comment