12545eb61SSteven Rostedt#!/usr/bin/perl -w 2d6ce2a0bSSteven Rostedt# 3d6ce2a0bSSteven Rostedt# Copywrite 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. 4d6ce2a0bSSteven Rostedt# Licensed under the terms of the GNU GPL License version 2 5d6ce2a0bSSteven Rostedt# 62545eb61SSteven Rostedt 72545eb61SSteven Rostedtuse strict; 82545eb61SSteven Rostedtuse IPC::Open2; 92545eb61SSteven Rostedtuse Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); 107faafbd6SSteven Rostedtuse File::Path qw(mkpath); 117faafbd6SSteven Rostedtuse File::Copy qw(cp); 122545eb61SSteven Rostedtuse FileHandle; 132545eb61SSteven Rostedt 142545eb61SSteven Rostedt$#ARGV >= 0 || die "usage: autotest.pl config-file\n"; 152545eb61SSteven Rostedt 162545eb61SSteven Rostedt$| = 1; 172545eb61SSteven Rostedt 182545eb61SSteven Rostedtmy %opt; 19*a75fececSSteven Rostedtmy %default; 202545eb61SSteven Rostedt 212545eb61SSteven Rostedt#default opts 22*a75fececSSteven Rostedt$default{"NUM_TESTS"} = 5; 23*a75fececSSteven Rostedt$default{"REBOOT_TYPE"} = "grub"; 24*a75fececSSteven Rostedt$default{"TEST_TYPE"} = "test"; 25*a75fececSSteven Rostedt$default{"BUILD_TYPE"} = "randconfig"; 26*a75fececSSteven Rostedt$default{"MAKE_CMD"} = "make"; 27*a75fececSSteven Rostedt$default{"TIMEOUT"} = 120; 28*a75fececSSteven Rostedt$default{"TMP_DIR"} = "/tmp/autotest"; 29*a75fececSSteven Rostedt$default{"SLEEP_TIME"} = 60; # sleep time between tests 30*a75fececSSteven Rostedt$default{"BUILD_NOCLEAN"} = 0; 31*a75fececSSteven Rostedt$default{"REBOOT_ON_ERROR"} = 0; 32*a75fececSSteven Rostedt$default{"POWEROFF_ON_ERROR"} = 0; 33*a75fececSSteven Rostedt$default{"REBOOT_ON_SUCCESS"} = 1; 34*a75fececSSteven Rostedt$default{"POWEROFF_ON_SUCCESS"} = 0; 35*a75fececSSteven Rostedt$default{"BUILD_OPTIONS"} = ""; 36*a75fececSSteven Rostedt$default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects 37*a75fececSSteven Rostedt$default{"CLEAR_LOG"} = 0; 38*a75fececSSteven Rostedt$default{"SUCCESS_LINE"} = "login:"; 39*a75fececSSteven Rostedt$default{"BOOTED_TIMEOUT"} = 1; 40*a75fececSSteven Rostedt$default{"DIE_ON_FAILURE"} = 1; 412545eb61SSteven Rostedt 422545eb61SSteven Rostedtmy $version; 43*a75fececSSteven Rostedtmy $machine; 44*a75fececSSteven Rostedtmy $tmpdir; 45*a75fececSSteven Rostedtmy $builddir; 46*a75fececSSteven Rostedtmy $outputdir; 47*a75fececSSteven Rostedtmy $test_type; 487faafbd6SSteven Rostedtmy $build_type; 49*a75fececSSteven Rostedtmy $build_options; 50*a75fececSSteven Rostedtmy $reboot_type; 51*a75fececSSteven Rostedtmy $reboot_script; 52*a75fececSSteven Rostedtmy $power_cycle; 53*a75fececSSteven Rostedtmy $reboot_on_error; 54*a75fececSSteven Rostedtmy $poweroff_on_error; 55*a75fececSSteven Rostedtmy $die_on_failure; 56*a75fececSSteven Rostedtmy $power_off; 57*a75fececSSteven Rostedtmy $grub_menu; 582545eb61SSteven Rostedtmy $grub_number; 592545eb61SSteven Rostedtmy $target; 602545eb61SSteven Rostedtmy $make; 615c42fc5bSSteven Rostedtmy $noclean; 625f9b6cedSSteven Rostedtmy $minconfig; 632b7d9b21SSteven Rostedtmy $addconfig; 645f9b6cedSSteven Rostedtmy $in_bisect = 0; 655f9b6cedSSteven Rostedtmy $bisect_bad = ""; 66d6ce2a0bSSteven Rostedtmy $reverse_bisect; 676c5ee0beSSteven Rostedtmy $in_patchcheck = 0; 685a391fbfSSteven Rostedtmy $run_test; 696c5ee0beSSteven Rostedtmy $redirect; 707faafbd6SSteven Rostedtmy $buildlog; 717faafbd6SSteven Rostedtmy $dmesg; 727faafbd6SSteven Rostedtmy $monitor_fp; 737faafbd6SSteven Rostedtmy $monitor_pid; 747faafbd6SSteven Rostedtmy $monitor_cnt = 0; 75*a75fececSSteven Rostedtmy $sleep_time; 76*a75fececSSteven Rostedtmy $bisect_sleep_time; 77*a75fececSSteven Rostedtmy $store_failures; 78*a75fececSSteven Rostedtmy $timeout; 79*a75fececSSteven Rostedtmy $booted_timeout; 80*a75fececSSteven Rostedtmy $console; 81*a75fececSSteven Rostedtmy $success_line; 82*a75fececSSteven Rostedtmy $build_target; 83*a75fececSSteven Rostedtmy $target_image; 84*a75fececSSteven Rostedtmy $localversion; 852545eb61SSteven Rostedt 862545eb61SSteven Rostedtsub read_config { 872545eb61SSteven Rostedt my ($config) = @_; 882545eb61SSteven Rostedt 892545eb61SSteven Rostedt open(IN, $config) || die "can't read file $config"; 902545eb61SSteven Rostedt 912545eb61SSteven Rostedt while (<IN>) { 922545eb61SSteven Rostedt 932545eb61SSteven Rostedt # ignore blank lines and comments 942545eb61SSteven Rostedt next if (/^\s*$/ || /\s*\#/); 952545eb61SSteven Rostedt 962545eb61SSteven Rostedt if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) { 972545eb61SSteven Rostedt my $lvalue = $1; 982545eb61SSteven Rostedt my $rvalue = $2; 992545eb61SSteven Rostedt 100*a75fececSSteven Rostedt if (defined($opt{$lvalue})) { 101*a75fececSSteven Rostedt die "Error: Option $lvalue defined more than once!\n"; 102*a75fececSSteven Rostedt } 1032545eb61SSteven Rostedt $opt{$lvalue} = $rvalue; 1042545eb61SSteven Rostedt } 1052545eb61SSteven Rostedt } 1062545eb61SSteven Rostedt 1072545eb61SSteven Rostedt close(IN); 108*a75fececSSteven Rostedt 109*a75fececSSteven Rostedt # set any defaults 110*a75fececSSteven Rostedt 111*a75fececSSteven Rostedt foreach my $default (keys %default) { 112*a75fececSSteven Rostedt if (!defined($opt{$default})) { 113*a75fececSSteven Rostedt $opt{$default} = $default{$default}; 114*a75fececSSteven Rostedt } 115*a75fececSSteven Rostedt } 1162545eb61SSteven Rostedt} 1172545eb61SSteven Rostedt 1185f9b6cedSSteven Rostedtsub logit { 1192545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 1202545eb61SSteven Rostedt open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 1212545eb61SSteven Rostedt print OUT @_; 1222545eb61SSteven Rostedt close(OUT); 1232545eb61SSteven Rostedt } 1242545eb61SSteven Rostedt} 1252545eb61SSteven Rostedt 1265f9b6cedSSteven Rostedtsub doprint { 1275f9b6cedSSteven Rostedt print @_; 1285f9b6cedSSteven Rostedt logit @_; 1295f9b6cedSSteven Rostedt} 1305f9b6cedSSteven Rostedt 1317faafbd6SSteven Rostedtsub run_command; 1327faafbd6SSteven Rostedt 1337faafbd6SSteven Rostedtsub reboot { 1347faafbd6SSteven Rostedt # try to reboot normally 1357faafbd6SSteven Rostedt if (!run_command "ssh $target reboot") { 1367faafbd6SSteven Rostedt # nope? power cycle it. 137*a75fececSSteven Rostedt run_command "$power_cycle"; 1387faafbd6SSteven Rostedt } 1397faafbd6SSteven Rostedt} 1407faafbd6SSteven Rostedt 1415c42fc5bSSteven Rostedtsub dodie { 1425a391fbfSSteven Rostedt doprint "CRITICAL FAILURE... ", @_, "\n"; 1435c42fc5bSSteven Rostedt 144*a75fececSSteven Rostedt if ($reboot_on_error && $test_type ne "build") { 14575c3fda7SSteven Rostedt doprint "REBOOTING\n"; 1467faafbd6SSteven Rostedt reboot; 14775c3fda7SSteven Rostedt 148*a75fececSSteven Rostedt } elsif ($poweroff_on_error && defined($power_off)) { 1495c42fc5bSSteven Rostedt doprint "POWERING OFF\n"; 150*a75fececSSteven Rostedt `$power_off`; 1515c42fc5bSSteven Rostedt } 15275c3fda7SSteven Rostedt 1535c42fc5bSSteven Rostedt die @_; 1545c42fc5bSSteven Rostedt} 1555c42fc5bSSteven Rostedt 1567faafbd6SSteven Rostedtsub open_console { 1577faafbd6SSteven Rostedt my ($fp) = @_; 1587faafbd6SSteven Rostedt 1597faafbd6SSteven Rostedt my $flags; 1607faafbd6SSteven Rostedt 161*a75fececSSteven Rostedt my $pid = open($fp, "$console|") or 162*a75fececSSteven Rostedt dodie "Can't open console $console"; 1637faafbd6SSteven Rostedt 1647faafbd6SSteven Rostedt $flags = fcntl($fp, F_GETFL, 0) or 1657faafbd6SSteven Rostedt dodie "Can't get flags for the socket: $!\n"; 1667faafbd6SSteven Rostedt $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 1677faafbd6SSteven Rostedt dodie "Can't set flags for the socket: $!\n"; 1687faafbd6SSteven Rostedt 1697faafbd6SSteven Rostedt return $pid; 1707faafbd6SSteven Rostedt} 1717faafbd6SSteven Rostedt 1727faafbd6SSteven Rostedtsub close_console { 1737faafbd6SSteven Rostedt my ($fp, $pid) = @_; 1747faafbd6SSteven Rostedt 1757faafbd6SSteven Rostedt doprint "kill child process $pid\n"; 1767faafbd6SSteven Rostedt kill 2, $pid; 1777faafbd6SSteven Rostedt 1787faafbd6SSteven Rostedt print "closing!\n"; 1797faafbd6SSteven Rostedt close($fp); 1807faafbd6SSteven Rostedt} 1817faafbd6SSteven Rostedt 1827faafbd6SSteven Rostedtsub start_monitor { 1837faafbd6SSteven Rostedt if ($monitor_cnt++) { 1847faafbd6SSteven Rostedt return; 1857faafbd6SSteven Rostedt } 1867faafbd6SSteven Rostedt $monitor_fp = \*MONFD; 1877faafbd6SSteven Rostedt $monitor_pid = open_console $monitor_fp; 188*a75fececSSteven Rostedt 189*a75fececSSteven Rostedt return; 190*a75fececSSteven Rostedt 191*a75fececSSteven Rostedt open(MONFD, "Stop perl from warning about single use of MONFD"); 1927faafbd6SSteven Rostedt} 1937faafbd6SSteven Rostedt 1947faafbd6SSteven Rostedtsub end_monitor { 1957faafbd6SSteven Rostedt if (--$monitor_cnt) { 1967faafbd6SSteven Rostedt return; 1977faafbd6SSteven Rostedt } 1987faafbd6SSteven Rostedt close_console($monitor_fp, $monitor_pid); 1997faafbd6SSteven Rostedt} 2007faafbd6SSteven Rostedt 2017faafbd6SSteven Rostedtsub wait_for_monitor { 2027faafbd6SSteven Rostedt my ($time) = @_; 2037faafbd6SSteven Rostedt my $line; 2047faafbd6SSteven Rostedt 205*a75fececSSteven Rostedt doprint "** Wait for monitor to settle down **\n"; 2067faafbd6SSteven Rostedt 2077faafbd6SSteven Rostedt # read the monitor and wait for the system to calm down 2087faafbd6SSteven Rostedt do { 2097faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 210*a75fececSSteven Rostedt print "$line" if (defined($line)); 2117faafbd6SSteven Rostedt } while (defined($line)); 212*a75fececSSteven Rostedt print "** Monitor flushed **\n"; 2137faafbd6SSteven Rostedt} 2147faafbd6SSteven Rostedt 2152b7d9b21SSteven Rostedtsub fail { 2162b7d9b21SSteven Rostedt 217*a75fececSSteven Rostedt if ($die_on_failure) { 2182b7d9b21SSteven Rostedt dodie @_; 2192b7d9b21SSteven Rostedt } 2202b7d9b21SSteven Rostedt 221*a75fececSSteven Rostedt doprint "FAILED\n"; 2227faafbd6SSteven Rostedt 223*a75fececSSteven Rostedt # no need to reboot for just building. 224*a75fececSSteven Rostedt if ($test_type ne "build") { 2257faafbd6SSteven Rostedt doprint "REBOOTING\n"; 2267faafbd6SSteven Rostedt reboot; 2277faafbd6SSteven Rostedt start_monitor; 228*a75fececSSteven Rostedt wait_for_monitor $sleep_time; 2297faafbd6SSteven Rostedt end_monitor; 230*a75fececSSteven Rostedt } 2317faafbd6SSteven Rostedt 232*a75fececSSteven Rostedt doprint "**** Failed: ", @_, " ****\n"; 233*a75fececSSteven Rostedt 234*a75fececSSteven Rostedt return 1 if (!defined($store_failures)); 2357faafbd6SSteven Rostedt 2367faafbd6SSteven Rostedt my @t = localtime; 2377faafbd6SSteven Rostedt my $date = sprintf "%04d%02d%02d%02d%02d%02d", 2387faafbd6SSteven Rostedt 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 2397faafbd6SSteven Rostedt 240*a75fececSSteven Rostedt my $dir = "$machine-$test_type-$build_type-fail-$date"; 241*a75fececSSteven Rostedt my $faildir = "$store_failures/$dir"; 2427faafbd6SSteven Rostedt 2437faafbd6SSteven Rostedt if (!-d $faildir) { 2447faafbd6SSteven Rostedt mkpath($faildir) or 245*a75fececSSteven Rostedt die "can't create $faildir"; 2467faafbd6SSteven Rostedt } 247*a75fececSSteven Rostedt if (-f "$outputdir/.config") { 248*a75fececSSteven Rostedt cp "$outputdir/.config", "$faildir/config" or 2497faafbd6SSteven Rostedt die "failed to copy .config"; 2507faafbd6SSteven Rostedt } 2517faafbd6SSteven Rostedt if (-f $buildlog) { 2527faafbd6SSteven Rostedt cp $buildlog, "$faildir/buildlog" or 2537faafbd6SSteven Rostedt die "failed to move $buildlog"; 2547faafbd6SSteven Rostedt } 2557faafbd6SSteven Rostedt if (-f $dmesg) { 2567faafbd6SSteven Rostedt cp $dmesg, "$faildir/dmesg" or 2577faafbd6SSteven Rostedt die "failed to move $dmesg"; 2587faafbd6SSteven Rostedt } 2597faafbd6SSteven Rostedt 2607faafbd6SSteven Rostedt doprint "*** Saved info to $faildir ***\n"; 2617faafbd6SSteven Rostedt 2622b7d9b21SSteven Rostedt return 1; 2632b7d9b21SSteven Rostedt} 2642b7d9b21SSteven Rostedt 2652545eb61SSteven Rostedtsub run_command { 2662545eb61SSteven Rostedt my ($command) = @_; 267d6ce2a0bSSteven Rostedt my $dolog = 0; 268d6ce2a0bSSteven Rostedt my $dord = 0; 269d6ce2a0bSSteven Rostedt my $pid; 270d6ce2a0bSSteven Rostedt 271d6ce2a0bSSteven Rostedt doprint("$command ... "); 272d6ce2a0bSSteven Rostedt 273d6ce2a0bSSteven Rostedt $pid = open(CMD, "$command 2>&1 |") or 2742b7d9b21SSteven Rostedt (fail "unable to exec $command" and return 0); 2752545eb61SSteven Rostedt 2762545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 277d6ce2a0bSSteven Rostedt open(LOG, ">>$opt{LOG_FILE}") or 278d6ce2a0bSSteven Rostedt dodie "failed to write to log"; 279d6ce2a0bSSteven Rostedt $dolog = 1; 2806c5ee0beSSteven Rostedt } 2816c5ee0beSSteven Rostedt 2826c5ee0beSSteven Rostedt if (defined($redirect)) { 283d6ce2a0bSSteven Rostedt open (RD, ">$redirect") or 284d6ce2a0bSSteven Rostedt dodie "failed to write to redirect $redirect"; 285d6ce2a0bSSteven Rostedt $dord = 1; 2862545eb61SSteven Rostedt } 2872545eb61SSteven Rostedt 288d6ce2a0bSSteven Rostedt while (<CMD>) { 289d6ce2a0bSSteven Rostedt print LOG if ($dolog); 290d6ce2a0bSSteven Rostedt print RD if ($dord); 291d6ce2a0bSSteven Rostedt } 2922545eb61SSteven Rostedt 293d6ce2a0bSSteven Rostedt waitpid($pid, 0); 2942545eb61SSteven Rostedt my $failed = $?; 2952545eb61SSteven Rostedt 296d6ce2a0bSSteven Rostedt close(CMD); 297d6ce2a0bSSteven Rostedt close(LOG) if ($dolog); 298d6ce2a0bSSteven Rostedt close(RD) if ($dord); 299d6ce2a0bSSteven Rostedt 3002545eb61SSteven Rostedt if ($failed) { 3012545eb61SSteven Rostedt doprint "FAILED!\n"; 3022545eb61SSteven Rostedt } else { 3032545eb61SSteven Rostedt doprint "SUCCESS\n"; 3042545eb61SSteven Rostedt } 3052545eb61SSteven Rostedt 3065f9b6cedSSteven Rostedt return !$failed; 3075f9b6cedSSteven Rostedt} 3085f9b6cedSSteven Rostedt 3095f9b6cedSSteven Rostedtsub get_grub_index { 3105f9b6cedSSteven Rostedt 311*a75fececSSteven Rostedt if ($reboot_type ne "grub") { 312*a75fececSSteven Rostedt return; 313*a75fececSSteven Rostedt } 3145a391fbfSSteven Rostedt return if (defined($grub_number)); 3155f9b6cedSSteven Rostedt 3165f9b6cedSSteven Rostedt doprint "Find grub menu ... "; 3175f9b6cedSSteven Rostedt $grub_number = -1; 3185f9b6cedSSteven Rostedt open(IN, "ssh $target cat /boot/grub/menu.lst |") 3195f9b6cedSSteven Rostedt or die "unable to get menu.lst"; 3205f9b6cedSSteven Rostedt while (<IN>) { 321*a75fececSSteven Rostedt if (/^\s*title\s+$grub_menu\s*$/) { 3225f9b6cedSSteven Rostedt $grub_number++; 3235f9b6cedSSteven Rostedt last; 3245f9b6cedSSteven Rostedt } elsif (/^\s*title\s/) { 3255f9b6cedSSteven Rostedt $grub_number++; 3265f9b6cedSSteven Rostedt } 3275f9b6cedSSteven Rostedt } 3285f9b6cedSSteven Rostedt close(IN); 3295f9b6cedSSteven Rostedt 330*a75fececSSteven Rostedt die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 3315f9b6cedSSteven Rostedt if ($grub_number < 0); 3325f9b6cedSSteven Rostedt doprint "$grub_number\n"; 3332545eb61SSteven Rostedt} 3342545eb61SSteven Rostedt 3352545eb61SSteven Rostedtsub wait_for_input 3362545eb61SSteven Rostedt{ 3372545eb61SSteven Rostedt my ($fp, $time) = @_; 3382545eb61SSteven Rostedt my $rin; 3392545eb61SSteven Rostedt my $ready; 3402545eb61SSteven Rostedt my $line; 3412545eb61SSteven Rostedt my $ch; 3422545eb61SSteven Rostedt 3432545eb61SSteven Rostedt if (!defined($time)) { 3442545eb61SSteven Rostedt $time = $timeout; 3452545eb61SSteven Rostedt } 3462545eb61SSteven Rostedt 3472545eb61SSteven Rostedt $rin = ''; 3482545eb61SSteven Rostedt vec($rin, fileno($fp), 1) = 1; 3492545eb61SSteven Rostedt $ready = select($rin, undef, undef, $time); 3502545eb61SSteven Rostedt 3512545eb61SSteven Rostedt $line = ""; 3522545eb61SSteven Rostedt 3532545eb61SSteven Rostedt # try to read one char at a time 3542545eb61SSteven Rostedt while (sysread $fp, $ch, 1) { 3552545eb61SSteven Rostedt $line .= $ch; 3562545eb61SSteven Rostedt last if ($ch eq "\n"); 3572545eb61SSteven Rostedt } 3582545eb61SSteven Rostedt 3592545eb61SSteven Rostedt if (!length($line)) { 3602545eb61SSteven Rostedt return undef; 3612545eb61SSteven Rostedt } 3622545eb61SSteven Rostedt 3632545eb61SSteven Rostedt return $line; 3642545eb61SSteven Rostedt} 3652545eb61SSteven Rostedt 36675c3fda7SSteven Rostedtsub reboot_to { 367*a75fececSSteven Rostedt if ($reboot_type eq "grub") { 3682545eb61SSteven Rostedt run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; 369*a75fececSSteven Rostedt return; 370*a75fececSSteven Rostedt } 371*a75fececSSteven Rostedt 372*a75fececSSteven Rostedt run_command "$reboot_script"; 3732545eb61SSteven Rostedt} 3742545eb61SSteven Rostedt 3755a391fbfSSteven Rostedtsub monitor { 3762545eb61SSteven Rostedt my $booted = 0; 3772545eb61SSteven Rostedt my $bug = 0; 3785c42fc5bSSteven Rostedt my $skip_call_trace = 0; 3792b7d9b21SSteven Rostedt my $loops; 3802545eb61SSteven Rostedt 3817faafbd6SSteven Rostedt wait_for_monitor 5; 3822545eb61SSteven Rostedt 3832545eb61SSteven Rostedt my $line; 3842545eb61SSteven Rostedt my $full_line = ""; 3852545eb61SSteven Rostedt 3867faafbd6SSteven Rostedt open(DMESG, "> $dmesg") or 3877faafbd6SSteven Rostedt die "unable to write to $dmesg"; 3882545eb61SSteven Rostedt 38975c3fda7SSteven Rostedt reboot_to; 3902545eb61SSteven Rostedt 3912545eb61SSteven Rostedt for (;;) { 3922545eb61SSteven Rostedt 3932b7d9b21SSteven Rostedt if ($booted) { 394*a75fececSSteven Rostedt $line = wait_for_input($monitor_fp, $booted_timeout); 3952b7d9b21SSteven Rostedt } else { 3967faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp); 3972b7d9b21SSteven Rostedt } 3982545eb61SSteven Rostedt 3992545eb61SSteven Rostedt last if (!defined($line)); 4002545eb61SSteven Rostedt 4012545eb61SSteven Rostedt doprint $line; 4027faafbd6SSteven Rostedt print DMESG $line; 4032545eb61SSteven Rostedt 4042545eb61SSteven Rostedt # we are not guaranteed to get a full line 4052545eb61SSteven Rostedt $full_line .= $line; 4062545eb61SSteven Rostedt 407*a75fececSSteven Rostedt if ($full_line =~ /$success_line/) { 4082545eb61SSteven Rostedt $booted = 1; 4092545eb61SSteven Rostedt } 4102545eb61SSteven Rostedt 4115c42fc5bSSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 4125c42fc5bSSteven Rostedt $skip_call_trace = 1; 4135c42fc5bSSteven Rostedt } 4145c42fc5bSSteven Rostedt 4152545eb61SSteven Rostedt if ($full_line =~ /call trace:/i) { 4165c42fc5bSSteven Rostedt $bug = 1 if (!$skip_call_trace); 4175c42fc5bSSteven Rostedt } 4185c42fc5bSSteven Rostedt 4195c42fc5bSSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 4205c42fc5bSSteven Rostedt $skip_call_trace = 0; 4215c42fc5bSSteven Rostedt } 4225c42fc5bSSteven Rostedt 4235c42fc5bSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 4242545eb61SSteven Rostedt $bug = 1; 4252545eb61SSteven Rostedt } 4262545eb61SSteven Rostedt 4272545eb61SSteven Rostedt if ($line =~ /\n/) { 4282545eb61SSteven Rostedt $full_line = ""; 4292545eb61SSteven Rostedt } 4302545eb61SSteven Rostedt } 4312545eb61SSteven Rostedt 4327faafbd6SSteven Rostedt close(DMESG); 4332545eb61SSteven Rostedt 4342545eb61SSteven Rostedt if ($bug) { 4352b7d9b21SSteven Rostedt return 0 if ($in_bisect); 4362b7d9b21SSteven Rostedt fail "failed - got a bug report\n" and return 0; 4372545eb61SSteven Rostedt } 4385f9b6cedSSteven Rostedt 439*a75fececSSteven Rostedt if (!$booted) { 440*a75fececSSteven Rostedt return 0 if ($in_bisect); 441*a75fececSSteven Rostedt fail "failed - never got a boot prompt.\n" and return 0; 442*a75fececSSteven Rostedt } 443*a75fececSSteven Rostedt 4442b7d9b21SSteven Rostedt return 1; 4452545eb61SSteven Rostedt} 4462545eb61SSteven Rostedt 4472545eb61SSteven Rostedtsub install { 4482545eb61SSteven Rostedt 449*a75fececSSteven Rostedt run_command "scp $outputdir/$build_target $target:$target_image" or 4505c42fc5bSSteven Rostedt dodie "failed to copy image"; 4515f9b6cedSSteven Rostedt 4525f9b6cedSSteven Rostedt my $install_mods = 0; 4535f9b6cedSSteven Rostedt 4545f9b6cedSSteven Rostedt # should we process modules? 4555f9b6cedSSteven Rostedt $install_mods = 0; 456*a75fececSSteven Rostedt open(IN, "$outputdir/.config") or dodie("Can't read config file"); 4575f9b6cedSSteven Rostedt while (<IN>) { 4585f9b6cedSSteven Rostedt if (/CONFIG_MODULES(=y)?/) { 4595f9b6cedSSteven Rostedt $install_mods = 1 if (defined($1)); 4605f9b6cedSSteven Rostedt last; 4615f9b6cedSSteven Rostedt } 4625f9b6cedSSteven Rostedt } 4635f9b6cedSSteven Rostedt close(IN); 4645f9b6cedSSteven Rostedt 4655f9b6cedSSteven Rostedt if (!$install_mods) { 4665f9b6cedSSteven Rostedt doprint "No modules needed\n"; 4675f9b6cedSSteven Rostedt return; 4682545eb61SSteven Rostedt } 4692545eb61SSteven Rostedt 470*a75fececSSteven Rostedt run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or 4715f9b6cedSSteven Rostedt dodie "Failed to install modules"; 4725f9b6cedSSteven Rostedt 4732545eb61SSteven Rostedt my $modlib = "/lib/modules/$version"; 4745c42fc5bSSteven Rostedt my $modtar = "autotest-mods.tar.bz2"; 4752545eb61SSteven Rostedt 4765f9b6cedSSteven Rostedt run_command "ssh $target rm -rf $modlib" or 4775c42fc5bSSteven Rostedt dodie "failed to remove old mods: $modlib"; 4782545eb61SSteven Rostedt 4795c42fc5bSSteven Rostedt # would be nice if scp -r did not follow symbolic links 480*a75fececSSteven Rostedt run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 4815c42fc5bSSteven Rostedt dodie "making tarball"; 4825c42fc5bSSteven Rostedt 483*a75fececSSteven Rostedt run_command "scp $tmpdir/$modtar $target:/tmp" or 4845c42fc5bSSteven Rostedt dodie "failed to copy modules"; 4855c42fc5bSSteven Rostedt 486*a75fececSSteven Rostedt unlink "$tmpdir/$modtar"; 4875c42fc5bSSteven Rostedt 4885f9b6cedSSteven Rostedt run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or 4895c42fc5bSSteven Rostedt dodie "failed to tar modules"; 4905c42fc5bSSteven Rostedt 4915c42fc5bSSteven Rostedt run_command "ssh $target rm -f /tmp/$modtar"; 4922545eb61SSteven Rostedt} 4932545eb61SSteven Rostedt 4946c5ee0beSSteven Rostedtsub check_buildlog { 4956c5ee0beSSteven Rostedt my ($patch) = @_; 4966c5ee0beSSteven Rostedt 4976c5ee0beSSteven Rostedt my @files = `git show $patch | diffstat -l`; 4986c5ee0beSSteven Rostedt 4996c5ee0beSSteven Rostedt open(IN, "git show $patch |") or 5006c5ee0beSSteven Rostedt dodie "failed to show $patch"; 5016c5ee0beSSteven Rostedt while (<IN>) { 5026c5ee0beSSteven Rostedt if (m,^--- a/(.*),) { 5036c5ee0beSSteven Rostedt chomp $1; 5046c5ee0beSSteven Rostedt $files[$#files] = $1; 5056c5ee0beSSteven Rostedt } 5066c5ee0beSSteven Rostedt } 5076c5ee0beSSteven Rostedt close(IN); 5086c5ee0beSSteven Rostedt 5096c5ee0beSSteven Rostedt open(IN, $buildlog) or dodie "Can't open $buildlog"; 5106c5ee0beSSteven Rostedt while (<IN>) { 5116c5ee0beSSteven Rostedt if (/^\s*(.*?):.*(warning|error)/) { 5126c5ee0beSSteven Rostedt my $err = $1; 5136c5ee0beSSteven Rostedt foreach my $file (@files) { 514*a75fececSSteven Rostedt my $fullpath = "$builddir/$file"; 5156c5ee0beSSteven Rostedt if ($file eq $err || $fullpath eq $err) { 5162b7d9b21SSteven Rostedt fail "$file built with warnings" and return 0; 5176c5ee0beSSteven Rostedt } 5186c5ee0beSSteven Rostedt } 5196c5ee0beSSteven Rostedt } 5206c5ee0beSSteven Rostedt } 5216c5ee0beSSteven Rostedt close(IN); 5222b7d9b21SSteven Rostedt 5232b7d9b21SSteven Rostedt return 1; 5246c5ee0beSSteven Rostedt} 5256c5ee0beSSteven Rostedt 5262545eb61SSteven Rostedtsub build { 5272545eb61SSteven Rostedt my ($type) = @_; 5285c42fc5bSSteven Rostedt my $defconfig = ""; 5295c42fc5bSSteven Rostedt my $append = ""; 5302545eb61SSteven Rostedt 5317faafbd6SSteven Rostedt unlink $buildlog; 5327faafbd6SSteven Rostedt 53375c3fda7SSteven Rostedt if ($type =~ /^useconfig:(.*)/) { 534*a75fececSSteven Rostedt run_command "cp $1 $outputdir/.config" or 53575c3fda7SSteven Rostedt dodie "could not copy $1 to .config"; 5365f9b6cedSSteven Rostedt 53775c3fda7SSteven Rostedt $type = "oldconfig"; 53875c3fda7SSteven Rostedt } 53975c3fda7SSteven Rostedt 5405c42fc5bSSteven Rostedt # old config can ask questions 5415c42fc5bSSteven Rostedt if ($type eq "oldconfig") { 5425c42fc5bSSteven Rostedt $append = "yes ''|"; 54375c3fda7SSteven Rostedt 54475c3fda7SSteven Rostedt # allow for empty configs 545*a75fececSSteven Rostedt run_command "touch $outputdir/.config"; 54675c3fda7SSteven Rostedt 547*a75fececSSteven Rostedt run_command "mv $outputdir/.config $outputdir/config_temp" or 5485c42fc5bSSteven Rostedt dodie "moving .config"; 5495c42fc5bSSteven Rostedt 5505f9b6cedSSteven Rostedt if (!$noclean && !run_command "$make mrproper") { 5515c42fc5bSSteven Rostedt dodie "make mrproper"; 5525c42fc5bSSteven Rostedt } 5535c42fc5bSSteven Rostedt 554*a75fececSSteven Rostedt run_command "mv $outputdir/config_temp $outputdir/.config" or 5555c42fc5bSSteven Rostedt dodie "moving config_temp"; 5565c42fc5bSSteven Rostedt 5575c42fc5bSSteven Rostedt } elsif (!$noclean) { 558*a75fececSSteven Rostedt unlink "$outputdir/.config"; 5595f9b6cedSSteven Rostedt run_command "$make mrproper" or 5605c42fc5bSSteven Rostedt dodie "make mrproper"; 5615c42fc5bSSteven Rostedt } 5622545eb61SSteven Rostedt 5632545eb61SSteven Rostedt # add something to distinguish this build 564*a75fececSSteven Rostedt open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 565*a75fececSSteven Rostedt print OUT "$localversion\n"; 5662545eb61SSteven Rostedt close(OUT); 5672545eb61SSteven Rostedt 5685f9b6cedSSteven Rostedt if (defined($minconfig)) { 5695f9b6cedSSteven Rostedt $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; 5702545eb61SSteven Rostedt } 5712545eb61SSteven Rostedt 572*a75fececSSteven Rostedt run_command "$append $defconfig $make $type" or 5735c42fc5bSSteven Rostedt dodie "failed make config"; 5742545eb61SSteven Rostedt 575*a75fececSSteven Rostedt $redirect = "$buildlog"; 576*a75fececSSteven Rostedt if (!run_command "$make $build_options") { 5776c5ee0beSSteven Rostedt undef $redirect; 5785f9b6cedSSteven Rostedt # bisect may need this to pass 5792b7d9b21SSteven Rostedt return 0 if ($in_bisect); 5802b7d9b21SSteven Rostedt fail "failed build" and return 0; 5812545eb61SSteven Rostedt } 5826c5ee0beSSteven Rostedt undef $redirect; 5835f9b6cedSSteven Rostedt 5842b7d9b21SSteven Rostedt return 1; 5852545eb61SSteven Rostedt} 5862545eb61SSteven Rostedt 58775c3fda7SSteven Rostedtsub halt { 588*a75fececSSteven Rostedt if (!run_command "ssh $target halt" or defined($power_off)) { 58975c3fda7SSteven Rostedt # nope? the zap it! 590*a75fececSSteven Rostedt run_command "$power_off"; 59175c3fda7SSteven Rostedt } 59275c3fda7SSteven Rostedt} 59375c3fda7SSteven Rostedt 5945f9b6cedSSteven Rostedtsub success { 5955f9b6cedSSteven Rostedt my ($i) = @_; 5965f9b6cedSSteven Rostedt 5975f9b6cedSSteven Rostedt doprint "\n\n*******************************************\n"; 5985f9b6cedSSteven Rostedt doprint "*******************************************\n"; 599*a75fececSSteven Rostedt doprint "** TEST $i SUCCESS!!!! **\n"; 6005f9b6cedSSteven Rostedt doprint "*******************************************\n"; 6015f9b6cedSSteven Rostedt doprint "*******************************************\n"; 6025f9b6cedSSteven Rostedt 603*a75fececSSteven Rostedt if ($i != $opt{"NUM_TESTS"} && $test_type ne "build" && 604*a75fececSSteven Rostedt !($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") && 605*a75fececSSteven Rostedt !($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build")) { 606*a75fececSSteven Rostedt doprint "Reboot and wait $sleep_time seconds\n"; 6075f9b6cedSSteven Rostedt reboot; 6087faafbd6SSteven Rostedt start_monitor; 609*a75fececSSteven Rostedt wait_for_monitor $sleep_time; 6107faafbd6SSteven Rostedt end_monitor; 6115f9b6cedSSteven Rostedt } 6125f9b6cedSSteven Rostedt} 6135f9b6cedSSteven Rostedt 6145f9b6cedSSteven Rostedtsub get_version { 6155f9b6cedSSteven Rostedt # get the release name 6165f9b6cedSSteven Rostedt doprint "$make kernelrelease ... "; 6175f9b6cedSSteven Rostedt $version = `$make kernelrelease | tail -1`; 6185f9b6cedSSteven Rostedt chomp($version); 6195f9b6cedSSteven Rostedt doprint "$version\n"; 6205f9b6cedSSteven Rostedt} 6215f9b6cedSSteven Rostedt 6225a391fbfSSteven Rostedtsub child_run_test { 6237faafbd6SSteven Rostedt my $failed = 0; 6245a391fbfSSteven Rostedt 6257faafbd6SSteven Rostedt # child should have no power 626*a75fececSSteven Rostedt $reboot_on_error = 0; 627*a75fececSSteven Rostedt $poweroff_on_error = 0; 628*a75fececSSteven Rostedt $die_on_failure = 1; 6297faafbd6SSteven Rostedt 6307faafbd6SSteven Rostedt run_command $run_test or $failed = 1; 6315a391fbfSSteven Rostedt exit $failed; 6325a391fbfSSteven Rostedt} 6335a391fbfSSteven Rostedt 6345a391fbfSSteven Rostedtmy $child_done; 6355a391fbfSSteven Rostedt 6365a391fbfSSteven Rostedtsub child_finished { 6375a391fbfSSteven Rostedt $child_done = 1; 6385a391fbfSSteven Rostedt} 6395a391fbfSSteven Rostedt 6405a391fbfSSteven Rostedtsub do_run_test { 6415a391fbfSSteven Rostedt my $child_pid; 6425a391fbfSSteven Rostedt my $child_exit; 6435a391fbfSSteven Rostedt my $line; 6445a391fbfSSteven Rostedt my $full_line; 6455a391fbfSSteven Rostedt my $bug = 0; 6465a391fbfSSteven Rostedt 6477faafbd6SSteven Rostedt wait_for_monitor 1; 6485a391fbfSSteven Rostedt 6497faafbd6SSteven Rostedt doprint "run test $run_test\n"; 6505a391fbfSSteven Rostedt 6515a391fbfSSteven Rostedt $child_done = 0; 6525a391fbfSSteven Rostedt 6535a391fbfSSteven Rostedt $SIG{CHLD} = qw(child_finished); 6545a391fbfSSteven Rostedt 6555a391fbfSSteven Rostedt $child_pid = fork; 6565a391fbfSSteven Rostedt 6575a391fbfSSteven Rostedt child_run_test if (!$child_pid); 6585a391fbfSSteven Rostedt 6595a391fbfSSteven Rostedt $full_line = ""; 6605a391fbfSSteven Rostedt 6615a391fbfSSteven Rostedt do { 6627faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 6635a391fbfSSteven Rostedt if (defined($line)) { 6645a391fbfSSteven Rostedt 6655a391fbfSSteven Rostedt # we are not guaranteed to get a full line 6665a391fbfSSteven Rostedt $full_line .= $line; 6675a391fbfSSteven Rostedt 6685a391fbfSSteven Rostedt if ($full_line =~ /call trace:/i) { 6695a391fbfSSteven Rostedt $bug = 1; 6705a391fbfSSteven Rostedt } 6715a391fbfSSteven Rostedt 6725a391fbfSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 6735a391fbfSSteven Rostedt $bug = 1; 6745a391fbfSSteven Rostedt } 6755a391fbfSSteven Rostedt 6765a391fbfSSteven Rostedt if ($line =~ /\n/) { 6775a391fbfSSteven Rostedt $full_line = ""; 6785a391fbfSSteven Rostedt } 6795a391fbfSSteven Rostedt } 6805a391fbfSSteven Rostedt } while (!$child_done && !$bug); 6815a391fbfSSteven Rostedt 6825a391fbfSSteven Rostedt if ($bug) { 6835a391fbfSSteven Rostedt doprint "Detected kernel crash!\n"; 6845a391fbfSSteven Rostedt # kill the child with extreme prejudice 6855a391fbfSSteven Rostedt kill 9, $child_pid; 6865a391fbfSSteven Rostedt } 6875a391fbfSSteven Rostedt 6885a391fbfSSteven Rostedt waitpid $child_pid, 0; 6895a391fbfSSteven Rostedt $child_exit = $?; 6905a391fbfSSteven Rostedt 6915a391fbfSSteven Rostedt if ($bug || $child_exit) { 6922b7d9b21SSteven Rostedt return 0 if $in_bisect; 6932b7d9b21SSteven Rostedt fail "test failed" and return 0; 6945a391fbfSSteven Rostedt } 6952b7d9b21SSteven Rostedt return 1; 6965a391fbfSSteven Rostedt} 6975a391fbfSSteven Rostedt 698*a75fececSSteven Rostedtsub run_git_bisect { 699*a75fececSSteven Rostedt my ($command) = @_; 700*a75fececSSteven Rostedt 701*a75fececSSteven Rostedt doprint "$command ... "; 702*a75fececSSteven Rostedt 703*a75fececSSteven Rostedt my $output = `$command 2>&1`; 704*a75fececSSteven Rostedt my $ret = $?; 705*a75fececSSteven Rostedt 706*a75fececSSteven Rostedt logit $output; 707*a75fececSSteven Rostedt 708*a75fececSSteven Rostedt if ($ret) { 709*a75fececSSteven Rostedt doprint "FAILED\n"; 710*a75fececSSteven Rostedt dodie "Failed to git bisect"; 711*a75fececSSteven Rostedt } 712*a75fececSSteven Rostedt 713*a75fececSSteven Rostedt doprint "SUCCESS\n"; 714*a75fececSSteven Rostedt if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 715*a75fececSSteven Rostedt doprint "$1 [$2]\n"; 716*a75fececSSteven Rostedt } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 717*a75fececSSteven Rostedt $bisect_bad = $1; 718*a75fececSSteven Rostedt doprint "Found bad commit... $1\n"; 719*a75fececSSteven Rostedt return 0; 720*a75fececSSteven Rostedt } else { 721*a75fececSSteven Rostedt # we already logged it, just print it now. 722*a75fececSSteven Rostedt print $output; 723*a75fececSSteven Rostedt } 724*a75fececSSteven Rostedt 725*a75fececSSteven Rostedt return 1; 726*a75fececSSteven Rostedt} 727*a75fececSSteven Rostedt 7285f9b6cedSSteven Rostedtsub run_bisect { 7295f9b6cedSSteven Rostedt my ($type) = @_; 7305f9b6cedSSteven Rostedt 7312b7d9b21SSteven Rostedt my $failed = 0; 7325f9b6cedSSteven Rostedt my $result; 7335f9b6cedSSteven Rostedt my $output; 7345f9b6cedSSteven Rostedt my $ret; 7355f9b6cedSSteven Rostedt 7365f9b6cedSSteven Rostedt if (defined($minconfig)) { 7372b7d9b21SSteven Rostedt build "useconfig:$minconfig" or $failed = 1; 7385f9b6cedSSteven Rostedt } else { 7395f9b6cedSSteven Rostedt # ?? no config to use? 7402b7d9b21SSteven Rostedt build "oldconfig" or $failed = 1; 7415f9b6cedSSteven Rostedt } 7425f9b6cedSSteven Rostedt 7435f9b6cedSSteven Rostedt if ($type ne "build") { 7447faafbd6SSteven Rostedt dodie "Failed on build" if $failed; 7455f9b6cedSSteven Rostedt 7465f9b6cedSSteven Rostedt # Now boot the box 7475f9b6cedSSteven Rostedt get_grub_index; 7485f9b6cedSSteven Rostedt get_version; 7495f9b6cedSSteven Rostedt install; 7507faafbd6SSteven Rostedt 7517faafbd6SSteven Rostedt start_monitor; 7522b7d9b21SSteven Rostedt monitor or $failed = 1; 7535f9b6cedSSteven Rostedt 7545f9b6cedSSteven Rostedt if ($type ne "boot") { 7557faafbd6SSteven Rostedt dodie "Failed on boot" if $failed; 7565a391fbfSSteven Rostedt 7572b7d9b21SSteven Rostedt do_run_test or $failed = 1; 7585f9b6cedSSteven Rostedt } 7597faafbd6SSteven Rostedt end_monitor; 7605f9b6cedSSteven Rostedt } 7615f9b6cedSSteven Rostedt 7625f9b6cedSSteven Rostedt if ($failed) { 7635f9b6cedSSteven Rostedt $result = "bad"; 7645a391fbfSSteven Rostedt 7655a391fbfSSteven Rostedt # reboot the box to a good kernel 766*a75fececSSteven Rostedt if ($type ne "build") { 767*a75fececSSteven Rostedt doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 7685a391fbfSSteven Rostedt reboot; 7697faafbd6SSteven Rostedt start_monitor; 770*a75fececSSteven Rostedt wait_for_monitor $bisect_sleep_time; 7717faafbd6SSteven Rostedt end_monitor; 7725a391fbfSSteven Rostedt } 7735f9b6cedSSteven Rostedt } else { 7745f9b6cedSSteven Rostedt $result = "good"; 7755f9b6cedSSteven Rostedt } 7765f9b6cedSSteven Rostedt 777d6ce2a0bSSteven Rostedt # Are we looking for where it worked, not failed? 778d6ce2a0bSSteven Rostedt if ($reverse_bisect) { 779d6ce2a0bSSteven Rostedt if ($failed) { 780d6ce2a0bSSteven Rostedt $result = "good"; 781d6ce2a0bSSteven Rostedt } else { 782d6ce2a0bSSteven Rostedt $result = "bad"; 783d6ce2a0bSSteven Rostedt } 784d6ce2a0bSSteven Rostedt } 785d6ce2a0bSSteven Rostedt 786*a75fececSSteven Rostedt return $result; 7875f9b6cedSSteven Rostedt} 7885f9b6cedSSteven Rostedt 7895f9b6cedSSteven Rostedtsub bisect { 7905f9b6cedSSteven Rostedt my ($i) = @_; 7915f9b6cedSSteven Rostedt 7925f9b6cedSSteven Rostedt my $result; 7935f9b6cedSSteven Rostedt 7945f9b6cedSSteven Rostedt die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 7955f9b6cedSSteven Rostedt die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 7965f9b6cedSSteven Rostedt die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 7975f9b6cedSSteven Rostedt 7985f9b6cedSSteven Rostedt my $good = $opt{"BISECT_GOOD[$i]"}; 7995f9b6cedSSteven Rostedt my $bad = $opt{"BISECT_BAD[$i]"}; 8005f9b6cedSSteven Rostedt my $type = $opt{"BISECT_TYPE[$i]"}; 801*a75fececSSteven Rostedt my $start = $opt{"BISECT_START[$i]"}; 802*a75fececSSteven Rostedt my $replay = $opt{"BISECT_REPLAY[$i]"}; 8035f9b6cedSSteven Rostedt 804d6ce2a0bSSteven Rostedt if (defined($opt{"BISECT_REVERSE[$i]"}) && 805d6ce2a0bSSteven Rostedt $opt{"BISECT_REVERSE[$i]"} == 1) { 806d6ce2a0bSSteven Rostedt doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 807d6ce2a0bSSteven Rostedt $reverse_bisect = 1; 808d6ce2a0bSSteven Rostedt } else { 809d6ce2a0bSSteven Rostedt $reverse_bisect = 0; 810d6ce2a0bSSteven Rostedt } 811d6ce2a0bSSteven Rostedt 8125f9b6cedSSteven Rostedt $in_bisect = 1; 8135f9b6cedSSteven Rostedt 8145a391fbfSSteven Rostedt # Can't have a test without having a test to run 8155a391fbfSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 8165a391fbfSSteven Rostedt $type = "boot"; 8175a391fbfSSteven Rostedt } 8185a391fbfSSteven Rostedt 819*a75fececSSteven Rostedt my $check = $opt{"BISECT_CHECK[$i]"}; 820*a75fececSSteven Rostedt if (defined($check) && $check ne "0") { 821*a75fececSSteven Rostedt 822*a75fececSSteven Rostedt # get current HEAD 823*a75fececSSteven Rostedt doprint "git rev-list HEAD --max-count=1 ... "; 824*a75fececSSteven Rostedt my $head = `git rev-list HEAD --max-count=1`; 825*a75fececSSteven Rostedt my $ret = $?; 826*a75fececSSteven Rostedt 827*a75fececSSteven Rostedt logit $head; 828*a75fececSSteven Rostedt 829*a75fececSSteven Rostedt if ($ret) { 830*a75fececSSteven Rostedt doprint "FAILED\n"; 831*a75fececSSteven Rostedt dodie "Failed to get git HEAD"; 832*a75fececSSteven Rostedt } 833*a75fececSSteven Rostedt 834*a75fececSSteven Rostedt print "SUCCESS\n"; 835*a75fececSSteven Rostedt 836*a75fececSSteven Rostedt chomp $head; 837*a75fececSSteven Rostedt 838*a75fececSSteven Rostedt if ($check ne "good") { 839*a75fececSSteven Rostedt doprint "TESTING BISECT BAD [$bad]\n"; 840*a75fececSSteven Rostedt run_command "git checkout $bad" or 841*a75fececSSteven Rostedt die "Failed to checkout $bad"; 842*a75fececSSteven Rostedt 843*a75fececSSteven Rostedt $result = run_bisect $type; 844*a75fececSSteven Rostedt 845*a75fececSSteven Rostedt if ($result ne "bad") { 846*a75fececSSteven Rostedt fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 847*a75fececSSteven Rostedt } 848*a75fececSSteven Rostedt } 849*a75fececSSteven Rostedt 850*a75fececSSteven Rostedt if ($check ne "bad") { 851*a75fececSSteven Rostedt doprint "TESTING BISECT GOOD [$good]\n"; 852*a75fececSSteven Rostedt run_command "git checkout $good" or 853*a75fececSSteven Rostedt die "Failed to checkout $good"; 854*a75fececSSteven Rostedt 855*a75fececSSteven Rostedt $result = run_bisect $type; 856*a75fececSSteven Rostedt 857*a75fececSSteven Rostedt if ($result ne "good") { 858*a75fececSSteven Rostedt fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 859*a75fececSSteven Rostedt } 860*a75fececSSteven Rostedt } 861*a75fececSSteven Rostedt 862*a75fececSSteven Rostedt # checkout where we started 863*a75fececSSteven Rostedt run_command "git checkout $head" or 864*a75fececSSteven Rostedt die "Failed to checkout $head"; 865*a75fececSSteven Rostedt } 866*a75fececSSteven Rostedt 867*a75fececSSteven Rostedt run_command "git bisect start" or 868*a75fececSSteven Rostedt dodie "could not start bisect"; 869*a75fececSSteven Rostedt 870*a75fececSSteven Rostedt run_command "git bisect good $good" or 871*a75fececSSteven Rostedt dodie "could not set bisect good to $good"; 872*a75fececSSteven Rostedt 873*a75fececSSteven Rostedt run_git_bisect "git bisect bad $bad" or 874*a75fececSSteven Rostedt dodie "could not set bisect bad to $bad"; 875*a75fececSSteven Rostedt 876*a75fececSSteven Rostedt if (defined($replay)) { 877*a75fececSSteven Rostedt run_command "git bisect replay $replay" or 878*a75fececSSteven Rostedt dodie "failed to run replay"; 879*a75fececSSteven Rostedt } 880*a75fececSSteven Rostedt 881*a75fececSSteven Rostedt if (defined($start)) { 882*a75fececSSteven Rostedt run_command "git checkout $start" or 883*a75fececSSteven Rostedt dodie "failed to checkout $start"; 884*a75fececSSteven Rostedt } 885*a75fececSSteven Rostedt 886*a75fececSSteven Rostedt my $test; 8875f9b6cedSSteven Rostedt do { 8885f9b6cedSSteven Rostedt $result = run_bisect $type; 889*a75fececSSteven Rostedt $test = run_git_bisect "git bisect $result"; 890*a75fececSSteven Rostedt } while ($test); 8915f9b6cedSSteven Rostedt 8925f9b6cedSSteven Rostedt run_command "git bisect log" or 8935f9b6cedSSteven Rostedt dodie "could not capture git bisect log"; 8945f9b6cedSSteven Rostedt 8955f9b6cedSSteven Rostedt run_command "git bisect reset" or 8965f9b6cedSSteven Rostedt dodie "could not reset git bisect"; 8975f9b6cedSSteven Rostedt 8985f9b6cedSSteven Rostedt doprint "Bad commit was [$bisect_bad]\n"; 8995f9b6cedSSteven Rostedt 9005f9b6cedSSteven Rostedt $in_bisect = 0; 9015f9b6cedSSteven Rostedt 9025f9b6cedSSteven Rostedt success $i; 9035f9b6cedSSteven Rostedt} 9045f9b6cedSSteven Rostedt 9056c5ee0beSSteven Rostedtsub patchcheck { 9066c5ee0beSSteven Rostedt my ($i) = @_; 9076c5ee0beSSteven Rostedt 9086c5ee0beSSteven Rostedt die "PATCHCHECK_START[$i] not defined\n" 9096c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_START[$i]"})); 9106c5ee0beSSteven Rostedt die "PATCHCHECK_TYPE[$i] not defined\n" 9116c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 9126c5ee0beSSteven Rostedt 9136c5ee0beSSteven Rostedt my $start = $opt{"PATCHCHECK_START[$i]"}; 9146c5ee0beSSteven Rostedt 9156c5ee0beSSteven Rostedt my $end = "HEAD"; 9166c5ee0beSSteven Rostedt if (defined($opt{"PATCHCHECK_END[$i]"})) { 9176c5ee0beSSteven Rostedt $end = $opt{"PATCHCHECK_END[$i]"}; 9186c5ee0beSSteven Rostedt } 9196c5ee0beSSteven Rostedt 9206c5ee0beSSteven Rostedt my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 9216c5ee0beSSteven Rostedt 9226c5ee0beSSteven Rostedt # Can't have a test without having a test to run 9236c5ee0beSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 9246c5ee0beSSteven Rostedt $type = "boot"; 9256c5ee0beSSteven Rostedt } 9266c5ee0beSSteven Rostedt 9276c5ee0beSSteven Rostedt open (IN, "git log --pretty=oneline $end|") or 9286c5ee0beSSteven Rostedt dodie "could not get git list"; 9296c5ee0beSSteven Rostedt 9306c5ee0beSSteven Rostedt my @list; 9316c5ee0beSSteven Rostedt 9326c5ee0beSSteven Rostedt while (<IN>) { 9336c5ee0beSSteven Rostedt chomp; 9346c5ee0beSSteven Rostedt $list[$#list+1] = $_; 9356c5ee0beSSteven Rostedt last if (/^$start/); 9366c5ee0beSSteven Rostedt } 9376c5ee0beSSteven Rostedt close(IN); 9386c5ee0beSSteven Rostedt 9396c5ee0beSSteven Rostedt if ($list[$#list] !~ /^$start/) { 9402b7d9b21SSteven Rostedt fail "SHA1 $start not found"; 9416c5ee0beSSteven Rostedt } 9426c5ee0beSSteven Rostedt 9436c5ee0beSSteven Rostedt # go backwards in the list 9446c5ee0beSSteven Rostedt @list = reverse @list; 9456c5ee0beSSteven Rostedt 9466c5ee0beSSteven Rostedt my $save_clean = $noclean; 9476c5ee0beSSteven Rostedt 9486c5ee0beSSteven Rostedt $in_patchcheck = 1; 9496c5ee0beSSteven Rostedt foreach my $item (@list) { 9506c5ee0beSSteven Rostedt my $sha1 = $item; 9516c5ee0beSSteven Rostedt $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 9526c5ee0beSSteven Rostedt 9536c5ee0beSSteven Rostedt doprint "\nProcessing commit $item\n\n"; 9546c5ee0beSSteven Rostedt 9556c5ee0beSSteven Rostedt run_command "git checkout $sha1" or 9566c5ee0beSSteven Rostedt die "Failed to checkout $sha1"; 9576c5ee0beSSteven Rostedt 9586c5ee0beSSteven Rostedt # only clean on the first and last patch 9596c5ee0beSSteven Rostedt if ($item eq $list[0] || 9606c5ee0beSSteven Rostedt $item eq $list[$#list]) { 9616c5ee0beSSteven Rostedt $noclean = $save_clean; 9626c5ee0beSSteven Rostedt } else { 9636c5ee0beSSteven Rostedt $noclean = 1; 9646c5ee0beSSteven Rostedt } 9656c5ee0beSSteven Rostedt 9666c5ee0beSSteven Rostedt if (defined($minconfig)) { 9672b7d9b21SSteven Rostedt build "useconfig:$minconfig" or return 0; 9686c5ee0beSSteven Rostedt } else { 9696c5ee0beSSteven Rostedt # ?? no config to use? 9702b7d9b21SSteven Rostedt build "oldconfig" or return 0; 9716c5ee0beSSteven Rostedt } 9726c5ee0beSSteven Rostedt 9732b7d9b21SSteven Rostedt check_buildlog $sha1 or return 0; 9746c5ee0beSSteven Rostedt 9756c5ee0beSSteven Rostedt next if ($type eq "build"); 9766c5ee0beSSteven Rostedt 9776c5ee0beSSteven Rostedt get_grub_index; 9786c5ee0beSSteven Rostedt get_version; 9796c5ee0beSSteven Rostedt install; 9806c5ee0beSSteven Rostedt 9817faafbd6SSteven Rostedt my $failed = 0; 9827faafbd6SSteven Rostedt 9837faafbd6SSteven Rostedt start_monitor; 9847faafbd6SSteven Rostedt monitor or $failed = 1; 9857faafbd6SSteven Rostedt 9867faafbd6SSteven Rostedt if (!$failed && $type ne "boot"){ 9877faafbd6SSteven Rostedt do_run_test or $failed = 1; 9887faafbd6SSteven Rostedt } 9897faafbd6SSteven Rostedt end_monitor; 9907faafbd6SSteven Rostedt return 0 if ($failed); 9917faafbd6SSteven Rostedt 9926c5ee0beSSteven Rostedt } 9936c5ee0beSSteven Rostedt $in_patchcheck = 0; 9946c5ee0beSSteven Rostedt success $i; 9952b7d9b21SSteven Rostedt 9962b7d9b21SSteven Rostedt return 1; 9976c5ee0beSSteven Rostedt} 9986c5ee0beSSteven Rostedt 9992545eb61SSteven Rostedtread_config $ARGV[0]; 10002545eb61SSteven Rostedt 10012545eb61SSteven Rostedt# mandatory configs 10022545eb61SSteven Rostedtdie "MACHINE not defined\n" if (!defined($opt{"MACHINE"})); 10032545eb61SSteven Rostedtdie "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"})); 10042545eb61SSteven Rostedtdie "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"})); 10052545eb61SSteven Rostedtdie "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"})); 10062545eb61SSteven Rostedtdie "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"})); 100775c3fda7SSteven Rostedtdie "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"})); 10082545eb61SSteven Rostedtdie "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"})); 10092545eb61SSteven Rostedtdie "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"})); 10102545eb61SSteven Rostedtdie "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"})); 10112545eb61SSteven Rostedt 10122b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 10132b7d9b21SSteven Rostedt unlink $opt{"LOG_FILE"}; 10142b7d9b21SSteven Rostedt} 10152545eb61SSteven Rostedt 10162b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 10172b7d9b21SSteven Rostedt 10182b7d9b21SSteven Rostedtforeach my $option (sort keys %opt) { 10192b7d9b21SSteven Rostedt doprint "$option = $opt{$option}\n"; 10202b7d9b21SSteven Rostedt} 10212545eb61SSteven Rostedt 1022*a75fececSSteven Rostedtsub set_test_option { 10235a391fbfSSteven Rostedt my ($name, $i) = @_; 10245a391fbfSSteven Rostedt 10255a391fbfSSteven Rostedt my $option = "$name\[$i\]"; 10265a391fbfSSteven Rostedt 10275a391fbfSSteven Rostedt if (defined($opt{$option})) { 10285a391fbfSSteven Rostedt return $opt{$option}; 10295a391fbfSSteven Rostedt } 10305a391fbfSSteven Rostedt 10315a391fbfSSteven Rostedt if (defined($opt{$name})) { 10325a391fbfSSteven Rostedt return $opt{$name}; 10335a391fbfSSteven Rostedt } 10345a391fbfSSteven Rostedt 10355a391fbfSSteven Rostedt return undef; 10365a391fbfSSteven Rostedt} 10375a391fbfSSteven Rostedt 10382545eb61SSteven Rostedt# First we need to do is the builds 1039*a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 10402545eb61SSteven Rostedt 1041*a75fececSSteven Rostedt my $ssh_user = set_test_option("SSH_USER", $i); 1042*a75fececSSteven Rostedt my $makecmd = set_test_option("MAKE_CMD", $i); 1043*a75fececSSteven Rostedt 1044*a75fececSSteven Rostedt $machine = set_test_option("MACHINE", $i); 1045*a75fececSSteven Rostedt $tmpdir = set_test_option("TMP_DIR", $i); 1046*a75fececSSteven Rostedt $outputdir = set_test_option("OUTPUT_DIR", $i); 1047*a75fececSSteven Rostedt $builddir = set_test_option("BUILD_DIR", $i); 1048*a75fececSSteven Rostedt $test_type = set_test_option("TEST_TYPE", $i); 1049*a75fececSSteven Rostedt $build_type = set_test_option("BUILD_TYPE", $i); 1050*a75fececSSteven Rostedt $build_options = set_test_option("BUILD_OPTIONS", $i); 1051*a75fececSSteven Rostedt $power_cycle = set_test_option("POWER_CYCLE", $i); 1052*a75fececSSteven Rostedt $noclean = set_test_option("BUILD_NOCLEAN", $i); 1053*a75fececSSteven Rostedt $minconfig = set_test_option("MIN_CONFIG", $i); 1054*a75fececSSteven Rostedt $run_test = set_test_option("TEST", $i); 1055*a75fececSSteven Rostedt $addconfig = set_test_option("ADD_CONFIG", $i); 1056*a75fececSSteven Rostedt $reboot_type = set_test_option("REBOOT_TYPE", $i); 1057*a75fececSSteven Rostedt $grub_menu = set_test_option("GRUB_MENU", $i); 1058*a75fececSSteven Rostedt $reboot_script = set_test_option("REBOOT_SCRIPT", $i); 1059*a75fececSSteven Rostedt $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); 1060*a75fececSSteven Rostedt $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); 1061*a75fececSSteven Rostedt $die_on_failure = set_test_option("DIE_ON_FAILURE", $i); 1062*a75fececSSteven Rostedt $power_off = set_test_option("POWER_OFF", $i); 1063*a75fececSSteven Rostedt $sleep_time = set_test_option("SLEEP_TIME", $i); 1064*a75fececSSteven Rostedt $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 1065*a75fececSSteven Rostedt $store_failures = set_test_option("STORE_FAILURES", $i); 1066*a75fececSSteven Rostedt $timeout = set_test_option("TIMEOUT", $i); 1067*a75fececSSteven Rostedt $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 1068*a75fececSSteven Rostedt $console = set_test_option("CONSOLE", $i); 1069*a75fececSSteven Rostedt $success_line = set_test_option("SUCCESS_LINE", $i); 1070*a75fececSSteven Rostedt $build_target = set_test_option("BUILD_TARGET", $i); 1071*a75fececSSteven Rostedt $target_image = set_test_option("TARGET_IMAGE", $i); 1072*a75fececSSteven Rostedt $localversion = set_test_option("LOCALVERSION", $i); 1073*a75fececSSteven Rostedt 1074*a75fececSSteven Rostedt chdir $builddir || die "can't change directory to $builddir"; 1075*a75fececSSteven Rostedt 1076*a75fececSSteven Rostedt if (!-d $tmpdir) { 1077*a75fececSSteven Rostedt mkpath($tmpdir) or 1078*a75fececSSteven Rostedt die "can't create $tmpdir"; 1079*a75fececSSteven Rostedt } 1080*a75fececSSteven Rostedt 1081*a75fececSSteven Rostedt $target = "$ssh_user\@$machine"; 1082*a75fececSSteven Rostedt 1083*a75fececSSteven Rostedt $buildlog = "$tmpdir/buildlog-$machine"; 1084*a75fececSSteven Rostedt $dmesg = "$tmpdir/dmesg-$machine"; 1085*a75fececSSteven Rostedt $make = "$makecmd O=$outputdir"; 1086*a75fececSSteven Rostedt 1087*a75fececSSteven Rostedt if ($reboot_type eq "grub") { 1088*a75fececSSteven Rostedt dodie "GRUB_MENU not defined\n" if (!defined($grub_menu)); 1089*a75fececSSteven Rostedt } elsif (!defined($reboot_script)) { 1090*a75fececSSteven Rostedt dodie "REBOOT_SCRIPT not defined\n" 1091*a75fececSSteven Rostedt } 1092*a75fececSSteven Rostedt 1093*a75fececSSteven Rostedt my $run_type = $build_type; 1094*a75fececSSteven Rostedt if ($test_type eq "patchcheck") { 1095*a75fececSSteven Rostedt $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 1096*a75fececSSteven Rostedt } elsif ($test_type eq "bisect") { 1097*a75fececSSteven Rostedt $run_type = $opt{"BISECT_TYPE[$i]"}; 1098*a75fececSSteven Rostedt } 1099*a75fececSSteven Rostedt 1100*a75fececSSteven Rostedt # mistake in config file? 1101*a75fececSSteven Rostedt if (!defined($run_type)) { 1102*a75fececSSteven Rostedt $run_type = "ERROR"; 1103*a75fececSSteven Rostedt } 11042545eb61SSteven Rostedt 11052545eb61SSteven Rostedt doprint "\n\n"; 1106*a75fececSSteven Rostedt doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n"; 11077faafbd6SSteven Rostedt 11087faafbd6SSteven Rostedt unlink $dmesg; 11097faafbd6SSteven Rostedt unlink $buildlog; 11102545eb61SSteven Rostedt 11112b7d9b21SSteven Rostedt if (!defined($minconfig)) { 11122b7d9b21SSteven Rostedt $minconfig = $addconfig; 11132b7d9b21SSteven Rostedt 11142b7d9b21SSteven Rostedt } elsif (defined($addconfig)) { 1115*a75fececSSteven Rostedt run_command "cat $addconfig $minconfig > $tmpdir/use_config" or 11162b7d9b21SSteven Rostedt dodie "Failed to create temp config"; 1117*a75fececSSteven Rostedt $minconfig = "$tmpdir/use_config"; 11182b7d9b21SSteven Rostedt } 11192b7d9b21SSteven Rostedt 11206c5ee0beSSteven Rostedt my $checkout = $opt{"CHECKOUT[$i]"}; 11216c5ee0beSSteven Rostedt if (defined($checkout)) { 11226c5ee0beSSteven Rostedt run_command "git checkout $checkout" or 11236c5ee0beSSteven Rostedt die "failed to checkout $checkout"; 11246c5ee0beSSteven Rostedt } 11256c5ee0beSSteven Rostedt 1126*a75fececSSteven Rostedt if ($test_type eq "bisect") { 11275f9b6cedSSteven Rostedt bisect $i; 11285f9b6cedSSteven Rostedt next; 1129*a75fececSSteven Rostedt } elsif ($test_type eq "patchcheck") { 11306c5ee0beSSteven Rostedt patchcheck $i; 11316c5ee0beSSteven Rostedt next; 11325f9b6cedSSteven Rostedt } 11335f9b6cedSSteven Rostedt 11347faafbd6SSteven Rostedt if ($build_type ne "nobuild") { 11357faafbd6SSteven Rostedt build $build_type or next; 11362545eb61SSteven Rostedt } 11372545eb61SSteven Rostedt 1138*a75fececSSteven Rostedt if ($test_type ne "build") { 11395f9b6cedSSteven Rostedt get_grub_index; 11405f9b6cedSSteven Rostedt get_version; 11412545eb61SSteven Rostedt install; 11425a391fbfSSteven Rostedt 11437faafbd6SSteven Rostedt my $failed = 0; 11447faafbd6SSteven Rostedt start_monitor; 11457faafbd6SSteven Rostedt monitor or $failed = 1;; 1146*a75fececSSteven Rostedt 1147*a75fececSSteven Rostedt if (!$failed && $test_type ne "boot" && defined($run_test)) { 11487faafbd6SSteven Rostedt do_run_test or $failed = 1; 11495a391fbfSSteven Rostedt } 11507faafbd6SSteven Rostedt end_monitor; 11517faafbd6SSteven Rostedt next if ($failed); 1152*a75fececSSteven Rostedt } 11535a391fbfSSteven Rostedt 11545f9b6cedSSteven Rostedt success $i; 115575c3fda7SSteven Rostedt} 11562545eb61SSteven Rostedt 11575c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) { 115875c3fda7SSteven Rostedt halt; 1159*a75fececSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && $test_type ne "build") { 116075c3fda7SSteven Rostedt reboot; 11615c42fc5bSSteven Rostedt} 116275c3fda7SSteven Rostedt 11632545eb61SSteven Rostedtexit 0; 1164