File Coverage

blib/lib/Test/AllModules.pm
Criterion Covered Total %
statement 112 122 91.8
branch 47 58 81.0
condition 10 18 55.5
subroutine 17 17 100.0
pod 1 1 100.0
total 187 216 86.5


line stmt bran cond sub pod time code
1             package Test::AllModules;
2 22     22   205985 use strict;
  22         182  
  22         608  
3 22     22   119 use warnings;
  22         37  
  22         551  
4 22     22   10692 use Module::Pluggable::Object;
  22         211462  
  22         727  
5 22     22   12331 use Test::More ();
  22         1309945  
  22         4246  
6              
7             our $VERSION = '0.16';
8              
9             my $USE_OK = sub {
10 5     5   2001 eval "use $_[0];"; ## no critic
  5         600  
  5         97  
11             if (my $e = $@) {
12             Test::More::note($e);
13             return;
14             }
15             return 1;
16             };
17             my $USE_NO_IMPORT_OK = sub {
18             eval "use $_[0] qw//;"; ## no critic
19             if (my $e = $@) {
20             Test::More::note($e);
21             return;
22             }
23             return 1;
24             };
25              
26              
27             my $REQUIRE_OK = sub {
28             eval "require $_[0];"; ## no critic
29             if (my $e = $@) {
30             Test::More::note($e);
31             return;
32             }
33             return 1;
34             };
35              
36             sub import {
37 22     22   245 my $class = shift;
38              
39 22         64 my $caller = caller;
40              
41 22     22   235 no strict 'refs'; ## no critic
  22         53  
  22         17633  
42 22         64 for my $func (qw/ all_ok /) {
43 22         43 *{"${caller}::$func"} = \&{"Test::AllModules::$func"};
  22         3129  
  22         104  
44             }
45             }
46              
47             sub all_ok {
48 20     20 1 1937 my %param = @_;
49              
50 20         79 my $search_path = delete $param{search_path};
51 20   66     166 my $use_ok = delete $param{use} || $param{use_ok};
52 20   66     167 my $require_ok = delete $param{require} || $param{require_ok};
53 20         49 my $check = delete $param{check};
54 20         39 my $checks = delete $param{checks};
55 20         43 my $except = delete $param{except};
56 20         56 my $lib = delete $param{lib};
57 20         70 my $fork = delete $param{fork};
58 20         84 my $shuffle = delete $param{shuffle};
59 20         41 my $show_version = delete $param{show_version};
60 20         40 my $no_import = delete $param{no_import};
61 20         36 my $before_hook = delete $param{before_hook};
62 20         38 my $after_hook = delete $param{after_hook};
63              
64 20 50 33     54 if ( _is_win() && $fork ) {
65 0         0 Test::More::plan skip_all => 'The "fork" option is not supported in Windows';
66 0         0 exit;
67             }
68              
69 20         62 my @checks;
70 20 50       116 push @checks, +{ test => $no_import ? $USE_NO_IMPORT_OK : $USE_OK, name => 'use: ' } if $use_ok;
    100          
71 20 100       74 push @checks, +{ test => $REQUIRE_OK, name => 'require: ' } if $require_ok;
72              
73 20 100       70 if (ref($check) eq 'CODE') {
74 1         6 push @checks, +{ test => $check, name => '', };
75             }
76             else {
77 19 100       36 for my $code ( $check, @{ $checks || [] } ) {
  19         158  
78 25 100       47 my ($name) = keys %{$code || +{}};
  25         151  
79 25 100       105 my $test = $name ? $code->{$name} : undef;
80 25 100       125 if (ref($test) eq 'CODE') {
81 17         86 push @checks, +{ test => $test, name => "$name: ", };
82             }
83             }
84             }
85              
86 20 50       113 unless ($search_path) {
87 0         0 Test::More::plan skip_all => 'no search path';
88 0         0 exit;
89             }
90              
91 20         110 Test::More::plan('no_plan');
92 20 100       5842 my @exceptions = @{ $except || [] };
  20         136  
93              
94 20 100       88 if ($fork) {
95 8         4992 require Test::SharedFork;
96 8         394180 Test::More::note("Tests run under forking. Parent PID=$$");
97             }
98              
99 20         4974 my $count = 0;
100 20         159 for my $class (
101 41         143 grep { !_is_excluded( $_, @exceptions ) }
102             _classes($search_path, $lib, $shuffle) ) {
103 33         115 $count++;
104 33         126 for my $code (@checks) {
105 38 50 33     261 next if $before_hook && $before_hook->($code, $class, $count);
106 38         183 my $ret = _exec_test($code, $class, $count, $fork, $show_version);
107 32 50       349 $after_hook && $after_hook->($ret, $code, $class, $count);
108             }
109              
110             }
111              
112 14 100       386 Test::More::note( "total: $count module". ($count > 1 ? 's' : '') );
113             }
114              
115             sub _exec_test {
116 38     38   163 my ($code, $class, $count, $fork, $show_version) = @_;
117              
118 38         103 my $ret;
119              
120 38 100       125 unless ($fork) {
121 20         52 $ret = _ok($code, $class, $count, undef, $show_version);
122 20         46 return $ret;
123             }
124              
125 18         16032 my $pid = fork();
126 18 50       942 die 'could not fork' unless defined $pid;
127              
128 18 100       432 if ($pid) {
129 12         3784081 waitpid($pid, 0);
130             }
131             else {
132 6         863 $ret = _ok($code, $class, $count, $fork, $show_version);
133 6         14316 exit;
134             }
135              
136 12         581 return $ret;
137             }
138              
139             sub _ok {
140 26     26   219 my ($code, $class, $count, $fork, $show_version) = @_;
141              
142 26 100 100     641 my $test_name = "$code->{name}$class". ($fork && $fork == 2 ? "(PID=$$)" : '');
143              
144 26         112 my $ret;
145 26         129 eval {
146 26         387 $ret = $code->{test}->($class, $count);
147             };
148              
149 26 50       12798 if (my $e = $@) {
150 0         0 Test::More::fail($test_name);
151 0         0 Test::More::note("The Test failed: $e");
152 0         0 return;
153             }
154              
155 26 50       331 if ( Test::More::ok($ret, $test_name) ) {
156 26 100       20636 if ($show_version) {
157 22     22   191 no strict 'refs'; ## no critic
  22         51  
  22         10345  
158 2 100       4 if ( my $version = ${"$class\::VERSION"} ) {
  2         13  
159 1         4 Test::More::note("$class $version");
160             }
161             }
162 26         410 return 1; # ok
163             }
164             else {
165 0 0       0 my $got = defined $ret ? $ret : '';
166 0         0 Test::More::note("The Test did NOT return true value. got: $got");
167             }
168              
169 0         0 return;
170             }
171              
172             sub _classes {
173 21     21   201 my ($search_path, $lib, $shuffle) = @_;
174              
175 21 100       47 local @INC = @{ $lib || ['lib'] };
  21         249  
176 21         324 my $finder = Module::Pluggable::Object->new(
177             search_path => $search_path,
178             );
179 21         294 my @classes = ( $search_path, $finder->plugins );
180              
181 21 100       17561 return $shuffle ? _shuffle(@classes) : sort(@classes);
182             }
183              
184             # This '_shuffle' method copied
185             # from http://blog.nomadscafe.jp/archives/000246.html
186             sub _shuffle {
187 1     1   23 map { $_[$_->[0]] } sort { $a->[1] <=> $b->[1] } map { [$_ , rand(1)] } 0..$#_;
  3         27  
  2         13  
  3         46  
188             }
189              
190             # This '_any' method copied from List::MoreUtils.
191             sub _any (&@) { ## no critic
192 41     41   101 my $f = shift;
193              
194 41         92 foreach ( @_ ) {
195 5 100       11 return 1 if $f->();
196             }
197 39         175 return;
198             }
199              
200             sub _is_excluded {
201 41     41   93 my ( $module, @exceptions ) = @_;
202 41 100   5   176 _any { $module eq $_ || $module =~ /$_/ } @exceptions;
  5         50  
203             }
204              
205             sub _is_win {
206 20 50 33 20   252 return ($^O && $^O eq 'MSWin32') ? 1 : 0;
207             }
208              
209             1;
210              
211             __END__