File Coverage

inc/Test/More.pm
Criterion Covered Total %
statement 118 355 33.2
branch 35 180 19.4
condition 17 67 25.3
subroutine 21 51 41.1
pod 26 27 96.3
total 217 680 31.9


line stmt bran cond sub pod time code
1             #line 1
2             package Test::More;
3 3     3   1751  
  3         9  
4 3     3   11 use 5.006;
  3         3  
  3         46  
5 3     3   8 use strict;
  3         4  
  3         398  
6             use warnings;
7              
8             #---- perlcritic exemptions. ----#
9              
10             # We use a lot of subroutine prototypes
11             ## no critic (Subroutines::ProhibitSubroutinePrototypes)
12              
13             # Can't use Carp because it might cause C to accidentally succeed
14             # even though the module being used forgot to use Carp. Yes, this
15             # actually happened.
16 0     0   0 sub _carp {
17 0         0 my( $file, $line ) = ( caller(1) )[ 1, 2 ];
18             return warn @_, " at $file line $line\n";
19             }
20              
21             our $VERSION = '1.302194';
22 3     3   1313  
  3         249130  
  3         19  
23             use Test::Builder::Module;
24             our @ISA = qw(Test::Builder::Module);
25             our @EXPORT = qw(ok use_ok require_ok
26             is isnt like unlike is_deeply
27             cmp_ok
28             skip todo todo_skip
29             pass fail
30             eq_array eq_hash eq_set
31             $TODO
32             plan
33             done_testing
34             can_ok isa_ok new_ok
35             diag note explain
36             subtest
37             BAIL_OUT
38             );
39              
40             #line 166
41              
42             sub plan {
43             my $tb = Test::More->builder;
44              
45             return $tb->plan(@_);
46             }
47              
48             # This implements "use Test::More 'no_diag'" but the behavior is
49             # deprecated.
50             sub import_extra {
51             my $class = shift;
52             my $list = shift;
53              
54             my @other = ();
55             my $idx = 0;
56             my $import;
57             while( $idx <= $#{$list} ) {
58             my $item = $list->[$idx];
59              
60             if( defined $item and $item eq 'no_diag' ) {
61             $class->builder->no_diag(1);
62             }
63             elsif( defined $item and $item eq 'import' ) {
64             if ($import) {
65             push @$import, @{$list->[ ++$idx ]};
66             }
67             else {
68             $import = $list->[ ++$idx ];
69             push @other, $item, $import;
70             }
71             }
72             else {
73             push @other, $item;
74             }
75              
76             $idx++;
77             }
78              
79             @$list = @other;
80              
81             if ($class eq __PACKAGE__ && (!$import || grep $_ eq '$TODO', @$import)) {
82             my $to = $class->builder->exported_to;
83             no strict 'refs';
84             *{"$to\::TODO"} = \our $TODO;
85             if ($import) {
86             @$import = grep $_ ne '$TODO', @$import;
87             }
88             else {
89             push @$list, import => [grep $_ ne '$TODO', @EXPORT];
90             }
91             }
92              
93             return;
94             }
95              
96             #line 245
97              
98             sub done_testing {
99             my $tb = Test::More->builder;
100             $tb->done_testing(@_);
101             }
102              
103             #line 317
104              
105             sub ok ($;$) {
106             my( $test, $name ) = @_;
107             my $tb = Test::More->builder;
108              
109             return $tb->ok( $test, $name );
110             }
111              
112             #line 405
113              
114             sub is ($$;$) {
115             my $tb = Test::More->builder;
116              
117             return $tb->is_eq(@_);
118             }
119              
120             sub isnt ($$;$) {
121             my $tb = Test::More->builder;
122              
123             return $tb->isnt_eq(@_);
124             }
125              
126             # Historically it was possible to use apostrophes as a package
127             # separator. make this available as isn't() for perl's that support it.
128             # However in 5.37.9 the apostrophe as a package separator was
129             # deprecated, so warn users of isn't() that they should use isnt()
130             # instead. We assume that if they are calling isn::t() they are doing so
131             # via isn't() as we have no way to be sure that they aren't spelling it
132             # with a double colon. We only trigger the warning if deprecation
133             # warnings are enabled, so the user can silence the warning if they
134             # wish.
135             sub isn::t {
136             local ($@, $!, $?);
137             if (warnings::enabled("deprecated")) {
138             _carp
139             "Use of apostrophe as package separator was deprecated in Perl 5.37.9,\n",
140             "and will be removed in Perl 5.42.0. You should change code that uses\n",
141             "Test::More::isn't() to use Test::More::isnt() as a replacement";
142             }
143             goto &isnt;
144             }
145              
146             #line 467
147              
148             sub like ($$;$) {
149             my $tb = Test::More->builder;
150              
151             return $tb->like(@_);
152             }
153              
154             #line 482
155              
156             sub unlike ($$;$) {
157             my $tb = Test::More->builder;
158              
159             return $tb->unlike(@_);
160             }
161              
162             #line 528
163              
164             sub cmp_ok($$$;$) {
165             my $tb = Test::More->builder;
166              
167             return $tb->cmp_ok(@_);
168 1     1 1 181348 }
169              
170 1         29 #line 563
171              
172             sub can_ok ($@) {
173             my( $proto, @methods ) = @_;
174             my $class = ref $proto || $proto;
175             my $tb = Test::More->builder;
176 3     3 1 191  
177 3         5 unless($class) {
178             my $ok = $tb->ok( 0, "->can(...)" );
179 3         6 $tb->diag(' can_ok() called with empty class or reference');
180 3         4 return $ok;
181 3         5 }
182 3         5  
  7         20  
183 4         7 unless(@methods) {
184             my $ok = $tb->ok( 0, "$class->can(...)" );
185 4 50 33     20 $tb->diag(' can_ok() called with no methods');
    50 33        
186 0         0 return $ok;
187             }
188              
189 0 0       0 my @nok = ();
190 0         0 foreach my $method (@methods) {
  0         0  
191             $tb->_try( sub { $proto->can($method) } ) or push @nok, $method;
192             }
193 0         0  
194 0         0 my $name = (@methods == 1) ? "$class->can('$methods[0]')" :
195             "$class->can(...)" ;
196              
197             my $ok = $tb->ok( !@nok, $name );
198 4         21  
199             $tb->diag( map " $class->can('$_') failed\n", @nok );
200              
201 4         4 return $ok;
202             }
203              
204 3         7 #line 629
205              
206 3 50 33     18 sub isa_ok ($$;$) {
      33        
207 3         8 my( $thing, $class, $thing_name ) = @_;
208 3     3   4394 my $tb = Test::More->builder;
  3         4  
  3         8452  
209 3         44  
  3         16  
210 3 50       7 my $whatami;
211 0         0 if( !defined $thing ) {
212             $whatami = 'undef';
213             }
214 3         25 elsif( ref $thing ) {
215             $whatami = 'reference';
216              
217             local($@,$!);
218 3         8 require Scalar::Util;
219             if( Scalar::Util::blessed($thing) ) {
220             $whatami = 'object';
221             }
222             }
223             else {
224             $whatami = 'class';
225             }
226              
227             # We can't use UNIVERSAL::isa because we want to honor isa() overrides
228             my( $rslt, $error ) = $tb->_try( sub { $thing->isa($class) } );
229              
230             if($error) {
231             die <
232             WHOA! I tried to call ->isa on your $whatami and got some weird error.
233             Here's the error.
234             $error
235             WHOA
236             }
237              
238             # Special case for isa_ok( [], "ARRAY" ) and like
239             if( $whatami eq 'reference' ) {
240             $rslt = UNIVERSAL::isa($thing, $class);
241             }
242              
243             my($diag, $name);
244             if( defined $thing_name ) {
245             $name = "'$thing_name' isa '$class'";
246             $diag = defined $thing ? "'$thing_name' isn't a '$class'" : "'$thing_name' isn't defined";
247 0     0 1 0 }
248 0         0 elsif( $whatami eq 'object' ) {
249             my $my_class = ref $thing;
250             $thing_name = qq[An object of class '$my_class'];
251             $name = "$thing_name isa '$class'";
252             $diag = "The object of class '$my_class' isn't a '$class'";
253             }
254             elsif( $whatami eq 'reference' ) {
255             my $type = ref $thing;
256             $thing_name = qq[A reference of type '$type'];
257             $name = "$thing_name isa '$class'";
258             $diag = "The reference of type '$type' isn't a '$class'";
259             }
260             elsif( $whatami eq 'undef' ) {
261             $thing_name = 'undef';
262             $name = "$thing_name isa '$class'";
263             $diag = "$thing_name isn't defined";
264             }
265             elsif( $whatami eq 'class' ) {
266             $thing_name = qq[The class (or class-like) '$thing'];
267             $name = "$thing_name isa '$class'";
268             $diag = "$thing_name isn't a '$class'";
269             }
270             else {
271             die;
272             }
273              
274             my $ok;
275             if($rslt) {
276             $ok = $tb->ok( 1, $name );
277             }
278             else {
279             $ok = $tb->ok( 0, $name );
280             $tb->diag(" $diag\n");
281             }
282              
283             return $ok;
284             }
285              
286             #line 730
287              
288             sub new_ok {
289             my $tb = Test::More->builder;
290             $tb->croak("new_ok() must be given at least a class") unless @_;
291              
292             my( $class, $args, $object_name ) = @_;
293              
294             $args ||= [];
295              
296             my $obj;
297             my( $success, $error ) = $tb->_try( sub { $obj = $class->new(@$args); 1 } );
298             if($success) {
299             local $Test::Builder::Level = $Test::Builder::Level + 1;
300             isa_ok $obj, $class, $object_name;
301             }
302             else {
303             $class = 'undef' if !defined $class;
304             $tb->ok( 0, "$class->new() died" );
305             $tb->diag(" Error was: $error");
306             }
307              
308             return $obj;
309             }
310              
311             #line 827
312              
313             sub subtest {
314             my $tb = Test::More->builder;
315             return $tb->subtest(@_);
316             }
317              
318             #line 849
319 4     4 1 1002454  
320 4         84 sub pass (;$) {
321             my $tb = Test::More->builder;
322 4         80  
323             return $tb->ok( 1, @_ );
324             }
325              
326             sub fail (;$) {
327             my $tb = Test::More->builder;
328              
329             return $tb->ok( 0, @_ );
330             }
331              
332             #line 902
333              
334             sub require_ok ($) {
335             my($module) = shift;
336             my $tb = Test::More->builder;
337              
338             my $pack = caller;
339              
340             # Try to determine if we've been given a module name or file.
341             # Module names must be barewords, files not.
342             $module = qq['$module'] unless _is_module_name($module);
343              
344             my $code = <
345             package $pack;
346             require $module;
347             1;
348             REQUIRE
349              
350             my( $eval_result, $eval_error ) = _eval($code);
351             my $ok = $tb->ok( $eval_result, "require $module;" );
352              
353             unless($ok) {
354             chomp $eval_error;
355             $tb->diag(<
356             Tried to require '$module'.
357             Error: $eval_error
358             DIAGNOSTIC
359              
360             }
361              
362             return $ok;
363             }
364              
365             sub _is_module_name {
366             my $module = shift;
367              
368             # Module names start with a letter.
369             # End with an alphanumeric.
370             # The rest is an alphanumeric or ::
371             $module =~ s/\b::\b//g;
372              
373             return $module =~ /^[a-zA-Z]\w*$/ ? 1 : 0;
374             }
375              
376              
377             #line 996
378              
379             sub use_ok ($;@) {
380             my( $module, @imports ) = @_;
381             @imports = () unless @imports;
382             my $tb = Test::More->builder;
383              
384             my %caller;
385             @caller{qw/pack file line sub args want eval req strict warn/} = caller(0);
386              
387             my ($pack, $filename, $line, $warn) = @caller{qw/pack file line warn/};
388             $filename =~ y/\n\r/_/; # so it doesn't run off the "#line $line $f" line
389              
390             my $code;
391             if( @imports == 1 and $imports[0] =~ /^\d+(?:\.\d+)?$/ ) {
392             # probably a version check. Perl needs to see the bare number
393             # for it to work with non-Exporter based modules.
394             $code = <
395             package $pack;
396             BEGIN { \${^WARNING_BITS} = \$args[-1] if defined \$args[-1] }
397             #line $line $filename
398             use $module $imports[0];
399             1;
400             USE
401             }
402             else {
403             $code = <
404             package $pack;
405             BEGIN { \${^WARNING_BITS} = \$args[-1] if defined \$args[-1] }
406             #line $line $filename
407 11     11 1 15727 use $module \@{\$args[0]};
408             1;
409 11         246 USE
410             }
411              
412             my ($eval_result, $eval_error) = _eval($code, \@imports, $warn);
413 0     0 1 0 my $ok = $tb->ok( $eval_result, "use $module;" );
414              
415 0         0 unless($ok) {
416             chomp $eval_error;
417             $@ =~ s{^BEGIN failed--compilation aborted at .*$}
418             {BEGIN failed--compilation aborted at $filename line $line.}m;
419             $tb->diag(<
420             Tried to use '$module'.
421             Error: $eval_error
422             DIAGNOSTIC
423              
424             }
425              
426             return $ok;
427             }
428 0     0   0  
429 0 0       0 sub _eval {
430 0         0 my( $code, @args ) = @_;
431              
432             # Work around oddities surrounding resetting of $@ by immediately
433             # storing it.
434             my( $sigdie, $eval_result, $eval_error );
435 0         0 {
436             local( $@, $!, $SIG{__DIE__} ); # isolate eval
437             $eval_result = eval $code; ## no critic (BuiltinFunctions::ProhibitStringyEval)
438             $eval_error = $@;
439             $sigdie = $SIG{__DIE__} || undef;
440             }
441             # make sure that $code got a chance to set $SIG{__DIE__}
442             $SIG{__DIE__} = $sigdie if defined $sigdie;
443              
444             return( $eval_result, $eval_error );
445             }
446              
447              
448             #line 1114
449              
450             our( @Data_Stack, %Refs_Seen );
451             my $DNE = bless [], 'Does::Not::Exist';
452              
453             sub _dne {
454             return ref $_[0] eq ref $DNE;
455             }
456              
457             ## no critic (Subroutines::RequireArgUnpacking)
458             sub is_deeply {
459             my $tb = Test::More->builder;
460              
461             unless( @_ == 2 or @_ == 3 ) {
462             my $msg = <<'WARNING';
463             is_deeply() takes two or three args, you gave %d.
464             This usually means you passed an array or hash instead
465             of a reference to it
466             WARNING
467             chop $msg; # clip off newline so carp() will put in line/file
468              
469 0     0 1 0 _carp sprintf $msg, scalar @_;
470              
471 0         0 return $tb->ok(0);
472             }
473              
474             my( $got, $expected, $name ) = @_;
475              
476             $tb->_unoverload_str( \$expected, \$got );
477              
478             my $ok;
479             if( !ref $got and !ref $expected ) { # neither is a reference
480             $ok = $tb->is_eq( $got, $expected, $name );
481             }
482             elsif( !ref $got xor !ref $expected ) { # one's a reference, one isn't
483             $ok = $tb->ok( 0, $name );
484 0     0 1 0 $tb->diag( _format_stack({ vals => [ $got, $expected ] }) );
485             }
486 0         0 else { # both references
487             local @Data_Stack = ();
488             if( _deep_check( $got, $expected ) ) {
489             $ok = $tb->ok( 1, $name );
490             }
491             else {
492             $ok = $tb->ok( 0, $name );
493             $tb->diag( _format_stack(@Data_Stack) );
494             }
495             }
496              
497             return $ok;
498             }
499              
500             sub _format_stack {
501             my(@Stack) = @_;
502              
503             my $var = '$FOO';
504             my $did_arrow = 0;
505             foreach my $entry (@Stack) {
506             my $type = $entry->{type} || '';
507             my $idx = $entry->{'idx'};
508             if( $type eq 'HASH' ) {
509             $var .= "->" unless $did_arrow++;
510             $var .= "{$idx}";
511             }
512             elsif( $type eq 'ARRAY' ) {
513             $var .= "->" unless $did_arrow++;
514             $var .= "[$idx]";
515             }
516             elsif( $type eq 'REF' ) {
517             $var = "\${$var}";
518             }
519             }
520              
521             my @vals = @{ $Stack[-1]{vals} }[ 0, 1 ];
522             my @vars = ();
523             ( $vars[0] = $var ) =~ s/\$FOO/ \$got/;
524             ( $vars[1] = $var ) =~ s/\$FOO/\$expected/;
525              
526             my $out = "Structures begin differing at:\n";
527             foreach my $idx ( 0 .. $#vals ) {
528             my $val = $vals[$idx];
529             $vals[$idx]
530 0     0 1 0 = !defined $val ? 'undef'
531             : _dne($val) ? "Does not exist"
532 0         0 : ref $val ? "$val"
533             : "'$val'";
534             }
535              
536             $out .= "$vars[0] = $vals[0]\n";
537             $out .= "$vars[1] = $vals[1]\n";
538              
539             $out =~ s/^/ /msg;
540             return $out;
541             }
542              
543             sub _type {
544             my $thing = shift;
545              
546             return '' if !ref $thing;
547              
548             for my $type (qw(Regexp ARRAY HASH REF SCALAR GLOB CODE VSTRING)) {
549             return $type if UNIVERSAL::isa( $thing, $type );
550             }
551              
552             return '';
553             }
554              
555             #line 1274
556              
557             sub diag {
558             return Test::More->builder->diag(@_);
559             }
560              
561             sub note {
562             return Test::More->builder->note(@_);
563             }
564              
565 0     0 1 0 #line 1300
566 0   0     0  
567 0         0 sub explain {
568             return Test::More->builder->explain(@_);
569 0 0       0 }
570 0         0  
571 0         0 #line 1366
572 0         0  
573             ## no critic (Subroutines::RequireFinalReturn)
574             sub skip {
575 0 0       0 my( $why, $how_many ) = @_;
576 0         0 my $tb = Test::More->builder;
577 0         0  
578 0         0 # If the plan is set, and is static, then skip needs a count. If the plan
579             # is 'no_plan' we are fine. As well if plan is undefined then we are
580             # waiting for done_testing.
581 0         0 unless (defined $how_many) {
582 0         0 my $plan = $tb->has_plan;
583 0 0   0   0 _carp "skip() needs to know \$how_many tests are in the block"
  0         0  
584             if $plan && $plan =~ m/^\d+$/;
585             $how_many = 1;
586 0 0       0 }
587              
588             if( defined $how_many and $how_many =~ /\D/ ) {
589 0         0 _carp
590             "skip() was passed a non-numeric number of tests. Did you get the arguments backwards?";
591 0         0 $how_many = 1;
592             }
593 0         0  
594             for( 1 .. $how_many ) {
595             $tb->skip($why);
596             }
597              
598             no warnings 'exiting';
599             last SKIP;
600             }
601              
602             #line 1462
603              
604             sub todo_skip {
605             my( $why, $how_many ) = @_;
606             my $tb = Test::More->builder;
607              
608             unless( defined $how_many ) {
609             # $how_many can only be avoided when no_plan is in use.
610             _carp "todo_skip() needs to know \$how_many tests are in the block"
611             unless $tb->has_plan eq 'no_plan';
612             $how_many = 1;
613             }
614              
615             for( 1 .. $how_many ) {
616             $tb->todo_skip($why);
617             }
618              
619             no warnings 'exiting';
620             last TODO;
621             }
622              
623             #line 1517
624              
625             sub BAIL_OUT {
626             my $reason = shift;
627             my $tb = Test::More->builder;
628              
629             $tb->BAIL_OUT($reason);
630             }
631 0     0 1 0  
632 0         0 #line 1556
633              
634 0         0 #'#
635 0 0       0 sub eq_array {
    0          
636 0         0 local @Data_Stack = ();
637             _deep_check(@_);
638             }
639 0         0  
640             sub _eq_array {
641 0         0 my( $a1, $a2 ) = @_;
642 0         0  
643 0 0       0 if( grep _type($_) ne 'ARRAY', $a1, $a2 ) {
644 0         0 warn "eq_array passed a non-array ref";
645             return 0;
646             }
647              
648 0         0 return 1 if $a1 eq $a2;
649              
650             my $ok = 1;
651             my $max = $#$a1 > $#$a2 ? $#$a1 : $#$a2;
652 0     0   0 for( 0 .. $max ) {
  0         0  
653             my $e1 = $_ > $#$a1 ? $DNE : $a1->[$_];
654 0 0       0 my $e2 = $_ > $#$a2 ? $DNE : $a2->[$_];
655 0 0       0  
656             next if _equal_nonrefs($e1, $e2);
657              
658             push @Data_Stack, { type => 'ARRAY', idx => $_, vals => [ $e1, $e2 ] };
659             $ok = _deep_check( $e1, $e2 );
660             pop @Data_Stack if $ok;
661              
662             last unless $ok;
663 0 0       0 }
664 0         0  
665             return $ok;
666             }
667 0         0  
668 0 0       0 sub _equal_nonrefs {
    0          
    0          
    0          
    0          
669 0         0 my( $e1, $e2 ) = @_;
670 0 0       0  
671             return if ref $e1 or ref $e2;
672              
673 0         0 if ( defined $e1 ) {
674 0         0 return 1 if defined $e2 and $e1 eq $e2;
675 0         0 }
676 0         0 else {
677             return 1 if !defined $e2;
678             }
679 0         0  
680 0         0 return;
681 0         0 }
682 0         0  
683             sub _deep_check {
684             my( $e1, $e2 ) = @_;
685 0         0 my $tb = Test::More->builder;
686 0         0  
687 0         0 my $ok = 0;
688              
689             # Effectively turn %Refs_Seen into a stack. This avoids picking up
690 0         0 # the same referenced used twice (such as [\$a, \$a]) to be considered
691 0         0 # circular.
692 0         0 local %Refs_Seen = %Refs_Seen;
693              
694             {
695 0         0 $tb->_unoverload_str( \$e1, \$e2 );
696              
697             # Either they're both references or both not.
698 0         0 my $same_ref = !( !ref $e1 xor !ref $e2 );
699 0 0       0 my $not_ref = ( !ref $e1 and !ref $e2 );
700 0         0  
701             if( defined $e1 xor defined $e2 ) {
702             $ok = 0;
703 0         0 }
704 0         0 elsif( !defined $e1 and !defined $e2 ) {
705             # Shortcut if they're both undefined.
706             $ok = 1;
707 0         0 }
708             elsif( _dne($e1) xor _dne($e2) ) {
709             $ok = 0;
710             }
711             elsif( $same_ref and( $e1 eq $e2 ) ) {
712             $ok = 1;
713             }
714             elsif($not_ref) {
715             push @Data_Stack, { type => '', vals => [ $e1, $e2 ] };
716             $ok = 0;
717             }
718             else {
719             if( $Refs_Seen{$e1} ) {
720             return $Refs_Seen{$e1} eq $e2;
721             }
722             else {
723             $Refs_Seen{$e1} = "$e2";
724             }
725              
726             my $type = _type($e1);
727             $type = 'DIFFERENT' unless _type($e2) eq $type;
728              
729             if( $type eq 'DIFFERENT' ) {
730             push @Data_Stack, { type => $type, vals => [ $e1, $e2 ] };
731             $ok = 0;
732 0     0 1 0 }
733 0 0       0 elsif( $type eq 'ARRAY' ) {
734             $ok = _eq_array( $e1, $e2 );
735 0         0 }
736             elsif( $type eq 'HASH' ) {
737 0   0     0 $ok = _eq_hash( $e1, $e2 );
738             }
739 0         0 elsif( $type eq 'REF' ) {
740 0     0   0 push @Data_Stack, { type => $type, vals => [ $e1, $e2 ] };
  0         0  
  0         0  
741 0 0       0 $ok = _deep_check( $$e1, $$e2 );
742 0         0 pop @Data_Stack if $ok;
743 0         0 }
744             elsif( $type eq 'SCALAR' ) {
745             push @Data_Stack, { type => 'REF', vals => [ $e1, $e2 ] };
746 0 0       0 $ok = _deep_check( $$e1, $$e2 );
747 0         0 pop @Data_Stack if $ok;
748 0         0 }
749             elsif($type) {
750             push @Data_Stack, { type => $type, vals => [ $e1, $e2 ] };
751 0         0 $ok = 0;
752             }
753             else {
754             _whoa( 1, "No type in _deep_check" );
755             }
756             }
757             }
758              
759             return $ok;
760             }
761              
762             sub _whoa {
763             my( $check, $desc ) = @_;
764             if($check) {
765             die <<"WHOA";
766             WHOA! $desc
767             This should never happen! Please contact the author immediately!
768             WHOA
769             }
770             }
771              
772             #line 1703
773              
774             sub eq_hash {
775             local @Data_Stack = ();
776             return _deep_check(@_);
777             }
778              
779             sub _eq_hash {
780             my( $a1, $a2 ) = @_;
781              
782             if( grep _type($_) ne 'HASH', $a1, $a2 ) {
783             warn "eq_hash passed a non-hash ref";
784             return 0;
785             }
786              
787             return 1 if $a1 eq $a2;
788              
789             my $ok = 1;
790             my $bigger = keys %$a1 > keys %$a2 ? $a1 : $a2;
791             foreach my $k ( keys %$bigger ) {
792             my $e1 = exists $a1->{$k} ? $a1->{$k} : $DNE;
793             my $e2 = exists $a2->{$k} ? $a2->{$k} : $DNE;
794              
795             next if _equal_nonrefs($e1, $e2);
796              
797             push @Data_Stack, { type => 'HASH', idx => $k, vals => [ $e1, $e2 ] };
798             $ok = _deep_check( $e1, $e2 );
799             pop @Data_Stack if $ok;
800              
801             last unless $ok;
802             }
803              
804             return $ok;
805             }
806              
807             #line 1762
808              
809             sub eq_set {
810             my( $a1, $a2 ) = @_;
811             return 0 unless @$a1 == @$a2;
812              
813             no warnings 'uninitialized';
814              
815             # It really doesn't matter how we sort them, as long as both arrays are
816             # sorted with the same algorithm.
817             #
818             # Ensure that references are not accidentally treated the same as a
819             # string containing the reference.
820             #
821             # Have to inline the sort routine due to a threading/sort bug.
822             # See [rt.cpan.org 6782]
823             #
824             # I don't know how references would be sorted so we just don't sort
825             # them. This means eq_set doesn't really work with refs.
826             return eq_array(
827             [ grep( ref, @$a1 ), sort( grep( !ref, @$a1 ) ) ],
828             [ grep( ref, @$a2 ), sort( grep( !ref, @$a2 ) ) ],
829 0     0 1 0 );
830 0         0 }
831              
832             #line 2026
833              
834             1;