File Coverage

inc/Test/Builder.pm
Criterion Covered Total %
statement 287 694 41.3
branch 78 346 22.5
condition 14 86 16.2
subroutine 55 100 55.0
pod 49 49 100.0
total 483 1275 37.8


line stmt bran cond sub pod time code
1             #line 1
2             package Test::Builder;
3 2     2   25  
  2         4  
  2         60  
4 2     2   10 use 5.006;
  2         3  
  2         47  
5 2     2   8 use strict;
  2         58  
  2         49  
6 2     2   1976 use warnings;
  2         25346  
  2         241  
7             use Encode;
8              
9             our $VERSION = '0.94';
10             $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval)
11              
12 2 50   2   46 BEGIN {
13 0         0 if( $] < 5.008 ) {
14             require Test::Builder::IO::Scalar;
15             }
16             }
17              
18              
19             # Make Test::Builder thread-safe for ithreads.
20 2     2   15 BEGIN {
  2         4  
  2         568  
21             use Config;
22             # Load threads::shared when threads are turned on.
23 2 50 33 2   46 # 5.8.0's threads are so busted we no longer support them.
      33        
24 0         0 if( $] >= 5.008001 && $Config{useithreads} && $INC{'threads.pm'} ) {
25             require threads::shared;
26              
27             # Hack around YET ANOTHER threads::shared bug. It would
28             # occassionally forget the contents of the variable when sharing it.
29             # So we first copy the data, then share, then put our copy back.
30 0         0 *share = sub (\[$@%]) {
31 0         0 my $type = ref $_[0];
32             my $data;
33 0 0       0  
    0          
    0          
34 0         0 if( $type eq 'HASH' ) {
  0         0  
35             %$data = %{ $_[0] };
36             }
37 0         0 elsif( $type eq 'ARRAY' ) {
  0         0  
38             @$data = @{ $_[0] };
39             }
40 0         0 elsif( $type eq 'SCALAR' ) {
  0         0  
41             $$data = ${ $_[0] };
42             }
43 0         0 else {
44             die( "Unknown type: " . $type );
45             }
46 0         0  
47             $_[0] = &threads::shared::share( $_[0] );
48 0 0       0  
    0          
    0          
49 0         0 if( $type eq 'HASH' ) {
  0         0  
50             %{ $_[0] } = %$data;
51             }
52 0         0 elsif( $type eq 'ARRAY' ) {
  0         0  
53             @{ $_[0] } = @$data;
54             }
55 0         0 elsif( $type eq 'SCALAR' ) {
  0         0  
56             ${ $_[0] } = $$data;
57             }
58 0         0 else {
59             die( "Unknown type: " . $type );
60             }
61 0         0  
62 0         0 return $_[0];
63             };
64             }
65             # 5.8.0's threads::shared is busted when threads are off
66             # and earlier Perls just don't have that module at all.
67 2     6   8 else {
  6         17  
68 2     1   6819 *share = sub { return $_[0] };
  1         3  
69             *lock = sub { 0 };
70             }
71             }
72              
73             #line 118
74              
75             our $Test = Test::Builder->new;
76              
77             sub new {
78             my($class) = shift;
79             $Test ||= $class->create;
80             return $Test;
81             }
82              
83             #line 140
84              
85             sub create {
86             my $class = shift;
87              
88             my $self = bless {}, $class;
89             $self->reset;
90              
91             return $self;
92             }
93              
94             #line 169
95              
96             sub child {
97             my( $self, $name ) = @_;
98              
99             if( $self->{Child_Name} ) {
100             $self->croak("You already have a child named ($self->{Child_Name}) running");
101             }
102              
103             my $child = bless {}, ref $self;
104             $child->reset;
105              
106             # Add to our indentation
107             $child->_indent( $self->_indent . ' ' );
108             $child->{$_} = $self->{$_} foreach qw{Out_FH Todo_FH Fail_FH};
109              
110             # This will be reset in finalize. We do this here lest one child failure
111             # cause all children to fail.
112             $child->{Child_Error} = $?;
113             $? = 0;
114             $child->{Parent} = $self;
115             $child->{Name} = $name || "Child of " . $self->name;
116             $self->{Child_Name} = $child->name;
117             return $child;
118             }
119              
120              
121             #line 202
122 6     6 1 19  
123 6   66     49 sub subtest {
124 6         19 my $self = shift;
125             my($name, $subtests) = @_;
126              
127             if ('CODE' ne ref $subtests) {
128             $self->croak("subtest()'s second argument must be a code ref");
129             }
130              
131             # Turn the child into the parent so anyone who has stored a copy of
132             # the Test::Builder singleton will get the child.
133             my $child = $self->child($name);
134             my %parent = %$self;
135             %$self = %$child;
136              
137             my $error;
138             if( !eval { $subtests->(); 1 } ) {
139             $error = $@;
140             }
141              
142 2     2 1 5 # Restore the parent and the copied child.
143             %$child = %$self;
144 2         7 %$self = %parent;
145 2         11  
146             # Die *after* we restore the parent.
147 2         9 die $error if $error and !eval { $error->isa('Test::Builder::Exception') };
148              
149             return $child->finalize;
150             }
151              
152              
153             #line 251
154              
155             sub finalize {
156             my $self = shift;
157              
158             return unless $self->parent;
159             if( $self->{Child_Name} ) {
160             $self->croak("Can't call finalize() with child ($self->{Child_Name}) active");
161             }
162             $self->_ending;
163              
164             # XXX This will only be necessary for TAP envelopes (we think)
165             #$self->_print( $self->is_passing ? "PASS\n" : "FAIL\n" );
166              
167             my $ok = 1;
168             $self->parent->{Child_Name} = undef;
169             if ( $self->{Skip_All} ) {
170             $self->parent->skip($self->{Skip_All});
171 0     0 1 0 }
172             elsif ( not @{ $self->{Test_Results} } ) {
173 0 0       0 $self->parent->ok( 0, sprintf q[No tests run for subtest "%s"], $self->name );
174 0         0 }
175             else {
176             $self->parent->ok( $self->is_passing, $self->name );
177 0         0 }
178 0         0 $? = $self->{Child_Error};
179             delete $self->{Parent};
180              
181 0         0 return $self->is_passing;
182 0         0 }
183              
184             sub _indent {
185             my $self = shift;
186 0         0  
187 0         0 if( @_ ) {
188 0         0 $self->{Indent} = shift;
189 0   0     0 }
190 0         0  
191 0         0 return $self->{Indent};
192             }
193              
194             #line 301
195              
196             sub parent { shift->{Parent} }
197              
198             #line 313
199              
200             sub name { shift->{Name} }
201              
202             sub DESTROY {
203             my $self = shift;
204 0     0 1 0 if ( $self->parent ) {
205 0         0 my $name = $self->name;
206             $self->diag(<<"FAIL");
207 0 0       0 Child ($name) exited without calling finalize()
208 0         0 FAIL
209             $self->parent->{In_Destroy} = 1;
210             $self->parent->ok(0, $name);
211             }
212             }
213 0         0  
214 0         0 #line 337
215 0         0  
216             our $Level;
217 0         0  
218 0 0       0 sub reset { ## no critic (Subroutines::ProhibitBuiltinHomonyms)
  0         0  
  0         0  
219 0         0 my($self) = @_;
220              
221             # We leave this a global because it has to be localized and localizing
222             # hash keys is just asking for pain. Also, it was documented.
223 0         0 $Level = 1;
224 0         0  
225             $self->{Name} = $0;
226             $self->is_passing(1);
227 0 0 0     0 $self->{Ending} = 0;
  0         0  
228             $self->{Have_Plan} = 0;
229 0         0 $self->{No_Plan} = 0;
230             $self->{Have_Output_Plan} = 0;
231              
232             $self->{Original_Pid} = $$;
233             $self->{Child_Name} = undef;
234             $self->{Indent} ||= '';
235              
236             share( $self->{Curr_Test} );
237             $self->{Curr_Test} = 0;
238             $self->{Test_Results} = &share( [] );
239              
240             $self->{Exported_To} = undef;
241             $self->{Expected_Tests} = 0;
242              
243             $self->{Skip_All} = 0;
244              
245             $self->{Use_Nums} = 1;
246              
247             $self->{No_Header} = 0;
248             $self->{No_Ending} = 0;
249              
250             $self->{Todo} = undef;
251             $self->{Todo_Stack} = [];
252             $self->{Start_Todo} = 0;
253 0     0 1 0 $self->{Opened_Testhandles} = 0;
254              
255 0 0       0 $self->_dup_stdhandles;
256 0 0       0  
257 0         0 return;
258             }
259 0         0  
260             #line 415
261              
262             my %plan_cmds = (
263             no_plan => \&no_plan,
264 0         0 skip_all => \&skip_all,
265 0         0 tests => \&_plan_tests,
266 0 0       0 );
  0 0       0  
