xref: /aosp_15_r20/external/curl/tests/runner.pm (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker#***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker#                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker#  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker#                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker#                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker#                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker#
8*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker#
10*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker#
14*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker#
18*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker#
21*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker#
23*6236dae4SAndroid Build Coastguard Worker###########################################################################
24*6236dae4SAndroid Build Coastguard Worker
25*6236dae4SAndroid Build Coastguard Worker# This module contains entry points to run a single test. runner_init
26*6236dae4SAndroid Build Coastguard Worker# determines whether they will run in a separate process or in the process of
27*6236dae4SAndroid Build Coastguard Worker# the caller. The relevant interface is asynchronous so it will work in either
28*6236dae4SAndroid Build Coastguard Worker# case. Program arguments are marshalled and then written to the end of a pipe
29*6236dae4SAndroid Build Coastguard Worker# (in controlleripccall) which is later read from and the arguments
30*6236dae4SAndroid Build Coastguard Worker# unmarshalled (in ipcrecv) before the desired function is called normally.
31*6236dae4SAndroid Build Coastguard Worker# The function return values are then marshalled and written into another pipe
32*6236dae4SAndroid Build Coastguard Worker# (again in ipcrecv) when is later read from and unmarshalled (in runnerar)
33*6236dae4SAndroid Build Coastguard Worker# before being returned to the caller.
34*6236dae4SAndroid Build Coastguard Worker
35*6236dae4SAndroid Build Coastguard Workerpackage runner;
36*6236dae4SAndroid Build Coastguard Worker
37*6236dae4SAndroid Build Coastguard Workeruse strict;
38*6236dae4SAndroid Build Coastguard Workeruse warnings;
39*6236dae4SAndroid Build Coastguard Workeruse 5.006;
40*6236dae4SAndroid Build Coastguard Worker
41*6236dae4SAndroid Build Coastguard WorkerBEGIN {
42*6236dae4SAndroid Build Coastguard Worker    use base qw(Exporter);
43*6236dae4SAndroid Build Coastguard Worker
44*6236dae4SAndroid Build Coastguard Worker    our @EXPORT = qw(
45*6236dae4SAndroid Build Coastguard Worker        checktestcmd
46*6236dae4SAndroid Build Coastguard Worker        prepro
47*6236dae4SAndroid Build Coastguard Worker        readtestkeywords
48*6236dae4SAndroid Build Coastguard Worker        restore_test_env
49*6236dae4SAndroid Build Coastguard Worker        runner_init
50*6236dae4SAndroid Build Coastguard Worker        runnerac_clearlocks
51*6236dae4SAndroid Build Coastguard Worker        runnerac_shutdown
52*6236dae4SAndroid Build Coastguard Worker        runnerac_stopservers
53*6236dae4SAndroid Build Coastguard Worker        runnerac_test_preprocess
54*6236dae4SAndroid Build Coastguard Worker        runnerac_test_run
55*6236dae4SAndroid Build Coastguard Worker        runnerar
56*6236dae4SAndroid Build Coastguard Worker        runnerar_ready
57*6236dae4SAndroid Build Coastguard Worker        stderrfilename
58*6236dae4SAndroid Build Coastguard Worker        stdoutfilename
59*6236dae4SAndroid Build Coastguard Worker        $DBGCURL
60*6236dae4SAndroid Build Coastguard Worker        $gdb
61*6236dae4SAndroid Build Coastguard Worker        $gdbthis
62*6236dae4SAndroid Build Coastguard Worker        $gdbxwin
63*6236dae4SAndroid Build Coastguard Worker        $shallow
64*6236dae4SAndroid Build Coastguard Worker        $tortalloc
65*6236dae4SAndroid Build Coastguard Worker        $valgrind_logfile
66*6236dae4SAndroid Build Coastguard Worker        $valgrind_tool
67*6236dae4SAndroid Build Coastguard Worker    );
68*6236dae4SAndroid Build Coastguard Worker
69*6236dae4SAndroid Build Coastguard Worker    # these are for debugging only
70*6236dae4SAndroid Build Coastguard Worker    our @EXPORT_OK = qw(
71*6236dae4SAndroid Build Coastguard Worker        singletest_preprocess
72*6236dae4SAndroid Build Coastguard Worker    );
73*6236dae4SAndroid Build Coastguard Worker}
74*6236dae4SAndroid Build Coastguard Worker
75*6236dae4SAndroid Build Coastguard Workeruse B qw(
76*6236dae4SAndroid Build Coastguard Worker    svref_2object
77*6236dae4SAndroid Build Coastguard Worker    );
78*6236dae4SAndroid Build Coastguard Workeruse Storable qw(
79*6236dae4SAndroid Build Coastguard Worker    freeze
80*6236dae4SAndroid Build Coastguard Worker    thaw
81*6236dae4SAndroid Build Coastguard Worker    );
82*6236dae4SAndroid Build Coastguard Worker
83*6236dae4SAndroid Build Coastguard Workeruse pathhelp qw(
84*6236dae4SAndroid Build Coastguard Worker    exe_ext
85*6236dae4SAndroid Build Coastguard Worker    );
86*6236dae4SAndroid Build Coastguard Workeruse processhelp qw(
87*6236dae4SAndroid Build Coastguard Worker    portable_sleep
88*6236dae4SAndroid Build Coastguard Worker    );
89*6236dae4SAndroid Build Coastguard Workeruse servers qw(
90*6236dae4SAndroid Build Coastguard Worker    checkcmd
91*6236dae4SAndroid Build Coastguard Worker    clearlocks
92*6236dae4SAndroid Build Coastguard Worker    initserverconfig
93*6236dae4SAndroid Build Coastguard Worker    serverfortest
94*6236dae4SAndroid Build Coastguard Worker    stopserver
95*6236dae4SAndroid Build Coastguard Worker    stopservers
96*6236dae4SAndroid Build Coastguard Worker    subvariables
97*6236dae4SAndroid Build Coastguard Worker    );
98*6236dae4SAndroid Build Coastguard Workeruse getpart;
99*6236dae4SAndroid Build Coastguard Workeruse globalconfig;
100*6236dae4SAndroid Build Coastguard Workeruse testutil qw(
101*6236dae4SAndroid Build Coastguard Worker    clearlogs
102*6236dae4SAndroid Build Coastguard Worker    logmsg
103*6236dae4SAndroid Build Coastguard Worker    runclient
104*6236dae4SAndroid Build Coastguard Worker    shell_quote
105*6236dae4SAndroid Build Coastguard Worker    subbase64
106*6236dae4SAndroid Build Coastguard Worker    subsha256base64file
107*6236dae4SAndroid Build Coastguard Worker    substrippemfile
108*6236dae4SAndroid Build Coastguard Worker    subnewlines
109*6236dae4SAndroid Build Coastguard Worker    );
110*6236dae4SAndroid Build Coastguard Workeruse valgrind;
111*6236dae4SAndroid Build Coastguard Worker
112*6236dae4SAndroid Build Coastguard Worker
113*6236dae4SAndroid Build Coastguard Worker#######################################################################
114*6236dae4SAndroid Build Coastguard Worker# Global variables set elsewhere but used only by this package
115*6236dae4SAndroid Build Coastguard Worker# These may only be set *before* runner_init is called
116*6236dae4SAndroid Build Coastguard Workerour $DBGCURL=$CURL; #"../src/.libs/curl";  # alternative for debugging
117*6236dae4SAndroid Build Coastguard Workerour $valgrind_logfile="--log-file";  # the option name for valgrind >=3
118*6236dae4SAndroid Build Coastguard Workerour $valgrind_tool="--tool=memcheck";
119*6236dae4SAndroid Build Coastguard Workerour $gdb = checktestcmd("gdb");
120*6236dae4SAndroid Build Coastguard Workerour $gdbthis = 0;  # run test case with debugger (gdb or lldb)
121*6236dae4SAndroid Build Coastguard Workerour $gdbxwin;      # use windowed gdb when using gdb
122*6236dae4SAndroid Build Coastguard Worker
123*6236dae4SAndroid Build Coastguard Worker# torture test variables
124*6236dae4SAndroid Build Coastguard Workerour $shallow;
125*6236dae4SAndroid Build Coastguard Workerour $tortalloc;
126*6236dae4SAndroid Build Coastguard Worker
127*6236dae4SAndroid Build Coastguard Worker# local variables
128*6236dae4SAndroid Build Coastguard Workermy %oldenv;       # environment variables before test is started
129*6236dae4SAndroid Build Coastguard Workermy $UNITDIR="./unit";
130*6236dae4SAndroid Build Coastguard Workermy $CURLLOG="$LOGDIR/commands.log"; # all command lines run
131*6236dae4SAndroid Build Coastguard Workermy $defserverlogslocktimeout = 5; # timeout to await server logs lock removal
132*6236dae4SAndroid Build Coastguard Workermy $defpostcommanddelay = 0; # delay between command and postcheck sections
133*6236dae4SAndroid Build Coastguard Workermy $multiprocess;   # nonzero with a separate test runner process
134*6236dae4SAndroid Build Coastguard Worker
135*6236dae4SAndroid Build Coastguard Worker# pipes
136*6236dae4SAndroid Build Coastguard Workermy $runnerr;        # pipe that runner reads from
137*6236dae4SAndroid Build Coastguard Workermy $runnerw;        # pipe that runner writes to
138*6236dae4SAndroid Build Coastguard Worker
139*6236dae4SAndroid Build Coastguard Worker# per-runner variables, indexed by runner ID; these are used by controller only
140*6236dae4SAndroid Build Coastguard Workermy %controllerr;    # pipe that controller reads from
141*6236dae4SAndroid Build Coastguard Workermy %controllerw;    # pipe that controller writes to
142*6236dae4SAndroid Build Coastguard Worker
143*6236dae4SAndroid Build Coastguard Worker# redirected stdout/stderr to these files
144*6236dae4SAndroid Build Coastguard Workersub stdoutfilename {
145*6236dae4SAndroid Build Coastguard Worker    my ($logdir, $testnum)=@_;
146*6236dae4SAndroid Build Coastguard Worker    return "$logdir/stdout$testnum";
147*6236dae4SAndroid Build Coastguard Worker}
148*6236dae4SAndroid Build Coastguard Worker
149*6236dae4SAndroid Build Coastguard Workersub stderrfilename {
150*6236dae4SAndroid Build Coastguard Worker    my ($logdir, $testnum)=@_;
151*6236dae4SAndroid Build Coastguard Worker    return "$logdir/stderr$testnum";
152*6236dae4SAndroid Build Coastguard Worker}
153*6236dae4SAndroid Build Coastguard Worker
154*6236dae4SAndroid Build Coastguard Worker#######################################################################
155*6236dae4SAndroid Build Coastguard Worker# Initialize the runner and prepare it to run tests
156*6236dae4SAndroid Build Coastguard Worker# The runner ID returned by this function must be passed into the other
157*6236dae4SAndroid Build Coastguard Worker# runnerac_* functions
158*6236dae4SAndroid Build Coastguard Worker# Called by controller
159*6236dae4SAndroid Build Coastguard Workersub runner_init {
160*6236dae4SAndroid Build Coastguard Worker    my ($logdir, $jobs)=@_;
161*6236dae4SAndroid Build Coastguard Worker
162*6236dae4SAndroid Build Coastguard Worker    $multiprocess = !!$jobs;
163*6236dae4SAndroid Build Coastguard Worker
164*6236dae4SAndroid Build Coastguard Worker    # enable memory debugging if curl is compiled with it
165*6236dae4SAndroid Build Coastguard Worker    $ENV{'CURL_MEMDEBUG'} = "$logdir/$MEMDUMP";
166*6236dae4SAndroid Build Coastguard Worker    $ENV{'CURL_ENTROPY'}="12345678";
167*6236dae4SAndroid Build Coastguard Worker    $ENV{'CURL_FORCETIME'}=1; # for debug NTLM magic
168*6236dae4SAndroid Build Coastguard Worker    $ENV{'CURL_GLOBAL_INIT'}=1; # debug curl_global_init/cleanup use
169*6236dae4SAndroid Build Coastguard Worker    $ENV{'HOME'}=$pwd;
170*6236dae4SAndroid Build Coastguard Worker    $ENV{'CURL_HOME'}=$ENV{'HOME'};
171*6236dae4SAndroid Build Coastguard Worker    $ENV{'XDG_CONFIG_HOME'}=$ENV{'HOME'};
172*6236dae4SAndroid Build Coastguard Worker    $ENV{'COLUMNS'}=79; # screen width!
173*6236dae4SAndroid Build Coastguard Worker
174*6236dae4SAndroid Build Coastguard Worker    # Incorporate the $logdir into the random seed and re-seed the PRNG.
175*6236dae4SAndroid Build Coastguard Worker    # This gives each runner a unique yet consistent seed which provides
176*6236dae4SAndroid Build Coastguard Worker    # more unique port number selection in each runner, yet is deterministic
177*6236dae4SAndroid Build Coastguard Worker    # across runs.
178*6236dae4SAndroid Build Coastguard Worker    $randseed += unpack('%16C*', $logdir);
179*6236dae4SAndroid Build Coastguard Worker    srand $randseed;
180*6236dae4SAndroid Build Coastguard Worker
181*6236dae4SAndroid Build Coastguard Worker    # create pipes for communication with runner
182*6236dae4SAndroid Build Coastguard Worker    my ($thisrunnerr, $thiscontrollerw, $thiscontrollerr, $thisrunnerw);
183*6236dae4SAndroid Build Coastguard Worker    pipe $thisrunnerr, $thiscontrollerw;
184*6236dae4SAndroid Build Coastguard Worker    pipe $thiscontrollerr, $thisrunnerw;
185*6236dae4SAndroid Build Coastguard Worker
186*6236dae4SAndroid Build Coastguard Worker    my $thisrunnerid;
187*6236dae4SAndroid Build Coastguard Worker    if($multiprocess) {
188*6236dae4SAndroid Build Coastguard Worker        # Create a separate process in multiprocess mode
189*6236dae4SAndroid Build Coastguard Worker        my $child = fork();
190*6236dae4SAndroid Build Coastguard Worker        if(0 == $child) {
191*6236dae4SAndroid Build Coastguard Worker            # TODO: set up better signal handlers
192*6236dae4SAndroid Build Coastguard Worker            $SIG{INT} = 'IGNORE';
193*6236dae4SAndroid Build Coastguard Worker            $SIG{TERM} = 'IGNORE';
194*6236dae4SAndroid Build Coastguard Worker            eval {
195*6236dae4SAndroid Build Coastguard Worker                # some msys2 perl versions don't define SIGUSR1, also missing from Win32 Perl
196*6236dae4SAndroid Build Coastguard Worker                $SIG{USR1} = 'IGNORE';
197*6236dae4SAndroid Build Coastguard Worker            };
198*6236dae4SAndroid Build Coastguard Worker
199*6236dae4SAndroid Build Coastguard Worker            $thisrunnerid = $$;
200*6236dae4SAndroid Build Coastguard Worker            print "Runner $thisrunnerid starting\n" if($verbose);
201*6236dae4SAndroid Build Coastguard Worker
202*6236dae4SAndroid Build Coastguard Worker            # Here we are the child (runner).
203*6236dae4SAndroid Build Coastguard Worker            close($thiscontrollerw);
204*6236dae4SAndroid Build Coastguard Worker            close($thiscontrollerr);
205*6236dae4SAndroid Build Coastguard Worker            $runnerr = $thisrunnerr;
206*6236dae4SAndroid Build Coastguard Worker            $runnerw = $thisrunnerw;
207*6236dae4SAndroid Build Coastguard Worker
208*6236dae4SAndroid Build Coastguard Worker            # Set this directory as ours
209*6236dae4SAndroid Build Coastguard Worker            $LOGDIR = $logdir;
210*6236dae4SAndroid Build Coastguard Worker            mkdir("$LOGDIR/$PIDDIR", 0777);
211*6236dae4SAndroid Build Coastguard Worker            mkdir("$LOGDIR/$LOCKDIR", 0777);
212*6236dae4SAndroid Build Coastguard Worker
213*6236dae4SAndroid Build Coastguard Worker            # Initialize various server variables
214*6236dae4SAndroid Build Coastguard Worker            initserverconfig();
215*6236dae4SAndroid Build Coastguard Worker
216*6236dae4SAndroid Build Coastguard Worker            # handle IPC calls
217*6236dae4SAndroid Build Coastguard Worker            event_loop();
218*6236dae4SAndroid Build Coastguard Worker
219*6236dae4SAndroid Build Coastguard Worker            # Can't rely on logmsg here in case it's buffered
220*6236dae4SAndroid Build Coastguard Worker            print "Runner $thisrunnerid exiting\n" if($verbose);
221*6236dae4SAndroid Build Coastguard Worker
222*6236dae4SAndroid Build Coastguard Worker            # To reach this point, either the controller has sent
223*6236dae4SAndroid Build Coastguard Worker            # runnerac_stopservers() and runnerac_shutdown() or we have called
224*6236dae4SAndroid Build Coastguard Worker            # runnerabort(). In both cases, there are no more of our servers
225*6236dae4SAndroid Build Coastguard Worker            # running and we can safely exit.
226*6236dae4SAndroid Build Coastguard Worker            exit 0;
227*6236dae4SAndroid Build Coastguard Worker        }
228*6236dae4SAndroid Build Coastguard Worker
229*6236dae4SAndroid Build Coastguard Worker        # Here we are the parent (controller).
230*6236dae4SAndroid Build Coastguard Worker        close($thisrunnerw);
231*6236dae4SAndroid Build Coastguard Worker        close($thisrunnerr);
232*6236dae4SAndroid Build Coastguard Worker
233*6236dae4SAndroid Build Coastguard Worker        $thisrunnerid = $child;
234*6236dae4SAndroid Build Coastguard Worker
235*6236dae4SAndroid Build Coastguard Worker    } else {
236*6236dae4SAndroid Build Coastguard Worker        # Create our pid directory
237*6236dae4SAndroid Build Coastguard Worker        mkdir("$LOGDIR/$PIDDIR", 0777);
238*6236dae4SAndroid Build Coastguard Worker
239*6236dae4SAndroid Build Coastguard Worker        # Don't create a separate process
240*6236dae4SAndroid Build Coastguard Worker        $thisrunnerid = "integrated";
241*6236dae4SAndroid Build Coastguard Worker    }
242*6236dae4SAndroid Build Coastguard Worker
243*6236dae4SAndroid Build Coastguard Worker    $controllerw{$thisrunnerid} = $thiscontrollerw;
244*6236dae4SAndroid Build Coastguard Worker    $runnerr = $thisrunnerr;
245*6236dae4SAndroid Build Coastguard Worker    $runnerw = $thisrunnerw;
246*6236dae4SAndroid Build Coastguard Worker    $controllerr{$thisrunnerid} = $thiscontrollerr;
247*6236dae4SAndroid Build Coastguard Worker
248*6236dae4SAndroid Build Coastguard Worker    return $thisrunnerid;
249*6236dae4SAndroid Build Coastguard Worker}
250*6236dae4SAndroid Build Coastguard Worker
251*6236dae4SAndroid Build Coastguard Worker#######################################################################
252*6236dae4SAndroid Build Coastguard Worker# Loop to execute incoming IPC calls until the shutdown call
253*6236dae4SAndroid Build Coastguard Workersub event_loop {
254*6236dae4SAndroid Build Coastguard Worker    while () {
255*6236dae4SAndroid Build Coastguard Worker        if(ipcrecv()) {
256*6236dae4SAndroid Build Coastguard Worker            last;
257*6236dae4SAndroid Build Coastguard Worker        }
258*6236dae4SAndroid Build Coastguard Worker    }
259*6236dae4SAndroid Build Coastguard Worker}
260*6236dae4SAndroid Build Coastguard Worker
261*6236dae4SAndroid Build Coastguard Worker#######################################################################
262*6236dae4SAndroid Build Coastguard Worker# Check for a command in the PATH of the machine running curl.
263*6236dae4SAndroid Build Coastguard Worker#
264*6236dae4SAndroid Build Coastguard Workersub checktestcmd {
265*6236dae4SAndroid Build Coastguard Worker    my ($cmd)=@_;
266*6236dae4SAndroid Build Coastguard Worker    my @testpaths=("$LIBDIR/.libs", "$LIBDIR");
267*6236dae4SAndroid Build Coastguard Worker    return checkcmd($cmd, @testpaths);
268*6236dae4SAndroid Build Coastguard Worker}
269*6236dae4SAndroid Build Coastguard Worker
270*6236dae4SAndroid Build Coastguard Worker# See if Valgrind should actually be used
271*6236dae4SAndroid Build Coastguard Workersub use_valgrind {
272*6236dae4SAndroid Build Coastguard Worker    if($valgrind) {
273*6236dae4SAndroid Build Coastguard Worker        my @valgrindoption = getpart("verify", "valgrind");
274*6236dae4SAndroid Build Coastguard Worker        if((!@valgrindoption) || ($valgrindoption[0] !~ /disable/)) {
275*6236dae4SAndroid Build Coastguard Worker            return 1;
276*6236dae4SAndroid Build Coastguard Worker        }
277*6236dae4SAndroid Build Coastguard Worker    }
278*6236dae4SAndroid Build Coastguard Worker    return 0;
279*6236dae4SAndroid Build Coastguard Worker}
280*6236dae4SAndroid Build Coastguard Worker
281*6236dae4SAndroid Build Coastguard Worker# Massage the command result code into a useful form
282*6236dae4SAndroid Build Coastguard Workersub normalize_cmdres {
283*6236dae4SAndroid Build Coastguard Worker    my $cmdres = $_[0];
284*6236dae4SAndroid Build Coastguard Worker    my $signal_num  = $cmdres & 127;
285*6236dae4SAndroid Build Coastguard Worker    my $dumped_core = $cmdres & 128;
286*6236dae4SAndroid Build Coastguard Worker
287*6236dae4SAndroid Build Coastguard Worker    if(!$anyway && ($signal_num || $dumped_core)) {
288*6236dae4SAndroid Build Coastguard Worker        $cmdres = 1000;
289*6236dae4SAndroid Build Coastguard Worker    }
290*6236dae4SAndroid Build Coastguard Worker    else {
291*6236dae4SAndroid Build Coastguard Worker        $cmdres >>= 8;
292*6236dae4SAndroid Build Coastguard Worker        $cmdres = (2000 + $signal_num) if($signal_num && !$cmdres);
293*6236dae4SAndroid Build Coastguard Worker    }
294*6236dae4SAndroid Build Coastguard Worker    return ($cmdres, $dumped_core);
295*6236dae4SAndroid Build Coastguard Worker}
296*6236dae4SAndroid Build Coastguard Worker
297*6236dae4SAndroid Build Coastguard Worker# 'prepro' processes the input array and replaces %-variables in the array
298*6236dae4SAndroid Build Coastguard Worker# etc. Returns the processed version of the array
299*6236dae4SAndroid Build Coastguard Workersub prepro {
300*6236dae4SAndroid Build Coastguard Worker    my $testnum = shift;
301*6236dae4SAndroid Build Coastguard Worker    my (@entiretest) = @_;
302*6236dae4SAndroid Build Coastguard Worker    my $show = 1;
303*6236dae4SAndroid Build Coastguard Worker    my @out;
304*6236dae4SAndroid Build Coastguard Worker    my $data_crlf;
305*6236dae4SAndroid Build Coastguard Worker    my @pshow;
306*6236dae4SAndroid Build Coastguard Worker    my @altshow;
307*6236dae4SAndroid Build Coastguard Worker    my $plvl;
308*6236dae4SAndroid Build Coastguard Worker    my $line;
309*6236dae4SAndroid Build Coastguard Worker    for my $s (@entiretest) {
310*6236dae4SAndroid Build Coastguard Worker        my $f = $s;
311*6236dae4SAndroid Build Coastguard Worker        $line++;
312*6236dae4SAndroid Build Coastguard Worker        if($s =~ /^ *%if ([A-Za-z0-9!_-]*)/) {
313*6236dae4SAndroid Build Coastguard Worker            my $cond = $1;
314*6236dae4SAndroid Build Coastguard Worker            my $rev = 0;
315*6236dae4SAndroid Build Coastguard Worker
316*6236dae4SAndroid Build Coastguard Worker            if($cond =~ /^!(.*)/) {
317*6236dae4SAndroid Build Coastguard Worker                $cond = $1;
318*6236dae4SAndroid Build Coastguard Worker                $rev = 1;
319*6236dae4SAndroid Build Coastguard Worker            }
320*6236dae4SAndroid Build Coastguard Worker            $rev ^= $feature{$cond} ? 1 : 0;
321*6236dae4SAndroid Build Coastguard Worker            push @pshow, $show; # push the previous state
322*6236dae4SAndroid Build Coastguard Worker            $plvl++;
323*6236dae4SAndroid Build Coastguard Worker            if($show) {
324*6236dae4SAndroid Build Coastguard Worker                # only if this was showing before we can allow the alternative
325*6236dae4SAndroid Build Coastguard Worker                # to go showing as well
326*6236dae4SAndroid Build Coastguard Worker                push @altshow, $rev ^ 1; # push the reversed show state
327*6236dae4SAndroid Build Coastguard Worker            }
328*6236dae4SAndroid Build Coastguard Worker            else {
329*6236dae4SAndroid Build Coastguard Worker                push @altshow, 0; # the alt should still hide
330*6236dae4SAndroid Build Coastguard Worker            }
331*6236dae4SAndroid Build Coastguard Worker            if($show) {
332*6236dae4SAndroid Build Coastguard Worker                # we only allow show if already showing
333*6236dae4SAndroid Build Coastguard Worker                $show = $rev;
334*6236dae4SAndroid Build Coastguard Worker            }
335*6236dae4SAndroid Build Coastguard Worker            next;
336*6236dae4SAndroid Build Coastguard Worker        }
337*6236dae4SAndroid Build Coastguard Worker        elsif($s =~ /^ *%else/) {
338*6236dae4SAndroid Build Coastguard Worker            if(!$plvl) {
339*6236dae4SAndroid Build Coastguard Worker                print STDERR "error: test$testnum:$line: %else no %if\n";
340*6236dae4SAndroid Build Coastguard Worker                last;
341*6236dae4SAndroid Build Coastguard Worker            }
342*6236dae4SAndroid Build Coastguard Worker            $show = pop @altshow;
343*6236dae4SAndroid Build Coastguard Worker            push @altshow, $show; # put it back for consistency
344*6236dae4SAndroid Build Coastguard Worker            next;
345*6236dae4SAndroid Build Coastguard Worker        }
346*6236dae4SAndroid Build Coastguard Worker        elsif($s =~ /^ *%endif/) {
347*6236dae4SAndroid Build Coastguard Worker            if(!$plvl--) {
348*6236dae4SAndroid Build Coastguard Worker                print STDERR "error: test$testnum:$line: %endif had no %if\n";
349*6236dae4SAndroid Build Coastguard Worker                last;
350*6236dae4SAndroid Build Coastguard Worker            }
351*6236dae4SAndroid Build Coastguard Worker            $show = pop @pshow;
352*6236dae4SAndroid Build Coastguard Worker            pop @altshow; # not used here but we must pop it
353*6236dae4SAndroid Build Coastguard Worker            next;
354*6236dae4SAndroid Build Coastguard Worker        }
355*6236dae4SAndroid Build Coastguard Worker        if($show) {
356*6236dae4SAndroid Build Coastguard Worker            # The processor does CRLF replacements in the <data*> sections if
357*6236dae4SAndroid Build Coastguard Worker            # necessary since those parts might be read by separate servers.
358*6236dae4SAndroid Build Coastguard Worker            if($s =~ /^ *<data(.*)\>/) {
359*6236dae4SAndroid Build Coastguard Worker                if($1 =~ /crlf="yes"/ ||
360*6236dae4SAndroid Build Coastguard Worker                   ($feature{"hyper"} && ($keywords{"HTTP"} || $keywords{"HTTPS"}))) {
361*6236dae4SAndroid Build Coastguard Worker                    $data_crlf = 1;
362*6236dae4SAndroid Build Coastguard Worker                }
363*6236dae4SAndroid Build Coastguard Worker            }
364*6236dae4SAndroid Build Coastguard Worker            elsif(($s =~ /^ *<\/data/) && $data_crlf) {
365*6236dae4SAndroid Build Coastguard Worker                $data_crlf = 0;
366*6236dae4SAndroid Build Coastguard Worker            }
367*6236dae4SAndroid Build Coastguard Worker            subvariables(\$s, $testnum, "%");
368*6236dae4SAndroid Build Coastguard Worker            subbase64(\$s);
369*6236dae4SAndroid Build Coastguard Worker            subsha256base64file(\$s);
370*6236dae4SAndroid Build Coastguard Worker            substrippemfile(\$s);
371*6236dae4SAndroid Build Coastguard Worker            subnewlines(0, \$s) if($data_crlf);
372*6236dae4SAndroid Build Coastguard Worker            push @out, $s;
373*6236dae4SAndroid Build Coastguard Worker        }
374*6236dae4SAndroid Build Coastguard Worker    }
375*6236dae4SAndroid Build Coastguard Worker    return @out;
376*6236dae4SAndroid Build Coastguard Worker}
377*6236dae4SAndroid Build Coastguard Worker
378*6236dae4SAndroid Build Coastguard Worker
379*6236dae4SAndroid Build Coastguard Worker#######################################################################
380*6236dae4SAndroid Build Coastguard Worker# Load test keywords into %keywords hash
381*6236dae4SAndroid Build Coastguard Worker#
382*6236dae4SAndroid Build Coastguard Workersub readtestkeywords {
383*6236dae4SAndroid Build Coastguard Worker    my @info_keywords = getpart("info", "keywords");
384*6236dae4SAndroid Build Coastguard Worker
385*6236dae4SAndroid Build Coastguard Worker    # Clear the list of keywords from the last test
386*6236dae4SAndroid Build Coastguard Worker    %keywords = ();
387*6236dae4SAndroid Build Coastguard Worker    for my $k (@info_keywords) {
388*6236dae4SAndroid Build Coastguard Worker        chomp $k;
389*6236dae4SAndroid Build Coastguard Worker        $keywords{$k} = 1;
390*6236dae4SAndroid Build Coastguard Worker    }
391*6236dae4SAndroid Build Coastguard Worker}
392*6236dae4SAndroid Build Coastguard Worker
393*6236dae4SAndroid Build Coastguard Worker
394*6236dae4SAndroid Build Coastguard Worker#######################################################################
395*6236dae4SAndroid Build Coastguard Worker# Return a list of log locks that still exist
396*6236dae4SAndroid Build Coastguard Worker#
397*6236dae4SAndroid Build Coastguard Workersub logslocked {
398*6236dae4SAndroid Build Coastguard Worker    opendir(my $lockdir, "$LOGDIR/$LOCKDIR");
399*6236dae4SAndroid Build Coastguard Worker    my @locks;
400*6236dae4SAndroid Build Coastguard Worker    foreach (readdir $lockdir) {
401*6236dae4SAndroid Build Coastguard Worker        if(/^(.*)\.lock$/) {
402*6236dae4SAndroid Build Coastguard Worker            push @locks, $1;
403*6236dae4SAndroid Build Coastguard Worker        }
404*6236dae4SAndroid Build Coastguard Worker    }
405*6236dae4SAndroid Build Coastguard Worker    return @locks;
406*6236dae4SAndroid Build Coastguard Worker}
407*6236dae4SAndroid Build Coastguard Worker
408*6236dae4SAndroid Build Coastguard Worker#######################################################################
409*6236dae4SAndroid Build Coastguard Worker# Wait log locks to be unlocked
410*6236dae4SAndroid Build Coastguard Worker#
411*6236dae4SAndroid Build Coastguard Workersub waitlockunlock {
412*6236dae4SAndroid Build Coastguard Worker    # If a server logs advisor read lock file exists, it is an indication
413*6236dae4SAndroid Build Coastguard Worker    # that the server has not yet finished writing out all its log files,
414*6236dae4SAndroid Build Coastguard Worker    # including server request log files used for protocol verification.
415*6236dae4SAndroid Build Coastguard Worker    # So, if the lock file exists the script waits here a certain amount
416*6236dae4SAndroid Build Coastguard Worker    # of time until the server removes it, or the given time expires.
417*6236dae4SAndroid Build Coastguard Worker    my $serverlogslocktimeout = shift;
418*6236dae4SAndroid Build Coastguard Worker
419*6236dae4SAndroid Build Coastguard Worker    if($serverlogslocktimeout) {
420*6236dae4SAndroid Build Coastguard Worker        my $lockretry = $serverlogslocktimeout * 20;
421*6236dae4SAndroid Build Coastguard Worker        my @locks;
422*6236dae4SAndroid Build Coastguard Worker        while((@locks = logslocked()) && $lockretry--) {
423*6236dae4SAndroid Build Coastguard Worker            portable_sleep(0.05);
424*6236dae4SAndroid Build Coastguard Worker        }
425*6236dae4SAndroid Build Coastguard Worker        if(($lockretry < 0) &&
426*6236dae4SAndroid Build Coastguard Worker           ($serverlogslocktimeout >= $defserverlogslocktimeout)) {
427*6236dae4SAndroid Build Coastguard Worker            logmsg "Warning: server logs lock timeout ",
428*6236dae4SAndroid Build Coastguard Worker                   "($serverlogslocktimeout seconds) expired (locks: " .
429*6236dae4SAndroid Build Coastguard Worker                   join(", ", @locks) . ")\n";
430*6236dae4SAndroid Build Coastguard Worker        }
431*6236dae4SAndroid Build Coastguard Worker    }
432*6236dae4SAndroid Build Coastguard Worker}
433*6236dae4SAndroid Build Coastguard Worker
434*6236dae4SAndroid Build Coastguard Worker#######################################################################
435*6236dae4SAndroid Build Coastguard Worker# Memory allocation test and failure torture testing.
436*6236dae4SAndroid Build Coastguard Worker#
437*6236dae4SAndroid Build Coastguard Workersub torture {
438*6236dae4SAndroid Build Coastguard Worker    my ($testcmd, $testnum, $gdbline) = @_;
439*6236dae4SAndroid Build Coastguard Worker
440*6236dae4SAndroid Build Coastguard Worker    # remove memdump first to be sure we get a new nice and clean one
441*6236dae4SAndroid Build Coastguard Worker    unlink("$LOGDIR/$MEMDUMP");
442*6236dae4SAndroid Build Coastguard Worker
443*6236dae4SAndroid Build Coastguard Worker    # First get URL from test server, ignore the output/result
444*6236dae4SAndroid Build Coastguard Worker    runclient($testcmd);
445*6236dae4SAndroid Build Coastguard Worker
446*6236dae4SAndroid Build Coastguard Worker    logmsg " CMD: $testcmd\n" if($verbose);
447*6236dae4SAndroid Build Coastguard Worker
448*6236dae4SAndroid Build Coastguard Worker    # memanalyze -v is our friend, get the number of allocations made
449*6236dae4SAndroid Build Coastguard Worker    my $count=0;
450*6236dae4SAndroid Build Coastguard Worker    my @out = `$memanalyze -v "$LOGDIR/$MEMDUMP"`;
451*6236dae4SAndroid Build Coastguard Worker    for(@out) {
452*6236dae4SAndroid Build Coastguard Worker        if(/^Operations: (\d+)/) {
453*6236dae4SAndroid Build Coastguard Worker            $count = $1;
454*6236dae4SAndroid Build Coastguard Worker            last;
455*6236dae4SAndroid Build Coastguard Worker        }
456*6236dae4SAndroid Build Coastguard Worker    }
457*6236dae4SAndroid Build Coastguard Worker    if(!$count) {
458*6236dae4SAndroid Build Coastguard Worker        logmsg " found no functions to make fail\n";
459*6236dae4SAndroid Build Coastguard Worker        return 0;
460*6236dae4SAndroid Build Coastguard Worker    }
461*6236dae4SAndroid Build Coastguard Worker
462*6236dae4SAndroid Build Coastguard Worker    my @ttests = (1 .. $count);
463*6236dae4SAndroid Build Coastguard Worker    if($shallow && ($shallow < $count)) {
464*6236dae4SAndroid Build Coastguard Worker        my $discard = scalar(@ttests) - $shallow;
465*6236dae4SAndroid Build Coastguard Worker        my $percent = sprintf("%.2f%%", $shallow * 100 / scalar(@ttests));
466*6236dae4SAndroid Build Coastguard Worker        logmsg " $count functions found, but only fail $shallow ($percent)\n";
467*6236dae4SAndroid Build Coastguard Worker        while($discard) {
468*6236dae4SAndroid Build Coastguard Worker            my $rm;
469*6236dae4SAndroid Build Coastguard Worker            do {
470*6236dae4SAndroid Build Coastguard Worker                # find a test to discard
471*6236dae4SAndroid Build Coastguard Worker                $rm = rand(scalar(@ttests));
472*6236dae4SAndroid Build Coastguard Worker            } while(!$ttests[$rm]);
473*6236dae4SAndroid Build Coastguard Worker            $ttests[$rm] = undef;
474*6236dae4SAndroid Build Coastguard Worker            $discard--;
475*6236dae4SAndroid Build Coastguard Worker        }
476*6236dae4SAndroid Build Coastguard Worker    }
477*6236dae4SAndroid Build Coastguard Worker    else {
478*6236dae4SAndroid Build Coastguard Worker        logmsg " $count functions to make fail\n";
479*6236dae4SAndroid Build Coastguard Worker    }
480*6236dae4SAndroid Build Coastguard Worker
481*6236dae4SAndroid Build Coastguard Worker    for (@ttests) {
482*6236dae4SAndroid Build Coastguard Worker        my $limit = $_;
483*6236dae4SAndroid Build Coastguard Worker        my $fail;
484*6236dae4SAndroid Build Coastguard Worker        my $dumped_core;
485*6236dae4SAndroid Build Coastguard Worker
486*6236dae4SAndroid Build Coastguard Worker        if(!defined($limit)) {
487*6236dae4SAndroid Build Coastguard Worker            # --shallow can undefine them
488*6236dae4SAndroid Build Coastguard Worker            next;
489*6236dae4SAndroid Build Coastguard Worker        }
490*6236dae4SAndroid Build Coastguard Worker        if($tortalloc && ($tortalloc != $limit)) {
491*6236dae4SAndroid Build Coastguard Worker            next;
492*6236dae4SAndroid Build Coastguard Worker        }
493*6236dae4SAndroid Build Coastguard Worker
494*6236dae4SAndroid Build Coastguard Worker        if($verbose) {
495*6236dae4SAndroid Build Coastguard Worker            my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
496*6236dae4SAndroid Build Coastguard Worker                localtime(time());
497*6236dae4SAndroid Build Coastguard Worker            my $now = sprintf("%02d:%02d:%02d ", $hour, $min, $sec);
498*6236dae4SAndroid Build Coastguard Worker            logmsg "Fail function no: $limit at $now\r";
499*6236dae4SAndroid Build Coastguard Worker        }
500*6236dae4SAndroid Build Coastguard Worker
501*6236dae4SAndroid Build Coastguard Worker        # make the memory allocation function number $limit return failure
502*6236dae4SAndroid Build Coastguard Worker        $ENV{'CURL_MEMLIMIT'} = $limit;
503*6236dae4SAndroid Build Coastguard Worker
504*6236dae4SAndroid Build Coastguard Worker        # remove memdump first to be sure we get a new nice and clean one
505*6236dae4SAndroid Build Coastguard Worker        unlink("$LOGDIR/$MEMDUMP");
506*6236dae4SAndroid Build Coastguard Worker
507*6236dae4SAndroid Build Coastguard Worker        my $cmd = $testcmd;
508*6236dae4SAndroid Build Coastguard Worker        if($valgrind && !$gdbthis) {
509*6236dae4SAndroid Build Coastguard Worker            my @valgrindoption = getpart("verify", "valgrind");
510*6236dae4SAndroid Build Coastguard Worker            if((!@valgrindoption) || ($valgrindoption[0] !~ /disable/)) {
511*6236dae4SAndroid Build Coastguard Worker                my $valgrindcmd = "$valgrind ";
512*6236dae4SAndroid Build Coastguard Worker                $valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
513*6236dae4SAndroid Build Coastguard Worker                $valgrindcmd .= "--quiet --leak-check=yes ";
514*6236dae4SAndroid Build Coastguard Worker                $valgrindcmd .= "--suppressions=$srcdir/valgrind.supp ";
515*6236dae4SAndroid Build Coastguard Worker                # $valgrindcmd .= "--gen-suppressions=all ";
516*6236dae4SAndroid Build Coastguard Worker                $valgrindcmd .= "--num-callers=16 ";
517*6236dae4SAndroid Build Coastguard Worker                $valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
518*6236dae4SAndroid Build Coastguard Worker                $cmd = "$valgrindcmd $testcmd";
519*6236dae4SAndroid Build Coastguard Worker            }
520*6236dae4SAndroid Build Coastguard Worker        }
521*6236dae4SAndroid Build Coastguard Worker        logmsg "*** Function number $limit is now set to fail ***\n" if($gdbthis);
522*6236dae4SAndroid Build Coastguard Worker
523*6236dae4SAndroid Build Coastguard Worker        my $ret = 0;
524*6236dae4SAndroid Build Coastguard Worker        if($gdbthis) {
525*6236dae4SAndroid Build Coastguard Worker            runclient($gdbline);
526*6236dae4SAndroid Build Coastguard Worker        }
527*6236dae4SAndroid Build Coastguard Worker        else {
528*6236dae4SAndroid Build Coastguard Worker            $ret = runclient($cmd);
529*6236dae4SAndroid Build Coastguard Worker        }
530*6236dae4SAndroid Build Coastguard Worker        #logmsg "$_ Returned " . ($ret >> 8) . "\n";
531*6236dae4SAndroid Build Coastguard Worker
532*6236dae4SAndroid Build Coastguard Worker        # Now clear the variable again
533*6236dae4SAndroid Build Coastguard Worker        delete $ENV{'CURL_MEMLIMIT'} if($ENV{'CURL_MEMLIMIT'});
534*6236dae4SAndroid Build Coastguard Worker
535*6236dae4SAndroid Build Coastguard Worker        if(-r "core") {
536*6236dae4SAndroid Build Coastguard Worker            # there's core file present now!
537*6236dae4SAndroid Build Coastguard Worker            logmsg " core dumped\n";
538*6236dae4SAndroid Build Coastguard Worker            $dumped_core = 1;
539*6236dae4SAndroid Build Coastguard Worker            $fail = 2;
540*6236dae4SAndroid Build Coastguard Worker        }
541*6236dae4SAndroid Build Coastguard Worker
542*6236dae4SAndroid Build Coastguard Worker        if($valgrind) {
543*6236dae4SAndroid Build Coastguard Worker            my @e = valgrindparse("$LOGDIR/valgrind$testnum");
544*6236dae4SAndroid Build Coastguard Worker            if(@e && $e[0]) {
545*6236dae4SAndroid Build Coastguard Worker                if($automakestyle) {
546*6236dae4SAndroid Build Coastguard Worker                    logmsg "FAIL: torture $testnum - valgrind\n";
547*6236dae4SAndroid Build Coastguard Worker                }
548*6236dae4SAndroid Build Coastguard Worker                else {
549*6236dae4SAndroid Build Coastguard Worker                    logmsg " valgrind ERROR ";
550*6236dae4SAndroid Build Coastguard Worker                    logmsg @e;
551*6236dae4SAndroid Build Coastguard Worker                }
552*6236dae4SAndroid Build Coastguard Worker                $fail = 1;
553*6236dae4SAndroid Build Coastguard Worker            }
554*6236dae4SAndroid Build Coastguard Worker        }
555*6236dae4SAndroid Build Coastguard Worker
556*6236dae4SAndroid Build Coastguard Worker        # verify that it returns a proper error code, doesn't leak memory
557*6236dae4SAndroid Build Coastguard Worker        # and doesn't core dump
558*6236dae4SAndroid Build Coastguard Worker        if(($ret & 255) || ($ret >> 8) >= 128) {
559*6236dae4SAndroid Build Coastguard Worker            logmsg " system() returned $ret\n";
560*6236dae4SAndroid Build Coastguard Worker            $fail=1;
561*6236dae4SAndroid Build Coastguard Worker        }
562*6236dae4SAndroid Build Coastguard Worker        else {
563*6236dae4SAndroid Build Coastguard Worker            my @memdata=`$memanalyze "$LOGDIR/$MEMDUMP"`;
564*6236dae4SAndroid Build Coastguard Worker            my $leak=0;
565*6236dae4SAndroid Build Coastguard Worker            for(@memdata) {
566*6236dae4SAndroid Build Coastguard Worker                if($_ ne "") {
567*6236dae4SAndroid Build Coastguard Worker                    # well it could be other memory problems as well, but
568*6236dae4SAndroid Build Coastguard Worker                    # we call it leak for short here
569*6236dae4SAndroid Build Coastguard Worker                    $leak=1;
570*6236dae4SAndroid Build Coastguard Worker                }
571*6236dae4SAndroid Build Coastguard Worker            }
572*6236dae4SAndroid Build Coastguard Worker            if($leak) {
573*6236dae4SAndroid Build Coastguard Worker                logmsg "** MEMORY FAILURE\n";
574*6236dae4SAndroid Build Coastguard Worker                logmsg @memdata;
575*6236dae4SAndroid Build Coastguard Worker                logmsg `$memanalyze -l "$LOGDIR/$MEMDUMP"`;
576*6236dae4SAndroid Build Coastguard Worker                $fail = 1;
577*6236dae4SAndroid Build Coastguard Worker            }
578*6236dae4SAndroid Build Coastguard Worker        }
579*6236dae4SAndroid Build Coastguard Worker        if($fail) {
580*6236dae4SAndroid Build Coastguard Worker            logmsg " $testnum: torture FAILED: function number $limit in test.\n",
581*6236dae4SAndroid Build Coastguard Worker            " invoke with \"-t$limit\" to repeat this single case.\n";
582*6236dae4SAndroid Build Coastguard Worker            stopservers($verbose);
583*6236dae4SAndroid Build Coastguard Worker            return 1;
584*6236dae4SAndroid Build Coastguard Worker        }
585*6236dae4SAndroid Build Coastguard Worker    }
586*6236dae4SAndroid Build Coastguard Worker
587*6236dae4SAndroid Build Coastguard Worker    logmsg "\n" if($verbose);
588*6236dae4SAndroid Build Coastguard Worker    logmsg "torture OK\n";
589*6236dae4SAndroid Build Coastguard Worker    return 0;
590*6236dae4SAndroid Build Coastguard Worker}
591*6236dae4SAndroid Build Coastguard Worker
592*6236dae4SAndroid Build Coastguard Worker
593*6236dae4SAndroid Build Coastguard Worker#######################################################################
594*6236dae4SAndroid Build Coastguard Worker# restore environment variables that were modified in test
595*6236dae4SAndroid Build Coastguard Workersub restore_test_env {
596*6236dae4SAndroid Build Coastguard Worker    my $deleteoldenv = $_[0];   # 1 to delete the saved contents after restore
597*6236dae4SAndroid Build Coastguard Worker    foreach my $var (keys %oldenv) {
598*6236dae4SAndroid Build Coastguard Worker        if($oldenv{$var} eq 'notset') {
599*6236dae4SAndroid Build Coastguard Worker            delete $ENV{$var} if($ENV{$var});
600*6236dae4SAndroid Build Coastguard Worker        }
601*6236dae4SAndroid Build Coastguard Worker        else {
602*6236dae4SAndroid Build Coastguard Worker            $ENV{$var} = $oldenv{$var};
603*6236dae4SAndroid Build Coastguard Worker        }
604*6236dae4SAndroid Build Coastguard Worker        if($deleteoldenv) {
605*6236dae4SAndroid Build Coastguard Worker            delete $oldenv{$var};
606*6236dae4SAndroid Build Coastguard Worker        }
607*6236dae4SAndroid Build Coastguard Worker    }
608*6236dae4SAndroid Build Coastguard Worker}
609*6236dae4SAndroid Build Coastguard Worker
610*6236dae4SAndroid Build Coastguard Worker
611*6236dae4SAndroid Build Coastguard Worker#######################################################################
612*6236dae4SAndroid Build Coastguard Worker# Start the servers needed to run this test case
613*6236dae4SAndroid Build Coastguard Workersub singletest_startservers {
614*6236dae4SAndroid Build Coastguard Worker    my ($testnum, $testtimings) = @_;
615*6236dae4SAndroid Build Coastguard Worker
616*6236dae4SAndroid Build Coastguard Worker    # remove old test server files before servers are started/verified
617*6236dae4SAndroid Build Coastguard Worker    unlink("$LOGDIR/$SERVERCMD");
618*6236dae4SAndroid Build Coastguard Worker    unlink("$LOGDIR/$SERVERIN");
619*6236dae4SAndroid Build Coastguard Worker    unlink("$LOGDIR/$PROXYIN");
620*6236dae4SAndroid Build Coastguard Worker
621*6236dae4SAndroid Build Coastguard Worker    # timestamp required servers verification start
622*6236dae4SAndroid Build Coastguard Worker    $$testtimings{"timesrvrini"} = Time::HiRes::time();
623*6236dae4SAndroid Build Coastguard Worker
624*6236dae4SAndroid Build Coastguard Worker    my $why;
625*6236dae4SAndroid Build Coastguard Worker    my $error;
626*6236dae4SAndroid Build Coastguard Worker    if (!$listonly) {
627*6236dae4SAndroid Build Coastguard Worker        my @what = getpart("client", "server");
628*6236dae4SAndroid Build Coastguard Worker        if(!$what[0]) {
629*6236dae4SAndroid Build Coastguard Worker            warn "Test case $testnum has no server(s) specified";
630*6236dae4SAndroid Build Coastguard Worker            $why = "no server specified";
631*6236dae4SAndroid Build Coastguard Worker            $error = -1;
632*6236dae4SAndroid Build Coastguard Worker        } else {
633*6236dae4SAndroid Build Coastguard Worker            my $err;
634*6236dae4SAndroid Build Coastguard Worker            ($why, $err) = serverfortest(@what);
635*6236dae4SAndroid Build Coastguard Worker            if($err == 1) {
636*6236dae4SAndroid Build Coastguard Worker                # Error indicates an actual problem starting the server
637*6236dae4SAndroid Build Coastguard Worker                $error = -2;
638*6236dae4SAndroid Build Coastguard Worker            } else {
639*6236dae4SAndroid Build Coastguard Worker                $error = -1;
640*6236dae4SAndroid Build Coastguard Worker            }
641*6236dae4SAndroid Build Coastguard Worker        }
642*6236dae4SAndroid Build Coastguard Worker    }
643*6236dae4SAndroid Build Coastguard Worker
644*6236dae4SAndroid Build Coastguard Worker    # timestamp required servers verification end
645*6236dae4SAndroid Build Coastguard Worker    $$testtimings{"timesrvrend"} = Time::HiRes::time();
646*6236dae4SAndroid Build Coastguard Worker
647*6236dae4SAndroid Build Coastguard Worker    return ($why, $error);
648*6236dae4SAndroid Build Coastguard Worker}
649*6236dae4SAndroid Build Coastguard Worker
650*6236dae4SAndroid Build Coastguard Worker
651*6236dae4SAndroid Build Coastguard Worker#######################################################################
652*6236dae4SAndroid Build Coastguard Worker# Generate preprocessed test file
653*6236dae4SAndroid Build Coastguard Workersub singletest_preprocess {
654*6236dae4SAndroid Build Coastguard Worker    my $testnum = $_[0];
655*6236dae4SAndroid Build Coastguard Worker
656*6236dae4SAndroid Build Coastguard Worker    # Save a preprocessed version of the entire test file. This allows more
657*6236dae4SAndroid Build Coastguard Worker    # "basic" test case readers to enjoy variable replacements.
658*6236dae4SAndroid Build Coastguard Worker    my @entiretest = fulltest();
659*6236dae4SAndroid Build Coastguard Worker    my $otest = "$LOGDIR/test$testnum";
660*6236dae4SAndroid Build Coastguard Worker
661*6236dae4SAndroid Build Coastguard Worker    @entiretest = prepro($testnum, @entiretest);
662*6236dae4SAndroid Build Coastguard Worker
663*6236dae4SAndroid Build Coastguard Worker    # save the new version
664*6236dae4SAndroid Build Coastguard Worker    open(my $fulltesth, ">", "$otest") || die "Failure writing test file";
665*6236dae4SAndroid Build Coastguard Worker    foreach my $bytes (@entiretest) {
666*6236dae4SAndroid Build Coastguard Worker        print $fulltesth pack('a*', $bytes) or die "Failed to print '$bytes': $!";
667*6236dae4SAndroid Build Coastguard Worker    }
668*6236dae4SAndroid Build Coastguard Worker    close($fulltesth) || die "Failure writing test file";
669*6236dae4SAndroid Build Coastguard Worker
670*6236dae4SAndroid Build Coastguard Worker    # in case the process changed the file, reload it
671*6236dae4SAndroid Build Coastguard Worker    loadtest("$LOGDIR/test${testnum}");
672*6236dae4SAndroid Build Coastguard Worker}
673*6236dae4SAndroid Build Coastguard Worker
674*6236dae4SAndroid Build Coastguard Worker
675*6236dae4SAndroid Build Coastguard Worker#######################################################################
676*6236dae4SAndroid Build Coastguard Worker# Set up the test environment to run this test case
677*6236dae4SAndroid Build Coastguard Workersub singletest_setenv {
678*6236dae4SAndroid Build Coastguard Worker    my @setenv = getpart("client", "setenv");
679*6236dae4SAndroid Build Coastguard Worker    foreach my $s (@setenv) {
680*6236dae4SAndroid Build Coastguard Worker        chomp $s;
681*6236dae4SAndroid Build Coastguard Worker        if($s =~ /([^=]*)(.*)/) {
682*6236dae4SAndroid Build Coastguard Worker            my ($var, $content) = ($1, $2);
683*6236dae4SAndroid Build Coastguard Worker            # remember current setting, to restore it once test runs
684*6236dae4SAndroid Build Coastguard Worker            $oldenv{$var} = ($ENV{$var})?"$ENV{$var}":'notset';
685*6236dae4SAndroid Build Coastguard Worker
686*6236dae4SAndroid Build Coastguard Worker            if($content =~ /^=(.*)/) {
687*6236dae4SAndroid Build Coastguard Worker                # assign it
688*6236dae4SAndroid Build Coastguard Worker                $content = $1;
689*6236dae4SAndroid Build Coastguard Worker
690*6236dae4SAndroid Build Coastguard Worker                if($var =~ /^LD_PRELOAD/) {
691*6236dae4SAndroid Build Coastguard Worker                    if(exe_ext('TOOL') && (exe_ext('TOOL') eq '.exe')) {
692*6236dae4SAndroid Build Coastguard Worker                        logmsg "Skipping LD_PRELOAD due to lack of OS support\n" if($verbose);
693*6236dae4SAndroid Build Coastguard Worker                        next;
694*6236dae4SAndroid Build Coastguard Worker                    }
695*6236dae4SAndroid Build Coastguard Worker                    if($feature{"Debug"} || !$has_shared) {
696*6236dae4SAndroid Build Coastguard Worker                        logmsg "Skipping LD_PRELOAD due to no release shared build\n" if($verbose);
697*6236dae4SAndroid Build Coastguard Worker                        next;
698*6236dae4SAndroid Build Coastguard Worker                    }
699*6236dae4SAndroid Build Coastguard Worker                }
700*6236dae4SAndroid Build Coastguard Worker                $ENV{$var} = "$content";
701*6236dae4SAndroid Build Coastguard Worker                logmsg "setenv $var = $content\n" if($verbose);
702*6236dae4SAndroid Build Coastguard Worker            }
703*6236dae4SAndroid Build Coastguard Worker            else {
704*6236dae4SAndroid Build Coastguard Worker                # remove it
705*6236dae4SAndroid Build Coastguard Worker                delete $ENV{$var} if($ENV{$var});
706*6236dae4SAndroid Build Coastguard Worker            }
707*6236dae4SAndroid Build Coastguard Worker
708*6236dae4SAndroid Build Coastguard Worker        }
709*6236dae4SAndroid Build Coastguard Worker    }
710*6236dae4SAndroid Build Coastguard Worker    if($proxy_address) {
711*6236dae4SAndroid Build Coastguard Worker        $ENV{http_proxy} = $proxy_address;
712*6236dae4SAndroid Build Coastguard Worker        $ENV{HTTPS_PROXY} = $proxy_address;
713*6236dae4SAndroid Build Coastguard Worker    }
714*6236dae4SAndroid Build Coastguard Worker}
715*6236dae4SAndroid Build Coastguard Worker
716*6236dae4SAndroid Build Coastguard Worker
717*6236dae4SAndroid Build Coastguard Worker#######################################################################
718*6236dae4SAndroid Build Coastguard Worker# Check that test environment is fine to run this test case
719*6236dae4SAndroid Build Coastguard Workersub singletest_precheck {
720*6236dae4SAndroid Build Coastguard Worker    my $testnum = $_[0];
721*6236dae4SAndroid Build Coastguard Worker    my $why;
722*6236dae4SAndroid Build Coastguard Worker    my @precheck = getpart("client", "precheck");
723*6236dae4SAndroid Build Coastguard Worker    if(@precheck) {
724*6236dae4SAndroid Build Coastguard Worker        my $cmd = $precheck[0];
725*6236dae4SAndroid Build Coastguard Worker        chomp $cmd;
726*6236dae4SAndroid Build Coastguard Worker        if($cmd) {
727*6236dae4SAndroid Build Coastguard Worker            my @p = split(/ /, $cmd);
728*6236dae4SAndroid Build Coastguard Worker            if($p[0] !~ /\//) {
729*6236dae4SAndroid Build Coastguard Worker                # the first word, the command, does not contain a slash so
730*6236dae4SAndroid Build Coastguard Worker                # we will scan the "improved" PATH to find the command to
731*6236dae4SAndroid Build Coastguard Worker                # be able to run it
732*6236dae4SAndroid Build Coastguard Worker                my $fullp = checktestcmd($p[0]);
733*6236dae4SAndroid Build Coastguard Worker
734*6236dae4SAndroid Build Coastguard Worker                if($fullp) {
735*6236dae4SAndroid Build Coastguard Worker                    $p[0] = $fullp;
736*6236dae4SAndroid Build Coastguard Worker                }
737*6236dae4SAndroid Build Coastguard Worker                $cmd = join(" ", @p);
738*6236dae4SAndroid Build Coastguard Worker            }
739*6236dae4SAndroid Build Coastguard Worker
740*6236dae4SAndroid Build Coastguard Worker            my @o = `$cmd 2> $LOGDIR/precheck-$testnum`;
741*6236dae4SAndroid Build Coastguard Worker            if($o[0]) {
742*6236dae4SAndroid Build Coastguard Worker                $why = $o[0];
743*6236dae4SAndroid Build Coastguard Worker                $why =~ s/[\r\n]//g;
744*6236dae4SAndroid Build Coastguard Worker            }
745*6236dae4SAndroid Build Coastguard Worker            elsif($?) {
746*6236dae4SAndroid Build Coastguard Worker                $why = "precheck command error";
747*6236dae4SAndroid Build Coastguard Worker            }
748*6236dae4SAndroid Build Coastguard Worker            logmsg "prechecked $cmd\n" if($verbose);
749*6236dae4SAndroid Build Coastguard Worker        }
750*6236dae4SAndroid Build Coastguard Worker    }
751*6236dae4SAndroid Build Coastguard Worker    return $why;
752*6236dae4SAndroid Build Coastguard Worker}
753*6236dae4SAndroid Build Coastguard Worker
754*6236dae4SAndroid Build Coastguard Worker
755*6236dae4SAndroid Build Coastguard Worker#######################################################################
756*6236dae4SAndroid Build Coastguard Worker# Prepare the test environment to run this test case
757*6236dae4SAndroid Build Coastguard Workersub singletest_prepare {
758*6236dae4SAndroid Build Coastguard Worker    my ($testnum) = @_;
759*6236dae4SAndroid Build Coastguard Worker
760*6236dae4SAndroid Build Coastguard Worker    if($feature{"TrackMemory"}) {
761*6236dae4SAndroid Build Coastguard Worker        unlink("$LOGDIR/$MEMDUMP");
762*6236dae4SAndroid Build Coastguard Worker    }
763*6236dae4SAndroid Build Coastguard Worker    unlink("core");
764*6236dae4SAndroid Build Coastguard Worker
765*6236dae4SAndroid Build Coastguard Worker    # remove server output logfiles after servers are started/verified
766*6236dae4SAndroid Build Coastguard Worker    unlink("$LOGDIR/$SERVERIN");
767*6236dae4SAndroid Build Coastguard Worker    unlink("$LOGDIR/$PROXYIN");
768*6236dae4SAndroid Build Coastguard Worker
769*6236dae4SAndroid Build Coastguard Worker    # if this section exists, it might be FTP server instructions:
770*6236dae4SAndroid Build Coastguard Worker    my @ftpservercmd = getpart("reply", "servercmd");
771*6236dae4SAndroid Build Coastguard Worker    push @ftpservercmd, "Testnum $testnum\n";
772*6236dae4SAndroid Build Coastguard Worker    # write the instructions to file
773*6236dae4SAndroid Build Coastguard Worker    writearray("$LOGDIR/$SERVERCMD", \@ftpservercmd);
774*6236dae4SAndroid Build Coastguard Worker
775*6236dae4SAndroid Build Coastguard Worker    # create (possibly-empty) files before starting the test
776*6236dae4SAndroid Build Coastguard Worker    for my $partsuffix (('', '1', '2', '3', '4')) {
777*6236dae4SAndroid Build Coastguard Worker        my @inputfile=getpart("client", "file".$partsuffix);
778*6236dae4SAndroid Build Coastguard Worker        my %fileattr = getpartattr("client", "file".$partsuffix);
779*6236dae4SAndroid Build Coastguard Worker        my $filename=$fileattr{'name'};
780*6236dae4SAndroid Build Coastguard Worker        if(@inputfile || $filename) {
781*6236dae4SAndroid Build Coastguard Worker            if(!$filename) {
782*6236dae4SAndroid Build Coastguard Worker                logmsg " $testnum: IGNORED: section client=>file has no name attribute\n";
783*6236dae4SAndroid Build Coastguard Worker                return -1;
784*6236dae4SAndroid Build Coastguard Worker            }
785*6236dae4SAndroid Build Coastguard Worker            my $fileContent = join('', @inputfile);
786*6236dae4SAndroid Build Coastguard Worker
787*6236dae4SAndroid Build Coastguard Worker            # make directories if needed
788*6236dae4SAndroid Build Coastguard Worker            my $path = $filename;
789*6236dae4SAndroid Build Coastguard Worker            # cut off the file name part
790*6236dae4SAndroid Build Coastguard Worker            $path =~ s/^(.*)\/[^\/]*/$1/;
791*6236dae4SAndroid Build Coastguard Worker            my @ldparts = split(/\//, $LOGDIR);
792*6236dae4SAndroid Build Coastguard Worker            my $nparts = @ldparts;
793*6236dae4SAndroid Build Coastguard Worker            my @parts = split(/\//, $path);
794*6236dae4SAndroid Build Coastguard Worker            if(join("/", @parts[0..$nparts-1]) eq $LOGDIR) {
795*6236dae4SAndroid Build Coastguard Worker                # the file is in $LOGDIR/
796*6236dae4SAndroid Build Coastguard Worker                my $d = shift @parts;
797*6236dae4SAndroid Build Coastguard Worker                for(@parts) {
798*6236dae4SAndroid Build Coastguard Worker                    $d .= "/$_";
799*6236dae4SAndroid Build Coastguard Worker                    mkdir $d; # 0777
800*6236dae4SAndroid Build Coastguard Worker                }
801*6236dae4SAndroid Build Coastguard Worker            }
802*6236dae4SAndroid Build Coastguard Worker            if (open(my $outfile, ">", "$filename")) {
803*6236dae4SAndroid Build Coastguard Worker                binmode $outfile; # for crapage systems, use binary
804*6236dae4SAndroid Build Coastguard Worker                if($fileattr{'nonewline'}) {
805*6236dae4SAndroid Build Coastguard Worker                    # cut off the final newline
806*6236dae4SAndroid Build Coastguard Worker                    chomp($fileContent);
807*6236dae4SAndroid Build Coastguard Worker                }
808*6236dae4SAndroid Build Coastguard Worker                print $outfile $fileContent;
809*6236dae4SAndroid Build Coastguard Worker                close($outfile);
810*6236dae4SAndroid Build Coastguard Worker            } else {
811*6236dae4SAndroid Build Coastguard Worker                logmsg "ERROR: cannot write $filename\n";
812*6236dae4SAndroid Build Coastguard Worker            }
813*6236dae4SAndroid Build Coastguard Worker        }
814*6236dae4SAndroid Build Coastguard Worker    }
815*6236dae4SAndroid Build Coastguard Worker    return 0;
816*6236dae4SAndroid Build Coastguard Worker}
817*6236dae4SAndroid Build Coastguard Worker
818*6236dae4SAndroid Build Coastguard Worker
819*6236dae4SAndroid Build Coastguard Worker#######################################################################
820*6236dae4SAndroid Build Coastguard Worker# Run the test command
821*6236dae4SAndroid Build Coastguard Workersub singletest_run {
822*6236dae4SAndroid Build Coastguard Worker    my ($testnum, $testtimings) = @_;
823*6236dae4SAndroid Build Coastguard Worker
824*6236dae4SAndroid Build Coastguard Worker    # get the command line options to use
825*6236dae4SAndroid Build Coastguard Worker    my ($cmd, @blaha)= getpart("client", "command");
826*6236dae4SAndroid Build Coastguard Worker    if($cmd) {
827*6236dae4SAndroid Build Coastguard Worker        # make some nice replace operations
828*6236dae4SAndroid Build Coastguard Worker        $cmd =~ s/\n//g; # no newlines please
829*6236dae4SAndroid Build Coastguard Worker        # substitute variables in the command line
830*6236dae4SAndroid Build Coastguard Worker    }
831*6236dae4SAndroid Build Coastguard Worker    else {
832*6236dae4SAndroid Build Coastguard Worker        # there was no command given, use something silly
833*6236dae4SAndroid Build Coastguard Worker        $cmd="-";
834*6236dae4SAndroid Build Coastguard Worker    }
835*6236dae4SAndroid Build Coastguard Worker
836*6236dae4SAndroid Build Coastguard Worker    my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout
837*6236dae4SAndroid Build Coastguard Worker
838*6236dae4SAndroid Build Coastguard Worker    # if stdout section exists, we verify that the stdout contained this:
839*6236dae4SAndroid Build Coastguard Worker    my $out="";
840*6236dae4SAndroid Build Coastguard Worker    my %cmdhash = getpartattr("client", "command");
841*6236dae4SAndroid Build Coastguard Worker    if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-output/)) {
842*6236dae4SAndroid Build Coastguard Worker        #We may slap on --output!
843*6236dae4SAndroid Build Coastguard Worker        if (!partexists("verify", "stdout") ||
844*6236dae4SAndroid Build Coastguard Worker                ($cmdhash{'option'} && $cmdhash{'option'} =~ /force-output/)) {
845*6236dae4SAndroid Build Coastguard Worker            $out=" --output $CURLOUT ";
846*6236dae4SAndroid Build Coastguard Worker        }
847*6236dae4SAndroid Build Coastguard Worker    }
848*6236dae4SAndroid Build Coastguard Worker
849*6236dae4SAndroid Build Coastguard Worker    my @codepieces = getpart("client", "tool");
850*6236dae4SAndroid Build Coastguard Worker    my $tool="";
851*6236dae4SAndroid Build Coastguard Worker    my $tool_name="";  # without exe extension
852*6236dae4SAndroid Build Coastguard Worker    if(@codepieces) {
853*6236dae4SAndroid Build Coastguard Worker        $tool_name = $codepieces[0];
854*6236dae4SAndroid Build Coastguard Worker        chomp $tool_name;
855*6236dae4SAndroid Build Coastguard Worker        $tool = $tool_name . exe_ext('TOOL');
856*6236dae4SAndroid Build Coastguard Worker    }
857*6236dae4SAndroid Build Coastguard Worker
858*6236dae4SAndroid Build Coastguard Worker    my $disablevalgrind;
859*6236dae4SAndroid Build Coastguard Worker    my $CMDLINE="";
860*6236dae4SAndroid Build Coastguard Worker    my $cmdargs;
861*6236dae4SAndroid Build Coastguard Worker    my $cmdtype = $cmdhash{'type'} || "default";
862*6236dae4SAndroid Build Coastguard Worker    my $fail_due_event_based = $run_event_based;
863*6236dae4SAndroid Build Coastguard Worker    if($cmdtype eq "perl") {
864*6236dae4SAndroid Build Coastguard Worker        # run the command line prepended with "perl"
865*6236dae4SAndroid Build Coastguard Worker        $cmdargs ="$cmd";
866*6236dae4SAndroid Build Coastguard Worker        $CMDLINE = "$perl ";
867*6236dae4SAndroid Build Coastguard Worker        $tool=$CMDLINE;
868*6236dae4SAndroid Build Coastguard Worker        $disablevalgrind=1;
869*6236dae4SAndroid Build Coastguard Worker    }
870*6236dae4SAndroid Build Coastguard Worker    elsif($cmdtype eq "shell") {
871*6236dae4SAndroid Build Coastguard Worker        # run the command line prepended with "/bin/sh"
872*6236dae4SAndroid Build Coastguard Worker        $cmdargs ="$cmd";
873*6236dae4SAndroid Build Coastguard Worker        $CMDLINE = "/bin/sh ";
874*6236dae4SAndroid Build Coastguard Worker        $tool=$CMDLINE;
875*6236dae4SAndroid Build Coastguard Worker        $disablevalgrind=1;
876*6236dae4SAndroid Build Coastguard Worker    }
877*6236dae4SAndroid Build Coastguard Worker    elsif(!$tool && !$keywords{"unittest"}) {
878*6236dae4SAndroid Build Coastguard Worker        # run curl, add suitable command line options
879*6236dae4SAndroid Build Coastguard Worker        my $inc="";
880*6236dae4SAndroid Build Coastguard Worker        if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-include/)) {
881*6236dae4SAndroid Build Coastguard Worker            $inc = " --include";
882*6236dae4SAndroid Build Coastguard Worker        }
883*6236dae4SAndroid Build Coastguard Worker        $cmdargs = "$out$inc ";
884*6236dae4SAndroid Build Coastguard Worker
885*6236dae4SAndroid Build Coastguard Worker        if($cmdhash{'option'} && ($cmdhash{'option'} =~ /binary-trace/)) {
886*6236dae4SAndroid Build Coastguard Worker            $cmdargs .= "--trace $LOGDIR/trace$testnum ";
887*6236dae4SAndroid Build Coastguard Worker        }
888*6236dae4SAndroid Build Coastguard Worker        else {
889*6236dae4SAndroid Build Coastguard Worker            $cmdargs .= "--trace-ascii $LOGDIR/trace$testnum ";
890*6236dae4SAndroid Build Coastguard Worker        }
891*6236dae4SAndroid Build Coastguard Worker        $cmdargs .= "--trace-config all ";
892*6236dae4SAndroid Build Coastguard Worker        $cmdargs .= "--trace-time ";
893*6236dae4SAndroid Build Coastguard Worker        if($run_event_based) {
894*6236dae4SAndroid Build Coastguard Worker            $cmdargs .= "--test-event ";
895*6236dae4SAndroid Build Coastguard Worker            $fail_due_event_based--;
896*6236dae4SAndroid Build Coastguard Worker        }
897*6236dae4SAndroid Build Coastguard Worker        $cmdargs .= $cmd;
898*6236dae4SAndroid Build Coastguard Worker        if ($proxy_address) {
899*6236dae4SAndroid Build Coastguard Worker            $cmdargs .= " --proxy $proxy_address ";
900*6236dae4SAndroid Build Coastguard Worker        }
901*6236dae4SAndroid Build Coastguard Worker    }
902*6236dae4SAndroid Build Coastguard Worker    else {
903*6236dae4SAndroid Build Coastguard Worker        $cmdargs = " $cmd"; # $cmd is the command line for the test file
904*6236dae4SAndroid Build Coastguard Worker        $CURLOUT = stdoutfilename($LOGDIR, $testnum); # sends received data to stdout
905*6236dae4SAndroid Build Coastguard Worker
906*6236dae4SAndroid Build Coastguard Worker        # Default the tool to a unit test with the same name as the test spec
907*6236dae4SAndroid Build Coastguard Worker        if($keywords{"unittest"} && !$tool) {
908*6236dae4SAndroid Build Coastguard Worker            $tool_name="unit$testnum";
909*6236dae4SAndroid Build Coastguard Worker            $tool = $tool_name;
910*6236dae4SAndroid Build Coastguard Worker        }
911*6236dae4SAndroid Build Coastguard Worker
912*6236dae4SAndroid Build Coastguard Worker        if($tool =~ /^lib/) {
913*6236dae4SAndroid Build Coastguard Worker            if($bundle) {
914*6236dae4SAndroid Build Coastguard Worker                $CMDLINE="$LIBDIR/libtests";
915*6236dae4SAndroid Build Coastguard Worker            }
916*6236dae4SAndroid Build Coastguard Worker            else {
917*6236dae4SAndroid Build Coastguard Worker                $CMDLINE="$LIBDIR/$tool";
918*6236dae4SAndroid Build Coastguard Worker            }
919*6236dae4SAndroid Build Coastguard Worker        }
920*6236dae4SAndroid Build Coastguard Worker        elsif($tool =~ /^unit/) {
921*6236dae4SAndroid Build Coastguard Worker            if($bundle) {
922*6236dae4SAndroid Build Coastguard Worker                $CMDLINE="$UNITDIR/units";
923*6236dae4SAndroid Build Coastguard Worker            }
924*6236dae4SAndroid Build Coastguard Worker            else {
925*6236dae4SAndroid Build Coastguard Worker                $CMDLINE="$UNITDIR/$tool";
926*6236dae4SAndroid Build Coastguard Worker            }
927*6236dae4SAndroid Build Coastguard Worker        }
928*6236dae4SAndroid Build Coastguard Worker
929*6236dae4SAndroid Build Coastguard Worker        if(! -f $CMDLINE) {
930*6236dae4SAndroid Build Coastguard Worker            logmsg " $testnum: IGNORED: The tool set in the test case for this: '$tool' does not exist\n";
931*6236dae4SAndroid Build Coastguard Worker            return (-1, 0, 0, "", "", 0);
932*6236dae4SAndroid Build Coastguard Worker        }
933*6236dae4SAndroid Build Coastguard Worker
934*6236dae4SAndroid Build Coastguard Worker        if($bundle) {
935*6236dae4SAndroid Build Coastguard Worker            $CMDLINE.=" $tool_name";
936*6236dae4SAndroid Build Coastguard Worker        }
937*6236dae4SAndroid Build Coastguard Worker
938*6236dae4SAndroid Build Coastguard Worker        $DBGCURL=$CMDLINE;
939*6236dae4SAndroid Build Coastguard Worker    }
940*6236dae4SAndroid Build Coastguard Worker
941*6236dae4SAndroid Build Coastguard Worker    if($fail_due_event_based) {
942*6236dae4SAndroid Build Coastguard Worker        logmsg " $testnum: IGNORED: This test cannot run event based\n";
943*6236dae4SAndroid Build Coastguard Worker        return (-1, 0, 0, "", "", 0);
944*6236dae4SAndroid Build Coastguard Worker    }
945*6236dae4SAndroid Build Coastguard Worker
946*6236dae4SAndroid Build Coastguard Worker    if($gdbthis) {
947*6236dae4SAndroid Build Coastguard Worker        # gdb is incompatible with valgrind, so disable it when debugging
948*6236dae4SAndroid Build Coastguard Worker        # Perhaps a better approach would be to run it under valgrind anyway
949*6236dae4SAndroid Build Coastguard Worker        # with --db-attach=yes or --vgdb=yes.
950*6236dae4SAndroid Build Coastguard Worker        $disablevalgrind=1;
951*6236dae4SAndroid Build Coastguard Worker    }
952*6236dae4SAndroid Build Coastguard Worker
953*6236dae4SAndroid Build Coastguard Worker    my @stdintest = getpart("client", "stdin");
954*6236dae4SAndroid Build Coastguard Worker
955*6236dae4SAndroid Build Coastguard Worker    if(@stdintest) {
956*6236dae4SAndroid Build Coastguard Worker        my $stdinfile="$LOGDIR/stdin-for-$testnum";
957*6236dae4SAndroid Build Coastguard Worker
958*6236dae4SAndroid Build Coastguard Worker        my %hash = getpartattr("client", "stdin");
959*6236dae4SAndroid Build Coastguard Worker        if($hash{'nonewline'}) {
960*6236dae4SAndroid Build Coastguard Worker            # cut off the final newline from the final line of the stdin data
961*6236dae4SAndroid Build Coastguard Worker            chomp($stdintest[-1]);
962*6236dae4SAndroid Build Coastguard Worker        }
963*6236dae4SAndroid Build Coastguard Worker
964*6236dae4SAndroid Build Coastguard Worker        writearray($stdinfile, \@stdintest);
965*6236dae4SAndroid Build Coastguard Worker
966*6236dae4SAndroid Build Coastguard Worker        $cmdargs .= " <$stdinfile";
967*6236dae4SAndroid Build Coastguard Worker    }
968*6236dae4SAndroid Build Coastguard Worker
969*6236dae4SAndroid Build Coastguard Worker    if(!$tool) {
970*6236dae4SAndroid Build Coastguard Worker        $CMDLINE=shell_quote($CURL);
971*6236dae4SAndroid Build Coastguard Worker        if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-q/)) {
972*6236dae4SAndroid Build Coastguard Worker            $CMDLINE .= " -q";
973*6236dae4SAndroid Build Coastguard Worker        }
974*6236dae4SAndroid Build Coastguard Worker    }
975*6236dae4SAndroid Build Coastguard Worker
976*6236dae4SAndroid Build Coastguard Worker    if(use_valgrind() && !$disablevalgrind) {
977*6236dae4SAndroid Build Coastguard Worker        my $valgrindcmd = "$valgrind ";
978*6236dae4SAndroid Build Coastguard Worker        $valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
979*6236dae4SAndroid Build Coastguard Worker        $valgrindcmd .= "--quiet --leak-check=yes ";
980*6236dae4SAndroid Build Coastguard Worker        $valgrindcmd .= "--suppressions=$srcdir/valgrind.supp ";
981*6236dae4SAndroid Build Coastguard Worker        # $valgrindcmd .= "--gen-suppressions=all ";
982*6236dae4SAndroid Build Coastguard Worker        $valgrindcmd .= "--num-callers=16 ";
983*6236dae4SAndroid Build Coastguard Worker        $valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
984*6236dae4SAndroid Build Coastguard Worker        $CMDLINE = "$valgrindcmd $CMDLINE";
985*6236dae4SAndroid Build Coastguard Worker    }
986*6236dae4SAndroid Build Coastguard Worker
987*6236dae4SAndroid Build Coastguard Worker    $CMDLINE .= "$cmdargs > " . stdoutfilename($LOGDIR, $testnum) .
988*6236dae4SAndroid Build Coastguard Worker                " 2> " . stderrfilename($LOGDIR, $testnum);
989*6236dae4SAndroid Build Coastguard Worker
990*6236dae4SAndroid Build Coastguard Worker    if($verbose) {
991*6236dae4SAndroid Build Coastguard Worker        logmsg "$CMDLINE\n";
992*6236dae4SAndroid Build Coastguard Worker    }
993*6236dae4SAndroid Build Coastguard Worker
994*6236dae4SAndroid Build Coastguard Worker    open(my $cmdlog, ">", $CURLLOG) || die "Failure writing log file";
995*6236dae4SAndroid Build Coastguard Worker    print $cmdlog "$CMDLINE\n";
996*6236dae4SAndroid Build Coastguard Worker    close($cmdlog) || die "Failure writing log file";
997*6236dae4SAndroid Build Coastguard Worker
998*6236dae4SAndroid Build Coastguard Worker    my $dumped_core;
999*6236dae4SAndroid Build Coastguard Worker    my $cmdres;
1000*6236dae4SAndroid Build Coastguard Worker
1001*6236dae4SAndroid Build Coastguard Worker    if($gdbthis) {
1002*6236dae4SAndroid Build Coastguard Worker        my $gdbinit = "$TESTDIR/gdbinit$testnum";
1003*6236dae4SAndroid Build Coastguard Worker        open(my $gdbcmd, ">", "$LOGDIR/gdbcmd") || die "Failure writing gdb file";
1004*6236dae4SAndroid Build Coastguard Worker        if($gdbthis == 1) {
1005*6236dae4SAndroid Build Coastguard Worker            # gdb mode
1006*6236dae4SAndroid Build Coastguard Worker            print $gdbcmd "set args $cmdargs\n";
1007*6236dae4SAndroid Build Coastguard Worker            print $gdbcmd "show args\n";
1008*6236dae4SAndroid Build Coastguard Worker            print $gdbcmd "source $gdbinit\n" if -e $gdbinit;
1009*6236dae4SAndroid Build Coastguard Worker        }
1010*6236dae4SAndroid Build Coastguard Worker        else {
1011*6236dae4SAndroid Build Coastguard Worker            # lldb mode
1012*6236dae4SAndroid Build Coastguard Worker            print $gdbcmd "set args $cmdargs\n";
1013*6236dae4SAndroid Build Coastguard Worker        }
1014*6236dae4SAndroid Build Coastguard Worker        close($gdbcmd) || die "Failure writing gdb file";
1015*6236dae4SAndroid Build Coastguard Worker    }
1016*6236dae4SAndroid Build Coastguard Worker
1017*6236dae4SAndroid Build Coastguard Worker    # Flush output.
1018*6236dae4SAndroid Build Coastguard Worker    $| = 1;
1019*6236dae4SAndroid Build Coastguard Worker
1020*6236dae4SAndroid Build Coastguard Worker    # timestamp starting of test command
1021*6236dae4SAndroid Build Coastguard Worker    $$testtimings{"timetoolini"} = Time::HiRes::time();
1022*6236dae4SAndroid Build Coastguard Worker
1023*6236dae4SAndroid Build Coastguard Worker    # run the command line we built
1024*6236dae4SAndroid Build Coastguard Worker    if ($torture) {
1025*6236dae4SAndroid Build Coastguard Worker        $cmdres = torture($CMDLINE,
1026*6236dae4SAndroid Build Coastguard Worker                          $testnum,
1027*6236dae4SAndroid Build Coastguard Worker                          "$gdb --directory $LIBDIR " . shell_quote($DBGCURL) . " -x $LOGDIR/gdbcmd");
1028*6236dae4SAndroid Build Coastguard Worker    }
1029*6236dae4SAndroid Build Coastguard Worker    elsif($gdbthis == 1) {
1030*6236dae4SAndroid Build Coastguard Worker        # gdb
1031*6236dae4SAndroid Build Coastguard Worker        my $GDBW = ($gdbxwin) ? "-w" : "";
1032*6236dae4SAndroid Build Coastguard Worker        runclient("$gdb --directory $LIBDIR " . shell_quote($DBGCURL) . " $GDBW -x $LOGDIR/gdbcmd");
1033*6236dae4SAndroid Build Coastguard Worker        $cmdres=0; # makes it always continue after a debugged run
1034*6236dae4SAndroid Build Coastguard Worker    }
1035*6236dae4SAndroid Build Coastguard Worker    elsif($gdbthis == 2) {
1036*6236dae4SAndroid Build Coastguard Worker        # $gdb is "lldb"
1037*6236dae4SAndroid Build Coastguard Worker        print "runs lldb -- $CURL $cmdargs\n";
1038*6236dae4SAndroid Build Coastguard Worker        runclient("lldb -- $CURL $cmdargs");
1039*6236dae4SAndroid Build Coastguard Worker        $cmdres=0; # makes it always continue after a debugged run
1040*6236dae4SAndroid Build Coastguard Worker    }
1041*6236dae4SAndroid Build Coastguard Worker    else {
1042*6236dae4SAndroid Build Coastguard Worker        # Convert the raw result code into a more useful one
1043*6236dae4SAndroid Build Coastguard Worker        ($cmdres, $dumped_core) = normalize_cmdres(runclient("$CMDLINE"));
1044*6236dae4SAndroid Build Coastguard Worker    }
1045*6236dae4SAndroid Build Coastguard Worker
1046*6236dae4SAndroid Build Coastguard Worker    # timestamp finishing of test command
1047*6236dae4SAndroid Build Coastguard Worker    $$testtimings{"timetoolend"} = Time::HiRes::time();
1048*6236dae4SAndroid Build Coastguard Worker
1049*6236dae4SAndroid Build Coastguard Worker    return (0, $cmdres, $dumped_core, $CURLOUT, $tool, use_valgrind() && !$disablevalgrind);
1050*6236dae4SAndroid Build Coastguard Worker}
1051*6236dae4SAndroid Build Coastguard Worker
1052*6236dae4SAndroid Build Coastguard Worker
1053*6236dae4SAndroid Build Coastguard Worker#######################################################################
1054*6236dae4SAndroid Build Coastguard Worker# Clean up after test command
1055*6236dae4SAndroid Build Coastguard Workersub singletest_clean {
1056*6236dae4SAndroid Build Coastguard Worker    my ($testnum, $dumped_core, $testtimings)=@_;
1057*6236dae4SAndroid Build Coastguard Worker
1058*6236dae4SAndroid Build Coastguard Worker    if(!$dumped_core) {
1059*6236dae4SAndroid Build Coastguard Worker        if(-r "core") {
1060*6236dae4SAndroid Build Coastguard Worker            # there's core file present now!
1061*6236dae4SAndroid Build Coastguard Worker            $dumped_core = 1;
1062*6236dae4SAndroid Build Coastguard Worker        }
1063*6236dae4SAndroid Build Coastguard Worker    }
1064*6236dae4SAndroid Build Coastguard Worker
1065*6236dae4SAndroid Build Coastguard Worker    if($dumped_core) {
1066*6236dae4SAndroid Build Coastguard Worker        logmsg "core dumped\n";
1067*6236dae4SAndroid Build Coastguard Worker        if(0 && $gdb) {
1068*6236dae4SAndroid Build Coastguard Worker            logmsg "running gdb for post-mortem analysis:\n";
1069*6236dae4SAndroid Build Coastguard Worker            open(my $gdbcmd, ">", "$LOGDIR/gdbcmd2") || die "Failure writing gdb file";
1070*6236dae4SAndroid Build Coastguard Worker            print $gdbcmd "bt\n";
1071*6236dae4SAndroid Build Coastguard Worker            close($gdbcmd) || die "Failure writing gdb file";
1072*6236dae4SAndroid Build Coastguard Worker            runclient("$gdb --directory libtest -x $LOGDIR/gdbcmd2 -batch " . shell_quote($DBGCURL) . " core ");
1073*6236dae4SAndroid Build Coastguard Worker     #       unlink("$LOGDIR/gdbcmd2");
1074*6236dae4SAndroid Build Coastguard Worker        }
1075*6236dae4SAndroid Build Coastguard Worker    }
1076*6236dae4SAndroid Build Coastguard Worker
1077*6236dae4SAndroid Build Coastguard Worker    my $serverlogslocktimeout = $defserverlogslocktimeout;
1078*6236dae4SAndroid Build Coastguard Worker    my %cmdhash = getpartattr("client", "command");
1079*6236dae4SAndroid Build Coastguard Worker    if($cmdhash{'timeout'}) {
1080*6236dae4SAndroid Build Coastguard Worker        # test is allowed to override default server logs lock timeout
1081*6236dae4SAndroid Build Coastguard Worker        if($cmdhash{'timeout'} =~ /(\d+)/) {
1082*6236dae4SAndroid Build Coastguard Worker            $serverlogslocktimeout = $1 if($1 >= 0);
1083*6236dae4SAndroid Build Coastguard Worker        }
1084*6236dae4SAndroid Build Coastguard Worker    }
1085*6236dae4SAndroid Build Coastguard Worker
1086*6236dae4SAndroid Build Coastguard Worker    # Test harness ssh server does not have this synchronization mechanism,
1087*6236dae4SAndroid Build Coastguard Worker    # this implies that some ssh server based tests might need a small delay
1088*6236dae4SAndroid Build Coastguard Worker    # once that the client command has run to avoid false test failures.
1089*6236dae4SAndroid Build Coastguard Worker    #
1090*6236dae4SAndroid Build Coastguard Worker    # gnutls-serv also lacks this synchronization mechanism, so gnutls-serv
1091*6236dae4SAndroid Build Coastguard Worker    # based tests might need a small delay once that the client command has
1092*6236dae4SAndroid Build Coastguard Worker    # run to avoid false test failures.
1093*6236dae4SAndroid Build Coastguard Worker    my $postcommanddelay = $defpostcommanddelay;
1094*6236dae4SAndroid Build Coastguard Worker    if($cmdhash{'delay'}) {
1095*6236dae4SAndroid Build Coastguard Worker        # test is allowed to specify a delay after command is executed
1096*6236dae4SAndroid Build Coastguard Worker        if($cmdhash{'delay'} =~ /(\d+)/) {
1097*6236dae4SAndroid Build Coastguard Worker            $postcommanddelay = $1 if($1 > 0);
1098*6236dae4SAndroid Build Coastguard Worker        }
1099*6236dae4SAndroid Build Coastguard Worker    }
1100*6236dae4SAndroid Build Coastguard Worker
1101*6236dae4SAndroid Build Coastguard Worker    portable_sleep($postcommanddelay) if($postcommanddelay);
1102*6236dae4SAndroid Build Coastguard Worker
1103*6236dae4SAndroid Build Coastguard Worker    my @killtestservers = getpart("client", "killserver");
1104*6236dae4SAndroid Build Coastguard Worker    if(@killtestservers) {
1105*6236dae4SAndroid Build Coastguard Worker        foreach my $server (@killtestservers) {
1106*6236dae4SAndroid Build Coastguard Worker            chomp $server;
1107*6236dae4SAndroid Build Coastguard Worker            if(stopserver($server)) {
1108*6236dae4SAndroid Build Coastguard Worker                logmsg " $testnum: killserver FAILED\n";
1109*6236dae4SAndroid Build Coastguard Worker                return 1; # normal error if asked to fail on unexpected alive
1110*6236dae4SAndroid Build Coastguard Worker            }
1111*6236dae4SAndroid Build Coastguard Worker        }
1112*6236dae4SAndroid Build Coastguard Worker    }
1113*6236dae4SAndroid Build Coastguard Worker
1114*6236dae4SAndroid Build Coastguard Worker    # wait for any servers left running to release their locks
1115*6236dae4SAndroid Build Coastguard Worker    waitlockunlock($serverlogslocktimeout);
1116*6236dae4SAndroid Build Coastguard Worker
1117*6236dae4SAndroid Build Coastguard Worker    # timestamp removal of server logs advisor read lock
1118*6236dae4SAndroid Build Coastguard Worker    $$testtimings{"timesrvrlog"} = Time::HiRes::time();
1119*6236dae4SAndroid Build Coastguard Worker
1120*6236dae4SAndroid Build Coastguard Worker    # test definition might instruct to stop some servers
1121*6236dae4SAndroid Build Coastguard Worker    # stop also all servers relative to the given one
1122*6236dae4SAndroid Build Coastguard Worker
1123*6236dae4SAndroid Build Coastguard Worker    return 0;
1124*6236dae4SAndroid Build Coastguard Worker}
1125*6236dae4SAndroid Build Coastguard Worker
1126*6236dae4SAndroid Build Coastguard Worker#######################################################################
1127*6236dae4SAndroid Build Coastguard Worker# Verify that the postcheck succeeded
1128*6236dae4SAndroid Build Coastguard Workersub singletest_postcheck {
1129*6236dae4SAndroid Build Coastguard Worker    my ($testnum)=@_;
1130*6236dae4SAndroid Build Coastguard Worker
1131*6236dae4SAndroid Build Coastguard Worker    # run the postcheck command
1132*6236dae4SAndroid Build Coastguard Worker    my @postcheck= getpart("client", "postcheck");
1133*6236dae4SAndroid Build Coastguard Worker    if(@postcheck) {
1134*6236dae4SAndroid Build Coastguard Worker        die "test$testnum uses client/postcheck";
1135*6236dae4SAndroid Build Coastguard Worker    }
1136*6236dae4SAndroid Build Coastguard Worker
1137*6236dae4SAndroid Build Coastguard Worker    @postcheck= getpart("verify", "postcheck");
1138*6236dae4SAndroid Build Coastguard Worker    if(@postcheck) {
1139*6236dae4SAndroid Build Coastguard Worker        my $cmd = join("", @postcheck);
1140*6236dae4SAndroid Build Coastguard Worker        chomp $cmd;
1141*6236dae4SAndroid Build Coastguard Worker        if($cmd) {
1142*6236dae4SAndroid Build Coastguard Worker            logmsg "postcheck $cmd\n" if($verbose);
1143*6236dae4SAndroid Build Coastguard Worker            my $rc = runclient("$cmd");
1144*6236dae4SAndroid Build Coastguard Worker            # Must run the postcheck command in torture mode in order
1145*6236dae4SAndroid Build Coastguard Worker            # to clean up, but the result can't be relied upon.
1146*6236dae4SAndroid Build Coastguard Worker            if($rc != 0 && !$torture) {
1147*6236dae4SAndroid Build Coastguard Worker                logmsg " $testnum: postcheck FAILED\n";
1148*6236dae4SAndroid Build Coastguard Worker                return -1;
1149*6236dae4SAndroid Build Coastguard Worker            }
1150*6236dae4SAndroid Build Coastguard Worker        }
1151*6236dae4SAndroid Build Coastguard Worker    }
1152*6236dae4SAndroid Build Coastguard Worker    return 0;
1153*6236dae4SAndroid Build Coastguard Worker}
1154*6236dae4SAndroid Build Coastguard Worker
1155*6236dae4SAndroid Build Coastguard Worker
1156*6236dae4SAndroid Build Coastguard Worker
1157*6236dae4SAndroid Build Coastguard Worker###################################################################
1158*6236dae4SAndroid Build Coastguard Worker# Get ready to run a single test case
1159*6236dae4SAndroid Build Coastguard Workersub runner_test_preprocess {
1160*6236dae4SAndroid Build Coastguard Worker    my ($testnum)=@_;
1161*6236dae4SAndroid Build Coastguard Worker    my %testtimings;
1162*6236dae4SAndroid Build Coastguard Worker
1163*6236dae4SAndroid Build Coastguard Worker    if(clearlogs()) {
1164*6236dae4SAndroid Build Coastguard Worker        logmsg "Warning: log messages were lost\n";
1165*6236dae4SAndroid Build Coastguard Worker    }
1166*6236dae4SAndroid Build Coastguard Worker
1167*6236dae4SAndroid Build Coastguard Worker    # timestamp test preparation start
1168*6236dae4SAndroid Build Coastguard Worker    # TODO: this metric now shows only a portion of the prep time; better would
1169*6236dae4SAndroid Build Coastguard Worker    # be to time singletest_preprocess below instead
1170*6236dae4SAndroid Build Coastguard Worker    $testtimings{"timeprepini"} = Time::HiRes::time();
1171*6236dae4SAndroid Build Coastguard Worker
1172*6236dae4SAndroid Build Coastguard Worker    ###################################################################
1173*6236dae4SAndroid Build Coastguard Worker    # Load test metadata
1174*6236dae4SAndroid Build Coastguard Worker    # ignore any error here--if there were one, it would have been
1175*6236dae4SAndroid Build Coastguard Worker    # caught during the selection phase and this test would not be
1176*6236dae4SAndroid Build Coastguard Worker    # running now
1177*6236dae4SAndroid Build Coastguard Worker    loadtest("${TESTDIR}/test${testnum}");
1178*6236dae4SAndroid Build Coastguard Worker    readtestkeywords();
1179*6236dae4SAndroid Build Coastguard Worker
1180*6236dae4SAndroid Build Coastguard Worker    ###################################################################
1181*6236dae4SAndroid Build Coastguard Worker    # Restore environment variables that were modified in a previous run.
1182*6236dae4SAndroid Build Coastguard Worker    # Test definition may instruct to (un)set environment vars.
1183*6236dae4SAndroid Build Coastguard Worker    restore_test_env(1);
1184*6236dae4SAndroid Build Coastguard Worker
1185*6236dae4SAndroid Build Coastguard Worker    ###################################################################
1186*6236dae4SAndroid Build Coastguard Worker    # Start the servers needed to run this test case
1187*6236dae4SAndroid Build Coastguard Worker    my ($why, $error) = singletest_startservers($testnum, \%testtimings);
1188*6236dae4SAndroid Build Coastguard Worker
1189*6236dae4SAndroid Build Coastguard Worker    # make sure no locks left for responsive test
1190*6236dae4SAndroid Build Coastguard Worker    waitlockunlock($defserverlogslocktimeout);
1191*6236dae4SAndroid Build Coastguard Worker
1192*6236dae4SAndroid Build Coastguard Worker    if(!$why) {
1193*6236dae4SAndroid Build Coastguard Worker
1194*6236dae4SAndroid Build Coastguard Worker        ###############################################################
1195*6236dae4SAndroid Build Coastguard Worker        # Generate preprocessed test file
1196*6236dae4SAndroid Build Coastguard Worker        # This must be done after the servers are started so server
1197*6236dae4SAndroid Build Coastguard Worker        # variables are available for substitution.
1198*6236dae4SAndroid Build Coastguard Worker        singletest_preprocess($testnum);
1199*6236dae4SAndroid Build Coastguard Worker
1200*6236dae4SAndroid Build Coastguard Worker        ###############################################################
1201*6236dae4SAndroid Build Coastguard Worker        # Set up the test environment to run this test case
1202*6236dae4SAndroid Build Coastguard Worker        singletest_setenv();
1203*6236dae4SAndroid Build Coastguard Worker
1204*6236dae4SAndroid Build Coastguard Worker        ###############################################################
1205*6236dae4SAndroid Build Coastguard Worker        # Check that the test environment is fine to run this test case
1206*6236dae4SAndroid Build Coastguard Worker        if (!$listonly) {
1207*6236dae4SAndroid Build Coastguard Worker            $why = singletest_precheck($testnum);
1208*6236dae4SAndroid Build Coastguard Worker            $error = -1;
1209*6236dae4SAndroid Build Coastguard Worker        }
1210*6236dae4SAndroid Build Coastguard Worker    }
1211*6236dae4SAndroid Build Coastguard Worker    return ($why, $error, clearlogs(), \%testtimings);
1212*6236dae4SAndroid Build Coastguard Worker}
1213*6236dae4SAndroid Build Coastguard Worker
1214*6236dae4SAndroid Build Coastguard Worker
1215*6236dae4SAndroid Build Coastguard Worker###################################################################
1216*6236dae4SAndroid Build Coastguard Worker# Run a single test case with an environment that already been prepared
1217*6236dae4SAndroid Build Coastguard Worker# Returns 0=success, -1=skippable failure, -2=permanent error,
1218*6236dae4SAndroid Build Coastguard Worker#   1=unskippable test failure, as first integer, plus any log messages,
1219*6236dae4SAndroid Build Coastguard Worker#   plus more return values when error is 0
1220*6236dae4SAndroid Build Coastguard Workersub runner_test_run {
1221*6236dae4SAndroid Build Coastguard Worker    my ($testnum)=@_;
1222*6236dae4SAndroid Build Coastguard Worker
1223*6236dae4SAndroid Build Coastguard Worker    if(clearlogs()) {
1224*6236dae4SAndroid Build Coastguard Worker        logmsg "Warning: log messages were lost\n";
1225*6236dae4SAndroid Build Coastguard Worker    }
1226*6236dae4SAndroid Build Coastguard Worker
1227*6236dae4SAndroid Build Coastguard Worker    #######################################################################
1228*6236dae4SAndroid Build Coastguard Worker    # Prepare the test environment to run this test case
1229*6236dae4SAndroid Build Coastguard Worker    my $error = singletest_prepare($testnum);
1230*6236dae4SAndroid Build Coastguard Worker    if($error) {
1231*6236dae4SAndroid Build Coastguard Worker        return (-2, clearlogs());
1232*6236dae4SAndroid Build Coastguard Worker    }
1233*6236dae4SAndroid Build Coastguard Worker
1234*6236dae4SAndroid Build Coastguard Worker    #######################################################################
1235*6236dae4SAndroid Build Coastguard Worker    # Run the test command
1236*6236dae4SAndroid Build Coastguard Worker    my %testtimings;
1237*6236dae4SAndroid Build Coastguard Worker    my $cmdres;
1238*6236dae4SAndroid Build Coastguard Worker    my $dumped_core;
1239*6236dae4SAndroid Build Coastguard Worker    my $CURLOUT;
1240*6236dae4SAndroid Build Coastguard Worker    my $tool;
1241*6236dae4SAndroid Build Coastguard Worker    my $usedvalgrind;
1242*6236dae4SAndroid Build Coastguard Worker    ($error, $cmdres, $dumped_core, $CURLOUT, $tool, $usedvalgrind) = singletest_run($testnum, \%testtimings);
1243*6236dae4SAndroid Build Coastguard Worker    if($error) {
1244*6236dae4SAndroid Build Coastguard Worker        return (-2, clearlogs(), \%testtimings);
1245*6236dae4SAndroid Build Coastguard Worker    }
1246*6236dae4SAndroid Build Coastguard Worker
1247*6236dae4SAndroid Build Coastguard Worker    #######################################################################
1248*6236dae4SAndroid Build Coastguard Worker    # Clean up after test command
1249*6236dae4SAndroid Build Coastguard Worker    $error = singletest_clean($testnum, $dumped_core, \%testtimings);
1250*6236dae4SAndroid Build Coastguard Worker    if($error) {
1251*6236dae4SAndroid Build Coastguard Worker        return ($error, clearlogs(), \%testtimings);
1252*6236dae4SAndroid Build Coastguard Worker    }
1253*6236dae4SAndroid Build Coastguard Worker
1254*6236dae4SAndroid Build Coastguard Worker    #######################################################################
1255*6236dae4SAndroid Build Coastguard Worker    # Verify that the postcheck succeeded
1256*6236dae4SAndroid Build Coastguard Worker    $error = singletest_postcheck($testnum);
1257*6236dae4SAndroid Build Coastguard Worker    if($error) {
1258*6236dae4SAndroid Build Coastguard Worker        return ($error, clearlogs(), \%testtimings);
1259*6236dae4SAndroid Build Coastguard Worker    }
1260*6236dae4SAndroid Build Coastguard Worker
1261*6236dae4SAndroid Build Coastguard Worker    #######################################################################
1262*6236dae4SAndroid Build Coastguard Worker    # restore environment variables that were modified
1263*6236dae4SAndroid Build Coastguard Worker    restore_test_env(0);
1264*6236dae4SAndroid Build Coastguard Worker
1265*6236dae4SAndroid Build Coastguard Worker    return (0, clearlogs(), \%testtimings, $cmdres, $CURLOUT, $tool, $usedvalgrind);
1266*6236dae4SAndroid Build Coastguard Worker}
1267*6236dae4SAndroid Build Coastguard Worker
1268*6236dae4SAndroid Build Coastguard Worker# Async call runner_clearlocks
1269*6236dae4SAndroid Build Coastguard Worker# Called by controller
1270*6236dae4SAndroid Build Coastguard Workersub runnerac_clearlocks {
1271*6236dae4SAndroid Build Coastguard Worker    return controlleripccall(\&runner_clearlocks, @_);
1272*6236dae4SAndroid Build Coastguard Worker}
1273*6236dae4SAndroid Build Coastguard Worker
1274*6236dae4SAndroid Build Coastguard Worker# Async call runner_shutdown
1275*6236dae4SAndroid Build Coastguard Worker# This call does NOT generate an IPC response and must be the last IPC call
1276*6236dae4SAndroid Build Coastguard Worker# received.
1277*6236dae4SAndroid Build Coastguard Worker# Called by controller
1278*6236dae4SAndroid Build Coastguard Workersub runnerac_shutdown {
1279*6236dae4SAndroid Build Coastguard Worker    my ($runnerid)=$_[0];
1280*6236dae4SAndroid Build Coastguard Worker    my $err = controlleripccall(\&runner_shutdown, @_);
1281*6236dae4SAndroid Build Coastguard Worker
1282*6236dae4SAndroid Build Coastguard Worker    # These have no more use
1283*6236dae4SAndroid Build Coastguard Worker    close($controllerw{$runnerid});
1284*6236dae4SAndroid Build Coastguard Worker    undef $controllerw{$runnerid};
1285*6236dae4SAndroid Build Coastguard Worker    close($controllerr{$runnerid});
1286*6236dae4SAndroid Build Coastguard Worker    undef $controllerr{$runnerid};
1287*6236dae4SAndroid Build Coastguard Worker    return $err;
1288*6236dae4SAndroid Build Coastguard Worker}
1289*6236dae4SAndroid Build Coastguard Worker
1290*6236dae4SAndroid Build Coastguard Worker# Async call of runner_stopservers
1291*6236dae4SAndroid Build Coastguard Worker# Called by controller
1292*6236dae4SAndroid Build Coastguard Workersub runnerac_stopservers {
1293*6236dae4SAndroid Build Coastguard Worker    return controlleripccall(\&runner_stopservers, @_);
1294*6236dae4SAndroid Build Coastguard Worker}
1295*6236dae4SAndroid Build Coastguard Worker
1296*6236dae4SAndroid Build Coastguard Worker# Async call of runner_test_preprocess
1297*6236dae4SAndroid Build Coastguard Worker# Called by controller
1298*6236dae4SAndroid Build Coastguard Workersub runnerac_test_preprocess {
1299*6236dae4SAndroid Build Coastguard Worker    return controlleripccall(\&runner_test_preprocess, @_);
1300*6236dae4SAndroid Build Coastguard Worker}
1301*6236dae4SAndroid Build Coastguard Worker
1302*6236dae4SAndroid Build Coastguard Worker# Async call of runner_test_run
1303*6236dae4SAndroid Build Coastguard Worker# Called by controller
1304*6236dae4SAndroid Build Coastguard Workersub runnerac_test_run {
1305*6236dae4SAndroid Build Coastguard Worker    return controlleripccall(\&runner_test_run, @_);
1306*6236dae4SAndroid Build Coastguard Worker}
1307*6236dae4SAndroid Build Coastguard Worker
1308*6236dae4SAndroid Build Coastguard Worker###################################################################
1309*6236dae4SAndroid Build Coastguard Worker# Call an arbitrary function via IPC
1310*6236dae4SAndroid Build Coastguard Worker# The first argument is the function reference, the second is the runner ID
1311*6236dae4SAndroid Build Coastguard Worker# Returns 0 on success, -1 on error writing to runner
1312*6236dae4SAndroid Build Coastguard Worker# Called by controller (indirectly, via a more specific function)
1313*6236dae4SAndroid Build Coastguard Workersub controlleripccall {
1314*6236dae4SAndroid Build Coastguard Worker    my $funcref = shift @_;
1315*6236dae4SAndroid Build Coastguard Worker    my $runnerid = shift @_;
1316*6236dae4SAndroid Build Coastguard Worker    # Get the name of the function from the reference
1317*6236dae4SAndroid Build Coastguard Worker    my $cv = svref_2object($funcref);
1318*6236dae4SAndroid Build Coastguard Worker    my $gv = $cv->GV;
1319*6236dae4SAndroid Build Coastguard Worker    # Prepend the name to the function arguments so it's marshalled along with them
1320*6236dae4SAndroid Build Coastguard Worker    unshift @_, $gv->NAME;
1321*6236dae4SAndroid Build Coastguard Worker    # Marshall the arguments into a flat string
1322*6236dae4SAndroid Build Coastguard Worker    my $margs = freeze \@_;
1323*6236dae4SAndroid Build Coastguard Worker
1324*6236dae4SAndroid Build Coastguard Worker    # Send IPC call via pipe
1325*6236dae4SAndroid Build Coastguard Worker    my $err;
1326*6236dae4SAndroid Build Coastguard Worker    while(! defined ($err = syswrite($controllerw{$runnerid}, (pack "L", length($margs)) . $margs)) || $err <= 0) {
1327*6236dae4SAndroid Build Coastguard Worker        if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
1328*6236dae4SAndroid Build Coastguard Worker            # Runner has likely died
1329*6236dae4SAndroid Build Coastguard Worker            return -1;
1330*6236dae4SAndroid Build Coastguard Worker        }
1331*6236dae4SAndroid Build Coastguard Worker        # system call was interrupted, probably by ^C; restart it so we stay in sync
1332*6236dae4SAndroid Build Coastguard Worker    }
1333*6236dae4SAndroid Build Coastguard Worker
1334*6236dae4SAndroid Build Coastguard Worker    if(!$multiprocess) {
1335*6236dae4SAndroid Build Coastguard Worker        # Call the remote function here in single process mode
1336*6236dae4SAndroid Build Coastguard Worker        ipcrecv();
1337*6236dae4SAndroid Build Coastguard Worker     }
1338*6236dae4SAndroid Build Coastguard Worker     return 0;
1339*6236dae4SAndroid Build Coastguard Worker}
1340*6236dae4SAndroid Build Coastguard Worker
1341*6236dae4SAndroid Build Coastguard Worker###################################################################
1342*6236dae4SAndroid Build Coastguard Worker# Receive async response of a previous call via IPC
1343*6236dae4SAndroid Build Coastguard Worker# The first return value is the runner ID or undef on error
1344*6236dae4SAndroid Build Coastguard Worker# Called by controller
1345*6236dae4SAndroid Build Coastguard Workersub runnerar {
1346*6236dae4SAndroid Build Coastguard Worker    my ($runnerid) = @_;
1347*6236dae4SAndroid Build Coastguard Worker    my $err;
1348*6236dae4SAndroid Build Coastguard Worker    my $datalen;
1349*6236dae4SAndroid Build Coastguard Worker    while(! defined ($err = sysread($controllerr{$runnerid}, $datalen, 4)) || $err <= 0) {
1350*6236dae4SAndroid Build Coastguard Worker        if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
1351*6236dae4SAndroid Build Coastguard Worker            # Runner is likely dead and closed the pipe
1352*6236dae4SAndroid Build Coastguard Worker            return undef;
1353*6236dae4SAndroid Build Coastguard Worker        }
1354*6236dae4SAndroid Build Coastguard Worker        # system call was interrupted, probably by ^C; restart it so we stay in sync
1355*6236dae4SAndroid Build Coastguard Worker    }
1356*6236dae4SAndroid Build Coastguard Worker    my $len=unpack("L", $datalen);
1357*6236dae4SAndroid Build Coastguard Worker    my $buf;
1358*6236dae4SAndroid Build Coastguard Worker    while(! defined ($err = sysread($controllerr{$runnerid}, $buf, $len)) || $err <= 0) {
1359*6236dae4SAndroid Build Coastguard Worker        if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
1360*6236dae4SAndroid Build Coastguard Worker            # Runner is likely dead and closed the pipe
1361*6236dae4SAndroid Build Coastguard Worker            return undef;
1362*6236dae4SAndroid Build Coastguard Worker        }
1363*6236dae4SAndroid Build Coastguard Worker        # system call was interrupted, probably by ^C; restart it so we stay in sync
1364*6236dae4SAndroid Build Coastguard Worker    }
1365*6236dae4SAndroid Build Coastguard Worker
1366*6236dae4SAndroid Build Coastguard Worker    # Decode response values
1367*6236dae4SAndroid Build Coastguard Worker    my $resarrayref = thaw $buf;
1368*6236dae4SAndroid Build Coastguard Worker
1369*6236dae4SAndroid Build Coastguard Worker    # First argument is runner ID
1370*6236dae4SAndroid Build Coastguard Worker    # TODO: remove this; it's unneeded since it's passed in
1371*6236dae4SAndroid Build Coastguard Worker    unshift @$resarrayref, $runnerid;
1372*6236dae4SAndroid Build Coastguard Worker    return @$resarrayref;
1373*6236dae4SAndroid Build Coastguard Worker}
1374*6236dae4SAndroid Build Coastguard Worker
1375*6236dae4SAndroid Build Coastguard Worker###################################################################
1376*6236dae4SAndroid Build Coastguard Worker# Returns runner ID if a response from an async call is ready or error
1377*6236dae4SAndroid Build Coastguard Worker# First value is ready, second is error, however an error case shows up
1378*6236dae4SAndroid Build Coastguard Worker# as ready in Linux, so you can't trust it.
1379*6236dae4SAndroid Build Coastguard Worker# argument is 0 for nonblocking, undef for blocking, anything else for timeout
1380*6236dae4SAndroid Build Coastguard Worker# Called by controller
1381*6236dae4SAndroid Build Coastguard Workersub runnerar_ready {
1382*6236dae4SAndroid Build Coastguard Worker    my ($blocking) = @_;
1383*6236dae4SAndroid Build Coastguard Worker    my $rin = "";
1384*6236dae4SAndroid Build Coastguard Worker    my %idbyfileno;
1385*6236dae4SAndroid Build Coastguard Worker    my $maxfileno=0;
1386*6236dae4SAndroid Build Coastguard Worker    my @ready_runners = ();
1387*6236dae4SAndroid Build Coastguard Worker    foreach my $p (keys(%controllerr)) {
1388*6236dae4SAndroid Build Coastguard Worker        my $fd = fileno($controllerr{$p});
1389*6236dae4SAndroid Build Coastguard Worker        vec($rin, $fd, 1) = 1;
1390*6236dae4SAndroid Build Coastguard Worker        $idbyfileno{$fd} = $p;  # save the runner ID for each pipe fd
1391*6236dae4SAndroid Build Coastguard Worker        if($fd > $maxfileno) {
1392*6236dae4SAndroid Build Coastguard Worker            $maxfileno = $fd;
1393*6236dae4SAndroid Build Coastguard Worker        }
1394*6236dae4SAndroid Build Coastguard Worker    }
1395*6236dae4SAndroid Build Coastguard Worker    $maxfileno || die "Internal error: no runners are available to wait on\n";
1396*6236dae4SAndroid Build Coastguard Worker
1397*6236dae4SAndroid Build Coastguard Worker    # Wait for any pipe from any runner to be ready
1398*6236dae4SAndroid Build Coastguard Worker    # This may be interrupted and return EINTR, but this is ignored and the
1399*6236dae4SAndroid Build Coastguard Worker    # caller will need to later call this function again.
1400*6236dae4SAndroid Build Coastguard Worker    # TODO: this is relatively slow with hundreds of fds
1401*6236dae4SAndroid Build Coastguard Worker    my $ein = $rin;
1402*6236dae4SAndroid Build Coastguard Worker    if(select(my $rout=$rin, undef, my $eout=$ein, $blocking) >= 1) {
1403*6236dae4SAndroid Build Coastguard Worker        for my $fd (0..$maxfileno) {
1404*6236dae4SAndroid Build Coastguard Worker            # Return an error condition first in case it's both
1405*6236dae4SAndroid Build Coastguard Worker            if(vec($eout, $fd, 1)) {
1406*6236dae4SAndroid Build Coastguard Worker                return (undef, $idbyfileno{$fd});
1407*6236dae4SAndroid Build Coastguard Worker            }
1408*6236dae4SAndroid Build Coastguard Worker            if(vec($rout, $fd, 1)) {
1409*6236dae4SAndroid Build Coastguard Worker                push(@ready_runners, $idbyfileno{$fd});
1410*6236dae4SAndroid Build Coastguard Worker            }
1411*6236dae4SAndroid Build Coastguard Worker        }
1412*6236dae4SAndroid Build Coastguard Worker        die "Internal pipe readiness inconsistency\n" if(!@ready_runners);
1413*6236dae4SAndroid Build Coastguard Worker        return (@ready_runners, undef);
1414*6236dae4SAndroid Build Coastguard Worker    }
1415*6236dae4SAndroid Build Coastguard Worker    return (undef, undef);
1416*6236dae4SAndroid Build Coastguard Worker}
1417*6236dae4SAndroid Build Coastguard Worker
1418*6236dae4SAndroid Build Coastguard Worker
1419*6236dae4SAndroid Build Coastguard Worker###################################################################
1420*6236dae4SAndroid Build Coastguard Worker# Cleanly abort and exit the runner
1421*6236dae4SAndroid Build Coastguard Worker# This uses print since there is no longer any controller to write logs.
1422*6236dae4SAndroid Build Coastguard Workersub runnerabort{
1423*6236dae4SAndroid Build Coastguard Worker    print "Controller is gone: runner $$ for $LOGDIR exiting\n";
1424*6236dae4SAndroid Build Coastguard Worker    my ($error, $logs) = runner_stopservers();
1425*6236dae4SAndroid Build Coastguard Worker    print $logs;
1426*6236dae4SAndroid Build Coastguard Worker    runner_shutdown();
1427*6236dae4SAndroid Build Coastguard Worker}
1428*6236dae4SAndroid Build Coastguard Worker
1429*6236dae4SAndroid Build Coastguard Worker###################################################################
1430*6236dae4SAndroid Build Coastguard Worker# Receive an IPC call in the runner and execute it
1431*6236dae4SAndroid Build Coastguard Worker# The IPC is read from the $runnerr pipe and the response is
1432*6236dae4SAndroid Build Coastguard Worker# written to the $runnerw pipe
1433*6236dae4SAndroid Build Coastguard Worker# Returns 0 if more IPC calls are expected or 1 if the runner should exit
1434*6236dae4SAndroid Build Coastguard Workersub ipcrecv {
1435*6236dae4SAndroid Build Coastguard Worker    my $err;
1436*6236dae4SAndroid Build Coastguard Worker    my $datalen;
1437*6236dae4SAndroid Build Coastguard Worker    while(! defined ($err = sysread($runnerr, $datalen, 4)) || $err <= 0) {
1438*6236dae4SAndroid Build Coastguard Worker        if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
1439*6236dae4SAndroid Build Coastguard Worker            # pipe has closed; controller is gone and we must exit
1440*6236dae4SAndroid Build Coastguard Worker            runnerabort();
1441*6236dae4SAndroid Build Coastguard Worker            # Special case: no response will be forthcoming
1442*6236dae4SAndroid Build Coastguard Worker            return 1;
1443*6236dae4SAndroid Build Coastguard Worker        }
1444*6236dae4SAndroid Build Coastguard Worker        # system call was interrupted, probably by ^C; restart it so we stay in sync
1445*6236dae4SAndroid Build Coastguard Worker    }
1446*6236dae4SAndroid Build Coastguard Worker    my $len=unpack("L", $datalen);
1447*6236dae4SAndroid Build Coastguard Worker    my $buf;
1448*6236dae4SAndroid Build Coastguard Worker    while(! defined ($err = sysread($runnerr, $buf, $len)) || $err <= 0) {
1449*6236dae4SAndroid Build Coastguard Worker        if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
1450*6236dae4SAndroid Build Coastguard Worker            # pipe has closed; controller is gone and we must exit
1451*6236dae4SAndroid Build Coastguard Worker            runnerabort();
1452*6236dae4SAndroid Build Coastguard Worker            # Special case: no response will be forthcoming
1453*6236dae4SAndroid Build Coastguard Worker            return 1;
1454*6236dae4SAndroid Build Coastguard Worker        }
1455*6236dae4SAndroid Build Coastguard Worker        # system call was interrupted, probably by ^C; restart it so we stay in sync
1456*6236dae4SAndroid Build Coastguard Worker    }
1457*6236dae4SAndroid Build Coastguard Worker
1458*6236dae4SAndroid Build Coastguard Worker    # Decode the function name and arguments
1459*6236dae4SAndroid Build Coastguard Worker    my $argsarrayref = thaw $buf;
1460*6236dae4SAndroid Build Coastguard Worker
1461*6236dae4SAndroid Build Coastguard Worker    # The name of the function to call is the first argument
1462*6236dae4SAndroid Build Coastguard Worker    my $funcname = shift @$argsarrayref;
1463*6236dae4SAndroid Build Coastguard Worker
1464*6236dae4SAndroid Build Coastguard Worker    # print "ipcrecv $funcname\n";
1465*6236dae4SAndroid Build Coastguard Worker    # Synchronously call the desired function
1466*6236dae4SAndroid Build Coastguard Worker    my @res;
1467*6236dae4SAndroid Build Coastguard Worker    if($funcname eq "runner_clearlocks") {
1468*6236dae4SAndroid Build Coastguard Worker        @res = runner_clearlocks(@$argsarrayref);
1469*6236dae4SAndroid Build Coastguard Worker    }
1470*6236dae4SAndroid Build Coastguard Worker    elsif($funcname eq "runner_shutdown") {
1471*6236dae4SAndroid Build Coastguard Worker        runner_shutdown(@$argsarrayref);
1472*6236dae4SAndroid Build Coastguard Worker        # Special case: no response will be forthcoming
1473*6236dae4SAndroid Build Coastguard Worker        return 1;
1474*6236dae4SAndroid Build Coastguard Worker    }
1475*6236dae4SAndroid Build Coastguard Worker    elsif($funcname eq "runner_stopservers") {
1476*6236dae4SAndroid Build Coastguard Worker        @res = runner_stopservers(@$argsarrayref);
1477*6236dae4SAndroid Build Coastguard Worker    }
1478*6236dae4SAndroid Build Coastguard Worker    elsif($funcname eq "runner_test_preprocess") {
1479*6236dae4SAndroid Build Coastguard Worker        @res = runner_test_preprocess(@$argsarrayref);
1480*6236dae4SAndroid Build Coastguard Worker    }
1481*6236dae4SAndroid Build Coastguard Worker    elsif($funcname eq "runner_test_run") {
1482*6236dae4SAndroid Build Coastguard Worker        @res = runner_test_run(@$argsarrayref);
1483*6236dae4SAndroid Build Coastguard Worker    } else {
1484*6236dae4SAndroid Build Coastguard Worker        die "Unknown IPC function $funcname\n";
1485*6236dae4SAndroid Build Coastguard Worker    }
1486*6236dae4SAndroid Build Coastguard Worker    # print "ipcrecv results\n";
1487*6236dae4SAndroid Build Coastguard Worker
1488*6236dae4SAndroid Build Coastguard Worker    # Marshall the results to return
1489*6236dae4SAndroid Build Coastguard Worker    $buf = freeze \@res;
1490*6236dae4SAndroid Build Coastguard Worker
1491*6236dae4SAndroid Build Coastguard Worker    while(! defined ($err = syswrite($runnerw, (pack "L", length($buf)) . $buf)) || $err <= 0) {
1492*6236dae4SAndroid Build Coastguard Worker        if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
1493*6236dae4SAndroid Build Coastguard Worker            # pipe has closed; controller is gone and we must exit
1494*6236dae4SAndroid Build Coastguard Worker            runnerabort();
1495*6236dae4SAndroid Build Coastguard Worker            # Special case: no response will be forthcoming
1496*6236dae4SAndroid Build Coastguard Worker            return 1;
1497*6236dae4SAndroid Build Coastguard Worker        }
1498*6236dae4SAndroid Build Coastguard Worker        # system call was interrupted, probably by ^C; restart it so we stay in sync
1499*6236dae4SAndroid Build Coastguard Worker    }
1500*6236dae4SAndroid Build Coastguard Worker
1501*6236dae4SAndroid Build Coastguard Worker    return 0;
1502*6236dae4SAndroid Build Coastguard Worker}
1503*6236dae4SAndroid Build Coastguard Worker
1504*6236dae4SAndroid Build Coastguard Worker###################################################################
1505*6236dae4SAndroid Build Coastguard Worker# Kill the server processes that still have lock files in a directory
1506*6236dae4SAndroid Build Coastguard Workersub runner_clearlocks {
1507*6236dae4SAndroid Build Coastguard Worker    my ($lockdir)=@_;
1508*6236dae4SAndroid Build Coastguard Worker    if(clearlogs()) {
1509*6236dae4SAndroid Build Coastguard Worker        logmsg "Warning: log messages were lost\n";
1510*6236dae4SAndroid Build Coastguard Worker    }
1511*6236dae4SAndroid Build Coastguard Worker    clearlocks($lockdir);
1512*6236dae4SAndroid Build Coastguard Worker    return clearlogs();
1513*6236dae4SAndroid Build Coastguard Worker}
1514*6236dae4SAndroid Build Coastguard Worker
1515*6236dae4SAndroid Build Coastguard Worker
1516*6236dae4SAndroid Build Coastguard Worker###################################################################
1517*6236dae4SAndroid Build Coastguard Worker# Kill all server processes
1518*6236dae4SAndroid Build Coastguard Workersub runner_stopservers {
1519*6236dae4SAndroid Build Coastguard Worker    my $error = stopservers($verbose);
1520*6236dae4SAndroid Build Coastguard Worker    my $logs = clearlogs();
1521*6236dae4SAndroid Build Coastguard Worker    return ($error, $logs);
1522*6236dae4SAndroid Build Coastguard Worker}
1523*6236dae4SAndroid Build Coastguard Worker
1524*6236dae4SAndroid Build Coastguard Worker###################################################################
1525*6236dae4SAndroid Build Coastguard Worker# Shut down this runner
1526*6236dae4SAndroid Build Coastguard Workersub runner_shutdown {
1527*6236dae4SAndroid Build Coastguard Worker    close($runnerr);
1528*6236dae4SAndroid Build Coastguard Worker    undef $runnerr;
1529*6236dae4SAndroid Build Coastguard Worker    close($runnerw);
1530*6236dae4SAndroid Build Coastguard Worker    undef $runnerw;
1531*6236dae4SAndroid Build Coastguard Worker}
1532*6236dae4SAndroid Build Coastguard Worker
1533*6236dae4SAndroid Build Coastguard Worker
1534*6236dae4SAndroid Build Coastguard Worker1;
1535