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"} = ""; 262545eb61SSteven Rostedt 272545eb61SSteven Rostedtmy $version; 282545eb61SSteven Rostedtmy $grub_number; 292545eb61SSteven Rostedtmy $target; 302545eb61SSteven Rostedtmy $make; 315c42fc5bSSteven Rostedtmy $noclean; 32*5f9b6cedSSteven Rostedtmy $minconfig; 33*5f9b6cedSSteven Rostedtmy $in_bisect = 0; 34*5f9b6cedSSteven Rostedtmy $bisect_bad = ""; 352545eb61SSteven Rostedt 362545eb61SSteven Rostedtsub read_config { 372545eb61SSteven Rostedt my ($config) = @_; 382545eb61SSteven Rostedt 392545eb61SSteven Rostedt open(IN, $config) || die "can't read file $config"; 402545eb61SSteven Rostedt 412545eb61SSteven Rostedt while (<IN>) { 422545eb61SSteven Rostedt 432545eb61SSteven Rostedt # ignore blank lines and comments 442545eb61SSteven Rostedt next if (/^\s*$/ || /\s*\#/); 452545eb61SSteven Rostedt 462545eb61SSteven Rostedt if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) { 472545eb61SSteven Rostedt my $lvalue = $1; 482545eb61SSteven Rostedt my $rvalue = $2; 492545eb61SSteven Rostedt 502545eb61SSteven Rostedt $opt{$lvalue} = $rvalue; 512545eb61SSteven Rostedt } 522545eb61SSteven Rostedt } 532545eb61SSteven Rostedt 542545eb61SSteven Rostedt close(IN); 552545eb61SSteven Rostedt} 562545eb61SSteven Rostedt 57*5f9b6cedSSteven Rostedtsub logit { 582545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 592545eb61SSteven Rostedt open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 602545eb61SSteven Rostedt print OUT @_; 612545eb61SSteven Rostedt close(OUT); 622545eb61SSteven Rostedt } 632545eb61SSteven Rostedt} 642545eb61SSteven Rostedt 65*5f9b6cedSSteven Rostedtsub doprint { 66*5f9b6cedSSteven Rostedt print @_; 67*5f9b6cedSSteven Rostedt logit @_; 68*5f9b6cedSSteven Rostedt} 69*5f9b6cedSSteven Rostedt 705c42fc5bSSteven Rostedtsub dodie { 715c42fc5bSSteven Rostedt doprint "CRITICAL FAILURE... ", @_; 725c42fc5bSSteven Rostedt 7375c3fda7SSteven Rostedt if ($opt{"REBOOT_ON_ERROR"}) { 7475c3fda7SSteven Rostedt doprint "REBOOTING\n"; 7575c3fda7SSteven Rostedt `$opt{"POWER_CYCLE"}`; 7675c3fda7SSteven Rostedt 7775c3fda7SSteven Rostedt } elsif ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) { 785c42fc5bSSteven Rostedt doprint "POWERING OFF\n"; 795c42fc5bSSteven Rostedt `$opt{"POWER_OFF"}`; 805c42fc5bSSteven Rostedt } 8175c3fda7SSteven Rostedt 825c42fc5bSSteven Rostedt die @_; 835c42fc5bSSteven Rostedt} 845c42fc5bSSteven Rostedt 852545eb61SSteven Rostedtsub run_command { 862545eb61SSteven Rostedt my ($command) = @_; 872545eb61SSteven Rostedt my $redirect = ""; 882545eb61SSteven Rostedt 892545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 902545eb61SSteven Rostedt $redirect = " >> $opt{LOG_FILE} 2>&1"; 912545eb61SSteven Rostedt } 922545eb61SSteven Rostedt 932545eb61SSteven Rostedt doprint "$command ... "; 942545eb61SSteven Rostedt `$command $redirect`; 952545eb61SSteven Rostedt 962545eb61SSteven Rostedt my $failed = $?; 972545eb61SSteven Rostedt 982545eb61SSteven Rostedt if ($failed) { 992545eb61SSteven Rostedt doprint "FAILED!\n"; 1002545eb61SSteven Rostedt } else { 1012545eb61SSteven Rostedt doprint "SUCCESS\n"; 1022545eb61SSteven Rostedt } 1032545eb61SSteven Rostedt 104*5f9b6cedSSteven Rostedt return !$failed; 105*5f9b6cedSSteven Rostedt} 106*5f9b6cedSSteven Rostedt 107*5f9b6cedSSteven Rostedtsub get_grub_index { 108*5f9b6cedSSteven Rostedt 109*5f9b6cedSSteven Rostedt return if ($grub_number >= 0); 110*5f9b6cedSSteven Rostedt 111*5f9b6cedSSteven Rostedt doprint "Find grub menu ... "; 112*5f9b6cedSSteven Rostedt $grub_number = -1; 113*5f9b6cedSSteven Rostedt open(IN, "ssh $target cat /boot/grub/menu.lst |") 114*5f9b6cedSSteven Rostedt or die "unable to get menu.lst"; 115*5f9b6cedSSteven Rostedt while (<IN>) { 116*5f9b6cedSSteven Rostedt if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) { 117*5f9b6cedSSteven Rostedt $grub_number++; 118*5f9b6cedSSteven Rostedt last; 119*5f9b6cedSSteven Rostedt } elsif (/^\s*title\s/) { 120*5f9b6cedSSteven Rostedt $grub_number++; 121*5f9b6cedSSteven Rostedt } 122*5f9b6cedSSteven Rostedt } 123*5f9b6cedSSteven Rostedt close(IN); 124*5f9b6cedSSteven Rostedt 125*5f9b6cedSSteven Rostedt die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}" 126*5f9b6cedSSteven Rostedt if ($grub_number < 0); 127*5f9b6cedSSteven Rostedt doprint "$grub_number\n"; 1282545eb61SSteven Rostedt} 1292545eb61SSteven Rostedt 1302545eb61SSteven Rostedtmy $timeout = $opt{"TIMEOUT"}; 1312545eb61SSteven Rostedt 1322545eb61SSteven Rostedtsub wait_for_input 1332545eb61SSteven Rostedt{ 1342545eb61SSteven Rostedt my ($fp, $time) = @_; 1352545eb61SSteven Rostedt my $rin; 1362545eb61SSteven Rostedt my $ready; 1372545eb61SSteven Rostedt my $line; 1382545eb61SSteven Rostedt my $ch; 1392545eb61SSteven Rostedt 1402545eb61SSteven Rostedt if (!defined($time)) { 1412545eb61SSteven Rostedt $time = $timeout; 1422545eb61SSteven Rostedt } 1432545eb61SSteven Rostedt 1442545eb61SSteven Rostedt $rin = ''; 1452545eb61SSteven Rostedt vec($rin, fileno($fp), 1) = 1; 1462545eb61SSteven Rostedt $ready = select($rin, undef, undef, $time); 1472545eb61SSteven Rostedt 1482545eb61SSteven Rostedt $line = ""; 1492545eb61SSteven Rostedt 1502545eb61SSteven Rostedt # try to read one char at a time 1512545eb61SSteven Rostedt while (sysread $fp, $ch, 1) { 1522545eb61SSteven Rostedt $line .= $ch; 1532545eb61SSteven Rostedt last if ($ch eq "\n"); 1542545eb61SSteven Rostedt } 1552545eb61SSteven Rostedt 1562545eb61SSteven Rostedt if (!length($line)) { 1572545eb61SSteven Rostedt return undef; 1582545eb61SSteven Rostedt } 1592545eb61SSteven Rostedt 1602545eb61SSteven Rostedt return $line; 1612545eb61SSteven Rostedt} 1622545eb61SSteven Rostedt 16375c3fda7SSteven Rostedtsub reboot_to { 1642545eb61SSteven Rostedt run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; 1652545eb61SSteven Rostedt} 1662545eb61SSteven Rostedt 1672545eb61SSteven Rostedtsub monitor { 1682545eb61SSteven Rostedt my $flags; 1692545eb61SSteven Rostedt my $booted = 0; 1702545eb61SSteven Rostedt my $bug = 0; 1712545eb61SSteven Rostedt my $pid; 1722545eb61SSteven Rostedt my $doopen2 = 0; 1735c42fc5bSSteven Rostedt my $skip_call_trace = 0; 1742545eb61SSteven Rostedt 1752545eb61SSteven Rostedt if ($doopen2) { 17675c3fda7SSteven Rostedt $pid = open2(\*IN, \*OUT, $opt{"CONSOLE"}); 1772545eb61SSteven Rostedt if ($pid < 0) { 1785c42fc5bSSteven Rostedt dodie "Failed to connect to the console"; 1792545eb61SSteven Rostedt } 1802545eb61SSteven Rostedt } else { 1812545eb61SSteven Rostedt $pid = open(IN, "$opt{CONSOLE} |"); 1822545eb61SSteven Rostedt } 1832545eb61SSteven Rostedt 1842545eb61SSteven Rostedt $flags = fcntl(IN, F_GETFL, 0) or 1855c42fc5bSSteven Rostedt dodie "Can't get flags for the socket: $!\n"; 1862545eb61SSteven Rostedt 1872545eb61SSteven Rostedt $flags = fcntl(IN, F_SETFL, $flags | O_NONBLOCK) or 1885c42fc5bSSteven Rostedt dodie "Can't set flags for the socket: $!\n"; 1892545eb61SSteven Rostedt 1902545eb61SSteven Rostedt my $line; 1912545eb61SSteven Rostedt my $full_line = ""; 1922545eb61SSteven Rostedt 1932545eb61SSteven Rostedt doprint "Wait for monitor to settle down.\n"; 1942545eb61SSteven Rostedt # read the monitor and wait for the system to calm down 1952545eb61SSteven Rostedt do { 1962545eb61SSteven Rostedt $line = wait_for_input(\*IN, 5); 1972545eb61SSteven Rostedt } while (defined($line)); 1982545eb61SSteven Rostedt 19975c3fda7SSteven Rostedt reboot_to; 2002545eb61SSteven Rostedt 2012545eb61SSteven Rostedt for (;;) { 2022545eb61SSteven Rostedt 2032545eb61SSteven Rostedt $line = wait_for_input(\*IN); 2042545eb61SSteven Rostedt 2052545eb61SSteven Rostedt last if (!defined($line)); 2062545eb61SSteven Rostedt 2072545eb61SSteven Rostedt doprint $line; 2082545eb61SSteven Rostedt 2092545eb61SSteven Rostedt # we are not guaranteed to get a full line 2102545eb61SSteven Rostedt $full_line .= $line; 2112545eb61SSteven Rostedt 2122545eb61SSteven Rostedt if ($full_line =~ /login:/) { 2132545eb61SSteven Rostedt $booted = 1; 2142545eb61SSteven Rostedt } 2152545eb61SSteven Rostedt 2165c42fc5bSSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 2175c42fc5bSSteven Rostedt $skip_call_trace = 1; 2185c42fc5bSSteven Rostedt } 2195c42fc5bSSteven Rostedt 2202545eb61SSteven Rostedt if ($full_line =~ /call trace:/i) { 2215c42fc5bSSteven Rostedt $bug = 1 if (!$skip_call_trace); 2225c42fc5bSSteven Rostedt } 2235c42fc5bSSteven Rostedt 2245c42fc5bSSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 2255c42fc5bSSteven Rostedt $skip_call_trace = 0; 2265c42fc5bSSteven Rostedt } 2275c42fc5bSSteven Rostedt 2285c42fc5bSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 2292545eb61SSteven Rostedt $bug = 1; 2302545eb61SSteven Rostedt } 2312545eb61SSteven Rostedt 2322545eb61SSteven Rostedt if ($line =~ /\n/) { 2332545eb61SSteven Rostedt $full_line = ""; 2342545eb61SSteven Rostedt } 2352545eb61SSteven Rostedt } 2362545eb61SSteven Rostedt 2372545eb61SSteven Rostedt doprint "kill child process $pid\n"; 2382545eb61SSteven Rostedt kill 2, $pid; 2392545eb61SSteven Rostedt 2402545eb61SSteven Rostedt print "closing!\n"; 2412545eb61SSteven Rostedt close(IN); 2422545eb61SSteven Rostedt 2432545eb61SSteven Rostedt if (!$booted) { 244*5f9b6cedSSteven Rostedt return 1 if (!$in_bisect); 2455c42fc5bSSteven Rostedt dodie "failed - never got a boot prompt.\n"; 2462545eb61SSteven Rostedt } 2472545eb61SSteven Rostedt 2482545eb61SSteven Rostedt if ($bug) { 249*5f9b6cedSSteven Rostedt return 1 if (!$in_bisect); 2505c42fc5bSSteven Rostedt dodie "failed - got a bug report\n"; 2512545eb61SSteven Rostedt } 252*5f9b6cedSSteven Rostedt 253*5f9b6cedSSteven Rostedt return 0; 2542545eb61SSteven Rostedt} 2552545eb61SSteven Rostedt 2562545eb61SSteven Rostedtsub install { 2572545eb61SSteven Rostedt 258*5f9b6cedSSteven Rostedt run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}" or 2595c42fc5bSSteven Rostedt dodie "failed to copy image"; 260*5f9b6cedSSteven Rostedt 261*5f9b6cedSSteven Rostedt my $install_mods = 0; 262*5f9b6cedSSteven Rostedt 263*5f9b6cedSSteven Rostedt # should we process modules? 264*5f9b6cedSSteven Rostedt $install_mods = 0; 265*5f9b6cedSSteven Rostedt open(IN, "$opt{OUTPUT_DIR}/.config") or dodie("Can't read config file"); 266*5f9b6cedSSteven Rostedt while (<IN>) { 267*5f9b6cedSSteven Rostedt if (/CONFIG_MODULES(=y)?/) { 268*5f9b6cedSSteven Rostedt $install_mods = 1 if (defined($1)); 269*5f9b6cedSSteven Rostedt last; 270*5f9b6cedSSteven Rostedt } 271*5f9b6cedSSteven Rostedt } 272*5f9b6cedSSteven Rostedt close(IN); 273*5f9b6cedSSteven Rostedt 274*5f9b6cedSSteven Rostedt if (!$install_mods) { 275*5f9b6cedSSteven Rostedt doprint "No modules needed\n"; 276*5f9b6cedSSteven Rostedt return; 2772545eb61SSteven Rostedt } 2782545eb61SSteven Rostedt 279*5f9b6cedSSteven Rostedt run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install" or 280*5f9b6cedSSteven Rostedt dodie "Failed to install modules"; 281*5f9b6cedSSteven Rostedt 2822545eb61SSteven Rostedt my $modlib = "/lib/modules/$version"; 2835c42fc5bSSteven Rostedt my $modtar = "autotest-mods.tar.bz2"; 2842545eb61SSteven Rostedt 285*5f9b6cedSSteven Rostedt run_command "ssh $target rm -rf $modlib" or 2865c42fc5bSSteven Rostedt dodie "failed to remove old mods: $modlib"; 2872545eb61SSteven Rostedt 2885c42fc5bSSteven Rostedt # would be nice if scp -r did not follow symbolic links 289*5f9b6cedSSteven Rostedt run_command "cd $opt{TMP_DIR} && tar -cjf $modtar lib/modules/$version" or 2905c42fc5bSSteven Rostedt dodie "making tarball"; 2915c42fc5bSSteven Rostedt 292*5f9b6cedSSteven Rostedt run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp" or 2935c42fc5bSSteven Rostedt dodie "failed to copy modules"; 2945c42fc5bSSteven Rostedt 2955c42fc5bSSteven Rostedt unlink "$opt{TMP_DIR}/$modtar"; 2965c42fc5bSSteven Rostedt 297*5f9b6cedSSteven Rostedt run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or 2985c42fc5bSSteven Rostedt dodie "failed to tar modules"; 2995c42fc5bSSteven Rostedt 3005c42fc5bSSteven Rostedt run_command "ssh $target rm -f /tmp/$modtar"; 3012545eb61SSteven Rostedt} 3022545eb61SSteven Rostedt 3032545eb61SSteven Rostedtsub build { 3042545eb61SSteven Rostedt my ($type) = @_; 3055c42fc5bSSteven Rostedt my $defconfig = ""; 3065c42fc5bSSteven Rostedt my $append = ""; 3072545eb61SSteven Rostedt 30875c3fda7SSteven Rostedt if ($type =~ /^useconfig:(.*)/) { 309*5f9b6cedSSteven Rostedt run_command "cp $1 $opt{OUTPUT_DIR}/.config" or 31075c3fda7SSteven Rostedt dodie "could not copy $1 to .config"; 311*5f9b6cedSSteven Rostedt 31275c3fda7SSteven Rostedt $type = "oldconfig"; 31375c3fda7SSteven Rostedt } 31475c3fda7SSteven Rostedt 3155c42fc5bSSteven Rostedt # old config can ask questions 3165c42fc5bSSteven Rostedt if ($type eq "oldconfig") { 3175c42fc5bSSteven Rostedt $append = "yes ''|"; 31875c3fda7SSteven Rostedt 31975c3fda7SSteven Rostedt # allow for empty configs 32075c3fda7SSteven Rostedt run_command "touch $opt{OUTPUT_DIR}/.config"; 32175c3fda7SSteven Rostedt 322*5f9b6cedSSteven Rostedt run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp" or 3235c42fc5bSSteven Rostedt dodie "moving .config"; 3245c42fc5bSSteven Rostedt 325*5f9b6cedSSteven Rostedt if (!$noclean && !run_command "$make mrproper") { 3265c42fc5bSSteven Rostedt dodie "make mrproper"; 3275c42fc5bSSteven Rostedt } 3285c42fc5bSSteven Rostedt 329*5f9b6cedSSteven Rostedt run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config" or 3305c42fc5bSSteven Rostedt dodie "moving config_temp"; 3315c42fc5bSSteven Rostedt 3325c42fc5bSSteven Rostedt } elsif (!$noclean) { 3332545eb61SSteven Rostedt unlink "$opt{OUTPUT_DIR}/.config"; 334*5f9b6cedSSteven Rostedt run_command "$make mrproper" or 3355c42fc5bSSteven Rostedt dodie "make mrproper"; 3365c42fc5bSSteven Rostedt } 3372545eb61SSteven Rostedt 3382545eb61SSteven Rostedt # add something to distinguish this build 3395c42fc5bSSteven Rostedt open(OUT, "> $opt{OUTPUT_DIR}/localversion") or dodie("Can't make localversion file"); 3402545eb61SSteven Rostedt print OUT "$opt{LOCALVERSION}\n"; 3412545eb61SSteven Rostedt close(OUT); 3422545eb61SSteven Rostedt 343*5f9b6cedSSteven Rostedt if (defined($minconfig)) { 344*5f9b6cedSSteven Rostedt $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; 3452545eb61SSteven Rostedt } 3462545eb61SSteven Rostedt 347*5f9b6cedSSteven Rostedt run_command "$defconfig $append $make $type" or 3485c42fc5bSSteven Rostedt dodie "failed make config"; 3492545eb61SSteven Rostedt 350*5f9b6cedSSteven Rostedt if (!run_command "$make $opt{BUILD_OPTIONS}") { 351*5f9b6cedSSteven Rostedt # bisect may need this to pass 352*5f9b6cedSSteven Rostedt return 1 if ($in_bisect); 3535c42fc5bSSteven Rostedt dodie "failed build"; 3542545eb61SSteven Rostedt } 355*5f9b6cedSSteven Rostedt 356*5f9b6cedSSteven Rostedt return 0; 3572545eb61SSteven Rostedt} 3582545eb61SSteven Rostedt 35975c3fda7SSteven Rostedtsub reboot { 36075c3fda7SSteven Rostedt # try to reboot normally 361*5f9b6cedSSteven Rostedt if (!run_command "ssh $target reboot") { 36275c3fda7SSteven Rostedt # nope? power cycle it. 36375c3fda7SSteven Rostedt run_command "$opt{POWER_CYCLE}"; 36475c3fda7SSteven Rostedt } 36575c3fda7SSteven Rostedt} 36675c3fda7SSteven Rostedt 36775c3fda7SSteven Rostedtsub halt { 368*5f9b6cedSSteven Rostedt if (!run_command "ssh $target halt" or defined($opt{"POWER_OFF"})) { 36975c3fda7SSteven Rostedt # nope? the zap it! 37075c3fda7SSteven Rostedt run_command "$opt{POWER_OFF}"; 37175c3fda7SSteven Rostedt } 37275c3fda7SSteven Rostedt} 37375c3fda7SSteven Rostedt 374*5f9b6cedSSteven Rostedtsub success { 375*5f9b6cedSSteven Rostedt my ($i) = @_; 376*5f9b6cedSSteven Rostedt 377*5f9b6cedSSteven Rostedt doprint "\n\n*******************************************\n"; 378*5f9b6cedSSteven Rostedt doprint "*******************************************\n"; 379*5f9b6cedSSteven Rostedt doprint "** SUCCESS!!!! **\n"; 380*5f9b6cedSSteven Rostedt doprint "*******************************************\n"; 381*5f9b6cedSSteven Rostedt doprint "*******************************************\n"; 382*5f9b6cedSSteven Rostedt 383*5f9b6cedSSteven Rostedt if ($i != $opt{"NUM_BUILDS"}) { 384*5f9b6cedSSteven Rostedt reboot; 385*5f9b6cedSSteven Rostedt doprint "Sleeping $opt{SLEEP_TIME} seconds\n"; 386*5f9b6cedSSteven Rostedt sleep "$opt{SLEEP_TIME}"; 387*5f9b6cedSSteven Rostedt } 388*5f9b6cedSSteven Rostedt} 389*5f9b6cedSSteven Rostedt 390*5f9b6cedSSteven Rostedtsub get_version { 391*5f9b6cedSSteven Rostedt # get the release name 392*5f9b6cedSSteven Rostedt doprint "$make kernelrelease ... "; 393*5f9b6cedSSteven Rostedt $version = `$make kernelrelease | tail -1`; 394*5f9b6cedSSteven Rostedt chomp($version); 395*5f9b6cedSSteven Rostedt doprint "$version\n"; 396*5f9b6cedSSteven Rostedt} 397*5f9b6cedSSteven Rostedt 398*5f9b6cedSSteven Rostedtsub run_bisect { 399*5f9b6cedSSteven Rostedt my ($type) = @_; 400*5f9b6cedSSteven Rostedt 401*5f9b6cedSSteven Rostedt my $failed; 402*5f9b6cedSSteven Rostedt my $result; 403*5f9b6cedSSteven Rostedt my $output; 404*5f9b6cedSSteven Rostedt my $ret; 405*5f9b6cedSSteven Rostedt 406*5f9b6cedSSteven Rostedt 407*5f9b6cedSSteven Rostedt if (defined($minconfig)) { 408*5f9b6cedSSteven Rostedt $failed = build "useconfig:$minconfig"; 409*5f9b6cedSSteven Rostedt } else { 410*5f9b6cedSSteven Rostedt # ?? no config to use? 411*5f9b6cedSSteven Rostedt $failed = build "oldconfig"; 412*5f9b6cedSSteven Rostedt } 413*5f9b6cedSSteven Rostedt 414*5f9b6cedSSteven Rostedt if ($type ne "build") { 415*5f9b6cedSSteven Rostedt dodie "Failed on build" if $failed; 416*5f9b6cedSSteven Rostedt 417*5f9b6cedSSteven Rostedt # Now boot the box 418*5f9b6cedSSteven Rostedt get_grub_index; 419*5f9b6cedSSteven Rostedt get_version; 420*5f9b6cedSSteven Rostedt install; 421*5f9b6cedSSteven Rostedt $failed = monitor; 422*5f9b6cedSSteven Rostedt 423*5f9b6cedSSteven Rostedt if ($type ne "boot") { 424*5f9b6cedSSteven Rostedt dodie "Failed on boot" if $failed; 425*5f9b6cedSSteven Rostedt } 426*5f9b6cedSSteven Rostedt } 427*5f9b6cedSSteven Rostedt 428*5f9b6cedSSteven Rostedt if ($failed) { 429*5f9b6cedSSteven Rostedt $result = "bad"; 430*5f9b6cedSSteven Rostedt } else { 431*5f9b6cedSSteven Rostedt $result = "good"; 432*5f9b6cedSSteven Rostedt } 433*5f9b6cedSSteven Rostedt 434*5f9b6cedSSteven Rostedt doprint "git bisect $result ... "; 435*5f9b6cedSSteven Rostedt $output = `git bisect $result 2>&1`; 436*5f9b6cedSSteven Rostedt $ret = $?; 437*5f9b6cedSSteven Rostedt 438*5f9b6cedSSteven Rostedt logit $output; 439*5f9b6cedSSteven Rostedt 440*5f9b6cedSSteven Rostedt if ($ret) { 441*5f9b6cedSSteven Rostedt doprint "FAILED\n"; 442*5f9b6cedSSteven Rostedt dodie "Failed to git bisect"; 443*5f9b6cedSSteven Rostedt } 444*5f9b6cedSSteven Rostedt 445*5f9b6cedSSteven Rostedt doprint "SUCCESS\n"; 446*5f9b6cedSSteven Rostedt if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\)) \[([[:xdigit:]]+)\]/) { 447*5f9b6cedSSteven Rostedt doprint "$1 [$2]\n"; 448*5f9b6cedSSteven Rostedt } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 449*5f9b6cedSSteven Rostedt $bisect_bad = $1; 450*5f9b6cedSSteven Rostedt doprint "Found bad commit... $1\n"; 451*5f9b6cedSSteven Rostedt return 0; 452*5f9b6cedSSteven Rostedt } 453*5f9b6cedSSteven Rostedt 454*5f9b6cedSSteven Rostedt 455*5f9b6cedSSteven Rostedt return 1; 456*5f9b6cedSSteven Rostedt} 457*5f9b6cedSSteven Rostedt 458*5f9b6cedSSteven Rostedtsub bisect { 459*5f9b6cedSSteven Rostedt my ($i) = @_; 460*5f9b6cedSSteven Rostedt 461*5f9b6cedSSteven Rostedt my $result; 462*5f9b6cedSSteven Rostedt 463*5f9b6cedSSteven Rostedt die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 464*5f9b6cedSSteven Rostedt die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 465*5f9b6cedSSteven Rostedt die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 466*5f9b6cedSSteven Rostedt 467*5f9b6cedSSteven Rostedt my $good = $opt{"BISECT_GOOD[$i]"}; 468*5f9b6cedSSteven Rostedt my $bad = $opt{"BISECT_BAD[$i]"}; 469*5f9b6cedSSteven Rostedt my $type = $opt{"BISECT_TYPE[$i]"}; 470*5f9b6cedSSteven Rostedt 471*5f9b6cedSSteven Rostedt $in_bisect = 1; 472*5f9b6cedSSteven Rostedt 473*5f9b6cedSSteven Rostedt run_command "git bisect start" or 474*5f9b6cedSSteven Rostedt dodie "could not start bisect"; 475*5f9b6cedSSteven Rostedt 476*5f9b6cedSSteven Rostedt run_command "git bisect good $good" or 477*5f9b6cedSSteven Rostedt dodie "could not set bisect good to $good"; 478*5f9b6cedSSteven Rostedt 479*5f9b6cedSSteven Rostedt run_command "git bisect bad $bad" or 480*5f9b6cedSSteven Rostedt dodie "could not set bisect good to $bad"; 481*5f9b6cedSSteven Rostedt 482*5f9b6cedSSteven Rostedt do { 483*5f9b6cedSSteven Rostedt $result = run_bisect $type; 484*5f9b6cedSSteven Rostedt } while ($result); 485*5f9b6cedSSteven Rostedt 486*5f9b6cedSSteven Rostedt run_command "git bisect log" or 487*5f9b6cedSSteven Rostedt dodie "could not capture git bisect log"; 488*5f9b6cedSSteven Rostedt 489*5f9b6cedSSteven Rostedt run_command "git bisect reset" or 490*5f9b6cedSSteven Rostedt dodie "could not reset git bisect"; 491*5f9b6cedSSteven Rostedt 492*5f9b6cedSSteven Rostedt doprint "Bad commit was [$bisect_bad]\n"; 493*5f9b6cedSSteven Rostedt 494*5f9b6cedSSteven Rostedt $in_bisect = 0; 495*5f9b6cedSSteven Rostedt 496*5f9b6cedSSteven Rostedt success $i; 497*5f9b6cedSSteven Rostedt} 498*5f9b6cedSSteven Rostedt 4992545eb61SSteven Rostedtread_config $ARGV[0]; 5002545eb61SSteven Rostedt 5012545eb61SSteven Rostedt# mandatory configs 5022545eb61SSteven Rostedtdie "MACHINE not defined\n" if (!defined($opt{"MACHINE"})); 5032545eb61SSteven Rostedtdie "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"})); 5042545eb61SSteven Rostedtdie "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"})); 5052545eb61SSteven Rostedtdie "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"})); 5062545eb61SSteven Rostedtdie "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"})); 50775c3fda7SSteven Rostedtdie "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"})); 5082545eb61SSteven Rostedtdie "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"})); 5092545eb61SSteven Rostedtdie "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"})); 5102545eb61SSteven Rostedtdie "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"})); 5112545eb61SSteven Rostedtdie "GRUB_MENU not defined\n" if (!defined($opt{"GRUB_MENU"})); 5122545eb61SSteven Rostedt 5132545eb61SSteven Rostedtchdir $opt{"BUILD_DIR"} || die "can't change directory to $opt{BUILD_DIR}"; 5142545eb61SSteven Rostedt 5152545eb61SSteven Rostedt$target = "$opt{SSH_USER}\@$opt{MACHINE}"; 5162545eb61SSteven Rostedt 5172545eb61SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n"; 5182545eb61SSteven Rostedt 5192545eb61SSteven Rostedt 5202545eb61SSteven Rostedt$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}"; 5212545eb61SSteven Rostedt 5222545eb61SSteven Rostedt# First we need to do is the builds 5232545eb61SSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) { 5242545eb61SSteven Rostedt my $type = "BUILD_TYPE[$i]"; 5252545eb61SSteven Rostedt 5265c42fc5bSSteven Rostedt if (defined($opt{"BUILD_NOCLEAN[$i]"}) && 5275c42fc5bSSteven Rostedt $opt{"BUILD_NOCLEAN[$i]"} != 0) { 5285c42fc5bSSteven Rostedt $noclean = 1; 5295c42fc5bSSteven Rostedt } else { 5305c42fc5bSSteven Rostedt $noclean = $opt{"BUILD_NOCLEAN"}; 5315c42fc5bSSteven Rostedt } 5325c42fc5bSSteven Rostedt 533*5f9b6cedSSteven Rostedt if (defined($opt{"MIN_CONFIG[$i]"})) { 534*5f9b6cedSSteven Rostedt $minconfig = $opt{"MIN_CONFIG[$i]"}; 535*5f9b6cedSSteven Rostedt } elsif (defined($opt{"MIN_CONFIG"})) { 536*5f9b6cedSSteven Rostedt $minconfig = $opt{"MIN_CONFIG"}; 537*5f9b6cedSSteven Rostedt } else { 538*5f9b6cedSSteven Rostedt undef $minconfig; 539*5f9b6cedSSteven Rostedt } 540*5f9b6cedSSteven Rostedt 5412545eb61SSteven Rostedt if (!defined($opt{$type})) { 5422545eb61SSteven Rostedt $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"}; 5432545eb61SSteven Rostedt } 5442545eb61SSteven Rostedt 5452545eb61SSteven Rostedt doprint "\n\n"; 5462545eb61SSteven Rostedt doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n"; 5472545eb61SSteven Rostedt 548*5f9b6cedSSteven Rostedt if ($opt{$type} eq "bisect") { 549*5f9b6cedSSteven Rostedt bisect $i; 550*5f9b6cedSSteven Rostedt next; 551*5f9b6cedSSteven Rostedt } 552*5f9b6cedSSteven Rostedt 5532545eb61SSteven Rostedt if ($opt{$type} ne "nobuild") { 5545c42fc5bSSteven Rostedt build $opt{$type}; 5552545eb61SSteven Rostedt } 5562545eb61SSteven Rostedt 557*5f9b6cedSSteven Rostedt get_grub_index; 558*5f9b6cedSSteven Rostedt get_version; 5592545eb61SSteven Rostedt install; 5602545eb61SSteven Rostedt monitor; 561*5f9b6cedSSteven Rostedt success $i; 56275c3fda7SSteven Rostedt} 5632545eb61SSteven Rostedt 5645c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) { 56575c3fda7SSteven Rostedt halt; 56675c3fda7SSteven Rostedt} else { 56775c3fda7SSteven Rostedt reboot; 5685c42fc5bSSteven Rostedt} 56975c3fda7SSteven Rostedt 5702545eb61SSteven Rostedtexit 0; 571