File Coverage

blib/lib/Assert/Refute/Report.pm
Criterion Covered Total %
statement 220 220 100.0
branch 111 120 92.5
condition 47 68 69.1
subroutine 34 34 100.0
pod 25 25 100.0
total 437 467 93.5


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