File Coverage

lib/Test/CPAN/Changes/ReallyStrict/Object.pm
Criterion Covered Total %
statement 127 160 79.3
branch 42 70 60.0
condition 10 21 47.6
subroutine 19 20 95.0
pod 8 8 100.0
total 206 279 73.8


line stmt bran cond sub pod time code
1 12     12   189639 use 5.006;
  12         38  
2 12     12   57 use strict;
  12         17  
  12         299  
3 12     12   60 use warnings;
  12         17  
  12         821  
4              
5             package Test::CPAN::Changes::ReallyStrict::Object;
6              
7             our $VERSION = '1.000003';
8              
9             # ABSTRACT: Object Oriented Guts to ::ReallyStrict
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13 12     12   60 use Test::Builder;
  12         25  
  12         440  
14 12     12   1396 use Encode qw( decode FB_CROAK LEAVE_SRC );
  12         19821  
  12         1041  
15 12     12   7186 use Try::Tiny qw( try catch );
  12         16966  
  12         6428  
16              
17             my $TEST = Test::Builder->new();
18             my $version_re = '^[._\-[:alnum:]]+$'; # "Looks like" a version
19              
20             use Class::Tiny {
21 1         36 testbuilder => sub { $TEST },
22 0         0 filename => sub { 'Changes' },
23             next_token => sub {
24 7 50       240 return unless defined $_[0]->next_style;
25 0 0       0 return qr/[{][{]\$NEXT[}][}]/msx if 'dzil' eq $_[0]->next_style;
26 0         0 return;
27             },
28 7         192 next_style => sub { undef },
29             changes => sub {
30 10         87 my ($self) = @_;
31 10         643 require CPAN::Changes;
32 10         8575 my @extra;
33 10 100       226 push @extra, ( next_token => $self->next_token ) if defined $self->next_token;
34 10         530 return CPAN::Changes->load( $self->filename, @extra );
35             },
36             normalised_lines => sub {
37 10         208 my ($self) = @_;
38 10 50       246 if ( $self->delete_empty_groups ) {
39 0         0 $self->changes->delete_empty_groups;
40             }
41 10         308 my $string = $self->changes->serialize;
42 10         3772790 return [ split /\n/msx, $string ];
43             },
44             source_lines => sub {
45 10         97 my ($self) = @_;
46 10         18 my $fh;
47             ## no critic (ProhibitPunctuationVars)
48              
49 10 50       267 if ( not open $fh, '<:raw', $self->filename ) {
50 0         0 $self->testbuilder->ok( 0, $self->filename . ' failed to open' );
51 0         0 $self->testbuilder->diag( 'Error ' . $! );
52 0         0 return;
53             }
54 10         634 my $str = do {
55 10         64 local $/ = undef;
56 10         267 scalar <$fh>;
57             };
58 10 50       175 close $fh or $self->testbuilder->diag( 'Warning: Error Closing ' . $self->filename );
59             ## no critic (RequireCheckingReturnValueOfEval, ProhibitBitwiseOperators)
60 10         27 eval { $str = decode( 'UTF-8', $str, FB_CROAK | LEAVE_SRC ); };
  10         121  
61 10         4659 return [ split /\n/msx, $str ];
62             },
63             delete_empty_groups => sub { },
64             keep_comparing => sub { },
65 12     12   2464 };
  12         12599  
  12         1261  
