Introduce the prove(1) utility.
(The prove-switches test is disabled for now.)
p4raw-id: //depot/perl@21826
lib/Test/Harness/Iterator.pm Test::Harness::Iterator (internal use only)
lib/Test/Harness.pm A test harness
lib/Test/Harness/Straps.pm Test::Harness::Straps
+lib/Test/Harness/bin/prove The prove harness utility
lib/Test/Harness/t/00compile.t Test::Harness test
lib/Test/Harness/t/assert.t Test::Harness::Assert test
lib/Test/Harness/t/base.t Test::Harness test
lib/Test/Harness/t/callback.t Test::Harness test
+lib/Test/Harness/t/inc_taint.t Test::Harness test
lib/Test/Harness/t/nonumbers.t Test::Harness test
lib/Test/Harness/t/ok.t Test::Harness test
lib/Test/Harness/t/pod.t Test::Harness test
+lib/Test/Harness/t/prove-switches.t Test::Harness::Straps test
lib/Test/Harness/t/strap-analyze.t Test::Harness::Straps test
lib/Test/Harness/t/strap.t Test::Harness::Straps test
lib/Test/Harness/t/test-harness.t Test::Harness test
t/lib/1_compile.t See if the various libraries and extensions compile
t/lib/commonsense.t See if configuration meets basic needs
t/lib/compmod.pl Helper for 1_compile.t
+t/lib/Dev/Null.pm Module for testing Test::Harness
t/lib/Devel/switchd.pm Module for t/run/switchd.t
t/lib/dprof/test1_t Perl code profiler tests
t/lib/dprof/test1_v Perl code profiler tests
t/lib/sample-tests/bignum Test data for Test::Harness
t/lib/sample-tests/combined Test data for Test::Harness
t/lib/sample-tests/descriptive Test data for Test::Harness
-t/lib/sample-tests/die Test data for Test::Harness
t/lib/sample-tests/die_head_end Test data for Test::Harness
t/lib/sample-tests/die_last_minute Test data for Test::Harness
+t/lib/sample-tests/die Test data for Test::Harness
t/lib/sample-tests/duplicates Test data for Test::Harness
t/lib/sample-tests/head_end Test data for Test::Harness
t/lib/sample-tests/head_fail Test data for Test::Harness
+t/lib/sample-tests/inc_taint Test data for Test::Harness
t/lib/sample-tests/lone_not_bug Test data for Test::Harness
t/lib/sample-tests/no_nums Test data for Test::Harness
t/lib/sample-tests/no_output Test data for Test::Harness
t/lib/sample-tests/out_of_order Test data for Test::Harness
t/lib/sample-tests/segfault Test data for Test::Harness
t/lib/sample-tests/shbang_misparse Test data for Test::Harness
-t/lib/sample-tests/simple Test data for Test::Harness
t/lib/sample-tests/simple_fail Test data for Test::Harness
-t/lib/sample-tests/skip Test data for Test::Harness
-t/lib/sample-tests/skipall Test data for Test::Harness
+t/lib/sample-tests/simple Test data for Test::Harness
t/lib/sample-tests/skipall_nomsg Test data for Test::Harness
+t/lib/sample-tests/skipall Test data for Test::Harness
t/lib/sample-tests/skip_nomsg Test data for Test::Harness
+t/lib/sample-tests/skip Test data for Test::Harness
t/lib/sample-tests/switches Test data for Test::Harness
t/lib/sample-tests/taint Test data for Test::Harness
-t/lib/sample-tests/todo Test data for Test::Harness
+t/lib/sample-tests/taint_warn Test data for Test::Harness
t/lib/sample-tests/todo_inline Test data for Test::Harness
+t/lib/sample-tests/todo Test data for Test::Harness
t/lib/sample-tests/too_many Test data for Test::Harness
t/lib/sample-tests/vms_nit Test data for Test::Harness
t/lib/sample-tests/with_comments Test data for Test::Harness
utils/perlivp.PL installation verification procedure
utils/piconv.PL iconv(1), reinvented in perl
utils/pl2pm.PL A pl to pm translator
+utils/prove.PL The prove harness utility
utils/splain.PL Stand-alone version of diagnostics.pm
utils/xsubpp.PL External subroutine preprocessor
uts/sprintf_wrap.c sprintf wrapper for UTS
# .exists files, .PL files, and test files.
return if $name =~ m{\.orig$|\.rej$|~$|^#.+#$|,v$|^\.exists|\.PL$|\.plc$|\.t$|^test\.pl$} ||
$dir =~ m{/t(?:/|$)};
- # ignore the cpan script in lib/CPAN/bin and the instmodsh and xsubpp
- # scripts in lib/ExtUtils (they're installed later with other utils)
- return if $name =~ /^(?:cpan|instmodsh|xsubpp)\z/;
+ # ignore the cpan script in lib/CPAN/bin, the instmodsh and xsubpp
+ # scripts in lib/ExtUtils, and the prove script in lib/Test/Harness
+ # (they're installed later with other utils)
+ return if $name =~ /^(?:cpan|instmodsh|xsubpp|prove)\z/;
# ignore the Makefiles
return if $name =~ /^makefile$/i;
# ignore the test extensions
# -*- Mode: cperl; cperl-indent-level: 4 -*-
-# $Id: Harness.pm,v 1.54 2003/08/15 01:05:00 andy Exp $
+# $Id: Harness.pm,v 1.76 2003/11/25 04:41:03 andy Exp $
package Test::Harness;
use Config;
use strict;
-use vars qw($VERSION $Verbose $Switches $Have_Devel_Corestack $Curtest
- $Columns $verbose $switches $ML $Strap
- @ISA @EXPORT @EXPORT_OK $Last_ML_Print
- );
+use vars qw(
+ $VERSION
+ @ISA @EXPORT @EXPORT_OK
+ $Verbose $Switches $Debug
+ $verbose $switches $debug
+ $Have_Devel_Corestack
+ $Curtest
+ $Columns
+ $ML $Last_ML_Print
+ $Strap
+);
+
+=head1 NAME
+
+Test::Harness - Run Perl standard test scripts with statistics
+
+=head1 VERSION
+
+Version 2.38
+
+ $Header: /home/cvs/test-harness/lib/Test/Harness.pm,v 1.76 2003/11/25 04:41:03 andy Exp $
+
+=cut
+
+$VERSION = '2.38';
# Backwards compatibility for exportable variable names.
*verbose = *Verbose;
*switches = *Switches;
+*debug = *Debug;
$Have_Devel_Corestack = 0;
-$VERSION = '2.30';
-
$ENV{HARNESS_ACTIVE} = 1;
END {
@EXPORT_OK = qw($verbose $switches);
$Verbose = $ENV{HARNESS_VERBOSE} || 0;
+$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.
-
-=head1 NAME
-
-Test::Harness - run perl standard test scripts with statistics
-
=head1 SYNOPSIS
use Test::Harness;
=item B<Todo tests>
-If the standard output line contains the substring C< # TODO> after
+If the standard output line contains the substring C< # TODO > after
C<not ok> or C<not ok NUMBER>, it is counted as a todo test. The text
afterwards is the thing that has to be done before this test will
succeed.
not ok 13 # TODO harness the power of the atom
+Note that the TODO must have a space after it.
+
=begin _deprecated
Alternatively, you can specify a list of what tests are todo as part
=back
-
=head2 Taint mode
-Test::Harness will honor the C<-T> in the #! line on your test files. So
-if you begin a test with:
+Test::Harness will honor the C<-T> or C<-t> in the #! line on your
+test files. So if you begin a test with:
#!perl -T
the test will be run with taint mode on.
-
=head2 Configuration variables.
These variables can be used to configure the behavior of
=over 4
-=item B<$Test::Harness::verbose>
+=item B<$Test::Harness::Verbose>
-The global variable $Test::Harness::verbose is exportable and can be
-used to let runtests() display the standard output of the script
-without altering the behavior otherwise.
+The global variable C<$Test::Harness::Verbose> is exportable and can be
+used to let C<runtests()> display the standard output of the script
+without altering the behavior otherwise. The F<prove> utility's C<-v>
+flag will set this.
=item B<$Test::Harness::switches>
-The global variable $Test::Harness::switches is exportable and can be
+The global variable C<$Test::Harness::switches> is exportable and can be
used to set perl command line options used for running the test
-script(s). The default value is C<-w>.
+script(s). The default value is C<-w>. It overrides C<HARNESS_SWITCHES>.
=back
=head2 Failure
-It will happen, your tests will fail. After you mop up your ego, you
+It will happen: your tests will fail. After you mop up your ego, you
can begin examining the summary report:
t/base..............ok
=item B<Wstat>
-The wait status of the test I<umm, I need a better explanation here>.
+The wait status of the test.
=item B<Total>
my($total, $failed) = _run_all_tests(@test_files);
-Runs all the given @test_files (as runtests()) but does it quietly (no
-report). $total is a hash ref summary of all the tests run. Its keys
-and values are this:
+Runs all the given C<@test_files> (as C<runtests()>) but does it
+quietly (no report). $total is a hash ref summary of all the tests
+run. Its keys and values are this:
bonus Number of individual todo tests unexpectedly passed
max Number of individual tests ran
tests Number of test files originally given
skipped Number of test files skipped
-If $total->{bad} == 0 and $total->{max} > 0, you've got a successful
-test.
+If C<< $total->{bad} == 0 >> and C<< $total->{max} > 0 >>, you've
+got a successful test.
$failed is a hash ref of all the test scripts which failed. Each key
is the name of a test script, each value is another hash representing
percent Percentage of tests which failed
canon List of tests which failed (as string).
-Needless to say, $failed should be empty if everything passed.
+C<$failed> should be empty if everything passed.
B<NOTE> Currently this function is still noisy. I'm working on it.
my $width = _leader_width(@tests);
foreach my $tfile (@tests) {
+ if ( $Test::Harness::Debug ) {
+ print "# Running: ", $Strap->_command_line($tfile), "\n";
+ }
+
$Last_ML_Print = 0; # so each test prints at least once
my($leader, $ml) = _mk_leader($tfile, $width);
local $ML = $ml;
+
print $leader;
$tot{files}++;
$Strap->{_seen_header} = 0;
my %results = $Strap->analyze_file($tfile) or
- do { warn "$Strap->{error}\n"; next };
+ do { warn $Strap->{error}, "\n"; next };
# state of the current test.
my @failed = grep { !$results{details}[$_-1]{ok} }
my($leader, $ml) = _mk_leader($test_file, $width);
-Generates the 't/foo........' $leader for the given $test_file as well
+Generates the 't/foo........' $leader for the given C<$test_file> as well
as a similar version which will overwrite the current line (by use of
-\r and such). $ml may be empty if Test::Harness doesn't think you're
+\r and such). C<$ml> may be empty if Test::Harness doesn't think you're
on TTY.
-The $width is the width of the "yada/blah.." string.
+The C<$width> is the width of the "yada/blah.." string.
=cut
C<&runtests> is exported by Test::Harness by default.
-C<$verbose> and C<$switches> are exported upon request.
-
+C<$verbose>, C<$switches> and C<$debug> are exported upon request.
=head1 DIAGNOSTICS
B<NOTE> This currently only works when sitting in the perl source
directory!
+=item C<HARNESS_DEBUG>
+
+If true, Test::Harness will print debugging information about itself as
+it runs the tests. This is different from C<HARNESS_VERBOSE>, which prints
+the output from the test being run. Setting C<$Test::Harness::Debug> will
+override this, or you can use the C<-d> switch in the F<prove> utility.
+
=item C<HARNESS_FILELEAK_IN_DIR>
When set to the name of a directory, harness will check after each
=item C<HARNESS_OK_SLOW>
-If true, the C<ok> messages are printed out only every second.
-This reduces output and therefore may for example help testing
-over slow connections.
+If true, the C<ok> messages are printed out only every second. This
+reduces output and may help increase testing speed over slow
+connections, or with very large numbers of tests.
+
+=item C<HARNESS_PERL>
+
+Usually your tests will be run by C<$^X>, the currently-executing Perl.
+However, you may want to have it run by a different executable, such as
+a threading perl, or a different version.
+
+If you're using the F<prove> utility, you can use the C<--perl> switch.
=item C<HARNESS_PERL_SWITCHES>
=item C<HARNESS_VERBOSE>
If true, Test::Harness will output the verbose results of running
-its tests. Setting $Test::Harness::verbose will override this.
+its tests. Setting C<$Test::Harness::verbose> will override this,
+or you can use the C<-v> switch in the F<prove> utility.
=back
HARNESS_COMPILE_TEST currently assumes it's run from the Perl source
directory.
+Please use the CPAN bug ticketing system at L<http://rt.cpan.org/>.
+You can also mail bugs, fixes and enhancements to
+C<< <bug-test-harness@rt.cpan.org> >>.
+
+=head1 AUTHORS
+
+Original code by Michael G Schwern, maintained by Andy Lester.
+
+=head1 COPYRIGHT
+
+Copyright 2003 by Michael G Schwern C<< <schwern@pobox.com> >>,
+ Andy Lester C<< <andy@petdance.com> >>.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+See L<http://www.perl.com/perl/misc/Artistic.html>.
+
=cut
-# $Id: Assert.pm,v 1.2 2002/04/26 05:12:27 schwern Exp $
+# $Id: Assert.pm,v 1.3 2003/09/11 15:57:29 andy Exp $
package Test::Harness::Assert;
require Exporter;
use vars qw($VERSION @EXPORT @ISA);
-$VERSION = '0.01';
+$VERSION = '0.02';
@ISA = qw(Exporter);
@EXPORT = qw(assert);
B<For internal use by Test::Harness ONLY!>
-=head2 Functions
+=head1 FUNCTIONS
-=over 4
-
-=item B<assert>
+=head2 C<assert()>
assert( EXPR, $name );
=head1 AUTHOR
-Michael G Schwern E<lt>schwern@pobox.comE<gt>
+Michael G Schwern C<< <schwern@pobox.com> >>
=head1 SEE ALSO
Revision history for Perl extension Test::Harness
+2.38 Mon Nov 24 22:36:18 CST 2003
+ Released. See changes below.
+
+2.37_03 Tue Nov 18 23:51:38 CST 2003
+ [ENHANCEMENTS]
+ * prove -V now shows the Perl version being used.
+ * Now there's a HARNESS_DEBUG flag that shows diagnostics as the
+ harness runs the tests. This is different from HARNESS_VERBOSE,
+ which shows test output, but not information about the harness
+ itself.
+ * Added _command_line() to the Strap API.
+
+ [FIXES]
+ * Bad interaction with Module::Build: The strap was only checking
+ $ENV{HARNESS_PERL_SWITCHES} for definedness, but not emptiness.
+ It now also strips any leading or trailing whitesapce from the
+ switches.
+ * Test::Harness and prove only quote those parms that actually need
+ to be quoted: Have some whitespace and aren't already quoted.
+
+2.36 Fri Nov 14 09:24:44 CST 2003
+ [FIXES]
+ * t/prove-includes.t properly ignores PROVE_SWITCHES that you may
+ already have set.
+
+2.35_02 Thu Nov 13 09:57:36 CST 2003
+ [ENHANCEMENTS]
+ * prove's --blib now works just like the blib pragma.
+
+2.35_01 Wed Nov 12 23:08:45 CST 2003
+ [FIXES]
+ * Fixed taint-handling and path preservation under MacOS. Thanks to
+ Schwern for the patch and the tests.
+
+ * Preserves case of -t or -T in the shebang line of the test.
+
+ [ENHANCEMENTS]
+ * Added -t to prove analogous to Perl's -t. Removed the --taint
+ switch.
+
+ * prove can take default options from the PROVE_SWITCHES variable.
+
+ * Added HARNESS_PERL to allow you to specify the Perl interpreter
+ to run the tests as.
+
+ * prove's --perl switch sets the HARNESS_PERL on the fly for you.
+
+ * Quotes the switches and filename in the subprogram. This helps
+ with filenames with spaces that are subject to shell mangling.
+
+
+2.34 Sat Nov 8 22:09:15 CST 2003
+ [FIXES]
+ * Allowed prove to run on Perl versions < 5.6.0.
+
+ [ENHANCEMENTS]
+ * Command-line switches to prove may now be stacked.
+ * Added check for proper Pod::Usage version.
+ * "make clean" does a better job of cleaning up after itself.
+
+
+2.32 Fri Nov 7 09:41:21 CST 2003
+ Test::Harness now includes a powerful development tool to help
+ programmers work with automated tests. The prove utility runs
+ test files against the harness, like a "make test", but with many
+ advantages:
+
+ * prove is designed as a development tool
+ Perl users typically run the test harness through a makefile via
+ "make test". That's fine for module distributions, but it's
+ suboptimal for a test/code/debug development cycle.
+
+ * prove is granular
+ prove lets your run against only the files you want to check.
+ Running "prove t/live/ t/master.t" checks every *.t in t/live, plus
+ t/master.t.
+
+ * prove has an easy verbose mode
+ To get full test program output from "make test", you must set
+ "HARNESS_VERBOSE" in the environment. prove has a "-v" option.
+
+ * prove can run under taint mode
+ prove's "-T" runs your tests under "perl -T".
+
+ * prove can shuffle tests
+ You can use prove's "--shuffle" option to try to excite problems
+ that don't show up when tests are run in the same order every time.
+
+ * Not everything is a module
+ More and more users are using Perl's testing tools outside the
+ context of a module distribution, and may not even use a makefile at
+ all.
+
+ Prove requires Pod::Usage, which is standard after Perl 5.004.
+
+ I'm very excited about prove, and hope that developers will begin
+ adopting it to their coding cycles. I welcome your comments at
+ andy@petdance.com.
+
+ There are also some minor bug fixes in Test::Harness itself, listed
+ below in the 2.31_* notes.
+
+
+2.31_05 Thu Nov 6 14:56:22 CST 2003
+ [FIXES]
+ - If a MacPerl script had a shebang with -T, the -T wouldn't get
+ passed as a switch.
+ - Removed the -T on three *.t files, which didn't need them, and
+ which were causing problems.
+ - Conditionally installs bin/prove, depending on whether Pod::Usage
+ is available, which prove needs.
+ - Removed old leftover code from Makefile.PL.
+
+2.31_04 Mon Nov 3 23:36:06 CST 2003
+ Minor tweaks here and there, almost ready to release.
+
+2.31_03 Mon Nov 3 08:50:36 CST 2003
+ [FEATURES]
+ - prove is almost feature-complete. Removed the handling of
+ --exclude for excluding certain tests. It may go back in the
+ future.
+ - prove -d is now debug. Dry is prove -D.
+
+2.31_02 Fri Oct 31 23:46:03 CST 2003
+ [FEATURES]
+ - Added many more switches to prove: -d for dry run, and -b for
+ blib.
+
+ [FIXES]
+ - T:H:Straps now recognizes MSWin32 in $^0.
+ - RT#3811: Could do regex matching on garbage in _is_test().
+ Fixed by Yves Orton
+ - RT#3827: Strips backslashes from and normalizes @INC entries
+ for Win32. Fixed by Yves Orton.
+
+ [INTERNALS]
+ - Added $self->{_is_macos} to the T:H:Strap object.
+ - t/test-harness.t sorts its test results, rather than relying on
+ internal key order.
+
+2.31_01
+ [FEATURES]
+ - Added "prove" script to run a test or set of tests through the
+ harness. Thanks to Curtis Poe for the foundation.
+
+ [DOCUMENTATION]
+ - Fixed POD problem in Test::Harness::Assert
+
2.30 Thu Aug 14 20:04:00 CDT 2003
No functional changes in this version. It's only to make some doc
tweaks, and bump up the version number in T:H:Straps.
- Incorporated the TODO file into Harness.pm proper.
- Cleaned up formatting in Test::Harness::Straps.
-2.29 Wed Jul 17 14:08:00 CDT 2003
+2.29 Wed Jul 17 14:08:00 CDT 2003
- Released as 2.29.
-2.28_91 Sun Jul 13 00:10:00 CDT 2003
+2.28_91 Sun Jul 13 00:10:00 CDT 2003
[ENHANCEMENTS]
- Added support for HARNESS_OK_SLOW. This will make a significant
speedup for slower connections.
- Fixed the prototype for the canonfailed() function, not that
it matters since it's never called without parens.
-2.28_90 Sat Jul 05 20:21:00 CDT 2003
+2.28_90 Sat Jul 05 20:21:00 CDT 2003
[ENHANCEMENTS]
- Now, when you run a test harnessed, the numbers don't fly by one
at a time, one update per second. This significantly speeds
=head1 SYNOPSIS
use Test::Harness::Iterator;
- use Test::Harness::Iterator;
my $it = Test::Harness::Iterator->new(\*TEST);
my $it = Test::Harness::Iterator->new(\@array);
my $line = $it->next;
-
=head1 DESCRIPTION
B<FOR INTERNAL USE ONLY!>
# -*- Mode: cperl; cperl-indent-level: 4 -*-
-# $Id: Straps.pm,v 1.18 2003/08/15 01:29:23 andy Exp $
+# $Id: Straps.pm,v 1.34 2003/11/23 00:02:11 andy Exp $
package Test::Harness::Straps;
use strict;
use vars qw($VERSION);
use Config;
-$VERSION = '0.15';
+$VERSION = '0.18';
use Test::Harness::Assert;
use Test::Harness::Iterator;
sub _init {
my($self) = shift;
- $self->{_is_vms} = $^O eq 'VMS';
- $self->{_is_win32} = $^O eq 'Win32';
+ $self->{_is_vms} = ( $^O eq 'VMS' );
+ $self->{_is_win32} = ( $^O =~ /^(MS)?Win32$/ );
+ $self->{_is_macos} = ( $^O eq 'MacOS' );
}
=head1 Analysis
local $ENV{PERL5LIB} = $self->_INC2PERL5LIB;
- my $cmd = $self->{_is_vms} ? "MCR $^X" :
- $self->{_is_win32} ? Win32::GetShortPathName($^X)
- : $^X;
-
- my $switches = $self->_switches($file);
-
# *sigh* this breaks under taint, but open -| is unportable.
- unless( open(FILE, "$cmd $switches $file|") ) {
+ my $line = $self->_command_line($file);
+ unless( open(FILE, "$line|") ) {
print "can't run $file. $!\n";
return;
}
*_wait2exit = sub { POSIX::WEXITSTATUS($_[0]) }
}
+=head2 C<_command_line( $file )>
+
+ my $command_line = $self->_command_line();
+
+Returns the full command line that will be run to test I<$file>.
+
+=cut
+
+sub _command_line {
+ my $self = shift;
+ my $file = shift;
+
+ my $command = $self->_command();
+ my $switches = $self->_switches($file);
+
+ $file = qq["$file"] if ($file =~ /\s/) && ($file !~ /^".*"$/);
+ my $line = "$command $switches $file";
+
+ return $line;
+}
+
+
+=head2 C<_command>
+
+ my $command = $self->_command();
+
+Returns the command that runs the test. Combine this with _switches()
+to build a command line.
+
+Typically this is C<$^X>, but you can set C<$ENV{HARNESS_COMMAND}>
+to use a different Perl than what you're running the harness under.
+This might be to run a threaded Perl, for example.
+
+You can also overload this method if you've built your own strap subclass,
+such as a PHP interpreter for a PHP-based strap.
+
+=cut
+
+sub _command {
+ my $self = shift;
+
+ return $ENV{HARNESS_PERL} if defined $ENV{HARNESS_PERL};
+ return "MCR $^X" if $self->{_is_vms};
+ return Win32::GetShortPathName($^X) if $self->{_is_win32};
+ return $^X;
+}
+
=head2 C<_switches>
sub _switches {
my($self, $file) = @_;
+ my @existing_switches = $self->_cleaned_switches( $Test::Harness::Switches, $ENV{HARNESS_PERL_SWITCHES} );
+ my @derived_switches;
+
local *TEST;
open(TEST, $file) or print "can't open $file. $!\n";
- my $first = <TEST>;
- my $s = $Test::Harness::Switches || '';
- $s .= " $ENV{'HARNESS_PERL_SWITCHES'}"
- if exists $ENV{'HARNESS_PERL_SWITCHES'};
-
- if ($first =~ /^#!.*\bperl.*\s-\w*([Tt]+)/) {
- # When taint mode is on, PERL5LIB is ignored. So we need to put
- # all that on the command line as -Is.
- $s .= join " ", qq[ "-$1"], map {qq["-I$_"]} $self->_filtered_INC;
+ my $shebang = <TEST>;
+ close(TEST) or print "can't close $file. $!\n";
+
+ my $taint = ( $shebang =~ /^#!.*\bperl.*\s-\w*([Tt]+)/ );
+ push( @derived_switches, "-$1" ) if $taint;
+
+ # When taint mode is on, PERL5LIB is ignored. So we need to put
+ # all that on the command line as -Is.
+ # MacPerl's putenv is broken, so it will not see PERL5LIB, tainted or not.
+ if ( $taint || $self->{_is_macos} ) {
+ my @inc = $self->_filtered_INC;
+ push @derived_switches, map { "-I$_" } @inc;
}
- elsif ($^O eq 'MacOS') {
- # MacPerl's putenv is broken, so it will not see PERL5LIB.
- $s .= join " ", map {qq["-I$_"]} $self->_filtered_INC;
+
+ # Quote all switches to prevent shell interference, or VMS downcasing
+ for ( @derived_switches ) {
+ $_ = qq["$_"] if /\s/ && !/^".*"$/;
}
+ return join( " ", @existing_switches, @derived_switches );
+}
- close(TEST) or print "can't close $file. $!\n";
+=head2 C<_cleaned_switches>
- return $s;
-}
+ my @switches = $self->_cleaned_switches( @switches_from_user );
+Returns only defined, non-blank, trimmed switches from the parms passed.
+
+=cut
+
+sub _cleaned_switches {
+ my $self = shift;
+
+ local $_;
+
+ my @switches;
+ for ( @_ ) {
+ my $switch = $_;
+ next unless defined $switch;
+ $switch =~ s/^\s+//;
+ $switch =~ s/\s+$//;
+ push( @switches, $switch ) if $switch ne "";
+ }
+
+ return @switches;
+}
=head2 C<_INC2PERL5LIB>
my($self, @inc) = @_;
@inc = @INC unless @inc;
- # VMS has a 255-byte limit on the length of %ENV entries, so
- # toss the ones that involve perl_root, the install location
- # for VMS
if( $self->{_is_vms} ) {
+ # VMS has a 255-byte limit on the length of %ENV entries, so
+ # toss the ones that involve perl_root, the install location
@inc = grep !/perl_root/i, @inc;
+
+ } elsif ( $self->{_is_win32} ) {
+ # Lose any trailing backslashes in the Win32 paths
+ s/[\\\/+]$// foreach @inc;
}
+ my %dupes;
+ @inc = grep !$dupes{$_}++, @inc;
+
return @inc;
}
# We pulverize the line down into pieces in three parts.
if( my($not, $num, $extra) = $line =~ /$Report_Re/ox ) {
- my($name, $control) = split /(?:[^\\]|^)#/, $extra if $extra;
- my($type, $reason) = $control =~ /^\s*(\S+)(?:\s+(.*))?$/ if $control;
+ my ($name, $control) = $extra ? split(/(?:[^\\]|^)#/, $extra) : ();
+ my ($type, $reason) = $control ? $control =~ /^\s*(\S+)(?:\s+(.*))?$/ : ();
$test->{number} = $num;
$test->{ok} = $not ? 0 : 1;
return $YES;
}
else{
- # Sometimes the "not " and "ok" will be on seperate lines on VMS.
+ # Sometimes the "not " and "ok" will be on separate lines on VMS.
# We catch this and remember we saw it.
if( $line =~ /^not\s+$/ ) {
$self->{saw_lone_not} = 1;
=cut
-
1;
--- /dev/null
+#!/usr/bin/perl -w
+
+use strict;
+
+use Test::Harness;
+use Getopt::Long;
+use Pod::Usage 1.12;
+use File::Spec;
+
+use vars qw( $VERSION );
+$VERSION = "1.04";
+
+my @ext = ();
+my $shuffle = 0;
+my $dry = 0;
+my $blib = 0;
+my $recurse = 0;
+my @includes = ();
+my @switches = ();
+
+# Allow cuddling the paths with the -I
+@ARGV = map { /^(-I)(.+)/ ? ($1,$2) : $_ } @ARGV;
+
+# Stick any default switches at the beginning, so they can be overridden
+# by the command line switches.
+unshift @ARGV, split( " ", $ENV{PROVE_SWITCHES} ) if defined $ENV{PROVE_SWITCHES};
+
+Getopt::Long::Configure( "no_ignore_case" );
+Getopt::Long::Configure( "bundling" );
+GetOptions(
+ 'b|blib' => \$blib,
+ 'd|debug' => \$Test::Harness::debug,
+ 'D|dry' => \$dry,
+ 'h|help|?' => sub {pod2usage({-verbose => 1, -input => \*DATA}); exit},
+ 'H|man' => sub {pod2usage({-verbose => 2, -input => \*DATA}); exit},
+ 'I=s@' => \@includes,
+ 'r|recurse' => \$recurse,
+ 's|shuffle' => \$shuffle,
+ 't' => sub { unshift @switches, "-t" }, # Always want -t up front
+ 'T' => sub { unshift @switches, "-T" }, # Always want -T up front
+ 'v|verbose' => \$Test::Harness::verbose,
+ 'V|version' => sub { print_version(); exit; },
+ 'ext=s@' => \@ext,
+) or exit 1;
+
+# Build up extensions regex
+@ext = map { split /,/ } @ext;
+s/^\.// foreach @ext;
+@ext = ("t") unless @ext;
+my $ext_regex = join( "|", map { quotemeta } @ext );
+$ext_regex = qr/\.($ext_regex)$/;
+
+# Handle blib includes
+if ( $blib ) {
+ my @blibdirs = blibdirs();
+ if ( @blibdirs ) {
+ unshift @includes, @blibdirs;
+ } else {
+ warn "No blib directories found.\n";
+ }
+}
+
+# Build up TH switches
+push( @switches, map { /\s/ && !/^".*"$/ ? qq["-I$_"] : "-I$_" } @includes );
+$Test::Harness::Switches = join( " ", @switches );
+print "# \$Test::Harness::Switches: $Test::Harness::Switches\n" if $Test::Harness::debug;
+
+my @tests;
+@ARGV = File::Spec->curdir unless @ARGV;
+push( @tests, -d $_ ? all_in( $_ ) : $_ ) for @ARGV;
+
+if ( @tests ) {
+ shuffle(@tests) if $shuffle;
+ if ( $dry ) {
+ print join( "\n", @tests, "" );
+ } else {
+ print "# ", scalar @tests, " tests to run\n" if $Test::Harness::debug;
+ runtests(@tests);
+ }
+}
+
+sub all_in {
+ my $start = shift;
+
+ my @hits = ();
+
+ local *DH;
+ if ( opendir( DH, $start ) ) {
+ while ( my $file = readdir DH ) {
+ next if $file eq File::Spec->updir || $file eq File::Spec->curdir;
+ next if $file eq ".svn";
+ next if $file eq "CVS";
+
+ my $currfile = File::Spec->catfile( $start, $file );
+ if ( -d $currfile ) {
+ push( @hits, all_in( $currfile ) ) if $recurse;
+ } else {
+ push( @hits, $currfile ) if $currfile =~ $ext_regex;
+ }
+ }
+ } else {
+ warn "$start: $!\n";
+ }
+
+ return @hits;
+}
+
+sub shuffle {
+ # Fisher-Yates shuffle
+ my $i = @_;
+ while ($i) {
+ my $j = rand $i--;
+ @_[$i, $j] = @_[$j, $i];
+ }
+}
+
+sub print_version {
+ printf( "prove v%s, using Test::Harness v%s and Perl v%vd\n",
+ $VERSION, $Test::Harness::VERSION, $^V );
+}
+
+# Stolen directly from blib.pm
+sub blibdirs {
+ my $dir = File::Spec->curdir;
+ if ($^O eq 'VMS') {
+ ($dir = VMS::Filespec::unixify($dir)) =~ s-/\z--;
+ }
+ my $archdir = "arch";
+ if ( $^O eq "MacOS" ) {
+ # Double up the MP::A so that it's not used only once.
+ $archdir = $MacPerl::Architecture = $MacPerl::Architecture;
+ }
+
+ my $i = 5;
+ while ($i--) {
+ my $blib = File::Spec->catdir( $dir, "blib" );
+ my $blib_lib = File::Spec->catdir( $blib, "lib" );
+ my $blib_arch = File::Spec->catdir( $blib, $archdir );
+
+ if ( -d $blib && -d $blib_arch && -d $blib_lib ) {
+ return ($blib_arch,$blib_lib);
+ }
+ $dir = File::Spec->catdir($dir, File::Spec->updir);
+ }
+ warn "$0: Cannot find blib\n";
+ return;
+}
+
+__END__
+
+=head1 NAME
+
+prove -- A command-line tool for running tests against Test::Harness
+
+=head1 SYNOPSIS
+
+prove [options] [files/directories]
+
+Options:
+
+ -b, --blib Adds blib/lib to the path for your tests, a la "use blib".
+ -d, --debug Includes extra debugging information.
+ -D, --dry Dry run: Show the tests to run, but don't run them.
+ --ext=x Extensions (defaults to .t)
+ -h, --help Display this help
+ -H, --man Longer manpage for prove
+ -I Add libraries to @INC, as Perl's -I
+ -r, --recurse Recursively descend into directories.
+ -s, --shuffle Run the tests in a random order.
+ -T Enable tainting checks
+ -t Enable tainting warnings
+ -v, --verbose Display standard output of test scripts while running them.
+ -V, --version Display version info
+
+Single-character options may be stacked. Default options may be set by
+specifying the PROVE_SWITCHES environment variable.
+
+=head1 OVERVIEW
+
+F<prove> is a command-line interface to the test-running functionality
+of C<Test::Harness>. With no arguments, it will run all tests in the
+current directory.
+
+Shell metacharacters may be used with command lines options and will be exanded
+via C<glob>.
+
+=head1 PROVE VS. "MAKE TEST"
+
+F<prove> has a number of advantages over C<make test> when doing development.
+
+=over 4
+
+=item * F<prove> is designed as a development tool
+
+Perl users typically run the test harness through a makefile via
+C<make test>. That's fine for module distributions, but it's
+suboptimal for a test/code/debug development cycle.
+
+=item * F<prove> is granular
+
+F<prove> lets your run against only the files you want to check.
+Running C<prove t/live/ t/master.t> checks every F<*.t> in F<t/live>,
+plus F<t/master.t>.
+
+=item * F<prove> has an easy verbose mode
+
+F<prove> has a C<-v> option to see the raw output from the tests.
+To do this with C<make test>, you must set C<HARNESS_VERBOSE=1> in
+the environment.
+
+=item * F<prove> can run under taint mode
+
+F<prove>'s C<-T> runs your tests under C<perl -T>, and C<-t> runs them
+under C<perl -t>.
+
+=item * F<prove> can shuffle tests
+
+You can use F<prove>'s C<--shuffle> option to try to excite problems
+that don't show up when tests are run in the same order every time.
+
+=item * F<prove> doesn't rely on a make tool
+
+Not everyone wants to write a makefile, or use L<ExtUtils::MakeMaker>
+to do so. F<prove> has no external dependencies.
+
+=item * Not everything is a module
+
+More and more users are using Perl's testing tools outside the
+context of a module distribution, and may not even use a makefile
+at all.
+
+=back
+
+=head1 COMMAND LINE OPTIONS
+
+=head2 -b, --blib
+
+Adds blib/lib to the path for your tests, a la "use blib".
+
+=head2 -d, --debug
+
+Include debug information about how F<prove> is being run. This
+option doesn't show the output from the test scripts. That's handled
+by -v,--verbose.
+
+=head2 -D, --dry
+
+Dry run: Show the tests to run, but don't run them.
+
+=head2 --ext=extension
+
+Specify extensions of the test files to run. By default, these are .t,
+but you may have other non-.t test files, most likely .sh shell scripts.
+The --ext is repeatable.
+
+=head2 -I
+
+Add libraries to @INC, as Perl's -I
+
+=head2 -r, --recurse
+
+Descends into subdirectories of any directories specified, looking for tests.
+
+=head2 -s, --shuffle
+
+Sometimes tests are accidentally dependent on tests that have been
+run before. This switch will shuffle the tests to be run prior to
+running them, thus ensuring that hidden dependencies in the test
+order are likely to be revealed. The author hopes the run the
+algorithm on the preceding sentence to see if he can produce something
+slightly less awkward.
+
+=head2 -t
+
+Runs test programs under perl's -t taint warning mode.
+
+=head2 -T
+
+Runs test programs under perl's -T taint mode.
+
+=head2 -v, --verbose
+
+Display standard output of test scripts while running them.
+
+=head2 -V, --version
+
+Display version info.
+
+=head1 BUGS
+
+Please use the CPAN bug ticketing system at L<http://rt.cpan.org/>.
+You can also mail bugs, fixes and enhancements to
+C<< <bug-test-harness@rt.cpan.org> >>.
+
+=head1 TODO
+
+=over 4
+
+=item *
+
+Shuffled tests must be recreatable
+
+=item *
+
+Add a flag to run prove under Devel::Cover
+
+=back
+
+=head1 AUTHORS
+
+Andy Lester C<< <andy@petdance.com> >>
+
+=head1 COPYRIGHT
+
+Copyright 2003 by Andy Lester C<< <andy@petdance.com> >>.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+See L<http://www.perl.com/perl/misc/Artistic.html>.
+
+=cut
-#!/usr/bin/perl -Tw
+#!/usr/bin/perl -w
BEGIN {
if($ENV{PERL_CORE}) {
-#!/usr/bin/perl -Tw
+#!/usr/bin/perl -w
BEGIN {
if( $ENV{PERL_CORE} ) {
push @out, $type;
};
-while( my($test, $expect) = each %samples ) {
+for my $test ( sort keys %samples ) {
+ my $expect = $samples{$test};
+
local @out = ();
$strap->analyze_file(File::Spec->catfile($SAMPLE_TESTS, $test));
--- /dev/null
+#!/usr/bin/perl -w
+
+BEGIN {
+ if( $ENV{PERL_CORE} ) {
+ chdir 't';
+ @INC = ('../lib', 'lib');
+ }
+ else {
+ unshift @INC, 't/lib';
+ }
+}
+
+use Test::Harness;
+use Test::More tests => 1;
+use Dev::Null;
+
+push @INC, 'we_added_this_lib';
+
+tie *NULL, 'Dev::Null' or die $!;
+select NULL;
+my($tot, $failed) = Test::Harness::_run_all_tests(
+ $ENV{PERL_CORE}
+ ? 'lib/sample-tests/inc_taint'
+ : 't/sample-tests/inc_taint'
+);
+select STDOUT;
+
+ok( Test::Harness::_all_ok($tot), 'tests with taint on preserve @INC' );
BEGIN {
- eval "use Test::More";
- if ($@) {
- print "1..0 # SKIPPED: Test::More not installed.\n";
- exit;
+ if( $ENV{PERL_CORE} ) {
+ chdir 't';
+ @INC = ('../lib', 'lib');
+ }
+ else {
+ unshift @INC, 't/lib';
}
}
-use File::Spec;
-use File::Find;
-use strict;
-
-eval "use Test::Pod 0.95";
-
-if ($@) {
- plan skip_all => "Test::Pod v0.95 required for testing POD";
-} else {
- my @files;
- my $blib = File::Spec->catfile(qw(blib lib));
- find( sub {push @files, $File::Find::name if /\.p(l|m|od)$/}, $blib);
- plan tests => scalar @files;
- Test::Pod::pod_file_ok($_) foreach @files;
-}
+use Test::More;
+eval "use Test::Pod 1.00";
+plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
+all_pod_files_ok();
--- /dev/null
+BEGIN {
+ if( $ENV{PERL_CORE} ) {
+ chdir 't';
+ @INC = ('../lib', 'lib');
+ }
+ else {
+ unshift @INC, 't/lib';
+ }
+}
+
+use strict;
+use File::Spec;
+use Test::More;
+plan skip_all => "Not adapted to perl core" if $ENV{PERL_CORE};
+plan skip_all => "Not installing prove" if -e "t/SKIP-PROVE";
+
+plan tests => 3;
+local $/ = undef;
+
+my $blib = File::Spec->catfile( File::Spec->curdir, "blib" );
+my $blib_lib = File::Spec->catfile( $blib, "lib" );
+my $blib_arch = File::Spec->catfile( $blib, "arch" );
+my $prove = File::Spec->catfile( $blib, "script", "prove" );
+
+CAPITAL_TAINT: {
+ local $ENV{PROVE_SWITCHES};
+ my @actual = qx/$prove -Ifirst -D -I second -Ithird -Tvdb/;
+ my @expected = ( "# \$Test::Harness::Switches: -T -I$blib_arch -I$blib_lib -Ifirst -Isecond -Ithird\n" );
+ array_match_ok( \@actual, \@expected, "Capital taint flags OK" );
+}
+
+LOWERCASE_TAINT: {
+ local $ENV{PROVE_SWITCHES};
+ my @actual = qx/$prove -dD -Ifirst -I second -t -Ithird -vb/;
+ my @expected = ( "# \$Test::Harness::Switches: -t -I$blib_arch -I$blib_lib -Ifirst -Isecond -Ithird\n" );
+ array_match_ok( \@actual, \@expected, "Lowercase taint OK" );
+}
+
+PROVE_SWITCHES: {
+ local $ENV{PROVE_SWITCHES} = "-dvb -I fark";
+ my @actual = qx/$prove -Ibork -Dd/;
+ my @expected = ( "# \$Test::Harness::Switches: -I$blib_arch -I$blib_lib -Ifark -Ibork\n" );
+ array_match_ok( \@actual, \@expected, "PROVE_SWITCHES OK" );
+}
+
+sub array_match_ok {
+ my $actual = shift;
+ my $expected = shift;
+ my $message = shift;
+ my $n = 0;
+
+ my @actual = @$actual;
+ my @expected = @$expected;
+
+ while ( @actual && @expected ) {
+ return ok( 0, "Differs at element $n: $message" ) if shift @actual ne shift @expected;
+ ++$n;
+ }
+ return ok( 0, "Too many actual: $message" ) if @actual;
+ return ok( 0, "Too many expected: $message" ) if @expected;
+
+ return ok( 1, $message );
+}
warn @_ unless $_[0] =~ /^Enormous test number/ ||
$_[0] =~ /^Can't detailize/
};
-while( my($test, $expect) = each %samples ) {
+
+for my $test ( sort keys %samples ) {
+ my $expect = $samples{$test};
+
for (0..$#{$expect->{details}}) {
$expect->{details}[$_]{type} = ''
unless exists $expect->{details}[$_]{type};
-#!/usr/bin/perl -Tw
+#!/usr/bin/perl -w
BEGIN {
if( $ENV{PERL_CORE} ) {
"#" => '',
);
-while( my($line, $line_comment) = each %comments ) {
+for my $line ( sort keys %comments ) {
+ my $line_comment = $comments{$line};
my $strap = Test::Harness::Straps->new;
isa_ok( $strap, 'Test::Harness::Straps' );
}
);
-while( my($header, $expect) = each %headers ) {
+for my $header ( sort keys %headers ) {
+ my $expect = $headers{$header};
my $strap = Test::Harness::Straps->new;
isa_ok( $strap, 'Test::Harness::Straps' );
},
);
-while( my($line, $expect) = each %tests ) {
+for my $line ( sort keys %tests ) {
+ my $expect = $tests{$line};
my %test;
ok( $strap->_is_test($line, \%test), "_is_test() spots '$line'" );
'bail out! - Out of coffee' => '- Out of coffee',
);
-while( my($line, $expect) = each %bails ) {
+for my $line ( sort keys %bails ) {
+ my $expect = $bails{$line};
my $strap = Test::Harness::Straps->new;
isa_ok( $strap, 'Test::Harness::Straps' );
: File::Spec->catdir($Curdir, 't', 'sample-tests');
-# For shutting up Test::Harness.
-# Has to work on 5.004 which doesn't have Tie::StdHandle.
-package My::Dev::Null;
-
-sub WRITE {}
-sub PRINT {}
-sub PRINTF {}
-sub TIEHANDLE {
- my $class = shift;
- my $fh = do { local *HANDLE; \*HANDLE };
- return bless $fh, $class;
-}
-sub READ {}
-sub READLINE {}
-sub GETC {}
-
-
-package main;
-
use Test::More;
+use Dev::Null;
my $IsMacPerl = $^O eq 'MacOS';
my $IsVMS = $^O eq 'VMS';
all_ok => 1,
},
+ taint_warn => {
+ total => {
+ bonus => 0,
+ max => 1,
+ 'ok' => 1,
+ files => 1,
+ bad => 0,
+ good => 1,
+ tests => 1,
+ sub_skipped=> 0,
+ 'todo' => 0,
+ skipped => 0,
+ },
+ failed => { },
+ all_ok => 1,
+ },
+
'die' => {
total => {
bonus => 0,
use Test::Harness; # So that we don't get "used only once" warnings on the next line
$Test::Harness::Switches = '"-Mstrict"';
-tie *NULL, 'My::Dev::Null' or die $!;
+tie *NULL, 'Dev::Null' or die $!;
+
+for my $test ( sort keys %samples ) {
+SKIP: {
+ skip "-t introduced in 5.8.0", 8 if $test eq 'taint_warn' and $] < 5.008;
+
+ my $expect = $samples{$test};
-while (my($test, $expect) = each %samples) {
# _run_all_tests() runs the tests but skips the formatting.
my($totals, $failed);
my $warning = '';
my $test_path = File::Spec->catfile($SAMPLE_TESTS, $test);
+ print STDERR "# $test\n" if $ENV{TEST_VERBOSE};
eval {
select NULL; # _run_all_tests() isn't as quiet as it should be.
local $SIG{__WARN__} = sub { $warning .= join '', @_; };
is( $warning, '' );
}
}
+}
--- /dev/null
+# For shutting up Test::Harness.
+# Has to work on 5.004 which doesn't have Tie::StdHandle.
+package Dev::Null;
+
+sub WRITE {}
+sub PRINT {}
+sub PRINTF {}
+sub TIEHANDLE {
+ my $class = shift;
+ my $fh = do { local *HANDLE; \*HANDLE };
+ return bless $fh, $class;
+}
+sub READ {}
+sub READLINE {}
+sub GETC {}
+
+1;
--- /dev/null
+#!/usr/bin/perl -Tw
+
+use lib qw(t/lib);
+use Test::More tests => 1;
+
+ok( grep(/we_added_this_lib/, @INC) );
+
--- /dev/null
+#!/usr/bin/perl -tw
+
+use lib qw(t/lib);
+use Test::More tests => 1;
+
+my $warnings = '';
+{
+ local $SIG{__WARN__} = sub { $warnings .= join '', @_ };
+ kill 0, $^X;
+}
+like( $warnings, '/^Insecure dependency/', '-t honored' );
utils/perlivp
utils/piconv
utils/pl2pm
+utils/prove
utils/splain
utils/xsubpp
x2p/a2p # pod = x2p/a2p.pod
# Files to be built with variable substitution after miniperl is
# available. Dependencies handled manually below (for now).
-pl = c2ph.PL cpan.PL h2ph.PL h2xs.PL instmodsh.PL perlbug.PL perldoc.PL perlivp.PL pl2pm.PL splain.PL perlcc.PL dprofpp.PL libnetcfg.PL piconv.PL enc2xs.PL xsubpp.PL
-plextract = c2ph cpan h2ph h2xs instmodsh perlbug perldoc perlivp pl2pm splain perlcc dprofpp libnetcfg piconv enc2xs xsubpp
-plextractexe = ./c2ph ./cpan ./h2ph ./h2xs ./instmodsh ./perlbug ./perldoc ./perlivp ./pl2pm ./splain ./perlcc ./dprofpp ./libnetcfg ./piconv ./enc2xs ./xsubpp
+pl = c2ph.PL cpan.PL h2ph.PL h2xs.PL instmodsh.PL perlbug.PL perldoc.PL perlivp.PL pl2pm.PL prove.PL splain.PL perlcc.PL dprofpp.PL libnetcfg.PL piconv.PL enc2xs.PL xsubpp.PL
+plextract = c2ph cpan h2ph h2xs instmodsh perlbug perldoc perlivp pl2pm prove splain perlcc dprofpp libnetcfg piconv enc2xs xsubpp
+plextractexe = ./c2ph ./cpan ./h2ph ./h2xs ./instmodsh ./perlbug ./perldoc ./perlivp ./pl2pm ./prove ./splain ./perlcc ./dprofpp ./libnetcfg ./piconv ./enc2xs ./xsubpp
all: $(plextract)
perlivp: perlivp.PL ../config.sh
+prove: prove.PL ../config.sh
+
pl2pm: pl2pm.PL ../config.sh
splain: splain.PL ../config.sh ../lib/diagnostics.pm
--- /dev/null
+#!/usr/local/bin/perl
+
+use Config;
+use File::Basename qw(&basename &dirname);
+use Cwd;
+
+# List explicitly here the variables you want Configure to
+# generate. Metaconfig only looks for shell variables, so you
+# have to mention them as if they were shell variables, not
+# %Config entries. Thus you write
+# $startperl
+# to ensure Configure will look for $Config{startperl}.
+
+# This forces PL files to create target in same directory as PL file.
+# This is so that make depend always knows where to find PL derivatives.
+my $origdir = cwd;
+chdir dirname($0);
+my $file = basename($0, '.PL');
+$file .= '.com' if $^O eq 'VMS';
+
+open OUT,">$file" or die "Can't create $file: $!";
+
+print "Extracting $file (with variable substitutions)\n";
+
+# In this section, perl variables will be expanded during extraction.
+# You can use $Config{...} to use Configure variables.
+
+print OUT <<"!GROK!THIS!";
+$Config{startperl}
+ eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
+ if \$running_under_some_shell;
+!GROK!THIS!
+
+use File::Spec;
+
+my $prove = File::Spec->catfile(File::Spec->catdir(File::Spec->updir,
+ "lib", "Test", "Harness", "bin"), "prove");
+
+if (open(PROVE, $prove)) {
+ print OUT <PROVE>;
+ close PROVE;
+} else {
+ die "$0: cannot find '$prove'\n";
+}
+
+close OUT or die "Can't close $file: $!";
+chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
+exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
+chdir $origdir;