682d2332d5a8709433e6909464e0f995cf43d929
[p5sagit/p5-mst-13.2.git] / lib / File / Find / t / find.t
1 #!./perl
2
3
4 my %Expect_File = (); # what we expect for $_ 
5 my %Expect_Name = (); # what we expect for $File::Find::name/fullname
6 my %Expect_Dir  = (); # what we expect for $File::Find::dir
7 my $symlink_exists = eval { symlink("",""); 1 };
8 my $warn_msg;
9
10
11 BEGIN {
12     chdir 't' if -d 't';
13     unshift @INC => '../lib';
14
15     $SIG{'__WARN__'} = sub { $warn_msg = $_[0]; warn "# $_[0]"; }
16 }
17
18 if ( $symlink_exists ) { print "1..188\n"; }
19 else                   { print "1..78\n";  }
20
21 BEGIN {
22     use File::Spec;
23     if ($^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'VMS')
24      {
25       # This is a hack - at present File::Find does not produce native names on 
26       # Win32 or VMS, so force File::Spec to use Unix names.
27       # must be set *before* importing File::Find
28       require File::Spec::Unix;
29       @File::Spec::ISA = 'File::Spec::Unix';
30      }
31      require File::Find;
32      import File::Find;
33 }
34 cleanup();
35
36 find({wanted => sub { print "ok 1\n" if $_ eq 'commonsense.t'; } },
37    File::Spec->curdir);
38
39 finddepth({wanted => sub { print "ok 2\n" if $_ eq 'commonsense.t'; } },
40         File::Spec->curdir);
41
42 my $case = 2;
43 my $FastFileTests_OK = 0;
44
45 sub cleanup {
46     if (-d dir_path('for_find')) {
47         chdir(dir_path('for_find'));
48     }
49     if (-d dir_path('fa')) {
50         unlink file_path('fa', 'fa_ord'),
51                file_path('fa', 'fsl'),
52                file_path('fa', 'faa', 'faa_ord'),
53                file_path('fa', 'fab', 'fab_ord'),
54                file_path('fa', 'fab', 'faba', 'faba_ord'),
55                file_path('fb', 'fb_ord'),
56                file_path('fb', 'fba', 'fba_ord');
57         rmdir dir_path('fa', 'faa');
58         rmdir dir_path('fa', 'fab', 'faba');
59         rmdir dir_path('fa', 'fab');
60         rmdir dir_path('fa');
61         rmdir dir_path('fb', 'fba');
62         rmdir dir_path('fb');
63         chdir File::Spec->updir;
64         rmdir dir_path('for_find');
65     }
66 }
67
68 END {
69     cleanup();
70 }
71
72 sub Check($) {
73     $case++;
74     if ($_[0]) { print "ok $case\n"; }
75     else       { print "not ok $case\n"; }
76 }
77
78 sub CheckDie($) {
79     $case++;
80     if ($_[0]) { print "ok $case\n"; }
81     else { print "not ok $case\n $!\n"; exit 0; }
82 }
83
84 sub touch {
85     CheckDie( open(my $T,'>',$_[0]) );
86 }
87
88 sub MkDir($$) {
89     CheckDie( mkdir($_[0],$_[1]) );
90 }
91
92 sub wanted_File_Dir {
93     print "# \$File::Find::dir => '$File::Find::dir'\n";
94     print "# \$_ => '$_'\n";
95     s#\.$## if ($^O eq 'VMS' && $_ ne '.');
96     Check( $Expect_File{$_} );
97     if ( $FastFileTests_OK ) {
98         delete $Expect_File{ $_} 
99           unless ( $Expect_Dir{$_} && ! -d _ );
100     } else {
101         delete $Expect_File{$_} 
102           unless ( $Expect_Dir{$_} && ! -d $_ );
103     }
104 }
105
106 sub wanted_File_Dir_prune {
107     &wanted_File_Dir;
108     $File::Find::prune=1 if  $_ eq 'faba';
109 }
110
111 sub wanted_Name {
112     my $n = $File::Find::name;
113     $n =~ s#\.$## if ($^O eq 'VMS' && $n ne '.');
114     print "# \$File::Find::name => '$n'\n";
115     my $i = rindex($n,'/');
116     my $OK = exists($Expect_Name{$n});
117     unless ($^O eq 'MacOS') {
118         if ( $OK ) {
119             $OK= exists($Expect_Name{substr($n,0,$i)})  if $i >= 0;    
120         }
121     }
122     Check($OK);
123     delete $Expect_Name{$n};
124 }
125
126 sub wanted_File {
127     print "# \$_ => '$_'\n";
128     s#\.$## if ($^O eq 'VMS' && $_ ne '.');
129     my $i = rindex($_,'/');
130     my $OK = exists($Expect_File{ $_});
131     unless ($^O eq 'MacOS') {
132         if ( $OK ) {
133             $OK= exists($Expect_File{ substr($_,0,$i)})  if $i >= 0;
134         }
135     }
136     Check($OK);
137     delete $Expect_File{ $_};
138 }
139
140 sub simple_wanted {
141     print "# \$File::Find::dir => '$File::Find::dir'\n";
142     print "# \$_ => '$_'\n";
143 }
144
145 sub noop_wanted {}
146
147 sub my_preprocess {
148     @files = @_;
149     print "# --preprocess--\n";
150     print "#   \$File::Find::dir => '$File::Find::dir' \n";
151     foreach $file (@files) {
152         $file =~ s/\.(dir)?$// if $^O eq 'VMS';
153         print "#   $file \n";
154         delete $Expect_Dir{ $File::Find::dir }->{$file};
155     }
156     print "# --end preprocess--\n";
157     Check(scalar(keys %{$Expect_Dir{ $File::Find::dir }}) == 0);
158     if (scalar(keys %{$Expect_Dir{ $File::Find::dir }}) == 0) {
159         delete $Expect_Dir{ $File::Find::dir }
160     }
161     return @files;
162 }
163
164 sub my_postprocess {
165     print "# postprocess: \$File::Find::dir => '$File::Find::dir' \n";
166     delete $Expect_Dir{ $File::Find::dir};
167 }
168
169
170 # Use dir_path() to specify a directory path that's expected for
171 # $File::Find::dir (%Expect_Dir). Also use it in file operations like
172 # chdir, rmdir etc.
173 #
174 # dir_path() concatenates directory names to form a *relative*
175 # directory path, independent from the platform it's run on, although
176 # there are limitations. Don't try to create an absolute path,
177 # because that may fail on operating systems that have the concept of
178 # volume names (e.g. Mac OS). As a special case, you can pass it a "." 
179 # as first argument, to create a directory path like "./fa/dir" on
180 # operating systems other than Mac OS (actually, Mac OS will ignore
181 # the ".", if it's the first argument). If there's no second argument,
182 # this function will return the empty string on Mac OS and the string
183 # "./" otherwise.
184
185 sub dir_path {
186     my $first_arg = shift @_;
187
188     if ($first_arg eq '.') {
189         if ($^O eq 'MacOS') {
190             return '' unless @_;
191             # ignore first argument; return a relative path
192             # with leading ":" and with trailing ":"
193             return File::Spec->catdir(@_); 
194         } else { # other OS
195             return './' unless @_;
196             my $path = File::Spec->catdir(@_);
197             # add leading "./"
198             $path = "./$path";
199             return $path;
200         }
201
202     } else { # $first_arg ne '.'
203         return $first_arg unless @_; # return plain filename
204         return File::Spec->catdir($first_arg, @_); # relative path
205     }
206 }
207
208
209 # Use topdir() to specify a directory path that you want to pass to
210 # find/finddepth. Basically, topdir() does the same as dir_path() (see
211 # above), except that there's no trailing ":" on Mac OS.
212
213 sub topdir {
214     my $path = dir_path(@_);
215     $path =~ s/:$// if ($^O eq 'MacOS');
216     return $path;
217 }
218
219
220 # Use file_path() to specify a file path that's expected for $_
221 # (%Expect_File). Also suitable for file operations like unlink etc.
222 #
223 # file_path() concatenates directory names (if any) and a filename to
224 # form a *relative* file path (the last argument is assumed to be a
225 # file). It's independent from the platform it's run on, although
226 # there are limitations. As a special case, you can pass it a "." as 
227 # first argument, to create a file path like "./fa/file" on operating 
228 # systems other than Mac OS (actually, Mac OS will ignore the ".", if 
229 # it's the first argument). If there's no second argument, this 
230 # function will return the empty string on Mac OS and the string "./" 
231 # otherwise.
232
233 sub file_path {
234     my $first_arg = shift @_;
235
236     if ($first_arg eq '.') {
237         if ($^O eq 'MacOS') {
238             return '' unless @_;
239             # ignore first argument; return a relative path  
240             # with leading ":", but without trailing ":"
241             return File::Spec->catfile(@_); 
242         } else { # other OS
243             return './' unless @_;
244             my $path = File::Spec->catfile(@_);
245             # add leading "./" 
246             $path = "./$path"; 
247             return $path;
248         }
249
250     } else { # $first_arg ne '.'
251         return $first_arg unless @_; # return plain filename
252         return File::Spec->catfile($first_arg, @_); # relative path
253     }
254 }
255
256
257 # Use file_path_name() to specify a file path that's expected for
258 # $File::Find::Name (%Expect_Name). Note: When the no_chdir => 1
259 # option is in effect, $_ is the same as $File::Find::Name. In that
260 # case, also use this function to specify a file path that's expected
261 # for $_.
262 #
263 # Basically, file_path_name() does the same as file_path() (see
264 # above), except that there's always a leading ":" on Mac OS, even for
265 # plain file/directory names.
266
267 sub file_path_name {
268     my $path = file_path(@_);
269     $path = ":$path" if (($^O eq 'MacOS') && ($path !~ /:/));
270     return $path;
271 }
272
273
274
275 MkDir( dir_path('for_find'), 0770 );
276 CheckDie(chdir( dir_path('for_find')));
277 MkDir( dir_path('fa'), 0770 );
278 MkDir( dir_path('fb'), 0770  );
279 touch( file_path('fb', 'fb_ord') );
280 MkDir( dir_path('fb', 'fba'), 0770  );
281 touch( file_path('fb', 'fba', 'fba_ord') );
282 if ($^O eq 'MacOS') {
283       CheckDie( symlink(':fb',':fa:fsl') ) if $symlink_exists;
284 } else {
285       CheckDie( symlink('../fb','fa/fsl') ) if $symlink_exists;
286 }
287 touch( file_path('fa', 'fa_ord') );
288
289 MkDir( dir_path('fa', 'faa'), 0770  );
290 touch( file_path('fa', 'faa', 'faa_ord') );
291 MkDir( dir_path('fa', 'fab'), 0770  );
292 touch( file_path('fa', 'fab', 'fab_ord') );
293 MkDir( dir_path('fa', 'fab', 'faba'), 0770  );
294 touch( file_path('fa', 'fab', 'faba', 'faba_ord') );
295
296
297 %Expect_File = (File::Spec->curdir => 1, file_path('fsl') => 1,
298                 file_path('fa_ord') => 1, file_path('fab') => 1,
299                 file_path('fab_ord') => 1, file_path('faba') => 1,
300                 file_path('faa') => 1, file_path('faa_ord') => 1);
301
302 delete $Expect_File{ file_path('fsl') } unless $symlink_exists;
303 %Expect_Name = ();
304
305 %Expect_Dir = ( dir_path('fa') => 1, dir_path('faa') => 1,
306                 dir_path('fab') => 1, dir_path('faba') => 1,
307                 dir_path('fb') => 1, dir_path('fba') => 1);
308
309 delete @Expect_Dir{ dir_path('fb'), dir_path('fba') } unless $symlink_exists;
310 File::Find::find( {wanted => \&wanted_File_Dir_prune}, topdir('fa') ); 
311 Check( scalar(keys %Expect_File) == 0 );
312
313
314 print "# check re-entrancy\n";
315
316 %Expect_File = (File::Spec->curdir => 1, file_path('fsl') => 1,
317                 file_path('fa_ord') => 1, file_path('fab') => 1,
318                 file_path('fab_ord') => 1, file_path('faba') => 1,
319                 file_path('faa') => 1, file_path('faa_ord') => 1);
320
321 delete $Expect_File{ file_path('fsl') } unless $symlink_exists;
322 %Expect_Name = ();
323
324 %Expect_Dir = ( dir_path('fa') => 1, dir_path('faa') => 1,
325                 dir_path('fab') => 1, dir_path('faba') => 1,
326                 dir_path('fb') => 1, dir_path('fba') => 1);
327
328 delete @Expect_Dir{ dir_path('fb'), dir_path('fba') } unless $symlink_exists;
329
330 File::Find::find( {wanted => sub { wanted_File_Dir_prune();
331                                     File::Find::find( {wanted => sub
332                                     {} }, File::Spec->curdir ); } },
333                                     topdir('fa') );
334
335 Check( scalar(keys %Expect_File) == 0 ); 
336
337
338 # no_chdir is in effect, hence we use file_path_name to specify the expected paths for %Expect_File
339
340 %Expect_File = (file_path_name('fa') => 1,
341                 file_path_name('fa', 'fsl') => 1,
342                 file_path_name('fa', 'fa_ord') => 1,
343                 file_path_name('fa', 'fab') => 1,
344                 file_path_name('fa', 'fab', 'fab_ord') => 1,
345                 file_path_name('fa', 'fab', 'faba') => 1,
346                 file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
347                 file_path_name('fa', 'faa') => 1,
348                 file_path_name('fa', 'faa', 'faa_ord') => 1,);
349
350 delete $Expect_File{ file_path_name('fa', 'fsl') } unless $symlink_exists;
351 %Expect_Name = ();
352
353 %Expect_Dir = (dir_path('fa') => 1,
354                dir_path('fa', 'faa') => 1,
355                dir_path('fa', 'fab') => 1,
356                dir_path('fa', 'fab', 'faba') => 1,
357                dir_path('fb') => 1,
358                dir_path('fb', 'fba') => 1);
359
360 delete @Expect_Dir{ dir_path('fb'), dir_path('fb', 'fba') }
361     unless $symlink_exists;
362
363 File::Find::find( {wanted => \&wanted_File_Dir, no_chdir => 1},
364                   topdir('fa') ); Check( scalar(keys %Expect_File) == 0 );
365
366
367 %Expect_File = ();
368
369 %Expect_Name = (File::Spec->curdir => 1,
370                 file_path_name('.', 'fa') => 1,
371                 file_path_name('.', 'fa', 'fsl') => 1,
372                 file_path_name('.', 'fa', 'fa_ord') => 1,
373                 file_path_name('.', 'fa', 'fab') => 1,
374                 file_path_name('.', 'fa', 'fab', 'fab_ord') => 1,
375                 file_path_name('.', 'fa', 'fab', 'faba') => 1,
376                 file_path_name('.', 'fa', 'fab', 'faba', 'faba_ord') => 1,
377                 file_path_name('.', 'fa', 'faa') => 1,
378                 file_path_name('.', 'fa', 'faa', 'faa_ord') => 1,
379                 file_path_name('.', 'fb') => 1,
380                 file_path_name('.', 'fb', 'fba') => 1,
381                 file_path_name('.', 'fb', 'fba', 'fba_ord') => 1,
382                 file_path_name('.', 'fb', 'fb_ord') => 1);
383
384 delete $Expect_Name{ file_path('.', 'fa', 'fsl') } unless $symlink_exists;
385 %Expect_Dir = (); 
386 File::Find::finddepth( {wanted => \&wanted_Name}, File::Spec->curdir );
387 Check( scalar(keys %Expect_Name) == 0 );
388
389
390 # no_chdir is in effect, hence we use file_path_name to specify the
391 # expected paths for %Expect_File
392
393 %Expect_File = (File::Spec->curdir => 1,
394                 file_path_name('.', 'fa') => 1,
395                 file_path_name('.', 'fa', 'fsl') => 1,
396                 file_path_name('.', 'fa', 'fa_ord') => 1,
397                 file_path_name('.', 'fa', 'fab') => 1,
398                 file_path_name('.', 'fa', 'fab', 'fab_ord') => 1,
399                 file_path_name('.', 'fa', 'fab', 'faba') => 1,
400                 file_path_name('.', 'fa', 'fab', 'faba', 'faba_ord') => 1,
401                 file_path_name('.', 'fa', 'faa') => 1,
402                 file_path_name('.', 'fa', 'faa', 'faa_ord') => 1,
403                 file_path_name('.', 'fb') => 1,
404                 file_path_name('.', 'fb', 'fba') => 1,
405                 file_path_name('.', 'fb', 'fba', 'fba_ord') => 1,
406                 file_path_name('.', 'fb', 'fb_ord') => 1);
407
408 delete $Expect_File{ file_path_name('.', 'fa', 'fsl') } unless $symlink_exists;
409 %Expect_Name = ();
410 %Expect_Dir = (); 
411
412 File::Find::finddepth( {wanted => \&wanted_File, no_chdir => 1},
413                      File::Spec->curdir );
414
415 Check( scalar(keys %Expect_File) == 0 );
416
417
418 print "# check preprocess\n";
419 %Expect_File = ();
420 %Expect_Name = ();
421 %Expect_Dir = (
422           File::Spec->curdir                 => {fa => 1, fb => 1}, 
423           dir_path('.', 'fa')                => {faa => 1, fab => 1, fa_ord => 1},
424           dir_path('.', 'fa', 'faa')         => {faa_ord => 1},
425           dir_path('.', 'fa', 'fab')         => {faba => 1, fab_ord => 1},
426           dir_path('.', 'fa', 'fab', 'faba') => {faba_ord => 1},
427           dir_path('.', 'fb')                => {fba => 1, fb_ord => 1},
428           dir_path('.', 'fb', 'fba')         => {fba_ord => 1}
429           );
430
431 File::Find::find( {wanted => \&noop_wanted,
432                    preprocess => \&my_preprocess}, File::Spec->curdir );
433
434 Check( scalar(keys %Expect_Dir) == 0 );
435
436
437 print "# check postprocess\n";
438 %Expect_File = ();
439 %Expect_Name = ();
440 %Expect_Dir = (
441           File::Spec->curdir                 => 1,
442           dir_path('.', 'fa')                => 1,
443           dir_path('.', 'fa', 'faa')         => 1,
444           dir_path('.', 'fa', 'fab')         => 1,
445           dir_path('.', 'fa', 'fab', 'faba') => 1,
446           dir_path('.', 'fb')                => 1,
447           dir_path('.', 'fb', 'fba')         => 1
448           );
449
450 File::Find::find( {wanted => \&noop_wanted,
451                    postprocess => \&my_postprocess}, File::Spec->curdir );
452
453 Check( scalar(keys %Expect_Dir) == 0 );
454
455
456 if ( $symlink_exists ) {
457     print "# --- symbolic link tests --- \n";
458     $FastFileTests_OK= 1;
459
460
461     # Verify that File::Find::find will call wanted even if the topdir of
462     # is a symlink to a directory, and it shouldn't follow the link
463     # unless follow is set, which it isn't in this case
464     %Expect_File = ( file_path('fsl') => 1 );
465     %Expect_Name = ();
466     %Expect_Dir = ();
467     File::Find::find( {wanted => \&wanted_File_Dir}, topdir('fa', 'fsl') );
468     Check( scalar(keys %Expect_File) == 0 );
469
470  
471     %Expect_File = (File::Spec->curdir => 1, file_path('fa_ord') => 1,
472                     file_path('fsl') => 1, file_path('fb_ord') => 1,
473                     file_path('fba') => 1, file_path('fba_ord') => 1,
474                     file_path('fab') => 1, file_path('fab_ord') => 1,
475                     file_path('faba') => 1, file_path('faa') => 1,
476                     file_path('faa_ord') => 1);
477
478     %Expect_Name = ();
479
480     %Expect_Dir = (File::Spec->curdir => 1, dir_path('fa') => 1,
481                    dir_path('faa') => 1, dir_path('fab') => 1,
482                    dir_path('faba') => 1, dir_path('fb') => 1,
483                    dir_path('fba') => 1);
484
485     File::Find::find( {wanted => \&wanted_File_Dir_prune,
486                        follow_fast => 1}, topdir('fa') );
487
488     Check( scalar(keys %Expect_File) == 0 );  
489
490
491     # no_chdir is in effect, hence we use file_path_name to specify
492     # the expected paths for %Expect_File
493
494     %Expect_File = (file_path_name('fa') => 1,
495                     file_path_name('fa', 'fa_ord') => 1,
496                     file_path_name('fa', 'fsl') => 1,
497                     file_path_name('fa', 'fsl', 'fb_ord') => 1,
498                     file_path_name('fa', 'fsl', 'fba') => 1,
499                     file_path_name('fa', 'fsl', 'fba', 'fba_ord') => 1,
500                     file_path_name('fa', 'fab') => 1,
501                     file_path_name('fa', 'fab', 'fab_ord') => 1,
502                     file_path_name('fa', 'fab', 'faba') => 1,
503                     file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
504                     file_path_name('fa', 'faa') => 1,
505                     file_path_name('fa', 'faa', 'faa_ord') => 1);
506
507     %Expect_Name = ();
508
509     %Expect_Dir = (dir_path('fa') => 1,
510                    dir_path('fa', 'faa') => 1,
511                    dir_path('fa', 'fab') => 1,
512                    dir_path('fa', 'fab', 'faba') => 1,
513                    dir_path('fb') => 1,
514                    dir_path('fb', 'fba') => 1);
515
516     File::Find::find( {wanted => \&wanted_File_Dir, follow_fast => 1,
517                        no_chdir => 1}, topdir('fa') );
518
519     Check( scalar(keys %Expect_File) == 0 );
520
521     %Expect_File = ();
522
523     %Expect_Name = (file_path_name('fa') => 1,
524                     file_path_name('fa', 'fa_ord') => 1,
525                     file_path_name('fa', 'fsl') => 1,
526                     file_path_name('fa', 'fsl', 'fb_ord') => 1,
527                     file_path_name('fa', 'fsl', 'fba') => 1,
528                     file_path_name('fa', 'fsl', 'fba', 'fba_ord') => 1,
529                     file_path_name('fa', 'fab') => 1,
530                     file_path_name('fa', 'fab', 'fab_ord') => 1,
531                     file_path_name('fa', 'fab', 'faba') => 1,
532                     file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
533                     file_path_name('fa', 'faa') => 1,
534                     file_path_name('fa', 'faa', 'faa_ord') => 1);
535
536     %Expect_Dir = ();
537
538     File::Find::finddepth( {wanted => \&wanted_Name,
539                             follow_fast => 1}, topdir('fa') );
540
541     Check( scalar(keys %Expect_Name) == 0 );
542
543     # no_chdir is in effect, hence we use file_path_name to specify
544     # the expected paths for %Expect_File
545
546     %Expect_File = (file_path_name('fa') => 1,
547                     file_path_name('fa', 'fa_ord') => 1,
548                     file_path_name('fa', 'fsl') => 1,
549                     file_path_name('fa', 'fsl', 'fb_ord') => 1,
550                     file_path_name('fa', 'fsl', 'fba') => 1,
551                     file_path_name('fa', 'fsl', 'fba', 'fba_ord') => 1,
552                     file_path_name('fa', 'fab') => 1,
553                     file_path_name('fa', 'fab', 'fab_ord') => 1,
554                     file_path_name('fa', 'fab', 'faba') => 1,
555                     file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
556                     file_path_name('fa', 'faa') => 1,
557                     file_path_name('fa', 'faa', 'faa_ord') => 1);
558
559     %Expect_Name = ();
560     %Expect_Dir = ();
561
562     File::Find::finddepth( {wanted => \&wanted_File, follow_fast => 1,
563                             no_chdir => 1}, topdir('fa') );
564
565     Check( scalar(keys %Expect_File) == 0 );     
566
567  
568     print "# check dangling symbolic links\n";
569     MkDir( dir_path('dangling_dir'), 0770 );
570     CheckDie( symlink( dir_path('dangling_dir'),
571                        file_path('dangling_dir_sl') ) );
572     rmdir dir_path('dangling_dir');
573     touch(file_path('dangling_file'));  
574     if ($^O eq 'MacOS') {
575         CheckDie( symlink('dangling_file', ':fa:dangling_file_sl') );
576     } else {
577         CheckDie( symlink('../dangling_file','fa/dangling_file_sl') );
578     }      
579     unlink file_path('dangling_file');
580
581     { 
582         # these tests should also emit a warning
583         use warnings;
584
585         %Expect_File = (File::Spec->curdir => 1,
586                         file_path('fa_ord') => 1,
587                         file_path('fsl') => 1,
588                         file_path('fb_ord') => 1,
589                         file_path('fba') => 1,
590                         file_path('fba_ord') => 1,
591                         file_path('fab') => 1,
592                         file_path('fab_ord') => 1,
593                         file_path('faba') => 1,
594                         file_path('faba_ord') => 1,
595                         file_path('faa') => 1,
596                         file_path('faa_ord') => 1);
597
598         %Expect_Name = ();
599         %Expect_Dir = ();
600         undef $warn_msg;
601
602         File::Find::find( {wanted => \&wanted_File, follow => 1,
603                            dangling_symlinks =>
604                                sub { $warn_msg = "$_[0] is a dangling symbolic link" }
605                            },
606                            topdir('dangling_dir_sl'), topdir('fa') );
607
608         Check( scalar(keys %Expect_File) == 0 );
609         Check( $warn_msg =~ m|dangling_dir_sl is a dangling symbolic link| );  
610         unlink file_path('fa', 'dangling_file_sl'),
611                          file_path('dangling_dir_sl');
612
613     }
614
615
616     print "# check recursion\n";
617     if ($^O eq 'MacOS') {
618         CheckDie( symlink(':fa:faa',':fa:faa:faa_sl') );
619     } else {
620         CheckDie( symlink('../faa','fa/faa/faa_sl') );
621     }
622     undef $@;
623     eval {File::Find::find( {wanted => \&simple_wanted, follow => 1,
624                              no_chdir => 1}, topdir('fa') ); };
625     Check( $@ =~ m|for_find[:/]fa[:/]faa[:/]faa_sl is a recursive symbolic link| );  
626     unlink file_path('fa', 'faa', 'faa_sl'); 
627
628
629     print "# check follow_skip (file)\n";
630     if ($^O eq 'MacOS') {
631         CheckDie( symlink(':fa:fa_ord',':fa:fa_ord_sl') ); # symlink to a file
632     } else {
633         CheckDie( symlink('./fa_ord','fa/fa_ord_sl') ); # symlink to a file
634     }
635     undef $@;
636
637     eval {File::Find::finddepth( {wanted => \&simple_wanted,
638                                   follow => 1,
639                                   follow_skip => 0, no_chdir => 1},
640                                   topdir('fa') );};
641
642     Check( $@ =~ m|for_find[:/]fa[:/]fa_ord encountered a second time| );
643
644
645     # no_chdir is in effect, hence we use file_path_name to specify
646     # the expected paths for %Expect_File
647
648     %Expect_File = (file_path_name('fa') => 1,
649                     file_path_name('fa', 'fa_ord') => 1,
650                     file_path_name('fa', 'fsl') => 1,
651                     file_path_name('fa', 'fsl', 'fb_ord') => 1,
652                     file_path_name('fa', 'fsl', 'fba') => 1,
653                     file_path_name('fa', 'fsl', 'fba', 'fba_ord') => 1,
654                     file_path_name('fa', 'fab') => 1,
655                     file_path_name('fa', 'fab', 'fab_ord') => 1,
656                     file_path_name('fa', 'fab', 'faba') => 1,
657                     file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
658                     file_path_name('fa', 'faa') => 1,
659                     file_path_name('fa', 'faa', 'faa_ord') => 1);
660
661     %Expect_Name = ();
662
663     %Expect_Dir = (dir_path('fa') => 1,
664                    dir_path('fa', 'faa') => 1,
665                    dir_path('fa', 'fab') => 1,
666                    dir_path('fa', 'fab', 'faba') => 1,
667                    dir_path('fb') => 1,
668                    dir_path('fb','fba') => 1);
669
670     File::Find::finddepth( {wanted => \&wanted_File_Dir, follow => 1,
671                            follow_skip => 1, no_chdir => 1},
672                            topdir('fa') );
673
674     Check( scalar(keys %Expect_File) == 0 );
675     unlink file_path('fa', 'fa_ord_sl');
676
677
678     print "# check follow_skip (directory)\n";
679     if ($^O eq 'MacOS') {
680         CheckDie( symlink(':fa:faa',':fa:faa_sl') ); # symlink to a directory
681     } else {
682         CheckDie( symlink('./faa','fa/faa_sl') ); # symlink to a directory
683     }
684     undef $@;
685
686     eval {File::Find::find( {wanted => \&simple_wanted, follow => 1,
687                             follow_skip => 0, no_chdir => 1},
688                             topdir('fa') );};
689
690     Check( $@ =~ m|for_find[:/]fa[:/]faa[:/]? encountered a second time| );
691
692   
693     undef $@;
694
695     eval {File::Find::find( {wanted => \&simple_wanted, follow => 1,
696                             follow_skip => 1, no_chdir => 1},
697                             topdir('fa') );};
698
699     Check( $@ =~ m|for_find[:/]fa[:/]faa[:/]? encountered a second time| );  
700
701     # no_chdir is in effect, hence we use file_path_name to specify
702     # the expected paths for %Expect_File
703
704     %Expect_File = (file_path_name('fa') => 1,
705                     file_path_name('fa', 'fa_ord') => 1,
706                     file_path_name('fa', 'fsl') => 1,
707                     file_path_name('fa', 'fsl', 'fb_ord') => 1,
708                     file_path_name('fa', 'fsl', 'fba') => 1,
709                     file_path_name('fa', 'fsl', 'fba', 'fba_ord') => 1,
710                     file_path_name('fa', 'fab') => 1,
711                     file_path_name('fa', 'fab', 'fab_ord') => 1,
712                     file_path_name('fa', 'fab', 'faba') => 1,
713                     file_path_name('fa', 'fab', 'faba', 'faba_ord') => 1,
714                     file_path_name('fa', 'faa') => 1,
715                     file_path_name('fa', 'faa', 'faa_ord') => 1);
716
717     %Expect_Name = ();
718
719     %Expect_Dir = (dir_path('fa') => 1,
720                    dir_path('fa', 'faa') => 1,
721                    dir_path('fa', 'fab') => 1,
722                    dir_path('fa', 'fab', 'faba') => 1,
723                    dir_path('fb') => 1,
724                    dir_path('fb', 'fba') => 1);
725
726     File::Find::find( {wanted => \&wanted_File_Dir, follow => 1,
727                        follow_skip => 2, no_chdir => 1}, topdir('fa') );
728
729     Check( scalar(keys %Expect_File) == 0 );
730     unlink file_path('fa', 'faa_sl');
731
732
733