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   1883835 use 5.006;
  63         284  
4 63     63   396 use strict;
  63         174  
  63         2241  
5 63     63   486 use warnings;
  63         200  
  63         5769  
6             our $VERSION = '0.1701';
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   430 use Carp;
  63         199  
  63         5371  
44 63     63   474 use Scalar::Util qw( blessed weaken );
  63         132  
  63         4895  
45              
46 63     63   28283 use Assert::Refute::Build qw(to_scalar);
  63         218  
  63         274246  
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 183     183 1 4200194 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 82 my $self = shift;
99 17 100       138 $self->_croak("Odd number of arguments in plan()")
100             if @_ % 2;
101 16         54 my %args = @_;
102              
103 16         48 my @extra = grep { !$allow_plan{$_} } keys %args;
  17         59  
104 16 100       47 $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       48 if $self->{done};
111              
112             $self->_croak( "plan(): already defined" )
113 15 100       46 if defined $self->{plan_tests};
114             $self->_croak( "plan(): testing already started" )
115 14 100       44 if $self->{count} > 0;
116              
117 13 100       55 if ($args{skip_all}) {
    100          
118 1         3 $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         33 $self->{plan_tests} = int $args{tests};
126             };
127              
128 12 100       58 if ($args{title}) {
129 2         27 $self->set_title( $args{title} );
130             };
131              
132 12         40 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 293     293 1 819 my ($self, $cond, $msg) = @_;
148              
149             $self->_croak( $ERROR_DONE )
150 293 100       802 if $self->{done};
151              
152 292         585 my $n = ++$self->{count};
153 292 100       2046 $self->{name}{$n} = $msg if defined $msg;
154 292         485 delete $self->{log}; # log is a shortcut to $self->{messages}{$n}
155             # see do_log()
156              
157             # Pass, return ASAP
158 292 100       1137 return $n unless $cond;
159              
160             # Test failed!
161 114         317 $self->{fail}{$n} = $cond;
162 114         225 $self->{fail_count}++;
163 114         315 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 91     91 1 1044 my $self = shift;
184              
185 91         242 $self->do_log( 0, -1, join " ", map { to_scalar($_) } @_ );
  100         371  