267 0         0  
268             sub plan {
269             my( $self, $cmd, $arg ) = @_;
270 0         0  
271             return unless $cmd;
272              
273 0         0 local $Level = $Level + 1;
274              
275 0         0 $self->croak("You tried to plan twice") if $self->{Have_Plan};
276 0         0  
277             if( my $method = $plan_cmds{$cmd} ) {
278 0         0 local $Level = $Level + 1;
279             $self->$method($arg);
280             }
281             else {
282 3     3   5 my @args = grep { defined } ( $cmd, $arg );
283             $self->croak("plan() doesn't understand @args");
284 3 50       17 }
285 0         0  
286             return 1;
287             }
288 3         1446  
289              
290             sub _plan_tests {
291             my($self, $arg) = @_;
292              
293             if($arg) {
294             local $Level = $Level + 1;
295             return $self->expected_tests($arg);
296             }
297             elsif( !defined $arg ) {
298             $self->croak("Got an undefined number of tests");
299             }
300             else {
301             $self->croak("You said to run 0 tests");
302 2     2 1 12 }
303              
304             return;
305             }
306              
307              
308             #line 471
309              
310             sub expected_tests {
311             my $self = shift;
312             my($max) = @_;
313              
314 0     0 1 0 if(@_) {
315             $self->croak("Number of tests must be a positive integer. You gave it '$max'")
316             unless $max =~ /^\+?\d+$/;
317 0     0   0  
318 0 0       0 $self->{Expected_Tests} = $max;
319 0         0 $self->{Have_Plan} = 1;
320 0         0  
321             $self->_output_plan($max) unless $self->no_header;
322             }
323 0         0 return $self->{Expected_Tests};
324 0         0 }
325              
326             #line 495
327              
328             sub no_plan {
329             my($self, $arg) = @_;
330              
331             $self->carp("no_plan takes no arguments") if $arg;
332              
333             $self->{No_Plan} = 1;
334             $self->{Have_Plan} = 1;
335              
336             return 1;
337             }
338              
339              
340             #line 529
341 2     2 1 3  
342             sub _output_plan {
343             my($self, $max, $directive, $reason) = @_;
344              
345 2         4 $self->carp("The plan was already output") if $self->{Have_Output_Plan};
346              
347 2         24 my $plan = "1..$max";
348 2         8 $plan .= " # $directive" if defined $directive;
349 2         4 $plan .= " $reason" if defined $reason;
350 2         5  
351 2         5 $self->_print("$plan\n");
352 2         5  
353             $self->{Have_Output_Plan} = 1;
354 2         25  
355 2         7 return;
356 2   50     18 }
357              
358 2         11 #line 580
359 2         5  
360 2         7 sub done_testing {
361             my($self, $num_tests) = @_;
362 2         5  
363 2         5 # If done_testing() specified the number of tests, shut off no_plan.
364             if( defined $num_tests ) {
365 2         4 $self->{No_Plan} = 0;
366             }
367 2         4 else {
368             $num_tests = $self->current_test;
369 2         9 }
370 2         4  
371             if( $self->{Done_Testing} ) {
372 2         5 my($file, $line) = @{$self->{Done_Testing}}[1,2];
373 2         5 $self->ok(0, "done_testing() was already called at $file line $line");
374 2         4 return;
375 2         5 }
376              
377 2         7 $self->{Done_Testing} = [caller];
378              
379 2         2 if( $self->expected_tests && $num_tests != $self->expected_tests ) {
380             $self->ok(0, "planned to run @{[ $self->expected_tests ]} ".
381             "but done_testing() expects $num_tests");
382             }
383             else {
384             $self->{Expected_Tests} = $num_tests;
385             }
386              
387             $self->_output_plan($num_tests) unless $self->{Have_Output_Plan};
388              
389             $self->{Have_Plan} = 1;
390              
391             # The wrong number of tests were run
392             $self->is_passing(0) if $self->{Expected_Tests} != $self->{Curr_Test};
393              
394             # No tests were run
395             $self->is_passing(0) if $self->{Curr_Test} == 0;
396              
397             return 1;
398             }
399              
400              
401             #line 631
402              
403             sub has_plan {
404             my $self = shift;
405              
406             return( $self->{Expected_Tests} ) if $self->{Expected_Tests};
407             return('no_plan') if $self->{No_Plan};
408             return(undef);
409             }
410              
411             #line 648
412              
413             sub skip_all {
414             my( $self, $reason ) = @_;
415              
416             $self->{Skip_All} = $self->parent ? $reason : 1;
417              
418             $self->_output_plan(0, "SKIP", $reason) unless $self->no_header;
419             if ( $self->parent ) {
420             die bless {} => 'Test::Builder::Exception';
421             }
422             exit(0);
423 1     1 1 2 }
424              
425 1 50       4 #line 673
426              
427 1         2 sub exported_to {
428             my( $self, $pack ) = @_;
429 1 50       3  
430             if( defined $pack ) {
431 1 50       4 $self->{Exported_To} = $pack;
432 1         2 }
433 1         3 return $self->{Exported_To};
434             }
435              
436 0         0 #line 703
  0         0  
