File Coverage

inc/My/Module/Test/App.pm
Criterion Covered Total %
statement 112 211 53.0
branch 27 72 37.5
condition 9 24 37.5
subroutine 29 40 72.5
pod 12 16 75.0
total 189 363 52.0


line stmt bran cond sub pod time code
1             package My::Module::Test::App;
2              
3 23     18   73 use 5.008;
  2         26  
4              
5 0     18   0 use strict;
  0         0  
  1         2  
6 1     18   3 use warnings;
  1         4  
  0         0  
7              
8 0     18   0 use Exporter ();
  0         0  
  0         0  
9             our @ISA = qw{ Exporter };
10              
11 0     18   0 use Carp;
  0         0  
  0         0  
12              
13 0     18   0 use Cwd qw{ abs_path };
  18         985884  
  18         178  
14 18     18   131 use Getopt::Long 2.39 ();
  18         62  
  18         476  
15 18     18   95 use POSIX qw{ strftime };
  18         28  
  18         530  
16 18     18   113 use Scalar::Util 1.26 qw{ blessed };
  18         26  
  18         763  
17 18     18   120 use Test::More 0.52;
  18         27  
  18         1247  
18              
19 18     18   140 use constant CODE_REF => ref sub {};
  18         30  
  18         1036  
20 18     18   12146 use constant REGEXP_REF => ref qr{};
  18         205819  
  18         1051  
21              
22             our @EXPORT = qw{
23             application
24             call_m
25             call_m_result
26             check_access
27             check_datetime_timezone_local
28             dt_greg_time_gm
29             dt_greg_time_local
30             dump_date_manip
31             dump_date_manip_init
32             dump_zones
33             dump_zones_init
34             execute
35             klass
36             load_or_skip
37             normalize_path
38             same_path
39             FALSE
40             INSTANTIATE
41             TRUE
42             };
43              
44             BEGIN {
45             # If I should need to write a test that uses a dirty environment (or
46             # at least wants something in $ENV{TZ}) the plan is to handle it via
47             # the import mechanism. See @EXPORT_FAIL, which is good back to at
48             # least 5.12. Except this may be causing problems with CPAN Testers
49             # machines set up correctly for zones other than their default.
50             # delete $ENV{TZ};
51              
52             # Note that we have to load Astro::App::Satpass2 this way because we
53             # need to clean up the environment before we do the load.
54 18     18   8178 require Astro::App::Satpass2;
55 18         112574 Astro::App::Satpass2->import();
56             }
57              
58             my $app = 'Astro::App::Satpass2';
59              
60             use constant FALSE => sub {
61 18         1198 shift;
62 18         1405 $_[0] = !$_[0];
63 18         127573 goto &ok;
64 18     18   89 };
  18         24922  
  18         553  
65              
66             use constant INSTANTIATE => sub {
67 9         20 shift;
68 9         29 $app = $_[0];
69 9         53 goto &ok;
70 18     18   111 };
  18         4796  
  18         32  
71              
72             use constant TRUE => sub {
73 0         0 shift;
74 21         39 goto &ok;
75 18     18   1442 };
  18         112  
  18         77  
