| 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__ |