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