=item *
Stringification isn't forced on the test operands.
-However, L</ok> honors C<'bool'> overloading, L</is> honors C<'eq'> overloading and L</cmp_ok> honors whichever overloading category corresponds to the specified operator.
+However, L</ok> honors C<'bool'> overloading, L</is> and L</is_deeply> honor C<'eq'> overloading (and just that one) and L</cmp_ok> honors whichever overloading category corresponds to the specified operator.
=item *
=item *
+L</like> and L</unlike> don't special case regular expressions that are passed as C<'/.../'> strings.
+A string regexp argument is always treated as a the source of the regexp, making C<like $text, $rx> and C<like $text, qr[$rx]> equivalent to each other and to C<cmp_ok $text, '=~', $rx> (and likewise for C<unlike>).
+
+=item *
+
L</cmp_ok> throws an exception if the given operator isn't a valid Perl binary operator (except C<'='> and variants).
It also tests in scalar context, so C<'..'> will be treated as the flip-flop operator and not the range operator.
=item *
+L</is_deeply> doesn't guard for memory cycles.
+If the two first arguments present parallel memory cycles, the test may result in an infinite loop.
+
+=item *
+
+The tests don't output any kind of default diagnostic in case of failure ; the rationale being that if you have a large number of tests and a lot of them are failing, then you don't want to be flooded by diagnostics.
+
+=item *
+
C<use_ok>, C<require_ok>, C<can_ok>, C<isa_ok>, C<new_ok>, C<subtest>, C<explain>, C<TODO> blocks and C<todo_skip> are not implemented.
+=item *
+
+L<Test::Leaner> depends on L<Scalar::Util>, while L<Test::More> does not.
+
=back
=cut
-use Exporter ();
+use Exporter ();
+use Scalar::Util ();
BEGIN {
if ($] >= 5.008 and $INC{'threads.pm'}) {
ok
is
isnt
- cmp_ok
like
unlike
+ cmp_ok
+ is_deeply
diag
note
BAIL_OUT
=head2 C<like $got, $regexp_expected [, $desc ]>
+=cut
+
=head2 C<unlike $got, $regexp_expected, [, $desc ]>
=cut
goto $handler;
}
+=head2 C<is_deeply $got, $expected [, $desc ]>
+
+=cut
+
+sub _deep_check {
+ my ($x, $y) = @_;
+
+ no warnings qw<numeric uninitialized>;
+
+ return 0 if defined($x) xor defined($y);
+
+ # Try object identity/eq overloading first. It also covers the case where
+ # $x and $y are both undefined.
+ # If either $x or $y is overloaded but none has eq overloading, the test will
+ # break at that point.
+ return 1 if not(ref($x) xor ref($y)) and $x eq $y;
+
+ # Test::More::is_deeply happily breaks encapsulation if the objects aren't
+ # overloaded.
+ my $ry = Scalar::Util::reftype($y);
+ return 0 if Scalar::Util::reftype($x) ne $ry;
+
+ # Shortcut if $x and $y are both not references and failed the previous
+ # $x eq $y test.
+ return 0 unless $ry;
+
+ if ($ry eq 'ARRAY') {
+ if ($#$x == $#$y) {
+ # Prevent vivification of deleted elements by fetching the array values.
+ my ($ex, $ey);
+ _deep_check($ex = $x->[$_], $ey = $y->[$_]) or return 0 for 0 .. $#$x;
+ return 1;
+ }
+ } elsif ($ry eq 'HASH') {
+ if (keys(%$x) == keys(%$y)) {
+ (exists $x->{$_} and _deep_check($x->{$_}, $y->{$_}))
+ or return 0 for keys %$y;
+ return 1;
+ }
+ } elsif ($ry eq 'SCALAR' or $ry eq 'REF') {
+ return _deep_check($$x, $$y);
+ }
+
+ return 0;
+};
+
+sub is_deeply {
+ @_ = (
+ &_deep_check,
+ $_[2],
+ );
+ goto &ok;
+}
+
sub _diag_fh {
my $fh = shift;
L<perl> 5.6.
-L<Exporter>, L<Test::More>
+L<Exporter>, L<Scalar::Util>, L<Test::More>.
=head1 AUTHOR