1#!perl -T 2 3BEGIN { 4 use Config; 5 use Test::More; 6 plan skip_all => "POSIX is unavailable" if $Config{'extensions'} !~ m!\bPOSIX\b!; 7} 8 9use strict; 10use File::Spec; 11use POSIX; 12 13sub check(@) { 14 grep { eval "&$_;1" or $@!~/vendor has not defined POSIX macro/ } @_ 15} 16 17my @path_consts = check qw( 18 _PC_CHOWN_RESTRICTED _PC_LINK_MAX _PC_NAME_MAX 19 _PC_NO_TRUNC _PC_PATH_MAX 20); 21 22my @path_consts_terminal = check qw( 23 _PC_MAX_CANON _PC_MAX_INPUT _PC_VDISABLE 24); 25 26my @path_consts_fifo = check qw( 27 _PC_PIPE_BUF 28); 29 30my @sys_consts = check qw( 31 _SC_ARG_MAX _SC_CHILD_MAX _SC_CLK_TCK _SC_JOB_CONTROL 32 _SC_NGROUPS_MAX _SC_OPEN_MAX _SC_PAGESIZE _SC_SAVED_IDS 33 _SC_STREAM_MAX _SC_VERSION _SC_TZNAME_MAX 34); 35 36my $tests = 2 * 2 * @path_consts + 37 2 * 2 * @path_consts_terminal + 38 2 * 2 * @path_consts_fifo + 39 1 * @sys_consts; 40plan $tests 41 ? (tests => $tests) 42 : (skip_all => "No tests to run on this OS") 43; 44 45# Don't test on "." as it can be networked storage which returns EINVAL 46# Testing on "/" may not be portable to non-Unix as it may not be readable 47# "/tmp" should be readable and likely also local. 48my $testdir = File::Spec->tmpdir; 49$testdir = VMS::Filespec::fileify($testdir) if $^O eq 'VMS'; 50 51my $r; 52 53my $TTY = "/dev/tty"; 54 55sub _check_and_report { 56 my ($sub, $constant, $description) = @_; 57 $! = 0; 58 my $return_val = eval {$sub->(eval "$constant()")}; 59 my $errno = $!; # Grab this before anything else changes it. 60 is($@, '', $description); 61 62 # We can't test sysconf further without investigating the type of argument 63 # provided 64 return if $description =~ /sysconf/; 65 66 if (defined $return_val) { 67 like($return_val, qr/\A(?:-?[1-9][0-9]*|0 but true)\z/, 68 'the returned value should be a signed integer'); 69 } else { 70 SKIP: 71 { 72 # POSIX specifies EINVAL is returned if the f?pathconf() 73 # isn't implemented for the specific path 74 skip "$description not implemented for this path", 1 75 if $errno == EINVAL && $description =~ /pathconf/; 76 cmp_ok($errno, '==', 0, 'errno should be 0 as before the call') 77 or diag("\$!: $errno"); 78 } 79 } 80} 81 82# testing fpathconf() on a non-terminal file 83SKIP: { 84 my $fd = POSIX::open($testdir, O_RDONLY) 85 or skip "could not open test directory '$testdir' ($!)", 86 2 * @path_consts; 87 88 for my $constant (@path_consts) { 89 _check_and_report(sub { fpathconf($fd, shift) }, $constant, 90 "calling fpathconf($fd, $constant)"); 91 } 92 93 POSIX::close($fd); 94} 95 96# testing pathconf() on a non-terminal file 97for my $constant (@path_consts) { 98 _check_and_report(sub { pathconf($testdir, shift) }, $constant, 99 "calling pathconf('$testdir', $constant)"); 100} 101 102SKIP: { 103 my $n = 2 * 2 * @path_consts_terminal; 104 105 -c $TTY 106 or skip("$TTY not a character file", $n); 107 open(TTY, $TTY) 108 or skip("failed to open $TTY: $!", $n); 109 -t TTY 110 or skip("TTY ($TTY) not a terminal file", $n); 111 112 my $fd = fileno(TTY); 113 114 # testing fpathconf() on a terminal file 115 for my $constant (@path_consts_terminal) { 116 _check_and_report(sub { fpathconf($fd, shift) }, $constant, 117 "calling fpathconf($fd, $constant) ($TTY)"); 118 } 119 120 close($fd); 121 # testing pathconf() on a terminal file 122 for my $constant (@path_consts_terminal) { 123 _check_and_report(sub { pathconf($TTY, shift) }, $constant, 124 "calling pathconf($TTY, $constant)"); 125 } 126} 127 128my $fifo = "fifo$$"; 129 130SKIP: { 131 eval { mkfifo($fifo, 0666) } 132 or skip("could not create fifo $fifo ($!)", 2 * 2 * @path_consts_fifo); 133 134 SKIP: { 135 my $fd = POSIX::open($fifo, O_RDONLY | O_NONBLOCK) 136 or skip("could not open $fifo ($!)", 2 * @path_consts_fifo); 137 138 for my $constant (@path_consts_fifo) { 139 _check_and_report(sub { fpathconf($fd, shift) }, $constant, 140 "calling fpathconf($fd, $constant) ($fifo)"); 141 } 142 143 POSIX::close($fd); 144 } 145 146 # testing pathconf() on a fifo file 147 for my $constant (@path_consts_fifo) { 148 _check_and_report(sub { pathconf($fifo, shift) }, $constant, 149 "calling pathconf($fifo, $constant"); 150 } 151} 152 153END { 154 1 while unlink($fifo); 155} 156 157SKIP: { 158 if($^O eq 'cygwin') { 159 pop @sys_consts; 160 skip("No _SC_TZNAME_MAX on Cygwin", 1); 161 } 162 163} 164# testing sysconf() 165for my $constant (@sys_consts) { 166 _check_and_report(sub {sysconf(shift)}, $constant, 167 "calling sysconf($constant)"); 168} 169