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