=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 .. $#$y;
- 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 {
@_ = (
capture_to_buffer $buf
or plan skip_all =>'perl 5.8 required to test is_deeply() failing';
-plan tests => 3 * 2 * (30 + 1 + 2);
+plan tests => 3 * 2 * (32 + 1 + 2);
my $shrunk = [ [ 1, 2, 3 ] => [ 1, 2, 3 ] ];
delete $shrunk->[0]->[2];
[ [ 0 ] => [ '' ] ],
[ [ '' ] => [ ] ],
+ [ [ \1 ] => [ \"1.0" ] ],
+
[ [ 1, undef, 3 ] => [ 1, 2, 3 ] ],
[ [ 1, 2, undef ] => [ 1, 2 ] ],
$shrunk,
[ { a => '' } => { } ],
[ { a => 1 } => { 'A' => 1 } ],
+ [ { a => 1 } => { 'a' => \"1.0" } ],
[ [ { a => 1 }, 2, { b => \3 } ] => [ { a => 1 }, 2, { b => \'3.0' } ] ],