testcurl.pl 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. #!/usr/bin/env perl
  2. #***************************************************************************
  3. # _ _ ____ _
  4. # Project ___| | | | _ \| |
  5. # / __| | | | |_) | |
  6. # | (__| |_| | _ <| |___
  7. # \___|\___/|_| \_\_____|
  8. #
  9. # Copyright (C) 1998 - 2008, Daniel Stenberg, <[email protected]>, et al.
  10. #
  11. # This software is licensed as described in the file COPYING, which
  12. # you should have received as part of this distribution. The terms
  13. # are also available at http://curl.haxx.se/docs/copyright.html.
  14. #
  15. # You may opt to use, copy, modify, merge, publish, distribute and/or sell
  16. # copies of the Software, and permit persons to whom the Software is
  17. # furnished to do so, under the terms of the COPYING file.
  18. #
  19. # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  20. # KIND, either express or implied.
  21. #
  22. # $Id$
  23. ###########################################################################
  24. ###########################
  25. # What is This Script?
  26. ###########################
  27. # testcurl.pl is the master script to use for automatic testing of CVS-curl.
  28. # This is written for the purpose of being run from a crontab job or similar
  29. # at a regular interval. The output is suitable to be mailed to
  30. # [email protected] to be dealt with automatically (make sure the
  31. # subject includes the word "autobuild" as the mail gets silently discarded
  32. # otherwise). The most current build status (with a resonable backlog) will
  33. # be published on the curl site, at http://curl.haxx.se/auto/
  34. # USAGE:
  35. # testcurl.pl [options] [curl-daily-name] > output
  36. # Options:
  37. #
  38. # --configure=[options] Configure options
  39. # --crosscompile This is a crosscompile
  40. # --desc=[desc] Description of your test system
  41. # --email=[email] Set email address to report as
  42. # --extvercmd=[command] Command to use for displaying version with cross compiles.
  43. # --mktarball=[command] Command to run after completed test
  44. # --name=[name] Set name to report as
  45. # --nocvsup Don't update from CVS even though it is a CVS tree
  46. # --nobuildconf Don't run buildconf
  47. # --runtestopts=[options] Options to pass to runtests.pl
  48. # --setup=[file name] File name to read setup from (deprecated)
  49. # --target=[your os] Specify your target environment.
  50. #
  51. # if [curl-daily-name] is omitted, a 'curl' CVS directory is assumed.
  52. #
  53. use strict;
  54. use Cwd;
  55. # Turn on warnings (equivalent to -w, which can't be used with /usr/bin/env)
  56. #BEGIN { $^W = 1; }
  57. use vars qw($version $fixed $infixed $CURLDIR $CVS $pwd $build $buildlog
  58. $buildlogname $configurebuild $targetos $confsuffix $binext
  59. $libext);
  60. use vars qw($name $email $desc $confopts $runtestopts $setupfile $mktarball
  61. $extvercmd $nocvsup $nobuildconf $crosscompile $timestamp);
  62. # version of this script
  63. $version='$Revision$';
  64. $fixed=0;
  65. # Determine if we're running from CVS or a canned copy of curl,
  66. # or if we got a specific target option or setup file option.
  67. $CURLDIR="curl";
  68. $CVS=1;
  69. $setupfile = 'setup';
  70. while ($ARGV[0]) {
  71. if ($ARGV[0] =~ /--target=/) {
  72. $targetos = (split(/=/, shift @ARGV))[1];
  73. }
  74. elsif ($ARGV[0] =~ /--setup=/) {
  75. $setupfile = (split(/=/, shift @ARGV))[1];
  76. }
  77. elsif ($ARGV[0] =~ /--extvercmd=/) {
  78. $extvercmd = (split(/=/, shift @ARGV))[1];
  79. }
  80. elsif ($ARGV[0] =~ /--mktarball=/) {
  81. $mktarball = (split(/=/, shift @ARGV))[1];
  82. }
  83. elsif ($ARGV[0] =~ /--name=/) {
  84. $name = (split(/=/, shift @ARGV))[1];
  85. }
  86. elsif ($ARGV[0] =~ /--email=/) {
  87. $email = (split(/=/, shift @ARGV))[1];
  88. }
  89. elsif ($ARGV[0] =~ /--desc=/) {
  90. $desc = (split(/=/, shift @ARGV))[1];
  91. }
  92. elsif ($ARGV[0] =~ /--configure=/) {
  93. $confopts = (split(/=/, shift @ARGV))[1];
  94. }
  95. elsif ($ARGV[0] =~ /--nocvsup/) {
  96. $nocvsup=1;
  97. shift @ARGV;
  98. }
  99. elsif ($ARGV[0] =~ /--nobuildconf/) {
  100. $nobuildconf=1;
  101. shift @ARGV;
  102. }
  103. elsif ($ARGV[0] =~ /--crosscompile/) {
  104. $crosscompile=1;
  105. shift @ARGV;
  106. }
  107. elsif ($ARGV[0] =~ /--runtestopts=/) {
  108. $runtestopts = (split(/=/, shift @ARGV, 2))[1];
  109. }
  110. else {
  111. $CURLDIR=shift @ARGV;
  112. $CVS=0;
  113. }
  114. }
  115. # Do the platform-specific stuff here
  116. $configurebuild = 1;
  117. $confsuffix = '';
  118. $binext = '';
  119. $libext = '.la'; # .la since both libcurl and libcares are made with libtool
  120. if ($^O eq 'MSWin32' || $targetos) {
  121. if (!$targetos) {
  122. # If no target defined on Win32 lets assume vc
  123. $targetos = 'vc';
  124. }
  125. if ($targetos =~ /vc/ || $targetos =~ /borland/) {
  126. $binext = '.exe';
  127. $libext = '.lib';
  128. }
  129. elsif ($targetos =~ /mingw32/) {
  130. $binext = '.exe';
  131. if ($^O eq 'MSWin32') {
  132. $libext = '.a';
  133. }
  134. }
  135. elsif ($targetos =~ /netware/) {
  136. $configurebuild = 0;
  137. $binext = '.nlm';
  138. if ($^O eq 'MSWin32') {
  139. $libext = '.lib';
  140. }
  141. else {
  142. $libext = '.a';
  143. }
  144. }
  145. }
  146. if (($^O eq 'MSWin32') &&
  147. ($targetos =~ /vc/ || $targetos =~ /mingw32/ || $targetos =~ /borland/)) {
  148. # Set these things only when building ON Windows and for Win32 platform.
  149. # FOR Windows since we might be cross-compiling on another system. Non-
  150. # Windows builds still default to configure-style builds with no confsuffix.
  151. $configurebuild = 0;
  152. $confsuffix = '-win32';
  153. }
  154. $ENV{LANG}="C";
  155. sub rmtree($) {
  156. my $target = $_[0];
  157. if ($^O eq 'MSWin32') {
  158. foreach (glob($target)) {
  159. s:/:\\:g;
  160. system("rd /s /q $_");
  161. }
  162. } else {
  163. system("rm -rf $target");
  164. }
  165. }
  166. sub grepfile($$) {
  167. my ($target, $fn) = @_;
  168. open(F, $fn) or die;
  169. while (<F>) {
  170. if (/$target/) {
  171. close(F);
  172. return 1;
  173. }
  174. }
  175. close(F);
  176. return 0;
  177. }
  178. sub logit($) {
  179. my $text=$_[0];
  180. if ($text) {
  181. print "testcurl: $text\n";
  182. }
  183. }
  184. sub mydie($){
  185. my $text=$_[0];
  186. logit "$text";
  187. chdir $pwd; # cd back to the original root dir
  188. if ($pwd && $build) {
  189. # we have a build directory name, remove the dir
  190. logit "removing the $build dir";
  191. rmtree "$pwd/$build";
  192. }
  193. if (-r $buildlog) {
  194. # we have a build log output file left, remove it
  195. logit "removing the $buildlogname file";
  196. unlink "$buildlog";
  197. }
  198. logit "ENDING HERE"; # last line logged!
  199. exit 1;
  200. }
  201. if (open(F, "$setupfile")) {
  202. while (<F>) {
  203. if (/(\w+)=(.*)/) {
  204. eval "\$$1=$2;";
  205. }
  206. }
  207. close(F);
  208. $infixed=$fixed;
  209. } else {
  210. $infixed=0; # so that "additional args to configure" works properly first time...
  211. }
  212. if (!$name) {
  213. print "please enter your name\n";
  214. $name = <>;
  215. chomp $name;
  216. $fixed=1;
  217. }
  218. if (!$email) {
  219. print "please enter your contact email address\n";
  220. $email = <>;
  221. chomp $email;
  222. $fixed=2;
  223. }
  224. if (!$desc) {
  225. print "please enter a one line system description\n";
  226. $desc = <>;
  227. chomp $desc;
  228. $fixed=3;
  229. }
  230. if (!$confopts) {
  231. if ($infixed < 4) {
  232. print "please enter your additional arguments to configure\n";
  233. print "examples: --with-ssl --enable-debug --enable-ipv6 --with-krb4\n";
  234. $confopts = <>;
  235. chomp $confopts;
  236. }
  237. }
  238. if ($fixed < 4) {
  239. $fixed=4;
  240. open(F, ">$setupfile") or die;
  241. print F "name='$name'\n";
  242. print F "email='$email'\n";
  243. print F "desc='$desc'\n";
  244. print F "confopts='$confopts'\n";
  245. print F "fixed='$fixed'\n";
  246. close(F);
  247. }
  248. my $str1066os = 'o' x 1066;
  249. # Set timestamp to the UTC this script is running. Its value might
  250. # be changed later in the script to the value present in curlver.h
  251. $timestamp = scalar(gmtime)." UTC";
  252. logit "STARTING HERE"; # first line logged, for scripts to trigger on
  253. logit 'TRANSFER CONTROL ==== 1120 CHAR LINE' . $str1066os . 'LINE_END';
  254. logit "NAME = $name";
  255. logit "EMAIL = $email";
  256. logit "DESC = $desc";
  257. logit "CONFOPTS = $confopts";
  258. logit "CPPFLAGS = ".$ENV{CPPFLAGS};
  259. logit "CFLAGS = ".$ENV{CFLAGS};
  260. logit "LDFLAGS = ".$ENV{LDFLAGS};
  261. logit "CC = ".$ENV{CC};
  262. logit "target = ".$targetos;
  263. logit "version = $version"; # script version
  264. logit "date = $timestamp"; # When the test build starts
  265. $str1066os = undef;
  266. # Make $pwd to become the path without newline. We'll use that in order to cut
  267. # off that path from all possible logs and error messages etc.
  268. $pwd = getcwd();
  269. if (-d $CURLDIR) {
  270. if ($CVS && -d "$CURLDIR/CVS") {
  271. logit "$CURLDIR is verified to be a fine source dir";
  272. # remove the generated sources to force them to be re-generated each
  273. # time we run this test
  274. unlink "$CURLDIR/src/hugehelp.c";
  275. } elsif (!$CVS && -f "$CURLDIR/tests/testcurl.pl") {
  276. logit "$CURLDIR is verified to be a fine daily source dir"
  277. } else {
  278. mydie "$CURLDIR is not a daily source dir or checked out from CVS!"
  279. }
  280. }
  281. $build="build-$$";
  282. $buildlogname="buildlog-$$";
  283. $buildlog="$pwd/$buildlogname";
  284. # remove any previous left-overs
  285. rmtree "build-*";
  286. rmtree "buildlog-*";
  287. # this is to remove old build logs that ended up in the wrong dir
  288. foreach (glob("$CURLDIR/buildlog-*")) { unlink $_; }
  289. # create a dir to build in
  290. mkdir $build, 0777;
  291. if (-d $build) {
  292. logit "build dir $build was created fine";
  293. } else {
  294. mydie "failed to create dir $build";
  295. }
  296. # get in the curl source tree root
  297. chdir $CURLDIR;
  298. # Do the CVS thing, or not...
  299. if ($CVS) {
  300. # this is a temporary fix to make things work again, remove later
  301. logit "remove ares/aclocal.m4";
  302. unlink "ares/aclocal.m4";
  303. logit "update from CVS";
  304. my $cvsstat;
  305. sub cvsup() {
  306. # update quietly to the latest CVS
  307. if($nocvsup) {
  308. logit "Skipping CVS update (--nocvsup)";
  309. return 1;
  310. }
  311. else {
  312. logit "run cvs up";
  313. system("cvs -Q up -dP 2>&1");
  314. }
  315. $cvsstat=$?;
  316. # return !RETURNVALUE so that errors return 0 while goodness
  317. # returns 1
  318. return !$cvsstat;
  319. }
  320. my $att=0;
  321. while (!cvsup()) {
  322. $att++;
  323. logit "failed CVS update attempt number $att.";
  324. if ($att > 20) {
  325. $cvsstat=111;
  326. last; # get out of the loop
  327. }
  328. sleep 5;
  329. }
  330. if ($cvsstat != 0) {
  331. mydie "failed to update from CVS ($cvsstat), exiting";
  332. }
  333. elsif (!$nocvsup) {
  334. # Set timestamp to the UTC the CVS update took place.
  335. $timestamp = scalar(gmtime)." UTC";
  336. }
  337. if($nobuildconf) {
  338. logit "told to not run buildconf";
  339. }
  340. elsif ($configurebuild) {
  341. # remove possible left-overs from the past
  342. unlink "configure";
  343. unlink "autom4te.cache";
  344. # generate the build files
  345. logit "invoke buildconf, but filter off aclocal underquoted definition warnings";
  346. open(F, "./buildconf 2>&1 |") or die;
  347. open(LOG, ">$buildlog") or die;
  348. while (<F>) {
  349. next if /warning: underquoted definition of/;
  350. print;
  351. print LOG;
  352. }
  353. close(F);
  354. close(LOG);
  355. if (grepfile("^buildconf: OK", $buildlog)) {
  356. logit "buildconf was successful";
  357. }
  358. else {
  359. mydie "buildconf was NOT successful";
  360. }
  361. }
  362. else {
  363. logit "buildconf was successful (dummy message)";
  364. }
  365. }
  366. # Set timestamp to the one in curlver.h if this isn't a CVS test build.
  367. if ((-f "include/curl/curlver.h") &&
  368. (open(F, "<include/curl/curlver.h"))) {
  369. while (<F>) {
  370. chomp;
  371. if ($_ =~ /^\#define\s+LIBCURL_TIMESTAMP\s+\"(.+)\".*$/) {
  372. my $stampstring = $1;
  373. if ($stampstring !~ /CVS/) {
  374. $stampstring =~ s/\s+UTC//;
  375. $timestamp = $stampstring." UTC";
  376. }
  377. last;
  378. }
  379. }
  380. close(F);
  381. }
  382. # Show timestamp we are using for this test build.
  383. logit "timestamp = $timestamp";
  384. if ($configurebuild) {
  385. if (-f "configure") {
  386. logit "configure created (at least it exists)";
  387. } else {
  388. mydie "no configure created/found";
  389. }
  390. } else {
  391. logit "configure created (dummy message)"; # dummy message to feign success
  392. }
  393. sub findinpath {
  394. my $c;
  395. my $e;
  396. my $x='';
  397. $x='.exe' if ($^O eq 'MSWin32');
  398. my $s=':';
  399. $s=';' if ($^O eq 'MSWin32');
  400. my $p=$ENV{'PATH'};
  401. my @pa = split($s, $p);
  402. for $c (@_) {
  403. for $e (@pa) {
  404. if( -x "$e/$c$x") {
  405. return $c;
  406. }
  407. }
  408. }
  409. }
  410. my $make = findinpath("gmake", "make", "nmake");
  411. if(!$make) {
  412. mydie "Couldn't find make in the PATH";
  413. }
  414. logit "going with $make as make";
  415. # change to build dir
  416. chdir "$pwd/$build";
  417. if ($configurebuild) {
  418. # run configure script
  419. print `../$CURLDIR/configure $confopts 2>&1`;
  420. if (-f "lib/Makefile") {
  421. logit "configure seems to have finished fine";
  422. } else {
  423. mydie "configure didn't work";
  424. }
  425. } else {
  426. logit "copying files to build dir ...";
  427. if (($^O eq 'MSWin32') && ($targetos !~ /netware/)) {
  428. system("xcopy /s /q ..\\$CURLDIR .");
  429. system("buildconf.bat");
  430. }
  431. elsif ($targetos =~ /netware/) {
  432. system("cp -afr ../$CURLDIR/* .");
  433. system("cp -af ../$CURLDIR/Makefile.dist Makefile");
  434. system("$make -i -C lib -f Makefile.netware prebuild");
  435. system("$make -i -C src -f Makefile.netware prebuild");
  436. }
  437. elsif ($^O eq 'linux') {
  438. system("cp -afr ../$CURLDIR/* .");
  439. system("cp -af ../$CURLDIR/Makefile.dist Makefile");
  440. system("cp -af ../$CURLDIR/include/curl/curlbuild.h.dist ./include/curl/curlbuild.h");
  441. system("$make -i -C lib -f Makefile.$targetos prebuild");
  442. system("$make -i -C src -f Makefile.$targetos prebuild");
  443. }
  444. }
  445. if(-f "./include/curl/curlbuild.h") {
  446. logit "display include/curl/curlbuild.h";
  447. if(open(F, "<./include/curl/curlbuild.h")) {
  448. while(<F>) {
  449. my $ll = $_;
  450. print $ll if(($ll =~ /^ *# *define/) && ($ll !~ /__CURL_CURLBUILD_H/));
  451. }
  452. close(F);
  453. }
  454. }
  455. else {
  456. mydie "no curlbuild.h created/found";
  457. }
  458. logit "display lib/config$confsuffix.h";
  459. open(F, "lib/config$confsuffix.h") or die "lib/config$confsuffix.h: $!";
  460. while (<F>) {
  461. print if /^ *#/;
  462. }
  463. close(F);
  464. if (grepfile("define USE_ARES", "lib/config$confsuffix.h")) {
  465. logit "setup to build ares";
  466. logit "display ares/config$confsuffix.h";
  467. if(open(F, "ares/config$confsuffix.h")) {
  468. while (<F>) {
  469. print if /^ *#/;
  470. }
  471. close(F);
  472. }
  473. logit "build ares";
  474. chdir "ares";
  475. if ($targetos && !$configurebuild) {
  476. logit "$make -f Makefile.$targetos";
  477. open(F, "$make -f Makefile.$targetos 2>&1 |") or die;
  478. }
  479. else {
  480. logit "$make";
  481. open(F, "$make 2>&1 |") or die;
  482. }
  483. while (<F>) {
  484. s/$pwd//g;
  485. print;
  486. }
  487. close(F);
  488. if (-f "libcares$libext") {
  489. logit "ares is now built successfully (libcares$libext)";
  490. } else {
  491. logit "ares build failed (libares$libext)";
  492. }
  493. # cd back to the curl build dir
  494. chdir "$pwd/$build";
  495. }
  496. if ($configurebuild) {
  497. logit "$make -i";
  498. open(F, "$make -i 2>&1 |") or die;
  499. while (<F>) {
  500. s/$pwd//g;
  501. print;
  502. }
  503. close(F);
  504. }
  505. else {
  506. logit "$make -i $targetos";
  507. if ($^O eq 'MSWin32') {
  508. if ($targetos =~ /vc/) {
  509. open(F, "nmake -i $targetos|") or die;
  510. }
  511. else {
  512. open(F, "$make -i $targetos |") or die;
  513. }
  514. }
  515. else {
  516. open(F, "$make -i $targetos 2>&1 |") or die;
  517. }
  518. while (<F>) {
  519. s/$pwd//g;
  520. print;
  521. }
  522. close(F);
  523. }
  524. if (-f "lib/libcurl$libext") {
  525. logit "libcurl was created fine (libcurl$libext)";
  526. }
  527. else {
  528. mydie "libcurl was not created (libcurl$libext)";
  529. }
  530. if (-f "src/curl$binext") {
  531. logit "curl was created fine (curl$binext)";
  532. }
  533. else {
  534. mydie "curl was not created (curl$binext)";
  535. }
  536. if (!$crosscompile || (($extvercmd ne '') && (-x $extvercmd))) {
  537. logit "display curl${binext} --version output";
  538. my $cmd = ($extvercmd ne '' ? $extvercmd.' ' : '')."./src/curl${binext} --version|";
  539. open(F, $cmd);
  540. while(<F>) {
  541. print;
  542. print LOG;
  543. }
  544. close(F);
  545. }
  546. if ($configurebuild && !$crosscompile) {
  547. my $o;
  548. if($runtestopts) {
  549. $o = "TEST_F=\"$runtestopts\" ";
  550. }
  551. logit "$make -k ${o}test-full";
  552. open(F, "$make -k ${o}test-full 2>&1 |") or die;
  553. open(LOG, ">$buildlog") or die;
  554. while (<F>) {
  555. s/$pwd//g;
  556. print;
  557. print LOG;
  558. }
  559. close(F);
  560. close(LOG);
  561. if (grepfile("^TEST", $buildlog)) {
  562. logit "tests were run";
  563. } else {
  564. mydie "test suite failure";
  565. }
  566. if (grepfile("^TESTFAIL:", $buildlog)) {
  567. logit "the tests were not successful";
  568. } else {
  569. logit "the tests were successful!";
  570. }
  571. } else {
  572. # dummy message to feign success
  573. if($crosscompile) {
  574. logit "cross-compiling, can't run tests";
  575. }
  576. print "TESTDONE: 1 tests out of 0 (dummy message)\n";
  577. }
  578. # create a tarball if we got that option.
  579. if (($mktarball ne '') && (-x $mktarball)) {
  580. system($mktarball);
  581. }
  582. # mydie to cleanup
  583. mydie "ending nicely";