437 0         0  
438             sub ok {
439             my( $self, $test, $name ) = @_;
440 1         3  
441             if ( $self->{Child_Name} and not $self->{In_Destroy} ) {
442             $name = 'unnamed test' unless defined $name;
443             $self->is_passing(0);
444             $self->croak("Cannot run test ($name) with active children");
445 1     1   2 }
446             # $test might contain an object which we don't want to accidentally
447 1 50       3 # store, so we turn it into a boolean.
    0          
448 1         1 $test = $test ? 1 : 0;
449 1         5  
450             lock $self->{Curr_Test};
451             $self->{Curr_Test}++;
452 0         0  
453             # In case $name is a string overloaded object, force it to stringify.
454             $self->_unoverload_str( \$name );
455 0         0  
456             $self->diag(<<"ERR") if defined $name and $name =~ /^[\d\s]+$/;
457             You named your test '$name'. You shouldn't use numbers for your test names.
458 0         0 Very confusing.
459             ERR
460              
461             # Capture the value of $TODO for the rest of this ok() call
462             # so it can more easily be found by other routines.
463             my $todo = $self->todo();
464             my $in_todo = $self->in_todo;
465             local $self->{Todo} = $todo if $in_todo;
466              
467             $self->_unoverload_str( \$todo );
468              
469             my $out;
470             my $result = &share( {} );
471              
472             unless($test) {
473 1     1 1 1 $out .= "not ";
474 1         2 @$result{ 'ok', 'actual_ok' } = ( ( $self->in_todo ? 1 : 0 ), 0 );
475             }
476 1 50       3 else {
477 1 50       6 @$result{ 'ok', 'actual_ok' } = ( 1, $test );
478             }
479              
480 1         2 $out .= "ok";
481 1         36 $out .= " $self->{Curr_Test}" if $self->use_numbers;
482              
483 1 50       4 if( defined $name ) {
484             $name =~ s|#|\\#|g; # # in a name can confuse Test::Harness.
485 1         3 $out .= " - $name";
486             $result->{name} = $name;
487             }
488             else {
489             $result->{name} = '';
490             }
491              
492             if( $self->in_todo ) {
493             $out .= " # TODO $todo";
494             $result->{reason} = $todo;
495             $result->{type} = 'todo';
496             }
497 0     0 1 0 else {
498             $result->{reason} = '';
499 0 0       0 $result->{type} = '';
500             }
501 0         0  
502 0         0 $self->{Test_Results}[ $self->{Curr_Test} - 1 ] = $result;
503             $out .= "\n";
504 0         0  
505             $self->_print($out);
506              
507             unless($test) {
508             my $msg = $self->in_todo ? "Failed (TODO)" : "Failed";
509             $self->_print_to_fh( $self->_diag_fh, "\n" ) if $ENV{HARNESS_ACTIVE};
510              
511             my( undef, $file, $line ) = $self->caller;
512             if( defined $name ) {
513             $self->diag(qq[ $msg test '$name'\n]);
514             $self->diag(qq[ at $file line $line.\n]);
515             }
516             else {
517             $self->diag(qq[ $msg test at $file line $line.\n]);
518             }
519             }
520              
521             $self->is_passing(0) unless $test || $self->in_todo;
522              
523             # Check that we haven't violated the plan
524             $self->_check_is_passing_plan();
525              
526             return $test ? 1 : 0;
527             }
528              
529              
530             # Check that we haven't yet violated the plan and set
531 2     2   5 # is_passing() accordingly
532             sub _check_is_passing_plan {
533 2 50       12 my $self = shift;
534              
535 2         7 my $plan = $self->has_plan;
536 2 100       8 return unless defined $plan; # no plan yet defined
537 2 100       9 return unless $plan !~ /\D/; # no numeric plan
538             $self->is_passing(0) if $plan < $self->{Curr_Test};
539 2         27 }
540              
541 2         7  
542             sub _unoverload {
543 2         7 my $self = shift;
544             my $type = shift;
545              
546             $self->_try(sub { require overload; }, die_on_fail => 1);
547              
548             foreach my $thing (@_) {
549             if( $self->_is_object($$thing) ) {
550             if( my $string_meth = overload::Method( $$thing, $type ) ) {
551             $$thing = $$thing->$string_meth();
552             }
553             }
554             }
555              
556             return;
557             }
558              
559             sub _is_object {
560             my( $self, $thing ) = @_;
561              
562             return $self->_try( sub { ref $thing && $thing->isa('UNIVERSAL') } ) ? 1 : 0;
563             }
564              
565             sub _unoverload_str {
566             my $self = shift;
567              
568             return $self->_unoverload( q[""], @_ );
569             }
570              
571             sub _unoverload_num {
572             my $self = shift;
573              
574             $self->_unoverload( '0+', @_ );
575              
576             for my $val (@_) {
577             next unless $self->_is_dualvar($$val);
578             $$val = $$val + 0;
579             }
580              
581             return;
582 0     0 1 0 }
583              
584             # This is a hack to detect a dualvar such as $!
585 0 0       0 sub _is_dualvar {
586 0         0 my( $self, $val ) = @_;
587              
588             # Objects are not dualvars.
589 0         0 return 0 if ref $val;
590              
591             no warnings 'numeric';
592 0 0       0 my $numval = $val + 0;
593 0         0 return $numval != 0 and $numval ne $val ? 1 : 0;
  0         0  
594 0         0 }
595 0         0  
596             #line 877
597              
598 0         0 sub is_eq {
599             my( $self, $got, $expect, $name ) = @_;
600 0 0 0     0 local $Level = $Level + 1;
601 0         0  
  0         0  
602             $self->_unoverload_str( \$got, \$expect );
603              
604             if( !defined $got || !defined $expect ) {
605 0         0 # undef only matches undef and nothing else
606             my $test = !defined $got && !defined $expect;
607              
608 0 0       0 $self->ok( $test, $name );
609             $self->_is_diag( $got, 'eq', $expect ) unless $test;
610 0         0 return $test;
611             }
612              
613 0 0       0 return $self->cmp_ok( $got, 'eq', $expect, $name );
614             }
615              
616 0 0       0 sub is_num {
617             my( $self, $got, $expect, $name ) = @_;
618 0         0 local $Level = $Level + 1;
619              
620             $self->_unoverload_num( \$got, \$expect );
621              
622             if( !defined $got || !defined $expect ) {
623             # undef only matches undef and nothing else
624             my $test = !defined $got && !defined $expect;
625              
626             $self->ok( $test, $name );
627             $self->_is_diag( $got, '==', $expect ) unless $test;
628             return $test;
629             }
630              
631             return $self->cmp_ok( $got, '==', $expect, $name );
632             }
633 1     1 1 2  
634             sub _diag_fmt {
635 1 50       4 my( $self, $type, $val ) = @_;
636 0 0       0  
637 0         0 if( defined $$val ) {
638             if( $type eq 'eq' or $type eq 'ne' ) {
639             # quote and force string context
640             $$val = "'$$val'";
641             }
642             else {
643             # force numeric context
644             $self->_unoverload_num($val);
645             }
646             }
647             else {
648             $$val = 'undef';
649             }
650 1     1 1 3  
651             return;
652 1 50       7 }
653              
654 1 50       5 sub _is_diag {
655 1 50       5 my( $self, $got, $type, $expect ) = @_;
656 0         0  
657             $self->_diag_fmt( $type, $_ ) for \$got, \$expect;
658 1         201939  
659             local $Level = $Level + 1;
660             return $self->diag(<<"DIAGNOSTIC");
661             got: $got
662             expected: $expect
663             DIAGNOSTIC
664              
665             }
666              
667             sub _isnt_diag {
668             my( $self, $got, $type ) = @_;
669              
670             $self->_diag_fmt( $type, \$got );
671              
672             local $Level = $Level + 1;
673             return $self->diag(<<"DIAGNOSTIC");
674             got: $got
675 2     2 1 4 expected: anything else
676             DIAGNOSTIC
677 2 50       10 }
678 2         6  
679             #line 974
680 2         5  
681             sub isnt_eq {
682             my( $self, $got, $dont_expect, $name ) = @_;
683             local $Level = $Level + 1;
684              
685             if( !defined $got || !defined $dont_expect ) {
686             # undef only matches undef and nothing else
687             my $test = defined $got || defined $dont_expect;
688              
689             $self->ok( $test, $name );
690             $self->_isnt_diag( $got, 'ne' ) unless $test;
691             return $test;
692             }
693              
694             return $self->cmp_ok( $got, 'ne', $dont_expect, $name );
695             }
696              
697             sub isnt_num {
698             my( $self, $got, $dont_expect, $name ) = @_;
699             local $Level = $Level + 1;
700              
701             if( !defined $got || !defined $dont_expect ) {
702             # undef only matches undef and nothing else
703             my $test = defined $got || defined $dont_expect;
704              
705 1     1 1 3 $self->ok( $test, $name );
706             $self->_isnt_diag( $got, '!=' ) unless $test;
707 1 50 33     7 return $test;
708 0 0       0 }
709 0         0  
710 0         0 return $self->cmp_ok( $got, '!=', $dont_expect, $name );
711             }
712              
713             #line 1023
714 1 50       5  
715             sub like {
716 1         7 my( $self, $this, $regex, $name ) = @_;
717 1         3  
718             local $Level = $Level + 1;
719             return $self->_regex_ok( $this, $regex, '=~', $name );
720 1         7 }
721              
722 1 50 33     12 sub unlike {
723             my( $self, $this, $regex, $name ) = @_;
724              
725             local $Level = $Level + 1;
726             return $self->_regex_ok( $this, $regex, '!~', $name );
727             }
728              
729 1         5 #line 1047
730 1         4  
731 1 50       4 my %numeric_cmps = map { ( $_, 1 ) } ( "<", "<=", ">", ">=", "==", "!=", "<=>" );
732              
733 1         3 sub cmp_ok {
734             my( $self, $got, $type, $expect, $name ) = @_;
735 1         1  
736 1         4 my $test;
737             my $error;
738 1 50       3 {
739 0         0 ## no critic (BuiltinFunctions::ProhibitStringyEval)
740 0 0       0  
741             local( $@, $!, $SIG{__DIE__} ); # isolate eval
742              
743 1         5 my($pack, $file, $line) = $self->caller();
744              
745             $test = eval qq[
746 1         3 #line 1 "cmp_ok [from $file line $line]"
747 1 50       3 \$got $type \$expect;
748             ];
749 1 50       3 $error = $@;
750 1         3 }
751 1         3 local $Level = $Level + 1;
752 1         4 my $ok = $self->ok( $test, $name );
753              
754             # Treat overloaded objects as numbers if we're asked to do a
755 0         0 # numeric comparison.
756             my $unoverload
757             = $numeric_cmps{$type}
758 1 50       9 ? '_unoverload_num'
759 0         0 : '_unoverload_str';
760 0         0  
761 0         0 $self->diag(<<"END") if $error;
762             An error occurred while using $type:
763             ------------------------------------
764 1         3 $error
765 1         3 ------------------------------------
766             END
767              
768 1         4 unless($ok) {
769 1         2 $self->$unoverload( \$got, \$expect );
770              
771 1         9 if( $type =~ /^(eq|==)$/ ) {
772             $self->_is_diag( $got, $type, $expect );
773 1 50       10 }
774 0 0       0 elsif( $type =~ /^(ne|!=)$/ ) {
775 0 0       0 $self->_isnt_diag( $got, $type );
776             }
777 0         0 else {
778 0 0       0 $self->_cmp_diag( $got, $type, $expect );
779 0         0 }
780 0         0 }
781             return $ok;
782             }
783 0         0  
784             sub _cmp_diag {
785             my( $self, $got, $type, $expect ) = @_;
786              
787 1 50 33     4 $got = defined $got ? "'$got'" : 'undef';
788             $expect = defined $expect ? "'$expect'" : 'undef';
789              
790 1         3 local $Level = $Level + 1;
791             return $self->diag(<<"DIAGNOSTIC");
792 1 50       5 $got
793             $type
794             $expect
795             DIAGNOSTIC
796             }
797              
798             sub _caller_context {
799 1     1   2 my $self = shift;
800              
801 1         4 my( $pack, $file, $line ) = $self->caller(1);
802 1 50       2  
803 1 50       4 my $code = '';
804 1 50       4 $code .= "#line $line $file\n" if defined $file and defined $line;
805              
806             return $code;
807             }
808              
809 2     2   4 #line 1146
810 2         3  
811             sub BAIL_OUT {
812 2     2   13 my( $self, $reason ) = @_;
  2         1758  
813              
814 2         9 $self->{Bailed_Out} = 1;
815 2 50       7 $self->_print("Bail out! $reason");
816 0 0       0 exit 255;
817 0         0 }
818              
819             #line 1159
820              
821             {
822 2         5 no warnings 'once';
823             *BAILOUT = \&BAIL_OUT;
824             }
825              
826 2     2   4 #line 1173
827              
828 2 50   2   12 sub skip {
  2 50       8  
829             my( $self, $why ) = @_;
830             $why ||= '';
831             $self->_unoverload_str( \$why );
832 2     2   6  
833             lock( $self->{Curr_Test} );
834 2         7 $self->{Curr_Test}++;
835              
836             $self->{Test_Results}[ $self->{Curr_Test} - 1 ] = &share(
837             {
838 0     0   0 'ok' => 1,
839             actual_ok => 1,
840 0         0 name => '',
841             type => 'skip',
842 0         0 reason => $why,
843 0 0       0 }
844 0         0 );
845              
846             my $out = "ok";
847 0         0 $out .= " $self->{Curr_Test}" if $self->use_numbers;
848             $out .= " # skip";
849             $out .= " $why" if length $why;
850             $out .= "\n";
851              
852 0     0   0 $self->_print($out);
853              
854             return 1;
855 0 0       0 }
856              
857 2     2   20 #line 1214
  2         4  
  2         3079  
