line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# PODNAME: App::ape::plan |
2
|
|
|
|
|
|
|
# ABSTRACT: plan testing using elasticsearch |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
package App::ape::plan; |
5
|
|
|
|
|
|
|
$App::ape::plan::VERSION = '0.001'; |
6
|
3
|
|
|
3
|
|
116998
|
use strict; |
|
3
|
|
|
|
|
13
|
|
|
3
|
|
|
|
|
74
|
|
7
|
3
|
|
|
3
|
|
12
|
use warnings; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
81
|
|
8
|
|
|
|
|
|
|
|
9
|
3
|
|
|
3
|
|
535
|
use Getopt::Long qw{GetOptionsFromArray}; |
|
3
|
|
|
|
|
8293
|
|
|
3
|
|
|
|
|
18
|
|
10
|
3
|
|
|
3
|
|
746
|
use App::Prove::Elasticsearch::Utils; |
|
3
|
|
|
|
|
28
|
|
|
3
|
|
|
|
|
72
|
|
11
|
3
|
|
|
3
|
|
1170
|
use App::Prove::State; |
|
3
|
|
|
|
|
29824
|
|
|
3
|
|
|
|
|
86
|
|
12
|
3
|
|
|
3
|
|
427
|
use Pod::Usage; |
|
3
|
|
|
|
|
35654
|
|
|
3
|
|
|
|
|
318
|
|
13
|
3
|
|
|
3
|
|
1975
|
use IO::Prompter [ -yesno, -single, -stdio, -style => 'bold' ]; |
|
3
|
|
|
|
|
74296
|
|
|
3
|
|
|
|
|
49
|
|
14
|
3
|
|
|
3
|
|
216
|
use List::Util qw{shuffle}; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
170
|
|
15
|
3
|
|
|
3
|
|
15
|
use File::Basename qw{basename}; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
132
|
|
16
|
3
|
|
|
3
|
|
14
|
use POSIX qw{strftime}; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
22
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub new { |
19
|
4
|
|
|
4
|
1
|
2382
|
my ($class, @args) = @_; |
20
|
|
|
|
|
|
|
|
21
|
4
|
|
|
|
|
7
|
my (%options, @conf, $help); |
22
|
|
|
|
|
|
|
GetOptionsFromArray( |
23
|
|
|
|
|
|
|
\@args, |
24
|
|
|
|
|
|
|
'platform=s@' => \$options{platforms}, |
25
|
|
|
|
|
|
|
'version=s' => \$options{version}, |
26
|
|
|
|
|
|
|
'show' => \$options{show}, |
27
|
|
|
|
|
|
|
'prompt' => \$options{prompt}, |
28
|
|
|
|
|
|
|
'pairwise' => \$options{pairwise}, |
29
|
|
|
|
|
|
|
'all-platforms' => \$options{allplatforms}, |
30
|
|
|
|
|
|
|
'recurse' => \$options{recurse}, |
31
|
|
|
|
|
|
|
'extension=s@' => \$options{exts}, |
32
|
|
|
|
|
|
|
'name' => \$options{name}, |
33
|
|
|
|
|
|
|
'requeue' => \$options{requeue}, |
34
|
|
|
|
|
|
|
'replay' => \$options{replay}, |
35
|
4
|
|
|
|
|
37
|
'help' => \$help, |
36
|
|
|
|
|
|
|
); |
37
|
4
|
|
100
|
|
|
2694
|
$options{platforms} //= []; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
#Deliberately exiting here, as I "unit" test this as the binary |
40
|
4
|
50
|
|
|
|
9
|
pod2usage(0) if $help; |
41
|
|
|
|
|
|
|
|
42
|
4
|
100
|
|
|
|
8
|
if (!$options{version}) { |
43
|
1
|
|
|
|
|
7
|
pod2usage( |
44
|
|
|
|
|
|
|
-exitval => "NOEXIT", |
45
|
|
|
|
|
|
|
-msg => "Insufficient arguments. You must pass --version.", |
46
|
|
|
|
|
|
|
); |
47
|
1
|
|
|
|
|
4732
|
return 2; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
3
|
50
|
66
|
|
|
10
|
if ($options{prompt} && $options{show}) { |
51
|
1
|
|
|
|
|
4
|
pod2usage( |
52
|
|
|
|
|
|
|
-exitval => "NOEXIT", |
53
|
|
|
|
|
|
|
-msg => |
54
|
|
|
|
|
|
|
"--prompt and --show are mutually exclusive options. You must pass one or the other.", |
55
|
|
|
|
|
|
|
); |
56
|
1
|
|
|
|
|
4221
|
return 3; |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
#Store platform groups in the configuration to differentiate further plans |
60
|
2
|
|
|
|
|
5
|
my $conf = App::Prove::Elasticsearch::Utils::process_configuration(@conf); |
61
|
|
|
|
|
|
|
|
62
|
2
|
100
|
|
|
|
12
|
if ( |
63
|
|
|
|
|
|
|
scalar( |
64
|
|
|
|
|
|
|
grep { |
65
|
2
|
|
|
|
|
3
|
my $subj = $_; |
66
|
2
|
|
|
|
|
4
|
grep { $subj eq $_ } qw{server.host server.port} |
|
4
|
|
|
|
|
8
|
|
67
|
|
|
|
|
|
|
} keys(%$conf) |
68
|
|
|
|
|
|
|
) != 2 |
69
|
|
|
|
|
|
|
) { |
70
|
1
|
|
|
|
|
5
|
pod2usage( |
71
|
|
|
|
|
|
|
-exitval => "NOEXIT", |
72
|
|
|
|
|
|
|
-msg => |
73
|
|
|
|
|
|
|
"Insufficient information provided to associate defect with test results to elasticsearch", |
74
|
|
|
|
|
|
|
); |
75
|
1
|
|
|
|
|
4156
|
return 4; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
1
|
|
|
|
|
2
|
my $self = {}; |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
#default platforms to whatever platformer can figure out |
81
|
1
|
0
|
33
|
|
|
1
|
if (!scalar(@{$options{platforms}}) && !$options{allplatforms}) { |
|
1
|
|
|
|
|
6
|
|
82
|
0
|
|
|
|
|
0
|
my $platformer = |
83
|
|
|
|
|
|
|
App::Prove::Elasticsearch::Utils::require_platformer($conf); |
84
|
0
|
|
|
|
|
0
|
$options{platforms} = &{\&{$platformer . "::get_platforms"}}(); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
1
|
|
|
|
|
3
|
$self->{planner} = App::Prove::Elasticsearch::Utils::require_planner($conf); |
88
|
1
|
|
|
|
|
5
|
&{\&{$self->{planner} . "::check_index"}}($conf); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
7
|
|
89
|
|
|
|
|
|
|
|
90
|
1
|
|
|
|
|
3
|
my $queue = App::Prove::Elasticsearch::Utils::require_queue($conf); |
91
|
1
|
|
|
|
|
3
|
$self->{queue} = &{\&{$queue . "::new"}}($queue, \@conf); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
5
|
|
92
|
1
|
|
|
|
|
14
|
$self->{queue}->{requeue} = $options{requeue}; |
93
|
|
|
|
|
|
|
|
94
|
1
|
|
|
|
|
4
|
$self->{searcher} = $self->{queue}->_get_searcher(); |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
#Use Prove's arg parser to grab tests & globs correctly |
97
|
1
|
|
|
|
|
6
|
my $proveState = App::Prove::State->new(); |
98
|
1
|
50
|
|
|
|
7
|
$proveState->extensions($options{exts}) if $options{exts}; |
99
|
1
|
|
|
|
|
4
|
my @tests_filtered = $proveState->get_tests($options{'recurse'}, @args); |
100
|
1
|
|
|
|
|
6
|
@args = map { basename $_ } grep { -f $_ } @tests_filtered; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
101
|
1
|
|
|
|
|
2
|
$self->{cases} = \@args; |
102
|
|
|
|
|
|
|
|
103
|
1
|
|
|
|
|
2
|
$self->{conf} = $conf; |
104
|
1
|
|
|
|
|
2
|
$self->{options} = \%options; |
105
|
|
|
|
|
|
|
|
106
|
1
|
|
|
|
|
13
|
return bless($self, $class); |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub run { |
110
|
5
|
|
|
5
|
1
|
1787
|
my $self = shift; |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
my @plans = _build_plans( |
113
|
|
|
|
|
|
|
$self->{planner}, $self->{conf}, $self->{cases}, |
114
|
5
|
|
|
|
|
11
|
%{$self->{options}} |
|
5
|
|
|
|
|
18
|
|
115
|
|
|
|
|
|
|
); |
116
|
|
|
|
|
|
|
|
117
|
5
|
|
|
|
|
17
|
my $global_result = 0; |
118
|
5
|
|
|
|
|
6
|
my $queue_result = 0; |
119
|
5
|
|
|
|
|
17
|
foreach my $plan (@plans) { |
120
|
|
|
|
|
|
|
|
121
|
5
|
100
|
|
|
|
11
|
if ($self->{options}{show}) { |
122
|
1
|
50
|
|
|
|
4
|
$plan->{replay} = $self->{cases} if $self->{options}{replay}; |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
#Get the state of the plan |
125
|
1
|
|
|
|
|
2
|
$plan->{state} = []; |
126
|
1
|
|
|
|
|
3
|
@{$plan->{state}} = &{\&{$self->{planner} . "::get_plan_status"}} |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
127
|
1
|
|
|
|
|
2
|
($plan, $self->{searcher}); |
128
|
|
|
|
|
|
|
|
129
|
1
|
|
|
|
|
6
|
_print_plan($plan, 1); |
130
|
1
|
|
|
|
|
3
|
next; |
131
|
|
|
|
|
|
|
} |
132
|
4
|
100
|
|
|
|
10
|
if ($self->{options}{prompt}) { |
133
|
3
|
|
|
|
|
6
|
_print_plan($plan); |
134
|
3
|
100
|
|
|
|
10
|
if (!$plan->{noop}) { |
135
|
2
|
50
|
|
|
|
3
|
IO::Prompter::prompt("Do you want to enact the above changes?") |
136
|
|
|
|
|
|
|
or next; |
137
|
|
|
|
|
|
|
} else { |
138
|
|
|
|
|
|
|
( |
139
|
|
|
|
|
|
|
IO::Prompter::prompt("Do you want to re-queue the plan?") |
140
|
|
|
|
|
|
|
or next |
141
|
1
|
50
|
50
|
|
|
4
|
) unless $self->{options}{requeue}; |
142
|
1
|
|
|
|
|
8
|
$self->{queue}->{requeue} = 1; |
143
|
1
|
|
|
|
|
4
|
$queue_result += $self->{queue}->queue_jobs($plan); |
144
|
1
|
|
|
|
|
3
|
next; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
#Ensure bogus data doesn't get into ES |
149
|
3
|
|
|
|
|
9
|
delete $plan->{replay}; |
150
|
3
|
|
|
|
|
4
|
delete $plan->{requeue}; |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
$global_result += |
153
|
3
|
|
|
|
|
5
|
&{\&{$self->{planner} . "::add_plan_to_index"}}($plan); |
|
3
|
|
|
|
|
3
|
|
|
3
|
|
|
|
|
11
|
|
154
|
|
|
|
|
|
|
$queue_result += $self->{queue}->queue_jobs($plan) |
155
|
3
|
50
|
66
|
|
|
21
|
if !$plan->{noop} || $self->{options}{requeue}; |
156
|
|
|
|
|
|
|
} |
157
|
5
|
100
|
|
|
|
43
|
print "$global_result plans failed to be created, examine above output\n" |
158
|
|
|
|
|
|
|
if $global_result; |
159
|
5
|
100
|
|
|
|
16
|
print "$queue_result plans failed to be queued, examine above output\n" |
160
|
|
|
|
|
|
|
if $queue_result; |
161
|
5
|
100
|
|
|
|
28
|
return $global_result ? 2 : 0; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
sub _build_plans { |
165
|
0
|
|
|
0
|
|
0
|
my ($planner, $conf, $tests, %options) = @_; |
166
|
|
|
|
|
|
|
|
167
|
0
|
|
|
|
|
0
|
my @plans; |
168
|
0
|
|
|
|
|
0
|
my @pgroups = grep { $_ =~ m/PlatformGroups/ } keys(%$conf); |
|
0
|
|
|
|
|
0
|
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
#filter groups by what we actually passed, if we have any |
171
|
0
|
0
|
0
|
|
|
0
|
if (scalar(@{$options{platforms}}) && !$options{allplatforms}) { |
|
0
|
|
|
|
|
0
|
|
172
|
|
|
|
|
|
|
|
173
|
0
|
|
|
|
|
0
|
foreach my $grp (@pgroups) { |
174
|
0
|
|
|
|
|
0
|
@{$conf->{$grp}} = grep { |
175
|
0
|
|
|
|
|
0
|
my $grp = $_; |
176
|
0
|
|
|
|
|
0
|
grep { $grp eq $_ } @{$options{platforms}}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
177
|
0
|
|
|
|
|
0
|
} @{$conf->{$grp}}; |
|
0
|
|
|
|
|
0
|
|
178
|
0
|
0
|
|
|
|
0
|
delete $conf->{$grp} unless scalar(@{$conf->{$grp}}); |
|
0
|
|
|
|
|
0
|
|
179
|
|
|
|
|
|
|
} |
180
|
0
|
|
|
|
|
0
|
@pgroups = grep { $_ =~ m/PlatformGroups/ } keys(%$conf); |
|
0
|
|
|
|
|
0
|
|
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
0
|
0
|
|
|
|
0
|
if (scalar(@pgroups)) { |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
#break out the groups depending if we are pairwise or not |
186
|
0
|
0
|
|
|
|
0
|
if ($options{pairwise}) { |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
#Randomize execution order |
189
|
0
|
|
|
|
|
0
|
@$tests = shuffle(@$tests); |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# The idea here is to have at least one pigeon in each hole. |
192
|
|
|
|
|
|
|
# This is accomplished by finding the longest list of groups, and then iterating over everything we have modulo their size. |
193
|
0
|
|
|
|
|
0
|
my $longest; |
194
|
0
|
|
|
|
|
0
|
foreach my $pgroup (@pgroups) { |
195
|
0
|
|
0
|
|
|
0
|
$longest ||= $pgroup; |
196
|
|
|
|
|
|
|
$longest = $pgroup |
197
|
0
|
0
|
|
|
|
0
|
if scalar(@{$conf->{$pgroup}}) > scalar(@{$conf->{$longest}}); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
0
|
|
|
|
|
0
|
my @last_tests_apportioned; |
201
|
0
|
|
|
|
|
0
|
for (my $i = 0; $i < scalar(@{$conf->{$longest}}); $i++) { |
|
0
|
|
|
|
|
0
|
|
202
|
0
|
|
|
|
|
0
|
my %cloned = %options; |
203
|
0
|
|
|
|
|
0
|
my @newplats; |
204
|
0
|
|
|
|
|
0
|
foreach my $pgroup (@pgroups) { |
205
|
0
|
|
|
|
|
0
|
my $idx = $i % scalar(@{$conf->{$pgroup}}); |
|
0
|
|
|
|
|
0
|
|
206
|
0
|
|
|
|
|
0
|
push(@newplats, $conf->{$pgroup}->[$idx]); |
207
|
|
|
|
|
|
|
} |
208
|
0
|
|
|
|
|
0
|
$cloned{platforms} = \@newplats; |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
#Figure out how many tests to dole out to the run |
211
|
0
|
|
|
|
|
0
|
my @tests_apportioned; |
212
|
|
|
|
|
|
|
my $tests_picked = |
213
|
0
|
|
|
|
|
0
|
int(scalar(@$tests) / scalar(@{$conf->{$longest}})); |
|
0
|
|
|
|
|
0
|
|
214
|
0
|
|
|
|
|
0
|
for (0 .. $tests_picked) { |
215
|
0
|
|
|
|
|
0
|
my $picked = shift @$tests; |
216
|
0
|
0
|
|
|
|
0
|
push(@tests_apportioned, $picked) if $picked; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
#Handle the corner case where we are passed less tests than we have platforms |
220
|
|
|
|
|
|
|
@tests_apportioned = @last_tests_apportioned |
221
|
0
|
0
|
|
|
|
0
|
if !scalar(@tests_apportioned); |
222
|
0
|
|
|
|
|
0
|
@last_tests_apportioned = @tests_apportioned; |
223
|
|
|
|
|
|
|
|
224
|
0
|
|
|
|
|
0
|
push( |
225
|
|
|
|
|
|
|
@plans, |
226
|
|
|
|
|
|
|
_build_plan($planner, \@tests_apportioned, %cloned) |
227
|
|
|
|
|
|
|
); |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
} else { |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
#construct iterator |
232
|
0
|
|
|
|
|
0
|
my @pigeonholes = map { $conf->{$_} } @pgroups; |
|
0
|
|
|
|
|
0
|
|
233
|
|
|
|
|
|
|
|
234
|
0
|
|
|
|
|
0
|
my @iterator = @{$pigeonholes[0]}; |
|
0
|
|
|
|
|
0
|
|
235
|
0
|
|
|
|
|
0
|
while (scalar(@iterator)) { |
236
|
0
|
|
|
|
|
0
|
my $subj = shift @iterator; |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
#Handle initial elements |
239
|
0
|
0
|
|
|
|
0
|
$subj = [$subj] if ref $subj ne 'ARRAY'; |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
#Break out of the loop if we have no more possibilities to exploit |
242
|
0
|
0
|
|
|
|
0
|
if (scalar(@$subj) == scalar(@pigeonholes)) { |
243
|
0
|
|
|
|
|
0
|
my %cloned = %options; |
244
|
0
|
|
|
|
|
0
|
$cloned{platforms} = $subj; |
245
|
0
|
|
|
|
|
0
|
push(@plans, _build_plan($planner, $tests, %cloned)); |
246
|
0
|
|
|
|
|
0
|
next; |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
#Keep pushing partials on to the end of the iterator, until we run out of categories to add |
250
|
0
|
|
|
|
|
0
|
foreach my $element (@{$pigeonholes[ scalar(@$subj) ]}) { |
|
0
|
|
|
|
|
0
|
|
251
|
0
|
|
|
|
|
0
|
my @partial = @$subj; |
252
|
0
|
|
|
|
|
0
|
push(@partial, $element); |
253
|
0
|
|
|
|
|
0
|
push(@iterator, \@partial); |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
} else { |
259
|
0
|
|
|
|
|
0
|
push(@plans, _build_plan($planner, $tests, %options)); |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
#TODO inject creator & created time into plans |
263
|
|
|
|
|
|
|
@plans = |
264
|
0
|
|
|
|
|
0
|
map { $_->{created} = strftime("%Y-%m-%d %H:%M:%S", localtime()); $_ } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
265
|
|
|
|
|
|
|
@plans; |
266
|
|
|
|
|
|
|
|
267
|
0
|
|
|
|
|
0
|
return @plans; |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
sub _build_plan { |
271
|
2
|
|
|
2
|
|
2184
|
my ($planner, $tests, %options) = @_; |
272
|
2
|
|
|
|
|
5
|
$options{tests} = $tests; |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
#First, see if we already have a plan like this. |
275
|
2
|
|
|
|
|
3
|
my $existing = &{\&{$planner . "::get_plan"}}(%options); |
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
10
|
|
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
#If not, make the plan. Otherwise, construct the update statements needed to 'make it so'. |
278
|
2
|
100
|
|
|
|
11
|
if (!$existing) { |
279
|
1
|
|
|
|
|
2
|
$existing = &{\&{$planner . "::make_plan"}}(%options); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
280
|
|
|
|
|
|
|
} else { |
281
|
1
|
|
|
|
|
2
|
$existing = &{\&{$planner . "::make_plan_update"}}($existing, %options); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
2
|
|
|
|
|
12
|
return $existing; |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
sub _print_plan { |
288
|
7
|
|
|
7
|
|
14266
|
my ($plan, $force) = @_; |
289
|
7
|
100
|
100
|
|
|
30
|
if (!$plan->{noop} || $force) { |
290
|
6
|
50
|
|
|
|
118
|
print "Name: $plan->{name}\n" if $plan->{name}; |
291
|
6
|
|
|
|
|
54
|
print "SUT version: $plan->{version}\n"; |
292
|
6
|
|
|
|
|
11
|
print "Platforms: " . join(', ', @{$plan->{platforms}}) . "\n"; |
|
6
|
|
|
|
|
46
|
|
293
|
|
|
|
|
|
|
print "Pairwise? " |
294
|
6
|
50
|
|
|
|
52
|
. ($plan->{pairwise} ne 'false' ? 'yes' : 'no') . "\n"; |
295
|
6
|
|
|
|
|
43
|
print "Created at $plan->{created}\n"; |
296
|
6
|
|
|
|
|
38
|
print "=========================\n"; |
297
|
6
|
100
|
|
|
|
19
|
if ($plan->{state}) { |
298
|
4
|
|
|
|
|
5
|
foreach my $t (@{$plan->{state}}) { |
|
4
|
|
|
|
|
10
|
|
299
|
8
|
50
|
66
|
|
|
23
|
if ($plan->{replay} && $t->{body}) { |
300
|
|
|
|
|
|
|
next |
301
|
2
|
|
|
|
|
6
|
if (scalar(@{$plan->{replay}}) |
302
|
2
|
50
|
33
|
|
|
3
|
&& !grep { $_ eq $t->{name} } @{$plan->{replay}}); |
|
4
|
|
|
|
|
11
|
|
|
2
|
|
|
|
|
4
|
|
303
|
2
|
|
|
|
|
34
|
print "\n$t->{name}..\n"; |
304
|
|
|
|
|
|
|
print "Test Version: $t->{test_version}\n" |
305
|
2
|
50
|
|
|
|
19
|
if $t->{test_version}; |
306
|
2
|
|
|
|
|
13
|
print "=========================\n"; |
307
|
2
|
|
|
|
|
15
|
print "$t->{body}"; |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
8
|
|
|
|
|
13
|
my $pln = ''; |
311
|
8
|
100
|
66
|
|
|
26
|
if ( ($t->{status} ne 'UNTESTED') |
312
|
|
|
|
|
|
|
&& (ref($t->{steps}) eq 'ARRAY')) { |
313
|
4
|
|
|
|
|
6
|
my $executed = scalar(@{$t->{steps}}); |
|
4
|
|
|
|
|
6
|
|
314
|
4
|
|
|
|
|
7
|
my $planned = $t->{steps_planned}; |
315
|
4
|
|
|
|
|
7
|
$pln = "$executed/$planned "; |
316
|
|
|
|
|
|
|
} |
317
|
8
|
|
|
|
|
92
|
printf "%-60s %-10s %s\n", $t->{name}, $pln, $t->{status}; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
} else { |
320
|
2
|
|
|
|
|
3
|
foreach my $t (@{$plan->{tests}}) { |
|
2
|
|
|
|
|
5
|
|
321
|
4
|
|
|
|
|
28
|
print "$t\n"; |
322
|
|
|
|
|
|
|
} |
323
|
2
|
50
|
|
|
|
10
|
if ($plan->{update}) { |
324
|
2
|
50
|
|
|
|
6
|
if (ref $plan->{update}->{subtraction}->{tests} eq 'ARRAY') { |
325
|
2
|
|
|
|
|
14
|
print "\nRemove the following from the plan:\n"; |
326
|
2
|
|
|
|
|
12
|
print "=========================\n"; |
327
|
2
|
|
|
|
|
5
|
foreach my $t (@{$plan->{update}->{subtraction}->{tests}}) { |
|
2
|
|
|
|
|
5
|
|
328
|
2
|
|
|
|
|
13
|
print "$t\n"; |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
} |
331
|
2
|
50
|
|
|
|
9
|
if (ref $plan->{update}->{addition}->{tests} eq 'ARRAY') { |
332
|
2
|
|
|
|
|
13
|
print "\nAdd the following to the plan:\n"; |
333
|
2
|
|
|
|
|
13
|
print "=========================\n"; |
334
|
2
|
|
|
|
|
4
|
foreach my $t (@{$plan->{update}->{addition}->{tests}}) { |
|
2
|
|
|
|
|
5
|
|
335
|
2
|
|
|
|
|
24
|
print "$t\n"; |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
} else { |
341
|
1
|
|
|
|
|
36
|
print "Plan already exists, and no updates will be made.\n"; |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
1; |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
__END__ |