xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision dbd3783b4dd33dd7ce5c378bf5b1da27a1298735)
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;
25bb8474b1SSteven Rostedt$default{"TEST_TYPE"}		= "build";
26a75fececSSteven Rostedt$default{"BUILD_TYPE"}		= "randconfig";
27a75fececSSteven Rostedt$default{"MAKE_CMD"}		= "make";
28a75fececSSteven Rostedt$default{"TIMEOUT"}		= 120;
2948920630SSteven Rostedt$default{"TMP_DIR"}		= "/tmp/ktest/\${MACHINE}";
30a75fececSSteven Rostedt$default{"SLEEP_TIME"}		= 60;	# sleep time between tests
31a75fececSSteven Rostedt$default{"BUILD_NOCLEAN"}	= 0;
32a75fececSSteven Rostedt$default{"REBOOT_ON_ERROR"}	= 0;
33a75fececSSteven Rostedt$default{"POWEROFF_ON_ERROR"}	= 0;
34a75fececSSteven Rostedt$default{"REBOOT_ON_SUCCESS"}	= 1;
35a75fececSSteven Rostedt$default{"POWEROFF_ON_SUCCESS"}	= 0;
36a75fececSSteven Rostedt$default{"BUILD_OPTIONS"}	= "";
37a75fececSSteven Rostedt$default{"BISECT_SLEEP_TIME"}	= 60;   # sleep time between bisects
3827d934b2SSteven Rostedt$default{"PATCHCHECK_SLEEP_TIME"} = 60; # sleep time between patch checks
39a75fececSSteven Rostedt$default{"CLEAR_LOG"}		= 0;
40c960bb9fSSteven Rostedt$default{"BISECT_MANUAL"}	= 0;
41c23dca7cSSteven Rostedt$default{"BISECT_SKIP"}		= 1;
42a75fececSSteven Rostedt$default{"SUCCESS_LINE"}	= "login:";
43f1a5b962SSteven Rostedt$default{"DETECT_TRIPLE_FAULT"} = 1;
44e0a8742eSSteven Rostedt$default{"NO_INSTALL"}		= 0;
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;
53600bbf0aSSteven Rostedt
54600bbf0aSSteven Rostedt# required, and we will ask users if they don't have them but we keep the default
55600bbf0aSSteven Rostedt# value something that is common.
56600bbf0aSSteven Rostedt$default{"REBOOT_TYPE"}		= "grub";
578d1491baSSteven Rostedt$default{"LOCALVERSION"}	= "-test";
58600bbf0aSSteven Rostedt$default{"SSH_USER"}		= "root";
59600bbf0aSSteven Rostedt$default{"BUILD_TARGET"} 	= "arch/x86/boot/bzImage";
60600bbf0aSSteven Rostedt$default{"TARGET_IMAGE"}	= "/boot/vmlinuz-test";
612545eb61SSteven Rostedt
628d1491baSSteven Rostedtmy $ktest_config;
632545eb61SSteven Rostedtmy $version;
64a75fececSSteven Rostedtmy $machine;
65e48c5293SSteven Rostedtmy $ssh_user;
66a75fececSSteven Rostedtmy $tmpdir;
67a75fececSSteven Rostedtmy $builddir;
68a75fececSSteven Rostedtmy $outputdir;
6951ad1dd1SSteven Rostedtmy $output_config;
70a75fececSSteven Rostedtmy $test_type;
717faafbd6SSteven Rostedtmy $build_type;
72a75fececSSteven Rostedtmy $build_options;
730bd6c1a3SSteven Rostedtmy $pre_build;
740bd6c1a3SSteven Rostedtmy $post_build;
750bd6c1a3SSteven Rostedtmy $pre_build_die;
760bd6c1a3SSteven Rostedtmy $post_build_die;
77a75fececSSteven Rostedtmy $reboot_type;
78a75fececSSteven Rostedtmy $reboot_script;
79a75fececSSteven Rostedtmy $power_cycle;
80e48c5293SSteven Rostedtmy $reboot;
81a75fececSSteven Rostedtmy $reboot_on_error;
82a75fececSSteven Rostedtmy $poweroff_on_error;
83a75fececSSteven Rostedtmy $die_on_failure;
84576f627cSSteven Rostedtmy $powercycle_after_reboot;
85576f627cSSteven Rostedtmy $poweroff_after_halt;
86e48c5293SSteven Rostedtmy $ssh_exec;
87e48c5293SSteven Rostedtmy $scp_to_target;
88a75fececSSteven Rostedtmy $power_off;
89a75fececSSteven Rostedtmy $grub_menu;
902545eb61SSteven Rostedtmy $grub_number;
912545eb61SSteven Rostedtmy $target;
922545eb61SSteven Rostedtmy $make;
938b37ca8cSSteven Rostedtmy $post_install;
94e0a8742eSSteven Rostedtmy $no_install;
955c42fc5bSSteven Rostedtmy $noclean;
965f9b6cedSSteven Rostedtmy $minconfig;
974c4ab120SSteven Rostedtmy $start_minconfig;
9835ce5952SSteven Rostedtmy $start_minconfig_defined;
994c4ab120SSteven Rostedtmy $output_minconfig;
1004c4ab120SSteven Rostedtmy $ignore_config;
1012b7d9b21SSteven Rostedtmy $addconfig;
1025f9b6cedSSteven Rostedtmy $in_bisect = 0;
1035f9b6cedSSteven Rostedtmy $bisect_bad = "";
104d6ce2a0bSSteven Rostedtmy $reverse_bisect;
105c960bb9fSSteven Rostedtmy $bisect_manual;
106c23dca7cSSteven Rostedtmy $bisect_skip;
10730f75da5SSteven Rostedtmy $config_bisect_good;
1086c5ee0beSSteven Rostedtmy $in_patchcheck = 0;
1095a391fbfSSteven Rostedtmy $run_test;
1106c5ee0beSSteven Rostedtmy $redirect;
1117faafbd6SSteven Rostedtmy $buildlog;
112a9dd5d63SRabin Vincentmy $testlog;
1137faafbd6SSteven Rostedtmy $dmesg;
1147faafbd6SSteven Rostedtmy $monitor_fp;
1157faafbd6SSteven Rostedtmy $monitor_pid;
1167faafbd6SSteven Rostedtmy $monitor_cnt = 0;
117a75fececSSteven Rostedtmy $sleep_time;
118a75fececSSteven Rostedtmy $bisect_sleep_time;
11927d934b2SSteven Rostedtmy $patchcheck_sleep_time;
1201990207dSSteven Rostedtmy $ignore_warnings;
121a75fececSSteven Rostedtmy $store_failures;
122de5b6e3bSRabin Vincentmy $store_successes;
1239064af52SSteven Rostedtmy $test_name;
124a75fececSSteven Rostedtmy $timeout;
125a75fececSSteven Rostedtmy $booted_timeout;
126f1a5b962SSteven Rostedtmy $detect_triplefault;
127a75fececSSteven Rostedtmy $console;
1282b803365SSteven Rostedtmy $reboot_success_line;
129a75fececSSteven Rostedtmy $success_line;
1301c8a617aSSteven Rostedtmy $stop_after_success;
1311c8a617aSSteven Rostedtmy $stop_after_failure;
1322d01b26aSSteven Rostedtmy $stop_test_after;
133a75fececSSteven Rostedtmy $build_target;
134a75fececSSteven Rostedtmy $target_image;
135a75fececSSteven Rostedtmy $localversion;
136576f627cSSteven Rostedtmy $iteration = 0;
137e48c5293SSteven Rostedtmy $successes = 0;
1382545eb61SSteven Rostedt
139bb8474b1SSteven Rostedt# set when a test is something other that just building
140bb8474b1SSteven Rostedt# which would require more options.
141bb8474b1SSteven Rostedtmy $buildonly = 1;
142bb8474b1SSteven Rostedt
143*dbd3783bSSteven Rostedt# set when creating a new config
144*dbd3783bSSteven Rostedtmy $newconfig = 0;
145*dbd3783bSSteven Rostedt
1468d1491baSSteven Rostedtmy %entered_configs;
1478d1491baSSteven Rostedtmy %config_help;
14877d942ceSSteven Rostedtmy %variable;
149fcb3f16aSSteven Rostedtmy %force_config;
1508d1491baSSteven Rostedt
1514ab1cce5SSteven Rostedt# do not force reboots on config problems
1524ab1cce5SSteven Rostedtmy $no_reboot = 1;
1534ab1cce5SSteven Rostedt
1547bf51073SSteven Rostedt# default variables that can be used
1557bf51073SSteven Rostedtchomp ($variable{"PWD"} = `pwd`);
1567bf51073SSteven Rostedt
1578d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF"
1588d1491baSSteven Rostedt The machine hostname that you will test.
159bb8474b1SSteven Rostedt For build only tests, it is still needed to differentiate log files.
1608d1491baSSteven RostedtEOF
1618d1491baSSteven Rostedt    ;
1628d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF"
1638d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user
1648d1491baSSteven Rostedt  (most likely root, since you need privileged operations)
1658d1491baSSteven RostedtEOF
1668d1491baSSteven Rostedt    ;
1678d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF"
1688d1491baSSteven Rostedt The directory that contains the Linux source code (full path).
1690e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
1700e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
1718d1491baSSteven RostedtEOF
1728d1491baSSteven Rostedt    ;
1738d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF"
1748d1491baSSteven Rostedt The directory that the objects will be built (full path).
1758d1491baSSteven Rostedt (can not be same as BUILD_DIR)
1760e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
1770e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
1788d1491baSSteven RostedtEOF
1798d1491baSSteven Rostedt    ;
1808d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF"
1818d1491baSSteven Rostedt The location of the compiled file to copy to the target.
1828d1491baSSteven Rostedt (relative to OUTPUT_DIR)
1838d1491baSSteven RostedtEOF
1848d1491baSSteven Rostedt    ;
185*dbd3783bSSteven Rostedt$config_help{"BUILD_OPTIONS"} = << "EOF"
186*dbd3783bSSteven Rostedt Options to add to \"make\" when building.
187*dbd3783bSSteven Rostedt i.e.  -j20
188*dbd3783bSSteven RostedtEOF
189*dbd3783bSSteven Rostedt    ;
1908d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF"
1918d1491baSSteven Rostedt The place to put your image on the test machine.
1928d1491baSSteven RostedtEOF
1938d1491baSSteven Rostedt    ;
1948d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF"
1958d1491baSSteven Rostedt A script or command to reboot the box.
1968d1491baSSteven Rostedt
1978d1491baSSteven Rostedt Here is a digital loggers power switch example
1988d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
1998d1491baSSteven Rostedt
2008d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host
2018d1491baSSteven Rostedt with the name "Guest".
2028d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
2038d1491baSSteven RostedtEOF
2048d1491baSSteven Rostedt    ;
2058d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF"
2068d1491baSSteven Rostedt The script or command that reads the console
2078d1491baSSteven Rostedt
2088d1491baSSteven Rostedt  If you use ttywatch server, something like the following would work.
2098d1491baSSteven RostedtCONSOLE = nc -d localhost 3001
2108d1491baSSteven Rostedt
2118d1491baSSteven Rostedt For a virtual machine with guest name "Guest".
2128d1491baSSteven RostedtCONSOLE =  virsh console Guest
2138d1491baSSteven RostedtEOF
2148d1491baSSteven Rostedt    ;
2158d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF"
2168d1491baSSteven Rostedt Required version ending to differentiate the test
2178d1491baSSteven Rostedt from other linux builds on the system.
2188d1491baSSteven RostedtEOF
2198d1491baSSteven Rostedt    ;
2208d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF"
2218d1491baSSteven Rostedt Way to reboot the box to the test kernel.
2228d1491baSSteven Rostedt Only valid options so far are "grub" and "script".
2238d1491baSSteven Rostedt
2248d1491baSSteven Rostedt If you specify grub, it will assume grub version 1
2258d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
2268d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not
2278d1491baSSteven Rostedt your setup, then specify "script" and have a command or script
2288d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target.
2298d1491baSSteven Rostedt
2308d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually.
2318d1491baSSteven Rostedt The test will not modify that file.
2328d1491baSSteven RostedtEOF
2338d1491baSSteven Rostedt    ;
2348d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF"
2358d1491baSSteven Rostedt The grub title name for the test kernel to boot
2368d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = grub)
2378d1491baSSteven Rostedt
2388d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to
2398d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search
2408d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to
2418d1491baSSteven Rostedt reboot into.
2428d1491baSSteven Rostedt
2438d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has:
2448d1491baSSteven Rostedt title Test Kernel
2458d1491baSSteven Rostedt kernel vmlinuz-test
2468d1491baSSteven Rostedt GRUB_MENU = Test Kernel
2478d1491baSSteven RostedtEOF
2488d1491baSSteven Rostedt    ;
2498d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF"
2508d1491baSSteven Rostedt A script to reboot the target into the test kernel
2518d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script)
2528d1491baSSteven RostedtEOF
2538d1491baSSteven Rostedt    ;
2548d1491baSSteven Rostedt
255dad98754SSteven Rostedtsub read_prompt {
256dad98754SSteven Rostedt    my ($cancel, $prompt) = @_;
25735ce5952SSteven Rostedt
25835ce5952SSteven Rostedt    my $ans;
25935ce5952SSteven Rostedt
26035ce5952SSteven Rostedt    for (;;) {
261dad98754SSteven Rostedt	if ($cancel) {
262dad98754SSteven Rostedt	    print "$prompt [y/n/C] ";
263dad98754SSteven Rostedt	} else {
26435ce5952SSteven Rostedt	    print "$prompt [Y/n] ";
265dad98754SSteven Rostedt	}
26635ce5952SSteven Rostedt	$ans = <STDIN>;
26735ce5952SSteven Rostedt	chomp $ans;
26835ce5952SSteven Rostedt	if ($ans =~ /^\s*$/) {
269dad98754SSteven Rostedt	    if ($cancel) {
270dad98754SSteven Rostedt		$ans = "c";
271dad98754SSteven Rostedt	    } else {
27235ce5952SSteven Rostedt		$ans = "y";
27335ce5952SSteven Rostedt	    }
274dad98754SSteven Rostedt	}
27535ce5952SSteven Rostedt	last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
276dad98754SSteven Rostedt	if ($cancel) {
277dad98754SSteven Rostedt	    last if ($ans =~ /^c$/i);
278dad98754SSteven Rostedt	    print "Please answer either 'y', 'n' or 'c'.\n";
279dad98754SSteven Rostedt	} else {
28035ce5952SSteven Rostedt	    print "Please answer either 'y' or 'n'.\n";
28135ce5952SSteven Rostedt	}
282dad98754SSteven Rostedt    }
283dad98754SSteven Rostedt    if ($ans =~ /^c/i) {
284dad98754SSteven Rostedt	exit;
285dad98754SSteven Rostedt    }
28635ce5952SSteven Rostedt    if ($ans !~ /^y$/i) {
28735ce5952SSteven Rostedt	return 0;
28835ce5952SSteven Rostedt    }
28935ce5952SSteven Rostedt    return 1;
29035ce5952SSteven Rostedt}
2918d1491baSSteven Rostedt
292dad98754SSteven Rostedtsub read_yn {
293dad98754SSteven Rostedt    my ($prompt) = @_;
294dad98754SSteven Rostedt
295dad98754SSteven Rostedt    return read_prompt 0, $prompt;
296dad98754SSteven Rostedt}
297dad98754SSteven Rostedt
298dad98754SSteven Rostedtsub read_ync {
299dad98754SSteven Rostedt    my ($prompt) = @_;
300dad98754SSteven Rostedt
301dad98754SSteven Rostedt    return read_prompt 1, $prompt;
302dad98754SSteven Rostedt}
303dad98754SSteven Rostedt
3048d1491baSSteven Rostedtsub get_ktest_config {
3058d1491baSSteven Rostedt    my ($config) = @_;
306815e2bd7SSteven Rostedt    my $ans;
3078d1491baSSteven Rostedt
3088d1491baSSteven Rostedt    return if (defined($opt{$config}));
3098d1491baSSteven Rostedt
3108d1491baSSteven Rostedt    if (defined($config_help{$config})) {
3118d1491baSSteven Rostedt	print "\n";
3128d1491baSSteven Rostedt	print $config_help{$config};
3138d1491baSSteven Rostedt    }
3148d1491baSSteven Rostedt
3158d1491baSSteven Rostedt    for (;;) {
3168d1491baSSteven Rostedt	print "$config = ";
317*dbd3783bSSteven Rostedt	if (defined($default{$config}) && length($default{$config})) {
3188d1491baSSteven Rostedt	    print "\[$default{$config}\] ";
3198d1491baSSteven Rostedt	}
320815e2bd7SSteven Rostedt	$ans = <STDIN>;
321815e2bd7SSteven Rostedt	$ans =~ s/^\s*(.*\S)\s*$/$1/;
322815e2bd7SSteven Rostedt	if ($ans =~ /^\s*$/) {
3238d1491baSSteven Rostedt	    if ($default{$config}) {
324815e2bd7SSteven Rostedt		$ans = $default{$config};
3258d1491baSSteven Rostedt	    } else {
3268d1491baSSteven Rostedt		print "Your answer can not be blank\n";
3278d1491baSSteven Rostedt		next;
3288d1491baSSteven Rostedt	    }
3298d1491baSSteven Rostedt	}
3300e7a22deSSteven Rostedt	$entered_configs{$config} = ${ans};
3318d1491baSSteven Rostedt	last;
3328d1491baSSteven Rostedt    }
3338d1491baSSteven Rostedt}
3348d1491baSSteven Rostedt
3358d1491baSSteven Rostedtsub get_ktest_configs {
3368d1491baSSteven Rostedt    get_ktest_config("MACHINE");
3378d1491baSSteven Rostedt    get_ktest_config("BUILD_DIR");
3388d1491baSSteven Rostedt    get_ktest_config("OUTPUT_DIR");
339bb8474b1SSteven Rostedt
340*dbd3783bSSteven Rostedt    if ($newconfig) {
341*dbd3783bSSteven Rostedt	get_ktest_config("BUILD_OPTIONS");
342*dbd3783bSSteven Rostedt    }
343*dbd3783bSSteven Rostedt
344bb8474b1SSteven Rostedt    # options required for other than just building a kernel
345bb8474b1SSteven Rostedt    if (!$buildonly) {
346bb8474b1SSteven Rostedt	get_ktest_config("SSH_USER");
3478d1491baSSteven Rostedt	get_ktest_config("BUILD_TARGET");
3488d1491baSSteven Rostedt	get_ktest_config("TARGET_IMAGE");
3498d1491baSSteven Rostedt	get_ktest_config("POWER_CYCLE");
3508d1491baSSteven Rostedt	get_ktest_config("CONSOLE");
351bb8474b1SSteven Rostedt    }
352bb8474b1SSteven Rostedt
3538d1491baSSteven Rostedt    get_ktest_config("LOCALVERSION");
3548d1491baSSteven Rostedt
355bb8474b1SSteven Rostedt    return if ($buildonly);
356bb8474b1SSteven Rostedt
3578d1491baSSteven Rostedt    my $rtype = $opt{"REBOOT_TYPE"};
3588d1491baSSteven Rostedt
3598d1491baSSteven Rostedt    if (!defined($rtype)) {
3608d1491baSSteven Rostedt	if (!defined($opt{"GRUB_MENU"})) {
3618d1491baSSteven Rostedt	    get_ktest_config("REBOOT_TYPE");
3628d1491baSSteven Rostedt	    $rtype = $entered_configs{"REBOOT_TYPE"};
3638d1491baSSteven Rostedt	} else {
3648d1491baSSteven Rostedt	    $rtype = "grub";
3658d1491baSSteven Rostedt	}
3668d1491baSSteven Rostedt    }
3678d1491baSSteven Rostedt
3688d1491baSSteven Rostedt    if ($rtype eq "grub") {
3698d1491baSSteven Rostedt	get_ktest_config("GRUB_MENU");
3708d1491baSSteven Rostedt    } else {
3718d1491baSSteven Rostedt	get_ktest_config("REBOOT_SCRIPT");
3728d1491baSSteven Rostedt    }
3738d1491baSSteven Rostedt}
3748d1491baSSteven Rostedt
37577d942ceSSteven Rostedtsub process_variables {
3768d735212SSteven Rostedt    my ($value, $remove_undef) = @_;
37777d942ceSSteven Rostedt    my $retval = "";
37877d942ceSSteven Rostedt
37977d942ceSSteven Rostedt    # We want to check for '\', and it is just easier
38077d942ceSSteven Rostedt    # to check the previous characet of '$' and not need
38177d942ceSSteven Rostedt    # to worry if '$' is the first character. By adding
38277d942ceSSteven Rostedt    # a space to $value, we can just check [^\\]\$ and
38377d942ceSSteven Rostedt    # it will still work.
38477d942ceSSteven Rostedt    $value = " $value";
38577d942ceSSteven Rostedt
38677d942ceSSteven Rostedt    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
38777d942ceSSteven Rostedt	my $begin = $1;
38877d942ceSSteven Rostedt	my $var = $2;
38977d942ceSSteven Rostedt	my $end = $3;
39077d942ceSSteven Rostedt	# append beginning of value to retval
39177d942ceSSteven Rostedt	$retval = "$retval$begin";
39277d942ceSSteven Rostedt	if (defined($variable{$var})) {
39377d942ceSSteven Rostedt	    $retval = "$retval$variable{$var}";
3948d735212SSteven Rostedt	} elsif (defined($remove_undef) && $remove_undef) {
3958d735212SSteven Rostedt	    # for if statements, any variable that is not defined,
3968d735212SSteven Rostedt	    # we simple convert to 0
3978d735212SSteven Rostedt	    $retval = "${retval}0";
39877d942ceSSteven Rostedt	} else {
39977d942ceSSteven Rostedt	    # put back the origin piece.
40077d942ceSSteven Rostedt	    $retval = "$retval\$\{$var\}";
40177d942ceSSteven Rostedt	}
40277d942ceSSteven Rostedt	$value = $end;
40377d942ceSSteven Rostedt    }
40477d942ceSSteven Rostedt    $retval = "$retval$value";
40577d942ceSSteven Rostedt
40677d942ceSSteven Rostedt    # remove the space added in the beginning
40777d942ceSSteven Rostedt    $retval =~ s/ //;
40877d942ceSSteven Rostedt
40977d942ceSSteven Rostedt    return "$retval"
41077d942ceSSteven Rostedt}
41177d942ceSSteven Rostedt
412a57419b3SSteven Rostedtsub set_value {
4133d1cc414SSteven Rostedt    my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
4142545eb61SSteven Rostedt
415bb8474b1SSteven Rostedt    if ($lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $rvalue ne "build") {
416bb8474b1SSteven Rostedt	# Note if a test is something other than build, then we
417bb8474b1SSteven Rostedt	# will need other manditory options.
418bb8474b1SSteven Rostedt	$buildonly = 0;
419bb8474b1SSteven Rostedt    }
420bb8474b1SSteven Rostedt
421a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
4223d1cc414SSteven Rostedt	if (!$override || defined(${$overrides}{$lvalue})) {
4233d1cc414SSteven Rostedt	    my $extra = "";
4243d1cc414SSteven Rostedt	    if ($override) {
4253d1cc414SSteven Rostedt		$extra = "In the same override section!\n";
4263d1cc414SSteven Rostedt	    }
4273d1cc414SSteven Rostedt	    die "$name: $.: Option $lvalue defined more than once!\n$extra";
4283d1cc414SSteven Rostedt	}
4293d1cc414SSteven Rostedt	${$overrides}{$lvalue} = $rvalue;
430a75fececSSteven Rostedt    }
43121a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
43221a9679fSSteven Rostedt	delete $opt{$lvalue};
43321a9679fSSteven Rostedt    } else {
43477d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
43521a9679fSSteven Rostedt	$opt{$lvalue} = $rvalue;
43621a9679fSSteven Rostedt    }
4372545eb61SSteven Rostedt}
438a57419b3SSteven Rostedt
43977d942ceSSteven Rostedtsub set_variable {
44077d942ceSSteven Rostedt    my ($lvalue, $rvalue) = @_;
44177d942ceSSteven Rostedt
44277d942ceSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
44377d942ceSSteven Rostedt	delete $variable{$lvalue};
44477d942ceSSteven Rostedt    } else {
44577d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
44677d942ceSSteven Rostedt	$variable{$lvalue} = $rvalue;
44777d942ceSSteven Rostedt    }
44877d942ceSSteven Rostedt}
44977d942ceSSteven Rostedt
450ab7a3f52SSteven Rostedtsub process_compare {
451ab7a3f52SSteven Rostedt    my ($lval, $cmp, $rval) = @_;
452ab7a3f52SSteven Rostedt
453ab7a3f52SSteven Rostedt    # remove whitespace
454ab7a3f52SSteven Rostedt
455ab7a3f52SSteven Rostedt    $lval =~ s/^\s*//;
456ab7a3f52SSteven Rostedt    $lval =~ s/\s*$//;
457ab7a3f52SSteven Rostedt
458ab7a3f52SSteven Rostedt    $rval =~ s/^\s*//;
459ab7a3f52SSteven Rostedt    $rval =~ s/\s*$//;
460ab7a3f52SSteven Rostedt
461ab7a3f52SSteven Rostedt    if ($cmp eq "==") {
462ab7a3f52SSteven Rostedt	return $lval eq $rval;
463ab7a3f52SSteven Rostedt    } elsif ($cmp eq "!=") {
464ab7a3f52SSteven Rostedt	return $lval ne $rval;
465ab7a3f52SSteven Rostedt    }
466ab7a3f52SSteven Rostedt
467ab7a3f52SSteven Rostedt    my $statement = "$lval $cmp $rval";
468ab7a3f52SSteven Rostedt    my $ret = eval $statement;
469ab7a3f52SSteven Rostedt
470ab7a3f52SSteven Rostedt    # $@ stores error of eval
471ab7a3f52SSteven Rostedt    if ($@) {
472ab7a3f52SSteven Rostedt	return -1;
473ab7a3f52SSteven Rostedt    }
474ab7a3f52SSteven Rostedt
475ab7a3f52SSteven Rostedt    return $ret;
476ab7a3f52SSteven Rostedt}
477ab7a3f52SSteven Rostedt
4789900b5dcSSteven Rostedtsub value_defined {
4799900b5dcSSteven Rostedt    my ($val) = @_;
4809900b5dcSSteven Rostedt
4819900b5dcSSteven Rostedt    return defined($variable{$2}) ||
4829900b5dcSSteven Rostedt	defined($opt{$2});
4839900b5dcSSteven Rostedt}
4849900b5dcSSteven Rostedt
4858d735212SSteven Rostedtmy $d = 0;
4868d735212SSteven Rostedtsub process_expression {
4878d735212SSteven Rostedt    my ($name, $val) = @_;
48845d73a5dSSteven Rostedt
4898d735212SSteven Rostedt    my $c = $d++;
4908d735212SSteven Rostedt
4918d735212SSteven Rostedt    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
4928d735212SSteven Rostedt	my $express = $1;
4938d735212SSteven Rostedt
4948d735212SSteven Rostedt	if (process_expression($name, $express)) {
4958d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
4968d735212SSteven Rostedt	} else {
4978d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
4988d735212SSteven Rostedt	}
4998d735212SSteven Rostedt    }
5008d735212SSteven Rostedt
5018d735212SSteven Rostedt    $d--;
5028d735212SSteven Rostedt    my $OR = "\\|\\|";
5038d735212SSteven Rostedt    my $AND = "\\&\\&";
5048d735212SSteven Rostedt
5058d735212SSteven Rostedt    while ($val =~ s/^(.*?)($OR|$AND)//) {
5068d735212SSteven Rostedt	my $express = $1;
5078d735212SSteven Rostedt	my $op = $2;
5088d735212SSteven Rostedt
5098d735212SSteven Rostedt	if (process_expression($name, $express)) {
5108d735212SSteven Rostedt	    if ($op eq "||") {
5118d735212SSteven Rostedt		return 1;
5128d735212SSteven Rostedt	    }
5138d735212SSteven Rostedt	} else {
5148d735212SSteven Rostedt	    if ($op eq "&&") {
5158d735212SSteven Rostedt		return 0;
5168d735212SSteven Rostedt	    }
5178d735212SSteven Rostedt	}
5188d735212SSteven Rostedt    }
51945d73a5dSSteven Rostedt
520ab7a3f52SSteven Rostedt    if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) {
521ab7a3f52SSteven Rostedt	my $ret = process_compare($1, $2, $3);
522ab7a3f52SSteven Rostedt	if ($ret < 0) {
523ab7a3f52SSteven Rostedt	    die "$name: $.: Unable to process comparison\n";
524ab7a3f52SSteven Rostedt	}
525ab7a3f52SSteven Rostedt	return $ret;
526ab7a3f52SSteven Rostedt    }
527ab7a3f52SSteven Rostedt
5289900b5dcSSteven Rostedt    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
5299900b5dcSSteven Rostedt	if (defined $1) {
5309900b5dcSSteven Rostedt	    return !value_defined($2);
5319900b5dcSSteven Rostedt	} else {
5329900b5dcSSteven Rostedt	    return value_defined($2);
5339900b5dcSSteven Rostedt	}
5349900b5dcSSteven Rostedt    }
5359900b5dcSSteven Rostedt
53645d73a5dSSteven Rostedt    if ($val =~ /^\s*0\s*$/) {
53745d73a5dSSteven Rostedt	return 0;
53845d73a5dSSteven Rostedt    } elsif ($val =~ /^\s*\d+\s*$/) {
53945d73a5dSSteven Rostedt	return 1;
54045d73a5dSSteven Rostedt    }
54145d73a5dSSteven Rostedt
5429900b5dcSSteven Rostedt    die ("$name: $.: Undefined content $val in if statement\n");
5438d735212SSteven Rostedt}
5448d735212SSteven Rostedt
5458d735212SSteven Rostedtsub process_if {
5468d735212SSteven Rostedt    my ($name, $value) = @_;
5478d735212SSteven Rostedt
5488d735212SSteven Rostedt    # Convert variables and replace undefined ones with 0
5498d735212SSteven Rostedt    my $val = process_variables($value, 1);
5508d735212SSteven Rostedt    my $ret = process_expression $name, $val;
5518d735212SSteven Rostedt
5528d735212SSteven Rostedt    return $ret;
55345d73a5dSSteven Rostedt}
55445d73a5dSSteven Rostedt
5552ed3b161SSteven Rostedtsub __read_config {
5562ed3b161SSteven Rostedt    my ($config, $current_test_num) = @_;
557a57419b3SSteven Rostedt
5582ed3b161SSteven Rostedt    my $in;
5592ed3b161SSteven Rostedt    open($in, $config) || die "can't read file $config";
560a57419b3SSteven Rostedt
561a57419b3SSteven Rostedt    my $name = $config;
562a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
563a57419b3SSteven Rostedt
5642ed3b161SSteven Rostedt    my $test_num = $$current_test_num;
565a57419b3SSteven Rostedt    my $default = 1;
566a57419b3SSteven Rostedt    my $repeat = 1;
567a57419b3SSteven Rostedt    my $num_tests_set = 0;
568a57419b3SSteven Rostedt    my $skip = 0;
569a57419b3SSteven Rostedt    my $rest;
570a9f84424SSteven Rostedt    my $line;
5710df213caSSteven Rostedt    my $test_case = 0;
57245d73a5dSSteven Rostedt    my $if = 0;
57345d73a5dSSteven Rostedt    my $if_set = 0;
5743d1cc414SSteven Rostedt    my $override = 0;
5753d1cc414SSteven Rostedt
5763d1cc414SSteven Rostedt    my %overrides;
577a57419b3SSteven Rostedt
5782ed3b161SSteven Rostedt    while (<$in>) {
579a57419b3SSteven Rostedt
580a57419b3SSteven Rostedt	# ignore blank lines and comments
581a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
582a57419b3SSteven Rostedt
5830050b6bbSSteven Rostedt	if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
584a57419b3SSteven Rostedt
5850050b6bbSSteven Rostedt	    my $type = $1;
5860050b6bbSSteven Rostedt	    $rest = $2;
587a9f84424SSteven Rostedt	    $line = $2;
5880050b6bbSSteven Rostedt
5890050b6bbSSteven Rostedt	    my $old_test_num;
5900050b6bbSSteven Rostedt	    my $old_repeat;
5913d1cc414SSteven Rostedt	    $override = 0;
5920050b6bbSSteven Rostedt
5930050b6bbSSteven Rostedt	    if ($type eq "TEST_START") {
594a57419b3SSteven Rostedt
595a57419b3SSteven Rostedt		if ($num_tests_set) {
596a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
597a57419b3SSteven Rostedt		}
598a57419b3SSteven Rostedt
5990050b6bbSSteven Rostedt		$old_test_num = $test_num;
6000050b6bbSSteven Rostedt		$old_repeat = $repeat;
601a57419b3SSteven Rostedt
602a57419b3SSteven Rostedt		$test_num += $repeat;
603a57419b3SSteven Rostedt		$default = 0;
604a57419b3SSteven Rostedt		$repeat = 1;
6050050b6bbSSteven Rostedt	    } else {
6060050b6bbSSteven Rostedt		$default = 1;
6070050b6bbSSteven Rostedt	    }
608a57419b3SSteven Rostedt
609a9f84424SSteven Rostedt	    # If SKIP is anywhere in the line, the command will be skipped
610a9f84424SSteven Rostedt	    if ($rest =~ s/\s+SKIP\b//) {
611a57419b3SSteven Rostedt		$skip = 1;
612a57419b3SSteven Rostedt	    } else {
6130df213caSSteven Rostedt		$test_case = 1;
614a57419b3SSteven Rostedt		$skip = 0;
615a57419b3SSteven Rostedt	    }
616a57419b3SSteven Rostedt
617a9f84424SSteven Rostedt	    if ($rest =~ s/\sELSE\b//) {
618a9f84424SSteven Rostedt		if (!$if) {
619a9f84424SSteven Rostedt		    die "$name: $.: ELSE found with out matching IF section\n$_";
620a57419b3SSteven Rostedt		}
621a9f84424SSteven Rostedt		$if = 0;
622a9f84424SSteven Rostedt
623a9f84424SSteven Rostedt		if ($if_set) {
624a9f84424SSteven Rostedt		    $skip = 1;
625a9f84424SSteven Rostedt		} else {
626a9f84424SSteven Rostedt		    $skip = 0;
6273d1cc414SSteven Rostedt		}
6283d1cc414SSteven Rostedt	    }
629a57419b3SSteven Rostedt
630a9f84424SSteven Rostedt	    if ($rest =~ s/\sIF\s+(.*)//) {
63145d73a5dSSteven Rostedt		if (process_if($name, $1)) {
63245d73a5dSSteven Rostedt		    $if_set = 1;
63345d73a5dSSteven Rostedt		} else {
634a57419b3SSteven Rostedt		    $skip = 1;
635a57419b3SSteven Rostedt		}
63645d73a5dSSteven Rostedt		$if = 1;
63745d73a5dSSteven Rostedt	    } else {
63845d73a5dSSteven Rostedt		$if = 0;
639a9f84424SSteven Rostedt		$if_set = 0;
64045d73a5dSSteven Rostedt	    }
641a57419b3SSteven Rostedt
642a9f84424SSteven Rostedt	    if (!$skip) {
643a9f84424SSteven Rostedt		if ($type eq "TEST_START") {
644a9f84424SSteven Rostedt		    if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
645a9f84424SSteven Rostedt			$repeat = $1;
646a9f84424SSteven Rostedt			$repeat_tests{"$test_num"} = $repeat;
647a9f84424SSteven Rostedt		    }
648a9f84424SSteven Rostedt		} elsif ($rest =~ s/\sOVERRIDE\b//) {
649a9f84424SSteven Rostedt		    # DEFAULT only
650a9f84424SSteven Rostedt		    $override = 1;
651a9f84424SSteven Rostedt		    # Clear previous overrides
652a9f84424SSteven Rostedt		    %overrides = ();
653a9f84424SSteven Rostedt		}
654a9f84424SSteven Rostedt	    }
655a9f84424SSteven Rostedt
656a9f84424SSteven Rostedt	    if (!$skip && $rest !~ /^\s*$/) {
6570050b6bbSSteven Rostedt		die "$name: $.: Gargbage found after $type\n$_";
658a57419b3SSteven Rostedt	    }
659a57419b3SSteven Rostedt
6600050b6bbSSteven Rostedt	    if ($skip && $type eq "TEST_START") {
661a57419b3SSteven Rostedt		$test_num = $old_test_num;
662e48c5293SSteven Rostedt		$repeat = $old_repeat;
663a57419b3SSteven Rostedt	    }
664a57419b3SSteven Rostedt
665ab7a3f52SSteven Rostedt	} elsif (/^\s*ELSE\b(.*)$/) {
66645d73a5dSSteven Rostedt	    if (!$if) {
66745d73a5dSSteven Rostedt		die "$name: $.: ELSE found with out matching IF section\n$_";
66845d73a5dSSteven Rostedt	    }
66945d73a5dSSteven Rostedt	    $rest = $1;
67045d73a5dSSteven Rostedt	    if ($if_set) {
67145d73a5dSSteven Rostedt		$skip = 1;
672ab7a3f52SSteven Rostedt		$rest = "";
67345d73a5dSSteven Rostedt	    } else {
67445d73a5dSSteven Rostedt		$skip = 0;
67545d73a5dSSteven Rostedt
676ab7a3f52SSteven Rostedt		if ($rest =~ /\sIF\s+(.*)/) {
67745d73a5dSSteven Rostedt		    # May be a ELSE IF section.
67845d73a5dSSteven Rostedt		    if (!process_if($name, $1)) {
67945d73a5dSSteven Rostedt			$skip = 1;
68045d73a5dSSteven Rostedt		    }
681ab7a3f52SSteven Rostedt		    $rest = "";
68245d73a5dSSteven Rostedt		} else {
68345d73a5dSSteven Rostedt		    $if = 0;
68445d73a5dSSteven Rostedt		}
68545d73a5dSSteven Rostedt	    }
68645d73a5dSSteven Rostedt
687ab7a3f52SSteven Rostedt	    if ($rest !~ /^\s*$/) {
688ab7a3f52SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
689ab7a3f52SSteven Rostedt	    }
690ab7a3f52SSteven Rostedt
6912ed3b161SSteven Rostedt	} elsif (/^\s*INCLUDE\s+(\S+)/) {
6922ed3b161SSteven Rostedt
6932ed3b161SSteven Rostedt	    next if ($skip);
6942ed3b161SSteven Rostedt
6952ed3b161SSteven Rostedt	    if (!$default) {
6962ed3b161SSteven Rostedt		die "$name: $.: INCLUDE can only be done in default sections\n$_";
6972ed3b161SSteven Rostedt	    }
6982ed3b161SSteven Rostedt
6992ed3b161SSteven Rostedt	    my $file = process_variables($1);
7002ed3b161SSteven Rostedt
7012ed3b161SSteven Rostedt	    if ($file !~ m,^/,) {
7022ed3b161SSteven Rostedt		# check the path of the config file first
7032ed3b161SSteven Rostedt		if ($config =~ m,(.*)/,) {
7042ed3b161SSteven Rostedt		    if (-f "$1/$file") {
7052ed3b161SSteven Rostedt			$file = "$1/$file";
7062ed3b161SSteven Rostedt		    }
7072ed3b161SSteven Rostedt		}
7082ed3b161SSteven Rostedt	    }
7092ed3b161SSteven Rostedt
7102ed3b161SSteven Rostedt	    if ( ! -r $file ) {
7112ed3b161SSteven Rostedt		die "$name: $.: Can't read file $file\n$_";
7122ed3b161SSteven Rostedt	    }
7132ed3b161SSteven Rostedt
7142ed3b161SSteven Rostedt	    if (__read_config($file, \$test_num)) {
7152ed3b161SSteven Rostedt		$test_case = 1;
7162ed3b161SSteven Rostedt	    }
7172ed3b161SSteven Rostedt
718a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
719a57419b3SSteven Rostedt
720a57419b3SSteven Rostedt	    next if ($skip);
721a57419b3SSteven Rostedt
722a57419b3SSteven Rostedt	    my $lvalue = $1;
723a57419b3SSteven Rostedt	    my $rvalue = $2;
724a57419b3SSteven Rostedt
725a57419b3SSteven Rostedt	    if (!$default &&
726a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
727a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
728a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
729a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
730a57419b3SSteven Rostedt	    }
731a57419b3SSteven Rostedt
732a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
733a57419b3SSteven Rostedt		if ($test_num) {
734a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
735a57419b3SSteven Rostedt		}
736a57419b3SSteven Rostedt		if (!$default) {
737a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
738a57419b3SSteven Rostedt		}
739a57419b3SSteven Rostedt		$num_tests_set = 1;
740a57419b3SSteven Rostedt	    }
741a57419b3SSteven Rostedt
742a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
7433d1cc414SSteven Rostedt		set_value($lvalue, $rvalue, $override, \%overrides, $name);
744a57419b3SSteven Rostedt	    } else {
745a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
7463d1cc414SSteven Rostedt		set_value($val, $rvalue, $override, \%overrides, $name);
747a57419b3SSteven Rostedt
748a57419b3SSteven Rostedt		if ($repeat > 1) {
749a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
750a57419b3SSteven Rostedt		}
751a57419b3SSteven Rostedt	    }
75277d942ceSSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
75377d942ceSSteven Rostedt	    next if ($skip);
75477d942ceSSteven Rostedt
75577d942ceSSteven Rostedt	    my $lvalue = $1;
75677d942ceSSteven Rostedt	    my $rvalue = $2;
75777d942ceSSteven Rostedt
75877d942ceSSteven Rostedt	    # process config variables.
75977d942ceSSteven Rostedt	    # Config variables are only active while reading the
76077d942ceSSteven Rostedt	    # config and can be defined anywhere. They also ignore
76177d942ceSSteven Rostedt	    # TEST_START and DEFAULTS, but are skipped if they are in
76277d942ceSSteven Rostedt	    # on of these sections that have SKIP defined.
76377d942ceSSteven Rostedt	    # The save variable can be
76477d942ceSSteven Rostedt	    # defined multiple times and the new one simply overrides
76577d942ceSSteven Rostedt	    # the prevous one.
76677d942ceSSteven Rostedt	    set_variable($lvalue, $rvalue);
76777d942ceSSteven Rostedt
768a57419b3SSteven Rostedt	} else {
769a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
770a57419b3SSteven Rostedt	}
7712545eb61SSteven Rostedt    }
7722545eb61SSteven Rostedt
773a57419b3SSteven Rostedt    if ($test_num) {
774a57419b3SSteven Rostedt	$test_num += $repeat - 1;
775a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
776a57419b3SSteven Rostedt    }
777a57419b3SSteven Rostedt
7782ed3b161SSteven Rostedt    close($in);
7792ed3b161SSteven Rostedt
7802ed3b161SSteven Rostedt    $$current_test_num = $test_num;
7812ed3b161SSteven Rostedt
7822ed3b161SSteven Rostedt    return $test_case;
7832ed3b161SSteven Rostedt}
7842ed3b161SSteven Rostedt
785c4261d0fSSteven Rostedtsub get_test_case {
786c4261d0fSSteven Rostedt	print "What test case would you like to run?\n";
787c4261d0fSSteven Rostedt	print " (build, install or boot)\n";
788c4261d0fSSteven Rostedt	print " Other tests are available but require editing the config file\n";
789c4261d0fSSteven Rostedt	my $ans = <STDIN>;
790c4261d0fSSteven Rostedt	chomp $ans;
791c4261d0fSSteven Rostedt	$default{"TEST_TYPE"} = $ans;
792c4261d0fSSteven Rostedt}
793c4261d0fSSteven Rostedt
7942ed3b161SSteven Rostedtsub read_config {
7952ed3b161SSteven Rostedt    my ($config) = @_;
7962ed3b161SSteven Rostedt
7972ed3b161SSteven Rostedt    my $test_case;
7982ed3b161SSteven Rostedt    my $test_num = 0;
7992ed3b161SSteven Rostedt
8002ed3b161SSteven Rostedt    $test_case = __read_config $config, \$test_num;
8012ed3b161SSteven Rostedt
8028d1491baSSteven Rostedt    # make sure we have all mandatory configs
8038d1491baSSteven Rostedt    get_ktest_configs;
8048d1491baSSteven Rostedt
8050df213caSSteven Rostedt    # was a test specified?
8060df213caSSteven Rostedt    if (!$test_case) {
8070df213caSSteven Rostedt	print "No test case specified.\n";
808c4261d0fSSteven Rostedt	get_test_case;
8090df213caSSteven Rostedt    }
8100df213caSSteven Rostedt
811a75fececSSteven Rostedt    # set any defaults
812a75fececSSteven Rostedt
813a75fececSSteven Rostedt    foreach my $default (keys %default) {
814a75fececSSteven Rostedt	if (!defined($opt{$default})) {
815a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
816a75fececSSteven Rostedt	}
817a75fececSSteven Rostedt    }
8182545eb61SSteven Rostedt}
8192545eb61SSteven Rostedt
82023715c3cSSteven Rostedtsub __eval_option {
82123715c3cSSteven Rostedt    my ($option, $i) = @_;
82223715c3cSSteven Rostedt
82323715c3cSSteven Rostedt    # Add space to evaluate the character before $
82423715c3cSSteven Rostedt    $option = " $option";
82523715c3cSSteven Rostedt    my $retval = "";
826f9dfb65bSRabin Vincent    my $repeated = 0;
827f9dfb65bSRabin Vincent    my $parent = 0;
828f9dfb65bSRabin Vincent
829f9dfb65bSRabin Vincent    foreach my $test (keys %repeat_tests) {
830f9dfb65bSRabin Vincent	if ($i >= $test &&
831f9dfb65bSRabin Vincent	    $i < $test + $repeat_tests{$test}) {
832f9dfb65bSRabin Vincent
833f9dfb65bSRabin Vincent	    $repeated = 1;
834f9dfb65bSRabin Vincent	    $parent = $test;
835f9dfb65bSRabin Vincent	    last;
836f9dfb65bSRabin Vincent	}
837f9dfb65bSRabin Vincent    }
83823715c3cSSteven Rostedt
83923715c3cSSteven Rostedt    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
84023715c3cSSteven Rostedt	my $start = $1;
84123715c3cSSteven Rostedt	my $var = $2;
84223715c3cSSteven Rostedt	my $end = $3;
84323715c3cSSteven Rostedt
84423715c3cSSteven Rostedt	# Append beginning of line
84523715c3cSSteven Rostedt	$retval = "$retval$start";
84623715c3cSSteven Rostedt
84723715c3cSSteven Rostedt	# If the iteration option OPT[$i] exists, then use that.
84823715c3cSSteven Rostedt	# otherwise see if the default OPT (without [$i]) exists.
84923715c3cSSteven Rostedt
85023715c3cSSteven Rostedt	my $o = "$var\[$i\]";
851f9dfb65bSRabin Vincent	my $parento = "$var\[$parent\]";
85223715c3cSSteven Rostedt
85323715c3cSSteven Rostedt	if (defined($opt{$o})) {
85423715c3cSSteven Rostedt	    $o = $opt{$o};
85523715c3cSSteven Rostedt	    $retval = "$retval$o";
856f9dfb65bSRabin Vincent	} elsif ($repeated && defined($opt{$parento})) {
857f9dfb65bSRabin Vincent	    $o = $opt{$parento};
858f9dfb65bSRabin Vincent	    $retval = "$retval$o";
85923715c3cSSteven Rostedt	} elsif (defined($opt{$var})) {
86023715c3cSSteven Rostedt	    $o = $opt{$var};
86123715c3cSSteven Rostedt	    $retval = "$retval$o";
86223715c3cSSteven Rostedt	} else {
86323715c3cSSteven Rostedt	    $retval = "$retval\$\{$var\}";
86423715c3cSSteven Rostedt	}
86523715c3cSSteven Rostedt
86623715c3cSSteven Rostedt	$option = $end;
86723715c3cSSteven Rostedt    }
86823715c3cSSteven Rostedt
86923715c3cSSteven Rostedt    $retval = "$retval$option";
87023715c3cSSteven Rostedt
87123715c3cSSteven Rostedt    $retval =~ s/^ //;
87223715c3cSSteven Rostedt
87323715c3cSSteven Rostedt    return $retval;
87423715c3cSSteven Rostedt}
87523715c3cSSteven Rostedt
87623715c3cSSteven Rostedtsub eval_option {
87723715c3cSSteven Rostedt    my ($option, $i) = @_;
87823715c3cSSteven Rostedt
87923715c3cSSteven Rostedt    my $prev = "";
88023715c3cSSteven Rostedt
88123715c3cSSteven Rostedt    # Since an option can evaluate to another option,
88223715c3cSSteven Rostedt    # keep iterating until we do not evaluate any more
88323715c3cSSteven Rostedt    # options.
88423715c3cSSteven Rostedt    my $r = 0;
88523715c3cSSteven Rostedt    while ($prev ne $option) {
88623715c3cSSteven Rostedt	# Check for recursive evaluations.
88723715c3cSSteven Rostedt	# 100 deep should be more than enough.
88823715c3cSSteven Rostedt	if ($r++ > 100) {
88923715c3cSSteven Rostedt	    die "Over 100 evaluations accurred with $option\n" .
89023715c3cSSteven Rostedt		"Check for recursive variables\n";
89123715c3cSSteven Rostedt	}
89223715c3cSSteven Rostedt	$prev = $option;
89323715c3cSSteven Rostedt	$option = __eval_option($option, $i);
89423715c3cSSteven Rostedt    }
89523715c3cSSteven Rostedt
89623715c3cSSteven Rostedt    return $option;
89723715c3cSSteven Rostedt}
89823715c3cSSteven Rostedt
899d1e2f22aSSteven Rostedtsub _logit {
9002545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
9012545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
9022545eb61SSteven Rostedt	print OUT @_;
9032545eb61SSteven Rostedt	close(OUT);
9042545eb61SSteven Rostedt    }
9052545eb61SSteven Rostedt}
9062545eb61SSteven Rostedt
907d1e2f22aSSteven Rostedtsub logit {
908d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
909d1e2f22aSSteven Rostedt	_logit @_;
910d1e2f22aSSteven Rostedt    } else {
911d1e2f22aSSteven Rostedt	print @_;
912d1e2f22aSSteven Rostedt    }
913d1e2f22aSSteven Rostedt}
914d1e2f22aSSteven Rostedt
9155f9b6cedSSteven Rostedtsub doprint {
9165f9b6cedSSteven Rostedt    print @_;
917d1e2f22aSSteven Rostedt    _logit @_;
9185f9b6cedSSteven Rostedt}
9195f9b6cedSSteven Rostedt
9207faafbd6SSteven Rostedtsub run_command;
9212728be41SAndrew Jonessub start_monitor;
9222728be41SAndrew Jonessub end_monitor;
9232728be41SAndrew Jonessub wait_for_monitor;
9247faafbd6SSteven Rostedt
9257faafbd6SSteven Rostedtsub reboot {
9262728be41SAndrew Jones    my ($time) = @_;
9272728be41SAndrew Jones
9282b803365SSteven Rostedt    if (defined($time)) {
9292b803365SSteven Rostedt	start_monitor;
9302b803365SSteven Rostedt	# flush out current monitor
9312b803365SSteven Rostedt	# May contain the reboot success line
9322b803365SSteven Rostedt	wait_for_monitor 1;
9332b803365SSteven Rostedt    }
9342b803365SSteven Rostedt
9357faafbd6SSteven Rostedt    # try to reboot normally
936e48c5293SSteven Rostedt    if (run_command $reboot) {
937576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
938576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
939576f627cSSteven Rostedt	    run_command "$power_cycle";
940576f627cSSteven Rostedt	}
941576f627cSSteven Rostedt    } else {
9427faafbd6SSteven Rostedt	# nope? power cycle it.
943a75fececSSteven Rostedt	run_command "$power_cycle";
9447faafbd6SSteven Rostedt    }
9452728be41SAndrew Jones
9462728be41SAndrew Jones    if (defined($time)) {
9472b803365SSteven Rostedt	wait_for_monitor($time, $reboot_success_line);
9482728be41SAndrew Jones	end_monitor;
9492728be41SAndrew Jones    }
9507faafbd6SSteven Rostedt}
9517faafbd6SSteven Rostedt
952576f627cSSteven Rostedtsub do_not_reboot {
953576f627cSSteven Rostedt    my $i = $iteration;
954576f627cSSteven Rostedt
9554ab1cce5SSteven Rostedt    return $test_type eq "build" || $no_reboot ||
956576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
957576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
958576f627cSSteven Rostedt}
959576f627cSSteven Rostedt
9605c42fc5bSSteven Rostedtsub dodie {
9615a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
9625c42fc5bSSteven Rostedt
963576f627cSSteven Rostedt    my $i = $iteration;
964576f627cSSteven Rostedt
965576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
966576f627cSSteven Rostedt
96775c3fda7SSteven Rostedt	doprint "REBOOTING\n";
9687faafbd6SSteven Rostedt	reboot;
96975c3fda7SSteven Rostedt
970a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
9715c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
972a75fececSSteven Rostedt	`$power_off`;
9735c42fc5bSSteven Rostedt    }
97475c3fda7SSteven Rostedt
975f80802cbSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
976f80802cbSSteven Rostedt	print " See $opt{LOG_FILE} for more info.\n";
977f80802cbSSteven Rostedt    }
978f80802cbSSteven Rostedt
979576f627cSSteven Rostedt    die @_, "\n";
9805c42fc5bSSteven Rostedt}
9815c42fc5bSSteven Rostedt
9827faafbd6SSteven Rostedtsub open_console {
9837faafbd6SSteven Rostedt    my ($fp) = @_;
9847faafbd6SSteven Rostedt
9857faafbd6SSteven Rostedt    my $flags;
9867faafbd6SSteven Rostedt
987a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
988a75fececSSteven Rostedt	dodie "Can't open console $console";
9897faafbd6SSteven Rostedt
9907faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
991576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
9927faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
993576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
9947faafbd6SSteven Rostedt
9957faafbd6SSteven Rostedt    return $pid;
9967faafbd6SSteven Rostedt}
9977faafbd6SSteven Rostedt
9987faafbd6SSteven Rostedtsub close_console {
9997faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
10007faafbd6SSteven Rostedt
10017faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
10027faafbd6SSteven Rostedt    kill 2, $pid;
10037faafbd6SSteven Rostedt
10047faafbd6SSteven Rostedt    print "closing!\n";
10057faafbd6SSteven Rostedt    close($fp);
10067faafbd6SSteven Rostedt}
10077faafbd6SSteven Rostedt
10087faafbd6SSteven Rostedtsub start_monitor {
10097faafbd6SSteven Rostedt    if ($monitor_cnt++) {
10107faafbd6SSteven Rostedt	return;
10117faafbd6SSteven Rostedt    }
10127faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
10137faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
1014a75fececSSteven Rostedt
1015a75fececSSteven Rostedt    return;
1016a75fececSSteven Rostedt
1017a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
10187faafbd6SSteven Rostedt}
10197faafbd6SSteven Rostedt
10207faafbd6SSteven Rostedtsub end_monitor {
10217faafbd6SSteven Rostedt    if (--$monitor_cnt) {
10227faafbd6SSteven Rostedt	return;
10237faafbd6SSteven Rostedt    }
10247faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
10257faafbd6SSteven Rostedt}
10267faafbd6SSteven Rostedt
10277faafbd6SSteven Rostedtsub wait_for_monitor {
10282b803365SSteven Rostedt    my ($time, $stop) = @_;
10292b803365SSteven Rostedt    my $full_line = "";
10307faafbd6SSteven Rostedt    my $line;
10312b803365SSteven Rostedt    my $booted = 0;
10327faafbd6SSteven Rostedt
1033a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
10347faafbd6SSteven Rostedt
10357faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
10362b803365SSteven Rostedt    while (!$booted) {
10377faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
10382b803365SSteven Rostedt	last if (!defined($line));
10392b803365SSteven Rostedt	print "$line";
10402b803365SSteven Rostedt	$full_line .= $line;
10412b803365SSteven Rostedt
10422b803365SSteven Rostedt	if (defined($stop) && $full_line =~ /$stop/) {
10432b803365SSteven Rostedt	    doprint "wait for monitor detected $stop\n";
10442b803365SSteven Rostedt	    $booted = 1;
10452b803365SSteven Rostedt	}
10462b803365SSteven Rostedt
10472b803365SSteven Rostedt	if ($line =~ /\n/) {
10482b803365SSteven Rostedt	    $full_line = "";
10492b803365SSteven Rostedt	}
10502b803365SSteven Rostedt    }
1051a75fececSSteven Rostedt    print "** Monitor flushed **\n";
10527faafbd6SSteven Rostedt}
10537faafbd6SSteven Rostedt
1054de5b6e3bSRabin Vincentsub save_logs {
1055de5b6e3bSRabin Vincent	my ($result, $basedir) = @_;
1056de5b6e3bSRabin Vincent	my @t = localtime;
1057de5b6e3bSRabin Vincent	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1058de5b6e3bSRabin Vincent		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1059de5b6e3bSRabin Vincent
1060de5b6e3bSRabin Vincent	my $type = $build_type;
1061de5b6e3bSRabin Vincent	if ($type =~ /useconfig/) {
1062de5b6e3bSRabin Vincent	    $type = "useconfig";
1063de5b6e3bSRabin Vincent	}
1064de5b6e3bSRabin Vincent
1065de5b6e3bSRabin Vincent	my $dir = "$machine-$test_type-$type-$result-$date";
1066de5b6e3bSRabin Vincent
1067de5b6e3bSRabin Vincent	$dir = "$basedir/$dir";
1068de5b6e3bSRabin Vincent
1069de5b6e3bSRabin Vincent	if (!-d $dir) {
1070de5b6e3bSRabin Vincent	    mkpath($dir) or
1071de5b6e3bSRabin Vincent		die "can't create $dir";
1072de5b6e3bSRabin Vincent	}
1073de5b6e3bSRabin Vincent
1074de5b6e3bSRabin Vincent	my %files = (
1075de5b6e3bSRabin Vincent		"config" => $output_config,
1076de5b6e3bSRabin Vincent		"buildlog" => $buildlog,
1077de5b6e3bSRabin Vincent		"dmesg" => $dmesg,
1078de5b6e3bSRabin Vincent		"testlog" => $testlog,
1079de5b6e3bSRabin Vincent	);
1080de5b6e3bSRabin Vincent
1081de5b6e3bSRabin Vincent	while (my ($name, $source) = each(%files)) {
1082de5b6e3bSRabin Vincent		if (-f "$source") {
1083de5b6e3bSRabin Vincent			cp "$source", "$dir/$name" or
1084de5b6e3bSRabin Vincent				die "failed to copy $source";
1085de5b6e3bSRabin Vincent		}
1086de5b6e3bSRabin Vincent	}
1087de5b6e3bSRabin Vincent
1088de5b6e3bSRabin Vincent	doprint "*** Saved info to $dir ***\n";
1089de5b6e3bSRabin Vincent}
1090de5b6e3bSRabin Vincent
10912b7d9b21SSteven Rostedtsub fail {
10922b7d9b21SSteven Rostedt
1093a75fececSSteven Rostedt	if ($die_on_failure) {
10942b7d9b21SSteven Rostedt		dodie @_;
10952b7d9b21SSteven Rostedt	}
10962b7d9b21SSteven Rostedt
1097a75fececSSteven Rostedt	doprint "FAILED\n";
10987faafbd6SSteven Rostedt
1099576f627cSSteven Rostedt	my $i = $iteration;
1100576f627cSSteven Rostedt
1101a75fececSSteven Rostedt	# no need to reboot for just building.
1102576f627cSSteven Rostedt	if (!do_not_reboot) {
11037faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
11042728be41SAndrew Jones	    reboot $sleep_time;
1105a75fececSSteven Rostedt	}
11067faafbd6SSteven Rostedt
11079064af52SSteven Rostedt	my $name = "";
11089064af52SSteven Rostedt
11099064af52SSteven Rostedt	if (defined($test_name)) {
11109064af52SSteven Rostedt	    $name = " ($test_name)";
11119064af52SSteven Rostedt	}
11129064af52SSteven Rostedt
1113576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1114576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
11159064af52SSteven Rostedt	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1116576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1117576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1118a75fececSSteven Rostedt
1119de5b6e3bSRabin Vincent	if (defined($store_failures)) {
1120de5b6e3bSRabin Vincent	    save_logs "fail", $store_failures;
1121cccae1a6SSteven Rostedt        }
1122cccae1a6SSteven Rostedt
11232b7d9b21SSteven Rostedt	return 1;
11242b7d9b21SSteven Rostedt}
11252b7d9b21SSteven Rostedt
11262545eb61SSteven Rostedtsub run_command {
11272545eb61SSteven Rostedt    my ($command) = @_;
1128d6ce2a0bSSteven Rostedt    my $dolog = 0;
1129d6ce2a0bSSteven Rostedt    my $dord = 0;
1130d6ce2a0bSSteven Rostedt    my $pid;
1131d6ce2a0bSSteven Rostedt
1132e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
1133e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
1134e48c5293SSteven Rostedt
1135d6ce2a0bSSteven Rostedt    doprint("$command ... ");
1136d6ce2a0bSSteven Rostedt
1137d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
11382b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
11392545eb61SSteven Rostedt
11402545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1141d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
1142d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
1143d6ce2a0bSSteven Rostedt	$dolog = 1;
11446c5ee0beSSteven Rostedt    }
11456c5ee0beSSteven Rostedt
11466c5ee0beSSteven Rostedt    if (defined($redirect)) {
1147d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
1148d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
1149d6ce2a0bSSteven Rostedt	$dord = 1;
11502545eb61SSteven Rostedt    }
11512545eb61SSteven Rostedt
1152d6ce2a0bSSteven Rostedt    while (<CMD>) {
1153d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
1154d6ce2a0bSSteven Rostedt	print RD  if ($dord);
1155d6ce2a0bSSteven Rostedt    }
11562545eb61SSteven Rostedt
1157d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
11582545eb61SSteven Rostedt    my $failed = $?;
11592545eb61SSteven Rostedt
1160d6ce2a0bSSteven Rostedt    close(CMD);
1161d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
1162d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
1163d6ce2a0bSSteven Rostedt
11642545eb61SSteven Rostedt    if ($failed) {
11652545eb61SSteven Rostedt	doprint "FAILED!\n";
11662545eb61SSteven Rostedt    } else {
11672545eb61SSteven Rostedt	doprint "SUCCESS\n";
11682545eb61SSteven Rostedt    }
11692545eb61SSteven Rostedt
11705f9b6cedSSteven Rostedt    return !$failed;
11715f9b6cedSSteven Rostedt}
11725f9b6cedSSteven Rostedt
1173e48c5293SSteven Rostedtsub run_ssh {
1174e48c5293SSteven Rostedt    my ($cmd) = @_;
1175e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
1176e48c5293SSteven Rostedt
1177e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1178e48c5293SSteven Rostedt    return run_command "$cp_exec";
1179e48c5293SSteven Rostedt}
1180e48c5293SSteven Rostedt
1181e48c5293SSteven Rostedtsub run_scp {
1182e48c5293SSteven Rostedt    my ($src, $dst) = @_;
1183e48c5293SSteven Rostedt    my $cp_scp = $scp_to_target;
1184e48c5293SSteven Rostedt
1185e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
1186e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
1187e48c5293SSteven Rostedt
1188e48c5293SSteven Rostedt    return run_command "$cp_scp";
1189e48c5293SSteven Rostedt}
1190e48c5293SSteven Rostedt
11915f9b6cedSSteven Rostedtsub get_grub_index {
11925f9b6cedSSteven Rostedt
1193a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
1194a75fececSSteven Rostedt	return;
1195a75fececSSteven Rostedt    }
11965a391fbfSSteven Rostedt    return if (defined($grub_number));
11975f9b6cedSSteven Rostedt
11985f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
11995f9b6cedSSteven Rostedt    $grub_number = -1;
1200e48c5293SSteven Rostedt
1201e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
1202e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
1203e48c5293SSteven Rostedt
1204e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
12055f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
1206e48c5293SSteven Rostedt
1207eaa1fe25SSteven Rostedt    my $found = 0;
1208eaa1fe25SSteven Rostedt
12095f9b6cedSSteven Rostedt    while (<IN>) {
1210a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
12115f9b6cedSSteven Rostedt	    $grub_number++;
1212eaa1fe25SSteven Rostedt	    $found = 1;
12135f9b6cedSSteven Rostedt	    last;
12145f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
12155f9b6cedSSteven Rostedt	    $grub_number++;
12165f9b6cedSSteven Rostedt	}
12175f9b6cedSSteven Rostedt    }
12185f9b6cedSSteven Rostedt    close(IN);
12195f9b6cedSSteven Rostedt
1220a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
1221eaa1fe25SSteven Rostedt	if (!$found);
12225f9b6cedSSteven Rostedt    doprint "$grub_number\n";
12232545eb61SSteven Rostedt}
12242545eb61SSteven Rostedt
12252545eb61SSteven Rostedtsub wait_for_input
12262545eb61SSteven Rostedt{
12272545eb61SSteven Rostedt    my ($fp, $time) = @_;
12282545eb61SSteven Rostedt    my $rin;
12292545eb61SSteven Rostedt    my $ready;
12302545eb61SSteven Rostedt    my $line;
12312545eb61SSteven Rostedt    my $ch;
12322545eb61SSteven Rostedt
12332545eb61SSteven Rostedt    if (!defined($time)) {
12342545eb61SSteven Rostedt	$time = $timeout;
12352545eb61SSteven Rostedt    }
12362545eb61SSteven Rostedt
12372545eb61SSteven Rostedt    $rin = '';
12382545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
12392545eb61SSteven Rostedt    $ready = select($rin, undef, undef, $time);
12402545eb61SSteven Rostedt
12412545eb61SSteven Rostedt    $line = "";
12422545eb61SSteven Rostedt
12432545eb61SSteven Rostedt    # try to read one char at a time
12442545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
12452545eb61SSteven Rostedt	$line .= $ch;
12462545eb61SSteven Rostedt	last if ($ch eq "\n");
12472545eb61SSteven Rostedt    }
12482545eb61SSteven Rostedt
12492545eb61SSteven Rostedt    if (!length($line)) {
12502545eb61SSteven Rostedt	return undef;
12512545eb61SSteven Rostedt    }
12522545eb61SSteven Rostedt
12532545eb61SSteven Rostedt    return $line;
12542545eb61SSteven Rostedt}
12552545eb61SSteven Rostedt
125675c3fda7SSteven Rostedtsub reboot_to {
1257a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
1258c54367f9SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
1259c54367f9SSteven Rostedt	reboot;
1260a75fececSSteven Rostedt	return;
1261a75fececSSteven Rostedt    }
1262a75fececSSteven Rostedt
1263a75fececSSteven Rostedt    run_command "$reboot_script";
12642545eb61SSteven Rostedt}
12652545eb61SSteven Rostedt
1266a57419b3SSteven Rostedtsub get_sha1 {
1267a57419b3SSteven Rostedt    my ($commit) = @_;
1268a57419b3SSteven Rostedt
1269a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
1270a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
1271a57419b3SSteven Rostedt    my $ret = $?;
1272a57419b3SSteven Rostedt
1273a57419b3SSteven Rostedt    logit $sha1;
1274a57419b3SSteven Rostedt
1275a57419b3SSteven Rostedt    if ($ret) {
1276a57419b3SSteven Rostedt	doprint "FAILED\n";
1277a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
1278a57419b3SSteven Rostedt    }
1279a57419b3SSteven Rostedt
1280a57419b3SSteven Rostedt    print "SUCCESS\n";
1281a57419b3SSteven Rostedt
1282a57419b3SSteven Rostedt    chomp $sha1;
1283a57419b3SSteven Rostedt
1284a57419b3SSteven Rostedt    return $sha1;
1285a57419b3SSteven Rostedt}
1286a57419b3SSteven Rostedt
12875a391fbfSSteven Rostedtsub monitor {
12882545eb61SSteven Rostedt    my $booted = 0;
12892545eb61SSteven Rostedt    my $bug = 0;
12905c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
12912b7d9b21SSteven Rostedt    my $loops;
12922545eb61SSteven Rostedt
12937faafbd6SSteven Rostedt    wait_for_monitor 5;
12942545eb61SSteven Rostedt
12952545eb61SSteven Rostedt    my $line;
12962545eb61SSteven Rostedt    my $full_line = "";
12972545eb61SSteven Rostedt
12987faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
12997faafbd6SSteven Rostedt	die "unable to write to $dmesg";
13002545eb61SSteven Rostedt
130175c3fda7SSteven Rostedt    reboot_to;
13022545eb61SSteven Rostedt
13031c8a617aSSteven Rostedt    my $success_start;
13041c8a617aSSteven Rostedt    my $failure_start;
13052d01b26aSSteven Rostedt    my $monitor_start = time;
13062d01b26aSSteven Rostedt    my $done = 0;
1307f1a5b962SSteven Rostedt    my $version_found = 0;
13081c8a617aSSteven Rostedt
13092d01b26aSSteven Rostedt    while (!$done) {
13102545eb61SSteven Rostedt
1311ecaf8e52SSteven Rostedt	if ($bug && defined($stop_after_failure) &&
1312ecaf8e52SSteven Rostedt	    $stop_after_failure >= 0) {
1313ecaf8e52SSteven Rostedt	    my $time = $stop_after_failure - (time - $failure_start);
1314ecaf8e52SSteven Rostedt	    $line = wait_for_input($monitor_fp, $time);
1315ecaf8e52SSteven Rostedt	    if (!defined($line)) {
1316ecaf8e52SSteven Rostedt		doprint "bug timed out after $booted_timeout seconds\n";
1317ecaf8e52SSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1318ecaf8e52SSteven Rostedt		last;
1319ecaf8e52SSteven Rostedt	    }
1320ecaf8e52SSteven Rostedt	} elsif ($booted) {
1321a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
1322cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1323cd4f1d53SSteven Rostedt		my $s = $booted_timeout == 1 ? "" : "s";
1324cd4f1d53SSteven Rostedt		doprint "Successful boot found: break after $booted_timeout second$s\n";
1325cd4f1d53SSteven Rostedt		last;
1326cd4f1d53SSteven Rostedt	    }
13272b7d9b21SSteven Rostedt	} else {
13287faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
1329cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1330cd4f1d53SSteven Rostedt		my $s = $timeout == 1 ? "" : "s";
1331cd4f1d53SSteven Rostedt		doprint "Timed out after $timeout second$s\n";
1332cd4f1d53SSteven Rostedt		last;
13332b7d9b21SSteven Rostedt	    }
1334cd4f1d53SSteven Rostedt	}
13352545eb61SSteven Rostedt
13362545eb61SSteven Rostedt	doprint $line;
13377faafbd6SSteven Rostedt	print DMESG $line;
13382545eb61SSteven Rostedt
13392545eb61SSteven Rostedt	# we are not guaranteed to get a full line
13402545eb61SSteven Rostedt	$full_line .= $line;
13412545eb61SSteven Rostedt
1342a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
13432545eb61SSteven Rostedt	    $booted = 1;
13441c8a617aSSteven Rostedt	    $success_start = time;
13451c8a617aSSteven Rostedt	}
13461c8a617aSSteven Rostedt
13471c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
13481c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
13491c8a617aSSteven Rostedt	    my $now = time;
13501c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
13511c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
13521c8a617aSSteven Rostedt		last;
13531c8a617aSSteven Rostedt	    }
13542545eb61SSteven Rostedt	}
13552545eb61SSteven Rostedt
13565c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
13575c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
13585c42fc5bSSteven Rostedt	}
13595c42fc5bSSteven Rostedt
13602545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
13614651920eSSteven Rostedt	    if (!$bug && !$skip_call_trace) {
13621c8a617aSSteven Rostedt		$bug = 1;
13631c8a617aSSteven Rostedt		$failure_start = time;
13641c8a617aSSteven Rostedt	    }
13651c8a617aSSteven Rostedt	}
13661c8a617aSSteven Rostedt
13671c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
13681c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
13691c8a617aSSteven Rostedt	    my $now = time;
13701c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
13711c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
13721c8a617aSSteven Rostedt		last;
13731c8a617aSSteven Rostedt	    }
13745c42fc5bSSteven Rostedt	}
13755c42fc5bSSteven Rostedt
13765c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
13775c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
13785c42fc5bSSteven Rostedt	}
13795c42fc5bSSteven Rostedt
13805c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
138110abf118SSteven Rostedt	    $failure_start = time;
13822545eb61SSteven Rostedt	    $bug = 1;
13832545eb61SSteven Rostedt	}
13842545eb61SSteven Rostedt
1385f1a5b962SSteven Rostedt	# Detect triple faults by testing the banner
1386f1a5b962SSteven Rostedt	if ($full_line =~ /\bLinux version (\S+).*\n/) {
1387f1a5b962SSteven Rostedt	    if ($1 eq $version) {
1388f1a5b962SSteven Rostedt		$version_found = 1;
1389f1a5b962SSteven Rostedt	    } elsif ($version_found && $detect_triplefault) {
1390f1a5b962SSteven Rostedt		# We already booted into the kernel we are testing,
1391f1a5b962SSteven Rostedt		# but now we booted into another kernel?
1392f1a5b962SSteven Rostedt		# Consider this a triple fault.
1393f1a5b962SSteven Rostedt		doprint "Aleady booted in Linux kernel $version, but now\n";
1394f1a5b962SSteven Rostedt		doprint "we booted into Linux kernel $1.\n";
1395f1a5b962SSteven Rostedt		doprint "Assuming that this is a triple fault.\n";
1396f1a5b962SSteven Rostedt		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1397f1a5b962SSteven Rostedt		last;
1398f1a5b962SSteven Rostedt	    }
1399f1a5b962SSteven Rostedt	}
1400f1a5b962SSteven Rostedt
14012545eb61SSteven Rostedt	if ($line =~ /\n/) {
14022545eb61SSteven Rostedt	    $full_line = "";
14032545eb61SSteven Rostedt	}
14042d01b26aSSteven Rostedt
14052d01b26aSSteven Rostedt	if ($stop_test_after > 0 && !$booted && !$bug) {
14062d01b26aSSteven Rostedt	    if (time - $monitor_start > $stop_test_after) {
14074d62bf51SSteven Rostedt		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
14082d01b26aSSteven Rostedt		$done = 1;
14092d01b26aSSteven Rostedt	    }
14102d01b26aSSteven Rostedt	}
14112545eb61SSteven Rostedt    }
14122545eb61SSteven Rostedt
14137faafbd6SSteven Rostedt    close(DMESG);
14142545eb61SSteven Rostedt
14152545eb61SSteven Rostedt    if ($bug) {
14162b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
1417576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
14182545eb61SSteven Rostedt    }
14195f9b6cedSSteven Rostedt
1420a75fececSSteven Rostedt    if (!$booted) {
1421a75fececSSteven Rostedt	return 0 if ($in_bisect);
1422576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
1423a75fececSSteven Rostedt    }
1424a75fececSSteven Rostedt
14252b7d9b21SSteven Rostedt    return 1;
14262545eb61SSteven Rostedt}
14272545eb61SSteven Rostedt
1428db05cfefSSteven Rostedtsub do_post_install {
1429db05cfefSSteven Rostedt
1430db05cfefSSteven Rostedt    return if (!defined($post_install));
1431db05cfefSSteven Rostedt
1432db05cfefSSteven Rostedt    my $cp_post_install = $post_install;
1433db05cfefSSteven Rostedt    $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
1434db05cfefSSteven Rostedt    run_command "$cp_post_install" or
1435db05cfefSSteven Rostedt	dodie "Failed to run post install";
1436db05cfefSSteven Rostedt}
1437db05cfefSSteven Rostedt
14382545eb61SSteven Rostedtsub install {
14392545eb61SSteven Rostedt
1440e0a8742eSSteven Rostedt    return if ($no_install);
1441e0a8742eSSteven Rostedt
1442e48c5293SSteven Rostedt    run_scp "$outputdir/$build_target", "$target_image" or
14435c42fc5bSSteven Rostedt	dodie "failed to copy image";
14445f9b6cedSSteven Rostedt
14455f9b6cedSSteven Rostedt    my $install_mods = 0;
14465f9b6cedSSteven Rostedt
14475f9b6cedSSteven Rostedt    # should we process modules?
14485f9b6cedSSteven Rostedt    $install_mods = 0;
144951ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
14505f9b6cedSSteven Rostedt    while (<IN>) {
14515f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
14525f9b6cedSSteven Rostedt	    $install_mods = 1 if (defined($1));
14535f9b6cedSSteven Rostedt	    last;
14545f9b6cedSSteven Rostedt	}
14555f9b6cedSSteven Rostedt    }
14565f9b6cedSSteven Rostedt    close(IN);
14575f9b6cedSSteven Rostedt
14585f9b6cedSSteven Rostedt    if (!$install_mods) {
1459db05cfefSSteven Rostedt	do_post_install;
14605f9b6cedSSteven Rostedt	doprint "No modules needed\n";
14615f9b6cedSSteven Rostedt	return;
14622545eb61SSteven Rostedt    }
14632545eb61SSteven Rostedt
1464a75fececSSteven Rostedt    run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
14655f9b6cedSSteven Rostedt	dodie "Failed to install modules";
14665f9b6cedSSteven Rostedt
14672545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
1468a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
14692545eb61SSteven Rostedt
1470e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
14715c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
14722545eb61SSteven Rostedt
14735c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
1474a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
14755c42fc5bSSteven Rostedt	dodie "making tarball";
14765c42fc5bSSteven Rostedt
1477e48c5293SSteven Rostedt    run_scp "$tmpdir/$modtar", "/tmp" or
14785c42fc5bSSteven Rostedt	dodie "failed to copy modules";
14795c42fc5bSSteven Rostedt
1480a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
14815c42fc5bSSteven Rostedt
1482e7b13441SSteven Rostedt    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
14835c42fc5bSSteven Rostedt	dodie "failed to tar modules";
14845c42fc5bSSteven Rostedt
1485e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
14868b37ca8cSSteven Rostedt
1487db05cfefSSteven Rostedt    do_post_install;
14882545eb61SSteven Rostedt}
14892545eb61SSteven Rostedt
1490ddf607e5SSteven Rostedtsub get_version {
1491ddf607e5SSteven Rostedt    # get the release name
1492ddf607e5SSteven Rostedt    doprint "$make kernelrelease ... ";
1493ddf607e5SSteven Rostedt    $version = `$make kernelrelease | tail -1`;
1494ddf607e5SSteven Rostedt    chomp($version);
1495ddf607e5SSteven Rostedt    doprint "$version\n";
1496ddf607e5SSteven Rostedt}
1497ddf607e5SSteven Rostedt
1498ddf607e5SSteven Rostedtsub start_monitor_and_boot {
14999f7424ccSSteven Rostedt    # Make sure the stable kernel has finished booting
15009f7424ccSSteven Rostedt    start_monitor;
15019f7424ccSSteven Rostedt    wait_for_monitor 5;
15029f7424ccSSteven Rostedt    end_monitor;
15039f7424ccSSteven Rostedt
1504ddf607e5SSteven Rostedt    get_grub_index;
1505ddf607e5SSteven Rostedt    get_version;
1506ddf607e5SSteven Rostedt    install;
1507ddf607e5SSteven Rostedt
1508ddf607e5SSteven Rostedt    start_monitor;
1509ddf607e5SSteven Rostedt    return monitor;
1510ddf607e5SSteven Rostedt}
1511ddf607e5SSteven Rostedt
15126c5ee0beSSteven Rostedtsub check_buildlog {
15136c5ee0beSSteven Rostedt    my ($patch) = @_;
15146c5ee0beSSteven Rostedt
15156c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
15166c5ee0beSSteven Rostedt
15176c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
15186c5ee0beSSteven Rostedt	dodie "failed to show $patch";
15196c5ee0beSSteven Rostedt    while (<IN>) {
15206c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
15216c5ee0beSSteven Rostedt	    chomp $1;
15226c5ee0beSSteven Rostedt	    $files[$#files] = $1;
15236c5ee0beSSteven Rostedt	}
15246c5ee0beSSteven Rostedt    }
15256c5ee0beSSteven Rostedt    close(IN);
15266c5ee0beSSteven Rostedt
15276c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
15286c5ee0beSSteven Rostedt    while (<IN>) {
15296c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
15306c5ee0beSSteven Rostedt	    my $err = $1;
15316c5ee0beSSteven Rostedt	    foreach my $file (@files) {
1532a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
15336c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
15342b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
15356c5ee0beSSteven Rostedt		}
15366c5ee0beSSteven Rostedt	    }
15376c5ee0beSSteven Rostedt	}
15386c5ee0beSSteven Rostedt    }
15396c5ee0beSSteven Rostedt    close(IN);
15402b7d9b21SSteven Rostedt
15412b7d9b21SSteven Rostedt    return 1;
15426c5ee0beSSteven Rostedt}
15436c5ee0beSSteven Rostedt
1544fcb3f16aSSteven Rostedtsub apply_min_config {
1545fcb3f16aSSteven Rostedt    my $outconfig = "$output_config.new";
1546612b9e9bSSteven Rostedt
1547fcb3f16aSSteven Rostedt    # Read the config file and remove anything that
1548fcb3f16aSSteven Rostedt    # is in the force_config hash (from minconfig and others)
1549fcb3f16aSSteven Rostedt    # then add the force config back.
1550fcb3f16aSSteven Rostedt
1551fcb3f16aSSteven Rostedt    doprint "Applying minimum configurations into $output_config.new\n";
1552fcb3f16aSSteven Rostedt
1553fcb3f16aSSteven Rostedt    open (OUT, ">$outconfig") or
1554fcb3f16aSSteven Rostedt	dodie "Can't create $outconfig";
1555fcb3f16aSSteven Rostedt
1556fcb3f16aSSteven Rostedt    if (-f $output_config) {
1557fcb3f16aSSteven Rostedt	open (IN, $output_config) or
1558fcb3f16aSSteven Rostedt	    dodie "Failed to open $output_config";
1559fcb3f16aSSteven Rostedt	while (<IN>) {
1560fcb3f16aSSteven Rostedt	    if (/^(# )?(CONFIG_[^\s=]*)/) {
1561fcb3f16aSSteven Rostedt		next if (defined($force_config{$2}));
1562fcb3f16aSSteven Rostedt	    }
1563fcb3f16aSSteven Rostedt	    print OUT;
1564fcb3f16aSSteven Rostedt	}
1565fcb3f16aSSteven Rostedt	close IN;
1566fcb3f16aSSteven Rostedt    }
1567fcb3f16aSSteven Rostedt    foreach my $config (keys %force_config) {
1568fcb3f16aSSteven Rostedt	print OUT "$force_config{$config}\n";
1569fcb3f16aSSteven Rostedt    }
1570fcb3f16aSSteven Rostedt    close OUT;
1571fcb3f16aSSteven Rostedt
1572fcb3f16aSSteven Rostedt    run_command "mv $outconfig $output_config";
1573fcb3f16aSSteven Rostedt}
1574fcb3f16aSSteven Rostedt
1575fcb3f16aSSteven Rostedtsub make_oldconfig {
1576fcb3f16aSSteven Rostedt
15774c4ab120SSteven Rostedt    my @force_list = keys %force_config;
15784c4ab120SSteven Rostedt
15794c4ab120SSteven Rostedt    if ($#force_list >= 0) {
1580fcb3f16aSSteven Rostedt	apply_min_config;
15814c4ab120SSteven Rostedt    }
1582fcb3f16aSSteven Rostedt
1583fcb3f16aSSteven Rostedt    if (!run_command "$make oldnoconfig") {
1584612b9e9bSSteven Rostedt	# Perhaps oldnoconfig doesn't exist in this version of the kernel
1585612b9e9bSSteven Rostedt	# try a yes '' | oldconfig
1586612b9e9bSSteven Rostedt	doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1587fcb3f16aSSteven Rostedt	run_command "yes '' | $make oldconfig" or
1588612b9e9bSSteven Rostedt	    dodie "failed make config oldconfig";
1589612b9e9bSSteven Rostedt    }
1590612b9e9bSSteven Rostedt}
1591612b9e9bSSteven Rostedt
1592fcb3f16aSSteven Rostedt# read a config file and use this to force new configs.
1593fcb3f16aSSteven Rostedtsub load_force_config {
1594fcb3f16aSSteven Rostedt    my ($config) = @_;
1595fcb3f16aSSteven Rostedt
1596fcb3f16aSSteven Rostedt    open(IN, $config) or
1597fcb3f16aSSteven Rostedt	dodie "failed to read $config";
1598fcb3f16aSSteven Rostedt    while (<IN>) {
1599fcb3f16aSSteven Rostedt	chomp;
1600fcb3f16aSSteven Rostedt	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1601fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1602fcb3f16aSSteven Rostedt	} elsif (/^# (CONFIG_\S*) is not set/) {
1603fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1604fcb3f16aSSteven Rostedt	}
1605fcb3f16aSSteven Rostedt    }
1606fcb3f16aSSteven Rostedt    close IN;
1607fcb3f16aSSteven Rostedt}
1608fcb3f16aSSteven Rostedt
16092545eb61SSteven Rostedtsub build {
16102545eb61SSteven Rostedt    my ($type) = @_;
16112545eb61SSteven Rostedt
16127faafbd6SSteven Rostedt    unlink $buildlog;
16137faafbd6SSteven Rostedt
16144ab1cce5SSteven Rostedt    # Failed builds should not reboot the target
16154ab1cce5SSteven Rostedt    my $save_no_reboot = $no_reboot;
16164ab1cce5SSteven Rostedt    $no_reboot = 1;
16174ab1cce5SSteven Rostedt
16180bd6c1a3SSteven Rostedt    if (defined($pre_build)) {
16190bd6c1a3SSteven Rostedt	my $ret = run_command $pre_build;
16200bd6c1a3SSteven Rostedt	if (!$ret && defined($pre_build_die) &&
16210bd6c1a3SSteven Rostedt	    $pre_build_die) {
16220bd6c1a3SSteven Rostedt	    dodie "failed to pre_build\n";
16230bd6c1a3SSteven Rostedt	}
16240bd6c1a3SSteven Rostedt    }
16250bd6c1a3SSteven Rostedt
162675c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
162751ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
162875c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
16295f9b6cedSSteven Rostedt
163075c3fda7SSteven Rostedt	$type = "oldconfig";
163175c3fda7SSteven Rostedt    }
163275c3fda7SSteven Rostedt
16335c42fc5bSSteven Rostedt    # old config can ask questions
16345c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
16359386c6abSSteven Rostedt	$type = "oldnoconfig";
163675c3fda7SSteven Rostedt
163775c3fda7SSteven Rostedt	# allow for empty configs
163851ad1dd1SSteven Rostedt	run_command "touch $output_config";
163975c3fda7SSteven Rostedt
164013488231SAndrew Jones	if (!$noclean) {
164151ad1dd1SSteven Rostedt	    run_command "mv $output_config $outputdir/config_temp" or
16425c42fc5bSSteven Rostedt		dodie "moving .config";
16435c42fc5bSSteven Rostedt
164413488231SAndrew Jones	    run_command "$make mrproper" or dodie "make mrproper";
16455c42fc5bSSteven Rostedt
164651ad1dd1SSteven Rostedt	    run_command "mv $outputdir/config_temp $output_config" or
16475c42fc5bSSteven Rostedt		dodie "moving config_temp";
164813488231SAndrew Jones	}
16495c42fc5bSSteven Rostedt
16505c42fc5bSSteven Rostedt    } elsif (!$noclean) {
165151ad1dd1SSteven Rostedt	unlink "$output_config";
16525f9b6cedSSteven Rostedt	run_command "$make mrproper" or
16535c42fc5bSSteven Rostedt	    dodie "make mrproper";
16545c42fc5bSSteven Rostedt    }
16552545eb61SSteven Rostedt
16562545eb61SSteven Rostedt    # add something to distinguish this build
1657a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
1658a75fececSSteven Rostedt    print OUT "$localversion\n";
16592545eb61SSteven Rostedt    close(OUT);
16602545eb61SSteven Rostedt
16615f9b6cedSSteven Rostedt    if (defined($minconfig)) {
1662fcb3f16aSSteven Rostedt	load_force_config($minconfig);
16632545eb61SSteven Rostedt    }
16642545eb61SSteven Rostedt
1665fcb3f16aSSteven Rostedt    if ($type ne "oldnoconfig") {
1666fcb3f16aSSteven Rostedt	run_command "$make $type" or
16675c42fc5bSSteven Rostedt	    dodie "failed make config";
1668612b9e9bSSteven Rostedt    }
1669fcb3f16aSSteven Rostedt    # Run old config regardless, to enforce min configurations
1670fcb3f16aSSteven Rostedt    make_oldconfig;
16712545eb61SSteven Rostedt
1672a75fececSSteven Rostedt    $redirect = "$buildlog";
16730bd6c1a3SSteven Rostedt    my $build_ret = run_command "$make $build_options";
16746c5ee0beSSteven Rostedt    undef $redirect;
16750bd6c1a3SSteven Rostedt
16760bd6c1a3SSteven Rostedt    if (defined($post_build)) {
16770bd6c1a3SSteven Rostedt	my $ret = run_command $post_build;
16780bd6c1a3SSteven Rostedt	if (!$ret && defined($post_build_die) &&
16790bd6c1a3SSteven Rostedt	    $post_build_die) {
16800bd6c1a3SSteven Rostedt	    dodie "failed to post_build\n";
16810bd6c1a3SSteven Rostedt	}
16820bd6c1a3SSteven Rostedt    }
16830bd6c1a3SSteven Rostedt
16840bd6c1a3SSteven Rostedt    if (!$build_ret) {
16855f9b6cedSSteven Rostedt	# bisect may need this to pass
16864ab1cce5SSteven Rostedt	if ($in_bisect) {
16874ab1cce5SSteven Rostedt	    $no_reboot = $save_no_reboot;
16884ab1cce5SSteven Rostedt	    return 0;
16894ab1cce5SSteven Rostedt	}
16902b7d9b21SSteven Rostedt	fail "failed build" and return 0;
16912545eb61SSteven Rostedt    }
16925f9b6cedSSteven Rostedt
16934ab1cce5SSteven Rostedt    $no_reboot = $save_no_reboot;
16944ab1cce5SSteven Rostedt
16952b7d9b21SSteven Rostedt    return 1;
16962545eb61SSteven Rostedt}
16972545eb61SSteven Rostedt
169875c3fda7SSteven Rostedtsub halt {
1699e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
1700576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
1701576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
1702576f627cSSteven Rostedt	    run_command "$power_off";
1703576f627cSSteven Rostedt	}
1704576f627cSSteven Rostedt    } else {
170575c3fda7SSteven Rostedt	# nope? the zap it!
1706a75fececSSteven Rostedt	run_command "$power_off";
170775c3fda7SSteven Rostedt    }
170875c3fda7SSteven Rostedt}
170975c3fda7SSteven Rostedt
17105f9b6cedSSteven Rostedtsub success {
17115f9b6cedSSteven Rostedt    my ($i) = @_;
17125f9b6cedSSteven Rostedt
1713e48c5293SSteven Rostedt    $successes++;
1714e48c5293SSteven Rostedt
17159064af52SSteven Rostedt    my $name = "";
17169064af52SSteven Rostedt
17179064af52SSteven Rostedt    if (defined($test_name)) {
17189064af52SSteven Rostedt	$name = " ($test_name)";
17199064af52SSteven Rostedt    }
17209064af52SSteven Rostedt
17215f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
17225f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
17239064af52SSteven Rostedt    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
17245f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
17255f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
17265f9b6cedSSteven Rostedt
1727de5b6e3bSRabin Vincent    if (defined($store_successes)) {
1728de5b6e3bSRabin Vincent        save_logs "success", $store_successes;
1729de5b6e3bSRabin Vincent    }
1730de5b6e3bSRabin Vincent
1731576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1732a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
17332728be41SAndrew Jones	reboot $sleep_time;
17345f9b6cedSSteven Rostedt    }
17355f9b6cedSSteven Rostedt}
17365f9b6cedSSteven Rostedt
1737c960bb9fSSteven Rostedtsub answer_bisect {
1738c960bb9fSSteven Rostedt    for (;;) {
1739c960bb9fSSteven Rostedt	doprint "Pass or fail? [p/f]";
1740c960bb9fSSteven Rostedt	my $ans = <STDIN>;
1741c960bb9fSSteven Rostedt	chomp $ans;
1742c960bb9fSSteven Rostedt	if ($ans eq "p" || $ans eq "P") {
1743c960bb9fSSteven Rostedt	    return 1;
1744c960bb9fSSteven Rostedt	} elsif ($ans eq "f" || $ans eq "F") {
1745c960bb9fSSteven Rostedt	    return 0;
1746c960bb9fSSteven Rostedt	} else {
1747c960bb9fSSteven Rostedt	    print "Please answer 'P' or 'F'\n";
1748c960bb9fSSteven Rostedt	}
1749c960bb9fSSteven Rostedt    }
1750c960bb9fSSteven Rostedt}
1751c960bb9fSSteven Rostedt
17525a391fbfSSteven Rostedtsub child_run_test {
17537faafbd6SSteven Rostedt    my $failed = 0;
17545a391fbfSSteven Rostedt
17557faafbd6SSteven Rostedt    # child should have no power
1756a75fececSSteven Rostedt    $reboot_on_error = 0;
1757a75fececSSteven Rostedt    $poweroff_on_error = 0;
1758a75fececSSteven Rostedt    $die_on_failure = 1;
17597faafbd6SSteven Rostedt
1760a9dd5d63SRabin Vincent    $redirect = "$testlog";
17617faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
1762a9dd5d63SRabin Vincent    undef $redirect;
1763a9dd5d63SRabin Vincent
17645a391fbfSSteven Rostedt    exit $failed;
17655a391fbfSSteven Rostedt}
17665a391fbfSSteven Rostedt
17675a391fbfSSteven Rostedtmy $child_done;
17685a391fbfSSteven Rostedt
17695a391fbfSSteven Rostedtsub child_finished {
17705a391fbfSSteven Rostedt    $child_done = 1;
17715a391fbfSSteven Rostedt}
17725a391fbfSSteven Rostedt
17735a391fbfSSteven Rostedtsub do_run_test {
17745a391fbfSSteven Rostedt    my $child_pid;
17755a391fbfSSteven Rostedt    my $child_exit;
17765a391fbfSSteven Rostedt    my $line;
17775a391fbfSSteven Rostedt    my $full_line;
17785a391fbfSSteven Rostedt    my $bug = 0;
17795a391fbfSSteven Rostedt
17807faafbd6SSteven Rostedt    wait_for_monitor 1;
17815a391fbfSSteven Rostedt
17827faafbd6SSteven Rostedt    doprint "run test $run_test\n";
17835a391fbfSSteven Rostedt
17845a391fbfSSteven Rostedt    $child_done = 0;
17855a391fbfSSteven Rostedt
17865a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
17875a391fbfSSteven Rostedt
17885a391fbfSSteven Rostedt    $child_pid = fork;
17895a391fbfSSteven Rostedt
17905a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
17915a391fbfSSteven Rostedt
17925a391fbfSSteven Rostedt    $full_line = "";
17935a391fbfSSteven Rostedt
17945a391fbfSSteven Rostedt    do {
17957faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
17965a391fbfSSteven Rostedt	if (defined($line)) {
17975a391fbfSSteven Rostedt
17985a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
17995a391fbfSSteven Rostedt	    $full_line .= $line;
18008ea0e063SSteven Rostedt	    doprint $line;
18015a391fbfSSteven Rostedt
18025a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
18035a391fbfSSteven Rostedt		$bug = 1;
18045a391fbfSSteven Rostedt	    }
18055a391fbfSSteven Rostedt
18065a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
18075a391fbfSSteven Rostedt		$bug = 1;
18085a391fbfSSteven Rostedt	    }
18095a391fbfSSteven Rostedt
18105a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
18115a391fbfSSteven Rostedt		$full_line = "";
18125a391fbfSSteven Rostedt	    }
18135a391fbfSSteven Rostedt	}
18145a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
18155a391fbfSSteven Rostedt
18165a391fbfSSteven Rostedt    if ($bug) {
18178ea0e063SSteven Rostedt	my $failure_start = time;
18188ea0e063SSteven Rostedt	my $now;
18198ea0e063SSteven Rostedt	do {
18208ea0e063SSteven Rostedt	    $line = wait_for_input($monitor_fp, 1);
18218ea0e063SSteven Rostedt	    if (defined($line)) {
18228ea0e063SSteven Rostedt		doprint $line;
18238ea0e063SSteven Rostedt	    }
18248ea0e063SSteven Rostedt	    $now = time;
18258ea0e063SSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
18268ea0e063SSteven Rostedt		last;
18278ea0e063SSteven Rostedt	    }
18288ea0e063SSteven Rostedt	} while (defined($line));
18298ea0e063SSteven Rostedt
18305a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
18315a391fbfSSteven Rostedt	# kill the child with extreme prejudice
18325a391fbfSSteven Rostedt	kill 9, $child_pid;
18335a391fbfSSteven Rostedt    }
18345a391fbfSSteven Rostedt
18355a391fbfSSteven Rostedt    waitpid $child_pid, 0;
18365a391fbfSSteven Rostedt    $child_exit = $?;
18375a391fbfSSteven Rostedt
18385a391fbfSSteven Rostedt    if ($bug || $child_exit) {
18392b7d9b21SSteven Rostedt	return 0 if $in_bisect;
18402b7d9b21SSteven Rostedt	fail "test failed" and return 0;
18415a391fbfSSteven Rostedt    }
18422b7d9b21SSteven Rostedt    return 1;
18435a391fbfSSteven Rostedt}
18445a391fbfSSteven Rostedt
1845a75fececSSteven Rostedtsub run_git_bisect {
1846a75fececSSteven Rostedt    my ($command) = @_;
1847a75fececSSteven Rostedt
1848a75fececSSteven Rostedt    doprint "$command ... ";
1849a75fececSSteven Rostedt
1850a75fececSSteven Rostedt    my $output = `$command 2>&1`;
1851a75fececSSteven Rostedt    my $ret = $?;
1852a75fececSSteven Rostedt
1853a75fececSSteven Rostedt    logit $output;
1854a75fececSSteven Rostedt
1855a75fececSSteven Rostedt    if ($ret) {
1856a75fececSSteven Rostedt	doprint "FAILED\n";
1857a75fececSSteven Rostedt	dodie "Failed to git bisect";
1858a75fececSSteven Rostedt    }
1859a75fececSSteven Rostedt
1860a75fececSSteven Rostedt    doprint "SUCCESS\n";
1861a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1862a75fececSSteven Rostedt	doprint "$1 [$2]\n";
1863a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1864a75fececSSteven Rostedt	$bisect_bad = $1;
1865a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
1866a75fececSSteven Rostedt	return 0;
1867a75fececSSteven Rostedt    } else {
1868a75fececSSteven Rostedt	# we already logged it, just print it now.
1869a75fececSSteven Rostedt	print $output;
1870a75fececSSteven Rostedt    }
1871a75fececSSteven Rostedt
1872a75fececSSteven Rostedt    return 1;
1873a75fececSSteven Rostedt}
1874a75fececSSteven Rostedt
1875c23dca7cSSteven Rostedtsub bisect_reboot {
1876c23dca7cSSteven Rostedt    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
18772728be41SAndrew Jones    reboot $bisect_sleep_time;
1878c23dca7cSSteven Rostedt}
1879c23dca7cSSteven Rostedt
1880c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip
18810a05c769SSteven Rostedtsub run_bisect_test {
18820a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
18835f9b6cedSSteven Rostedt
18842b7d9b21SSteven Rostedt    my $failed = 0;
18855f9b6cedSSteven Rostedt    my $result;
18865f9b6cedSSteven Rostedt    my $output;
18875f9b6cedSSteven Rostedt    my $ret;
18885f9b6cedSSteven Rostedt
18890a05c769SSteven Rostedt    $in_bisect = 1;
18900a05c769SSteven Rostedt
18910a05c769SSteven Rostedt    build $buildtype or $failed = 1;
18925f9b6cedSSteven Rostedt
18935f9b6cedSSteven Rostedt    if ($type ne "build") {
1894c23dca7cSSteven Rostedt	if ($failed && $bisect_skip) {
1895c23dca7cSSteven Rostedt	    $in_bisect = 0;
1896c23dca7cSSteven Rostedt	    return -1;
1897c23dca7cSSteven Rostedt	}
18987faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
18995f9b6cedSSteven Rostedt
19005f9b6cedSSteven Rostedt	# Now boot the box
1901ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
19025f9b6cedSSteven Rostedt
19035f9b6cedSSteven Rostedt	if ($type ne "boot") {
1904c23dca7cSSteven Rostedt	    if ($failed && $bisect_skip) {
1905c23dca7cSSteven Rostedt		end_monitor;
1906c23dca7cSSteven Rostedt		bisect_reboot;
1907c23dca7cSSteven Rostedt		$in_bisect = 0;
1908c23dca7cSSteven Rostedt		return -1;
1909c23dca7cSSteven Rostedt	    }
19107faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
19115a391fbfSSteven Rostedt
19122b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
19135f9b6cedSSteven Rostedt	}
19147faafbd6SSteven Rostedt	end_monitor;
19155f9b6cedSSteven Rostedt    }
19165f9b6cedSSteven Rostedt
19175f9b6cedSSteven Rostedt    if ($failed) {
19180a05c769SSteven Rostedt	$result = 0;
19195f9b6cedSSteven Rostedt    } else {
19200a05c769SSteven Rostedt	$result = 1;
19215f9b6cedSSteven Rostedt    }
19224025bc62SSteven Rostedt
19234025bc62SSteven Rostedt    # reboot the box to a kernel we can ssh to
19244025bc62SSteven Rostedt    if ($type ne "build") {
19254025bc62SSteven Rostedt	bisect_reboot;
19264025bc62SSteven Rostedt    }
19270a05c769SSteven Rostedt    $in_bisect = 0;
19280a05c769SSteven Rostedt
19290a05c769SSteven Rostedt    return $result;
19300a05c769SSteven Rostedt}
19310a05c769SSteven Rostedt
19320a05c769SSteven Rostedtsub run_bisect {
19330a05c769SSteven Rostedt    my ($type) = @_;
19340a05c769SSteven Rostedt    my $buildtype = "oldconfig";
19350a05c769SSteven Rostedt
19360a05c769SSteven Rostedt    # We should have a minconfig to use?
19370a05c769SSteven Rostedt    if (defined($minconfig)) {
19380a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
19390a05c769SSteven Rostedt    }
19400a05c769SSteven Rostedt
19410a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
19420a05c769SSteven Rostedt
1943c960bb9fSSteven Rostedt    if ($bisect_manual) {
1944c960bb9fSSteven Rostedt	$ret = answer_bisect;
1945c960bb9fSSteven Rostedt    }
19465f9b6cedSSteven Rostedt
1947d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
1948d6ce2a0bSSteven Rostedt    if ($reverse_bisect) {
19490a05c769SSteven Rostedt	$ret = !$ret;
1950d6ce2a0bSSteven Rostedt    }
1951d6ce2a0bSSteven Rostedt
1952c23dca7cSSteven Rostedt    if ($ret > 0) {
19530a05c769SSteven Rostedt	return "good";
1954c23dca7cSSteven Rostedt    } elsif ($ret == 0) {
19550a05c769SSteven Rostedt	return  "bad";
1956c23dca7cSSteven Rostedt    } elsif ($bisect_skip) {
1957c23dca7cSSteven Rostedt	doprint "HIT A BAD COMMIT ... SKIPPING\n";
1958c23dca7cSSteven Rostedt	return "skip";
19590a05c769SSteven Rostedt    }
19605f9b6cedSSteven Rostedt}
19615f9b6cedSSteven Rostedt
1962dad98754SSteven Rostedtsub update_bisect_replay {
1963dad98754SSteven Rostedt    my $tmp_log = "$tmpdir/ktest_bisect_log";
1964dad98754SSteven Rostedt    run_command "git bisect log > $tmp_log" or
1965dad98754SSteven Rostedt	die "can't create bisect log";
1966dad98754SSteven Rostedt    return $tmp_log;
1967dad98754SSteven Rostedt}
1968dad98754SSteven Rostedt
19695f9b6cedSSteven Rostedtsub bisect {
19705f9b6cedSSteven Rostedt    my ($i) = @_;
19715f9b6cedSSteven Rostedt
19725f9b6cedSSteven Rostedt    my $result;
19735f9b6cedSSteven Rostedt
19745f9b6cedSSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($opt{"BISECT_GOOD[$i]"}));
19755f9b6cedSSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($opt{"BISECT_BAD[$i]"}));
19765f9b6cedSSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($opt{"BISECT_TYPE[$i]"}));
19775f9b6cedSSteven Rostedt
19785f9b6cedSSteven Rostedt    my $good = $opt{"BISECT_GOOD[$i]"};
19795f9b6cedSSteven Rostedt    my $bad = $opt{"BISECT_BAD[$i]"};
19805f9b6cedSSteven Rostedt    my $type = $opt{"BISECT_TYPE[$i]"};
1981a75fececSSteven Rostedt    my $start = $opt{"BISECT_START[$i]"};
1982a75fececSSteven Rostedt    my $replay = $opt{"BISECT_REPLAY[$i]"};
19833410f6fdSSteven Rostedt    my $start_files = $opt{"BISECT_FILES[$i]"};
19843410f6fdSSteven Rostedt
19853410f6fdSSteven Rostedt    if (defined($start_files)) {
19863410f6fdSSteven Rostedt	$start_files = " -- " . $start_files;
19873410f6fdSSteven Rostedt    } else {
19883410f6fdSSteven Rostedt	$start_files = "";
19893410f6fdSSteven Rostedt    }
19905f9b6cedSSteven Rostedt
1991a57419b3SSteven Rostedt    # convert to true sha1's
1992a57419b3SSteven Rostedt    $good = get_sha1($good);
1993a57419b3SSteven Rostedt    $bad = get_sha1($bad);
1994a57419b3SSteven Rostedt
1995d6ce2a0bSSteven Rostedt    if (defined($opt{"BISECT_REVERSE[$i]"}) &&
1996d6ce2a0bSSteven Rostedt	$opt{"BISECT_REVERSE[$i]"} == 1) {
1997d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1998d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
1999d6ce2a0bSSteven Rostedt    } else {
2000d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
2001d6ce2a0bSSteven Rostedt    }
2002d6ce2a0bSSteven Rostedt
20035a391fbfSSteven Rostedt    # Can't have a test without having a test to run
20045a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
20055a391fbfSSteven Rostedt	$type = "boot";
20065a391fbfSSteven Rostedt    }
20075a391fbfSSteven Rostedt
2008dad98754SSteven Rostedt    # Check if a bisect was running
2009dad98754SSteven Rostedt    my $bisect_start_file = "$builddir/.git/BISECT_START";
2010dad98754SSteven Rostedt
2011a75fececSSteven Rostedt    my $check = $opt{"BISECT_CHECK[$i]"};
2012dad98754SSteven Rostedt    my $do_check = defined($check) && $check ne "0";
2013dad98754SSteven Rostedt
2014dad98754SSteven Rostedt    if ( -f $bisect_start_file ) {
2015dad98754SSteven Rostedt	print "Bisect in progress found\n";
2016dad98754SSteven Rostedt	if ($do_check) {
2017dad98754SSteven Rostedt	    print " If you say yes, then no checks of good or bad will be done\n";
2018dad98754SSteven Rostedt	}
2019dad98754SSteven Rostedt	if (defined($replay)) {
2020dad98754SSteven Rostedt	    print "** BISECT_REPLAY is defined in config file **";
2021dad98754SSteven Rostedt	    print " Ignore config option and perform new git bisect log?\n";
2022dad98754SSteven Rostedt	    if (read_ync " (yes, no, or cancel) ") {
2023dad98754SSteven Rostedt		$replay = update_bisect_replay;
2024dad98754SSteven Rostedt		$do_check = 0;
2025dad98754SSteven Rostedt	    }
2026dad98754SSteven Rostedt	} elsif (read_yn "read git log and continue?") {
2027dad98754SSteven Rostedt	    $replay = update_bisect_replay;
2028dad98754SSteven Rostedt	    $do_check = 0;
2029dad98754SSteven Rostedt	}
2030dad98754SSteven Rostedt    }
2031dad98754SSteven Rostedt
2032dad98754SSteven Rostedt    if ($do_check) {
2033a75fececSSteven Rostedt
2034a75fececSSteven Rostedt	# get current HEAD
2035a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
2036a75fececSSteven Rostedt
2037a75fececSSteven Rostedt	if ($check ne "good") {
2038a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
2039a75fececSSteven Rostedt	    run_command "git checkout $bad" or
2040a75fececSSteven Rostedt		die "Failed to checkout $bad";
2041a75fececSSteven Rostedt
2042a75fececSSteven Rostedt	    $result = run_bisect $type;
2043a75fececSSteven Rostedt
2044a75fececSSteven Rostedt	    if ($result ne "bad") {
2045a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
2046a75fececSSteven Rostedt	    }
2047a75fececSSteven Rostedt	}
2048a75fececSSteven Rostedt
2049a75fececSSteven Rostedt	if ($check ne "bad") {
2050a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
2051a75fececSSteven Rostedt	    run_command "git checkout $good" or
2052a75fececSSteven Rostedt		die "Failed to checkout $good";
2053a75fececSSteven Rostedt
2054a75fececSSteven Rostedt	    $result = run_bisect $type;
2055a75fececSSteven Rostedt
2056a75fececSSteven Rostedt	    if ($result ne "good") {
2057a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
2058a75fececSSteven Rostedt	    }
2059a75fececSSteven Rostedt	}
2060a75fececSSteven Rostedt
2061a75fececSSteven Rostedt	# checkout where we started
2062a75fececSSteven Rostedt	run_command "git checkout $head" or
2063a75fececSSteven Rostedt	    die "Failed to checkout $head";
2064a75fececSSteven Rostedt    }
2065a75fececSSteven Rostedt
20663410f6fdSSteven Rostedt    run_command "git bisect start$start_files" or
2067a75fececSSteven Rostedt	dodie "could not start bisect";
2068a75fececSSteven Rostedt
2069a75fececSSteven Rostedt    run_command "git bisect good $good" or
2070a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
2071a75fececSSteven Rostedt
2072a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
2073a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
2074a75fececSSteven Rostedt
2075a75fececSSteven Rostedt    if (defined($replay)) {
2076a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
2077a75fececSSteven Rostedt	    dodie "failed to run replay";
2078a75fececSSteven Rostedt    }
2079a75fececSSteven Rostedt
2080a75fececSSteven Rostedt    if (defined($start)) {
2081a75fececSSteven Rostedt	run_command "git checkout $start" or
2082a75fececSSteven Rostedt	    dodie "failed to checkout $start";
2083a75fececSSteven Rostedt    }
2084a75fececSSteven Rostedt
2085a75fececSSteven Rostedt    my $test;
20865f9b6cedSSteven Rostedt    do {
20875f9b6cedSSteven Rostedt	$result = run_bisect $type;
2088a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
2089a75fececSSteven Rostedt    } while ($test);
20905f9b6cedSSteven Rostedt
20915f9b6cedSSteven Rostedt    run_command "git bisect log" or
20925f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
20935f9b6cedSSteven Rostedt
20945f9b6cedSSteven Rostedt    run_command "git bisect reset" or
20955f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
20965f9b6cedSSteven Rostedt
20975f9b6cedSSteven Rostedt    doprint "Bad commit was [$bisect_bad]\n";
20985f9b6cedSSteven Rostedt
20990a05c769SSteven Rostedt    success $i;
21000a05c769SSteven Rostedt}
21010a05c769SSteven Rostedt
21020a05c769SSteven Rostedtmy %config_ignore;
21030a05c769SSteven Rostedtmy %config_set;
21040a05c769SSteven Rostedt
21050a05c769SSteven Rostedtmy %config_list;
21060a05c769SSteven Rostedtmy %null_config;
21070a05c769SSteven Rostedt
21080a05c769SSteven Rostedtmy %dependency;
21090a05c769SSteven Rostedt
21104c4ab120SSteven Rostedtsub assign_configs {
21114c4ab120SSteven Rostedt    my ($hash, $config) = @_;
21120a05c769SSteven Rostedt
21130a05c769SSteven Rostedt    open (IN, $config)
21140a05c769SSteven Rostedt	or dodie "Failed to read $config";
21150a05c769SSteven Rostedt
21160a05c769SSteven Rostedt    while (<IN>) {
21179bf71749SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
21184c4ab120SSteven Rostedt	    ${$hash}{$2} = $1;
21190a05c769SSteven Rostedt	}
21200a05c769SSteven Rostedt    }
21210a05c769SSteven Rostedt
21220a05c769SSteven Rostedt    close(IN);
21230a05c769SSteven Rostedt}
21240a05c769SSteven Rostedt
21254c4ab120SSteven Rostedtsub process_config_ignore {
21264c4ab120SSteven Rostedt    my ($config) = @_;
21274c4ab120SSteven Rostedt
21284c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
21294c4ab120SSteven Rostedt}
21304c4ab120SSteven Rostedt
21310a05c769SSteven Rostedtsub read_current_config {
21320a05c769SSteven Rostedt    my ($config_ref) = @_;
21330a05c769SSteven Rostedt
21340a05c769SSteven Rostedt    %{$config_ref} = ();
21350a05c769SSteven Rostedt    undef %{$config_ref};
21360a05c769SSteven Rostedt
21370a05c769SSteven Rostedt    my @key = keys %{$config_ref};
21380a05c769SSteven Rostedt    if ($#key >= 0) {
21390a05c769SSteven Rostedt	print "did not delete!\n";
21400a05c769SSteven Rostedt	exit;
21410a05c769SSteven Rostedt    }
21420a05c769SSteven Rostedt    open (IN, "$output_config");
21430a05c769SSteven Rostedt
21440a05c769SSteven Rostedt    while (<IN>) {
21450a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
21460a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
21470a05c769SSteven Rostedt	}
21480a05c769SSteven Rostedt    }
21490a05c769SSteven Rostedt    close(IN);
21500a05c769SSteven Rostedt}
21510a05c769SSteven Rostedt
21520a05c769SSteven Rostedtsub get_dependencies {
21530a05c769SSteven Rostedt    my ($config) = @_;
21540a05c769SSteven Rostedt
21550a05c769SSteven Rostedt    my $arr = $dependency{$config};
21560a05c769SSteven Rostedt    if (!defined($arr)) {
21570a05c769SSteven Rostedt	return ();
21580a05c769SSteven Rostedt    }
21590a05c769SSteven Rostedt
21600a05c769SSteven Rostedt    my @deps = @{$arr};
21610a05c769SSteven Rostedt
21620a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
21630a05c769SSteven Rostedt	print "ADD DEP $dep\n";
21640a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
21650a05c769SSteven Rostedt    }
21660a05c769SSteven Rostedt
21670a05c769SSteven Rostedt    return @deps;
21680a05c769SSteven Rostedt}
21690a05c769SSteven Rostedt
21700a05c769SSteven Rostedtsub create_config {
21710a05c769SSteven Rostedt    my @configs = @_;
21720a05c769SSteven Rostedt
21730a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
21740a05c769SSteven Rostedt
21750a05c769SSteven Rostedt    foreach my $config (@configs) {
21760a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
21770a05c769SSteven Rostedt	my @deps = get_dependencies $config;
21780a05c769SSteven Rostedt	foreach my $dep (@deps) {
21790a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
21800a05c769SSteven Rostedt	}
21810a05c769SSteven Rostedt    }
21820a05c769SSteven Rostedt
21830a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
21840a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
21850a05c769SSteven Rostedt    }
21860a05c769SSteven Rostedt    close(OUT);
21870a05c769SSteven Rostedt
21880a05c769SSteven Rostedt#    exit;
2189fcb3f16aSSteven Rostedt    make_oldconfig;
21900a05c769SSteven Rostedt}
21910a05c769SSteven Rostedt
21920a05c769SSteven Rostedtsub compare_configs {
21930a05c769SSteven Rostedt    my (%a, %b) = @_;
21940a05c769SSteven Rostedt
21950a05c769SSteven Rostedt    foreach my $item (keys %a) {
21960a05c769SSteven Rostedt	if (!defined($b{$item})) {
21970a05c769SSteven Rostedt	    print "diff $item\n";
21980a05c769SSteven Rostedt	    return 1;
21990a05c769SSteven Rostedt	}
22000a05c769SSteven Rostedt	delete $b{$item};
22010a05c769SSteven Rostedt    }
22020a05c769SSteven Rostedt
22030a05c769SSteven Rostedt    my @keys = keys %b;
22040a05c769SSteven Rostedt    if ($#keys) {
22050a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
22060a05c769SSteven Rostedt    }
22070a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
22080a05c769SSteven Rostedt
22090a05c769SSteven Rostedt    return 0;
22100a05c769SSteven Rostedt}
22110a05c769SSteven Rostedt
22120a05c769SSteven Rostedtsub run_config_bisect_test {
22130a05c769SSteven Rostedt    my ($type) = @_;
22140a05c769SSteven Rostedt
22150a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
22160a05c769SSteven Rostedt}
22170a05c769SSteven Rostedt
22180a05c769SSteven Rostedtsub process_passed {
22190a05c769SSteven Rostedt    my (%configs) = @_;
22200a05c769SSteven Rostedt
22210a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
22220a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
22230a05c769SSteven Rostedt    # Add them to the min options.
22240a05c769SSteven Rostedt    foreach my $config (keys %configs) {
22250a05c769SSteven Rostedt	if (defined($config_list{$config})) {
22260a05c769SSteven Rostedt	    doprint " removing $config\n";
22270a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
22280a05c769SSteven Rostedt	    delete $config_list{$config};
22290a05c769SSteven Rostedt	}
22300a05c769SSteven Rostedt    }
2231f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
2232f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
22330a05c769SSteven Rostedt}
22340a05c769SSteven Rostedt
22350a05c769SSteven Rostedtsub process_failed {
22360a05c769SSteven Rostedt    my ($config) = @_;
22370a05c769SSteven Rostedt
22380a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
22390a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
22400a05c769SSteven Rostedt    doprint "***************************************\n\n";
22410a05c769SSteven Rostedt}
22420a05c769SSteven Rostedt
22430a05c769SSteven Rostedtsub run_config_bisect {
22440a05c769SSteven Rostedt
22450a05c769SSteven Rostedt    my @start_list = keys %config_list;
22460a05c769SSteven Rostedt
22470a05c769SSteven Rostedt    if ($#start_list < 0) {
22480a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
22490a05c769SSteven Rostedt	return -1;
22500a05c769SSteven Rostedt    }
22510a05c769SSteven Rostedt
22520a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
22530a05c769SSteven Rostedt    my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
22540a05c769SSteven Rostedt    my $ret;
22550a05c769SSteven Rostedt    my %current_config;
22560a05c769SSteven Rostedt
22570a05c769SSteven Rostedt    my $count = $#start_list + 1;
22580a05c769SSteven Rostedt    doprint "  $count configs to test\n";
22590a05c769SSteven Rostedt
22600a05c769SSteven Rostedt    my $half = int($#start_list / 2);
22610a05c769SSteven Rostedt
22620a05c769SSteven Rostedt    do {
22630a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
22640a05c769SSteven Rostedt
22650a05c769SSteven Rostedt	create_config @tophalf;
22660a05c769SSteven Rostedt	read_current_config \%current_config;
22670a05c769SSteven Rostedt
22680a05c769SSteven Rostedt	$count = $#tophalf + 1;
22690a05c769SSteven Rostedt	doprint "Testing $count configs\n";
22700a05c769SSteven Rostedt	my $found = 0;
22710a05c769SSteven Rostedt	# make sure we test something
22720a05c769SSteven Rostedt	foreach my $config (@tophalf) {
22730a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
22740a05c769SSteven Rostedt		logit " $config\n";
22750a05c769SSteven Rostedt		$found = 1;
22760a05c769SSteven Rostedt	    }
22770a05c769SSteven Rostedt	}
22780a05c769SSteven Rostedt	if (!$found) {
22790a05c769SSteven Rostedt	    # try the other half
22800a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
22814c8cc55bSSteven Rostedt	    @tophalf = @start_list[$half + 1 .. $#start_list];
22820a05c769SSteven Rostedt	    create_config @tophalf;
22830a05c769SSteven Rostedt	    read_current_config \%current_config;
22840a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
22850a05c769SSteven Rostedt		if (defined($current_config{$config})) {
22860a05c769SSteven Rostedt		    logit " $config\n";
22870a05c769SSteven Rostedt		    $found = 1;
22880a05c769SSteven Rostedt		}
22890a05c769SSteven Rostedt	    }
22900a05c769SSteven Rostedt	    if (!$found) {
22910a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
22920a05c769SSteven Rostedt		foreach my $config (@start_list) {
22930a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
22940a05c769SSteven Rostedt		}
22950a05c769SSteven Rostedt		return -1;
22960a05c769SSteven Rostedt	    }
22970a05c769SSteven Rostedt	    $count = $#tophalf + 1;
22980a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
22990a05c769SSteven Rostedt	}
23000a05c769SSteven Rostedt
23010a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
2302c960bb9fSSteven Rostedt	if ($bisect_manual) {
2303c960bb9fSSteven Rostedt	    $ret = answer_bisect;
2304c960bb9fSSteven Rostedt	}
23050a05c769SSteven Rostedt	if ($ret) {
23060a05c769SSteven Rostedt	    process_passed %current_config;
23070a05c769SSteven Rostedt	    return 0;
23080a05c769SSteven Rostedt	}
23090a05c769SSteven Rostedt
23100a05c769SSteven Rostedt	doprint "This config had a failure.\n";
23110a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
2312f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
2313f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
23140a05c769SSteven Rostedt
23150a05c769SSteven Rostedt	# A config exists in this group that was bad.
23160a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
23170a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
23180a05c769SSteven Rostedt		doprint " removing $config\n";
23190a05c769SSteven Rostedt		delete $config_list{$config};
23200a05c769SSteven Rostedt	    }
23210a05c769SSteven Rostedt	}
23220a05c769SSteven Rostedt
23230a05c769SSteven Rostedt	@start_list = @tophalf;
23240a05c769SSteven Rostedt
23250a05c769SSteven Rostedt	if ($#start_list == 0) {
23260a05c769SSteven Rostedt	    process_failed $start_list[0];
23270a05c769SSteven Rostedt	    return 1;
23280a05c769SSteven Rostedt	}
23290a05c769SSteven Rostedt
23300a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
23310a05c769SSteven Rostedt	# they are good.
23320a05c769SSteven Rostedt	$half = int($#start_list / 2);
23334c8cc55bSSteven Rostedt    } while ($#start_list > 0);
23340a05c769SSteven Rostedt
2335c960bb9fSSteven Rostedt    # we found a single config, try it again unless we are running manually
2336c960bb9fSSteven Rostedt
2337c960bb9fSSteven Rostedt    if ($bisect_manual) {
2338c960bb9fSSteven Rostedt	process_failed $start_list[0];
2339c960bb9fSSteven Rostedt	return 1;
2340c960bb9fSSteven Rostedt    }
2341c960bb9fSSteven Rostedt
23420a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
23430a05c769SSteven Rostedt
23440a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
23450a05c769SSteven Rostedt    if ($ret) {
23460a05c769SSteven Rostedt	process_passed %current_config;
23470a05c769SSteven Rostedt	return 0;
23480a05c769SSteven Rostedt    }
23490a05c769SSteven Rostedt
23500a05c769SSteven Rostedt    process_failed $start_list[0];
23510a05c769SSteven Rostedt    return 1;
23520a05c769SSteven Rostedt}
23530a05c769SSteven Rostedt
23540a05c769SSteven Rostedtsub config_bisect {
23550a05c769SSteven Rostedt    my ($i) = @_;
23560a05c769SSteven Rostedt
23570a05c769SSteven Rostedt    my $start_config = $opt{"CONFIG_BISECT[$i]"};
23580a05c769SSteven Rostedt
23590a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
23600a05c769SSteven Rostedt
236130f75da5SSteven Rostedt    if (defined($config_bisect_good)) {
236230f75da5SSteven Rostedt	process_config_ignore $config_bisect_good;
236330f75da5SSteven Rostedt    }
236430f75da5SSteven Rostedt
23650a05c769SSteven Rostedt    # Make the file with the bad config and the min config
23660a05c769SSteven Rostedt    if (defined($minconfig)) {
23670a05c769SSteven Rostedt	# read the min config for things to ignore
23680a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
23690a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
23700a05c769SSteven Rostedt    } else {
23710a05c769SSteven Rostedt	unlink $tmpconfig;
23720a05c769SSteven Rostedt    }
23730a05c769SSteven Rostedt
23740a05c769SSteven Rostedt    if (-f $tmpconfig) {
2375fcb3f16aSSteven Rostedt	load_force_config($tmpconfig);
23760a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
23770a05c769SSteven Rostedt    }
23780a05c769SSteven Rostedt
23790a05c769SSteven Rostedt    # now process the start config
23800a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
23810a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
23820a05c769SSteven Rostedt
23830a05c769SSteven Rostedt    # read directly what we want to check
23840a05c769SSteven Rostedt    my %config_check;
23850a05c769SSteven Rostedt    open (IN, $output_config)
23860a05c769SSteven Rostedt	or dodie "faied to open $output_config";
23870a05c769SSteven Rostedt
23880a05c769SSteven Rostedt    while (<IN>) {
23890a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
23900a05c769SSteven Rostedt	    $config_check{$2} = $1;
23910a05c769SSteven Rostedt	}
23920a05c769SSteven Rostedt    }
23930a05c769SSteven Rostedt    close(IN);
23940a05c769SSteven Rostedt
2395250bae8bSSteven Rostedt    # Now run oldconfig with the minconfig
2396fcb3f16aSSteven Rostedt    make_oldconfig;
23970a05c769SSteven Rostedt
23980a05c769SSteven Rostedt    # check to see what we lost (or gained)
23990a05c769SSteven Rostedt    open (IN, $output_config)
24000a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
24010a05c769SSteven Rostedt
24020a05c769SSteven Rostedt    my %removed_configs;
24030a05c769SSteven Rostedt    my %added_configs;
24040a05c769SSteven Rostedt
24050a05c769SSteven Rostedt    while (<IN>) {
24060a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
24070a05c769SSteven Rostedt	    # save off all options
24080a05c769SSteven Rostedt	    $config_set{$2} = $1;
24090a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
24100a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
24110a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
24120a05c769SSteven Rostedt		} else {
24130a05c769SSteven Rostedt		    $config_list{$2} = $1;
24140a05c769SSteven Rostedt		}
24150a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
24160a05c769SSteven Rostedt		$added_configs{$2} = $1;
24170a05c769SSteven Rostedt		$config_list{$2} = $1;
24180a05c769SSteven Rostedt	    }
24190a05c769SSteven Rostedt	}
24200a05c769SSteven Rostedt    }
24210a05c769SSteven Rostedt    close(IN);
24220a05c769SSteven Rostedt
24230a05c769SSteven Rostedt    my @confs = keys %removed_configs;
24240a05c769SSteven Rostedt    if ($#confs >= 0) {
24250a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
24260a05c769SSteven Rostedt	foreach my $config (@confs) {
24270a05c769SSteven Rostedt	    doprint " $config\n";
24280a05c769SSteven Rostedt	}
24290a05c769SSteven Rostedt    }
24300a05c769SSteven Rostedt    @confs = keys %added_configs;
24310a05c769SSteven Rostedt    if ($#confs >= 0) {
24320a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
24330a05c769SSteven Rostedt	foreach my $config (@confs) {
24340a05c769SSteven Rostedt	    doprint " $config\n";
24350a05c769SSteven Rostedt	}
24360a05c769SSteven Rostedt    }
24370a05c769SSteven Rostedt
24380a05c769SSteven Rostedt    my %config_test;
24390a05c769SSteven Rostedt    my $once = 0;
24400a05c769SSteven Rostedt
24410a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
24420a05c769SSteven Rostedt    # that the config we autocreate has everything we need
24430a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
24440a05c769SSteven Rostedt    # may not be able to create a new config.
24450a05c769SSteven Rostedt    # Here we create a config with everything set.
24460a05c769SSteven Rostedt    create_config (keys %config_list);
24470a05c769SSteven Rostedt    read_current_config \%config_test;
24480a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
24490a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
24500a05c769SSteven Rostedt	    if (!$once) {
24510a05c769SSteven Rostedt		$once = 1;
24520a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
24530a05c769SSteven Rostedt	    }
24540a05c769SSteven Rostedt	    doprint "  $config\n";
24550a05c769SSteven Rostedt	    delete $config_list{$config};
24560a05c769SSteven Rostedt	}
24570a05c769SSteven Rostedt    }
24580a05c769SSteven Rostedt    my $ret;
24590a05c769SSteven Rostedt    do {
24600a05c769SSteven Rostedt	$ret = run_config_bisect;
24610a05c769SSteven Rostedt    } while (!$ret);
24620a05c769SSteven Rostedt
24630a05c769SSteven Rostedt    return $ret if ($ret < 0);
24645f9b6cedSSteven Rostedt
24655f9b6cedSSteven Rostedt    success $i;
24665f9b6cedSSteven Rostedt}
24675f9b6cedSSteven Rostedt
246827d934b2SSteven Rostedtsub patchcheck_reboot {
246927d934b2SSteven Rostedt    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
24702728be41SAndrew Jones    reboot $patchcheck_sleep_time;
247127d934b2SSteven Rostedt}
247227d934b2SSteven Rostedt
24736c5ee0beSSteven Rostedtsub patchcheck {
24746c5ee0beSSteven Rostedt    my ($i) = @_;
24756c5ee0beSSteven Rostedt
24766c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
24776c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_START[$i]"}));
24786c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
24796c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
24806c5ee0beSSteven Rostedt
24816c5ee0beSSteven Rostedt    my $start = $opt{"PATCHCHECK_START[$i]"};
24826c5ee0beSSteven Rostedt
24836c5ee0beSSteven Rostedt    my $end = "HEAD";
24846c5ee0beSSteven Rostedt    if (defined($opt{"PATCHCHECK_END[$i]"})) {
24856c5ee0beSSteven Rostedt	$end = $opt{"PATCHCHECK_END[$i]"};
24866c5ee0beSSteven Rostedt    }
24876c5ee0beSSteven Rostedt
2488a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
2489a57419b3SSteven Rostedt    $start = get_sha1($start);
2490a57419b3SSteven Rostedt    $end = get_sha1($end);
2491a57419b3SSteven Rostedt
24926c5ee0beSSteven Rostedt    my $type = $opt{"PATCHCHECK_TYPE[$i]"};
24936c5ee0beSSteven Rostedt
24946c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
24956c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
24966c5ee0beSSteven Rostedt	$type = "boot";
24976c5ee0beSSteven Rostedt    }
24986c5ee0beSSteven Rostedt
24996c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
25006c5ee0beSSteven Rostedt	dodie "could not get git list";
25016c5ee0beSSteven Rostedt
25026c5ee0beSSteven Rostedt    my @list;
25036c5ee0beSSteven Rostedt
25046c5ee0beSSteven Rostedt    while (<IN>) {
25056c5ee0beSSteven Rostedt	chomp;
25066c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
25076c5ee0beSSteven Rostedt	last if (/^$start/);
25086c5ee0beSSteven Rostedt    }
25096c5ee0beSSteven Rostedt    close(IN);
25106c5ee0beSSteven Rostedt
25116c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
25122b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
25136c5ee0beSSteven Rostedt    }
25146c5ee0beSSteven Rostedt
25156c5ee0beSSteven Rostedt    # go backwards in the list
25166c5ee0beSSteven Rostedt    @list = reverse @list;
25176c5ee0beSSteven Rostedt
25186c5ee0beSSteven Rostedt    my $save_clean = $noclean;
25191990207dSSteven Rostedt    my %ignored_warnings;
25201990207dSSteven Rostedt
25211990207dSSteven Rostedt    if (defined($ignore_warnings)) {
25221990207dSSteven Rostedt	foreach my $sha1 (split /\s+/, $ignore_warnings) {
25231990207dSSteven Rostedt	    $ignored_warnings{$sha1} = 1;
25241990207dSSteven Rostedt	}
25251990207dSSteven Rostedt    }
25266c5ee0beSSteven Rostedt
25276c5ee0beSSteven Rostedt    $in_patchcheck = 1;
25286c5ee0beSSteven Rostedt    foreach my $item (@list) {
25296c5ee0beSSteven Rostedt	my $sha1 = $item;
25306c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
25316c5ee0beSSteven Rostedt
25326c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
25336c5ee0beSSteven Rostedt
25346c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
25356c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
25366c5ee0beSSteven Rostedt
25376c5ee0beSSteven Rostedt	# only clean on the first and last patch
25386c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
25396c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
25406c5ee0beSSteven Rostedt	    $noclean = $save_clean;
25416c5ee0beSSteven Rostedt	} else {
25426c5ee0beSSteven Rostedt	    $noclean = 1;
25436c5ee0beSSteven Rostedt	}
25446c5ee0beSSteven Rostedt
25456c5ee0beSSteven Rostedt	if (defined($minconfig)) {
25462b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
25476c5ee0beSSteven Rostedt	} else {
25486c5ee0beSSteven Rostedt	    # ?? no config to use?
25492b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
25506c5ee0beSSteven Rostedt	}
25516c5ee0beSSteven Rostedt
25521990207dSSteven Rostedt
25531990207dSSteven Rostedt	if (!defined($ignored_warnings{$sha1})) {
25542b7d9b21SSteven Rostedt	    check_buildlog $sha1 or return 0;
25551990207dSSteven Rostedt	}
25566c5ee0beSSteven Rostedt
25576c5ee0beSSteven Rostedt	next if ($type eq "build");
25586c5ee0beSSteven Rostedt
25597faafbd6SSteven Rostedt	my $failed = 0;
25607faafbd6SSteven Rostedt
2561ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
25627faafbd6SSteven Rostedt
25637faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
25647faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
25657faafbd6SSteven Rostedt	}
25667faafbd6SSteven Rostedt	end_monitor;
25677faafbd6SSteven Rostedt	return 0 if ($failed);
25687faafbd6SSteven Rostedt
256927d934b2SSteven Rostedt	patchcheck_reboot;
257027d934b2SSteven Rostedt
25716c5ee0beSSteven Rostedt    }
25726c5ee0beSSteven Rostedt    $in_patchcheck = 0;
25736c5ee0beSSteven Rostedt    success $i;
25742b7d9b21SSteven Rostedt
25752b7d9b21SSteven Rostedt    return 1;
25766c5ee0beSSteven Rostedt}
25776c5ee0beSSteven Rostedt
2578b9066f6cSSteven Rostedtmy %depends;
2579ac6974c7SSteven Rostedtmy %depcount;
2580b9066f6cSSteven Rostedtmy $iflevel = 0;
2581b9066f6cSSteven Rostedtmy @ifdeps;
2582b9066f6cSSteven Rostedt
2583b9066f6cSSteven Rostedt# prevent recursion
2584b9066f6cSSteven Rostedtmy %read_kconfigs;
2585b9066f6cSSteven Rostedt
2586ac6974c7SSteven Rostedtsub add_dep {
2587ac6974c7SSteven Rostedt    # $config depends on $dep
2588ac6974c7SSteven Rostedt    my ($config, $dep) = @_;
2589ac6974c7SSteven Rostedt
2590ac6974c7SSteven Rostedt    if (defined($depends{$config})) {
2591ac6974c7SSteven Rostedt	$depends{$config} .= " " . $dep;
2592ac6974c7SSteven Rostedt    } else {
2593ac6974c7SSteven Rostedt	$depends{$config} = $dep;
2594ac6974c7SSteven Rostedt    }
2595ac6974c7SSteven Rostedt
2596ac6974c7SSteven Rostedt    # record the number of configs depending on $dep
2597ac6974c7SSteven Rostedt    if (defined $depcount{$dep}) {
2598ac6974c7SSteven Rostedt	$depcount{$dep}++;
2599ac6974c7SSteven Rostedt    } else {
2600ac6974c7SSteven Rostedt	$depcount{$dep} = 1;
2601ac6974c7SSteven Rostedt    }
2602ac6974c7SSteven Rostedt}
2603ac6974c7SSteven Rostedt
2604b9066f6cSSteven Rostedt# taken from streamline_config.pl
2605b9066f6cSSteven Rostedtsub read_kconfig {
2606b9066f6cSSteven Rostedt    my ($kconfig) = @_;
2607b9066f6cSSteven Rostedt
2608b9066f6cSSteven Rostedt    my $state = "NONE";
2609b9066f6cSSteven Rostedt    my $config;
2610b9066f6cSSteven Rostedt    my @kconfigs;
2611b9066f6cSSteven Rostedt
2612b9066f6cSSteven Rostedt    my $cont = 0;
2613b9066f6cSSteven Rostedt    my $line;
2614b9066f6cSSteven Rostedt
2615b9066f6cSSteven Rostedt
2616b9066f6cSSteven Rostedt    if (! -f $kconfig) {
2617b9066f6cSSteven Rostedt	doprint "file $kconfig does not exist, skipping\n";
2618b9066f6cSSteven Rostedt	return;
2619b9066f6cSSteven Rostedt    }
2620b9066f6cSSteven Rostedt
2621b9066f6cSSteven Rostedt    open(KIN, "$kconfig")
2622b9066f6cSSteven Rostedt	or die "Can't open $kconfig";
2623b9066f6cSSteven Rostedt    while (<KIN>) {
2624b9066f6cSSteven Rostedt	chomp;
2625b9066f6cSSteven Rostedt
2626b9066f6cSSteven Rostedt	# Make sure that lines ending with \ continue
2627b9066f6cSSteven Rostedt	if ($cont) {
2628b9066f6cSSteven Rostedt	    $_ = $line . " " . $_;
2629b9066f6cSSteven Rostedt	}
2630b9066f6cSSteven Rostedt
2631b9066f6cSSteven Rostedt	if (s/\\$//) {
2632b9066f6cSSteven Rostedt	    $cont = 1;
2633b9066f6cSSteven Rostedt	    $line = $_;
2634b9066f6cSSteven Rostedt	    next;
2635b9066f6cSSteven Rostedt	}
2636b9066f6cSSteven Rostedt
2637b9066f6cSSteven Rostedt	$cont = 0;
2638b9066f6cSSteven Rostedt
2639b9066f6cSSteven Rostedt	# collect any Kconfig sources
2640b9066f6cSSteven Rostedt	if (/^source\s*"(.*)"/) {
2641b9066f6cSSteven Rostedt	    $kconfigs[$#kconfigs+1] = $1;
2642b9066f6cSSteven Rostedt	}
2643b9066f6cSSteven Rostedt
2644b9066f6cSSteven Rostedt	# configs found
2645b9066f6cSSteven Rostedt	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
2646b9066f6cSSteven Rostedt	    $state = "NEW";
2647b9066f6cSSteven Rostedt	    $config = $2;
2648b9066f6cSSteven Rostedt
2649b9066f6cSSteven Rostedt	    for (my $i = 0; $i < $iflevel; $i++) {
2650ac6974c7SSteven Rostedt		add_dep $config, $ifdeps[$i];
2651b9066f6cSSteven Rostedt	    }
2652b9066f6cSSteven Rostedt
2653b9066f6cSSteven Rostedt	# collect the depends for the config
2654b9066f6cSSteven Rostedt	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
2655b9066f6cSSteven Rostedt
2656ac6974c7SSteven Rostedt	    add_dep $config, $1;
2657b9066f6cSSteven Rostedt
2658b9066f6cSSteven Rostedt	# Get the configs that select this config
2659ac6974c7SSteven Rostedt	} elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
2660ac6974c7SSteven Rostedt
2661ac6974c7SSteven Rostedt	    # selected by depends on config
2662ac6974c7SSteven Rostedt	    add_dep $1, $config;
2663b9066f6cSSteven Rostedt
2664b9066f6cSSteven Rostedt	# Check for if statements
2665b9066f6cSSteven Rostedt	} elsif (/^if\s+(.*\S)\s*$/) {
2666b9066f6cSSteven Rostedt	    my $deps = $1;
2667b9066f6cSSteven Rostedt	    # remove beginning and ending non text
2668b9066f6cSSteven Rostedt	    $deps =~ s/^[^a-zA-Z0-9_]*//;
2669b9066f6cSSteven Rostedt	    $deps =~ s/[^a-zA-Z0-9_]*$//;
2670b9066f6cSSteven Rostedt
2671b9066f6cSSteven Rostedt	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
2672b9066f6cSSteven Rostedt
2673b9066f6cSSteven Rostedt	    $ifdeps[$iflevel++] = join ':', @deps;
2674b9066f6cSSteven Rostedt
2675b9066f6cSSteven Rostedt	} elsif (/^endif/) {
2676b9066f6cSSteven Rostedt
2677b9066f6cSSteven Rostedt	    $iflevel-- if ($iflevel);
2678b9066f6cSSteven Rostedt
2679b9066f6cSSteven Rostedt	# stop on "help"
2680b9066f6cSSteven Rostedt	} elsif (/^\s*help\s*$/) {
2681b9066f6cSSteven Rostedt	    $state = "NONE";
2682b9066f6cSSteven Rostedt	}
2683b9066f6cSSteven Rostedt    }
2684b9066f6cSSteven Rostedt    close(KIN);
2685b9066f6cSSteven Rostedt
2686b9066f6cSSteven Rostedt    # read in any configs that were found.
2687b9066f6cSSteven Rostedt    foreach $kconfig (@kconfigs) {
2688b9066f6cSSteven Rostedt	if (!defined($read_kconfigs{$kconfig})) {
2689b9066f6cSSteven Rostedt	    $read_kconfigs{$kconfig} = 1;
2690b9066f6cSSteven Rostedt	    read_kconfig("$builddir/$kconfig");
2691b9066f6cSSteven Rostedt	}
2692b9066f6cSSteven Rostedt    }
2693b9066f6cSSteven Rostedt}
2694b9066f6cSSteven Rostedt
2695b9066f6cSSteven Rostedtsub read_depends {
2696b9066f6cSSteven Rostedt    # find out which arch this is by the kconfig file
2697b9066f6cSSteven Rostedt    open (IN, $output_config)
2698b9066f6cSSteven Rostedt	or dodie "Failed to read $output_config";
2699b9066f6cSSteven Rostedt    my $arch;
2700b9066f6cSSteven Rostedt    while (<IN>) {
2701b9066f6cSSteven Rostedt	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
2702b9066f6cSSteven Rostedt	    $arch = $1;
2703b9066f6cSSteven Rostedt	    last;
2704b9066f6cSSteven Rostedt	}
2705b9066f6cSSteven Rostedt    }
2706b9066f6cSSteven Rostedt    close IN;
2707b9066f6cSSteven Rostedt
2708b9066f6cSSteven Rostedt    if (!defined($arch)) {
2709b9066f6cSSteven Rostedt	doprint "Could not find arch from config file\n";
2710b9066f6cSSteven Rostedt	doprint "no dependencies used\n";
2711b9066f6cSSteven Rostedt	return;
2712b9066f6cSSteven Rostedt    }
2713b9066f6cSSteven Rostedt
2714b9066f6cSSteven Rostedt    # arch is really the subarch, we need to know
2715b9066f6cSSteven Rostedt    # what directory to look at.
2716b9066f6cSSteven Rostedt    if ($arch eq "i386" || $arch eq "x86_64") {
2717b9066f6cSSteven Rostedt	$arch = "x86";
2718b9066f6cSSteven Rostedt    } elsif ($arch =~ /^tile/) {
2719b9066f6cSSteven Rostedt	$arch = "tile";
2720b9066f6cSSteven Rostedt    }
2721b9066f6cSSteven Rostedt
2722b9066f6cSSteven Rostedt    my $kconfig = "$builddir/arch/$arch/Kconfig";
2723b9066f6cSSteven Rostedt
2724b9066f6cSSteven Rostedt    if (! -f $kconfig && $arch =~ /\d$/) {
2725b9066f6cSSteven Rostedt	my $orig = $arch;
2726b9066f6cSSteven Rostedt 	# some subarchs have numbers, truncate them
2727b9066f6cSSteven Rostedt	$arch =~ s/\d*$//;
2728b9066f6cSSteven Rostedt	$kconfig = "$builddir/arch/$arch/Kconfig";
2729b9066f6cSSteven Rostedt	if (! -f $kconfig) {
2730b9066f6cSSteven Rostedt	    doprint "No idea what arch dir $orig is for\n";
2731b9066f6cSSteven Rostedt	    doprint "no dependencies used\n";
2732b9066f6cSSteven Rostedt	    return;
2733b9066f6cSSteven Rostedt	}
2734b9066f6cSSteven Rostedt    }
2735b9066f6cSSteven Rostedt
2736b9066f6cSSteven Rostedt    read_kconfig($kconfig);
2737b9066f6cSSteven Rostedt}
2738b9066f6cSSteven Rostedt
27394c4ab120SSteven Rostedtsub read_config_list {
27404c4ab120SSteven Rostedt    my ($config) = @_;
27414c4ab120SSteven Rostedt
27424c4ab120SSteven Rostedt    open (IN, $config)
27434c4ab120SSteven Rostedt	or dodie "Failed to read $config";
27444c4ab120SSteven Rostedt
27454c4ab120SSteven Rostedt    while (<IN>) {
27464c4ab120SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
27474c4ab120SSteven Rostedt	    if (!defined($config_ignore{$2})) {
27484c4ab120SSteven Rostedt		$config_list{$2} = $1;
27494c4ab120SSteven Rostedt	    }
27504c4ab120SSteven Rostedt	}
27514c4ab120SSteven Rostedt    }
27524c4ab120SSteven Rostedt
27534c4ab120SSteven Rostedt    close(IN);
27544c4ab120SSteven Rostedt}
27554c4ab120SSteven Rostedt
27564c4ab120SSteven Rostedtsub read_output_config {
27574c4ab120SSteven Rostedt    my ($config) = @_;
27584c4ab120SSteven Rostedt
27594c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
27604c4ab120SSteven Rostedt}
27614c4ab120SSteven Rostedt
27624c4ab120SSteven Rostedtsub make_new_config {
27634c4ab120SSteven Rostedt    my @configs = @_;
27644c4ab120SSteven Rostedt
27654c4ab120SSteven Rostedt    open (OUT, ">$output_config")
27664c4ab120SSteven Rostedt	or dodie "Failed to write $output_config";
27674c4ab120SSteven Rostedt
27684c4ab120SSteven Rostedt    foreach my $config (@configs) {
27694c4ab120SSteven Rostedt	print OUT "$config\n";
27704c4ab120SSteven Rostedt    }
27714c4ab120SSteven Rostedt    close OUT;
27724c4ab120SSteven Rostedt}
27734c4ab120SSteven Rostedt
2774ac6974c7SSteven Rostedtsub chomp_config {
2775ac6974c7SSteven Rostedt    my ($config) = @_;
2776ac6974c7SSteven Rostedt
2777ac6974c7SSteven Rostedt    $config =~ s/CONFIG_//;
2778ac6974c7SSteven Rostedt
2779ac6974c7SSteven Rostedt    return $config;
2780ac6974c7SSteven Rostedt}
2781ac6974c7SSteven Rostedt
2782b9066f6cSSteven Rostedtsub get_depends {
2783b9066f6cSSteven Rostedt    my ($dep) = @_;
2784b9066f6cSSteven Rostedt
2785ac6974c7SSteven Rostedt    my $kconfig = chomp_config $dep;
2786b9066f6cSSteven Rostedt
2787b9066f6cSSteven Rostedt    $dep = $depends{"$kconfig"};
2788b9066f6cSSteven Rostedt
2789b9066f6cSSteven Rostedt    # the dep string we have saves the dependencies as they
2790b9066f6cSSteven Rostedt    # were found, including expressions like ! && ||. We
2791b9066f6cSSteven Rostedt    # want to split this out into just an array of configs.
2792b9066f6cSSteven Rostedt
2793b9066f6cSSteven Rostedt    my $valid = "A-Za-z_0-9";
2794b9066f6cSSteven Rostedt
2795b9066f6cSSteven Rostedt    my @configs;
2796b9066f6cSSteven Rostedt
2797b9066f6cSSteven Rostedt    while ($dep =~ /[$valid]/) {
2798b9066f6cSSteven Rostedt
2799b9066f6cSSteven Rostedt	if ($dep =~ /^[^$valid]*([$valid]+)/) {
2800b9066f6cSSteven Rostedt	    my $conf = "CONFIG_" . $1;
2801b9066f6cSSteven Rostedt
2802b9066f6cSSteven Rostedt	    $configs[$#configs + 1] = $conf;
2803b9066f6cSSteven Rostedt
2804b9066f6cSSteven Rostedt	    $dep =~ s/^[^$valid]*[$valid]+//;
2805b9066f6cSSteven Rostedt	} else {
2806b9066f6cSSteven Rostedt	    die "this should never happen";
2807b9066f6cSSteven Rostedt	}
2808b9066f6cSSteven Rostedt    }
2809b9066f6cSSteven Rostedt
2810b9066f6cSSteven Rostedt    return @configs;
2811b9066f6cSSteven Rostedt}
2812b9066f6cSSteven Rostedt
2813b9066f6cSSteven Rostedtmy %min_configs;
2814b9066f6cSSteven Rostedtmy %keep_configs;
281543d1b651SSteven Rostedtmy %save_configs;
2816b9066f6cSSteven Rostedtmy %processed_configs;
2817b9066f6cSSteven Rostedtmy %nochange_config;
2818b9066f6cSSteven Rostedt
2819b9066f6cSSteven Rostedtsub test_this_config {
2820b9066f6cSSteven Rostedt    my ($config) = @_;
2821b9066f6cSSteven Rostedt
2822b9066f6cSSteven Rostedt    my $found;
2823b9066f6cSSteven Rostedt
2824b9066f6cSSteven Rostedt    # if we already processed this config, skip it
2825b9066f6cSSteven Rostedt    if (defined($processed_configs{$config})) {
2826b9066f6cSSteven Rostedt	return undef;
2827b9066f6cSSteven Rostedt    }
2828b9066f6cSSteven Rostedt    $processed_configs{$config} = 1;
2829b9066f6cSSteven Rostedt
2830b9066f6cSSteven Rostedt    # if this config failed during this round, skip it
2831b9066f6cSSteven Rostedt    if (defined($nochange_config{$config})) {
2832b9066f6cSSteven Rostedt	return undef;
2833b9066f6cSSteven Rostedt    }
2834b9066f6cSSteven Rostedt
2835ac6974c7SSteven Rostedt    my $kconfig = chomp_config $config;
2836b9066f6cSSteven Rostedt
2837b9066f6cSSteven Rostedt    # Test dependencies first
2838b9066f6cSSteven Rostedt    if (defined($depends{"$kconfig"})) {
2839b9066f6cSSteven Rostedt	my @parents = get_depends $config;
2840b9066f6cSSteven Rostedt	foreach my $parent (@parents) {
2841b9066f6cSSteven Rostedt	    # if the parent is in the min config, check it first
2842b9066f6cSSteven Rostedt	    next if (!defined($min_configs{$parent}));
2843b9066f6cSSteven Rostedt	    $found = test_this_config($parent);
2844b9066f6cSSteven Rostedt	    if (defined($found)) {
2845b9066f6cSSteven Rostedt		return $found;
2846b9066f6cSSteven Rostedt	    }
2847b9066f6cSSteven Rostedt	}
2848b9066f6cSSteven Rostedt    }
2849b9066f6cSSteven Rostedt
2850b9066f6cSSteven Rostedt    # Remove this config from the list of configs
2851b9066f6cSSteven Rostedt    # do a make oldnoconfig and then read the resulting
2852b9066f6cSSteven Rostedt    # .config to make sure it is missing the config that
2853b9066f6cSSteven Rostedt    # we had before
2854b9066f6cSSteven Rostedt    my %configs = %min_configs;
2855b9066f6cSSteven Rostedt    delete $configs{$config};
2856b9066f6cSSteven Rostedt    make_new_config ((values %configs), (values %keep_configs));
2857b9066f6cSSteven Rostedt    make_oldconfig;
2858b9066f6cSSteven Rostedt    undef %configs;
2859b9066f6cSSteven Rostedt    assign_configs \%configs, $output_config;
2860b9066f6cSSteven Rostedt
2861b9066f6cSSteven Rostedt    return $config if (!defined($configs{$config}));
2862b9066f6cSSteven Rostedt
2863b9066f6cSSteven Rostedt    doprint "disabling config $config did not change .config\n";
2864b9066f6cSSteven Rostedt
2865b9066f6cSSteven Rostedt    $nochange_config{$config} = 1;
2866b9066f6cSSteven Rostedt
2867b9066f6cSSteven Rostedt    return undef;
2868b9066f6cSSteven Rostedt}
2869b9066f6cSSteven Rostedt
28704c4ab120SSteven Rostedtsub make_min_config {
28714c4ab120SSteven Rostedt    my ($i) = @_;
28724c4ab120SSteven Rostedt
28734c4ab120SSteven Rostedt    if (!defined($output_minconfig)) {
28744c4ab120SSteven Rostedt	fail "OUTPUT_MIN_CONFIG not defined" and return;
28754c4ab120SSteven Rostedt    }
287635ce5952SSteven Rostedt
287735ce5952SSteven Rostedt    # If output_minconfig exists, and the start_minconfig
287835ce5952SSteven Rostedt    # came from min_config, than ask if we should use
287935ce5952SSteven Rostedt    # that instead.
288035ce5952SSteven Rostedt    if (-f $output_minconfig && !$start_minconfig_defined) {
288135ce5952SSteven Rostedt	print "$output_minconfig exists\n";
288235ce5952SSteven Rostedt	if (read_yn " Use it as minconfig?") {
288335ce5952SSteven Rostedt	    $start_minconfig = $output_minconfig;
288435ce5952SSteven Rostedt	}
288535ce5952SSteven Rostedt    }
288635ce5952SSteven Rostedt
28874c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
28884c4ab120SSteven Rostedt	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
28894c4ab120SSteven Rostedt    }
28904c4ab120SSteven Rostedt
289135ce5952SSteven Rostedt    my $temp_config = "$tmpdir/temp_config";
289235ce5952SSteven Rostedt
28934c4ab120SSteven Rostedt    # First things first. We build an allnoconfig to find
28944c4ab120SSteven Rostedt    # out what the defaults are that we can't touch.
28954c4ab120SSteven Rostedt    # Some are selections, but we really can't handle selections.
28964c4ab120SSteven Rostedt
28974c4ab120SSteven Rostedt    my $save_minconfig = $minconfig;
28984c4ab120SSteven Rostedt    undef $minconfig;
28994c4ab120SSteven Rostedt
29004c4ab120SSteven Rostedt    run_command "$make allnoconfig" or return 0;
29014c4ab120SSteven Rostedt
2902b9066f6cSSteven Rostedt    read_depends;
2903b9066f6cSSteven Rostedt
29044c4ab120SSteven Rostedt    process_config_ignore $output_config;
2905b9066f6cSSteven Rostedt
290643d1b651SSteven Rostedt    undef %save_configs;
2907b9066f6cSSteven Rostedt    undef %min_configs;
29084c4ab120SSteven Rostedt
29094c4ab120SSteven Rostedt    if (defined($ignore_config)) {
29104c4ab120SSteven Rostedt	# make sure the file exists
29114c4ab120SSteven Rostedt	`touch $ignore_config`;
291243d1b651SSteven Rostedt	assign_configs \%save_configs, $ignore_config;
29134c4ab120SSteven Rostedt    }
29144c4ab120SSteven Rostedt
291543d1b651SSteven Rostedt    %keep_configs = %save_configs;
291643d1b651SSteven Rostedt
29174c4ab120SSteven Rostedt    doprint "Load initial configs from $start_minconfig\n";
29184c4ab120SSteven Rostedt
29194c4ab120SSteven Rostedt    # Look at the current min configs, and save off all the
29204c4ab120SSteven Rostedt    # ones that were set via the allnoconfig
29214c4ab120SSteven Rostedt    assign_configs \%min_configs, $start_minconfig;
29224c4ab120SSteven Rostedt
29234c4ab120SSteven Rostedt    my @config_keys = keys %min_configs;
29244c4ab120SSteven Rostedt
2925ac6974c7SSteven Rostedt    # All configs need a depcount
2926ac6974c7SSteven Rostedt    foreach my $config (@config_keys) {
2927ac6974c7SSteven Rostedt	my $kconfig = chomp_config $config;
2928ac6974c7SSteven Rostedt	if (!defined $depcount{$kconfig}) {
2929ac6974c7SSteven Rostedt		$depcount{$kconfig} = 0;
2930ac6974c7SSteven Rostedt	}
2931ac6974c7SSteven Rostedt    }
2932ac6974c7SSteven Rostedt
29334c4ab120SSteven Rostedt    # Remove anything that was set by the make allnoconfig
29344c4ab120SSteven Rostedt    # we shouldn't need them as they get set for us anyway.
29354c4ab120SSteven Rostedt    foreach my $config (@config_keys) {
29364c4ab120SSteven Rostedt	# Remove anything in the ignore_config
29374c4ab120SSteven Rostedt	if (defined($keep_configs{$config})) {
29384c4ab120SSteven Rostedt	    my $file = $ignore_config;
29394c4ab120SSteven Rostedt	    $file =~ s,.*/(.*?)$,$1,;
29404c4ab120SSteven Rostedt	    doprint "$config set by $file ... ignored\n";
29414c4ab120SSteven Rostedt	    delete $min_configs{$config};
29424c4ab120SSteven Rostedt	    next;
29434c4ab120SSteven Rostedt	}
29444c4ab120SSteven Rostedt	# But make sure the settings are the same. If a min config
29454c4ab120SSteven Rostedt	# sets a selection, we do not want to get rid of it if
29464c4ab120SSteven Rostedt	# it is not the same as what we have. Just move it into
29474c4ab120SSteven Rostedt	# the keep configs.
29484c4ab120SSteven Rostedt	if (defined($config_ignore{$config})) {
29494c4ab120SSteven Rostedt	    if ($config_ignore{$config} ne $min_configs{$config}) {
29504c4ab120SSteven Rostedt		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
29514c4ab120SSteven Rostedt		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
29524c4ab120SSteven Rostedt		$keep_configs{$config} = $min_configs{$config};
29534c4ab120SSteven Rostedt	    } else {
29544c4ab120SSteven Rostedt		doprint "$config set by allnoconfig ... ignored\n";
29554c4ab120SSteven Rostedt	    }
29564c4ab120SSteven Rostedt	    delete $min_configs{$config};
29574c4ab120SSteven Rostedt	}
29584c4ab120SSteven Rostedt    }
29594c4ab120SSteven Rostedt
29604c4ab120SSteven Rostedt    my $done = 0;
2961b9066f6cSSteven Rostedt    my $take_two = 0;
29624c4ab120SSteven Rostedt
29634c4ab120SSteven Rostedt    while (!$done) {
29644c4ab120SSteven Rostedt
29654c4ab120SSteven Rostedt	my $config;
29664c4ab120SSteven Rostedt	my $found;
29674c4ab120SSteven Rostedt
29684c4ab120SSteven Rostedt	# Now disable each config one by one and do a make oldconfig
29694c4ab120SSteven Rostedt	# till we find a config that changes our list.
29704c4ab120SSteven Rostedt
29714c4ab120SSteven Rostedt	my @test_configs = keys %min_configs;
2972ac6974c7SSteven Rostedt
2973ac6974c7SSteven Rostedt	# Sort keys by who is most dependent on
2974ac6974c7SSteven Rostedt	@test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
2975ac6974c7SSteven Rostedt			  @test_configs ;
2976ac6974c7SSteven Rostedt
2977ac6974c7SSteven Rostedt	# Put configs that did not modify the config at the end.
29784c4ab120SSteven Rostedt	my $reset = 1;
29794c4ab120SSteven Rostedt	for (my $i = 0; $i < $#test_configs; $i++) {
29804c4ab120SSteven Rostedt	    if (!defined($nochange_config{$test_configs[0]})) {
29814c4ab120SSteven Rostedt		$reset = 0;
29824c4ab120SSteven Rostedt		last;
29834c4ab120SSteven Rostedt	    }
29844c4ab120SSteven Rostedt	    # This config didn't change the .config last time.
29854c4ab120SSteven Rostedt	    # Place it at the end
29864c4ab120SSteven Rostedt	    my $config = shift @test_configs;
29874c4ab120SSteven Rostedt	    push @test_configs, $config;
29884c4ab120SSteven Rostedt	}
29894c4ab120SSteven Rostedt
29904c4ab120SSteven Rostedt	# if every test config has failed to modify the .config file
29914c4ab120SSteven Rostedt	# in the past, then reset and start over.
29924c4ab120SSteven Rostedt	if ($reset) {
29934c4ab120SSteven Rostedt	    undef %nochange_config;
29944c4ab120SSteven Rostedt	}
29954c4ab120SSteven Rostedt
2996b9066f6cSSteven Rostedt	undef %processed_configs;
2997b9066f6cSSteven Rostedt
29984c4ab120SSteven Rostedt	foreach my $config (@test_configs) {
29994c4ab120SSteven Rostedt
3000b9066f6cSSteven Rostedt	    $found = test_this_config $config;
30014c4ab120SSteven Rostedt
3002b9066f6cSSteven Rostedt	    last if (defined($found));
30034c4ab120SSteven Rostedt
30044c4ab120SSteven Rostedt	    # oh well, try another config
30054c4ab120SSteven Rostedt	}
30064c4ab120SSteven Rostedt
30074c4ab120SSteven Rostedt	if (!defined($found)) {
3008b9066f6cSSteven Rostedt	    # we could have failed due to the nochange_config hash
3009b9066f6cSSteven Rostedt	    # reset and try again
3010b9066f6cSSteven Rostedt	    if (!$take_two) {
3011b9066f6cSSteven Rostedt		undef %nochange_config;
3012b9066f6cSSteven Rostedt		$take_two = 1;
3013b9066f6cSSteven Rostedt		next;
3014b9066f6cSSteven Rostedt	    }
30154c4ab120SSteven Rostedt	    doprint "No more configs found that we can disable\n";
30164c4ab120SSteven Rostedt	    $done = 1;
30174c4ab120SSteven Rostedt	    last;
30184c4ab120SSteven Rostedt	}
3019b9066f6cSSteven Rostedt	$take_two = 0;
30204c4ab120SSteven Rostedt
30214c4ab120SSteven Rostedt	$config = $found;
30224c4ab120SSteven Rostedt
30234c4ab120SSteven Rostedt	doprint "Test with $config disabled\n";
30244c4ab120SSteven Rostedt
30254c4ab120SSteven Rostedt	# set in_bisect to keep build and monitor from dieing
30264c4ab120SSteven Rostedt	$in_bisect = 1;
30274c4ab120SSteven Rostedt
30284c4ab120SSteven Rostedt	my $failed = 0;
30294c4ab120SSteven Rostedt	build "oldconfig";
30304c4ab120SSteven Rostedt	start_monitor_and_boot or $failed = 1;
30314c4ab120SSteven Rostedt	end_monitor;
30324c4ab120SSteven Rostedt
30334c4ab120SSteven Rostedt	$in_bisect = 0;
30344c4ab120SSteven Rostedt
30354c4ab120SSteven Rostedt	if ($failed) {
3036b9066f6cSSteven Rostedt	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
30374c4ab120SSteven Rostedt	    # this config is needed, add it to the ignore list.
30384c4ab120SSteven Rostedt	    $keep_configs{$config} = $min_configs{$config};
303943d1b651SSteven Rostedt	    $save_configs{$config} = $min_configs{$config};
30404c4ab120SSteven Rostedt	    delete $min_configs{$config};
304135ce5952SSteven Rostedt
304235ce5952SSteven Rostedt	    # update new ignore configs
304335ce5952SSteven Rostedt	    if (defined($ignore_config)) {
304435ce5952SSteven Rostedt		open (OUT, ">$temp_config")
304535ce5952SSteven Rostedt		    or die "Can't write to $temp_config";
304643d1b651SSteven Rostedt		foreach my $config (keys %save_configs) {
304743d1b651SSteven Rostedt		    print OUT "$save_configs{$config}\n";
304835ce5952SSteven Rostedt		}
304935ce5952SSteven Rostedt		close OUT;
305035ce5952SSteven Rostedt		run_command "mv $temp_config $ignore_config" or
305135ce5952SSteven Rostedt		    dodie "failed to copy update to $ignore_config";
305235ce5952SSteven Rostedt	    }
305335ce5952SSteven Rostedt
30544c4ab120SSteven Rostedt	} else {
30554c4ab120SSteven Rostedt	    # We booted without this config, remove it from the minconfigs.
30564c4ab120SSteven Rostedt	    doprint "$config is not needed, disabling\n";
30574c4ab120SSteven Rostedt
30584c4ab120SSteven Rostedt	    delete $min_configs{$config};
30594c4ab120SSteven Rostedt
30604c4ab120SSteven Rostedt	    # Also disable anything that is not enabled in this config
30614c4ab120SSteven Rostedt	    my %configs;
30624c4ab120SSteven Rostedt	    assign_configs \%configs, $output_config;
30634c4ab120SSteven Rostedt	    my @config_keys = keys %min_configs;
30644c4ab120SSteven Rostedt	    foreach my $config (@config_keys) {
30654c4ab120SSteven Rostedt		if (!defined($configs{$config})) {
30664c4ab120SSteven Rostedt		    doprint "$config is not set, disabling\n";
30674c4ab120SSteven Rostedt		    delete $min_configs{$config};
30684c4ab120SSteven Rostedt		}
30694c4ab120SSteven Rostedt	    }
30704c4ab120SSteven Rostedt
30714c4ab120SSteven Rostedt	    # Save off all the current mandidory configs
307235ce5952SSteven Rostedt	    open (OUT, ">$temp_config")
307335ce5952SSteven Rostedt		or die "Can't write to $temp_config";
30744c4ab120SSteven Rostedt	    foreach my $config (keys %keep_configs) {
30754c4ab120SSteven Rostedt		print OUT "$keep_configs{$config}\n";
30764c4ab120SSteven Rostedt	    }
30774c4ab120SSteven Rostedt	    foreach my $config (keys %min_configs) {
30784c4ab120SSteven Rostedt		print OUT "$min_configs{$config}\n";
30794c4ab120SSteven Rostedt	    }
30804c4ab120SSteven Rostedt	    close OUT;
308135ce5952SSteven Rostedt
308235ce5952SSteven Rostedt	    run_command "mv $temp_config $output_minconfig" or
308335ce5952SSteven Rostedt		dodie "failed to copy update to $output_minconfig";
30844c4ab120SSteven Rostedt	}
30854c4ab120SSteven Rostedt
30864c4ab120SSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
30872728be41SAndrew Jones	reboot $sleep_time;
30884c4ab120SSteven Rostedt    }
30894c4ab120SSteven Rostedt
30904c4ab120SSteven Rostedt    success $i;
30914c4ab120SSteven Rostedt    return 1;
30924c4ab120SSteven Rostedt}
30934c4ab120SSteven Rostedt
30948d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
30952545eb61SSteven Rostedt
30968d1491baSSteven Rostedtif ($#ARGV == 0) {
30978d1491baSSteven Rostedt    $ktest_config = $ARGV[0];
30988d1491baSSteven Rostedt    if (! -f $ktest_config) {
30998d1491baSSteven Rostedt	print "$ktest_config does not exist.\n";
310035ce5952SSteven Rostedt	if (!read_yn "Create it?") {
31018d1491baSSteven Rostedt	    exit 0;
31028d1491baSSteven Rostedt	}
31038d1491baSSteven Rostedt    }
31048d1491baSSteven Rostedt} else {
31058d1491baSSteven Rostedt    $ktest_config = "ktest.conf";
31068d1491baSSteven Rostedt}
31078d1491baSSteven Rostedt
31088d1491baSSteven Rostedtif (! -f $ktest_config) {
3109*dbd3783bSSteven Rostedt    $newconfig = 1;
3110c4261d0fSSteven Rostedt    get_test_case;
31118d1491baSSteven Rostedt    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
31128d1491baSSteven Rostedt    print OUT << "EOF"
31138d1491baSSteven Rostedt# Generated by ktest.pl
31148d1491baSSteven Rostedt#
31150e7a22deSSteven Rostedt
31160e7a22deSSteven Rostedt# PWD is a ktest.pl variable that will result in the process working
31170e7a22deSSteven Rostedt# directory that ktest.pl is executed in.
31180e7a22deSSteven Rostedt
31190e7a22deSSteven Rostedt# THIS_DIR is automatically assigned the PWD of the path that generated
31200e7a22deSSteven Rostedt# the config file. It is best to use this variable when assigning other
31210e7a22deSSteven Rostedt# directory paths within this directory. This allows you to easily
31220e7a22deSSteven Rostedt# move the test cases to other locations or to other machines.
31230e7a22deSSteven Rostedt#
31240e7a22deSSteven RostedtTHIS_DIR := $variable{"PWD"}
31250e7a22deSSteven Rostedt
31268d1491baSSteven Rostedt# Define each test with TEST_START
31278d1491baSSteven Rostedt# The config options below it will override the defaults
31288d1491baSSteven RostedtTEST_START
3129c4261d0fSSteven RostedtTEST_TYPE = $default{"TEST_TYPE"}
31308d1491baSSteven Rostedt
31318d1491baSSteven RostedtDEFAULTS
31328d1491baSSteven RostedtEOF
31338d1491baSSteven Rostedt;
31348d1491baSSteven Rostedt    close(OUT);
31358d1491baSSteven Rostedt}
31368d1491baSSteven Rostedtread_config $ktest_config;
31378d1491baSSteven Rostedt
313823715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) {
313923715c3cSSteven Rostedt    $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
314023715c3cSSteven Rostedt}
314123715c3cSSteven Rostedt
31428d1491baSSteven Rostedt# Append any configs entered in manually to the config file.
31438d1491baSSteven Rostedtmy @new_configs = keys %entered_configs;
31448d1491baSSteven Rostedtif ($#new_configs >= 0) {
31458d1491baSSteven Rostedt    print "\nAppending entered in configs to $ktest_config\n";
31468d1491baSSteven Rostedt    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
31478d1491baSSteven Rostedt    foreach my $config (@new_configs) {
31488d1491baSSteven Rostedt	print OUT "$config = $entered_configs{$config}\n";
31490e7a22deSSteven Rostedt	$opt{$config} = process_variables($entered_configs{$config});
31508d1491baSSteven Rostedt    }
31518d1491baSSteven Rostedt}
31522545eb61SSteven Rostedt
31532b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
31542b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
31552b7d9b21SSteven Rostedt}
31562545eb61SSteven Rostedt
31572b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
31582b7d9b21SSteven Rostedt
3159a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
3160a57419b3SSteven Rostedt
3161a57419b3SSteven Rostedt    if (!$i) {
3162a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
3163a57419b3SSteven Rostedt    } else {
3164a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
3165a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
3166a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
3167a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
3168a57419b3SSteven Rostedt	}
3169a57419b3SSteven Rostedt	doprint "\n";
3170a57419b3SSteven Rostedt    }
3171a57419b3SSteven Rostedt
31722b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
3173a57419b3SSteven Rostedt
3174a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
3175a57419b3SSteven Rostedt	    next if ($i != $1);
3176a57419b3SSteven Rostedt	} else {
3177a57419b3SSteven Rostedt	    next if ($i);
3178a57419b3SSteven Rostedt	}
3179a57419b3SSteven Rostedt
31802b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
31812b7d9b21SSteven Rostedt    }
3182a57419b3SSteven Rostedt}
31832545eb61SSteven Rostedt
31842a62512bSSteven Rostedtsub __set_test_option {
31855a391fbfSSteven Rostedt    my ($name, $i) = @_;
31865a391fbfSSteven Rostedt
31875a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
31885a391fbfSSteven Rostedt
31895a391fbfSSteven Rostedt    if (defined($opt{$option})) {
31905a391fbfSSteven Rostedt	return $opt{$option};
31915a391fbfSSteven Rostedt    }
31925a391fbfSSteven Rostedt
3193a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
3194a57419b3SSteven Rostedt	if ($i >= $test &&
3195a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
3196a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
3197a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
3198a57419b3SSteven Rostedt		return $opt{$option};
3199a57419b3SSteven Rostedt	    }
3200a57419b3SSteven Rostedt	}
3201a57419b3SSteven Rostedt    }
3202a57419b3SSteven Rostedt
32035a391fbfSSteven Rostedt    if (defined($opt{$name})) {
32045a391fbfSSteven Rostedt	return $opt{$name};
32055a391fbfSSteven Rostedt    }
32065a391fbfSSteven Rostedt
32075a391fbfSSteven Rostedt    return undef;
32085a391fbfSSteven Rostedt}
32095a391fbfSSteven Rostedt
32102a62512bSSteven Rostedtsub set_test_option {
32112a62512bSSteven Rostedt    my ($name, $i) = @_;
32122a62512bSSteven Rostedt
32132a62512bSSteven Rostedt    my $option = __set_test_option($name, $i);
32142a62512bSSteven Rostedt    return $option if (!defined($option));
32152a62512bSSteven Rostedt
321623715c3cSSteven Rostedt    return eval_option($option, $i);
32172a62512bSSteven Rostedt}
32182a62512bSSteven Rostedt
32192545eb61SSteven Rostedt# First we need to do is the builds
3220a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
32212545eb61SSteven Rostedt
32224ab1cce5SSteven Rostedt    # Do not reboot on failing test options
32234ab1cce5SSteven Rostedt    $no_reboot = 1;
32244ab1cce5SSteven Rostedt
3225576f627cSSteven Rostedt    $iteration = $i;
3226576f627cSSteven Rostedt
3227a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
3228a75fececSSteven Rostedt
3229a75fececSSteven Rostedt    $machine = set_test_option("MACHINE", $i);
3230e48c5293SSteven Rostedt    $ssh_user = set_test_option("SSH_USER", $i);
3231a75fececSSteven Rostedt    $tmpdir = set_test_option("TMP_DIR", $i);
3232a75fececSSteven Rostedt    $outputdir = set_test_option("OUTPUT_DIR", $i);
3233a75fececSSteven Rostedt    $builddir = set_test_option("BUILD_DIR", $i);
3234a75fececSSteven Rostedt    $test_type = set_test_option("TEST_TYPE", $i);
3235a75fececSSteven Rostedt    $build_type = set_test_option("BUILD_TYPE", $i);
3236a75fececSSteven Rostedt    $build_options = set_test_option("BUILD_OPTIONS", $i);
32370bd6c1a3SSteven Rostedt    $pre_build = set_test_option("PRE_BUILD", $i);
32380bd6c1a3SSteven Rostedt    $post_build = set_test_option("POST_BUILD", $i);
32390bd6c1a3SSteven Rostedt    $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
32400bd6c1a3SSteven Rostedt    $post_build_die = set_test_option("POST_BUILD_DIE", $i);
3241a75fececSSteven Rostedt    $power_cycle = set_test_option("POWER_CYCLE", $i);
3242e48c5293SSteven Rostedt    $reboot = set_test_option("REBOOT", $i);
3243a75fececSSteven Rostedt    $noclean = set_test_option("BUILD_NOCLEAN", $i);
3244a75fececSSteven Rostedt    $minconfig = set_test_option("MIN_CONFIG", $i);
32454c4ab120SSteven Rostedt    $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i);
32464c4ab120SSteven Rostedt    $start_minconfig = set_test_option("START_MIN_CONFIG", $i);
32474c4ab120SSteven Rostedt    $ignore_config = set_test_option("IGNORE_CONFIG", $i);
3248a75fececSSteven Rostedt    $run_test = set_test_option("TEST", $i);
3249a75fececSSteven Rostedt    $addconfig = set_test_option("ADD_CONFIG", $i);
3250a75fececSSteven Rostedt    $reboot_type = set_test_option("REBOOT_TYPE", $i);
3251a75fececSSteven Rostedt    $grub_menu = set_test_option("GRUB_MENU", $i);
32528b37ca8cSSteven Rostedt    $post_install = set_test_option("POST_INSTALL", $i);
3253e0a8742eSSteven Rostedt    $no_install = set_test_option("NO_INSTALL", $i);
3254a75fececSSteven Rostedt    $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
3255a75fececSSteven Rostedt    $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
3256a75fececSSteven Rostedt    $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
3257a75fececSSteven Rostedt    $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
3258a75fececSSteven Rostedt    $power_off = set_test_option("POWER_OFF", $i);
3259576f627cSSteven Rostedt    $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
3260576f627cSSteven Rostedt    $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
3261a75fececSSteven Rostedt    $sleep_time = set_test_option("SLEEP_TIME", $i);
3262a75fececSSteven Rostedt    $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
326327d934b2SSteven Rostedt    $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
32641990207dSSteven Rostedt    $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
3265c960bb9fSSteven Rostedt    $bisect_manual = set_test_option("BISECT_MANUAL", $i);
3266c23dca7cSSteven Rostedt    $bisect_skip = set_test_option("BISECT_SKIP", $i);
326730f75da5SSteven Rostedt    $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
3268a75fececSSteven Rostedt    $store_failures = set_test_option("STORE_FAILURES", $i);
3269de5b6e3bSRabin Vincent    $store_successes = set_test_option("STORE_SUCCESSES", $i);
32709064af52SSteven Rostedt    $test_name = set_test_option("TEST_NAME", $i);
3271a75fececSSteven Rostedt    $timeout = set_test_option("TIMEOUT", $i);
3272a75fececSSteven Rostedt    $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
3273a75fececSSteven Rostedt    $console = set_test_option("CONSOLE", $i);
3274f1a5b962SSteven Rostedt    $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
3275a75fececSSteven Rostedt    $success_line = set_test_option("SUCCESS_LINE", $i);
32762b803365SSteven Rostedt    $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i);
32771c8a617aSSteven Rostedt    $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
32781c8a617aSSteven Rostedt    $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
32792d01b26aSSteven Rostedt    $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
3280a75fececSSteven Rostedt    $build_target = set_test_option("BUILD_TARGET", $i);
3281e48c5293SSteven Rostedt    $ssh_exec = set_test_option("SSH_EXEC", $i);
3282e48c5293SSteven Rostedt    $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
3283a75fececSSteven Rostedt    $target_image = set_test_option("TARGET_IMAGE", $i);
3284a75fececSSteven Rostedt    $localversion = set_test_option("LOCALVERSION", $i);
3285a75fececSSteven Rostedt
328635ce5952SSteven Rostedt    $start_minconfig_defined = 1;
328735ce5952SSteven Rostedt
32884c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
328935ce5952SSteven Rostedt	$start_minconfig_defined = 0;
32904c4ab120SSteven Rostedt	$start_minconfig = $minconfig;
32914c4ab120SSteven Rostedt    }
32924c4ab120SSteven Rostedt
3293a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
3294a75fececSSteven Rostedt
3295a908a665SAndrew Jones    foreach my $dir ($tmpdir, $outputdir) {
3296a908a665SAndrew Jones	if (!-d $dir) {
3297a908a665SAndrew Jones	    mkpath($dir) or
3298a908a665SAndrew Jones		die "can't create $dir";
3299a908a665SAndrew Jones	}
3300a75fececSSteven Rostedt    }
3301a75fececSSteven Rostedt
3302e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
3303e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
3304e48c5293SSteven Rostedt
3305a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
3306a9dd5d63SRabin Vincent    $testlog = "$tmpdir/testlog-$machine";
3307a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
3308a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
330951ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
3310a75fececSSteven Rostedt
3311bb8474b1SSteven Rostedt    if (!$buildonly) {
3312bb8474b1SSteven Rostedt	$target = "$ssh_user\@$machine";
3313a75fececSSteven Rostedt	if ($reboot_type eq "grub") {
3314576f627cSSteven Rostedt	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3315a75fececSSteven Rostedt	} elsif (!defined($reboot_script)) {
3316576f627cSSteven Rostedt	    dodie "REBOOT_SCRIPT not defined"
3317a75fececSSteven Rostedt	}
3318bb8474b1SSteven Rostedt    }
3319a75fececSSteven Rostedt
3320a75fececSSteven Rostedt    my $run_type = $build_type;
3321a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
3322a75fececSSteven Rostedt	$run_type = $opt{"PATCHCHECK_TYPE[$i]"};
3323a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
3324a75fececSSteven Rostedt	$run_type = $opt{"BISECT_TYPE[$i]"};
33250a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
33260a05c769SSteven Rostedt	$run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
3327a75fececSSteven Rostedt    }
3328a75fececSSteven Rostedt
33294c4ab120SSteven Rostedt    if ($test_type eq "make_min_config") {
33304c4ab120SSteven Rostedt	$run_type = "";
33314c4ab120SSteven Rostedt    }
33324c4ab120SSteven Rostedt
3333a75fececSSteven Rostedt    # mistake in config file?
3334a75fececSSteven Rostedt    if (!defined($run_type)) {
3335a75fececSSteven Rostedt	$run_type = "ERROR";
3336a75fececSSteven Rostedt    }
33372545eb61SSteven Rostedt
3338e0a8742eSSteven Rostedt    my $installme = "";
3339e0a8742eSSteven Rostedt    $installme = " no_install" if ($no_install);
3340e0a8742eSSteven Rostedt
33412545eb61SSteven Rostedt    doprint "\n\n";
3342e0a8742eSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
33437faafbd6SSteven Rostedt
33447faafbd6SSteven Rostedt    unlink $dmesg;
33457faafbd6SSteven Rostedt    unlink $buildlog;
3346a9dd5d63SRabin Vincent    unlink $testlog;
33472545eb61SSteven Rostedt
3348250bae8bSSteven Rostedt    if (defined($addconfig)) {
3349250bae8bSSteven Rostedt	my $min = $minconfig;
33502b7d9b21SSteven Rostedt	if (!defined($minconfig)) {
3351250bae8bSSteven Rostedt	    $min = "";
3352250bae8bSSteven Rostedt	}
3353250bae8bSSteven Rostedt	run_command "cat $addconfig $min > $tmpdir/add_config" or
33542b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
33559be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
33562b7d9b21SSteven Rostedt    }
33572b7d9b21SSteven Rostedt
33586c5ee0beSSteven Rostedt    my $checkout = $opt{"CHECKOUT[$i]"};
33596c5ee0beSSteven Rostedt    if (defined($checkout)) {
33606c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
33616c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
33626c5ee0beSSteven Rostedt    }
33636c5ee0beSSteven Rostedt
33644ab1cce5SSteven Rostedt    $no_reboot = 0;
33654ab1cce5SSteven Rostedt
33664ab1cce5SSteven Rostedt
3367a75fececSSteven Rostedt    if ($test_type eq "bisect") {
33685f9b6cedSSteven Rostedt	bisect $i;
33695f9b6cedSSteven Rostedt	next;
33700a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
33710a05c769SSteven Rostedt	config_bisect $i;
33720a05c769SSteven Rostedt	next;
3373a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
33746c5ee0beSSteven Rostedt	patchcheck $i;
33756c5ee0beSSteven Rostedt	next;
33764c4ab120SSteven Rostedt    } elsif ($test_type eq "make_min_config") {
33774c4ab120SSteven Rostedt	make_min_config $i;
33784c4ab120SSteven Rostedt	next;
33795f9b6cedSSteven Rostedt    }
33805f9b6cedSSteven Rostedt
33817faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
33827faafbd6SSteven Rostedt	build $build_type or next;
33832545eb61SSteven Rostedt    }
33842545eb61SSteven Rostedt
3385cd8e368fSSteven Rostedt    if ($test_type eq "install") {
3386cd8e368fSSteven Rostedt	get_version;
3387cd8e368fSSteven Rostedt	install;
3388cd8e368fSSteven Rostedt	success $i;
3389cd8e368fSSteven Rostedt	next;
3390cd8e368fSSteven Rostedt    }
3391cd8e368fSSteven Rostedt
3392a75fececSSteven Rostedt    if ($test_type ne "build") {
33937faafbd6SSteven Rostedt	my $failed = 0;
3394ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
3395a75fececSSteven Rostedt
3396a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
33977faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
33985a391fbfSSteven Rostedt	}
33997faafbd6SSteven Rostedt	end_monitor;
34007faafbd6SSteven Rostedt	next if ($failed);
3401a75fececSSteven Rostedt    }
34025a391fbfSSteven Rostedt
34035f9b6cedSSteven Rostedt    success $i;
340475c3fda7SSteven Rostedt}
34052545eb61SSteven Rostedt
34065c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
340775c3fda7SSteven Rostedt    halt;
3408576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
340975c3fda7SSteven Rostedt    reboot;
34105c42fc5bSSteven Rostedt}
341175c3fda7SSteven Rostedt
3412e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
3413e48c5293SSteven Rostedt
34142545eb61SSteven Rostedtexit 0;
3415