Commit | Line | Data |
---|---|---|
99f36a73 | 1 | #!./perl -w |
ed4a5f99 | 2 | |
2adbc9b6 NC |
3 | use strict; |
4 | ||
78321866 | 5 | use Cwd; |
2adbc9b6 | 6 | |
99f36a73 | 7 | chdir 't'; |
ed4a5f99 | 8 | |
99f36a73 | 9 | use Config; |
e69a2255 | 10 | use File::Spec; |
1279e177 | 11 | use File::Path; |
ed4a5f99 | 12 | |
99f36a73 | 13 | use lib File::Spec->catdir('t', 'lib'); |
275e8705 | 14 | use Test::More; |
53e80d0b JM |
15 | |
16 | my $IsVMS = $^O eq 'VMS'; | |
17 | my $IsMacOS = $^O eq 'MacOS'; | |
18 | ||
19 | my $vms_unix_rpt = 0; | |
20 | my $vms_efs = 0; | |
21 | my $vms_mode = 0; | |
22 | ||
23 | if ($IsVMS) { | |
24 | require VMS::Filespec; | |
25 | use Carp; | |
26 | use Carp::Heavy; | |
27 | $vms_mode = 1; | |
28 | if (eval 'require VMS::Feature') { | |
29 | $vms_unix_rpt = VMS::Feature::current("filename_unix_report"); | |
30 | $vms_efs = VMS::Feature::current("efs_charset"); | |
31 | } else { | |
32 | my $unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || ''; | |
33 | my $efs_charset = $ENV{'DECC$EFS_CHARSET'} || ''; | |
34 | $vms_unix_rpt = $unix_rpt =~ /^[ET1]/i; | |
35 | $vms_efs = $efs_charset =~ /^[ET1]/i; | |
36 | } | |
37 | $vms_mode = 0 if ($vms_unix_rpt); | |
38 | } | |
275e8705 | 39 | |
23bb49fa | 40 | my $tests = 30; |
14815b0c RGS |
41 | # _perl_abs_path() currently only works when the directory separator |
42 | # is '/', so don't test it when it won't work. | |
99f36a73 RGS |
43 | my $EXTRA_ABSPATH_TESTS = ($Config{prefix} =~ m/\//) && $^O ne 'cygwin'; |
44 | $tests += 4 if $EXTRA_ABSPATH_TESTS; | |
275e8705 | 45 | plan tests => $tests; |
ca7ced35 | 46 | |
99f36a73 | 47 | SKIP: { |
b04f6d36 RGS |
48 | skip "no need to check for blib/ in the core", 1 if $ENV{PERL_CORE}; |
49 | like $INC{'Cwd.pm'}, qr{blib}i, "Cwd should be loaded from blib/ during testing"; | |
99f36a73 RGS |
50 | } |
51 | ||
ed4a5f99 BS |
52 | |
53 | # check imports | |
ca7ced35 MS |
54 | can_ok('main', qw(cwd getcwd fastcwd fastgetcwd)); |
55 | ok( !defined(&chdir), 'chdir() not exported by default' ); | |
56 | ok( !defined(&abs_path), ' nor abs_path()' ); | |
57 | ok( !defined(&fast_abs_path), ' nor fast_abs_path()'); | |
58 | ||
f6342b4b RGS |
59 | { |
60 | my @fields = qw(PATH IFS CDPATH ENV BASH_ENV); | |
61 | my $before = grep exists $ENV{$_}, @fields; | |
62 | cwd(); | |
63 | my $after = grep exists $ENV{$_}, @fields; | |
64 | is($before, $after, "cwd() shouldn't create spurious entries in %ENV"); | |
65 | } | |
ed4a5f99 | 66 | |
0d2079fa BS |
67 | # XXX force Cwd to bootsrap its XSUBs since we have set @INC = "../lib" |
68 | # XXX and subsequent chdir()s can make them impossible to find | |
69 | eval { fastcwd }; | |
70 | ||
da3f15f4 JH |
71 | # Must find an external pwd (or equivalent) command. |
72 | ||
38f52085 | 73 | my $pwd = $^O eq 'MSWin32' ? "cmd" : "pwd"; |
da3f15f4 | 74 | my $pwd_cmd = |
38f52085 | 75 | ($^O eq "NetWare") ? |
023b4a43 | 76 | "cd" : |
e69a2255 JH |
77 | ($IsMacOS) ? |
78 | "pwd" : | |
38f52085 | 79 | (grep { -x && -f } map { "$_/$pwd$Config{exe_ext}" } |
023b4a43 | 80 | split m/$Config{path_sep}/, $ENV{PATH})[0]; |
da3f15f4 | 81 | |
ca7ced35 | 82 | $pwd_cmd = 'SHOW DEFAULT' if $IsVMS; |
38f52085 GS |
83 | if ($^O eq 'MSWin32') { |
84 | $pwd_cmd =~ s,/,\\,g; | |
85 | $pwd_cmd = "$pwd_cmd /c cd"; | |
86 | } | |
e8f7eed0 JH |
87 | $pwd_cmd =~ s=\\=/=g if ($^O eq 'dos'); |
88 | ||
ca7ced35 MS |
89 | SKIP: { |
90 | skip "No native pwd command found to test against", 4 unless $pwd_cmd; | |
2390ecbc | 91 | |
d80cbc32 JH |
92 | print "# native pwd = '$pwd_cmd'\n"; |
93 | ||
926cbafe JH |
94 | local @ENV{qw(PATH IFS CDPATH ENV BASH_ENV)}; |
95 | my ($pwd_cmd_untainted) = $pwd_cmd =~ /^(.+)$/; # Untaint. | |
96 | chomp(my $start = `$pwd_cmd_untainted`); | |
97 | ||
14107c42 | 98 | # Win32's cd returns native C:\ style |
2986a63f | 99 | $start =~ s,\\,/,g if ($^O eq 'MSWin32' || $^O eq "NetWare"); |
53e80d0b JM |
100 | if ($IsVMS) { |
101 | # DCL SHOW DEFAULT has leading spaces | |
102 | $start =~ s/^\s+//; | |
103 | ||
104 | # When in UNIX report mode, need to convert to compare it. | |
105 | if ($vms_unix_rpt) { | |
106 | $start = VMS::Filespec::unixpath($start); | |
107 | # Remove trailing slash. | |
108 | $start =~ s#/$##; | |
109 | } | |
110 | } | |
ca7ced35 | 111 | SKIP: { |
12b7537a JH |
112 | skip("'$pwd_cmd' failed, nothing to test against", 4) if $?; |
113 | skip("/afs seen, paths unlikely to match", 4) if $start =~ m|/afs/|; | |
ca7ced35 | 114 | |
164336fe JH |
115 | # Darwin's getcwd(3) (which Cwd.xs:bsd_realpath() uses which |
116 | # Cwd.pm:getcwd uses) has some magic related to the PWD | |
117 | # environment variable: if PWD is set to a directory that | |
118 | # looks about right (guess: has the same (dev,ino) as the '.'?), | |
119 | # the PWD is returned. However, if that path contains | |
120 | # symlinks, the path will not be equal to the one returned by | |
121 | # /bin/pwd (which probably uses the usual walking upwards in | |
122 | # the path -trick). This situation is easy to reproduce since | |
123 | # /tmp is a symlink to /private/tmp. Therefore we invalidate | |
124 | # the PWD to force getcwd(3) to (re)compute the cwd in full. | |
125 | # Admittedly fixing this in the Cwd module would be better | |
126 | # long-term solution but deleting $ENV{PWD} should not be | |
127 | # done light-heartedly. --jhi | |
128 | delete $ENV{PWD} if $^O eq 'darwin'; | |
129 | ||
da3f15f4 JH |
130 | my $cwd = cwd; |
131 | my $getcwd = getcwd; | |
132 | my $fastcwd = fastcwd; | |
133 | my $fastgetcwd = fastgetcwd; | |
12b7537a | 134 | |
1c26fec0 JH |
135 | is($cwd, $start, 'cwd()'); |
136 | is($getcwd, $start, 'getcwd()'); | |
137 | is($fastcwd, $start, 'fastcwd()'); | |
138 | is($fastgetcwd, $start, 'fastgetcwd()'); | |
da3f15f4 JH |
139 | } |
140 | } | |
141 | ||
ea067225 RGS |
142 | my @test_dirs = qw{_ptrslt_ _path_ _to_ _a_ _dir_}; |
143 | my $Test_Dir = File::Spec->catdir(@test_dirs); | |
ca7ced35 | 144 | |
889f7a4f RGS |
145 | mkpath([$Test_Dir], 0, 0777); |
146 | Cwd::chdir $Test_Dir; | |
ca7ced35 | 147 | |
ad78113d RGS |
148 | foreach my $func (qw(cwd getcwd fastcwd fastgetcwd)) { |
149 | my $result = eval "$func()"; | |
150 | is $@, ''; | |
ea067225 | 151 | dir_ends_with( $result, $Test_Dir, "$func()" ); |
ad78113d | 152 | } |
ed4a5f99 | 153 | |
23bb49fa SP |
154 | { |
155 | # Some versions of File::Path (e.g. that shipped with perl 5.8.5) | |
156 | # call getcwd() with an argument (perhaps by calling it as a | |
157 | # method?), so make sure that doesn't die. | |
158 | is getcwd(), getcwd('foo'), "Call getcwd() with an argument"; | |
159 | } | |
160 | ||
ed4a5f99 | 161 | # Cwd::chdir should also update $ENV{PWD} |
ea067225 | 162 | dir_ends_with( $ENV{PWD}, $Test_Dir, 'Cwd::chdir() updates $ENV{PWD}' ); |
e69a2255 | 163 | my $updir = File::Spec->updir; |
bf7c0a3d SP |
164 | |
165 | for (1..@test_dirs) { | |
166 | Cwd::chdir $updir; | |
167 | print "#$ENV{PWD}\n"; | |
168 | } | |
1279e177 | 169 | |
ea067225 | 170 | rmtree($test_dirs[0], 0, 0); |
1279e177 | 171 | |
889f7a4f | 172 | { |
53e80d0b JM |
173 | my $check = ($vms_mode ? qr|\b((?i)t)\]$| : |
174 | $IsMacOS ? qr|\bt:$| : | |
175 | qr|\bt$| ); | |
889f7a4f RGS |
176 | |
177 | like($ENV{PWD}, $check); | |
2390ecbc | 178 | } |
ed4a5f99 | 179 | |
99f36a73 RGS |
180 | { |
181 | # Make sure abs_path() doesn't trample $ENV{PWD} | |
182 | my $start_pwd = $ENV{PWD}; | |
183 | mkpath([$Test_Dir], 0, 0777); | |
184 | Cwd::abs_path($Test_Dir); | |
185 | is $ENV{PWD}, $start_pwd; | |
186 | rmtree($test_dirs[0], 0, 0); | |
187 | } | |
188 | ||
ca7ced35 | 189 | SKIP: { |
275e8705 | 190 | skip "no symlinks on this platform", 2+$EXTRA_ABSPATH_TESTS unless $Config{d_symlink}; |
ca7ced35 | 191 | |
fa89a9ae | 192 | my $file = "linktest"; |
ca7ced35 | 193 | mkpath([$Test_Dir], 0, 0777); |
fa89a9ae | 194 | symlink $Test_Dir, $file; |
7040f5d5 | 195 | |
fa89a9ae NC |
196 | my $abs_path = Cwd::abs_path($file); |
197 | my $fast_abs_path = Cwd::fast_abs_path($file); | |
53e80d0b JM |
198 | my $want = quotemeta( |
199 | File::Spec->rel2abs( $Test_Dir ) | |
200 | ); | |
201 | if ($^O eq 'VMS') { | |
202 | # Not easy to predict the physical volume name | |
203 | $want = $ENV{PERL_CORE} ? $Test_Dir : File::Spec->catdir('t', $Test_Dir); | |
204 | ||
205 | # So just use the relative volume name | |
206 | $want =~ s/^\[//; | |
207 | ||
208 | $want = quotemeta($want); | |
209 | } | |
7040f5d5 | 210 | |
61729915 CB |
211 | like($abs_path, qr|$want$|i); |
212 | like($fast_abs_path, qr|$want$|i); | |
fa89a9ae | 213 | like(Cwd::_perl_abs_path($file), qr|$want$|i) if $EXTRA_ABSPATH_TESTS; |
7040f5d5 | 214 | |
ea067225 | 215 | rmtree($test_dirs[0], 0, 0); |
fa89a9ae | 216 | 1 while unlink $file; |
ed4a5f99 | 217 | } |
ea067225 | 218 | |
78321866 RGS |
219 | # Make sure we can run abs_path() on files, not just directories |
220 | my $path = 'cwd.t'; | |
9d7d9729 CB |
221 | path_ends_with(Cwd::abs_path($path), 'cwd.t', 'abs_path() can be invoked on a file'); |
222 | path_ends_with(Cwd::fast_abs_path($path), 'cwd.t', 'fast_abs_path() can be invoked on a file'); | |
275e8705 RGS |
223 | path_ends_with(Cwd::_perl_abs_path($path), 'cwd.t', '_perl_abs_path() can be invoked on a file') |
224 | if $EXTRA_ABSPATH_TESTS; | |
78321866 RGS |
225 | |
226 | $path = File::Spec->catfile(File::Spec->updir, 't', $path); | |
9d7d9729 CB |
227 | path_ends_with(Cwd::abs_path($path), 'cwd.t', 'abs_path() can be invoked on a file'); |
228 | path_ends_with(Cwd::fast_abs_path($path), 'cwd.t', 'fast_abs_path() can be invoked on a file'); | |
275e8705 RGS |
229 | path_ends_with(Cwd::_perl_abs_path($path), 'cwd.t', '_perl_abs_path() can be invoked on a file') |
230 | if $EXTRA_ABSPATH_TESTS; | |
78321866 RGS |
231 | |
232 | ||
99f36a73 RGS |
233 | |
234 | SKIP: { | |
235 | my $file; | |
236 | { | |
f5f48b4d | 237 | my $root = Cwd::abs_path(File::Spec->rootdir); # Add drive letter? |
99f36a73 RGS |
238 | local *FH; |
239 | opendir FH, $root or skip("Can't opendir($root): $!", 2+$EXTRA_ABSPATH_TESTS); | |
240 | ($file) = grep {-f $_ and not -l $_} map File::Spec->catfile($root, $_), readdir FH; | |
241 | closedir FH; | |
242 | } | |
243 | skip "No plain file in root directory to test with", 2+$EXTRA_ABSPATH_TESTS unless $file; | |
244 | ||
245 | $file = VMS::Filespec::rmsexpand($file) if $^O eq 'VMS'; | |
246 | is Cwd::abs_path($file), $file, 'abs_path() works on files in the root directory'; | |
247 | is Cwd::fast_abs_path($file), $file, 'fast_abs_path() works on files in the root directory'; | |
248 | is Cwd::_perl_abs_path($file), $file, '_perl_abs_path() works on files in the root directory' | |
249 | if $EXTRA_ABSPATH_TESTS; | |
250 | } | |
251 | ||
252 | ||
ea067225 | 253 | ############################################# |
9d7d9729 CB |
254 | # These routines give us sort of a poor-man's cross-platform |
255 | # directory or path comparison capability. | |
ea067225 | 256 | |
9d7d9729 | 257 | sub bracketed_form_dir { |
ea067225 RGS |
258 | return join '', map "[$_]", |
259 | grep length, File::Spec->splitdir(File::Spec->canonpath( shift() )); | |
260 | } | |
261 | ||
262 | sub dir_ends_with { | |
263 | my ($dir, $expect) = (shift, shift); | |
9d7d9729 CB |
264 | my $bracketed_expect = quotemeta bracketed_form_dir($expect); |
265 | like( bracketed_form_dir($dir), qr|$bracketed_expect$|i, (@_ ? shift : ()) ); | |
266 | } | |
267 | ||
268 | sub bracketed_form_path { | |
269 | return join '', map "[$_]", | |
270 | grep length, File::Spec->splitpath(File::Spec->canonpath( shift() )); | |
271 | } | |
272 | ||
273 | sub path_ends_with { | |
274 | my ($dir, $expect) = (shift, shift); | |
275 | my $bracketed_expect = quotemeta bracketed_form_path($expect); | |
276 | like( bracketed_form_path($dir), qr|$bracketed_expect$|i, (@_ ? shift : ()) ); | |
ea067225 | 277 | } |