File Coverage

blib/lib/App/CELL/Test.pm
Criterion Covered Total %
statement 71 82 86.5
branch 11 16 68.7
condition 5 11 45.4
subroutine 17 19 89.4
pod 5 5 100.0
total 109 133 81.9


line stmt bran cond sub pod time code
1             # *************************************************************************
2             # Copyright (c) 2014-2020, SUSE LLC
3             #
4             # All rights reserved.
5             #
6             # Redistribution and use in source and binary forms, with or without
7             # modification, are permitted provided that the following conditions are met:
8             #
9             # 1. Redistributions of source code must retain the above copyright notice,
10             # this list of conditions and the following disclaimer.
11             #
12             # 2. Redistributions in binary form must reproduce the above copyright
13             # notice, this list of conditions and the following disclaimer in the
14             # documentation and/or other materials provided with the distribution.
15             #
16             # 3. Neither the name of SUSE LLC nor the names of its contributors may be
17             # used to endorse or promote products derived from this software without
18             # specific prior written permission.
19             #
20             # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21             # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22             # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23             # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24             # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25             # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26             # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27             # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28             # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29             # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30             # POSSIBILITY OF SUCH DAMAGE.
31             # *************************************************************************
32              
33             package App::CELL::Test;
34              
35 16     16   904 use strict;
  16         25  
  16         366  
36 16     16   66 use warnings;
  16         25  
  16         325  
37 16     16   196 use 5.012;
  16         43  
38              
39 16     16   81 use App::CELL::Log qw( $log );
  16         24  
  16         1288  
40 16     16   218 use File::Spec;
  16         45  
  16         521  
41              
42             =head1 NAME
43              
44             App::CELL::Test - functions for unit testing
45              
46              
47             =head1 SYNOPSIS
48              
49             use App::CELL::Test;
50              
51             App::CELL::Test::cleartmpdir();
52             my $tmpdir = App::CELL::Test::mktmpdir();
53             App::CELL::Test::touch_files( $tmpdir, 'foo', 'bar', 'baz' );
54             my $booltrue = App::CELL::Test::cmp_arrays(
55             [ 0, 1, 2 ], [ 0, 1, 2 ]
56             );
57             my $boolfalse = App::CELL::Test::cmp_arrays(
58             [ 0, 1, 2 ], [ 'foo', 'bar', 'baz' ]
59             );
60              
61              
62             =head1 DESCRIPTION
63              
64             The C module provides a number of special-purpose functions for
65             use in CELL's test suite.
66              
67              
68              
69             =head1 EXPORTS
70              
71             This module exports the following routines:
72             cleartmpdir
73             cmp_arrays
74             mktmpdir
75             populate_file
76             touch_files
77              
78             =cut
79              
80 16     16   102 use Exporter qw( import );
  16         31  
  16         1127  
