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 46 namespace config = utils::config; 47 namespace fs = utils::fs; 48 namespace passwd = utils::passwd; 49 50 using utils::none; 51 using utils::optional; 52 53 54 namespace { 55 56 57 /// Replaces the system user database with a fake one for testing purposes. 58 static void 59 set_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. 74 static void 75 validate_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 94 ATF_TEST_CASE_WITHOUT_HEAD(config__defaults); 95 ATF_TEST_CASE_BODY(config__defaults) 96 { 97 const config::tree user_config = engine::default_config(); 98 validate_defaults(user_config); 99 } 100 101 102 ATF_TEST_CASE_WITHOUT_HEAD(config__load__defaults); 103 ATF_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 112 ATF_TEST_CASE_WITHOUT_HEAD(config__load__overrides); 113 ATF_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 144 ATF_TEST_CASE_WITHOUT_HEAD(config__load__lua_error); 145 ATF_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 154 ATF_TEST_CASE_WITHOUT_HEAD(config__load__bad_syntax__version); 155 ATF_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 165 ATF_TEST_CASE_WITHOUT_HEAD(config__load__missing_file); 166 ATF_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 173 ATF_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