line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test::Kit; |
2
|
|
|
|
|
|
|
$Test::Kit::VERSION = '2.16'; |
3
|
24
|
|
|
24
|
|
56473
|
use strict; |
|
24
|
|
|
|
|
170
|
|
|
24
|
|
|
|
|
695
|
|
4
|
24
|
|
|
24
|
|
120
|
use warnings; |
|
24
|
|
|
|
|
53
|
|
|
24
|
|
|
|
|
595
|
|
5
|
|
|
|
|
|
|
|
6
|
24
|
|
|
24
|
|
10842
|
use Import::Into; |
|
24
|
|
|
|
|
66636
|
|
|
24
|
|
|
|
|
770
|
|
7
|
24
|
|
|
24
|
|
179
|
use Module::Runtime 'use_module', 'module_notional_filename'; |
|
24
|
|
|
|
|
56
|
|
|
24
|
|
|
|
|
116
|
|
8
|
24
|
|
|
24
|
|
11370
|
use Sub::Delete; |
|
24
|
|
|
|
|
23404
|
|
|
24
|
|
|
|
|
1511
|
|
9
|
24
|
|
|
24
|
|
13361
|
use Test::Builder (); |
|
24
|
|
|
|
|
1260328
|
|
|
24
|
|
|
|
|
663
|
|
10
|
24
|
|
|
24
|
|
14173
|
use Test::More (); |
|
24
|
|
|
|
|
129426
|
|
|
24
|
|
|
|
|
693
|
|
11
|
24
|
|
|
24
|
|
174
|
use Scalar::Util qw(refaddr); |
|
24
|
|
|
|
|
49
|
|
|
24
|
|
|
|
|
1317
|
|
12
|
24
|
|
|
24
|
|
11833
|
use Hook::LexWrap qw(wrap); |
|
24
|
|
|
|
|
78715
|
|
|
24
|
|
|
|
|
143
|
|
13
|
|
|
|
|
|
|
|
14
|
24
|
|
|
24
|
|
10822
|
use parent 'Exporter'; |
|
24
|
|
|
|
|
7075
|
|
|
24
|
|
|
|
|
158
|
|
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
|
45
|
|
|
45
|
0
|
7055
|
my @to_include = @_; |
30
|
|
|
|
|
|
|
|
31
|
45
|
|
|
|
|
96
|
my $class = __PACKAGE__; |
32
|
|
|
|
|
|
|
|
33
|
45
|
|
|
|
|
69
|
my $include_hashref; |
34
|
45
|
100
|
|
|
|
103
|
if (grep { ref($_) } @to_include) { |
|
58
|
|
|
|
|
228
|
|
35
|
11
|
|
|
|
|
35
|
$include_hashref = { @to_include }; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
else { |
38
|
34
|
|
|
|
|
73
|
$include_hashref = { map { $_ => {} } @to_include }; |
|
36
|
|
|
|
|
139
|
|
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
45
|
|
|
|
|
161
|
return $class->_include($include_hashref); |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub _include { |
45
|
45
|
|
|
45
|
|
77
|
my $class = shift; |
46
|
45
|
|
|
|
|
83
|
my $include_hashref = shift; |
47
|
|
|
|
|
|
|
|
48
|
45
|
|
|
|
|
165
|
my $target = $class->_get_package_to_import_into(); |
49
|
|
|
|
|
|
|
|
50
|
45
|
|
|
|
|
395
|
$class->_make_target_a_test_more_like_exporter($target); |
51
|
|
|
|
|
|
|
|
52
|
44
|
|
|
|
|
228
|
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
|
46
|
50
|
0
|
|
|
888
|
if ($Test::Builder::VERSION < 1.3 && ($package eq 'strict' || $package eq 'warnings')) { |
|
|
|
33
|
|
|
|
|
72
|
0
|
|
|
0
|
|
0
|
wrap "${target}::import", post => sub { $package->import(); }; |
|
0
|
|
|
|
|
0
|
|
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
else { |
75
|
46
|
|
|
|
|
130
|
my $fake_package = $class->_create_fake_package($package, $include_hashref->{$package}, $target); |
76
|
45
|
|
|
|
|
180
|
$fake_package->import::into($target); |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
43
|
|
|
|
|
14777
|
$class->_update_target_exports($target); |
81
|
|
|
|
|
|
|
|
82
|
43
|
|
|
|
|
170
|
return; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sub _get_package_to_import_into { |
86
|
45
|
|
|
45
|
|
80
|
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
|
45
|
|
|
|
|
165
|
for my $i (1 .. 20) { |
101
|
90
|
|
|
|
|
242
|
my $caller_package = (caller($i))[0]; |
102
|
90
|
100
|
|
|
|
3597
|
if ($caller_package ne $class) { |
103
|
45
|
|
|
|
|
117
|
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
|
45
|
|
|
45
|
|
155
|
my $class = shift; |
112
|
45
|
|
|
|
|
67
|
my $target = shift; |
113
|
|
|
|
|
|
|
|
114
|
45
|
100
|
|
|
|
163
|
return if $test_kits_cache{$target}; |
115
|
|
|
|
|
|
|
|
116
|
29
|
|
|
|
|
85
|
$class->_check_target_does_not_import($target); |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
{ |
119
|
24
|
|
|
24
|
|
11038
|
no strict 'refs'; |
|
24
|
|
|
|
|
93
|
|
|
24
|
|
|
|
|
5993
|
|
|
28
|
|
|
|
|
44
|
|
120
|
28
|
|
|
|
|
48
|
push @{ "${target}::ISA" }, 'Test::Builder::Module'; |
|
28
|
|
|
|
|
373
|
|
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
|
28
|
|
|
|
|
94
|
*{ "${target}::import" } = \&Test::Builder::Module::import; |
|
28
|
|
|
|
|
107
|
|
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
28
|
|
|
|
|
74
|
$test_kits_cache{$target} = {}; |
129
|
|
|
|
|
|
|
|
130
|
28
|
|
|
|
|
59
|
return; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
sub _create_fake_package { |
134
|
46
|
|
|
46
|
|
74
|
my $class = shift; |
135
|
46
|
|
|
|
|
78
|
my $package = shift; |
136
|
46
|
|
|
|
|
64
|
my $package_include_hashref = shift; |
137
|
46
|
|
|
|
|
63
|
my $target = shift; |
138
|
|
|
|
|
|
|
|
139
|
46
|
|
|
|
|
136
|
my $fake_package = "Test::Kit::Fake::${target}::${package}"; |
140
|
|
|
|
|
|
|
|
141
|
46
|
|
|
|
|
206
|
my $fake_package_file = module_notional_filename($fake_package); |
142
|
46
|
|
|
|
|
2081
|
$INC{$fake_package_file} = 1; |
143
|
|
|
|
|
|
|
|
144
|
46
|
100
|
|
|
|
77
|
my %exclude = map { $_ => 1 } @{ $package_include_hashref->{exclude} || [] }; |
|
40
|
|
|
|
|
82
|
|
|
46
|
|
|
|
|
257
|
|
145
|
46
|
100
|
|
|
|
87
|
my %rename = %{ $package_include_hashref->{rename} || {} }; |
|
46
|
|
|
|
|
220
|
|
146
|
46
|
100
|
|
|
|
103
|
my @import = @{ $package_include_hashref->{import} || [] }; |
|
46
|
|
|
|
|
269
|
|
147
|
|
|
|
|
|
|
|
148
|
46
|
|
|
|
|
163
|
use_module($package)->import::into($fake_package, @import); |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
{ |
151
|
24
|
|
|
24
|
|
200
|
no strict 'refs'; |
|
24
|
|
|
|
|
54
|
|
|
24
|
|
|
|
|
928
|
|
|
46
|
|
|
|
|
94950
|
|
152
|
24
|
|
|
24
|
|
156
|
no warnings 'redefine'; |
|
24
|
|
|
|
|
91
|
|
|
24
|
|
|
|
|
7632
|
|
153
|
|
|
|
|
|
|
|
154
|
46
|
|
|
|
|
95
|
push @{ "${fake_package}::ISA" }, 'Exporter'; |
|
46
|
|
|
|
|
547
|
|
155
|
|
|
|
|
|
|
|
156
|
46
|
|
|
|
|
184
|
for my $from (sort keys %rename) { |
157
|
10
|
|
|
|
|
570
|
my $to = $rename{$from}; |
158
|
|
|
|
|
|
|
|
159
|
10
|
|
|
|
|
14
|
*{ "$fake_package\::$to" } = \&{ "$fake_package\::$from" }; |
|
10
|
|
|
|
|
43
|
|
|
10
|
|
|
|
|
38
|
|
160
|
|
|
|
|
|
|
|
161
|
10
|
|
|
|
|
42
|
delete_sub("${fake_package}::$from"); |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
46
|
|
|
|
|
981
|
for my $exclude (sort keys %exclude) { |
165
|
40
|
|
|
|
|
3915
|
delete_sub("${fake_package}::$exclude"); |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
|
168
|
46
|
|
|
|
|
803
|
@{ "${fake_package}::EXPORT" } = $class->_get_exports_for($fake_package, $package, $target, \%rename); |
|
45
|
|
|
|
|
306
|
|
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
45
|
|
|
|
|
158
|
return $fake_package; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
sub _get_exports_for { |
175
|
46
|
|
|
46
|
|
121
|
my $class = shift; |
176
|
46
|
|
|
|
|
86
|
my $fake_package = shift; |
177
|
46
|
|
|
|
|
68
|
my $package = shift; |
178
|
46
|
|
|
|
|
68
|
my $target = shift; |
179
|
46
|
|
|
|
|
67
|
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
|
46
|
|
|
|
|
177
|
my %type_to_sigil = ( # please don't export IO or FORMAT! ;-) |
191
|
|
|
|
|
|
|
SCALAR => '$', |
192
|
|
|
|
|
|
|
ARRAY => '@', |
193
|
|
|
|
|
|
|
HASH => '%', |
194
|
|
|
|
|
|
|
CODE => '', |
195
|
|
|
|
|
|
|
); |
196
|
46
|
50
|
|
|
|
70
|
my %reverse_rename = reverse %{ $rename || {} }; |
|
46
|
|
|
|
|
175
|
|
197
|
46
|
|
|
|
|
78
|
my @package_exports; |
198
|
|
|
|
|
|
|
{ |
199
|
24
|
|
|
24
|
|
193
|
no strict 'refs'; |
|
24
|
|
|
|
|
80
|
|
|
24
|
|
|
|
|
9901
|
|
|
46
|
|
|
|
|
62
|
|
200
|
|
|
|
|
|
|
|
201
|
46
|
|
|
|
|
66
|
for my $glob (keys %{ "${fake_package}::" }) { |
|
46
|
|
|
|
|
300
|
|
202
|
|
|
|
|
|
|
|
203
|
961
|
|
|
|
|
1273
|
my $fake_glob = $glob; |
204
|
961
|
|
66
|
|
|
2362
|
my $real_glob = $reverse_rename{$glob} // $glob; |
205
|
|
|
|
|
|
|
|
206
|
961
|
|
|
|
|
1868
|
for my $type (keys %type_to_sigil) { |
207
|
3843
|
|
|
|
|
4355
|
my $fake_refaddr = refaddr *{ "${fake_package}::${fake_glob}" }{$type}; |
|
3843
|
|
|
|
|
10946
|
|
208
|
3843
|
|
|
|
|
4783
|
my $real_refaddr = refaddr *{ "${package}::${real_glob}" }{$type}; |
|
3843
|
|
|
|
|
7915
|
|
209
|
|
|
|
|
|
|
|
210
|
3843
|
100
|
66
|
|
|
10896
|
if ($fake_refaddr && $real_refaddr && $fake_refaddr == $real_refaddr) { |
|
|
|
100
|
|
|
|
|
211
|
869
|
|
|
|
|
2127
|
my $export = sprintf("%s%s", $type_to_sigil{$type}, $fake_glob); |
212
|
869
|
|
|
|
|
1571
|
push @package_exports, $export; |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
# handle cache and collision checking |
215
|
869
|
|
|
|
|
989
|
push @{ $test_kits_cache{$target}{$export}{source} }, $package; |
|
869
|
|
|
|
|
2731
|
|
216
|
869
|
100
|
|
|
|
1802
|
if (my $existing_refaddr = $test_kits_cache{$target}{$export}{refaddr}) { |
217
|
53
|
100
|
|
|
|
104
|
if ($existing_refaddr != $real_refaddr) { |
218
|
|
|
|
|
|
|
die sprintf("Subroutine %s() already supplied to %s by %s", |
219
|
|
|
|
|
|
|
$export, |
220
|
|
|
|
|
|
|
$target, |
221
|
1
|
|
|
|
|
35
|
$test_kits_cache{$target}{$export}{source}[0], |
222
|
|
|
|
|
|
|
); |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
else { |
226
|
816
|
|
|
|
|
1748
|
$test_kits_cache{$target}{$export}{refaddr} = $real_refaddr; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
45
|
|
|
|
|
364
|
return @package_exports; |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub _check_target_does_not_import { |
237
|
29
|
|
|
29
|
|
48
|
my $class = shift; |
238
|
29
|
|
|
|
|
41
|
my $target = shift; |
239
|
|
|
|
|
|
|
|
240
|
29
|
|
|
|
|
328
|
my $import = $target->can('import'); |
241
|
29
|
|
|
|
|
133
|
my $uniimport = UNIVERSAL->can('import'); |
242
|
29
|
100
|
66
|
|
|
130
|
if ($import && !($uniimport && $import == $uniimport)) { |
|
|
|
100
|
|
|
|
|
243
|
1
|
|
|
|
|
24
|
die "Package $target already has an import() sub"; |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
28
|
|
|
|
|
56
|
return; |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
sub _update_target_exports { |
250
|
43
|
|
|
43
|
|
89
|
my $class = shift; |
251
|
43
|
|
|
|
|
64
|
my $target = shift; |
252
|
|
|
|
|
|
|
|
253
|
43
|
|
|
|
|
75
|
my @exports = sort keys %{ $test_kits_cache{$target} }; |
|
43
|
|
|
|
|
777
|
|
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
{ |
256
|
24
|
|
|
24
|
|
236
|
no strict 'refs'; |
|
24
|
|
|
|
|
67
|
|
|
24
|
|
|
|
|
2497
|
|
|
43
|
|
|
|
|
120
|
|
257
|
43
|
|
|
|
|
74
|
@{ "$target\::EXPORT" } = @exports; |
|
43
|
|
|
|
|
290
|
|
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
43
|
|
|
|
|
124
|
return; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
1; |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
__END__ |