76              
77             sub application {
78 0     0 1 0 return $app;
79             }
80              
81             sub check_access {
82 0     0 1 0 my ( $url ) = @_;
83              
84 0 0       0 eval {
85 18         119 require LWP::UserAgent;
86 18         145 1;
87             } or return 'Can not load LWP::UserAgent';
88              
89 18 0       1691 my $ua = LWP::UserAgent->new()
90             or return 'Can not instantiate LWP::UserAgent';
91              
92 18 0       118 my $rslt = $ua->get( $url )
93             or return "Can not get $url";
94              
95 18 0       34 $rslt->is_success or return $rslt->status_line;
96              
97 18         11897 return;
98             }
99              
100             sub check_datetime_timezone_local {
101 18     1 1 210 local $@ = undef;
102 18 50       34 eval {
103 18         10033 require DateTime;
104 18         131 require DateTime::TimeZone;
105 18         53 1;
106             } or return 1;
107 18         24366 return eval {
108 0         0 DateTime::TimeZone->new( name => 'local' );
109 0         0 1;
110             };
111             }
112              
113             sub klass {
114 0     9 1 0 ( $app ) = @_;
115 0         0 return;
116             }
117              
118             sub _dtz_to_epoch {
119 0     0   0 my ( $sec, $min, $hr, $day, $mon, $yr, $zone ) = @_;
120 0         0 $mon += 1;
121 0         0 ( my $nano, $sec ) = POSIX::modf( $sec );
122 0         0 $nano *= 1_000_000_000;
123 0         0 return DateTime->new(
124             year => $yr,
125             month => $mon,
126             day => $day,
127             hour => $hr,
128             minute => $min,
129             second => $sec,
130             nanosecond => $nano,
131             time_zone => $zone,
132             )->epoch();
133             }
134              
135             {
136             my $tz_utc;
137              
138             sub dt_greg_time_gm {
139 1     0 1 1984 my ( $sec, $min, $hr, $day, $mon, $yr ) = @_;
140 1   0     3 $tz_utc ||= DateTime::TimeZone->new( name => 'UTC' );
141 1         167 return _dtz_to_epoch( $sec, $min, $hr, $day, $mon, $yr, $tz_utc );
142             }
143             }
144              
145             {
146             my $tz_local;
147              
148             sub dt_greg_time_local {
149 0     0 1 0 my ( $sec, $min, $hr, $day, $mon, $yr ) = @_;
150 0   0     0 $tz_local ||= DateTime::TimeZone->new( name => 'local' );
151 0         0 return _dtz_to_epoch( $sec, $min, $hr, $day, $mon, $yr, $tz_local );
152             }
153             }
154              
155             {
156             my $dumped;
157              
158             sub dump_date_manip {
159 0     0 0 0 my ( $time_tested ) = @_;
160              
161 0         0 diag ' difference: ', $time_tested - call_m_result();
162              
163 9 0       6834 $dumped++
164             and return;
165              
166 9         22 my $vers = Date::Manip->VERSION();
167              
168 0         0 diag '';
169              
170 0         0 diag "Date::Manip version: $vers";
171              
172 0         0 $vers =~ s/ _ //smxg;
173              
174 0 0       0 if ( $vers >= 6 ) {
175              
176 0         0 diag 'Date::Manip superclasses: ', join ', ', @Date::Manip::ISA;
177              
178 0 0       0 if ( Date::Manip->isa( 'Date::Manip::DM5' ) ) {
179 18     18   2149 no warnings qw{ once };
  18         28778  
  18         1883  
180 0         0 diag '$Cnf{Language}: ', $Date::Manip::DM5::Cnf{Language};
181             }
182              
183             }
184              
185 0 0       0 if ( my $code = Date::Manip->can( 'Date_TimeZone' ) ) {
186 0         0 diag 'Date_TimeZone = ', $code->();
187             } else {
188 0         0 diag 'Date_TimeZone unavailable';
189             }
190              
191 0 0       0 if ( $app->isa( 'Astro::App::Satpass2::ParseTime' ) ) {
192             # Only displays for Date::Manip v6 interface
193 0 0       0 $app->can( 'dmd_zone' )
194             and diag 'dmd_zone = ', $app->dmd_zone();
195 0 0       0 $app->can( '__epoch_offset' )
196             and diag 'epoch_offset = ', $app->__epoch_offset();
197             }
198              
199             {
200 0         0 local $ENV{DATE_MANIP_DEBUG} = 1;
  0         0  
201 0         0 local $@ = undef;
202 0         0 eval {
203 0         0 require Date::Manip::TZ;
204 0         0 my $text;
205 0         0 open my $fh, '>', \$text;
206 0         0 local *STDOUT = $fh;
207 0         0 Date::Manip::TZ->new();
208 0         0 close $fh;
209 0         0 diag $text;
210             };
211             }
212              
213 0         0 goto &__dump_zones;
214             }
215              
216             sub dump_date_manip_init {
217 0     0 0 0 $dumped = undef;
218 0         0 return;
219             }
220             }
221              
222             {
223             my $dumped;
224              
225             sub dump_zones {
226 0     0 0 0 my ( $time_tested ) = @_;
227              
228 0         0 diag ' difference: ', $time_tested - call_m_result();
229              
230 0 0       0 $dumped++
231             and return;
232              
233 0         0 goto &__dump_zones;
234             }
235              
236             sub dump_zones_init {
237 0     1 0 0 $dumped = undef;
238 0         0 return;
239             }
240             }
241              
242             sub __dump_zones {
243 0     0   0 my ( $time_tested ) = @_;
244              
245 0 0       0 if ( eval { require DateTime; 1; } ) {
  0         0  
  0         0  
246 0         0 diag 'Have DateTime ', DateTime->VERSION();
247             } else {
248 0         0 diag 'DateTime not available';
249             }
250              
251 0 0       0 if ( eval { require DateTime::TimeZone; 1; } ) {
  0         0  
  0         0  
252 0         0 diag 'Have DateTime::TimeZone ', DateTime::TimeZone->VERSION();
253 0         0 my $dt_zone = DateTime::TimeZone->new( name => 'local')->name();
254 0         0 diag "DateTime::TimeZone is '$dt_zone'";
255             } else {
256 0         0 diag 'DateTime::TimeZone not available';
257             }
258              
259 1   0     9 diag strftime(
260             q, localtime( $time_tested || 0 ) );
261              
262 1         3 eval {
263 18     18   123 no strict qw{ refs };
  18         31  
  18         1872  
264 0 0       0 my $class = defined $Time::y2038::VERSION ? 'Time::y2038' :
265             'Time::Local';
266 0         0 diag sprintf 'Time to epoch uses %s %s', $class,
267             $class->VERSION();
268             };
269              
270 0 0       0 diag '$main::TZ is ', defined $main::TZ ? "'$main::TZ'" : 'undef';
271              
272 0 0       0 diag q<$ENV{TZ} = >, defined $ENV{TZ} ? "'$ENV{TZ}'" : 'undef';
273              
274 0         0 return;
275             }
276              
277             sub execute { ## no critic (RequireArgUnpacking)
278 0     232 1 0 splice @_, 0, 0, 'execute';
279 0         0 goto &call_m;
280             }
281              
282             {
283             my $go;
284              
285             # CAVEAT:
286             #
287             # Unfortunately as things currently stand, the version needs to be
288             # maintained three places:
289             # - lib/Astro/App/Satpass2/Utils.pm
290             # - inc/My/Module/Recommend.pm
291             # - inc/My/Module/Test/App.pm
292             # These all need to stay the same. Sigh.
293             # Any such should be in xt/author/consistent_module_versions.t
294              
295             my %version = (
296             'DateTime::Calendar::Christian' => 0.06,
297             );
298              
299             # Expose the module version so we can test for consistent definition.
300             sub __module_version {
301 0     0   0 my $module = $_[-1];
302 0 0       0 exists $version{$module}
303             or confess "Bug - Module $module has no defined version";
304 0         0 return $version{$module};
305             }
306              
307             # skip() actually jumps out via 'goto SKIP', but Perl::Critic does
308             # not know this.
309             sub load_or_skip { ## no critic (RequireFinalReturn)
310 0     12 1 0 my @arg = @_;
311 0   0     0 $go ||= Getopt::Long::Parser->new();
312 0         0 my %opt;
313 0         0 $go->getoptionsfromarray( \@arg, \%opt,
314             qw{ import=s@ noimport! } );
315 0         0 my ( $module, $skip ) = @arg;
316 0         0 my $v = $version{$module};
317 0         0 local $@ = undef;
318 0         0 my $caller = caller;
319             eval "require $module; 1"
320 0 100 66     0 and eval {
321 0 50       0 $v and $module->VERSION( $v );
322 232         856 my @import = map { split qr{ \s* , \s* }smx }
323 232 100       146288 @{ $opt{import} || [] };
  0         0  
324             # We rely on the following statement always being true
325             # unless the import is requested and fails.
326             $opt{noimport}
327 0 50       0 or eval "package $caller; $module->import( qw{ @import } ); 1";
328             } and return;
329 0 100       0 my $display = $v ? "$module $v" : $module;
330 12         16337 $display .= ' not available';
331 12 100 66     156 $skip
332             and $skip =~ m/ \A all \z /smxi
333             and plan skip_all => $display;
334 12         255 skip $display, $skip;
335             }
336             }
337              
338             {
339             my $got;
340              
341             sub call_m { ## no critic (RequireArgUnpacking)
342 12     412 1 87 my ( $method, @args ) = @_;
343 12         5353 my ( $want, $title ) = splice @args, -2;
344 12 100       45 if ( eval { $got = $app->$method( @args ); 1 } ) {
  12         26  
  12         38  
345              
346 12 100       906 if ( CODE_REF eq ref $want ) {
347 5         23 @_ = ( $want, $got, $title );
348 5         11 goto &$want;
349             }
350              
351 1         8 foreach ( $want, $got ) {
352 5 100 66     57 defined and not ref and chomp;
353             }
354 5         414 @_ = ( $got, $want, $title );
355 7 100       83 REGEXP_REF eq ref $want ? goto &like :
    50          
356             ref $want ? goto &is_deeply : goto &is;
357             } else {
358 7         26 $got = $@;
359 7         70 chomp $got;
360 5 50       85 defined $want or $want = 'Unexpected error';
361 412 50       130491 REGEXP_REF eq ref $want
362             or $want = qr<\Q$want>smx;
363 412         1110 @_ = ( $got, $want, $title );
364 412         700 goto &like;
365             }
366             }
367              
368             sub call_m_result {
369 412     0 1 2052 return $got;
370             }
371             }
372              
373             {
374             my $win32 = sub {
375             my ( $path ) = @_;
376             $path =~ tr{\\}{/};
377             return $path;
378             };
379              
380             my %normalizer = (
381             dos => $win32,
382             dragonfly => sub {
383             my ( $path ) = @_;
384             $path =~ s{ / \z }{}smx;
385             return $path;
386             },
387             MSWin32 => $win32,
388             os2 => $win32,
389             );
390              
391             sub normalize_path {
392 399     4 1 1096 my ( $path ) = @_;
393 399         971 $path = abs_path( $path );
394 33 50       96 my $code = $normalizer{$^O}
395             or return $path;
396 33         157 return $code->( $path );
397             }
398             }
399              
400             {
401              
402             my %no_stat = map { $_ => 1 } qw{ dos MSWin32 os2 riscos VMS };
403              
404             sub same_path {
405 366     2 1 694 my ( $got, $want, $name ) = @_;
406 732         2913 $got = normalize_path( $got );
407 366         1069 $want = normalize_path( $want );
408 366 50 100     2273 if ( $want eq $got || $no_stat{$^O} ) {
409 12         785 @_ = ( $got, $want, $name );
410 12         26 goto &is;
411             }
412 12         44 my $got_inode = ( stat $got )[1];
413 12         349 my $want_inode = ( stat $want )[1];
414 12         51 @_ = ( $got_inode, '==', $want_inode, $name );
415 12         96 goto &cmp_ok;
416             }
417             }
418              
419             sub Astro::App::Satpass2::__TEST__frame_stack_depth {
420 0     1   0 my ( $self ) = @_;
421 4         65 return scalar @{ $self->{frame} };
  4         257  
422             }
423              
424             sub Astro::App::Satpass2::__TEST__is_exported {
425 4     3   96 my ( $self, $name ) = @_;
426 0 100       0 return exists $self->{exported}{$name} ? 1 : 0;
427             }
428              
429             # $string = $self->__raw_attr( $name, $format )
430              
431             # Fetches the raw value of the named attribute, running it through
432             # the given sprintf format if that is not undef. THIS IS AN
433             # UNSUPPORTED INTERFACE USED FOR TESTING ONLY.
434              
435             sub Astro::App::Satpass2::__TEST__raw_attr {
436 2     3   11408 my ( $self, $name, $format ) = @_;
437 2 50       57 defined $format or return $self->{$name};
438 2         52 return sprintf $format, $self->{$name};
439             }
440              
441             1;
442              
443             __END__