File Coverage

blib/lib/SmokeRunner/Multi/TestSet.pm
Criterion Covered Total %
statement 99 99 100.0
branch 11 14 78.5
condition 6 8 75.0
subroutine 29 29 100.0
pod 11 11 100.0
total 156 161 96.8


line stmt bran cond sub pod time code
1             package SmokeRunner::Multi::TestSet;
2             BEGIN {
3 8     8   62095 $SmokeRunner::Multi::TestSet::AUTHORITY = 'cpan:YANICK';
4             }
5             {
6             $SmokeRunner::Multi::TestSet::VERSION = '0.19';
7             }
8             #ABSTRACT: Represents a set of tests
9              
10 8     8   61 use strict;
  8         15  
  8         253  
11 8     8   42 use warnings;
  8         16  
  8         270  
12              
13 8     8   43 use base 'Class::Accessor::Fast';
  8         36  
  8         3948  
14             __PACKAGE__->mk_ro_accessors( qw( name set_dir test_dir last_run_time is_prioritized ) );
15              
16 8     8   19094 use Class::Factory::Util;
  8         5585  
  8         56  
17 8     8   315 use File::Basename qw( basename );
  8         18  
  8         621  
18 8     8   7591 use File::Find::Rule;
  8         66301  
  8         84  
19 8     8   536 use File::Path qw( rmtree );
  8         16  
  8         520  
20 8     8   76 use File::Spec;
  8         16  
  8         186  
21 8     8   44 use List::Util qw( max );
  8         16  
  8         841  
22 8     8   5708 use SmokeRunner::Multi::DBI;
  8         24  
  8         282  
23 8     8   2100 use SmokeRunner::Multi::Validate qw( validate DIR_TYPE );
  8         16  
  8         68  
