summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/perl/cpan/File-Path/t/FilePathTest.pm
blob: 88b411d4bb3c24834c1321dbad0a52cd8e8240c7 (plain)
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;