xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision 51ad1dd1034684e9c490eb41c17cde8ffb682ab1)
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
14a57419b3SSteven Rostedt$#ARGV >= 0 || die "usage: ktest.pl config-file\n";
152545eb61SSteven Rostedt
162545eb61SSteven Rostedt$| = 1;
172545eb61SSteven Rostedt
182545eb61SSteven Rostedtmy %opt;
19a57419b3SSteven Rostedtmy %repeat_tests;
20a57419b3SSteven Rostedtmy %repeats;
21a75fececSSteven Rostedtmy %default;
222545eb61SSteven Rostedt
232545eb61SSteven Rostedt#default opts
24a57419b3SSteven Rostedt$default{"NUM_TESTS"}		= 1;
25a75fececSSteven Rostedt$default{"REBOOT_TYPE"}		= "grub";
26a75fececSSteven Rostedt$default{"TEST_TYPE"}		= "test";
27a75fececSSteven Rostedt$default{"BUILD_TYPE"}		= "randconfig";
28a75fececSSteven Rostedt$default{"MAKE_CMD"}		= "make";
29a75fececSSteven Rostedt$default{"TIMEOUT"}		= 120;
30a57419b3SSteven Rostedt$default{"TMP_DIR"}		= "/tmp/ktest";
31a75fececSSteven Rostedt$default{"SLEEP_TIME"}		= 60;	# sleep time between tests
32a75fececSSteven Rostedt$default{"BUILD_NOCLEAN"}	= 0;
33a75fececSSteven Rostedt$default{"REBOOT_ON_ERROR"}	= 0;
34a75fececSSteven Rostedt$default{"POWEROFF_ON_ERROR"}	= 0;
35a75fececSSteven Rostedt$default{"REBOOT_ON_SUCCESS"}	= 1;
36a75fececSSteven Rostedt$default{"POWEROFF_ON_SUCCESS"}	= 0;
37a75fececSSteven Rostedt$default{"BUILD_OPTIONS"}	= "";
38a75fececSSteven Rostedt$default{"BISECT_SLEEP_TIME"}	= 60;   # sleep time between bisects
39a75fececSSteven Rostedt$default{"CLEAR_LOG"}		= 0;
40a75fececSSteven Rostedt$default{"SUCCESS_LINE"}	= "login:";
41a75fececSSteven Rostedt$default{"BOOTED_TIMEOUT"}	= 1;
42a75fececSSteven Rostedt$default{"DIE_ON_FAILURE"}	= 1;
432545eb61SSteven Rostedt
442545eb61SSteven Rostedtmy $version;
45a75fececSSteven Rostedtmy $machine;
46a75fececSSteven Rostedtmy $tmpdir;
47a75fececSSteven Rostedtmy $builddir;
48a75fececSSteven Rostedtmy $outputdir;
49*51ad1dd1SSteven Rostedtmy $output_config;
50a75fececSSteven Rostedtmy $test_type;
517faafbd6SSteven Rostedtmy $build_type;
52a75fececSSteven Rostedtmy $build_options;
53a75fececSSteven Rostedtmy $reboot_type;
54a75fececSSteven Rostedtmy $reboot_script;
55a75fececSSteven Rostedtmy $power_cycle;
56a75fececSSteven Rostedtmy $reboot_on_error;
57a75fececSSteven Rostedtmy $poweroff_on_error;
58a75fececSSteven Rostedtmy $die_on_failure;
59576f627cSSteven Rostedtmy $powercycle_after_reboot;
60576f627cSSteven Rostedtmy $poweroff_after_halt;
61a75fececSSteven Rostedtmy $power_off;
62a75fececSSteven Rostedtmy $grub_menu;
632545eb61SSteven Rostedtmy $grub_number;
642545eb61SSteven Rostedtmy $target;
652545eb61SSteven Rostedtmy $make;
668b37ca8cSSteven Rostedtmy $post_install;
675c42fc5bSSteven Rostedtmy $noclean;
685f9b6cedSSteven Rostedtmy $minconfig;
692b7d9b21SSteven Rostedtmy $addconfig;
705f9b6cedSSteven Rostedtmy $in_bisect = 0;
715f9b6cedSSteven Rostedtmy $bisect_bad = "";
72d6ce2a0bSSteven Rostedtmy $reverse_bisect;
736c5ee0beSSteven Rostedtmy $in_patchcheck = 0;
745a391fbfSSteven Rostedtmy $run_test;
756c5ee0beSSteven Rostedtmy $redirect;
767faafbd6SSteven Rostedtmy $buildlog;
777faafbd6SSteven Rostedtmy $dmesg;
787faafbd6SSteven Rostedtmy $monitor_fp;
797faafbd6SSteven Rostedtmy $monitor_pid;
807faafbd6SSteven Rostedtmy $monitor_cnt = 0;
81a75fececSSteven Rostedtmy $sleep_time;
82a75fececSSteven Rostedtmy $bisect_sleep_time;
83a75fececSSteven Rostedtmy $store_failures;
84a75fececSSteven Rostedtmy $timeout;
85a75fececSSteven Rostedtmy $booted_timeout;
86a75fececSSteven Rostedtmy $console;
87a75fececSSteven Rostedtmy $success_line;
88a75fececSSteven Rostedtmy $build_target;
89a75fececSSteven Rostedtmy $target_image;
90a75fececSSteven Rostedtmy $localversion;
91576f627cSSteven Rostedtmy $iteration = 0;
922545eb61SSteven Rostedt
93a57419b3SSteven Rostedtsub set_value {
94a57419b3SSteven Rostedt    my ($lvalue, $rvalue) = @_;
952545eb61SSteven Rostedt
96a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
97a75fececSSteven Rostedt	die "Error: Option $lvalue defined more than once!\n";
98a75fececSSteven Rostedt    }
992545eb61SSteven Rostedt    $opt{$lvalue} = $rvalue;
1002545eb61SSteven Rostedt}
101a57419b3SSteven Rostedt
102a57419b3SSteven Rostedtsub read_config {
103a57419b3SSteven Rostedt    my ($config) = @_;
104a57419b3SSteven Rostedt
105a57419b3SSteven Rostedt    open(IN, $config) || die "can't read file $config";
106a57419b3SSteven Rostedt
107a57419b3SSteven Rostedt    my $name = $config;
108a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
109a57419b3SSteven Rostedt
110a57419b3SSteven Rostedt    my $test_num = 0;
111a57419b3SSteven Rostedt    my $default = 1;
112a57419b3SSteven Rostedt    my $repeat = 1;
113a57419b3SSteven Rostedt    my $num_tests_set = 0;
114a57419b3SSteven Rostedt    my $skip = 0;
115a57419b3SSteven Rostedt    my $rest;
116a57419b3SSteven Rostedt
117a57419b3SSteven Rostedt    while (<IN>) {
118a57419b3SSteven Rostedt
119a57419b3SSteven Rostedt	# ignore blank lines and comments
120a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
121a57419b3SSteven Rostedt
122a57419b3SSteven Rostedt	if (/^\s*TEST_START(.*)/) {
123a57419b3SSteven Rostedt
124a57419b3SSteven Rostedt	    $rest = $1;
125a57419b3SSteven Rostedt
126a57419b3SSteven Rostedt	    if ($num_tests_set) {
127a57419b3SSteven Rostedt		die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
128a57419b3SSteven Rostedt	    }
129a57419b3SSteven Rostedt
130a57419b3SSteven Rostedt	    my $old_test_num = $test_num;
131a57419b3SSteven Rostedt
132a57419b3SSteven Rostedt	    $test_num += $repeat;
133a57419b3SSteven Rostedt	    $default = 0;
134a57419b3SSteven Rostedt	    $repeat = 1;
135a57419b3SSteven Rostedt
136a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
137a57419b3SSteven Rostedt		$rest = $1;
138a57419b3SSteven Rostedt		$skip = 1;
139a57419b3SSteven Rostedt	    } else {
140a57419b3SSteven Rostedt		$skip = 0;
141a57419b3SSteven Rostedt	    }
142a57419b3SSteven Rostedt
143a57419b3SSteven Rostedt	    if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
144a57419b3SSteven Rostedt		$repeat = $1;
145a57419b3SSteven Rostedt		$rest = $2;
146a57419b3SSteven Rostedt		$repeat_tests{"$test_num"} = $repeat;
147a57419b3SSteven Rostedt	    }
148a57419b3SSteven Rostedt
149a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
150a57419b3SSteven Rostedt		$rest = $1;
151a57419b3SSteven Rostedt		$skip = 1;
152a57419b3SSteven Rostedt	    }
153a57419b3SSteven Rostedt
154a57419b3SSteven Rostedt	    if ($rest !~ /^\s*$/) {
155a57419b3SSteven Rostedt		die "$name: $.: Gargbage found after TEST_START\n$_";
156a57419b3SSteven Rostedt	    }
157a57419b3SSteven Rostedt
158a57419b3SSteven Rostedt	    if ($skip) {
159a57419b3SSteven Rostedt		$test_num = $old_test_num;
160a57419b3SSteven Rostedt		$repeat = 1;
161a57419b3SSteven Rostedt	    }
162a57419b3SSteven Rostedt
163a57419b3SSteven Rostedt	} elsif (/^\s*DEFAULTS(.*)$/) {
164a57419b3SSteven Rostedt	    $default = 1;
165a57419b3SSteven Rostedt
166a57419b3SSteven Rostedt	    $rest = $1;
167a57419b3SSteven Rostedt
168a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
169a57419b3SSteven Rostedt		$rest = $1;
170a57419b3SSteven Rostedt		$skip = 1;
171a57419b3SSteven Rostedt	    } else {
172a57419b3SSteven Rostedt		$skip = 0;
173a57419b3SSteven Rostedt	    }
174a57419b3SSteven Rostedt
175a57419b3SSteven Rostedt	    if ($rest !~ /^\s*$/) {
176a57419b3SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
177a57419b3SSteven Rostedt	    }
178a57419b3SSteven Rostedt
179a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
180a57419b3SSteven Rostedt
181a57419b3SSteven Rostedt	    next if ($skip);
182a57419b3SSteven Rostedt
183a57419b3SSteven Rostedt	    my $lvalue = $1;
184a57419b3SSteven Rostedt	    my $rvalue = $2;
185a57419b3SSteven Rostedt
186a57419b3SSteven Rostedt	    if (!$default &&
187a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
188a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
189a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
190a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
191a57419b3SSteven Rostedt	    }
192a57419b3SSteven Rostedt
193a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
194a57419b3SSteven Rostedt		if ($test_num) {
195a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
196a57419b3SSteven Rostedt		}
197a57419b3SSteven Rostedt		if (!$default) {
198a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
199a57419b3SSteven Rostedt		}
200a57419b3SSteven Rostedt		$num_tests_set = 1;
201a57419b3SSteven Rostedt	    }
202a57419b3SSteven Rostedt
203a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
204a57419b3SSteven Rostedt		set_value($lvalue, $rvalue);
205a57419b3SSteven Rostedt	    } else {
206a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
207a57419b3SSteven Rostedt		set_value($val, $rvalue);
208a57419b3SSteven Rostedt
209a57419b3SSteven Rostedt		if ($repeat > 1) {
210a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
211a57419b3SSteven Rostedt		}
212a57419b3SSteven Rostedt	    }
213a57419b3SSteven Rostedt	} else {
214a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
215a57419b3SSteven Rostedt	}
2162545eb61SSteven Rostedt    }
2172545eb61SSteven Rostedt
2182545eb61SSteven Rostedt    close(IN);
219a75fececSSteven Rostedt
220a57419b3SSteven Rostedt    if ($test_num) {
221a57419b3SSteven Rostedt	$test_num += $repeat - 1;
222a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
223a57419b3SSteven Rostedt    }
224a57419b3SSteven Rostedt
225a75fececSSteven Rostedt    # set any defaults
226a75fececSSteven Rostedt
227a75fececSSteven Rostedt    foreach my $default (keys %default) {
228a75fececSSteven Rostedt	if (!defined($opt{$default})) {
229a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
230a75fececSSteven Rostedt	}
231a75fececSSteven Rostedt    }
2322545eb61SSteven Rostedt}
2332545eb61SSteven Rostedt
234d1e2f22aSSteven Rostedtsub _logit {
2352545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
2362545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
2372545eb61SSteven Rostedt	print OUT @_;
2382545eb61SSteven Rostedt	close(OUT);
2392545eb61SSteven Rostedt    }
2402545eb61SSteven Rostedt}
2412545eb61SSteven Rostedt
242d1e2f22aSSteven Rostedtsub logit {
243d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
244d1e2f22aSSteven Rostedt	_logit @_;
245d1e2f22aSSteven Rostedt    } else {
246d1e2f22aSSteven Rostedt	print @_;
247d1e2f22aSSteven Rostedt    }
248d1e2f22aSSteven Rostedt}
249d1e2f22aSSteven Rostedt
2505f9b6cedSSteven Rostedtsub doprint {
2515f9b6cedSSteven Rostedt    print @_;
252d1e2f22aSSteven Rostedt    _logit @_;
2535f9b6cedSSteven Rostedt}
2545f9b6cedSSteven Rostedt
2557faafbd6SSteven Rostedtsub run_command;
2567faafbd6SSteven Rostedt
2577faafbd6SSteven Rostedtsub reboot {
2587faafbd6SSteven Rostedt    # try to reboot normally
259576f627cSSteven Rostedt    if (run_command "ssh $target reboot") {
260576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
261576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
262576f627cSSteven Rostedt	    run_command "$power_cycle";
263576f627cSSteven Rostedt	}
264576f627cSSteven Rostedt    } else {
2657faafbd6SSteven Rostedt	# nope? power cycle it.
266a75fececSSteven Rostedt	run_command "$power_cycle";
2677faafbd6SSteven Rostedt    }
2687faafbd6SSteven Rostedt}
2697faafbd6SSteven Rostedt
270576f627cSSteven Rostedtsub do_not_reboot {
271576f627cSSteven Rostedt    my $i = $iteration;
272576f627cSSteven Rostedt
273576f627cSSteven Rostedt    return $test_type eq "build" ||
274576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
275576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
276576f627cSSteven Rostedt}
277576f627cSSteven Rostedt
2785c42fc5bSSteven Rostedtsub dodie {
2795a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
2805c42fc5bSSteven Rostedt
281576f627cSSteven Rostedt    my $i = $iteration;
282576f627cSSteven Rostedt
283576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
284576f627cSSteven Rostedt
28575c3fda7SSteven Rostedt	doprint "REBOOTING\n";
2867faafbd6SSteven Rostedt	reboot;
28775c3fda7SSteven Rostedt
288a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
2895c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
290a75fececSSteven Rostedt	`$power_off`;
2915c42fc5bSSteven Rostedt    }
29275c3fda7SSteven Rostedt
293576f627cSSteven Rostedt    die @_, "\n";
2945c42fc5bSSteven Rostedt}
2955c42fc5bSSteven Rostedt
2967faafbd6SSteven Rostedtsub open_console {
2977faafbd6SSteven Rostedt    my ($fp) = @_;
2987faafbd6SSteven Rostedt
2997faafbd6SSteven Rostedt    my $flags;
3007faafbd6SSteven Rostedt
301a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
302a75fececSSteven Rostedt	dodie "Can't open console $console";
3037faafbd6SSteven Rostedt
3047faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
305576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
3067faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
307576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
3087faafbd6SSteven Rostedt
3097faafbd6SSteven Rostedt    return $pid;
3107faafbd6SSteven Rostedt}
3117faafbd6SSteven Rostedt
3127faafbd6SSteven Rostedtsub close_console {
3137faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
3147faafbd6SSteven Rostedt
3157faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
3167faafbd6SSteven Rostedt    kill 2, $pid;
3177faafbd6SSteven Rostedt
3187faafbd6SSteven Rostedt    print "closing!\n";
3197faafbd6SSteven Rostedt    close($fp);
3207faafbd6SSteven Rostedt}
3217faafbd6SSteven Rostedt
3227faafbd6SSteven Rostedtsub start_monitor {
3237faafbd6SSteven Rostedt    if ($monitor_cnt++) {
3247faafbd6SSteven Rostedt	return;
3257faafbd6SSteven Rostedt    }
3267faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
3277faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
328a75fececSSteven Rostedt
329a75fececSSteven Rostedt    return;
330a75fececSSteven Rostedt
331a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
3327faafbd6SSteven Rostedt}
3337faafbd6SSteven Rostedt
3347faafbd6SSteven Rostedtsub end_monitor {
3357faafbd6SSteven Rostedt    if (--$monitor_cnt) {
3367faafbd6SSteven Rostedt	return;
3377faafbd6SSteven Rostedt    }
3387faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
3397faafbd6SSteven Rostedt}
3407faafbd6SSteven Rostedt
3417faafbd6SSteven Rostedtsub wait_for_monitor {
3427faafbd6SSteven Rostedt    my ($time) = @_;
3437faafbd6SSteven Rostedt    my $line;
3447faafbd6SSteven Rostedt
345a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
3467faafbd6SSteven Rostedt
3477faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
3487faafbd6SSteven Rostedt    do {
3497faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
350a75fececSSteven Rostedt	print "$line" if (defined($line));
3517faafbd6SSteven Rostedt    } while (defined($line));
352a75fececSSteven Rostedt    print "** Monitor flushed **\n";
3537faafbd6SSteven Rostedt}
3547faafbd6SSteven Rostedt
3552b7d9b21SSteven Rostedtsub fail {
3562b7d9b21SSteven Rostedt
357a75fececSSteven Rostedt	if ($die_on_failure) {
3582b7d9b21SSteven Rostedt		dodie @_;
3592b7d9b21SSteven Rostedt	}
3602b7d9b21SSteven Rostedt
361a75fececSSteven Rostedt	doprint "FAILED\n";
3627faafbd6SSteven Rostedt
363576f627cSSteven Rostedt	my $i = $iteration;
364576f627cSSteven Rostedt
365a75fececSSteven Rostedt	# no need to reboot for just building.
366576f627cSSteven Rostedt	if (!do_not_reboot) {
3677faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
3687faafbd6SSteven Rostedt	    reboot;
3697faafbd6SSteven Rostedt	    start_monitor;
370a75fececSSteven Rostedt	    wait_for_monitor $sleep_time;
3717faafbd6SSteven Rostedt	    end_monitor;
372a75fececSSteven Rostedt	}
3737faafbd6SSteven Rostedt
374576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
375576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
376a75fececSSteven Rostedt	doprint "**** Failed: ", @_, " ****\n";
377576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
378576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
379a75fececSSteven Rostedt
380a75fececSSteven Rostedt	return 1 if (!defined($store_failures));
3817faafbd6SSteven Rostedt
3827faafbd6SSteven Rostedt	my @t = localtime;
3837faafbd6SSteven Rostedt	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
3847faafbd6SSteven Rostedt		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
3857faafbd6SSteven Rostedt
386a75fececSSteven Rostedt	my $dir = "$machine-$test_type-$build_type-fail-$date";
387a75fececSSteven Rostedt	my $faildir = "$store_failures/$dir";
3887faafbd6SSteven Rostedt
3897faafbd6SSteven Rostedt	if (!-d $faildir) {
3907faafbd6SSteven Rostedt	    mkpath($faildir) or
391a75fececSSteven Rostedt		die "can't create $faildir";
3927faafbd6SSteven Rostedt	}
393*51ad1dd1SSteven Rostedt	if (-f "$output_config") {
394*51ad1dd1SSteven Rostedt	    cp "$output_config", "$faildir/config" or
3957faafbd6SSteven Rostedt		die "failed to copy .config";
3967faafbd6SSteven Rostedt	}
3977faafbd6SSteven Rostedt	if (-f $buildlog) {
3987faafbd6SSteven Rostedt	    cp $buildlog, "$faildir/buildlog" or
3997faafbd6SSteven Rostedt		die "failed to move $buildlog";
4007faafbd6SSteven Rostedt	}
4017faafbd6SSteven Rostedt	if (-f $dmesg) {
4027faafbd6SSteven Rostedt	    cp $dmesg, "$faildir/dmesg" or
4037faafbd6SSteven Rostedt		die "failed to move $dmesg";
4047faafbd6SSteven Rostedt	}
4057faafbd6SSteven Rostedt
4067faafbd6SSteven Rostedt	doprint "*** Saved info to $faildir ***\n";
4077faafbd6SSteven Rostedt
4082b7d9b21SSteven Rostedt	return 1;
4092b7d9b21SSteven Rostedt}
4102b7d9b21SSteven Rostedt
4112545eb61SSteven Rostedtsub run_command {
4122545eb61SSteven Rostedt    my ($command) = @_;
413d6ce2a0bSSteven Rostedt    my $dolog = 0;
414d6ce2a0bSSteven Rostedt    my $dord = 0;
415d6ce2a0bSSteven Rostedt    my $pid;
416d6ce2a0bSSteven Rostedt
417d6ce2a0bSSteven Rostedt    doprint("$command ... ");
418d6ce2a0bSSteven Rostedt
419d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
4202b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
4212545eb61SSteven Rostedt
4222545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
423d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
424d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
425d6ce2a0bSSteven Rostedt	$dolog = 1;
4266c5ee0beSSteven Rostedt    }
4276c5ee0beSSteven Rostedt
4286c5ee0beSSteven Rostedt    if (defined($redirect)) {
429d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
430d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
431d6ce2a0bSSteven Rostedt	$dord = 1;
4322545eb61SSteven Rostedt    }
4332545eb61SSteven Rostedt
434d6ce2a0bSSteven Rostedt    while (<CMD>) {
435d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
436d6ce2a0bSSteven Rostedt	print RD  if ($dord);
437d6ce2a0bSSteven Rostedt    }
4382545eb61SSteven Rostedt
439d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
4402545eb61SSteven Rostedt    my $failed = $?;
4412545eb61SSteven Rostedt
442d6ce2a0bSSteven Rostedt    close(CMD);
443d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
444d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
445d6ce2a0bSSteven Rostedt
4462545eb61SSteven Rostedt    if ($failed) {
4472545eb61SSteven Rostedt	doprint "FAILED!\n";
4482545eb61SSteven Rostedt    } else {
4492545eb61SSteven Rostedt	doprint "SUCCESS\n";
4502545eb61SSteven Rostedt    }
4512545eb61SSteven Rostedt
4525f9b6cedSSteven Rostedt    return !$failed;
4535f9b6cedSSteven Rostedt}
4545f9b6cedSSteven Rostedt
4555f9b6cedSSteven Rostedtsub get_grub_index {
4565f9b6cedSSteven Rostedt
457a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
458a75fececSSteven Rostedt	return;
459a75fececSSteven Rostedt    }
4605a391fbfSSteven Rostedt    return if (defined($grub_number));
4615f9b6cedSSteven Rostedt
4625f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
4635f9b6cedSSteven Rostedt    $grub_number = -1;
4645f9b6cedSSteven Rostedt    open(IN, "ssh $target cat /boot/grub/menu.lst |")
4655f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
4665f9b6cedSSteven Rostedt    while (<IN>) {
467a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
4685f9b6cedSSteven Rostedt	    $grub_number++;
4695f9b6cedSSteven Rostedt	    last;
4705f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
4715f9b6cedSSteven Rostedt	    $grub_number++;
4725f9b6cedSSteven Rostedt	}
4735f9b6cedSSteven Rostedt    }
4745f9b6cedSSteven Rostedt    close(IN);
4755f9b6cedSSteven Rostedt
476a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
4775f9b6cedSSteven Rostedt	if ($grub_number < 0);
4785f9b6cedSSteven Rostedt    doprint "$grub_number\n";
4792545eb61SSteven Rostedt}
4802545eb61SSteven Rostedt
4812545eb61SSteven Rostedtsub wait_for_input
4822545eb61SSteven Rostedt{
4832545eb61SSteven Rostedt    my ($fp, $time) = @_;
4842545eb61SSteven Rostedt    my $rin;
4852545eb61SSteven Rostedt    my $ready;
4862545eb61SSteven Rostedt    my $line;
4872545eb61SSteven Rostedt    my $ch;
4882545eb61SSteven Rostedt
4892545eb61SSteven Rostedt    if (!defined($time)) {
4902545eb61SSteven Rostedt	$time = $timeout;
4912545eb61SSteven Rostedt    }
4922545eb61SSteven Rostedt
4932545eb61SSteven Rostedt    $rin = '';
4942545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
4952545eb61SSteven Rostedt    $ready = select($rin, undef, undef, $time);
4962545eb61SSteven Rostedt
4972545eb61SSteven Rostedt    $line = "";
4982545eb61SSteven Rostedt
4992545eb61SSteven Rostedt    # try to read one char at a time
5002545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
5012545eb61SSteven Rostedt	$line .= $ch;
5022545eb61SSteven Rostedt	last if ($ch eq "\n");
5032545eb61SSteven Rostedt    }
5042545eb61SSteven Rostedt
5052545eb61SSteven Rostedt    if (!length($line)) {
5062545eb61SSteven Rostedt	return undef;
5072545eb61SSteven Rostedt    }
5082545eb61SSteven Rostedt
5092545eb61SSteven Rostedt    return $line;
5102545eb61SSteven Rostedt}
5112545eb61SSteven Rostedt
51275c3fda7SSteven Rostedtsub reboot_to {
513a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
5142545eb61SSteven Rostedt	run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
515a75fececSSteven Rostedt	return;
516a75fececSSteven Rostedt    }
517a75fececSSteven Rostedt
518a75fececSSteven Rostedt    run_command "$reboot_script";
5192545eb61SSteven Rostedt}
5202545eb61SSteven Rostedt
521a57419b3SSteven Rostedtsub get_sha1 {
522a57419b3SSteven Rostedt    my ($commit) = @_;
523a57419b3SSteven Rostedt
524a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
525a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
526a57419b3SSteven Rostedt    my $ret = $?;
527a57419b3SSteven Rostedt
528a57419b3SSteven Rostedt    logit $sha1;
529a57419b3SSteven Rostedt
530a57419b3SSteven Rostedt    if ($ret) {
531a57419b3SSteven Rostedt	doprint "FAILED\n";
532a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
533a57419b3SSteven Rostedt    }
534a57419b3SSteven Rostedt
535a57419b3SSteven Rostedt    print "SUCCESS\n";
536a57419b3SSteven Rostedt
537a57419b3SSteven Rostedt    chomp $sha1;
538a57419b3SSteven Rostedt
539a57419b3SSteven Rostedt    return $sha1;
540a57419b3SSteven Rostedt}
541a57419b3SSteven Rostedt
5425a391fbfSSteven Rostedtsub monitor {
5432545eb61SSteven Rostedt    my $booted = 0;
5442545eb61SSteven Rostedt    my $bug = 0;
5455c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
5462b7d9b21SSteven Rostedt    my $loops;
5472545eb61SSteven Rostedt
5487faafbd6SSteven Rostedt    wait_for_monitor 5;
5492545eb61SSteven Rostedt
5502545eb61SSteven Rostedt    my $line;
5512545eb61SSteven Rostedt    my $full_line = "";
5522545eb61SSteven Rostedt
5537faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
5547faafbd6SSteven Rostedt	die "unable to write to $dmesg";
5552545eb61SSteven Rostedt
55675c3fda7SSteven Rostedt    reboot_to;
5572545eb61SSteven Rostedt
5582545eb61SSteven Rostedt    for (;;) {
5592545eb61SSteven Rostedt
5602b7d9b21SSteven Rostedt	if ($booted) {
561a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
5622b7d9b21SSteven Rostedt	} else {
5637faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
5642b7d9b21SSteven Rostedt	}
5652545eb61SSteven Rostedt
5662545eb61SSteven Rostedt	last if (!defined($line));
5672545eb61SSteven Rostedt
5682545eb61SSteven Rostedt	doprint $line;
5697faafbd6SSteven Rostedt	print DMESG $line;
5702545eb61SSteven Rostedt
5712545eb61SSteven Rostedt	# we are not guaranteed to get a full line
5722545eb61SSteven Rostedt	$full_line .= $line;
5732545eb61SSteven Rostedt
574a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
5752545eb61SSteven Rostedt	    $booted = 1;
5762545eb61SSteven Rostedt	}
5772545eb61SSteven Rostedt
5785c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
5795c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
5805c42fc5bSSteven Rostedt	}
5815c42fc5bSSteven Rostedt
5822545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
5835c42fc5bSSteven Rostedt	    $bug = 1 if (!$skip_call_trace);
5845c42fc5bSSteven Rostedt	}
5855c42fc5bSSteven Rostedt
5865c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
5875c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
5885c42fc5bSSteven Rostedt	}
5895c42fc5bSSteven Rostedt
5905c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
5912545eb61SSteven Rostedt	    $bug = 1;
5922545eb61SSteven Rostedt	}
5932545eb61SSteven Rostedt
5942545eb61SSteven Rostedt	if ($line =~ /\n/) {
5952545eb61SSteven Rostedt	    $full_line = "";
5962545eb61SSteven Rostedt	}
5972545eb61SSteven Rostedt    }
5982545eb61SSteven Rostedt
5997faafbd6SSteven Rostedt    close(DMESG);
6002545eb61SSteven Rostedt
6012545eb61SSteven Rostedt    if ($bug) {
6022b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
603576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
6042545eb61SSteven Rostedt    }
6055f9b6cedSSteven Rostedt
606a75fececSSteven Rostedt    if (!$booted) {
607a75fececSSteven Rostedt	return 0 if ($in_bisect);
608576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
609a75fececSSteven Rostedt    }
610a75fececSSteven Rostedt
6112b7d9b21SSteven Rostedt    return 1;
6122545eb61SSteven Rostedt}
6132545eb61SSteven Rostedt
6142545eb61SSteven Rostedtsub install {
6152545eb61SSteven Rostedt
616a75fececSSteven Rostedt    run_command "scp $outputdir/$build_target $target:$target_image" or
6175c42fc5bSSteven Rostedt	dodie "failed to copy image";
6185f9b6cedSSteven Rostedt
6195f9b6cedSSteven Rostedt    my $install_mods = 0;
6205f9b6cedSSteven Rostedt
6215f9b6cedSSteven Rostedt    # should we process modules?
6225f9b6cedSSteven Rostedt    $install_mods = 0;
623*51ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
6245f9b6cedSSteven Rostedt    while (<IN>) {
6255f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
6265f9b6cedSSteven Rostedt	    $install_mods = 1 if (defined($1));
6275f9b6cedSSteven Rostedt	    last;
6285f9b6cedSSteven Rostedt	}
6295f9b6cedSSteven Rostedt    }
6305f9b6cedSSteven Rostedt    close(IN);
6315f9b6cedSSteven Rostedt
6325f9b6cedSSteven Rostedt    if (!$install_mods) {
6335f9b6cedSSteven Rostedt	doprint "No modules needed\n";
6345f9b6cedSSteven Rostedt	return;
6352545eb61SSteven Rostedt    }
6362545eb61SSteven Rostedt
637a75fececSSteven Rostedt    run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
6385f9b6cedSSteven Rostedt	dodie "Failed to install modules";
6395f9b6cedSSteven Rostedt
6402545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
641a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
6422545eb61SSteven Rostedt
6435f9b6cedSSteven Rostedt    run_command "ssh $target rm -rf $modlib" or
6445c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
6452545eb61SSteven Rostedt
6465c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
647a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
6485c42fc5bSSteven Rostedt	dodie "making tarball";
6495c42fc5bSSteven Rostedt
650a75fececSSteven Rostedt    run_command "scp $tmpdir/$modtar $target:/tmp" or
6515c42fc5bSSteven Rostedt	dodie "failed to copy modules";
6525c42fc5bSSteven Rostedt
653a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
6545c42fc5bSSteven Rostedt
6555f9b6cedSSteven Rostedt    run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or
6565c42fc5bSSteven Rostedt	dodie "failed to tar modules";
6575c42fc5bSSteven Rostedt
6585c42fc5bSSteven Rostedt    run_command "ssh $target rm -f /tmp/$modtar";
6598b37ca8cSSteven Rostedt
6608b37ca8cSSteven Rostedt    return if (!defined($post_install));
6618b37ca8cSSteven Rostedt
6628b37ca8cSSteven Rostedt    my $save_env = $ENV{KERNEL_VERSION};
6638b37ca8cSSteven Rostedt
6648b37ca8cSSteven Rostedt    $ENV{KERNEL_VERSION} = $version;
665576f627cSSteven Rostedt    run_command "$post_install" or
666576f627cSSteven Rostedt	dodie "Failed to run post install";
6678b37ca8cSSteven Rostedt
6688b37ca8cSSteven Rostedt    $ENV{KERNEL_VERSION} = $save_env;
6692545eb61SSteven Rostedt}
6702545eb61SSteven Rostedt
6716c5ee0beSSteven Rostedtsub check_buildlog {
6726c5ee0beSSteven Rostedt    my ($patch) = @_;
6736c5ee0beSSteven Rostedt
6746c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
6756c5ee0beSSteven Rostedt
6766c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
6776c5ee0beSSteven Rostedt	dodie "failed to show $patch";
6786c5ee0beSSteven Rostedt    while (<IN>) {
6796c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
6806c5ee0beSSteven Rostedt	    chomp $1;
6816c5ee0beSSteven Rostedt	    $files[$#files] = $1;
6826c5ee0beSSteven Rostedt	}
6836c5ee0beSSteven Rostedt    }
6846c5ee0beSSteven Rostedt    close(IN);
6856c5ee0beSSteven Rostedt
6866c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
6876c5ee0beSSteven Rostedt    while (<IN>) {
6886c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
6896c5ee0beSSteven Rostedt	    my $err = $1;
6906c5ee0beSSteven Rostedt	    foreach my $file (@files) {
691a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
6926c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
6932b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
6946c5ee0beSSteven Rostedt		}
6956c5ee0beSSteven Rostedt	    }
6966c5ee0beSSteven Rostedt	}
6976c5ee0beSSteven Rostedt    }
6986c5ee0beSSteven Rostedt    close(IN);
6992b7d9b21SSteven Rostedt
7002b7d9b21SSteven Rostedt    return 1;
7016c5ee0beSSteven Rostedt}
7026c5ee0beSSteven Rostedt
7032545eb61SSteven Rostedtsub build {
7042545eb61SSteven Rostedt    my ($type) = @_;
7055c42fc5bSSteven Rostedt    my $defconfig = "";
7062545eb61SSteven Rostedt
7077faafbd6SSteven Rostedt    unlink $buildlog;
7087faafbd6SSteven Rostedt
70975c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
710*51ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
71175c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
7125f9b6cedSSteven Rostedt
71375c3fda7SSteven Rostedt	$type = "oldconfig";
71475c3fda7SSteven Rostedt    }
71575c3fda7SSteven Rostedt
7165c42fc5bSSteven Rostedt    # old config can ask questions
7175c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
7189386c6abSSteven Rostedt	$type = "oldnoconfig";
71975c3fda7SSteven Rostedt
72075c3fda7SSteven Rostedt	# allow for empty configs
721*51ad1dd1SSteven Rostedt	run_command "touch $output_config";
72275c3fda7SSteven Rostedt
723*51ad1dd1SSteven Rostedt	run_command "mv $output_config $outputdir/config_temp" or
7245c42fc5bSSteven Rostedt	    dodie "moving .config";
7255c42fc5bSSteven Rostedt
7265f9b6cedSSteven Rostedt	if (!$noclean && !run_command "$make mrproper") {
7275c42fc5bSSteven Rostedt	    dodie "make mrproper";
7285c42fc5bSSteven Rostedt	}
7295c42fc5bSSteven Rostedt
730*51ad1dd1SSteven Rostedt	run_command "mv $outputdir/config_temp $output_config" or
7315c42fc5bSSteven Rostedt	    dodie "moving config_temp";
7325c42fc5bSSteven Rostedt
7335c42fc5bSSteven Rostedt    } elsif (!$noclean) {
734*51ad1dd1SSteven Rostedt	unlink "$output_config";
7355f9b6cedSSteven Rostedt	run_command "$make mrproper" or
7365c42fc5bSSteven Rostedt	    dodie "make mrproper";
7375c42fc5bSSteven Rostedt    }
7382545eb61SSteven Rostedt
7392545eb61SSteven Rostedt    # add something to distinguish this build
740a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
741a75fececSSteven Rostedt    print OUT "$localversion\n";
7422545eb61SSteven Rostedt    close(OUT);
7432545eb61SSteven Rostedt
7445f9b6cedSSteven Rostedt    if (defined($minconfig)) {
7455f9b6cedSSteven Rostedt	$defconfig = "KCONFIG_ALLCONFIG=$minconfig";
7462545eb61SSteven Rostedt    }
7472545eb61SSteven Rostedt
7489386c6abSSteven Rostedt    run_command "$defconfig $make $type" or
7495c42fc5bSSteven Rostedt	dodie "failed make config";
7502545eb61SSteven Rostedt
751a75fececSSteven Rostedt    $redirect = "$buildlog";
752a75fececSSteven Rostedt    if (!run_command "$make $build_options") {
7536c5ee0beSSteven Rostedt	undef $redirect;
7545f9b6cedSSteven Rostedt	# bisect may need this to pass
7552b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
7562b7d9b21SSteven Rostedt	fail "failed build" and return 0;
7572545eb61SSteven Rostedt    }
7586c5ee0beSSteven Rostedt    undef $redirect;
7595f9b6cedSSteven Rostedt
7602b7d9b21SSteven Rostedt    return 1;
7612545eb61SSteven Rostedt}
7622545eb61SSteven Rostedt
76375c3fda7SSteven Rostedtsub halt {
764a75fececSSteven Rostedt    if (!run_command "ssh $target halt" or defined($power_off)) {
765576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
766576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
767576f627cSSteven Rostedt	    run_command "$power_off";
768576f627cSSteven Rostedt	}
769576f627cSSteven Rostedt    } else {
77075c3fda7SSteven Rostedt	# nope? the zap it!
771a75fececSSteven Rostedt	run_command "$power_off";
77275c3fda7SSteven Rostedt    }
77375c3fda7SSteven Rostedt}
77475c3fda7SSteven Rostedt
7755f9b6cedSSteven Rostedtsub success {
7765f9b6cedSSteven Rostedt    my ($i) = @_;
7775f9b6cedSSteven Rostedt
7785f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
7795f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
780a75fececSSteven Rostedt    doprint     "**           TEST $i SUCCESS!!!!         **\n";
7815f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
7825f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
7835f9b6cedSSteven Rostedt
784576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
785a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
7865f9b6cedSSteven Rostedt	reboot;
7877faafbd6SSteven Rostedt	start_monitor;
788a75fececSSteven Rostedt	wait_for_monitor $sleep_time;
7897faafbd6SSteven Rostedt	end_monitor;
7905f9b6cedSSteven Rostedt    }
7915f9b6cedSSteven Rostedt}
7925f9b6cedSSteven Rostedt
7935f9b6cedSSteven Rostedtsub get_version {
7945f9b6cedSSteven Rostedt    # get the release name
7955f9b6cedSSteven Rostedt    doprint "$make kernelrelease ... ";
7965f9b6cedSSteven Rostedt    $version = `$make kernelrelease | tail -1`;
7975f9b6cedSSteven Rostedt    chomp($version);
7985f9b6cedSSteven Rostedt    doprint "$version\n";
7995f9b6cedSSteven Rostedt}
8005f9b6cedSSteven Rostedt
8015a391fbfSSteven Rostedtsub child_run_test {
8027faafbd6SSteven Rostedt    my $failed = 0;
8035a391fbfSSteven Rostedt
8047faafbd6SSteven Rostedt    # child should have no power
805a75fececSSteven Rostedt    $reboot_on_error = 0;
806a75fececSSteven Rostedt    $poweroff_on_error = 0;
807a75fececSSteven Rostedt    $die_on_failure = 1;
8087faafbd6SSteven Rostedt
8097faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
8105a391fbfSSteven Rostedt    exit $failed;
8115a391fbfSSteven Rostedt}
8125a391fbfSSteven Rostedt
8135a391fbfSSteven Rostedtmy $child_done;
8145a391fbfSSteven Rostedt
8155a391fbfSSteven Rostedtsub child_finished {
8165a391fbfSSteven Rostedt    $child_done = 1;
8175a391fbfSSteven Rostedt}
8185a391fbfSSteven Rostedt
8195a391fbfSSteven Rostedtsub do_run_test {
8205a391fbfSSteven Rostedt    my $child_pid;
8215a391fbfSSteven Rostedt    my $child_exit;
8225a391fbfSSteven Rostedt    my $line;
8235a391fbfSSteven Rostedt    my $full_line;
8245a391fbfSSteven Rostedt    my $bug = 0;
8255a391fbfSSteven Rostedt
8267faafbd6SSteven Rostedt    wait_for_monitor 1;
8275a391fbfSSteven Rostedt
8287faafbd6SSteven Rostedt    doprint "run test $run_test\n";
8295a391fbfSSteven Rostedt
8305a391fbfSSteven Rostedt    $child_done = 0;
8315a391fbfSSteven Rostedt
8325a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
8335a391fbfSSteven Rostedt
8345a391fbfSSteven Rostedt    $child_pid = fork;
8355a391fbfSSteven Rostedt
8365a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
8375a391fbfSSteven Rostedt
8385a391fbfSSteven Rostedt    $full_line = "";
8395a391fbfSSteven Rostedt
8405a391fbfSSteven Rostedt    do {
8417faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
8425a391fbfSSteven Rostedt	if (defined($line)) {
8435a391fbfSSteven Rostedt
8445a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
8455a391fbfSSteven Rostedt	    $full_line .= $line;
8465a391fbfSSteven Rostedt
8475a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
8485a391fbfSSteven Rostedt		$bug = 1;
8495a391fbfSSteven Rostedt	    }
8505a391fbfSSteven Rostedt
8515a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
8525a391fbfSSteven Rostedt		$bug = 1;
8535a391fbfSSteven Rostedt	    }
8545a391fbfSSteven Rostedt
8555a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
8565a391fbfSSteven Rostedt		$full_line = "";
8575a391fbfSSteven Rostedt	    }
8585a391fbfSSteven Rostedt	}
8595a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
8605a391fbfSSteven Rostedt
8615a391fbfSSteven Rostedt    if ($bug) {
8625a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
8635a391fbfSSteven Rostedt	# kill the child with extreme prejudice
8645a391fbfSSteven Rostedt	kill 9, $child_pid;
8655a391fbfSSteven Rostedt    }
8665a391fbfSSteven Rostedt
8675a391fbfSSteven Rostedt    waitpid $child_pid, 0;
8685a391fbfSSteven Rostedt    $child_exit = $?;
8695a391fbfSSteven Rostedt
8705a391fbfSSteven Rostedt    if ($bug || $child_exit) {
8712b7d9b21SSteven Rostedt	return 0 if $in_bisect;
8722b7d9b21SSteven Rostedt	fail "test failed" and return 0;
8735a391fbfSSteven Rostedt    }
8742b7d9b21SSteven Rostedt    return 1;
8755a391fbfSSteven Rostedt}
8765a391fbfSSteven Rostedt
877a75fececSSteven Rostedtsub run_git_bisect {
878a75fececSSteven Rostedt    my ($command) = @_;
879a75fececSSteven Rostedt
880a75fececSSteven Rostedt    doprint "$command ... ";
881a75fececSSteven Rostedt
882a75fececSSteven Rostedt    my $output = `$command 2>&1`;
883a75fececSSteven Rostedt    my $ret = $?;
884a75fececSSteven Rostedt
885a75fececSSteven Rostedt    logit $output;
886a75fececSSteven Rostedt
887a75fececSSteven Rostedt    if ($ret) {
888a75fececSSteven Rostedt	doprint "FAILED\n";
889a75fececSSteven Rostedt	dodie "Failed to git bisect";
890a75fececSSteven Rostedt    }
891a75fececSSteven Rostedt
892a75fececSSteven Rostedt    doprint "SUCCESS\n";
893a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
894a75fececSSteven Rostedt	doprint "$1 [$2]\n";
895a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
896a75fececSSteven Rostedt	$bisect_bad = $1;
897a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
898a75fececSSteven Rostedt	return 0;
899a75fececSSteven Rostedt    } else {
900a75fececSSteven Rostedt	# we already logged it, just print it now.
901a75fececSSteven Rostedt	print $output;
902a75fececSSteven Rostedt    }
903a75fececSSteven Rostedt
904a75fececSSteven Rostedt    return 1;
905a75fececSSteven Rostedt}
906a75fececSSteven Rostedt
9075f9b6cedSSteven Rostedtsub run_bisect {
9085f9b6cedSSteven Rostedt    my ($type) = @_;
9095f9b6cedSSteven Rostedt
9102b7d9b21SSteven Rostedt    my $failed = 0;
9115f9b6cedSSteven Rostedt    my $result;
9125f9b6cedSSteven Rostedt    my $output;
9135f9b6cedSSteven Rostedt    my $ret;
9145f9b6cedSSteven Rostedt
9155f9b6cedSSteven Rostedt    if (defined($minconfig)) {
9162b7d9b21SSteven Rostedt	build "useconfig:$minconfig" or $failed = 1;
9175f9b6cedSSteven Rostedt    } else {
9185f9b6cedSSteven Rostedt	# ?? no config to use?
9192b7d9b21SSteven Rostedt	build "oldconfig" or $failed = 1;
9205f9b6cedSSteven Rostedt    }
9215f9b6cedSSteven Rostedt
9225f9b6cedSSteven Rostedt    if ($type ne "build") {
9237faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
9245f9b6cedSSteven Rostedt
9255f9b6cedSSteven Rostedt	# Now boot the box
9265f9b6cedSSteven Rostedt	get_grub_index;
9275f9b6cedSSteven Rostedt	get_version;
9285f9b6cedSSteven Rostedt	install;
9297faafbd6SSteven Rostedt
9307faafbd6SSteven Rostedt	start_monitor;
9312b7d9b21SSteven Rostedt	monitor or $failed = 1;
9325f9b6cedSSteven Rostedt
9335f9b6cedSSteven Rostedt	if ($type ne "boot") {
9347faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
9355a391fbfSSteven Rostedt
9362b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
9375f9b6cedSSteven Rostedt	}
9387faafbd6SSteven Rostedt	end_monitor;
9395f9b6cedSSteven Rostedt    }
9405f9b6cedSSteven Rostedt
9415f9b6cedSSteven Rostedt    if ($failed) {
9425f9b6cedSSteven Rostedt	$result = "bad";
9435a391fbfSSteven Rostedt
9445a391fbfSSteven Rostedt	# reboot the box to a good kernel
945a75fececSSteven Rostedt	if ($type ne "build") {
946a75fececSSteven Rostedt	    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
9475a391fbfSSteven Rostedt	    reboot;
9487faafbd6SSteven Rostedt	    start_monitor;
949a75fececSSteven Rostedt	    wait_for_monitor $bisect_sleep_time;
9507faafbd6SSteven Rostedt	    end_monitor;
9515a391fbfSSteven Rostedt	}
9525f9b6cedSSteven Rostedt    } else {
9535f9b6cedSSteven Rostedt	$result = "good";
9545f9b6cedSSteven Rostedt    }
9555f9b6cedSSteven Rostedt
956d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
957d6ce2a0bSSteven Rostedt    if ($reverse_bisect) {
958d6ce2a0bSSteven Rostedt	if ($failed) {
959d6ce2a0bSSteven Rostedt	    $result = "good";
960d6ce2a0bSSteven Rostedt	} else {
961d6ce2a0bSSteven Rostedt	    $result = "bad";
962d6ce2a0bSSteven Rostedt	}
963d6ce2a0bSSteven Rostedt    }
964d6ce2a0bSSteven Rostedt
965a75fececSSteven Rostedt    return $result;
9665f9b6cedSSteven Rostedt}
9675f9b6cedSSteven Rostedt
9685f9b6cedSSteven Rostedtsub bisect {
9695f9b6cedSSteven Rostedt    my ($i) = @_;
9705f9b6cedSSteven Rostedt
9715f9b6cedSSteven Rostedt    my $result;
9725f9b6cedSSteven Rostedt
9735f9b6cedSSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($opt{"BISECT_GOOD[$i]"}));
9745f9b6cedSSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($opt{"BISECT_BAD[$i]"}));
9755f9b6cedSSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($opt{"BISECT_TYPE[$i]"}));
9765f9b6cedSSteven Rostedt
9775f9b6cedSSteven Rostedt    my $good = $opt{"BISECT_GOOD[$i]"};
9785f9b6cedSSteven Rostedt    my $bad = $opt{"BISECT_BAD[$i]"};
9795f9b6cedSSteven Rostedt    my $type = $opt{"BISECT_TYPE[$i]"};
980a75fececSSteven Rostedt    my $start = $opt{"BISECT_START[$i]"};
981a75fececSSteven Rostedt    my $replay = $opt{"BISECT_REPLAY[$i]"};
9825f9b6cedSSteven Rostedt
983a57419b3SSteven Rostedt    # convert to true sha1's
984a57419b3SSteven Rostedt    $good = get_sha1($good);
985a57419b3SSteven Rostedt    $bad = get_sha1($bad);
986a57419b3SSteven Rostedt
987d6ce2a0bSSteven Rostedt    if (defined($opt{"BISECT_REVERSE[$i]"}) &&
988d6ce2a0bSSteven Rostedt	$opt{"BISECT_REVERSE[$i]"} == 1) {
989d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
990d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
991d6ce2a0bSSteven Rostedt    } else {
992d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
993d6ce2a0bSSteven Rostedt    }
994d6ce2a0bSSteven Rostedt
9955f9b6cedSSteven Rostedt    $in_bisect = 1;
9965f9b6cedSSteven Rostedt
9975a391fbfSSteven Rostedt    # Can't have a test without having a test to run
9985a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
9995a391fbfSSteven Rostedt	$type = "boot";
10005a391fbfSSteven Rostedt    }
10015a391fbfSSteven Rostedt
1002a75fececSSteven Rostedt    my $check = $opt{"BISECT_CHECK[$i]"};
1003a75fececSSteven Rostedt    if (defined($check) && $check ne "0") {
1004a75fececSSteven Rostedt
1005a75fececSSteven Rostedt	# get current HEAD
1006a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
1007a75fececSSteven Rostedt
1008a75fececSSteven Rostedt	if ($check ne "good") {
1009a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
1010a75fececSSteven Rostedt	    run_command "git checkout $bad" or
1011a75fececSSteven Rostedt		die "Failed to checkout $bad";
1012a75fececSSteven Rostedt
1013a75fececSSteven Rostedt	    $result = run_bisect $type;
1014a75fececSSteven Rostedt
1015a75fececSSteven Rostedt	    if ($result ne "bad") {
1016a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
1017a75fececSSteven Rostedt	    }
1018a75fececSSteven Rostedt	}
1019a75fececSSteven Rostedt
1020a75fececSSteven Rostedt	if ($check ne "bad") {
1021a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
1022a75fececSSteven Rostedt	    run_command "git checkout $good" or
1023a75fececSSteven Rostedt		die "Failed to checkout $good";
1024a75fececSSteven Rostedt
1025a75fececSSteven Rostedt	    $result = run_bisect $type;
1026a75fececSSteven Rostedt
1027a75fececSSteven Rostedt	    if ($result ne "good") {
1028a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
1029a75fececSSteven Rostedt	    }
1030a75fececSSteven Rostedt	}
1031a75fececSSteven Rostedt
1032a75fececSSteven Rostedt	# checkout where we started
1033a75fececSSteven Rostedt	run_command "git checkout $head" or
1034a75fececSSteven Rostedt	    die "Failed to checkout $head";
1035a75fececSSteven Rostedt    }
1036a75fececSSteven Rostedt
1037a75fececSSteven Rostedt    run_command "git bisect start" or
1038a75fececSSteven Rostedt	dodie "could not start bisect";
1039a75fececSSteven Rostedt
1040a75fececSSteven Rostedt    run_command "git bisect good $good" or
1041a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
1042a75fececSSteven Rostedt
1043a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
1044a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
1045a75fececSSteven Rostedt
1046a75fececSSteven Rostedt    if (defined($replay)) {
1047a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
1048a75fececSSteven Rostedt	    dodie "failed to run replay";
1049a75fececSSteven Rostedt    }
1050a75fececSSteven Rostedt
1051a75fececSSteven Rostedt    if (defined($start)) {
1052a75fececSSteven Rostedt	run_command "git checkout $start" or
1053a75fececSSteven Rostedt	    dodie "failed to checkout $start";
1054a75fececSSteven Rostedt    }
1055a75fececSSteven Rostedt
1056a75fececSSteven Rostedt    my $test;
10575f9b6cedSSteven Rostedt    do {
10585f9b6cedSSteven Rostedt	$result = run_bisect $type;
1059a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
1060a75fececSSteven Rostedt    } while ($test);
10615f9b6cedSSteven Rostedt
10625f9b6cedSSteven Rostedt    run_command "git bisect log" or
10635f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
10645f9b6cedSSteven Rostedt
10655f9b6cedSSteven Rostedt    run_command "git bisect reset" or
10665f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
10675f9b6cedSSteven Rostedt
10685f9b6cedSSteven Rostedt    doprint "Bad commit was [$bisect_bad]\n";
10695f9b6cedSSteven Rostedt
10705f9b6cedSSteven Rostedt    $in_bisect = 0;
10715f9b6cedSSteven Rostedt
10725f9b6cedSSteven Rostedt    success $i;
10735f9b6cedSSteven Rostedt}
10745f9b6cedSSteven Rostedt
10756c5ee0beSSteven Rostedtsub patchcheck {
10766c5ee0beSSteven Rostedt    my ($i) = @_;
10776c5ee0beSSteven Rostedt
10786c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
10796c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_START[$i]"}));
10806c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
10816c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
10826c5ee0beSSteven Rostedt
10836c5ee0beSSteven Rostedt    my $start = $opt{"PATCHCHECK_START[$i]"};
10846c5ee0beSSteven Rostedt
10856c5ee0beSSteven Rostedt    my $end = "HEAD";
10866c5ee0beSSteven Rostedt    if (defined($opt{"PATCHCHECK_END[$i]"})) {
10876c5ee0beSSteven Rostedt	$end = $opt{"PATCHCHECK_END[$i]"};
10886c5ee0beSSteven Rostedt    }
10896c5ee0beSSteven Rostedt
1090a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
1091a57419b3SSteven Rostedt    $start = get_sha1($start);
1092a57419b3SSteven Rostedt    $end = get_sha1($end);
1093a57419b3SSteven Rostedt
10946c5ee0beSSteven Rostedt    my $type = $opt{"PATCHCHECK_TYPE[$i]"};
10956c5ee0beSSteven Rostedt
10966c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
10976c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
10986c5ee0beSSteven Rostedt	$type = "boot";
10996c5ee0beSSteven Rostedt    }
11006c5ee0beSSteven Rostedt
11016c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
11026c5ee0beSSteven Rostedt	dodie "could not get git list";
11036c5ee0beSSteven Rostedt
11046c5ee0beSSteven Rostedt    my @list;
11056c5ee0beSSteven Rostedt
11066c5ee0beSSteven Rostedt    while (<IN>) {
11076c5ee0beSSteven Rostedt	chomp;
11086c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
11096c5ee0beSSteven Rostedt	last if (/^$start/);
11106c5ee0beSSteven Rostedt    }
11116c5ee0beSSteven Rostedt    close(IN);
11126c5ee0beSSteven Rostedt
11136c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
11142b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
11156c5ee0beSSteven Rostedt    }
11166c5ee0beSSteven Rostedt
11176c5ee0beSSteven Rostedt    # go backwards in the list
11186c5ee0beSSteven Rostedt    @list = reverse @list;
11196c5ee0beSSteven Rostedt
11206c5ee0beSSteven Rostedt    my $save_clean = $noclean;
11216c5ee0beSSteven Rostedt
11226c5ee0beSSteven Rostedt    $in_patchcheck = 1;
11236c5ee0beSSteven Rostedt    foreach my $item (@list) {
11246c5ee0beSSteven Rostedt	my $sha1 = $item;
11256c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
11266c5ee0beSSteven Rostedt
11276c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
11286c5ee0beSSteven Rostedt
11296c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
11306c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
11316c5ee0beSSteven Rostedt
11326c5ee0beSSteven Rostedt	# only clean on the first and last patch
11336c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
11346c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
11356c5ee0beSSteven Rostedt	    $noclean = $save_clean;
11366c5ee0beSSteven Rostedt	} else {
11376c5ee0beSSteven Rostedt	    $noclean = 1;
11386c5ee0beSSteven Rostedt	}
11396c5ee0beSSteven Rostedt
11406c5ee0beSSteven Rostedt	if (defined($minconfig)) {
11412b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
11426c5ee0beSSteven Rostedt	} else {
11436c5ee0beSSteven Rostedt	    # ?? no config to use?
11442b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
11456c5ee0beSSteven Rostedt	}
11466c5ee0beSSteven Rostedt
11472b7d9b21SSteven Rostedt	check_buildlog $sha1 or return 0;
11486c5ee0beSSteven Rostedt
11496c5ee0beSSteven Rostedt	next if ($type eq "build");
11506c5ee0beSSteven Rostedt
11516c5ee0beSSteven Rostedt	get_grub_index;
11526c5ee0beSSteven Rostedt	get_version;
11536c5ee0beSSteven Rostedt	install;
11546c5ee0beSSteven Rostedt
11557faafbd6SSteven Rostedt	my $failed = 0;
11567faafbd6SSteven Rostedt
11577faafbd6SSteven Rostedt	start_monitor;
11587faafbd6SSteven Rostedt	monitor or $failed = 1;
11597faafbd6SSteven Rostedt
11607faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
11617faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
11627faafbd6SSteven Rostedt	}
11637faafbd6SSteven Rostedt	end_monitor;
11647faafbd6SSteven Rostedt	return 0 if ($failed);
11657faafbd6SSteven Rostedt
11666c5ee0beSSteven Rostedt    }
11676c5ee0beSSteven Rostedt    $in_patchcheck = 0;
11686c5ee0beSSteven Rostedt    success $i;
11692b7d9b21SSteven Rostedt
11702b7d9b21SSteven Rostedt    return 1;
11716c5ee0beSSteven Rostedt}
11726c5ee0beSSteven Rostedt
11732545eb61SSteven Rostedtread_config $ARGV[0];
11742545eb61SSteven Rostedt
11752545eb61SSteven Rostedt# mandatory configs
11762545eb61SSteven Rostedtdie "MACHINE not defined\n"		if (!defined($opt{"MACHINE"}));
11772545eb61SSteven Rostedtdie "SSH_USER not defined\n"		if (!defined($opt{"SSH_USER"}));
11782545eb61SSteven Rostedtdie "BUILD_DIR not defined\n"		if (!defined($opt{"BUILD_DIR"}));
11792545eb61SSteven Rostedtdie "OUTPUT_DIR not defined\n"		if (!defined($opt{"OUTPUT_DIR"}));
11802545eb61SSteven Rostedtdie "BUILD_TARGET not defined\n"	if (!defined($opt{"BUILD_TARGET"}));
118175c3fda7SSteven Rostedtdie "TARGET_IMAGE not defined\n"	if (!defined($opt{"TARGET_IMAGE"}));
11822545eb61SSteven Rostedtdie "POWER_CYCLE not defined\n"		if (!defined($opt{"POWER_CYCLE"}));
11832545eb61SSteven Rostedtdie "CONSOLE not defined\n"		if (!defined($opt{"CONSOLE"}));
11842545eb61SSteven Rostedtdie "LOCALVERSION not defined\n"	if (!defined($opt{"LOCALVERSION"}));
11852545eb61SSteven Rostedt
11862b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
11872b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
11882b7d9b21SSteven Rostedt}
11892545eb61SSteven Rostedt
11902b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
11912b7d9b21SSteven Rostedt
1192a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
1193a57419b3SSteven Rostedt
1194a57419b3SSteven Rostedt    if (!$i) {
1195a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
1196a57419b3SSteven Rostedt    } else {
1197a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
1198a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
1199a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
1200a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
1201a57419b3SSteven Rostedt	}
1202a57419b3SSteven Rostedt	doprint "\n";
1203a57419b3SSteven Rostedt    }
1204a57419b3SSteven Rostedt
12052b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
1206a57419b3SSteven Rostedt
1207a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
1208a57419b3SSteven Rostedt	    next if ($i != $1);
1209a57419b3SSteven Rostedt	} else {
1210a57419b3SSteven Rostedt	    next if ($i);
1211a57419b3SSteven Rostedt	}
1212a57419b3SSteven Rostedt
12132b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
12142b7d9b21SSteven Rostedt    }
1215a57419b3SSteven Rostedt}
12162545eb61SSteven Rostedt
1217a75fececSSteven Rostedtsub set_test_option {
12185a391fbfSSteven Rostedt    my ($name, $i) = @_;
12195a391fbfSSteven Rostedt
12205a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
12215a391fbfSSteven Rostedt
12225a391fbfSSteven Rostedt    if (defined($opt{$option})) {
12235a391fbfSSteven Rostedt	return $opt{$option};
12245a391fbfSSteven Rostedt    }
12255a391fbfSSteven Rostedt
1226a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
1227a57419b3SSteven Rostedt	if ($i >= $test &&
1228a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
1229a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
1230a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
1231a57419b3SSteven Rostedt		return $opt{$option};
1232a57419b3SSteven Rostedt	    }
1233a57419b3SSteven Rostedt	}
1234a57419b3SSteven Rostedt    }
1235a57419b3SSteven Rostedt
12365a391fbfSSteven Rostedt    if (defined($opt{$name})) {
12375a391fbfSSteven Rostedt	return $opt{$name};
12385a391fbfSSteven Rostedt    }
12395a391fbfSSteven Rostedt
12405a391fbfSSteven Rostedt    return undef;
12415a391fbfSSteven Rostedt}
12425a391fbfSSteven Rostedt
12432545eb61SSteven Rostedt# First we need to do is the builds
1244a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
12452545eb61SSteven Rostedt
1246576f627cSSteven Rostedt    $iteration = $i;
1247576f627cSSteven Rostedt
1248a75fececSSteven Rostedt    my $ssh_user = set_test_option("SSH_USER", $i);
1249a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
1250a75fececSSteven Rostedt
1251a75fececSSteven Rostedt    $machine = set_test_option("MACHINE", $i);
1252a75fececSSteven Rostedt    $tmpdir = set_test_option("TMP_DIR", $i);
1253a75fececSSteven Rostedt    $outputdir = set_test_option("OUTPUT_DIR", $i);
1254a75fececSSteven Rostedt    $builddir = set_test_option("BUILD_DIR", $i);
1255a75fececSSteven Rostedt    $test_type = set_test_option("TEST_TYPE", $i);
1256a75fececSSteven Rostedt    $build_type = set_test_option("BUILD_TYPE", $i);
1257a75fececSSteven Rostedt    $build_options = set_test_option("BUILD_OPTIONS", $i);
1258a75fececSSteven Rostedt    $power_cycle = set_test_option("POWER_CYCLE", $i);
1259a75fececSSteven Rostedt    $noclean = set_test_option("BUILD_NOCLEAN", $i);
1260a75fececSSteven Rostedt    $minconfig = set_test_option("MIN_CONFIG", $i);
1261a75fececSSteven Rostedt    $run_test = set_test_option("TEST", $i);
1262a75fececSSteven Rostedt    $addconfig = set_test_option("ADD_CONFIG", $i);
1263a75fececSSteven Rostedt    $reboot_type = set_test_option("REBOOT_TYPE", $i);
1264a75fececSSteven Rostedt    $grub_menu = set_test_option("GRUB_MENU", $i);
12658b37ca8cSSteven Rostedt    $post_install = set_test_option("POST_INSTALL", $i);
1266a75fececSSteven Rostedt    $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
1267a75fececSSteven Rostedt    $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
1268a75fececSSteven Rostedt    $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
1269a75fececSSteven Rostedt    $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
1270a75fececSSteven Rostedt    $power_off = set_test_option("POWER_OFF", $i);
1271576f627cSSteven Rostedt    $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
1272576f627cSSteven Rostedt    $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
1273a75fececSSteven Rostedt    $sleep_time = set_test_option("SLEEP_TIME", $i);
1274a75fececSSteven Rostedt    $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
1275a75fececSSteven Rostedt    $store_failures = set_test_option("STORE_FAILURES", $i);
1276a75fececSSteven Rostedt    $timeout = set_test_option("TIMEOUT", $i);
1277a75fececSSteven Rostedt    $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
1278a75fececSSteven Rostedt    $console = set_test_option("CONSOLE", $i);
1279a75fececSSteven Rostedt    $success_line = set_test_option("SUCCESS_LINE", $i);
1280a75fececSSteven Rostedt    $build_target = set_test_option("BUILD_TARGET", $i);
1281a75fececSSteven Rostedt    $target_image = set_test_option("TARGET_IMAGE", $i);
1282a75fececSSteven Rostedt    $localversion = set_test_option("LOCALVERSION", $i);
1283a75fececSSteven Rostedt
1284a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
1285a75fececSSteven Rostedt
1286a75fececSSteven Rostedt    if (!-d $tmpdir) {
1287a75fececSSteven Rostedt	mkpath($tmpdir) or
1288a75fececSSteven Rostedt	    die "can't create $tmpdir";
1289a75fececSSteven Rostedt    }
1290a75fececSSteven Rostedt
1291a75fececSSteven Rostedt    $target = "$ssh_user\@$machine";
1292a75fececSSteven Rostedt
1293a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
1294a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
1295a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
1296*51ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
1297a75fececSSteven Rostedt
1298a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
1299576f627cSSteven Rostedt	dodie "GRUB_MENU not defined" if (!defined($grub_menu));
1300a75fececSSteven Rostedt    } elsif (!defined($reboot_script)) {
1301576f627cSSteven Rostedt	dodie "REBOOT_SCRIPT not defined"
1302a75fececSSteven Rostedt    }
1303a75fececSSteven Rostedt
1304a75fececSSteven Rostedt    my $run_type = $build_type;
1305a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
1306a75fececSSteven Rostedt	$run_type = $opt{"PATCHCHECK_TYPE[$i]"};
1307a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
1308a75fececSSteven Rostedt	$run_type = $opt{"BISECT_TYPE[$i]"};
1309a75fececSSteven Rostedt    }
1310a75fececSSteven Rostedt
1311a75fececSSteven Rostedt    # mistake in config file?
1312a75fececSSteven Rostedt    if (!defined($run_type)) {
1313a75fececSSteven Rostedt	$run_type = "ERROR";
1314a75fececSSteven Rostedt    }
13152545eb61SSteven Rostedt
13162545eb61SSteven Rostedt    doprint "\n\n";
1317a75fececSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
13187faafbd6SSteven Rostedt
13197faafbd6SSteven Rostedt    unlink $dmesg;
13207faafbd6SSteven Rostedt    unlink $buildlog;
13212545eb61SSteven Rostedt
13222b7d9b21SSteven Rostedt    if (!defined($minconfig)) {
13232b7d9b21SSteven Rostedt	$minconfig = $addconfig;
13242b7d9b21SSteven Rostedt
13252b7d9b21SSteven Rostedt    } elsif (defined($addconfig)) {
1326a75fececSSteven Rostedt	run_command "cat $addconfig $minconfig > $tmpdir/use_config" or
13272b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
1328a75fececSSteven Rostedt	$minconfig = "$tmpdir/use_config";
13292b7d9b21SSteven Rostedt    }
13302b7d9b21SSteven Rostedt
13316c5ee0beSSteven Rostedt    my $checkout = $opt{"CHECKOUT[$i]"};
13326c5ee0beSSteven Rostedt    if (defined($checkout)) {
13336c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
13346c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
13356c5ee0beSSteven Rostedt    }
13366c5ee0beSSteven Rostedt
1337a75fececSSteven Rostedt    if ($test_type eq "bisect") {
13385f9b6cedSSteven Rostedt	bisect $i;
13395f9b6cedSSteven Rostedt	next;
1340a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
13416c5ee0beSSteven Rostedt	patchcheck $i;
13426c5ee0beSSteven Rostedt	next;
13435f9b6cedSSteven Rostedt    }
13445f9b6cedSSteven Rostedt
13457faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
13467faafbd6SSteven Rostedt	build $build_type or next;
13472545eb61SSteven Rostedt    }
13482545eb61SSteven Rostedt
1349a75fececSSteven Rostedt    if ($test_type ne "build") {
13505f9b6cedSSteven Rostedt	get_grub_index;
13515f9b6cedSSteven Rostedt	get_version;
13522545eb61SSteven Rostedt	install;
13535a391fbfSSteven Rostedt
13547faafbd6SSteven Rostedt	my $failed = 0;
13557faafbd6SSteven Rostedt	start_monitor;
13567faafbd6SSteven Rostedt	monitor or $failed = 1;;
1357a75fececSSteven Rostedt
1358a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
13597faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
13605a391fbfSSteven Rostedt	}
13617faafbd6SSteven Rostedt	end_monitor;
13627faafbd6SSteven Rostedt	next if ($failed);
1363a75fececSSteven Rostedt    }
13645a391fbfSSteven Rostedt
13655f9b6cedSSteven Rostedt    success $i;
136675c3fda7SSteven Rostedt}
13672545eb61SSteven Rostedt
13685c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
136975c3fda7SSteven Rostedt    halt;
1370576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
137175c3fda7SSteven Rostedt    reboot;
13725c42fc5bSSteven Rostedt}
137375c3fda7SSteven Rostedt
13742545eb61SSteven Rostedtexit 0;
1375