111be35a1SLionel Sambuc // Copyright 2010 Google Inc.
211be35a1SLionel Sambuc // All rights reserved.
311be35a1SLionel Sambuc //
411be35a1SLionel Sambuc // Redistribution and use in source and binary forms, with or without
511be35a1SLionel Sambuc // modification, are permitted provided that the following conditions are
611be35a1SLionel Sambuc // met:
711be35a1SLionel Sambuc //
811be35a1SLionel Sambuc // * Redistributions of source code must retain the above copyright
911be35a1SLionel Sambuc // notice, this list of conditions and the following disclaimer.
1011be35a1SLionel Sambuc // * Redistributions in binary form must reproduce the above copyright
1111be35a1SLionel Sambuc // notice, this list of conditions and the following disclaimer in the
1211be35a1SLionel Sambuc // documentation and/or other materials provided with the distribution.
1311be35a1SLionel Sambuc // * Neither the name of Google Inc. nor the names of its contributors
1411be35a1SLionel Sambuc // may be used to endorse or promote products derived from this software
1511be35a1SLionel Sambuc // without specific prior written permission.
1611be35a1SLionel Sambuc //
1711be35a1SLionel Sambuc // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1811be35a1SLionel Sambuc // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1911be35a1SLionel Sambuc // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2011be35a1SLionel Sambuc // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2111be35a1SLionel Sambuc // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2211be35a1SLionel Sambuc // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2311be35a1SLionel Sambuc // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2411be35a1SLionel Sambuc // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2511be35a1SLionel Sambuc // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2611be35a1SLionel Sambuc // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2711be35a1SLionel Sambuc // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2811be35a1SLionel Sambuc
2911be35a1SLionel Sambuc #include "engine/test_case.hpp"
3011be35a1SLionel Sambuc
3111be35a1SLionel Sambuc extern "C" {
3211be35a1SLionel Sambuc #include <sys/stat.h>
3311be35a1SLionel Sambuc
3411be35a1SLionel Sambuc #include <signal.h>
3511be35a1SLionel Sambuc #include <unistd.h>
3611be35a1SLionel Sambuc }
3711be35a1SLionel Sambuc
3811be35a1SLionel Sambuc #include <cerrno>
3911be35a1SLionel Sambuc #include <cstdlib>
4011be35a1SLionel Sambuc #include <fstream>
4111be35a1SLionel Sambuc #include <iostream>
4211be35a1SLionel Sambuc #include <sstream>
4311be35a1SLionel Sambuc #include <stdexcept>
4411be35a1SLionel Sambuc #include <string>
4511be35a1SLionel Sambuc
4611be35a1SLionel Sambuc #include <atf-c++.hpp>
4711be35a1SLionel Sambuc
4811be35a1SLionel Sambuc #include "engine/config.hpp"
4911be35a1SLionel Sambuc #include "engine/exceptions.hpp"
5011be35a1SLionel Sambuc #include "engine/kyuafile.hpp"
5111be35a1SLionel Sambuc #include "engine/test_program.hpp"
5211be35a1SLionel Sambuc #include "engine/test_result.hpp"
5311be35a1SLionel Sambuc #include "utils/config/tree.ipp"
5411be35a1SLionel Sambuc #include "utils/datetime.hpp"
5511be35a1SLionel Sambuc #include "utils/env.hpp"
5611be35a1SLionel Sambuc #include "utils/format/macros.hpp"
5711be35a1SLionel Sambuc #include "utils/fs/operations.hpp"
5811be35a1SLionel Sambuc #include "utils/noncopyable.hpp"
5911be35a1SLionel Sambuc #include "utils/optional.ipp"
6011be35a1SLionel Sambuc #include "utils/passwd.hpp"
6111be35a1SLionel Sambuc #include "utils/process/child.ipp"
6211be35a1SLionel Sambuc #include "utils/sanity.hpp"
6311be35a1SLionel Sambuc #include "utils/stream.hpp"
6411be35a1SLionel Sambuc
6511be35a1SLionel Sambuc namespace config = utils::config;
6611be35a1SLionel Sambuc namespace datetime = utils::datetime;
6711be35a1SLionel Sambuc namespace fs = utils::fs;
6811be35a1SLionel Sambuc namespace passwd = utils::passwd;
6911be35a1SLionel Sambuc namespace process = utils::process;
7011be35a1SLionel Sambuc
7111be35a1SLionel Sambuc using utils::none;
7211be35a1SLionel Sambuc using utils::optional;
7311be35a1SLionel Sambuc
7411be35a1SLionel Sambuc
7511be35a1SLionel Sambuc namespace {
7611be35a1SLionel Sambuc
7711be35a1SLionel Sambuc
7811be35a1SLionel Sambuc /// Test case hooks to capture stdout and stderr in memory.
7911be35a1SLionel Sambuc class capture_hooks : public engine::test_case_hooks {
8011be35a1SLionel Sambuc public:
8111be35a1SLionel Sambuc /// Contents of the stdout of the test case.
8211be35a1SLionel Sambuc std::string stdout_contents;
8311be35a1SLionel Sambuc
8411be35a1SLionel Sambuc /// Contents of the stderr of the test case.
8511be35a1SLionel Sambuc std::string stderr_contents;
8611be35a1SLionel Sambuc
8711be35a1SLionel Sambuc /// Stores the stdout of the test case into stdout_contents.
8811be35a1SLionel Sambuc ///
8911be35a1SLionel Sambuc /// \param file The path to the file containing the stdout.
9011be35a1SLionel Sambuc void
got_stdout(const fs::path & file)9111be35a1SLionel Sambuc got_stdout(const fs::path& file)
9211be35a1SLionel Sambuc {
9311be35a1SLionel Sambuc atf::utils::cat_file(file.str(), "helper stdout:");
9411be35a1SLionel Sambuc ATF_REQUIRE(stdout_contents.empty());
9511be35a1SLionel Sambuc
9611be35a1SLionel Sambuc std::ifstream input(file.c_str());
9711be35a1SLionel Sambuc ATF_REQUIRE(input);
9811be35a1SLionel Sambuc stdout_contents = utils::read_stream(input);
9911be35a1SLionel Sambuc }
10011be35a1SLionel Sambuc
10111be35a1SLionel Sambuc /// Stores the stderr of the test case into stderr_contents.
10211be35a1SLionel Sambuc ///
10311be35a1SLionel Sambuc /// \param file The path to the file containing the stderr.
10411be35a1SLionel Sambuc void
got_stderr(const fs::path & file)10511be35a1SLionel Sambuc got_stderr(const fs::path& file)
10611be35a1SLionel Sambuc {
10711be35a1SLionel Sambuc atf::utils::cat_file(file.str(), "helper stderr:");
10811be35a1SLionel Sambuc ATF_REQUIRE(stderr_contents.empty());
10911be35a1SLionel Sambuc
11011be35a1SLionel Sambuc std::ifstream input(file.c_str());
11111be35a1SLionel Sambuc ATF_REQUIRE(input);
11211be35a1SLionel Sambuc stderr_contents = utils::read_stream(input);
11311be35a1SLionel Sambuc }
11411be35a1SLionel Sambuc };
11511be35a1SLionel Sambuc
11611be35a1SLionel Sambuc
11711be35a1SLionel Sambuc /// Launcher for the helper test cases.
11811be35a1SLionel Sambuc ///
11911be35a1SLionel Sambuc /// This builder class can be used to construct the runtime state of the helper
12011be35a1SLionel Sambuc /// test cases and later run them. The class also provides other helper methods
12111be35a1SLionel Sambuc /// to interact with the helper binary.
12211be35a1SLionel Sambuc class atf_helper : utils::noncopyable {
12311be35a1SLionel Sambuc /// Path to the test program's source directory.
12411be35a1SLionel Sambuc const fs::path _srcdir;
12511be35a1SLionel Sambuc
12611be35a1SLionel Sambuc /// The root of the test suite.
12711be35a1SLionel Sambuc fs::path _root;
12811be35a1SLionel Sambuc
12911be35a1SLionel Sambuc /// Path to the helper test program, relative to _root.
13011be35a1SLionel Sambuc fs::path _binary_path;
13111be35a1SLionel Sambuc
13211be35a1SLionel Sambuc /// Name of the helper test case to run.
13311be35a1SLionel Sambuc const std::string _name;
13411be35a1SLionel Sambuc
13511be35a1SLionel Sambuc /// Metadata of the test case.
13611be35a1SLionel Sambuc engine::metadata_builder _mdbuilder;
13711be35a1SLionel Sambuc
13811be35a1SLionel Sambuc /// Run-time configuration for the test case.
13911be35a1SLionel Sambuc config::tree _user_config;
14011be35a1SLionel Sambuc
14111be35a1SLionel Sambuc public:
14211be35a1SLionel Sambuc /// Constructs a new helper.
14311be35a1SLionel Sambuc ///
14411be35a1SLionel Sambuc /// \param atf_tc A pointer to the calling test case. Needed to obtain
14511be35a1SLionel Sambuc /// run-time configuration variables.
14611be35a1SLionel Sambuc /// \param name The name of the helper to run.
atf_helper(const atf::tests::tc * atf_tc,const char * name)14711be35a1SLionel Sambuc atf_helper(const atf::tests::tc* atf_tc, const char* name) :
14811be35a1SLionel Sambuc _srcdir(atf_tc->get_config_var("srcdir")),
14911be35a1SLionel Sambuc _root(_srcdir),
15011be35a1SLionel Sambuc _binary_path("test_case_atf_helpers"),
15111be35a1SLionel Sambuc _name(name),
15211be35a1SLionel Sambuc _user_config(engine::default_config())
15311be35a1SLionel Sambuc {
15411be35a1SLionel Sambuc _user_config.set_string("architecture", "mock-architecture");
15511be35a1SLionel Sambuc _user_config.set_string("platform", "mock-platform");
15611be35a1SLionel Sambuc }
15711be35a1SLionel Sambuc
15811be35a1SLionel Sambuc /// Provides raw access to the run-time configuration.
15911be35a1SLionel Sambuc ///
16011be35a1SLionel Sambuc /// To override test-suite-specific variables, use set_config() as it
16111be35a1SLionel Sambuc /// abstracts away the name of the fake test suite.
16211be35a1SLionel Sambuc ///
16311be35a1SLionel Sambuc /// \returns A reference to the test case configuration.
16411be35a1SLionel Sambuc config::tree&
config(void)16511be35a1SLionel Sambuc config(void)
16611be35a1SLionel Sambuc {
16711be35a1SLionel Sambuc return _user_config;
16811be35a1SLionel Sambuc }
16911be35a1SLionel Sambuc
17011be35a1SLionel Sambuc /// Sets a test-suite-specific configuration variable for the helper.
17111be35a1SLionel Sambuc ///
17211be35a1SLionel Sambuc /// \param variable The name of the environment variable to set.
17311be35a1SLionel Sambuc /// \param value The value of the variable; must be convertible to a string.
17411be35a1SLionel Sambuc template< typename T >
17511be35a1SLionel Sambuc void
set_config(const char * variable,const T & value)17611be35a1SLionel Sambuc set_config(const char* variable, const T& value)
17711be35a1SLionel Sambuc {
17811be35a1SLionel Sambuc _user_config.set_string(F("test_suites.the-suite.%s") % variable,
17911be35a1SLionel Sambuc F("%s") % value);
18011be35a1SLionel Sambuc }
18111be35a1SLionel Sambuc
18211be35a1SLionel Sambuc /// Sets a metadata variable for the helper.
18311be35a1SLionel Sambuc ///
18411be35a1SLionel Sambuc /// \param variable The name of the environment variable to set.
18511be35a1SLionel Sambuc /// \param value The value of the variable; must be convertible to a string.
18611be35a1SLionel Sambuc template< typename T >
18711be35a1SLionel Sambuc void
set_metadata(const char * variable,const T & value)18811be35a1SLionel Sambuc set_metadata(const char* variable, const T& value)
18911be35a1SLionel Sambuc {
19011be35a1SLionel Sambuc _mdbuilder.set_string(variable, F("%s") % value);
19111be35a1SLionel Sambuc }
19211be35a1SLionel Sambuc
19311be35a1SLionel Sambuc /// Places the helper in a different location.
19411be35a1SLionel Sambuc ///
19511be35a1SLionel Sambuc /// This prepares the helper to be run from a different location than the
19611be35a1SLionel Sambuc /// source directory so that the runtime execution can be validated.
19711be35a1SLionel Sambuc ///
19811be35a1SLionel Sambuc /// \param new_binary_path The new path to the binary, relative to the test
19911be35a1SLionel Sambuc /// suite root.
20011be35a1SLionel Sambuc /// \param new_root The new test suite root.
20111be35a1SLionel Sambuc ///
20211be35a1SLionel Sambuc /// \pre The directory holding the target test program must exist.
20311be35a1SLionel Sambuc /// Otherwise, the relocation of the binary will fail.
20411be35a1SLionel Sambuc void
move(const char * new_binary_path,const char * new_root)20511be35a1SLionel Sambuc move(const char* new_binary_path, const char* new_root)
20611be35a1SLionel Sambuc {
20711be35a1SLionel Sambuc _binary_path = fs::path(new_binary_path);
20811be35a1SLionel Sambuc _root = fs::path(new_root);
20911be35a1SLionel Sambuc
21011be35a1SLionel Sambuc const fs::path src_path = fs::path(_srcdir / "test_case_atf_helpers");
21111be35a1SLionel Sambuc const fs::path new_path = _root / _binary_path;
21211be35a1SLionel Sambuc ATF_REQUIRE(
21311be35a1SLionel Sambuc ::symlink(src_path.c_str(), new_path.c_str()) != -1);
21411be35a1SLionel Sambuc }
21511be35a1SLionel Sambuc
21611be35a1SLionel Sambuc /// Runs the helper.
21711be35a1SLionel Sambuc ///
21811be35a1SLionel Sambuc /// \return The result of the execution.
21911be35a1SLionel Sambuc engine::test_result
run(void) const22011be35a1SLionel Sambuc run(void) const
22111be35a1SLionel Sambuc {
22211be35a1SLionel Sambuc engine::test_case_hooks dummy_hooks;
22311be35a1SLionel Sambuc return run(dummy_hooks);
22411be35a1SLionel Sambuc }
22511be35a1SLionel Sambuc
22611be35a1SLionel Sambuc /// Runs the helper.
22711be35a1SLionel Sambuc ///
22811be35a1SLionel Sambuc /// \param hooks The hooks to pass to the test case.
22911be35a1SLionel Sambuc ///
23011be35a1SLionel Sambuc /// \return The result of the execution.
23111be35a1SLionel Sambuc engine::test_result
run(engine::test_case_hooks & hooks) const23211be35a1SLionel Sambuc run(engine::test_case_hooks& hooks) const
23311be35a1SLionel Sambuc {
23411be35a1SLionel Sambuc const engine::test_program test_program(
23511be35a1SLionel Sambuc "atf", _binary_path, _root, "the-suite",
23611be35a1SLionel Sambuc engine::metadata_builder().build());
23711be35a1SLionel Sambuc const engine::test_case test_case("atf", test_program, _name,
23811be35a1SLionel Sambuc _mdbuilder.build());
23911be35a1SLionel Sambuc
24011be35a1SLionel Sambuc const fs::path workdir("work");
24111be35a1SLionel Sambuc fs::mkdir(workdir, 0755);
24211be35a1SLionel Sambuc
24311be35a1SLionel Sambuc const engine::test_result result = engine::run_test_case(
24411be35a1SLionel Sambuc &test_case, _user_config, hooks, workdir);
24511be35a1SLionel Sambuc ATF_REQUIRE(::rmdir(workdir.c_str()) != -1);
24611be35a1SLionel Sambuc return result;
24711be35a1SLionel Sambuc }
24811be35a1SLionel Sambuc };
24911be35a1SLionel Sambuc
25011be35a1SLionel Sambuc
25111be35a1SLionel Sambuc /// Hooks to retrieve stdout and stderr.
25211be35a1SLionel Sambuc class fetch_output_hooks : public engine::test_case_hooks {
25311be35a1SLionel Sambuc public:
25411be35a1SLionel Sambuc /// Copies the stdout of the test case outside of its work directory.
25511be35a1SLionel Sambuc ///
25611be35a1SLionel Sambuc /// \param file The location of the test case's stdout.
25711be35a1SLionel Sambuc void
got_stdout(const fs::path & file)25811be35a1SLionel Sambuc got_stdout(const fs::path& file)
25911be35a1SLionel Sambuc {
26011be35a1SLionel Sambuc atf::utils::copy_file(file.str(), "helper-stdout.txt");
26111be35a1SLionel Sambuc atf::utils::cat_file("helper-stdout.txt", "helper stdout: ");
26211be35a1SLionel Sambuc }
26311be35a1SLionel Sambuc
26411be35a1SLionel Sambuc /// Copies the stderr of the test case outside of its work directory.
26511be35a1SLionel Sambuc ///
26611be35a1SLionel Sambuc /// \param file The location of the test case's stderr.
26711be35a1SLionel Sambuc void
got_stderr(const fs::path & file)26811be35a1SLionel Sambuc got_stderr(const fs::path& file)
26911be35a1SLionel Sambuc {
27011be35a1SLionel Sambuc atf::utils::copy_file(file.str(), "helper-stderr.txt");
27111be35a1SLionel Sambuc atf::utils::cat_file("helper-stderr.txt", "helper stderr: ");
27211be35a1SLionel Sambuc }
27311be35a1SLionel Sambuc };
27411be35a1SLionel Sambuc
27511be35a1SLionel Sambuc
27611be35a1SLionel Sambuc /// Simplifies the execution of the helper test cases.
27711be35a1SLionel Sambuc class plain_helper {
27811be35a1SLionel Sambuc /// Path to the test program's source directory.
27911be35a1SLionel Sambuc const fs::path _srcdir;
28011be35a1SLionel Sambuc
28111be35a1SLionel Sambuc /// The root of the test suite.
28211be35a1SLionel Sambuc fs::path _root;
28311be35a1SLionel Sambuc
28411be35a1SLionel Sambuc /// Path to the helper test program, relative to _root.
28511be35a1SLionel Sambuc fs::path _binary_path;
28611be35a1SLionel Sambuc
28711be35a1SLionel Sambuc /// Optional timeout for the test program.
28811be35a1SLionel Sambuc optional< datetime::delta > _timeout;
28911be35a1SLionel Sambuc
29011be35a1SLionel Sambuc public:
29111be35a1SLionel Sambuc /// Constructs a new helper.
29211be35a1SLionel Sambuc ///
29311be35a1SLionel Sambuc /// \param atf_tc A pointer to the calling test case. Needed to obtain
29411be35a1SLionel Sambuc /// run-time configuration variables.
29511be35a1SLionel Sambuc /// \param name The name of the helper to run.
29611be35a1SLionel Sambuc /// \param timeout An optional timeout for the test case.
plain_helper(const atf::tests::tc * atf_tc,const char * name,const optional<datetime::delta> timeout=none)29711be35a1SLionel Sambuc plain_helper(const atf::tests::tc* atf_tc, const char* name,
29811be35a1SLionel Sambuc const optional< datetime::delta > timeout = none) :
29911be35a1SLionel Sambuc _srcdir(atf_tc->get_config_var("srcdir")),
30011be35a1SLionel Sambuc _root(_srcdir),
30111be35a1SLionel Sambuc _binary_path("test_case_plain_helpers"),
30211be35a1SLionel Sambuc _timeout(timeout)
30311be35a1SLionel Sambuc {
30411be35a1SLionel Sambuc utils::setenv("TEST_CASE", name);
30511be35a1SLionel Sambuc }
30611be35a1SLionel Sambuc
30711be35a1SLionel Sambuc /// Sets an environment variable for the helper.
30811be35a1SLionel Sambuc ///
30911be35a1SLionel Sambuc /// This is simply syntactic sugar for utils::setenv.
31011be35a1SLionel Sambuc ///
31111be35a1SLionel Sambuc /// \param variable The name of the environment variable to set.
31211be35a1SLionel Sambuc /// \param value The value of the variable; must be convertible to a string.
31311be35a1SLionel Sambuc template< typename T >
31411be35a1SLionel Sambuc void
set(const char * variable,const T & value)31511be35a1SLionel Sambuc set(const char* variable, const T& value)
31611be35a1SLionel Sambuc {
31711be35a1SLionel Sambuc utils::setenv(variable, F("%s") % value);
31811be35a1SLionel Sambuc }
31911be35a1SLionel Sambuc
32011be35a1SLionel Sambuc /// Places the helper in a different location.
32111be35a1SLionel Sambuc ///
32211be35a1SLionel Sambuc /// This prepares the helper to be run from a different location than the
32311be35a1SLionel Sambuc /// source directory so that the runtime execution can be validated.
32411be35a1SLionel Sambuc ///
32511be35a1SLionel Sambuc /// \param new_binary_path The new path to the binary, relative to the test
32611be35a1SLionel Sambuc /// suite root.
32711be35a1SLionel Sambuc /// \param new_root The new test suite root.
32811be35a1SLionel Sambuc ///
32911be35a1SLionel Sambuc /// \pre The directory holding the target test program must exist.
33011be35a1SLionel Sambuc /// Otherwise, the relocation of the binary will fail.
33111be35a1SLionel Sambuc void
move(const char * new_binary_path,const char * new_root)33211be35a1SLionel Sambuc move(const char* new_binary_path, const char* new_root)
33311be35a1SLionel Sambuc {
33411be35a1SLionel Sambuc _binary_path = fs::path(new_binary_path);
33511be35a1SLionel Sambuc _root = fs::path(new_root);
33611be35a1SLionel Sambuc
33711be35a1SLionel Sambuc const fs::path src_path = fs::path(_srcdir) / "test_case_plain_helpers";
33811be35a1SLionel Sambuc const fs::path new_path = _root / _binary_path;
33911be35a1SLionel Sambuc ATF_REQUIRE(
34011be35a1SLionel Sambuc ::symlink(src_path.c_str(), new_path.c_str()) != -1);
34111be35a1SLionel Sambuc }
34211be35a1SLionel Sambuc
34311be35a1SLionel Sambuc /// Runs the helper.
34411be35a1SLionel Sambuc ///
34511be35a1SLionel Sambuc /// \param user_config The runtime engine configuration, if different to the
34611be35a1SLionel Sambuc /// defaults.
34711be35a1SLionel Sambuc ///
34811be35a1SLionel Sambuc /// \return The result of the execution.
34911be35a1SLionel Sambuc engine::test_result
run(const config::tree & user_config=engine::default_config ()) const35011be35a1SLionel Sambuc run(const config::tree& user_config = engine::default_config()) const
35111be35a1SLionel Sambuc {
35211be35a1SLionel Sambuc engine::metadata_builder mdbuilder;
35311be35a1SLionel Sambuc if (_timeout)
35411be35a1SLionel Sambuc mdbuilder.set_timeout(_timeout.get());
35511be35a1SLionel Sambuc const engine::test_program test_program(
35611be35a1SLionel Sambuc "plain", _binary_path, _root, "unit-tests", mdbuilder.build());
35711be35a1SLionel Sambuc const engine::test_cases_vector& tcs = test_program.test_cases();
35811be35a1SLionel Sambuc fetch_output_hooks fetcher;
35911be35a1SLionel Sambuc const engine::test_result result = engine::run_test_case(
36011be35a1SLionel Sambuc tcs[0].get(), user_config, fetcher, fs::path("."));
36111be35a1SLionel Sambuc std::cerr << "Result is: " << result << '\n';
36211be35a1SLionel Sambuc return result;
36311be35a1SLionel Sambuc }
36411be35a1SLionel Sambuc };
36511be35a1SLionel Sambuc
36611be35a1SLionel Sambuc
367*84d9c625SLionel Sambuc /// Creates a mock tester that receives a signal.
368*84d9c625SLionel Sambuc ///
369*84d9c625SLionel Sambuc /// \param interface The name of the interface implemented by the tester.
370*84d9c625SLionel Sambuc /// \param term_sig Signal to deliver to the tester. If the tester does not
371*84d9c625SLionel Sambuc /// exit due to this reason, it exits with an arbitrary non-zero code.
372*84d9c625SLionel Sambuc static void
create_mock_tester_signal(const char * interface,const int term_sig)373*84d9c625SLionel Sambuc create_mock_tester_signal(const char* interface, const int term_sig)
374*84d9c625SLionel Sambuc {
375*84d9c625SLionel Sambuc const std::string tester_name = F("kyua-%s-tester") % interface;
376*84d9c625SLionel Sambuc
377*84d9c625SLionel Sambuc atf::utils::create_file(
378*84d9c625SLionel Sambuc tester_name,
379*84d9c625SLionel Sambuc F("#! /bin/sh\n"
380*84d9c625SLionel Sambuc "echo 'stdout stuff'\n"
381*84d9c625SLionel Sambuc "echo 'stderr stuff' 1>&2\n"
382*84d9c625SLionel Sambuc "kill -%s $$\n"
383*84d9c625SLionel Sambuc "echo 'not reachable' 1>&2\n"
384*84d9c625SLionel Sambuc "exit 0\n") % term_sig);
385*84d9c625SLionel Sambuc ATF_REQUIRE(::chmod(tester_name.c_str(), 0755) != -1);
386*84d9c625SLionel Sambuc
387*84d9c625SLionel Sambuc utils::setenv("KYUA_TESTERSDIR", fs::current_path().str());
388*84d9c625SLionel Sambuc }
389*84d9c625SLionel Sambuc
390*84d9c625SLionel Sambuc
39111be35a1SLionel Sambuc } // anonymous namespace
39211be35a1SLionel Sambuc
39311be35a1SLionel Sambuc
39411be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(test_case__ctor_and_getters)
ATF_TEST_CASE_BODY(test_case__ctor_and_getters)39511be35a1SLionel Sambuc ATF_TEST_CASE_BODY(test_case__ctor_and_getters)
39611be35a1SLionel Sambuc {
39711be35a1SLionel Sambuc const engine::metadata md = engine::metadata_builder()
39811be35a1SLionel Sambuc .add_custom("first", "value")
39911be35a1SLionel Sambuc .build();
40011be35a1SLionel Sambuc const engine::test_program test_program(
40111be35a1SLionel Sambuc "mock", fs::path("abc"), fs::path("unused-root"),
40211be35a1SLionel Sambuc "unused-suite-name", engine::metadata_builder().build());
40311be35a1SLionel Sambuc const engine::test_case test_case("mock", test_program, "foo", md);
40411be35a1SLionel Sambuc ATF_REQUIRE_EQ(&test_program, &test_case.container_test_program());
40511be35a1SLionel Sambuc ATF_REQUIRE_EQ("foo", test_case.name());
40611be35a1SLionel Sambuc ATF_REQUIRE(md == test_case.get_metadata());
40711be35a1SLionel Sambuc }
40811be35a1SLionel Sambuc
40911be35a1SLionel Sambuc
41011be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(test_case__fake_result)
ATF_TEST_CASE_BODY(test_case__fake_result)41111be35a1SLionel Sambuc ATF_TEST_CASE_BODY(test_case__fake_result)
41211be35a1SLionel Sambuc {
41311be35a1SLionel Sambuc const engine::test_result result(engine::test_result::skipped,
41411be35a1SLionel Sambuc "Some reason");
41511be35a1SLionel Sambuc const engine::test_program test_program(
41611be35a1SLionel Sambuc "mock", fs::path("abc"), fs::path("unused-root"),
41711be35a1SLionel Sambuc "unused-suite-name", engine::metadata_builder().build());
41811be35a1SLionel Sambuc const engine::test_case test_case("mock", test_program, "__foo__",
41911be35a1SLionel Sambuc "Some description", result);
42011be35a1SLionel Sambuc ATF_REQUIRE_EQ(&test_program, &test_case.container_test_program());
42111be35a1SLionel Sambuc ATF_REQUIRE_EQ("__foo__", test_case.name());
42211be35a1SLionel Sambuc ATF_REQUIRE(result == test_case.fake_result().get());
42311be35a1SLionel Sambuc }
42411be35a1SLionel Sambuc
42511be35a1SLionel Sambuc
42611be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(test_case__operators_eq_and_ne__copy);
ATF_TEST_CASE_BODY(test_case__operators_eq_and_ne__copy)42711be35a1SLionel Sambuc ATF_TEST_CASE_BODY(test_case__operators_eq_and_ne__copy)
42811be35a1SLionel Sambuc {
42911be35a1SLionel Sambuc const engine::test_program tp(
43011be35a1SLionel Sambuc "plain", fs::path("non-existent"), fs::path("."), "suite-name",
43111be35a1SLionel Sambuc engine::metadata_builder().build());
43211be35a1SLionel Sambuc
43311be35a1SLionel Sambuc const engine::test_case tc1("plain", tp, "name",
43411be35a1SLionel Sambuc engine::metadata_builder().build());
43511be35a1SLionel Sambuc const engine::test_case tc2 = tc1;
43611be35a1SLionel Sambuc ATF_REQUIRE( tc1 == tc2);
43711be35a1SLionel Sambuc ATF_REQUIRE(!(tc1 != tc2));
43811be35a1SLionel Sambuc }
43911be35a1SLionel Sambuc
44011be35a1SLionel Sambuc
44111be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(test_case__output);
ATF_TEST_CASE_BODY(test_case__output)44211be35a1SLionel Sambuc ATF_TEST_CASE_BODY(test_case__output)
44311be35a1SLionel Sambuc {
44411be35a1SLionel Sambuc const engine::test_program tp(
44511be35a1SLionel Sambuc "plain", fs::path("non-existent"), fs::path("."), "suite-name",
44611be35a1SLionel Sambuc engine::metadata_builder().build());
44711be35a1SLionel Sambuc
44811be35a1SLionel Sambuc const engine::test_case tc1(
44911be35a1SLionel Sambuc "plain", tp, "the-name", engine::metadata_builder()
45011be35a1SLionel Sambuc .add_allowed_platform("foo").add_custom("X-bar", "baz").build());
45111be35a1SLionel Sambuc std::ostringstream str;
45211be35a1SLionel Sambuc str << tc1;
45311be35a1SLionel Sambuc ATF_REQUIRE_EQ(
45411be35a1SLionel Sambuc "test_case{interface='plain', name='the-name', "
45511be35a1SLionel Sambuc "metadata=metadata{allowed_architectures='', allowed_platforms='foo', "
45611be35a1SLionel Sambuc "custom.X-bar='baz', description='', has_cleanup='false', "
45711be35a1SLionel Sambuc "required_configs='', required_files='', required_memory='0', "
45811be35a1SLionel Sambuc "required_programs='', required_user='', timeout='300'}}",
45911be35a1SLionel Sambuc str.str());
46011be35a1SLionel Sambuc }
46111be35a1SLionel Sambuc
46211be35a1SLionel Sambuc
46311be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(test_case__operators_eq_and_ne__not_copy);
ATF_TEST_CASE_BODY(test_case__operators_eq_and_ne__not_copy)46411be35a1SLionel Sambuc ATF_TEST_CASE_BODY(test_case__operators_eq_and_ne__not_copy)
46511be35a1SLionel Sambuc {
46611be35a1SLionel Sambuc const std::string base_interface("plain");
46711be35a1SLionel Sambuc const engine::test_program base_tp(
46811be35a1SLionel Sambuc "plain", fs::path("non-existent"), fs::path("."), "suite-name",
46911be35a1SLionel Sambuc engine::metadata_builder().build());
47011be35a1SLionel Sambuc const std::string base_name("name");
47111be35a1SLionel Sambuc const engine::metadata base_metadata = engine::metadata_builder()
47211be35a1SLionel Sambuc .add_custom("X-foo", "bar")
47311be35a1SLionel Sambuc .build();
47411be35a1SLionel Sambuc
47511be35a1SLionel Sambuc const engine::test_case base_tc(base_interface, base_tp, base_name,
47611be35a1SLionel Sambuc base_metadata);
47711be35a1SLionel Sambuc
47811be35a1SLionel Sambuc // Construct with all same values.
47911be35a1SLionel Sambuc {
48011be35a1SLionel Sambuc const engine::test_case other_tc(base_interface, base_tp, base_name,
48111be35a1SLionel Sambuc base_metadata);
48211be35a1SLionel Sambuc
48311be35a1SLionel Sambuc ATF_REQUIRE( base_tc == other_tc);
48411be35a1SLionel Sambuc ATF_REQUIRE(!(base_tc != other_tc));
48511be35a1SLionel Sambuc }
48611be35a1SLionel Sambuc
48711be35a1SLionel Sambuc // Different interface.
48811be35a1SLionel Sambuc {
48911be35a1SLionel Sambuc const engine::test_case other_tc("atf", base_tp, base_name,
49011be35a1SLionel Sambuc base_metadata);
49111be35a1SLionel Sambuc
49211be35a1SLionel Sambuc ATF_REQUIRE(!(base_tc == other_tc));
49311be35a1SLionel Sambuc ATF_REQUIRE( base_tc != other_tc);
49411be35a1SLionel Sambuc }
49511be35a1SLionel Sambuc
49611be35a1SLionel Sambuc // Different test program, different identifier.
49711be35a1SLionel Sambuc {
49811be35a1SLionel Sambuc const engine::test_program other_tp(
49911be35a1SLionel Sambuc "plain", fs::path("another-name"), fs::path("."), "suite2-name",
50011be35a1SLionel Sambuc engine::metadata_builder().build());
50111be35a1SLionel Sambuc const engine::test_case other_tc(base_interface, other_tp, base_name,
50211be35a1SLionel Sambuc base_metadata);
50311be35a1SLionel Sambuc
50411be35a1SLionel Sambuc ATF_REQUIRE(!(base_tc == other_tc));
50511be35a1SLionel Sambuc ATF_REQUIRE( base_tc != other_tc);
50611be35a1SLionel Sambuc }
50711be35a1SLionel Sambuc
50811be35a1SLionel Sambuc // Different test program, same identifier. Cannot be detected!
50911be35a1SLionel Sambuc {
51011be35a1SLionel Sambuc const engine::test_program other_tp(
51111be35a1SLionel Sambuc "plain", fs::path("non-existent"), fs::path("."), "suite2-name",
51211be35a1SLionel Sambuc engine::metadata_builder().build());
51311be35a1SLionel Sambuc const engine::test_case other_tc(base_interface, other_tp, base_name,
51411be35a1SLionel Sambuc base_metadata);
51511be35a1SLionel Sambuc
51611be35a1SLionel Sambuc ATF_REQUIRE( base_tc == other_tc);
51711be35a1SLionel Sambuc ATF_REQUIRE(!(base_tc != other_tc));
51811be35a1SLionel Sambuc }
51911be35a1SLionel Sambuc
52011be35a1SLionel Sambuc // Different name.
52111be35a1SLionel Sambuc {
52211be35a1SLionel Sambuc const engine::test_case other_tc(base_interface, base_tp, "other",
52311be35a1SLionel Sambuc base_metadata);
52411be35a1SLionel Sambuc
52511be35a1SLionel Sambuc ATF_REQUIRE(!(base_tc == other_tc));
52611be35a1SLionel Sambuc ATF_REQUIRE( base_tc != other_tc);
52711be35a1SLionel Sambuc }
52811be35a1SLionel Sambuc
52911be35a1SLionel Sambuc // Different metadata.
53011be35a1SLionel Sambuc {
53111be35a1SLionel Sambuc const engine::test_case other_tc(base_interface, base_tp, base_name,
53211be35a1SLionel Sambuc engine::metadata_builder().build());
53311be35a1SLionel Sambuc
53411be35a1SLionel Sambuc ATF_REQUIRE(!(base_tc == other_tc));
53511be35a1SLionel Sambuc ATF_REQUIRE( base_tc != other_tc);
53611be35a1SLionel Sambuc }
53711be35a1SLionel Sambuc }
53811be35a1SLionel Sambuc
53911be35a1SLionel Sambuc
540*84d9c625SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__tester_crashes);
ATF_TEST_CASE_BODY(run_test_case__tester_crashes)541*84d9c625SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__tester_crashes)
542*84d9c625SLionel Sambuc {
543*84d9c625SLionel Sambuc atf_helper helper(this, "pass");
544*84d9c625SLionel Sambuc helper.move("program", ".");
545*84d9c625SLionel Sambuc create_mock_tester_signal("atf", SIGSEGV);
546*84d9c625SLionel Sambuc capture_hooks hooks;
547*84d9c625SLionel Sambuc const engine::test_result result = helper.run(hooks);
548*84d9c625SLionel Sambuc
549*84d9c625SLionel Sambuc ATF_REQUIRE(engine::test_result::broken == result.type());
550*84d9c625SLionel Sambuc ATF_REQUIRE_MATCH("Tester received signal.*bug", result.reason());
551*84d9c625SLionel Sambuc
552*84d9c625SLionel Sambuc ATF_REQUIRE_EQ("stdout stuff\n", hooks.stdout_contents);
553*84d9c625SLionel Sambuc ATF_REQUIRE_EQ("stderr stuff\n", hooks.stderr_contents);
554*84d9c625SLionel Sambuc }
555*84d9c625SLionel Sambuc
556*84d9c625SLionel Sambuc
55711be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__current_directory);
ATF_TEST_CASE_BODY(run_test_case__atf__current_directory)55811be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__current_directory)
55911be35a1SLionel Sambuc {
56011be35a1SLionel Sambuc atf_helper helper(this, "pass");
56111be35a1SLionel Sambuc helper.move("program", ".");
56211be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
56311be35a1SLionel Sambuc helper.run());
56411be35a1SLionel Sambuc }
56511be35a1SLionel Sambuc
56611be35a1SLionel Sambuc
56711be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__subdirectory);
ATF_TEST_CASE_BODY(run_test_case__atf__subdirectory)56811be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__subdirectory)
56911be35a1SLionel Sambuc {
57011be35a1SLionel Sambuc atf_helper helper(this, "pass");
57111be35a1SLionel Sambuc ATF_REQUIRE(::mkdir("dir1", 0755) != -1);
57211be35a1SLionel Sambuc ATF_REQUIRE(::mkdir("dir1/dir2", 0755) != -1);
57311be35a1SLionel Sambuc helper.move("dir2/program", "dir1");
57411be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
57511be35a1SLionel Sambuc helper.run());
57611be35a1SLionel Sambuc }
57711be35a1SLionel Sambuc
57811be35a1SLionel Sambuc
57911be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__config_variables);
ATF_TEST_CASE_BODY(run_test_case__atf__config_variables)58011be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__config_variables)
58111be35a1SLionel Sambuc {
58211be35a1SLionel Sambuc atf_helper helper(this, "create_cookie_in_control_dir");
58311be35a1SLionel Sambuc helper.set_config("control_dir", fs::current_path());
58411be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
58511be35a1SLionel Sambuc helper.run());
58611be35a1SLionel Sambuc
58711be35a1SLionel Sambuc if (!fs::exists(fs::path("cookie")))
58811be35a1SLionel Sambuc fail("The cookie was not created where we expected; the test program "
58911be35a1SLionel Sambuc "probably received an invalid configuration variable");
59011be35a1SLionel Sambuc }
59111be35a1SLionel Sambuc
59211be35a1SLionel Sambuc
59311be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__cleanup_shares_workdir);
ATF_TEST_CASE_BODY(run_test_case__atf__cleanup_shares_workdir)59411be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__cleanup_shares_workdir)
59511be35a1SLionel Sambuc {
59611be35a1SLionel Sambuc atf_helper helper(this, "check_cleanup_workdir");
59711be35a1SLionel Sambuc helper.set_metadata("has_cleanup", "true");
59811be35a1SLionel Sambuc helper.set_config("control_dir", fs::current_path());
59911be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped,
60011be35a1SLionel Sambuc "cookie created"), helper.run());
60111be35a1SLionel Sambuc
60211be35a1SLionel Sambuc if (fs::exists(fs::path("missing_cookie")))
60311be35a1SLionel Sambuc fail("The cleanup part did not see the cookie; the work directory "
60411be35a1SLionel Sambuc "is probably not shared");
60511be35a1SLionel Sambuc if (fs::exists(fs::path("invalid_cookie")))
60611be35a1SLionel Sambuc fail("The cleanup part read an invalid cookie");
60711be35a1SLionel Sambuc if (!fs::exists(fs::path("cookie_ok")))
60811be35a1SLionel Sambuc fail("The cleanup part was not executed");
60911be35a1SLionel Sambuc }
61011be35a1SLionel Sambuc
61111be35a1SLionel Sambuc
61211be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__has_cleanup__atf__false);
ATF_TEST_CASE_BODY(run_test_case__atf__has_cleanup__atf__false)61311be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__has_cleanup__atf__false)
61411be35a1SLionel Sambuc {
61511be35a1SLionel Sambuc atf_helper helper(this, "create_cookie_from_cleanup");
61611be35a1SLionel Sambuc helper.set_metadata("has_cleanup", "false");
61711be35a1SLionel Sambuc helper.set_config("control_dir", fs::current_path());
61811be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
61911be35a1SLionel Sambuc helper.run());
62011be35a1SLionel Sambuc
62111be35a1SLionel Sambuc if (fs::exists(fs::path("cookie")))
62211be35a1SLionel Sambuc fail("The cleanup part was executed even though the test case set "
62311be35a1SLionel Sambuc "has.cleanup to false");
62411be35a1SLionel Sambuc }
62511be35a1SLionel Sambuc
62611be35a1SLionel Sambuc
62711be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__has_cleanup__atf__true);
ATF_TEST_CASE_BODY(run_test_case__atf__has_cleanup__atf__true)62811be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__has_cleanup__atf__true)
62911be35a1SLionel Sambuc {
63011be35a1SLionel Sambuc atf_helper helper(this, "create_cookie_from_cleanup");
63111be35a1SLionel Sambuc helper.set_metadata("has_cleanup", "true");
63211be35a1SLionel Sambuc helper.set_config("control_dir", fs::current_path());
63311be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
63411be35a1SLionel Sambuc helper.run());
63511be35a1SLionel Sambuc
63611be35a1SLionel Sambuc if (!fs::exists(fs::path("cookie")))
63711be35a1SLionel Sambuc fail("The cleanup part was not executed even though the test case set "
63811be35a1SLionel Sambuc "has.cleanup to true");
63911be35a1SLionel Sambuc }
64011be35a1SLionel Sambuc
64111be35a1SLionel Sambuc
64211be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__kill_children);
ATF_TEST_CASE_BODY(run_test_case__atf__kill_children)64311be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__kill_children)
64411be35a1SLionel Sambuc {
64511be35a1SLionel Sambuc atf_helper helper(this, "spawn_blocking_child");
64611be35a1SLionel Sambuc helper.set_config("control_dir", fs::current_path());
64711be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
64811be35a1SLionel Sambuc helper.run());
64911be35a1SLionel Sambuc
65011be35a1SLionel Sambuc if (!fs::exists(fs::path("pid")))
65111be35a1SLionel Sambuc fail("The pid file was not created");
65211be35a1SLionel Sambuc std::ifstream pidfile("pid");
65311be35a1SLionel Sambuc ATF_REQUIRE(pidfile);
65411be35a1SLionel Sambuc pid_t pid;
65511be35a1SLionel Sambuc pidfile >> pid;
65611be35a1SLionel Sambuc pidfile.close();
65711be35a1SLionel Sambuc
65811be35a1SLionel Sambuc int attempts = 30;
65911be35a1SLionel Sambuc retry:
66011be35a1SLionel Sambuc if (::kill(pid, SIGCONT) != -1 || errno != ESRCH) {
66111be35a1SLionel Sambuc // Looks like the subchild did not die.
66211be35a1SLionel Sambuc //
66311be35a1SLionel Sambuc // Note that this might be inaccurate for two reasons:
66411be35a1SLionel Sambuc // 1) The system may have spawned a new process with the same pid as
66511be35a1SLionel Sambuc // our subchild... but in practice, this does not happen because
66611be35a1SLionel Sambuc // most systems do not immediately reuse pid numbers. If that
66711be35a1SLionel Sambuc // happens... well, we get a false test failure.
66811be35a1SLionel Sambuc // 2) We ran so fast that even if the process was sent a signal to
66911be35a1SLionel Sambuc // die, it has not had enough time to process it yet. This is why
67011be35a1SLionel Sambuc // we retry this a few times.
67111be35a1SLionel Sambuc if (attempts > 0) {
67211be35a1SLionel Sambuc std::cout << "Subprocess not dead yet; retrying wait\n";
67311be35a1SLionel Sambuc --attempts;
67411be35a1SLionel Sambuc ::usleep(100000);
67511be35a1SLionel Sambuc goto retry;
67611be35a1SLionel Sambuc }
67711be35a1SLionel Sambuc fail(F("The subprocess %s of our child was not killed") % pid);
67811be35a1SLionel Sambuc }
67911be35a1SLionel Sambuc }
68011be35a1SLionel Sambuc
68111be35a1SLionel Sambuc
68211be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__isolation);
ATF_TEST_CASE_BODY(run_test_case__atf__isolation)68311be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__isolation)
68411be35a1SLionel Sambuc {
68511be35a1SLionel Sambuc atf_helper helper(this, "validate_isolation");
68611be35a1SLionel Sambuc // Simple checks to make sure that the test case has been isolated.
68711be35a1SLionel Sambuc utils::setenv("HOME", "fake-value");
68811be35a1SLionel Sambuc utils::setenv("LANG", "C");
68911be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
69011be35a1SLionel Sambuc helper.run());
69111be35a1SLionel Sambuc }
69211be35a1SLionel Sambuc
69311be35a1SLionel Sambuc
69411be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__allowed_architectures);
ATF_TEST_CASE_BODY(run_test_case__atf__allowed_architectures)69511be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__allowed_architectures)
69611be35a1SLionel Sambuc {
69711be35a1SLionel Sambuc atf_helper helper(this, "create_cookie_in_control_dir");
69811be35a1SLionel Sambuc helper.set_metadata("allowed_architectures", "i386 x86_64");
69911be35a1SLionel Sambuc helper.config().set_string("architecture", "powerpc");
70011be35a1SLionel Sambuc helper.config().set_string("platform", "");
70111be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, "Current "
70211be35a1SLionel Sambuc "architecture 'powerpc' not supported"),
70311be35a1SLionel Sambuc helper.run());
70411be35a1SLionel Sambuc
70511be35a1SLionel Sambuc if (fs::exists(fs::path("cookie")))
70611be35a1SLionel Sambuc fail("The test case was not really skipped when the requirements "
70711be35a1SLionel Sambuc "check failed");
70811be35a1SLionel Sambuc }
70911be35a1SLionel Sambuc
71011be35a1SLionel Sambuc
71111be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__allowed_platforms);
ATF_TEST_CASE_BODY(run_test_case__atf__allowed_platforms)71211be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__allowed_platforms)
71311be35a1SLionel Sambuc {
71411be35a1SLionel Sambuc atf_helper helper(this, "create_cookie_in_control_dir");
71511be35a1SLionel Sambuc helper.set_metadata("allowed_platforms", "i386 amd64");
71611be35a1SLionel Sambuc helper.config().set_string("architecture", "");
71711be35a1SLionel Sambuc helper.config().set_string("platform", "macppc");
71811be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, "Current "
71911be35a1SLionel Sambuc "platform 'macppc' not supported"),
72011be35a1SLionel Sambuc helper.run());
72111be35a1SLionel Sambuc
72211be35a1SLionel Sambuc if (fs::exists(fs::path("cookie")))
72311be35a1SLionel Sambuc fail("The test case was not really skipped when the requirements "
72411be35a1SLionel Sambuc "check failed");
72511be35a1SLionel Sambuc }
72611be35a1SLionel Sambuc
72711be35a1SLionel Sambuc
72811be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__required_configs);
ATF_TEST_CASE_BODY(run_test_case__atf__required_configs)72911be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__required_configs)
73011be35a1SLionel Sambuc {
73111be35a1SLionel Sambuc atf_helper helper(this, "create_cookie_in_control_dir");
73211be35a1SLionel Sambuc helper.set_metadata("required_configs", "used-var");
73311be35a1SLionel Sambuc helper.set_config("control_dir", fs::current_path());
73411be35a1SLionel Sambuc helper.set_config("unused-var", "value");
73511be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, "Required "
73611be35a1SLionel Sambuc "configuration property 'used-var' not "
73711be35a1SLionel Sambuc "defined"),
73811be35a1SLionel Sambuc helper.run());
73911be35a1SLionel Sambuc
74011be35a1SLionel Sambuc if (fs::exists(fs::path("cookie")))
74111be35a1SLionel Sambuc fail("The test case was not really skipped when the requirements "
74211be35a1SLionel Sambuc "check failed");
74311be35a1SLionel Sambuc }
74411be35a1SLionel Sambuc
74511be35a1SLionel Sambuc
74611be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__required_programs);
ATF_TEST_CASE_BODY(run_test_case__atf__required_programs)74711be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__required_programs)
74811be35a1SLionel Sambuc {
74911be35a1SLionel Sambuc atf_helper helper(this, "create_cookie_in_control_dir");
75011be35a1SLionel Sambuc helper.set_metadata("required_programs", "/non-existent/program");
75111be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, "Required "
75211be35a1SLionel Sambuc "program '/non-existent/program' not "
75311be35a1SLionel Sambuc "found"),
75411be35a1SLionel Sambuc helper.run());
75511be35a1SLionel Sambuc
75611be35a1SLionel Sambuc if (fs::exists(fs::path("cookie")))
75711be35a1SLionel Sambuc fail("The test case was not really skipped when the requirements "
75811be35a1SLionel Sambuc "check failed");
75911be35a1SLionel Sambuc }
76011be35a1SLionel Sambuc
76111be35a1SLionel Sambuc
76211be35a1SLionel Sambuc ATF_TEST_CASE(run_test_case__atf__required_user__atf__root__atf__ok);
ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__root__atf__ok)76311be35a1SLionel Sambuc ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__root__atf__ok)
76411be35a1SLionel Sambuc {
76511be35a1SLionel Sambuc set_md_var("require.user", "root");
76611be35a1SLionel Sambuc }
ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__root__atf__ok)76711be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__root__atf__ok)
76811be35a1SLionel Sambuc {
76911be35a1SLionel Sambuc atf_helper helper(this, "create_cookie_in_workdir");
77011be35a1SLionel Sambuc helper.set_metadata("required_user", "root");
77111be35a1SLionel Sambuc ATF_REQUIRE(passwd::current_user().is_root());
77211be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
77311be35a1SLionel Sambuc helper.run());
77411be35a1SLionel Sambuc }
77511be35a1SLionel Sambuc
77611be35a1SLionel Sambuc
77711be35a1SLionel Sambuc ATF_TEST_CASE(run_test_case__atf__required_user__atf__root__atf__skip);
ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__root__atf__skip)77811be35a1SLionel Sambuc ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__root__atf__skip)
77911be35a1SLionel Sambuc {
78011be35a1SLionel Sambuc set_md_var("require.user", "unprivileged");
78111be35a1SLionel Sambuc }
ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__root__atf__skip)78211be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__root__atf__skip)
78311be35a1SLionel Sambuc {
78411be35a1SLionel Sambuc atf_helper helper(this, "create_cookie_in_workdir");
78511be35a1SLionel Sambuc helper.set_metadata("required_user", "root");
78611be35a1SLionel Sambuc ATF_REQUIRE(!passwd::current_user().is_root());
78711be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, "Requires "
78811be35a1SLionel Sambuc "root privileges"),
78911be35a1SLionel Sambuc helper.run());
79011be35a1SLionel Sambuc }
79111be35a1SLionel Sambuc
79211be35a1SLionel Sambuc
79311be35a1SLionel Sambuc ATF_TEST_CASE(run_test_case__atf__required_user__atf__unprivileged__atf__ok);
ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__unprivileged__atf__ok)79411be35a1SLionel Sambuc ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__unprivileged__atf__ok)
79511be35a1SLionel Sambuc {
79611be35a1SLionel Sambuc set_md_var("require.user", "unprivileged");
79711be35a1SLionel Sambuc }
ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__unprivileged__atf__ok)79811be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__unprivileged__atf__ok)
79911be35a1SLionel Sambuc {
80011be35a1SLionel Sambuc atf_helper helper(this, "create_cookie_in_workdir");
80111be35a1SLionel Sambuc helper.set_metadata("required_user", "unprivileged");
80211be35a1SLionel Sambuc ATF_REQUIRE(!helper.config().is_set("unprivileged_user"));
80311be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
80411be35a1SLionel Sambuc helper.run());
80511be35a1SLionel Sambuc }
80611be35a1SLionel Sambuc
80711be35a1SLionel Sambuc
80811be35a1SLionel Sambuc ATF_TEST_CASE(run_test_case__atf__required_user__atf__unprivileged__atf__skip);
ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__unprivileged__atf__skip)80911be35a1SLionel Sambuc ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__unprivileged__atf__skip)
81011be35a1SLionel Sambuc {
81111be35a1SLionel Sambuc set_md_var("require.user", "root");
81211be35a1SLionel Sambuc }
ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__unprivileged__atf__skip)81311be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__unprivileged__atf__skip)
81411be35a1SLionel Sambuc {
81511be35a1SLionel Sambuc atf_helper helper(this, "create_cookie_in_workdir");
81611be35a1SLionel Sambuc helper.set_metadata("required_user", "unprivileged");
81711be35a1SLionel Sambuc ATF_REQUIRE(!helper.config().is_set("unprivileged_user"));
81811be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, "Requires "
81911be35a1SLionel Sambuc "an unprivileged user but the "
82011be35a1SLionel Sambuc "unprivileged-user configuration "
82111be35a1SLionel Sambuc "variable is not defined"),
82211be35a1SLionel Sambuc helper.run());
82311be35a1SLionel Sambuc }
82411be35a1SLionel Sambuc
82511be35a1SLionel Sambuc
82611be35a1SLionel Sambuc ATF_TEST_CASE(run_test_case__atf__required_user__atf__unprivileged__atf__drop);
ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__unprivileged__atf__drop)82711be35a1SLionel Sambuc ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__unprivileged__atf__drop)
82811be35a1SLionel Sambuc {
82911be35a1SLionel Sambuc set_md_var("require.config", "unprivileged-user");
83011be35a1SLionel Sambuc set_md_var("require.user", "root");
83111be35a1SLionel Sambuc }
ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__unprivileged__atf__drop)83211be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__unprivileged__atf__drop)
83311be35a1SLionel Sambuc {
83411be35a1SLionel Sambuc atf_helper helper(this, "check_unprivileged");
83511be35a1SLionel Sambuc helper.set_metadata("required_user", "unprivileged");
83611be35a1SLionel Sambuc helper.config().set< engine::user_node >(
83711be35a1SLionel Sambuc "unprivileged_user",
83811be35a1SLionel Sambuc passwd::find_user_by_name(get_config_var("unprivileged-user")));
83911be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
84011be35a1SLionel Sambuc helper.run());
84111be35a1SLionel Sambuc }
84211be35a1SLionel Sambuc
84311be35a1SLionel Sambuc
84411be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__timeout_body);
ATF_TEST_CASE_BODY(run_test_case__atf__timeout_body)84511be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__timeout_body)
84611be35a1SLionel Sambuc {
84711be35a1SLionel Sambuc atf_helper helper(this, "timeout_body");
84811be35a1SLionel Sambuc helper.set_metadata("timeout", "1");
84911be35a1SLionel Sambuc helper.set_config("control_dir", fs::current_path());
85011be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::broken,
85111be35a1SLionel Sambuc "Test case body timed out"),
85211be35a1SLionel Sambuc helper.run());
85311be35a1SLionel Sambuc
85411be35a1SLionel Sambuc if (fs::exists(fs::path("cookie")))
85511be35a1SLionel Sambuc fail("It seems that the test case was not killed after it timed out");
85611be35a1SLionel Sambuc }
85711be35a1SLionel Sambuc
85811be35a1SLionel Sambuc
85911be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__timeout_cleanup);
ATF_TEST_CASE_BODY(run_test_case__atf__timeout_cleanup)86011be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__timeout_cleanup)
86111be35a1SLionel Sambuc {
86211be35a1SLionel Sambuc atf_helper helper(this, "timeout_cleanup");
86311be35a1SLionel Sambuc helper.set_metadata("has_cleanup", "true");
86411be35a1SLionel Sambuc helper.set_metadata("timeout", "1");
86511be35a1SLionel Sambuc helper.set_config("control_dir", fs::current_path());
86611be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::broken,
86711be35a1SLionel Sambuc "Test case cleanup timed out"),
86811be35a1SLionel Sambuc helper.run());
86911be35a1SLionel Sambuc
87011be35a1SLionel Sambuc if (fs::exists(fs::path("cookie")))
87111be35a1SLionel Sambuc fail("It seems that the test case was not killed after it timed out");
87211be35a1SLionel Sambuc }
87311be35a1SLionel Sambuc
87411be35a1SLionel Sambuc
87511be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__stacktrace__atf__body);
ATF_TEST_CASE_BODY(run_test_case__atf__stacktrace__atf__body)87611be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__stacktrace__atf__body)
87711be35a1SLionel Sambuc {
87811be35a1SLionel Sambuc atf_helper helper(this, "crash");
87911be35a1SLionel Sambuc capture_hooks hooks;
88011be35a1SLionel Sambuc const engine::test_result result = helper.run(hooks);
88111be35a1SLionel Sambuc ATF_REQUIRE(engine::test_result::broken == result.type());
88211be35a1SLionel Sambuc ATF_REQUIRE_MATCH("received signal.*core dumped", result.reason());
88311be35a1SLionel Sambuc
88411be35a1SLionel Sambuc ATF_REQUIRE(!atf::utils::grep_string("attempting to gather stack trace",
88511be35a1SLionel Sambuc hooks.stdout_contents));
88611be35a1SLionel Sambuc ATF_REQUIRE( atf::utils::grep_string("attempting to gather stack trace",
88711be35a1SLionel Sambuc hooks.stderr_contents));
88811be35a1SLionel Sambuc }
88911be35a1SLionel Sambuc
89011be35a1SLionel Sambuc
89111be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__stacktrace__atf__cleanup);
ATF_TEST_CASE_BODY(run_test_case__atf__stacktrace__atf__cleanup)89211be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__stacktrace__atf__cleanup)
89311be35a1SLionel Sambuc {
89411be35a1SLionel Sambuc atf_helper helper(this, "crash_cleanup");
89511be35a1SLionel Sambuc helper.set_metadata("has_cleanup", "true");
89611be35a1SLionel Sambuc capture_hooks hooks;
89711be35a1SLionel Sambuc const engine::test_result result = helper.run(hooks);
89811be35a1SLionel Sambuc ATF_REQUIRE(engine::test_result::broken == result.type());
89911be35a1SLionel Sambuc ATF_REQUIRE_MATCH(F("cleanup received signal %s") % SIGABRT,
90011be35a1SLionel Sambuc result.reason());
90111be35a1SLionel Sambuc
90211be35a1SLionel Sambuc ATF_REQUIRE(!atf::utils::grep_string("attempting to gather stack trace",
90311be35a1SLionel Sambuc hooks.stdout_contents));
90411be35a1SLionel Sambuc ATF_REQUIRE( atf::utils::grep_string("attempting to gather stack trace",
90511be35a1SLionel Sambuc hooks.stderr_contents));
90611be35a1SLionel Sambuc }
90711be35a1SLionel Sambuc
90811be35a1SLionel Sambuc
90911be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__missing_results_file);
ATF_TEST_CASE_BODY(run_test_case__atf__missing_results_file)91011be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__missing_results_file)
91111be35a1SLionel Sambuc {
91211be35a1SLionel Sambuc atf_helper helper(this, "crash");
91311be35a1SLionel Sambuc const engine::test_result result = helper.run();
91411be35a1SLionel Sambuc ATF_REQUIRE(engine::test_result::broken == result.type());
91511be35a1SLionel Sambuc // Need to match instead of doing an explicit comparison because the string
91611be35a1SLionel Sambuc // may include the "core dumped" substring.
91711be35a1SLionel Sambuc ATF_REQUIRE_MATCH(F("test case received signal %s") % SIGABRT,
91811be35a1SLionel Sambuc result.reason());
91911be35a1SLionel Sambuc }
92011be35a1SLionel Sambuc
92111be35a1SLionel Sambuc
92211be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__missing_test_program);
ATF_TEST_CASE_BODY(run_test_case__atf__missing_test_program)92311be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__missing_test_program)
92411be35a1SLionel Sambuc {
92511be35a1SLionel Sambuc atf_helper helper(this, "crash");
92611be35a1SLionel Sambuc ATF_REQUIRE(::mkdir("dir", 0755) != -1);
92711be35a1SLionel Sambuc helper.move("test_case_atf_helpers", "dir");
92811be35a1SLionel Sambuc ATF_REQUIRE(::unlink("dir/test_case_atf_helpers") != -1);
92911be35a1SLionel Sambuc const engine::test_result result = helper.run();
93011be35a1SLionel Sambuc ATF_REQUIRE(engine::test_result::broken == result.type());
93111be35a1SLionel Sambuc ATF_REQUIRE_MATCH("Test program does not exist", result.reason());
93211be35a1SLionel Sambuc }
93311be35a1SLionel Sambuc
93411be35a1SLionel Sambuc
93511be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__output);
ATF_TEST_CASE_BODY(run_test_case__atf__output)93611be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__atf__output)
93711be35a1SLionel Sambuc {
93811be35a1SLionel Sambuc atf_helper helper(this, "output");
93911be35a1SLionel Sambuc helper.set_metadata("has_cleanup", "true");
94011be35a1SLionel Sambuc
94111be35a1SLionel Sambuc capture_hooks hooks;
94211be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
94311be35a1SLionel Sambuc helper.run(hooks));
94411be35a1SLionel Sambuc
94511be35a1SLionel Sambuc ATF_REQUIRE_EQ("Body message to stdout\nCleanup message to stdout\n",
94611be35a1SLionel Sambuc hooks.stdout_contents);
94711be35a1SLionel Sambuc ATF_REQUIRE_EQ("Body message to stderr\nCleanup message to stderr\n",
94811be35a1SLionel Sambuc hooks.stderr_contents);
94911be35a1SLionel Sambuc }
95011be35a1SLionel Sambuc
95111be35a1SLionel Sambuc
95211be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__result_pass);
ATF_TEST_CASE_BODY(run_test_case__plain__result_pass)95311be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__plain__result_pass)
95411be35a1SLionel Sambuc {
95511be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
95611be35a1SLionel Sambuc plain_helper(this, "pass").run());
95711be35a1SLionel Sambuc }
95811be35a1SLionel Sambuc
95911be35a1SLionel Sambuc
96011be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__result_fail);
ATF_TEST_CASE_BODY(run_test_case__plain__result_fail)96111be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__plain__result_fail)
96211be35a1SLionel Sambuc {
96311be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::failed,
96411be35a1SLionel Sambuc "Returned non-success exit status 8"),
96511be35a1SLionel Sambuc plain_helper(this, "fail").run());
96611be35a1SLionel Sambuc }
96711be35a1SLionel Sambuc
96811be35a1SLionel Sambuc
96911be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__result_crash);
ATF_TEST_CASE_BODY(run_test_case__plain__result_crash)97011be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__plain__result_crash)
97111be35a1SLionel Sambuc {
97211be35a1SLionel Sambuc const engine::test_result result = plain_helper(this, "crash").run();
97311be35a1SLionel Sambuc ATF_REQUIRE(engine::test_result::broken == result.type());
97411be35a1SLionel Sambuc ATF_REQUIRE_MATCH(F("Received signal %s") % SIGABRT, result.reason());
97511be35a1SLionel Sambuc }
97611be35a1SLionel Sambuc
97711be35a1SLionel Sambuc
97811be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__current_directory);
ATF_TEST_CASE_BODY(run_test_case__plain__current_directory)97911be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__plain__current_directory)
98011be35a1SLionel Sambuc {
98111be35a1SLionel Sambuc plain_helper helper(this, "pass");
98211be35a1SLionel Sambuc helper.move("program", ".");
98311be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
98411be35a1SLionel Sambuc helper.run());
98511be35a1SLionel Sambuc }
98611be35a1SLionel Sambuc
98711be35a1SLionel Sambuc
98811be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__subdirectory);
ATF_TEST_CASE_BODY(run_test_case__plain__subdirectory)98911be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__plain__subdirectory)
99011be35a1SLionel Sambuc {
99111be35a1SLionel Sambuc plain_helper helper(this, "pass");
99211be35a1SLionel Sambuc ATF_REQUIRE(::mkdir("dir1", 0755) != -1);
99311be35a1SLionel Sambuc ATF_REQUIRE(::mkdir("dir1/dir2", 0755) != -1);
99411be35a1SLionel Sambuc helper.move("dir2/program", "dir1");
99511be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
99611be35a1SLionel Sambuc helper.run());
99711be35a1SLionel Sambuc }
99811be35a1SLionel Sambuc
99911be35a1SLionel Sambuc
100011be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__kill_children);
ATF_TEST_CASE_BODY(run_test_case__plain__kill_children)100111be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__plain__kill_children)
100211be35a1SLionel Sambuc {
100311be35a1SLionel Sambuc plain_helper helper(this, "spawn_blocking_child");
100411be35a1SLionel Sambuc helper.set("CONTROL_DIR", fs::current_path());
100511be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
100611be35a1SLionel Sambuc helper.run());
100711be35a1SLionel Sambuc
100811be35a1SLionel Sambuc if (!fs::exists(fs::path("pid")))
100911be35a1SLionel Sambuc fail("The pid file was not created");
101011be35a1SLionel Sambuc std::ifstream pidfile("pid");
101111be35a1SLionel Sambuc ATF_REQUIRE(pidfile);
101211be35a1SLionel Sambuc pid_t pid;
101311be35a1SLionel Sambuc pidfile >> pid;
101411be35a1SLionel Sambuc pidfile.close();
101511be35a1SLionel Sambuc
101611be35a1SLionel Sambuc int attempts = 30;
101711be35a1SLionel Sambuc retry:
101811be35a1SLionel Sambuc if (::kill(pid, SIGCONT) != -1 || errno != ESRCH) {
101911be35a1SLionel Sambuc // Looks like the subchild did not die.
102011be35a1SLionel Sambuc //
102111be35a1SLionel Sambuc // Note that this might be inaccurate for two reasons:
102211be35a1SLionel Sambuc // 1) The system may have spawned a new process with the same pid as
102311be35a1SLionel Sambuc // our subchild... but in practice, this does not happen because
102411be35a1SLionel Sambuc // most systems do not immediately reuse pid numbers. If that
102511be35a1SLionel Sambuc // happens... well, we get a false test failure.
102611be35a1SLionel Sambuc // 2) We ran so fast that even if the process was sent a signal to
102711be35a1SLionel Sambuc // die, it has not had enough time to process it yet. This is why
102811be35a1SLionel Sambuc // we retry this a few times.
102911be35a1SLionel Sambuc if (attempts > 0) {
103011be35a1SLionel Sambuc std::cout << "Subprocess not dead yet; retrying wait\n";
103111be35a1SLionel Sambuc --attempts;
103211be35a1SLionel Sambuc ::usleep(100000);
103311be35a1SLionel Sambuc goto retry;
103411be35a1SLionel Sambuc }
103511be35a1SLionel Sambuc fail(F("The subprocess %s of our child was not killed") % pid);
103611be35a1SLionel Sambuc }
103711be35a1SLionel Sambuc }
103811be35a1SLionel Sambuc
103911be35a1SLionel Sambuc
104011be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__isolation);
ATF_TEST_CASE_BODY(run_test_case__plain__isolation)104111be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__plain__isolation)
104211be35a1SLionel Sambuc {
104311be35a1SLionel Sambuc const plain_helper helper(this, "validate_isolation");
104411be35a1SLionel Sambuc utils::setenv("TEST_CASE", "validate_isolation");
104511be35a1SLionel Sambuc // Simple checks to make sure that the test case has been isolated.
104611be35a1SLionel Sambuc utils::setenv("HOME", "fake-value");
104711be35a1SLionel Sambuc utils::setenv("LANG", "C");
104811be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed),
104911be35a1SLionel Sambuc helper.run());
105011be35a1SLionel Sambuc }
105111be35a1SLionel Sambuc
105211be35a1SLionel Sambuc
105311be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__timeout);
ATF_TEST_CASE_BODY(run_test_case__plain__timeout)105411be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__plain__timeout)
105511be35a1SLionel Sambuc {
105611be35a1SLionel Sambuc plain_helper helper(this, "timeout",
105711be35a1SLionel Sambuc utils::make_optional(datetime::delta(1, 0)));
105811be35a1SLionel Sambuc helper.set("CONTROL_DIR", fs::current_path());
105911be35a1SLionel Sambuc ATF_REQUIRE_EQ(engine::test_result(engine::test_result::broken,
106011be35a1SLionel Sambuc "Test case timed out"),
106111be35a1SLionel Sambuc helper.run());
106211be35a1SLionel Sambuc
106311be35a1SLionel Sambuc if (fs::exists(fs::path("cookie")))
106411be35a1SLionel Sambuc fail("It seems that the test case was not killed after it timed out");
106511be35a1SLionel Sambuc }
106611be35a1SLionel Sambuc
106711be35a1SLionel Sambuc
106811be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__stacktrace);
ATF_TEST_CASE_BODY(run_test_case__plain__stacktrace)106911be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__plain__stacktrace)
107011be35a1SLionel Sambuc {
107111be35a1SLionel Sambuc plain_helper helper(this, "crash");
107211be35a1SLionel Sambuc helper.set("CONTROL_DIR", fs::current_path());
107311be35a1SLionel Sambuc
107411be35a1SLionel Sambuc const engine::test_result result = plain_helper(this, "crash").run();
107511be35a1SLionel Sambuc ATF_REQUIRE(engine::test_result::broken == result.type());
107611be35a1SLionel Sambuc ATF_REQUIRE_MATCH(F("Received signal %s") % SIGABRT, result.reason());
107711be35a1SLionel Sambuc
107811be35a1SLionel Sambuc ATF_REQUIRE(!atf::utils::grep_file("attempting to gather stack trace",
107911be35a1SLionel Sambuc "helper-stdout.txt"));
108011be35a1SLionel Sambuc ATF_REQUIRE( atf::utils::grep_file("attempting to gather stack trace",
108111be35a1SLionel Sambuc "helper-stderr.txt"));
108211be35a1SLionel Sambuc }
108311be35a1SLionel Sambuc
108411be35a1SLionel Sambuc
108511be35a1SLionel Sambuc ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__missing_test_program);
ATF_TEST_CASE_BODY(run_test_case__plain__missing_test_program)108611be35a1SLionel Sambuc ATF_TEST_CASE_BODY(run_test_case__plain__missing_test_program)
108711be35a1SLionel Sambuc {
108811be35a1SLionel Sambuc plain_helper helper(this, "pass");
108911be35a1SLionel Sambuc ATF_REQUIRE(::mkdir("dir", 0755) != -1);
109011be35a1SLionel Sambuc helper.move("test_case_helpers", "dir");
109111be35a1SLionel Sambuc ATF_REQUIRE(::unlink("dir/test_case_helpers") != -1);
109211be35a1SLionel Sambuc const engine::test_result result = helper.run();
109311be35a1SLionel Sambuc ATF_REQUIRE(engine::test_result::broken == result.type());
109411be35a1SLionel Sambuc ATF_REQUIRE_MATCH("Test program does not exist", result.reason());
109511be35a1SLionel Sambuc }
109611be35a1SLionel Sambuc
109711be35a1SLionel Sambuc
ATF_INIT_TEST_CASES(tcs)109811be35a1SLionel Sambuc ATF_INIT_TEST_CASES(tcs)
109911be35a1SLionel Sambuc {
110011be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, test_case__ctor_and_getters);
110111be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, test_case__fake_result);
110211be35a1SLionel Sambuc
110311be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, test_case__operators_eq_and_ne__copy);
110411be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, test_case__operators_eq_and_ne__not_copy);
110511be35a1SLionel Sambuc
110611be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, test_case__output);
110711be35a1SLionel Sambuc
1108*84d9c625SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__tester_crashes);
1109*84d9c625SLionel Sambuc
111011be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__current_directory);
111111be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__subdirectory);
111211be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__config_variables);
111311be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__cleanup_shares_workdir);
111411be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__has_cleanup__atf__false);
111511be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__has_cleanup__atf__true);
111611be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__kill_children);
111711be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__isolation);
111811be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__allowed_architectures);
111911be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__allowed_platforms);
112011be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_configs);
112111be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_programs);
112211be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_user__atf__root__atf__ok);
112311be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_user__atf__root__atf__skip);
112411be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_user__atf__unprivileged__atf__ok);
112511be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_user__atf__unprivileged__atf__skip);
112611be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_user__atf__unprivileged__atf__drop);
112711be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__timeout_body);
112811be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__timeout_cleanup);
112911be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__stacktrace__atf__body);
113011be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__stacktrace__atf__cleanup);
113111be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__missing_results_file);
113211be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__missing_test_program);
113311be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__atf__output);
113411be35a1SLionel Sambuc
113511be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__plain__result_pass);
113611be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__plain__result_fail);
113711be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__plain__result_crash);
113811be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__plain__current_directory);
113911be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__plain__subdirectory);
114011be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__plain__kill_children);
114111be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__plain__isolation);
114211be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__plain__timeout);
114311be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__plain__stacktrace);
114411be35a1SLionel Sambuc ATF_ADD_TEST_CASE(tcs, run_test_case__plain__missing_test_program);
114511be35a1SLionel Sambuc
114611be35a1SLionel Sambuc // TODO(jmmv): Add test cases for debug.
114711be35a1SLionel Sambuc }
1148