X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=t%2Fhttpd-corner.t;h=fb3ffcf1fba6abaadd38ca95ea754a8c2e56d947;hb=3c313f9034aac96182e2efdc2f92c40803626f32;hp=75573c3ef23a423a1238320b2b70cea592834a19;hpb=ad221e9b2852f6c57ec1692dafa786de60621bb6;p=public-inbox.git diff --git a/t/httpd-corner.t b/t/httpd-corner.t index 75573c3e..fb3ffcf1 100644 --- a/t/httpd-corner.t +++ b/t/httpd-corner.t @@ -14,19 +14,17 @@ foreach my $mod (qw(Plack::Util Plack::Builder HTTP::Date HTTP::Status)) { } use Digest::SHA qw(sha1_hex); -use File::Temp qw/tempdir/; use IO::Socket; use IO::Socket::UNIX; use Fcntl qw(:seek); use Socket qw(IPPROTO_TCP TCP_NODELAY SOL_SOCKET); use POSIX qw(mkfifo); -require './t/common.perl'; -my $tmpdir = tempdir('httpd-corner-XXXXXX', TMPDIR => 1, CLEANUP => 1); +use PublicInbox::TestCommon; +my ($tmpdir, $for_destroy) = tmpdir(); my $fifo = "$tmpdir/fifo"; ok(defined mkfifo($fifo, 0777), 'created FIFO'); my $err = "$tmpdir/stderr.log"; my $out = "$tmpdir/stdout.log"; -my $httpd = 'blib/script/public-inbox-httpd'; my $psgi = "./t/httpd-corner.psgi"; my $sock = tcp_server() or die; @@ -51,32 +49,45 @@ if ($^O eq 'linux') { setsockopt($sock, SOL_SOCKET, $var, $accf_arg) or die "setsockopt: $!"; } +sub unix_server ($) { + my $s = IO::Socket::UNIX->new( + Listen => 1024, + Type => Socket::SOCK_STREAM(), + Local => $_[0], + ); + $s->blocking(0); + $s; +} + my $upath = "$tmpdir/s"; my $unix = unix_server($upath); ok($unix, 'UNIX socket created'); -my $pid; -END { kill 'TERM', $pid if defined $pid }; +my $td; my $spawn_httpd = sub { my (@args) = @_; - my $cmd = [ $httpd, @args, "--stdout=$out", "--stderr=$err", $psgi ]; - $pid = spawn_listener(undef, $cmd, [ $sock, $unix ]); - ok(defined $pid, 'forked httpd process successfully'); + my $cmd = [ '-httpd', @args, "--stdout=$out", "--stderr=$err", $psgi ]; + $td = start_script($cmd, undef, { 3 => $sock, 4 => $unix }); }; $spawn_httpd->(); if ('test worker death') { my $conn = conn_for($sock, 'killed worker'); - $conn->write("GET /pid HTTP/1.0\r\n\r\n"); - ok($conn->read(my $buf, 8192), 'read response'); - my ($head, $body) = split(/\r\n\r\n/, $buf); - like($body, qr/\A[0-9]+\z/, '/pid response'); - my $pid = $body; + $conn->write("GET /pid HTTP/1.1\r\nHost:example.com\r\n\r\n"); + my $pid; + while (defined(my $line = $conn->getline)) { + next unless $line eq "\r\n"; + chomp($pid = $conn->getline); + last; + } + like($pid, qr/\A[0-9]+\z/, '/pid response'); is(kill('KILL', $pid), 1, 'killed worker'); + is($conn->getline, undef, 'worker died and EOF-ed client'); $conn = conn_for($sock, 'respawned worker'); $conn->write("GET /pid HTTP/1.0\r\n\r\n"); - ok($conn->read($buf, 8192), 'read response'); - ($head, $body) = split(/\r\n\r\n/, $buf); + ok($conn->read(my $buf, 8192), 'read response'); + my ($head, $body) = split(/\r\n\r\n/, $buf); + chomp($body); like($body, qr/\A[0-9]+\z/, '/pid response'); isnt($body, $pid, 'respawned worker'); } @@ -198,16 +209,14 @@ sub conn_for { open my $f, '>', $fifo or die "open $fifo: $!\n"; $f->autoflush(1); ok(print($f "hello\n"), 'wrote something to fifo'); - my $kpid = $pid; - $pid = undef; - is(kill('TERM', $kpid), 1, 'started graceful shutdown'); + is($td->kill, 1, 'started graceful shutdown'); ok(print($f "world\n"), 'wrote else to fifo'); close $f or die "close fifo: $!\n"; $conn->read(my $buf, 8192); my ($head, $body) = split(/\r\n\r\n/, $buf, 2); like($head, qr!\AHTTP/1\.[01] 200 OK!, 'got 200 for slow-header'); is($body, "hello\nworld\n", 'read expected body'); - is(waitpid($kpid, 0), $kpid, 'reaped httpd'); + $td->join; is($?, 0, 'no error'); $spawn_httpd->('-W0'); } @@ -229,15 +238,13 @@ sub conn_for { $conn->sysread($buf, 8192); is($buf, $c, 'got trickle for reading'); } - my $kpid = $pid; - $pid = undef; - is(kill('TERM', $kpid), 1, 'started graceful shutdown'); + is($td->kill, 1, 'started graceful shutdown'); ok(print($f "world\n"), 'wrote else to fifo'); close $f or die "close fifo: $!\n"; $conn->sysread($buf, 8192); is($buf, "world\n", 'read expected body'); is($conn->sysread($buf, 8192), 0, 'got EOF from server'); - is(waitpid($kpid, 0), $kpid, 'reaped httpd'); + $td->join; is($?, 0, 'no error'); $spawn_httpd->('-W0'); } @@ -331,9 +338,7 @@ SKIP: { $conn->write("Content-Length: $len\r\n"); delay(); $conn->write("\r\n"); - my $kpid = $pid; - $pid = undef; - is(kill('TERM', $kpid), 1, 'started graceful shutdown'); + is($td->kill, 1, 'started graceful shutdown'); delay(); my $n = 0; foreach my $c ('a'..'z') { @@ -341,7 +346,7 @@ SKIP: { } is($n, $len, 'wrote alphabet'); $check_self->($conn); - is(waitpid($kpid, 0), $kpid, 'reaped httpd'); + $td->join; is($?, 0, 'no error'); $spawn_httpd->('-W0'); } @@ -538,12 +543,29 @@ SKIP: { defined(my $x = getsockopt($sock, SOL_SOCKET, $var)) or die; is($x, $accf_arg, 'SO_ACCEPTFILTER unchanged if previously set'); }; + SKIP: { skip 'only testing lsof(8) output on Linux', 1 if $^O ne 'linux'; skip 'no lsof in PATH', 1 unless which('lsof'); - my @lsof = `lsof -p $pid`; + my @lsof = `lsof -p $td->{pid}`; is_deeply([grep(/\bdeleted\b/, @lsof)], [], 'no lingering deleted inputs'); - is_deeply([grep(/\bpipe\b/, @lsof)], [], 'no extra pipes with -W0'); + + # filter out pipes inherited from the parent + my @this = `lsof -p $$`; + my $bad; + my $extract_inodes = sub { + map {; + my @f = split(' ', $_); + my $inode = $f[-2]; + $bad = $_ if $inode !~ /\A[0-9]+\z/; + $inode => 1; + } grep (/\bpipe\b/, @_); + }; + my %child = $extract_inodes->(@lsof); + my %parent = $extract_inodes->(@this); + skip("inode not in expected format: $bad", 1) if defined($bad); + delete @child{(keys %parent)}; + is_deeply([], [keys %child], 'no extra pipes with -W0'); }; done_testing();