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); 10*7faafbd6SSteven Rostedtuse File::Path qw(mkpath); 11*7faafbd6SSteven 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; 192545eb61SSteven Rostedt 202545eb61SSteven Rostedt#default opts 212545eb61SSteven Rostedt$opt{"NUM_BUILDS"} = 5; 22*7faafbd6SSteven Rostedt$opt{"BUILD_TYPE"} = "randconfig"; 232545eb61SSteven Rostedt$opt{"MAKE_CMD"} = "make"; 242b7d9b21SSteven Rostedt$opt{"TIMEOUT"} = 120; 252545eb61SSteven Rostedt$opt{"TMP_DIR"} = "/tmp/autotest"; 262545eb61SSteven Rostedt$opt{"SLEEP_TIME"} = 60; # sleep time between tests 275c42fc5bSSteven Rostedt$opt{"BUILD_NOCLEAN"} = 0; 2875c3fda7SSteven Rostedt$opt{"REBOOT_ON_ERROR"} = 0; 295c42fc5bSSteven Rostedt$opt{"POWEROFF_ON_ERROR"} = 0; 301a5cfce3SSteven Rostedt$opt{"REBOOT_ON_SUCCESS"} = 1; 315c42fc5bSSteven Rostedt$opt{"POWEROFF_ON_SUCCESS"} = 0; 3275c3fda7SSteven Rostedt$opt{"BUILD_OPTIONS"} = ""; 335a391fbfSSteven Rostedt$opt{"BISECT_SLEEP_TIME"} = 10; # sleep time between bisects 342b7d9b21SSteven Rostedt$opt{"CLEAR_LOG"} = 0; 352b7d9b21SSteven Rostedt$opt{"SUCCESS_LINE"} = "login:"; 362b7d9b21SSteven Rostedt$opt{"BOOTED_TIMEOUT"} = 1; 372b7d9b21SSteven Rostedt$opt{"DIE_ON_FAILURE"} = 1; 382545eb61SSteven Rostedt 392545eb61SSteven Rostedtmy $version; 40*7faafbd6SSteven Rostedtmy $build_type; 412545eb61SSteven Rostedtmy $grub_number; 422545eb61SSteven Rostedtmy $target; 432545eb61SSteven Rostedtmy $make; 445c42fc5bSSteven Rostedtmy $noclean; 455f9b6cedSSteven Rostedtmy $minconfig; 462b7d9b21SSteven Rostedtmy $addconfig; 475f9b6cedSSteven Rostedtmy $in_bisect = 0; 485f9b6cedSSteven Rostedtmy $bisect_bad = ""; 49d6ce2a0bSSteven Rostedtmy $reverse_bisect; 506c5ee0beSSteven Rostedtmy $in_patchcheck = 0; 515a391fbfSSteven Rostedtmy $run_test; 526c5ee0beSSteven Rostedtmy $redirect; 53*7faafbd6SSteven Rostedtmy $buildlog; 54*7faafbd6SSteven Rostedtmy $dmesg; 55*7faafbd6SSteven Rostedtmy $monitor_fp; 56*7faafbd6SSteven Rostedtmy $monitor_pid; 57*7faafbd6SSteven Rostedtmy $monitor_cnt = 0; 582545eb61SSteven Rostedt 592545eb61SSteven Rostedtsub read_config { 602545eb61SSteven Rostedt my ($config) = @_; 612545eb61SSteven Rostedt 622545eb61SSteven Rostedt open(IN, $config) || die "can't read file $config"; 632545eb61SSteven Rostedt 642545eb61SSteven Rostedt while (<IN>) { 652545eb61SSteven Rostedt 662545eb61SSteven Rostedt # ignore blank lines and comments 672545eb61SSteven Rostedt next if (/^\s*$/ || /\s*\#/); 682545eb61SSteven Rostedt 692545eb61SSteven Rostedt if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) { 702545eb61SSteven Rostedt my $lvalue = $1; 712545eb61SSteven Rostedt my $rvalue = $2; 722545eb61SSteven Rostedt 732545eb61SSteven Rostedt $opt{$lvalue} = $rvalue; 742545eb61SSteven Rostedt } 752545eb61SSteven Rostedt } 762545eb61SSteven Rostedt 772545eb61SSteven Rostedt close(IN); 782545eb61SSteven Rostedt} 792545eb61SSteven Rostedt 805f9b6cedSSteven Rostedtsub logit { 812545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 822545eb61SSteven Rostedt open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 832545eb61SSteven Rostedt print OUT @_; 842545eb61SSteven Rostedt close(OUT); 852545eb61SSteven Rostedt } 862545eb61SSteven Rostedt} 872545eb61SSteven Rostedt 885f9b6cedSSteven Rostedtsub doprint { 895f9b6cedSSteven Rostedt print @_; 905f9b6cedSSteven Rostedt logit @_; 915f9b6cedSSteven Rostedt} 925f9b6cedSSteven Rostedt 93*7faafbd6SSteven Rostedtsub run_command; 94*7faafbd6SSteven Rostedt 95*7faafbd6SSteven Rostedtsub reboot { 96*7faafbd6SSteven Rostedt # try to reboot normally 97*7faafbd6SSteven Rostedt if (!run_command "ssh $target reboot") { 98*7faafbd6SSteven Rostedt # nope? power cycle it. 99*7faafbd6SSteven Rostedt run_command "$opt{POWER_CYCLE}"; 100*7faafbd6SSteven Rostedt } 101*7faafbd6SSteven Rostedt} 102*7faafbd6SSteven Rostedt 1035c42fc5bSSteven Rostedtsub dodie { 1045a391fbfSSteven Rostedt doprint "CRITICAL FAILURE... ", @_, "\n"; 1055c42fc5bSSteven Rostedt 10675c3fda7SSteven Rostedt if ($opt{"REBOOT_ON_ERROR"}) { 10775c3fda7SSteven Rostedt doprint "REBOOTING\n"; 108*7faafbd6SSteven Rostedt reboot; 10975c3fda7SSteven Rostedt 11075c3fda7SSteven Rostedt } elsif ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) { 1115c42fc5bSSteven Rostedt doprint "POWERING OFF\n"; 1125c42fc5bSSteven Rostedt `$opt{"POWER_OFF"}`; 1135c42fc5bSSteven Rostedt } 11475c3fda7SSteven Rostedt 1155c42fc5bSSteven Rostedt die @_; 1165c42fc5bSSteven Rostedt} 1175c42fc5bSSteven Rostedt 118*7faafbd6SSteven Rostedtsub open_console { 119*7faafbd6SSteven Rostedt my ($fp) = @_; 120*7faafbd6SSteven Rostedt 121*7faafbd6SSteven Rostedt my $flags; 122*7faafbd6SSteven Rostedt 123*7faafbd6SSteven Rostedt my $pid = open($fp, "$opt{CONSOLE}|") or 124*7faafbd6SSteven Rostedt dodie "Can't open console $opt{CONSOLE}"; 125*7faafbd6SSteven Rostedt 126*7faafbd6SSteven Rostedt $flags = fcntl($fp, F_GETFL, 0) or 127*7faafbd6SSteven Rostedt dodie "Can't get flags for the socket: $!\n"; 128*7faafbd6SSteven Rostedt $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 129*7faafbd6SSteven Rostedt dodie "Can't set flags for the socket: $!\n"; 130*7faafbd6SSteven Rostedt 131*7faafbd6SSteven Rostedt return $pid; 132*7faafbd6SSteven Rostedt} 133*7faafbd6SSteven Rostedt 134*7faafbd6SSteven Rostedtsub close_console { 135*7faafbd6SSteven Rostedt my ($fp, $pid) = @_; 136*7faafbd6SSteven Rostedt 137*7faafbd6SSteven Rostedt doprint "kill child process $pid\n"; 138*7faafbd6SSteven Rostedt kill 2, $pid; 139*7faafbd6SSteven Rostedt 140*7faafbd6SSteven Rostedt print "closing!\n"; 141*7faafbd6SSteven Rostedt close($fp); 142*7faafbd6SSteven Rostedt} 143*7faafbd6SSteven Rostedt 144*7faafbd6SSteven Rostedtsub start_monitor { 145*7faafbd6SSteven Rostedt if ($monitor_cnt++) { 146*7faafbd6SSteven Rostedt return; 147*7faafbd6SSteven Rostedt } 148*7faafbd6SSteven Rostedt $monitor_fp = \*MONFD; 149*7faafbd6SSteven Rostedt $monitor_pid = open_console $monitor_fp; 150*7faafbd6SSteven Rostedt} 151*7faafbd6SSteven Rostedt 152*7faafbd6SSteven Rostedtsub end_monitor { 153*7faafbd6SSteven Rostedt if (--$monitor_cnt) { 154*7faafbd6SSteven Rostedt return; 155*7faafbd6SSteven Rostedt } 156*7faafbd6SSteven Rostedt close_console($monitor_fp, $monitor_pid); 157*7faafbd6SSteven Rostedt} 158*7faafbd6SSteven Rostedt 159*7faafbd6SSteven Rostedtsub wait_for_monitor { 160*7faafbd6SSteven Rostedt my ($time) = @_; 161*7faafbd6SSteven Rostedt my $line; 162*7faafbd6SSteven Rostedt 163*7faafbd6SSteven Rostedt doprint "Wait for monitor to settle down.\n"; 164*7faafbd6SSteven Rostedt 165*7faafbd6SSteven Rostedt # read the monitor and wait for the system to calm down 166*7faafbd6SSteven Rostedt do { 167*7faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 168*7faafbd6SSteven Rostedt } while (defined($line)); 169*7faafbd6SSteven Rostedt} 170*7faafbd6SSteven Rostedt 1712b7d9b21SSteven Rostedtsub fail { 1722b7d9b21SSteven Rostedt 1732b7d9b21SSteven Rostedt if ($opt{"DIE_ON_FAILURE"}) { 1742b7d9b21SSteven Rostedt dodie @_; 1752b7d9b21SSteven Rostedt } 1762b7d9b21SSteven Rostedt 1772b7d9b21SSteven Rostedt doprint "Failed: ", @_, "\n"; 178*7faafbd6SSteven Rostedt 179*7faafbd6SSteven Rostedt doprint "REBOOTING\n"; 180*7faafbd6SSteven Rostedt reboot; 181*7faafbd6SSteven Rostedt start_monitor; 182*7faafbd6SSteven Rostedt wait_for_monitor $opt{"SLEEP_TIME"}; 183*7faafbd6SSteven Rostedt end_monitor; 184*7faafbd6SSteven Rostedt 185*7faafbd6SSteven Rostedt return 1 if (!defined($opt{"STORE_FAILURES"})); 186*7faafbd6SSteven Rostedt 187*7faafbd6SSteven Rostedt my @t = localtime; 188*7faafbd6SSteven Rostedt my $date = sprintf "%04d%02d%02d%02d%02d%02d", 189*7faafbd6SSteven Rostedt 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 190*7faafbd6SSteven Rostedt 191*7faafbd6SSteven Rostedt my $dir = "$opt{MACHINE}-$build_type-fail-$date"; 192*7faafbd6SSteven Rostedt my $faildir = "$opt{STORE_FAILURES}/$dir"; 193*7faafbd6SSteven Rostedt 194*7faafbd6SSteven Rostedt if (!-d $faildir) { 195*7faafbd6SSteven Rostedt mkpath($faildir) or 196*7faafbd6SSteven Rostedt die "can't create $opt{STORE_FAILURES}"; 197*7faafbd6SSteven Rostedt } 198*7faafbd6SSteven Rostedt if (-f "$opt{OUTPUT_DIR}/.config") { 199*7faafbd6SSteven Rostedt cp "$opt{OUTPUT_DIR}/.config", "$faildir/config" or 200*7faafbd6SSteven Rostedt die "failed to copy .config"; 201*7faafbd6SSteven Rostedt } 202*7faafbd6SSteven Rostedt if (-f $buildlog) { 203*7faafbd6SSteven Rostedt cp $buildlog, "$faildir/buildlog" or 204*7faafbd6SSteven Rostedt die "failed to move $buildlog"; 205*7faafbd6SSteven Rostedt } 206*7faafbd6SSteven Rostedt if (-f $dmesg) { 207*7faafbd6SSteven Rostedt cp $dmesg, "$faildir/dmesg" or 208*7faafbd6SSteven Rostedt die "failed to move $dmesg"; 209*7faafbd6SSteven Rostedt } 210*7faafbd6SSteven Rostedt 211*7faafbd6SSteven Rostedt doprint "*** Saved info to $faildir ***\n"; 212*7faafbd6SSteven Rostedt 2132b7d9b21SSteven Rostedt return 1; 2142b7d9b21SSteven Rostedt} 2152b7d9b21SSteven Rostedt 2162545eb61SSteven Rostedtsub run_command { 2172545eb61SSteven Rostedt my ($command) = @_; 218d6ce2a0bSSteven Rostedt my $dolog = 0; 219d6ce2a0bSSteven Rostedt my $dord = 0; 220d6ce2a0bSSteven Rostedt my $pid; 221d6ce2a0bSSteven Rostedt 222d6ce2a0bSSteven Rostedt doprint("$command ... "); 223d6ce2a0bSSteven Rostedt 224d6ce2a0bSSteven Rostedt $pid = open(CMD, "$command 2>&1 |") or 2252b7d9b21SSteven Rostedt (fail "unable to exec $command" and return 0); 2262545eb61SSteven Rostedt 2272545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 228d6ce2a0bSSteven Rostedt open(LOG, ">>$opt{LOG_FILE}") or 229d6ce2a0bSSteven Rostedt dodie "failed to write to log"; 230d6ce2a0bSSteven Rostedt $dolog = 1; 2316c5ee0beSSteven Rostedt } 2326c5ee0beSSteven Rostedt 2336c5ee0beSSteven Rostedt if (defined($redirect)) { 234d6ce2a0bSSteven Rostedt open (RD, ">$redirect") or 235d6ce2a0bSSteven Rostedt dodie "failed to write to redirect $redirect"; 236d6ce2a0bSSteven Rostedt $dord = 1; 2372545eb61SSteven Rostedt } 2382545eb61SSteven Rostedt 239d6ce2a0bSSteven Rostedt while (<CMD>) { 240d6ce2a0bSSteven Rostedt print LOG if ($dolog); 241d6ce2a0bSSteven Rostedt print RD if ($dord); 242d6ce2a0bSSteven Rostedt } 2432545eb61SSteven Rostedt 244d6ce2a0bSSteven Rostedt waitpid($pid, 0); 2452545eb61SSteven Rostedt my $failed = $?; 2462545eb61SSteven Rostedt 247d6ce2a0bSSteven Rostedt close(CMD); 248d6ce2a0bSSteven Rostedt close(LOG) if ($dolog); 249d6ce2a0bSSteven Rostedt close(RD) if ($dord); 250d6ce2a0bSSteven Rostedt 2512545eb61SSteven Rostedt if ($failed) { 2522545eb61SSteven Rostedt doprint "FAILED!\n"; 2532545eb61SSteven Rostedt } else { 2542545eb61SSteven Rostedt doprint "SUCCESS\n"; 2552545eb61SSteven Rostedt } 2562545eb61SSteven Rostedt 2575f9b6cedSSteven Rostedt return !$failed; 2585f9b6cedSSteven Rostedt} 2595f9b6cedSSteven Rostedt 2605f9b6cedSSteven Rostedtsub get_grub_index { 2615f9b6cedSSteven Rostedt 2625a391fbfSSteven Rostedt return if (defined($grub_number)); 2635f9b6cedSSteven Rostedt 2645f9b6cedSSteven Rostedt doprint "Find grub menu ... "; 2655f9b6cedSSteven Rostedt $grub_number = -1; 2665f9b6cedSSteven Rostedt open(IN, "ssh $target cat /boot/grub/menu.lst |") 2675f9b6cedSSteven Rostedt or die "unable to get menu.lst"; 2685f9b6cedSSteven Rostedt while (<IN>) { 2695f9b6cedSSteven Rostedt if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) { 2705f9b6cedSSteven Rostedt $grub_number++; 2715f9b6cedSSteven Rostedt last; 2725f9b6cedSSteven Rostedt } elsif (/^\s*title\s/) { 2735f9b6cedSSteven Rostedt $grub_number++; 2745f9b6cedSSteven Rostedt } 2755f9b6cedSSteven Rostedt } 2765f9b6cedSSteven Rostedt close(IN); 2775f9b6cedSSteven Rostedt 2785f9b6cedSSteven Rostedt die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}" 2795f9b6cedSSteven Rostedt if ($grub_number < 0); 2805f9b6cedSSteven Rostedt doprint "$grub_number\n"; 2812545eb61SSteven Rostedt} 2822545eb61SSteven Rostedt 2832545eb61SSteven Rostedtmy $timeout = $opt{"TIMEOUT"}; 2842545eb61SSteven Rostedt 2852545eb61SSteven Rostedtsub wait_for_input 2862545eb61SSteven Rostedt{ 2872545eb61SSteven Rostedt my ($fp, $time) = @_; 2882545eb61SSteven Rostedt my $rin; 2892545eb61SSteven Rostedt my $ready; 2902545eb61SSteven Rostedt my $line; 2912545eb61SSteven Rostedt my $ch; 2922545eb61SSteven Rostedt 2932545eb61SSteven Rostedt if (!defined($time)) { 2942545eb61SSteven Rostedt $time = $timeout; 2952545eb61SSteven Rostedt } 2962545eb61SSteven Rostedt 2972545eb61SSteven Rostedt $rin = ''; 2982545eb61SSteven Rostedt vec($rin, fileno($fp), 1) = 1; 2992545eb61SSteven Rostedt $ready = select($rin, undef, undef, $time); 3002545eb61SSteven Rostedt 3012545eb61SSteven Rostedt $line = ""; 3022545eb61SSteven Rostedt 3032545eb61SSteven Rostedt # try to read one char at a time 3042545eb61SSteven Rostedt while (sysread $fp, $ch, 1) { 3052545eb61SSteven Rostedt $line .= $ch; 3062545eb61SSteven Rostedt last if ($ch eq "\n"); 3072545eb61SSteven Rostedt } 3082545eb61SSteven Rostedt 3092545eb61SSteven Rostedt if (!length($line)) { 3102545eb61SSteven Rostedt return undef; 3112545eb61SSteven Rostedt } 3122545eb61SSteven Rostedt 3132545eb61SSteven Rostedt return $line; 3142545eb61SSteven Rostedt} 3152545eb61SSteven Rostedt 31675c3fda7SSteven Rostedtsub reboot_to { 3172545eb61SSteven Rostedt run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; 3182545eb61SSteven Rostedt} 3192545eb61SSteven Rostedt 3205a391fbfSSteven Rostedtsub monitor { 3212545eb61SSteven Rostedt my $booted = 0; 3222545eb61SSteven Rostedt my $bug = 0; 3235c42fc5bSSteven Rostedt my $skip_call_trace = 0; 3242b7d9b21SSteven Rostedt my $loops; 3252545eb61SSteven Rostedt 326*7faafbd6SSteven Rostedt wait_for_monitor 5; 3272545eb61SSteven Rostedt 3282545eb61SSteven Rostedt my $line; 3292545eb61SSteven Rostedt my $full_line = ""; 3302545eb61SSteven Rostedt 331*7faafbd6SSteven Rostedt open(DMESG, "> $dmesg") or 332*7faafbd6SSteven Rostedt die "unable to write to $dmesg"; 3332545eb61SSteven Rostedt 33475c3fda7SSteven Rostedt reboot_to; 3352545eb61SSteven Rostedt 3362545eb61SSteven Rostedt for (;;) { 3372545eb61SSteven Rostedt 3382b7d9b21SSteven Rostedt if ($booted) { 339*7faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, $opt{"BOOTED_TIMEOUT"}); 3402b7d9b21SSteven Rostedt } else { 341*7faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp); 3422b7d9b21SSteven Rostedt } 3432545eb61SSteven Rostedt 3442545eb61SSteven Rostedt last if (!defined($line)); 3452545eb61SSteven Rostedt 3462545eb61SSteven Rostedt doprint $line; 347*7faafbd6SSteven Rostedt print DMESG $line; 3482545eb61SSteven Rostedt 3492545eb61SSteven Rostedt # we are not guaranteed to get a full line 3502545eb61SSteven Rostedt $full_line .= $line; 3512545eb61SSteven Rostedt 3522b7d9b21SSteven Rostedt if ($full_line =~ /$opt{"SUCCESS_LINE"}/) { 3532545eb61SSteven Rostedt $booted = 1; 3542545eb61SSteven Rostedt } 3552545eb61SSteven Rostedt 3565c42fc5bSSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 3575c42fc5bSSteven Rostedt $skip_call_trace = 1; 3585c42fc5bSSteven Rostedt } 3595c42fc5bSSteven Rostedt 3602545eb61SSteven Rostedt if ($full_line =~ /call trace:/i) { 3615c42fc5bSSteven Rostedt $bug = 1 if (!$skip_call_trace); 3625c42fc5bSSteven Rostedt } 3635c42fc5bSSteven Rostedt 3645c42fc5bSSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 3655c42fc5bSSteven Rostedt $skip_call_trace = 0; 3665c42fc5bSSteven Rostedt } 3675c42fc5bSSteven Rostedt 3685c42fc5bSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 3692545eb61SSteven Rostedt $bug = 1; 3702545eb61SSteven Rostedt } 3712545eb61SSteven Rostedt 3722545eb61SSteven Rostedt if ($line =~ /\n/) { 3732545eb61SSteven Rostedt $full_line = ""; 3742545eb61SSteven Rostedt } 3752545eb61SSteven Rostedt } 3762545eb61SSteven Rostedt 377*7faafbd6SSteven Rostedt close(DMESG); 3782545eb61SSteven Rostedt 3792545eb61SSteven Rostedt if (!$booted) { 3802b7d9b21SSteven Rostedt return 0 if ($in_bisect); 3812b7d9b21SSteven Rostedt fail "failed - never got a boot prompt.\n" and return 0; 3822545eb61SSteven Rostedt } 3832545eb61SSteven Rostedt 3842545eb61SSteven Rostedt if ($bug) { 3852b7d9b21SSteven Rostedt return 0 if ($in_bisect); 3862b7d9b21SSteven Rostedt fail "failed - got a bug report\n" and return 0; 3872545eb61SSteven Rostedt } 3885f9b6cedSSteven Rostedt 3892b7d9b21SSteven Rostedt return 1; 3902545eb61SSteven Rostedt} 3912545eb61SSteven Rostedt 3922545eb61SSteven Rostedtsub install { 3932545eb61SSteven Rostedt 3945f9b6cedSSteven Rostedt run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}" or 3955c42fc5bSSteven Rostedt dodie "failed to copy image"; 3965f9b6cedSSteven Rostedt 3975f9b6cedSSteven Rostedt my $install_mods = 0; 3985f9b6cedSSteven Rostedt 3995f9b6cedSSteven Rostedt # should we process modules? 4005f9b6cedSSteven Rostedt $install_mods = 0; 4015f9b6cedSSteven Rostedt open(IN, "$opt{OUTPUT_DIR}/.config") or dodie("Can't read config file"); 4025f9b6cedSSteven Rostedt while (<IN>) { 4035f9b6cedSSteven Rostedt if (/CONFIG_MODULES(=y)?/) { 4045f9b6cedSSteven Rostedt $install_mods = 1 if (defined($1)); 4055f9b6cedSSteven Rostedt last; 4065f9b6cedSSteven Rostedt } 4075f9b6cedSSteven Rostedt } 4085f9b6cedSSteven Rostedt close(IN); 4095f9b6cedSSteven Rostedt 4105f9b6cedSSteven Rostedt if (!$install_mods) { 4115f9b6cedSSteven Rostedt doprint "No modules needed\n"; 4125f9b6cedSSteven Rostedt return; 4132545eb61SSteven Rostedt } 4142545eb61SSteven Rostedt 4155f9b6cedSSteven Rostedt run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install" or 4165f9b6cedSSteven Rostedt dodie "Failed to install modules"; 4175f9b6cedSSteven Rostedt 4182545eb61SSteven Rostedt my $modlib = "/lib/modules/$version"; 4195c42fc5bSSteven Rostedt my $modtar = "autotest-mods.tar.bz2"; 4202545eb61SSteven Rostedt 4215f9b6cedSSteven Rostedt run_command "ssh $target rm -rf $modlib" or 4225c42fc5bSSteven Rostedt dodie "failed to remove old mods: $modlib"; 4232545eb61SSteven Rostedt 4245c42fc5bSSteven Rostedt # would be nice if scp -r did not follow symbolic links 4255f9b6cedSSteven Rostedt run_command "cd $opt{TMP_DIR} && tar -cjf $modtar lib/modules/$version" or 4265c42fc5bSSteven Rostedt dodie "making tarball"; 4275c42fc5bSSteven Rostedt 4285f9b6cedSSteven Rostedt run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp" or 4295c42fc5bSSteven Rostedt dodie "failed to copy modules"; 4305c42fc5bSSteven Rostedt 4315c42fc5bSSteven Rostedt unlink "$opt{TMP_DIR}/$modtar"; 4325c42fc5bSSteven Rostedt 4335f9b6cedSSteven Rostedt run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or 4345c42fc5bSSteven Rostedt dodie "failed to tar modules"; 4355c42fc5bSSteven Rostedt 4365c42fc5bSSteven Rostedt run_command "ssh $target rm -f /tmp/$modtar"; 4372545eb61SSteven Rostedt} 4382545eb61SSteven Rostedt 4396c5ee0beSSteven Rostedtsub check_buildlog { 4406c5ee0beSSteven Rostedt my ($patch) = @_; 4416c5ee0beSSteven Rostedt 4426c5ee0beSSteven Rostedt my @files = `git show $patch | diffstat -l`; 4436c5ee0beSSteven Rostedt 4446c5ee0beSSteven Rostedt open(IN, "git show $patch |") or 4456c5ee0beSSteven Rostedt dodie "failed to show $patch"; 4466c5ee0beSSteven Rostedt while (<IN>) { 4476c5ee0beSSteven Rostedt if (m,^--- a/(.*),) { 4486c5ee0beSSteven Rostedt chomp $1; 4496c5ee0beSSteven Rostedt $files[$#files] = $1; 4506c5ee0beSSteven Rostedt } 4516c5ee0beSSteven Rostedt } 4526c5ee0beSSteven Rostedt close(IN); 4536c5ee0beSSteven Rostedt 4546c5ee0beSSteven Rostedt open(IN, $buildlog) or dodie "Can't open $buildlog"; 4556c5ee0beSSteven Rostedt while (<IN>) { 4566c5ee0beSSteven Rostedt if (/^\s*(.*?):.*(warning|error)/) { 4576c5ee0beSSteven Rostedt my $err = $1; 4586c5ee0beSSteven Rostedt foreach my $file (@files) { 4596c5ee0beSSteven Rostedt my $fullpath = "$opt{BUILD_DIR}/$file"; 4606c5ee0beSSteven Rostedt if ($file eq $err || $fullpath eq $err) { 4612b7d9b21SSteven Rostedt fail "$file built with warnings" and return 0; 4626c5ee0beSSteven Rostedt } 4636c5ee0beSSteven Rostedt } 4646c5ee0beSSteven Rostedt } 4656c5ee0beSSteven Rostedt } 4666c5ee0beSSteven Rostedt close(IN); 4672b7d9b21SSteven Rostedt 4682b7d9b21SSteven Rostedt return 1; 4696c5ee0beSSteven Rostedt} 4706c5ee0beSSteven Rostedt 4712545eb61SSteven Rostedtsub build { 4722545eb61SSteven Rostedt my ($type) = @_; 4735c42fc5bSSteven Rostedt my $defconfig = ""; 4745c42fc5bSSteven Rostedt my $append = ""; 4752545eb61SSteven Rostedt 476*7faafbd6SSteven Rostedt unlink $buildlog; 477*7faafbd6SSteven Rostedt 47875c3fda7SSteven Rostedt if ($type =~ /^useconfig:(.*)/) { 4795f9b6cedSSteven Rostedt run_command "cp $1 $opt{OUTPUT_DIR}/.config" or 48075c3fda7SSteven Rostedt dodie "could not copy $1 to .config"; 4815f9b6cedSSteven Rostedt 48275c3fda7SSteven Rostedt $type = "oldconfig"; 48375c3fda7SSteven Rostedt } 48475c3fda7SSteven Rostedt 4855c42fc5bSSteven Rostedt # old config can ask questions 4865c42fc5bSSteven Rostedt if ($type eq "oldconfig") { 4875c42fc5bSSteven Rostedt $append = "yes ''|"; 48875c3fda7SSteven Rostedt 48975c3fda7SSteven Rostedt # allow for empty configs 49075c3fda7SSteven Rostedt run_command "touch $opt{OUTPUT_DIR}/.config"; 49175c3fda7SSteven Rostedt 4925f9b6cedSSteven Rostedt run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp" or 4935c42fc5bSSteven Rostedt dodie "moving .config"; 4945c42fc5bSSteven Rostedt 4955f9b6cedSSteven Rostedt if (!$noclean && !run_command "$make mrproper") { 4965c42fc5bSSteven Rostedt dodie "make mrproper"; 4975c42fc5bSSteven Rostedt } 4985c42fc5bSSteven Rostedt 4995f9b6cedSSteven Rostedt run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config" or 5005c42fc5bSSteven Rostedt dodie "moving config_temp"; 5015c42fc5bSSteven Rostedt 5025c42fc5bSSteven Rostedt } elsif (!$noclean) { 5032545eb61SSteven Rostedt unlink "$opt{OUTPUT_DIR}/.config"; 5045f9b6cedSSteven Rostedt run_command "$make mrproper" or 5055c42fc5bSSteven Rostedt dodie "make mrproper"; 5065c42fc5bSSteven Rostedt } 5072545eb61SSteven Rostedt 5082545eb61SSteven Rostedt # add something to distinguish this build 5095c42fc5bSSteven Rostedt open(OUT, "> $opt{OUTPUT_DIR}/localversion") or dodie("Can't make localversion file"); 5102545eb61SSteven Rostedt print OUT "$opt{LOCALVERSION}\n"; 5112545eb61SSteven Rostedt close(OUT); 5122545eb61SSteven Rostedt 5135f9b6cedSSteven Rostedt if (defined($minconfig)) { 5145f9b6cedSSteven Rostedt $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; 5152545eb61SSteven Rostedt } 5162545eb61SSteven Rostedt 5175f9b6cedSSteven Rostedt run_command "$defconfig $append $make $type" or 5185c42fc5bSSteven Rostedt dodie "failed make config"; 5192545eb61SSteven Rostedt 5206c5ee0beSSteven Rostedt $redirect = "$opt{TMP_DIR}/buildlog"; 5215f9b6cedSSteven Rostedt if (!run_command "$make $opt{BUILD_OPTIONS}") { 5226c5ee0beSSteven Rostedt undef $redirect; 5235f9b6cedSSteven Rostedt # bisect may need this to pass 5242b7d9b21SSteven Rostedt return 0 if ($in_bisect); 5252b7d9b21SSteven Rostedt fail "failed build" and return 0; 5262545eb61SSteven Rostedt } 5276c5ee0beSSteven Rostedt undef $redirect; 5285f9b6cedSSteven Rostedt 5292b7d9b21SSteven Rostedt return 1; 5302545eb61SSteven Rostedt} 5312545eb61SSteven Rostedt 53275c3fda7SSteven Rostedtsub halt { 5335f9b6cedSSteven Rostedt if (!run_command "ssh $target halt" or defined($opt{"POWER_OFF"})) { 53475c3fda7SSteven Rostedt # nope? the zap it! 53575c3fda7SSteven Rostedt run_command "$opt{POWER_OFF}"; 53675c3fda7SSteven Rostedt } 53775c3fda7SSteven Rostedt} 53875c3fda7SSteven Rostedt 5395f9b6cedSSteven Rostedtsub success { 5405f9b6cedSSteven Rostedt my ($i) = @_; 5415f9b6cedSSteven Rostedt 5425f9b6cedSSteven Rostedt doprint "\n\n*******************************************\n"; 5435f9b6cedSSteven Rostedt doprint "*******************************************\n"; 5445f9b6cedSSteven Rostedt doprint "** SUCCESS!!!! **\n"; 5455f9b6cedSSteven Rostedt doprint "*******************************************\n"; 5465f9b6cedSSteven Rostedt doprint "*******************************************\n"; 5475f9b6cedSSteven Rostedt 5485f9b6cedSSteven Rostedt if ($i != $opt{"NUM_BUILDS"}) { 549*7faafbd6SSteven Rostedt doprint "Reboot and wait $opt{SLEEP_TIME} seconds\n"; 5505f9b6cedSSteven Rostedt reboot; 551*7faafbd6SSteven Rostedt start_monitor; 552*7faafbd6SSteven Rostedt wait_for_monitor $opt{"SLEEP_TIME"}; 553*7faafbd6SSteven Rostedt end_monitor; 5545f9b6cedSSteven Rostedt } 5555f9b6cedSSteven Rostedt} 5565f9b6cedSSteven Rostedt 5575f9b6cedSSteven Rostedtsub get_version { 5585f9b6cedSSteven Rostedt # get the release name 5595f9b6cedSSteven Rostedt doprint "$make kernelrelease ... "; 5605f9b6cedSSteven Rostedt $version = `$make kernelrelease | tail -1`; 5615f9b6cedSSteven Rostedt chomp($version); 5625f9b6cedSSteven Rostedt doprint "$version\n"; 5635f9b6cedSSteven Rostedt} 5645f9b6cedSSteven Rostedt 5655a391fbfSSteven Rostedtsub child_run_test { 566*7faafbd6SSteven Rostedt my $failed = 0; 5675a391fbfSSteven Rostedt 568*7faafbd6SSteven Rostedt # child should have no power 569*7faafbd6SSteven Rostedt $opt{"REBOOT_ON_ERROR"} = 0; 570*7faafbd6SSteven Rostedt $opt{"POWEROFF_ON_ERROR"} = 0; 571*7faafbd6SSteven Rostedt $opt{"DIE_ON_FAILURE"} = 1; 572*7faafbd6SSteven Rostedt 573*7faafbd6SSteven Rostedt run_command $run_test or $failed = 1; 5745a391fbfSSteven Rostedt exit $failed; 5755a391fbfSSteven Rostedt} 5765a391fbfSSteven Rostedt 5775a391fbfSSteven Rostedtmy $child_done; 5785a391fbfSSteven Rostedt 5795a391fbfSSteven Rostedtsub child_finished { 5805a391fbfSSteven Rostedt $child_done = 1; 5815a391fbfSSteven Rostedt} 5825a391fbfSSteven Rostedt 5835a391fbfSSteven Rostedtsub do_run_test { 5845a391fbfSSteven Rostedt my $child_pid; 5855a391fbfSSteven Rostedt my $child_exit; 5865a391fbfSSteven Rostedt my $line; 5875a391fbfSSteven Rostedt my $full_line; 5885a391fbfSSteven Rostedt my $bug = 0; 5895a391fbfSSteven Rostedt 590*7faafbd6SSteven Rostedt wait_for_monitor 1; 5915a391fbfSSteven Rostedt 592*7faafbd6SSteven Rostedt doprint "run test $run_test\n"; 5935a391fbfSSteven Rostedt 5945a391fbfSSteven Rostedt $child_done = 0; 5955a391fbfSSteven Rostedt 5965a391fbfSSteven Rostedt $SIG{CHLD} = qw(child_finished); 5975a391fbfSSteven Rostedt 5985a391fbfSSteven Rostedt $child_pid = fork; 5995a391fbfSSteven Rostedt 6005a391fbfSSteven Rostedt child_run_test if (!$child_pid); 6015a391fbfSSteven Rostedt 6025a391fbfSSteven Rostedt $full_line = ""; 6035a391fbfSSteven Rostedt 6045a391fbfSSteven Rostedt do { 605*7faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 6065a391fbfSSteven Rostedt if (defined($line)) { 6075a391fbfSSteven Rostedt 6085a391fbfSSteven Rostedt # we are not guaranteed to get a full line 6095a391fbfSSteven Rostedt $full_line .= $line; 6105a391fbfSSteven Rostedt 6115a391fbfSSteven Rostedt if ($full_line =~ /call trace:/i) { 6125a391fbfSSteven Rostedt $bug = 1; 6135a391fbfSSteven Rostedt } 6145a391fbfSSteven Rostedt 6155a391fbfSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 6165a391fbfSSteven Rostedt $bug = 1; 6175a391fbfSSteven Rostedt } 6185a391fbfSSteven Rostedt 6195a391fbfSSteven Rostedt if ($line =~ /\n/) { 6205a391fbfSSteven Rostedt $full_line = ""; 6215a391fbfSSteven Rostedt } 6225a391fbfSSteven Rostedt } 6235a391fbfSSteven Rostedt } while (!$child_done && !$bug); 6245a391fbfSSteven Rostedt 6255a391fbfSSteven Rostedt if ($bug) { 6265a391fbfSSteven Rostedt doprint "Detected kernel crash!\n"; 6275a391fbfSSteven Rostedt # kill the child with extreme prejudice 6285a391fbfSSteven Rostedt kill 9, $child_pid; 6295a391fbfSSteven Rostedt } 6305a391fbfSSteven Rostedt 6315a391fbfSSteven Rostedt waitpid $child_pid, 0; 6325a391fbfSSteven Rostedt $child_exit = $?; 6335a391fbfSSteven Rostedt 6345a391fbfSSteven Rostedt if ($bug || $child_exit) { 6352b7d9b21SSteven Rostedt return 0 if $in_bisect; 6362b7d9b21SSteven Rostedt fail "test failed" and return 0; 6375a391fbfSSteven Rostedt } 6382b7d9b21SSteven Rostedt return 1; 6395a391fbfSSteven Rostedt} 6405a391fbfSSteven Rostedt 6415f9b6cedSSteven Rostedtsub run_bisect { 6425f9b6cedSSteven Rostedt my ($type) = @_; 6435f9b6cedSSteven Rostedt 6442b7d9b21SSteven Rostedt my $failed = 0; 6455f9b6cedSSteven Rostedt my $result; 6465f9b6cedSSteven Rostedt my $output; 6475f9b6cedSSteven Rostedt my $ret; 6485f9b6cedSSteven Rostedt 6495f9b6cedSSteven Rostedt if (defined($minconfig)) { 6502b7d9b21SSteven Rostedt build "useconfig:$minconfig" or $failed = 1; 6515f9b6cedSSteven Rostedt } else { 6525f9b6cedSSteven Rostedt # ?? no config to use? 6532b7d9b21SSteven Rostedt build "oldconfig" or $failed = 1; 6545f9b6cedSSteven Rostedt } 6555f9b6cedSSteven Rostedt 6565f9b6cedSSteven Rostedt if ($type ne "build") { 657*7faafbd6SSteven Rostedt dodie "Failed on build" if $failed; 6585f9b6cedSSteven Rostedt 6595f9b6cedSSteven Rostedt # Now boot the box 6605f9b6cedSSteven Rostedt get_grub_index; 6615f9b6cedSSteven Rostedt get_version; 6625f9b6cedSSteven Rostedt install; 663*7faafbd6SSteven Rostedt 664*7faafbd6SSteven Rostedt start_monitor; 6652b7d9b21SSteven Rostedt monitor or $failed = 1; 6665f9b6cedSSteven Rostedt 6675f9b6cedSSteven Rostedt if ($type ne "boot") { 668*7faafbd6SSteven Rostedt dodie "Failed on boot" if $failed; 6695a391fbfSSteven Rostedt 6702b7d9b21SSteven Rostedt do_run_test or $failed = 1; 6715f9b6cedSSteven Rostedt } 672*7faafbd6SSteven Rostedt end_monitor; 6735f9b6cedSSteven Rostedt } 6745f9b6cedSSteven Rostedt 6755f9b6cedSSteven Rostedt if ($failed) { 6765f9b6cedSSteven Rostedt $result = "bad"; 6775a391fbfSSteven Rostedt 6785a391fbfSSteven Rostedt # reboot the box to a good kernel 6795a391fbfSSteven Rostedt if ($type eq "boot") { 680*7faafbd6SSteven Rostedt doprint "Reboot and sleep $opt{BISECT_SLEEP_TIME} seconds\n"; 6815a391fbfSSteven Rostedt reboot; 682*7faafbd6SSteven Rostedt start_monitor; 683*7faafbd6SSteven Rostedt wait_for_monitor $opt{"BISECT_SLEEP_TIME"}; 684*7faafbd6SSteven Rostedt end_monitor; 6855a391fbfSSteven Rostedt } 6865f9b6cedSSteven Rostedt } else { 6875f9b6cedSSteven Rostedt $result = "good"; 6885f9b6cedSSteven Rostedt } 6895f9b6cedSSteven Rostedt 690d6ce2a0bSSteven Rostedt # Are we looking for where it worked, not failed? 691d6ce2a0bSSteven Rostedt if ($reverse_bisect) { 692d6ce2a0bSSteven Rostedt if ($failed) { 693d6ce2a0bSSteven Rostedt $result = "good"; 694d6ce2a0bSSteven Rostedt } else { 695d6ce2a0bSSteven Rostedt $result = "bad"; 696d6ce2a0bSSteven Rostedt } 697d6ce2a0bSSteven Rostedt } 698d6ce2a0bSSteven Rostedt 6995f9b6cedSSteven Rostedt doprint "git bisect $result ... "; 7005f9b6cedSSteven Rostedt $output = `git bisect $result 2>&1`; 7015f9b6cedSSteven Rostedt $ret = $?; 7025f9b6cedSSteven Rostedt 7035f9b6cedSSteven Rostedt logit $output; 7045f9b6cedSSteven Rostedt 7055f9b6cedSSteven Rostedt if ($ret) { 7065f9b6cedSSteven Rostedt doprint "FAILED\n"; 7072b7d9b21SSteven Rostedt fail "Failed to git bisect"; 7085f9b6cedSSteven Rostedt } 7095f9b6cedSSteven Rostedt 7105f9b6cedSSteven Rostedt doprint "SUCCESS\n"; 7115a391fbfSSteven Rostedt if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 7125f9b6cedSSteven Rostedt doprint "$1 [$2]\n"; 7135f9b6cedSSteven Rostedt } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 7145f9b6cedSSteven Rostedt $bisect_bad = $1; 7155f9b6cedSSteven Rostedt doprint "Found bad commit... $1\n"; 7165f9b6cedSSteven Rostedt return 0; 7175a391fbfSSteven Rostedt } else { 7185a391fbfSSteven Rostedt # we already logged it, just print it now. 7195a391fbfSSteven Rostedt print $output; 7205f9b6cedSSteven Rostedt } 7215f9b6cedSSteven Rostedt 7225f9b6cedSSteven Rostedt 7235f9b6cedSSteven Rostedt return 1; 7245f9b6cedSSteven Rostedt} 7255f9b6cedSSteven Rostedt 7265f9b6cedSSteven Rostedtsub bisect { 7275f9b6cedSSteven Rostedt my ($i) = @_; 7285f9b6cedSSteven Rostedt 7295f9b6cedSSteven Rostedt my $result; 7305f9b6cedSSteven Rostedt 7315f9b6cedSSteven Rostedt die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 7325f9b6cedSSteven Rostedt die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 7335f9b6cedSSteven Rostedt die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 7345f9b6cedSSteven Rostedt 7355f9b6cedSSteven Rostedt my $good = $opt{"BISECT_GOOD[$i]"}; 7365f9b6cedSSteven Rostedt my $bad = $opt{"BISECT_BAD[$i]"}; 7375f9b6cedSSteven Rostedt my $type = $opt{"BISECT_TYPE[$i]"}; 7385f9b6cedSSteven Rostedt 739d6ce2a0bSSteven Rostedt if (defined($opt{"BISECT_REVERSE[$i]"}) && 740d6ce2a0bSSteven Rostedt $opt{"BISECT_REVERSE[$i]"} == 1) { 741d6ce2a0bSSteven Rostedt doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 742d6ce2a0bSSteven Rostedt $reverse_bisect = 1; 743d6ce2a0bSSteven Rostedt } else { 744d6ce2a0bSSteven Rostedt $reverse_bisect = 0; 745d6ce2a0bSSteven Rostedt } 746d6ce2a0bSSteven Rostedt 7475f9b6cedSSteven Rostedt $in_bisect = 1; 7485f9b6cedSSteven Rostedt 7495f9b6cedSSteven Rostedt run_command "git bisect start" or 7502b7d9b21SSteven Rostedt fail "could not start bisect"; 7515f9b6cedSSteven Rostedt 7525f9b6cedSSteven Rostedt run_command "git bisect good $good" or 7532b7d9b21SSteven Rostedt fail "could not set bisect good to $good"; 7545f9b6cedSSteven Rostedt 7555f9b6cedSSteven Rostedt run_command "git bisect bad $bad" or 7562b7d9b21SSteven Rostedt fail "could not set bisect good to $bad"; 7575f9b6cedSSteven Rostedt 7585a391fbfSSteven Rostedt # Can't have a test without having a test to run 7595a391fbfSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 7605a391fbfSSteven Rostedt $type = "boot"; 7615a391fbfSSteven Rostedt } 7625a391fbfSSteven Rostedt 7635f9b6cedSSteven Rostedt do { 7645f9b6cedSSteven Rostedt $result = run_bisect $type; 7655f9b6cedSSteven Rostedt } while ($result); 7665f9b6cedSSteven Rostedt 7675f9b6cedSSteven Rostedt run_command "git bisect log" or 7685f9b6cedSSteven Rostedt dodie "could not capture git bisect log"; 7695f9b6cedSSteven Rostedt 7705f9b6cedSSteven Rostedt run_command "git bisect reset" or 7715f9b6cedSSteven Rostedt dodie "could not reset git bisect"; 7725f9b6cedSSteven Rostedt 7735f9b6cedSSteven Rostedt doprint "Bad commit was [$bisect_bad]\n"; 7745f9b6cedSSteven Rostedt 7755f9b6cedSSteven Rostedt $in_bisect = 0; 7765f9b6cedSSteven Rostedt 7775f9b6cedSSteven Rostedt success $i; 7785f9b6cedSSteven Rostedt} 7795f9b6cedSSteven Rostedt 7806c5ee0beSSteven Rostedtsub patchcheck { 7816c5ee0beSSteven Rostedt my ($i) = @_; 7826c5ee0beSSteven Rostedt 7836c5ee0beSSteven Rostedt die "PATCHCHECK_START[$i] not defined\n" 7846c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_START[$i]"})); 7856c5ee0beSSteven Rostedt die "PATCHCHECK_TYPE[$i] not defined\n" 7866c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 7876c5ee0beSSteven Rostedt 7886c5ee0beSSteven Rostedt my $start = $opt{"PATCHCHECK_START[$i]"}; 7896c5ee0beSSteven Rostedt 7906c5ee0beSSteven Rostedt my $end = "HEAD"; 7916c5ee0beSSteven Rostedt if (defined($opt{"PATCHCHECK_END[$i]"})) { 7926c5ee0beSSteven Rostedt $end = $opt{"PATCHCHECK_END[$i]"}; 7936c5ee0beSSteven Rostedt } 7946c5ee0beSSteven Rostedt 7956c5ee0beSSteven Rostedt my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 7966c5ee0beSSteven Rostedt 7976c5ee0beSSteven Rostedt # Can't have a test without having a test to run 7986c5ee0beSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 7996c5ee0beSSteven Rostedt $type = "boot"; 8006c5ee0beSSteven Rostedt } 8016c5ee0beSSteven Rostedt 8026c5ee0beSSteven Rostedt open (IN, "git log --pretty=oneline $end|") or 8036c5ee0beSSteven Rostedt dodie "could not get git list"; 8046c5ee0beSSteven Rostedt 8056c5ee0beSSteven Rostedt my @list; 8066c5ee0beSSteven Rostedt 8076c5ee0beSSteven Rostedt while (<IN>) { 8086c5ee0beSSteven Rostedt chomp; 8096c5ee0beSSteven Rostedt $list[$#list+1] = $_; 8106c5ee0beSSteven Rostedt last if (/^$start/); 8116c5ee0beSSteven Rostedt } 8126c5ee0beSSteven Rostedt close(IN); 8136c5ee0beSSteven Rostedt 8146c5ee0beSSteven Rostedt if ($list[$#list] !~ /^$start/) { 8152b7d9b21SSteven Rostedt fail "SHA1 $start not found"; 8166c5ee0beSSteven Rostedt } 8176c5ee0beSSteven Rostedt 8186c5ee0beSSteven Rostedt # go backwards in the list 8196c5ee0beSSteven Rostedt @list = reverse @list; 8206c5ee0beSSteven Rostedt 8216c5ee0beSSteven Rostedt my $save_clean = $noclean; 8226c5ee0beSSteven Rostedt 8236c5ee0beSSteven Rostedt $in_patchcheck = 1; 8246c5ee0beSSteven Rostedt foreach my $item (@list) { 8256c5ee0beSSteven Rostedt my $sha1 = $item; 8266c5ee0beSSteven Rostedt $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 8276c5ee0beSSteven Rostedt 8286c5ee0beSSteven Rostedt doprint "\nProcessing commit $item\n\n"; 8296c5ee0beSSteven Rostedt 8306c5ee0beSSteven Rostedt run_command "git checkout $sha1" or 8316c5ee0beSSteven Rostedt die "Failed to checkout $sha1"; 8326c5ee0beSSteven Rostedt 8336c5ee0beSSteven Rostedt # only clean on the first and last patch 8346c5ee0beSSteven Rostedt if ($item eq $list[0] || 8356c5ee0beSSteven Rostedt $item eq $list[$#list]) { 8366c5ee0beSSteven Rostedt $noclean = $save_clean; 8376c5ee0beSSteven Rostedt } else { 8386c5ee0beSSteven Rostedt $noclean = 1; 8396c5ee0beSSteven Rostedt } 8406c5ee0beSSteven Rostedt 8416c5ee0beSSteven Rostedt if (defined($minconfig)) { 8422b7d9b21SSteven Rostedt build "useconfig:$minconfig" or return 0; 8436c5ee0beSSteven Rostedt } else { 8446c5ee0beSSteven Rostedt # ?? no config to use? 8452b7d9b21SSteven Rostedt build "oldconfig" or return 0; 8466c5ee0beSSteven Rostedt } 8476c5ee0beSSteven Rostedt 8482b7d9b21SSteven Rostedt check_buildlog $sha1 or return 0; 8496c5ee0beSSteven Rostedt 8506c5ee0beSSteven Rostedt next if ($type eq "build"); 8516c5ee0beSSteven Rostedt 8526c5ee0beSSteven Rostedt get_grub_index; 8536c5ee0beSSteven Rostedt get_version; 8546c5ee0beSSteven Rostedt install; 8556c5ee0beSSteven Rostedt 856*7faafbd6SSteven Rostedt my $failed = 0; 857*7faafbd6SSteven Rostedt 858*7faafbd6SSteven Rostedt start_monitor; 859*7faafbd6SSteven Rostedt monitor or $failed = 1; 860*7faafbd6SSteven Rostedt 861*7faafbd6SSteven Rostedt if (!$failed && $type ne "boot"){ 862*7faafbd6SSteven Rostedt do_run_test or $failed = 1; 863*7faafbd6SSteven Rostedt } 864*7faafbd6SSteven Rostedt end_monitor; 865*7faafbd6SSteven Rostedt return 0 if ($failed); 866*7faafbd6SSteven Rostedt 8676c5ee0beSSteven Rostedt } 8686c5ee0beSSteven Rostedt $in_patchcheck = 0; 8696c5ee0beSSteven Rostedt success $i; 8702b7d9b21SSteven Rostedt 8712b7d9b21SSteven Rostedt return 1; 8726c5ee0beSSteven Rostedt} 8736c5ee0beSSteven Rostedt 8742545eb61SSteven Rostedtread_config $ARGV[0]; 8752545eb61SSteven Rostedt 8762545eb61SSteven Rostedt# mandatory configs 8772545eb61SSteven Rostedtdie "MACHINE not defined\n" if (!defined($opt{"MACHINE"})); 8782545eb61SSteven Rostedtdie "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"})); 8792545eb61SSteven Rostedtdie "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"})); 8802545eb61SSteven Rostedtdie "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"})); 8812545eb61SSteven Rostedtdie "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"})); 88275c3fda7SSteven Rostedtdie "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"})); 8832545eb61SSteven Rostedtdie "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"})); 8842545eb61SSteven Rostedtdie "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"})); 8852545eb61SSteven Rostedtdie "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"})); 8862545eb61SSteven Rostedtdie "GRUB_MENU not defined\n" if (!defined($opt{"GRUB_MENU"})); 8872545eb61SSteven Rostedt 8882545eb61SSteven Rostedtchdir $opt{"BUILD_DIR"} || die "can't change directory to $opt{BUILD_DIR}"; 8892545eb61SSteven Rostedt 8902545eb61SSteven Rostedt$target = "$opt{SSH_USER}\@$opt{MACHINE}"; 8912545eb61SSteven Rostedt 8922b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 8932b7d9b21SSteven Rostedt unlink $opt{"LOG_FILE"}; 8942b7d9b21SSteven Rostedt} 8952545eb61SSteven Rostedt 8962b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 8972b7d9b21SSteven Rostedt 8982b7d9b21SSteven Rostedtforeach my $option (sort keys %opt) { 8992b7d9b21SSteven Rostedt doprint "$option = $opt{$option}\n"; 9002b7d9b21SSteven Rostedt} 9012545eb61SSteven Rostedt 902*7faafbd6SSteven Rostedt$buildlog = "$opt{TMP_DIR}/buildlog"; 903*7faafbd6SSteven Rostedt$dmesg = "$opt{TMP_DIR}/dmesg"; 9042545eb61SSteven Rostedt$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}"; 9052545eb61SSteven Rostedt 9065a391fbfSSteven Rostedtsub set_build_option { 9075a391fbfSSteven Rostedt my ($name, $i) = @_; 9085a391fbfSSteven Rostedt 9095a391fbfSSteven Rostedt my $option = "$name\[$i\]"; 9105a391fbfSSteven Rostedt 9115a391fbfSSteven Rostedt if (defined($opt{$option})) { 9125a391fbfSSteven Rostedt return $opt{$option}; 9135a391fbfSSteven Rostedt } 9145a391fbfSSteven Rostedt 9155a391fbfSSteven Rostedt if (defined($opt{$name})) { 9165a391fbfSSteven Rostedt return $opt{$name}; 9175a391fbfSSteven Rostedt } 9185a391fbfSSteven Rostedt 9195a391fbfSSteven Rostedt return undef; 9205a391fbfSSteven Rostedt} 9215a391fbfSSteven Rostedt 9222545eb61SSteven Rostedt# First we need to do is the builds 9232545eb61SSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) { 9242545eb61SSteven Rostedt 925*7faafbd6SSteven Rostedt $build_type = set_build_option("BUILD_TYPE", $i); 9265a391fbfSSteven Rostedt $noclean = set_build_option("BUILD_NOCLEAN", $i); 9275a391fbfSSteven Rostedt $minconfig = set_build_option("MIN_CONFIG", $i); 9285a391fbfSSteven Rostedt $run_test = set_build_option("TEST", $i); 9292b7d9b21SSteven Rostedt $addconfig = set_build_option("ADD_CONFIG", $i); 9302545eb61SSteven Rostedt 9312545eb61SSteven Rostedt doprint "\n\n"; 932*7faafbd6SSteven Rostedt doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $build_type\n\n"; 933*7faafbd6SSteven Rostedt 934*7faafbd6SSteven Rostedt unlink $dmesg; 935*7faafbd6SSteven Rostedt unlink $buildlog; 9362545eb61SSteven Rostedt 9372b7d9b21SSteven Rostedt if (!defined($minconfig)) { 9382b7d9b21SSteven Rostedt $minconfig = $addconfig; 9392b7d9b21SSteven Rostedt 9402b7d9b21SSteven Rostedt } elsif (defined($addconfig)) { 9412b7d9b21SSteven Rostedt run_command "cat $addconfig $minconfig > $opt{TMP_DIR}/use_config" or 9422b7d9b21SSteven Rostedt dodie "Failed to create temp config"; 9432b7d9b21SSteven Rostedt $minconfig = "$opt{TMP_DIR}/use_config"; 9442b7d9b21SSteven Rostedt } 9452b7d9b21SSteven Rostedt 9466c5ee0beSSteven Rostedt my $checkout = $opt{"CHECKOUT[$i]"}; 9476c5ee0beSSteven Rostedt if (defined($checkout)) { 9486c5ee0beSSteven Rostedt run_command "git checkout $checkout" or 9496c5ee0beSSteven Rostedt die "failed to checkout $checkout"; 9506c5ee0beSSteven Rostedt } 9516c5ee0beSSteven Rostedt 952*7faafbd6SSteven Rostedt if ($build_type eq "bisect") { 9535f9b6cedSSteven Rostedt bisect $i; 9545f9b6cedSSteven Rostedt next; 955*7faafbd6SSteven Rostedt } elsif ($build_type eq "patchcheck") { 9566c5ee0beSSteven Rostedt patchcheck $i; 9576c5ee0beSSteven Rostedt next; 9585f9b6cedSSteven Rostedt } 9595f9b6cedSSteven Rostedt 960*7faafbd6SSteven Rostedt if ($build_type ne "nobuild") { 961*7faafbd6SSteven Rostedt build $build_type or next; 9622545eb61SSteven Rostedt } 9632545eb61SSteven Rostedt 9645f9b6cedSSteven Rostedt get_grub_index; 9655f9b6cedSSteven Rostedt get_version; 9662545eb61SSteven Rostedt install; 9675a391fbfSSteven Rostedt 968*7faafbd6SSteven Rostedt my $failed = 0; 969*7faafbd6SSteven Rostedt start_monitor; 970*7faafbd6SSteven Rostedt monitor or $failed = 1;; 971*7faafbd6SSteven Rostedt if (!$failed && defined($run_test)) { 972*7faafbd6SSteven Rostedt do_run_test or $failed = 1; 9735a391fbfSSteven Rostedt } 974*7faafbd6SSteven Rostedt end_monitor; 975*7faafbd6SSteven Rostedt next if ($failed); 9765a391fbfSSteven Rostedt 9775f9b6cedSSteven Rostedt success $i; 97875c3fda7SSteven Rostedt} 9792545eb61SSteven Rostedt 9805c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) { 98175c3fda7SSteven Rostedt halt; 9821a5cfce3SSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"}) { 98375c3fda7SSteven Rostedt reboot; 9845c42fc5bSSteven Rostedt} 98575c3fda7SSteven Rostedt 9862545eb61SSteven Rostedtexit 0; 987