]> Sergey Matveev's repositories - public-inbox.git/blobdiff - t/cmd_ipc.t
xt/mem-imapd-tls: update aliases to DSdeflate subs
[public-inbox.git] / t / cmd_ipc.t
index 0a0a4e002a183776cf96ffb4dfd8c245c5c2828e..75697a1539e3e8b2b80bb4d1cfa80d685e7d57d5 100644 (file)
@@ -1,5 +1,5 @@
 #!perl -w
-# Copyright (C) 2021 all contributors <meta@public-inbox.org>
+# Copyright (C) all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 use strict;
 use v5.10.1;
@@ -10,6 +10,7 @@ pipe(my ($r, $w)) or BAIL_OUT;
 my ($send, $recv);
 require_ok 'PublicInbox::Spawn';
 my $SOCK_SEQPACKET = eval { Socket::SOCK_SEQPACKET() } // undef;
+use Time::HiRes qw(usleep);
 
 my $do_test = sub { SKIP: {
        my ($type, $flag, $desc) = @_;
@@ -45,11 +46,73 @@ my $do_test = sub { SKIP: {
                is($buf, (',' x 1023) . '-', 'silently truncated buf');
                $opens->();
                $r1 = $w1 = $s1a = undef;
+
+               $s2->blocking(0);
+               @fds = $recv->($s2, $buf, length($src) + 1);
+               ok($!{EAGAIN}, "EAGAIN set by ($desc)");
+               is_deeply(\@fds, [ undef ], "EAGAIN $desc");
+               $s2->blocking(1);
+
+               if ($ENV{TEST_ALRM}) {
+                       my $alrm = 0;
+                       local $SIG{ALRM} = sub { $alrm++ };
+                       my $tgt = $$;
+                       my $pid = fork // xbail "fork: $!";
+                       if ($pid == 0) {
+                               # need to loop since Perl signals are racy
+                               # (the interpreter doesn't self-pipe)
+                               while (usleep(1000)) {
+                                       kill 'ALRM', $tgt;
+                               }
+                       }
+                       @fds = $recv->($s2, $buf, length($src) + 1);
+                       ok($!{EINTR}, "EINTR set by ($desc)");
+                       kill('KILL', $pid);
+                       waitpid($pid, 0);
+                       is_deeply(\@fds, [ undef ], "EINTR $desc");
+                       ok($alrm, 'SIGALRM hit');
+               }
+
                close $s1;
                @fds = $recv->($s2, $buf, length($src) + 1);
                is_deeply(\@fds, [], "no FDs on EOF $desc");
                is($buf, '', "buffer cleared on EOF ($desc)");
 
+               socketpair($s1, $s2, AF_UNIX, $type, 0) or BAIL_OUT $!;
+               $s1->blocking(0);
+               my $nsent = 0;
+               while (defined(my $n = $send->($s1, $sfds, $src, $flag))) {
+                       $nsent += $n;
+                       fail "sent 0 bytes" if $n == 0;
+               }
+               ok($!{EAGAIN} || $!{ETOOMANYREFS},
+                       "hit EAGAIN || ETOOMANYREFS on send $desc") or
+                       diag "send failed with: $!";
+               ok($nsent > 0, 'sent some bytes');
+
+               socketpair($s1, $s2, AF_UNIX, $type, 0) or BAIL_OUT $!;
+               is($send->($s1, [], $src, $flag), length($src), 'sent w/o FDs');
+               $buf = 'nope';
+               @fds = $recv->($s2, $buf, length($src));
+               is(scalar(@fds), 0, 'no FDs received');
+               is($buf, $src, 'recv w/o FDs');
+
+               my $nr = 2 * 1024 * 1024;
+               while (1) {
+                       vec(my $vec = '', $nr * 8 - 1, 1) = 1;
+                       my $n = $send->($s1, [], $vec, $flag);
+                       if (defined($n)) {
+                               $n == length($vec) or
+                                       fail "short send: $n != ".length($vec);
+                               diag "sent $nr, retrying with more";
+                               $nr += 2 * 1024 * 1024;
+                       } else {
+                               ok($!{EMSGSIZE} || $!{ENOBUFS},
+                                       'got EMSGSIZE or ENOBUFS') or
+                                       diag "$nr bytes fails with: $!";
+                               last;
+                       }
+               }
        }
 } };
 
@@ -79,4 +142,15 @@ SKIP: {
        }
 }
 
+SKIP: {
+       skip 'not Linux', 1 if $^O ne 'linux';
+       require_ok 'PublicInbox::Syscall';
+       $send = PublicInbox::Syscall->can('send_cmd4') or
+               skip 'send_cmd4 not defined for arch';
+       $recv = PublicInbox::Syscall->can('recv_cmd4') or
+               skip 'recv_cmd4 not defined for arch';
+       $do_test->(SOCK_STREAM, 0, 'PP Linux stream');
+       $do_test->($SOCK_SEQPACKET, MSG_EOR, 'PP Linux seqpacket');
+}
+
 done_testing;