line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::TestOnTap::Harness; |
2
|
|
|
|
|
|
|
|
3
|
19
|
|
|
19
|
|
145
|
use strict; |
|
19
|
|
|
|
|
50
|
|
|
19
|
|
|
|
|
616
|
|
4
|
19
|
|
|
19
|
|
134
|
use warnings; |
|
19
|
|
|
|
|
46
|
|
|
19
|
|
|
|
|
665
|
|
5
|
|
|
|
|
|
|
|
6
|
19
|
|
|
19
|
|
123
|
use base qw(TAP::Harness); |
|
19
|
|
|
|
|
52
|
|
|
19
|
|
|
|
|
10705
|
|
7
|
|
|
|
|
|
|
|
8
|
19
|
|
|
19
|
|
123449
|
use App::TestOnTap::Scheduler; |
|
19
|
|
|
|
|
66
|
|
|
19
|
|
|
|
|
616
|
|
9
|
19
|
|
|
19
|
|
8994
|
use App::TestOnTap::Dispenser; |
|
19
|
|
|
|
|
58
|
|
|
19
|
|
|
|
|
739
|
|
10
|
19
|
|
|
19
|
|
147
|
use App::TestOnTap::Util qw(slashify runprocess $IS_PACKED); |
|
19
|
|
|
|
|
51
|
|
|
19
|
|
|
|
|
2139
|
|
11
|
|
|
|
|
|
|
|
12
|
19
|
|
|
19
|
|
8445
|
use TAP::Formatter::Console; |
|
19
|
|
|
|
|
70652
|
|
|
19
|
|
|
|
|
662
|
|
13
|
19
|
|
|
19
|
|
8341
|
use TAP::Formatter::File; |
|
19
|
|
|
|
|
56860
|
|
|
19
|
|
|
|
|
589
|
|
14
|
|
|
|
|
|
|
|
15
|
19
|
|
|
19
|
|
143
|
use List::Util qw(max); |
|
19
|
|
|
|
|
54
|
|
|
19
|
|
|
|
|
20353
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
sub new |
18
|
|
|
|
|
|
|
{ |
19
|
27
|
|
|
27
|
1
|
84
|
my $class = shift; |
20
|
27
|
|
|
|
|
65
|
my $args = shift; |
21
|
|
|
|
|
|
|
|
22
|
27
|
|
|
|
|
154
|
my $self = $class->SUPER::new |
23
|
|
|
|
|
|
|
( |
24
|
|
|
|
|
|
|
{ |
25
|
|
|
|
|
|
|
formatter => __getFormatter($args), |
26
|
|
|
|
|
|
|
jobs => $args->getJobs(), |
27
|
|
|
|
|
|
|
merge => $args->getMerge(), |
28
|
|
|
|
|
|
|
callbacks => { after_test => $args->getWorkDirManager()->getResultCollector() }, |
29
|
|
|
|
|
|
|
'exec' => __getExecMapper($args), |
30
|
|
|
|
|
|
|
scheduler_class => 'App::TestOnTap::Scheduler' |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
); |
33
|
|
|
|
|
|
|
|
34
|
27
|
|
|
|
|
10917
|
$self->{testontap} = { args => $args, pez => App::TestOnTap::Dispenser->new($args) }; |
35
|
|
|
|
|
|
|
|
36
|
26
|
|
|
|
|
140
|
return $self; |
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub make_scheduler |
40
|
|
|
|
|
|
|
{ |
41
|
26
|
|
|
26
|
1
|
118164
|
my $self = shift; |
42
|
|
|
|
|
|
|
|
43
|
26
|
|
|
|
|
331
|
return $self->{scheduler_class}->new($self->{testontap}->{pez}, @_); |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub runtests |
47
|
|
|
|
|
|
|
{ |
48
|
26
|
|
|
26
|
1
|
62
|
my $self = shift; |
49
|
|
|
|
|
|
|
|
50
|
26
|
|
|
|
|
72
|
my $args = $self->{testontap}->{args}; |
51
|
26
|
|
|
|
|
87
|
my $sr = $args->getSuiteRoot(); |
52
|
|
|
|
|
|
|
|
53
|
26
|
|
|
|
|
62
|
my @pairs; |
54
|
26
|
|
|
|
|
124
|
push(@pairs, [ slashify("$sr/$_"), $_ ]) foreach ($self->{testontap}->{pez}->getAllTests()); |
55
|
|
|
|
|
|
|
|
56
|
26
|
|
|
|
|
80
|
my $failed = 0; |
57
|
|
|
|
|
|
|
{ |
58
|
26
|
|
|
|
|
58
|
my $wdmgr = $self->{testontap}->{args}->getWorkDirManager(); |
|
26
|
|
|
|
|
115
|
|
59
|
|
|
|
|
|
|
|
60
|
26
|
|
|
|
|
72
|
local %ENV = %{$self->{testontap}->{args}->getPreprocess()->getEnv()}; |
|
26
|
|
|
|
|
121
|
|
61
|
26
|
|
|
|
|
213
|
$ENV{TESTONTAP_SUITE_DIR} = $sr; |
62
|
26
|
|
|
|
|
150
|
$ENV{TESTONTAP_TMP_DIR} = $wdmgr->getTmp(); |
63
|
26
|
|
|
|
|
156
|
$ENV{TESTONTAP_SAVE_DIR} = $wdmgr->getSaveSuite(); |
64
|
|
|
|
|
|
|
|
65
|
26
|
100
|
|
|
|
140
|
if ($self->{testontap}->{args}->useHarness()) |
66
|
|
|
|
|
|
|
{ |
67
|
|
|
|
|
|
|
# the normal case is to run with a 'real' harness that parses |
68
|
|
|
|
|
|
|
# TAP, handles parallelization, formatters and all that |
69
|
|
|
|
|
|
|
# |
70
|
25
|
|
|
|
|
163
|
$wdmgr->beginTestRun(); |
71
|
25
|
|
|
|
|
7416
|
my $aggregator = $self->SUPER::runtests(@pairs); |
72
|
25
|
|
|
|
|
19244
|
$wdmgr->endTestRun($self->{testontap}->{args}, $aggregator); |
73
|
25
|
|
100
|
|
|
432
|
$failed = $aggregator->failed() || 0; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
else |
76
|
|
|
|
|
|
|
{ |
77
|
|
|
|
|
|
|
# if the user has requested 'no harness', just run the jobs serially |
78
|
|
|
|
|
|
|
# in the right context, but make no effort to parse their output |
79
|
|
|
|
|
|
|
# in any way - more convenient for debugging (esp. with an execmap |
80
|
|
|
|
|
|
|
# that can start a test in debug mode) |
81
|
|
|
|
|
|
|
# |
82
|
1
|
|
|
|
|
6
|
my $scheduler = $self->make_scheduler(@pairs); |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# figure out the longest test file name with some extra to produce some |
85
|
|
|
|
|
|
|
# nice delimiters... |
86
|
|
|
|
|
|
|
# |
87
|
1
|
|
|
|
|
3
|
my $longestTestFileName = 0; |
88
|
1
|
|
|
|
|
7
|
$longestTestFileName = max($longestTestFileName, length($_->[0])) foreach (@pairs); |
89
|
1
|
|
|
|
|
4
|
$longestTestFileName += 10; |
90
|
1
|
|
|
|
|
4
|
my $topDelimLine = '#' x $longestTestFileName; |
91
|
1
|
|
|
|
|
4
|
my $bottomDelimLine = '-' x $longestTestFileName; |
92
|
|
|
|
|
|
|
|
93
|
1
|
|
|
|
|
6
|
while (my $job = $scheduler->get_job()) |
94
|
|
|
|
|
|
|
{ |
95
|
1
|
|
|
|
|
5
|
my $desc = $job->description(); |
96
|
1
|
|
|
|
|
7
|
my $filename = $job->filename; |
97
|
1
|
|
|
|
|
7
|
my $cmdline = $self->exec()->($self, $filename); |
98
|
1
|
|
|
|
|
6
|
my $dryrun = $self->{testontap}->{args}->doDryRun(); |
99
|
1
|
50
|
|
|
|
6
|
my $parallelizable = ($self->{testontap}->{args}->getConfig()->parallelizable($desc) ? '' : 'not ') . 'parallelizable'; |
100
|
1
|
|
|
|
|
56
|
print "$topDelimLine\n"; |
101
|
1
|
|
|
|
|
18
|
print "Run test '$desc' ($parallelizable) using:\n"; |
102
|
1
|
|
|
|
|
23
|
print " $_\n" foreach (@$cmdline); |
103
|
1
|
|
|
|
|
13
|
print "$bottomDelimLine\n"; |
104
|
1
|
50
|
|
|
|
6
|
if ($dryrun) |
105
|
|
|
|
|
|
|
{ |
106
|
0
|
|
|
|
|
0
|
print "(dry run only, actual test not executed)\n"; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
else |
109
|
|
|
|
|
|
|
{ |
110
|
1
|
50
|
|
|
|
105315
|
$failed++ if system(@$cmdline) >> 8; |
111
|
|
|
|
|
|
|
} |
112
|
1
|
|
|
|
|
87
|
$job->finish(); |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# run postprocessing |
117
|
|
|
|
|
|
|
# |
118
|
26
|
|
|
|
|
2580
|
my $postcmd = $self->{testontap}->{args}->getConfig()->getPostprocessCmd(); |
119
|
26
|
100
|
66
|
|
|
386
|
if ($postcmd && @$postcmd) |
120
|
|
|
|
|
|
|
{ |
121
|
1
|
|
|
|
|
5
|
my @postproc; |
122
|
|
|
|
|
|
|
my $xit = runprocess |
123
|
|
|
|
|
|
|
( |
124
|
|
|
|
|
|
|
sub |
125
|
|
|
|
|
|
|
{ |
126
|
1
|
|
|
1
|
|
23
|
push(@postproc, $_[0]); |
127
|
1
|
|
|
|
|
507
|
print STDERR $_[0] |
128
|
|
|
|
|
|
|
}, |
129
|
|
|
|
|
|
|
$sr, |
130
|
|
|
|
|
|
|
( |
131
|
|
|
|
|
|
|
@$postcmd, |
132
|
1
|
|
|
|
|
19
|
@{$self->{testontap}->{args}->getPreprocess()->getArgv()} |
|
1
|
|
|
|
|
11
|
|
133
|
|
|
|
|
|
|
) |
134
|
|
|
|
|
|
|
); |
135
|
1
|
50
|
|
|
|
47
|
if ($xit) |
136
|
|
|
|
|
|
|
{ |
137
|
1
|
|
|
|
|
8
|
$failed++; |
138
|
1
|
|
|
|
|
32
|
warn("WARNING: exit code '$xit' when running postprocess command\n"); |
139
|
|
|
|
|
|
|
} |
140
|
1
|
50
|
|
|
|
16
|
$failed++ if $xit; |
141
|
|
|
|
|
|
|
|
142
|
1
|
|
|
|
|
23
|
$args->getWorkDirManager()->recordPostprocess([ @postproc ]); |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# drop the special workaround envvar... |
146
|
|
|
|
|
|
|
# |
147
|
26
|
50
|
|
|
|
4456
|
delete $ENV{PERL5LIB} if $IS_PACKED; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
26
|
50
|
|
|
|
532
|
return ($failed > 127) ? 127 : $failed; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub _open_spool |
154
|
|
|
|
|
|
|
{ |
155
|
47
|
|
|
47
|
|
3913
|
my $self = shift; |
156
|
47
|
|
|
|
|
197
|
my $testpath = shift; |
157
|
|
|
|
|
|
|
|
158
|
47
|
|
|
|
|
255
|
return $self->{testontap}->{args}->getWorkDirManager()->openTAPHandle($testpath); |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub _close_spool |
162
|
|
|
|
|
|
|
{ |
163
|
47
|
|
|
47
|
|
25031630
|
my $self = shift; |
164
|
47
|
|
|
|
|
296
|
my $parser = shift; |
165
|
|
|
|
|
|
|
|
166
|
47
|
|
|
|
|
1482
|
$self->{testontap}->{args}->getWorkDirManager()->closeTAPHandle($parser); |
167
|
|
|
|
|
|
|
|
168
|
47
|
|
|
|
|
291
|
return; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub __getExecMapper |
172
|
|
|
|
|
|
|
{ |
173
|
27
|
|
|
27
|
|
81
|
my $args = shift; |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
return sub |
176
|
|
|
|
|
|
|
{ |
177
|
48
|
|
|
48
|
|
1929
|
my $harness = shift; |
178
|
48
|
|
|
|
|
143
|
my $testfile = shift; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
# trim down the full file name to the test name |
181
|
|
|
|
|
|
|
# |
182
|
48
|
|
|
|
|
318
|
my $srfs = slashify($args->getSuiteRoot(), '/'); |
183
|
48
|
|
|
|
|
192
|
my $testname = slashify($testfile, '/'); |
184
|
48
|
|
|
|
|
761
|
$testname =~ s#^\Q$srfs\E/##; |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
# get the commandline corresponding to the test name |
187
|
|
|
|
|
|
|
# |
188
|
48
|
|
|
|
|
279
|
my $cmdline = $args->getConfig()->getExecMapping($testname); |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
# expand it with the full set |
191
|
|
|
|
|
|
|
# |
192
|
48
|
|
|
|
|
9709
|
$cmdline = [ @$cmdline, $testfile, @{$args->getArgv()} ]; |
|
48
|
|
|
|
|
292
|
|
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
# make a note of the result for the work area records |
195
|
|
|
|
|
|
|
# |
196
|
48
|
|
|
|
|
239
|
$args->getWorkDirManager()->recordCommandLine($testname, $cmdline); |
197
|
|
|
|
|
|
|
|
198
|
48
|
|
|
|
|
239
|
return $cmdline; |
199
|
27
|
|
|
|
|
506
|
}; |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub __getFormatter |
203
|
|
|
|
|
|
|
{ |
204
|
27
|
|
|
27
|
|
76
|
my $args = shift; |
205
|
|
|
|
|
|
|
|
206
|
27
|
|
|
|
|
188
|
my $formatterArgs = |
207
|
|
|
|
|
|
|
{ |
208
|
|
|
|
|
|
|
jobs => $args->getJobs(), |
209
|
|
|
|
|
|
|
timer => $args->getTimer(), |
210
|
|
|
|
|
|
|
show_count => 1, |
211
|
|
|
|
|
|
|
verbosity => $args->getVerbose(), |
212
|
|
|
|
|
|
|
}; |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
return |
215
|
27
|
50
|
|
|
|
904
|
-t \*STDOUT |
216
|
|
|
|
|
|
|
? TAP::Formatter::Console->new($formatterArgs) |
217
|
|
|
|
|
|
|
: TAP::Formatter::File->new($formatterArgs); |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
1; |