summaryrefslogtreecommitdiff
path: root/lib/Test
diff options
context:
space:
mode:
authorRafael Garcia-Suarez <rgarciasuarez@gmail.com>2004-11-29 12:30:31 +0000
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2004-11-29 12:30:31 +0000
commit7483b81ca7308e71194e93199090ae9980c08e01 (patch)
treeaf36480c832b89b362a74c59ce1345947f68d17d /lib/Test
parent1a9ca8275f4f07a40855b3aff68b175f39e6965e (diff)
downloadperl-7483b81ca7308e71194e93199090ae9980c08e01.tar.gz
Upgrade to Test::Simple 0.53
p4raw-id: //depot/perl@23566
Diffstat (limited to 'lib/Test')
-rw-r--r--lib/Test/Builder.pm128
-rw-r--r--lib/Test/More.pm202
-rw-r--r--lib/Test/Simple.pm5
-rw-r--r--lib/Test/Simple/Changes48
-rw-r--r--lib/Test/Simple/README9
-rw-r--r--lib/Test/Simple/TODO21
-rw-r--r--lib/Test/Simple/t/00signature.t41
-rw-r--r--lib/Test/Simple/t/More.t11
-rw-r--r--lib/Test/Simple/t/circular_data.t33
-rw-r--r--lib/Test/Simple/t/diag.t45
-rw-r--r--lib/Test/Simple/t/fail_one.t2
-rw-r--r--lib/Test/Simple/t/is_deeply.t49
-rw-r--r--lib/Test/Simple/t/overload.t33
-rw-r--r--lib/Test/Simple/t/overload_threads.t69
-rw-r--r--lib/Test/Simple/t/plan_bad.t64
-rw-r--r--lib/Test/Simple/t/plan_shouldnt_import.t16
-rw-r--r--lib/Test/Simple/t/require_ok.t28
-rw-r--r--lib/Test/Simple/t/sort_bug.t64
-rw-r--r--lib/Test/Simple/t/todo.t7
19 files changed, 697 insertions, 178 deletions
diff --git a/lib/Test/Builder.pm b/lib/Test/Builder.pm
index cb202f91b3..54bd199df8 100644
--- a/lib/Test/Builder.pm
+++ b/lib/Test/Builder.pm
@@ -8,9 +8,8 @@ $^C ||= 0;
use strict;
use vars qw($VERSION);
-$VERSION = '0.19_01';
-
-my $IsVMS = $^O eq 'VMS';
+$VERSION = '0.21';
+$VERSION = eval $VERSION; # make the alpha version come out as a number
# Make Test::Builder thread-safe for ithreads.
BEGIN {
@@ -18,7 +17,44 @@ BEGIN {
# Load threads::shared when threads are turned on
if( $] >= 5.008 && $Config{useithreads} && $INC{'threads.pm'}) {
require threads::shared;
- threads::shared->import;
+
+ # Hack around YET ANOTHER threads::shared bug. It would
+ # occassionally forget the contents of the variable when sharing it.
+ # So we first copy the data, then share, then put our copy back.
+ *share = sub (\[$@%]) {
+ my $type = ref $_[0];
+ my $data;
+
+ if( $type eq 'HASH' ) {
+ %$data = %{$_[0]};
+ }
+ elsif( $type eq 'ARRAY' ) {
+ @$data = @{$_[0]};
+ }
+ elsif( $type eq 'SCALAR' ) {
+ $$data = ${$_[0]};
+ }
+ else {
+ die "Unknown type: ".$type;
+ }
+
+ $_[0] = &threads::shared::share($_[0]);
+
+ if( $type eq 'HASH' ) {
+ %{$_[0]} = %$data;
+ }
+ elsif( $type eq 'ARRAY' ) {
+ @{$_[0]} = @$data;
+ }
+ elsif( $type eq 'SCALAR' ) {
+ ${$_[0]} = $$data;
+ }
+ else {
+ die "Unknown type: ".$type;
+ }
+
+ return $_[0];
+ };
}
# 5.8.0's threads::shared is busted when threads are off.
# We emulate it here.
@@ -237,9 +273,13 @@ the appropriate headers.
=cut
sub expected_tests {
- my($self, $max) = @_;
+ my $self = shift;
+ my($max) = @_;
+
+ if( @_ ) {
+ die "Number of tests must be a postive integer. You gave it '$max'.\n"
+ unless $max =~ /^\+?\d+$/ and $max > 0;
- if( defined $max ) {
$Expected_Tests = $max;
$Have_Plan = 1;
@@ -335,15 +375,7 @@ sub ok {
$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->_unoverload(\$name);
$self->diag(<<ERR) if defined $name and $name =~ /^[\d\s]+$/;
You named your test '$name'. You shouldn't use numbers for your test names.
@@ -353,6 +385,7 @@ ERR
my($pack, $file, $line) = $self->caller;
my $todo = $self->todo($pack);
+ $self->_unoverload(\$todo);
my $out;
my $result = &share({});
@@ -371,16 +404,15 @@ ERR
if( defined $name ) {
$name =~ s|#|\\#|g; # # in a name can confuse Test::Harness.
$out .= " - $name";
- $result->{name} = "$name";
+ $result->{name} = $name;
}
else {
$result->{name} = '';
}
if( $todo ) {
- my $what_todo = $todo;
- $out .= " # TODO $what_todo";
- $result->{reason} = "$what_todo";
+ $out .= " # TODO $todo";
+ $result->{reason} = $todo;
$result->{type} = 'todo';
}
else {
@@ -402,6 +434,26 @@ ERR
return $test ? 1 : 0;
}
+
+sub _unoverload {
+ my $self = shift;
+
+ local($@,$!);
+
+ eval { require overload } || return;
+
+ foreach my $thing (@_) {
+ eval {
+ if( defined $$thing ) {
+ if( my $string_meth = overload::Method($$thing, '""') ) {
+ $$thing = $$thing->$string_meth();
+ }
+ }
+ };
+ }
+}
+
+
=item B<is_eq>
$Test->is_eq($got, $expected, $name);
@@ -709,6 +761,7 @@ Skips the current test, reporting $why.
sub skip {
my($self, $why) = @_;
$why ||= '';
+ $self->_unoverload(\$why);
unless( $Have_Plan ) {
require Carp;
@@ -914,9 +967,11 @@ Test::Builder's default output settings will not be affected.
$Test->diag(@msgs);
-Prints out the given $message. Normally, it uses the failure_output()
-handle, but if this is for a TODO test, the todo_output() handle is
-used.
+Prints out the given @msgs. Like C<print>, arguments are simply
+appended together.
+
+Normally, it uses the failure_output() handle, but if this is for a
+TODO test, the todo_output() handle is used.
Output will be indented and marked with a # so as not to interfere
with test output. A newline will be put on the end if there isn't one
@@ -941,16 +996,18 @@ sub diag {
# Prevent printing headers when compiling (i.e. -c)
return if $^C;
+ # Smash args together like print does.
+ # Convert undef to 'undef' so its readable.
+ my $msg = join '', map { defined($_) ? $_ : 'undef' } @msgs;
+
# Escape each line with a #.
- foreach (@msgs) {
- $_ = 'undef' unless defined;
- s/^/# /gms;
- }
+ $msg =~ s/^/# /gm;
- push @msgs, "\n" unless $msgs[-1] =~ /\n\Z/;
+ # Stick a newline on the end if it needs it.
+ $msg .= "\n" unless $msg =~ /\n\Z/;
local $Level = $Level + 1;
- $self->_print_diag(@msgs);
+ $self->_print_diag($msg);
return 0;
}
@@ -974,18 +1031,19 @@ sub _print {
# tests are deparsed with B::Deparse
return if $^C;
+ my $msg = join '', @msgs;
+
local($\, $", $,) = (undef, ' ', '');
my $fh = $self->output;
# Escape each line after the first with a # so we don't
# confuse Test::Harness.
- foreach (@msgs) {
- s/\n(.)/\n# $1/sg;
- }
+ $msg =~ s/\n(.)/\n# $1/sg;
- push @msgs, "\n" unless $msgs[-1] =~ /\n\Z/;
+ # Stick a newline on the end if it needs it.
+ $msg .= "\n" unless $msg =~ /\n\Z/;
- print $fh @msgs;
+ print $fh $msg;
}
@@ -1486,8 +1544,8 @@ E<lt>schwern@pobox.comE<gt>
=head1 COPYRIGHT
-Copyright 2002 by chromatic E<lt>chromatic@wgz.orgE<gt>,
- Michael G Schwern E<lt>schwern@pobox.comE<gt>.
+Copyright 2002, 2004 by chromatic E<lt>chromatic@wgz.orgE<gt> and
+ 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.
diff --git a/lib/Test/More.pm b/lib/Test/More.pm
index 5ca95e67b3..8f029e6f1b 100644
--- a/lib/Test/More.pm
+++ b/lib/Test/More.pm
@@ -18,7 +18,9 @@ sub _carp {
require Exporter;
use vars qw($VERSION @ISA @EXPORT %EXPORT_TAGS $TODO);
-$VERSION = '0.50';
+$VERSION = '0.53';
+$VERSION = eval $VERSION; # make the alpha version come out as a number
+
@ISA = qw(Exporter);
@EXPORT = qw(ok use_ok require_ok
is isnt like unlike is_deeply
@@ -177,36 +179,51 @@ or for deciding between running the tests at all:
sub plan {
my(@plan) = @_;
- my $caller = caller;
-
- $Test->exported_to($caller);
-
- my @cleaned_plan;
- my @imports = ();
my $idx = 0;
+ my @cleaned_plan;
while( $idx <= $#plan ) {
- if( $plan[$idx] eq 'import' ) {
- @imports = @{$plan[$idx+1]};
- $idx += 2;
- }
- elsif( $plan[$idx] eq 'no_diag' ) {
+ my $item = $plan[$idx];
+
+ if( $item eq 'no_diag' ) {
$Show_Diag = 0;
- $idx++;
}
else {
- push @cleaned_plan, $plan[$idx];
- $idx++;
+ push @cleaned_plan, $item;
}
+
+ $idx++;
}
$Test->plan(@cleaned_plan);
-
- __PACKAGE__->_export_to_level(1, __PACKAGE__, @imports);
}
sub import {
my($class) = shift;
- goto &plan;
+
+ my $caller = caller;
+
+ $Test->exported_to($caller);
+
+ my $idx = 0;
+ my @plan;
+ my @imports;
+ while( $idx <= $#_ ) {
+ my $item = $_[$idx];
+
+ if( $item eq 'import' ) {
+ push @imports, @{$_[$idx+1]};
+ $idx++;
+ }
+ else {
+ push @plan, $item;
+ }
+
+ $idx++;
+ }
+
+ plan(@plan);
+
+ __PACKAGE__->_export_to_level(1, __PACKAGE__, @imports);
}
@@ -618,7 +635,10 @@ messages which are safer than just C<print STDERR>.
diag(@diagnostic_message);
Prints a diagnostic message which is guaranteed not to interfere with
-test output. Handy for this sort of thing:
+test output. Like C<print> @diagnostic_message is simply concatinated
+together.
+
+Handy for this sort of thing:
ok( grep(/foo/, @users), "There's a foo user" ) or
diag("Since there's no foo, check that /etc/bar is set up right");
@@ -742,8 +762,9 @@ DIAGNOSTIC
=item B<require_ok>
require_ok($module);
+ require_ok($file);
-Like use_ok(), except it requires the $module.
+Like use_ok(), except it requires the $module or $file.
=cut
@@ -752,6 +773,10 @@ sub require_ok ($) {
my $pack = caller;
+ # Try to deterine if we've been given a module name or file.
+ # Module names must be barewords, files not.
+ $module = qq['$module'] unless _is_module_name($module);
+
local($!, $@); # eval sometimes interferes with $!
eval <<REQUIRE;
package $pack;
@@ -772,6 +797,17 @@ DIAGNOSTIC
return $ok;
}
+
+sub _is_module_name {
+ my $module = shift;
+
+ # Module names start with a letter.
+ # End with an alphanumeric.
+ # The rest is an alphanumeric or ::
+ $module =~ s/\b::\b//g;
+ $module =~ /^[a-zA-Z]\w+$/;
+}
+
=back
=head2 Conditional tests
@@ -950,8 +986,7 @@ Not everything is a simple eq check or regex. There are times you
need to see if two arrays are equivalent, for instance. For these
instances, Test::More provides a handful of useful functions.
-B<NOTE> These are NOT well-tested on circular references. Nor am I
-quite sure what will happen with filehandles.
+B<NOTE> I'm not quite sure what will happen with filehandles.
=over 4
@@ -969,7 +1004,7 @@ along these lines.
=cut
-use vars qw(@Data_Stack);
+use vars qw(@Data_Stack %Refs_Seen);
my $DNE = bless [], 'Does::Not::Exist';
sub is_deeply {
unless( @_ == 2 or @_ == 3 ) {
@@ -986,11 +1021,15 @@ WARNING
my($this, $that, $name) = @_;
my $ok;
- if( !ref $this || !ref $that ) {
+ if( !ref $this xor !ref $that ) { # one's a reference, one isn't
+ $ok = 0;
+ }
+ if( !ref $this and !ref $that ) {
$ok = $Test->is_eq($this, $that, $name);
}
else {
local @Data_Stack = ();
+ local %Refs_Seen = ();
if( _deep_check($this, $that) ) {
$ok = $Test->ok(1, $name);
}
@@ -1055,10 +1094,29 @@ multi-level structures are handled correctly.
=cut
#'#
-sub eq_array {
+sub eq_array {
+ local @Data_Stack;
+ local %Refs_Seen;
+ _eq_array(@_);
+}
+
+sub _eq_array {
my($a1, $a2) = @_;
+
+ if( grep !UNIVERSAL::isa($_, 'ARRAY'), $a1, $a2 ) {
+ warn "eq_array passed a non-array ref";
+ return 0;
+ }
+
return 1 if $a1 eq $a2;
+ if($Refs_Seen{$a1}) {
+ return $Refs_Seen{$a1} eq $a2;
+ }
+ else {
+ $Refs_Seen{$a1} = "$a2";
+ }
+
my $ok = 1;
my $max = $#$a1 > $#$a2 ? $#$a1 : $#$a2;
for (0..$max) {
@@ -1071,6 +1129,7 @@ sub eq_array {
last unless $ok;
}
+
return $ok;
}
@@ -1078,24 +1137,34 @@ sub _deep_check {
my($e1, $e2) = @_;
my $ok = 0;
- my $eq;
{
# Quiet uninitialized value warnings when comparing undefs.
local $^W = 0;
- if( $e1 eq $e2 ) {
+ $Test->_unoverload(\$e1, \$e2);
+
+ # Either they're both references or both not.
+ my $same_ref = !(!ref $e1 xor !ref $e2);
+
+ if( defined $e1 xor defined $e2 ) {
+ $ok = 0;
+ }
+ elsif ( $e1 == $DNE xor $e2 == $DNE ) {
+ $ok = 0;
+ }
+ elsif ( $same_ref and ($e1 eq $e2) ) {
$ok = 1;
}
else {
if( UNIVERSAL::isa($e1, 'ARRAY') and
UNIVERSAL::isa($e2, 'ARRAY') )
{
- $ok = eq_array($e1, $e2);
+ $ok = _eq_array($e1, $e2);
}
elsif( UNIVERSAL::isa($e1, 'HASH') and
UNIVERSAL::isa($e2, 'HASH') )
{
- $ok = eq_hash($e1, $e2);
+ $ok = _eq_hash($e1, $e2);
}
elsif( UNIVERSAL::isa($e1, 'REF') and
UNIVERSAL::isa($e2, 'REF') )
@@ -1109,6 +1178,7 @@ sub _deep_check {
{
push @Data_Stack, { type => 'REF', vals => [$e1, $e2] };
$ok = _deep_check($$e1, $$e2);
+ pop @Data_Stack if $ok;
}
else {
push @Data_Stack, { vals => [$e1, $e2] };
@@ -1131,9 +1201,28 @@ is a deep check.
=cut
sub eq_hash {
+ local @Data_Stack;
+ local %Refs_Seen;
+ return _eq_hash(@_);
+}
+
+sub _eq_hash {
my($a1, $a2) = @_;
+
+ if( grep !UNIVERSAL::isa($_, 'HASH'), $a1, $a2 ) {
+ warn "eq_hash passed a non-hash ref";
+ return 0;
+ }
+
return 1 if $a1 eq $a2;
+ if( $Refs_Seen{$a1} ) {
+ return $Refs_Seen{$a1} eq $a2;
+ }
+ else {
+ $Refs_Seen{$a1} = "$a2";
+ }
+
my $ok = 1;
my $bigger = keys %$a1 > keys %$a2 ? $a1 : $a2;
foreach my $k (keys %$bigger) {
@@ -1163,17 +1252,22 @@ While the order of elements does not matter, duplicate elements do.
=cut
-# 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 ? -1 : ref $b ? 1 : $a cmp $b }
-
sub eq_set {
my($a1, $a2) = @_;
return 0 unless @$a1 == @$a2;
# There's faster ways to do this, but this is easiest.
- return eq_array( [sort _bogus_sort @$a1], [sort _bogus_sort @$a2] );
+ local $^W = 0;
+
+ # 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.
+ # Have to inline the sort routine due to a threading/sort bug.
+ # See [rt.cpan.org 6782]
+ return eq_array(
+ [sort { ref $a ? -1 : ref $b ? 1 : $a cmp $b } @$a1],
+ [sort { ref $a ? -1 : ref $b ? 1 : $a cmp $b } @$a2]
+ );
}
=back
@@ -1227,13 +1321,27 @@ So the exit codes are...
If you fail more than 254 tests, it will be reported as 254.
-=head1 NOTES
+=head1 CAVEATS and NOTES
-Test::More is B<explicitly> tested all the way back to perl 5.004.
+=over 4
-=head1 BUGS and CAVEATS
+=item Backwards compatibility
+
+Test::More works with Perls as old as 5.004_05.
+
+
+=item Overloaded objects
+
+String overloaded objects are compared B<as strings>. This prevents
+Test::More from piercing an object's interface allowing better blackbox
+testing. So if a function starts returning overloaded objects instead of
+bare strings your tests won't notice the difference. This is good.
+
+However, it does mean that functions like is_deeply() cannot be used to
+test the internals of string overloaded objects. In this case I would
+suggest Test::Deep which contains more flexible testing functions for
+complex data structures.
-=over 4
=item Threads
@@ -1248,12 +1356,6 @@ 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
-instead.
-
-=item The eq_* family has some caveats.
=item Test::Harness upgrade
@@ -1313,12 +1415,18 @@ L<Bundle::Test> installs a whole bunch of useful test modules.
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, blackstar.co.uk, chromatic and the perl-qa gang.
+Slaymaker, Tony Bowden, blackstar.co.uk, chromatic, Fergal Daly and
+the perl-qa gang.
+
+
+=head1 BUGS
+
+See F<http://rt.cpan.org> to report and view bugs.
=head1 COPYRIGHT
-Copyright 2001, 2002 by Michael G Schwern E<lt>schwern@pobox.comE<gt>.
+Copyright 2001, 2002, 2004 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.
diff --git a/lib/Test/Simple.pm b/lib/Test/Simple.pm
index 45b2bb5742..ea3f11902a 100644
--- a/lib/Test/Simple.pm
+++ b/lib/Test/Simple.pm
@@ -4,7 +4,8 @@ use 5.004;
use strict 'vars';
use vars qw($VERSION);
-$VERSION = '0.50';
+$VERSION = '0.53';
+$VERSION = eval $VERSION; # make the alpha version come out as a number
use Test::Builder;
@@ -223,7 +224,7 @@ E<lt>schwern@pobox.comE<gt>, wardrobe by Calvin Klein.
=head1 COPYRIGHT
-Copyright 2001 by Michael G Schwern E<lt>schwern@pobox.comE<gt>.
+Copyright 2001, 2002, 2004 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.
diff --git a/lib/Test/Simple/Changes b/lib/Test/Simple/Changes
index 89c617a51b..083d97f577 100644
--- a/lib/Test/Simple/Changes
+++ b/lib/Test/Simple/Changes
@@ -1,8 +1,50 @@
+0.53 Mon Nov 29 04:43:24 EST 2004
+ - Apparently its possible to have Module::Signature installed without
+ it being functional. Fixed the signature test to account for this.
+ (not a real bug)
+
+0.52 Sun Nov 28 21:41:03 EST 2004
+ - plan() now better checks that the given plan is valid.
+ [rt.cpan.org 2597]
+
+0.51_02 Sat Nov 27 01:25:25 EST 2004
+ * is_deeply() and all the eq_* functions now handle circular data
+ structures. [rt.cpan.org 7289]
+ * require_ok() now handles filepaths in addition to modules.
+ - Clarifying Test::More's position on overloaded objects
+ - Fixed a bug introduced in 0.51_01 causing is_deeply() to pierce
+ overloaded objects.
+ - Mentioning rt.cpan.org for reporting bugs.
+
+0.51_01 Fri Nov 26 02:59:30 EST 2004
+ - plan() was accidentally exporting functions [rt.cpan.org 8385]
+ * diag @msgs would insert # between arguments. [rt.cpan.org 8392]
+ * eq_set() could cause problems under threads due to a weird sort bug
+ [rt.cpan.org 6782]
+ * undef no longer equals '' in is_deeply() [rt.cpan.org 6837]
+ * is_deeply() would sometimes compare references as strings.
+ [rt.cpan.org 7031]
+ - eq_array() and eq_hash() could hold onto references if they failed
+ keeping them in memory and preventing DESTROY. [rt.cpan.org 7032]
+ * is_deeply() could confuse [] with a non-existing value
+ [rt.cpan.org 7030]
+ - is_deeply() diagnostics a little off when scalar refs were inside
+ an array or hash ref [rt.cpan.org 7033]
+ - Thanks to Fergal Daly for ferretting out all these long standing
+ is_deeply and eq_* bugs.
+
+0.51 Tue Nov 23 04:51:12 EST 2004
+ - Fixed bug in fail_one.t on Windows (not a real bug).
+ - TODO reasons as overloaded objects now won't blow up under threads.
+ [Autrijus Tang]
+ - skip() in 0.50 tickled yet another bug in threads::shared. Hacked
+ around it.
+
0.50 Sat Nov 20 00:28:44 EST 2004
- * Fixed bug in fail-more test on Windows (not a real bug).
+ - 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.
+ - Change from CVS to SVK. Hopefully this is the last time I move
+ version control systems.
- Again removing File::Spec dependency (came back in 0.48_02)
- Change from Aegis back to CVS
diff --git a/lib/Test/Simple/README b/lib/Test/Simple/README
index e02329e701..2a6c50d4f8 100644
--- a/lib/Test/Simple/README
+++ b/lib/Test/Simple/README
@@ -13,12 +13,3 @@ perl Makefile.PL
make
make test
make install
-
-* Copyright
-
-Copyright 2001 by Michael G Schwern <schwern@pobox.com>.
-
-All rights reserved. You can redistribute and/or modify
-this bundle under the same terms as Perl itself.
-
-See <http://www.perl.com/perl/misc/Artistic.html>.
diff --git a/lib/Test/Simple/TODO b/lib/Test/Simple/TODO
index 71f4285558..6bf1286279 100644
--- a/lib/Test/Simple/TODO
+++ b/lib/Test/Simple/TODO
@@ -1,35 +1,18 @@
- 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.
+See https://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-Simple plus here's
+a few more I haven't put in RT yet.
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().
diff --git a/lib/Test/Simple/t/00signature.t b/lib/Test/Simple/t/00signature.t
index b36f68e2e2..3032dc78ee 100644
--- a/lib/Test/Simple/t/00signature.t
+++ b/lib/Test/Simple/t/00signature.t
@@ -1,22 +1,31 @@
#!/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;
+use Test::More;
-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" );
- }
+if (!eval { require Module::Signature; 1 }) {
+ plan skip_all =>
+ "Next time around, consider installing Module::Signature, ".
+ "so you can verify the integrity of this distribution.";
+}
+elsif ( !-e 'SIGNATURE' ) {
+ plan skip_all => "SIGNATURE not found";
+}
+elsif ( -s 'SIGNATURE' == 0 ) {
+ plan skip_all => "SIGNATURE file empty";
+}
+elsif (!eval { require Socket; Socket::inet_aton('pgp.mit.edu') }) {
+ plan skip_all => "Cannot connect to the keyserver to check module ".
+ "signature";
}
+else {
+ plan tests => 1;
+}
+
+my $ret = Module::Signature::verify();
+SKIP: {
+ skip "Module::Signature cannot verify", 1
+ if $ret eq Module::Signature::CANNOT_VERIFY();
-__END__
+ cmp_ok $ret, '==', Module::Signature::SIGNATURE_OK(), "Valid signature";
+}
diff --git a/lib/Test/Simple/t/More.t b/lib/Test/Simple/t/More.t
index 71f3fd0dfe..24141d92f8 100644
--- a/lib/Test/Simple/t/More.t
+++ b/lib/Test/Simple/t/More.t
@@ -7,7 +7,7 @@ BEGIN {
}
}
-use Test::More tests => 42;
+use Test::More tests => 48;
# Make sure we don't mess with $@ or $!. Test at bottom.
my $Err = "this should not be touched";
@@ -67,10 +67,15 @@ pass('pass() passed');
ok( eq_array([qw(this that whatever)], [qw(this that whatever)]),
'eq_array with simple arrays' );
+is @Test::More::Data_Stack, 0, '@Data_Stack not holding onto things';
+
ok( eq_hash({ foo => 42, bar => 23 }, {bar => 23, foo => 42}),
'eq_hash with simple hashes' );
+is @Test::More::Data_Stack, 0;
+
ok( eq_set([qw(this that whatever)], [qw(that whatever this)]),
'eq_set with simple sets' );
+is @Test::More::Data_Stack, 0;
my @complex_array1 = (
[qw(this that whatever)],
@@ -100,8 +105,11 @@ my @array2 = (qw(this that whatever),
ok( !eq_array(\@array1, \@array2),
'eq_array with slightly different complicated arrays' );
+is @Test::More::Data_Stack, 0;
+
ok( !eq_set(\@array1, \@array2),
'eq_set with slightly different complicated arrays' );
+is @Test::More::Data_Stack, 0;
my %hash1 = ( foo => 23,
bar => [qw(this that whatever)],
@@ -126,6 +134,7 @@ ok( eq_hash(\%hash1, \%hash2), 'eq_hash with complicated hashes');
ok( !eq_hash(\%hash1, \%hash2),
'eq_hash with slightly different complicated hashes' );
+is @Test::More::Data_Stack, 0;
is( Test::Builder->new, Test::More->builder, 'builder()' );
diff --git a/lib/Test/Simple/t/circular_data.t b/lib/Test/Simple/t/circular_data.t
new file mode 100644
index 0000000000..d7d17dcc2d
--- /dev/null
+++ b/lib/Test/Simple/t/circular_data.t
@@ -0,0 +1,33 @@
+#!/usr/bin/perl -w
+
+# Test is_deeply and friends with circular data structures [rt.cpan.org 7289]
+
+BEGIN {
+ if( $ENV{PERL_CORE} ) {
+ chdir 't';
+ @INC = ('../lib', 'lib');
+ }
+ else {
+ unshift @INC, 't/lib';
+ }
+}
+
+use strict;
+use Test::More tests => 5;
+
+my $a1 = [ 1, 2, 3 ];
+push @$a1, $a1;
+my $a2 = [ 1, 2, 3 ];
+push @$a2, $a2;
+
+is_deeply $a1, $a2;
+ok( eq_array ($a1, $a2) );
+ok( eq_set ($a1, $a2) );
+
+my $h1 = { 1=>1, 2=>2, 3=>3 };
+$h1->{4} = $h1;
+my $h2 = { 1=>1, 2=>2, 3=>3 };
+$h2->{4} = $h2;
+
+is_deeply $h1, $h2;
+ok( eq_hash ($h1, $h2) );
diff --git a/lib/Test/Simple/t/diag.t b/lib/Test/Simple/t/diag.t
index 3afdc17678..0b2a51fc6a 100644
--- a/lib/Test/Simple/t/diag.t
+++ b/lib/Test/Simple/t/diag.t
@@ -3,7 +3,10 @@
BEGIN {
if( $ENV{PERL_CORE} ) {
chdir 't';
- @INC = '../lib';
+ @INC = ('../lib', 'lib');
+ }
+ else {
+ unshift @INC, 't/lib';
}
}
@@ -21,17 +24,16 @@ BEGIN {
use strict;
-use Test::More tests => 7;
+use Test::More tests => 5;
my $Test = Test::More->builder;
# now make a filehandle where we can send data
-my $output;
-tie *FAKEOUT, 'FakeOut', \$output;
+use TieOut;
+my $output = tie *FAKEOUT, 'TieOut';
# force diagnostic output to a filehandle, glad I added this to
# Test::Builder :)
-my @lines;
my $ret;
{
local $TODO = 1;
@@ -39,35 +41,32 @@ my $ret;
diag("a single line");
- push @lines, $output;
- $output = '';
-
$ret = diag("multiple\n", "lines");
- push @lines, split(/\n/, $output);
}
-is( @lines, 3, 'diag() should send messages to its filehandle' );
-like( $lines[0], '/^#\s+/', ' should add comment mark to all lines' );
-is( $lines[0], "# a single line\n", ' should send exact message' );
-is( $output, "# multiple\n# lines\n", ' should append multi messages');
+is( $output->read, <<'DIAG', 'diag() with todo_output set' );
+# a single line
+# multiple
+# lines
+DIAG
+
ok( !$ret, 'diag returns false' );
{
$Test->failure_output(\*FAKEOUT);
- $output = '';
$ret = diag("# foo");
}
$Test->failure_output(\*STDERR);
-is( $output, "# # foo\n", "diag() adds a # even if there's one already" );
+is( $output->read, "# # foo\n", "diag() adds # even if there's one already" );
ok( !$ret, 'diag returns false' );
-package FakeOut;
-
-sub TIEHANDLE {
- bless( $_[1], $_[0] );
-}
-sub PRINT {
- my $self = shift;
- $$self .= join('', @_);
+# [rt.cpan.org 8392]
+{
+ $Test->failure_output(\*FAKEOUT);
+ diag(qw(one two));
}
+$Test->failure_output(\*STDERR);
+is( $output->read, <<'DIAG' );
+# onetwo
+DIAG
diff --git a/lib/Test/Simple/t/fail_one.t b/lib/Test/Simple/t/fail_one.t
index d9ce4b85c0..d379a77d23 100644
--- a/lib/Test/Simple/t/fail_one.t
+++ b/lib/Test/Simple/t/fail_one.t
@@ -52,7 +52,7 @@ END {
not ok 1
OUT
- My::Test::ok($$err eq <<"ERR") || print $$err;
+ My::Test::ok($$err eq <<ERR) || print $$err;
# Failed test ($0 at line 45)
# Looks like you failed 1 test of 1.
ERR
diff --git a/lib/Test/Simple/t/is_deeply.t b/lib/Test/Simple/t/is_deeply.t
index 867b1c3509..aa947d2374 100644
--- a/lib/Test/Simple/t/is_deeply.t
+++ b/lib/Test/Simple/t/is_deeply.t
@@ -23,10 +23,23 @@ local $ENV{HARNESS_ACTIVE} = 0;
# Can't use Test.pm, that's a 5.005 thing.
package main;
-print "1..25\n";
+print "1..34\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 is ($$;$) {
my($this, $that, $name) = @_;
my $test = $$this eq $that;
@@ -50,7 +63,7 @@ sub is ($$;$) {
sub like ($$;$) {
my($this, $regex, $name) = @_;
-
+
$regex = qr/$regex/ unless ref $regex;
my $test = $$this =~ $regex;
@@ -209,6 +222,7 @@ my $bar = {
#line 198
is_deeply( $foo, $bar, 'deep structures' );
+ok( @Test::More::Data_Stack == 0, '@Data_Stack not holding onto things' );
is( $out, "not ok 11 - deep structures\n", 'deep structures' );
is( $err, <<ERR, ' right diagnostic' );
# Failed test ($0 at line 198)
@@ -234,3 +248,34 @@ foreach my $test (@tests) {
like \$warning,
qr/^is_deeply\(\) takes two or three args, you gave $num_args\.\n/;
}
+
+
+#line 240
+# [rt.cpan.org 6837]
+ok !is_deeply([{Foo => undef}],[{Foo => ""}]), 'undef != ""';
+ok( @Test::More::Data_Stack == 0, '@Data_Stack not holding onto things' );
+
+
+#line 258
+# [rt.cpan.org 7031]
+my $a = [];
+ok !is_deeply($a, $a.''), "don't compare refs like strings";
+ok !is_deeply([$a], [$a.'']), " even deep inside";
+
+
+#line 265
+# [rt.cpan.org 7030]
+ok !is_deeply( {}, {key => []} ), '[] could match non-existent values';
+ok !is_deeply( [], [[]] );
+
+
+#line 273
+$$err = $$out = '';
+is_deeply( [\'a', 'b'], [\'a', 'c'] );
+is( $out, "not ok 20\n", 'scalar refs in an array' );
+is( $err, <<ERR, ' right diagnostic' );
+# Failed test ($0 at line 274)
+# Structures begin differing at:
+# \$got->[1] = 'b'
+# \$expected->[1] = 'c'
+ERR
diff --git a/lib/Test/Simple/t/overload.t b/lib/Test/Simple/t/overload.t
index 6b300add67..18e7c3d5f4 100644
--- a/lib/Test/Simple/t/overload.t
+++ b/lib/Test/Simple/t/overload.t
@@ -1,4 +1,4 @@
-#!perl -w
+#!/usr/bin/perl -w
BEGIN {
if( $ENV{PERL_CORE} ) {
@@ -9,14 +9,8 @@ BEGIN {
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 strict;
use Test::More;
BEGIN {
@@ -24,7 +18,7 @@ BEGIN {
plan skip_all => "needs overload.pm";
}
else {
- plan tests => 3;
+ plan tests => 7;
}
}
@@ -32,22 +26,25 @@ BEGIN {
package Overloaded;
use overload
- q{""} => sub { $_[0]->{string} };
+ q{""} => sub { $_[0]->{string} },
+ q{0} => sub { $_[0]->{num} },
+ fallback => 1;
sub new {
my $class = shift;
- bless { string => shift }, $class;
+ bless { string => shift, num => shift }, $class;
}
package main;
-my $warnings = '';
-local $SIG{__WARN__} = sub { $warnings = join '', @_ };
-my $obj = Overloaded->new('foo');
-ok( 1, $obj );
+my $obj = Overloaded->new('foo', 42);
+isa_ok $obj, 'Overloaded';
-my $undef = Overloaded->new(undef);
-pass( $undef );
+is $obj, 'foo', 'is() with string overloading';
+cmp_ok $obj, 'eq', 'foo', 'cmp_ok() ...';
+cmp_ok $obj, '==', 'foo', 'cmp_ok() with number overloading';
-is( $warnings, '' );
+is_deeply [$obj], ['foo'], 'is_deeply with string overloading';
+ok eq_array([$obj], ['foo']), 'eq_array ...';
+ok eq_hash({foo => $obj}, {foo => 'foo'}), 'eq_hash ...';
diff --git a/lib/Test/Simple/t/overload_threads.t b/lib/Test/Simple/t/overload_threads.t
new file mode 100644
index 0000000000..8ba78c1d9e
--- /dev/null
+++ b/lib/Test/Simple/t/overload_threads.t
@@ -0,0 +1,69 @@
+#!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 => 5;
+ }
+}
+
+
+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 '', @_ };
+
+# overloaded object as name
+my $obj = Overloaded->new('foo');
+ok( 1, $obj );
+
+# overloaded object which returns undef as name
+my $undef = Overloaded->new(undef);
+pass( $undef );
+
+is( $warnings, '' );
+
+
+TODO: {
+ my $obj = Overloaded->new('not really todo, testing overloaded reason');
+ local $TODO = $obj;
+ fail("Just checking todo as an overloaded value");
+}
+
+
+SKIP: {
+ my $obj = Overloaded->new('not really skipped, testing overloaded reason');
+ skip $obj, 1;
+}
diff --git a/lib/Test/Simple/t/plan_bad.t b/lib/Test/Simple/t/plan_bad.t
new file mode 100644
index 0000000000..cc1295a8f9
--- /dev/null
+++ b/lib/Test/Simple/t/plan_bad.t
@@ -0,0 +1,64 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+ if( $ENV{PERL_CORE} ) {
+ chdir 't';
+ @INC = '../lib';
+ }
+}
+
+
+# Can't use Test.pm, that's a 5.005 thing.
+package My::Test;
+
+print "1..7\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 is ($$;$) {
+ my($this, $that, $name) = @_;
+ my $test = $this eq $that;
+ my $ok = '';
+ $ok .= "not " unless $test;
+ $ok .= "ok $test_num";
+ $ok .= " - $name" if defined $name;
+ $ok .= "\n";
+ print $ok;
+
+ unless( $test ) {
+ print "# got \n$this";
+ print "# expected \n$that";
+ }
+ $test_num++;
+
+ return $test;
+}
+
+
+use Test::More import => ['plan'];
+
+ok !eval { plan tests => 'no_plan'; };
+is $@, "Number of tests must be a postive integer. You gave it 'no_plan'.\n";
+
+my $foo = [];
+my @foo = ($foo, 2, 3);
+ok !eval { plan tests => @foo };
+is $@, "Number of tests must be a postive integer. You gave it '$foo'.\n";
+
+ok !eval { plan tests => 0 };
+ok !eval { plan tests => -1 };
+ok !eval { plan tests => '' };
diff --git a/lib/Test/Simple/t/plan_shouldnt_import.t b/lib/Test/Simple/t/plan_shouldnt_import.t
new file mode 100644
index 0000000000..b6eb064244
--- /dev/null
+++ b/lib/Test/Simple/t/plan_shouldnt_import.t
@@ -0,0 +1,16 @@
+#!/usr/bin/perl -w
+
+# plan() used to export functions by mistake [rt.cpan.org 8385]
+
+BEGIN {
+ if( $ENV{PERL_CORE} ) {
+ chdir 't';
+ @INC = '../lib';
+ }
+}
+
+
+use Test::More ();
+Test::More::plan(tests => 1);
+
+Test::More::ok( !__PACKAGE__->can('ok'), 'plan should not export' );
diff --git a/lib/Test/Simple/t/require_ok.t b/lib/Test/Simple/t/require_ok.t
new file mode 100644
index 0000000000..269b9518cb
--- /dev/null
+++ b/lib/Test/Simple/t/require_ok.t
@@ -0,0 +1,28 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+ if( $ENV{PERL_CORE} ) {
+ chdir 't';
+ @INC = ('../lib', 'lib');
+ }
+ else {
+ unshift @INC, 't/lib';
+ }
+}
+
+use strict;
+use Test::More tests => 7;
+
+# Symbol and Class::Struct are both non-XS core modules back to 5.004.
+# So they'll always be there.
+require_ok("Symbol");
+ok( $INC{'Symbol.pm'}, "require_ok MODULE" );
+
+require_ok("Class/Struct.pm");
+ok( $INC{'Class/Struct.pm'}, "require_ok FILE" );
+
+# Its more trouble than its worth to try to create these filepaths to test
+# through require_ok() so we cheat and use the internal logic.
+ok !Test::More::_is_module_name('foo:bar');
+ok !Test::More::_is_module_name('foo/bar.thing');
+ok !Test::More::_is_module_name('Foo::Bar::');
diff --git a/lib/Test/Simple/t/sort_bug.t b/lib/Test/Simple/t/sort_bug.t
new file mode 100644
index 0000000000..f99212aaff
--- /dev/null
+++ b/lib/Test/Simple/t/sort_bug.t
@@ -0,0 +1,64 @@
+#!/usr/bin/perl -w
+
+# Test to see if we've worked around some wacky sort/threading bug
+# See [rt.cpan.org 6782]
+
+BEGIN {
+ if( $ENV{PERL_CORE} ) {
+ chdir 't';
+ @INC = ('../lib', 'lib');
+ }
+ else {
+ unshift @INC, 't/lib';
+ }
+}
+
+use strict;
+use Config;
+
+BEGIN {
+ require threads if $Config{useithreads};
+}
+use Test::More;
+
+# Passes with $nthreads = 1 and with eq_set().
+# Passes with $nthreads = 2 and with eq_array().
+# Fails with $nthreads = 2 and with eq_set().
+my $nthreads = 2;
+
+if( $Config{useithreads} ) {
+ plan tests => $nthreads;
+}
+else {
+ plan skip_all => 'no threads';
+}
+
+
+sub do_one_thread {
+ my $kid = shift;
+ my @list = ( 'x', 'yy', 'zzz', 'a', 'bb', 'ccc', 'aaaaa', 'z',
+ 'hello', 's', 'thisisalongname', '1', '2', '3',
+ 'abc', 'xyz', '1234567890', 'm', 'n', 'p' );
+ my @list2 = @list;
+ print "# kid $kid before eq_set\n";
+
+ for my $j (1..99) {
+ # With eq_set, either crashes or panics
+ eq_set(\@list, \@list2);
+ eq_array(\@list, \@list2);
+ }
+ print "# kid $kid exit\n";
+ return 42;
+}
+
+my @kids = ();
+for my $i (1..$nthreads) {
+ my $t = threads->new(\&do_one_thread, $i);
+ print "# parent $$: continue\n";
+ push(@kids, $t);
+}
+for my $t (@kids) {
+ print "# parent $$: waiting for join\n";
+ my $rc = $t->join();
+ cmp_ok( $rc, '==', 42, "threads exit status is $rc" );
+}
diff --git a/lib/Test/Simple/t/todo.t b/lib/Test/Simple/t/todo.t
index 9a16626a02..88b2e1559f 100644
--- a/lib/Test/Simple/t/todo.t
+++ b/lib/Test/Simple/t/todo.t
@@ -18,20 +18,23 @@ if( $th_version < 2.03 ) {
exit;
}
-plan tests => 15;
+plan tests => 16;
$Why = 'Just testing the todo interface.';
+my $is_todo;
TODO: {
local $TODO = $Why;
fail("Expected failure");
fail("Another expected failure");
-}
+ $is_todo = Test::More->builder->todo;
+}
pass("This is not todo");
+ok( $is_todo, 'TB->todo' );
TODO: {