ktest.pl 24 KB

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