186             };
187              
188             sub note {
189 3     3 1 920 my $self = shift;
190              
191 3         11 $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 1207 my ($self, $exception) = @_;
218              
219 138 100       664 if ($exception) {
    100          
220             # Record a totally failing contract.
221 8         20 delete $self->{done};
222 8         25 $self->{has_error} = $exception;
223             } elsif ($self->{done}) {
224             # A special case - done_testing(0) means "tentative stop"
225 4 100       51 return $self if defined $exception;
226 3         19 $self->_croak( $ERROR_DONE );
227             };
228              
229             # Any post-mortem messages go to a separate bucket
230 134   100     992 $self->{log} = $self->{messages}{ -1 } ||= [];
231              
232 134 100       390 if ($self->{has_error}) {
233 8         39 $self->diag( "Looks like contract was interrupted by", $self->{has_error} );
234             };
235              
236 134 100       443 if (defined $self->{plan_tests}) {
237             # Check plan
238 10 100       37 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     23 $self->{has_error} ||= $bad_plan;
242 3         10 $self->diag( $bad_plan );
243             };
244             };
245              
246 134 100       630 if ($self->{fail_count}) {
247 65         427 $self->diag(
248             "Looks like $self->{fail_count} tests out of $self->{count} have failed");
249 65         311 my $ctx = $self->context;
250 65         259 foreach (keys %$ctx) {
251 1         5 $self->diag("context: $_:", $ctx->{$_});
252             };
253             };
254              
255 134         496 $self->{done}++;
256 134         264 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 1152 my $self = shift;
269 70   100     466 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 14 my ($self, $hash) = @_;
282              
283 3 100       19 $self->_croak( "argument must be a HASH reference" )
284             unless ref $hash eq 'HASH';
285              
286 2         6 $self->{context} = $hash;
287 2         7 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 31 my ($self, $str) = @_;
304              
305             $self->_croak( $ERROR_DONE )
306 8 100       78 if $self->{done};
307              
308 7         21 $self->{title} = $str;
309 7         29 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 127 my ($self, $msg, $sub, @args) = @_;
366              
367             $self->_croak( $ERROR_DONE )
368 32 50       95 if $self->{done};
369 32 100 66     155 $self->_croak( "Name is required for subcontract" )
370             if !$msg or ref $msg;
371              
372 31         58 my $rethrow;
373             my $rep;
374 31 100 100     232 if ( blessed $sub and $sub->isa( "Assert::Refute::Contract" ) ) {
    100 66        
    100          
375 4         46 $rep = $sub->apply(@args);
376             } elsif (blessed $sub and $sub->isa( "Assert::Refute::Report" ) ) {
377 4 100       24 $self->_croak("pre-executed subcontract cannot take args")
378             if @args;
379 3 100       13 $self->_croak("pre-executed subcontract must be finished")
380             unless $sub->is_done;
381 2         4 $rep = $sub;
382             } elsif (UNIVERSAL::isa( $sub, 'CODE' )) {
383 22         50 $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         101 local $Assert::Refute::DRIVER = $rep;
387 22         57 $sub->($rep, @args);
388 21         49 $rep->done_testing(0);
389 21         57 1;
390 22 100       29 } or do {
391 1   33     19 $rethrow = $@ || Carp::shortmess("Subcontract execution interrupted");
392 1         5 $rep->done_testing( $rethrow );
393             };
394             } else {
395 1         5 $self->_croak("subcontract must be a coderef, a Contract object, or a finished Report object");
396             };
397              
398 28         82 $self->{subcontract}{ $self->get_count + 1 } = $rep;
399 28         79 my $ret = $self->refute( !$rep->is_passing, "$msg (subtest)" );
400 28 100       76 die $rethrow if $rethrow;
401 27         85 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 92 my $self = shift;
414 40   100     337 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 200 my $self = shift;
426              
427 80   100     552 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 254 my $self = shift;
438 94         337 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 5 my $self = shift;
449 2   100     15 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 4 my $self = shift;
460 2         17 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 7 my $self = shift;
471              
472 1 50       3 return my @list = sort { $a <=> $b } keys %{ $self->{fail} || {} };
  1         17  
  1         9  
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     21 if exists $self->{fail}{$n};
488              
489 2 100 66     28 return 0 if $n =~ /^[1-9]\d*$/ and $n<= $self->{count};
490              
491 1         7 $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 22021 my ($self, $n) = @_;
531              
532 39 50 33     244 $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         48 my @messages;
537 39 100       109 if (my $array = $self->{messages}{$n} ) {
538 9         19 @messages = @$array;
539             };
540              
541 39         92 my %ret = ( number => $n );
542              
543 39 100       86 if ($n >= 1) {
544             # a real test - add some information
545 33         48 my $reason = $self->{fail}{$n};
546 33         37 my @diag;
547              
548 33 100 100     114 if (ref $reason eq 'ARRAY') {
    100          
549 4         19 push @diag, [ 0, -1, to_scalar($_) ] for @$reason;
550             } elsif ( $reason and $reason ne 1 ) {
551 5         12 push @diag, [ 0, -1, to_scalar($reason) ];
552             };
553              
554 33         56 $ret{ok} = !$reason;
555 33         90 $ret{name} = $self->{name}{$n};
556 33         43 $ret{reason} = $reason;
557 33         74 $ret{log} = [@diag, @messages];
558 33         62 $ret{subcontract} = $self->{subcontract}{$n};
559             } else {
560             # leading or trailing messages
561 6         15 $ret{log} = \@messages,
562             };
563              
564             # Strip extra trash from internal log format
565 39         51 $ret{diag} = [ map { $_->[2] } grep { $_->[1] < 0 } @{ $ret{log} } ];
  23         56  
  23         47  
  39         87  
