2 // Automated Testing Framework (atf)
4 // Copyright (c) 2009 The NetBSD Foundation, Inc.
5 // All rights reserved.
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
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.
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.
31 #include <sys/types.h>
39 #include <atf-c++.hpp>
41 #include "atffile.hpp"
42 #include "exceptions.hpp"
43 #include "test_helpers.hpp"
45 namespace detail
= tools::detail
;
47 // ------------------------------------------------------------------------
48 // Auxiliary functions.
49 // ------------------------------------------------------------------------
53 typedef std::map
< std::string
, std::string
> vars_map
;
56 std::auto_ptr
< std::ofstream
>
59 std::auto_ptr
< std::ofstream
> os(new std::ofstream("Atffile"));
62 (*os
) << "Content-Type: application/X-atf-atffile; version=\"1\"\n\n";
68 touch_exec(const char* name
)
70 std::ofstream
os(name
);
73 ATF_REQUIRE(::chmod(name
, S_IRWXU
) != -1);
78 is_in(const std::string
& value
, const std::vector
< std::string
>& v
)
80 return std::find(v
.begin(), v
.end(), value
) != v
.end();
83 } // anonymous namespace
85 // ------------------------------------------------------------------------
86 // Tests cases for the "atffile" parser.
87 // ------------------------------------------------------------------------
89 class atffile_reader
: protected detail::atf_atffile_reader
{
91 got_conf(const std::string
& name
, const std::string
& val
)
93 m_calls
.push_back("got_conf(" + name
+ ", " + val
+ ")");
97 got_prop(const std::string
& name
, const std::string
& val
)
99 m_calls
.push_back("got_prop(" + name
+ ", " + val
+ ")");
103 got_tp(const std::string
& name
, bool isglob
)
105 m_calls
.push_back("got_tp(" + name
+ ", " + (isglob
? "true" : "false")
112 m_calls
.push_back("got_eof()");
116 atffile_reader(std::istream
& is
) :
117 detail::atf_atffile_reader(is
)
124 atf_atffile_reader::read();
127 std::vector
< std::string
> m_calls
;
130 ATF_TEST_CASE_WITHOUT_HEAD(atffile_1
);
131 ATF_TEST_CASE_BODY(atffile_1
)
134 "Content-Type: application/X-atf-atffile; version=\"1\"\n"
138 const char* exp_calls
[] = {
143 const char* exp_errors
[] = {
147 do_parser_test
< atffile_reader
>(input
, exp_calls
, exp_errors
);
150 ATF_TEST_CASE_WITHOUT_HEAD(atffile_2
);
151 ATF_TEST_CASE_BODY(atffile_2
)
154 "Content-Type: application/X-atf-atffile; version=\"1\"\n"
156 "# This is a comment on a line of its own.\n"
157 "# And this is another one.\n"
159 " # Another after some whitespace.\n"
161 "# The last one after an empty line.\n"
164 const char* exp_calls
[] = {
169 const char* exp_errors
[] = {
173 do_parser_test
< atffile_reader
>(input
, exp_calls
, exp_errors
);
176 ATF_TEST_CASE_WITHOUT_HEAD(atffile_3
);
177 ATF_TEST_CASE_BODY(atffile_3
)
180 "Content-Type: application/X-atf-atffile; version=\"1\"\n"
182 "conf: var1=value1\n"
183 "conf: var2 = value2\n"
184 "conf: var3 = value3\n"
185 "conf: var4 = value4\n"
188 " conf:var6=value6\n"
190 "conf: var7 = \"This is a long value.\"\n"
191 "conf: var8 = \"Single-word\"\n"
192 "conf: var9 = \" Single-word \"\n"
193 "conf: var10 = Single-word\n"
196 const char* exp_calls
[] = {
197 "got_conf(var1, value1)",
198 "got_conf(var2, value2)",
199 "got_conf(var3, value3)",
200 "got_conf(var4, value4)",
201 "got_conf(var5, value5)",
202 "got_conf(var6, value6)",
203 "got_conf(var7, This is a long value.)",
204 "got_conf(var8, Single-word)",
205 "got_conf(var9, Single-word )",
206 "got_conf(var10, Single-word)",
211 const char* exp_errors
[] = {
215 do_parser_test
< atffile_reader
>(input
, exp_calls
, exp_errors
);
218 ATF_TEST_CASE_WITHOUT_HEAD(atffile_4
);
219 ATF_TEST_CASE_BODY(atffile_4
)
222 "Content-Type: application/X-atf-atffile; version=\"1\"\n"
224 "prop: var1=value1\n"
225 "prop: var2 = value2\n"
226 "prop: var3 = value3\n"
227 "prop: var4 = value4\n"
230 " prop:var6=value6\n"
232 "prop: var7 = \"This is a long value.\"\n"
233 "prop: var8 = \"Single-word\"\n"
234 "prop: var9 = \" Single-word \"\n"
235 "prop: var10 = Single-word\n"
238 const char* exp_calls
[] = {
239 "got_prop(var1, value1)",
240 "got_prop(var2, value2)",
241 "got_prop(var3, value3)",
242 "got_prop(var4, value4)",
243 "got_prop(var5, value5)",
244 "got_prop(var6, value6)",
245 "got_prop(var7, This is a long value.)",
246 "got_prop(var8, Single-word)",
247 "got_prop(var9, Single-word )",
248 "got_prop(var10, Single-word)",
253 const char* exp_errors
[] = {
257 do_parser_test
< atffile_reader
>(input
, exp_calls
, exp_errors
);
260 ATF_TEST_CASE_WITHOUT_HEAD(atffile_5
);
261 ATF_TEST_CASE_BODY(atffile_5
)
264 "Content-Type: application/X-atf-atffile; version=\"1\"\n"
271 "tp: \"name with spaces\"\n"
272 "tp: \"single-word\"\n"
276 "tp-glob: foo*?bar\n"
277 "tp-glob: foo*?bar\n"
278 "tp-glob: foo*?bar\n"
279 "tp-glob: foo*?bar\n"
280 "tp-glob: \"glob * with ? spaces\"\n"
281 "tp-glob: \"single-*-word\"\n"
282 "tp-glob: single-*-word\n"
285 const char* exp_calls
[] = {
286 "got_tp(foo, false)",
287 "got_tp(foo, false)",
288 "got_tp(foo, false)",
289 "got_tp(foo, false)",
290 "got_tp(foo, false)",
291 "got_tp(name with spaces, false)",
292 "got_tp(single-word, false)",
293 "got_tp(single-word, false)",
294 "got_tp(foo*?bar, true)",
295 "got_tp(foo*?bar, true)",
296 "got_tp(foo*?bar, true)",
297 "got_tp(foo*?bar, true)",
298 "got_tp(foo*?bar, true)",
299 "got_tp(glob * with ? spaces, true)",
300 "got_tp(single-*-word, true)",
301 "got_tp(single-*-word, true)",
306 const char* exp_errors
[] = {
310 do_parser_test
< atffile_reader
>(input
, exp_calls
, exp_errors
);
313 ATF_TEST_CASE_WITHOUT_HEAD(atffile_6
);
314 ATF_TEST_CASE_BODY(atffile_6
)
317 "Content-Type: application/X-atf-atffile; version=\"1\"\n"
319 "prop: foo = bar # A comment.\n"
320 "conf: foo = bar # A comment.\n"
321 "tp: foo # A comment.\n"
322 "tp-glob: foo # A comment.\n"
325 const char* exp_calls
[] = {
326 "got_prop(foo, bar)",
327 "got_conf(foo, bar)",
328 "got_tp(foo, false)",
334 const char* exp_errors
[] = {
338 do_parser_test
< atffile_reader
>(input
, exp_calls
, exp_errors
);
341 ATF_TEST_CASE_WITHOUT_HEAD(atffile_50
);
342 ATF_TEST_CASE_BODY(atffile_50
)
345 "Content-Type: application/X-atf-atffile; version=\"1\"\n"
350 const char* exp_calls
[] = {
354 // NO_CHECK_STYLE_BEGIN
355 const char* exp_errors
[] = {
356 "3: Unexpected token `foo'; expected conf, #, prop, tp, tp-glob, a new line or eof",
359 // NO_CHECK_STYLE_END
361 do_parser_test
< atffile_reader
>(input
, exp_calls
, exp_errors
);
364 ATF_TEST_CASE_WITHOUT_HEAD(atffile_51
);
365 ATF_TEST_CASE_BODY(atffile_51
)
368 "Content-Type: application/X-atf-atffile; version=\"1\"\n"
374 const char* exp_calls
[] = {
378 // NO_CHECK_STYLE_BEGIN
379 const char* exp_errors
[] = {
380 "3: Unexpected token `foo'; expected conf, #, prop, tp, tp-glob, a new line or eof",
381 "4: Unexpected token `baz'; expected conf, #, prop, tp, tp-glob, a new line or eof",
384 // NO_CHECK_STYLE_END
386 do_parser_test
< atffile_reader
>(input
, exp_calls
, exp_errors
);
389 ATF_TEST_CASE_WITHOUT_HEAD(atffile_52
);
390 ATF_TEST_CASE_BODY(atffile_52
)
393 "Content-Type: application/X-atf-atffile; version=\"1\"\n"
398 "conf: bar = # A comment.\n"
403 "prop: bar = # A comment.\n"
411 "tp-glob: # A comment.\n"
414 const char* exp_calls
[] = {
418 const char* exp_errors
[] = {
419 "3: Unexpected token `<<NEWLINE>>'; expected `:'",
420 "4: Unexpected token `<<NEWLINE>>'; expected variable name",
421 "5: Unexpected token `<<NEWLINE>>'; expected word or quoted string",
422 "6: Unexpected token `#'; expected word or quoted string",
423 "8: Unexpected token `<<NEWLINE>>'; expected `:'",
424 "9: Unexpected token `<<NEWLINE>>'; expected property name",
425 "10: Unexpected token `<<NEWLINE>>'; expected word or quoted string",
426 "11: Unexpected token `#'; expected word or quoted string",
427 "13: Unexpected token `<<NEWLINE>>'; expected `:'",
428 "14: Unexpected token `<<NEWLINE>>'; expected word or quoted string",
429 "15: Unexpected token `#'; expected word or quoted string",
430 "17: Unexpected token `<<NEWLINE>>'; expected `:'",
431 "18: Unexpected token `<<NEWLINE>>'; expected word or quoted string",
432 "19: Unexpected token `#'; expected word or quoted string",
436 do_parser_test
< atffile_reader
>(input
, exp_calls
, exp_errors
);
439 ATF_TEST_CASE_WITHOUT_HEAD(atffile_53
);
440 ATF_TEST_CASE_BODY(atffile_53
)
443 "Content-Type: application/X-atf-atffile; version=\"1\"\n"
445 "prop: foo = \"Correct value\" # With comment.\n"
447 "prop: bar = # A comment.\n"
449 "prop: baz = \"Last variable\"\n"
454 const char* exp_calls
[] = {
455 "got_prop(foo, Correct value)",
459 const char* exp_errors
[] = {
460 "5: Unexpected token `#'; expected word or quoted string",
464 do_parser_test
< atffile_reader
>(input
, exp_calls
, exp_errors
);
467 ATF_TEST_CASE_WITHOUT_HEAD(atffile_54
);
468 ATF_TEST_CASE_BODY(atffile_54
)
471 "Content-Type: application/X-atf-atffile; version=\"1\"\n"
474 "prop: bar = \"text\n"
475 "prop: baz = \"te\\\"xt\n"
476 "prop: last = \"\\\"\n"
479 const char* exp_calls
[] = {
483 const char* exp_errors
[] = {
484 "3: Missing double quotes before end of line",
485 "4: Missing double quotes before end of line",
486 "5: Missing double quotes before end of line",
487 "6: Missing double quotes before end of line",
491 do_parser_test
< atffile_reader
>(input
, exp_calls
, exp_errors
);
494 // ------------------------------------------------------------------------
495 // Tests cases for the "atffile" class.
496 // ------------------------------------------------------------------------
498 ATF_TEST_CASE(atffile_getters
);
499 ATF_TEST_CASE_HEAD(atffile_getters
) {}
500 ATF_TEST_CASE_BODY(atffile_getters
) {
501 vars_map config_vars
;
502 config_vars
["config-var-1"] = "value 1";
504 std::vector
< std::string
> test_program_names
;
505 test_program_names
.push_back("test-program-1");
508 properties
["test-suite"] = "a test name";
510 const tools::atffile
atffile(config_vars
, test_program_names
, properties
);
511 ATF_REQUIRE(config_vars
== atffile
.conf());
512 ATF_REQUIRE(test_program_names
== atffile
.tps());
513 ATF_REQUIRE(properties
== atffile
.props());
516 // ------------------------------------------------------------------------
517 // Tests cases for the free functions.
518 // ------------------------------------------------------------------------
520 ATF_TEST_CASE_WITHOUT_HEAD(read_ok_simple
);
521 ATF_TEST_CASE_BODY(read_ok_simple
) {
522 std::auto_ptr
< std::ofstream
> os
= new_atffile();
523 (*os
) << "prop: test-suite = foo\n";
524 (*os
) << "tp: tp-1\n";
525 (*os
) << "conf: var1 = value1\n";
526 (*os
) << "tp: tp-2\n";
527 (*os
) << "tp: tp-3\n";
528 (*os
) << "prop: prop1 = propvalue1\n";
529 (*os
) << "conf: var2 = value2\n";
536 const tools::atffile atffile
= tools::read_atffile(
537 tools::fs::path("Atffile"));
538 ATF_REQUIRE_EQ(2, atffile
.conf().size());
539 ATF_REQUIRE_EQ("value1", atffile
.conf().find("var1")->second
);
540 ATF_REQUIRE_EQ("value2", atffile
.conf().find("var2")->second
);
541 ATF_REQUIRE_EQ(3, atffile
.tps().size());
542 ATF_REQUIRE(is_in("tp-1", atffile
.tps()));
543 ATF_REQUIRE(is_in("tp-2", atffile
.tps()));
544 ATF_REQUIRE(is_in("tp-3", atffile
.tps()));
545 ATF_REQUIRE_EQ(2, atffile
.props().size());
546 ATF_REQUIRE_EQ("foo", atffile
.props().find("test-suite")->second
);
547 ATF_REQUIRE_EQ("propvalue1", atffile
.props().find("prop1")->second
);
550 ATF_TEST_CASE_WITHOUT_HEAD(read_ok_some_globs
);
551 ATF_TEST_CASE_BODY(read_ok_some_globs
) {
552 std::auto_ptr
< std::ofstream
> os
= new_atffile();
553 (*os
) << "prop: test-suite = foo\n";
554 (*os
) << "tp: foo\n";
555 (*os
) << "tp-glob: *K*\n";
556 (*os
) << "tp: bar\n";
557 (*os
) << "tp-glob: t_*\n";
564 touch_exec("t_hello");
565 touch_exec("zzzt_hello");
567 const tools::atffile atffile
= tools::read_atffile(
568 tools::fs::path("Atffile"));
569 ATF_REQUIRE_EQ(5, atffile
.tps().size());
570 ATF_REQUIRE(is_in("foo", atffile
.tps()));
571 ATF_REQUIRE(is_in("bar", atffile
.tps()));
572 ATF_REQUIRE(is_in("aK", atffile
.tps()));
573 ATF_REQUIRE(is_in("KKKKK", atffile
.tps()));
574 ATF_REQUIRE(is_in("t_hello", atffile
.tps()));
577 ATF_TEST_CASE_WITHOUT_HEAD(read_missing_test_suite
);
578 ATF_TEST_CASE_BODY(read_missing_test_suite
) {
579 std::auto_ptr
< std::ofstream
> os
= new_atffile();
583 (void)tools::read_atffile(tools::fs::path("Atffile"));
584 ATF_FAIL("Missing property 'test-suite' did not raise an error");
585 } catch (const tools::not_found_error
< std::string
>& e
) {
586 ATF_REQUIRE_EQ("test-suite", e
.get_value());
590 ATF_TEST_CASE_WITHOUT_HEAD(read_missing_test_program
);
591 ATF_TEST_CASE_BODY(read_missing_test_program
) {
592 std::auto_ptr
< std::ofstream
> os
= new_atffile();
593 (*os
) << "tp: foo\n";
594 (*os
) << "tp: bar\n";
595 (*os
) << "tp: baz\n";
602 (void)tools::read_atffile(tools::fs::path("Atffile"));
603 ATF_FAIL("Missing file 'bar' did not raise an error");
604 } catch (const tools::not_found_error
< tools::fs::path
>& e
) {
605 ATF_REQUIRE_EQ("bar", e
.get_value().str());
609 // ------------------------------------------------------------------------
611 // ------------------------------------------------------------------------
613 ATF_INIT_TEST_CASES(tcs
)
615 // Add the test cases for the parser class.
616 ATF_ADD_TEST_CASE(tcs
, atffile_1
);
617 ATF_ADD_TEST_CASE(tcs
, atffile_2
);
618 ATF_ADD_TEST_CASE(tcs
, atffile_3
);
619 ATF_ADD_TEST_CASE(tcs
, atffile_4
);
620 ATF_ADD_TEST_CASE(tcs
, atffile_5
);
621 ATF_ADD_TEST_CASE(tcs
, atffile_6
);
622 ATF_ADD_TEST_CASE(tcs
, atffile_50
);
623 ATF_ADD_TEST_CASE(tcs
, atffile_51
);
624 ATF_ADD_TEST_CASE(tcs
, atffile_52
);
625 ATF_ADD_TEST_CASE(tcs
, atffile_53
);
626 ATF_ADD_TEST_CASE(tcs
, atffile_54
);
628 // Add the test cases for the atffile class.
629 ATF_ADD_TEST_CASE(tcs
, atffile_getters
);
631 // Add the test cases for the free functions.
632 ATF_ADD_TEST_CASE(tcs
, read_ok_simple
);
633 ATF_ADD_TEST_CASE(tcs
, read_ok_some_globs
);
634 ATF_ADD_TEST_CASE(tcs
, read_missing_test_suite
);
635 ATF_ADD_TEST_CASE(tcs
, read_missing_test_program
);