File Coverage

blib/lib/Test2/Harness.pm
Criterion Covered Total %
statement 92 102 90.2
branch 22 32 68.7
condition 9 19 47.3
subroutine 14 14 100.0
pod 0 3 0.0
total 137 170 80.5


line stmt bran cond sub pod time code
1             package Test2::Harness;
2 22     22   87 use strict;
  22         22  
  22         588  
3 22     22   66 use warnings;
  22         43  
  22         784  
4              
5             our $VERSION = '0.000012';
6              
7 22     22   66 use Carp qw/croak/;
  22         22  
  22         1064  
8 22     22   10155 use Time::HiRes qw/sleep/;
  22         22123  
  22         88  
9 22     22   3697 use Scalar::Util qw/blessed/;
  22         23  
  22         3305  
10              
11 22     22   11907 use Test2::Harness::Job;
  22         44  
  22         507  
12 22     22   7680 use Test2::Harness::Runner;
  22         45  
  22         625  
13 22     22   8609 use Test2::Harness::Parser;
  22         44  
  22         596  
14              
15 22         88 use Test2::Util::HashBase qw{
16             parser_class
17             runner
18             listeners
19             switches libs env_vars
20             jobs
21             verbose
22 22     22   89 };
  22         23  
23              
24             sub STEP_DELAY() { '0.05' }
25              
26             sub init {
27 54     54 0 814 my $self = shift;
28              
29 54   50     217 $self->{+ENV_VARS} ||= {};
30 54   50     148 $self->{+LIBS} ||= [];
31 54   50     192 $self->{+SWITCHES} ||= [];
32 54   50     148 $self->{+LISTENERS} ||= [];
33              
34 54   50     164 $self->{+PARSER_CLASS} ||= 'Test2::Harness::Parser';
35              
36 54   33     151 $self->{+RUNNER} ||= Test2::Harness::Runner->new();
37 54   50     175 $self->{+JOBS} ||= 1;
38             }
39              
40             sub environment {
41 663     663 0 1213 my $self = shift;
42              
43 663         4040 my $class = blessed($self);
44              
45             my %out = (
46             'HARNESS_CLASS' => $class,
47              
48             'HARNESS_ACTIVE' => '1',
49             'HARNESS_VERSION' => $Test2::Harness::VERSION,
50              
51             'HARNESS_IS_VERBOSE' => $self->verbose ? 1 : 0,
52              
53             'T2_HARNESS_ACTIVE' => '1',
54             'T2_HARNESS_VERSION' => $Test2::Harness::VERSION,
55              
56             'T2_FORMATTER' => 'T2Harness',
57              
58 663         9804 %{$self->{+ENV_VARS}},
59              
60 663 50 50     3400 'HARNESS_JOBS' => $self->{+JOBS} || 1,
61             );
62              
63 663         5555 return \%out;
64             }
65              
66             sub run {
67 42     42 0 63 my $self = shift;
68 42         189 my (@files) = @_;
69              
70 42 50       168 croak "No files to run" unless @files;
71              
72 42         84 my $pclass = $self->{+PARSER_CLASS};
73 42         84 my $listen = $self->{+LISTENERS};
74 42         84 my $runner = $self->{+RUNNER};
75 42   50     126 my $jobs = $self->{+JOBS} || 1;
76 42         147 my $env = $self->environment;
77              
78 42         126 my $slots = [];
79 42         63 my (@queue, @results);
80              
81 42         63 my $counter = 1;
82             my $start_file = sub {
83 621     621   1377 my $file = shift;
84 621         965 my $job_id = $counter++;
85              
86 621         6464 my $job = Test2::Harness::Job->new(
87             id => $job_id,
88             file => $file,
89             listeners => $listen,
90             );
91              
92             $job->start(
93             runner => $runner,
94             start_args => {
95             env => $self->environment,
96             libs => $self->{+LIBS},
97 621         6453 switches => $self->{+SWITCHES},
98             },
99             parser_class => $pclass,
100             );
101              
102 601         29930 return $job;
103 42         231 };
104              
105             my $wait = sub {
106 621     621   1446 my $slot;
107 621         1326 until($slot) {
108 17963         28881 my $no_sleep = 0;
109 17963         54949 for my $s (1 .. $jobs) {
110 17963         31635 my $job = $slots->[$s];
111              
112 17963 100       51626 if ($job) {
113 17921 100       93195 $no_sleep = 1 if $job->step;
114 17921 100       50389 next unless $job->is_done;
115 579         2433 push @results => $job->result;
116 579         2827 $slots->[$s] = undef;
117             }
118              
119 621 50       1455 next if $slots->[$s];
120              
121 621         840 $slot = $s;
122 621         30776 last;
123             }
124              
125 17963 100       31441 last if $slot;
126 17342 100       45118 next if $no_sleep;
127 6578         330026305 sleep STEP_DELAY();
128             }
129 621         1407 return $slot;
130 42         231 };
131              
132 42         126 for my $file (@files) {
133 621 50       2063 if ($self->{+JOBS} > 1) {
134 0         0 my $header = $runner->header($file);
135 0         0 my $concurrent = $header->{features}->{concurrency};
136 0 0       0 $concurrent = 1 unless defined($concurrent);
137              
138 0 0       0 unless ($concurrent) {
139 0         0 push @queue => $file;
140 0         0 next;
141             }
142             }
143              
144 621         2102 my $slot = $wait->();
145 621         1959 $slots->[$slot] = $start_file->($file);
146             }
147              
148 22         290 while (@$slots) {
149 1805         13703 my $no_sleep = 0;
150              
151 1805         4627 my @keep;
152 1805         10721 for my $j (@$slots) {
153 1827 100       9308 next unless $j;
154              
155 1805 100       21018 $no_sleep = 1 if $j->step;
156              
157 1805 100       12833 if($j->is_done) {
158 22         130 push @results => $j->result;
159             }
160             else {
161 1783         7381 push @keep => $j;
162             }
163             }
164              
165 1805         6285 @$slots = @keep;
166              
167 1805 100       87530356 sleep STEP_DELAY() unless $no_sleep;
168             }
169              
170 22         108 for my $file (@queue) {
171 0         0 my $job = $start_file->($file);
172              
173 0         0 while(!$job->is_done) {
174 0 0       0 sleep STEP_DELAY() unless $job->step;
175             }
176              
177 0         0 push @results => $job->result;
178             }
179              
180 22         1297 return \@results;
181             }
182              
183             1;
184              
185             __END__