1 // Copyright 2012 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/metadata.hpp"
30 
31 #include <sstream>
32 
33 #include <atf-c++.hpp>
34 
35 #include "engine/config.hpp"
36 #include "utils/config/tree.ipp"
37 #include "utils/datetime.hpp"
38 #include "utils/env.hpp"
39 #include "utils/fs/operations.hpp"
40 #include "utils/fs/path.hpp"
41 #include "utils/memory.hpp"
42 #include "utils/passwd.hpp"
43 #include "utils/units.hpp"
44 
45 namespace config = utils::config;
46 namespace datetime = utils::datetime;
47 namespace fs = utils::fs;
48 namespace passwd = utils::passwd;
49 namespace units = utils::units;
50 
51 
52 ATF_TEST_CASE_WITHOUT_HEAD(defaults);
ATF_TEST_CASE_BODY(defaults)53 ATF_TEST_CASE_BODY(defaults)
54 {
55     const engine::metadata md = engine::metadata_builder().build();
56     ATF_REQUIRE(md.allowed_architectures().empty());
57     ATF_REQUIRE(md.allowed_platforms().empty());
58     ATF_REQUIRE(md.allowed_platforms().empty());
59     ATF_REQUIRE(md.custom().empty());
60     ATF_REQUIRE(md.description().empty());
61     ATF_REQUIRE(!md.has_cleanup());
62     ATF_REQUIRE(md.required_configs().empty());
63     ATF_REQUIRE(md.required_files().empty());
64     ATF_REQUIRE_EQ(units::bytes(0), md.required_memory());
65     ATF_REQUIRE(md.required_programs().empty());
66     ATF_REQUIRE(md.required_user().empty());
67     ATF_REQUIRE(engine::default_timeout == md.timeout());
68 }
69 
70 
71 ATF_TEST_CASE_WITHOUT_HEAD(add);
ATF_TEST_CASE_BODY(add)72 ATF_TEST_CASE_BODY(add)
73 {
74     engine::strings_set architectures;
75     architectures.insert("1-architecture");
76     architectures.insert("2-architecture");
77 
78     engine::strings_set platforms;
79     platforms.insert("1-platform");
80     platforms.insert("2-platform");
81 
82     engine::properties_map custom;
83     custom["1-custom"] = "first";
84     custom["2-custom"] = "second";
85 
86     engine::strings_set configs;
87     configs.insert("1-config");
88     configs.insert("2-config");
89 
90     engine::paths_set files;
91     files.insert(fs::path("1-file"));
92     files.insert(fs::path("2-file"));
93 
94     engine::paths_set programs;
95     programs.insert(fs::path("1-program"));
96     programs.insert(fs::path("2-program"));
97 
98     const engine::metadata md = engine::metadata_builder()
99         .add_allowed_architecture("1-architecture")
100         .add_allowed_platform("1-platform")
101         .add_custom("1-custom", "first")
102         .add_custom("2-custom", "second")
103         .add_required_config("1-config")
104         .add_required_file(fs::path("1-file"))
105         .add_required_program(fs::path("1-program"))
106         .add_allowed_architecture("2-architecture")
107         .add_allowed_platform("2-platform")
108         .add_required_config("2-config")
109         .add_required_file(fs::path("2-file"))
110         .add_required_program(fs::path("2-program"))
111         .build();
112 
113     ATF_REQUIRE(architectures == md.allowed_architectures());
114     ATF_REQUIRE(platforms == md.allowed_platforms());
115     ATF_REQUIRE(custom == md.custom());
116     ATF_REQUIRE(configs == md.required_configs());
117     ATF_REQUIRE(files == md.required_files());
118     ATF_REQUIRE(programs == md.required_programs());
119 }
120 
121 
122 ATF_TEST_CASE_WITHOUT_HEAD(copy);
ATF_TEST_CASE_BODY(copy)123 ATF_TEST_CASE_BODY(copy)
124 {
125     const engine::metadata md1 = engine::metadata_builder()
126         .add_allowed_architecture("1-architecture")
127         .add_allowed_platform("1-platform")
128         .build();
129 
130     const engine::metadata md2 = engine::metadata_builder(md1)
131         .add_allowed_architecture("2-architecture")
132         .build();
133 
134     ATF_REQUIRE_EQ(1, md1.allowed_architectures().size());
135     ATF_REQUIRE_EQ(2, md2.allowed_architectures().size());
136     ATF_REQUIRE_EQ(1, md1.allowed_platforms().size());
137     ATF_REQUIRE_EQ(1, md2.allowed_platforms().size());
138 }
139 
140 
141 ATF_TEST_CASE_WITHOUT_HEAD(override_all_with_setters);
ATF_TEST_CASE_BODY(override_all_with_setters)142 ATF_TEST_CASE_BODY(override_all_with_setters)
143 {
144     engine::strings_set architectures;
145     architectures.insert("the-architecture");
146 
147     engine::strings_set platforms;
148     platforms.insert("the-platforms");
149 
150     engine::properties_map custom;
151     custom["first"] = "hello";
152     custom["second"] = "bye";
153 
154     const std::string description = "Some long text";
155 
156     engine::strings_set configs;
157     configs.insert("the-configs");
158 
159     engine::paths_set files;
160     files.insert(fs::path("the-files"));
161 
162     const units::bytes memory(12345);
163 
164     engine::paths_set programs;
165     programs.insert(fs::path("the-programs"));
166 
167     const std::string user = "root";
168 
169     const datetime::delta timeout(123, 0);
170 
171     const engine::metadata md = engine::metadata_builder()
172         .set_allowed_architectures(architectures)
173         .set_allowed_platforms(platforms)
174         .set_custom(custom)
175         .set_description(description)
176         .set_has_cleanup(true)
177         .set_required_configs(configs)
178         .set_required_files(files)
179         .set_required_memory(memory)
180         .set_required_programs(programs)
181         .set_required_user(user)
182         .set_timeout(timeout)
183         .build();
184 
185     ATF_REQUIRE(architectures == md.allowed_architectures());
186     ATF_REQUIRE(platforms == md.allowed_platforms());
187     ATF_REQUIRE(custom == md.custom());
188     ATF_REQUIRE_EQ(description, md.description());
189     ATF_REQUIRE(md.has_cleanup());
190     ATF_REQUIRE(configs == md.required_configs());
191     ATF_REQUIRE(files == md.required_files());
192     ATF_REQUIRE_EQ(memory, md.required_memory());
193     ATF_REQUIRE(programs == md.required_programs());
194     ATF_REQUIRE_EQ(user, md.required_user());
195     ATF_REQUIRE(timeout == md.timeout());
196 }
197 
198 
199 ATF_TEST_CASE_WITHOUT_HEAD(override_all_with_set_string);
ATF_TEST_CASE_BODY(override_all_with_set_string)200 ATF_TEST_CASE_BODY(override_all_with_set_string)
201 {
202     engine::strings_set architectures;
203     architectures.insert("a1");
204     architectures.insert("a2");
205 
206     engine::strings_set platforms;
207     platforms.insert("p1");
208     platforms.insert("p2");
209 
210     engine::properties_map custom;
211     custom["user-defined"] = "the-value";
212 
213     const std::string description = "Another long text";
214 
215     engine::strings_set configs;
216     configs.insert("config-var");
217 
218     engine::paths_set files;
219     files.insert(fs::path("plain"));
220     files.insert(fs::path("/absolute/path"));
221 
222     const units::bytes memory(1024 * 1024);
223 
224     engine::paths_set programs;
225     programs.insert(fs::path("program"));
226     programs.insert(fs::path("/absolute/prog"));
227 
228     const std::string user = "unprivileged";
229 
230     const datetime::delta timeout(45, 0);
231 
232     const engine::metadata md = engine::metadata_builder()
233         .set_string("allowed_architectures", "a1 a2")
234         .set_string("allowed_platforms", "p1 p2")
235         .set_string("custom.user-defined", "the-value")
236         .set_string("description", "Another long text")
237         .set_string("has_cleanup", "true")
238         .set_string("required_configs", "config-var")
239         .set_string("required_files", "plain /absolute/path")
240         .set_string("required_memory", "1M")
241         .set_string("required_programs", "program /absolute/prog")
242         .set_string("required_user", "unprivileged")
243         .set_string("timeout", "45")
244         .build();
245 
246     ATF_REQUIRE(architectures == md.allowed_architectures());
247     ATF_REQUIRE(platforms == md.allowed_platforms());
248     ATF_REQUIRE(custom == md.custom());
249     ATF_REQUIRE_EQ(description, md.description());
250     ATF_REQUIRE(md.has_cleanup());
251     ATF_REQUIRE(configs == md.required_configs());
252     ATF_REQUIRE(files == md.required_files());
253     ATF_REQUIRE_EQ(memory, md.required_memory());
254     ATF_REQUIRE(programs == md.required_programs());
255     ATF_REQUIRE_EQ(user, md.required_user());
256     ATF_REQUIRE(timeout == md.timeout());
257 }
258 
259 
260 ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__empty);
ATF_TEST_CASE_BODY(operators_eq_and_ne__empty)261 ATF_TEST_CASE_BODY(operators_eq_and_ne__empty)
262 {
263     const engine::metadata md1 = engine::metadata_builder().build();
264     const engine::metadata md2 = engine::metadata_builder().build();
265     ATF_REQUIRE(  md1 == md2);
266     ATF_REQUIRE(!(md1 != md2));
267 }
268 
269 
270 ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__copy);
ATF_TEST_CASE_BODY(operators_eq_and_ne__copy)271 ATF_TEST_CASE_BODY(operators_eq_and_ne__copy)
272 {
273     const engine::metadata md1 = engine::metadata_builder()
274         .add_custom("X-foo", "bar")
275         .build();
276     const engine::metadata md2 = md1;
277     ATF_REQUIRE(  md1 == md2);
278     ATF_REQUIRE(!(md1 != md2));
279 }
280 
281 
282 ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__equal);
ATF_TEST_CASE_BODY(operators_eq_and_ne__equal)283 ATF_TEST_CASE_BODY(operators_eq_and_ne__equal)
284 {
285     const engine::metadata md1 = engine::metadata_builder()
286         .add_allowed_architecture("a")
287         .add_allowed_architecture("b")
288         .add_custom("X-foo", "bar")
289         .build();
290     const engine::metadata md2 = engine::metadata_builder()
291         .add_allowed_architecture("b")
292         .add_allowed_architecture("a")
293         .add_custom("X-foo", "bar")
294         .build();
295     ATF_REQUIRE(  md1 == md2);
296     ATF_REQUIRE(!(md1 != md2));
297 }
298 
299 
300 ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__different);
ATF_TEST_CASE_BODY(operators_eq_and_ne__different)301 ATF_TEST_CASE_BODY(operators_eq_and_ne__different)
302 {
303     const engine::metadata md1 = engine::metadata_builder()
304         .add_custom("X-foo", "bar")
305         .build();
306     const engine::metadata md2 = engine::metadata_builder()
307         .add_custom("X-foo", "bar")
308         .add_custom("X-baz", "foo bar")
309         .build();
310     ATF_REQUIRE(!(md1 == md2));
311     ATF_REQUIRE(  md1 != md2);
312 }
313 
314 
315 ATF_TEST_CASE_WITHOUT_HEAD(output__defaults);
ATF_TEST_CASE_BODY(output__defaults)316 ATF_TEST_CASE_BODY(output__defaults)
317 {
318     std::ostringstream str;
319     str << engine::metadata_builder().build();
320     ATF_REQUIRE_EQ("metadata{allowed_architectures='', allowed_platforms='', "
321                    "description='', has_cleanup='false', required_configs='', "
322                    "required_files='', required_memory='0', "
323                    "required_programs='', required_user='', timeout='300'}",
324                    str.str());
325 }
326 
327 
328 ATF_TEST_CASE_WITHOUT_HEAD(output__some_values);
ATF_TEST_CASE_BODY(output__some_values)329 ATF_TEST_CASE_BODY(output__some_values)
330 {
331     std::ostringstream str;
332     str << engine::metadata_builder()
333         .add_allowed_architecture("abc")
334         .add_required_file(fs::path("foo"))
335         .add_required_file(fs::path("bar"))
336         .set_required_memory(units::bytes(1024))
337         .build();
338     ATF_REQUIRE_EQ(
339         "metadata{allowed_architectures='abc', allowed_platforms='', "
340         "description='', has_cleanup='false', required_configs='', "
341         "required_files='bar foo', required_memory='1.00K', "
342         "required_programs='', required_user='', timeout='300'}",
343         str.str());
344 }
345 
346 
347 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__none);
ATF_TEST_CASE_BODY(check_reqs__none)348 ATF_TEST_CASE_BODY(check_reqs__none)
349 {
350     const engine::metadata md = engine::metadata_builder().build();
351     ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "").empty());
352 }
353 
354 
355 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__one_ok);
ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__one_ok)356 ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__one_ok)
357 {
358     const engine::metadata md = engine::metadata_builder()
359         .add_allowed_architecture("x86_64")
360         .build();
361 
362     config::tree user_config = engine::default_config();
363     user_config.set_string("architecture", "x86_64");
364     user_config.set_string("platform", "");
365     ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty());
366 }
367 
368 
369 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__one_fail);
ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__one_fail)370 ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__one_fail)
371 {
372     const engine::metadata md = engine::metadata_builder()
373         .add_allowed_architecture("x86_64")
374         .build();
375 
376     config::tree user_config = engine::default_config();
377     user_config.set_string("architecture", "i386");
378     user_config.set_string("platform", "");
379     ATF_REQUIRE_MATCH("Current architecture 'i386' not supported",
380                       engine::check_reqs(md, user_config, ""));
381 }
382 
383 
384 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__many_ok);
ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__many_ok)385 ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__many_ok)
386 {
387     const engine::metadata md = engine::metadata_builder()
388         .add_allowed_architecture("x86_64")
389         .add_allowed_architecture("i386")
390         .add_allowed_architecture("powerpc")
391         .build();
392 
393     config::tree user_config = engine::default_config();
394     user_config.set_string("architecture", "i386");
395     user_config.set_string("platform", "");
396     ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty());
397 }
398 
399 
400 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__many_fail);
ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__many_fail)401 ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__many_fail)
402 {
403     const engine::metadata md = engine::metadata_builder()
404         .add_allowed_architecture("x86_64")
405         .add_allowed_architecture("i386")
406         .add_allowed_architecture("powerpc")
407         .build();
408 
409     config::tree user_config = engine::default_config();
410     user_config.set_string("architecture", "arm");
411     user_config.set_string("platform", "");
412     ATF_REQUIRE_MATCH("Current architecture 'arm' not supported",
413                       engine::check_reqs(md, user_config, ""));
414 }
415 
416 
417 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__one_ok);
ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__one_ok)418 ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__one_ok)
419 {
420     const engine::metadata md = engine::metadata_builder()
421         .add_allowed_platform("amd64")
422         .build();
423 
424     config::tree user_config = engine::default_config();
425     user_config.set_string("architecture", "");
426     user_config.set_string("platform", "amd64");
427     ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty());
428 }
429 
430 
431 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__one_fail);
ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__one_fail)432 ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__one_fail)
433 {
434     const engine::metadata md = engine::metadata_builder()
435         .add_allowed_platform("amd64")
436         .build();
437 
438     config::tree user_config = engine::default_config();
439     user_config.set_string("architecture", "");
440     user_config.set_string("platform", "i386");
441     ATF_REQUIRE_MATCH("Current platform 'i386' not supported",
442                       engine::check_reqs(md, user_config, ""));
443 }
444 
445 
446 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__many_ok);
ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__many_ok)447 ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__many_ok)
448 {
449     const engine::metadata md = engine::metadata_builder()
450         .add_allowed_platform("amd64")
451         .add_allowed_platform("i386")
452         .add_allowed_platform("macppc")
453         .build();
454 
455     config::tree user_config = engine::default_config();
456     user_config.set_string("architecture", "");
457     user_config.set_string("platform", "i386");
458     ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty());
459 }
460 
461 
462 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__many_fail);
ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__many_fail)463 ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__many_fail)
464 {
465     const engine::metadata md = engine::metadata_builder()
466         .add_allowed_platform("amd64")
467         .add_allowed_platform("i386")
468         .add_allowed_platform("macppc")
469         .build();
470 
471     config::tree user_config = engine::default_config();
472     user_config.set_string("architecture", "");
473     user_config.set_string("platform", "shark");
474     ATF_REQUIRE_MATCH("Current platform 'shark' not supported",
475                       engine::check_reqs(md, user_config, ""));
476 }
477 
478 
479 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__one_ok);
ATF_TEST_CASE_BODY(check_reqs__required_configs__one_ok)480 ATF_TEST_CASE_BODY(check_reqs__required_configs__one_ok)
481 {
482     const engine::metadata md = engine::metadata_builder()
483         .add_required_config("my-var")
484         .build();
485 
486     config::tree user_config = engine::default_config();
487     user_config.set_string("test_suites.suite.aaa", "value1");
488     user_config.set_string("test_suites.suite.my-var", "value2");
489     user_config.set_string("test_suites.suite.zzz", "value3");
490     ATF_REQUIRE(engine::check_reqs(md, user_config, "suite").empty());
491 }
492 
493 
494 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__one_fail);
ATF_TEST_CASE_BODY(check_reqs__required_configs__one_fail)495 ATF_TEST_CASE_BODY(check_reqs__required_configs__one_fail)
496 {
497     const engine::metadata md = engine::metadata_builder()
498         .add_required_config("unprivileged_user")
499         .build();
500 
501     config::tree user_config = engine::default_config();
502     user_config.set_string("test_suites.suite.aaa", "value1");
503     user_config.set_string("test_suites.suite.my-var", "value2");
504     user_config.set_string("test_suites.suite.zzz", "value3");
505     ATF_REQUIRE_MATCH("Required configuration property 'unprivileged_user' not "
506                       "defined",
507                       engine::check_reqs(md, user_config, "suite"));
508 }
509 
510 
511 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__many_ok);
ATF_TEST_CASE_BODY(check_reqs__required_configs__many_ok)512 ATF_TEST_CASE_BODY(check_reqs__required_configs__many_ok)
513 {
514     const engine::metadata md = engine::metadata_builder()
515         .add_required_config("foo")
516         .add_required_config("bar")
517         .add_required_config("baz")
518         .build();
519 
520     config::tree user_config = engine::default_config();
521     user_config.set_string("test_suites.suite.aaa", "value1");
522     user_config.set_string("test_suites.suite.foo", "value2");
523     user_config.set_string("test_suites.suite.bar", "value3");
524     user_config.set_string("test_suites.suite.baz", "value4");
525     user_config.set_string("test_suites.suite.zzz", "value5");
526     ATF_REQUIRE(engine::check_reqs(md, user_config, "suite").empty());
527 }
528 
529 
530 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__many_fail);
ATF_TEST_CASE_BODY(check_reqs__required_configs__many_fail)531 ATF_TEST_CASE_BODY(check_reqs__required_configs__many_fail)
532 {
533     const engine::metadata md = engine::metadata_builder()
534         .add_required_config("foo")
535         .add_required_config("bar")
536         .add_required_config("baz")
537         .build();
538 
539     config::tree user_config = engine::default_config();
540     user_config.set_string("test_suites.suite.aaa", "value1");
541     user_config.set_string("test_suites.suite.foo", "value2");
542     user_config.set_string("test_suites.suite.zzz", "value3");
543     ATF_REQUIRE_MATCH("Required configuration property 'bar' not defined",
544                       engine::check_reqs(md, user_config, "suite"));
545 }
546 
547 
548 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__special);
ATF_TEST_CASE_BODY(check_reqs__required_configs__special)549 ATF_TEST_CASE_BODY(check_reqs__required_configs__special)
550 {
551     const engine::metadata md = engine::metadata_builder()
552         .add_required_config("unprivileged-user")
553         .build();
554 
555     config::tree user_config = engine::default_config();
556     ATF_REQUIRE_MATCH("Required configuration property 'unprivileged-user' "
557                       "not defined",
558                       engine::check_reqs(md, user_config, ""));
559     user_config.set< engine::user_node >(
560         "unprivileged_user", passwd::user("foo", 1, 2));
561     ATF_REQUIRE(engine::check_reqs(md, user_config, "foo").empty());
562 }
563 
564 
565 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__root__ok);
ATF_TEST_CASE_BODY(check_reqs__required_user__root__ok)566 ATF_TEST_CASE_BODY(check_reqs__required_user__root__ok)
567 {
568     const engine::metadata md = engine::metadata_builder()
569         .set_required_user("root")
570         .build();
571 
572     config::tree user_config = engine::default_config();
573     ATF_REQUIRE(!user_config.is_set("unprivileged_user"));
574 
575     passwd::set_current_user_for_testing(passwd::user("", 0, 1));
576     ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty());
577 }
578 
579 
580 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__root__fail);
ATF_TEST_CASE_BODY(check_reqs__required_user__root__fail)581 ATF_TEST_CASE_BODY(check_reqs__required_user__root__fail)
582 {
583     const engine::metadata md = engine::metadata_builder()
584         .set_required_user("root")
585         .build();
586 
587     passwd::set_current_user_for_testing(passwd::user("", 123, 1));
588     ATF_REQUIRE_MATCH("Requires root privileges",
589                       engine::check_reqs(md, engine::empty_config(), ""));
590 }
591 
592 
593 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__unprivileged__same);
ATF_TEST_CASE_BODY(check_reqs__required_user__unprivileged__same)594 ATF_TEST_CASE_BODY(check_reqs__required_user__unprivileged__same)
595 {
596     const engine::metadata md = engine::metadata_builder()
597         .set_required_user("unprivileged")
598         .build();
599 
600     config::tree user_config = engine::default_config();
601     ATF_REQUIRE(!user_config.is_set("unprivileged_user"));
602 
603     passwd::set_current_user_for_testing(passwd::user("", 123, 1));
604     ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty());
605 }
606 
607 
608 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__unprivileged__ok);
ATF_TEST_CASE_BODY(check_reqs__required_user__unprivileged__ok)609 ATF_TEST_CASE_BODY(check_reqs__required_user__unprivileged__ok)
610 {
611     const engine::metadata md = engine::metadata_builder()
612         .set_required_user("unprivileged")
613         .build();
614 
615     config::tree user_config = engine::default_config();
616     user_config.set< engine::user_node >(
617         "unprivileged_user", passwd::user("", 123, 1));
618 
619     passwd::set_current_user_for_testing(passwd::user("", 0, 1));
620     ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty());
621 }
622 
623 
624 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__unprivileged__fail);
ATF_TEST_CASE_BODY(check_reqs__required_user__unprivileged__fail)625 ATF_TEST_CASE_BODY(check_reqs__required_user__unprivileged__fail)
626 {
627     const engine::metadata md = engine::metadata_builder()
628         .set_required_user("unprivileged")
629         .build();
630 
631     config::tree user_config = engine::default_config();
632     ATF_REQUIRE(!user_config.is_set("unprivileged_user"));
633 
634     passwd::set_current_user_for_testing(passwd::user("", 0, 1));
635     ATF_REQUIRE_MATCH("Requires.*unprivileged.*unprivileged-user",
636                       engine::check_reqs(md, user_config, ""));
637 }
638 
639 
640 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_files__ok);
ATF_TEST_CASE_BODY(check_reqs__required_files__ok)641 ATF_TEST_CASE_BODY(check_reqs__required_files__ok)
642 {
643     const engine::metadata md = engine::metadata_builder()
644         .add_required_file(fs::current_path() / "test-file")
645         .build();
646 
647     atf::utils::create_file("test-file", "");
648 
649     ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "").empty());
650 }
651 
652 
653 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_files__fail);
ATF_TEST_CASE_BODY(check_reqs__required_files__fail)654 ATF_TEST_CASE_BODY(check_reqs__required_files__fail)
655 {
656     const engine::metadata md = engine::metadata_builder()
657         .add_required_file(fs::path("/non-existent/file"))
658         .build();
659 
660     ATF_REQUIRE_MATCH("'/non-existent/file' not found$",
661                       engine::check_reqs(md, engine::empty_config(), ""));
662 }
663 
664 
665 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_memory__ok);
ATF_TEST_CASE_BODY(check_reqs__required_memory__ok)666 ATF_TEST_CASE_BODY(check_reqs__required_memory__ok)
667 {
668     const engine::metadata md = engine::metadata_builder()
669         .set_required_memory(units::bytes::parse("1m"))
670         .build();
671 
672     ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "").empty());
673 }
674 
675 
676 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_memory__fail);
ATF_TEST_CASE_BODY(check_reqs__required_memory__fail)677 ATF_TEST_CASE_BODY(check_reqs__required_memory__fail)
678 {
679     const engine::metadata md = engine::metadata_builder()
680         .set_required_memory(units::bytes::parse("100t"))
681         .build();
682 
683     if (utils::physical_memory() == 0)
684         skip("Don't know how to query the amount of physical memory");
685     ATF_REQUIRE_MATCH("Requires 100.00T .*memory",
686                       engine::check_reqs(md, engine::empty_config(), ""));
687 }
688 
689 
690 ATF_TEST_CASE(check_reqs__required_programs__ok);
ATF_TEST_CASE_HEAD(check_reqs__required_programs__ok)691 ATF_TEST_CASE_HEAD(check_reqs__required_programs__ok)
692 {
693     set_md_var("require.progs", "/bin/ls /bin/mv");
694 }
ATF_TEST_CASE_BODY(check_reqs__required_programs__ok)695 ATF_TEST_CASE_BODY(check_reqs__required_programs__ok)
696 {
697     const engine::metadata md = engine::metadata_builder()
698         .add_required_program(fs::path("/bin/ls"))
699         .add_required_program(fs::path("foo"))
700         .add_required_program(fs::path("/bin/mv"))
701         .build();
702 
703     fs::mkdir(fs::path("bin"), 0755);
704     atf::utils::create_file("bin/foo", "");
705     utils::setenv("PATH", (fs::current_path() / "bin").str());
706 
707     ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "").empty());
708 }
709 
710 
711 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_programs__fail_absolute);
ATF_TEST_CASE_BODY(check_reqs__required_programs__fail_absolute)712 ATF_TEST_CASE_BODY(check_reqs__required_programs__fail_absolute)
713 {
714     const engine::metadata md = engine::metadata_builder()
715         .add_required_program(fs::path("/non-existent/program"))
716         .build();
717 
718     ATF_REQUIRE_MATCH("'/non-existent/program' not found$",
719                       engine::check_reqs(md, engine::empty_config(), ""));
720 }
721 
722 
723 ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_programs__fail_relative);
ATF_TEST_CASE_BODY(check_reqs__required_programs__fail_relative)724 ATF_TEST_CASE_BODY(check_reqs__required_programs__fail_relative)
725 {
726     const engine::metadata md = engine::metadata_builder()
727         .add_required_program(fs::path("foo"))
728         .add_required_program(fs::path("bar"))
729         .build();
730 
731     fs::mkdir(fs::path("bin"), 0755);
732     atf::utils::create_file("bin/foo", "");
733     utils::setenv("PATH", (fs::current_path() / "bin").str());
734 
735     ATF_REQUIRE_MATCH("'bar' not found in PATH$",
736                       engine::check_reqs(md, engine::empty_config(), ""));
737 }
738 
739 
ATF_INIT_TEST_CASES(tcs)740 ATF_INIT_TEST_CASES(tcs)
741 {
742     ATF_ADD_TEST_CASE(tcs, defaults);
743     ATF_ADD_TEST_CASE(tcs, add);
744     ATF_ADD_TEST_CASE(tcs, copy);
745     ATF_ADD_TEST_CASE(tcs, override_all_with_setters);
746     ATF_ADD_TEST_CASE(tcs, override_all_with_set_string);
747 
748     ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__empty);
749     ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__copy);
750     ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__equal);
751     ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__different);
752 
753     ATF_ADD_TEST_CASE(tcs, output__defaults);
754     ATF_ADD_TEST_CASE(tcs, output__some_values);
755 
756     // TODO(jmmv): Add tests for error conditions (invalid keys and invalid
757     // values).
758 
759     ATF_ADD_TEST_CASE(tcs, check_reqs__none);
760     ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_architectures__one_ok);
761     ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_architectures__one_fail);
762     ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_architectures__many_ok);
763     ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_architectures__many_fail);
764     ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_platforms__one_ok);
765     ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_platforms__one_fail);
766     ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_platforms__many_ok);
767     ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_platforms__many_fail);
768     ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__one_ok);
769     ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__one_fail);
770     ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__many_ok);
771     ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__many_fail);
772     ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__special);
773     ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__root__ok);
774     ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__root__fail);
775     ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__unprivileged__same);
776     ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__unprivileged__ok);
777     ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__unprivileged__fail);
778     ATF_ADD_TEST_CASE(tcs, check_reqs__required_files__ok);
779     ATF_ADD_TEST_CASE(tcs, check_reqs__required_files__fail);
780     ATF_ADD_TEST_CASE(tcs, check_reqs__required_memory__ok);
781     ATF_ADD_TEST_CASE(tcs, check_reqs__required_memory__fail);
782     ATF_ADD_TEST_CASE(tcs, check_reqs__required_programs__ok);
783     ATF_ADD_TEST_CASE(tcs, check_reqs__required_programs__fail_absolute);
784     ATF_ADD_TEST_CASE(tcs, check_reqs__required_programs__fail_relative);
785 }
786