xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision 7faafbd69639b53b6cc2d450c283d9cc12e62c70)
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