1#!/usr/bin/perl -w 2 3BEGIN { 4 unshift @INC, 't/lib'; 5} 6 7use strict; 8use warnings; 9 10use Test::More; 11use IO::c55Capture; 12 13use Config; 14use POSIX; 15 16use TAP::Harness; 17 18# This is done to prevent the colors environment variables from 19# interfering. 20local $ENV{HARNESS_SUMMARY_COLOR_FAIL}; 21local $ENV{HARNESS_SUMMARY_COLOR_SUCCESS}; 22delete $ENV{HARNESS_SUMMARY_COLOR_FAIL}; 23delete $ENV{HARNESS_SUMMARY_COLOR_SUCCESS}; 24 25my $HARNESS = 'TAP::Harness'; 26 27my $source_tests = 't/source_tests'; 28my $sample_tests = 't/sample-tests'; 29 30plan tests => 133; 31 32# note that this test will always pass when run through 'prove' 33ok $ENV{HARNESS_ACTIVE}, 'HARNESS_ACTIVE env variable should be set'; 34ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set'; 35 36#### For color tests #### 37 38package Colorizer; 39 40sub new { bless {}, shift } 41sub can_color {1} 42 43sub set_color { 44 my ( $self, $output, $color ) = @_; 45 $output->("[[$color]]"); 46} 47 48package main; 49 50sub colorize { 51 my $harness = shift; 52 $harness->formatter->_colorizer( Colorizer->new ); 53} 54 55can_ok $HARNESS, 'new'; 56 57eval { $HARNESS->new( { no_such_key => 1 } ) }; 58like $@, qr/\QUnknown arguments to TAP::Harness::new (no_such_key)/, 59 '... and calling it with bad keys should fail'; 60 61eval { $HARNESS->new( { lib => 'aint_no_such_lib' } ) }; 62is $@, '', '... and calling it with a non-existent lib is fine'; 63 64eval { $HARNESS->new( { lib => [qw/bad_lib_1 bad_lib_2/] } ) }; 65is $@, '', '... and calling it with non-existent libs is fine'; 66 67ok my $harness = $HARNESS->new, 68 'Calling new() without arguments should succeed'; 69 70for my $test_args ( get_arg_sets() ) { 71 my %args = %$test_args; 72 for my $key ( sort keys %args ) { 73 $args{$key} = $args{$key}{in}; 74 } 75 ok my $harness = $HARNESS->new( {%args} ), 76 'Calling new() with valid arguments should succeed'; 77 isa_ok $harness, $HARNESS, '... and the object it returns'; 78 79 while ( my ( $property, $test ) = each %$test_args ) { 80 my $value = $test->{out}; 81 can_ok $harness, $property; 82 is_deeply scalar $harness->$property(), $value, $test->{test_name}; 83 } 84} 85 86{ 87 my @output; 88 no warnings 'redefine'; 89 local *TAP::Formatter::Base::_output = sub { 90 my $self = shift; 91 push @output => grep { $_ ne '' } 92 map { 93 local $_ = $_; 94 chomp; 95 trim($_) 96 } @_; 97 }; 98 my $harness = TAP::Harness->new( 99 { verbosity => 1, formatter_class => "TAP::Formatter::Console" } ); 100 my $harness_whisper = TAP::Harness->new( 101 { verbosity => -1, formatter_class => "TAP::Formatter::Console" } ); 102 my $harness_mute = TAP::Harness->new( 103 { verbosity => -2, formatter_class => "TAP::Formatter::Console" } ); 104 my $harness_directives = TAP::Harness->new( 105 { directives => 1, formatter_class => "TAP::Formatter::Console" } ); 106 my $harness_failures = TAP::Harness->new( 107 { failures => 1, formatter_class => "TAP::Formatter::Console" } ); 108 109 colorize($harness); 110 111 can_ok $harness, 'runtests'; 112 113 # normal tests in verbose mode 114 115 ok my $aggregate = _runtests( $harness, "$source_tests/harness" ), 116 '... runtests returns the aggregate'; 117 118 isa_ok $aggregate, 'TAP::Parser::Aggregator'; 119 120 chomp(@output); 121 122 my @expected = ( 123 "$source_tests/harness ..", 124 '1..1', 125 '[[reset]]', 126 'ok 1 - this is a test', 127 '[[reset]]', 128 'ok', 129 '[[green]]', 130 'All tests successful.', 131 '[[reset]]', 132 ); 133 my $status = pop @output; 134 my $expected_status = qr{^Result: PASS$}; 135 my $summary = pop @output; 136 my $expected_summary = qr{^Files=1, Tests=1, +\d+ wallclock secs}; 137 138 is_deeply \@output, \@expected, '... and the output should be correct'; 139 like $status, $expected_status, 140 '... and the status line should be correct'; 141 like $summary, $expected_summary, 142 '... and the report summary should look correct'; 143 144 # use an alias for test name 145 146 @output = (); 147 ok $aggregate 148 = _runtests( $harness, [ "$source_tests/harness", 'My Nice Test' ] ), 149 '... runtests returns the aggregate'; 150 151 isa_ok $aggregate, 'TAP::Parser::Aggregator'; 152 153 chomp(@output); 154 155 @expected = ( 156 'My Nice Test ..', 157 '1..1', 158 '[[reset]]', 159 'ok 1 - this is a test', 160 '[[reset]]', 161 'ok', 162 '[[green]]', 163 'All tests successful.', 164 '[[reset]]', 165 ); 166 $status = pop @output; 167 $expected_status = qr{^Result: PASS$}; 168 $summary = pop @output; 169 $expected_summary = qr{^Files=1, Tests=1, +\d+ wallclock secs}; 170 171 is_deeply \@output, \@expected, '... and the output should be correct'; 172 like $status, $expected_status, 173 '... and the status line should be correct'; 174 like $summary, $expected_summary, 175 '... and the report summary should look correct'; 176 177 # run same test twice 178 179 @output = (); 180 ok $aggregate = _runtests( 181 $harness, [ "$source_tests/harness", 'My Nice Test' ], 182 [ "$source_tests/harness", 'My Nice Test Again' ] 183 ), 184 '... runtests returns the aggregate'; 185 186 isa_ok $aggregate, 'TAP::Parser::Aggregator'; 187 188 chomp(@output); 189 190 @expected = ( 191 'My Nice Test ........', 192 '1..1', 193 '[[reset]]', 194 'ok 1 - this is a test', 195 '[[reset]]', 196 'ok', 197 'My Nice Test Again ..', 198 '1..1', 199 '[[reset]]', 200 'ok 1 - this is a test', 201 '[[reset]]', 202 'ok', 203 '[[green]]', 204 'All tests successful.', 205 '[[reset]]', 206 ); 207 $status = pop @output; 208 $expected_status = qr{^Result: PASS$}; 209 $summary = pop @output; 210 $expected_summary = qr{^Files=2, Tests=2, +\d+ wallclock secs}; 211 212 is_deeply \@output, \@expected, '... and the output should be correct'; 213 like $status, $expected_status, 214 '... and the status line should be correct'; 215 like $summary, $expected_summary, 216 '... and the report summary should look correct'; 217 218 # normal tests in quiet mode 219 220 @output = (); 221 _runtests( $harness_whisper, "$source_tests/harness" ); 222 223 chomp(@output); 224 @expected = ( 225 "$source_tests/harness ..", 226 'ok', 227 'All tests successful.', 228 ); 229 230 $status = pop @output; 231 $expected_status = qr{^Result: PASS$}; 232 $summary = pop @output; 233 $expected_summary = qr/^Files=1, Tests=1, +\d+ wallclock secs/; 234 235 is_deeply \@output, \@expected, '... and the output should be correct'; 236 like $status, $expected_status, 237 '... and the status line should be correct'; 238 like $summary, $expected_summary, 239 '... and the report summary should look correct'; 240 241 # normal tests in really_quiet mode 242 243 @output = (); 244 _runtests( $harness_mute, "$source_tests/harness" ); 245 246 chomp(@output); 247 @expected = ( 248 'All tests successful.', 249 ); 250 251 $status = pop @output; 252 $expected_status = qr{^Result: PASS$}; 253 $summary = pop @output; 254 $expected_summary = qr/^Files=1, Tests=1, +\d+ wallclock secs/; 255 256 is_deeply \@output, \@expected, '... and the output should be correct'; 257 like $status, $expected_status, 258 '... and the status line should be correct'; 259 like $summary, $expected_summary, 260 '... and the report summary should look correct'; 261 262 # normal tests with failures 263 264 @output = (); 265 _runtests( $harness, "$source_tests/harness_failure" ); 266 267 $status = pop @output; 268 $summary = pop @output; 269 270 like $status, qr{^Result: FAIL$}, 271 '... and the status line should be correct'; 272 273 my @summary = @output[ 18 .. $#output ]; 274 @output = @output[ 0 .. 17 ]; 275 276 @expected = ( 277 "$source_tests/harness_failure ..", 278 '1..2', 279 '[[reset]]', 280 'ok 1 - this is a test', 281 '[[reset]]', 282 '[[red]]', 283 'not ok 2 - this is another test', 284 '[[reset]]', 285 q{# Failed test 'this is another test'}, 286 '[[reset]]', 287 '# in harness_failure.t at line 5.', 288 '[[reset]]', 289 q{# got: 'waffle'}, 290 '[[reset]]', 291 q{# expected: 'yarblokos'}, 292 '[[reset]]', 293 '[[red]]', 294 'Failed 1/2 subtests', 295 ); 296 297 is_deeply \@output, \@expected, 298 '... and failing test output should be correct'; 299 300 my @expected_summary = ( 301 '[[reset]]', 302 'Test Summary Report', 303 '-------------------', 304 '[[red]]', 305 "$source_tests/harness_failure (Wstat: 0 Tests: 2 Failed: 1)", 306 '[[reset]]', 307 '[[red]]', 308 'Failed test:', 309 '[[reset]]', 310 '[[red]]', 311 '2', 312 '[[reset]]', 313 ); 314 315 is_deeply \@summary, \@expected_summary, 316 '... and the failure summary should also be correct'; 317 318 # quiet tests with failures 319 320 @output = (); 321 _runtests( $harness_whisper, "$source_tests/harness_failure" ); 322 323 $status = pop @output; 324 $summary = pop @output; 325 @expected = ( 326 "$source_tests/harness_failure ..", 327 'Failed 1/2 subtests', 328 'Test Summary Report', 329 '-------------------', 330 "$source_tests/harness_failure (Wstat: 0 Tests: 2 Failed: 1)", 331 'Failed test:', 332 '2', 333 ); 334 335 like $status, qr{^Result: FAIL$}, 336 '... and the status line should be correct'; 337 338 is_deeply \@output, \@expected, 339 '... and failing test output should be correct'; 340 341 # really quiet tests with failures 342 343 @output = (); 344 _runtests( $harness_mute, "$source_tests/harness_failure" ); 345 346 $status = pop @output; 347 $summary = pop @output; 348 @expected = ( 349 'Test Summary Report', 350 '-------------------', 351 "$source_tests/harness_failure (Wstat: 0 Tests: 2 Failed: 1)", 352 'Failed test:', 353 '2', 354 ); 355 356 like $status, qr{^Result: FAIL$}, 357 '... and the status line should be correct'; 358 359 is_deeply \@output, \@expected, 360 '... and failing test output should be correct'; 361 362 # only show directives 363 364 @output = (); 365 _runtests( 366 $harness_directives, 367 "$source_tests/harness_directives" 368 ); 369 370 chomp(@output); 371 372 @expected = ( 373 "$source_tests/harness_directives ..", 374 'not ok 2 - we have a something # TODO some output', 375 "ok 3 houston, we don't have liftoff # SKIP no funding", 376 'ok', 377 'All tests successful.', 378 379 # ~TODO {{{ this should be an option 380 #'Test Summary Report', 381 #'-------------------', 382 #"$source_tests/harness_directives (Wstat: 0 Tests: 3 Failed: 0)", 383 #'Tests skipped:', 384 #'3', 385 # }}} 386 ); 387 388 $status = pop @output; 389 $summary = pop @output; 390 $expected_summary = qr/^Files=1, Tests=3, +\d+ wallclock secs/; 391 392 is_deeply \@output, \@expected, '... and the output should be correct'; 393 like $summary, $expected_summary, 394 '... and the report summary should look correct'; 395 396 like $status, qr{^Result: PASS$}, 397 '... and the status line should be correct'; 398 399 # normal tests with bad tap 400 401 # install callback handler 402 my $parser; 403 my $callback_count = 0; 404 405 my @callback_log = (); 406 407 for my $evt (qw(parser_args made_parser before_runtests after_runtests)) { 408 $harness->callback( 409 $evt => sub { 410 push @callback_log, $evt; 411 } 412 ); 413 } 414 415 $harness->callback( 416 made_parser => sub { 417 $parser = shift; 418 $callback_count++; 419 } 420 ); 421 422 @output = (); 423 _runtests( $harness, "$source_tests/harness_badtap" ); 424 chomp(@output); 425 426 @output = map { trim($_) } @output; 427 $status = pop @output; 428 @summary = @output[ 12 .. ( $#output - 1 ) ]; 429 @output = @output[ 0 .. 11 ]; 430 @expected = ( 431 "$source_tests/harness_badtap ..", 432 '1..2', 433 '[[reset]]', 434 'ok 1 - this is a test', 435 '[[reset]]', 436 '[[red]]', 437 'not ok 2 - this is another test', 438 '[[reset]]', 439 '1..2', 440 '[[reset]]', 441 '[[red]]', 442 'Failed 1/2 subtests', 443 ); 444 is_deeply \@output, \@expected, 445 '... and failing test output should be correct'; 446 like $status, qr{^Result: FAIL$}, 447 '... and the status line should be correct'; 448 @expected_summary = ( 449 '[[reset]]', 450 'Test Summary Report', 451 '-------------------', 452 '[[red]]', 453 "$source_tests/harness_badtap (Wstat: 0 Tests: 2 Failed: 1)", 454 '[[reset]]', 455 '[[red]]', 456 'Failed test:', 457 '[[reset]]', 458 '[[red]]', 459 '2', 460 '[[reset]]', 461 '[[red]]', 462 'Parse errors: More than one plan found in TAP output', 463 '[[reset]]', 464 ); 465 is_deeply \@summary, \@expected_summary, 466 '... and the badtap summary should also be correct'; 467 468 cmp_ok( $callback_count, '==', 1, 'callback called once' ); 469 is_deeply( 470 \@callback_log, 471 [ 'before_runtests', 'parser_args', 'made_parser', 'after_runtests' ], 472 'callback log matches' 473 ); 474 isa_ok $parser, 'TAP::Parser'; 475 476 # coverage testing for _should_show_failures 477 # only show failures 478 479 @output = (); 480 _runtests( $harness_failures, "$source_tests/harness_failure" ); 481 482 chomp(@output); 483 484 @expected = ( 485 "$source_tests/harness_failure ..", 486 'not ok 2 - this is another test', 487 'Failed 1/2 subtests', 488 'Test Summary Report', 489 '-------------------', 490 "$source_tests/harness_failure (Wstat: 0 Tests: 2 Failed: 1)", 491 'Failed test:', 492 '2', 493 ); 494 495 $status = pop @output; 496 $summary = pop @output; 497 498 like $status, qr{^Result: FAIL$}, 499 '... and the status line should be correct'; 500 $expected_summary = qr/^Files=1, Tests=2, +\d+ wallclock secs/; 501 is_deeply \@output, \@expected, '... and the output should be correct'; 502 503 # check the status output for no tests 504 505 @output = (); 506 _runtests( $harness_failures, "$sample_tests/no_output" ); 507 508 chomp(@output); 509 510 @expected = ( 511 "$sample_tests/no_output ..", 512 'No subtests run', 513 'Test Summary Report', 514 '-------------------', 515 "$sample_tests/no_output (Wstat: 0 Tests: 0 Failed: 0)", 516 'Parse errors: No plan found in TAP output', 517 ); 518 519 $status = pop @output; 520 $summary = pop @output; 521 522 like $status, qr{^Result: FAIL$}, 523 '... and the status line should be correct'; 524 $expected_summary = qr/^Files=1, Tests=2, +\d+ wallclock secs/; 525 is_deeply \@output, \@expected, '... and the output should be correct'; 526 527 SKIP: { 528 skip "Skipping for now because of ASAN failures", 1; # Core-only modification 529 skip "No SIGSEGV on $^O", 1 if $^O eq 'MSWin32' or $Config::Config{'sig_name'} !~ m/SEGV/; 530 531 @output = (); 532 _runtests( $harness_failures, "$sample_tests/segfault" ); 533 534 my $out_str = join q<>, @output; 535 536 like( $out_str, qr<SEGV>, 'SIGSEGV is parsed out' ); 537 } 538 539 #XXXX 540} 541 542# make sure we can exec something ... anything! 543SKIP: { 544 545 my $cat = '/bin/cat'; 546 547 # TODO: use TYPE on win32? 548 unless ( -e $cat ) { 549 skip "no '$cat'", 2; 550 } 551 552 my $capture = IO::c55Capture->new_handle; 553 my $harness = TAP::Harness->new( 554 { verbosity => -2, 555 stdout => $capture, 556 exec => [$cat], 557 } 558 ); 559 560 eval { _runtests( $harness, 't/data/catme.1' ); }; 561 562 my @output = tied($$capture)->dump; 563 my $status = pop @output; 564 like $status, qr{^Result: PASS$}, 565 '... and the status line should be correct'; 566 pop @output; # get rid of summary line 567 my $answer = pop @output; 568 is( $answer, "All tests successful.\n", 'cat meows' ); 569} 570 571# make sure that we can exec with a code ref. 572{ 573 my $capture = IO::c55Capture->new_handle; 574 my $harness = TAP::Harness->new( 575 { verbosity => -2, 576 stdout => $capture, 577 exec => sub {undef}, 578 } 579 ); 580 581 _runtests( $harness, "$source_tests/harness" ); 582 583 my @output = tied($$capture)->dump; 584 my $status = pop @output; 585 like $status, qr{^Result: PASS$}, 586 '... and the status line should be correct'; 587 pop @output; # get rid of summary line 588 my $answer = pop @output; 589 is( $answer, "All tests successful.\n", 'cat meows' ); 590} 591 592# Exec with a coderef that returns an arrayref 593SKIP: { 594 my $cat = '/bin/cat'; 595 unless ( -e $cat ) { 596 skip "no '$cat'", 2; 597 } 598 599 my $capture = IO::c55Capture->new_handle; 600 my $harness = TAP::Harness->new( 601 { verbosity => -2, 602 stdout => $capture, 603 exec => sub { 604 return [ 605 $cat, 606 't/data/catme.1' 607 ]; 608 }, 609 } 610 ); 611 612 _runtests( $harness, "$source_tests/harness" ); 613 614 my @output = tied($$capture)->dump; 615 my $status = pop @output; 616 like $status, qr{^Result: PASS$}, 617 '... and the status line should be correct'; 618 pop @output; # get rid of summary line 619 my $answer = pop @output; 620 is( $answer, "All tests successful.\n", 'cat meows' ); 621} 622 623# Exec with a coderef that returns raw TAP 624{ 625 my $capture = IO::c55Capture->new_handle; 626 my $harness = TAP::Harness->new( 627 { verbosity => -2, 628 stdout => $capture, 629 exec => sub { 630 return "1..1\nok 1 - raw TAP\n"; 631 }, 632 } 633 ); 634 635 _runtests( $harness, "$source_tests/harness" ); 636 637 my @output = tied($$capture)->dump; 638 my $status = pop @output; 639 like $status, qr{^Result: PASS$}, 640 '... and the status line should be correct'; 641 pop @output; # get rid of summary line 642 my $answer = pop @output; 643 is( $answer, "All tests successful.\n", 'cat meows' ); 644} 645 646# Exec with a coderef that returns a filehandle 647{ 648 my $capture = IO::c55Capture->new_handle; 649 my $harness = TAP::Harness->new( 650 { verbosity => -2, 651 stdout => $capture, 652 exec => sub { 653 open my $fh, 't/data/catme.1'; 654 return $fh; 655 }, 656 } 657 ); 658 659 _runtests( $harness, "$source_tests/harness" ); 660 661 my @output = tied($$capture)->dump; 662 my $status = pop @output; 663 like $status, qr{^Result: PASS$}, 664 '... and the status line should be correct'; 665 pop @output; # get rid of summary line 666 my $answer = pop @output; 667 is( $answer, "All tests successful.\n", 'cat meows' ); 668} 669 670# catches "exec accumulates arguments" issue (r77) 671{ 672 my $capture = IO::c55Capture->new_handle; 673 my $harness = TAP::Harness->new( 674 { verbosity => -2, 675 stdout => $capture, 676 exec => [$^X] 677 } 678 ); 679 680 _runtests( 681 $harness, 682 "$source_tests/harness_complain" 683 , # will get mad if run with args 684 "$source_tests/harness", 685 ); 686 687 my @output = tied($$capture)->dump; 688 my $status = pop @output; 689 like $status, qr{^Result: PASS$}, 690 '... and the status line should be correct'; 691 pop @output; # get rid of summary line 692 is( $output[-1], "All tests successful.\n", 693 'No exec accumulation' 694 ); 695} 696 697# customize default File source 698{ 699 my $capture = IO::c55Capture->new_handle; 700 my $harness = TAP::Harness->new( 701 { verbosity => -2, 702 stdout => $capture, 703 sources => { 704 File => { extensions => ['.1'] }, 705 }, 706 } 707 ); 708 709 _runtests( $harness, "$source_tests/source.1" ); 710 711 my @output = tied($$capture)->dump; 712 my $status = pop @output; 713 like $status, qr{^Result: PASS$}, 714 'customized File source has correct status line'; 715 pop @output; # get rid of summary line 716 my $answer = pop @output; 717 is( $answer, "All tests successful.\n", '... all tests passed' ); 718} 719 720# load a custom source 721{ 722 my $capture = IO::c55Capture->new_handle; 723 my $harness = TAP::Harness->new( 724 { verbosity => -2, 725 stdout => $capture, 726 sources => { 727 MyFileSourceHandler => { extensions => ['.1'] }, 728 }, 729 } 730 ); 731 732 my $source_test = "$source_tests/source.1"; 733 eval { _runtests( $harness, "$source_tests/source.1" ); }; 734 my $e = $@; 735 ok( !$e, 'no error on load custom source' ) || diag($e); 736 737 no warnings 'once'; 738 can_ok( 'MyFileSourceHandler', 'make_iterator' ); 739 ok( $MyFileSourceHandler::CAN_HANDLE, 740 '... MyFileSourceHandler->can_handle was called' 741 ); 742 ok( $MyFileSourceHandler::MAKE_ITER, 743 '... MyFileSourceHandler->make_iterator was called' 744 ); 745 746 my $raw_source = eval { ${ $MyFileSourceHandler::LAST_SOURCE->raw } }; 747 is( $raw_source, $source_test, '... used the right source' ); 748 749 my @output = tied($$capture)->dump; 750 my $status = pop(@output) || ''; 751 like $status, qr{^Result: PASS$}, '... and test has correct status line'; 752 pop @output; # get rid of summary line 753 my $answer = pop @output; 754 is( $answer, "All tests successful.\n", '... all tests passed' ); 755} 756 757sub trim { 758 $_[0] =~ s/^\s+|\s+$//g; 759 return $_[0]; 760} 761 762sub liblist { 763 return [ map {"-I$_"} @_ ]; 764} 765 766sub get_arg_sets { 767 768 # keys are keys to new() 769 return { 770 lib => { 771 in => 'lib', 772 out => liblist('lib'), 773 test_name => '... a single lib switch should be correct' 774 }, 775 verbosity => { 776 in => 1, 777 out => 1, 778 test_name => '... and we should be able to set verbosity to 1' 779 }, 780 781 # verbose => { 782 # in => 1, 783 # out => 1, 784 # test_name => '... and we should be able to set verbose to true' 785 # }, 786 }, 787 { lib => { 788 in => [ 'lib', 't' ], 789 out => liblist( 'lib', 't' ), 790 test_name => '... multiple lib dirs should be correct' 791 }, 792 verbosity => { 793 in => 0, 794 out => 0, 795 test_name => '... and we should be able to set verbosity to 0' 796 }, 797 798 # verbose => { 799 # in => 0, 800 # out => 0, 801 # test_name => '... and we should be able to set verbose to false' 802 # }, 803 }, 804 { switches => { 805 in => [ '-T', '-w', '-T' ], 806 out => [ '-T', '-w', '-T' ], 807 test_name => '... duplicate switches should remain', 808 }, 809 failures => { 810 in => 1, 811 out => 1, 812 test_name => 813 '... and we should be able to set failures to true', 814 }, 815 verbosity => { 816 in => -1, 817 out => -1, 818 test_name => '... and we should be able to set verbosity to -1' 819 }, 820 821 # quiet => { 822 # in => 1, 823 # out => 1, 824 # test_name => '... and we should be able to set quiet to false' 825 # }, 826 }, 827 828 { verbosity => { 829 in => -2, 830 out => -2, 831 test_name => '... and we should be able to set verbosity to -2' 832 }, 833 834 # really_quiet => { 835 # in => 1, 836 # out => 1, 837 # test_name => 838 # '... and we should be able to set really_quiet to true', 839 # }, 840 exec => { 841 in => $^X, 842 out => $^X, 843 test_name => 844 '... and we should be able to set the executable', 845 }, 846 }, 847 { switches => { 848 in => 'T', 849 out => ['T'], 850 test_name => 851 '... leading dashes (-) on switches are not optional', 852 }, 853 }, 854 { switches => { 855 in => '-T', 856 out => ['-T'], 857 test_name => '... we should be able to set switches', 858 }, 859 failures => { 860 in => 1, 861 out => 1, 862 test_name => '... and we should be able to set failures to true' 863 }, 864 }; 865} 866 867sub _runtests { 868 my ( $harness, @tests ) = @_; 869 local $ENV{PERL_TEST_HARNESS_DUMP_TAP} = 0; 870 my $aggregate = $harness->runtests(@tests); 871 return $aggregate; 872} 873 874{ 875 876 # coverage tests for ctor 877 878 my $harness = TAP::Harness->new( 879 { timer => 0, 880 errors => 1, 881 merge => 2, 882 883 # formatter => 3, 884 } 885 ); 886 887 is $harness->timer(), 0, 'timer getter'; 888 is $harness->timer(10), 10, 'timer setter'; 889 is $harness->errors(), 1, 'errors getter'; 890 is $harness->errors(10), 10, 'errors setter'; 891 is $harness->merge(), 2, 'merge getter'; 892 is $harness->merge(10), 10, 'merge setter'; 893 894 # jobs accessor 895 is $harness->jobs(), 1, 'jobs'; 896} 897 898{ 899 900# coverage tests for the stdout key of VALIDATON_FOR, used by _initialize() in the ctor 901 902 { 903 904 # ref $ref => false 905 my @die; 906 907 eval { 908 local $SIG{__DIE__} = sub { push @die, @_ }; 909 910 my $harness = TAP::Harness->new( 911 { stdout => bless {}, '0', # how evil is THAT !!! 912 } 913 ); 914 }; 915 916 is @die, 1, 'bad filehandle to stdout'; 917 like pop @die, qr/option 'stdout' needs a filehandle/, 918 '... and we died as expected'; 919 } 920 921 { 922 923 # ref => ! GLOB and ref->can(print) 924 925 package Printable; 926 927 sub new { return bless {}, shift } 928 929 sub print {return} 930 931 package main; 932 933 my $harness = TAP::Harness->new( 934 { stdout => Printable->new(), 935 } 936 ); 937 938 isa_ok $harness, 'TAP::Harness'; 939 } 940 941 { 942 943 # ref $ref => GLOB 944 945 my $harness = TAP::Harness->new( 946 { stdout => bless {}, 'GLOB', # again with the evil 947 } 948 ); 949 950 isa_ok $harness, 'TAP::Harness'; 951 } 952 953 { 954 955 # bare glob 956 957 my $harness = TAP::Harness->new( { stdout => *STDOUT } ); 958 959 isa_ok $harness, 'TAP::Harness'; 960 } 961 962 { 963 964 # string filehandle 965 966 my $string = ''; 967 open my $fh, ">", \$string or die $!; 968 my $harness = TAP::Harness->new( { stdout => $fh } ); 969 970 isa_ok $harness, 'TAP::Harness'; 971 } 972 973 { 974 975 # lexical filehandle reference 976 977 my $string = ''; 978 open my $fh, ">", \$string or die $!; 979 ok !eval { TAP::Harness->new( { stdout => \$fh } ); }; 980 like $@, qr/^option 'stdout' needs a filehandle /; 981 } 982} 983 984{ 985 986 # coverage testing of lib/switches accessor 987 my $harness = TAP::Harness->new; 988 989 my @die; 990 991 eval { 992 local $SIG{__DIE__} = sub { push @die, @_ }; 993 994 $harness->switches(qw( too many arguments)); 995 }; 996 997 is @die, 1, 'too many arguments to accessor'; 998 999 like pop @die, qr/Too many arguments to method 'switches'/, 1000 '...and we died as expected'; 1001 1002 $harness->switches('simple scalar'); 1003 1004 my $arrref = $harness->switches; 1005 is_deeply $arrref, ['simple scalar'], 'scalar wrapped in arr ref'; 1006} 1007 1008{ 1009 1010 # coverage tests for the basically untested T::H::_open_spool 1011 1012 my @spool = ( 't', 'spool' ); 1013 $ENV{PERL_TEST_HARNESS_DUMP_TAP} = File::Spec->catfile(@spool); 1014 1015# now given that we're going to be writing stuff to the file system, make sure we have 1016# a cleanup hook 1017 1018 END { 1019 use File::Path; 1020 1021 # remove the tree if we made it this far 1022 rmtree( $ENV{PERL_TEST_HARNESS_DUMP_TAP} ) 1023 if $ENV{PERL_TEST_HARNESS_DUMP_TAP}; 1024 } 1025 1026 my $harness = TAP::Harness->new( { verbosity => -2 } ); 1027 1028 can_ok $harness, 'runtests'; 1029 1030 # normal tests in verbose mode 1031 1032 my $parser 1033 = $harness->runtests( File::Spec->catfile( $source_tests, 'harness' ) ); 1034 1035 isa_ok $parser, 'TAP::Parser::Aggregator', 1036 '... runtests returns the aggregate'; 1037 1038 ok -e File::Spec->catfile( 1039 $ENV{PERL_TEST_HARNESS_DUMP_TAP}, 1040 $source_tests, 'harness' 1041 ); 1042} 1043 1044{ 1045 1046 # test name munging 1047 my @cases = ( 1048 { name => 'all the same', 1049 input => [ 'foo.t', 'bar.t', 'fletz.t' ], 1050 output => [ 1051 [ 'foo.t', 'foo.t' ], [ 'bar.t', 'bar.t' ], 1052 [ 'fletz.t', 'fletz.t' ] 1053 ], 1054 }, 1055 { name => 'all the same, already cooked', 1056 input => [ 'foo.t', [ 'bar.t', 'brip' ], 'fletz.t' ], 1057 output => [ 1058 [ 'foo.t', 'foo.t' ], [ 'bar.t', 'brip' ], 1059 [ 'fletz.t', 'fletz.t' ] 1060 ], 1061 }, 1062 { name => 'different exts', 1063 input => [ 'foo.t', 'bar.u', 'fletz.v' ], 1064 output => [ 1065 [ 'foo.t', 'foo.t' ], [ 'bar.u', 'bar.u' ], 1066 [ 'fletz.v', 'fletz.v' ] 1067 ], 1068 }, 1069 { name => 'different exts, one already cooked', 1070 input => [ 'foo.t', [ 'bar.u', 'bam' ], 'fletz.v' ], 1071 output => [ 1072 [ 'foo.t', 'foo.t' ], [ 'bar.u', 'bam' ], 1073 [ 'fletz.v', 'fletz.v' ] 1074 ], 1075 }, 1076 { name => 'different exts, two already cooked', 1077 input => [ 'foo.t', [ 'bar.u', 'bam.q' ], [ 'fletz.v', 'boo' ] ], 1078 output => [ 1079 [ 'foo.t', 'foo.t' ], [ 'bar.u', 'bam.q' ], 1080 [ 'fletz.v', 'boo' ] 1081 ], 1082 }, 1083 ); 1084 1085 for my $case (@cases) { 1086 is_deeply [ TAP::Harness->_add_descriptions( @{ $case->{input} } ) ], 1087 $case->{output}, '_add_descriptions: ' . $case->{name}; 1088 } 1089} 1090