File Coverage

blib/lib/Test/Pod/Coverage/TrustMe.pm
Criterion Covered Total %
statement 102 109 93.5
branch 30 42 71.4
condition 17 35 48.5
subroutine 13 13 100.0
pod 3 3 100.0
total 165 202 81.6


line stmt bran cond sub pod time code
1             package Test::Pod::Coverage::TrustMe;
2 15     15   1703867 use strict;
  15         38  
  15         638  
3 15     15   77 use warnings;
  15         101  
  15         1517  
4              
5             our $VERSION = '0.002001';
6             $VERSION =~ tr/_//d;
7              
8 15     15   117 use File::Spec ();
  15         33  
  15         352  
9 15     15   98 use Cwd ();
  15         74  
  15         485  
10 15     15   839 use Test::Builder ();
  15         113806  
  15         315  
11              
12 15     15   144 use Exporter ();
  15         41  
  15         28742  
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 2     2   12 my $dir = File::Spec->curdir;
23 2         11 my $try = 5;
24 2         13 while ($try--) {
25 2         18 my $blib = File::Spec->catdir($dir, 'blib');
26 2 50 33     123 if (
      33        
27             -d $blib
28             && -d File::Spec->catdir($blib, 'arch')
29             && -d File::Spec->catdir($blib, 'lib')
30             ) {
31 2         15 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 2     2   39 my $dir = File::Spec->curdir;
41 2         6 my $try = 5;
42 2         8 while ($try--) {
43 2         27 my $lib = File::Spec->catdir($dir, 'lib');
44 2 50       94 if (-d $lib) {
45 2         87 my @parts = File::Spec->splitdir(Cwd::realpath($lib));
46 2 50 33     33 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 2         15 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 2     2   6 my %find;
64 2 50       8 if (my $lib = _lib()) {
65 2         44 $find{Cwd::realpath($lib)}++;
66             }
67 2 50       10 if (my $blib = _blib()) {
68 2         62 $find{Cwd::realpath(File::Spec->catdir($blib, 'arch'))}++;
69 2         56 $find{Cwd::realpath(File::Spec->catdir($blib, 'lib'))}++;
70             }
71              
72 2         676 my @dirs = grep $find{Cwd::realpath($_)}, @INC;
73 2         44 return @dirs;
74             }
75              
76             sub all_modules {
77 2     2 1 7 my @dirs = @_;
78 2 50       13 @dirs = _base_dirs
79             if !@dirs;
80              
81 2         44 my %searched;
82             my @modules;
83 2         0 my %modules;
84              
85 2         14 my @search = map [$_], @dirs;
86 2         10 while (my $search = shift @search) {
87 34         127 my ($dir, @pre) = @$search;
88             next
89 34 100       2226 if $searched{Cwd::realpath($dir)}++;
90 32 50       1159 opendir my $dh, $dir or die;
91 32         1317 my @found = File::Spec->no_upwards(readdir $dh);
92 32         533 closedir $dh;
93              
94 32   66     477 my @mods = grep /\.pm\z/ && -f File::Spec->catfile($dir, $_), @found;
95 32         157 s/\.pm\z// for @mods;
96             push @modules,
97 32         112 grep !$modules{$_}++,
98             map join('::', @pre, $_),
99             grep !/\W/,
100             @mods;
101              
102 32         1183 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 2         24 return @modules;
111             }
112              
113             sub _fh_has_encoding {
114 6     6   16 my $fh = shift;
115             return !!(
116 6   33     88 defined &PerlIO::get_layers
117             and grep $_ eq 'utf8', PerlIO::get_layers($fh)
118             );
119             }
120              
121             sub pod_coverage_ok {
122 26     26 1 2486023 my $module = shift;
123 26 100       138 my %opts = ref $_[0] eq 'HASH' ? %{ +shift } : ();
  13         62  
124 26   66     153 my $msg = shift || "Pod coverage on $module";
125              
126 26         86 $opts{package} = $module;
127              
128 26   100     136 my $class = delete $opts{coverage_class} || 'Pod::Coverage::TrustMe';
129 26         174 (my $mod = "$class.pm") =~ s{::}{/}g;
130 26         5256 require $mod;
131              
132 26         569 my $cover = $class->new(%opts);
133              
134 26   66     244 our $Test ||= Test::Builder->new;
135 26         245 local $Test::Builder::Level = $Test::Builder::Level + 1;
136              
137 26         69 my $ok;
138             my $extra;
139 26         12898 my $rating = $cover->coverage;
140 26 100       8976 if (!defined $rating) {
141 3         20 my $why = $cover->why_unrated;
142             my $symbols
143             = $cover->can('symbols') ? $cover->symbols
144 3 100       31 : do {
145             # shim for using with Pod::Coverage subclasses rather than TrustMe
146 2         118 my @symbs = $cover->_get_syms($module);
147 2 50       568 $cover->why_unrated =~ /\Arequiring .* failed\z/
148             ? undef : { map +($_ => 1), @symbs };
149             };
150 3   66     32 $ok = $Test->ok( defined $symbols && !%$symbols, $msg );
151 3         1913 $extra = "$module: $why";
152             }
153             else {
154 23         472 $ok = $Test->is_eq((map sprintf('%3.0f%%', $_ * 100), $rating, 1), $msg);
155 23 100       28288 if (!$ok) {
156 3         34 $extra = join('',
157             "Naked subroutines:\n",
158             map " $_\n", sort $cover->uncovered,
159             );
160             }
161             }
162 26 100       112 if (defined $extra) {
163 6 100       126 my $fh = $ok ? $Test->output : $Test->_diag_fh;
164 6 50       1762 if (!_fh_has_encoding($fh)) {
165 6         25 utf8::encode($extra);
166             }
167 6 100       37 if ($ok) {
168 2         12 $Test->note( $extra );
169             }
170             else {
171 4         19 $Test->diag( $extra );
172             }
173             }
174 26         4023 return $ok;
175             }
176              
177             sub all_pod_coverage_ok {
178 2 100   2 1 460911 my %opts = ref $_[0] eq 'HASH' ? %{ +shift } : ();
  1         5  
179 2         8 my $dirs = delete $opts{dirs};
180 2 50       4 my @modules = all_modules(@{ $dirs || [] });
  2         22  
181              
182 2   33     32 our $Test ||= Test::Builder->new;
183 2         33 local $Test::Builder::Level = $Test::Builder::Level + 1;
184 2         5 my $ok = 1;
185              
186 2 50       8 if ( @modules ) {
187 2         14 $Test->plan( tests => scalar @modules );
188              
189 2         3413 for my $module ( @modules ) {
190 6 50       30 pod_coverage_ok( $module, @_ ) 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 2         221 return $ok;
199             }
200              
201             1;
202             __END__