ktest.pl 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174
  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 File::Path qw(mkpath);
  10. use File::Copy qw(cp);
  11. use FileHandle;
  12. $#ARGV >= 0 || die "usage: autotest.pl config-file\n";
  13. $| = 1;
  14. my %opt;
  15. my %default;
  16. #default opts
  17. $default{"NUM_TESTS"} = 5;
  18. $default{"REBOOT_TYPE"} = "grub";
  19. $default{"TEST_TYPE"} = "test";
  20. $default{"BUILD_TYPE"} = "randconfig";
  21. $default{"MAKE_CMD"} = "make";
  22. $default{"TIMEOUT"} = 120;
  23. $default{"TMP_DIR"} = "/tmp/autotest";
  24. $default{"SLEEP_TIME"} = 60; # sleep time between tests
  25. $default{"BUILD_NOCLEAN"} = 0;
  26. $default{"REBOOT_ON_ERROR"} = 0;
  27. $default{"POWEROFF_ON_ERROR"} = 0;
  28. $default{"REBOOT_ON_SUCCESS"} = 1;
  29. $default{"POWEROFF_ON_SUCCESS"} = 0;
  30. $default{"BUILD_OPTIONS"} = "";
  31. $default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects
  32. $default{"CLEAR_LOG"} = 0;
  33. $default{"SUCCESS_LINE"} = "login:";
  34. $default{"BOOTED_TIMEOUT"} = 1;
  35. $default{"DIE_ON_FAILURE"} = 1;
  36. my $version;
  37. my $machine;
  38. my $tmpdir;
  39. my $builddir;
  40. my $outputdir;
  41. my $test_type;
  42. my $build_type;
  43. my $build_options;
  44. my $reboot_type;
  45. my $reboot_script;
  46. my $power_cycle;
  47. my $reboot_on_error;
  48. my $poweroff_on_error;
  49. my $die_on_failure;
  50. my $power_off;
  51. my $grub_menu;
  52. my $grub_number;
  53. my $target;
  54. my $make;
  55. my $post_install;
  56. my $noclean;
  57. my $minconfig;
  58. my $addconfig;
  59. my $in_bisect = 0;
  60. my $bisect_bad = "";
  61. my $reverse_bisect;
  62. my $in_patchcheck = 0;
  63. my $run_test;
  64. my $redirect;
  65. my $buildlog;
  66. my $dmesg;
  67. my $monitor_fp;
  68. my $monitor_pid;
  69. my $monitor_cnt = 0;
  70. my $sleep_time;
  71. my $bisect_sleep_time;
  72. my $store_failures;
  73. my $timeout;
  74. my $booted_timeout;
  75. my $console;
  76. my $success_line;
  77. my $build_target;
  78. my $target_image;
  79. my $localversion;
  80. sub read_config {
  81. my ($config) = @_;
  82. open(IN, $config) || die "can't read file $config";
  83. while (<IN>) {
  84. # ignore blank lines and comments
  85. next if (/^\s*$/ || /\s*\#/);
  86. if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) {
  87. my $lvalue = $1;
  88. my $rvalue = $2;
  89. if (defined($opt{$lvalue})) {
  90. die "Error: Option $lvalue defined more than once!\n";
  91. }
  92. $opt{$lvalue} = $rvalue;
  93. }
  94. }
  95. close(IN);
  96. # set any defaults
  97. foreach my $default (keys %default) {
  98. if (!defined($opt{$default})) {
  99. $opt{$default} = $default{$default};
  100. }
  101. }
  102. }
  103. sub logit {
  104. if (defined($opt{"LOG_FILE"})) {
  105. open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
  106. print OUT @_;
  107. close(OUT);
  108. }
  109. }
  110. sub doprint {
  111. print @_;
  112. logit @_;
  113. }
  114. sub run_command;
  115. sub reboot {
  116. # try to reboot normally
  117. if (!run_command "ssh $target reboot") {
  118. # nope? power cycle it.
  119. run_command "$power_cycle";
  120. }
  121. }
  122. sub dodie {
  123. doprint "CRITICAL FAILURE... ", @_, "\n";
  124. if ($reboot_on_error && $test_type ne "build") {
  125. doprint "REBOOTING\n";
  126. reboot;
  127. } elsif ($poweroff_on_error && defined($power_off)) {
  128. doprint "POWERING OFF\n";
  129. `$power_off`;
  130. }
  131. die @_;
  132. }
  133. sub open_console {
  134. my ($fp) = @_;
  135. my $flags;
  136. my $pid = open($fp, "$console|") or
  137. dodie "Can't open console $console";
  138. $flags = fcntl($fp, F_GETFL, 0) or
  139. dodie "Can't get flags for the socket: $!\n";
  140. $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
  141. dodie "Can't set flags for the socket: $!\n";
  142. return $pid;
  143. }
  144. sub close_console {
  145. my ($fp, $pid) = @_;
  146. doprint "kill child process $pid\n";
  147. kill 2, $pid;
  148. print "closing!\n";
  149. close($fp);
  150. }
  151. sub start_monitor {
  152. if ($monitor_cnt++) {
  153. return;
  154. }
  155. $monitor_fp = \*MONFD;
  156. $monitor_pid = open_console $monitor_fp;
  157. return;
  158. open(MONFD, "Stop perl from warning about single use of MONFD");
  159. }
  160. sub end_monitor {
  161. if (--$monitor_cnt) {
  162. return;
  163. }
  164. close_console($monitor_fp, $monitor_pid);
  165. }
  166. sub wait_for_monitor {
  167. my ($time) = @_;
  168. my $line;
  169. doprint "** Wait for monitor to settle down **\n";
  170. # read the monitor and wait for the system to calm down
  171. do {
  172. $line = wait_for_input($monitor_fp, $time);
  173. print "$line" if (defined($line));
  174. } while (defined($line));
  175. print "** Monitor flushed **\n";
  176. }
  177. sub fail {
  178. if ($die_on_failure) {
  179. dodie @_;
  180. }
  181. doprint "FAILED\n";
  182. # no need to reboot for just building.
  183. if ($test_type ne "build") {
  184. doprint "REBOOTING\n";
  185. reboot;
  186. start_monitor;
  187. wait_for_monitor $sleep_time;
  188. end_monitor;
  189. }
  190. doprint "**** Failed: ", @_, " ****\n";
  191. return 1 if (!defined($store_failures));
  192. my @t = localtime;
  193. my $date = sprintf "%04d%02d%02d%02d%02d%02d",
  194. 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
  195. my $dir = "$machine-$test_type-$build_type-fail-$date";
  196. my $faildir = "$store_failures/$dir";
  197. if (!-d $faildir) {
  198. mkpath($faildir) or
  199. die "can't create $faildir";
  200. }
  201. if (-f "$outputdir/.config") {
  202. cp "$outputdir/.config", "$faildir/config" or
  203. die "failed to copy .config";
  204. }
  205. if (-f $buildlog) {
  206. cp $buildlog, "$faildir/buildlog" or
  207. die "failed to move $buildlog";
  208. }
  209. if (-f $dmesg) {
  210. cp $dmesg, "$faildir/dmesg" or
  211. die "failed to move $dmesg";
  212. }
  213. doprint "*** Saved info to $faildir ***\n";
  214. return 1;
  215. }
  216. sub run_command {
  217. my ($command) = @_;
  218. my $dolog = 0;
  219. my $dord = 0;
  220. my $pid;
  221. doprint("$command ... ");
  222. $pid = open(CMD, "$command 2>&1 |") or
  223. (fail "unable to exec $command" and return 0);
  224. if (defined($opt{"LOG_FILE"})) {
  225. open(LOG, ">>$opt{LOG_FILE}") or
  226. dodie "failed to write to log";
  227. $dolog = 1;
  228. }
  229. if (defined($redirect)) {
  230. open (RD, ">$redirect") or
  231. dodie "failed to write to redirect $redirect";
  232. $dord = 1;
  233. }
  234. while (<CMD>) {
  235. print LOG if ($dolog);
  236. print RD if ($dord);
  237. }
  238. waitpid($pid, 0);
  239. my $failed = $?;
  240. close(CMD);
  241. close(LOG) if ($dolog);
  242. close(RD) if ($dord);
  243. if ($failed) {
  244. doprint "FAILED!\n";
  245. } else {
  246. doprint "SUCCESS\n";
  247. }
  248. return !$failed;
  249. }
  250. sub get_grub_index {
  251. if ($reboot_type ne "grub") {
  252. return;
  253. }
  254. return if (defined($grub_number));
  255. doprint "Find grub menu ... ";
  256. $grub_number = -1;
  257. open(IN, "ssh $target cat /boot/grub/menu.lst |")
  258. or die "unable to get menu.lst";
  259. while (<IN>) {
  260. if (/^\s*title\s+$grub_menu\s*$/) {
  261. $grub_number++;
  262. last;
  263. } elsif (/^\s*title\s/) {
  264. $grub_number++;
  265. }
  266. }
  267. close(IN);
  268. die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
  269. if ($grub_number < 0);
  270. doprint "$grub_number\n";
  271. }
  272. sub wait_for_input
  273. {
  274. my ($fp, $time) = @_;
  275. my $rin;
  276. my $ready;
  277. my $line;
  278. my $ch;
  279. if (!defined($time)) {
  280. $time = $timeout;
  281. }
  282. $rin = '';
  283. vec($rin, fileno($fp), 1) = 1;
  284. $ready = select($rin, undef, undef, $time);
  285. $line = "";
  286. # try to read one char at a time
  287. while (sysread $fp, $ch, 1) {
  288. $line .= $ch;
  289. last if ($ch eq "\n");
  290. }
  291. if (!length($line)) {
  292. return undef;
  293. }
  294. return $line;
  295. }
  296. sub reboot_to {
  297. if ($reboot_type eq "grub") {
  298. run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
  299. return;
  300. }
  301. run_command "$reboot_script";
  302. }
  303. sub monitor {
  304. my $booted = 0;
  305. my $bug = 0;
  306. my $skip_call_trace = 0;
  307. my $loops;
  308. wait_for_monitor 5;
  309. my $line;
  310. my $full_line = "";
  311. open(DMESG, "> $dmesg") or
  312. die "unable to write to $dmesg";
  313. reboot_to;
  314. for (;;) {
  315. if ($booted) {
  316. $line = wait_for_input($monitor_fp, $booted_timeout);
  317. } else {
  318. $line = wait_for_input($monitor_fp);
  319. }
  320. last if (!defined($line));
  321. doprint $line;
  322. print DMESG $line;
  323. # we are not guaranteed to get a full line
  324. $full_line .= $line;
  325. if ($full_line =~ /$success_line/) {
  326. $booted = 1;
  327. }
  328. if ($full_line =~ /\[ backtrace testing \]/) {
  329. $skip_call_trace = 1;
  330. }
  331. if ($full_line =~ /call trace:/i) {
  332. $bug = 1 if (!$skip_call_trace);
  333. }
  334. if ($full_line =~ /\[ end of backtrace testing \]/) {
  335. $skip_call_trace = 0;
  336. }
  337. if ($full_line =~ /Kernel panic -/) {
  338. $bug = 1;
  339. }
  340. if ($line =~ /\n/) {
  341. $full_line = "";
  342. }
  343. }
  344. close(DMESG);
  345. if ($bug) {
  346. return 0 if ($in_bisect);
  347. fail "failed - got a bug report\n" and return 0;
  348. }
  349. if (!$booted) {
  350. return 0 if ($in_bisect);
  351. fail "failed - never got a boot prompt.\n" and return 0;
  352. }
  353. return 1;
  354. }
  355. sub install {
  356. run_command "scp $outputdir/$build_target $target:$target_image" or
  357. dodie "failed to copy image";
  358. my $install_mods = 0;
  359. # should we process modules?
  360. $install_mods = 0;
  361. open(IN, "$outputdir/.config") or dodie("Can't read config file");
  362. while (<IN>) {
  363. if (/CONFIG_MODULES(=y)?/) {
  364. $install_mods = 1 if (defined($1));
  365. last;
  366. }
  367. }
  368. close(IN);
  369. if (!$install_mods) {
  370. doprint "No modules needed\n";
  371. return;
  372. }
  373. run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
  374. dodie "Failed to install modules";
  375. my $modlib = "/lib/modules/$version";
  376. my $modtar = "autotest-mods.tar.bz2";
  377. run_command "ssh $target rm -rf $modlib" or
  378. dodie "failed to remove old mods: $modlib";
  379. # would be nice if scp -r did not follow symbolic links
  380. run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
  381. dodie "making tarball";
  382. run_command "scp $tmpdir/$modtar $target:/tmp" or
  383. dodie "failed to copy modules";
  384. unlink "$tmpdir/$modtar";
  385. run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or
  386. dodie "failed to tar modules";
  387. run_command "ssh $target rm -f /tmp/$modtar";
  388. return if (!defined($post_install));
  389. my $save_env = $ENV{KERNEL_VERSION};
  390. $ENV{KERNEL_VERSION} = $version;
  391. run_command "$post_install";
  392. $ENV{KERNEL_VERSION} = $save_env;
  393. }
  394. sub check_buildlog {
  395. my ($patch) = @_;
  396. my @files = `git show $patch | diffstat -l`;
  397. open(IN, "git show $patch |") or
  398. dodie "failed to show $patch";
  399. while (<IN>) {
  400. if (m,^--- a/(.*),) {
  401. chomp $1;
  402. $files[$#files] = $1;
  403. }
  404. }
  405. close(IN);
  406. open(IN, $buildlog) or dodie "Can't open $buildlog";
  407. while (<IN>) {
  408. if (/^\s*(.*?):.*(warning|error)/) {
  409. my $err = $1;
  410. foreach my $file (@files) {
  411. my $fullpath = "$builddir/$file";
  412. if ($file eq $err || $fullpath eq $err) {
  413. fail "$file built with warnings" and return 0;
  414. }
  415. }
  416. }
  417. }
  418. close(IN);
  419. return 1;
  420. }
  421. sub build {
  422. my ($type) = @_;
  423. my $defconfig = "";
  424. my $append = "";
  425. unlink $buildlog;
  426. if ($type =~ /^useconfig:(.*)/) {
  427. run_command "cp $1 $outputdir/.config" or
  428. dodie "could not copy $1 to .config";
  429. $type = "oldconfig";
  430. }
  431. # old config can ask questions
  432. if ($type eq "oldconfig") {
  433. $append = "yes ''|";
  434. # allow for empty configs
  435. run_command "touch $outputdir/.config";
  436. run_command "mv $outputdir/.config $outputdir/config_temp" or
  437. dodie "moving .config";
  438. if (!$noclean && !run_command "$make mrproper") {
  439. dodie "make mrproper";
  440. }
  441. run_command "mv $outputdir/config_temp $outputdir/.config" or
  442. dodie "moving config_temp";
  443. } elsif (!$noclean) {
  444. unlink "$outputdir/.config";
  445. run_command "$make mrproper" or
  446. dodie "make mrproper";
  447. }
  448. # add something to distinguish this build
  449. open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
  450. print OUT "$localversion\n";
  451. close(OUT);
  452. if (defined($minconfig)) {
  453. $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
  454. }
  455. run_command "$append $defconfig $make $type" or
  456. dodie "failed make config";
  457. $redirect = "$buildlog";
  458. if (!run_command "$make $build_options") {
  459. undef $redirect;
  460. # bisect may need this to pass
  461. return 0 if ($in_bisect);
  462. fail "failed build" and return 0;
  463. }
  464. undef $redirect;
  465. return 1;
  466. }
  467. sub halt {
  468. if (!run_command "ssh $target halt" or defined($power_off)) {
  469. # nope? the zap it!
  470. run_command "$power_off";
  471. }
  472. }
  473. sub success {
  474. my ($i) = @_;
  475. doprint "\n\n*******************************************\n";
  476. doprint "*******************************************\n";
  477. doprint "** TEST $i SUCCESS!!!! **\n";
  478. doprint "*******************************************\n";
  479. doprint "*******************************************\n";
  480. if ($i != $opt{"NUM_TESTS"} && $test_type ne "build" &&
  481. !($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") &&
  482. !($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build")) {
  483. doprint "Reboot and wait $sleep_time seconds\n";
  484. reboot;
  485. start_monitor;
  486. wait_for_monitor $sleep_time;
  487. end_monitor;
  488. }
  489. }
  490. sub get_version {
  491. # get the release name
  492. doprint "$make kernelrelease ... ";
  493. $version = `$make kernelrelease | tail -1`;
  494. chomp($version);
  495. doprint "$version\n";
  496. }
  497. sub child_run_test {
  498. my $failed = 0;
  499. # child should have no power
  500. $reboot_on_error = 0;
  501. $poweroff_on_error = 0;
  502. $die_on_failure = 1;
  503. run_command $run_test or $failed = 1;
  504. exit $failed;
  505. }
  506. my $child_done;
  507. sub child_finished {
  508. $child_done = 1;
  509. }
  510. sub do_run_test {
  511. my $child_pid;
  512. my $child_exit;
  513. my $line;
  514. my $full_line;
  515. my $bug = 0;
  516. wait_for_monitor 1;
  517. doprint "run test $run_test\n";
  518. $child_done = 0;
  519. $SIG{CHLD} = qw(child_finished);
  520. $child_pid = fork;
  521. child_run_test if (!$child_pid);
  522. $full_line = "";
  523. do {
  524. $line = wait_for_input($monitor_fp, 1);
  525. if (defined($line)) {
  526. # we are not guaranteed to get a full line
  527. $full_line .= $line;
  528. if ($full_line =~ /call trace:/i) {
  529. $bug = 1;
  530. }
  531. if ($full_line =~ /Kernel panic -/) {
  532. $bug = 1;
  533. }
  534. if ($line =~ /\n/) {
  535. $full_line = "";
  536. }
  537. }
  538. } while (!$child_done && !$bug);
  539. if ($bug) {
  540. doprint "Detected kernel crash!\n";
  541. # kill the child with extreme prejudice
  542. kill 9, $child_pid;
  543. }
  544. waitpid $child_pid, 0;
  545. $child_exit = $?;
  546. if ($bug || $child_exit) {
  547. return 0 if $in_bisect;
  548. fail "test failed" and return 0;
  549. }
  550. return 1;
  551. }
  552. sub run_git_bisect {
  553. my ($command) = @_;
  554. doprint "$command ... ";
  555. my $output = `$command 2>&1`;
  556. my $ret = $?;
  557. logit $output;
  558. if ($ret) {
  559. doprint "FAILED\n";
  560. dodie "Failed to git bisect";
  561. }
  562. doprint "SUCCESS\n";
  563. if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
  564. doprint "$1 [$2]\n";
  565. } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
  566. $bisect_bad = $1;
  567. doprint "Found bad commit... $1\n";
  568. return 0;
  569. } else {
  570. # we already logged it, just print it now.
  571. print $output;
  572. }
  573. return 1;
  574. }
  575. sub run_bisect {
  576. my ($type) = @_;
  577. my $failed = 0;
  578. my $result;
  579. my $output;
  580. my $ret;
  581. if (defined($minconfig)) {
  582. build "useconfig:$minconfig" or $failed = 1;
  583. } else {
  584. # ?? no config to use?
  585. build "oldconfig" or $failed = 1;
  586. }
  587. if ($type ne "build") {
  588. dodie "Failed on build" if $failed;
  589. # Now boot the box
  590. get_grub_index;
  591. get_version;
  592. install;
  593. start_monitor;
  594. monitor or $failed = 1;
  595. if ($type ne "boot") {
  596. dodie "Failed on boot" if $failed;
  597. do_run_test or $failed = 1;
  598. }
  599. end_monitor;
  600. }
  601. if ($failed) {
  602. $result = "bad";
  603. # reboot the box to a good kernel
  604. if ($type ne "build") {
  605. doprint "Reboot and sleep $bisect_sleep_time seconds\n";
  606. reboot;
  607. start_monitor;
  608. wait_for_monitor $bisect_sleep_time;
  609. end_monitor;
  610. }
  611. } else {
  612. $result = "good";
  613. }
  614. # Are we looking for where it worked, not failed?
  615. if ($reverse_bisect) {
  616. if ($failed) {
  617. $result = "good";
  618. } else {
  619. $result = "bad";
  620. }
  621. }
  622. return $result;
  623. }
  624. sub bisect {
  625. my ($i) = @_;
  626. my $result;
  627. die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
  628. die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
  629. die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
  630. my $good = $opt{"BISECT_GOOD[$i]"};
  631. my $bad = $opt{"BISECT_BAD[$i]"};
  632. my $type = $opt{"BISECT_TYPE[$i]"};
  633. my $start = $opt{"BISECT_START[$i]"};
  634. my $replay = $opt{"BISECT_REPLAY[$i]"};
  635. if (defined($opt{"BISECT_REVERSE[$i]"}) &&
  636. $opt{"BISECT_REVERSE[$i]"} == 1) {
  637. doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
  638. $reverse_bisect = 1;
  639. } else {
  640. $reverse_bisect = 0;
  641. }
  642. $in_bisect = 1;
  643. # Can't have a test without having a test to run
  644. if ($type eq "test" && !defined($run_test)) {
  645. $type = "boot";
  646. }
  647. my $check = $opt{"BISECT_CHECK[$i]"};
  648. if (defined($check) && $check ne "0") {
  649. # get current HEAD
  650. doprint "git rev-list HEAD --max-count=1 ... ";
  651. my $head = `git rev-list HEAD --max-count=1`;
  652. my $ret = $?;
  653. logit $head;
  654. if ($ret) {
  655. doprint "FAILED\n";
  656. dodie "Failed to get git HEAD";
  657. }
  658. print "SUCCESS\n";
  659. chomp $head;
  660. if ($check ne "good") {
  661. doprint "TESTING BISECT BAD [$bad]\n";
  662. run_command "git checkout $bad" or
  663. die "Failed to checkout $bad";
  664. $result = run_bisect $type;
  665. if ($result ne "bad") {
  666. fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
  667. }
  668. }
  669. if ($check ne "bad") {
  670. doprint "TESTING BISECT GOOD [$good]\n";
  671. run_command "git checkout $good" or
  672. die "Failed to checkout $good";
  673. $result = run_bisect $type;
  674. if ($result ne "good") {
  675. fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
  676. }
  677. }
  678. # checkout where we started
  679. run_command "git checkout $head" or
  680. die "Failed to checkout $head";
  681. }
  682. run_command "git bisect start" or
  683. dodie "could not start bisect";
  684. run_command "git bisect good $good" or
  685. dodie "could not set bisect good to $good";
  686. run_git_bisect "git bisect bad $bad" or
  687. dodie "could not set bisect bad to $bad";
  688. if (defined($replay)) {
  689. run_command "git bisect replay $replay" or
  690. dodie "failed to run replay";
  691. }
  692. if (defined($start)) {
  693. run_command "git checkout $start" or
  694. dodie "failed to checkout $start";
  695. }
  696. my $test;
  697. do {
  698. $result = run_bisect $type;
  699. $test = run_git_bisect "git bisect $result";
  700. } while ($test);
  701. run_command "git bisect log" or
  702. dodie "could not capture git bisect log";
  703. run_command "git bisect reset" or
  704. dodie "could not reset git bisect";
  705. doprint "Bad commit was [$bisect_bad]\n";
  706. $in_bisect = 0;
  707. success $i;
  708. }
  709. sub patchcheck {
  710. my ($i) = @_;
  711. die "PATCHCHECK_START[$i] not defined\n"
  712. if (!defined($opt{"PATCHCHECK_START[$i]"}));
  713. die "PATCHCHECK_TYPE[$i] not defined\n"
  714. if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
  715. my $start = $opt{"PATCHCHECK_START[$i]"};
  716. my $end = "HEAD";
  717. if (defined($opt{"PATCHCHECK_END[$i]"})) {
  718. $end = $opt{"PATCHCHECK_END[$i]"};
  719. }
  720. my $type = $opt{"PATCHCHECK_TYPE[$i]"};
  721. # Can't have a test without having a test to run
  722. if ($type eq "test" && !defined($run_test)) {
  723. $type = "boot";
  724. }
  725. open (IN, "git log --pretty=oneline $end|") or
  726. dodie "could not get git list";
  727. my @list;
  728. while (<IN>) {
  729. chomp;
  730. $list[$#list+1] = $_;
  731. last if (/^$start/);
  732. }
  733. close(IN);
  734. if ($list[$#list] !~ /^$start/) {
  735. fail "SHA1 $start not found";
  736. }
  737. # go backwards in the list
  738. @list = reverse @list;
  739. my $save_clean = $noclean;
  740. $in_patchcheck = 1;
  741. foreach my $item (@list) {
  742. my $sha1 = $item;
  743. $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
  744. doprint "\nProcessing commit $item\n\n";
  745. run_command "git checkout $sha1" or
  746. die "Failed to checkout $sha1";
  747. # only clean on the first and last patch
  748. if ($item eq $list[0] ||
  749. $item eq $list[$#list]) {
  750. $noclean = $save_clean;
  751. } else {
  752. $noclean = 1;
  753. }
  754. if (defined($minconfig)) {
  755. build "useconfig:$minconfig" or return 0;
  756. } else {
  757. # ?? no config to use?
  758. build "oldconfig" or return 0;
  759. }
  760. check_buildlog $sha1 or return 0;
  761. next if ($type eq "build");
  762. get_grub_index;
  763. get_version;
  764. install;
  765. my $failed = 0;
  766. start_monitor;
  767. monitor or $failed = 1;
  768. if (!$failed && $type ne "boot"){
  769. do_run_test or $failed = 1;
  770. }
  771. end_monitor;
  772. return 0 if ($failed);
  773. }
  774. $in_patchcheck = 0;
  775. success $i;
  776. return 1;
  777. }
  778. read_config $ARGV[0];
  779. # mandatory configs
  780. die "MACHINE not defined\n" if (!defined($opt{"MACHINE"}));
  781. die "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"}));
  782. die "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"}));
  783. die "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"}));
  784. die "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"}));
  785. die "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"}));
  786. die "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"}));
  787. die "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"}));
  788. die "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"}));
  789. if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
  790. unlink $opt{"LOG_FILE"};
  791. }
  792. doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
  793. foreach my $option (sort keys %opt) {
  794. doprint "$option = $opt{$option}\n";
  795. }
  796. sub set_test_option {
  797. my ($name, $i) = @_;
  798. my $option = "$name\[$i\]";
  799. if (defined($opt{$option})) {
  800. return $opt{$option};
  801. }
  802. if (defined($opt{$name})) {
  803. return $opt{$name};
  804. }
  805. return undef;
  806. }
  807. # First we need to do is the builds
  808. for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
  809. my $ssh_user = set_test_option("SSH_USER", $i);
  810. my $makecmd = set_test_option("MAKE_CMD", $i);
  811. $machine = set_test_option("MACHINE", $i);
  812. $tmpdir = set_test_option("TMP_DIR", $i);
  813. $outputdir = set_test_option("OUTPUT_DIR", $i);
  814. $builddir = set_test_option("BUILD_DIR", $i);
  815. $test_type = set_test_option("TEST_TYPE", $i);
  816. $build_type = set_test_option("BUILD_TYPE", $i);
  817. $build_options = set_test_option("BUILD_OPTIONS", $i);
  818. $power_cycle = set_test_option("POWER_CYCLE", $i);
  819. $noclean = set_test_option("BUILD_NOCLEAN", $i);
  820. $minconfig = set_test_option("MIN_CONFIG", $i);
  821. $run_test = set_test_option("TEST", $i);
  822. $addconfig = set_test_option("ADD_CONFIG", $i);
  823. $reboot_type = set_test_option("REBOOT_TYPE", $i);
  824. $grub_menu = set_test_option("GRUB_MENU", $i);
  825. $post_install = set_test_option("POST_INSTALL", $i);
  826. $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
  827. $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
  828. $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
  829. $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
  830. $power_off = set_test_option("POWER_OFF", $i);
  831. $sleep_time = set_test_option("SLEEP_TIME", $i);
  832. $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
  833. $store_failures = set_test_option("STORE_FAILURES", $i);
  834. $timeout = set_test_option("TIMEOUT", $i);
  835. $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
  836. $console = set_test_option("CONSOLE", $i);
  837. $success_line = set_test_option("SUCCESS_LINE", $i);
  838. $build_target = set_test_option("BUILD_TARGET", $i);
  839. $target_image = set_test_option("TARGET_IMAGE", $i);
  840. $localversion = set_test_option("LOCALVERSION", $i);
  841. chdir $builddir || die "can't change directory to $builddir";
  842. if (!-d $tmpdir) {
  843. mkpath($tmpdir) or
  844. die "can't create $tmpdir";
  845. }
  846. $target = "$ssh_user\@$machine";
  847. $buildlog = "$tmpdir/buildlog-$machine";
  848. $dmesg = "$tmpdir/dmesg-$machine";
  849. $make = "$makecmd O=$outputdir";
  850. if ($reboot_type eq "grub") {
  851. dodie "GRUB_MENU not defined\n" if (!defined($grub_menu));
  852. } elsif (!defined($reboot_script)) {
  853. dodie "REBOOT_SCRIPT not defined\n"
  854. }
  855. my $run_type = $build_type;
  856. if ($test_type eq "patchcheck") {
  857. $run_type = $opt{"PATCHCHECK_TYPE[$i]"};
  858. } elsif ($test_type eq "bisect") {
  859. $run_type = $opt{"BISECT_TYPE[$i]"};
  860. }
  861. # mistake in config file?
  862. if (!defined($run_type)) {
  863. $run_type = "ERROR";
  864. }
  865. doprint "\n\n";
  866. doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
  867. unlink $dmesg;
  868. unlink $buildlog;
  869. if (!defined($minconfig)) {
  870. $minconfig = $addconfig;
  871. } elsif (defined($addconfig)) {
  872. run_command "cat $addconfig $minconfig > $tmpdir/use_config" or
  873. dodie "Failed to create temp config";
  874. $minconfig = "$tmpdir/use_config";
  875. }
  876. my $checkout = $opt{"CHECKOUT[$i]"};
  877. if (defined($checkout)) {
  878. run_command "git checkout $checkout" or
  879. die "failed to checkout $checkout";
  880. }
  881. if ($test_type eq "bisect") {
  882. bisect $i;
  883. next;
  884. } elsif ($test_type eq "patchcheck") {
  885. patchcheck $i;
  886. next;
  887. }
  888. if ($build_type ne "nobuild") {
  889. build $build_type or next;
  890. }
  891. if ($test_type ne "build") {
  892. get_grub_index;
  893. get_version;
  894. install;
  895. my $failed = 0;
  896. start_monitor;
  897. monitor or $failed = 1;;
  898. if (!$failed && $test_type ne "boot" && defined($run_test)) {
  899. do_run_test or $failed = 1;
  900. }
  901. end_monitor;
  902. next if ($failed);
  903. }
  904. success $i;
  905. }
  906. if ($opt{"POWEROFF_ON_SUCCESS"}) {
  907. halt;
  908. } elsif ($opt{"REBOOT_ON_SUCCESS"} && $test_type ne "build") {
  909. reboot;
  910. }
  911. exit 0;