File Coverage

blib/lib/App/TestOnTap/Harness.pm
Criterion Covered Total %
statement 107 108 99.0
branch 12 20 60.0
condition 4 5 80.0
subroutine 18 18 100.0
pod 3 3 100.0
total 144 154 93.5


line stmt bran cond sub pod time code
1             package App::TestOnTap::Harness;
2              
3 19     19   154 use strict;
  19         52  
  19         703  
4 19     19   109 use warnings;
  19         43  
  19         585  
5              
6 19     19   117 use base qw(TAP::Harness);
  19         59  
  19         10857  
7              
8 19     19   125466 use App::TestOnTap::Scheduler;
  19         63  
  19         572  
9 19     19   8958 use App::TestOnTap::Dispenser;
  19         68  
  19         794  
10 19     19   140 use App::TestOnTap::Util qw(slashify runprocess $IS_PACKED);
  19         57  
  19         2114  
11              
12 19     19   8429 use TAP::Formatter::Console;
  19         69264  
  19         617  
13 19     19   8169 use TAP::Formatter::File;
  19         55156  
  19         589  
14              
15 19     19   137 use List::Util qw(max);
  19         47  
  19         20725  
16              
17             sub new
18             {
19 27     27 1 84 my $class = shift;
20 27         71 my $args = shift;
21              
22 27         142 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         10944 $self->{testontap} = { args => $args, pez => App::TestOnTap::Dispenser->new($args) };
35              
36 26         138 return $self;
37             }
38              
39             sub make_scheduler
40             {
41 26     26 1 121774 my $self = shift;
42            
43 26         366 return $self->{scheduler_class}->new($self->{testontap}->{pez}, @_);
44             }
45              
46             sub runtests
47             {
48 26     26 1 68 my $self = shift;
49            
50 26         91 my $args = $self->{testontap}->{args};
51 26         109 my $sr = $args->getSuiteRoot();
52            
53 26         66 my @pairs;
54 26         140 push(@pairs, [ slashify("$sr/$_"), $_ ]) foreach ($self->{testontap}->{pez}->getAllTests());
55              
56 26         83 my $failed = 0;
57             {
58 26         60 my $wdmgr = $self->{testontap}->{args}->getWorkDirManager();
  26         116  
59              
60 26         72 local %ENV = %{$self->{testontap}->{args}->getPreprocess()->getEnv()};
  26         184  
61 26         259 $ENV{TESTONTAP_SUITE_DIR} = $sr;
62 26         214 $ENV{TESTONTAP_TMP_DIR} = $wdmgr->getTmp();
63 26         169 $ENV{TESTONTAP_SAVE_DIR} = $wdmgr->getSaveSuite();
64            
65 26 100       149 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         175 $wdmgr->beginTestRun();
71 25         7319 my $aggregator = $self->SUPER::runtests(@pairs);
72 25         19364 $wdmgr->endTestRun($self->{testontap}->{args}, $aggregator);
73 25   100     400 $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         8 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         2 my $longestTestFileName = 0;
88 1         10 $longestTestFileName = max($longestTestFileName, length($_->[0])) foreach (@pairs);
89 1         3 $longestTestFileName += 10;
90 1         6 my $topDelimLine = '#' x $longestTestFileName;
91 1         3 my $bottomDelimLine = '-' x $longestTestFileName;
92              
93 1         6 while (my $job = $scheduler->get_job())
94             {
95 1         13 my $desc = $job->description();
96 1         9 my $filename = $job->filename;
97 1         7 my $cmdline = $self->exec()->($self, $filename);
98 1         7 my $dryrun = $self->{testontap}->{args}->doDryRun();
99 1 50       7 my $parallelizable = ($self->{testontap}->{args}->getConfig()->parallelizable($desc) ? '' : 'not ') . 'parallelizable';
100 1         64 print "$topDelimLine\n";
101 1         18 print "Run test '$desc' ($parallelizable) using:\n";
102 1         25 print " $_\n" foreach (@$cmdline);
103 1         12 print "$bottomDelimLine\n";
104 1 50       7 if ($dryrun)
105             {
106 0         0 print "(dry run only, actual test not executed)\n";
107             }
108             else
109             {
110 1 50       100508 $failed++ if system(@$cmdline) >> 8;
111             }
112 1         75 $job->finish();
113             }
114             }
115            
116             # run postprocessing
117             #
118 26         2347 my $postcmd = $self->{testontap}->{args}->getConfig()->getPostprocessCmd();
119 26 100 66     396 if ($postcmd && @$postcmd)
120             {
121 1         7 my @postproc;
122             my $xit = runprocess
123             (
124             sub
125             {
126 1     1   21 push(@postproc, $_[0]);
127 1         394 print STDERR $_[0]
128             },
129             $sr,
130             (
131             @$postcmd,
132 1         16 @{$self->{testontap}->{args}->getPreprocess()->getArgv()}
  1         8  
133             )
134             );
135 1 50       46 if ($xit)
136             {
137 1         7 $failed++;
138 1         32 warn("WARNING: exit code '$xit' when running postprocess command\n");
139             }
140 1 50       17 $failed++ if $xit;
141              
142 1         22 $args->getWorkDirManager()->recordPostprocess([ @postproc ]);
143             }
144            
145             # drop the special workaround envvar...
146             #
147 26 50       3927 delete $ENV{PERL5LIB} if $IS_PACKED;
148             }
149            
150 26 50       470 return ($failed > 127) ? 127 : $failed;
151             }
152              
153             sub _open_spool
154             {
155 47     47   4316 my $self = shift;
156 47         171 my $testpath = shift;
157              
158 47         271 return $self->{testontap}->{args}->getWorkDirManager()->openTAPHandle($testpath);
159             }
160              
161             sub _close_spool
162             {
163 47     47   25062293 my $self = shift;
164 47         279 my $parser = shift;
165              
166 47         1368 $self->{testontap}->{args}->getWorkDirManager()->closeTAPHandle($parser);
167              
168 47         266 return;
169             }
170              
171             sub __getExecMapper
172             {
173 27     27   90 my $args = shift;
174              
175             return sub
176             {
177 48     48   2050 my $harness = shift;
178 48         125 my $testfile = shift;
179            
180             # trim down the full file name to the test name
181             #
182 48         350 my $srfs = slashify($args->getSuiteRoot(), '/');
183 48         194 my $testname = slashify($testfile, '/');
184 48         796 $testname =~ s#^\Q$srfs\E/##;
185              
186             # get the commandline corresponding to the test name
187             #
188 48         275 my $cmdline = $args->getConfig()->getExecMapping($testname);
189            
190             # expand it with the full set
191             #
192 48         9859 $cmdline = [ @$cmdline, $testfile, @{$args->getArgv()} ];
  48         315  
193            
194             # make a note of the result for the work area records
195             #
196 48         258 $args->getWorkDirManager()->recordCommandLine($testname, $cmdline);
197            
198 48         248 return $cmdline;
199 27         472 };
200             }
201              
202             sub __getFormatter
203             {
204 27     27   72 my $args = shift;
205              
206 27         153 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       992 -t \*STDOUT
216             ? TAP::Formatter::Console->new($formatterArgs)
217             : TAP::Formatter::File->new($formatterArgs);
218             }
219              
220             1;