]> Sergey Matveev's repositories - public-inbox.git/blobdiff - t/cmd_ipc.t
No ext_urls
[public-inbox.git] / t / cmd_ipc.t
index b9f4d128138c3cdf60cb269df8ecff8eb7c775bb..cd76d5e896d160a015e19a9f9e119bfa0ffaa188 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;
@@ -17,7 +17,8 @@ my $do_test = sub { SKIP: {
        my ($s1, $s2);
        my $src = 'some payload' x 40;
        socketpair($s1, $s2, AF_UNIX, $type, 0) or BAIL_OUT $!;
-       $send->($s1, fileno($r), fileno($w), fileno($s1), $src, $flag);
+       my $sfds = [ fileno($r), fileno($w), fileno($s1) ];
+       $send->($s1, $sfds, $src, $flag);
        my (@fds) = $recv->($s2, my $buf, length($src) + 1);
        is($buf, $src, 'got buffer payload '.$desc);
        my ($r1, $w1, $s1a);
@@ -39,16 +40,78 @@ my $do_test = sub { SKIP: {
        if (defined($SOCK_SEQPACKET) && $type == $SOCK_SEQPACKET) {
                $r1 = $w1 = $s1a = undef;
                $src = (',' x 1023) . '-' .('.' x 1024);
-               $send->($s1, fileno($r), fileno($w), fileno($s1), $src, $flag);
+               $send->($s1, $sfds, $src, $flag);
                (@fds) = $recv->($s2, $buf, 1024);
                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 (tick(0.01)) {
+                                       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,12 +142,14 @@ SKIP: {
 }
 
 SKIP: {
-       require_mods('IO::FDPass', 13);
-       require_ok 'PublicInbox::CmdIPC1';
-       $send = PublicInbox::CmdIPC1->can('send_cmd1');
-       $recv = PublicInbox::CmdIPC1->can('recv_cmd1');
-       $do_test->(SOCK_STREAM, 0, 'IO::FDPass stream');
-       $do_test->($SOCK_SEQPACKET, MSG_EOR, 'IO::FDPass seqpacket');
+       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;