File Coverage

blib/lib/Tapper/Reports/Web/Controller/Tapper/Testplan.pm
Criterion Covered Total %
statement 42 132 31.8
branch 0 32 0.0
condition 0 23 0.0
subroutine 14 23 60.8
pod 2 8 25.0
total 58 218 26.6


line stmt bran cond sub pod time code
1             package Tapper::Reports::Web::Controller::Tapper::Testplan;
2             our $AUTHORITY = 'cpan:TAPPER';
3             $Tapper::Reports::Web::Controller::Tapper::Testplan::VERSION = '5.0.15';
4 11     11   6231 use parent 'Tapper::Reports::Web::Controller::Base';
  11         29  
  11         73  
5              
6 11     11   825 use common::sense;
  11         28  
  11         93  
7             ## no critic (RequireUseStrict)
8              
9 11     11   558 use DateTime::Format::Natural;
  11         23  
  11         493  
10 11     11   5021 use Tapper::Reports::Web::Util::Filter::Testplan;
  11         32  
  11         377  
11 11     11   79 use Tapper::Model 'model';
  11         31  
  11         480  
12 11     11   6156 use Tapper::Cmd::Testplan;
  11         1153008  
  11         965  
13              
14             sub auto :Private
15             {
16 0     0   0 my ( $self, $c ) = @_;
17              
18 0         0 $c->forward('/tapper/testplan/prepare_navi');
19 11     11   113 }
  11         27  
  11         106  
20              
21              
22 11     11 0 139150 sub base : Chained PathPrefix CaptureArgs(0) { }
  11     0   30  
  11         54  
23              
24             sub id : Chained('base') PathPart('') CaptureArgs(1)
25             {
26 0     0 0 0 my ( $self, $c, $id ) = @_;
27 0         0 $c->stash(testplan => $c->model('TestrunDB')->resultset('TestplanInstance')->find($id));
28 0 0       0 if (not $c->stash->{testplan}) {
29 0         0 $c->response->body(qq(No testplan instance with id "$id" found in the database!));
30 0         0 return;
31             }
32              
33 11     11   12107 }
  11         37  
  11         56  
34              
35             sub rerun : Chained('id') PathPart('rerun') Args(0)
36             {
37 0     0 0 0 my ( $self, $c ) = @_;
38              
39 0         0 my $cmd = Tapper::Cmd::Testplan->new();
40 0         0 my $retval = $cmd->rerun($c->stash->{testplan}->id)->{testplan_id};
41 0 0       0 if (not $retval) {
42 0         0 $c->response->body(qq(Can not rerun testplan));
43 0         0 return;
44             }
45 0         0 $c->stash(testplan => $c->model('TestrunDB')->resultset('TestplanInstance')->find($retval));
46 11     11   12129 }
  11         29  
  11         53  
47              
48              
49             sub delete : Chained('id') PathPart('delete')
50             {
51 0     0 0 0 my ( $self, $c, $force) = @_;
52              
53 0         0 my $cmd = Tapper::Cmd::Testplan->new();
54 0 0       0 if ($force) {
55 0         0 $c->stash->{force} = 1;
56 0         0 my $retval = $cmd->del($c->stash->{testplan}->id);
57 0 0       0 if ($retval) {
58 0         0 $c->response->body(qq(Can not delete testplan: $retval));
59 0         0 return;
60             }
61             }
62 11     11   11976 }
  11         26  
  11         56  
63              
64             sub cancel : Chained('id') PathPart('cancel')
65             {
66 0     0 0 0 my ($self, $c) = @_;
67              
68 0         0 my $cmd = Tapper::Cmd::Testplan->new;
69 0         0 my $testplan_id = $c->stash->{testplan}->id;
70 0         0 my $retval = $cmd->cancel($testplan_id, "Cancelled testplan in WebGUI");
71 0 0       0 if ($retval) {
72 0         0 $c->response->body(qq(Can not cancel testplan: $retval));
73 0         0 return;
74             }
75 0         0 $c->flash->{msg} = "<strong>Cancelling this testplan is in progress...</strong><br/><br/>";
76 0         0 $c->res->redirect("/tapper/testplan/id/$testplan_id");
77 11     11   11945 }
  11         30  
  11         63  
