xref: /openbsd-src/gnu/usr.bin/perl/dist/IO/t/cachepropagate-unix.t (revision fac98b93b71777a71b1e912ccaf68ce33d7b87c4)
191f110e0Safresh1#!/usr/bin/perl
291f110e0Safresh1
391f110e0Safresh1use warnings;
491f110e0Safresh1use strict;
591f110e0Safresh1
691f110e0Safresh1use File::Temp qw(tempdir);
791f110e0Safresh1use File::Spec::Functions;
891f110e0Safresh1use IO::Socket;
991f110e0Safresh1use IO::Socket::UNIX;
1091f110e0Safresh1use Socket;
1191f110e0Safresh1use Config;
1291f110e0Safresh1use Test::More;
1391f110e0Safresh1
1491f110e0Safresh1plan skip_all => "UNIX domain sockets not implemented on $^O"
1591f110e0Safresh1  if ($^O =~ m/^(?:qnx|nto|vos|MSWin32|VMS)$/);
1691f110e0Safresh1
1791f110e0Safresh1my $socketpath = catfile(tempdir( CLEANUP => 1 ), 'testsock');
1891f110e0Safresh1
195759b3d2Safresh1# check the socketpath fits in sun_path.
205759b3d2Safresh1#
215759b3d2Safresh1# pack_sockaddr_un() just truncates the path, this may change, but how
225759b3d2Safresh1# it will handle such a condition is undetermined (and we might need
235759b3d2Safresh1# to work with older versions of Socket outside of a perl build)
245759b3d2Safresh1# https://rt.cpan.org/Ticket/Display.html?id=116819
255759b3d2Safresh1
265759b3d2Safresh1my $name = eval { pack_sockaddr_un($socketpath) };
275759b3d2Safresh1if (defined $name) {
285759b3d2Safresh1    my ($packed_name) = eval { unpack_sockaddr_un($name) };
295759b3d2Safresh1    if (!defined $packed_name || $packed_name ne $socketpath) {
305759b3d2Safresh1        plan skip_all => "socketpath too long for sockaddr_un";
315759b3d2Safresh1    }
325759b3d2Safresh1}
335759b3d2Safresh1
345759b3d2Safresh1plan tests => 15;
355759b3d2Safresh1
3691f110e0Safresh1# start testing stream sockets:
3791f110e0Safresh1my $listener = IO::Socket::UNIX->new(Type => SOCK_STREAM,
3891f110e0Safresh1				     Listen => 1,
3991f110e0Safresh1				     Local => $socketpath);
4091f110e0Safresh1ok(defined($listener), 'stream socket created');
4191f110e0Safresh1
4291f110e0Safresh1my $p = $listener->protocol();
4356d68f1eSafresh1{
4456d68f1eSafresh1    # the value of protocol isn't well defined for AF_UNIX, when we
4556d68f1eSafresh1    # create the socket we supply 0, which leaves it up to the implementation
4656d68f1eSafresh1    # to select a protocol, so we (now) don't save a 0 protocol during socket
4756d68f1eSafresh1    # creation.  This test then breaks if the implementation doesn't support
4856d68f1eSafresh1    # SO_SOCKET (at least on AF_UNIX).
4956d68f1eSafresh1    # This specifically includes NetBSD, Darwin and cygwin.
5056d68f1eSafresh1    # This is a TODO instead of a skip so if these ever implement SO_PROTOCOL
5156d68f1eSafresh1    # we'll be notified about the passing TODO so the test can be updated.
5256d68f1eSafresh1    local $TODO = "$^O doesn't support SO_PROTOCOL on AF_UNIX"
53eac174f2Safresh1        if $^O =~ /^(netbsd|darwin|cygwin|hpux|solaris|dragonfly|os390|gnu)$/;
5491f110e0Safresh1    ok(defined($p), 'protocol defined');
5556d68f1eSafresh1}
5691f110e0Safresh1my $d = $listener->sockdomain();
5791f110e0Safresh1ok(defined($d), 'domain defined');
5891f110e0Safresh1my $s = $listener->socktype();
5991f110e0Safresh1ok(defined($s), 'type defined');
6091f110e0Safresh1
6191f110e0Safresh1SKIP: {
6291f110e0Safresh1    skip "fork not available", 4
6391f110e0Safresh1	unless $Config{d_fork} || $Config{d_pseudofork};
6491f110e0Safresh1
6591f110e0Safresh1    my $cpid = fork();
6691f110e0Safresh1    if (0 == $cpid) {
6791f110e0Safresh1	# the child:
6891f110e0Safresh1	sleep(1);
6991f110e0Safresh1	my $connector = IO::Socket::UNIX->new(Peer => $socketpath);
7091f110e0Safresh1	exit(0);
7191f110e0Safresh1    } else {
7291f110e0Safresh1	ok(defined($cpid), 'spawned a child');
7391f110e0Safresh1    }
7491f110e0Safresh1
7591f110e0Safresh1    my $new = $listener->accept();
7691f110e0Safresh1
7791f110e0Safresh1    is($new->sockdomain(), $d, 'domain match');
7891f110e0Safresh1  SKIP: {
7991f110e0Safresh1      skip "no Socket::SO_PROTOCOL", 1 if !defined(eval { Socket::SO_PROTOCOL });
8091f110e0Safresh1      skip "SO_PROTOCOL defined but not implemented", 1
8191f110e0Safresh1         if !defined $new->sockopt(Socket::SO_PROTOCOL);
8291f110e0Safresh1      is($new->protocol(), $p, 'protocol match');
8391f110e0Safresh1    }
8491f110e0Safresh1  SKIP: {
8591f110e0Safresh1      skip "no Socket::SO_TYPE", 1 if !defined(eval { Socket::SO_TYPE });
8691f110e0Safresh1      skip "SO_TYPE defined but not implemented", 1
8791f110e0Safresh1         if !defined $new->sockopt(Socket::SO_TYPE);
8891f110e0Safresh1      is($new->socktype(), $s, 'type match');
8991f110e0Safresh1    }
9091f110e0Safresh1
9191f110e0Safresh1    unlink($socketpath);
9291f110e0Safresh1    wait();
9391f110e0Safresh1}
9491f110e0Safresh1
9591f110e0Safresh1undef $TODO;
9691f110e0Safresh1SKIP: {
9791f110e0Safresh1    skip "datagram unix sockets not supported on $^O", 7
9891f110e0Safresh1      if $^O eq "haiku";
9991f110e0Safresh1    # now test datagram sockets:
10091f110e0Safresh1    $listener = IO::Socket::UNIX->new(Type => SOCK_DGRAM,
10191f110e0Safresh1				      Local => $socketpath);
10291f110e0Safresh1    ok(defined($listener), 'datagram socket created');
10391f110e0Safresh1
10491f110e0Safresh1    $p = $listener->protocol();
10556d68f1eSafresh1    {
10656d68f1eSafresh1        # see comment above
10756d68f1eSafresh1        local $TODO = "$^O doesn't support SO_PROTOCOL on AF_UNIX"
108eac174f2Safresh1            if $^O =~ /^(netbsd|darwin|cygwin|hpux|solaris|dragonfly|os390|gnu)$/;
10991f110e0Safresh1        ok(defined($p), 'protocol defined');
11056d68f1eSafresh1    }
11191f110e0Safresh1    $d = $listener->sockdomain();
11291f110e0Safresh1    ok(defined($d), 'domain defined');
11391f110e0Safresh1    $s = $listener->socktype();
11491f110e0Safresh1    ok(defined($s), 'type defined');
11591f110e0Safresh1
11691f110e0Safresh1    my $new = IO::Socket::UNIX->new_from_fd($listener->fileno(), 'r+');
11791f110e0Safresh1
11891f110e0Safresh1    is($new->sockdomain(), $d, 'domain match');
11991f110e0Safresh1    SKIP: {
12091f110e0Safresh1      skip "no Socket::SO_PROTOCOL", 1 if !defined(eval { Socket::SO_PROTOCOL });
12191f110e0Safresh1      skip "SO_PROTOCOL defined but not implemented", 1
12291f110e0Safresh1         if !defined $new->sockopt(Socket::SO_PROTOCOL);
123*fac98b93Safresh1      skip "SO_PROTOCOL returns chosen protocol on OpenBSD", 1
124*fac98b93Safresh1         if $^O eq 'openbsd';
12591f110e0Safresh1      is($new->protocol(), $p, 'protocol match');
12691f110e0Safresh1    }
12791f110e0Safresh1    SKIP: {
12891f110e0Safresh1      skip "AIX: getsockopt(SO_TYPE) is badly broken on UDP/UNIX sockets", 1
12991f110e0Safresh1         if $^O eq "aix";
13091f110e0Safresh1      skip "no Socket::SO_TYPE", 1 if !defined(eval { Socket::SO_TYPE });
13191f110e0Safresh1      skip "SO_TYPE defined but not implemented", 1
13291f110e0Safresh1         if !defined $new->sockopt(Socket::SO_TYPE);
13391f110e0Safresh1      is($new->socktype(), $s, 'type match');
13491f110e0Safresh1    }
13591f110e0Safresh1}
13691f110e0Safresh1unlink($socketpath);
137