summaryrefslogtreecommitdiff
path: root/lib/Test
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2008-07-31 21:27:36 +0000
committerNicholas Clark <nick@ccl4.org>2008-07-31 21:27:36 +0000
commitf7c69158501ed4705d71f069f23211f56bd55a2e (patch)
treef2387107086e230c5d3bf132a7ebfbf3e39dd5c3 /lib/Test
parentb78dccfb97f2a41b9be93ea6888a12b7bef9a4b2 (diff)
downloadperl-f7c69158501ed4705d71f069f23211f56bd55a2e.tar.gz
Upgrade to Test::Harness 3.13
p4raw-id: //depot/perl@34169
Diffstat (limited to 'lib/Test')
-rw-r--r--lib/Test/Harness.pm27
-rw-r--r--lib/Test/Harness/Changes61
-rw-r--r--lib/Test/Harness/bin/prove8
-rw-r--r--lib/Test/Harness/t/000-load.t10
-rw-r--r--lib/Test/Harness/t/aggregator.t15
-rw-r--r--lib/Test/Harness/t/base.t24
-rw-r--r--lib/Test/Harness/t/callbacks.t11
-rw-r--r--lib/Test/Harness/t/compat/inc-propagation.t38
-rw-r--r--lib/Test/Harness/t/compat/inc_taint.t6
-rw-r--r--lib/Test/Harness/t/compat/regression.t1
-rw-r--r--lib/Test/Harness/t/compat/test-harness-compat.t29
-rw-r--r--lib/Test/Harness/t/grammar.t30
-rw-r--r--lib/Test/Harness/t/harness.t69
-rw-r--r--lib/Test/Harness/t/iterators.t32
-rw-r--r--lib/Test/Harness/t/multiplexer.t12
-rw-r--r--lib/Test/Harness/t/object.t37
-rwxr-xr-xlib/Test/Harness/t/parse.t122
-rw-r--r--lib/Test/Harness/t/parser-config.t46
-rw-r--r--lib/Test/Harness/t/parser-subclass.t88
-rw-r--r--lib/Test/Harness/t/premature-bailout.t9
-rw-r--r--lib/Test/Harness/t/process.t14
-rw-r--r--lib/Test/Harness/t/prove.t7
-rw-r--r--lib/Test/Harness/t/proveenv.t17
-rw-r--r--lib/Test/Harness/t/proverun.t21
-rw-r--r--lib/Test/Harness/t/regression.t4
-rw-r--r--lib/Test/Harness/t/results.t29
-rw-r--r--lib/Test/Harness/t/scheduler.t225
-rw-r--r--lib/Test/Harness/t/source.t45
-rw-r--r--lib/Test/Harness/t/spool.t5
-rwxr-xr-xlib/Test/Harness/t/streams.t14
-rw-r--r--lib/Test/Harness/t/testargs.t6
-rw-r--r--lib/Test/Harness/t/unicode.t1
-rw-r--r--lib/Test/Harness/t/yamlish.t20
33 files changed, 828 insertions, 255 deletions
diff --git a/lib/Test/Harness.pm b/lib/Test/Harness.pm
index 17e891653b..4f0164eee3 100644
--- a/lib/Test/Harness.pm
+++ b/lib/Test/Harness.pm
@@ -28,6 +28,7 @@ use vars qw(
$Timer
$Strap
$has_time_hires
+ $IgnoreExit
);
# $ML $Last_ML_Print
@@ -43,11 +44,11 @@ Test::Harness - Run Perl standard test scripts with statistics
=head1 VERSION
-Version 3.10
+Version 3.13
=cut
-$VERSION = '3.10';
+$VERSION = '3.13';
# Backwards compatibility for exportable variable names.
*verbose = *Verbose;
@@ -73,8 +74,9 @@ $Debug = $ENV{HARNESS_DEBUG} || 0;
$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;
-$Color = $ENV{HARNESS_COLOR} || 0;
+$Timer = $ENV{HARNESS_TIMER} || 0;
+$Color = $ENV{HARNESS_COLOR} || 0;
+$IgnoreExit = $ENV{HARNESS_IGNORE_EXIT} || 0;
=head1 SYNOPSIS
@@ -225,9 +227,7 @@ sub _new_harness {
my $sub_args = shift || {};
my ( @lib, @switches );
- for my $opt (
- split_shell( $Switches, $ENV{HARNESS_PERL_SWITCHES} ) )
- {
+ for my $opt ( split_shell( $Switches, $ENV{HARNESS_PERL_SWITCHES} ) ) {
if ( $opt =~ /^ -I (.*) $ /x ) {
push @lib, $1;
}
@@ -243,12 +243,13 @@ sub _new_harness {
my $verbosity = ( $Verbose ? ( $Verbose !~ /\d/ ) ? 1 : $Verbose : 0 );
my $args = {
- timer => $Timer,
- directives => $Directives,
- lib => \@lib,
- switches => \@switches,
- color => $Color,
- verbosity => $verbosity,
+ timer => $Timer,
+ directives => $Directives,
+ lib => \@lib,
+ switches => \@switches,
+ color => $Color,
+ verbosity => $verbosity,
+ ignore_exit => $IgnoreExit,
};
$args->{stdout} = $sub_args->{out}
diff --git a/lib/Test/Harness/Changes b/lib/Test/Harness/Changes
index ff7eee0482..2051eab790 100644
--- a/lib/Test/Harness/Changes
+++ b/lib/Test/Harness/Changes
@@ -1,6 +1,65 @@
Revision history for Test-Harness
-3.07 2008-01-13
+3.13 2008-07-27
+ - fixed various closure related leaks
+ - made prove honour HARNESS_TIMER
+ - Applied patches supplied by Alex Vandiver
+ - add 'rules' switch to prove: allows parallel execution rules
+ to be specified on the command line.
+ - allow '**' (any path) wildcard in parallel rules
+ - fix bug report address
+ - make tprove_gtk example work again.
+
+3.12 2008-06-22
+ - applied Steve Purkis' huge refactoring patch which adds
+ configurable factories for most of the major internal classes.
+ - applied David Wheeler's patch to allow exec to be a code
+ reference.
+ - made tests more robust in the presence of -MFoo in PERL5OPT.
+
+3.11 2008-06-09
+ - applied Jim Keenan's patch that makes App::Prove::run return a
+ rather than exit (#33609)
+ - prove -r now recurses cwd rather than 't' by default (#33007)
+ - restored --ext switch to prove (#33848)
+ - added ignore_exit option to TAP::Parser and corresponding
+ interfaces to TAP::Harness and Test::Harness. Requested for
+ Parrot.
+ - Implemented rule based parallel scheduler.
+ - Moved filename -> display name mapping out of formatter. This
+ prevents the formatter's strip-extensions logic from stripping
+ extensions from supplied descriptions.
+ - Only strip extensions from test names if all tests have the
+ same extension. Previously we stripped extensions if all names
+ had /any/ extension making it impossible to distinguish tests
+ whose name differed only in the extension.
+ - Removed privacy test that made it impossible to subclass
+ TAP::Parser.
+ - Delayed initialisation of grammar making it easier to replace
+ the TAP::Parser stream after instantiation.
+ - Make it possible to supply import parameters to a replacement
+ harness with prove.
+ - Make it possible to replace either _grammar /or/ _stream
+ before reading from a TAP::Parser.
+
+3.10 2008-02-26
+ - fix undefined value warnings with bleadperl.
+ - added pragma support.
+ - fault unknown TAP tokens under strict pragma.
+
+3.09 2008-02-10
+ - support for HARNESS_PERL_SWITCHES containing things like
+ '-e "system(shift)"'.
+ - set HARNESS_IS_VERBOSE during verbose testing.
+ - documentation fixes.
+
+3.08 2008-02-08
+ - added support for 'out' option to
+ Test::Harness::execute_tests. See #32476. Thanks RENEEB.
+ - Fixed YAMLish handling of non-alphanumeric hash keys.
+ - Added --dry option to prove for 2.64 compatibility.
+
+3.07 2008-01-13
- prove now supports HARNESS_PERL_SWITCHES.
- restored TEST_VERBOSE to prove.
diff --git a/lib/Test/Harness/bin/prove b/lib/Test/Harness/bin/prove
index acd845a48c..ee31df8832 100644
--- a/lib/Test/Harness/bin/prove
+++ b/lib/Test/Harness/bin/prove
@@ -5,7 +5,7 @@ use App::Prove;
my $app = App::Prove->new;
$app->process_args(@ARGV);
-$app->run;
+exit( $app->run ? 0 : 1 );
__END__
@@ -23,13 +23,15 @@ Boolean options:
-v, --verbose Print all test lines.
-l, --lib Add 'lib' to the path for your tests (-Ilib).
- -b, --blib Add 'blib/lib' to the path for your tests (-Iblib/lib).
+ -b, --blib Add 'blib/lib' and 'blib/arch' to the path for your tests
-s, --shuffle Run the tests in random order.
-c, --color Colored test output (default).
--nocolor Do not color test output.
-D --dry Dry run. Show test that would have run.
+ --ext Set the extension for tests (default '.t')
-f, --failures Only show failed tests.
- --fork Fork to run harness in multiple processes
+ --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.
-r, --recurse Recursively descend into directories.
--reverse Run the tests in reverse order.
diff --git a/lib/Test/Harness/t/000-load.t b/lib/Test/Harness/t/000-load.t
index 5c952a7f27..c6d6a92531 100644
--- a/lib/Test/Harness/t/000-load.t
+++ b/lib/Test/Harness/t/000-load.t
@@ -3,7 +3,7 @@
use strict;
use lib 't/lib';
-use Test::More tests => 62;
+use Test::More tests => 74;
BEGIN {
@@ -20,11 +20,14 @@ BEGIN {
TAP::Harness
TAP::Parser::Aggregator
TAP::Parser::Grammar
+ TAP::Parser::Iterator
TAP::Parser::Iterator::Array
TAP::Parser::Iterator::Process
TAP::Parser::Iterator::Stream
- TAP::Parser::Iterator
+ TAP::Parser::IteratorFactory
TAP::Parser::Multiplexer
+ TAP::Parser::Result
+ TAP::Parser::ResultFactory
TAP::Parser::Result::Bailout
TAP::Parser::Result::Comment
TAP::Parser::Result::Plan
@@ -34,6 +37,9 @@ BEGIN {
TAP::Parser::Result::Version
TAP::Parser::Result::YAML
TAP::Parser::Result
+ TAP::Parser::Scheduler
+ TAP::Parser::Scheduler::Job
+ TAP::Parser::Scheduler::Spinner
TAP::Parser::Source::Perl
TAP::Parser::Source
TAP::Parser::YAMLish::Reader
diff --git a/lib/Test/Harness/t/aggregator.t b/lib/Test/Harness/t/aggregator.t
index 441e2ba47c..b3aff2a21f 100644
--- a/lib/Test/Harness/t/aggregator.t
+++ b/lib/Test/Harness/t/aggregator.t
@@ -1,13 +1,12 @@
#!/usr/bin/perl -wT
-
use strict;
use lib 't/lib';
use Test::More tests => 79;
use TAP::Parser;
-use TAP::Parser::Iterator;
+use TAP::Parser::IteratorFactory;
use TAP::Parser::Aggregator;
my $tap = <<'END_TAP';
@@ -21,7 +20,8 @@ not ok 4 - this is a real failure
ok 5 # skip we have no description
END_TAP
-my $stream = TAP::Parser::Iterator->new( [ split /\n/ => $tap ] );
+my $factory = TAP::Parser::IteratorFactory->new;
+my $stream = $factory->make_iterator( [ split /\n/ => $tap ] );
isa_ok $stream, 'TAP::Parser::Iterator';
my $parser1 = TAP::Parser->new( { stream => $stream } );
@@ -207,12 +207,9 @@ is $agg->todo_passed, 1,
'... and the correct number of unexpectedly succeeded tests';
ok $agg->has_problems,
'... and it should report true that there are problems';
-is $agg->get_status, 'PASS',
- '... and the status should be passing';
-ok !$agg->has_errors,
- '.... but it should not report any errors';
-ok $agg->all_passed,
- '... bonus tests should be passing tests, too';
+is $agg->get_status, 'PASS', '... and the status should be passing';
+ok !$agg->has_errors, '.... but it should not report any errors';
+ok $agg->all_passed, '... bonus tests should be passing tests, too';
# 2. !failed && !todo_passed && parse_errors
diff --git a/lib/Test/Harness/t/base.t b/lib/Test/Harness/t/base.t
index 25197f6f76..4fee54844e 100644
--- a/lib/Test/Harness/t/base.t
+++ b/lib/Test/Harness/t/base.t
@@ -89,8 +89,8 @@ package main;
ok( !$@, 'callbacks installed OK' );
my $nice_cbs = $base->_callback_for('nice_event');
- is( ref $nice_cbs, 'ARRAY', 'callbacks type ok' );
- is( scalar @$nice_cbs, 1, 'right number of callbacks' );
+ is( ref $nice_cbs, 'ARRAY', 'callbacks type ok' );
+ is( scalar @$nice_cbs, 1, 'right number of callbacks' );
my $nice_cb = $nice_cbs->[0];
ok( ref $nice_cb eq 'CODE', 'callback for nice_event returned' );
my $got = $nice_cb->('Is ');
@@ -98,16 +98,16 @@ package main;
cmp_ok( $nice, '==', 1, 'callback calls the right sub' );
my $other_cbs = $base->_callback_for('other_event');
- is( ref $other_cbs, 'ARRAY', 'callbacks type ok' );
- is( scalar @$other_cbs, 1, 'right number of callbacks' );
+ is( ref $other_cbs, 'ARRAY', 'callbacks type ok' );
+ is( scalar @$other_cbs, 1, 'right number of callbacks' );
my $other_cb = $other_cbs->[0];
ok( ref $other_cb eq 'CODE', 'callback for other_event returned' );
$other_cb->();
cmp_ok( $other, '==', -1, 'callback calls the right sub' );
my @got = $base->_make_callback( 'nice_event', 'I am ' );
- is( scalar @got, 1, 'right number of results' );
- is( $got[0], 'I am OK', 'callback via _make_callback works' );
+ is( scalar @got, 1, 'right number of results' );
+ is( $got[0], 'I am OK', 'callback via _make_callback works' );
}
{
@@ -139,16 +139,16 @@ package main;
ok( !$@, 'callback installed OK' );
my $nice_cbs = $base->_callback_for('nice_event');
- is( ref $nice_cbs, 'ARRAY', 'callbacks type ok' );
- is( scalar @$nice_cbs, 1, 'right number of callbacks' );
+ is( ref $nice_cbs, 'ARRAY', 'callbacks type ok' );
+ is( scalar @$nice_cbs, 1, 'right number of callbacks' );
my $nice_cb = $nice_cbs->[0];
ok( ref $nice_cb eq 'CODE', 'callback for nice_event returned' );
$nice_cb->();
cmp_ok( $nice, '==', 1, 'callback calls the right sub' );
my $other_cbs = $base->_callback_for('other_event');
- is( ref $other_cbs, 'ARRAY', 'callbacks type ok' );
- is( scalar @$other_cbs, 1, 'right number of callbacks' );
+ is( ref $other_cbs, 'ARRAY', 'callbacks type ok' );
+ is( scalar @$other_cbs, 1, 'right number of callbacks' );
my $other_cb = $other_cbs->[0];
ok( ref $other_cb eq 'CODE', 'callback for other_event returned' );
$other_cb->();
@@ -164,8 +164,8 @@ package main;
$base->callback( other_event => sub { $status = 'OK'; return 'Aye' } );
my $new_cbs = $base->_callback_for('other_event');
- is( ref $new_cbs, 'ARRAY', 'callbacks type ok' );
- is( scalar @$new_cbs, 2, 'right number of callbacks' );
+ is( ref $new_cbs, 'ARRAY', 'callbacks type ok' );
+ is( scalar @$new_cbs, 2, 'right number of callbacks' );
my $new_cb = $new_cbs->[1];
ok( ref $new_cb eq 'CODE', 'callback for new_event returned' );
my @got = $new_cb->();
diff --git a/lib/Test/Harness/t/callbacks.t b/lib/Test/Harness/t/callbacks.t
index b23762102c..9d0cae46c5 100644
--- a/lib/Test/Harness/t/callbacks.t
+++ b/lib/Test/Harness/t/callbacks.t
@@ -6,7 +6,7 @@ use lib 't/lib';
use Test::More tests => 10;
use TAP::Parser;
-use TAP::Parser::Iterator;
+use TAP::Parser::IteratorFactory;
my $tap = <<'END_TAP';
1..5
@@ -36,8 +36,9 @@ my %callbacks = (
}
);
-my $stream = TAP::Parser::Iterator->new( [ split /\n/ => $tap ] );
-my $parser = TAP::Parser->new(
+my $factory = TAP::Parser::IteratorFactory->new;
+my $stream = $factory->make_iterator( [ split /\n/ => $tap ] );
+my $parser = TAP::Parser->new(
{ stream => $stream,
callbacks => \%callbacks,
}
@@ -77,7 +78,7 @@ my $end = 0;
},
);
-$stream = TAP::Parser::Iterator->new( [ split /\n/ => $tap ] );
+$stream = $factory->make_iterator( [ split /\n/ => $tap ] );
$parser = TAP::Parser->new(
{ stream => $stream,
callbacks => \%callbacks,
@@ -102,7 +103,7 @@ is $end, 1, 'EOF callback correctly called';
ELSES => sub { },
);
-$stream = TAP::Parser::Iterator->new( [ split /\n/ => $tap ] );
+$stream = $factory->make_iterator( [ split /\n/ => $tap ] );
eval {
$parser = TAP::Parser->new(
{ stream => $stream,
diff --git a/lib/Test/Harness/t/compat/inc-propagation.t b/lib/Test/Harness/t/compat/inc-propagation.t
index 564297c737..ffa53700a1 100644
--- a/lib/Test/Harness/t/compat/inc-propagation.t
+++ b/lib/Test/Harness/t/compat/inc-propagation.t
@@ -22,60 +22,28 @@ use Test::More (
: ( tests => 2 )
);
-use Data::Dumper;
use Test::Harness;
# Change @INC so we ensure it's preserved.
use lib 'wibble';
-# TODO: Disabled until we find out why it's breaking on Windows. It's
-# not strictly a TODO because it seems pretty likely that it's a Windows
-# problem rather than a problem with Test::Harness.
-
-# Put a stock directory near the beginning.
-# use lib $INC[$#INC-2];
-
-my $inc = Data::Dumper->new( [ \@INC ] )->Terse(1)->Purity(1)->Dump;
-my $taint_inc
- = Data::Dumper->new( [ [ grep { $_ ne '.' } @INC ] ] )->Terse(1)->Purity(1)
- ->Dump;
-
-# The tail of @INC is munged during core testing. We're only *really*
-# interested in whether 'wibble' makes it anyway.
-my $cmp_slice = $ENV{PERL_CORE} ? '[0..1]' : '';
-
my $test_template = <<'END';
#!/usr/bin/perl %s
use Test::More tests => 2;
-sub _strip_dups {
- my %%dups;
- # Drop '.' which sneaks in on some platforms
- my @r = grep { $_ ne '.' } grep { !$dups{$_}++ } @_;
- return @r%s;
-}
-
# Make sure we did something sensible with PERL5LIB
like $ENV{PERL5LIB}, qr{wibble};
+ok grep { $_ eq 'wibble' } @INC;
-is_deeply(
- [_strip_dups(@INC)],
- [_strip_dups(@{%s})],
- '@INC propagated to test'
-) or do {
- diag join ",\n", _strip_dups(@INC);
- diag '-----------------';
- diag join ",\n", _strip_dups(@{%s});
-};
END
open TEST, ">inc_check.t.tmp";
-printf TEST $test_template, '', $cmp_slice, $inc, $inc;
+printf TEST $test_template, '';
close TEST;
open TEST, ">inc_check_taint.t.tmp";
-printf TEST $test_template, '-T', $cmp_slice, $taint_inc, $taint_inc;
+printf TEST $test_template, '-T';
close TEST;
END { 1 while unlink 'inc_check_taint.t.tmp', 'inc_check.t.tmp'; }
diff --git a/lib/Test/Harness/t/compat/inc_taint.t b/lib/Test/Harness/t/compat/inc_taint.t
index f0101c396f..06a8e237bd 100644
--- a/lib/Test/Harness/t/compat/inc_taint.t
+++ b/lib/Test/Harness/t/compat/inc_taint.t
@@ -1,12 +1,12 @@
#!/usr/bin/perl -w
BEGIN {
- if( $ENV{PERL_CORE} ) {
+ if ( $ENV{PERL_CORE} ) {
chdir 't';
- @INC = ('../lib', 'lib');
+ @INC = ( '../lib', 'lib' );
}
else {
- use lib 't/lib';
+ use lib 't/lib';
}
}
diff --git a/lib/Test/Harness/t/compat/regression.t b/lib/Test/Harness/t/compat/regression.t
index d8105c9f7f..1d848f9174 100644
--- a/lib/Test/Harness/t/compat/regression.t
+++ b/lib/Test/Harness/t/compat/regression.t
@@ -7,6 +7,7 @@ use Test::More tests => 1;
use Test::Harness;
{
+
#28567
unshift @INC, 'wibble';
my @before = Test::Harness::_filtered_inc();
diff --git a/lib/Test/Harness/t/compat/test-harness-compat.t b/lib/Test/Harness/t/compat/test-harness-compat.t
index 5709d7a185..480d6d8d70 100644
--- a/lib/Test/Harness/t/compat/test-harness-compat.t
+++ b/lib/Test/Harness/t/compat/test-harness-compat.t
@@ -9,6 +9,7 @@ BEGIN {
}
use strict;
+
use lib 't/lib';
use Test::More;
@@ -52,7 +53,7 @@ local $ENV{HARNESS_PERL_SWITCHES};
head_end head_fail inc_taint junk_before_plan lone_not_bug
no_nums no_output schwern sequence_misparse shbang_misparse
simple simple_fail skip skip_nomsg skipall skipall_nomsg
- stdout_stderr switches taint todo_inline
+ stdout_stderr taint todo_inline
todo_misparse too_many vms_nit
)
) => {
@@ -129,14 +130,6 @@ local $ENV{HARNESS_PERL_SWITCHES};
'name' => 't/sample-tests/simple_fail',
'wstat' => ''
},
- 't/sample-tests/switches' => {
- 'canon' => 1,
- 'estat' => '',
- 'failed' => 1,
- 'max' => 1,
- 'name' => 't/sample-tests/switches',
- 'wstat' => ''
- },
't/sample-tests/todo_misparse' => {
'canon' => 1,
'estat' => '',
@@ -173,15 +166,15 @@ local $ENV{HARNESS_PERL_SWITCHES};
}
},
'totals' => {
- 'bad' => 13,
+ 'bad' => 12,
'bonus' => 1,
- 'files' => 28,
+ 'files' => 27,
'good' => 15,
- 'max' => 77,
+ 'max' => 76,
'ok' => 78,
'skipped' => 2,
'sub_skipped' => 2,
- 'tests' => 28,
+ 'tests' => 27,
'todo' => 2
}
},
@@ -603,6 +596,9 @@ local $ENV{HARNESS_PERL_SWITCHES};
}
},
'switches' => {
+ 'skip_if' => sub {
+ ( $ENV{PERL5OPT} || '' ) =~ m{(?:^|\s)-[dM]};
+ },
'failed' => {
't/sample-tests/switches' => {
'canon' => 1,
@@ -814,6 +810,13 @@ local $ENV{HARNESS_PERL_SWITCHES};
if ( $result->{require} && $] < $result->{require} ) {
skip "Test requires Perl $result->{require}, we have $]", 4;
}
+
+ if ( my $skip_if = $result->{skip_if} ) {
+ skip
+ "Test '$test_key' can't run properly in this environment", 4
+ if $skip_if->();
+ }
+
my @test_names = split( /,/, $test_key );
my @test_files
= map { File::Spec->catfile( $TEST_DIR, $_ ) } @test_names;
diff --git a/lib/Test/Harness/t/grammar.t b/lib/Test/Harness/t/grammar.t
index 6d572f9082..f1521ede5e 100644
--- a/lib/Test/Harness/t/grammar.t
+++ b/lib/Test/Harness/t/grammar.t
@@ -1,10 +1,20 @@
#!/usr/bin/perl -w
use strict;
-use lib 't/lib';
+
+BEGIN {
+ if ( $ENV{PERL_CORE} ) {
+ chdir 't';
+ @INC = ( '../lib', 'lib' );
+ }
+ else {
+ unshift @INC, 't/lib';
+ }
+}
use Test::More tests => 94;
+use EmptyParser;
use TAP::Parser::Grammar;
use TAP::Parser::Iterator::Array;
@@ -33,8 +43,9 @@ sub handle_unicode { }
package main;
my $stream = SS->new;
+my $parser = EmptyParser->new;
can_ok $GRAMMAR, 'new';
-my $grammar = $GRAMMAR->new($stream);
+my $grammar = $GRAMMAR->new( { stream => $stream, parser => $parser } );
isa_ok $grammar, $GRAMMAR, '... and the object it returns';
# Note: all methods are actually class methods. See the docs for the reason
@@ -341,9 +352,9 @@ is_deeply $token, $expected,
# tokenize
{
- my $stream = SS->new;
-
- my $grammar = $GRAMMAR->new($stream);
+ my $stream = SS->new;
+ my $parser = EmptyParser->new;
+ my $grammar = $GRAMMAR->new( { stream => $stream, parser => $parser } );
my $plan = '';
@@ -357,7 +368,8 @@ is_deeply $token, $expected,
# _make_plan_token
{
- my $grammar = $GRAMMAR->new;
+ my $parser = EmptyParser->new;
+ my $grammar = $GRAMMAR->new( { parser => $parser } );
my $plan
= '1..1 # SKIP with explanation'; # trigger warning in _make_plan_token
@@ -384,9 +396,9 @@ is_deeply $token, $expected,
# _make_yaml_token
{
- my $stream = SS->new;
-
- my $grammar = $GRAMMAR->new($stream);
+ my $stream = SS->new;
+ my $parser = EmptyParser->new;
+ my $grammar = $GRAMMAR->new( { stream => $stream, parser => $parser } );
$grammar->set_version(13);
diff --git a/lib/Test/Harness/t/harness.t b/lib/Test/Harness/t/harness.t
index 484f2108b9..70ff42e452 100644
--- a/lib/Test/Harness/t/harness.t
+++ b/lib/Test/Harness/t/harness.t
@@ -22,7 +22,7 @@ my $HARNESS = 'TAP::Harness';
my $source_tests = $ENV{PERL_CORE} ? 'lib/source_tests' : 't/source_tests';
my $sample_tests = $ENV{PERL_CORE} ? 'lib/sample-tests' : 't/sample-tests';
-plan tests => 106;
+plan tests => 113;
# note that this test will always pass when run through 'prove'
ok $ENV{HARNESS_ACTIVE}, 'HARNESS_ACTIVE env variable should be set';
@@ -536,6 +536,27 @@ SKIP: {
is( $answer, "All tests successful.\n", 'cat meows' );
}
+# make sure that we can exec with a code ref.
+{
+ my $capture = IO::c55Capture->new_handle;
+ my $harness = TAP::Harness->new(
+ { verbosity => -2,
+ stdout => $capture,
+ exec => sub {undef},
+ }
+ );
+
+ _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;
@@ -820,3 +841,49 @@ sub _runtests {
$source_tests, 'harness'
);
}
+
+{
+
+ # test name munging
+ my @cases = (
+ { name => 'all the same',
+ input => [ 'foo.t', 'bar.t', 'fletz.t' ],
+ output => [
+ [ 'foo.t', 'foo' ], [ 'bar.t', 'bar' ], [ 'fletz.t', 'fletz' ]
+ ],
+ },
+ { name => 'all the same, already cooked',
+ input => [ 'foo.t', [ 'bar.t', 'brip' ], 'fletz.t' ],
+ output => [
+ [ 'foo.t', 'foo' ], [ 'bar.t', 'brip' ],
+ [ 'fletz.t', 'fletz' ]
+ ],
+ },
+ { name => 'different exts',
+ input => [ 'foo.t', 'bar.u', 'fletz.v' ],
+ output => [
+ [ 'foo.t', 'foo.t' ], [ 'bar.u', 'bar.u' ],
+ [ 'fletz.v', 'fletz.v' ]
+ ],
+ },
+ { name => 'different exts, one already cooked',
+ input => [ 'foo.t', [ 'bar.u', 'bam' ], 'fletz.v' ],
+ output => [
+ [ 'foo.t', 'foo.t' ], [ 'bar.u', 'bam' ],
+ [ 'fletz.v', 'fletz.v' ]
+ ],
+ },
+ { name => 'different exts, two already cooked',
+ input => [ 'foo.t', [ 'bar.u', 'bam.q' ], [ 'fletz.v', 'boo' ] ],
+ output => [
+ [ 'foo.t', 'foo.t' ], [ 'bar.u', 'bam.q' ],
+ [ 'fletz.v', 'boo' ]
+ ],
+ },
+ );
+
+ for my $case (@cases) {
+ is_deeply [ TAP::Harness->_add_descriptions( @{ $case->{input} } ) ],
+ $case->{output}, '_add_descriptions: ' . $case->{name};
+ }
+}
diff --git a/lib/Test/Harness/t/iterators.t b/lib/Test/Harness/t/iterators.t
index 44d2004baf..11b2899b12 100644
--- a/lib/Test/Harness/t/iterators.t
+++ b/lib/Test/Harness/t/iterators.t
@@ -7,7 +7,7 @@ use Test::More tests => 76;
use File::Spec;
use TAP::Parser;
-use TAP::Parser::Iterator;
+use TAP::Parser::IteratorFactory;
use Config;
sub array_ref_from {
@@ -41,8 +41,10 @@ my @schedule = (
source => {
command => [
$^X,
- File::Spec->catfile( ($ENV{PERL_CORE} ? 'lib' : 't'),
- 'sample-tests', 'out_err_mix' )
+ File::Spec->catfile(
+ ( $ENV{PERL_CORE} ? 'lib' : 't' ),
+ 'sample-tests', 'out_err_mix'
+ )
],
merge => 1,
setup => $setup,
@@ -79,6 +81,7 @@ sub _can_open3 {
return $^O eq 'MSWin32' || $Config{d_fork};
}
+my $factory = TAP::Parser::IteratorFactory->new;
for my $test (@schedule) {
SKIP: {
my $name = $test->{name};
@@ -86,9 +89,12 @@ for my $test (@schedule) {
skip "No open3", $need_open3 if $need_open3 && !_can_open3();
my $subclass = $test->{subclass};
my $source = $test->{source};
- my $class = $test->{class} || 'TAP::Parser::Iterator';
- ok my $iter = $class->new($source),
- "$name: We should be able to create a new iterator";
+ my $class = $test->{class};
+ my $iter
+ = $class
+ ? $class->new($source)
+ : $factory->make_iterator($source);
+ ok $iter, "$name: We should be able to create a new iterator";
isa_ok $iter, 'TAP::Parser::Iterator',
'... and the object it returns';
isa_ok $iter, $subclass, '... and the object it returns';
@@ -126,7 +132,7 @@ for my $test (@schedule) {
# coverage tests for the ctor
- my $stream = TAP::Parser::Iterator->new( IO::Handle->new );
+ my $stream = $factory->make_iterator( IO::Handle->new );
isa_ok $stream, 'TAP::Parser::Iterator::Stream';
@@ -135,7 +141,7 @@ for my $test (@schedule) {
eval {
local $SIG{__DIE__} = sub { push @die, @_ };
- TAP::Parser::Iterator->new( \1 ); # a ref to a scalar
+ $factory->make_iterator( \1 ); # a ref to a scalar
};
is @die, 1, 'coverage of error case';
@@ -148,7 +154,7 @@ for my $test (@schedule) {
# coverage test for VMS case
- my $stream = TAP::Parser::Iterator->new(
+ my $stream = $factory->make_iterator(
[ 'not ',
'ok 1 - I hate VMS',
]
@@ -159,7 +165,7 @@ for my $test (@schedule) {
# coverage test for VMS case - nothing after 'not'
- $stream = TAP::Parser::Iterator->new(
+ $stream = $factory->make_iterator(
[ 'not ',
]
);
@@ -177,7 +183,7 @@ SKIP: {
eval {
local $SIG{__DIE__} = sub { push @die, @_ };
- TAP::Parser::Iterator->new( {} );
+ $factory->make_iterator( {} );
};
is @die, 1, 'coverage testing for TPI::Process';
@@ -185,7 +191,7 @@ SKIP: {
like pop @die, qr/Must supply a command to execute/,
'...and we died as expected';
- my $parser = TAP::Parser::Iterator->new(
+ my $parser = $factory->make_iterator(
{ command => [
$^X,
File::Spec->catfile( 't', 'sample-tests', 'out_err_mix' )
@@ -194,7 +200,7 @@ SKIP: {
}
);
- is $parser->{err}, '', 'confirm we set err to empty string';
+ is $parser->{err}, '', 'confirm we set err to empty string';
is $parser->{sel}, undef, '...and selector to undef';
# And then we read from the parser to sidestep the Mac OS / open3
diff --git a/lib/Test/Harness/t/multiplexer.t b/lib/Test/Harness/t/multiplexer.t
index e74c15cd07..dd988dcee1 100644
--- a/lib/Test/Harness/t/multiplexer.t
+++ b/lib/Test/Harness/t/multiplexer.t
@@ -56,8 +56,8 @@ my @schedule = (
return [
TAP::Parser->new(
{ source => File::Spec->catfile(
- ($ENV{PERL_CORE} ? 'lib' : 't'), 'sample-tests',
- 'simple'
+ ( $ENV{PERL_CORE} ? 'lib' : 't' ), 'sample-tests',
+ 'simple'
),
}
),
@@ -76,8 +76,8 @@ my @schedule = (
return map {
[ TAP::Parser->new(
{ source => File::Spec->catfile(
- ($ENV{PERL_CORE} ? 'lib' : 't'),
- 'sample-tests', 'simple'
+ ( $ENV{PERL_CORE} ? 'lib' : 't' ),
+ 'sample-tests', 'simple'
),
}
),
@@ -116,8 +116,8 @@ my @schedule = (
( map {
[ TAP::Parser->new(
{ source => File::Spec->catfile(
- ($ENV{PERL_CORE} ? 'lib' : 't'),
- 'sample-tests', 'simple'
+ ( $ENV{PERL_CORE} ? 'lib' : 't' ),
+ 'sample-tests', 'simple'
),
}
),
diff --git a/lib/Test/Harness/t/object.t b/lib/Test/Harness/t/object.t
new file mode 100644
index 0000000000..b1a4dd0b98
--- /dev/null
+++ b/lib/Test/Harness/t/object.t
@@ -0,0 +1,37 @@
+#!/usr/bin/perl -wT
+
+use strict;
+use lib 't/lib';
+
+use Test::More tests => 7;
+
+use_ok('TAP::Object');
+
+can_ok( 'TAP::Object', 'new' );
+can_ok( 'TAP::Object', '_initialize' );
+can_ok( 'TAP::Object', '_croak' );
+
+{
+
+ package TAP::TestObj;
+ use vars qw(@ISA);
+ @ISA = qw(TAP::Object);
+
+ sub _initialize {
+ my $self = shift;
+ $self->{init} = 1;
+ $self->{args} = [@_];
+ return $self;
+ }
+}
+
+# I know these tests are simple, but they're documenting the base API, so
+# necessary none-the-less...
+my $obj = TAP::TestObj->new( 'foo', { bar => 'baz' } );
+ok( $obj->{init}, '_initialize' );
+is_deeply( $obj->{args}, [ 'foo', { bar => 'baz' } ], '_initialize: args' );
+
+eval { $obj->_croak('eek') };
+my $err = $@;
+like( $err, qr/^eek/, '_croak' );
+
diff --git a/lib/Test/Harness/t/parse.t b/lib/Test/Harness/t/parse.t
index a53ad3a746..7118199a51 100755
--- a/lib/Test/Harness/t/parse.t
+++ b/lib/Test/Harness/t/parse.t
@@ -12,13 +12,13 @@ BEGIN {
}
}
-use Test::More tests => 268;
+use Test::More tests => 282;
use IO::c55Capture;
use File::Spec;
use TAP::Parser;
-use TAP::Parser::Iterator;
+use TAP::Parser::IteratorFactory;
sub _get_results {
my $parser = shift;
@@ -41,6 +41,8 @@ my ( $PARSER, $PLAN, $PRAGMA, $TEST, $COMMENT, $BAILOUT, $UNKNOWN, $YAML, $VERSI
TAP::Parser::Result::Version
);
+my $factory = TAP::Parser::IteratorFactory->new;
+
my $tap = <<'END_TAP';
TAP version 13
1..7
@@ -220,7 +222,7 @@ ok $test->is_actual_ok,
'... and the correct boolean version of is_actual_ok()';
is $test->number, 5, '... and have the correct test number';
ok !$test->description, '... and skipped tests have no description';
-is $test->directive, 'SKIP', '... and teh correct directive';
+is $test->directive, 'SKIP', '... and the correct directive';
is $test->explanation, 'we have no description',
'... but we should have an explanation';
ok $test->has_skip, '... and it is a SKIPped test';
@@ -349,7 +351,7 @@ END_TAP
my $aref = [ split /\n/ => $tap ];
can_ok $PARSER, 'new';
-$parser = $PARSER->new( { stream => TAP::Parser::Iterator->new($aref) } );
+$parser = $PARSER->new( { stream => $factory->make_iterator($aref) } );
isa_ok $parser, $PARSER, '... and calling it should succeed';
# results() is sane?
@@ -436,29 +438,6 @@ 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';
-# coverage tests
-{
-
- # calling a TAP::Parser internal method with a 'foreign' class
-
- my $foreigner = bless {}, 'Foreigner';
-
- my @die;
-
- eval {
- local $SIG{__DIE__} = sub { push @die, @_ };
-
- TAP::Parser::_stream $foreigner, qw(a b c);
- };
-
- unless ( is @die, 1, 'coverage testing for TAP::Parser accessors' ) {
- diag " >>> $_ <<<\n" for @die;
- }
-
- like pop @die, qr/_stream[(][)] may not be set externally/,
- '... and we died with expected message';
-}
-
{
# set a spool to write to
@@ -662,10 +641,10 @@ END_TAP
_get_results($parser);
- ok !$parser->failed;
- ok $parser->todo_passed;
+ ok !$parser->failed, 'parser didnt fail';
+ ok $parser->todo_passed, '... and todo_passed is true';
- ok !$parser->has_problems, 'and has_problems is false';
+ ok !$parser->has_problems, '... and has_problems is false';
# now parse_errors
@@ -679,11 +658,11 @@ END_TAP
_get_results($parser);
- ok !$parser->failed;
- ok !$parser->todo_passed;
- ok $parser->parse_errors;
+ ok !$parser->failed, 'parser didnt fail';
+ ok !$parser->todo_passed, '... and todo_passed is false';
+ ok $parser->parse_errors, '... and parse_errors is true';
- ok $parser->has_problems;
+ ok $parser->has_problems, '... and has_problems';
# Now wait and exit are hard to do in an OS platform-independent way, so
# we won't even bother
@@ -701,27 +680,27 @@ END_TAP
$parser->wait(1);
- ok !$parser->failed;
- ok !$parser->todo_passed;
- ok !$parser->parse_errors;
+ ok !$parser->failed, 'parser didnt fail';
+ ok !$parser->todo_passed, '... and todo_passed is false';
+ ok !$parser->parse_errors, '... and parse_errors is false';
- ok $parser->wait;
+ ok $parser->wait, '... and wait is set';
- ok $parser->has_problems;
+ ok $parser->has_problems, '... and has_problems';
# and use the same for exit
$parser->wait(0);
$parser->exit(1);
- ok !$parser->failed;
- ok !$parser->todo_passed;
- ok !$parser->parse_errors;
- ok !$parser->wait;
+ ok !$parser->failed, 'parser didnt fail';
+ ok !$parser->todo_passed, '... and todo_passed is false';
+ ok !$parser->parse_errors, '... and parse_errors is false';
+ ok !$parser->wait, '... and wait is not set';
- ok $parser->exit;
+ ok $parser->exit, '... and exit is set';
- ok $parser->has_problems;
+ ok $parser->has_problems, '... and has_problems';
}
{
@@ -807,10 +786,6 @@ END_TAP
@ISA = qw(TAP::Parser::Iterator);
- sub new {
- return bless {}, shift;
- }
-
sub next_raw {
die 'this is the dying iterator';
}
@@ -840,7 +815,11 @@ END_TAP
$parser->_stream($stream);
# build a new grammar
- my $grammar = TAP::Parser::Grammar->new($stream);
+ my $grammar = TAP::Parser::Grammar->new(
+ { stream => $stream,
+ parser => $parser
+ }
+ );
# replace our grammar with this new one
$parser->_grammar($grammar);
@@ -872,7 +851,11 @@ END_TAP
$parser->_stream($stream);
# build a new grammar
- my $grammar = TAP::Parser::Grammar->new($stream);
+ my $grammar = TAP::Parser::Grammar->new(
+ { stream => $stream,
+ parser => $parser
+ }
+ );
# replace our grammar with this new one
$parser->_grammar($grammar);
@@ -1018,3 +1001,40 @@ END_TAP
is_deeply [ sort keys %reachable ], [@states], "all states reachable";
}
+
+{
+
+ # exit, wait, ignore_exit interactions
+
+ my @truth = (
+ [ 0, 0, 0, 0 ],
+ [ 0, 0, 1, 0 ],
+ [ 1, 0, 0, 1 ],
+ [ 1, 0, 1, 0 ],
+ [ 1, 1, 0, 1 ],
+ [ 1, 1, 1, 0 ],
+ [ 0, 1, 0, 1 ],
+ [ 0, 1, 1, 0 ],
+ );
+
+ for my $t (@truth) {
+ my ( $wait, $exit, $ignore_exit, $has_problems ) = @$t;
+ my $test_parser = sub {
+ my $parser = shift;
+ $parser->wait($wait);
+ $parser->exit($exit);
+ ok $has_problems ? $parser->has_problems : !$parser->has_problems,
+ "exit=$exit, wait=$wait, ignore=$ignore_exit";
+ };
+
+ my $parser = TAP::Parser->new( { tap => "1..1\nok 1\n" } );
+ $parser->ignore_exit($ignore_exit);
+ $test_parser->($parser);
+
+ $test_parser->(
+ TAP::Parser->new(
+ { tap => "1..1\nok 1\n", ignore_exit => $ignore_exit }
+ )
+ );
+ }
+}
diff --git a/lib/Test/Harness/t/parser-config.t b/lib/Test/Harness/t/parser-config.t
new file mode 100644
index 0000000000..cf0a246a03
--- /dev/null
+++ b/lib/Test/Harness/t/parser-config.t
@@ -0,0 +1,46 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+ if ( $ENV{PERL_CORE} ) {
+ chdir 't';
+ @INC = ( '../lib', 'lib' );
+ }
+ else {
+ unshift @INC, 't/lib';
+ }
+}
+
+use strict;
+use vars qw(%INIT %CUSTOM);
+
+use Test::More tests => 11;
+use File::Spec::Functions qw( catfile );
+use TAP::Parser;
+
+use_ok('MySource');
+use_ok('MyPerlSource');
+use_ok('MyGrammar');
+use_ok('MyIteratorFactory');
+use_ok('MyResultFactory');
+
+my $t_dir = $ENV{PERL_CORE} ? 'lib' : 't';
+my $source = catfile( $t_dir, 'source_tests', 'source' );
+my %customize = (
+ source_class => 'MySource',
+ perl_source_class => 'MyPerlSource',
+ grammar_class => 'MyGrammar',
+ iterator_factory_class => 'MyIteratorFactory',
+ result_factory_class => 'MyResultFactory',
+);
+my $p = TAP::Parser->new(
+ { source => $source,
+ %customize,
+ }
+);
+ok( $p, 'new customized parser' );
+
+foreach my $key ( keys %customize ) {
+ is( $p->$key(), $customize{$key}, "customized $key" );
+}
+
+# TODO: make sure these things are propogated down through the parser...
diff --git a/lib/Test/Harness/t/parser-subclass.t b/lib/Test/Harness/t/parser-subclass.t
new file mode 100644
index 0000000000..f522f89aff
--- /dev/null
+++ b/lib/Test/Harness/t/parser-subclass.t
@@ -0,0 +1,88 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+ if ( $ENV{PERL_CORE} ) {
+ chdir 't';
+ @INC = ( '../lib', 'lib' );
+ }
+ else {
+ unshift @INC, 't/lib';
+ }
+}
+
+use strict;
+use vars qw(%INIT %CUSTOM);
+
+use Test::More tests => 24;
+use File::Spec::Functions qw( catfile );
+
+use_ok('TAP::Parser::SubclassTest');
+
+# TODO: foreach my $source ( ... )
+my $t_dir = $ENV{PERL_CORE} ? 'lib' : 't';
+
+{ # perl source
+ %INIT = %CUSTOM = ();
+ my $source = catfile( $t_dir, 'subclass_tests', 'perl_source' );
+ my $p = TAP::Parser::SubclassTest->new( { source => $source } );
+
+ # The grammar is lazily constructed so we need to ask for it to
+ # trigger it's creation.
+ my $grammer = $p->_grammar;
+
+ ok( $p->{initialized}, 'new subclassed parser' );
+
+ is( $p->source_class => 'MySource', 'source_class' );
+ is( $p->perl_source_class => 'MyPerlSource', 'perl_source_class' );
+ is( $p->grammar_class => 'MyGrammar', 'grammar_class' );
+ is( $p->iterator_factory_class => 'MyIteratorFactory',
+ 'iterator_factory_class'
+ );
+ is( $p->result_factory_class => 'MyResultFactory',
+ 'result_factory_class'
+ );
+
+ is( $INIT{MyPerlSource}, 1, 'initialized MyPerlSource' );
+ is( $CUSTOM{MyPerlSource}, 1, '... and it was customized' );
+ is( $INIT{MyGrammar}, 1, 'initialized MyGrammar' );
+ is( $CUSTOM{MyGrammar}, 1, '... and it was customized' );
+
+ # make sure overrided make_* methods work...
+ %CUSTOM = ();
+ $p->make_source;
+ is( $CUSTOM{MySource}, 1, 'make custom source' );
+ $p->make_perl_source;
+ is( $CUSTOM{MyPerlSource}, 1, 'make custom perl source' );
+ $p->make_grammar;
+ is( $CUSTOM{MyGrammar}, 1, 'make custom grammar' );
+ $p->make_iterator;
+ is( $CUSTOM{MyIterator}, 1, 'make custom iterator' );
+ $p->make_result;
+ is( $CUSTOM{MyResult}, 1, 'make custom result' );
+
+ # make sure parser helpers use overrided classes too (the parser should
+ # be the central source of configuration/overriding functionality)
+ # The source is already tested above (parser doesn't keep a copy of the
+ # source currently). So only one to check is the Grammar:
+ %INIT = %CUSTOM = ();
+ my $r = $p->_grammar->tokenize;
+ isa_ok( $r, 'MyResult', 'i has results' );
+ is( $INIT{MyResult}, 1, 'initialized MyResult' );
+ is( $CUSTOM{MyResult}, 1, '... and it was customized' );
+ is( $INIT{MyResultFactory}, 1, '"initialized" MyResultFactory' );
+}
+
+SKIP: { # non-perl source
+ %INIT = %CUSTOM = ();
+ my $cat = '/bin/cat';
+ unless ( -e $cat ) {
+ skip "no '$cat'", 4;
+ }
+ my $file = catfile( $t_dir, 'data', 'catme.1' );
+ my $p = TAP::Parser::SubclassTest->new( { exec => [ $cat => $file ] } );
+
+ is( $INIT{MySource}, 1, 'initialized MySource subclass' );
+ is( $CUSTOM{MySource}, 1, '... and it was customized' );
+ is( $INIT{MyIterator}, 1, 'initialized MyIterator subclass' );
+ is( $CUSTOM{MyIterator}, 1, '... and it was customized' );
+}
diff --git a/lib/Test/Harness/t/premature-bailout.t b/lib/Test/Harness/t/premature-bailout.t
index d38e6d189a..9226a44064 100644
--- a/lib/Test/Harness/t/premature-bailout.t
+++ b/lib/Test/Harness/t/premature-bailout.t
@@ -6,7 +6,7 @@ use lib 't/lib';
use Test::More tests => 14;
use TAP::Parser;
-use TAP::Parser::Iterator;
+use TAP::Parser::IteratorFactory;
sub tap_to_lines {
my $string = shift;
@@ -26,8 +26,9 @@ Bail out! We ran out of foobar.
not ok 5
END_TAP
-my $parser = TAP::Parser->new(
- { stream => TAP::Parser::Iterator->new( tap_to_lines($tap) ),
+my $factory = TAP::Parser::IteratorFactory->new;
+my $parser = TAP::Parser->new(
+ { stream => $factory->make_iterator( tap_to_lines($tap) ),
}
);
@@ -105,7 +106,7 @@ is( $bailout->explanation, 'We ran out of foobar.',
my $more_tap = "1..1\nok 1 - input file opened\n";
my $second_parser = TAP::Parser->new(
- { stream => TAP::Parser::Iterator->new( [ split( /\n/, $more_tap ) ] ),
+ { stream => $factory->make_iterator( [ split( /\n/, $more_tap ) ] ),
}
);
diff --git a/lib/Test/Harness/t/process.t b/lib/Test/Harness/t/process.t
index e4d585e261..5adddc9017 100644
--- a/lib/Test/Harness/t/process.t
+++ b/lib/Test/Harness/t/process.t
@@ -9,9 +9,11 @@ BEGIN {
$hires = eval 'use Time::HiRes qw(sleep); 1';
}
-use Test::More ( $^O eq 'VMS' ? ( skip_all => 'VMS' )
- : $hires ? ( tests => 9 * 3 )
- : ( skip_all => 'Need Time::HiRes' ) );
+use Test::More (
+ $^O eq 'VMS' ? ( skip_all => 'VMS' )
+ : $hires ? ( tests => 9 * 3 )
+ : ( skip_all => 'Need Time::HiRes' )
+);
use File::Spec;
use TAP::Parser::Iterator::Process;
@@ -25,8 +27,10 @@ my @expect = (
'ok 5 00000',
);
-my $source = File::Spec->catfile( ($ENV{PERL_CORE} ? 'lib' : 't'),
- 'sample-tests', 'delayed' );
+my $source = File::Spec->catfile(
+ ( $ENV{PERL_CORE} ? 'lib' : 't' ),
+ 'sample-tests', 'delayed'
+);
for my $chunk_size ( 1, 4, 65536 ) {
for my $where ( 0 .. 8 ) {
diff --git a/lib/Test/Harness/t/prove.t b/lib/Test/Harness/t/prove.t
index 02d2e31202..38b9b85097 100644
--- a/lib/Test/Harness/t/prove.t
+++ b/lib/Test/Harness/t/prove.t
@@ -75,9 +75,10 @@ BEGIN { # START PLAN
# list of attributes
@ATTR = qw(
- archive argv blib color directives exec failures formatter harness
- includes lib merge parse quiet really_quiet recurse backwards
- shuffle taint_fail taint_warn verbose warnings_fail warnings_warn
+ archive argv blib color directives exec extension failures
+ formatter harness includes lib merge parse quiet really_quiet
+ recurse backwards shuffle taint_fail taint_warn verbose
+ warnings_fail warnings_warn
);
# what we expect if the 'expect' hash does not define it
diff --git a/lib/Test/Harness/t/proveenv.t b/lib/Test/Harness/t/proveenv.t
new file mode 100644
index 0000000000..be9942a043
--- /dev/null
+++ b/lib/Test/Harness/t/proveenv.t
@@ -0,0 +1,17 @@
+#!perl
+use strict;
+use lib 't/lib';
+use Test::More tests => 2;
+use App::Prove;
+
+{
+ local $ENV{HARNESS_TIMER} = 0;
+ my $prv = App::Prove->new;
+ ok !$prv->timer, 'timer set via HARNESS_TIMER';
+}
+
+{
+ local $ENV{HARNESS_TIMER} = 1;
+ my $prv = App::Prove->new;
+ ok $prv->timer, 'timer set via HARNESS_TIMER';
+}
diff --git a/lib/Test/Harness/t/proverun.t b/lib/Test/Harness/t/proverun.t
index 6cda6c4532..b40d56362d 100644
--- a/lib/Test/Harness/t/proverun.t
+++ b/lib/Test/Harness/t/proverun.t
@@ -44,7 +44,7 @@ BEGIN {
},
);
- plan tests => @SCHEDULE * 2;
+ plan tests => @SCHEDULE * 3;
}
# Waaaaay too much boilerplate
@@ -61,12 +61,6 @@ sub new {
return $self;
}
-sub _exit {
- my $self = shift;
- push @{ $self->{_log} }, [ '_exit', @_ ];
- die "Exited";
-}
-
sub get_log {
my $self = shift;
my @log = @{ $self->{_log} };
@@ -85,14 +79,17 @@ package main;
local $^W; # no warnings
- my $orig_new = \&TAP::Parser::Iterator::Process::new;
- *TAP::Parser::Iterator::Process::new = sub {
+ my $orig_new = TAP::Parser::Iterator::Process->can('new');
+
+ # Avoid "used only once" warning
+ *TAP::Parser::Iterator::Process::new
+ = *TAP::Parser::Iterator::Process::new = sub {
push @call_log, [ 'new', @_ ];
# And then new turns round and tramples on our args...
$_[1] = { %{ $_[1] } };
$orig_new->(@_);
- };
+ };
# Patch TAP::Formatter::Console;
my $orig_output = \&TAP::Formatter::Console::_output;
@@ -143,8 +140,8 @@ for my $test (@SCHEDULE) {
# Why does this make the output from the test spew out of
# our STDOUT?
- eval { $app->run };
- like $@, qr{Exited}, "$name: exited via _exit()";
+ ok eval { $app->run }, 'run returned true';
+ ok !$@, 'no errors';
my @log = get_log();
diff --git a/lib/Test/Harness/t/regression.t b/lib/Test/Harness/t/regression.t
index 5398580c7b..c029a050a9 100644
--- a/lib/Test/Harness/t/regression.t
+++ b/lib/Test/Harness/t/regression.t
@@ -2198,7 +2198,7 @@ my %samples = (
passed => TRUE,
is_ok => TRUE,
directive => 'SKIP',
- explanation => 'rope'
+ explanation => ''
},
],
plan => '1..0',
@@ -2217,7 +2217,7 @@ my %samples = (
'exit' => 0,
wait => 0,
version => 12,
- skip_all => 'rope',
+ skip_all => '(no reason given)',
},
skipall_v13 => {
results => [
diff --git a/lib/Test/Harness/t/results.t b/lib/Test/Harness/t/results.t
index 431bb7dc71..0522dd6299 100644
--- a/lib/Test/Harness/t/results.t
+++ b/lib/Test/Harness/t/results.t
@@ -3,8 +3,9 @@
use strict;
use lib 't/lib';
-use Test::More tests => 222;
+use Test::More tests => 227;
+use TAP::Parser::ResultFactory;
use TAP::Parser::Result;
use constant RESULT => 'TAP::Parser::Result';
@@ -22,6 +23,7 @@ $SIG{__WARN__} = sub { $warning = shift };
# found in the regression tests.
#
+my $factory = TAP::Parser::ResultFactory->new;
my %inherited_methods = (
is_plan => '',
is_test => '',
@@ -46,11 +48,32 @@ like $warning, qr/^\Qpassed() is deprecated. Please use "is_ok()"/,
'... but it should emit a deprecation warning';
can_ok RESULT, 'new';
-eval { RESULT->new( { type => 'no_such_type' } ) };
+
+can_ok $factory, 'make_result';
+eval { $factory->make_result( { type => 'no_such_type' } ) };
ok my $error = $@, '... and calling it with an unknown class should fail';
like $error, qr/^Could not determine class for.*no_such_type/s,
'... with an appropriate error message';
+# register new Result types:
+can_ok $factory, 'class_for';
+can_ok $factory, 'register_type';
+{
+
+ package MyResult;
+ use strict;
+ use vars qw($VERSION @ISA);
+ @ISA = 'TAP::Parser::Result';
+ TAP::Parser::ResultFactory->register_type( 'my_type' => __PACKAGE__ );
+}
+
+{
+ my $r = eval { $factory->make_result( { type => 'my_type' } ) };
+ my $error = $@;
+ isa_ok( $r, 'MyResult', 'register custom type' );
+ ok( !$error, '... and no error' );
+}
+
#
# test unknown tokens
#
@@ -246,7 +269,7 @@ sub run_tests {
sub instantiate {
my $instantiated = shift;
my $class = $instantiated->{class};
- ok my $result = RESULT->new( $instantiated->{data} ),
+ ok my $result = $factory->make_result( $instantiated->{data} ),
'Creating $class results should succeed';
isa_ok $result, $class, '.. and the object it returns';
return $result;
diff --git a/lib/Test/Harness/t/scheduler.t b/lib/Test/Harness/t/scheduler.t
new file mode 100644
index 0000000000..b2742078b1
--- /dev/null
+++ b/lib/Test/Harness/t/scheduler.t
@@ -0,0 +1,225 @@
+#!/usr/bin/perl -w
+
+use strict;
+use lib 't/lib';
+
+use Test::More;
+use TAP::Parser::Scheduler;
+
+my $perl_rules = {
+ par => [
+ { seq => '../ext/DB_File/t/*' },
+ { seq => '../ext/IO_Compress_Zlib/t/*' },
+ { seq => '../lib/CPANPLUS/*' },
+ { seq => '../lib/ExtUtils/t/*' },
+ '*'
+ ]
+};
+
+my $incomplete_rules = { par => [ { seq => [ '*A', '*D' ] } ] };
+
+my $some_tests = [
+ '../ext/DB_File/t/A',
+ 'foo',
+ '../ext/DB_File/t/B',
+ '../ext/DB_File/t/C',
+ '../lib/CPANPLUS/D',
+ '../lib/CPANPLUS/E',
+ 'bar',
+ '../lib/CPANPLUS/F',
+ '../ext/DB_File/t/D',
+ '../ext/DB_File/t/E',
+ '../ext/DB_File/t/F',
+];
+
+my @schedule = (
+ { name => 'Sequential, no rules',
+ tests => $some_tests,
+ jobs => 1,
+ },
+ { name => 'Sequential, Perl rules',
+ rules => $perl_rules,
+ tests => $some_tests,
+ jobs => 1,
+ },
+ { name => 'Two in parallel, Perl rules',
+ rules => $perl_rules,
+ tests => $some_tests,
+ jobs => 2,
+ },
+ { name => 'Massively parallel, Perl rules',
+ rules => $perl_rules,
+ tests => $some_tests,
+ jobs => 1000,
+ },
+ { name => 'Massively parallel, no rules',
+ tests => $some_tests,
+ jobs => 1000,
+ },
+ { name => 'Sequential, incomplete rules',
+ rules => $incomplete_rules,
+ tests => $some_tests,
+ jobs => 1,
+ },
+ { name => 'Two in parallel, incomplete rules',
+ rules => $incomplete_rules,
+ tests => $some_tests,
+ jobs => 2,
+ },
+ { name => 'Massively parallel, incomplete rules',
+ rules => $incomplete_rules,
+ tests => $some_tests,
+ jobs => 1000,
+ },
+);
+
+plan tests => @schedule * 2 + 266;
+
+for my $test (@schedule) {
+ test_scheduler(
+ $test->{name},
+ $test->{tests},
+ $test->{rules},
+ $test->{jobs}
+ );
+}
+
+# An ad-hoc test
+
+{
+ my @tests = qw(
+ A1 A2 A3 B1 C1 C8 C5 C7 C4 C6 C3 C2 C9 D1 D2 D3 E3 E2 E1
+ );
+
+ my $rules = {
+ par => [
+ { seq => 'A*' },
+ { par => 'B*' },
+ { seq => [ 'C1', 'C2' ] },
+ { par => [
+ { seq => [ 'C3', 'C4', 'C5' ] },
+ { seq => [ 'C6', 'C7', 'C8' ] }
+ ]
+ },
+ { seq => [
+ { par => ['D*'] },
+ { par => ['E*'] }
+ ]
+ },
+ ]
+ };
+
+ my $scheduler = TAP::Parser::Scheduler->new(
+ tests => \@tests,
+ rules => $rules
+ );
+
+ # diag $scheduler->as_string;
+
+ my $A1 = ok_job( $scheduler, 'A1' );
+ my $B1 = ok_job( $scheduler, 'B1' );
+ finish($A1);
+ my $A2 = ok_job( $scheduler, 'A2' );
+ my $C1 = ok_job( $scheduler, 'C1' );
+ finish( $A2, $C1 );
+ my $A3 = ok_job( $scheduler, 'A3' );
+ my $C2 = ok_job( $scheduler, 'C2' );
+ finish( $A3, $C2 );
+ my $C3 = ok_job( $scheduler, 'C3' );
+ my $C6 = ok_job( $scheduler, 'C6' );
+ my $D1 = ok_job( $scheduler, 'D1' );
+ my $D2 = ok_job( $scheduler, 'D2' );
+ finish($C6);
+ my $C7 = ok_job( $scheduler, 'C7' );
+ my $D3 = ok_job( $scheduler, 'D3' );
+ ok_job( $scheduler, '#' );
+ ok_job( $scheduler, '#' );
+ finish( $D3, $C3, $D1, $B1 );
+ my $C4 = ok_job( $scheduler, 'C4' );
+ finish( $C4, $C7 );
+ my $C5 = ok_job( $scheduler, 'C5' );
+ my $C8 = ok_job( $scheduler, 'C8' );
+ ok_job( $scheduler, '#' );
+ finish($D2);
+ my $E3 = ok_job( $scheduler, 'E3' );
+ my $E2 = ok_job( $scheduler, 'E2' );
+ my $E1 = ok_job( $scheduler, 'E1' );
+ finish( $E1, $E2, $E3, $C5, $C8 );
+ my $C9 = ok_job( $scheduler, 'C9' );
+ ok_job( $scheduler, undef );
+}
+
+{
+ my @tests = ();
+ for my $t ( 'A' .. 'Z' ) {
+ push @tests, map {"$t$_"} 1 .. 9;
+ }
+ my $rules = { par => [ map { { seq => "$_*" } } 'A' .. 'Z' ] };
+
+ my $scheduler = TAP::Parser::Scheduler->new(
+ tests => \@tests,
+ rules => $rules
+ );
+
+ # diag $scheduler->as_string;
+
+ for my $n ( 1 .. 9 ) {
+ my @got = ();
+ push @got, ok_job( $scheduler, "$_$n" ) for 'A' .. 'Z';
+ ok_job( $scheduler, $n == 9 ? undef : '#' );
+ finish(@got);
+ }
+}
+
+sub finish { $_->finish for @_ }
+
+sub ok_job {
+ my ( $scheduler, $want ) = @_;
+ my $job = $scheduler->get_job;
+ if ( !defined $want ) {
+ ok !defined $job, 'undef';
+ }
+ elsif ( $want eq '#' ) {
+ ok $job->is_spinner, 'spinner';
+ }
+ else {
+ is $job->filename, $want, $want;
+ }
+ return $job;
+}
+
+sub test_scheduler {
+ my ( $name, $tests, $rules, $jobs ) = @_;
+
+ ok my $scheduler = TAP::Parser::Scheduler->new(
+ tests => $tests,
+ defined $rules ? ( rules => $rules ) : (),
+ ),
+ "$name: new";
+
+ # diag $scheduler->as_string;
+
+ my @pipeline = ();
+ my @got = ();
+
+ while ( defined( my $job = $scheduler->get_job ) ) {
+
+ # diag $scheduler->as_string;
+ if ( $job->is_spinner || @pipeline >= $jobs ) {
+ die "Oops! Spinner!" unless @pipeline;
+ my $done = shift @pipeline;
+ $done->finish;
+
+ # diag "Completed ", $done->filename;
+ }
+ next if $job->is_spinner;
+
+ # diag " Got ", $job->filename;
+ push @pipeline, $job;
+
+ push @got, $job->filename;
+ }
+
+ is_deeply [ sort @got ], [ sort @$tests ], "$name: got all tests";
+}
+
diff --git a/lib/Test/Harness/t/source.t b/lib/Test/Harness/t/source.t
index cfdf751f72..8f7e60f2e3 100644
--- a/lib/Test/Harness/t/source.t
+++ b/lib/Test/Harness/t/source.t
@@ -12,14 +12,16 @@ BEGIN {
use strict;
-use Test::More tests => 30;
+use Test::More tests => 26;
use File::Spec;
+use EmptyParser;
use TAP::Parser::Source;
use TAP::Parser::Source::Perl;
-my $test = File::Spec->catfile(
+my $parser = EmptyParser->new;
+my $test = File::Spec->catfile(
( $ENV{PERL_CORE} ? 'lib' : 't' ), 'source_tests',
'source'
);
@@ -39,7 +41,7 @@ ok $source->source( [ $perl, '-It/lib', '-T', $test ] ),
'... and calling it with valid args should succeed';
can_ok $source, 'get_stream';
-my $stream = $source->get_stream;
+my $stream = $source->get_stream($parser);
isa_ok $stream, 'TAP::Parser::Iterator::Process',
'get_stream returns the right object';
@@ -57,7 +59,7 @@ ok $source->source( [$test] ),
'... and calling it with valid args should succeed';
can_ok $source, 'get_stream';
-$stream = $source->get_stream;
+$stream = $source->get_stream($parser);
isa_ok $stream, 'TAP::Parser::Iterator::Process',
'... and the object it returns';
@@ -79,7 +81,7 @@ ok( grep( $_ =~ /^['"]?-T['"]?$/, $source->_switches ),
# coverage for method get_steam
- my $source = TAP::Parser::Source->new();
+ my $source = TAP::Parser::Source->new( { parser => $parser } );
my @die;
@@ -94,36 +96,3 @@ ok( grep( $_ =~ /^['"]?-T['"]?$/, $source->_switches ),
like pop @die, qr/No command found!/, '...and it failed as expect';
}
-{
-
- # coverage testing for error
-
- my $source = TAP::Parser::Source->new();
-
- my $error = $source->error;
-
- is $error, undef, 'coverage testing for error()';
-
- $source->error('save me');
-
- $error = $source->error;
-
- is $error, 'save me', '...and we got the expected message';
-}
-
-{
-
- # coverage testing for exit
-
- my $source = TAP::Parser::Source->new();
-
- my $exit = $source->exit;
-
- is $exit, undef, 'coverage testing for exit()';
-
- $source->exit('save me');
-
- $exit = $source->exit;
-
- is $exit, 'save me', '...and we got the expected message';
-}
diff --git a/lib/Test/Harness/t/spool.t b/lib/Test/Harness/t/spool.t
index 428423ac02..deb1a0205f 100644
--- a/lib/Test/Harness/t/spool.t
+++ b/lib/Test/Harness/t/spool.t
@@ -117,8 +117,9 @@ ok 1 - input file opened
END_TAP
my $parser = TAP::Parser->new(
- { spool => $spoolHandle,
- stream => TAP::Parser::Iterator->new( [ split /\n/ => $tap ] )
+ { spool => $spoolHandle,
+ stream =>
+ TAP::Parser::IteratorFactory->new( [ split /\n/ => $tap ] )
}
);
diff --git a/lib/Test/Harness/t/streams.t b/lib/Test/Harness/t/streams.t
index fba0591b3e..b312ae8367 100755
--- a/lib/Test/Harness/t/streams.t
+++ b/lib/Test/Harness/t/streams.t
@@ -6,13 +6,15 @@ use lib 't/lib';
use Test::More tests => 47;
use TAP::Parser;
-use TAP::Parser::Iterator;
+use TAP::Parser::IteratorFactory;
-my ( $STREAMED, $ITER ) = ( 'TAP::Parser', 'TAP::Parser::Iterator' );
+my $STREAMED = 'TAP::Parser';
+my $ITER = 'TAP::Parser::Iterator';
my $ITER_FH = "${ITER}::Stream";
my $ITER_ARRAY = "${ITER}::Array";
-my $stream = TAP::Parser::Iterator->new( \*DATA );
+my $factory = TAP::Parser::IteratorFactory->new;
+my $stream = $factory->make_iterator( \*DATA );
isa_ok $stream, 'TAP::Parser::Iterator';
my $parser = TAP::Parser->new( { stream => $stream } );
isa_ok $parser, 'TAP::Parser',
@@ -55,7 +57,7 @@ ok 5 # skip we have no description
1..5
END_TAP
-$stream = $ITER->new( [ split /\n/ => $tap ] );
+$stream = $factory->make_iterator( [ split /\n/ => $tap ] );
ok $parser = TAP::Parser->new( { stream => $stream } ),
'Now we create a parser with the plan at the end';
isa_ok $parser->_stream, $ITER_ARRAY,
@@ -93,7 +95,7 @@ not ok 4 - this is a real failure
ok 5 # skip we have no description
END_TAP
-$stream = $ITER->new( [ split /\n/ => $tap ] );
+$stream = $factory->make_iterator( [ split /\n/ => $tap ] );
ok $parser = TAP::Parser->new( { stream => $stream } ),
'Now we create a parser with a plan as the second line';
@@ -131,7 +133,7 @@ not ok 4 - this is a real failure
ok 5 # skip we have no description
END_TAP
-$stream = $ITER->new( [ split /\n/ => $tap ] );
+$stream = $factory->make_iterator( [ split /\n/ => $tap ] );
ok $parser = TAP::Parser->new( { stream => $stream } ),
'Now we create a parser with the plan as the second to last line';
diff --git a/lib/Test/Harness/t/testargs.t b/lib/Test/Harness/t/testargs.t
index 76ee9a5bb6..9160c5909b 100644
--- a/lib/Test/Harness/t/testargs.t
+++ b/lib/Test/Harness/t/testargs.t
@@ -13,8 +13,10 @@ use TAP::Parser;
use TAP::Harness;
use App::Prove;
-my $test = File::Spec->catfile( ($ENV{PERL_CORE} ? 'lib' : 't'),
- 'sample-tests', 'echo' );
+my $test = File::Spec->catfile(
+ ( $ENV{PERL_CORE} ? 'lib' : 't' ),
+ 'sample-tests', 'echo'
+);
diag( "\n\n", bigness( join ' ', @ARGV ), "\n\n" ) if @ARGV;
diff --git a/lib/Test/Harness/t/unicode.t b/lib/Test/Harness/t/unicode.t
index de52689ea0..88d32081ba 100644
--- a/lib/Test/Harness/t/unicode.t
+++ b/lib/Test/Harness/t/unicode.t
@@ -9,6 +9,7 @@ my @schedule;
my %make_test;
BEGIN {
+
# TODO: Investigate failure on 5.8.0
plan skip_all => "unicode on Perl <= 5.8.0"
unless $] > 5.008;
diff --git a/lib/Test/Harness/t/yamlish.t b/lib/Test/Harness/t/yamlish.t
index 3cdaf541df..76ba7982b4 100644
--- a/lib/Test/Harness/t/yamlish.t
+++ b/lib/Test/Harness/t/yamlish.t
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!perl -w
use strict;
use lib 't/lib';
@@ -48,6 +48,15 @@ BEGIN {
],
out => "Hello, World\n",
},
+ { name => 'Hello World Block',
+ in => [
+ '--- |',
+ ' Hello,',
+ ' World',
+ '...',
+ ],
+ out => "Hello,\n World\n",
+ },
{ name => 'Hello World 5',
in => [
'--- >',
@@ -128,7 +137,10 @@ BEGIN {
six => '6'
},
},
-
+ { name => 'Space after colon',
+ in => [ '---', 'spog: ', ' - 1', ' - 2', '...' ],
+ out => { spog => [ 1, 2 ] },
+ },
{ name => 'Original YAML::Tiny test',
in => [
'---',
@@ -471,6 +483,10 @@ BEGIN {
"\n\t" => 'newline, tab',
},
},
+ { name => 'Empty',
+ in => [],
+ out => undef,
+ },
);
plan tests => @SCHEDULE * 5;