line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Fennec; |
2
|
137
|
|
|
137
|
|
153618
|
use strict; |
|
137
|
|
|
|
|
551
|
|
|
137
|
|
|
|
|
5710
|
|
3
|
137
|
|
|
137
|
|
1031
|
use warnings; |
|
137
|
|
|
|
|
423
|
|
|
137
|
|
|
|
|
5966
|
|
4
|
|
|
|
|
|
|
|
5
|
137
|
|
|
137
|
|
67806
|
BEGIN { require Fennec::Runner } |
6
|
|
|
|
|
|
|
|
7
|
137
|
|
|
137
|
|
98687
|
use Fennec::Test; |
|
137
|
|
|
|
|
529
|
|
|
137
|
|
|
|
|
10157
|
|
8
|
137
|
|
|
137
|
|
838
|
use Fennec::Util qw/inject_sub require_module verbose_message/; |
|
137
|
|
|
|
|
286
|
|
|
137
|
|
|
|
|
3328
|
|
9
|
137
|
|
|
137
|
|
154211
|
use Carp qw/croak carp/; |
|
137
|
|
|
|
|
342
|
|
|
137
|
|
|
|
|
51173
|
|
10
|
|
|
|
|
|
|
our $VERSION = '2.017'; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub defaults { |
13
|
|
|
|
|
|
|
( |
14
|
274
|
50
|
50
|
274
|
0
|
11274
|
utils => [ |
15
|
|
|
|
|
|
|
'Test::More', |
16
|
|
|
|
|
|
|
'Test::Warn', |
17
|
|
|
|
|
|
|
'Test::Exception', |
18
|
|
|
|
|
|
|
'Test::Workflow', |
19
|
|
|
|
|
|
|
'Mock::Quick', |
20
|
|
|
|
|
|
|
'Child', |
21
|
|
|
|
|
|
|
], |
22
|
|
|
|
|
|
|
parallel => defined $ENV{'FENNEC_PARALLEL'} ? $ENV{'FENNEC_PARALLEL'} : 3, |
23
|
|
|
|
|
|
|
runner_class => 'Fennec::Runner', |
24
|
|
|
|
|
|
|
with_tests => [], |
25
|
|
|
|
|
|
|
Child => ['child'], |
26
|
|
|
|
|
|
|
debug => $ENV{'FENNEC_DEBUG'} || 0, |
27
|
|
|
|
|
|
|
); |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub _setup_class { |
31
|
137
|
|
|
137
|
|
362
|
my $class = shift; |
32
|
137
|
|
|
|
|
551
|
my ( $runner, $importer, $load ) = @_; |
33
|
137
|
100
|
|
|
|
989
|
return unless $load; |
34
|
|
|
|
|
|
|
|
35
|
2
|
|
|
|
|
184
|
require_module $load; |
36
|
|
|
|
|
|
|
|
37
|
137
|
|
|
137
|
|
11205
|
no strict 'refs'; |
|
137
|
|
|
|
|
327
|
|
|
137
|
|
|
|
|
121414
|
|
38
|
2
|
|
|
|
|
29054
|
*{"$importer\::CLASS"} = \$load; |
|
2
|
|
|
|
|
18
|
|
39
|
2
|
|
|
1
|
|
16
|
*{"$importer\::class"} = sub { $load }; |
|
2
|
|
|
|
|
16
|
|
|
1
|
|
|
|
|
72
|
|
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub import { |
43
|
137
|
|
|
137
|
|
158487
|
my $class = shift; |
44
|
137
|
|
|
|
|
451
|
my $importer = caller; |
45
|
|
|
|
|
|
|
|
46
|
137
|
|
|
|
|
828
|
my %defaults = $class->defaults; |
47
|
137
|
|
50
|
|
|
2597
|
$defaults{runner_class} ||= 'Fennec::Runner'; |
48
|
137
|
|
|
|
|
870
|
my %params = ( %defaults, @_ ); |
49
|
|
|
|
|
|
|
|
50
|
137
|
50
|
0
|
|
|
945
|
$ENV{FENNEC_SEED} ||= $params{seed} if $params{seed}; |
51
|
137
|
50
|
0
|
|
|
623
|
$ENV{FENNEC_DEBUG} ||= $params{debug} if $params{debug}; |
52
|
|
|
|
|
|
|
|
53
|
137
|
|
|
|
|
1139
|
my ( $runner, $runner_init ) = $class->_get_runner( |
54
|
|
|
|
|
|
|
$importer, |
55
|
|
|
|
|
|
|
$defaults{runner_class}, |
56
|
|
|
|
|
|
|
$defaults{runner_params}, |
57
|
|
|
|
|
|
|
); |
58
|
|
|
|
|
|
|
|
59
|
137
|
|
|
|
|
3253
|
verbose_message("Entering build stage: $importer\n"); |
60
|
|
|
|
|
|
|
|
61
|
137
|
|
|
|
|
371
|
push @{$runner->test_classes} => $importer; |
|
137
|
|
|
|
|
1002
|
|
62
|
|
|
|
|
|
|
|
63
|
137
|
|
|
|
|
1415
|
my $meta = $class->_init_meta( $importer, %params ); |
64
|
|
|
|
|
|
|
|
65
|
137
|
|
|
|
|
1066
|
$class->_setup_class( $runner, $importer, $params{class} ); |
66
|
137
|
|
|
|
|
1050
|
$class->_process_deps( $runner, $params{skip_without} ); |
67
|
135
|
|
|
|
|
1003
|
$class->_set_isa( $importer, 'Fennec::Test', $meta->base ); |
68
|
135
|
|
|
|
|
925
|
$class->_load_utils( $importer, %params ); |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# Intercept Mock::Quick mocks |
71
|
135
|
|
|
|
|
1340
|
my $wfmeta = $importer->TEST_WORKFLOW; |
72
|
135
|
50
|
33
|
|
|
1593
|
if ( $wfmeta && grep { $_ eq 'Mock::Quick' } @{$defaults{utils} || []}) { |
|
813
|
50
|
|
|
|
2470
|
|
|
135
|
|
|
|
|
872
|
|
73
|
|
|
|
|
|
|
my $intercept = sub { |
74
|
20
|
|
|
20
|
|
46
|
my ($code) = @_; |
75
|
20
|
|
|
|
|
164
|
my @caller = caller; |
76
|
|
|
|
|
|
|
|
77
|
20
|
|
|
|
|
144
|
my $store = $wfmeta->control_store; |
78
|
20
|
100
|
|
|
|
115
|
return push @$store => $code->() if $store; |
79
|
|
|
|
|
|
|
|
80
|
10
|
|
33
|
|
|
45
|
my $layer = $wfmeta->peek_layer || $wfmeta->root_layer; |
81
|
10
|
|
|
|
|
60
|
$layer->add_control($code); |
82
|
135
|
|
|
|
|
1209
|
}; |
83
|
137
|
|
|
137
|
|
1053
|
no strict 'refs'; |
|
137
|
|
|
|
|
278
|
|
|
137
|
|
|
|
|
41861
|
|
84
|
135
|
|
|
20
|
|
610
|
*{"$importer\::QINTERCEPT"} = sub{ $intercept }; |
|
135
|
|
|
|
|
913
|
|
|
20
|
|
|
|
|
2468
|
|
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
135
|
|
|
|
|
1518
|
$class->_with_tests( $importer, $params{with_tests} ); |
88
|
135
|
|
|
|
|
1060
|
$class->init( %params, importer => $importer, meta => $meta ); |
89
|
|
|
|
|
|
|
|
90
|
135
|
50
|
33
|
|
|
1387
|
if ($ENV{FENNEC_DEBUG} || $params{debug}) { |
91
|
0
|
|
|
|
|
0
|
require Time::HiRes; |
92
|
0
|
|
|
|
|
0
|
my $collector; |
93
|
|
|
|
|
|
|
my $debug = sub { |
94
|
0
|
|
|
0
|
|
0
|
my $msg = pop; |
95
|
|
|
|
|
|
|
|
96
|
0
|
|
|
|
|
0
|
my ($sec, $ms) = Time::HiRes::gettimeofday(); |
97
|
0
|
|
|
|
|
0
|
my $line = sprintf( |
98
|
|
|
|
|
|
|
"FENNEC_DEBUG_CUSTOM:PID:%d\0SEC:%d\0MSEC:%d\0MESSAGE:%s\n", |
99
|
|
|
|
|
|
|
$$, |
100
|
|
|
|
|
|
|
$sec, |
101
|
|
|
|
|
|
|
$ms, |
102
|
|
|
|
|
|
|
$msg |
103
|
|
|
|
|
|
|
); |
104
|
0
|
|
0
|
|
|
0
|
$collector ||= Fennec::Runner->new->collector; |
105
|
0
|
|
|
|
|
0
|
$collector->diag($line); |
106
|
0
|
|
|
|
|
0
|
}; |
107
|
137
|
|
|
137
|
|
900
|
no strict 'refs'; |
|
137
|
|
|
|
|
340
|
|
|
137
|
|
|
|
|
35106
|
|
108
|
0
|
|
|
|
|
0
|
*{"$importer\::fennec_debug"} = $debug; |
|
0
|
|
|
|
|
0
|
|
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
$class->_export_done_testing( |
112
|
135
|
|
|
|
|
765
|
$importer, |
113
|
|
|
|
|
|
|
$runner, |
114
|
|
|
|
|
|
|
$runner_init, |
115
|
|
|
|
|
|
|
); |
116
|
|
|
|
|
|
|
|
117
|
135
|
100
|
33
|
|
|
1742
|
$class->after_import({ |
118
|
|
|
|
|
|
|
importer => $importer, |
119
|
|
|
|
|
|
|
runner => $runner, |
120
|
|
|
|
|
|
|
meta => $meta, |
121
|
|
|
|
|
|
|
wf_meta => $wfmeta, |
122
|
|
|
|
|
|
|
layer => $wfmeta->peek_layer || $wfmeta->root_layer, |
123
|
|
|
|
|
|
|
}) if $class->can('after_import'); |
124
|
|
|
|
|
|
|
|
125
|
135
|
|
|
|
|
1030
|
verbose_message("Entering primary stage: $importer\n"); |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
sub init { |
129
|
135
|
|
|
135
|
0
|
330
|
my $class = shift; |
130
|
135
|
|
|
|
|
1010
|
my %params = @_; |
131
|
135
|
|
|
|
|
387
|
my $importer = $params{importer}; |
132
|
135
|
|
|
|
|
359
|
my $meta = $params{meta}; |
133
|
|
|
|
|
|
|
|
134
|
135
|
|
|
|
|
578
|
my $wfmeta = $importer->TEST_WORKFLOW; |
135
|
135
|
100
|
|
|
|
869
|
$wfmeta->test_sort( $meta->test_sort ) |
136
|
|
|
|
|
|
|
if $meta->test_sort; |
137
|
|
|
|
|
|
|
|
138
|
137
|
|
|
137
|
|
1038
|
no strict 'refs'; |
|
137
|
|
|
|
|
310
|
|
|
137
|
|
|
|
|
128338
|
|
139
|
135
|
|
|
|
|
287
|
my $stash = \%{"$importer\::"}; |
|
135
|
|
|
|
|
745
|
|
140
|
135
|
|
|
|
|
1456
|
delete $stash->{$_} for qw/run_tests done_testing/; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub _get_runner { |
144
|
137
|
|
|
137
|
|
335
|
my $class = shift; |
145
|
137
|
|
|
|
|
705
|
my ( $importer, $runner_class, $runner_params ) = @_; |
146
|
|
|
|
|
|
|
|
147
|
137
|
|
|
|
|
819
|
require_module $runner_class; |
148
|
137
|
|
|
|
|
1368
|
my $runner_init = $runner_class->is_initialized; |
149
|
|
|
|
|
|
|
|
150
|
137
|
50
|
66
|
|
|
5359
|
croak "Fennec cannot be used in package 'main' when the test is used with Fennec::Finder" |
151
|
|
|
|
|
|
|
if $runner_init && $importer eq 'main'; |
152
|
|
|
|
|
|
|
|
153
|
137
|
100
|
|
|
|
537
|
if ($runner_init) { |
154
|
48
|
|
|
|
|
359
|
my $runner = $runner_class->new; |
155
|
48
|
50
|
|
|
|
884
|
carp "Runner is already initialized, but it is not a $runner_class" |
156
|
|
|
|
|
|
|
unless $runner->isa($runner_class); |
157
|
|
|
|
|
|
|
|
158
|
48
|
50
|
|
|
|
180
|
carp "Runner is already initialized, ignoring 'runner_params'" |
159
|
|
|
|
|
|
|
if $runner_params; |
160
|
|
|
|
|
|
|
|
161
|
48
|
|
|
|
|
211
|
return ( $runner, $runner_init ); |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
89
|
50
|
|
|
|
784
|
my $runner = $runner_class->new( |
165
|
|
|
|
|
|
|
parallel => 0, |
166
|
|
|
|
|
|
|
$runner_params ? (%$runner_params) : (), |
167
|
|
|
|
|
|
|
); |
168
|
|
|
|
|
|
|
|
169
|
89
|
|
|
|
|
53498
|
require Fennec::EndRunner; |
170
|
89
|
|
|
|
|
707
|
Fennec::EndRunner->set_pid($$); |
171
|
89
|
|
|
|
|
365
|
Fennec::EndRunner->set_runner($runner); |
172
|
|
|
|
|
|
|
|
173
|
89
|
|
|
|
|
437
|
return ( $runner, $runner_init ); |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub _process_deps { |
177
|
137
|
|
|
137
|
|
329
|
my $class = shift; |
178
|
137
|
|
|
|
|
2160
|
my ( $runner, $deps ) = @_; |
179
|
|
|
|
|
|
|
|
180
|
137
|
100
|
66
|
|
|
984
|
return unless $deps && @$deps; |
181
|
|
|
|
|
|
|
|
182
|
2
|
|
|
|
|
9
|
for my $require (@$deps) { |
183
|
2
|
50
|
|
|
|
4
|
unless ( eval { require_module $require; 1 } ) { |
|
2
|
|
|
|
|
9
|
|
|
0
|
|
|
|
|
0
|
|
184
|
2
|
|
|
|
|
32
|
$runner->_skip_all(1); |
185
|
2
|
|
|
|
|
16
|
$runner->collector->skip("'$require' is not installed"); |
186
|
2
|
|
|
|
|
10
|
$runner->collector->finish; |
187
|
2
|
|
|
|
|
1568
|
exit 0; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub _init_meta { |
193
|
137
|
|
|
137
|
|
371
|
my $class = shift; |
194
|
137
|
|
|
|
|
845
|
my ( $importer, %params ) = @_; |
195
|
|
|
|
|
|
|
|
196
|
137
|
|
|
|
|
89278
|
require Fennec::Meta; |
197
|
|
|
|
|
|
|
|
198
|
137
|
|
|
|
|
1364
|
my $meta = Fennec::Meta->new( |
199
|
|
|
|
|
|
|
%params, |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
# Well, this is confusing. |
202
|
|
|
|
|
|
|
fennec => $class, |
203
|
|
|
|
|
|
|
class => $importer, |
204
|
|
|
|
|
|
|
); |
205
|
|
|
|
|
|
|
|
206
|
137
|
|
|
1495
|
|
1800
|
inject_sub( $importer, 'FENNEC', sub { $meta } ); |
|
1495
|
|
|
|
|
15977
|
|
207
|
|
|
|
|
|
|
|
208
|
137
|
|
|
|
|
529
|
return $meta; |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub _set_isa { |
212
|
135
|
|
|
135
|
|
397
|
my $class = shift; |
213
|
135
|
|
|
|
|
454
|
my ( $importer, @bases ) = @_; |
214
|
|
|
|
|
|
|
|
215
|
135
|
|
|
|
|
420
|
for my $base (@bases) { |
216
|
270
|
100
|
|
|
|
1333
|
next unless $base; |
217
|
137
|
|
|
137
|
|
989
|
no strict 'refs'; |
|
137
|
|
|
|
|
362
|
|
|
137
|
|
|
|
|
57309
|
|
218
|
135
|
|
|
|
|
608
|
require_module $base; |
219
|
135
|
|
|
|
|
2852
|
push @{"$importer\::ISA"} => $base |
|
0
|
|
|
|
|
0
|
|
220
|
135
|
50
|
|
|
|
247
|
unless grep { $_ eq $base } @{"$importer\::ISA"}; |
|
135
|
|
|
|
|
2025
|
|
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
sub _load_utils { |
225
|
135
|
|
|
135
|
|
330
|
my $class = shift; |
226
|
135
|
|
|
|
|
577
|
my ( $importer, %params ) = @_; |
227
|
|
|
|
|
|
|
|
228
|
135
|
|
|
|
|
320
|
my $utils = $params{utils}; |
229
|
135
|
50
|
33
|
|
|
1433
|
return unless $utils && @$utils; |
230
|
|
|
|
|
|
|
|
231
|
135
|
|
|
|
|
375
|
for my $util (@$utils) { |
232
|
813
|
|
|
|
|
4197
|
require_module $util; |
233
|
813
|
|
100
|
|
|
4949016
|
my $args = $params{$util} || []; |
234
|
813
|
|
|
|
|
3179
|
my $code = "package $importer; $util\->import(\@\$args); 1"; |
235
|
813
|
50
|
|
|
|
80162
|
eval $code || die $@; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
sub _with_tests { |
240
|
135
|
|
|
135
|
|
345
|
my $class = shift; |
241
|
135
|
|
|
|
|
376
|
my ( $importer, $classes ) = @_; |
242
|
|
|
|
|
|
|
|
243
|
135
|
100
|
66
|
|
|
1309
|
return unless $classes && @$classes; |
244
|
|
|
|
|
|
|
|
245
|
2
|
|
|
|
|
10
|
$importer->TEST_WORKFLOW->root_layer->merge_in( undef, @$classes ); |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub _export_done_testing { |
249
|
135
|
|
|
135
|
|
337
|
my $class = shift; |
250
|
135
|
|
|
|
|
1213
|
my ( $importer, $runner, $runner_init ) = @_; |
251
|
|
|
|
|
|
|
|
252
|
135
|
100
|
|
|
|
513
|
if ($runner_init) { |
253
|
137
|
|
|
137
|
|
900
|
no strict 'refs'; |
|
137
|
|
|
|
|
286
|
|
|
137
|
|
|
|
|
5369
|
|
254
|
137
|
|
|
137
|
|
833
|
no warnings 'redefine'; |
|
137
|
|
|
|
|
281
|
|
|
137
|
|
|
|
|
48554
|
|
255
|
47
|
|
|
|
|
568
|
*{"$importer\::done_testing"} = sub { |
256
|
47
|
100
|
|
47
|
|
511
|
$importer->FENNEC->post(@_) if @_; |
257
|
47
|
|
|
|
|
621
|
return 1; |
258
|
47
|
|
|
|
|
289
|
}; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
else { |
261
|
137
|
|
|
137
|
|
887
|
no strict 'refs'; |
|
137
|
|
|
|
|
1255
|
|
|
137
|
|
|
|
|
5425
|
|
262
|
137
|
|
|
137
|
|
1087
|
no warnings 'redefine'; |
|
137
|
|
|
|
|
371
|
|
|
137
|
|
|
|
|
25394
|
|
263
|
88
|
|
|
|
|
203
|
my $has_run = 0; |
264
|
88
|
|
|
|
|
578
|
*{"$importer\::done_testing"} = sub { |
265
|
77
|
50
|
|
77
|
|
2418
|
croak "done_testing() called more than once!" |
266
|
|
|
|
|
|
|
if $has_run++; |
267
|
|
|
|
|
|
|
|
268
|
77
|
|
|
|
|
852
|
Fennec::EndRunner->set_runner(undef); |
269
|
|
|
|
|
|
|
|
270
|
77
|
100
|
|
|
|
429
|
$importer->FENNEC->post(@_) if @_; |
271
|
77
|
|
|
|
|
593
|
$runner->run(); |
272
|
|
|
|
|
|
|
|
273
|
18
|
|
|
|
|
3058
|
1; |
274
|
88
|
|
|
|
|
476
|
}; |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
1; |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
__END__ |