#!./perl
BEGIN {
chdir
't'
if
-d
't'
;
require
'./test.pl'
;
set_up_inc(
qw '../lib
../cpan/Perl-OSType/lib');
}
plan(
tests
=> 58 + 27*14);
if
($^O =~ /MSWin32|cygwin|msys/ && !is_miniperl) {
}
is(-d
'op'
, 1,
"-d: directory correctly identified"
);
is(-f
'TEST'
, 1,
"-f: plain file correctly identified"
);
isnt(-f
'op'
, 1,
"-f: directory is not a plain file"
);
isnt(-d
'TEST'
, 1,
"-d: plain file is not a directory"
);
is(-r
'TEST'
, 1,
"-r: file readable by effective uid/gid not found"
);
my
$ro_empty_file
= tempfile();
{
open
my
$fh
,
'>'
,
$ro_empty_file
or
die
"open $fh: $!"
;
close
$fh
or
die
"close $fh: $!"
;
}
chmod
0555,
$ro_empty_file
or
die
"chmod 0555, '$ro_empty_file' failed: $!"
;
SKIP: {
my
$restore_root
;
skip
"Need Win32::IsAdminUser() on $^O"
, 1
if
$^O =~ /MSWin32|cygwin|msys/ && is_miniperl();
my
$Is_WinAdminUser
= ($^O =~ /MSWin32|cygwin|msys/ and Win32::IsAdminUser()) ? 1 : 0;
if
(
$Is_WinAdminUser
) {
skip(
"As Windows Administrator we cannot rely on -w via uid/gid"
);
}
elsif
($> == 0) {
eval
'$> = 1'
;
skip(
"Can't drop root privs to test read-only files"
)
if
$> == 0;
note(
"Dropped root privs to test read-only files. \$> == $>"
);
++
$restore_root
;
}
isnt(-w
$ro_empty_file
, 1,
"-w: file writable by effective uid/gid"
);
if
(
$restore_root
) {
$> = 0;
note(
"Restored root privs after testing read-only files. \$> == $>"
);
}
}
is(-r
'op'
, 1,
"-r: directory readable by effective uid/gid"
);
is(-w
'op'
, 1,
"-w: directory writable by effective uid/gid"
);
is(-x
'op'
, 1,
"-x: executable by effective uid/gid"
);
is(
"@{[grep -r, qw(foo io noo op zoo)]}"
,
"io op"
,
"-r: found directories readable by effective uid/gid"
);
is(
defined
( -f -d
'TEST'
), 1,
"-f and -d stackable: plain file found"
);
isnt(-f -d _, 1,
"-f and -d stackable: no plain file found"
);
isnt(
defined
( -e
'zoo'
), 1,
"-e: file does not exist"
);
isnt(
defined
( -e -d
'zoo'
), 1,
"-e and -d: neither file nor directory exists"
);
isnt(
defined
( -f -e
'zoo'
), 1,
"-f and -e: not a plain file and does not exist"
);
is(-f -e
'TEST'
, 1,
"-f and -e: plain file and exists"
);
is(-e -f
'TEST'
, 1,
"-e and -f: exists and is plain file"
);
is(
defined
(-d -e
'TEST'
), 1,
"-d and -e: file at least exists"
);
is(
defined
(-e -d
'TEST'
), 1,
"-e and -d: file at least exists"
);
isnt( -f -d
'op'
, 1,
"-f and -d: directory found but is not a plain file"
);
is(-x -d -x
'op'
, 1,
"-x, -d and -x again: directory exists and is executable"
);
my
(
$size
) = (
stat
'TEST'
)[7];
cmp_ok(
$size
,
'>'
, 1,
'TEST is longer than 1 byte'
);
is( (-s -f
'TEST'
),
$size
,
"-s returns real size"
);
is(-f -s
'TEST'
, 1,
"-f and -s: plain file with non-zero size"
);
is(-f
$ro_empty_file
, 1,
"-f: plain file found"
);
is(-s
$ro_empty_file
, 0,
"-s: file has 0 bytes"
);
is(-f -s
$ro_empty_file
, 0,
"-f and -s: plain file with 0 bytes"
);
is(-s -f
$ro_empty_file
, 0,
"-s and -f: file with 0 bytes is plain file"
);
eval
{ -l -e
"TEST"
};
like $@,
qr/^The stat preceding -l _ wasn't an lstat at /
,
'stacked -l non-lstat error with warnings off'
;
{
local
$^W = 1;
eval
{ -l -e
"TEST"
};
like $@,
qr/^The stat preceding -l _ wasn't an lstat at /
,
'stacked -l non-lstat error with warnings on'
;
}
SKIP: {
if
(os_type ne
'Unix'
) { skip
"Not Unix"
, 3 }
if
( $^O =~ /android/ ) {
$ln
=
"ln"
;
}
else
{
chomp
(
my
$ln
= `which ln`);
if
( ! -e
$ln
) { skip
"No ln"
, 3 }
}
lstat
$ro_empty_file
;
`ln -s
$ro_empty_file
1`;
isnt(-l -e _, 1,
'stacked -l uses previous stat, not previous retval'
);
unlink
1;
system
'ln'
,
'-s'
,
$ro_empty_file
, \
*foo
;
local
$^W = 1;
my
@warnings
;
local
$SIG
{__WARN__} =
sub
{
push
@warnings
,
@_
};
is(-l \
*foo
, 1,
'-l \*foo is a file name'
);
ok(
$warnings
[0] =~ /-l on filehandle foo/,
'warning for -l $handle'
);
unlink
\
*foo
;
}
{
local
$^W = 1;
my
@warnings
;
local
$SIG
{__WARN__} =
sub
{
push
@warnings
,
@_
};
() = -l \*{
"\x{3c6}oo"
};
like(
$warnings
[0],
qr/-l on filehandle \x{3c6}oo/
,
'-l $handle warning is utf8-clean'
);
() = -l
*foo
;
like(
$warnings
[1],
qr/-l on filehandle foo/
,
'-l $handle warning occurs for globs, not just globrefs'
);
tell
foo;
() = -l
*foo
{IO};
like(
$warnings
[3],
qr/-l on filehandle at/
,
'-l $handle warning occurs for iorefs as well'
);
}
-f
'TEST'
;
is(-f _, 1,
"_ is bareword after filetest operator"
);
sub
_ {
"this is not a file name"
}
is(-f _, 1,
"_ is bareword after filetest operator"
);
my
$over
;
{
fallback
=> 1,
-X
=>
sub
{
$over
= [
qq($_[0])
,
$_
[1]];
"-$_[1]"
;
};
}
{
use
overload
q/""/
=>
sub
{
$over
= 1;
"TEST"
};
}
{
q/""/
=>
sub
{
"TEST"
},
-X
=>
sub
{
"-$_[1]"
};
}
{
'+'
=>
sub
{ 1 },
fallback
=> 1;
}
my
$ft
=
bless
[],
"OverFtest"
;
my
$ftstr
=
qq($ft)
;
my
$str
=
bless
[],
"OverString"
;
my
$both
=
bless
[],
"OverBoth"
;
my
$neither
=
bless
[],
"OverNeither"
;
my
$nstr
=
qq($neither)
;
open
my
$gv
,
"<"
,
"TEST"
;
bless
$gv
,
"OverString"
;
open
my
$io
,
"<"
,
"TEST"
;
$io
= *{
$io
}{IO};
bless
$io
,
"OverString"
;
my
$fcntl_not_available
;
eval
{
require
Fcntl } or
$fcntl_not_available
= 1;
for
my
$op
(
split
//,
"rwxoRWXOezsfdlpSbctugkTMBAC"
) {
$over
= [];
my
$rv
=
eval
"-$op \$ft"
;
isnt(
$rv
,
undef
,
"overloaded -$op succeeds"
)
or diag( $@ );
is(
$over
->[0],
$ftstr
,
"correct object for overloaded -$op"
);
is(
$over
->[1],
$op
,
"correct op for overloaded -$op"
);
is(
$rv
,
"-$op"
,
"correct return value for overloaded -$op"
);
my
(
$exp
,
$is
) = (1,
"is"
);
$over
= 0;
$rv
=
eval
"-$op \$str"
;
is($@,
""
,
"-$op succeeds with string overloading"
);
is(
$rv
,
eval
"-$op 'TEST'"
,
"correct -$op on string overload"
);
is(
$over
,
$exp
,
"string overload $is called for -$op"
);
(
$exp
,
$is
) =
$op
eq
"l"
? (1,
"is"
) : (0,
"not"
);
$over
= 0;
eval
"-$op \$gv"
;
is(
$over
,
$exp
,
"string overload $is called for -$op on GLOB"
);
$op
eq
"t"
||
$op
eq
"T"
||
$op
eq
"B"
and (
$exp
,
$is
) = (1,
"is"
);
$over
= 0;
eval
"-$op \$io"
;
is(
$over
,
$exp
,
"string overload $is called for -$op on IO"
);
$rv
=
eval
"-$op \$both"
;
is(
$rv
,
"-$op"
,
"correct -$op on string/-X overload"
);
$rv
=
eval
"-$op \$neither"
;
is($@,
""
,
"-$op succeeds with random overloading"
);
is(
$rv
,
eval
"-$op \$nstr"
,
"correct -$op with random overloading"
);
is(
eval
"-r -$op \$ft"
,
"-r"
,
"stacked overloaded -$op"
);
is(
eval
"-$op -r \$ft"
,
"-$op"
,
"overloaded stacked -$op"
);
}
{
push
my
@foo
,
"bar"
, -l baz;
is
$foo
[0],
"bar"
,
'-l bareword does not corrupt the stack'
;
}
stat
"test.pl"
;
eval
{
use
warnings
FATAL
=> io; -l cradd };
isnt(
stat
_, 1,
'fatal warnings do not prevent -l HANDLE from setting stat status'
);
{
my
$w
;
sub
oon::TIESCALAR{
bless
[],
'oon'
}
sub
oon::FETCH{
$w
++}
tie
my
$t
,
'oon'
;
push
my
@a
,
$t
, -t;
is
$w
, 1,
'file test does not call FETCH on stack item not its own'
;
}
my
$Perl
= which_perl();
SKIP: {
skip
"no -T on filehandles"
, 8
unless
eval
{ -T STDERR; 1 };
-l
"perl.c"
;
-T STDERR;
eval
{ -l _ };
like $@,
qr/^The stat preceding -l _ wasn't an lstat at /
,
'-T HANDLE sets the stat type'
;
fresh_perl_is
'open my $fh, "test.pl"; -r $fh; undef $fh; open my $fh2, '
.
"q\0$Perl\0; print -B _"
,
''
,
{
switches
=> [
'-l'
] },
'PL_statgv should not point to freed-and-reused SV'
;
fresh_perl_is
'open Fh, "test.pl"; -r($h{i} = *Fh); $h{i} = 3; undef %h;'
.
'open my $fh2, '
.
"q\0"
. which_perl() .
"\0; print -B _"
,
''
,
{
switches
=> [
'-l'
] },
'PL_statgv should not point to coerced-freed-and-reused GV'
;
open
my
$fh
,
'test.pl'
;
stat
$Perl
;
stat
*$fh
{IO};
is(-T _, 1,
'-T _ works after stat $ioref'
);
-r
*$fh
{IO};
is(-T _, 1,
'-T _ works after -r $ioref'
);
stat
$fh
;
close
$fh
;
-T _;
isnt(
stat
_, 1,
'-T _ on closed filehandle resets stat info'
);
lstat
"test.pl"
;
-T
$fh
;
eval
{
lstat
_ };
like $@,
qr/^The stat preceding lstat\(\) wasn't an lstat at /
,
'-T on closed handle resets last stat type'
;
$! = 7;
-T cradd;
my
$errno
= $!;
$! = 7;
eval
{
use
warnings
FATAL
=> unopened; -T cradd };
my
$errno2
= $!;
is
$errno2
,
$errno
,
'fatal warnings do not affect errno after -T BADHADNLE'
;
}
is runperl(
prog
=>
'-T _'
,
switches
=> [
'-w'
],
stderr
=> 1),
""
,
'no uninit warnings from -T with no preceding stat'
;
SKIP: {
my
$rand_file_name
=
'filetest-'
.
rand
=~ y/.//dr;
if
(-e
$rand_file_name
) { skip
"File $rand_file_name exists"
, 1 }
stat
'test.pl'
;
-T
$rand_file_name
;
isnt(
stat
_, 1,
'-T "nonexistent" resets stat success status'
);
}
{
stat
"test.pl"
;
-r
*phlon
;
my
$failed_stat1
=
stat
_;
stat
"test.pl"
;
eval
{
use
warnings
FATAL
=> unopened; -r
*phlon
};
my
$failed_stat2
=
stat
_;
is
$failed_stat2
,
$failed_stat1
,
'failed -r($gv_without_io) with and w/out fatal warnings'
;
stat
"test.pl"
;
-r cength;
$failed_stat1
=
stat
_;
stat
"test.pl"
;
eval
{
use
warnings
FATAL
=> unopened; -r cength };
$failed_stat2
=
stat
_;
is
$failed_stat2
,
$failed_stat1
,
'failed -r($gv_with_io_but_no_fp) with and w/out fatal warnings'
;
}
{
ok(!-T
"TEST\0-"
,
'-T on name with \0'
);
ok(!-B
"TEST\0-"
,
'-B on name with \0'
);
ok(!-f
"TEST\0-"
,
'-f on name with \0'
);
ok(!-r
"TEST\0-"
,
'-r on name with \0'
);
}
{
""
=~ /(.*)/;
my
$x
= $1;
"test.pl"
=~ /(.*)/;
ok(-f -r $1,
"stacked handles on a name with magic"
);
}