line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test::Kit; |
2
|
|
|
|
|
|
|
$Test::Kit::VERSION = '2.15'; |
3
|
23
|
|
|
23
|
|
33487
|
use strict; |
|
23
|
|
|
|
|
27
|
|
|
23
|
|
|
|
|
527
|
|
4
|
23
|
|
|
23
|
|
76
|
use warnings; |
|
23
|
|
|
|
|
21
|
|
|
23
|
|
|
|
|
494
|
|
5
|
|
|
|
|
|
|
|
6
|
23
|
|
|
23
|
|
8025
|
use Import::Into; |
|
23
|
|
|
|
|
45187
|
|
|
23
|
|
|
|
|
563
|
|
7
|
23
|
|
|
23
|
|
100
|
use Module::Runtime 'use_module', 'module_notional_filename'; |
|
23
|
|
|
|
|
23
|
|
|
23
|
|
|
|
|
64
|
|
8
|
23
|
|
|
23
|
|
8659
|
use Sub::Delete; |
|
23
|
|
|
|
|
13826
|
|
|
23
|
|
|
|
|
1065
|
|
9
|
23
|
|
|
23
|
|
10571
|
use Test::Builder (); |
|
23
|
|
|
|
|
148289
|
|
|
23
|
|
|
|
|
439
|
|
10
|
23
|
|
|
23
|
|
10106
|
use Test::More (); |
|
23
|
|
|
|
|
85914
|
|
|
23
|
|
|
|
|
489
|
|
11
|
23
|
|
|
23
|
|
99
|
use Scalar::Util qw(refaddr); |
|
23
|
|
|
|
|
26
|
|
|
23
|
|
|
|
|
1754
|
|
12
|
23
|
|
|
23
|
|
8482
|
use Hook::LexWrap qw(wrap); |
|
23
|
|
|
|
|
52041
|
|
|
23
|
|
|
|
|
95
|
|
13
|
|
|
|
|
|
|
|
14
|
23
|
|
|
23
|
|
8450
|
use parent 'Exporter'; |
|
23
|
|
|
|
|
5191
|
|
|
23
|
|
|
|
|
118
|
|
15
|
|
|
|
|
|
|
our @EXPORT = ('include'); |
16
|
|
|
|
|
|
|
# my %test_kits_cache = ( |
17
|
|
|
|
|
|
|
# 'MyTest::Awesome' => { |
18
|
|
|
|
|
|
|
# 'ok' => { source => [ 'Test::More' ], refaddr => 0x1234, }, |
19
|
|
|
|
|
|
|
# 'pass' => { source => [ 'Test::Simple', 'Test::More' ], refaddr => 0xbeef, }, |
20
|
|
|
|
|
|
|
# 'warnings_are' => { source => [ 'Test::Warn' ], refaddr => 0xbead, }, |
21
|
|
|
|
|
|
|
# ... |
22
|
|
|
|
|
|
|
# }, |
23
|
|
|
|
|
|
|
# ... |
24
|
|
|
|
|
|
|
# ) |
25
|
|
|
|
|
|
|
# |
26
|
|
|
|
|
|
|
my %test_kits_cache; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
sub include { |
29
|
43
|
|
|
43
|
0
|
4722
|
my @to_include = @_; |
30
|
|
|
|
|
|
|
|
31
|
43
|
|
|
|
|
52
|
my $class = __PACKAGE__; |
32
|
|
|
|
|
|
|
|
33
|
43
|
|
|
|
|
38
|
my $include_hashref; |
34
|
43
|
100
|
|
|
|
52
|
if (grep { ref($_) } @to_include) { |
|
56
|
|
|
|
|
159
|
|
35
|
11
|
|
|
|
|
17
|
$include_hashref = { @to_include }; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
else { |
38
|
32
|
|
|
|
|
47
|
$include_hashref = { map { $_ => {} } @to_include }; |
|
34
|
|
|
|
|
86
|
|
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
43
|
|
|
|
|
88
|
return $class->_include($include_hashref); |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub _include { |
45
|
43
|
|
|
43
|
|
40
|
my $class = shift; |
46
|
43
|
|
|
|
|
59
|
my $include_hashref = shift; |
47
|
|
|
|
|
|
|
|
48
|
43
|
|
|
|
|
64
|
my $target = $class->_get_package_to_import_into(); |
49
|
|
|
|
|
|
|
|
50
|
43
|
|
|
|
|
75
|
$class->_make_target_a_test_more_like_exporter($target); |
51
|
|
|
|
|
|
|
|
52
|
42
|
|
|
|
|
117
|
for my $package (sort keys %$include_hashref) { |
53
|
|
|
|
|
|
|
# special cases for strict and warnings on pre-1.3 Test::Builder |
54
|
|
|
|
|
|
|
# |
55
|
|
|
|
|
|
|
# The logic here is copied from Moose which always causes strict and |
56
|
|
|
|
|
|
|
# warnings to be enabled when it is used. |
57
|
|
|
|
|
|
|
# |
58
|
|
|
|
|
|
|
# A comment in Moose::Exporter states: |
59
|
|
|
|
|
|
|
# |
60
|
|
|
|
|
|
|
# "this works because both pragmas set $^H (see perldoc perlvar) which |
61
|
|
|
|
|
|
|
# affects the current compilation - i.e. the file who use'd us - which |
62
|
|
|
|
|
|
|
# is why we don't need to do anything special to make it affect that |
63
|
|
|
|
|
|
|
# file rather than this one (which is already compiled)" |
64
|
|
|
|
|
|
|
# |
65
|
|
|
|
|
|
|
# In the Moose code the author simply calls strict->import() in the |
66
|
|
|
|
|
|
|
# appropriate import() method and that does the trick. For us working |
67
|
|
|
|
|
|
|
# at a bit more of a distance we have to be a bit trickier - adding |
68
|
|
|
|
|
|
|
# strict->import() or warnings->import() to the import method on the |
69
|
|
|
|
|
|
|
# target class. We do that by wrapping it with Hook::LexWrap::wrap(). |
70
|
|
|
|
|
|
|
# |
71
|
44
|
100
|
100
|
|
|
2484
|
if ($Test::Builder::VERSION < 1.3 && ($package eq 'strict' || $package eq 'warnings')) { |
|
|
|
33
|
|
|
|
|
72
|
2
|
|
|
2
|
|
11
|
wrap "${target}::import", post => sub { $package->import(); }; |
|
2
|
|
|
|
|
307
|
|
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
else { |
75
|
42
|
|
|
|
|
91
|
my $fake_package = $class->_create_fake_package($package, $include_hashref->{$package}, $target); |
76
|
41
|
|
|
|
|
128
|
$fake_package->import::into($target); |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
41
|
|
|
|
|
9436
|
$class->_update_target_exports($target); |
81
|
|
|
|
|
|
|
|
82
|
41
|
|
|
|
|
111
|
return; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sub _get_package_to_import_into { |
86
|
43
|
|
|
43
|
|
56
|
my $class = shift; |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# so, as far as I can tell, on Perl 5.14 and 5.16 at least, we have the |
89
|
|
|
|
|
|
|
# following callstack... |
90
|
|
|
|
|
|
|
# |
91
|
|
|
|
|
|
|
# 1. Test::Kit |
92
|
|
|
|
|
|
|
# 2. MyTest |
93
|
|
|
|
|
|
|
# 3. main |
94
|
|
|
|
|
|
|
# 4. main |
95
|
|
|
|
|
|
|
# 5. main |
96
|
|
|
|
|
|
|
# |
97
|
|
|
|
|
|
|
# ... and we want to get the package name "MyTest" out of there. |
98
|
|
|
|
|
|
|
# So let's look for the first non-Test::Kit result |
99
|
|
|
|
|
|
|
|
100
|
43
|
|
|
|
|
115
|
for my $i (1 .. 20) { |
101
|
86
|
|
|
|
|
158
|
my $caller_package = (caller($i))[0]; |
102
|
86
|
100
|
|
|
|
2007
|
if ($caller_package ne $class) { |
103
|
43
|
|
|
|
|
72
|
return $caller_package; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
0
|
die "Unable to find package to import into"; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub _make_target_a_test_more_like_exporter { |
111
|
43
|
|
|
43
|
|
37
|
my $class = shift; |
112
|
43
|
|
|
|
|
33
|
my $target = shift; |
113
|
|
|
|
|
|
|
|
114
|
43
|
100
|
|
|
|
96
|
return if $test_kits_cache{$target}; |
115
|
|
|
|
|
|
|
|
116
|
28
|
|
|
|
|
57
|
$class->_check_target_does_not_import($target); |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
{ |
119
|
23
|
|
|
23
|
|
7519
|
no strict 'refs'; |
|
23
|
|
|
|
|
32
|
|
|
23
|
|
|
|
|
3850
|
|
|
27
|
|
|
|
|
25
|
|
120
|
27
|
|
|
|
|
23
|
push @{ "${target}::ISA" }, 'Test::Builder::Module'; |
|
27
|
|
|
|
|
258
|
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# need to explicitly do this so that if we need to wrap import() |
123
|
|
|
|
|
|
|
# for strict and warnings includes it already exists at the right |
124
|
|
|
|
|
|
|
# point. |
125
|
27
|
|
|
|
|
54
|
*{ "${target}::import" } = \&Test::Builder::Module::import; |
|
27
|
|
|
|
|
70
|
|
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
27
|
|
|
|
|
632
|
$test_kits_cache{$target} = {}; |
129
|
|
|
|
|
|
|
|
130
|
27
|
|
|
|
|
647
|
return; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
sub _create_fake_package { |
134
|
42
|
|
|
42
|
|
1370
|
my $class = shift; |
135
|
42
|
|
|
|
|
39
|
my $package = shift; |
136
|
42
|
|
|
|
|
40
|
my $package_include_hashref = shift; |
137
|
42
|
|
|
|
|
35
|
my $target = shift; |
138
|
|
|
|
|
|
|
|
139
|
42
|
|
|
|
|
676
|
my $fake_package = "Test::Kit::Fake::${target}::${package}"; |
140
|
|
|
|
|
|
|
|
141
|
42
|
|
|
|
|
103
|
my $fake_package_file = module_notional_filename($fake_package); |
142
|
42
|
|
|
|
|
1204
|
$INC{$fake_package_file} = 1; |
143
|
|
|
|
|
|
|
|
144
|
42
|
100
|
|
|
|
143
|
my %exclude = map { $_ => 1 } @{ $package_include_hashref->{exclude} || [] }; |
|
40
|
|
|
|
|
47
|
|
|
42
|
|
|
|
|
259
|
|
145
|
42
|
100
|
|
|
|
42
|
my %rename = %{ $package_include_hashref->{rename} || {} }; |
|
42
|
|
|
|
|
171
|
|
146
|
42
|
100
|
|
|
|
47
|
my @import = @{ $package_include_hashref->{import} || [] }; |
|
42
|
|
|
|
|
148
|
|
147
|
|
|
|
|
|
|
|
148
|
42
|
|
|
|
|
94
|
use_module($package)->import::into($fake_package, @import); |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
{ |
151
|
23
|
|
|
23
|
|
92
|
no strict 'refs'; |
|
23
|
|
|
|
|
27
|
|
|
23
|
|
|
|
|
552
|
|
|
42
|
|
|
|
|
72315
|
|
152
|
23
|
|
|
23
|
|
69
|
no warnings 'redefine'; |
|
23
|
|
|
|
|
23
|
|
|
23
|
|
|
|
|
4839
|
|
153
|
|
|
|
|
|
|
|
154
|
42
|
|
|
|
|
44
|
push @{ "${fake_package}::ISA" }, 'Exporter'; |
|
42
|
|
|
|
|
309
|
|
155
|
|
|
|
|
|
|
|
156
|
42
|
|
|
|
|
134
|
for my $from (sort keys %rename) { |
157
|
10
|
|
|
|
|
344
|
my $to = $rename{$from}; |
158
|
|
|
|
|
|
|
|
159
|
10
|
|
|
|
|
9
|
*{ "$fake_package\::$to" } = \&{ "$fake_package\::$from" }; |
|
10
|
|
|
|
|
30
|
|
|
10
|
|
|
|
|
26
|
|
160
|
|
|
|
|
|
|
|
161
|
10
|
|
|
|
|
27
|
delete_sub("${fake_package}::$from"); |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
42
|
|
|
|
|
582
|
for my $exclude (sort keys %exclude) { |
165
|
40
|
|
|
|
|
2384
|
delete_sub("${fake_package}::$exclude"); |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
|
168
|
42
|
|
|
|
|
1659
|
@{ "${fake_package}::EXPORT" } = $class->_get_exports_for($fake_package, $package, $target, \%rename); |
|
41
|
|
|
|
|
230
|
|
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
41
|
|
|
|
|
102
|
return $fake_package; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
sub _get_exports_for { |
175
|
42
|
|
|
42
|
|
581
|
my $class = shift; |
176
|
42
|
|
|
|
|
38
|
my $fake_package = shift; |
177
|
42
|
|
|
|
|
36
|
my $package = shift; |
178
|
42
|
|
|
|
|
1091
|
my $target = shift; |
179
|
42
|
|
|
|
|
39
|
my $rename = shift; |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
# Want to look at each item in the symbol table of |
182
|
|
|
|
|
|
|
# the fake package, and see whether it's the same |
183
|
|
|
|
|
|
|
# (according to refaddr) as the one that was in the |
184
|
|
|
|
|
|
|
# included package. If it is then it was exported |
185
|
|
|
|
|
|
|
# by the package into the fake package. |
186
|
|
|
|
|
|
|
# |
187
|
|
|
|
|
|
|
# We also store the refaddr so that we can check things which are identical |
188
|
|
|
|
|
|
|
# between included packages, and not throw a collision exception in that |
189
|
|
|
|
|
|
|
# case. |
190
|
42
|
|
|
|
|
118
|
my %type_to_sigil = ( # please don't export IO or FORMAT! ;-) |
191
|
|
|
|
|
|
|
SCALAR => '$', |
192
|
|
|
|
|
|
|
ARRAY => '@', |
193
|
|
|
|
|
|
|
HASH => '%', |
194
|
|
|
|
|
|
|
CODE => '', |
195
|
|
|
|
|
|
|
); |
196
|
42
|
50
|
|
|
|
38
|
my %reverse_rename = reverse %{ $rename || {} }; |
|
42
|
|
|
|
|
140
|
|
197
|
42
|
|
|
|
|
37
|
my @package_exports; |
198
|
|
|
|
|
|
|
{ |
199
|
23
|
|
|
23
|
|
87
|
no strict 'refs'; |
|
23
|
|
|
|
|
22
|
|
|
23
|
|
|
|
|
5629
|
|
|
42
|
|
|
|
|
33
|
|
200
|
|
|
|
|
|
|
|
201
|
42
|
|
|
|
|
709
|
for my $glob (keys %{ "${fake_package}::" }) { |
|
42
|
|
|
|
|
211
|
|
202
|
|
|
|
|
|
|
|
203
|
916
|
|
|
|
|
609
|
my $fake_glob = $glob; |
204
|
916
|
|
66
|
|
|
1895
|
my $real_glob = $reverse_rename{$glob} // $glob; |
205
|
|
|
|
|
|
|
|
206
|
916
|
|
|
|
|
1071
|
for my $type (keys %type_to_sigil) { |
207
|
3662
|
|
|
|
|
2002
|
my $fake_refaddr = refaddr *{ "${fake_package}::${fake_glob}" }{$type}; |
|
3662
|
|
|
|
|
7874
|
|
208
|
3662
|
|
|
|
|
2109
|
my $real_refaddr = refaddr *{ "${package}::${real_glob}" }{$type}; |
|
3662
|
|
|
|
|
5370
|
|
209
|
|
|
|
|
|
|
|
210
|
3662
|
100
|
66
|
|
|
9383
|
if ($fake_refaddr && $real_refaddr && $fake_refaddr == $real_refaddr) { |
|
|
|
100
|
|
|
|
|
211
|
832
|
|
|
|
|
1286
|
my $export = sprintf("%s%s", $type_to_sigil{$type}, $fake_glob); |
212
|
832
|
|
|
|
|
743
|
push @package_exports, $export; |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
# handle cache and collision checking |
215
|
832
|
|
|
|
|
469
|
push @{ $test_kits_cache{$target}{$export}{source} }, $package; |
|
832
|
|
|
|
|
1588
|
|
216
|
832
|
100
|
|
|
|
1054
|
if (my $existing_refaddr = $test_kits_cache{$target}{$export}{refaddr}) { |
217
|
53
|
100
|
|
|
|
81
|
if ($existing_refaddr != $real_refaddr) { |
218
|
|
|
|
|
|
|
die sprintf("Subroutine %s() already supplied to %s by %s", |
219
|
|
|
|
|
|
|
$export, |
220
|
|
|
|
|
|
|
$target, |
221
|
1
|
|
|
|
|
21
|
$test_kits_cache{$target}{$export}{source}[0], |
222
|
|
|
|
|
|
|
); |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
else { |
226
|
779
|
|
|
|
|
1030
|
$test_kits_cache{$target}{$export}{refaddr} = $real_refaddr; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
41
|
|
|
|
|
237
|
return @package_exports; |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub _check_target_does_not_import { |
237
|
28
|
|
|
28
|
|
26
|
my $class = shift; |
238
|
28
|
|
|
|
|
25
|
my $target = shift; |
239
|
|
|
|
|
|
|
|
240
|
28
|
100
|
|
|
|
300
|
if ($target->can('import')) { |
241
|
1
|
|
|
|
|
20
|
die "Package $target already has an import() sub"; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
27
|
|
|
|
|
32
|
return; |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
sub _update_target_exports { |
248
|
41
|
|
|
41
|
|
50
|
my $class = shift; |
249
|
41
|
|
|
|
|
31
|
my $target = shift; |
250
|
|
|
|
|
|
|
|
251
|
41
|
|
|
|
|
36
|
my @exports = sort keys %{ $test_kits_cache{$target} }; |
|
41
|
|
|
|
|
506
|
|
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
{ |
254
|
23
|
|
|
23
|
|
89
|
no strict 'refs'; |
|
23
|
|
|
|
|
31
|
|
|
23
|
|
|
|
|
1200
|
|
|
41
|
|
|
|
|
66
|
|
255
|
41
|
|
|
|
|
34
|
@{ "$target\::EXPORT" } = @exports; |
|
41
|
|
|
|
|
216
|
|
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
41
|
|
|
|
|
100
|
return; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
1; |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
__END__ |