858 0         0  
859 0 0       0 sub todo_skip {
    0          
860             my( $self, $why ) = @_;
861             $why ||= '';
862              
863             lock( $self->{Curr_Test} );
864             $self->{Curr_Test}++;
865              
866             $self->{Test_Results}[ $self->{Curr_Test} - 1 ] = &share(
867             {
868             'ok' => 1,
869             actual_ok => 0,
870             name => '',
871             type => 'todo_skip',
872             reason => $why,
873             }
874             );
875              
876             my $out = "not ok";
877             $out .= " $self->{Curr_Test}" if $self->use_numbers;
878             $out .= " # TODO & SKIP $why\n";
879 0     0 1 0  
880 0         0 $self->_print($out);
881              
882 0         0 return 1;
883             }
884 0 0 0     0  
885             #line 1294
886 0   0     0  
887             sub maybe_regex {
888 0         0 my( $self, $regex ) = @_;
889 0 0       0 my $usable_regex = undef;
890 0         0  
891             return $usable_regex unless defined $regex;
892              
893 0         0 my( $re, $opts );
894              
895             # Check for qr/foo/
896             if( _is_qr($regex) ) {
897 0     0 1 0 $usable_regex = $regex;
898 0         0 }
899             # Check for '/foo/' or 'm,foo,'
900 0         0 elsif(( $re, $opts ) = $regex =~ m{^ /(.*)/ (\w*) $ }sx or
901             ( undef, $re, $opts ) = $regex =~ m,^ m([^\w\s]) (.+) \1 (\w*) $,sx
902 0 0 0     0 )
903             {
904 0   0     0 $usable_regex = length $opts ? "(?$opts)$re" : $re;
905             }
906 0         0  
907 0 0       0 return $usable_regex;
908 0         0 }
909              
910             sub _is_qr {
911 0         0 my $regex = shift;
912              
913             # is_regexp() checks for regexes in a robust manner, say if they're
914             # blessed.
915 0     0   0 return re::is_regexp($regex) if defined &re::is_regexp;
916             return ref $regex eq 'Regexp';
917 0 0       0 }
918 0 0 0     0  
919             sub _regex_ok {
920 0         0 my( $self, $this, $regex, $cmp, $name ) = @_;
921              
922             my $ok = 0;
923             my $usable_regex = $self->maybe_regex($regex);
924 0         0 unless( defined $usable_regex ) {
925             local $Level = $Level + 1;
926             $ok = $self->ok( 0, $name );
927             $self->diag(" '$regex' doesn't look much like a regex to me.");
928 0         0 return $ok;
929             }
930              
931 0         0 {
932             ## no critic (BuiltinFunctions::ProhibitStringyEval)
933              
934             my $test;
935 0     0   0 my $context = $self->_caller_context;
936              
937 0         0 local( $@, $!, $SIG{__DIE__} ); # isolate eval
938              
939 0         0 $test = eval $context . q{$test = $this =~ /$usable_regex/ ? 1 : 0};
940 0         0  
941             $test = !$test if $cmp eq '!~';
942              
943             local $Level = $Level + 1;
944             $ok = $self->ok( $test, $name );
945             }
946              
947             unless($ok) {
948 0     0   0 $this = defined $this ? "'$this'" : 'undef';
949             my $match = $cmp eq '=~' ? "doesn't match" : "matches";
950 0         0  
951             local $Level = $Level + 1;
952 0         0 $self->diag( sprintf <<'DIAGNOSTIC', $this, $match, $regex );
953 0         0 %s
954             %13s '%s'
955             DIAGNOSTIC
956              
957             }
958              
959             return $ok;
960             }
961              
962             # I'm not ready to publish this. It doesn't deal with array return
963             # values from the code or context.
964              
965             #line 1390
966              
967             sub _try {
968             my( $self, $code, %opts ) = @_;
969              
970             my $error;
971             my $return;
972             {
973             local $!; # eval can mess up $!
974             local $@; # don't set $@ in the test
975             local $SIG{__DIE__}; # don't trip an outside DIE handler.
976 0     0 1 0 $return = eval { $code->() };
977 0         0 $error = $@;
978             }
979 0 0 0     0  
980             die $error if $error and $opts{die_on_fail};
981 0   0     0  
982             return wantarray ? ( $return, $error ) : $return;
983 0         0 }
984 0 0       0  
985 0         0 #line 1419
986              
987             sub is_fh {
988 0         0 my $self = shift;
989             my $maybe_fh = shift;
990             return 0 unless defined $maybe_fh;
991              
992 0     0 1 0 return 1 if ref $maybe_fh eq 'GLOB'; # its a glob ref
993 0         0 return 1 if ref \$maybe_fh eq 'GLOB'; # its a glob
994              
995 0 0 0     0 return eval { $maybe_fh->isa("IO::Handle") } ||
996             eval { tied($maybe_fh)->can('TIEHANDLE') };
997 0   0     0 }
998              
999 0         0 #line 1462
1000 0 0       0  
1001 0         0 sub level {
1002             my( $self, $level ) = @_;
1003              
1004 0         0 if( defined $level ) {
1005             $Level = $level;
1006             }
1007             return $Level;
1008             }
1009              
1010             #line 1494
1011              
1012             sub use_numbers {
1013             my( $self, $use_nums ) = @_;
1014              
1015             if( defined $use_nums ) {
1016             $self->{Use_Nums} = $use_nums;
1017             }
1018             return $self->{Use_Nums};
1019             }
1020              
1021             #line 1527
1022              
1023             foreach my $attribute (qw(No_Header No_Ending No_Diag)) {
1024             my $method = lc $attribute;
1025 0     0 1 0  
1026             my $code = sub {
1027 0         0 my( $self, $no ) = @_;
1028 0         0  
1029             if( defined $no ) {
1030             $self->{$attribute} = $no;
1031             }
1032 0     0 1 0 return $self->{$attribute};
1033             };
1034 0         0  
1035 0         0 no strict 'refs'; ## no critic
1036             *{ __PACKAGE__ . '::' . $method } = $code;
1037             }
1038              
1039             #line 1580
1040              
1041             sub diag {
1042             my $self = shift;
1043              
1044             $self->_print_comment( $self->_diag_fh, @_ );
1045             }
1046              
1047             #line 1595
1048              
1049             sub note {
1050             my $self = shift;
1051 0     0 1 0  
1052             $self->_print_comment( $self->output, @_ );
1053 0         0 }
1054              
1055             sub _diag_fh {
1056             my $self = shift;
1057              
1058 0         0 local $Level = $Level + 1;
  0         0  
1059             return $self->in_todo ? $self->todo_output : $self->failure_output;
1060 0         0 }
1061              
1062 0         0 sub _print_comment {
1063             my( $self, $fh, @msgs ) = @_;
1064              
1065             return if $self->no_diag;
1066 0         0 return unless @msgs;
1067              
1068 0         0 # Prevent printing headers when compiling (i.e. -c)
1069 0         0 return if $^C;
1070              
1071             # Smash args together like print does.
1072             # Convert undef to 'undef' so its readable.
1073 0 0       0 my $msg = join '', map { defined($_) ? $_ : 'undef' } @msgs;
1074              
1075             # Escape the beginning, _print will take care of the rest.
1076             $msg =~ s/^/# /;
1077              
1078 0 0       0 local $Level = $Level + 1;
1079             $self->_print_to_fh( $fh, $msg );
1080              
1081             return 0;
1082             }
1083              
1084             #line 1645
1085 0 0       0  
1086 0         0 sub explain {
1087             my $self = shift;
1088 0 0       0  
    0          
1089 0         0 return map {
1090             ref $_
1091             ? do {
1092 0         0 $self->_try(sub { require Data::Dumper }, die_on_fail => 1);
1093              
1094             my $dumper = Data::Dumper->new( [$_] );
1095 0         0 $dumper->Indent(1)->Terse(1);
1096             $dumper->Sortkeys(1) if $dumper->can("Sortkeys");
1097             $dumper->Dump;
1098 0         0 }
1099             : $_
1100             } @_;
1101             }
1102 0     0   0  
1103             #line 1674
1104 0 0       0  
1105 0 0       0 sub _print {
1106             my $self = shift;
1107 0         0 return $self->_print_to_fh( $self->output, @_ );
1108 0         0 }
1109              
1110             sub _print_to_fh {
1111             my( $self, $fh, @msgs ) = @_;
1112              
1113             # Prevent printing headers when only compiling. Mostly for when
1114             # tests are deparsed with B::Deparse
1115             return if $^C;
1116 0     0   0  
1117             my $msg = join '', @msgs;
1118 0         0  
1119             local( $\, $", $, ) = ( undef, ' ', '' );
1120 0         0  
1121 0 0 0     0 # Escape each line after the first with a # so we don't
1122             # confuse Test::Harness.
1123 0         0 $msg =~ s{\n(?!\z)}{\n# }sg;
1124              
1125             # Stick a newline on the end if it needs it.
1126             $msg .= "\n" unless $msg =~ /\n\z/;
1127              
1128             if ( Encode::is_utf8($msg) ) {
1129             return print $fh $self->_indent, Encode::encode_utf8($msg);
1130             } else {
1131             return print $fh $self->_indent, $msg;
1132             }
1133             }
1134              
1135             #line 1737
1136              
1137             sub output {
1138             my( $self, $fh ) = @_;
1139              
1140             if( defined $fh ) {
1141             $self->{Out_FH} = $self->_new_fh($fh);
1142             }
1143             return $self->{Out_FH};
1144             }
1145              
1146             sub failure_output {
1147             my( $self, $fh ) = @_;
1148 0     0 1 0  
1149             if( defined $fh ) {
1150 0         0 $self->{Fail_FH} = $self->_new_fh($fh);
1151 0         0 }
1152 0         0 return $self->{Fail_FH};
1153             }
1154              
1155             sub todo_output {
1156             my( $self, $fh ) = @_;
1157              
1158             if( defined $fh ) {
1159             $self->{Todo_FH} = $self->_new_fh($fh);
1160             }
1161 2     2   13 return $self->{Todo_FH};
  2         4  
  2         2383  
1162             }
1163              
1164             sub _new_fh {
1165             my $self = shift;
1166             my($file_or_fh) = shift;
1167              
1168             my $fh;
1169             if( $self->is_fh($file_or_fh) ) {
1170             $fh = $file_or_fh;
1171             }
1172             elsif( ref $file_or_fh eq 'SCALAR' ) {
1173             # Scalar refs as filehandles was added in 5.8.
1174             if( $] >= 5.008 ) {
1175 0     0 1 0 open $fh, ">>", $file_or_fh
1176 0   0     0 or $self->croak("Can't open scalar ref $file_or_fh: $!");
1177 0         0 }
1178             # Emulate scalar ref filehandles with a tie.
1179 0         0 else {
1180 0         0 $fh = Test::Builder::IO::Scalar->new($file_or_fh)
1181             or $self->croak("Can't tie scalar ref $file_or_fh");
1182 0         0 }
1183             }
1184             else {
1185             open $fh, ">", $file_or_fh
1186             or $self->croak("Can't open test output log $file_or_fh: $!");
1187             _autoflush($fh);
1188             }
1189              
1190             return $fh;
1191             }
1192 0         0  
1193 0 0       0 sub _autoflush {
1194 0         0 my($fh) = shift;
1195 0 0       0 my $old_fh = select $fh;
1196 0         0 $| = 1;
1197             select $old_fh;
1198 0         0  
1199             return;
1200 0         0 }
1201              
1202             my( $Testout, $Testerr );
1203              
1204             sub _dup_stdhandles {
1205             my $self = shift;
1206              
1207             $self->_open_testhandles;
1208              
1209             # Set everything to unbuffered else plain prints to STDOUT will
1210             # come out in the wrong order from our own prints.
1211             _autoflush($Testout);
1212             _autoflush( \*STDOUT );
1213             _autoflush($Testerr);
1214             _autoflush( \*STDERR );
1215              
1216 0     0 1 0 $self->reset_outputs;
1217 0   0     0  
1218             return;
1219 0         0 }
1220 0         0  
1221             sub _open_testhandles {
1222 0         0 my $self = shift;
1223              
1224             return if $self->{Opened_Testhandles};
1225              
1226             # We dup STDOUT and STDERR so people can change them in their
1227             # test suites while still getting normal test output.
1228             open( $Testout, ">&STDOUT" ) or die "Can't dup STDOUT: $!";
1229             open( $Testerr, ">&STDERR" ) or die "Can't dup STDERR: $!";
1230              
1231             # $self->_copy_io_layers( \*STDOUT, $Testout );
1232 0         0 # $self->_copy_io_layers( \*STDERR, $Testerr );
1233 0 0       0  
1234 0         0 $self->{Opened_Testhandles} = 1;
1235              
1236 0         0 return;
1237             }
1238 0         0  
1239             sub _copy_io_layers {
1240             my( $self, $src, $dst ) = @_;
1241              
1242             $self->_try(
1243             sub {
1244             require PerlIO;
1245             my @src_layers = PerlIO::get_layers($src);
1246              
1247             binmode $dst, join " ", map ":$_", @src_layers if @src_layers;
1248             }
1249             );
1250              
1251             return;
1252             }
1253              
1254             #line 1862
1255              
1256             sub reset_outputs {
1257             my $self = shift;
1258              
1259             $self->output ($Testout);
1260             $self->failure_output($Testerr);
1261             $self->todo_output ($Testout);
1262              
1263             return;
1264             }
1265              
1266             #line 1888
1267              
1268             sub _message_at_caller {
1269             my $self = shift;
1270              
1271             local $Level = $Level + 1;
1272             my( $pack, $file, $line ) = $self->caller;
1273             return join( "", @_ ) . " at $file line $line.\n";
1274             }
1275              
1276             sub carp {
1277             my $self = shift;
1278             return warn $self->_message_at_caller(@_);
1279             }
1280              
1281             sub croak {
1282             my $self = shift;
1283             return die $self->_message_at_caller(@_);
1284             }
1285              
1286              
1287             #line 1928
1288              
1289             sub current_test {
1290             my( $self, $num ) = @_;
1291              
1292             lock( $self->{Curr_Test} );
1293             if( defined $num ) {
1294             $self->{Curr_Test} = $num;
1295              
1296 0     0 1 0 # If the test counter is being pushed forward fill in the details.
1297 0         0 my $test_results = $self->{Test_Results};
1298             if( $num > @$test_results ) {
1299 0 0       0 my $start = @$test_results ? @$test_results : 0;
1300             for( $start .. $num - 1 ) {
1301 0         0 $test_results->[$_] = &share(
1302             {
1303             'ok' => 1,
1304 0 0 0     0 actual_ok => undef,
    0          
1305 0         0 reason => 'incrementing test number',
1306             type => 'unknown',
1307             name => undef
1308             }
1309             );
1310             }
1311             }
1312 0 0       0 # If backward, wipe history. Its their funeral.
1313             elsif( $num < @$test_results ) {
1314             $#{$test_results} = $num - 1;
1315 0         0 }
1316             }
1317             return $self->{Curr_Test};
1318             }
1319 0     0   0  
1320             #line 1976
1321              
1322             sub is_passing {
1323 0 0       0 my $self = shift;
1324 0         0  
1325             if( @_ ) {
1326             $self->{Is_Passing} = shift;
1327             }
1328 0     0   0  
1329             return $self->{Is_Passing};
1330 0         0 }
1331 0         0  
1332 0 0       0  
1333 0         0 #line 1998
1334 0         0  
1335 0         0 sub summary {
1336 0         0 my($self) = shift;
1337              
1338             return map { $_->{'ok'} } @{ $self->{Test_Results} };
1339             }
1340              
1341             #line 2053
1342 0         0  
  0         0  
1343 0         0 sub details {
1344             my $self = shift;
1345 0         0 return @{ $self->{Test_Results} };
1346             }
1347 0         0  
1348             #line 2082
1349 0 0       0  
1350             sub todo {
1351 0         0 my( $self, $pack ) = @_;
1352 0         0  
1353             return $self->{Todo} if defined $self->{Todo};
1354              
1355 0 0       0 local $Level = $Level + 1;
1356 0 0       0 my $todo = $self->find_TODO($pack);
1357 0 0       0 return $todo if defined $todo;
1358              
1359 0         0 return '';
1360 0         0 }
1361              
1362             #line 2104
1363              
1364             sub find_TODO {
1365             my( $self, $pack ) = @_;
1366              
1367 0         0 $pack = $pack || $self->caller(1) || $self->exported_to;
1368             return unless $pack;
1369              
1370             no strict 'refs'; ## no critic
1371             return ${ $pack . '::TODO' };
1372             }
1373              
1374             #line 2122
1375              
1376             sub in_todo {
1377             my $self = shift;
1378              
1379             local $Level = $Level + 1;
1380             return( defined $self->{Todo} || $self->find_TODO ) ? 1 : 0;
1381             }
1382              
1383             #line 2172
1384              
1385             sub todo_start {
1386             my $self = shift;
1387             my $message = @_ ? shift : '';
1388              
1389             $self->{Start_Todo}++;
1390             if( $self->in_todo ) {
1391             push @{ $self->{Todo_Stack} } => $self->todo;
1392 4     4   8 }
1393             $self->{Todo} = $message;
1394 4         6  
1395             return;
1396             }
1397 4         5  
  4         9  
1398 4         4 #line 2194
1399 4         12  
1400 4         6 sub todo_end {
  4         8  
1401 4         1020 my $self = shift;
1402              
1403             if( !$self->{Start_Todo} ) {
1404 4 50 33     11 $self->croak('todo_end() called without todo_start()');
1405             }
1406 4 50       25  
1407             $self->{Start_Todo}--;
1408              
1409             if( $self->{Start_Todo} && @{ $self->{Todo_Stack} } ) {
1410             $self->{Todo} = pop @{ $self->{Todo_Stack} };
1411             }
1412             else {
1413             delete $self->{Todo};
1414             }
1415              
1416             return;
1417             }
1418              
1419             #line 2227
1420              
1421 6     6 1 9 sub caller { ## no critic (Subroutines::ProhibitBuiltinHomonyms)
1422 6         7 my( $self, $height ) = @_;
1423 6 50       13 $height ||= 0;
1424              
1425 6 50       29 my $level = $self->level + $height + 1;
1426 0 0       0 my @caller;
1427             do {
1428             @caller = CORE::caller( $level );
1429 0   0     0 $level--;
1430             } until @caller;
1431             return wantarray ? @caller : $caller[0];
1432             }
1433              
1434             #line 2244
1435              
1436             #line 2258
1437              
1438             #'#
1439             sub _sanity_check {
1440             my $self = shift;
1441              
1442             $self->_whoa( $self->{Curr_Test} < 0, 'Says here you ran a negative number of tests!' );
1443             $self->_whoa( $self->{Curr_Test} != @{ $self->{Test_Results} },
1444             'Somehow you got a different number of results than tests ran!' );
1445              
1446             return;
1447             }
1448              
1449             #line 2279
1450              
1451             sub _whoa {
1452             my( $self, $check, $desc ) = @_;
1453             if($check) {
1454             local $Level = $Level + 1;
1455             $self->croak(<<"WHOA");
1456             WHOA! $desc
1457             This should never happen! Please contact the author immediately!
1458             WHOA
1459             }
1460              
1461             return;
1462             }
1463              
1464 3     3 1 3 #line 2303
1465              
1466 3 50       15 sub _my_exit {
1467 0         0 $? = $_[0]; ## no critic (Variables::RequireLocalizedPunctuationVars)
1468              
1469 3         6 return 1;
1470             }
1471              
1472             #line 2315
1473              
1474             sub _ending {
1475             my $self = shift;
1476             return if $self->no_ending;
1477             return if $self->{Ending}++;
1478              
1479             my $real_exit_code = $?;
1480              
1481             # Don't bother with an ending if this is a forked copy. Only the parent
1482             # should do the ending.
1483             if( $self->{Original_Pid} != $$ ) {
1484             return;
1485             }
1486              
1487             # Ran tests but never declared a plan or hit done_testing
1488             if( !$self->{Have_Plan} and $self->{Curr_Test} ) {
1489             $self->is_passing(0);
1490             $self->diag("Tests were run but no plan was declared and done_testing() was not seen.");
1491             }
1492              
1493             # Exit if plan() was never called. This is so "require Test::Simple"
1494             # doesn't puke.
1495             if( !$self->{Have_Plan} ) {
1496 1     1 1 2 return;
1497             }
1498 1 50       3  
1499 0         0 # Don't do an ending if we bailed out.
1500             if( $self->{Bailed_Out} ) {
1501 1         4 $self->is_passing(0);
1502             return;
1503             }
1504             # Figure out if we passed or failed and print helpful messages.
1505             my $test_results = $self->{Test_Results};
1506             if(@$test_results) {
1507             # The plan? We have no plan.
1508             if( $self->{No_Plan} ) {
1509             $self->_output_plan($self->{Curr_Test}) unless $self->no_header;
1510             $self->{Expected_Tests} = $self->{Curr_Test};
1511             }
1512              
1513             # Auto-extended arrays and elements which aren't explicitly
1514             # filled in with a shared reference will puke under 5.8.0
1515             # ithreads. So we have to fill them in by hand. :(
1516             my $empty_result = &share( {} );
1517             for my $idx ( 0 .. $self->{Expected_Tests} - 1 ) {
1518             $test_results->[$idx] = $empty_result
1519             unless defined $test_results->[$idx];
1520             }
1521              
1522             my $num_failed = grep !$_->{'ok'}, @{$test_results}[ 0 .. $self->{Curr_Test} - 1 ];
1523              
1524             my $num_extra = $self->{Curr_Test} - $self->{Expected_Tests};
1525              
1526             if( $num_extra != 0 ) {
1527             my $s = $self->{Expected_Tests} == 1 ? '' : 's';
1528             $self->diag(<<"FAIL");
1529             Looks like you planned $self->{Expected_Tests} test$s but ran $self->{Curr_Test}.
1530             FAIL
1531             $self->is_passing(0);
1532 4     4   11 }
1533              
1534 4 50       17 if($num_failed) {
1535 0         0 my $num_tests = $self->{Curr_Test};
1536             my $s = $num_failed == 1 ? '' : 's';
1537 4         40  
1538             my $qualifier = $num_extra == 0 ? '' : ' run';
1539              
1540 2     2   29 $self->diag(<<"FAIL");
  2         4  
  2         4046  
1541             Looks like you failed $num_failed test$s of $num_tests$qualifier.
1542             FAIL
1543             $self->is_passing(0);
1544             }
1545              
1546             if($real_exit_code) {
1547             $self->diag(<<"FAIL");
1548             Looks like your test exited with $real_exit_code just after $self->{Curr_Test}.
1549             FAIL
1550             $self->is_passing(0);
1551             _my_exit($real_exit_code) && return;
1552             }
1553              
1554             my $exit_code;
1555             if($num_failed) {
1556             $exit_code = $num_failed <= 254 ? $num_failed : 254;
1557             }
1558             elsif( $num_extra != 0 ) {
1559             $exit_code = 255;
1560             }
1561             else {
1562             $exit_code = 0;
1563             }
1564              
1565             _my_exit($exit_code) && return;
1566             }
1567             elsif( $self->{Skip_All} ) {
1568             _my_exit(0) && return;
1569             }
1570             elsif($real_exit_code) {
1571             $self->diag(<<"FAIL");
1572             Looks like your test exited with $real_exit_code before it could output anything.
1573             FAIL
1574             $self->is_passing(0);
1575             _my_exit($real_exit_code) && return;
1576             }
1577             else {
1578             $self->diag("No tests run!\n");
1579             $self->is_passing(0);
1580             _my_exit(255) && return;
1581             }
1582 0     0 1 0  
1583             $self->is_passing(0);
1584 0         0 $self->_whoa( 1, "We fell off the end of _ending()" );
1585             }
1586              
1587             END {
1588             $Test->_ending if defined $Test;
1589             }
1590              
1591             #line 2503
1592              
1593             1;
1594