Assimilate Test-Simple 0.50
Nicholas Clark [Sat, 20 Nov 2004 22:17:18 +0000 (22:17 +0000)]
p4raw-id: //depot/perl@23523

35 files changed:
MANIFEST
lib/Test/Builder.pm
lib/Test/More.pm
lib/Test/Simple.pm
lib/Test/Simple/Changes
lib/Test/Simple/TODO [new file with mode: 0644]
lib/Test/Simple/t/00signature.t [new file with mode: 0644]
lib/Test/Simple/t/00test_harness_check.t [new file with mode: 0644]
lib/Test/Simple/t/More.t
lib/Test/Simple/t/diag.t
lib/Test/Simple/t/eq_set.t [new file with mode: 0644]
lib/Test/Simple/t/extra.t
lib/Test/Simple/t/extra_one.t [new file with mode: 0644]
lib/Test/Simple/t/fail-like.t
lib/Test/Simple/t/fail-more.t
lib/Test/Simple/t/fail.t
lib/Test/Simple/t/fail_one.t [new file with mode: 0644]
lib/Test/Simple/t/harness_active.t [new file with mode: 0644]
lib/Test/Simple/t/has_plan2.t
lib/Test/Simple/t/is_deeply.t
lib/Test/Simple/t/missing.t
lib/Test/Simple/t/no_diag.t [new file with mode: 0644]
lib/Test/Simple/t/output.t
lib/Test/Simple/t/overload.t [new file with mode: 0644]
lib/Test/Simple/t/plan_is_noplan.t
lib/Test/Simple/t/plan_no_plan.t
lib/Test/Simple/t/reset.t [new file with mode: 0644]
lib/Test/Simple/t/thread_taint.t [new file with mode: 0644]
lib/Test/Simple/t/threads.t
lib/Test/Simple/t/todo.t
lib/Test/Simple/t/use_ok.t
lib/Test/Tutorial.pod
t/lib/NoExporter.pm [new file with mode: 0644]
t/lib/Test/Simple/Catch.pm
t/lib/TieOut.pm

index 05a30ad..128f790 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1776,19 +1776,25 @@ lib/Test.pm                     A simple framework for writing test scripts
 lib/Test/Simple/Changes                Test::Simple changes
 lib/Test/Simple.pm             Basic utility for writing tests
 lib/Test/Simple/README         Test::Simple README
+lib/Test/Simple/t/00signature.t        Test::Simple test
+lib/Test/Simple/t/00test_harness_check.t       Test::Simple test
 lib/Test/Simple/t/bad_plan.t   Test::Builder plan() test
 lib/Test/Simple/t/buffer.t     Test::Builder buffering test
 lib/Test/Simple/t/Builder.t    Test::Builder tests
 lib/Test/Simple/t/curr_test.t  Test::Builder->curr_test tests
 lib/Test/Simple/t/details.t    Test::Builder tests
 lib/Test/Simple/t/diag.t       Test::More diag() test
+lib/Test/Simple/t/eq_set.t     Test::Simple test
 lib/Test/Simple/t/exit.t       Test::Simple test, exit codes
 lib/Test/Simple/t/extra.t      Test::Simple test
+lib/Test/Simple/t/extra_one.t  Test::Simple test
 lib/Test/Simple/t/fail-like.t  Test::More test, like() failures
 lib/Test/Simple/t/fail-more.t  Test::More test, tests failing
 lib/Test/Simple/t/fail.t       Test::Simple test, test failures
+lib/Test/Simple/t/fail_one.t   Test::Simple test
 lib/Test/Simple/t/filehandles.t        Test::Simple test, STDOUT can be played with
 lib/Test/Simple/t/fork.t       Test::More fork tests
+lib/Test/Simple/t/harness_active.t     Test::Simple test
 lib/Test/Simple/t/has_plan2.t  Test::More->plan tests
 lib/Test/Simple/t/has_plan.t   Test::Builder->plan tests
 lib/Test/Simple/t/import.t     Test::More test, importing functions
@@ -1796,24 +1802,29 @@ lib/Test/Simple/t/is_deeply.t   Test::More test, is_deeply()
 lib/Test/Simple/t/maybe_regex.t        Test::Builder->maybe_regex() tests
 lib/Test/Simple/t/missing.t    Test::Simple test, missing tests
 lib/Test/Simple/t/More.t       Test::More test, basic stuff
+lib/Test/Simple/t/no_diag.t    Test::Simple test
 lib/Test/Simple/t/no_ending.t  Test::Builder test, no_ending()
 lib/Test/Simple/t/no_header.t  Test::Builder test, no_header()
 lib/Test/Simple/t/no_plan.t    Test::Simple test, forgot the plan
 lib/Test/Simple/t/ok_obj.t     Test::Builder object tests
 lib/Test/Simple/t/output.t     Test::Builder test, output methods
+lib/Test/Simple/t/overload.t   Test::Simple test
 lib/Test/Simple/t/plan_is_noplan.t     Test::Simple test, no_plan
 lib/Test/Simple/t/plan_no_plan.t       Test::More test, plan() w/no_plan
 lib/Test/Simple/t/plan_skip_all.t      Test::More test, plan() w/skip_all
 lib/Test/Simple/t/plan.t       Test::More test, plan()
+lib/Test/Simple/t/reset.t      Test::Simple test
 lib/Test/Simple/t/simple.t     Test::Simple test, basic stuff
 lib/Test/Simple/t/skipall.t    Test::More test, skip all tests
 lib/Test/Simple/t/skip.t       Test::More test, SKIP tests
 lib/Test/Simple/t/strays.t     Test::Builder stray newline checks
+lib/Test/Simple/t/thread_taint.t       Test::Simple test
 lib/Test/Simple/t/threads.t    Test::Builder thread-safe checks
 lib/Test/Simple/t/todo.t       Test::More test, TODO tests
 lib/Test/Simple/t/undef.t      Test::More test, undefs don't cause warnings
 lib/Test/Simple/t/useing.t     Test::More test, compile test
 lib/Test/Simple/t/use_ok.t     Test::More test, use_ok()
+lib/Test/Simple/TODO           Test::Simple TODO
 lib/Test/t/05_about_verbose.t  See if Test works
 lib/Test/t/fail.t              See if Test works
 lib/Test/t/mix.t               See if Test works
@@ -2475,6 +2486,7 @@ t/lib/Math/BigInt/BareCalc.pm     Bigint's simulation of Calc
 t/lib/Math/BigInt/Scalar.pm    Pure Perl module to support Math::BigInt
 t/lib/Math/BigInt/Subclass.pm  Empty subclass of BigInt for test
 t/lib/Math/BigRat/Test.pm              Math::BigRat test helper
+t/lib/NoExporter.pm                    Part of Test-Simple
 t/lib/sample-tests/bailout             Test data for Test::Harness
 t/lib/sample-tests/bignum              Test data for Test::Harness
 t/lib/sample-tests/combined            Test data for Test::Harness
index 331ce67..cb202f9 100644 (file)
@@ -7,34 +7,27 @@ use 5.004;
 $^C ||= 0;
 
 use strict;
-use vars qw($VERSION $CLASS);
-$VERSION = '0.17_01';
-$CLASS = __PACKAGE__;
+use vars qw($VERSION);
+$VERSION = '0.19_01';
 
 my $IsVMS = $^O eq 'VMS';
 
 # Make Test::Builder thread-safe for ithreads.
 BEGIN {
     use Config;
-    if( $] >= 5.008 && $Config{useithreads} ) {
-        require threads;
+    # Load threads::shared when threads are turned on
+    if( $] >= 5.008 && $Config{useithreads} && $INC{'threads.pm'}) {
         require threads::shared;
         threads::shared->import;
     }
+    # 5.8.0's threads::shared is busted when threads are off.
+    # We emulate it here.
     else {
-        *share = sub { 0 };
+        *share = sub { return $_[0] };
         *lock  = sub { 0 };
     }
 }
 
-use vars qw($Level);
-my($Test_Died) = 0;
-my($Have_Plan) = 0;
-my $Original_Pid = $$;
-my $Curr_Test = 0;      share($Curr_Test);
-my @Test_Results = ();  share(@Test_Results);
-my @Test_Details = ();  share(@Test_Details);
-
 
 =head1 NAME
 
@@ -92,13 +85,69 @@ getting the same object.  (This is called a singleton).
 
 =cut
 
-my $Test;
+my $Test = Test::Builder->new;
 sub new {
     my($class) = shift;
     $Test ||= bless ['Move along, nothing to see here'], $class;
     return $Test;
 }
 
+=item B<reset>
+
+  $Test->reset;
+
+Reinitializes the Test::Builder singleton to its original state.
+Mostly useful for tests run in persistent environments where the same
+test might be run multiple times in the same process.
+
+=cut
+
+my $Test_Died;
+my $Have_Plan;
+my $No_Plan;
+my $Curr_Test;     share($Curr_Test);
+use vars qw($Level);
+my $Original_Pid;
+my @Test_Results;  share(@Test_Results);
+my @Test_Details;  share(@Test_Details);
+
+my $Exported_To;
+my $Expected_Tests;
+
+my $Skip_All;
+
+my $Use_Nums;
+
+my($No_Header, $No_Ending);
+
+$Test->reset;
+
+sub reset {
+    my ($self) = @_;
+
+    $Test_Died = 0;
+    $Have_Plan = 0;
+    $No_Plan   = 0;
+    $Curr_Test = 0;
+    $Level     = 1;
+    $Original_Pid = $$;
+    @Test_Results = ();
+    @Test_Details = ();
+
+    $Exported_To    = undef;
+    $Expected_Tests = 0;
+
+    $Skip_All = 0;
+
+    $Use_Nums = 1;
+
+    ($No_Header, $No_Ending) = (0,0);
+
+    $self->_dup_stdhandles unless $^C;
+
+    return undef;
+}
+
 =back
 
 =head2 Setting up tests
