=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 *
=head2 C<< plan [ tests => $count | 'no_plan' | skip_all => $reason ] >>
+See L<Test::More/plan>.
+
=cut
sub plan {
=head2 C<< skip $reason => $count >>
+See L<Test::More/skip>.
+
=cut
sub skip {
=head2 C<done_testing [ $count ]>
+See L<Test::More/done_testing>.
+
=cut
sub done_testing {
=head2 C<ok $ok [, $desc ]>
+See L<Test::More/ok>.
+
=cut
sub ok ($;$) {
=head2 C<pass [ $desc ]>
+See L<Test::More/pass>.
+
=cut
sub pass (;$) {
=head2 C<fail [ $desc ]>
+See L<Test::More/fail>.
+
=cut
sub fail (;$) {
=head2 C<is $got, $expected [, $desc ]>
+See L<Test::More/is>.
+
=cut
sub is ($$;$) {
=head2 C<isnt $got, $expected [, $desc ]>
+See L<Test::More/isnt>.
+
=cut
sub isnt ($$;$) {
=head2 C<like $got, $regexp_expected [, $desc ]>
-=cut
+See L<Test::More/like>.
=head2 C<unlike $got, $regexp_expected, [, $desc ]>
+See L<Test::More/unlike>.
+
=cut
{
=head2 C<cmp_ok $got, $op, $expected [, $desc ]>
+See L<Test::More/cmp_ok>.
+
=cut
sub cmp_ok ($$$;$) {
=head2 C<is_deeply $got, $expected [, $desc ]>
+See L<Test::More/is_deeply>.
+
=cut
+sub _deep_ref_check {
+ my ($x, $y, $ry) = @_;
+
+ no warnings qw<numeric uninitialized>;
+
+ if ($ry eq 'ARRAY') {
+ return 0 unless $#$x == $#$y;
+
+ my ($ex, $ey);
+ for (0 .. $#$y) {
+ $ex = $x->[$_];
+ $ey = $y->[$_];
+
+ # Inline the beginning of _deep_check
+ return 0 if defined $ex xor defined $ey;
+
+ next if not(ref $ex xor ref $ey) and $ex eq $ey;
+
+ $ry = Scalar::Util::reftype($ey);
+ return 0 if Scalar::Util::reftype($ex) ne $ry;
+
+ return 0 unless $ry and _deep_ref_check($ex, $ey, $ry);
+ }
+
+ return 1;
+ } elsif ($ry eq 'HASH') {
+ return 0 unless keys(%$x) == keys(%$y);
+
+ my ($ex, $ey);
+ for (keys %$y) {
+ return 0 unless exists $x->{$_};
+ $ex = $x->{$_};
+ $ey = $y->{$_};
+
+ # Inline the beginning of _deep_check
+ return 0 if defined $ex xor defined $ey;
+
+ next if not(ref $ex xor ref $ey) and $ex eq $ey;
+
+ $ry = Scalar::Util::reftype($ey);
+ return 0 if Scalar::Util::reftype($ex) ne $ry;
+
+ return 0 unless $ry and _deep_ref_check($ex, $ey, $ry);
+ }
+
+ return 1;
+ } elsif ($ry eq 'SCALAR' or $ry eq 'REF') {
+ return _deep_check($$x, $$y);
+ }
+
+ return 0;
+}
+
sub _deep_check {
my ($x, $y) = @_;
no warnings qw<numeric uninitialized>;
- return 0 if defined($x) xor defined($y);
+ 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;
+ 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.
# $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;
-};
+ # We know that $x and $y are both references of type $ry, without overloading.
+ _deep_ref_check($x, $y, $ry);
+}
sub is_deeply {
@_ = (
=head2 C<diag @text>
+See L<Test::More/diag>.
+
=cut
sub diag {
=head2 C<note @text>
+See L<Test::More/note>.
+
=cut
sub note {
=head2 C<BAIL_OUT [ $desc ]>
+See L<Test::More/BAIL_OUT>.
+
=cut
sub BAIL_OUT {