File Coverage

blib/lib/Assert/Refute/Report.pm
Criterion Covered Total %
statement 236 236 100.0
branch 123 132 93.1
condition 42 56 75.0
subroutine 37 37 100.0
pod 28 28 100.0
total 466 489 95.3


line stmt bran cond sub pod time code
1             package Assert::Refute::Report;
2              
3 63     63   947843 use 5.006;
  63         366  
4 63     63   327 use strict;
  63         127  
  63         1412  
5 63     63   347 use warnings;
  63         157  
  63         3505  
6             our $VERSION = '0.17';
7              
8             =head1 NAME
9              
10             Assert::Refute::Report - Contract execution class for Assert::Refute suite
11              
12             =head1 DESCRIPTION
13              
14             This class represents one specific application of contract.
15             It is mutable, but can only changed in one way
16             (there is no undo of tests and diagnostic messages).
17             Eventually a C locks it completely, leaving only
18             L for inspection.
19              
20             See L for contract I.
21              
22             =head1 SYNOPSIS
23              
24             my $c = Assert::Refute::Report->new;
25             $c->refute ( $cond, $message );
26             $c->refute ( $cond2, $message2 );
27             # .......
28             $c->done_testing; # no more refute after this
29              
30             $c->get_count; # how many tests were run
31             $c->is_passing; # did any of them fail?
32             $c->get_tap; # return printable summary in familiar format
33              
34             =cut
35              
36             # Now this module is the CORE of Assert::Refute.
37             # There are 3 things for which performance matters:
38             # 1) new()
39             # 2) refute( 0, ... )
40             # 3) done_testing()
41             # The rest can wait.
42              
43 63     63   452 use Carp;
  63         148  
  63         4293  
44 63     63   437 use Scalar::Util qw( blessed weaken );
  63         145  
  63         4036  
45              
46 63     63   22478 use Assert::Refute::Build qw(to_scalar);
  63         162  
  63         213860  