78              
79              
80              
81             sub index :Path :Args()
82             {
83 0     0 1 0 my ( $self, $c, @args ) = @_;
84              
85 0         0 my $filter = Tapper::Reports::Web::Util::Filter::Testplan->new(context => $c);
86 0         0 my $filter_condition = $filter->parse_filters(\@args, ['days', 'date', 'path', 'name']);
87 0         0 $c->stash->{title} = "Testplan list";
88 0         0 $c->stash->{testplan_id} = undef;
89              
90 0 0       0 if ($filter_condition->{error}) {
91 0         0 $c->flash->{error_msg} = join("; ", @{$filter_condition->{error}});
  0         0  
92 0         0 $c->res->redirect("/tapper/testplan/days/2");
93             }
94              
95 0   0     0 my $days = $filter_condition->{days} || 6;
96 0         0 $c->stash->{days} = $days;
97              
98 0         0 $c->stash->{testplan_days} = [];
99 0         0 my $today = DateTime::Format::Natural->new->parse_datetime("today at midnight");
100 0         0 my $dtf = $c->model("TestrunDB")->storage->datetime_parser;
101              
102             # testplans after "today at midnight"
103             # handling them special makes later code more readable
104             {
105 0         0 my $todays_instances = model('TestrunDB')->resultset('TestplanInstance')->search
106             (
107             $filter_condition->{early},
108 0         0 { order_by => 'me.id desc' }
109             );
110 0         0 $todays_instances = $todays_instances->search({created_at => { '>' => $dtf->format_datetime($today) }});
111              
112 0         0 my @details = $self->get_testrun_details($todays_instances);
113 0 0       0 if (@details) {
114 0         0 push @{$c->stash->{testplan_days}}, { date => $today,
  0         0  
115             testplan_instances => \@details,
116             };
117             }
118             }
119              
120 0         0 for my $date (1..($days-1)) {
121 0         0 my $yesterday = $today->clone->subtract( days => 1 );
122              
123             my $todays_instances = model('TestrunDB')->resultset('TestplanInstance')->search
124             ($filter_condition->{early},
125 0         0 { order_by => 'me.id desc' }
126             );
127 0         0 $todays_instances = $todays_instances->search({'-and' => [{created_at => { '>' => $dtf->format_datetime($yesterday) }},
128             {created_at => {'<=' => $dtf->format_datetime($today) }},
129             ]});
130 0         0 my @details = $self->get_testrun_details($todays_instances);
131 0 0       0 if (@details) {
132 0         0 push @{$c->stash->{testplan_days}}, { date => $yesterday,
  0         0  
133             testplan_instances => \@details,
134             };
135             }
136 0         0 $today = $yesterday;
137             }
138 0         0 return;
139 11     11   16008 }
  11         28  
  11         56  
