1// Copyright 2010 Google Inc. 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 KYUA_PLATFORM, 83 config.lookup< config::string_node >("platform")); 84 85 ATF_REQUIRE(!config.is_set("unprivileged_user")); 86 87 ATF_REQUIRE(config.all_properties("test_suites").empty()); 88} 89 90 91} // anonymous namespace 92 93 94ATF_TEST_CASE_WITHOUT_HEAD(config__defaults); 95ATF_TEST_CASE_BODY(config__defaults) 96{ 97 const config::tree user_config = engine::default_config(); 98 validate_defaults(user_config); 99} 100 101 102ATF_TEST_CASE_WITHOUT_HEAD(config__load__defaults); 103ATF_TEST_CASE_BODY(config__load__defaults) 104{ 105 atf::utils::create_file("config", "syntax(2)\n"); 106 107 const config::tree user_config = engine::load_config(fs::path("config")); 108 validate_defaults(user_config); 109} 110 111 112ATF_TEST_CASE_WITHOUT_HEAD(config__load__overrides); 113ATF_TEST_CASE_BODY(config__load__overrides) 114{ 115 set_mock_users(); 116 117 atf::utils::create_file( 118 "config", 119 "syntax(2)\n" 120 "architecture = 'test-architecture'\n" 121 "platform = 'test-platform'\n" 122 "unprivileged_user = 'user2'\n" 123 "test_suites.mysuite.myvar = 'myvalue'\n"); 124 125 const config::tree user_config = engine::load_config(fs::path("config")); 126 127 ATF_REQUIRE_EQ("test-architecture", 128 user_config.lookup_string("architecture")); 129 ATF_REQUIRE_EQ("test-platform", 130 user_config.lookup_string("platform")); 131 132 const passwd::user& user = user_config.lookup< engine::user_node >( 133 "unprivileged_user"); 134 ATF_REQUIRE_EQ("user2", user.name); 135 ATF_REQUIRE_EQ(200, user.uid); 136 137 config::properties_map exp_test_suites; 138 exp_test_suites["test_suites.mysuite.myvar"] = "myvalue"; 139 140 ATF_REQUIRE(exp_test_suites == user_config.all_properties("test_suites")); 141} 142 143 144ATF_TEST_CASE_WITHOUT_HEAD(config__load__lua_error); 145ATF_TEST_CASE_BODY(config__load__lua_error) 146{ 147 atf::utils::create_file("config", "this syntax is invalid\n"); 148 149 ATF_REQUIRE_THROW(engine::load_error, engine::load_config( 150 fs::path("config"))); 151} 152 153 154ATF_TEST_CASE_WITHOUT_HEAD(config__load__bad_syntax__version); 155ATF_TEST_CASE_BODY(config__load__bad_syntax__version) 156{ 157 atf::utils::create_file("config", "syntax(123)\n"); 158 159 ATF_REQUIRE_THROW_RE(engine::load_error, 160 "Unsupported config version 123", 161 engine::load_config(fs::path("config"))); 162} 163 164 165ATF_TEST_CASE_WITHOUT_HEAD(config__load__missing_file); 166ATF_TEST_CASE_BODY(config__load__missing_file) 167{ 168 ATF_REQUIRE_THROW_RE(engine::load_error, "Load of 'missing' failed", 169 engine::load_config(fs::path("missing"))); 170} 171 172 173ATF_INIT_TEST_CASES(tcs) 174{ 175 ATF_ADD_TEST_CASE(tcs, config__defaults); 176 ATF_ADD_TEST_CASE(tcs, config__load__defaults); 177 ATF_ADD_TEST_CASE(tcs, config__load__overrides); 178 ATF_ADD_TEST_CASE(tcs, config__load__lua_error); 179 ATF_ADD_TEST_CASE(tcs, config__load__bad_syntax__version); 180 ATF_ADD_TEST_CASE(tcs, config__load__missing_file); 181} 182