This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Increase $File::Find::VERSION to 1.21
[perl5.git] / lib / File / Find / t / find.t
CommitLineData
3fa6e24b 1#!./perl
dd87e51f
CB
2use strict;
3use Cwd;
81793b90 4
3fa6e24b
TW
5my %Expect_File = (); # what we expect for $_
6my %Expect_Name = (); # what we expect for $File::Find::name/fullname
7my %Expect_Dir = (); # what we expect for $File::Find::dir
81793b90 8my $symlink_exists = eval { symlink("",""); 1 };
dd87e51f 9my ($warn_msg, @files, $file);
3fa6e24b 10
1a3850a5
GA
11
12BEGIN {
234fd682 13 require File::Spec;
1a3850a5 14 chdir 't' if -d 't';
234fd682
JM
15 # May be doing dynamic loading while @INC is all relative
16 unshift @INC => File::Spec->rel2abs('../lib');
7e47e6ff 17
3fa6e24b 18 $SIG{'__WARN__'} = sub { $warn_msg = $_[0]; warn "# $_[0]"; }
1a3850a5
GA
19}
20
68c65ec0 21my $test_count = 85;
1c8cb608 22$test_count += 119 if $symlink_exists;
a0b245d5 23$test_count += 26 if $^O eq 'MSWin32';
68c65ec0
B
24$test_count += 2 if $^O eq 'MSWin32' and $symlink_exists;
25
26print "1..$test_count\n";
27#if ( $symlink_exists ) { print "1..199\n"; }
28#else { print "1..85\n"; }
1a3850a5 29
dd87e51f
CB
30my $orig_dir = cwd();
31
7dc9aaa5
MS
32# Uncomment this to see where File::Find is chdir'ing to. Helpful for
33# debugging its little jaunts around the filesystem.
34# BEGIN {
35# use Cwd;
36# *CORE::GLOBAL::chdir = sub ($) {
37# my($file, $line) = (caller)[1,2];
38#
39# printf "# cwd: %s\n", cwd();
40# print "# chdir: @_ from $file at $line\n";
41# my($return) = CORE::chdir($_[0]);
42# printf "# newcwd: %s\n", cwd();
43#
44# return $return;
45# };
46# }
47
48
ea05ec2d
CL
49BEGIN {
50 use File::Spec;
51 if ($^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'VMS')
52 {
53 # This is a hack - at present File::Find does not produce native names on
54 # Win32 or VMS, so force File::Spec to use Unix names.
55 # must be set *before* importing File::Find
56 require File::Spec::Unix;
57 @File::Spec::ISA = 'File::Spec::Unix';
58 }
59 require File::Find;
60 import File::Find;
61}
6455dd3b 62
c80f55d1
JH
63cleanup();
64
912440be
NC
65$::count_commonsense = 0;
66find({wanted => sub { ++$::count_commonsense if $_ eq 'commonsense.t'; } },
bb7dc48b 67 File::Spec->curdir);
912440be
NC
68if ($::count_commonsense == 1) {
69 print "ok 1\n";
70} else {
71 print "not ok 1 # found $::count_commonsense files named 'commonsense.t'\n";
72}
3fa6e24b 73
912440be
NC
74$::count_commonsense = 0;
75finddepth({wanted => sub { ++$::count_commonsense if $_ eq 'commonsense.t'; } },
bb7dc48b 76 File::Spec->curdir);
912440be
NC
77if ($::count_commonsense == 1) {
78 print "ok 2\n";
79} else {
80 print "not ok 2 # found $::count_commonsense files named 'commonsense.t'\n";
81}
6455dd3b 82
81793b90 83my $case = 2;
5eb85357 84my $FastFileTests_OK = 0;
81793b90 85
c80f55d1 86sub cleanup {
dd87e51f
CB
87 chdir($orig_dir);
88 my $need_updir = 0;
3fa6e24b 89 if (-d dir_path('for_find')) {
dd87e51f 90 $need_updir = 1 if chdir(dir_path('for_find'));
6fecce66
RGS
91 }
92 if (-d dir_path('fa')) {
93 unlink file_path('fa', 'fa_ord'),
94 file_path('fa', 'fsl'),
95 file_path('fa', 'faa', 'faa_ord'),
96 file_path('fa', 'fab', 'fab_ord'),
97 file_path('fa', 'fab', 'faba', 'faba_ord'),
51393fc0 98 file_path('fa', 'fac', 'faca'),
6fecce66 99 file_path('fb', 'fb_ord'),
51393fc0
A
100 file_path('fb', 'fba', 'fba_ord'),
101 file_path('fb', 'fbc', 'fbca');
6fecce66
RGS
102 rmdir dir_path('fa', 'faa');
103 rmdir dir_path('fa', 'fab', 'faba');
104 rmdir dir_path('fa', 'fab');
51393fc0 105 rmdir dir_path('fa', 'fac');
6fecce66
RGS
106 rmdir dir_path('fa');
107 rmdir dir_path('fb', 'fba');
51393fc0 108 rmdir dir_path('fb', 'fbc');
6fecce66
RGS
109 rmdir dir_path('fb');
110 }
dd87e51f
CB
111 if ($need_updir) {
112 my $updir = $^O eq 'VMS' ? File::Spec::VMS->updir() : File::Spec->updir;
113 chdir($updir);
114 }
6fecce66
RGS
115 if (-d dir_path('for_find')) {
116 rmdir dir_path('for_find') or print "# Can't rmdir for_find: $!\n";
c80f55d1
JH
117 }
118}
119
81793b90 120END {
c80f55d1 121 cleanup();
81793b90
GS
122}
123
124sub Check($) {
3fa6e24b
TW
125 $case++;
126 if ($_[0]) { print "ok $case\n"; }
127 else { print "not ok $case\n"; }
81793b90
GS
128}
129
130sub CheckDie($) {
3fa6e24b
TW
131 $case++;
132 if ($_[0]) { print "ok $case\n"; }
133 else { print "not ok $case\n $!\n"; exit 0; }
81793b90
GS
134}
135
136sub touch {
3fa6e24b 137 CheckDie( open(my $T,'>',$_[0]) );
81793b90
GS
138}
139
140sub MkDir($$) {
3fa6e24b 141 CheckDie( mkdir($_[0],$_[1]) );
81793b90
GS
142}
143
3fa6e24b 144sub wanted_File_Dir {
aaaf2301 145 printf "# \$File::Find::dir => '$File::Find::dir'\t\$_ => '$_'\n";
3fa6e24b 146 s#\.$## if ($^O eq 'VMS' && $_ ne '.');
a1ccf0c4 147 s/(.dir)?$//i if ($^O eq 'VMS' && -d _);
3fa6e24b
TW
148 Check( $Expect_File{$_} );
149 if ( $FastFileTests_OK ) {
150 delete $Expect_File{ $_}
151 unless ( $Expect_Dir{$_} && ! -d _ );
152 } else {
153 delete $Expect_File{$_}
154 unless ( $Expect_Dir{$_} && ! -d $_ );
155 }
156}
7e47e6ff 157
3fa6e24b
TW
158sub wanted_File_Dir_prune {
159 &wanted_File_Dir;
160 $File::Find::prune=1 if $_ eq 'faba';
81793b90
GS
161}
162
3fa6e24b
TW
163sub wanted_Name {
164 my $n = $File::Find::name;
165 $n =~ s#\.$## if ($^O eq 'VMS' && $n ne '.');
166 print "# \$File::Find::name => '$n'\n";
167 my $i = rindex($n,'/');
168 my $OK = exists($Expect_Name{$n});
786dada4
NC
169 if ( $OK ) {
170 $OK= exists($Expect_Name{substr($n,0,$i)}) if $i >= 0;
7e47e6ff 171 }
3fa6e24b
TW
172 Check($OK);
173 delete $Expect_Name{$n};
57907763
GS
174}
175
3fa6e24b
TW
176sub wanted_File {
177 print "# \$_ => '$_'\n";
178 s#\.$## if ($^O eq 'VMS' && $_ ne '.');
179 my $i = rindex($_,'/');
180 my $OK = exists($Expect_File{ $_});
786dada4
NC
181 if ( $OK ) {
182 $OK= exists($Expect_File{ substr($_,0,$i)}) if $i >= 0;
7e47e6ff 183 }
3fa6e24b
TW
184 Check($OK);
185 delete $Expect_File{ $_};
57907763
GS
186}
187
7e47e6ff 188sub simple_wanted {
3fa6e24b
TW
189 print "# \$File::Find::dir => '$File::Find::dir'\n";
190 print "# \$_ => '$_'\n";
7e47e6ff
JH
191}
192
193sub noop_wanted {}
78eac027 194
7e47e6ff 195sub my_preprocess {
3fa6e24b
TW
196 @files = @_;
197 print "# --preprocess--\n";
198 print "# \$File::Find::dir => '$File::Find::dir' \n";
199 foreach $file (@files) {
30db15be 200 $file =~ s/\.(dir)?$// if $^O eq 'VMS';
3fa6e24b
TW
201 print "# $file \n";
202 delete $Expect_Dir{ $File::Find::dir }->{$file};
203 }
204 print "# --end preprocess--\n";
205 Check(scalar(keys %{$Expect_Dir{ $File::Find::dir }}) == 0);
206 if (scalar(keys %{$Expect_Dir{ $File::Find::dir }}) == 0) {
207 delete $Expect_Dir{ $File::Find::dir }
208 }
209 return @files;
7e47e6ff
JH
210}
211
212sub my_postprocess {
3fa6e24b
TW
213 print "# postprocess: \$File::Find::dir => '$File::Find::dir' \n";
214 delete $Expect_Dir{ $File::Find::dir};
7e47e6ff
JH
215}
216
217
bb7dc48b
JH
218# Use dir_path() to specify a directory path that's expected for
219# $File::Find::dir (%Expect_Dir). Also use it in file operations like
220# chdir, rmdir etc.
3fa6e24b 221#
2586ba89 222# dir_path() concatenates directory names to form a *relative*
30db15be 223# directory path, independent from the platform it's run on, although
2586ba89 224# there are limitations. Don't try to create an absolute path,
bb7dc48b 225# because that may fail on operating systems that have the concept of
2586ba89 226# volume names (e.g. Mac OS). As a special case, you can pass it a "."
786dada4
NC
227# as first argument, to create a directory path like "./fa/dir". If there's
228# no second argument, this function will return "./"
3fa6e24b
TW
229
230sub dir_path {
2586ba89 231 my $first_arg = shift @_;
3fa6e24b 232
2586ba89 233 if ($first_arg eq '.') {
786dada4
NC
234 return './' unless @_;
235 my $path = File::Spec->catdir(@_);
236 # add leading "./"
237 $path = "./$path";
238 return $path;
2586ba89
JH
239 } else { # $first_arg ne '.'
240 return $first_arg unless @_; # return plain filename
241 return File::Spec->catdir($first_arg, @_); # relative path
3fa6e24b
TW
242 }
243}
7e47e6ff 244
7e47e6ff 245
bb7dc48b 246# Use topdir() to specify a directory path that you want to pass to
786dada4 247# find/finddepth. Historically topdir() differed on Mac OS classic.
7e47e6ff 248
786dada4 249*topdir = \&dir_path;
7e47e6ff 250
7e47e6ff 251
bb7dc48b 252# Use file_path() to specify a file path that's expected for $_
2586ba89 253# (%Expect_File). Also suitable for file operations like unlink etc.
3fa6e24b 254#
bb7dc48b 255# file_path() concatenates directory names (if any) and a filename to
2586ba89 256# form a *relative* file path (the last argument is assumed to be a
30db15be 257# file). It's independent from the platform it's run on, although
2586ba89
JH
258# there are limitations. As a special case, you can pass it a "." as
259# first argument, to create a file path like "./fa/file" on operating
786dada4
NC
260# systems. If there's no second argument, this function will return the
261# string "./"
3fa6e24b
TW
262
263sub file_path {
2586ba89 264 my $first_arg = shift @_;
3fa6e24b 265
2586ba89 266 if ($first_arg eq '.') {
786dada4
NC
267 return './' unless @_;
268 my $path = File::Spec->catfile(@_);
269 # add leading "./"
270 $path = "./$path";
271 return $path;
2586ba89
JH
272 } else { # $first_arg ne '.'
273 return $first_arg unless @_; # return plain filename
274 return File::Spec->catfile($first_arg, @_); # relative path
7e47e6ff 275 }
3fa6e24b
TW
276}
277
278
bb7dc48b
JH
279# Use file_path_name() to specify a file path that's expected for
280# $File::Find::Name (%Expect_Name). Note: When the no_chdir => 1
281# option is in effect, $_ is the same as $File::Find::Name. In that
282# case, also use this function to specify a file path that's expected
283# for $_.
3fa6e24b 284#
786dada4
NC
285# Historically file_path_name differed on Mac OS classic.
286
287*file_path_name = \&file_path;
3fa6e24b 288
7e47e6ff 289
3fa6e24b
TW
290
291MkDir( dir_path('for_find'), 0770 );
292CheckDie(chdir( dir_path('for_find')));
293MkDir( dir_path('fa'), 0770 );
294MkDir( dir_path('fb'), 0770 );
295touch( file_path('fb', 'fb_ord') );
296MkDir( dir_path('fb', 'fba'), 0770 );
297touch( file_path('fb', 'fba', 'fba_ord') );
786dada4 298CheckDie( symlink('../fb','fa/fsl') ) if $symlink_exists;
3fa6e24b
TW
299touch( file_path('fa', 'fa_ord') );
300
301MkDir( dir_path('fa', 'faa'), 0770 );
302touch( file_path('fa', 'faa', 'faa_ord') );
303MkDir( dir_path('fa', 'fab'), 0770 );
304touch( file_path('fa', 'fab', 'fab_ord') );
305MkDir( dir_path('fa', 'fab', 'faba'), 0770 );
306touch( file_path('fa', 'fab', 'faba', 'faba_ord') );
307
308
bb7dc48b
JH
309%Expect_File = (File::Spec->curdir => 1, file_path('fsl') => 1,
310 file_path('fa_ord') => 1, file_path('fab') => 1,
311 file_path('fab_ord') => 1, file_path('faba') => 1,
3fa6e24b 312 file_path('faa') => 1, file_path('faa_ord') => 1);
bb7dc48b 313
3fa6e24b
TW
314delete $Expect_File{ file_path('fsl') } unless $symlink_exists;
315%Expect_Name = ();
bb7dc48b
JH
316
317%Expect_Dir = ( dir_path('fa') => 1, dir_path('faa') => 1,
318 dir_path('fab') => 1, dir_path('faba') => 1,
3fa6e24b 319 dir_path('fb') => 1, dir_path('fba') => 1);
bb7dc48b 320
3fa6e24b
TW
321delete @Expect_Dir{ dir_path('fb'), dir_path('fba') } unless $symlink_exists;
322File::Find::find( {wanted => \&wanted_File_Dir_prune}, topdir('fa') );
323Check( scalar(keys %Expect_File) == 0 );
324
325
326print "# check re-entrancy\n";
bb7dc48b
JH
327
328%Expect_File = (File::Spec->curdir => 1, file_path('fsl') => 1,
329 file_path('fa_ord') => 1, file_path('fab') => 1,
330 file_path('fab_ord') => 1, file_path('faba') => 1,
3fa6e24b 331 file_path('faa') => 1, file_path('faa_ord') => 1);
bb7dc48b 332
3fa6e24b
TW
333delete $Expect_File{ file_path('fsl') } unless $symlink_exists;
334%Expect_Name = ();
bb7dc48b
JH
335
336%Expect_Dir = ( dir_path('fa') => 1, dir_path('faa') => 1,
337 dir_path('fab') => 1, dir_path('faba') => 1,
3fa6e24b 338 dir_path('fb') => 1, dir_path('fba') => 1);
bb7dc48b 339
3fa6e24b 340delete @Expect_Dir{ dir_path('fb'), dir_path('fba') } unless $symlink_exists;
bb7dc48b
JH
341
342File::Find::find( {wanted => sub { wanted_File_Dir_prune();
343 File::Find::find( {wanted => sub
344 {} }, File::Spec->curdir ); } },
345 topdir('fa') );
346
3fa6e24b
TW
347Check( scalar(keys %Expect_File) == 0 );
348
349
350# no_chdir is in effect, hence we use file_path_name to specify the expected paths for %Expect_File
bb7dc48b
JH
351
352%Expect_File = (file_path_name('fa') => 1,
353 file_path_name('fa', 'fsl') => 1,
354 file_path_name('fa', 'fa_ord') => 1,
355 file_path_name('fa', 'fab') => 1,
356 file_path_name('fa', 'fab', 'fab_ord') => 1,
357 file_path_name('fa', 'fab', 'faba') => 1,
358 file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
359 file_path_name('fa', 'faa') => 1,
360 file_path_name('fa', 'faa', 'faa_ord') => 1,);
361
3fa6e24b
TW
362delete $Expect_File{ file_path_name('fa', 'fsl') } unless $symlink_exists;
363%Expect_Name = ();
bb7dc48b
JH
364
365%Expect_Dir = (dir_path('fa') => 1,
366 dir_path('fa', 'faa') => 1,
367 dir_path('fa', 'fab') => 1,
368 dir_path('fa', 'fab', 'faba') => 1,
369 dir_path('fb') => 1,
370 dir_path('fb', 'fba') => 1);
371
372delete @Expect_Dir{ dir_path('fb'), dir_path('fb', 'fba') }
373 unless $symlink_exists;
374
375File::Find::find( {wanted => \&wanted_File_Dir, no_chdir => 1},
376 topdir('fa') ); Check( scalar(keys %Expect_File) == 0 );
3fa6e24b
TW
377
378
379%Expect_File = ();
bb7dc48b
JH
380
381%Expect_Name = (File::Spec->curdir => 1,
382 file_path_name('.', 'fa') => 1,
383 file_path_name('.', 'fa', 'fsl') => 1,
384 file_path_name('.', 'fa', 'fa_ord') => 1,
385 file_path_name('.', 'fa', 'fab') => 1,
386 file_path_name('.', 'fa', 'fab', 'fab_ord') => 1,
387 file_path_name('.', 'fa', 'fab', 'faba') => 1,
388 file_path_name('.', 'fa', 'fab', 'faba', 'faba_ord') => 1,
389 file_path_name('.', 'fa', 'faa') => 1,
390 file_path_name('.', 'fa', 'faa', 'faa_ord') => 1,
391 file_path_name('.', 'fb') => 1,
392 file_path_name('.', 'fb', 'fba') => 1,
393 file_path_name('.', 'fb', 'fba', 'fba_ord') => 1,
394 file_path_name('.', 'fb', 'fb_ord') => 1);
395
3fa6e24b
TW
396delete $Expect_Name{ file_path('.', 'fa', 'fsl') } unless $symlink_exists;
397%Expect_Dir = ();
398File::Find::finddepth( {wanted => \&wanted_Name}, File::Spec->curdir );
399Check( scalar(keys %Expect_Name) == 0 );
400
401
bb7dc48b
JH
402# no_chdir is in effect, hence we use file_path_name to specify the
403# expected paths for %Expect_File
404
405%Expect_File = (File::Spec->curdir => 1,
406 file_path_name('.', 'fa') => 1,
407 file_path_name('.', 'fa', 'fsl') => 1,
408 file_path_name('.', 'fa', 'fa_ord') => 1,
409 file_path_name('.', 'fa', 'fab') => 1,
410 file_path_name('.', 'fa', 'fab', 'fab_ord') => 1,
411 file_path_name('.', 'fa', 'fab', 'faba') => 1,
412 file_path_name('.', 'fa', 'fab', 'faba', 'faba_ord') => 1,
413 file_path_name('.', 'fa', 'faa') => 1,
414 file_path_name('.', 'fa', 'faa', 'faa_ord') => 1,
415 file_path_name('.', 'fb') => 1,
416 file_path_name('.', 'fb', 'fba') => 1,
417 file_path_name('.', 'fb', 'fba', 'fba_ord') => 1,
418 file_path_name('.', 'fb', 'fb_ord') => 1);
419
3fa6e24b
TW
420delete $Expect_File{ file_path_name('.', 'fa', 'fsl') } unless $symlink_exists;
421%Expect_Name = ();
422%Expect_Dir = ();
bb7dc48b
JH
423
424File::Find::finddepth( {wanted => \&wanted_File, no_chdir => 1},
425 File::Spec->curdir );
426
3fa6e24b
TW
427Check( scalar(keys %Expect_File) == 0 );
428
429
430print "# check preprocess\n";
431%Expect_File = ();
432%Expect_Name = ();
433%Expect_Dir = (
434 File::Spec->curdir => {fa => 1, fb => 1},
435 dir_path('.', 'fa') => {faa => 1, fab => 1, fa_ord => 1},
436 dir_path('.', 'fa', 'faa') => {faa_ord => 1},
437 dir_path('.', 'fa', 'fab') => {faba => 1, fab_ord => 1},
438 dir_path('.', 'fa', 'fab', 'faba') => {faba_ord => 1},
439 dir_path('.', 'fb') => {fba => 1, fb_ord => 1},
440 dir_path('.', 'fb', 'fba') => {fba_ord => 1}
441 );
bb7dc48b
JH
442
443File::Find::find( {wanted => \&noop_wanted,
444 preprocess => \&my_preprocess}, File::Spec->curdir );
445
3fa6e24b
TW
446Check( scalar(keys %Expect_Dir) == 0 );
447
448
449print "# check postprocess\n";
450%Expect_File = ();
451%Expect_Name = ();
452%Expect_Dir = (
453 File::Spec->curdir => 1,
454 dir_path('.', 'fa') => 1,
455 dir_path('.', 'fa', 'faa') => 1,
456 dir_path('.', 'fa', 'fab') => 1,
457 dir_path('.', 'fa', 'fab', 'faba') => 1,
458 dir_path('.', 'fb') => 1,
459 dir_path('.', 'fb', 'fba') => 1
460 );
bb7dc48b
JH
461
462File::Find::find( {wanted => \&noop_wanted,
463 postprocess => \&my_postprocess}, File::Spec->curdir );
464
3fa6e24b
TW
465Check( scalar(keys %Expect_Dir) == 0 );
466
17ab9c14
JB
467{
468 print "# checking argument localization\n";
469
470 ### this checks the fix of perlbug [19977] ###
471 my @foo = qw( a b c d e f );
472 my %pre = map { $_ => } @foo;
473
474 File::Find::find( sub { } , 'fa' ) for @foo;
475 delete $pre{$_} for @foo;
476
477 Check( scalar( keys %pre ) == 0 );
478}
3fa6e24b 479
bc125c03
NC
480# see thread starting
481# http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2004-02/msg00351.html
482{
483 print "# checking that &_ and %_ are still accessible and that\n",
484 "# tie magic on \$_ is not triggered\n";
485
486 my $true_count;
487 my $sub = 0;
488 sub _ {
489 ++$sub;
490 }
491 my $tie_called = 0;
492
493 package Foo;
494 sub STORE {
495 ++$tie_called;
496 }
497 sub FETCH {return 'N'};
498 sub TIESCALAR {bless []};
499 package main;
500
501 Check( scalar( keys %_ ) == 0 );
502 my @foo = 'n';
503 tie $foo[0], "Foo";
504
505 File::Find::find( sub { $true_count++; $_{$_}++; &_; } , 'fa' ) for @foo;
506 untie $_;
507
508 Check( $tie_called == 0);
509 Check( scalar( keys %_ ) == $true_count );
510 Check( $sub == $true_count );
511 Check( scalar( @foo ) == 1);
512 Check( $foo[0] eq 'N' );
513}
514
3fa6e24b 515if ( $symlink_exists ) {
bb7dc48b 516 print "# --- symbolic link tests --- \n";
3fa6e24b 517 $FastFileTests_OK= 1;
7e47e6ff 518
7e47e6ff 519
3fa6e24b
TW
520 # Verify that File::Find::find will call wanted even if the topdir of
521 # is a symlink to a directory, and it shouldn't follow the link
522 # unless follow is set, which it isn't in this case
523 %Expect_File = ( file_path('fsl') => 1 );
524 %Expect_Name = ();
525 %Expect_Dir = ();
526 File::Find::find( {wanted => \&wanted_File_Dir}, topdir('fa', 'fsl') );
527 Check( scalar(keys %Expect_File) == 0 );
528
529
bb7dc48b
JH
530 %Expect_File = (File::Spec->curdir => 1, file_path('fa_ord') => 1,
531 file_path('fsl') => 1, file_path('fb_ord') => 1,
532 file_path('fba') => 1, file_path('fba_ord') => 1,
533 file_path('fab') => 1, file_path('fab_ord') => 1,
534 file_path('faba') => 1, file_path('faa') => 1,
535 file_path('faa_ord') => 1);
536
3fa6e24b 537 %Expect_Name = ();
bb7dc48b
JH
538
539 %Expect_Dir = (File::Spec->curdir => 1, dir_path('fa') => 1,
540 dir_path('faa') => 1, dir_path('fab') => 1,
541 dir_path('faba') => 1, dir_path('fb') => 1,
542 dir_path('fba') => 1);
543
544 File::Find::find( {wanted => \&wanted_File_Dir_prune,
545 follow_fast => 1}, topdir('fa') );
546
3fa6e24b
TW
547 Check( scalar(keys %Expect_File) == 0 );
548
549
bb7dc48b
JH
550 # no_chdir is in effect, hence we use file_path_name to specify
551 # the expected paths for %Expect_File
552
553 %Expect_File = (file_path_name('fa') => 1,
554 file_path_name('fa', 'fa_ord') => 1,
555 file_path_name('fa', 'fsl') => 1,
556 file_path_name('fa', 'fsl', 'fb_ord') => 1,
557 file_path_name('fa', 'fsl', 'fba') => 1,
558 file_path_name('fa', 'fsl', 'fba', 'fba_ord') => 1,
559 file_path_name('fa', 'fab') => 1,
560 file_path_name('fa', 'fab', 'fab_ord') => 1,
561 file_path_name('fa', 'fab', 'faba') => 1,
562 file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
563 file_path_name('fa', 'faa') => 1,
564 file_path_name('fa', 'faa', 'faa_ord') => 1);
565
3fa6e24b 566 %Expect_Name = ();
3fa6e24b 567
bb7dc48b
JH
568 %Expect_Dir = (dir_path('fa') => 1,
569 dir_path('fa', 'faa') => 1,
570 dir_path('fa', 'fab') => 1,
571 dir_path('fa', 'fab', 'faba') => 1,
572 dir_path('fb') => 1,
573 dir_path('fb', 'fba') => 1);
574
575 File::Find::find( {wanted => \&wanted_File_Dir, follow_fast => 1,
576 no_chdir => 1}, topdir('fa') );
577
578 Check( scalar(keys %Expect_File) == 0 );
3fa6e24b
TW
579
580 %Expect_File = ();
bb7dc48b
JH
581
582 %Expect_Name = (file_path_name('fa') => 1,
583 file_path_name('fa', 'fa_ord') => 1,
584 file_path_name('fa', 'fsl') => 1,
585 file_path_name('fa', 'fsl', 'fb_ord') => 1,
586 file_path_name('fa', 'fsl', 'fba') => 1,
587 file_path_name('fa', 'fsl', 'fba', 'fba_ord') => 1,
588 file_path_name('fa', 'fab') => 1,
589 file_path_name('fa', 'fab', 'fab_ord') => 1,
590 file_path_name('fa', 'fab', 'faba') => 1,
591 file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
592 file_path_name('fa', 'faa') => 1,
3fa6e24b 593 file_path_name('fa', 'faa', 'faa_ord') => 1);
bb7dc48b 594
3fa6e24b 595 %Expect_Dir = ();
3fa6e24b 596
bb7dc48b
JH
597 File::Find::finddepth( {wanted => \&wanted_Name,
598 follow_fast => 1}, topdir('fa') );
599
600 Check( scalar(keys %Expect_Name) == 0 );
3fa6e24b 601
bb7dc48b
JH
602 # no_chdir is in effect, hence we use file_path_name to specify
603 # the expected paths for %Expect_File
604
605 %Expect_File = (file_path_name('fa') => 1,
606 file_path_name('fa', 'fa_ord') => 1,
607 file_path_name('fa', 'fsl') => 1,
608 file_path_name('fa', 'fsl', 'fb_ord') => 1,
609 file_path_name('fa', 'fsl', 'fba') => 1,
610 file_path_name('fa', 'fsl', 'fba', 'fba_ord') => 1,
611 file_path_name('fa', 'fab') => 1,
612 file_path_name('fa', 'fab', 'fab_ord') => 1,
613 file_path_name('fa', 'fab', 'faba') => 1,
614 file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
615 file_path_name('fa', 'faa') => 1,
3fa6e24b 616 file_path_name('fa', 'faa', 'faa_ord') => 1);
bb7dc48b 617
3fa6e24b
TW
618 %Expect_Name = ();
619 %Expect_Dir = ();
bb7dc48b
JH
620
621 File::Find::finddepth( {wanted => \&wanted_File, follow_fast => 1,
622 no_chdir => 1}, topdir('fa') );
623
3fa6e24b
TW
624 Check( scalar(keys %Expect_File) == 0 );
625
626
627 print "# check dangling symbolic links\n";
628 MkDir( dir_path('dangling_dir'), 0770 );
bb7dc48b
JH
629 CheckDie( symlink( dir_path('dangling_dir'),
630 file_path('dangling_dir_sl') ) );
3fa6e24b
TW
631 rmdir dir_path('dangling_dir');
632 touch(file_path('dangling_file'));
786dada4 633 CheckDie( symlink('../dangling_file','fa/dangling_file_sl') );
3fa6e24b
TW
634 unlink file_path('dangling_file');
635
636 {
637 # these tests should also emit a warning
bb7dc48b
JH
638 use warnings;
639
640 %Expect_File = (File::Spec->curdir => 1,
615a2b9b 641 file_path('dangling_file_sl') => 1,
bb7dc48b
JH
642 file_path('fa_ord') => 1,
643 file_path('fsl') => 1,
644 file_path('fb_ord') => 1,
645 file_path('fba') => 1,
646 file_path('fba_ord') => 1,
647 file_path('fab') => 1,
648 file_path('fab_ord') => 1,
649 file_path('faba') => 1,
650 file_path('faba_ord') => 1,
651 file_path('faa') => 1,
652 file_path('faa_ord') => 1);
653
3fa6e24b
TW
654 %Expect_Name = ();
655 %Expect_Dir = ();
656 undef $warn_msg;
bb7dc48b
JH
657
658 File::Find::find( {wanted => \&wanted_File, follow => 1,
659 dangling_symlinks =>
660 sub { $warn_msg = "$_[0] is a dangling symbolic link" }
661 },
662 topdir('dangling_dir_sl'), topdir('fa') );
663
3fa6e24b 664 Check( scalar(keys %Expect_File) == 0 );
615a2b9b 665 Check( $warn_msg =~ m|dangling_file_sl is a dangling symbolic link| );
bb7dc48b
JH
666 unlink file_path('fa', 'dangling_file_sl'),
667 file_path('dangling_dir_sl');
668
3fa6e24b
TW
669 }
670
671
672 print "# check recursion\n";
786dada4 673 CheckDie( symlink('../faa','fa/faa/faa_sl') );
7e47e6ff 674 undef $@;
bb7dc48b
JH
675 eval {File::Find::find( {wanted => \&simple_wanted, follow => 1,
676 no_chdir => 1}, topdir('fa') ); };
a1ccf0c4 677 Check( $@ =~ m|for_find[:/]fa[:/]faa[:/]faa_sl is a recursive symbolic link|i );
3fa6e24b 678 unlink file_path('fa', 'faa', 'faa_sl');
7e47e6ff 679
3fa6e24b
TW
680
681 print "# check follow_skip (file)\n";
786dada4 682 CheckDie( symlink('./fa_ord','fa/fa_ord_sl') ); # symlink to a file
7e47e6ff 683 undef $@;
bb7dc48b
JH
684
685 eval {File::Find::finddepth( {wanted => \&simple_wanted,
686 follow => 1,
687 follow_skip => 0, no_chdir => 1},
688 topdir('fa') );};
689
a1ccf0c4 690 Check( $@ =~ m|for_find[:/]fa[:/]fa_ord encountered a second time|i );
7e47e6ff 691
7e47e6ff 692
bb7dc48b
JH
693 # no_chdir is in effect, hence we use file_path_name to specify
694 # the expected paths for %Expect_File
695
696 %Expect_File = (file_path_name('fa') => 1,
aaaf2301
NC
697 file_path_name('fa', 'fa_ord') => 2,
698 # We may encounter the symlink first
699 file_path_name('fa', 'fa_ord_sl') => 2,
bb7dc48b
JH
700 file_path_name('fa', 'fsl') => 1,
701 file_path_name('fa', 'fsl', 'fb_ord') => 1,
702 file_path_name('fa', 'fsl', 'fba') => 1,
703 file_path_name('fa', 'fsl', 'fba', 'fba_ord') => 1,
704 file_path_name('fa', 'fab') => 1,
705 file_path_name('fa', 'fab', 'fab_ord') => 1,
706 file_path_name('fa', 'fab', 'faba') => 1,
707 file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
708 file_path_name('fa', 'faa') => 1,
709 file_path_name('fa', 'faa', 'faa_ord') => 1);
3fa6e24b
TW
710
711 %Expect_Name = ();
bb7dc48b
JH
712
713 %Expect_Dir = (dir_path('fa') => 1,
714 dir_path('fa', 'faa') => 1,
715 dir_path('fa', 'fab') => 1,
716 dir_path('fa', 'fab', 'faba') => 1,
717 dir_path('fb') => 1,
718 dir_path('fb','fba') => 1);
719
720 File::Find::finddepth( {wanted => \&wanted_File_Dir, follow => 1,
721 follow_skip => 1, no_chdir => 1},
3fa6e24b 722 topdir('fa') );
615a2b9b 723 Check( scalar(keys %Expect_File) == 0 );
3fa6e24b
TW
724 unlink file_path('fa', 'fa_ord_sl');
725
726
727 print "# check follow_skip (directory)\n";
786dada4 728 CheckDie( symlink('./faa','fa/faa_sl') ); # symlink to a directory
3fa6e24b 729 undef $@;
bb7dc48b
JH
730
731 eval {File::Find::find( {wanted => \&simple_wanted, follow => 1,
732 follow_skip => 0, no_chdir => 1},
3fa6e24b 733 topdir('fa') );};
bb7dc48b 734
a1ccf0c4 735 Check( $@ =~ m|for_find[:/]fa[:/]faa[:/]? encountered a second time|i );
3fa6e24b
TW
736
737
738 undef $@;
bb7dc48b
JH
739
740 eval {File::Find::find( {wanted => \&simple_wanted, follow => 1,
741 follow_skip => 1, no_chdir => 1},
3fa6e24b 742 topdir('fa') );};
bb7dc48b 743
a1ccf0c4 744 Check( $@ =~ m|for_find[:/]fa[:/]faa[:/]? encountered a second time|i );
3fa6e24b 745
bb7dc48b
JH
746 # no_chdir is in effect, hence we use file_path_name to specify
747 # the expected paths for %Expect_File
748
749 %Expect_File = (file_path_name('fa') => 1,
750 file_path_name('fa', 'fa_ord') => 1,
751 file_path_name('fa', 'fsl') => 1,
752 file_path_name('fa', 'fsl', 'fb_ord') => 1,
753 file_path_name('fa', 'fsl', 'fba') => 1,
754 file_path_name('fa', 'fsl', 'fba', 'fba_ord') => 1,
755 file_path_name('fa', 'fab') => 1,
756 file_path_name('fa', 'fab', 'fab_ord') => 1,
757 file_path_name('fa', 'fab', 'faba') => 1,
758 file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
759 file_path_name('fa', 'faa') => 1,
aaaf2301
NC
760 file_path_name('fa', 'faa', 'faa_ord') => 1,
761 # We may actually encounter the symlink first.
762 file_path_name('fa', 'faa_sl') => 1,
763 file_path_name('fa', 'faa_sl', 'faa_ord') => 1);
3fa6e24b
TW
764
765 %Expect_Name = ();
bb7dc48b
JH
766
767 %Expect_Dir = (dir_path('fa') => 1,
768 dir_path('fa', 'faa') => 1,
769 dir_path('fa', 'fab') => 1,
770 dir_path('fa', 'fab', 'faba') => 1,
771 dir_path('fb') => 1,
772 dir_path('fb', 'fba') => 1);
773
774 File::Find::find( {wanted => \&wanted_File_Dir, follow => 1,
775 follow_skip => 2, no_chdir => 1}, topdir('fa') );
776
aaaf2301
NC
777 # If we encountered the symlink first, then the entries corresponding to
778 # the real name remain, if the real name first then the symlink
779 my @names = sort keys %Expect_File;
615a2b9b 780 Check( @names == 1 );
aaaf2301
NC
781 # Normalise both to the original name
782 s/_sl// foreach @names;
615a2b9b 783 Check ($names[0] eq file_path_name('fa', 'faa', 'faa_ord'));
3fa6e24b
TW
784 unlink file_path('fa', 'faa_sl');
785
17ab9c14 786}
68c65ec0
B
787
788
789# Win32 checks - [perl #41555]
790if ($^O eq 'MSWin32') {
791 require File::Spec::Win32;
792 my ($volume) = File::Spec::Win32->splitpath($orig_dir, 1);
793 print STDERR "VOLUME = $volume\n";
794
795 # with chdir
796 %Expect_File = (File::Spec->curdir => 1,
797 file_path('fsl') => 1,
798 file_path('fa_ord') => 1,
799 file_path('fab') => 1,
800 file_path('fab_ord') => 1,
801 file_path('faba') => 1,
802 file_path('faba_ord') => 1,
803 file_path('faa') => 1,
804 file_path('faa_ord') => 1);
805
806 delete $Expect_File{ file_path('fsl') } unless $symlink_exists;
807 %Expect_Name = ();
808
809 %Expect_Dir = (dir_path('fa') => 1,
810 dir_path('faa') => 1,
811 dir_path('fab') => 1,
812 dir_path('faba') => 1,
813 dir_path('fb') => 1,
814 dir_path('fba') => 1);
815
816
817
818 File::Find::find( {wanted => \&wanted_File_Dir}, topdir('fa'));
819 Check( scalar(keys %Expect_File) == 0 );
820
821 # no_chdir
822 %Expect_File = ($volume . file_path_name('fa') => 1,
823 $volume . file_path_name('fa', 'fsl') => 1,
824 $volume . file_path_name('fa', 'fa_ord') => 1,
825 $volume . file_path_name('fa', 'fab') => 1,
826 $volume . file_path_name('fa', 'fab', 'fab_ord') => 1,
827 $volume . file_path_name('fa', 'fab', 'faba') => 1,
828 $volume . file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
829 $volume . file_path_name('fa', 'faa') => 1,
830 $volume . file_path_name('fa', 'faa', 'faa_ord') => 1);
831
832
833 delete $Expect_File{ $volume . file_path_name('fa', 'fsl') } unless $symlink_exists;
834 %Expect_Name = ();
835
836 %Expect_Dir = ($volume . dir_path('fa') => 1,
837 $volume . dir_path('fa', 'faa') => 1,
838 $volume . dir_path('fa', 'fab') => 1,
839 $volume . dir_path('fa', 'fab', 'faba') => 1);
840
841 File::Find::find( {wanted => \&wanted_File_Dir, no_chdir => 1}, $volume . topdir('fa'));
842 Check( scalar(keys %Expect_File) == 0 );
843}
51393fc0
A
844
845
846if ($symlink_exists) { # Issue 68260
847 print "# BUG 68260\n";
848 MkDir (dir_path ('fa', 'fac'), 0770);
849 MkDir (dir_path ('fb', 'fbc'), 0770);
850 touch (file_path ('fa', 'fac', 'faca'));
786dada4 851 CheckDie (symlink ('..////../fa/fac/faca', 'fb/fbc/fbca'));
51393fc0
A
852
853 use warnings;
854 my $dangling_symlink;
855 local $SIG {__WARN__} = sub {
856 local $" = " ";
857 $dangling_symlink ++ if "@_" =~ /dangling symbolic link/;
858 };
859
860 File::Find::find (
861 {
862 wanted => sub {1;},
863 follow => 1,
864 follow_skip => 2,
865 dangling_symlinks => 1,
866 },
867 File::Spec -> curdir
868 );
869
870 Check (!$dangling_symlink);
871}
a0b245d5
AD
872
873
874if ($^O eq 'MSWin32') {
875 # Check F:F:f correctly handles a root directory path.
876 # Rather than processing the entire drive (!), simply test that the
877 # first file passed to the wanted routine is correct and then bail out.
878 $orig_dir =~ /^(\w:)/ or die "expected a drive: $orig_dir";
879 my $drive = $1;
880
881 # Determine the file in the root directory which would be
882 # first if processed in sorted order. Create one if necessary.
883 my $expected_first_file;
884 opendir(ROOT_DIR, "/") or die "cannot opendir /: $!\n";
885 foreach my $f (sort readdir ROOT_DIR) {
886 if (-f "/$f") {
887 $expected_first_file = $f;
888 last;
889 }
890 }
891 closedir ROOT_DIR;
892 my $created_file;
893 unless (defined $expected_first_file) {
894 $expected_first_file = '__perl_File_Find_test.tmp';
895 open(F, ">", "/$expected_first_file") && close(F)
896 or die "cannot create file in root directory: $!\n";
897 $created_file = 1;
898 }
899
900 # Run F:F:f with/without no_chdir for each possible style of root path.
901 # NB. If HOME were "/", then an inadvertent chdir('') would fluke the
902 # expected result, so ensure it is something else:
903 local $ENV{HOME} = $orig_dir;
904 foreach my $no_chdir (0, 1) {
905 foreach my $root_dir ("/", "\\", "$drive/", "$drive\\") {
906 eval {
907 File::Find::find({
908 'no_chdir' => $no_chdir,
909 'preprocess' => sub { return sort @_ },
910 'wanted' => sub {
911 -f or return; # the first call is for $root_dir itself.
912 my $got = $File::Find::name;
913 my $exp = "$root_dir$expected_first_file";
914 print "# no_chdir=$no_chdir $root_dir '$got'\n";
915 Check($got eq $exp);
916 die "done"; # don't process the entire drive!
917 },
918 }, $root_dir);
919 };
920 # If F:F:f did not die "done" then it did not Check() either.
921 unless ($@ and $@ =~ /done/) {
922 print "# no_chdir=$no_chdir $root_dir ",
923 ($@ ? "error: $@" : "no files found"), "\n";
924 Check(0);
925 }
926 }
927 }
928 if ($created_file) {
929 unlink("/$expected_first_file")
930 or warn "can't unlink /$expected_first_file: $!\n";
931 }
932}