line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package TAP::Formatter::Base; |
2
|
|
|
|
|
|
|
|
3
|
17
|
|
|
17
|
|
5878
|
use strict; |
|
17
|
|
|
|
|
23
|
|
|
17
|
|
|
|
|
444
|
|
4
|
17
|
|
|
17
|
|
64
|
use warnings; |
|
17
|
|
|
|
|
19
|
|
|
17
|
|
|
|
|
435
|
|
5
|
17
|
|
|
17
|
|
58
|
use base 'TAP::Base'; |
|
17
|
|
|
|
|
21
|
|
|
17
|
|
|
|
|
1410
|
|
6
|
17
|
|
|
17
|
|
1672
|
use POSIX qw(strftime); |
|
17
|
|
|
|
|
17209
|
|
|
17
|
|
|
|
|
77
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
my $MAX_ERRORS = 5; |
9
|
|
|
|
|
|
|
my %VALIDATION_FOR; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
BEGIN { |
12
|
|
|
|
|
|
|
%VALIDATION_FOR = ( |
13
|
2
|
|
|
|
|
3
|
directives => sub { shift; shift }, |
|
2
|
|
|
|
|
9
|
|
14
|
66
|
|
|
|
|
70
|
verbosity => sub { shift; shift }, |
|
66
|
|
|
|
|
149
|
|
15
|
0
|
|
|
|
|
0
|
normalize => sub { shift; shift }, |
|
0
|
|
|
|
|
0
|
|
16
|
41
|
|
|
|
|
40
|
timer => sub { shift; shift }, |
|
41
|
|
|
|
|
93
|
|
17
|
6
|
|
|
|
|
7
|
failures => sub { shift; shift }, |
|
6
|
|
|
|
|
19
|
|
18
|
3
|
|
|
|
|
2
|
comments => sub { shift; shift }, |
|
3
|
|
|
|
|
8
|
|
19
|
1
|
|
|
|
|
2
|
errors => sub { shift; shift }, |
|
1
|
|
|
|
|
12
|
|
20
|
40
|
|
|
|
|
49
|
color => sub { shift; shift }, |
|
40
|
|
|
|
|
110
|
|
21
|
86
|
|
|
|
|
93
|
jobs => sub { shift; shift }, |
|
86
|
|
|
|
|
243
|
|
22
|
2
|
|
|
|
|
3
|
show_count => sub { shift; shift }, |
|
2
|
|
|
|
|
8
|
|
23
|
|
|
|
|
|
|
stdout => sub { |
24
|
15
|
|
|
|
|
21
|
my ( $self, $ref ) = @_; |
25
|
|
|
|
|
|
|
|
26
|
15
|
100
|
|
|
|
36
|
$self->_croak("option 'stdout' needs a filehandle") |
27
|
|
|
|
|
|
|
unless $self->_is_filehandle($ref); |
28
|
|
|
|
|
|
|
|
29
|
13
|
|
|
|
|
30
|
return $ref; |
30
|
|
|
|
|
|
|
}, |
31
|
17
|
|
|
17
|
|
10946
|
); |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub _is_filehandle { |
34
|
15
|
|
|
15
|
|
15
|
my ( $self, $ref ) = @_; |
35
|
|
|
|
|
|
|
|
36
|
15
|
50
|
|
|
|
30
|
return 0 if !defined $ref; |
37
|
|
|
|
|
|
|
|
38
|
15
|
100
|
|
|
|
39
|
return 1 if ref $ref eq 'GLOB'; # lexical filehandle |
39
|
13
|
100
|
100
|
|
|
45
|
return 1 if !ref $ref && ref \$ref eq 'GLOB'; # bare glob like *STDOUT |
40
|
|
|
|
|
|
|
|
41
|
12
|
100
|
|
|
|
13
|
return 1 if eval { $ref->can('print') }; |
|
12
|
|
|
|
|
90
|
|
42
|
|
|
|
|
|
|
|
43
|
2
|
|
|
|
|
17
|
return 0; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
17
|
|
|
|
|
55
|
my @getter_setters = qw( |
47
|
|
|
|
|
|
|
_longest |
48
|
|
|
|
|
|
|
_printed_summary_header |
49
|
|
|
|
|
|
|
_colorizer |
50
|
|
|
|
|
|
|
); |
51
|
|
|
|
|
|
|
|
52
|
17
|
|
|
|
|
190
|
__PACKAGE__->mk_methods( @getter_setters, keys %VALIDATION_FOR ); |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head1 NAME |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
TAP::Formatter::Base - Base class for harness output delegates |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head1 VERSION |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
Version 3.38 |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=cut |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
our $VERSION = '3.38'; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=head1 DESCRIPTION |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
This provides console orientated output formatting for TAP::Harness. |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=head1 SYNOPSIS |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
use TAP::Formatter::Console; |
74
|
|
|
|
|
|
|
my $harness = TAP::Formatter::Console->new( \%args ); |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=cut |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub _initialize { |
79
|
88
|
|
|
88
|
|
118
|
my ( $self, $arg_for ) = @_; |
80
|
88
|
|
100
|
|
|
212
|
$arg_for ||= {}; |
81
|
|
|
|
|
|
|
|
82
|
88
|
|
|
|
|
302
|
$self->SUPER::_initialize($arg_for); |
83
|
88
|
|
|
|
|
345
|
my %arg_for = %$arg_for; # force a shallow copy |
84
|
|
|
|
|
|
|
|
85
|
88
|
|
|
|
|
323
|
$self->verbosity(0); |
86
|
|
|
|
|
|
|
|
87
|
88
|
|
|
|
|
330
|
for my $name ( keys %VALIDATION_FOR ) { |
88
|
958
|
|
|
|
|
738
|
my $property = delete $arg_for{$name}; |
89
|
958
|
100
|
|
|
|
1301
|
if ( defined $property ) { |
90
|
262
|
|
|
|
|
242
|
my $validate = $VALIDATION_FOR{$name}; |
91
|
262
|
|
|
|
|
512
|
$self->$name( $self->$validate($property) ); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
86
|
50
|
|
|
|
278
|
if ( my @props = keys %arg_for ) { |
96
|
0
|
|
|
|
|
0
|
$self->_croak( |
97
|
|
|
|
|
|
|
"Unknown arguments to " . __PACKAGE__ . "::new (@props)" ); |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
86
|
100
|
|
|
|
262
|
$self->stdout( \*STDOUT ) unless $self->stdout; |
101
|
|
|
|
|
|
|
|
102
|
86
|
100
|
|
|
|
223
|
if ( $self->color ) { |
103
|
1
|
|
|
|
|
328
|
require TAP::Formatter::Color; |
104
|
1
|
|
|
|
|
9
|
$self->_colorizer( TAP::Formatter::Color->new ); |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
86
|
|
|
|
|
312
|
return $self; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
423
|
|
|
423
|
1
|
882
|
sub verbose { shift->verbosity >= 1 } |
111
|
398
|
|
|
398
|
1
|
784
|
sub quiet { shift->verbosity <= -1 } |
112
|
142
|
|
|
142
|
1
|
319
|
sub really_quiet { shift->verbosity <= -2 } |
113
|
44
|
|
|
44
|
1
|
92
|
sub silent { shift->verbosity <= -3 } |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=head1 METHODS |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=head2 Class Methods |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=head3 C |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
my %args = ( |
122
|
|
|
|
|
|
|
verbose => 1, |
123
|
|
|
|
|
|
|
) |
124
|
|
|
|
|
|
|
my $harness = TAP::Formatter::Console->new( \%args ); |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
The constructor returns a new C object. If |
127
|
|
|
|
|
|
|
a L is created with no C a |
128
|
|
|
|
|
|
|
C is automatically created. If any of the |
129
|
|
|
|
|
|
|
following options were given to TAP::Harness->new they well be passed to |
130
|
|
|
|
|
|
|
this constructor which accepts an optional hashref whose allowed keys are: |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=over 4 |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=item * C |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
Set the verbosity level. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=item * C |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
Printing individual test results to STDOUT. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=item * C |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
Append run time for each test to output. Uses L if available. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=item * C |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
Show test failures (this is a no-op if C is selected). |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=item * C |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
Show test comments (this is a no-op if C is selected). |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=item * C |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
Suppressing some test output (mostly failures while tests are running). |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=item * C |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
Suppressing everything but the tests summary. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=item * C |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
Suppressing all output. |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=item * C |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
If parse errors are found in the TAP output, a note of this will be made |
169
|
|
|
|
|
|
|
in the summary report. To see all of the parse errors, set this argument to |
170
|
|
|
|
|
|
|
true: |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
errors => 1 |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=item * C |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
If set to a true value, only test results with directives will be displayed. |
177
|
|
|
|
|
|
|
This overrides other settings such as C, C, or C. |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=item * C |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
A filehandle for catching standard output. |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=item * C |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
If defined specifies whether color output is desired. If C is not |
186
|
|
|
|
|
|
|
defined it will default to color output if color support is available on |
187
|
|
|
|
|
|
|
the current platform and output is not being redirected. |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=item * C |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
The number of concurrent jobs this formatter will handle. |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=item * C |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
Boolean value. If false, disables the C test count which shows up while |
196
|
|
|
|
|
|
|
tests are running. |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=back |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
Any keys for which the value is C will be ignored. |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=cut |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
# new supplied by TAP::Base |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=head3 C |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
Called by Test::Harness before any test output is generated. |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
This is an advisory and may not be called in the case where tests are |
211
|
|
|
|
|
|
|
being supplied to Test::Harness by an iterator. |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=cut |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub prepare { |
216
|
79
|
|
|
79
|
1
|
131
|
my ( $self, @tests ) = @_; |
217
|
|
|
|
|
|
|
|
218
|
79
|
|
|
|
|
102
|
my $longest = 0; |
219
|
|
|
|
|
|
|
|
220
|
79
|
|
|
|
|
204
|
for my $test (@tests) { |
221
|
107
|
100
|
|
|
|
246
|
$longest = length $test if length $test > $longest; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
79
|
|
|
|
|
238
|
$self->_longest($longest); |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
0
|
|
|
0
|
|
0
|
sub _format_now { strftime "[%H:%M:%S]", localtime } |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
sub _format_name { |
230
|
105
|
|
|
105
|
|
159
|
my ( $self, $test ) = @_; |
231
|
105
|
|
|
|
|
141
|
my $name = $test; |
232
|
105
|
|
|
|
|
473
|
my $periods = '.' x ( $self->_longest + 2 - length $test ); |
233
|
105
|
|
|
|
|
230
|
$periods = " $periods "; |
234
|
|
|
|
|
|
|
|
235
|
105
|
50
|
|
|
|
291
|
if ( $self->timer ) { |
236
|
0
|
|
|
|
|
0
|
my $stamp = $self->_format_now(); |
237
|
0
|
|
|
|
|
0
|
return "$stamp $name$periods"; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
else { |
240
|
105
|
|
|
|
|
315
|
return "$name$periods"; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=head3 C |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
Called to create a new test session. A test session looks like this: |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
my $session = $formatter->open_test( $test, $parser ); |
250
|
|
|
|
|
|
|
while ( defined( my $result = $parser->next ) ) { |
251
|
|
|
|
|
|
|
$session->result($result); |
252
|
|
|
|
|
|
|
exit 1 if $result->is_bailout; |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
$session->close_test; |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=cut |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub open_test { |
259
|
0
|
|
|
0
|
1
|
0
|
die "Unimplemented."; |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
sub _output_success { |
263
|
18
|
|
|
18
|
|
33
|
my ( $self, $msg ) = @_; |
264
|
18
|
|
|
|
|
46
|
$self->_output($msg); |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
=head3 C |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
$harness->summary( $aggregate ); |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
C prints the summary report after all tests are run. The first |
272
|
|
|
|
|
|
|
argument is an aggregate to summarise. An optional second argument may |
273
|
|
|
|
|
|
|
be set to a true value to indicate that the summary is being output as a |
274
|
|
|
|
|
|
|
result of an interrupted test run. |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=cut |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub summary { |
279
|
44
|
|
|
44
|
1
|
64
|
my ( $self, $aggregate, $interrupted ) = @_; |
280
|
|
|
|
|
|
|
|
281
|
44
|
100
|
|
|
|
121
|
return if $self->silent; |
282
|
|
|
|
|
|
|
|
283
|
38
|
|
|
|
|
109
|
my @t = $aggregate->descriptions; |
284
|
38
|
|
|
|
|
60
|
my $tests = \@t; |
285
|
|
|
|
|
|
|
|
286
|
38
|
|
|
|
|
92
|
my $runtime = $aggregate->elapsed_timestr; |
287
|
|
|
|
|
|
|
|
288
|
38
|
|
|
|
|
2581
|
my $total = $aggregate->total; |
289
|
38
|
|
|
|
|
113
|
my $passed = $aggregate->passed; |
290
|
|
|
|
|
|
|
|
291
|
38
|
50
|
|
|
|
81
|
if ( $self->timer ) { |
292
|
0
|
|
|
|
|
0
|
$self->_output( $self->_format_now(), "\n" ); |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
38
|
50
|
|
|
|
81
|
$self->_failure_output("Test run interrupted!\n") |
296
|
|
|
|
|
|
|
if $interrupted; |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
# TODO: Check this condition still works when all subtests pass but |
299
|
|
|
|
|
|
|
# the exit status is nonzero |
300
|
|
|
|
|
|
|
|
301
|
38
|
100
|
|
|
|
96
|
if ( $aggregate->all_passed ) { |
302
|
24
|
|
|
|
|
74
|
$self->_output_success("All tests successful.\n"); |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
# ~TODO option where $aggregate->skipped generates reports |
306
|
38
|
100
|
100
|
|
|
342
|
if ( $total != $passed or $aggregate->has_problems ) { |
307
|
15
|
|
|
|
|
46
|
$self->_output("\nTest Summary Report"); |
308
|
15
|
|
|
|
|
240
|
$self->_output("\n-------------------\n"); |
309
|
15
|
|
|
|
|
190
|
for my $test (@$tests) { |
310
|
15
|
|
|
|
|
75
|
$self->_printed_summary_header(0); |
311
|
15
|
|
|
|
|
50
|
my ($parser) = $aggregate->parsers($test); |
312
|
15
|
|
|
|
|
75
|
$self->_output_summary_failure( |
313
|
|
|
|
|
|
|
'failed', |
314
|
|
|
|
|
|
|
[ ' Failed test: ', ' Failed tests: ' ], |
315
|
|
|
|
|
|
|
$test, $parser |
316
|
|
|
|
|
|
|
); |
317
|
15
|
|
|
|
|
34
|
$self->_output_summary_failure( |
318
|
|
|
|
|
|
|
'todo_passed', |
319
|
|
|
|
|
|
|
" TODO passed: ", $test, $parser |
320
|
|
|
|
|
|
|
); |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# ~TODO this cannot be the default |
323
|
|
|
|
|
|
|
#$self->_output_summary_failure( 'skipped', " Tests skipped: " ); |
324
|
|
|
|
|
|
|
|
325
|
15
|
50
|
|
|
|
36
|
if ( my $exit = $parser->exit ) { |
|
|
50
|
|
|
|
|
|
326
|
0
|
|
|
|
|
0
|
$self->_summary_test_header( $test, $parser ); |
327
|
0
|
|
|
|
|
0
|
$self->_failure_output(" Non-zero exit status: $exit\n"); |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
elsif ( my $wait = $parser->wait ) { |
330
|
0
|
|
|
|
|
0
|
$self->_summary_test_header( $test, $parser ); |
331
|
0
|
|
|
|
|
0
|
$self->_failure_output(" Non-zero wait status: $wait\n"); |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
15
|
100
|
|
|
|
31
|
if ( my @errors = $parser->parse_errors ) { |
335
|
4
|
|
|
|
|
8
|
my $explain; |
336
|
4
|
50
|
33
|
|
|
19
|
if ( @errors > $MAX_ERRORS && !$self->errors ) { |
337
|
0
|
|
|
|
|
0
|
$explain |
338
|
|
|
|
|
|
|
= "Displayed the first $MAX_ERRORS of " |
339
|
|
|
|
|
|
|
. scalar(@errors) |
340
|
|
|
|
|
|
|
. " TAP syntax errors.\n" |
341
|
|
|
|
|
|
|
. "Re-run prove with the -p option to see them all.\n"; |
342
|
0
|
|
|
|
|
0
|
splice @errors, $MAX_ERRORS; |
343
|
|
|
|
|
|
|
} |
344
|
4
|
|
|
|
|
15
|
$self->_summary_test_header( $test, $parser ); |
345
|
4
|
|
|
|
|
18
|
$self->_failure_output( |
346
|
|
|
|
|
|
|
sprintf " Parse errors: %s\n", |
347
|
|
|
|
|
|
|
shift @errors |
348
|
|
|
|
|
|
|
); |
349
|
4
|
|
|
|
|
43
|
for my $error (@errors) { |
350
|
0
|
|
|
|
|
0
|
my $spaces = ' ' x 16; |
351
|
0
|
|
|
|
|
0
|
$self->_failure_output("$spaces$error\n"); |
352
|
|
|
|
|
|
|
} |
353
|
4
|
50
|
|
|
|
17
|
$self->_failure_output($explain) if $explain; |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
} |
357
|
38
|
|
|
|
|
50
|
my $files = @$tests; |
358
|
38
|
|
|
|
|
136
|
$self->_output("Files=$files, Tests=$total, $runtime\n"); |
359
|
38
|
|
|
|
|
461
|
my $status = $aggregate->get_status; |
360
|
38
|
|
|
|
|
104
|
$self->_output("Result: $status\n"); |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
sub _output_summary_failure { |
364
|
30
|
|
|
30
|
|
38
|
my ( $self, $method, $name, $test, $parser ) = @_; |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
# ugly hack. Must rethink this :( |
367
|
30
|
100
|
|
|
|
62
|
my $output = $method eq 'failed' ? '_failure_output' : '_output'; |
368
|
|
|
|
|
|
|
|
369
|
30
|
100
|
|
|
|
77
|
if ( my @r = $parser->$method() ) { |
370
|
13
|
|
|
|
|
39
|
$self->_summary_test_header( $test, $parser ); |
371
|
13
|
100
|
|
|
|
47
|
my ( $singular, $plural ) |
372
|
|
|
|
|
|
|
= 'ARRAY' eq ref $name ? @$name : ( $name, $name ); |
373
|
13
|
50
|
|
|
|
42
|
$self->$output( @r == 1 ? $singular : $plural ); |
374
|
13
|
|
|
|
|
129
|
my @results = $self->_balanced_range( 40, @r ); |
375
|
13
|
|
|
|
|
50
|
$self->$output( sprintf "%s\n" => shift @results ); |
376
|
13
|
|
|
|
|
98
|
my $spaces = ' ' x 16; |
377
|
13
|
|
|
|
|
43
|
while (@results) { |
378
|
0
|
|
|
|
|
0
|
$self->$output( sprintf "$spaces%s\n" => shift @results ); |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
sub _summary_test_header { |
384
|
17
|
|
|
17
|
|
21
|
my ( $self, $test, $parser ) = @_; |
385
|
17
|
100
|
|
|
|
31
|
return if $self->_printed_summary_header; |
386
|
15
|
|
|
|
|
32
|
my $spaces = ' ' x ( $self->_longest - length $test ); |
387
|
15
|
50
|
|
|
|
28
|
$spaces = ' ' unless $spaces; |
388
|
15
|
|
|
|
|
35
|
my $output = $self->_get_output_method($parser); |
389
|
15
|
|
|
|
|
47
|
my $wait = $parser->wait; |
390
|
15
|
50
|
|
|
|
32
|
defined $wait or $wait = '(none)'; |
391
|
15
|
|
|
|
|
52
|
$self->$output( |
392
|
|
|
|
|
|
|
sprintf "$test$spaces(Wstat: %s Tests: %d Failed: %d)\n", |
393
|
|
|
|
|
|
|
$wait, $parser->tests_run, scalar $parser->failed |
394
|
|
|
|
|
|
|
); |
395
|
15
|
|
|
|
|
185
|
$self->_printed_summary_header(1); |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
sub _output { |
399
|
162
|
|
|
162
|
|
180
|
my $self = shift; |
400
|
|
|
|
|
|
|
|
401
|
162
|
|
|
|
|
183
|
print { $self->stdout } @_; |
|
162
|
|
|
|
|
328
|
|
402
|
|
|
|
|
|
|
} |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
sub _failure_output { |
405
|
68
|
|
|
68
|
|
71
|
my $self = shift; |
406
|
|
|
|
|
|
|
|
407
|
68
|
|
|
|
|
136
|
$self->_output(@_); |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
sub _balanced_range { |
411
|
14
|
|
|
14
|
|
762
|
my ( $self, $limit, @range ) = @_; |
412
|
14
|
|
|
|
|
42
|
@range = $self->_range(@range); |
413
|
14
|
|
|
|
|
18
|
my $line = ""; |
414
|
14
|
|
|
|
|
15
|
my @lines; |
415
|
14
|
|
|
|
|
16
|
my $curr = 0; |
416
|
14
|
|
|
|
|
31
|
while (@range) { |
417
|
17
|
100
|
|
|
|
39
|
if ( $curr < $limit ) { |
|
|
50
|
|
|
|
|
|
418
|
16
|
|
|
|
|
30
|
my $range = ( shift @range ) . ", "; |
419
|
16
|
|
|
|
|
27
|
$line .= $range; |
420
|
16
|
|
|
|
|
40
|
$curr += length $range; |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
elsif (@range) { |
423
|
1
|
|
|
|
|
7
|
$line =~ s/, $//; |
424
|
1
|
|
|
|
|
3
|
push @lines => $line; |
425
|
1
|
|
|
|
|
2
|
$line = ''; |
426
|
1
|
|
|
|
|
4
|
$curr = 0; |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
} |
429
|
14
|
50
|
|
|
|
39
|
if ($line) { |
430
|
14
|
|
|
|
|
59
|
$line =~ s/, $//; |
431
|
14
|
|
|
|
|
23
|
push @lines => $line; |
432
|
|
|
|
|
|
|
} |
433
|
14
|
|
|
|
|
33
|
return @lines; |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
sub _range { |
437
|
15
|
|
|
15
|
|
994
|
my ( $self, @numbers ) = @_; |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
# shouldn't be needed, but subclasses might call this |
440
|
15
|
|
|
|
|
31
|
@numbers = sort { $a <=> $b } @numbers; |
|
20
|
|
|
|
|
19
|
|
441
|
15
|
|
|
|
|
21
|
my ( $min, @range ); |
442
|
|
|
|
|
|
|
|
443
|
15
|
|
|
|
|
51
|
for my $i ( 0 .. $#numbers ) { |
444
|
25
|
|
|
|
|
37
|
my $num = $numbers[$i]; |
445
|
25
|
|
|
|
|
33
|
my $next = $numbers[ $i + 1 ]; |
446
|
25
|
100
|
100
|
|
|
94
|
if ( defined $next && $next == $num + 1 ) { |
|
|
100
|
|
|
|
|
|
447
|
6
|
100
|
|
|
|
13
|
if ( !defined $min ) { |
448
|
4
|
|
|
|
|
7
|
$min = $num; |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
elsif ( defined $min ) { |
452
|
4
|
|
|
|
|
7
|
push @range => "$min-$num"; |
453
|
4
|
|
|
|
|
7
|
undef $min; |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
else { |
456
|
15
|
|
|
|
|
33
|
push @range => $num; |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
} |
459
|
15
|
|
|
|
|
43
|
return @range; |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
sub _get_output_method { |
463
|
54
|
|
|
54
|
|
54
|
my ( $self, $parser ) = @_; |
464
|
54
|
100
|
|
|
|
90
|
return $parser->has_problems ? '_failure_output' : '_output'; |
465
|
|
|
|
|
|
|
} |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
1; |