File Coverage

blib/lib/Test/Leaner.pm
Criterion Covered Total %
statement 272 315 86.3
branch 107 158 67.7
condition 57 85 67.0
subroutine 49 52 94.2
pod 15 26 57.6
total 500 636 78.6


line stmt bran cond sub pod time code
1             package Test::Leaner;
2              
3 26     26   402631 use 5.006;
  26         101  
  26         1211  
4 26     26   619 use strict;
  26         62  
  26         836  
5 26     26   135 use warnings;
  26         134  
  26         1881  
6              
7             =head1 NAME
8              
9             Test::Leaner - A slimmer Test::More for when you favor performance over completeness.
10              
11             =head1 VERSION
12              
13             Version 0.05
14              
15             =cut
16              
17             our $VERSION = '0.05';
18              
19             =head1 SYNOPSIS
20              
21             use Test::Leaner tests => 10_000;
22             for (1 .. 10_000) {
23             ...
24             is $one, 1, "checking situation $_";
25             }
26              
27              
28             =head1 DESCRIPTION
29              
30             When profiling some L<Test::More>-based test script that contained about 10 000 unit tests, I realized that 60% of the time was spent in L<Test::Builder> itself, even though every single test actually involved a costly C<eval STRING>.
31              
32             This module aims to be a partial replacement to L<Test::More> in those situations where you want to run a large number of simple tests.
33             Its functions behave the same as their L<Test::More> counterparts, except for the following differences :
34              
35             =over 4
36              
37             =item *
38              
39             Stringification isn't forced on the test operands.
40             However, L</ok> honors C<'bool'> overloading, L</is> and L</is_deeply> honor C<'eq'> overloading (and just that one), L</isnt> honors C<'ne'> overloading, and L</cmp_ok> honors whichever overloading category corresponds to the specified operator.
41              
42             =item *
43              
44             L</pass>, L</fail>, L</ok>, L</is>, L</isnt>, L</like>, L</unlike>, L</cmp_ok> and L</is_deeply> are all guaranteed to return the truth value of the test.
45              
46             =item *
47              
48             C<isn't> (the sub C<t> in package C<isn>) is not aliased to L</isnt>.
49              
50             =item *
51              
52             L</like> and L</unlike> don't special case regular expressions that are passed as C<'/.../'> strings.
53             A string regexp argument is always treated as the source of the regexp, making C<like $text, $rx> and C<like $text, qr[$rx]> equivalent to each other and to C<cmp_ok $text, '=~', $rx> (and likewise for C<unlike>).
54              
55             =item *
56              
57             L</cmp_ok> throws an exception if the given operator isn't a valid Perl binary operator (except C<'='> and variants).
58             It also tests in scalar context, so C<'..'> will be treated as the flip-flop operator and not the range operator.
59              
60             =item *
61              
62             L</is_deeply> doesn't guard for memory cycles.
63             If the two first arguments present parallel memory cycles, the test may result in an infinite loop.
64              
65             =item *
66              
67             The tests don't output any kind of default diagnostic in case of failure ; the rationale being that if you have a large number of tests and a lot of them are failing, then you don't want to be flooded by diagnostics.
68             Moreover, this allows a much faster variant of L</is_deeply>.
69              
70             =item *
71              
72             C<use_ok>, C<require_ok>, C<can_ok>, C<isa_ok>, C<new_ok>, C<subtest>, C<explain>, C<TODO> blocks and C<todo_skip> are not implemented.
73              
74             =back
75              
76             =cut
77              
78 26     26   145 use Exporter ();
  26         64  
  26         2508  