81             our @EXPORT_OK = qw( cleartmpdir cmp_arrays mktmpdir populate_file
82             touch_files _touch );
83              
84              
85              
86             =head1 PACKAGE VARIABLES
87              
88             =cut
89              
90             our $tdo; # temporary directory object
91              
92              
93              
94             =head1 FUNCTIONS
95              
96              
97             =head2 mktmpdir
98              
99             Creates the App::CELL testing directory in a temporary directory
100             (obtained using L) and returns the path to this directory in
101             the payload of a status object.
102              
103             =cut
104              
105             sub mktmpdir {
106              
107 16     16   83 use Try::Tiny;
  16         30  
  16         961  
108              
109             try {
110 16     16   9060 use File::Temp;
  16         225785  
  16         3984  
111 4     4   211 $tdo = File::Temp->newdir();
112             }
113             catch {
114 0   0 0   0 my $errmsg = $_ || '';
115 0         0 $errmsg =~ s/\n//g;
116 0         0 $errmsg =~ s/\012/ -- /g;
117 0         0 return App::CELL::Status->new( level => 'ERR',
118             code => 'CELL_CREATE_TMPDIR_FAIL',
119             args => [ $errmsg ],
120             );
121 4     4 1 524 };
122 4         2872 $log->debug( "Created temporary directory" . $tdo );
123 4         19 return App::CELL::Status->ok( $tdo->dirname );
124             }
125              
126              
127             =head2 cleartmpdir
128              
129             DESTROYs the temporary directory object (see L).
130              
131             =cut
132              
133             sub cleartmpdir {
134 2 100   2 1 520 $tdo->DESTROY if defined $tdo;
135 2         500 return App::CELL::Status->ok;
136             }
137              
138              
139             =head3 _touch
140              
141             Touch a file
142              
143             =cut
144              
145             sub _touch {
146 18     18   37 my ( $file ) = @_;
147 18         31 my $now = time;
148              
149 18 50 33     1320 utime ($now, $now, $file)
150             || open my $fh, ">>", $file
151             || warn ("Couldn't touch file: $!\n");
152             }
153              
154              
155             =head2 touch_files
156              
157             "Touch" some files. Takes: directory path and list of files to "touch" in
158             that directory. Returns number of files successfully touched.
159              
160             =cut
161              
162             sub touch_files {
163 2     2 1 264 my ( $dirspec, @file_list ) = @_;
164 16     16   113 use Try::Tiny;
  16         26  
  16         7871  
165              
166 2         4 my $count = @file_list;
167             try {
168 2     2   69 foreach my $file ( map { File::Spec->catfile( $dirspec, $_ ); } @file_list ) {
  10         81  
169 10         31 _touch( $file );
170             }
171             }
172             catch {
173 0     0   0 my $errmsg = $_;
174 0         0 $errmsg =~ s/\n//g;
175 0         0 $errmsg =~ s/\012/ -- /g;
176 0         0 $errmsg = "Attempting to 'touch' $count files in $dirspec . . . failure: $errmsg";
177 0         0 $log->debug( $errmsg );
178 0         0 print STDERR $errmsg, "\n";
179 0         0 return 0;
180 2         16 };
181 2         55 $log->debug( "Attempting to 'touch' $count files in $dirspec . . . success" );
182 2         18 return $count;
183             }
184              
185              
186             =head2 populate_file
187              
188             Takes filename (full path) and contents (as a string, potentially
189             containing newlines) to write to it. If the file exists, it is first
190             unlinked. Then the routine creates the file and populates it with
191             the contents. Returns true if something was written, or false if not.
192              
193             =cut
194              
195             sub populate_file {
196 8     8 1 2378 my ( $full_path, $contents ) = @_;
197 8         198 unlink $full_path;
198             {
199 8 50       19 _touch( $full_path ) or die "Could not touch $full_path";
  8         23  
200             }
201 8 50 33     153 return 0 unless -f $full_path and -W $full_path;
202 8 50       20 return 0 unless $contents;
203 8 50       299 open(my $fh, '>', $full_path ) or die "Could not open file: $!";
204 8         90 print $fh $contents;
205 8         608 close $fh;
206 8         54 return length $contents;
207             }
208              
209             =head2 cmp_arrays
210              
211             Compare two arrays of unique elements, order doesn't matter.
212             Takes: two array references
213             Returns: true (they have the same elements) or false (they differ).
214              
215             =cut
216              
217             sub cmp_arrays {
218 8     8 1 1313 my ( $ref1, $ref2 ) = @_;
219            
220 8         42 $log->debug( "cmp_arrays: we were asked to compare two arrays:");
221 8         57 $log->debug( "ARRAY #1: " . join( ',', @$ref1 ) );
222 8         53 $log->debug( "ARRAY #2: " . join( ',', @$ref2 ) );
223              
224             # convert them into hashes
225 8         23 my ( %ref1, %ref2 );
226 8         16 map { $ref1{ $_ } = ''; } @$ref1;
  21         41  
227 8         13 map { $ref2{ $_ } = ''; } @$ref2;
  22         35  
228              
229             # make a copy of ref1
230 8         25 my %ref1_copy = %ref1;
231              
232             # for each element of ref1, if it matches an element in ref2, delete
233             # the element from _BOTH_
234 8         21 foreach ( keys( %ref1_copy ) ) {
235 17 100       30 if ( exists( $ref2{ $_ } ) ) {
236 14         17 delete $ref1{ $_ };
237 14         19 delete $ref2{ $_ };
238             }
239             }
240              
241             # if the two arrays are the same, the number of keys in both hashes should
242             # be zero
243 8         49 $log->debug( "cmp_arrays: after comparison, hash #1 has " . keys( %ref1 )
244             . " elements and hash #2 has " . keys ( %ref2 ) . " elements" );
245 8 100 100     66 if ( keys( %ref1 ) == 0 and keys( %ref2 ) == 0 ) {
246 6         26 return 1;
247             } else {
248 2         6 return 0;
249             }
250             }
251              
252             1;