diff options
author | Bram <perl-rt@wizbit.be> | 2008-08-10 22:29:07 +0200 |
---|---|---|
committer | Dave Mitchell <davem@fdisolutions.com> | 2008-12-09 15:35:03 +0000 |
commit | d7cbb54926a4ec4ff6f7f8077cdf49b4d94c6670 (patch) | |
tree | 78edc4d49a68488ce62a80a0be0e650ba1352587 | |
parent | 296f12bbbbaa06de9be9d09d3dcf8f4528898a49 (diff) | |
download | perl-d7cbb54926a4ec4ff6f7f8077cdf49b4d94c6670.tar.gz |
Integrate:
[ 34174]
If TEST_JOBS is set to something non-zero, use TAP::Harness to run the
tests in parallel. The tests aren't fully parallelisable yet to the
level we'd like, but one needs to start somewhere.
[ 34175]
Avoid a potential testing race condition in Shell.pm's test.
[ 34176]
Run t/uni/*.t t/mro/*.t t/lib/*.t fully in parallel.
[ 34177]
As rules can be glob patterns, leave them as glob patterns, and instead
expand the globs when we walk the rules to create the full list of
tests. Tests run more quickly.
[ 34181]
Let rip with t/op/*.t in parallel too.
[ 34185]
Everything in t/ can now run in parallel.
[ 34191]
Don't need to do the globbing before building the rules, as it makes
the rules larger than necessary, and potentially slows things down.
[ 34192]
Use App::Prove::State to store the timings for the tests, and if
timings are available, reorder the parallelisable tests to run the
slowest first. Timings for a second run are 18 seconds less for me:
Files=1553, Tests=209393, 459 wallclock secs (94.89 usr 13.16 sys + 638.19 cusr 58.59 csys = 804.83 CPU)
Files=1553, Tests=209393, 441 wallclock secs (82.83 usr 13.90 sys + 622.13 cusr 59.20 csys = 778.06 CPU)
[ 34195]
Subject: Re: Change 34175: Avoid a potential testing race condition in Shell.pm's test.
Message-ID: <20080810202907.0pfnzshsoco8owg4@horde.wizbit.be>
p4raw-link: @34195 on //depot/perl: a13fba344ba4e4964ffc44249a610a56dd386eff
p4raw-link: @34192 on //depot/perl: 0279961e65f24cb3d5407ae9771030dcc5eb6882
p4raw-link: @34191 on //depot/perl: 2f4cffa7723545b6812f9ecf0e78635684033dad
p4raw-link: @34185 on //depot/perl: 67d8fe77dde42ec7ef8beb57080a549b242ef2db
p4raw-link: @34181 on //depot/perl: 213f370f28504f3af87af602895b0afe68c0106a
p4raw-link: @34177 on //depot/perl: 0ae187c2299ef45fea08a054a5af0902048b539e
p4raw-link: @34176 on //depot/perl: e6867818d3d9ce24342ef3f6ceff06868f5e8457
p4raw-link: @34175 on //depot/perl: 75ff0aabd99f2dc0b759e6d27a79bfedc15168a7
p4raw-link: @34174 on //depot/perl: 9ae5a6c323cea172e440bd71782fdef16f8f20b1
p4raw-id: //depot/maint-5.10/perl@35062
p4raw-integrated: from //depot/perl@35061 'copy in' lib/Shell.t
(@34175..) 'merge in' win32/Makefile.ce (@32646..)
vms/descrip_mms.template (@33971..)
p4raw-integrated: from //depot/perl@34192 'merge in' win32/Makefile
win32/makefile.mk (@33349..) Makefile.SH (@33757..)
p4raw-integrated: from //depot/perl@34174 'ignore' t/harness (@34172..)
-rw-r--r-- | Makefile.SH | 1 | ||||
-rw-r--r-- | lib/Shell.t | 12 | ||||
-rw-r--r-- | t/harness | 125 | ||||
-rw-r--r-- | vms/descrip_mms.template | 1 | ||||
-rw-r--r-- | win32/Makefile | 1 | ||||
-rw-r--r-- | win32/Makefile.ce | 1 | ||||
-rw-r--r-- | win32/makefile.mk | 1 |
7 files changed, 126 insertions, 16 deletions
diff --git a/Makefile.SH b/Makefile.SH index 100cb40e1c..db47d97f73 100644 --- a/Makefile.SH +++ b/Makefile.SH @@ -1128,6 +1128,7 @@ realclean: cleanup_unpacked_files _realcleaner _mopup _clobber: -@rm -f Cross/run-* Cross/to-* Cross/from-* + rm -f t/test_state rm -f config.sh cppstdin Policy.sh extras.lst clobber: cleanup_unpacked_files _realcleaner _mopup _clobber diff --git a/lib/Shell.t b/lib/Shell.t index c76628c4ce..13bba2255e 100644 --- a/lib/Shell.t +++ b/lib/Shell.t @@ -41,6 +41,14 @@ ok(($^O eq 'os2' xor !(-s $tmpfile)), '$Shell::capture_stderr'); $Shell::capture_stderr = 0; +# Trying to do two repeated C<ls>s in t in core and expecting the same output +# is a race condition when tests are running in parallel, and using it as a +# temporary directory. So go somewhere quieter. +if ($ENV{PERL_CORE} && -d 'uni') { + chdir 'uni'; + $chdir++; +} + # someone will have to fill in the blanks for other platforms if ($Is_VMS) { @@ -70,3 +78,7 @@ if ($Is_VMS) { } open(STDERR, ">&SAVERR") ; + +if ($chdir) { + chdir ".."; +} @@ -55,6 +55,41 @@ sub _populate_hash { return map {$_, 1} split /\s+/, $_[0]; } +# Generate T::H schedule rules that run the contents of each directory +# sequentially. +sub _seq_dir_rules { + my @tests = @_; + my %dir; + for (@tests) { + s{[^/]+$}{\*}; + $dir{$_}++; + } + + return { par => [ map { { seq => $_ } } sort keys %dir ] }; +} + +sub _extract_tests; +sub _extract_tests { + # This can probably be done more tersely with a map, but I doubt that it + # would be as clear + my @results; + foreach (@_) { + my $ref = ref $_; + if ($ref) { + if ($ref eq 'ARRAY') { + push @results, _extract_tests @$_; + } elsif ($ref eq 'HASH') { + push @results, _extract_tests values %$_; + } else { + die "Unknown reference type $ref"; + } + } else { + push @results, glob $_; + } + } + @results; +} + if ($ARGV[0] && $ARGV[0]=~/^-re/) { if ($ARGV[0]!~/=/) { shift; @@ -65,7 +100,11 @@ if ($ARGV[0] && $ARGV[0]=~/^-re/) { } } +my $jobs = $ENV{TEST_JOBS}; +my ($rules, $state); + if (@ARGV) { + # If you want these run in speed order, just use prove if ($^O eq 'MSWin32') { @tests = map(glob($_),@ARGV); } @@ -73,18 +112,52 @@ if (@ARGV) { @tests = @ARGV; } } else { + # Ideally we'd get somewhere close to Tux's Oslo rules + # my $rules = { + # par => [ + # { seq => '../ext/DB_File/t/*' }, + # { seq => '../ext/IO_Compress_Zlib/t/*' }, + # { seq => '../lib/CPANPLUS/*' }, + # { seq => '../lib/ExtUtils/t/*' }, + # '*' + # ] + # }; + + # but for now, run all directories in sequence. In particular, it would be + # nice to get the tests in t/op/*.t able to run in parallel. + unless (@tests) { - push @tests, <base/*.t>; - push @tests, <comp/*.t>; - push @tests, <cmd/*.t>; - push @tests, <run/*.t>; - push @tests, <io/*.t>; - push @tests, <op/*.t>; - push @tests, <uni/*.t>; - push @tests, <mro/*.t>; - push @tests, <lib/*.t>; - push @tests, <japh/*.t> if $torture; - push @tests, <win32/*.t> if $^O eq 'MSWin32'; + my @seq = <base/*.t>; + + my @next = qw(comp cmd run io op uni mro lib); + push @next, 'japh' if $torture; + push @next, 'win32' if $^O eq 'MSWin32'; + # Hopefully TAP::Parser::Scheduler will support this syntax soon. + # my $next = { par => '{' . join (',', @next) . '}/*.t' }; + my $next = { par => [ + map { "$_/*.t" } @next + ] }; + @tests = _extract_tests ($next); + + # This is a bit of a game, because we only want to sort these tests in + # speed order. base/*.t wants to run first, and ext,lib etc last and in + # MANIFEST order + if ($jobs) { + require App::Prove::State; + $state = App::Prove::State->new({ store => 'test_state' }); + $state->apply_switch('slow', 'save'); + # For some reason get_tests returns *all* the tests previously run, + # (in the right order), not simply the selection in @tests + # (in the right order). Not sure if this is a bug or a feature. + # Whatever, *we* are only interested in the ones that are in @tests + my %seen; + @seen{@tests} = (); + @tests = grep {exists $seen{$_} } $state->get_tests(0, @tests); + } + @tests = (@seq, @tests); + push @seq, $next; + + my @last; use Config; my %skip; { @@ -114,13 +187,19 @@ if (@ARGV) { close MANI; # Sort the list of test files read from MANIFEST into a sensible # order instead of using the order in which they are listed there - push @tests, sort { lc $a cmp lc $b } @manitests; + push @last, sort { lc $a cmp lc $b } @manitests; } else { warn "$0: cannot open $mani: $!\n"; } - push @tests, <Module_Pluggable/*.t>; - push @tests, <pod/*.t>; - push @tests, <x2p/*.t>; + push @last, <Module_Pluggable/*.t>; + push @last, <pod/*.t>; + push @last, <x2p/*.t>; + + push @tests, @last; + + push @seq, _seq_dir_rules @last; + + $rules = { seq => \@seq }; } } if ($^O eq 'MSWin32') { @@ -128,5 +207,19 @@ if ($^O eq 'MSWin32') { } @tests=grep /$re/, @tests if $re; -Test::Harness::runtests @tests; + +if ($jobs) { + eval 'use TAP::Harness 3.13; 1' or die $@; + my $h = TAP::Harness->new({ jobs => $jobs, rules => $rules}); + if ($state) { + $h->callback( + after_test => sub { + $state->observe_test(@_); + } + ); + } + $h->runtests(@tests); +} else { + Test::Harness::runtests @tests; +} exit(0); diff --git a/vms/descrip_mms.template b/vms/descrip_mms.template index a95804463a..adf6e82f46 100644 --- a/vms/descrip_mms.template +++ b/vms/descrip_mms.template @@ -1865,6 +1865,7 @@ realclean : clean - If F$Search("[...]*$(E)").nes."" Then Delete/NoConfirm/Log [...]*$(E);* - If F$Search("[.vms]Perl_Setup.Com").nes."" Then Delete/NoConfirm/Log [.vms]Perl_Setup.Com;* - If F$Search("[.t]rantests.").nes."" Then Delete/NoConfirm/Log [.t]rantests.;* + - If F$Search("[.t]test_state.").nes."" Then Delete/NoConfirm/Log [.t]test_state.;* - If F$Search("[.t.lib]vmsfspec.t").nes."" Then Delete/NoConfirm/Log [.t.lib]vmsfspec.t;* - If F$Search("[.t.lib]vmsish.t").nes."" Then Delete/NoConfirm/Log [.t.lib]vmsish.t;* - If F$Search("[.t.lib]vms_dclsym.t").nes."" Then Delete/NoConfirm/Log [.t.lib]vms_dclsym.t;* diff --git a/win32/Makefile b/win32/Makefile index 758028d342..6088f190b0 100644 --- a/win32/Makefile +++ b/win32/Makefile @@ -1225,6 +1225,7 @@ distclean: realclean -if exist pod2htmd.tmp del pod2htmd.tmp -if exist pod2htmi.tmp del pod2htmi.tmp -if exist $(HTMLDIR) rmdir /s /q $(HTMLDIR) + -del /f ..\t\test_state install : all installbare installhtml diff --git a/win32/Makefile.ce b/win32/Makefile.ce index 3231d75fff..c5bef57510 100644 --- a/win32/Makefile.ce +++ b/win32/Makefile.ce @@ -779,6 +779,7 @@ clean: -rm -f $(MACHINE)/*.lib -rm -f ../config.sh ../lib/Config.pm -rm -f config.h xconfig.h perl.res + -rm -f ../t/test_state XDLLOBJS = \ $(DLLDIR)\av.obj \ diff --git a/win32/makefile.mk b/win32/makefile.mk index b613c71d0d..17f5fe3a4d 100644 --- a/win32/makefile.mk +++ b/win32/makefile.mk @@ -1549,6 +1549,7 @@ distclean: realclean -if exist pod2htmd.tmp del pod2htmd.tmp -if exist pod2htmi.tmp del pod2htmi.tmp -if exist $(HTMLDIR) rmdir /s /q $(HTMLDIR) + -del /f ..\t\test_state install : all installbare installhtml |