X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FTestCommon.pm;h=b252810fca51865903e332aaecd2ef4b4f21d2a0;hb=b2b1006759730507731fcd3fc3e0de68239e3b92;hp=79e597f598623315166b5fcd6eb49e06ed68a90d;hpb=9787fae1f7235bd790d1db6f0b513ce420c361bd;p=public-inbox.git diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm index 79e597f5..b252810f 100644 --- a/lib/PublicInbox/TestCommon.pm +++ b/lib/PublicInbox/TestCommon.pm @@ -5,11 +5,12 @@ package PublicInbox::TestCommon; use strict; use parent qw(Exporter); +use v5.10.1; use Fcntl qw(FD_CLOEXEC F_SETFD F_GETFD :seek); use POSIX qw(dup2); use IO::Socket::INET; our @EXPORT = qw(tmpdir tcp_server tcp_connect require_git require_mods - run_script start_script key2sub xsys xqx eml_load); + run_script start_script key2sub xsys xqx eml_load tick); sub eml_load ($) { my ($path, $cb) = @_; @@ -36,17 +37,18 @@ sub tcp_server () { Type => Socket::SOCK_STREAM(), Listen => 1024, Blocking => 0, - ) + ) or Test::More::BAIL_OUT("failed to create TCP server: $!"); } sub tcp_connect { my ($dest, %opt) = @_; + my $addr = $dest->sockhost . ':' . $dest->sockport; my $s = IO::Socket::INET->new( Proto => 'tcp', Type => Socket::SOCK_STREAM(), - PeerAddr => $dest->sockhost . ':' . $dest->sockport, + PeerAddr => $addr, %opt, - ); + ) or Test::More::BAIL_OUT("failed to connect to $addr: $!"); $s->autoflush(1); $s; } @@ -70,7 +72,7 @@ sub require_mods { my @mods = @_; my $maybe = pop @mods if $mods[-1] =~ /\A[0-9]+\z/; my @need; - for my $mod (@mods) { + while (my $mod = shift(@mods)) { if ($mod eq 'Search::Xapian') { if (eval { require PublicInbox::Search } && PublicInbox::Search::load_xapian()) { @@ -81,10 +83,27 @@ sub require_mods { PublicInbox::SearchIdx::load_xapian_writable()){ next; } + } elsif (index($mod, '||') >= 0) { # "Foo||Bar" + my $ok; + for my $m (split(/\Q||\E/, $mod)) { + eval "require $m"; + next if $@; + $ok = $m; + last; + } + next if $ok; } else { eval "require $mod"; } - push @need, $mod if $@; + if ($@) { + push @need, $mod; + } elsif ($mod eq 'IO::Socket::SSL' && + # old versions of IO::Socket::SSL aren't supported + # by libnet, at least: + # https://rt.cpan.org/Ticket/Display.html?id=100529 + !eval{ IO::Socket::SSL->VERSION(2.007); 1 }) { + push @need, $@; + } } return unless @need; my $m = join(', ', @need)." missing for $0"; @@ -249,7 +268,39 @@ sub run_script ($;$$) { $? == 0; } -sub wait_for_tail () { sleep(2) } +sub tick (;$) { + my $tick = shift // 0.1; + select undef, undef, undef, $tick; + 1; +} + +sub wait_for_tail ($;$) { + my ($tail_pid, $stop) = @_; + my $wait = 2; + if ($^O eq 'linux') { # GNU tail may use inotify + state $tail_has_inotify; + return tick if $stop && $tail_has_inotify; + my $end = time + $wait; + my @ino; + do { + @ino = grep { + readlink($_) =~ /\binotify\b/ + } glob("/proc/$tail_pid/fd/*"); + } while (!@ino && time <= $end and tick); + return if !@ino; + $tail_has_inotify = 1; + $ino[0] =~ s!/fd/!/fdinfo/!; + my @info; + do { + if (open my $fh, '<', $ino[0]) { + local $/ = "\n"; + @info = grep(/^inotify wd:/, <$fh>); + } + } while (scalar(@info) < 2 && time <= $end and tick); + } else { + sleep($wait); + } +} # like system() built-in, but uses spawn() for env/rdr + vfork sub xsys { @@ -294,7 +345,7 @@ sub start_script { exec(split(' ', $tail_cmd), @paths); die "$tail_cmd failed: $!"; } - wait_for_tail(); + wait_for_tail($tail_pid); } } defined(my $pid = fork) or die "fork: $!\n"; @@ -321,6 +372,7 @@ sub start_script { } $0 = join(' ', @$cmd); if ($sub) { + eval { PublicInbox::DS->Reset }; _run_sub($sub, $key, \@argv); POSIX::_exit($? >> 8); } else { @@ -359,11 +411,15 @@ sub join { sub DESTROY { my ($self) = @_; return if $self->{owner} != $$; - if (my $tail = delete $self->{tail_pid}) { - PublicInbox::TestCommon::wait_for_tail(); - CORE::kill('TERM', $tail); + if (my $tail_pid = delete $self->{tail_pid}) { + PublicInbox::TestCommon::wait_for_tail($tail_pid, 1); + CORE::kill('TERM', $tail_pid); } $self->join('TERM'); } +package PublicInbox::TestCommon::InboxWakeup; +use strict; +sub on_inbox_unlock { ${$_[0]}->($_[1]) } + 1;