143003dfeSmillert#!./perl 243003dfeSmillert 343003dfeSmillertBEGIN { 443003dfeSmillert chdir 't' if -d 't'; 5898184e3Ssthen @INC = '../lib'; 643003dfeSmillert require Config; import Config; 743003dfeSmillert if ($Config{'extensions'} !~ /\bFile\/Glob\b/i) { 843003dfeSmillert print "1..0\n"; 943003dfeSmillert exit 0; 1043003dfeSmillert } 1143003dfeSmillert} 1243003dfeSmillertuse strict; 13*5486feefSafresh1use Test::More tests => 56; 1443003dfeSmillertBEGIN {use_ok('File::Glob', ':glob')}; 1543003dfeSmillertuse Cwd (); 1643003dfeSmillert 1743003dfeSmillertmy $vms_unix_rpt = 0; 1843003dfeSmillertmy $vms_efs = 0; 1943003dfeSmillertmy $vms_mode = 0; 2043003dfeSmillertif ($^O eq 'VMS') { 2143003dfeSmillert if (eval 'require VMS::Feature') { 2243003dfeSmillert $vms_unix_rpt = VMS::Feature::current("filename_unix_report"); 2343003dfeSmillert $vms_efs = VMS::Feature::current("efs_charset"); 2443003dfeSmillert } else { 2543003dfeSmillert my $unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || ''; 2643003dfeSmillert my $efs_charset = $ENV{'DECC$EFS_CHARSET'} || ''; 2743003dfeSmillert $vms_unix_rpt = $unix_rpt =~ /^[ET1]/i; 2843003dfeSmillert $vms_efs = $efs_charset =~ /^[ET1]/i; 2943003dfeSmillert } 3043003dfeSmillert $vms_mode = 1 unless ($vms_unix_rpt); 3143003dfeSmillert} 3243003dfeSmillert 3343003dfeSmillert 3443003dfeSmillert# look for the contents of the current directory 356fb12b70Safresh1# try it in a directory that doesn't get modified during testing, 366fb12b70Safresh1# so parallel testing won't give us race conditions. t/base/ seems 376fb12b70Safresh1# fairly static 386fb12b70Safresh1 396fb12b70Safresh1chdir 'base' or die "chdir base: $!"; 4043003dfeSmillert$ENV{PATH} = "/bin"; 4143003dfeSmillertdelete @ENV{qw(BASH_ENV CDPATH ENV IFS)}; 4243003dfeSmillertmy @correct = (); 43898184e3Ssthenif (opendir(D, ".")) { 4443003dfeSmillert @correct = grep { !/^\./ } sort readdir(D); 4543003dfeSmillert closedir D; 4643003dfeSmillert} 47de8cc8edSafresh1 48de8cc8edSafresh1is( 49de8cc8edSafresh1 File::Glob->can('glob'), 50de8cc8edSafresh1 undef, 51de8cc8edSafresh1 'Did not find glob() function in File::Glob', 52de8cc8edSafresh1); 53de8cc8edSafresh1 546fb12b70Safresh1chdir '..' or die "chdir .. $!"; 5543003dfeSmillert 5643003dfeSmillert# look up the user's home directory 5743003dfeSmillert# should return a list with one item, and not set ERROR 58f3efcd01Safresh1my @a; 59f3efcd01Safresh1 6043003dfeSmillertSKIP: { 6143003dfeSmillert my ($name, $home); 62*5486feefSafresh1 skip $^O, 2 if $^O eq 'MSWin32' || $^O eq 'VMS' 6391f110e0Safresh1 || $^O eq 'os2'; 64*5486feefSafresh1 skip "Can't find user for $>: $@", 2 unless eval { 6543003dfeSmillert ($name, $home) = (getpwuid($>))[0,7]; 6643003dfeSmillert 1; 6743003dfeSmillert }; 68*5486feefSafresh1 skip "$> has no home directory", 2 6943003dfeSmillert unless defined $home && defined $name && -d $home; 7043003dfeSmillert 7143003dfeSmillert @a = bsd_glob("~$name", GLOB_TILDE); 7243003dfeSmillert 7343003dfeSmillert if (GLOB_ERROR) { 7443003dfeSmillert fail(GLOB_ERROR); 7543003dfeSmillert } else { 76f3efcd01Safresh1 is_deeply (\@a, [$home], 77f3efcd01Safresh1 "GLOB_TILDE expands patterns that start with '~' to user name home directories" 78f3efcd01Safresh1 ); 7943003dfeSmillert } 80*5486feefSafresh1 81*5486feefSafresh1 my @b = bsd_glob("~$name", GLOB_TILDE | GLOB_MARK); 82*5486feefSafresh1 83*5486feefSafresh1 if (GLOB_ERROR) { 84*5486feefSafresh1 fail(GLOB_ERROR); 85*5486feefSafresh1 } else { 86*5486feefSafresh1 is_deeply (\@b, ["$home/"], 87*5486feefSafresh1 "GLOB_MARK matches directories with path separator attached" 88*5486feefSafresh1 ); 89*5486feefSafresh1 } 9043003dfeSmillert} 91898184e3Ssthen# check plain tilde expansion 92898184e3Ssthen{ 93898184e3Ssthen my $tilde_check = sub { 94898184e3Ssthen my @a = bsd_glob('~'); 95898184e3Ssthen 96898184e3Ssthen if (GLOB_ERROR) { 97898184e3Ssthen fail(GLOB_ERROR); 98898184e3Ssthen } else { 99898184e3Ssthen is_deeply (\@a, [$_[0]], join ' - ', 'tilde expansion', @_ > 1 ? $_[1] : ()); 100898184e3Ssthen } 101898184e3Ssthen }; 102898184e3Ssthen my $passwd_home = eval { (getpwuid($>))[7] }; 103898184e3Ssthen 104898184e3Ssthen TODO: { 105898184e3Ssthen local $TODO = 'directory brackets look like pattern brackets to glob' if $^O eq 'VMS'; 106898184e3Ssthen local $ENV{HOME}; 107898184e3Ssthen delete $ENV{HOME}; 108898184e3Ssthen local $ENV{USERPROFILE}; 109898184e3Ssthen delete $ENV{USERPROFILE}; 110898184e3Ssthen $tilde_check->(defined $passwd_home ? $passwd_home : q{~}, 'no environment'); 111898184e3Ssthen } 112898184e3Ssthen 113898184e3Ssthen SKIP: { 114898184e3Ssthen skip 'MSWin32 only', 1 if $^O ne 'MSWin32'; 115898184e3Ssthen local $ENV{HOME}; 116898184e3Ssthen delete $ENV{HOME}; 117898184e3Ssthen local $ENV{USERPROFILE}; 118898184e3Ssthen $ENV{USERPROFILE} = 'sweet win32 home'; 119898184e3Ssthen $tilde_check->(defined $passwd_home ? $passwd_home : $ENV{USERPROFILE}, 'USERPROFILE'); 120898184e3Ssthen } 121898184e3Ssthen 122898184e3Ssthen TODO: { 123898184e3Ssthen local $TODO = 'directory brackets look like pattern brackets to glob' if $^O eq 'VMS'; 124898184e3Ssthen my $home = exists $ENV{HOME} ? $ENV{HOME} 125898184e3Ssthen : eval { getpwuid($>); 1 } ? (getpwuid($>))[7] 126898184e3Ssthen : $^O eq 'MSWin32' && exists $ENV{USERPROFILE} ? $ENV{USERPROFILE} 127898184e3Ssthen : q{~}; 128898184e3Ssthen $tilde_check->($home); 129898184e3Ssthen } 130898184e3Ssthen} 13143003dfeSmillert 13243003dfeSmillert# check backslashing 13343003dfeSmillert# should return a list with one item, and not set ERROR 13443003dfeSmillert@a = bsd_glob('TEST', GLOB_QUOTE); 13543003dfeSmillertif (GLOB_ERROR) { 13643003dfeSmillert fail(GLOB_ERROR); 13743003dfeSmillert} else { 138f3efcd01Safresh1 is_deeply(\@a, ['TEST'], "GLOB_QUOTE works as expected"); 13943003dfeSmillert} 14043003dfeSmillert 14143003dfeSmillert# check nonexistent checks 14243003dfeSmillert# should return an empty list 14343003dfeSmillert# XXX since errfunc is NULL on win32, this test is not valid there 14443003dfeSmillertSKIP: { 145*5486feefSafresh1 skip $^O, 5 if $^O eq 'MSWin32'; 146*5486feefSafresh1 my @a = bsd_glob("asdfasdf", 0); 147f3efcd01Safresh1 is_deeply(\@a, [], "bsd_glob() works as expected for unmatched pattern and 0 flag"); 148*5486feefSafresh1 149*5486feefSafresh1 my $pattern = "asdfasdf"; 150*5486feefSafresh1 @a = bsd_glob($pattern, GLOB_NOCHECK); 151*5486feefSafresh1 is(scalar @a, 1, 152*5486feefSafresh1 "unmatched pattern with GLOB_NOCHECK returned single-item list"); 153*5486feefSafresh1 cmp_ok($a[0], 'eq', $pattern, 154*5486feefSafresh1 "bsd_glob() works as expected for unmatched pattern and GLOB_NOCHECK flag"); 155*5486feefSafresh1 156*5486feefSafresh1 my @b = bsd_glob($pattern, GLOB_NOCHECK | GLOB_QUOTE); 157*5486feefSafresh1 is(scalar @b, 1, 158*5486feefSafresh1 "unmatched pattern with GLOB_NOCHECK and GLOB_QUOTE returned single-item list"); 159*5486feefSafresh1 cmp_ok($b[0], 'eq', $pattern, 160*5486feefSafresh1 "bsd_glob() works as expected for unmatched pattern and GLOB_NOCHECK and GLOB_QUOTE flags"); 16143003dfeSmillert} 16243003dfeSmillert 16343003dfeSmillert# check bad protections 16443003dfeSmillert# should return an empty list, and set ERROR 16543003dfeSmillertSKIP: { 166256a93a4Safresh1 skip $^O, 2 if $^O eq 'MSWin32' 16743003dfeSmillert or $^O eq 'os2' or $^O eq 'VMS' or $^O eq 'cygwin'; 16843003dfeSmillert skip "AFS", 2 if Cwd::cwd() =~ m#^$Config{'afsroot'}#s; 16943003dfeSmillert skip "running as root", 2 if not $>; 17043003dfeSmillert 17143003dfeSmillert my $dir = "pteerslo"; 17243003dfeSmillert mkdir $dir, 0; 17343003dfeSmillert @a = bsd_glob("$dir/*", GLOB_ERR); 17443003dfeSmillert rmdir $dir; 17543003dfeSmillert local $TODO = 'hit VOS bug posix-956' if $^O eq 'vos'; 17643003dfeSmillert 177f3efcd01Safresh1 isnt(GLOB_ERROR, 0, "GLOB_ERROR is not 0"); 178f3efcd01Safresh1 is_deeply(\@a, [], "Got empty list as expected"); 17943003dfeSmillert} 18043003dfeSmillert 18143003dfeSmillert# check for csh style globbing 18243003dfeSmillert@a = bsd_glob('{a,b}', GLOB_BRACE | GLOB_NOMAGIC); 183f3efcd01Safresh1is_deeply(\@a, ['a', 'b'], "Check for csh-style globbing"); 18443003dfeSmillert 18543003dfeSmillert@a = bsd_glob( 18643003dfeSmillert '{TES*,doesntexist*,a,b}', 18743003dfeSmillert GLOB_BRACE | GLOB_NOMAGIC | ($^O eq 'VMS' ? GLOB_NOCASE : 0) 18843003dfeSmillert); 18943003dfeSmillert 19043003dfeSmillert# Working on t/TEST often causes this test to fail because it sees Emacs temp 19143003dfeSmillert# and RCS files. Filter them out, and .pm files too, and patch temp files. 19243003dfeSmillert@a = grep !/(,v$|~$|\.(pm|ori?g|rej)$)/, @a; 19343003dfeSmillert@a = (grep !/test.pl/, @a) if $^O eq 'VMS'; 19443003dfeSmillert 19591f110e0Safresh1map { $_ =~ s/test\.?/TEST/i } @a if $^O eq 'VMS'; 19643003dfeSmillertprint "# @a\n"; 19743003dfeSmillert 198f3efcd01Safresh1is_deeply(\@a, ['TEST', 'a', 'b'], "Got list of 3 elements, including 'TEST'"); 19943003dfeSmillert 20043003dfeSmillert# "~" should expand to $ENV{HOME} 201898184e3Ssthen{ 202898184e3Ssthen local $ENV{HOME} = "sweet home"; 20343003dfeSmillert @a = bsd_glob('~', GLOB_TILDE | GLOB_NOMAGIC); 204f3efcd01Safresh1 is_deeply(\@a, [$ENV{HOME}], "~ expands to envvar \$HOME"); 20543003dfeSmillert} 20643003dfeSmillert 20743003dfeSmillert# GLOB_ALPHASORT (default) should sort alphabetically regardless of case 208256a93a4Safresh1mkdir "pteerslo", 0777 or die "mkdir 'pteerslo', 0777: $!"; 209256a93a4Safresh1chdir "pteerslo" or die "chdir 'pteerslo' $!"; 21043003dfeSmillert 21143003dfeSmillertmy @f_names = qw(Ax.pl Bx.pl Cx.pl aY.pl bY.pl cY.pl); 21243003dfeSmillertmy @f_alpha = qw(Ax.pl aY.pl Bx.pl bY.pl Cx.pl cY.pl); 21343003dfeSmillertif ('a' lt 'A') { # EBCDIC char sets sort lower case before UPPER 21443003dfeSmillert @f_names = sort(@f_names); 21543003dfeSmillert} 21643003dfeSmillertif ($^O eq 'VMS') { # VMS is happily caseignorant 21743003dfeSmillert @f_alpha = qw(ax.pl ay.pl bx.pl by.pl cx.pl cy.pl); 21843003dfeSmillert @f_names = @f_alpha; 21943003dfeSmillert} 22043003dfeSmillert 22143003dfeSmillertfor (@f_names) { 222256a93a4Safresh1 open T, '>', $_ or die "Couldn't write to '$_': $!"; 223256a93a4Safresh1 close T or die "Couldn't close '$_': $!"; 22443003dfeSmillert} 22543003dfeSmillert 22643003dfeSmillertmy $pat = "*.pl"; 22743003dfeSmillert 22843003dfeSmillertmy @g_names = bsd_glob($pat, 0); 22943003dfeSmillertprint "# f_names = @f_names\n"; 23043003dfeSmillertprint "# g_names = @g_names\n"; 231f3efcd01Safresh1is_deeply(\@g_names, \@f_names, "Got expected case-sensitive list of filenames"); 23243003dfeSmillert 23343003dfeSmillertmy @g_alpha = bsd_glob($pat); 23443003dfeSmillertprint "# f_alpha = @f_alpha\n"; 23543003dfeSmillertprint "# g_alpha = @g_alpha\n"; 236f3efcd01Safresh1is_deeply(\@g_alpha, \@f_alpha, "Got expected case-insensitive list of filenames"); 23743003dfeSmillert 238*5486feefSafresh1my @h_alpha = bsd_glob($pat, GLOB_ALPHASORT); 239*5486feefSafresh1print "# f_alpha = @f_alpha\n"; 240*5486feefSafresh1print "# h_alpha = @h_alpha\n"; 241*5486feefSafresh1is_deeply(\@h_alpha, \@f_alpha, 242*5486feefSafresh1 "Got expected case-insensitive list of filenames (explicit GLOB_ALPHASORT)"); 243*5486feefSafresh1 244*5486feefSafresh1my (%h_seen, %i_seen); 245*5486feefSafresh1map { $h_seen{$_} => 1 } @h_alpha; 246*5486feefSafresh1map { $i_seen{$_} => 1 } bsd_glob($pat, GLOB_NOSORT); 247*5486feefSafresh1is_deeply(\%h_seen, \%i_seen, 248*5486feefSafresh1 "GLOB_NOSORT saw same names as default (though probably not in same order)"); 249*5486feefSafresh1 25043003dfeSmillertunlink @f_names; 25143003dfeSmillertchdir ".."; 25243003dfeSmillertrmdir "pteerslo"; 25343003dfeSmillert 25443003dfeSmillert# this can panic if PL_glob_index gets passed as flags to bsd_glob 25543003dfeSmillert<*>; <*>; 25643003dfeSmillertpass("Don't panic"); 25743003dfeSmillert 25843003dfeSmillert{ 25943003dfeSmillert use File::Temp qw(tempdir); 26043003dfeSmillert use File::Spec qw(); 26143003dfeSmillert 26243003dfeSmillert my($dir) = tempdir(CLEANUP => 1) 26343003dfeSmillert or die "Could not create temporary directory"; 26443003dfeSmillert for my $file (qw(a_dej a_ghj a_qej)) { 26543003dfeSmillert open my $fh, ">", File::Spec->catfile($dir, $file) 26643003dfeSmillert or die "Could not create file $dir/$file: $!"; 26743003dfeSmillert close $fh; 26843003dfeSmillert } 26943003dfeSmillert my $cwd = Cwd::cwd(); 27043003dfeSmillert chdir $dir 27143003dfeSmillert or die "Could not chdir to $dir: $!"; 27243003dfeSmillert my(@glob_files) = glob("a*{d[e]}j"); 27343003dfeSmillert chdir $cwd 27443003dfeSmillert or die "Could not chdir back to $cwd: $!"; 27543003dfeSmillert local $TODO = "home-made glob doesn't do regexes" if $^O eq 'VMS'; 276f3efcd01Safresh1 is_deeply(\@glob_files, ['a_dej'], 277f3efcd01Safresh1 "Got expected list: metacharacters and character class in pattern"); 27843003dfeSmillert} 279898184e3Ssthen 280898184e3Ssthen# This used to segfault. 281898184e3Ssthenmy $i = bsd_glob('*', GLOB_ALTDIRFUNC); 282898184e3Ssthenis(&File::Glob::GLOB_ERROR, 0, "Successfuly ignored unsupported flag"); 283898184e3Ssthen 284898184e3Ssthenpackage frimpy; # get away from the glob override, so we can test csh_glob, 285898184e3Ssthenuse Test::More; # which is perl's default 286898184e3Ssthen 287898184e3Ssthen# In case of PERL_EXTERNAL_GLOB: 288898184e3Ssthenuse subs 'glob'; 289898184e3SsthenBEGIN { *glob = \&File::Glob::csh_glob } 290898184e3Ssthen 291898184e3Ssthenis +(glob "a'b'")[0], (<a'b' c>)[0], "a'b' with and without spaces"; 292898184e3Ssthenis <a"b">, 'ab', 'a"b" without spaces'; 293898184e3Ssthenis_deeply [<a"b" c>], [qw<ab c>], 'a"b" without spaces'; 294898184e3Ssthenis_deeply [<\\* .\\*>], [<\\*>,<.\\*>], 'backslashes with(out) spaces'; 295898184e3Ssthenlike <\\ >, qr/^\\? \z/, 'final escaped space'; 296898184e3Ssthenis <a"b>, 'a"b', 'unmatched quote'; 297898184e3Ssthenis < a"b >, 'a"b', 'unmatched quote with surrounding spaces'; 298898184e3Ssthenis glob('a\"b'), 'a"b', '\ before quote *only* escapes quote'; 299898184e3Ssthenis glob(q"a\'b"), "a'b", '\ before single quote *only* escapes quote'; 300898184e3Ssthenis glob('"a\"b c\"d"'), 'a"b c"d', 'before \" within "..."'; 301898184e3Ssthenis glob(q"'a\'b c\'d'"), "a'b c'd", q"before \' within '...'"; 302898184e3Ssthen 303898184e3Ssthen 304898184e3Ssthenpackage bsdglob; # for testing the :bsd_glob export tag 305898184e3Ssthen 306898184e3Ssthenuse File::Glob ':bsd_glob'; 307898184e3Ssthenuse Test::More; 308898184e3Ssthenfor (qw[ 309898184e3Ssthen GLOB_ABEND 310898184e3Ssthen GLOB_ALPHASORT 311898184e3Ssthen GLOB_ALTDIRFUNC 312898184e3Ssthen GLOB_BRACE 313898184e3Ssthen GLOB_CSH 314898184e3Ssthen GLOB_ERR 315898184e3Ssthen GLOB_ERROR 316898184e3Ssthen GLOB_LIMIT 317898184e3Ssthen GLOB_MARK 318898184e3Ssthen GLOB_NOCASE 319898184e3Ssthen GLOB_NOCHECK 320898184e3Ssthen GLOB_NOMAGIC 321898184e3Ssthen GLOB_NOSORT 322898184e3Ssthen GLOB_NOSPACE 323898184e3Ssthen GLOB_QUOTE 324898184e3Ssthen GLOB_TILDE 325898184e3Ssthen bsd_glob 326898184e3Ssthen ]) { 327898184e3Ssthen ok (exists &$_, qq':bsd_glob exports $_'); 328898184e3Ssthen} 329898184e3Ssthenis <a b>, 'a b', '<a b> under :bsd_glob'; 330898184e3Ssthenis <"a" "b">, '"a" "b"', '<"a" "b"> under :bsd_glob'; 331898184e3Ssthenis_deeply [<a b>], [q<a b>], '<> in list context under :bsd_glob'; 332