ktest.pl 29 KB

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