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