24              
25              
26             BEGIN
27             {
28 8     8   72 for my $subclass ( map { __PACKAGE__ . '::' . $_ } __PACKAGE__->subclasses() )
  8         4618  
29             {
30 8 50       523 eval "require $subclass" or die $@;
31             }
32             }
33              
34             {
35             my $spec = { set_dir => DIR_TYPE };
36             sub new
37             {
38 49     49 1 27538 my $class = shift;
39 49         1742 my %p = validate( @_, $spec );
40              
41 49         835 my $test_dir = File::Spec->catdir( $p{set_dir}, 't' );
42 49 100       1512 die "A test set's directory must have a 't' subdirectory"
43             unless -d $test_dir;
44              
45 47         3152 my %subclass_p = ( %p,
46             name => basename( $p{set_dir} ),
47             test_dir => $test_dir,
48             dbh => SmokeRunner::Multi::DBI::handle(),
49             );
50              
51 47         126 my $self;
52 47         454 for my $subclass ( map { __PACKAGE__ . '::' . $_ } $class->subclasses() )
  47         47023  
53             {
54 47         703 $self = $subclass->_new(%subclass_p);
55             }
56              
57 47   66     553 $self ||= __PACKAGE__->_new(%subclass_p);
58              
59 47         203 $self->_instantiate_in_db();
60 47         2331064 $self->_get_db_data();
61              
62 47         1594 return $self;
63             }
64             }
65              
66             sub _new
67             {
68 44     44   86 my $class = shift;
69              
70 44         590 return bless { @_ }, $class;
71             }
72              
73             sub _instantiate_in_db
74             {
75 47     47   84 my $self = shift;
76              
77 47         164 my $insert_sql = 'INSERT OR IGNORE INTO TestSet (name) VALUES (?)';
78              
79 47         270 $self->{dbh}->do( $insert_sql, {}, $self->name() );
80             }
81              
82             sub _get_db_data
83             {
84 56     56   174 my $self = shift;
85              
86 56         130 my $select_sql = 'SELECT last_run_time, is_prioritized FROM TestSet WHERE name = ?';
87              
88 56         486 @{ $self }{ qw( last_run_time is_prioritized ) } =
  56         17060  
89             $self->{dbh}->selectrow_array( $select_sql, {}, $self->name() );
90             }
91              
92             sub test_files
93             {
94 37     37 1 5393 my $self = shift;
95              
96 37         1635 return sort File::Find::Rule->file()->name( '*.t' )->in( $self->test_dir() );
97             }
98              
99             sub last_mod_time
100             {
101 56     56 1 1676 my $self = shift;
102              
103 56 100       312 return $self->{last_mod_time} if exists $self->{last_mod_time};
104              
105 30   100     192 $self->{last_mod_time} = $self->_last_mod_time() || 0;
106              
107 30         2995 return $self->{last_mod_time};
108             }
109              
110             sub _last_mod_time
111             {
112 29     29   105 my $self = shift;
113              
114 29         79 return max map { ( stat $_ )[9] } $self->test_files();
  62         34612  
115             }
116              
117             sub is_out_of_date
118             {
119 4     4 1 4376 my $self = shift;
120              
121 4 100       18 return $self->seconds_out_of_date() > 0 ? 1 : 0;
122             }
123              
124             sub seconds_out_of_date
125             {
126 55     55 1 422 my $self = shift;
127              
128 55         149 return $self->last_mod_time() - $self->last_run_time();
129             }
130              
131             sub update_last_run_time
132             {
133 3     3 1 1964 my $self = shift;
134 3         18 my $time = shift;
135              
136 3         15 my $update_sql = 'UPDATE TestSet SET last_run_time = ? WHERE name = ?';
137              
138 3         35 $self->{dbh}->do( $update_sql, {}, $time, $self->name() );
139              
140 3         442483 $self->_get_db_data();
141             }
142              
143             sub prioritize
144             {
145 4     4 1 588 my $self = shift;
146              
147 4         9 my $update_sql = 'UPDATE TestSet SET is_prioritized = ? WHERE name = ?';
148              
149 4         22 $self->{dbh}->do( $update_sql, {}, 1, $self->name() );
150              
151 4         81160 $self->_get_db_data();
152             }
153              
154             sub unprioritize
155             {
156 2     2 1 1334 my $self = shift;
157              
158 2         9 my $update_sql = 'UPDATE TestSet SET is_prioritized = ? WHERE name = ?';
159              
160 2         19 $self->{dbh}->do( $update_sql, {}, 0, $self->name() );
161              
162 2         150052 $self->_get_db_data();
163             }
164              
165             sub update_files
166             {
167 1     1 1 3 return;
168             }
169              
170             sub remove
171             {
172 2     2 1 15 my $self = shift;
173              
174 2         5 my $delete_sql = 'DELETE FROM TestSet WHERE name = ?';
175              
176 2         10 $self->{dbh}->do( $delete_sql, {}, $self->name() );
177              
178 2 50       204017 rmtree( $self->set_dir(), 0, 0 )
179             or die "Cannot rmtree " . $self->set_dir() . "\n";
180             }
181              
182             sub All
183             {
184 10     10 1 18309 my $class = shift;
185              
186 10         134 my $root_dir = SmokeRunner::Multi::Config->instance()->root_dir();
187              
188 10 50       454 opendir my $dh, $root_dir
189             or die "Cannot read $root_dir: $!";
190              
191             return
192             ( sort _sort_sets
193 33 100       70 map { eval { $class->new( set_dir => $_ ) } || () }
  33         270  
  52         1664  
194 52         417 grep { -d }
195 10         565 map { File::Spec->catdir( $root_dir, $_ ) }
196             File::Spec->no_upwards( readdir $dh )
197             );
198             }
199              
200             sub _sort_sets
201             {
202             return
203 30   66 30   314 ( $b->is_prioritized() <=> $a->is_prioritized()
204             or
205             $b->seconds_out_of_date() <=> $a->seconds_out_of_date()
206             or
207             # This last clause simply ensures that the sort order is
208             # unique and repeatable.
209             $a->name() cmp $b->name()
210             );
211             }
212              
213              
214             1;
215              
216             __END__