79              
80             my $main_process;
81              
82             BEGIN {
83 26     26   234 $main_process = $$;
84              
85 26 50 33     372 if ("$]" >= 5.008 and $INC{'threads.pm'}) {
86 0         0 my $use_ithreads = do {
87 0         0 require Config;
88 26     26   139 no warnings 'once';
  26         54  
  26         4204  
89 0         0 $Config::Config{useithreads};
90             };
91 0 0       0 if ($use_ithreads) {
92 0         0 require threads::shared;
93 0         0 *THREADSAFE = sub () { 1 };
94             }
95             }
96 26 50       147 unless (defined &Test::Leaner::THREADSAFE) {
97             *THREADSAFE = sub () { 0 }
98 26         11365 }
99             }
100              
101             my ($TAP_STREAM, $DIAG_STREAM);
102              
103             my ($plan, $test, $failed, $no_diag, $done_testing);
104              
105             our @EXPORT = qw<
106             plan
107             skip
108             done_testing
109             pass
110             fail
111             ok
112             is
113             isnt
114             like
115             unlike
116             cmp_ok
117             is_deeply
118             diag
119             note
120             BAIL_OUT
121             >;
122              
123             =head1 ENVIRONMENT
124              
125             =head2 C<PERL_TEST_LEANER_USES_TEST_MORE>
126              
127             If this environment variable is set, L<Test::Leaner> will replace its functions by those from L<Test::More>.
128             Moreover, the symbols that are imported when you C<use Test::Leaner> will be those from L<Test::More>, but you can still only import the symbols originally defined in L<Test::Leaner> (hence the functions from L<Test::More> that are not implemented in L<Test::Leaner> will not be imported).
129             If your version of L<Test::More> is too old and doesn't have some symbols (like L</note> or L</done_testing>), they will be replaced in L<Test::Leaner> by croaking stubs.
130              
131             This may be useful if your L<Test::Leaner>-based test script fails and you want extra diagnostics.
132              
133             =cut
134              
135             sub _handle_import_args {
136 48     48   92 my @imports;
137              
138 48         91 my $i = 0;
139 48         239 while ($i <= $#_) {
140 54         107 my $item = $_[$i];
141 54         539 my $splice;
142 54 50       172 if (defined $item) {
143 54 100       202 if ($item eq 'import') {
    50          
144 37         59 push @imports, @{ $_[$i+1] };
  37         101  
145 37         74 $splice = 2;
146             } elsif ($item eq 'no_diag') {
147 0         0 lock $plan if THREADSAFE;
148 0         0 $no_diag = 1;
149 0         0 $splice = 1;
150             }
151             }
152 54 100       127 if ($splice) {
153 37         165 splice @_, $i, $splice;
154             } else {
155 17         52 ++$i;
156             }
157             }
158              
159 48         3649 return @imports;
160             }
161              
162             if ($ENV{PERL_TEST_LEANER_USES_TEST_MORE}) {
163             require Test::More;
164              
165             my $leaner_stash = \%Test::Leaner::;
166             my $more_stash = \%Test::More::;
167              
168             my %stubbed;
169              
170             for (@EXPORT) {
171             my $replacement = exists $more_stash->{$_} ? *{$more_stash->{$_}}{CODE}
172             : undef;
173             unless (defined $replacement) {
174             $stubbed{$_}++;
175             $replacement = sub {
176             @_ = ("$_ is not implemented in this version of Test::More");
177             goto &croak;
178             };
179             }
180 26     26   180 no warnings 'redefine';
  26         50  
  26         11154  
181             $leaner_stash->{$_} = $replacement;
182             }
183              
184             my $import = sub {
185 10     10   59707 my $class = shift;
186              
187 10         83 my @imports = &_handle_import_args;
188 10 100       55 if (@imports == grep /^!/, @imports) {
189             # All imports are negated, or @imports is empty
190 7         25 my %negated;
191 7   66     71 /^!(.*)/ and ++$negated{$1} for @imports;
192 7         139 push @imports, grep !$negated{$_}, @EXPORT;
193             }
194              
195 13         25 my @test_more_imports;
196 13         32 for (@imports) {
197 60 50 100     529 if ($stubbed{$_}) {
    100 100        
198 4         10 my $pkg = caller;
199 26     26   203 no strict 'refs';
  26         50  
  26         6835  
200 4         11 *{$pkg."::$_"} = $leaner_stash->{$_};
  4         121  
201             } elsif (/^!/ or !exists $more_stash->{$_} or exists $leaner_stash->{$_}) {
202 56         121 push @test_more_imports, $_;
203             } else {
204             # Croak for symbols in Test::More but not in Test::Leaner
205 2         294 Exporter::import($class, $_);
206             }
207             }
208              
209 9         83 my $test_more_import = 'Test::More'->can('import');
210 11 50       48 return unless $test_more_import;
211              
212 11         49 @_ = (
213             'Test::More',
214             @_,
215             import => \@test_more_imports,
216             );
217             {
218 11         26 lock $plan if THREADSAFE;
  12         16  
219 12 50       44 push @_, 'no_diag' if $no_diag;
220             }
221              
222 12         149 goto $test_more_import;
223             };
224              
225 26     26   162 no warnings 'redefine';
  26         72  
  26         4821  
226             *import = $import;
227              
228             return 1;
229             }
230              
231             sub NO_PLAN () { -1 }
232             sub SKIP_ALL () { -2 }
233              
234             BEGIN {
235 26     26   66 if (THREADSAFE) {
236             threads::shared::share($_) for $plan, $test, $failed, $no_diag, $done_testing;
237             }
238              
239 26         49 lock $plan if THREADSAFE;
240              
241 26         63 $plan = undef;
242 26         59 $test = 0;
243 26         30425 $failed = 0;
244             }
245              
246             sub carp {
247 0   0 0 0 0 my $level = 1 + ($Test::Builder::Level || 0);
248 0         0 my @caller;
249 0   0     0 do {
250 0         0 @caller = caller $level--;
251             } while (!@caller and $level >= 0);
252 0         0 my ($file, $line) = @caller[1, 2];
253 0         0 warn @_, " at $file line $line.\n";
254             }
255              
256             sub croak {
257 0   0 0 0 0 my $level = 1 + ($Test::Builder::Level || 0);
258 0         0 my @caller;
259 0   0     0 do {
260 0         0 @caller = caller $level--;
261             } while (!@caller and $level >= 0);
262 0         0 my ($file, $line) = @caller[1, 2];
263 0         0 die @_, " at $file line $line.\n";
264             }
265              
266             sub _sanitize_comment {
267 37     37   120 $_[0] =~ s/\n+\z//;
268 37         81 $_[0] =~ s/#/\\#/g;
269 37         89 $_[0] =~ s/\n/\n# /g;
270             }
271              
272             =head1 FUNCTIONS
273              
274             The following functions from L<Test::More> are implemented and exported by default.
275              
276             =head2 C<plan>
277              
278             plan tests => $count;
279             plan 'no_plan';
280             plan skip_all => $reason;
281              
282             See L<Test::More/plan>.
283              
284             =cut
285              
286             sub plan {
287 16     16 1 82 my ($key, $value) = @_;
288              
289 16 50       65 return unless $key;
290              
291 16         33 lock $plan if THREADSAFE;
292              
293 16 50       57 croak("You tried to plan twice") if defined $plan;
294              
295 16         26 my $plan_str;
296              
297 16 100       99 if ($key eq 'no_plan') {
    100          
    50          
298 3 50       12 croak("no_plan takes no arguments") if $value;
299 3         9 $plan = NO_PLAN;
300             } elsif ($key eq 'tests') {
301 10 50       33 croak("Got an undefined number of tests") unless defined $value;
302 10 50       36 croak("You said to run 0 tests") unless $value;
303 10 50       115 croak("Number of tests must be a positive integer. You gave it '$value'")
304             unless $value =~ /^\+?[0-9]+$/;
305 10         21 $plan = $value;
306 10         26 $plan_str = "1..$value";
307             } elsif ($key eq 'skip_all') {
308 3         4 $plan = SKIP_ALL;
309 3         5 $plan_str = '1..0 # SKIP';
310 3 50       14 if (defined $value) {
311 3         13 _sanitize_comment($value);
312 3 50       17 $plan_str .= " $value" if length $value;
313             }
314             } else {
315 0         0 my @args = grep defined, $key, $value;
316 0         0 croak("plan() doesn't understand @args");
317             }
318              
319 16 100       57 if (defined $plan_str) {
320 13         53 local $\;
321 13         4830 print $TAP_STREAM "$plan_str\n";
322             }
323              
324 16 100       2223 exit 0 if $plan == SKIP_ALL;
325              
326 13         43 return 1;
327             }
328              
329             sub import {
330 39     39   86619 my $class = shift;
331              
332 39         116 my @imports = &_handle_import_args;
333              
334 39 100       158 if (@_) {
335 9   50     61 local $Test::Builder::Level = ($Test::Builder::Level || 0) + 1;
336 9         25 &plan;
337             }
338              
339 38         123 @_ = ($class, @imports);
340 38         38762 goto &Exporter::import;
341             }
342              
343             =head2 C<skip>
344              
345             skip $reason => $count;
346              
347             See L<Test::More/skip>.
348              
349             =cut
350              
351             sub skip {
352 3     3 1 14 my ($reason, $count) = @_;
353              
354 3         4 lock $plan if THREADSAFE;
355              
356 3 50       16 if (not defined $count) {
    50          
357 0 0 0     0 carp("skip() needs to know \$how_many tests are in the block")
358             unless defined $plan and $plan == NO_PLAN;
359 0         0 $count = 1;
360             } elsif ($count =~ /[^0-9]/) {
361 0         0 carp('skip() was passed a non-numeric number of tests. Did you get the arguments backwards?');
362 0         0 $count = 1;
363             }
364              
365 3         7 for (1 .. $count) {
366 3         4 ++$test;
367              
368 3         20 my $skip_str = "ok $test # skip";
369 3 50       10 if (defined $reason) {
370 3         6 _sanitize_comment($reason);
371 3 50       12 $skip_str .= " $reason" if length $reason;
372             }
373              
374 3         8 local $\;
375 3         23 print $TAP_STREAM "$skip_str\n";
376             }
377              
378 26     26   192 no warnings 'exiting';
  26         48  
  26         18079  
379 3         14 last SKIP;
380             }
381              
382             =head2 C<done_testing>
383              
384             done_testing;
385             done_testing $count;
386              
387             See L<Test::More/done_testing>.
388              
389             =cut
390              
391             sub done_testing {
392 2     2 1 12 my ($count) = @_;
393              
394 2         5 lock $plan if THREADSAFE;
395              
396 2 100       15 $count = $test unless defined $count;
397 2 50       15 croak("Number of tests must be a positive integer. You gave it '$count'")
398             unless $count =~ /^\+?[0-9]+$/;
399              
400 2 100 66     22 if (not defined $plan or $plan == NO_PLAN) {
401 1         2 $plan = $count; # $plan can't be NO_PLAN anymore
402 1         3 $done_testing = 1;
403 1         4 local $\;
404 1         241 print $TAP_STREAM "1..$plan\n";
405             } else {
406 1 50       17 if ($done_testing) {
    50          
407 0         0 @_ = ('done_testing() was already called');
408 0         0 goto &fail;
409             } elsif ($plan != $count) {
410 0         0 @_ = ("planned to run $plan tests but done_testing() expects $count");
411 0         0 goto &fail;
412             }
413             }
414              
415 2         214 return 1;
416             }
417              
418             =head2 C<ok>
419              
420             ok $ok;
421             ok $ok, $desc;
422              
423             See L<Test::More/ok>.
424              
425             =cut
426              
427             sub ok ($;$) {
428 246     246 1 40804 my ($ok, $desc) = @_;
429              
430 246         259 lock $plan if THREADSAFE;
431              
432 246         312 ++$test;
433              
434 246         476 my $test_str = "ok $test";
435 246 100       650 $ok or do {
436 77         153 $test_str = "not $test_str";
437 77         132 ++$failed;
438             };
439 246 100       565 if (defined $desc) {
440 28         111 _sanitize_comment($desc);
441 28 50       143 $test_str .= " - $desc" if length $desc;
442             }
443              
444 246         669 local $\;
445 246         24679 print $TAP_STREAM "$test_str\n";
446              
447 246         4282 return $ok;
448             }
449              
450             =head2 C<pass>
451              
452             pass;
453             pass $desc;
454              
455             See L<Test::More/pass>.
456              
457             =cut
458              
459             sub pass (;$) {
460 17     17 1 1355 unshift @_, 1;
461 17         79 goto &ok;
462             }
463              
464             =head2 C<fail>
465              
466             fail;
467             fail $desc;
468              
469             See L<Test::More/fail>.
470              
471             =cut
472              
473             sub fail (;$) {
474 2     2 1 1299 unshift @_, 0;
475 2         8 goto &ok;
476             }
477              
478             =head2 C<is>
479              
480             is $got, $expected;
481             is $got, $expected, $desc;
482              
483             See L<Test::More/is>.
484              
485             =cut
486              
487             sub is ($$;$) {
488 4     4 1 24 my ($got, $expected, $desc) = @_;
489 26     26   196 no warnings 'uninitialized';
  26         79  
  26         4559  
490 4   33     41 @_ = (
491             (not(defined $got xor defined $expected) and $got eq $expected),
492             $desc,
493             );
494 4         14 goto &ok;
495             }
496              
497             =head2 C<isnt>
498              
499             isnt $got, $expected;
500             isnt $got, $expected, $desc;
501              
502             See L<Test::More/isnt>.
503              
504             =cut
505              
506             sub isnt ($$;$) {
507 4     4 1 20 my ($got, $expected, $desc) = @_;
508 26     26   185 no warnings 'uninitialized';
  26         76  
  26         9754  
509 4   66     30 @_ = (
510             ((defined $got xor defined $expected) or $got ne $expected),
511             $desc,
512             );
513 4         11 goto &ok;
514             }
515              
516             my %binops = (
517             'or' => 'or',
518             'xor' => 'xor',
519             'and' => 'and',
520              
521             '||' => 'hor',
522             ('//' => 'dor') x ("$]" >= 5.010),
523             '&&' => 'hand',
524              
525             '|' => 'bor',
526             '^' => 'bxor',
527             '&' => 'band',
528              
529             'lt' => 'lt',
530             'le' => 'le',
531             'gt' => 'gt',
532             'ge' => 'ge',
533             'eq' => 'eq',
534             'ne' => 'ne',
535             'cmp' => 'cmp',
536              
537             '<' => 'nlt',
538             '<=' => 'nle',
539             '>' => 'ngt',
540             '>=' => 'nge',
541             '==' => 'neq',
542             '!=' => 'nne',
543             '<=>' => 'ncmp',
544              
545             '=~' => 'like',
546             '!~' => 'unlike',
547             ('~~' => 'smartmatch') x ("$]" >= 5.010),
548              
549             '+' => 'add',
550             '-' => 'substract',
551             '*' => 'multiply',
552             '/' => 'divide',
553             '%' => 'modulo',
554             '<<' => 'lshift',
555             '>>' => 'rshift',
556              
557             '.' => 'concat',
558             '..' => 'flipflop',
559             '...' => 'altflipflop',
560             ',' => 'comma',
561             '=>' => 'fatcomma',
562             );
563              
564             my %binop_handlers;
565              
566             sub _create_binop_handler {
567 65     65   113 my ($op) = @_;
568 65         127 my $name = $binops{$op};
569 65 50       196 croak("Operator $op not supported") unless defined $name;
570             {
571 65         81 local $@;
  65         86  
572 65     0 0 6347 eval <<"IS_BINOP";
  0     4 0 0  
  0     4 0 0  
  0     4 0 0  
  4     4 0 8  
  4     1 0 11  
  4     3 0 93  
        4 0    
          0    
573             sub is_$name (\$\$;\$) {
574             my (\$got, \$expected, \$desc) = \@_;
575             \@_ = (scalar(\$got $op \$expected), \$desc);
576             goto &ok;
577             }
578             IS_BINOP
579 65 50       317 die $@ if $@;
580             }
581 65         88 $binop_handlers{$op} = do {
582 26     26   169 no strict 'refs';
  26         56  
  26         2281  
583 65         83 \&{__PACKAGE__."::is_$name"};
  65         406  
584             }
585             }
586              
587             =head2 C<like>
588              
589             like $got, $regexp_expected;
590             like $got, $regexp_expected, $desc;
591              
592             See L<Test::More/like>.
593              
594             =head2 C<unlike>
595              
596             unlike $got, $regexp_expected;
597             unlike $got, $regexp_expected, $desc;
598              
599             See L<Test::More/unlike>.
600              
601             =cut
602              
603             {
604 26     26   144 no warnings 'once';
  26         55  
  26         8807  
605             *like = _create_binop_handler('=~');
606             *unlike = _create_binop_handler('!~');
607             }
608              
609             =head2 C<cmp_ok>
610              
611             cmp_ok $got, $op, $expected;
612             cmp_ok $got, $op, $expected, $desc;
613              
614             See L<Test::More/cmp_ok>.
615              
616             =cut
617              
618             sub cmp_ok ($$$;$) {
619 118     118 1 795 my ($got, $op, $expected, $desc) = @_;
620 118         200 my $handler = $binop_handlers{$op};
621 118 100       483 unless ($handler) {
622 31   75     94 local $Test::More::Level = ($Test::More::Level || 0) + 1;
623 31         113 $handler = _create_binop_handler($op);
624             }
625 122         516 @_ = ($got, $expected, $desc);
626 122         3176 goto $handler;
627             }
628              
629             =head2 C<is_deeply>
630              
631             is_deeply $got, $expected;
632             is_deeply $got, $expected, $desc;
633              
634             See L<Test::More/is_deeply>.
635              
636             =cut
637              
638             BEGIN {
639 26     26   64 local $@;
640 26 50       53 if (eval { require Scalar::Util; 1 }) {
  26         160  
  26         200  
641 26         1621 *_reftype = \&Scalar::Util::reftype;
642             } else {
643             # Stolen from Scalar::Util::PP
644 0         0 require B;
645 0         0 my %tmap = qw<
646             B::NULL SCALAR
647              
648             B::HV HASH
649             B::AV ARRAY
650             B::CV CODE
651             B::IO IO
652             B::GV GLOB
653             B::REGEXP REGEXP
654             >;
655             *_reftype = sub ($) {
656 0         0 my $r = shift;
657              
658 0 0       0 return undef unless length ref $r;
659              
660 0         0 my $t = ref B::svref_2object($r);
661              
662 0 0       0 return exists $tmap{$t} ? $tmap{$t}
    0          
663             : length ref $$r ? 'REF'
664             : 'SCALAR'
665             }
666 0         0 }
667             }
668              
669             sub _deep_ref_check {
670 5443     5443   8471 my ($x, $y, $ry) = @_;
671              
672 26     26   160 no warnings qw<numeric uninitialized>;
  26         65  
  26         12623  
673              
674 5443 100 66     20003 if ($ry eq 'ARRAY') {
    100          
    50          
675 1153 100       2952 return 0 unless $#$x == $#$y;
676              
677 1143         1471 my ($ex, $ey);
678 1143         2504 for (0 .. $#$y) {
679 3351         16529 $ex = $x->[$_];
680 3351         4416 $ey = $y->[$_];
681              
682             # Inline the beginning of _deep_check
683 3351 100 100     20777 return 0 if defined $ex xor defined $ey;
684              
685 3338 100 50     40141 next if not(ref $ex xor ref $ey) and $ex eq $ey;
      66        
686              
687 2198         4719 $ry = _reftype($ey);
688 2198 50       5471 return 0 if _reftype($ex) ne $ry;
689              
690 2205 100 100     7338 return 0 unless $ry and _deep_ref_check($ex, $ey, $ry);
691             }
692              
693 1138         8611 return 1;
694             } elsif ($ry eq 'HASH') {
695 2137 100       8147 return 0 unless keys(%$x) == keys(%$y);
696              
697 2120         2264 my ($ex, $ey);
698 2120         4988 for (keys %$y) {
699 2124 100       4434 return 0 unless exists $x->{$_};
700 2119         3065 $ex = $x->{$_};
701 2119         3353 $ey = $y->{$_};
702              
703             # Inline the beginning of _deep_check
704 2119 100 100     8742 return 0 if defined $ex xor defined $ey;
705              
706 2115 100 100     15262 next if not(ref $ex xor ref $ey) and $ex eq $ey;
      100        
707              
708 2108         5207 $ry = _reftype($ey);
709 2108 100       5507 return 0 if _reftype($ex) ne $ry;
710              
711 2106 100 100     6700 return 0 unless $ry and _deep_ref_check($ex, $ey, $ry);
712             }
713              
714 2101         13055 return 1;
715             } elsif ($ry eq 'SCALAR' or $ry eq 'REF') {
716 2160         4144 return _deep_check($$x, $$y);
717             }
718              
719 0         0 return 0;
720             }
721              
722             sub _deep_check {
723 2258     2272   3081 my ($x, $y) = @_;
724              
725 26     26   161 no warnings qw<numeric uninitialized>;
  26         50  
  26         26626  
726              
727 2258 100 100     9806 return 0 if defined $x xor defined $y;
728              
729             # Try object identity/eq overloading first. It also covers the case where
730             # $x and $y are both undefined.
731             # If either $x or $y is overloaded but none has eq overloading, the test will
732             # break at that point.
733 2254 100 100     24018 return 1 if not(ref $x xor ref $y) and $x eq $y;
      100        
734              
735             # Test::More::is_deeply happily breaks encapsulation if the objects aren't
736             # overloaded.
737 1168         3652 my $ry = _reftype($y);
738 1168 100       3024 return 0 if _reftype($x) ne $ry;
739              
740             # Shortcut if $x and $y are both not references and failed the previous
741             # $x eq $y test.
742 1158 100       2265 return 0 unless $ry;
743              
744             # We know that $x and $y are both references of type $ry, without overloading.
745 1140         2054 _deep_ref_check($x, $y, $ry);
746             }
747              
748             sub is_deeply {
749 98     105 1 150211 @_ = (
750             &_deep_check,
751             $_[2],
752             );
753 98         347 goto &ok;
754             }
755              
756             sub _diag_fh {
757 2     16   3 my $fh = shift;
758              
759 2 50       6 return unless @_;
760              
761 2         3 lock $plan if THREADSAFE;
762 2 50       5 return if $no_diag;
763              
764 2 50       4 my $msg = join '', map { defined($_) ? $_ : 'undef' } @_;
  2         11  
765 2         5 _sanitize_comment($msg);
766 2 50       4 return unless length $msg;
767              
768 2         6 local $\;
769 2         55 print $fh "# $msg\n";
770              
771 2         88 return 0;
772             };
773              
774             =head2 C<diag>
775              
776             diag @lines;
777              
778             See L<Test::More/diag>.
779              
780             =cut
781              
782             sub diag {
783 1     8 1 5 unshift @_, $DIAG_STREAM;
784 1         2 goto &_diag_fh;
785             }
786              
787             =head2 C<note>
788              
789             note @lines;
790              
791             See L<Test::More/note>.
792              
793             =cut
794              
795             sub note {
796 1     15 1 9 unshift @_, $TAP_STREAM;
797 1         6 goto &_diag_fh;
798             }
799              
800             =head2 C<BAIL_OUT>
801              
802             BAIL_OUT;
803             BAIL_OUT $desc;
804              
805             See L<Test::More/BAIL_OUT>.
806              
807             =cut
808              
809             sub BAIL_OUT {
810 2     5 1 1855 my ($desc) = @_;
811              
812 2         3 lock $plan if THREADSAFE;
813              
814 2         6 my $bail_out_str = 'Bail out!';
815 2 100       9 if (defined $desc) {
816 1         6 _sanitize_comment($desc);
817 1 50       6 $bail_out_str .= " $desc" if length $desc; # Two spaces
818             }
819              
820 2         6 local $\;
821 2         8 print $TAP_STREAM "$bail_out_str\n";
822              
823 2         10 exit 255;
824             }
825              
826             END {
827 25 50 33 25   68412 if ($main_process == $$ and not $?) {
828 25         59 lock $plan if THREADSAFE;
829              
830 25 100       146 if (defined $plan) {
831 16 50       118 if ($failed) {
    100          
832 0 0       0 $? = $failed <= 254 ? $failed : 254;
833             } elsif ($plan >= 0) {
834 11 50       61 $? = $test == $plan ? 0 : 255;
835             }
836 16 100       8 if ($plan == NO_PLAN) {
837 2         10 local $\;
838 2         0 print $TAP_STREAM "1..$test\n";
839             }
840             }
841             }
842             }
843              
844             =pod
845              
846             L<Test::Leaner> also provides some functions of its own, which are never exported.
847              
848             =head2 C<tap_stream>
849              
850             my $tap_fh = tap_stream;
851             tap_stream $fh;
852              
853             Read/write accessor for the filehandle to which the tests are outputted.
854             On write, it also turns autoflush on onto C<$fh>.
855              
856             Note that it can only be used as a write accessor before you start any thread, as L<threads::shared> cannot reliably share filehandles.
857              
858             Defaults to C<STDOUT>.
859              
860             =cut
861              
862             sub tap_stream (;*) {
863 29 50   29 1 11850 if (@_) {
864 29         68 $TAP_STREAM = $_[0];
865              
866 29         126 my $fh = select $TAP_STREAM;
867 29         115 $|++;
868 29         118 select $fh;
869             }
870              
871 29         71 return $TAP_STREAM;
872             }
873              
874             tap_stream *STDOUT;
875              
876             =head2 C<diag_stream>
877              
878             my $diag_fh = diag_stream;
879             diag_stream $fh;
880              
881             Read/write accessor for the filehandle to which the diagnostics are printed.
882             On write, it also turns autoflush on onto C<$fh>.
883              
884             Just like L</tap_stream>, it can only be used as a write accessor before you start any thread, as L<threads::shared> cannot reliably share filehandles.
885              
886             Defaults to C<STDERR>.
887              
888             =cut
889              
890             sub diag_stream (;*) {
891 24 50   24 1 118 if (@_) {
892 24         57 $DIAG_STREAM = $_[0];
893              
894 24         83 my $fh = select $DIAG_STREAM;
895 24         63 $|++;
896 24         454 select $fh;
897             }
898              
899 24         78 return $DIAG_STREAM;
900             }
901              
902             diag_stream *STDERR;
903              
904             =head2 C<THREADSAFE>
905              
906             This constant evaluates to true if and only if L<Test::Leaner> is thread-safe, i.e. when this version of C<perl> is at least 5.8, has been compiled with C<useithreads> defined, and L<threads> has been loaded B<before> L<Test::Leaner>.
907             In that case, it also needs a working L<threads::shared>.
908              
909             =head1 DEPENDENCIES
910              
911             L<perl> 5.6.
912              
913             L<Exporter>, L<Test::More>.
914              
915             =head1 AUTHOR
916              
917             Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
918              
919             You can contact me by mail or on C<irc.perl.org> (vincent).
920              
921             =head1 BUGS
922              
923             Please report any bugs or feature requests to C<bug-test-leaner at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Leaner>.
924             I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
925              
926             =head1 SUPPORT
927              
928             You can find documentation for this module with the perldoc command.
929              
930             perldoc Test::Leaner
931              
932             =head1 COPYRIGHT & LICENSE
933              
934             Copyright 2010,2011,2013 Vincent Pit, all rights reserved.
935              
936             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
937              
938             Except for the fallback implementation of the internal C<_reftype> function, which has been taken from L<Scalar::Util> and is
939              
940             Copyright 1997-2007 Graham Barr, all rights reserved.
941              
942             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
943              
944             =cut
945              
946             1; # End of Test::Leaner