File Coverage

blib/lib/Test/Fetchware.pm
Criterion Covered Total %
statement 166 207 80.1
branch 51 98 52.0
condition 5 18 27.7
subroutine 30 35 85.7
pod 15 15 100.0
total 267 373 71.5


line stmt bran cond sub pod time code
1             package Test::Fetchware;
2             our $VERSION = '1.016'; # VERSION: generated by DZP::OurPkgVersion
3             # ABSTRACT: Provides testing subroutines for App::Fetchware.
4 52     52   266674 use strict;
  52         57  
  52         1418  
5 52     52   159 use warnings;
  52         50  
  52         1816  
6              
7             # CPAN modules making Fetchwarefile better.
8 52     52   27976 use File::Temp 'tempdir';
  52         593167  
  52         2809  
9 52     52   12868 use File::Spec::Functions qw(catfile rel2abs updir tmpdir);
  52         17281  
  52         2821  
10 52     52   1273 use Test::More 0.98; # some utility test subroutines need it.
  52         24588  
  52         330  
11 52     52   10929 use Cwd;
  52         59  
  52         2282  
12 52     52   31907 use Archive::Tar;
  52         3131763  
  52         2835  
13 52     52   17772 use Path::Class;
  52         546794  
  52         2432  
14 52     52   311 use Digest::MD5;
  52         59  
  52         1468  
15 52     52   260 use Fcntl qw(:flock :mode);
  52         85  
  52         12303  
16 52     52   20733 use Perl::OSType 'is_os_type';
  52         12832  
  52         2434  
17 52     52   255 use File::Temp 'tempfile';
  52         52  
  52         1720  
18 52     52   172 use File::Path 'remove_tree';
  52         53  
  52         1593  
19              
20 52     52   28626 use App::Fetchware::Util ':UTIL';
  52         105  
  52         10434  
21 52     52   382 use App::Fetchware::Config ':CONFIG';
  52         63  
  52         4977  
22              
23             # Enable Perl 6 knockoffs, and use 5.10.1, because smartmatching and other
24             # things in 5.10 were changed in 5.10.1+.
25 52     52   917 use 5.010001;
  52         136  
26              
27              
28             # Set up Exporter to bring App::Fetchware's API to everyone who use's it
29             # including fetchware's ability to let you rip into its guts, and customize it
30             # as you need.
31 52     52   171 use Exporter qw( import );
  52         59  
  52         97360  
