xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision f1a27850095ebc66c138c940c1efedb8a95f92c4)
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
14e48c5293SSteven Rostedtmy $VERSION = "0.2";
15e48c5293SSteven Rostedt
16e48c5293SSteven Rostedt$#ARGV >= 0 || die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
172545eb61SSteven Rostedt
182545eb61SSteven Rostedt$| = 1;
192545eb61SSteven Rostedt
202545eb61SSteven Rostedtmy %opt;
21a57419b3SSteven Rostedtmy %repeat_tests;
22a57419b3SSteven Rostedtmy %repeats;
23a75fececSSteven Rostedtmy %default;
242545eb61SSteven Rostedt
252545eb61SSteven Rostedt#default opts
26a57419b3SSteven Rostedt$default{"NUM_TESTS"}		= 1;
27a75fececSSteven Rostedt$default{"REBOOT_TYPE"}		= "grub";
28a75fececSSteven Rostedt$default{"TEST_TYPE"}		= "test";
29a75fececSSteven Rostedt$default{"BUILD_TYPE"}		= "randconfig";
30a75fececSSteven Rostedt$default{"MAKE_CMD"}		= "make";
31a75fececSSteven Rostedt$default{"TIMEOUT"}		= 120;
32a57419b3SSteven Rostedt$default{"TMP_DIR"}		= "/tmp/ktest";
33a75fececSSteven Rostedt$default{"SLEEP_TIME"}		= 60;	# sleep time between tests
34a75fececSSteven Rostedt$default{"BUILD_NOCLEAN"}	= 0;
35a75fececSSteven Rostedt$default{"REBOOT_ON_ERROR"}	= 0;
36a75fececSSteven Rostedt$default{"POWEROFF_ON_ERROR"}	= 0;
37a75fececSSteven Rostedt$default{"REBOOT_ON_SUCCESS"}	= 1;
38a75fececSSteven Rostedt$default{"POWEROFF_ON_SUCCESS"}	= 0;
39a75fececSSteven Rostedt$default{"BUILD_OPTIONS"}	= "";
40a75fececSSteven Rostedt$default{"BISECT_SLEEP_TIME"}	= 60;   # sleep time between bisects
41a75fececSSteven Rostedt$default{"CLEAR_LOG"}		= 0;
42a75fececSSteven Rostedt$default{"SUCCESS_LINE"}	= "login:";
43a75fececSSteven Rostedt$default{"BOOTED_TIMEOUT"}	= 1;
44a75fececSSteven Rostedt$default{"DIE_ON_FAILURE"}	= 1;
45e48c5293SSteven Rostedt$default{"SSH_EXEC"}		= "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
46e48c5293SSteven Rostedt$default{"SCP_TO_TARGET"}	= "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE";
47e48c5293SSteven Rostedt$default{"REBOOT"}		= "ssh \$SSH_USER\@\$MACHINE reboot";
481c8a617aSSteven Rostedt$default{"STOP_AFTER_SUCCESS"}	= 10;
491c8a617aSSteven Rostedt$default{"STOP_AFTER_FAILURE"}	= 60;
502545eb61SSteven Rostedt
512545eb61SSteven Rostedtmy $version;
52a75fececSSteven Rostedtmy $machine;
53e48c5293SSteven Rostedtmy $ssh_user;
54a75fececSSteven Rostedtmy $tmpdir;
55a75fececSSteven Rostedtmy $builddir;
56a75fececSSteven Rostedtmy $outputdir;
5751ad1dd1SSteven Rostedtmy $output_config;
58a75fececSSteven Rostedtmy $test_type;
597faafbd6SSteven Rostedtmy $build_type;
60a75fececSSteven Rostedtmy $build_options;
61a75fececSSteven Rostedtmy $reboot_type;
62a75fececSSteven Rostedtmy $reboot_script;
63a75fececSSteven Rostedtmy $power_cycle;
64e48c5293SSteven Rostedtmy $reboot;
65a75fececSSteven Rostedtmy $reboot_on_error;
66a75fececSSteven Rostedtmy $poweroff_on_error;
67a75fececSSteven Rostedtmy $die_on_failure;
68576f627cSSteven Rostedtmy $powercycle_after_reboot;
69576f627cSSteven Rostedtmy $poweroff_after_halt;
70e48c5293SSteven Rostedtmy $ssh_exec;
71e48c5293SSteven Rostedtmy $scp_to_target;
72a75fececSSteven Rostedtmy $power_off;
73a75fececSSteven Rostedtmy $grub_menu;
742545eb61SSteven Rostedtmy $grub_number;
752545eb61SSteven Rostedtmy $target;
762545eb61SSteven Rostedtmy $make;
778b37ca8cSSteven Rostedtmy $post_install;
785c42fc5bSSteven Rostedtmy $noclean;
795f9b6cedSSteven Rostedtmy $minconfig;
802b7d9b21SSteven Rostedtmy $addconfig;
815f9b6cedSSteven Rostedtmy $in_bisect = 0;
825f9b6cedSSteven Rostedtmy $bisect_bad = "";
83d6ce2a0bSSteven Rostedtmy $reverse_bisect;
846c5ee0beSSteven Rostedtmy $in_patchcheck = 0;
855a391fbfSSteven Rostedtmy $run_test;
866c5ee0beSSteven Rostedtmy $redirect;
877faafbd6SSteven Rostedtmy $buildlog;
887faafbd6SSteven Rostedtmy $dmesg;
897faafbd6SSteven Rostedtmy $monitor_fp;
907faafbd6SSteven Rostedtmy $monitor_pid;
917faafbd6SSteven Rostedtmy $monitor_cnt = 0;
92a75fececSSteven Rostedtmy $sleep_time;
93a75fececSSteven Rostedtmy $bisect_sleep_time;
94a75fececSSteven Rostedtmy $store_failures;
95a75fececSSteven Rostedtmy $timeout;
96a75fececSSteven Rostedtmy $booted_timeout;
97a75fececSSteven Rostedtmy $console;
98a75fececSSteven Rostedtmy $success_line;
991c8a617aSSteven Rostedtmy $stop_after_success;
1001c8a617aSSteven Rostedtmy $stop_after_failure;
101a75fececSSteven Rostedtmy $build_target;
102a75fececSSteven Rostedtmy $target_image;
103a75fececSSteven Rostedtmy $localversion;
104576f627cSSteven Rostedtmy $iteration = 0;
105e48c5293SSteven Rostedtmy $successes = 0;
1062545eb61SSteven Rostedt
107a57419b3SSteven Rostedtsub set_value {
108a57419b3SSteven Rostedt    my ($lvalue, $rvalue) = @_;
1092545eb61SSteven Rostedt
110a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
111a75fececSSteven Rostedt	die "Error: Option $lvalue defined more than once!\n";
112a75fececSSteven Rostedt    }
11321a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
11421a9679fSSteven Rostedt	delete $opt{$lvalue};
11521a9679fSSteven Rostedt    } else {
11621a9679fSSteven Rostedt	$opt{$lvalue} = $rvalue;
11721a9679fSSteven Rostedt    }
1182545eb61SSteven Rostedt}
119a57419b3SSteven Rostedt
120a57419b3SSteven Rostedtsub read_config {
121a57419b3SSteven Rostedt    my ($config) = @_;
122a57419b3SSteven Rostedt
123a57419b3SSteven Rostedt    open(IN, $config) || die "can't read file $config";
124a57419b3SSteven Rostedt
125a57419b3SSteven Rostedt    my $name = $config;
126a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
127a57419b3SSteven Rostedt
128a57419b3SSteven Rostedt    my $test_num = 0;
129a57419b3SSteven Rostedt    my $default = 1;
130a57419b3SSteven Rostedt    my $repeat = 1;
131a57419b3SSteven Rostedt    my $num_tests_set = 0;
132a57419b3SSteven Rostedt    my $skip = 0;
133a57419b3SSteven Rostedt    my $rest;
134a57419b3SSteven Rostedt
135a57419b3SSteven Rostedt    while (<IN>) {
136a57419b3SSteven Rostedt
137a57419b3SSteven Rostedt	# ignore blank lines and comments
138a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
139a57419b3SSteven Rostedt
140a57419b3SSteven Rostedt	if (/^\s*TEST_START(.*)/) {
141a57419b3SSteven Rostedt
142a57419b3SSteven Rostedt	    $rest = $1;
143a57419b3SSteven Rostedt
144a57419b3SSteven Rostedt	    if ($num_tests_set) {
145a57419b3SSteven Rostedt		die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
146a57419b3SSteven Rostedt	    }
147a57419b3SSteven Rostedt
148a57419b3SSteven Rostedt	    my $old_test_num = $test_num;
149e48c5293SSteven Rostedt	    my $old_repeat = $repeat;
150a57419b3SSteven Rostedt
151a57419b3SSteven Rostedt	    $test_num += $repeat;
152a57419b3SSteven Rostedt	    $default = 0;
153a57419b3SSteven Rostedt	    $repeat = 1;
154a57419b3SSteven Rostedt
155a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
156a57419b3SSteven Rostedt		$rest = $1;
157a57419b3SSteven Rostedt		$skip = 1;
158a57419b3SSteven Rostedt	    } else {
159a57419b3SSteven Rostedt		$skip = 0;
160a57419b3SSteven Rostedt	    }
161a57419b3SSteven Rostedt
162a57419b3SSteven Rostedt	    if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
163a57419b3SSteven Rostedt		$repeat = $1;
164a57419b3SSteven Rostedt		$rest = $2;
165a57419b3SSteven Rostedt		$repeat_tests{"$test_num"} = $repeat;
166a57419b3SSteven Rostedt	    }
167a57419b3SSteven Rostedt
168a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
169a57419b3SSteven Rostedt		$rest = $1;
170a57419b3SSteven Rostedt		$skip = 1;
171a57419b3SSteven Rostedt	    }
172a57419b3SSteven Rostedt
173a57419b3SSteven Rostedt	    if ($rest !~ /^\s*$/) {
174a57419b3SSteven Rostedt		die "$name: $.: Gargbage found after TEST_START\n$_";
175a57419b3SSteven Rostedt	    }
176a57419b3SSteven Rostedt
177a57419b3SSteven Rostedt	    if ($skip) {
178a57419b3SSteven Rostedt		$test_num = $old_test_num;
179e48c5293SSteven Rostedt		$repeat = $old_repeat;
180a57419b3SSteven Rostedt	    }
181a57419b3SSteven Rostedt
182a57419b3SSteven Rostedt	} elsif (/^\s*DEFAULTS(.*)$/) {
183a57419b3SSteven Rostedt	    $default = 1;
184a57419b3SSteven Rostedt
185a57419b3SSteven Rostedt	    $rest = $1;
186a57419b3SSteven Rostedt
187a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
188a57419b3SSteven Rostedt		$rest = $1;
189a57419b3SSteven Rostedt		$skip = 1;
190a57419b3SSteven Rostedt	    } else {
191a57419b3SSteven Rostedt		$skip = 0;
192a57419b3SSteven Rostedt	    }
193a57419b3SSteven Rostedt
194a57419b3SSteven Rostedt	    if ($rest !~ /^\s*$/) {
195a57419b3SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
196a57419b3SSteven Rostedt	    }
197a57419b3SSteven Rostedt
198a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
199a57419b3SSteven Rostedt
200a57419b3SSteven Rostedt	    next if ($skip);
201a57419b3SSteven Rostedt
202a57419b3SSteven Rostedt	    my $lvalue = $1;
203a57419b3SSteven Rostedt	    my $rvalue = $2;
204a57419b3SSteven Rostedt
205a57419b3SSteven Rostedt	    if (!$default &&
206a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
207a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
208a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
209a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
210a57419b3SSteven Rostedt	    }
211a57419b3SSteven Rostedt
212a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
213a57419b3SSteven Rostedt		if ($test_num) {
214a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
215a57419b3SSteven Rostedt		}
216a57419b3SSteven Rostedt		if (!$default) {
217a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
218a57419b3SSteven Rostedt		}
219a57419b3SSteven Rostedt		$num_tests_set = 1;
220a57419b3SSteven Rostedt	    }
221a57419b3SSteven Rostedt
222a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
223a57419b3SSteven Rostedt		set_value($lvalue, $rvalue);
224a57419b3SSteven Rostedt	    } else {
225a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
226a57419b3SSteven Rostedt		set_value($val, $rvalue);
227a57419b3SSteven Rostedt
228a57419b3SSteven Rostedt		if ($repeat > 1) {
229a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
230a57419b3SSteven Rostedt		}
231a57419b3SSteven Rostedt	    }
232a57419b3SSteven Rostedt	} else {
233a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
234a57419b3SSteven Rostedt	}
2352545eb61SSteven Rostedt    }
2362545eb61SSteven Rostedt
2372545eb61SSteven Rostedt    close(IN);
238a75fececSSteven Rostedt
239a57419b3SSteven Rostedt    if ($test_num) {
240a57419b3SSteven Rostedt	$test_num += $repeat - 1;
241a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
242a57419b3SSteven Rostedt    }
243a57419b3SSteven Rostedt
244a75fececSSteven Rostedt    # set any defaults
245a75fececSSteven Rostedt
246a75fececSSteven Rostedt    foreach my $default (keys %default) {
247a75fececSSteven Rostedt	if (!defined($opt{$default})) {
248a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
249a75fececSSteven Rostedt	}
250a75fececSSteven Rostedt    }
2512545eb61SSteven Rostedt}
2522545eb61SSteven Rostedt
253d1e2f22aSSteven Rostedtsub _logit {
2542545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
2552545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
2562545eb61SSteven Rostedt	print OUT @_;
2572545eb61SSteven Rostedt	close(OUT);
2582545eb61SSteven Rostedt    }
2592545eb61SSteven Rostedt}
2602545eb61SSteven Rostedt
261d1e2f22aSSteven Rostedtsub logit {
262d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
263d1e2f22aSSteven Rostedt	_logit @_;
264d1e2f22aSSteven Rostedt    } else {
265d1e2f22aSSteven Rostedt	print @_;
266d1e2f22aSSteven Rostedt    }
267d1e2f22aSSteven Rostedt}
268d1e2f22aSSteven Rostedt
2695f9b6cedSSteven Rostedtsub doprint {
2705f9b6cedSSteven Rostedt    print @_;
271d1e2f22aSSteven Rostedt    _logit @_;
2725f9b6cedSSteven Rostedt}
2735f9b6cedSSteven Rostedt
2747faafbd6SSteven Rostedtsub run_command;
2757faafbd6SSteven Rostedt
2767faafbd6SSteven Rostedtsub reboot {
2777faafbd6SSteven Rostedt    # try to reboot normally
278e48c5293SSteven Rostedt    if (run_command $reboot) {
279576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
280576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
281576f627cSSteven Rostedt	    run_command "$power_cycle";
282576f627cSSteven Rostedt	}
283576f627cSSteven Rostedt    } else {
2847faafbd6SSteven Rostedt	# nope? power cycle it.
285a75fececSSteven Rostedt	run_command "$power_cycle";
2867faafbd6SSteven Rostedt    }
2877faafbd6SSteven Rostedt}
2887faafbd6SSteven Rostedt
289576f627cSSteven Rostedtsub do_not_reboot {
290576f627cSSteven Rostedt    my $i = $iteration;
291576f627cSSteven Rostedt
292576f627cSSteven Rostedt    return $test_type eq "build" ||
293576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
294576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
295576f627cSSteven Rostedt}
296576f627cSSteven Rostedt
2975c42fc5bSSteven Rostedtsub dodie {
2985a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
2995c42fc5bSSteven Rostedt
300576f627cSSteven Rostedt    my $i = $iteration;
301576f627cSSteven Rostedt
302576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
303576f627cSSteven Rostedt
30475c3fda7SSteven Rostedt	doprint "REBOOTING\n";
3057faafbd6SSteven Rostedt	reboot;
30675c3fda7SSteven Rostedt
307a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
3085c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
309a75fececSSteven Rostedt	`$power_off`;
3105c42fc5bSSteven Rostedt    }
31175c3fda7SSteven Rostedt
312576f627cSSteven Rostedt    die @_, "\n";
3135c42fc5bSSteven Rostedt}
3145c42fc5bSSteven Rostedt
3157faafbd6SSteven Rostedtsub open_console {
3167faafbd6SSteven Rostedt    my ($fp) = @_;
3177faafbd6SSteven Rostedt
3187faafbd6SSteven Rostedt    my $flags;
3197faafbd6SSteven Rostedt
320a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
321a75fececSSteven Rostedt	dodie "Can't open console $console";
3227faafbd6SSteven Rostedt
3237faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
324576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
3257faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
326576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
3277faafbd6SSteven Rostedt
3287faafbd6SSteven Rostedt    return $pid;
3297faafbd6SSteven Rostedt}
3307faafbd6SSteven Rostedt
3317faafbd6SSteven Rostedtsub close_console {
3327faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
3337faafbd6SSteven Rostedt
3347faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
3357faafbd6SSteven Rostedt    kill 2, $pid;
3367faafbd6SSteven Rostedt
3377faafbd6SSteven Rostedt    print "closing!\n";
3387faafbd6SSteven Rostedt    close($fp);
3397faafbd6SSteven Rostedt}
3407faafbd6SSteven Rostedt
3417faafbd6SSteven Rostedtsub start_monitor {
3427faafbd6SSteven Rostedt    if ($monitor_cnt++) {
3437faafbd6SSteven Rostedt	return;
3447faafbd6SSteven Rostedt    }
3457faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
3467faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
347a75fececSSteven Rostedt
348a75fececSSteven Rostedt    return;
349a75fececSSteven Rostedt
350a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
3517faafbd6SSteven Rostedt}
3527faafbd6SSteven Rostedt
3537faafbd6SSteven Rostedtsub end_monitor {
3547faafbd6SSteven Rostedt    if (--$monitor_cnt) {
3557faafbd6SSteven Rostedt	return;
3567faafbd6SSteven Rostedt    }
3577faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
3587faafbd6SSteven Rostedt}
3597faafbd6SSteven Rostedt
3607faafbd6SSteven Rostedtsub wait_for_monitor {
3617faafbd6SSteven Rostedt    my ($time) = @_;
3627faafbd6SSteven Rostedt    my $line;
3637faafbd6SSteven Rostedt
364a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
3657faafbd6SSteven Rostedt
3667faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
3677faafbd6SSteven Rostedt    do {
3687faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
369a75fececSSteven Rostedt	print "$line" if (defined($line));
3707faafbd6SSteven Rostedt    } while (defined($line));
371a75fececSSteven Rostedt    print "** Monitor flushed **\n";
3727faafbd6SSteven Rostedt}
3737faafbd6SSteven Rostedt
3742b7d9b21SSteven Rostedtsub fail {
3752b7d9b21SSteven Rostedt
376a75fececSSteven Rostedt	if ($die_on_failure) {
3772b7d9b21SSteven Rostedt		dodie @_;
3782b7d9b21SSteven Rostedt	}
3792b7d9b21SSteven Rostedt
380a75fececSSteven Rostedt	doprint "FAILED\n";
3817faafbd6SSteven Rostedt
382576f627cSSteven Rostedt	my $i = $iteration;
383576f627cSSteven Rostedt
384a75fececSSteven Rostedt	# no need to reboot for just building.
385576f627cSSteven Rostedt	if (!do_not_reboot) {
3867faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
3877faafbd6SSteven Rostedt	    reboot;
3887faafbd6SSteven Rostedt	    start_monitor;
389a75fececSSteven Rostedt	    wait_for_monitor $sleep_time;
3907faafbd6SSteven Rostedt	    end_monitor;
391a75fececSSteven Rostedt	}
3927faafbd6SSteven Rostedt
393576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
394576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
3957a849cd9SSteven Rostedt	doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n";
396576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
397576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
398a75fececSSteven Rostedt
399a75fececSSteven Rostedt	return 1 if (!defined($store_failures));
4007faafbd6SSteven Rostedt
4017faafbd6SSteven Rostedt	my @t = localtime;
4027faafbd6SSteven Rostedt	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
4037faafbd6SSteven Rostedt		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
4047faafbd6SSteven Rostedt
405cccae1a6SSteven Rostedt	my $type = $build_type;
406cccae1a6SSteven Rostedt	if ($type =~ /useconfig/) {
407cccae1a6SSteven Rostedt	    $type = "useconfig";
408cccae1a6SSteven Rostedt	}
409cccae1a6SSteven Rostedt
410cccae1a6SSteven Rostedt	my $dir = "$machine-$test_type-$type-fail-$date";
411a75fececSSteven Rostedt	my $faildir = "$store_failures/$dir";
4127faafbd6SSteven Rostedt
4137faafbd6SSteven Rostedt	if (!-d $faildir) {
4147faafbd6SSteven Rostedt	    mkpath($faildir) or
415a75fececSSteven Rostedt		die "can't create $faildir";
4167faafbd6SSteven Rostedt	}
41751ad1dd1SSteven Rostedt	if (-f "$output_config") {
41851ad1dd1SSteven Rostedt	    cp "$output_config", "$faildir/config" or
4197faafbd6SSteven Rostedt		die "failed to copy .config";
4207faafbd6SSteven Rostedt	}
4217faafbd6SSteven Rostedt	if (-f $buildlog) {
4227faafbd6SSteven Rostedt	    cp $buildlog, "$faildir/buildlog" or
4237faafbd6SSteven Rostedt		die "failed to move $buildlog";
4247faafbd6SSteven Rostedt	}
4257faafbd6SSteven Rostedt	if (-f $dmesg) {
4267faafbd6SSteven Rostedt	    cp $dmesg, "$faildir/dmesg" or
4277faafbd6SSteven Rostedt		die "failed to move $dmesg";
4287faafbd6SSteven Rostedt	}
4297faafbd6SSteven Rostedt
4307faafbd6SSteven Rostedt	doprint "*** Saved info to $faildir ***\n";
4317faafbd6SSteven Rostedt
4322b7d9b21SSteven Rostedt	return 1;
4332b7d9b21SSteven Rostedt}
4342b7d9b21SSteven Rostedt
4352545eb61SSteven Rostedtsub run_command {
4362545eb61SSteven Rostedt    my ($command) = @_;
437d6ce2a0bSSteven Rostedt    my $dolog = 0;
438d6ce2a0bSSteven Rostedt    my $dord = 0;
439d6ce2a0bSSteven Rostedt    my $pid;
440d6ce2a0bSSteven Rostedt
441e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
442e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
443e48c5293SSteven Rostedt
444d6ce2a0bSSteven Rostedt    doprint("$command ... ");
445d6ce2a0bSSteven Rostedt
446d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
4472b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
4482545eb61SSteven Rostedt
4492545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
450d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
451d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
452d6ce2a0bSSteven Rostedt	$dolog = 1;
4536c5ee0beSSteven Rostedt    }
4546c5ee0beSSteven Rostedt
4556c5ee0beSSteven Rostedt    if (defined($redirect)) {
456d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
457d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
458d6ce2a0bSSteven Rostedt	$dord = 1;
4592545eb61SSteven Rostedt    }
4602545eb61SSteven Rostedt
461d6ce2a0bSSteven Rostedt    while (<CMD>) {
462d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
463d6ce2a0bSSteven Rostedt	print RD  if ($dord);
464d6ce2a0bSSteven Rostedt    }
4652545eb61SSteven Rostedt
466d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
4672545eb61SSteven Rostedt    my $failed = $?;
4682545eb61SSteven Rostedt
469d6ce2a0bSSteven Rostedt    close(CMD);
470d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
471d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
472d6ce2a0bSSteven Rostedt
4732545eb61SSteven Rostedt    if ($failed) {
4742545eb61SSteven Rostedt	doprint "FAILED!\n";
4752545eb61SSteven Rostedt    } else {
4762545eb61SSteven Rostedt	doprint "SUCCESS\n";
4772545eb61SSteven Rostedt    }
4782545eb61SSteven Rostedt
4795f9b6cedSSteven Rostedt    return !$failed;
4805f9b6cedSSteven Rostedt}
4815f9b6cedSSteven Rostedt
482e48c5293SSteven Rostedtsub run_ssh {
483e48c5293SSteven Rostedt    my ($cmd) = @_;
484e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
485e48c5293SSteven Rostedt
486e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
487e48c5293SSteven Rostedt    return run_command "$cp_exec";
488e48c5293SSteven Rostedt}
489e48c5293SSteven Rostedt
490e48c5293SSteven Rostedtsub run_scp {
491e48c5293SSteven Rostedt    my ($src, $dst) = @_;
492e48c5293SSteven Rostedt    my $cp_scp = $scp_to_target;
493e48c5293SSteven Rostedt
494e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
495e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
496e48c5293SSteven Rostedt
497e48c5293SSteven Rostedt    return run_command "$cp_scp";
498e48c5293SSteven Rostedt}
499e48c5293SSteven Rostedt
5005f9b6cedSSteven Rostedtsub get_grub_index {
5015f9b6cedSSteven Rostedt
502a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
503a75fececSSteven Rostedt	return;
504a75fececSSteven Rostedt    }
5055a391fbfSSteven Rostedt    return if (defined($grub_number));
5065f9b6cedSSteven Rostedt
5075f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
5085f9b6cedSSteven Rostedt    $grub_number = -1;
509e48c5293SSteven Rostedt
510e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
511e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
512e48c5293SSteven Rostedt
513e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
5145f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
515e48c5293SSteven Rostedt
5165f9b6cedSSteven Rostedt    while (<IN>) {
517a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
5185f9b6cedSSteven Rostedt	    $grub_number++;
5195f9b6cedSSteven Rostedt	    last;
5205f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
5215f9b6cedSSteven Rostedt	    $grub_number++;
5225f9b6cedSSteven Rostedt	}
5235f9b6cedSSteven Rostedt    }
5245f9b6cedSSteven Rostedt    close(IN);
5255f9b6cedSSteven Rostedt
526a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
5275f9b6cedSSteven Rostedt	if ($grub_number < 0);
5285f9b6cedSSteven Rostedt    doprint "$grub_number\n";
5292545eb61SSteven Rostedt}
5302545eb61SSteven Rostedt
5312545eb61SSteven Rostedtsub wait_for_input
5322545eb61SSteven Rostedt{
5332545eb61SSteven Rostedt    my ($fp, $time) = @_;
5342545eb61SSteven Rostedt    my $rin;
5352545eb61SSteven Rostedt    my $ready;
5362545eb61SSteven Rostedt    my $line;
5372545eb61SSteven Rostedt    my $ch;
5382545eb61SSteven Rostedt
5392545eb61SSteven Rostedt    if (!defined($time)) {
5402545eb61SSteven Rostedt	$time = $timeout;
5412545eb61SSteven Rostedt    }
5422545eb61SSteven Rostedt
5432545eb61SSteven Rostedt    $rin = '';
5442545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
5452545eb61SSteven Rostedt    $ready = select($rin, undef, undef, $time);
5462545eb61SSteven Rostedt
5472545eb61SSteven Rostedt    $line = "";
5482545eb61SSteven Rostedt
5492545eb61SSteven Rostedt    # try to read one char at a time
5502545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
5512545eb61SSteven Rostedt	$line .= $ch;
5522545eb61SSteven Rostedt	last if ($ch eq "\n");
5532545eb61SSteven Rostedt    }
5542545eb61SSteven Rostedt
5552545eb61SSteven Rostedt    if (!length($line)) {
5562545eb61SSteven Rostedt	return undef;
5572545eb61SSteven Rostedt    }
5582545eb61SSteven Rostedt
5592545eb61SSteven Rostedt    return $line;
5602545eb61SSteven Rostedt}
5612545eb61SSteven Rostedt
56275c3fda7SSteven Rostedtsub reboot_to {
563a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
564eec56460SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
565a75fececSSteven Rostedt	return;
566a75fececSSteven Rostedt    }
567a75fececSSteven Rostedt
568a75fececSSteven Rostedt    run_command "$reboot_script";
5692545eb61SSteven Rostedt}
5702545eb61SSteven Rostedt
571a57419b3SSteven Rostedtsub get_sha1 {
572a57419b3SSteven Rostedt    my ($commit) = @_;
573a57419b3SSteven Rostedt
574a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
575a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
576a57419b3SSteven Rostedt    my $ret = $?;
577a57419b3SSteven Rostedt
578a57419b3SSteven Rostedt    logit $sha1;
579a57419b3SSteven Rostedt
580a57419b3SSteven Rostedt    if ($ret) {
581a57419b3SSteven Rostedt	doprint "FAILED\n";
582a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
583a57419b3SSteven Rostedt    }
584a57419b3SSteven Rostedt
585a57419b3SSteven Rostedt    print "SUCCESS\n";
586a57419b3SSteven Rostedt
587a57419b3SSteven Rostedt    chomp $sha1;
588a57419b3SSteven Rostedt
589a57419b3SSteven Rostedt    return $sha1;
590a57419b3SSteven Rostedt}
591a57419b3SSteven Rostedt
5925a391fbfSSteven Rostedtsub monitor {
5932545eb61SSteven Rostedt    my $booted = 0;
5942545eb61SSteven Rostedt    my $bug = 0;
5955c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
5962b7d9b21SSteven Rostedt    my $loops;
5972545eb61SSteven Rostedt
5987faafbd6SSteven Rostedt    wait_for_monitor 5;
5992545eb61SSteven Rostedt
6002545eb61SSteven Rostedt    my $line;
6012545eb61SSteven Rostedt    my $full_line = "";
6022545eb61SSteven Rostedt
6037faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
6047faafbd6SSteven Rostedt	die "unable to write to $dmesg";
6052545eb61SSteven Rostedt
60675c3fda7SSteven Rostedt    reboot_to;
6072545eb61SSteven Rostedt
6081c8a617aSSteven Rostedt    my $success_start;
6091c8a617aSSteven Rostedt    my $failure_start;
6101c8a617aSSteven Rostedt
6112545eb61SSteven Rostedt    for (;;) {
6122545eb61SSteven Rostedt
6132b7d9b21SSteven Rostedt	if ($booted) {
614a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
6152b7d9b21SSteven Rostedt	} else {
6167faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
6172b7d9b21SSteven Rostedt	}
6182545eb61SSteven Rostedt
6192545eb61SSteven Rostedt	last if (!defined($line));
6202545eb61SSteven Rostedt
6212545eb61SSteven Rostedt	doprint $line;
6227faafbd6SSteven Rostedt	print DMESG $line;
6232545eb61SSteven Rostedt
6242545eb61SSteven Rostedt	# we are not guaranteed to get a full line
6252545eb61SSteven Rostedt	$full_line .= $line;
6262545eb61SSteven Rostedt
627a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
6282545eb61SSteven Rostedt	    $booted = 1;
6291c8a617aSSteven Rostedt	    $success_start = time;
6301c8a617aSSteven Rostedt	}
6311c8a617aSSteven Rostedt
6321c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
6331c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
6341c8a617aSSteven Rostedt	    my $now = time;
6351c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
6361c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
6371c8a617aSSteven Rostedt		last;
6381c8a617aSSteven Rostedt	    }
6392545eb61SSteven Rostedt	}
6402545eb61SSteven Rostedt
6415c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
6425c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
6435c42fc5bSSteven Rostedt	}
6445c42fc5bSSteven Rostedt
6452545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
6461c8a617aSSteven Rostedt	    if (!$skip_call_trace) {
6471c8a617aSSteven Rostedt		$bug = 1;
6481c8a617aSSteven Rostedt		$failure_start = time;
6491c8a617aSSteven Rostedt	    }
6501c8a617aSSteven Rostedt	}
6511c8a617aSSteven Rostedt
6521c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
6531c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
6541c8a617aSSteven Rostedt	    my $now = time;
6551c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
6561c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
6571c8a617aSSteven Rostedt		last;
6581c8a617aSSteven Rostedt	    }
6595c42fc5bSSteven Rostedt	}
6605c42fc5bSSteven Rostedt
6615c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
6625c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
6635c42fc5bSSteven Rostedt	}
6645c42fc5bSSteven Rostedt
6655c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
6662545eb61SSteven Rostedt	    $bug = 1;
6672545eb61SSteven Rostedt	}
6682545eb61SSteven Rostedt
6692545eb61SSteven Rostedt	if ($line =~ /\n/) {
6702545eb61SSteven Rostedt	    $full_line = "";
6712545eb61SSteven Rostedt	}
6722545eb61SSteven Rostedt    }
6732545eb61SSteven Rostedt
6747faafbd6SSteven Rostedt    close(DMESG);
6752545eb61SSteven Rostedt
6762545eb61SSteven Rostedt    if ($bug) {
6772b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
678576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
6792545eb61SSteven Rostedt    }
6805f9b6cedSSteven Rostedt
681a75fececSSteven Rostedt    if (!$booted) {
682a75fececSSteven Rostedt	return 0 if ($in_bisect);
683576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
684a75fececSSteven Rostedt    }
685a75fececSSteven Rostedt
6862b7d9b21SSteven Rostedt    return 1;
6872545eb61SSteven Rostedt}
6882545eb61SSteven Rostedt
6892545eb61SSteven Rostedtsub install {
6902545eb61SSteven Rostedt
691e48c5293SSteven Rostedt    run_scp "$outputdir/$build_target", "$target_image" or
6925c42fc5bSSteven Rostedt	dodie "failed to copy image";
6935f9b6cedSSteven Rostedt
6945f9b6cedSSteven Rostedt    my $install_mods = 0;
6955f9b6cedSSteven Rostedt
6965f9b6cedSSteven Rostedt    # should we process modules?
6975f9b6cedSSteven Rostedt    $install_mods = 0;
69851ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
6995f9b6cedSSteven Rostedt    while (<IN>) {
7005f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
7015f9b6cedSSteven Rostedt	    $install_mods = 1 if (defined($1));
7025f9b6cedSSteven Rostedt	    last;
7035f9b6cedSSteven Rostedt	}
7045f9b6cedSSteven Rostedt    }
7055f9b6cedSSteven Rostedt    close(IN);
7065f9b6cedSSteven Rostedt
7075f9b6cedSSteven Rostedt    if (!$install_mods) {
7085f9b6cedSSteven Rostedt	doprint "No modules needed\n";
7095f9b6cedSSteven Rostedt	return;
7102545eb61SSteven Rostedt    }
7112545eb61SSteven Rostedt
712a75fececSSteven Rostedt    run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
7135f9b6cedSSteven Rostedt	dodie "Failed to install modules";
7145f9b6cedSSteven Rostedt
7152545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
716a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
7172545eb61SSteven Rostedt
718e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
7195c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
7202545eb61SSteven Rostedt
7215c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
722a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
7235c42fc5bSSteven Rostedt	dodie "making tarball";
7245c42fc5bSSteven Rostedt
725e48c5293SSteven Rostedt    run_scp "$tmpdir/$modtar", "/tmp" or
7265c42fc5bSSteven Rostedt	dodie "failed to copy modules";
7275c42fc5bSSteven Rostedt
728a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
7295c42fc5bSSteven Rostedt
730e48c5293SSteven Rostedt    run_ssh "'(cd / && tar xf /tmp/$modtar)'" or
7315c42fc5bSSteven Rostedt	dodie "failed to tar modules";
7325c42fc5bSSteven Rostedt
733e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
7348b37ca8cSSteven Rostedt
7358b37ca8cSSteven Rostedt    return if (!defined($post_install));
7368b37ca8cSSteven Rostedt
737e48c5293SSteven Rostedt    my $cp_post_install = $post_install;
738e48c5293SSteven Rostedt    $cp_post_install = s/\$KERNEL_VERSION/$version/g;
739e48c5293SSteven Rostedt    run_command "$cp_post_install" or
740576f627cSSteven Rostedt	dodie "Failed to run post install";
7412545eb61SSteven Rostedt}
7422545eb61SSteven Rostedt
7436c5ee0beSSteven Rostedtsub check_buildlog {
7446c5ee0beSSteven Rostedt    my ($patch) = @_;
7456c5ee0beSSteven Rostedt
7466c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
7476c5ee0beSSteven Rostedt
7486c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
7496c5ee0beSSteven Rostedt	dodie "failed to show $patch";
7506c5ee0beSSteven Rostedt    while (<IN>) {
7516c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
7526c5ee0beSSteven Rostedt	    chomp $1;
7536c5ee0beSSteven Rostedt	    $files[$#files] = $1;
7546c5ee0beSSteven Rostedt	}
7556c5ee0beSSteven Rostedt    }
7566c5ee0beSSteven Rostedt    close(IN);
7576c5ee0beSSteven Rostedt
7586c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
7596c5ee0beSSteven Rostedt    while (<IN>) {
7606c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
7616c5ee0beSSteven Rostedt	    my $err = $1;
7626c5ee0beSSteven Rostedt	    foreach my $file (@files) {
763a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
7646c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
7652b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
7666c5ee0beSSteven Rostedt		}
7676c5ee0beSSteven Rostedt	    }
7686c5ee0beSSteven Rostedt	}
7696c5ee0beSSteven Rostedt    }
7706c5ee0beSSteven Rostedt    close(IN);
7712b7d9b21SSteven Rostedt
7722b7d9b21SSteven Rostedt    return 1;
7736c5ee0beSSteven Rostedt}
7746c5ee0beSSteven Rostedt
7752545eb61SSteven Rostedtsub build {
7762545eb61SSteven Rostedt    my ($type) = @_;
7775c42fc5bSSteven Rostedt    my $defconfig = "";
7782545eb61SSteven Rostedt
7797faafbd6SSteven Rostedt    unlink $buildlog;
7807faafbd6SSteven Rostedt
78175c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
78251ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
78375c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
7845f9b6cedSSteven Rostedt
78575c3fda7SSteven Rostedt	$type = "oldconfig";
78675c3fda7SSteven Rostedt    }
78775c3fda7SSteven Rostedt
7885c42fc5bSSteven Rostedt    # old config can ask questions
7895c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
7909386c6abSSteven Rostedt	$type = "oldnoconfig";
79175c3fda7SSteven Rostedt
79275c3fda7SSteven Rostedt	# allow for empty configs
79351ad1dd1SSteven Rostedt	run_command "touch $output_config";
79475c3fda7SSteven Rostedt
79551ad1dd1SSteven Rostedt	run_command "mv $output_config $outputdir/config_temp" or
7965c42fc5bSSteven Rostedt	    dodie "moving .config";
7975c42fc5bSSteven Rostedt
7985f9b6cedSSteven Rostedt	if (!$noclean && !run_command "$make mrproper") {
7995c42fc5bSSteven Rostedt	    dodie "make mrproper";
8005c42fc5bSSteven Rostedt	}
8015c42fc5bSSteven Rostedt
80251ad1dd1SSteven Rostedt	run_command "mv $outputdir/config_temp $output_config" or
8035c42fc5bSSteven Rostedt	    dodie "moving config_temp";
8045c42fc5bSSteven Rostedt
8055c42fc5bSSteven Rostedt    } elsif (!$noclean) {
80651ad1dd1SSteven Rostedt	unlink "$output_config";
8075f9b6cedSSteven Rostedt	run_command "$make mrproper" or
8085c42fc5bSSteven Rostedt	    dodie "make mrproper";
8095c42fc5bSSteven Rostedt    }
8102545eb61SSteven Rostedt
8112545eb61SSteven Rostedt    # add something to distinguish this build
812a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
813a75fececSSteven Rostedt    print OUT "$localversion\n";
8142545eb61SSteven Rostedt    close(OUT);
8152545eb61SSteven Rostedt
8165f9b6cedSSteven Rostedt    if (defined($minconfig)) {
8175f9b6cedSSteven Rostedt	$defconfig = "KCONFIG_ALLCONFIG=$minconfig";
8182545eb61SSteven Rostedt    }
8192545eb61SSteven Rostedt
8209386c6abSSteven Rostedt    run_command "$defconfig $make $type" or
8215c42fc5bSSteven Rostedt	dodie "failed make config";
8222545eb61SSteven Rostedt
823a75fececSSteven Rostedt    $redirect = "$buildlog";
824a75fececSSteven Rostedt    if (!run_command "$make $build_options") {
8256c5ee0beSSteven Rostedt	undef $redirect;
8265f9b6cedSSteven Rostedt	# bisect may need this to pass
8272b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
8282b7d9b21SSteven Rostedt	fail "failed build" and return 0;
8292545eb61SSteven Rostedt    }
8306c5ee0beSSteven Rostedt    undef $redirect;
8315f9b6cedSSteven Rostedt
8322b7d9b21SSteven Rostedt    return 1;
8332545eb61SSteven Rostedt}
8342545eb61SSteven Rostedt
83575c3fda7SSteven Rostedtsub halt {
836e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
837576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
838576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
839576f627cSSteven Rostedt	    run_command "$power_off";
840576f627cSSteven Rostedt	}
841576f627cSSteven Rostedt    } else {
84275c3fda7SSteven Rostedt	# nope? the zap it!
843a75fececSSteven Rostedt	run_command "$power_off";
84475c3fda7SSteven Rostedt    }
84575c3fda7SSteven Rostedt}
84675c3fda7SSteven Rostedt
8475f9b6cedSSteven Rostedtsub success {
8485f9b6cedSSteven Rostedt    my ($i) = @_;
8495f9b6cedSSteven Rostedt
850e48c5293SSteven Rostedt    $successes++;
851e48c5293SSteven Rostedt
8525f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
8535f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
8547a849cd9SSteven Rostedt    doprint     "KTEST RESULT: TEST $i SUCCESS!!!!         **\n";
8555f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
8565f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
8575f9b6cedSSteven Rostedt
858576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
859a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
8605f9b6cedSSteven Rostedt	reboot;
8617faafbd6SSteven Rostedt	start_monitor;
862a75fececSSteven Rostedt	wait_for_monitor $sleep_time;
8637faafbd6SSteven Rostedt	end_monitor;
8645f9b6cedSSteven Rostedt    }
8655f9b6cedSSteven Rostedt}
8665f9b6cedSSteven Rostedt
8675f9b6cedSSteven Rostedtsub get_version {
8685f9b6cedSSteven Rostedt    # get the release name
8695f9b6cedSSteven Rostedt    doprint "$make kernelrelease ... ";
8705f9b6cedSSteven Rostedt    $version = `$make kernelrelease | tail -1`;
8715f9b6cedSSteven Rostedt    chomp($version);
8725f9b6cedSSteven Rostedt    doprint "$version\n";
8735f9b6cedSSteven Rostedt}
8745f9b6cedSSteven Rostedt
8755a391fbfSSteven Rostedtsub child_run_test {
8767faafbd6SSteven Rostedt    my $failed = 0;
8775a391fbfSSteven Rostedt
8787faafbd6SSteven Rostedt    # child should have no power
879a75fececSSteven Rostedt    $reboot_on_error = 0;
880a75fececSSteven Rostedt    $poweroff_on_error = 0;
881a75fececSSteven Rostedt    $die_on_failure = 1;
8827faafbd6SSteven Rostedt
8837faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
8845a391fbfSSteven Rostedt    exit $failed;
8855a391fbfSSteven Rostedt}
8865a391fbfSSteven Rostedt
8875a391fbfSSteven Rostedtmy $child_done;
8885a391fbfSSteven Rostedt
8895a391fbfSSteven Rostedtsub child_finished {
8905a391fbfSSteven Rostedt    $child_done = 1;
8915a391fbfSSteven Rostedt}
8925a391fbfSSteven Rostedt
8935a391fbfSSteven Rostedtsub do_run_test {
8945a391fbfSSteven Rostedt    my $child_pid;
8955a391fbfSSteven Rostedt    my $child_exit;
8965a391fbfSSteven Rostedt    my $line;
8975a391fbfSSteven Rostedt    my $full_line;
8985a391fbfSSteven Rostedt    my $bug = 0;
8995a391fbfSSteven Rostedt
9007faafbd6SSteven Rostedt    wait_for_monitor 1;
9015a391fbfSSteven Rostedt
9027faafbd6SSteven Rostedt    doprint "run test $run_test\n";
9035a391fbfSSteven Rostedt
9045a391fbfSSteven Rostedt    $child_done = 0;
9055a391fbfSSteven Rostedt
9065a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
9075a391fbfSSteven Rostedt
9085a391fbfSSteven Rostedt    $child_pid = fork;
9095a391fbfSSteven Rostedt
9105a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
9115a391fbfSSteven Rostedt
9125a391fbfSSteven Rostedt    $full_line = "";
9135a391fbfSSteven Rostedt
9145a391fbfSSteven Rostedt    do {
9157faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
9165a391fbfSSteven Rostedt	if (defined($line)) {
9175a391fbfSSteven Rostedt
9185a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
9195a391fbfSSteven Rostedt	    $full_line .= $line;
9205a391fbfSSteven Rostedt
9215a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
9225a391fbfSSteven Rostedt		$bug = 1;
9235a391fbfSSteven Rostedt	    }
9245a391fbfSSteven Rostedt
9255a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
9265a391fbfSSteven Rostedt		$bug = 1;
9275a391fbfSSteven Rostedt	    }
9285a391fbfSSteven Rostedt
9295a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
9305a391fbfSSteven Rostedt		$full_line = "";
9315a391fbfSSteven Rostedt	    }
9325a391fbfSSteven Rostedt	}
9335a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
9345a391fbfSSteven Rostedt
9355a391fbfSSteven Rostedt    if ($bug) {
9365a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
9375a391fbfSSteven Rostedt	# kill the child with extreme prejudice
9385a391fbfSSteven Rostedt	kill 9, $child_pid;
9395a391fbfSSteven Rostedt    }
9405a391fbfSSteven Rostedt
9415a391fbfSSteven Rostedt    waitpid $child_pid, 0;
9425a391fbfSSteven Rostedt    $child_exit = $?;
9435a391fbfSSteven Rostedt
9445a391fbfSSteven Rostedt    if ($bug || $child_exit) {
9452b7d9b21SSteven Rostedt	return 0 if $in_bisect;
9462b7d9b21SSteven Rostedt	fail "test failed" and return 0;
9475a391fbfSSteven Rostedt    }
9482b7d9b21SSteven Rostedt    return 1;
9495a391fbfSSteven Rostedt}
9505a391fbfSSteven Rostedt
951a75fececSSteven Rostedtsub run_git_bisect {
952a75fececSSteven Rostedt    my ($command) = @_;
953a75fececSSteven Rostedt
954a75fececSSteven Rostedt    doprint "$command ... ";
955a75fececSSteven Rostedt
956a75fececSSteven Rostedt    my $output = `$command 2>&1`;
957a75fececSSteven Rostedt    my $ret = $?;
958a75fececSSteven Rostedt
959a75fececSSteven Rostedt    logit $output;
960a75fececSSteven Rostedt
961a75fececSSteven Rostedt    if ($ret) {
962a75fececSSteven Rostedt	doprint "FAILED\n";
963a75fececSSteven Rostedt	dodie "Failed to git bisect";
964a75fececSSteven Rostedt    }
965a75fececSSteven Rostedt
966a75fececSSteven Rostedt    doprint "SUCCESS\n";
967a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
968a75fececSSteven Rostedt	doprint "$1 [$2]\n";
969a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
970a75fececSSteven Rostedt	$bisect_bad = $1;
971a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
972a75fececSSteven Rostedt	return 0;
973a75fececSSteven Rostedt    } else {
974a75fececSSteven Rostedt	# we already logged it, just print it now.
975a75fececSSteven Rostedt	print $output;
976a75fececSSteven Rostedt    }
977a75fececSSteven Rostedt
978a75fececSSteven Rostedt    return 1;
979a75fececSSteven Rostedt}
980a75fececSSteven Rostedt
9810a05c769SSteven Rostedt# returns 1 on success, 0 on failure
9820a05c769SSteven Rostedtsub run_bisect_test {
9830a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
9845f9b6cedSSteven Rostedt
9852b7d9b21SSteven Rostedt    my $failed = 0;
9865f9b6cedSSteven Rostedt    my $result;
9875f9b6cedSSteven Rostedt    my $output;
9885f9b6cedSSteven Rostedt    my $ret;
9895f9b6cedSSteven Rostedt
9900a05c769SSteven Rostedt    $in_bisect = 1;
9910a05c769SSteven Rostedt
9920a05c769SSteven Rostedt    build $buildtype or $failed = 1;
9935f9b6cedSSteven Rostedt
9945f9b6cedSSteven Rostedt    if ($type ne "build") {
9957faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
9965f9b6cedSSteven Rostedt
9975f9b6cedSSteven Rostedt	# Now boot the box
9985f9b6cedSSteven Rostedt	get_grub_index;
9995f9b6cedSSteven Rostedt	get_version;
10005f9b6cedSSteven Rostedt	install;
10017faafbd6SSteven Rostedt
10027faafbd6SSteven Rostedt	start_monitor;
10032b7d9b21SSteven Rostedt	monitor or $failed = 1;
10045f9b6cedSSteven Rostedt
10055f9b6cedSSteven Rostedt	if ($type ne "boot") {
10067faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
10075a391fbfSSteven Rostedt
10082b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
10095f9b6cedSSteven Rostedt	}
10107faafbd6SSteven Rostedt	end_monitor;
10115f9b6cedSSteven Rostedt    }
10125f9b6cedSSteven Rostedt
10135f9b6cedSSteven Rostedt    if ($failed) {
10140a05c769SSteven Rostedt	$result = 0;
10155a391fbfSSteven Rostedt
10165a391fbfSSteven Rostedt	# reboot the box to a good kernel
1017a75fececSSteven Rostedt	if ($type ne "build") {
1018a75fececSSteven Rostedt	    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
10195a391fbfSSteven Rostedt	    reboot;
10207faafbd6SSteven Rostedt	    start_monitor;
1021a75fececSSteven Rostedt	    wait_for_monitor $bisect_sleep_time;
10227faafbd6SSteven Rostedt	    end_monitor;
10235a391fbfSSteven Rostedt	}
10245f9b6cedSSteven Rostedt    } else {
10250a05c769SSteven Rostedt	$result = 1;
10265f9b6cedSSteven Rostedt    }
10270a05c769SSteven Rostedt    $in_bisect = 0;
10280a05c769SSteven Rostedt
10290a05c769SSteven Rostedt    return $result;
10300a05c769SSteven Rostedt}
10310a05c769SSteven Rostedt
10320a05c769SSteven Rostedtsub run_bisect {
10330a05c769SSteven Rostedt    my ($type) = @_;
10340a05c769SSteven Rostedt    my $buildtype = "oldconfig";
10350a05c769SSteven Rostedt
10360a05c769SSteven Rostedt    # We should have a minconfig to use?
10370a05c769SSteven Rostedt    if (defined($minconfig)) {
10380a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
10390a05c769SSteven Rostedt    }
10400a05c769SSteven Rostedt
10410a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
10420a05c769SSteven Rostedt
10435f9b6cedSSteven Rostedt
1044d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
1045d6ce2a0bSSteven Rostedt    if ($reverse_bisect) {
10460a05c769SSteven Rostedt	$ret = !$ret;
1047d6ce2a0bSSteven Rostedt    }
1048d6ce2a0bSSteven Rostedt
10490a05c769SSteven Rostedt    if ($ret) {
10500a05c769SSteven Rostedt	return "good";
10510a05c769SSteven Rostedt    } else {
10520a05c769SSteven Rostedt	return  "bad";
10530a05c769SSteven Rostedt    }
10545f9b6cedSSteven Rostedt}
10555f9b6cedSSteven Rostedt
10565f9b6cedSSteven Rostedtsub bisect {
10575f9b6cedSSteven Rostedt    my ($i) = @_;
10585f9b6cedSSteven Rostedt
10595f9b6cedSSteven Rostedt    my $result;
10605f9b6cedSSteven Rostedt
10615f9b6cedSSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($opt{"BISECT_GOOD[$i]"}));
10625f9b6cedSSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($opt{"BISECT_BAD[$i]"}));
10635f9b6cedSSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($opt{"BISECT_TYPE[$i]"}));
10645f9b6cedSSteven Rostedt
10655f9b6cedSSteven Rostedt    my $good = $opt{"BISECT_GOOD[$i]"};
10665f9b6cedSSteven Rostedt    my $bad = $opt{"BISECT_BAD[$i]"};
10675f9b6cedSSteven Rostedt    my $type = $opt{"BISECT_TYPE[$i]"};
1068a75fececSSteven Rostedt    my $start = $opt{"BISECT_START[$i]"};
1069a75fececSSteven Rostedt    my $replay = $opt{"BISECT_REPLAY[$i]"};
10705f9b6cedSSteven Rostedt
1071a57419b3SSteven Rostedt    # convert to true sha1's
1072a57419b3SSteven Rostedt    $good = get_sha1($good);
1073a57419b3SSteven Rostedt    $bad = get_sha1($bad);
1074a57419b3SSteven Rostedt
1075d6ce2a0bSSteven Rostedt    if (defined($opt{"BISECT_REVERSE[$i]"}) &&
1076d6ce2a0bSSteven Rostedt	$opt{"BISECT_REVERSE[$i]"} == 1) {
1077d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1078d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
1079d6ce2a0bSSteven Rostedt    } else {
1080d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
1081d6ce2a0bSSteven Rostedt    }
1082d6ce2a0bSSteven Rostedt
10835a391fbfSSteven Rostedt    # Can't have a test without having a test to run
10845a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
10855a391fbfSSteven Rostedt	$type = "boot";
10865a391fbfSSteven Rostedt    }
10875a391fbfSSteven Rostedt
1088a75fececSSteven Rostedt    my $check = $opt{"BISECT_CHECK[$i]"};
1089a75fececSSteven Rostedt    if (defined($check) && $check ne "0") {
1090a75fececSSteven Rostedt
1091a75fececSSteven Rostedt	# get current HEAD
1092a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
1093a75fececSSteven Rostedt
1094a75fececSSteven Rostedt	if ($check ne "good") {
1095a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
1096a75fececSSteven Rostedt	    run_command "git checkout $bad" or
1097a75fececSSteven Rostedt		die "Failed to checkout $bad";
1098a75fececSSteven Rostedt
1099a75fececSSteven Rostedt	    $result = run_bisect $type;
1100a75fececSSteven Rostedt
1101a75fececSSteven Rostedt	    if ($result ne "bad") {
1102a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
1103a75fececSSteven Rostedt	    }
1104a75fececSSteven Rostedt	}
1105a75fececSSteven Rostedt
1106a75fececSSteven Rostedt	if ($check ne "bad") {
1107a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
1108a75fececSSteven Rostedt	    run_command "git checkout $good" or
1109a75fececSSteven Rostedt		die "Failed to checkout $good";
1110a75fececSSteven Rostedt
1111a75fececSSteven Rostedt	    $result = run_bisect $type;
1112a75fececSSteven Rostedt
1113a75fececSSteven Rostedt	    if ($result ne "good") {
1114a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
1115a75fececSSteven Rostedt	    }
1116a75fececSSteven Rostedt	}
1117a75fececSSteven Rostedt
1118a75fececSSteven Rostedt	# checkout where we started
1119a75fececSSteven Rostedt	run_command "git checkout $head" or
1120a75fececSSteven Rostedt	    die "Failed to checkout $head";
1121a75fececSSteven Rostedt    }
1122a75fececSSteven Rostedt
1123a75fececSSteven Rostedt    run_command "git bisect start" or
1124a75fececSSteven Rostedt	dodie "could not start bisect";
1125a75fececSSteven Rostedt
1126a75fececSSteven Rostedt    run_command "git bisect good $good" or
1127a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
1128a75fececSSteven Rostedt
1129a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
1130a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
1131a75fececSSteven Rostedt
1132a75fececSSteven Rostedt    if (defined($replay)) {
1133a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
1134a75fececSSteven Rostedt	    dodie "failed to run replay";
1135a75fececSSteven Rostedt    }
1136a75fececSSteven Rostedt
1137a75fececSSteven Rostedt    if (defined($start)) {
1138a75fececSSteven Rostedt	run_command "git checkout $start" or
1139a75fececSSteven Rostedt	    dodie "failed to checkout $start";
1140a75fececSSteven Rostedt    }
1141a75fececSSteven Rostedt
1142a75fececSSteven Rostedt    my $test;
11435f9b6cedSSteven Rostedt    do {
11445f9b6cedSSteven Rostedt	$result = run_bisect $type;
1145a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
1146a75fececSSteven Rostedt    } while ($test);
11475f9b6cedSSteven Rostedt
11485f9b6cedSSteven Rostedt    run_command "git bisect log" or
11495f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
11505f9b6cedSSteven Rostedt
11515f9b6cedSSteven Rostedt    run_command "git bisect reset" or
11525f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
11535f9b6cedSSteven Rostedt
11545f9b6cedSSteven Rostedt    doprint "Bad commit was [$bisect_bad]\n";
11555f9b6cedSSteven Rostedt
11560a05c769SSteven Rostedt    success $i;
11570a05c769SSteven Rostedt}
11580a05c769SSteven Rostedt
11590a05c769SSteven Rostedtmy %config_ignore;
11600a05c769SSteven Rostedtmy %config_set;
11610a05c769SSteven Rostedt
11620a05c769SSteven Rostedtmy %config_list;
11630a05c769SSteven Rostedtmy %null_config;
11640a05c769SSteven Rostedt
11650a05c769SSteven Rostedtmy %dependency;
11660a05c769SSteven Rostedt
11670a05c769SSteven Rostedtsub process_config_ignore {
11680a05c769SSteven Rostedt    my ($config) = @_;
11690a05c769SSteven Rostedt
11700a05c769SSteven Rostedt    open (IN, $config)
11710a05c769SSteven Rostedt	or dodie "Failed to read $config";
11720a05c769SSteven Rostedt
11730a05c769SSteven Rostedt    while (<IN>) {
11740a05c769SSteven Rostedt	if (/^(.*?(CONFIG\S*)(=.*| is not set))/) {
11750a05c769SSteven Rostedt	    $config_ignore{$2} = $1;
11760a05c769SSteven Rostedt	}
11770a05c769SSteven Rostedt    }
11780a05c769SSteven Rostedt
11790a05c769SSteven Rostedt    close(IN);
11800a05c769SSteven Rostedt}
11810a05c769SSteven Rostedt
11820a05c769SSteven Rostedtsub read_current_config {
11830a05c769SSteven Rostedt    my ($config_ref) = @_;
11840a05c769SSteven Rostedt
11850a05c769SSteven Rostedt    %{$config_ref} = ();
11860a05c769SSteven Rostedt    undef %{$config_ref};
11870a05c769SSteven Rostedt
11880a05c769SSteven Rostedt    my @key = keys %{$config_ref};
11890a05c769SSteven Rostedt    if ($#key >= 0) {
11900a05c769SSteven Rostedt	print "did not delete!\n";
11910a05c769SSteven Rostedt	exit;
11920a05c769SSteven Rostedt    }
11930a05c769SSteven Rostedt    open (IN, "$output_config");
11940a05c769SSteven Rostedt
11950a05c769SSteven Rostedt    while (<IN>) {
11960a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
11970a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
11980a05c769SSteven Rostedt	}
11990a05c769SSteven Rostedt    }
12000a05c769SSteven Rostedt    close(IN);
12010a05c769SSteven Rostedt}
12020a05c769SSteven Rostedt
12030a05c769SSteven Rostedtsub get_dependencies {
12040a05c769SSteven Rostedt    my ($config) = @_;
12050a05c769SSteven Rostedt
12060a05c769SSteven Rostedt    my $arr = $dependency{$config};
12070a05c769SSteven Rostedt    if (!defined($arr)) {
12080a05c769SSteven Rostedt	return ();
12090a05c769SSteven Rostedt    }
12100a05c769SSteven Rostedt
12110a05c769SSteven Rostedt    my @deps = @{$arr};
12120a05c769SSteven Rostedt
12130a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
12140a05c769SSteven Rostedt	print "ADD DEP $dep\n";
12150a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
12160a05c769SSteven Rostedt    }
12170a05c769SSteven Rostedt
12180a05c769SSteven Rostedt    return @deps;
12190a05c769SSteven Rostedt}
12200a05c769SSteven Rostedt
12210a05c769SSteven Rostedtsub create_config {
12220a05c769SSteven Rostedt    my @configs = @_;
12230a05c769SSteven Rostedt
12240a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
12250a05c769SSteven Rostedt
12260a05c769SSteven Rostedt    foreach my $config (@configs) {
12270a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
12280a05c769SSteven Rostedt	my @deps = get_dependencies $config;
12290a05c769SSteven Rostedt	foreach my $dep (@deps) {
12300a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
12310a05c769SSteven Rostedt	}
12320a05c769SSteven Rostedt    }
12330a05c769SSteven Rostedt
12340a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
12350a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
12360a05c769SSteven Rostedt    }
12370a05c769SSteven Rostedt    close(OUT);
12380a05c769SSteven Rostedt
12390a05c769SSteven Rostedt#    exit;
12400a05c769SSteven Rostedt    run_command "$make oldnoconfig" or
12410a05c769SSteven Rostedt	dodie "failed make config oldconfig";
12420a05c769SSteven Rostedt
12430a05c769SSteven Rostedt}
12440a05c769SSteven Rostedt
12450a05c769SSteven Rostedtsub compare_configs {
12460a05c769SSteven Rostedt    my (%a, %b) = @_;
12470a05c769SSteven Rostedt
12480a05c769SSteven Rostedt    foreach my $item (keys %a) {
12490a05c769SSteven Rostedt	if (!defined($b{$item})) {
12500a05c769SSteven Rostedt	    print "diff $item\n";
12510a05c769SSteven Rostedt	    return 1;
12520a05c769SSteven Rostedt	}
12530a05c769SSteven Rostedt	delete $b{$item};
12540a05c769SSteven Rostedt    }
12550a05c769SSteven Rostedt
12560a05c769SSteven Rostedt    my @keys = keys %b;
12570a05c769SSteven Rostedt    if ($#keys) {
12580a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
12590a05c769SSteven Rostedt    }
12600a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
12610a05c769SSteven Rostedt
12620a05c769SSteven Rostedt    return 0;
12630a05c769SSteven Rostedt}
12640a05c769SSteven Rostedt
12650a05c769SSteven Rostedtsub run_config_bisect_test {
12660a05c769SSteven Rostedt    my ($type) = @_;
12670a05c769SSteven Rostedt
12680a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
12690a05c769SSteven Rostedt}
12700a05c769SSteven Rostedt
12710a05c769SSteven Rostedtsub process_passed {
12720a05c769SSteven Rostedt    my (%configs) = @_;
12730a05c769SSteven Rostedt
12740a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
12750a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
12760a05c769SSteven Rostedt    # Add them to the min options.
12770a05c769SSteven Rostedt    foreach my $config (keys %configs) {
12780a05c769SSteven Rostedt	if (defined($config_list{$config})) {
12790a05c769SSteven Rostedt	    doprint " removing $config\n";
12800a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
12810a05c769SSteven Rostedt	    delete $config_list{$config};
12820a05c769SSteven Rostedt	}
12830a05c769SSteven Rostedt    }
1284*f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
1285*f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
12860a05c769SSteven Rostedt}
12870a05c769SSteven Rostedt
12880a05c769SSteven Rostedtsub process_failed {
12890a05c769SSteven Rostedt    my ($config) = @_;
12900a05c769SSteven Rostedt
12910a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
12920a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
12930a05c769SSteven Rostedt    doprint "***************************************\n\n";
12940a05c769SSteven Rostedt}
12950a05c769SSteven Rostedt
12960a05c769SSteven Rostedtsub run_config_bisect {
12970a05c769SSteven Rostedt
12980a05c769SSteven Rostedt    my @start_list = keys %config_list;
12990a05c769SSteven Rostedt
13000a05c769SSteven Rostedt    if ($#start_list < 0) {
13010a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
13020a05c769SSteven Rostedt	return -1;
13030a05c769SSteven Rostedt    }
13040a05c769SSteven Rostedt
13050a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
13060a05c769SSteven Rostedt    my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
13070a05c769SSteven Rostedt    my $ret;
13080a05c769SSteven Rostedt    my %current_config;
13090a05c769SSteven Rostedt
13100a05c769SSteven Rostedt    my $count = $#start_list + 1;
13110a05c769SSteven Rostedt    doprint "  $count configs to test\n";
13120a05c769SSteven Rostedt
13130a05c769SSteven Rostedt    my $half = int($#start_list / 2);
13140a05c769SSteven Rostedt
13150a05c769SSteven Rostedt    do {
13160a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
13170a05c769SSteven Rostedt
13180a05c769SSteven Rostedt	create_config @tophalf;
13190a05c769SSteven Rostedt	read_current_config \%current_config;
13200a05c769SSteven Rostedt
13210a05c769SSteven Rostedt	$count = $#tophalf + 1;
13220a05c769SSteven Rostedt	doprint "Testing $count configs\n";
13230a05c769SSteven Rostedt	my $found = 0;
13240a05c769SSteven Rostedt	# make sure we test something
13250a05c769SSteven Rostedt	foreach my $config (@tophalf) {
13260a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
13270a05c769SSteven Rostedt		logit " $config\n";
13280a05c769SSteven Rostedt		$found = 1;
13290a05c769SSteven Rostedt	    }
13300a05c769SSteven Rostedt	}
13310a05c769SSteven Rostedt	if (!$found) {
13320a05c769SSteven Rostedt	    # try the other half
13330a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
13340a05c769SSteven Rostedt	    @tophalf = @start_list[$half .. $#start_list];
13350a05c769SSteven Rostedt	    create_config @tophalf;
13360a05c769SSteven Rostedt	    read_current_config \%current_config;
13370a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
13380a05c769SSteven Rostedt		if (defined($current_config{$config})) {
13390a05c769SSteven Rostedt		    logit " $config\n";
13400a05c769SSteven Rostedt		    $found = 1;
13410a05c769SSteven Rostedt		}
13420a05c769SSteven Rostedt	    }
13430a05c769SSteven Rostedt	    if (!$found) {
13440a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
13450a05c769SSteven Rostedt		foreach my $config (@start_list) {
13460a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
13470a05c769SSteven Rostedt		}
13480a05c769SSteven Rostedt		return -1;
13490a05c769SSteven Rostedt	    }
13500a05c769SSteven Rostedt	    $count = $#tophalf + 1;
13510a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
13520a05c769SSteven Rostedt	}
13530a05c769SSteven Rostedt
13540a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
13550a05c769SSteven Rostedt
13560a05c769SSteven Rostedt	if ($ret) {
13570a05c769SSteven Rostedt	    process_passed %current_config;
13580a05c769SSteven Rostedt	    return 0;
13590a05c769SSteven Rostedt	}
13600a05c769SSteven Rostedt
13610a05c769SSteven Rostedt	doprint "This config had a failure.\n";
13620a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
1363*f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
1364*f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
13650a05c769SSteven Rostedt
13660a05c769SSteven Rostedt	# A config exists in this group that was bad.
13670a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
13680a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
13690a05c769SSteven Rostedt		doprint " removing $config\n";
13700a05c769SSteven Rostedt		delete $config_list{$config};
13710a05c769SSteven Rostedt	    }
13720a05c769SSteven Rostedt	}
13730a05c769SSteven Rostedt
13740a05c769SSteven Rostedt	@start_list = @tophalf;
13750a05c769SSteven Rostedt
13760a05c769SSteven Rostedt	if ($#start_list == 0) {
13770a05c769SSteven Rostedt	    process_failed $start_list[0];
13780a05c769SSteven Rostedt	    return 1;
13790a05c769SSteven Rostedt	}
13800a05c769SSteven Rostedt
13810a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
13820a05c769SSteven Rostedt	# they are good.
13830a05c769SSteven Rostedt	$half = int($#start_list / 2);
13840a05c769SSteven Rostedt    } while ($half > 0);
13850a05c769SSteven Rostedt
13860a05c769SSteven Rostedt    # we found a single config, try it again
13870a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
13880a05c769SSteven Rostedt
13890a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
13900a05c769SSteven Rostedt    if ($ret) {
13910a05c769SSteven Rostedt	process_passed %current_config;
13920a05c769SSteven Rostedt	return 0;
13930a05c769SSteven Rostedt    }
13940a05c769SSteven Rostedt
13950a05c769SSteven Rostedt    process_failed $start_list[0];
13960a05c769SSteven Rostedt    return 1;
13970a05c769SSteven Rostedt}
13980a05c769SSteven Rostedt
13990a05c769SSteven Rostedtsub config_bisect {
14000a05c769SSteven Rostedt    my ($i) = @_;
14010a05c769SSteven Rostedt
14020a05c769SSteven Rostedt    my $start_config = $opt{"CONFIG_BISECT[$i]"};
14030a05c769SSteven Rostedt
14040a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
14050a05c769SSteven Rostedt
14060a05c769SSteven Rostedt    # Make the file with the bad config and the min config
14070a05c769SSteven Rostedt    if (defined($minconfig)) {
14080a05c769SSteven Rostedt	# read the min config for things to ignore
14090a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
14100a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
14110a05c769SSteven Rostedt    } else {
14120a05c769SSteven Rostedt	unlink $tmpconfig;
14130a05c769SSteven Rostedt    }
14140a05c769SSteven Rostedt
14150a05c769SSteven Rostedt    # Add other configs
14160a05c769SSteven Rostedt    if (defined($addconfig)) {
14170a05c769SSteven Rostedt	run_command "cat $addconfig >> $tmpconfig" or
14180a05c769SSteven Rostedt	    dodie "failed to append $addconfig";
14190a05c769SSteven Rostedt    }
14200a05c769SSteven Rostedt
14210a05c769SSteven Rostedt    my $defconfig = "";
14220a05c769SSteven Rostedt    if (-f $tmpconfig) {
14230a05c769SSteven Rostedt	$defconfig = "KCONFIG_ALLCONFIG=$tmpconfig";
14240a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
14250a05c769SSteven Rostedt    }
14260a05c769SSteven Rostedt
14270a05c769SSteven Rostedt    # now process the start config
14280a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
14290a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
14300a05c769SSteven Rostedt
14310a05c769SSteven Rostedt    # read directly what we want to check
14320a05c769SSteven Rostedt    my %config_check;
14330a05c769SSteven Rostedt    open (IN, $output_config)
14340a05c769SSteven Rostedt	or dodie "faied to open $output_config";
14350a05c769SSteven Rostedt
14360a05c769SSteven Rostedt    while (<IN>) {
14370a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
14380a05c769SSteven Rostedt	    $config_check{$2} = $1;
14390a05c769SSteven Rostedt	}
14400a05c769SSteven Rostedt    }
14410a05c769SSteven Rostedt    close(IN);
14420a05c769SSteven Rostedt
14430a05c769SSteven Rostedt    # Now run oldconfig with the minconfig (and addconfigs)
14440a05c769SSteven Rostedt    run_command "$defconfig $make oldnoconfig" or
14450a05c769SSteven Rostedt	dodie "failed make config oldconfig";
14460a05c769SSteven Rostedt
14470a05c769SSteven Rostedt    # check to see what we lost (or gained)
14480a05c769SSteven Rostedt    open (IN, $output_config)
14490a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
14500a05c769SSteven Rostedt
14510a05c769SSteven Rostedt    my %removed_configs;
14520a05c769SSteven Rostedt    my %added_configs;
14530a05c769SSteven Rostedt
14540a05c769SSteven Rostedt    while (<IN>) {
14550a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
14560a05c769SSteven Rostedt	    # save off all options
14570a05c769SSteven Rostedt	    $config_set{$2} = $1;
14580a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
14590a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
14600a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
14610a05c769SSteven Rostedt		} else {
14620a05c769SSteven Rostedt		    $config_list{$2} = $1;
14630a05c769SSteven Rostedt		}
14640a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
14650a05c769SSteven Rostedt		$added_configs{$2} = $1;
14660a05c769SSteven Rostedt		$config_list{$2} = $1;
14670a05c769SSteven Rostedt	    }
14680a05c769SSteven Rostedt	}
14690a05c769SSteven Rostedt    }
14700a05c769SSteven Rostedt    close(IN);
14710a05c769SSteven Rostedt
14720a05c769SSteven Rostedt    my @confs = keys %removed_configs;
14730a05c769SSteven Rostedt    if ($#confs >= 0) {
14740a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
14750a05c769SSteven Rostedt	foreach my $config (@confs) {
14760a05c769SSteven Rostedt	    doprint " $config\n";
14770a05c769SSteven Rostedt	}
14780a05c769SSteven Rostedt    }
14790a05c769SSteven Rostedt    @confs = keys %added_configs;
14800a05c769SSteven Rostedt    if ($#confs >= 0) {
14810a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
14820a05c769SSteven Rostedt	foreach my $config (@confs) {
14830a05c769SSteven Rostedt	    doprint " $config\n";
14840a05c769SSteven Rostedt	}
14850a05c769SSteven Rostedt    }
14860a05c769SSteven Rostedt
14870a05c769SSteven Rostedt    my %config_test;
14880a05c769SSteven Rostedt    my $once = 0;
14890a05c769SSteven Rostedt
14900a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
14910a05c769SSteven Rostedt    # that the config we autocreate has everything we need
14920a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
14930a05c769SSteven Rostedt    # may not be able to create a new config.
14940a05c769SSteven Rostedt    # Here we create a config with everything set.
14950a05c769SSteven Rostedt    create_config (keys %config_list);
14960a05c769SSteven Rostedt    read_current_config \%config_test;
14970a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
14980a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
14990a05c769SSteven Rostedt	    if (!$once) {
15000a05c769SSteven Rostedt		$once = 1;
15010a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
15020a05c769SSteven Rostedt	    }
15030a05c769SSteven Rostedt	    doprint "  $config\n";
15040a05c769SSteven Rostedt	    delete $config_list{$config};
15050a05c769SSteven Rostedt	}
15060a05c769SSteven Rostedt    }
15070a05c769SSteven Rostedt    my $ret;
15080a05c769SSteven Rostedt    do {
15090a05c769SSteven Rostedt	$ret = run_config_bisect;
15100a05c769SSteven Rostedt    } while (!$ret);
15110a05c769SSteven Rostedt
15120a05c769SSteven Rostedt    return $ret if ($ret < 0);
15135f9b6cedSSteven Rostedt
15145f9b6cedSSteven Rostedt    success $i;
15155f9b6cedSSteven Rostedt}
15165f9b6cedSSteven Rostedt
15176c5ee0beSSteven Rostedtsub patchcheck {
15186c5ee0beSSteven Rostedt    my ($i) = @_;
15196c5ee0beSSteven Rostedt
15206c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
15216c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_START[$i]"}));
15226c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
15236c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
15246c5ee0beSSteven Rostedt
15256c5ee0beSSteven Rostedt    my $start = $opt{"PATCHCHECK_START[$i]"};
15266c5ee0beSSteven Rostedt
15276c5ee0beSSteven Rostedt    my $end = "HEAD";
15286c5ee0beSSteven Rostedt    if (defined($opt{"PATCHCHECK_END[$i]"})) {
15296c5ee0beSSteven Rostedt	$end = $opt{"PATCHCHECK_END[$i]"};
15306c5ee0beSSteven Rostedt    }
15316c5ee0beSSteven Rostedt
1532a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
1533a57419b3SSteven Rostedt    $start = get_sha1($start);
1534a57419b3SSteven Rostedt    $end = get_sha1($end);
1535a57419b3SSteven Rostedt
15366c5ee0beSSteven Rostedt    my $type = $opt{"PATCHCHECK_TYPE[$i]"};
15376c5ee0beSSteven Rostedt
15386c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
15396c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
15406c5ee0beSSteven Rostedt	$type = "boot";
15416c5ee0beSSteven Rostedt    }
15426c5ee0beSSteven Rostedt
15436c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
15446c5ee0beSSteven Rostedt	dodie "could not get git list";
15456c5ee0beSSteven Rostedt
15466c5ee0beSSteven Rostedt    my @list;
15476c5ee0beSSteven Rostedt
15486c5ee0beSSteven Rostedt    while (<IN>) {
15496c5ee0beSSteven Rostedt	chomp;
15506c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
15516c5ee0beSSteven Rostedt	last if (/^$start/);
15526c5ee0beSSteven Rostedt    }
15536c5ee0beSSteven Rostedt    close(IN);
15546c5ee0beSSteven Rostedt
15556c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
15562b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
15576c5ee0beSSteven Rostedt    }
15586c5ee0beSSteven Rostedt
15596c5ee0beSSteven Rostedt    # go backwards in the list
15606c5ee0beSSteven Rostedt    @list = reverse @list;
15616c5ee0beSSteven Rostedt
15626c5ee0beSSteven Rostedt    my $save_clean = $noclean;
15636c5ee0beSSteven Rostedt
15646c5ee0beSSteven Rostedt    $in_patchcheck = 1;
15656c5ee0beSSteven Rostedt    foreach my $item (@list) {
15666c5ee0beSSteven Rostedt	my $sha1 = $item;
15676c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
15686c5ee0beSSteven Rostedt
15696c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
15706c5ee0beSSteven Rostedt
15716c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
15726c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
15736c5ee0beSSteven Rostedt
15746c5ee0beSSteven Rostedt	# only clean on the first and last patch
15756c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
15766c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
15776c5ee0beSSteven Rostedt	    $noclean = $save_clean;
15786c5ee0beSSteven Rostedt	} else {
15796c5ee0beSSteven Rostedt	    $noclean = 1;
15806c5ee0beSSteven Rostedt	}
15816c5ee0beSSteven Rostedt
15826c5ee0beSSteven Rostedt	if (defined($minconfig)) {
15832b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
15846c5ee0beSSteven Rostedt	} else {
15856c5ee0beSSteven Rostedt	    # ?? no config to use?
15862b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
15876c5ee0beSSteven Rostedt	}
15886c5ee0beSSteven Rostedt
15892b7d9b21SSteven Rostedt	check_buildlog $sha1 or return 0;
15906c5ee0beSSteven Rostedt
15916c5ee0beSSteven Rostedt	next if ($type eq "build");
15926c5ee0beSSteven Rostedt
15936c5ee0beSSteven Rostedt	get_grub_index;
15946c5ee0beSSteven Rostedt	get_version;
15956c5ee0beSSteven Rostedt	install;
15966c5ee0beSSteven Rostedt
15977faafbd6SSteven Rostedt	my $failed = 0;
15987faafbd6SSteven Rostedt
15997faafbd6SSteven Rostedt	start_monitor;
16007faafbd6SSteven Rostedt	monitor or $failed = 1;
16017faafbd6SSteven Rostedt
16027faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
16037faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
16047faafbd6SSteven Rostedt	}
16057faafbd6SSteven Rostedt	end_monitor;
16067faafbd6SSteven Rostedt	return 0 if ($failed);
16077faafbd6SSteven Rostedt
16086c5ee0beSSteven Rostedt    }
16096c5ee0beSSteven Rostedt    $in_patchcheck = 0;
16106c5ee0beSSteven Rostedt    success $i;
16112b7d9b21SSteven Rostedt
16122b7d9b21SSteven Rostedt    return 1;
16136c5ee0beSSteven Rostedt}
16146c5ee0beSSteven Rostedt
16152545eb61SSteven Rostedtread_config $ARGV[0];
16162545eb61SSteven Rostedt
16172545eb61SSteven Rostedt# mandatory configs
16182545eb61SSteven Rostedtdie "MACHINE not defined\n"		if (!defined($opt{"MACHINE"}));
16192545eb61SSteven Rostedtdie "SSH_USER not defined\n"		if (!defined($opt{"SSH_USER"}));
16202545eb61SSteven Rostedtdie "BUILD_DIR not defined\n"		if (!defined($opt{"BUILD_DIR"}));
16212545eb61SSteven Rostedtdie "OUTPUT_DIR not defined\n"		if (!defined($opt{"OUTPUT_DIR"}));
16222545eb61SSteven Rostedtdie "BUILD_TARGET not defined\n"	if (!defined($opt{"BUILD_TARGET"}));
162375c3fda7SSteven Rostedtdie "TARGET_IMAGE not defined\n"	if (!defined($opt{"TARGET_IMAGE"}));
16242545eb61SSteven Rostedtdie "POWER_CYCLE not defined\n"		if (!defined($opt{"POWER_CYCLE"}));
16252545eb61SSteven Rostedtdie "CONSOLE not defined\n"		if (!defined($opt{"CONSOLE"}));
16262545eb61SSteven Rostedtdie "LOCALVERSION not defined\n"	if (!defined($opt{"LOCALVERSION"}));
16272545eb61SSteven Rostedt
16282b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
16292b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
16302b7d9b21SSteven Rostedt}
16312545eb61SSteven Rostedt
16322b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
16332b7d9b21SSteven Rostedt
1634a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
1635a57419b3SSteven Rostedt
1636a57419b3SSteven Rostedt    if (!$i) {
1637a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
1638a57419b3SSteven Rostedt    } else {
1639a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
1640a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
1641a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
1642a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
1643a57419b3SSteven Rostedt	}
1644a57419b3SSteven Rostedt	doprint "\n";
1645a57419b3SSteven Rostedt    }
1646a57419b3SSteven Rostedt
16472b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
1648a57419b3SSteven Rostedt
1649a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
1650a57419b3SSteven Rostedt	    next if ($i != $1);
1651a57419b3SSteven Rostedt	} else {
1652a57419b3SSteven Rostedt	    next if ($i);
1653a57419b3SSteven Rostedt	}
1654a57419b3SSteven Rostedt
16552b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
16562b7d9b21SSteven Rostedt    }
1657a57419b3SSteven Rostedt}
16582545eb61SSteven Rostedt
1659a75fececSSteven Rostedtsub set_test_option {
16605a391fbfSSteven Rostedt    my ($name, $i) = @_;
16615a391fbfSSteven Rostedt
16625a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
16635a391fbfSSteven Rostedt
16645a391fbfSSteven Rostedt    if (defined($opt{$option})) {
16655a391fbfSSteven Rostedt	return $opt{$option};
16665a391fbfSSteven Rostedt    }
16675a391fbfSSteven Rostedt
1668a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
1669a57419b3SSteven Rostedt	if ($i >= $test &&
1670a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
1671a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
1672a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
1673a57419b3SSteven Rostedt		return $opt{$option};
1674a57419b3SSteven Rostedt	    }
1675a57419b3SSteven Rostedt	}
1676a57419b3SSteven Rostedt    }
1677a57419b3SSteven Rostedt
16785a391fbfSSteven Rostedt    if (defined($opt{$name})) {
16795a391fbfSSteven Rostedt	return $opt{$name};
16805a391fbfSSteven Rostedt    }
16815a391fbfSSteven Rostedt
16825a391fbfSSteven Rostedt    return undef;
16835a391fbfSSteven Rostedt}
16845a391fbfSSteven Rostedt
16852545eb61SSteven Rostedt# First we need to do is the builds
1686a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
16872545eb61SSteven Rostedt
1688576f627cSSteven Rostedt    $iteration = $i;
1689576f627cSSteven Rostedt
1690a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
1691a75fececSSteven Rostedt
1692a75fececSSteven Rostedt    $machine = set_test_option("MACHINE", $i);
1693e48c5293SSteven Rostedt    $ssh_user = set_test_option("SSH_USER", $i);
1694a75fececSSteven Rostedt    $tmpdir = set_test_option("TMP_DIR", $i);
1695a75fececSSteven Rostedt    $outputdir = set_test_option("OUTPUT_DIR", $i);
1696a75fececSSteven Rostedt    $builddir = set_test_option("BUILD_DIR", $i);
1697a75fececSSteven Rostedt    $test_type = set_test_option("TEST_TYPE", $i);
1698a75fececSSteven Rostedt    $build_type = set_test_option("BUILD_TYPE", $i);
1699a75fececSSteven Rostedt    $build_options = set_test_option("BUILD_OPTIONS", $i);
1700a75fececSSteven Rostedt    $power_cycle = set_test_option("POWER_CYCLE", $i);
1701e48c5293SSteven Rostedt    $reboot = set_test_option("REBOOT", $i);
1702a75fececSSteven Rostedt    $noclean = set_test_option("BUILD_NOCLEAN", $i);
1703a75fececSSteven Rostedt    $minconfig = set_test_option("MIN_CONFIG", $i);
1704a75fececSSteven Rostedt    $run_test = set_test_option("TEST", $i);
1705a75fececSSteven Rostedt    $addconfig = set_test_option("ADD_CONFIG", $i);
1706a75fececSSteven Rostedt    $reboot_type = set_test_option("REBOOT_TYPE", $i);
1707a75fececSSteven Rostedt    $grub_menu = set_test_option("GRUB_MENU", $i);
17088b37ca8cSSteven Rostedt    $post_install = set_test_option("POST_INSTALL", $i);
1709a75fececSSteven Rostedt    $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
1710a75fececSSteven Rostedt    $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
1711a75fececSSteven Rostedt    $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
1712a75fececSSteven Rostedt    $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
1713a75fececSSteven Rostedt    $power_off = set_test_option("POWER_OFF", $i);
1714576f627cSSteven Rostedt    $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
1715576f627cSSteven Rostedt    $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
1716a75fececSSteven Rostedt    $sleep_time = set_test_option("SLEEP_TIME", $i);
1717a75fececSSteven Rostedt    $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
1718a75fececSSteven Rostedt    $store_failures = set_test_option("STORE_FAILURES", $i);
1719a75fececSSteven Rostedt    $timeout = set_test_option("TIMEOUT", $i);
1720a75fececSSteven Rostedt    $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
1721a75fececSSteven Rostedt    $console = set_test_option("CONSOLE", $i);
1722a75fececSSteven Rostedt    $success_line = set_test_option("SUCCESS_LINE", $i);
17231c8a617aSSteven Rostedt    $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
17241c8a617aSSteven Rostedt    $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
1725a75fececSSteven Rostedt    $build_target = set_test_option("BUILD_TARGET", $i);
1726e48c5293SSteven Rostedt    $ssh_exec = set_test_option("SSH_EXEC", $i);
1727e48c5293SSteven Rostedt    $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
1728a75fececSSteven Rostedt    $target_image = set_test_option("TARGET_IMAGE", $i);
1729a75fececSSteven Rostedt    $localversion = set_test_option("LOCALVERSION", $i);
1730a75fececSSteven Rostedt
1731a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
1732a75fececSSteven Rostedt
1733a75fececSSteven Rostedt    if (!-d $tmpdir) {
1734a75fececSSteven Rostedt	mkpath($tmpdir) or
1735a75fececSSteven Rostedt	    die "can't create $tmpdir";
1736a75fececSSteven Rostedt    }
1737a75fececSSteven Rostedt
1738e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
1739e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
1740e48c5293SSteven Rostedt
1741a75fececSSteven Rostedt    $target = "$ssh_user\@$machine";
1742a75fececSSteven Rostedt
1743a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
1744a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
1745a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
174651ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
1747a75fececSSteven Rostedt
1748a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
1749576f627cSSteven Rostedt	dodie "GRUB_MENU not defined" if (!defined($grub_menu));
1750a75fececSSteven Rostedt    } elsif (!defined($reboot_script)) {
1751576f627cSSteven Rostedt	dodie "REBOOT_SCRIPT not defined"
1752a75fececSSteven Rostedt    }
1753a75fececSSteven Rostedt
1754a75fececSSteven Rostedt    my $run_type = $build_type;
1755a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
1756a75fececSSteven Rostedt	$run_type = $opt{"PATCHCHECK_TYPE[$i]"};
1757a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
1758a75fececSSteven Rostedt	$run_type = $opt{"BISECT_TYPE[$i]"};
17590a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
17600a05c769SSteven Rostedt	$run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
1761a75fececSSteven Rostedt    }
1762a75fececSSteven Rostedt
1763a75fececSSteven Rostedt    # mistake in config file?
1764a75fececSSteven Rostedt    if (!defined($run_type)) {
1765a75fececSSteven Rostedt	$run_type = "ERROR";
1766a75fececSSteven Rostedt    }
17672545eb61SSteven Rostedt
17682545eb61SSteven Rostedt    doprint "\n\n";
1769a75fececSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
17707faafbd6SSteven Rostedt
17717faafbd6SSteven Rostedt    unlink $dmesg;
17727faafbd6SSteven Rostedt    unlink $buildlog;
17732545eb61SSteven Rostedt
17742b7d9b21SSteven Rostedt    if (!defined($minconfig)) {
17752b7d9b21SSteven Rostedt	$minconfig = $addconfig;
17762b7d9b21SSteven Rostedt
17772b7d9b21SSteven Rostedt    } elsif (defined($addconfig)) {
17789be2e6b5SSteven Rostedt	run_command "cat $addconfig $minconfig > $tmpdir/add_config" or
17792b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
17809be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
17812b7d9b21SSteven Rostedt    }
17822b7d9b21SSteven Rostedt
17836c5ee0beSSteven Rostedt    my $checkout = $opt{"CHECKOUT[$i]"};
17846c5ee0beSSteven Rostedt    if (defined($checkout)) {
17856c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
17866c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
17876c5ee0beSSteven Rostedt    }
17886c5ee0beSSteven Rostedt
1789a75fececSSteven Rostedt    if ($test_type eq "bisect") {
17905f9b6cedSSteven Rostedt	bisect $i;
17915f9b6cedSSteven Rostedt	next;
17920a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
17930a05c769SSteven Rostedt	config_bisect $i;
17940a05c769SSteven Rostedt	next;
1795a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
17966c5ee0beSSteven Rostedt	patchcheck $i;
17976c5ee0beSSteven Rostedt	next;
17985f9b6cedSSteven Rostedt    }
17995f9b6cedSSteven Rostedt
18007faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
18017faafbd6SSteven Rostedt	build $build_type or next;
18022545eb61SSteven Rostedt    }
18032545eb61SSteven Rostedt
1804a75fececSSteven Rostedt    if ($test_type ne "build") {
18055f9b6cedSSteven Rostedt	get_grub_index;
18065f9b6cedSSteven Rostedt	get_version;
18072545eb61SSteven Rostedt	install;
18085a391fbfSSteven Rostedt
18097faafbd6SSteven Rostedt	my $failed = 0;
18107faafbd6SSteven Rostedt	start_monitor;
18117faafbd6SSteven Rostedt	monitor or $failed = 1;;
1812a75fececSSteven Rostedt
1813a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
18147faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
18155a391fbfSSteven Rostedt	}
18167faafbd6SSteven Rostedt	end_monitor;
18177faafbd6SSteven Rostedt	next if ($failed);
1818a75fececSSteven Rostedt    }
18195a391fbfSSteven Rostedt
18205f9b6cedSSteven Rostedt    success $i;
182175c3fda7SSteven Rostedt}
18222545eb61SSteven Rostedt
18235c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
182475c3fda7SSteven Rostedt    halt;
1825576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
182675c3fda7SSteven Rostedt    reboot;
18275c42fc5bSSteven Rostedt}
182875c3fda7SSteven Rostedt
1829e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
1830e48c5293SSteven Rostedt
18312545eb61SSteven Rostedtexit 0;
1832