xref: /openbsd-src/gnu/usr.bin/perl/cpan/File-Path/t/Path.t (revision eac174f2741a08d8deb8aae59a7f778ef9b5d770)
1b8851fccSafresh1#! /usr/bin/env perl
2b39c5158Smillert# Path.t -- tests for module File::Path
3b39c5158Smillert
4b39c5158Smillertuse strict;
5b39c5158Smillert
6*eac174f2Safresh1use Test::More tests => 167;
7b39c5158Smillertuse Config;
8b8851fccSafresh1use Fcntl ':mode';
92e109fb9Safresh1use lib './t';
102e109fb9Safresh1use FilePathTest qw(
112e109fb9Safresh1    _run_for_warning
122e109fb9Safresh1    _run_for_verbose
132e109fb9Safresh1    _cannot_delete_safe_mode
142e109fb9Safresh1    _verbose_expected
152e109fb9Safresh1    create_3_level_subdirs
162e109fb9Safresh1    cleanup_3_level_subdirs
172e109fb9Safresh1);
182e109fb9Safresh1use Errno qw(:POSIX);
192e109fb9Safresh1use Carp;
20b39c5158Smillert
21b39c5158SmillertBEGIN {
22b39c5158Smillert    use_ok('Cwd');
23b39c5158Smillert    use_ok('File::Path', qw(rmtree mkpath make_path remove_tree));
24b39c5158Smillert    use_ok('File::Spec::Functions');
25b39c5158Smillert}
26b39c5158Smillert
27b39c5158Smillertmy $Is_VMS = $^O eq 'VMS';
28b39c5158Smillert
292e109fb9Safresh1my $fchmod_supported = 0;
302e109fb9Safresh1if (open my $fh, curdir()) {
312e109fb9Safresh1    my ($perm) = (stat($fh))[2];
322e109fb9Safresh1    $perm &= 07777;
332e109fb9Safresh1    eval { $fchmod_supported = chmod( $perm, $fh); };
342e109fb9Safresh1}
352e109fb9Safresh1
36b39c5158Smillert# first check for stupid permissions second for full, so we clean up
37b39c5158Smillert# behind ourselves
38b39c5158Smillertfor my $perm (0111,0777) {
39b39c5158Smillert    my $path = catdir(curdir(), "mhx", "bar");
40b39c5158Smillert    mkpath($path);
41b39c5158Smillert    chmod $perm, "mhx", $path;
42b39c5158Smillert
43b39c5158Smillert    my $oct = sprintf('0%o', $perm);
44b8851fccSafresh1
45b39c5158Smillert    ok(-d "mhx", "mkdir parent dir $oct");
46b39c5158Smillert    ok(-d $path, "mkdir child dir $oct");
47b39c5158Smillert
48b39c5158Smillert    rmtree("mhx");
49b8851fccSafresh1
50b39c5158Smillert    ok(! -e "mhx", "mhx does not exist $oct");
51b39c5158Smillert}
52b39c5158Smillert
53b39c5158Smillert# find a place to work
54b39c5158Smillertmy ($error, $list, $file, $message);
55b39c5158Smillertmy $tmp_base = catdir(
56b39c5158Smillert    curdir(),
57b39c5158Smillert    sprintf( 'test-%x-%x-%x', time, $$, rand(99999) ),
58b39c5158Smillert);
59b39c5158Smillert
60b39c5158Smillert# invent some names
61b39c5158Smillertmy @dir = (
62b39c5158Smillert    catdir($tmp_base, qw(a b)),
63b39c5158Smillert    catdir($tmp_base, qw(a c)),
64b39c5158Smillert    catdir($tmp_base, qw(z b)),
65b39c5158Smillert    catdir($tmp_base, qw(z c)),
66b39c5158Smillert);
67b39c5158Smillert
68b39c5158Smillert# create them
69b39c5158Smillertmy @created = mkpath([@dir]);
70b39c5158Smillert
71b39c5158Smillertis(scalar(@created), 7, "created list of directories");
72b39c5158Smillert
73b39c5158Smillert# pray for no race conditions blowing them out from under us
74b39c5158Smillert@created = mkpath([$tmp_base]);
75b39c5158Smillertis(scalar(@created), 0, "skipped making existing directory")
76b39c5158Smillert    or diag("unexpectedly recreated @created");
77b39c5158Smillert
78b39c5158Smillert# create a file
79b39c5158Smillertmy $file_name = catfile( $tmp_base, 'a', 'delete.me' );
80b39c5158Smillertmy $file_count = 0;
81b39c5158Smillertif (open OUT, "> $file_name") {
82b39c5158Smillert    print OUT "this file may be deleted\n";
83b39c5158Smillert    close OUT;
84b39c5158Smillert    ++$file_count;
85b39c5158Smillert}
86b39c5158Smillertelse {
87b39c5158Smillert    diag( "Failed to create file $file_name: $!" );
88b39c5158Smillert}
89b39c5158Smillert
90b39c5158SmillertSKIP: {
91b39c5158Smillert    skip "cannot remove a file we failed to create", 1
92b39c5158Smillert        unless $file_count == 1;
93b39c5158Smillert    my $count = rmtree($file_name);
94b39c5158Smillert    is($count, 1, "rmtree'ed a file");
95b39c5158Smillert}
96b39c5158Smillert
97b39c5158Smillert@created = mkpath('');
98b39c5158Smillertis(scalar(@created), 0, "Can't create a directory named ''");
99b39c5158Smillert
100b39c5158Smillertmy $dir;
101b39c5158Smillertmy $dir2;
102b39c5158Smillert
103b39c5158Smillertsub gisle {
104b39c5158Smillert    # background info: @_ = 1; !shift # gives '' not 0
105b39c5158Smillert    # Message-Id: <3C820CE6-4400-4E91-AF43-A3D19B356E68@activestate.com>
106b39c5158Smillert    # http://www.nntp.perl.org/group/perl.perl5.porters/2008/05/msg136625.html
107b39c5158Smillert    mkpath(shift, !shift, 0755);
108b39c5158Smillert}
109b39c5158Smillert
110b39c5158Smillertsub count {
111b39c5158Smillert    opendir D, shift or return -1;
112b39c5158Smillert    my $count = () = readdir D;
113b39c5158Smillert    closedir D or return -1;
114b39c5158Smillert    return $count;
115b39c5158Smillert}
116b39c5158Smillert
117b39c5158Smillert{
118b39c5158Smillert    mkdir 'solo', 0755;
119b39c5158Smillert    chdir 'solo';
120b39c5158Smillert    open my $f, '>', 'foo.dat';
121b39c5158Smillert    close $f;
122b39c5158Smillert    my $before = count(curdir());
123b39c5158Smillert    cmp_ok($before, '>', 0, "baseline $before");
124b39c5158Smillert
125b39c5158Smillert    gisle('1st', 1);
126b39c5158Smillert    is(count(curdir()), $before + 1, "first after $before");
127b39c5158Smillert
128b39c5158Smillert    $before = count(curdir());
129b39c5158Smillert    gisle('2nd', 1);
130b8851fccSafresh1
131b39c5158Smillert    is(count(curdir()), $before + 1, "second after $before");
132b39c5158Smillert
133b39c5158Smillert    chdir updir();
134b39c5158Smillert    rmtree 'solo';
135b39c5158Smillert}
136b39c5158Smillert
137b39c5158Smillert{
138b39c5158Smillert    mkdir 'solo', 0755;
139b39c5158Smillert    chdir 'solo';
140b39c5158Smillert    open my $f, '>', 'foo.dat';
141b39c5158Smillert    close $f;
142b39c5158Smillert    my $before = count(curdir());
143b8851fccSafresh1
144b39c5158Smillert    cmp_ok($before, '>', 0, "ARGV $before");
145b39c5158Smillert    {
146b39c5158Smillert        local @ARGV = (1);
147b39c5158Smillert        mkpath('3rd', !shift, 0755);
148b39c5158Smillert    }
149b8851fccSafresh1
150b39c5158Smillert    is(count(curdir()), $before + 1, "third after $before");
151b39c5158Smillert
152b39c5158Smillert    $before = count(curdir());
153b39c5158Smillert    {
154b39c5158Smillert        local @ARGV = (1);
155b39c5158Smillert        mkpath('4th', !shift, 0755);
156b39c5158Smillert    }
157b8851fccSafresh1
158b39c5158Smillert    is(count(curdir()), $before + 1, "fourth after $before");
159b39c5158Smillert
160b39c5158Smillert    chdir updir();
161b39c5158Smillert    rmtree 'solo';
162b39c5158Smillert}
163b39c5158Smillert
164b39c5158SmillertSKIP: {
165b39c5158Smillert    # tests for rmtree() of ancestor directory
166b39c5158Smillert    my $nr_tests = 6;
167b39c5158Smillert    my $cwd = getcwd() or skip "failed to getcwd: $!", $nr_tests;
168b39c5158Smillert    my $dir  = catdir($cwd, 'remove');
169b39c5158Smillert    my $dir2 = catdir($cwd, 'remove', 'this', 'dir');
170b39c5158Smillert
171b39c5158Smillert    skip "failed to mkpath '$dir2': $!", $nr_tests
172b39c5158Smillert        unless mkpath($dir2, {verbose => 0});
173b39c5158Smillert    skip "failed to chdir dir '$dir2': $!", $nr_tests
174b39c5158Smillert        unless chdir($dir2);
175b39c5158Smillert
176b39c5158Smillert    rmtree($dir, {error => \$error});
177b39c5158Smillert    my $nr_err = @$error;
178b8851fccSafresh1
179b39c5158Smillert    is($nr_err, 1, "ancestor error");
180b39c5158Smillert
181b39c5158Smillert    if ($nr_err) {
182b39c5158Smillert        my ($file, $message) = each %{$error->[0]};
183b8851fccSafresh1
184b39c5158Smillert        is($file, $dir, "ancestor named");
185b39c5158Smillert        my $ortho_dir = $^O eq 'MSWin32' ? File::Path::_slash_lc($dir2) : $dir2;
186b39c5158Smillert        $^O eq 'MSWin32' and $message
187b39c5158Smillert            =~ s/\A(cannot remove path when cwd is )(.*)\Z/$1 . File::Path::_slash_lc($2)/e;
188b8851fccSafresh1
189b39c5158Smillert        is($message, "cannot remove path when cwd is $ortho_dir", "ancestor reason");
190b8851fccSafresh1
191b39c5158Smillert        ok(-d $dir2, "child not removed");
192b8851fccSafresh1
193b39c5158Smillert        ok(-d $dir, "ancestor not removed");
194b39c5158Smillert    }
195b39c5158Smillert    else {
196b39c5158Smillert        fail( "ancestor 1");
197b39c5158Smillert        fail( "ancestor 2");
198b39c5158Smillert        fail( "ancestor 3");
199b39c5158Smillert        fail( "ancestor 4");
200b39c5158Smillert    }
201b39c5158Smillert    chdir $cwd;
202b39c5158Smillert    rmtree($dir);
203b8851fccSafresh1
204b39c5158Smillert    ok(!(-d $dir), "ancestor now removed");
205b39c5158Smillert};
206b39c5158Smillert
207b39c5158Smillertmy $count = rmtree({error => \$error});
208b8851fccSafresh1
209b39c5158Smillertis( $count, 0, 'rmtree of nothing, count of zero' );
210b8851fccSafresh1
211b39c5158Smillertis( scalar(@$error), 0, 'no diagnostic captured' );
212b39c5158Smillert
213b39c5158Smillert@created = mkpath($tmp_base, 0);
214b8851fccSafresh1
215b39c5158Smillertis(scalar(@created), 0, "skipped making existing directories (old style 1)")
216b39c5158Smillert    or diag("unexpectedly recreated @created");
217b39c5158Smillert
218b39c5158Smillert$dir = catdir($tmp_base,'C');
219b39c5158Smillert# mkpath returns unix syntax filespecs on VMS
220b39c5158Smillert$dir = VMS::Filespec::unixify($dir) if $Is_VMS;
221b39c5158Smillert@created = make_path($tmp_base, $dir);
222b8851fccSafresh1
223b39c5158Smillertis(scalar(@created), 1, "created directory (new style 1)");
224b8851fccSafresh1
225b39c5158Smillertis($created[0], $dir, "created directory (new style 1) cross-check");
226b39c5158Smillert
227b39c5158Smillert@created = mkpath($tmp_base, 0, 0700);
228b8851fccSafresh1
229b39c5158Smillertis(scalar(@created), 0, "skipped making existing directories (old style 2)")
230b39c5158Smillert    or diag("unexpectedly recreated @created");
231b39c5158Smillert
232b39c5158Smillert$dir2 = catdir($tmp_base,'D');
233b39c5158Smillert# mkpath returns unix syntax filespecs on VMS
234b39c5158Smillert$dir2 = VMS::Filespec::unixify($dir2) if $Is_VMS;
235b39c5158Smillert@created = make_path($tmp_base, $dir, $dir2);
236b8851fccSafresh1
237b39c5158Smillertis(scalar(@created), 1, "created directory (new style 2)");
238b8851fccSafresh1
239b39c5158Smillertis($created[0], $dir2, "created directory (new style 2) cross-check");
240b39c5158Smillert
241b39c5158Smillert$count = rmtree($dir, 0);
242b8851fccSafresh1
243b39c5158Smillertis($count, 1, "removed directory unsafe mode");
244b39c5158Smillert
245b8851fccSafresh1my $expected_count = _cannot_delete_safe_mode($dir2) ? 0 : 1;
246b8851fccSafresh1
247b39c5158Smillert$count = rmtree($dir2, 0, 1);
248b8851fccSafresh1
249b8851fccSafresh1is($count, $expected_count, "removed directory safe mode");
250b39c5158Smillert
251b39c5158Smillert# mkdir foo ./E/../Y
252b39c5158Smillert# Y should exist
253b39c5158Smillert# existence of E is neither here nor there
254b39c5158Smillert$dir = catdir($tmp_base, 'E', updir(), 'Y');
255b39c5158Smillert@created =mkpath($dir);
256b8851fccSafresh1
257b39c5158Smillertcmp_ok(scalar(@created), '>=', 1, "made one or more dirs because of ..");
258b8851fccSafresh1
259b39c5158Smillertcmp_ok(scalar(@created), '<=', 2, "made less than two dirs because of ..");
260b8851fccSafresh1
261b39c5158Smillertok( -d catdir($tmp_base, 'Y'), "directory after parent" );
262b39c5158Smillert
263b39c5158Smillert@created = make_path(catdir(curdir(), $tmp_base));
264b8851fccSafresh1
265b39c5158Smillertis(scalar(@created), 0, "nothing created")
266b39c5158Smillert    or diag(@created);
267b39c5158Smillert
268b39c5158Smillert$dir  = catdir($tmp_base, 'a');
269b39c5158Smillert$dir2 = catdir($tmp_base, 'z');
270b39c5158Smillert
271b39c5158Smillertrmtree( $dir, $dir2,
272b39c5158Smillert    {
273b39c5158Smillert        error     => \$error,
274b39c5158Smillert        result    => \$list,
275b39c5158Smillert        keep_root => 1,
276b39c5158Smillert    }
277b39c5158Smillert);
278b39c5158Smillert
279b8851fccSafresh1
280b39c5158Smillertis(scalar(@$error), 0, "no errors unlinking a and z");
281b8851fccSafresh1
282b39c5158Smillertis(scalar(@$list),  4, "list contains 4 elements")
283b39c5158Smillert    or diag("@$list");
284b39c5158Smillert
285b39c5158Smillertok(-d $dir,  "dir a still exists");
286b8851fccSafresh1
287b39c5158Smillertok(-d $dir2, "dir z still exists");
288b39c5158Smillert
289b39c5158Smillert$dir = catdir($tmp_base,'F');
290b39c5158Smillert# mkpath returns unix syntax filespecs on VMS
291b39c5158Smillert$dir = VMS::Filespec::unixify($dir) if $Is_VMS;
292b39c5158Smillert
293b39c5158Smillert@created = mkpath($dir, undef, 0770);
294b8851fccSafresh1
295b39c5158Smillertis(scalar(@created), 1, "created directory (old style 2 verbose undef)");
296b8851fccSafresh1
297b39c5158Smillertis($created[0], $dir, "created directory (old style 2 verbose undef) cross-check");
298b8851fccSafresh1
299b39c5158Smillertis(rmtree($dir, undef, 0), 1, "removed directory 2 verbose undef");
300b39c5158Smillert
301b39c5158Smillert@created = mkpath($dir, undef);
302b8851fccSafresh1
303b39c5158Smillertis(scalar(@created), 1, "created directory (old style 2a verbose undef)");
304b8851fccSafresh1
305b39c5158Smillertis($created[0], $dir, "created directory (old style 2a verbose undef) cross-check");
306b8851fccSafresh1
307b39c5158Smillertis(rmtree($dir, undef), 1, "removed directory 2a verbose undef");
308b39c5158Smillert
309b39c5158Smillert@created = mkpath($dir, 0, undef);
310b8851fccSafresh1
311b39c5158Smillertis(scalar(@created), 1, "created directory (old style 3 mode undef)");
312b8851fccSafresh1
313b39c5158Smillertis($created[0], $dir, "created directory (old style 3 mode undef) cross-check");
314b8851fccSafresh1
315b39c5158Smillertis(rmtree($dir, 0, undef), 1, "removed directory 3 verbose undef");
316b39c5158Smillert
3172e109fb9Safresh1SKIP: {
3182e109fb9Safresh1    skip "fchmod of directories not supported on this platform", 3 unless $fchmod_supported;
319b39c5158Smillert    $dir = catdir($tmp_base,'G');
320b39c5158Smillert    $dir = VMS::Filespec::unixify($dir) if $Is_VMS;
321b39c5158Smillert
3222e109fb9Safresh1    @created = mkpath($dir, undef, 0400);
323b8851fccSafresh1
3242e109fb9Safresh1    is(scalar(@created), 1, "created read-only dir");
325b8851fccSafresh1
3262e109fb9Safresh1    is($created[0], $dir, "created read-only directory cross-check");
327b8851fccSafresh1
3282e109fb9Safresh1    is(rmtree($dir), 1, "removed read-only dir");
3292e109fb9Safresh1}
330b39c5158Smillert
331b39c5158Smillert# borderline new-style heuristics
332b39c5158Smillertif (chdir $tmp_base) {
333b39c5158Smillert    pass("chdir to temp dir");
334b39c5158Smillert}
335b39c5158Smillertelse {
336b39c5158Smillert    fail("chdir to temp dir: $!");
337b39c5158Smillert}
338b39c5158Smillert
339b39c5158Smillert$dir   = catdir('a', 'd1');
340b39c5158Smillert$dir2  = catdir('a', 'd2');
341b39c5158Smillert
342b39c5158Smillert@created = make_path( $dir, 0, $dir2 );
343b8851fccSafresh1
344b39c5158Smillertis(scalar @created, 3, 'new-style 3 dirs created');
345b39c5158Smillert
346b39c5158Smillert$count = remove_tree( $dir, 0, $dir2, );
347b8851fccSafresh1
348b39c5158Smillertis($count, 3, 'new-style 3 dirs removed');
349b39c5158Smillert
350b39c5158Smillert@created = make_path( $dir, $dir2, 1 );
351b8851fccSafresh1
352b39c5158Smillertis(scalar @created, 3, 'new-style 3 dirs created (redux)');
353b39c5158Smillert
354b39c5158Smillert$count = remove_tree( $dir, $dir2, 1 );
355b8851fccSafresh1
356b39c5158Smillertis($count, 3, 'new-style 3 dirs removed (redux)');
357b39c5158Smillert
358b39c5158Smillert@created = make_path( $dir, $dir2 );
359b8851fccSafresh1
360b39c5158Smillertis(scalar @created, 2, 'new-style 2 dirs created');
361b39c5158Smillert
362b39c5158Smillert$count = remove_tree( $dir, $dir2 );
363b8851fccSafresh1
364b39c5158Smillertis($count, 2, 'new-style 2 dirs removed');
365b39c5158Smillert
366b8851fccSafresh1$dir = catdir("a\nb", 'd1');
367b8851fccSafresh1$dir2 = catdir("a\nb", 'd2');
368b8851fccSafresh1
369b8851fccSafresh1SKIP: {
370b8851fccSafresh1  # Better to search for *nix derivatives?
371b8851fccSafresh1  # Not sure what else doesn't support newline in paths
372b8851fccSafresh1  skip "$^O doesn't allow newline in paths", 2
373b8851fccSafresh1    if $^O =~ m/^(MSWin32|VMS)$/;
374b8851fccSafresh1
375b8851fccSafresh1  @created = make_path( $dir, $dir2 );
376b8851fccSafresh1
377b8851fccSafresh1  is(scalar @created, 3, 'new-style 3 dirs created in parent with newline');
378b8851fccSafresh1
379b8851fccSafresh1  $count = remove_tree( $dir, $dir2 );
380b8851fccSafresh1
381b8851fccSafresh1  is($count, 2, 'new-style 2 dirs removed in parent with newline');
382b8851fccSafresh1}
383b8851fccSafresh1
384b39c5158Smillertif (chdir updir()) {
385b39c5158Smillert    pass("chdir parent");
386b39c5158Smillert}
387b39c5158Smillertelse {
388b39c5158Smillert    fail("chdir parent: $!");
389b39c5158Smillert}
390b39c5158Smillert
391b39c5158SmillertSKIP: {
392b39c5158Smillert    # test bug http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=487319
393b8851fccSafresh1    skip "Don't need Force_Writeable semantics on $^O", 6
394b39c5158Smillert        if grep {$^O eq $_} qw(amigaos dos epoc MSWin32 MacOS os2);
395b8851fccSafresh1    skip "Symlinks not available", 6 unless $Config{d_symlink};
396b39c5158Smillert    $dir  = 'bug487319';
397b39c5158Smillert    $dir2 = 'bug487319-symlink';
398b39c5158Smillert    @created = make_path($dir, {mask => 0700});
399b8851fccSafresh1
400b39c5158Smillert    is( scalar @created, 1, 'bug 487319 setup' );
401b39c5158Smillert    symlink($dir, $dir2);
402b8851fccSafresh1
403b39c5158Smillert    ok(-e $dir2, "debian bug 487319 setup symlink") or diag($dir2);
404b39c5158Smillert
405b39c5158Smillert    chmod 0500, $dir;
406b39c5158Smillert    my $mask_initial = (stat $dir)[2];
407b39c5158Smillert    remove_tree($dir2);
408b39c5158Smillert
409b39c5158Smillert    my $mask = (stat $dir)[2];
410b8851fccSafresh1
411b39c5158Smillert    is( $mask, $mask_initial, 'mask of symlink target dir unchanged (debian bug 487319)');
412b39c5158Smillert
413b39c5158Smillert    # now try a file
414b8851fccSafresh1    #my $file = catfile($dir, 'file');
415b8851fccSafresh1    my $file  = 'bug487319-file';
416b8851fccSafresh1    my $file2 = 'bug487319-file-symlink';
417b39c5158Smillert    open my $out, '>', $file;
418b39c5158Smillert    close $out;
419b39c5158Smillert
420b8851fccSafresh1    ok(-e $file, 'file exists');
421b8851fccSafresh1
422b39c5158Smillert    chmod 0500, $file;
423b39c5158Smillert    $mask_initial = (stat $file)[2];
424b39c5158Smillert
425b39c5158Smillert    symlink($file, $file2);
426b8851fccSafresh1
427b8851fccSafresh1    ok(-e $file2, 'file2 exists');
428b39c5158Smillert    remove_tree($file2);
429b39c5158Smillert
430b39c5158Smillert    $mask = (stat $file)[2];
431b8851fccSafresh1
432b39c5158Smillert    is( $mask, $mask_initial, 'mask of symlink target file unchanged (debian bug 487319)');
433b39c5158Smillert
434b39c5158Smillert    remove_tree($dir);
435b8851fccSafresh1    remove_tree($file);
436b39c5158Smillert}
437b39c5158Smillert
438b39c5158Smillert# see what happens if a file exists where we want a directory
439b39c5158SmillertSKIP: {
440b8851fccSafresh1    my $entry = catfile($tmp_base, "file");
441b8851fccSafresh1    skip "VMS can have a file and a directory with the same name.", 4
442b8851fccSafresh1        if $Is_VMS;
443b39c5158Smillert    skip "Cannot create $entry", 4 unless open OUT, "> $entry";
444b39c5158Smillert    print OUT "test file, safe to delete\n", scalar(localtime), "\n";
445b39c5158Smillert    close OUT;
446b39c5158Smillert    ok(-e $entry, "file exists in place of directory");
447b39c5158Smillert
448b39c5158Smillert    mkpath( $entry, {error => \$error} );
449b39c5158Smillert    is( scalar(@$error), 1, "caught error condition" );
450b39c5158Smillert    ($file, $message) = each %{$error->[0]};
451b39c5158Smillert    is( $entry, $file, "and the message is: $message");
452b39c5158Smillert
453b39c5158Smillert    eval {@created = mkpath($entry, 0, 0700)};
454b39c5158Smillert    $error = $@;
455b39c5158Smillert    chomp $error; # just to remove silly # in TAP output
456b39c5158Smillert    cmp_ok( $error, 'ne', "", "no directory created (old-style) err=$error" )
457b39c5158Smillert        or diag(@created);
458b39c5158Smillert}
459b39c5158Smillert
460b39c5158Smillert{
461b39c5158Smillert    $dir = catdir($tmp_base, 'ZZ');
462b39c5158Smillert    @created = mkpath($dir);
463b39c5158Smillert    is(scalar(@created), 1, "create a ZZ directory");
464b39c5158Smillert
465b39c5158Smillert    local @ARGV = ($dir);
466b39c5158Smillert    rmtree( [grep -e $_, @ARGV], 0, 0 );
467b39c5158Smillert    ok(!-e $dir, "blow it away via \@ARGV");
468b39c5158Smillert}
469b39c5158Smillert
470b39c5158SmillertSKIP : {
4712e109fb9Safresh1    my $skip_count = 18;
472b8851fccSafresh1    # this test will fail on Windows, as per:
473b8851fccSafresh1    #   http://perldoc.perl.org/perlport.html#chmod
474b39c5158Smillert
475b8851fccSafresh1    skip "Windows chmod test skipped", $skip_count
476b8851fccSafresh1        if $^O eq 'MSWin32';
4772e109fb9Safresh1    skip "fchmod() on directories is not supported on this platform", $skip_count
4782e109fb9Safresh1        unless $fchmod_supported;
479b8851fccSafresh1    my $mode;
480b8851fccSafresh1    my $octal_mode;
481b8851fccSafresh1    my @inputs = (
4822e109fb9Safresh1      0777, 0700, 0470, 0407,
4832e109fb9Safresh1      0433, 0400, 0430, 0403,
4842e109fb9Safresh1      0111, 0100, 0110, 0101,
4852e109fb9Safresh1      0731, 0713, 0317, 0371,
4862e109fb9Safresh1      0173, 0137);
487b8851fccSafresh1    my $input;
488b8851fccSafresh1    my $octal_input;
489b39c5158Smillert
490b8851fccSafresh1    foreach (@inputs) {
491b8851fccSafresh1        $input = $_;
4922e109fb9Safresh1        $dir = catdir($tmp_base, sprintf("chmod_test%04o", $input));
493b8851fccSafresh1        # We can skip from here because 0 is last in the list.
494b8851fccSafresh1        skip "Mode of 0 means assume user defaults on VMS", 1
495b8851fccSafresh1          if ($input == 0 && $Is_VMS);
496b8851fccSafresh1        @created = mkpath($dir, {chmod => $input});
497b8851fccSafresh1        $mode = (stat($dir))[2];
498b8851fccSafresh1        $octal_mode = S_IMODE($mode);
499b8851fccSafresh1        $octal_input = sprintf "%04o", S_IMODE($input);
5002e109fb9Safresh1        SKIP: {
5012e109fb9Safresh1	    skip "permissions are not fully supported by the filesystem", 1
5022e109fb9Safresh1                if (($^O eq 'MSWin32' || $^O eq 'cygwin') && ((Win32::FsType())[1] & 8) == 0);
503b8851fccSafresh1            is($octal_mode,$input, "create a new directory with chmod $input ($octal_input)");
5042e109fb9Safresh1	    }
505b8851fccSafresh1        rmtree( $dir );
506b39c5158Smillert    }
507b39c5158Smillert}
508b39c5158Smillert
509b8851fccSafresh1my $dir_base = catdir($tmp_base,'output');
510b8851fccSafresh1my $dir_a    = catdir($dir_base, 'A');
511b8851fccSafresh1my $dir_b    = catdir($dir_base, 'B');
512b39c5158Smillert
513b8851fccSafresh1is(_run_for_verbose(sub {@created = mkpath($dir_a, 1)}),
514b8851fccSafresh1    _verbose_expected('mkpath', $dir_base, 0, 1)
515b8851fccSafresh1    . _verbose_expected('mkpath', $dir_a, 0),
516b39c5158Smillert    'mkpath verbose (old style 1)'
517b39c5158Smillert);
518b39c5158Smillert
519b8851fccSafresh1is(_run_for_verbose(sub {@created = mkpath([$dir_b], 1)}),
520b8851fccSafresh1    _verbose_expected('mkpath', $dir_b, 0),
521b39c5158Smillert    'mkpath verbose (old style 2)'
522b39c5158Smillert);
523b39c5158Smillert
524b8851fccSafresh1my $verbose_expected;
525b8851fccSafresh1
526b8851fccSafresh1# Must determine expectations while directories still exist.
527b8851fccSafresh1$verbose_expected = _verbose_expected('rmtree', $dir_a, 1)
528b8851fccSafresh1                  . _verbose_expected('rmtree', $dir_b, 1);
529b8851fccSafresh1
530b8851fccSafresh1is(_run_for_verbose(sub {$count = rmtree([$dir_a, $dir_b], 1, 1)}),
531b8851fccSafresh1    $verbose_expected,
532b39c5158Smillert    'rmtree verbose (old style)'
533b39c5158Smillert);
534b39c5158Smillert
535b8851fccSafresh1# In case we didn't delete them in safe mode.
536b8851fccSafresh1rmtree($dir_a) if -d $dir_a;
537b8851fccSafresh1rmtree($dir_b) if -d $dir_b;
538b8851fccSafresh1
539b8851fccSafresh1is(_run_for_verbose(sub {@created = mkpath( $dir_a,
540b8851fccSafresh1                                            {verbose => 1, mask => 0750})}),
541b8851fccSafresh1    _verbose_expected('mkpath', $dir_a, 0),
542b39c5158Smillert    'mkpath verbose (new style 1)'
543b39c5158Smillert);
544b39c5158Smillert
545b8851fccSafresh1is(_run_for_verbose(sub {@created = mkpath($dir_b, 1, 0771)}),
546b8851fccSafresh1    _verbose_expected('mkpath', $dir_b, 0),
547b39c5158Smillert    'mkpath verbose (new style 2)'
548b39c5158Smillert);
549b39c5158Smillert
550b8851fccSafresh1$verbose_expected = _verbose_expected('rmtree', $dir_a, 1)
551b8851fccSafresh1                  . _verbose_expected('rmtree', $dir_b, 1);
552b8851fccSafresh1
553b8851fccSafresh1is(_run_for_verbose(sub {$count = rmtree([$dir_a, $dir_b], 1, 1)}),
554b8851fccSafresh1    $verbose_expected,
555b8851fccSafresh1    'again: rmtree verbose (old style)'
556b8851fccSafresh1);
557b8851fccSafresh1
558b8851fccSafresh1rmtree($dir_a) if -d $dir_a;
559b8851fccSafresh1rmtree($dir_b) if -d $dir_b;
560b8851fccSafresh1
561b8851fccSafresh1is(_run_for_verbose(sub {@created = make_path( $dir_a, $dir_b,
562b8851fccSafresh1                                               {verbose => 1, mode => 0711});}),
563b8851fccSafresh1      _verbose_expected('make_path', $dir_a, 1)
564b8851fccSafresh1    . _verbose_expected('make_path', $dir_b, 1),
565b8851fccSafresh1    'make_path verbose with final hashref'
566b8851fccSafresh1);
567b8851fccSafresh1
568b8851fccSafresh1$verbose_expected = _verbose_expected('remove_tree', $dir_a, 0)
569b8851fccSafresh1                  . _verbose_expected('remove_tree', $dir_b, 0);
570b8851fccSafresh1
571b8851fccSafresh1is(_run_for_verbose(sub {@created = remove_tree( $dir_a, $dir_b,
572b8851fccSafresh1                                                 {verbose => 1});}),
573b8851fccSafresh1    $verbose_expected,
574b8851fccSafresh1    'remove_tree verbose with final hashref'
575b8851fccSafresh1);
576b8851fccSafresh1
577b8851fccSafresh1rmtree($dir_a) if -d $dir_a;
578b8851fccSafresh1rmtree($dir_b) if -d $dir_b;
579b8851fccSafresh1
580b8851fccSafresh1# Have to re-create these 2 directories so that next block is not skipped.
581b8851fccSafresh1@created = make_path(
582b8851fccSafresh1    $dir_a,
583b8851fccSafresh1    $dir_b,
584b8851fccSafresh1    { mode => 0711 }
585b8851fccSafresh1);
586b8851fccSafresh1is(@created, 2, "2 directories created");
587b8851fccSafresh1
588b39c5158SmillertSKIP: {
589b8851fccSafresh1    $file = catfile($dir_b, "file");
590b39c5158Smillert    skip "Cannot create $file", 2 unless open OUT, "> $file";
591b39c5158Smillert    print OUT "test file, safe to delete\n", scalar(localtime), "\n";
592b39c5158Smillert    close OUT;
593b39c5158Smillert
594b8851fccSafresh1    $verbose_expected = _verbose_expected('rmtree', $dir_a, 1)
595b8851fccSafresh1                      . _verbose_expected('unlink', $file, 0)
596b8851fccSafresh1                      . _verbose_expected('rmtree', $dir_b, 1);
597b8851fccSafresh1
598b39c5158Smillert    ok(-e $file, "file created in directory");
599b39c5158Smillert
600b8851fccSafresh1    is(_run_for_verbose(sub {$count = rmtree( $dir_a, $dir_b,
601b8851fccSafresh1                                              {verbose => 1, safe => 1})}),
602b8851fccSafresh1        $verbose_expected,
603b39c5158Smillert        'rmtree safe verbose (new style)'
604b39c5158Smillert    );
605b8851fccSafresh1    rmtree($dir_a) if -d $dir_a;
606b8851fccSafresh1    rmtree($dir_b) if -d $dir_b;
607b39c5158Smillert}
608b39c5158Smillert
609b8851fccSafresh1{
610b8851fccSafresh1    my $base = catdir( $tmp_base, 'output2');
611b8851fccSafresh1    my $dir  = catdir( $base, 'A');
612b8851fccSafresh1    my $dir2 = catdir( $base, 'B');
613b39c5158Smillert
614b8851fccSafresh1    {
6152e109fb9Safresh1        my $warn = _run_for_warning( sub {
616b8851fccSafresh1            my @created = make_path(
617b8851fccSafresh1                $dir,
618b8851fccSafresh1                $dir2,
619b8851fccSafresh1                { mode => 0711, foo => 1, bar => 1 }
620b8851fccSafresh1            );
6212e109fb9Safresh1        } );
622b8851fccSafresh1        like($warn,
6232e109fb9Safresh1            qr/Unrecognized option\(s\) passed to mkpath\(\) or make_path\(\):.*?bar.*?foo/,
624b8851fccSafresh1            'make_path with final hashref warned due to unrecognized options'
625b8851fccSafresh1        );
626b39c5158Smillert    }
627b8851fccSafresh1
628b8851fccSafresh1    {
6292e109fb9Safresh1        my $warn = _run_for_warning( sub {
630b8851fccSafresh1            my @created = remove_tree(
631b8851fccSafresh1                $dir,
632b8851fccSafresh1                $dir2,
633b8851fccSafresh1                { foo => 1, bar => 1 }
634b8851fccSafresh1            );
6352e109fb9Safresh1        } );
636b8851fccSafresh1        like($warn,
637b8851fccSafresh1            qr/Unrecognized option\(s\) passed to remove_tree\(\):.*?bar.*?foo/,
638b8851fccSafresh1            'remove_tree with final hashref failed due to unrecognized options'
639b8851fccSafresh1        );
640b39c5158Smillert    }
641b39c5158Smillert}
642b39c5158Smillert
643b39c5158SmillertSKIP: {
644b39c5158Smillert    my $nr_tests = 6;
645b39c5158Smillert    my $cwd = getcwd() or skip "failed to getcwd: $!", $nr_tests;
646b39c5158Smillert    rmtree($tmp_base, {result => \$list} );
647b39c5158Smillert    is(ref($list), 'ARRAY', "received a final list of results");
648b39c5158Smillert    ok( !(-d $tmp_base), "test base directory gone" );
649b39c5158Smillert
650b39c5158Smillert    my $p = getcwd();
651b39c5158Smillert    my $x = "x$$";
652b39c5158Smillert    my $xx = $x . "x";
653b39c5158Smillert
654b39c5158Smillert    # setup
655b39c5158Smillert    ok(mkpath($xx), "make $xx");
656b39c5158Smillert    ok(chdir($xx), "... and chdir $xx");
657b39c5158Smillert    END {
658b8851fccSafresh1#         ok(chdir($p), "... now chdir $p");
659b8851fccSafresh1#         ok(rmtree($xx), "... and finally rmtree $xx");
660b8851fccSafresh1       chdir($p);
661b8851fccSafresh1       rmtree($xx);
662b39c5158Smillert    }
663b39c5158Smillert
664b39c5158Smillert    # create and delete directory
665b39c5158Smillert    my $px = catdir($p, $x);
666b39c5158Smillert    ok(mkpath($px), 'create and delete directory 2.07');
667b39c5158Smillert    ok(rmtree($px), '.. rmtree fails in File-Path-2.07');
668b8851fccSafresh1    chdir updir();
669b8851fccSafresh1}
670b8851fccSafresh1
671b8851fccSafresh1my $windows_dir = 'C:\Path\To\Dir';
672b8851fccSafresh1my $expect = 'c:/path/to/dir';
673b8851fccSafresh1is(
674b8851fccSafresh1    File::Path::_slash_lc($windows_dir),
675b8851fccSafresh1    $expect,
676b8851fccSafresh1    "Windows path unixified as expected"
677b8851fccSafresh1);
678b8851fccSafresh1
679b8851fccSafresh1{
680b8851fccSafresh1    my ($x, $message, $object, $expect, $rv, $arg, $error);
681b8851fccSafresh1    my ($k, $v, $second_error, $third_error);
6822e109fb9Safresh1    local $! = ENOENT;
683b8851fccSafresh1    $x = $!;
684b8851fccSafresh1
685b8851fccSafresh1    $message = 'message in a bottle';
686b8851fccSafresh1    $object = '/path/to/glory';
687b8851fccSafresh1    $expect = "$message for $object: $x";
688b8851fccSafresh1    $rv = _run_for_warning( sub {
689b8851fccSafresh1        File::Path::_error(
690b8851fccSafresh1            {},
691b8851fccSafresh1            $message,
692b8851fccSafresh1            $object
693b8851fccSafresh1        );
694b8851fccSafresh1    } );
695b8851fccSafresh1    like($rv, qr/^$expect/,
696b8851fccSafresh1        "no \$arg->{error}: defined 2nd and 3rd args: got expected error message");
697b8851fccSafresh1
698b8851fccSafresh1    $object = undef;
699b8851fccSafresh1    $expect = "$message: $x";
700b8851fccSafresh1    $rv = _run_for_warning( sub {
701b8851fccSafresh1        File::Path::_error(
702b8851fccSafresh1            {},
703b8851fccSafresh1            $message,
704b8851fccSafresh1            $object
705b8851fccSafresh1        );
706b8851fccSafresh1    } );
707b8851fccSafresh1    like($rv, qr/^$expect/,
708b8851fccSafresh1        "no \$arg->{error}: defined 2nd arg; undefined 3rd arg: got expected error message");
709b8851fccSafresh1
710b8851fccSafresh1    $message = 'message in a bottle';
711b8851fccSafresh1    $object = undef;
712b8851fccSafresh1    $expect = "$message: $x";
713b8851fccSafresh1    $arg = { error => \$error };
714b8851fccSafresh1    File::Path::_error(
715b8851fccSafresh1        $arg,
716b8851fccSafresh1        $message,
717b8851fccSafresh1        $object
718b8851fccSafresh1    );
719b8851fccSafresh1    is(ref($error->[0]), 'HASH',
720b8851fccSafresh1        "first element of array inside \$error is hashref");
721b8851fccSafresh1    ($k, $v) = %{$error->[0]};
722b8851fccSafresh1    is($k, '', 'key of hash is empty string, since 3rd arg was undef');
723b8851fccSafresh1    is($v, $expect, "value of hash is 2nd arg: $message");
724b8851fccSafresh1
725b8851fccSafresh1    $message = '';
726b8851fccSafresh1    $object = '/path/to/glory';
727b8851fccSafresh1    $expect = "$message: $x";
728b8851fccSafresh1    $arg = { error => \$second_error };
729b8851fccSafresh1    File::Path::_error(
730b8851fccSafresh1        $arg,
731b8851fccSafresh1        $message,
732b8851fccSafresh1        $object
733b8851fccSafresh1    );
734b8851fccSafresh1    is(ref($second_error->[0]), 'HASH',
735b8851fccSafresh1        "first element of array inside \$second_error is hashref");
736b8851fccSafresh1    ($k, $v) = %{$second_error->[0]};
737b8851fccSafresh1    is($k, $object, "key of hash is '$object', since 3rd arg was defined");
738b8851fccSafresh1    is($v, $expect, "value of hash is 2nd arg: $message");
739b8851fccSafresh1
740b8851fccSafresh1    $message = '';
741b8851fccSafresh1    $object = undef;
742b8851fccSafresh1    $expect = "$message: $x";
743b8851fccSafresh1    $arg = { error => \$third_error };
744b8851fccSafresh1    File::Path::_error(
745b8851fccSafresh1        $arg,
746b8851fccSafresh1        $message,
747b8851fccSafresh1        $object
748b8851fccSafresh1    );
749b8851fccSafresh1    is(ref($third_error->[0]), 'HASH',
750b8851fccSafresh1        "first element of array inside \$third_error is hashref");
751b8851fccSafresh1    ($k, $v) = %{$third_error->[0]};
752b8851fccSafresh1    is($k, '', "key of hash is empty string, since 3rd arg was undef");
753b8851fccSafresh1    is($v, $expect, "value of hash is 2nd arg: $message");
754b39c5158Smillert}
7552e109fb9Safresh1
7562e109fb9Safresh1{
7572e109fb9Safresh1    # https://rt.cpan.org/Ticket/Display.html?id=117019
7582e109fb9Safresh1    # remove_tree(): Permit re-use of options hash without issuing a warning
7592e109fb9Safresh1
7602e109fb9Safresh1    my ($least_deep, $next_deepest, $deepest) =
7619f11ffb7Safresh1        create_3_level_subdirs( qw| ZoYhvc6RmGnl S2CrQ0lju0o7 lvOqVYWpfhcP | );
7622e109fb9Safresh1    my @created;
7632e109fb9Safresh1    @created = File::Path::make_path($deepest, { mode => 0711 });
7642e109fb9Safresh1    is(scalar(@created), 3, "Created 3 subdirectories");
7652e109fb9Safresh1
7662e109fb9Safresh1    my $x = '';
7672e109fb9Safresh1    my $opts = { error => \$x };
7682e109fb9Safresh1    File::Path::remove_tree($deepest, $opts);
7692e109fb9Safresh1    ok(! -d $deepest, "directory '$deepest' removed, as expected");
7702e109fb9Safresh1
7712e109fb9Safresh1    my $warn;
7722e109fb9Safresh1    $warn = _run_for_warning( sub { File::Path::remove_tree($next_deepest, $opts); } );
7732e109fb9Safresh1    ok(! $warn, "CPAN 117019: No warning thrown when re-using \$opts");
7742e109fb9Safresh1    ok(! -d $next_deepest, "directory '$next_deepest' removed, as expected");
7752e109fb9Safresh1
7762e109fb9Safresh1    $warn = _run_for_warning( sub { File::Path::remove_tree($least_deep, $opts); } );
7772e109fb9Safresh1    ok(! $warn, "CPAN 117019: No warning thrown when re-using \$opts");
7782e109fb9Safresh1    ok(! -d $least_deep, "directory '$least_deep' removed, as expected");
7792e109fb9Safresh1}
7802e109fb9Safresh1
7812e109fb9Safresh1{
7822e109fb9Safresh1    # Corner cases with respect to arguments provided to functions
7832e109fb9Safresh1    my $count;
7842e109fb9Safresh1
7852e109fb9Safresh1    $count = remove_tree();
7862e109fb9Safresh1    is($count, 0,
7872e109fb9Safresh1        "If not provided with any paths, remove_tree() will return a count of 0 things deleted");
7882e109fb9Safresh1
7892e109fb9Safresh1    $count = remove_tree('');
7902e109fb9Safresh1    is($count, 0,
7912e109fb9Safresh1        "If not provided with any paths, remove_tree() will return a count of 0 things deleted");
7922e109fb9Safresh1
7932e109fb9Safresh1    my $warn;
7942e109fb9Safresh1    $warn = _run_for_warning( sub { $count = rmtree(); } );
7952e109fb9Safresh1    like($warn, qr/No root path\(s\) specified/s, "Got expected carp");
7962e109fb9Safresh1    is($count, 0,
7972e109fb9Safresh1        "If not provided with any paths, remove_tree() will return a count of 0 things deleted");
7982e109fb9Safresh1
7992e109fb9Safresh1    $warn = _run_for_warning( sub {$count = rmtree(undef); } );
8002e109fb9Safresh1    like($warn, qr/No root path\(s\) specified/s, "Got expected carp");
8012e109fb9Safresh1    is($count, 0,
8022e109fb9Safresh1        "If provided only with an undefined value, remove_tree() will return a count of 0 things deleted");
8032e109fb9Safresh1
8042e109fb9Safresh1    $warn = _run_for_warning( sub {$count = rmtree(''); } );
8052e109fb9Safresh1    like($warn, qr/No root path\(s\) specified/s, "Got expected carp");
8062e109fb9Safresh1    is($count, 0,
8072e109fb9Safresh1        "If provided with an empty string for a path, remove_tree() will return a count of 0 things deleted");
8082e109fb9Safresh1
8092e109fb9Safresh1    $count = make_path();
8102e109fb9Safresh1    is($count, 0,
8112e109fb9Safresh1        "If not provided with any paths, make_path() will return a count of 0 things created");
8122e109fb9Safresh1
8132e109fb9Safresh1    $count = mkpath();
8142e109fb9Safresh1    is($count, 0,
8152e109fb9Safresh1        "If not provided with any paths, make_path() will return a count of 0 things created");
8162e109fb9Safresh1}
8172e109fb9Safresh1
8182e109fb9Safresh1SKIP: {
8199f11ffb7Safresh1    my $skip_count = 3;
8202e109fb9Safresh1    skip "Windows will not set this error condition", $skip_count
8212e109fb9Safresh1        if $^O eq 'MSWin32';
8222e109fb9Safresh1
8232e109fb9Safresh1    # mkpath() with hashref:  case of phony user
8242e109fb9Safresh1    my ($least_deep, $next_deepest, $deepest) =
8259f11ffb7Safresh1        create_3_level_subdirs( qw| Hhu1KpF4EVAV vUj5k37bih8v Vkdw02POXJxj | );
8262e109fb9Safresh1    my (@created, $error);
8272e109fb9Safresh1    my $user = join('_' => 'foobar', $$);
8282e109fb9Safresh1    @created = mkpath($deepest, { mode => 0711, user => $user, error => \$error });
8299f11ffb7Safresh1#    TODO: {
8309f11ffb7Safresh1#        local $TODO = "Notwithstanding the phony 'user', mkpath will actually create subdirectories; should it?";
8319f11ffb7Safresh1#        is(scalar(@created), 0, "No subdirectories created");
8329f11ffb7Safresh1#    }
8332e109fb9Safresh1    is(scalar(@$error), 1, "caught error condition" );
8342e109fb9Safresh1    my ($file, $message) = each %{$error->[0]};
8352e109fb9Safresh1    like($message,
8362e109fb9Safresh1        qr/unable to map $user to a uid, ownership not changed/s,
8372e109fb9Safresh1        "Got expected error message for phony user",
8382e109fb9Safresh1    );
8392e109fb9Safresh1
8402e109fb9Safresh1    cleanup_3_level_subdirs($least_deep);
8412e109fb9Safresh1}
8422e109fb9Safresh1
8432e109fb9Safresh1{
8442e109fb9Safresh1    # mkpath() with hashref:  case of valid uid
8452e109fb9Safresh1    my ($least_deep, $next_deepest, $deepest) =
8469f11ffb7Safresh1        create_3_level_subdirs( qw| b5wj8CJcc7gl XTJe2C3WGLg5 VZ_y2T0XfKu3 | );
8472e109fb9Safresh1    my (@created, $error);
848*eac174f2Safresh1    my $warn;
849*eac174f2Safresh1    local $SIG{__WARN__} = sub { $warn = shift };
8502e109fb9Safresh1    @created = mkpath($deepest, { mode => 0711, uid => $>, error => \$error });
851*eac174f2Safresh1    SKIP: {
852*eac174f2Safresh1        my $skip_count = 1;
853*eac174f2Safresh1        skip "Warning should only appear on Windows", $skip_count
854*eac174f2Safresh1            unless $^O eq 'MSWin32';
855*eac174f2Safresh1        like($warn,
856*eac174f2Safresh1            qr/Option\(s\) implausible on Win32 passed to mkpath\(\) or make_path\(\)/,
857*eac174f2Safresh1            'make_path with final hashref warned due to options implausible on Win32'
858*eac174f2Safresh1        );
859*eac174f2Safresh1    }
8602e109fb9Safresh1    is(scalar(@created), 3, "Provide valid 'uid' argument: 3 subdirectories created");
8612e109fb9Safresh1
8622e109fb9Safresh1    cleanup_3_level_subdirs($least_deep);
8632e109fb9Safresh1}
8642e109fb9Safresh1
8652e109fb9Safresh1SKIP: {
8662e109fb9Safresh1    my $skip_count = 3;
8672e109fb9Safresh1    skip "getpwuid() and getgrgid() not implemented on Windows", $skip_count
8682e109fb9Safresh1        if $^O eq 'MSWin32';
8692e109fb9Safresh1
8702e109fb9Safresh1    # mkpath() with hashref:  case of valid owner
8712e109fb9Safresh1    my ($least_deep, $next_deepest, $deepest) =
8729f11ffb7Safresh1        create_3_level_subdirs( qw| aiJEDKaAEH25 nqhXsBM_7_bv qfRj4cur4Jrs | );
8732e109fb9Safresh1    my (@created, $error);
8742e109fb9Safresh1    my $name = getpwuid($>);
8752e109fb9Safresh1    @created = mkpath($deepest, { mode => 0711, owner => $name, error => \$error });
8762e109fb9Safresh1    is(scalar(@created), 3, "Provide valid 'owner' argument: 3 subdirectories created");
8772e109fb9Safresh1
8782e109fb9Safresh1    cleanup_3_level_subdirs($least_deep);
8792e109fb9Safresh1}
8802e109fb9Safresh1
8812e109fb9Safresh1SKIP: {
8822e109fb9Safresh1    my $skip_count = 5;
8832e109fb9Safresh1    skip "Windows will not set this error condition", $skip_count
8842e109fb9Safresh1        if $^O eq 'MSWin32';
8852e109fb9Safresh1
8862e109fb9Safresh1    # mkpath() with hashref:  case of phony group
8872e109fb9Safresh1    my ($least_deep, $next_deepest, $deepest) =
8889f11ffb7Safresh1        create_3_level_subdirs( qw| nOR4lGRMdLvz NnwkEHEVL5li _3f1Kv6q77yA | );
8892e109fb9Safresh1    my (@created, $error);
8902e109fb9Safresh1    my $bad_group = join('_' => 'foobarbaz', $$);
8912e109fb9Safresh1    @created = mkpath($deepest, { mode => 0711, group => $bad_group, error => \$error });
8929f11ffb7Safresh1#    TODO: {
8939f11ffb7Safresh1#        local $TODO = "Notwithstanding the phony 'group', mkpath will actually create subdirectories; should it?";
8949f11ffb7Safresh1#        is(scalar(@created), 0, "No subdirectories created");
8959f11ffb7Safresh1#    }
8962e109fb9Safresh1    is(scalar(@$error), 1, "caught error condition" );
8972e109fb9Safresh1    my ($file, $message) = each %{$error->[0]};
8982e109fb9Safresh1    like($message,
8992e109fb9Safresh1        qr/unable to map $bad_group to a gid, group ownership not changed/s,
9002e109fb9Safresh1        "Got expected error message for phony user",
9012e109fb9Safresh1    );
9022e109fb9Safresh1
9032e109fb9Safresh1    cleanup_3_level_subdirs($least_deep);
9042e109fb9Safresh1}
9052e109fb9Safresh1
9062e109fb9Safresh1{
9072e109fb9Safresh1    # mkpath() with hashref:  case of valid group
9082e109fb9Safresh1    my ($least_deep, $next_deepest, $deepest) =
9099f11ffb7Safresh1        create_3_level_subdirs( qw| BEcigvaBNisY rd4lJ1iZRyeS OyQnDPIBxP2K | );
9102e109fb9Safresh1    my (@created, $error);
911*eac174f2Safresh1    my $warn;
912*eac174f2Safresh1    local $SIG{__WARN__} = sub { $warn = shift };
9132e109fb9Safresh1    @created = mkpath($deepest, { mode => 0711, group => $(, error => \$error });
914*eac174f2Safresh1    SKIP: {
915*eac174f2Safresh1        my $skip_count = 1;
916*eac174f2Safresh1        skip "Warning should only appear on Windows", $skip_count
917*eac174f2Safresh1            unless $^O eq 'MSWin32';
918*eac174f2Safresh1        like($warn,
919*eac174f2Safresh1            qr/Option\(s\) implausible on Win32 passed to mkpath\(\) or make_path\(\)/,
920*eac174f2Safresh1            'make_path with final hashref warned due to options implausible on Win32'
921*eac174f2Safresh1        );
922*eac174f2Safresh1    }
9232e109fb9Safresh1    is(scalar(@created), 3, "Provide valid 'group' argument: 3 subdirectories created");
9242e109fb9Safresh1
9252e109fb9Safresh1    cleanup_3_level_subdirs($least_deep);
9262e109fb9Safresh1}
9272e109fb9Safresh1
9282e109fb9Safresh1SKIP: {
9292e109fb9Safresh1    my $skip_count = 3;
9302e109fb9Safresh1    skip "getpwuid() and getgrgid() not implemented on Windows", $skip_count
9312e109fb9Safresh1        if $^O eq 'MSWin32';
9322e109fb9Safresh1
9332e109fb9Safresh1    # mkpath() with hashref:  case of valid group
9342e109fb9Safresh1    my ($least_deep, $next_deepest, $deepest) =
9359f11ffb7Safresh1        create_3_level_subdirs( qw| IayhWFDvys8X gTd6gaeuFzmV VVI6UWLJCOEC | );
9362e109fb9Safresh1    my (@created, $error);
9372e109fb9Safresh1    my $group_name = (getgrgid($())[0];
9382e109fb9Safresh1    @created = mkpath($deepest, { mode => 0711, group => $group_name, error => \$error });
9392e109fb9Safresh1    is(scalar(@created), 3, "Provide valid 'group' argument: 3 subdirectories created");
9402e109fb9Safresh1
9412e109fb9Safresh1    cleanup_3_level_subdirs($least_deep);
9422e109fb9Safresh1}
9432e109fb9Safresh1
9442e109fb9Safresh1SKIP: {
9452e109fb9Safresh1    my $skip_count = 3;
9462e109fb9Safresh1    skip "getpwuid() and getgrgid() not implemented on Windows", $skip_count
9472e109fb9Safresh1        if $^O eq 'MSWin32';
9482e109fb9Safresh1
9492e109fb9Safresh1    # mkpath() with hashref:  case of valid owner and group
9502e109fb9Safresh1    my ($least_deep, $next_deepest, $deepest) =
9519f11ffb7Safresh1        create_3_level_subdirs( qw| xsmOvlnxOqJc olsGlBSoVUpp tDuRilkD35rd | );
9522e109fb9Safresh1    my (@created, $error);
9532e109fb9Safresh1    my $name = getpwuid($>);
9542e109fb9Safresh1    my $group_name = (getgrgid($())[0];
9552e109fb9Safresh1    @created = mkpath($deepest, { mode => 0711, owner => $name, group => $group_name, error => \$error });
9562e109fb9Safresh1    is(scalar(@created), 3, "Provide valid 'owner' and 'group' 'group' arguments: 3 subdirectories created");
9572e109fb9Safresh1
9582e109fb9Safresh1    cleanup_3_level_subdirs($least_deep);
9592e109fb9Safresh1}
960