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