Final one tonight!

eq_array and eq_hash don't tidy up after themselves. You would have to be very 
unfortunate to be stung by this problem but potentially you could end up with 
extra references to some of your variables which could effect tests further 
on due to DESTROYs not being called or whatever.

use Test::More;
for(1..10)
{
  eq_array( [[]], [{}] )
}
print join(", ", @Test::More::Data_Stack)."\n";

The solution is to make eq_array and eq_hash wrappers around the original 
functions. This is needed for the circular structures patch anyway.

Actually, I've gone a little further and made them wrappers around a new 
eq_deeply(). All they do is check that the second argument is of the correct 
type. This means that all the localling of @Data_Stack is only done in 
eq_deeply.

It also means they won't die anymore if the wrong kind of arguments are passed 
in. Although, I'm not sure if this is a good idea, maybe dying is preferable.

Patch attached.

Also attached is a test script that exercises the various comparison 
functions. It's missing a few cases but it covers a fair bit,

F

-- 
Do you need someone with lots of Unix sysadmin and/or lots of OO software 
development experience? Go on, giz a job.
My CV - http://www.fergaldaly.com/cv.html
--- lib/Test/More.pm.orig	2003-02-27 20:54:34.000000000 +0000
+++ lib/Test/More.pm	2003-02-28 00:11:47.000000000 +0000
@@ -25,7 +25,7 @@
              cmp_ok
              skip todo todo_skip
              pass fail
-             eq_array eq_hash eq_set
+             eq_array eq_hash eq_set eq_deeply
              $TODO
              plan
              can_ok  isa_ok
@@ -996,6 +996,12 @@
     return $out;
 }
 
+sub eq_deeply {
+    my ($a1, $a2) = @_;
+
+    local @Data_Stack = ();
+    return _deep_check($a1, $a2);
+}
 
 =item B<eq_array>
 
@@ -1007,7 +1013,14 @@
 =cut
 
 #'#
-sub eq_array  {
+
+sub eq_array {
+    my ($a1, $a2) = @_;
+
+    return UNIVERSAL::isa($a2, "ARRAY") ? return eq_deeply($a1, $a2) : 0;
+}
+
+sub _eq_array  {
     my($a1, $a2) = @_;
     return 1 if !ref $a1 and ! ref $a2 and $a1 eq $a2;
 
@@ -1042,12 +1055,12 @@
             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') )
@@ -1084,6 +1097,12 @@
 =cut
 
 sub eq_hash {
+    my ($a1, $a2) = @_;
+
+    return UNIVERSAL::isa($a2, "HASH") ? return eq_deeply($a1, $a2) : 0;
+}
+
+sub _eq_hash {
     my($a1, $a2) = @_;
     return 1 if !ref $a1 and ! ref $a2 and $a1 eq $a2;
 
# -*-perl-*-
use strict;
use Test::More (tests => 18);

{
	my $a = [];
	my $b = $a."";

	ok(! eq_deeply([$a], [$b]), "stringified");
}

{
	# take an array full of a variety of things and break each one

	my @a1 = an_array();
	my @a2 = an_array();

	is_deeply([EMAIL PROTECTED], [EMAIL PROTECTED], "is array");
	ok(eq_array([EMAIL PROTECTED], [EMAIL PROTECTED]), "eq array");

	for (my $i = 0; $i < @a1; $i++)
	{
		my @new = an_array();
		my $it = $new[$i];
		my $broken = break_it($it);

		$new[$i] = $broken;
		ok(! eq_array([EMAIL PROTECTED], [EMAIL PROTECTED]), "array broken ref='".ref($broken)."'");
	}

	my @new = an_array();
	break_it([EMAIL PROTECTED]);
	ok(! eq_array([EMAIL PROTECTED], [EMAIL PROTECTED]), "array broken extra");
}

{
	# take a hash full of a variety of things and break each one

	my %a1 = a_hash();
	my %a2 = a_hash();

	is_deeply(\%a1, \%a2, "is hash");
	ok(eq_hash(\%a1, \%a2), "eq hash");

	foreach my $key (keys %a1)
	{
		my %new = a_hash();
		my $it = $new{$key};
		my $broken = break_it($it);

		$new{$key} = $broken;
		ok(! eq_hash(\%new, \%a1), "hash broken ref='".ref($broken)."'");
	}

	my %new = a_hash();
	break_it(\%new);
	ok(! eq_hash(\%new, \%a1), "hash broken extra");
}

# test a messy complex thing
is_deeply(complex_thing(), complex_thing(), "complex");

sub an_array
{
	return ( [], {}, "hello", \"ref", \['hello'] );
}

sub a_hash
{
	return (
		key1 => [],
		key2 => {},
		key3 => "hello",
		key4 => \"ref",
		key5  => \['hello']
	);
}

sub break_it
{
	my $it = shift;

	if (UNIVERSAL::isa($it, 'ARRAY'))
	{
		push(@$it, "extra elem");
	}
	elsif (UNIVERSAL::isa($it, 'HASH'))
	{
		$it->{"extra key"} = "extra value";
	}
	elsif (UNIVERSAL::isa($it, 'REF'))
	{
		$it = \['a different ref'];
	}
	elsif (UNIVERSAL::isa($it, 'SCALAR'))
	{
		$it = \"$$it and something else";
	}
	else
	{
		$it = "$it something else";
	}
	return $it
}

sub complex_thing
{
	my $b = [qw( hello world)];
	my $a = [
		{
			key1 => \$b,
			key2 => [{}],
			key3 => \'scalarref',
			key4 => 'scalar',
		},
		[\"scalarref"],
	];

	return $a;
}

Reply via email to