Home | History | Annotate | Line # | Download | only in engine
metadata_test.cpp revision 1.1.1.1
      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);
     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);
     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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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='1024', "
    342         "required_programs='', required_user='', timeout='300'}",
    343         str.str());
    344 }
    345 
    346 
    347 ATF_TEST_CASE_WITHOUT_HEAD(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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    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);
    691 ATF_TEST_CASE_HEAD(check_reqs__required_programs__ok)
    692 {
    693     set_md_var("require.progs", "/bin/ls /bin/mv");
    694 }
    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);
    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);
    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 
    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