summaryrefslogtreecommitdiff
path: root/tests/runner.pm
diff options
context:
space:
mode:
Diffstat (limited to 'tests/runner.pm')
-rw-r--r--tests/runner.pm189
1 files changed, 184 insertions, 5 deletions
diff --git a/tests/runner.pm b/tests/runner.pm
index 737f24d60..a8e623c9a 100644
--- a/tests/runner.pm
+++ b/tests/runner.pm
@@ -28,6 +28,7 @@ package runner;
use strict;
use warnings;
+use 5.006;
BEGIN {
use base qw(Exporter);
@@ -37,10 +38,13 @@ BEGIN {
prepro
restore_test_env
runner_init
- runner_clearlocks
- runner_stopservers
- runner_test_preprocess
- runner_test_run
+ runnerac_clearlocks
+ runnerac_shutdown
+ runnerac_stopservers
+ runnerac_test_preprocess
+ runnerac_test_run
+ runnerar
+ runnerar_ready
stderrfilename
stdoutfilename
$DBGCURL
@@ -60,6 +64,14 @@ BEGIN {
);
}
+use B qw(
+ svref_2object
+ );
+use Storable qw(
+ freeze
+ thaw
+ );
+
use pathhelp qw(
exe_ext
);
@@ -105,6 +117,10 @@ my $CURLLOG="$LOGDIR/commands.log"; # all command lines run
my $SERVERLOGS_LOCK="$LOGDIR/serverlogs.lock"; # server logs advisor read lock
my $defserverlogslocktimeout = 2; # timeout to await server logs lock removal
my $defpostcommanddelay = 0; # delay between command and postcheck sections
+my $controllerw; # pipe that controller writes to
+my $runnerr; # pipe that runner reads from
+my $runnerw; # pipe that runner writes to
+my $controllerr; # pipe that controller reads from
# redirected stdout/stderr to these files
@@ -120,7 +136,9 @@ sub stderrfilename {
#######################################################################
# Initialize the runner and prepare it to run tests
-#
+# The runner ID returned by this function must be passed into the other
+# runnerac_* functions
+# Called by controller
sub runner_init {
my ($logdir)=@_;
@@ -138,6 +156,13 @@ sub runner_init {
$ENV{'CURL_HOME'}=$ENV{'HOME'};
$ENV{'XDG_CONFIG_HOME'}=$ENV{'HOME'};
$ENV{'COLUMNS'}=79; # screen width!
+
+ # create pipes for communication with runner
+ pipe $runnerr, $controllerw;
+ pipe $controllerr, $runnerw;
+
+ # There is only one runner right now
+ return "singleton";
}
#######################################################################
@@ -1034,6 +1059,151 @@ sub runner_test_run {
return (0, clearlogs(), \%testtimings, $cmdres, $CURLOUT, $tool, $usedvalgrind);
}
+# Async call runner_clearlocks
+# Called by controller
+sub runnerac_clearlocks {
+ controlleripccall(\&runner_clearlocks, @_);
+}
+
+# Async call runner_shutdown
+# This call does NOT generate an IPC response and must be the last IPC call
+# received.
+# Called by controller
+sub runnerac_shutdown {
+ controlleripccall(\&runner_shutdown, @_);
+
+ # These have no more use
+ close($controllerw);
+ undef $controllerw;
+ close($controllerr);
+ undef $controllerr;
+}
+
+# Async call of runner_stopservers
+# Called by controller
+sub runnerac_stopservers {
+ controlleripccall(\&runner_stopservers, @_);
+}
+
+# Async call of runner_test_preprocess
+# Called by controller
+sub runnerac_test_preprocess {
+ controlleripccall(\&runner_test_preprocess, @_);
+}
+
+# Async call of runner_test_run
+# Called by controller
+sub runnerac_test_run {
+ controlleripccall(\&runner_test_run, @_);
+}
+
+###################################################################
+# Call an arbitrary function via IPC
+# The first argument is the function reference, the second is the runner ID
+# Called by controller (indirectly, via a more specific function)
+sub controlleripccall {
+ my $funcref = shift @_;
+ my $runnerid = shift @_;
+ # Get the name of the function from the reference
+ my $cv = svref_2object($funcref);
+ my $gv = $cv->GV;
+ # Prepend the name to the function arguments so it's marshalled along with them
+ unshift @_, $gv->NAME;
+ # Marshall the arguments into a flat string
+ my $margs = freeze \@_;
+
+ # Send IPC call via pipe
+ syswrite($controllerw, (pack "L", length($margs)) . $margs);
+
+ # Call the remote function
+ # TODO: this will eventually be done in a separate runner process
+ # kicked off by runner_init()
+ ipcrecv();
+}
+
+###################################################################
+# Receive async response of a previous call via IPC
+# The first return value is the runner ID
+# Called by controller
+sub runnerar {
+ my $datalen;
+ if (sysread($controllerr, $datalen, 4) <= 0) {
+ die "error in runnerar\n";
+ }
+ my $len=unpack("L", $datalen);
+ my $buf;
+ if (sysread($controllerr, $buf, $len) <= 0) {
+ die "error in runnerar\n";
+ }
+
+ # Decode response values
+ my $resarrayref = thaw $buf;
+
+ # First argument is runner ID
+ unshift @$resarrayref, "singleton";
+ return @$resarrayref;
+}
+
+###################################################################
+# Returns nonzero if a response from an async call is ready
+# Called by controller
+sub runnerar_ready {
+ my ($blocking) = @_;
+ my $rin = "";
+ vec($rin, fileno($controllerr), 1) = 1;
+ return select(my $rout=$rin, undef, my $eout=$rin, $blocking ? undef : 0);
+}
+
+###################################################################
+# Receive an IPC call in the runner and execute it
+# The IPC is read from the $runnerr pipe and the response is
+# written to the $runnerw pipe
+sub ipcrecv {
+ my $datalen;
+ if (sysread($runnerr, $datalen, 4) <= 0) {
+ die "error in ipcrecv\n";
+ }
+ my $len=unpack("L", $datalen);
+ my $buf;
+ if (sysread($runnerr, $buf, $len) <= 0) {
+ die "error in ipcrecv\n";
+ }
+
+ # Decode the function name and arguments
+ my $argsarrayref = thaw $buf;
+
+ # The name of the function to call is the frist argument
+ my $funcname = shift @$argsarrayref;
+
+ # print "ipcrecv $funcname\n";
+ # Synchronously call the desired function
+ my @res;
+ if($funcname eq "runner_clearlocks") {
+ @res = runner_clearlocks(@$argsarrayref);
+ }
+ elsif($funcname eq "runner_shutdown") {
+ runner_shutdown(@$argsarrayref);
+ # Special case: no response
+ return;
+ }
+ elsif($funcname eq "runner_stopservers") {
+ @res = runner_stopservers(@$argsarrayref);
+ }
+ elsif($funcname eq "runner_test_preprocess") {
+ @res = runner_test_preprocess(@$argsarrayref);
+ }
+ elsif($funcname eq "runner_test_run") {
+ @res = runner_test_run(@$argsarrayref);
+ } else {
+ die "Unknown IPC function $funcname\n";
+ }
+ # print "ipcrecv results\n";
+
+ # Marshall the results to return
+ $buf = freeze \@res;
+
+ syswrite($runnerw, (pack "L", length($buf)) . $buf);
+}
###################################################################
# Kill the server processes that still have lock files in a directory
@@ -1055,5 +1225,14 @@ sub runner_stopservers {
return ($error, $logs);
}
+###################################################################
+# Shut down this runner
+sub runner_shutdown {
+ close($runnerr);
+ undef $runnerr;
+ close($runnerw);
+ undef $runnerw;
+}
+
1;