File Coverage

lib/Test/Unit/Lite.pm
Criterion Covered Total %
statement 480 535 89.7
branch 171 234 73.0
condition 46 73 63.0
subroutine 101 112 90.1
pod 2 52 3.8
total 800 1006 79.5


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -c
2              
3             package Test::Unit::Lite;
4              
5             =head1 NAME
6              
7             Test::Unit::Lite - Unit testing without external dependencies
8              
9             =head1 SYNOPSIS
10              
11             Bundling the L as a part of package distribution:
12              
13             perl -MTest::Unit::Lite -e bundle
14              
15             Running all test units:
16              
17             perl -MTest::Unit::Lite -e all_tests
18              
19             Using as a replacement for Test::Unit:
20              
21             package FooBarTest;
22             use Test::Unit::Lite; # unnecessary if module isn't directly used
23             use base 'Test::Unit::TestCase';
24              
25             sub new {
26             my $self = shift()->SUPER::new(@_);
27             # your state for fixture here
28             return $self;
29             }
30              
31             sub set_up {
32             # provide fixture
33             }
34             sub tear_down {
35             # clean up after test
36             }
37             sub test_foo {
38             my $self = shift;
39             my $obj = ClassUnderTest->new(...);
40             $self->assert_not_null($obj);
41             $self->assert_equals('expected result', $obj->foo);
42             $self->assert(qr/pattern/, $obj->foobar);
43             }
44             sub test_bar {
45             # test the bar feature
46             }
47              
48             =head1 DESCRIPTION
49              
50             This framework provides lighter version of L framework. It
51             implements some of the L classes and methods needed to run test
52             units. The L tries to be compatible with public API of
53             L. It doesn't implement all classes and methods at 100% and only
54             those necessary to run tests are available.
55              
56             The L can be distributed as a part of package distribution,
57             so the package can be distributed without dependency on modules outside
58             standard Perl distribution. The L is provided as a single
59             file.
60              
61             =head2 Bundling the L as a part of package distribution
62              
63             The L framework can be bundled to the package distribution.
64             Then the L module is copied to the F directory of the
65             source directory for the package distribution.
66              
67             =cut
68              
69              
70 1     1   1054 use 5.006;
  1         3  
  1         39  
71              
72 1     1   5 use strict;
  1         2  
  1         25  
73 1     1   5 use warnings;
  1         4  
  1         43  
74              
75             our $VERSION = '0.1202';
76              
77 1     1   5 use Carp ();
  1         1  
  1         20  
78 1     1   5 use File::Spec ();
  1         2  
  1         13  
79 1     1   5 use File::Basename ();
  1         1  
  1         25  
80 1     1   945 use File::Copy ();
  1         7953  
  1         27  
81 1     1   7 use File::Path ();
  1         1  
  1         16  
82 1     1   878 use Symbol ();
  1         967  
  1         22  
83              
84              
85             # Can't use Exporter 'import'. Compatibility with Perl 5.6
86 1     1   7 use Exporter ();
  1         2  
  1         29  
