Upgrade to Test-Harness-3.17
authorSteve Peters <steve@fisharerojo.org>
Sun, 7 Jun 2009 18:16:22 +0000 (13:16 -0500)
committerSteve Peters <steve@fisharerojo.org>
Sun, 7 Jun 2009 18:16:22 +0000 (13:16 -0500)
58 files changed:
MANIFEST
ext/Test-Harness/Changes
ext/Test-Harness/bin/prove
ext/Test-Harness/lib/App/Prove.pm
ext/Test-Harness/lib/App/Prove/State.pm
ext/Test-Harness/lib/App/Prove/State/Result.pm
ext/Test-Harness/lib/App/Prove/State/Result/Test.pm
ext/Test-Harness/lib/TAP/Base.pm
ext/Test-Harness/lib/TAP/Formatter/Base.pm
ext/Test-Harness/lib/TAP/Formatter/Color.pm
ext/Test-Harness/lib/TAP/Formatter/Console.pm
ext/Test-Harness/lib/TAP/Formatter/Console/ParallelSession.pm
ext/Test-Harness/lib/TAP/Formatter/Console/Session.pm
ext/Test-Harness/lib/TAP/Formatter/File.pm
ext/Test-Harness/lib/TAP/Formatter/File/Session.pm
ext/Test-Harness/lib/TAP/Formatter/Session.pm
ext/Test-Harness/lib/TAP/Harness.pm
ext/Test-Harness/lib/TAP/Object.pm
ext/Test-Harness/lib/TAP/Parser.pm
ext/Test-Harness/lib/TAP/Parser/Aggregator.pm
ext/Test-Harness/lib/TAP/Parser/Grammar.pm
ext/Test-Harness/lib/TAP/Parser/Iterator.pm
ext/Test-Harness/lib/TAP/Parser/Iterator/Array.pm
ext/Test-Harness/lib/TAP/Parser/Iterator/Process.pm
ext/Test-Harness/lib/TAP/Parser/Iterator/Stream.pm
ext/Test-Harness/lib/TAP/Parser/IteratorFactory.pm
ext/Test-Harness/lib/TAP/Parser/Multiplexer.pm
ext/Test-Harness/lib/TAP/Parser/Result.pm
ext/Test-Harness/lib/TAP/Parser/Result/Bailout.pm
ext/Test-Harness/lib/TAP/Parser/Result/Comment.pm
ext/Test-Harness/lib/TAP/Parser/Result/Plan.pm
ext/Test-Harness/lib/TAP/Parser/Result/Pragma.pm
ext/Test-Harness/lib/TAP/Parser/Result/Test.pm
ext/Test-Harness/lib/TAP/Parser/Result/Unknown.pm
ext/Test-Harness/lib/TAP/Parser/Result/Version.pm
ext/Test-Harness/lib/TAP/Parser/Result/YAML.pm
ext/Test-Harness/lib/TAP/Parser/ResultFactory.pm
ext/Test-Harness/lib/TAP/Parser/Scheduler.pm
ext/Test-Harness/lib/TAP/Parser/Scheduler/Job.pm
ext/Test-Harness/lib/TAP/Parser/Scheduler/Spinner.pm
ext/Test-Harness/lib/TAP/Parser/Source.pm
ext/Test-Harness/lib/TAP/Parser/Source/Perl.pm
ext/Test-Harness/lib/TAP/Parser/Utils.pm
ext/Test-Harness/lib/TAP/Parser/YAMLish/Reader.pm
ext/Test-Harness/lib/TAP/Parser/YAMLish/Writer.pm
ext/Test-Harness/lib/Test/Harness.pm
ext/Test-Harness/t/callbacks.t
ext/Test-Harness/t/compat/switches.t [new file with mode: 0644]
ext/Test-Harness/t/file.t
ext/Test-Harness/t/harness.t
ext/Test-Harness/t/multiplexer.t
ext/Test-Harness/t/parse.t
ext/Test-Harness/t/perl5lib.t
ext/Test-Harness/t/prove.t
ext/Test-Harness/t/proverc/emptyexec [new file with mode: 0644]
ext/Test-Harness/t/regression.t
ext/Test-Harness/t/sample-tests/zero_valid [new file with mode: 0644]
ext/Test-Harness/t/source_tests/harness_failure

index c6806b5..c4d43cf 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1290,6 +1290,7 @@ ext/Test-Harness/t/compat/inc-propagation.t               Test::Harness test
 ext/Test-Harness/t/compat/inc_taint.t                  Test::Harness test
 ext/Test-Harness/t/compat/nonumbers.t                  Test::Harness test
 ext/Test-Harness/t/compat/regression.t                 Test::Harness test
+ext/Test-Harness/t/compat/switches.t                   Test::Harness test
 ext/Test-Harness/t/compat/test-harness-compat.t                Test::Harness test
 ext/Test-Harness/t/compat/version.t                    Test::Harness test
 ext/Test-Harness/t/console.t                           Test::Harness test
@@ -1331,6 +1332,7 @@ ext/Test-Harness/t/perl5lib.t                             Test::Harness test
 ext/Test-Harness/t/premature-bailout.t                 Test::Harness test
 ext/Test-Harness/t/process.t                           Test::Harness test
 ext/Test-Harness/t/proveenv.t                          Test::Harness test
+ext/Test-Harness/t/proverc/emptyexec                   Test data for Test::Harness
 ext/Test-Harness/t/proverc.t                           Test::Harness test
 ext/Test-Harness/t/proverun.t                          Test::Harness test
 ext/Test-Harness/t/prove.t                             Test::Harness test
@@ -1390,6 +1392,7 @@ ext/Test-Harness/t/sample-tests/version_late              Test data for Test::Harness
 ext/Test-Harness/t/sample-tests/version_old            Test data for Test::Harness
 ext/Test-Harness/t/sample-tests/vms_nit                        Test data for Test::Harness
 ext/Test-Harness/t/sample-tests/with_comments          Test data for Test::Harness
+ext/Test-Harness/t/sample-tests/zero_valid             Test data for Test::Harness
 ext/Test-Harness/t/scheduler.t                         Test::Harness test
 ext/Test-Harness/t/source.t                            Test::Harness test
 ext/Test-Harness/t/source_tests/harness                        Test data for Test::Harness
index 44c04bd..6141f78 100644 (file)
@@ -1,5 +1,18 @@
 Revision history for Test-Harness
 
+3.17    2009-05-05
+        - Changed the 'failures' so that it is overridden by verbosity rather
+          than the other way around.
+        - Added the 'comments' option, most useful when used in conjunction
+          with the 'failures' option.
+        - Deprecated support for Perls earlier than 5.6.0.
+        - Allow '-I lib' as well as '-Ilib' in $Test::Harness::Switches
+          (regression).
+        - Restore old skip parsing semantics for TAP < v13. Refs #39031.
+        - Numerous small documentation fixes.
+        - Remove support for fork-based parallel testing. Multiplexed
+          parallel testing remains.
+
 3.16    2009-02-19
         - Fix path splicing on platforms where the path separator
           is not ':'.
index cde1b9b..a592a80 100644 (file)
@@ -31,7 +31,8 @@ Boolean options:
       --nocount     Disable the X/Y test count.
  -D   --dry         Dry run. Show test that would have run.
       --ext         Set the extension for tests (default '.t')
- -f,  --failures    Only show failed tests.
+ -f,  --failures    Show failed tests.
+ -o,  --comments    Show comments.
       --fork        Fork to run harness in multiple processes.
       --ignore-exit Ignore exit status from test scripts.
  -m,  --merge       Merge test scripts' STDERR with their STDOUT.
