| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Test::Inline::Script; |
|
2
|
|
|
|
|
|
|
# ABSTRACT: Generate the test file for a single source file |
|
3
|
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
#pod =pod |
|
5
|
|
|
|
|
|
|
#pod |
|
6
|
|
|
|
|
|
|
#pod =head1 DESCRIPTION |
|
7
|
|
|
|
|
|
|
#pod |
|
8
|
|
|
|
|
|
|
#pod This class is where the heavy lifting happens to actually generating a |
|
9
|
|
|
|
|
|
|
#pod test file takes place. Given a source filename, this modules will load |
|
10
|
|
|
|
|
|
|
#pod it, parse out the relavent bits, put them into order based on the tags, |
|
11
|
|
|
|
|
|
|
#pod and then merge them into a test file. |
|
12
|
|
|
|
|
|
|
#pod |
|
13
|
|
|
|
|
|
|
#pod =head1 METHODS |
|
14
|
|
|
|
|
|
|
#pod |
|
15
|
|
|
|
|
|
|
#pod =cut |
|
16
|
|
|
|
|
|
|
|
|
17
|
12
|
|
|
12
|
|
93
|
use strict; |
|
|
12
|
|
|
|
|
23
|
|
|
|
12
|
|
|
|
|
410
|
|
|
18
|
12
|
|
|
12
|
|
79
|
use List::Util (); |
|
|
12
|
|
|
|
|
26
|
|
|
|
12
|
|
|
|
|
264
|
|
|
19
|
12
|
|
|
12
|
|
61
|
use Params::Util qw{_ARRAY _INSTANCE}; |
|
|
12
|
|
|
|
|
23
|
|
|
|
12
|
|
|
|
|
742
|
|
|
20
|
12
|
|
|
12
|
|
85
|
use Algorithm::Dependency::Item (); |
|
|
12
|
|
|
|
|
23
|
|
|
|
12
|
|
|
|
|
190
|
|
|
21
|
12
|
|
|
12
|
|
52
|
use Algorithm::Dependency::Source (); |
|
|
12
|
|
|
|
|
22
|
|
|
|
12
|
|
|
|
|
241
|
|
|
22
|
12
|
|
|
12
|
|
5977
|
use Algorithm::Dependency::Ordered (); |
|
|
12
|
|
|
|
|
5345
|
|
|
|
12
|
|
|
|
|
537
|
|
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
use overload 'bool' => sub () { 1 }, |
|
25
|
12
|
|
|
12
|
|
119
|
'""' => 'filename'; |
|
|
12
|
|
|
|
|
25
|
|
|
|
12
|
|
|
|
|
81
|
|
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
our $VERSION = '2.214'; |
|
28
|
|
|
|
|
|
|
our @ISA = qw{ |
|
29
|
|
|
|
|
|
|
Algorithm::Dependency::Source |
|
30
|
|
|
|
|
|
|
Algorithm::Dependency::Item |
|
31
|
|
|
|
|
|
|
}; |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# Special case, for when doing unit tests ONLY. |
|
34
|
|
|
|
|
|
|
# Don't throw the missing files warning. |
|
35
|
12
|
|
|
12
|
|
1340
|
use vars qw{$NO_MISSING_DEPENDENCIES_WARNING}; |
|
|
12
|
|
|
|
|
28
|
|
|
|
12
|
|
|
|
|
555
|
|
|
36
|
|
|
|
|
|
|
BEGIN { |
|
37
|
12
|
|
|
12
|
|
18258
|
$NO_MISSING_DEPENDENCIES_WARNING = ''; |
|
38
|
|
|
|
|
|
|
} |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
##################################################################### |
|
45
|
|
|
|
|
|
|
# Constructor and Accessors |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
#pod =pod |
|
48
|
|
|
|
|
|
|
#pod |
|
49
|
|
|
|
|
|
|
#pod =head2 new |
|
50
|
|
|
|
|
|
|
#pod |
|
51
|
|
|
|
|
|
|
#pod my $File = Test::Inline::Script->new( $class, \@sections, $check_count ); |
|
52
|
|
|
|
|
|
|
#pod |
|
53
|
|
|
|
|
|
|
#pod The C constructor takes a class name, set of Section objects and |
|
54
|
|
|
|
|
|
|
#pod an optional C flag. |
|
55
|
|
|
|
|
|
|
#pod |
|
56
|
|
|
|
|
|
|
#pod Returns a Test::Inline::Script object on success. |
|
57
|
|
|
|
|
|
|
#pod Returns C on error. |
|
58
|
|
|
|
|
|
|
#pod |
|
59
|
|
|
|
|
|
|
#pod =cut |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub new { |
|
62
|
20
|
|
|
20
|
1
|
45
|
my $class = shift; |
|
63
|
20
|
50
|
|
|
|
54
|
my $_class = defined $_[0] ? shift : return undef; |
|
64
|
20
|
50
|
|
|
|
104
|
my $Sections = _ARRAY(shift) or return undef; |
|
65
|
20
|
|
100
|
|
|
75
|
my $check_count = shift || 0; |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# Create the object |
|
68
|
|
|
|
|
|
|
my $self = bless { |
|
69
|
|
|
|
|
|
|
class => $_class, |
|
70
|
49
|
|
|
|
|
153
|
setup => [ grep { $_->setup } @$Sections ], |
|
71
|
20
|
|
|
|
|
54
|
sections => [ grep { ! $_->setup } @$Sections ], |
|
|
49
|
|
|
|
|
101
|
|
|
72
|
|
|
|
|
|
|
filename => lc "$_class.t", |
|
73
|
|
|
|
|
|
|
check_count => $check_count, |
|
74
|
|
|
|
|
|
|
# tests => undef, |
|
75
|
|
|
|
|
|
|
}, $class; |
|
76
|
20
|
|
|
|
|
460
|
$self->{filename} =~ s/::/_/g; |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# Verify the uniqueness of the names |
|
79
|
20
|
50
|
|
|
|
77
|
$self->_duplicate_names and return undef; |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
# Warn if we have missing dependencies |
|
82
|
20
|
|
|
|
|
128
|
my $missing = $self->missing_dependencies; |
|
83
|
20
|
100
|
|
|
|
123
|
if ( $missing ) { |
|
84
|
1
|
|
|
|
|
3
|
foreach ( @$missing ) { |
|
85
|
1
|
50
|
|
|
|
4
|
next if $NO_MISSING_DEPENDENCIES_WARNING; |
|
86
|
0
|
|
|
|
|
0
|
print "Warning: Missing dependency '$_' in $self->{class}\n"; |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# Quickly predetermine if there will be an unknown number |
|
91
|
|
|
|
|
|
|
# of unit tests in the file |
|
92
|
20
|
|
|
|
|
44
|
my $unknown = grep { ! defined $_->tests } @$Sections; |
|
|
49
|
|
|
|
|
104
|
|
|
93
|
20
|
50
|
66
|
|
|
68
|
unless ( $unknown or grep { $_->tests } @$Sections ) { |
|
|
27
|
|
|
|
|
52
|
|
|
94
|
0
|
|
|
|
|
0
|
$unknown = 1; |
|
95
|
|
|
|
|
|
|
} |
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# Flag all sections that need count checking in advance |
|
98
|
20
|
100
|
|
|
|
69
|
if ( $check_count ) { |
|
99
|
19
|
|
|
|
|
50
|
foreach my $Section ( @$Sections ) { |
|
100
|
44
|
100
|
|
|
|
118
|
next unless defined $Section->tests; |
|
101
|
34
|
100
|
100
|
|
|
136
|
next unless $unknown or $check_count > 1; |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# Each count check is itself a test, so |
|
104
|
|
|
|
|
|
|
# increment the number of tests for the section |
|
105
|
|
|
|
|
|
|
# when we enable the check flag. |
|
106
|
12
|
|
|
|
|
21
|
$Section->{check_count} = 1; |
|
107
|
12
|
|
|
|
|
20
|
$Section->{tests}++; |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
|
|
111
|
20
|
|
|
|
|
134
|
$self; |
|
112
|
|
|
|
|
|
|
} |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
#pod =pod |
|
115
|
|
|
|
|
|
|
#pod |
|
116
|
|
|
|
|
|
|
#pod =head2 class |
|
117
|
|
|
|
|
|
|
#pod |
|
118
|
|
|
|
|
|
|
#pod Returns the class that the test file will test |
|
119
|
|
|
|
|
|
|
#pod |
|
120
|
|
|
|
|
|
|
#pod =head2 filename |
|
121
|
|
|
|
|
|
|
#pod |
|
122
|
|
|
|
|
|
|
#pod my $filename = $File->filename; |
|
123
|
|
|
|
|
|
|
#pod |
|
124
|
|
|
|
|
|
|
#pod The C method returns the name of the output file that the tests |
|
125
|
|
|
|
|
|
|
#pod should be written to. For example, the class C would have the |
|
126
|
|
|
|
|
|
|
#pod filename value C. |
|
127
|
|
|
|
|
|
|
#pod |
|
128
|
|
|
|
|
|
|
#pod =head2 config |
|
129
|
|
|
|
|
|
|
#pod |
|
130
|
|
|
|
|
|
|
#pod my $config = $File->config; |
|
131
|
|
|
|
|
|
|
#pod |
|
132
|
|
|
|
|
|
|
#pod The C method returns the config object for the file, assuming that |
|
133
|
|
|
|
|
|
|
#pod it has one. If more than one are found, the first will be used, and any |
|
134
|
|
|
|
|
|
|
#pod additional config sections discarded. |
|
135
|
|
|
|
|
|
|
#pod |
|
136
|
|
|
|
|
|
|
#pod Returns a L object on success, or false if the |
|
137
|
|
|
|
|
|
|
#pod file does not contain a config section. |
|
138
|
|
|
|
|
|
|
#pod |
|
139
|
|
|
|
|
|
|
#pod =head2 setup |
|
140
|
|
|
|
|
|
|
#pod |
|
141
|
|
|
|
|
|
|
#pod my @setup = $File->setup; |
|
142
|
|
|
|
|
|
|
#pod |
|
143
|
|
|
|
|
|
|
#pod The C method returns the setup sections from the file, in the same |
|
144
|
|
|
|
|
|
|
#pod order as in the file. |
|
145
|
|
|
|
|
|
|
#pod |
|
146
|
|
|
|
|
|
|
#pod Returns a list of setup L objects, the null |
|
147
|
|
|
|
|
|
|
#pod array C<()> if the file does not contain any setup objects. |
|
148
|
|
|
|
|
|
|
#pod |
|
149
|
|
|
|
|
|
|
#pod =head2 sections |
|
150
|
|
|
|
|
|
|
#pod |
|
151
|
|
|
|
|
|
|
#pod my @sections = $File->sections; |
|
152
|
|
|
|
|
|
|
#pod |
|
153
|
|
|
|
|
|
|
#pod The C method returns all normal sections from the file, in the |
|
154
|
|
|
|
|
|
|
#pod same order as in the file. This may not be the order they will be written |
|
155
|
|
|
|
|
|
|
#pod to the test file, for that you should see the C method. |
|
156
|
|
|
|
|
|
|
#pod |
|
157
|
|
|
|
|
|
|
#pod Returns a list of L objects, or the null array |
|
158
|
|
|
|
|
|
|
#pod C<()> if the file does not contain any non-setup sections. |
|
159
|
|
|
|
|
|
|
#pod |
|
160
|
|
|
|
|
|
|
#pod =cut |
|
161
|
|
|
|
|
|
|
|
|
162
|
2
|
|
|
2
|
1
|
518
|
sub class { $_[0]->{class} } |
|
163
|
42
|
|
|
42
|
1
|
2588
|
sub filename { $_[0]->{filename} } |
|
164
|
0
|
0
|
|
0
|
1
|
0
|
sub config { $_[0]->{config} || '' } |
|
165
|
65
|
|
|
65
|
1
|
89
|
sub setup { @{$_[0]->{setup}} } |
|
|
65
|
|
|
|
|
162
|
|
|
166
|
243
|
|
|
243
|
1
|
334
|
sub sections { @{$_[0]->{sections}} } |
|
|
243
|
|
|
|
|
637
|
|
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
##################################################################### |
|
173
|
|
|
|
|
|
|
# Main Methods |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
#pod =pod |
|
176
|
|
|
|
|
|
|
#pod |
|
177
|
|
|
|
|
|
|
#pod =head2 sorted |
|
178
|
|
|
|
|
|
|
#pod |
|
179
|
|
|
|
|
|
|
#pod The C method returns all normal sections from the file, in an order |
|
180
|
|
|
|
|
|
|
#pod that satisfies any dependencies in the sections. |
|
181
|
|
|
|
|
|
|
#pod |
|
182
|
|
|
|
|
|
|
#pod Returns a reference to an array of L objects, |
|
183
|
|
|
|
|
|
|
#pod C<0> if the file does not contain any non-setup sections, or C on |
|
184
|
|
|
|
|
|
|
#pod error. |
|
185
|
|
|
|
|
|
|
#pod |
|
186
|
|
|
|
|
|
|
#pod =cut |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub sorted { |
|
189
|
18
|
|
|
18
|
1
|
40
|
my $self = shift; |
|
190
|
18
|
50
|
|
|
|
79
|
return $self->{sorted} if $self->{sorted}; |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
# Handle the simple case there there are no dependencies, |
|
193
|
|
|
|
|
|
|
# so we don't have to load the dependency algorithm code. |
|
194
|
18
|
100
|
|
|
|
88
|
unless ( map { $_->depends } $self->sections ) { |
|
|
37
|
|
|
|
|
137
|
|
|
195
|
12
|
|
|
|
|
39
|
return $self->{sorted} = [ $self->setup, $self->sections ]; |
|
196
|
|
|
|
|
|
|
} |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# Create the dependency algorithm object |
|
199
|
6
|
50
|
|
|
|
99
|
my $Algorithm = Algorithm::Dependency::Ordered->new( |
|
200
|
|
|
|
|
|
|
source => $self, |
|
201
|
|
|
|
|
|
|
ignore_orphans => 1, # Be lenient to non-existant dependencies |
|
202
|
|
|
|
|
|
|
) or return undef; |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
# Pull the schedule from the algorithm. If we get an error back, it |
|
205
|
|
|
|
|
|
|
# should be because there is a circular dependency. |
|
206
|
6
|
|
|
|
|
218
|
my $schedule = $Algorithm->schedule_all; |
|
207
|
6
|
50
|
|
|
|
118
|
unless ( $schedule ) { |
|
208
|
0
|
|
|
|
|
0
|
warn " (Failed to build $self->{class} test schedule) "; |
|
209
|
0
|
|
|
|
|
0
|
return undef; |
|
210
|
|
|
|
|
|
|
} |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
# Index the sections by name |
|
213
|
6
|
|
|
|
|
20
|
my %hash = map { $_->name => $_ } grep { $_->name } $self->sections; |
|
|
18
|
|
|
|
|
36
|
|
|
|
24
|
|
|
|
|
51
|
|
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
# Merge together the setup, schedule, and anonymous parts into a |
|
216
|
|
|
|
|
|
|
# single sorted list. |
|
217
|
|
|
|
|
|
|
my @sorted = ( |
|
218
|
|
|
|
|
|
|
$self->setup, |
|
219
|
18
|
|
|
|
|
37
|
( map { $hash{$_} } @$schedule ), |
|
220
|
6
|
|
|
|
|
35
|
( grep { $_->anonymous } $self->sections ) |
|
|
24
|
|
|
|
|
51
|
|
|
221
|
|
|
|
|
|
|
); |
|
222
|
|
|
|
|
|
|
|
|
223
|
6
|
|
|
|
|
53
|
$self->{sorted} = \@sorted; |
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
#pod =pod |
|
227
|
|
|
|
|
|
|
#pod |
|
228
|
|
|
|
|
|
|
#pod =head2 tests |
|
229
|
|
|
|
|
|
|
#pod |
|
230
|
|
|
|
|
|
|
#pod If the number of tests for all of the sections within the file are known, |
|
231
|
|
|
|
|
|
|
#pod then the number of tests for the entire file can also be determined. |
|
232
|
|
|
|
|
|
|
#pod |
|
233
|
|
|
|
|
|
|
#pod The C method determines if the number of tests can be known, and |
|
234
|
|
|
|
|
|
|
#pod if so, calculates and returns the number of tests. Returns false if the |
|
235
|
|
|
|
|
|
|
#pod number of tests is not known. |
|
236
|
|
|
|
|
|
|
#pod |
|
237
|
|
|
|
|
|
|
#pod =cut |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
sub tests { |
|
240
|
22
|
|
|
22
|
1
|
44
|
my $self = shift; |
|
241
|
22
|
100
|
|
|
|
60
|
return $self->{tests} if exists $self->{tests}; |
|
242
|
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
# Add up the tests |
|
244
|
19
|
|
|
|
|
32
|
my $total = 0; |
|
245
|
19
|
|
|
|
|
50
|
foreach my $Section ( $self->setup, $self->sections ) { |
|
246
|
|
|
|
|
|
|
# Return undef if section has an unknown number of tests |
|
247
|
37
|
100
|
|
|
|
93
|
return undef unless defined $Section->tests; |
|
248
|
28
|
|
|
|
|
77
|
$total += $Section->tests; |
|
249
|
|
|
|
|
|
|
} |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
# If the total is zero, it's probably screwed, go with "unknown" |
|
252
|
10
|
|
50
|
|
|
46
|
$self->{tests} = $total || undef; |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
#pod =pod |
|
256
|
|
|
|
|
|
|
#pod |
|
257
|
|
|
|
|
|
|
#pod =head2 merged_content |
|
258
|
|
|
|
|
|
|
#pod |
|
259
|
|
|
|
|
|
|
#pod The C method generates and returns the merged contents of all |
|
260
|
|
|
|
|
|
|
#pod the sections in the file, including the setup sections at the beginning. The |
|
261
|
|
|
|
|
|
|
#pod method does not return the entire file, merely the part contained in the |
|
262
|
|
|
|
|
|
|
#pod sections. For the full file contents, see the C method. |
|
263
|
|
|
|
|
|
|
#pod |
|
264
|
|
|
|
|
|
|
#pod Returns a string containing the merged section content on success, false |
|
265
|
|
|
|
|
|
|
#pod if there is no content, despite the existance of sections ( which would |
|
266
|
|
|
|
|
|
|
#pod have been empty ), or C on error. |
|
267
|
|
|
|
|
|
|
#pod |
|
268
|
|
|
|
|
|
|
#pod =cut |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
sub merged_content { |
|
271
|
22
|
|
|
22
|
1
|
41
|
my $self = shift; |
|
272
|
22
|
100
|
|
|
|
81
|
return $self->{content} if exists $self->{content}; |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
# Get the sorted Test::Inline::Section objects |
|
275
|
18
|
50
|
|
|
|
48
|
my $sorted = $self->sorted or return undef; |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# Prepare |
|
278
|
18
|
|
|
|
|
44
|
$self->{_example_count} = 0; |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# Strip out empty sections |
|
281
|
18
|
|
|
|
|
47
|
@$sorted = grep { $_->content =~ /\S/ } @$sorted; |
|
|
43
|
|
|
|
|
98
|
|
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
# Generate wrapped code chunks |
|
284
|
18
|
|
|
|
|
49
|
my @content = map { $self->_wrap_content($_) } @$sorted; |
|
|
43
|
|
|
|
|
93
|
|
|
285
|
18
|
50
|
|
|
|
54
|
return '' unless @content; |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
# Merge to create the core testing code |
|
288
|
18
|
|
|
|
|
100
|
$self->{content} = join "\n\n\n", @content; |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# Clean up and return |
|
291
|
18
|
|
|
|
|
40
|
delete $self->{_example_count}; |
|
292
|
18
|
|
|
|
|
67
|
$self->{content}; |
|
293
|
|
|
|
|
|
|
} |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
# Take a single generated section of code, and wrap it |
|
296
|
|
|
|
|
|
|
# in the standard boilerplate. |
|
297
|
|
|
|
|
|
|
sub _wrap_content { |
|
298
|
43
|
|
|
43
|
|
62
|
my $self = shift; |
|
299
|
43
|
50
|
|
|
|
285
|
my $Section = _INSTANCE(shift, 'Test::Inline::Section') or return undef; |
|
300
|
43
|
|
|
|
|
139
|
my $code = $Section->content; |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# Wrap in compilation test code if an example |
|
303
|
43
|
100
|
|
|
|
95
|
if ( $Section->example ) { |
|
304
|
1
|
|
|
|
|
2
|
$self->{_example_count}++; |
|
305
|
1
|
|
|
|
|
6
|
$code =~ s/^/ /mg; |
|
306
|
1
|
|
|
|
|
6
|
$code = "eval q{\n" |
|
307
|
|
|
|
|
|
|
. " my \$example = sub {\n" |
|
308
|
|
|
|
|
|
|
. " local \$^W = 0;\n" |
|
309
|
|
|
|
|
|
|
. $code |
|
310
|
|
|
|
|
|
|
. " };\n" |
|
311
|
|
|
|
|
|
|
. "};\n" |
|
312
|
|
|
|
|
|
|
. "is(\$@, '', 'Example $self->{_example_count} compiles cleanly');\n"; |
|
313
|
|
|
|
|
|
|
} |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
# Wrap in scope braces unless it is a setup section |
|
316
|
43
|
100
|
|
|
|
132
|
unless ( $Section->setup ) { |
|
317
|
37
|
|
|
|
|
106
|
$code = "{\n" |
|
318
|
|
|
|
|
|
|
. $code |
|
319
|
|
|
|
|
|
|
. "}\n"; |
|
320
|
|
|
|
|
|
|
} |
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# Add the count-checking code if needed |
|
323
|
43
|
100
|
|
|
|
123
|
if ( $Section->{check_count} ) { |
|
324
|
12
|
|
|
|
|
25
|
my $increase = $Section->tests - 1; |
|
325
|
12
|
100
|
|
|
|
31
|
my $were = $increase == 1 ? 'test was' : 'tests were'; |
|
326
|
12
|
|
100
|
|
|
59
|
my $section = |
|
327
|
|
|
|
|
|
|
$code = "\$::__tc = Test::Builder->new->current_test;\n" |
|
328
|
|
|
|
|
|
|
. $code |
|
329
|
|
|
|
|
|
|
. "is( Test::Builder->new->current_test - \$::__tc, " |
|
330
|
|
|
|
|
|
|
. ($increase || '0') |
|
331
|
|
|
|
|
|
|
. ",\n" |
|
332
|
|
|
|
|
|
|
. "\t'$increase $were run in the section' );\n"; |
|
333
|
|
|
|
|
|
|
} |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
# Add the section header |
|
336
|
43
|
|
|
|
|
144
|
$code = "# $Section->{begin}\n" |
|
337
|
|
|
|
|
|
|
. $code; |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
# Aaaaaaaand we're done |
|
340
|
43
|
|
|
|
|
119
|
$code; |
|
341
|
|
|
|
|
|
|
} |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
##################################################################### |
|
348
|
|
|
|
|
|
|
# Implement the Algorithm::Dependency::Source Interface |
|
349
|
|
|
|
|
|
|
# This is used for section-level dependency. |
|
350
|
|
|
|
|
|
|
# These methods, though public, are undocumented. |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
# Our implementation of Algorithm::Dependency::Source->load is a no-op |
|
353
|
21
|
|
|
21
|
1
|
505
|
sub load { 1 } |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
# Pull a single item by name, section in the sections for it |
|
356
|
|
|
|
|
|
|
sub item { |
|
357
|
107
|
|
|
107
|
1
|
1224
|
my $self = shift; |
|
358
|
107
|
50
|
|
|
|
211
|
my $name = shift or return undef; |
|
359
|
107
|
|
|
310
|
|
345
|
List::Util::first { $_->name eq $name } $self->sections; |
|
|
310
|
|
|
|
|
626
|
|
|
360
|
|
|
|
|
|
|
} |
|
361
|
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
# Return, in their original order, all the items ( named sections ) |
|
363
|
27
|
|
|
27
|
1
|
186
|
sub items { grep { $_->name } $_[0]->sections } |
|
|
67
|
|
|
|
|
133
|
|
|
364
|
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
##################################################################### |
|
370
|
|
|
|
|
|
|
# Implement the Algorithm::Dependency::Item Interface |
|
371
|
|
|
|
|
|
|
# This is used for class-level dependency. |
|
372
|
|
|
|
|
|
|
# These methods, though public, are undocumented. |
|
373
|
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
sub id { |
|
375
|
14
|
|
|
14
|
1
|
77
|
$_[0]->{class}; |
|
376
|
|
|
|
|
|
|
} |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
sub depends { |
|
379
|
28
|
|
|
28
|
1
|
144
|
my $self = shift; |
|
380
|
0
|
|
|
|
|
0
|
my %depends = map { $_ => 1 } |
|
381
|
28
|
|
|
|
|
58
|
map { $_->classes } |
|
|
46
|
|
|
|
|
95
|
|
|
382
|
|
|
|
|
|
|
($self->setup, $self->sections); |
|
383
|
28
|
|
|
|
|
71
|
keys %depends; |
|
384
|
|
|
|
|
|
|
} |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
##################################################################### |
|
391
|
|
|
|
|
|
|
# Utility Functions |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
sub _duplicate_names(@) { |
|
394
|
20
|
|
|
20
|
|
53
|
my $self = shift; |
|
395
|
20
|
|
|
|
|
65
|
my %seen = (); |
|
396
|
20
|
|
|
|
|
56
|
foreach ( map { $_->name } $self->sections ) { |
|
|
42
|
|
|
|
|
106
|
|
|
397
|
42
|
100
|
|
|
|
107
|
next unless $_; |
|
398
|
33
|
50
|
|
|
|
140
|
return 1 if $seen{$_}++; |
|
399
|
|
|
|
|
|
|
} |
|
400
|
20
|
|
|
|
|
90
|
undef; |
|
401
|
|
|
|
|
|
|
} |
|
402
|
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
1; |
|
404
|
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
__END__ |