566              
567 39         180 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 181 my $self = shift;
579 61   100     511 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 6753 my ($self, $verbosity) = @_;
613              
614 67   100     407 $verbosity ||= 0;
615              
616 67         274 my $mess = $self->get_log( $verbosity );
617              
618 67         138 my @str;
619 67         180 foreach (@$mess) {
620 358         733 my ($indent, $level, $mess) = @$_;
621 358 50       767 next if $level > $verbosity;
622              
623 358         641 my $pad = ' ' x $indent;
624             $pad .= exists $padding{$level}
625             ? $padding{$level}
626 358 100       1511 : ($padding{$level} = _get_padding( $level ));
627 358         2789 $mess =~ s/\s*$//s;
628              
629 358         1005 foreach (split /\n/, $mess) {
630 416         1227 push @str, "$pad$_";
631             };
632             };
633              
634 67         847 return join "\n", @str, '';
635             };
636              
637             sub _get_padding {
638 63     63   143 my $level = shift;
639              
640 63 100       169 return '#' x $level . '# ' if $level > 0;
641 62 100       216 return '# ' if $level == -1;
642 41         163 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 8764 my $self = shift;
678              
679 57         150 my @t = ("t");
680              
681 57         114 my $streak;
682 57         211 foreach (1 .. $self->{count}) {
683 167 100       578 if ( $self->{fail}{$_} ) {
684 68 100       204 push @t, $streak if $streak;
685 68         108 $streak = 0;
686 68         151 push @t, "N"; # for "not ok"
687             } else {
688 99         175 $streak++;
689             };
690             };
691 57 100       196 push @t, $streak if $streak;
692              
693 57 100       204 my $d = $self->get_error ? 'E' : $self->{done} ? 'd' : 'r';
    100          
694 57         445 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 1668 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 186 my ($self, $code, @args) = @_;
747              
748 55         129 local $Assert::Refute::DRIVER = $self;
749 55         218 $code->($self, @args);
750 52         291 $self->done_testing(0);
751              
752 52         266 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 94     94 1 290 my ($self, $indent, $level, $mess) = @_;
765              
766             $self->_croak( $ERROR_DONE )
767 94 100       330 if $self->{done};
768              
769 92   50     407 $self->{log} ||= $self->{messages}{ $self->{count} } ||= [];
      66        
770 92         148 push @{ $self->{log} }, [$indent, $level, $mess];
  92         458  
771              
772 92         252 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 173 my ($self, $verbosity) = @_;
788 71 50       216 $verbosity = 9**9**9 unless defined $verbosity;
789              
790 71         143 my @mess;
791              
792             # output plan if there was plan
793 71 100       230 if (defined $self->{plan_tests}) {
794             push @mess, _plan_to_tap( $self->{plan_tests}, $self->{plan_skip} )
795 9 50       84 unless $verbosity < 0;
796             };
797              
798 71         263 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       672 if ($n > 0) {
803 154         336 my $reason = $self->{fail}{$n};
804 154 100       435 my ($level, $prefix) = $reason ? (-2, "not ok") : (0, "ok");
805 154 100       520 my $name = $self->{name}{$n} ? "$n - $self->{name}{$n}" : $n;
806 154         471 push @mess, [ 0, $level, "$prefix $name" ];
807              
808 154 100       442 if ($self->{subcontract}{$n}) {
809             push @mess, map {
810 14         42 [ $_->[0]+1, $_->[1], $_->[2] ];
811 4         6 } @{ $self->{subcontract}{$n}->get_log( $verbosity ) };
  4         43  
812             };
813              
814 154 100 100     843 if (ref $reason eq 'ARRAY') {
    100          
815             push @mess, map {
816 7         16 [ 0, -1, to_scalar( $_ ) ]
  21         45  
817             } @$reason;
818             } elsif ($reason and $reason ne 1) {
819 54         208 push @mess, [ 0, -1, to_scalar( $reason ) ];
820             };
821             };
822              
823             # and all following diags
824 296 100       956 if (my $rest = $self->{messages}{$n} ) {
825 78         230 push @mess, grep { $_->[1] <= $verbosity } @$rest;
  63         362  
826             };
827             };
828              
829 71 100 100     448 if (!defined $self->{plan_tests} and $self->{done}) {
830 57 50       245 push @mess, _plan_to_tap( $self->get_count )
831             unless $verbosity < 0;
832             };
833              
834 71         216 return \@mess;
835             };
836              
837             sub _plan_to_tap {
838 66     66   167 my ($n, $skip) = @_;
839              
840 66         145 my $line = "1..".$n;
841 66 100       256 $line .= " # SKIP $skip"
842             if defined $skip;
843 66         220 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 127 my ($self, $parent) = @_;
869              
870 27 100       109 if (blessed $parent) {
    100          
871 25         51 $self->{parent} = $parent;
872             # avoid a circular loop because $self is likely to be stored
873             # in parent as subcontract
874 25         46 weaken $self->{parent};
875             } elsif (!defined $parent) {
876 1         2 delete $self->{parent};
877             } else {
878 1   50     31 $self->_croak('parent must be a Report object, not a '.(ref $parent || 'scalar'))
879             };
880 26         50 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 859 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 12 my $self = shift;
909              
910 4 100       20 if (!exists $self->{depth}) {
911 3         10 my $parent = $self->get_parent;
912 3 100       16 $self->{depth} = $parent ? $parent->get_depth + 1 : 0;
913             };
914              
915 4         15 return $self->{depth};
916             };
917              
918             sub _croak {
919 19     19   55 my ($self, $mess) = @_;
920              
921 19   50     58 $mess ||= "Something terrible happened";
922 19         182 $mess =~ s/\n+$//s;
923              
924 19         126 my $fun = (caller 1)[3];
925 19         308 $fun =~ s/(.*)::/${1}->/;
926              
927 19         3670 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