@@ -42,6 +43,7 @@ Boolean options:
  -p,  --parse       Show full list of TAP parse errors, if any.
       --directives  Only show results with TODO or SKIP directives.
       --timer       Print elapsed time after each test.
+      --normalize   Normalize TAP output in verbose output
  -T                 Enable tainting checks.
  -t                 Enable tainting warnings.
  -W                 Enable fatal warnings.
@@ -106,6 +108,10 @@ Color support requires L<Term::ANSIColor> on Unix-like platforms and
 L<Win32::Console> windows. If the necessary module is not installed
 colored output will not be available.
 
+=head2 Exit Code
+
+If the tests fail C<prove> will exit with non-zero status.
+
 =head2 Arguments to Tests
 
 It is possible to supply arguments to tests. To do so separate them from
@@ -248,6 +254,15 @@ The C<--state> switch may be used more than once.
 
     $ prove -b --state=hot --state=all,save
 
+=head2 @INC
+
+prove introduces a separation between "options passed to the perl which
+runs prove" and "options passed to the perl which runs tests"; this
+distinction is by design. Thus the perl which is running a test starts
+with the default C<@INC>. Additional library directories can be added
+via the C<PERL5LIB> environment variable, via -Ifoo in C<PERL5OPT> or
+via the C<-Ilib> option to F<prove>.
+
 =head2 Taint Mode
 
 Normally when a Perl program is run in taint mode the contents of the
index bc665fa..fd431ed 100644 (file)
@@ -17,11 +17,11 @@ App::Prove - Implements the C<prove> command.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
@@ -54,11 +54,12 @@ BEGIN {
     @ISA = qw(TAP::Object);
 
     @ATTR = qw(
-      archive argv blib show_count color directives exec failures fork
+      archive argv blib show_count color directives exec failures comments
       formatter harness includes modules plugins jobs lib merge parse quiet
       really_quiet recurse backwards shuffle taint_fail taint_warn timer
       verbose warnings_fail warnings_warn show_help show_man show_version
       state_class test_args state dry extension ignore_exit rules state_manager
+      normalize
     );
     __PACKAGE__->mk_methods(@ATTR);
 }
@@ -132,8 +133,9 @@ sub add_rc_file {
     local *RC;
     open RC, "<$rc_file" or croak "Can't read $rc_file ($!)";
     while ( defined( my $line = <RC> ) ) {
-        push @{ $self->{rc_opts} }, grep $_ && $_ !~ /^#/,
-          $line =~ m{ ' ([^']*) ' | " ([^"]*) " | (\#.*) | (\S*) }xg;
+        push @{ $self->{rc_opts} },
+          grep { defined and not /^#/ }
+          $line =~ m{ ' ([^']*) ' | " ([^"]*) " | (\#.*) | (\S+) }xg;
     }
     close RC;
 }
