runner.pm 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. #***************************************************************************
  2. # _ _ ____ _
  3. # Project ___| | | | _ \| |
  4. # / __| | | | |_) | |
  5. # | (__| |_| | _ <| |___
  6. # \___|\___/|_| \_\_____|
  7. #
  8. # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
  9. #
  10. # This software is licensed as described in the file COPYING, which
  11. # you should have received as part of this distribution. The terms
  12. # are also available at https://curl.se/docs/copyright.html.
  13. #
  14. # You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. # copies of the Software, and permit persons to whom the Software is
  16. # furnished to do so, under the terms of the COPYING file.
  17. #
  18. # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. # KIND, either express or implied.
  20. #
  21. # SPDX-License-Identifier: curl
  22. #
  23. ###########################################################################
  24. # This module contains entry points to run a single test
  25. package runner;
  26. use strict;
  27. use warnings;
  28. BEGIN {
  29. use base qw(Exporter);
  30. our @EXPORT = qw(
  31. prepro
  32. restore_test_env
  33. runner_test_preprocess
  34. runner_test_run
  35. checktestcmd
  36. $DBGCURL
  37. $gdbthis
  38. $gdbxwin
  39. $shallow
  40. $tortalloc
  41. $valgrind_logfile
  42. $valgrind_tool
  43. $gdb
  44. );
  45. # these are for debugging only
  46. our @EXPORT_OK = qw(
  47. readtestkeywords
  48. singletest_preprocess
  49. );
  50. }
  51. use pathhelp qw(
  52. exe_ext
  53. );
  54. use processhelp qw(
  55. portable_sleep
  56. );
  57. use servers;
  58. use getpart;
  59. use globalconfig;
  60. use testutil;
  61. #######################################################################
  62. # Global variables set elsewhere but used only by this package
  63. our $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging
  64. our $valgrind_logfile="--log-file"; # the option name for valgrind >=3
  65. our $valgrind_tool="--tool=memcheck";
  66. our $gdb = checktestcmd("gdb");
  67. our $gdbthis; # run test case with gdb debugger
  68. our $gdbxwin; # use windowed gdb when using gdb
  69. # torture test variables
  70. our $shallow;
  71. our $tortalloc;
  72. # local variables
  73. my %oldenv; # environment variables before test is started
  74. my $UNITDIR="./unit";
  75. my $CURLLOG="$LOGDIR/commands.log"; # all command lines run
  76. my $SERVERLOGS_LOCK="$LOGDIR/serverlogs.lock"; # server logs advisor read lock
  77. my $defserverlogslocktimeout = 2; # timeout to await server logs lock removal
  78. my $defpostcommanddelay = 0; # delay between command and postcheck sections
  79. #######################################################################
  80. # Log an informational message
  81. # This just calls main's logmsg for now.
  82. sub logmsg {
  83. return main::logmsg(@_);
  84. }
  85. #######################################################################
  86. # Call main's displaylogs
  87. # TODO: this will eventually stop being called in this package
  88. sub displaylogs{
  89. return main::displaylogs(@_);
  90. }
  91. #######################################################################
  92. # Check for a command in the PATH of the machine running curl.
  93. #
  94. sub checktestcmd {
  95. my ($cmd)=@_;
  96. my @testpaths=("$LIBDIR/.libs", "$LIBDIR");
  97. return checkcmd($cmd, @testpaths);
  98. }
  99. # See if Valgrind should actually be used
  100. sub use_valgrind {
  101. if($valgrind) {
  102. my @valgrindoption = getpart("verify", "valgrind");
  103. if((!@valgrindoption) || ($valgrindoption[0] !~ /disable/)) {
  104. return 1;
  105. }
  106. }
  107. return 0;
  108. }
  109. # Massage the command result code into a useful form
  110. sub normalize_cmdres {
  111. my $cmdres = $_[0];
  112. my $signal_num = $cmdres & 127;
  113. my $dumped_core = $cmdres & 128;
  114. if(!$anyway && ($signal_num || $dumped_core)) {
  115. $cmdres = 1000;
  116. }
  117. else {
  118. $cmdres >>= 8;
  119. $cmdres = (2000 + $signal_num) if($signal_num && !$cmdres);
  120. }
  121. return ($cmdres, $dumped_core);
  122. }
  123. # 'prepro' processes the input array and replaces %-variables in the array
  124. # etc. Returns the processed version of the array
  125. sub prepro {
  126. my $testnum = shift;
  127. my (@entiretest) = @_;
  128. my $show = 1;
  129. my @out;
  130. my $data_crlf;
  131. for my $s (@entiretest) {
  132. my $f = $s;
  133. if($s =~ /^ *%if (.*)/) {
  134. my $cond = $1;
  135. my $rev = 0;
  136. if($cond =~ /^!(.*)/) {
  137. $cond = $1;
  138. $rev = 1;
  139. }
  140. $rev ^= $feature{$cond} ? 1 : 0;
  141. $show = $rev;
  142. next;
  143. }
  144. elsif($s =~ /^ *%else/) {
  145. $show ^= 1;
  146. next;
  147. }
  148. elsif($s =~ /^ *%endif/) {
  149. $show = 1;
  150. next;
  151. }
  152. if($show) {
  153. # The processor does CRLF replacements in the <data*> sections if
  154. # necessary since those parts might be read by separate servers.
  155. if($s =~ /^ *<data(.*)\>/) {
  156. if($1 =~ /crlf="yes"/ ||
  157. ($feature{"hyper"} && ($keywords{"HTTP"} || $keywords{"HTTPS"}))) {
  158. $data_crlf = 1;
  159. }
  160. }
  161. elsif(($s =~ /^ *<\/data/) && $data_crlf) {
  162. $data_crlf = 0;
  163. }
  164. subvariables(\$s, $testnum, "%");
  165. subbase64(\$s);
  166. subnewlines(0, \$s) if($data_crlf);
  167. push @out, $s;
  168. }
  169. }
  170. return @out;
  171. }
  172. #######################################################################
  173. # Load test keywords into %keywords hash
  174. #
  175. sub readtestkeywords {
  176. my @info_keywords = getpart("info", "keywords");
  177. # Clear the list of keywords from the last test
  178. %keywords = ();
  179. for my $k (@info_keywords) {
  180. chomp $k;
  181. $keywords{$k} = 1;
  182. }
  183. }
  184. #######################################################################
  185. # Memory allocation test and failure torture testing.
  186. #
  187. sub torture {
  188. my ($testcmd, $testnum, $gdbline) = @_;
  189. # remove memdump first to be sure we get a new nice and clean one
  190. unlink($memdump);
  191. # First get URL from test server, ignore the output/result
  192. runclient($testcmd);
  193. logmsg " CMD: $testcmd\n" if($verbose);
  194. # memanalyze -v is our friend, get the number of allocations made
  195. my $count=0;
  196. my @out = `$memanalyze -v $memdump`;
  197. for(@out) {
  198. if(/^Operations: (\d+)/) {
  199. $count = $1;
  200. last;
  201. }
  202. }
  203. if(!$count) {
  204. logmsg " found no functions to make fail\n";
  205. return 0;
  206. }
  207. my @ttests = (1 .. $count);
  208. if($shallow && ($shallow < $count)) {
  209. my $discard = scalar(@ttests) - $shallow;
  210. my $percent = sprintf("%.2f%%", $shallow * 100 / scalar(@ttests));
  211. logmsg " $count functions found, but only fail $shallow ($percent)\n";
  212. while($discard) {
  213. my $rm;
  214. do {
  215. # find a test to discard
  216. $rm = rand(scalar(@ttests));
  217. } while(!$ttests[$rm]);
  218. $ttests[$rm] = undef;
  219. $discard--;
  220. }
  221. }
  222. else {
  223. logmsg " $count functions to make fail\n";
  224. }
  225. for (@ttests) {
  226. my $limit = $_;
  227. my $fail;
  228. my $dumped_core;
  229. if(!defined($limit)) {
  230. # --shallow can undefine them
  231. next;
  232. }
  233. if($tortalloc && ($tortalloc != $limit)) {
  234. next;
  235. }
  236. if($verbose) {
  237. my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
  238. localtime(time());
  239. my $now = sprintf("%02d:%02d:%02d ", $hour, $min, $sec);
  240. logmsg "Fail function no: $limit at $now\r";
  241. }
  242. # make the memory allocation function number $limit return failure
  243. $ENV{'CURL_MEMLIMIT'} = $limit;
  244. # remove memdump first to be sure we get a new nice and clean one
  245. unlink($memdump);
  246. my $cmd = $testcmd;
  247. if($valgrind && !$gdbthis) {
  248. my @valgrindoption = getpart("verify", "valgrind");
  249. if((!@valgrindoption) || ($valgrindoption[0] !~ /disable/)) {
  250. my $valgrindcmd = "$valgrind ";
  251. $valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
  252. $valgrindcmd .= "--quiet --leak-check=yes ";
  253. $valgrindcmd .= "--suppressions=$srcdir/valgrind.supp ";
  254. # $valgrindcmd .= "--gen-suppressions=all ";
  255. $valgrindcmd .= "--num-callers=16 ";
  256. $valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
  257. $cmd = "$valgrindcmd $testcmd";
  258. }
  259. }
  260. logmsg "*** Function number $limit is now set to fail ***\n" if($gdbthis);
  261. my $ret = 0;
  262. if($gdbthis) {
  263. runclient($gdbline);
  264. }
  265. else {
  266. $ret = runclient($cmd);
  267. }
  268. #logmsg "$_ Returned " . ($ret >> 8) . "\n";
  269. # Now clear the variable again
  270. delete $ENV{'CURL_MEMLIMIT'} if($ENV{'CURL_MEMLIMIT'});
  271. if(-r "core") {
  272. # there's core file present now!
  273. logmsg " core dumped\n";
  274. $dumped_core = 1;
  275. $fail = 2;
  276. }
  277. if($valgrind) {
  278. my @e = valgrindparse("$LOGDIR/valgrind$testnum");
  279. if(@e && $e[0]) {
  280. if($automakestyle) {
  281. logmsg "FAIL: torture $testnum - valgrind\n";
  282. }
  283. else {
  284. logmsg " valgrind ERROR ";
  285. logmsg @e;
  286. }
  287. $fail = 1;
  288. }
  289. }
  290. # verify that it returns a proper error code, doesn't leak memory
  291. # and doesn't core dump
  292. if(($ret & 255) || ($ret >> 8) >= 128) {
  293. logmsg " system() returned $ret\n";
  294. $fail=1;
  295. }
  296. else {
  297. my @memdata=`$memanalyze $memdump`;
  298. my $leak=0;
  299. for(@memdata) {
  300. if($_ ne "") {
  301. # well it could be other memory problems as well, but
  302. # we call it leak for short here
  303. $leak=1;
  304. }
  305. }
  306. if($leak) {
  307. logmsg "** MEMORY FAILURE\n";
  308. logmsg @memdata;
  309. logmsg `$memanalyze -l $memdump`;
  310. $fail = 1;
  311. }
  312. }
  313. if($fail) {
  314. logmsg " Failed on function number $limit in test.\n",
  315. " invoke with \"-t$limit\" to repeat this single case.\n";
  316. stopservers($verbose);
  317. return 1;
  318. }
  319. }
  320. logmsg "torture OK\n";
  321. return 0;
  322. }
  323. #######################################################################
  324. # restore environment variables that were modified in test
  325. sub restore_test_env {
  326. my $deleteoldenv = $_[0]; # 1 to delete the saved contents after restore
  327. foreach my $var (keys %oldenv) {
  328. if($oldenv{$var} eq 'notset') {
  329. delete $ENV{$var} if($ENV{$var});
  330. }
  331. else {
  332. $ENV{$var} = $oldenv{$var};
  333. }
  334. if($deleteoldenv) {
  335. delete $oldenv{$var};
  336. }
  337. }
  338. }
  339. #######################################################################
  340. # Start the servers needed to run this test case
  341. sub singletest_startservers {
  342. my ($testnum, $testtimings) = @_;
  343. # remove test server commands file before servers are started/verified
  344. unlink($FTPDCMD) if(-f $FTPDCMD);
  345. # timestamp required servers verification start
  346. $$testtimings{"timesrvrini"} = Time::HiRes::time();
  347. my $why;
  348. if (!$listonly) {
  349. my @what = getpart("client", "server");
  350. if(!$what[0]) {
  351. warn "Test case $testnum has no server(s) specified";
  352. $why = "no server specified";
  353. } else {
  354. my $err;
  355. ($why, $err) = serverfortest(@what);
  356. if($err == 1) {
  357. # Error indicates an actual problem starting the server, so
  358. # display the server logs
  359. displaylogs($testnum);
  360. }
  361. }
  362. }
  363. # timestamp required servers verification end
  364. $$testtimings{"timesrvrend"} = Time::HiRes::time();
  365. # remove server output logfile after servers are started/verified
  366. unlink($SERVERIN);
  367. unlink($SERVER2IN);
  368. unlink($PROXYIN);
  369. return $why;
  370. }
  371. #######################################################################
  372. # Generate preprocessed test file
  373. sub singletest_preprocess {
  374. my $testnum = $_[0];
  375. # Save a preprocessed version of the entire test file. This allows more
  376. # "basic" test case readers to enjoy variable replacements.
  377. my @entiretest = fulltest();
  378. my $otest = "$LOGDIR/test$testnum";
  379. @entiretest = prepro($testnum, @entiretest);
  380. # save the new version
  381. open(my $fulltesth, ">", "$otest") || die "Failure writing test file";
  382. foreach my $bytes (@entiretest) {
  383. print $fulltesth pack('a*', $bytes) or die "Failed to print '$bytes': $!";
  384. }
  385. close($fulltesth) || die "Failure writing test file";
  386. # in case the process changed the file, reload it
  387. loadtest("$LOGDIR/test${testnum}");
  388. }
  389. #######################################################################
  390. # Set up the test environment to run this test case
  391. sub singletest_setenv {
  392. my @setenv = getpart("client", "setenv");
  393. foreach my $s (@setenv) {
  394. chomp $s;
  395. if($s =~ /([^=]*)=(.*)/) {
  396. my ($var, $content) = ($1, $2);
  397. # remember current setting, to restore it once test runs
  398. $oldenv{$var} = ($ENV{$var})?"$ENV{$var}":'notset';
  399. # set new value
  400. if(!$content) {
  401. delete $ENV{$var} if($ENV{$var});
  402. }
  403. else {
  404. if($var =~ /^LD_PRELOAD/) {
  405. if(exe_ext('TOOL') && (exe_ext('TOOL') eq '.exe')) {
  406. # print "Skipping LD_PRELOAD due to lack of OS support\n";
  407. next;
  408. }
  409. if($feature{"debug"} || !$has_shared) {
  410. # print "Skipping LD_PRELOAD due to no release shared build\n";
  411. next;
  412. }
  413. }
  414. $ENV{$var} = "$content";
  415. print "setenv $var = $content\n" if($verbose);
  416. }
  417. }
  418. }
  419. if($proxy_address) {
  420. $ENV{http_proxy} = $proxy_address;
  421. $ENV{HTTPS_PROXY} = $proxy_address;
  422. }
  423. }
  424. #######################################################################
  425. # Check that test environment is fine to run this test case
  426. sub singletest_precheck {
  427. my $testnum = $_[0];
  428. my $why;
  429. my @precheck = getpart("client", "precheck");
  430. if(@precheck) {
  431. my $cmd = $precheck[0];
  432. chomp $cmd;
  433. if($cmd) {
  434. my @p = split(/ /, $cmd);
  435. if($p[0] !~ /\//) {
  436. # the first word, the command, does not contain a slash so
  437. # we will scan the "improved" PATH to find the command to
  438. # be able to run it
  439. my $fullp = checktestcmd($p[0]);
  440. if($fullp) {
  441. $p[0] = $fullp;
  442. }
  443. $cmd = join(" ", @p);
  444. }
  445. my @o = `$cmd 2> $LOGDIR/precheck-$testnum`;
  446. if($o[0]) {
  447. $why = $o[0];
  448. $why =~ s/[\r\n]//g;
  449. }
  450. elsif($?) {
  451. $why = "precheck command error";
  452. }
  453. logmsg "prechecked $cmd\n" if($verbose);
  454. }
  455. }
  456. return $why;
  457. }
  458. #######################################################################
  459. # Prepare the test environment to run this test case
  460. sub singletest_prepare {
  461. my ($testnum) = @_;
  462. if($feature{"TrackMemory"}) {
  463. unlink($memdump);
  464. }
  465. unlink("core");
  466. # if this section exists, it might be FTP server instructions:
  467. my @ftpservercmd = getpart("reply", "servercmd");
  468. push @ftpservercmd, "Testnum $testnum\n";
  469. # write the instructions to file
  470. writearray($FTPDCMD, \@ftpservercmd);
  471. # create (possibly-empty) files before starting the test
  472. for my $partsuffix (('', '1', '2', '3', '4')) {
  473. my @inputfile=getpart("client", "file".$partsuffix);
  474. my %fileattr = getpartattr("client", "file".$partsuffix);
  475. my $filename=$fileattr{'name'};
  476. if(@inputfile || $filename) {
  477. if(!$filename) {
  478. logmsg "ERROR: section client=>file has no name attribute\n";
  479. return -1;
  480. }
  481. my $fileContent = join('', @inputfile);
  482. # make directories if needed
  483. my $path = $filename;
  484. # cut off the file name part
  485. $path =~ s/^(.*)\/[^\/]*/$1/;
  486. my @parts = split(/\//, $path);
  487. if($parts[0] eq $LOGDIR) {
  488. # the file is in $LOGDIR/
  489. my $d = shift @parts;
  490. for(@parts) {
  491. $d .= "/$_";
  492. mkdir $d; # 0777
  493. }
  494. }
  495. if (open(my $outfile, ">", "$filename")) {
  496. binmode $outfile; # for crapage systems, use binary
  497. if($fileattr{'nonewline'}) {
  498. # cut off the final newline
  499. chomp($fileContent);
  500. }
  501. print $outfile $fileContent;
  502. close($outfile);
  503. } else {
  504. logmsg "ERROR: cannot write $filename\n";
  505. }
  506. }
  507. }
  508. return 0;
  509. }
  510. #######################################################################
  511. # Run the test command
  512. sub singletest_run {
  513. my ($testnum, $testtimings) = @_;
  514. # get the command line options to use
  515. my ($cmd, @blaha)= getpart("client", "command");
  516. if($cmd) {
  517. # make some nice replace operations
  518. $cmd =~ s/\n//g; # no newlines please
  519. # substitute variables in the command line
  520. }
  521. else {
  522. # there was no command given, use something silly
  523. $cmd="-";
  524. }
  525. my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout
  526. # if stdout section exists, we verify that the stdout contained this:
  527. my $out="";
  528. my %cmdhash = getpartattr("client", "command");
  529. if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-output/)) {
  530. #We may slap on --output!
  531. if (!partexists("verify", "stdout") ||
  532. ($cmdhash{'option'} && $cmdhash{'option'} =~ /force-output/)) {
  533. $out=" --output $CURLOUT ";
  534. }
  535. }
  536. # redirected stdout/stderr to these files
  537. $STDOUT="$LOGDIR/stdout$testnum";
  538. $STDERR="$LOGDIR/stderr$testnum";
  539. my @codepieces = getpart("client", "tool");
  540. my $tool="";
  541. if(@codepieces) {
  542. $tool = $codepieces[0];
  543. chomp $tool;
  544. $tool .= exe_ext('TOOL');
  545. }
  546. my $disablevalgrind;
  547. my $CMDLINE="";
  548. my $cmdargs;
  549. my $cmdtype = $cmdhash{'type'} || "default";
  550. my $fail_due_event_based = $run_event_based;
  551. if($cmdtype eq "perl") {
  552. # run the command line prepended with "perl"
  553. $cmdargs ="$cmd";
  554. $CMDLINE = "$perl ";
  555. $tool=$CMDLINE;
  556. $disablevalgrind=1;
  557. }
  558. elsif($cmdtype eq "shell") {
  559. # run the command line prepended with "/bin/sh"
  560. $cmdargs ="$cmd";
  561. $CMDLINE = "/bin/sh ";
  562. $tool=$CMDLINE;
  563. $disablevalgrind=1;
  564. }
  565. elsif(!$tool && !$keywords{"unittest"}) {
  566. # run curl, add suitable command line options
  567. my $inc="";
  568. if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-include/)) {
  569. $inc = " --include";
  570. }
  571. $cmdargs = "$out$inc ";
  572. if($cmdhash{'option'} && ($cmdhash{'option'} =~ /binary-trace/)) {
  573. $cmdargs .= "--trace $LOGDIR/trace$testnum ";
  574. }
  575. else {
  576. $cmdargs .= "--trace-ascii $LOGDIR/trace$testnum ";
  577. }
  578. $cmdargs .= "--trace-time ";
  579. if($run_event_based) {
  580. $cmdargs .= "--test-event ";
  581. $fail_due_event_based--;
  582. }
  583. $cmdargs .= $cmd;
  584. if ($proxy_address) {
  585. $cmdargs .= " --proxy $proxy_address ";
  586. }
  587. }
  588. else {
  589. $cmdargs = " $cmd"; # $cmd is the command line for the test file
  590. $CURLOUT = $STDOUT; # sends received data to stdout
  591. # Default the tool to a unit test with the same name as the test spec
  592. if($keywords{"unittest"} && !$tool) {
  593. $tool="unit$testnum";
  594. }
  595. if($tool =~ /^lib/) {
  596. $CMDLINE="$LIBDIR/$tool";
  597. }
  598. elsif($tool =~ /^unit/) {
  599. $CMDLINE="$UNITDIR/$tool";
  600. }
  601. if(! -f $CMDLINE) {
  602. logmsg "The tool set in the test case for this: '$tool' does not exist\n";
  603. return (-1, 0, 0, "", "", 0);
  604. }
  605. $DBGCURL=$CMDLINE;
  606. }
  607. if($fail_due_event_based) {
  608. logmsg "This test cannot run event based\n";
  609. return (-1, 0, 0, "", "", 0);
  610. }
  611. if($gdbthis) {
  612. # gdb is incompatible with valgrind, so disable it when debugging
  613. # Perhaps a better approach would be to run it under valgrind anyway
  614. # with --db-attach=yes or --vgdb=yes.
  615. $disablevalgrind=1;
  616. }
  617. my @stdintest = getpart("client", "stdin");
  618. if(@stdintest) {
  619. my $stdinfile="$LOGDIR/stdin-for-$testnum";
  620. my %hash = getpartattr("client", "stdin");
  621. if($hash{'nonewline'}) {
  622. # cut off the final newline from the final line of the stdin data
  623. chomp($stdintest[-1]);
  624. }
  625. writearray($stdinfile, \@stdintest);
  626. $cmdargs .= " <$stdinfile";
  627. }
  628. if(!$tool) {
  629. $CMDLINE="$CURL";
  630. }
  631. if(use_valgrind() && !$disablevalgrind) {
  632. my $valgrindcmd = "$valgrind ";
  633. $valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
  634. $valgrindcmd .= "--quiet --leak-check=yes ";
  635. $valgrindcmd .= "--suppressions=$srcdir/valgrind.supp ";
  636. # $valgrindcmd .= "--gen-suppressions=all ";
  637. $valgrindcmd .= "--num-callers=16 ";
  638. $valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
  639. $CMDLINE = "$valgrindcmd $CMDLINE";
  640. }
  641. $CMDLINE .= "$cmdargs >$STDOUT 2>$STDERR";
  642. if($verbose) {
  643. logmsg "$CMDLINE\n";
  644. }
  645. open(my $cmdlog, ">", $CURLLOG) || die "Failure writing log file";
  646. print $cmdlog "$CMDLINE\n";
  647. close($cmdlog) || die "Failure writing log file";
  648. my $dumped_core;
  649. my $cmdres;
  650. if($gdbthis) {
  651. my $gdbinit = "$TESTDIR/gdbinit$testnum";
  652. open(my $gdbcmd, ">", "$LOGDIR/gdbcmd") || die "Failure writing gdb file";
  653. print $gdbcmd "set args $cmdargs\n";
  654. print $gdbcmd "show args\n";
  655. print $gdbcmd "source $gdbinit\n" if -e $gdbinit;
  656. close($gdbcmd) || die "Failure writing gdb file";
  657. }
  658. # Flush output.
  659. $| = 1;
  660. # timestamp starting of test command
  661. $$testtimings{"timetoolini"} = Time::HiRes::time();
  662. # run the command line we built
  663. if ($torture) {
  664. $cmdres = torture($CMDLINE,
  665. $testnum,
  666. "$gdb --directory $LIBDIR $DBGCURL -x $LOGDIR/gdbcmd");
  667. }
  668. elsif($gdbthis) {
  669. my $GDBW = ($gdbxwin) ? "-w" : "";
  670. runclient("$gdb --directory $LIBDIR $DBGCURL $GDBW -x $LOGDIR/gdbcmd");
  671. $cmdres=0; # makes it always continue after a debugged run
  672. }
  673. else {
  674. # Convert the raw result code into a more useful one
  675. ($cmdres, $dumped_core) = normalize_cmdres(runclient("$CMDLINE"));
  676. }
  677. # timestamp finishing of test command
  678. $$testtimings{"timetoolend"} = Time::HiRes::time();
  679. return (0, $cmdres, $dumped_core, $CURLOUT, $tool, use_valgrind() && !$disablevalgrind);
  680. }
  681. #######################################################################
  682. # Clean up after test command
  683. sub singletest_clean {
  684. my ($testnum, $dumped_core, $testtimings)=@_;
  685. if(!$dumped_core) {
  686. if(-r "core") {
  687. # there's core file present now!
  688. $dumped_core = 1;
  689. }
  690. }
  691. if($dumped_core) {
  692. logmsg "core dumped\n";
  693. if(0 && $gdb) {
  694. logmsg "running gdb for post-mortem analysis:\n";
  695. open(my $gdbcmd, ">", "$LOGDIR/gdbcmd2") || die "Failure writing gdb file";
  696. print $gdbcmd "bt\n";
  697. close($gdbcmd) || die "Failure writing gdb file";
  698. runclient("$gdb --directory libtest -x $LOGDIR/gdbcmd2 -batch $DBGCURL core ");
  699. # unlink("$LOGDIR/gdbcmd2");
  700. }
  701. }
  702. # If a server logs advisor read lock file exists, it is an indication
  703. # that the server has not yet finished writing out all its log files,
  704. # including server request log files used for protocol verification.
  705. # So, if the lock file exists the script waits here a certain amount
  706. # of time until the server removes it, or the given time expires.
  707. my $serverlogslocktimeout = $defserverlogslocktimeout;
  708. my %cmdhash = getpartattr("client", "command");
  709. if($cmdhash{'timeout'}) {
  710. # test is allowed to override default server logs lock timeout
  711. if($cmdhash{'timeout'} =~ /(\d+)/) {
  712. $serverlogslocktimeout = $1 if($1 >= 0);
  713. }
  714. }
  715. if($serverlogslocktimeout) {
  716. my $lockretry = $serverlogslocktimeout * 20;
  717. while((-f $SERVERLOGS_LOCK) && $lockretry--) {
  718. portable_sleep(0.05);
  719. }
  720. if(($lockretry < 0) &&
  721. ($serverlogslocktimeout >= $defserverlogslocktimeout)) {
  722. logmsg "Warning: server logs lock timeout ",
  723. "($serverlogslocktimeout seconds) expired\n";
  724. }
  725. }
  726. # Test harness ssh server does not have this synchronization mechanism,
  727. # this implies that some ssh server based tests might need a small delay
  728. # once that the client command has run to avoid false test failures.
  729. #
  730. # gnutls-serv also lacks this synchronization mechanism, so gnutls-serv
  731. # based tests might need a small delay once that the client command has
  732. # run to avoid false test failures.
  733. my $postcommanddelay = $defpostcommanddelay;
  734. if($cmdhash{'delay'}) {
  735. # test is allowed to specify a delay after command is executed
  736. if($cmdhash{'delay'} =~ /(\d+)/) {
  737. $postcommanddelay = $1 if($1 > 0);
  738. }
  739. }
  740. portable_sleep($postcommanddelay) if($postcommanddelay);
  741. # timestamp removal of server logs advisor read lock
  742. $$testtimings{"timesrvrlog"} = Time::HiRes::time();
  743. # test definition might instruct to stop some servers
  744. # stop also all servers relative to the given one
  745. my @killtestservers = getpart("client", "killserver");
  746. if(@killtestservers) {
  747. foreach my $server (@killtestservers) {
  748. chomp $server;
  749. if(stopserver($server)) {
  750. logmsg " killserver FAILED\n";
  751. return 1; # normal error if asked to fail on unexpected alive
  752. }
  753. }
  754. }
  755. return 0;
  756. }
  757. #######################################################################
  758. # Verify that the postcheck succeeded
  759. sub singletest_postcheck {
  760. my ($testnum)=@_;
  761. # run the postcheck command
  762. my @postcheck= getpart("client", "postcheck");
  763. if(@postcheck) {
  764. my $cmd = join("", @postcheck);
  765. chomp $cmd;
  766. if($cmd) {
  767. logmsg "postcheck $cmd\n" if($verbose);
  768. my $rc = runclient("$cmd");
  769. # Must run the postcheck command in torture mode in order
  770. # to clean up, but the result can't be relied upon.
  771. if($rc != 0 && !$torture) {
  772. logmsg " postcheck FAILED\n";
  773. return -1;
  774. }
  775. }
  776. }
  777. return 0;
  778. }
  779. ###################################################################
  780. # Get ready to run a single test case
  781. sub runner_test_preprocess {
  782. my ($testnum)=@_;
  783. my %testtimings;
  784. # timestamp test preparation start
  785. # TODO: this metric now shows only a portion of the prep time; better would
  786. # be to time singletest_preprocess below instead
  787. $testtimings{"timeprepini"} = Time::HiRes::time();
  788. ###################################################################
  789. # Load test metadata
  790. # ignore any error here--if there were one, it would have been
  791. # caught during the selection phase and this test would not be
  792. # running now
  793. loadtest("${TESTDIR}/test${testnum}");
  794. readtestkeywords();
  795. ###################################################################
  796. # Start the servers needed to run this test case
  797. my $why = singletest_startservers($testnum, \%testtimings);
  798. if(!$why) {
  799. ###############################################################
  800. # Generate preprocessed test file
  801. # This must be done after the servers are started so server
  802. # variables are available for substitution.
  803. singletest_preprocess($testnum);
  804. ###############################################################
  805. # Set up the test environment to run this test case
  806. singletest_setenv();
  807. ###############################################################
  808. # Check that the test environment is fine to run this test case
  809. if (!$listonly) {
  810. $why = singletest_precheck($testnum);
  811. }
  812. }
  813. return ($why, \%testtimings);
  814. }
  815. ###################################################################
  816. # Run a single test case with an environment that already been prepared
  817. # Returns 0=success, -1=skippable failure, -2=permanent error,
  818. # 1=unskippable test failure, as first integer, plus more return
  819. # values when error is 0
  820. sub runner_test_run {
  821. my ($testnum)=@_;
  822. my %testtimings;
  823. #######################################################################
  824. # Prepare the test environment to run this test case
  825. my $error = singletest_prepare($testnum);
  826. if($error) {
  827. return -2;
  828. }
  829. #######################################################################
  830. # Run the test command
  831. my $cmdres;
  832. my $dumped_core;
  833. my $CURLOUT;
  834. my $tool;
  835. my $usedvalgrind;
  836. ($error, $cmdres, $dumped_core, $CURLOUT, $tool, $usedvalgrind) = singletest_run($testnum, \%testtimings);
  837. if($error) {
  838. return (-2, \%testtimings);
  839. }
  840. #######################################################################
  841. # Clean up after test command
  842. $error = singletest_clean($testnum, $dumped_core, \%testtimings);
  843. if($error) {
  844. return ($error, \%testtimings);
  845. }
  846. #######################################################################
  847. # Verify that the postcheck succeeded
  848. $error = singletest_postcheck($testnum);
  849. if($error) {
  850. return ($error, \%testtimings);
  851. }
  852. #######################################################################
  853. # restore environment variables that were modified
  854. restore_test_env(0);
  855. return (0, \%testtimings, $cmdres, $CURLOUT, $tool, $usedvalgrind);
  856. }
  857. 1;