1// Copyright 2010 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#include "engine/config.hpp" 30 31#if defined(HAVE_CONFIG_H) 32# include "config.h" 33#endif 34 35#include <stdexcept> 36#include <vector> 37 38#include <atf-c++.hpp> 39 40#include "engine/exceptions.hpp" 41#include "utils/cmdline/exceptions.hpp" 42#include "utils/cmdline/parser.hpp" 43#include "utils/config/tree.ipp" 44#include "utils/passwd.hpp" 45 46namespace config = utils::config; 47namespace fs = utils::fs; 48namespace passwd = utils::passwd; 49 50using utils::none; 51using utils::optional; 52 53 54namespace { 55 56 57/// Replaces the system user database with a fake one for testing purposes. 58static void 59set_mock_users(void) 60{ 61 std::vector< passwd::user > users; 62 users.push_back(passwd::user("user1", 100, 150)); 63 users.push_back(passwd::user("user2", 200, 250)); 64 passwd::set_mock_users_for_testing(users); 65} 66 67 68/// Checks that the default values of a config object match our expectations. 69/// 70/// This fails the test case if any field of the input config object is not 71/// what we expect. 72/// 73/// \param config The configuration to validate. 74static void 75validate_defaults(const config::tree& config) 76{ 77 ATF_REQUIRE_EQ( 78 KYUA_ARCHITECTURE, 79 config.lookup< config::string_node >("architecture")); 80 81 ATF_REQUIRE_EQ( 82 1, 83 config.lookup< config::positive_int_node >("parallelism")); 84 85 ATF_REQUIRE_EQ( 86 KYUA_PLATFORM, 87 config.lookup< config::string_node >("platform")); 88 89 ATF_REQUIRE(!config.is_set("unprivileged_user")); 90 91 ATF_REQUIRE(config.all_properties("test_suites").empty()); 92} 93 94 95} // anonymous namespace 96 97 98ATF_TEST_CASE_WITHOUT_HEAD(config__defaults); 99ATF_TEST_CASE_BODY(config__defaults) 100{ 101 const config::tree user_config = engine::default_config(); 102 validate_defaults(user_config); 103} 104 105 106ATF_TEST_CASE_WITHOUT_HEAD(config__set__parallelism); 107ATF_TEST_CASE_BODY(config__set__parallelism) 108{ 109 config::tree user_config = engine::default_config(); 110 user_config.set_string("parallelism", "8"); 111 ATF_REQUIRE_THROW_RE( 112 config::error, "parallelism.*Must be a positive integer", 113 user_config.set_string("parallelism", "0")); 114 ATF_REQUIRE_THROW_RE( 115 config::error, "parallelism.*Must be a positive integer", 116 user_config.set_string("parallelism", "-1")); 117} 118 119 120ATF_TEST_CASE_WITHOUT_HEAD(config__load__defaults); 121ATF_TEST_CASE_BODY(config__load__defaults) 122{ 123 atf::utils::create_file("config", "syntax(2)\n"); 124 125 const config::tree user_config = engine::load_config(fs::path("config")); 126 validate_defaults(user_config); 127} 128 129 130ATF_TEST_CASE_WITHOUT_HEAD(config__load__overrides); 131ATF_TEST_CASE_BODY(config__load__overrides) 132{ 133 set_mock_users(); 134 135 atf::utils::create_file( 136 "config", 137 "syntax(2)\n" 138 "architecture = 'test-architecture'\n" 139 "parallelism = 16\n" 140 "platform = 'test-platform'\n" 141 "unprivileged_user = 'user2'\n" 142 "test_suites.mysuite.myvar = 'myvalue'\n"); 143 144 const config::tree user_config = engine::load_config(fs::path("config")); 145 146 ATF_REQUIRE_EQ("test-architecture", 147 user_config.lookup_string("architecture")); 148 ATF_REQUIRE_EQ("16", 149 user_config.lookup_string("parallelism")); 150 ATF_REQUIRE_EQ("test-platform", 151 user_config.lookup_string("platform")); 152 153 const passwd::user& user = user_config.lookup< engine::user_node >( 154 "unprivileged_user"); 155 ATF_REQUIRE_EQ("user2", user.name); 156 ATF_REQUIRE_EQ(200, user.uid); 157 158 config::properties_map exp_test_suites; 159 exp_test_suites["test_suites.mysuite.myvar"] = "myvalue"; 160 161 ATF_REQUIRE(exp_test_suites == user_config.all_properties("test_suites")); 162} 163 164 165ATF_TEST_CASE_WITHOUT_HEAD(config__load__lua_error); 166ATF_TEST_CASE_BODY(config__load__lua_error) 167{ 168 atf::utils::create_file("config", "this syntax is invalid\n"); 169 170 ATF_REQUIRE_THROW(engine::load_error, engine::load_config( 171 fs::path("config"))); 172} 173 174 175ATF_TEST_CASE_WITHOUT_HEAD(config__load__bad_syntax__version); 176ATF_TEST_CASE_BODY(config__load__bad_syntax__version) 177{ 178 atf::utils::create_file("config", "syntax(123)\n"); 179 180 ATF_REQUIRE_THROW_RE(engine::load_error, 181 "Unsupported config version 123", 182 engine::load_config(fs::path("config"))); 183} 184 185 186ATF_TEST_CASE_WITHOUT_HEAD(config__load__missing_file); 187ATF_TEST_CASE_BODY(config__load__missing_file) 188{ 189 ATF_REQUIRE_THROW_RE(engine::load_error, "Load of 'missing' failed", 190 engine::load_config(fs::path("missing"))); 191} 192 193 194ATF_INIT_TEST_CASES(tcs) 195{ 196 ATF_ADD_TEST_CASE(tcs, config__defaults); 197 ATF_ADD_TEST_CASE(tcs, config__set__parallelism); 198 ATF_ADD_TEST_CASE(tcs, config__load__defaults); 199 ATF_ADD_TEST_CASE(tcs, config__load__overrides); 200 ATF_ADD_TEST_CASE(tcs, config__load__lua_error); 201 ATF_ADD_TEST_CASE(tcs, config__load__bad_syntax__version); 202 ATF_ADD_TEST_CASE(tcs, config__load__missing_file); 203} 204