Update Test-Harness to CPAN version 3.27
authorNicholas Clark <nick@ccl4.org>
Thu, 2 May 2013 08:45:57 +0000 (10:45 +0200)
committerNicholas Clark <nick@ccl4.org>
Mon, 20 May 2013 15:11:12 +0000 (17:11 +0200)
  [DELTA]

  3.28    2013-05-02
          - Bugfix: Fix taint failures on Windows (Jan Dubois)

  3.27    2013-04-30
          - Dramatically reduce memory usage (Nick Clark, RT #84939)
          - Store test_num (in Grammar.pm) as a number instead of a string.
            Reduces memory usage (Nick Clark, RT #84939)
          - PERL5LIB is always propogated to a test's @INC, even with taint more
            (Schwern, RT #84377)

The local modifications to t/source.t are retained. [rt.cpan.org #64353]

58 files changed:
MANIFEST
Porting/Maintainers.pl
cpan/Test-Harness/Changes
cpan/Test-Harness/MANIFEST
cpan/Test-Harness/MANIFEST.CUMMULATIVE
cpan/Test-Harness/bin/prove
cpan/Test-Harness/lib/App/Prove.pm
cpan/Test-Harness/lib/App/Prove/State.pm
cpan/Test-Harness/lib/App/Prove/State/Result.pm
cpan/Test-Harness/lib/App/Prove/State/Result/Test.pm
cpan/Test-Harness/lib/TAP/Base.pm
cpan/Test-Harness/lib/TAP/Formatter/Base.pm
cpan/Test-Harness/lib/TAP/Formatter/Color.pm
cpan/Test-Harness/lib/TAP/Formatter/Console.pm
cpan/Test-Harness/lib/TAP/Formatter/Console/ParallelSession.pm
cpan/Test-Harness/lib/TAP/Formatter/Console/Session.pm
cpan/Test-Harness/lib/TAP/Formatter/File.pm
cpan/Test-Harness/lib/TAP/Formatter/File/Session.pm
cpan/Test-Harness/lib/TAP/Formatter/Session.pm
cpan/Test-Harness/lib/TAP/Harness.pm
cpan/Test-Harness/lib/TAP/Object.pm
cpan/Test-Harness/lib/TAP/Parser.pm
cpan/Test-Harness/lib/TAP/Parser/Aggregator.pm
cpan/Test-Harness/lib/TAP/Parser/Grammar.pm
cpan/Test-Harness/lib/TAP/Parser/Iterator.pm
cpan/Test-Harness/lib/TAP/Parser/Iterator/Array.pm
cpan/Test-Harness/lib/TAP/Parser/Iterator/Process.pm
cpan/Test-Harness/lib/TAP/Parser/Iterator/Stream.pm
cpan/Test-Harness/lib/TAP/Parser/IteratorFactory.pm
cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
cpan/Test-Harness/lib/TAP/Parser/Result.pm
cpan/Test-Harness/lib/TAP/Parser/Result/Bailout.pm
cpan/Test-Harness/lib/TAP/Parser/Result/Comment.pm
cpan/Test-Harness/lib/TAP/Parser/Result/Plan.pm
cpan/Test-Harness/lib/TAP/Parser/Result/Pragma.pm
cpan/Test-Harness/lib/TAP/Parser/Result/Test.pm
cpan/Test-Harness/lib/TAP/Parser/Result/Unknown.pm
cpan/Test-Harness/lib/TAP/Parser/Result/Version.pm
cpan/Test-Harness/lib/TAP/Parser/Result/YAML.pm
cpan/Test-Harness/lib/TAP/Parser/ResultFactory.pm
cpan/Test-Harness/lib/TAP/Parser/Scheduler.pm
cpan/Test-Harness/lib/TAP/Parser/Scheduler/Job.pm
cpan/Test-Harness/lib/TAP/Parser/Scheduler/Spinner.pm
cpan/Test-Harness/lib/TAP/Parser/Source.pm
cpan/Test-Harness/lib/TAP/Parser/SourceHandler.pm
cpan/Test-Harness/lib/TAP/Parser/SourceHandler/Executable.pm
cpan/Test-Harness/lib/TAP/Parser/SourceHandler/File.pm
cpan/Test-Harness/lib/TAP/Parser/SourceHandler/Handle.pm
cpan/Test-Harness/lib/TAP/Parser/SourceHandler/Perl.pm
cpan/Test-Harness/lib/TAP/Parser/SourceHandler/RawTAP.pm
cpan/Test-Harness/lib/TAP/Parser/Utils.pm
cpan/Test-Harness/lib/TAP/Parser/YAMLish/Reader.pm
cpan/Test-Harness/lib/TAP/Parser/YAMLish/Writer.pm
cpan/Test-Harness/lib/Test/Harness.pm
cpan/Test-Harness/t/compat/inc-propagation.t
cpan/Test-Harness/t/nowarn.t [deleted file]
cpan/Test-Harness/t/taint.t
pod/perldelta.pod

index 3eaa80c..232bbd2 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -2162,7 +2162,6 @@ cpan/Test-Harness/t/multiplexer.t                 Test::Harness test
 cpan/Test-Harness/t/nested.t                           Test::Harness test
 cpan/Test-Harness/t/nofork-mux.t                       Test::Harness test
 cpan/Test-Harness/t/nofork.t                           Test::Harness test
-cpan/Test-Harness/t/nowarn.t
 cpan/Test-Harness/t/object.t                           Test::Harness test
 cpan/Test-Harness/t/parser-config.t                    Test::Harness test
 cpan/Test-Harness/t/parser-subclass.t                  Test::Harness test
index bca39d9..dd3d670 100755 (executable)
@@ -1659,7 +1659,7 @@ use File::Glob qw(:case);
 
     'Test::Harness' => {
         'MAINTAINER'   => 'andya',
-        'DISTRIBUTION' => 'OVID/Test-Harness-3.26.tar.gz',
+        'DISTRIBUTION' => 'OVID/Test-Harness-3.28.tar.gz',
         'FILES'        => q[cpan/Test-Harness],
         'EXCLUDED'     => [
             qr{^examples/},
index 88039e5..f0c9cf0 100644 (file)
@@ -1,5 +1,15 @@
 Revision history for Test-Harness
 
+3.28    2013-05-02
+        - Bugfix: Fix taint failures on Windows (Jan Dubois)
+
+3.27    2013-04-30
+        - Dramatically reduce memory usage (Nick Clark, RT #84939)
+        - Store test_num (in Grammar.pm) as a number instead of a string.
+          Reduces memory usage (Nick Clark, RT #84939)
+        - PERL5LIB is always propogated to a test's @INC, even with taint more
+          (Schwern, RT #84377)
+
 3.26    2013-01-16
         - Renamed env.opts.t to env_opts.t (for VMS)
         - Skipped some TAP::Formatter::HTML tests due to this bug: #82738
index 93e9ac8..53f9521 100644 (file)
@@ -126,7 +126,6 @@ t/multiplexer.t
 t/nested.t
 t/nofork-mux.t
 t/nofork.t
-t/nowarn.t
 t/object.t
 t/parse.t
 t/parser-config.t
index bd2b6f0..c0e58b0 100644 (file)
@@ -156,7 +156,6 @@ t/compat/040-test-harness-compat.t
 t/compat/060-version.t
 t/compat/base.t
 t/compat/callback.t
-t/compat/env.opts.t
 t/compat/env.t
 t/compat/failure.t
 t/compat/from_line.t
@@ -221,7 +220,6 @@ t/multiplexer.t
 t/nested.t
 t/nofork-mux.t
 t/nofork.t
-t/nowarn.t
 t/object.t
 t/parse.t
 t/parser-config.t
index e14ceba..4f46ed6 100644 (file)
@@ -32,7 +32,6 @@ Boolean options:
                         (default)
       --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        Show failed tests.
  -o,  --comments        Show comments.
       --ignore-exit     Ignore exit status from test scripts.
@@ -62,6 +61,7 @@ Options that take arguments:
  -M                     Load a module.
  -e,  --exec            Interpreter to run the tests ('' for compiled
                         tests.)
+      --ext             Set the extension for tests (default '.t')
       --harness         Define test harness to use.  See TAP::Harness.
       --formatter       Result formatter to use. See FORMATTERS.
       --source          Load and/or configure a SourceHandler. See
@@ -70,6 +70,7 @@ Options that take arguments:
  -j,  --jobs N          Run N test jobs in parallel (try 9.)
       --state=opts      Control prove's persistent state.
       --rc=rcfile       Process options from rcfile
+      --rules           Rules for parallel vs sequential processing.
 
 =head1 NOTES
 
@@ -264,6 +265,61 @@ The C<--state> switch may be used more than once.
 
     $ prove -b --state=hot --state=all,save
 
+=head2 --rules
+
+The C<--rules> option is used to control which tests are run sequentially and
+which are run in parallel, if the C<--jobs> option is specified. The option may
+be specified multiple times, and the order matters.
+
+The most practical use is likely to specify that some tests are not
+"parallel-ready".  Since mentioning a file with --rules doens't cause it to
+selected to run as a test, you can "set and forget" some rules preferences in
+your .proverc file. Then you'll be able to take maximum advantage of the
+performance benefits of parallel testing, while some exceptions are still run
+in parallel.
+
+=head3 --rules examples
+
+    # All tests are allowed to run in parallel, except those starting with "p"
+    --rules='seq=t/p*.t' --rules='par=**'
+
+    # All tests must run in sequence except those starting with "p", which should be run parallel
+    --rules='par=t/p*.t'
+
+=head3 --rules resolution
+
+=over4
+
+=item * By default, all tests are eligible to be run in parallel. Specifying any of your own rules removes this one.
+
+=item * "First match wins". The first rule that matches a test will be the one that applies.
+
+=item * Any test which does not match a rule will be run in sequence at the end of the run.
+
+=item * The existence of a rule does not imply selecting a test. You must still specify the tests to run.
+
+=item * Specifying a rule to allow tests to run in parallel does not make the run in parallel. You still need specify the number of parallel C<jobs> in your Harness object.
+
+=back
+
+=head3 --rules Glob-style pattern matching
+
+We implement our own glob-style pattern matching for --rules. Here are the
+supported patterns:
+
+    ** is any number of characters, including /, within a pathname
+    * is zero or more characters within a filename/directory name
+    ? is exactly one character within a filename/directory name
+    {foo,bar,baz} is any of foo, bar or baz.
+    \ is an escape character
+
+=head3 More advance specifications for parallel vs sequence run rules
+
+If you need more advanced management of what runs in parallel vs in sequence, see
+the associated 'rules' documentation in L<TAP::Harness> and L<TAP::Parser::Scheduler>.
+If what's possible directly through C<prove> is not sufficient, you can write your own
+harness to access these features directly.
+
 =head2 @INC
 
 prove introduces a separation between "options passed to the perl which
index 67c691b..5b2b98b 100644 (file)
@@ -17,11 +17,11 @@ App::Prove - Implements the C<prove> command.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index a9c38de..5e9a13e 100644 (file)
@@ -26,11 +26,11 @@ App::Prove::State - State storage for the C<prove> command.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
@@ -41,7 +41,7 @@ and the operations that may be performed on it.
 =head1 SYNOPSIS
 
     # Re-run failed tests
-    $ prove --state=fail,save -rbv
+    $ prove --state=failed,save -rbv
 
 =cut
 
index 7bb4457..4e89d5a 100644 (file)
@@ -14,11 +14,11 @@ App::Prove::State::Result - Individual test suite results.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
@@ -29,7 +29,7 @@ single test suite run.
 =head1 SYNOPSIS
 
     # Re-run failed tests
-    $ prove --state=fail,save -rbv
+    $ prove --state=failed,save -rbv
 
 =cut
 
index f626f1d..351c696 100644 (file)
@@ -10,11 +10,11 @@ App::Prove::State::Result::Test - Individual test results.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
@@ -25,7 +25,7 @@ single test.
 =head1 SYNOPSIS
 
     # Re-run failed tests
-    $ prove --state=fail,save -rbv
+    $ prove --state=failed,save -rbv
 
 =cut
 
index ff8da42..e13c6b0 100644 (file)
@@ -14,11 +14,11 @@ and L<TAP::Harness>
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 use constant GOT_TIME_HIRES => do {
     eval 'use Time::HiRes qw(time);';
index af7b3fc..5755cb3 100644 (file)
@@ -61,11 +61,11 @@ TAP::Formatter::Base - Base class for harness output delegates
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index 16d6f79..d7c8e98 100644 (file)
@@ -71,11 +71,11 @@ TAP::Formatter::Color - Run Perl test scripts with color
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index 0a9115f..14121d5 100644 (file)
@@ -14,11 +14,11 @@ TAP::Formatter::Console - Harness output delegate for default console output
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index 8739039..204d4b9 100644 (file)
@@ -42,11 +42,11 @@ TAP::Formatter::Console::ParallelSession - Harness output delegate for parallel
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index f5b3dc1..6578150 100644 (file)
@@ -28,11 +28,11 @@ TAP::Formatter::Console::Session - Harness output delegate for default console o
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index 8d94a2c..e10ecfd 100644 (file)
@@ -15,11 +15,11 @@ TAP::Formatter::File - Harness output delegate for file output
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index 9b61cab..eb19222 100644 (file)
@@ -13,11 +13,11 @@ TAP::Formatter::File::Session - Harness output delegate for file output
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index 081ca9a..c56b2bd 100644 (file)
@@ -25,11 +25,11 @@ TAP::Formatter::Session - Abstract base class for harness output delegate
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 METHODS
 
index c60d1d9..9564630 100644 (file)
@@ -19,11 +19,11 @@ TAP::Harness - Run test scripts with statistics
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 $ENV{HARNESS_ACTIVE}  = 1;
 $ENV{HARNESS_VERSION} = $VERSION;
@@ -330,20 +330,37 @@ run only one test at a time.
 
 =item * C<rules>
 
-A reference to a hash of rules that control which tests may be
-executed in parallel. This is an experimental feature and the
-interface may change.
-
-    $harness->rules(
-        {   par => [
-                { seq => '../ext/DB_File/t/*' },
-                { seq => '../ext/IO_Compress_Zlib/t/*' },
-                { seq => '../lib/CPANPLUS/*' },
-                { seq => '../lib/ExtUtils/t/*' },
-                '*'
-            ]
-        }
-    );
+A reference to a hash of rules that control which tests may be executed in
+parallel. If no rules are declared, all tests are eligible for being run in
+parallel. Here some simple examples. For the full details of the data structure
+and the related glob-style pattern matching, see
+L<TAP::Parser::Scheduler/"Rules data structure">.
+
+    # Run all tests in sequence, except those starting with "p"
+    $harness->rules({
+        par => 't/p*.t'
+    });
+
+    # Run all tests in parallel, except those starting with "p"
+    $harness->rules({
+        seq => [
+                  { seq => 't/p*.t' },
+                  { par => '**'     },
+               ],
+    });
+
+    # Run some  startup tests in sequence, then some parallel tests than some
+    # teardown tests in sequence.
+    $harness->rules({
+        seq => [
+            { seq => 't/startup/*.t' },
+            { par => ['t/a/*.t','t/b/*.t','t/c/*.t'], }
+            { seq => 't/shutdown/*.t' },
+        ],
+
+    });
+
+This is an experimental feature and the interface may change.
 
 =item * C<stdout>
 
index 6d0bc30..b2a60b4 100644 (file)
@@ -9,11 +9,11 @@ TAP::Object - Base class that provides common functionality to all C<TAP::*> mod
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index 9590903..f869e2d 100644 (file)
@@ -24,11 +24,11 @@ TAP::Parser - Parse L<TAP|Test::Harness::TAP> output
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 my $DEFAULT_TAP_VERSION = 12;
 my $MAX_TAP_VERSION     = 13;
@@ -795,7 +795,11 @@ but had a TODO directive, it will be counted as a passed test.
 
 =cut
 
-sub passed { @{ shift->{passed} } }
+sub passed {
+    return @{ $_[0]->{passed} }
+      if ref $_[0]->{passed};
+    return wantarray ? 1 .. $_[0]->{passed} : $_[0]->{passed};
+}
 
 =head3 C<failed>
 
@@ -822,7 +826,11 @@ regardless of whether or not a TODO directive was found.
 
 =cut
 
-sub actual_passed { @{ shift->{actual_passed} } }
+sub actual_passed {
+    return @{ $_[0]->{actual_passed} }
+      if ref $_[0]->{actual_passed};
+    return wantarray ? 1 .. $_[0]->{actual_passed} : $_[0]->{actual_passed};
+}
 *actual_ok = \&actual_passed;
 
 =head3 C<actual_ok>
@@ -1496,6 +1504,17 @@ sub _finish {
     }
 
     $self->is_good_plan(0) unless defined $self->is_good_plan;
+
+    unless ( $self->parse_errors ) {
+        # Optimise storage where possible
+        if ( $self->tests_run == @{$self->{passed}} ) {
+            $self->{passed} = $self->tests_run;
+        }
+        if ( $self->tests_run == @{$self->{actual_passed}} ) {
+            $self->{actual_passed} = $self->tests_run;
+        }
+    }
+
     return $self;
 }
 
index d2836e5..ad51ba3 100644 (file)
@@ -14,11 +14,11 @@ TAP::Parser::Aggregator - Aggregate TAP::Parser results
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index aba4c66..b3b16de 100644 (file)
@@ -15,11 +15,11 @@ TAP::Parser::Grammar - A grammar for the Test Anything Protocol.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
@@ -405,7 +405,10 @@ sub _make_test_token {
     my ( $self, $line, $ok, $num, $desc, $dir, $explanation ) = @_;
     return {
         ok          => $ok,
-        test_num    => $num,
+
+        # forcing this to be an integer (and not a string) reduces memory
+        # consumption. RT #84939
+        test_num    => ( defined $num ? 0 + $num : undef ),
         description => _trim($desc),
         directive   => ( defined $dir ? uc $dir : '' ),
         explanation => _trim($explanation),
index aebcb94..1385aea 100644 (file)
@@ -13,11 +13,11 @@ TAP::Parser::Iterator - Base class for TAP source iterators
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index a3bb662..34daa15 100644 (file)
@@ -13,11 +13,11 @@ TAP::Parser::Iterator::Array - Iterator for array-based TAP sources
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index 8f43f0a..8a0fb11 100644 (file)
@@ -17,11 +17,11 @@ TAP::Parser::Iterator::Process - Iterator for process-based TAP sources
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index 1d04574..e249e27 100644 (file)
@@ -13,11 +13,11 @@ TAP::Parser::Iterator::Stream - Iterator for filehandle-based TAP sources
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index cda251e..fe31f71 100644 (file)
@@ -18,11 +18,11 @@ TAP::Parser::IteratorFactory - Figures out which SourceHandler objects to use fo
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index a3a23da..913aa92 100644 (file)
@@ -18,11 +18,11 @@ TAP::Parser::Multiplexer - Multiplex multiple TAP::Parsers
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index a0caebe..144a081 100644 (file)
@@ -26,11 +26,11 @@ TAP::Parser::Result - Base class for TAP::Parser output objects
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index 14bef6c..437d8f5 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Result::Bailout - Bailout result token.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index 8a2cb93..678a6d0 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Result::Comment - Comment result token.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index b515e61..ef85b82 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Result::Plan - Plan result token.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index 0416e3a..bf17fc6 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Result::Pragma - TAP pragma token.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index b977f71..eff9b9b 100644 (file)
@@ -14,11 +14,11 @@ TAP::Parser::Result::Test - Test result token.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index 0d0e583..61f441a 100644 (file)
@@ -14,11 +14,11 @@ TAP::Parser::Result::Unknown - Unknown result token.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index 2380c43..db8e1bc 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Result::Version - TAP syntax version token.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index f92b43a..9e0cbad 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Result::YAML - YAML result token.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 DESCRIPTION
 
index 729bf4f..fe95045 100644 (file)
@@ -30,11 +30,11 @@ TAP::Parser::ResultFactory - Factory for creating TAP::Parser output objects
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head2 DESCRIPTION
 
index f7a3e46..144b38e 100644 (file)
@@ -12,11 +12,11 @@ TAP::Parser::Scheduler - Schedule tests during parallel testing
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
@@ -30,9 +30,98 @@ $VERSION = '3.26';
 
 =head3 C<new>
 
-    my $sched = TAP::Parser::Scheduler->new;
+    my $sched = TAP::Parser::Scheduler->new(tests => \@tests);
+    my $sched = TAP::Parser::Scheduler->new(
+        tests => [ ['t/test_name.t','Test Description'], ... ],
+        rules => \%rules,
+    );
+
+Given 'tests' and optional 'rules' as input, returns a new
+C<TAP::Parser::Scheduler> object.  Each member of C<@tests> should be either a
+a test file name, or a two element arrayref, where the first element is a test
+file name, and the second element is a test description. By default, we'll use
+the test name as the description.
+
+The optional C<rules> attribute provides direction on which tests should be run
+in parallel and which should be run sequentially. If no rule data structure is
+provided, a default data structure is used which makes every test eligible to
+be run in parallel:
+
+    { par => '**' },
+
+The rules data structure is documented more in the next section.
+
+=head2 Rules data structure
+
+The "C<rules>" data structure is the the heart of the scheduler. It allows you
+to express simple rules like "run all tests in sequence" or "run all tests in
+parallel except these five tests.". However, the rules structure also supports
+glob-style pattern matching and recursive definitions, so you can also express
+arbitarily complicated patterns.
+
+The rule must only have one top level key: either 'par' for "parallel" or 'seq'
+for "sequence".
+
+Values must be either strings with possible glob-style matching, or arrayrefs
+of strings or hashrefs which follow this pattern recursively.
+
+Every element in an arrayref directly below a 'par' key is eligible to be run
+in parallel, while vavalues directly below a 'seq' key must be run in sequence.
+
+=head3 Rules examples
+
+Here are some examples:
+
+    # All tests be run in parallel (the default rule)
+    { par => '**' },
+
+    # Run all tests in sequence, except those starting with "p"
+    { par => 't/p*.t' },
+
+    # Run all tests in parallel, except those starting with "p"
+    {
+        seq => [
+                  { seq => 't/p*.t' },
+                  { par => '**'     },
+               ],
+    }
+
+    # Run some  startup tests in sequence, then some parallel tests than some
+    # teardown tests in sequence.
+    {
+        seq => [
+            { seq => 't/startup/*.t' },
+            { par => ['t/a/*.t','t/b/*.t','t/c/*.t'], }
+            { seq => 't/shutdown/*.t' },
+        ],
+    },
+
 
-Returns a new C<TAP::Parser::Scheduler> object.
+=head3 Rules resolution
+
+=over4
+
+=item * By default, all tests are eligible to be run in parallel. Specifying any of your own rules removes this one.
+
+=item * "First match wins". The first rule that matches a test will be the one that applies.
+
+=item * Any test which does not match a rule will be run in sequence at the end of the run.
+
+=item * The existence of a rule does not imply selecting a test. You must still specify the tests to run.
+
+=item * Specifying a rule to allow tests to run in parallel does not make the run in parallel. You still need specify the number of parallel C<jobs> in your Harness object.
+
+=back
+
+=head3 Glob-style pattern matching for rules
+
+We implement our own glob-style pattern matching. Here are the patterns it supports:
+
+    ** is any number of characters, including /, within a pathname
+    * is zero or more characters within a filename/directory name
+    ? is exactly one character within a filename/directory name
+    {foo,bar,baz} is any of foo, bar or baz.
+    \ is an escape character
 
 =cut
 
@@ -70,6 +159,9 @@ sub new {
 
 sub _set_rules {
     my ( $self, $rules, $tests ) = @_;
+
+    # Convert all incoming tests to job objects. 
+    # If no test description is provided use the file name as the description. 
     my @tests = map { TAP::Parser::Scheduler::Job->new(@$_) }
       map { 'ARRAY' eq ref $_ ? $_ : [ $_, $_ ] } @$tests;
     my $schedule = $self->_rule_clause( $rules, \@tests );
@@ -185,6 +277,8 @@ sub _expand {
     return @match;
 }
 
+=head2 Instance Methods
+
 =head3 C<get_all>
 
 Get a list of all remaining tests.
@@ -207,9 +301,9 @@ sub _gather {
 
 =head3 C<get_job>
 
-Return the next available job or C<undef> if none are available. Returns
-a C<TAP::Parser::Scheduler::Spinner> if the scheduler still has pending
-jobs but none are available to run right now.
+Return the next available job as L<TAP::Parser::Scheduler::Job> object or
+C<undef> if none are available. Returns a L<TAP::Parser::Scheduler::Spinner> if
+the scheduler still has pending jobs but none are available to run right now.
 
 =cut
 
@@ -281,9 +375,50 @@ sub _find_next_job {
 =head3 C<as_string>
 
 Return a human readable representation of the scheduling tree.
+For example:
+
+    my @tests = (qw{
+        t/startup/foo.t 
+        t/shutdown/foo.t
+    
+        t/a/foo.t t/b/foo.t t/c/foo.t t/d/foo.t
+    });
+    my $sched = TAP::Parser::Scheduler->new(
+        tests => \@tests,
+        rules => {
+            seq => [
+                { seq => 't/startup/*.t' },
+                { par => ['t/a/*.t','t/b/*.t','t/c/*.t'] },
+                { seq => 't/shutdown/*.t' },
+            ],
+        },
+    );
+
+Produces:
+
+    par:
+      seq:
+        par:
+          seq:
+            par:
+              seq:
+                't/startup/foo.t'
+            par:
+              seq:
+                't/a/foo.t'
+              seq:
+                't/b/foo.t'
+              seq:
+                't/c/foo.t'
+            par:
+              seq:
+                't/shutdown/foo.t'
+        't/d/foo.t'
+
 
 =cut
 
+
 sub as_string {
     my $self = shift;
     return $self->_as_string( $self->{schedule} );
index bac5883..961a695 100644 (file)
@@ -10,11 +10,11 @@ TAP::Parser::Scheduler::Job - A single testing job.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
@@ -31,10 +31,11 @@ Represents a single test 'job'.
 =head3 C<new>
 
     my $job = TAP::Parser::Scheduler::Job->new(
-        $name, $desc 
+        $filename, $description
     );
 
-Returns a new C<TAP::Parser::Scheduler::Job> object.
+Given the filename and description of a test as scalars, returns a new
+L<TAP::Parser::Scheduler::Job> object.
 
 =cut
 
@@ -47,9 +48,14 @@ sub new {
     }, $class;
 }
 
+=head2 Instance Methods
+
 =head3 C<on_finish>
 
-Register a closure to be called when this job is destroyed.
+    $self->on_finish(\&method).
+
+Register a closure to be called when this job is destroyed. The callback
+will be passed the C<TAP::Parser::Scheduler::Job> object as it's only argument.
 
 =cut
 
@@ -60,7 +66,10 @@ sub on_finish {
 
 =head3 C<finish>
 
-Called when a job is complete to unlock it.
+   $self->finish;
+
+Called when a job is complete to unlock it. If a callback has been registered
+with C<on_finish>, it calls it. Otherwise, it does nothing. 
 
 =cut
 
@@ -71,6 +80,15 @@ sub finish {
     }
 }
 
+=head2 Attributes
+
+  $self->filename;
+  $self->description;
+  $self->context;
+
+These are all "getters" which return the data set for these attributes during object construction.
+
+
 =head3 C<filename>
 
 =head3 C<description>
@@ -96,6 +114,8 @@ sub as_array_ref {
 
 =head3 C<is_spinner>
 
+  $self->is_spinner;
+
 Returns false indicating that this is a real job rather than a
 'spinner'. Spinners are returned when the scheduler still has pending
 jobs but can't (because of locking) return one right now.
index 21d4d67..fde39ae 100644 (file)
@@ -10,11 +10,11 @@ TAP::Parser::Scheduler::Spinner - A no-op job.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
@@ -34,12 +34,14 @@ return a real job.
 
     my $job = TAP::Parser::Scheduler::Spinner->new;
 
-Returns a new C<TAP::Parser::Scheduler::Spinner> object.
+Ignores any arguments and returns a new C<TAP::Parser::Scheduler::Spinner> object.
 
 =cut
 
 sub new { bless {}, shift }
 
+=head2 Instance Methods
+
 =head3 C<is_spinner>
 
 Returns true indicating that is a 'spinner' job. Spinners are returned
@@ -50,4 +52,10 @@ return one right now.
 
 sub is_spinner {1}
 
+=head1 SEE ALSO
+
+L<TAP::Parser::Scheduler>, L<TAP::Parser::Scheduler::Job>
+
+=cut
+
 1;
index 6eda5db..e59e9fb 100644 (file)
@@ -16,11 +16,11 @@ TAP::Parser::Source - a TAP source & meta data about it
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index e8412ab..740a60e 100644 (file)
@@ -14,11 +14,11 @@ TAP::Parser::SourceHandler - Base class for different TAP source handlers
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index f20e651..bffff4c 100644 (file)
@@ -17,11 +17,11 @@ TAP::Parser::SourceHandler::Executable - Stream output from an executable TAP so
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index 1faaceb..b3c5b1a 100644 (file)
@@ -17,11 +17,11 @@ TAP::Parser::SourceHandler::File - Stream TAP from a text file.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index f004347..af7de82 100644 (file)
@@ -17,11 +17,11 @@ TAP::Parser::SourceHandler::Handle - Stream TAP from an IO::Handle or a GLOB.
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index 97eba8e..9257f6a 100644 (file)
@@ -22,11 +22,11 @@ TAP::Parser::SourceHandler::Perl - Stream TAP from a Perl executable
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
@@ -152,17 +152,26 @@ sub make_iterator {
     $class->_run( $source, $libs, $switches );
 }
 
+
+sub _has_taint_switch {
+    my( $class, $switches ) = @_;
+
+    my $has_taint = grep { $_ eq "-T" || $_ eq "-t" } @{$switches};
+    return $has_taint ? 1 : 0;
+}
+
 sub _mangle_switches {
     my ( $class, $libs, $switches ) = @_;
 
     # Taint mode ignores environment variables so we must retranslate
     # PERL5LIB as -I switches and place PERL5OPT on the command line
     # in order that it be seen.
-    if ( grep { $_ eq "-T" || $_ eq "-t" } @{$switches} ) {
+    if ( $class->_has_taint_switch($switches) ) {
+        my @perl5lib = split /$Config{path_sep}/, $ENV{PERL5LIB};
         return (
             $libs,
             [   @{$switches},
-                $class->_libs2switches($libs),
+                $class->_libs2switches([@$libs, @perl5lib]),
                 split_shell( $ENV{PERL5OPT} )
             ],
         );
@@ -200,10 +209,10 @@ sub _filter_libs {
 }
 
 sub _iterator_hooks {
-    my ( $class, $source, $libs ) = @_;
+    my ( $class, $source, $libs, $switches ) = @_;
 
     my $setup = sub {
-        if ( @{$libs} ) {
+        if ( @{$libs} and !$class->_has_taint_switch($switches) ) {
             $ENV{PERL5LIB} = join(
                 $Config{path_sep}, grep {defined} @{$libs},
                 $ENV{PERL5LIB}
@@ -211,8 +220,8 @@ sub _iterator_hooks {
         }
     };
 
-    # Cargo culted from comments seen elsewhere about VMS / environment
-    # variables. I don't know if this is actually necessary.
+    # VMS environment variables aren't guaranteed to reset at the end of
+    # the process, so we need to put PERL5LIB back.
     my $previous = $ENV{PERL5LIB};
     my $teardown = sub {
         if ( defined $previous ) {
@@ -232,7 +241,7 @@ sub _run {
     my @command = $class->_get_command_for_switches( $source, $switches )
       or $class->_croak("No command found!");
 
-    my ( $setup, $teardown ) = $class->_iterator_hooks( $source, $libs );
+    my ( $setup, $teardown ) = $class->_iterator_hooks( $source, $libs, $switches );
 
     return $class->_create_iterator( $source, \@command, $setup, $teardown );
 }
index 04b4b9c..84d320d 100644 (file)
@@ -17,11 +17,11 @@ TAP::Parser::SourceHandler::RawTAP - Stream output from raw TAP in a scalar/arra
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index 2096b0e..e9735b0 100644 (file)
@@ -13,11 +13,11 @@ TAP::Parser::Utils - Internal TAP::Parser utilities
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 =head1 SYNOPSIS
 
index ac2c455..855485c 100644 (file)
@@ -6,7 +6,7 @@ use vars qw($VERSION @ISA);
 use TAP::Object ();
 
 @ISA     = 'TAP::Object';
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 # TODO:
 #   Handle blessed object syntax
@@ -270,7 +270,7 @@ TAP::Parser::YAMLish::Reader - Read YAMLish data from iterator
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =head1 SYNOPSIS
 
index 9f20fb2..f5308b0 100644 (file)
@@ -6,7 +6,7 @@ use vars qw($VERSION @ISA);
 use TAP::Object ();
 
 @ISA     = 'TAP::Object';
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 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.26
+Version 3.28
 
 =head1 SYNOPSIS
 
index fe11d14..8c82199 100644 (file)
@@ -46,11 +46,11 @@ Test::Harness - Run Perl standard test scripts with statistics
 
 =head1 VERSION
 
-Version 3.26
+Version 3.28
 
 =cut
 
-$VERSION = '3.26';
+$VERSION = '3.28';
 
 # Backwards compatibility for exportable variable names.
 *verbose  = *Verbose;
@@ -73,7 +73,7 @@ END {
 
 $Verbose = $ENV{HARNESS_VERBOSE} || 0;
 $Debug   = $ENV{HARNESS_DEBUG}   || 0;
-$Switches = '';
+$Switches = '-w';
 $Columns = $ENV{HARNESS_COLUMNS} || $ENV{COLUMNS} || 80;
 $Columns--;    # Some shells have trouble with a full line of text.
 $Timer      = $ENV{HARNESS_TIMER}       || 0;
@@ -519,6 +519,17 @@ This is the version of C<Test::Harness>.
 
 =over 4
 
+=item C<HARNESS_PERL_SWITCHES>
+
+Setting this adds perl command line switches to each test file run.
+
+For example, C<HARNESS_PERL_SWITCHES=-T> will turn on taint mode.
+C<HARNESS_PERL_SWITCHES=-MDevel::Cover> will run C<Devel::Cover> for
+each test.
+
+C<-w> is always set.  You can turn this off in the test with C<BEGIN {
+$^W = 0 }>.
+
 =item C<HARNESS_TIMER>
 
 Setting this to true will make the harness display the number of
index 8bd0951..876f031 100644 (file)
@@ -36,10 +36,9 @@ use lib 'wibble';
 my $test_template = <<'END';
 #!/usr/bin/perl %s
 
-use Test::More tests => 2;
+use Test::More tests => 1;
 
 is $INC[0], "wibble", 'basic order of @INC preserved' or diag "\@INC: @INC";
-like $ENV{PERL5LIB}, qr{wibble};
 
 END
 
diff --git a/cpan/Test-Harness/t/nowarn.t b/cpan/Test-Harness/t/nowarn.t
deleted file mode 100644 (file)
index 5b6809f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!perl
-
-use Test::More tests => 1;
-
-# Make sure that warnings are only enabled if we enable them
-# specifically.
-ok !$^W, 'warnings disabled';
-
-# vim:ts=2:sw=2:et:ft=perl
-
index c6f5483..ceed7a4 100644 (file)
@@ -4,10 +4,10 @@ BEGIN {
     unshift @INC, 't/lib';
 }
 
-# Test that options in PERL5OPT are propogated to tainted tests
+# Test that environment options are propagated to tainted tests
 
 use strict;
-use Test::More ( $^O eq 'VMS' ? ( skip_all => 'VMS' ) : ( tests => 1 ) );
+use Test::More ( $^O eq 'VMS' ? ( skip_all => 'VMS' ) : ( tests => 2 ) );
 
 use Config;
 use TAP::Parser;
@@ -47,4 +47,18 @@ print $INC{'strict.pm'} ? "ok 1\n" : "not ok 1\n";
 END
 }
 
+
+# Check that PERL5LIB is propagated to -T.
+{
+    my $sentinel_dir = 'i/do/not/exist';
+    local $ENV{PERL5LIB} = join $Config{path_sep}, $ENV{PERL5LIB}, $sentinel_dir;
+    run_test_file(sprintf <<'END', $sentinel_dir);
+#!/usr/bin/perl -T
+
+print "1..1\n";
+my $ok = grep { $_ eq '%s' } @INC;
+print $ok ? "ok 1\n" : "not ok 1\n";
+END
+}
+
 1;
index a65a455..cb99f64 100644 (file)
@@ -119,7 +119,12 @@ XXX
 
 =item *
 
-L<XXX> has been upgraded from version A.xx to B.yy.
+Test::Harness has been upgraded from version 3.26 to 3.28
+
+Memory usage is dramatically reduced. t/harness now uses about 10% of the
+memory used by 3.26 and earlier.
+
+C<PERL5LIB> is always propagated to a test's C<@INC>, even under C<-T>.
 
 =back