line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test::Snapshots; |
2
|
6
|
|
|
6
|
|
164151
|
use strict; |
|
6
|
|
|
|
|
16
|
|
|
6
|
|
|
|
|
224
|
|
3
|
6
|
|
|
6
|
|
32
|
use warnings; |
|
6
|
|
|
|
|
10
|
|
|
6
|
|
|
|
|
156
|
|
4
|
|
|
|
|
|
|
|
5
|
6
|
|
|
6
|
|
151
|
use 5.008005; |
|
6
|
|
|
|
|
22
|
|
|
6
|
|
|
|
|
486
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = '0.02'; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 NAME |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
Test::Snapshots - for testing stand alone scripts and executables |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 SYNOPSIS |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
use Test::More; |
16
|
|
|
|
|
|
|
use Test::Snapshots; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
test_all_snapshots('eg'); |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
Will go over all the .pl files in the eg/ directory, run them using |
21
|
|
|
|
|
|
|
with the content of the SCRIPT.out and SCRIPT.err files |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
Optional configurations before calling test_all_snapshots: |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
Test::Snapshots::debug(1); |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
Get some extra diag messages |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
Test::Snapshots::combine(1); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Combines the stdout and stderr and compares them to the SCRIPT.out file |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
Test::Snapshots::set_glob('*.t'); |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
Change the way we locate the scripts to be executed. |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
Test::Snapshots::set_accessories_dir('path/to/dir'); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
Change the place where TS looks for .out files. |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=head1 WARNING |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
This is alpha software. The API will most certainly change as |
47
|
|
|
|
|
|
|
the requirements get clearer. |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=head1 Examples |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
Many of the unit test of this module are actually simple use cases |
52
|
|
|
|
|
|
|
with the files to be tested located in the eg/ subdirectory of the |
53
|
|
|
|
|
|
|
distribution. Check them out. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head1 TODO |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=over 4 |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=item * |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
Add more test this module. Especially, we don't yet have failing tests. |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=item * |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
Change the API to look more OO. Probably sg. like: |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
Test::Snapshots->set_glob() |
68
|
|
|
|
|
|
|
->combine() |
69
|
|
|
|
|
|
|
->set_accessories_dir() |
70
|
|
|
|
|
|
|
->set_directories('eg') |
71
|
|
|
|
|
|
|
->test_all_snapshots(); |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=item * |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
Allow subclassing or extending the module in some other way. |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=item * |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
Deal with command line arguments. (.argv ?) |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=item * |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
Deal with single file asseccories: A single file that holds the contents of |
84
|
|
|
|
|
|
|
the .in , .our, .err etc... file in sections. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
E.g. the PHP core testing has .phpt files with sections: |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
--TEST-- |
89
|
|
|
|
|
|
|
Name of the test |
90
|
|
|
|
|
|
|
--FILE-- |
91
|
|
|
|
|
|
|
The code that needs to be saved in a file and executed |
92
|
|
|
|
|
|
|
--EXPECT-- |
93
|
|
|
|
|
|
|
The expected output |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
Test::Snapshots should be able to support that with the code |
96
|
|
|
|
|
|
|
to be executed inside as in the case of php or being outside |
97
|
|
|
|
|
|
|
as when testing executables. |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=item * |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
Allow to pass several directories to traverse |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=item * |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
Allow multiple runs in the same test script. (This will probably |
106
|
|
|
|
|
|
|
mean the test counting needs to be done separately or we will have |
107
|
|
|
|
|
|
|
to use the new "add plan" feature of Test::More. |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=item * |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
Allow definiton of expected exit code for each file in some |
112
|
|
|
|
|
|
|
centralized form maybe similar to the way skip is defined. |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=item * |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
Do we need a TODO test capability here? |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=item * |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
Use L ? |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=back |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=head1 DESCRIPTION |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
Test::Snapshots was created especially to be able to test a |
127
|
|
|
|
|
|
|
large number of command line oriented executables. It does not |
128
|
|
|
|
|
|
|
matter if the executable is something compiled from C, a Perl, |
129
|
|
|
|
|
|
|
Python or PHP script. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Test::Snapshot can be seen as a very simple replacement of L. |
132
|
|
|
|
|
|
|
It will go over the designated direcory and run every execute like this: |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
executable arguments < input_file > output_file 2> error_file |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
It will then check if the output_file is the same as the exepcted output file |
137
|
|
|
|
|
|
|
and if the error_file is the sameas the expected error file. |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
If an input file is not supplied then the < input_file part will be |
140
|
|
|
|
|
|
|
omitted. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
The input file, the list of arguments and the expected output and |
143
|
|
|
|
|
|
|
error files all have the same name as the executable. So if you have |
144
|
|
|
|
|
|
|
an executable called C then you'd create the following |
145
|
|
|
|
|
|
|
files: |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
fabricate.exe.in |
148
|
|
|
|
|
|
|
fabricate.exe.argv |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
fabricate.exe.out |
151
|
|
|
|
|
|
|
fabricate.exe.err |
152
|
|
|
|
|
|
|
fabricate.exe.exit |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
If .in is omitted we assume there is no input |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
If .argv is omitted then no arguments are provided |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
If .err or .out is omitted then it is assumed to be empty. |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
If .exit is omitted then it is expected that the exit code will be |
161
|
|
|
|
|
|
|
equal to the default exit code which is 0. |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=head2 Multiple test cases |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
Sometime a single executable file should have multiple test cases. That is |
166
|
|
|
|
|
|
|
we might want to provide different .in and .argv files and expect different |
167
|
|
|
|
|
|
|
.out/.err/.exit values. |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
In order to allow such mode the files need to have a number in their name. |
170
|
|
|
|
|
|
|
So if you are testing I the files need to be |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
xyz.01.in |
173
|
|
|
|
|
|
|
xyz.01.out |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
xyz.02.in |
176
|
|
|
|
|
|
|
xyz.02.out |
177
|
|
|
|
|
|
|
xyz.02.err |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
The expected number of test is the number of different numbers so if you have |
180
|
|
|
|
|
|
|
two files xyz.01.in and xyz.27.err then Test::Snapshots will run two test. One |
181
|
|
|
|
|
|
|
of them has no input and some expected error while the other has only input |
182
|
|
|
|
|
|
|
and not expected output or error. |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=head2 Timeout |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
In order to avoid stuck test cases (e.g. waiting on STDIN) |
187
|
|
|
|
|
|
|
by default every test case can run up to 10 secs. |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=head1 METHODS |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=cut |
192
|
|
|
|
|
|
|
|
193
|
6
|
|
|
6
|
|
31
|
use Carp (); |
|
6
|
|
|
|
|
10
|
|
|
6
|
|
|
|
|
149
|
|
194
|
6
|
|
|
6
|
|
8770
|
use File::Temp qw(tempdir); |
|
6
|
|
|
|
|
183261
|
|
|
6
|
|
|
|
|
523
|
|
195
|
6
|
|
|
6
|
|
6252
|
use Text::Diff qw(diff); |
|
6
|
|
|
|
|
65222
|
|
|
6
|
|
|
|
|
484
|
|
196
|
6
|
|
|
6
|
|
7731
|
use File::Find::Rule; |
|
6
|
|
|
|
|
56882
|
|
|
6
|
|
|
|
|
81
|
|
197
|
6
|
|
|
6
|
|
451
|
use List::Util qw(sum); |
|
6
|
|
|
|
|
15
|
|
|
6
|
|
|
|
|
836
|
|
198
|
|
|
|
|
|
|
|
199
|
6
|
|
|
6
|
|
35
|
use base 'Test::Builder::Module'; |
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
906
|
|
200
|
6
|
|
|
6
|
|
122
|
use base 'Exporter'; |
|
6
|
|
|
|
|
14
|
|
|
6
|
|
|
|
|
8753
|
|
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
our @EXPORT = qw(test_all_snapshots); |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
my $debug; |
205
|
|
|
|
|
|
|
my $combine; |
206
|
|
|
|
|
|
|
my $glob = '*.pl'; |
207
|
|
|
|
|
|
|
my $command = $^X; |
208
|
|
|
|
|
|
|
my $skip = {}; |
209
|
|
|
|
|
|
|
my $accessories_dir; |
210
|
|
|
|
|
|
|
my $default_expected_exit = 0; |
211
|
|
|
|
|
|
|
my $multiple; |
212
|
|
|
|
|
|
|
my $timeout = 10; |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=head2 timeout |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
Set timeout for the executions so if one of them gets stuck |
217
|
|
|
|
|
|
|
(e.g. waiting on STDIN) the whole test suit won't suffer. |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
Default 10 secs. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=head2 combine |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
Set to 1 if you'd like to combine the STDOUT and STDERR and compare the |
224
|
|
|
|
|
|
|
combined output to the .out file. |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
Default is 0 meaning they will be captured separatelly and compared |
227
|
|
|
|
|
|
|
separatelly to the .out and .err files. |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
=cut |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
sub combine { |
232
|
1
|
|
|
1
|
1
|
9
|
$combine = shift; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=head2 set_glob |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
Set what glob to use to fine the files to be executed. Currently it |
238
|
|
|
|
|
|
|
defaults to '*.pl' but maybe it should have no default forcing the user |
239
|
|
|
|
|
|
|
to set one. |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=cut |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub set_glob { |
244
|
0
|
|
|
0
|
1
|
0
|
$glob = shift; |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=head2 skip |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
Pass to it a hash ref of path => 'explanation' pairs |
250
|
|
|
|
|
|
|
for all the files that need to be skipped. |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
skip({ |
253
|
|
|
|
|
|
|
path => 'good reason', |
254
|
|
|
|
|
|
|
path2 => 'some excuse', |
255
|
|
|
|
|
|
|
}); |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=cut |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
sub skip { |
260
|
0
|
|
|
0
|
1
|
0
|
$skip = shift; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
=head2 set_accessories_dir |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
We are calling the .out, .err etc files accessories. |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
In some cases you don't want them to be next to the script that |
268
|
|
|
|
|
|
|
are being tested. In such cases you can use the above function |
269
|
|
|
|
|
|
|
to tell Test::Snapshots where those files can be found. |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
=cut |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
sub set_accessories_dir { |
274
|
1
|
|
|
1
|
1
|
7
|
$accessories_dir = shift; |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub multiple { |
279
|
1
|
|
|
1
|
0
|
7
|
$multiple = shift; |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=head2 command |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
By default Test::Snapshots will assume the files to be tested |
285
|
|
|
|
|
|
|
are stand alone executables or that at least they know where their |
286
|
|
|
|
|
|
|
interpreter is. So they will be executed directly. |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
In most of the cases you will want to run them with some |
289
|
|
|
|
|
|
|
specific command. e.g. You might want to make sure they run with the |
290
|
|
|
|
|
|
|
same perl interpreter as your test script runs. In that case call the following: |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
command($^X) |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
In other cases the files need to be executed with some other tool, eg. |
295
|
|
|
|
|
|
|
the perl 6 or python interpreter which is in the path: |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
command("perl6"); |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
or |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
command("python"); |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=cut |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub command { |
306
|
0
|
|
|
0
|
1
|
0
|
$command = shift; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
=head2 default_expected_exit_code |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
The exepceted exit code can be defined on a perl case basis |
312
|
|
|
|
|
|
|
in the .exit file. If the .exit file does not exist |
313
|
|
|
|
|
|
|
then there is a default expected exit code. Which is 0 by default. |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
Use this method to chane the default. |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=cut |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub default_expected_exit_code { |
320
|
0
|
|
|
0
|
1
|
0
|
$default_expected_exit = shift; |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=head2 debug |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
You can turn on the debug flag by calling debug(1). |
326
|
|
|
|
|
|
|
If it is set Test::Snippets will call diag() with all kinds of |
327
|
|
|
|
|
|
|
information during the test execution. |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=cut |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
sub debug { |
332
|
0
|
|
|
0
|
1
|
0
|
$debug = shift; |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=head2 test_all_snapshots |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
This is the call that actually goes out, locates all the |
338
|
|
|
|
|
|
|
files to be tested, sets the C and executes all the test. |
339
|
|
|
|
|
|
|
Currently one should give a directory as a paramter to it but |
340
|
|
|
|
|
|
|
I plan to move that parameter to a separate method and to allow |
341
|
|
|
|
|
|
|
the setting of multiple directories. |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=cut |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
sub test_all_snapshots { |
346
|
4
|
|
|
4
|
1
|
24
|
my ($dir) = @_; |
347
|
|
|
|
|
|
|
|
348
|
4
|
50
|
|
|
|
17
|
Carp::croak("Need to supply directory name") if not defined $dir; |
349
|
|
|
|
|
|
|
|
350
|
4
|
|
|
|
|
171
|
my @files = sort File::Find::Rule->file()->name($glob)->in($dir); |
351
|
4
|
|
|
|
|
4733
|
my $prefix_length = length $dir; |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
# go over all the files and count the different .in, .out, .err, .exit files |
354
|
4
|
|
|
|
|
9
|
my %tests; |
355
|
4
|
100
|
|
|
|
16
|
if ($multiple) { |
356
|
1
|
|
|
|
|
3
|
foreach my $file (@files) { |
357
|
1
|
|
|
|
|
2
|
my %seen; |
358
|
6
|
|
|
|
|
16
|
my @extras = grep { !$seen{$_}++ } |
|
6
|
|
|
|
|
18
|
|
359
|
1
|
|
|
|
|
118
|
map {$_ =~ /\.(\d+)\.(out|err|in|exit)$/; $1} |
|
6
|
|
|
|
|
17
|
|
360
|
|
|
|
|
|
|
glob "$file.*"; |
361
|
1
|
|
|
|
|
7
|
$tests{$file} = \@extras; |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
|
365
|
4
|
|
|
|
|
43
|
my $T = Test::Builder->new; |
366
|
|
|
|
|
|
|
|
367
|
4
|
100
|
|
|
|
53
|
my $cnt = $combine ? 1 : 2; |
368
|
4
|
|
|
|
|
9
|
$cnt++; # for exit codes |
369
|
4
|
|
|
|
|
30
|
my $test_count = @files * $cnt; |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
#use Data::Dumper; |
372
|
|
|
|
|
|
|
#$T->diag(Dumper \@files); |
373
|
|
|
|
|
|
|
#$T->diag(Dumper \%tests); |
374
|
4
|
100
|
|
|
|
19
|
if ($multiple) { |
375
|
|
|
|
|
|
|
#$T->diag(sum (map { scalar @{ $tests{$_} } } @files)); |
376
|
1
|
|
|
|
|
2
|
$test_count = $cnt * sum (map { scalar @{ $tests{$_} } } @files); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
14
|
|
377
|
|
|
|
|
|
|
} |
378
|
4
|
|
|
|
|
23
|
$T->plan(tests => $test_count ); |
379
|
|
|
|
|
|
|
|
380
|
4
|
|
|
|
|
1258
|
foreach my $file (@files) { |
381
|
7
|
50
|
|
|
|
227
|
if ($skip->{$file}) { |
382
|
0
|
0
|
|
|
|
0
|
my $count = $cnt * ($multiple ? scalar(@{ $tests{$file} }) : 1); |
|
0
|
|
|
|
|
0
|
|
383
|
0
|
|
|
|
|
0
|
$T->skip($skip->{$file}) for 1..$count; |
384
|
0
|
|
|
|
|
0
|
next; |
385
|
|
|
|
|
|
|
} |
386
|
7
|
100
|
|
|
|
23
|
if ($multiple) { |
387
|
1
|
|
|
|
|
2
|
foreach my $case (@{ $tests{$file} }) { |
|
1
|
|
|
|
|
3
|
|
388
|
2
|
|
|
|
|
16
|
test_single_file($file, $prefix_length, ".$case"); |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
} else { |
391
|
6
|
|
|
|
|
25
|
test_single_file($file, $prefix_length,); |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
} |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
=head2 test_single_file |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
Testing a single file. It gets the path to the file to be tested. |
399
|
|
|
|
|
|
|
The length of the prefix and optionally a case which is the 01, 02 etc. |
400
|
|
|
|
|
|
|
name of the test case for the multple-test-cases. |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
Currently this is considered an internal method. |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
=cut |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
sub test_single_file { |
408
|
8
|
|
|
8
|
1
|
61
|
my ($file, $prefix_length, $case) = @_; |
409
|
8
|
|
100
|
|
|
50
|
$case ||= ''; |
410
|
|
|
|
|
|
|
|
411
|
8
|
|
|
|
|
90
|
my $tempdir = tempdir( CLEANUP => 1 ); |
412
|
8
|
|
|
|
|
5965
|
my $T = Test::Builder->new; |
413
|
|
|
|
|
|
|
|
414
|
8
|
100
|
|
|
|
88
|
my $accessories_path = $accessories_dir ? $accessories_dir . substr($file, $prefix_length) : $file; |
415
|
|
|
|
|
|
|
#$T->diag($accessories_path); |
416
|
8
|
|
|
|
|
27
|
my $in_file = "$accessories_path$case.in"; |
417
|
|
|
|
|
|
|
|
418
|
8
|
|
|
|
|
18
|
my %std; |
419
|
8
|
|
|
|
|
29
|
$std{out} = "$tempdir/out"; |
420
|
8
|
|
|
|
|
22
|
$std{err} = "$tempdir/err"; |
421
|
|
|
|
|
|
|
|
422
|
8
|
|
|
|
|
26
|
my $cmd = "$command $file"; |
423
|
8
|
100
|
|
|
|
22
|
if ($combine) { |
424
|
2
|
|
|
|
|
7
|
$cmd .= " >$std{out} 2>&1"; |
425
|
|
|
|
|
|
|
} else { |
426
|
6
|
|
|
|
|
202
|
$cmd .= " >$std{out} 2>$std{err}"; |
427
|
|
|
|
|
|
|
} |
428
|
8
|
50
|
|
|
|
154
|
if (-e $in_file) { |
429
|
8
|
|
|
|
|
45
|
$cmd .= " < $in_file"; |
430
|
|
|
|
|
|
|
} |
431
|
8
|
50
|
|
|
|
27
|
if ($debug) { |
432
|
0
|
|
|
|
|
0
|
$T->diag($cmd); |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
|
435
|
8
|
100
|
|
|
|
32
|
my @stds = $combine ? qw(out) : qw(err out); |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
|
438
|
8
|
|
|
|
|
13
|
my $exit; |
439
|
|
|
|
|
|
|
#$T->diag($file); |
440
|
8
|
|
|
0
|
|
233
|
$SIG{ALRM} = sub { die "TIMEOUT\n" }; |
|
0
|
|
|
|
|
0
|
|
441
|
8
|
|
|
|
|
96
|
alarm($timeout); |
442
|
|
|
|
|
|
|
eval { |
443
|
8
|
|
|
|
|
170516
|
system $cmd; |
444
|
8
|
|
|
|
|
504
|
$exit = $?; |
445
|
8
|
|
|
|
|
310
|
1; |
446
|
|
|
|
|
|
|
|
447
|
8
|
50
|
|
|
|
17
|
} or do { |
448
|
0
|
|
|
|
|
0
|
alarm(0); |
449
|
0
|
0
|
|
|
|
0
|
if ($@ eq "TIMEOUT\n") { |
450
|
0
|
|
|
|
|
0
|
$T->ok(0, "Timeout. No result") for 1..@stds+1; |
451
|
0
|
|
|
|
|
0
|
return; |
452
|
|
|
|
|
|
|
} else { |
453
|
0
|
|
|
|
|
0
|
die $@; # unknown exception |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
}; |
456
|
8
|
|
|
|
|
92
|
alarm(0); |
457
|
|
|
|
|
|
|
#$T->diag("Exit '$exit'"); |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
|
460
|
8
|
|
|
|
|
555
|
foreach my $ext (@stds) { |
461
|
14
|
|
|
|
|
6215
|
my $expected = "$accessories_path$case.$ext"; |
462
|
14
|
50
|
|
|
|
599
|
if (-e $expected) { |
463
|
14
|
|
|
|
|
582
|
my $diff = diff($expected, "$std{$ext}"); |
464
|
14
|
50
|
|
|
|
12127
|
$T->ok(!$diff, "$ext of $file") or $T->diag($diff); |
465
|
|
|
|
|
|
|
} else { |
466
|
0
|
|
|
|
|
0
|
my $data = _slurp($std{$ext}); |
467
|
0
|
0
|
|
|
|
0
|
$T->ok($data eq '', "$ext of $file") |
468
|
|
|
|
|
|
|
or $T->diag("Expected nothing.\nReceived\n\n$data"); |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
} |
471
|
|
|
|
|
|
|
# exit code |
472
|
|
|
|
|
|
|
{ |
473
|
8
|
|
|
|
|
11371
|
my $expected_exit = $default_expected_exit; |
|
8
|
|
|
|
|
26
|
|
474
|
8
|
|
|
|
|
28
|
my $expected_file = "$accessories_path$case.exit"; |
475
|
8
|
100
|
|
|
|
163
|
if (-e $expected_file) { |
476
|
3
|
|
|
|
|
34
|
$expected_exit = _slurp($expected_file); |
477
|
3
|
|
|
|
|
11
|
chomp $expected_exit; |
478
|
|
|
|
|
|
|
} |
479
|
8
|
|
|
|
|
82
|
$T->is_eq($exit >> 8, $expected_exit, "Exit code of $file"); |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
|
482
|
8
|
|
|
|
|
5024
|
return; |
483
|
|
|
|
|
|
|
} |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
# a private slurp method. |
487
|
|
|
|
|
|
|
sub _slurp { |
488
|
3
|
|
|
3
|
|
9
|
my $file = shift; |
489
|
3
|
50
|
|
|
|
295
|
open my $fh, '<', $file or die $!; |
490
|
3
|
|
|
|
|
22
|
local $/ = undef; |
491
|
3
|
|
|
|
|
270
|
return <$fh>; |
492
|
|
|
|
|
|
|
} |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=head1 See Also |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
L, L and L. |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
L, L, L, |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
=head1 COPYRIGHT |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
Copyright 2009 Gabor Szabo gabor@szabgab.com http://szabgab.com/ |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
=head1 LICENSE |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or |
507
|
|
|
|
|
|
|
modify it under the same terms as Perl 5 itself. |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
=head1 DISCLAIMER OF WARRANTY |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY |
512
|
|
|
|
|
|
|
FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN |
513
|
|
|
|
|
|
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES |
514
|
|
|
|
|
|
|
PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER |
515
|
|
|
|
|
|
|
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
516
|
|
|
|
|
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE |
517
|
|
|
|
|
|
|
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH |
518
|
|
|
|
|
|
|
YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL |
519
|
|
|
|
|
|
|
NECESSARY SERVICING, REPAIR, OR CORRECTION. |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
522
|
|
|
|
|
|
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR |
523
|
|
|
|
|
|
|
REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE |
524
|
|
|
|
|
|
|
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, |
525
|
|
|
|
|
|
|
OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE |
526
|
|
|
|
|
|
|
THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING |
527
|
|
|
|
|
|
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A |
528
|
|
|
|
|
|
|
FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF |
529
|
|
|
|
|
|
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF |
530
|
|
|
|
|
|
|
SUCH DAMAGES. |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
=cut |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
1; |