File Coverage

lib/Test/Assertions.pm
Criterion Covered Total %
statement 149 218 68.3
branch 45 92 48.9
condition 12 26 46.1
subroutine 21 29 72.4
pod 14 20 70.0
total 241 385 62.6


line stmt bran cond sub pod time code
1             package Test::Assertions;
2              
3 2     2   2445 use strict;
  2         5  
  2         478  
4             @Test::Assertions::EXPORT = qw(DIED COMPILES EQUAL EQUALS_FILE MATCHES_FILE FILES_EQUAL ASSESS ASSESS_FILE INTERPRET tests READ_FILE WRITE_FILE);
5             $Test::Assertions::VERSION = sprintf"%d.%03d", q$Revision: 1.54 $ =~ /: (\d+)\.(\d+)/;
6              
7             #Define constants
8             #(avoid "use constant" to cut compile-time overhead slightly - it *is* measurable)
9             BEGIN
10             {
11 2     2   9 *tests = sub () {1}; # constant to export
12 2         5 *HAVE_ALARM = sub () {1}; # a flag, so that alarm() is never called if it isn't present (e.g. on Windows)
13             eval
14 2         6 {
15 2         36 my $was = alarm 0;
16 2         10 alarm $was;
17             };
18 2 50       173 undef *HAVE_ALARM, *HAVE_ALARM = sub () {0} if($@); #Change the constant!
19             }
20              
21             # this is the number of the current test, for automatically
22             # numbering the output of ASSERT
23             $Test::Assertions::test_no = 0;
24             # this is a flag - true if we are imported in a testing mode
25             $Test::Assertions::test_mode = 0;
26              
27             sub import
28             {
29 4     4   34 my $pkg = shift;
30 4         7 my $style = shift;
31 4         11 my $callpkg = caller(0);
32 2     2   13 no strict 'refs';
  2         4  
  2         6518  
33 4         11 foreach my $sym (@Test::Assertions::EXPORT) {
34 48         67 *{"$callpkg\::$sym"} = \&{"$pkg\::$sym"};
  48         202  
  48         127  
35             }
36              
37             #Select implementation of ASSERT
38 4 50 66     56 if(!$style) {
    50          
    50          
    50          
    50          
    50          
39 0     0   0 *{"$callpkg\::ASSERT"} = sub {};
  0         0  
  0         0  
40             }
41             elsif($style eq 'die') {
42 0         0 *{"$callpkg\::ASSERT"} = \&{"$pkg\::ASSERT_die"};
  0         0  
  0         0  
43             }
44             elsif($style eq 'warn') {
45 0         0 *{"$callpkg\::ASSERT"} = \&{"$pkg\::ASSERT_warn"};
  0         0  
  0         0  
46             }
47             elsif($style eq 'confess') {
48 0         0 *{"$callpkg\::ASSERT"} = \&{"$pkg\::ASSERT_confess"};
  0         0  
  0         0  
49             }
50             elsif($style eq 'cluck') {
51 0         0 *{"$callpkg\::ASSERT"} = \&{"$pkg\::ASSERT_cluck"};
  0         0  
  0         0  
52             }
53             elsif($style eq 'test' || $style eq 'test/ok') {
54 4         92 require File::Spec;
55 4         193 $Test::Assertions::calling_script = File::Spec->rel2abs($0);
56 4         21 $Test::Assertions::use_ok = $style eq 'test/ok';
57 4         6 *{"$callpkg\::ASSERT"} = \&{"$pkg\::ASSERT_test"};
  4         18  
  4         14  
58 4 100       17 *{"$callpkg\::ok"} = \&{"$pkg\::ASSERT_test"} if($style eq 'test/ok');
  1         7  
  1         3  
59 4         6 *{"$callpkg\::plan"} = \&{"$pkg\::plan"};
  4         14  
  4         12  
60 4         7 *{"$callpkg\::ignore"} = \&{"$pkg\::ignore"};
  4         14  
  4         11  
61 4         7 *{"$callpkg\::only"} = \&{"$pkg\::only"};
  4         16  
  4         12  
62 4         2611 $Test::Assertions::test_mode = 1;
63             }
64             else {
65 0         0 croak("Test::Assertions imported with unknown directive: $style");
66             }
67             }
68              
69             #For compatibility with Test::Simple
70             sub plan
71             {
72 2     2 1 129 shift(); #tests
73 2         5 my $number = shift();
74 2 100 66     23 $number = _count_tests($Test::Assertions::calling_script)
75             unless (defined($number) && $number =~ /^\d+$/);
76 2         27 print "1..$number\n";
77 2         184 $Test::Assertions::planned_tests = $number;
78 2         8 return $number;
79             }
80              
81             END
82             {
83             # if we're in test mode and plan() has been called, ensure that the right number of tests have been run
84 2 50 33 2   222 if ($Test::Assertions::test_mode && defined($Test::Assertions::planned_tests)) {
85 2 50       0 if ($Test::Assertions::test_no != $Test::Assertions::planned_tests) {
86 0         0 warn "# Looks like you planned $Test::Assertions::planned_tests tests but actually ran $Test::Assertions::test_no.\n";
87             }
88             }
89             }
90              
91             #Test filtering
92             sub ignore
93             {
94 0     0 1 0 %Test::Assertions::ignore = map {$_ => 1} @_;
  0         0  
95             }
96              
97             sub only
98             {
99 0     0 1 0 %Test::Assertions::only = map {$_ => 1} @_;
  0         0  
100             }
101              
102              
103             #
104             # Various styles
105             #
106              
107             sub ASSERT_test ($;$)
108             {
109 59     59 0 31853 my ($test,$msg) = @_;
110 59         502 my ($pkg, $filename, $line, $sub) = caller(0);
111 59         212 $Test::Assertions::test_no++;
112 59 50 33     561 if($Test::Assertions::ignore{$Test::Assertions::test_no} ||
      33        
113             %Test::Assertions::only && !$Test::Assertions::only{$Test::Assertions::test_no})
114             {
115 0         0 print "ok - skipped $Test::Assertions::test_no";
116             }
117             else
118             {
119 59 50       1706 print ($test?"ok $Test::Assertions::test_no":"not ok $Test::Assertions::test_no at line $line in $filename");
120             }
121 59 100       874 print " ($msg)" if(defined $msg);
122 59         22341 print "\n";
123             }
124              
125             sub ASSERT_die ($;$)
126             {
127 0     0 0 0 my $test = shift;
128 0         0 my $msg = shift;
129 0 0       0 $msg="($msg)" if(defined $msg);
130 0         0 my ($pkg, $filename, $line, $sub) = caller(0);
131 0 0       0 die("Assertion failure at line $line in $filename $msg\n") unless($test);
132             }
133              
134             sub ASSERT_warn ($;$)
135             {
136 0     0 0 0 my $test = shift;
137 0         0 my $msg = shift;
138 0 0       0 $msg="($msg)" if(defined $msg);
139 0         0 my ($pkg, $filename, $line, $sub) = caller(0);
140 0 0       0 warn("Assertion failure at line $line in $filename $msg\n") unless($test);
141             }
142              
143             sub ASSERT_confess ($;$)
144             {
145 0     0 0 0 my $test = shift;
146 0         0 my $msg = shift;
147 0         0 require Carp;
148 0 0       0 $msg="($msg)" if(defined $msg);
149 0         0 my ($pkg, $filename, $line, $sub);
150 0 0       0 if (caller(1)) {
151 0         0 ($pkg, $filename, $line, $sub) = caller(1);
152             } else {
153 0         0 ($pkg, $filename, $line, $sub) = caller(0);
154             }
155 0 0       0 Carp::confess("Assertion failure at line $line in $filename $msg\n") unless($test);
156             }
157              
158             sub ASSERT_cluck ($;$)
159             {
160 0     0 0 0 my $test = shift;
161 0         0 my $msg = shift;
162 0         0 require Carp;
163 0 0       0 $msg="($msg)" if(defined $msg);
164 0         0 my ($pkg, $filename, $line, $sub);
165 0 0       0 if (caller(1)) {
166 0         0 ($pkg, $filename, $line, $sub) = caller(1);
167             } else {
168 0         0 ($pkg, $filename, $line, $sub) = caller(0);
169             }
170 0 0       0 Carp::cluck("Assertion failure at line $line in $filename $msg\n") unless($test);
171             }
172              
173             sub DIED
174             {
175 1     1 1 10 my ($coderef) = @_;
176 1         20 eval {&$coderef};
  1         5  
177 1         15 my $error = $@;
178 1         5 TRACE("DIED: " . $error);
179 1         4 return $error;
180             }
181              
182             sub COMPILES
183             {
184 0     0 1 0 my ($file, $strict, $strref) = @_;
185              
186 0         0 my @args = ($^X);
187 0 0       0 push @args, '-Mstrict', '-w' if $strict;
188 0         0 push @args, '-c', $file;
189 0         0 my $output;
190 0         0 my $ok = 0;
191 0 0 0     0 if ($strref && ref($strref) eq 'SCALAR') {
192 0         0 require IO::CaptureOutput;
193 0         0 ($output, $$strref) = IO::CaptureOutput::capture_exec(@args);
194 0         0 $ok = ($$strref =~ /syntax OK/);
195             } else {
196 0         0 my $command = join ' ', @args;
197 0         0 $output = `$command 2>&1`;
198 0         0 $output =~ s/\n$//;
199 0         0 $ok = ($output =~ /syntax OK/);
200             }
201 0 0       0 return wantarray? ($ok, $output) : $ok;
202             }
203              
204             sub EQUAL
205             {
206 8     8 1 2200 require Test::More;
207 8         63329 my ($lhs, $rhs) = @_;
208 8         43 return Test::More::eq_array([$lhs],[$rhs]);
209             }
210              
211             sub FILES_EQUAL
212             {
213 4     4 1 1020 require File::Compare;
214 4         1316 my ($lhs, $rhs) = @_;
215 4         11 return File::Compare::compare($lhs,$rhs)==0;
216             }
217              
218             sub EQUALS_FILE
219             {
220 3     3 1 9 my ($lhs, $rhs) = @_;
221 3         9 return($lhs eq _read_file($rhs));
222             }
223              
224             sub MATCHES_FILE
225             {
226 4     4 1 10 my ($lhs, $rhs) = @_;
227 4         10 my $regex = _read_file($rhs);
228 4         58 return($lhs =~ /^$regex$/);
229             }
230              
231             sub ASSESS_FILE
232             {
233 1     1 1 2 my ($file, $verbose, $timeout) = @_;
234 1 50       4 $timeout = 60 unless(defined $timeout);
235 1         3 my @tests;
236 1         3 local *FH;
237             eval
238 1         2 {
239 1         10 alarm $timeout if HAVE_ALARM;
240 1 50       6345 open (*FH, "$file |") or die("unable to execute $file - $!");
241 1         5394 @tests = ;
242 1         56 close FH;
243             };
244 1         9 alarm 0 if HAVE_ALARM;
245 1         12 my $rs;
246 1 50       25 if($@) {
    50          
247 0         0 $rs = "not ok for $file ($@)\n"
248             } elsif ($?) {
249 0         0 $rs = "not ok for $file (exit code = $?)\n";
250             } else {
251 1         295 $rs = ASSESS(\@tests, $file, $verbose);
252             }
253 1 50       38 return wantarray? INTERPRET($rs) : $rs;
254             }
255              
256             sub ASSESS
257             {
258 6     6 1 21 my ($tests, $name, $verbose) = @_;
259 6         11 my $errors = 0;
260 6         8 my $total = 0;
261 6         6 my $expected;
262 6 100       7 if (${$tests}[0] =~ m/^1\.\.(\d+)$/) {
  6         137  
263 2         24 $expected = $1;
264             }
265             else
266             {
267 4         6 $expected = -1;
268             }
269 6         17 foreach(@$tests)
270             {
271 11 100       60 if(/^not ok/)
    100          
272             {
273 3         5 $errors++; $total++;
  3         4  
274 3 50       13 if($verbose)
275             {
276 0         0 s/\n?$/ in $name\n/;
277 0         0 print;
278             }
279             }
280             elsif(/^ok/)
281             {
282 6         19 $total++;
283             }
284             }
285              
286 6         370 my $rs;
287 6 100       12 if(defined $name) { $name = " for $name"; } else { $name = ''; }
  3         11  
  3         4  
288 6 100 66     45 if($errors)
    100          
289             {
290 3         29 $rs = "not ok$name ($errors errors in $total tests)\n";
291             }
292             elsif($expected != -1 && $total != $expected)
293             {
294 1         5 $rs = "not ok$name (Expected $expected tests, ran $total tests)\n";
295             }
296             else
297             {
298 2 50       8 $rs = "ok$name".($verbose?" passed all $total tests ":"")."\n";
299             }
300 6 100       57 return wantarray? INTERPRET($rs) : $rs;
301             }
302              
303             sub INTERPRET
304             {
305 2     2 1 4 my $rs = shift;
306 2         16 my ($status, $desc) = ($rs =~ /^((?:not )?ok)(.*)$/);
307 2         12 $desc =~ s/^\s+//;
308 2         136 $desc =~ s/^for //; #ok for x => x
309 2         6 $desc =~ s/^- //; #ok - x => x
310 2         4 $desc =~ s/^\((.*)\)/$1/; #ok (x) => x
311 2   100     22 return ($status eq 'ok' || 0, $desc);
312             }
313              
314             sub READ_FILE
315             {
316 17     17 1 110 my $filename = shift;
317 17         28 my $contents;
318 17         69 eval {
319 17         85 $contents = _read_file($filename);
320             };
321 17         377 return $contents;
322             }
323              
324             sub WRITE_FILE
325             {
326 18     18 1 220 my ($filename, $contents) = @_;
327 18         45 my $success;
328 18         33 eval {
329 18         56 _write_file($filename, $contents);
330 18         36 $success = 1;
331             };
332 18         46 return $success;
333             }
334              
335             # Misc subroutines
336              
337             sub _count_tests
338             {
339 1     1   2 my $filename = shift;
340 1         1 my $count = 0;
341 1         3 local *LI;
342 1 50       60 open (LI, $filename) || die ("Unable to open $filename to count tests - $!");
343 1         26 while(
  • )
  • 344             {
    345 26         41 s/\#.+//; # ignore commented-out lines
    346 26 100       56 $count++ if(/\bASSERT[\s\(]/);
    347 26 50 33     140 $count++ if($Test::Assertions::use_ok && /\bok[\s\(]/);
    348             }
    349 1         13 close LI;
    350 1         4 return $count;
    351             }
    352              
    353             sub _read_file
    354             {
    355 24     24   66 my $filename = shift;
    356 24 100       940 open (FH, $filename) || die("unable to open $filename - $!");
    357 23         413 local $/ = undef;
    358 23         657 my $data = ;
    359 23         220 close FH;
    360 23         114 return $data;
    361             }
    362              
    363             sub _write_file
    364             {
    365 18     18   35 my ($filename, $data) = @_;
    366 18         62 local *FH;
    367 18 50       1427 open(FH, ">$filename") or die("Unable to open $filename - $!");
    368 18         43 binmode FH;
    369 18         81 print FH $data;
    370 18         670 close FH;
    371             }
    372              
    373             #Standard debugging stub - intended to be overridden when
    374             #debugging is needed, e.g. by Log::Trace
    375 1     1 0 3 sub TRACE {}
    376              
    377             1;
    378              
    379             __END__