@@ -118,7 +167,6 @@ This is important for getting TODO tests right.
 
 =cut
 
-my $Exported_To;
 sub exported_to {
     my($self, $pack) = @_;
 
@@ -188,7 +236,6 @@ the appropriate headers.
 
 =cut
 
-my $Expected_Tests = 0;
 sub expected_tests {
     my($self, $max) = @_;
 
@@ -210,7 +257,6 @@ Declares that this test will run an indeterminate # of tests.
 
 =cut
 
-my($No_Plan) = 0;
 sub no_plan {
     $No_Plan    = 1;
     $Have_Plan  = 1;
@@ -240,7 +286,6 @@ Skips all the tests, using the given $reason.  Exits immediately with 0.
 
 =cut
 
-my $Skip_All = 0;
 sub skip_all {
     my($self, $reason) = @_;
 
@@ -289,6 +334,17 @@ sub ok {
     lock $Curr_Test;
     $Curr_Test++;
 
+    # In case $name is a string overloaded object, force it to stringify.
+    local($@,$!);
+    eval { 
+        if( defined $name ) {
+            require overload;
+            if( my $string_meth = overload::Method($name, '""') ) {
+                $name = $name->$string_meth();
+            }
+        }
+    };
+
     $self->diag(<<ERR) if defined $name and $name =~ /^[\d\s]+$/;
     You named your test '$name'.  You shouldn't use numbers for your test names.
     Very confusing.
@@ -299,8 +355,7 @@ ERR
     my $todo = $self->todo($pack);
 
     my $out;
-    my $result = {};
-    share($result);
+    my $result = &share({});
 
     unless( $test ) {
         $out .= "not ";
@@ -340,6 +395,7 @@ ERR
 
     unless( $test ) {
         my $msg = $todo ? "Failed (TODO)" : "Failed";
+        $self->_print_diag("\n") if $ENV{HARNESS_ACTIVE};
         $self->diag("    $msg test ($file at line $line)\n");
     } 
 
@@ -445,7 +501,7 @@ sub isnt_eq {
         my $test = defined $got || defined $dont_expect;
 
         $self->ok($test, $name);
-        $self->_cmp_diag('ne', $got, $dont_expect) unless $test;
+        $self->_cmp_diag($got, 'ne', $dont_expect) unless $test;
         return $test;
     }
 
@@ -461,7 +517,7 @@ sub isnt_num {
         my $test = defined $got || defined $dont_expect;
 
         $self->ok($test, $name);
-        $self->_cmp_diag('!=', $got, $dont_expect) unless $test;
+        $self->_cmp_diag($got, '!=', $dont_expect) unless $test;
         return $test;
     }
 
@@ -662,16 +718,13 @@ sub skip {
     lock($Curr_Test);
     $Curr_Test++;
 
-    my %result;
-    share(%result);
-    %result = (
+    $Test_Results[$Curr_Test-1] = &share({
         'ok'      => 1,
         actual_ok => 1,
         name      => '',
         type      => 'skip',
         reason    => $why,
-    );
-    $Test_Results[$Curr_Test-1] = \%result;
+    });
 
     my $out = "ok";
     $out   .= " $Curr_Test" if $self->use_numbers;
@@ -707,17 +760,13 @@ sub todo_skip {
     lock($Curr_Test);
     $Curr_Test++;
 
-    my %result;
-    share(%result);
-    %result = (
+    $Test_Results[$Curr_Test-1] = &share({
         'ok'      => 1,
         actual_ok => 0,
         name      => '',
         type      => 'todo_skip',
         reason    => $why,
-    );
-
-    $Test_Results[$Curr_Test-1] = \%result;
+    });
 
     my $out = "not ok";
     $out   .= " $Curr_Test" if $self->use_numbers;
@@ -779,8 +828,6 @@ sub level {
     return $Level;
 }
 
-$CLASS->level(1);
-
 
 =item B<use_numbers>
 
@@ -807,7 +854,6 @@ Defaults to on.
 
 =cut
 
-my $Use_Nums = 1;
 sub use_numbers {
     my($self, $use_nums) = @_;
 
@@ -828,13 +874,12 @@ If set to true, no "1..N" header will be printed.
     $Test->no_ending($no_ending);
 
 Normally, Test::Builder does some extra diagnostics when the test
-ends.  It also changes the exit code as described in Test::Simple.
+ends.  It also changes the exit code as described below.
 
 If this is true, none of that will be done.
 
 =cut
 
-my($No_Header, $No_Ending) = (0,0);
 sub no_header {
     my($self, $no_header) = @_;
 
@@ -905,9 +950,7 @@ sub diag {
     push @msgs, "\n" unless $msgs[-1] =~ /\n\Z/;
 
     local $Level = $Level + 1;
-    my $fh = $self->todo ? $self->todo_output : $self->failure_output;
-    local($\, $", $,) = (undef, ' ', '');
-    print $fh @msgs;
+    $self->_print_diag(@msgs);
 
     return 0;
 }
@@ -946,6 +989,22 @@ sub _print {
 }
 
 
+=item B<_print_diag>
+
+    $Test->_print_diag(@msg);
+
+Like _print, but prints to the current diagnostic filehandle.
+
+=cut
+
+sub _print_diag {
+    my $self = shift;
+
+    local($\, $", $,) = (undef, ' ', '');
+    my $fh = $self->todo ? $self->todo_output : $self->failure_output;
+    print $fh @_;
+}    
+
 =item B<output>
 
     $Test->output($fh);
@@ -1019,11 +1078,19 @@ sub _new_fh {
     return $fh;
 }
 
-unless( $^C ) {
-    # We dup STDOUT and STDERR so people can change them in their
-    # test suites while still getting normal test output.
-    open(TESTOUT, ">&STDOUT") or die "Can't dup STDOUT:  $!";
-    open(TESTERR, ">&STDERR") or die "Can't dup STDERR:  $!";
+sub _autoflush {
+    my($fh) = shift;
+    my $old_fh = select $fh;
+    $| = 1;
+    select $old_fh;
+}
+
+
+my $Opened_Testhandles = 0;
+sub _dup_stdhandles {
+    my $self = shift;
+
+    $self->_open_testhandles unless $Opened_Testhandles;
 
     # Set everything to unbuffered else plain prints to STDOUT will
     # come out in the wrong order from our own prints.
@@ -1032,16 +1099,17 @@ unless( $^C ) {
     _autoflush(\*TESTERR);
     _autoflush(\*STDERR);
 
-    $CLASS->output(\*TESTOUT);
-    $CLASS->failure_output(\*TESTERR);
-    $CLASS->todo_output(\*TESTOUT);
+    $Test->output(\*TESTOUT);
+    $Test->failure_output(\*TESTERR);
+    $Test->todo_output(\*TESTOUT);
 }
 
-sub _autoflush {
-    my($fh) = shift;
-    my $old_fh = select $fh;
-    $| = 1;
-    select $old_fh;
+sub _open_testhandles {
+    # We dup STDOUT and STDERR so people can change them in their
+    # test suites while still getting normal test output.
+    open(TESTOUT, ">&STDOUT") or die "Can't dup STDOUT:  $!";
+    open(TESTERR, ">&STDERR") or die "Can't dup STDERR:  $!";
+    $Opened_Testhandles = 1;
 }
 
 
@@ -1077,15 +1145,13 @@ sub current_test {
         if( $num > @Test_Results ) {
             my $start = @Test_Results ? $#Test_Results + 1 : 0;
             for ($start..$num-1) {
-                my %result;
-                share(%result);
-                %result = ( ok        => 1, 
-                            actual_ok => undef, 
-                            reason    => 'incrementing test number', 
-                            type      => 'unknown', 
-                            name      => undef 
-                          );
-                $Test_Results[$_] = \%result;
+                $Test_Results[$_] = &share({
+                    'ok'      => 1, 
+                    actual_ok => undef, 
+                    reason    => 'incrementing test number', 
+                    type      => 'unknown', 
+                    name      => undef 
+                });
             }
         }
     }
@@ -1315,13 +1381,12 @@ sub _ending {
             $Expected_Tests = $Curr_Test;
         }
 
-        # 5.8.0 threads bug.  Shared arrays will not be auto-extended 
-        # by a slice.  Worse, we have to fill in every entry else
-        # we'll get an "Invalid value for shared scalar" error
-        for my $idx ($#Test_Results..$Expected_Tests-1) {
-            my %empty_result = ();
-            share(%empty_result);
-            $Test_Results[$idx] = \%empty_result
+        # Auto-extended arrays and elements which aren't explicitly
+        # filled in with a shared reference will puke under 5.8.0
+        # ithreads.  So we have to fill them in by hand. :(
+        my $empty_result = &share({});
+        for my $idx ( 0..$Expected_Tests-1 ) {
+            $Test_Results[$idx] = $empty_result
               unless defined $Test_Results[$idx];
         }
 
@@ -1329,19 +1394,22 @@ sub _ending {
         $num_failed += abs($Expected_Tests - @Test_Results);
 
         if( $Curr_Test < $Expected_Tests ) {
+            my $s = $Expected_Tests == 1 ? '' : 's';
             $self->diag(<<"FAIL");
-Looks like you planned $Expected_Tests tests but only ran $Curr_Test.
+Looks like you planned $Expected_Tests test$s but only ran $Curr_Test.
 FAIL
         }
         elsif( $Curr_Test > $Expected_Tests ) {
             my $num_extra = $Curr_Test - $Expected_Tests;
+            my $s = $Expected_Tests == 1 ? '' : 's';
             $self->diag(<<"FAIL");
-Looks like you planned $Expected_Tests tests but ran $num_extra extra.
+Looks like you planned $Expected_Tests test$s but ran $num_extra extra.
 FAIL
         }
         elsif ( $num_failed ) {
+            my $s = $num_failed == 1 ? '' : 's';
             $self->diag(<<"FAIL");
-Looks like you failed $num_failed tests of $Expected_Tests.
+Looks like you failed $num_failed test$s of $Expected_Tests.
 FAIL
         }
 
@@ -1362,6 +1430,7 @@ FAIL
         $self->diag(<<'FAIL');
 Looks like your test died before it could output anything.
 FAIL
+        _my_exit( 255 ) && return;
     }
     else {
         $self->diag("No tests run!\n");
@@ -1373,12 +1442,34 @@ END {
     $Test->_ending if defined $Test and !$Test->no_ending;
 }
 
+=head1 EXIT CODES
+
+If all your tests passed, Test::Builder will exit with zero (which is
+normal).  If anything failed it will exit with how many failed.  If
+you run less (or more) tests than you planned, the missing (or extras)
+will be considered failures.  If no tests were ever run Test::Builder
+will throw a warning and exit with 255.  If the test died, even after
+having successfully completed all its tests, it will still be
+considered a failure and will exit with 255.
+
+So the exit codes are...
+
+    0                   all tests successful
+    255                 test died
+    any other number    how many failed (including missing or extras)
+
+If you fail more than 254 tests, it will be reported as 254.
+
+
 =head1 THREADS
 
 In perl 5.8.0 and later, Test::Builder is thread-safe.  The test
 number is shared amongst all threads.  This means if one thread sets
 the test number using current_test() they will all be effected.
 
+Test::Builder is only thread-aware if threads.pm is loaded I<before>
+Test::Builder.
+
 =head1 EXAMPLES
 
 CPAN can provide the best examples.  Test::Simple, Test::More,
index d82f81d..5ca95e6 100644 (file)
@@ -18,7 +18,7 @@ sub _carp {
 
 require Exporter;
 use vars qw($VERSION @ISA @EXPORT %EXPORT_TAGS $TODO);
-$VERSION = '0.47';
+$VERSION = '0.50';
 @ISA    = qw(Exporter);
 @EXPORT = qw(ok use_ok require_ok
              is isnt like unlike is_deeply
@@ -33,6 +33,7 @@ $VERSION = '0.47';
             );
 
 my $Test = Test::Builder->new;
+my $Show_Diag = 1;
 
 
 # 5.004's Exporter doesn't have export_to_level.
@@ -138,6 +139,9 @@ have no plan.  (Try to avoid using this as it weakens your test.)
 
   use Test::More qw(no_plan);
 
+B<NOTE>: using no_plan requires a Test::Harness upgrade else it will
+think everything has failed.  See L<BUGS and CAVEATS>)
+
 In some cases, you'll want to completely skip an entire testing script.
 
   use Test::More skip_all => $skip_reason;
@@ -177,16 +181,25 @@ sub plan {
 
     $Test->exported_to($caller);
 
+    my @cleaned_plan;
     my @imports = ();
-    foreach my $idx (0..$#plan) {
+    my $idx = 0;
+    while( $idx <= $#plan ) {
         if( $plan[$idx] eq 'import' ) {
-            my($tag, $imports) = splice @plan, $idx, 2;
-            @imports = @$imports;
-            last;
+            @imports = @{$plan[$idx+1]};
+            $idx += 2;
+        }
+        elsif( $plan[$idx] eq 'no_diag' ) {
+            $Show_Diag = 0;
+            $idx++;
+        }
+        else {
+            push @cleaned_plan, $plan[$idx];
+            $idx++;
         }
     }
 
-    $Test->plan(@plan);
+    $Test->plan(@cleaned_plan);
 
     __PACKAGE__->_export_to_level(1, __PACKAGE__, @imports);
 }
@@ -314,14 +327,14 @@ You are encouraged to use is() and isnt() over ok() where possible,
 however do not be tempted to use them to find out if something is
 true or false!
 
-  # XXX BAD!  $pope->isa('Catholic') eq 1
-  is( $pope->isa('Catholic'), 1,        'Is the Pope Catholic?' );
+  # XXX BAD!
+  is( exists $brooklyn{tree}, 1, 'A tree grows in Brooklyn' );
 
-This does not check if C<$pope->isa('Catholic')> is true, it checks if
+This does not check if C<exists $brooklyn{tree}> is true, it checks if
 it returns 1.  Very different.  Similar caveats exist for false and 0.
 In these cases, use ok().
 
-  ok( $pope->isa('Catholic') ),         'Is the Pope Catholic?' );
+  ok( exists $brooklyn{tree},    'A tree grows in Brooklyn' );
 
 For those grammatical pedants out there, there's an C<isn't()>
 function which is an alias of isnt().
@@ -383,7 +396,7 @@ given pattern.
 
 =cut
 
-sub unlike {
+sub unlike ($$;$) {
     $Test->unlike(@_);
 }
 
@@ -402,7 +415,7 @@ compare two arguments using any binary perl operator.
     cmp_ok( $this, '==', $that, 'this == that' );
 
     # ok( $this && $that );
-    cmp_ok( $this, '&&', $that, 'this || that' );
+    cmp_ok( $this, '&&', $that, 'this && that' );
     ...etc...
 
 Its advantage over ok() is when the test fails you'll know what $this
@@ -488,7 +501,7 @@ sub can_ok ($@) {
   isa_ok($object, $class, $object_name);
   isa_ok($ref,    $type,  $ref_name);
 
-Checks to see if the given $object->isa($class).  Also checks to make
+Checks to see if the given C<< $object->isa($class) >>.  Also checks to make
 sure the object was defined in the first place.  Handy for this sort
 of thing:
 
@@ -619,6 +632,12 @@ which would produce:
 You might remember C<ok() or diag()> with the mnemonic C<open() or
 die()>.
 
+All diag()s can be made silent by passing the "no_diag" option to
+Test::More.  C<use Test::More tests => 1, 'no_diag'>.  This is useful
+if you have diagnostics for personal testing but then wish to make
+them silent for release without commenting out each individual
+statement.
+
 B<NOTE> The exact formatting of the diagnostic output is still
 changing, but it is guaranteed that whatever you throw at it it won't
 interfere with the test.
@@ -626,6 +645,7 @@ interfere with the test.
 =cut
 
 sub diag {
+    return unless $Show_Diag;
     $Test->diag(@_);
 }
 
@@ -658,7 +678,12 @@ is like doing this:
 
    use Some::Module qw(foo bar);
 
-don't try to do this:
+Version numbers can be checked like so:
+
+   # Just like "use Some::Module 1.02"
+   BEGIN { use_ok('Some::Module', 1.02) }
+
+Don't try to do this:
 
    BEGIN {
        use_ok('Some::Module');
@@ -667,7 +692,7 @@ don't try to do this:
        ...happening at compile time...
    }
 
-instead, you want:
+because the notion of "compile-time" is relative.  Instead, you want:
 
   BEGIN { use_ok('Some::Module') }
   BEGIN { ...some code that depends on the use... }
@@ -679,19 +704,31 @@ sub use_ok ($;@) {
     my($module, @imports) = @_;
     @imports = () unless @imports;
 
-    my $pack = caller;
+    my($pack,$filename,$line) = caller;
 
     local($@,$!);   # eval sometimes interferes with $!
-    eval <<USE;
+
+    if( @imports == 1 and $imports[0] =~ /^\d+(?:\.\d+)?$/ ) {
+        # probably a version check.  Perl needs to see the bare number
+        # for it to work with non-Exporter based modules.
+        eval <<USE;
 package $pack;
-require $module;
-'$module'->import(\@imports);
+use $module $imports[0];
 USE
+    }
+    else {
+        eval <<USE;
+package $pack;
+use $module \@imports;
+USE
+    }
 
     my $ok = $Test->ok( !$@, "use $module;" );
 
     unless( $ok ) {
         chomp $@;
+        $@ =~ s{^BEGIN failed--compilation aborted at .*$}
+                {BEGIN failed--compilation aborted at $filename line $line.}m;
         $Test->diag(<<DIAGNOSTIC);
     Tried to use '$module'.
     Error:  $@
@@ -851,6 +888,9 @@ and you'll know immediately when they're fixed.
 Once a todo test starts succeeding, simply move it outside the block.
 When the block is empty, delete it.
 
+B<NOTE>: TODO tests require a Test::Harness upgrade else it will
+treat it as a normal failure.  See L<BUGS and CAVEATS>)
+
 
 =item B<todo_skip>
 
@@ -924,16 +964,25 @@ references, it does a deep comparison walking each data structure to
 see if they are equivalent.  If the two structures are different, it
 will display the place where they start differing.
 
-Barrie Slaymaker's Test::Differences module provides more in-depth
-functionality along these lines, and it plays well with Test::More.
-
-B<NOTE> Display of scalar refs is not quite 100%
+Test::Differences and Test::Deep provide more in-depth functionality
+along these lines.
 
 =cut
 
 use vars qw(@Data_Stack);
 my $DNE = bless [], 'Does::Not::Exist';
 sub is_deeply {
+    unless( @_ == 2 or @_ == 3 ) {
+        my $msg = <<WARNING;
+is_deeply() takes two or three args, you gave %d.
+This usually means you passed an array or hash instead 
+of a reference to it
+WARNING
+        chop $msg;   # clip off newline so carp() will put in line/file
+
+        _carp sprintf $msg, scalar @_;
+    }
+
     my($this, $that, $name) = @_;
 
     my $ok;
@@ -1117,7 +1166,7 @@ While the order of elements does not matter, duplicate elements do.
 # We must make sure that references are treated neutrally.  It really
 # doesn't matter how we sort them, as long as both arrays are sorted
 # with the same algorithm.
-sub _bogus_sort { local $^W = 0;  ref $a ? 0 : $a cmp $b }
+sub _bogus_sort { local $^W = 0;  ref $a ? -1 : ref $b ? 1 : $a cmp $b }
 
 sub eq_set  {
     my($a1, $a2) = @_;
@@ -1159,16 +1208,46 @@ sub builder {
 =back
 
 
+=head1 EXIT CODES
+
+If all your tests passed, Test::Builder will exit with zero (which is
+normal).  If anything failed it will exit with how many failed.  If
+you run less (or more) tests than you planned, the missing (or extras)
+will be considered failures.  If no tests were ever run Test::Builder
+will throw a warning and exit with 255.  If the test died, even after
+having successfully completed all its tests, it will still be
+considered a failure and will exit with 255.
+
+So the exit codes are...
+
+    0                   all tests successful
+    255                 test died
+    any other number    how many failed (including missing or extras)
+
+If you fail more than 254 tests, it will be reported as 254.
+
+
 =head1 NOTES
 
 Test::More is B<explicitly> tested all the way back to perl 5.004.
 
-Test::More is thread-safe for perl 5.8.0 and up.
-
 =head1 BUGS and CAVEATS
 
 =over 4
 
+=item Threads
+
+Test::More will only be aware of threads if "use threads" has been done
+I<before> Test::More is loaded.  This is ok:
+
+    use threads;
+    use Test::More;
+
+This may cause problems:
+
+    use Test::More
+    use threads;
+
 =item Making your own ok()
 
 If you are trying to extend Test::More, don't.  Use Test::Builder
@@ -1176,7 +1255,7 @@ instead.
 
 =item The eq_* family has some caveats.
 
-=item Test::Harness upgrades
+=item Test::Harness upgrade
 
 no_plan and todo depend on new Test::Harness features and fixes.  If
 you're going to distribute tests that use no_plan or todo your
@@ -1184,8 +1263,7 @@ end-users will have to upgrade Test::Harness to the latest one on
 CPAN.  If you avoid no_plan and TODO tests, the stock Test::Harness
 will work fine.
 
-If you simply depend on Test::More, it's own dependencies will cause a
-Test::Harness upgrade.
+Installing Test::More should also upgrade Test::Harness.
 
 =back
 
@@ -1211,32 +1289,36 @@ L<Test::Simple> if all this confuses you and you just want to write
 some tests.  You can upgrade to Test::More later (it's forward
 compatible).
 
-L<Test::Differences> for more ways to test complex data structures.
-And it plays well with Test::More.
-
 L<Test> is the old testing module.  Its main benefit is that it has
 been distributed with Perl since 5.004_05.
 
 L<Test::Harness> for details on how your test results are interpreted
 by Perl.
 
-L<Test::Unit> describes a very featureful unit testing interface.
+L<Test::Differences> for more ways to test complex data structures.
+And it plays well with Test::More.
+
+L<Test::Class> is like XUnit but more perlish.
+
+L<Test::Deep> gives you more powerful complex data structure testing.
+
+L<Test::Unit> is XUnit style testing.
 
 L<Test::Inline> shows the idea of embedded testing.
 
-L<SelfTest> is another approach to embedded testing.
+L<Bundle::Test> installs a whole bunch of useful test modules.
 
 
 =head1 AUTHORS
 
 Michael G Schwern E<lt>schwern@pobox.comE<gt> with much inspiration
 from Joshua Pritikin's Test module and lots of help from Barrie
-Slaymaker, Tony Bowden, chromatic and the perl-qa gang.
+Slaymaker, Tony Bowden, blackstar.co.uk, chromatic and the perl-qa gang.
 
 
 =head1 COPYRIGHT
 
-Copyright 2001 by Michael G Schwern E<lt>schwern@pobox.comE<gt>.
+Copyright 2001, 2002 by Michael G Schwern E<lt>schwern@pobox.comE<gt>.
 
 This program is free software; you can redistribute it and/or 
 modify it under the same terms as Perl itself.
index 563528b..45b2bb5 100644 (file)
@@ -4,7 +4,7 @@ use 5.004;
 
 use strict 'vars';
 use vars qw($VERSION);
-$VERSION = '0.47';
+$VERSION = '0.50';
 
 
 use Test::Builder;
index 272b07e..89c617a 100644 (file)
@@ -1,4 +1,49 @@
-Revision history for Perl extension Test::Simple
+0.50  Sat Nov 20 00:28:44 EST 2004
+    * Fixed bug in fail-more test on Windows (not a real bug).
+      [rt.cpan.org 8022]
+    - Change from CVS to SVK.  Hopefully this is the last version control
+      system change.
+    - Again removing File::Spec dependency (came back in 0.48_02)
+    - Change from Aegis back to CVS
+
+0.49  Thu Oct 14 21:58:50 EDT 2004
+    - t/harness_active.t would fail for frivolous reasons with older
+      MakeMakers (test bug) [thanks Bill Moseley for noticing]
+
+0.48_02  Mon Jul 19 02:07:23 EDT 2004
+    * Overloaded objects as names now won't blow up under threads
+      [rt.cpan.org 4218 and 4232]
+    * Overloaded objects which stringify to undef used as test names
+      now won't cause internal uninit warnings. [rt.cpan.org 4232]
+    * Failure diagnostics now come out on their own line when run in 
+      Test::Harness.
+    - eq_set() sometimes wasn't giving the right results if nested refs 
+      were involved [rt.cpan.org 3747]
+    - isnt() giving wrong diagnostics and warning if given any undefs.
+    * Give unlike() the right prototype [rt.cpan.org 4944]
+    - Change from CVS to Aegis
+    - is_deeply() will now do some basic argument checks to guard against
+      accidentally passing in a whole array instead of its reference.
+    - Mentioning Test::Differences, Test::Deep and Bundle::Test.
+    - Removed dependency on File::Spec.
+    - Fixing the grammar of diagnostic outputs when only a single test
+      is run or failed (ie. "Looks like you failed 1 tests").
+      [Darren Chamberlain]
+
+0.48_01  Mon Nov 11 02:36:43 EST 2002
+    - Mention Test::Class in Test::More's SEE ALSO
+    * use_ok() now DWIM for version checks
+    - More problems with ithreads fixed.
+    * Test::Harness upgrade no longer optional.  It was causing too
+      many problems when the T::H upgrade didn't work.
+    * Drew Taylor added a 'no_diag' option to Test::More to switch
+      off all diag() statements.
+    * Test::Builder/More no longer automatically loads threads.pm
+      when threads are enabled.  The user must now do this manually.
+    * Alex Francis added reset() reset the state of Test::Builder in 
+      persistent environments.
+    - David Hand noted that Test::Builder/More exit code behavior was
+      not documented.  Only Test::Simple.
 
 0.47  Mon Aug 26 03:54:22 PDT 2002 
     * Tatsuhiko Miyagawa noticed Test::Builder was accidentally storing 
diff --git a/lib/Test/Simple/TODO b/lib/Test/Simple/TODO
new file mode 100644 (file)
index 0000000..71f4285
--- /dev/null
@@ -0,0 +1,37 @@
+    Test use_ok() with imports better.
+
+    Add BAIL_OUT() (little known Test::Harness feature that basically
+    declares that the universe has turned out all wrong and the test
+    will now stop what it's doing and just go back to bed.)
+
+    Add a way to ask "Are we passing so far?".  Probably a
+    Test::Builder method.
+
+    Finish (start?) Test::FAQ
+
+    Expand the Test::Tutorial
+
+    Restructure the Test::More synopsis.
+
+    Decide if the exit code behavior on failure is a useful default
+    case.
+
+    $^C exception control?
+
+    Document that everything goes through Test::Builder->ok()
+
+    Add test name to diagnostic output
+
+    Put a newline before the first diagnostic failure when in Test::Harness
+
+    Trap bare exit() calls.
+
+    Add diag() to details().
+
+    Add is_passing() method to check if we're passing?
+
+    Add at_end() callback?
+
+    Combine all *output methods into outputs().
+
+    Change *output* to return the old FH, not the new one when setting.
diff --git a/lib/Test/Simple/t/00signature.t b/lib/Test/Simple/t/00signature.t
new file mode 100644 (file)
index 0000000..b36f68e
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+# $File: //member/autrijus/Module-Signature/t/0-signature.t $ $Author: autrijus $
+# $Revision: #5 $ $Change: 7212 $ $DateTime: 2003/07/28 14:21:21 $
+
+use strict;
+use Test::More tests => 1;
+
+SKIP: {
+    if (!eval { require Module::Signature; 1 }) {
+       skip("Next time around, consider install Module::Signature, ".
+            "so you can verify the integrity of this distribution.", 1);
+    }
+    elsif (!eval { require Socket; Socket::inet_aton('pgp.mit.edu') }) {
+       skip("Cannot connect to the keyserver", 1);
+    }
+    else {
+       ok(Module::Signature::verify() == Module::Signature::SIGNATURE_OK()
+           => "Valid signature" );
+    }
+}
+
+__END__
diff --git a/lib/Test/Simple/t/00test_harness_check.t b/lib/Test/Simple/t/00test_harness_check.t
new file mode 100644 (file)
index 0000000..7a290f4
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/perl -w
+
+# A test to make sure the new Test::Harness was installed properly.
+
+use Test::More;
+plan tests => 1;
+
+require Test::Harness;
+unless( cmp_ok( $Test::Harness::VERSION, '>', 1.20, "T::H version" ) ) {
+    diag <<INSTRUCTIONS;
+
+Test::Simple/More/Builder has features which depend on a version of
+Test::Harness greater than 1.20.  You have $Test::Harness::VERSION.
+Please install a new version from CPAN.
+
+If you've already tried to upgrade Test::Harness and still get this
+message, the new version may be "shadowed" by the old.  Check the
+output of Test::Harness's "make install" for "## Differing version"
+messages.  You can delete the old version by running 
+"make install UNINST=1".
+
+INSTRUCTIONS
+}
+
index df8c5fe..71f3fd0 100644 (file)
@@ -7,7 +7,7 @@ BEGIN {
     }
 }
 
-use Test::More tests => 41;
+use Test::More tests => 42;
 
 # Make sure we don't mess with $@ or $!.  Test at bottom.
 my $Err   = "this should not be touched";
@@ -33,6 +33,9 @@ unlike("fbar", '/^bar/',    'unlike bar');
 unlike("FooBle", '/foo/',   'foo is unlike FooBle');
 unlike("/var/local/pr0n/", '/^\/usr\/local/','regexes with slashes in unlike' );
 
+my @foo = qw(foo bar baz);
+unlike(@foo, '/foo/');
+
 can_ok('Test::More', qw(require_ok use_ok ok is isnt like skip can_ok
                         pass fail eq_array eq_hash eq_set));
 can_ok(bless({}, "Test::More"), qw(require_ok use_ok ok is isnt like skip 
index 453984b..3afdc17 100644 (file)
@@ -7,6 +7,18 @@ BEGIN {
     }
 }
 
+
+# Turn on threads here, if available, since this test tends to find
+# lots of threading bugs.
+use Config;
+BEGIN {
+    if( $] >= 5.008 && $Config{useithreads} ) {
+        require threads;
+        'threads'->import;
+    }
+}
+
+
 use strict;
 
 use Test::More tests => 7;
diff --git a/lib/Test/Simple/t/eq_set.t b/lib/Test/Simple/t/eq_set.t
new file mode 100644 (file)
index 0000000..4785507
--- /dev/null
@@ -0,0 +1,21 @@
+#!perl -w
+
+BEGIN {
+    if( $ENV{PERL_CORE} ) {
+        chdir 't';
+        @INC = ('../lib', 'lib');
+    }
+    else {
+        unshift @INC, 't/lib';
+    }
+}
+chdir 't';
+
+use strict;
+use Test::More;
+
+plan tests => 2;
+
+# RT 3747
+ok( eq_set([1, 2, [3]], [[3], 1, 2]) );
+ok( eq_set([1,2,[3]], [1,[3],2]) );
index 1ed94ad..4dceb2c 100644 (file)
@@ -34,6 +34,7 @@ chdir 't';
 push @INC, '../t/lib/';
 require Test::Simple::Catch;
 my($out, $err) = Test::Simple::Catch::caught();
+local $ENV{HARNESS_ACTIVE} = 0;
 
 Test::Simple->import(tests => 3);
 
diff --git a/lib/Test/Simple/t/extra_one.t b/lib/Test/Simple/t/extra_one.t
new file mode 100644 (file)
index 0000000..f8dacc6
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+    if( $ENV{PERL_CORE} ) {
+        chdir 't';
+        @INC = ('../lib', 'lib');
+    }
+    else {
+        unshift @INC, 't/lib';
+    }
+}
+
+use strict;
+
+require Test::Simple::Catch;
+my($out, $err) = Test::Simple::Catch::caught();
+
+# Can't use Test.pm, that's a 5.005 thing.
+package My::Test;
+
+print "1..2\n";
+
+my $test_num = 1;
+# Utility testing functions.
+sub ok ($;$) {
+    my($test, $name) = @_;
+    my $ok = '';
+    $ok .= "not " unless $test;
+    $ok .= "ok $test_num";
+    $ok .= " - $name" if defined $name;
+    $ok .= "\n";
+    print $ok;
+    $test_num++;
+}
+
+
+package main;
+
+require Test::Simple;
+Test::Simple->import(tests => 1);
+ok(1);
+ok(1);
+ok(1);
+
+END {
+    My::Test::ok($$out eq <<OUT);
+1..1
+ok 1
+ok 2
+ok 3
+OUT
+
+    My::Test::ok($$err eq <<ERR);
+# Looks like you planned 1 test but ran 2 extra.
+ERR
+
+    # Prevent Test::Simple from existing with non-zero
+    exit 0;
+}
index 1336763..799762f 100644 (file)
@@ -2,7 +2,7 @@
 # of high enough version.
 BEGIN { 
     if( $] < 5.005 ) {
-        print "1..0\n";
+        print "1..0 # Skipped Test requires qr//\n";
         exit(0);
     }
 }
@@ -24,6 +24,7 @@ use strict;
 
 require Test::Simple::Catch;
 my($out, $err) = Test::Simple::Catch::caught();
+local $ENV{HARNESS_ACTIVE} = 0;
 
 
 # Can't use Test.pm, that's a 5.005 thing.
@@ -63,7 +64,7 @@ OUT
 #     Failed test \\(.*\\)
 #                   'foo'
 #     doesn't match '\\(\\?-xism:that\\)'
-# Looks like you failed 1 tests of 1\\.
+# Looks like you failed 1 test of 1\\.
 ERR
 
 
index 29f8eb2..ab18b5b 100644 (file)
@@ -14,12 +14,13 @@ use strict;
 
 require Test::Simple::Catch;
 my($out, $err) = Test::Simple::Catch::caught();
+local $ENV{HARNESS_ACTIVE} = 0;
 
 
 # Can't use Test.pm, that's a 5.005 thing.
 package My::Test;
 
-print "1..2\n";
+print "1..12\n";
 
 my $test_num = 1;
 # Utility testing functions.
@@ -37,98 +38,43 @@ sub ok ($;$) {
 }
 
 
+sub main::err ($) {
+    my($expect) = @_;
+    my $got = $err->read;
+
+    my $ok = ok( $got eq $expect );
+
+    unless( $ok ) {
+        print STDERR "$got\n";
+        print STDERR "$expect\n";
+    }
+
+    return $ok;
+}
+
+
 package main;
 
 require Test::More;
-my $Total = 28;
+my $Total = 29;
 Test::More->import(tests => $Total);
 
+my $tb = Test::More->builder;
+$tb->use_numbers(0);
+
 # Preserve the line numbers.
 #line 38
 ok( 0, 'failing' );
+err( <<ERR );
+#     Failed test ($0 at line 38)
+ERR
 
 #line 40
 is( "foo", "bar", 'foo is bar?');
 is( undef, '',    'undef is empty string?');
 is( undef, 0,     'undef is 0?');
 is( '',    0,     'empty string is 0?' );
-
-isnt("foo", "foo", 'foo isnt foo?' );
-isn't("foo", "foo",'foo isn\'t foo?' );
-
-like( "foo", '/that/',  'is foo like that' );
-unlike( "foo", '/foo/', 'is foo unlike foo' );
-
-# Nick Clark found this was a bug.  Fixed in 0.40.
-like( "bug", '/(%)/',   'regex with % in it' );
-
-fail('fail()');
-
-#line 52
-can_ok('Mooble::Hooble::Yooble', qw(this that));
-can_ok('Mooble::Hooble::Yooble', ());
-
-isa_ok(bless([], "Foo"), "Wibble");
-isa_ok(42,    "Wibble", "My Wibble");
-isa_ok(undef, "Wibble", "Another Wibble");
-isa_ok([],    "HASH");
-
-#line 68
-cmp_ok( 'foo', 'eq', 'bar', 'cmp_ok eq' );
-cmp_ok( 42.1,  '==', 23,  , '       ==' );
-cmp_ok( 42,    '!=', 42   , '       !=' );
-cmp_ok( 1,     '&&', 0    , '       &&' );
-cmp_ok( 42,    '==', "foo", '       == with strings' );
-cmp_ok( 42,    'eq', "foo", '       eq with numbers' );
-cmp_ok( undef, 'eq', 'foo', '       eq with undef' );
-
-# generate a $!, it changes its value by context.
--e "wibblehibble";
-my $Errno_Number = $!+0;
-my $Errno_String = $!.'';
-cmp_ok( $!,    'eq', '',    '       eq with stringified errno' );
-cmp_ok( $!,    '==', -1,    '       eq with numerified errno' );
-
-#line 84
-use_ok('Hooble::mooble::yooble');
-require_ok('ALL::YOUR::BASE::ARE::BELONG::TO::US::wibble');
-
-#line 88
-END {
-    My::Test::ok($$out eq <<OUT, 'failing output');
-1..$Total
-not ok 1 - failing
-not ok 2 - foo is bar?
-not ok 3 - undef is empty string?
-not ok 4 - undef is 0?
-not ok 5 - empty string is 0?
-not ok 6 - foo isnt foo?
-not ok 7 - foo isn't foo?
-not ok 8 - is foo like that
-not ok 9 - is foo unlike foo
-not ok 10 - regex with % in it
-not ok 11 - fail()
-not ok 12 - Mooble::Hooble::Yooble->can(...)
-not ok 13 - Mooble::Hooble::Yooble->can(...)
-not ok 14 - The object isa Wibble
-not ok 15 - My Wibble isa Wibble
-not ok 16 - Another Wibble isa Wibble
-not ok 17 - The object isa HASH
-not ok 18 - cmp_ok eq
-not ok 19 -        ==
-not ok 20 -        !=
-not ok 21 -        &&
-not ok 22 -        == with strings
-not ok 23 -        eq with numbers
-not ok 24 -        eq with undef
-not ok 25 -        eq with stringified errno
-not ok 26 -        eq with numerified errno
-not ok 27 - use Hooble::mooble::yooble;
-not ok 28 - require ALL::YOUR::BASE::ARE::BELONG::TO::US::wibble;
-OUT
-
-    my $err_re = <<ERR;
-#     Failed test ($0 at line 38)
+err( <<ERR );
 #     Failed test ($0 at line 40)
 #          got: 'foo'
 #     expected: 'bar'
@@ -141,6 +87,13 @@ OUT
 #     Failed test ($0 at line 43)
 #          got: ''
 #     expected: '0'
+ERR
+
+#line 45
+isnt("foo", "foo", 'foo isnt foo?' );
+isn't("foo", "foo",'foo isn\'t foo?' );
+isnt(undef, undef, 'undef isnt undef?');
+err( <<ERR );
 #     Failed test ($0 at line 45)
 #     'foo'
 #         ne
@@ -149,21 +102,54 @@ OUT
 #     'foo'
 #         ne
 #     'foo'
+#     Failed test ($0 at line 47)
+#     undef
+#         ne
+#     undef
+ERR
+
+#line 48
+like( "foo", '/that/',  'is foo like that' );
+unlike( "foo", '/foo/', 'is foo unlike foo' );
+err( <<ERR );
 #     Failed test ($0 at line 48)
 #                   'foo'
 #     doesn't match '/that/'
 #     Failed test ($0 at line 49)
 #                   'foo'
 #           matches '/foo/'
-#     Failed test ($0 at line 52)
+ERR
+
+# Nick Clark found this was a bug.  Fixed in 0.40.
+like( "bug", '/(%)/',   'regex with % in it' );
+err( <<ERR );
+#     Failed test ($0 at line 60)
 #                   'bug'
 #     doesn't match '/(%)/'
-#     Failed test ($0 at line 54)
+ERR
+
+fail('fail()');
+err( <<ERR );
+#     Failed test ($0 at line 67)
+ERR
+
+#line 52
+can_ok('Mooble::Hooble::Yooble', qw(this that));
+can_ok('Mooble::Hooble::Yooble', ());
+err( <<ERR );
 #     Failed test ($0 at line 52)
 #     Mooble::Hooble::Yooble->can('this') failed
 #     Mooble::Hooble::Yooble->can('that') failed
 #     Failed test ($0 at line 53)
 #     can_ok() called with no methods
+ERR
+
+#line 55
+isa_ok(bless([], "Foo"), "Wibble");
+isa_ok(42,    "Wibble", "My Wibble");
+isa_ok(undef, "Wibble", "Another Wibble");
+isa_ok([],    "HASH");
+err( <<ERR );
 #     Failed test ($0 at line 55)
 #     The object isn't a 'Wibble' it's a 'Foo'
 #     Failed test ($0 at line 56)
@@ -172,6 +158,17 @@ OUT
 #     Another Wibble isn't defined
 #     Failed test ($0 at line 58)
 #     The object isn't a 'HASH' it's a 'ARRAY'
+ERR
+
+#line 68
+cmp_ok( 'foo', 'eq', 'bar', 'cmp_ok eq' );
+cmp_ok( 42.1,  '==', 23,  , '       ==' );
+cmp_ok( 42,    '!=', 42   , '       !=' );
+cmp_ok( 1,     '&&', 0    , '       &&' );
+cmp_ok( 42,    '==', "foo", '       == with strings' );
+cmp_ok( 42,    'eq', "foo", '       eq with numbers' );
+cmp_ok( undef, 'eq', 'foo', '       eq with undef' );
+err( <<ERR );
 #     Failed test ($0 at line 68)
 #          got: 'foo'
 #     expected: 'bar'
@@ -195,6 +192,16 @@ OUT
 #     Failed test ($0 at line 74)
 #          got: undef
 #     expected: 'foo'
+ERR
+
+# generate a $!, it changes its value by context.
+-e "wibblehibble";
+my $Errno_Number = $!+0;
+my $Errno_String = $!.'';
+#line 80
+cmp_ok( $!,    'eq', '',    '       eq with stringified errno' );
+cmp_ok( $!,    '==', -1,    '       eq with numerified errno' );
+err( <<ERR );
 #     Failed test ($0 at line 80)
 #          got: '$Errno_String'
 #     expected: ''
@@ -203,18 +210,58 @@ OUT
 #     expected: -1
 ERR
 
+#line 84
+use_ok('Hooble::mooble::yooble');
+require_ok('ALL::YOUR::BASE::ARE::BELONG::TO::US::wibble');
+
+#line 88
+END {
+    My::Test::ok($$out eq <<OUT, 'failing output');
+1..$Total
+not ok - failing
+not ok - foo is bar?
+not ok - undef is empty string?
+not ok - undef is 0?
+not ok - empty string is 0?
+not ok - foo isnt foo?
+not ok - foo isn't foo?
+not ok - undef isnt undef?
+not ok - is foo like that
+not ok - is foo unlike foo
+not ok - regex with % in it
+not ok - fail()
+not ok - Mooble::Hooble::Yooble->can(...)
+not ok - Mooble::Hooble::Yooble->can(...)
+not ok - The object isa Wibble
+not ok - My Wibble isa Wibble
+not ok - Another Wibble isa Wibble
+not ok - The object isa HASH
+not ok - cmp_ok eq
+not ok -        ==
+not ok -        !=
+not ok -        &&
+not ok -        == with strings
+not ok -        eq with numbers
+not ok -        eq with undef
+not ok -        eq with stringified errno
+not ok -        eq with numerified errno
+not ok - use Hooble::mooble::yooble;
+not ok - require ALL::YOUR::BASE::ARE::BELONG::TO::US::wibble;
+OUT
+
    my $filename = quotemeta $0;
    my $more_err_re = <<ERR;
 #     Failed test \\($filename at line 84\\)
 #     Tried to use 'Hooble::mooble::yooble'.
 #     Error:  Can't locate Hooble.* in \\\@INC .*
+# BEGIN failed--compilation aborted at $filename line 84.
 #     Failed test \\($filename at line 85\\)
 #     Tried to require 'ALL::YOUR::BASE::ARE::BELONG::TO::US::wibble'.
 #     Error:  Can't locate ALL.* in \\\@INC .*
 # Looks like you failed $Total tests of $Total.
 ERR
 
-    unless( My::Test::ok($$err =~ /^\Q$err_re\E$more_err_re$/, 
+    unless( My::Test::ok($$err =~ /^$more_err_re$/, 
                          'failing errors') ) {
         print $$err;
     }
index a041ab0..30a107b 100644 (file)
@@ -14,6 +14,7 @@ use strict;
 
 require Test::Simple::Catch;
 my($out, $err) = Test::Simple::Catch::caught();
+local $ENV{HARNESS_ACTIVE} = 0;
 
 
 # Can't use Test.pm, that's a 5.005 thing.
diff --git a/lib/Test/Simple/t/fail_one.t b/lib/Test/Simple/t/fail_one.t
new file mode 100644 (file)
index 0000000..d9ce4b8
--- /dev/null
@@ -0,0 +1,62 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+    if( $ENV{PERL_CORE} ) {
+        chdir 't';
+        @INC = ('../lib', 'lib');
+    }
+    else {
+        unshift @INC, 't/lib';
+    }
+}
+
+use strict;
+
+require Test::Simple::Catch;
+my($out, $err) = Test::Simple::Catch::caught();
+local $ENV{HARNESS_ACTIVE} = 0;
+
+
+# Can't use Test.pm, that's a 5.005 thing.
+package My::Test;
+
+print "1..2\n";
+
+my $test_num = 1;
+# Utility testing functions.
+sub ok ($;$) {
+    my($test, $name) = @_;
+    my $ok = '';
+    $ok .= "not " unless $test;
+    $ok .= "ok $test_num";
+    $ok .= " - $name" if defined $name;
+    $ok .= "\n";
+    print $ok;
+    $test_num++;
+
+    return $test ? 1 : 0;
+}
+
+
+package main;
+
+require Test::Simple;
+Test::Simple->import(tests => 1);
+
+#line 45
+ok(0);
+
+END {
+    My::Test::ok($$out eq <<OUT);
+1..1
+not ok 1
+OUT
+
+    My::Test::ok($$err eq <<"ERR") || print $$err;
+#     Failed test ($0 at line 45)
+# Looks like you failed 1 test of 1.
+ERR
+
+    # Prevent Test::Simple from existing with non-zero
+    exit 0;
+}
diff --git a/lib/Test/Simple/t/harness_active.t b/lib/Test/Simple/t/harness_active.t
new file mode 100644 (file)
index 0000000..be4bb85
--- /dev/null
@@ -0,0 +1,99 @@
+#!perl -w
+
+BEGIN {
+    if( $ENV{PERL_CORE} ) {
+        chdir 't';
+        @INC = ('../lib', 'lib');
+    }
+    else {
+        unshift @INC, 't/lib';
+    }
+}
+
+use strict;
+
+use Test::Simple::Catch;
+my($out, $err) = Test::Simple::Catch::caught();
+
+
+# Can't use Test.pm, that's a 5.005 thing.
+package My::Test;
+
+print "1..4\n";
+
+my $test_num = 1;
+# Utility testing functions.
+sub ok ($;$) {
+    my($test, $name) = @_;
+    my $ok = '';
+    $ok .= "not " unless $test;
+    $ok .= "ok $test_num";
+    $ok .= " - $name" if defined $name;
+    $ok .= "\n";
+    print $ok;
+    $test_num++;
+
+    return $test;
+}
+
+
+sub main::err ($) {
+    my($expect) = @_;
+    my $got = $err->read;
+
+    my $ok = ok( $got eq $expect );
+
+    unless( $ok ) {
+        print STDERR "got\n$got\n";
+        print STDERR "expected\n$expect\n";
+    }
+
+    return $ok;
+}
+
+
+package main;
+
+require Test::More;
+Test::More->import(tests => 4);
+Test::More->builder->no_ending(1);
+
+{
+    local $ENV{HARNESS_ACTIVE} = 0;
+
+#line 62
+    fail( "this fails" );
+    err( <<ERR );
+#     Failed test ($0 at line 62)
+ERR
+
+#line 72
+    is( 1, 0 );
+    err( <<ERR );
+#     Failed test ($0 at line 72)
+#          got: '1'
+#     expected: '0'
+ERR
+}
+
+{
+    local $ENV{HARNESS_ACTIVE} = 1;
+                   
+#line 71
+    fail( "this fails" );
+    err( <<ERR );
+
+#     Failed test ($0 at line 71)
+ERR
+
+
+#line 84
+    is( 1, 0 );
+    err( <<ERR );
+
+#     Failed test ($0 at line 84)
+#          got: '1'
+#     expected: '0'
+ERR
+
+}
index 2b9ac49..b988737 100644 (file)
@@ -19,8 +19,12 @@ BEGIN {
     require Test::Harness;
 }
 
-if( $Test::Harness::VERSION < 1.20 ) {
-    plan skip_all => 'Need Test::Harness 1.20 or up';
+# This feature requires a fairly new version of Test::Harness
+if( $Test::Harness::VERSION < 2.03 ) {
+    plan tests => 1;
+    diag "Need Test::Harness 2.03 or up.  You have $Test::Harness::VERSION.";
+    fail 'Need Test::Harness 2.03 or up';
+    exit;
 }
 
 use strict;
index 5291fb8..867b1c3 100644 (file)
@@ -17,11 +17,13 @@ require Test::Simple::Catch;
 my($out, $err) = Test::Simple::Catch::caught();
 Test::Builder->new->no_header(1);
 Test::Builder->new->no_ending(1);
+local $ENV{HARNESS_ACTIVE} = 0;
+
 
 # Can't use Test.pm, that's a 5.005 thing.
 package main;
 
-print "1..22\n";
+print "1..25\n";
 
 my $test_num = 1;
 # Utility testing functions.
@@ -48,8 +50,9 @@ sub is ($$;$) {
 
 sub like ($$;$) {
     my($this, $regex, $name) = @_;
-
-    my $test = $$this =~ /$regex/;
+    
+    $regex = qr/$regex/ unless ref $regex;
+    my $test = $$this =~ $regex;
 
     my $ok = '';
     $ok .= "not " unless $test;
@@ -140,7 +143,7 @@ is( $err, <<ERR,                            '    right diagnostic' );
 ERR
 
 #line 131
-is_deeply({ foo => undef }, {},    'hashes of undefs',    'hashes of undefs' );
+is_deeply({ foo => undef }, {},    'hashes of undefs' );
 is( $out, "not ok 7 - hashes of undefs\n",  'hashes of undefs' );
 is( $err, <<ERR,                            '    right diagnostic' );
 #     Failed test ($0 at line 131)
@@ -213,3 +216,21 @@ is( $err, <<ERR,                            '    right diagnostic' );
 #          \$got->{that}{foo} = Does not exist
 #     \$expected->{that}{foo} = '42'
 ERR
+
+
+#line 221
+my @tests = ([],
+             [qw(42)],
+             [qw(42 23), qw(42 23)]
+            );
+
+foreach my $test (@tests) {
+    my $num_args = @$test;
+
+    my $warning;
+    local $SIG{__WARN__} = sub { $warning .= join '', @_; };
+    is_deeply(@$test);
+
+    like \$warning, 
+         qr/^is_deeply\(\) takes two or three args, you gave $num_args\.\n/;
+}
index 7f45180..f8a4581 100644 (file)
@@ -33,6 +33,7 @@ require Test::Simple;
 
 require Test::Simple::Catch;
 my($out, $err) = Test::Simple::Catch::caught();
+local $ENV{HARNESS_ACTIVE} = 0;
 
 Test::Simple->import(tests => 5);
 
diff --git a/lib/Test/Simple/t/no_diag.t b/lib/Test/Simple/t/no_diag.t
new file mode 100644 (file)
index 0000000..21ecd03
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/perl -w
+
+use Test::More 'no_diag', tests => 1;
+
+pass('foo');
+diag('This should not be displayed');
index dd051c1..72d0460 100644 (file)
@@ -9,6 +9,8 @@ BEGIN {
         unshift @INC, 't/lib';
     }
 }
+chdir 't';
+
 
 # Can't use Test.pm, that's a 5.005 thing.
 print "1..4\n";
@@ -33,7 +35,9 @@ use Test::Builder;
 my $Test = Test::Builder->new();
 
 my $result;
-my $out = $Test->output('foo');
+my $tmpfile = 'foo.tmp';
+my $out = $Test->output($tmpfile);
+END { unlink($tmpfile) }
 
 ok( defined $out );
 
@@ -41,26 +45,25 @@ print $out "hi!\n";
 close *$out;
 
 undef $out;
-open(IN, 'foo') or die $!;
+open(IN, $tmpfile) or die $!;
 chomp(my $line = <IN>);
 close IN;
 
 ok($line eq 'hi!');
 
-open(FOO, ">>foo") or die $!;
+open(FOO, ">>$tmpfile") or die $!;
 $out = $Test->output(\*FOO);
 $old = select *$out;
 print "Hello!\n";
 close *$out;
 undef $out;
 select $old;
-open(IN, 'foo') or die $!;
+open(IN, $tmpfile) or die $!;
 my @lines = <IN>;
 close IN;
 
 ok($lines[1] =~ /Hello!/);
 
-unlink('foo');
 
 
 # Ensure stray newline in name escaping works.
diff --git a/lib/Test/Simple/t/overload.t b/lib/Test/Simple/t/overload.t
new file mode 100644 (file)
index 0000000..6b300ad
--- /dev/null
@@ -0,0 +1,53 @@
+#!perl -w
+
+BEGIN {
+    if( $ENV{PERL_CORE} ) {
+        chdir 't';
+        @INC = ('../lib', 'lib');
+    }
+    else {
+        unshift @INC, 't/lib';
+    }
+}
+chdir 't';
+
+BEGIN {
+    # There was a bug with overloaded objects and threads.
+    # See rt.cpan.org 4218
+    eval { require threads; 'threads'->import; 1; };
+}
+
+use Test::More;
+
+BEGIN {
+    if( !eval "require overload" ) {
+        plan skip_all => "needs overload.pm";
+    }
+    else {
+        plan tests => 3;
+    }
+}
+
+
+package Overloaded;
+
+use overload
+  q{""} => sub { $_[0]->{string} };
+
+sub new {
+    my $class = shift;
+    bless { string => shift }, $class;
+}
+
+
+package main;
+
+my $warnings = '';
+local $SIG{__WARN__} = sub { $warnings = join '', @_ };
+my $obj = Overloaded->new('foo');
+ok( 1, $obj );
+
+my $undef = Overloaded->new(undef);
+pass( $undef );
+
+is( $warnings, '' );
index 1ab2a0e..e39cd40 100644 (file)
@@ -11,20 +11,6 @@ BEGIN {
 # Can't use Test.pm, that's a 5.005 thing.
 package My::Test;
 
-BEGIN {
-    if( !$ENV{HARNESS_ACTIVE} && $ENV{PERL_CORE} ) {
-        print "1..0 # Skipped: Won't work with t/TEST\n";
-        exit 0;
-    }
-
-    # This feature requires a fairly new version of Test::Harness
-    require Test::Harness;
-    if( $Test::Harness::VERSION < 1.20 ) {
-        print "1..0 # Skipped: Need Test::Harness 1.20 or up\n";
-        exit(0);
-    }
-}
-
 print "1..2\n";
 
 my $test_num = 1;
index b39b101..6ae06bf 100644 (file)
@@ -17,12 +17,15 @@ BEGIN {
     require Test::Harness;
 }
 
-if( $Test::Harness::VERSION < 1.20 ) {
-    plan skip_all => 'Need Test::Harness 1.20 or up';
-}
-else {
-    plan 'no_plan';
+# This feature requires a fairly new version of Test::Harness
+if( $Test::Harness::VERSION < 2.03 ) {
+    plan tests => 1;
+    diag "Need Test::Harness 2.03 or up.  You have $Test::Harness::VERSION.";
+    fail 'Need Test::Harness 2.03 or up';
+    exit;
 }
 
+plan 'no_plan';
+
 pass('Just testing');
 ok(1, 'Testing again');
diff --git a/lib/Test/Simple/t/reset.t b/lib/Test/Simple/t/reset.t
new file mode 100644 (file)
index 0000000..bc1546b
--- /dev/null
@@ -0,0 +1,84 @@
+#!/usr/bin/perl -w
+
+# Test Test::Builder->reset;
+
+BEGIN {
+    if( $ENV{PERL_CORE} ) {
+        chdir 't';
+        @INC = ('../lib', 'lib');
+    }
+    else {
+        unshift @INC, 't/lib';
+    }
+}
+chdir 't';
+
+
+use Test::Builder;
+my $tb = Test::Builder->new;
+$tb->plan(tests => 14);
+$tb->level(0);
+
+# Alter the state of Test::Builder as much as possible.
+$tb->ok(1, "Running a test to alter TB's state");
+
+my $tmpfile = 'foo.tmp';
+
+$tb->output($tmpfile);
+$tb->failure_output($tmpfile);
+$tb->todo_output($tmpfile);
+END { unlink $tmpfile }
+
+# This won't print since we just sent output off to oblivion.
+$tb->ok(0, "And a failure for fun");
+
+$Test::Builder::Level = 3;
+
+$tb->exported_to('Foofer');
+
+$tb->use_numbers(0);
+$tb->no_header(1);
+$tb->no_ending(1);
+
+
+# Now reset it.
+$tb->reset;
+
+my $test_num = 2;   # since we already printed 1
+# Utility testing functions.
+sub ok ($;$) {
+    my($test, $name) = @_;
+    my $ok = '';
+    $ok .= "not " unless $test;
+    $ok .= "ok $test_num";
+    $ok .= " - $name" if defined $name;
+    $ok .= "\n";
+    print $ok;
+    $test_num++;
+
+    return $test;
+}
+
+
+ok( !defined $tb->exported_to,          'exported_to' );
+ok( $tb->expected_tests == 0,           'expected_tests' );
+ok( $tb->level          == 1,           'level' );
+ok( $tb->use_numbers    == 1,           'use_numbers' );
+ok( $tb->no_header      == 0,           'no_header' );
+ok( $tb->no_ending      == 0,           'no_ending' );
+ok( fileno $tb->output         == fileno *Test::Builder::TESTOUT,    
+                                        'output' );
+ok( fileno $tb->failure_output == fileno *Test::Builder::TESTERR,    
+                                        'failure_output' );
+ok( fileno $tb->todo_output    == fileno *Test::Builder::TESTOUT,
+                                        'todo_output' );
+ok( $tb->current_test   == 0,           'current_test' );
+ok( $tb->summary        == 0,           'summary' );
+ok( $tb->details        == 0,           'details' );
+
+$tb->no_ending(1);
+$tb->no_header(1);
+$tb->plan(tests => 14);
+$tb->current_test(13);
+$tb->level(0);
+$tb->ok(1, 'final test to make sure output was reset');
diff --git a/lib/Test/Simple/t/thread_taint.t b/lib/Test/Simple/t/thread_taint.t
new file mode 100644 (file)
index 0000000..d547e6d
--- /dev/null
@@ -0,0 +1,5 @@
+#!/usr/bin/perl -w
+
+use Test::More tests => 1;
+
+ok( !$INC{'threads.pm'}, 'Loading Test::More does not load threads.pm' );
\ No newline at end of file
index 5670bda..35696e2 100644 (file)
@@ -8,13 +8,16 @@ BEGIN {
 }
 
 use Config;
-unless ($Config{'useithreads'} and eval { require threads; 1 }) {
-    print "1..0 # Skip: no threads\n";
-    exit 0;
+BEGIN {
+    unless ( $] >= 5.008 && $Config{'useithreads'} && 
+             eval { require threads; 'threads'->import; 1; }) 
+    {
+        print "1..0 # Skip: no threads\n";
+        exit 0;
+    }
 }
 
 use strict;
-require threads;
 use Test::Builder;
 
 my $Test = Test::Builder->new;
index 31ceb5f..9a16626 100644 (file)
@@ -7,18 +7,20 @@ BEGIN {
     }
 }
 
-BEGIN {
-    require Test::Harness;
-    use Test::More;
-
-    if( $Test::Harness::VERSION < 1.23 ) {
-        plan skip_all => 'Need Test::Harness 1.23 or up';
-    }
-    else {
-        plan tests => 15;
-    }
+require Test::Harness;
+use Test::More;
+
+# This feature requires a fairly new version of Test::Harness
+(my $th_version = $Test::Harness::VERSION) =~ s/_//; # for X.Y_Z alpha versions
+if( $th_version < 2.03 ) {
+    plan tests => 1;
+    fail "Need Test::Harness 2.03 or up.  You have $th_version.";
+    exit;
 }
 
+plan tests => 15;
+
+
 $Why = 'Just testing the todo interface.';
 
 TODO: {
index e944628..d0c145f 100644 (file)
@@ -3,11 +3,14 @@
 BEGIN {
     if( $ENV{PERL_CORE} ) {
         chdir 't';
-        @INC = '../lib';
+        @INC = ('../lib', 'lib');
+    }
+    else {
+        unshift @INC, 't/lib';
     }
 }
 
-use Test::More tests => 10;
+use Test::More tests => 13;
 
 # Using Symbol because it's core and exports lots of stuff.
 {
@@ -36,3 +39,22 @@ use Test::More tests => 10;
     ::ok( defined &foo, 'constant' );
     ::is( $warn, undef, 'no warning');
 }
+
+{
+    package Foo::five;
+    ::use_ok("Symbol", 1.02);
+}
+
+{
+    package Foo::six;
+    ::use_ok("NoExporter", 1.02);
+}
+
+{
+    package Foo::seven;
+    local $SIG{__WARN__} = sub {
+        # Old perls will warn on X.YY_ZZ style versions.  Not our problem
+        warn @_ unless $_[0] =~ /^Argument "\d+\.\d+_\d+" isn't numeric/;
+    };
+    ::use_ok("Test::More", 0.47);
+}
index a57d047..7a6c084 100644 (file)
@@ -502,7 +502,7 @@ C<local $TODO> and turn it into a real test.
 =head2 Testing with taint mode.
 
 Taint mode is a funny thing.  It's the globalest of all global
-features.  Once you turn it on it effects I<all> code in your program
+features.  Once you turn it on, it affects I<all> code in your program
 and I<all> modules used (and all the modules they use).  If a single
 piece of code isn't taint clean, the whole thing explodes.  With that
 in mind, it's very important to ensure your module works under taint
@@ -514,8 +514,6 @@ in C<#!> and use them to run your tests.
 
     #!/usr/bin/perl -Tw
 
-    use Test::More 'no_plan';
-
     ...test normally here...
 
 So when you say C<make test> it will be run with taint mode and
diff --git a/t/lib/NoExporter.pm b/t/lib/NoExporter.pm
new file mode 100644 (file)
index 0000000..1ab5b8f
--- /dev/null
@@ -0,0 +1,10 @@
+package NoExporter;
+
+$VERSION = 1.02;
+sub import { 
+    shift;
+    die "NoExporter exports nothing.  You asked for: @_" if @_;
+}
+
+1;
+
index e1ccd7c..441a125 100644 (file)
@@ -2,9 +2,10 @@
 package Test::Simple::Catch;
 
 use Symbol;
+use TieOut;
 my($out_fh, $err_fh) = (gensym, gensym);
-my $out = tie *$out_fh, __PACKAGE__;
-my $err = tie *$err_fh, __PACKAGE__;
+my $out = tie *$out_fh, 'TieOut';
+my $err = tie *$err_fh, 'TieOut';
 
 use Test::Builder;
 my $t = Test::Builder->new;
@@ -14,19 +15,4 @@ $t->todo_output($err_fh);
 
 sub caught { return($out, $err) }
 
-sub PRINT  {
-    my $self = shift;
-    $$self .= join '', @_;
-}
-
-sub TIEHANDLE {
-    my $class = shift;
-    my $self = '';
-    return bless \$self, $class;
-}
-sub READ {}
-sub READLINE {}
-sub GETC {}
-sub FILENO {}
-
 1;
index 072e8fd..e41b602 100644 (file)
@@ -1,23 +1,26 @@
 package TieOut;
 
 sub TIEHANDLE {
-       bless( \(my $scalar), $_[0]);
+    my $scalar = '';
+    bless( \$scalar, $_[0]);
 }
 
 sub PRINT {
-       my $self = shift;
-       $$self .= join('', @_);
+    my $self = shift;
+    $$self .= join('', @_);
 }
 
 sub PRINTF {
-       my $self = shift;
+    my $self = shift;
     my $fmt  = shift;
-       $$self .= sprintf $fmt, @_;
+    $$self .= sprintf $fmt, @_;
 }
 
 sub read {
-       my $self = shift;
-       return substr($$self, 0, length($$self), '');
+    my $self = shift;
+    my $data = $$self;
+    $$self = '';
+    return $data;
 }
 
 1;