File Coverage

blib/lib/Test/Pod/Coverage/TrustMe.pm
Criterion Covered Total %
statement 101 109 92.6
branch 29 42 69.0
condition 17 35 48.5
subroutine 13 13 100.0
pod 3 3 100.0
total 163 202 80.6


line stmt bran cond sub pod time code
1             package Test::Pod::Coverage::TrustMe;
2 14     14   1140921 use strict;
  14         31  
  14         457  
3 14     14   49 use warnings;
  14         25  
  14         1067  
4              
5             our $VERSION = '0.002002';
6             $VERSION =~ tr/_//d;
7              
8 14     14   71 use File::Spec ();
  14         22  
  14         219  
9 14     14   53 use Cwd ();
  14         53  
  14         226  
10 14     14   878 use Test::Builder ();
  14         83968  
  14         263  
11              
12 14     14   103 use Exporter ();
  14         43  
  14         18381  
13             *import = \&Exporter::import;
14              
15             our @EXPORT = qw(
16             all_modules
17             pod_coverage_ok
18             all_pod_coverage_ok
19             );
20              
21             sub _blib {
22 1     1   10 my $dir = File::Spec->curdir;
23 1         4 my $try = 5;
24 1         4 while ($try--) {
25 1         5 my $blib = File::Spec->catdir($dir, 'blib');
26 1 50 33     37 if (
      33        
27             -d $blib
28             && -d File::Spec->catdir($blib, 'arch')
29             && -d File::Spec->catdir($blib, 'lib')
30             ) {
31 1         4 return $blib;
32             }
33              
34 0         0 $dir = File::Spec->catdir($dir, File::Spec->updir);
35             }
36 0         0 return undef;
37             }
38              
39             sub _lib {
40 1     1   13 my $dir = File::Spec->curdir;
41 1         2 my $try = 5;
42 1         3 while ($try--) {
43 1         11 my $lib = File::Spec->catdir($dir, 'lib');
44 1 50       24 if (-d $lib) {
45 1         29 my @parts = File::Spec->splitdir(Cwd::realpath($lib));
46 1 50 33     11 if (
      33        
      33        
47             @parts >= 2
48             && $parts[-1] eq 'lib'
49             && ($parts[-2] eq 't' || $parts[-2] eq 'xt')
50             ) {
51 0         0 next;
52             }
53              
54 1         4 return $lib;
55             }
56              
57 0         0 $dir = File::Spec->catdir($dir, File::Spec->updir);
58             }
59 0         0 return undef;
60             }
61              
62             sub _base_dirs {
63 1     1   1 my %find;
64 1 50       20 if (my $lib = _lib()) {
65 1         11 $find{Cwd::realpath($lib)}++;
66             }
67 1 50       4 if (my $blib = _blib()) {
68 1         16 $find{Cwd::realpath(File::Spec->catdir($blib, 'arch'))}++;
69 1         45 $find{Cwd::realpath(File::Spec->catdir($blib, 'lib'))}++;
70             }
71              
72 1         189 my @dirs = grep $find{Cwd::realpath($_)}, @INC;
73 1         4 return @dirs;
74             }
75              
76             sub all_modules {
77 1     1 1 2 my @dirs = @_;
78 1 50       5 @dirs = _base_dirs
79             if !@dirs;
80              
81 1         3 my %searched;
82             my @modules;
83 1         0 my %modules;
84              
85 1         4 my @search = map [$_], @dirs;
86 1         3 while (my $search = shift @search) {
87 17         45 my ($dir, @pre) = @$search;
88             next
89 17 100       674 if $searched{Cwd::realpath($dir)}++;
90 16 50       322 opendir my $dh, $dir or die;
91 16         365 my @found = File::Spec->no_upwards(readdir $dh);
92 16         141 closedir $dh;
93              
94 16   66     108 my @mods = grep /\.pm\z/ && -f File::Spec->catfile($dir, $_), @found;
95 16         33 s/\.pm\z// for @mods;
96             push @modules,
97 16         35 grep !$modules{$_}++,
98             map join('::', @pre, $_),
99             grep !/\W/,
100             @mods;
101              
102 16         413 unshift @search,
103             map [ $_->[0], @pre, $_->[1] ],
104             grep -d $_->[0],
105             map [ File::Spec->catdir($dir, $_) => $_ ],
106             grep !/\W/,
107             @found;
108             }
109              
110 1         7 return @modules;
111             }
112              
113             sub _fh_has_encoding {
114 6     6   12 my $fh = shift;
115             return !!(
116 6   33     58 defined &PerlIO::get_layers
117             and grep $_ eq 'utf8', PerlIO::get_layers($fh)
118             );
119             }
120              
121             sub pod_coverage_ok {
122 23     23 1 1697659 my $module = shift;
123 23 100       95 my %opts = ref $_[0] eq 'HASH' ? %{ +shift } : ();
  16         51  
124 23   66     130 my $msg = shift || "Pod coverage on $module";
125              
126 23         57 $opts{package} = $module;
127              
128 23   100     83 my $class = delete $opts{coverage_class} || 'Pod::Coverage::TrustMe';
129 23         115 (my $mod = "$class.pm") =~ s{::}{/}g;
130 23         3547 require $mod;
131              
132 23         427 my $cover = $class->new(%opts);
133              
134 23   66     161 our $Test ||= Test::Builder->new;
135 23         137 local $Test::Builder::Level = $Test::Builder::Level + 1;
136              
137 23         39 my $ok;
138             my $extra;
139 23         10661 my $rating = $cover->coverage;
140 23 100       6377 if (!defined $rating) {
141 3         13 my $why = $cover->why_unrated;
142             my $symbols
143             = $cover->can('symbols') ? $cover->symbols
144 3 100       25 : do {
145             # shim for using with Pod::Coverage subclasses rather than TrustMe
146 2         117 my @symbs = $cover->_get_syms($module);
147 2 50       700 $cover->why_unrated =~ /\Arequiring .* failed\z/
148             ? undef : { map +($_ => 1), @symbs };
149             };
150 3   66     27 $ok = $Test->ok( defined $symbols && !%$symbols, $msg );
151 3         1708 $extra = "$module: $why";
152             }
153             else {
154 20         335 $ok = $Test->is_eq((map sprintf('%3.0f%%', $_ * 100), $rating, 1), $msg);
155 20 100       18393 if (!$ok) {
156 3         29 $extra = join('',
157             "Naked subroutines:\n",
158             map " $_\n", sort $cover->uncovered,
159             );
160             }
161             }
162 23 100       75 if (defined $extra) {
163 6 100       49 my $fh = $ok ? $Test->output : $Test->_diag_fh;
164 6 50       1281 if (!_fh_has_encoding($fh)) {
165 6         26 utf8::encode($extra);
166             }
167 6 100       27 if ($ok) {
168 2         9 $Test->note( $extra );
169             }
170             else {
171 4         12 $Test->diag( $extra );
172             }
173             }
174 23         2795 return $ok;
175             }
176              
177             sub all_pod_coverage_ok {
178 1 50   1 1 195045 my %opts = ref $_[0] eq 'HASH' ? %{ +shift } : ();
  0         0  
179 1         2 my $dirs = delete $opts{dirs};
180 1 50       2 my @modules = all_modules(@{ $dirs || [] });
  1         8  
181              
182 1   33     10 our $Test ||= Test::Builder->new;
183 1         8 local $Test::Builder::Level = $Test::Builder::Level + 1;
184 1         2 my $ok = 1;
185              
186 1 50       2 if ( @modules ) {
187 1         5 $Test->plan( tests => scalar @modules );
188              
189 1         699 for my $module ( @modules ) {
190 3 50       13 pod_coverage_ok( $module, \%opts, @_ ) or $ok = 0;
191             }
192             }
193             else {
194 0         0 $Test->plan( tests => 1 );
195 0         0 $Test->ok( 1, "No modules found." );
196             }
197              
198 1         92 return $ok;
199             }
200              
201             1;
202             __END__