ktest.pl 18 KB

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