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 40namespace impl = tools::test_program; 41namespace detail = tools::test_program::detail; 42 43// ------------------------------------------------------------------------- 44// Auxiliary functions. 45// ------------------------------------------------------------------------- 46 47namespace { 48 49typedef std::map< std::string, std::string > vars_map; 50 51static 52tools::fs::path 53get_helper(const atf::tests::tc& tc, const char* name) 54{ 55 return tools::fs::path(tc.get_config_var("srcdir")) / name; 56} 57 58static 59void 60check_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 67static void 68check_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 76static 77void 78write_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 86static 87void 88print_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. 100static 101void 102check_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 123class tp_reader : protected detail::atf_tp_reader { 124 void 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 140 got_eof(void) 141 { 142 m_calls.push_back("got_eof()"); 143 } 144 145public: 146 tp_reader(std::istream& is) : 147 detail::atf_tp_reader(is) 148 { 149 } 150 151 void 152 read(void) 153 { 154 atf_tp_reader::read(); 155 } 156 157 std::vector< std::string > m_calls; 158}; 159 160ATF_TEST_CASE_WITHOUT_HEAD(tp_1); 161ATF_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 188ATF_TEST_CASE_WITHOUT_HEAD(tp_2); 189ATF_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 222ATF_TEST_CASE_WITHOUT_HEAD(tp_3); 223ATF_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 254ATF_TEST_CASE_WITHOUT_HEAD(tp_4); 255ATF_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 277ATF_TEST_CASE_WITHOUT_HEAD(tp_50); 278ATF_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 297ATF_TEST_CASE_WITHOUT_HEAD(tp_51); 298ATF_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 320ATF_TEST_CASE_WITHOUT_HEAD(tp_52); 321ATF_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 343ATF_TEST_CASE_WITHOUT_HEAD(tp_53); 344ATF_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 365ATF_TEST_CASE_WITHOUT_HEAD(tp_54); 366ATF_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 386ATF_TEST_CASE_WITHOUT_HEAD(tp_55); 387ATF_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 407ATF_TEST_CASE_WITHOUT_HEAD(tp_56); 408ATF_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 429ATF_TEST_CASE_WITHOUT_HEAD(tp_57); 430ATF_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 451ATF_TEST_CASE_WITHOUT_HEAD(tp_58); 452ATF_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 473ATF_TEST_CASE_WITHOUT_HEAD(tp_59); 474ATF_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 496ATF_TEST_CASE_WITHOUT_HEAD(tp_60); 497ATF_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 523ATF_TEST_CASE(atf_tps_writer); 524ATF_TEST_CASE_HEAD(atf_tps_writer) 525{ 526 set_md_var("descr", "Verifies the application/X-atf-tps writer"); 527} 528ATF_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 761ATF_TEST_CASE(get_metadata_bad); 762ATF_TEST_CASE_HEAD(get_metadata_bad) {} 763ATF_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 769ATF_TEST_CASE(get_metadata_zero_tcs); 770ATF_TEST_CASE_HEAD(get_metadata_zero_tcs) {} 771ATF_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 777ATF_TEST_CASE(get_metadata_several_tcs); 778ATF_TEST_CASE_HEAD(get_metadata_several_tcs) {} 779ATF_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 821ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_death); 822ATF_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 832ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_exit); 833ATF_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 847ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_failure); 848ATF_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 858ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_signal); 859ATF_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 873ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_timeout); 874ATF_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 884ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_failed); 885ATF_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 895ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_passed); 896ATF_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 906ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_skipped); 907ATF_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 917ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_unknown); 918ATF_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 927ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_failed); 928ATF_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 936ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_skipped); 937ATF_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 946ATF_TEST_CASE(read_test_case_result_no_file); 947ATF_TEST_CASE_HEAD(read_test_case_result_no_file) {} 948ATF_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 953ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_empty_file); 954ATF_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 960ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_invalid); 961ATF_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 967ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_multiline); 968ATF_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 980ATF_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