xref: /openbsd-src/gnu/usr.bin/perl/ext/File-Glob/t/basic.t (revision 5486feefcc8cb79b19e014ab332cc5dfd05b3b33)
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