47              
48             # Always add basic testing primitives to the arsenal
49             require Assert::Refute::T::Basic;
50              
51             my $ERROR_DONE = "done_testing was called, no more changes may be added";
52              
53             =head1 METHODS
54              
55             =head3 new
56              
57             Assert::Refute::Report->new();
58              
59             No arguments are currently supported.
60              
61             =cut
62              
63             # NOTE keep it simple for performance reasons
64             sub new {
65 182     182 1 32637 bless {
66             fail => {},
67             count => 0,
68             }, shift;
69             };
70              
71             =head2 RUNNING PRIMITIVES
72              
73             =head3 plan( tests => $n )
74              
75             Plan to run exactly n tests.
76             This is not required, and L (see below)
77             is needed at the end anyway.
78              
79             =head3 plan( skip_all => $reason )
80              
81             Plan to run no tests at all.
82             As of current, this does not prevent any future checks from being run.
83              
84             In both cases,
85             dies if there's already a plan, or tests are being run, or done_testing
86             was seen.
87              
88             If plan is not fullfilled by the time of C call,
89             a message indicating plan violation will be added,
90             and the report will become unconditionally failing.
91              
92             =cut
93              
94             my %allow_plan;
95             $allow_plan{$_}++ for qw( tests skip_all title );
96              
97             sub plan {
98 17     17 1 73 my $self = shift;
99 17 100       69 $self->_croak("Odd number of arguments in plan()")
100             if @_ % 2;
101 16         87 my %args = @_;
102              
103 16         50 my @extra = grep { !$allow_plan{$_} } keys %args;
  17         69  
104 16 100       63 $self->_croak( "Unknown options to plan(): ".join ",", sort @extra )
105             if @extra;
106 15 50       42 $self->_croak( "Useless use of plan() without arguments" )
107             unless %args;
108              
109             $self->_croak( $ERROR_DONE )
110 15 50       109 if $self->{done};
111              
112             $self->_croak( "plan(): already defined" )
113 15 100       47 if defined $self->{plan_tests};
114             $self->_croak( "plan(): testing already started" )
115 14 100       53 if $self->{count} > 0;
116              
117 13 100       57 if ($args{skip_all}) {
    100          
118 1         2 $self->{plan_skip} = $args{skip_all};
119 1         2 $self->{plan_tests} = 0;
120             # TODO should we lock report?
121             } elsif (defined $args{tests}) {
122             $self->_croak( "plan(): usage: plan tests => n")
123 11 100       79 unless $args{tests} =~ /^[0-9]+$/;
124             # TODO should we forbid tests => 0 w/o a reason?
125 10         37 $self->{plan_tests} = int $args{tests};
126             };
127              
128 12 100       37 if ($args{title}) {
129 2         9 $self->set_title( $args{title} );
130             };
131              
132 12         41 return $self;
133             };
134              
135             =head3 refute( $condition, $message )
136              
137             An inverted assertion. That is, it B if C<$condition> is B.
138              
139             Returns inverse of first argument.
140             Dies if L was called.
141              
142             See L for more detailed discussion.
143              
144             =cut
145              
146             sub refute {
147 288     288 1 907 my ($self, $cond, $msg) = @_;
148              
149             $self->_croak( $ERROR_DONE )
150 288 100       762 if $self->{done};
151              
152 287         514 my $n = ++$self->{count};
153 287 100       851 $self->{name}{$n} = $msg if defined $msg;
154 287         468 delete $self->{log}; # log is a shortcut to $self->{messages}{$n}
155             # see do_log()
156              
157             # Pass, return ASAP
158 287 100       1135 return $n unless $cond;
159              
160             # Test failed!
161 111         267 $self->{fail}{$n} = $cond;
162 111         290 $self->{fail_count}++;
163 111         272 return 0;
164             };
165              
166             =head3 diag
167              
168             diag "Message", \%reference, ...;
169              
170             Add human-readable diagnostic message to report.
171             References are auto-explained via L.
172              
173             =head3 note
174              
175             diag "Message", \%reference, ...;
176              
177             Add human-readable notice message to report.
178             References are auto-explained via L.
179              
180             =cut
181              
182             sub diag {
183 90     90 1 1188 my $self = shift;
184              
185 90         229 $self->do_log( 0, -1, join " ", map { to_scalar($_) } @_ );
  99         312  
186             };
187              
188             sub note {
189 3     3 1 1307 my $self = shift;
190              
191 3         12 $self->do_log( 0, 1, join " ", map { to_scalar($_) } @_ );
  4         15  
192             };
193              
194             =head3 done_testing
195              
196             Stop testing.
197             After this call, no more writes (including done_testing)
198             can be performed on this contract.
199             This happens by default at the end of C block.
200              
201             Dies if called for a second time, I an argument is given.
202              
203             A true argument is considered to be the exception
204             that interrupted the contract execution,
205             resulting in an unconditionally failed contract.
206              
207             A false argument just avoids dying and is equivalent to
208              
209             $report->done_testing
210             unless $report->is_done;
211              
212             Returns self.
213              
214             =cut
215              
216             sub done_testing {
217 138     138 1 2423 my ($self, $exception) = @_;
218              
219 138 100       563 if ($exception) {
    100          
220             # Record a totally failing contract.
221 8         18 delete $self->{done};
222 8         24 $self->{has_error} = $exception;
223             } elsif ($self->{done}) {
224             # A special case - done_testing(0) means "tentative stop"
225 4 100       16 return $self if defined $exception;
226 3         14 $self->_croak( $ERROR_DONE );
227             };
228              
229             # Any post-mortem messages go to a separate bucket
230 134   100     777 $self->{log} = $self->{messages}{ -1 } ||= [];
231              
232 134 100       427 if ($self->{has_error}) {
233 8         33 $self->diag( "Looks like contract was interrupted by", $self->{has_error} );
234             };
235              
236 134 100       525 if (defined $self->{plan_tests}) {
237             # Check plan
238 10 100       30 if ($self->{count} != $self->{plan_tests}) {
239 3         16 my $bad_plan = "Looks like you planned $self->{plan_tests}"
240             ." tests but ran $self->{count}";
241 3   33     21 $self->{has_error} ||= $bad_plan;
242 3         16 $self->diag( $bad_plan );
243             };
244             };
245              
246 134 100       351 if ($self->{fail_count}) {
247 65         383 $self->diag(
248             "Looks like $self->{fail_count} tests out of $self->{count} have failed");
249 65         199 my $ctx = $self->context;
250 65         289 foreach (keys %$ctx) {
251 1         5 $self->diag("context: $_:", $ctx->{$_});
252             };
253             };
254              
255 134         387 $self->{done}++;
256 134         325 return $self;
257             };
258              
259             =head3 context()
260              
261             Get execution context hash with arbitrary user data.
262              
263             Upon failure, the hash content is going to be appended to the log at diag level.
264              
265             =cut
266              
267             sub context {
268 70     70 1 1741 my $self = shift;
269 70   100     418 return $self->{context} ||= {};
270             };
271              
272             =head3 set_context( \%hash )
273              
274             Set the context hash.
275              
276             Only plain (not blessed) hash is allowed as argument.
277              
278             =cut
279              
280             sub set_context {
281 3     3 1 11 my ($self, $hash) = @_;
282              
283 3 100       13 $self->_croak( "argument must be a HASH reference" )
284             unless ref $hash eq 'HASH';
285              
286 2         5 $self->{context} = $hash;
287 2         26 return $self;
288             };
289              
290             =head3 set_title
291              
292             Set the a contract title
293             that briefly explains what we are trying to prove, and why.
294              
295             See also L.
296              
297             B<[EXPERIMENTAL]>. Name and meaning may change in the future.
298              
299             =cut
300              
301             # TODO setter
302             sub set_title {
303 8     8 1 28 my ($self, $str) = @_;
304              
305             $self->_croak( $ERROR_DONE )
306 8 100       48 if $self->{done};
307              
308 7         18 $self->{title} = $str;
309 7         22 return $self;
310             };
311              
312             =head2 TESTING PRIMITIVES
313              
314             L comes with a set of basic checks
315             similar to that of L, all being wrappers around
316             L discussed above.
317             They are available as both prototyped functions (if requested) I
318             methods in contract execution object and its descendants.
319              
320             The list is as follows:
321              
322             C, C, C, C, C, C,
323             C, C, C, C, C,
324             C, C, C, C, C, C.
325              
326             See L for more details.
327              
328             Additionally, I checks defined using L
329             will be added to L as methods
330             unless explicitly told otherwise.
331              
332             =head3 subcontract( "Message" => $specification, @arguments ... )
333              
334             Execute a previously defined group of tests and fail loudly if it fails.
335              
336             $specification may be one of:
337              
338             =over
339              
340             =item * code reference - will be executed in C block, with a I
341             L passed as argument.
342              
343             Exceptions are rethrown, leaving a failed contract behind.
344              
345             $report->subcontract( "My code" => sub {
346             my $new_report = shift;
347             # run some checks here
348             } );
349              
350             =item * L instance - apply() will be called;
351              
352             As of v.0.15, contract swallows exceptions, leaving behind a failed
353             contract report only. This MAY change in the future.
354              
355             =item * L instance from a previously executed test.
356              
357             =back
358              
359             B<[NOTE]> that the message comes first, unlike in C or other
360             test conditions, and is required.
361              
362             =cut
363              
364             sub subcontract {
365 32     32 1 118 my ($self, $msg, $sub, @args) = @_;
366              
367             $self->_croak( $ERROR_DONE )
368 32 50       100 if $self->{done};
369 32 100 66     189 $self->_croak( "Name is required for subcontract" )
370             if !$msg or ref $msg;
371              
372 31         55 my $rethrow;
373             my $rep;
374 31 100 100     267 if ( blessed $sub and $sub->isa( "Assert::Refute::Contract" ) ) {
    100 66        
    100          
375 4         13 $rep = $sub->apply(@args);
376             } elsif (blessed $sub and $sub->isa( "Assert::Refute::Report" ) ) {
377 4 100       13 $self->_croak("pre-executed subcontract cannot take args")
378             if @args;
379 3 100       16 $self->_croak("pre-executed subcontract must be finished")
380             unless $sub->is_done;
381 2         10 $rep = $sub;
382             } elsif (UNIVERSAL::isa( $sub, 'CODE' )) {
383 22         52 $rep = Assert::Refute::Report->new->set_parent($self);
384             eval {
385             # This is ripoff of do_run - maybe just call do_run here
386 22         35 local $Assert::Refute::DRIVER = $rep;
387 22         64 $sub->($rep, @args);
388 21         62 $rep->done_testing(0);
389 21         60 1;
390 22 100       41 } or do {
391 1   33     12 $rethrow = $@ || Carp::shortmess("Subcontract execution interrupted");
392 1         4 $rep->done_testing( $rethrow );
393             };
394             } else {
395 1         4 $self->_croak("subcontract must be a coderef, a Contract object, or a finished Report object");
396             };
397              
398 28         80 $self->{subcontract}{ $self->get_count + 1 } = $rep;
399 28         68 my $ret = $self->refute( !$rep->is_passing, "$msg (subtest)" );
400 28 100       88 die $rethrow if $rethrow;
401 27         80 return $ret;
402             };
403              
404             =head2 QUERYING PRIMITIVES
405              
406             =head3 is_done
407              
408             Tells whether done_testing was seen.
409              
410             =cut
411              
412             sub is_done {
413 40     40 1 90 my $self = shift;
414 40   100     294 return $self->{done} || 0;
415             };
416              
417              
418             =head3 is_passing
419              
420             Tell whether the contract is passing or not.
421              
422             =cut
423              
424             sub is_passing {
425 80     80 1 165 my $self = shift;
426              
427 80   100     525 return !$self->{fail_count} && !$self->{has_error};
428             };
429              
430             =head3 get_count
431              
432             How many tests have been executed.
433              
434             =cut
435              
436             sub get_count {
437 94     94 1 276 my $self = shift;
438 94         301 return $self->{count};
439             };
440              
441             =head3 get_fail_count
442              
443             How many tests failed
444              
445             =cut
446              
447             sub get_fail_count {
448 2     2 1 24 my $self = shift;
449 2   100     32 return $self->{fail_count} || 0;
450             };
451              
452             =head3 get_tests
453              
454             Returns a list of test ids, preserving order.
455              
456             =cut
457              
458             sub get_tests {
459 2     2 1 5 my $self = shift;
460 2         13 return 1 .. $self->{count};
461             };
462              
463             =head3 get_failed_ids
464              
465             List the numbers of tests that failed.
466              
467             =cut
468              
469             sub get_failed_ids {
470 1     1 1 6 my $self = shift;
471              
472 1 50       2 return my @list = sort { $a <=> $b } keys %{ $self->{fail} || {} };
  1         11  
  1         8  
473             };
474              
475             =head3 get_result( $id )
476              
477             Returns result of test denoted by $id, dies if such test was never performed.
478             The result is false for passing tests and whatever the reason for failure was
479             for failing ones.
480              
481             =cut
482              
483             sub get_result {
484 3     3 1 10 my ($self, $n) = @_;
485              
486             return $self->{fail}{$n} || 0
487 3 100 50     15 if exists $self->{fail}{$n};
488              
489 2 100 66     22 return 0 if $n =~ /^[1-9]\d*$/ and $n<= $self->{count};
490              
491 1         8 $self->_croak( "Test $n has never been performed" );
492             };
493              
494             =head3 get_result_details ($id)
495              
496             Returns a hash containing information about a test:
497              
498             =over
499              
500             =item * number - the number of test (this is equal to argument);
501              
502             =item * name - name of the test (if any);
503              
504             =item * ok - whether the test was successful;
505              
506             =item * reason - the reason for test failing, if it failed;
507             Undefined for "ok" tests.
508              
509             =item * diag - diagnostic messages as one array, without leading C<#>;
510              
511             =item * log - any log messages that followed the test (see get_log for format)
512              
513             =item * subcontract - if test was a subcontract, contains the report.
514              
515             =back
516              
517             Returns empty hash for nonexistent tests, and dies if test number is not integer.
518              
519             As a special case, tests number 0 and -1 represent the output before any
520             tests and postmortem output, respectively.
521             These only contains the C and C fields.
522              
523             See also L.
524              
525             B<[EXPERIMENTAL]>. Name and meaning may change in the future.
526              
527             =cut
528              
529             sub get_result_details {
530 39     39 1 13238 my ($self, $n) = @_;
531              
532 39 50 33     262 $self->_croak( "Bad test number $n, must be nonnegatine integer" )
533             unless defined $n and $n =~ /^(?:[0-9]+|-1)$/;
534              
535             # Process messages, return if premature(0) or post-mortem (n+1)
536 39         76 my @messages;
537 39 100       122 if (my $array = $self->{messages}{$n} ) {
538 9         27 @messages = @$array;
539             };
540              
541 39         106 my %ret = ( number => $n );
542              
543 39 100       100 if ($n >= 1) {
544             # a real test - add some information
545 33         65 my $reason = $self->{fail}{$n};
546 33         55 my @diag;
547              
548 33 100 100     152 if (ref $reason eq 'ARRAY') {
    100          
549 4         24 push @diag, [ 0, -1, to_scalar($_) ] for @$reason;
550             } elsif ( $reason and $reason ne 1 ) {
551 5         20 push @diag, [ 0, -1, to_scalar($reason) ];
552             };
553              
554 33         74 $ret{ok} = !$reason;
555 33         69 $ret{name} = $self->{name}{$n};
556 33         55 $ret{reason} = $reason;
557 33         78 $ret{log} = [@diag, @messages];
558 33         83 $ret{subcontract} = $self->{subcontract}{$n};
559             } else {
560             # leading or trailing messages
561 6         18 $ret{log} = \@messages,
562             };
563              
564             # Strip extra trash from internal log format
565 39         65 $ret{diag} = [ map { $_->[2] } grep { $_->[1] < 0 } @{ $ret{log} } ];
  23         57  
  23         62  
  39         107  
566              
567 39         264 return \%ret;
568             };
569              
570             =head3 get_error
571              
572             Return last error that was recorded during contract execution,
573             or false if there was none.
574              
575             =cut
576              
577             sub get_error {
578 61     61 1 112 my $self = shift;
579 61   100     451 return $self->{has_error} || '';
580             };
581              
582             =head3 get_tap( $level )
583              
584             Return a would-be Test::More script output for current contract.
585              
586             The level parameter allows to adjust verbosity level.
587             The default is 0 which includes passing tests,
588             but not notes and/or debugging messages.
589              
590             B<[NOTE]> that C is higher than C.
591              
592             =over
593              
594             =item * -3 - something totally horrible, like C
595              
596             =item * -2 - a failing test
597              
598             =item * -1 - a diagnostic message, think C
599              
600             =item * 0 - a passing test
601              
602             =item * 1+ - a normally ignored verbose message, think L
603              
604             =back
605              
606             =cut
607              
608             my %padding; # cache level => leading spaces mapping
609             my $tab = ' ';
610              
611             sub get_tap {
612 67     67 1 6616 my ($self, $verbosity) = @_;
613              
614 67   100     361 $verbosity ||= 0;
615              
616 67         263 my $mess = $self->get_log( $verbosity );
617              
618 67         117 my @str;
619 67         178 foreach (@$mess) {
620 358         784 my ($indent, $level, $mess) = @$_;
621 358 50       703 next if $level > $verbosity;
622              
623 358         573 my $pad = ' ' x $indent;
624             $pad .= exists $padding{$level}
625             ? $padding{$level}
626 358 100       900 : ($padding{$level} = _get_padding( $level ));
627 358         2168 $mess =~ s/\s*$//s;
628              
629 358         920 foreach (split /\n/, $mess) {
630 416         1171 push @str, "$pad$_";
631             };
632             };
633              
634 67         728 return join "\n", @str, '';
635             };
636              
637             sub _get_padding {
638 63     63   125 my $level = shift;
639              
640 63 100       177 return '#' x $level . '# ' if $level > 0;
641 62 100       221 return '# ' if $level == -1;
642 41         150 return '';
643             };
644              
645             =head3 get_sign
646              
647             Produce a terse pass/fail summary (signature)
648             as a string of numbers and letters.
649              
650             The format is C<"t(\d+|N)*[rdE]">.
651              
652             =over
653              
654             =item * C is always present at the start;
655              
656             =item * a number stands for a series of passing tests;
657              
658             =item * C stands for a I failing test;
659              
660             =item * C stands for a contract that is still Bunning;
661              
662             =item * C stands for a an Bxception during execution;
663              
664             =item * C stands for a contract that is Bone.
665              
666             =back
667              
668             The format is still evolving.
669             Capital letters are used to represent failure,
670             and it is likely to stay like that.
671              
672             The numeric notation was inspired by Forsyth-Edwards notation (FEN) in chess.
673              
674             =cut
675              
676             sub get_sign {
677 57     57 1 5886 my $self = shift;
678              
679 57         156 my @t = ("t");
680              
681 57         113 my $streak;
682 57         222 foreach (1 .. $self->{count}) {
683 167 100       398 if ( $self->{fail}{$_} ) {
684 68 100       218 push @t, $streak if $streak;
685 68         125 $streak = 0;
686 68         155 push @t, "N"; # for "not ok"
687             } else {
688 99         188 $streak++;
689             };
690             };
691 57 100       173 push @t, $streak if $streak;
692              
693 57 100       184 my $d = $self->get_error ? 'E' : $self->{done} ? 'd' : 'r';
    100          
694 57         447 return join '', @t, $d;
695             };
696              
697             =head3 get_title
698              
699             Returns the contract title
700             that briefly explains what we are trying to prove, and why.
701              
702             See also L.
703              
704             B<[EXPERIMENTAL]>. Name and meaning may change in the future.
705              
706             =cut
707              
708             # TODO Dumb getter
709             sub get_title {
710 9     9 1 1245 return $_[0]->{title};
711             };
712              
713             =head2 DEVELOPMENT PRIMITIVES
714              
715             Generally one should not touch these methods unless
716             when subclassing to build a new test backend.
717              
718             When extending this module,
719             please try to stick to C, C, and C
720             to avoid clash with test names.
721              
722             This is weird and probably has to be fixed at some point.
723              
724             =head3 do_run( $code, @list )
725              
726             Run given CODEREF, passing self as both first argument I
727             current_contract().
728             Report object is locked afterwards via L call.
729              
730             Exceptions are rethrown.
731             As of current, an exception in CODEREF leaves report in an unfinished state.
732             This may or may not change in the future.
733              
734             Returns self.
735              
736             Example usage is
737              
738             Assert::Refute::Report->new->run( sub {
739             like $this, qr/.../;
740             can_ok $that, qw(foo bar frobnicate);
741             } );
742              
743             =cut
744              
745             sub do_run {
746 55     55 1 160 my ($self, $code, @args) = @_;
747              
748 55         111 local $Assert::Refute::DRIVER = $self;
749 55         192 $code->($self, @args);
750 52         217 $self->done_testing(0);
751              
752 52         201 return $self;
753             };
754              
755             =head3 do_log( $indent, $level, $message )
756              
757             Append a message to execution log.
758              
759             See L for level descriptions.
760              
761             =cut
762              
763             sub do_log {
764 93     93 1 308 my ($self, $indent, $level, $mess) = @_;
765              
766             $self->_croak( $ERROR_DONE )
767 93 100       394 if $self->{done};
768              
769 91   50     371 $self->{log} ||= $self->{messages}{ $self->{count} } ||= [];
      66        
770 91         150 push @{ $self->{log} }, [$indent, $level, $mess];
  91         327  
771              
772 91         209 return $self;
773             };
774              
775             =head3 get_log
776              
777             Return log messages "as is" as array reference
778             containing triads of (indent, level, message).
779              
780             B<[CAUTION]> This currently returns reference to internal structure,
781             so be careful not to spoil it.
782             This MAY change in the future.
783              
784             =cut
785              
786             sub get_log {
787 71     71 1 166 my ($self, $verbosity) = @_;
788 71 50       183 $verbosity = 9**9**9 unless defined $verbosity;
789              
790 71         123 my @mess;
791              
792             # output plan if there was plan
793 71 100       203 if (defined $self->{plan_tests}) {
794             push @mess, _plan_to_tap( $self->{plan_tests}, $self->{plan_skip} )
795 9 50       48 unless $verbosity < 0;
796             };
797              
798 71         224 foreach my $n ( 0 .. $self->{count}, -1 ) {
799             # Report test details.
800             # Only append the logs for
801             # premature (0) and postmortem (-1) messages
802 296 100       603 if ($n > 0) {
803 154         281 my $reason = $self->{fail}{$n};
804 154 100       385 my ($level, $prefix) = $reason ? (-2, "not ok") : (0, "ok");
805 154 100       432 my $name = $self->{name}{$n} ? "$n - $self->{name}{$n}" : $n;
806 154         458 push @mess, [ 0, $level, "$prefix $name" ];
807              
808 154 100       385 if ($self->{subcontract}{$n}) {
809             push @mess, map {
810 14         45 [ $_->[0]+1, $_->[1], $_->[2] ];
811 4         6 } @{ $self->{subcontract}{$n}->get_log( $verbosity ) };
  4         33  
812             };
813              
814 154 100 100     703 if (ref $reason eq 'ARRAY') {
    100          
815             push @mess, map {
816 7         18 [ 0, -1, to_scalar( $_ ) ]
  21         53  
817             } @$reason;
818             } elsif ($reason and $reason ne 1) {
819 54         264 push @mess, [ 0, -1, to_scalar( $reason ) ];
820             };
821             };
822              
823             # and all following diags
824 296 100       817 if (my $rest = $self->{messages}{$n} ) {
825 78         193 push @mess, grep { $_->[1] <= $verbosity } @$rest;
  63         247  
826             };
827             };
828              
829 71 100 100     385 if (!defined $self->{plan_tests} and $self->{done}) {
830 57 50       285 push @mess, _plan_to_tap( $self->get_count )
831             unless $verbosity < 0;
832             };
833              
834 71         262 return \@mess;
835             };
836              
837             sub _plan_to_tap {
838 66     66   176 my ($n, $skip) = @_;
839              
840 66         177 my $line = "1..".$n;
841 66 100       171 $line .= " # SKIP $skip"
842             if defined $skip;
843 66         216 return [ 0, 0, $line ];
844             };
845              
846             =head2 set_parent
847              
848             $report->set_parent($bigger_report);
849             $report->set_parent(undef);
850              
851             Indicate that a contract is part of a larger one.
852             The parent object should be an L instance.
853             The parent object reference will be weakened to avoid memory leak.
854              
855             Provide C as argument to erase parent information.
856              
857             Returns self, so that calls to set_parent can be chained.
858              
859             This is used internally by L.
860              
861             B As of 0.16, no C/C check on the argument is enforced.
862             It must be blessed, however.
863             This MAY change in the future.
864              
865             =cut
866              
867             sub set_parent {
868 27     27 1 76 my ($self, $parent) = @_;
869              
870 27 100       140 if (blessed $parent) {
    100          
871 25         57 $self->{parent} = $parent;
872             # avoid a circular loop because $self is likely to be stored
873             # in parent as subcontract
874 25         73 weaken $self->{parent};
875             } elsif (!defined $parent) {
876 1         2 delete $self->{parent};
877             } else {
878 1   50     14 $self->_croak('parent must be a Report object, not a '.(ref $parent || 'scalar'))
879             };
880 26         66 return $self;
881             };
882              
883             =head2 get_parent
884              
885             Return parent contract, i.e. the contract we are subcontract of, if any.
886              
887             Always check get_parent to be defined
888             as it will vanish if parent object goes out of scope.
889             This is done so to avoid memory leak in subcontract call.
890              
891             =cut
892              
893             # Dumb getter
894             sub get_parent {
895 8     8 1 634 return $_[0]->{parent};
896             };
897              
898             =head2 get_depth
899              
900             Returns 0 is there is no parent, or parent's depth + 1.
901             This of this as "this contract's indentation level".
902              
903             B. Name and meaning MAY change in the future.
904              
905             =cut
906              
907             sub get_depth {
908 4     4 1 11 my $self = shift;
909              
910 4 100       16 if (!exists $self->{depth}) {
911 3         43 my $parent = $self->get_parent;
912 3 100       15 $self->{depth} = $parent ? $parent->get_depth + 1 : 0;
913             };
914              
915 4         14 return $self->{depth};
916             };
917              
918             sub _croak {
919 19     19   55 my ($self, $mess) = @_;
920              
921 19   50     52 $mess ||= "Something terrible happened";
922 19         54 $mess =~ s/\n+$//s;
923              
924 19         133 my $fun = (caller 1)[3];
925 19         204 $fun =~ s/(.*)::/${1}->/;
926              
927 19         2478 croak "$fun(): $mess";
928             };
929              
930             =head1 LICENSE AND COPYRIGHT
931              
932             This module is part of L suite.
933              
934             Copyright 2017-2018 Konstantin S. Uvarin. C<< >>
935              
936             This program is free software; you can redistribute it and/or modify it
937             under the terms of the the Artistic License (2.0). You may obtain a
938             copy of the full license at:
939              
940             L
941              
942             =cut
943              
944             1; # End of Assert::Refute::Report