140              
141              
142              
143             sub get_testrun_details
144             {
145 0     0 1   my ($self, $todays_instances) = @_;
146 0 0 0       return unless $todays_instances and $todays_instances->can('next');
147              
148 0           my @testplan_instances;
149              
150 0           while ( my $instance = $todays_instances->next) {
151              
152 0           my $details = {};
153 0           foreach my $col ($instance->columns) {
154 0           $details->{$col} = $instance->$col;
155             }
156              
157 0           my $testruns = $instance->testruns;
158             TESTRUN:
159 0           while (my $testrun = $testruns->next)
160             {
161 0           my $job = $testrun->testrun_scheduling;
162 0 0 0       $details->{count_unfinished}++ if $job and $job->status ne 'finished';
163 0 0 0       $details->{count_running}++ if $job and $job->status eq 'running';
164 0 0 0       $details->{count_schedule}++ if $job and $job->status eq 'schedule';
165 0 0 0       $details->{count_prepare}++ if $job and $job->status eq 'prepare';
166              
167 0 0         next TESTRUN if $job->status ne 'finished';
168 0           my $stats = model('TestrunDB')->resultset('ReportgroupTestrunStats')->search({testrun_id => $testrun->id}, {rows => 1})->first;
169              
170 0 0 0       $details->{count_fail}++ if $stats and $stats->success_ratio < 100;
171 0 0 0       $details->{count_pass}++ if $stats and $stats->success_ratio == 100;
172             }
173 0           push @testplan_instances, $details;
174             }
175 0           return @testplan_instances;
176             }
177              
178             sub prepare_navi : Private
179             {
180 0     0 0   my ( $self, $c ) = @_;
181 0           $c->stash->{navi} = [];
182              
183 0           my %args = @{$c->req->arguments};
  0            
184              
185             $c->stash->{navi} = [
186             {
187 0           title => "Matrix Overview",
188             href => "/tapper/testplan/taskjuggler/",
189             },
190             {
191             title => "Testplan by date",
192             href => "",
193             subnavi => [
194             {
195             title => "today",
196             href => "/tapper/testplan/".$self->prepare_filter_path($c, 1),
197             },
198             {
199             title => "2 days",
200             href => "/tapper/testplan/".$self->prepare_filter_path($c, 2),
201             },
202             {
203             title => "1 week",
204             href => "/tapper/testplan/".$self->prepare_filter_path($c, 7),
205             },
206             {
207             title => "2 weeks",
208             href => "/tapper/testplan/".$self->prepare_filter_path($c, 14),
209             },
210             {
211             title => "3 weeks",
212             href => "/tapper/testplan/".$self->prepare_filter_path($c, 21),
213             },
214             {
215             title => "1 month",
216             href => "/tapper/testplan/".$self->prepare_filter_path($c, 31),
217             },
218             {
219             title => "2 months",
220             href => "/tapper/testplan/".$self->prepare_filter_path($c, 62),
221             },
222             {
223             title => "4 months",
224             href => "/tapper/testplan/".$self->prepare_filter_path($c, 124),
225             },
226             {
227             title => "6 months",
228             href => "/tapper/testplan/".$self->prepare_filter_path($c, 182),
229             },
230             {
231             title => "12 months",
232             href => "/tapper/testplan/".$self->prepare_filter_path($c, 365),
233             },
234              
235             ],
236             },
237             ];
238              
239 0           push @{$c->stash->{navi}}, {title => 'Active Filters',
240             subnavi => [
241             map {
242 0           {
243 0           title => "$_: ".$args{$_},
244             href => "/tapper/reports/".$self->reduced_filter_path(\%args, $_),
245             image => "/tapper/static/images/minus.png",
246             }
247             } keys %args ]};
248 11     11   17389 }
  11         32  
  11         54  
249              
250              
251              
252             1;
253              
254             __END__
255              
256             =pod
257              
258             =encoding UTF-8
259              
260             =head1 NAME
261              
262             Tapper::Reports::Web::Controller::Tapper::Testplan
263              
264             =head1 DESCRIPTION
265              
266             Catalyst Controller.
267              
268             =head2 index
269              
270             =head2 get_testrun_details
271              
272             Get the details of the testruns belonging to the testplan instance given
273             as argument.
274              
275             @param DBIC ResultSet TestplanInstance - testplan instances of current day
276              
277             @returnlist success - array ref of lists of details of testruns in given instances
278             @returnlist error - empty list
279              
280             =head1 NAME
281              
282             Tapper::Reports::Web::Controller::Tapper::Testplan - Catalyst Controller for test plans
283              
284             =head1 METHODS
285              
286             =head2 index
287              
288             =head1 AUTHOR
289              
290             AMD OSRC Tapper Team, C<< <tapper at amd64.org> >>
291              
292             =head1 LICENSE
293              
294             This program is released under the following license: freebsd
295              
296             =head1 AUTHORS
297              
298             =over 4
299              
300             =item *
301              
302             AMD OSRC Tapper Team <tapper@amd64.org>
303              
304             =item *
305              
306             Tapper Team <tapper-ops@amazon.com>
307              
308             =back
309              
310             =head1 COPYRIGHT AND LICENSE
311              
312             This software is Copyright (c) 2020 by Advanced Micro Devices, Inc..
313              
314             This is free software, licensed under:
315              
316             The (two-clause) FreeBSD License
317              
318             =cut