ktest.pl 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. #!/usr/bin/perl -w
  2. #
  3. # Copywrite 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
  4. # Licensed under the terms of the GNU GPL License version 2
  5. #
  6. use strict;
  7. use IPC::Open2;
  8. use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
  9. use FileHandle;
  10. $#ARGV >= 0 || die "usage: autotest.pl config-file\n";
  11. $| = 1;
  12. my %opt;
  13. #default opts
  14. $opt{"NUM_BUILDS"} = 5;
  15. $opt{"DEFAULT_BUILD_TYPE"} = "randconfig";
  16. $opt{"MAKE_CMD"} = "make";
  17. $opt{"TIMEOUT"} = 50;
  18. $opt{"TMP_DIR"} = "/tmp/autotest";
  19. $opt{"SLEEP_TIME"} = 60; # sleep time between tests
  20. $opt{"BUILD_NOCLEAN"} = 0;
  21. $opt{"REBOOT_ON_ERROR"} = 0;
  22. $opt{"POWEROFF_ON_ERROR"} = 0;
  23. $opt{"REBOOT_ON_SUCCESS"} = 1;
  24. $opt{"POWEROFF_ON_SUCCESS"} = 0;
  25. $opt{"BUILD_OPTIONS"} = "";
  26. $opt{"BISECT_SLEEP_TIME"} = 10; # sleep time between bisects
  27. my $version;
  28. my $grub_number;
  29. my $target;
  30. my $make;
  31. my $noclean;
  32. my $minconfig;
  33. my $in_bisect = 0;
  34. my $bisect_bad = "";
  35. my $reverse_bisect;
  36. my $in_patchcheck = 0;
  37. my $run_test;
  38. my $redirect;
  39. sub read_config {
  40. my ($config) = @_;
  41. open(IN, $config) || die "can't read file $config";
  42. while (<IN>) {
  43. # ignore blank lines and comments
  44. next if (/^\s*$/ || /\s*\#/);
  45. if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) {
  46. my $lvalue = $1;
  47. my $rvalue = $2;
  48. $opt{$lvalue} = $rvalue;
  49. }
  50. }
  51. close(IN);
  52. }
  53. sub logit {
  54. if (defined($opt{"LOG_FILE"})) {
  55. open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
  56. print OUT @_;
  57. close(OUT);
  58. }
  59. }
  60. sub doprint {
  61. print @_;
  62. logit @_;
  63. }
  64. sub dodie {
  65. doprint "CRITICAL FAILURE... ", @_, "\n";
  66. if ($opt{"REBOOT_ON_ERROR"}) {
  67. doprint "REBOOTING\n";
  68. `$opt{"POWER_CYCLE"}`;
  69. } elsif ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) {
  70. doprint "POWERING OFF\n";
  71. `$opt{"POWER_OFF"}`;
  72. }
  73. die @_;
  74. }
  75. sub run_command {
  76. my ($command) = @_;
  77. my $dolog = 0;
  78. my $dord = 0;
  79. my $pid;
  80. doprint("$command ... ");
  81. $pid = open(CMD, "$command 2>&1 |") or
  82. dodie "unable to exec $command";
  83. if (defined($opt{"LOG_FILE"})) {
  84. open(LOG, ">>$opt{LOG_FILE}") or
  85. dodie "failed to write to log";
  86. $dolog = 1;
  87. }
  88. if (defined($redirect)) {
  89. open (RD, ">$redirect") or
  90. dodie "failed to write to redirect $redirect";
  91. $dord = 1;
  92. }
  93. while (<CMD>) {
  94. print LOG if ($dolog);
  95. print RD if ($dord);
  96. }
  97. waitpid($pid, 0);
  98. my $failed = $?;
  99. close(CMD);
  100. close(LOG) if ($dolog);
  101. close(RD) if ($dord);
  102. if ($failed) {
  103. doprint "FAILED!\n";
  104. } else {
  105. doprint "SUCCESS\n";
  106. }
  107. return !$failed;
  108. }
  109. sub get_grub_index {
  110. return if (defined($grub_number));
  111. doprint "Find grub menu ... ";
  112. $grub_number = -1;
  113. open(IN, "ssh $target cat /boot/grub/menu.lst |")
  114. or die "unable to get menu.lst";
  115. while (<IN>) {
  116. if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) {
  117. $grub_number++;
  118. last;
  119. } elsif (/^\s*title\s/) {
  120. $grub_number++;
  121. }
  122. }
  123. close(IN);
  124. die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}"
  125. if ($grub_number < 0);
  126. doprint "$grub_number\n";
  127. }
  128. my $timeout = $opt{"TIMEOUT"};
  129. sub wait_for_input
  130. {
  131. my ($fp, $time) = @_;
  132. my $rin;
  133. my $ready;
  134. my $line;
  135. my $ch;
  136. if (!defined($time)) {
  137. $time = $timeout;
  138. }
  139. $rin = '';
  140. vec($rin, fileno($fp), 1) = 1;
  141. $ready = select($rin, undef, undef, $time);
  142. $line = "";
  143. # try to read one char at a time
  144. while (sysread $fp, $ch, 1) {
  145. $line .= $ch;
  146. last if ($ch eq "\n");
  147. }
  148. if (!length($line)) {
  149. return undef;
  150. }
  151. return $line;
  152. }
  153. sub reboot_to {
  154. run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
  155. }
  156. sub open_console {
  157. my ($fp) = @_;
  158. my $flags;
  159. my $pid = open($fp, "$opt{CONSOLE}|") or
  160. dodie "Can't open console $opt{CONSOLE}";
  161. $flags = fcntl($fp, F_GETFL, 0) or
  162. dodie "Can't get flags for the socket: $!\n";
  163. $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
  164. dodie "Can't set flags for the socket: $!\n";
  165. return $pid;
  166. }
  167. sub close_console {
  168. my ($fp, $pid) = @_;
  169. doprint "kill child process $pid\n";
  170. kill 2, $pid;
  171. print "closing!\n";
  172. close($fp);
  173. }
  174. sub monitor {
  175. my $booted = 0;
  176. my $bug = 0;
  177. my $pid;
  178. my $skip_call_trace = 0;
  179. my $fp = \*IN;
  180. $pid = open_console($fp);
  181. my $line;
  182. my $full_line = "";
  183. doprint "Wait for monitor to settle down.\n";
  184. # read the monitor and wait for the system to calm down
  185. do {
  186. $line = wait_for_input($fp, 5);
  187. } while (defined($line));
  188. reboot_to;
  189. for (;;) {
  190. $line = wait_for_input($fp);
  191. last if (!defined($line));
  192. doprint $line;
  193. # we are not guaranteed to get a full line
  194. $full_line .= $line;
  195. if ($full_line =~ /login:/) {
  196. $booted = 1;
  197. }
  198. if ($full_line =~ /\[ backtrace testing \]/) {
  199. $skip_call_trace = 1;
  200. }
  201. if ($full_line =~ /call trace:/i) {
  202. $bug = 1 if (!$skip_call_trace);
  203. }
  204. if ($full_line =~ /\[ end of backtrace testing \]/) {
  205. $skip_call_trace = 0;
  206. }
  207. if ($full_line =~ /Kernel panic -/) {
  208. $bug = 1;
  209. }
  210. if ($line =~ /\n/) {
  211. $full_line = "";
  212. }
  213. }
  214. close_console($fp, $pid);
  215. if (!$booted) {
  216. return 1 if ($in_bisect);
  217. dodie "failed - never got a boot prompt.\n";
  218. }
  219. if ($bug) {
  220. return 1 if ($in_bisect);
  221. dodie "failed - got a bug report\n";
  222. }
  223. return 0;
  224. }
  225. sub install {
  226. run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}" or
  227. dodie "failed to copy image";
  228. my $install_mods = 0;
  229. # should we process modules?
  230. $install_mods = 0;
  231. open(IN, "$opt{OUTPUT_DIR}/.config") or dodie("Can't read config file");
  232. while (<IN>) {
  233. if (/CONFIG_MODULES(=y)?/) {
  234. $install_mods = 1 if (defined($1));
  235. last;
  236. }
  237. }
  238. close(IN);
  239. if (!$install_mods) {
  240. doprint "No modules needed\n";
  241. return;
  242. }
  243. run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install" or
  244. dodie "Failed to install modules";
  245. my $modlib = "/lib/modules/$version";
  246. my $modtar = "autotest-mods.tar.bz2";
  247. run_command "ssh $target rm -rf $modlib" or
  248. dodie "failed to remove old mods: $modlib";
  249. # would be nice if scp -r did not follow symbolic links
  250. run_command "cd $opt{TMP_DIR} && tar -cjf $modtar lib/modules/$version" or
  251. dodie "making tarball";
  252. run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp" or
  253. dodie "failed to copy modules";
  254. unlink "$opt{TMP_DIR}/$modtar";
  255. run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or
  256. dodie "failed to tar modules";
  257. run_command "ssh $target rm -f /tmp/$modtar";
  258. }
  259. sub check_buildlog {
  260. my ($patch) = @_;
  261. my $buildlog = "$opt{TMP_DIR}/buildlog";
  262. my @files = `git show $patch | diffstat -l`;
  263. open(IN, "git show $patch |") or
  264. dodie "failed to show $patch";
  265. while (<IN>) {
  266. if (m,^--- a/(.*),) {
  267. chomp $1;
  268. $files[$#files] = $1;
  269. }
  270. }
  271. close(IN);
  272. open(IN, $buildlog) or dodie "Can't open $buildlog";
  273. while (<IN>) {
  274. if (/^\s*(.*?):.*(warning|error)/) {
  275. my $err = $1;
  276. foreach my $file (@files) {
  277. my $fullpath = "$opt{BUILD_DIR}/$file";
  278. if ($file eq $err || $fullpath eq $err) {
  279. dodie "$file built with warnings";
  280. }
  281. }
  282. }
  283. }
  284. close(IN);
  285. }
  286. sub build {
  287. my ($type) = @_;
  288. my $defconfig = "";
  289. my $append = "";
  290. if ($type =~ /^useconfig:(.*)/) {
  291. run_command "cp $1 $opt{OUTPUT_DIR}/.config" or
  292. dodie "could not copy $1 to .config";
  293. $type = "oldconfig";
  294. }
  295. # old config can ask questions
  296. if ($type eq "oldconfig") {
  297. $append = "yes ''|";
  298. # allow for empty configs
  299. run_command "touch $opt{OUTPUT_DIR}/.config";
  300. run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp" or
  301. dodie "moving .config";
  302. if (!$noclean && !run_command "$make mrproper") {
  303. dodie "make mrproper";
  304. }
  305. run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config" or
  306. dodie "moving config_temp";
  307. } elsif (!$noclean) {
  308. unlink "$opt{OUTPUT_DIR}/.config";
  309. run_command "$make mrproper" or
  310. dodie "make mrproper";
  311. }
  312. # add something to distinguish this build
  313. open(OUT, "> $opt{OUTPUT_DIR}/localversion") or dodie("Can't make localversion file");
  314. print OUT "$opt{LOCALVERSION}\n";
  315. close(OUT);
  316. if (defined($minconfig)) {
  317. $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
  318. }
  319. run_command "$defconfig $append $make $type" or
  320. dodie "failed make config";
  321. # patch check will examine the log
  322. if ($in_patchcheck) {
  323. $redirect = "$opt{TMP_DIR}/buildlog";
  324. }
  325. if (!run_command "$make $opt{BUILD_OPTIONS}") {
  326. undef $redirect;
  327. # bisect may need this to pass
  328. return 1 if ($in_bisect);
  329. dodie "failed build";
  330. }
  331. undef $redirect;
  332. return 0;
  333. }
  334. sub reboot {
  335. # try to reboot normally
  336. if (!run_command "ssh $target reboot") {
  337. # nope? power cycle it.
  338. run_command "$opt{POWER_CYCLE}";
  339. }
  340. }
  341. sub halt {
  342. if (!run_command "ssh $target halt" or defined($opt{"POWER_OFF"})) {
  343. # nope? the zap it!
  344. run_command "$opt{POWER_OFF}";
  345. }
  346. }
  347. sub success {
  348. my ($i) = @_;
  349. doprint "\n\n*******************************************\n";
  350. doprint "*******************************************\n";
  351. doprint "** SUCCESS!!!! **\n";
  352. doprint "*******************************************\n";
  353. doprint "*******************************************\n";
  354. if ($i != $opt{"NUM_BUILDS"}) {
  355. reboot;
  356. doprint "Sleeping $opt{SLEEP_TIME} seconds\n";
  357. sleep "$opt{SLEEP_TIME}";
  358. }
  359. }
  360. sub get_version {
  361. # get the release name
  362. doprint "$make kernelrelease ... ";
  363. $version = `$make kernelrelease | tail -1`;
  364. chomp($version);
  365. doprint "$version\n";
  366. }
  367. sub child_run_test {
  368. my $failed;
  369. $failed = !run_command $run_test;
  370. exit $failed;
  371. }
  372. my $child_done;
  373. sub child_finished {
  374. $child_done = 1;
  375. }
  376. sub do_run_test {
  377. my $child_pid;
  378. my $child_exit;
  379. my $pid;
  380. my $line;
  381. my $full_line;
  382. my $bug = 0;
  383. my $fp = \*IN;
  384. $pid = open_console($fp);
  385. # read the monitor and wait for the system to calm down
  386. do {
  387. $line = wait_for_input($fp, 1);
  388. } while (defined($line));
  389. $child_done = 0;
  390. $SIG{CHLD} = qw(child_finished);
  391. $child_pid = fork;
  392. child_run_test if (!$child_pid);
  393. $full_line = "";
  394. do {
  395. $line = wait_for_input($fp, 1);
  396. if (defined($line)) {
  397. # we are not guaranteed to get a full line
  398. $full_line .= $line;
  399. if ($full_line =~ /call trace:/i) {
  400. $bug = 1;
  401. }
  402. if ($full_line =~ /Kernel panic -/) {
  403. $bug = 1;
  404. }
  405. if ($line =~ /\n/) {
  406. $full_line = "";
  407. }
  408. }
  409. } while (!$child_done && !$bug);
  410. if ($bug) {
  411. doprint "Detected kernel crash!\n";
  412. # kill the child with extreme prejudice
  413. kill 9, $child_pid;
  414. }
  415. waitpid $child_pid, 0;
  416. $child_exit = $?;
  417. close_console($fp, $pid);
  418. if ($bug || $child_exit) {
  419. return 1 if $in_bisect;
  420. dodie "test failed";
  421. }
  422. return 0;
  423. }
  424. sub run_bisect {
  425. my ($type) = @_;
  426. my $failed;
  427. my $result;
  428. my $output;
  429. my $ret;
  430. if (defined($minconfig)) {
  431. $failed = build "useconfig:$minconfig";
  432. } else {
  433. # ?? no config to use?
  434. $failed = build "oldconfig";
  435. }
  436. if ($type ne "build") {
  437. dodie "Failed on build" if $failed;
  438. # Now boot the box
  439. get_grub_index;
  440. get_version;
  441. install;
  442. $failed = monitor;
  443. if ($type ne "boot") {
  444. dodie "Failed on boot" if $failed;
  445. $failed = do_run_test;
  446. }
  447. }
  448. if ($failed) {
  449. $result = "bad";
  450. # reboot the box to a good kernel
  451. if ($type eq "boot") {
  452. reboot;
  453. doprint "sleep a little for reboot\n";
  454. sleep $opt{"BISECT_SLEEP_TIME"};
  455. }
  456. } else {
  457. $result = "good";
  458. }
  459. # Are we looking for where it worked, not failed?
  460. if ($reverse_bisect) {
  461. if ($failed) {
  462. $result = "good";
  463. } else {
  464. $result = "bad";
  465. }
  466. }
  467. doprint "git bisect $result ... ";
  468. $output = `git bisect $result 2>&1`;
  469. $ret = $?;
  470. logit $output;
  471. if ($ret) {
  472. doprint "FAILED\n";
  473. dodie "Failed to git bisect";
  474. }
  475. doprint "SUCCESS\n";
  476. if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
  477. doprint "$1 [$2]\n";
  478. } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
  479. $bisect_bad = $1;
  480. doprint "Found bad commit... $1\n";
  481. return 0;
  482. } else {
  483. # we already logged it, just print it now.
  484. print $output;
  485. }
  486. return 1;
  487. }
  488. sub bisect {
  489. my ($i) = @_;
  490. my $result;
  491. die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
  492. die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
  493. die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
  494. my $good = $opt{"BISECT_GOOD[$i]"};
  495. my $bad = $opt{"BISECT_BAD[$i]"};
  496. my $type = $opt{"BISECT_TYPE[$i]"};
  497. if (defined($opt{"BISECT_REVERSE[$i]"}) &&
  498. $opt{"BISECT_REVERSE[$i]"} == 1) {
  499. doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
  500. $reverse_bisect = 1;
  501. } else {
  502. $reverse_bisect = 0;
  503. }
  504. $in_bisect = 1;
  505. run_command "git bisect start" or
  506. dodie "could not start bisect";
  507. run_command "git bisect good $good" or
  508. dodie "could not set bisect good to $good";
  509. run_command "git bisect bad $bad" or
  510. dodie "could not set bisect good to $bad";
  511. # Can't have a test without having a test to run
  512. if ($type eq "test" && !defined($run_test)) {
  513. $type = "boot";
  514. }
  515. do {
  516. $result = run_bisect $type;
  517. } while ($result);
  518. run_command "git bisect log" or
  519. dodie "could not capture git bisect log";
  520. run_command "git bisect reset" or
  521. dodie "could not reset git bisect";
  522. doprint "Bad commit was [$bisect_bad]\n";
  523. $in_bisect = 0;
  524. success $i;
  525. }
  526. sub patchcheck {
  527. my ($i) = @_;
  528. die "PATCHCHECK_START[$i] not defined\n"
  529. if (!defined($opt{"PATCHCHECK_START[$i]"}));
  530. die "PATCHCHECK_TYPE[$i] not defined\n"
  531. if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
  532. my $start = $opt{"PATCHCHECK_START[$i]"};
  533. my $end = "HEAD";
  534. if (defined($opt{"PATCHCHECK_END[$i]"})) {
  535. $end = $opt{"PATCHCHECK_END[$i]"};
  536. }
  537. my $type = $opt{"PATCHCHECK_TYPE[$i]"};
  538. # Can't have a test without having a test to run
  539. if ($type eq "test" && !defined($run_test)) {
  540. $type = "boot";
  541. }
  542. open (IN, "git log --pretty=oneline $end|") or
  543. dodie "could not get git list";
  544. my @list;
  545. while (<IN>) {
  546. chomp;
  547. $list[$#list+1] = $_;
  548. last if (/^$start/);
  549. }
  550. close(IN);
  551. if ($list[$#list] !~ /^$start/) {
  552. dodie "SHA1 $start not found";
  553. }
  554. # go backwards in the list
  555. @list = reverse @list;
  556. my $save_clean = $noclean;
  557. $in_patchcheck = 1;
  558. foreach my $item (@list) {
  559. my $sha1 = $item;
  560. $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
  561. doprint "\nProcessing commit $item\n\n";
  562. run_command "git checkout $sha1" or
  563. die "Failed to checkout $sha1";
  564. # only clean on the first and last patch
  565. if ($item eq $list[0] ||
  566. $item eq $list[$#list]) {
  567. $noclean = $save_clean;
  568. } else {
  569. $noclean = 1;
  570. }
  571. if (defined($minconfig)) {
  572. build "useconfig:$minconfig";
  573. } else {
  574. # ?? no config to use?
  575. build "oldconfig";
  576. }
  577. check_buildlog $sha1;
  578. next if ($type eq "build");
  579. get_grub_index;
  580. get_version;
  581. install;
  582. monitor;
  583. next if ($type eq "boot");
  584. do_run_test;
  585. }
  586. $in_patchcheck = 0;
  587. success $i;
  588. }
  589. read_config $ARGV[0];
  590. # mandatory configs
  591. die "MACHINE not defined\n" if (!defined($opt{"MACHINE"}));
  592. die "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"}));
  593. die "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"}));
  594. die "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"}));
  595. die "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"}));
  596. die "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"}));
  597. die "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"}));
  598. die "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"}));
  599. die "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"}));
  600. die "GRUB_MENU not defined\n" if (!defined($opt{"GRUB_MENU"}));
  601. chdir $opt{"BUILD_DIR"} || die "can't change directory to $opt{BUILD_DIR}";
  602. $target = "$opt{SSH_USER}\@$opt{MACHINE}";
  603. doprint "\n\nSTARTING AUTOMATED TESTS\n";
  604. $make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}";
  605. sub set_build_option {
  606. my ($name, $i) = @_;
  607. my $option = "$name\[$i\]";
  608. if (defined($opt{$option})) {
  609. return $opt{$option};
  610. }
  611. if (defined($opt{$name})) {
  612. return $opt{$name};
  613. }
  614. return undef;
  615. }
  616. # First we need to do is the builds
  617. for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
  618. my $type = "BUILD_TYPE[$i]";
  619. if (!defined($opt{$type})) {
  620. $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"};
  621. }
  622. $noclean = set_build_option("BUILD_NOCLEAN", $i);
  623. $minconfig = set_build_option("MIN_CONFIG", $i);
  624. $run_test = set_build_option("TEST", $i);
  625. doprint "\n\n";
  626. doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n";
  627. my $checkout = $opt{"CHECKOUT[$i]"};
  628. if (defined($checkout)) {
  629. run_command "git checkout $checkout" or
  630. die "failed to checkout $checkout";
  631. }
  632. if ($opt{$type} eq "bisect") {
  633. bisect $i;
  634. next;
  635. } elsif ($opt{$type} eq "patchcheck") {
  636. patchcheck $i;
  637. next;
  638. }
  639. if ($opt{$type} ne "nobuild") {
  640. build $opt{$type};
  641. }
  642. get_grub_index;
  643. get_version;
  644. install;
  645. monitor;
  646. if (defined($run_test)) {
  647. do_run_test;
  648. }
  649. success $i;
  650. }
  651. if ($opt{"POWEROFF_ON_SUCCESS"}) {
  652. halt;
  653. } elsif ($opt{"REBOOT_ON_SUCCESS"}) {
  654. reboot;
  655. }
  656. exit 0;