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