xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision e48c5293bde398e253f83fdd0247fb2bc71cc92f)
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
14*e48c5293SSteven Rostedtmy $VERSION = "0.2";
15*e48c5293SSteven Rostedt
16*e48c5293SSteven 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;
45*e48c5293SSteven Rostedt$default{"SSH_EXEC"}		= "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
46*e48c5293SSteven Rostedt$default{"SCP_TO_TARGET"}	= "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE";
47*e48c5293SSteven Rostedt$default{"REBOOT"}		= "ssh \$SSH_USER\@\$MACHINE reboot";
482545eb61SSteven Rostedt
492545eb61SSteven Rostedtmy $version;
50a75fececSSteven Rostedtmy $machine;
51*e48c5293SSteven Rostedtmy $ssh_user;
52a75fececSSteven Rostedtmy $tmpdir;
53a75fececSSteven Rostedtmy $builddir;
54a75fececSSteven Rostedtmy $outputdir;
5551ad1dd1SSteven Rostedtmy $output_config;
56a75fececSSteven Rostedtmy $test_type;
577faafbd6SSteven Rostedtmy $build_type;
58a75fececSSteven Rostedtmy $build_options;
59a75fececSSteven Rostedtmy $reboot_type;
60a75fececSSteven Rostedtmy $reboot_script;
61a75fececSSteven Rostedtmy $power_cycle;
62*e48c5293SSteven Rostedtmy $reboot;
63a75fececSSteven Rostedtmy $reboot_on_error;
64a75fececSSteven Rostedtmy $poweroff_on_error;
65a75fececSSteven Rostedtmy $die_on_failure;
66576f627cSSteven Rostedtmy $powercycle_after_reboot;
67576f627cSSteven Rostedtmy $poweroff_after_halt;
68*e48c5293SSteven Rostedtmy $ssh_exec;
69*e48c5293SSteven Rostedtmy $scp_to_target;
70a75fececSSteven Rostedtmy $power_off;
71a75fececSSteven Rostedtmy $grub_menu;
722545eb61SSteven Rostedtmy $grub_number;
732545eb61SSteven Rostedtmy $target;
742545eb61SSteven Rostedtmy $make;
758b37ca8cSSteven Rostedtmy $post_install;
765c42fc5bSSteven Rostedtmy $noclean;
775f9b6cedSSteven Rostedtmy $minconfig;
782b7d9b21SSteven Rostedtmy $addconfig;
795f9b6cedSSteven Rostedtmy $in_bisect = 0;
805f9b6cedSSteven Rostedtmy $bisect_bad = "";
81d6ce2a0bSSteven Rostedtmy $reverse_bisect;
826c5ee0beSSteven Rostedtmy $in_patchcheck = 0;
835a391fbfSSteven Rostedtmy $run_test;
846c5ee0beSSteven Rostedtmy $redirect;
857faafbd6SSteven Rostedtmy $buildlog;
867faafbd6SSteven Rostedtmy $dmesg;
877faafbd6SSteven Rostedtmy $monitor_fp;
887faafbd6SSteven Rostedtmy $monitor_pid;
897faafbd6SSteven Rostedtmy $monitor_cnt = 0;
90a75fececSSteven Rostedtmy $sleep_time;
91a75fececSSteven Rostedtmy $bisect_sleep_time;
92a75fececSSteven Rostedtmy $store_failures;
93a75fececSSteven Rostedtmy $timeout;
94a75fececSSteven Rostedtmy $booted_timeout;
95a75fececSSteven Rostedtmy $console;
96a75fececSSteven Rostedtmy $success_line;
97a75fececSSteven Rostedtmy $build_target;
98a75fececSSteven Rostedtmy $target_image;
99a75fececSSteven Rostedtmy $localversion;
100576f627cSSteven Rostedtmy $iteration = 0;
101*e48c5293SSteven Rostedtmy $successes = 0;
1022545eb61SSteven Rostedt
103a57419b3SSteven Rostedtsub set_value {
104a57419b3SSteven Rostedt    my ($lvalue, $rvalue) = @_;
1052545eb61SSteven Rostedt
106a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
107a75fececSSteven Rostedt	die "Error: Option $lvalue defined more than once!\n";
108a75fececSSteven Rostedt    }
1092545eb61SSteven Rostedt    $opt{$lvalue} = $rvalue;
11021a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
11121a9679fSSteven Rostedt	delete $opt{$lvalue};
11221a9679fSSteven Rostedt    } else {
11321a9679fSSteven Rostedt	$opt{$lvalue} = $rvalue;
11421a9679fSSteven Rostedt    }
1152545eb61SSteven Rostedt}
116a57419b3SSteven Rostedt
117a57419b3SSteven Rostedtsub read_config {
118a57419b3SSteven Rostedt    my ($config) = @_;
119a57419b3SSteven Rostedt
120a57419b3SSteven Rostedt    open(IN, $config) || die "can't read file $config";
121a57419b3SSteven Rostedt
122a57419b3SSteven Rostedt    my $name = $config;
123a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
124a57419b3SSteven Rostedt
125a57419b3SSteven Rostedt    my $test_num = 0;
126a57419b3SSteven Rostedt    my $default = 1;
127a57419b3SSteven Rostedt    my $repeat = 1;
128a57419b3SSteven Rostedt    my $num_tests_set = 0;
129a57419b3SSteven Rostedt    my $skip = 0;
130a57419b3SSteven Rostedt    my $rest;
131a57419b3SSteven Rostedt
132a57419b3SSteven Rostedt    while (<IN>) {
133a57419b3SSteven Rostedt
134a57419b3SSteven Rostedt	# ignore blank lines and comments
135a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
136a57419b3SSteven Rostedt
137a57419b3SSteven Rostedt	if (/^\s*TEST_START(.*)/) {
138a57419b3SSteven Rostedt
139a57419b3SSteven Rostedt	    $rest = $1;
140a57419b3SSteven Rostedt
141a57419b3SSteven Rostedt	    if ($num_tests_set) {
142a57419b3SSteven Rostedt		die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
143a57419b3SSteven Rostedt	    }
144a57419b3SSteven Rostedt
145a57419b3SSteven Rostedt	    my $old_test_num = $test_num;
146*e48c5293SSteven Rostedt	    my $old_repeat = $repeat;
147a57419b3SSteven Rostedt
148a57419b3SSteven Rostedt	    $test_num += $repeat;
149a57419b3SSteven Rostedt	    $default = 0;
150a57419b3SSteven Rostedt	    $repeat = 1;
151a57419b3SSteven Rostedt
152a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
153a57419b3SSteven Rostedt		$rest = $1;
154a57419b3SSteven Rostedt		$skip = 1;
155a57419b3SSteven Rostedt	    } else {
156a57419b3SSteven Rostedt		$skip = 0;
157a57419b3SSteven Rostedt	    }
158a57419b3SSteven Rostedt
159a57419b3SSteven Rostedt	    if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
160a57419b3SSteven Rostedt		$repeat = $1;
161a57419b3SSteven Rostedt		$rest = $2;
162a57419b3SSteven Rostedt		$repeat_tests{"$test_num"} = $repeat;
163a57419b3SSteven Rostedt	    }
164a57419b3SSteven Rostedt
165a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
166a57419b3SSteven Rostedt		$rest = $1;
167a57419b3SSteven Rostedt		$skip = 1;
168a57419b3SSteven Rostedt	    }
169a57419b3SSteven Rostedt
170a57419b3SSteven Rostedt	    if ($rest !~ /^\s*$/) {
171a57419b3SSteven Rostedt		die "$name: $.: Gargbage found after TEST_START\n$_";
172a57419b3SSteven Rostedt	    }
173a57419b3SSteven Rostedt
174a57419b3SSteven Rostedt	    if ($skip) {
175a57419b3SSteven Rostedt		$test_num = $old_test_num;
176*e48c5293SSteven Rostedt		$repeat = $old_repeat;
177a57419b3SSteven Rostedt	    }
178a57419b3SSteven Rostedt
179a57419b3SSteven Rostedt	} elsif (/^\s*DEFAULTS(.*)$/) {
180a57419b3SSteven Rostedt	    $default = 1;
181a57419b3SSteven Rostedt
182a57419b3SSteven Rostedt	    $rest = $1;
183a57419b3SSteven Rostedt
184a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
185a57419b3SSteven Rostedt		$rest = $1;
186a57419b3SSteven Rostedt		$skip = 1;
187a57419b3SSteven Rostedt	    } else {
188a57419b3SSteven Rostedt		$skip = 0;
189a57419b3SSteven Rostedt	    }
190a57419b3SSteven Rostedt
191a57419b3SSteven Rostedt	    if ($rest !~ /^\s*$/) {
192a57419b3SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
193a57419b3SSteven Rostedt	    }
194a57419b3SSteven Rostedt
195a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
196a57419b3SSteven Rostedt
197a57419b3SSteven Rostedt	    next if ($skip);
198a57419b3SSteven Rostedt
199a57419b3SSteven Rostedt	    my $lvalue = $1;
200a57419b3SSteven Rostedt	    my $rvalue = $2;
201a57419b3SSteven Rostedt
202a57419b3SSteven Rostedt	    if (!$default &&
203a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
204a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
205a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
206a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
207a57419b3SSteven Rostedt	    }
208a57419b3SSteven Rostedt
209a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
210a57419b3SSteven Rostedt		if ($test_num) {
211a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
212a57419b3SSteven Rostedt		}
213a57419b3SSteven Rostedt		if (!$default) {
214a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
215a57419b3SSteven Rostedt		}
216a57419b3SSteven Rostedt		$num_tests_set = 1;
217a57419b3SSteven Rostedt	    }
218a57419b3SSteven Rostedt
219a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
220a57419b3SSteven Rostedt		set_value($lvalue, $rvalue);
221a57419b3SSteven Rostedt	    } else {
222a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
223a57419b3SSteven Rostedt		set_value($val, $rvalue);
224a57419b3SSteven Rostedt
225a57419b3SSteven Rostedt		if ($repeat > 1) {
226a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
227a57419b3SSteven Rostedt		}
228a57419b3SSteven Rostedt	    }
229a57419b3SSteven Rostedt	} else {
230a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
231a57419b3SSteven Rostedt	}
2322545eb61SSteven Rostedt    }
2332545eb61SSteven Rostedt
2342545eb61SSteven Rostedt    close(IN);
235a75fececSSteven Rostedt
236a57419b3SSteven Rostedt    if ($test_num) {
237a57419b3SSteven Rostedt	$test_num += $repeat - 1;
238a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
239a57419b3SSteven Rostedt    }
240a57419b3SSteven Rostedt
241a75fececSSteven Rostedt    # set any defaults
242a75fececSSteven Rostedt
243a75fececSSteven Rostedt    foreach my $default (keys %default) {
244a75fececSSteven Rostedt	if (!defined($opt{$default})) {
245a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
246a75fececSSteven Rostedt	}
247a75fececSSteven Rostedt    }
2482545eb61SSteven Rostedt}
2492545eb61SSteven Rostedt
250d1e2f22aSSteven Rostedtsub _logit {
2512545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
2522545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
2532545eb61SSteven Rostedt	print OUT @_;
2542545eb61SSteven Rostedt	close(OUT);
2552545eb61SSteven Rostedt    }
2562545eb61SSteven Rostedt}
2572545eb61SSteven Rostedt
258d1e2f22aSSteven Rostedtsub logit {
259d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
260d1e2f22aSSteven Rostedt	_logit @_;
261d1e2f22aSSteven Rostedt    } else {
262d1e2f22aSSteven Rostedt	print @_;
263d1e2f22aSSteven Rostedt    }
264d1e2f22aSSteven Rostedt}
265d1e2f22aSSteven Rostedt
2665f9b6cedSSteven Rostedtsub doprint {
2675f9b6cedSSteven Rostedt    print @_;
268d1e2f22aSSteven Rostedt    _logit @_;
2695f9b6cedSSteven Rostedt}
2705f9b6cedSSteven Rostedt
2717faafbd6SSteven Rostedtsub run_command;
2727faafbd6SSteven Rostedt
2737faafbd6SSteven Rostedtsub reboot {
2747faafbd6SSteven Rostedt    # try to reboot normally
275*e48c5293SSteven Rostedt    if (run_command $reboot) {
276576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
277576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
278576f627cSSteven Rostedt	    run_command "$power_cycle";
279576f627cSSteven Rostedt	}
280576f627cSSteven Rostedt    } else {
2817faafbd6SSteven Rostedt	# nope? power cycle it.
282a75fececSSteven Rostedt	run_command "$power_cycle";
2837faafbd6SSteven Rostedt    }
2847faafbd6SSteven Rostedt}
2857faafbd6SSteven Rostedt
286576f627cSSteven Rostedtsub do_not_reboot {
287576f627cSSteven Rostedt    my $i = $iteration;
288576f627cSSteven Rostedt
289576f627cSSteven Rostedt    return $test_type eq "build" ||
290576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
291576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
292576f627cSSteven Rostedt}
293576f627cSSteven Rostedt
2945c42fc5bSSteven Rostedtsub dodie {
2955a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
2965c42fc5bSSteven Rostedt
297576f627cSSteven Rostedt    my $i = $iteration;
298576f627cSSteven Rostedt
299576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
300576f627cSSteven Rostedt
30175c3fda7SSteven Rostedt	doprint "REBOOTING\n";
3027faafbd6SSteven Rostedt	reboot;
30375c3fda7SSteven Rostedt
304a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
3055c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
306a75fececSSteven Rostedt	`$power_off`;
3075c42fc5bSSteven Rostedt    }
30875c3fda7SSteven Rostedt
309576f627cSSteven Rostedt    die @_, "\n";
3105c42fc5bSSteven Rostedt}
3115c42fc5bSSteven Rostedt
3127faafbd6SSteven Rostedtsub open_console {
3137faafbd6SSteven Rostedt    my ($fp) = @_;
3147faafbd6SSteven Rostedt
3157faafbd6SSteven Rostedt    my $flags;
3167faafbd6SSteven Rostedt
317a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
318a75fececSSteven Rostedt	dodie "Can't open console $console";
3197faafbd6SSteven Rostedt
3207faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
321576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
3227faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
323576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
3247faafbd6SSteven Rostedt
3257faafbd6SSteven Rostedt    return $pid;
3267faafbd6SSteven Rostedt}
3277faafbd6SSteven Rostedt
3287faafbd6SSteven Rostedtsub close_console {
3297faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
3307faafbd6SSteven Rostedt
3317faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
3327faafbd6SSteven Rostedt    kill 2, $pid;
3337faafbd6SSteven Rostedt
3347faafbd6SSteven Rostedt    print "closing!\n";
3357faafbd6SSteven Rostedt    close($fp);
3367faafbd6SSteven Rostedt}
3377faafbd6SSteven Rostedt
3387faafbd6SSteven Rostedtsub start_monitor {
3397faafbd6SSteven Rostedt    if ($monitor_cnt++) {
3407faafbd6SSteven Rostedt	return;
3417faafbd6SSteven Rostedt    }
3427faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
3437faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
344a75fececSSteven Rostedt
345a75fececSSteven Rostedt    return;
346a75fececSSteven Rostedt
347a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
3487faafbd6SSteven Rostedt}
3497faafbd6SSteven Rostedt
3507faafbd6SSteven Rostedtsub end_monitor {
3517faafbd6SSteven Rostedt    if (--$monitor_cnt) {
3527faafbd6SSteven Rostedt	return;
3537faafbd6SSteven Rostedt    }
3547faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
3557faafbd6SSteven Rostedt}
3567faafbd6SSteven Rostedt
3577faafbd6SSteven Rostedtsub wait_for_monitor {
3587faafbd6SSteven Rostedt    my ($time) = @_;
3597faafbd6SSteven Rostedt    my $line;
3607faafbd6SSteven Rostedt
361a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
3627faafbd6SSteven Rostedt
3637faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
3647faafbd6SSteven Rostedt    do {
3657faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
366a75fececSSteven Rostedt	print "$line" if (defined($line));
3677faafbd6SSteven Rostedt    } while (defined($line));
368a75fececSSteven Rostedt    print "** Monitor flushed **\n";
3697faafbd6SSteven Rostedt}
3707faafbd6SSteven Rostedt
3712b7d9b21SSteven Rostedtsub fail {
3722b7d9b21SSteven Rostedt
373a75fececSSteven Rostedt	if ($die_on_failure) {
3742b7d9b21SSteven Rostedt		dodie @_;
3752b7d9b21SSteven Rostedt	}
3762b7d9b21SSteven Rostedt
377a75fececSSteven Rostedt	doprint "FAILED\n";
3787faafbd6SSteven Rostedt
379576f627cSSteven Rostedt	my $i = $iteration;
380576f627cSSteven Rostedt
381a75fececSSteven Rostedt	# no need to reboot for just building.
382576f627cSSteven Rostedt	if (!do_not_reboot) {
3837faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
3847faafbd6SSteven Rostedt	    reboot;
3857faafbd6SSteven Rostedt	    start_monitor;
386a75fececSSteven Rostedt	    wait_for_monitor $sleep_time;
3877faafbd6SSteven Rostedt	    end_monitor;
388a75fececSSteven Rostedt	}
3897faafbd6SSteven Rostedt
390576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
391576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
3927a849cd9SSteven Rostedt	doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n";
393576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
394576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
395a75fececSSteven Rostedt
396a75fececSSteven Rostedt	return 1 if (!defined($store_failures));
3977faafbd6SSteven Rostedt
3987faafbd6SSteven Rostedt	my @t = localtime;
3997faafbd6SSteven Rostedt	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
4007faafbd6SSteven Rostedt		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
4017faafbd6SSteven Rostedt
402a75fececSSteven Rostedt	my $dir = "$machine-$test_type-$build_type-fail-$date";
403a75fececSSteven Rostedt	my $faildir = "$store_failures/$dir";
4047faafbd6SSteven Rostedt
4057faafbd6SSteven Rostedt	if (!-d $faildir) {
4067faafbd6SSteven Rostedt	    mkpath($faildir) or
407a75fececSSteven Rostedt		die "can't create $faildir";
4087faafbd6SSteven Rostedt	}
40951ad1dd1SSteven Rostedt	if (-f "$output_config") {
41051ad1dd1SSteven Rostedt	    cp "$output_config", "$faildir/config" or
4117faafbd6SSteven Rostedt		die "failed to copy .config";
4127faafbd6SSteven Rostedt	}
4137faafbd6SSteven Rostedt	if (-f $buildlog) {
4147faafbd6SSteven Rostedt	    cp $buildlog, "$faildir/buildlog" or
4157faafbd6SSteven Rostedt		die "failed to move $buildlog";
4167faafbd6SSteven Rostedt	}
4177faafbd6SSteven Rostedt	if (-f $dmesg) {
4187faafbd6SSteven Rostedt	    cp $dmesg, "$faildir/dmesg" or
4197faafbd6SSteven Rostedt		die "failed to move $dmesg";
4207faafbd6SSteven Rostedt	}
4217faafbd6SSteven Rostedt
4227faafbd6SSteven Rostedt	doprint "*** Saved info to $faildir ***\n";
4237faafbd6SSteven Rostedt
4242b7d9b21SSteven Rostedt	return 1;
4252b7d9b21SSteven Rostedt}
4262b7d9b21SSteven Rostedt
4272545eb61SSteven Rostedtsub run_command {
4282545eb61SSteven Rostedt    my ($command) = @_;
429d6ce2a0bSSteven Rostedt    my $dolog = 0;
430d6ce2a0bSSteven Rostedt    my $dord = 0;
431d6ce2a0bSSteven Rostedt    my $pid;
432d6ce2a0bSSteven Rostedt
433*e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
434*e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
435*e48c5293SSteven Rostedt
436d6ce2a0bSSteven Rostedt    doprint("$command ... ");
437d6ce2a0bSSteven Rostedt
438d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
4392b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
4402545eb61SSteven Rostedt
4412545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
442d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
443d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
444d6ce2a0bSSteven Rostedt	$dolog = 1;
4456c5ee0beSSteven Rostedt    }
4466c5ee0beSSteven Rostedt
4476c5ee0beSSteven Rostedt    if (defined($redirect)) {
448d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
449d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
450d6ce2a0bSSteven Rostedt	$dord = 1;
4512545eb61SSteven Rostedt    }
4522545eb61SSteven Rostedt
453d6ce2a0bSSteven Rostedt    while (<CMD>) {
454d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
455d6ce2a0bSSteven Rostedt	print RD  if ($dord);
456d6ce2a0bSSteven Rostedt    }
4572545eb61SSteven Rostedt
458d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
4592545eb61SSteven Rostedt    my $failed = $?;
4602545eb61SSteven Rostedt
461d6ce2a0bSSteven Rostedt    close(CMD);
462d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
463d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
464d6ce2a0bSSteven Rostedt
4652545eb61SSteven Rostedt    if ($failed) {
4662545eb61SSteven Rostedt	doprint "FAILED!\n";
4672545eb61SSteven Rostedt    } else {
4682545eb61SSteven Rostedt	doprint "SUCCESS\n";
4692545eb61SSteven Rostedt    }
4702545eb61SSteven Rostedt
4715f9b6cedSSteven Rostedt    return !$failed;
4725f9b6cedSSteven Rostedt}
4735f9b6cedSSteven Rostedt
474*e48c5293SSteven Rostedtsub run_ssh {
475*e48c5293SSteven Rostedt    my ($cmd) = @_;
476*e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
477*e48c5293SSteven Rostedt
478*e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
479*e48c5293SSteven Rostedt    return run_command "$cp_exec";
480*e48c5293SSteven Rostedt}
481*e48c5293SSteven Rostedt
482*e48c5293SSteven Rostedtsub run_scp {
483*e48c5293SSteven Rostedt    my ($src, $dst) = @_;
484*e48c5293SSteven Rostedt    my $cp_scp = $scp_to_target;
485*e48c5293SSteven Rostedt
486*e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
487*e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
488*e48c5293SSteven Rostedt
489*e48c5293SSteven Rostedt    return run_command "$cp_scp";
490*e48c5293SSteven Rostedt}
491*e48c5293SSteven Rostedt
4925f9b6cedSSteven Rostedtsub get_grub_index {
4935f9b6cedSSteven Rostedt
494a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
495a75fececSSteven Rostedt	return;
496a75fececSSteven Rostedt    }
4975a391fbfSSteven Rostedt    return if (defined($grub_number));
4985f9b6cedSSteven Rostedt
4995f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
5005f9b6cedSSteven Rostedt    $grub_number = -1;
501*e48c5293SSteven Rostedt
502*e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
503*e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
504*e48c5293SSteven Rostedt
505*e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
5065f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
507*e48c5293SSteven Rostedt
5085f9b6cedSSteven Rostedt    while (<IN>) {
509a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
5105f9b6cedSSteven Rostedt	    $grub_number++;
5115f9b6cedSSteven Rostedt	    last;
5125f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
5135f9b6cedSSteven Rostedt	    $grub_number++;
5145f9b6cedSSteven Rostedt	}
5155f9b6cedSSteven Rostedt    }
5165f9b6cedSSteven Rostedt    close(IN);
5175f9b6cedSSteven Rostedt
518a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
5195f9b6cedSSteven Rostedt	if ($grub_number < 0);
5205f9b6cedSSteven Rostedt    doprint "$grub_number\n";
5212545eb61SSteven Rostedt}
5222545eb61SSteven Rostedt
5232545eb61SSteven Rostedtsub wait_for_input
5242545eb61SSteven Rostedt{
5252545eb61SSteven Rostedt    my ($fp, $time) = @_;
5262545eb61SSteven Rostedt    my $rin;
5272545eb61SSteven Rostedt    my $ready;
5282545eb61SSteven Rostedt    my $line;
5292545eb61SSteven Rostedt    my $ch;
5302545eb61SSteven Rostedt
5312545eb61SSteven Rostedt    if (!defined($time)) {
5322545eb61SSteven Rostedt	$time = $timeout;
5332545eb61SSteven Rostedt    }
5342545eb61SSteven Rostedt
5352545eb61SSteven Rostedt    $rin = '';
5362545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
5372545eb61SSteven Rostedt    $ready = select($rin, undef, undef, $time);
5382545eb61SSteven Rostedt
5392545eb61SSteven Rostedt    $line = "";
5402545eb61SSteven Rostedt
5412545eb61SSteven Rostedt    # try to read one char at a time
5422545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
5432545eb61SSteven Rostedt	$line .= $ch;
5442545eb61SSteven Rostedt	last if ($ch eq "\n");
5452545eb61SSteven Rostedt    }
5462545eb61SSteven Rostedt
5472545eb61SSteven Rostedt    if (!length($line)) {
5482545eb61SSteven Rostedt	return undef;
5492545eb61SSteven Rostedt    }
5502545eb61SSteven Rostedt
5512545eb61SSteven Rostedt    return $line;
5522545eb61SSteven Rostedt}
5532545eb61SSteven Rostedt
55475c3fda7SSteven Rostedtsub reboot_to {
555a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
556*e48c5293SSteven Rostedt	run_command "$ssh_exec '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
557a75fececSSteven Rostedt	return;
558a75fececSSteven Rostedt    }
559a75fececSSteven Rostedt
560a75fececSSteven Rostedt    run_command "$reboot_script";
5612545eb61SSteven Rostedt}
5622545eb61SSteven Rostedt
563a57419b3SSteven Rostedtsub get_sha1 {
564a57419b3SSteven Rostedt    my ($commit) = @_;
565a57419b3SSteven Rostedt
566a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
567a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
568a57419b3SSteven Rostedt    my $ret = $?;
569a57419b3SSteven Rostedt
570a57419b3SSteven Rostedt    logit $sha1;
571a57419b3SSteven Rostedt
572a57419b3SSteven Rostedt    if ($ret) {
573a57419b3SSteven Rostedt	doprint "FAILED\n";
574a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
575a57419b3SSteven Rostedt    }
576a57419b3SSteven Rostedt
577a57419b3SSteven Rostedt    print "SUCCESS\n";
578a57419b3SSteven Rostedt
579a57419b3SSteven Rostedt    chomp $sha1;
580a57419b3SSteven Rostedt
581a57419b3SSteven Rostedt    return $sha1;
582a57419b3SSteven Rostedt}
583a57419b3SSteven Rostedt
5845a391fbfSSteven Rostedtsub monitor {
5852545eb61SSteven Rostedt    my $booted = 0;
5862545eb61SSteven Rostedt    my $bug = 0;
5875c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
5882b7d9b21SSteven Rostedt    my $loops;
5892545eb61SSteven Rostedt
5907faafbd6SSteven Rostedt    wait_for_monitor 5;
5912545eb61SSteven Rostedt
5922545eb61SSteven Rostedt    my $line;
5932545eb61SSteven Rostedt    my $full_line = "";
5942545eb61SSteven Rostedt
5957faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
5967faafbd6SSteven Rostedt	die "unable to write to $dmesg";
5972545eb61SSteven Rostedt
59875c3fda7SSteven Rostedt    reboot_to;
5992545eb61SSteven Rostedt
6002545eb61SSteven Rostedt    for (;;) {
6012545eb61SSteven Rostedt
6022b7d9b21SSteven Rostedt	if ($booted) {
603a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
6042b7d9b21SSteven Rostedt	} else {
6057faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
6062b7d9b21SSteven Rostedt	}
6072545eb61SSteven Rostedt
6082545eb61SSteven Rostedt	last if (!defined($line));
6092545eb61SSteven Rostedt
6102545eb61SSteven Rostedt	doprint $line;
6117faafbd6SSteven Rostedt	print DMESG $line;
6122545eb61SSteven Rostedt
6132545eb61SSteven Rostedt	# we are not guaranteed to get a full line
6142545eb61SSteven Rostedt	$full_line .= $line;
6152545eb61SSteven Rostedt
616a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
6172545eb61SSteven Rostedt	    $booted = 1;
6182545eb61SSteven Rostedt	}
6192545eb61SSteven Rostedt
6205c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
6215c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
6225c42fc5bSSteven Rostedt	}
6235c42fc5bSSteven Rostedt
6242545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
6255c42fc5bSSteven Rostedt	    $bug = 1 if (!$skip_call_trace);
6265c42fc5bSSteven Rostedt	}
6275c42fc5bSSteven Rostedt
6285c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
6295c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
6305c42fc5bSSteven Rostedt	}
6315c42fc5bSSteven Rostedt
6325c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
6332545eb61SSteven Rostedt	    $bug = 1;
6342545eb61SSteven Rostedt	}
6352545eb61SSteven Rostedt
6362545eb61SSteven Rostedt	if ($line =~ /\n/) {
6372545eb61SSteven Rostedt	    $full_line = "";
6382545eb61SSteven Rostedt	}
6392545eb61SSteven Rostedt    }
6402545eb61SSteven Rostedt
6417faafbd6SSteven Rostedt    close(DMESG);
6422545eb61SSteven Rostedt
6432545eb61SSteven Rostedt    if ($bug) {
6442b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
645576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
6462545eb61SSteven Rostedt    }
6475f9b6cedSSteven Rostedt
648a75fececSSteven Rostedt    if (!$booted) {
649a75fececSSteven Rostedt	return 0 if ($in_bisect);
650576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
651a75fececSSteven Rostedt    }
652a75fececSSteven Rostedt
6532b7d9b21SSteven Rostedt    return 1;
6542545eb61SSteven Rostedt}
6552545eb61SSteven Rostedt
6562545eb61SSteven Rostedtsub install {
6572545eb61SSteven Rostedt
658*e48c5293SSteven Rostedt    run_scp "$outputdir/$build_target", "$target_image" or
6595c42fc5bSSteven Rostedt	dodie "failed to copy image";
6605f9b6cedSSteven Rostedt
6615f9b6cedSSteven Rostedt    my $install_mods = 0;
6625f9b6cedSSteven Rostedt
6635f9b6cedSSteven Rostedt    # should we process modules?
6645f9b6cedSSteven Rostedt    $install_mods = 0;
66551ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
6665f9b6cedSSteven Rostedt    while (<IN>) {
6675f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
6685f9b6cedSSteven Rostedt	    $install_mods = 1 if (defined($1));
6695f9b6cedSSteven Rostedt	    last;
6705f9b6cedSSteven Rostedt	}
6715f9b6cedSSteven Rostedt    }
6725f9b6cedSSteven Rostedt    close(IN);
6735f9b6cedSSteven Rostedt
6745f9b6cedSSteven Rostedt    if (!$install_mods) {
6755f9b6cedSSteven Rostedt	doprint "No modules needed\n";
6765f9b6cedSSteven Rostedt	return;
6772545eb61SSteven Rostedt    }
6782545eb61SSteven Rostedt
679a75fececSSteven Rostedt    run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
6805f9b6cedSSteven Rostedt	dodie "Failed to install modules";
6815f9b6cedSSteven Rostedt
6822545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
683a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
6842545eb61SSteven Rostedt
685*e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
6865c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
6872545eb61SSteven Rostedt
6885c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
689a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
6905c42fc5bSSteven Rostedt	dodie "making tarball";
6915c42fc5bSSteven Rostedt
692*e48c5293SSteven Rostedt    run_scp "$tmpdir/$modtar", "/tmp" or
6935c42fc5bSSteven Rostedt	dodie "failed to copy modules";
6945c42fc5bSSteven Rostedt
695a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
6965c42fc5bSSteven Rostedt
697*e48c5293SSteven Rostedt    run_ssh "'(cd / && tar xf /tmp/$modtar)'" or
6985c42fc5bSSteven Rostedt	dodie "failed to tar modules";
6995c42fc5bSSteven Rostedt
700*e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
7018b37ca8cSSteven Rostedt
7028b37ca8cSSteven Rostedt    return if (!defined($post_install));
7038b37ca8cSSteven Rostedt
704*e48c5293SSteven Rostedt    my $cp_post_install = $post_install;
705*e48c5293SSteven Rostedt    $cp_post_install = s/\$KERNEL_VERSION/$version/g;
706*e48c5293SSteven Rostedt    run_command "$cp_post_install" or
707576f627cSSteven Rostedt	dodie "Failed to run post install";
7082545eb61SSteven Rostedt}
7092545eb61SSteven Rostedt
7106c5ee0beSSteven Rostedtsub check_buildlog {
7116c5ee0beSSteven Rostedt    my ($patch) = @_;
7126c5ee0beSSteven Rostedt
7136c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
7146c5ee0beSSteven Rostedt
7156c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
7166c5ee0beSSteven Rostedt	dodie "failed to show $patch";
7176c5ee0beSSteven Rostedt    while (<IN>) {
7186c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
7196c5ee0beSSteven Rostedt	    chomp $1;
7206c5ee0beSSteven Rostedt	    $files[$#files] = $1;
7216c5ee0beSSteven Rostedt	}
7226c5ee0beSSteven Rostedt    }
7236c5ee0beSSteven Rostedt    close(IN);
7246c5ee0beSSteven Rostedt
7256c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
7266c5ee0beSSteven Rostedt    while (<IN>) {
7276c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
7286c5ee0beSSteven Rostedt	    my $err = $1;
7296c5ee0beSSteven Rostedt	    foreach my $file (@files) {
730a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
7316c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
7322b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
7336c5ee0beSSteven Rostedt		}
7346c5ee0beSSteven Rostedt	    }
7356c5ee0beSSteven Rostedt	}
7366c5ee0beSSteven Rostedt    }
7376c5ee0beSSteven Rostedt    close(IN);
7382b7d9b21SSteven Rostedt
7392b7d9b21SSteven Rostedt    return 1;
7406c5ee0beSSteven Rostedt}
7416c5ee0beSSteven Rostedt
7422545eb61SSteven Rostedtsub build {
7432545eb61SSteven Rostedt    my ($type) = @_;
7445c42fc5bSSteven Rostedt    my $defconfig = "";
7452545eb61SSteven Rostedt
7467faafbd6SSteven Rostedt    unlink $buildlog;
7477faafbd6SSteven Rostedt
74875c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
74951ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
75075c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
7515f9b6cedSSteven Rostedt
75275c3fda7SSteven Rostedt	$type = "oldconfig";
75375c3fda7SSteven Rostedt    }
75475c3fda7SSteven Rostedt
7555c42fc5bSSteven Rostedt    # old config can ask questions
7565c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
7579386c6abSSteven Rostedt	$type = "oldnoconfig";
75875c3fda7SSteven Rostedt
75975c3fda7SSteven Rostedt	# allow for empty configs
76051ad1dd1SSteven Rostedt	run_command "touch $output_config";
76175c3fda7SSteven Rostedt
76251ad1dd1SSteven Rostedt	run_command "mv $output_config $outputdir/config_temp" or
7635c42fc5bSSteven Rostedt	    dodie "moving .config";
7645c42fc5bSSteven Rostedt
7655f9b6cedSSteven Rostedt	if (!$noclean && !run_command "$make mrproper") {
7665c42fc5bSSteven Rostedt	    dodie "make mrproper";
7675c42fc5bSSteven Rostedt	}
7685c42fc5bSSteven Rostedt
76951ad1dd1SSteven Rostedt	run_command "mv $outputdir/config_temp $output_config" or
7705c42fc5bSSteven Rostedt	    dodie "moving config_temp";
7715c42fc5bSSteven Rostedt
7725c42fc5bSSteven Rostedt    } elsif (!$noclean) {
77351ad1dd1SSteven Rostedt	unlink "$output_config";
7745f9b6cedSSteven Rostedt	run_command "$make mrproper" or
7755c42fc5bSSteven Rostedt	    dodie "make mrproper";
7765c42fc5bSSteven Rostedt    }
7772545eb61SSteven Rostedt
7782545eb61SSteven Rostedt    # add something to distinguish this build
779a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
780a75fececSSteven Rostedt    print OUT "$localversion\n";
7812545eb61SSteven Rostedt    close(OUT);
7822545eb61SSteven Rostedt
7835f9b6cedSSteven Rostedt    if (defined($minconfig)) {
7845f9b6cedSSteven Rostedt	$defconfig = "KCONFIG_ALLCONFIG=$minconfig";
7852545eb61SSteven Rostedt    }
7862545eb61SSteven Rostedt
7879386c6abSSteven Rostedt    run_command "$defconfig $make $type" or
7885c42fc5bSSteven Rostedt	dodie "failed make config";
7892545eb61SSteven Rostedt
790a75fececSSteven Rostedt    $redirect = "$buildlog";
791a75fececSSteven Rostedt    if (!run_command "$make $build_options") {
7926c5ee0beSSteven Rostedt	undef $redirect;
7935f9b6cedSSteven Rostedt	# bisect may need this to pass
7942b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
7952b7d9b21SSteven Rostedt	fail "failed build" and return 0;
7962545eb61SSteven Rostedt    }
7976c5ee0beSSteven Rostedt    undef $redirect;
7985f9b6cedSSteven Rostedt
7992b7d9b21SSteven Rostedt    return 1;
8002545eb61SSteven Rostedt}
8012545eb61SSteven Rostedt
80275c3fda7SSteven Rostedtsub halt {
803*e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
804576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
805576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
806576f627cSSteven Rostedt	    run_command "$power_off";
807576f627cSSteven Rostedt	}
808576f627cSSteven Rostedt    } else {
80975c3fda7SSteven Rostedt	# nope? the zap it!
810a75fececSSteven Rostedt	run_command "$power_off";
81175c3fda7SSteven Rostedt    }
81275c3fda7SSteven Rostedt}
81375c3fda7SSteven Rostedt
8145f9b6cedSSteven Rostedtsub success {
8155f9b6cedSSteven Rostedt    my ($i) = @_;
8165f9b6cedSSteven Rostedt
817*e48c5293SSteven Rostedt    $successes++;
818*e48c5293SSteven Rostedt
8195f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
8205f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
8217a849cd9SSteven Rostedt    doprint     "KTEST RESULT: TEST $i SUCCESS!!!!         **\n";
8225f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
8235f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
8245f9b6cedSSteven Rostedt
825576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
826a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
8275f9b6cedSSteven Rostedt	reboot;
8287faafbd6SSteven Rostedt	start_monitor;
829a75fececSSteven Rostedt	wait_for_monitor $sleep_time;
8307faafbd6SSteven Rostedt	end_monitor;
8315f9b6cedSSteven Rostedt    }
8325f9b6cedSSteven Rostedt}
8335f9b6cedSSteven Rostedt
8345f9b6cedSSteven Rostedtsub get_version {
8355f9b6cedSSteven Rostedt    # get the release name
8365f9b6cedSSteven Rostedt    doprint "$make kernelrelease ... ";
8375f9b6cedSSteven Rostedt    $version = `$make kernelrelease | tail -1`;
8385f9b6cedSSteven Rostedt    chomp($version);
8395f9b6cedSSteven Rostedt    doprint "$version\n";
8405f9b6cedSSteven Rostedt}
8415f9b6cedSSteven Rostedt
8425a391fbfSSteven Rostedtsub child_run_test {
8437faafbd6SSteven Rostedt    my $failed = 0;
8445a391fbfSSteven Rostedt
8457faafbd6SSteven Rostedt    # child should have no power
846a75fececSSteven Rostedt    $reboot_on_error = 0;
847a75fececSSteven Rostedt    $poweroff_on_error = 0;
848a75fececSSteven Rostedt    $die_on_failure = 1;
8497faafbd6SSteven Rostedt
8507faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
8515a391fbfSSteven Rostedt    exit $failed;
8525a391fbfSSteven Rostedt}
8535a391fbfSSteven Rostedt
8545a391fbfSSteven Rostedtmy $child_done;
8555a391fbfSSteven Rostedt
8565a391fbfSSteven Rostedtsub child_finished {
8575a391fbfSSteven Rostedt    $child_done = 1;
8585a391fbfSSteven Rostedt}
8595a391fbfSSteven Rostedt
8605a391fbfSSteven Rostedtsub do_run_test {
8615a391fbfSSteven Rostedt    my $child_pid;
8625a391fbfSSteven Rostedt    my $child_exit;
8635a391fbfSSteven Rostedt    my $line;
8645a391fbfSSteven Rostedt    my $full_line;
8655a391fbfSSteven Rostedt    my $bug = 0;
8665a391fbfSSteven Rostedt
8677faafbd6SSteven Rostedt    wait_for_monitor 1;
8685a391fbfSSteven Rostedt
8697faafbd6SSteven Rostedt    doprint "run test $run_test\n";
8705a391fbfSSteven Rostedt
8715a391fbfSSteven Rostedt    $child_done = 0;
8725a391fbfSSteven Rostedt
8735a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
8745a391fbfSSteven Rostedt
8755a391fbfSSteven Rostedt    $child_pid = fork;
8765a391fbfSSteven Rostedt
8775a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
8785a391fbfSSteven Rostedt
8795a391fbfSSteven Rostedt    $full_line = "";
8805a391fbfSSteven Rostedt
8815a391fbfSSteven Rostedt    do {
8827faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
8835a391fbfSSteven Rostedt	if (defined($line)) {
8845a391fbfSSteven Rostedt
8855a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
8865a391fbfSSteven Rostedt	    $full_line .= $line;
8875a391fbfSSteven Rostedt
8885a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
8895a391fbfSSteven Rostedt		$bug = 1;
8905a391fbfSSteven Rostedt	    }
8915a391fbfSSteven Rostedt
8925a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
8935a391fbfSSteven Rostedt		$bug = 1;
8945a391fbfSSteven Rostedt	    }
8955a391fbfSSteven Rostedt
8965a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
8975a391fbfSSteven Rostedt		$full_line = "";
8985a391fbfSSteven Rostedt	    }
8995a391fbfSSteven Rostedt	}
9005a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
9015a391fbfSSteven Rostedt
9025a391fbfSSteven Rostedt    if ($bug) {
9035a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
9045a391fbfSSteven Rostedt	# kill the child with extreme prejudice
9055a391fbfSSteven Rostedt	kill 9, $child_pid;
9065a391fbfSSteven Rostedt    }
9075a391fbfSSteven Rostedt
9085a391fbfSSteven Rostedt    waitpid $child_pid, 0;
9095a391fbfSSteven Rostedt    $child_exit = $?;
9105a391fbfSSteven Rostedt
9115a391fbfSSteven Rostedt    if ($bug || $child_exit) {
9122b7d9b21SSteven Rostedt	return 0 if $in_bisect;
9132b7d9b21SSteven Rostedt	fail "test failed" and return 0;
9145a391fbfSSteven Rostedt    }
9152b7d9b21SSteven Rostedt    return 1;
9165a391fbfSSteven Rostedt}
9175a391fbfSSteven Rostedt
918a75fececSSteven Rostedtsub run_git_bisect {
919a75fececSSteven Rostedt    my ($command) = @_;
920a75fececSSteven Rostedt
921a75fececSSteven Rostedt    doprint "$command ... ";
922a75fececSSteven Rostedt
923a75fececSSteven Rostedt    my $output = `$command 2>&1`;
924a75fececSSteven Rostedt    my $ret = $?;
925a75fececSSteven Rostedt
926a75fececSSteven Rostedt    logit $output;
927a75fececSSteven Rostedt
928a75fececSSteven Rostedt    if ($ret) {
929a75fececSSteven Rostedt	doprint "FAILED\n";
930a75fececSSteven Rostedt	dodie "Failed to git bisect";
931a75fececSSteven Rostedt    }
932a75fececSSteven Rostedt
933a75fececSSteven Rostedt    doprint "SUCCESS\n";
934a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
935a75fececSSteven Rostedt	doprint "$1 [$2]\n";
936a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
937a75fececSSteven Rostedt	$bisect_bad = $1;
938a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
939a75fececSSteven Rostedt	return 0;
940a75fececSSteven Rostedt    } else {
941a75fececSSteven Rostedt	# we already logged it, just print it now.
942a75fececSSteven Rostedt	print $output;
943a75fececSSteven Rostedt    }
944a75fececSSteven Rostedt
945a75fececSSteven Rostedt    return 1;
946a75fececSSteven Rostedt}
947a75fececSSteven Rostedt
9485f9b6cedSSteven Rostedtsub run_bisect {
9495f9b6cedSSteven Rostedt    my ($type) = @_;
9505f9b6cedSSteven Rostedt
9512b7d9b21SSteven Rostedt    my $failed = 0;
9525f9b6cedSSteven Rostedt    my $result;
9535f9b6cedSSteven Rostedt    my $output;
9545f9b6cedSSteven Rostedt    my $ret;
9555f9b6cedSSteven Rostedt
9565f9b6cedSSteven Rostedt    if (defined($minconfig)) {
9572b7d9b21SSteven Rostedt	build "useconfig:$minconfig" or $failed = 1;
9585f9b6cedSSteven Rostedt    } else {
9595f9b6cedSSteven Rostedt	# ?? no config to use?
9602b7d9b21SSteven Rostedt	build "oldconfig" or $failed = 1;
9615f9b6cedSSteven Rostedt    }
9625f9b6cedSSteven Rostedt
9635f9b6cedSSteven Rostedt    if ($type ne "build") {
9647faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
9655f9b6cedSSteven Rostedt
9665f9b6cedSSteven Rostedt	# Now boot the box
9675f9b6cedSSteven Rostedt	get_grub_index;
9685f9b6cedSSteven Rostedt	get_version;
9695f9b6cedSSteven Rostedt	install;
9707faafbd6SSteven Rostedt
9717faafbd6SSteven Rostedt	start_monitor;
9722b7d9b21SSteven Rostedt	monitor or $failed = 1;
9735f9b6cedSSteven Rostedt
9745f9b6cedSSteven Rostedt	if ($type ne "boot") {
9757faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
9765a391fbfSSteven Rostedt
9772b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
9785f9b6cedSSteven Rostedt	}
9797faafbd6SSteven Rostedt	end_monitor;
9805f9b6cedSSteven Rostedt    }
9815f9b6cedSSteven Rostedt
9825f9b6cedSSteven Rostedt    if ($failed) {
9835f9b6cedSSteven Rostedt	$result = "bad";
9845a391fbfSSteven Rostedt
9855a391fbfSSteven Rostedt	# reboot the box to a good kernel
986a75fececSSteven Rostedt	if ($type ne "build") {
987a75fececSSteven Rostedt	    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
9885a391fbfSSteven Rostedt	    reboot;
9897faafbd6SSteven Rostedt	    start_monitor;
990a75fececSSteven Rostedt	    wait_for_monitor $bisect_sleep_time;
9917faafbd6SSteven Rostedt	    end_monitor;
9925a391fbfSSteven Rostedt	}
9935f9b6cedSSteven Rostedt    } else {
9945f9b6cedSSteven Rostedt	$result = "good";
9955f9b6cedSSteven Rostedt    }
9965f9b6cedSSteven Rostedt
997d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
998d6ce2a0bSSteven Rostedt    if ($reverse_bisect) {
999d6ce2a0bSSteven Rostedt	if ($failed) {
1000d6ce2a0bSSteven Rostedt	    $result = "good";
1001d6ce2a0bSSteven Rostedt	} else {
1002d6ce2a0bSSteven Rostedt	    $result = "bad";
1003d6ce2a0bSSteven Rostedt	}
1004d6ce2a0bSSteven Rostedt    }
1005d6ce2a0bSSteven Rostedt
1006a75fececSSteven Rostedt    return $result;
10075f9b6cedSSteven Rostedt}
10085f9b6cedSSteven Rostedt
10095f9b6cedSSteven Rostedtsub bisect {
10105f9b6cedSSteven Rostedt    my ($i) = @_;
10115f9b6cedSSteven Rostedt
10125f9b6cedSSteven Rostedt    my $result;
10135f9b6cedSSteven Rostedt
10145f9b6cedSSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($opt{"BISECT_GOOD[$i]"}));
10155f9b6cedSSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($opt{"BISECT_BAD[$i]"}));
10165f9b6cedSSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($opt{"BISECT_TYPE[$i]"}));
10175f9b6cedSSteven Rostedt
10185f9b6cedSSteven Rostedt    my $good = $opt{"BISECT_GOOD[$i]"};
10195f9b6cedSSteven Rostedt    my $bad = $opt{"BISECT_BAD[$i]"};
10205f9b6cedSSteven Rostedt    my $type = $opt{"BISECT_TYPE[$i]"};
1021a75fececSSteven Rostedt    my $start = $opt{"BISECT_START[$i]"};
1022a75fececSSteven Rostedt    my $replay = $opt{"BISECT_REPLAY[$i]"};
10235f9b6cedSSteven Rostedt
1024a57419b3SSteven Rostedt    # convert to true sha1's
1025a57419b3SSteven Rostedt    $good = get_sha1($good);
1026a57419b3SSteven Rostedt    $bad = get_sha1($bad);
1027a57419b3SSteven Rostedt
1028d6ce2a0bSSteven Rostedt    if (defined($opt{"BISECT_REVERSE[$i]"}) &&
1029d6ce2a0bSSteven Rostedt	$opt{"BISECT_REVERSE[$i]"} == 1) {
1030d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1031d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
1032d6ce2a0bSSteven Rostedt    } else {
1033d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
1034d6ce2a0bSSteven Rostedt    }
1035d6ce2a0bSSteven Rostedt
10365f9b6cedSSteven Rostedt    $in_bisect = 1;
10375f9b6cedSSteven Rostedt
10385a391fbfSSteven Rostedt    # Can't have a test without having a test to run
10395a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
10405a391fbfSSteven Rostedt	$type = "boot";
10415a391fbfSSteven Rostedt    }
10425a391fbfSSteven Rostedt
1043a75fececSSteven Rostedt    my $check = $opt{"BISECT_CHECK[$i]"};
1044a75fececSSteven Rostedt    if (defined($check) && $check ne "0") {
1045a75fececSSteven Rostedt
1046a75fececSSteven Rostedt	# get current HEAD
1047a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
1048a75fececSSteven Rostedt
1049a75fececSSteven Rostedt	if ($check ne "good") {
1050a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
1051a75fececSSteven Rostedt	    run_command "git checkout $bad" or
1052a75fececSSteven Rostedt		die "Failed to checkout $bad";
1053a75fececSSteven Rostedt
1054a75fececSSteven Rostedt	    $result = run_bisect $type;
1055a75fececSSteven Rostedt
1056a75fececSSteven Rostedt	    if ($result ne "bad") {
1057a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
1058a75fececSSteven Rostedt	    }
1059a75fececSSteven Rostedt	}
1060a75fececSSteven Rostedt
1061a75fececSSteven Rostedt	if ($check ne "bad") {
1062a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
1063a75fececSSteven Rostedt	    run_command "git checkout $good" or
1064a75fececSSteven Rostedt		die "Failed to checkout $good";
1065a75fececSSteven Rostedt
1066a75fececSSteven Rostedt	    $result = run_bisect $type;
1067a75fececSSteven Rostedt
1068a75fececSSteven Rostedt	    if ($result ne "good") {
1069a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
1070a75fececSSteven Rostedt	    }
1071a75fececSSteven Rostedt	}
1072a75fececSSteven Rostedt
1073a75fececSSteven Rostedt	# checkout where we started
1074a75fececSSteven Rostedt	run_command "git checkout $head" or
1075a75fececSSteven Rostedt	    die "Failed to checkout $head";
1076a75fececSSteven Rostedt    }
1077a75fececSSteven Rostedt
1078a75fececSSteven Rostedt    run_command "git bisect start" or
1079a75fececSSteven Rostedt	dodie "could not start bisect";
1080a75fececSSteven Rostedt
1081a75fececSSteven Rostedt    run_command "git bisect good $good" or
1082a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
1083a75fececSSteven Rostedt
1084a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
1085a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
1086a75fececSSteven Rostedt
1087a75fececSSteven Rostedt    if (defined($replay)) {
1088a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
1089a75fececSSteven Rostedt	    dodie "failed to run replay";
1090a75fececSSteven Rostedt    }
1091a75fececSSteven Rostedt
1092a75fececSSteven Rostedt    if (defined($start)) {
1093a75fececSSteven Rostedt	run_command "git checkout $start" or
1094a75fececSSteven Rostedt	    dodie "failed to checkout $start";
1095a75fececSSteven Rostedt    }
1096a75fececSSteven Rostedt
1097a75fececSSteven Rostedt    my $test;
10985f9b6cedSSteven Rostedt    do {
10995f9b6cedSSteven Rostedt	$result = run_bisect $type;
1100a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
1101a75fececSSteven Rostedt    } while ($test);
11025f9b6cedSSteven Rostedt
11035f9b6cedSSteven Rostedt    run_command "git bisect log" or
11045f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
11055f9b6cedSSteven Rostedt
11065f9b6cedSSteven Rostedt    run_command "git bisect reset" or
11075f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
11085f9b6cedSSteven Rostedt
11095f9b6cedSSteven Rostedt    doprint "Bad commit was [$bisect_bad]\n";
11105f9b6cedSSteven Rostedt
11115f9b6cedSSteven Rostedt    $in_bisect = 0;
11125f9b6cedSSteven Rostedt
11135f9b6cedSSteven Rostedt    success $i;
11145f9b6cedSSteven Rostedt}
11155f9b6cedSSteven Rostedt
11166c5ee0beSSteven Rostedtsub patchcheck {
11176c5ee0beSSteven Rostedt    my ($i) = @_;
11186c5ee0beSSteven Rostedt
11196c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
11206c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_START[$i]"}));
11216c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
11226c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
11236c5ee0beSSteven Rostedt
11246c5ee0beSSteven Rostedt    my $start = $opt{"PATCHCHECK_START[$i]"};
11256c5ee0beSSteven Rostedt
11266c5ee0beSSteven Rostedt    my $end = "HEAD";
11276c5ee0beSSteven Rostedt    if (defined($opt{"PATCHCHECK_END[$i]"})) {
11286c5ee0beSSteven Rostedt	$end = $opt{"PATCHCHECK_END[$i]"};
11296c5ee0beSSteven Rostedt    }
11306c5ee0beSSteven Rostedt
1131a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
1132a57419b3SSteven Rostedt    $start = get_sha1($start);
1133a57419b3SSteven Rostedt    $end = get_sha1($end);
1134a57419b3SSteven Rostedt
11356c5ee0beSSteven Rostedt    my $type = $opt{"PATCHCHECK_TYPE[$i]"};
11366c5ee0beSSteven Rostedt
11376c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
11386c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
11396c5ee0beSSteven Rostedt	$type = "boot";
11406c5ee0beSSteven Rostedt    }
11416c5ee0beSSteven Rostedt
11426c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
11436c5ee0beSSteven Rostedt	dodie "could not get git list";
11446c5ee0beSSteven Rostedt
11456c5ee0beSSteven Rostedt    my @list;
11466c5ee0beSSteven Rostedt
11476c5ee0beSSteven Rostedt    while (<IN>) {
11486c5ee0beSSteven Rostedt	chomp;
11496c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
11506c5ee0beSSteven Rostedt	last if (/^$start/);
11516c5ee0beSSteven Rostedt    }
11526c5ee0beSSteven Rostedt    close(IN);
11536c5ee0beSSteven Rostedt
11546c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
11552b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
11566c5ee0beSSteven Rostedt    }
11576c5ee0beSSteven Rostedt
11586c5ee0beSSteven Rostedt    # go backwards in the list
11596c5ee0beSSteven Rostedt    @list = reverse @list;
11606c5ee0beSSteven Rostedt
11616c5ee0beSSteven Rostedt    my $save_clean = $noclean;
11626c5ee0beSSteven Rostedt
11636c5ee0beSSteven Rostedt    $in_patchcheck = 1;
11646c5ee0beSSteven Rostedt    foreach my $item (@list) {
11656c5ee0beSSteven Rostedt	my $sha1 = $item;
11666c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
11676c5ee0beSSteven Rostedt
11686c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
11696c5ee0beSSteven Rostedt
11706c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
11716c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
11726c5ee0beSSteven Rostedt
11736c5ee0beSSteven Rostedt	# only clean on the first and last patch
11746c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
11756c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
11766c5ee0beSSteven Rostedt	    $noclean = $save_clean;
11776c5ee0beSSteven Rostedt	} else {
11786c5ee0beSSteven Rostedt	    $noclean = 1;
11796c5ee0beSSteven Rostedt	}
11806c5ee0beSSteven Rostedt
11816c5ee0beSSteven Rostedt	if (defined($minconfig)) {
11822b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
11836c5ee0beSSteven Rostedt	} else {
11846c5ee0beSSteven Rostedt	    # ?? no config to use?
11852b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
11866c5ee0beSSteven Rostedt	}
11876c5ee0beSSteven Rostedt
11882b7d9b21SSteven Rostedt	check_buildlog $sha1 or return 0;
11896c5ee0beSSteven Rostedt
11906c5ee0beSSteven Rostedt	next if ($type eq "build");
11916c5ee0beSSteven Rostedt
11926c5ee0beSSteven Rostedt	get_grub_index;
11936c5ee0beSSteven Rostedt	get_version;
11946c5ee0beSSteven Rostedt	install;
11956c5ee0beSSteven Rostedt
11967faafbd6SSteven Rostedt	my $failed = 0;
11977faafbd6SSteven Rostedt
11987faafbd6SSteven Rostedt	start_monitor;
11997faafbd6SSteven Rostedt	monitor or $failed = 1;
12007faafbd6SSteven Rostedt
12017faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
12027faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
12037faafbd6SSteven Rostedt	}
12047faafbd6SSteven Rostedt	end_monitor;
12057faafbd6SSteven Rostedt	return 0 if ($failed);
12067faafbd6SSteven Rostedt
12076c5ee0beSSteven Rostedt    }
12086c5ee0beSSteven Rostedt    $in_patchcheck = 0;
12096c5ee0beSSteven Rostedt    success $i;
12102b7d9b21SSteven Rostedt
12112b7d9b21SSteven Rostedt    return 1;
12126c5ee0beSSteven Rostedt}
12136c5ee0beSSteven Rostedt
12142545eb61SSteven Rostedtread_config $ARGV[0];
12152545eb61SSteven Rostedt
12162545eb61SSteven Rostedt# mandatory configs
12172545eb61SSteven Rostedtdie "MACHINE not defined\n"		if (!defined($opt{"MACHINE"}));
12182545eb61SSteven Rostedtdie "SSH_USER not defined\n"		if (!defined($opt{"SSH_USER"}));
12192545eb61SSteven Rostedtdie "BUILD_DIR not defined\n"		if (!defined($opt{"BUILD_DIR"}));
12202545eb61SSteven Rostedtdie "OUTPUT_DIR not defined\n"		if (!defined($opt{"OUTPUT_DIR"}));
12212545eb61SSteven Rostedtdie "BUILD_TARGET not defined\n"	if (!defined($opt{"BUILD_TARGET"}));
122275c3fda7SSteven Rostedtdie "TARGET_IMAGE not defined\n"	if (!defined($opt{"TARGET_IMAGE"}));
12232545eb61SSteven Rostedtdie "POWER_CYCLE not defined\n"		if (!defined($opt{"POWER_CYCLE"}));
12242545eb61SSteven Rostedtdie "CONSOLE not defined\n"		if (!defined($opt{"CONSOLE"}));
12252545eb61SSteven Rostedtdie "LOCALVERSION not defined\n"	if (!defined($opt{"LOCALVERSION"}));
12262545eb61SSteven Rostedt
12272b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
12282b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
12292b7d9b21SSteven Rostedt}
12302545eb61SSteven Rostedt
12312b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
12322b7d9b21SSteven Rostedt
1233a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
1234a57419b3SSteven Rostedt
1235a57419b3SSteven Rostedt    if (!$i) {
1236a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
1237a57419b3SSteven Rostedt    } else {
1238a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
1239a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
1240a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
1241a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
1242a57419b3SSteven Rostedt	}
1243a57419b3SSteven Rostedt	doprint "\n";
1244a57419b3SSteven Rostedt    }
1245a57419b3SSteven Rostedt
12462b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
1247a57419b3SSteven Rostedt
1248a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
1249a57419b3SSteven Rostedt	    next if ($i != $1);
1250a57419b3SSteven Rostedt	} else {
1251a57419b3SSteven Rostedt	    next if ($i);
1252a57419b3SSteven Rostedt	}
1253a57419b3SSteven Rostedt
12542b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
12552b7d9b21SSteven Rostedt    }
1256a57419b3SSteven Rostedt}
12572545eb61SSteven Rostedt
1258a75fececSSteven Rostedtsub set_test_option {
12595a391fbfSSteven Rostedt    my ($name, $i) = @_;
12605a391fbfSSteven Rostedt
12615a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
12625a391fbfSSteven Rostedt
12635a391fbfSSteven Rostedt    if (defined($opt{$option})) {
12645a391fbfSSteven Rostedt	return $opt{$option};
12655a391fbfSSteven Rostedt    }
12665a391fbfSSteven Rostedt
1267a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
1268a57419b3SSteven Rostedt	if ($i >= $test &&
1269a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
1270a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
1271a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
1272a57419b3SSteven Rostedt		return $opt{$option};
1273a57419b3SSteven Rostedt	    }
1274a57419b3SSteven Rostedt	}
1275a57419b3SSteven Rostedt    }
1276a57419b3SSteven Rostedt
12775a391fbfSSteven Rostedt    if (defined($opt{$name})) {
12785a391fbfSSteven Rostedt	return $opt{$name};
12795a391fbfSSteven Rostedt    }
12805a391fbfSSteven Rostedt
12815a391fbfSSteven Rostedt    return undef;
12825a391fbfSSteven Rostedt}
12835a391fbfSSteven Rostedt
12842545eb61SSteven Rostedt# First we need to do is the builds
1285a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
12862545eb61SSteven Rostedt
1287576f627cSSteven Rostedt    $iteration = $i;
1288576f627cSSteven Rostedt
1289a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
1290a75fececSSteven Rostedt
1291a75fececSSteven Rostedt    $machine = set_test_option("MACHINE", $i);
1292*e48c5293SSteven Rostedt    $ssh_user = set_test_option("SSH_USER", $i);
1293a75fececSSteven Rostedt    $tmpdir = set_test_option("TMP_DIR", $i);
1294a75fececSSteven Rostedt    $outputdir = set_test_option("OUTPUT_DIR", $i);
1295a75fececSSteven Rostedt    $builddir = set_test_option("BUILD_DIR", $i);
1296a75fececSSteven Rostedt    $test_type = set_test_option("TEST_TYPE", $i);
1297a75fececSSteven Rostedt    $build_type = set_test_option("BUILD_TYPE", $i);
1298a75fececSSteven Rostedt    $build_options = set_test_option("BUILD_OPTIONS", $i);
1299a75fececSSteven Rostedt    $power_cycle = set_test_option("POWER_CYCLE", $i);
1300*e48c5293SSteven Rostedt    $reboot = set_test_option("REBOOT", $i);
1301a75fececSSteven Rostedt    $noclean = set_test_option("BUILD_NOCLEAN", $i);
1302a75fececSSteven Rostedt    $minconfig = set_test_option("MIN_CONFIG", $i);
1303a75fececSSteven Rostedt    $run_test = set_test_option("TEST", $i);
1304a75fececSSteven Rostedt    $addconfig = set_test_option("ADD_CONFIG", $i);
1305a75fececSSteven Rostedt    $reboot_type = set_test_option("REBOOT_TYPE", $i);
1306a75fececSSteven Rostedt    $grub_menu = set_test_option("GRUB_MENU", $i);
13078b37ca8cSSteven Rostedt    $post_install = set_test_option("POST_INSTALL", $i);
1308a75fececSSteven Rostedt    $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
1309a75fececSSteven Rostedt    $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
1310a75fececSSteven Rostedt    $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
1311a75fececSSteven Rostedt    $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
1312a75fececSSteven Rostedt    $power_off = set_test_option("POWER_OFF", $i);
1313576f627cSSteven Rostedt    $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
1314576f627cSSteven Rostedt    $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
1315a75fececSSteven Rostedt    $sleep_time = set_test_option("SLEEP_TIME", $i);
1316a75fececSSteven Rostedt    $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
1317a75fececSSteven Rostedt    $store_failures = set_test_option("STORE_FAILURES", $i);
1318a75fececSSteven Rostedt    $timeout = set_test_option("TIMEOUT", $i);
1319a75fececSSteven Rostedt    $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
1320a75fececSSteven Rostedt    $console = set_test_option("CONSOLE", $i);
1321a75fececSSteven Rostedt    $success_line = set_test_option("SUCCESS_LINE", $i);
1322a75fececSSteven Rostedt    $build_target = set_test_option("BUILD_TARGET", $i);
1323*e48c5293SSteven Rostedt    $ssh_exec = set_test_option("SSH_EXEC", $i);
1324*e48c5293SSteven Rostedt    $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
1325a75fececSSteven Rostedt    $target_image = set_test_option("TARGET_IMAGE", $i);
1326a75fececSSteven Rostedt    $localversion = set_test_option("LOCALVERSION", $i);
1327a75fececSSteven Rostedt
1328a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
1329a75fececSSteven Rostedt
1330a75fececSSteven Rostedt    if (!-d $tmpdir) {
1331a75fececSSteven Rostedt	mkpath($tmpdir) or
1332a75fececSSteven Rostedt	    die "can't create $tmpdir";
1333a75fececSSteven Rostedt    }
1334a75fececSSteven Rostedt
1335*e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
1336*e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
1337*e48c5293SSteven Rostedt
1338a75fececSSteven Rostedt    $target = "$ssh_user\@$machine";
1339a75fececSSteven Rostedt
1340a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
1341a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
1342a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
134351ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
1344*e48c5293SSteven Rostedt    $output_config = "$outputdir/.config";
1345a75fececSSteven Rostedt
1346a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
1347576f627cSSteven Rostedt	dodie "GRUB_MENU not defined" if (!defined($grub_menu));
1348a75fececSSteven Rostedt    } elsif (!defined($reboot_script)) {
1349576f627cSSteven Rostedt	dodie "REBOOT_SCRIPT not defined"
1350a75fececSSteven Rostedt    }
1351a75fececSSteven Rostedt
1352a75fececSSteven Rostedt    my $run_type = $build_type;
1353a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
1354a75fececSSteven Rostedt	$run_type = $opt{"PATCHCHECK_TYPE[$i]"};
1355a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
1356a75fececSSteven Rostedt	$run_type = $opt{"BISECT_TYPE[$i]"};
1357a75fececSSteven Rostedt    }
1358a75fececSSteven Rostedt
1359a75fececSSteven Rostedt    # mistake in config file?
1360a75fececSSteven Rostedt    if (!defined($run_type)) {
1361a75fececSSteven Rostedt	$run_type = "ERROR";
1362a75fececSSteven Rostedt    }
13632545eb61SSteven Rostedt
13642545eb61SSteven Rostedt    doprint "\n\n";
1365a75fececSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
13667faafbd6SSteven Rostedt
13677faafbd6SSteven Rostedt    unlink $dmesg;
13687faafbd6SSteven Rostedt    unlink $buildlog;
13692545eb61SSteven Rostedt
13702b7d9b21SSteven Rostedt    if (!defined($minconfig)) {
13712b7d9b21SSteven Rostedt	$minconfig = $addconfig;
13722b7d9b21SSteven Rostedt
13732b7d9b21SSteven Rostedt    } elsif (defined($addconfig)) {
1374a75fececSSteven Rostedt	run_command "cat $addconfig $minconfig > $tmpdir/use_config" or
13752b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
1376a75fececSSteven Rostedt	$minconfig = "$tmpdir/use_config";
13772b7d9b21SSteven Rostedt    }
13782b7d9b21SSteven Rostedt
13796c5ee0beSSteven Rostedt    my $checkout = $opt{"CHECKOUT[$i]"};
13806c5ee0beSSteven Rostedt    if (defined($checkout)) {
13816c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
13826c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
13836c5ee0beSSteven Rostedt    }
13846c5ee0beSSteven Rostedt
1385a75fececSSteven Rostedt    if ($test_type eq "bisect") {
13865f9b6cedSSteven Rostedt	bisect $i;
13875f9b6cedSSteven Rostedt	next;
1388a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
13896c5ee0beSSteven Rostedt	patchcheck $i;
13906c5ee0beSSteven Rostedt	next;
13915f9b6cedSSteven Rostedt    }
13925f9b6cedSSteven Rostedt
13937faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
13947faafbd6SSteven Rostedt	build $build_type or next;
13952545eb61SSteven Rostedt    }
13962545eb61SSteven Rostedt
1397a75fececSSteven Rostedt    if ($test_type ne "build") {
13985f9b6cedSSteven Rostedt	get_grub_index;
13995f9b6cedSSteven Rostedt	get_version;
14002545eb61SSteven Rostedt	install;
14015a391fbfSSteven Rostedt
14027faafbd6SSteven Rostedt	my $failed = 0;
14037faafbd6SSteven Rostedt	start_monitor;
14047faafbd6SSteven Rostedt	monitor or $failed = 1;;
1405a75fececSSteven Rostedt
1406a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
14077faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
14085a391fbfSSteven Rostedt	}
14097faafbd6SSteven Rostedt	end_monitor;
14107faafbd6SSteven Rostedt	next if ($failed);
1411a75fececSSteven Rostedt    }
14125a391fbfSSteven Rostedt
14135f9b6cedSSteven Rostedt    success $i;
141475c3fda7SSteven Rostedt}
14152545eb61SSteven Rostedt
14165c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
141775c3fda7SSteven Rostedt    halt;
1418576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
141975c3fda7SSteven Rostedt    reboot;
14205c42fc5bSSteven Rostedt}
142175c3fda7SSteven Rostedt
1422*e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
1423*e48c5293SSteven Rostedt
14242545eb61SSteven Rostedtexit 0;
1425