config_test.cpp revision 1.1 1 1.1 jmmv // Copyright 2011 Google Inc.
2 1.1 jmmv // All rights reserved.
3 1.1 jmmv //
4 1.1 jmmv // Redistribution and use in source and binary forms, with or without
5 1.1 jmmv // modification, are permitted provided that the following conditions are
6 1.1 jmmv // met:
7 1.1 jmmv //
8 1.1 jmmv // * Redistributions of source code must retain the above copyright
9 1.1 jmmv // notice, this list of conditions and the following disclaimer.
10 1.1 jmmv // * Redistributions in binary form must reproduce the above copyright
11 1.1 jmmv // notice, this list of conditions and the following disclaimer in the
12 1.1 jmmv // documentation and/or other materials provided with the distribution.
13 1.1 jmmv // * Neither the name of Google Inc. nor the names of its contributors
14 1.1 jmmv // may be used to endorse or promote products derived from this software
15 1.1 jmmv // without specific prior written permission.
16 1.1 jmmv //
17 1.1 jmmv // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 1.1 jmmv // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 1.1 jmmv // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 1.1 jmmv // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 1.1 jmmv // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 1.1 jmmv // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 1.1 jmmv // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 1.1 jmmv // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 1.1 jmmv // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 1.1 jmmv // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 1.1 jmmv // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.1 jmmv
29 1.1 jmmv #include "cli/config.hpp"
30 1.1 jmmv
31 1.1 jmmv #include <atf-c++.hpp>
32 1.1 jmmv
33 1.1 jmmv #include "engine/config.hpp"
34 1.1 jmmv #include "engine/exceptions.hpp"
35 1.1 jmmv #include "utils/env.hpp"
36 1.1 jmmv #include "utils/format/macros.hpp"
37 1.1 jmmv #include "utils/fs/operations.hpp"
38 1.1 jmmv #include "utils/fs/path.hpp"
39 1.1 jmmv
40 1.1 jmmv namespace cmdline = utils::cmdline;
41 1.1 jmmv namespace config = utils::config;
42 1.1 jmmv namespace fs = utils::fs;
43 1.1 jmmv
44 1.1 jmmv
45 1.1 jmmv namespace {
46 1.1 jmmv
47 1.1 jmmv
48 1.1 jmmv /// Creates a configuration file for testing purposes.
49 1.1 jmmv ///
50 1.1 jmmv /// To ensure that the loaded file is the one created by this function, use
51 1.1 jmmv /// validate_mock_config().
52 1.1 jmmv ///
53 1.1 jmmv /// \param name The name of the configuration file to create.
54 1.1 jmmv /// \param cookie The magic value to set in the configuration file, or NULL if a
55 1.1 jmmv /// broken configuration file is desired.
56 1.1 jmmv static void
57 1.1 jmmv create_mock_config(const char* name, const char* cookie)
58 1.1 jmmv {
59 1.1 jmmv if (cookie != NULL) {
60 1.1 jmmv atf::utils::create_file(
61 1.1 jmmv name,
62 1.1 jmmv F("syntax(2)\n"
63 1.1 jmmv "test_suites.suite.magic_value = '%s'\n") % cookie);
64 1.1 jmmv } else {
65 1.1 jmmv atf::utils::create_file(name, "syntax(200)\n");
66 1.1 jmmv }
67 1.1 jmmv }
68 1.1 jmmv
69 1.1 jmmv
70 1.1 jmmv /// Creates an invalid system configuration.
71 1.1 jmmv ///
72 1.1 jmmv /// \param cookie The magic value to set in the configuration file, or NULL if a
73 1.1 jmmv /// broken configuration file is desired.
74 1.1 jmmv static void
75 1.1 jmmv mock_system_config(const char* cookie)
76 1.1 jmmv {
77 1.1 jmmv fs::mkdir(fs::path("system-dir"), 0755);
78 1.1 jmmv utils::setenv("KYUA_CONFDIR", (fs::current_path() / "system-dir").str());
79 1.1 jmmv create_mock_config("system-dir/kyua.conf", cookie);
80 1.1 jmmv }
81 1.1 jmmv
82 1.1 jmmv
83 1.1 jmmv /// Creates an invalid user configuration.
84 1.1 jmmv ///
85 1.1 jmmv /// \param cookie The magic value to set in the configuration file, or NULL if a
86 1.1 jmmv /// broken configuration file is desired.
87 1.1 jmmv static void
88 1.1 jmmv mock_user_config(const char* cookie)
89 1.1 jmmv {
90 1.1 jmmv fs::mkdir(fs::path("user-dir"), 0755);
91 1.1 jmmv fs::mkdir(fs::path("user-dir/.kyua"), 0755);
92 1.1 jmmv utils::setenv("HOME", (fs::current_path() / "user-dir").str());
93 1.1 jmmv create_mock_config("user-dir/.kyua/kyua.conf", cookie);
94 1.1 jmmv }
95 1.1 jmmv
96 1.1 jmmv
97 1.1 jmmv /// Ensures that a loaded configuration was created with create_mock_config().
98 1.1 jmmv ///
99 1.1 jmmv /// \param user_config The configuration to validate.
100 1.1 jmmv /// \param cookie The magic value to expect in the configuration file.
101 1.1 jmmv static void
102 1.1 jmmv validate_mock_config(const config::tree& user_config, const char* cookie)
103 1.1 jmmv {
104 1.1 jmmv const config::properties_map& properties = user_config.all_properties(
105 1.1 jmmv "test_suites.suite", true);
106 1.1 jmmv const config::properties_map::const_iterator iter =
107 1.1 jmmv properties.find("magic_value");
108 1.1 jmmv ATF_REQUIRE(iter != properties.end());
109 1.1 jmmv ATF_REQUIRE_EQ(cookie, (*iter).second);
110 1.1 jmmv }
111 1.1 jmmv
112 1.1 jmmv
113 1.1 jmmv /// Ensures that two configuration trees are equal.
114 1.1 jmmv ///
115 1.1 jmmv /// \param exp_tree The expected configuration tree.
116 1.1 jmmv /// \param actual_tree The configuration tree being validated against exp_tree.
117 1.1 jmmv static void
118 1.1 jmmv require_eq(const config::tree& exp_tree, const config::tree& actual_tree)
119 1.1 jmmv {
120 1.1 jmmv ATF_REQUIRE(exp_tree.all_properties() == actual_tree.all_properties());
121 1.1 jmmv }
122 1.1 jmmv
123 1.1 jmmv
124 1.1 jmmv } // anonymous namespace
125 1.1 jmmv
126 1.1 jmmv
127 1.1 jmmv ATF_TEST_CASE_WITHOUT_HEAD(load_config__none);
128 1.1 jmmv ATF_TEST_CASE_BODY(load_config__none)
129 1.1 jmmv {
130 1.1 jmmv utils::setenv("KYUA_CONFDIR", "/the/system/does/not/exist");
131 1.1 jmmv utils::setenv("HOME", "/the/user/does/not/exist");
132 1.1 jmmv
133 1.1 jmmv std::map< std::string, std::vector< std::string > > options;
134 1.1 jmmv options["config"].push_back(cli::config_option.default_value());
135 1.1 jmmv const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
136 1.1 jmmv
137 1.1 jmmv require_eq(engine::default_config(),
138 1.1 jmmv cli::load_config(mock_cmdline, true));
139 1.1 jmmv }
140 1.1 jmmv
141 1.1 jmmv
142 1.1 jmmv ATF_TEST_CASE_WITHOUT_HEAD(load_config__explicit__ok);
143 1.1 jmmv ATF_TEST_CASE_BODY(load_config__explicit__ok)
144 1.1 jmmv {
145 1.1 jmmv mock_system_config(NULL);
146 1.1 jmmv mock_user_config(NULL);
147 1.1 jmmv
148 1.1 jmmv create_mock_config("test-file", "hello");
149 1.1 jmmv
150 1.1 jmmv std::map< std::string, std::vector< std::string > > options;
151 1.1 jmmv options["config"].push_back("test-file");
152 1.1 jmmv const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
153 1.1 jmmv
154 1.1 jmmv const config::tree user_config = cli::load_config(mock_cmdline, true);
155 1.1 jmmv validate_mock_config(user_config, "hello");
156 1.1 jmmv }
157 1.1 jmmv
158 1.1 jmmv
159 1.1 jmmv ATF_TEST_CASE_WITHOUT_HEAD(load_config__explicit__disable);
160 1.1 jmmv ATF_TEST_CASE_BODY(load_config__explicit__disable)
161 1.1 jmmv {
162 1.1 jmmv mock_system_config(NULL);
163 1.1 jmmv mock_user_config(NULL);
164 1.1 jmmv
165 1.1 jmmv std::map< std::string, std::vector< std::string > > options;
166 1.1 jmmv options["config"].push_back("none");
167 1.1 jmmv const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
168 1.1 jmmv
169 1.1 jmmv require_eq(engine::default_config(),
170 1.1 jmmv cli::load_config(mock_cmdline, true));
171 1.1 jmmv }
172 1.1 jmmv
173 1.1 jmmv
174 1.1 jmmv ATF_TEST_CASE_WITHOUT_HEAD(load_config__explicit__fail);
175 1.1 jmmv ATF_TEST_CASE_BODY(load_config__explicit__fail)
176 1.1 jmmv {
177 1.1 jmmv mock_system_config("ok1");
178 1.1 jmmv mock_user_config("ok2");
179 1.1 jmmv
180 1.1 jmmv create_mock_config("test-file", NULL);
181 1.1 jmmv
182 1.1 jmmv std::map< std::string, std::vector< std::string > > options;
183 1.1 jmmv options["config"].push_back("test-file");
184 1.1 jmmv const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
185 1.1 jmmv
186 1.1 jmmv ATF_REQUIRE_THROW_RE(engine::error, "200",
187 1.1 jmmv cli::load_config(mock_cmdline, true));
188 1.1 jmmv
189 1.1 jmmv const config::tree config = cli::load_config(mock_cmdline, false);
190 1.1 jmmv require_eq(engine::default_config(), config);
191 1.1 jmmv }
192 1.1 jmmv
193 1.1 jmmv
194 1.1 jmmv ATF_TEST_CASE_WITHOUT_HEAD(load_config__user__ok);
195 1.1 jmmv ATF_TEST_CASE_BODY(load_config__user__ok)
196 1.1 jmmv {
197 1.1 jmmv mock_system_config(NULL);
198 1.1 jmmv mock_user_config("I am the user config");
199 1.1 jmmv
200 1.1 jmmv std::map< std::string, std::vector< std::string > > options;
201 1.1 jmmv options["config"].push_back(cli::config_option.default_value());
202 1.1 jmmv const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
203 1.1 jmmv
204 1.1 jmmv const config::tree user_config = cli::load_config(mock_cmdline, true);
205 1.1 jmmv validate_mock_config(user_config, "I am the user config");
206 1.1 jmmv }
207 1.1 jmmv
208 1.1 jmmv
209 1.1 jmmv ATF_TEST_CASE_WITHOUT_HEAD(load_config__user__fail);
210 1.1 jmmv ATF_TEST_CASE_BODY(load_config__user__fail)
211 1.1 jmmv {
212 1.1 jmmv mock_system_config("valid");
213 1.1 jmmv mock_user_config(NULL);
214 1.1 jmmv
215 1.1 jmmv std::map< std::string, std::vector< std::string > > options;
216 1.1 jmmv options["config"].push_back(cli::config_option.default_value());
217 1.1 jmmv const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
218 1.1 jmmv
219 1.1 jmmv ATF_REQUIRE_THROW_RE(engine::error, "200",
220 1.1 jmmv cli::load_config(mock_cmdline, true));
221 1.1 jmmv
222 1.1 jmmv const config::tree config = cli::load_config(mock_cmdline, false);
223 1.1 jmmv require_eq(engine::default_config(), config);
224 1.1 jmmv }
225 1.1 jmmv
226 1.1 jmmv
227 1.1 jmmv ATF_TEST_CASE_WITHOUT_HEAD(load_config__user__bad_home);
228 1.1 jmmv ATF_TEST_CASE_BODY(load_config__user__bad_home)
229 1.1 jmmv {
230 1.1 jmmv mock_system_config("Fallback system config");
231 1.1 jmmv utils::setenv("HOME", "");
232 1.1 jmmv
233 1.1 jmmv std::map< std::string, std::vector< std::string > > options;
234 1.1 jmmv options["config"].push_back(cli::config_option.default_value());
235 1.1 jmmv const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
236 1.1 jmmv
237 1.1 jmmv const config::tree user_config = cli::load_config(mock_cmdline, true);
238 1.1 jmmv validate_mock_config(user_config, "Fallback system config");
239 1.1 jmmv }
240 1.1 jmmv
241 1.1 jmmv
242 1.1 jmmv ATF_TEST_CASE_WITHOUT_HEAD(load_config__system__ok);
243 1.1 jmmv ATF_TEST_CASE_BODY(load_config__system__ok)
244 1.1 jmmv {
245 1.1 jmmv mock_system_config("I am the system config");
246 1.1 jmmv utils::setenv("HOME", "/the/user/does/not/exist");
247 1.1 jmmv
248 1.1 jmmv std::map< std::string, std::vector< std::string > > options;
249 1.1 jmmv options["config"].push_back(cli::config_option.default_value());
250 1.1 jmmv const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
251 1.1 jmmv
252 1.1 jmmv const config::tree user_config = cli::load_config(mock_cmdline, true);
253 1.1 jmmv validate_mock_config(user_config, "I am the system config");
254 1.1 jmmv }
255 1.1 jmmv
256 1.1 jmmv
257 1.1 jmmv ATF_TEST_CASE_WITHOUT_HEAD(load_config__system__fail);
258 1.1 jmmv ATF_TEST_CASE_BODY(load_config__system__fail)
259 1.1 jmmv {
260 1.1 jmmv mock_system_config(NULL);
261 1.1 jmmv utils::setenv("HOME", "/the/user/does/not/exist");
262 1.1 jmmv
263 1.1 jmmv std::map< std::string, std::vector< std::string > > options;
264 1.1 jmmv options["config"].push_back(cli::config_option.default_value());
265 1.1 jmmv const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
266 1.1 jmmv
267 1.1 jmmv ATF_REQUIRE_THROW_RE(engine::error, "200",
268 1.1 jmmv cli::load_config(mock_cmdline, true));
269 1.1 jmmv
270 1.1 jmmv const config::tree config = cli::load_config(mock_cmdline, false);
271 1.1 jmmv require_eq(engine::default_config(), config);
272 1.1 jmmv }
273 1.1 jmmv
274 1.1 jmmv
275 1.1 jmmv ATF_TEST_CASE_WITHOUT_HEAD(load_config__overrides__no);
276 1.1 jmmv ATF_TEST_CASE_BODY(load_config__overrides__no)
277 1.1 jmmv {
278 1.1 jmmv utils::setenv("KYUA_CONFDIR", fs::current_path().str());
279 1.1 jmmv
280 1.1 jmmv std::map< std::string, std::vector< std::string > > options;
281 1.1 jmmv options["config"].push_back(cli::config_option.default_value());
282 1.1 jmmv options["variable"].push_back("architecture=1");
283 1.1 jmmv options["variable"].push_back("platform=2");
284 1.1 jmmv const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
285 1.1 jmmv
286 1.1 jmmv const config::tree user_config = cli::load_config(mock_cmdline, true);
287 1.1 jmmv ATF_REQUIRE_EQ("1",
288 1.1 jmmv user_config.lookup< config::string_node >("architecture"));
289 1.1 jmmv ATF_REQUIRE_EQ("2",
290 1.1 jmmv user_config.lookup< config::string_node >("platform"));
291 1.1 jmmv }
292 1.1 jmmv
293 1.1 jmmv
294 1.1 jmmv ATF_TEST_CASE_WITHOUT_HEAD(load_config__overrides__yes);
295 1.1 jmmv ATF_TEST_CASE_BODY(load_config__overrides__yes)
296 1.1 jmmv {
297 1.1 jmmv atf::utils::create_file(
298 1.1 jmmv "config",
299 1.1 jmmv "syntax(2)\n"
300 1.1 jmmv "architecture = 'do not see me'\n"
301 1.1 jmmv "platform = 'see me'\n");
302 1.1 jmmv
303 1.1 jmmv std::map< std::string, std::vector< std::string > > options;
304 1.1 jmmv options["config"].push_back("config");
305 1.1 jmmv options["variable"].push_back("architecture=overriden");
306 1.1 jmmv const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
307 1.1 jmmv
308 1.1 jmmv const config::tree user_config = cli::load_config(mock_cmdline, true);
309 1.1 jmmv ATF_REQUIRE_EQ("overriden",
310 1.1 jmmv user_config.lookup< config::string_node >("architecture"));
311 1.1 jmmv ATF_REQUIRE_EQ("see me",
312 1.1 jmmv user_config.lookup< config::string_node >("platform"));
313 1.1 jmmv }
314 1.1 jmmv
315 1.1 jmmv
316 1.1 jmmv ATF_TEST_CASE_WITHOUT_HEAD(load_config__overrides__fail);
317 1.1 jmmv ATF_TEST_CASE_BODY(load_config__overrides__fail)
318 1.1 jmmv {
319 1.1 jmmv utils::setenv("KYUA_CONFDIR", fs::current_path().str());
320 1.1 jmmv
321 1.1 jmmv std::map< std::string, std::vector< std::string > > options;
322 1.1 jmmv options["config"].push_back(cli::config_option.default_value());
323 1.1 jmmv options["variable"].push_back(".a=d");
324 1.1 jmmv const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
325 1.1 jmmv
326 1.1 jmmv ATF_REQUIRE_THROW_RE(engine::error, "Empty component in key.*'\\.a'",
327 1.1 jmmv cli::load_config(mock_cmdline, true));
328 1.1 jmmv
329 1.1 jmmv const config::tree config = cli::load_config(mock_cmdline, false);
330 1.1 jmmv require_eq(engine::default_config(), config);
331 1.1 jmmv }
332 1.1 jmmv
333 1.1 jmmv
334 1.1 jmmv ATF_INIT_TEST_CASES(tcs)
335 1.1 jmmv {
336 1.1 jmmv ATF_ADD_TEST_CASE(tcs, load_config__none);
337 1.1 jmmv ATF_ADD_TEST_CASE(tcs, load_config__explicit__ok);
338 1.1 jmmv ATF_ADD_TEST_CASE(tcs, load_config__explicit__disable);
339 1.1 jmmv ATF_ADD_TEST_CASE(tcs, load_config__explicit__fail);
340 1.1 jmmv ATF_ADD_TEST_CASE(tcs, load_config__user__ok);
341 1.1 jmmv ATF_ADD_TEST_CASE(tcs, load_config__user__fail);
342 1.1 jmmv ATF_ADD_TEST_CASE(tcs, load_config__user__bad_home);
343 1.1 jmmv ATF_ADD_TEST_CASE(tcs, load_config__system__ok);
344 1.1 jmmv ATF_ADD_TEST_CASE(tcs, load_config__system__fail);
345 1.1 jmmv ATF_ADD_TEST_CASE(tcs, load_config__overrides__no);
346 1.1 jmmv ATF_ADD_TEST_CASE(tcs, load_config__overrides__yes);
347 1.1 jmmv ATF_ADD_TEST_CASE(tcs, load_config__overrides__fail);
348 1.1 jmmv }
349