1*b0d29bc4SBrooks Davis // Copyright 2010 The Kyua Authors.
2*b0d29bc4SBrooks Davis // All rights reserved.
3*b0d29bc4SBrooks Davis //
4*b0d29bc4SBrooks Davis // Redistribution and use in source and binary forms, with or without
5*b0d29bc4SBrooks Davis // modification, are permitted provided that the following conditions are
6*b0d29bc4SBrooks Davis // met:
7*b0d29bc4SBrooks Davis //
8*b0d29bc4SBrooks Davis // * Redistributions of source code must retain the above copyright
9*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer.
10*b0d29bc4SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
11*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer in the
12*b0d29bc4SBrooks Davis // documentation and/or other materials provided with the distribution.
13*b0d29bc4SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
14*b0d29bc4SBrooks Davis // may be used to endorse or promote products derived from this software
15*b0d29bc4SBrooks Davis // without specific prior written permission.
16*b0d29bc4SBrooks Davis //
17*b0d29bc4SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*b0d29bc4SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*b0d29bc4SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*b0d29bc4SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*b0d29bc4SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*b0d29bc4SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*b0d29bc4SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*b0d29bc4SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*b0d29bc4SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*b0d29bc4SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*b0d29bc4SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*b0d29bc4SBrooks Davis
29*b0d29bc4SBrooks Davis #include "engine/config.hpp"
30*b0d29bc4SBrooks Davis
31*b0d29bc4SBrooks Davis #if defined(HAVE_CONFIG_H)
32*b0d29bc4SBrooks Davis # include "config.h"
33*b0d29bc4SBrooks Davis #endif
34*b0d29bc4SBrooks Davis
35*b0d29bc4SBrooks Davis #include <stdexcept>
36*b0d29bc4SBrooks Davis #include <vector>
37*b0d29bc4SBrooks Davis
38*b0d29bc4SBrooks Davis #include <atf-c++.hpp>
39*b0d29bc4SBrooks Davis
40*b0d29bc4SBrooks Davis #include "engine/exceptions.hpp"
41*b0d29bc4SBrooks Davis #include "utils/cmdline/exceptions.hpp"
42*b0d29bc4SBrooks Davis #include "utils/cmdline/parser.hpp"
43*b0d29bc4SBrooks Davis #include "utils/config/tree.ipp"
44*b0d29bc4SBrooks Davis #include "utils/passwd.hpp"
45*b0d29bc4SBrooks Davis
46*b0d29bc4SBrooks Davis namespace config = utils::config;
47*b0d29bc4SBrooks Davis namespace fs = utils::fs;
48*b0d29bc4SBrooks Davis namespace passwd = utils::passwd;
49*b0d29bc4SBrooks Davis
50*b0d29bc4SBrooks Davis using utils::none;
51*b0d29bc4SBrooks Davis using utils::optional;
52*b0d29bc4SBrooks Davis
53*b0d29bc4SBrooks Davis
54*b0d29bc4SBrooks Davis namespace {
55*b0d29bc4SBrooks Davis
56*b0d29bc4SBrooks Davis
57*b0d29bc4SBrooks Davis /// Replaces the system user database with a fake one for testing purposes.
58*b0d29bc4SBrooks Davis static void
set_mock_users(void)59*b0d29bc4SBrooks Davis set_mock_users(void)
60*b0d29bc4SBrooks Davis {
61*b0d29bc4SBrooks Davis std::vector< passwd::user > users;
62*b0d29bc4SBrooks Davis users.push_back(passwd::user("user1", 100, 150));
63*b0d29bc4SBrooks Davis users.push_back(passwd::user("user2", 200, 250));
64*b0d29bc4SBrooks Davis passwd::set_mock_users_for_testing(users);
65*b0d29bc4SBrooks Davis }
66*b0d29bc4SBrooks Davis
67*b0d29bc4SBrooks Davis
68*b0d29bc4SBrooks Davis /// Checks that the default values of a config object match our expectations.
69*b0d29bc4SBrooks Davis ///
70*b0d29bc4SBrooks Davis /// This fails the test case if any field of the input config object is not
71*b0d29bc4SBrooks Davis /// what we expect.
72*b0d29bc4SBrooks Davis ///
73*b0d29bc4SBrooks Davis /// \param config The configuration to validate.
74*b0d29bc4SBrooks Davis static void
validate_defaults(const config::tree & config)75*b0d29bc4SBrooks Davis validate_defaults(const config::tree& config)
76*b0d29bc4SBrooks Davis {
77*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(
78*b0d29bc4SBrooks Davis KYUA_ARCHITECTURE,
79*b0d29bc4SBrooks Davis config.lookup< config::string_node >("architecture"));
80*b0d29bc4SBrooks Davis
81*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(
82*b0d29bc4SBrooks Davis 1,
83*b0d29bc4SBrooks Davis config.lookup< config::positive_int_node >("parallelism"));
84*b0d29bc4SBrooks Davis
85*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(
86*b0d29bc4SBrooks Davis KYUA_PLATFORM,
87*b0d29bc4SBrooks Davis config.lookup< config::string_node >("platform"));
88*b0d29bc4SBrooks Davis
89*b0d29bc4SBrooks Davis ATF_REQUIRE(!config.is_set("unprivileged_user"));
90*b0d29bc4SBrooks Davis
91*b0d29bc4SBrooks Davis ATF_REQUIRE(config.all_properties("test_suites").empty());
92*b0d29bc4SBrooks Davis }
93*b0d29bc4SBrooks Davis
94*b0d29bc4SBrooks Davis
95*b0d29bc4SBrooks Davis } // anonymous namespace
96*b0d29bc4SBrooks Davis
97*b0d29bc4SBrooks Davis
98*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(config__defaults);
ATF_TEST_CASE_BODY(config__defaults)99*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(config__defaults)
100*b0d29bc4SBrooks Davis {
101*b0d29bc4SBrooks Davis const config::tree user_config = engine::default_config();
102*b0d29bc4SBrooks Davis validate_defaults(user_config);
103*b0d29bc4SBrooks Davis }
104*b0d29bc4SBrooks Davis
105*b0d29bc4SBrooks Davis
106*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(config__set__parallelism);
ATF_TEST_CASE_BODY(config__set__parallelism)107*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(config__set__parallelism)
108*b0d29bc4SBrooks Davis {
109*b0d29bc4SBrooks Davis config::tree user_config = engine::default_config();
110*b0d29bc4SBrooks Davis user_config.set_string("parallelism", "8");
111*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW_RE(
112*b0d29bc4SBrooks Davis config::error, "parallelism.*Must be a positive integer",
113*b0d29bc4SBrooks Davis user_config.set_string("parallelism", "0"));
114*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW_RE(
115*b0d29bc4SBrooks Davis config::error, "parallelism.*Must be a positive integer",
116*b0d29bc4SBrooks Davis user_config.set_string("parallelism", "-1"));
117*b0d29bc4SBrooks Davis }
118*b0d29bc4SBrooks Davis
119*b0d29bc4SBrooks Davis
120*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(config__load__defaults);
ATF_TEST_CASE_BODY(config__load__defaults)121*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(config__load__defaults)
122*b0d29bc4SBrooks Davis {
123*b0d29bc4SBrooks Davis atf::utils::create_file("config", "syntax(2)\n");
124*b0d29bc4SBrooks Davis
125*b0d29bc4SBrooks Davis const config::tree user_config = engine::load_config(fs::path("config"));
126*b0d29bc4SBrooks Davis validate_defaults(user_config);
127*b0d29bc4SBrooks Davis }
128*b0d29bc4SBrooks Davis
129*b0d29bc4SBrooks Davis
130*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(config__load__overrides);
ATF_TEST_CASE_BODY(config__load__overrides)131*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(config__load__overrides)
132*b0d29bc4SBrooks Davis {
133*b0d29bc4SBrooks Davis set_mock_users();
134*b0d29bc4SBrooks Davis
135*b0d29bc4SBrooks Davis atf::utils::create_file(
136*b0d29bc4SBrooks Davis "config",
137*b0d29bc4SBrooks Davis "syntax(2)\n"
138*b0d29bc4SBrooks Davis "architecture = 'test-architecture'\n"
139*b0d29bc4SBrooks Davis "parallelism = 16\n"
140*b0d29bc4SBrooks Davis "platform = 'test-platform'\n"
141*b0d29bc4SBrooks Davis "unprivileged_user = 'user2'\n"
142*b0d29bc4SBrooks Davis "test_suites.mysuite.myvar = 'myvalue'\n");
143*b0d29bc4SBrooks Davis
144*b0d29bc4SBrooks Davis const config::tree user_config = engine::load_config(fs::path("config"));
145*b0d29bc4SBrooks Davis
146*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ("test-architecture",
147*b0d29bc4SBrooks Davis user_config.lookup_string("architecture"));
148*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ("16",
149*b0d29bc4SBrooks Davis user_config.lookup_string("parallelism"));
150*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ("test-platform",
151*b0d29bc4SBrooks Davis user_config.lookup_string("platform"));
152*b0d29bc4SBrooks Davis
153*b0d29bc4SBrooks Davis const passwd::user& user = user_config.lookup< engine::user_node >(
154*b0d29bc4SBrooks Davis "unprivileged_user");
155*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ("user2", user.name);
156*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(200, user.uid);
157*b0d29bc4SBrooks Davis
158*b0d29bc4SBrooks Davis config::properties_map exp_test_suites;
159*b0d29bc4SBrooks Davis exp_test_suites["test_suites.mysuite.myvar"] = "myvalue";
160*b0d29bc4SBrooks Davis
161*b0d29bc4SBrooks Davis ATF_REQUIRE(exp_test_suites == user_config.all_properties("test_suites"));
162*b0d29bc4SBrooks Davis }
163*b0d29bc4SBrooks Davis
164*b0d29bc4SBrooks Davis
165*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(config__load__lua_error);
ATF_TEST_CASE_BODY(config__load__lua_error)166*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(config__load__lua_error)
167*b0d29bc4SBrooks Davis {
168*b0d29bc4SBrooks Davis atf::utils::create_file("config", "this syntax is invalid\n");
169*b0d29bc4SBrooks Davis
170*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW(engine::load_error, engine::load_config(
171*b0d29bc4SBrooks Davis fs::path("config")));
172*b0d29bc4SBrooks Davis }
173*b0d29bc4SBrooks Davis
174*b0d29bc4SBrooks Davis
175*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(config__load__bad_syntax__version);
ATF_TEST_CASE_BODY(config__load__bad_syntax__version)176*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(config__load__bad_syntax__version)
177*b0d29bc4SBrooks Davis {
178*b0d29bc4SBrooks Davis atf::utils::create_file("config", "syntax(123)\n");
179*b0d29bc4SBrooks Davis
180*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW_RE(engine::load_error,
181*b0d29bc4SBrooks Davis "Unsupported config version 123",
182*b0d29bc4SBrooks Davis engine::load_config(fs::path("config")));
183*b0d29bc4SBrooks Davis }
184*b0d29bc4SBrooks Davis
185*b0d29bc4SBrooks Davis
186*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(config__load__missing_file);
ATF_TEST_CASE_BODY(config__load__missing_file)187*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(config__load__missing_file)
188*b0d29bc4SBrooks Davis {
189*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW_RE(engine::load_error, "Load of 'missing' failed",
190*b0d29bc4SBrooks Davis engine::load_config(fs::path("missing")));
191*b0d29bc4SBrooks Davis }
192*b0d29bc4SBrooks Davis
193*b0d29bc4SBrooks Davis
ATF_INIT_TEST_CASES(tcs)194*b0d29bc4SBrooks Davis ATF_INIT_TEST_CASES(tcs)
195*b0d29bc4SBrooks Davis {
196*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, config__defaults);
197*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, config__set__parallelism);
198*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, config__load__defaults);
199*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, config__load__overrides);
200*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, config__load__lua_error);
201*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, config__load__bad_syntax__version);
202*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, config__load__missing_file);
203*b0d29bc4SBrooks Davis }
204