summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram <perl-rt@wizbit.be>2008-08-10 22:29:07 +0200
committerDave Mitchell <davem@fdisolutions.com>2008-12-09 15:35:03 +0000
commitd7cbb54926a4ec4ff6f7f8077cdf49b4d94c6670 (patch)
tree78edc4d49a68488ce62a80a0be0e650ba1352587
parent296f12bbbbaa06de9be9d09d3dcf8f4528898a49 (diff)
downloadperl-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.SH1
-rw-r--r--lib/Shell.t12
-rw-r--r--t/harness125
-rw-r--r--vms/descrip_mms.template1
-rw-r--r--win32/Makefile1
-rw-r--r--win32/Makefile.ce1
-rw-r--r--win32/makefile.mk1
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 "..";
+}
diff --git a/t/harness b/t/harness
index 1c6bcf1276..8a4e9b4c3a 100644
--- a/t/harness
+++ b/t/harness
@@ -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