xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision fcb3f16a4f4bf4e667ae4c68b1d5401824058efb)
12545eb61SSteven Rostedt#!/usr/bin/perl -w
2d6ce2a0bSSteven Rostedt#
3cce1dac8SUwe Kleine-König# Copyright 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
162545eb61SSteven Rostedt$| = 1;
172545eb61SSteven Rostedt
182545eb61SSteven Rostedtmy %opt;
19a57419b3SSteven Rostedtmy %repeat_tests;
20a57419b3SSteven Rostedtmy %repeats;
21a75fececSSteven Rostedtmy %default;
222545eb61SSteven Rostedt
232545eb61SSteven Rostedt#default opts
24a57419b3SSteven Rostedt$default{"NUM_TESTS"}		= 1;
25a75fececSSteven Rostedt$default{"REBOOT_TYPE"}		= "grub";
26a75fececSSteven Rostedt$default{"TEST_TYPE"}		= "test";
27a75fececSSteven Rostedt$default{"BUILD_TYPE"}		= "randconfig";
28a75fececSSteven Rostedt$default{"MAKE_CMD"}		= "make";
29a75fececSSteven Rostedt$default{"TIMEOUT"}		= 120;
30a57419b3SSteven Rostedt$default{"TMP_DIR"}		= "/tmp/ktest";
31a75fececSSteven Rostedt$default{"SLEEP_TIME"}		= 60;	# sleep time between tests
32a75fececSSteven Rostedt$default{"BUILD_NOCLEAN"}	= 0;
33a75fececSSteven Rostedt$default{"REBOOT_ON_ERROR"}	= 0;
34a75fececSSteven Rostedt$default{"POWEROFF_ON_ERROR"}	= 0;
35a75fececSSteven Rostedt$default{"REBOOT_ON_SUCCESS"}	= 1;
36a75fececSSteven Rostedt$default{"POWEROFF_ON_SUCCESS"}	= 0;
37a75fececSSteven Rostedt$default{"BUILD_OPTIONS"}	= "";
38a75fececSSteven Rostedt$default{"BISECT_SLEEP_TIME"}	= 60;   # sleep time between bisects
3927d934b2SSteven Rostedt$default{"PATCHCHECK_SLEEP_TIME"} = 60; # sleep time between patch checks
40a75fececSSteven Rostedt$default{"CLEAR_LOG"}		= 0;
41c960bb9fSSteven Rostedt$default{"BISECT_MANUAL"}	= 0;
42c23dca7cSSteven Rostedt$default{"BISECT_SKIP"}		= 1;
43a75fececSSteven Rostedt$default{"SUCCESS_LINE"}	= "login:";
44f1a5b962SSteven Rostedt$default{"DETECT_TRIPLE_FAULT"} = 1;
45a75fececSSteven Rostedt$default{"BOOTED_TIMEOUT"}	= 1;
46a75fececSSteven Rostedt$default{"DIE_ON_FAILURE"}	= 1;
47e48c5293SSteven Rostedt$default{"SSH_EXEC"}		= "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
48e48c5293SSteven Rostedt$default{"SCP_TO_TARGET"}	= "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE";
49e48c5293SSteven Rostedt$default{"REBOOT"}		= "ssh \$SSH_USER\@\$MACHINE reboot";
501c8a617aSSteven Rostedt$default{"STOP_AFTER_SUCCESS"}	= 10;
511c8a617aSSteven Rostedt$default{"STOP_AFTER_FAILURE"}	= 60;
522d01b26aSSteven Rostedt$default{"STOP_TEST_AFTER"}	= 600;
538d1491baSSteven Rostedt$default{"LOCALVERSION"}	= "-test";
542545eb61SSteven Rostedt
558d1491baSSteven Rostedtmy $ktest_config;
562545eb61SSteven Rostedtmy $version;
57a75fececSSteven Rostedtmy $machine;
58e48c5293SSteven Rostedtmy $ssh_user;
59a75fececSSteven Rostedtmy $tmpdir;
60a75fececSSteven Rostedtmy $builddir;
61a75fececSSteven Rostedtmy $outputdir;
6251ad1dd1SSteven Rostedtmy $output_config;
63a75fececSSteven Rostedtmy $test_type;
647faafbd6SSteven Rostedtmy $build_type;
65a75fececSSteven Rostedtmy $build_options;
66a75fececSSteven Rostedtmy $reboot_type;
67a75fececSSteven Rostedtmy $reboot_script;
68a75fececSSteven Rostedtmy $power_cycle;
69e48c5293SSteven Rostedtmy $reboot;
70a75fececSSteven Rostedtmy $reboot_on_error;
71a75fececSSteven Rostedtmy $poweroff_on_error;
72a75fececSSteven Rostedtmy $die_on_failure;
73576f627cSSteven Rostedtmy $powercycle_after_reboot;
74576f627cSSteven Rostedtmy $poweroff_after_halt;
75e48c5293SSteven Rostedtmy $ssh_exec;
76e48c5293SSteven Rostedtmy $scp_to_target;
77a75fececSSteven Rostedtmy $power_off;
78a75fececSSteven Rostedtmy $grub_menu;
792545eb61SSteven Rostedtmy $grub_number;
802545eb61SSteven Rostedtmy $target;
812545eb61SSteven Rostedtmy $make;
828b37ca8cSSteven Rostedtmy $post_install;
835c42fc5bSSteven Rostedtmy $noclean;
845f9b6cedSSteven Rostedtmy $minconfig;
852b7d9b21SSteven Rostedtmy $addconfig;
865f9b6cedSSteven Rostedtmy $in_bisect = 0;
875f9b6cedSSteven Rostedtmy $bisect_bad = "";
88d6ce2a0bSSteven Rostedtmy $reverse_bisect;
89c960bb9fSSteven Rostedtmy $bisect_manual;
90c23dca7cSSteven Rostedtmy $bisect_skip;
9130f75da5SSteven Rostedtmy $config_bisect_good;
926c5ee0beSSteven Rostedtmy $in_patchcheck = 0;
935a391fbfSSteven Rostedtmy $run_test;
946c5ee0beSSteven Rostedtmy $redirect;
957faafbd6SSteven Rostedtmy $buildlog;
967faafbd6SSteven Rostedtmy $dmesg;
977faafbd6SSteven Rostedtmy $monitor_fp;
987faafbd6SSteven Rostedtmy $monitor_pid;
997faafbd6SSteven Rostedtmy $monitor_cnt = 0;
100a75fececSSteven Rostedtmy $sleep_time;
101a75fececSSteven Rostedtmy $bisect_sleep_time;
10227d934b2SSteven Rostedtmy $patchcheck_sleep_time;
103a75fececSSteven Rostedtmy $store_failures;
1049064af52SSteven Rostedtmy $test_name;
105a75fececSSteven Rostedtmy $timeout;
106a75fececSSteven Rostedtmy $booted_timeout;
107f1a5b962SSteven Rostedtmy $detect_triplefault;
108a75fececSSteven Rostedtmy $console;
109a75fececSSteven Rostedtmy $success_line;
1101c8a617aSSteven Rostedtmy $stop_after_success;
1111c8a617aSSteven Rostedtmy $stop_after_failure;
1122d01b26aSSteven Rostedtmy $stop_test_after;
113a75fececSSteven Rostedtmy $build_target;
114a75fececSSteven Rostedtmy $target_image;
115a75fececSSteven Rostedtmy $localversion;
116576f627cSSteven Rostedtmy $iteration = 0;
117e48c5293SSteven Rostedtmy $successes = 0;
1182545eb61SSteven Rostedt
1198d1491baSSteven Rostedtmy %entered_configs;
1208d1491baSSteven Rostedtmy %config_help;
12177d942ceSSteven Rostedtmy %variable;
122*fcb3f16aSSteven Rostedtmy %force_config;
1238d1491baSSteven Rostedt
1248d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF"
1258d1491baSSteven Rostedt The machine hostname that you will test.
1268d1491baSSteven RostedtEOF
1278d1491baSSteven Rostedt    ;
1288d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF"
1298d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user
1308d1491baSSteven Rostedt  (most likely root, since you need privileged operations)
1318d1491baSSteven RostedtEOF
1328d1491baSSteven Rostedt    ;
1338d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF"
1348d1491baSSteven Rostedt The directory that contains the Linux source code (full path).
1358d1491baSSteven RostedtEOF
1368d1491baSSteven Rostedt    ;
1378d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF"
1388d1491baSSteven Rostedt The directory that the objects will be built (full path).
1398d1491baSSteven Rostedt (can not be same as BUILD_DIR)
1408d1491baSSteven RostedtEOF
1418d1491baSSteven Rostedt    ;
1428d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF"
1438d1491baSSteven Rostedt The location of the compiled file to copy to the target.
1448d1491baSSteven Rostedt (relative to OUTPUT_DIR)
1458d1491baSSteven RostedtEOF
1468d1491baSSteven Rostedt    ;
1478d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF"
1488d1491baSSteven Rostedt The place to put your image on the test machine.
1498d1491baSSteven RostedtEOF
1508d1491baSSteven Rostedt    ;
1518d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF"
1528d1491baSSteven Rostedt A script or command to reboot the box.
1538d1491baSSteven Rostedt
1548d1491baSSteven Rostedt Here is a digital loggers power switch example
1558d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
1568d1491baSSteven Rostedt
1578d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host
1588d1491baSSteven Rostedt with the name "Guest".
1598d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
1608d1491baSSteven RostedtEOF
1618d1491baSSteven Rostedt    ;
1628d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF"
1638d1491baSSteven Rostedt The script or command that reads the console
1648d1491baSSteven Rostedt
1658d1491baSSteven Rostedt  If you use ttywatch server, something like the following would work.
1668d1491baSSteven RostedtCONSOLE = nc -d localhost 3001
1678d1491baSSteven Rostedt
1688d1491baSSteven Rostedt For a virtual machine with guest name "Guest".
1698d1491baSSteven RostedtCONSOLE =  virsh console Guest
1708d1491baSSteven RostedtEOF
1718d1491baSSteven Rostedt    ;
1728d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF"
1738d1491baSSteven Rostedt Required version ending to differentiate the test
1748d1491baSSteven Rostedt from other linux builds on the system.
1758d1491baSSteven RostedtEOF
1768d1491baSSteven Rostedt    ;
1778d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF"
1788d1491baSSteven Rostedt Way to reboot the box to the test kernel.
1798d1491baSSteven Rostedt Only valid options so far are "grub" and "script".
1808d1491baSSteven Rostedt
1818d1491baSSteven Rostedt If you specify grub, it will assume grub version 1
1828d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
1838d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not
1848d1491baSSteven Rostedt your setup, then specify "script" and have a command or script
1858d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target.
1868d1491baSSteven Rostedt
1878d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually.
1888d1491baSSteven Rostedt The test will not modify that file.
1898d1491baSSteven RostedtEOF
1908d1491baSSteven Rostedt    ;
1918d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF"
1928d1491baSSteven Rostedt The grub title name for the test kernel to boot
1938d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = grub)
1948d1491baSSteven Rostedt
1958d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to
1968d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search
1978d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to
1988d1491baSSteven Rostedt reboot into.
1998d1491baSSteven Rostedt
2008d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has:
2018d1491baSSteven Rostedt title Test Kernel
2028d1491baSSteven Rostedt kernel vmlinuz-test
2038d1491baSSteven Rostedt GRUB_MENU = Test Kernel
2048d1491baSSteven RostedtEOF
2058d1491baSSteven Rostedt    ;
2068d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF"
2078d1491baSSteven Rostedt A script to reboot the target into the test kernel
2088d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script)
2098d1491baSSteven RostedtEOF
2108d1491baSSteven Rostedt    ;
2118d1491baSSteven Rostedt
2128d1491baSSteven Rostedt
2138d1491baSSteven Rostedtsub get_ktest_config {
2148d1491baSSteven Rostedt    my ($config) = @_;
2158d1491baSSteven Rostedt
2168d1491baSSteven Rostedt    return if (defined($opt{$config}));
2178d1491baSSteven Rostedt
2188d1491baSSteven Rostedt    if (defined($config_help{$config})) {
2198d1491baSSteven Rostedt	print "\n";
2208d1491baSSteven Rostedt	print $config_help{$config};
2218d1491baSSteven Rostedt    }
2228d1491baSSteven Rostedt
2238d1491baSSteven Rostedt    for (;;) {
2248d1491baSSteven Rostedt	print "$config = ";
2258d1491baSSteven Rostedt	if (defined($default{$config})) {
2268d1491baSSteven Rostedt	    print "\[$default{$config}\] ";
2278d1491baSSteven Rostedt	}
2288d1491baSSteven Rostedt	$entered_configs{$config} = <STDIN>;
2298d1491baSSteven Rostedt	$entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/;
2308d1491baSSteven Rostedt	if ($entered_configs{$config} =~ /^\s*$/) {
2318d1491baSSteven Rostedt	    if ($default{$config}) {
2328d1491baSSteven Rostedt		$entered_configs{$config} = $default{$config};
2338d1491baSSteven Rostedt	    } else {
2348d1491baSSteven Rostedt		print "Your answer can not be blank\n";
2358d1491baSSteven Rostedt		next;
2368d1491baSSteven Rostedt	    }
2378d1491baSSteven Rostedt	}
2388d1491baSSteven Rostedt	last;
2398d1491baSSteven Rostedt    }
2408d1491baSSteven Rostedt}
2418d1491baSSteven Rostedt
2428d1491baSSteven Rostedtsub get_ktest_configs {
2438d1491baSSteven Rostedt    get_ktest_config("MACHINE");
2448d1491baSSteven Rostedt    get_ktest_config("SSH_USER");
2458d1491baSSteven Rostedt    get_ktest_config("BUILD_DIR");
2468d1491baSSteven Rostedt    get_ktest_config("OUTPUT_DIR");
2478d1491baSSteven Rostedt    get_ktest_config("BUILD_TARGET");
2488d1491baSSteven Rostedt    get_ktest_config("TARGET_IMAGE");
2498d1491baSSteven Rostedt    get_ktest_config("POWER_CYCLE");
2508d1491baSSteven Rostedt    get_ktest_config("CONSOLE");
2518d1491baSSteven Rostedt    get_ktest_config("LOCALVERSION");
2528d1491baSSteven Rostedt
2538d1491baSSteven Rostedt    my $rtype = $opt{"REBOOT_TYPE"};
2548d1491baSSteven Rostedt
2558d1491baSSteven Rostedt    if (!defined($rtype)) {
2568d1491baSSteven Rostedt	if (!defined($opt{"GRUB_MENU"})) {
2578d1491baSSteven Rostedt	    get_ktest_config("REBOOT_TYPE");
2588d1491baSSteven Rostedt	    $rtype = $entered_configs{"REBOOT_TYPE"};
2598d1491baSSteven Rostedt	} else {
2608d1491baSSteven Rostedt	    $rtype = "grub";
2618d1491baSSteven Rostedt	}
2628d1491baSSteven Rostedt    }
2638d1491baSSteven Rostedt
2648d1491baSSteven Rostedt    if ($rtype eq "grub") {
2658d1491baSSteven Rostedt	get_ktest_config("GRUB_MENU");
2668d1491baSSteven Rostedt    } else {
2678d1491baSSteven Rostedt	get_ktest_config("REBOOT_SCRIPT");
2688d1491baSSteven Rostedt    }
2698d1491baSSteven Rostedt}
2708d1491baSSteven Rostedt
27177d942ceSSteven Rostedtsub process_variables {
27277d942ceSSteven Rostedt    my ($value) = @_;
27377d942ceSSteven Rostedt    my $retval = "";
27477d942ceSSteven Rostedt
27577d942ceSSteven Rostedt    # We want to check for '\', and it is just easier
27677d942ceSSteven Rostedt    # to check the previous characet of '$' and not need
27777d942ceSSteven Rostedt    # to worry if '$' is the first character. By adding
27877d942ceSSteven Rostedt    # a space to $value, we can just check [^\\]\$ and
27977d942ceSSteven Rostedt    # it will still work.
28077d942ceSSteven Rostedt    $value = " $value";
28177d942ceSSteven Rostedt
28277d942ceSSteven Rostedt    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
28377d942ceSSteven Rostedt	my $begin = $1;
28477d942ceSSteven Rostedt	my $var = $2;
28577d942ceSSteven Rostedt	my $end = $3;
28677d942ceSSteven Rostedt	# append beginning of value to retval
28777d942ceSSteven Rostedt	$retval = "$retval$begin";
28877d942ceSSteven Rostedt	if (defined($variable{$var})) {
28977d942ceSSteven Rostedt	    $retval = "$retval$variable{$var}";
29077d942ceSSteven Rostedt	} else {
29177d942ceSSteven Rostedt	    # put back the origin piece.
29277d942ceSSteven Rostedt	    $retval = "$retval\$\{$var\}";
29377d942ceSSteven Rostedt	}
29477d942ceSSteven Rostedt	$value = $end;
29577d942ceSSteven Rostedt    }
29677d942ceSSteven Rostedt    $retval = "$retval$value";
29777d942ceSSteven Rostedt
29877d942ceSSteven Rostedt    # remove the space added in the beginning
29977d942ceSSteven Rostedt    $retval =~ s/ //;
30077d942ceSSteven Rostedt
30177d942ceSSteven Rostedt    return "$retval"
30277d942ceSSteven Rostedt}
30377d942ceSSteven Rostedt
304a57419b3SSteven Rostedtsub set_value {
305a57419b3SSteven Rostedt    my ($lvalue, $rvalue) = @_;
3062545eb61SSteven Rostedt
307a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
308a75fececSSteven Rostedt	die "Error: Option $lvalue defined more than once!\n";
309a75fececSSteven Rostedt    }
31021a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
31121a9679fSSteven Rostedt	delete $opt{$lvalue};
31221a9679fSSteven Rostedt    } else {
31377d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
31421a9679fSSteven Rostedt	$opt{$lvalue} = $rvalue;
31521a9679fSSteven Rostedt    }
3162545eb61SSteven Rostedt}
317a57419b3SSteven Rostedt
31877d942ceSSteven Rostedtsub set_variable {
31977d942ceSSteven Rostedt    my ($lvalue, $rvalue) = @_;
32077d942ceSSteven Rostedt
32177d942ceSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
32277d942ceSSteven Rostedt	delete $variable{$lvalue};
32377d942ceSSteven Rostedt    } else {
32477d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
32577d942ceSSteven Rostedt	$variable{$lvalue} = $rvalue;
32677d942ceSSteven Rostedt    }
32777d942ceSSteven Rostedt}
32877d942ceSSteven Rostedt
329a57419b3SSteven Rostedtsub read_config {
330a57419b3SSteven Rostedt    my ($config) = @_;
331a57419b3SSteven Rostedt
332a57419b3SSteven Rostedt    open(IN, $config) || die "can't read file $config";
333a57419b3SSteven Rostedt
334a57419b3SSteven Rostedt    my $name = $config;
335a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
336a57419b3SSteven Rostedt
337a57419b3SSteven Rostedt    my $test_num = 0;
338a57419b3SSteven Rostedt    my $default = 1;
339a57419b3SSteven Rostedt    my $repeat = 1;
340a57419b3SSteven Rostedt    my $num_tests_set = 0;
341a57419b3SSteven Rostedt    my $skip = 0;
342a57419b3SSteven Rostedt    my $rest;
343a57419b3SSteven Rostedt
344a57419b3SSteven Rostedt    while (<IN>) {
345a57419b3SSteven Rostedt
346a57419b3SSteven Rostedt	# ignore blank lines and comments
347a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
348a57419b3SSteven Rostedt
349a57419b3SSteven Rostedt	if (/^\s*TEST_START(.*)/) {
350a57419b3SSteven Rostedt
351a57419b3SSteven Rostedt	    $rest = $1;
352a57419b3SSteven Rostedt
353a57419b3SSteven Rostedt	    if ($num_tests_set) {
354a57419b3SSteven Rostedt		die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
355a57419b3SSteven Rostedt	    }
356a57419b3SSteven Rostedt
357a57419b3SSteven Rostedt	    my $old_test_num = $test_num;
358e48c5293SSteven Rostedt	    my $old_repeat = $repeat;
359a57419b3SSteven Rostedt
360a57419b3SSteven Rostedt	    $test_num += $repeat;
361a57419b3SSteven Rostedt	    $default = 0;
362a57419b3SSteven Rostedt	    $repeat = 1;
363a57419b3SSteven Rostedt
364a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
365a57419b3SSteven Rostedt		$rest = $1;
366a57419b3SSteven Rostedt		$skip = 1;
367a57419b3SSteven Rostedt	    } else {
368a57419b3SSteven Rostedt		$skip = 0;
369a57419b3SSteven Rostedt	    }
370a57419b3SSteven Rostedt
371a57419b3SSteven Rostedt	    if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
372a57419b3SSteven Rostedt		$repeat = $1;
373a57419b3SSteven Rostedt		$rest = $2;
374a57419b3SSteven Rostedt		$repeat_tests{"$test_num"} = $repeat;
375a57419b3SSteven Rostedt	    }
376a57419b3SSteven Rostedt
377a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
378a57419b3SSteven Rostedt		$rest = $1;
379a57419b3SSteven Rostedt		$skip = 1;
380a57419b3SSteven Rostedt	    }
381a57419b3SSteven Rostedt
382a57419b3SSteven Rostedt	    if ($rest !~ /^\s*$/) {
383a57419b3SSteven Rostedt		die "$name: $.: Gargbage found after TEST_START\n$_";
384a57419b3SSteven Rostedt	    }
385a57419b3SSteven Rostedt
386a57419b3SSteven Rostedt	    if ($skip) {
387a57419b3SSteven Rostedt		$test_num = $old_test_num;
388e48c5293SSteven Rostedt		$repeat = $old_repeat;
389a57419b3SSteven Rostedt	    }
390a57419b3SSteven Rostedt
391a57419b3SSteven Rostedt	} elsif (/^\s*DEFAULTS(.*)$/) {
392a57419b3SSteven Rostedt	    $default = 1;
393a57419b3SSteven Rostedt
394a57419b3SSteven Rostedt	    $rest = $1;
395a57419b3SSteven Rostedt
396a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
397a57419b3SSteven Rostedt		$rest = $1;
398a57419b3SSteven Rostedt		$skip = 1;
399a57419b3SSteven Rostedt	    } else {
400a57419b3SSteven Rostedt		$skip = 0;
401a57419b3SSteven Rostedt	    }
402a57419b3SSteven Rostedt
403a57419b3SSteven Rostedt	    if ($rest !~ /^\s*$/) {
404a57419b3SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
405a57419b3SSteven Rostedt	    }
406a57419b3SSteven Rostedt
407a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
408a57419b3SSteven Rostedt
409a57419b3SSteven Rostedt	    next if ($skip);
410a57419b3SSteven Rostedt
411a57419b3SSteven Rostedt	    my $lvalue = $1;
412a57419b3SSteven Rostedt	    my $rvalue = $2;
413a57419b3SSteven Rostedt
414a57419b3SSteven Rostedt	    if (!$default &&
415a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
416a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
417a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
418a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
419a57419b3SSteven Rostedt	    }
420a57419b3SSteven Rostedt
421a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
422a57419b3SSteven Rostedt		if ($test_num) {
423a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
424a57419b3SSteven Rostedt		}
425a57419b3SSteven Rostedt		if (!$default) {
426a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
427a57419b3SSteven Rostedt		}
428a57419b3SSteven Rostedt		$num_tests_set = 1;
429a57419b3SSteven Rostedt	    }
430a57419b3SSteven Rostedt
431a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
432a57419b3SSteven Rostedt		set_value($lvalue, $rvalue);
433a57419b3SSteven Rostedt	    } else {
434a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
435a57419b3SSteven Rostedt		set_value($val, $rvalue);
436a57419b3SSteven Rostedt
437a57419b3SSteven Rostedt		if ($repeat > 1) {
438a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
439a57419b3SSteven Rostedt		}
440a57419b3SSteven Rostedt	    }
44177d942ceSSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
44277d942ceSSteven Rostedt	    next if ($skip);
44377d942ceSSteven Rostedt
44477d942ceSSteven Rostedt	    my $lvalue = $1;
44577d942ceSSteven Rostedt	    my $rvalue = $2;
44677d942ceSSteven Rostedt
44777d942ceSSteven Rostedt	    # process config variables.
44877d942ceSSteven Rostedt	    # Config variables are only active while reading the
44977d942ceSSteven Rostedt	    # config and can be defined anywhere. They also ignore
45077d942ceSSteven Rostedt	    # TEST_START and DEFAULTS, but are skipped if they are in
45177d942ceSSteven Rostedt	    # on of these sections that have SKIP defined.
45277d942ceSSteven Rostedt	    # The save variable can be
45377d942ceSSteven Rostedt	    # defined multiple times and the new one simply overrides
45477d942ceSSteven Rostedt	    # the prevous one.
45577d942ceSSteven Rostedt	    set_variable($lvalue, $rvalue);
45677d942ceSSteven Rostedt
457a57419b3SSteven Rostedt	} else {
458a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
459a57419b3SSteven Rostedt	}
4602545eb61SSteven Rostedt    }
4612545eb61SSteven Rostedt
4622545eb61SSteven Rostedt    close(IN);
463a75fececSSteven Rostedt
464a57419b3SSteven Rostedt    if ($test_num) {
465a57419b3SSteven Rostedt	$test_num += $repeat - 1;
466a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
467a57419b3SSteven Rostedt    }
468a57419b3SSteven Rostedt
4698d1491baSSteven Rostedt    # make sure we have all mandatory configs
4708d1491baSSteven Rostedt    get_ktest_configs;
4718d1491baSSteven Rostedt
472a75fececSSteven Rostedt    # set any defaults
473a75fececSSteven Rostedt
474a75fececSSteven Rostedt    foreach my $default (keys %default) {
475a75fececSSteven Rostedt	if (!defined($opt{$default})) {
476a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
477a75fececSSteven Rostedt	}
478a75fececSSteven Rostedt    }
4792545eb61SSteven Rostedt}
4802545eb61SSteven Rostedt
481d1e2f22aSSteven Rostedtsub _logit {
4822545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
4832545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
4842545eb61SSteven Rostedt	print OUT @_;
4852545eb61SSteven Rostedt	close(OUT);
4862545eb61SSteven Rostedt    }
4872545eb61SSteven Rostedt}
4882545eb61SSteven Rostedt
489d1e2f22aSSteven Rostedtsub logit {
490d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
491d1e2f22aSSteven Rostedt	_logit @_;
492d1e2f22aSSteven Rostedt    } else {
493d1e2f22aSSteven Rostedt	print @_;
494d1e2f22aSSteven Rostedt    }
495d1e2f22aSSteven Rostedt}
496d1e2f22aSSteven Rostedt
4975f9b6cedSSteven Rostedtsub doprint {
4985f9b6cedSSteven Rostedt    print @_;
499d1e2f22aSSteven Rostedt    _logit @_;
5005f9b6cedSSteven Rostedt}
5015f9b6cedSSteven Rostedt
5027faafbd6SSteven Rostedtsub run_command;
5037faafbd6SSteven Rostedt
5047faafbd6SSteven Rostedtsub reboot {
5057faafbd6SSteven Rostedt    # try to reboot normally
506e48c5293SSteven Rostedt    if (run_command $reboot) {
507576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
508576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
509576f627cSSteven Rostedt	    run_command "$power_cycle";
510576f627cSSteven Rostedt	}
511576f627cSSteven Rostedt    } else {
5127faafbd6SSteven Rostedt	# nope? power cycle it.
513a75fececSSteven Rostedt	run_command "$power_cycle";
5147faafbd6SSteven Rostedt    }
5157faafbd6SSteven Rostedt}
5167faafbd6SSteven Rostedt
517576f627cSSteven Rostedtsub do_not_reboot {
518576f627cSSteven Rostedt    my $i = $iteration;
519576f627cSSteven Rostedt
520576f627cSSteven Rostedt    return $test_type eq "build" ||
521576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
522576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
523576f627cSSteven Rostedt}
524576f627cSSteven Rostedt
5255c42fc5bSSteven Rostedtsub dodie {
5265a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
5275c42fc5bSSteven Rostedt
528576f627cSSteven Rostedt    my $i = $iteration;
529576f627cSSteven Rostedt
530576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
531576f627cSSteven Rostedt
53275c3fda7SSteven Rostedt	doprint "REBOOTING\n";
5337faafbd6SSteven Rostedt	reboot;
53475c3fda7SSteven Rostedt
535a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
5365c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
537a75fececSSteven Rostedt	`$power_off`;
5385c42fc5bSSteven Rostedt    }
53975c3fda7SSteven Rostedt
540f80802cbSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
541f80802cbSSteven Rostedt	print " See $opt{LOG_FILE} for more info.\n";
542f80802cbSSteven Rostedt    }
543f80802cbSSteven Rostedt
544576f627cSSteven Rostedt    die @_, "\n";
5455c42fc5bSSteven Rostedt}
5465c42fc5bSSteven Rostedt
5477faafbd6SSteven Rostedtsub open_console {
5487faafbd6SSteven Rostedt    my ($fp) = @_;
5497faafbd6SSteven Rostedt
5507faafbd6SSteven Rostedt    my $flags;
5517faafbd6SSteven Rostedt
552a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
553a75fececSSteven Rostedt	dodie "Can't open console $console";
5547faafbd6SSteven Rostedt
5557faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
556576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
5577faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
558576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
5597faafbd6SSteven Rostedt
5607faafbd6SSteven Rostedt    return $pid;
5617faafbd6SSteven Rostedt}
5627faafbd6SSteven Rostedt
5637faafbd6SSteven Rostedtsub close_console {
5647faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
5657faafbd6SSteven Rostedt
5667faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
5677faafbd6SSteven Rostedt    kill 2, $pid;
5687faafbd6SSteven Rostedt
5697faafbd6SSteven Rostedt    print "closing!\n";
5707faafbd6SSteven Rostedt    close($fp);
5717faafbd6SSteven Rostedt}
5727faafbd6SSteven Rostedt
5737faafbd6SSteven Rostedtsub start_monitor {
5747faafbd6SSteven Rostedt    if ($monitor_cnt++) {
5757faafbd6SSteven Rostedt	return;
5767faafbd6SSteven Rostedt    }
5777faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
5787faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
579a75fececSSteven Rostedt
580a75fececSSteven Rostedt    return;
581a75fececSSteven Rostedt
582a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
5837faafbd6SSteven Rostedt}
5847faafbd6SSteven Rostedt
5857faafbd6SSteven Rostedtsub end_monitor {
5867faafbd6SSteven Rostedt    if (--$monitor_cnt) {
5877faafbd6SSteven Rostedt	return;
5887faafbd6SSteven Rostedt    }
5897faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
5907faafbd6SSteven Rostedt}
5917faafbd6SSteven Rostedt
5927faafbd6SSteven Rostedtsub wait_for_monitor {
5937faafbd6SSteven Rostedt    my ($time) = @_;
5947faafbd6SSteven Rostedt    my $line;
5957faafbd6SSteven Rostedt
596a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
5977faafbd6SSteven Rostedt
5987faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
5997faafbd6SSteven Rostedt    do {
6007faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
601a75fececSSteven Rostedt	print "$line" if (defined($line));
6027faafbd6SSteven Rostedt    } while (defined($line));
603a75fececSSteven Rostedt    print "** Monitor flushed **\n";
6047faafbd6SSteven Rostedt}
6057faafbd6SSteven Rostedt
6062b7d9b21SSteven Rostedtsub fail {
6072b7d9b21SSteven Rostedt
608a75fececSSteven Rostedt	if ($die_on_failure) {
6092b7d9b21SSteven Rostedt		dodie @_;
6102b7d9b21SSteven Rostedt	}
6112b7d9b21SSteven Rostedt
612a75fececSSteven Rostedt	doprint "FAILED\n";
6137faafbd6SSteven Rostedt
614576f627cSSteven Rostedt	my $i = $iteration;
615576f627cSSteven Rostedt
616a75fececSSteven Rostedt	# no need to reboot for just building.
617576f627cSSteven Rostedt	if (!do_not_reboot) {
6187faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
6197faafbd6SSteven Rostedt	    reboot;
6207faafbd6SSteven Rostedt	    start_monitor;
621a75fececSSteven Rostedt	    wait_for_monitor $sleep_time;
6227faafbd6SSteven Rostedt	    end_monitor;
623a75fececSSteven Rostedt	}
6247faafbd6SSteven Rostedt
6259064af52SSteven Rostedt	my $name = "";
6269064af52SSteven Rostedt
6279064af52SSteven Rostedt	if (defined($test_name)) {
6289064af52SSteven Rostedt	    $name = " ($test_name)";
6299064af52SSteven Rostedt	}
6309064af52SSteven Rostedt
631576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
632576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
6339064af52SSteven Rostedt	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
634576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
635576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
636a75fececSSteven Rostedt
637a75fececSSteven Rostedt	return 1 if (!defined($store_failures));
6387faafbd6SSteven Rostedt
6397faafbd6SSteven Rostedt	my @t = localtime;
6407faafbd6SSteven Rostedt	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
6417faafbd6SSteven Rostedt		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
6427faafbd6SSteven Rostedt
643cccae1a6SSteven Rostedt	my $type = $build_type;
644cccae1a6SSteven Rostedt	if ($type =~ /useconfig/) {
645cccae1a6SSteven Rostedt	    $type = "useconfig";
646cccae1a6SSteven Rostedt	}
647cccae1a6SSteven Rostedt
648cccae1a6SSteven Rostedt	my $dir = "$machine-$test_type-$type-fail-$date";
649a75fececSSteven Rostedt	my $faildir = "$store_failures/$dir";
6507faafbd6SSteven Rostedt
6517faafbd6SSteven Rostedt	if (!-d $faildir) {
6527faafbd6SSteven Rostedt	    mkpath($faildir) or
653a75fececSSteven Rostedt		die "can't create $faildir";
6547faafbd6SSteven Rostedt	}
65551ad1dd1SSteven Rostedt	if (-f "$output_config") {
65651ad1dd1SSteven Rostedt	    cp "$output_config", "$faildir/config" or
6577faafbd6SSteven Rostedt		die "failed to copy .config";
6587faafbd6SSteven Rostedt	}
6597faafbd6SSteven Rostedt	if (-f $buildlog) {
6607faafbd6SSteven Rostedt	    cp $buildlog, "$faildir/buildlog" or
6617faafbd6SSteven Rostedt		die "failed to move $buildlog";
6627faafbd6SSteven Rostedt	}
6637faafbd6SSteven Rostedt	if (-f $dmesg) {
6647faafbd6SSteven Rostedt	    cp $dmesg, "$faildir/dmesg" or
6657faafbd6SSteven Rostedt		die "failed to move $dmesg";
6667faafbd6SSteven Rostedt	}
6677faafbd6SSteven Rostedt
6687faafbd6SSteven Rostedt	doprint "*** Saved info to $faildir ***\n";
6697faafbd6SSteven Rostedt
6702b7d9b21SSteven Rostedt	return 1;
6712b7d9b21SSteven Rostedt}
6722b7d9b21SSteven Rostedt
6732545eb61SSteven Rostedtsub run_command {
6742545eb61SSteven Rostedt    my ($command) = @_;
675d6ce2a0bSSteven Rostedt    my $dolog = 0;
676d6ce2a0bSSteven Rostedt    my $dord = 0;
677d6ce2a0bSSteven Rostedt    my $pid;
678d6ce2a0bSSteven Rostedt
679e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
680e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
681e48c5293SSteven Rostedt
682d6ce2a0bSSteven Rostedt    doprint("$command ... ");
683d6ce2a0bSSteven Rostedt
684d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
6852b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
6862545eb61SSteven Rostedt
6872545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
688d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
689d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
690d6ce2a0bSSteven Rostedt	$dolog = 1;
6916c5ee0beSSteven Rostedt    }
6926c5ee0beSSteven Rostedt
6936c5ee0beSSteven Rostedt    if (defined($redirect)) {
694d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
695d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
696d6ce2a0bSSteven Rostedt	$dord = 1;
6972545eb61SSteven Rostedt    }
6982545eb61SSteven Rostedt
699d6ce2a0bSSteven Rostedt    while (<CMD>) {
700d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
701d6ce2a0bSSteven Rostedt	print RD  if ($dord);
702d6ce2a0bSSteven Rostedt    }
7032545eb61SSteven Rostedt
704d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
7052545eb61SSteven Rostedt    my $failed = $?;
7062545eb61SSteven Rostedt
707d6ce2a0bSSteven Rostedt    close(CMD);
708d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
709d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
710d6ce2a0bSSteven Rostedt
7112545eb61SSteven Rostedt    if ($failed) {
7122545eb61SSteven Rostedt	doprint "FAILED!\n";
7132545eb61SSteven Rostedt    } else {
7142545eb61SSteven Rostedt	doprint "SUCCESS\n";
7152545eb61SSteven Rostedt    }
7162545eb61SSteven Rostedt
7175f9b6cedSSteven Rostedt    return !$failed;
7185f9b6cedSSteven Rostedt}
7195f9b6cedSSteven Rostedt
720e48c5293SSteven Rostedtsub run_ssh {
721e48c5293SSteven Rostedt    my ($cmd) = @_;
722e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
723e48c5293SSteven Rostedt
724e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
725e48c5293SSteven Rostedt    return run_command "$cp_exec";
726e48c5293SSteven Rostedt}
727e48c5293SSteven Rostedt
728e48c5293SSteven Rostedtsub run_scp {
729e48c5293SSteven Rostedt    my ($src, $dst) = @_;
730e48c5293SSteven Rostedt    my $cp_scp = $scp_to_target;
731e48c5293SSteven Rostedt
732e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
733e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
734e48c5293SSteven Rostedt
735e48c5293SSteven Rostedt    return run_command "$cp_scp";
736e48c5293SSteven Rostedt}
737e48c5293SSteven Rostedt
7385f9b6cedSSteven Rostedtsub get_grub_index {
7395f9b6cedSSteven Rostedt
740a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
741a75fececSSteven Rostedt	return;
742a75fececSSteven Rostedt    }
7435a391fbfSSteven Rostedt    return if (defined($grub_number));
7445f9b6cedSSteven Rostedt
7455f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
7465f9b6cedSSteven Rostedt    $grub_number = -1;
747e48c5293SSteven Rostedt
748e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
749e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
750e48c5293SSteven Rostedt
751e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
7525f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
753e48c5293SSteven Rostedt
7545f9b6cedSSteven Rostedt    while (<IN>) {
755a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
7565f9b6cedSSteven Rostedt	    $grub_number++;
7575f9b6cedSSteven Rostedt	    last;
7585f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
7595f9b6cedSSteven Rostedt	    $grub_number++;
7605f9b6cedSSteven Rostedt	}
7615f9b6cedSSteven Rostedt    }
7625f9b6cedSSteven Rostedt    close(IN);
7635f9b6cedSSteven Rostedt
764a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
7655f9b6cedSSteven Rostedt	if ($grub_number < 0);
7665f9b6cedSSteven Rostedt    doprint "$grub_number\n";
7672545eb61SSteven Rostedt}
7682545eb61SSteven Rostedt
7692545eb61SSteven Rostedtsub wait_for_input
7702545eb61SSteven Rostedt{
7712545eb61SSteven Rostedt    my ($fp, $time) = @_;
7722545eb61SSteven Rostedt    my $rin;
7732545eb61SSteven Rostedt    my $ready;
7742545eb61SSteven Rostedt    my $line;
7752545eb61SSteven Rostedt    my $ch;
7762545eb61SSteven Rostedt
7772545eb61SSteven Rostedt    if (!defined($time)) {
7782545eb61SSteven Rostedt	$time = $timeout;
7792545eb61SSteven Rostedt    }
7802545eb61SSteven Rostedt
7812545eb61SSteven Rostedt    $rin = '';
7822545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
7832545eb61SSteven Rostedt    $ready = select($rin, undef, undef, $time);
7842545eb61SSteven Rostedt
7852545eb61SSteven Rostedt    $line = "";
7862545eb61SSteven Rostedt
7872545eb61SSteven Rostedt    # try to read one char at a time
7882545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
7892545eb61SSteven Rostedt	$line .= $ch;
7902545eb61SSteven Rostedt	last if ($ch eq "\n");
7912545eb61SSteven Rostedt    }
7922545eb61SSteven Rostedt
7932545eb61SSteven Rostedt    if (!length($line)) {
7942545eb61SSteven Rostedt	return undef;
7952545eb61SSteven Rostedt    }
7962545eb61SSteven Rostedt
7972545eb61SSteven Rostedt    return $line;
7982545eb61SSteven Rostedt}
7992545eb61SSteven Rostedt
80075c3fda7SSteven Rostedtsub reboot_to {
801a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
8024da46da2SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'";
803a75fececSSteven Rostedt	return;
804a75fececSSteven Rostedt    }
805a75fececSSteven Rostedt
806a75fececSSteven Rostedt    run_command "$reboot_script";
8072545eb61SSteven Rostedt}
8082545eb61SSteven Rostedt
809a57419b3SSteven Rostedtsub get_sha1 {
810a57419b3SSteven Rostedt    my ($commit) = @_;
811a57419b3SSteven Rostedt
812a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
813a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
814a57419b3SSteven Rostedt    my $ret = $?;
815a57419b3SSteven Rostedt
816a57419b3SSteven Rostedt    logit $sha1;
817a57419b3SSteven Rostedt
818a57419b3SSteven Rostedt    if ($ret) {
819a57419b3SSteven Rostedt	doprint "FAILED\n";
820a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
821a57419b3SSteven Rostedt    }
822a57419b3SSteven Rostedt
823a57419b3SSteven Rostedt    print "SUCCESS\n";
824a57419b3SSteven Rostedt
825a57419b3SSteven Rostedt    chomp $sha1;
826a57419b3SSteven Rostedt
827a57419b3SSteven Rostedt    return $sha1;
828a57419b3SSteven Rostedt}
829a57419b3SSteven Rostedt
8305a391fbfSSteven Rostedtsub monitor {
8312545eb61SSteven Rostedt    my $booted = 0;
8322545eb61SSteven Rostedt    my $bug = 0;
8335c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
8342b7d9b21SSteven Rostedt    my $loops;
8352545eb61SSteven Rostedt
8367faafbd6SSteven Rostedt    wait_for_monitor 5;
8372545eb61SSteven Rostedt
8382545eb61SSteven Rostedt    my $line;
8392545eb61SSteven Rostedt    my $full_line = "";
8402545eb61SSteven Rostedt
8417faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
8427faafbd6SSteven Rostedt	die "unable to write to $dmesg";
8432545eb61SSteven Rostedt
84475c3fda7SSteven Rostedt    reboot_to;
8452545eb61SSteven Rostedt
8461c8a617aSSteven Rostedt    my $success_start;
8471c8a617aSSteven Rostedt    my $failure_start;
8482d01b26aSSteven Rostedt    my $monitor_start = time;
8492d01b26aSSteven Rostedt    my $done = 0;
850f1a5b962SSteven Rostedt    my $version_found = 0;
8511c8a617aSSteven Rostedt
8522d01b26aSSteven Rostedt    while (!$done) {
8532545eb61SSteven Rostedt
8542b7d9b21SSteven Rostedt	if ($booted) {
855a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
856cd4f1d53SSteven Rostedt	    if (!defined($line)) {
857cd4f1d53SSteven Rostedt		my $s = $booted_timeout == 1 ? "" : "s";
858cd4f1d53SSteven Rostedt		doprint "Successful boot found: break after $booted_timeout second$s\n";
859cd4f1d53SSteven Rostedt		last;
860cd4f1d53SSteven Rostedt	    }
8612b7d9b21SSteven Rostedt	} else {
8627faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
863cd4f1d53SSteven Rostedt	    if (!defined($line)) {
864cd4f1d53SSteven Rostedt		my $s = $timeout == 1 ? "" : "s";
865cd4f1d53SSteven Rostedt		doprint "Timed out after $timeout second$s\n";
866cd4f1d53SSteven Rostedt		last;
8672b7d9b21SSteven Rostedt	    }
868cd4f1d53SSteven Rostedt	}
8692545eb61SSteven Rostedt
8702545eb61SSteven Rostedt	doprint $line;
8717faafbd6SSteven Rostedt	print DMESG $line;
8722545eb61SSteven Rostedt
8732545eb61SSteven Rostedt	# we are not guaranteed to get a full line
8742545eb61SSteven Rostedt	$full_line .= $line;
8752545eb61SSteven Rostedt
876a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
8772545eb61SSteven Rostedt	    $booted = 1;
8781c8a617aSSteven Rostedt	    $success_start = time;
8791c8a617aSSteven Rostedt	}
8801c8a617aSSteven Rostedt
8811c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
8821c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
8831c8a617aSSteven Rostedt	    my $now = time;
8841c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
8851c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
8861c8a617aSSteven Rostedt		last;
8871c8a617aSSteven Rostedt	    }
8882545eb61SSteven Rostedt	}
8892545eb61SSteven Rostedt
8905c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
8915c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
8925c42fc5bSSteven Rostedt	}
8935c42fc5bSSteven Rostedt
8942545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
8954651920eSSteven Rostedt	    if (!$bug && !$skip_call_trace) {
8961c8a617aSSteven Rostedt		$bug = 1;
8971c8a617aSSteven Rostedt		$failure_start = time;
8981c8a617aSSteven Rostedt	    }
8991c8a617aSSteven Rostedt	}
9001c8a617aSSteven Rostedt
9011c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
9021c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
9031c8a617aSSteven Rostedt	    my $now = time;
9041c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
9051c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
9061c8a617aSSteven Rostedt		last;
9071c8a617aSSteven Rostedt	    }
9085c42fc5bSSteven Rostedt	}
9095c42fc5bSSteven Rostedt
9105c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
9115c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
9125c42fc5bSSteven Rostedt	}
9135c42fc5bSSteven Rostedt
9145c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
91510abf118SSteven Rostedt	    $failure_start = time;
9162545eb61SSteven Rostedt	    $bug = 1;
9172545eb61SSteven Rostedt	}
9182545eb61SSteven Rostedt
919f1a5b962SSteven Rostedt	# Detect triple faults by testing the banner
920f1a5b962SSteven Rostedt	if ($full_line =~ /\bLinux version (\S+).*\n/) {
921f1a5b962SSteven Rostedt	    if ($1 eq $version) {
922f1a5b962SSteven Rostedt		$version_found = 1;
923f1a5b962SSteven Rostedt	    } elsif ($version_found && $detect_triplefault) {
924f1a5b962SSteven Rostedt		# We already booted into the kernel we are testing,
925f1a5b962SSteven Rostedt		# but now we booted into another kernel?
926f1a5b962SSteven Rostedt		# Consider this a triple fault.
927f1a5b962SSteven Rostedt		doprint "Aleady booted in Linux kernel $version, but now\n";
928f1a5b962SSteven Rostedt		doprint "we booted into Linux kernel $1.\n";
929f1a5b962SSteven Rostedt		doprint "Assuming that this is a triple fault.\n";
930f1a5b962SSteven Rostedt		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
931f1a5b962SSteven Rostedt		last;
932f1a5b962SSteven Rostedt	    }
933f1a5b962SSteven Rostedt	}
934f1a5b962SSteven Rostedt
9352545eb61SSteven Rostedt	if ($line =~ /\n/) {
9362545eb61SSteven Rostedt	    $full_line = "";
9372545eb61SSteven Rostedt	}
9382d01b26aSSteven Rostedt
9392d01b26aSSteven Rostedt	if ($stop_test_after > 0 && !$booted && !$bug) {
9402d01b26aSSteven Rostedt	    if (time - $monitor_start > $stop_test_after) {
9414d62bf51SSteven Rostedt		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
9422d01b26aSSteven Rostedt		$done = 1;
9432d01b26aSSteven Rostedt	    }
9442d01b26aSSteven Rostedt	}
9452545eb61SSteven Rostedt    }
9462545eb61SSteven Rostedt
9477faafbd6SSteven Rostedt    close(DMESG);
9482545eb61SSteven Rostedt
9492545eb61SSteven Rostedt    if ($bug) {
9502b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
951576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
9522545eb61SSteven Rostedt    }
9535f9b6cedSSteven Rostedt
954a75fececSSteven Rostedt    if (!$booted) {
955a75fececSSteven Rostedt	return 0 if ($in_bisect);
956576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
957a75fececSSteven Rostedt    }
958a75fececSSteven Rostedt
9592b7d9b21SSteven Rostedt    return 1;
9602545eb61SSteven Rostedt}
9612545eb61SSteven Rostedt
9622545eb61SSteven Rostedtsub install {
9632545eb61SSteven Rostedt
964e48c5293SSteven Rostedt    run_scp "$outputdir/$build_target", "$target_image" or
9655c42fc5bSSteven Rostedt	dodie "failed to copy image";
9665f9b6cedSSteven Rostedt
9675f9b6cedSSteven Rostedt    my $install_mods = 0;
9685f9b6cedSSteven Rostedt
9695f9b6cedSSteven Rostedt    # should we process modules?
9705f9b6cedSSteven Rostedt    $install_mods = 0;
97151ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
9725f9b6cedSSteven Rostedt    while (<IN>) {
9735f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
9745f9b6cedSSteven Rostedt	    $install_mods = 1 if (defined($1));
9755f9b6cedSSteven Rostedt	    last;
9765f9b6cedSSteven Rostedt	}
9775f9b6cedSSteven Rostedt    }
9785f9b6cedSSteven Rostedt    close(IN);
9795f9b6cedSSteven Rostedt
9805f9b6cedSSteven Rostedt    if (!$install_mods) {
9815f9b6cedSSteven Rostedt	doprint "No modules needed\n";
9825f9b6cedSSteven Rostedt	return;
9832545eb61SSteven Rostedt    }
9842545eb61SSteven Rostedt
985a75fececSSteven Rostedt    run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
9865f9b6cedSSteven Rostedt	dodie "Failed to install modules";
9875f9b6cedSSteven Rostedt
9882545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
989a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
9902545eb61SSteven Rostedt
991e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
9925c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
9932545eb61SSteven Rostedt
9945c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
995a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
9965c42fc5bSSteven Rostedt	dodie "making tarball";
9975c42fc5bSSteven Rostedt
998e48c5293SSteven Rostedt    run_scp "$tmpdir/$modtar", "/tmp" or
9995c42fc5bSSteven Rostedt	dodie "failed to copy modules";
10005c42fc5bSSteven Rostedt
1001a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
10025c42fc5bSSteven Rostedt
1003e48c5293SSteven Rostedt    run_ssh "'(cd / && tar xf /tmp/$modtar)'" or
10045c42fc5bSSteven Rostedt	dodie "failed to tar modules";
10055c42fc5bSSteven Rostedt
1006e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
10078b37ca8cSSteven Rostedt
10088b37ca8cSSteven Rostedt    return if (!defined($post_install));
10098b37ca8cSSteven Rostedt
1010e48c5293SSteven Rostedt    my $cp_post_install = $post_install;
1011ca6a21f8SSteven Rostedt    $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
1012e48c5293SSteven Rostedt    run_command "$cp_post_install" or
1013576f627cSSteven Rostedt	dodie "Failed to run post install";
10142545eb61SSteven Rostedt}
10152545eb61SSteven Rostedt
10166c5ee0beSSteven Rostedtsub check_buildlog {
10176c5ee0beSSteven Rostedt    my ($patch) = @_;
10186c5ee0beSSteven Rostedt
10196c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
10206c5ee0beSSteven Rostedt
10216c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
10226c5ee0beSSteven Rostedt	dodie "failed to show $patch";
10236c5ee0beSSteven Rostedt    while (<IN>) {
10246c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
10256c5ee0beSSteven Rostedt	    chomp $1;
10266c5ee0beSSteven Rostedt	    $files[$#files] = $1;
10276c5ee0beSSteven Rostedt	}
10286c5ee0beSSteven Rostedt    }
10296c5ee0beSSteven Rostedt    close(IN);
10306c5ee0beSSteven Rostedt
10316c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
10326c5ee0beSSteven Rostedt    while (<IN>) {
10336c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
10346c5ee0beSSteven Rostedt	    my $err = $1;
10356c5ee0beSSteven Rostedt	    foreach my $file (@files) {
1036a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
10376c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
10382b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
10396c5ee0beSSteven Rostedt		}
10406c5ee0beSSteven Rostedt	    }
10416c5ee0beSSteven Rostedt	}
10426c5ee0beSSteven Rostedt    }
10436c5ee0beSSteven Rostedt    close(IN);
10442b7d9b21SSteven Rostedt
10452b7d9b21SSteven Rostedt    return 1;
10466c5ee0beSSteven Rostedt}
10476c5ee0beSSteven Rostedt
1048*fcb3f16aSSteven Rostedtsub apply_min_config {
1049*fcb3f16aSSteven Rostedt    my $outconfig = "$output_config.new";
1050612b9e9bSSteven Rostedt
1051*fcb3f16aSSteven Rostedt    # Read the config file and remove anything that
1052*fcb3f16aSSteven Rostedt    # is in the force_config hash (from minconfig and others)
1053*fcb3f16aSSteven Rostedt    # then add the force config back.
1054*fcb3f16aSSteven Rostedt
1055*fcb3f16aSSteven Rostedt    doprint "Applying minimum configurations into $output_config.new\n";
1056*fcb3f16aSSteven Rostedt
1057*fcb3f16aSSteven Rostedt    open (OUT, ">$outconfig") or
1058*fcb3f16aSSteven Rostedt	dodie "Can't create $outconfig";
1059*fcb3f16aSSteven Rostedt
1060*fcb3f16aSSteven Rostedt    if (-f $output_config) {
1061*fcb3f16aSSteven Rostedt	open (IN, $output_config) or
1062*fcb3f16aSSteven Rostedt	    dodie "Failed to open $output_config";
1063*fcb3f16aSSteven Rostedt	while (<IN>) {
1064*fcb3f16aSSteven Rostedt	    if (/^(# )?(CONFIG_[^\s=]*)/) {
1065*fcb3f16aSSteven Rostedt		next if (defined($force_config{$2}));
1066*fcb3f16aSSteven Rostedt	    }
1067*fcb3f16aSSteven Rostedt	    print OUT;
1068*fcb3f16aSSteven Rostedt	}
1069*fcb3f16aSSteven Rostedt	close IN;
1070*fcb3f16aSSteven Rostedt    }
1071*fcb3f16aSSteven Rostedt    foreach my $config (keys %force_config) {
1072*fcb3f16aSSteven Rostedt	print OUT "$force_config{$config}\n";
1073*fcb3f16aSSteven Rostedt    }
1074*fcb3f16aSSteven Rostedt    close OUT;
1075*fcb3f16aSSteven Rostedt
1076*fcb3f16aSSteven Rostedt    run_command "mv $outconfig $output_config";
1077*fcb3f16aSSteven Rostedt}
1078*fcb3f16aSSteven Rostedt
1079*fcb3f16aSSteven Rostedtsub make_oldconfig {
1080*fcb3f16aSSteven Rostedt
1081*fcb3f16aSSteven Rostedt    apply_min_config;
1082*fcb3f16aSSteven Rostedt
1083*fcb3f16aSSteven Rostedt    if (!run_command "$make oldnoconfig") {
1084612b9e9bSSteven Rostedt	# Perhaps oldnoconfig doesn't exist in this version of the kernel
1085612b9e9bSSteven Rostedt	# try a yes '' | oldconfig
1086612b9e9bSSteven Rostedt	doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1087*fcb3f16aSSteven Rostedt	run_command "yes '' | $make oldconfig" or
1088612b9e9bSSteven Rostedt	    dodie "failed make config oldconfig";
1089612b9e9bSSteven Rostedt    }
1090612b9e9bSSteven Rostedt}
1091612b9e9bSSteven Rostedt
1092*fcb3f16aSSteven Rostedt# read a config file and use this to force new configs.
1093*fcb3f16aSSteven Rostedtsub load_force_config {
1094*fcb3f16aSSteven Rostedt    my ($config) = @_;
1095*fcb3f16aSSteven Rostedt
1096*fcb3f16aSSteven Rostedt    open(IN, $config) or
1097*fcb3f16aSSteven Rostedt	dodie "failed to read $config";
1098*fcb3f16aSSteven Rostedt    while (<IN>) {
1099*fcb3f16aSSteven Rostedt	chomp;
1100*fcb3f16aSSteven Rostedt	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1101*fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1102*fcb3f16aSSteven Rostedt	} elsif (/^# (CONFIG_\S*) is not set/) {
1103*fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1104*fcb3f16aSSteven Rostedt	}
1105*fcb3f16aSSteven Rostedt    }
1106*fcb3f16aSSteven Rostedt    close IN;
1107*fcb3f16aSSteven Rostedt}
1108*fcb3f16aSSteven Rostedt
11092545eb61SSteven Rostedtsub build {
11102545eb61SSteven Rostedt    my ($type) = @_;
11112545eb61SSteven Rostedt
11127faafbd6SSteven Rostedt    unlink $buildlog;
11137faafbd6SSteven Rostedt
111475c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
111551ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
111675c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
11175f9b6cedSSteven Rostedt
111875c3fda7SSteven Rostedt	$type = "oldconfig";
111975c3fda7SSteven Rostedt    }
112075c3fda7SSteven Rostedt
11215c42fc5bSSteven Rostedt    # old config can ask questions
11225c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
11239386c6abSSteven Rostedt	$type = "oldnoconfig";
112475c3fda7SSteven Rostedt
112575c3fda7SSteven Rostedt	# allow for empty configs
112651ad1dd1SSteven Rostedt	run_command "touch $output_config";
112775c3fda7SSteven Rostedt
112851ad1dd1SSteven Rostedt	run_command "mv $output_config $outputdir/config_temp" or
11295c42fc5bSSteven Rostedt	    dodie "moving .config";
11305c42fc5bSSteven Rostedt
11315f9b6cedSSteven Rostedt	if (!$noclean && !run_command "$make mrproper") {
11325c42fc5bSSteven Rostedt	    dodie "make mrproper";
11335c42fc5bSSteven Rostedt	}
11345c42fc5bSSteven Rostedt
113551ad1dd1SSteven Rostedt	run_command "mv $outputdir/config_temp $output_config" or
11365c42fc5bSSteven Rostedt	    dodie "moving config_temp";
11375c42fc5bSSteven Rostedt
11385c42fc5bSSteven Rostedt    } elsif (!$noclean) {
113951ad1dd1SSteven Rostedt	unlink "$output_config";
11405f9b6cedSSteven Rostedt	run_command "$make mrproper" or
11415c42fc5bSSteven Rostedt	    dodie "make mrproper";
11425c42fc5bSSteven Rostedt    }
11432545eb61SSteven Rostedt
11442545eb61SSteven Rostedt    # add something to distinguish this build
1145a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
1146a75fececSSteven Rostedt    print OUT "$localversion\n";
11472545eb61SSteven Rostedt    close(OUT);
11482545eb61SSteven Rostedt
11495f9b6cedSSteven Rostedt    if (defined($minconfig)) {
1150*fcb3f16aSSteven Rostedt	load_force_config($minconfig);
11512545eb61SSteven Rostedt    }
11522545eb61SSteven Rostedt
1153*fcb3f16aSSteven Rostedt    if ($type ne "oldnoconfig") {
1154*fcb3f16aSSteven Rostedt	run_command "$make $type" or
11555c42fc5bSSteven Rostedt	    dodie "failed make config";
1156612b9e9bSSteven Rostedt    }
1157*fcb3f16aSSteven Rostedt    # Run old config regardless, to enforce min configurations
1158*fcb3f16aSSteven Rostedt    make_oldconfig;
11592545eb61SSteven Rostedt
1160a75fececSSteven Rostedt    $redirect = "$buildlog";
1161a75fececSSteven Rostedt    if (!run_command "$make $build_options") {
11626c5ee0beSSteven Rostedt	undef $redirect;
11635f9b6cedSSteven Rostedt	# bisect may need this to pass
11642b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
11652b7d9b21SSteven Rostedt	fail "failed build" and return 0;
11662545eb61SSteven Rostedt    }
11676c5ee0beSSteven Rostedt    undef $redirect;
11685f9b6cedSSteven Rostedt
11692b7d9b21SSteven Rostedt    return 1;
11702545eb61SSteven Rostedt}
11712545eb61SSteven Rostedt
117275c3fda7SSteven Rostedtsub halt {
1173e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
1174576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
1175576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
1176576f627cSSteven Rostedt	    run_command "$power_off";
1177576f627cSSteven Rostedt	}
1178576f627cSSteven Rostedt    } else {
117975c3fda7SSteven Rostedt	# nope? the zap it!
1180a75fececSSteven Rostedt	run_command "$power_off";
118175c3fda7SSteven Rostedt    }
118275c3fda7SSteven Rostedt}
118375c3fda7SSteven Rostedt
11845f9b6cedSSteven Rostedtsub success {
11855f9b6cedSSteven Rostedt    my ($i) = @_;
11865f9b6cedSSteven Rostedt
1187e48c5293SSteven Rostedt    $successes++;
1188e48c5293SSteven Rostedt
11899064af52SSteven Rostedt    my $name = "";
11909064af52SSteven Rostedt
11919064af52SSteven Rostedt    if (defined($test_name)) {
11929064af52SSteven Rostedt	$name = " ($test_name)";
11939064af52SSteven Rostedt    }
11949064af52SSteven Rostedt
11955f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
11965f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
11979064af52SSteven Rostedt    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
11985f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
11995f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
12005f9b6cedSSteven Rostedt
1201576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1202a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
12035f9b6cedSSteven Rostedt	reboot;
12047faafbd6SSteven Rostedt	start_monitor;
1205a75fececSSteven Rostedt	wait_for_monitor $sleep_time;
12067faafbd6SSteven Rostedt	end_monitor;
12075f9b6cedSSteven Rostedt    }
12085f9b6cedSSteven Rostedt}
12095f9b6cedSSteven Rostedt
12105f9b6cedSSteven Rostedtsub get_version {
12115f9b6cedSSteven Rostedt    # get the release name
12125f9b6cedSSteven Rostedt    doprint "$make kernelrelease ... ";
12135f9b6cedSSteven Rostedt    $version = `$make kernelrelease | tail -1`;
12145f9b6cedSSteven Rostedt    chomp($version);
12155f9b6cedSSteven Rostedt    doprint "$version\n";
12165f9b6cedSSteven Rostedt}
12175f9b6cedSSteven Rostedt
1218c960bb9fSSteven Rostedtsub answer_bisect {
1219c960bb9fSSteven Rostedt    for (;;) {
1220c960bb9fSSteven Rostedt	doprint "Pass or fail? [p/f]";
1221c960bb9fSSteven Rostedt	my $ans = <STDIN>;
1222c960bb9fSSteven Rostedt	chomp $ans;
1223c960bb9fSSteven Rostedt	if ($ans eq "p" || $ans eq "P") {
1224c960bb9fSSteven Rostedt	    return 1;
1225c960bb9fSSteven Rostedt	} elsif ($ans eq "f" || $ans eq "F") {
1226c960bb9fSSteven Rostedt	    return 0;
1227c960bb9fSSteven Rostedt	} else {
1228c960bb9fSSteven Rostedt	    print "Please answer 'P' or 'F'\n";
1229c960bb9fSSteven Rostedt	}
1230c960bb9fSSteven Rostedt    }
1231c960bb9fSSteven Rostedt}
1232c960bb9fSSteven Rostedt
12335a391fbfSSteven Rostedtsub child_run_test {
12347faafbd6SSteven Rostedt    my $failed = 0;
12355a391fbfSSteven Rostedt
12367faafbd6SSteven Rostedt    # child should have no power
1237a75fececSSteven Rostedt    $reboot_on_error = 0;
1238a75fececSSteven Rostedt    $poweroff_on_error = 0;
1239a75fececSSteven Rostedt    $die_on_failure = 1;
12407faafbd6SSteven Rostedt
12417faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
12425a391fbfSSteven Rostedt    exit $failed;
12435a391fbfSSteven Rostedt}
12445a391fbfSSteven Rostedt
12455a391fbfSSteven Rostedtmy $child_done;
12465a391fbfSSteven Rostedt
12475a391fbfSSteven Rostedtsub child_finished {
12485a391fbfSSteven Rostedt    $child_done = 1;
12495a391fbfSSteven Rostedt}
12505a391fbfSSteven Rostedt
12515a391fbfSSteven Rostedtsub do_run_test {
12525a391fbfSSteven Rostedt    my $child_pid;
12535a391fbfSSteven Rostedt    my $child_exit;
12545a391fbfSSteven Rostedt    my $line;
12555a391fbfSSteven Rostedt    my $full_line;
12565a391fbfSSteven Rostedt    my $bug = 0;
12575a391fbfSSteven Rostedt
12587faafbd6SSteven Rostedt    wait_for_monitor 1;
12595a391fbfSSteven Rostedt
12607faafbd6SSteven Rostedt    doprint "run test $run_test\n";
12615a391fbfSSteven Rostedt
12625a391fbfSSteven Rostedt    $child_done = 0;
12635a391fbfSSteven Rostedt
12645a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
12655a391fbfSSteven Rostedt
12665a391fbfSSteven Rostedt    $child_pid = fork;
12675a391fbfSSteven Rostedt
12685a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
12695a391fbfSSteven Rostedt
12705a391fbfSSteven Rostedt    $full_line = "";
12715a391fbfSSteven Rostedt
12725a391fbfSSteven Rostedt    do {
12737faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
12745a391fbfSSteven Rostedt	if (defined($line)) {
12755a391fbfSSteven Rostedt
12765a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
12775a391fbfSSteven Rostedt	    $full_line .= $line;
12788ea0e063SSteven Rostedt	    doprint $line;
12795a391fbfSSteven Rostedt
12805a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
12815a391fbfSSteven Rostedt		$bug = 1;
12825a391fbfSSteven Rostedt	    }
12835a391fbfSSteven Rostedt
12845a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
12855a391fbfSSteven Rostedt		$bug = 1;
12865a391fbfSSteven Rostedt	    }
12875a391fbfSSteven Rostedt
12885a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
12895a391fbfSSteven Rostedt		$full_line = "";
12905a391fbfSSteven Rostedt	    }
12915a391fbfSSteven Rostedt	}
12925a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
12935a391fbfSSteven Rostedt
12945a391fbfSSteven Rostedt    if ($bug) {
12958ea0e063SSteven Rostedt	my $failure_start = time;
12968ea0e063SSteven Rostedt	my $now;
12978ea0e063SSteven Rostedt	do {
12988ea0e063SSteven Rostedt	    $line = wait_for_input($monitor_fp, 1);
12998ea0e063SSteven Rostedt	    if (defined($line)) {
13008ea0e063SSteven Rostedt		doprint $line;
13018ea0e063SSteven Rostedt	    }
13028ea0e063SSteven Rostedt	    $now = time;
13038ea0e063SSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
13048ea0e063SSteven Rostedt		last;
13058ea0e063SSteven Rostedt	    }
13068ea0e063SSteven Rostedt	} while (defined($line));
13078ea0e063SSteven Rostedt
13085a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
13095a391fbfSSteven Rostedt	# kill the child with extreme prejudice
13105a391fbfSSteven Rostedt	kill 9, $child_pid;
13115a391fbfSSteven Rostedt    }
13125a391fbfSSteven Rostedt
13135a391fbfSSteven Rostedt    waitpid $child_pid, 0;
13145a391fbfSSteven Rostedt    $child_exit = $?;
13155a391fbfSSteven Rostedt
13165a391fbfSSteven Rostedt    if ($bug || $child_exit) {
13172b7d9b21SSteven Rostedt	return 0 if $in_bisect;
13182b7d9b21SSteven Rostedt	fail "test failed" and return 0;
13195a391fbfSSteven Rostedt    }
13202b7d9b21SSteven Rostedt    return 1;
13215a391fbfSSteven Rostedt}
13225a391fbfSSteven Rostedt
1323a75fececSSteven Rostedtsub run_git_bisect {
1324a75fececSSteven Rostedt    my ($command) = @_;
1325a75fececSSteven Rostedt
1326a75fececSSteven Rostedt    doprint "$command ... ";
1327a75fececSSteven Rostedt
1328a75fececSSteven Rostedt    my $output = `$command 2>&1`;
1329a75fececSSteven Rostedt    my $ret = $?;
1330a75fececSSteven Rostedt
1331a75fececSSteven Rostedt    logit $output;
1332a75fececSSteven Rostedt
1333a75fececSSteven Rostedt    if ($ret) {
1334a75fececSSteven Rostedt	doprint "FAILED\n";
1335a75fececSSteven Rostedt	dodie "Failed to git bisect";
1336a75fececSSteven Rostedt    }
1337a75fececSSteven Rostedt
1338a75fececSSteven Rostedt    doprint "SUCCESS\n";
1339a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1340a75fececSSteven Rostedt	doprint "$1 [$2]\n";
1341a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1342a75fececSSteven Rostedt	$bisect_bad = $1;
1343a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
1344a75fececSSteven Rostedt	return 0;
1345a75fececSSteven Rostedt    } else {
1346a75fececSSteven Rostedt	# we already logged it, just print it now.
1347a75fececSSteven Rostedt	print $output;
1348a75fececSSteven Rostedt    }
1349a75fececSSteven Rostedt
1350a75fececSSteven Rostedt    return 1;
1351a75fececSSteven Rostedt}
1352a75fececSSteven Rostedt
1353c23dca7cSSteven Rostedtsub bisect_reboot {
1354c23dca7cSSteven Rostedt    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
1355c23dca7cSSteven Rostedt    reboot;
1356c23dca7cSSteven Rostedt    start_monitor;
1357c23dca7cSSteven Rostedt    wait_for_monitor $bisect_sleep_time;
1358c23dca7cSSteven Rostedt    end_monitor;
1359c23dca7cSSteven Rostedt}
1360c23dca7cSSteven Rostedt
1361c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip
13620a05c769SSteven Rostedtsub run_bisect_test {
13630a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
13645f9b6cedSSteven Rostedt
13652b7d9b21SSteven Rostedt    my $failed = 0;
13665f9b6cedSSteven Rostedt    my $result;
13675f9b6cedSSteven Rostedt    my $output;
13685f9b6cedSSteven Rostedt    my $ret;
13695f9b6cedSSteven Rostedt
13700a05c769SSteven Rostedt    $in_bisect = 1;
13710a05c769SSteven Rostedt
13720a05c769SSteven Rostedt    build $buildtype or $failed = 1;
13735f9b6cedSSteven Rostedt
13745f9b6cedSSteven Rostedt    if ($type ne "build") {
1375c23dca7cSSteven Rostedt	if ($failed && $bisect_skip) {
1376c23dca7cSSteven Rostedt	    $in_bisect = 0;
1377c23dca7cSSteven Rostedt	    return -1;
1378c23dca7cSSteven Rostedt	}
13797faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
13805f9b6cedSSteven Rostedt
13815f9b6cedSSteven Rostedt	# Now boot the box
13825f9b6cedSSteven Rostedt	get_grub_index;
13835f9b6cedSSteven Rostedt	get_version;
13845f9b6cedSSteven Rostedt	install;
13857faafbd6SSteven Rostedt
13867faafbd6SSteven Rostedt	start_monitor;
13872b7d9b21SSteven Rostedt	monitor or $failed = 1;
13885f9b6cedSSteven Rostedt
13895f9b6cedSSteven Rostedt	if ($type ne "boot") {
1390c23dca7cSSteven Rostedt	    if ($failed && $bisect_skip) {
1391c23dca7cSSteven Rostedt		end_monitor;
1392c23dca7cSSteven Rostedt		bisect_reboot;
1393c23dca7cSSteven Rostedt		$in_bisect = 0;
1394c23dca7cSSteven Rostedt		return -1;
1395c23dca7cSSteven Rostedt	    }
13967faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
13975a391fbfSSteven Rostedt
13982b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
13995f9b6cedSSteven Rostedt	}
14007faafbd6SSteven Rostedt	end_monitor;
14015f9b6cedSSteven Rostedt    }
14025f9b6cedSSteven Rostedt
14035f9b6cedSSteven Rostedt    if ($failed) {
14040a05c769SSteven Rostedt	$result = 0;
14055f9b6cedSSteven Rostedt    } else {
14060a05c769SSteven Rostedt	$result = 1;
14075f9b6cedSSteven Rostedt    }
14084025bc62SSteven Rostedt
14094025bc62SSteven Rostedt    # reboot the box to a kernel we can ssh to
14104025bc62SSteven Rostedt    if ($type ne "build") {
14114025bc62SSteven Rostedt	bisect_reboot;
14124025bc62SSteven Rostedt    }
14130a05c769SSteven Rostedt    $in_bisect = 0;
14140a05c769SSteven Rostedt
14150a05c769SSteven Rostedt    return $result;
14160a05c769SSteven Rostedt}
14170a05c769SSteven Rostedt
14180a05c769SSteven Rostedtsub run_bisect {
14190a05c769SSteven Rostedt    my ($type) = @_;
14200a05c769SSteven Rostedt    my $buildtype = "oldconfig";
14210a05c769SSteven Rostedt
14220a05c769SSteven Rostedt    # We should have a minconfig to use?
14230a05c769SSteven Rostedt    if (defined($minconfig)) {
14240a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
14250a05c769SSteven Rostedt    }
14260a05c769SSteven Rostedt
14270a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
14280a05c769SSteven Rostedt
1429c960bb9fSSteven Rostedt    if ($bisect_manual) {
1430c960bb9fSSteven Rostedt	$ret = answer_bisect;
1431c960bb9fSSteven Rostedt    }
14325f9b6cedSSteven Rostedt
1433d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
1434d6ce2a0bSSteven Rostedt    if ($reverse_bisect) {
14350a05c769SSteven Rostedt	$ret = !$ret;
1436d6ce2a0bSSteven Rostedt    }
1437d6ce2a0bSSteven Rostedt
1438c23dca7cSSteven Rostedt    if ($ret > 0) {
14390a05c769SSteven Rostedt	return "good";
1440c23dca7cSSteven Rostedt    } elsif ($ret == 0) {
14410a05c769SSteven Rostedt	return  "bad";
1442c23dca7cSSteven Rostedt    } elsif ($bisect_skip) {
1443c23dca7cSSteven Rostedt	doprint "HIT A BAD COMMIT ... SKIPPING\n";
1444c23dca7cSSteven Rostedt	return "skip";
14450a05c769SSteven Rostedt    }
14465f9b6cedSSteven Rostedt}
14475f9b6cedSSteven Rostedt
14485f9b6cedSSteven Rostedtsub bisect {
14495f9b6cedSSteven Rostedt    my ($i) = @_;
14505f9b6cedSSteven Rostedt
14515f9b6cedSSteven Rostedt    my $result;
14525f9b6cedSSteven Rostedt
14535f9b6cedSSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($opt{"BISECT_GOOD[$i]"}));
14545f9b6cedSSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($opt{"BISECT_BAD[$i]"}));
14555f9b6cedSSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($opt{"BISECT_TYPE[$i]"}));
14565f9b6cedSSteven Rostedt
14575f9b6cedSSteven Rostedt    my $good = $opt{"BISECT_GOOD[$i]"};
14585f9b6cedSSteven Rostedt    my $bad = $opt{"BISECT_BAD[$i]"};
14595f9b6cedSSteven Rostedt    my $type = $opt{"BISECT_TYPE[$i]"};
1460a75fececSSteven Rostedt    my $start = $opt{"BISECT_START[$i]"};
1461a75fececSSteven Rostedt    my $replay = $opt{"BISECT_REPLAY[$i]"};
14623410f6fdSSteven Rostedt    my $start_files = $opt{"BISECT_FILES[$i]"};
14633410f6fdSSteven Rostedt
14643410f6fdSSteven Rostedt    if (defined($start_files)) {
14653410f6fdSSteven Rostedt	$start_files = " -- " . $start_files;
14663410f6fdSSteven Rostedt    } else {
14673410f6fdSSteven Rostedt	$start_files = "";
14683410f6fdSSteven Rostedt    }
14695f9b6cedSSteven Rostedt
1470a57419b3SSteven Rostedt    # convert to true sha1's
1471a57419b3SSteven Rostedt    $good = get_sha1($good);
1472a57419b3SSteven Rostedt    $bad = get_sha1($bad);
1473a57419b3SSteven Rostedt
1474d6ce2a0bSSteven Rostedt    if (defined($opt{"BISECT_REVERSE[$i]"}) &&
1475d6ce2a0bSSteven Rostedt	$opt{"BISECT_REVERSE[$i]"} == 1) {
1476d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1477d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
1478d6ce2a0bSSteven Rostedt    } else {
1479d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
1480d6ce2a0bSSteven Rostedt    }
1481d6ce2a0bSSteven Rostedt
14825a391fbfSSteven Rostedt    # Can't have a test without having a test to run
14835a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
14845a391fbfSSteven Rostedt	$type = "boot";
14855a391fbfSSteven Rostedt    }
14865a391fbfSSteven Rostedt
1487a75fececSSteven Rostedt    my $check = $opt{"BISECT_CHECK[$i]"};
1488a75fececSSteven Rostedt    if (defined($check) && $check ne "0") {
1489a75fececSSteven Rostedt
1490a75fececSSteven Rostedt	# get current HEAD
1491a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
1492a75fececSSteven Rostedt
1493a75fececSSteven Rostedt	if ($check ne "good") {
1494a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
1495a75fececSSteven Rostedt	    run_command "git checkout $bad" or
1496a75fececSSteven Rostedt		die "Failed to checkout $bad";
1497a75fececSSteven Rostedt
1498a75fececSSteven Rostedt	    $result = run_bisect $type;
1499a75fececSSteven Rostedt
1500a75fececSSteven Rostedt	    if ($result ne "bad") {
1501a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
1502a75fececSSteven Rostedt	    }
1503a75fececSSteven Rostedt	}
1504a75fececSSteven Rostedt
1505a75fececSSteven Rostedt	if ($check ne "bad") {
1506a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
1507a75fececSSteven Rostedt	    run_command "git checkout $good" or
1508a75fececSSteven Rostedt		die "Failed to checkout $good";
1509a75fececSSteven Rostedt
1510a75fececSSteven Rostedt	    $result = run_bisect $type;
1511a75fececSSteven Rostedt
1512a75fececSSteven Rostedt	    if ($result ne "good") {
1513a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
1514a75fececSSteven Rostedt	    }
1515a75fececSSteven Rostedt	}
1516a75fececSSteven Rostedt
1517a75fececSSteven Rostedt	# checkout where we started
1518a75fececSSteven Rostedt	run_command "git checkout $head" or
1519a75fececSSteven Rostedt	    die "Failed to checkout $head";
1520a75fececSSteven Rostedt    }
1521a75fececSSteven Rostedt
15223410f6fdSSteven Rostedt    run_command "git bisect start$start_files" or
1523a75fececSSteven Rostedt	dodie "could not start bisect";
1524a75fececSSteven Rostedt
1525a75fececSSteven Rostedt    run_command "git bisect good $good" or
1526a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
1527a75fececSSteven Rostedt
1528a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
1529a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
1530a75fececSSteven Rostedt
1531a75fececSSteven Rostedt    if (defined($replay)) {
1532a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
1533a75fececSSteven Rostedt	    dodie "failed to run replay";
1534a75fececSSteven Rostedt    }
1535a75fececSSteven Rostedt
1536a75fececSSteven Rostedt    if (defined($start)) {
1537a75fececSSteven Rostedt	run_command "git checkout $start" or
1538a75fececSSteven Rostedt	    dodie "failed to checkout $start";
1539a75fececSSteven Rostedt    }
1540a75fececSSteven Rostedt
1541a75fececSSteven Rostedt    my $test;
15425f9b6cedSSteven Rostedt    do {
15435f9b6cedSSteven Rostedt	$result = run_bisect $type;
1544a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
1545a75fececSSteven Rostedt    } while ($test);
15465f9b6cedSSteven Rostedt
15475f9b6cedSSteven Rostedt    run_command "git bisect log" or
15485f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
15495f9b6cedSSteven Rostedt
15505f9b6cedSSteven Rostedt    run_command "git bisect reset" or
15515f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
15525f9b6cedSSteven Rostedt
15535f9b6cedSSteven Rostedt    doprint "Bad commit was [$bisect_bad]\n";
15545f9b6cedSSteven Rostedt
15550a05c769SSteven Rostedt    success $i;
15560a05c769SSteven Rostedt}
15570a05c769SSteven Rostedt
15580a05c769SSteven Rostedtmy %config_ignore;
15590a05c769SSteven Rostedtmy %config_set;
15600a05c769SSteven Rostedt
15610a05c769SSteven Rostedtmy %config_list;
15620a05c769SSteven Rostedtmy %null_config;
15630a05c769SSteven Rostedt
15640a05c769SSteven Rostedtmy %dependency;
15650a05c769SSteven Rostedt
15660a05c769SSteven Rostedtsub process_config_ignore {
15670a05c769SSteven Rostedt    my ($config) = @_;
15680a05c769SSteven Rostedt
15690a05c769SSteven Rostedt    open (IN, $config)
15700a05c769SSteven Rostedt	or dodie "Failed to read $config";
15710a05c769SSteven Rostedt
15720a05c769SSteven Rostedt    while (<IN>) {
15739bf71749SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
15740a05c769SSteven Rostedt	    $config_ignore{$2} = $1;
15750a05c769SSteven Rostedt	}
15760a05c769SSteven Rostedt    }
15770a05c769SSteven Rostedt
15780a05c769SSteven Rostedt    close(IN);
15790a05c769SSteven Rostedt}
15800a05c769SSteven Rostedt
15810a05c769SSteven Rostedtsub read_current_config {
15820a05c769SSteven Rostedt    my ($config_ref) = @_;
15830a05c769SSteven Rostedt
15840a05c769SSteven Rostedt    %{$config_ref} = ();
15850a05c769SSteven Rostedt    undef %{$config_ref};
15860a05c769SSteven Rostedt
15870a05c769SSteven Rostedt    my @key = keys %{$config_ref};
15880a05c769SSteven Rostedt    if ($#key >= 0) {
15890a05c769SSteven Rostedt	print "did not delete!\n";
15900a05c769SSteven Rostedt	exit;
15910a05c769SSteven Rostedt    }
15920a05c769SSteven Rostedt    open (IN, "$output_config");
15930a05c769SSteven Rostedt
15940a05c769SSteven Rostedt    while (<IN>) {
15950a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
15960a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
15970a05c769SSteven Rostedt	}
15980a05c769SSteven Rostedt    }
15990a05c769SSteven Rostedt    close(IN);
16000a05c769SSteven Rostedt}
16010a05c769SSteven Rostedt
16020a05c769SSteven Rostedtsub get_dependencies {
16030a05c769SSteven Rostedt    my ($config) = @_;
16040a05c769SSteven Rostedt
16050a05c769SSteven Rostedt    my $arr = $dependency{$config};
16060a05c769SSteven Rostedt    if (!defined($arr)) {
16070a05c769SSteven Rostedt	return ();
16080a05c769SSteven Rostedt    }
16090a05c769SSteven Rostedt
16100a05c769SSteven Rostedt    my @deps = @{$arr};
16110a05c769SSteven Rostedt
16120a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
16130a05c769SSteven Rostedt	print "ADD DEP $dep\n";
16140a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
16150a05c769SSteven Rostedt    }
16160a05c769SSteven Rostedt
16170a05c769SSteven Rostedt    return @deps;
16180a05c769SSteven Rostedt}
16190a05c769SSteven Rostedt
16200a05c769SSteven Rostedtsub create_config {
16210a05c769SSteven Rostedt    my @configs = @_;
16220a05c769SSteven Rostedt
16230a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
16240a05c769SSteven Rostedt
16250a05c769SSteven Rostedt    foreach my $config (@configs) {
16260a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
16270a05c769SSteven Rostedt	my @deps = get_dependencies $config;
16280a05c769SSteven Rostedt	foreach my $dep (@deps) {
16290a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
16300a05c769SSteven Rostedt	}
16310a05c769SSteven Rostedt    }
16320a05c769SSteven Rostedt
16330a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
16340a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
16350a05c769SSteven Rostedt    }
16360a05c769SSteven Rostedt    close(OUT);
16370a05c769SSteven Rostedt
16380a05c769SSteven Rostedt#    exit;
1639*fcb3f16aSSteven Rostedt    make_oldconfig;
16400a05c769SSteven Rostedt}
16410a05c769SSteven Rostedt
16420a05c769SSteven Rostedtsub compare_configs {
16430a05c769SSteven Rostedt    my (%a, %b) = @_;
16440a05c769SSteven Rostedt
16450a05c769SSteven Rostedt    foreach my $item (keys %a) {
16460a05c769SSteven Rostedt	if (!defined($b{$item})) {
16470a05c769SSteven Rostedt	    print "diff $item\n";
16480a05c769SSteven Rostedt	    return 1;
16490a05c769SSteven Rostedt	}
16500a05c769SSteven Rostedt	delete $b{$item};
16510a05c769SSteven Rostedt    }
16520a05c769SSteven Rostedt
16530a05c769SSteven Rostedt    my @keys = keys %b;
16540a05c769SSteven Rostedt    if ($#keys) {
16550a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
16560a05c769SSteven Rostedt    }
16570a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
16580a05c769SSteven Rostedt
16590a05c769SSteven Rostedt    return 0;
16600a05c769SSteven Rostedt}
16610a05c769SSteven Rostedt
16620a05c769SSteven Rostedtsub run_config_bisect_test {
16630a05c769SSteven Rostedt    my ($type) = @_;
16640a05c769SSteven Rostedt
16650a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
16660a05c769SSteven Rostedt}
16670a05c769SSteven Rostedt
16680a05c769SSteven Rostedtsub process_passed {
16690a05c769SSteven Rostedt    my (%configs) = @_;
16700a05c769SSteven Rostedt
16710a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
16720a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
16730a05c769SSteven Rostedt    # Add them to the min options.
16740a05c769SSteven Rostedt    foreach my $config (keys %configs) {
16750a05c769SSteven Rostedt	if (defined($config_list{$config})) {
16760a05c769SSteven Rostedt	    doprint " removing $config\n";
16770a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
16780a05c769SSteven Rostedt	    delete $config_list{$config};
16790a05c769SSteven Rostedt	}
16800a05c769SSteven Rostedt    }
1681f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
1682f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
16830a05c769SSteven Rostedt}
16840a05c769SSteven Rostedt
16850a05c769SSteven Rostedtsub process_failed {
16860a05c769SSteven Rostedt    my ($config) = @_;
16870a05c769SSteven Rostedt
16880a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
16890a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
16900a05c769SSteven Rostedt    doprint "***************************************\n\n";
16910a05c769SSteven Rostedt}
16920a05c769SSteven Rostedt
16930a05c769SSteven Rostedtsub run_config_bisect {
16940a05c769SSteven Rostedt
16950a05c769SSteven Rostedt    my @start_list = keys %config_list;
16960a05c769SSteven Rostedt
16970a05c769SSteven Rostedt    if ($#start_list < 0) {
16980a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
16990a05c769SSteven Rostedt	return -1;
17000a05c769SSteven Rostedt    }
17010a05c769SSteven Rostedt
17020a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
17030a05c769SSteven Rostedt    my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
17040a05c769SSteven Rostedt    my $ret;
17050a05c769SSteven Rostedt    my %current_config;
17060a05c769SSteven Rostedt
17070a05c769SSteven Rostedt    my $count = $#start_list + 1;
17080a05c769SSteven Rostedt    doprint "  $count configs to test\n";
17090a05c769SSteven Rostedt
17100a05c769SSteven Rostedt    my $half = int($#start_list / 2);
17110a05c769SSteven Rostedt
17120a05c769SSteven Rostedt    do {
17130a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
17140a05c769SSteven Rostedt
17150a05c769SSteven Rostedt	create_config @tophalf;
17160a05c769SSteven Rostedt	read_current_config \%current_config;
17170a05c769SSteven Rostedt
17180a05c769SSteven Rostedt	$count = $#tophalf + 1;
17190a05c769SSteven Rostedt	doprint "Testing $count configs\n";
17200a05c769SSteven Rostedt	my $found = 0;
17210a05c769SSteven Rostedt	# make sure we test something
17220a05c769SSteven Rostedt	foreach my $config (@tophalf) {
17230a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
17240a05c769SSteven Rostedt		logit " $config\n";
17250a05c769SSteven Rostedt		$found = 1;
17260a05c769SSteven Rostedt	    }
17270a05c769SSteven Rostedt	}
17280a05c769SSteven Rostedt	if (!$found) {
17290a05c769SSteven Rostedt	    # try the other half
17300a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
17314c8cc55bSSteven Rostedt	    @tophalf = @start_list[$half + 1 .. $#start_list];
17320a05c769SSteven Rostedt	    create_config @tophalf;
17330a05c769SSteven Rostedt	    read_current_config \%current_config;
17340a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
17350a05c769SSteven Rostedt		if (defined($current_config{$config})) {
17360a05c769SSteven Rostedt		    logit " $config\n";
17370a05c769SSteven Rostedt		    $found = 1;
17380a05c769SSteven Rostedt		}
17390a05c769SSteven Rostedt	    }
17400a05c769SSteven Rostedt	    if (!$found) {
17410a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
17420a05c769SSteven Rostedt		foreach my $config (@start_list) {
17430a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
17440a05c769SSteven Rostedt		}
17450a05c769SSteven Rostedt		return -1;
17460a05c769SSteven Rostedt	    }
17470a05c769SSteven Rostedt	    $count = $#tophalf + 1;
17480a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
17490a05c769SSteven Rostedt	}
17500a05c769SSteven Rostedt
17510a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
1752c960bb9fSSteven Rostedt	if ($bisect_manual) {
1753c960bb9fSSteven Rostedt	    $ret = answer_bisect;
1754c960bb9fSSteven Rostedt	}
17550a05c769SSteven Rostedt	if ($ret) {
17560a05c769SSteven Rostedt	    process_passed %current_config;
17570a05c769SSteven Rostedt	    return 0;
17580a05c769SSteven Rostedt	}
17590a05c769SSteven Rostedt
17600a05c769SSteven Rostedt	doprint "This config had a failure.\n";
17610a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
1762f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
1763f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
17640a05c769SSteven Rostedt
17650a05c769SSteven Rostedt	# A config exists in this group that was bad.
17660a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
17670a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
17680a05c769SSteven Rostedt		doprint " removing $config\n";
17690a05c769SSteven Rostedt		delete $config_list{$config};
17700a05c769SSteven Rostedt	    }
17710a05c769SSteven Rostedt	}
17720a05c769SSteven Rostedt
17730a05c769SSteven Rostedt	@start_list = @tophalf;
17740a05c769SSteven Rostedt
17750a05c769SSteven Rostedt	if ($#start_list == 0) {
17760a05c769SSteven Rostedt	    process_failed $start_list[0];
17770a05c769SSteven Rostedt	    return 1;
17780a05c769SSteven Rostedt	}
17790a05c769SSteven Rostedt
17800a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
17810a05c769SSteven Rostedt	# they are good.
17820a05c769SSteven Rostedt	$half = int($#start_list / 2);
17834c8cc55bSSteven Rostedt    } while ($#start_list > 0);
17840a05c769SSteven Rostedt
1785c960bb9fSSteven Rostedt    # we found a single config, try it again unless we are running manually
1786c960bb9fSSteven Rostedt
1787c960bb9fSSteven Rostedt    if ($bisect_manual) {
1788c960bb9fSSteven Rostedt	process_failed $start_list[0];
1789c960bb9fSSteven Rostedt	return 1;
1790c960bb9fSSteven Rostedt    }
1791c960bb9fSSteven Rostedt
17920a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
17930a05c769SSteven Rostedt
17940a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
17950a05c769SSteven Rostedt    if ($ret) {
17960a05c769SSteven Rostedt	process_passed %current_config;
17970a05c769SSteven Rostedt	return 0;
17980a05c769SSteven Rostedt    }
17990a05c769SSteven Rostedt
18000a05c769SSteven Rostedt    process_failed $start_list[0];
18010a05c769SSteven Rostedt    return 1;
18020a05c769SSteven Rostedt}
18030a05c769SSteven Rostedt
18040a05c769SSteven Rostedtsub config_bisect {
18050a05c769SSteven Rostedt    my ($i) = @_;
18060a05c769SSteven Rostedt
18070a05c769SSteven Rostedt    my $start_config = $opt{"CONFIG_BISECT[$i]"};
18080a05c769SSteven Rostedt
18090a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
18100a05c769SSteven Rostedt
181130f75da5SSteven Rostedt    if (defined($config_bisect_good)) {
181230f75da5SSteven Rostedt	process_config_ignore $config_bisect_good;
181330f75da5SSteven Rostedt    }
181430f75da5SSteven Rostedt
18150a05c769SSteven Rostedt    # Make the file with the bad config and the min config
18160a05c769SSteven Rostedt    if (defined($minconfig)) {
18170a05c769SSteven Rostedt	# read the min config for things to ignore
18180a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
18190a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
18200a05c769SSteven Rostedt    } else {
18210a05c769SSteven Rostedt	unlink $tmpconfig;
18220a05c769SSteven Rostedt    }
18230a05c769SSteven Rostedt
18240a05c769SSteven Rostedt    # Add other configs
18250a05c769SSteven Rostedt    if (defined($addconfig)) {
18260a05c769SSteven Rostedt	run_command "cat $addconfig >> $tmpconfig" or
18270a05c769SSteven Rostedt	    dodie "failed to append $addconfig";
18280a05c769SSteven Rostedt    }
18290a05c769SSteven Rostedt
18300a05c769SSteven Rostedt    if (-f $tmpconfig) {
1831*fcb3f16aSSteven Rostedt	load_force_config($tmpconfig);
18320a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
18330a05c769SSteven Rostedt    }
18340a05c769SSteven Rostedt
18350a05c769SSteven Rostedt    # now process the start config
18360a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
18370a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
18380a05c769SSteven Rostedt
18390a05c769SSteven Rostedt    # read directly what we want to check
18400a05c769SSteven Rostedt    my %config_check;
18410a05c769SSteven Rostedt    open (IN, $output_config)
18420a05c769SSteven Rostedt	or dodie "faied to open $output_config";
18430a05c769SSteven Rostedt
18440a05c769SSteven Rostedt    while (<IN>) {
18450a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
18460a05c769SSteven Rostedt	    $config_check{$2} = $1;
18470a05c769SSteven Rostedt	}
18480a05c769SSteven Rostedt    }
18490a05c769SSteven Rostedt    close(IN);
18500a05c769SSteven Rostedt
18510a05c769SSteven Rostedt    # Now run oldconfig with the minconfig (and addconfigs)
1852*fcb3f16aSSteven Rostedt    make_oldconfig;
18530a05c769SSteven Rostedt
18540a05c769SSteven Rostedt    # check to see what we lost (or gained)
18550a05c769SSteven Rostedt    open (IN, $output_config)
18560a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
18570a05c769SSteven Rostedt
18580a05c769SSteven Rostedt    my %removed_configs;
18590a05c769SSteven Rostedt    my %added_configs;
18600a05c769SSteven Rostedt
18610a05c769SSteven Rostedt    while (<IN>) {
18620a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
18630a05c769SSteven Rostedt	    # save off all options
18640a05c769SSteven Rostedt	    $config_set{$2} = $1;
18650a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
18660a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
18670a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
18680a05c769SSteven Rostedt		} else {
18690a05c769SSteven Rostedt		    $config_list{$2} = $1;
18700a05c769SSteven Rostedt		}
18710a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
18720a05c769SSteven Rostedt		$added_configs{$2} = $1;
18730a05c769SSteven Rostedt		$config_list{$2} = $1;
18740a05c769SSteven Rostedt	    }
18750a05c769SSteven Rostedt	}
18760a05c769SSteven Rostedt    }
18770a05c769SSteven Rostedt    close(IN);
18780a05c769SSteven Rostedt
18790a05c769SSteven Rostedt    my @confs = keys %removed_configs;
18800a05c769SSteven Rostedt    if ($#confs >= 0) {
18810a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
18820a05c769SSteven Rostedt	foreach my $config (@confs) {
18830a05c769SSteven Rostedt	    doprint " $config\n";
18840a05c769SSteven Rostedt	}
18850a05c769SSteven Rostedt    }
18860a05c769SSteven Rostedt    @confs = keys %added_configs;
18870a05c769SSteven Rostedt    if ($#confs >= 0) {
18880a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
18890a05c769SSteven Rostedt	foreach my $config (@confs) {
18900a05c769SSteven Rostedt	    doprint " $config\n";
18910a05c769SSteven Rostedt	}
18920a05c769SSteven Rostedt    }
18930a05c769SSteven Rostedt
18940a05c769SSteven Rostedt    my %config_test;
18950a05c769SSteven Rostedt    my $once = 0;
18960a05c769SSteven Rostedt
18970a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
18980a05c769SSteven Rostedt    # that the config we autocreate has everything we need
18990a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
19000a05c769SSteven Rostedt    # may not be able to create a new config.
19010a05c769SSteven Rostedt    # Here we create a config with everything set.
19020a05c769SSteven Rostedt    create_config (keys %config_list);
19030a05c769SSteven Rostedt    read_current_config \%config_test;
19040a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
19050a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
19060a05c769SSteven Rostedt	    if (!$once) {
19070a05c769SSteven Rostedt		$once = 1;
19080a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
19090a05c769SSteven Rostedt	    }
19100a05c769SSteven Rostedt	    doprint "  $config\n";
19110a05c769SSteven Rostedt	    delete $config_list{$config};
19120a05c769SSteven Rostedt	}
19130a05c769SSteven Rostedt    }
19140a05c769SSteven Rostedt    my $ret;
19150a05c769SSteven Rostedt    do {
19160a05c769SSteven Rostedt	$ret = run_config_bisect;
19170a05c769SSteven Rostedt    } while (!$ret);
19180a05c769SSteven Rostedt
19190a05c769SSteven Rostedt    return $ret if ($ret < 0);
19205f9b6cedSSteven Rostedt
19215f9b6cedSSteven Rostedt    success $i;
19225f9b6cedSSteven Rostedt}
19235f9b6cedSSteven Rostedt
192427d934b2SSteven Rostedtsub patchcheck_reboot {
192527d934b2SSteven Rostedt    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
192627d934b2SSteven Rostedt    reboot;
192727d934b2SSteven Rostedt    start_monitor;
192827d934b2SSteven Rostedt    wait_for_monitor $patchcheck_sleep_time;
192927d934b2SSteven Rostedt    end_monitor;
193027d934b2SSteven Rostedt}
193127d934b2SSteven Rostedt
19326c5ee0beSSteven Rostedtsub patchcheck {
19336c5ee0beSSteven Rostedt    my ($i) = @_;
19346c5ee0beSSteven Rostedt
19356c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
19366c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_START[$i]"}));
19376c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
19386c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
19396c5ee0beSSteven Rostedt
19406c5ee0beSSteven Rostedt    my $start = $opt{"PATCHCHECK_START[$i]"};
19416c5ee0beSSteven Rostedt
19426c5ee0beSSteven Rostedt    my $end = "HEAD";
19436c5ee0beSSteven Rostedt    if (defined($opt{"PATCHCHECK_END[$i]"})) {
19446c5ee0beSSteven Rostedt	$end = $opt{"PATCHCHECK_END[$i]"};
19456c5ee0beSSteven Rostedt    }
19466c5ee0beSSteven Rostedt
1947a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
1948a57419b3SSteven Rostedt    $start = get_sha1($start);
1949a57419b3SSteven Rostedt    $end = get_sha1($end);
1950a57419b3SSteven Rostedt
19516c5ee0beSSteven Rostedt    my $type = $opt{"PATCHCHECK_TYPE[$i]"};
19526c5ee0beSSteven Rostedt
19536c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
19546c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
19556c5ee0beSSteven Rostedt	$type = "boot";
19566c5ee0beSSteven Rostedt    }
19576c5ee0beSSteven Rostedt
19586c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
19596c5ee0beSSteven Rostedt	dodie "could not get git list";
19606c5ee0beSSteven Rostedt
19616c5ee0beSSteven Rostedt    my @list;
19626c5ee0beSSteven Rostedt
19636c5ee0beSSteven Rostedt    while (<IN>) {
19646c5ee0beSSteven Rostedt	chomp;
19656c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
19666c5ee0beSSteven Rostedt	last if (/^$start/);
19676c5ee0beSSteven Rostedt    }
19686c5ee0beSSteven Rostedt    close(IN);
19696c5ee0beSSteven Rostedt
19706c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
19712b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
19726c5ee0beSSteven Rostedt    }
19736c5ee0beSSteven Rostedt
19746c5ee0beSSteven Rostedt    # go backwards in the list
19756c5ee0beSSteven Rostedt    @list = reverse @list;
19766c5ee0beSSteven Rostedt
19776c5ee0beSSteven Rostedt    my $save_clean = $noclean;
19786c5ee0beSSteven Rostedt
19796c5ee0beSSteven Rostedt    $in_patchcheck = 1;
19806c5ee0beSSteven Rostedt    foreach my $item (@list) {
19816c5ee0beSSteven Rostedt	my $sha1 = $item;
19826c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
19836c5ee0beSSteven Rostedt
19846c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
19856c5ee0beSSteven Rostedt
19866c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
19876c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
19886c5ee0beSSteven Rostedt
19896c5ee0beSSteven Rostedt	# only clean on the first and last patch
19906c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
19916c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
19926c5ee0beSSteven Rostedt	    $noclean = $save_clean;
19936c5ee0beSSteven Rostedt	} else {
19946c5ee0beSSteven Rostedt	    $noclean = 1;
19956c5ee0beSSteven Rostedt	}
19966c5ee0beSSteven Rostedt
19976c5ee0beSSteven Rostedt	if (defined($minconfig)) {
19982b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
19996c5ee0beSSteven Rostedt	} else {
20006c5ee0beSSteven Rostedt	    # ?? no config to use?
20012b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
20026c5ee0beSSteven Rostedt	}
20036c5ee0beSSteven Rostedt
20042b7d9b21SSteven Rostedt	check_buildlog $sha1 or return 0;
20056c5ee0beSSteven Rostedt
20066c5ee0beSSteven Rostedt	next if ($type eq "build");
20076c5ee0beSSteven Rostedt
20086c5ee0beSSteven Rostedt	get_grub_index;
20096c5ee0beSSteven Rostedt	get_version;
20106c5ee0beSSteven Rostedt	install;
20116c5ee0beSSteven Rostedt
20127faafbd6SSteven Rostedt	my $failed = 0;
20137faafbd6SSteven Rostedt
20147faafbd6SSteven Rostedt	start_monitor;
20157faafbd6SSteven Rostedt	monitor or $failed = 1;
20167faafbd6SSteven Rostedt
20177faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
20187faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
20197faafbd6SSteven Rostedt	}
20207faafbd6SSteven Rostedt	end_monitor;
20217faafbd6SSteven Rostedt	return 0 if ($failed);
20227faafbd6SSteven Rostedt
202327d934b2SSteven Rostedt	patchcheck_reboot;
202427d934b2SSteven Rostedt
20256c5ee0beSSteven Rostedt    }
20266c5ee0beSSteven Rostedt    $in_patchcheck = 0;
20276c5ee0beSSteven Rostedt    success $i;
20282b7d9b21SSteven Rostedt
20292b7d9b21SSteven Rostedt    return 1;
20306c5ee0beSSteven Rostedt}
20316c5ee0beSSteven Rostedt
20328d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
20332545eb61SSteven Rostedt
20348d1491baSSteven Rostedtif ($#ARGV == 0) {
20358d1491baSSteven Rostedt    $ktest_config = $ARGV[0];
20368d1491baSSteven Rostedt    if (! -f $ktest_config) {
20378d1491baSSteven Rostedt	print "$ktest_config does not exist.\n";
20388d1491baSSteven Rostedt	my $ans;
20398d1491baSSteven Rostedt        for (;;) {
20408d1491baSSteven Rostedt	    print "Create it? [Y/n] ";
20418d1491baSSteven Rostedt	    $ans = <STDIN>;
20428d1491baSSteven Rostedt	    chomp $ans;
20438d1491baSSteven Rostedt	    if ($ans =~ /^\s*$/) {
20448d1491baSSteven Rostedt		$ans = "y";
20458d1491baSSteven Rostedt	    }
20468d1491baSSteven Rostedt	    last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
20478d1491baSSteven Rostedt	    print "Please answer either 'y' or 'n'.\n";
20488d1491baSSteven Rostedt	}
20498d1491baSSteven Rostedt	if ($ans !~ /^y$/i) {
20508d1491baSSteven Rostedt	    exit 0;
20518d1491baSSteven Rostedt	}
20528d1491baSSteven Rostedt    }
20538d1491baSSteven Rostedt} else {
20548d1491baSSteven Rostedt    $ktest_config = "ktest.conf";
20558d1491baSSteven Rostedt}
20568d1491baSSteven Rostedt
20578d1491baSSteven Rostedtif (! -f $ktest_config) {
20588d1491baSSteven Rostedt    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
20598d1491baSSteven Rostedt    print OUT << "EOF"
20608d1491baSSteven Rostedt# Generated by ktest.pl
20618d1491baSSteven Rostedt#
20628d1491baSSteven Rostedt# Define each test with TEST_START
20638d1491baSSteven Rostedt# The config options below it will override the defaults
20648d1491baSSteven RostedtTEST_START
20658d1491baSSteven Rostedt
20668d1491baSSteven RostedtDEFAULTS
20678d1491baSSteven RostedtEOF
20688d1491baSSteven Rostedt;
20698d1491baSSteven Rostedt    close(OUT);
20708d1491baSSteven Rostedt}
20718d1491baSSteven Rostedtread_config $ktest_config;
20728d1491baSSteven Rostedt
20738d1491baSSteven Rostedt# Append any configs entered in manually to the config file.
20748d1491baSSteven Rostedtmy @new_configs = keys %entered_configs;
20758d1491baSSteven Rostedtif ($#new_configs >= 0) {
20768d1491baSSteven Rostedt    print "\nAppending entered in configs to $ktest_config\n";
20778d1491baSSteven Rostedt    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
20788d1491baSSteven Rostedt    foreach my $config (@new_configs) {
20798d1491baSSteven Rostedt	print OUT "$config = $entered_configs{$config}\n";
20808d1491baSSteven Rostedt	$opt{$config} = $entered_configs{$config};
20818d1491baSSteven Rostedt    }
20828d1491baSSteven Rostedt}
20832545eb61SSteven Rostedt
20842b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
20852b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
20862b7d9b21SSteven Rostedt}
20872545eb61SSteven Rostedt
20882b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
20892b7d9b21SSteven Rostedt
2090a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
2091a57419b3SSteven Rostedt
2092a57419b3SSteven Rostedt    if (!$i) {
2093a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
2094a57419b3SSteven Rostedt    } else {
2095a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
2096a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
2097a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
2098a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
2099a57419b3SSteven Rostedt	}
2100a57419b3SSteven Rostedt	doprint "\n";
2101a57419b3SSteven Rostedt    }
2102a57419b3SSteven Rostedt
21032b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
2104a57419b3SSteven Rostedt
2105a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
2106a57419b3SSteven Rostedt	    next if ($i != $1);
2107a57419b3SSteven Rostedt	} else {
2108a57419b3SSteven Rostedt	    next if ($i);
2109a57419b3SSteven Rostedt	}
2110a57419b3SSteven Rostedt
21112b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
21122b7d9b21SSteven Rostedt    }
2113a57419b3SSteven Rostedt}
21142545eb61SSteven Rostedt
21152a62512bSSteven Rostedtsub __set_test_option {
21165a391fbfSSteven Rostedt    my ($name, $i) = @_;
21175a391fbfSSteven Rostedt
21185a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
21195a391fbfSSteven Rostedt
21205a391fbfSSteven Rostedt    if (defined($opt{$option})) {
21215a391fbfSSteven Rostedt	return $opt{$option};
21225a391fbfSSteven Rostedt    }
21235a391fbfSSteven Rostedt
2124a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
2125a57419b3SSteven Rostedt	if ($i >= $test &&
2126a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
2127a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
2128a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
2129a57419b3SSteven Rostedt		return $opt{$option};
2130a57419b3SSteven Rostedt	    }
2131a57419b3SSteven Rostedt	}
2132a57419b3SSteven Rostedt    }
2133a57419b3SSteven Rostedt
21345a391fbfSSteven Rostedt    if (defined($opt{$name})) {
21355a391fbfSSteven Rostedt	return $opt{$name};
21365a391fbfSSteven Rostedt    }
21375a391fbfSSteven Rostedt
21385a391fbfSSteven Rostedt    return undef;
21395a391fbfSSteven Rostedt}
21405a391fbfSSteven Rostedt
21412a62512bSSteven Rostedtsub eval_option {
21422a62512bSSteven Rostedt    my ($option, $i) = @_;
21432a62512bSSteven Rostedt
21442a62512bSSteven Rostedt    # Add space to evaluate the character before $
21452a62512bSSteven Rostedt    $option = " $option";
21462a62512bSSteven Rostedt    my $retval = "";
21472a62512bSSteven Rostedt
21482a62512bSSteven Rostedt    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
21492a62512bSSteven Rostedt	my $start = $1;
21502a62512bSSteven Rostedt	my $var = $2;
21512a62512bSSteven Rostedt	my $end = $3;
21522a62512bSSteven Rostedt
21532a62512bSSteven Rostedt	# Append beginning of line
21542a62512bSSteven Rostedt	$retval = "$retval$start";
21552a62512bSSteven Rostedt
21562a62512bSSteven Rostedt	# If the iteration option OPT[$i] exists, then use that.
21572a62512bSSteven Rostedt	# otherwise see if the default OPT (without [$i]) exists.
21582a62512bSSteven Rostedt
21592a62512bSSteven Rostedt	my $o = "$var\[$i\]";
21602a62512bSSteven Rostedt
21612a62512bSSteven Rostedt	if (defined($opt{$o})) {
21622a62512bSSteven Rostedt	    $o = $opt{$o};
21632a62512bSSteven Rostedt	    $retval = "$retval$o";
21642a62512bSSteven Rostedt	} elsif (defined($opt{$var})) {
21652a62512bSSteven Rostedt	    $o = $opt{$var};
21662a62512bSSteven Rostedt	    $retval = "$retval$o";
21672a62512bSSteven Rostedt	} else {
21682a62512bSSteven Rostedt	    $retval = "$retval\$\{$var\}";
21692a62512bSSteven Rostedt	}
21702a62512bSSteven Rostedt
21712a62512bSSteven Rostedt	$option = $end;
21722a62512bSSteven Rostedt    }
21732a62512bSSteven Rostedt
21742a62512bSSteven Rostedt    $retval = "$retval$option";
21752a62512bSSteven Rostedt
21762a62512bSSteven Rostedt    $retval =~ s/^ //;
21772a62512bSSteven Rostedt
21782a62512bSSteven Rostedt    return $retval;
21792a62512bSSteven Rostedt}
21802a62512bSSteven Rostedt
21812a62512bSSteven Rostedtsub set_test_option {
21822a62512bSSteven Rostedt    my ($name, $i) = @_;
21832a62512bSSteven Rostedt
21842a62512bSSteven Rostedt    my $option = __set_test_option($name, $i);
21852a62512bSSteven Rostedt    return $option if (!defined($option));
21862a62512bSSteven Rostedt
21872a62512bSSteven Rostedt    my $prev = "";
21882a62512bSSteven Rostedt
21892a62512bSSteven Rostedt    # Since an option can evaluate to another option,
21902a62512bSSteven Rostedt    # keep iterating until we do not evaluate any more
21912a62512bSSteven Rostedt    # options.
21922a62512bSSteven Rostedt    my $r = 0;
21932a62512bSSteven Rostedt    while ($prev ne $option) {
21942a62512bSSteven Rostedt	# Check for recursive evaluations.
21952a62512bSSteven Rostedt	# 100 deep should be more than enough.
21962a62512bSSteven Rostedt	if ($r++ > 100) {
21972a62512bSSteven Rostedt	    die "Over 100 evaluations accurred with $name\n" .
21982a62512bSSteven Rostedt		"Check for recursive variables\n";
21992a62512bSSteven Rostedt	}
22002a62512bSSteven Rostedt	$prev = $option;
22012a62512bSSteven Rostedt	$option = eval_option($option, $i);
22022a62512bSSteven Rostedt    }
22032a62512bSSteven Rostedt
22042a62512bSSteven Rostedt    return $option;
22052a62512bSSteven Rostedt}
22062a62512bSSteven Rostedt
22072545eb61SSteven Rostedt# First we need to do is the builds
2208a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
22092545eb61SSteven Rostedt
2210576f627cSSteven Rostedt    $iteration = $i;
2211576f627cSSteven Rostedt
2212a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
2213a75fececSSteven Rostedt
2214a75fececSSteven Rostedt    $machine = set_test_option("MACHINE", $i);
2215e48c5293SSteven Rostedt    $ssh_user = set_test_option("SSH_USER", $i);
2216a75fececSSteven Rostedt    $tmpdir = set_test_option("TMP_DIR", $i);
2217a75fececSSteven Rostedt    $outputdir = set_test_option("OUTPUT_DIR", $i);
2218a75fececSSteven Rostedt    $builddir = set_test_option("BUILD_DIR", $i);
2219a75fececSSteven Rostedt    $test_type = set_test_option("TEST_TYPE", $i);
2220a75fececSSteven Rostedt    $build_type = set_test_option("BUILD_TYPE", $i);
2221a75fececSSteven Rostedt    $build_options = set_test_option("BUILD_OPTIONS", $i);
2222a75fececSSteven Rostedt    $power_cycle = set_test_option("POWER_CYCLE", $i);
2223e48c5293SSteven Rostedt    $reboot = set_test_option("REBOOT", $i);
2224a75fececSSteven Rostedt    $noclean = set_test_option("BUILD_NOCLEAN", $i);
2225a75fececSSteven Rostedt    $minconfig = set_test_option("MIN_CONFIG", $i);
2226a75fececSSteven Rostedt    $run_test = set_test_option("TEST", $i);
2227a75fececSSteven Rostedt    $addconfig = set_test_option("ADD_CONFIG", $i);
2228a75fececSSteven Rostedt    $reboot_type = set_test_option("REBOOT_TYPE", $i);
2229a75fececSSteven Rostedt    $grub_menu = set_test_option("GRUB_MENU", $i);
22308b37ca8cSSteven Rostedt    $post_install = set_test_option("POST_INSTALL", $i);
2231a75fececSSteven Rostedt    $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
2232a75fececSSteven Rostedt    $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
2233a75fececSSteven Rostedt    $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
2234a75fececSSteven Rostedt    $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
2235a75fececSSteven Rostedt    $power_off = set_test_option("POWER_OFF", $i);
2236576f627cSSteven Rostedt    $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
2237576f627cSSteven Rostedt    $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
2238a75fececSSteven Rostedt    $sleep_time = set_test_option("SLEEP_TIME", $i);
2239a75fececSSteven Rostedt    $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
224027d934b2SSteven Rostedt    $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
2241c960bb9fSSteven Rostedt    $bisect_manual = set_test_option("BISECT_MANUAL", $i);
2242c23dca7cSSteven Rostedt    $bisect_skip = set_test_option("BISECT_SKIP", $i);
224330f75da5SSteven Rostedt    $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
2244a75fececSSteven Rostedt    $store_failures = set_test_option("STORE_FAILURES", $i);
22459064af52SSteven Rostedt    $test_name = set_test_option("TEST_NAME", $i);
2246a75fececSSteven Rostedt    $timeout = set_test_option("TIMEOUT", $i);
2247a75fececSSteven Rostedt    $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
2248a75fececSSteven Rostedt    $console = set_test_option("CONSOLE", $i);
2249f1a5b962SSteven Rostedt    $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
2250a75fececSSteven Rostedt    $success_line = set_test_option("SUCCESS_LINE", $i);
22511c8a617aSSteven Rostedt    $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
22521c8a617aSSteven Rostedt    $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
22532d01b26aSSteven Rostedt    $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
2254a75fececSSteven Rostedt    $build_target = set_test_option("BUILD_TARGET", $i);
2255e48c5293SSteven Rostedt    $ssh_exec = set_test_option("SSH_EXEC", $i);
2256e48c5293SSteven Rostedt    $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
2257a75fececSSteven Rostedt    $target_image = set_test_option("TARGET_IMAGE", $i);
2258a75fececSSteven Rostedt    $localversion = set_test_option("LOCALVERSION", $i);
2259a75fececSSteven Rostedt
2260a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
2261a75fececSSteven Rostedt
2262a75fececSSteven Rostedt    if (!-d $tmpdir) {
2263a75fececSSteven Rostedt	mkpath($tmpdir) or
2264a75fececSSteven Rostedt	    die "can't create $tmpdir";
2265a75fececSSteven Rostedt    }
2266a75fececSSteven Rostedt
2267e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
2268e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
2269e48c5293SSteven Rostedt
2270a75fececSSteven Rostedt    $target = "$ssh_user\@$machine";
2271a75fececSSteven Rostedt
2272a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
2273a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
2274a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
227551ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
2276a75fececSSteven Rostedt
2277a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
2278576f627cSSteven Rostedt	dodie "GRUB_MENU not defined" if (!defined($grub_menu));
2279a75fececSSteven Rostedt    } elsif (!defined($reboot_script)) {
2280576f627cSSteven Rostedt	dodie "REBOOT_SCRIPT not defined"
2281a75fececSSteven Rostedt    }
2282a75fececSSteven Rostedt
2283a75fececSSteven Rostedt    my $run_type = $build_type;
2284a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
2285a75fececSSteven Rostedt	$run_type = $opt{"PATCHCHECK_TYPE[$i]"};
2286a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
2287a75fececSSteven Rostedt	$run_type = $opt{"BISECT_TYPE[$i]"};
22880a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
22890a05c769SSteven Rostedt	$run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
2290a75fececSSteven Rostedt    }
2291a75fececSSteven Rostedt
2292a75fececSSteven Rostedt    # mistake in config file?
2293a75fececSSteven Rostedt    if (!defined($run_type)) {
2294a75fececSSteven Rostedt	$run_type = "ERROR";
2295a75fececSSteven Rostedt    }
22962545eb61SSteven Rostedt
22972545eb61SSteven Rostedt    doprint "\n\n";
2298a75fececSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
22997faafbd6SSteven Rostedt
23007faafbd6SSteven Rostedt    unlink $dmesg;
23017faafbd6SSteven Rostedt    unlink $buildlog;
23022545eb61SSteven Rostedt
23032b7d9b21SSteven Rostedt    if (!defined($minconfig)) {
23042b7d9b21SSteven Rostedt	$minconfig = $addconfig;
23052b7d9b21SSteven Rostedt
23062b7d9b21SSteven Rostedt    } elsif (defined($addconfig)) {
23079be2e6b5SSteven Rostedt	run_command "cat $addconfig $minconfig > $tmpdir/add_config" or
23082b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
23099be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
23102b7d9b21SSteven Rostedt    }
23112b7d9b21SSteven Rostedt
23126c5ee0beSSteven Rostedt    my $checkout = $opt{"CHECKOUT[$i]"};
23136c5ee0beSSteven Rostedt    if (defined($checkout)) {
23146c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
23156c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
23166c5ee0beSSteven Rostedt    }
23176c5ee0beSSteven Rostedt
2318a75fececSSteven Rostedt    if ($test_type eq "bisect") {
23195f9b6cedSSteven Rostedt	bisect $i;
23205f9b6cedSSteven Rostedt	next;
23210a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
23220a05c769SSteven Rostedt	config_bisect $i;
23230a05c769SSteven Rostedt	next;
2324a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
23256c5ee0beSSteven Rostedt	patchcheck $i;
23266c5ee0beSSteven Rostedt	next;
23275f9b6cedSSteven Rostedt    }
23285f9b6cedSSteven Rostedt
23297faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
23307faafbd6SSteven Rostedt	build $build_type or next;
23312545eb61SSteven Rostedt    }
23322545eb61SSteven Rostedt
2333a75fececSSteven Rostedt    if ($test_type ne "build") {
23345f9b6cedSSteven Rostedt	get_grub_index;
23355f9b6cedSSteven Rostedt	get_version;
23362545eb61SSteven Rostedt	install;
23375a391fbfSSteven Rostedt
23387faafbd6SSteven Rostedt	my $failed = 0;
23397faafbd6SSteven Rostedt	start_monitor;
23407faafbd6SSteven Rostedt	monitor or $failed = 1;;
2341a75fececSSteven Rostedt
2342a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
23437faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
23445a391fbfSSteven Rostedt	}
23457faafbd6SSteven Rostedt	end_monitor;
23467faafbd6SSteven Rostedt	next if ($failed);
2347a75fececSSteven Rostedt    }
23485a391fbfSSteven Rostedt
23495f9b6cedSSteven Rostedt    success $i;
235075c3fda7SSteven Rostedt}
23512545eb61SSteven Rostedt
23525c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
235375c3fda7SSteven Rostedt    halt;
2354576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
235575c3fda7SSteven Rostedt    reboot;
23565c42fc5bSSteven Rostedt}
235775c3fda7SSteven Rostedt
2358e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
2359e48c5293SSteven Rostedt
23602545eb61SSteven Rostedtexit 0;
2361