Home | History | Annotate | Line # | Download | only in tools
      1 //
      2 // Automated Testing Framework (atf)
      3 //
      4 // Copyright (c) 2010 The NetBSD Foundation, Inc.
      5 // All rights reserved.
      6 //
      7 // Redistribution and use in source and binary forms, with or without
      8 // modification, are permitted provided that the following conditions
      9 // are met:
     10 // 1. Redistributions of source code must retain the above copyright
     11 //    notice, this list of conditions and the following disclaimer.
     12 // 2. Redistributions in binary form must reproduce the above copyright
     13 //    notice, this list of conditions and the following disclaimer in the
     14 //    documentation and/or other materials provided with the distribution.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
     17 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     18 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
     21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     23 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     26 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 //
     29 
     30 #include <atf-c++.hpp>
     31 
     32 #include "config.hpp"
     33 #include "config_file.hpp"
     34 #include "env.hpp"
     35 #include "test_helpers.hpp"
     36 
     37 namespace impl = tools::config_file;
     38 namespace detail = tools::config_file::detail;
     39 
     40 namespace {
     41 
     42 typedef std::map< std::string, std::string > vars_map;
     43 
     44 } // anonymous namespace
     45 
     46 namespace atf {
     47 namespace config {
     48 
     49 void __reinit(void);
     50 
     51 }  // namespace config
     52 }  // namespace atf
     53 
     54 // -------------------------------------------------------------------------
     55 // Tests for the "config" parser.
     56 // -------------------------------------------------------------------------
     57 
     58 class config_reader : protected detail::atf_config_reader {
     59     void
     60     got_var(const std::string& name, const std::string& val)
     61     {
     62         m_calls.push_back("got_var(" + name + ", " + val + ")");
     63     }
     64 
     65     void
     66     got_eof(void)
     67     {
     68         m_calls.push_back("got_eof()");
     69     }
     70 
     71 public:
     72     config_reader(std::istream& is) :
     73         detail::atf_config_reader(is)
     74     {
     75     }
     76 
     77     void
     78     read(void)
     79     {
     80         atf_config_reader::read();
     81     }
     82 
     83     std::vector< std::string > m_calls;
     84 };
     85 
     86 ATF_TEST_CASE_WITHOUT_HEAD(config_1);
     87 ATF_TEST_CASE_BODY(config_1)
     88 {
     89     const char* input =
     90         "Content-Type: application/X-atf-config; version=\"1\"\n"
     91         "\n"
     92     ;
     93 
     94     const char* exp_calls[] = {
     95         "got_eof()",
     96         NULL
     97     };
     98 
     99     const char* exp_errors[] = {
    100         NULL
    101     };
    102 
    103     do_parser_test< config_reader >(input, exp_calls, exp_errors);
    104 }
    105 
    106 ATF_TEST_CASE_WITHOUT_HEAD(config_2);
    107 ATF_TEST_CASE_BODY(config_2)
    108 {
    109     const char* input =
    110         "Content-Type: application/X-atf-config; version=\"1\"\n"
    111         "\n"
    112         "# This is a comment on a line of its own.\n"
    113         "# And this is another one.\n"
    114         "\n"
    115         "	    # Another after some whitespace.\n"
    116         "\n"
    117         "# The last one after an empty line.\n"
    118     ;
    119 
    120     const char* exp_calls[] = {
    121         "got_eof()",
    122         NULL
    123     };
    124 
    125     const char* exp_errors[] = {
    126         NULL
    127     };
    128 
    129     do_parser_test< config_reader >(input, exp_calls, exp_errors);
    130 }
    131 
    132 ATF_TEST_CASE_WITHOUT_HEAD(config_3);
    133 ATF_TEST_CASE_BODY(config_3)
    134 {
    135     const char* input =
    136         "Content-Type: application/X-atf-config; version=\"1\"\n"
    137         "\n"
    138         "var1=value1\n"
    139         "var2 = value2\n"
    140         "var3	=	value3\n"
    141         "var4	    =	    value4\n"
    142         "\n"
    143         "var5=value5\n"
    144         "    var6=value6\n"
    145         "\n"
    146         "var7 = \"This is a long value.\"\n"
    147         "var8 = \"Single-word\"\n"
    148         "var9 = \"    Single-word	\"\n"
    149         "var10 = Single-word\n"
    150     ;
    151 
    152     const char* exp_calls[] = {
    153         "got_var(var1, value1)",
    154         "got_var(var2, value2)",
    155         "got_var(var3, value3)",
    156         "got_var(var4, value4)",
    157         "got_var(var5, value5)",
    158         "got_var(var6, value6)",
    159         "got_var(var7, This is a long value.)",
    160         "got_var(var8, Single-word)",
    161         "got_var(var9,     Single-word	)",
    162         "got_var(var10, Single-word)",
    163         "got_eof()",
    164         NULL
    165     };
    166 
    167     const char* exp_errors[] = {
    168         NULL
    169     };
    170 
    171     do_parser_test< config_reader >(input, exp_calls, exp_errors);
    172 }
    173 
    174 ATF_TEST_CASE_WITHOUT_HEAD(config_4);
    175 ATF_TEST_CASE_BODY(config_4)
    176 {
    177     const char* input =
    178         "Content-Type: application/X-atf-config; version=\"1\"\n"
    179         "\n"
    180         "foo = bar # A comment.\n"
    181     ;
    182 
    183     const char* exp_calls[] = {
    184         "got_var(foo, bar)",
    185         "got_eof()",
    186         NULL
    187     };
    188 
    189     const char* exp_errors[] = {
    190         NULL
    191     };
    192 
    193     do_parser_test< config_reader >(input, exp_calls, exp_errors);
    194 }
    195 
    196 ATF_TEST_CASE_WITHOUT_HEAD(config_50);
    197 ATF_TEST_CASE_BODY(config_50)
    198 {
    199     const char* input =
    200         "Content-Type: application/X-atf-config; version=\"1\"\n"
    201         "\n"
    202         "foo\n"
    203     ;
    204 
    205     const char* exp_calls[] = {
    206         NULL
    207     };
    208 
    209     const char* exp_errors[] = {
    210         "3: Unexpected token `<<NEWLINE>>'; expected equal sign",
    211         NULL
    212     };
    213 
    214     do_parser_test< config_reader >(input, exp_calls, exp_errors);
    215 }
    216 
    217 ATF_TEST_CASE_WITHOUT_HEAD(config_51);
    218 ATF_TEST_CASE_BODY(config_51)
    219 {
    220     const char* input =
    221         "Content-Type: application/X-atf-config; version=\"1\"\n"
    222         "\n"
    223         "foo bar\n"
    224         "baz\n"
    225     ;
    226 
    227     const char* exp_calls[] = {
    228         NULL
    229     };
    230 
    231     const char* exp_errors[] = {
    232         "3: Unexpected token `bar'; expected equal sign",
    233         "4: Unexpected token `<<NEWLINE>>'; expected equal sign",
    234         NULL
    235     };
    236 
    237     do_parser_test< config_reader >(input, exp_calls, exp_errors);
    238 }
    239 
    240 ATF_TEST_CASE_WITHOUT_HEAD(config_52);
    241 ATF_TEST_CASE_BODY(config_52)
    242 {
    243     const char* input =
    244         "Content-Type: application/X-atf-config; version=\"1\"\n"
    245         "\n"
    246         "foo =\n"
    247         "bar = # A comment.\n"
    248     ;
    249 
    250     const char* exp_calls[] = {
    251         NULL
    252     };
    253 
    254     const char* exp_errors[] = {
    255         "3: Unexpected token `<<NEWLINE>>'; expected word or quoted string",
    256         "4: Unexpected token `#'; expected word or quoted string",
    257         NULL
    258     };
    259 
    260     do_parser_test< config_reader >(input, exp_calls, exp_errors);
    261 }
    262 
    263 ATF_TEST_CASE_WITHOUT_HEAD(config_53);
    264 ATF_TEST_CASE_BODY(config_53)
    265 {
    266     const char* input =
    267         "Content-Type: application/X-atf-config; version=\"1\"\n"
    268         "\n"
    269         "foo = \"Correct value\" # With comment.\n"
    270         "\n"
    271         "bar = # A comment.\n"
    272         "\n"
    273         "baz = \"Last variable\"\n"
    274         "\n"
    275         "# End of file.\n"
    276     ;
    277 
    278     const char* exp_calls[] = {
    279         "got_var(foo, Correct value)",
    280         NULL
    281     };
    282 
    283     const char* exp_errors[] = {
    284         "5: Unexpected token `#'; expected word or quoted string",
    285         NULL
    286     };
    287 
    288     do_parser_test< config_reader >(input, exp_calls, exp_errors);
    289 }
    290 
    291 ATF_TEST_CASE_WITHOUT_HEAD(config_54);
    292 ATF_TEST_CASE_BODY(config_54)
    293 {
    294     const char* input =
    295         "Content-Type: application/X-atf-config; version=\"1\"\n"
    296         "\n"
    297         "foo = \"\n"
    298         "bar = \"text\n"
    299         "baz = \"te\\\"xt\n"
    300         "last = \"\\\"\n"
    301     ;
    302 
    303     const char* exp_calls[] = {
    304         NULL
    305     };
    306 
    307     const char* exp_errors[] = {
    308         "3: Missing double quotes before end of line",
    309         "4: Missing double quotes before end of line",
    310         "5: Missing double quotes before end of line",
    311         "6: Missing double quotes before end of line",
    312         NULL
    313     };
    314 
    315     do_parser_test< config_reader >(input, exp_calls, exp_errors);
    316 }
    317 
    318 // -------------------------------------------------------------------------
    319 // Tests for the free functions.
    320 // -------------------------------------------------------------------------
    321 
    322 ATF_TEST_CASE(merge_configs_both_empty);
    323 ATF_TEST_CASE_HEAD(merge_configs_both_empty) {}
    324 ATF_TEST_CASE_BODY(merge_configs_both_empty) {
    325     vars_map lower, upper;
    326 
    327     ATF_REQUIRE(impl::merge_configs(lower, upper).empty());
    328 }
    329 
    330 ATF_TEST_CASE(merge_configs_lower_empty);
    331 ATF_TEST_CASE_HEAD(merge_configs_lower_empty) {}
    332 ATF_TEST_CASE_BODY(merge_configs_lower_empty) {
    333     vars_map lower, upper;
    334     upper["var"] = "value";
    335 
    336     vars_map merged = impl::merge_configs(lower, upper);
    337     ATF_REQUIRE_EQ("value", merged["var"]);
    338 }
    339 
    340 ATF_TEST_CASE(merge_configs_upper_empty);
    341 ATF_TEST_CASE_HEAD(merge_configs_upper_empty) {}
    342 ATF_TEST_CASE_BODY(merge_configs_upper_empty) {
    343     vars_map lower, upper;
    344     lower["var"] = "value";
    345 
    346     vars_map merged = impl::merge_configs(lower, upper);
    347     ATF_REQUIRE_EQ("value", merged["var"]);
    348 }
    349 
    350 ATF_TEST_CASE(merge_configs_mixed);
    351 ATF_TEST_CASE_HEAD(merge_configs_mixed) {}
    352 ATF_TEST_CASE_BODY(merge_configs_mixed) {
    353     vars_map lower, upper;
    354     lower["var1"] = "value1";
    355     lower["var2"] = "value2-l";
    356     upper["var2"] = "value2-u";
    357     upper["var3"] = "value3";
    358 
    359     vars_map merged = impl::merge_configs(lower, upper);
    360     ATF_REQUIRE_EQ("value1", merged["var1"]);
    361     ATF_REQUIRE_EQ("value2-u", merged["var2"]);
    362     ATF_REQUIRE_EQ("value3", merged["var3"]);
    363 }
    364 
    365 ATF_TEST_CASE(read_config_files_none);
    366 ATF_TEST_CASE_HEAD(read_config_files_none) {}
    367 ATF_TEST_CASE_BODY(read_config_files_none) {
    368     tools::env::set("ATF_CONFDIR", ".");
    369     atf::config::__reinit();
    370     ATF_REQUIRE(vars_map() == impl::read_config_files("test-suite"));
    371 }
    372 
    373 // -------------------------------------------------------------------------
    374 // Main.
    375 // -------------------------------------------------------------------------
    376 
    377 ATF_INIT_TEST_CASES(tcs)
    378 {
    379     ATF_ADD_TEST_CASE(tcs, config_1);
    380     ATF_ADD_TEST_CASE(tcs, config_2);
    381     ATF_ADD_TEST_CASE(tcs, config_3);
    382     ATF_ADD_TEST_CASE(tcs, config_4);
    383     ATF_ADD_TEST_CASE(tcs, config_50);
    384     ATF_ADD_TEST_CASE(tcs, config_51);
    385     ATF_ADD_TEST_CASE(tcs, config_52);
    386     ATF_ADD_TEST_CASE(tcs, config_53);
    387     ATF_ADD_TEST_CASE(tcs, config_54);
    388 
    389     ATF_ADD_TEST_CASE(tcs, merge_configs_both_empty);
    390     ATF_ADD_TEST_CASE(tcs, merge_configs_lower_empty);
    391     ATF_ADD_TEST_CASE(tcs, merge_configs_upper_empty);
    392     ATF_ADD_TEST_CASE(tcs, merge_configs_mixed);
    393 
    394     ATF_ADD_TEST_CASE(tcs, read_config_files_none);
    395 }
    396