1#!./perl
2
3#
4# test glob() in File::DosGlob
5#
6
7# Make sure it can load before other XS extensions
8use File::DosGlob;
9
10use FindBin;
11use File::Spec::Functions;
12BEGIN {
13    chdir catdir $FindBin::Bin, (updir)x3, 't';
14    @INC = '../lib';
15}
16
17use Test::More tests => 21;
18
19# override it in main::
20use File::DosGlob 'glob';
21
22require Cwd;
23
24my $expected;
25$expected = $_ = "op/a*.t";
26my @r = glob;
27is ($_, $expected, 'test if $_ takes as the default');
28cmp_ok(@r, '>=', 9) or diag("|@r|");
29
30@r = <*/a*.t>;
31# at least {argv,abbrev,anydbm,autoloader,append,arith,array,assignwarn,auto}.t
32cmp_ok(@r, '>=', 9, 'check <*/*>') or diag("|@r|");
33my $r = scalar @r;
34
35@r = ();
36while (defined($_ = <*/a*.t>)) {
37    print "# $_\n";
38    push @r, $_;
39}
40is(scalar @r, $r, 'check scalar context');
41
42@r = ();
43for (<*/a*.t>) {
44    print "# $_\n";
45    push @r, $_;
46}
47is(scalar @r, $r, 'check list context');
48
49@r = ();
50while (<*/a*.t>) {
51    print "# $_\n";
52    push @r, $_;
53}
54is(scalar @r, $r, 'implicit assign to $_ in while()');
55
56my @s = ();
57my $pat = '*/a*.t';
58while (glob ($pat)) {
59    print "# $_\n";
60    push @s, $_;
61}
62is("@r", "@s", 'explicit glob() gets assign magic too');
63
64package Foo;
65use File::DosGlob 'glob';
66use Test::More;
67@s = ();
68$pat = '*/a*.t';
69while (glob($pat)) {
70    print "# $_\n";
71    push @s, $_;
72}
73is("@r", "@s", 'in a different package');
74
75@s = ();
76while (<*/a*.t>) {
77    my $i = 0;
78    print "# $_ <";
79    push @s, $_;
80    while (<*/b*.t>) {
81	print " $_";
82	$i++;
83    }
84    print " >\n";
85}
86is("@r", "@s", 'different glob ops maintain independent contexts');
87
88@s = ();
89eval <<'EOT';
90use File::DosGlob 'GLOBAL_glob';
91package Bar;
92while (<*/a*.t>) {
93    my $i = 0;
94    print "# $_ <";
95    push @s, $_;
96    while (glob '*/b*.t') {
97	print " $_";
98	$i++;
99    }
100    print " >\n";
101}
102EOT
103is("@r", "@s", 'global override');
104
105# Test that a glob pattern containing ()'s works.
106# NB. The spaces in the glob patterns need to be backslash escaped.
107my $filename_containing_parens = "foo (123) bar";
108SKIP: {
109    skip("can't create '$filename_containing_parens': $!", 9)
110	unless open my $touch, ">", $filename_containing_parens;
111    close $touch;
112
113    foreach my $pattern ("foo\\ (*", "*)\\ bar", "foo\\ (1*3)\\ bar") {
114	@r = ();
115	eval { @r = File::DosGlob::glob($pattern) };
116	is($@, "", "eval for glob($pattern)");
117	is(scalar @r, 1);
118	is($r[0], $filename_containing_parens);
119    }
120
121    1 while unlink $filename_containing_parens;
122}
123
124# Test the globbing of a drive relative pattern such as "c:*.pl".
125# NB. previous versions of DosGlob inserted "./ after the drive letter to
126# make the expansion process work correctly. However, while it is harmless,
127# there is no reason for it to be in the result.
128my $cwd = Cwd::cwd();
129if ($cwd =~ /^([a-zA-Z]:)/) {
130    my $drive = $1;
131    @r = ();
132    # This assumes we're in the "t" directory.
133    eval { @r = File::DosGlob::glob("${drive}io/*.t") };
134    ok(@r and !grep !m|^${drive}io/[^/]*\.t$|, @r);
135} else {
136    pass();
137}
138
139# Test that our internal data are freed when the caller���s op tree is freed,
140# even if iteration has not finished.
141# Using XS::APItest is the only simple way to test this.  Since this is a
142# core-only module, this should be OK.
143SKIP: {
144    require Config;
145    skip "no XS::APItest"
146     unless eval { require XS::APItest; import XS::APItest "sv_count"; 1 };
147    # Use a random number of ops, so that the glob op does not reuse the
148    # same address each time, giving us false passes.
149    my($count,$count2);
150    eval '$x+'x(1+rand() * 100) . '<*>';
151    $count = sv_count();
152    eval '$x+'x(1+rand() * 100) . '<*>';
153    $count2 = sv_count();
154    cmp_ok $count2, '<=', $count,
155     'no leak when partly iterated caller is freed';
156}
157