File Coverage

blib/lib/Tapper/Schema/TestrunDB/Result/Testrun.pm
Criterion Covered Total %
statement 85 109 77.9
branch 10 30 33.3
condition 9 27 33.3
subroutine 11 13 84.6
pod 9 9 100.0
total 124 188 65.9


line stmt bran cond sub pod time code
1             package Tapper::Schema::TestrunDB::Result::Testrun;
2             our $AUTHORITY = 'cpan:TAPPER';
3             $Tapper::Schema::TestrunDB::Result::Testrun::VERSION = '5.0.9';
4             # ABSTRACT: Tapper - Containing Testruns
5              
6 7     7   3438 use 5.010;
  7         17  
7 7     7   26 use strict;
  7         8  
  7         128  
8 7     7   21 use warnings;
  7         6  
  7         152  
9              
10 7     7   19 use parent 'DBIx::Class';
  7         7  
  7         30  
11              
12             __PACKAGE__->load_components(qw/InflateColumn::DateTime TimeStamp Core/);
13             __PACKAGE__->table('testrun');
14             __PACKAGE__->add_columns(
15             'id', {
16             data_type => 'INT',
17             default_value => undef,
18             is_nullable => 0,
19             size => 11,
20             is_auto_increment => 1,
21             },
22             'shortname', {
23             data_type => 'VARCHAR',
24             default_value => undef,
25             is_nullable => 0,
26             size => 255,
27             },
28             'notes', {
29             data_type => 'TEXT',
30             default_value => undef,
31             is_nullable => 1,
32             },
33             'topic_name', {
34             data_type => 'VARCHAR',
35             default_value => undef,
36             is_nullable => 0,
37             size => 255,
38             is_foreign_key => 1,
39             },
40             'starttime_earliest', {
41             data_type => 'TIMESTAMP',
42             default_value => undef,
43             is_nullable => 1,
44             },
45             'starttime_testrun', {
46             data_type => 'TIMESTAMP',
47             default_value => undef,
48             is_nullable => 1,
49             },
50             'starttime_test_program', {
51             data_type => 'TIMESTAMP',
52             default_value => undef,
53             is_nullable => 1,
54             },
55             'endtime_test_program', {
56             data_type => 'TIMESTAMP',
57             default_value => undef,
58             is_nullable => 1,
59             },
60             'owner_id', {
61             data_type => 'INT',
62             default_value => undef,
63             is_nullable => 1,
64             size => 11,
65             is_foreign_key => 1,
66             },
67             'testplan_id', {
68             data_type => 'INT',
69             default_value => undef,
70             is_nullable => 1,
71             size => 11,
72             is_foreign_key => 1,
73             },
74             'wait_after_tests', {
75             data_type => 'TINYINT',
76             default_value => 0,
77             is_nullable => 1, #TODO: 0
78             size => 1,
79             },
80             # number of times to rerun this test on error
81             'rerun_on_error', {
82             data_type => 'TINYINT',
83             default_value => 0,
84             is_nullable => 1, #TODO: 0
85             size => 1,
86             },
87             'created_at', {
88             data_type => 'TIMESTAMP',
89             default_value => undef,
90             is_nullable => 1,
91             set_on_create => 1,
92             },
93             'updated_at', {
94             data_type => 'TIMESTAMP',
95             default_value => undef,
96             is_nullable => 1,
97             set_on_create => 1,
98             set_on_update => 1,
99             },
100             );
101              
102             __PACKAGE__->set_primary_key('id');
103              
104             (my $basepkg = __PACKAGE__) =~ s/::\w+$//;
105              
106             # * : 1
107             __PACKAGE__->belongs_to(
108             owner => "${basepkg}::Owner",
109             { 'foreign.id' => 'self.owner_id' },
110             );
111             __PACKAGE__->belongs_to(
112             testplan_instance => "${basepkg}::TestplanInstance",
113             { 'foreign.id' => 'self.testplan_id' },
114             );
115              
116             # 1 : 0,1
117             __PACKAGE__->might_have(
118             testrun_scheduling => "${basepkg}::TestrunScheduling",
119             { 'foreign.testrun_id' => 'self.id' },
120             );
121             __PACKAGE__->might_have(
122             scenario_element => "${basepkg}::ScenarioElement",
123             { 'foreign.testrun_id' => 'self.id' },
124             );
125             __PACKAGE__->might_have(
126             state => "${basepkg}::State",
127             { 'foreign.testrun_id' => 'self.id' },
128             );
129             __PACKAGE__->might_have(
130             reportgrouptestrunstats => "${basepkg}::ReportgroupTestrunStats",
131             { 'foreign.testrun_id' => 'self.id' },
132             );
133              
134             # 1 : *
135             __PACKAGE__->has_many(
136             testrun_precondition => "${basepkg}::TestrunPrecondition",
137             { 'foreign.testrun_id' => 'self.id' },
138             );
139             __PACKAGE__->has_many(
140             message => "${basepkg}::Message",
141             { 'foreign.testrun_id' => 'self.id' },
142             );
143             __PACKAGE__->has_many(
144             testrun_requested_host => "${basepkg}::TestrunRequestedHost",
145             { 'foreign.testrun_id' => 'self.id' },
146             );
147              
148             # * : *
149             __PACKAGE__->many_to_many(
150             preconditions => "testrun_precondition",
151             'precondition'
152             );
153              
154             # -------------------- methods on results --------------------
155              
156              
157             sub to_string
158             {
159 0     0 1 0 my ($self) = @_;
160              
161 0         0 my $format = join( $Tapper::Schema::TestrunDB::DELIM, qw/%s %s %s %s %s %s %s %s %s %s %s %s %s %s /, '');
162             sprintf (
163             $format,
164             map {
165 0 0       0 defined $self->$_
166             ? $self->$_
167             : $Tapper::Schema::TestrunDB::NULL
168 0         0 } @{$self->result_source->{_ordered_columns} }
  0         0  
169             );
170             }
171              
172              
173             sub is_member
174             {
175 20     20 1 37 my ($head, @tail) = @_;
176 20         39 grep { $head->id eq $_->id } @tail;
  66         1969  
177             }
178              
179              
180             sub ordered_preconditions
181             {
182 2     2 1 4684 my ($self) = @_;
183              
184 2         5 my @done = ();
185 2         4 my %seen = ();
186 2         4 my @todo = ();
187              
188 2         10 @todo = $self->preconditions->search({}, {order_by => 'succession'})->all;
189              
190 2         12727 while (my $head = shift @todo)
191             {
192 32 100       1942 if ($seen{$head->id})
193             {
194 20 100       219 push @done, $head unless is_member($head, @done);
195             }
196             else
197             {
198 12         276 $seen{$head->id} = 1;
199 12         123 my @pre_todo = $head->child_preconditions->search({}, { order_by => 'succession' } )->all;
200 12         73314 unshift @todo, @pre_todo, $head;
201             }
202             }
203 2         85 return @done;
204             }
205              
206              
207             sub update_content {
208 0     0 1 0 my ($self, $args) =@_;
209              
210 0 0       0 $self->notes ( $args->{notes} ) if $args->{notes};
211 0 0       0 $self->shortname ( $args->{shortname} ) if $args->{shortname};
212 0 0       0 $self->topic_name ( $args->{topic} ) if $args->{topic};
213 0 0       0 $self->starttime_earliest ( $args->{date} ) if $args->{date};
214 0 0       0 $self->owner_id ( $args->{owner_id} ) if $args->{owner_id};
215 0         0 $self->update;
216 0         0 return $self->id;
217             }
218              
219              
220             sub rerun
221             {
222 1     1 1 59063 my ($self, $args) = @_;
223              
224             my $testrun_new = $self->result_source->schema->resultset('Testrun')->new
225             ({
226             notes => $args->{notes} || $self->notes,
227             shortname => $args->{shortname} || $self->shortname,
228             topic_name => $args->{topic_name} || $self->topic_name,
229             starttime_earliest => $args->{earliest} || DateTime->now,
230 1   33     48 owner_id => $args->{owner_id} || $self->owner_id,
      33        
      33        
      33        
      33        
231             });
232              
233             # prepare job scheduling infos
234 1         1372 my $testrunscheduling = $self->result_source->schema->resultset('TestrunScheduling')->search({ testrun_id => $self->id }, {rows => 1})->first;
235 1         3368 my ($queue_id, $host_id, $auto_rerun, $requested_features, $requested_hosts);
236 1 50       128 if ($testrunscheduling) {
237 1         27 $queue_id = $testrunscheduling->queue_id;
238 1         40 $host_id = $testrunscheduling->host_id;
239 1         25 $auto_rerun = $testrunscheduling->auto_rerun;
240 1         12 $requested_features = $testrunscheduling->requested_features;
241 1         1819 $requested_hosts = $testrunscheduling->requested_hosts;
242             } else {
243 0         0 my $queue = $self->result_source->schema->resultset('Queue')->search({ name => "AdHoc"}, {rows => 1})->first;
244 0 0       0 if (not $queue) {
245 0         0 die "No default queue 'AdHoc' found.";
246             }
247 0         0 $queue_id = $queue->id;
248 0         0 $auto_rerun = 0;
249             }
250              
251             # create testrun and job
252 1         1259 $testrun_new->insert;
253             my $testrunscheduling_new = $self->result_source->schema->resultset('TestrunScheduling')->new
254             ({
255             testrun_id => $testrun_new->id,
256             queue_id => $args->{queue_id} || $queue_id,
257             status => "prepare",
258 1   33     8437 auto_rerun => $args->{host_id} // $auto_rerun,
      33        
259             host_id => undef,
260             });
261 1         892 $testrunscheduling_new->insert;
262              
263             # assign requested host and features
264 1 50 33     7528 if ($testrunscheduling and $testrunscheduling->requested_features->count) {
265 0         0 foreach my $feature (map {$_->feature}$testrunscheduling->requested_features->all) {
  0         0  
266 0         0 my $assigned_feature = $self->result_source->schema->resultset('TestrunRequestedFeature')->new({feature => $feature, testrun_id => $testrun_new->id});
267 0         0 $assigned_feature->insert;
268             }
269             }
270 1 50 33     4018 if ($testrunscheduling and $testrunscheduling->requested_hosts->count) {
271 1         3413 foreach my $host_id (map {$_->host_id}$testrunscheduling->requested_hosts->all) {
  3         1859  
272 3         14221 my $assigned_host = $self->result_source->schema->resultset('TestrunRequestedHost')->new({host_id => $host_id, testrun_id => $testrun_new->id});
273 3         1511 $assigned_host->insert;
274             }
275             }
276              
277             # assign preconditions
278 1         5260 my $preconditions = $self->preconditions->search({}, {order_by => 'succession'});
279 1         3101 my @preconditions;
280 1         17 while (my $precond = $preconditions->next) {
281 0         0 push @preconditions, $precond->id;
282             }
283 1         4680 $testrunscheduling_new->status('schedule');
284 1         332 $testrunscheduling_new->update;
285 1         8362 $testrun_new->assign_preconditions(@preconditions);
286              
287 1         7 return $testrun_new;
288              
289             }
290              
291              
292             sub assign_preconditions {
293 2     2 1 7282 my ($self, @preconditions) = @_;
294              
295 2         4 my $succession = 1;
296 2         5 foreach my $precondition_id (@preconditions) {
297 2         26 my $testrun_precondition = $self->result_source->schema->resultset('TestrunPrecondition')->new
298             ({
299             testrun_id => $self->id,
300             precondition_id => $precondition_id,
301             succession => $succession,
302             });
303 2         827 eval {
304 2         43 $testrun_precondition->insert;
305             };
306 2 50       9395 return "Can not assign $precondition_id: $@" if $@;
307 2         12 $succession++;
308             }
309 2         26 return 0;
310             }
311              
312              
313             sub insert_preconditions {
314 1     1 1 103927 my ($self, $position, @preconditions) = @_;
315              
316 1         2 my $succession = $position;
317 1         5 my $testrun_precondition = $self->result_source->schema->resultset('TestrunPrecondition');
318              
319             # move existing preconditions
320 1         327 my $remaining_preconditions = $testrun_precondition->search({testrun_id => $self->id,
321             succession => { '>=' => $position }});
322 1         154 while (my $remain = $remaining_preconditions->next) {
323 3         90244 $remain->succession($remain->succession + int @preconditions);
324 3         671 $remain->update;
325             }
326              
327             # assign new ones
328 1         5807 foreach my $precondition_id (@preconditions) {
329 2         76 my $testrun_precondition = $testrun_precondition->new
330             ({
331             testrun_id => $self->id,
332             precondition_id => $precondition_id,
333             succession => $succession,
334             });
335 2         297 eval {
336 2         7 $testrun_precondition->insert;
337             };
338 2 50       12056 return "Can not assign $precondition_id: $@" if $@;
339 2         9 $succession++;
340             }
341 1         24 return 0;
342             }
343              
344              
345             sub disassign_preconditions {
346 1     1 1 40570 my ($self, @preconditions) = @_;
347              
348 1         7 my $table = $self->result_source->schema->resultset('TestrunPrecondition');
349 1         408 my $preconditions;
350 1 50       3 if (not @preconditions) {
351 1         21 $preconditions = $table->search({testrun_id => $self->id});
352             } else {
353 0         0 $preconditions = $table->search({testrun_id => $self->id,
354             precondition_id => [ -or => [ @preconditions ]]});
355             }
356              
357              
358 1         165 while( my $precondition = $preconditions->next) {
359 2         10994 $precondition->delete();
360             }
361 1         4735 return 0;
362             }
363              
364              
365             sub sqlt_deploy_hook
366             {
367 7     7 1 18814 my ($self, $sqlt_table) = @_;
368 7         37 $sqlt_table->add_index(name => 'testrun_idx_created_at', fields => ['created_at']);
369             }
370              
371             1;
372              
373             __END__
374              
375             =pod
376              
377             =encoding UTF-8
378              
379             =head1 NAME
380              
381             Tapper::Schema::TestrunDB::Result::Testrun - Tapper - Containing Testruns
382              
383             =head2 to_string
384              
385             Return printable representation.
386              
387             =head2 is_member($head, @tail)
388              
389             Checks if the first element is already in the list of the remaining
390             elements.
391              
392             =head2 ordered_preconditions
393              
394             Returns all preconditions in the order they need to be installed.
395              
396             =head2 update_content
397              
398             Update precondition from given params.
399              
400             =head2 rerun
401              
402             Insert a new testrun similar to this one. Arguments can be given to overwrite
403             some values. All values of the new testrun not given as argument will be taken
404             from $self.
405              
406             @param hash ref - overwrite arguments
407              
408             @return success - new testrun id
409             @return error - exception
410              
411             =head2 assign_preconditions
412              
413             Assign given preconditions to this testrun.
414              
415             @param array - list of precondition ids
416              
417             @return success - 0
418             @return error - error message
419              
420             =head2 insert_preconditions
421              
422             Insert given preconditions (as id) starting at given position and push
423             all later preconditions to make sure they come after the inserted.
424              
425             @param int - starting position
426             @param_list list of precondition_ids
427              
428             @return success - 0
429             @return error - error message
430              
431             =head2 disassign_preconditions
432              
433             Disconnect list of preconditions from a testrun.
434              
435             @param array - list of precondition ids
436              
437             =head2 sqlt_deploy_hook
438              
439             Add useful indexes at deploy time.
440              
441             =head1 AUTHORS
442              
443             =over 4
444              
445             =item *
446              
447             AMD OSRC Tapper Team <tapper@amd64.org>
448              
449             =item *
450              
451             Tapper Team <tapper-ops@amazon.com>
452              
453             =back
454              
455             =head1 COPYRIGHT AND LICENSE
456              
457             This software is Copyright (c) 2017 by Advanced Micro Devices, Inc..
458              
459             This is free software, licensed under:
460              
461             The (two-clause) FreeBSD License
462              
463             =cut