File Coverage

blib/lib/Test/AllModules.pm
Criterion Covered Total %
statement 112 122 91.8
branch 48 58 82.7
condition 11 18 61.1
subroutine 17 17 100.0
pod 1 1 100.0
total 189 216 87.5


line stmt bran cond sub pod time code
1             package Test::AllModules;
2 24     24   223718 use strict;
  24         256  
  24         704  
3 23     23   126 use warnings;
  23         37  
  23         702  
4 23     23   12429 use Module::Pluggable::Object;
  23         237478  
  23         960  
5 23     23   16038 use Test::More ();
  23         1502262  
  23         4551  
6              
7             our $VERSION = '0.18';
8              
9             my $USE_OK = sub {
10 6     6   2741 eval "use $_[0];"; ## no critic
  6         760  
  6         139  
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 23     23   293 my $class = shift;
38              
39 23         72 my $caller = caller;
40              
41 23     23   312 no strict 'refs'; ## no critic
  23         54  
  23         19217  
42 23         74 for my $func (qw/ all_ok /) {
43 23         46 *{"${caller}::$func"} = \&{"Test::AllModules::$func"};
  23         3318  
  23         124  
44             }
45             }
46              
47             sub all_ok {
48 21     21 1 2799 my %param = @_;
49              
50 21         70 my $search_path = delete $param{search_path};
51 21   66     183 my $use_ok = delete $param{use} || $param{use_ok};
52 21   66     177 my $require_ok = delete $param{require} || $param{require_ok};
53 21         53 my $check = delete $param{check};
54 21         46 my $checks = delete $param{checks};
55 21         42 my $except = delete $param{except};
56 21         48 my $lib = delete $param{lib};
57 21         95 my $fork = delete $param{fork};
58 21         48 my $shuffle = delete $param{shuffle};
59 21         48 my $show_version = delete $param{show_version};
60 21         40 my $no_import = delete $param{no_import};
61 21         37 my $before_hook = delete $param{before_hook};
62 21         39 my $after_hook = delete $param{after_hook};
63              
64 21 50 33     60 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 21         72 my @checks;
70 21 50       153 push @checks, +{ test => $no_import ? $USE_NO_IMPORT_OK : $USE_OK, name => 'use: ' } if $use_ok;
    100          
71 21 100       82 push @checks, +{ test => $REQUIRE_OK, name => 'require: ' } if $require_ok;
72              
73 21 100       91 if (ref($check) eq 'CODE') {
74 1         5 push @checks, +{ test => $check, name => '', };
75             }
76             else {
77 20 100       74 for my $code ( $check, @{ $checks || [] } ) {
  20         178  
78 26 100       51 my ($name) = keys %{$code || +{}};
  26         212  
79 26 100       121 my $test = $name ? $code->{$name} : undef;
80 26 100       143 if (ref($test) eq 'CODE') {
81 17         97 push @checks, +{ test => $test, name => "$name: ", };
82             }
83             }
84             }
85              
86 21 50       78 unless ($search_path) {
87 0         0 Test::More::plan skip_all => 'no search path';
88 0         0 exit;
89             }
90              
91 21         114 Test::More::plan('no_plan');
92 21 100       7919 my @exceptions = @{ $except || [] };
  21         149  
93              
94 21 100       93 if ($fork) {
95 8         5544 require Test::SharedFork;
96 8         435756 Test::More::note("Tests run under forking. Parent PID=$$");
97             }
98              
99 21         5615 my $count = 0;
100 21         188 for my $class (
101 43         150 grep { !_is_excluded( $_, @exceptions ) }
102             _classes($search_path, $lib, $shuffle) ) {
103 35         472 $count++;
104 35         225 for my $code (@checks) {
105 40 50 66     273 next if $before_hook && $before_hook->($code, $class, $count);
106 40         1031 my $ret = _exec_test($code, $class, $count, $fork, $show_version);
107 34 100       392 $after_hook && $after_hook->($ret, $code, $class, $count);
108             }
109              
110             }
111              
112 15 100       789 Test::More::note( "total: $count module". ($count > 1 ? 's' : '') );
113             }
114              
115             sub _exec_test {
116 40     40   220 my ($code, $class, $count, $fork, $show_version) = @_;
117              
118 40         81 my $ret;
119              
120 40 100       148 unless ($fork) {
121 22         70 $ret = _ok($code, $class, $count, undef, $show_version);
122 22         49 return $ret;
123             }
124              
125 18         17856 my $pid = fork();
126 18 50       1068 die 'could not fork' unless defined $pid;
127              
128 18 100       561 if ($pid) {
129 12         4071357 waitpid($pid, 0);
130             }
131             else {
132 6         1083 $ret = _ok($code, $class, $count, $fork, $show_version);
133 6         17000 exit;
134             }
135              
136 12         679 return $ret;
137             }
138              
139             sub _ok {
140 28     28   280 my ($code, $class, $count, $fork, $show_version) = @_;
141              
142 28 100 100     724 my $test_name = "$code->{name}$class". ($fork && $fork == 2 ? "(PID=$$)" : '');
143              
144 28         76 my $ret;
145 28         181 eval {
146 28         434 $ret = $code->{test}->($class, $count);
147             };
148              
149 28 50       14480 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 28 50       316 if ( Test::More::ok($ret, $test_name) ) {
156 28 100       24041 if ($show_version) {
157 23     23   206 no strict 'refs'; ## no critic
  23         51  
  23         11493  
158 2 100       4 if ( my $version = ${"$class\::VERSION"} ) {
  2         12  
159 1         5 Test::More::note("$class $version");
160             }
161             }
162 28         470 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 22     22   220 my ($search_path, $lib, $shuffle) = @_;
174              
175 22 100       47 local @INC = @{ $lib || ['lib'] };
  22         273  
176 22         361 my $finder = Module::Pluggable::Object->new(
177             search_path => $search_path,
178             );
179 22         318 my @classes = ( $search_path, $finder->plugins );
180              
181 22 100       20072 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   24 map { $_[$_->[0]] } sort { $a->[1] <=> $b->[1] } map { [$_ , rand(1)] } 0..$#_;
  3         27  
  2         14  
  3         62  
188             }
189              
190             # This '_any' method copied from List::MoreUtils.
191             sub _any (&@) { ## no critic
192 43     43   99 my $f = shift;
193              
194 43         109 foreach ( @_ ) {
195 5 100       7 return 1 if $f->();
196             }
197 41         206 return;
198             }
199              
200             sub _is_excluded {
201 43     43   116 my ( $module, @exceptions ) = @_;
202 43 100   5   233 _any { $module eq $_ || $module =~ /$_/ } @exceptions;
  5         53  
203             }
204              
205             sub _is_win {
206 21 50 33 21   298 return ($^O && $^O eq 'MSWin32') ? 1 : 0;
207             }
208              
209             1;
210              
211             __END__