1 // Copyright 2011 The Kyua Authors. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // * Neither the name of Google Inc. nor the names of its contributors 14 // may be used to endorse or promote products derived from this software 15 // without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 extern "C" { 30 #include <unistd.h> 31 } 32 33 #include <atf-c++.hpp> 34 35 #include "engine/config.hpp" 36 #include "engine/kyuafile.hpp" 37 #include "engine/plain.hpp" 38 #include "engine/scheduler.hpp" 39 #include "model/metadata.hpp" 40 #include "model/test_program.hpp" 41 #include "utils/config/tree.ipp" 42 #include "utils/env.hpp" 43 #include "utils/fs/operations.hpp" 44 #include "utils/fs/path.hpp" 45 #include "utils/logging/operations.hpp" 46 #include "utils/optional.ipp" 47 #include "utils/passwd.hpp" 48 49 namespace config = utils::config; 50 namespace fs = utils::fs; 51 namespace passwd = utils::passwd; 52 namespace scheduler = engine::scheduler; 53 54 using utils::none; 55 56 57 namespace { 58 59 60 /// Gets the path to an example file. 61 /// 62 /// \param name The name of the example file. 63 /// 64 /// \return A path to the desired example file. This can either be inside the 65 /// source tree before installing Kyua or in the target installation directory 66 /// after installation. 67 static fs::path 68 example_file(const char* name) 69 { 70 const fs::path examplesdir(utils::getenv_with_default( 71 "KYUA_EXAMPLESDIR", KYUA_EXAMPLESDIR)); 72 return examplesdir / name; 73 } 74 75 76 } // anonymous namespace 77 78 79 ATF_TEST_CASE(kyua_conf); 80 ATF_TEST_CASE_HEAD(kyua_conf) 81 { 82 utils::logging::set_inmemory(); 83 set_md_var("require.files", example_file("kyua.conf").str()); 84 } 85 ATF_TEST_CASE_BODY(kyua_conf) 86 { 87 std::vector< passwd::user > users; 88 users.push_back(passwd::user("nobody", 1, 2)); 89 passwd::set_mock_users_for_testing(users); 90 91 const config::tree user_config = engine::load_config( 92 example_file("kyua.conf")); 93 94 ATF_REQUIRE_EQ( 95 "x86_64", 96 user_config.lookup< config::string_node >("architecture")); 97 ATF_REQUIRE_EQ( 98 16, 99 user_config.lookup< config::positive_int_node >("parallelism")); 100 ATF_REQUIRE_EQ( 101 "amd64", 102 user_config.lookup< config::string_node >("platform")); 103 104 ATF_REQUIRE_EQ( 105 "nobody", 106 user_config.lookup< engine::user_node >("unprivileged_user").name); 107 108 config::properties_map exp_test_suites; 109 exp_test_suites["test_suites.kyua.run_coredump_tests"] = "false"; 110 exp_test_suites["test_suites.FreeBSD.iterations"] = "1000"; 111 exp_test_suites["test_suites.FreeBSD.run_old_tests"] = "false"; 112 exp_test_suites["test_suites.NetBSD.file_systems"] = "ffs lfs ext2fs"; 113 exp_test_suites["test_suites.NetBSD.iterations"] = "100"; 114 exp_test_suites["test_suites.NetBSD.run_broken_tests"] = "true"; 115 ATF_REQUIRE(exp_test_suites == user_config.all_properties("test_suites")); 116 } 117 118 119 ATF_TEST_CASE(kyuafile_top__no_matches); 120 ATF_TEST_CASE_HEAD(kyuafile_top__no_matches) 121 { 122 utils::logging::set_inmemory(); 123 set_md_var("require.files", example_file("Kyuafile.top").str()); 124 } 125 ATF_TEST_CASE_BODY(kyuafile_top__no_matches) 126 { 127 scheduler::scheduler_handle handle = scheduler::setup(); 128 129 fs::mkdir(fs::path("root"), 0755); 130 const fs::path source_path = example_file("Kyuafile.top"); 131 ATF_REQUIRE(::symlink(source_path.c_str(), "root/Kyuafile") != -1); 132 133 atf::utils::create_file("root/file", ""); 134 fs::mkdir(fs::path("root/subdir"), 0755); 135 136 const engine::kyuafile kyuafile = engine::kyuafile::load( 137 fs::path("root/Kyuafile"), none, engine::default_config(), handle); 138 ATF_REQUIRE_EQ(fs::path("root"), kyuafile.source_root()); 139 ATF_REQUIRE_EQ(fs::path("root"), kyuafile.build_root()); 140 ATF_REQUIRE(kyuafile.test_programs().empty()); 141 142 handle.cleanup(); 143 } 144 145 146 ATF_TEST_CASE(kyuafile_top__some_matches); 147 ATF_TEST_CASE_HEAD(kyuafile_top__some_matches) 148 { 149 utils::logging::set_inmemory(); 150 set_md_var("require.files", example_file("Kyuafile.top").str()); 151 } 152 ATF_TEST_CASE_BODY(kyuafile_top__some_matches) 153 { 154 scheduler::scheduler_handle handle = scheduler::setup(); 155 156 fs::mkdir(fs::path("root"), 0755); 157 const fs::path source_path = example_file("Kyuafile.top"); 158 ATF_REQUIRE(::symlink(source_path.c_str(), "root/Kyuafile") != -1); 159 160 atf::utils::create_file("root/file", ""); 161 162 fs::mkdir(fs::path("root/subdir1"), 0755); 163 atf::utils::create_file("root/subdir1/Kyuafile", 164 "syntax(2)\n" 165 "plain_test_program{name='a', test_suite='b'}\n"); 166 atf::utils::create_file("root/subdir1/a", ""); 167 168 fs::mkdir(fs::path("root/subdir2"), 0755); 169 atf::utils::create_file("root/subdir2/Kyuafile", 170 "syntax(2)\n" 171 "plain_test_program{name='c', test_suite='d'}\n"); 172 atf::utils::create_file("root/subdir2/c", ""); 173 atf::utils::create_file("root/subdir2/Kyuafile.etc", "invalid"); 174 175 const engine::kyuafile kyuafile = engine::kyuafile::load( 176 fs::path("root/Kyuafile"), none, engine::default_config(), handle); 177 ATF_REQUIRE_EQ(fs::path("root"), kyuafile.source_root()); 178 ATF_REQUIRE_EQ(fs::path("root"), kyuafile.build_root()); 179 180 const model::test_program exp_test_program_a = model::test_program_builder( 181 "plain", fs::path("subdir1/a"), fs::path("root").to_absolute(), "b") 182 .add_test_case("main") 183 .build(); 184 const model::test_program exp_test_program_c = model::test_program_builder( 185 "plain", fs::path("subdir2/c"), fs::path("root").to_absolute(), "d") 186 .add_test_case("main") 187 .build(); 188 189 ATF_REQUIRE_EQ(2, kyuafile.test_programs().size()); 190 ATF_REQUIRE((exp_test_program_a == *kyuafile.test_programs()[0] && 191 exp_test_program_c == *kyuafile.test_programs()[1]) 192 || 193 (exp_test_program_a == *kyuafile.test_programs()[1] && 194 exp_test_program_c == *kyuafile.test_programs()[0])); 195 196 handle.cleanup(); 197 } 198 199 200 ATF_INIT_TEST_CASES(tcs) 201 { 202 scheduler::register_interface( 203 "plain", std::shared_ptr< scheduler::interface >( 204 new engine::plain_interface())); 205 206 ATF_ADD_TEST_CASE(tcs, kyua_conf); 207 208 ATF_ADD_TEST_CASE(tcs, kyuafile_top__no_matches); 209 ATF_ADD_TEST_CASE(tcs, kyuafile_top__some_matches); 210 } 211