87 1     1   335 BEGIN { *import = \&Exporter::import };
88             our @EXPORT = qw{ bundle all_tests };
89              
90              
91             # Copy this module to inc subdirectory of the source distribution
92             sub bundle {
93 0 0 0 0 1 0 -f 'Makefile.PL' or -f 'Build.PL'
94             or die "Cannot find Makefile.PL or Build.PL in current directory\n";
95              
96 0         0 my $src = __FILE__;
97 0         0 my $dst = "inc/Test/Unit/Lite.pm";
98              
99              
100 0         0 my @src = split m{/}, $src;
101 0         0 my @dst = split m{/}, $dst;
102 0         0 my $srcfile = File::Spec->catfile(@src);
103 0         0 my $dstfile = File::Spec->catfile(@dst);
104              
105 0 0       0 die "Cannot bundle to itself: $srcfile\n" if $srcfile eq $dstfile;
106 0         0 print "Copying $srcfile -> $dstfile\n";
107              
108 0         0 my $dstdir = File::Basename::dirname($dstfile);
109              
110 0 0       0 -d $dstdir or File::Path::mkpath([$dstdir], 0, oct(777) & ~umask);
111              
112 0 0       0 File::Copy::cp($srcfile, $dstfile) or die "Cannot copy $srcfile to $dstfile: $!\n";
113             }
114              
115             sub all_tests {
116 0     0 1 0 Test::Unit::TestRunner->new->start('Test::Unit::Lite::AllTests');
117             }
118              
119              
120             {
121             package Test::Unit::TestCase;
122 1     1   5 use Carp ();
  1         2  
  1         720  
123             our $VERSION = $Test::Unit::Lite::VERSION;
124              
125             our %Seen_Refs = ();
126             our @Data_Stack;
127             my $DNE = bless [], 'Does::Not::Exist';
128              
129             sub new {
130 15     15 0 50 my ($class) = @_;
131 15 100       36 $class = ref $class if ref $class;
132 15         23 my $self = {};
133 15         268 return bless $self => $class;
134             }
135              
136 38     38 0 57 sub set_up { }
137              
138 41     41 0 53 sub tear_down { }
139              
140             sub list_tests {
141 33     33 0 63 my ($self) = @_;
142              
143 33   33     82 my $class = ref $self || $self;
144              
145 33         38 my @tests;
146              
147             my %seen_isa;
148 0         0 my $list_base_tests;
149             $list_base_tests = sub {
150 77     77   127 my ($class) = @_;
151 77         80 foreach my $isa (@{ *{ Symbol::qualify_to_ref("${class}::ISA") } }) {
  77         78  
  77         269  
152 46 100       689 next unless $isa->isa(__PACKAGE__);
153 44 50       253 $list_base_tests->($isa) unless $seen_isa{$isa};
154 44         434 $seen_isa{$isa} = 1;
155 44         50 push @tests, grep { /^test_/ } keys %{ *{ Symbol::qualify_to_ref("${class}::") } };
  527         1611  
  44         40  
  44         145  
156             };
157 33         174 };
158 33         69 $list_base_tests->($class);
159              
160 33         78 my %uniq_tests = map { $_ => 1 } @tests;
  121         422  
161 33         152 @tests = sort keys %uniq_tests;
162              
163 33 50       199 return wantarray ? @tests : [ @tests ];
164             }
165              
166             sub __croak {
167 89     89   126 my ($default_message, $custom_message) = @_;
168 89 50       193 $default_message = '' unless defined $default_message;
169 89 100       178 $custom_message = '' unless defined $custom_message;
170 89         104 my $n = 1;
171              
172 89         564 my ($file, $line) = (caller($n++))[1,2];
173 89         151 my $caller;
174 89   66     274 $n++ while (defined( $caller = caller($n) ) and not eval { $caller->isa('Test::Unit::TestSuite') });
  351         3019  
175              
176 89   50     616 my $sub = (caller($n))[3] || '::';
177 89         1839 $sub =~ /^(.*)::([^:]*)$/;
178 89         228 my ($test, $unit) = ($1, $2);
179              
180 89         270 my $message = "$file:$line - $test($unit)\n$default_message\n$custom_message";
181 89         132 chomp $message;
182              
183 1     1   7 no warnings 'once';
  1         2  
  1         952  
184 89         192 local $Carp::Internal{'Test::Unit::TestCase'} = 1;
185 89         10681 Carp::confess("$message\n");
186             }
187              
188             sub fail {
189 2     2 0 571 my ($self, $msg) = @_;
190 2 100       9 $msg = '' unless defined $msg;
191 2         7 __croak $msg;
192             }
193              
194             sub assert {
195 31     31 0 5322 my $self = shift;
196 31         43 my $arg1 = shift;
197 31 100       109 if (ref $arg1 eq 'Regexp') {
198 9         13 my $arg2 = shift;
199 9         14 my $msg = shift;
200 9 100       157 __croak "'$arg2' did not match /$arg1/", $msg unless $arg2 =~ $arg1;
201             }
202             else {
203 22         26 my $msg = shift;
204 22 100       71 __croak "Boolean assertion failed", $msg unless $arg1;
205             }
206             }
207              
208             sub assert_null {
209 3     3 0 546 my ($self, $arg, $msg) = @_;
210 3 100       14 __croak "$arg is defined", $msg unless not defined $arg;
211             }
212              
213             sub assert_not_null {
214 8     8 0 1156 my ($self, $arg, $msg) = @_;
215 8 100       28 __croak " unexpected", $msg unless defined $arg;
216             }
217              
218             sub assert_equals {
219 6     6 0 58 my ($self, $arg1, $arg2, $msg) = @_;
220 6 100 66     20 if (not defined $arg1 and not defined $arg2) {
221 1         3 return;
222             }
223 5 100       12 __croak "expected value was undef; should be using assert_null?", $msg unless defined $arg1;
224 4 50       10 __croak "expected '$arg1', got undef", $msg unless defined $arg2;
225 4 100 66     78 if ($arg1 =~ /^[+-]?(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?$/ and
226             $arg2 =~ /^[+-]?(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?$/)
227             {
228 2 50       9 __croak "expected $arg1, got $arg2", $msg unless $arg1 == $arg2;
229             }
230             else {
231 2 100       21 __croak "expected '$arg1', got '$arg2'", $msg unless $arg1 eq $arg2;
232             }
233             }
234              
235             sub assert_not_equals {
236 37     37 0 12709 my ($self, $arg1, $arg2, $msg) = @_;
237 37 100 66     97 if (not defined $arg1 and not defined $arg2) {
238 2         6 __croak "both args were undefined", $msg;
239             }
240 35 100 75     380 if (not defined $arg1 xor not defined $arg2) {
    100 100        
241             # pass
242             }
243             elsif ($arg1 =~ /^[+-]?(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?$/ and
244             $arg2 =~ /^[+-]?(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?$/)
245             {
246 21 100       87 __croak "$arg1 and $arg2 should differ", $msg unless $arg1 != $arg2;
247             }
248             else {
249 10 100       42 __croak "'$arg1' and '$arg2' should differ", $msg unless $arg1 ne $arg2;
250             }
251             }
252              
253             sub assert_num_equals {
254 8     8 0 53 my ($self, $arg1, $arg2, $msg) = @_;
255 8 50       19 __croak "expected value was undef; should be using assert_null?", $msg unless defined $arg1;
256 8 50       14 __croak "expected '$arg1', got undef", $msg unless defined $arg2;
257 1     1   6 no warnings 'numeric';
  1         3  
  1         157  
258 8 50       65 __croak "expected $arg1, got $arg2", $msg unless $arg1 == $arg2;
259             }
260              
261             sub assert_num_not_equals {
262 0     0 0 0 my ($self, $arg1, $arg2, $msg) = @_;
263 0 0       0 __croak "expected value was undef; should be using assert_null?", $msg unless defined $arg1;
264 0 0       0 __croak "expected '$arg1', got undef", $msg unless defined $arg2;
265 1     1   5 no warnings 'numeric';
  1         2  
  1         2529  
266 0 0       0 __croak "$arg1 and $arg2 should differ", $msg unless $arg1 != $arg2;
267             }
268              
269             sub assert_str_equals {
270 24     24 0 7094 my ($self, $arg1, $arg2, $msg) = @_;
271 24 100       65 __croak "expected value was undef; should be using assert_null?", $msg unless defined $arg1;
272 20 100       46 __croak "expected '$arg1', got undef", $msg unless defined $arg2;
273 17 100       100 __croak "expected '$arg1', got '$arg2'", $msg unless "$arg1" eq "$arg2";
274             }
275              
276             sub assert_str_not_equals {
277 0     0 0 0 my ($self, $arg1, $arg2, $msg) = @_;
278 0 0       0 __croak "expected value was undef; should be using assert_null?", $msg unless defined $arg1;
279 0 0       0 __croak "expected '$arg1', got undef", $msg unless defined $arg2;
280 0 0       0 __croak "'$arg1' and '$arg2' should differ", $msg unless "$arg1" ne "$arg2";
281             }
282              
283             sub assert_matches {
284 3     3 0 380 my ($self, $arg1, $arg2, $msg) = @_;
285 3 100       14 __croak "arg 1 to assert_matches() must be a regexp", $msg unless ref $arg1 eq 'Regexp';
286 2 50       5 __croak "expected '$arg1', got undef", $msg unless defined $arg2;
287 2 50       17 __croak "$arg2 didn't match /$arg1/", $msg unless $arg2 =~ $arg1;
288             }
289              
290             sub assert_does_not_match {
291 2     2 0 30 my ($self, $arg1, $arg2, $msg) = @_;
292 2 100       9 __croak "arg 1 to assert_does_not_match() must be a regexp", $msg unless ref $arg1 eq 'Regexp';
293 1 50       4 __croak "expected '$arg1', got undef", $msg unless defined $arg2;
294 1 50       7 __croak "$arg2 matched /$arg1/", $msg unless $arg2 !~ $arg1;
295             }
296              
297             sub assert_deep_equals {
298 48     48 0 25474 my ($self, $arg1, $arg2, $msg) = @_;
299 48 100 66     244 __croak 'Both arguments were not references', $msg unless ref $arg1 and ref $arg2;
300 38         71 local @Data_Stack = ();
301 38         71 local %Seen_Refs = ();
302 38 100       106 __croak $self->_format_stack(@Data_Stack), $msg unless $self->_deep_check($arg1, $arg2);
303             }
304              
305             sub assert_deep_not_equals {
306 0     0 0 0 my ($self, $arg1, $arg2, $msg) = @_;
307              
308 0 0 0     0 __croak 'Both arguments were not references', $msg unless ref $arg1 and ref $arg2;
309              
310 0         0 local @Data_Stack = ();
311 0         0 local %Seen_Refs = ();
312 0 0       0 __croak $self->_format_stack(@Data_Stack), $msg if $self->_deep_check($arg1, $arg2);
313             }
314              
315             sub _deep_check {
316 160     160   234 my ($self, $e1, $e2) = @_;
317              
318 160 100 66     507 if ( ! defined $e1 || ! defined $e2 ) {
319 9 100 66     31 return 1 if !defined $e1 && !defined $e2;
320 8         23 push @Data_Stack, { vals => [$e1, $e2] };
321 8         18 return 0;
322             }
323              
324 151 100       446 return 1 if $e1 eq $e2;
325 96 100 100     410 if ( ref $e1 && ref $e2 ) {
326 84         160 my $e2_ref = "$e2";
327 84 100 100     283 return 1 if defined $Seen_Refs{$e1} && $Seen_Refs{$e1} eq $e2_ref;
328 78         228 $Seen_Refs{$e1} = $e2_ref;
329             }
330              
331 90 100 100     697 if (ref $e1 eq 'ARRAY' and ref $e2 eq 'ARRAY') {
    100 100        
    50 33        
    100 66        
332 35         100 return $self->_eq_array($e1, $e2);
333             }
334             elsif (ref $e1 eq 'HASH' and ref $e2 eq 'HASH') {
335 29         81 return $self->_eq_hash($e1, $e2);
336             }
337             elsif (ref $e1 eq 'REF' and ref $e2 eq 'REF') {
338 0         0 push @Data_Stack, { type => 'REF', vals => [$e1, $e2] };
339 0         0 my $ok = $self->_deep_check($$e1, $$e2);
340 0 0       0 pop @Data_Stack if $ok;
341 0         0 return $ok;
342             }
343             elsif (ref $e1 eq 'SCALAR' and ref $e2 eq 'SCALAR') {
344 6         21 push @Data_Stack, { type => 'REF', vals => [$e1, $e2] };
345 6         16 return $self->_deep_check($$e1, $$e2);
346             }
347             else {
348 20         73 push @Data_Stack, { vals => [$e1, $e2] };
349 20         63 return 0;
350             }
351             }
352              
353             sub _eq_array {
354 35     35   91 my ($self, $a1, $a2) = @_;
355 35 50       120 return 1 if $a1 eq $a2;
356              
357 35         46 my $ok = 1;
358 35 100       80 my $max = $#$a1 > $#$a2 ? $#$a1 : $#$a2;
359 35         201 for (0..$max) {
360 65 100       151 my $e1 = $_ > $#$a1 ? $DNE : $a1->[$_];
361 65 100       129 my $e2 = $_ > $#$a2 ? $DNE : $a2->[$_];
362              
363 65         252 push @Data_Stack, { type => 'ARRAY', idx => $_, vals => [$e1, $e2] };
364 65         156 $ok = $self->_deep_check($e1,$e2);
365 65 100       139 pop @Data_Stack if $ok;
366              
367 65 100       203 last unless $ok;
368             }
369 35         168 return $ok;
370             }
371              
372             sub _eq_hash {
373 29     29   41 my ($self, $a1, $a2) = @_;
374 29 50       78 return 1 if $a1 eq $a2;
375              
376 29         36 my $ok = 1;
377 29 100       87 my $bigger = keys %$a1 > keys %$a2 ? $a1 : $a2;
378 29         91 foreach my $k (sort keys %$bigger) {
379 51 50       123 my $e1 = exists $a1->{$k} ? $a1->{$k} : $DNE;
380 51 100       108 my $e2 = exists $a2->{$k} ? $a2->{$k} : $DNE;
381              
382 51         215 push @Data_Stack, { type => 'HASH', idx => $k, vals => [$e1, $e2] };
383 51         121 $ok = $self->_deep_check($e1, $e2);
384 51 100       112 pop @Data_Stack if $ok;
385              
386 51 100       154 last unless $ok;
387             }
388              
389 29         124 return $ok;
390             }
391              
392             sub _format_stack {
393 28     28   51 my ($self, @Stack) = @_;
394              
395 28         34 my $var = '$FOO';
396 28         35 my $did_arrow = 0;
397 28         41 foreach my $entry (@Stack) {
398 70   100     205 my $type = $entry->{type} || '';
399 70         97 my $idx = $entry->{'idx'};
400 70 100       220 if( $type eq 'HASH' ) {
    100          
    100          
401 18 100       43 $var .= "->" unless $did_arrow++;
402 18         40 $var .= "{$idx}";
403             }
404             elsif( $type eq 'ARRAY' ) {
405 20 100       47 $var .= "->" unless $did_arrow++;
406 20         46 $var .= "[$idx]";
407             }
408             elsif( $type eq 'REF' ) {
409 4         10 $var = "\${$var}";
410             }
411             }
412              
413 28         45 my @vals = @{$Stack[-1]{vals}}[0,1];
  28         73  
414              
415 28         44 my @vars = ();
416 28         92 ($vars[0] = $var) =~ s/\$FOO/ \$a/;
417 28         155 ($vars[1] = $var) =~ s/\$FOO/ \$b/;
418              
419 28         57 my $out = "Structures begin differing at:\n";
420 28         65 foreach my $idx (0..$#vals) {
421 56         70 my $val = $vals[$idx];
422 56 100       243 $vals[$idx] = !defined $val ? 'undef' :
    100          
423             $val eq $DNE ? 'Does not exist'
424             : "'$val'";
425             }
426              
427 28         83 $out .= "$vars[0] = $vals[0]\n";
428 28         56 $out .= "$vars[1] = $vals[1]";
429              
430 28         109 return $out;
431             }
432              
433 1     1   639 BEGIN { $INC{'Test/Unit/TestCase.pm'} = __FILE__; }
434             }
435              
436             {
437             package Test::Unit::Result;
438             our $VERSION = $Test::Unit::Lite::VERSION;
439              
440             sub new {
441 6     6 0 12 my ($class) = @_;
442 6         27 my $self = {
443             'messages' => [],
444             'errors' => 0,
445             'failures' => 0,
446             'passes' => 0,
447             };
448              
449 6         18 return bless $self => $class;
450             }
451              
452             sub messages {
453 45     45 0 50 my ($self) = @_;
454 45         111 return $self->{messages};
455             }
456              
457             sub errors {
458 8     8 0 10 my ($self) = @_;
459 8         25 return $self->{errors};
460             }
461              
462             sub failures {
463 7     7 0 8 my ($self) = @_;
464 7         31 return $self->{failures};
465             }
466              
467             sub passes {
468 0     0 0 0 my ($self) = @_;
469 0         0 return $self->{passes};
470             }
471              
472             sub add_error {
473 2     2 0 4 my ($self, $test, $message, $runner) = @_;
474 2         4 $self->{errors}++;
475 2         8 my $result = {test => $test, type => 'ERROR', message => $message};
476 2         3 push @{$self->messages}, $result;
  2         6  
477 2 50       10 $runner->print_error($result) if defined $runner;
478             }
479              
480             sub add_failure {
481 1     1 0 3 my ($self, $test, $message, $runner) = @_;
482 1         2 $self->{failures}++;
483 1         4 my $result = {test => $test, type => 'FAILURE', message => $message};
484 1         2 push @{$self->messages}, $result;
  1         3  
485 1 50       15 $runner->print_failure($result) if defined $runner;
486             }
487              
488             sub add_pass {
489 39     39 0 69 my ($self, $test, $message, $runner) = @_;
490 39         76 $self->{passes}++;
491 39         137 my $result = {test => $test, type => 'PASS', message => $message};
492 39         55 push @{$self->messages}, $result;
  39         83  
493 39 50       142 $runner->print_pass($result) if defined $runner;
494             }
495              
496 1     1   863 BEGIN { $INC{'Test/Unit/Result.pm'} = __FILE__; }
497             }
498              
499             {
500             package Test::Unit::TestSuite;
501             our $VERSION = $Test::Unit::Lite::VERSION;
502              
503             sub empty_new {
504 6     6 0 31 my ($class, $name) = @_;
505 6 100       28 my $self = {
506             'name' => defined $name ? $name : 'Test suite',
507             'units' => [],
508             };
509              
510 6         33 return bless $self => $class;
511             }
512              
513             sub new {
514 3     3 0 18 my ($class, $test) = @_;
515              
516 3         15 my $self = {
517             'name' => 'Test suite',
518             'units' => [],
519             };
520              
521 3 100 66     17 if (defined $test and not ref $test) {
    50          
522             # untaint $test
523 2         7 $test =~ /([A-Za-z0-9:-]*)/;
524 2         6 $test = $1;
525 1     1   6 eval "use $test;";
  1     1   2  
  1         17  
  1         5  
  1         2  
  1         10  
  2         121  
526 2 50       8 die if $@;
527             }
528             elsif (not defined $test) {
529 1         2 $test = $class;
530             }
531              
532 3 100 66     45 if (defined $test and $test->isa('Test::Unit::TestSuite')) {
    50 33        
533 1 50       4 $class = ref $test ? ref $test : $test;
534 1 50       3 $self->{name} = $test->name if ref $test;
535 1 50       14 $self->{units} = $test->units if ref $test;
536             }
537             elsif (defined $test and $test->isa('Test::Unit::TestCase')) {
538 2 50       7 $class = ref $test ? ref $test : $test;
539 2         7 $self->{units} = [ $test ];
540             }
541             else {
542 0         0 require Carp;
543 0         0 Carp::croak(sprintf("usage: %s->new([CLASSNAME | TEST])\n", __PACKAGE__));
544             }
545              
546 3         18 return bless $self => $class;
547             }
548              
549             sub name {
550 1     1 0 9 return $_[0]->{name};
551             }
552              
553             sub units {
554 8     8 0 23 return $_[0]->{units};
555             }
556              
557             sub add_test {
558 18     18 0 31 my ($self, $unit) = @_;
559              
560 18 100       43 if (not ref $unit) {
561             # untaint $unit
562 16         44 $unit =~ /([A-Za-z0-9:-]*)/;
563 16         34 $unit = $1;
564 1     1   1001 eval "use $unit;";
  1     1   1106  
  1     1   15  
  1     1   684  
  1     1   282  
  1     1   14  
  1     1   740  
  1     1   296  
  1     1   16  
  1     1   757  
  1     1   660  
  1     1   15  
  1     1   870  
  1     1   5571  
  1     1   26  
  1     1   842  
  1         212  
  1         21  
  1         686  
  1         3381  
  1         23  
  1         8  
  1         2  
  1         13  
  1         1092  
  1         129  
  1         18  
  1         994  
  1         346  
  1         15  
  1         737  
  1         329  
  1         16  
  1         817  
  1         4213  
  1         21  
  1         790  
  1         340  
  1         17  
  1         7  
  1         2  
  1         12  
  1         6  
  1         3  
  1         10  
  1         5  
  1         2  
  1         84  
  16         837  
565 16 50       62 die if $@;
566 16 100       687 return unless $unit->isa('Test::Unit::TestCase');
567             }
568              
569 17 100       23 return push @{ $self->{units} }, ref $unit ? $unit : $unit->new;
  17         173  
570             }
571              
572             sub count_test_cases {
573 4     4 0 8 my ($self) = @_;
574              
575 4         5 my $plan = 0;
576              
577 4         40 foreach my $unit (@{ $self->units }) {
  4         11  
578 15         16 $plan += scalar @{ $unit->list_tests };
  15         74  
579             }
580 4         300 return $plan;
581             }
582              
583             sub run {
584 4     4 0 7 my ($self, $result, $runner) = @_;
585              
586 4 50       11 die "Undefined result object" unless defined $result;
587              
588 4         6 foreach my $unit (@{ $self->units }) {
  4         10  
589 15         24 foreach my $test (@{ $unit->list_tests }) {
  15         65  
590 42 50       163 my $unit_test = (ref $unit ? ref $unit : $unit) . '::' . $test;
591 42         49 my $add_what;
592 42         55 my $e = '';
593 42         53 eval {
594 42         134 $unit->set_up;
595             };
596 42 100       96 if ($@) {
597 2         4 $e = "$@";
598 2         4 $add_what = 'add_error';
599             }
600             else {
601 40         46 eval {
602 40         177 $unit->$test;
603             };
604 40 100       5383 if ($@) {
605 1         3 $e = "$@";
606 1         2 $add_what = 'add_failure';
607             }
608             else {
609 39         61 $add_what = 'add_pass';
610             };
611             };
612 42         49 eval {
613 42         130 $unit->tear_down;
614             };
615 42 100       105 if ($@) {
616 1         2 $e .= "$@";
617 1         2 $add_what = 'add_error';
618             };
619 42         116 $result->$add_what($unit_test, $e, $runner);
620             }
621             }
622 4         35 return;
623             }
624              
625 1     1   1101 BEGIN { $INC{'Test/Unit/TestSuite.pm'} = __FILE__; }
626             }
627              
628             {
629             package Test::Unit::TestRunner;
630             our $VERSION = $Test::Unit::Lite::VERSION;
631              
632             sub new {
633 6     6 0 152 my ($class, $fh_out, $fh_err) = @_;
634 6 100       19 $fh_out = \*STDOUT unless defined $fh_out;
635 6 100       17 $fh_err = \*STDERR unless defined $fh_err;
636 6         17 _autoflush($fh_out);
637 6         12 _autoflush($fh_err);
638 6         22 my $self = {
639             'suite' => undef,
640             'fh_out' => $fh_out,
641             'fh_err' => $fh_err,
642             };
643 6         30 return bless $self => $class;
644             }
645              
646             sub fh_out {
647 62     62 0 83 my ($self) = @_;
648 62         10674 return $self->{fh_out};
649             }
650              
651             sub fh_err {
652 0     0 0 0 my ($self) = @_;
653 0         0 return $self->{fh_err};
654             }
655              
656             sub result {
657 0     0 0 0 my ($self) = @_;
658 0         0 return $self->{result};
659             }
660              
661             sub _autoflush {
662 12     12   19 my ($fh) = @_;
663 12         29 my $old_fh = select $fh;
664 12         26 $| = 1;
665 12         30 select $old_fh;
666             }
667              
668             sub suite {
669 11     11 0 16 my ($self) = @_;
670 11         47 return $self->{suite};
671             }
672              
673 3     3 0 5 sub print_header {
674             }
675              
676             sub print_error {
677 2     2 0 3 my ($self, $result) = @_;
678 2         3 print { $self->fh_out } "E";
  2         6  
679             }
680              
681             sub print_failure {
682 1     1 0 2 my ($self, $result) = @_;
683 1         2 print { $self->fh_out } "F";
  1         2  
684             }
685              
686             sub print_pass {
687 0     0 0 0 my ($self, $result) = @_;
688 0         0 print { $self->fh_out } ".";
  0         0  
689             }
690              
691             sub print_footer {
692 3     3 0 5 my ($self, $result) = @_;
693 3         6 printf { $self->fh_out } "\nTests run: %d", $self->suite->count_test_cases;
  3         7  
694 3 100       26 if ($result->errors) {
695 2         4 printf { $self->fh_out } ", Errors: %d", $result->errors;
  2         5  
696             }
697 3 100       18 if ($result->failures) {
698 1         2 printf { $self->fh_out } ", Failures: %d", $result->failures;
  1         4  
699             }
700 3         9 print { $self->fh_out } "\n";
  3         7  
701 3 100       18 if ($result->errors) {
702 2         4 print { $self->fh_out } "\nERRORS!!!\n\n";
  2         5  
703 2         11 foreach my $message (@{ $result->messages }) {
  2         6  
704 2 50       8 if ($message->{type} eq 'ERROR') {
705 2         13 printf { $self->fh_out } "%s\n%s:\n\n%s\n",
  2         6  
706             '-' x 78,
707             $message->{test},
708             $message->{message};
709             }
710             }
711 2         19 printf { $self->fh_out } "%s\n", '-' x 78;
  2         5  
712             }
713 3 100       18 if ($result->failures) {
714 1         1 print { $self->fh_out } "\nFAILURES!!!\n\n";
  1         3  
715 1         5 foreach my $message (@{ $result->messages }) {
  1         3  
716 1 50       4 if ($message->{type} eq 'FAILURE') {
717 1         4 printf { $self->fh_out } "%s\n%s:\n\n%s\n",
  1         2  
718             '-' x 78,
719             $message->{test},
720             $message->{message};
721             }
722             }
723 1         10 printf { $self->fh_out } "%s\n", '-' x 78;
  1         3  
724             }
725             }
726              
727             sub start {
728 6     6 0 33 my ($self, $test) = @_;
729              
730 6         32 my $result = Test::Unit::Result->new;
731              
732             # untaint $test
733 6         26 $test =~ /([A-Za-z0-9:-]*)/;
734 6         18 $test = $1;
735 1     1   10 eval "use $test;";
  1     1   3  
  1     1   26  
  1     1   920  
  1     1   501  
  1     1   17  
  1         666  
  1         60  
  1         15  
  1         1042  
  1         270  
  1         17  
  1         772  
  1         210  
  1         14  
  1         763  
  1         183  
  1         14  
  6         477  
736 6 50       24 die if $@;
737              
738 6 100       79 if ($test->isa('Test::Unit::TestSuite')) {
    100          
739 1         6 $self->{suite} = $test->suite;
740             }
741             elsif ($test->isa('Test::Unit::TestCase')) {
742 3         17 $self->{suite} = Test::Unit::TestSuite->empty_new;
743 3         9 $self->suite->add_test($test);
744             }
745             else {
746 2         20 die "Unknown test $test\n";
747             }
748              
749 4         15 $self->print_header;
750 4         11 $self->suite->run($result, $self);
751 4         15 $self->print_footer($result);
752             }
753              
754 1     1   193 BEGIN { $INC{'Test/Unit/TestRunner.pm'} = __FILE__; }
755             }
756              
757             {
758             package Test::Unit::HarnessUnit;
759             our $VERSION = $Test::Unit::Lite::VERSION;
760              
761 1     1   10 use base 'Test::Unit::TestRunner';
  1         2  
  1         562  
762              
763             sub print_header {
764 1     1 0 2 my ($self) = @_;
765 1         2 print { $self->fh_out } "STARTING TEST RUN\n";
  1         9  
766 1         4 printf { $self->fh_out } "1..%d\n", $self->suite->count_test_cases;
  1         4  
767             }
768              
769             sub print_error {
770 0     0 0 0 my ($self, $result) = @_;
771 0         0 printf { $self->fh_out } "not ok %s %s\n", $result->{type}, $result->{test};
  0         0  
772 0         0 print { $self->fh_err } join("\n# ", split /\n/, "# " . $result->{message}), "\n";
  0         0  
773             }
774              
775             sub print_failure {
776 0     0 0 0 my ($self, $result) = @_;
777 0         0 printf { $self->fh_out } "not ok %s %s\n", $result->{type}, $result->{test};
  0         0  
778 0         0 print { $self->fh_err } join("\n# ", split /\n/, "# " . $result->{message}), "\n";
  0         0  
779             }
780              
781             sub print_pass {
782 39     39 0 55 my ($self, $result) = @_;
783 39         42 printf { $self->fh_out } "ok %s %s\n", $result->{type}, $result->{test};
  39         93  
784             }
785              
786 1     1 0 0 sub print_footer {
787             }
788              
789 1     1   74 BEGIN { $INC{'Test/Unit/HarnessUnit.pm'} = __FILE__; }
790             }
791              
792             {
793             package Test::Unit::Debug;
794             our $VERSION = $Test::Unit::Lite::VERSION;
795              
796 1     1   53 BEGIN { $INC{'Test/Unit/Debug.pm'} = __FILE__; }
797             }
798              
799             {
800             package Test::Unit::Lite::AllTests;
801             our $VERSION = $Test::Unit::Lite::VERSION;
802              
803 1     1   12 use base 'Test::Unit::TestSuite';
  1         3  
  1         78  
804              
805 1     1   6 use Cwd ();
  1         2  
  1         26  
806 1     1   6 use File::Find ();
  1         2  
  1         15  
807 1     1   7 use File::Basename ();
  1         1  
  1         21  
808 1     1   6 use File::Spec ();
  1         2  
  1         441  
809              
810             sub suite {
811 1     1 0 3 my $class = shift;
812 1         7 my $suite = Test::Unit::TestSuite->empty_new('All Tests');
813              
814 1 50       7 my $cwd = ${^TAINT} ? do { local $_=Cwd::getcwd; /(.*)/; $1 } : '.';
  0         0  
  0         0  
  0         0  
815 1         22 my $dir = File::Spec->catdir($cwd, 't', 'tlib');
816 1         13 my $depth = scalar File::Spec->splitdir($dir);
817              
818 1         3 push @INC, $dir;
819              
820             File::Find::find({
821             wanted => sub {
822 31     31   191 my $path = File::Spec->canonpath($File::Find::name);
823 31 100       586 return unless $path =~ s/(Test)\.pm$/$1/;
824 13         92 my @path = File::Spec->splitdir($path);
825 13         31 splice @path, 0, $depth;
826 13 50       37 return unless scalar @path > 0;
827 13         32 my $class = join '::', @path;
828 13 50       26 return unless $class;
829 13 50       35 return if $class =~ /^Test::Unit::/;
830 13 50 33     40 return if @ARGV and $class !~ $ARGV[0];
831 13         34 $suite->add_test($class);
832             },
833 1   50     117 no_chdir => 1,
834             }, $dir || '.');
835              
836 1         19 return $suite;
837             }
838              
839 1     1   49 BEGIN { $INC{'Test/Unit/Lite/AllTests.pm'} = __FILE__; }
840             }
841              
842              
843             1;
844              
845              
846             __END__