12545eb61SSteven Rostedt#!/usr/bin/perl -w 22545eb61SSteven Rostedt 32545eb61SSteven Rostedtuse strict; 42545eb61SSteven Rostedtuse IPC::Open2; 52545eb61SSteven Rostedtuse Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); 62545eb61SSteven Rostedtuse FileHandle; 72545eb61SSteven Rostedt 82545eb61SSteven Rostedt$#ARGV >= 0 || die "usage: autotest.pl config-file\n"; 92545eb61SSteven Rostedt 102545eb61SSteven Rostedt$| = 1; 112545eb61SSteven Rostedt 122545eb61SSteven Rostedtmy %opt; 132545eb61SSteven Rostedt 142545eb61SSteven Rostedt#default opts 152545eb61SSteven Rostedt$opt{"NUM_BUILDS"} = 5; 162545eb61SSteven Rostedt$opt{"DEFAULT_BUILD_TYPE"} = "randconfig"; 172545eb61SSteven Rostedt$opt{"MAKE_CMD"} = "make"; 182545eb61SSteven Rostedt$opt{"TIMEOUT"} = 50; 192545eb61SSteven Rostedt$opt{"TMP_DIR"} = "/tmp/autotest"; 202545eb61SSteven Rostedt$opt{"SLEEP_TIME"} = 60; # sleep time between tests 215c42fc5bSSteven Rostedt$opt{"BUILD_NOCLEAN"} = 0; 2275c3fda7SSteven Rostedt$opt{"REBOOT_ON_ERROR"} = 0; 235c42fc5bSSteven Rostedt$opt{"POWEROFF_ON_ERROR"} = 0; 245c42fc5bSSteven Rostedt$opt{"POWEROFF_ON_SUCCESS"} = 0; 2575c3fda7SSteven Rostedt$opt{"BUILD_OPTIONS"} = ""; 26*5a391fbfSSteven Rostedt$opt{"BISECT_SLEEP_TIME"} = 10; # sleep time between bisects 272545eb61SSteven Rostedt 282545eb61SSteven Rostedtmy $version; 292545eb61SSteven Rostedtmy $grub_number; 302545eb61SSteven Rostedtmy $target; 312545eb61SSteven Rostedtmy $make; 325c42fc5bSSteven Rostedtmy $noclean; 335f9b6cedSSteven Rostedtmy $minconfig; 345f9b6cedSSteven Rostedtmy $in_bisect = 0; 355f9b6cedSSteven Rostedtmy $bisect_bad = ""; 36*5a391fbfSSteven Rostedtmy $run_test; 372545eb61SSteven Rostedt 382545eb61SSteven Rostedtsub read_config { 392545eb61SSteven Rostedt my ($config) = @_; 402545eb61SSteven Rostedt 412545eb61SSteven Rostedt open(IN, $config) || die "can't read file $config"; 422545eb61SSteven Rostedt 432545eb61SSteven Rostedt while (<IN>) { 442545eb61SSteven Rostedt 452545eb61SSteven Rostedt # ignore blank lines and comments 462545eb61SSteven Rostedt next if (/^\s*$/ || /\s*\#/); 472545eb61SSteven Rostedt 482545eb61SSteven Rostedt if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) { 492545eb61SSteven Rostedt my $lvalue = $1; 502545eb61SSteven Rostedt my $rvalue = $2; 512545eb61SSteven Rostedt 522545eb61SSteven Rostedt $opt{$lvalue} = $rvalue; 532545eb61SSteven Rostedt } 542545eb61SSteven Rostedt } 552545eb61SSteven Rostedt 562545eb61SSteven Rostedt close(IN); 572545eb61SSteven Rostedt} 582545eb61SSteven Rostedt 595f9b6cedSSteven Rostedtsub logit { 602545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 612545eb61SSteven Rostedt open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 622545eb61SSteven Rostedt print OUT @_; 632545eb61SSteven Rostedt close(OUT); 642545eb61SSteven Rostedt } 652545eb61SSteven Rostedt} 662545eb61SSteven Rostedt 675f9b6cedSSteven Rostedtsub doprint { 685f9b6cedSSteven Rostedt print @_; 695f9b6cedSSteven Rostedt logit @_; 705f9b6cedSSteven Rostedt} 715f9b6cedSSteven Rostedt 725c42fc5bSSteven Rostedtsub dodie { 73*5a391fbfSSteven Rostedt doprint "CRITICAL FAILURE... ", @_, "\n"; 745c42fc5bSSteven Rostedt 7575c3fda7SSteven Rostedt if ($opt{"REBOOT_ON_ERROR"}) { 7675c3fda7SSteven Rostedt doprint "REBOOTING\n"; 7775c3fda7SSteven Rostedt `$opt{"POWER_CYCLE"}`; 7875c3fda7SSteven Rostedt 7975c3fda7SSteven Rostedt } elsif ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) { 805c42fc5bSSteven Rostedt doprint "POWERING OFF\n"; 815c42fc5bSSteven Rostedt `$opt{"POWER_OFF"}`; 825c42fc5bSSteven Rostedt } 8375c3fda7SSteven Rostedt 845c42fc5bSSteven Rostedt die @_; 855c42fc5bSSteven Rostedt} 865c42fc5bSSteven Rostedt 872545eb61SSteven Rostedtsub run_command { 882545eb61SSteven Rostedt my ($command) = @_; 89*5a391fbfSSteven Rostedt my $redirect_log = ""; 902545eb61SSteven Rostedt 912545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 92*5a391fbfSSteven Rostedt $redirect_log = " >> $opt{LOG_FILE} 2>&1"; 932545eb61SSteven Rostedt } 942545eb61SSteven Rostedt 952545eb61SSteven Rostedt doprint "$command ... "; 96*5a391fbfSSteven Rostedt `$command $redirect_log`; 972545eb61SSteven Rostedt 982545eb61SSteven Rostedt my $failed = $?; 992545eb61SSteven Rostedt 1002545eb61SSteven Rostedt if ($failed) { 1012545eb61SSteven Rostedt doprint "FAILED!\n"; 1022545eb61SSteven Rostedt } else { 1032545eb61SSteven Rostedt doprint "SUCCESS\n"; 1042545eb61SSteven Rostedt } 1052545eb61SSteven Rostedt 1065f9b6cedSSteven Rostedt return !$failed; 1075f9b6cedSSteven Rostedt} 1085f9b6cedSSteven Rostedt 1095f9b6cedSSteven Rostedtsub get_grub_index { 1105f9b6cedSSteven Rostedt 111*5a391fbfSSteven Rostedt return if (defined($grub_number)); 1125f9b6cedSSteven Rostedt 1135f9b6cedSSteven Rostedt doprint "Find grub menu ... "; 1145f9b6cedSSteven Rostedt $grub_number = -1; 1155f9b6cedSSteven Rostedt open(IN, "ssh $target cat /boot/grub/menu.lst |") 1165f9b6cedSSteven Rostedt or die "unable to get menu.lst"; 1175f9b6cedSSteven Rostedt while (<IN>) { 1185f9b6cedSSteven Rostedt if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) { 1195f9b6cedSSteven Rostedt $grub_number++; 1205f9b6cedSSteven Rostedt last; 1215f9b6cedSSteven Rostedt } elsif (/^\s*title\s/) { 1225f9b6cedSSteven Rostedt $grub_number++; 1235f9b6cedSSteven Rostedt } 1245f9b6cedSSteven Rostedt } 1255f9b6cedSSteven Rostedt close(IN); 1265f9b6cedSSteven Rostedt 1275f9b6cedSSteven Rostedt die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}" 1285f9b6cedSSteven Rostedt if ($grub_number < 0); 1295f9b6cedSSteven Rostedt doprint "$grub_number\n"; 1302545eb61SSteven Rostedt} 1312545eb61SSteven Rostedt 1322545eb61SSteven Rostedtmy $timeout = $opt{"TIMEOUT"}; 1332545eb61SSteven Rostedt 1342545eb61SSteven Rostedtsub wait_for_input 1352545eb61SSteven Rostedt{ 1362545eb61SSteven Rostedt my ($fp, $time) = @_; 1372545eb61SSteven Rostedt my $rin; 1382545eb61SSteven Rostedt my $ready; 1392545eb61SSteven Rostedt my $line; 1402545eb61SSteven Rostedt my $ch; 1412545eb61SSteven Rostedt 1422545eb61SSteven Rostedt if (!defined($time)) { 1432545eb61SSteven Rostedt $time = $timeout; 1442545eb61SSteven Rostedt } 1452545eb61SSteven Rostedt 1462545eb61SSteven Rostedt $rin = ''; 1472545eb61SSteven Rostedt vec($rin, fileno($fp), 1) = 1; 1482545eb61SSteven Rostedt $ready = select($rin, undef, undef, $time); 1492545eb61SSteven Rostedt 1502545eb61SSteven Rostedt $line = ""; 1512545eb61SSteven Rostedt 1522545eb61SSteven Rostedt # try to read one char at a time 1532545eb61SSteven Rostedt while (sysread $fp, $ch, 1) { 1542545eb61SSteven Rostedt $line .= $ch; 1552545eb61SSteven Rostedt last if ($ch eq "\n"); 1562545eb61SSteven Rostedt } 1572545eb61SSteven Rostedt 1582545eb61SSteven Rostedt if (!length($line)) { 1592545eb61SSteven Rostedt return undef; 1602545eb61SSteven Rostedt } 1612545eb61SSteven Rostedt 1622545eb61SSteven Rostedt return $line; 1632545eb61SSteven Rostedt} 1642545eb61SSteven Rostedt 16575c3fda7SSteven Rostedtsub reboot_to { 1662545eb61SSteven Rostedt run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; 1672545eb61SSteven Rostedt} 1682545eb61SSteven Rostedt 169*5a391fbfSSteven Rostedtsub open_console { 170*5a391fbfSSteven Rostedt my ($fp) = @_; 171*5a391fbfSSteven Rostedt 1722545eb61SSteven Rostedt my $flags; 173*5a391fbfSSteven Rostedt 174*5a391fbfSSteven Rostedt my $pid = open($fp, "$opt{CONSOLE}|") or 175*5a391fbfSSteven Rostedt dodie "Can't open console $opt{CONSOLE}"; 176*5a391fbfSSteven Rostedt 177*5a391fbfSSteven Rostedt $flags = fcntl($fp, F_GETFL, 0) or 178*5a391fbfSSteven Rostedt dodie "Can't get flags for the socket: $!\n"; 179*5a391fbfSSteven Rostedt $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 180*5a391fbfSSteven Rostedt dodie "Can't set flags for the socket: $!\n"; 181*5a391fbfSSteven Rostedt 182*5a391fbfSSteven Rostedt return $pid; 183*5a391fbfSSteven Rostedt} 184*5a391fbfSSteven Rostedt 185*5a391fbfSSteven Rostedtsub close_console { 186*5a391fbfSSteven Rostedt my ($fp, $pid) = @_; 187*5a391fbfSSteven Rostedt 188*5a391fbfSSteven Rostedt doprint "kill child process $pid\n"; 189*5a391fbfSSteven Rostedt kill 2, $pid; 190*5a391fbfSSteven Rostedt 191*5a391fbfSSteven Rostedt print "closing!\n"; 192*5a391fbfSSteven Rostedt close($fp); 193*5a391fbfSSteven Rostedt} 194*5a391fbfSSteven Rostedt 195*5a391fbfSSteven Rostedtsub monitor { 1962545eb61SSteven Rostedt my $booted = 0; 1972545eb61SSteven Rostedt my $bug = 0; 1982545eb61SSteven Rostedt my $pid; 1995c42fc5bSSteven Rostedt my $skip_call_trace = 0; 200*5a391fbfSSteven Rostedt my $fp = \*IN; 2012545eb61SSteven Rostedt 202*5a391fbfSSteven Rostedt $pid = open_console($fp); 2032545eb61SSteven Rostedt 2042545eb61SSteven Rostedt my $line; 2052545eb61SSteven Rostedt my $full_line = ""; 2062545eb61SSteven Rostedt 2072545eb61SSteven Rostedt doprint "Wait for monitor to settle down.\n"; 2082545eb61SSteven Rostedt # read the monitor and wait for the system to calm down 2092545eb61SSteven Rostedt do { 210*5a391fbfSSteven Rostedt $line = wait_for_input($fp, 5); 2112545eb61SSteven Rostedt } while (defined($line)); 2122545eb61SSteven Rostedt 21375c3fda7SSteven Rostedt reboot_to; 2142545eb61SSteven Rostedt 2152545eb61SSteven Rostedt for (;;) { 2162545eb61SSteven Rostedt 217*5a391fbfSSteven Rostedt $line = wait_for_input($fp); 2182545eb61SSteven Rostedt 2192545eb61SSteven Rostedt last if (!defined($line)); 2202545eb61SSteven Rostedt 2212545eb61SSteven Rostedt doprint $line; 2222545eb61SSteven Rostedt 2232545eb61SSteven Rostedt # we are not guaranteed to get a full line 2242545eb61SSteven Rostedt $full_line .= $line; 2252545eb61SSteven Rostedt 2262545eb61SSteven Rostedt if ($full_line =~ /login:/) { 2272545eb61SSteven Rostedt $booted = 1; 2282545eb61SSteven Rostedt } 2292545eb61SSteven Rostedt 2305c42fc5bSSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 2315c42fc5bSSteven Rostedt $skip_call_trace = 1; 2325c42fc5bSSteven Rostedt } 2335c42fc5bSSteven Rostedt 2342545eb61SSteven Rostedt if ($full_line =~ /call trace:/i) { 2355c42fc5bSSteven Rostedt $bug = 1 if (!$skip_call_trace); 2365c42fc5bSSteven Rostedt } 2375c42fc5bSSteven Rostedt 2385c42fc5bSSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 2395c42fc5bSSteven Rostedt $skip_call_trace = 0; 2405c42fc5bSSteven Rostedt } 2415c42fc5bSSteven Rostedt 2425c42fc5bSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 2432545eb61SSteven Rostedt $bug = 1; 2442545eb61SSteven Rostedt } 2452545eb61SSteven Rostedt 2462545eb61SSteven Rostedt if ($line =~ /\n/) { 2472545eb61SSteven Rostedt $full_line = ""; 2482545eb61SSteven Rostedt } 2492545eb61SSteven Rostedt } 2502545eb61SSteven Rostedt 251*5a391fbfSSteven Rostedt close_console($fp, $pid); 2522545eb61SSteven Rostedt 2532545eb61SSteven Rostedt if (!$booted) { 254*5a391fbfSSteven Rostedt return 1 if ($in_bisect); 2555c42fc5bSSteven Rostedt dodie "failed - never got a boot prompt.\n"; 2562545eb61SSteven Rostedt } 2572545eb61SSteven Rostedt 2582545eb61SSteven Rostedt if ($bug) { 259*5a391fbfSSteven Rostedt return 1 if ($in_bisect); 2605c42fc5bSSteven Rostedt dodie "failed - got a bug report\n"; 2612545eb61SSteven Rostedt } 2625f9b6cedSSteven Rostedt 2635f9b6cedSSteven Rostedt return 0; 2642545eb61SSteven Rostedt} 2652545eb61SSteven Rostedt 2662545eb61SSteven Rostedtsub install { 2672545eb61SSteven Rostedt 2685f9b6cedSSteven Rostedt run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}" or 2695c42fc5bSSteven Rostedt dodie "failed to copy image"; 2705f9b6cedSSteven Rostedt 2715f9b6cedSSteven Rostedt my $install_mods = 0; 2725f9b6cedSSteven Rostedt 2735f9b6cedSSteven Rostedt # should we process modules? 2745f9b6cedSSteven Rostedt $install_mods = 0; 2755f9b6cedSSteven Rostedt open(IN, "$opt{OUTPUT_DIR}/.config") or dodie("Can't read config file"); 2765f9b6cedSSteven Rostedt while (<IN>) { 2775f9b6cedSSteven Rostedt if (/CONFIG_MODULES(=y)?/) { 2785f9b6cedSSteven Rostedt $install_mods = 1 if (defined($1)); 2795f9b6cedSSteven Rostedt last; 2805f9b6cedSSteven Rostedt } 2815f9b6cedSSteven Rostedt } 2825f9b6cedSSteven Rostedt close(IN); 2835f9b6cedSSteven Rostedt 2845f9b6cedSSteven Rostedt if (!$install_mods) { 2855f9b6cedSSteven Rostedt doprint "No modules needed\n"; 2865f9b6cedSSteven Rostedt return; 2872545eb61SSteven Rostedt } 2882545eb61SSteven Rostedt 2895f9b6cedSSteven Rostedt run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install" or 2905f9b6cedSSteven Rostedt dodie "Failed to install modules"; 2915f9b6cedSSteven Rostedt 2922545eb61SSteven Rostedt my $modlib = "/lib/modules/$version"; 2935c42fc5bSSteven Rostedt my $modtar = "autotest-mods.tar.bz2"; 2942545eb61SSteven Rostedt 2955f9b6cedSSteven Rostedt run_command "ssh $target rm -rf $modlib" or 2965c42fc5bSSteven Rostedt dodie "failed to remove old mods: $modlib"; 2972545eb61SSteven Rostedt 2985c42fc5bSSteven Rostedt # would be nice if scp -r did not follow symbolic links 2995f9b6cedSSteven Rostedt run_command "cd $opt{TMP_DIR} && tar -cjf $modtar lib/modules/$version" or 3005c42fc5bSSteven Rostedt dodie "making tarball"; 3015c42fc5bSSteven Rostedt 3025f9b6cedSSteven Rostedt run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp" or 3035c42fc5bSSteven Rostedt dodie "failed to copy modules"; 3045c42fc5bSSteven Rostedt 3055c42fc5bSSteven Rostedt unlink "$opt{TMP_DIR}/$modtar"; 3065c42fc5bSSteven Rostedt 3075f9b6cedSSteven Rostedt run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or 3085c42fc5bSSteven Rostedt dodie "failed to tar modules"; 3095c42fc5bSSteven Rostedt 3105c42fc5bSSteven Rostedt run_command "ssh $target rm -f /tmp/$modtar"; 3112545eb61SSteven Rostedt} 3122545eb61SSteven Rostedt 3132545eb61SSteven Rostedtsub build { 3142545eb61SSteven Rostedt my ($type) = @_; 3155c42fc5bSSteven Rostedt my $defconfig = ""; 3165c42fc5bSSteven Rostedt my $append = ""; 3172545eb61SSteven Rostedt 31875c3fda7SSteven Rostedt if ($type =~ /^useconfig:(.*)/) { 3195f9b6cedSSteven Rostedt run_command "cp $1 $opt{OUTPUT_DIR}/.config" or 32075c3fda7SSteven Rostedt dodie "could not copy $1 to .config"; 3215f9b6cedSSteven Rostedt 32275c3fda7SSteven Rostedt $type = "oldconfig"; 32375c3fda7SSteven Rostedt } 32475c3fda7SSteven Rostedt 3255c42fc5bSSteven Rostedt # old config can ask questions 3265c42fc5bSSteven Rostedt if ($type eq "oldconfig") { 3275c42fc5bSSteven Rostedt $append = "yes ''|"; 32875c3fda7SSteven Rostedt 32975c3fda7SSteven Rostedt # allow for empty configs 33075c3fda7SSteven Rostedt run_command "touch $opt{OUTPUT_DIR}/.config"; 33175c3fda7SSteven Rostedt 3325f9b6cedSSteven Rostedt run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp" or 3335c42fc5bSSteven Rostedt dodie "moving .config"; 3345c42fc5bSSteven Rostedt 3355f9b6cedSSteven Rostedt if (!$noclean && !run_command "$make mrproper") { 3365c42fc5bSSteven Rostedt dodie "make mrproper"; 3375c42fc5bSSteven Rostedt } 3385c42fc5bSSteven Rostedt 3395f9b6cedSSteven Rostedt run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config" or 3405c42fc5bSSteven Rostedt dodie "moving config_temp"; 3415c42fc5bSSteven Rostedt 3425c42fc5bSSteven Rostedt } elsif (!$noclean) { 3432545eb61SSteven Rostedt unlink "$opt{OUTPUT_DIR}/.config"; 3445f9b6cedSSteven Rostedt run_command "$make mrproper" or 3455c42fc5bSSteven Rostedt dodie "make mrproper"; 3465c42fc5bSSteven Rostedt } 3472545eb61SSteven Rostedt 3482545eb61SSteven Rostedt # add something to distinguish this build 3495c42fc5bSSteven Rostedt open(OUT, "> $opt{OUTPUT_DIR}/localversion") or dodie("Can't make localversion file"); 3502545eb61SSteven Rostedt print OUT "$opt{LOCALVERSION}\n"; 3512545eb61SSteven Rostedt close(OUT); 3522545eb61SSteven Rostedt 3535f9b6cedSSteven Rostedt if (defined($minconfig)) { 3545f9b6cedSSteven Rostedt $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; 3552545eb61SSteven Rostedt } 3562545eb61SSteven Rostedt 3575f9b6cedSSteven Rostedt run_command "$defconfig $append $make $type" or 3585c42fc5bSSteven Rostedt dodie "failed make config"; 3592545eb61SSteven Rostedt 3605f9b6cedSSteven Rostedt if (!run_command "$make $opt{BUILD_OPTIONS}") { 3615f9b6cedSSteven Rostedt # bisect may need this to pass 3625f9b6cedSSteven Rostedt return 1 if ($in_bisect); 3635c42fc5bSSteven Rostedt dodie "failed build"; 3642545eb61SSteven Rostedt } 3655f9b6cedSSteven Rostedt 3665f9b6cedSSteven Rostedt return 0; 3672545eb61SSteven Rostedt} 3682545eb61SSteven Rostedt 36975c3fda7SSteven Rostedtsub reboot { 37075c3fda7SSteven Rostedt # try to reboot normally 3715f9b6cedSSteven Rostedt if (!run_command "ssh $target reboot") { 37275c3fda7SSteven Rostedt # nope? power cycle it. 37375c3fda7SSteven Rostedt run_command "$opt{POWER_CYCLE}"; 37475c3fda7SSteven Rostedt } 37575c3fda7SSteven Rostedt} 37675c3fda7SSteven Rostedt 37775c3fda7SSteven Rostedtsub halt { 3785f9b6cedSSteven Rostedt if (!run_command "ssh $target halt" or defined($opt{"POWER_OFF"})) { 37975c3fda7SSteven Rostedt # nope? the zap it! 38075c3fda7SSteven Rostedt run_command "$opt{POWER_OFF}"; 38175c3fda7SSteven Rostedt } 38275c3fda7SSteven Rostedt} 38375c3fda7SSteven Rostedt 3845f9b6cedSSteven Rostedtsub success { 3855f9b6cedSSteven Rostedt my ($i) = @_; 3865f9b6cedSSteven Rostedt 3875f9b6cedSSteven Rostedt doprint "\n\n*******************************************\n"; 3885f9b6cedSSteven Rostedt doprint "*******************************************\n"; 3895f9b6cedSSteven Rostedt doprint "** SUCCESS!!!! **\n"; 3905f9b6cedSSteven Rostedt doprint "*******************************************\n"; 3915f9b6cedSSteven Rostedt doprint "*******************************************\n"; 3925f9b6cedSSteven Rostedt 3935f9b6cedSSteven Rostedt if ($i != $opt{"NUM_BUILDS"}) { 3945f9b6cedSSteven Rostedt reboot; 3955f9b6cedSSteven Rostedt doprint "Sleeping $opt{SLEEP_TIME} seconds\n"; 3965f9b6cedSSteven Rostedt sleep "$opt{SLEEP_TIME}"; 3975f9b6cedSSteven Rostedt } 3985f9b6cedSSteven Rostedt} 3995f9b6cedSSteven Rostedt 4005f9b6cedSSteven Rostedtsub get_version { 4015f9b6cedSSteven Rostedt # get the release name 4025f9b6cedSSteven Rostedt doprint "$make kernelrelease ... "; 4035f9b6cedSSteven Rostedt $version = `$make kernelrelease | tail -1`; 4045f9b6cedSSteven Rostedt chomp($version); 4055f9b6cedSSteven Rostedt doprint "$version\n"; 4065f9b6cedSSteven Rostedt} 4075f9b6cedSSteven Rostedt 408*5a391fbfSSteven Rostedtsub child_run_test { 409*5a391fbfSSteven Rostedt my $failed; 410*5a391fbfSSteven Rostedt 411*5a391fbfSSteven Rostedt $failed = !run_command $run_test; 412*5a391fbfSSteven Rostedt exit $failed; 413*5a391fbfSSteven Rostedt} 414*5a391fbfSSteven Rostedt 415*5a391fbfSSteven Rostedtmy $child_done; 416*5a391fbfSSteven Rostedt 417*5a391fbfSSteven Rostedtsub child_finished { 418*5a391fbfSSteven Rostedt $child_done = 1; 419*5a391fbfSSteven Rostedt} 420*5a391fbfSSteven Rostedt 421*5a391fbfSSteven Rostedtsub do_run_test { 422*5a391fbfSSteven Rostedt my $child_pid; 423*5a391fbfSSteven Rostedt my $child_exit; 424*5a391fbfSSteven Rostedt my $pid; 425*5a391fbfSSteven Rostedt my $line; 426*5a391fbfSSteven Rostedt my $full_line; 427*5a391fbfSSteven Rostedt my $bug = 0; 428*5a391fbfSSteven Rostedt my $fp = \*IN; 429*5a391fbfSSteven Rostedt 430*5a391fbfSSteven Rostedt $pid = open_console($fp); 431*5a391fbfSSteven Rostedt 432*5a391fbfSSteven Rostedt # read the monitor and wait for the system to calm down 433*5a391fbfSSteven Rostedt do { 434*5a391fbfSSteven Rostedt $line = wait_for_input($fp, 1); 435*5a391fbfSSteven Rostedt } while (defined($line)); 436*5a391fbfSSteven Rostedt 437*5a391fbfSSteven Rostedt $child_done = 0; 438*5a391fbfSSteven Rostedt 439*5a391fbfSSteven Rostedt $SIG{CHLD} = qw(child_finished); 440*5a391fbfSSteven Rostedt 441*5a391fbfSSteven Rostedt $child_pid = fork; 442*5a391fbfSSteven Rostedt 443*5a391fbfSSteven Rostedt child_run_test if (!$child_pid); 444*5a391fbfSSteven Rostedt 445*5a391fbfSSteven Rostedt $full_line = ""; 446*5a391fbfSSteven Rostedt 447*5a391fbfSSteven Rostedt do { 448*5a391fbfSSteven Rostedt $line = wait_for_input($fp, 1); 449*5a391fbfSSteven Rostedt if (defined($line)) { 450*5a391fbfSSteven Rostedt 451*5a391fbfSSteven Rostedt # we are not guaranteed to get a full line 452*5a391fbfSSteven Rostedt $full_line .= $line; 453*5a391fbfSSteven Rostedt 454*5a391fbfSSteven Rostedt if ($full_line =~ /call trace:/i) { 455*5a391fbfSSteven Rostedt $bug = 1; 456*5a391fbfSSteven Rostedt } 457*5a391fbfSSteven Rostedt 458*5a391fbfSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 459*5a391fbfSSteven Rostedt $bug = 1; 460*5a391fbfSSteven Rostedt } 461*5a391fbfSSteven Rostedt 462*5a391fbfSSteven Rostedt if ($line =~ /\n/) { 463*5a391fbfSSteven Rostedt $full_line = ""; 464*5a391fbfSSteven Rostedt } 465*5a391fbfSSteven Rostedt } 466*5a391fbfSSteven Rostedt } while (!$child_done && !$bug); 467*5a391fbfSSteven Rostedt 468*5a391fbfSSteven Rostedt if ($bug) { 469*5a391fbfSSteven Rostedt doprint "Detected kernel crash!\n"; 470*5a391fbfSSteven Rostedt # kill the child with extreme prejudice 471*5a391fbfSSteven Rostedt kill 9, $child_pid; 472*5a391fbfSSteven Rostedt } 473*5a391fbfSSteven Rostedt 474*5a391fbfSSteven Rostedt waitpid $child_pid, 0; 475*5a391fbfSSteven Rostedt $child_exit = $?; 476*5a391fbfSSteven Rostedt 477*5a391fbfSSteven Rostedt close_console($fp, $pid); 478*5a391fbfSSteven Rostedt 479*5a391fbfSSteven Rostedt if ($bug || $child_exit) { 480*5a391fbfSSteven Rostedt return 1 if $in_bisect; 481*5a391fbfSSteven Rostedt dodie "test failed"; 482*5a391fbfSSteven Rostedt } 483*5a391fbfSSteven Rostedt return 0; 484*5a391fbfSSteven Rostedt} 485*5a391fbfSSteven Rostedt 4865f9b6cedSSteven Rostedtsub run_bisect { 4875f9b6cedSSteven Rostedt my ($type) = @_; 4885f9b6cedSSteven Rostedt 4895f9b6cedSSteven Rostedt my $failed; 4905f9b6cedSSteven Rostedt my $result; 4915f9b6cedSSteven Rostedt my $output; 4925f9b6cedSSteven Rostedt my $ret; 4935f9b6cedSSteven Rostedt 4945f9b6cedSSteven Rostedt 4955f9b6cedSSteven Rostedt if (defined($minconfig)) { 4965f9b6cedSSteven Rostedt $failed = build "useconfig:$minconfig"; 4975f9b6cedSSteven Rostedt } else { 4985f9b6cedSSteven Rostedt # ?? no config to use? 4995f9b6cedSSteven Rostedt $failed = build "oldconfig"; 5005f9b6cedSSteven Rostedt } 5015f9b6cedSSteven Rostedt 5025f9b6cedSSteven Rostedt if ($type ne "build") { 5035f9b6cedSSteven Rostedt dodie "Failed on build" if $failed; 5045f9b6cedSSteven Rostedt 5055f9b6cedSSteven Rostedt # Now boot the box 5065f9b6cedSSteven Rostedt get_grub_index; 5075f9b6cedSSteven Rostedt get_version; 5085f9b6cedSSteven Rostedt install; 5095f9b6cedSSteven Rostedt $failed = monitor; 5105f9b6cedSSteven Rostedt 5115f9b6cedSSteven Rostedt if ($type ne "boot") { 5125f9b6cedSSteven Rostedt dodie "Failed on boot" if $failed; 513*5a391fbfSSteven Rostedt 514*5a391fbfSSteven Rostedt $failed = do_run_test; 5155f9b6cedSSteven Rostedt } 5165f9b6cedSSteven Rostedt } 5175f9b6cedSSteven Rostedt 5185f9b6cedSSteven Rostedt if ($failed) { 5195f9b6cedSSteven Rostedt $result = "bad"; 520*5a391fbfSSteven Rostedt 521*5a391fbfSSteven Rostedt # reboot the box to a good kernel 522*5a391fbfSSteven Rostedt if ($type eq "boot") { 523*5a391fbfSSteven Rostedt reboot; 524*5a391fbfSSteven Rostedt doprint "sleep a little for reboot\n"; 525*5a391fbfSSteven Rostedt sleep $opt{"BISECT_SLEEP_TIME"}; 526*5a391fbfSSteven Rostedt } 5275f9b6cedSSteven Rostedt } else { 5285f9b6cedSSteven Rostedt $result = "good"; 5295f9b6cedSSteven Rostedt } 5305f9b6cedSSteven Rostedt 5315f9b6cedSSteven Rostedt doprint "git bisect $result ... "; 5325f9b6cedSSteven Rostedt $output = `git bisect $result 2>&1`; 5335f9b6cedSSteven Rostedt $ret = $?; 5345f9b6cedSSteven Rostedt 5355f9b6cedSSteven Rostedt logit $output; 5365f9b6cedSSteven Rostedt 5375f9b6cedSSteven Rostedt if ($ret) { 5385f9b6cedSSteven Rostedt doprint "FAILED\n"; 5395f9b6cedSSteven Rostedt dodie "Failed to git bisect"; 5405f9b6cedSSteven Rostedt } 5415f9b6cedSSteven Rostedt 5425f9b6cedSSteven Rostedt doprint "SUCCESS\n"; 543*5a391fbfSSteven Rostedt if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 5445f9b6cedSSteven Rostedt doprint "$1 [$2]\n"; 5455f9b6cedSSteven Rostedt } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 5465f9b6cedSSteven Rostedt $bisect_bad = $1; 5475f9b6cedSSteven Rostedt doprint "Found bad commit... $1\n"; 5485f9b6cedSSteven Rostedt return 0; 549*5a391fbfSSteven Rostedt } else { 550*5a391fbfSSteven Rostedt # we already logged it, just print it now. 551*5a391fbfSSteven Rostedt print $output; 5525f9b6cedSSteven Rostedt } 5535f9b6cedSSteven Rostedt 5545f9b6cedSSteven Rostedt 5555f9b6cedSSteven Rostedt return 1; 5565f9b6cedSSteven Rostedt} 5575f9b6cedSSteven Rostedt 5585f9b6cedSSteven Rostedtsub bisect { 5595f9b6cedSSteven Rostedt my ($i) = @_; 5605f9b6cedSSteven Rostedt 5615f9b6cedSSteven Rostedt my $result; 5625f9b6cedSSteven Rostedt 5635f9b6cedSSteven Rostedt die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 5645f9b6cedSSteven Rostedt die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 5655f9b6cedSSteven Rostedt die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 5665f9b6cedSSteven Rostedt 5675f9b6cedSSteven Rostedt my $good = $opt{"BISECT_GOOD[$i]"}; 5685f9b6cedSSteven Rostedt my $bad = $opt{"BISECT_BAD[$i]"}; 5695f9b6cedSSteven Rostedt my $type = $opt{"BISECT_TYPE[$i]"}; 5705f9b6cedSSteven Rostedt 5715f9b6cedSSteven Rostedt $in_bisect = 1; 5725f9b6cedSSteven Rostedt 5735f9b6cedSSteven Rostedt run_command "git bisect start" or 5745f9b6cedSSteven Rostedt dodie "could not start bisect"; 5755f9b6cedSSteven Rostedt 5765f9b6cedSSteven Rostedt run_command "git bisect good $good" or 5775f9b6cedSSteven Rostedt dodie "could not set bisect good to $good"; 5785f9b6cedSSteven Rostedt 5795f9b6cedSSteven Rostedt run_command "git bisect bad $bad" or 5805f9b6cedSSteven Rostedt dodie "could not set bisect good to $bad"; 5815f9b6cedSSteven Rostedt 582*5a391fbfSSteven Rostedt # Can't have a test without having a test to run 583*5a391fbfSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 584*5a391fbfSSteven Rostedt $type = "boot"; 585*5a391fbfSSteven Rostedt } 586*5a391fbfSSteven Rostedt 5875f9b6cedSSteven Rostedt do { 5885f9b6cedSSteven Rostedt $result = run_bisect $type; 5895f9b6cedSSteven Rostedt } while ($result); 5905f9b6cedSSteven Rostedt 5915f9b6cedSSteven Rostedt run_command "git bisect log" or 5925f9b6cedSSteven Rostedt dodie "could not capture git bisect log"; 5935f9b6cedSSteven Rostedt 5945f9b6cedSSteven Rostedt run_command "git bisect reset" or 5955f9b6cedSSteven Rostedt dodie "could not reset git bisect"; 5965f9b6cedSSteven Rostedt 5975f9b6cedSSteven Rostedt doprint "Bad commit was [$bisect_bad]\n"; 5985f9b6cedSSteven Rostedt 5995f9b6cedSSteven Rostedt $in_bisect = 0; 6005f9b6cedSSteven Rostedt 6015f9b6cedSSteven Rostedt success $i; 6025f9b6cedSSteven Rostedt} 6035f9b6cedSSteven Rostedt 6042545eb61SSteven Rostedtread_config $ARGV[0]; 6052545eb61SSteven Rostedt 6062545eb61SSteven Rostedt# mandatory configs 6072545eb61SSteven Rostedtdie "MACHINE not defined\n" if (!defined($opt{"MACHINE"})); 6082545eb61SSteven Rostedtdie "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"})); 6092545eb61SSteven Rostedtdie "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"})); 6102545eb61SSteven Rostedtdie "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"})); 6112545eb61SSteven Rostedtdie "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"})); 61275c3fda7SSteven Rostedtdie "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"})); 6132545eb61SSteven Rostedtdie "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"})); 6142545eb61SSteven Rostedtdie "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"})); 6152545eb61SSteven Rostedtdie "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"})); 6162545eb61SSteven Rostedtdie "GRUB_MENU not defined\n" if (!defined($opt{"GRUB_MENU"})); 6172545eb61SSteven Rostedt 6182545eb61SSteven Rostedtchdir $opt{"BUILD_DIR"} || die "can't change directory to $opt{BUILD_DIR}"; 6192545eb61SSteven Rostedt 6202545eb61SSteven Rostedt$target = "$opt{SSH_USER}\@$opt{MACHINE}"; 6212545eb61SSteven Rostedt 6222545eb61SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n"; 6232545eb61SSteven Rostedt 6242545eb61SSteven Rostedt 6252545eb61SSteven Rostedt$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}"; 6262545eb61SSteven Rostedt 627*5a391fbfSSteven Rostedtsub set_build_option { 628*5a391fbfSSteven Rostedt my ($name, $i) = @_; 629*5a391fbfSSteven Rostedt 630*5a391fbfSSteven Rostedt my $option = "$name\[$i\]"; 631*5a391fbfSSteven Rostedt 632*5a391fbfSSteven Rostedt if (defined($opt{$option})) { 633*5a391fbfSSteven Rostedt return $opt{$option}; 634*5a391fbfSSteven Rostedt } 635*5a391fbfSSteven Rostedt 636*5a391fbfSSteven Rostedt if (defined($opt{$name})) { 637*5a391fbfSSteven Rostedt return $opt{$name}; 638*5a391fbfSSteven Rostedt } 639*5a391fbfSSteven Rostedt 640*5a391fbfSSteven Rostedt return undef; 641*5a391fbfSSteven Rostedt} 642*5a391fbfSSteven Rostedt 6432545eb61SSteven Rostedt# First we need to do is the builds 6442545eb61SSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) { 6452545eb61SSteven Rostedt my $type = "BUILD_TYPE[$i]"; 6462545eb61SSteven Rostedt 647*5a391fbfSSteven Rostedt $noclean = set_build_option("BUILD_NOCLEAN", $i); 648*5a391fbfSSteven Rostedt $minconfig = set_build_option("MIN_CONFIG", $i); 649*5a391fbfSSteven Rostedt $run_test = set_build_option("TEST", $i); 6502545eb61SSteven Rostedt 6512545eb61SSteven Rostedt doprint "\n\n"; 6522545eb61SSteven Rostedt doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n"; 6532545eb61SSteven Rostedt 6545f9b6cedSSteven Rostedt if ($opt{$type} eq "bisect") { 6555f9b6cedSSteven Rostedt bisect $i; 6565f9b6cedSSteven Rostedt next; 6575f9b6cedSSteven Rostedt } 6585f9b6cedSSteven Rostedt 6592545eb61SSteven Rostedt if ($opt{$type} ne "nobuild") { 6605c42fc5bSSteven Rostedt build $opt{$type}; 6612545eb61SSteven Rostedt } 6622545eb61SSteven Rostedt 6635f9b6cedSSteven Rostedt get_grub_index; 6645f9b6cedSSteven Rostedt get_version; 6652545eb61SSteven Rostedt install; 6662545eb61SSteven Rostedt monitor; 667*5a391fbfSSteven Rostedt 668*5a391fbfSSteven Rostedt if (defined($run_test)) { 669*5a391fbfSSteven Rostedt do_run_test; 670*5a391fbfSSteven Rostedt } 671*5a391fbfSSteven Rostedt 6725f9b6cedSSteven Rostedt success $i; 67375c3fda7SSteven Rostedt} 6742545eb61SSteven Rostedt 6755c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) { 67675c3fda7SSteven Rostedt halt; 67775c3fda7SSteven Rostedt} else { 67875c3fda7SSteven Rostedt reboot; 6795c42fc5bSSteven Rostedt} 68075c3fda7SSteven Rostedt 6812545eb61SSteven Rostedtexit 0; 682