1#!perl
2
3## Spellcheck as much as we can
4
5use 5.006;
6use strict;
7use warnings;
8use Test::More;
9select(($|=1,select(STDERR),$|=1)[1]);
10
11my (@testfiles, @perlfiles, @textfiles, @commentfiles, $fh);
12
13if (! $ENV{RELEASE_TESTING}) {
14	plan (skip_all =>  'Test skipped unless environment variable RELEASE_TESTING is set');
15}
16elsif (!eval { require Text::SpellChecker; 1 }) {
17	plan skip_all => 'Could not find Text::SpellChecker';
18}
19else {
20	opendir my $dir, 't' or die qq{Could not open directory 't': $!\n};
21	@testfiles = map { "t/$_" } grep { /^.+\.(t|pl)$/ } readdir $dir;
22	closedir $dir or die qq{Could not closedir "$dir": $!\n};
23
24	open my $fh, '<', 'MANIFEST' or die qq{Could not open the MANIFEST file: $!\n};
25	while (<$fh>) {
26		next unless /(.*\.pm)/;
27		push @perlfiles, $1;
28	}
29	close $fh or die qq{Could not close the MANIFEST file: $!\n};
30
31	@textfiles = qw/README Changes LICENSE/;
32
33	@commentfiles = (@testfiles, 'Makefile.PL', @perlfiles);
34
35	plan tests => @textfiles + @perlfiles + @commentfiles;
36}
37
38my %okword;
39my $file = 'Common';
40while (<DATA>) {
41	if (/^## (.+):/) {
42		$file = $1;
43		next;
44	}
45	next if /^#/ or ! /\w/;
46	for (split) {
47		++$okword{$file}{$_};
48	}
49}
50
51sub spellcheck {
52	my ($desc, $text, $sfile) = @_;
53	my $check = Text::SpellChecker->new(text => $text);
54	my %badword;
55	my $class = $sfile =~ /\.pm$/ ? 'Perl' : $sfile =~ /\.t$/ ? 'Test' : '';
56	while (my $word = $check->next_word) {
57		next if $okword{Common}{$word} or $okword{$sfile}{$word} or $okword{$class}{$word};
58		++$badword{$word};
59	}
60	my $count = keys %badword;
61	if (! $count) {
62		pass ("Spell check passed for $desc");
63		return;
64	}
65	fail ("Spell check failed for $desc. Bad words: $count");
66	for (sort keys %badword) {
67		diag "$_\n";
68	}
69	return;
70}
71
72
73## General spellchecking
74for my $file (@textfiles) {
75	if (!open $fh, '<', $file) {
76		fail (qq{Could not find the file "$file"!});
77	}
78	else {
79		{ local $/; $_ = <$fh>; }
80		close $fh or warn qq{Could not close "$file": $!\n};
81		spellcheck ($file => $_, $file);
82	}
83}
84
85## Now the embedded POD
86SKIP: {
87	if (!eval { require Pod::Spell; 1 }) {
88		my $files = @perlfiles;
89		skip ('Need Pod::Spell to test the spelling of embedded POD', $files);
90	}
91
92	for my $file (@perlfiles) {
93		if (! -e $file) {
94			fail (qq{Could not find the file "$file"!});
95		}
96		my $string = qx{podspell $file};
97		spellcheck ("POD from $file" => $string, $file);
98	}
99}
100
101## Now the comments
102SKIP: {
103	if (!eval { require File::Comments; 1 }) {
104		my $files = @commentfiles;
105		skip ('Need File::Comments to test the spelling inside comments', $files);
106	}
107
108	my $fc = File::Comments->new();
109
110	for my $file (@commentfiles) {
111		if (! -e $file) {
112			fail (qq{Could not find the file "$file"!});
113		}
114		my $string = $fc->comments($file);
115		if (! $string) {
116			fail (qq{Could not get comments from file $file});
117			next;
118		}
119		$string = join "\n" => @$string;
120		$string =~ s/=head1.+//sm;
121		spellcheck ("comments from $file" => $string, $file);
122	}
123
124}
125
126
127__DATA__
128## These words are okay
129
130## Common:
131babcdefgh
132badd
133bcmp
134bdiv
135bfac
136bgcd
137Biggar
138BigInt
139bior
140bloodgate
141bmod
142bmul
143bsub
144bxor
145chipt
146cpan
147CPAN
148cturner
149Divisior
150dk
151des
152DES
153env
154fac
155 fibonacci
156gcd
157gmp
158GMP
159GPL
160Haydon
161gmppmt
162Ilya
163intify
164jacobi
165legendre
166Makefile
167MERCHANTABILITY
168Behaviour
169Probabilistically
170mmod
171mul
172Mullane
173namespace
174nicholas
175n'th
176ok
177Oxh
178oxhoej
179perl
180perl
181powm
182README
183redhat
184Sabino
185Sep
186sizeinbase
187Spellcheck
188spellchecking
189sqrt
190Tels
191tels
192tradeoff
193tstbit
194ui
195Ulrich
196uintify
197xff
198xs
199YAML
200YAMLiciousness
201yml
202Zakharevich
203
204## Changes
205
206iglu
207il
208libgmp
209probab
210shlomif
211blcm
212bmodinv
213bsqrt
214lcm
215