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