1b8851fccSafresh1package FilePathTest; 2b8851fccSafresh1use strict; 3b8851fccSafresh1use warnings; 4b8851fccSafresh1use base 'Exporter'; 5b8851fccSafresh1use SelectSaver; 6*2e109fb9Safresh1use Carp; 7b8851fccSafresh1use Cwd; 8b8851fccSafresh1use File::Spec::Functions; 9*2e109fb9Safresh1use File::Path (); 10*2e109fb9Safresh1use Test::More (); 11b8851fccSafresh1 12*2e109fb9Safresh1our @EXPORT_OK = qw( 13*2e109fb9Safresh1 _run_for_warning 14*2e109fb9Safresh1 _run_for_verbose 15b8851fccSafresh1 _cannot_delete_safe_mode 16*2e109fb9Safresh1 _verbose_expected 17*2e109fb9Safresh1 create_3_level_subdirs 18*2e109fb9Safresh1 cleanup_3_level_subdirs 19014083a1Safresh1); 20c0dd97bfSafresh1 21*2e109fb9Safresh1sub _basedir { 22*2e109fb9Safresh1 return catdir( 23*2e109fb9Safresh1 curdir(), 24*2e109fb9Safresh1 sprintf( 'test-%x-%x-%x', time, $$, rand(99999) ), 25*2e109fb9Safresh1 ); 26b8851fccSafresh1} 27b8851fccSafresh1 28b8851fccSafresh1sub _run_for_warning { 29b8851fccSafresh1 my $coderef = shift; 30b8851fccSafresh1 my $warn = ''; 31b8851fccSafresh1 local $SIG{__WARN__} = sub { $warn .= shift }; 32b8851fccSafresh1 &$coderef; 33b8851fccSafresh1 return $warn; 34b8851fccSafresh1} 35b8851fccSafresh1 36b8851fccSafresh1sub _run_for_verbose { 37b8851fccSafresh1 my $coderef = shift; 38b8851fccSafresh1 my $stdout = ''; 39b8851fccSafresh1 { 40b8851fccSafresh1 my $guard = SelectSaver->new(_ref_to_fh(\$stdout)); 41b8851fccSafresh1 &$coderef; 42b8851fccSafresh1 } 43b8851fccSafresh1 return $stdout; 44b8851fccSafresh1} 45b8851fccSafresh1 46b8851fccSafresh1sub _ref_to_fh { 47b8851fccSafresh1 my $output = shift; 48b8851fccSafresh1 open my $fh, '>', $output; 49b8851fccSafresh1 return $fh; 50b8851fccSafresh1} 51b8851fccSafresh1 52b8851fccSafresh1# Whether a directory can be deleted without modifying permissions varies 53b8851fccSafresh1# by platform and by current privileges, so we really have to do the same 54b8851fccSafresh1# check the module does in safe mode to determine that. 55b8851fccSafresh1 56b8851fccSafresh1sub _cannot_delete_safe_mode { 57b8851fccSafresh1 my $path = shift; 58b8851fccSafresh1 return $^O eq 'VMS' 59b8851fccSafresh1 ? !&VMS::Filespec::candelete($path) 60b8851fccSafresh1 : !-w $path; 61b8851fccSafresh1} 62b8851fccSafresh1 63b8851fccSafresh1# What verbose mode reports depends on what it can do in safe mode. 64b8851fccSafresh1# Plus on VMS, mkpath may report what it's operating on in a 65b8851fccSafresh1# different format from the format of the path passed to it. 66b8851fccSafresh1 67b8851fccSafresh1sub _verbose_expected { 68b8851fccSafresh1 my ($function, $path, $safe_mode, $base) = @_; 69b8851fccSafresh1 my $expected; 70b8851fccSafresh1 71b8851fccSafresh1 if ($function =~ m/^(mkpath|make_path)$/) { 72b8851fccSafresh1 # On VMS, mkpath reports in Unix format. Maddeningly, it 73b8851fccSafresh1 # reports the top-level directory without a trailing slash 74b8851fccSafresh1 # and everything else with. 75b8851fccSafresh1 if ($^O eq 'VMS') { 76b8851fccSafresh1 $path = VMS::Filespec::unixify($path); 77b8851fccSafresh1 $path =~ s/\/$// if defined $base && $base; 78b8851fccSafresh1 } 79b8851fccSafresh1 $expected = "mkdir $path\n"; 80b8851fccSafresh1 } 81b8851fccSafresh1 elsif ($function =~ m/^(rmtree|remove_tree)$/) { 82b8851fccSafresh1 # N.B. Directories must still/already exist for this to work. 83b8851fccSafresh1 $expected = $safe_mode && _cannot_delete_safe_mode($path) 84b8851fccSafresh1 ? "skipped $path\n" 85b8851fccSafresh1 : "rmdir $path\n"; 86b8851fccSafresh1 } 87b8851fccSafresh1 elsif ($function =~ m/^(unlink)$/) { 88b8851fccSafresh1 $expected = "unlink $path\n"; 89b8851fccSafresh1 $expected =~ s/\n\z/\.\n/ if $^O eq 'VMS'; 90b8851fccSafresh1 } 91b8851fccSafresh1 else { 92b8851fccSafresh1 die "Unknown function $function in _verbose_expected"; 93b8851fccSafresh1 } 94b8851fccSafresh1 return $expected; 95b8851fccSafresh1} 96b8851fccSafresh1 97b8851fccSafresh1BEGIN { 98b8851fccSafresh1 if ($] < 5.008000) { 99b8851fccSafresh1 eval qq{#line @{[__LINE__+1]} "@{[__FILE__]}"\n} . <<'END' or die $@; 100b8851fccSafresh1 no warnings 'redefine'; 101b8851fccSafresh1 use Symbol (); 102b8851fccSafresh1 103b8851fccSafresh1 sub _ref_to_fh { 104b8851fccSafresh1 my $output = shift; 105b8851fccSafresh1 my $fh = Symbol::gensym(); 106b8851fccSafresh1 tie *$fh, 'StringIO', $output; 107b8851fccSafresh1 return $fh; 108b8851fccSafresh1 } 109b8851fccSafresh1 110b8851fccSafresh1 package StringIO; 111b8851fccSafresh1 sub TIEHANDLE { bless [ $_[1] ], $_[0] } 112b8851fccSafresh1 sub CLOSE { @{$_[0]} = (); 1 } 113b8851fccSafresh1 sub PRINT { ${ $_[0][0] } .= $_[1] } 114b8851fccSafresh1 sub PRINTF { ${ $_[0][0] } .= sprintf $_[1], @_[2..$#_] } 115b8851fccSafresh1 1; 116b8851fccSafresh1END 117b8851fccSafresh1 } 118b8851fccSafresh1} 119b8851fccSafresh1 120*2e109fb9Safresh1sub create_3_level_subdirs { 121*2e109fb9Safresh1 my @dirnames = @_; 122*2e109fb9Safresh1 my %seen = map {$_ => 1} @dirnames; 123*2e109fb9Safresh1 croak "Need 3 distinct names for subdirectories" 124*2e109fb9Safresh1 unless scalar(keys %seen) == 3; 125*2e109fb9Safresh1 my $tdir = File::Spec::Functions::tmpdir(); 126*2e109fb9Safresh1 my $least_deep = catdir($tdir, $dirnames[0]); 127*2e109fb9Safresh1 my $next_deepest = catdir($least_deep, $dirnames[1]); 128*2e109fb9Safresh1 my $deepest = catdir($next_deepest, $dirnames[2]); 129*2e109fb9Safresh1 return ($least_deep, $next_deepest, $deepest); 130*2e109fb9Safresh1} 131*2e109fb9Safresh1 132*2e109fb9Safresh1sub cleanup_3_level_subdirs { 133*2e109fb9Safresh1 # runs 2 tests 134*2e109fb9Safresh1 my $least_deep = shift; 135*2e109fb9Safresh1 croak "Must provide path of least subdirectory" 136*2e109fb9Safresh1 unless (length($least_deep) and (-d $least_deep)); 137*2e109fb9Safresh1 my $x; 138*2e109fb9Safresh1 my $opts = { error => \$x }; 139*2e109fb9Safresh1 File::Path::remove_tree($least_deep, $opts); 140*2e109fb9Safresh1 Test::More::ok(! -d $least_deep, "directory '$least_deep' removed, as expected"); 141*2e109fb9Safresh1 Test::More::is(scalar(@{$x}), 0, "no error messages using remove_tree() with \$opts"); 142*2e109fb9Safresh1} 143*2e109fb9Safresh1 144b8851fccSafresh11; 145