xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision cad9666980c1c1a76345f36a68e96fda3d78d857)
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
139165708b2SSteven Rostedt# set when a test is something other that just building or install
140bb8474b1SSteven Rostedt# which would require more options.
141bb8474b1SSteven Rostedtmy $buildonly = 1;
142bb8474b1SSteven Rostedt
143dbd3783bSSteven Rostedt# set when creating a new config
144dbd3783bSSteven Rostedtmy $newconfig = 0;
145dbd3783bSSteven 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    ;
185dbd3783bSSteven Rostedt$config_help{"BUILD_OPTIONS"} = << "EOF"
186dbd3783bSSteven Rostedt Options to add to \"make\" when building.
187dbd3783bSSteven Rostedt i.e.  -j20
188dbd3783bSSteven RostedtEOF
189dbd3783bSSteven 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 = ";
317dbd3783bSSteven 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
340dbd3783bSSteven Rostedt    if ($newconfig) {
341dbd3783bSSteven Rostedt	get_ktest_config("BUILD_OPTIONS");
342dbd3783bSSteven Rostedt    }
343dbd3783bSSteven Rostedt
344bb8474b1SSteven Rostedt    # options required for other than just building a kernel
345bb8474b1SSteven Rostedt    if (!$buildonly) {
346165708b2SSteven Rostedt	get_ktest_config("POWER_CYCLE");
347165708b2SSteven Rostedt	get_ktest_config("CONSOLE");
348165708b2SSteven Rostedt    }
349165708b2SSteven Rostedt
350165708b2SSteven Rostedt    # options required for install and more
351165708b2SSteven Rostedt    if ($buildonly != 1) {
352bb8474b1SSteven Rostedt	get_ktest_config("SSH_USER");
3538d1491baSSteven Rostedt	get_ktest_config("BUILD_TARGET");
3548d1491baSSteven Rostedt	get_ktest_config("TARGET_IMAGE");
355bb8474b1SSteven Rostedt    }
356bb8474b1SSteven Rostedt
3578d1491baSSteven Rostedt    get_ktest_config("LOCALVERSION");
3588d1491baSSteven Rostedt
359bb8474b1SSteven Rostedt    return if ($buildonly);
360bb8474b1SSteven Rostedt
3618d1491baSSteven Rostedt    my $rtype = $opt{"REBOOT_TYPE"};
3628d1491baSSteven Rostedt
3638d1491baSSteven Rostedt    if (!defined($rtype)) {
3648d1491baSSteven Rostedt	if (!defined($opt{"GRUB_MENU"})) {
3658d1491baSSteven Rostedt	    get_ktest_config("REBOOT_TYPE");
3668d1491baSSteven Rostedt	    $rtype = $entered_configs{"REBOOT_TYPE"};
3678d1491baSSteven Rostedt	} else {
3688d1491baSSteven Rostedt	    $rtype = "grub";
3698d1491baSSteven Rostedt	}
3708d1491baSSteven Rostedt    }
3718d1491baSSteven Rostedt
3728d1491baSSteven Rostedt    if ($rtype eq "grub") {
3738d1491baSSteven Rostedt	get_ktest_config("GRUB_MENU");
3748d1491baSSteven Rostedt    } else {
3758d1491baSSteven Rostedt	get_ktest_config("REBOOT_SCRIPT");
3768d1491baSSteven Rostedt    }
3778d1491baSSteven Rostedt}
3788d1491baSSteven Rostedt
37977d942ceSSteven Rostedtsub process_variables {
3808d735212SSteven Rostedt    my ($value, $remove_undef) = @_;
38177d942ceSSteven Rostedt    my $retval = "";
38277d942ceSSteven Rostedt
38377d942ceSSteven Rostedt    # We want to check for '\', and it is just easier
38477d942ceSSteven Rostedt    # to check the previous characet of '$' and not need
38577d942ceSSteven Rostedt    # to worry if '$' is the first character. By adding
38677d942ceSSteven Rostedt    # a space to $value, we can just check [^\\]\$ and
38777d942ceSSteven Rostedt    # it will still work.
38877d942ceSSteven Rostedt    $value = " $value";
38977d942ceSSteven Rostedt
39077d942ceSSteven Rostedt    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
39177d942ceSSteven Rostedt	my $begin = $1;
39277d942ceSSteven Rostedt	my $var = $2;
39377d942ceSSteven Rostedt	my $end = $3;
39477d942ceSSteven Rostedt	# append beginning of value to retval
39577d942ceSSteven Rostedt	$retval = "$retval$begin";
39677d942ceSSteven Rostedt	if (defined($variable{$var})) {
39777d942ceSSteven Rostedt	    $retval = "$retval$variable{$var}";
3988d735212SSteven Rostedt	} elsif (defined($remove_undef) && $remove_undef) {
3998d735212SSteven Rostedt	    # for if statements, any variable that is not defined,
4008d735212SSteven Rostedt	    # we simple convert to 0
4018d735212SSteven Rostedt	    $retval = "${retval}0";
40277d942ceSSteven Rostedt	} else {
40377d942ceSSteven Rostedt	    # put back the origin piece.
40477d942ceSSteven Rostedt	    $retval = "$retval\$\{$var\}";
40577d942ceSSteven Rostedt	}
40677d942ceSSteven Rostedt	$value = $end;
40777d942ceSSteven Rostedt    }
40877d942ceSSteven Rostedt    $retval = "$retval$value";
40977d942ceSSteven Rostedt
41077d942ceSSteven Rostedt    # remove the space added in the beginning
41177d942ceSSteven Rostedt    $retval =~ s/ //;
41277d942ceSSteven Rostedt
41377d942ceSSteven Rostedt    return "$retval"
41477d942ceSSteven Rostedt}
41577d942ceSSteven Rostedt
416a57419b3SSteven Rostedtsub set_value {
4173d1cc414SSteven Rostedt    my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
4182545eb61SSteven Rostedt
419*cad96669SSteven Rostedt    my $prvalue = process_variables($rvalue);
420*cad96669SSteven Rostedt
421*cad96669SSteven Rostedt    if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") {
422bb8474b1SSteven Rostedt	# Note if a test is something other than build, then we
423bb8474b1SSteven Rostedt	# will need other manditory options.
424*cad96669SSteven Rostedt	if ($prvalue ne "install") {
425bb8474b1SSteven Rostedt	    $buildonly = 0;
426165708b2SSteven Rostedt	} else {
427165708b2SSteven Rostedt	    # install still limits some manditory options.
428165708b2SSteven Rostedt	    $buildonly = 2;
429165708b2SSteven Rostedt	}
430bb8474b1SSteven Rostedt    }
431bb8474b1SSteven Rostedt
432a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
4333d1cc414SSteven Rostedt	if (!$override || defined(${$overrides}{$lvalue})) {
4343d1cc414SSteven Rostedt	    my $extra = "";
4353d1cc414SSteven Rostedt	    if ($override) {
4363d1cc414SSteven Rostedt		$extra = "In the same override section!\n";
4373d1cc414SSteven Rostedt	    }
4383d1cc414SSteven Rostedt	    die "$name: $.: Option $lvalue defined more than once!\n$extra";
4393d1cc414SSteven Rostedt	}
440*cad96669SSteven Rostedt	${$overrides}{$lvalue} = $prvalue;
441a75fececSSteven Rostedt    }
44221a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
44321a9679fSSteven Rostedt	delete $opt{$lvalue};
44421a9679fSSteven Rostedt    } else {
445*cad96669SSteven Rostedt	$opt{$lvalue} = $prvalue;
44621a9679fSSteven Rostedt    }
4472545eb61SSteven Rostedt}
448a57419b3SSteven Rostedt
44977d942ceSSteven Rostedtsub set_variable {
45077d942ceSSteven Rostedt    my ($lvalue, $rvalue) = @_;
45177d942ceSSteven Rostedt
45277d942ceSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
45377d942ceSSteven Rostedt	delete $variable{$lvalue};
45477d942ceSSteven Rostedt    } else {
45577d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
45677d942ceSSteven Rostedt	$variable{$lvalue} = $rvalue;
45777d942ceSSteven Rostedt    }
45877d942ceSSteven Rostedt}
45977d942ceSSteven Rostedt
460ab7a3f52SSteven Rostedtsub process_compare {
461ab7a3f52SSteven Rostedt    my ($lval, $cmp, $rval) = @_;
462ab7a3f52SSteven Rostedt
463ab7a3f52SSteven Rostedt    # remove whitespace
464ab7a3f52SSteven Rostedt
465ab7a3f52SSteven Rostedt    $lval =~ s/^\s*//;
466ab7a3f52SSteven Rostedt    $lval =~ s/\s*$//;
467ab7a3f52SSteven Rostedt
468ab7a3f52SSteven Rostedt    $rval =~ s/^\s*//;
469ab7a3f52SSteven Rostedt    $rval =~ s/\s*$//;
470ab7a3f52SSteven Rostedt
471ab7a3f52SSteven Rostedt    if ($cmp eq "==") {
472ab7a3f52SSteven Rostedt	return $lval eq $rval;
473ab7a3f52SSteven Rostedt    } elsif ($cmp eq "!=") {
474ab7a3f52SSteven Rostedt	return $lval ne $rval;
475ab7a3f52SSteven Rostedt    }
476ab7a3f52SSteven Rostedt
477ab7a3f52SSteven Rostedt    my $statement = "$lval $cmp $rval";
478ab7a3f52SSteven Rostedt    my $ret = eval $statement;
479ab7a3f52SSteven Rostedt
480ab7a3f52SSteven Rostedt    # $@ stores error of eval
481ab7a3f52SSteven Rostedt    if ($@) {
482ab7a3f52SSteven Rostedt	return -1;
483ab7a3f52SSteven Rostedt    }
484ab7a3f52SSteven Rostedt
485ab7a3f52SSteven Rostedt    return $ret;
486ab7a3f52SSteven Rostedt}
487ab7a3f52SSteven Rostedt
4889900b5dcSSteven Rostedtsub value_defined {
4899900b5dcSSteven Rostedt    my ($val) = @_;
4909900b5dcSSteven Rostedt
4919900b5dcSSteven Rostedt    return defined($variable{$2}) ||
4929900b5dcSSteven Rostedt	defined($opt{$2});
4939900b5dcSSteven Rostedt}
4949900b5dcSSteven Rostedt
4958d735212SSteven Rostedtmy $d = 0;
4968d735212SSteven Rostedtsub process_expression {
4978d735212SSteven Rostedt    my ($name, $val) = @_;
49845d73a5dSSteven Rostedt
4998d735212SSteven Rostedt    my $c = $d++;
5008d735212SSteven Rostedt
5018d735212SSteven Rostedt    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
5028d735212SSteven Rostedt	my $express = $1;
5038d735212SSteven Rostedt
5048d735212SSteven Rostedt	if (process_expression($name, $express)) {
5058d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
5068d735212SSteven Rostedt	} else {
5078d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
5088d735212SSteven Rostedt	}
5098d735212SSteven Rostedt    }
5108d735212SSteven Rostedt
5118d735212SSteven Rostedt    $d--;
5128d735212SSteven Rostedt    my $OR = "\\|\\|";
5138d735212SSteven Rostedt    my $AND = "\\&\\&";
5148d735212SSteven Rostedt
5158d735212SSteven Rostedt    while ($val =~ s/^(.*?)($OR|$AND)//) {
5168d735212SSteven Rostedt	my $express = $1;
5178d735212SSteven Rostedt	my $op = $2;
5188d735212SSteven Rostedt
5198d735212SSteven Rostedt	if (process_expression($name, $express)) {
5208d735212SSteven Rostedt	    if ($op eq "||") {
5218d735212SSteven Rostedt		return 1;
5228d735212SSteven Rostedt	    }
5238d735212SSteven Rostedt	} else {
5248d735212SSteven Rostedt	    if ($op eq "&&") {
5258d735212SSteven Rostedt		return 0;
5268d735212SSteven Rostedt	    }
5278d735212SSteven Rostedt	}
5288d735212SSteven Rostedt    }
52945d73a5dSSteven Rostedt
530ab7a3f52SSteven Rostedt    if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) {
531ab7a3f52SSteven Rostedt	my $ret = process_compare($1, $2, $3);
532ab7a3f52SSteven Rostedt	if ($ret < 0) {
533ab7a3f52SSteven Rostedt	    die "$name: $.: Unable to process comparison\n";
534ab7a3f52SSteven Rostedt	}
535ab7a3f52SSteven Rostedt	return $ret;
536ab7a3f52SSteven Rostedt    }
537ab7a3f52SSteven Rostedt
5389900b5dcSSteven Rostedt    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
5399900b5dcSSteven Rostedt	if (defined $1) {
5409900b5dcSSteven Rostedt	    return !value_defined($2);
5419900b5dcSSteven Rostedt	} else {
5429900b5dcSSteven Rostedt	    return value_defined($2);
5439900b5dcSSteven Rostedt	}
5449900b5dcSSteven Rostedt    }
5459900b5dcSSteven Rostedt
54645d73a5dSSteven Rostedt    if ($val =~ /^\s*0\s*$/) {
54745d73a5dSSteven Rostedt	return 0;
54845d73a5dSSteven Rostedt    } elsif ($val =~ /^\s*\d+\s*$/) {
54945d73a5dSSteven Rostedt	return 1;
55045d73a5dSSteven Rostedt    }
55145d73a5dSSteven Rostedt
5529900b5dcSSteven Rostedt    die ("$name: $.: Undefined content $val in if statement\n");
5538d735212SSteven Rostedt}
5548d735212SSteven Rostedt
5558d735212SSteven Rostedtsub process_if {
5568d735212SSteven Rostedt    my ($name, $value) = @_;
5578d735212SSteven Rostedt
5588d735212SSteven Rostedt    # Convert variables and replace undefined ones with 0
5598d735212SSteven Rostedt    my $val = process_variables($value, 1);
5608d735212SSteven Rostedt    my $ret = process_expression $name, $val;
5618d735212SSteven Rostedt
5628d735212SSteven Rostedt    return $ret;
56345d73a5dSSteven Rostedt}
56445d73a5dSSteven Rostedt
5652ed3b161SSteven Rostedtsub __read_config {
5662ed3b161SSteven Rostedt    my ($config, $current_test_num) = @_;
567a57419b3SSteven Rostedt
5682ed3b161SSteven Rostedt    my $in;
5692ed3b161SSteven Rostedt    open($in, $config) || die "can't read file $config";
570a57419b3SSteven Rostedt
571a57419b3SSteven Rostedt    my $name = $config;
572a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
573a57419b3SSteven Rostedt
5742ed3b161SSteven Rostedt    my $test_num = $$current_test_num;
575a57419b3SSteven Rostedt    my $default = 1;
576a57419b3SSteven Rostedt    my $repeat = 1;
577a57419b3SSteven Rostedt    my $num_tests_set = 0;
578a57419b3SSteven Rostedt    my $skip = 0;
579a57419b3SSteven Rostedt    my $rest;
580a9f84424SSteven Rostedt    my $line;
5810df213caSSteven Rostedt    my $test_case = 0;
58245d73a5dSSteven Rostedt    my $if = 0;
58345d73a5dSSteven Rostedt    my $if_set = 0;
5843d1cc414SSteven Rostedt    my $override = 0;
5853d1cc414SSteven Rostedt
5863d1cc414SSteven Rostedt    my %overrides;
587a57419b3SSteven Rostedt
5882ed3b161SSteven Rostedt    while (<$in>) {
589a57419b3SSteven Rostedt
590a57419b3SSteven Rostedt	# ignore blank lines and comments
591a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
592a57419b3SSteven Rostedt
5930050b6bbSSteven Rostedt	if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
594a57419b3SSteven Rostedt
5950050b6bbSSteven Rostedt	    my $type = $1;
5960050b6bbSSteven Rostedt	    $rest = $2;
597a9f84424SSteven Rostedt	    $line = $2;
5980050b6bbSSteven Rostedt
5990050b6bbSSteven Rostedt	    my $old_test_num;
6000050b6bbSSteven Rostedt	    my $old_repeat;
6013d1cc414SSteven Rostedt	    $override = 0;
6020050b6bbSSteven Rostedt
6030050b6bbSSteven Rostedt	    if ($type eq "TEST_START") {
604a57419b3SSteven Rostedt
605a57419b3SSteven Rostedt		if ($num_tests_set) {
606a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
607a57419b3SSteven Rostedt		}
608a57419b3SSteven Rostedt
6090050b6bbSSteven Rostedt		$old_test_num = $test_num;
6100050b6bbSSteven Rostedt		$old_repeat = $repeat;
611a57419b3SSteven Rostedt
612a57419b3SSteven Rostedt		$test_num += $repeat;
613a57419b3SSteven Rostedt		$default = 0;
614a57419b3SSteven Rostedt		$repeat = 1;
6150050b6bbSSteven Rostedt	    } else {
6160050b6bbSSteven Rostedt		$default = 1;
6170050b6bbSSteven Rostedt	    }
618a57419b3SSteven Rostedt
619a9f84424SSteven Rostedt	    # If SKIP is anywhere in the line, the command will be skipped
620a9f84424SSteven Rostedt	    if ($rest =~ s/\s+SKIP\b//) {
621a57419b3SSteven Rostedt		$skip = 1;
622a57419b3SSteven Rostedt	    } else {
6230df213caSSteven Rostedt		$test_case = 1;
624a57419b3SSteven Rostedt		$skip = 0;
625a57419b3SSteven Rostedt	    }
626a57419b3SSteven Rostedt
627a9f84424SSteven Rostedt	    if ($rest =~ s/\sELSE\b//) {
628a9f84424SSteven Rostedt		if (!$if) {
629a9f84424SSteven Rostedt		    die "$name: $.: ELSE found with out matching IF section\n$_";
630a57419b3SSteven Rostedt		}
631a9f84424SSteven Rostedt		$if = 0;
632a9f84424SSteven Rostedt
633a9f84424SSteven Rostedt		if ($if_set) {
634a9f84424SSteven Rostedt		    $skip = 1;
635a9f84424SSteven Rostedt		} else {
636a9f84424SSteven Rostedt		    $skip = 0;
6373d1cc414SSteven Rostedt		}
6383d1cc414SSteven Rostedt	    }
639a57419b3SSteven Rostedt
640a9f84424SSteven Rostedt	    if ($rest =~ s/\sIF\s+(.*)//) {
64145d73a5dSSteven Rostedt		if (process_if($name, $1)) {
64245d73a5dSSteven Rostedt		    $if_set = 1;
64345d73a5dSSteven Rostedt		} else {
644a57419b3SSteven Rostedt		    $skip = 1;
645a57419b3SSteven Rostedt		}
64645d73a5dSSteven Rostedt		$if = 1;
64745d73a5dSSteven Rostedt	    } else {
64845d73a5dSSteven Rostedt		$if = 0;
649a9f84424SSteven Rostedt		$if_set = 0;
65045d73a5dSSteven Rostedt	    }
651a57419b3SSteven Rostedt
652a9f84424SSteven Rostedt	    if (!$skip) {
653a9f84424SSteven Rostedt		if ($type eq "TEST_START") {
654a9f84424SSteven Rostedt		    if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
655a9f84424SSteven Rostedt			$repeat = $1;
656a9f84424SSteven Rostedt			$repeat_tests{"$test_num"} = $repeat;
657a9f84424SSteven Rostedt		    }
658a9f84424SSteven Rostedt		} elsif ($rest =~ s/\sOVERRIDE\b//) {
659a9f84424SSteven Rostedt		    # DEFAULT only
660a9f84424SSteven Rostedt		    $override = 1;
661a9f84424SSteven Rostedt		    # Clear previous overrides
662a9f84424SSteven Rostedt		    %overrides = ();
663a9f84424SSteven Rostedt		}
664a9f84424SSteven Rostedt	    }
665a9f84424SSteven Rostedt
666a9f84424SSteven Rostedt	    if (!$skip && $rest !~ /^\s*$/) {
6670050b6bbSSteven Rostedt		die "$name: $.: Gargbage found after $type\n$_";
668a57419b3SSteven Rostedt	    }
669a57419b3SSteven Rostedt
6700050b6bbSSteven Rostedt	    if ($skip && $type eq "TEST_START") {
671a57419b3SSteven Rostedt		$test_num = $old_test_num;
672e48c5293SSteven Rostedt		$repeat = $old_repeat;
673a57419b3SSteven Rostedt	    }
674a57419b3SSteven Rostedt
675ab7a3f52SSteven Rostedt	} elsif (/^\s*ELSE\b(.*)$/) {
67645d73a5dSSteven Rostedt	    if (!$if) {
67745d73a5dSSteven Rostedt		die "$name: $.: ELSE found with out matching IF section\n$_";
67845d73a5dSSteven Rostedt	    }
67945d73a5dSSteven Rostedt	    $rest = $1;
68045d73a5dSSteven Rostedt	    if ($if_set) {
68145d73a5dSSteven Rostedt		$skip = 1;
682ab7a3f52SSteven Rostedt		$rest = "";
68345d73a5dSSteven Rostedt	    } else {
68445d73a5dSSteven Rostedt		$skip = 0;
68545d73a5dSSteven Rostedt
686ab7a3f52SSteven Rostedt		if ($rest =~ /\sIF\s+(.*)/) {
68745d73a5dSSteven Rostedt		    # May be a ELSE IF section.
68845d73a5dSSteven Rostedt		    if (!process_if($name, $1)) {
68945d73a5dSSteven Rostedt			$skip = 1;
69045d73a5dSSteven Rostedt		    }
691ab7a3f52SSteven Rostedt		    $rest = "";
69245d73a5dSSteven Rostedt		} else {
69345d73a5dSSteven Rostedt		    $if = 0;
69445d73a5dSSteven Rostedt		}
69545d73a5dSSteven Rostedt	    }
69645d73a5dSSteven Rostedt
697ab7a3f52SSteven Rostedt	    if ($rest !~ /^\s*$/) {
698ab7a3f52SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
699ab7a3f52SSteven Rostedt	    }
700ab7a3f52SSteven Rostedt
7012ed3b161SSteven Rostedt	} elsif (/^\s*INCLUDE\s+(\S+)/) {
7022ed3b161SSteven Rostedt
7032ed3b161SSteven Rostedt	    next if ($skip);
7042ed3b161SSteven Rostedt
7052ed3b161SSteven Rostedt	    if (!$default) {
7062ed3b161SSteven Rostedt		die "$name: $.: INCLUDE can only be done in default sections\n$_";
7072ed3b161SSteven Rostedt	    }
7082ed3b161SSteven Rostedt
7092ed3b161SSteven Rostedt	    my $file = process_variables($1);
7102ed3b161SSteven Rostedt
7112ed3b161SSteven Rostedt	    if ($file !~ m,^/,) {
7122ed3b161SSteven Rostedt		# check the path of the config file first
7132ed3b161SSteven Rostedt		if ($config =~ m,(.*)/,) {
7142ed3b161SSteven Rostedt		    if (-f "$1/$file") {
7152ed3b161SSteven Rostedt			$file = "$1/$file";
7162ed3b161SSteven Rostedt		    }
7172ed3b161SSteven Rostedt		}
7182ed3b161SSteven Rostedt	    }
7192ed3b161SSteven Rostedt
7202ed3b161SSteven Rostedt	    if ( ! -r $file ) {
7212ed3b161SSteven Rostedt		die "$name: $.: Can't read file $file\n$_";
7222ed3b161SSteven Rostedt	    }
7232ed3b161SSteven Rostedt
7242ed3b161SSteven Rostedt	    if (__read_config($file, \$test_num)) {
7252ed3b161SSteven Rostedt		$test_case = 1;
7262ed3b161SSteven Rostedt	    }
7272ed3b161SSteven Rostedt
728a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
729a57419b3SSteven Rostedt
730a57419b3SSteven Rostedt	    next if ($skip);
731a57419b3SSteven Rostedt
732a57419b3SSteven Rostedt	    my $lvalue = $1;
733a57419b3SSteven Rostedt	    my $rvalue = $2;
734a57419b3SSteven Rostedt
735a57419b3SSteven Rostedt	    if (!$default &&
736a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
737a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
738a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
739a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
740a57419b3SSteven Rostedt	    }
741a57419b3SSteven Rostedt
742a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
743a57419b3SSteven Rostedt		if ($test_num) {
744a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
745a57419b3SSteven Rostedt		}
746a57419b3SSteven Rostedt		if (!$default) {
747a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
748a57419b3SSteven Rostedt		}
749a57419b3SSteven Rostedt		$num_tests_set = 1;
750a57419b3SSteven Rostedt	    }
751a57419b3SSteven Rostedt
752a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
7533d1cc414SSteven Rostedt		set_value($lvalue, $rvalue, $override, \%overrides, $name);
754a57419b3SSteven Rostedt	    } else {
755a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
7563d1cc414SSteven Rostedt		set_value($val, $rvalue, $override, \%overrides, $name);
757a57419b3SSteven Rostedt
758a57419b3SSteven Rostedt		if ($repeat > 1) {
759a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
760a57419b3SSteven Rostedt		}
761a57419b3SSteven Rostedt	    }
76277d942ceSSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
76377d942ceSSteven Rostedt	    next if ($skip);
76477d942ceSSteven Rostedt
76577d942ceSSteven Rostedt	    my $lvalue = $1;
76677d942ceSSteven Rostedt	    my $rvalue = $2;
76777d942ceSSteven Rostedt
76877d942ceSSteven Rostedt	    # process config variables.
76977d942ceSSteven Rostedt	    # Config variables are only active while reading the
77077d942ceSSteven Rostedt	    # config and can be defined anywhere. They also ignore
77177d942ceSSteven Rostedt	    # TEST_START and DEFAULTS, but are skipped if they are in
77277d942ceSSteven Rostedt	    # on of these sections that have SKIP defined.
77377d942ceSSteven Rostedt	    # The save variable can be
77477d942ceSSteven Rostedt	    # defined multiple times and the new one simply overrides
77577d942ceSSteven Rostedt	    # the prevous one.
77677d942ceSSteven Rostedt	    set_variable($lvalue, $rvalue);
77777d942ceSSteven Rostedt
778a57419b3SSteven Rostedt	} else {
779a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
780a57419b3SSteven Rostedt	}
7812545eb61SSteven Rostedt    }
7822545eb61SSteven Rostedt
783a57419b3SSteven Rostedt    if ($test_num) {
784a57419b3SSteven Rostedt	$test_num += $repeat - 1;
785a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
786a57419b3SSteven Rostedt    }
787a57419b3SSteven Rostedt
7882ed3b161SSteven Rostedt    close($in);
7892ed3b161SSteven Rostedt
7902ed3b161SSteven Rostedt    $$current_test_num = $test_num;
7912ed3b161SSteven Rostedt
7922ed3b161SSteven Rostedt    return $test_case;
7932ed3b161SSteven Rostedt}
7942ed3b161SSteven Rostedt
795c4261d0fSSteven Rostedtsub get_test_case {
796c4261d0fSSteven Rostedt	print "What test case would you like to run?\n";
797c4261d0fSSteven Rostedt	print " (build, install or boot)\n";
798c4261d0fSSteven Rostedt	print " Other tests are available but require editing the config file\n";
799c4261d0fSSteven Rostedt	my $ans = <STDIN>;
800c4261d0fSSteven Rostedt	chomp $ans;
801c4261d0fSSteven Rostedt	$default{"TEST_TYPE"} = $ans;
802c4261d0fSSteven Rostedt}
803c4261d0fSSteven Rostedt
8042ed3b161SSteven Rostedtsub read_config {
8052ed3b161SSteven Rostedt    my ($config) = @_;
8062ed3b161SSteven Rostedt
8072ed3b161SSteven Rostedt    my $test_case;
8082ed3b161SSteven Rostedt    my $test_num = 0;
8092ed3b161SSteven Rostedt
8102ed3b161SSteven Rostedt    $test_case = __read_config $config, \$test_num;
8112ed3b161SSteven Rostedt
8128d1491baSSteven Rostedt    # make sure we have all mandatory configs
8138d1491baSSteven Rostedt    get_ktest_configs;
8148d1491baSSteven Rostedt
8150df213caSSteven Rostedt    # was a test specified?
8160df213caSSteven Rostedt    if (!$test_case) {
8170df213caSSteven Rostedt	print "No test case specified.\n";
818c4261d0fSSteven Rostedt	get_test_case;
8190df213caSSteven Rostedt    }
8200df213caSSteven Rostedt
821a75fececSSteven Rostedt    # set any defaults
822a75fececSSteven Rostedt
823a75fececSSteven Rostedt    foreach my $default (keys %default) {
824a75fececSSteven Rostedt	if (!defined($opt{$default})) {
825a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
826a75fececSSteven Rostedt	}
827a75fececSSteven Rostedt    }
8282545eb61SSteven Rostedt}
8292545eb61SSteven Rostedt
83023715c3cSSteven Rostedtsub __eval_option {
83123715c3cSSteven Rostedt    my ($option, $i) = @_;
83223715c3cSSteven Rostedt
83323715c3cSSteven Rostedt    # Add space to evaluate the character before $
83423715c3cSSteven Rostedt    $option = " $option";
83523715c3cSSteven Rostedt    my $retval = "";
836f9dfb65bSRabin Vincent    my $repeated = 0;
837f9dfb65bSRabin Vincent    my $parent = 0;
838f9dfb65bSRabin Vincent
839f9dfb65bSRabin Vincent    foreach my $test (keys %repeat_tests) {
840f9dfb65bSRabin Vincent	if ($i >= $test &&
841f9dfb65bSRabin Vincent	    $i < $test + $repeat_tests{$test}) {
842f9dfb65bSRabin Vincent
843f9dfb65bSRabin Vincent	    $repeated = 1;
844f9dfb65bSRabin Vincent	    $parent = $test;
845f9dfb65bSRabin Vincent	    last;
846f9dfb65bSRabin Vincent	}
847f9dfb65bSRabin Vincent    }
84823715c3cSSteven Rostedt
84923715c3cSSteven Rostedt    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
85023715c3cSSteven Rostedt	my $start = $1;
85123715c3cSSteven Rostedt	my $var = $2;
85223715c3cSSteven Rostedt	my $end = $3;
85323715c3cSSteven Rostedt
85423715c3cSSteven Rostedt	# Append beginning of line
85523715c3cSSteven Rostedt	$retval = "$retval$start";
85623715c3cSSteven Rostedt
85723715c3cSSteven Rostedt	# If the iteration option OPT[$i] exists, then use that.
85823715c3cSSteven Rostedt	# otherwise see if the default OPT (without [$i]) exists.
85923715c3cSSteven Rostedt
86023715c3cSSteven Rostedt	my $o = "$var\[$i\]";
861f9dfb65bSRabin Vincent	my $parento = "$var\[$parent\]";
86223715c3cSSteven Rostedt
86323715c3cSSteven Rostedt	if (defined($opt{$o})) {
86423715c3cSSteven Rostedt	    $o = $opt{$o};
86523715c3cSSteven Rostedt	    $retval = "$retval$o";
866f9dfb65bSRabin Vincent	} elsif ($repeated && defined($opt{$parento})) {
867f9dfb65bSRabin Vincent	    $o = $opt{$parento};
868f9dfb65bSRabin Vincent	    $retval = "$retval$o";
86923715c3cSSteven Rostedt	} elsif (defined($opt{$var})) {
87023715c3cSSteven Rostedt	    $o = $opt{$var};
87123715c3cSSteven Rostedt	    $retval = "$retval$o";
87223715c3cSSteven Rostedt	} else {
87323715c3cSSteven Rostedt	    $retval = "$retval\$\{$var\}";
87423715c3cSSteven Rostedt	}
87523715c3cSSteven Rostedt
87623715c3cSSteven Rostedt	$option = $end;
87723715c3cSSteven Rostedt    }
87823715c3cSSteven Rostedt
87923715c3cSSteven Rostedt    $retval = "$retval$option";
88023715c3cSSteven Rostedt
88123715c3cSSteven Rostedt    $retval =~ s/^ //;
88223715c3cSSteven Rostedt
88323715c3cSSteven Rostedt    return $retval;
88423715c3cSSteven Rostedt}
88523715c3cSSteven Rostedt
88623715c3cSSteven Rostedtsub eval_option {
88723715c3cSSteven Rostedt    my ($option, $i) = @_;
88823715c3cSSteven Rostedt
88923715c3cSSteven Rostedt    my $prev = "";
89023715c3cSSteven Rostedt
89123715c3cSSteven Rostedt    # Since an option can evaluate to another option,
89223715c3cSSteven Rostedt    # keep iterating until we do not evaluate any more
89323715c3cSSteven Rostedt    # options.
89423715c3cSSteven Rostedt    my $r = 0;
89523715c3cSSteven Rostedt    while ($prev ne $option) {
89623715c3cSSteven Rostedt	# Check for recursive evaluations.
89723715c3cSSteven Rostedt	# 100 deep should be more than enough.
89823715c3cSSteven Rostedt	if ($r++ > 100) {
89923715c3cSSteven Rostedt	    die "Over 100 evaluations accurred with $option\n" .
90023715c3cSSteven Rostedt		"Check for recursive variables\n";
90123715c3cSSteven Rostedt	}
90223715c3cSSteven Rostedt	$prev = $option;
90323715c3cSSteven Rostedt	$option = __eval_option($option, $i);
90423715c3cSSteven Rostedt    }
90523715c3cSSteven Rostedt
90623715c3cSSteven Rostedt    return $option;
90723715c3cSSteven Rostedt}
90823715c3cSSteven Rostedt
909d1e2f22aSSteven Rostedtsub _logit {
9102545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
9112545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
9122545eb61SSteven Rostedt	print OUT @_;
9132545eb61SSteven Rostedt	close(OUT);
9142545eb61SSteven Rostedt    }
9152545eb61SSteven Rostedt}
9162545eb61SSteven Rostedt
917d1e2f22aSSteven Rostedtsub logit {
918d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
919d1e2f22aSSteven Rostedt	_logit @_;
920d1e2f22aSSteven Rostedt    } else {
921d1e2f22aSSteven Rostedt	print @_;
922d1e2f22aSSteven Rostedt    }
923d1e2f22aSSteven Rostedt}
924d1e2f22aSSteven Rostedt
9255f9b6cedSSteven Rostedtsub doprint {
9265f9b6cedSSteven Rostedt    print @_;
927d1e2f22aSSteven Rostedt    _logit @_;
9285f9b6cedSSteven Rostedt}
9295f9b6cedSSteven Rostedt
9307faafbd6SSteven Rostedtsub run_command;
9312728be41SAndrew Jonessub start_monitor;
9322728be41SAndrew Jonessub end_monitor;
9332728be41SAndrew Jonessub wait_for_monitor;
9347faafbd6SSteven Rostedt
9357faafbd6SSteven Rostedtsub reboot {
9362728be41SAndrew Jones    my ($time) = @_;
9372728be41SAndrew Jones
9382b803365SSteven Rostedt    if (defined($time)) {
9392b803365SSteven Rostedt	start_monitor;
9402b803365SSteven Rostedt	# flush out current monitor
9412b803365SSteven Rostedt	# May contain the reboot success line
9422b803365SSteven Rostedt	wait_for_monitor 1;
9432b803365SSteven Rostedt    }
9442b803365SSteven Rostedt
9457faafbd6SSteven Rostedt    # try to reboot normally
946e48c5293SSteven Rostedt    if (run_command $reboot) {
947576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
948576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
949576f627cSSteven Rostedt	    run_command "$power_cycle";
950576f627cSSteven Rostedt	}
951576f627cSSteven Rostedt    } else {
9527faafbd6SSteven Rostedt	# nope? power cycle it.
953a75fececSSteven Rostedt	run_command "$power_cycle";
9547faafbd6SSteven Rostedt    }
9552728be41SAndrew Jones
9562728be41SAndrew Jones    if (defined($time)) {
9572b803365SSteven Rostedt	wait_for_monitor($time, $reboot_success_line);
9582728be41SAndrew Jones	end_monitor;
9592728be41SAndrew Jones    }
9607faafbd6SSteven Rostedt}
9617faafbd6SSteven Rostedt
962576f627cSSteven Rostedtsub do_not_reboot {
963576f627cSSteven Rostedt    my $i = $iteration;
964576f627cSSteven Rostedt
9654ab1cce5SSteven Rostedt    return $test_type eq "build" || $no_reboot ||
966576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
967576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
968576f627cSSteven Rostedt}
969576f627cSSteven Rostedt
9705c42fc5bSSteven Rostedtsub dodie {
9715a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
9725c42fc5bSSteven Rostedt
973576f627cSSteven Rostedt    my $i = $iteration;
974576f627cSSteven Rostedt
975576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
976576f627cSSteven Rostedt
97775c3fda7SSteven Rostedt	doprint "REBOOTING\n";
9787faafbd6SSteven Rostedt	reboot;
97975c3fda7SSteven Rostedt
980a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
9815c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
982a75fececSSteven Rostedt	`$power_off`;
9835c42fc5bSSteven Rostedt    }
98475c3fda7SSteven Rostedt
985f80802cbSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
986f80802cbSSteven Rostedt	print " See $opt{LOG_FILE} for more info.\n";
987f80802cbSSteven Rostedt    }
988f80802cbSSteven Rostedt
989576f627cSSteven Rostedt    die @_, "\n";
9905c42fc5bSSteven Rostedt}
9915c42fc5bSSteven Rostedt
9927faafbd6SSteven Rostedtsub open_console {
9937faafbd6SSteven Rostedt    my ($fp) = @_;
9947faafbd6SSteven Rostedt
9957faafbd6SSteven Rostedt    my $flags;
9967faafbd6SSteven Rostedt
997a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
998a75fececSSteven Rostedt	dodie "Can't open console $console";
9997faafbd6SSteven Rostedt
10007faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
1001576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
10027faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
1003576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
10047faafbd6SSteven Rostedt
10057faafbd6SSteven Rostedt    return $pid;
10067faafbd6SSteven Rostedt}
10077faafbd6SSteven Rostedt
10087faafbd6SSteven Rostedtsub close_console {
10097faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
10107faafbd6SSteven Rostedt
10117faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
10127faafbd6SSteven Rostedt    kill 2, $pid;
10137faafbd6SSteven Rostedt
10147faafbd6SSteven Rostedt    print "closing!\n";
10157faafbd6SSteven Rostedt    close($fp);
10167faafbd6SSteven Rostedt}
10177faafbd6SSteven Rostedt
10187faafbd6SSteven Rostedtsub start_monitor {
10197faafbd6SSteven Rostedt    if ($monitor_cnt++) {
10207faafbd6SSteven Rostedt	return;
10217faafbd6SSteven Rostedt    }
10227faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
10237faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
1024a75fececSSteven Rostedt
1025a75fececSSteven Rostedt    return;
1026a75fececSSteven Rostedt
1027a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
10287faafbd6SSteven Rostedt}
10297faafbd6SSteven Rostedt
10307faafbd6SSteven Rostedtsub end_monitor {
10317faafbd6SSteven Rostedt    if (--$monitor_cnt) {
10327faafbd6SSteven Rostedt	return;
10337faafbd6SSteven Rostedt    }
10347faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
10357faafbd6SSteven Rostedt}
10367faafbd6SSteven Rostedt
10377faafbd6SSteven Rostedtsub wait_for_monitor {
10382b803365SSteven Rostedt    my ($time, $stop) = @_;
10392b803365SSteven Rostedt    my $full_line = "";
10407faafbd6SSteven Rostedt    my $line;
10412b803365SSteven Rostedt    my $booted = 0;
10427faafbd6SSteven Rostedt
1043a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
10447faafbd6SSteven Rostedt
10457faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
10462b803365SSteven Rostedt    while (!$booted) {
10477faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
10482b803365SSteven Rostedt	last if (!defined($line));
10492b803365SSteven Rostedt	print "$line";
10502b803365SSteven Rostedt	$full_line .= $line;
10512b803365SSteven Rostedt
10522b803365SSteven Rostedt	if (defined($stop) && $full_line =~ /$stop/) {
10532b803365SSteven Rostedt	    doprint "wait for monitor detected $stop\n";
10542b803365SSteven Rostedt	    $booted = 1;
10552b803365SSteven Rostedt	}
10562b803365SSteven Rostedt
10572b803365SSteven Rostedt	if ($line =~ /\n/) {
10582b803365SSteven Rostedt	    $full_line = "";
10592b803365SSteven Rostedt	}
10602b803365SSteven Rostedt    }
1061a75fececSSteven Rostedt    print "** Monitor flushed **\n";
10627faafbd6SSteven Rostedt}
10637faafbd6SSteven Rostedt
1064de5b6e3bSRabin Vincentsub save_logs {
1065de5b6e3bSRabin Vincent	my ($result, $basedir) = @_;
1066de5b6e3bSRabin Vincent	my @t = localtime;
1067de5b6e3bSRabin Vincent	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1068de5b6e3bSRabin Vincent		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1069de5b6e3bSRabin Vincent
1070de5b6e3bSRabin Vincent	my $type = $build_type;
1071de5b6e3bSRabin Vincent	if ($type =~ /useconfig/) {
1072de5b6e3bSRabin Vincent	    $type = "useconfig";
1073de5b6e3bSRabin Vincent	}
1074de5b6e3bSRabin Vincent
1075de5b6e3bSRabin Vincent	my $dir = "$machine-$test_type-$type-$result-$date";
1076de5b6e3bSRabin Vincent
1077de5b6e3bSRabin Vincent	$dir = "$basedir/$dir";
1078de5b6e3bSRabin Vincent
1079de5b6e3bSRabin Vincent	if (!-d $dir) {
1080de5b6e3bSRabin Vincent	    mkpath($dir) or
1081de5b6e3bSRabin Vincent		die "can't create $dir";
1082de5b6e3bSRabin Vincent	}
1083de5b6e3bSRabin Vincent
1084de5b6e3bSRabin Vincent	my %files = (
1085de5b6e3bSRabin Vincent		"config" => $output_config,
1086de5b6e3bSRabin Vincent		"buildlog" => $buildlog,
1087de5b6e3bSRabin Vincent		"dmesg" => $dmesg,
1088de5b6e3bSRabin Vincent		"testlog" => $testlog,
1089de5b6e3bSRabin Vincent	);
1090de5b6e3bSRabin Vincent
1091de5b6e3bSRabin Vincent	while (my ($name, $source) = each(%files)) {
1092de5b6e3bSRabin Vincent		if (-f "$source") {
1093de5b6e3bSRabin Vincent			cp "$source", "$dir/$name" or
1094de5b6e3bSRabin Vincent				die "failed to copy $source";
1095de5b6e3bSRabin Vincent		}
1096de5b6e3bSRabin Vincent	}
1097de5b6e3bSRabin Vincent
1098de5b6e3bSRabin Vincent	doprint "*** Saved info to $dir ***\n";
1099de5b6e3bSRabin Vincent}
1100de5b6e3bSRabin Vincent
11012b7d9b21SSteven Rostedtsub fail {
11022b7d9b21SSteven Rostedt
1103a75fececSSteven Rostedt	if ($die_on_failure) {
11042b7d9b21SSteven Rostedt		dodie @_;
11052b7d9b21SSteven Rostedt	}
11062b7d9b21SSteven Rostedt
1107a75fececSSteven Rostedt	doprint "FAILED\n";
11087faafbd6SSteven Rostedt
1109576f627cSSteven Rostedt	my $i = $iteration;
1110576f627cSSteven Rostedt
1111a75fececSSteven Rostedt	# no need to reboot for just building.
1112576f627cSSteven Rostedt	if (!do_not_reboot) {
11137faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
11142728be41SAndrew Jones	    reboot $sleep_time;
1115a75fececSSteven Rostedt	}
11167faafbd6SSteven Rostedt
11179064af52SSteven Rostedt	my $name = "";
11189064af52SSteven Rostedt
11199064af52SSteven Rostedt	if (defined($test_name)) {
11209064af52SSteven Rostedt	    $name = " ($test_name)";
11219064af52SSteven Rostedt	}
11229064af52SSteven Rostedt
1123576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1124576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
11259064af52SSteven Rostedt	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1126576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1127576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1128a75fececSSteven Rostedt
1129de5b6e3bSRabin Vincent	if (defined($store_failures)) {
1130de5b6e3bSRabin Vincent	    save_logs "fail", $store_failures;
1131cccae1a6SSteven Rostedt        }
1132cccae1a6SSteven Rostedt
11332b7d9b21SSteven Rostedt	return 1;
11342b7d9b21SSteven Rostedt}
11352b7d9b21SSteven Rostedt
11362545eb61SSteven Rostedtsub run_command {
11372545eb61SSteven Rostedt    my ($command) = @_;
1138d6ce2a0bSSteven Rostedt    my $dolog = 0;
1139d6ce2a0bSSteven Rostedt    my $dord = 0;
1140d6ce2a0bSSteven Rostedt    my $pid;
1141d6ce2a0bSSteven Rostedt
1142e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
1143e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
1144e48c5293SSteven Rostedt
1145d6ce2a0bSSteven Rostedt    doprint("$command ... ");
1146d6ce2a0bSSteven Rostedt
1147d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
11482b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
11492545eb61SSteven Rostedt
11502545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1151d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
1152d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
1153d6ce2a0bSSteven Rostedt	$dolog = 1;
11546c5ee0beSSteven Rostedt    }
11556c5ee0beSSteven Rostedt
11566c5ee0beSSteven Rostedt    if (defined($redirect)) {
1157d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
1158d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
1159d6ce2a0bSSteven Rostedt	$dord = 1;
11602545eb61SSteven Rostedt    }
11612545eb61SSteven Rostedt
1162d6ce2a0bSSteven Rostedt    while (<CMD>) {
1163d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
1164d6ce2a0bSSteven Rostedt	print RD  if ($dord);
1165d6ce2a0bSSteven Rostedt    }
11662545eb61SSteven Rostedt
1167d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
11682545eb61SSteven Rostedt    my $failed = $?;
11692545eb61SSteven Rostedt
1170d6ce2a0bSSteven Rostedt    close(CMD);
1171d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
1172d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
1173d6ce2a0bSSteven Rostedt
11742545eb61SSteven Rostedt    if ($failed) {
11752545eb61SSteven Rostedt	doprint "FAILED!\n";
11762545eb61SSteven Rostedt    } else {
11772545eb61SSteven Rostedt	doprint "SUCCESS\n";
11782545eb61SSteven Rostedt    }
11792545eb61SSteven Rostedt
11805f9b6cedSSteven Rostedt    return !$failed;
11815f9b6cedSSteven Rostedt}
11825f9b6cedSSteven Rostedt
1183e48c5293SSteven Rostedtsub run_ssh {
1184e48c5293SSteven Rostedt    my ($cmd) = @_;
1185e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
1186e48c5293SSteven Rostedt
1187e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1188e48c5293SSteven Rostedt    return run_command "$cp_exec";
1189e48c5293SSteven Rostedt}
1190e48c5293SSteven Rostedt
1191e48c5293SSteven Rostedtsub run_scp {
1192e48c5293SSteven Rostedt    my ($src, $dst) = @_;
1193e48c5293SSteven Rostedt    my $cp_scp = $scp_to_target;
1194e48c5293SSteven Rostedt
1195e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
1196e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
1197e48c5293SSteven Rostedt
1198e48c5293SSteven Rostedt    return run_command "$cp_scp";
1199e48c5293SSteven Rostedt}
1200e48c5293SSteven Rostedt
12015f9b6cedSSteven Rostedtsub get_grub_index {
12025f9b6cedSSteven Rostedt
1203a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
1204a75fececSSteven Rostedt	return;
1205a75fececSSteven Rostedt    }
12065a391fbfSSteven Rostedt    return if (defined($grub_number));
12075f9b6cedSSteven Rostedt
12085f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
12095f9b6cedSSteven Rostedt    $grub_number = -1;
1210e48c5293SSteven Rostedt
1211e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
1212e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
1213e48c5293SSteven Rostedt
1214e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
12155f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
1216e48c5293SSteven Rostedt
1217eaa1fe25SSteven Rostedt    my $found = 0;
1218eaa1fe25SSteven Rostedt
12195f9b6cedSSteven Rostedt    while (<IN>) {
1220a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
12215f9b6cedSSteven Rostedt	    $grub_number++;
1222eaa1fe25SSteven Rostedt	    $found = 1;
12235f9b6cedSSteven Rostedt	    last;
12245f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
12255f9b6cedSSteven Rostedt	    $grub_number++;
12265f9b6cedSSteven Rostedt	}
12275f9b6cedSSteven Rostedt    }
12285f9b6cedSSteven Rostedt    close(IN);
12295f9b6cedSSteven Rostedt
1230a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
1231eaa1fe25SSteven Rostedt	if (!$found);
12325f9b6cedSSteven Rostedt    doprint "$grub_number\n";
12332545eb61SSteven Rostedt}
12342545eb61SSteven Rostedt
12352545eb61SSteven Rostedtsub wait_for_input
12362545eb61SSteven Rostedt{
12372545eb61SSteven Rostedt    my ($fp, $time) = @_;
12382545eb61SSteven Rostedt    my $rin;
12392545eb61SSteven Rostedt    my $ready;
12402545eb61SSteven Rostedt    my $line;
12412545eb61SSteven Rostedt    my $ch;
12422545eb61SSteven Rostedt
12432545eb61SSteven Rostedt    if (!defined($time)) {
12442545eb61SSteven Rostedt	$time = $timeout;
12452545eb61SSteven Rostedt    }
12462545eb61SSteven Rostedt
12472545eb61SSteven Rostedt    $rin = '';
12482545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
12492545eb61SSteven Rostedt    $ready = select($rin, undef, undef, $time);
12502545eb61SSteven Rostedt
12512545eb61SSteven Rostedt    $line = "";
12522545eb61SSteven Rostedt
12532545eb61SSteven Rostedt    # try to read one char at a time
12542545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
12552545eb61SSteven Rostedt	$line .= $ch;
12562545eb61SSteven Rostedt	last if ($ch eq "\n");
12572545eb61SSteven Rostedt    }
12582545eb61SSteven Rostedt
12592545eb61SSteven Rostedt    if (!length($line)) {
12602545eb61SSteven Rostedt	return undef;
12612545eb61SSteven Rostedt    }
12622545eb61SSteven Rostedt
12632545eb61SSteven Rostedt    return $line;
12642545eb61SSteven Rostedt}
12652545eb61SSteven Rostedt
126675c3fda7SSteven Rostedtsub reboot_to {
1267a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
1268c54367f9SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
1269c54367f9SSteven Rostedt	reboot;
1270a75fececSSteven Rostedt	return;
1271a75fececSSteven Rostedt    }
1272a75fececSSteven Rostedt
1273a75fececSSteven Rostedt    run_command "$reboot_script";
12742545eb61SSteven Rostedt}
12752545eb61SSteven Rostedt
1276a57419b3SSteven Rostedtsub get_sha1 {
1277a57419b3SSteven Rostedt    my ($commit) = @_;
1278a57419b3SSteven Rostedt
1279a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
1280a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
1281a57419b3SSteven Rostedt    my $ret = $?;
1282a57419b3SSteven Rostedt
1283a57419b3SSteven Rostedt    logit $sha1;
1284a57419b3SSteven Rostedt
1285a57419b3SSteven Rostedt    if ($ret) {
1286a57419b3SSteven Rostedt	doprint "FAILED\n";
1287a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
1288a57419b3SSteven Rostedt    }
1289a57419b3SSteven Rostedt
1290a57419b3SSteven Rostedt    print "SUCCESS\n";
1291a57419b3SSteven Rostedt
1292a57419b3SSteven Rostedt    chomp $sha1;
1293a57419b3SSteven Rostedt
1294a57419b3SSteven Rostedt    return $sha1;
1295a57419b3SSteven Rostedt}
1296a57419b3SSteven Rostedt
12975a391fbfSSteven Rostedtsub monitor {
12982545eb61SSteven Rostedt    my $booted = 0;
12992545eb61SSteven Rostedt    my $bug = 0;
13005c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
13012b7d9b21SSteven Rostedt    my $loops;
13022545eb61SSteven Rostedt
13037faafbd6SSteven Rostedt    wait_for_monitor 5;
13042545eb61SSteven Rostedt
13052545eb61SSteven Rostedt    my $line;
13062545eb61SSteven Rostedt    my $full_line = "";
13072545eb61SSteven Rostedt
13087faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
13097faafbd6SSteven Rostedt	die "unable to write to $dmesg";
13102545eb61SSteven Rostedt
131175c3fda7SSteven Rostedt    reboot_to;
13122545eb61SSteven Rostedt
13131c8a617aSSteven Rostedt    my $success_start;
13141c8a617aSSteven Rostedt    my $failure_start;
13152d01b26aSSteven Rostedt    my $monitor_start = time;
13162d01b26aSSteven Rostedt    my $done = 0;
1317f1a5b962SSteven Rostedt    my $version_found = 0;
13181c8a617aSSteven Rostedt
13192d01b26aSSteven Rostedt    while (!$done) {
13202545eb61SSteven Rostedt
1321ecaf8e52SSteven Rostedt	if ($bug && defined($stop_after_failure) &&
1322ecaf8e52SSteven Rostedt	    $stop_after_failure >= 0) {
1323ecaf8e52SSteven Rostedt	    my $time = $stop_after_failure - (time - $failure_start);
1324ecaf8e52SSteven Rostedt	    $line = wait_for_input($monitor_fp, $time);
1325ecaf8e52SSteven Rostedt	    if (!defined($line)) {
1326ecaf8e52SSteven Rostedt		doprint "bug timed out after $booted_timeout seconds\n";
1327ecaf8e52SSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1328ecaf8e52SSteven Rostedt		last;
1329ecaf8e52SSteven Rostedt	    }
1330ecaf8e52SSteven Rostedt	} elsif ($booted) {
1331a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
1332cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1333cd4f1d53SSteven Rostedt		my $s = $booted_timeout == 1 ? "" : "s";
1334cd4f1d53SSteven Rostedt		doprint "Successful boot found: break after $booted_timeout second$s\n";
1335cd4f1d53SSteven Rostedt		last;
1336cd4f1d53SSteven Rostedt	    }
13372b7d9b21SSteven Rostedt	} else {
13387faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
1339cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1340cd4f1d53SSteven Rostedt		my $s = $timeout == 1 ? "" : "s";
1341cd4f1d53SSteven Rostedt		doprint "Timed out after $timeout second$s\n";
1342cd4f1d53SSteven Rostedt		last;
13432b7d9b21SSteven Rostedt	    }
1344cd4f1d53SSteven Rostedt	}
13452545eb61SSteven Rostedt
13462545eb61SSteven Rostedt	doprint $line;
13477faafbd6SSteven Rostedt	print DMESG $line;
13482545eb61SSteven Rostedt
13492545eb61SSteven Rostedt	# we are not guaranteed to get a full line
13502545eb61SSteven Rostedt	$full_line .= $line;
13512545eb61SSteven Rostedt
1352a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
13532545eb61SSteven Rostedt	    $booted = 1;
13541c8a617aSSteven Rostedt	    $success_start = time;
13551c8a617aSSteven Rostedt	}
13561c8a617aSSteven Rostedt
13571c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
13581c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
13591c8a617aSSteven Rostedt	    my $now = time;
13601c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
13611c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
13621c8a617aSSteven Rostedt		last;
13631c8a617aSSteven Rostedt	    }
13642545eb61SSteven Rostedt	}
13652545eb61SSteven Rostedt
13665c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
13675c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
13685c42fc5bSSteven Rostedt	}
13695c42fc5bSSteven Rostedt
13702545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
13714651920eSSteven Rostedt	    if (!$bug && !$skip_call_trace) {
13721c8a617aSSteven Rostedt		$bug = 1;
13731c8a617aSSteven Rostedt		$failure_start = time;
13741c8a617aSSteven Rostedt	    }
13751c8a617aSSteven Rostedt	}
13761c8a617aSSteven Rostedt
13771c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
13781c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
13791c8a617aSSteven Rostedt	    my $now = time;
13801c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
13811c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
13821c8a617aSSteven Rostedt		last;
13831c8a617aSSteven Rostedt	    }
13845c42fc5bSSteven Rostedt	}
13855c42fc5bSSteven Rostedt
13865c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
13875c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
13885c42fc5bSSteven Rostedt	}
13895c42fc5bSSteven Rostedt
13905c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
139110abf118SSteven Rostedt	    $failure_start = time;
13922545eb61SSteven Rostedt	    $bug = 1;
13932545eb61SSteven Rostedt	}
13942545eb61SSteven Rostedt
1395f1a5b962SSteven Rostedt	# Detect triple faults by testing the banner
1396f1a5b962SSteven Rostedt	if ($full_line =~ /\bLinux version (\S+).*\n/) {
1397f1a5b962SSteven Rostedt	    if ($1 eq $version) {
1398f1a5b962SSteven Rostedt		$version_found = 1;
1399f1a5b962SSteven Rostedt	    } elsif ($version_found && $detect_triplefault) {
1400f1a5b962SSteven Rostedt		# We already booted into the kernel we are testing,
1401f1a5b962SSteven Rostedt		# but now we booted into another kernel?
1402f1a5b962SSteven Rostedt		# Consider this a triple fault.
1403f1a5b962SSteven Rostedt		doprint "Aleady booted in Linux kernel $version, but now\n";
1404f1a5b962SSteven Rostedt		doprint "we booted into Linux kernel $1.\n";
1405f1a5b962SSteven Rostedt		doprint "Assuming that this is a triple fault.\n";
1406f1a5b962SSteven Rostedt		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1407f1a5b962SSteven Rostedt		last;
1408f1a5b962SSteven Rostedt	    }
1409f1a5b962SSteven Rostedt	}
1410f1a5b962SSteven Rostedt
14112545eb61SSteven Rostedt	if ($line =~ /\n/) {
14122545eb61SSteven Rostedt	    $full_line = "";
14132545eb61SSteven Rostedt	}
14142d01b26aSSteven Rostedt
14152d01b26aSSteven Rostedt	if ($stop_test_after > 0 && !$booted && !$bug) {
14162d01b26aSSteven Rostedt	    if (time - $monitor_start > $stop_test_after) {
14174d62bf51SSteven Rostedt		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
14182d01b26aSSteven Rostedt		$done = 1;
14192d01b26aSSteven Rostedt	    }
14202d01b26aSSteven Rostedt	}
14212545eb61SSteven Rostedt    }
14222545eb61SSteven Rostedt
14237faafbd6SSteven Rostedt    close(DMESG);
14242545eb61SSteven Rostedt
14252545eb61SSteven Rostedt    if ($bug) {
14262b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
1427576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
14282545eb61SSteven Rostedt    }
14295f9b6cedSSteven Rostedt
1430a75fececSSteven Rostedt    if (!$booted) {
1431a75fececSSteven Rostedt	return 0 if ($in_bisect);
1432576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
1433a75fececSSteven Rostedt    }
1434a75fececSSteven Rostedt
14352b7d9b21SSteven Rostedt    return 1;
14362545eb61SSteven Rostedt}
14372545eb61SSteven Rostedt
14382b29b2f8SSteven Rostedtsub eval_kernel_version {
14392b29b2f8SSteven Rostedt    my ($option) = @_;
14402b29b2f8SSteven Rostedt
14412b29b2f8SSteven Rostedt    $option =~ s/\$KERNEL_VERSION/$version/g;
14422b29b2f8SSteven Rostedt
14432b29b2f8SSteven Rostedt    return $option;
14442b29b2f8SSteven Rostedt}
14452b29b2f8SSteven Rostedt
1446db05cfefSSteven Rostedtsub do_post_install {
1447db05cfefSSteven Rostedt
1448db05cfefSSteven Rostedt    return if (!defined($post_install));
1449db05cfefSSteven Rostedt
14502b29b2f8SSteven Rostedt    my $cp_post_install = eval_kernel_version $post_install;
1451db05cfefSSteven Rostedt    run_command "$cp_post_install" or
1452db05cfefSSteven Rostedt	dodie "Failed to run post install";
1453db05cfefSSteven Rostedt}
1454db05cfefSSteven Rostedt
14552545eb61SSteven Rostedtsub install {
14562545eb61SSteven Rostedt
1457e0a8742eSSteven Rostedt    return if ($no_install);
1458e0a8742eSSteven Rostedt
14592b29b2f8SSteven Rostedt    my $cp_target = eval_kernel_version $target_image;
14602b29b2f8SSteven Rostedt
14612b29b2f8SSteven Rostedt    run_scp "$outputdir/$build_target", "$cp_target" or
14625c42fc5bSSteven Rostedt	dodie "failed to copy image";
14635f9b6cedSSteven Rostedt
14645f9b6cedSSteven Rostedt    my $install_mods = 0;
14655f9b6cedSSteven Rostedt
14665f9b6cedSSteven Rostedt    # should we process modules?
14675f9b6cedSSteven Rostedt    $install_mods = 0;
146851ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
14695f9b6cedSSteven Rostedt    while (<IN>) {
14705f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
14715f9b6cedSSteven Rostedt	    $install_mods = 1 if (defined($1));
14725f9b6cedSSteven Rostedt	    last;
14735f9b6cedSSteven Rostedt	}
14745f9b6cedSSteven Rostedt    }
14755f9b6cedSSteven Rostedt    close(IN);
14765f9b6cedSSteven Rostedt
14775f9b6cedSSteven Rostedt    if (!$install_mods) {
1478db05cfefSSteven Rostedt	do_post_install;
14795f9b6cedSSteven Rostedt	doprint "No modules needed\n";
14805f9b6cedSSteven Rostedt	return;
14812545eb61SSteven Rostedt    }
14822545eb61SSteven Rostedt
1483a75fececSSteven Rostedt    run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
14845f9b6cedSSteven Rostedt	dodie "Failed to install modules";
14855f9b6cedSSteven Rostedt
14862545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
1487a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
14882545eb61SSteven Rostedt
1489e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
14905c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
14912545eb61SSteven Rostedt
14925c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
1493a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
14945c42fc5bSSteven Rostedt	dodie "making tarball";
14955c42fc5bSSteven Rostedt
1496e48c5293SSteven Rostedt    run_scp "$tmpdir/$modtar", "/tmp" or
14975c42fc5bSSteven Rostedt	dodie "failed to copy modules";
14985c42fc5bSSteven Rostedt
1499a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
15005c42fc5bSSteven Rostedt
1501e7b13441SSteven Rostedt    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
15025c42fc5bSSteven Rostedt	dodie "failed to tar modules";
15035c42fc5bSSteven Rostedt
1504e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
15058b37ca8cSSteven Rostedt
1506db05cfefSSteven Rostedt    do_post_install;
15072545eb61SSteven Rostedt}
15082545eb61SSteven Rostedt
1509ddf607e5SSteven Rostedtsub get_version {
1510ddf607e5SSteven Rostedt    # get the release name
1511ddf607e5SSteven Rostedt    doprint "$make kernelrelease ... ";
1512ddf607e5SSteven Rostedt    $version = `$make kernelrelease | tail -1`;
1513ddf607e5SSteven Rostedt    chomp($version);
1514ddf607e5SSteven Rostedt    doprint "$version\n";
1515ddf607e5SSteven Rostedt}
1516ddf607e5SSteven Rostedt
1517ddf607e5SSteven Rostedtsub start_monitor_and_boot {
15189f7424ccSSteven Rostedt    # Make sure the stable kernel has finished booting
15199f7424ccSSteven Rostedt    start_monitor;
15209f7424ccSSteven Rostedt    wait_for_monitor 5;
15219f7424ccSSteven Rostedt    end_monitor;
15229f7424ccSSteven Rostedt
1523ddf607e5SSteven Rostedt    get_grub_index;
1524ddf607e5SSteven Rostedt    get_version;
1525ddf607e5SSteven Rostedt    install;
1526ddf607e5SSteven Rostedt
1527ddf607e5SSteven Rostedt    start_monitor;
1528ddf607e5SSteven Rostedt    return monitor;
1529ddf607e5SSteven Rostedt}
1530ddf607e5SSteven Rostedt
15316c5ee0beSSteven Rostedtsub check_buildlog {
15326c5ee0beSSteven Rostedt    my ($patch) = @_;
15336c5ee0beSSteven Rostedt
15346c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
15356c5ee0beSSteven Rostedt
15366c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
15376c5ee0beSSteven Rostedt	dodie "failed to show $patch";
15386c5ee0beSSteven Rostedt    while (<IN>) {
15396c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
15406c5ee0beSSteven Rostedt	    chomp $1;
15416c5ee0beSSteven Rostedt	    $files[$#files] = $1;
15426c5ee0beSSteven Rostedt	}
15436c5ee0beSSteven Rostedt    }
15446c5ee0beSSteven Rostedt    close(IN);
15456c5ee0beSSteven Rostedt
15466c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
15476c5ee0beSSteven Rostedt    while (<IN>) {
15486c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
15496c5ee0beSSteven Rostedt	    my $err = $1;
15506c5ee0beSSteven Rostedt	    foreach my $file (@files) {
1551a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
15526c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
15532b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
15546c5ee0beSSteven Rostedt		}
15556c5ee0beSSteven Rostedt	    }
15566c5ee0beSSteven Rostedt	}
15576c5ee0beSSteven Rostedt    }
15586c5ee0beSSteven Rostedt    close(IN);
15592b7d9b21SSteven Rostedt
15602b7d9b21SSteven Rostedt    return 1;
15616c5ee0beSSteven Rostedt}
15626c5ee0beSSteven Rostedt
1563fcb3f16aSSteven Rostedtsub apply_min_config {
1564fcb3f16aSSteven Rostedt    my $outconfig = "$output_config.new";
1565612b9e9bSSteven Rostedt
1566fcb3f16aSSteven Rostedt    # Read the config file and remove anything that
1567fcb3f16aSSteven Rostedt    # is in the force_config hash (from minconfig and others)
1568fcb3f16aSSteven Rostedt    # then add the force config back.
1569fcb3f16aSSteven Rostedt
1570fcb3f16aSSteven Rostedt    doprint "Applying minimum configurations into $output_config.new\n";
1571fcb3f16aSSteven Rostedt
1572fcb3f16aSSteven Rostedt    open (OUT, ">$outconfig") or
1573fcb3f16aSSteven Rostedt	dodie "Can't create $outconfig";
1574fcb3f16aSSteven Rostedt
1575fcb3f16aSSteven Rostedt    if (-f $output_config) {
1576fcb3f16aSSteven Rostedt	open (IN, $output_config) or
1577fcb3f16aSSteven Rostedt	    dodie "Failed to open $output_config";
1578fcb3f16aSSteven Rostedt	while (<IN>) {
1579fcb3f16aSSteven Rostedt	    if (/^(# )?(CONFIG_[^\s=]*)/) {
1580fcb3f16aSSteven Rostedt		next if (defined($force_config{$2}));
1581fcb3f16aSSteven Rostedt	    }
1582fcb3f16aSSteven Rostedt	    print OUT;
1583fcb3f16aSSteven Rostedt	}
1584fcb3f16aSSteven Rostedt	close IN;
1585fcb3f16aSSteven Rostedt    }
1586fcb3f16aSSteven Rostedt    foreach my $config (keys %force_config) {
1587fcb3f16aSSteven Rostedt	print OUT "$force_config{$config}\n";
1588fcb3f16aSSteven Rostedt    }
1589fcb3f16aSSteven Rostedt    close OUT;
1590fcb3f16aSSteven Rostedt
1591fcb3f16aSSteven Rostedt    run_command "mv $outconfig $output_config";
1592fcb3f16aSSteven Rostedt}
1593fcb3f16aSSteven Rostedt
1594fcb3f16aSSteven Rostedtsub make_oldconfig {
1595fcb3f16aSSteven Rostedt
15964c4ab120SSteven Rostedt    my @force_list = keys %force_config;
15974c4ab120SSteven Rostedt
15984c4ab120SSteven Rostedt    if ($#force_list >= 0) {
1599fcb3f16aSSteven Rostedt	apply_min_config;
16004c4ab120SSteven Rostedt    }
1601fcb3f16aSSteven Rostedt
1602fcb3f16aSSteven Rostedt    if (!run_command "$make oldnoconfig") {
1603612b9e9bSSteven Rostedt	# Perhaps oldnoconfig doesn't exist in this version of the kernel
1604612b9e9bSSteven Rostedt	# try a yes '' | oldconfig
1605612b9e9bSSteven Rostedt	doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1606fcb3f16aSSteven Rostedt	run_command "yes '' | $make oldconfig" or
1607612b9e9bSSteven Rostedt	    dodie "failed make config oldconfig";
1608612b9e9bSSteven Rostedt    }
1609612b9e9bSSteven Rostedt}
1610612b9e9bSSteven Rostedt
1611fcb3f16aSSteven Rostedt# read a config file and use this to force new configs.
1612fcb3f16aSSteven Rostedtsub load_force_config {
1613fcb3f16aSSteven Rostedt    my ($config) = @_;
1614fcb3f16aSSteven Rostedt
1615fcb3f16aSSteven Rostedt    open(IN, $config) or
1616fcb3f16aSSteven Rostedt	dodie "failed to read $config";
1617fcb3f16aSSteven Rostedt    while (<IN>) {
1618fcb3f16aSSteven Rostedt	chomp;
1619fcb3f16aSSteven Rostedt	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1620fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1621fcb3f16aSSteven Rostedt	} elsif (/^# (CONFIG_\S*) is not set/) {
1622fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1623fcb3f16aSSteven Rostedt	}
1624fcb3f16aSSteven Rostedt    }
1625fcb3f16aSSteven Rostedt    close IN;
1626fcb3f16aSSteven Rostedt}
1627fcb3f16aSSteven Rostedt
16282545eb61SSteven Rostedtsub build {
16292545eb61SSteven Rostedt    my ($type) = @_;
16302545eb61SSteven Rostedt
16317faafbd6SSteven Rostedt    unlink $buildlog;
16327faafbd6SSteven Rostedt
16334ab1cce5SSteven Rostedt    # Failed builds should not reboot the target
16344ab1cce5SSteven Rostedt    my $save_no_reboot = $no_reboot;
16354ab1cce5SSteven Rostedt    $no_reboot = 1;
16364ab1cce5SSteven Rostedt
16370bd6c1a3SSteven Rostedt    if (defined($pre_build)) {
16380bd6c1a3SSteven Rostedt	my $ret = run_command $pre_build;
16390bd6c1a3SSteven Rostedt	if (!$ret && defined($pre_build_die) &&
16400bd6c1a3SSteven Rostedt	    $pre_build_die) {
16410bd6c1a3SSteven Rostedt	    dodie "failed to pre_build\n";
16420bd6c1a3SSteven Rostedt	}
16430bd6c1a3SSteven Rostedt    }
16440bd6c1a3SSteven Rostedt
164575c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
164651ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
164775c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
16485f9b6cedSSteven Rostedt
164975c3fda7SSteven Rostedt	$type = "oldconfig";
165075c3fda7SSteven Rostedt    }
165175c3fda7SSteven Rostedt
16525c42fc5bSSteven Rostedt    # old config can ask questions
16535c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
16549386c6abSSteven Rostedt	$type = "oldnoconfig";
165575c3fda7SSteven Rostedt
165675c3fda7SSteven Rostedt	# allow for empty configs
165751ad1dd1SSteven Rostedt	run_command "touch $output_config";
165875c3fda7SSteven Rostedt
165913488231SAndrew Jones	if (!$noclean) {
166051ad1dd1SSteven Rostedt	    run_command "mv $output_config $outputdir/config_temp" or
16615c42fc5bSSteven Rostedt		dodie "moving .config";
16625c42fc5bSSteven Rostedt
166313488231SAndrew Jones	    run_command "$make mrproper" or dodie "make mrproper";
16645c42fc5bSSteven Rostedt
166551ad1dd1SSteven Rostedt	    run_command "mv $outputdir/config_temp $output_config" or
16665c42fc5bSSteven Rostedt		dodie "moving config_temp";
166713488231SAndrew Jones	}
16685c42fc5bSSteven Rostedt
16695c42fc5bSSteven Rostedt    } elsif (!$noclean) {
167051ad1dd1SSteven Rostedt	unlink "$output_config";
16715f9b6cedSSteven Rostedt	run_command "$make mrproper" or
16725c42fc5bSSteven Rostedt	    dodie "make mrproper";
16735c42fc5bSSteven Rostedt    }
16742545eb61SSteven Rostedt
16752545eb61SSteven Rostedt    # add something to distinguish this build
1676a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
1677a75fececSSteven Rostedt    print OUT "$localversion\n";
16782545eb61SSteven Rostedt    close(OUT);
16792545eb61SSteven Rostedt
16805f9b6cedSSteven Rostedt    if (defined($minconfig)) {
1681fcb3f16aSSteven Rostedt	load_force_config($minconfig);
16822545eb61SSteven Rostedt    }
16832545eb61SSteven Rostedt
1684fcb3f16aSSteven Rostedt    if ($type ne "oldnoconfig") {
1685fcb3f16aSSteven Rostedt	run_command "$make $type" or
16865c42fc5bSSteven Rostedt	    dodie "failed make config";
1687612b9e9bSSteven Rostedt    }
1688fcb3f16aSSteven Rostedt    # Run old config regardless, to enforce min configurations
1689fcb3f16aSSteven Rostedt    make_oldconfig;
16902545eb61SSteven Rostedt
1691a75fececSSteven Rostedt    $redirect = "$buildlog";
16920bd6c1a3SSteven Rostedt    my $build_ret = run_command "$make $build_options";
16936c5ee0beSSteven Rostedt    undef $redirect;
16940bd6c1a3SSteven Rostedt
16950bd6c1a3SSteven Rostedt    if (defined($post_build)) {
16960bd6c1a3SSteven Rostedt	my $ret = run_command $post_build;
16970bd6c1a3SSteven Rostedt	if (!$ret && defined($post_build_die) &&
16980bd6c1a3SSteven Rostedt	    $post_build_die) {
16990bd6c1a3SSteven Rostedt	    dodie "failed to post_build\n";
17000bd6c1a3SSteven Rostedt	}
17010bd6c1a3SSteven Rostedt    }
17020bd6c1a3SSteven Rostedt
17030bd6c1a3SSteven Rostedt    if (!$build_ret) {
17045f9b6cedSSteven Rostedt	# bisect may need this to pass
17054ab1cce5SSteven Rostedt	if ($in_bisect) {
17064ab1cce5SSteven Rostedt	    $no_reboot = $save_no_reboot;
17074ab1cce5SSteven Rostedt	    return 0;
17084ab1cce5SSteven Rostedt	}
17092b7d9b21SSteven Rostedt	fail "failed build" and return 0;
17102545eb61SSteven Rostedt    }
17115f9b6cedSSteven Rostedt
17124ab1cce5SSteven Rostedt    $no_reboot = $save_no_reboot;
17134ab1cce5SSteven Rostedt
17142b7d9b21SSteven Rostedt    return 1;
17152545eb61SSteven Rostedt}
17162545eb61SSteven Rostedt
171775c3fda7SSteven Rostedtsub halt {
1718e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
1719576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
1720576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
1721576f627cSSteven Rostedt	    run_command "$power_off";
1722576f627cSSteven Rostedt	}
1723576f627cSSteven Rostedt    } else {
172475c3fda7SSteven Rostedt	# nope? the zap it!
1725a75fececSSteven Rostedt	run_command "$power_off";
172675c3fda7SSteven Rostedt    }
172775c3fda7SSteven Rostedt}
172875c3fda7SSteven Rostedt
17295f9b6cedSSteven Rostedtsub success {
17305f9b6cedSSteven Rostedt    my ($i) = @_;
17315f9b6cedSSteven Rostedt
1732e48c5293SSteven Rostedt    $successes++;
1733e48c5293SSteven Rostedt
17349064af52SSteven Rostedt    my $name = "";
17359064af52SSteven Rostedt
17369064af52SSteven Rostedt    if (defined($test_name)) {
17379064af52SSteven Rostedt	$name = " ($test_name)";
17389064af52SSteven Rostedt    }
17399064af52SSteven Rostedt
17405f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
17415f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
17429064af52SSteven Rostedt    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
17435f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
17445f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
17455f9b6cedSSteven Rostedt
1746de5b6e3bSRabin Vincent    if (defined($store_successes)) {
1747de5b6e3bSRabin Vincent        save_logs "success", $store_successes;
1748de5b6e3bSRabin Vincent    }
1749de5b6e3bSRabin Vincent
1750576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1751a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
17522728be41SAndrew Jones	reboot $sleep_time;
17535f9b6cedSSteven Rostedt    }
17545f9b6cedSSteven Rostedt}
17555f9b6cedSSteven Rostedt
1756c960bb9fSSteven Rostedtsub answer_bisect {
1757c960bb9fSSteven Rostedt    for (;;) {
1758c960bb9fSSteven Rostedt	doprint "Pass or fail? [p/f]";
1759c960bb9fSSteven Rostedt	my $ans = <STDIN>;
1760c960bb9fSSteven Rostedt	chomp $ans;
1761c960bb9fSSteven Rostedt	if ($ans eq "p" || $ans eq "P") {
1762c960bb9fSSteven Rostedt	    return 1;
1763c960bb9fSSteven Rostedt	} elsif ($ans eq "f" || $ans eq "F") {
1764c960bb9fSSteven Rostedt	    return 0;
1765c960bb9fSSteven Rostedt	} else {
1766c960bb9fSSteven Rostedt	    print "Please answer 'P' or 'F'\n";
1767c960bb9fSSteven Rostedt	}
1768c960bb9fSSteven Rostedt    }
1769c960bb9fSSteven Rostedt}
1770c960bb9fSSteven Rostedt
17715a391fbfSSteven Rostedtsub child_run_test {
17727faafbd6SSteven Rostedt    my $failed = 0;
17735a391fbfSSteven Rostedt
17747faafbd6SSteven Rostedt    # child should have no power
1775a75fececSSteven Rostedt    $reboot_on_error = 0;
1776a75fececSSteven Rostedt    $poweroff_on_error = 0;
1777a75fececSSteven Rostedt    $die_on_failure = 1;
17787faafbd6SSteven Rostedt
1779a9dd5d63SRabin Vincent    $redirect = "$testlog";
17807faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
1781a9dd5d63SRabin Vincent    undef $redirect;
1782a9dd5d63SRabin Vincent
17835a391fbfSSteven Rostedt    exit $failed;
17845a391fbfSSteven Rostedt}
17855a391fbfSSteven Rostedt
17865a391fbfSSteven Rostedtmy $child_done;
17875a391fbfSSteven Rostedt
17885a391fbfSSteven Rostedtsub child_finished {
17895a391fbfSSteven Rostedt    $child_done = 1;
17905a391fbfSSteven Rostedt}
17915a391fbfSSteven Rostedt
17925a391fbfSSteven Rostedtsub do_run_test {
17935a391fbfSSteven Rostedt    my $child_pid;
17945a391fbfSSteven Rostedt    my $child_exit;
17955a391fbfSSteven Rostedt    my $line;
17965a391fbfSSteven Rostedt    my $full_line;
17975a391fbfSSteven Rostedt    my $bug = 0;
17985a391fbfSSteven Rostedt
17997faafbd6SSteven Rostedt    wait_for_monitor 1;
18005a391fbfSSteven Rostedt
18017faafbd6SSteven Rostedt    doprint "run test $run_test\n";
18025a391fbfSSteven Rostedt
18035a391fbfSSteven Rostedt    $child_done = 0;
18045a391fbfSSteven Rostedt
18055a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
18065a391fbfSSteven Rostedt
18075a391fbfSSteven Rostedt    $child_pid = fork;
18085a391fbfSSteven Rostedt
18095a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
18105a391fbfSSteven Rostedt
18115a391fbfSSteven Rostedt    $full_line = "";
18125a391fbfSSteven Rostedt
18135a391fbfSSteven Rostedt    do {
18147faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
18155a391fbfSSteven Rostedt	if (defined($line)) {
18165a391fbfSSteven Rostedt
18175a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
18185a391fbfSSteven Rostedt	    $full_line .= $line;
18198ea0e063SSteven Rostedt	    doprint $line;
18205a391fbfSSteven Rostedt
18215a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
18225a391fbfSSteven Rostedt		$bug = 1;
18235a391fbfSSteven Rostedt	    }
18245a391fbfSSteven Rostedt
18255a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
18265a391fbfSSteven Rostedt		$bug = 1;
18275a391fbfSSteven Rostedt	    }
18285a391fbfSSteven Rostedt
18295a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
18305a391fbfSSteven Rostedt		$full_line = "";
18315a391fbfSSteven Rostedt	    }
18325a391fbfSSteven Rostedt	}
18335a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
18345a391fbfSSteven Rostedt
18355a391fbfSSteven Rostedt    if ($bug) {
18368ea0e063SSteven Rostedt	my $failure_start = time;
18378ea0e063SSteven Rostedt	my $now;
18388ea0e063SSteven Rostedt	do {
18398ea0e063SSteven Rostedt	    $line = wait_for_input($monitor_fp, 1);
18408ea0e063SSteven Rostedt	    if (defined($line)) {
18418ea0e063SSteven Rostedt		doprint $line;
18428ea0e063SSteven Rostedt	    }
18438ea0e063SSteven Rostedt	    $now = time;
18448ea0e063SSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
18458ea0e063SSteven Rostedt		last;
18468ea0e063SSteven Rostedt	    }
18478ea0e063SSteven Rostedt	} while (defined($line));
18488ea0e063SSteven Rostedt
18495a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
18505a391fbfSSteven Rostedt	# kill the child with extreme prejudice
18515a391fbfSSteven Rostedt	kill 9, $child_pid;
18525a391fbfSSteven Rostedt    }
18535a391fbfSSteven Rostedt
18545a391fbfSSteven Rostedt    waitpid $child_pid, 0;
18555a391fbfSSteven Rostedt    $child_exit = $?;
18565a391fbfSSteven Rostedt
18575a391fbfSSteven Rostedt    if ($bug || $child_exit) {
18582b7d9b21SSteven Rostedt	return 0 if $in_bisect;
18592b7d9b21SSteven Rostedt	fail "test failed" and return 0;
18605a391fbfSSteven Rostedt    }
18612b7d9b21SSteven Rostedt    return 1;
18625a391fbfSSteven Rostedt}
18635a391fbfSSteven Rostedt
1864a75fececSSteven Rostedtsub run_git_bisect {
1865a75fececSSteven Rostedt    my ($command) = @_;
1866a75fececSSteven Rostedt
1867a75fececSSteven Rostedt    doprint "$command ... ";
1868a75fececSSteven Rostedt
1869a75fececSSteven Rostedt    my $output = `$command 2>&1`;
1870a75fececSSteven Rostedt    my $ret = $?;
1871a75fececSSteven Rostedt
1872a75fececSSteven Rostedt    logit $output;
1873a75fececSSteven Rostedt
1874a75fececSSteven Rostedt    if ($ret) {
1875a75fececSSteven Rostedt	doprint "FAILED\n";
1876a75fececSSteven Rostedt	dodie "Failed to git bisect";
1877a75fececSSteven Rostedt    }
1878a75fececSSteven Rostedt
1879a75fececSSteven Rostedt    doprint "SUCCESS\n";
1880a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1881a75fececSSteven Rostedt	doprint "$1 [$2]\n";
1882a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1883a75fececSSteven Rostedt	$bisect_bad = $1;
1884a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
1885a75fececSSteven Rostedt	return 0;
1886a75fececSSteven Rostedt    } else {
1887a75fececSSteven Rostedt	# we already logged it, just print it now.
1888a75fececSSteven Rostedt	print $output;
1889a75fececSSteven Rostedt    }
1890a75fececSSteven Rostedt
1891a75fececSSteven Rostedt    return 1;
1892a75fececSSteven Rostedt}
1893a75fececSSteven Rostedt
1894c23dca7cSSteven Rostedtsub bisect_reboot {
1895c23dca7cSSteven Rostedt    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
18962728be41SAndrew Jones    reboot $bisect_sleep_time;
1897c23dca7cSSteven Rostedt}
1898c23dca7cSSteven Rostedt
1899c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip
19000a05c769SSteven Rostedtsub run_bisect_test {
19010a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
19025f9b6cedSSteven Rostedt
19032b7d9b21SSteven Rostedt    my $failed = 0;
19045f9b6cedSSteven Rostedt    my $result;
19055f9b6cedSSteven Rostedt    my $output;
19065f9b6cedSSteven Rostedt    my $ret;
19075f9b6cedSSteven Rostedt
19080a05c769SSteven Rostedt    $in_bisect = 1;
19090a05c769SSteven Rostedt
19100a05c769SSteven Rostedt    build $buildtype or $failed = 1;
19115f9b6cedSSteven Rostedt
19125f9b6cedSSteven Rostedt    if ($type ne "build") {
1913c23dca7cSSteven Rostedt	if ($failed && $bisect_skip) {
1914c23dca7cSSteven Rostedt	    $in_bisect = 0;
1915c23dca7cSSteven Rostedt	    return -1;
1916c23dca7cSSteven Rostedt	}
19177faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
19185f9b6cedSSteven Rostedt
19195f9b6cedSSteven Rostedt	# Now boot the box
1920ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
19215f9b6cedSSteven Rostedt
19225f9b6cedSSteven Rostedt	if ($type ne "boot") {
1923c23dca7cSSteven Rostedt	    if ($failed && $bisect_skip) {
1924c23dca7cSSteven Rostedt		end_monitor;
1925c23dca7cSSteven Rostedt		bisect_reboot;
1926c23dca7cSSteven Rostedt		$in_bisect = 0;
1927c23dca7cSSteven Rostedt		return -1;
1928c23dca7cSSteven Rostedt	    }
19297faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
19305a391fbfSSteven Rostedt
19312b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
19325f9b6cedSSteven Rostedt	}
19337faafbd6SSteven Rostedt	end_monitor;
19345f9b6cedSSteven Rostedt    }
19355f9b6cedSSteven Rostedt
19365f9b6cedSSteven Rostedt    if ($failed) {
19370a05c769SSteven Rostedt	$result = 0;
19385f9b6cedSSteven Rostedt    } else {
19390a05c769SSteven Rostedt	$result = 1;
19405f9b6cedSSteven Rostedt    }
19414025bc62SSteven Rostedt
19424025bc62SSteven Rostedt    # reboot the box to a kernel we can ssh to
19434025bc62SSteven Rostedt    if ($type ne "build") {
19444025bc62SSteven Rostedt	bisect_reboot;
19454025bc62SSteven Rostedt    }
19460a05c769SSteven Rostedt    $in_bisect = 0;
19470a05c769SSteven Rostedt
19480a05c769SSteven Rostedt    return $result;
19490a05c769SSteven Rostedt}
19500a05c769SSteven Rostedt
19510a05c769SSteven Rostedtsub run_bisect {
19520a05c769SSteven Rostedt    my ($type) = @_;
19530a05c769SSteven Rostedt    my $buildtype = "oldconfig";
19540a05c769SSteven Rostedt
19550a05c769SSteven Rostedt    # We should have a minconfig to use?
19560a05c769SSteven Rostedt    if (defined($minconfig)) {
19570a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
19580a05c769SSteven Rostedt    }
19590a05c769SSteven Rostedt
19600a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
19610a05c769SSteven Rostedt
1962c960bb9fSSteven Rostedt    if ($bisect_manual) {
1963c960bb9fSSteven Rostedt	$ret = answer_bisect;
1964c960bb9fSSteven Rostedt    }
19655f9b6cedSSteven Rostedt
1966d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
1967d6ce2a0bSSteven Rostedt    if ($reverse_bisect) {
19680a05c769SSteven Rostedt	$ret = !$ret;
1969d6ce2a0bSSteven Rostedt    }
1970d6ce2a0bSSteven Rostedt
1971c23dca7cSSteven Rostedt    if ($ret > 0) {
19720a05c769SSteven Rostedt	return "good";
1973c23dca7cSSteven Rostedt    } elsif ($ret == 0) {
19740a05c769SSteven Rostedt	return  "bad";
1975c23dca7cSSteven Rostedt    } elsif ($bisect_skip) {
1976c23dca7cSSteven Rostedt	doprint "HIT A BAD COMMIT ... SKIPPING\n";
1977c23dca7cSSteven Rostedt	return "skip";
19780a05c769SSteven Rostedt    }
19795f9b6cedSSteven Rostedt}
19805f9b6cedSSteven Rostedt
1981dad98754SSteven Rostedtsub update_bisect_replay {
1982dad98754SSteven Rostedt    my $tmp_log = "$tmpdir/ktest_bisect_log";
1983dad98754SSteven Rostedt    run_command "git bisect log > $tmp_log" or
1984dad98754SSteven Rostedt	die "can't create bisect log";
1985dad98754SSteven Rostedt    return $tmp_log;
1986dad98754SSteven Rostedt}
1987dad98754SSteven Rostedt
19885f9b6cedSSteven Rostedtsub bisect {
19895f9b6cedSSteven Rostedt    my ($i) = @_;
19905f9b6cedSSteven Rostedt
19915f9b6cedSSteven Rostedt    my $result;
19925f9b6cedSSteven Rostedt
19935f9b6cedSSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($opt{"BISECT_GOOD[$i]"}));
19945f9b6cedSSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($opt{"BISECT_BAD[$i]"}));
19955f9b6cedSSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($opt{"BISECT_TYPE[$i]"}));
19965f9b6cedSSteven Rostedt
19975f9b6cedSSteven Rostedt    my $good = $opt{"BISECT_GOOD[$i]"};
19985f9b6cedSSteven Rostedt    my $bad = $opt{"BISECT_BAD[$i]"};
19995f9b6cedSSteven Rostedt    my $type = $opt{"BISECT_TYPE[$i]"};
2000a75fececSSteven Rostedt    my $start = $opt{"BISECT_START[$i]"};
2001a75fececSSteven Rostedt    my $replay = $opt{"BISECT_REPLAY[$i]"};
20023410f6fdSSteven Rostedt    my $start_files = $opt{"BISECT_FILES[$i]"};
20033410f6fdSSteven Rostedt
20043410f6fdSSteven Rostedt    if (defined($start_files)) {
20053410f6fdSSteven Rostedt	$start_files = " -- " . $start_files;
20063410f6fdSSteven Rostedt    } else {
20073410f6fdSSteven Rostedt	$start_files = "";
20083410f6fdSSteven Rostedt    }
20095f9b6cedSSteven Rostedt
2010a57419b3SSteven Rostedt    # convert to true sha1's
2011a57419b3SSteven Rostedt    $good = get_sha1($good);
2012a57419b3SSteven Rostedt    $bad = get_sha1($bad);
2013a57419b3SSteven Rostedt
2014d6ce2a0bSSteven Rostedt    if (defined($opt{"BISECT_REVERSE[$i]"}) &&
2015d6ce2a0bSSteven Rostedt	$opt{"BISECT_REVERSE[$i]"} == 1) {
2016d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
2017d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
2018d6ce2a0bSSteven Rostedt    } else {
2019d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
2020d6ce2a0bSSteven Rostedt    }
2021d6ce2a0bSSteven Rostedt
20225a391fbfSSteven Rostedt    # Can't have a test without having a test to run
20235a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
20245a391fbfSSteven Rostedt	$type = "boot";
20255a391fbfSSteven Rostedt    }
20265a391fbfSSteven Rostedt
2027dad98754SSteven Rostedt    # Check if a bisect was running
2028dad98754SSteven Rostedt    my $bisect_start_file = "$builddir/.git/BISECT_START";
2029dad98754SSteven Rostedt
2030a75fececSSteven Rostedt    my $check = $opt{"BISECT_CHECK[$i]"};
2031dad98754SSteven Rostedt    my $do_check = defined($check) && $check ne "0";
2032dad98754SSteven Rostedt
2033dad98754SSteven Rostedt    if ( -f $bisect_start_file ) {
2034dad98754SSteven Rostedt	print "Bisect in progress found\n";
2035dad98754SSteven Rostedt	if ($do_check) {
2036dad98754SSteven Rostedt	    print " If you say yes, then no checks of good or bad will be done\n";
2037dad98754SSteven Rostedt	}
2038dad98754SSteven Rostedt	if (defined($replay)) {
2039dad98754SSteven Rostedt	    print "** BISECT_REPLAY is defined in config file **";
2040dad98754SSteven Rostedt	    print " Ignore config option and perform new git bisect log?\n";
2041dad98754SSteven Rostedt	    if (read_ync " (yes, no, or cancel) ") {
2042dad98754SSteven Rostedt		$replay = update_bisect_replay;
2043dad98754SSteven Rostedt		$do_check = 0;
2044dad98754SSteven Rostedt	    }
2045dad98754SSteven Rostedt	} elsif (read_yn "read git log and continue?") {
2046dad98754SSteven Rostedt	    $replay = update_bisect_replay;
2047dad98754SSteven Rostedt	    $do_check = 0;
2048dad98754SSteven Rostedt	}
2049dad98754SSteven Rostedt    }
2050dad98754SSteven Rostedt
2051dad98754SSteven Rostedt    if ($do_check) {
2052a75fececSSteven Rostedt
2053a75fececSSteven Rostedt	# get current HEAD
2054a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
2055a75fececSSteven Rostedt
2056a75fececSSteven Rostedt	if ($check ne "good") {
2057a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
2058a75fececSSteven Rostedt	    run_command "git checkout $bad" or
2059a75fececSSteven Rostedt		die "Failed to checkout $bad";
2060a75fececSSteven Rostedt
2061a75fececSSteven Rostedt	    $result = run_bisect $type;
2062a75fececSSteven Rostedt
2063a75fececSSteven Rostedt	    if ($result ne "bad") {
2064a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
2065a75fececSSteven Rostedt	    }
2066a75fececSSteven Rostedt	}
2067a75fececSSteven Rostedt
2068a75fececSSteven Rostedt	if ($check ne "bad") {
2069a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
2070a75fececSSteven Rostedt	    run_command "git checkout $good" or
2071a75fececSSteven Rostedt		die "Failed to checkout $good";
2072a75fececSSteven Rostedt
2073a75fececSSteven Rostedt	    $result = run_bisect $type;
2074a75fececSSteven Rostedt
2075a75fececSSteven Rostedt	    if ($result ne "good") {
2076a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
2077a75fececSSteven Rostedt	    }
2078a75fececSSteven Rostedt	}
2079a75fececSSteven Rostedt
2080a75fececSSteven Rostedt	# checkout where we started
2081a75fececSSteven Rostedt	run_command "git checkout $head" or
2082a75fececSSteven Rostedt	    die "Failed to checkout $head";
2083a75fececSSteven Rostedt    }
2084a75fececSSteven Rostedt
20853410f6fdSSteven Rostedt    run_command "git bisect start$start_files" or
2086a75fececSSteven Rostedt	dodie "could not start bisect";
2087a75fececSSteven Rostedt
2088a75fececSSteven Rostedt    run_command "git bisect good $good" or
2089a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
2090a75fececSSteven Rostedt
2091a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
2092a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
2093a75fececSSteven Rostedt
2094a75fececSSteven Rostedt    if (defined($replay)) {
2095a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
2096a75fececSSteven Rostedt	    dodie "failed to run replay";
2097a75fececSSteven Rostedt    }
2098a75fececSSteven Rostedt
2099a75fececSSteven Rostedt    if (defined($start)) {
2100a75fececSSteven Rostedt	run_command "git checkout $start" or
2101a75fececSSteven Rostedt	    dodie "failed to checkout $start";
2102a75fececSSteven Rostedt    }
2103a75fececSSteven Rostedt
2104a75fececSSteven Rostedt    my $test;
21055f9b6cedSSteven Rostedt    do {
21065f9b6cedSSteven Rostedt	$result = run_bisect $type;
2107a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
2108a75fececSSteven Rostedt    } while ($test);
21095f9b6cedSSteven Rostedt
21105f9b6cedSSteven Rostedt    run_command "git bisect log" or
21115f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
21125f9b6cedSSteven Rostedt
21135f9b6cedSSteven Rostedt    run_command "git bisect reset" or
21145f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
21155f9b6cedSSteven Rostedt
21165f9b6cedSSteven Rostedt    doprint "Bad commit was [$bisect_bad]\n";
21175f9b6cedSSteven Rostedt
21180a05c769SSteven Rostedt    success $i;
21190a05c769SSteven Rostedt}
21200a05c769SSteven Rostedt
21210a05c769SSteven Rostedtmy %config_ignore;
21220a05c769SSteven Rostedtmy %config_set;
21230a05c769SSteven Rostedt
21240a05c769SSteven Rostedtmy %config_list;
21250a05c769SSteven Rostedtmy %null_config;
21260a05c769SSteven Rostedt
21270a05c769SSteven Rostedtmy %dependency;
21280a05c769SSteven Rostedt
21294c4ab120SSteven Rostedtsub assign_configs {
21304c4ab120SSteven Rostedt    my ($hash, $config) = @_;
21310a05c769SSteven Rostedt
21320a05c769SSteven Rostedt    open (IN, $config)
21330a05c769SSteven Rostedt	or dodie "Failed to read $config";
21340a05c769SSteven Rostedt
21350a05c769SSteven Rostedt    while (<IN>) {
21369bf71749SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
21374c4ab120SSteven Rostedt	    ${$hash}{$2} = $1;
21380a05c769SSteven Rostedt	}
21390a05c769SSteven Rostedt    }
21400a05c769SSteven Rostedt
21410a05c769SSteven Rostedt    close(IN);
21420a05c769SSteven Rostedt}
21430a05c769SSteven Rostedt
21444c4ab120SSteven Rostedtsub process_config_ignore {
21454c4ab120SSteven Rostedt    my ($config) = @_;
21464c4ab120SSteven Rostedt
21474c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
21484c4ab120SSteven Rostedt}
21494c4ab120SSteven Rostedt
21500a05c769SSteven Rostedtsub read_current_config {
21510a05c769SSteven Rostedt    my ($config_ref) = @_;
21520a05c769SSteven Rostedt
21530a05c769SSteven Rostedt    %{$config_ref} = ();
21540a05c769SSteven Rostedt    undef %{$config_ref};
21550a05c769SSteven Rostedt
21560a05c769SSteven Rostedt    my @key = keys %{$config_ref};
21570a05c769SSteven Rostedt    if ($#key >= 0) {
21580a05c769SSteven Rostedt	print "did not delete!\n";
21590a05c769SSteven Rostedt	exit;
21600a05c769SSteven Rostedt    }
21610a05c769SSteven Rostedt    open (IN, "$output_config");
21620a05c769SSteven Rostedt
21630a05c769SSteven Rostedt    while (<IN>) {
21640a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
21650a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
21660a05c769SSteven Rostedt	}
21670a05c769SSteven Rostedt    }
21680a05c769SSteven Rostedt    close(IN);
21690a05c769SSteven Rostedt}
21700a05c769SSteven Rostedt
21710a05c769SSteven Rostedtsub get_dependencies {
21720a05c769SSteven Rostedt    my ($config) = @_;
21730a05c769SSteven Rostedt
21740a05c769SSteven Rostedt    my $arr = $dependency{$config};
21750a05c769SSteven Rostedt    if (!defined($arr)) {
21760a05c769SSteven Rostedt	return ();
21770a05c769SSteven Rostedt    }
21780a05c769SSteven Rostedt
21790a05c769SSteven Rostedt    my @deps = @{$arr};
21800a05c769SSteven Rostedt
21810a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
21820a05c769SSteven Rostedt	print "ADD DEP $dep\n";
21830a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
21840a05c769SSteven Rostedt    }
21850a05c769SSteven Rostedt
21860a05c769SSteven Rostedt    return @deps;
21870a05c769SSteven Rostedt}
21880a05c769SSteven Rostedt
21890a05c769SSteven Rostedtsub create_config {
21900a05c769SSteven Rostedt    my @configs = @_;
21910a05c769SSteven Rostedt
21920a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
21930a05c769SSteven Rostedt
21940a05c769SSteven Rostedt    foreach my $config (@configs) {
21950a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
21960a05c769SSteven Rostedt	my @deps = get_dependencies $config;
21970a05c769SSteven Rostedt	foreach my $dep (@deps) {
21980a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
21990a05c769SSteven Rostedt	}
22000a05c769SSteven Rostedt    }
22010a05c769SSteven Rostedt
22020a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
22030a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
22040a05c769SSteven Rostedt    }
22050a05c769SSteven Rostedt    close(OUT);
22060a05c769SSteven Rostedt
22070a05c769SSteven Rostedt#    exit;
2208fcb3f16aSSteven Rostedt    make_oldconfig;
22090a05c769SSteven Rostedt}
22100a05c769SSteven Rostedt
22110a05c769SSteven Rostedtsub compare_configs {
22120a05c769SSteven Rostedt    my (%a, %b) = @_;
22130a05c769SSteven Rostedt
22140a05c769SSteven Rostedt    foreach my $item (keys %a) {
22150a05c769SSteven Rostedt	if (!defined($b{$item})) {
22160a05c769SSteven Rostedt	    print "diff $item\n";
22170a05c769SSteven Rostedt	    return 1;
22180a05c769SSteven Rostedt	}
22190a05c769SSteven Rostedt	delete $b{$item};
22200a05c769SSteven Rostedt    }
22210a05c769SSteven Rostedt
22220a05c769SSteven Rostedt    my @keys = keys %b;
22230a05c769SSteven Rostedt    if ($#keys) {
22240a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
22250a05c769SSteven Rostedt    }
22260a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
22270a05c769SSteven Rostedt
22280a05c769SSteven Rostedt    return 0;
22290a05c769SSteven Rostedt}
22300a05c769SSteven Rostedt
22310a05c769SSteven Rostedtsub run_config_bisect_test {
22320a05c769SSteven Rostedt    my ($type) = @_;
22330a05c769SSteven Rostedt
22340a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
22350a05c769SSteven Rostedt}
22360a05c769SSteven Rostedt
22370a05c769SSteven Rostedtsub process_passed {
22380a05c769SSteven Rostedt    my (%configs) = @_;
22390a05c769SSteven Rostedt
22400a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
22410a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
22420a05c769SSteven Rostedt    # Add them to the min options.
22430a05c769SSteven Rostedt    foreach my $config (keys %configs) {
22440a05c769SSteven Rostedt	if (defined($config_list{$config})) {
22450a05c769SSteven Rostedt	    doprint " removing $config\n";
22460a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
22470a05c769SSteven Rostedt	    delete $config_list{$config};
22480a05c769SSteven Rostedt	}
22490a05c769SSteven Rostedt    }
2250f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
2251f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
22520a05c769SSteven Rostedt}
22530a05c769SSteven Rostedt
22540a05c769SSteven Rostedtsub process_failed {
22550a05c769SSteven Rostedt    my ($config) = @_;
22560a05c769SSteven Rostedt
22570a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
22580a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
22590a05c769SSteven Rostedt    doprint "***************************************\n\n";
22600a05c769SSteven Rostedt}
22610a05c769SSteven Rostedt
22620a05c769SSteven Rostedtsub run_config_bisect {
22630a05c769SSteven Rostedt
22640a05c769SSteven Rostedt    my @start_list = keys %config_list;
22650a05c769SSteven Rostedt
22660a05c769SSteven Rostedt    if ($#start_list < 0) {
22670a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
22680a05c769SSteven Rostedt	return -1;
22690a05c769SSteven Rostedt    }
22700a05c769SSteven Rostedt
22710a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
22720a05c769SSteven Rostedt    my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
22730a05c769SSteven Rostedt    my $ret;
22740a05c769SSteven Rostedt    my %current_config;
22750a05c769SSteven Rostedt
22760a05c769SSteven Rostedt    my $count = $#start_list + 1;
22770a05c769SSteven Rostedt    doprint "  $count configs to test\n";
22780a05c769SSteven Rostedt
22790a05c769SSteven Rostedt    my $half = int($#start_list / 2);
22800a05c769SSteven Rostedt
22810a05c769SSteven Rostedt    do {
22820a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
22830a05c769SSteven Rostedt
22840a05c769SSteven Rostedt	create_config @tophalf;
22850a05c769SSteven Rostedt	read_current_config \%current_config;
22860a05c769SSteven Rostedt
22870a05c769SSteven Rostedt	$count = $#tophalf + 1;
22880a05c769SSteven Rostedt	doprint "Testing $count configs\n";
22890a05c769SSteven Rostedt	my $found = 0;
22900a05c769SSteven Rostedt	# make sure we test something
22910a05c769SSteven Rostedt	foreach my $config (@tophalf) {
22920a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
22930a05c769SSteven Rostedt		logit " $config\n";
22940a05c769SSteven Rostedt		$found = 1;
22950a05c769SSteven Rostedt	    }
22960a05c769SSteven Rostedt	}
22970a05c769SSteven Rostedt	if (!$found) {
22980a05c769SSteven Rostedt	    # try the other half
22990a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
23004c8cc55bSSteven Rostedt	    @tophalf = @start_list[$half + 1 .. $#start_list];
23010a05c769SSteven Rostedt	    create_config @tophalf;
23020a05c769SSteven Rostedt	    read_current_config \%current_config;
23030a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
23040a05c769SSteven Rostedt		if (defined($current_config{$config})) {
23050a05c769SSteven Rostedt		    logit " $config\n";
23060a05c769SSteven Rostedt		    $found = 1;
23070a05c769SSteven Rostedt		}
23080a05c769SSteven Rostedt	    }
23090a05c769SSteven Rostedt	    if (!$found) {
23100a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
23110a05c769SSteven Rostedt		foreach my $config (@start_list) {
23120a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
23130a05c769SSteven Rostedt		}
23140a05c769SSteven Rostedt		return -1;
23150a05c769SSteven Rostedt	    }
23160a05c769SSteven Rostedt	    $count = $#tophalf + 1;
23170a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
23180a05c769SSteven Rostedt	}
23190a05c769SSteven Rostedt
23200a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
2321c960bb9fSSteven Rostedt	if ($bisect_manual) {
2322c960bb9fSSteven Rostedt	    $ret = answer_bisect;
2323c960bb9fSSteven Rostedt	}
23240a05c769SSteven Rostedt	if ($ret) {
23250a05c769SSteven Rostedt	    process_passed %current_config;
23260a05c769SSteven Rostedt	    return 0;
23270a05c769SSteven Rostedt	}
23280a05c769SSteven Rostedt
23290a05c769SSteven Rostedt	doprint "This config had a failure.\n";
23300a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
2331f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
2332f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
23330a05c769SSteven Rostedt
23340a05c769SSteven Rostedt	# A config exists in this group that was bad.
23350a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
23360a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
23370a05c769SSteven Rostedt		doprint " removing $config\n";
23380a05c769SSteven Rostedt		delete $config_list{$config};
23390a05c769SSteven Rostedt	    }
23400a05c769SSteven Rostedt	}
23410a05c769SSteven Rostedt
23420a05c769SSteven Rostedt	@start_list = @tophalf;
23430a05c769SSteven Rostedt
23440a05c769SSteven Rostedt	if ($#start_list == 0) {
23450a05c769SSteven Rostedt	    process_failed $start_list[0];
23460a05c769SSteven Rostedt	    return 1;
23470a05c769SSteven Rostedt	}
23480a05c769SSteven Rostedt
23490a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
23500a05c769SSteven Rostedt	# they are good.
23510a05c769SSteven Rostedt	$half = int($#start_list / 2);
23524c8cc55bSSteven Rostedt    } while ($#start_list > 0);
23530a05c769SSteven Rostedt
2354c960bb9fSSteven Rostedt    # we found a single config, try it again unless we are running manually
2355c960bb9fSSteven Rostedt
2356c960bb9fSSteven Rostedt    if ($bisect_manual) {
2357c960bb9fSSteven Rostedt	process_failed $start_list[0];
2358c960bb9fSSteven Rostedt	return 1;
2359c960bb9fSSteven Rostedt    }
2360c960bb9fSSteven Rostedt
23610a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
23620a05c769SSteven Rostedt
23630a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
23640a05c769SSteven Rostedt    if ($ret) {
23650a05c769SSteven Rostedt	process_passed %current_config;
23660a05c769SSteven Rostedt	return 0;
23670a05c769SSteven Rostedt    }
23680a05c769SSteven Rostedt
23690a05c769SSteven Rostedt    process_failed $start_list[0];
23700a05c769SSteven Rostedt    return 1;
23710a05c769SSteven Rostedt}
23720a05c769SSteven Rostedt
23730a05c769SSteven Rostedtsub config_bisect {
23740a05c769SSteven Rostedt    my ($i) = @_;
23750a05c769SSteven Rostedt
23760a05c769SSteven Rostedt    my $start_config = $opt{"CONFIG_BISECT[$i]"};
23770a05c769SSteven Rostedt
23780a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
23790a05c769SSteven Rostedt
238030f75da5SSteven Rostedt    if (defined($config_bisect_good)) {
238130f75da5SSteven Rostedt	process_config_ignore $config_bisect_good;
238230f75da5SSteven Rostedt    }
238330f75da5SSteven Rostedt
23840a05c769SSteven Rostedt    # Make the file with the bad config and the min config
23850a05c769SSteven Rostedt    if (defined($minconfig)) {
23860a05c769SSteven Rostedt	# read the min config for things to ignore
23870a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
23880a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
23890a05c769SSteven Rostedt    } else {
23900a05c769SSteven Rostedt	unlink $tmpconfig;
23910a05c769SSteven Rostedt    }
23920a05c769SSteven Rostedt
23930a05c769SSteven Rostedt    if (-f $tmpconfig) {
2394fcb3f16aSSteven Rostedt	load_force_config($tmpconfig);
23950a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
23960a05c769SSteven Rostedt    }
23970a05c769SSteven Rostedt
23980a05c769SSteven Rostedt    # now process the start config
23990a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
24000a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
24010a05c769SSteven Rostedt
24020a05c769SSteven Rostedt    # read directly what we want to check
24030a05c769SSteven Rostedt    my %config_check;
24040a05c769SSteven Rostedt    open (IN, $output_config)
24050a05c769SSteven Rostedt	or dodie "faied to open $output_config";
24060a05c769SSteven Rostedt
24070a05c769SSteven Rostedt    while (<IN>) {
24080a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
24090a05c769SSteven Rostedt	    $config_check{$2} = $1;
24100a05c769SSteven Rostedt	}
24110a05c769SSteven Rostedt    }
24120a05c769SSteven Rostedt    close(IN);
24130a05c769SSteven Rostedt
2414250bae8bSSteven Rostedt    # Now run oldconfig with the minconfig
2415fcb3f16aSSteven Rostedt    make_oldconfig;
24160a05c769SSteven Rostedt
24170a05c769SSteven Rostedt    # check to see what we lost (or gained)
24180a05c769SSteven Rostedt    open (IN, $output_config)
24190a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
24200a05c769SSteven Rostedt
24210a05c769SSteven Rostedt    my %removed_configs;
24220a05c769SSteven Rostedt    my %added_configs;
24230a05c769SSteven Rostedt
24240a05c769SSteven Rostedt    while (<IN>) {
24250a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
24260a05c769SSteven Rostedt	    # save off all options
24270a05c769SSteven Rostedt	    $config_set{$2} = $1;
24280a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
24290a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
24300a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
24310a05c769SSteven Rostedt		} else {
24320a05c769SSteven Rostedt		    $config_list{$2} = $1;
24330a05c769SSteven Rostedt		}
24340a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
24350a05c769SSteven Rostedt		$added_configs{$2} = $1;
24360a05c769SSteven Rostedt		$config_list{$2} = $1;
24370a05c769SSteven Rostedt	    }
24380a05c769SSteven Rostedt	}
24390a05c769SSteven Rostedt    }
24400a05c769SSteven Rostedt    close(IN);
24410a05c769SSteven Rostedt
24420a05c769SSteven Rostedt    my @confs = keys %removed_configs;
24430a05c769SSteven Rostedt    if ($#confs >= 0) {
24440a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
24450a05c769SSteven Rostedt	foreach my $config (@confs) {
24460a05c769SSteven Rostedt	    doprint " $config\n";
24470a05c769SSteven Rostedt	}
24480a05c769SSteven Rostedt    }
24490a05c769SSteven Rostedt    @confs = keys %added_configs;
24500a05c769SSteven Rostedt    if ($#confs >= 0) {
24510a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
24520a05c769SSteven Rostedt	foreach my $config (@confs) {
24530a05c769SSteven Rostedt	    doprint " $config\n";
24540a05c769SSteven Rostedt	}
24550a05c769SSteven Rostedt    }
24560a05c769SSteven Rostedt
24570a05c769SSteven Rostedt    my %config_test;
24580a05c769SSteven Rostedt    my $once = 0;
24590a05c769SSteven Rostedt
24600a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
24610a05c769SSteven Rostedt    # that the config we autocreate has everything we need
24620a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
24630a05c769SSteven Rostedt    # may not be able to create a new config.
24640a05c769SSteven Rostedt    # Here we create a config with everything set.
24650a05c769SSteven Rostedt    create_config (keys %config_list);
24660a05c769SSteven Rostedt    read_current_config \%config_test;
24670a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
24680a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
24690a05c769SSteven Rostedt	    if (!$once) {
24700a05c769SSteven Rostedt		$once = 1;
24710a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
24720a05c769SSteven Rostedt	    }
24730a05c769SSteven Rostedt	    doprint "  $config\n";
24740a05c769SSteven Rostedt	    delete $config_list{$config};
24750a05c769SSteven Rostedt	}
24760a05c769SSteven Rostedt    }
24770a05c769SSteven Rostedt    my $ret;
24780a05c769SSteven Rostedt    do {
24790a05c769SSteven Rostedt	$ret = run_config_bisect;
24800a05c769SSteven Rostedt    } while (!$ret);
24810a05c769SSteven Rostedt
24820a05c769SSteven Rostedt    return $ret if ($ret < 0);
24835f9b6cedSSteven Rostedt
24845f9b6cedSSteven Rostedt    success $i;
24855f9b6cedSSteven Rostedt}
24865f9b6cedSSteven Rostedt
248727d934b2SSteven Rostedtsub patchcheck_reboot {
248827d934b2SSteven Rostedt    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
24892728be41SAndrew Jones    reboot $patchcheck_sleep_time;
249027d934b2SSteven Rostedt}
249127d934b2SSteven Rostedt
24926c5ee0beSSteven Rostedtsub patchcheck {
24936c5ee0beSSteven Rostedt    my ($i) = @_;
24946c5ee0beSSteven Rostedt
24956c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
24966c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_START[$i]"}));
24976c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
24986c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
24996c5ee0beSSteven Rostedt
25006c5ee0beSSteven Rostedt    my $start = $opt{"PATCHCHECK_START[$i]"};
25016c5ee0beSSteven Rostedt
25026c5ee0beSSteven Rostedt    my $end = "HEAD";
25036c5ee0beSSteven Rostedt    if (defined($opt{"PATCHCHECK_END[$i]"})) {
25046c5ee0beSSteven Rostedt	$end = $opt{"PATCHCHECK_END[$i]"};
25056c5ee0beSSteven Rostedt    }
25066c5ee0beSSteven Rostedt
2507a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
2508a57419b3SSteven Rostedt    $start = get_sha1($start);
2509a57419b3SSteven Rostedt    $end = get_sha1($end);
2510a57419b3SSteven Rostedt
25116c5ee0beSSteven Rostedt    my $type = $opt{"PATCHCHECK_TYPE[$i]"};
25126c5ee0beSSteven Rostedt
25136c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
25146c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
25156c5ee0beSSteven Rostedt	$type = "boot";
25166c5ee0beSSteven Rostedt    }
25176c5ee0beSSteven Rostedt
25186c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
25196c5ee0beSSteven Rostedt	dodie "could not get git list";
25206c5ee0beSSteven Rostedt
25216c5ee0beSSteven Rostedt    my @list;
25226c5ee0beSSteven Rostedt
25236c5ee0beSSteven Rostedt    while (<IN>) {
25246c5ee0beSSteven Rostedt	chomp;
25256c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
25266c5ee0beSSteven Rostedt	last if (/^$start/);
25276c5ee0beSSteven Rostedt    }
25286c5ee0beSSteven Rostedt    close(IN);
25296c5ee0beSSteven Rostedt
25306c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
25312b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
25326c5ee0beSSteven Rostedt    }
25336c5ee0beSSteven Rostedt
25346c5ee0beSSteven Rostedt    # go backwards in the list
25356c5ee0beSSteven Rostedt    @list = reverse @list;
25366c5ee0beSSteven Rostedt
25376c5ee0beSSteven Rostedt    my $save_clean = $noclean;
25381990207dSSteven Rostedt    my %ignored_warnings;
25391990207dSSteven Rostedt
25401990207dSSteven Rostedt    if (defined($ignore_warnings)) {
25411990207dSSteven Rostedt	foreach my $sha1 (split /\s+/, $ignore_warnings) {
25421990207dSSteven Rostedt	    $ignored_warnings{$sha1} = 1;
25431990207dSSteven Rostedt	}
25441990207dSSteven Rostedt    }
25456c5ee0beSSteven Rostedt
25466c5ee0beSSteven Rostedt    $in_patchcheck = 1;
25476c5ee0beSSteven Rostedt    foreach my $item (@list) {
25486c5ee0beSSteven Rostedt	my $sha1 = $item;
25496c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
25506c5ee0beSSteven Rostedt
25516c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
25526c5ee0beSSteven Rostedt
25536c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
25546c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
25556c5ee0beSSteven Rostedt
25566c5ee0beSSteven Rostedt	# only clean on the first and last patch
25576c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
25586c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
25596c5ee0beSSteven Rostedt	    $noclean = $save_clean;
25606c5ee0beSSteven Rostedt	} else {
25616c5ee0beSSteven Rostedt	    $noclean = 1;
25626c5ee0beSSteven Rostedt	}
25636c5ee0beSSteven Rostedt
25646c5ee0beSSteven Rostedt	if (defined($minconfig)) {
25652b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
25666c5ee0beSSteven Rostedt	} else {
25676c5ee0beSSteven Rostedt	    # ?? no config to use?
25682b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
25696c5ee0beSSteven Rostedt	}
25706c5ee0beSSteven Rostedt
25711990207dSSteven Rostedt
25721990207dSSteven Rostedt	if (!defined($ignored_warnings{$sha1})) {
25732b7d9b21SSteven Rostedt	    check_buildlog $sha1 or return 0;
25741990207dSSteven Rostedt	}
25756c5ee0beSSteven Rostedt
25766c5ee0beSSteven Rostedt	next if ($type eq "build");
25776c5ee0beSSteven Rostedt
25787faafbd6SSteven Rostedt	my $failed = 0;
25797faafbd6SSteven Rostedt
2580ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
25817faafbd6SSteven Rostedt
25827faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
25837faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
25847faafbd6SSteven Rostedt	}
25857faafbd6SSteven Rostedt	end_monitor;
25867faafbd6SSteven Rostedt	return 0 if ($failed);
25877faafbd6SSteven Rostedt
258827d934b2SSteven Rostedt	patchcheck_reboot;
258927d934b2SSteven Rostedt
25906c5ee0beSSteven Rostedt    }
25916c5ee0beSSteven Rostedt    $in_patchcheck = 0;
25926c5ee0beSSteven Rostedt    success $i;
25932b7d9b21SSteven Rostedt
25942b7d9b21SSteven Rostedt    return 1;
25956c5ee0beSSteven Rostedt}
25966c5ee0beSSteven Rostedt
2597b9066f6cSSteven Rostedtmy %depends;
2598ac6974c7SSteven Rostedtmy %depcount;
2599b9066f6cSSteven Rostedtmy $iflevel = 0;
2600b9066f6cSSteven Rostedtmy @ifdeps;
2601b9066f6cSSteven Rostedt
2602b9066f6cSSteven Rostedt# prevent recursion
2603b9066f6cSSteven Rostedtmy %read_kconfigs;
2604b9066f6cSSteven Rostedt
2605ac6974c7SSteven Rostedtsub add_dep {
2606ac6974c7SSteven Rostedt    # $config depends on $dep
2607ac6974c7SSteven Rostedt    my ($config, $dep) = @_;
2608ac6974c7SSteven Rostedt
2609ac6974c7SSteven Rostedt    if (defined($depends{$config})) {
2610ac6974c7SSteven Rostedt	$depends{$config} .= " " . $dep;
2611ac6974c7SSteven Rostedt    } else {
2612ac6974c7SSteven Rostedt	$depends{$config} = $dep;
2613ac6974c7SSteven Rostedt    }
2614ac6974c7SSteven Rostedt
2615ac6974c7SSteven Rostedt    # record the number of configs depending on $dep
2616ac6974c7SSteven Rostedt    if (defined $depcount{$dep}) {
2617ac6974c7SSteven Rostedt	$depcount{$dep}++;
2618ac6974c7SSteven Rostedt    } else {
2619ac6974c7SSteven Rostedt	$depcount{$dep} = 1;
2620ac6974c7SSteven Rostedt    }
2621ac6974c7SSteven Rostedt}
2622ac6974c7SSteven Rostedt
2623b9066f6cSSteven Rostedt# taken from streamline_config.pl
2624b9066f6cSSteven Rostedtsub read_kconfig {
2625b9066f6cSSteven Rostedt    my ($kconfig) = @_;
2626b9066f6cSSteven Rostedt
2627b9066f6cSSteven Rostedt    my $state = "NONE";
2628b9066f6cSSteven Rostedt    my $config;
2629b9066f6cSSteven Rostedt    my @kconfigs;
2630b9066f6cSSteven Rostedt
2631b9066f6cSSteven Rostedt    my $cont = 0;
2632b9066f6cSSteven Rostedt    my $line;
2633b9066f6cSSteven Rostedt
2634b9066f6cSSteven Rostedt
2635b9066f6cSSteven Rostedt    if (! -f $kconfig) {
2636b9066f6cSSteven Rostedt	doprint "file $kconfig does not exist, skipping\n";
2637b9066f6cSSteven Rostedt	return;
2638b9066f6cSSteven Rostedt    }
2639b9066f6cSSteven Rostedt
2640b9066f6cSSteven Rostedt    open(KIN, "$kconfig")
2641b9066f6cSSteven Rostedt	or die "Can't open $kconfig";
2642b9066f6cSSteven Rostedt    while (<KIN>) {
2643b9066f6cSSteven Rostedt	chomp;
2644b9066f6cSSteven Rostedt
2645b9066f6cSSteven Rostedt	# Make sure that lines ending with \ continue
2646b9066f6cSSteven Rostedt	if ($cont) {
2647b9066f6cSSteven Rostedt	    $_ = $line . " " . $_;
2648b9066f6cSSteven Rostedt	}
2649b9066f6cSSteven Rostedt
2650b9066f6cSSteven Rostedt	if (s/\\$//) {
2651b9066f6cSSteven Rostedt	    $cont = 1;
2652b9066f6cSSteven Rostedt	    $line = $_;
2653b9066f6cSSteven Rostedt	    next;
2654b9066f6cSSteven Rostedt	}
2655b9066f6cSSteven Rostedt
2656b9066f6cSSteven Rostedt	$cont = 0;
2657b9066f6cSSteven Rostedt
2658b9066f6cSSteven Rostedt	# collect any Kconfig sources
2659b9066f6cSSteven Rostedt	if (/^source\s*"(.*)"/) {
2660b9066f6cSSteven Rostedt	    $kconfigs[$#kconfigs+1] = $1;
2661b9066f6cSSteven Rostedt	}
2662b9066f6cSSteven Rostedt
2663b9066f6cSSteven Rostedt	# configs found
2664b9066f6cSSteven Rostedt	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
2665b9066f6cSSteven Rostedt	    $state = "NEW";
2666b9066f6cSSteven Rostedt	    $config = $2;
2667b9066f6cSSteven Rostedt
2668b9066f6cSSteven Rostedt	    for (my $i = 0; $i < $iflevel; $i++) {
2669ac6974c7SSteven Rostedt		add_dep $config, $ifdeps[$i];
2670b9066f6cSSteven Rostedt	    }
2671b9066f6cSSteven Rostedt
2672b9066f6cSSteven Rostedt	# collect the depends for the config
2673b9066f6cSSteven Rostedt	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
2674b9066f6cSSteven Rostedt
2675ac6974c7SSteven Rostedt	    add_dep $config, $1;
2676b9066f6cSSteven Rostedt
2677b9066f6cSSteven Rostedt	# Get the configs that select this config
2678ac6974c7SSteven Rostedt	} elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
2679ac6974c7SSteven Rostedt
2680ac6974c7SSteven Rostedt	    # selected by depends on config
2681ac6974c7SSteven Rostedt	    add_dep $1, $config;
2682b9066f6cSSteven Rostedt
2683b9066f6cSSteven Rostedt	# Check for if statements
2684b9066f6cSSteven Rostedt	} elsif (/^if\s+(.*\S)\s*$/) {
2685b9066f6cSSteven Rostedt	    my $deps = $1;
2686b9066f6cSSteven Rostedt	    # remove beginning and ending non text
2687b9066f6cSSteven Rostedt	    $deps =~ s/^[^a-zA-Z0-9_]*//;
2688b9066f6cSSteven Rostedt	    $deps =~ s/[^a-zA-Z0-9_]*$//;
2689b9066f6cSSteven Rostedt
2690b9066f6cSSteven Rostedt	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
2691b9066f6cSSteven Rostedt
2692b9066f6cSSteven Rostedt	    $ifdeps[$iflevel++] = join ':', @deps;
2693b9066f6cSSteven Rostedt
2694b9066f6cSSteven Rostedt	} elsif (/^endif/) {
2695b9066f6cSSteven Rostedt
2696b9066f6cSSteven Rostedt	    $iflevel-- if ($iflevel);
2697b9066f6cSSteven Rostedt
2698b9066f6cSSteven Rostedt	# stop on "help"
2699b9066f6cSSteven Rostedt	} elsif (/^\s*help\s*$/) {
2700b9066f6cSSteven Rostedt	    $state = "NONE";
2701b9066f6cSSteven Rostedt	}
2702b9066f6cSSteven Rostedt    }
2703b9066f6cSSteven Rostedt    close(KIN);
2704b9066f6cSSteven Rostedt
2705b9066f6cSSteven Rostedt    # read in any configs that were found.
2706b9066f6cSSteven Rostedt    foreach $kconfig (@kconfigs) {
2707b9066f6cSSteven Rostedt	if (!defined($read_kconfigs{$kconfig})) {
2708b9066f6cSSteven Rostedt	    $read_kconfigs{$kconfig} = 1;
2709b9066f6cSSteven Rostedt	    read_kconfig("$builddir/$kconfig");
2710b9066f6cSSteven Rostedt	}
2711b9066f6cSSteven Rostedt    }
2712b9066f6cSSteven Rostedt}
2713b9066f6cSSteven Rostedt
2714b9066f6cSSteven Rostedtsub read_depends {
2715b9066f6cSSteven Rostedt    # find out which arch this is by the kconfig file
2716b9066f6cSSteven Rostedt    open (IN, $output_config)
2717b9066f6cSSteven Rostedt	or dodie "Failed to read $output_config";
2718b9066f6cSSteven Rostedt    my $arch;
2719b9066f6cSSteven Rostedt    while (<IN>) {
2720b9066f6cSSteven Rostedt	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
2721b9066f6cSSteven Rostedt	    $arch = $1;
2722b9066f6cSSteven Rostedt	    last;
2723b9066f6cSSteven Rostedt	}
2724b9066f6cSSteven Rostedt    }
2725b9066f6cSSteven Rostedt    close IN;
2726b9066f6cSSteven Rostedt
2727b9066f6cSSteven Rostedt    if (!defined($arch)) {
2728b9066f6cSSteven Rostedt	doprint "Could not find arch from config file\n";
2729b9066f6cSSteven Rostedt	doprint "no dependencies used\n";
2730b9066f6cSSteven Rostedt	return;
2731b9066f6cSSteven Rostedt    }
2732b9066f6cSSteven Rostedt
2733b9066f6cSSteven Rostedt    # arch is really the subarch, we need to know
2734b9066f6cSSteven Rostedt    # what directory to look at.
2735b9066f6cSSteven Rostedt    if ($arch eq "i386" || $arch eq "x86_64") {
2736b9066f6cSSteven Rostedt	$arch = "x86";
2737b9066f6cSSteven Rostedt    } elsif ($arch =~ /^tile/) {
2738b9066f6cSSteven Rostedt	$arch = "tile";
2739b9066f6cSSteven Rostedt    }
2740b9066f6cSSteven Rostedt
2741b9066f6cSSteven Rostedt    my $kconfig = "$builddir/arch/$arch/Kconfig";
2742b9066f6cSSteven Rostedt
2743b9066f6cSSteven Rostedt    if (! -f $kconfig && $arch =~ /\d$/) {
2744b9066f6cSSteven Rostedt	my $orig = $arch;
2745b9066f6cSSteven Rostedt 	# some subarchs have numbers, truncate them
2746b9066f6cSSteven Rostedt	$arch =~ s/\d*$//;
2747b9066f6cSSteven Rostedt	$kconfig = "$builddir/arch/$arch/Kconfig";
2748b9066f6cSSteven Rostedt	if (! -f $kconfig) {
2749b9066f6cSSteven Rostedt	    doprint "No idea what arch dir $orig is for\n";
2750b9066f6cSSteven Rostedt	    doprint "no dependencies used\n";
2751b9066f6cSSteven Rostedt	    return;
2752b9066f6cSSteven Rostedt	}
2753b9066f6cSSteven Rostedt    }
2754b9066f6cSSteven Rostedt
2755b9066f6cSSteven Rostedt    read_kconfig($kconfig);
2756b9066f6cSSteven Rostedt}
2757b9066f6cSSteven Rostedt
27584c4ab120SSteven Rostedtsub read_config_list {
27594c4ab120SSteven Rostedt    my ($config) = @_;
27604c4ab120SSteven Rostedt
27614c4ab120SSteven Rostedt    open (IN, $config)
27624c4ab120SSteven Rostedt	or dodie "Failed to read $config";
27634c4ab120SSteven Rostedt
27644c4ab120SSteven Rostedt    while (<IN>) {
27654c4ab120SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
27664c4ab120SSteven Rostedt	    if (!defined($config_ignore{$2})) {
27674c4ab120SSteven Rostedt		$config_list{$2} = $1;
27684c4ab120SSteven Rostedt	    }
27694c4ab120SSteven Rostedt	}
27704c4ab120SSteven Rostedt    }
27714c4ab120SSteven Rostedt
27724c4ab120SSteven Rostedt    close(IN);
27734c4ab120SSteven Rostedt}
27744c4ab120SSteven Rostedt
27754c4ab120SSteven Rostedtsub read_output_config {
27764c4ab120SSteven Rostedt    my ($config) = @_;
27774c4ab120SSteven Rostedt
27784c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
27794c4ab120SSteven Rostedt}
27804c4ab120SSteven Rostedt
27814c4ab120SSteven Rostedtsub make_new_config {
27824c4ab120SSteven Rostedt    my @configs = @_;
27834c4ab120SSteven Rostedt
27844c4ab120SSteven Rostedt    open (OUT, ">$output_config")
27854c4ab120SSteven Rostedt	or dodie "Failed to write $output_config";
27864c4ab120SSteven Rostedt
27874c4ab120SSteven Rostedt    foreach my $config (@configs) {
27884c4ab120SSteven Rostedt	print OUT "$config\n";
27894c4ab120SSteven Rostedt    }
27904c4ab120SSteven Rostedt    close OUT;
27914c4ab120SSteven Rostedt}
27924c4ab120SSteven Rostedt
2793ac6974c7SSteven Rostedtsub chomp_config {
2794ac6974c7SSteven Rostedt    my ($config) = @_;
2795ac6974c7SSteven Rostedt
2796ac6974c7SSteven Rostedt    $config =~ s/CONFIG_//;
2797ac6974c7SSteven Rostedt
2798ac6974c7SSteven Rostedt    return $config;
2799ac6974c7SSteven Rostedt}
2800ac6974c7SSteven Rostedt
2801b9066f6cSSteven Rostedtsub get_depends {
2802b9066f6cSSteven Rostedt    my ($dep) = @_;
2803b9066f6cSSteven Rostedt
2804ac6974c7SSteven Rostedt    my $kconfig = chomp_config $dep;
2805b9066f6cSSteven Rostedt
2806b9066f6cSSteven Rostedt    $dep = $depends{"$kconfig"};
2807b9066f6cSSteven Rostedt
2808b9066f6cSSteven Rostedt    # the dep string we have saves the dependencies as they
2809b9066f6cSSteven Rostedt    # were found, including expressions like ! && ||. We
2810b9066f6cSSteven Rostedt    # want to split this out into just an array of configs.
2811b9066f6cSSteven Rostedt
2812b9066f6cSSteven Rostedt    my $valid = "A-Za-z_0-9";
2813b9066f6cSSteven Rostedt
2814b9066f6cSSteven Rostedt    my @configs;
2815b9066f6cSSteven Rostedt
2816b9066f6cSSteven Rostedt    while ($dep =~ /[$valid]/) {
2817b9066f6cSSteven Rostedt
2818b9066f6cSSteven Rostedt	if ($dep =~ /^[^$valid]*([$valid]+)/) {
2819b9066f6cSSteven Rostedt	    my $conf = "CONFIG_" . $1;
2820b9066f6cSSteven Rostedt
2821b9066f6cSSteven Rostedt	    $configs[$#configs + 1] = $conf;
2822b9066f6cSSteven Rostedt
2823b9066f6cSSteven Rostedt	    $dep =~ s/^[^$valid]*[$valid]+//;
2824b9066f6cSSteven Rostedt	} else {
2825b9066f6cSSteven Rostedt	    die "this should never happen";
2826b9066f6cSSteven Rostedt	}
2827b9066f6cSSteven Rostedt    }
2828b9066f6cSSteven Rostedt
2829b9066f6cSSteven Rostedt    return @configs;
2830b9066f6cSSteven Rostedt}
2831b9066f6cSSteven Rostedt
2832b9066f6cSSteven Rostedtmy %min_configs;
2833b9066f6cSSteven Rostedtmy %keep_configs;
283443d1b651SSteven Rostedtmy %save_configs;
2835b9066f6cSSteven Rostedtmy %processed_configs;
2836b9066f6cSSteven Rostedtmy %nochange_config;
2837b9066f6cSSteven Rostedt
2838b9066f6cSSteven Rostedtsub test_this_config {
2839b9066f6cSSteven Rostedt    my ($config) = @_;
2840b9066f6cSSteven Rostedt
2841b9066f6cSSteven Rostedt    my $found;
2842b9066f6cSSteven Rostedt
2843b9066f6cSSteven Rostedt    # if we already processed this config, skip it
2844b9066f6cSSteven Rostedt    if (defined($processed_configs{$config})) {
2845b9066f6cSSteven Rostedt	return undef;
2846b9066f6cSSteven Rostedt    }
2847b9066f6cSSteven Rostedt    $processed_configs{$config} = 1;
2848b9066f6cSSteven Rostedt
2849b9066f6cSSteven Rostedt    # if this config failed during this round, skip it
2850b9066f6cSSteven Rostedt    if (defined($nochange_config{$config})) {
2851b9066f6cSSteven Rostedt	return undef;
2852b9066f6cSSteven Rostedt    }
2853b9066f6cSSteven Rostedt
2854ac6974c7SSteven Rostedt    my $kconfig = chomp_config $config;
2855b9066f6cSSteven Rostedt
2856b9066f6cSSteven Rostedt    # Test dependencies first
2857b9066f6cSSteven Rostedt    if (defined($depends{"$kconfig"})) {
2858b9066f6cSSteven Rostedt	my @parents = get_depends $config;
2859b9066f6cSSteven Rostedt	foreach my $parent (@parents) {
2860b9066f6cSSteven Rostedt	    # if the parent is in the min config, check it first
2861b9066f6cSSteven Rostedt	    next if (!defined($min_configs{$parent}));
2862b9066f6cSSteven Rostedt	    $found = test_this_config($parent);
2863b9066f6cSSteven Rostedt	    if (defined($found)) {
2864b9066f6cSSteven Rostedt		return $found;
2865b9066f6cSSteven Rostedt	    }
2866b9066f6cSSteven Rostedt	}
2867b9066f6cSSteven Rostedt    }
2868b9066f6cSSteven Rostedt
2869b9066f6cSSteven Rostedt    # Remove this config from the list of configs
2870b9066f6cSSteven Rostedt    # do a make oldnoconfig and then read the resulting
2871b9066f6cSSteven Rostedt    # .config to make sure it is missing the config that
2872b9066f6cSSteven Rostedt    # we had before
2873b9066f6cSSteven Rostedt    my %configs = %min_configs;
2874b9066f6cSSteven Rostedt    delete $configs{$config};
2875b9066f6cSSteven Rostedt    make_new_config ((values %configs), (values %keep_configs));
2876b9066f6cSSteven Rostedt    make_oldconfig;
2877b9066f6cSSteven Rostedt    undef %configs;
2878b9066f6cSSteven Rostedt    assign_configs \%configs, $output_config;
2879b9066f6cSSteven Rostedt
2880b9066f6cSSteven Rostedt    return $config if (!defined($configs{$config}));
2881b9066f6cSSteven Rostedt
2882b9066f6cSSteven Rostedt    doprint "disabling config $config did not change .config\n";
2883b9066f6cSSteven Rostedt
2884b9066f6cSSteven Rostedt    $nochange_config{$config} = 1;
2885b9066f6cSSteven Rostedt
2886b9066f6cSSteven Rostedt    return undef;
2887b9066f6cSSteven Rostedt}
2888b9066f6cSSteven Rostedt
28894c4ab120SSteven Rostedtsub make_min_config {
28904c4ab120SSteven Rostedt    my ($i) = @_;
28914c4ab120SSteven Rostedt
28924c4ab120SSteven Rostedt    if (!defined($output_minconfig)) {
28934c4ab120SSteven Rostedt	fail "OUTPUT_MIN_CONFIG not defined" and return;
28944c4ab120SSteven Rostedt    }
289535ce5952SSteven Rostedt
289635ce5952SSteven Rostedt    # If output_minconfig exists, and the start_minconfig
289735ce5952SSteven Rostedt    # came from min_config, than ask if we should use
289835ce5952SSteven Rostedt    # that instead.
289935ce5952SSteven Rostedt    if (-f $output_minconfig && !$start_minconfig_defined) {
290035ce5952SSteven Rostedt	print "$output_minconfig exists\n";
290135ce5952SSteven Rostedt	if (read_yn " Use it as minconfig?") {
290235ce5952SSteven Rostedt	    $start_minconfig = $output_minconfig;
290335ce5952SSteven Rostedt	}
290435ce5952SSteven Rostedt    }
290535ce5952SSteven Rostedt
29064c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
29074c4ab120SSteven Rostedt	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
29084c4ab120SSteven Rostedt    }
29094c4ab120SSteven Rostedt
291035ce5952SSteven Rostedt    my $temp_config = "$tmpdir/temp_config";
291135ce5952SSteven Rostedt
29124c4ab120SSteven Rostedt    # First things first. We build an allnoconfig to find
29134c4ab120SSteven Rostedt    # out what the defaults are that we can't touch.
29144c4ab120SSteven Rostedt    # Some are selections, but we really can't handle selections.
29154c4ab120SSteven Rostedt
29164c4ab120SSteven Rostedt    my $save_minconfig = $minconfig;
29174c4ab120SSteven Rostedt    undef $minconfig;
29184c4ab120SSteven Rostedt
29194c4ab120SSteven Rostedt    run_command "$make allnoconfig" or return 0;
29204c4ab120SSteven Rostedt
2921b9066f6cSSteven Rostedt    read_depends;
2922b9066f6cSSteven Rostedt
29234c4ab120SSteven Rostedt    process_config_ignore $output_config;
2924b9066f6cSSteven Rostedt
292543d1b651SSteven Rostedt    undef %save_configs;
2926b9066f6cSSteven Rostedt    undef %min_configs;
29274c4ab120SSteven Rostedt
29284c4ab120SSteven Rostedt    if (defined($ignore_config)) {
29294c4ab120SSteven Rostedt	# make sure the file exists
29304c4ab120SSteven Rostedt	`touch $ignore_config`;
293143d1b651SSteven Rostedt	assign_configs \%save_configs, $ignore_config;
29324c4ab120SSteven Rostedt    }
29334c4ab120SSteven Rostedt
293443d1b651SSteven Rostedt    %keep_configs = %save_configs;
293543d1b651SSteven Rostedt
29364c4ab120SSteven Rostedt    doprint "Load initial configs from $start_minconfig\n";
29374c4ab120SSteven Rostedt
29384c4ab120SSteven Rostedt    # Look at the current min configs, and save off all the
29394c4ab120SSteven Rostedt    # ones that were set via the allnoconfig
29404c4ab120SSteven Rostedt    assign_configs \%min_configs, $start_minconfig;
29414c4ab120SSteven Rostedt
29424c4ab120SSteven Rostedt    my @config_keys = keys %min_configs;
29434c4ab120SSteven Rostedt
2944ac6974c7SSteven Rostedt    # All configs need a depcount
2945ac6974c7SSteven Rostedt    foreach my $config (@config_keys) {
2946ac6974c7SSteven Rostedt	my $kconfig = chomp_config $config;
2947ac6974c7SSteven Rostedt	if (!defined $depcount{$kconfig}) {
2948ac6974c7SSteven Rostedt		$depcount{$kconfig} = 0;
2949ac6974c7SSteven Rostedt	}
2950ac6974c7SSteven Rostedt    }
2951ac6974c7SSteven Rostedt
29524c4ab120SSteven Rostedt    # Remove anything that was set by the make allnoconfig
29534c4ab120SSteven Rostedt    # we shouldn't need them as they get set for us anyway.
29544c4ab120SSteven Rostedt    foreach my $config (@config_keys) {
29554c4ab120SSteven Rostedt	# Remove anything in the ignore_config
29564c4ab120SSteven Rostedt	if (defined($keep_configs{$config})) {
29574c4ab120SSteven Rostedt	    my $file = $ignore_config;
29584c4ab120SSteven Rostedt	    $file =~ s,.*/(.*?)$,$1,;
29594c4ab120SSteven Rostedt	    doprint "$config set by $file ... ignored\n";
29604c4ab120SSteven Rostedt	    delete $min_configs{$config};
29614c4ab120SSteven Rostedt	    next;
29624c4ab120SSteven Rostedt	}
29634c4ab120SSteven Rostedt	# But make sure the settings are the same. If a min config
29644c4ab120SSteven Rostedt	# sets a selection, we do not want to get rid of it if
29654c4ab120SSteven Rostedt	# it is not the same as what we have. Just move it into
29664c4ab120SSteven Rostedt	# the keep configs.
29674c4ab120SSteven Rostedt	if (defined($config_ignore{$config})) {
29684c4ab120SSteven Rostedt	    if ($config_ignore{$config} ne $min_configs{$config}) {
29694c4ab120SSteven Rostedt		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
29704c4ab120SSteven Rostedt		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
29714c4ab120SSteven Rostedt		$keep_configs{$config} = $min_configs{$config};
29724c4ab120SSteven Rostedt	    } else {
29734c4ab120SSteven Rostedt		doprint "$config set by allnoconfig ... ignored\n";
29744c4ab120SSteven Rostedt	    }
29754c4ab120SSteven Rostedt	    delete $min_configs{$config};
29764c4ab120SSteven Rostedt	}
29774c4ab120SSteven Rostedt    }
29784c4ab120SSteven Rostedt
29794c4ab120SSteven Rostedt    my $done = 0;
2980b9066f6cSSteven Rostedt    my $take_two = 0;
29814c4ab120SSteven Rostedt
29824c4ab120SSteven Rostedt    while (!$done) {
29834c4ab120SSteven Rostedt
29844c4ab120SSteven Rostedt	my $config;
29854c4ab120SSteven Rostedt	my $found;
29864c4ab120SSteven Rostedt
29874c4ab120SSteven Rostedt	# Now disable each config one by one and do a make oldconfig
29884c4ab120SSteven Rostedt	# till we find a config that changes our list.
29894c4ab120SSteven Rostedt
29904c4ab120SSteven Rostedt	my @test_configs = keys %min_configs;
2991ac6974c7SSteven Rostedt
2992ac6974c7SSteven Rostedt	# Sort keys by who is most dependent on
2993ac6974c7SSteven Rostedt	@test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
2994ac6974c7SSteven Rostedt			  @test_configs ;
2995ac6974c7SSteven Rostedt
2996ac6974c7SSteven Rostedt	# Put configs that did not modify the config at the end.
29974c4ab120SSteven Rostedt	my $reset = 1;
29984c4ab120SSteven Rostedt	for (my $i = 0; $i < $#test_configs; $i++) {
29994c4ab120SSteven Rostedt	    if (!defined($nochange_config{$test_configs[0]})) {
30004c4ab120SSteven Rostedt		$reset = 0;
30014c4ab120SSteven Rostedt		last;
30024c4ab120SSteven Rostedt	    }
30034c4ab120SSteven Rostedt	    # This config didn't change the .config last time.
30044c4ab120SSteven Rostedt	    # Place it at the end
30054c4ab120SSteven Rostedt	    my $config = shift @test_configs;
30064c4ab120SSteven Rostedt	    push @test_configs, $config;
30074c4ab120SSteven Rostedt	}
30084c4ab120SSteven Rostedt
30094c4ab120SSteven Rostedt	# if every test config has failed to modify the .config file
30104c4ab120SSteven Rostedt	# in the past, then reset and start over.
30114c4ab120SSteven Rostedt	if ($reset) {
30124c4ab120SSteven Rostedt	    undef %nochange_config;
30134c4ab120SSteven Rostedt	}
30144c4ab120SSteven Rostedt
3015b9066f6cSSteven Rostedt	undef %processed_configs;
3016b9066f6cSSteven Rostedt
30174c4ab120SSteven Rostedt	foreach my $config (@test_configs) {
30184c4ab120SSteven Rostedt
3019b9066f6cSSteven Rostedt	    $found = test_this_config $config;
30204c4ab120SSteven Rostedt
3021b9066f6cSSteven Rostedt	    last if (defined($found));
30224c4ab120SSteven Rostedt
30234c4ab120SSteven Rostedt	    # oh well, try another config
30244c4ab120SSteven Rostedt	}
30254c4ab120SSteven Rostedt
30264c4ab120SSteven Rostedt	if (!defined($found)) {
3027b9066f6cSSteven Rostedt	    # we could have failed due to the nochange_config hash
3028b9066f6cSSteven Rostedt	    # reset and try again
3029b9066f6cSSteven Rostedt	    if (!$take_two) {
3030b9066f6cSSteven Rostedt		undef %nochange_config;
3031b9066f6cSSteven Rostedt		$take_two = 1;
3032b9066f6cSSteven Rostedt		next;
3033b9066f6cSSteven Rostedt	    }
30344c4ab120SSteven Rostedt	    doprint "No more configs found that we can disable\n";
30354c4ab120SSteven Rostedt	    $done = 1;
30364c4ab120SSteven Rostedt	    last;
30374c4ab120SSteven Rostedt	}
3038b9066f6cSSteven Rostedt	$take_two = 0;
30394c4ab120SSteven Rostedt
30404c4ab120SSteven Rostedt	$config = $found;
30414c4ab120SSteven Rostedt
30424c4ab120SSteven Rostedt	doprint "Test with $config disabled\n";
30434c4ab120SSteven Rostedt
30444c4ab120SSteven Rostedt	# set in_bisect to keep build and monitor from dieing
30454c4ab120SSteven Rostedt	$in_bisect = 1;
30464c4ab120SSteven Rostedt
30474c4ab120SSteven Rostedt	my $failed = 0;
30484c4ab120SSteven Rostedt	build "oldconfig";
30494c4ab120SSteven Rostedt	start_monitor_and_boot or $failed = 1;
30504c4ab120SSteven Rostedt	end_monitor;
30514c4ab120SSteven Rostedt
30524c4ab120SSteven Rostedt	$in_bisect = 0;
30534c4ab120SSteven Rostedt
30544c4ab120SSteven Rostedt	if ($failed) {
3055b9066f6cSSteven Rostedt	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
30564c4ab120SSteven Rostedt	    # this config is needed, add it to the ignore list.
30574c4ab120SSteven Rostedt	    $keep_configs{$config} = $min_configs{$config};
305843d1b651SSteven Rostedt	    $save_configs{$config} = $min_configs{$config};
30594c4ab120SSteven Rostedt	    delete $min_configs{$config};
306035ce5952SSteven Rostedt
306135ce5952SSteven Rostedt	    # update new ignore configs
306235ce5952SSteven Rostedt	    if (defined($ignore_config)) {
306335ce5952SSteven Rostedt		open (OUT, ">$temp_config")
306435ce5952SSteven Rostedt		    or die "Can't write to $temp_config";
306543d1b651SSteven Rostedt		foreach my $config (keys %save_configs) {
306643d1b651SSteven Rostedt		    print OUT "$save_configs{$config}\n";
306735ce5952SSteven Rostedt		}
306835ce5952SSteven Rostedt		close OUT;
306935ce5952SSteven Rostedt		run_command "mv $temp_config $ignore_config" or
307035ce5952SSteven Rostedt		    dodie "failed to copy update to $ignore_config";
307135ce5952SSteven Rostedt	    }
307235ce5952SSteven Rostedt
30734c4ab120SSteven Rostedt	} else {
30744c4ab120SSteven Rostedt	    # We booted without this config, remove it from the minconfigs.
30754c4ab120SSteven Rostedt	    doprint "$config is not needed, disabling\n";
30764c4ab120SSteven Rostedt
30774c4ab120SSteven Rostedt	    delete $min_configs{$config};
30784c4ab120SSteven Rostedt
30794c4ab120SSteven Rostedt	    # Also disable anything that is not enabled in this config
30804c4ab120SSteven Rostedt	    my %configs;
30814c4ab120SSteven Rostedt	    assign_configs \%configs, $output_config;
30824c4ab120SSteven Rostedt	    my @config_keys = keys %min_configs;
30834c4ab120SSteven Rostedt	    foreach my $config (@config_keys) {
30844c4ab120SSteven Rostedt		if (!defined($configs{$config})) {
30854c4ab120SSteven Rostedt		    doprint "$config is not set, disabling\n";
30864c4ab120SSteven Rostedt		    delete $min_configs{$config};
30874c4ab120SSteven Rostedt		}
30884c4ab120SSteven Rostedt	    }
30894c4ab120SSteven Rostedt
30904c4ab120SSteven Rostedt	    # Save off all the current mandidory configs
309135ce5952SSteven Rostedt	    open (OUT, ">$temp_config")
309235ce5952SSteven Rostedt		or die "Can't write to $temp_config";
30934c4ab120SSteven Rostedt	    foreach my $config (keys %keep_configs) {
30944c4ab120SSteven Rostedt		print OUT "$keep_configs{$config}\n";
30954c4ab120SSteven Rostedt	    }
30964c4ab120SSteven Rostedt	    foreach my $config (keys %min_configs) {
30974c4ab120SSteven Rostedt		print OUT "$min_configs{$config}\n";
30984c4ab120SSteven Rostedt	    }
30994c4ab120SSteven Rostedt	    close OUT;
310035ce5952SSteven Rostedt
310135ce5952SSteven Rostedt	    run_command "mv $temp_config $output_minconfig" or
310235ce5952SSteven Rostedt		dodie "failed to copy update to $output_minconfig";
31034c4ab120SSteven Rostedt	}
31044c4ab120SSteven Rostedt
31054c4ab120SSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
31062728be41SAndrew Jones	reboot $sleep_time;
31074c4ab120SSteven Rostedt    }
31084c4ab120SSteven Rostedt
31094c4ab120SSteven Rostedt    success $i;
31104c4ab120SSteven Rostedt    return 1;
31114c4ab120SSteven Rostedt}
31124c4ab120SSteven Rostedt
31138d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
31142545eb61SSteven Rostedt
31158d1491baSSteven Rostedtif ($#ARGV == 0) {
31168d1491baSSteven Rostedt    $ktest_config = $ARGV[0];
31178d1491baSSteven Rostedt    if (! -f $ktest_config) {
31188d1491baSSteven Rostedt	print "$ktest_config does not exist.\n";
311935ce5952SSteven Rostedt	if (!read_yn "Create it?") {
31208d1491baSSteven Rostedt	    exit 0;
31218d1491baSSteven Rostedt	}
31228d1491baSSteven Rostedt    }
31238d1491baSSteven Rostedt} else {
31248d1491baSSteven Rostedt    $ktest_config = "ktest.conf";
31258d1491baSSteven Rostedt}
31268d1491baSSteven Rostedt
31278d1491baSSteven Rostedtif (! -f $ktest_config) {
3128dbd3783bSSteven Rostedt    $newconfig = 1;
3129c4261d0fSSteven Rostedt    get_test_case;
31308d1491baSSteven Rostedt    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
31318d1491baSSteven Rostedt    print OUT << "EOF"
31328d1491baSSteven Rostedt# Generated by ktest.pl
31338d1491baSSteven Rostedt#
31340e7a22deSSteven Rostedt
31350e7a22deSSteven Rostedt# PWD is a ktest.pl variable that will result in the process working
31360e7a22deSSteven Rostedt# directory that ktest.pl is executed in.
31370e7a22deSSteven Rostedt
31380e7a22deSSteven Rostedt# THIS_DIR is automatically assigned the PWD of the path that generated
31390e7a22deSSteven Rostedt# the config file. It is best to use this variable when assigning other
31400e7a22deSSteven Rostedt# directory paths within this directory. This allows you to easily
31410e7a22deSSteven Rostedt# move the test cases to other locations or to other machines.
31420e7a22deSSteven Rostedt#
31430e7a22deSSteven RostedtTHIS_DIR := $variable{"PWD"}
31440e7a22deSSteven Rostedt
31458d1491baSSteven Rostedt# Define each test with TEST_START
31468d1491baSSteven Rostedt# The config options below it will override the defaults
31478d1491baSSteven RostedtTEST_START
3148c4261d0fSSteven RostedtTEST_TYPE = $default{"TEST_TYPE"}
31498d1491baSSteven Rostedt
31508d1491baSSteven RostedtDEFAULTS
31518d1491baSSteven RostedtEOF
31528d1491baSSteven Rostedt;
31538d1491baSSteven Rostedt    close(OUT);
31548d1491baSSteven Rostedt}
31558d1491baSSteven Rostedtread_config $ktest_config;
31568d1491baSSteven Rostedt
315723715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) {
315823715c3cSSteven Rostedt    $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
315923715c3cSSteven Rostedt}
316023715c3cSSteven Rostedt
31618d1491baSSteven Rostedt# Append any configs entered in manually to the config file.
31628d1491baSSteven Rostedtmy @new_configs = keys %entered_configs;
31638d1491baSSteven Rostedtif ($#new_configs >= 0) {
31648d1491baSSteven Rostedt    print "\nAppending entered in configs to $ktest_config\n";
31658d1491baSSteven Rostedt    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
31668d1491baSSteven Rostedt    foreach my $config (@new_configs) {
31678d1491baSSteven Rostedt	print OUT "$config = $entered_configs{$config}\n";
31680e7a22deSSteven Rostedt	$opt{$config} = process_variables($entered_configs{$config});
31698d1491baSSteven Rostedt    }
31708d1491baSSteven Rostedt}
31712545eb61SSteven Rostedt
31722b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
31732b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
31742b7d9b21SSteven Rostedt}
31752545eb61SSteven Rostedt
31762b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
31772b7d9b21SSteven Rostedt
3178a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
3179a57419b3SSteven Rostedt
3180a57419b3SSteven Rostedt    if (!$i) {
3181a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
3182a57419b3SSteven Rostedt    } else {
3183a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
3184a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
3185a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
3186a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
3187a57419b3SSteven Rostedt	}
3188a57419b3SSteven Rostedt	doprint "\n";
3189a57419b3SSteven Rostedt    }
3190a57419b3SSteven Rostedt
31912b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
3192a57419b3SSteven Rostedt
3193a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
3194a57419b3SSteven Rostedt	    next if ($i != $1);
3195a57419b3SSteven Rostedt	} else {
3196a57419b3SSteven Rostedt	    next if ($i);
3197a57419b3SSteven Rostedt	}
3198a57419b3SSteven Rostedt
31992b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
32002b7d9b21SSteven Rostedt    }
3201a57419b3SSteven Rostedt}
32022545eb61SSteven Rostedt
32032a62512bSSteven Rostedtsub __set_test_option {
32045a391fbfSSteven Rostedt    my ($name, $i) = @_;
32055a391fbfSSteven Rostedt
32065a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
32075a391fbfSSteven Rostedt
32085a391fbfSSteven Rostedt    if (defined($opt{$option})) {
32095a391fbfSSteven Rostedt	return $opt{$option};
32105a391fbfSSteven Rostedt    }
32115a391fbfSSteven Rostedt
3212a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
3213a57419b3SSteven Rostedt	if ($i >= $test &&
3214a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
3215a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
3216a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
3217a57419b3SSteven Rostedt		return $opt{$option};
3218a57419b3SSteven Rostedt	    }
3219a57419b3SSteven Rostedt	}
3220a57419b3SSteven Rostedt    }
3221a57419b3SSteven Rostedt
32225a391fbfSSteven Rostedt    if (defined($opt{$name})) {
32235a391fbfSSteven Rostedt	return $opt{$name};
32245a391fbfSSteven Rostedt    }
32255a391fbfSSteven Rostedt
32265a391fbfSSteven Rostedt    return undef;
32275a391fbfSSteven Rostedt}
32285a391fbfSSteven Rostedt
32292a62512bSSteven Rostedtsub set_test_option {
32302a62512bSSteven Rostedt    my ($name, $i) = @_;
32312a62512bSSteven Rostedt
32322a62512bSSteven Rostedt    my $option = __set_test_option($name, $i);
32332a62512bSSteven Rostedt    return $option if (!defined($option));
32342a62512bSSteven Rostedt
323523715c3cSSteven Rostedt    return eval_option($option, $i);
32362a62512bSSteven Rostedt}
32372a62512bSSteven Rostedt
32382545eb61SSteven Rostedt# First we need to do is the builds
3239a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
32402545eb61SSteven Rostedt
32414ab1cce5SSteven Rostedt    # Do not reboot on failing test options
32424ab1cce5SSteven Rostedt    $no_reboot = 1;
32434ab1cce5SSteven Rostedt
3244576f627cSSteven Rostedt    $iteration = $i;
3245576f627cSSteven Rostedt
3246a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
3247a75fececSSteven Rostedt
3248a75fececSSteven Rostedt    $machine = set_test_option("MACHINE", $i);
3249e48c5293SSteven Rostedt    $ssh_user = set_test_option("SSH_USER", $i);
3250a75fececSSteven Rostedt    $tmpdir = set_test_option("TMP_DIR", $i);
3251a75fececSSteven Rostedt    $outputdir = set_test_option("OUTPUT_DIR", $i);
3252a75fececSSteven Rostedt    $builddir = set_test_option("BUILD_DIR", $i);
3253a75fececSSteven Rostedt    $test_type = set_test_option("TEST_TYPE", $i);
3254a75fececSSteven Rostedt    $build_type = set_test_option("BUILD_TYPE", $i);
3255a75fececSSteven Rostedt    $build_options = set_test_option("BUILD_OPTIONS", $i);
32560bd6c1a3SSteven Rostedt    $pre_build = set_test_option("PRE_BUILD", $i);
32570bd6c1a3SSteven Rostedt    $post_build = set_test_option("POST_BUILD", $i);
32580bd6c1a3SSteven Rostedt    $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
32590bd6c1a3SSteven Rostedt    $post_build_die = set_test_option("POST_BUILD_DIE", $i);
3260a75fececSSteven Rostedt    $power_cycle = set_test_option("POWER_CYCLE", $i);
3261e48c5293SSteven Rostedt    $reboot = set_test_option("REBOOT", $i);
3262a75fececSSteven Rostedt    $noclean = set_test_option("BUILD_NOCLEAN", $i);
3263a75fececSSteven Rostedt    $minconfig = set_test_option("MIN_CONFIG", $i);
32644c4ab120SSteven Rostedt    $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i);
32654c4ab120SSteven Rostedt    $start_minconfig = set_test_option("START_MIN_CONFIG", $i);
32664c4ab120SSteven Rostedt    $ignore_config = set_test_option("IGNORE_CONFIG", $i);
3267a75fececSSteven Rostedt    $run_test = set_test_option("TEST", $i);
3268a75fececSSteven Rostedt    $addconfig = set_test_option("ADD_CONFIG", $i);
3269a75fececSSteven Rostedt    $reboot_type = set_test_option("REBOOT_TYPE", $i);
3270a75fececSSteven Rostedt    $grub_menu = set_test_option("GRUB_MENU", $i);
32718b37ca8cSSteven Rostedt    $post_install = set_test_option("POST_INSTALL", $i);
3272e0a8742eSSteven Rostedt    $no_install = set_test_option("NO_INSTALL", $i);
3273a75fececSSteven Rostedt    $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
3274a75fececSSteven Rostedt    $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
3275a75fececSSteven Rostedt    $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
3276a75fececSSteven Rostedt    $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
3277a75fececSSteven Rostedt    $power_off = set_test_option("POWER_OFF", $i);
3278576f627cSSteven Rostedt    $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
3279576f627cSSteven Rostedt    $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
3280a75fececSSteven Rostedt    $sleep_time = set_test_option("SLEEP_TIME", $i);
3281a75fececSSteven Rostedt    $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
328227d934b2SSteven Rostedt    $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
32831990207dSSteven Rostedt    $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
3284c960bb9fSSteven Rostedt    $bisect_manual = set_test_option("BISECT_MANUAL", $i);
3285c23dca7cSSteven Rostedt    $bisect_skip = set_test_option("BISECT_SKIP", $i);
328630f75da5SSteven Rostedt    $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
3287a75fececSSteven Rostedt    $store_failures = set_test_option("STORE_FAILURES", $i);
3288de5b6e3bSRabin Vincent    $store_successes = set_test_option("STORE_SUCCESSES", $i);
32899064af52SSteven Rostedt    $test_name = set_test_option("TEST_NAME", $i);
3290a75fececSSteven Rostedt    $timeout = set_test_option("TIMEOUT", $i);
3291a75fececSSteven Rostedt    $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
3292a75fececSSteven Rostedt    $console = set_test_option("CONSOLE", $i);
3293f1a5b962SSteven Rostedt    $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
3294a75fececSSteven Rostedt    $success_line = set_test_option("SUCCESS_LINE", $i);
32952b803365SSteven Rostedt    $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i);
32961c8a617aSSteven Rostedt    $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
32971c8a617aSSteven Rostedt    $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
32982d01b26aSSteven Rostedt    $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
3299a75fececSSteven Rostedt    $build_target = set_test_option("BUILD_TARGET", $i);
3300e48c5293SSteven Rostedt    $ssh_exec = set_test_option("SSH_EXEC", $i);
3301e48c5293SSteven Rostedt    $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
3302a75fececSSteven Rostedt    $target_image = set_test_option("TARGET_IMAGE", $i);
3303a75fececSSteven Rostedt    $localversion = set_test_option("LOCALVERSION", $i);
3304a75fececSSteven Rostedt
330535ce5952SSteven Rostedt    $start_minconfig_defined = 1;
330635ce5952SSteven Rostedt
33074c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
330835ce5952SSteven Rostedt	$start_minconfig_defined = 0;
33094c4ab120SSteven Rostedt	$start_minconfig = $minconfig;
33104c4ab120SSteven Rostedt    }
33114c4ab120SSteven Rostedt
3312a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
3313a75fececSSteven Rostedt
3314a908a665SAndrew Jones    foreach my $dir ($tmpdir, $outputdir) {
3315a908a665SAndrew Jones	if (!-d $dir) {
3316a908a665SAndrew Jones	    mkpath($dir) or
3317a908a665SAndrew Jones		die "can't create $dir";
3318a908a665SAndrew Jones	}
3319a75fececSSteven Rostedt    }
3320a75fececSSteven Rostedt
3321e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
3322e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
3323e48c5293SSteven Rostedt
3324a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
3325a9dd5d63SRabin Vincent    $testlog = "$tmpdir/testlog-$machine";
3326a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
3327a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
332851ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
3329a75fececSSteven Rostedt
3330bb8474b1SSteven Rostedt    if (!$buildonly) {
3331bb8474b1SSteven Rostedt	$target = "$ssh_user\@$machine";
3332a75fececSSteven Rostedt	if ($reboot_type eq "grub") {
3333576f627cSSteven Rostedt	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3334a75fececSSteven Rostedt	} elsif (!defined($reboot_script)) {
3335576f627cSSteven Rostedt	    dodie "REBOOT_SCRIPT not defined"
3336a75fececSSteven Rostedt	}
3337bb8474b1SSteven Rostedt    }
3338a75fececSSteven Rostedt
3339a75fececSSteven Rostedt    my $run_type = $build_type;
3340a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
3341a75fececSSteven Rostedt	$run_type = $opt{"PATCHCHECK_TYPE[$i]"};
3342a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
3343a75fececSSteven Rostedt	$run_type = $opt{"BISECT_TYPE[$i]"};
33440a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
33450a05c769SSteven Rostedt	$run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
3346a75fececSSteven Rostedt    }
3347a75fececSSteven Rostedt
33484c4ab120SSteven Rostedt    if ($test_type eq "make_min_config") {
33494c4ab120SSteven Rostedt	$run_type = "";
33504c4ab120SSteven Rostedt    }
33514c4ab120SSteven Rostedt
3352a75fececSSteven Rostedt    # mistake in config file?
3353a75fececSSteven Rostedt    if (!defined($run_type)) {
3354a75fececSSteven Rostedt	$run_type = "ERROR";
3355a75fececSSteven Rostedt    }
33562545eb61SSteven Rostedt
3357e0a8742eSSteven Rostedt    my $installme = "";
3358e0a8742eSSteven Rostedt    $installme = " no_install" if ($no_install);
3359e0a8742eSSteven Rostedt
33602545eb61SSteven Rostedt    doprint "\n\n";
3361e0a8742eSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
33627faafbd6SSteven Rostedt
33637faafbd6SSteven Rostedt    unlink $dmesg;
33647faafbd6SSteven Rostedt    unlink $buildlog;
3365a9dd5d63SRabin Vincent    unlink $testlog;
33662545eb61SSteven Rostedt
3367250bae8bSSteven Rostedt    if (defined($addconfig)) {
3368250bae8bSSteven Rostedt	my $min = $minconfig;
33692b7d9b21SSteven Rostedt	if (!defined($minconfig)) {
3370250bae8bSSteven Rostedt	    $min = "";
3371250bae8bSSteven Rostedt	}
3372250bae8bSSteven Rostedt	run_command "cat $addconfig $min > $tmpdir/add_config" or
33732b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
33749be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
33752b7d9b21SSteven Rostedt    }
33762b7d9b21SSteven Rostedt
33776c5ee0beSSteven Rostedt    my $checkout = $opt{"CHECKOUT[$i]"};
33786c5ee0beSSteven Rostedt    if (defined($checkout)) {
33796c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
33806c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
33816c5ee0beSSteven Rostedt    }
33826c5ee0beSSteven Rostedt
33834ab1cce5SSteven Rostedt    $no_reboot = 0;
33844ab1cce5SSteven Rostedt
33854ab1cce5SSteven Rostedt
3386a75fececSSteven Rostedt    if ($test_type eq "bisect") {
33875f9b6cedSSteven Rostedt	bisect $i;
33885f9b6cedSSteven Rostedt	next;
33890a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
33900a05c769SSteven Rostedt	config_bisect $i;
33910a05c769SSteven Rostedt	next;
3392a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
33936c5ee0beSSteven Rostedt	patchcheck $i;
33946c5ee0beSSteven Rostedt	next;
33954c4ab120SSteven Rostedt    } elsif ($test_type eq "make_min_config") {
33964c4ab120SSteven Rostedt	make_min_config $i;
33974c4ab120SSteven Rostedt	next;
33985f9b6cedSSteven Rostedt    }
33995f9b6cedSSteven Rostedt
34007faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
34017faafbd6SSteven Rostedt	build $build_type or next;
34022545eb61SSteven Rostedt    }
34032545eb61SSteven Rostedt
3404cd8e368fSSteven Rostedt    if ($test_type eq "install") {
3405cd8e368fSSteven Rostedt	get_version;
3406cd8e368fSSteven Rostedt	install;
3407cd8e368fSSteven Rostedt	success $i;
3408cd8e368fSSteven Rostedt	next;
3409cd8e368fSSteven Rostedt    }
3410cd8e368fSSteven Rostedt
3411a75fececSSteven Rostedt    if ($test_type ne "build") {
34127faafbd6SSteven Rostedt	my $failed = 0;
3413ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
3414a75fececSSteven Rostedt
3415a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
34167faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
34175a391fbfSSteven Rostedt	}
34187faafbd6SSteven Rostedt	end_monitor;
34197faafbd6SSteven Rostedt	next if ($failed);
3420a75fececSSteven Rostedt    }
34215a391fbfSSteven Rostedt
34225f9b6cedSSteven Rostedt    success $i;
342375c3fda7SSteven Rostedt}
34242545eb61SSteven Rostedt
34255c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
342675c3fda7SSteven Rostedt    halt;
3427576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
342875c3fda7SSteven Rostedt    reboot;
34295c42fc5bSSteven Rostedt}
343075c3fda7SSteven Rostedt
3431e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
3432e48c5293SSteven Rostedt
34332545eb61SSteven Rostedtexit 0;
3434