line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyright 1999-2001 Steven Knight. All rights reserved. This program |
2
|
|
|
|
|
|
|
# is free software; you can redistribute it and/or modify it under the |
3
|
|
|
|
|
|
|
# same terms as Perl itself. |
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
# This package tests an executable program or script, |
6
|
|
|
|
|
|
|
# managing one or more temporary working directories, |
7
|
|
|
|
|
|
|
# keeping track of standard and error output, |
8
|
|
|
|
|
|
|
# and cleaning up after everything is done. |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
package Test::Cmd; |
11
|
|
|
|
|
|
|
|
12
|
30
|
|
|
30
|
|
150514
|
use 5.006; |
|
30
|
|
|
|
|
80
|
|
|
30
|
|
|
|
|
1016
|
|
13
|
30
|
|
|
30
|
|
120
|
use strict; |
|
30
|
|
|
|
|
40
|
|
|
30
|
|
|
|
|
778
|
|
14
|
30
|
|
|
30
|
|
108
|
use warnings; |
|
30
|
|
|
|
|
44
|
|
|
30
|
|
|
|
|
718
|
|
15
|
30
|
|
|
30
|
|
108
|
use Exporter; |
|
30
|
|
|
|
|
35
|
|
|
30
|
|
|
|
|
949
|
|
16
|
30
|
|
|
30
|
|
135
|
use File::Basename (); # don't import the basename() method, we redefine it |
|
30
|
|
|
|
|
45
|
|
|
30
|
|
|
|
|
466
|
|
17
|
30
|
|
|
30
|
|
111
|
use File::Find; |
|
30
|
|
|
|
|
43
|
|
|
30
|
|
|
|
|
1553
|
|
18
|
30
|
|
|
30
|
|
144
|
use File::Spec; |
|
30
|
|
|
|
|
34
|
|
|
30
|
|
|
|
|
16123
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
our $VERSION = '1.08'; |
21
|
|
|
|
|
|
|
our @ISA = qw(Exporter File::Spec); |
22
|
|
|
|
|
|
|
our @EXPORT_OK = qw(match_exact match_regex diff_exact diff_regex); |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 NAME |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
Test::Cmd - Perl module for portable testing of commands and scripts |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head1 SYNOPSIS |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
An example using L with this module to run a command |
33
|
|
|
|
|
|
|
and then test the exit code, standard out, and standard error: |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
use Test::Cmd; |
36
|
|
|
|
|
|
|
use Test::More tests => 3; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
my $test = Test::Cmd->new( prog => 'outerr', workdir => '' ); |
39
|
|
|
|
|
|
|
$test->run(); |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
is( $test->stdout, "out\n", 'standard out' ); |
42
|
|
|
|
|
|
|
is( $test->stderr, "err\n", 'standard error' ); |
43
|
|
|
|
|
|
|
is( $? >> 8, 1, 'exit status' ); |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
Where C is the shell script: |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
$ cat outerr |
48
|
|
|
|
|
|
|
#!/bin/sh |
49
|
|
|
|
|
|
|
echo out |
50
|
|
|
|
|
|
|
echo >&2 err |
51
|
|
|
|
|
|
|
exit 1 |
52
|
|
|
|
|
|
|
$ chmod +x outerr |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
See below for other examples. Otherwise, the full list of available |
55
|
|
|
|
|
|
|
methods is: |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
use Test::Cmd; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
$test = Test::Cmd->new(prog => 'program_or_script_to_test', |
60
|
|
|
|
|
|
|
interpreter => 'script_interpreter', |
61
|
|
|
|
|
|
|
string => 'identifier_string', |
62
|
|
|
|
|
|
|
workdir => '', |
63
|
|
|
|
|
|
|
subdir => 'dir', |
64
|
|
|
|
|
|
|
match_sub => $code_ref, |
65
|
|
|
|
|
|
|
verbose => 1); |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
$test->verbose(1); |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
$test->prog('program_or_script_to_test'); |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
$test->basename(@suffixlist); |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
$test->interpreter('script_interpreter'); |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
$test->string('identifier string'); |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
$test->workdir('prefix'); |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
$test->workpath('subdir', 'file'); |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
$test->subdir('subdir', ...); |
82
|
|
|
|
|
|
|
$test->subdir(['sub', 'dir'], ...); |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
$test->write('file', <<'EOF'); |
85
|
|
|
|
|
|
|
contents of file |
86
|
|
|
|
|
|
|
EOF |
87
|
|
|
|
|
|
|
$test->write(['subdir', 'file'], <<'EOF'); |
88
|
|
|
|
|
|
|
contents of file |
89
|
|
|
|
|
|
|
EOF |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
$test->read(\$contents, 'file'); |
92
|
|
|
|
|
|
|
$test->read(\@lines, 'file'); |
93
|
|
|
|
|
|
|
$test->read(\$contents, ['subdir', 'file']); |
94
|
|
|
|
|
|
|
$test->read(\@lines, ['subdir', 'file']); |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
$test->writable('dir'); |
97
|
|
|
|
|
|
|
$test->writable('dir', $rwflag); |
98
|
|
|
|
|
|
|
$test->writable('dir', $rwflag, \%errors); |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
$test->preserve(condition, ...); |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
$test->cleanup(condition); |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
$test->run(prog => 'program_or_script_to_test', |
105
|
|
|
|
|
|
|
interpreter => 'script_interpreter', |
106
|
|
|
|
|
|
|
chdir => 'dir', args => 'arguments', stdin => <<'EOF'); |
107
|
|
|
|
|
|
|
input to program |
108
|
|
|
|
|
|
|
EOF |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
$test->pass(condition); |
111
|
|
|
|
|
|
|
$test->pass(condition, \&func); |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
$test->fail(condition); |
114
|
|
|
|
|
|
|
$test->fail(condition, \&func); |
115
|
|
|
|
|
|
|
$test->fail(condition, \&func, $caller); |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
$test->no_result(condition); |
118
|
|
|
|
|
|
|
$test->no_result(condition, \&func); |
119
|
|
|
|
|
|
|
$test->no_result(condition, \&func, $caller); |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
$test->stdout; |
122
|
|
|
|
|
|
|
$test->stdout($run_number); |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
$test->stderr; |
125
|
|
|
|
|
|
|
$test->stderr($run_number); |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
$test->match(\@lines, \@matches); |
128
|
|
|
|
|
|
|
$test->match($lines, $matches); |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
$test->match_exact(\@lines, \@matches); |
131
|
|
|
|
|
|
|
$test->match_exact($lines, $matches); |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
$test->match_regex(\@lines, \@regexes); |
134
|
|
|
|
|
|
|
$test->match_regex($lines, $regexes); |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
$test->diff_exact(\@lines, \@matches, \@output); |
137
|
|
|
|
|
|
|
$test->diff_exact($lines, $matches, \@output); |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
$test->diff_regex(\@lines, \@regexes, \@output); |
140
|
|
|
|
|
|
|
$test->diff_regex($lines, $regexes, \@output); |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
sub func { |
143
|
|
|
|
|
|
|
my ($self, $lines, $matches) = @_; |
144
|
|
|
|
|
|
|
# code to match $lines and $matches |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
$test->match_sub(\&func); |
147
|
|
|
|
|
|
|
$test->match_sub(sub { code to match $_[1] and $_[2] }); |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
$test->here; |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=head1 DESCRIPTION |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
The C module provides a low-level framework for portable |
154
|
|
|
|
|
|
|
automated testing of executable commands and scripts (in any language, |
155
|
|
|
|
|
|
|
not just Perl), especially commands and scripts that interact with the |
156
|
|
|
|
|
|
|
file system. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
The C module makes no assumptions about what constitutes |
159
|
|
|
|
|
|
|
a successful or failed test. Attempting to read a file that doesn't |
160
|
|
|
|
|
|
|
exist, for example, may or may not be an error, depending on the |
161
|
|
|
|
|
|
|
software being tested. |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
Consequently, no C methods (including the C method) |
164
|
|
|
|
|
|
|
exit, die or throw any other sorts of exceptions (but they all do return |
165
|
|
|
|
|
|
|
useful error indications). Exceptions or other error status should |
166
|
|
|
|
|
|
|
be handled by a higher layer: a subclass of L, or another |
167
|
|
|
|
|
|
|
testing framework such as the L or L Perl modules, |
168
|
|
|
|
|
|
|
or by the test itself. |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
(That said, see the L module if you want a similar |
171
|
|
|
|
|
|
|
module that provides exception handling, either to use directly in your |
172
|
|
|
|
|
|
|
own tests, or as an example of how to use C.) |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
In addition to running tests and evaluating conditions, the C |
175
|
|
|
|
|
|
|
module manages and cleans up one or more temporary workspace |
176
|
|
|
|
|
|
|
directories, and provides methods for creating files and directories in |
177
|
|
|
|
|
|
|
those workspace directories from in-line data (that is, here-documents), |
178
|
|
|
|
|
|
|
allowing tests to be completely self-contained. When used in |
179
|
|
|
|
|
|
|
conjunction with another testing framework, the C module can |
180
|
|
|
|
|
|
|
function as a I (common startup code for multiple tests) for |
181
|
|
|
|
|
|
|
simple management of command execution and temporary workspaces. |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
The C module inherits L methods |
184
|
|
|
|
|
|
|
(C, C, etc.) to support writing |
185
|
|
|
|
|
|
|
tests portably across a variety of operating and file systems. |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
A C environment object is created via the usual invocation: |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
$test = Test::Cmd->new(); |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
Arguments to the C method are keyword-value pairs that |
192
|
|
|
|
|
|
|
may be used to initialize the object, typically by invoking the same-named |
193
|
|
|
|
|
|
|
method as the keyword. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=head1 TESTING FRAMEWORKS |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
As mentioned, because the C module makes no assumptions |
198
|
|
|
|
|
|
|
about what constitutes success or failure of a test, it can be used to |
199
|
|
|
|
|
|
|
provide temporary workspaces, other file system interaction, or command |
200
|
|
|
|
|
|
|
execution for a variety of testing frameworks. This section describes |
201
|
|
|
|
|
|
|
how to use the C with several different higher-layer testing |
202
|
|
|
|
|
|
|
frameworks. |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
Note that you should I intermix multiple testing frameworks in a |
205
|
|
|
|
|
|
|
single testing script. |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=head2 C |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
The C module may be used in tests that print results in a |
210
|
|
|
|
|
|
|
format suitable for the standard Perl L module: |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
use Test::Cmd; |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
print "1..5\n"; |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
$test = Test::Cmd->new(prog => 'test_program', workdir => ''); |
217
|
|
|
|
|
|
|
if ($test) { print "ok 1\n"; } else { print "not ok 1\n"; } |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
$input = <<_EOF; |
220
|
|
|
|
|
|
|
test_program should process this input |
221
|
|
|
|
|
|
|
and exit successfully (status 0). |
222
|
|
|
|
|
|
|
_EOF_ |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
$wrote_file = $test->write('input_file', $input); |
225
|
|
|
|
|
|
|
if ($wrote_file) { print "ok 2\n"; } else { print "not ok 2\n"; } |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
$test->run(args => '-x input_file'); |
228
|
|
|
|
|
|
|
if ($? == 0) { print "ok 3\n"; } else { print "not ok 3\n"; } |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
$wrote_file = $test->write('input_file', $input); |
231
|
|
|
|
|
|
|
if ($wrote_file) { print "ok 4\n"; } else { print "not ok 4\n"; } |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
$test->run(args => '-y input_file'); |
234
|
|
|
|
|
|
|
if ($? == 0) { print "ok 5\n"; } else { print "not ok 5\n"; } |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
Several other Perl modules simplify the use of L |
237
|
|
|
|
|
|
|
by eliminating the need to hand-code the C statements and |
238
|
|
|
|
|
|
|
test numbers. The L module, the L module, and |
239
|
|
|
|
|
|
|
the L module all export an C subroutine to test |
240
|
|
|
|
|
|
|
conditions. Here is how the above example would look rewritten to use |
241
|
|
|
|
|
|
|
L: |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
use Test::Simple tests => 5; |
244
|
|
|
|
|
|
|
use Test::Cmd; |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
$test = Test::Cmd->new(prog => 'test_program', workdir => ''); |
247
|
|
|
|
|
|
|
ok($test, "creating Test::Cmd object"); |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
$input = <<_EOF; |
250
|
|
|
|
|
|
|
test_program should process this input |
251
|
|
|
|
|
|
|
and exit successfully (status 0). |
252
|
|
|
|
|
|
|
_EOF_ |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
$wrote_file = $test->write('input_file', $input); |
255
|
|
|
|
|
|
|
ok($wrote_file, "writing input_file"); |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
$test->run(args => '-x input_file'); |
258
|
|
|
|
|
|
|
ok($? == 0, "executing test_program -x input_file"); |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
$wrote_file = $test->write('input_file', $input); |
261
|
|
|
|
|
|
|
ok($wrote_file, "writing input_file"); |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
$test->run(args => '-y input_file'); |
264
|
|
|
|
|
|
|
ok($? == 0, "executing test_program -y input_file"); |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=head2 C |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
The Perl L package provides a procedural testing interface |
269
|
|
|
|
|
|
|
modeled after a testing framework widely used in the eXtreme Programming |
270
|
|
|
|
|
|
|
development methodology. The C module can function as part |
271
|
|
|
|
|
|
|
of a L fixture that can set up workspaces as needed for a |
272
|
|
|
|
|
|
|
set of tests. This avoids having to repeat code to re-initialize an |
273
|
|
|
|
|
|
|
input file multiple times: |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
use Test::Unit; |
276
|
|
|
|
|
|
|
use Test::Cmd; |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
my $test; |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
$input = <<'EOF'; |
281
|
|
|
|
|
|
|
test_program should process this input |
282
|
|
|
|
|
|
|
and exit successfully (status 0). |
283
|
|
|
|
|
|
|
EOF |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
sub set_up { |
286
|
|
|
|
|
|
|
$test = Test::Cmd->new(prog => 'test_program', workdir => ''); |
287
|
|
|
|
|
|
|
$test->write('input_file', $input); |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
sub test_x { |
291
|
|
|
|
|
|
|
my $result = $test->run(args => '-x input_file'); |
292
|
|
|
|
|
|
|
assert($result == 0, "failed test_x\n"); |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
sub test_y { |
296
|
|
|
|
|
|
|
my $result = $test->run(args => '-y input_file'); |
297
|
|
|
|
|
|
|
assert($result == 0, "failed test_y\n"); |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
create_suite(); |
301
|
|
|
|
|
|
|
run_suite; |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
Note that, because the C module takes care of cleaning up |
304
|
|
|
|
|
|
|
temporary workspaces on exit, there is no need to remove explicitly the |
305
|
|
|
|
|
|
|
workspace in a C subroutine. (There may, of course, be other |
306
|
|
|
|
|
|
|
things in the test that need a C subroutine.) |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=head2 Aegis |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
Alternatively, the C module provides C, C, |
311
|
|
|
|
|
|
|
and C methods that can be used to provide an appropriate |
312
|
|
|
|
|
|
|
exit status and simple printed indication for a test. These methods |
313
|
|
|
|
|
|
|
terminate the test immediately, reporting C, C, or |
314
|
|
|
|
|
|
|
C respectively, and exiting with status 0 (success), 1 or 2 |
315
|
|
|
|
|
|
|
respectively. |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
The separate C and C methods allow for a |
318
|
|
|
|
|
|
|
distinction between an actual failed test and a test that could not be |
319
|
|
|
|
|
|
|
properly evaluated because of an external condition (such as a full file |
320
|
|
|
|
|
|
|
system or incorrect permissions). |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
The exit status values happen to match the requirements of the Aegis |
323
|
|
|
|
|
|
|
change management system, and the printed strings are based on existing |
324
|
|
|
|
|
|
|
Aegis conventions. They are not really Aegis-specific, however, and |
325
|
|
|
|
|
|
|
provide a simple, useful starting point if you don't already have |
326
|
|
|
|
|
|
|
another testing framework: |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
use Test::Cmd; |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
$test = Test::Cmd->new(prog => 'test_program', workdir => ''); |
331
|
|
|
|
|
|
|
Test::Cmd->no_result(! $test); |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
$input = <
|
334
|
|
|
|
|
|
|
test_program should process this input |
335
|
|
|
|
|
|
|
and exit successfully (status 0). |
336
|
|
|
|
|
|
|
EOF |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
$wrote_file = $test->write('input_file', $input); |
339
|
|
|
|
|
|
|
$test->no_result(! $wrote_file); |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
$test->run(args => '-x input_file'); |
342
|
|
|
|
|
|
|
$test->fail($? != 0); |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
$wrote_file = $test->write('input_file', $input); |
345
|
|
|
|
|
|
|
$test->no_result(! $wrote_file); |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
$test->run(args => '-y input_file'); |
348
|
|
|
|
|
|
|
$test->fail($? != 0); |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
$test->pass; |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
Note that the separate L wrapper module can simplify |
353
|
|
|
|
|
|
|
the above example even further by taking care of common exception |
354
|
|
|
|
|
|
|
handling cases within the testing object itself. |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
use Test::Cmd::Common; |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
$test = Test::Cmd::Common->new(prog => 'test_program', workdir => ''); |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
$input = <
|
361
|
|
|
|
|
|
|
test_program should process this input |
362
|
|
|
|
|
|
|
and exit successfully (status 0). |
363
|
|
|
|
|
|
|
EOF |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
$wrote_file = $test->write('input_file', $input); |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
$test->run(args => '-x input_file'); |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
$wrote_file = $test->write('input_file', $input); |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
$test->run(args => '-y input_file'); |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
$test->pass; |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
See the L module for details. |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
=head1 METHODS |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
Methods supported by the C module include: |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
=over 4 |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=cut |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
my @Cleanup; |
388
|
|
|
|
|
|
|
my $Run_Count; |
389
|
|
|
|
|
|
|
my $Default; |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
# Map exit values to conditions. |
392
|
|
|
|
|
|
|
my @Cond = ( 'pass', 'fail', 'no_result' ); |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
BEGIN { |
395
|
30
|
|
|
30
|
|
69
|
$Run_Count = 0; |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
# The File::Spec->tmpdir method was only added recently, |
398
|
|
|
|
|
|
|
# so we can't assume it's there. |
399
|
30
|
|
|
|
|
1695
|
$Test::Cmd::TMPDIR = eval("File::Spec->tmpdir"); |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
# now we do win32 detection. what a mess :-( |
402
|
|
|
|
|
|
|
# if the version is 5.003, we can check $^O |
403
|
30
|
|
|
|
|
81
|
my $iswin32; |
404
|
30
|
50
|
|
|
|
109
|
if ($] < 5.003) { |
405
|
0
|
|
|
|
|
0
|
eval("require Win32"); |
406
|
0
|
|
|
|
|
0
|
$iswin32 = ! $@; |
407
|
|
|
|
|
|
|
} else { |
408
|
30
|
|
|
|
|
75
|
$iswin32 = $^O eq "MSWin32"; |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
|
411
|
30
|
|
|
|
|
234
|
my @tmps = (); |
412
|
30
|
50
|
|
|
|
66
|
if ($iswin32) { |
413
|
0
|
|
|
|
|
0
|
eval("use Win32;"); |
414
|
0
|
|
|
|
|
0
|
$Test::Cmd::_WIN32 = 1; |
415
|
0
|
|
|
|
|
0
|
$Test::Cmd::Temp_Prefix = "~testcmd$$-"; |
416
|
0
|
|
|
|
|
0
|
$Test::Cmd::Cwd_Ref = \&Win32::GetCwd; |
417
|
|
|
|
|
|
|
# Test for WIN32 temporary directories. |
418
|
|
|
|
|
|
|
# The following is lifted from the 5.005056 |
419
|
|
|
|
|
|
|
# version of File::Spec::Win32::tmpdir. |
420
|
0
|
|
|
|
|
0
|
push @tmps, (@ENV{qw(TMPDIR TEMP TMP)}, qw(/tmp /)); |
421
|
|
|
|
|
|
|
} else { |
422
|
30
|
|
|
30
|
|
1644
|
eval("use Cwd"); |
|
30
|
|
|
|
|
145
|
|
|
30
|
|
|
|
|
34
|
|
|
30
|
|
|
|
|
1310
|
|
423
|
30
|
|
|
|
|
243
|
$Test::Cmd::Temp_Prefix = "testcmd$$."; |
424
|
30
|
|
|
|
|
44
|
$Test::Cmd::Cwd_Ref = \&Cwd::cwd; |
425
|
|
|
|
|
|
|
# Test for UNIX temporary directories. |
426
|
|
|
|
|
|
|
# The following is lifted from the 5.005056 |
427
|
|
|
|
|
|
|
# version of File::Spec::Unix::tmpdir. |
428
|
30
|
|
|
|
|
75
|
push @tmps, ($ENV{TMPDIR}, "/tmp"); |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
30
|
50
|
|
|
|
89
|
if (! $Test::Cmd::TMPDIR) { |
432
|
0
|
|
|
|
|
0
|
foreach (@tmps) { |
433
|
0
|
0
|
0
|
|
|
0
|
next unless defined && -d && -w; |
|
|
|
0
|
|
|
|
|
434
|
0
|
|
|
|
|
0
|
$Test::Cmd::TMPDIR = $_; |
435
|
0
|
|
|
|
|
0
|
last; |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
# Get the absolute path to the temporary directory, in case |
440
|
|
|
|
|
|
|
# the TMPDIR specification is affected by symbolic links, |
441
|
|
|
|
|
|
|
# or by lack of a volume name on WIN32. |
442
|
|
|
|
|
|
|
# The following better way isn't available in the Cwd module |
443
|
|
|
|
|
|
|
# until sometime after 5.003: |
444
|
|
|
|
|
|
|
# $Test::Cmd::TMPDIR = Cwd::abs_path($Test::Cmd::TMPDIR); |
445
|
30
|
|
|
|
|
60850
|
my($save) = &$Test::Cmd::Cwd_Ref(); |
446
|
30
|
|
|
|
|
713
|
chdir($Test::Cmd::TMPDIR); |
447
|
30
|
|
|
|
|
51454
|
$Test::Cmd::TMPDIR = &$Test::Cmd::Cwd_Ref(); |
448
|
30
|
|
|
|
|
575
|
chdir($save); |
449
|
|
|
|
|
|
|
|
450
|
30
|
|
|
|
|
111
|
$Default = {}; |
451
|
|
|
|
|
|
|
|
452
|
30
|
|
|
|
|
117
|
$Default->{'failed'} = 0; |
453
|
30
|
|
50
|
|
|
421
|
$Default->{'verbose'} = $ENV{VERBOSE} || 0; |
454
|
|
|
|
|
|
|
|
455
|
30
|
50
|
|
|
|
145
|
if (defined $ENV{PRESERVE}) { |
456
|
0
|
|
0
|
|
|
0
|
$Default->{'preserve'}->{'fail'} = $ENV{PRESERVE} || 0; |
457
|
0
|
|
0
|
|
|
0
|
$Default->{'preserve'}->{'pass'} = $ENV{PRESERVE} || 0; |
458
|
0
|
|
0
|
|
|
0
|
$Default->{'preserve'}->{'no_result'} = $ENV{PRESERVE} || 0; |
459
|
|
|
|
|
|
|
} else { |
460
|
30
|
|
50
|
|
|
349
|
$Default->{'preserve'}->{'fail'} = $ENV{PRESERVE_FAIL} || 0; |
461
|
30
|
|
50
|
|
|
193
|
$Default->{'preserve'}->{'pass'} = $ENV{PRESERVE_PASS} || 0; |
462
|
30
|
|
50
|
|
|
200
|
$Default->{'preserve'}->{'no_result'} = $ENV{PRESERVE_NO_RESULT} || 0; |
463
|
|
|
|
|
|
|
} |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
sub handler { |
466
|
0
|
|
|
0
|
0
|
0
|
print STDERR "NO RESULT -- SIG$_ received.\n"; |
467
|
0
|
|
|
|
|
0
|
my $test; |
468
|
0
|
|
|
|
|
0
|
foreach $test (@Cleanup) { |
469
|
0
|
|
|
|
|
0
|
$test->cleanup('no_result'); |
470
|
|
|
|
|
|
|
} |
471
|
0
|
|
|
|
|
0
|
exit(2); |
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
|
474
|
30
|
50
|
|
|
|
238
|
$SIG{HUP} = \&handler if $SIG{HUP}; |
475
|
30
|
|
|
|
|
496
|
$SIG{INT} = \&handler; |
476
|
30
|
|
|
|
|
131
|
$SIG{QUIT} = \&handler; |
477
|
30
|
|
|
|
|
114553
|
$SIG{TERM} = \&handler; |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
END { |
481
|
30
|
|
50
|
30
|
|
1558151
|
my $cond = @Cond[$?] || 'no_result'; |
482
|
30
|
|
|
|
|
1066
|
my $test; |
483
|
30
|
|
|
|
|
108
|
foreach $test (@Cleanup) { |
484
|
51
|
|
|
|
|
1256
|
$test->cleanup($cond); |
485
|
|
|
|
|
|
|
} |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
=item C |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
Create a new C environment. Arguments with which to initialize |
493
|
|
|
|
|
|
|
the environment are passed in as keyword-value pairs. Fails if a |
494
|
|
|
|
|
|
|
specified temporary working directory or subdirectory cannot be created. |
495
|
|
|
|
|
|
|
Does NOT die or exit on failure, but returns C if the test environment |
496
|
|
|
|
|
|
|
object cannot be created. |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=cut |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
sub new { |
501
|
52
|
|
|
52
|
1
|
10490
|
my $type = shift; |
502
|
52
|
|
|
|
|
150
|
my $self = {}; |
503
|
|
|
|
|
|
|
|
504
|
52
|
|
|
|
|
375
|
%$self = %$Default; |
505
|
|
|
|
|
|
|
|
506
|
52
|
|
|
|
|
172
|
$self->{'cleanup'} = []; |
507
|
|
|
|
|
|
|
|
508
|
52
|
|
|
|
|
150
|
$self->{'preserve'} = {}; |
509
|
52
|
|
|
|
|
97
|
%{$self->{'preserve'}} = %{$Default->{'preserve'}}; |
|
52
|
|
|
|
|
186
|
|
|
52
|
|
|
|
|
274
|
|
510
|
|
|
|
|
|
|
|
511
|
52
|
|
|
|
|
105325
|
$self->{'cwd'} = &$Test::Cmd::Cwd_Ref(); |
512
|
|
|
|
|
|
|
|
513
|
52
|
|
|
|
|
626
|
while (@_) { |
514
|
56
|
|
|
|
|
215
|
my $keyword = shift; |
515
|
56
|
|
|
|
|
359
|
$self->{$keyword} = shift; |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
|
518
|
52
|
|
|
|
|
363
|
bless $self, $type; |
519
|
|
|
|
|
|
|
|
520
|
52
|
100
|
|
|
|
658
|
if (defined $self->{'workdir'}) { |
521
|
37
|
100
|
|
|
|
300
|
if (! $self->workdir($self->{'workdir'})) { |
522
|
1
|
|
|
|
|
40
|
return undef; |
523
|
|
|
|
|
|
|
} |
524
|
|
|
|
|
|
|
} |
525
|
51
|
|
|
|
|
222
|
push @Cleanup, $self; |
526
|
51
|
100
|
|
|
|
242
|
if (defined $self->{'subdir'}) { |
527
|
7
|
100
|
|
|
|
53
|
if (! $self->subdir($self->{'subdir'})) { |
528
|
1
|
|
|
|
|
7
|
return undef; |
529
|
|
|
|
|
|
|
} |
530
|
|
|
|
|
|
|
} |
531
|
|
|
|
|
|
|
|
532
|
50
|
|
|
|
|
538
|
$self->prog($self->{'prog'}); |
533
|
|
|
|
|
|
|
|
534
|
50
|
|
100
|
|
|
841
|
$self->match_sub($self->{'match_sub'} || \&Test::Cmd::match_regex); |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
|
537
|
50
|
|
|
|
|
344
|
$self; |
538
|
|
|
|
|
|
|
} |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
=item C |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
Sets the verbose level for the environment object to the specified value. |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
=cut |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
sub verbose { |
549
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
550
|
0
|
|
|
|
|
0
|
$self->{'verbose'} = $_; |
551
|
|
|
|
|
|
|
} |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
=item C |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
Specifies the executable program or script to be tested. Returns the |
558
|
|
|
|
|
|
|
absolute path name of the current program or script. |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
=cut |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
sub prog { |
563
|
58
|
|
|
58
|
1
|
988
|
my ($self, $prog) = @_; |
564
|
58
|
100
|
|
|
|
213
|
if ($prog) { |
565
|
|
|
|
|
|
|
# make sure we're always talking about the same program |
566
|
12
|
50
|
|
|
|
173
|
if (! $self->file_name_is_absolute($prog)) { |
567
|
12
|
|
|
|
|
158
|
$prog = $self->catfile($self->{'cwd'}, $prog); |
568
|
|
|
|
|
|
|
} |
569
|
12
|
|
|
|
|
1077
|
$self->{'prog'} = $prog; |
570
|
|
|
|
|
|
|
} |
571
|
58
|
|
|
|
|
120
|
return $self->{'prog'}; |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
=item C |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
Returns the basename of the current program or script. Any specified |
579
|
|
|
|
|
|
|
arguments are a list of file suffixes that may be stripped from the |
580
|
|
|
|
|
|
|
basename. |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
=cut |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
sub basename { |
585
|
5
|
|
|
5
|
1
|
210
|
my $self = shift; |
586
|
5
|
100
|
|
|
|
15
|
return undef if ! $self->{'prog'}; |
587
|
4
|
|
|
|
|
211
|
File::Basename::basename($self->{'prog'}, @_); |
588
|
|
|
|
|
|
|
} |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
=item C |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
Specifies the program to be used to interpret C as a script. |
595
|
|
|
|
|
|
|
Returns the current value of C. |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
=cut |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
sub interpreter { |
600
|
1
|
|
|
1
|
1
|
289
|
my ($self, $interpreter) = @_; |
601
|
1
|
50
|
|
|
|
7
|
$self->{'interpreter'} = $interpreter if defined $interpreter; |
602
|
1
|
|
|
|
|
3
|
$self->{'interpreter'}; |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
=item C |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
Specifies an identifier string for the functionality being tested to be |
610
|
|
|
|
|
|
|
printed on failure or no result. |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
=cut |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
sub string { |
615
|
4
|
|
|
4
|
1
|
181
|
my ($self, $string) = @_; |
616
|
4
|
100
|
|
|
|
10
|
$self->{'string'} = $string if defined $string; |
617
|
4
|
|
|
|
|
22
|
$self->{'string'}; |
618
|
|
|
|
|
|
|
} |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
my $counter = 0; |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
sub _workdir_name { |
625
|
37
|
|
|
37
|
|
64
|
my $self = shift; |
626
|
37
|
|
|
|
|
66
|
while (1) { |
627
|
37
|
|
|
|
|
87
|
$counter++; |
628
|
37
|
|
|
|
|
1018
|
my $name = $self->catfile($Test::Cmd::TMPDIR, |
629
|
|
|
|
|
|
|
$Test::Cmd::Temp_Prefix . $counter); |
630
|
37
|
50
|
|
|
|
2689
|
return $name if ! -e $name; |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
} |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
=item C |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
When an argument is specified, creates a temporary working directory |
637
|
|
|
|
|
|
|
with the specified name. If the argument is a NULL string (''), |
638
|
|
|
|
|
|
|
the directory is named C by default, followed by the |
639
|
|
|
|
|
|
|
unique ID of the executing process. |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
Returns the absolute pathname to the temporary working directory, or |
642
|
|
|
|
|
|
|
FALSE if the directory could not be created. |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
=cut |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
sub workdir { |
647
|
85
|
|
|
85
|
1
|
8967
|
my ($self, $workdir) = @_; |
648
|
85
|
100
|
|
|
|
290
|
if (defined($workdir)) { |
649
|
|
|
|
|
|
|
# return if $workdir && $self->{'workdir'} eq $workdir; # no change |
650
|
42
|
|
66
|
|
|
343
|
my $wdir = $workdir || $self->_workdir_name; |
651
|
42
|
100
|
|
|
|
34423
|
if (!mkdir($wdir, 0755)) { |
652
|
2
|
|
|
|
|
12
|
return undef; |
653
|
|
|
|
|
|
|
} |
654
|
|
|
|
|
|
|
# The following better way to fetch the absolute path of the |
655
|
|
|
|
|
|
|
# workdir isn't available in the Cwd module until sometime |
656
|
|
|
|
|
|
|
# after 5.003: |
657
|
|
|
|
|
|
|
# $self->{'workdir'} = Cwd::abs_path($wdir); |
658
|
40
|
|
|
|
|
71396
|
my($save) = &$Test::Cmd::Cwd_Ref(); |
659
|
40
|
|
|
|
|
662
|
chdir($wdir); |
660
|
40
|
|
|
|
|
72145
|
$self->{'workdir'} = &$Test::Cmd::Cwd_Ref(); |
661
|
40
|
|
|
|
|
861
|
chdir($save); |
662
|
40
|
|
|
|
|
154
|
push(@{$self->{'cleanup'}}, $self->{'workdir'}); |
|
40
|
|
|
|
|
281
|
|
663
|
|
|
|
|
|
|
} |
664
|
83
|
|
|
|
|
2165
|
$self->{'workdir'}; |
665
|
|
|
|
|
|
|
} |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
=item C |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
Returns the absolute path name to a subdirectory or file under the |
672
|
|
|
|
|
|
|
current temporary working directory by concatenating the temporary |
673
|
|
|
|
|
|
|
working directory name with the specified arguments. |
674
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
=cut |
676
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
sub workpath { |
678
|
26
|
|
|
26
|
1
|
1502
|
my $self = shift; |
679
|
26
|
100
|
|
|
|
69
|
return undef if ! $self->{'workdir'}; |
680
|
25
|
|
|
|
|
398
|
$self->catfile($self->{'workdir'}, @_); |
681
|
|
|
|
|
|
|
} |
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
=item C |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
Creates new subdirectories under the temporary working dir, one for |
688
|
|
|
|
|
|
|
each argument. An argument may be an array reference, in which case the |
689
|
|
|
|
|
|
|
array elements are concatenated together using the Ccatfile> |
690
|
|
|
|
|
|
|
method. Subdirectories multiple levels deep must be created via a |
691
|
|
|
|
|
|
|
separate argument for each level: |
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
$test->subdir('sub', ['sub', 'dir'], [qw(sub dir ectory)]); |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
Returns the number of subdirectories actually created. |
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
=cut |
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
sub subdir { |
700
|
13
|
|
|
13
|
1
|
2415
|
my $self = shift; |
701
|
13
|
|
|
|
|
20
|
my $count = 0; |
702
|
13
|
|
|
|
|
37
|
foreach (@_) { |
703
|
17
|
100
|
|
|
|
110
|
my $newdir = ref $_ ? $self->catfile(@$_) : $_; |
704
|
17
|
100
|
|
|
|
269
|
if (! $self->file_name_is_absolute($newdir)) { |
705
|
15
|
|
|
|
|
136
|
$newdir = $self->catfile($self->{'workdir'}, $newdir); |
706
|
|
|
|
|
|
|
} |
707
|
17
|
100
|
|
|
|
879
|
if (mkdir($newdir, 0755)) { |
708
|
15
|
|
|
|
|
49
|
$count++; |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
} |
711
|
13
|
|
|
|
|
45
|
return $count; |
712
|
|
|
|
|
|
|
} |
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
=item C |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
Writes the specified text (second argument) to the specified file name |
719
|
|
|
|
|
|
|
(first argument). The file name may be an array reference, in which |
720
|
|
|
|
|
|
|
case all the array elements except the last are subdirectory names |
721
|
|
|
|
|
|
|
to be concatenated together. The file is created under the temporary |
722
|
|
|
|
|
|
|
working directory. Any subdirectories in the path must already exist. |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
=cut |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
sub write { |
727
|
33
|
|
|
33
|
1
|
8050
|
my $self = shift; |
728
|
33
|
|
|
|
|
64
|
my $file = shift; # the file to write to |
729
|
33
|
100
|
|
|
|
1122
|
$file = $self->catfile(@$file) if ref $file; |
730
|
33
|
100
|
|
|
|
497
|
if (! $self->file_name_is_absolute($file)) { |
731
|
28
|
|
|
|
|
349
|
$file = $self->catfile($self->{'workdir'}, $file); |
732
|
|
|
|
|
|
|
} |
733
|
33
|
100
|
|
|
|
2379
|
if (! open(OUT, ">$file")) { |
734
|
3
|
|
|
|
|
8
|
return undef; |
735
|
|
|
|
|
|
|
} |
736
|
30
|
50
|
|
|
|
342
|
if (! print OUT @_) { |
737
|
0
|
|
|
|
|
0
|
return undef; |
738
|
|
|
|
|
|
|
} |
739
|
30
|
|
|
|
|
1112
|
return close(OUT); |
740
|
|
|
|
|
|
|
} |
741
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
=item C |
745
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
Reads the contents of the specified file name (second argument) into |
747
|
|
|
|
|
|
|
the scalar or array referred to by the first argument. The file name |
748
|
|
|
|
|
|
|
may be an array reference, in which case all the array elements except |
749
|
|
|
|
|
|
|
the last are subdirectory names to be concatenated together. The file |
750
|
|
|
|
|
|
|
is assumed to be under the temporary working directory unless it is an |
751
|
|
|
|
|
|
|
absolute path name. |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
Returns TRUE on successfully opening and reading the file, FALSE |
754
|
|
|
|
|
|
|
otherwise. |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
=cut |
757
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
sub read { |
759
|
41
|
|
|
41
|
1
|
2222
|
my ($self, $destref, $file) = @_; |
760
|
41
|
50
|
66
|
|
|
265
|
return undef if ref $destref ne 'SCALAR' && ref $destref ne 'ARRAY'; |
761
|
41
|
100
|
|
|
|
100
|
$file = $self->catfile(@$file) if ref $file; |
762
|
41
|
100
|
|
|
|
458
|
if (! $self->file_name_is_absolute($file)) { |
763
|
8
|
|
|
|
|
50
|
$file = $self->catfile($self->{'workdir'}, $file); |
764
|
|
|
|
|
|
|
} |
765
|
41
|
100
|
|
|
|
1253
|
if (! open(IN, "<$file")) { |
766
|
2
|
|
|
|
|
5
|
return undef; |
767
|
|
|
|
|
|
|
} |
768
|
39
|
|
|
|
|
542
|
my @lines = ; |
769
|
39
|
50
|
|
|
|
306
|
if (! close(IN)) { |
770
|
0
|
|
|
|
|
0
|
return undef; |
771
|
|
|
|
|
|
|
} |
772
|
39
|
100
|
|
|
|
122
|
if (ref $destref eq 'SCALAR') { |
773
|
5
|
|
|
|
|
14
|
$$destref = join('', @lines); |
774
|
|
|
|
|
|
|
} else { |
775
|
34
|
|
|
|
|
121
|
@$destref = @lines; |
776
|
|
|
|
|
|
|
} |
777
|
39
|
|
|
|
|
132
|
return (1); |
778
|
|
|
|
|
|
|
} |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
=item C |
783
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
Makes every file and directory within the specified directory tree |
785
|
|
|
|
|
|
|
writable (C == TRUE) or not writable (C == FALSE). The |
786
|
|
|
|
|
|
|
default is to make the directory tree writable. Optionally fills in the |
787
|
|
|
|
|
|
|
supplied hash reference with a hash of path names that could not have |
788
|
|
|
|
|
|
|
their permissions set appropriately, with the reason why each could not |
789
|
|
|
|
|
|
|
be set. |
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
=cut |
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
my $_errors; |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
sub writable { |
796
|
44
|
|
|
44
|
1
|
1280
|
my ($self, $dir, $flag, $err) = @_; |
797
|
44
|
100
|
|
|
|
134
|
$flag = 1 if ! defined $flag; |
798
|
44
|
|
100
|
|
|
1532
|
$Test::Cmd::_errors = $err || {}; |
799
|
44
|
100
|
|
|
|
162
|
if ($flag) { |
800
|
|
|
|
|
|
|
sub _writable { |
801
|
196
|
50
|
|
196
|
|
5714
|
if (!chmod 0755, $_) { |
802
|
0
|
|
|
|
|
0
|
$Test::Cmd::_errors->{$_} = $!; |
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
} |
805
|
42
|
|
|
|
|
7486
|
finddepth(\&_writable, $dir); |
806
|
|
|
|
|
|
|
} else { |
807
|
|
|
|
|
|
|
sub _writeprotect { |
808
|
8
|
50
|
|
8
|
|
277
|
if (!chmod 0555, $_) { |
809
|
0
|
|
|
|
|
0
|
$Test::Cmd::_errors->{$_} = $!; |
810
|
|
|
|
|
|
|
} |
811
|
|
|
|
|
|
|
} |
812
|
2
|
|
|
|
|
342
|
finddepth(\&_writeprotect, $dir); |
813
|
|
|
|
|
|
|
} |
814
|
44
|
|
|
|
|
184
|
return 0 + keys %$Test::Cmd::_errors; |
815
|
|
|
|
|
|
|
} |
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
=item C |
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
Arranges for the temporary working directories for the specified |
822
|
|
|
|
|
|
|
C environment to be preserved for one or more conditions. |
823
|
|
|
|
|
|
|
If no conditions are specified, arranges for the temporary working |
824
|
|
|
|
|
|
|
directories to be preserved for all conditions. |
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
=cut |
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
sub preserve { |
829
|
3
|
|
|
3
|
1
|
279
|
my $self = shift; |
830
|
3
|
50
|
|
|
|
26
|
my @cond = (@_) ? @_ : qw(pass fail no_result); |
831
|
3
|
|
|
|
|
9
|
my $cond; |
832
|
3
|
|
|
|
|
12
|
foreach $cond (@cond) { |
833
|
4
|
|
|
|
|
16
|
$self->{'preserve'}->{$cond} = 1; |
834
|
|
|
|
|
|
|
} |
835
|
|
|
|
|
|
|
} |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
sub _nuke { |
840
|
|
|
|
|
|
|
# print STDERR "unlink($_)\n" if (!-d $_); |
841
|
|
|
|
|
|
|
# print STDERR "rmdir($_)\n" if (-d $_ && $_ ne "."); |
842
|
188
|
100
|
|
188
|
|
6447
|
unlink($_) if (!-d $_); |
843
|
188
|
100
|
100
|
|
|
2837
|
rmdir($_) if (-d $_ && $_ ne "."); |
844
|
188
|
|
|
|
|
2920
|
1; |
845
|
|
|
|
|
|
|
} |
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
=item C |
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
Removes any temporary working directories for the specified C |
852
|
|
|
|
|
|
|
environment. If the environment variable C was set when |
853
|
|
|
|
|
|
|
the C module was loaded, temporary working directories are |
854
|
|
|
|
|
|
|
not removed. If any of the environment variables C, |
855
|
|
|
|
|
|
|
C, or C were set when the C |
856
|
|
|
|
|
|
|
module was loaded, then temporary working directories are not removed |
857
|
|
|
|
|
|
|
if the test passed, failed, or had no result, respectively. Temporary |
858
|
|
|
|
|
|
|
working directories are also preserved for conditions specified via the |
859
|
|
|
|
|
|
|
C method. |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
Typically, this method is not called directly, but is used when the |
862
|
|
|
|
|
|
|
script exits to clean up temporary working directories as appropriate |
863
|
|
|
|
|
|
|
for the exit status. |
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
=cut |
866
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
sub cleanup { |
868
|
62
|
|
|
62
|
1
|
2543
|
my ($self, $cond) = @_; |
869
|
62
|
50
|
|
|
|
1281
|
$cond = (($self->{'failed'} == 0) ? 'pass' : 'fail') if !$cond; |
|
|
100
|
|
|
|
|
|
870
|
62
|
100
|
|
|
|
1214
|
if ($self->{'preserve'}->{$cond}) { |
871
|
5
|
50
|
|
|
|
12
|
print STDERR "Preserving work directory ".$self->{'workdir'}."\n" if $self->{'verbose'}; |
872
|
5
|
|
|
|
|
12
|
return; |
873
|
|
|
|
|
|
|
} |
874
|
57
|
|
|
|
|
1058
|
chdir $self->{'cwd'}; # cd out of whatever work dir we're in |
875
|
57
|
|
|
|
|
83
|
my $dir; |
876
|
57
|
|
|
|
|
3670
|
foreach $dir (@{$self->{'cleanup'}}) { |
|
57
|
|
|
|
|
206
|
|
877
|
40
|
|
|
|
|
179
|
$self->writable($dir, "true"); |
878
|
40
|
|
|
|
|
3218
|
finddepth(\&_nuke, $dir); |
879
|
40
|
|
|
|
|
3568
|
rmdir($dir); |
880
|
|
|
|
|
|
|
} |
881
|
57
|
|
|
|
|
1902
|
$self->{'cleanup'} = []; |
882
|
|
|
|
|
|
|
} |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
=item C |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
Runs a test of the program or script for the test environment. Standard |
889
|
|
|
|
|
|
|
output and error output are saved for future retrieval via the C |
890
|
|
|
|
|
|
|
and C methods. |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
Arguments are supplied as keyword-value pairs: |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
=over 4 |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
=item C |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
Specifies the command-line arguments to be supplied to the program |
899
|
|
|
|
|
|
|
or script under test for this run: |
900
|
|
|
|
|
|
|
|
901
|
|
|
|
|
|
|
$test->run(args => 'arg1 arg2'); |
902
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
=item C |
904
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
Changes directory to the path specified as the value argument: |
906
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
$test->run(chdir => 'xyzzy'); |
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
If the specified path is not an absolute path name (begins with '/' |
910
|
|
|
|
|
|
|
on Unix systems), then the subdirectory is relative to the temporary |
911
|
|
|
|
|
|
|
working directory for the environment (C<$test-&>workdir>). Note that, |
912
|
|
|
|
|
|
|
by default, the C module does NOT chdir to the temporary |
913
|
|
|
|
|
|
|
working directory, so to execute the test under the temporary working |
914
|
|
|
|
|
|
|
directory, you must specify an explicit C to the current directory: |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
$test->run(chdir => '.'); # Unix-specific |
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
$test->run(chdir => $test->curdir); # portable |
919
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
=item C |
921
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
Specifies the program to be used to interpret C as a script, |
923
|
|
|
|
|
|
|
for this run only. This does not change the C<$test-&>interpreter> |
924
|
|
|
|
|
|
|
value of the test environment. |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
=item C |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
Specifies the executable program or script to be run, for this run only. |
929
|
|
|
|
|
|
|
This does not change the C<$test-&>prog> value of the test environment. |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
=item C |
932
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
Pipes the specified value (string or array ref) to the program |
934
|
|
|
|
|
|
|
or script under test for this run: |
935
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
$test->run(stdin => <<_EOF_); |
937
|
|
|
|
|
|
|
input to the program under test |
938
|
|
|
|
|
|
|
_EOF_ |
939
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
=back |
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
Returns the exit status of the program or script. |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
=cut |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
sub run { |
947
|
30
|
|
|
30
|
1
|
2271
|
my $self = shift; |
948
|
30
|
|
|
|
|
112
|
my %args = @_; |
949
|
30
|
|
|
|
|
37
|
my $oldcwd; |
950
|
30
|
100
|
|
|
|
1131
|
if ($args{'chdir'}) { |
951
|
6
|
|
|
|
|
11784
|
$oldcwd = &$Test::Cmd::Cwd_Ref(); |
952
|
6
|
50
|
|
|
|
146
|
if (! $self->file_name_is_absolute($args{'chdir'})) { |
953
|
6
|
|
|
|
|
123
|
$args{'chdir'} = $self->catfile($self->{'workdir'}, $args{'chdir'}); |
954
|
|
|
|
|
|
|
} |
955
|
6
|
50
|
|
|
|
30
|
print STDERR "Changing to $args{'chdir'}\n" if $self->{'verbose'}; |
956
|
6
|
100
|
|
|
|
131
|
if (!chdir $args{'chdir'}) { |
957
|
2
|
|
|
|
|
27
|
return undef; |
958
|
|
|
|
|
|
|
} |
959
|
|
|
|
|
|
|
} |
960
|
28
|
|
|
|
|
42
|
$Run_Count++; |
961
|
28
|
|
|
|
|
108
|
my $stdout_file = $self->_stdout_file($Run_Count); |
962
|
28
|
|
|
|
|
1038
|
my $stderr_file = $self->_stderr_file($Run_Count); |
963
|
28
|
|
|
|
|
54
|
my $cmd; |
964
|
28
|
100
|
|
|
|
73
|
if ($args{'prog'}) { |
965
|
7
|
50
|
|
|
|
64
|
if (! $self->file_name_is_absolute($args{'prog'})) { |
966
|
7
|
|
|
|
|
53
|
$args{'prog'} = $self->catfile($self->{'cwd'}, $args{'prog'}); |
967
|
|
|
|
|
|
|
} |
968
|
7
|
|
|
|
|
17
|
$cmd = $args{'prog'}; |
969
|
7
|
100
|
|
|
|
21
|
$cmd = $args{'interpreter'}." ".$cmd if $args{'interpreter'}; |
970
|
|
|
|
|
|
|
} else { |
971
|
21
|
|
|
|
|
61
|
$cmd = $self->{'prog'}; |
972
|
21
|
100
|
|
|
|
81
|
if ($args{'interpreter'}) { |
|
|
100
|
|
|
|
|
|
973
|
2
|
|
|
|
|
7
|
$cmd = $args{'interpreter'}." ".$cmd; |
974
|
|
|
|
|
|
|
} elsif ($self->{'interpreter'}) { |
975
|
15
|
|
|
|
|
39
|
$cmd = $self->{'interpreter'}." ".$cmd; |
976
|
|
|
|
|
|
|
} |
977
|
|
|
|
|
|
|
} |
978
|
28
|
100
|
|
|
|
93
|
$cmd = $cmd." ".$args{'args'} if $args{'args'}; |
979
|
28
|
|
|
|
|
89
|
$cmd =~ s/\$work/$self->{'workdir'}/g; |
980
|
28
|
|
|
|
|
85
|
$cmd = "|$cmd 1>$stdout_file 2>$stderr_file"; |
981
|
28
|
50
|
|
|
|
71
|
print STDERR "Invoking $cmd\n" if $self->{'verbose'}; |
982
|
28
|
50
|
|
|
|
38259
|
if (! open(RUN, $cmd)) { |
983
|
0
|
|
|
|
|
0
|
$? = 2; |
984
|
0
|
|
|
|
|
0
|
print STDERR "Could not invoke $cmd: $!\n"; |
985
|
0
|
|
|
|
|
0
|
return undef; |
986
|
|
|
|
|
|
|
} |
987
|
28
|
100
|
|
|
|
162
|
if ($args{'stdin'}) { |
988
|
3
|
100
|
|
|
|
38
|
print RUN ref $args{'stdin'} ? @{$args{'stdin'}} : $args{'stdin'}; |
|
1
|
|
|
|
|
15
|
|
989
|
|
|
|
|
|
|
} |
990
|
28
|
|
|
|
|
221008
|
close(RUN); |
991
|
28
|
|
|
|
|
343
|
my $return = $?; |
992
|
28
|
100
|
|
|
|
188
|
chdir $oldcwd if $oldcwd; |
993
|
28
|
|
|
|
|
668
|
return $return; |
994
|
|
|
|
|
|
|
} |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
sub _to_value { |
999
|
0
|
|
|
0
|
|
0
|
my $v = shift; |
1000
|
0
|
0
|
0
|
|
|
0
|
(ref $v or '') eq 'CODE' ? &$v() : $v; |
1001
|
|
|
|
|
|
|
} |
1002
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
|
1005
|
|
|
|
|
|
|
=item C |
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
Exits the test successfully. Reports "PASSED" on the error output and |
1008
|
|
|
|
|
|
|
exits with a status of 0. If a condition is supplied, only exits |
1009
|
|
|
|
|
|
|
the test if the condition evaluates TRUE. If a function reference is |
1010
|
|
|
|
|
|
|
supplied, executes the function before reporting and exiting. |
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
=cut |
1013
|
|
|
|
|
|
|
|
1014
|
|
|
|
|
|
|
sub pass { |
1015
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1016
|
0
|
0
|
|
|
|
0
|
@_ = (1) if @_ == 0; # provide default arg |
1017
|
0
|
|
|
|
|
0
|
my ($cond, $funcref) = @_; |
1018
|
0
|
0
|
|
|
|
0
|
return if ! _to_value($cond); |
1019
|
0
|
0
|
|
|
|
0
|
&$funcref() if $funcref; |
1020
|
0
|
|
|
|
|
0
|
print STDERR "PASSED\n"; |
1021
|
|
|
|
|
|
|
# Let END take care of cleanup. |
1022
|
0
|
|
|
|
|
0
|
exit (0); |
1023
|
|
|
|
|
|
|
} |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
|
1027
|
|
|
|
|
|
|
=item C |
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
Exits the test unsuccessfully. Reports "FAILED test of {string} at line |
1030
|
|
|
|
|
|
|
{line} of {file}." on the error output and exits with a status of 1. |
1031
|
|
|
|
|
|
|
If a condition is supplied, only exits the test if the condition evaluates |
1032
|
|
|
|
|
|
|
TRUE. If a function reference is supplied, executes the function before |
1033
|
|
|
|
|
|
|
reporting and exiting. If a caller level is supplied, prints a simple |
1034
|
|
|
|
|
|
|
calling trace N levels deep as part of reporting the failure. |
1035
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
=cut |
1037
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
sub fail { |
1039
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1040
|
0
|
0
|
|
|
|
0
|
@_ = (1) if @_ == 0; # provide default arg |
1041
|
0
|
|
|
|
|
0
|
my ($cond, $funcref, $caller) = @_; |
1042
|
0
|
0
|
|
|
|
0
|
return if ! _to_value($cond); |
1043
|
0
|
0
|
|
|
|
0
|
&$funcref() if $funcref; |
1044
|
0
|
0
|
|
|
|
0
|
$caller = 0 if ! defined($caller); |
1045
|
0
|
|
|
|
|
0
|
my $of_str = " "; |
1046
|
0
|
0
|
|
|
|
0
|
if (ref $self) { |
1047
|
0
|
|
|
|
|
0
|
my $basename = $self->basename; |
1048
|
0
|
0
|
|
|
|
0
|
if ($basename) { |
1049
|
0
|
|
|
|
|
0
|
$of_str = " of ".$self->basename; |
1050
|
0
|
0
|
|
|
|
0
|
if ($self->{'string'}) { |
1051
|
0
|
|
|
|
|
0
|
$of_str .= " [".$self->{'string'}."]"; |
1052
|
|
|
|
|
|
|
} |
1053
|
0
|
|
|
|
|
0
|
$of_str .= "\n\t"; |
1054
|
|
|
|
|
|
|
} |
1055
|
|
|
|
|
|
|
} |
1056
|
0
|
|
|
|
|
0
|
my $c = 0; |
1057
|
0
|
|
|
|
|
0
|
my ($pkg,$file,$line,$sub) = caller($c++); |
1058
|
0
|
|
|
|
|
0
|
print STDERR "FAILED test${of_str}at line $line of $file"; |
1059
|
0
|
|
|
|
|
0
|
while ($c <= $caller) { |
1060
|
0
|
|
|
|
|
0
|
($pkg,$file,$line,$sub) = caller($c++); |
1061
|
0
|
|
|
|
|
0
|
print STDERR " ($sub)\n\tfrom line $line of $file"; |
1062
|
|
|
|
|
|
|
} |
1063
|
0
|
|
|
|
|
0
|
print STDERR ".\n"; |
1064
|
|
|
|
|
|
|
# Let END take care of cleanup. |
1065
|
0
|
|
|
|
|
0
|
exit (1); |
1066
|
|
|
|
|
|
|
} |
1067
|
|
|
|
|
|
|
|
1068
|
|
|
|
|
|
|
|
1069
|
|
|
|
|
|
|
|
1070
|
|
|
|
|
|
|
=item C |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
Exits the test with an indeterminate result (the test could not be |
1073
|
|
|
|
|
|
|
performed due to external conditions such as, for example, a full |
1074
|
|
|
|
|
|
|
file system). Reports "NO RESULT for test of {string} at line {line} of |
1075
|
|
|
|
|
|
|
{file}." on the error output and exits with a status of 2. If a condition |
1076
|
|
|
|
|
|
|
is supplied, only exits the test if the condition evaluates TRUE. If a |
1077
|
|
|
|
|
|
|
function reference is supplied, executes the function before reporting |
1078
|
|
|
|
|
|
|
and exiting. If a caller level is supplied, prints a simple calling |
1079
|
|
|
|
|
|
|
trace N levels deep as part of reporting the failure. |
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
=cut |
1082
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
sub no_result { |
1084
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1085
|
0
|
0
|
|
|
|
0
|
@_ = (1) if @_ == 0; # provide default arg |
1086
|
0
|
|
|
|
|
0
|
my ($cond, $funcref, $caller) = @_; |
1087
|
0
|
0
|
|
|
|
0
|
return if ! _to_value($cond); |
1088
|
0
|
0
|
|
|
|
0
|
&$funcref() if $funcref; |
1089
|
0
|
0
|
|
|
|
0
|
$caller = 0 if ! defined($caller); |
1090
|
0
|
|
|
|
|
0
|
my $of_str = " "; |
1091
|
0
|
0
|
|
|
|
0
|
if (ref $self) { |
1092
|
0
|
|
|
|
|
0
|
my $basename = $self->basename; |
1093
|
0
|
0
|
|
|
|
0
|
if ($basename) { |
1094
|
0
|
|
|
|
|
0
|
$of_str = " of ".$self->basename; |
1095
|
0
|
0
|
|
|
|
0
|
if ($self->{'string'}) { |
1096
|
0
|
|
|
|
|
0
|
$of_str .= " [".$self->{'string'}."]"; |
1097
|
|
|
|
|
|
|
} |
1098
|
0
|
|
|
|
|
0
|
$of_str .= "\n\t"; |
1099
|
|
|
|
|
|
|
} |
1100
|
|
|
|
|
|
|
} |
1101
|
0
|
|
|
|
|
0
|
my $c = 0; |
1102
|
0
|
|
|
|
|
0
|
my ($pkg,$file,$line,$sub) = caller($c++); |
1103
|
0
|
|
|
|
|
0
|
print STDERR "NO RESULT for test${of_str}at line $line of $file"; |
1104
|
0
|
|
|
|
|
0
|
while ($c <= $caller) { |
1105
|
0
|
|
|
|
|
0
|
($pkg,$file,$line,$sub) = caller($c++); |
1106
|
0
|
|
|
|
|
0
|
print STDERR " ($sub)\n\tfrom line $line of $file"; |
1107
|
|
|
|
|
|
|
} |
1108
|
0
|
|
|
|
|
0
|
print STDERR ".\n"; |
1109
|
|
|
|
|
|
|
# Let END take care of cleanup. |
1110
|
0
|
|
|
|
|
0
|
exit (2); |
1111
|
|
|
|
|
|
|
} |
1112
|
|
|
|
|
|
|
|
1113
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
sub _stdout_file { |
1116
|
45
|
|
|
45
|
|
83
|
my ($self, $count) = @_; |
1117
|
45
|
|
|
|
|
651
|
$self->catfile($self->{'workdir'}, "stdout.$count"); |
1118
|
|
|
|
|
|
|
} |
1119
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
sub _stderr_file { |
1121
|
40
|
|
|
40
|
|
66
|
my ($self, $count) = @_; |
1122
|
40
|
|
|
|
|
319
|
$self->catfile($self->{'workdir'}, "stderr.$count"); |
1123
|
|
|
|
|
|
|
} |
1124
|
|
|
|
|
|
|
|
1125
|
|
|
|
|
|
|
|
1126
|
|
|
|
|
|
|
|
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
|
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
=item C |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
Returns the standard output from the specified run number. If there is no |
1133
|
|
|
|
|
|
|
specified run number, then returns the standard output of the last run. |
1134
|
|
|
|
|
|
|
Returns the standard output as either a scalar or an array of output |
1135
|
|
|
|
|
|
|
lines, as appropriate for the calling context. Returns C if |
1136
|
|
|
|
|
|
|
there has been no test run. |
1137
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
=cut |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
sub stdout { |
1141
|
19
|
|
|
19
|
1
|
4676
|
my $self = shift; |
1142
|
19
|
100
|
|
|
|
1055
|
my $count = @_ ? shift : $Run_Count; |
1143
|
19
|
100
|
|
|
|
73
|
return undef if ! $Run_Count; |
1144
|
17
|
|
|
|
|
25
|
my @lines; |
1145
|
17
|
50
|
|
|
|
81
|
if (! $self->read(\@lines, $self->_stdout_file($count))) { |
1146
|
0
|
|
|
|
|
0
|
return undef; |
1147
|
|
|
|
|
|
|
} |
1148
|
17
|
50
|
|
|
|
149
|
return (wantarray ? @lines : join('', @lines)); |
1149
|
|
|
|
|
|
|
} |
1150
|
|
|
|
|
|
|
|
1151
|
|
|
|
|
|
|
|
1152
|
|
|
|
|
|
|
|
1153
|
|
|
|
|
|
|
=item C |
1154
|
|
|
|
|
|
|
|
1155
|
|
|
|
|
|
|
Returns the error output from the specified run number. If there is |
1156
|
|
|
|
|
|
|
no specified run number, then returns the error output of the last run. |
1157
|
|
|
|
|
|
|
Returns the error output as either a scalar or an array of output lines, |
1158
|
|
|
|
|
|
|
as apporpriate for the calling context. Returns C if there has |
1159
|
|
|
|
|
|
|
been no test run. |
1160
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
=cut |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
sub stderr { |
1164
|
13
|
|
|
13
|
1
|
121
|
my $self = shift; |
1165
|
13
|
100
|
|
|
|
51
|
my $count = @_ ? shift : $Run_Count; |
1166
|
13
|
100
|
|
|
|
1143
|
return undef if ! $Run_Count; |
1167
|
12
|
|
|
|
|
16
|
my @lines; |
1168
|
12
|
50
|
|
|
|
46
|
if (! $self->read(\@lines, $self->_stderr_file($count))) { |
1169
|
0
|
|
|
|
|
0
|
return undef; |
1170
|
|
|
|
|
|
|
} |
1171
|
12
|
50
|
|
|
|
114
|
return (wantarray ? @lines : join('', @lines)); |
1172
|
|
|
|
|
|
|
} |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
|
1175
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
sub _make_arrays { |
1177
|
71
|
|
|
71
|
|
70
|
my ($lines, $matches) = @_; |
1178
|
71
|
|
|
|
|
54
|
my @line_array; |
1179
|
|
|
|
|
|
|
my @match_array; |
1180
|
71
|
100
|
|
|
|
122
|
if (ref $lines) { |
1181
|
31
|
|
|
|
|
87
|
chomp(@line_array = @$lines); |
1182
|
|
|
|
|
|
|
} else { |
1183
|
40
|
|
|
|
|
126
|
@line_array = split(/\n/, $lines, -1); |
1184
|
40
|
|
|
|
|
51
|
pop(@line_array); |
1185
|
|
|
|
|
|
|
} |
1186
|
71
|
100
|
|
|
|
115
|
if (ref $matches) { |
1187
|
31
|
|
|
|
|
65
|
chomp(@match_array = @$matches); |
1188
|
|
|
|
|
|
|
} else { |
1189
|
40
|
|
|
|
|
96
|
@match_array = split(/\n/, $matches, -1); |
1190
|
40
|
|
|
|
|
44
|
pop(@match_array); |
1191
|
|
|
|
|
|
|
} |
1192
|
71
|
|
|
|
|
145
|
return (\@line_array, \@match_array); |
1193
|
|
|
|
|
|
|
} |
1194
|
|
|
|
|
|
|
|
1195
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
|
1197
|
|
|
|
|
|
|
=item C |
1198
|
|
|
|
|
|
|
|
1199
|
|
|
|
|
|
|
Matches one or more input lines against an equal number of expected lines |
1200
|
|
|
|
|
|
|
using the currently-registered line-matching function. The default |
1201
|
|
|
|
|
|
|
line-matching function is the C method, which means that |
1202
|
|
|
|
|
|
|
the default is to match lines against regular expressions. |
1203
|
|
|
|
|
|
|
|
1204
|
|
|
|
|
|
|
=cut |
1205
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
sub match { |
1207
|
23
|
|
|
23
|
1
|
2670
|
my $self = shift; |
1208
|
|
|
|
|
|
|
# We can write this more clearly when we drop support for Perl 5.003: |
1209
|
|
|
|
|
|
|
# $self->{'match_sub'}->($self, @_); |
1210
|
23
|
|
|
|
|
37
|
&{$self->{'match_sub'}}($self, @_); |
|
23
|
|
|
|
|
52
|
|
1211
|
|
|
|
|
|
|
} |
1212
|
|
|
|
|
|
|
|
1213
|
|
|
|
|
|
|
|
1214
|
|
|
|
|
|
|
|
1215
|
|
|
|
|
|
|
sub _matcher { |
1216
|
52
|
|
|
52
|
|
67
|
my ($lines, $matches, $sub) = @_; |
1217
|
52
|
|
|
|
|
80
|
($lines, $matches) = _make_arrays($lines, $matches); |
1218
|
52
|
100
|
|
|
|
184
|
return undef if @$lines != @$matches; |
1219
|
50
|
|
|
|
|
46
|
my ($i, $l, $m); |
1220
|
50
|
|
|
|
|
62
|
for ($i = 0; $i <= $#{ $matches }; $i++) { |
|
106
|
|
|
|
|
212
|
|
1221
|
|
|
|
|
|
|
# More clearly, but doesn't work in Perl 5.003: |
1222
|
|
|
|
|
|
|
# if (! $sub->($lines->[$i], $matches->[$i])) |
1223
|
76
|
100
|
|
|
|
80
|
if (! &{$sub}($lines->[$i], $matches->[$i])) { |
|
76
|
|
|
|
|
123
|
|
1224
|
|
|
|
|
|
|
#print STDERR "Line ", $i+1, " does not match:\n"; |
1225
|
|
|
|
|
|
|
#print STDERR "Expect: ${\$matches->[\$i]}\n"; |
1226
|
|
|
|
|
|
|
#print STDERR "Got: ${\$lines->[\$i]}\n"; |
1227
|
20
|
|
|
|
|
69
|
return undef; |
1228
|
|
|
|
|
|
|
} |
1229
|
|
|
|
|
|
|
} |
1230
|
30
|
|
|
|
|
114
|
return 1; |
1231
|
|
|
|
|
|
|
} |
1232
|
|
|
|
|
|
|
|
1233
|
|
|
|
|
|
|
|
1234
|
|
|
|
|
|
|
|
1235
|
|
|
|
|
|
|
=item C |
1236
|
|
|
|
|
|
|
|
1237
|
|
|
|
|
|
|
Compares two arrays of lines for exact matches. The arguments are passed |
1238
|
|
|
|
|
|
|
in as either scalars, in which case each is split on newline boundaries, |
1239
|
|
|
|
|
|
|
or as array references. An unequal number of lines in the two arrays |
1240
|
|
|
|
|
|
|
fails immediately and returns FALSE before any comparisons are performed. |
1241
|
|
|
|
|
|
|
|
1242
|
|
|
|
|
|
|
Returns TRUE if each line matched its corresponding line in the other |
1243
|
|
|
|
|
|
|
array, FALSE otherwise. |
1244
|
|
|
|
|
|
|
|
1245
|
|
|
|
|
|
|
=cut |
1246
|
|
|
|
|
|
|
|
1247
|
|
|
|
|
|
|
sub match_exact { |
1248
|
22
|
|
|
22
|
1
|
1637
|
my ($self, $lines, $matches) = @_; |
1249
|
22
|
|
|
28
|
|
111
|
_matcher($lines, $matches, sub {$_[0] eq $_[1]}); |
|
28
|
|
|
|
|
71
|
|
1250
|
|
|
|
|
|
|
} |
1251
|
|
|
|
|
|
|
|
1252
|
|
|
|
|
|
|
|
1253
|
|
|
|
|
|
|
|
1254
|
|
|
|
|
|
|
=item C |
1255
|
|
|
|
|
|
|
|
1256
|
|
|
|
|
|
|
Matches one or more input lines against an equal number of regular |
1257
|
|
|
|
|
|
|
expressions. The arguments are passed in as either scalars, in which |
1258
|
|
|
|
|
|
|
case each is split on newline boundaries, or as array references. |
1259
|
|
|
|
|
|
|
Trailing newlines are stripped from each line and regular expression. |
1260
|
|
|
|
|
|
|
An unequal number of lines and regular expressions fails immediately |
1261
|
|
|
|
|
|
|
and returns FALSE before any comparisons are performed. Comparison is |
1262
|
|
|
|
|
|
|
performed for each entire line, that is, with each regular expression |
1263
|
|
|
|
|
|
|
anchored at both the start of line (^) and end of line ($). |
1264
|
|
|
|
|
|
|
|
1265
|
|
|
|
|
|
|
Returns TRUE if each line matched each regular expression, FALSE |
1266
|
|
|
|
|
|
|
otherwise. |
1267
|
|
|
|
|
|
|
|
1268
|
|
|
|
|
|
|
=cut |
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
sub match_regex { |
1271
|
11
|
|
|
11
|
1
|
275
|
my ($self, $lines, $regexes) = @_; |
1272
|
11
|
|
|
17
|
|
57
|
_matcher($lines, $regexes, sub {$_[0] =~ m/^$_[1]$/}); |
|
17
|
|
|
|
|
333
|
|
1273
|
|
|
|
|
|
|
} |
1274
|
|
|
|
|
|
|
|
1275
|
|
|
|
|
|
|
|
1276
|
|
|
|
|
|
|
|
1277
|
|
|
|
|
|
|
sub _range { |
1278
|
0
|
0
|
|
0
|
|
0
|
($_[0]->[1] + 1) . ((@_ == 1) ? '' : (',' . ($_[-1]->[1] + 1))) |
1279
|
|
|
|
|
|
|
} |
1280
|
|
|
|
|
|
|
|
1281
|
|
|
|
|
|
|
my $_differ; |
1282
|
|
|
|
|
|
|
|
1283
|
30
|
|
|
30
|
|
6362
|
eval("use Algorithm::DiffOld;"); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
1284
|
|
|
|
|
|
|
if ($@) { |
1285
|
|
|
|
|
|
|
$_differ = \&_differ_no_lcs; |
1286
|
|
|
|
|
|
|
} else { |
1287
|
|
|
|
|
|
|
$_differ = \&_differ_lcs; |
1288
|
|
|
|
|
|
|
} |
1289
|
|
|
|
|
|
|
|
1290
|
|
|
|
|
|
|
sub _differ_lcs { |
1291
|
0
|
|
|
0
|
|
0
|
my ($matches, $lines, $output, $sub) = @_; |
1292
|
0
|
|
|
|
|
0
|
($lines, $matches) = _make_arrays($lines, $matches); |
1293
|
0
|
0
|
|
|
|
0
|
@$output = () if defined $output; |
1294
|
0
|
|
|
|
|
0
|
my @diffs = Algorithm::DiffOld::diff($matches, $lines, $sub); |
1295
|
0
|
0
|
|
|
|
0
|
return 1 if @diffs == 0; |
1296
|
0
|
0
|
|
|
|
0
|
if (defined $output) { |
1297
|
0
|
|
|
|
|
0
|
my $added = 0; |
1298
|
0
|
|
|
|
|
0
|
my $hunk; |
1299
|
0
|
|
|
|
|
0
|
foreach $hunk (@diffs) { |
1300
|
0
|
|
|
|
|
0
|
my @deletions = grep($_->[0] eq '-', @$hunk); |
1301
|
0
|
|
|
|
|
0
|
my @additions = grep($_->[0] eq '+', @$hunk); |
1302
|
0
|
0
|
|
|
|
0
|
if (! @deletions) { |
|
|
0
|
|
|
|
|
|
1303
|
0
|
|
|
|
|
0
|
push @$output, ($additions[0]->[1] - $added) . 'a' . |
1304
|
|
|
|
|
|
|
_range(@additions) . "\n"; |
1305
|
0
|
|
|
|
|
0
|
push @$output, "> " . |
1306
|
|
|
|
|
|
|
join("\n> ", map($_->[2], @additions)) . |
1307
|
|
|
|
|
|
|
"\n"; |
1308
|
|
|
|
|
|
|
} elsif (! @additions) { |
1309
|
0
|
|
|
|
|
0
|
push @$output, _range(@deletions) . 'd' . |
1310
|
|
|
|
|
|
|
($deletions[0]->[1] + $added) . "\n"; |
1311
|
0
|
|
|
|
|
0
|
push @$output, "< " . |
1312
|
|
|
|
|
|
|
join("\n< ", map($_->[2], @deletions)) . |
1313
|
|
|
|
|
|
|
"\n"; |
1314
|
|
|
|
|
|
|
} else { |
1315
|
0
|
|
|
|
|
0
|
push @$output, _range(@deletions) . 'c' . |
1316
|
|
|
|
|
|
|
_range(@additions) . "\n"; |
1317
|
0
|
|
|
|
|
0
|
push @$output, "< " . |
1318
|
|
|
|
|
|
|
join("\n< ", map($_->[2], @deletions)) . |
1319
|
|
|
|
|
|
|
"\n"; |
1320
|
0
|
|
|
|
|
0
|
push @$output, "---\n"; |
1321
|
0
|
|
|
|
|
0
|
push @$output, "> " . |
1322
|
|
|
|
|
|
|
join("\n> ", map($_->[2], @additions)) . |
1323
|
|
|
|
|
|
|
"\n"; |
1324
|
|
|
|
|
|
|
} |
1325
|
0
|
|
|
|
|
0
|
$added += @additions - @deletions; |
1326
|
|
|
|
|
|
|
} |
1327
|
|
|
|
|
|
|
} |
1328
|
0
|
|
|
|
|
0
|
return undef; |
1329
|
|
|
|
|
|
|
} |
1330
|
|
|
|
|
|
|
|
1331
|
|
|
|
|
|
|
sub _differ_no_lcs { |
1332
|
19
|
|
|
19
|
|
22
|
my ($matches, $lines, $output, $sub) = @_; |
1333
|
19
|
|
|
|
|
36
|
($lines, $matches) = _make_arrays($lines, $matches); |
1334
|
19
|
50
|
|
|
|
60
|
@$output = () if defined $output; |
1335
|
19
|
100
|
|
|
|
29
|
return 1 if _matcher($matches, $lines, $sub); |
1336
|
11
|
50
|
|
|
|
28
|
if (defined $output) { |
1337
|
11
|
|
|
|
|
16
|
push @$output, "Expected =====\n"; |
1338
|
11
|
|
|
|
|
20
|
push @$output, map { $_ . "\n" } @$matches; |
|
67
|
|
|
|
|
101
|
|
1339
|
11
|
|
|
|
|
22
|
push @$output, "Actual =====\n"; |
1340
|
11
|
|
|
|
|
19
|
push @$output, map { $_ . "\n" } @$lines; |
|
63
|
|
|
|
|
80
|
|
1341
|
|
|
|
|
|
|
} |
1342
|
11
|
|
|
|
|
40
|
return undef; |
1343
|
|
|
|
|
|
|
} |
1344
|
|
|
|
|
|
|
|
1345
|
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
|
1347
|
|
|
|
|
|
|
=item C |
1348
|
|
|
|
|
|
|
|
1349
|
|
|
|
|
|
|
Diffs two arrays of lines in a manner similar to the UNIX L |
1350
|
|
|
|
|
|
|
utility. |
1351
|
|
|
|
|
|
|
|
1352
|
|
|
|
|
|
|
If the L package is installed on the local system, |
1353
|
|
|
|
|
|
|
output describing the differences between the input lines and the |
1354
|
|
|
|
|
|
|
matching lines, in L format, is saved to the C<$output> array |
1355
|
|
|
|
|
|
|
reference. In the diff output, the expected output lines are considered |
1356
|
|
|
|
|
|
|
the "old" (left-hand) file, and the actual output is considered the |
1357
|
|
|
|
|
|
|
"new" (right-hand) file. |
1358
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
If the L package is I installed on the local |
1360
|
|
|
|
|
|
|
system, the Expected and Actual contents are saved as-is to the |
1361
|
|
|
|
|
|
|
C<$output> array reference. |
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
The C and C arguments are passed in as either scalars, |
1364
|
|
|
|
|
|
|
in which case each is split on newline boundaries, or as array |
1365
|
|
|
|
|
|
|
references. Trailing newlines are stripped from each line and regular |
1366
|
|
|
|
|
|
|
expression. |
1367
|
|
|
|
|
|
|
|
1368
|
|
|
|
|
|
|
Returns TRUE if each line matched its corresponding line in the expected |
1369
|
|
|
|
|
|
|
matches, FALSE otherwise, in order to conform to the conventions of the |
1370
|
|
|
|
|
|
|
C method. |
1371
|
|
|
|
|
|
|
|
1372
|
|
|
|
|
|
|
Typical invocation: |
1373
|
|
|
|
|
|
|
|
1374
|
|
|
|
|
|
|
if (! $test->diff_exact($test->stdout, |
1375
|
|
|
|
|
|
|
\@expected_lines, |
1376
|
|
|
|
|
|
|
\@diff)) { |
1377
|
|
|
|
|
|
|
print @diff; |
1378
|
|
|
|
|
|
|
} |
1379
|
|
|
|
|
|
|
|
1380
|
|
|
|
|
|
|
=cut |
1381
|
|
|
|
|
|
|
|
1382
|
|
|
|
|
|
|
sub diff_exact { |
1383
|
11
|
|
|
11
|
1
|
3496
|
my ($self, $lines, $matches, $output) = @_; |
1384
|
11
|
|
|
17
|
|
45
|
return &{$_differ}($matches, $lines, $output, sub {$_[0] eq $_[1]}); |
|
11
|
|
|
|
|
20
|
|
|
17
|
|
|
|
|
40
|
|
1385
|
|
|
|
|
|
|
} |
1386
|
|
|
|
|
|
|
|
1387
|
|
|
|
|
|
|
|
1388
|
|
|
|
|
|
|
|
1389
|
|
|
|
|
|
|
=item C |
1390
|
|
|
|
|
|
|
|
1391
|
|
|
|
|
|
|
Diffs one or more input lines against one or more regular expressions |
1392
|
|
|
|
|
|
|
in a manner similar to the UNIX L utility. |
1393
|
|
|
|
|
|
|
|
1394
|
|
|
|
|
|
|
If the L package is installed on the local system, |
1395
|
|
|
|
|
|
|
output describing the differences between the input lines and the |
1396
|
|
|
|
|
|
|
matching lines, in L format, is saved to the C<$output> array |
1397
|
|
|
|
|
|
|
reference. In the diff output, the expected output lines are considered |
1398
|
|
|
|
|
|
|
the "old" (left-hand) file, and the actual output is considered the |
1399
|
|
|
|
|
|
|
"new" (right-hand) file. |
1400
|
|
|
|
|
|
|
|
1401
|
|
|
|
|
|
|
If the L package is I installed on the local |
1402
|
|
|
|
|
|
|
system, the Expected and Actual contents are saved as-is to the |
1403
|
|
|
|
|
|
|
C<$output> array reference. |
1404
|
|
|
|
|
|
|
|
1405
|
|
|
|
|
|
|
The C and C arguments are passed in as either scalars, |
1406
|
|
|
|
|
|
|
in which case each is split on newline boundaries, or as array |
1407
|
|
|
|
|
|
|
references. Trailing newlines are stripped from each line and regular |
1408
|
|
|
|
|
|
|
expression. Comparison is performed for each entire line, that is, with |
1409
|
|
|
|
|
|
|
each regular expression anchored at both the start of line (^) and end |
1410
|
|
|
|
|
|
|
of line ($). |
1411
|
|
|
|
|
|
|
|
1412
|
|
|
|
|
|
|
Returns TRUE if each line matched each regular expression, FALSE |
1413
|
|
|
|
|
|
|
otherwise, in order to conform to the conventions of the C |
1414
|
|
|
|
|
|
|
method. |
1415
|
|
|
|
|
|
|
|
1416
|
|
|
|
|
|
|
Typical invocation: |
1417
|
|
|
|
|
|
|
|
1418
|
|
|
|
|
|
|
if (! $test->diff_regex($test->stdout, |
1419
|
|
|
|
|
|
|
\@expected_lines, |
1420
|
|
|
|
|
|
|
\@diff)) { |
1421
|
|
|
|
|
|
|
print @diff; |
1422
|
|
|
|
|
|
|
} |
1423
|
|
|
|
|
|
|
|
1424
|
|
|
|
|
|
|
=cut |
1425
|
|
|
|
|
|
|
|
1426
|
|
|
|
|
|
|
sub diff_regex { |
1427
|
8
|
|
|
8
|
1
|
2395
|
my ($self, $lines, $regexes, $output) = @_; |
1428
|
8
|
|
|
14
|
|
35
|
return &{$_differ}($regexes, $lines, $output, sub {$_[1] =~ /^$_[0]$/}); |
|
8
|
|
|
|
|
16
|
|
|
14
|
|
|
|
|
196
|
|
1429
|
|
|
|
|
|
|
} |
1430
|
|
|
|
|
|
|
|
1431
|
|
|
|
|
|
|
|
1432
|
|
|
|
|
|
|
|
1433
|
|
|
|
|
|
|
=item C |
1434
|
|
|
|
|
|
|
|
1435
|
|
|
|
|
|
|
Registers the specified code reference as the line-matching function |
1436
|
|
|
|
|
|
|
to be called by the C method. This can be a user-supplied |
1437
|
|
|
|
|
|
|
subroutine, or the C, C, C, or |
1438
|
|
|
|
|
|
|
C methods supplied by the C module: |
1439
|
|
|
|
|
|
|
|
1440
|
|
|
|
|
|
|
$test->match_sub(\&Test::Cmd::match_exact); |
1441
|
|
|
|
|
|
|
|
1442
|
|
|
|
|
|
|
$test->match_sub(\&Test::Cmd::match_regex); |
1443
|
|
|
|
|
|
|
|
1444
|
|
|
|
|
|
|
$test->match_sub(\&Test::Cmd::diff_exact); |
1445
|
|
|
|
|
|
|
|
1446
|
|
|
|
|
|
|
$test->match_sub(\&Test::Cmd::diff_regex); |
1447
|
|
|
|
|
|
|
|
1448
|
|
|
|
|
|
|
The C, C, C and C |
1449
|
|
|
|
|
|
|
subroutine names are exportable from the C module, and may be |
1450
|
|
|
|
|
|
|
specified at object initialization: |
1451
|
|
|
|
|
|
|
|
1452
|
|
|
|
|
|
|
use Test::Cmd qw(match_exact match_regex diff_exact diff_regex); |
1453
|
|
|
|
|
|
|
$test_exact = Test::Cmd->new(match_sub => \&match_exact); |
1454
|
|
|
|
|
|
|
$test_regex = Test::Cmd->new(match_sub => \&match_regex); |
1455
|
|
|
|
|
|
|
$test_exact = Test::Cmd->new(match_sub => \&diff_exact); |
1456
|
|
|
|
|
|
|
$test_regex = Test::Cmd->new(match_sub => \&diff_regex); |
1457
|
|
|
|
|
|
|
|
1458
|
|
|
|
|
|
|
=cut |
1459
|
|
|
|
|
|
|
|
1460
|
|
|
|
|
|
|
sub match_sub { |
1461
|
55
|
|
|
55
|
1
|
656
|
my ($self, $funcref) = @_; |
1462
|
55
|
50
|
|
|
|
2305
|
$self->{'match_sub'} = $funcref if defined $funcref; |
1463
|
55
|
|
|
|
|
100
|
$self->{'match_sub'}; |
1464
|
|
|
|
|
|
|
} |
1465
|
|
|
|
|
|
|
|
1466
|
|
|
|
|
|
|
|
1467
|
|
|
|
|
|
|
|
1468
|
|
|
|
|
|
|
=item C |
1469
|
|
|
|
|
|
|
|
1470
|
|
|
|
|
|
|
Returns the absolute path name of the current working directory. |
1471
|
|
|
|
|
|
|
(This is essentially the same as the C method, except that the |
1472
|
|
|
|
|
|
|
C method preserves the directory separators exactly |
1473
|
|
|
|
|
|
|
as returned by the underlying operating-system-dependent method. |
1474
|
|
|
|
|
|
|
The C method canonicalizes all directory separators to '/', |
1475
|
|
|
|
|
|
|
which makes for consistent path name representations within Perl, but may |
1476
|
|
|
|
|
|
|
mess up another program or script to which you try to pass the path name.) |
1477
|
|
|
|
|
|
|
|
1478
|
|
|
|
|
|
|
=cut |
1479
|
|
|
|
|
|
|
|
1480
|
|
|
|
|
|
|
sub here { |
1481
|
6
|
|
|
6
|
1
|
14536
|
&$Test::Cmd::Cwd_Ref(); |
1482
|
|
|
|
|
|
|
} |
1483
|
|
|
|
|
|
|
|
1484
|
|
|
|
|
|
|
|
1485
|
|
|
|
|
|
|
|
1486
|
|
|
|
|
|
|
1; |
1487
|
|
|
|
|
|
|
__END__ |