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 <fstream>
31 #include <iostream>
32
33 #include "atf-c++/macros.hpp"
34
35 #include "atf-c++/detail/parser.hpp"
36 #include "atf-c++/detail/test_helpers.hpp"
37 #include "atf-c++/detail/text.hpp"
38
39 #include "test-program.hpp"
40
41 namespace impl = atf::atf_run;
42 namespace detail = atf::atf_run::detail;
43
44 using atf::tests::vars_map;
45
46 // -------------------------------------------------------------------------
47 // Auxiliary functions.
48 // -------------------------------------------------------------------------
49
50 static
51 atf::fs::path
get_helper(const atf::tests::tc & tc,const char * name)52 get_helper(const atf::tests::tc& tc, const char* name)
53 {
54 return atf::fs::path(tc.get_config_var("srcdir")) / name;
55 }
56
57 static
58 void
check_property(const vars_map & props,const char * name,const char * value)59 check_property(const vars_map& props, const char* name, const char* value)
60 {
61 const vars_map::const_iterator iter = props.find(name);
62 ATF_REQUIRE(iter != props.end());
63 ATF_REQUIRE_EQ(value, (*iter).second);
64 }
65
66 static void
check_result(const char * exp_state,const int exp_value,const char * exp_reason,const impl::test_case_result & tcr)67 check_result(const char* exp_state, const int exp_value, const char* exp_reason,
68 const impl::test_case_result& tcr)
69 {
70 ATF_REQUIRE_EQ(exp_state, tcr.state());
71 ATF_REQUIRE_EQ(exp_value, tcr.value());
72 ATF_REQUIRE_EQ(exp_reason, tcr.reason());
73 }
74
75 static
76 void
write_test_case_result(const char * results_path,const std::string & contents)77 write_test_case_result(const char *results_path, const std::string& contents)
78 {
79 std::ofstream results_file(results_path);
80 ATF_REQUIRE(results_file);
81
82 results_file << contents;
83 }
84
85 static
86 void
print_indented(const std::string & str)87 print_indented(const std::string& str)
88 {
89 std::vector< std::string > ws = atf::text::split(str, "\n");
90 for (std::vector< std::string >::const_iterator iter = ws.begin();
91 iter != ws.end(); iter++)
92 std::cout << ">>" << *iter << "<<\n";
93 }
94
95 // XXX Should this string handling and verbosity level be part of the
96 // ATF_REQUIRE_EQ macro? It may be hard to predict sometimes that a
97 // string can have newlines in it, and so the error message generated
98 // at the moment will be bogus if there are some.
99 static
100 void
check_match(const atf::tests::tc & tc,const std::string & str,const std::string & exp)101 check_match(const atf::tests::tc& tc, const std::string& str,
102 const std::string& exp)
103 {
104 if (!atf::text::match(str, exp)) {
105 std::cout << "String match check failed.\n"
106 << "Adding >> and << to delimit the string boundaries "
107 "below.\n";
108 std::cout << "GOT:\n";
109 print_indented(str);
110 std::cout << "EXPECTED:\n";
111 print_indented(exp);
112 tc.fail("Constructed string differs from the expected one");
113 }
114 }
115
116 // -------------------------------------------------------------------------
117 // Tests for the "tp" reader.
118 // -------------------------------------------------------------------------
119
120 class tp_reader : protected detail::atf_tp_reader {
121 void
got_tc(const std::string & ident,const std::map<std::string,std::string> & md)122 got_tc(const std::string& ident,
123 const std::map< std::string, std::string >& md)
124 {
125 std::string call = "got_tc(" + ident + ", {";
126 for (std::map< std::string, std::string >::const_iterator iter =
127 md.begin(); iter != md.end(); iter++) {
128 if (iter != md.begin())
129 call += ", ";
130 call += (*iter).first + '=' + (*iter).second;
131 }
132 call += "})";
133 m_calls.push_back(call);
134 }
135
136 void
got_eof(void)137 got_eof(void)
138 {
139 m_calls.push_back("got_eof()");
140 }
141
142 public:
tp_reader(std::istream & is)143 tp_reader(std::istream& is) :
144 detail::atf_tp_reader(is)
145 {
146 }
147
148 void
read(void)149 read(void)
150 {
151 atf_tp_reader::read();
152 }
153
154 std::vector< std::string > m_calls;
155 };
156
157 ATF_TEST_CASE_WITHOUT_HEAD(tp_1);
ATF_TEST_CASE_BODY(tp_1)158 ATF_TEST_CASE_BODY(tp_1)
159 {
160 const char* input =
161 "Content-Type: application/X-atf-tp; version=\"1\"\n"
162 "\n"
163 "ident: test_case_1\n"
164 "\n"
165 "ident: test_case_2\n"
166 "\n"
167 "ident: test_case_3\n"
168 ;
169
170 const char* exp_calls[] = {
171 "got_tc(test_case_1, {ident=test_case_1})",
172 "got_tc(test_case_2, {ident=test_case_2})",
173 "got_tc(test_case_3, {ident=test_case_3})",
174 "got_eof()",
175 NULL
176 };
177
178 const char* exp_errors[] = {
179 NULL
180 };
181
182 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
183 }
184
185 ATF_TEST_CASE_WITHOUT_HEAD(tp_2);
ATF_TEST_CASE_BODY(tp_2)186 ATF_TEST_CASE_BODY(tp_2)
187 {
188 const char* input =
189 "Content-Type: application/X-atf-tp; version=\"1\"\n"
190 "\n"
191 "ident: test_case_1\n"
192 "descr: This is the description\n"
193 "timeout: 300\n"
194 "\n"
195 "ident: test_case_2\n"
196 "\n"
197 "ident: test_case_3\n"
198 "X-prop1: A custom property\n"
199 "descr: Third test case\n"
200 ;
201
202 // NO_CHECK_STYLE_BEGIN
203 const char* exp_calls[] = {
204 "got_tc(test_case_1, {descr=This is the description, ident=test_case_1, timeout=300})",
205 "got_tc(test_case_2, {ident=test_case_2})",
206 "got_tc(test_case_3, {X-prop1=A custom property, descr=Third test case, ident=test_case_3})",
207 "got_eof()",
208 NULL
209 };
210 // NO_CHECK_STYLE_END
211
212 const char* exp_errors[] = {
213 NULL
214 };
215
216 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
217 }
218
219 ATF_TEST_CASE_WITHOUT_HEAD(tp_3);
ATF_TEST_CASE_BODY(tp_3)220 ATF_TEST_CASE_BODY(tp_3)
221 {
222 const char* input =
223 "Content-Type: application/X-atf-tp; version=\"1\"\n"
224 "\n"
225 "ident: single_test\n"
226 "descr: Some description\n"
227 "timeout: 300\n"
228 "require.arch: thearch\n"
229 "require.config: foo-bar\n"
230 "require.files: /a/1 /b/2\n"
231 "require.machine: themachine\n"
232 "require.progs: /bin/cp mv\n"
233 "require.user: root\n"
234 ;
235
236 // NO_CHECK_STYLE_BEGIN
237 const char* exp_calls[] = {
238 "got_tc(single_test, {descr=Some description, ident=single_test, require.arch=thearch, require.config=foo-bar, require.files=/a/1 /b/2, require.machine=themachine, require.progs=/bin/cp mv, require.user=root, timeout=300})",
239 "got_eof()",
240 NULL
241 };
242 // NO_CHECK_STYLE_END
243
244 const char* exp_errors[] = {
245 NULL
246 };
247
248 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
249 }
250
251 ATF_TEST_CASE_WITHOUT_HEAD(tp_4);
ATF_TEST_CASE_BODY(tp_4)252 ATF_TEST_CASE_BODY(tp_4)
253 {
254 const char* input =
255 "Content-Type: application/X-atf-tp; version=\"1\"\n"
256 "\n"
257 "ident: single_test \n"
258 "descr: Some description \n"
259 ;
260
261 const char* exp_calls[] = {
262 "got_tc(single_test, {descr=Some description, ident=single_test})",
263 "got_eof()",
264 NULL
265 };
266
267 const char* exp_errors[] = {
268 NULL
269 };
270
271 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
272 }
273
274 ATF_TEST_CASE_WITHOUT_HEAD(tp_50);
ATF_TEST_CASE_BODY(tp_50)275 ATF_TEST_CASE_BODY(tp_50)
276 {
277 const char* input =
278 "Content-Type: application/X-atf-tp; version=\"1\"\n"
279 "\n"
280 ;
281
282 const char* exp_calls[] = {
283 NULL
284 };
285
286 const char* exp_errors[] = {
287 "3: Unexpected token `<<EOF>>'; expected property name",
288 NULL
289 };
290
291 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
292 }
293
294 ATF_TEST_CASE_WITHOUT_HEAD(tp_51);
ATF_TEST_CASE_BODY(tp_51)295 ATF_TEST_CASE_BODY(tp_51)
296 {
297 const char* input =
298 "Content-Type: application/X-atf-tp; version=\"1\"\n"
299 "\n"
300 "\n"
301 "\n"
302 "\n"
303 ;
304
305 const char* exp_calls[] = {
306 NULL
307 };
308
309 const char* exp_errors[] = {
310 "3: Unexpected token `<<NEWLINE>>'; expected property name",
311 NULL
312 };
313
314 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
315 }
316
317 ATF_TEST_CASE_WITHOUT_HEAD(tp_52);
ATF_TEST_CASE_BODY(tp_52)318 ATF_TEST_CASE_BODY(tp_52)
319 {
320 const char* input =
321 "Content-Type: application/X-atf-tp; version=\"1\"\n"
322 "\n"
323 "ident: test1\n"
324 "ident: test2\n"
325 ;
326
327 const char* exp_calls[] = {
328 "got_tc(test1, {ident=test1})",
329 "got_eof()",
330 NULL
331 };
332
333 const char* exp_errors[] = {
334 NULL
335 };
336
337 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
338 }
339
340 ATF_TEST_CASE_WITHOUT_HEAD(tp_53);
ATF_TEST_CASE_BODY(tp_53)341 ATF_TEST_CASE_BODY(tp_53)
342 {
343 const char* input =
344 "Content-Type: application/X-atf-tp; version=\"1\"\n"
345 "\n"
346 "descr: Out of order\n"
347 "ident: test1\n"
348 ;
349
350 const char* exp_calls[] = {
351 NULL
352 };
353
354 const char* exp_errors[] = {
355 "3: First property of a test case must be 'ident'",
356 NULL
357 };
358
359 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
360 }
361
362 ATF_TEST_CASE_WITHOUT_HEAD(tp_54);
ATF_TEST_CASE_BODY(tp_54)363 ATF_TEST_CASE_BODY(tp_54)
364 {
365 const char* input =
366 "Content-Type: application/X-atf-tp; version=\"1\"\n"
367 "\n"
368 "ident:\n"
369 ;
370
371 const char* exp_calls[] = {
372 NULL
373 };
374
375 const char* exp_errors[] = {
376 "3: The value for 'ident' cannot be empty",
377 NULL
378 };
379
380 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
381 }
382
383 ATF_TEST_CASE_WITHOUT_HEAD(tp_55);
ATF_TEST_CASE_BODY(tp_55)384 ATF_TEST_CASE_BODY(tp_55)
385 {
386 const char* input =
387 "Content-Type: application/X-atf-tp; version=\"1\"\n"
388 "\n"
389 "ident: +*,\n"
390 ;
391
392 const char* exp_calls[] = {
393 NULL
394 };
395
396 const char* exp_errors[] = {
397 "3: The identifier must match ^[_A-Za-z0-9]+$; was '+*,'",
398 NULL
399 };
400
401 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
402 }
403
404 ATF_TEST_CASE_WITHOUT_HEAD(tp_56);
ATF_TEST_CASE_BODY(tp_56)405 ATF_TEST_CASE_BODY(tp_56)
406 {
407 const char* input =
408 "Content-Type: application/X-atf-tp; version=\"1\"\n"
409 "\n"
410 "ident: test\n"
411 "timeout: hello\n"
412 ;
413
414 const char* exp_calls[] = {
415 NULL
416 };
417
418 const char* exp_errors[] = {
419 "4: The timeout property requires an integer value",
420 NULL
421 };
422
423 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
424 }
425
426 ATF_TEST_CASE_WITHOUT_HEAD(tp_57);
ATF_TEST_CASE_BODY(tp_57)427 ATF_TEST_CASE_BODY(tp_57)
428 {
429 const char* input =
430 "Content-Type: application/X-atf-tp; version=\"1\"\n"
431 "\n"
432 "ident: test\n"
433 "unknown: property\n"
434 ;
435
436 const char* exp_calls[] = {
437 NULL
438 };
439
440 const char* exp_errors[] = {
441 "4: Unknown property 'unknown'",
442 NULL
443 };
444
445 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
446 }
447
448 ATF_TEST_CASE_WITHOUT_HEAD(tp_58);
ATF_TEST_CASE_BODY(tp_58)449 ATF_TEST_CASE_BODY(tp_58)
450 {
451 const char* input =
452 "Content-Type: application/X-atf-tp; version=\"1\"\n"
453 "\n"
454 "ident: test\n"
455 "X-foo:\n"
456 ;
457
458 const char* exp_calls[] = {
459 NULL
460 };
461
462 const char* exp_errors[] = {
463 "4: The value for 'X-foo' cannot be empty",
464 NULL
465 };
466
467 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
468 }
469
470 ATF_TEST_CASE_WITHOUT_HEAD(tp_59);
ATF_TEST_CASE_BODY(tp_59)471 ATF_TEST_CASE_BODY(tp_59)
472 {
473 const char* input =
474 "Content-Type: application/X-atf-tp; version=\"1\"\n"
475 "\n"
476 "\n"
477 "ident: test\n"
478 "timeout: 300\n"
479 ;
480
481 const char* exp_calls[] = {
482 NULL
483 };
484
485 const char* exp_errors[] = {
486 "3: Unexpected token `<<NEWLINE>>'; expected property name",
487 NULL
488 };
489
490 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
491 }
492
493 ATF_TEST_CASE_WITHOUT_HEAD(tp_60);
ATF_TEST_CASE_BODY(tp_60)494 ATF_TEST_CASE_BODY(tp_60)
495 {
496 const char* input =
497 "Content-Type: application/X-atf-tp; version=\"1\"\n"
498 "\n"
499 "ident: test\n"
500 "require.memory: 12345D\n"
501 ;
502
503 const char* exp_calls[] = {
504 NULL
505 };
506
507 const char* exp_errors[] = {
508 "4: The require.memory property requires an integer value representing"
509 " an amount of bytes",
510 NULL
511 };
512
513 do_parser_test< tp_reader >(input, exp_calls, exp_errors);
514 }
515
516 // -------------------------------------------------------------------------
517 // Tests for the "tps" writer.
518 // -------------------------------------------------------------------------
519
520 ATF_TEST_CASE(atf_tps_writer);
ATF_TEST_CASE_HEAD(atf_tps_writer)521 ATF_TEST_CASE_HEAD(atf_tps_writer)
522 {
523 set_md_var("descr", "Verifies the application/X-atf-tps writer");
524 }
ATF_TEST_CASE_BODY(atf_tps_writer)525 ATF_TEST_CASE_BODY(atf_tps_writer)
526 {
527 std::ostringstream expss;
528 std::ostringstream ss;
529 const char *ts_regex = "[0-9]+\\.[0-9]{1,6}, ";
530
531 #define RESET \
532 expss.str(""); \
533 ss.str("")
534
535 #define CHECK \
536 check_match(*this, ss.str(), expss.str())
537
538 {
539 RESET;
540
541 impl::atf_tps_writer w(ss);
542 expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
543 CHECK;
544 }
545
546 {
547 RESET;
548
549 impl::atf_tps_writer w(ss);
550 expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
551 CHECK;
552
553 w.info("foo", "bar");
554 expss << "info: foo, bar\n";
555 CHECK;
556
557 w.info("baz", "second info");
558 expss << "info: baz, second info\n";
559 CHECK;
560 }
561
562 {
563 RESET;
564
565 impl::atf_tps_writer w(ss);
566 expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
567 CHECK;
568
569 w.ntps(0);
570 expss << "tps-count: 0\n";
571 CHECK;
572 }
573
574 {
575 RESET;
576
577 impl::atf_tps_writer w(ss);
578 expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
579 CHECK;
580
581 w.ntps(123);
582 expss << "tps-count: 123\n";
583 CHECK;
584 }
585
586 {
587 RESET;
588
589 impl::atf_tps_writer w(ss);
590 expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
591 CHECK;
592
593 w.ntps(2);
594 expss << "tps-count: 2\n";
595 CHECK;
596
597 w.start_tp("foo", 0);
598 expss << "tp-start: " << ts_regex << "foo, 0\n";
599 CHECK;
600
601 w.end_tp("");
602 expss << "tp-end: " << ts_regex << "foo\n";
603 CHECK;
604
605 w.start_tp("bar", 0);
606 expss << "tp-start: " << ts_regex << "bar, 0\n";
607 CHECK;
608
609 w.end_tp("failed program");
610 expss << "tp-end: " << ts_regex << "bar, failed program\n";
611 CHECK;
612 }
613
614 {
615 RESET;
616
617 impl::atf_tps_writer w(ss);
618 expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
619 CHECK;
620
621 w.ntps(1);
622 expss << "tps-count: 1\n";
623 CHECK;
624
625 w.start_tp("foo", 1);
626 expss << "tp-start: " << ts_regex << "foo, 1\n";
627 CHECK;
628
629 w.start_tc("brokentc");
630 expss << "tc-start: " << ts_regex << "brokentc\n";
631 CHECK;
632
633 w.end_tp("aborted");
634 expss << "tp-end: " << ts_regex << "foo, aborted\n";
635 CHECK;
636 }
637
638 {
639 RESET;
640
641 impl::atf_tps_writer w(ss);
642 expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
643 CHECK;
644
645 w.ntps(1);
646 expss << "tps-count: 1\n";
647 CHECK;
648
649 w.start_tp("thetp", 3);
650 expss << "tp-start: " << ts_regex << "thetp, 3\n";
651 CHECK;
652
653 w.start_tc("passtc");
654 expss << "tc-start: " << ts_regex << "passtc\n";
655 CHECK;
656
657 w.end_tc("passed", "");
658 expss << "tc-end: " << ts_regex << "passtc, passed\n";
659 CHECK;
660
661 w.start_tc("failtc");
662 expss << "tc-start: " << ts_regex << "failtc\n";
663 CHECK;
664
665 w.end_tc("failed", "The reason");
666 expss << "tc-end: " << ts_regex << "failtc, failed, The reason\n";
667 CHECK;
668
669 w.start_tc("skiptc");
670 expss << "tc-start: " << ts_regex << "skiptc\n";
671 CHECK;
672
673 w.end_tc("skipped", "The reason");
674 expss << "tc-end: " << ts_regex << "skiptc, skipped, The reason\n";
675 CHECK;
676
677 w.end_tp("");
678 expss << "tp-end: " << ts_regex << "thetp\n";
679 CHECK;
680 }
681
682 {
683 RESET;
684
685 impl::atf_tps_writer w(ss);
686 expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
687 CHECK;
688
689 w.ntps(1);
690 expss << "tps-count: 1\n";
691 CHECK;
692
693 w.start_tp("thetp", 1);
694 expss << "tp-start: " << ts_regex << "thetp, 1\n";
695 CHECK;
696
697 w.start_tc("thetc");
698 expss << "tc-start: " << ts_regex << "thetc\n";
699 CHECK;
700
701 w.stdout_tc("a line");
702 expss << "tc-so:a line\n";
703 CHECK;
704
705 w.stdout_tc("another line");
706 expss << "tc-so:another line\n";
707 CHECK;
708
709 w.stderr_tc("an error message");
710 expss << "tc-se:an error message\n";
711 CHECK;
712
713 w.end_tc("passed", "");
714 expss << "tc-end: " << ts_regex << "thetc, passed\n";
715 CHECK;
716
717 w.end_tp("");
718 expss << "tp-end: " << ts_regex << "thetp\n";
719 CHECK;
720 }
721
722 {
723 RESET;
724
725 impl::atf_tps_writer w(ss);
726 expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
727 CHECK;
728
729 w.ntps(1);
730 expss << "tps-count: 1\n";
731 CHECK;
732
733 w.start_tp("thetp", 0);
734 expss << "tp-start: " << ts_regex << "thetp, 0\n";
735 CHECK;
736
737 w.end_tp("");
738 expss << "tp-end: " << ts_regex << "thetp\n";
739 CHECK;
740
741 w.info("foo", "bar");
742 expss << "info: foo, bar\n";
743 CHECK;
744
745 w.info("baz", "second value");
746 expss << "info: baz, second value\n";
747 CHECK;
748 }
749
750 #undef CHECK
751 #undef RESET
752 }
753
754 // -------------------------------------------------------------------------
755 // Tests for the free functions.
756 // -------------------------------------------------------------------------
757
758 ATF_TEST_CASE(get_metadata_bad);
ATF_TEST_CASE_HEAD(get_metadata_bad)759 ATF_TEST_CASE_HEAD(get_metadata_bad) {}
ATF_TEST_CASE_BODY(get_metadata_bad)760 ATF_TEST_CASE_BODY(get_metadata_bad) {
761 const atf::fs::path executable = get_helper(*this, "bad_metadata_helper");
762 ATF_REQUIRE_THROW(atf::parser::parse_errors,
763 impl::get_metadata(executable, vars_map()));
764 }
765
766 ATF_TEST_CASE(get_metadata_zero_tcs);
ATF_TEST_CASE_HEAD(get_metadata_zero_tcs)767 ATF_TEST_CASE_HEAD(get_metadata_zero_tcs) {}
ATF_TEST_CASE_BODY(get_metadata_zero_tcs)768 ATF_TEST_CASE_BODY(get_metadata_zero_tcs) {
769 const atf::fs::path executable = get_helper(*this, "zero_tcs_helper");
770 ATF_REQUIRE_THROW(atf::parser::parse_errors,
771 impl::get_metadata(executable, vars_map()));
772 }
773
774 ATF_TEST_CASE(get_metadata_several_tcs);
ATF_TEST_CASE_HEAD(get_metadata_several_tcs)775 ATF_TEST_CASE_HEAD(get_metadata_several_tcs) {}
ATF_TEST_CASE_BODY(get_metadata_several_tcs)776 ATF_TEST_CASE_BODY(get_metadata_several_tcs) {
777 const atf::fs::path executable = get_helper(*this, "several_tcs_helper");
778 const impl::metadata md = impl::get_metadata(executable, vars_map());
779 ATF_REQUIRE_EQ(3, md.test_cases.size());
780
781 {
782 const impl::test_cases_map::const_iterator iter =
783 md.test_cases.find("first");
784 ATF_REQUIRE(iter != md.test_cases.end());
785
786 ATF_REQUIRE_EQ(4, (*iter).second.size());
787 check_property((*iter).second, "descr", "Description 1");
788 check_property((*iter).second, "has.cleanup", "false");
789 check_property((*iter).second, "ident", "first");
790 check_property((*iter).second, "timeout", "300");
791 }
792
793 {
794 const impl::test_cases_map::const_iterator iter =
795 md.test_cases.find("second");
796 ATF_REQUIRE(iter != md.test_cases.end());
797
798 ATF_REQUIRE_EQ(5, (*iter).second.size());
799 check_property((*iter).second, "descr", "Description 2");
800 check_property((*iter).second, "has.cleanup", "true");
801 check_property((*iter).second, "ident", "second");
802 check_property((*iter).second, "timeout", "500");
803 check_property((*iter).second, "X-property", "Custom property");
804 }
805
806 {
807 const impl::test_cases_map::const_iterator iter =
808 md.test_cases.find("third");
809 ATF_REQUIRE(iter != md.test_cases.end());
810
811 ATF_REQUIRE_EQ(3, (*iter).second.size());
812 check_property((*iter).second, "has.cleanup", "false");
813 check_property((*iter).second, "ident", "third");
814 check_property((*iter).second, "timeout", "300");
815 }
816 }
817
818 ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_death);
ATF_TEST_CASE_BODY(parse_test_case_result_expected_death)819 ATF_TEST_CASE_BODY(parse_test_case_result_expected_death) {
820 check_result("expected_death", -1, "foo bar",
821 detail::parse_test_case_result("expected_death: foo bar"));
822
823 ATF_REQUIRE_THROW(std::runtime_error,
824 detail::parse_test_case_result("expected_death"));
825 ATF_REQUIRE_THROW(std::runtime_error,
826 detail::parse_test_case_result("expected_death(3): foo"));
827 }
828
829 ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_exit);
ATF_TEST_CASE_BODY(parse_test_case_result_expected_exit)830 ATF_TEST_CASE_BODY(parse_test_case_result_expected_exit) {
831 check_result("expected_exit", -1, "foo bar",
832 detail::parse_test_case_result("expected_exit: foo bar"));
833 check_result("expected_exit", -1, "foo bar",
834 detail::parse_test_case_result("expected_exit(): foo bar"));
835 check_result("expected_exit", 5, "foo bar",
836 detail::parse_test_case_result("expected_exit(5): foo bar"));
837
838 ATF_REQUIRE_THROW(std::runtime_error,
839 detail::parse_test_case_result("expected_exit"));
840 ATF_REQUIRE_THROW(std::runtime_error,
841 detail::parse_test_case_result("expected_exit("));
842 }
843
844 ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_failure);
ATF_TEST_CASE_BODY(parse_test_case_result_expected_failure)845 ATF_TEST_CASE_BODY(parse_test_case_result_expected_failure) {
846 check_result("expected_failure", -1, "foo bar",
847 detail::parse_test_case_result("expected_failure: foo bar"));
848
849 ATF_REQUIRE_THROW(std::runtime_error,
850 detail::parse_test_case_result("expected_failure"));
851 ATF_REQUIRE_THROW(std::runtime_error,
852 detail::parse_test_case_result("expected_failure(3): foo"));
853 }
854
855 ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_signal);
ATF_TEST_CASE_BODY(parse_test_case_result_expected_signal)856 ATF_TEST_CASE_BODY(parse_test_case_result_expected_signal) {
857 check_result("expected_signal", -1, "foo bar",
858 detail::parse_test_case_result("expected_signal: foo bar"));
859 check_result("expected_signal", -1, "foo bar",
860 detail::parse_test_case_result("expected_signal(): foo bar"));
861 check_result("expected_signal", 5, "foo bar",
862 detail::parse_test_case_result("expected_signal(5): foo bar"));
863
864 ATF_REQUIRE_THROW(std::runtime_error,
865 detail::parse_test_case_result("expected_signal"));
866 ATF_REQUIRE_THROW(std::runtime_error,
867 detail::parse_test_case_result("expected_signal("));
868 }
869
870 ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_timeout);
ATF_TEST_CASE_BODY(parse_test_case_result_expected_timeout)871 ATF_TEST_CASE_BODY(parse_test_case_result_expected_timeout) {
872 check_result("expected_timeout", -1, "foo bar",
873 detail::parse_test_case_result("expected_timeout: foo bar"));
874
875 ATF_REQUIRE_THROW(std::runtime_error,
876 detail::parse_test_case_result("expected_timeout"));
877 ATF_REQUIRE_THROW(std::runtime_error,
878 detail::parse_test_case_result("expected_timeout(3): foo"));
879 }
880
881 ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_failed);
ATF_TEST_CASE_BODY(parse_test_case_result_failed)882 ATF_TEST_CASE_BODY(parse_test_case_result_failed) {
883 check_result("failed", -1, "foo bar",
884 detail::parse_test_case_result("failed: foo bar"));
885
886 ATF_REQUIRE_THROW(std::runtime_error,
887 detail::parse_test_case_result("failed"));
888 ATF_REQUIRE_THROW(std::runtime_error,
889 detail::parse_test_case_result("failed(3): foo"));
890 }
891
892 ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_passed);
ATF_TEST_CASE_BODY(parse_test_case_result_passed)893 ATF_TEST_CASE_BODY(parse_test_case_result_passed) {
894 check_result("passed", -1, "",
895 detail::parse_test_case_result("passed"));
896
897 ATF_REQUIRE_THROW(std::runtime_error,
898 detail::parse_test_case_result("passed: foo"));
899 ATF_REQUIRE_THROW(std::runtime_error,
900 detail::parse_test_case_result("passed(3): foo"));
901 }
902
903 ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_skipped);
ATF_TEST_CASE_BODY(parse_test_case_result_skipped)904 ATF_TEST_CASE_BODY(parse_test_case_result_skipped) {
905 check_result("skipped", -1, "foo bar",
906 detail::parse_test_case_result("skipped: foo bar"));
907
908 ATF_REQUIRE_THROW(std::runtime_error,
909 detail::parse_test_case_result("skipped"));
910 ATF_REQUIRE_THROW(std::runtime_error,
911 detail::parse_test_case_result("skipped(3): foo"));
912 }
913
914 ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_unknown);
ATF_TEST_CASE_BODY(parse_test_case_result_unknown)915 ATF_TEST_CASE_BODY(parse_test_case_result_unknown) {
916 ATF_REQUIRE_THROW(std::runtime_error,
917 detail::parse_test_case_result("foo"));
918 ATF_REQUIRE_THROW(std::runtime_error,
919 detail::parse_test_case_result("bar: foo"));
920 ATF_REQUIRE_THROW(std::runtime_error,
921 detail::parse_test_case_result("baz: foo"));
922 }
923
924 ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_failed);
ATF_TEST_CASE_BODY(read_test_case_result_failed)925 ATF_TEST_CASE_BODY(read_test_case_result_failed) {
926 write_test_case_result("resfile", "failed: foo bar\n");
927 const impl::test_case_result tcr = impl::read_test_case_result(
928 atf::fs::path("resfile"));
929 ATF_REQUIRE_EQ("failed", tcr.state());
930 ATF_REQUIRE_EQ("foo bar", tcr.reason());
931 }
932
933 ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_skipped);
ATF_TEST_CASE_BODY(read_test_case_result_skipped)934 ATF_TEST_CASE_BODY(read_test_case_result_skipped) {
935 write_test_case_result("resfile", "skipped: baz bar\n");
936 const impl::test_case_result tcr = impl::read_test_case_result(
937 atf::fs::path("resfile"));
938 ATF_REQUIRE_EQ("skipped", tcr.state());
939 ATF_REQUIRE_EQ("baz bar", tcr.reason());
940 }
941
942
943 ATF_TEST_CASE(read_test_case_result_no_file);
ATF_TEST_CASE_HEAD(read_test_case_result_no_file)944 ATF_TEST_CASE_HEAD(read_test_case_result_no_file) {}
ATF_TEST_CASE_BODY(read_test_case_result_no_file)945 ATF_TEST_CASE_BODY(read_test_case_result_no_file) {
946 ATF_REQUIRE_THROW(std::runtime_error,
947 impl::read_test_case_result(atf::fs::path("resfile")));
948 }
949
950 ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_empty_file);
ATF_TEST_CASE_BODY(read_test_case_result_empty_file)951 ATF_TEST_CASE_BODY(read_test_case_result_empty_file) {
952 write_test_case_result("resfile", "");
953 ATF_REQUIRE_THROW(std::runtime_error,
954 impl::read_test_case_result(atf::fs::path("resfile")));
955 }
956
957 ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_invalid);
ATF_TEST_CASE_BODY(read_test_case_result_invalid)958 ATF_TEST_CASE_BODY(read_test_case_result_invalid) {
959 write_test_case_result("resfile", "passed: hello\n");
960 ATF_REQUIRE_THROW(std::runtime_error,
961 impl::read_test_case_result(atf::fs::path("resfile")));
962 }
963
964 ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_multiline);
ATF_TEST_CASE_BODY(read_test_case_result_multiline)965 ATF_TEST_CASE_BODY(read_test_case_result_multiline) {
966 write_test_case_result("resfile", "skipped: foo\nbar\n");
967 const impl::test_case_result tcr = impl::read_test_case_result(
968 atf::fs::path("resfile"));
969 ATF_REQUIRE_EQ("skipped", tcr.state());
970 ATF_REQUIRE_EQ("foo<<NEWLINE UNEXPECTED>>bar", tcr.reason());
971 }
972
973 // -------------------------------------------------------------------------
974 // Main.
975 // -------------------------------------------------------------------------
976
ATF_INIT_TEST_CASES(tcs)977 ATF_INIT_TEST_CASES(tcs)
978 {
979 ATF_ADD_TEST_CASE(tcs, tp_1);
980 ATF_ADD_TEST_CASE(tcs, tp_2);
981 ATF_ADD_TEST_CASE(tcs, tp_3);
982 ATF_ADD_TEST_CASE(tcs, tp_4);
983 ATF_ADD_TEST_CASE(tcs, tp_50);
984 ATF_ADD_TEST_CASE(tcs, tp_51);
985 ATF_ADD_TEST_CASE(tcs, tp_52);
986 ATF_ADD_TEST_CASE(tcs, tp_53);
987 ATF_ADD_TEST_CASE(tcs, tp_54);
988 ATF_ADD_TEST_CASE(tcs, tp_55);
989 ATF_ADD_TEST_CASE(tcs, tp_56);
990 ATF_ADD_TEST_CASE(tcs, tp_57);
991 ATF_ADD_TEST_CASE(tcs, tp_58);
992 ATF_ADD_TEST_CASE(tcs, tp_59);
993 ATF_ADD_TEST_CASE(tcs, tp_60);
994
995 ATF_ADD_TEST_CASE(tcs, atf_tps_writer);
996
997 ATF_ADD_TEST_CASE(tcs, get_metadata_bad);
998 ATF_ADD_TEST_CASE(tcs, get_metadata_zero_tcs);
999 ATF_ADD_TEST_CASE(tcs, get_metadata_several_tcs);
1000
1001 ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_death);
1002 ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_exit);
1003 ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_failure);
1004 ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_signal);
1005 ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_timeout);
1006 ATF_ADD_TEST_CASE(tcs, parse_test_case_result_failed);
1007 ATF_ADD_TEST_CASE(tcs, parse_test_case_result_passed);
1008 ATF_ADD_TEST_CASE(tcs, parse_test_case_result_skipped);
1009 ATF_ADD_TEST_CASE(tcs, parse_test_case_result_unknown);
1010
1011 ATF_ADD_TEST_CASE(tcs, read_test_case_result_failed);
1012 ATF_ADD_TEST_CASE(tcs, read_test_case_result_skipped);
1013 ATF_ADD_TEST_CASE(tcs, read_test_case_result_no_file);
1014 ATF_ADD_TEST_CASE(tcs, read_test_case_result_empty_file);
1015 ATF_ADD_TEST_CASE(tcs, read_test_case_result_multiline);
1016 ATF_ADD_TEST_CASE(tcs, read_test_case_result_invalid);
1017
1018 // TODO: Add tests for run_test_case once all the missing functionality
1019 // is implemented.
1020 }
1021