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 |