about summary refs log tree commit homepage
path: root/t
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2021-01-01 19:13:39 -1400
committerEric Wong <e@80x24.org>2021-01-02 22:38:49 +0000
commit6dd3c17ed185c0ed4569541dae52e0570be4deca (patch)
treee5b694ec690130e288361b1131959de3363195b0 /t
parent0bd668ac6f15f791b626f5c644d23952c377b200 (diff)
downloadpublic-inbox-6dd3c17ed185c0ed4569541dae52e0570be4deca.tar.gz
To get rid of the ugly $PublicInbox::DS::in_loop localization
in MboxReader, we'll distinguish between ->CLOSE and ->DESTROY
with ProcessPipe.

If we end up closing via ->DESTROY, we'll assume the caller will
want to deal with $? asynchronously via the event loop (or not
even care about $?).

If we hit ->CLOSE directly, we'll assume the caller called
close() and wants to check $? synchronously.

Note: wantarray doesn't seem to propagate into tied methods,
otherwise I'd be relying on that.
Diffstat (limited to 't')
-rw-r--r--t/mbox_reader.t17
-rw-r--r--t/spawn.t38
2 files changed, 55 insertions, 0 deletions
diff --git a/t/mbox_reader.t b/t/mbox_reader.t
index 53458ec2..4ea2ae29 100644
--- a/t/mbox_reader.t
+++ b/t/mbox_reader.t
@@ -72,4 +72,21 @@ for my $fmt (@mbox) { $check_fmt->($fmt) }
 s/\n/\r\n/sg for (values %raw);
 for my $fmt (@mbox) { $check_fmt->($fmt) }
 
+SKIP: {
+        use PublicInbox::Spawn qw(popen_rd);
+        use Time::HiRes qw(alarm);
+        my $fh = popen_rd([ $^X, '-E', <<'' ]);
+say "From x@y Fri Oct  2 00:00:00 1993";
+print "a: b\n\n", "x" x 70000, "\n\n";
+say "From x@y Fri Oct  2 00:00:00 2010";
+print "Final: bit\n\n", "Incomplete\n\n";
+exit 1
+
+        my @x;
+        eval { $reader->mboxrd($fh, sub { push @x, shift->as_string }) };
+        like($@, qr/error closing mbox/, 'detects error reading from pipe');
+        is(scalar(@x), 1, 'only saw one message');
+        is(scalar(grep(/Final/, @x)), 0, 'no incomplete bit');
+}
+
 done_testing;
diff --git a/t/spawn.t b/t/spawn.t
index 552bba33..d97e13a6 100644
--- a/t/spawn.t
+++ b/t/spawn.t
@@ -98,6 +98,44 @@ EOF
         isnt($?, 0, '$? set properly: '.$?);
 }
 
+{ # ->CLOSE vs ->DESTROY waitpid caller distinction
+        my @c;
+        my $fh = popen_rd(['true'], undef, { cb => sub { @c = caller } });
+        ok(close($fh), '->CLOSE fired and successful');
+        ok(scalar(@c), 'callback fired by ->CLOSE');
+        ok(grep(!m[/PublicInbox/DS\.pm\z], @c), 'callback not invoked by DS');
+
+        @c = ();
+        $fh = popen_rd(['true'], undef, { cb => sub { @c = caller } });
+        undef $fh; # ->DESTROY
+        ok(scalar(@c), 'callback fired by ->DESTROY');
+        ok(grep(!m[/PublicInbox/ProcessPipe\.pm\z], @c),
+                'callback not invoked by ProcessPipe');
+}
+
+{ # children don't wait on siblings
+        use POSIX qw(_exit);
+        pipe(my ($r, $w)) or BAIL_OUT $!;
+        my $cb = sub { warn "x=$$\n" };
+        my $fh = popen_rd(['cat'], undef, { 0 => $r, cb => $cb });
+        my $pp = tied *$fh;
+        my $pid = fork // BAIL_OUT $!;
+        local $SIG{__WARN__} = sub { _exit(1) };
+        if ($pid == 0) {
+                local $SIG{__DIE__} = sub { _exit(2) };
+                undef $fh;
+                _exit(0);
+        }
+        waitpid($pid, 0);
+        is($?, 0, 'forked process exited');
+        my @w;
+        local $SIG{__WARN__} = sub { push @w, @_ };
+        close $w;
+        close $fh;
+        is($?, 0, 'cat exited');
+        is_deeply(\@w, [ "x=$$\n" ], 'callback fired from owner');
+}
+
 SKIP: {
         eval {
                 require BSD::Resource;