1 package Test::Pod::_parser;
2 use base 'Pod::Simple';
5 sub _handle_element_start {
6 my($parser, $element_name, $attr_hash_r) = @_;
8 # Curiously, Pod::Simple supports L<text|scheme:...> rather well.
10 if( $element_name eq "L" and $attr_hash_r->{type} eq "url") {
11 $parser->{_state_of_concern}{'Lurl'} = $attr_hash_r->{to};
14 return $parser->SUPER::_handle_element_start(@_);
17 sub _handle_element_end {
18 my($parser, $element_name) = @_;
20 delete $parser->{_state_of_concern}{'Lurl'}
21 if $element_name eq "L" and exists $parser->{_state_of_concern}{'Lurl'};
23 return $parser->SUPER::_handle_element_end(@_);
27 my($parser, $text) = @_;
28 if( my $href = $parser->{_state_of_concern}{'Lurl'} ) {
29 if( $href ne $text ) {
30 my $line = $parser->line_count() -2; # XXX: -2, WHY WHY WHY??
32 $parser->whine($line, "L<text|scheme:...> is invalid according to perlpod");
36 return $parser->SUPER::_handle_text(@_);
47 Test::Pod - check for POD errors in files
55 our $VERSION = '1.40';
59 C<Test::Pod> lets you check the validity of a POD file, and report
60 its results in standard C<Test::Simple> fashion.
62 use Test::Pod tests => $num_tests;
63 pod_file_ok( $file, "Valid POD file" );
65 Module authors can include the following in a F<t/pod.t> file and
66 have C<Test::Pod> automatically find and check all POD files in a
70 eval "use Test::Pod 1.00";
71 plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
74 You can also specify a list of files to check, using the
75 C<all_pod_files()> function supplied:
79 eval "use Test::Pod 1.00";
80 plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
81 my @poddirs = qw( blib script );
82 all_pod_files_ok( all_pod_files( @poddirs ) );
84 Or even (if you're running under L<Apache::Test>):
88 eval "use Test::Pod 1.00";
89 plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
91 my @poddirs = qw( blib script );
92 use File::Spec::Functions qw( catdir updir );
94 all_pod_files( map { catdir updir, $_ } @poddirs )
99 Check POD files for errors or warnings in a test file, using
100 C<Pod::Simple> to do the heavy lifting.
112 '.hg' => 'Mercurial',
114 '.svn' => 'Subversion',
119 _sgbak => 'Vault/Fortress',
122 my $Test = Test::Builder->new;
128 for my $func ( qw( pod_file_ok all_pod_files all_pod_files_ok ) ) {
130 *{$caller."::".$func} = \&$func;
133 $Test->exported_to($caller);
137 sub _additional_test_pod_specific_checks {
138 my ($ok, $errata, $file) = @_;
145 =head2 pod_file_ok( FILENAME[, TESTNAME ] )
147 C<pod_file_ok()> will okay the test if the POD parses correctly. Certain
148 conditions are not reported yet, such as a file with no pod in it at all.
150 When it fails, C<pod_file_ok()> will show any pod checking errors as
153 The optional second argument TESTNAME is the name of the test. If it
154 is omitted, C<pod_file_ok()> chooses a default test name "POD test
161 my $name = @_ ? shift : "POD test for $file";
164 $Test->ok( 0, $name );
165 $Test->diag( "$file does not exist" );
169 my $checker = Test::Pod::_parser->new;
171 $checker->output_string( \my $trash ); # Ignore any output
172 $checker->parse_file( $file );
174 my $ok = !$checker->any_errata_seen;
175 $ok = _additional_test_pod_specific_checks( $ok, ($checker->{errata}||={}), $file );
177 $Test->ok( $ok, $name );
179 my $lines = $checker->{errata};
180 for my $line ( sort { $a<=>$b } keys %$lines ) {
181 my $errors = $lines->{$line};
182 $Test->diag( "$file ($line): $_" ) for @$errors;
189 =head2 all_pod_files_ok( [@files/@directories] )
191 Checks all the files in C<@files> for valid POD. It runs
192 L<all_pod_files()> on each file/directory, and calls the C<plan()>
193 function for you (one test for each function), so you can't have
194 already called C<plan>.
196 If C<@files> is empty or not passed, the function finds all POD
197 files in the F<blib> directory if it exists, or the F<lib> directory
198 if not. A POD file is one that ends with F<.pod>, F<.pl> and F<.pm>,
199 or any file where the first line looks like a shebang line.
201 If you're testing a module, just make a F<t/pod.t>:
204 eval "use Test::Pod 1.00";
205 plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
208 Returns true if all pod files are ok, or false if any fail.
212 sub all_pod_files_ok {
213 my @files = @_ ? @_ : all_pod_files();
215 $Test->plan( tests => scalar @files );
218 foreach my $file ( @files ) {
219 pod_file_ok( $file, $file ) or undef $ok;
224 =head2 all_pod_files( [@dirs] )
226 Returns a list of all the Perl files in I<$dir> and in directories
227 below. If no directories are passed, it defaults to F<blib> if
228 F<blib> exists, or else F<lib> if not. Skips any files in CVS,
229 .svn, .git and similar directories. See C<%Test::Pod::ignore_dirs>
236 =item * Any file that ends in F<.PL>, F<.pl>, F<.pm>, F<.pod> or F<.t>.
238 =item * Any file that has a first line with a shebang and "perl" on it.
242 The order of the files returned is machine-dependent. If you want them
243 sorted, you'll have to sort them yourself.
248 my @queue = @_ ? @_ : _starting_points();
252 my $file = shift @queue;
255 opendir DH, $file or next;
256 my @newfiles = readdir DH;
259 @newfiles = File::Spec->no_upwards( @newfiles );
260 @newfiles = grep { not exists $ignore_dirs{ $_ } } @newfiles;
262 foreach my $newfile (@newfiles) {
263 my $filename = File::Spec->catfile( $file, $newfile );
264 if ( -f $filename ) {
265 push @queue, $filename;
268 push @queue, File::Spec->catdir( $file, $newfile );
273 push @pod, $file if _is_perl( $file );
279 sub _starting_points {
280 return 'blib' if -e 'blib';
287 return 1 if $file =~ /\.PL$/;
288 return 1 if $file =~ /\.p(?:l|m|od)$/;
289 return 1 if $file =~ /\.t$/;
291 open my $fh, '<', $file or return;
295 return 1 if defined $first && ($first =~ /^#!.*perl/);
304 Note the changes that are being made.
306 Note that you no longer can test for "no pod".
310 Currently maintained by Andy Lester, C<< <andy at petdance.com> >>.
312 Originally by brian d foy.
314 =head1 ACKNOWLEDGEMENTS
321 for contributions and to C<brian d foy> for the original code.
325 Copyright 2006-2009, Andy Lester, All Rights Reserved.
327 You may use, modify, and distribute this package under the terms
328 as the Artistic License v2.0 or GNU Public License v2.0.