32             # By default fetchware exports its configuration file like subroutines and
33             # fetchware().
34             #
35              
36             # These tags go with the override() subroutine, and together allow you to
37             # replace some or all of fetchware's default behavior to install unusual
38             # software.
39             our %EXPORT_TAGS = (
40             TESTING => [qw(
41             eval_ok
42             print_ok
43             fork_ok
44             fork_not_ok
45             skip_all_unless_release_testing
46             make_clean
47             make_test_dist
48             md5sum_file
49             expected_filename_listing
50             verbose_on
51             export_ok
52             end_ok
53             add_prefix_if_nonroot
54             create_test_fetchwarefile
55             rmdashr_ok
56             )],
57             );
58             # *All* entries in @EXPORT_TAGS must also be in @EXPORT_OK.
59             our @EXPORT_OK = map {@{$_}} values %EXPORT_TAGS;
60              
61              
62              
63             sub eval_ok {
64 45     45 1 14713 my ($code, $expected_exception_text_or_regex, $test_name) = @_;
65 45         67 eval {$code->()};
  45         102  
66             # Test if an exception was actually thrown.
67 45 50       1570 if (not defined $@) {
68 0         0 BAIL_OUT("[$test_name]'s provided code did not actually throw an exception");
69             }
70            
71             # Support regexing the thrown exception's test if needed.
72 45 100       122 if (ref $expected_exception_text_or_regex ne 'Regexp') {
    50          
73 35         99 is($@, $expected_exception_text_or_regex, $test_name);
74             } elsif (ref $expected_exception_text_or_regex eq 'Regexp') {
75 10         66 like($@, qr/$expected_exception_text_or_regex/, $test_name);
76             }
77              
78             }
79              
80              
81              
82             sub print_ok {
83 75     75 1 787208 my ($printer, $expected, $test_name) = @_;
84              
85 75         216 my $error;
86             my $stdout;
87             # Use eval to catch errors that $printer->() could possibly throw.
88             eval {
89 75         367 local *STDOUT;
90             # Turn on Autoflush mode, so each time print is called it causes perl to
91             # flush STDOUT's buffer. Otherwise a write could happen, that may not
92             # actually get written before this eval closes, causing $stdout to stay
93             # undef instead of getting whatever was written to STDOUT.
94 75         385 $| = 1;
95 75 50   25   3082 open STDOUT, '>', \$stdout
  25         313  
  25         65  
  25         273  
96             or $error = 'Can\'t open STDOUT to test cmd_upgrade using cmd_list';
97              
98             # Execute $printer
99 75         23694 $printer->();
100              
101 66 50       580 close STDOUT
102             or $error = 'WTF! closing STDOUT actually failed! Huh?';
103 75 50       332 } or do {
104 0 0       0 $error = $@ if $@;
105 0 0       0 fail($error) if defined $error;
106             };
107              
108             # Since Test::More's testing subroutines return true or false if the test
109             # passes or fails, return this true or false value back to the caller.
110 66 100       361 if (ref($expected) eq '') {
    100          
    50          
111 28         69 return is($stdout, $expected,
112             $test_name);
113             } elsif (ref($expected) eq 'Regexp') {
114 5         23 return like($stdout, $expected,
115             $test_name);
116             } elsif (ref($expected) eq 'CODE') {
117             # Call the provided callback with what $printer->() printed.
118 33         110 return ok($expected->($stdout),
119             $test_name);
120             }
121             }
122              
123              
124              
125             sub fork_ok {
126 173     173 1 95596 my $coderef = shift;
127 173         368 my $test_name = shift;
128              
129              
130 173         186383 my $kid = fork;
131 173 50       3306 die "Couldn't fork: $!\n" if not defined $kid;
132             # ... parent code here ...
133 173 100       2784 if ( $kid ) {
134             # Block waiting for the child process ($kid) to exit.
135 155         264226718 waitpid($kid, 0);
136             }
137             # ... child code here ...
138             else {
139             # Run caller's code wihtout any args.
140             # And exit based on the success or failure of $coderef.
141 18 50       1540 $coderef->() ? exit 0 : exit 1;
142             }
143              
144             # And test that the child returned successfully.
145 155         4474 ok(($? >> 8) == 0, $test_name);
146              
147 155         111554 return $?;
148             }
149              
150              
151              
152             sub fork_not_ok {
153 2     2 1 1950 my $coderef = shift;
154 2         6 my $test_name = shift;
155              
156              
157 2         2702 my $kid = fork;
158 2 50       102 die "Couldn't fork: $!\n" if not defined $kid;
159             # ... parent code here ...
160 2 100       102 if ( $kid ) {
161             # Block waiting for the child process ($kid) to exit.
162 1         1563227 waitpid($kid, 0);
163             }
164             # ... child code here ...
165             else {
166             # Run caller's code wihtout any args.
167             # And exit based on the success or failure of $coderef.
168 1 50       43 $coderef->() ? exit 0 : exit 1;
169             }
170              
171             # Check that the child failed and returned nonzero.
172 1         37 ok(($? >> 8) != 0, $test_name);
173              
174 1         421 return $?;
175             }
176              
177              
178              
179             sub skip_all_unless_release_testing {
180 71 50 33 71 1 87209 if (not exists $ENV{FETCHWARE_RELEASE_TESTING}
      33        
181             or not defined $ENV{FETCHWARE_RELEASE_TESTING}
182             or $ENV{FETCHWARE_RELEASE_TESTING}
183             ne '***setting this will install software on your computer!!!!!!!***'
184              
185             # Enforce having *all* other FETCHWARE_* env vars set too to make it
186             # even harder to easily enable FETCHWARE_RELEASE_TESTING. This is
187             # because FETCHWARE_RELEASE_TESTING *installs* software on your
188             # computer.
189             #
190             # Furthermore, the env vars below are required for
191             # FETCHWARE_RELEASE_TESTING to work properly, so without them being set,
192             # then FETCHWARE_RELEASE_TESTING will not work properly, because these
193             # env vars will be undef; therefore, check to see if they're enabled.
194             ) {
195 71         236 plan skip_all => 'Not testing for release.';
196             }
197             }
198              
199              
200              
201             sub make_clean {
202 0 0 0 0 1 0 BAIL_OUT(<
203             Running make_clean() inside of fetchware's own directory! make_clean() should
204             only be called inside testing build directories, and perhaps also only called if
205             FETCHWARE_RELEASE_TESTING has been set.
206             EOF
207 0         0 system('make', 'clean');
208 0 0       0 chdir(updir()) or fail(q{Can't chdir(updir())!});
209             }
210              
211              
212              
213             ###BUGALERT### make_test_dist() only works properly on Unix, because of its
214             #dependencies on the shell and make, just replace those commands with perl
215             #itself, which we can pretty much guaranteed to be installed.
216             sub make_test_dist {
217 203     203 1 30152276 my %opts = @_;
218              
219             # Validate options, and set defaults if they need to be set.
220 203 50       1032 if (not defined $opts{file_name}) {
221 0         0 die <
222             Test-Fetchware: file_name named parameter is a mandatory options, and must be
223             specified despite it pretty much always being just 'test-dist'. It is still
224             mandatory.
225             EOD
226             }
227 203 50       643 if (not defined $opts{ver_num}) {
228 0         0 die <
229             Test-Fetchware: ver_num named parameter is a mandatory options, and must be
230             specified despite it pretty much always being just '1.00'. It is still
231             mandatory.
232             EOD
233             }
234             # $destination_directory is a mandatory option, but if the caller does not
235             # provide one, then simply use a tempdir().
236 203 100       646 if (not defined $opts{destination_directory}) {
237             $opts{destination_directory}
238 96         845 = tempdir("fetchware-test-$$-XXXXXXXXXXX", TMPDIR => 1, CLEANUP => 1);
239             # Don't *only* create the tempdid $destination_directory, also, it must
240             # be chmod()'d to 755, unless stay_root is set, so that the dropped priv
241             # user can still access the directory make_test_dist() creates.
242 96 50       40130 chmod 0755, $opts{destination_directory} or die <
243             Test-Fetchware: Fetchware failed to change the permissions of it's testing
244             destination directory [$opts{destination_directory}] this shouldn't happen, and is
245             perhaps a bug. The OS error was [$!].
246             EOD
247             }
248             # This %opts check must go before the code below sets fetchwarefile even if
249             # the user did not supply it. Perhaps separate things should stay separate,
250             # and %opts and %test_dist_files should both exist for this, but why bother
251             # duplicating the same information if only one options is annoyed?
252 203 50 66     902 if (defined $opts{fetchwarefile} and defined $opts{append_option}) {
253 0         0 die <
254             fetchware: Run-time error. make_test_dist() can only be called with the
255             Fetchwarefile option *or* the append_option named parameters never both. Only
256             specify one.
257             EOD
258             }
259 203 100       560 if (not defined $opts{fetchwarefile}) {
260 200         1861 $opts{fetchwarefile} = <
261             # $opts{file_name} is a fake "test distribution" meant for testing fetchware's basic
262             # installing, upgrading, and so on functionality.
263             use App::Fetchware;
264              
265             program '$opts{file_name}';
266              
267             # Every Fetchwarefile needs a lookup_url...
268             lookup_url 'file://$opts{destination_directory}';
269              
270             # ...and a mirror.
271             mirror 'file://$opts{destination_directory}';
272              
273             # Need to filter out the cruft.
274             filter '$opts{file_name}';
275              
276             # Just use MD5 to verify it.
277             verify_method 'md5';
278              
279             EOF
280             }
281 203 50       641 if (not defined $opts{configure}) {
282 203         850 $opts{configure} = <
283             #!/bin/sh
284              
285             # A Test ./configure file for testing Fetchware's install, upgrade, and so on
286             # functionality.
287              
288             echo "fetchware: ./configure ran successfully!"
289             EOF
290             }
291 203 50       479 if (not defined $opts{makefile}) {
292 203         415 $opts{makefile} = <
293             # Makefile for test-dist, which is a "test distribution" for testing Fetchware's
294             # install, upgrade, and so on functionality.
295              
296             all:
297             sh -c 'echo "fetchware: make ran successfully!"'
298              
299             install:
300             sh -c 'echo "fetchware: make install ran successfully!"'
301              
302             uninstall:
303             sh -c 'echo "fetchware: make uninstall ran successfully!"'
304              
305             build-package:
306             sh -c 'echo "Build package and creating md5sum."'
307              
308             sh -c '(cd .. && tar --create --gzip --verbose --file test-dist-1.00.fpkg ./Fetchwarefile test-dist-1.00)'
309              
310             sh -c '(cd .. && md5sum test-dist-1.00.fpkg > test-dist-1.00.fpkg.md5)'
311              
312             sh -c 'echo "Build package and creating md5sum for upgrade version."'
313              
314             sh -c 'cp -R ../test-dist-1.00 ../test-dist-1.01'
315              
316             sh -c '(cd .. && tar --create --gzip --verbose --file test-dist-1.00/test-dist-1.01.fpkg ./Fetchwarefile test-dist-1.01)'
317              
318             sh -c 'rm -r ../test-dist-1.01'
319              
320             sh -c 'md5sum test-dist-1.01.fpkg > test-dist-1.01.fpkg.md5'
321             EOF
322             }
323 203 100       496 if (defined $opts{append_option}) {
324 27         166 $opts{fetchware} .= "\n$opts{append_option}\n"
325             }
326              
327              
328             # Set up some variables used during test_dist creation.
329             # Append $ver_num to $file_name to complete the dist's name.
330 203         520 my $dist_name = "$opts{file_name}-$opts{ver_num}";
331 203         1014 $opts{destination_directory} = rel2abs($opts{destination_directory});
332 203         4185 my $test_dist_filename = catfile($opts{destination_directory}, "$dist_name.fpkg");
333 203         732 my $configure_path = catfile($dist_name, 'configure');
334              
335              
336             # Be sure to add a prefix to the generated Fetchwarefile if fetchware is not
337             # running as root to ensure that our test installs succeed.
338             add_prefix_if_nonroot(sub {
339 0     0   0 my $prefix_dir = tempdir("fetchware-test-$$-XXXXXXXXXX",
340             TMPDIR => 1, CLEANUP => 1);
341             $opts{fetchwarefile}
342             .=
343 0         0 "prefix '$prefix_dir';";
344             }
345 203         2581 );
346              
347              
348             # Create a temp dir to create or test-dist-1.$opts{ver_num} directory in.
349             # Must be done before original_cwd() is used to set $opts{destination_directory},
350             # because original_cwd() is undef until create_tempdir() sets it.
351 203         1862 my $temp_dir = create_tempdir();
352              
353 203 50       10461 mkdir($dist_name) or die <
354             fetchware: Run-time error. Fetchware failed to create the directory
355             [$dist_name] in the current directory of [$temp_dir]. The OS error was
356             [$!].
357             EOD
358              
359             my %test_dist_files = (
360             './Fetchwarefile' => $opts{fetchwarefile},
361             $configure_path => $opts{configure},
362             catfile($dist_name, 'Makefile') => $opts{makefile},
363 203         3687 );
364              
365 203         961 for my $file_to_create (keys %test_dist_files) {
366 609 50       31999 open(my $fh, '>', $file_to_create) or die <
367             fetchware: Run-time error. Fetchware failed to open
368             [$file_to_create] for writing to create the Configure script that
369             test-dist needs to work properly. The OS error was [$!].
370             EOD
371 609         2028 print $fh $test_dist_files{$file_to_create};
372 609         16323 close $fh;
373             }
374              
375             # chmod() ./configure, so it can be executed.
376 203 50       3300 chmod(0755, $configure_path) or die <
377             fetchware: run-time error. fetchware failed to chmod [$configure_path] to add
378             execute permissions, which ./configure needs. Os error [$!].
379             EOC
380              
381             # Create a tar archive of all of the files needed for test-dist.
382 203 50       3460 Archive::Tar->create_archive("$test_dist_filename", COMPRESS_GZIP,
383             keys %test_dist_files) or die <
384             fetchware: Run-time error. Fetchware failed to create the test-dist archive for
385 0         0 testing [$test_dist_filename] The error was [@{[Archive::Tar->error()]}].
386             EOD
387              
388             # Cd back to original_cwd() and delete $temp_dir.
389 203         838927 cleanup_tempdir();
390              
391 203         1179 return rel2abs($test_dist_filename);
392             }
393              
394              
395              
396             sub md5sum_file {
397 180     180 1 11069 my $archive_to_md5 = shift;
398              
399 180 50       5528 open(my $package_fh, '<', $archive_to_md5)
400             or die <
401             App-Fetchware: run-time error. Fetchware failed to open the file it downloaded
402             while trying to read it in order to check its MD5 sum. The file was
403             [$archive_to_md5]. OS error [$!]. See perldoc App::Fetchware.
404             EOD
405              
406 180         2037 my $digest = Digest::MD5->new();
407              
408             # Digest requires the filehandle to have binmode set.
409 180         484 binmode $package_fh;
410              
411 180         236 my $calculated_digest;
412 180         293 eval {
413             # Add the file for digesting.
414 180         2499 $digest->addfile($package_fh);
415             # Actually digest it.
416 180         883 $calculated_digest = $digest->hexdigest();
417             };
418 180 50       486 if ($@) {
419 0         0 die <
420             App-Fetchware: run-time error. Digest::MD5 croak()ed an error [$@].
421             See perldoc App::Fetchware.
422             EOD
423             }
424              
425 180 50       1248 close $package_fh or die <
426             App-Fetchware: run-time error Fetchware failed to close the file
427             [$archive_to_md5] after opening it for reading. See perldoc App::Fetchware.
428             EOD
429            
430 180         535 my $md5sum_file = rel2abs($archive_to_md5);
431 180         2152 $md5sum_file = "$md5sum_file.md5";
432 180 50       10694 open(my $md5_fh, '>', $md5sum_file) or die <
433             fetchware: run-time error. Failed to open [$md5sum_file] while calculating a
434             md5sum. Os error [$!].
435             EOD
436              
437 180         511 print $md5_fh "$calculated_digest @{[file($archive_to_md5)->basename()]}";
  180         1287  
438              
439 180 50       28186 close $md5_fh or die <
440             App-Fetchware: run-time error Fetchware failed to close the file
441             [$md5sum_file] after opening it for reading. See perldoc App::Fetchware.
442             EOD
443              
444 180         1665 return $md5sum_file;
445             }
446              
447              
448              
449             sub expected_filename_listing {
450 2     2 1 4 my $expected_filename_listing = <<'EOC';
451             array_each(
452             array_each(any(
453             re(qr/Announcement2.\d.(html|txt)/),
454             re(qr/CHANGES_2\.\d(\.\d+)?/),
455             re(qr/CURRENT(-|_)IS(-|_)\d\.\d+?\.\d+/),
456             re(qr/
457             HEADER.html
458             |
459             KEYS
460             |
461             README.html
462             |
463             binaries
464             |
465             docs
466             |
467             flood
468             /x),
469             re(qr/httpd-2\.\d\.\d+?-win32-src\.zip(\.asc)?/),
470             re(qr/httpd-2\.\d\.\d+?\.tar\.(bz2|gz)(\.asc)?/),
471             re(qr/httpd-2\.\d\.\d+?-deps\.tar\.(bz2|gz)(\.asc)?/),
472             re(qr/
473             libapreq
474             |
475             mod_fcgid
476             |
477             mod_ftp
478             |
479             patches
480             /x),
481             re(qr/\d{10,12}/)
482             ) # end any
483             )
484             );
485             EOC
486              
487 2         563 return $expected_filename_listing;
488             }
489              
490              
491              
492             sub verbose_on {
493             # Turn on verbose functionality.
494 40     40 1 10470 $fetchware::verbose = 1;
495             }
496              
497              
498              
499             sub export_ok{
500 12     12 1 2425 my ($sorted_subs, $sorted_export) = @_;
501              
502             package main;
503 12         79 my @sorted_subs = sort @$sorted_subs;
504 12         46 my @sorted_export = sort @$sorted_export;
505              
506 12 50       27 fail("Specified arrays have a different length.\n[@sorted_subs]\n[@sorted_export]")
507             if @sorted_subs != @sorted_export;
508              
509 12         12 my $i = 0;
510 12         17 for my $e (@sorted_subs) {
511 159 50       245 if ($e eq $sorted_export[$i]) {
512 159         435 pass("[$e] matches [$sorted_export[$i]]");
513             } else {
514 0         0 fail("[$e] does *not* match [$sorted_export[$i]]");
515             }
516 159         27221 $i++;
517             }
518             }
519              
520              
521              
522             sub end_ok {
523 0     0 1 0 my $temp_dir = shift;
524              
525 0         0 ok(open(my $fh_sem, '>', catfile($temp_dir, 'fetchware.sem')),
526             'checked cleanup_tempdir() open fetchware lock file success.');
527 0         0 ok( flock($fh_sem, LOCK_EX | LOCK_NB),
528             'checked cleanup_tempdir() success.');
529 0         0 ok(close $fh_sem,
530             'checked cleanup_tempdir() released fetchware lock file success.');
531             }
532              
533              
534              
535             sub add_prefix_if_nonroot {
536 203     203 1 293 my $callback = shift;
537 203         211 my $prefix;
538 203 50 33     1492 if (not is_os_type('Unix') or $> != 0 ) {
539 0 0       0 if (not defined $callback) {
540 0         0 $prefix = tempdir("fetchware-test-$$-XXXXXXXXXX",
541             TMPDIR => 1, CLEANUP => 1);
542 0         0 note("Running as nonroot or nonunix using prefix temp dir [$prefix]");
543 0         0 config(prefix => $prefix);
544             } else {
545 0         0 ok(ref $callback eq 'CODE', <
546             Received callback that is a proper coderef [$callback].
547             EOD
548 0         0 $prefix = $callback->();
549             }
550            
551             # Return the prefix that will be used.
552 0         0 return $prefix;
553             } else {
554             # Return undef meaning no prefix was added.
555 203         5705 return;
556             }
557             }
558              
559              
560              
561             sub create_test_fetchwarefile {
562 0     0 1 0 my $fetchwarefile_content = shift;
563              
564             # Use a temp dir outside of the installation directory
565 0         0 my ($fh, $fetchwarefile_path)
566             =
567             tempfile("fetchware-$$-XXXXXXXXXXXXXX", TMPDIR => 1, UNLINK => 1);
568              
569             # Chmod 644 to ensure a possibly dropped priv child can still at least read
570             # the file. It doesn't need write access just read.
571 0 0 0     0 unless (chmod 0644, $fetchwarefile_path
572             and
573             # Only Unix drops privs. Nonunix does not.
574             is_os_type('Unix')
575             ) {
576 0         0 die <
577             fetchware: Failed to chmod 0644, [$fetchwarefile_path]! This is a fatal error,
578             because if the file is not chmod()ed, then fetchware cannot access the file if
579             it was created by root, and then tried to read it, but root on Unix dropped
580             privs. OS error [$!].
581             EOD
582             }
583              
584             # Be sure to add a prefix to the generated Fetchwarefile if fetchware is not
585             # running as root to ensure that our test installs succeed.
586             #
587             # Prepend a newline to ensure that prefix is not added to an existing line.
588             add_prefix_if_nonroot(sub {
589 0     0   0 my $prefix_dir = tempdir("fetchware-test-$$-XXXXXXXXXX",
590             TMPDIR => 1, CLEANUP => 1);
591 0         0 $fetchwarefile_content
592             .=
593             "\nprefix '$prefix_dir';";
594             }
595 0         0 );
596              
597             # Put test stuff in Fetchwarefile.
598 0         0 print $fh "$fetchwarefile_content";
599              
600             # Close the file in case it bothers Archive::Tar reading it.
601 0         0 close $fh;
602              
603 0         0 return $fetchwarefile_path;
604             }
605              
606              
607              
608             sub rmdashr_ok {
609 4     4 1 8110 my ($dir_to_recursive_delete, $test_message) = @_;
610              
611             # If $dir_to_recursive_delete is just a file, just unlink it.
612 4 100       40 if (not -d $dir_to_recursive_delete) {
613 1 50       31 unlink($dir_to_recursive_delete)
614             or fail("Failed to unlink([$dir_to_recursive_delete]): $!")
615             } else {
616             # Delete the whole $tempdir. Use error and result for File::Path's
617             # experimental error handling, and set safe to true to avoid borking the
618             # filesystem. This might be run as root, so it really could screw up
619             # your filesystem big time! So set safe to true to avoid doing so.
620 3         7511 my $ok = remove_tree($dir_to_recursive_delete, {
621             error => \my $err,
622             result => \my $res,
623             safe => 1} );
624              
625             # Parse remove_tree()'s insane error handling system. It's expirimental,
626             # but it's been experimental forever, so I can't see it changing.
627 3 50       1084 if (@$err) {
628 0         0 for my $diag (@$err) {
629 0         0 my ($file, $message) = %$diag;
630 0 0       0 if ($file eq '') {
631 0         0 warn "general error: $message\n";
632             } else {
633 0         0 warn "problem unlinking $file: $message\n";
634             }
635             }
636             } else {
637 3         18 note("No errors encountered during removal of [$dir_to_recursive_delete]\n");
638             }
639              
640              
641             # Summarize success or failure for user, so he doesn't have to dig
642             # through a bunch of error messages to see if it worked right.
643 3 50       224 note < 0;
644 0         0 rmdashr_ok() had [@{[scalar @$err]}] files give errors.
645             EOM
646 3 50       11 note < 0;
647 3         19 rmdashr_ok() successfully deleted [@{[scalar @$res]}] directories.
648             EOM
649              
650 3         110 ok($ok > 0, $test_message);
651             }
652             }
653              
654              
655              
656             ###BUGALERT### Create a frt() subroutine to mirror my frt bash function that
657             #will work like Util's config() does, but access %ENV instead of %CONFIG, and if
658             #the requested env var does not exist it will print a failure mesage using
659             #fail(). I could also use this function as a place to paste in frt() as well.
660              
661              
662             1;
663              
664             =pod
665              
666             =head1 NAME
667              
668             Test::Fetchware - Provides testing subroutines for App::Fetchware.
669              
670             =head1 VERSION
671              
672             version 1.016
673              
674             =head1 SYNOPSIS
675              
676             use Test::Fetchware ':TESTING';
677              
678             eval_ok($code, $expected_exception_text_or_regex, $test_name);
679             eval_ok(sub { some_code_that_dies()},
680             <
681             some_code_that_dies() died with this message!
682             EOE
683             eval_ok(sub { some_code_whose_messages_change(),
684             qr/A regex that matches some_code_whose_messages_change() error message/,
685             'checked some_code_whose_messages_change() exception');
686              
687             print_ok(\&printer, $expected, $test_name);
688             print_ok(sub { some_func_that_prints()},
689             \$expected, 'checked some_func_that_prints() printed $expected');
690             print_ok(sub {some_func_that_prints()},
691             qr/some regex that matches what some_func_that_prints() prints/,
692             'checked some_func_that_prints() printed matched expected regex');
693             print_ok(sub { some_func_that_prints()},
694              
695             sub { # a coderef that returns true of some_func_that_prints() printed what it
696             #should print and returns false if it did not
697             }, 'checked some_func_that_prints() printed matched coderefs expectations.');
698              
699             subtest 'some subtest that tests fetchware' => sub {
700             skip_all_unless_release_testing();
701              
702             # ... Your tests go here that will be skipped unless
703             # FETCHWARE_RELEASE_TESTING among other env vars are set properly.
704             };
705              
706             make_clean();
707              
708             my $test_dist_path = make_test_dist(
709             file_name => $file_name,
710             ver_num = $ver_num,
711             # These are all optional...
712             destination_directory => rel2abs($destination_directory),
713             fetchwarefile => $fetchwarefile,
714             # You can only specify fetchwarefile *or* append_option.
715             append_option => q{fetchware_option 'some value';},
716             configure => <
717             #!/bin/sh
718              
719             # A test ./configure for testing ./configure failure...it always fails.
720              
721             echo "fetchware: ./configure failed!
722             # Return failure exit status to truly indicate failure.
723             exit 1
724             EOF
725             makefile => <
726             # Test Makefile.
727             all:
728             sh -c 'echo "fetchware make failed!"'
729             EOF
730             );
731              
732             my $md5sum_fil_path = md5sum_file($archive_to_md5);
733              
734              
735             my $expected_filename_listing = expected_filename_listing()
736              
737             =head1 DESCRIPTION
738              
739             These subroutines provide miscellaneous subroutines that App::Fetchware's test
740             suite uses. Some are quite specific such as make_test_dist(), while others are
741             simple subroutines replacing entire CPAN modules such as eval_ok (similar to
742             Test::Exception) and print_ok (similar to Test::Output). I wrote them instead of
743             using the CPAN dependency, because all it would take is a relatively simple
744             function that I could easily write and test. And their interfaces disagreed with
745             me.
746              
747             =head1 TESTING SUBROUTINES
748              
749             =head2 eval_ok()
750              
751             eval_ok($code, $expected_exception_text_or_regex, $test_name);
752              
753             Executes the $code coderef, and compares its thrown exception, C<$@>, to
754             $expected_exception_text_or_regex, and uses $test_name as the name for the test if
755             provided.
756              
757             If $expected_exception_text_or_regex is a string then Test::More's is() is used,
758             and if $expected_exception_text_or_regex is a C<'Regexp'> according to ref(),
759             then like() is used, which will treat $expected_exception_text_or_regex as a
760             regex instead of as just a string.
761              
762             =head2 print_ok()
763              
764             print_ok(\&printer, $expected, $test_name);
765              
766             Tests if $expected is in the output that C<\&printer-E()> produces on C.
767              
768             It passes $test_name along to the underlying L function that it uses
769             to do the test.
770              
771             $expected can be a C, C, or C as returned by Perl's
772             L function.
773              
774             =over
775              
776             =item * If $expected is a SCALAR according to ref()
777              
778             =over
779              
780             =item * Then Use eq to determine if the test passes.
781              
782             =back
783              
784             =item * If $expected is a Regexp according to ref()
785              
786             =over
787              
788             =item * Then use a regex comparision just like Test::More's like() function.
789              
790             =back
791              
792             =item * If $expected is a CODEREF according to ref()
793              
794             =over
795              
796             =item * Then execute the coderef with a copy of the $printer's STDOUT and use the result of that expression to determine if the test passed or failed .
797              
798             =back
799              
800             =back
801              
802             =over
803              
804             NOTICE: C manipuation of STDOUT only works for the current Perl
805             process. STDOUT may be inherited by forks, but for some reason my knowledge of
806             Perl and Unix lacks a better explanation other than that print_ok() does not
807             work for testing what C and C processes do such as those
808             executed with run_prog().
809              
810             I also have not tested other possibilities, such as using IO::Handle to
811             manipulate STDOUT, or tie()ing STDOUT like Test::Output does. These methods
812             probably would not survive a fork() and an exec() though either.
813              
814             =back
815              
816             =head2 fork_ok()
817              
818             fork_ok(&code_fork_should_do, $test_name);
819              
820             Simply properly forks, and runs the caller's provided coderef in the child,
821             and tests that the child's exit value is 0 for success using a simple ok() call from
822             Test::More. The child's exit value is controlled by the caller based on what
823             &code_fork_should_do returns. If &code_fork_should_do returns true, then the
824             child returns C<0> for success, and if &code_fork_should_do returns false, then
825             the child returns C<1> for failure.
826              
827             Because the fork()ed child is a copy of the current perl process you can still
828             access whatever Test::More or Test::Fetchware testing subroutines you may have
829             imported for use in the test file that uses fork_ok().
830              
831             This testing helper subroutine only exists for testing fetchware's command line
832             interface. This interface is fetchware's run() subroutine and when you actually
833             execute the fetchware program from the command line such as C.
834              
835             =over
836              
837             =item WARNING
838              
839             fork_ok() has a major bug that makes any tests you attempt to run in
840             &code_fork_should_do that fail never report this failure properly to
841             Test::Builder. Also, any success is not reported either. This is not fork_ok()'s
842             fault it is Test::Builder's fault for still not having support for forking. This
843             lack of support for forking may be fixed in Test::Builder 1.5 or perhaps 2.0,
844             but those are still in development.
845              
846             =back
847              
848             =head2 fork_not_ok()
849              
850             fork_not_ok(&code_fork_should_do, $test_name);
851              
852             The exact same thing as fork_ok() except it expects failure and reports true
853             when the provided coderef returns failure. If the provided coderef returns true,
854             then it reports failure to the test suite.
855              
856             The same warnings and problems associated with fork_ok() apply to fork_not_ok().
857              
858             =head2 skip_all_unless_release_testing()
859              
860             subtest 'some subtest that tests fetchware' => sub {
861             skip_all_unless_release_testing();
862              
863             # ... Your tests go here that will be skipped unless
864             # FETCHWARE_RELEASE_TESTING among other env vars are set properly.
865             };
866              
867             Skips all tests in your test file or subtest() if fetchware's testing
868             environment variable, C, is not set to its proper
869             value. See L
870             for more information.
871              
872             =over
873              
874             =item WARNING
875              
876             If you call skip_all_unless_release_testing() in your main test file without
877             being enclosed inside a subtest, then skip_all_unless_release_testing() will
878             skip all of your test from that point on till then end of the file, so be
879             careful where you use it, or just I use it in subtests to be safe.
880              
881             =back
882              
883             =head2 make_clean()
884              
885             make_clean();
886              
887             Runs C and then chdirs to the parent directory. This subroutine is
888             used in build() and install()'s test scripts to run make clean in between test
889             runs. If you override build() or install() you may wish to use make_clean to
890             automate this for you.
891              
892             make_clean() also makes some simple checks to ensure that you are not running it
893             inside of fetchware's own build directory. If it detects this, it BAIL_OUT()'s
894             of the test file to indicate that the test file has gone crazy, and is about to
895             do something it shouldn't.
896              
897             =head2 make_test_dist()
898              
899             my $test_dist_path = make_test_dist(
900             file_name => $file_name,
901             ver_num = $ver_num,
902             # These are all optional...
903             destination_directory => rel2abs($destination_directory),
904             fetchwarefile => $fetchwarefile,
905             # You can only specify fetchwarefile *or* append_option.
906             append_option => q{fetchware_option 'some value';},
907             configure => <
908             #!/bin/sh
909              
910             # A test ./configure for testing ./configure failure...it always fails.
911              
912             echo "fetchware: ./configure failed!
913             # Return failure exit status to truly indicate failure.
914             exit 1
915             EOF
916             makefile => <
917             # Test Makefile.
918             all:
919             sh -c 'echo "fetchware make failed!"'
920             EOF
921             );
922              
923             Makes a C<$filename-$ver_num.fpkg> fetchware package that can be used for
924             testing fetchware's functionality without actually installing anything.
925              
926             Reuses create_tempdir() to create a temp directory that is used to put the
927             test-dist's files in. Then an archive is created based on original_cwd() or
928             $destination_directory if provided, which is the current working directory
929             before you call make_test_dist(). After the archive is created in original_cwd(),
930             make_test_dist() deletes the $temp_dir using cleanup_tempdir().
931              
932             If $destination_directory is not provided as an argument, then make_test_dist()
933             will just use tmpdir(), File::Spec's location for your system's temporary
934             directory.
935              
936             Returns the full path to the created test-dist fetchwware package.
937              
938             make_test_dist() supports customizing the C, C<./configure>, and
939             C of the generated make_test_dist():
940              
941             =over
942              
943             =item * C - option takes a string that will be written to disk as that test dist's actual Fetchwarefile.
944              
945             =item * C - option confilicts with fetchwarefile option, so only one or the other can be used at the same time. C quite literally just appends a fetchware option (or any other string) to the default C
946              
947             =item * C - option takes a string that will completely replace the default ./configure file in your generated test dist. This file is expected to be a shell script by fetchware, but will probably transition into being a perl script file for better Windows support in the future.
948              
949             =item * C - option takes a string that will completely replace the default Makefile that is placed in your generated test dist. This file is expected to actually be a real Makefile.
950              
951             =back
952              
953             =over
954              
955             =item WARNING
956              
957             When you specify your own $destination_directory, you must also B that
958             it's permissions are C<0755>, because during testing fetchware may drop_privs()
959             causing it to lose its ability to access the $destination_directory. Therefore,
960             when specifying your own $destination_directory, please C it to to
961             C<0755> to ensure its child can still access the test distribution in your
962             $destination_directory.
963              
964             =back
965              
966             =head2 md5sum_file()
967              
968             my $md5sum_fil_path = md5sum_file($archive_to_md5);
969              
970             Uses Digest::MD5 to generate a md5sum just like the md5sum program does, and
971             instead of returning the output it returns the full path to a file containing
972             the md5sum called C<"$archive_to_md5.md5">.
973              
974             =head2 expected_filename_listing()
975              
976             cmd_deeply($got_filelisting, eval(expected_filename_listing()),
977             'test name');
978              
979             Returns a crazy string meant for use with Test::Deep for testing that Apache
980             directory listings have been parsed correctly by lookup().
981              
982             You must surround expected_filename_listing() with an eval, because Test::Deep's
983             crazy subroutines for creating complex data structure tests are actual
984             subroutines that need to be executed. They are not strings that can just be
985             returned by expected_filename_listing(), and then forwarded along to Test::Deep,
986             they must be executed:
987              
988             cmd_deeply($got_filelisting, eval(expected_filename_listing()),
989             'test name');
990              
991             =head2 verbose_on()
992              
993             verbose_on();
994              
995             Just turns C<$fetchware::vebose> on, by setting it to 1. It does not do anything
996             else. There is no corresponding verbose_off(). Just a vebose_on().
997              
998             Meant to be used in test suites, so that you can see any vmsg()s that print
999             during testing for debugging purposes.
1000              
1001             =head2 export_ok()
1002              
1003             export_ok($sorted_subs, $sorted_export);
1004            
1005             my @api_subs
1006             = qw(start lookup download verify unarchive build install uninstall);
1007             export_ok(\@api_subs, \@TestPackage::EXPORT);
1008              
1009             Just loops over C<@{$sorted_subs}>, and array ref, and ensures that each one
1010             matches the same element of C<@{$sorted_export}>. You do not have to pre sort
1011             these array refs, because export_ok() will copy them, and sort that copy of
1012             them. Uses Test::More's pass() or fail() for each element in the arrays.
1013              
1014             =head2 end_ok()
1015              
1016             Because end() no longer uses File::Temp's cleanup() to delete B temporary
1017             File::Temp managed temporary directories when end() is called, you can no longer
1018             test end() we a simple C; instead, you should
1019             use this testing subroutine. It tests if the specified $temp_dir still has a
1020             locked C<'fetchware.sem'> fetchware semaphore file. If the file is not locked,
1021             then end_ok() reports success, but if it cannot obtain a lock, end_ok reports
1022             failure simply using ok().
1023              
1024             =head2 add_prefix_if_nonroot()
1025              
1026             my $prefix = add_prefix_if_nonroot();
1027              
1028             my $callbacks_return_value = add_prefix_if_nonroot(sub { a callback });
1029              
1030             fetchware is designed to be run as root, and to install system software in
1031             system directories requiring root privileges. But, fetchware is flexible enough
1032             to let you specifiy where you want the software you're going to install be
1033             installed via the prefix configuration option. This subroutine when run creates
1034             a temporary directory in File::Spec's tmpdir(), and then it directly runs
1035             config() itself to create this config option for you.
1036              
1037             However, if you supply a coderef, add_prefix_if_nonroot() will instead call your
1038             coderef instead of using config() directly. If your callback returns a scalar
1039             such as the temporary directory that add_prefix_if_nonroot() normally returns,
1040             this scalar is also returned back to the caller.
1041              
1042             It returns the path of the prefix that it configured for use, or it returns
1043             false if it's conditions were not met causing it not to add a prefix.
1044              
1045             =head2 create_test_fetchwarefile()
1046              
1047             my $fetchwarefile_path = create_test_fetchwarefile($fetchwarefile_content);
1048              
1049             Writes the provided $fetchwarefile_content to a C inside a
1050             File::Temp::tempfile(), and returns that file's path, $fetchwarefile_path.
1051              
1052             =head2 rmdashr_ok()
1053              
1054             rmdashr_ok($dir_to_recursive_delete, $test_message)
1055              
1056             Recursively deletes the specified directory using L's remove_tree()
1057             subroutine. Returns nothing, but does call L's ok() for you with
1058             your $test_message if remove_tree() was successful.
1059              
1060             =over
1061              
1062             =item NOTE:
1063              
1064             rmdashr_ok() reports its test as PASS if I number of files are successfully
1065             deleted. It only reports FAIL if I directories were deleted. L's
1066             note() is used to print out verbose info about exactly what files were deleted,
1067             any errors, and number or errors/warnings and successfully deleted files are
1068             printed using note(), which only shows the output if prove(1)'s C<-v> switch is
1069             used.
1070              
1071             =back
1072              
1073             =head1 ERRORS
1074              
1075             As with the rest of App::Fetchware, Test::Fetchware does not return any error
1076             codes; instead, all errors are die()'d if it's Test::Fetchware's error, or
1077             croak()'d if its the caller's fault. These exceptions are simple strings, and
1078             usually more than just one line long to help further describe the problem to
1079             make fixing it easier.
1080              
1081             =head1 SEE ALSO
1082              
1083             L is similar to Test::Fetchware's eval_ok().
1084              
1085             L is similar to Test::Fetchware's print_ok().
1086              
1087             =head1 AUTHOR
1088              
1089             David Yingling
1090              
1091             =head1 COPYRIGHT AND LICENSE
1092              
1093             This software is copyright (c) 2016 by David Yingling.
1094              
1095             This is free software; you can redistribute it and/or modify it under
1096             the same terms as the Perl 5 programming language system itself.
1097              
1098             =cut
1099              
1100             __END__