| 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.13'; | 
| 4 | 10 |  |  | 10 |  | 5455 | use parent 'Tapper::Reports::Web::Controller::Base'; | 
|  | 10 |  |  |  |  | 18 |  | 
|  | 10 |  |  |  |  | 72 |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 10 |  |  | 10 |  | 1603 | use common::sense; | 
|  | 10 |  |  |  |  | 19 |  | 
|  | 10 |  |  |  |  | 76 |  | 
| 7 |  |  |  |  |  |  | ## no critic (RequireUseStrict) | 
| 8 |  |  |  |  |  |  |  | 
| 9 | 10 |  |  | 10 |  | 453 | use DateTime::Format::Natural; | 
|  | 10 |  |  |  |  | 13 |  | 
|  | 10 |  |  |  |  | 408 |  | 
| 10 | 10 |  |  | 10 |  | 3945 | use Tapper::Reports::Web::Util::Filter::Testplan; | 
|  | 10 |  |  |  |  | 22 |  | 
|  | 10 |  |  |  |  | 330 |  | 
| 11 | 10 |  |  | 10 |  | 51 | use Tapper::Model 'model'; | 
|  | 10 |  |  |  |  | 13 |  | 
|  | 10 |  |  |  |  | 381 |  | 
| 12 | 10 |  |  | 10 |  | 4986 | use Tapper::Cmd::Testplan; | 
|  | 10 |  |  |  |  | 1404457 |  | 
|  | 10 |  |  |  |  | 846 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | sub auto :Private | 
| 15 |  |  |  |  |  |  | { | 
| 16 | 0 |  |  | 0 |  | 0 | my ( $self, $c ) = @_; | 
| 17 |  |  |  |  |  |  |  | 
| 18 | 0 |  |  |  |  | 0 | $c->forward('/tapper/testplan/prepare_navi'); | 
| 19 | 10 |  |  | 10 |  | 73 | } | 
|  | 10 |  |  |  |  | 15 |  | 
|  | 10 |  |  |  |  | 84 |  | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  |  | 
| 22 | 10 |  |  | 10 | 0 | 75418 | sub base : Chained PathPrefix CaptureArgs(0) { } | 
|  | 10 |  |  | 0 |  | 18 |  | 
|  | 10 |  |  |  |  | 41 |  | 
| 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 | 10 |  |  | 10 |  | 7915 | } | 
|  | 10 |  |  |  |  | 14 |  | 
|  | 10 |  |  |  |  | 38 |  | 
| 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); | 
| 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 | 10 |  |  | 10 |  | 7756 | } | 
|  | 10 |  |  |  |  | 15 |  | 
|  | 10 |  |  |  |  | 42 |  | 
| 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 |  |  |  |  |  |  |  | 
| 63 | 10 |  |  | 10 |  | 7721 | } | 
|  | 10 |  |  |  |  | 18 |  | 
|  | 10 |  |  |  |  | 37 |  | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | sub index :Path :Args() | 
| 68 |  |  |  |  |  |  | { | 
| 69 | 0 |  |  | 0 | 1 | 0 | my ( $self, $c, @args ) = @_; | 
| 70 |  |  |  |  |  |  |  | 
| 71 | 0 |  |  |  |  | 0 | my $filter = Tapper::Reports::Web::Util::Filter::Testplan->new(context => $c); | 
| 72 | 0 |  |  |  |  | 0 | my $filter_condition = $filter->parse_filters(\@args, ['days', 'date', 'path', 'name']); | 
| 73 | 0 |  |  |  |  | 0 | $c->stash->{title} = "Testplan list"; | 
| 74 | 0 |  |  |  |  | 0 | $c->stash->{testplan_id} = undef; | 
| 75 |  |  |  |  |  |  |  | 
| 76 | 0 | 0 |  |  |  | 0 | if ($filter_condition->{error}) { | 
| 77 | 0 |  |  |  |  | 0 | $c->flash->{error_msg} = join("; ", @{$filter_condition->{error}}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 78 | 0 |  |  |  |  | 0 | $c->res->redirect("/tapper/testplan/days/2"); | 
| 79 |  |  |  |  |  |  | } | 
| 80 |  |  |  |  |  |  |  | 
| 81 | 0 |  | 0 |  |  | 0 | my $days = $filter_condition->{days} || 6; | 
| 82 | 0 |  |  |  |  | 0 | $c->stash->{days} = $days; | 
| 83 |  |  |  |  |  |  |  | 
| 84 | 0 |  |  |  |  | 0 | $c->stash->{testplan_days} = []; | 
| 85 | 0 |  |  |  |  | 0 | my $today = DateTime::Format::Natural->new->parse_datetime("today at midnight"); | 
| 86 | 0 |  |  |  |  | 0 | my $dtf = $c->model("TestrunDB")->storage->datetime_parser; | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | # testplans after "today at midnight" | 
| 89 |  |  |  |  |  |  | # handling them special makes later code more readable | 
| 90 |  |  |  |  |  |  | { | 
| 91 | 0 |  |  |  |  | 0 | my $todays_instances = model('TestrunDB')->resultset('TestplanInstance')->search | 
| 92 |  |  |  |  |  |  | ( | 
| 93 |  |  |  |  |  |  | $filter_condition->{early}, | 
| 94 | 0 |  |  |  |  | 0 | { order_by => 'me.id desc' } | 
| 95 |  |  |  |  |  |  | ); | 
| 96 | 0 |  |  |  |  | 0 | $todays_instances = $todays_instances->search({created_at => { '>' => $dtf->format_datetime($today) }}); | 
| 97 |  |  |  |  |  |  |  | 
| 98 | 0 |  |  |  |  | 0 | my @details = $self->get_testrun_details($todays_instances); | 
| 99 | 0 | 0 |  |  |  | 0 | if (@details) { | 
| 100 | 0 |  |  |  |  | 0 | push @{$c->stash->{testplan_days}}, { date               => $today, | 
|  | 0 |  |  |  |  | 0 |  | 
| 101 |  |  |  |  |  |  | testplan_instances => \@details, | 
| 102 |  |  |  |  |  |  | }; | 
| 103 |  |  |  |  |  |  | } | 
| 104 |  |  |  |  |  |  | } | 
| 105 |  |  |  |  |  |  |  | 
| 106 | 0 |  |  |  |  | 0 | for my $date (1..($days-1)) { | 
| 107 | 0 |  |  |  |  | 0 | my $yesterday = $today->clone->subtract( days => 1 ); | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | my $todays_instances = model('TestrunDB')->resultset('TestplanInstance')->search | 
| 110 |  |  |  |  |  |  | ($filter_condition->{early}, | 
| 111 | 0 |  |  |  |  | 0 | { order_by => 'me.id desc' } | 
| 112 |  |  |  |  |  |  | ); | 
| 113 | 0 |  |  |  |  | 0 | $todays_instances = $todays_instances->search({'-and' => [{created_at => { '>' => $dtf->format_datetime($yesterday) }}, | 
| 114 |  |  |  |  |  |  | {created_at => {'<=' => $dtf->format_datetime($today) }}, | 
| 115 |  |  |  |  |  |  | ]}); | 
| 116 | 0 |  |  |  |  | 0 | my @details = $self->get_testrun_details($todays_instances); | 
| 117 | 0 | 0 |  |  |  | 0 | if (@details) { | 
| 118 | 0 |  |  |  |  | 0 | push @{$c->stash->{testplan_days}}, { date               => $today, | 
|  | 0 |  |  |  |  | 0 |  | 
| 119 |  |  |  |  |  |  | testplan_instances => \@details, | 
| 120 |  |  |  |  |  |  | }; | 
| 121 |  |  |  |  |  |  | } | 
| 122 | 0 |  |  |  |  | 0 | $today = $yesterday; | 
| 123 |  |  |  |  |  |  | } | 
| 124 | 0 |  |  |  |  | 0 | return; | 
| 125 | 10 |  |  | 10 |  | 10468 | } | 
|  | 10 |  |  |  |  | 16 |  | 
|  | 10 |  |  |  |  | 39 |  | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | sub get_testrun_details | 
| 130 |  |  |  |  |  |  | { | 
| 131 | 0 |  |  | 0 | 1 |  | my ($self, $todays_instances) = @_; | 
| 132 | 0 | 0 | 0 |  |  |  | return unless $todays_instances and $todays_instances->can('next'); | 
| 133 |  |  |  |  |  |  |  | 
| 134 | 0 |  |  |  |  |  | my @testplan_instances; | 
| 135 |  |  |  |  |  |  |  | 
| 136 | 0 |  |  |  |  |  | while ( my $instance = $todays_instances->next) { | 
| 137 |  |  |  |  |  |  |  | 
| 138 | 0 |  |  |  |  |  | my $details = {}; | 
| 139 | 0 |  |  |  |  |  | foreach my $col ($instance->columns) { | 
| 140 | 0 |  |  |  |  |  | $details->{$col} = $instance->$col; | 
| 141 |  |  |  |  |  |  | } | 
| 142 | 0 | 0 |  |  |  |  | $details->{count_unfinished} = int grep {$_->testrun_scheduling and | 
|  | 0 |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | $_->testrun_scheduling->status ne 'finished'} $instance->testruns->all; | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 0 |  |  |  |  |  | my $testruns = $instance->testruns; | 
| 147 |  |  |  |  |  |  | TESTRUN: | 
| 148 | 0 |  |  |  |  |  | while ( my $testrun = $testruns->next) { | 
| 149 | 0 | 0 |  |  |  |  | next TESTRUN if $testrun->testrun_scheduling->status ne 'finished'; | 
| 150 | 0 |  |  |  |  |  | my $stats   = model('TestrunDB')->resultset('ReportgroupTestrunStats')->search({testrun_id => $testrun->id}, {rows => 1})->first; | 
| 151 |  |  |  |  |  |  |  | 
| 152 | 0 | 0 | 0 |  |  |  | $details->{count_fail}++ if $stats and $stats->success_ratio  < 100; | 
| 153 | 0 | 0 | 0 |  |  |  | $details->{count_pass}++ if $stats and $stats->success_ratio == 100; | 
| 154 |  |  |  |  |  |  | } | 
| 155 | 0 |  |  |  |  |  | push @testplan_instances, $details; | 
| 156 |  |  |  |  |  |  | } | 
| 157 | 0 |  |  |  |  |  | return @testplan_instances; | 
| 158 |  |  |  |  |  |  | } | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | sub prepare_navi : Private | 
| 161 |  |  |  |  |  |  | { | 
| 162 | 0 |  |  | 0 | 0 |  | my ( $self, $c ) = @_; | 
| 163 | 0 |  |  |  |  |  | $c->stash->{navi} = []; | 
| 164 |  |  |  |  |  |  |  | 
| 165 | 0 |  |  |  |  |  | my %args = @{$c->req->arguments}; | 
|  | 0 |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | $c->stash->{navi} = [ | 
| 168 |  |  |  |  |  |  | { | 
| 169 | 0 |  |  |  |  |  | title  => "Matrix Overview", | 
| 170 |  |  |  |  |  |  | href => "/tapper/testplan/taskjuggler/", | 
| 171 |  |  |  |  |  |  | }, | 
| 172 |  |  |  |  |  |  | { | 
| 173 |  |  |  |  |  |  | title  => "Testplan by date", | 
| 174 |  |  |  |  |  |  | href   => "", | 
| 175 |  |  |  |  |  |  | subnavi => [ | 
| 176 |  |  |  |  |  |  | { | 
| 177 |  |  |  |  |  |  | title  => "today", | 
| 178 |  |  |  |  |  |  | href   => "/tapper/testplan/".$self->prepare_filter_path($c, 1), | 
| 179 |  |  |  |  |  |  | }, | 
| 180 |  |  |  |  |  |  | { | 
| 181 |  |  |  |  |  |  | title  => "2 days", | 
| 182 |  |  |  |  |  |  | href   => "/tapper/testplan/".$self->prepare_filter_path($c, 2), | 
| 183 |  |  |  |  |  |  | }, | 
| 184 |  |  |  |  |  |  | { | 
| 185 |  |  |  |  |  |  | title  => "1 week", | 
| 186 |  |  |  |  |  |  | href   => "/tapper/testplan/".$self->prepare_filter_path($c, 7), | 
| 187 |  |  |  |  |  |  | }, | 
| 188 |  |  |  |  |  |  | { | 
| 189 |  |  |  |  |  |  | title  => "2 weeks", | 
| 190 |  |  |  |  |  |  | href   => "/tapper/testplan/".$self->prepare_filter_path($c, 14), | 
| 191 |  |  |  |  |  |  | }, | 
| 192 |  |  |  |  |  |  | { | 
| 193 |  |  |  |  |  |  | title  => "3 weeks", | 
| 194 |  |  |  |  |  |  | href   => "/tapper/testplan/".$self->prepare_filter_path($c, 21), | 
| 195 |  |  |  |  |  |  | }, | 
| 196 |  |  |  |  |  |  | { | 
| 197 |  |  |  |  |  |  | title  => "1 month", | 
| 198 |  |  |  |  |  |  | href   => "/tapper/testplan/".$self->prepare_filter_path($c, 31), | 
| 199 |  |  |  |  |  |  | }, | 
| 200 |  |  |  |  |  |  | { | 
| 201 |  |  |  |  |  |  | title  => "2 months", | 
| 202 |  |  |  |  |  |  | href   => "/tapper/testplan/".$self->prepare_filter_path($c, 62), | 
| 203 |  |  |  |  |  |  | }, | 
| 204 |  |  |  |  |  |  | { | 
| 205 |  |  |  |  |  |  | title  => "4 months", | 
| 206 |  |  |  |  |  |  | href   => "/tapper/testplan/".$self->prepare_filter_path($c, 124), | 
| 207 |  |  |  |  |  |  | }, | 
| 208 |  |  |  |  |  |  | { | 
| 209 |  |  |  |  |  |  | title  => "6 months", | 
| 210 |  |  |  |  |  |  | href   => "/tapper/testplan/".$self->prepare_filter_path($c, 182), | 
| 211 |  |  |  |  |  |  | }, | 
| 212 |  |  |  |  |  |  | { | 
| 213 |  |  |  |  |  |  | title  => "12 months", | 
| 214 |  |  |  |  |  |  | href   => "/tapper/testplan/".$self->prepare_filter_path($c, 365), | 
| 215 |  |  |  |  |  |  | }, | 
| 216 |  |  |  |  |  |  |  | 
| 217 |  |  |  |  |  |  | ], | 
| 218 |  |  |  |  |  |  | }, | 
| 219 |  |  |  |  |  |  | ]; | 
| 220 |  |  |  |  |  |  |  | 
| 221 | 0 |  |  |  |  |  | push @{$c->stash->{navi}}, {title   => 'Active Filters', | 
| 222 |  |  |  |  |  |  | subnavi => [ | 
| 223 |  |  |  |  |  |  | map { | 
| 224 | 0 |  |  |  |  |  | { | 
| 225 | 0 |  |  |  |  |  | title => "$_: ".$args{$_}, | 
| 226 |  |  |  |  |  |  | href => "/tapper/reports/".$self->reduced_filter_path(\%args, $_), | 
| 227 |  |  |  |  |  |  | image  => "/tapper/static/images/minus.png", | 
| 228 |  |  |  |  |  |  | } | 
| 229 |  |  |  |  |  |  | } keys %args ]}; | 
| 230 | 10 |  |  | 10 |  | 11376 | } | 
|  | 10 |  |  |  |  | 17 |  | 
|  | 10 |  |  |  |  | 42 |  | 
| 231 |  |  |  |  |  |  |  | 
| 232 |  |  |  |  |  |  |  | 
| 233 |  |  |  |  |  |  |  | 
| 234 |  |  |  |  |  |  | 1; | 
| 235 |  |  |  |  |  |  |  | 
| 236 |  |  |  |  |  |  | __END__ | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  | =pod | 
| 239 |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | =encoding UTF-8 | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | =head1 NAME | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | Tapper::Reports::Web::Controller::Tapper::Testplan | 
| 245 |  |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 247 |  |  |  |  |  |  |  | 
| 248 |  |  |  |  |  |  | Catalyst Controller. | 
| 249 |  |  |  |  |  |  |  | 
| 250 |  |  |  |  |  |  | =head2 index | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | =head2 get_testrun_details | 
| 253 |  |  |  |  |  |  |  | 
| 254 |  |  |  |  |  |  | Get the details of the testruns belonging to the testplan instance given | 
| 255 |  |  |  |  |  |  | as argument. | 
| 256 |  |  |  |  |  |  |  | 
| 257 |  |  |  |  |  |  | @param DBIC ResultSet TestplanInstance - testplan instances of current day | 
| 258 |  |  |  |  |  |  |  | 
| 259 |  |  |  |  |  |  | @returnlist success - array ref of lists of details of testruns in given instances | 
| 260 |  |  |  |  |  |  | @returnlist error   - empty list | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | =head1 NAME | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  | Tapper::Reports::Web::Controller::Tapper::Testplan - Catalyst Controller for test plans | 
| 265 |  |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | =head1 METHODS | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | =head2 index | 
| 269 |  |  |  |  |  |  |  | 
| 270 |  |  |  |  |  |  | =head1 AUTHOR | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | AMD OSRC Tapper Team, C<< <tapper at amd64.org> >> | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | =head1 LICENSE | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | This program is released under the following license: freebsd | 
| 277 |  |  |  |  |  |  |  | 
| 278 |  |  |  |  |  |  | =head1 AUTHORS | 
| 279 |  |  |  |  |  |  |  | 
| 280 |  |  |  |  |  |  | =over 4 | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | =item * | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | AMD OSRC Tapper Team <tapper@amd64.org> | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | =item * | 
| 287 |  |  |  |  |  |  |  | 
| 288 |  |  |  |  |  |  | Tapper Team <tapper-ops@amazon.com> | 
| 289 |  |  |  |  |  |  |  | 
| 290 |  |  |  |  |  |  | =back | 
| 291 |  |  |  |  |  |  |  | 
| 292 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | This software is Copyright (c) 2017 by Advanced Micro Devices, Inc.. | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | This is free software, licensed under: | 
| 297 |  |  |  |  |  |  |  | 
| 298 |  |  |  |  |  |  | The (two-clause) FreeBSD License | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | =cut |