runtests: spawn a new process for the test runner
When the -j option is given, a new process is spawned in which the test programs are run and from which test servers are started. Only one process can be started at once, but this is sufficient to test that the infrastructure can isolate those functions in a new task. There should be no visible difference between the two modes at the moment. Ref: #10818 Closes #11064
This commit is contained in:
Родитель
d4a1b5b60c
Коммит
38465f9a55
|
@ -85,7 +85,8 @@ our $CURLVERSION=""; # curl's reported version number
|
|||
our $pwd = getcwd(); # current working directory
|
||||
our $srcdir = $ENV{'srcdir'} || '.'; # root of the test source code
|
||||
our $perl="perl -I$srcdir"; # invoke perl like this
|
||||
our $LOGDIR="log"; # root of the log directory
|
||||
our $LOGDIR="log"; # root of the log directory; this will be different for
|
||||
# each runner in multiprocess mode
|
||||
our $LIBDIR="./libtest";
|
||||
our $TESTDIR="$srcdir/data";
|
||||
our $CURL="../src/curl".exe_ext('TOOL'); # what curl binary to run on the tests
|
||||
|
|
|
@ -22,7 +22,15 @@
|
|||
#
|
||||
###########################################################################
|
||||
|
||||
# This module contains entry points to run a single test
|
||||
# This module contains entry points to run a single test. runner_init
|
||||
# determines whether they will run in a separate process or in the process of
|
||||
# the caller. The relevant interface is asynchronous so it will work in either
|
||||
# case. Program arguments are marshalled and then written to the end of a pipe
|
||||
# (in controlleripccall) which is later read from and the arguments
|
||||
# unmarshalled (in ipcrecv) before the desired function is called normally.
|
||||
# The function return values are then marshalled and written into another pipe
|
||||
# (again in ipcrecv) when is later read from and unmarshalled (in runnerar)
|
||||
# before being returned to the caller.
|
||||
|
||||
package runner;
|
||||
|
||||
|
@ -36,6 +44,7 @@ BEGIN {
|
|||
our @EXPORT = qw(
|
||||
checktestcmd
|
||||
prepro
|
||||
readtestkeywords
|
||||
restore_test_env
|
||||
runner_init
|
||||
runnerac_clearlocks
|
||||
|
@ -59,7 +68,6 @@ BEGIN {
|
|||
|
||||
# these are for debugging only
|
||||
our @EXPORT_OK = qw(
|
||||
readtestkeywords
|
||||
singletest_preprocess
|
||||
);
|
||||
}
|
||||
|
@ -99,6 +107,7 @@ use testutil qw(
|
|||
|
||||
#######################################################################
|
||||
# Global variables set elsewhere but used only by this package
|
||||
# These may only be set *before* runner_init is called
|
||||
our $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging
|
||||
our $valgrind_logfile="--log-file"; # the option name for valgrind >=3
|
||||
our $valgrind_tool="--tool=memcheck";
|
||||
|
@ -121,7 +130,8 @@ 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
|
||||
|
||||
my $multiprocess; # nonzero with a separate test runner process
|
||||
my $onerunnerid; # a single runner ID
|
||||
|
||||
# redirected stdout/stderr to these files
|
||||
sub stdoutfilename {
|
||||
|
@ -140,12 +150,9 @@ sub stderrfilename {
|
|||
# runnerac_* functions
|
||||
# Called by controller
|
||||
sub runner_init {
|
||||
my ($logdir)=@_;
|
||||
my ($logdir, $jobs)=@_;
|
||||
|
||||
# Set this directory as ours
|
||||
# TODO: This will need to be uncommented once there are multiple runners
|
||||
#$LOGDIR = $logdir;
|
||||
mkdir("$LOGDIR/$PIDDIR", 0777);
|
||||
$multiprocess = !!$jobs;
|
||||
|
||||
# enable memory debugging if curl is compiled with it
|
||||
$ENV{'CURL_MEMDEBUG'} = "$LOGDIR/$MEMDUMP";
|
||||
|
@ -161,8 +168,58 @@ sub runner_init {
|
|||
pipe $runnerr, $controllerw;
|
||||
pipe $controllerr, $runnerw;
|
||||
|
||||
# There is only one runner right now
|
||||
return "singleton";
|
||||
if($multiprocess) {
|
||||
# Create a separate process in multiprocess mode
|
||||
my $child = fork();
|
||||
if(0 == $child) {
|
||||
# TODO: set up a better signal handler
|
||||
$SIG{INT} = 'IGNORE';
|
||||
$SIG{TERM} = 'IGNORE';
|
||||
|
||||
$onerunnerid = $$;
|
||||
print "Runner $onerunnerid starting\n" if($verbose);
|
||||
|
||||
# Here we are the child (runner).
|
||||
close($controllerw);
|
||||
close($controllerr);
|
||||
|
||||
# Set this directory as ours
|
||||
$LOGDIR = $logdir;
|
||||
mkdir("$LOGDIR/$PIDDIR", 0777);
|
||||
|
||||
# handle IPC calls
|
||||
event_loop();
|
||||
|
||||
# Can't rely on logmsg here in case it's buffered
|
||||
print "Runner $onerunnerid exiting\n" if($verbose);
|
||||
exit 0;
|
||||
}
|
||||
|
||||
# Here we are the parent (controller).
|
||||
close($runnerw);
|
||||
close($runnerr);
|
||||
|
||||
$onerunnerid = $child;
|
||||
|
||||
} else {
|
||||
# Create our pid directory
|
||||
mkdir("$LOGDIR/$PIDDIR", 0777);
|
||||
|
||||
# Don't create a separate process
|
||||
$onerunnerid = "integrated";
|
||||
}
|
||||
|
||||
return $onerunnerid;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# Loop to execute incoming IPC calls until the shutdown call
|
||||
sub event_loop {
|
||||
while () {
|
||||
if(ipcrecv()) {
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
@ -979,6 +1036,11 @@ sub runner_test_preprocess {
|
|||
loadtest("${TESTDIR}/test${testnum}");
|
||||
readtestkeywords();
|
||||
|
||||
###################################################################
|
||||
# Restore environment variables that were modified in a previous run.
|
||||
# Test definition may instruct to (un)set environment vars.
|
||||
restore_test_env(1);
|
||||
|
||||
###################################################################
|
||||
# Start the servers needed to run this test case
|
||||
my ($why, $error) = singletest_startservers($testnum, \%testtimings);
|
||||
|
@ -1115,10 +1177,10 @@ sub controlleripccall {
|
|||
# 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()
|
||||
if(!$multiprocess) {
|
||||
# Call the remote function here in single process mode
|
||||
ipcrecv();
|
||||
}
|
||||
}
|
||||
|
||||
###################################################################
|
||||
|
@ -1140,7 +1202,7 @@ sub runnerar {
|
|||
my $resarrayref = thaw $buf;
|
||||
|
||||
# First argument is runner ID
|
||||
unshift @$resarrayref, "singleton";
|
||||
unshift @$resarrayref, $onerunnerid;
|
||||
return @$resarrayref;
|
||||
}
|
||||
|
||||
|
|
|
@ -174,6 +174,7 @@ my $postmortem; # display detailed info about failed tests
|
|||
my $run_disabled; # run the specific tests even if listed in DISABLED
|
||||
my $scrambleorder;
|
||||
my $randseed = 0;
|
||||
my $jobs = 0;
|
||||
|
||||
# Azure Pipelines specific variables
|
||||
my $AZURE_RUN_ID = 0;
|
||||
|
@ -748,6 +749,10 @@ sub checksystemfeatures {
|
|||
"* System: $hosttype",
|
||||
"* OS: $hostos\n");
|
||||
|
||||
if($jobs) {
|
||||
# Only show if not the default for now
|
||||
logmsg "* Jobs: $jobs\n";
|
||||
}
|
||||
if($feature{"TrackMemory"} && $feature{"threaded-resolver"}) {
|
||||
logmsg("*\n",
|
||||
"*** DISABLES memory tracking when using threaded resolver\n",
|
||||
|
@ -1633,7 +1638,6 @@ sub singletest {
|
|||
|
||||
if($singletest_state == ST_INIT) {
|
||||
my $logdir = getlogdir($testnum);
|
||||
|
||||
# first, remove all lingering log files
|
||||
if(!cleardir($logdir) && $clearlocks) {
|
||||
runnerac_clearlocks($runnerid, $logdir);
|
||||
|
@ -1661,7 +1665,7 @@ sub singletest {
|
|||
# Test definition may instruct to (un)set environment vars.
|
||||
# This is done this early so that leftover variables don't affect
|
||||
# starting servers or CI registration.
|
||||
restore_test_env(1);
|
||||
# restore_test_env(1);
|
||||
|
||||
###################################################################
|
||||
# Load test file so CI registration can get the right data before the
|
||||
|
@ -1687,6 +1691,11 @@ sub singletest {
|
|||
}
|
||||
updatetesttimings($testnum, %$testtimings);
|
||||
|
||||
#######################################################################
|
||||
# Load test file for this test number
|
||||
my $logdir = getlogdir($testnum);
|
||||
loadtest("${logdir}/test${testnum}");
|
||||
|
||||
#######################################################################
|
||||
# Print the test name and count tests
|
||||
$error = singletest_count($testnum, $why);
|
||||
|
@ -1739,6 +1748,12 @@ sub singletest {
|
|||
|
||||
#######################################################################
|
||||
# Verify that the test succeeded
|
||||
#
|
||||
# Load test file for this test number
|
||||
my $logdir = getlogdir($testnum);
|
||||
loadtest("${logdir}/test${testnum}");
|
||||
readtestkeywords();
|
||||
|
||||
$error = singletest_check($runnerid, $testnum, $cmdres, $CURLOUT, $tool, $usedvalgrind);
|
||||
if($error == -1) {
|
||||
my $err = ignoreresultcode($testnum);
|
||||
|
@ -2076,6 +2091,14 @@ while(@ARGV) {
|
|||
# lists the test case names only
|
||||
$listonly=1;
|
||||
}
|
||||
elsif($ARGV[0] =~ /^-j(.*)/) {
|
||||
# parallel jobs
|
||||
$jobs=1;
|
||||
my $xtra = $1;
|
||||
if($xtra =~ s/(\d+)$//) {
|
||||
$jobs = $1;
|
||||
}
|
||||
}
|
||||
elsif($ARGV[0] eq "-k") {
|
||||
# keep stdout and stderr files after tests
|
||||
$keepoutfiles=1;
|
||||
|
@ -2133,6 +2156,7 @@ Usage: runtests.pl [options] [test selection(s)]
|
|||
-g run the test case with gdb
|
||||
-gw run the test case with gdb as a windowed application
|
||||
-h this help text
|
||||
-j[N] spawn this number of processes to run tests (default 0, max. 1)
|
||||
-k keep stdout and stderr files present after tests
|
||||
-L path require an additional perl library file to replace certain functions
|
||||
-l list all test case names/descriptions
|
||||
|
@ -2291,8 +2315,10 @@ mkdir($LOGDIR, 0777);
|
|||
#
|
||||
|
||||
get_disttests();
|
||||
# Disable buffered logging for now
|
||||
setlogfunc(\&logmsg);
|
||||
if(!$jobs) {
|
||||
# Disable buffered logging with only one test job
|
||||
setlogfunc(\&logmsg);
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# Output curl version and host info being tested
|
||||
|
@ -2560,7 +2586,7 @@ citest_starttestrun();
|
|||
# Initialize the runner to prepare to run tests
|
||||
cleardir($LOGDIR);
|
||||
mkdir($LOGDIR, 0777);
|
||||
my $runnerid = runner_init($LOGDIR);
|
||||
my $runnerid = runner_init($LOGDIR, $jobs);
|
||||
|
||||
#######################################################################
|
||||
# The main test-loop
|
||||
|
|
Загрузка…
Ссылка в новой задаче