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