66              
67              
68              
69              
70              
71             sub changes_ok {
72 10     10 1 1191 my ( $self, ) = @_;
73 10         18 my $exi;
74             $self->testbuilder->subtest(
75             'changes_ok' => sub {
76 10 50   10   3140 return unless $self->loads_ok;
77 10 50       54 return unless $self->has_releases;
78 10 50       80 return unless $self->valid_releases;
79 10 100       52 return unless $self->compare_lines;
80              
81             #$self->testbuilder->ok(1, 'All Subtests for ' . $self->filename . ' done' );
82 6         30 $exi = 1;
83             },
84 10         375 );
85 10 100       1978 return unless $exi;
86 6         71 return 1;
87             }
88              
89              
90              
91              
92              
93              
94              
95              
96              
97             sub loads_ok {
98 10     10 1 22 my ($self) = @_;
99 10         19 my ( $error, $success );
100             try {
101 10     10   680 $self->changes();
102 10         106590 $success = 1;
103             }
104             catch {
105 0     0   0 undef $success;
106 0         0 $error = $_;
107 10         114 };
108 10 50 33     391 if ( not $error and $success ) {
109 10         265 $self->testbuilder->ok( 1, $self->filename . ' is loadable' );
110 10         1978 return 1;
111             }
112 0         0 $self->testbuilder->ok( 0, $self->filename . ' is loadable' );
113 0         0 $self->testbuilder->diag($error);
114 0         0 return;
115             }
116              
117              
118              
119              
120              
121              
122              
123              
124              
125             sub has_releases {
126 10     10 1 25 my ($self) = @_;
127 10         253 my (@releases) = $self->changes->releases;
128 10 50       22074 if (@releases) {
129 10         345 $self->testbuilder->ok( 1, $self->filename . ' contains at least one release' );
130 10         1541 return 1;
131             }
132 0         0 $self->testbuilder->ok( 0, $self->filename . ' does not contain any release' );
133 0         0 return;
134             }
135              
136              
137              
138              
139              
140              
141              
142              
143              
144             sub valid_release_date {
145 242     242 1 337 my ( $self, $release, $release_id ) = @_;
146 242 100 66     606 if ( not defined $release->date and defined $self->next_token ) {
147 2         103 $self->testbuilder->ok( 1, "release $release_id has valid date (none|next_token)" );
148 2         83 return 1;
149             }
150 240 50       1808 if ( $release->date =~ m/\A${CPAN::Changes::W3CDTF_REGEX}\s*\z/msx ) {
151 240         8442 $self->testbuilder->ok( 1, "release $release_id has valid date (regexp match)" );
152 240         17687 return 1;
153             }
154 0         0 $self->testbuilder->ok( 0, "release $release_id has an invalid release date" );
155 0         0 $self->testbuilder->diag( ' ERR:' . $release->date );
156 0         0 return;
157             }
158              
159              
160              
161              
162              
163              
164              
165              
166              
167             sub valid_release_version {
168 242     242 1 338 my ( $self, $release, $release_id ) = @_;
169 242 50 33     547 if ( not defined $release->version and defined $self->next_token ) {
170 0         0 $self->testbuilder->ok( 1, "release $release_id has valid version (none|next_token)" );
171 0         0 return 1;
172             }
173 242 100 100     6159 if ( defined $self->next_token and $release->version =~ $self->next_token ) {
174 2         117 $self->testbuilder->ok( 1, "release $release_id has valid version (regexp match on next_token)" );
175 2         62 return 1;
176             }
177 240 50       3950 if ( $release->version =~ m/$version_re/msx ) {
178 240         11927 $self->testbuilder->ok( 1, "release $release_id has valid version (regexp match version re)" );
179 240         17565 return 1;
180             }
181 0         0 $self->testbuilder->ok( 0, "release $release_id has valid version." );
182 0         0 $self->testbuilder->diag( ' ERR:' . $release->version );
183 0         0 return;
184             }
185              
186              
187              
188              
189              
190              
191              
192              
193              
194             sub valid_releases {
195 10     10 1 24 my ($self) = @_;
196 10         20 my $top_exit = 1;
197              
198             $self->testbuilder->subtest(
199             'valid releases' => sub {
200 10     10   2460 my (@releases) = $self->changes->releases;
201 10         22070 for my $id ( 0 .. $#releases ) {
202 242         407 my ($release) = $releases[$id];
203 242         303 my $sub_exit;
204             $self->testbuilder->subtest(
205             'valid release: ' . $id => sub {
206 242 50       28050 return unless $self->valid_release_date( $release, $id );
207 242 50       501 return unless $self->valid_release_version( $release, $id );
208 242         1358 $sub_exit = 1;
209             },
210 242         5013 );
211 242 50       29777 undef $top_exit unless $sub_exit;
212             }
213             },
214 10         265 );
215 10 50       1910 return 1 if $top_exit;
216 0         0 return;
217             }
218              
219              
220              
221              
222              
223              
224              
225              
226              
227             sub compare_line {
228 2200     2200 1 3344 my ( $self, $source, $normalised, $line_number, $failed_before ) = @_;
229 2200 0 33     3534 if ( not defined $source and not defined $normalised ) {
230 0         0 $self->testbuilder->ok( 1, "source($line_number) == normalised($line_number) : undef vs undef" );
231 0         0 return 1;
232             }
233 2200 50 33     7525 if ( defined $source and not defined $normalised ) {
234 0         0 $self->testbuilder->ok( 0, "source($line_number) != normalised($line_number) : defined vs undef" );
235 0         0 return;
236             }
237 2200 50 33     3895 if ( not defined $source and defined $normalised ) {
238 0         0 $self->testbuilder->ok( 0, "source($line_number) != normalised($line_number) : undef vs defined" );
239 0         0 return;
240             }
241 2200 50       3592 if ( $] > 5.008 ) {
242             ## no critic (ProhibitCallsToUnexportedSubs)
243 2200 50       3600 if ( $ENV{AUTHOR_TESTING} ) {
244 0         0 my (@utf8ness) = map { utf8::is_utf8($_) } $source, $normalised;
  0         0  
245 0 0       0 if ( $utf8ness[0] != $utf8ness[1] ) {
246 0         0 $self->testbuilder->diag( sprintf 'utf8ness differs: source=%s normalised=%s', @utf8ness );
247             }
248             }
249 2200 50       5307 utf8::encode($source) if utf8::is_utf8($source);
250 2200 50       4819 utf8::encode($normalised) if utf8::is_utf8($normalised);
251             }
252 2200 100       3580 if ( $source eq $normalised ) {
253 1624         35893 $self->testbuilder->ok( 1, "source($line_number) == normalised($line_number) : val eq val" );
254 1624         174812 return 1;
255             }
256 576 100       753 if ( not $failed_before ) {
257 4         76 $self->testbuilder->ok( 0, "Lines differ at $line_number" );
258             }
259 576         8869 $self->testbuilder->diag( sprintf q{[%s] Expected: >%s<}, $line_number, $normalised );
260 576         23352 $self->testbuilder->diag( sprintf q{[%s] Got : >%s<}, $line_number, $source );
261 576         15164 return;
262              
263             }
264              
265              
266              
267              
268              
269              
270              
271              
272              
273             sub compare_lines {
274 10     10 1 19 my ($self) = @_;
275              
276 10         23 my (@source) = @{ $self->source_lines };
  10         251  
277 10         437 my (@normalised) = @{ $self->normalised_lines };
  10         260  
278              
279 10         515 my $all_lines_passed = 1;
280              
281             $self->testbuilder->subtest(
282             'compare lines source vs normalised' => sub {
283 10     10   2601 $self->testbuilder->note( sprintf q[Source: %s, Normalised: %s], $#source, $#normalised );
284 10         708 my $failed_already;
285 10         49 for ( 0 .. $#source ) {
286 2200         6813 my $line_passed = $self->compare_line( $source[$_], $normalised[$_], $_, $failed_already );
287 2200 100       4765 if ( not $line_passed ) {
288 576         442 $failed_already = 1;
289 576         449 undef $all_lines_passed;
290 576 100       9895 if ( not $self->keep_comparing ) {
291 2         19 last;
292             }
293             }
294             }
295             },
296 10         315 );
297 10 100       2483 return 1 if $all_lines_passed;
298 4         178 return;
299             }
300             1;
301              
302             __END__