@@ -201,6 +203,7 @@ sub process_args {
         GetOptions(
             'v|verbose'   => \$self->{verbose},
             'f|failures'  => \$self->{failures},
+            'o|comments'  => \$self->{comments},
             'l|lib'       => \$self->{lib},
             'b|blib'      => \$self->{blib},
             's|shuffle'   => \$self->{shuffle},
@@ -215,7 +218,6 @@ sub process_args {
             'formatter=s' => \$self->{formatter},
             'r|recurse'   => \$self->{recurse},
             'reverse'     => \$self->{backwards},
-            'fork'        => \$self->{fork},
             'p|parse'     => \$self->{parse},
             'q|quiet'     => \$self->{quiet},
             'Q|QUIET'     => \$self->{really_quiet},
@@ -236,6 +238,7 @@ sub process_args {
             't'           => \$self->{taint_warn},
             'W'           => \$self->{warnings_fail},
             'w'           => \$self->{warnings_warn},
+            'normalize'   => \$self->{normalize},
             'rules=s@'    => $self->{rules},
         ) or croak('Unable to continue');
 
@@ -272,7 +275,7 @@ sub _help {
 sub _color_default {
     my $self = shift;
 
-    return -t STDOUT && !IS_WIN32;
+    return -t STDOUT && !$ENV{HARNESS_NOTTY} && !IS_WIN32;
 }
 
 sub _get_args {
@@ -299,10 +302,6 @@ sub _get_args {
         $args{jobs} = $jobs;
     }
 
-    if ( my $fork = $self->fork ) {
-        $args{fork} = $fork;
-    }
-
     if ( my $harness_opt = $self->harness ) {
         $self->require_harness( harness => $harness_opt );
     }
@@ -340,7 +339,7 @@ sub _get_args {
 
     $args{verbosity} = shift @verb_adj || 0;
 
-    for my $a (qw( merge failures timer directives )) {
+    for my $a (qw( merge failures comments timer directives normalize )) {
         $args{$a} = 1 if $self->$a();
     }
 
@@ -629,7 +628,7 @@ calling C<run>.
 
 =item C<failures>
 
-=item C<fork>
+=item C<comments>
 
 =item C<formatter>
 
index 6eef184..202f7aa 100644 (file)
@@ -26,11 +26,11 @@ App::Prove::State - State storage for the C<prove> command.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
@@ -146,7 +146,13 @@ sub commit {
 
 =head3 C<apply_switch>
 
-Apply a list of switch options to the state.
+ $self->apply_switch('failed,save');
+
+Apply a list of switch options to the state, updating the internal
+object state as a result. Nothing is returned.
+
+Diagnostics:
+    - "Illegal state option: %s"
 
 =over
 
@@ -271,6 +277,7 @@ sub apply_switch {
           || croak "Illegal state option: $opt";
         $code->($arg);
     }
+    return;
 }
 
 sub _select {
index a087da4..274676a 100644 (file)
@@ -14,11 +14,11 @@ App::Prove::State::Result - Individual test suite results.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index 4744086..231f789 100644 (file)
@@ -10,11 +10,11 @@ App::Prove::State::Result::Test - Individual test results.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index 762d93d..f88ad11 100644 (file)
@@ -14,18 +14,16 @@ and L<TAP::Harness>
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
-my $GOT_TIME_HIRES;
-
-BEGIN {
+use constant GOT_TIME_HIRES => do {
     eval 'use Time::HiRes qw(time);';
-    $GOT_TIME_HIRES = $@ ? 0 : 1;
-}
+    $@ ? 0 : 1;
+};
 
 =head1 SYNOPSIS
 
@@ -126,6 +124,6 @@ Return true if the time returned by get_time is high resolution (i.e. if Time::H
 
 =cut
 
-sub time_is_hires { return $GOT_TIME_HIRES }
+sub time_is_hires { return GOT_TIME_HIRES }
 
 1;
index 704cfad..f2b54a9 100644 (file)
@@ -15,8 +15,10 @@ BEGIN {
     %VALIDATION_FOR = (
         directives => sub { shift; shift },
         verbosity  => sub { shift; shift },
+        normalize  => sub { shift; shift },
         timer      => sub { shift; shift },
         failures   => sub { shift; shift },
+        comments   => sub { shift; shift },
         errors     => sub { shift; shift },
         color      => sub { shift; shift },
         jobs       => sub { shift; shift },
@@ -45,11 +47,11 @@ TAP::Formatter::Console - Harness output delegate for default console output
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
@@ -132,7 +134,11 @@ Append run time for each test to output. Uses L<Time::HiRes> if available.
 
 =item * C<failures>
 
-Only show test failures (this is a no-op if C<verbose> is selected).
+Show test failures (this is a no-op if C<verbose> is selected).
+
+=item * C<comments>
+
+Show test comments (this is a no-op if C<verbose> is selected).
 
 =item * C<quiet>
 
@@ -157,7 +163,7 @@ true:
 =item * C<directives>
 
 If set to a true value, only test results with directives will be displayed.
-This overrides other settings such as C<verbose> or C<failures>.
+This overrides other settings such as C<verbose>, C<failures>, or C<comments>.
 
 =item * C<stdout>
 
@@ -242,6 +248,11 @@ sub open_test {
     die "Unimplemented.";
 }
 
+sub _output_success {
+    my ( $self, $msg ) = @_;
+    $self->_output($msg);
+}
+
 =head3 C<summary>
 
   $harness->summary( $aggregate );
@@ -272,7 +283,7 @@ sub summary {
     # the exit status is nonzero
 
     if ( $aggregate->all_passed ) {
-        $self->_output("All tests successful.\n");
+        $self->_output_success("All tests successful.\n");
     }
 
     # ~TODO option where $aggregate->skipped generates reports
index 36a5b16..349d3b8 100644 (file)
@@ -71,11 +71,11 @@ TAP::Formatter::Color - Run Perl test scripts with color
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index 71cad30..aeca2f2 100644 (file)
@@ -14,11 +14,11 @@ TAP::Formatter::Console - Harness output delegate for default console output
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
@@ -70,6 +70,13 @@ sub _set_colors {
     }
 }
 
+sub _output_success {
+    my ( $self, $msg ) = @_;
+    $self->_set_colors('green');
+    $self->_output($msg);
+    $self->_set_colors('reset');
+}
+
 sub _failure_output {
     my $self = shift;
     $self->_set_colors('red');
index dcee635..b6b5134 100644 (file)
@@ -42,11 +42,11 @@ TAP::Formatter::Console::ParallelSession - Harness output delegate for parallel
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index 129f388..675512c 100644 (file)
@@ -28,11 +28,11 @@ TAP::Formatter::Console::Session - Harness output delegate for default console o
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
@@ -71,11 +71,11 @@ sub _get_output_result {
                 last;
             }
         }
-        $formatter->_output( $result->as_string );
+        $formatter->_output( $self->_format_for_output($result) );
         $formatter->_set_colors('reset');
       }
       : sub {
-        $formatter->_output( shift->as_string );
+        $formatter->_output( $self->_format_for_output(shift) );
       };
 }
 
@@ -92,6 +92,7 @@ sub _closures {
     my $verbose      = $formatter->verbose;
     my $directives   = $formatter->directives;
     my $failures     = $formatter->failures;
+    my $comments     = $formatter->comments;
 
     my $output_result = $self->_get_output_result;
 
@@ -146,9 +147,10 @@ sub _closures {
             }
 
             if (!$quiet
-                && (   ( $verbose && !$failures )
+                && (   $verbose
                     || ( $is_test && $failures && !$result->is_ok )
-                    || ( $result->has_directive && $directives ) )
+                    || ( $comments   && $result->is_comment )
+                    || ( $directives && $result->has_directive ) )
               )
             {
                 unless ($newline_printed) {
index 142fbc9..8514bc0 100644 (file)
@@ -15,11 +15,11 @@ TAP::Formatter::File - Harness output delegate for file output
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index 1448770..c6abfd6 100644 (file)
@@ -13,11 +13,11 @@ TAP::Formatter::File::Session - Harness output delegate for file output
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
@@ -52,12 +52,13 @@ sub result {
     }
 
     if (!$formatter->quiet
-        && (   ( $formatter->verbose && !$formatter->failures )
+        && (   $formatter->verbose
             || ( $result->is_test && $formatter->failures && !$result->is_ok )
+            || ( $formatter->comments   && $result->is_comment )
             || ( $result->has_directive && $formatter->directives ) )
       )
     {
-        $self->{results} .= $result->as_string . "\n";
+        $self->{results} .= $self->_format_for_output($result) . "\n";
     }
 }
 
index a68e2a0..21767e5 100644 (file)
@@ -25,11 +25,11 @@ TAP::Formatter::Session - Abstract base class for harness output delegate
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 METHODS
 
@@ -113,7 +113,15 @@ sub clear_for_close { }
 
 sub _should_show_count {
     my $self = shift;
-    return !$self->formatter->verbose && -t $self->formatter->stdout;
+    return
+         !$self->formatter->verbose
+      && -t $self->formatter->stdout
+      && !$ENV{HARNESS_NOTTY};
+}
+
+sub _format_for_output {
+    my ( $self, $result ) = @_;
+    return $self->formatter->normalize ? $result->as_string : $result->raw;
 }
 
 sub _output_test_failure {
index 1512969..749e7af 100644 (file)
@@ -19,11 +19,11 @@ TAP::Harness - Run test scripts with statistics
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 $ENV{HARNESS_ACTIVE}  = 1;
 $ENV{HARNESS_VERSION} = $VERSION;
@@ -60,7 +60,8 @@ sub _error {
 BEGIN {
 
     @FORMATTER_ARGS = qw(
-      directives verbosity timer failures errors stdout color show_count
+      directives verbosity timer failures comments errors stdout color
+      show_count normalize
     );
 
     %VALIDATION_FOR = (
@@ -80,7 +81,6 @@ BEGIN {
         scheduler_class   => sub { shift; shift },
         formatter         => sub { shift; shift },
         jobs              => sub { shift; shift },
-        fork              => sub { shift; shift },
         test_args         => sub { shift; shift },
         ignore_exit       => sub { shift; shift },
         rules             => sub { shift; shift },
@@ -133,7 +133,7 @@ BEGIN {
 
  my %args = (
     verbosity => 1,
-    lib     => [ 'lib', 'blib/lib' ],
+    lib     => [ 'lib', 'blib/lib', 'blib/arch' ],
  )
  my $harness = TAP::Harness->new( \%args );
 
@@ -160,12 +160,20 @@ available.
 
 =item * C<failures>
 
-Only show test failures (this is a no-op if C<verbose> is selected).
+Show test failures (this is a no-op if C<verbose> is selected).
+
+=item * C<comments>
+
+Show test comments (this is a no-op if C<verbose> is selected).
 
 =item * C<show_count>
 
 Update the running test count during testing.
 
+=item * C<normalize>
+
+Set to a true value to normalize the TAP that is emitted in verbose modes.
+
 =item * C<lib>
 
 Accepts a scalar value or array ref of scalar values indicating which
@@ -213,6 +221,9 @@ TAP::Harness will fall back on executing the test script in Perl:
           if $test_file =~ /[.]rb$/;
       }
 
+If the subroutine returns a scalar with a newline or a filehandle, it
+will be interpreted as raw TAP or as a TAP stream, respectively.
+
 =item * C<merge>
 
 If C<merge> is true the harness will create parsers that merge STDOUT
@@ -274,12 +285,6 @@ The maximum number of parallel tests to run at any time.  Which tests
 can be run in parallel is controlled by C<rules>.  The default is to
 run only one test at a time.
 
-=item * C<fork>
-
-If true the harness will attempt to fork and run the parser for each
-test in a separate process. Currently this option requires
-L<Parallel::Iterator> to be installed.
-
 =item * C<rules>
 
 A reference to a hash of rules that control which tests may be
@@ -349,7 +354,7 @@ Any keys for which the value is C<undef> will be ignored.
         $self->jobs(1) unless defined $self->jobs;
 
         local $default_class{formatter_class} = 'TAP::Formatter::File'
-          unless -t ( $arg_for{stdout} || \*STDOUT );
+          unless -t ( $arg_for{stdout} || \*STDOUT ) && !$ENV{HARNESS_NOTTY};
 
         while ( my ( $attr, $class ) = each %default_class ) {
             $self->$attr( $self->$attr() || $class );
@@ -448,47 +453,6 @@ sub _after_test {
     $aggregate->add( $job->description, $parser );
 }
 
-sub _aggregate_forked {
-    my ( $self, $aggregate, $scheduler ) = @_;
-
-    eval { require Parallel::Iterator };
-
-    croak "Parallel::Iterator required for --fork option ($@)"
-      if $@;
-
-    my $iter = Parallel::Iterator::iterate(
-        { workers => $self->jobs || 0 },
-        sub {
-            my $job = shift;
-
-            return if $job->is_spinner;
-
-            my ( $parser, $session ) = $self->make_parser($job);
-
-            while ( defined( my $result = $parser->next ) ) {
-                $self->_bailout($result) if $result->is_bailout;
-            }
-
-            $self->finish_parser( $parser, $session );
-
-            # Can't serialise coderefs...
-            delete $parser->{_iter};
-            delete $parser->{_stream};
-            delete $parser->{_grammar};
-            return $parser;
-        },
-        sub { $scheduler->get_job }
-    );
-
-    while ( my ( $job, $parser ) = $iter->() ) {
-        next if $job->is_spinner;
-        $self->_after_test( $aggregate, $job, $parser );
-        $job->finish;
-    }
-
-    return;
-}
-
 sub _bailout {
     my ( $self, $result ) = @_;
     my $explanation = $result->explanation;
@@ -629,12 +593,7 @@ sub aggregate_tests {
     $self->formatter->prepare( map { $_->description } $scheduler->get_all );
 
     if ( $self->jobs > 1 ) {
-        if ( $self->fork ) {
-            $self->_aggregate_forked( $aggregate, $scheduler );
-        }
-        else {
-            $self->_aggregate_parallel( $aggregate, $scheduler );
-        }
+        $self->_aggregate_parallel( $aggregate, $scheduler );
     }
     else {
         $self->_aggregate_single( $aggregate, $scheduler );
@@ -676,12 +635,6 @@ Gets or sets the number of concurrent test runs the harness is
 handling.  By default, this value is 1 -- for parallel testing, this
 should be set higher.
 
-=head3 C<fork>
-
-If true the harness will attempt to fork and run the parser for each
-test in a separate process. Currently this option requires
-L<Parallel::Iterator> to be installed.
-
 =cut
 
 ##############################################################################
@@ -752,7 +705,12 @@ sub _get_parser_args {
           = ref $exec eq 'CODE'
           ? $exec->( $self, $test_prog )
           : [ @$exec, $test_prog ];
-        $args{source} = $test_prog unless $args{exec};
+        if ( not defined $args{exec} ) {
+            $args{source} = $test_prog;
+        }
+        elsif ( ( ref( $args{exec} ) || "" ) ne "ARRAY" ) {
+            $args{source} = delete $args{exec};
+        }
     }
     else {
         $args{source} = $test_prog;
index b57d32e..498bb80 100644 (file)
@@ -9,11 +9,11 @@ TAP::Object - Base class that provides common functionality to all C<TAP::*> mod
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 2393418..ea3acd9 100644 (file)
@@ -20,11 +20,11 @@ TAP::Parser - Parse L<TAP|Test::Harness::TAP> output
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 my $DEFAULT_TAP_VERSION = 12;
 my $MAX_TAP_VERSION     = 13;
@@ -448,7 +448,11 @@ sub _iterator_for_source {
             $stream = $source->get_stream($self);
         }
         elsif ($source) {
-            if ( ref $source ) {
+            if ( $source =~ /\n/ ) {
+                $stream
+                  = $self->_iterator_for_source( [ split "\n" => $source ] );
+            }
+            elsif ( ref $source ) {
                 $stream = $self->_iterator_for_source($source);
             }
             elsif ( -e $source ) {
@@ -1197,7 +1201,7 @@ sub _make_state_table {
                     }
                 }
 
-                if ($number) {
+                if ( defined $number ) {
                     if ( $number != $tests_run ) {
                         my $count = $tests_run;
                         $self->_add_error( "Tests out of sequence.  Found "
@@ -1421,7 +1425,7 @@ sub _iter {
             }
             else {
                 $result = $end_handler->();
-                $self->_make_callback( 'EOF', $result )
+                $self->_make_callback( 'EOF', $self )
                   unless defined $result;
             }
 
index 2adc6e5..10b37ef 100644 (file)
@@ -14,11 +14,11 @@ TAP::Parser::Aggregator - Aggregate TAP::Parser results
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 7ea1d03..44f28a0 100644 (file)
@@ -15,11 +15,11 @@ TAP::Parser::Grammar - A grammar for the Test Anything Protocol.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
@@ -105,7 +105,7 @@ my %language_for;
                     $skip = 'SKIP';
 
                     # If we can't match # SKIP the directive should be undef.
-                    ($explanation) = $tail =~ /^#\s*SKIP\s+(.*)/i;
+                    ($explanation) = $tail =~ /^#\s*SKIP\S*\s+(.*)/i;
                 }
                 elsif ( $tail !~ /^\s*$/ ) {
                     return $self->_make_unknown_token($line);
index b66e2e1..09d40be 100644 (file)
@@ -13,11 +13,11 @@ TAP::Parser::Iterator - Internal base class for TAP::Parser Iterators
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 9d7e2c2..1513d5b 100644 (file)
@@ -13,11 +13,11 @@ TAP::Parser::Iterator::Array - Internal TAP::Parser array Iterator
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 027de0c..a0a5a8e 100644 (file)
@@ -17,11 +17,11 @@ TAP::Parser::Iterator::Process - Internal TAP::Parser Iterator
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 3ed2534..c92cbab 100644 (file)
@@ -13,11 +13,11 @@ TAP::Parser::Iterator::Stream - Internal TAP::Parser Iterator
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 5186df1..064d7be 100644 (file)
@@ -16,11 +16,11 @@ TAP::Parser::IteratorFactory - Internal TAP::Parser Iterator
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 94761bc..2e5d929 100644 (file)
@@ -18,11 +18,11 @@ TAP::Parser::Multiplexer - Multiplex multiple TAP::Parsers
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 8e3497b..b01e95c 100644 (file)
@@ -26,11 +26,11 @@ TAP::Parser::Result - Base class for TAP::Parser output objects
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index f80ea29..3e42f41 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Result::Bailout - Bailout result token.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index d07e1d2..1e9ba13 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Result::Comment - Comment result token.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index a577212..67c01df 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Result::Plan - Plan result token.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index df7a4fd..3eb62b3 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Result::Pragma - TAP pragma token.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index 7431769..11cf302 100644 (file)
@@ -14,11 +14,11 @@ TAP::Parser::Result::Test - Test result token.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index f0ed6e3..52e1958 100644 (file)
@@ -14,11 +14,11 @@ TAP::Parser::Result::Unknown - Unknown result token.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index d666091..b97681e 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Result::Version - TAP syntax version token.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index 0dcc95b..ada3ae4 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Result::YAML - YAML result token.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 DESCRIPTION
 
index 10deb63..46d0df2 100644 (file)
@@ -30,11 +30,11 @@ TAP::Parser::ResultFactory - Factory for creating TAP::Parser output objects
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head2 DESCRIPTION
 
index 0320d19..f181709 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Scheduler - Schedule tests during parallel testing
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 8003fc0..7ab68f9 100644 (file)
@@ -10,11 +10,11 @@ TAP::Parser::Scheduler::Job - A single testing job.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 53cfc92..10af5e3 100644 (file)
@@ -10,11 +10,11 @@ TAP::Parser::Scheduler::Spinner - A no-op job.
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index c04adcf..9263e9e 100644 (file)
@@ -17,11 +17,11 @@ TAP::Parser::Source - Stream output from some source
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 2a2586e..1f4f2e1 100644 (file)
@@ -18,11 +18,11 @@ TAP::Parser::Source::Perl - Stream Perl output
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 8aabd21..a3d2dd1 100644 (file)
@@ -13,11 +13,11 @@ TAP::Parser::Utils - Internal TAP::Parser utilities
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 =head1 SYNOPSIS
 
index 9eba0c3..524d7dc 100644 (file)
@@ -6,7 +6,7 @@ use vars qw($VERSION @ISA);
 use TAP::Object ();
 
 @ISA     = 'TAP::Object';
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 # TODO:
 #   Handle blessed object syntax
@@ -270,7 +270,7 @@ TAP::Parser::YAMLish::Reader - Read YAMLish data from iterator
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =head1 SYNOPSIS
 
index 6c2e636..ed81f6d 100644 (file)
@@ -6,7 +6,7 @@ use vars qw($VERSION @ISA);
 use TAP::Object ();
 
 @ISA     = 'TAP::Object';
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 my $ESCAPE_CHAR = qr{ [ \x00-\x1f \" ] }x;
 my $ESCAPE_KEY  = qr{ (?: ^\W ) | $ESCAPE_CHAR }x;
@@ -147,7 +147,7 @@ TAP::Parser::YAMLish::Writer - Write YAMLish data
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =head1 SYNOPSIS
 
index 5a7a5ea..eba3c5e 100644 (file)
@@ -44,11 +44,11 @@ Test::Harness - Run Perl standard test scripts with statistics
 
 =head1 VERSION
 
-Version 3.16
+Version 3.17
 
 =cut
 
-$VERSION = '3.16';
+$VERSION = '3.17';
 
 # Backwards compatibility for exportable variable names.
 *verbose  = *Verbose;
@@ -207,9 +207,10 @@ sub _new_harness {
     my $sub_args = shift || {};
 
     my ( @lib, @switches );
-    for my $opt ( split_shell( $Switches, $ENV{HARNESS_PERL_SWITCHES} ) ) {
+    my @opt = split_shell( $Switches, $ENV{HARNESS_PERL_SWITCHES} );
+    while ( my $opt = shift @opt ) {
         if ( $opt =~ /^ -I (.*) $ /x ) {
-            push @lib, $1;
+            push @lib, length($1) ? $1 : shift @opt;
         }
         else {
             push @switches, $opt;
@@ -240,9 +241,6 @@ sub _new_harness {
             if ( $opt =~ /^j(\d*)$/ ) {
                 $args->{jobs} = $1 || 9;
             }
-            elsif ( $opt eq 'f' ) {
-                $args->{fork} = 1;
-            }
             elsif ( $opt eq 'c' ) {
                 $args->{color} = 1;
             }
index 9d0cae4..18c6f0d 100644 (file)
@@ -68,7 +68,8 @@ my $end  = 0;
         $plan_output = $plan->as_string;
     },
     EOF => sub {
-        $end = 1 if $all == 8;
+        my $p = shift;
+        $end = 1 if $all == 8 and $p->isa('TAP::Parser');
     },
     ELSE => sub {
         $else++;
diff --git a/ext/Test-Harness/t/compat/switches.t b/ext/Test-Harness/t/compat/switches.t
new file mode 100644 (file)
index 0000000..42b16c8
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Test::More (
+    $^O eq 'VMS'
+    ? ( skip_all => 'VMS' )
+    : ( tests => 4 )
+);
+
+use Test::Harness;
+
+for my $switch ( '-Ifoo', '-I foo' ) {
+    $Test::Harness::Switches = $switch;
+    ok my $harness = Test::Harness::_new_harness, 'made harness';
+    is_deeply [ $harness->lib ], ['-Ifoo'], 'got libs';
+}
+
index 68ad045..40793c3 100644 (file)
@@ -23,7 +23,7 @@ my $source_tests
 my $sample_tests
   = $ENV{PERL_CORE} ? '../ext/Test-Harness/t/sample-tests' : 't/sample-tests';
 
-plan tests => 41;
+plan tests => 56;
 
 # note that this test will always pass when run through 'prove'
 ok $ENV{HARNESS_ACTIVE},  'HARNESS_ACTIVE env variable should be set';
@@ -42,11 +42,24 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
             trim($_)
           } map { split /\n/ } @_;
     };
-    my $harness            = TAP::Harness->new( { verbosity  => 1 } );
+
+    # Make sure verbosity 1 overrides failures and comments.
+    my $harness = TAP::Harness->new(
+        {   verbosity => 1,
+            failures  => 1,
+            comments  => 1,
+        }
+    );
     my $harness_whisper    = TAP::Harness->new( { verbosity  => -1 } );
     my $harness_mute       = TAP::Harness->new( { verbosity  => -2 } );
     my $harness_directives = TAP::Harness->new( { directives => 1 } );
     my $harness_failures   = TAP::Harness->new( { failures   => 1 } );
+    my $harness_comments   = TAP::Harness->new( { comments   => 1 } );
+    my $harness_fandc      = TAP::Harness->new(
+        {   failures => 1,
+            comments => 1
+        }
+    );
 
     can_ok $harness, 'runtests';
 
@@ -71,7 +84,7 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     my $summary          = pop @output;
     my $expected_summary = qr{^Files=1, Tests=1,  \d+ wallclock secs};
 
-    is_deeply \@output, \@expected, '... and the output should be correct';
+    is_deeply \@output, \@expected, '... the output should be correct';
     like $status, $expected_status,
       '... and the status line should be correct';
     like $summary, $expected_summary,
@@ -82,7 +95,7 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     @output = ();
     ok $aggregate
       = _runtests( $harness, [ "$source_tests/harness", 'My Nice Test' ] ),
-      '... runtests returns the aggregate';
+      'runtests returns the aggregate';
 
     isa_ok $aggregate, 'TAP::Parser::Aggregator';
 
@@ -100,7 +113,7 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     $summary          = pop @output;
     $expected_summary = qr{^Files=1, Tests=1,  \d+ wallclock secs};
 
-    is_deeply \@output, \@expected, '... and the output should be correct';
+    is_deeply \@output, \@expected, '... the output should be correct';
     like $status, $expected_status,
       '... and the status line should be correct';
     like $summary, $expected_summary,
@@ -113,7 +126,7 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
         $harness, [ "$source_tests/harness", 'My Nice Test' ],
         [ "$source_tests/harness", 'My Nice Test Again' ]
       ),
-      '... runtests returns the aggregate';
+      'runtests labels returns the aggregate';
 
     isa_ok $aggregate, 'TAP::Parser::Aggregator';
 
@@ -135,7 +148,7 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     $summary          = pop @output;
     $expected_summary = qr{^Files=2, Tests=2,  \d+ wallclock secs};
 
-    is_deeply \@output, \@expected, '... and the output should be correct';
+    is_deeply \@output, \@expected, '... the output should be correct';
     like $status, $expected_status,
       '... and the status line should be correct';
     like $summary, $expected_summary,
@@ -144,7 +157,8 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     # normal tests in quiet mode
 
     @output = ();
-    _runtests( $harness_whisper, "$source_tests/harness" );
+    ok _runtests( $harness_whisper, "$source_tests/harness" ),
+      'Run tests with whisper';
 
     chomp(@output);
     @expected = (
@@ -157,7 +171,7 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     $summary          = pop @output;
     $expected_summary = qr/^Files=1, Tests=1,  \d+ wallclock secs/;
 
-    is_deeply \@output, \@expected, '... and the output should be correct';
+    is_deeply \@output, \@expected, '... the output should be correct';
     like $status, $expected_status,
       '... and the status line should be correct';
     like $summary, $expected_summary,
@@ -166,7 +180,7 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     # normal tests in really_quiet mode
 
     @output = ();
-    _runtests( $harness_mute, "$source_tests/harness" );
+    ok _runtests( $harness_mute, "$source_tests/harness" ), 'Run tests mute';
 
     chomp(@output);
     @expected = (
@@ -178,7 +192,7 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     $summary          = pop @output;
     $expected_summary = qr/^Files=1, Tests=1,  \d+ wallclock secs/;
 
-    is_deeply \@output, \@expected, '... and the output should be correct';
+    is_deeply \@output, \@expected, '... the output should be correct';
     like $status, $expected_status,
       '... and the status line should be correct';
     like $summary, $expected_summary,
@@ -187,22 +201,26 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     # normal tests with failures
 
     @output = ();
-    _runtests( $harness, "$source_tests/harness_failure" );
+    ok _runtests( $harness, "$source_tests/harness_failure" ),
+      'Run tests with failures';
 
     $status  = pop @output;
     $summary = pop @output;
 
-    like $status, qr{^Result: FAIL$},
-      '... and the status line should be correct';
+    like $status, qr{^Result: FAIL$}, '... the status line should be correct';
 
-    my @summary = @output[ 5 .. $#output ];
-    @output = @output[ 0 .. 4 ];
+    my @summary = @output[ 9 .. $#output ];
+    @output = @output[ 0 .. 8 ];
 
     @expected = (
         "$source_tests/harness_failure ..",
         '1..2',
         'ok 1 - this is a test',
         'not ok 2 - this is another test',
+        q{#   Failed test 'this is another test'},
+        '#   in harness_failure.t at line 5.',
+        q{#          got: 'waffle'},
+        q{#     expected: 'yarblokos'},
         'Failed 1/2 subtests',
     );
 
@@ -223,7 +241,8 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     # quiet tests with failures
 
     @output = ();
-    _runtests( $harness_whisper, "$source_tests/harness_failure" );
+    ok _runtests( $harness_whisper, "$source_tests/harness_failure" ),
+      'Run whisper tests with failures';
 
     $status   = pop @output;
     $summary  = pop @output;
@@ -237,8 +256,7 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
         '2',
     );
 
-    like $status, qr{^Result: FAIL$},
-      '... and the status line should be correct';
+    like $status, qr{^Result: FAIL$}, '... the status line should be correct';
 
     is_deeply \@output, \@expected,
       '... and failing test output should be correct';
@@ -246,7 +264,8 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     # really quiet tests with failures
 
     @output = ();
-    _runtests( $harness_mute, "$source_tests/harness_failure" );
+    ok _runtests( $harness_mute, "$source_tests/harness_failure" ),
+      'Run mute tests with failures';
 
     $status   = pop @output;
     $summary  = pop @output;
@@ -258,8 +277,7 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
         '2',
     );
 
-    like $status, qr{^Result: FAIL$},
-      '... and the status line should be correct';
+    like $status, qr{^Result: FAIL$}, '... the status line should be correct';
 
     is_deeply \@output, \@expected,
       '... and failing test output should be correct';
@@ -267,10 +285,11 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     # only show directives
 
     @output = ();
-    _runtests(
+    ok _runtests(
         $harness_directives,
         "$source_tests/harness_directives"
-    );
+      ),
+      'Run tests with directives';
 
     chomp(@output);
 
@@ -294,7 +313,7 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     $summary          = pop @output;
     $expected_summary = qr/^Files=1, Tests=3,  \d+ wallclock secs/;
 
-    is_deeply \@output, \@expected, '... and the output should be correct';
+    is_deeply \@output, \@expected, '... the output should be correct';
     like $summary, $expected_summary,
       '... and the report summary should look correct';
 
@@ -304,7 +323,8 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     # normal tests with bad tap
 
     @output = ();
-    _runtests( $harness, "$source_tests/harness_badtap" );
+    ok _runtests( $harness, "$source_tests/harness_badtap" ),
+      'Run tests with bad TAP';
     chomp(@output);
 
     @output   = map { trim($_) } @output;
@@ -320,7 +340,7 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
         'Failed 1/2 subtests',
     );
     is_deeply \@output, \@expected,
-      '... and failing test output should be correct';
+      '... failing test output should be correct';
     like $status, qr{^Result: FAIL$},
       '... and the status line should be correct';
     @expected_summary = (
@@ -338,7 +358,8 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     # only show failures
 
     @output = ();
-    _runtests( $harness_failures, "$source_tests/harness_failure" );
+    ok _runtests( $harness_failures, "$source_tests/harness_failure" ),
+      'Run tests with failures only';
 
     chomp(@output);
 
@@ -356,15 +377,15 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     $status  = pop @output;
     $summary = pop @output;
 
-    like $status, qr{^Result: FAIL$},
-      '... and the status line should be correct';
+    like $status, qr{^Result: FAIL$}, '... the status line should be correct';
     $expected_summary = qr/^Files=1, Tests=2,  \d+ wallclock secs/;
     is_deeply \@output, \@expected, '... and the output should be correct';
 
     # check the status output for no tests
 
     @output = ();
-    _runtests( $harness_failures, "$sample_tests/no_output" );
+    ok _runtests( $harness_failures, "$sample_tests/no_output" ),
+      'Run tests with failures';
 
     chomp(@output);
 
@@ -380,8 +401,68 @@ ok $ENV{HARNESS_VERSION}, 'HARNESS_VERSION env variable should be set';
     $status  = pop @output;
     $summary = pop @output;
 
-    like $status, qr{^Result: FAIL$},
-      '... and the status line should be correct';
+    like $status, qr{^Result: FAIL$}, '... the status line should be correct';
+    $expected_summary = qr/^Files=1, Tests=2,  \d+ wallclock secs/;
+    is_deeply \@output, \@expected, '... and the output should be correct';
+
+    # coverage testing for _should_show_comments
+    # only show comments
+
+    @output = ();
+    ok _runtests( $harness_comments, "$source_tests/harness_failure" ),
+      'Run tests with comments';
+    chomp(@output);
+
+    @expected = (
+        "$source_tests/harness_failure ..",
+        q{#   Failed test 'this is another test'},
+        '#   in harness_failure.t at line 5.',
+        q{#          got: 'waffle'},
+        q{#     expected: 'yarblokos'},
+        'Failed 1/2 subtests',
+        'Test Summary Report',
+        '-------------------',
+        "$source_tests/harness_failure (Wstat: 0 Tests: 2 Failed: 1)",
+        'Failed test:',
+        '2',
+    );
+
+    $status  = pop @output;
+    $summary = pop @output;
+
+    like $status, qr{^Result: FAIL$}, '... the status line should be correct';
+    $expected_summary = qr/^Files=1, Tests=2,  \d+ wallclock secs/;
+    is_deeply \@output, \@expected, '... and the output should be correct';
+
+    # coverage testing for _should_show_comments and _should_show_failures
+    # only show comments and failures
+
+    @output = ();
+    $ENV{FOO} = 1;
+    ok _runtests( $harness_fandc, "$source_tests/harness_failure" ),
+      'Run tests with failures and comments';
+    delete $ENV{FOO};
+    chomp(@output);
+
+    @expected = (
+        "$source_tests/harness_failure ..",
+        'not ok 2 - this is another test',
+        q{#   Failed test 'this is another test'},
+        '#   in harness_failure.t at line 5.',
+        q{#          got: 'waffle'},
+        q{#     expected: 'yarblokos'},
+        'Failed 1/2 subtests',
+        'Test Summary Report',
+        '-------------------',
+        "$source_tests/harness_failure (Wstat: 0 Tests: 2 Failed: 1)",
+        'Failed test:',
+        '2',
+    );
+
+    $status  = pop @output;
+    $summary = pop @output;
+
+    like $status, qr{^Result: FAIL$}, '... the status line should be correct';
     $expected_summary = qr/^Files=1, Tests=2,  \d+ wallclock secs/;
     is_deeply \@output, \@expected, '... and the output should be correct';
 
index c9f835a..3a6dc03 100644 (file)
@@ -24,7 +24,7 @@ my $source_tests
 my $sample_tests
   = $ENV{PERL_CORE} ? '../ext/Test-Harness/t/sample-tests' : 't/sample-tests';
 
-plan tests => 113;
+plan tests => 119;
 
 # note that this test will always pass when run through 'prove'
 ok $ENV{HARNESS_ACTIVE},  'HARNESS_ACTIVE env variable should be set';
@@ -123,7 +123,9 @@ foreach my $test_args ( get_arg_sets() ) {
         'ok 1 - this is a test',
         '[[reset]]',
         'ok',
+        '[[green]]',
         'All tests successful.',
+        '[[reset]]',
     );
     my $status           = pop @output;
     my $expected_status  = qr{^Result: PASS$};
@@ -154,7 +156,9 @@ foreach my $test_args ( get_arg_sets() ) {
         'ok 1 - this is a test',
         '[[reset]]',
         'ok',
+        '[[green]]',
         'All tests successful.',
+        '[[reset]]',
     );
     $status           = pop @output;
     $expected_status  = qr{^Result: PASS$};
@@ -193,7 +197,9 @@ foreach my $test_args ( get_arg_sets() ) {
         'ok 1 - this is a test',
         '[[reset]]',
         'ok',
+        '[[green]]',
         'All tests successful.',
+        '[[reset]]',
     );
     $status           = pop @output;
     $expected_status  = qr{^Result: PASS$};
@@ -261,8 +267,8 @@ foreach my $test_args ( get_arg_sets() ) {
     like $status, qr{^Result: FAIL$},
       '... and the status line should be correct';
 
-    my @summary = @output[ 10 .. $#output ];
-    @output = @output[ 0 .. 9 ];
+    my @summary = @output[ 18 .. $#output ];
+    @output = @output[ 0 .. 17 ];
 
     @expected = (
         "$source_tests/harness_failure ..",
@@ -273,6 +279,14 @@ foreach my $test_args ( get_arg_sets() ) {
         '[[red]]',
         'not ok 2 - this is another test',
         '[[reset]]',
+        q{#   Failed test 'this is another test'},
+        '[[reset]]',
+        '#   in harness_failure.t at line 5.',
+        '[[reset]]',
+        q{#          got: 'waffle'},
+        '[[reset]]',
+        q{#     expected: 'yarblokos'},
+        '[[reset]]',
         '[[red]]',
         'Failed 1/2 subtests',
     );
@@ -565,6 +579,89 @@ SKIP: {
     is( $answer, "All tests successful.\n", 'cat meows' );
 }
 
+# Exec with a coderef that returns an arrayref
+SKIP: {
+    my $cat = '/bin/cat';
+    unless ( -e $cat ) {
+        skip "no '$cat'", 2;
+    }
+
+    my $capture = IO::c55Capture->new_handle;
+    my $harness = TAP::Harness->new(
+        {   verbosity => -2,
+            stdout    => $capture,
+            exec      => sub {
+                return [
+                    $cat,
+                    $ENV{PERL_CORE}
+                    ? '../ext/Test-Harness/t/data/catme.1'
+                    : 't/data/catme.1'
+                ];
+            },
+        }
+    );
+
+    _runtests( $harness, "$source_tests/harness" );
+
+    my @output = tied($$capture)->dump;
+    my $status = pop @output;
+    like $status, qr{^Result: PASS$},
+      '... and the status line should be correct';
+    pop @output;    # get rid of summary line
+    my $answer = pop @output;
+    is( $answer, "All tests successful.\n", 'cat meows' );
+}
+
+# Exec with a coderef that returns raw TAP
+{
+    my $capture = IO::c55Capture->new_handle;
+    my $harness = TAP::Harness->new(
+        {   verbosity => -2,
+            stdout    => $capture,
+            exec      => sub {
+                return "1..1\nok 1 - raw TAP\n";
+            },
+        }
+    );
+
+    _runtests( $harness, "$source_tests/harness" );
+
+    my @output = tied($$capture)->dump;
+    my $status = pop @output;
+    like $status, qr{^Result: PASS$},
+      '... and the status line should be correct';
+    pop @output;    # get rid of summary line
+    my $answer = pop @output;
+    is( $answer, "All tests successful.\n", 'cat meows' );
+}
+
+# Exec with a coderef that returns a filehandle
+{
+    my $capture = IO::c55Capture->new_handle;
+    my $harness = TAP::Harness->new(
+        {   verbosity => -2,
+            stdout    => $capture,
+            exec      => sub {
+                open my $fh,
+                  $ENV{PERL_CORE}
+                  ? '../ext/Test-Harness/t/data/catme.1'
+                  : 't/data/catme.1';
+                return $fh;
+            },
+        }
+    );
+
+    _runtests( $harness, "$source_tests/harness" );
+
+    my @output = tied($$capture)->dump;
+    my $status = pop @output;
+    like $status, qr{^Result: PASS$},
+      '... and the status line should be correct';
+    pop @output;    # get rid of summary line
+    my $answer = pop @output;
+    is( $answer, "All tests successful.\n", 'cat meows' );
+}
+
 # catches "exec accumulates arguments" issue (r77)
 {
     my $capture = IO::c55Capture->new_handle;
index fefbc21..3598521 100644 (file)
@@ -84,7 +84,7 @@ my @schedule = (
                         {   source => File::Spec->catfile(
                                 (   $ENV{PERL_CORE}
                                     ? ( File::Spec->updir(), 'ext',
-                                       'Test-Harness'
+                                        'Test-Harness'
                                       )
                                     : ()
                                 ),
index 4bcaba3..942c178 100644 (file)
@@ -12,7 +12,7 @@ BEGIN {
     }
 }
 
-use Test::More tests => 282;
+use Test::More tests => 294;
 use IO::c55Capture;
 
 use File::Spec;
@@ -438,6 +438,30 @@ is $test->raw, 'ok 2 - read the rest of the file',
 is scalar $parser->passed, 2,
   'Empty junk lines should not affect the correct number of tests passed';
 
+# Check source => "tap content"
+can_ok $PARSER, 'new';
+$parser = $PARSER->new( { source => "1..1\nok 1\n" } );
+isa_ok $parser, $PARSER, '... and calling it should succeed';
+ok @results = _get_results($parser), 'The parser should return results';
+is( scalar @results, 2, "Got two lines of TAP" );
+
+# Check source => [array]
+can_ok $PARSER, 'new';
+$parser = $PARSER->new( { source => [ "1..1", "ok 1" ] } );
+isa_ok $parser, $PARSER, '... and calling it should succeed';
+ok @results = _get_results($parser), 'The parser should return results';
+is( scalar @results, 2, "Got two lines of TAP" );
+
+# Check source => $filehandle
+can_ok $PARSER, 'new';
+open my $fh, $ENV{PERL_CORE}
+  ? '../ext/Test-Harness/t/data/catme.1'
+  : 't/data/catme.1';
+$parser = $PARSER->new( { source => $fh } );
+isa_ok $parser, $PARSER, '... and calling it should succeed';
+ok @results = _get_results($parser), 'The parser should return results';
+is( scalar @results, 2, "Got two lines of TAP" );
+
 {
 
     # set a spool to write to
index 6ee3db2..51113e1 100644 (file)
@@ -29,8 +29,10 @@ use Test::Harness;
 use App::Prove;
 
 # Change PERL5LIB so we ensure it's preserved.
-$ENV{PERL5LIB} = join( $path_sep, 'wibble',
-    ($ENV{PERL_CORE} ? '../lib' : ()), $ENV{PERL5LIB} || '' );
+$ENV{PERL5LIB} = join(
+    $path_sep, 'wibble',
+    ( $ENV{PERL_CORE} ? '../lib' : () ), $ENV{PERL5LIB} || ''
+);
 
 open TEST, ">perl5lib_check.t.tmp";
 print TEST <<"END";
index f8ce128..d6ca95f 100644 (file)
@@ -1009,6 +1009,26 @@ BEGIN {    # START PLAN
             ],
         },
 
+        # .proverc
+        {   name => 'Empty exec in .proverc',
+            args => {
+                argv => [qw( one two three )],
+            },
+            proverc  => $ENV{PERL_CORE} ? '../ext/Test-Harness/t/proverc/emptyexec' : 't/proverc/emptyexec',
+            switches => [$dummy_test],
+            expect   => { exec => '' },
+            runlog   => [
+                [   '_runtests',
+                    {   exec       => [],
+                        verbosity  => 0,
+                        show_count => 1,
+                    },
+                    'TAP::Harness',
+                    $dummy_test
+                ]
+            ],
+        },
+
         # Executing one word (why would it be a -s though?)
         {   name => 'Switch --exec -s',
             args => {
@@ -1442,6 +1462,9 @@ for my $test (@SCHEDULE) {
 
     # Optionally parse command args
     if ( my $switches = $test->{switches} ) {
+        if ( my $proverc = $test->{proverc} ) {
+            $app->add_rc_file( File::Spec->catfile( split /\//, $proverc ) );
+        }
         eval { $app->process_args( '--norc', @$switches ) };
         if ( my $err_pattern = $test->{parse_error} ) {
             like $@, $err_pattern, "$name: expected parse error";
@@ -1453,9 +1476,12 @@ for my $test (@SCHEDULE) {
 
     my $expect = $test->{expect} || {};
     for my $attr ( sort @ATTR ) {
-        my $val       = $app->$attr();
-        my $assertion = $expect->{$attr} || $DEFAULT_ASSERTION{$attr};
-        my $is_ok     = undef;
+        my $val = $app->$attr();
+        my $assertion
+          = exists $expect->{$attr}
+          ? $expect->{$attr}
+          : $DEFAULT_ASSERTION{$attr};
+        my $is_ok = undef;
 
         if ( 'CODE' eq ref $assertion ) {
             $is_ok = ok $assertion->( $val, $attr ),
diff --git a/ext/Test-Harness/t/proverc/emptyexec b/ext/Test-Harness/t/proverc/emptyexec
new file mode 100644 (file)
index 0000000..5381b8f
--- /dev/null
@@ -0,0 +1,2 @@
+--exec ''
+
index 28baee4..b86dd07 100644 (file)
@@ -2202,7 +2202,7 @@ my %samples = (
                 passed        => TRUE,
                 is_ok         => TRUE,
                 directive     => 'SKIP',
-                explanation   => ''
+                explanation   => 'rope'
             },
         ],
         plan          => '1..0',
@@ -2221,7 +2221,7 @@ my %samples = (
         'exit'        => 0,
         wait          => 0,
         version       => 12,
-        skip_all      => '(no reason given)',
+        skip_all      => 'rope',
     },
     skipall_v13 => {
         results => [
@@ -3049,6 +3049,90 @@ my %samples = (
         wait          => 0,
         version       => 12,
     },
+
+    zero_valid => {
+        results => [
+            {   is_plan       => TRUE,
+                raw           => '1..5',
+                tests_planned => 5,
+                passed        => TRUE,
+                is_ok         => TRUE,
+            },
+            {   actual_passed => TRUE,
+                is_actual_ok  => TRUE,
+                description   => '- One',
+                passed        => TRUE,
+                is_ok         => TRUE,
+                is_test       => TRUE,
+                has_skip      => FALSE,
+                has_todo      => FALSE,
+                number        => 1,
+                is_unplanned  => FALSE,
+            },
+            {   actual_passed => TRUE,
+                is_actual_ok  => TRUE,
+                description   => '- Two',
+                passed        => TRUE,
+                is_ok         => TRUE,
+                is_test       => TRUE,
+                has_skip      => FALSE,
+                has_todo      => FALSE,
+                number        => 2,
+                is_unplanned  => FALSE,
+            },
+            {   actual_passed => TRUE,
+                is_actual_ok  => TRUE,
+                description   => '- Three',
+                passed        => TRUE,
+                is_ok         => TRUE,
+                is_test       => TRUE,
+                has_skip      => FALSE,
+                has_todo      => FALSE,
+                number        => 3,
+                is_unplanned  => FALSE,
+            },
+            {   actual_passed => TRUE,
+                is_actual_ok  => TRUE,
+                description   => '- Four',
+                passed        => TRUE,
+                is_ok         => TRUE,
+                is_test       => TRUE,
+                has_skip      => FALSE,
+                has_todo      => FALSE,
+                number        => 0,
+                is_unplanned  => FALSE,
+            },
+            {   actual_passed => TRUE,
+                is_actual_ok  => TRUE,
+                description   => '- Five',
+                passed        => TRUE,
+                is_ok         => TRUE,
+                is_test       => TRUE,
+                has_skip      => FALSE,
+                has_todo      => FALSE,
+                number        => 5,
+                is_unplanned  => FALSE,
+            },
+        ],
+        plan          => '1..5',
+        passed        => [ 1 .. 3, 0, 5 ],
+        actual_passed => [ 1 .. 3, 0, 5 ],
+        failed        => [],
+        actual_failed => [],
+        todo          => [],
+        todo_passed   => [],
+        skipped       => [],
+        good_plan     => TRUE,
+        is_good_plan  => TRUE,
+        tests_planned => 5,
+        tests_run     => 5,
+        parse_errors  => [
+            'Tests out of sequence.  Found (0) but expected (4)',
+        ],
+        'exit'  => 0,
+        wait    => 0,
+        version => 12,
+    },
 );
 
 my %HANDLER_FOR = (
diff --git a/ext/Test-Harness/t/sample-tests/zero_valid b/ext/Test-Harness/t/sample-tests/zero_valid
new file mode 100644 (file)
index 0000000..dae91a1
--- /dev/null
@@ -0,0 +1,8 @@
+print <<DUMMY;
+1..5
+ok 1 - One
+ok 2 - Two
+ok - Three
+ok 0 - Four
+ok 5 - Five
+DUMMY
index d8b0add..a36e5c1 100644 (file)
@@ -4,4 +4,8 @@ print <<'END_TESTS';
 1..2
 ok 1 - this is a test
 not ok 2 - this is another test
+#   Failed test 'this is another test'
+#   in harness_failure.t at line 5.
+#          got: 'waffle'
+#     expected: 'yarblokos'
 END_TESTS