X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FTestCommon.pm;h=600843f006663815a3b0f95b1f61a1c24dfa3899;hb=57af9c8d0bedafac3267b5b42f963bb8aa5c2ea1;hp=d6d1e9394937c1ea652ccb06b52b41d82cc06470;hpb=033f628b52ebacf4a7bf8795084ba5ec498004bf;p=public-inbox.git diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm index d6d1e939..600843f0 100644 --- a/lib/PublicInbox/TestCommon.pm +++ b/lib/PublicInbox/TestCommon.pm @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2019 all contributors +# Copyright (C) 2015-2020 all contributors # License: AGPL-3.0+ # internal APIs used only for tests @@ -9,7 +9,20 @@ 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); + run_script start_script key2sub xsys xqx mime_load eml_load); + +sub mime_load ($) { + my ($path) = @_; + open(my $fh, '<', $path) or die "open $path: $!"; + PublicInbox::MIME->new(\(do { local $/; <$fh> })); +} + +sub eml_load ($) { + my ($path, $cb) = @_; + open(my $fh, '<', $path) or die "open $path: $!"; + binmode $fh; + PublicInbox::Eml->new(\(do { local $/; <$fh> })); +} sub tmpdir (;$) { my ($base) = @_; @@ -87,7 +100,7 @@ sub require_mods { sub key2script ($) { my ($key) = @_; - return $key if (index($key, '/') >= 0); + return $key if ($key eq 'git' || index($key, '/') >= 0); # n.b. we may have scripts which don't start with "public-inbox" in # the future: $key =~ s/\A([-\.])/public-inbox$1/; @@ -119,11 +132,11 @@ sub _undo_redirects ($) { } } -# $opt->{run_mode} (or $ENV{TEST_RUN_MODE}) allows chosing between +# $opt->{run_mode} (or $ENV{TEST_RUN_MODE}) allows choosing between # three ways to spawn our own short-lived Perl scripts for testing: # # 0 - (fork|vfork) + execve, the most realistic but slowest -# 1 - preloading and running in a forked subprocess (fast) +# 1 - (not currently implemented) # 2 - preloading and running in current process (slightly faster than 1) # # 2 is not compatible with scripts which use "exit" (which we'll try to @@ -215,7 +228,6 @@ sub run_script ($;$$) { require PublicInbox::Spawn; my $cmd = [ key2script($key), @argv ]; my $pid = PublicInbox::Spawn::spawn($cmd, $env, $spawn_opt); - defined($pid) or die "spawn: $!"; if (defined $pid) { my $r = waitpid($pid, 0); defined($r) or die "waitpid: $!"; @@ -245,10 +257,32 @@ sub run_script ($;$$) { sub wait_for_tail () { sleep(2) } +# like system() built-in, but uses spawn() for env/rdr + vfork +sub xsys { + my ($cmd, $env, $rdr) = @_; + if (ref($cmd)) { + $rdr ||= {}; + } else { + $cmd = [ @_ ]; + $env = undef; + $rdr = {}; + } + run_script($cmd, $env, { %$rdr, run_mode => 0 }); + $? >> 8 +} + +# like `backtick` or qx{} op, but uses spawn() for env/rdr + vfork +sub xqx { + my ($cmd, $env, $rdr) = @_; + $rdr //= {}; + run_script($cmd, $env, { %$rdr, run_mode => 0, 1 => \(my $out) }); + wantarray ? split(/^/m, $out) : $out; +} + sub start_script { my ($cmd, $env, $opt) = @_; my ($key, @argv) = @$cmd; - my $run_mode = $ENV{TEST_RUN_MODE} // $opt->{run_mode} // 1; + my $run_mode = $ENV{TEST_RUN_MODE} // $opt->{run_mode} // 2; my $sub = $run_mode == 0 ? undef : key2sub($key); my $tail_pid; if (my $tail_cmd = $ENV{TAIL}) { @@ -320,8 +354,9 @@ sub kill { } sub join { - my ($self) = @_; + my ($self, $sig) = @_; my $pid = delete $self->{pid} or return; + CORE::kill($sig, $pid) if defined $sig; my $ret = waitpid($pid, 0); defined($ret) or die "waitpid($pid): $!"; $ret == $pid or die "waitpid($pid) != $ret"; @@ -334,8 +369,7 @@ sub DESTROY { PublicInbox::TestCommon::wait_for_tail(); CORE::kill('TERM', $tail); } - my $pid = delete $self->{pid} or return; - CORE::kill('TERM', $pid); + $self->join('TERM'); } 1;