xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision 165708b273f87ac52a4564b114a6c046e6b3a02d)
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
139*165708b2SSteven 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) {
346*165708b2SSteven Rostedt	get_ktest_config("POWER_CYCLE");
347*165708b2SSteven Rostedt	get_ktest_config("CONSOLE");
348*165708b2SSteven Rostedt    }
349*165708b2SSteven Rostedt
350*165708b2SSteven Rostedt    # options required for install and more
351*165708b2SSteven 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*165708b2SSteven Rostedt    if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $rvalue ne "build") {
420bb8474b1SSteven Rostedt	# Note if a test is something other than build, then we
421bb8474b1SSteven Rostedt	# will need other manditory options.
422*165708b2SSteven Rostedt	if ($rvalue ne "install") {
423bb8474b1SSteven Rostedt	    $buildonly = 0;
424*165708b2SSteven Rostedt	} else {
425*165708b2SSteven Rostedt	    # install still limits some manditory options.
426*165708b2SSteven Rostedt	    $buildonly = 2;
427*165708b2SSteven Rostedt	}
428bb8474b1SSteven Rostedt    }
429bb8474b1SSteven Rostedt
430a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
4313d1cc414SSteven Rostedt	if (!$override || defined(${$overrides}{$lvalue})) {
4323d1cc414SSteven Rostedt	    my $extra = "";
4333d1cc414SSteven Rostedt	    if ($override) {
4343d1cc414SSteven Rostedt		$extra = "In the same override section!\n";
4353d1cc414SSteven Rostedt	    }
4363d1cc414SSteven Rostedt	    die "$name: $.: Option $lvalue defined more than once!\n$extra";
4373d1cc414SSteven Rostedt	}
4383d1cc414SSteven Rostedt	${$overrides}{$lvalue} = $rvalue;
439a75fececSSteven Rostedt    }
44021a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
44121a9679fSSteven Rostedt	delete $opt{$lvalue};
44221a9679fSSteven Rostedt    } else {
44377d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
44421a9679fSSteven Rostedt	$opt{$lvalue} = $rvalue;
44521a9679fSSteven Rostedt    }
4462545eb61SSteven Rostedt}
447a57419b3SSteven Rostedt
44877d942ceSSteven Rostedtsub set_variable {
44977d942ceSSteven Rostedt    my ($lvalue, $rvalue) = @_;
45077d942ceSSteven Rostedt
45177d942ceSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
45277d942ceSSteven Rostedt	delete $variable{$lvalue};
45377d942ceSSteven Rostedt    } else {
45477d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
45577d942ceSSteven Rostedt	$variable{$lvalue} = $rvalue;
45677d942ceSSteven Rostedt    }
45777d942ceSSteven Rostedt}
45877d942ceSSteven Rostedt
459ab7a3f52SSteven Rostedtsub process_compare {
460ab7a3f52SSteven Rostedt    my ($lval, $cmp, $rval) = @_;
461ab7a3f52SSteven Rostedt
462ab7a3f52SSteven Rostedt    # remove whitespace
463ab7a3f52SSteven Rostedt
464ab7a3f52SSteven Rostedt    $lval =~ s/^\s*//;
465ab7a3f52SSteven Rostedt    $lval =~ s/\s*$//;
466ab7a3f52SSteven Rostedt
467ab7a3f52SSteven Rostedt    $rval =~ s/^\s*//;
468ab7a3f52SSteven Rostedt    $rval =~ s/\s*$//;
469ab7a3f52SSteven Rostedt
470ab7a3f52SSteven Rostedt    if ($cmp eq "==") {
471ab7a3f52SSteven Rostedt	return $lval eq $rval;
472ab7a3f52SSteven Rostedt    } elsif ($cmp eq "!=") {
473ab7a3f52SSteven Rostedt	return $lval ne $rval;
474ab7a3f52SSteven Rostedt    }
475ab7a3f52SSteven Rostedt
476ab7a3f52SSteven Rostedt    my $statement = "$lval $cmp $rval";
477ab7a3f52SSteven Rostedt    my $ret = eval $statement;
478ab7a3f52SSteven Rostedt
479ab7a3f52SSteven Rostedt    # $@ stores error of eval
480ab7a3f52SSteven Rostedt    if ($@) {
481ab7a3f52SSteven Rostedt	return -1;
482ab7a3f52SSteven Rostedt    }
483ab7a3f52SSteven Rostedt
484ab7a3f52SSteven Rostedt    return $ret;
485ab7a3f52SSteven Rostedt}
486ab7a3f52SSteven Rostedt
4879900b5dcSSteven Rostedtsub value_defined {
4889900b5dcSSteven Rostedt    my ($val) = @_;
4899900b5dcSSteven Rostedt
4909900b5dcSSteven Rostedt    return defined($variable{$2}) ||
4919900b5dcSSteven Rostedt	defined($opt{$2});
4929900b5dcSSteven Rostedt}
4939900b5dcSSteven Rostedt
4948d735212SSteven Rostedtmy $d = 0;
4958d735212SSteven Rostedtsub process_expression {
4968d735212SSteven Rostedt    my ($name, $val) = @_;
49745d73a5dSSteven Rostedt
4988d735212SSteven Rostedt    my $c = $d++;
4998d735212SSteven Rostedt
5008d735212SSteven Rostedt    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
5018d735212SSteven Rostedt	my $express = $1;
5028d735212SSteven Rostedt
5038d735212SSteven Rostedt	if (process_expression($name, $express)) {
5048d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
5058d735212SSteven Rostedt	} else {
5068d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
5078d735212SSteven Rostedt	}
5088d735212SSteven Rostedt    }
5098d735212SSteven Rostedt
5108d735212SSteven Rostedt    $d--;
5118d735212SSteven Rostedt    my $OR = "\\|\\|";
5128d735212SSteven Rostedt    my $AND = "\\&\\&";
5138d735212SSteven Rostedt
5148d735212SSteven Rostedt    while ($val =~ s/^(.*?)($OR|$AND)//) {
5158d735212SSteven Rostedt	my $express = $1;
5168d735212SSteven Rostedt	my $op = $2;
5178d735212SSteven Rostedt
5188d735212SSteven Rostedt	if (process_expression($name, $express)) {
5198d735212SSteven Rostedt	    if ($op eq "||") {
5208d735212SSteven Rostedt		return 1;
5218d735212SSteven Rostedt	    }
5228d735212SSteven Rostedt	} else {
5238d735212SSteven Rostedt	    if ($op eq "&&") {
5248d735212SSteven Rostedt		return 0;
5258d735212SSteven Rostedt	    }
5268d735212SSteven Rostedt	}
5278d735212SSteven Rostedt    }
52845d73a5dSSteven Rostedt
529ab7a3f52SSteven Rostedt    if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) {
530ab7a3f52SSteven Rostedt	my $ret = process_compare($1, $2, $3);
531ab7a3f52SSteven Rostedt	if ($ret < 0) {
532ab7a3f52SSteven Rostedt	    die "$name: $.: Unable to process comparison\n";
533ab7a3f52SSteven Rostedt	}
534ab7a3f52SSteven Rostedt	return $ret;
535ab7a3f52SSteven Rostedt    }
536ab7a3f52SSteven Rostedt
5379900b5dcSSteven Rostedt    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
5389900b5dcSSteven Rostedt	if (defined $1) {
5399900b5dcSSteven Rostedt	    return !value_defined($2);
5409900b5dcSSteven Rostedt	} else {
5419900b5dcSSteven Rostedt	    return value_defined($2);
5429900b5dcSSteven Rostedt	}
5439900b5dcSSteven Rostedt    }
5449900b5dcSSteven Rostedt
54545d73a5dSSteven Rostedt    if ($val =~ /^\s*0\s*$/) {
54645d73a5dSSteven Rostedt	return 0;
54745d73a5dSSteven Rostedt    } elsif ($val =~ /^\s*\d+\s*$/) {
54845d73a5dSSteven Rostedt	return 1;
54945d73a5dSSteven Rostedt    }
55045d73a5dSSteven Rostedt
5519900b5dcSSteven Rostedt    die ("$name: $.: Undefined content $val in if statement\n");
5528d735212SSteven Rostedt}
5538d735212SSteven Rostedt
5548d735212SSteven Rostedtsub process_if {
5558d735212SSteven Rostedt    my ($name, $value) = @_;
5568d735212SSteven Rostedt
5578d735212SSteven Rostedt    # Convert variables and replace undefined ones with 0
5588d735212SSteven Rostedt    my $val = process_variables($value, 1);
5598d735212SSteven Rostedt    my $ret = process_expression $name, $val;
5608d735212SSteven Rostedt
5618d735212SSteven Rostedt    return $ret;
56245d73a5dSSteven Rostedt}
56345d73a5dSSteven Rostedt
5642ed3b161SSteven Rostedtsub __read_config {
5652ed3b161SSteven Rostedt    my ($config, $current_test_num) = @_;
566a57419b3SSteven Rostedt
5672ed3b161SSteven Rostedt    my $in;
5682ed3b161SSteven Rostedt    open($in, $config) || die "can't read file $config";
569a57419b3SSteven Rostedt
570a57419b3SSteven Rostedt    my $name = $config;
571a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
572a57419b3SSteven Rostedt
5732ed3b161SSteven Rostedt    my $test_num = $$current_test_num;
574a57419b3SSteven Rostedt    my $default = 1;
575a57419b3SSteven Rostedt    my $repeat = 1;
576a57419b3SSteven Rostedt    my $num_tests_set = 0;
577a57419b3SSteven Rostedt    my $skip = 0;
578a57419b3SSteven Rostedt    my $rest;
579a9f84424SSteven Rostedt    my $line;
5800df213caSSteven Rostedt    my $test_case = 0;
58145d73a5dSSteven Rostedt    my $if = 0;
58245d73a5dSSteven Rostedt    my $if_set = 0;
5833d1cc414SSteven Rostedt    my $override = 0;
5843d1cc414SSteven Rostedt
5853d1cc414SSteven Rostedt    my %overrides;
586a57419b3SSteven Rostedt
5872ed3b161SSteven Rostedt    while (<$in>) {
588a57419b3SSteven Rostedt
589a57419b3SSteven Rostedt	# ignore blank lines and comments
590a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
591a57419b3SSteven Rostedt
5920050b6bbSSteven Rostedt	if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
593a57419b3SSteven Rostedt
5940050b6bbSSteven Rostedt	    my $type = $1;
5950050b6bbSSteven Rostedt	    $rest = $2;
596a9f84424SSteven Rostedt	    $line = $2;
5970050b6bbSSteven Rostedt
5980050b6bbSSteven Rostedt	    my $old_test_num;
5990050b6bbSSteven Rostedt	    my $old_repeat;
6003d1cc414SSteven Rostedt	    $override = 0;
6010050b6bbSSteven Rostedt
6020050b6bbSSteven Rostedt	    if ($type eq "TEST_START") {
603a57419b3SSteven Rostedt
604a57419b3SSteven Rostedt		if ($num_tests_set) {
605a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
606a57419b3SSteven Rostedt		}
607a57419b3SSteven Rostedt
6080050b6bbSSteven Rostedt		$old_test_num = $test_num;
6090050b6bbSSteven Rostedt		$old_repeat = $repeat;
610a57419b3SSteven Rostedt
611a57419b3SSteven Rostedt		$test_num += $repeat;
612a57419b3SSteven Rostedt		$default = 0;
613a57419b3SSteven Rostedt		$repeat = 1;
6140050b6bbSSteven Rostedt	    } else {
6150050b6bbSSteven Rostedt		$default = 1;
6160050b6bbSSteven Rostedt	    }
617a57419b3SSteven Rostedt
618a9f84424SSteven Rostedt	    # If SKIP is anywhere in the line, the command will be skipped
619a9f84424SSteven Rostedt	    if ($rest =~ s/\s+SKIP\b//) {
620a57419b3SSteven Rostedt		$skip = 1;
621a57419b3SSteven Rostedt	    } else {
6220df213caSSteven Rostedt		$test_case = 1;
623a57419b3SSteven Rostedt		$skip = 0;
624a57419b3SSteven Rostedt	    }
625a57419b3SSteven Rostedt
626a9f84424SSteven Rostedt	    if ($rest =~ s/\sELSE\b//) {
627a9f84424SSteven Rostedt		if (!$if) {
628a9f84424SSteven Rostedt		    die "$name: $.: ELSE found with out matching IF section\n$_";
629a57419b3SSteven Rostedt		}
630a9f84424SSteven Rostedt		$if = 0;
631a9f84424SSteven Rostedt
632a9f84424SSteven Rostedt		if ($if_set) {
633a9f84424SSteven Rostedt		    $skip = 1;
634a9f84424SSteven Rostedt		} else {
635a9f84424SSteven Rostedt		    $skip = 0;
6363d1cc414SSteven Rostedt		}
6373d1cc414SSteven Rostedt	    }
638a57419b3SSteven Rostedt
639a9f84424SSteven Rostedt	    if ($rest =~ s/\sIF\s+(.*)//) {
64045d73a5dSSteven Rostedt		if (process_if($name, $1)) {
64145d73a5dSSteven Rostedt		    $if_set = 1;
64245d73a5dSSteven Rostedt		} else {
643a57419b3SSteven Rostedt		    $skip = 1;
644a57419b3SSteven Rostedt		}
64545d73a5dSSteven Rostedt		$if = 1;
64645d73a5dSSteven Rostedt	    } else {
64745d73a5dSSteven Rostedt		$if = 0;
648a9f84424SSteven Rostedt		$if_set = 0;
64945d73a5dSSteven Rostedt	    }
650a57419b3SSteven Rostedt
651a9f84424SSteven Rostedt	    if (!$skip) {
652a9f84424SSteven Rostedt		if ($type eq "TEST_START") {
653a9f84424SSteven Rostedt		    if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
654a9f84424SSteven Rostedt			$repeat = $1;
655a9f84424SSteven Rostedt			$repeat_tests{"$test_num"} = $repeat;
656a9f84424SSteven Rostedt		    }
657a9f84424SSteven Rostedt		} elsif ($rest =~ s/\sOVERRIDE\b//) {
658a9f84424SSteven Rostedt		    # DEFAULT only
659a9f84424SSteven Rostedt		    $override = 1;
660a9f84424SSteven Rostedt		    # Clear previous overrides
661a9f84424SSteven Rostedt		    %overrides = ();
662a9f84424SSteven Rostedt		}
663a9f84424SSteven Rostedt	    }
664a9f84424SSteven Rostedt
665a9f84424SSteven Rostedt	    if (!$skip && $rest !~ /^\s*$/) {
6660050b6bbSSteven Rostedt		die "$name: $.: Gargbage found after $type\n$_";
667a57419b3SSteven Rostedt	    }
668a57419b3SSteven Rostedt
6690050b6bbSSteven Rostedt	    if ($skip && $type eq "TEST_START") {
670a57419b3SSteven Rostedt		$test_num = $old_test_num;
671e48c5293SSteven Rostedt		$repeat = $old_repeat;
672a57419b3SSteven Rostedt	    }
673a57419b3SSteven Rostedt
674ab7a3f52SSteven Rostedt	} elsif (/^\s*ELSE\b(.*)$/) {
67545d73a5dSSteven Rostedt	    if (!$if) {
67645d73a5dSSteven Rostedt		die "$name: $.: ELSE found with out matching IF section\n$_";
67745d73a5dSSteven Rostedt	    }
67845d73a5dSSteven Rostedt	    $rest = $1;
67945d73a5dSSteven Rostedt	    if ($if_set) {
68045d73a5dSSteven Rostedt		$skip = 1;
681ab7a3f52SSteven Rostedt		$rest = "";
68245d73a5dSSteven Rostedt	    } else {
68345d73a5dSSteven Rostedt		$skip = 0;
68445d73a5dSSteven Rostedt
685ab7a3f52SSteven Rostedt		if ($rest =~ /\sIF\s+(.*)/) {
68645d73a5dSSteven Rostedt		    # May be a ELSE IF section.
68745d73a5dSSteven Rostedt		    if (!process_if($name, $1)) {
68845d73a5dSSteven Rostedt			$skip = 1;
68945d73a5dSSteven Rostedt		    }
690ab7a3f52SSteven Rostedt		    $rest = "";
69145d73a5dSSteven Rostedt		} else {
69245d73a5dSSteven Rostedt		    $if = 0;
69345d73a5dSSteven Rostedt		}
69445d73a5dSSteven Rostedt	    }
69545d73a5dSSteven Rostedt
696ab7a3f52SSteven Rostedt	    if ($rest !~ /^\s*$/) {
697ab7a3f52SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
698ab7a3f52SSteven Rostedt	    }
699ab7a3f52SSteven Rostedt
7002ed3b161SSteven Rostedt	} elsif (/^\s*INCLUDE\s+(\S+)/) {
7012ed3b161SSteven Rostedt
7022ed3b161SSteven Rostedt	    next if ($skip);
7032ed3b161SSteven Rostedt
7042ed3b161SSteven Rostedt	    if (!$default) {
7052ed3b161SSteven Rostedt		die "$name: $.: INCLUDE can only be done in default sections\n$_";
7062ed3b161SSteven Rostedt	    }
7072ed3b161SSteven Rostedt
7082ed3b161SSteven Rostedt	    my $file = process_variables($1);
7092ed3b161SSteven Rostedt
7102ed3b161SSteven Rostedt	    if ($file !~ m,^/,) {
7112ed3b161SSteven Rostedt		# check the path of the config file first
7122ed3b161SSteven Rostedt		if ($config =~ m,(.*)/,) {
7132ed3b161SSteven Rostedt		    if (-f "$1/$file") {
7142ed3b161SSteven Rostedt			$file = "$1/$file";
7152ed3b161SSteven Rostedt		    }
7162ed3b161SSteven Rostedt		}
7172ed3b161SSteven Rostedt	    }
7182ed3b161SSteven Rostedt
7192ed3b161SSteven Rostedt	    if ( ! -r $file ) {
7202ed3b161SSteven Rostedt		die "$name: $.: Can't read file $file\n$_";
7212ed3b161SSteven Rostedt	    }
7222ed3b161SSteven Rostedt
7232ed3b161SSteven Rostedt	    if (__read_config($file, \$test_num)) {
7242ed3b161SSteven Rostedt		$test_case = 1;
7252ed3b161SSteven Rostedt	    }
7262ed3b161SSteven Rostedt
727a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
728a57419b3SSteven Rostedt
729a57419b3SSteven Rostedt	    next if ($skip);
730a57419b3SSteven Rostedt
731a57419b3SSteven Rostedt	    my $lvalue = $1;
732a57419b3SSteven Rostedt	    my $rvalue = $2;
733a57419b3SSteven Rostedt
734a57419b3SSteven Rostedt	    if (!$default &&
735a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
736a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
737a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
738a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
739a57419b3SSteven Rostedt	    }
740a57419b3SSteven Rostedt
741a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
742a57419b3SSteven Rostedt		if ($test_num) {
743a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
744a57419b3SSteven Rostedt		}
745a57419b3SSteven Rostedt		if (!$default) {
746a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
747a57419b3SSteven Rostedt		}
748a57419b3SSteven Rostedt		$num_tests_set = 1;
749a57419b3SSteven Rostedt	    }
750a57419b3SSteven Rostedt
751a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
7523d1cc414SSteven Rostedt		set_value($lvalue, $rvalue, $override, \%overrides, $name);
753a57419b3SSteven Rostedt	    } else {
754a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
7553d1cc414SSteven Rostedt		set_value($val, $rvalue, $override, \%overrides, $name);
756a57419b3SSteven Rostedt
757a57419b3SSteven Rostedt		if ($repeat > 1) {
758a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
759a57419b3SSteven Rostedt		}
760a57419b3SSteven Rostedt	    }
76177d942ceSSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
76277d942ceSSteven Rostedt	    next if ($skip);
76377d942ceSSteven Rostedt
76477d942ceSSteven Rostedt	    my $lvalue = $1;
76577d942ceSSteven Rostedt	    my $rvalue = $2;
76677d942ceSSteven Rostedt
76777d942ceSSteven Rostedt	    # process config variables.
76877d942ceSSteven Rostedt	    # Config variables are only active while reading the
76977d942ceSSteven Rostedt	    # config and can be defined anywhere. They also ignore
77077d942ceSSteven Rostedt	    # TEST_START and DEFAULTS, but are skipped if they are in
77177d942ceSSteven Rostedt	    # on of these sections that have SKIP defined.
77277d942ceSSteven Rostedt	    # The save variable can be
77377d942ceSSteven Rostedt	    # defined multiple times and the new one simply overrides
77477d942ceSSteven Rostedt	    # the prevous one.
77577d942ceSSteven Rostedt	    set_variable($lvalue, $rvalue);
77677d942ceSSteven Rostedt
777a57419b3SSteven Rostedt	} else {
778a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
779a57419b3SSteven Rostedt	}
7802545eb61SSteven Rostedt    }
7812545eb61SSteven Rostedt
782a57419b3SSteven Rostedt    if ($test_num) {
783a57419b3SSteven Rostedt	$test_num += $repeat - 1;
784a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
785a57419b3SSteven Rostedt    }
786a57419b3SSteven Rostedt
7872ed3b161SSteven Rostedt    close($in);
7882ed3b161SSteven Rostedt
7892ed3b161SSteven Rostedt    $$current_test_num = $test_num;
7902ed3b161SSteven Rostedt
7912ed3b161SSteven Rostedt    return $test_case;
7922ed3b161SSteven Rostedt}
7932ed3b161SSteven Rostedt
794c4261d0fSSteven Rostedtsub get_test_case {
795c4261d0fSSteven Rostedt	print "What test case would you like to run?\n";
796c4261d0fSSteven Rostedt	print " (build, install or boot)\n";
797c4261d0fSSteven Rostedt	print " Other tests are available but require editing the config file\n";
798c4261d0fSSteven Rostedt	my $ans = <STDIN>;
799c4261d0fSSteven Rostedt	chomp $ans;
800c4261d0fSSteven Rostedt	$default{"TEST_TYPE"} = $ans;
801c4261d0fSSteven Rostedt}
802c4261d0fSSteven Rostedt
8032ed3b161SSteven Rostedtsub read_config {
8042ed3b161SSteven Rostedt    my ($config) = @_;
8052ed3b161SSteven Rostedt
8062ed3b161SSteven Rostedt    my $test_case;
8072ed3b161SSteven Rostedt    my $test_num = 0;
8082ed3b161SSteven Rostedt
8092ed3b161SSteven Rostedt    $test_case = __read_config $config, \$test_num;
8102ed3b161SSteven Rostedt
8118d1491baSSteven Rostedt    # make sure we have all mandatory configs
8128d1491baSSteven Rostedt    get_ktest_configs;
8138d1491baSSteven Rostedt
8140df213caSSteven Rostedt    # was a test specified?
8150df213caSSteven Rostedt    if (!$test_case) {
8160df213caSSteven Rostedt	print "No test case specified.\n";
817c4261d0fSSteven Rostedt	get_test_case;
8180df213caSSteven Rostedt    }
8190df213caSSteven Rostedt
820a75fececSSteven Rostedt    # set any defaults
821a75fececSSteven Rostedt
822a75fececSSteven Rostedt    foreach my $default (keys %default) {
823a75fececSSteven Rostedt	if (!defined($opt{$default})) {
824a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
825a75fececSSteven Rostedt	}
826a75fececSSteven Rostedt    }
8272545eb61SSteven Rostedt}
8282545eb61SSteven Rostedt
82923715c3cSSteven Rostedtsub __eval_option {
83023715c3cSSteven Rostedt    my ($option, $i) = @_;
83123715c3cSSteven Rostedt
83223715c3cSSteven Rostedt    # Add space to evaluate the character before $
83323715c3cSSteven Rostedt    $option = " $option";
83423715c3cSSteven Rostedt    my $retval = "";
835f9dfb65bSRabin Vincent    my $repeated = 0;
836f9dfb65bSRabin Vincent    my $parent = 0;
837f9dfb65bSRabin Vincent
838f9dfb65bSRabin Vincent    foreach my $test (keys %repeat_tests) {
839f9dfb65bSRabin Vincent	if ($i >= $test &&
840f9dfb65bSRabin Vincent	    $i < $test + $repeat_tests{$test}) {
841f9dfb65bSRabin Vincent
842f9dfb65bSRabin Vincent	    $repeated = 1;
843f9dfb65bSRabin Vincent	    $parent = $test;
844f9dfb65bSRabin Vincent	    last;
845f9dfb65bSRabin Vincent	}
846f9dfb65bSRabin Vincent    }
84723715c3cSSteven Rostedt
84823715c3cSSteven Rostedt    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
84923715c3cSSteven Rostedt	my $start = $1;
85023715c3cSSteven Rostedt	my $var = $2;
85123715c3cSSteven Rostedt	my $end = $3;
85223715c3cSSteven Rostedt
85323715c3cSSteven Rostedt	# Append beginning of line
85423715c3cSSteven Rostedt	$retval = "$retval$start";
85523715c3cSSteven Rostedt
85623715c3cSSteven Rostedt	# If the iteration option OPT[$i] exists, then use that.
85723715c3cSSteven Rostedt	# otherwise see if the default OPT (without [$i]) exists.
85823715c3cSSteven Rostedt
85923715c3cSSteven Rostedt	my $o = "$var\[$i\]";
860f9dfb65bSRabin Vincent	my $parento = "$var\[$parent\]";
86123715c3cSSteven Rostedt
86223715c3cSSteven Rostedt	if (defined($opt{$o})) {
86323715c3cSSteven Rostedt	    $o = $opt{$o};
86423715c3cSSteven Rostedt	    $retval = "$retval$o";
865f9dfb65bSRabin Vincent	} elsif ($repeated && defined($opt{$parento})) {
866f9dfb65bSRabin Vincent	    $o = $opt{$parento};
867f9dfb65bSRabin Vincent	    $retval = "$retval$o";
86823715c3cSSteven Rostedt	} elsif (defined($opt{$var})) {
86923715c3cSSteven Rostedt	    $o = $opt{$var};
87023715c3cSSteven Rostedt	    $retval = "$retval$o";
87123715c3cSSteven Rostedt	} else {
87223715c3cSSteven Rostedt	    $retval = "$retval\$\{$var\}";
87323715c3cSSteven Rostedt	}
87423715c3cSSteven Rostedt
87523715c3cSSteven Rostedt	$option = $end;
87623715c3cSSteven Rostedt    }
87723715c3cSSteven Rostedt
87823715c3cSSteven Rostedt    $retval = "$retval$option";
87923715c3cSSteven Rostedt
88023715c3cSSteven Rostedt    $retval =~ s/^ //;
88123715c3cSSteven Rostedt
88223715c3cSSteven Rostedt    return $retval;
88323715c3cSSteven Rostedt}
88423715c3cSSteven Rostedt
88523715c3cSSteven Rostedtsub eval_option {
88623715c3cSSteven Rostedt    my ($option, $i) = @_;
88723715c3cSSteven Rostedt
88823715c3cSSteven Rostedt    my $prev = "";
88923715c3cSSteven Rostedt
89023715c3cSSteven Rostedt    # Since an option can evaluate to another option,
89123715c3cSSteven Rostedt    # keep iterating until we do not evaluate any more
89223715c3cSSteven Rostedt    # options.
89323715c3cSSteven Rostedt    my $r = 0;
89423715c3cSSteven Rostedt    while ($prev ne $option) {
89523715c3cSSteven Rostedt	# Check for recursive evaluations.
89623715c3cSSteven Rostedt	# 100 deep should be more than enough.
89723715c3cSSteven Rostedt	if ($r++ > 100) {
89823715c3cSSteven Rostedt	    die "Over 100 evaluations accurred with $option\n" .
89923715c3cSSteven Rostedt		"Check for recursive variables\n";
90023715c3cSSteven Rostedt	}
90123715c3cSSteven Rostedt	$prev = $option;
90223715c3cSSteven Rostedt	$option = __eval_option($option, $i);
90323715c3cSSteven Rostedt    }
90423715c3cSSteven Rostedt
90523715c3cSSteven Rostedt    return $option;
90623715c3cSSteven Rostedt}
90723715c3cSSteven Rostedt
908d1e2f22aSSteven Rostedtsub _logit {
9092545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
9102545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
9112545eb61SSteven Rostedt	print OUT @_;
9122545eb61SSteven Rostedt	close(OUT);
9132545eb61SSteven Rostedt    }
9142545eb61SSteven Rostedt}
9152545eb61SSteven Rostedt
916d1e2f22aSSteven Rostedtsub logit {
917d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
918d1e2f22aSSteven Rostedt	_logit @_;
919d1e2f22aSSteven Rostedt    } else {
920d1e2f22aSSteven Rostedt	print @_;
921d1e2f22aSSteven Rostedt    }
922d1e2f22aSSteven Rostedt}
923d1e2f22aSSteven Rostedt
9245f9b6cedSSteven Rostedtsub doprint {
9255f9b6cedSSteven Rostedt    print @_;
926d1e2f22aSSteven Rostedt    _logit @_;
9275f9b6cedSSteven Rostedt}
9285f9b6cedSSteven Rostedt
9297faafbd6SSteven Rostedtsub run_command;
9302728be41SAndrew Jonessub start_monitor;
9312728be41SAndrew Jonessub end_monitor;
9322728be41SAndrew Jonessub wait_for_monitor;
9337faafbd6SSteven Rostedt
9347faafbd6SSteven Rostedtsub reboot {
9352728be41SAndrew Jones    my ($time) = @_;
9362728be41SAndrew Jones
9372b803365SSteven Rostedt    if (defined($time)) {
9382b803365SSteven Rostedt	start_monitor;
9392b803365SSteven Rostedt	# flush out current monitor
9402b803365SSteven Rostedt	# May contain the reboot success line
9412b803365SSteven Rostedt	wait_for_monitor 1;
9422b803365SSteven Rostedt    }
9432b803365SSteven Rostedt
9447faafbd6SSteven Rostedt    # try to reboot normally
945e48c5293SSteven Rostedt    if (run_command $reboot) {
946576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
947576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
948576f627cSSteven Rostedt	    run_command "$power_cycle";
949576f627cSSteven Rostedt	}
950576f627cSSteven Rostedt    } else {
9517faafbd6SSteven Rostedt	# nope? power cycle it.
952a75fececSSteven Rostedt	run_command "$power_cycle";
9537faafbd6SSteven Rostedt    }
9542728be41SAndrew Jones
9552728be41SAndrew Jones    if (defined($time)) {
9562b803365SSteven Rostedt	wait_for_monitor($time, $reboot_success_line);
9572728be41SAndrew Jones	end_monitor;
9582728be41SAndrew Jones    }
9597faafbd6SSteven Rostedt}
9607faafbd6SSteven Rostedt
961576f627cSSteven Rostedtsub do_not_reboot {
962576f627cSSteven Rostedt    my $i = $iteration;
963576f627cSSteven Rostedt
9644ab1cce5SSteven Rostedt    return $test_type eq "build" || $no_reboot ||
965576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
966576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
967576f627cSSteven Rostedt}
968576f627cSSteven Rostedt
9695c42fc5bSSteven Rostedtsub dodie {
9705a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
9715c42fc5bSSteven Rostedt
972576f627cSSteven Rostedt    my $i = $iteration;
973576f627cSSteven Rostedt
974576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
975576f627cSSteven Rostedt
97675c3fda7SSteven Rostedt	doprint "REBOOTING\n";
9777faafbd6SSteven Rostedt	reboot;
97875c3fda7SSteven Rostedt
979a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
9805c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
981a75fececSSteven Rostedt	`$power_off`;
9825c42fc5bSSteven Rostedt    }
98375c3fda7SSteven Rostedt
984f80802cbSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
985f80802cbSSteven Rostedt	print " See $opt{LOG_FILE} for more info.\n";
986f80802cbSSteven Rostedt    }
987f80802cbSSteven Rostedt
988576f627cSSteven Rostedt    die @_, "\n";
9895c42fc5bSSteven Rostedt}
9905c42fc5bSSteven Rostedt
9917faafbd6SSteven Rostedtsub open_console {
9927faafbd6SSteven Rostedt    my ($fp) = @_;
9937faafbd6SSteven Rostedt
9947faafbd6SSteven Rostedt    my $flags;
9957faafbd6SSteven Rostedt
996a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
997a75fececSSteven Rostedt	dodie "Can't open console $console";
9987faafbd6SSteven Rostedt
9997faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
1000576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
10017faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
1002576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
10037faafbd6SSteven Rostedt
10047faafbd6SSteven Rostedt    return $pid;
10057faafbd6SSteven Rostedt}
10067faafbd6SSteven Rostedt
10077faafbd6SSteven Rostedtsub close_console {
10087faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
10097faafbd6SSteven Rostedt
10107faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
10117faafbd6SSteven Rostedt    kill 2, $pid;
10127faafbd6SSteven Rostedt
10137faafbd6SSteven Rostedt    print "closing!\n";
10147faafbd6SSteven Rostedt    close($fp);
10157faafbd6SSteven Rostedt}
10167faafbd6SSteven Rostedt
10177faafbd6SSteven Rostedtsub start_monitor {
10187faafbd6SSteven Rostedt    if ($monitor_cnt++) {
10197faafbd6SSteven Rostedt	return;
10207faafbd6SSteven Rostedt    }
10217faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
10227faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
1023a75fececSSteven Rostedt
1024a75fececSSteven Rostedt    return;
1025a75fececSSteven Rostedt
1026a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
10277faafbd6SSteven Rostedt}
10287faafbd6SSteven Rostedt
10297faafbd6SSteven Rostedtsub end_monitor {
10307faafbd6SSteven Rostedt    if (--$monitor_cnt) {
10317faafbd6SSteven Rostedt	return;
10327faafbd6SSteven Rostedt    }
10337faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
10347faafbd6SSteven Rostedt}
10357faafbd6SSteven Rostedt
10367faafbd6SSteven Rostedtsub wait_for_monitor {
10372b803365SSteven Rostedt    my ($time, $stop) = @_;
10382b803365SSteven Rostedt    my $full_line = "";
10397faafbd6SSteven Rostedt    my $line;
10402b803365SSteven Rostedt    my $booted = 0;
10417faafbd6SSteven Rostedt
1042a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
10437faafbd6SSteven Rostedt
10447faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
10452b803365SSteven Rostedt    while (!$booted) {
10467faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
10472b803365SSteven Rostedt	last if (!defined($line));
10482b803365SSteven Rostedt	print "$line";
10492b803365SSteven Rostedt	$full_line .= $line;
10502b803365SSteven Rostedt
10512b803365SSteven Rostedt	if (defined($stop) && $full_line =~ /$stop/) {
10522b803365SSteven Rostedt	    doprint "wait for monitor detected $stop\n";
10532b803365SSteven Rostedt	    $booted = 1;
10542b803365SSteven Rostedt	}
10552b803365SSteven Rostedt
10562b803365SSteven Rostedt	if ($line =~ /\n/) {
10572b803365SSteven Rostedt	    $full_line = "";
10582b803365SSteven Rostedt	}
10592b803365SSteven Rostedt    }
1060a75fececSSteven Rostedt    print "** Monitor flushed **\n";
10617faafbd6SSteven Rostedt}
10627faafbd6SSteven Rostedt
1063de5b6e3bSRabin Vincentsub save_logs {
1064de5b6e3bSRabin Vincent	my ($result, $basedir) = @_;
1065de5b6e3bSRabin Vincent	my @t = localtime;
1066de5b6e3bSRabin Vincent	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1067de5b6e3bSRabin Vincent		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1068de5b6e3bSRabin Vincent
1069de5b6e3bSRabin Vincent	my $type = $build_type;
1070de5b6e3bSRabin Vincent	if ($type =~ /useconfig/) {
1071de5b6e3bSRabin Vincent	    $type = "useconfig";
1072de5b6e3bSRabin Vincent	}
1073de5b6e3bSRabin Vincent
1074de5b6e3bSRabin Vincent	my $dir = "$machine-$test_type-$type-$result-$date";
1075de5b6e3bSRabin Vincent
1076de5b6e3bSRabin Vincent	$dir = "$basedir/$dir";
1077de5b6e3bSRabin Vincent
1078de5b6e3bSRabin Vincent	if (!-d $dir) {
1079de5b6e3bSRabin Vincent	    mkpath($dir) or
1080de5b6e3bSRabin Vincent		die "can't create $dir";
1081de5b6e3bSRabin Vincent	}
1082de5b6e3bSRabin Vincent
1083de5b6e3bSRabin Vincent	my %files = (
1084de5b6e3bSRabin Vincent		"config" => $output_config,
1085de5b6e3bSRabin Vincent		"buildlog" => $buildlog,
1086de5b6e3bSRabin Vincent		"dmesg" => $dmesg,
1087de5b6e3bSRabin Vincent		"testlog" => $testlog,
1088de5b6e3bSRabin Vincent	);
1089de5b6e3bSRabin Vincent
1090de5b6e3bSRabin Vincent	while (my ($name, $source) = each(%files)) {
1091de5b6e3bSRabin Vincent		if (-f "$source") {
1092de5b6e3bSRabin Vincent			cp "$source", "$dir/$name" or
1093de5b6e3bSRabin Vincent				die "failed to copy $source";
1094de5b6e3bSRabin Vincent		}
1095de5b6e3bSRabin Vincent	}
1096de5b6e3bSRabin Vincent
1097de5b6e3bSRabin Vincent	doprint "*** Saved info to $dir ***\n";
1098de5b6e3bSRabin Vincent}
1099de5b6e3bSRabin Vincent
11002b7d9b21SSteven Rostedtsub fail {
11012b7d9b21SSteven Rostedt
1102a75fececSSteven Rostedt	if ($die_on_failure) {
11032b7d9b21SSteven Rostedt		dodie @_;
11042b7d9b21SSteven Rostedt	}
11052b7d9b21SSteven Rostedt
1106a75fececSSteven Rostedt	doprint "FAILED\n";
11077faafbd6SSteven Rostedt
1108576f627cSSteven Rostedt	my $i = $iteration;
1109576f627cSSteven Rostedt
1110a75fececSSteven Rostedt	# no need to reboot for just building.
1111576f627cSSteven Rostedt	if (!do_not_reboot) {
11127faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
11132728be41SAndrew Jones	    reboot $sleep_time;
1114a75fececSSteven Rostedt	}
11157faafbd6SSteven Rostedt
11169064af52SSteven Rostedt	my $name = "";
11179064af52SSteven Rostedt
11189064af52SSteven Rostedt	if (defined($test_name)) {
11199064af52SSteven Rostedt	    $name = " ($test_name)";
11209064af52SSteven Rostedt	}
11219064af52SSteven Rostedt
1122576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1123576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
11249064af52SSteven Rostedt	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1125576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1126576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1127a75fececSSteven Rostedt
1128de5b6e3bSRabin Vincent	if (defined($store_failures)) {
1129de5b6e3bSRabin Vincent	    save_logs "fail", $store_failures;
1130cccae1a6SSteven Rostedt        }
1131cccae1a6SSteven Rostedt
11322b7d9b21SSteven Rostedt	return 1;
11332b7d9b21SSteven Rostedt}
11342b7d9b21SSteven Rostedt
11352545eb61SSteven Rostedtsub run_command {
11362545eb61SSteven Rostedt    my ($command) = @_;
1137d6ce2a0bSSteven Rostedt    my $dolog = 0;
1138d6ce2a0bSSteven Rostedt    my $dord = 0;
1139d6ce2a0bSSteven Rostedt    my $pid;
1140d6ce2a0bSSteven Rostedt
1141e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
1142e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
1143e48c5293SSteven Rostedt
1144d6ce2a0bSSteven Rostedt    doprint("$command ... ");
1145d6ce2a0bSSteven Rostedt
1146d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
11472b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
11482545eb61SSteven Rostedt
11492545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1150d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
1151d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
1152d6ce2a0bSSteven Rostedt	$dolog = 1;
11536c5ee0beSSteven Rostedt    }
11546c5ee0beSSteven Rostedt
11556c5ee0beSSteven Rostedt    if (defined($redirect)) {
1156d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
1157d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
1158d6ce2a0bSSteven Rostedt	$dord = 1;
11592545eb61SSteven Rostedt    }
11602545eb61SSteven Rostedt
1161d6ce2a0bSSteven Rostedt    while (<CMD>) {
1162d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
1163d6ce2a0bSSteven Rostedt	print RD  if ($dord);
1164d6ce2a0bSSteven Rostedt    }
11652545eb61SSteven Rostedt
1166d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
11672545eb61SSteven Rostedt    my $failed = $?;
11682545eb61SSteven Rostedt
1169d6ce2a0bSSteven Rostedt    close(CMD);
1170d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
1171d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
1172d6ce2a0bSSteven Rostedt
11732545eb61SSteven Rostedt    if ($failed) {
11742545eb61SSteven Rostedt	doprint "FAILED!\n";
11752545eb61SSteven Rostedt    } else {
11762545eb61SSteven Rostedt	doprint "SUCCESS\n";
11772545eb61SSteven Rostedt    }
11782545eb61SSteven Rostedt
11795f9b6cedSSteven Rostedt    return !$failed;
11805f9b6cedSSteven Rostedt}
11815f9b6cedSSteven Rostedt
1182e48c5293SSteven Rostedtsub run_ssh {
1183e48c5293SSteven Rostedt    my ($cmd) = @_;
1184e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
1185e48c5293SSteven Rostedt
1186e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1187e48c5293SSteven Rostedt    return run_command "$cp_exec";
1188e48c5293SSteven Rostedt}
1189e48c5293SSteven Rostedt
1190e48c5293SSteven Rostedtsub run_scp {
1191e48c5293SSteven Rostedt    my ($src, $dst) = @_;
1192e48c5293SSteven Rostedt    my $cp_scp = $scp_to_target;
1193e48c5293SSteven Rostedt
1194e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
1195e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
1196e48c5293SSteven Rostedt
1197e48c5293SSteven Rostedt    return run_command "$cp_scp";
1198e48c5293SSteven Rostedt}
1199e48c5293SSteven Rostedt
12005f9b6cedSSteven Rostedtsub get_grub_index {
12015f9b6cedSSteven Rostedt
1202a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
1203a75fececSSteven Rostedt	return;
1204a75fececSSteven Rostedt    }
12055a391fbfSSteven Rostedt    return if (defined($grub_number));
12065f9b6cedSSteven Rostedt
12075f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
12085f9b6cedSSteven Rostedt    $grub_number = -1;
1209e48c5293SSteven Rostedt
1210e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
1211e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
1212e48c5293SSteven Rostedt
1213e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
12145f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
1215e48c5293SSteven Rostedt
1216eaa1fe25SSteven Rostedt    my $found = 0;
1217eaa1fe25SSteven Rostedt
12185f9b6cedSSteven Rostedt    while (<IN>) {
1219a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
12205f9b6cedSSteven Rostedt	    $grub_number++;
1221eaa1fe25SSteven Rostedt	    $found = 1;
12225f9b6cedSSteven Rostedt	    last;
12235f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
12245f9b6cedSSteven Rostedt	    $grub_number++;
12255f9b6cedSSteven Rostedt	}
12265f9b6cedSSteven Rostedt    }
12275f9b6cedSSteven Rostedt    close(IN);
12285f9b6cedSSteven Rostedt
1229a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
1230eaa1fe25SSteven Rostedt	if (!$found);
12315f9b6cedSSteven Rostedt    doprint "$grub_number\n";
12322545eb61SSteven Rostedt}
12332545eb61SSteven Rostedt
12342545eb61SSteven Rostedtsub wait_for_input
12352545eb61SSteven Rostedt{
12362545eb61SSteven Rostedt    my ($fp, $time) = @_;
12372545eb61SSteven Rostedt    my $rin;
12382545eb61SSteven Rostedt    my $ready;
12392545eb61SSteven Rostedt    my $line;
12402545eb61SSteven Rostedt    my $ch;
12412545eb61SSteven Rostedt
12422545eb61SSteven Rostedt    if (!defined($time)) {
12432545eb61SSteven Rostedt	$time = $timeout;
12442545eb61SSteven Rostedt    }
12452545eb61SSteven Rostedt
12462545eb61SSteven Rostedt    $rin = '';
12472545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
12482545eb61SSteven Rostedt    $ready = select($rin, undef, undef, $time);
12492545eb61SSteven Rostedt
12502545eb61SSteven Rostedt    $line = "";
12512545eb61SSteven Rostedt
12522545eb61SSteven Rostedt    # try to read one char at a time
12532545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
12542545eb61SSteven Rostedt	$line .= $ch;
12552545eb61SSteven Rostedt	last if ($ch eq "\n");
12562545eb61SSteven Rostedt    }
12572545eb61SSteven Rostedt
12582545eb61SSteven Rostedt    if (!length($line)) {
12592545eb61SSteven Rostedt	return undef;
12602545eb61SSteven Rostedt    }
12612545eb61SSteven Rostedt
12622545eb61SSteven Rostedt    return $line;
12632545eb61SSteven Rostedt}
12642545eb61SSteven Rostedt
126575c3fda7SSteven Rostedtsub reboot_to {
1266a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
1267c54367f9SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
1268c54367f9SSteven Rostedt	reboot;
1269a75fececSSteven Rostedt	return;
1270a75fececSSteven Rostedt    }
1271a75fececSSteven Rostedt
1272a75fececSSteven Rostedt    run_command "$reboot_script";
12732545eb61SSteven Rostedt}
12742545eb61SSteven Rostedt
1275a57419b3SSteven Rostedtsub get_sha1 {
1276a57419b3SSteven Rostedt    my ($commit) = @_;
1277a57419b3SSteven Rostedt
1278a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
1279a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
1280a57419b3SSteven Rostedt    my $ret = $?;
1281a57419b3SSteven Rostedt
1282a57419b3SSteven Rostedt    logit $sha1;
1283a57419b3SSteven Rostedt
1284a57419b3SSteven Rostedt    if ($ret) {
1285a57419b3SSteven Rostedt	doprint "FAILED\n";
1286a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
1287a57419b3SSteven Rostedt    }
1288a57419b3SSteven Rostedt
1289a57419b3SSteven Rostedt    print "SUCCESS\n";
1290a57419b3SSteven Rostedt
1291a57419b3SSteven Rostedt    chomp $sha1;
1292a57419b3SSteven Rostedt
1293a57419b3SSteven Rostedt    return $sha1;
1294a57419b3SSteven Rostedt}
1295a57419b3SSteven Rostedt
12965a391fbfSSteven Rostedtsub monitor {
12972545eb61SSteven Rostedt    my $booted = 0;
12982545eb61SSteven Rostedt    my $bug = 0;
12995c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
13002b7d9b21SSteven Rostedt    my $loops;
13012545eb61SSteven Rostedt
13027faafbd6SSteven Rostedt    wait_for_monitor 5;
13032545eb61SSteven Rostedt
13042545eb61SSteven Rostedt    my $line;
13052545eb61SSteven Rostedt    my $full_line = "";
13062545eb61SSteven Rostedt
13077faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
13087faafbd6SSteven Rostedt	die "unable to write to $dmesg";
13092545eb61SSteven Rostedt
131075c3fda7SSteven Rostedt    reboot_to;
13112545eb61SSteven Rostedt
13121c8a617aSSteven Rostedt    my $success_start;
13131c8a617aSSteven Rostedt    my $failure_start;
13142d01b26aSSteven Rostedt    my $monitor_start = time;
13152d01b26aSSteven Rostedt    my $done = 0;
1316f1a5b962SSteven Rostedt    my $version_found = 0;
13171c8a617aSSteven Rostedt
13182d01b26aSSteven Rostedt    while (!$done) {
13192545eb61SSteven Rostedt
1320ecaf8e52SSteven Rostedt	if ($bug && defined($stop_after_failure) &&
1321ecaf8e52SSteven Rostedt	    $stop_after_failure >= 0) {
1322ecaf8e52SSteven Rostedt	    my $time = $stop_after_failure - (time - $failure_start);
1323ecaf8e52SSteven Rostedt	    $line = wait_for_input($monitor_fp, $time);
1324ecaf8e52SSteven Rostedt	    if (!defined($line)) {
1325ecaf8e52SSteven Rostedt		doprint "bug timed out after $booted_timeout seconds\n";
1326ecaf8e52SSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1327ecaf8e52SSteven Rostedt		last;
1328ecaf8e52SSteven Rostedt	    }
1329ecaf8e52SSteven Rostedt	} elsif ($booted) {
1330a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
1331cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1332cd4f1d53SSteven Rostedt		my $s = $booted_timeout == 1 ? "" : "s";
1333cd4f1d53SSteven Rostedt		doprint "Successful boot found: break after $booted_timeout second$s\n";
1334cd4f1d53SSteven Rostedt		last;
1335cd4f1d53SSteven Rostedt	    }
13362b7d9b21SSteven Rostedt	} else {
13377faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
1338cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1339cd4f1d53SSteven Rostedt		my $s = $timeout == 1 ? "" : "s";
1340cd4f1d53SSteven Rostedt		doprint "Timed out after $timeout second$s\n";
1341cd4f1d53SSteven Rostedt		last;
13422b7d9b21SSteven Rostedt	    }
1343cd4f1d53SSteven Rostedt	}
13442545eb61SSteven Rostedt
13452545eb61SSteven Rostedt	doprint $line;
13467faafbd6SSteven Rostedt	print DMESG $line;
13472545eb61SSteven Rostedt
13482545eb61SSteven Rostedt	# we are not guaranteed to get a full line
13492545eb61SSteven Rostedt	$full_line .= $line;
13502545eb61SSteven Rostedt
1351a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
13522545eb61SSteven Rostedt	    $booted = 1;
13531c8a617aSSteven Rostedt	    $success_start = time;
13541c8a617aSSteven Rostedt	}
13551c8a617aSSteven Rostedt
13561c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
13571c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
13581c8a617aSSteven Rostedt	    my $now = time;
13591c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
13601c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
13611c8a617aSSteven Rostedt		last;
13621c8a617aSSteven Rostedt	    }
13632545eb61SSteven Rostedt	}
13642545eb61SSteven Rostedt
13655c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
13665c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
13675c42fc5bSSteven Rostedt	}
13685c42fc5bSSteven Rostedt
13692545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
13704651920eSSteven Rostedt	    if (!$bug && !$skip_call_trace) {
13711c8a617aSSteven Rostedt		$bug = 1;
13721c8a617aSSteven Rostedt		$failure_start = time;
13731c8a617aSSteven Rostedt	    }
13741c8a617aSSteven Rostedt	}
13751c8a617aSSteven Rostedt
13761c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
13771c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
13781c8a617aSSteven Rostedt	    my $now = time;
13791c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
13801c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
13811c8a617aSSteven Rostedt		last;
13821c8a617aSSteven Rostedt	    }
13835c42fc5bSSteven Rostedt	}
13845c42fc5bSSteven Rostedt
13855c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
13865c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
13875c42fc5bSSteven Rostedt	}
13885c42fc5bSSteven Rostedt
13895c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
139010abf118SSteven Rostedt	    $failure_start = time;
13912545eb61SSteven Rostedt	    $bug = 1;
13922545eb61SSteven Rostedt	}
13932545eb61SSteven Rostedt
1394f1a5b962SSteven Rostedt	# Detect triple faults by testing the banner
1395f1a5b962SSteven Rostedt	if ($full_line =~ /\bLinux version (\S+).*\n/) {
1396f1a5b962SSteven Rostedt	    if ($1 eq $version) {
1397f1a5b962SSteven Rostedt		$version_found = 1;
1398f1a5b962SSteven Rostedt	    } elsif ($version_found && $detect_triplefault) {
1399f1a5b962SSteven Rostedt		# We already booted into the kernel we are testing,
1400f1a5b962SSteven Rostedt		# but now we booted into another kernel?
1401f1a5b962SSteven Rostedt		# Consider this a triple fault.
1402f1a5b962SSteven Rostedt		doprint "Aleady booted in Linux kernel $version, but now\n";
1403f1a5b962SSteven Rostedt		doprint "we booted into Linux kernel $1.\n";
1404f1a5b962SSteven Rostedt		doprint "Assuming that this is a triple fault.\n";
1405f1a5b962SSteven Rostedt		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1406f1a5b962SSteven Rostedt		last;
1407f1a5b962SSteven Rostedt	    }
1408f1a5b962SSteven Rostedt	}
1409f1a5b962SSteven Rostedt
14102545eb61SSteven Rostedt	if ($line =~ /\n/) {
14112545eb61SSteven Rostedt	    $full_line = "";
14122545eb61SSteven Rostedt	}
14132d01b26aSSteven Rostedt
14142d01b26aSSteven Rostedt	if ($stop_test_after > 0 && !$booted && !$bug) {
14152d01b26aSSteven Rostedt	    if (time - $monitor_start > $stop_test_after) {
14164d62bf51SSteven Rostedt		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
14172d01b26aSSteven Rostedt		$done = 1;
14182d01b26aSSteven Rostedt	    }
14192d01b26aSSteven Rostedt	}
14202545eb61SSteven Rostedt    }
14212545eb61SSteven Rostedt
14227faafbd6SSteven Rostedt    close(DMESG);
14232545eb61SSteven Rostedt
14242545eb61SSteven Rostedt    if ($bug) {
14252b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
1426576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
14272545eb61SSteven Rostedt    }
14285f9b6cedSSteven Rostedt
1429a75fececSSteven Rostedt    if (!$booted) {
1430a75fececSSteven Rostedt	return 0 if ($in_bisect);
1431576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
1432a75fececSSteven Rostedt    }
1433a75fececSSteven Rostedt
14342b7d9b21SSteven Rostedt    return 1;
14352545eb61SSteven Rostedt}
14362545eb61SSteven Rostedt
1437db05cfefSSteven Rostedtsub do_post_install {
1438db05cfefSSteven Rostedt
1439db05cfefSSteven Rostedt    return if (!defined($post_install));
1440db05cfefSSteven Rostedt
1441db05cfefSSteven Rostedt    my $cp_post_install = $post_install;
1442db05cfefSSteven Rostedt    $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
1443db05cfefSSteven Rostedt    run_command "$cp_post_install" or
1444db05cfefSSteven Rostedt	dodie "Failed to run post install";
1445db05cfefSSteven Rostedt}
1446db05cfefSSteven Rostedt
14472545eb61SSteven Rostedtsub install {
14482545eb61SSteven Rostedt
1449e0a8742eSSteven Rostedt    return if ($no_install);
1450e0a8742eSSteven Rostedt
1451e48c5293SSteven Rostedt    run_scp "$outputdir/$build_target", "$target_image" or
14525c42fc5bSSteven Rostedt	dodie "failed to copy image";
14535f9b6cedSSteven Rostedt
14545f9b6cedSSteven Rostedt    my $install_mods = 0;
14555f9b6cedSSteven Rostedt
14565f9b6cedSSteven Rostedt    # should we process modules?
14575f9b6cedSSteven Rostedt    $install_mods = 0;
145851ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
14595f9b6cedSSteven Rostedt    while (<IN>) {
14605f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
14615f9b6cedSSteven Rostedt	    $install_mods = 1 if (defined($1));
14625f9b6cedSSteven Rostedt	    last;
14635f9b6cedSSteven Rostedt	}
14645f9b6cedSSteven Rostedt    }
14655f9b6cedSSteven Rostedt    close(IN);
14665f9b6cedSSteven Rostedt
14675f9b6cedSSteven Rostedt    if (!$install_mods) {
1468db05cfefSSteven Rostedt	do_post_install;
14695f9b6cedSSteven Rostedt	doprint "No modules needed\n";
14705f9b6cedSSteven Rostedt	return;
14712545eb61SSteven Rostedt    }
14722545eb61SSteven Rostedt
1473a75fececSSteven Rostedt    run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
14745f9b6cedSSteven Rostedt	dodie "Failed to install modules";
14755f9b6cedSSteven Rostedt
14762545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
1477a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
14782545eb61SSteven Rostedt
1479e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
14805c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
14812545eb61SSteven Rostedt
14825c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
1483a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
14845c42fc5bSSteven Rostedt	dodie "making tarball";
14855c42fc5bSSteven Rostedt
1486e48c5293SSteven Rostedt    run_scp "$tmpdir/$modtar", "/tmp" or
14875c42fc5bSSteven Rostedt	dodie "failed to copy modules";
14885c42fc5bSSteven Rostedt
1489a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
14905c42fc5bSSteven Rostedt
1491e7b13441SSteven Rostedt    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
14925c42fc5bSSteven Rostedt	dodie "failed to tar modules";
14935c42fc5bSSteven Rostedt
1494e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
14958b37ca8cSSteven Rostedt
1496db05cfefSSteven Rostedt    do_post_install;
14972545eb61SSteven Rostedt}
14982545eb61SSteven Rostedt
1499ddf607e5SSteven Rostedtsub get_version {
1500ddf607e5SSteven Rostedt    # get the release name
1501ddf607e5SSteven Rostedt    doprint "$make kernelrelease ... ";
1502ddf607e5SSteven Rostedt    $version = `$make kernelrelease | tail -1`;
1503ddf607e5SSteven Rostedt    chomp($version);
1504ddf607e5SSteven Rostedt    doprint "$version\n";
1505ddf607e5SSteven Rostedt}
1506ddf607e5SSteven Rostedt
1507ddf607e5SSteven Rostedtsub start_monitor_and_boot {
15089f7424ccSSteven Rostedt    # Make sure the stable kernel has finished booting
15099f7424ccSSteven Rostedt    start_monitor;
15109f7424ccSSteven Rostedt    wait_for_monitor 5;
15119f7424ccSSteven Rostedt    end_monitor;
15129f7424ccSSteven Rostedt
1513ddf607e5SSteven Rostedt    get_grub_index;
1514ddf607e5SSteven Rostedt    get_version;
1515ddf607e5SSteven Rostedt    install;
1516ddf607e5SSteven Rostedt
1517ddf607e5SSteven Rostedt    start_monitor;
1518ddf607e5SSteven Rostedt    return monitor;
1519ddf607e5SSteven Rostedt}
1520ddf607e5SSteven Rostedt
15216c5ee0beSSteven Rostedtsub check_buildlog {
15226c5ee0beSSteven Rostedt    my ($patch) = @_;
15236c5ee0beSSteven Rostedt
15246c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
15256c5ee0beSSteven Rostedt
15266c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
15276c5ee0beSSteven Rostedt	dodie "failed to show $patch";
15286c5ee0beSSteven Rostedt    while (<IN>) {
15296c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
15306c5ee0beSSteven Rostedt	    chomp $1;
15316c5ee0beSSteven Rostedt	    $files[$#files] = $1;
15326c5ee0beSSteven Rostedt	}
15336c5ee0beSSteven Rostedt    }
15346c5ee0beSSteven Rostedt    close(IN);
15356c5ee0beSSteven Rostedt
15366c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
15376c5ee0beSSteven Rostedt    while (<IN>) {
15386c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
15396c5ee0beSSteven Rostedt	    my $err = $1;
15406c5ee0beSSteven Rostedt	    foreach my $file (@files) {
1541a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
15426c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
15432b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
15446c5ee0beSSteven Rostedt		}
15456c5ee0beSSteven Rostedt	    }
15466c5ee0beSSteven Rostedt	}
15476c5ee0beSSteven Rostedt    }
15486c5ee0beSSteven Rostedt    close(IN);
15492b7d9b21SSteven Rostedt
15502b7d9b21SSteven Rostedt    return 1;
15516c5ee0beSSteven Rostedt}
15526c5ee0beSSteven Rostedt
1553fcb3f16aSSteven Rostedtsub apply_min_config {
1554fcb3f16aSSteven Rostedt    my $outconfig = "$output_config.new";
1555612b9e9bSSteven Rostedt
1556fcb3f16aSSteven Rostedt    # Read the config file and remove anything that
1557fcb3f16aSSteven Rostedt    # is in the force_config hash (from minconfig and others)
1558fcb3f16aSSteven Rostedt    # then add the force config back.
1559fcb3f16aSSteven Rostedt
1560fcb3f16aSSteven Rostedt    doprint "Applying minimum configurations into $output_config.new\n";
1561fcb3f16aSSteven Rostedt
1562fcb3f16aSSteven Rostedt    open (OUT, ">$outconfig") or
1563fcb3f16aSSteven Rostedt	dodie "Can't create $outconfig";
1564fcb3f16aSSteven Rostedt
1565fcb3f16aSSteven Rostedt    if (-f $output_config) {
1566fcb3f16aSSteven Rostedt	open (IN, $output_config) or
1567fcb3f16aSSteven Rostedt	    dodie "Failed to open $output_config";
1568fcb3f16aSSteven Rostedt	while (<IN>) {
1569fcb3f16aSSteven Rostedt	    if (/^(# )?(CONFIG_[^\s=]*)/) {
1570fcb3f16aSSteven Rostedt		next if (defined($force_config{$2}));
1571fcb3f16aSSteven Rostedt	    }
1572fcb3f16aSSteven Rostedt	    print OUT;
1573fcb3f16aSSteven Rostedt	}
1574fcb3f16aSSteven Rostedt	close IN;
1575fcb3f16aSSteven Rostedt    }
1576fcb3f16aSSteven Rostedt    foreach my $config (keys %force_config) {
1577fcb3f16aSSteven Rostedt	print OUT "$force_config{$config}\n";
1578fcb3f16aSSteven Rostedt    }
1579fcb3f16aSSteven Rostedt    close OUT;
1580fcb3f16aSSteven Rostedt
1581fcb3f16aSSteven Rostedt    run_command "mv $outconfig $output_config";
1582fcb3f16aSSteven Rostedt}
1583fcb3f16aSSteven Rostedt
1584fcb3f16aSSteven Rostedtsub make_oldconfig {
1585fcb3f16aSSteven Rostedt
15864c4ab120SSteven Rostedt    my @force_list = keys %force_config;
15874c4ab120SSteven Rostedt
15884c4ab120SSteven Rostedt    if ($#force_list >= 0) {
1589fcb3f16aSSteven Rostedt	apply_min_config;
15904c4ab120SSteven Rostedt    }
1591fcb3f16aSSteven Rostedt
1592fcb3f16aSSteven Rostedt    if (!run_command "$make oldnoconfig") {
1593612b9e9bSSteven Rostedt	# Perhaps oldnoconfig doesn't exist in this version of the kernel
1594612b9e9bSSteven Rostedt	# try a yes '' | oldconfig
1595612b9e9bSSteven Rostedt	doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1596fcb3f16aSSteven Rostedt	run_command "yes '' | $make oldconfig" or
1597612b9e9bSSteven Rostedt	    dodie "failed make config oldconfig";
1598612b9e9bSSteven Rostedt    }
1599612b9e9bSSteven Rostedt}
1600612b9e9bSSteven Rostedt
1601fcb3f16aSSteven Rostedt# read a config file and use this to force new configs.
1602fcb3f16aSSteven Rostedtsub load_force_config {
1603fcb3f16aSSteven Rostedt    my ($config) = @_;
1604fcb3f16aSSteven Rostedt
1605fcb3f16aSSteven Rostedt    open(IN, $config) or
1606fcb3f16aSSteven Rostedt	dodie "failed to read $config";
1607fcb3f16aSSteven Rostedt    while (<IN>) {
1608fcb3f16aSSteven Rostedt	chomp;
1609fcb3f16aSSteven Rostedt	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1610fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1611fcb3f16aSSteven Rostedt	} elsif (/^# (CONFIG_\S*) is not set/) {
1612fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1613fcb3f16aSSteven Rostedt	}
1614fcb3f16aSSteven Rostedt    }
1615fcb3f16aSSteven Rostedt    close IN;
1616fcb3f16aSSteven Rostedt}
1617fcb3f16aSSteven Rostedt
16182545eb61SSteven Rostedtsub build {
16192545eb61SSteven Rostedt    my ($type) = @_;
16202545eb61SSteven Rostedt
16217faafbd6SSteven Rostedt    unlink $buildlog;
16227faafbd6SSteven Rostedt
16234ab1cce5SSteven Rostedt    # Failed builds should not reboot the target
16244ab1cce5SSteven Rostedt    my $save_no_reboot = $no_reboot;
16254ab1cce5SSteven Rostedt    $no_reboot = 1;
16264ab1cce5SSteven Rostedt
16270bd6c1a3SSteven Rostedt    if (defined($pre_build)) {
16280bd6c1a3SSteven Rostedt	my $ret = run_command $pre_build;
16290bd6c1a3SSteven Rostedt	if (!$ret && defined($pre_build_die) &&
16300bd6c1a3SSteven Rostedt	    $pre_build_die) {
16310bd6c1a3SSteven Rostedt	    dodie "failed to pre_build\n";
16320bd6c1a3SSteven Rostedt	}
16330bd6c1a3SSteven Rostedt    }
16340bd6c1a3SSteven Rostedt
163575c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
163651ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
163775c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
16385f9b6cedSSteven Rostedt
163975c3fda7SSteven Rostedt	$type = "oldconfig";
164075c3fda7SSteven Rostedt    }
164175c3fda7SSteven Rostedt
16425c42fc5bSSteven Rostedt    # old config can ask questions
16435c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
16449386c6abSSteven Rostedt	$type = "oldnoconfig";
164575c3fda7SSteven Rostedt
164675c3fda7SSteven Rostedt	# allow for empty configs
164751ad1dd1SSteven Rostedt	run_command "touch $output_config";
164875c3fda7SSteven Rostedt
164913488231SAndrew Jones	if (!$noclean) {
165051ad1dd1SSteven Rostedt	    run_command "mv $output_config $outputdir/config_temp" or
16515c42fc5bSSteven Rostedt		dodie "moving .config";
16525c42fc5bSSteven Rostedt
165313488231SAndrew Jones	    run_command "$make mrproper" or dodie "make mrproper";
16545c42fc5bSSteven Rostedt
165551ad1dd1SSteven Rostedt	    run_command "mv $outputdir/config_temp $output_config" or
16565c42fc5bSSteven Rostedt		dodie "moving config_temp";
165713488231SAndrew Jones	}
16585c42fc5bSSteven Rostedt
16595c42fc5bSSteven Rostedt    } elsif (!$noclean) {
166051ad1dd1SSteven Rostedt	unlink "$output_config";
16615f9b6cedSSteven Rostedt	run_command "$make mrproper" or
16625c42fc5bSSteven Rostedt	    dodie "make mrproper";
16635c42fc5bSSteven Rostedt    }
16642545eb61SSteven Rostedt
16652545eb61SSteven Rostedt    # add something to distinguish this build
1666a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
1667a75fececSSteven Rostedt    print OUT "$localversion\n";
16682545eb61SSteven Rostedt    close(OUT);
16692545eb61SSteven Rostedt
16705f9b6cedSSteven Rostedt    if (defined($minconfig)) {
1671fcb3f16aSSteven Rostedt	load_force_config($minconfig);
16722545eb61SSteven Rostedt    }
16732545eb61SSteven Rostedt
1674fcb3f16aSSteven Rostedt    if ($type ne "oldnoconfig") {
1675fcb3f16aSSteven Rostedt	run_command "$make $type" or
16765c42fc5bSSteven Rostedt	    dodie "failed make config";
1677612b9e9bSSteven Rostedt    }
1678fcb3f16aSSteven Rostedt    # Run old config regardless, to enforce min configurations
1679fcb3f16aSSteven Rostedt    make_oldconfig;
16802545eb61SSteven Rostedt
1681a75fececSSteven Rostedt    $redirect = "$buildlog";
16820bd6c1a3SSteven Rostedt    my $build_ret = run_command "$make $build_options";
16836c5ee0beSSteven Rostedt    undef $redirect;
16840bd6c1a3SSteven Rostedt
16850bd6c1a3SSteven Rostedt    if (defined($post_build)) {
16860bd6c1a3SSteven Rostedt	my $ret = run_command $post_build;
16870bd6c1a3SSteven Rostedt	if (!$ret && defined($post_build_die) &&
16880bd6c1a3SSteven Rostedt	    $post_build_die) {
16890bd6c1a3SSteven Rostedt	    dodie "failed to post_build\n";
16900bd6c1a3SSteven Rostedt	}
16910bd6c1a3SSteven Rostedt    }
16920bd6c1a3SSteven Rostedt
16930bd6c1a3SSteven Rostedt    if (!$build_ret) {
16945f9b6cedSSteven Rostedt	# bisect may need this to pass
16954ab1cce5SSteven Rostedt	if ($in_bisect) {
16964ab1cce5SSteven Rostedt	    $no_reboot = $save_no_reboot;
16974ab1cce5SSteven Rostedt	    return 0;
16984ab1cce5SSteven Rostedt	}
16992b7d9b21SSteven Rostedt	fail "failed build" and return 0;
17002545eb61SSteven Rostedt    }
17015f9b6cedSSteven Rostedt
17024ab1cce5SSteven Rostedt    $no_reboot = $save_no_reboot;
17034ab1cce5SSteven Rostedt
17042b7d9b21SSteven Rostedt    return 1;
17052545eb61SSteven Rostedt}
17062545eb61SSteven Rostedt
170775c3fda7SSteven Rostedtsub halt {
1708e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
1709576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
1710576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
1711576f627cSSteven Rostedt	    run_command "$power_off";
1712576f627cSSteven Rostedt	}
1713576f627cSSteven Rostedt    } else {
171475c3fda7SSteven Rostedt	# nope? the zap it!
1715a75fececSSteven Rostedt	run_command "$power_off";
171675c3fda7SSteven Rostedt    }
171775c3fda7SSteven Rostedt}
171875c3fda7SSteven Rostedt
17195f9b6cedSSteven Rostedtsub success {
17205f9b6cedSSteven Rostedt    my ($i) = @_;
17215f9b6cedSSteven Rostedt
1722e48c5293SSteven Rostedt    $successes++;
1723e48c5293SSteven Rostedt
17249064af52SSteven Rostedt    my $name = "";
17259064af52SSteven Rostedt
17269064af52SSteven Rostedt    if (defined($test_name)) {
17279064af52SSteven Rostedt	$name = " ($test_name)";
17289064af52SSteven Rostedt    }
17299064af52SSteven Rostedt
17305f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
17315f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
17329064af52SSteven Rostedt    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
17335f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
17345f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
17355f9b6cedSSteven Rostedt
1736de5b6e3bSRabin Vincent    if (defined($store_successes)) {
1737de5b6e3bSRabin Vincent        save_logs "success", $store_successes;
1738de5b6e3bSRabin Vincent    }
1739de5b6e3bSRabin Vincent
1740576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1741a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
17422728be41SAndrew Jones	reboot $sleep_time;
17435f9b6cedSSteven Rostedt    }
17445f9b6cedSSteven Rostedt}
17455f9b6cedSSteven Rostedt
1746c960bb9fSSteven Rostedtsub answer_bisect {
1747c960bb9fSSteven Rostedt    for (;;) {
1748c960bb9fSSteven Rostedt	doprint "Pass or fail? [p/f]";
1749c960bb9fSSteven Rostedt	my $ans = <STDIN>;
1750c960bb9fSSteven Rostedt	chomp $ans;
1751c960bb9fSSteven Rostedt	if ($ans eq "p" || $ans eq "P") {
1752c960bb9fSSteven Rostedt	    return 1;
1753c960bb9fSSteven Rostedt	} elsif ($ans eq "f" || $ans eq "F") {
1754c960bb9fSSteven Rostedt	    return 0;
1755c960bb9fSSteven Rostedt	} else {
1756c960bb9fSSteven Rostedt	    print "Please answer 'P' or 'F'\n";
1757c960bb9fSSteven Rostedt	}
1758c960bb9fSSteven Rostedt    }
1759c960bb9fSSteven Rostedt}
1760c960bb9fSSteven Rostedt
17615a391fbfSSteven Rostedtsub child_run_test {
17627faafbd6SSteven Rostedt    my $failed = 0;
17635a391fbfSSteven Rostedt
17647faafbd6SSteven Rostedt    # child should have no power
1765a75fececSSteven Rostedt    $reboot_on_error = 0;
1766a75fececSSteven Rostedt    $poweroff_on_error = 0;
1767a75fececSSteven Rostedt    $die_on_failure = 1;
17687faafbd6SSteven Rostedt
1769a9dd5d63SRabin Vincent    $redirect = "$testlog";
17707faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
1771a9dd5d63SRabin Vincent    undef $redirect;
1772a9dd5d63SRabin Vincent
17735a391fbfSSteven Rostedt    exit $failed;
17745a391fbfSSteven Rostedt}
17755a391fbfSSteven Rostedt
17765a391fbfSSteven Rostedtmy $child_done;
17775a391fbfSSteven Rostedt
17785a391fbfSSteven Rostedtsub child_finished {
17795a391fbfSSteven Rostedt    $child_done = 1;
17805a391fbfSSteven Rostedt}
17815a391fbfSSteven Rostedt
17825a391fbfSSteven Rostedtsub do_run_test {
17835a391fbfSSteven Rostedt    my $child_pid;
17845a391fbfSSteven Rostedt    my $child_exit;
17855a391fbfSSteven Rostedt    my $line;
17865a391fbfSSteven Rostedt    my $full_line;
17875a391fbfSSteven Rostedt    my $bug = 0;
17885a391fbfSSteven Rostedt
17897faafbd6SSteven Rostedt    wait_for_monitor 1;
17905a391fbfSSteven Rostedt
17917faafbd6SSteven Rostedt    doprint "run test $run_test\n";
17925a391fbfSSteven Rostedt
17935a391fbfSSteven Rostedt    $child_done = 0;
17945a391fbfSSteven Rostedt
17955a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
17965a391fbfSSteven Rostedt
17975a391fbfSSteven Rostedt    $child_pid = fork;
17985a391fbfSSteven Rostedt
17995a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
18005a391fbfSSteven Rostedt
18015a391fbfSSteven Rostedt    $full_line = "";
18025a391fbfSSteven Rostedt
18035a391fbfSSteven Rostedt    do {
18047faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
18055a391fbfSSteven Rostedt	if (defined($line)) {
18065a391fbfSSteven Rostedt
18075a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
18085a391fbfSSteven Rostedt	    $full_line .= $line;
18098ea0e063SSteven Rostedt	    doprint $line;
18105a391fbfSSteven Rostedt
18115a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
18125a391fbfSSteven Rostedt		$bug = 1;
18135a391fbfSSteven Rostedt	    }
18145a391fbfSSteven Rostedt
18155a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
18165a391fbfSSteven Rostedt		$bug = 1;
18175a391fbfSSteven Rostedt	    }
18185a391fbfSSteven Rostedt
18195a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
18205a391fbfSSteven Rostedt		$full_line = "";
18215a391fbfSSteven Rostedt	    }
18225a391fbfSSteven Rostedt	}
18235a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
18245a391fbfSSteven Rostedt
18255a391fbfSSteven Rostedt    if ($bug) {
18268ea0e063SSteven Rostedt	my $failure_start = time;
18278ea0e063SSteven Rostedt	my $now;
18288ea0e063SSteven Rostedt	do {
18298ea0e063SSteven Rostedt	    $line = wait_for_input($monitor_fp, 1);
18308ea0e063SSteven Rostedt	    if (defined($line)) {
18318ea0e063SSteven Rostedt		doprint $line;
18328ea0e063SSteven Rostedt	    }
18338ea0e063SSteven Rostedt	    $now = time;
18348ea0e063SSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
18358ea0e063SSteven Rostedt		last;
18368ea0e063SSteven Rostedt	    }
18378ea0e063SSteven Rostedt	} while (defined($line));
18388ea0e063SSteven Rostedt
18395a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
18405a391fbfSSteven Rostedt	# kill the child with extreme prejudice
18415a391fbfSSteven Rostedt	kill 9, $child_pid;
18425a391fbfSSteven Rostedt    }
18435a391fbfSSteven Rostedt
18445a391fbfSSteven Rostedt    waitpid $child_pid, 0;
18455a391fbfSSteven Rostedt    $child_exit = $?;
18465a391fbfSSteven Rostedt
18475a391fbfSSteven Rostedt    if ($bug || $child_exit) {
18482b7d9b21SSteven Rostedt	return 0 if $in_bisect;
18492b7d9b21SSteven Rostedt	fail "test failed" and return 0;
18505a391fbfSSteven Rostedt    }
18512b7d9b21SSteven Rostedt    return 1;
18525a391fbfSSteven Rostedt}
18535a391fbfSSteven Rostedt
1854a75fececSSteven Rostedtsub run_git_bisect {
1855a75fececSSteven Rostedt    my ($command) = @_;
1856a75fececSSteven Rostedt
1857a75fececSSteven Rostedt    doprint "$command ... ";
1858a75fececSSteven Rostedt
1859a75fececSSteven Rostedt    my $output = `$command 2>&1`;
1860a75fececSSteven Rostedt    my $ret = $?;
1861a75fececSSteven Rostedt
1862a75fececSSteven Rostedt    logit $output;
1863a75fececSSteven Rostedt
1864a75fececSSteven Rostedt    if ($ret) {
1865a75fececSSteven Rostedt	doprint "FAILED\n";
1866a75fececSSteven Rostedt	dodie "Failed to git bisect";
1867a75fececSSteven Rostedt    }
1868a75fececSSteven Rostedt
1869a75fececSSteven Rostedt    doprint "SUCCESS\n";
1870a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1871a75fececSSteven Rostedt	doprint "$1 [$2]\n";
1872a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1873a75fececSSteven Rostedt	$bisect_bad = $1;
1874a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
1875a75fececSSteven Rostedt	return 0;
1876a75fececSSteven Rostedt    } else {
1877a75fececSSteven Rostedt	# we already logged it, just print it now.
1878a75fececSSteven Rostedt	print $output;
1879a75fececSSteven Rostedt    }
1880a75fececSSteven Rostedt
1881a75fececSSteven Rostedt    return 1;
1882a75fececSSteven Rostedt}
1883a75fececSSteven Rostedt
1884c23dca7cSSteven Rostedtsub bisect_reboot {
1885c23dca7cSSteven Rostedt    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
18862728be41SAndrew Jones    reboot $bisect_sleep_time;
1887c23dca7cSSteven Rostedt}
1888c23dca7cSSteven Rostedt
1889c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip
18900a05c769SSteven Rostedtsub run_bisect_test {
18910a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
18925f9b6cedSSteven Rostedt
18932b7d9b21SSteven Rostedt    my $failed = 0;
18945f9b6cedSSteven Rostedt    my $result;
18955f9b6cedSSteven Rostedt    my $output;
18965f9b6cedSSteven Rostedt    my $ret;
18975f9b6cedSSteven Rostedt
18980a05c769SSteven Rostedt    $in_bisect = 1;
18990a05c769SSteven Rostedt
19000a05c769SSteven Rostedt    build $buildtype or $failed = 1;
19015f9b6cedSSteven Rostedt
19025f9b6cedSSteven Rostedt    if ($type ne "build") {
1903c23dca7cSSteven Rostedt	if ($failed && $bisect_skip) {
1904c23dca7cSSteven Rostedt	    $in_bisect = 0;
1905c23dca7cSSteven Rostedt	    return -1;
1906c23dca7cSSteven Rostedt	}
19077faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
19085f9b6cedSSteven Rostedt
19095f9b6cedSSteven Rostedt	# Now boot the box
1910ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
19115f9b6cedSSteven Rostedt
19125f9b6cedSSteven Rostedt	if ($type ne "boot") {
1913c23dca7cSSteven Rostedt	    if ($failed && $bisect_skip) {
1914c23dca7cSSteven Rostedt		end_monitor;
1915c23dca7cSSteven Rostedt		bisect_reboot;
1916c23dca7cSSteven Rostedt		$in_bisect = 0;
1917c23dca7cSSteven Rostedt		return -1;
1918c23dca7cSSteven Rostedt	    }
19197faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
19205a391fbfSSteven Rostedt
19212b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
19225f9b6cedSSteven Rostedt	}
19237faafbd6SSteven Rostedt	end_monitor;
19245f9b6cedSSteven Rostedt    }
19255f9b6cedSSteven Rostedt
19265f9b6cedSSteven Rostedt    if ($failed) {
19270a05c769SSteven Rostedt	$result = 0;
19285f9b6cedSSteven Rostedt    } else {
19290a05c769SSteven Rostedt	$result = 1;
19305f9b6cedSSteven Rostedt    }
19314025bc62SSteven Rostedt
19324025bc62SSteven Rostedt    # reboot the box to a kernel we can ssh to
19334025bc62SSteven Rostedt    if ($type ne "build") {
19344025bc62SSteven Rostedt	bisect_reboot;
19354025bc62SSteven Rostedt    }
19360a05c769SSteven Rostedt    $in_bisect = 0;
19370a05c769SSteven Rostedt
19380a05c769SSteven Rostedt    return $result;
19390a05c769SSteven Rostedt}
19400a05c769SSteven Rostedt
19410a05c769SSteven Rostedtsub run_bisect {
19420a05c769SSteven Rostedt    my ($type) = @_;
19430a05c769SSteven Rostedt    my $buildtype = "oldconfig";
19440a05c769SSteven Rostedt
19450a05c769SSteven Rostedt    # We should have a minconfig to use?
19460a05c769SSteven Rostedt    if (defined($minconfig)) {
19470a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
19480a05c769SSteven Rostedt    }
19490a05c769SSteven Rostedt
19500a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
19510a05c769SSteven Rostedt
1952c960bb9fSSteven Rostedt    if ($bisect_manual) {
1953c960bb9fSSteven Rostedt	$ret = answer_bisect;
1954c960bb9fSSteven Rostedt    }
19555f9b6cedSSteven Rostedt
1956d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
1957d6ce2a0bSSteven Rostedt    if ($reverse_bisect) {
19580a05c769SSteven Rostedt	$ret = !$ret;
1959d6ce2a0bSSteven Rostedt    }
1960d6ce2a0bSSteven Rostedt
1961c23dca7cSSteven Rostedt    if ($ret > 0) {
19620a05c769SSteven Rostedt	return "good";
1963c23dca7cSSteven Rostedt    } elsif ($ret == 0) {
19640a05c769SSteven Rostedt	return  "bad";
1965c23dca7cSSteven Rostedt    } elsif ($bisect_skip) {
1966c23dca7cSSteven Rostedt	doprint "HIT A BAD COMMIT ... SKIPPING\n";
1967c23dca7cSSteven Rostedt	return "skip";
19680a05c769SSteven Rostedt    }
19695f9b6cedSSteven Rostedt}
19705f9b6cedSSteven Rostedt
1971dad98754SSteven Rostedtsub update_bisect_replay {
1972dad98754SSteven Rostedt    my $tmp_log = "$tmpdir/ktest_bisect_log";
1973dad98754SSteven Rostedt    run_command "git bisect log > $tmp_log" or
1974dad98754SSteven Rostedt	die "can't create bisect log";
1975dad98754SSteven Rostedt    return $tmp_log;
1976dad98754SSteven Rostedt}
1977dad98754SSteven Rostedt
19785f9b6cedSSteven Rostedtsub bisect {
19795f9b6cedSSteven Rostedt    my ($i) = @_;
19805f9b6cedSSteven Rostedt
19815f9b6cedSSteven Rostedt    my $result;
19825f9b6cedSSteven Rostedt
19835f9b6cedSSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($opt{"BISECT_GOOD[$i]"}));
19845f9b6cedSSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($opt{"BISECT_BAD[$i]"}));
19855f9b6cedSSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($opt{"BISECT_TYPE[$i]"}));
19865f9b6cedSSteven Rostedt
19875f9b6cedSSteven Rostedt    my $good = $opt{"BISECT_GOOD[$i]"};
19885f9b6cedSSteven Rostedt    my $bad = $opt{"BISECT_BAD[$i]"};
19895f9b6cedSSteven Rostedt    my $type = $opt{"BISECT_TYPE[$i]"};
1990a75fececSSteven Rostedt    my $start = $opt{"BISECT_START[$i]"};
1991a75fececSSteven Rostedt    my $replay = $opt{"BISECT_REPLAY[$i]"};
19923410f6fdSSteven Rostedt    my $start_files = $opt{"BISECT_FILES[$i]"};
19933410f6fdSSteven Rostedt
19943410f6fdSSteven Rostedt    if (defined($start_files)) {
19953410f6fdSSteven Rostedt	$start_files = " -- " . $start_files;
19963410f6fdSSteven Rostedt    } else {
19973410f6fdSSteven Rostedt	$start_files = "";
19983410f6fdSSteven Rostedt    }
19995f9b6cedSSteven Rostedt
2000a57419b3SSteven Rostedt    # convert to true sha1's
2001a57419b3SSteven Rostedt    $good = get_sha1($good);
2002a57419b3SSteven Rostedt    $bad = get_sha1($bad);
2003a57419b3SSteven Rostedt
2004d6ce2a0bSSteven Rostedt    if (defined($opt{"BISECT_REVERSE[$i]"}) &&
2005d6ce2a0bSSteven Rostedt	$opt{"BISECT_REVERSE[$i]"} == 1) {
2006d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
2007d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
2008d6ce2a0bSSteven Rostedt    } else {
2009d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
2010d6ce2a0bSSteven Rostedt    }
2011d6ce2a0bSSteven Rostedt
20125a391fbfSSteven Rostedt    # Can't have a test without having a test to run
20135a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
20145a391fbfSSteven Rostedt	$type = "boot";
20155a391fbfSSteven Rostedt    }
20165a391fbfSSteven Rostedt
2017dad98754SSteven Rostedt    # Check if a bisect was running
2018dad98754SSteven Rostedt    my $bisect_start_file = "$builddir/.git/BISECT_START";
2019dad98754SSteven Rostedt
2020a75fececSSteven Rostedt    my $check = $opt{"BISECT_CHECK[$i]"};
2021dad98754SSteven Rostedt    my $do_check = defined($check) && $check ne "0";
2022dad98754SSteven Rostedt
2023dad98754SSteven Rostedt    if ( -f $bisect_start_file ) {
2024dad98754SSteven Rostedt	print "Bisect in progress found\n";
2025dad98754SSteven Rostedt	if ($do_check) {
2026dad98754SSteven Rostedt	    print " If you say yes, then no checks of good or bad will be done\n";
2027dad98754SSteven Rostedt	}
2028dad98754SSteven Rostedt	if (defined($replay)) {
2029dad98754SSteven Rostedt	    print "** BISECT_REPLAY is defined in config file **";
2030dad98754SSteven Rostedt	    print " Ignore config option and perform new git bisect log?\n";
2031dad98754SSteven Rostedt	    if (read_ync " (yes, no, or cancel) ") {
2032dad98754SSteven Rostedt		$replay = update_bisect_replay;
2033dad98754SSteven Rostedt		$do_check = 0;
2034dad98754SSteven Rostedt	    }
2035dad98754SSteven Rostedt	} elsif (read_yn "read git log and continue?") {
2036dad98754SSteven Rostedt	    $replay = update_bisect_replay;
2037dad98754SSteven Rostedt	    $do_check = 0;
2038dad98754SSteven Rostedt	}
2039dad98754SSteven Rostedt    }
2040dad98754SSteven Rostedt
2041dad98754SSteven Rostedt    if ($do_check) {
2042a75fececSSteven Rostedt
2043a75fececSSteven Rostedt	# get current HEAD
2044a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
2045a75fececSSteven Rostedt
2046a75fececSSteven Rostedt	if ($check ne "good") {
2047a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
2048a75fececSSteven Rostedt	    run_command "git checkout $bad" or
2049a75fececSSteven Rostedt		die "Failed to checkout $bad";
2050a75fececSSteven Rostedt
2051a75fececSSteven Rostedt	    $result = run_bisect $type;
2052a75fececSSteven Rostedt
2053a75fececSSteven Rostedt	    if ($result ne "bad") {
2054a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
2055a75fececSSteven Rostedt	    }
2056a75fececSSteven Rostedt	}
2057a75fececSSteven Rostedt
2058a75fececSSteven Rostedt	if ($check ne "bad") {
2059a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
2060a75fececSSteven Rostedt	    run_command "git checkout $good" or
2061a75fececSSteven Rostedt		die "Failed to checkout $good";
2062a75fececSSteven Rostedt
2063a75fececSSteven Rostedt	    $result = run_bisect $type;
2064a75fececSSteven Rostedt
2065a75fececSSteven Rostedt	    if ($result ne "good") {
2066a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
2067a75fececSSteven Rostedt	    }
2068a75fececSSteven Rostedt	}
2069a75fececSSteven Rostedt
2070a75fececSSteven Rostedt	# checkout where we started
2071a75fececSSteven Rostedt	run_command "git checkout $head" or
2072a75fececSSteven Rostedt	    die "Failed to checkout $head";
2073a75fececSSteven Rostedt    }
2074a75fececSSteven Rostedt
20753410f6fdSSteven Rostedt    run_command "git bisect start$start_files" or
2076a75fececSSteven Rostedt	dodie "could not start bisect";
2077a75fececSSteven Rostedt
2078a75fececSSteven Rostedt    run_command "git bisect good $good" or
2079a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
2080a75fececSSteven Rostedt
2081a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
2082a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
2083a75fececSSteven Rostedt
2084a75fececSSteven Rostedt    if (defined($replay)) {
2085a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
2086a75fececSSteven Rostedt	    dodie "failed to run replay";
2087a75fececSSteven Rostedt    }
2088a75fececSSteven Rostedt
2089a75fececSSteven Rostedt    if (defined($start)) {
2090a75fececSSteven Rostedt	run_command "git checkout $start" or
2091a75fececSSteven Rostedt	    dodie "failed to checkout $start";
2092a75fececSSteven Rostedt    }
2093a75fececSSteven Rostedt
2094a75fececSSteven Rostedt    my $test;
20955f9b6cedSSteven Rostedt    do {
20965f9b6cedSSteven Rostedt	$result = run_bisect $type;
2097a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
2098a75fececSSteven Rostedt    } while ($test);
20995f9b6cedSSteven Rostedt
21005f9b6cedSSteven Rostedt    run_command "git bisect log" or
21015f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
21025f9b6cedSSteven Rostedt
21035f9b6cedSSteven Rostedt    run_command "git bisect reset" or
21045f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
21055f9b6cedSSteven Rostedt
21065f9b6cedSSteven Rostedt    doprint "Bad commit was [$bisect_bad]\n";
21075f9b6cedSSteven Rostedt
21080a05c769SSteven Rostedt    success $i;
21090a05c769SSteven Rostedt}
21100a05c769SSteven Rostedt
21110a05c769SSteven Rostedtmy %config_ignore;
21120a05c769SSteven Rostedtmy %config_set;
21130a05c769SSteven Rostedt
21140a05c769SSteven Rostedtmy %config_list;
21150a05c769SSteven Rostedtmy %null_config;
21160a05c769SSteven Rostedt
21170a05c769SSteven Rostedtmy %dependency;
21180a05c769SSteven Rostedt
21194c4ab120SSteven Rostedtsub assign_configs {
21204c4ab120SSteven Rostedt    my ($hash, $config) = @_;
21210a05c769SSteven Rostedt
21220a05c769SSteven Rostedt    open (IN, $config)
21230a05c769SSteven Rostedt	or dodie "Failed to read $config";
21240a05c769SSteven Rostedt
21250a05c769SSteven Rostedt    while (<IN>) {
21269bf71749SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
21274c4ab120SSteven Rostedt	    ${$hash}{$2} = $1;
21280a05c769SSteven Rostedt	}
21290a05c769SSteven Rostedt    }
21300a05c769SSteven Rostedt
21310a05c769SSteven Rostedt    close(IN);
21320a05c769SSteven Rostedt}
21330a05c769SSteven Rostedt
21344c4ab120SSteven Rostedtsub process_config_ignore {
21354c4ab120SSteven Rostedt    my ($config) = @_;
21364c4ab120SSteven Rostedt
21374c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
21384c4ab120SSteven Rostedt}
21394c4ab120SSteven Rostedt
21400a05c769SSteven Rostedtsub read_current_config {
21410a05c769SSteven Rostedt    my ($config_ref) = @_;
21420a05c769SSteven Rostedt
21430a05c769SSteven Rostedt    %{$config_ref} = ();
21440a05c769SSteven Rostedt    undef %{$config_ref};
21450a05c769SSteven Rostedt
21460a05c769SSteven Rostedt    my @key = keys %{$config_ref};
21470a05c769SSteven Rostedt    if ($#key >= 0) {
21480a05c769SSteven Rostedt	print "did not delete!\n";
21490a05c769SSteven Rostedt	exit;
21500a05c769SSteven Rostedt    }
21510a05c769SSteven Rostedt    open (IN, "$output_config");
21520a05c769SSteven Rostedt
21530a05c769SSteven Rostedt    while (<IN>) {
21540a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
21550a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
21560a05c769SSteven Rostedt	}
21570a05c769SSteven Rostedt    }
21580a05c769SSteven Rostedt    close(IN);
21590a05c769SSteven Rostedt}
21600a05c769SSteven Rostedt
21610a05c769SSteven Rostedtsub get_dependencies {
21620a05c769SSteven Rostedt    my ($config) = @_;
21630a05c769SSteven Rostedt
21640a05c769SSteven Rostedt    my $arr = $dependency{$config};
21650a05c769SSteven Rostedt    if (!defined($arr)) {
21660a05c769SSteven Rostedt	return ();
21670a05c769SSteven Rostedt    }
21680a05c769SSteven Rostedt
21690a05c769SSteven Rostedt    my @deps = @{$arr};
21700a05c769SSteven Rostedt
21710a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
21720a05c769SSteven Rostedt	print "ADD DEP $dep\n";
21730a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
21740a05c769SSteven Rostedt    }
21750a05c769SSteven Rostedt
21760a05c769SSteven Rostedt    return @deps;
21770a05c769SSteven Rostedt}
21780a05c769SSteven Rostedt
21790a05c769SSteven Rostedtsub create_config {
21800a05c769SSteven Rostedt    my @configs = @_;
21810a05c769SSteven Rostedt
21820a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
21830a05c769SSteven Rostedt
21840a05c769SSteven Rostedt    foreach my $config (@configs) {
21850a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
21860a05c769SSteven Rostedt	my @deps = get_dependencies $config;
21870a05c769SSteven Rostedt	foreach my $dep (@deps) {
21880a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
21890a05c769SSteven Rostedt	}
21900a05c769SSteven Rostedt    }
21910a05c769SSteven Rostedt
21920a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
21930a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
21940a05c769SSteven Rostedt    }
21950a05c769SSteven Rostedt    close(OUT);
21960a05c769SSteven Rostedt
21970a05c769SSteven Rostedt#    exit;
2198fcb3f16aSSteven Rostedt    make_oldconfig;
21990a05c769SSteven Rostedt}
22000a05c769SSteven Rostedt
22010a05c769SSteven Rostedtsub compare_configs {
22020a05c769SSteven Rostedt    my (%a, %b) = @_;
22030a05c769SSteven Rostedt
22040a05c769SSteven Rostedt    foreach my $item (keys %a) {
22050a05c769SSteven Rostedt	if (!defined($b{$item})) {
22060a05c769SSteven Rostedt	    print "diff $item\n";
22070a05c769SSteven Rostedt	    return 1;
22080a05c769SSteven Rostedt	}
22090a05c769SSteven Rostedt	delete $b{$item};
22100a05c769SSteven Rostedt    }
22110a05c769SSteven Rostedt
22120a05c769SSteven Rostedt    my @keys = keys %b;
22130a05c769SSteven Rostedt    if ($#keys) {
22140a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
22150a05c769SSteven Rostedt    }
22160a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
22170a05c769SSteven Rostedt
22180a05c769SSteven Rostedt    return 0;
22190a05c769SSteven Rostedt}
22200a05c769SSteven Rostedt
22210a05c769SSteven Rostedtsub run_config_bisect_test {
22220a05c769SSteven Rostedt    my ($type) = @_;
22230a05c769SSteven Rostedt
22240a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
22250a05c769SSteven Rostedt}
22260a05c769SSteven Rostedt
22270a05c769SSteven Rostedtsub process_passed {
22280a05c769SSteven Rostedt    my (%configs) = @_;
22290a05c769SSteven Rostedt
22300a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
22310a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
22320a05c769SSteven Rostedt    # Add them to the min options.
22330a05c769SSteven Rostedt    foreach my $config (keys %configs) {
22340a05c769SSteven Rostedt	if (defined($config_list{$config})) {
22350a05c769SSteven Rostedt	    doprint " removing $config\n";
22360a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
22370a05c769SSteven Rostedt	    delete $config_list{$config};
22380a05c769SSteven Rostedt	}
22390a05c769SSteven Rostedt    }
2240f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
2241f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
22420a05c769SSteven Rostedt}
22430a05c769SSteven Rostedt
22440a05c769SSteven Rostedtsub process_failed {
22450a05c769SSteven Rostedt    my ($config) = @_;
22460a05c769SSteven Rostedt
22470a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
22480a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
22490a05c769SSteven Rostedt    doprint "***************************************\n\n";
22500a05c769SSteven Rostedt}
22510a05c769SSteven Rostedt
22520a05c769SSteven Rostedtsub run_config_bisect {
22530a05c769SSteven Rostedt
22540a05c769SSteven Rostedt    my @start_list = keys %config_list;
22550a05c769SSteven Rostedt
22560a05c769SSteven Rostedt    if ($#start_list < 0) {
22570a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
22580a05c769SSteven Rostedt	return -1;
22590a05c769SSteven Rostedt    }
22600a05c769SSteven Rostedt
22610a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
22620a05c769SSteven Rostedt    my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
22630a05c769SSteven Rostedt    my $ret;
22640a05c769SSteven Rostedt    my %current_config;
22650a05c769SSteven Rostedt
22660a05c769SSteven Rostedt    my $count = $#start_list + 1;
22670a05c769SSteven Rostedt    doprint "  $count configs to test\n";
22680a05c769SSteven Rostedt
22690a05c769SSteven Rostedt    my $half = int($#start_list / 2);
22700a05c769SSteven Rostedt
22710a05c769SSteven Rostedt    do {
22720a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
22730a05c769SSteven Rostedt
22740a05c769SSteven Rostedt	create_config @tophalf;
22750a05c769SSteven Rostedt	read_current_config \%current_config;
22760a05c769SSteven Rostedt
22770a05c769SSteven Rostedt	$count = $#tophalf + 1;
22780a05c769SSteven Rostedt	doprint "Testing $count configs\n";
22790a05c769SSteven Rostedt	my $found = 0;
22800a05c769SSteven Rostedt	# make sure we test something
22810a05c769SSteven Rostedt	foreach my $config (@tophalf) {
22820a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
22830a05c769SSteven Rostedt		logit " $config\n";
22840a05c769SSteven Rostedt		$found = 1;
22850a05c769SSteven Rostedt	    }
22860a05c769SSteven Rostedt	}
22870a05c769SSteven Rostedt	if (!$found) {
22880a05c769SSteven Rostedt	    # try the other half
22890a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
22904c8cc55bSSteven Rostedt	    @tophalf = @start_list[$half + 1 .. $#start_list];
22910a05c769SSteven Rostedt	    create_config @tophalf;
22920a05c769SSteven Rostedt	    read_current_config \%current_config;
22930a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
22940a05c769SSteven Rostedt		if (defined($current_config{$config})) {
22950a05c769SSteven Rostedt		    logit " $config\n";
22960a05c769SSteven Rostedt		    $found = 1;
22970a05c769SSteven Rostedt		}
22980a05c769SSteven Rostedt	    }
22990a05c769SSteven Rostedt	    if (!$found) {
23000a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
23010a05c769SSteven Rostedt		foreach my $config (@start_list) {
23020a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
23030a05c769SSteven Rostedt		}
23040a05c769SSteven Rostedt		return -1;
23050a05c769SSteven Rostedt	    }
23060a05c769SSteven Rostedt	    $count = $#tophalf + 1;
23070a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
23080a05c769SSteven Rostedt	}
23090a05c769SSteven Rostedt
23100a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
2311c960bb9fSSteven Rostedt	if ($bisect_manual) {
2312c960bb9fSSteven Rostedt	    $ret = answer_bisect;
2313c960bb9fSSteven Rostedt	}
23140a05c769SSteven Rostedt	if ($ret) {
23150a05c769SSteven Rostedt	    process_passed %current_config;
23160a05c769SSteven Rostedt	    return 0;
23170a05c769SSteven Rostedt	}
23180a05c769SSteven Rostedt
23190a05c769SSteven Rostedt	doprint "This config had a failure.\n";
23200a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
2321f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
2322f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
23230a05c769SSteven Rostedt
23240a05c769SSteven Rostedt	# A config exists in this group that was bad.
23250a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
23260a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
23270a05c769SSteven Rostedt		doprint " removing $config\n";
23280a05c769SSteven Rostedt		delete $config_list{$config};
23290a05c769SSteven Rostedt	    }
23300a05c769SSteven Rostedt	}
23310a05c769SSteven Rostedt
23320a05c769SSteven Rostedt	@start_list = @tophalf;
23330a05c769SSteven Rostedt
23340a05c769SSteven Rostedt	if ($#start_list == 0) {
23350a05c769SSteven Rostedt	    process_failed $start_list[0];
23360a05c769SSteven Rostedt	    return 1;
23370a05c769SSteven Rostedt	}
23380a05c769SSteven Rostedt
23390a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
23400a05c769SSteven Rostedt	# they are good.
23410a05c769SSteven Rostedt	$half = int($#start_list / 2);
23424c8cc55bSSteven Rostedt    } while ($#start_list > 0);
23430a05c769SSteven Rostedt
2344c960bb9fSSteven Rostedt    # we found a single config, try it again unless we are running manually
2345c960bb9fSSteven Rostedt
2346c960bb9fSSteven Rostedt    if ($bisect_manual) {
2347c960bb9fSSteven Rostedt	process_failed $start_list[0];
2348c960bb9fSSteven Rostedt	return 1;
2349c960bb9fSSteven Rostedt    }
2350c960bb9fSSteven Rostedt
23510a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
23520a05c769SSteven Rostedt
23530a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
23540a05c769SSteven Rostedt    if ($ret) {
23550a05c769SSteven Rostedt	process_passed %current_config;
23560a05c769SSteven Rostedt	return 0;
23570a05c769SSteven Rostedt    }
23580a05c769SSteven Rostedt
23590a05c769SSteven Rostedt    process_failed $start_list[0];
23600a05c769SSteven Rostedt    return 1;
23610a05c769SSteven Rostedt}
23620a05c769SSteven Rostedt
23630a05c769SSteven Rostedtsub config_bisect {
23640a05c769SSteven Rostedt    my ($i) = @_;
23650a05c769SSteven Rostedt
23660a05c769SSteven Rostedt    my $start_config = $opt{"CONFIG_BISECT[$i]"};
23670a05c769SSteven Rostedt
23680a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
23690a05c769SSteven Rostedt
237030f75da5SSteven Rostedt    if (defined($config_bisect_good)) {
237130f75da5SSteven Rostedt	process_config_ignore $config_bisect_good;
237230f75da5SSteven Rostedt    }
237330f75da5SSteven Rostedt
23740a05c769SSteven Rostedt    # Make the file with the bad config and the min config
23750a05c769SSteven Rostedt    if (defined($minconfig)) {
23760a05c769SSteven Rostedt	# read the min config for things to ignore
23770a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
23780a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
23790a05c769SSteven Rostedt    } else {
23800a05c769SSteven Rostedt	unlink $tmpconfig;
23810a05c769SSteven Rostedt    }
23820a05c769SSteven Rostedt
23830a05c769SSteven Rostedt    if (-f $tmpconfig) {
2384fcb3f16aSSteven Rostedt	load_force_config($tmpconfig);
23850a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
23860a05c769SSteven Rostedt    }
23870a05c769SSteven Rostedt
23880a05c769SSteven Rostedt    # now process the start config
23890a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
23900a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
23910a05c769SSteven Rostedt
23920a05c769SSteven Rostedt    # read directly what we want to check
23930a05c769SSteven Rostedt    my %config_check;
23940a05c769SSteven Rostedt    open (IN, $output_config)
23950a05c769SSteven Rostedt	or dodie "faied to open $output_config";
23960a05c769SSteven Rostedt
23970a05c769SSteven Rostedt    while (<IN>) {
23980a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
23990a05c769SSteven Rostedt	    $config_check{$2} = $1;
24000a05c769SSteven Rostedt	}
24010a05c769SSteven Rostedt    }
24020a05c769SSteven Rostedt    close(IN);
24030a05c769SSteven Rostedt
2404250bae8bSSteven Rostedt    # Now run oldconfig with the minconfig
2405fcb3f16aSSteven Rostedt    make_oldconfig;
24060a05c769SSteven Rostedt
24070a05c769SSteven Rostedt    # check to see what we lost (or gained)
24080a05c769SSteven Rostedt    open (IN, $output_config)
24090a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
24100a05c769SSteven Rostedt
24110a05c769SSteven Rostedt    my %removed_configs;
24120a05c769SSteven Rostedt    my %added_configs;
24130a05c769SSteven Rostedt
24140a05c769SSteven Rostedt    while (<IN>) {
24150a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
24160a05c769SSteven Rostedt	    # save off all options
24170a05c769SSteven Rostedt	    $config_set{$2} = $1;
24180a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
24190a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
24200a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
24210a05c769SSteven Rostedt		} else {
24220a05c769SSteven Rostedt		    $config_list{$2} = $1;
24230a05c769SSteven Rostedt		}
24240a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
24250a05c769SSteven Rostedt		$added_configs{$2} = $1;
24260a05c769SSteven Rostedt		$config_list{$2} = $1;
24270a05c769SSteven Rostedt	    }
24280a05c769SSteven Rostedt	}
24290a05c769SSteven Rostedt    }
24300a05c769SSteven Rostedt    close(IN);
24310a05c769SSteven Rostedt
24320a05c769SSteven Rostedt    my @confs = keys %removed_configs;
24330a05c769SSteven Rostedt    if ($#confs >= 0) {
24340a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
24350a05c769SSteven Rostedt	foreach my $config (@confs) {
24360a05c769SSteven Rostedt	    doprint " $config\n";
24370a05c769SSteven Rostedt	}
24380a05c769SSteven Rostedt    }
24390a05c769SSteven Rostedt    @confs = keys %added_configs;
24400a05c769SSteven Rostedt    if ($#confs >= 0) {
24410a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
24420a05c769SSteven Rostedt	foreach my $config (@confs) {
24430a05c769SSteven Rostedt	    doprint " $config\n";
24440a05c769SSteven Rostedt	}
24450a05c769SSteven Rostedt    }
24460a05c769SSteven Rostedt
24470a05c769SSteven Rostedt    my %config_test;
24480a05c769SSteven Rostedt    my $once = 0;
24490a05c769SSteven Rostedt
24500a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
24510a05c769SSteven Rostedt    # that the config we autocreate has everything we need
24520a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
24530a05c769SSteven Rostedt    # may not be able to create a new config.
24540a05c769SSteven Rostedt    # Here we create a config with everything set.
24550a05c769SSteven Rostedt    create_config (keys %config_list);
24560a05c769SSteven Rostedt    read_current_config \%config_test;
24570a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
24580a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
24590a05c769SSteven Rostedt	    if (!$once) {
24600a05c769SSteven Rostedt		$once = 1;
24610a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
24620a05c769SSteven Rostedt	    }
24630a05c769SSteven Rostedt	    doprint "  $config\n";
24640a05c769SSteven Rostedt	    delete $config_list{$config};
24650a05c769SSteven Rostedt	}
24660a05c769SSteven Rostedt    }
24670a05c769SSteven Rostedt    my $ret;
24680a05c769SSteven Rostedt    do {
24690a05c769SSteven Rostedt	$ret = run_config_bisect;
24700a05c769SSteven Rostedt    } while (!$ret);
24710a05c769SSteven Rostedt
24720a05c769SSteven Rostedt    return $ret if ($ret < 0);
24735f9b6cedSSteven Rostedt
24745f9b6cedSSteven Rostedt    success $i;
24755f9b6cedSSteven Rostedt}
24765f9b6cedSSteven Rostedt
247727d934b2SSteven Rostedtsub patchcheck_reboot {
247827d934b2SSteven Rostedt    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
24792728be41SAndrew Jones    reboot $patchcheck_sleep_time;
248027d934b2SSteven Rostedt}
248127d934b2SSteven Rostedt
24826c5ee0beSSteven Rostedtsub patchcheck {
24836c5ee0beSSteven Rostedt    my ($i) = @_;
24846c5ee0beSSteven Rostedt
24856c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
24866c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_START[$i]"}));
24876c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
24886c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
24896c5ee0beSSteven Rostedt
24906c5ee0beSSteven Rostedt    my $start = $opt{"PATCHCHECK_START[$i]"};
24916c5ee0beSSteven Rostedt
24926c5ee0beSSteven Rostedt    my $end = "HEAD";
24936c5ee0beSSteven Rostedt    if (defined($opt{"PATCHCHECK_END[$i]"})) {
24946c5ee0beSSteven Rostedt	$end = $opt{"PATCHCHECK_END[$i]"};
24956c5ee0beSSteven Rostedt    }
24966c5ee0beSSteven Rostedt
2497a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
2498a57419b3SSteven Rostedt    $start = get_sha1($start);
2499a57419b3SSteven Rostedt    $end = get_sha1($end);
2500a57419b3SSteven Rostedt
25016c5ee0beSSteven Rostedt    my $type = $opt{"PATCHCHECK_TYPE[$i]"};
25026c5ee0beSSteven Rostedt
25036c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
25046c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
25056c5ee0beSSteven Rostedt	$type = "boot";
25066c5ee0beSSteven Rostedt    }
25076c5ee0beSSteven Rostedt
25086c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
25096c5ee0beSSteven Rostedt	dodie "could not get git list";
25106c5ee0beSSteven Rostedt
25116c5ee0beSSteven Rostedt    my @list;
25126c5ee0beSSteven Rostedt
25136c5ee0beSSteven Rostedt    while (<IN>) {
25146c5ee0beSSteven Rostedt	chomp;
25156c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
25166c5ee0beSSteven Rostedt	last if (/^$start/);
25176c5ee0beSSteven Rostedt    }
25186c5ee0beSSteven Rostedt    close(IN);
25196c5ee0beSSteven Rostedt
25206c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
25212b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
25226c5ee0beSSteven Rostedt    }
25236c5ee0beSSteven Rostedt
25246c5ee0beSSteven Rostedt    # go backwards in the list
25256c5ee0beSSteven Rostedt    @list = reverse @list;
25266c5ee0beSSteven Rostedt
25276c5ee0beSSteven Rostedt    my $save_clean = $noclean;
25281990207dSSteven Rostedt    my %ignored_warnings;
25291990207dSSteven Rostedt
25301990207dSSteven Rostedt    if (defined($ignore_warnings)) {
25311990207dSSteven Rostedt	foreach my $sha1 (split /\s+/, $ignore_warnings) {
25321990207dSSteven Rostedt	    $ignored_warnings{$sha1} = 1;
25331990207dSSteven Rostedt	}
25341990207dSSteven Rostedt    }
25356c5ee0beSSteven Rostedt
25366c5ee0beSSteven Rostedt    $in_patchcheck = 1;
25376c5ee0beSSteven Rostedt    foreach my $item (@list) {
25386c5ee0beSSteven Rostedt	my $sha1 = $item;
25396c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
25406c5ee0beSSteven Rostedt
25416c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
25426c5ee0beSSteven Rostedt
25436c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
25446c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
25456c5ee0beSSteven Rostedt
25466c5ee0beSSteven Rostedt	# only clean on the first and last patch
25476c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
25486c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
25496c5ee0beSSteven Rostedt	    $noclean = $save_clean;
25506c5ee0beSSteven Rostedt	} else {
25516c5ee0beSSteven Rostedt	    $noclean = 1;
25526c5ee0beSSteven Rostedt	}
25536c5ee0beSSteven Rostedt
25546c5ee0beSSteven Rostedt	if (defined($minconfig)) {
25552b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
25566c5ee0beSSteven Rostedt	} else {
25576c5ee0beSSteven Rostedt	    # ?? no config to use?
25582b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
25596c5ee0beSSteven Rostedt	}
25606c5ee0beSSteven Rostedt
25611990207dSSteven Rostedt
25621990207dSSteven Rostedt	if (!defined($ignored_warnings{$sha1})) {
25632b7d9b21SSteven Rostedt	    check_buildlog $sha1 or return 0;
25641990207dSSteven Rostedt	}
25656c5ee0beSSteven Rostedt
25666c5ee0beSSteven Rostedt	next if ($type eq "build");
25676c5ee0beSSteven Rostedt
25687faafbd6SSteven Rostedt	my $failed = 0;
25697faafbd6SSteven Rostedt
2570ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
25717faafbd6SSteven Rostedt
25727faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
25737faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
25747faafbd6SSteven Rostedt	}
25757faafbd6SSteven Rostedt	end_monitor;
25767faafbd6SSteven Rostedt	return 0 if ($failed);
25777faafbd6SSteven Rostedt
257827d934b2SSteven Rostedt	patchcheck_reboot;
257927d934b2SSteven Rostedt
25806c5ee0beSSteven Rostedt    }
25816c5ee0beSSteven Rostedt    $in_patchcheck = 0;
25826c5ee0beSSteven Rostedt    success $i;
25832b7d9b21SSteven Rostedt
25842b7d9b21SSteven Rostedt    return 1;
25856c5ee0beSSteven Rostedt}
25866c5ee0beSSteven Rostedt
2587b9066f6cSSteven Rostedtmy %depends;
2588ac6974c7SSteven Rostedtmy %depcount;
2589b9066f6cSSteven Rostedtmy $iflevel = 0;
2590b9066f6cSSteven Rostedtmy @ifdeps;
2591b9066f6cSSteven Rostedt
2592b9066f6cSSteven Rostedt# prevent recursion
2593b9066f6cSSteven Rostedtmy %read_kconfigs;
2594b9066f6cSSteven Rostedt
2595ac6974c7SSteven Rostedtsub add_dep {
2596ac6974c7SSteven Rostedt    # $config depends on $dep
2597ac6974c7SSteven Rostedt    my ($config, $dep) = @_;
2598ac6974c7SSteven Rostedt
2599ac6974c7SSteven Rostedt    if (defined($depends{$config})) {
2600ac6974c7SSteven Rostedt	$depends{$config} .= " " . $dep;
2601ac6974c7SSteven Rostedt    } else {
2602ac6974c7SSteven Rostedt	$depends{$config} = $dep;
2603ac6974c7SSteven Rostedt    }
2604ac6974c7SSteven Rostedt
2605ac6974c7SSteven Rostedt    # record the number of configs depending on $dep
2606ac6974c7SSteven Rostedt    if (defined $depcount{$dep}) {
2607ac6974c7SSteven Rostedt	$depcount{$dep}++;
2608ac6974c7SSteven Rostedt    } else {
2609ac6974c7SSteven Rostedt	$depcount{$dep} = 1;
2610ac6974c7SSteven Rostedt    }
2611ac6974c7SSteven Rostedt}
2612ac6974c7SSteven Rostedt
2613b9066f6cSSteven Rostedt# taken from streamline_config.pl
2614b9066f6cSSteven Rostedtsub read_kconfig {
2615b9066f6cSSteven Rostedt    my ($kconfig) = @_;
2616b9066f6cSSteven Rostedt
2617b9066f6cSSteven Rostedt    my $state = "NONE";
2618b9066f6cSSteven Rostedt    my $config;
2619b9066f6cSSteven Rostedt    my @kconfigs;
2620b9066f6cSSteven Rostedt
2621b9066f6cSSteven Rostedt    my $cont = 0;
2622b9066f6cSSteven Rostedt    my $line;
2623b9066f6cSSteven Rostedt
2624b9066f6cSSteven Rostedt
2625b9066f6cSSteven Rostedt    if (! -f $kconfig) {
2626b9066f6cSSteven Rostedt	doprint "file $kconfig does not exist, skipping\n";
2627b9066f6cSSteven Rostedt	return;
2628b9066f6cSSteven Rostedt    }
2629b9066f6cSSteven Rostedt
2630b9066f6cSSteven Rostedt    open(KIN, "$kconfig")
2631b9066f6cSSteven Rostedt	or die "Can't open $kconfig";
2632b9066f6cSSteven Rostedt    while (<KIN>) {
2633b9066f6cSSteven Rostedt	chomp;
2634b9066f6cSSteven Rostedt
2635b9066f6cSSteven Rostedt	# Make sure that lines ending with \ continue
2636b9066f6cSSteven Rostedt	if ($cont) {
2637b9066f6cSSteven Rostedt	    $_ = $line . " " . $_;
2638b9066f6cSSteven Rostedt	}
2639b9066f6cSSteven Rostedt
2640b9066f6cSSteven Rostedt	if (s/\\$//) {
2641b9066f6cSSteven Rostedt	    $cont = 1;
2642b9066f6cSSteven Rostedt	    $line = $_;
2643b9066f6cSSteven Rostedt	    next;
2644b9066f6cSSteven Rostedt	}
2645b9066f6cSSteven Rostedt
2646b9066f6cSSteven Rostedt	$cont = 0;
2647b9066f6cSSteven Rostedt
2648b9066f6cSSteven Rostedt	# collect any Kconfig sources
2649b9066f6cSSteven Rostedt	if (/^source\s*"(.*)"/) {
2650b9066f6cSSteven Rostedt	    $kconfigs[$#kconfigs+1] = $1;
2651b9066f6cSSteven Rostedt	}
2652b9066f6cSSteven Rostedt
2653b9066f6cSSteven Rostedt	# configs found
2654b9066f6cSSteven Rostedt	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
2655b9066f6cSSteven Rostedt	    $state = "NEW";
2656b9066f6cSSteven Rostedt	    $config = $2;
2657b9066f6cSSteven Rostedt
2658b9066f6cSSteven Rostedt	    for (my $i = 0; $i < $iflevel; $i++) {
2659ac6974c7SSteven Rostedt		add_dep $config, $ifdeps[$i];
2660b9066f6cSSteven Rostedt	    }
2661b9066f6cSSteven Rostedt
2662b9066f6cSSteven Rostedt	# collect the depends for the config
2663b9066f6cSSteven Rostedt	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
2664b9066f6cSSteven Rostedt
2665ac6974c7SSteven Rostedt	    add_dep $config, $1;
2666b9066f6cSSteven Rostedt
2667b9066f6cSSteven Rostedt	# Get the configs that select this config
2668ac6974c7SSteven Rostedt	} elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
2669ac6974c7SSteven Rostedt
2670ac6974c7SSteven Rostedt	    # selected by depends on config
2671ac6974c7SSteven Rostedt	    add_dep $1, $config;
2672b9066f6cSSteven Rostedt
2673b9066f6cSSteven Rostedt	# Check for if statements
2674b9066f6cSSteven Rostedt	} elsif (/^if\s+(.*\S)\s*$/) {
2675b9066f6cSSteven Rostedt	    my $deps = $1;
2676b9066f6cSSteven Rostedt	    # remove beginning and ending non text
2677b9066f6cSSteven Rostedt	    $deps =~ s/^[^a-zA-Z0-9_]*//;
2678b9066f6cSSteven Rostedt	    $deps =~ s/[^a-zA-Z0-9_]*$//;
2679b9066f6cSSteven Rostedt
2680b9066f6cSSteven Rostedt	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
2681b9066f6cSSteven Rostedt
2682b9066f6cSSteven Rostedt	    $ifdeps[$iflevel++] = join ':', @deps;
2683b9066f6cSSteven Rostedt
2684b9066f6cSSteven Rostedt	} elsif (/^endif/) {
2685b9066f6cSSteven Rostedt
2686b9066f6cSSteven Rostedt	    $iflevel-- if ($iflevel);
2687b9066f6cSSteven Rostedt
2688b9066f6cSSteven Rostedt	# stop on "help"
2689b9066f6cSSteven Rostedt	} elsif (/^\s*help\s*$/) {
2690b9066f6cSSteven Rostedt	    $state = "NONE";
2691b9066f6cSSteven Rostedt	}
2692b9066f6cSSteven Rostedt    }
2693b9066f6cSSteven Rostedt    close(KIN);
2694b9066f6cSSteven Rostedt
2695b9066f6cSSteven Rostedt    # read in any configs that were found.
2696b9066f6cSSteven Rostedt    foreach $kconfig (@kconfigs) {
2697b9066f6cSSteven Rostedt	if (!defined($read_kconfigs{$kconfig})) {
2698b9066f6cSSteven Rostedt	    $read_kconfigs{$kconfig} = 1;
2699b9066f6cSSteven Rostedt	    read_kconfig("$builddir/$kconfig");
2700b9066f6cSSteven Rostedt	}
2701b9066f6cSSteven Rostedt    }
2702b9066f6cSSteven Rostedt}
2703b9066f6cSSteven Rostedt
2704b9066f6cSSteven Rostedtsub read_depends {
2705b9066f6cSSteven Rostedt    # find out which arch this is by the kconfig file
2706b9066f6cSSteven Rostedt    open (IN, $output_config)
2707b9066f6cSSteven Rostedt	or dodie "Failed to read $output_config";
2708b9066f6cSSteven Rostedt    my $arch;
2709b9066f6cSSteven Rostedt    while (<IN>) {
2710b9066f6cSSteven Rostedt	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
2711b9066f6cSSteven Rostedt	    $arch = $1;
2712b9066f6cSSteven Rostedt	    last;
2713b9066f6cSSteven Rostedt	}
2714b9066f6cSSteven Rostedt    }
2715b9066f6cSSteven Rostedt    close IN;
2716b9066f6cSSteven Rostedt
2717b9066f6cSSteven Rostedt    if (!defined($arch)) {
2718b9066f6cSSteven Rostedt	doprint "Could not find arch from config file\n";
2719b9066f6cSSteven Rostedt	doprint "no dependencies used\n";
2720b9066f6cSSteven Rostedt	return;
2721b9066f6cSSteven Rostedt    }
2722b9066f6cSSteven Rostedt
2723b9066f6cSSteven Rostedt    # arch is really the subarch, we need to know
2724b9066f6cSSteven Rostedt    # what directory to look at.
2725b9066f6cSSteven Rostedt    if ($arch eq "i386" || $arch eq "x86_64") {
2726b9066f6cSSteven Rostedt	$arch = "x86";
2727b9066f6cSSteven Rostedt    } elsif ($arch =~ /^tile/) {
2728b9066f6cSSteven Rostedt	$arch = "tile";
2729b9066f6cSSteven Rostedt    }
2730b9066f6cSSteven Rostedt
2731b9066f6cSSteven Rostedt    my $kconfig = "$builddir/arch/$arch/Kconfig";
2732b9066f6cSSteven Rostedt
2733b9066f6cSSteven Rostedt    if (! -f $kconfig && $arch =~ /\d$/) {
2734b9066f6cSSteven Rostedt	my $orig = $arch;
2735b9066f6cSSteven Rostedt 	# some subarchs have numbers, truncate them
2736b9066f6cSSteven Rostedt	$arch =~ s/\d*$//;
2737b9066f6cSSteven Rostedt	$kconfig = "$builddir/arch/$arch/Kconfig";
2738b9066f6cSSteven Rostedt	if (! -f $kconfig) {
2739b9066f6cSSteven Rostedt	    doprint "No idea what arch dir $orig is for\n";
2740b9066f6cSSteven Rostedt	    doprint "no dependencies used\n";
2741b9066f6cSSteven Rostedt	    return;
2742b9066f6cSSteven Rostedt	}
2743b9066f6cSSteven Rostedt    }
2744b9066f6cSSteven Rostedt
2745b9066f6cSSteven Rostedt    read_kconfig($kconfig);
2746b9066f6cSSteven Rostedt}
2747b9066f6cSSteven Rostedt
27484c4ab120SSteven Rostedtsub read_config_list {
27494c4ab120SSteven Rostedt    my ($config) = @_;
27504c4ab120SSteven Rostedt
27514c4ab120SSteven Rostedt    open (IN, $config)
27524c4ab120SSteven Rostedt	or dodie "Failed to read $config";
27534c4ab120SSteven Rostedt
27544c4ab120SSteven Rostedt    while (<IN>) {
27554c4ab120SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
27564c4ab120SSteven Rostedt	    if (!defined($config_ignore{$2})) {
27574c4ab120SSteven Rostedt		$config_list{$2} = $1;
27584c4ab120SSteven Rostedt	    }
27594c4ab120SSteven Rostedt	}
27604c4ab120SSteven Rostedt    }
27614c4ab120SSteven Rostedt
27624c4ab120SSteven Rostedt    close(IN);
27634c4ab120SSteven Rostedt}
27644c4ab120SSteven Rostedt
27654c4ab120SSteven Rostedtsub read_output_config {
27664c4ab120SSteven Rostedt    my ($config) = @_;
27674c4ab120SSteven Rostedt
27684c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
27694c4ab120SSteven Rostedt}
27704c4ab120SSteven Rostedt
27714c4ab120SSteven Rostedtsub make_new_config {
27724c4ab120SSteven Rostedt    my @configs = @_;
27734c4ab120SSteven Rostedt
27744c4ab120SSteven Rostedt    open (OUT, ">$output_config")
27754c4ab120SSteven Rostedt	or dodie "Failed to write $output_config";
27764c4ab120SSteven Rostedt
27774c4ab120SSteven Rostedt    foreach my $config (@configs) {
27784c4ab120SSteven Rostedt	print OUT "$config\n";
27794c4ab120SSteven Rostedt    }
27804c4ab120SSteven Rostedt    close OUT;
27814c4ab120SSteven Rostedt}
27824c4ab120SSteven Rostedt
2783ac6974c7SSteven Rostedtsub chomp_config {
2784ac6974c7SSteven Rostedt    my ($config) = @_;
2785ac6974c7SSteven Rostedt
2786ac6974c7SSteven Rostedt    $config =~ s/CONFIG_//;
2787ac6974c7SSteven Rostedt
2788ac6974c7SSteven Rostedt    return $config;
2789ac6974c7SSteven Rostedt}
2790ac6974c7SSteven Rostedt
2791b9066f6cSSteven Rostedtsub get_depends {
2792b9066f6cSSteven Rostedt    my ($dep) = @_;
2793b9066f6cSSteven Rostedt
2794ac6974c7SSteven Rostedt    my $kconfig = chomp_config $dep;
2795b9066f6cSSteven Rostedt
2796b9066f6cSSteven Rostedt    $dep = $depends{"$kconfig"};
2797b9066f6cSSteven Rostedt
2798b9066f6cSSteven Rostedt    # the dep string we have saves the dependencies as they
2799b9066f6cSSteven Rostedt    # were found, including expressions like ! && ||. We
2800b9066f6cSSteven Rostedt    # want to split this out into just an array of configs.
2801b9066f6cSSteven Rostedt
2802b9066f6cSSteven Rostedt    my $valid = "A-Za-z_0-9";
2803b9066f6cSSteven Rostedt
2804b9066f6cSSteven Rostedt    my @configs;
2805b9066f6cSSteven Rostedt
2806b9066f6cSSteven Rostedt    while ($dep =~ /[$valid]/) {
2807b9066f6cSSteven Rostedt
2808b9066f6cSSteven Rostedt	if ($dep =~ /^[^$valid]*([$valid]+)/) {
2809b9066f6cSSteven Rostedt	    my $conf = "CONFIG_" . $1;
2810b9066f6cSSteven Rostedt
2811b9066f6cSSteven Rostedt	    $configs[$#configs + 1] = $conf;
2812b9066f6cSSteven Rostedt
2813b9066f6cSSteven Rostedt	    $dep =~ s/^[^$valid]*[$valid]+//;
2814b9066f6cSSteven Rostedt	} else {
2815b9066f6cSSteven Rostedt	    die "this should never happen";
2816b9066f6cSSteven Rostedt	}
2817b9066f6cSSteven Rostedt    }
2818b9066f6cSSteven Rostedt
2819b9066f6cSSteven Rostedt    return @configs;
2820b9066f6cSSteven Rostedt}
2821b9066f6cSSteven Rostedt
2822b9066f6cSSteven Rostedtmy %min_configs;
2823b9066f6cSSteven Rostedtmy %keep_configs;
282443d1b651SSteven Rostedtmy %save_configs;
2825b9066f6cSSteven Rostedtmy %processed_configs;
2826b9066f6cSSteven Rostedtmy %nochange_config;
2827b9066f6cSSteven Rostedt
2828b9066f6cSSteven Rostedtsub test_this_config {
2829b9066f6cSSteven Rostedt    my ($config) = @_;
2830b9066f6cSSteven Rostedt
2831b9066f6cSSteven Rostedt    my $found;
2832b9066f6cSSteven Rostedt
2833b9066f6cSSteven Rostedt    # if we already processed this config, skip it
2834b9066f6cSSteven Rostedt    if (defined($processed_configs{$config})) {
2835b9066f6cSSteven Rostedt	return undef;
2836b9066f6cSSteven Rostedt    }
2837b9066f6cSSteven Rostedt    $processed_configs{$config} = 1;
2838b9066f6cSSteven Rostedt
2839b9066f6cSSteven Rostedt    # if this config failed during this round, skip it
2840b9066f6cSSteven Rostedt    if (defined($nochange_config{$config})) {
2841b9066f6cSSteven Rostedt	return undef;
2842b9066f6cSSteven Rostedt    }
2843b9066f6cSSteven Rostedt
2844ac6974c7SSteven Rostedt    my $kconfig = chomp_config $config;
2845b9066f6cSSteven Rostedt
2846b9066f6cSSteven Rostedt    # Test dependencies first
2847b9066f6cSSteven Rostedt    if (defined($depends{"$kconfig"})) {
2848b9066f6cSSteven Rostedt	my @parents = get_depends $config;
2849b9066f6cSSteven Rostedt	foreach my $parent (@parents) {
2850b9066f6cSSteven Rostedt	    # if the parent is in the min config, check it first
2851b9066f6cSSteven Rostedt	    next if (!defined($min_configs{$parent}));
2852b9066f6cSSteven Rostedt	    $found = test_this_config($parent);
2853b9066f6cSSteven Rostedt	    if (defined($found)) {
2854b9066f6cSSteven Rostedt		return $found;
2855b9066f6cSSteven Rostedt	    }
2856b9066f6cSSteven Rostedt	}
2857b9066f6cSSteven Rostedt    }
2858b9066f6cSSteven Rostedt
2859b9066f6cSSteven Rostedt    # Remove this config from the list of configs
2860b9066f6cSSteven Rostedt    # do a make oldnoconfig and then read the resulting
2861b9066f6cSSteven Rostedt    # .config to make sure it is missing the config that
2862b9066f6cSSteven Rostedt    # we had before
2863b9066f6cSSteven Rostedt    my %configs = %min_configs;
2864b9066f6cSSteven Rostedt    delete $configs{$config};
2865b9066f6cSSteven Rostedt    make_new_config ((values %configs), (values %keep_configs));
2866b9066f6cSSteven Rostedt    make_oldconfig;
2867b9066f6cSSteven Rostedt    undef %configs;
2868b9066f6cSSteven Rostedt    assign_configs \%configs, $output_config;
2869b9066f6cSSteven Rostedt
2870b9066f6cSSteven Rostedt    return $config if (!defined($configs{$config}));
2871b9066f6cSSteven Rostedt
2872b9066f6cSSteven Rostedt    doprint "disabling config $config did not change .config\n";
2873b9066f6cSSteven Rostedt
2874b9066f6cSSteven Rostedt    $nochange_config{$config} = 1;
2875b9066f6cSSteven Rostedt
2876b9066f6cSSteven Rostedt    return undef;
2877b9066f6cSSteven Rostedt}
2878b9066f6cSSteven Rostedt
28794c4ab120SSteven Rostedtsub make_min_config {
28804c4ab120SSteven Rostedt    my ($i) = @_;
28814c4ab120SSteven Rostedt
28824c4ab120SSteven Rostedt    if (!defined($output_minconfig)) {
28834c4ab120SSteven Rostedt	fail "OUTPUT_MIN_CONFIG not defined" and return;
28844c4ab120SSteven Rostedt    }
288535ce5952SSteven Rostedt
288635ce5952SSteven Rostedt    # If output_minconfig exists, and the start_minconfig
288735ce5952SSteven Rostedt    # came from min_config, than ask if we should use
288835ce5952SSteven Rostedt    # that instead.
288935ce5952SSteven Rostedt    if (-f $output_minconfig && !$start_minconfig_defined) {
289035ce5952SSteven Rostedt	print "$output_minconfig exists\n";
289135ce5952SSteven Rostedt	if (read_yn " Use it as minconfig?") {
289235ce5952SSteven Rostedt	    $start_minconfig = $output_minconfig;
289335ce5952SSteven Rostedt	}
289435ce5952SSteven Rostedt    }
289535ce5952SSteven Rostedt
28964c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
28974c4ab120SSteven Rostedt	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
28984c4ab120SSteven Rostedt    }
28994c4ab120SSteven Rostedt
290035ce5952SSteven Rostedt    my $temp_config = "$tmpdir/temp_config";
290135ce5952SSteven Rostedt
29024c4ab120SSteven Rostedt    # First things first. We build an allnoconfig to find
29034c4ab120SSteven Rostedt    # out what the defaults are that we can't touch.
29044c4ab120SSteven Rostedt    # Some are selections, but we really can't handle selections.
29054c4ab120SSteven Rostedt
29064c4ab120SSteven Rostedt    my $save_minconfig = $minconfig;
29074c4ab120SSteven Rostedt    undef $minconfig;
29084c4ab120SSteven Rostedt
29094c4ab120SSteven Rostedt    run_command "$make allnoconfig" or return 0;
29104c4ab120SSteven Rostedt
2911b9066f6cSSteven Rostedt    read_depends;
2912b9066f6cSSteven Rostedt
29134c4ab120SSteven Rostedt    process_config_ignore $output_config;
2914b9066f6cSSteven Rostedt
291543d1b651SSteven Rostedt    undef %save_configs;
2916b9066f6cSSteven Rostedt    undef %min_configs;
29174c4ab120SSteven Rostedt
29184c4ab120SSteven Rostedt    if (defined($ignore_config)) {
29194c4ab120SSteven Rostedt	# make sure the file exists
29204c4ab120SSteven Rostedt	`touch $ignore_config`;
292143d1b651SSteven Rostedt	assign_configs \%save_configs, $ignore_config;
29224c4ab120SSteven Rostedt    }
29234c4ab120SSteven Rostedt
292443d1b651SSteven Rostedt    %keep_configs = %save_configs;
292543d1b651SSteven Rostedt
29264c4ab120SSteven Rostedt    doprint "Load initial configs from $start_minconfig\n";
29274c4ab120SSteven Rostedt
29284c4ab120SSteven Rostedt    # Look at the current min configs, and save off all the
29294c4ab120SSteven Rostedt    # ones that were set via the allnoconfig
29304c4ab120SSteven Rostedt    assign_configs \%min_configs, $start_minconfig;
29314c4ab120SSteven Rostedt
29324c4ab120SSteven Rostedt    my @config_keys = keys %min_configs;
29334c4ab120SSteven Rostedt
2934ac6974c7SSteven Rostedt    # All configs need a depcount
2935ac6974c7SSteven Rostedt    foreach my $config (@config_keys) {
2936ac6974c7SSteven Rostedt	my $kconfig = chomp_config $config;
2937ac6974c7SSteven Rostedt	if (!defined $depcount{$kconfig}) {
2938ac6974c7SSteven Rostedt		$depcount{$kconfig} = 0;
2939ac6974c7SSteven Rostedt	}
2940ac6974c7SSteven Rostedt    }
2941ac6974c7SSteven Rostedt
29424c4ab120SSteven Rostedt    # Remove anything that was set by the make allnoconfig
29434c4ab120SSteven Rostedt    # we shouldn't need them as they get set for us anyway.
29444c4ab120SSteven Rostedt    foreach my $config (@config_keys) {
29454c4ab120SSteven Rostedt	# Remove anything in the ignore_config
29464c4ab120SSteven Rostedt	if (defined($keep_configs{$config})) {
29474c4ab120SSteven Rostedt	    my $file = $ignore_config;
29484c4ab120SSteven Rostedt	    $file =~ s,.*/(.*?)$,$1,;
29494c4ab120SSteven Rostedt	    doprint "$config set by $file ... ignored\n";
29504c4ab120SSteven Rostedt	    delete $min_configs{$config};
29514c4ab120SSteven Rostedt	    next;
29524c4ab120SSteven Rostedt	}
29534c4ab120SSteven Rostedt	# But make sure the settings are the same. If a min config
29544c4ab120SSteven Rostedt	# sets a selection, we do not want to get rid of it if
29554c4ab120SSteven Rostedt	# it is not the same as what we have. Just move it into
29564c4ab120SSteven Rostedt	# the keep configs.
29574c4ab120SSteven Rostedt	if (defined($config_ignore{$config})) {
29584c4ab120SSteven Rostedt	    if ($config_ignore{$config} ne $min_configs{$config}) {
29594c4ab120SSteven Rostedt		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
29604c4ab120SSteven Rostedt		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
29614c4ab120SSteven Rostedt		$keep_configs{$config} = $min_configs{$config};
29624c4ab120SSteven Rostedt	    } else {
29634c4ab120SSteven Rostedt		doprint "$config set by allnoconfig ... ignored\n";
29644c4ab120SSteven Rostedt	    }
29654c4ab120SSteven Rostedt	    delete $min_configs{$config};
29664c4ab120SSteven Rostedt	}
29674c4ab120SSteven Rostedt    }
29684c4ab120SSteven Rostedt
29694c4ab120SSteven Rostedt    my $done = 0;
2970b9066f6cSSteven Rostedt    my $take_two = 0;
29714c4ab120SSteven Rostedt
29724c4ab120SSteven Rostedt    while (!$done) {
29734c4ab120SSteven Rostedt
29744c4ab120SSteven Rostedt	my $config;
29754c4ab120SSteven Rostedt	my $found;
29764c4ab120SSteven Rostedt
29774c4ab120SSteven Rostedt	# Now disable each config one by one and do a make oldconfig
29784c4ab120SSteven Rostedt	# till we find a config that changes our list.
29794c4ab120SSteven Rostedt
29804c4ab120SSteven Rostedt	my @test_configs = keys %min_configs;
2981ac6974c7SSteven Rostedt
2982ac6974c7SSteven Rostedt	# Sort keys by who is most dependent on
2983ac6974c7SSteven Rostedt	@test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
2984ac6974c7SSteven Rostedt			  @test_configs ;
2985ac6974c7SSteven Rostedt
2986ac6974c7SSteven Rostedt	# Put configs that did not modify the config at the end.
29874c4ab120SSteven Rostedt	my $reset = 1;
29884c4ab120SSteven Rostedt	for (my $i = 0; $i < $#test_configs; $i++) {
29894c4ab120SSteven Rostedt	    if (!defined($nochange_config{$test_configs[0]})) {
29904c4ab120SSteven Rostedt		$reset = 0;
29914c4ab120SSteven Rostedt		last;
29924c4ab120SSteven Rostedt	    }
29934c4ab120SSteven Rostedt	    # This config didn't change the .config last time.
29944c4ab120SSteven Rostedt	    # Place it at the end
29954c4ab120SSteven Rostedt	    my $config = shift @test_configs;
29964c4ab120SSteven Rostedt	    push @test_configs, $config;
29974c4ab120SSteven Rostedt	}
29984c4ab120SSteven Rostedt
29994c4ab120SSteven Rostedt	# if every test config has failed to modify the .config file
30004c4ab120SSteven Rostedt	# in the past, then reset and start over.
30014c4ab120SSteven Rostedt	if ($reset) {
30024c4ab120SSteven Rostedt	    undef %nochange_config;
30034c4ab120SSteven Rostedt	}
30044c4ab120SSteven Rostedt
3005b9066f6cSSteven Rostedt	undef %processed_configs;
3006b9066f6cSSteven Rostedt
30074c4ab120SSteven Rostedt	foreach my $config (@test_configs) {
30084c4ab120SSteven Rostedt
3009b9066f6cSSteven Rostedt	    $found = test_this_config $config;
30104c4ab120SSteven Rostedt
3011b9066f6cSSteven Rostedt	    last if (defined($found));
30124c4ab120SSteven Rostedt
30134c4ab120SSteven Rostedt	    # oh well, try another config
30144c4ab120SSteven Rostedt	}
30154c4ab120SSteven Rostedt
30164c4ab120SSteven Rostedt	if (!defined($found)) {
3017b9066f6cSSteven Rostedt	    # we could have failed due to the nochange_config hash
3018b9066f6cSSteven Rostedt	    # reset and try again
3019b9066f6cSSteven Rostedt	    if (!$take_two) {
3020b9066f6cSSteven Rostedt		undef %nochange_config;
3021b9066f6cSSteven Rostedt		$take_two = 1;
3022b9066f6cSSteven Rostedt		next;
3023b9066f6cSSteven Rostedt	    }
30244c4ab120SSteven Rostedt	    doprint "No more configs found that we can disable\n";
30254c4ab120SSteven Rostedt	    $done = 1;
30264c4ab120SSteven Rostedt	    last;
30274c4ab120SSteven Rostedt	}
3028b9066f6cSSteven Rostedt	$take_two = 0;
30294c4ab120SSteven Rostedt
30304c4ab120SSteven Rostedt	$config = $found;
30314c4ab120SSteven Rostedt
30324c4ab120SSteven Rostedt	doprint "Test with $config disabled\n";
30334c4ab120SSteven Rostedt
30344c4ab120SSteven Rostedt	# set in_bisect to keep build and monitor from dieing
30354c4ab120SSteven Rostedt	$in_bisect = 1;
30364c4ab120SSteven Rostedt
30374c4ab120SSteven Rostedt	my $failed = 0;
30384c4ab120SSteven Rostedt	build "oldconfig";
30394c4ab120SSteven Rostedt	start_monitor_and_boot or $failed = 1;
30404c4ab120SSteven Rostedt	end_monitor;
30414c4ab120SSteven Rostedt
30424c4ab120SSteven Rostedt	$in_bisect = 0;
30434c4ab120SSteven Rostedt
30444c4ab120SSteven Rostedt	if ($failed) {
3045b9066f6cSSteven Rostedt	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
30464c4ab120SSteven Rostedt	    # this config is needed, add it to the ignore list.
30474c4ab120SSteven Rostedt	    $keep_configs{$config} = $min_configs{$config};
304843d1b651SSteven Rostedt	    $save_configs{$config} = $min_configs{$config};
30494c4ab120SSteven Rostedt	    delete $min_configs{$config};
305035ce5952SSteven Rostedt
305135ce5952SSteven Rostedt	    # update new ignore configs
305235ce5952SSteven Rostedt	    if (defined($ignore_config)) {
305335ce5952SSteven Rostedt		open (OUT, ">$temp_config")
305435ce5952SSteven Rostedt		    or die "Can't write to $temp_config";
305543d1b651SSteven Rostedt		foreach my $config (keys %save_configs) {
305643d1b651SSteven Rostedt		    print OUT "$save_configs{$config}\n";
305735ce5952SSteven Rostedt		}
305835ce5952SSteven Rostedt		close OUT;
305935ce5952SSteven Rostedt		run_command "mv $temp_config $ignore_config" or
306035ce5952SSteven Rostedt		    dodie "failed to copy update to $ignore_config";
306135ce5952SSteven Rostedt	    }
306235ce5952SSteven Rostedt
30634c4ab120SSteven Rostedt	} else {
30644c4ab120SSteven Rostedt	    # We booted without this config, remove it from the minconfigs.
30654c4ab120SSteven Rostedt	    doprint "$config is not needed, disabling\n";
30664c4ab120SSteven Rostedt
30674c4ab120SSteven Rostedt	    delete $min_configs{$config};
30684c4ab120SSteven Rostedt
30694c4ab120SSteven Rostedt	    # Also disable anything that is not enabled in this config
30704c4ab120SSteven Rostedt	    my %configs;
30714c4ab120SSteven Rostedt	    assign_configs \%configs, $output_config;
30724c4ab120SSteven Rostedt	    my @config_keys = keys %min_configs;
30734c4ab120SSteven Rostedt	    foreach my $config (@config_keys) {
30744c4ab120SSteven Rostedt		if (!defined($configs{$config})) {
30754c4ab120SSteven Rostedt		    doprint "$config is not set, disabling\n";
30764c4ab120SSteven Rostedt		    delete $min_configs{$config};
30774c4ab120SSteven Rostedt		}
30784c4ab120SSteven Rostedt	    }
30794c4ab120SSteven Rostedt
30804c4ab120SSteven Rostedt	    # Save off all the current mandidory configs
308135ce5952SSteven Rostedt	    open (OUT, ">$temp_config")
308235ce5952SSteven Rostedt		or die "Can't write to $temp_config";
30834c4ab120SSteven Rostedt	    foreach my $config (keys %keep_configs) {
30844c4ab120SSteven Rostedt		print OUT "$keep_configs{$config}\n";
30854c4ab120SSteven Rostedt	    }
30864c4ab120SSteven Rostedt	    foreach my $config (keys %min_configs) {
30874c4ab120SSteven Rostedt		print OUT "$min_configs{$config}\n";
30884c4ab120SSteven Rostedt	    }
30894c4ab120SSteven Rostedt	    close OUT;
309035ce5952SSteven Rostedt
309135ce5952SSteven Rostedt	    run_command "mv $temp_config $output_minconfig" or
309235ce5952SSteven Rostedt		dodie "failed to copy update to $output_minconfig";
30934c4ab120SSteven Rostedt	}
30944c4ab120SSteven Rostedt
30954c4ab120SSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
30962728be41SAndrew Jones	reboot $sleep_time;
30974c4ab120SSteven Rostedt    }
30984c4ab120SSteven Rostedt
30994c4ab120SSteven Rostedt    success $i;
31004c4ab120SSteven Rostedt    return 1;
31014c4ab120SSteven Rostedt}
31024c4ab120SSteven Rostedt
31038d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
31042545eb61SSteven Rostedt
31058d1491baSSteven Rostedtif ($#ARGV == 0) {
31068d1491baSSteven Rostedt    $ktest_config = $ARGV[0];
31078d1491baSSteven Rostedt    if (! -f $ktest_config) {
31088d1491baSSteven Rostedt	print "$ktest_config does not exist.\n";
310935ce5952SSteven Rostedt	if (!read_yn "Create it?") {
31108d1491baSSteven Rostedt	    exit 0;
31118d1491baSSteven Rostedt	}
31128d1491baSSteven Rostedt    }
31138d1491baSSteven Rostedt} else {
31148d1491baSSteven Rostedt    $ktest_config = "ktest.conf";
31158d1491baSSteven Rostedt}
31168d1491baSSteven Rostedt
31178d1491baSSteven Rostedtif (! -f $ktest_config) {
3118dbd3783bSSteven Rostedt    $newconfig = 1;
3119c4261d0fSSteven Rostedt    get_test_case;
31208d1491baSSteven Rostedt    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
31218d1491baSSteven Rostedt    print OUT << "EOF"
31228d1491baSSteven Rostedt# Generated by ktest.pl
31238d1491baSSteven Rostedt#
31240e7a22deSSteven Rostedt
31250e7a22deSSteven Rostedt# PWD is a ktest.pl variable that will result in the process working
31260e7a22deSSteven Rostedt# directory that ktest.pl is executed in.
31270e7a22deSSteven Rostedt
31280e7a22deSSteven Rostedt# THIS_DIR is automatically assigned the PWD of the path that generated
31290e7a22deSSteven Rostedt# the config file. It is best to use this variable when assigning other
31300e7a22deSSteven Rostedt# directory paths within this directory. This allows you to easily
31310e7a22deSSteven Rostedt# move the test cases to other locations or to other machines.
31320e7a22deSSteven Rostedt#
31330e7a22deSSteven RostedtTHIS_DIR := $variable{"PWD"}
31340e7a22deSSteven Rostedt
31358d1491baSSteven Rostedt# Define each test with TEST_START
31368d1491baSSteven Rostedt# The config options below it will override the defaults
31378d1491baSSteven RostedtTEST_START
3138c4261d0fSSteven RostedtTEST_TYPE = $default{"TEST_TYPE"}
31398d1491baSSteven Rostedt
31408d1491baSSteven RostedtDEFAULTS
31418d1491baSSteven RostedtEOF
31428d1491baSSteven Rostedt;
31438d1491baSSteven Rostedt    close(OUT);
31448d1491baSSteven Rostedt}
31458d1491baSSteven Rostedtread_config $ktest_config;
31468d1491baSSteven Rostedt
314723715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) {
314823715c3cSSteven Rostedt    $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
314923715c3cSSteven Rostedt}
315023715c3cSSteven Rostedt
31518d1491baSSteven Rostedt# Append any configs entered in manually to the config file.
31528d1491baSSteven Rostedtmy @new_configs = keys %entered_configs;
31538d1491baSSteven Rostedtif ($#new_configs >= 0) {
31548d1491baSSteven Rostedt    print "\nAppending entered in configs to $ktest_config\n";
31558d1491baSSteven Rostedt    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
31568d1491baSSteven Rostedt    foreach my $config (@new_configs) {
31578d1491baSSteven Rostedt	print OUT "$config = $entered_configs{$config}\n";
31580e7a22deSSteven Rostedt	$opt{$config} = process_variables($entered_configs{$config});
31598d1491baSSteven Rostedt    }
31608d1491baSSteven Rostedt}
31612545eb61SSteven Rostedt
31622b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
31632b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
31642b7d9b21SSteven Rostedt}
31652545eb61SSteven Rostedt
31662b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
31672b7d9b21SSteven Rostedt
3168a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
3169a57419b3SSteven Rostedt
3170a57419b3SSteven Rostedt    if (!$i) {
3171a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
3172a57419b3SSteven Rostedt    } else {
3173a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
3174a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
3175a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
3176a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
3177a57419b3SSteven Rostedt	}
3178a57419b3SSteven Rostedt	doprint "\n";
3179a57419b3SSteven Rostedt    }
3180a57419b3SSteven Rostedt
31812b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
3182a57419b3SSteven Rostedt
3183a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
3184a57419b3SSteven Rostedt	    next if ($i != $1);
3185a57419b3SSteven Rostedt	} else {
3186a57419b3SSteven Rostedt	    next if ($i);
3187a57419b3SSteven Rostedt	}
3188a57419b3SSteven Rostedt
31892b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
31902b7d9b21SSteven Rostedt    }
3191a57419b3SSteven Rostedt}
31922545eb61SSteven Rostedt
31932a62512bSSteven Rostedtsub __set_test_option {
31945a391fbfSSteven Rostedt    my ($name, $i) = @_;
31955a391fbfSSteven Rostedt
31965a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
31975a391fbfSSteven Rostedt
31985a391fbfSSteven Rostedt    if (defined($opt{$option})) {
31995a391fbfSSteven Rostedt	return $opt{$option};
32005a391fbfSSteven Rostedt    }
32015a391fbfSSteven Rostedt
3202a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
3203a57419b3SSteven Rostedt	if ($i >= $test &&
3204a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
3205a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
3206a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
3207a57419b3SSteven Rostedt		return $opt{$option};
3208a57419b3SSteven Rostedt	    }
3209a57419b3SSteven Rostedt	}
3210a57419b3SSteven Rostedt    }
3211a57419b3SSteven Rostedt
32125a391fbfSSteven Rostedt    if (defined($opt{$name})) {
32135a391fbfSSteven Rostedt	return $opt{$name};
32145a391fbfSSteven Rostedt    }
32155a391fbfSSteven Rostedt
32165a391fbfSSteven Rostedt    return undef;
32175a391fbfSSteven Rostedt}
32185a391fbfSSteven Rostedt
32192a62512bSSteven Rostedtsub set_test_option {
32202a62512bSSteven Rostedt    my ($name, $i) = @_;
32212a62512bSSteven Rostedt
32222a62512bSSteven Rostedt    my $option = __set_test_option($name, $i);
32232a62512bSSteven Rostedt    return $option if (!defined($option));
32242a62512bSSteven Rostedt
322523715c3cSSteven Rostedt    return eval_option($option, $i);
32262a62512bSSteven Rostedt}
32272a62512bSSteven Rostedt
32282545eb61SSteven Rostedt# First we need to do is the builds
3229a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
32302545eb61SSteven Rostedt
32314ab1cce5SSteven Rostedt    # Do not reboot on failing test options
32324ab1cce5SSteven Rostedt    $no_reboot = 1;
32334ab1cce5SSteven Rostedt
3234576f627cSSteven Rostedt    $iteration = $i;
3235576f627cSSteven Rostedt
3236a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
3237a75fececSSteven Rostedt
3238a75fececSSteven Rostedt    $machine = set_test_option("MACHINE", $i);
3239e48c5293SSteven Rostedt    $ssh_user = set_test_option("SSH_USER", $i);
3240a75fececSSteven Rostedt    $tmpdir = set_test_option("TMP_DIR", $i);
3241a75fececSSteven Rostedt    $outputdir = set_test_option("OUTPUT_DIR", $i);
3242a75fececSSteven Rostedt    $builddir = set_test_option("BUILD_DIR", $i);
3243a75fececSSteven Rostedt    $test_type = set_test_option("TEST_TYPE", $i);
3244a75fececSSteven Rostedt    $build_type = set_test_option("BUILD_TYPE", $i);
3245a75fececSSteven Rostedt    $build_options = set_test_option("BUILD_OPTIONS", $i);
32460bd6c1a3SSteven Rostedt    $pre_build = set_test_option("PRE_BUILD", $i);
32470bd6c1a3SSteven Rostedt    $post_build = set_test_option("POST_BUILD", $i);
32480bd6c1a3SSteven Rostedt    $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
32490bd6c1a3SSteven Rostedt    $post_build_die = set_test_option("POST_BUILD_DIE", $i);
3250a75fececSSteven Rostedt    $power_cycle = set_test_option("POWER_CYCLE", $i);
3251e48c5293SSteven Rostedt    $reboot = set_test_option("REBOOT", $i);
3252a75fececSSteven Rostedt    $noclean = set_test_option("BUILD_NOCLEAN", $i);
3253a75fececSSteven Rostedt    $minconfig = set_test_option("MIN_CONFIG", $i);
32544c4ab120SSteven Rostedt    $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i);
32554c4ab120SSteven Rostedt    $start_minconfig = set_test_option("START_MIN_CONFIG", $i);
32564c4ab120SSteven Rostedt    $ignore_config = set_test_option("IGNORE_CONFIG", $i);
3257a75fececSSteven Rostedt    $run_test = set_test_option("TEST", $i);
3258a75fececSSteven Rostedt    $addconfig = set_test_option("ADD_CONFIG", $i);
3259a75fececSSteven Rostedt    $reboot_type = set_test_option("REBOOT_TYPE", $i);
3260a75fececSSteven Rostedt    $grub_menu = set_test_option("GRUB_MENU", $i);
32618b37ca8cSSteven Rostedt    $post_install = set_test_option("POST_INSTALL", $i);
3262e0a8742eSSteven Rostedt    $no_install = set_test_option("NO_INSTALL", $i);
3263a75fececSSteven Rostedt    $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
3264a75fececSSteven Rostedt    $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
3265a75fececSSteven Rostedt    $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
3266a75fececSSteven Rostedt    $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
3267a75fececSSteven Rostedt    $power_off = set_test_option("POWER_OFF", $i);
3268576f627cSSteven Rostedt    $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
3269576f627cSSteven Rostedt    $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
3270a75fececSSteven Rostedt    $sleep_time = set_test_option("SLEEP_TIME", $i);
3271a75fececSSteven Rostedt    $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
327227d934b2SSteven Rostedt    $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
32731990207dSSteven Rostedt    $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
3274c960bb9fSSteven Rostedt    $bisect_manual = set_test_option("BISECT_MANUAL", $i);
3275c23dca7cSSteven Rostedt    $bisect_skip = set_test_option("BISECT_SKIP", $i);
327630f75da5SSteven Rostedt    $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
3277a75fececSSteven Rostedt    $store_failures = set_test_option("STORE_FAILURES", $i);
3278de5b6e3bSRabin Vincent    $store_successes = set_test_option("STORE_SUCCESSES", $i);
32799064af52SSteven Rostedt    $test_name = set_test_option("TEST_NAME", $i);
3280a75fececSSteven Rostedt    $timeout = set_test_option("TIMEOUT", $i);
3281a75fececSSteven Rostedt    $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
3282a75fececSSteven Rostedt    $console = set_test_option("CONSOLE", $i);
3283f1a5b962SSteven Rostedt    $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
3284a75fececSSteven Rostedt    $success_line = set_test_option("SUCCESS_LINE", $i);
32852b803365SSteven Rostedt    $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i);
32861c8a617aSSteven Rostedt    $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
32871c8a617aSSteven Rostedt    $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
32882d01b26aSSteven Rostedt    $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
3289a75fececSSteven Rostedt    $build_target = set_test_option("BUILD_TARGET", $i);
3290e48c5293SSteven Rostedt    $ssh_exec = set_test_option("SSH_EXEC", $i);
3291e48c5293SSteven Rostedt    $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
3292a75fececSSteven Rostedt    $target_image = set_test_option("TARGET_IMAGE", $i);
3293a75fececSSteven Rostedt    $localversion = set_test_option("LOCALVERSION", $i);
3294a75fececSSteven Rostedt
329535ce5952SSteven Rostedt    $start_minconfig_defined = 1;
329635ce5952SSteven Rostedt
32974c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
329835ce5952SSteven Rostedt	$start_minconfig_defined = 0;
32994c4ab120SSteven Rostedt	$start_minconfig = $minconfig;
33004c4ab120SSteven Rostedt    }
33014c4ab120SSteven Rostedt
3302a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
3303a75fececSSteven Rostedt
3304a908a665SAndrew Jones    foreach my $dir ($tmpdir, $outputdir) {
3305a908a665SAndrew Jones	if (!-d $dir) {
3306a908a665SAndrew Jones	    mkpath($dir) or
3307a908a665SAndrew Jones		die "can't create $dir";
3308a908a665SAndrew Jones	}
3309a75fececSSteven Rostedt    }
3310a75fececSSteven Rostedt
3311e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
3312e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
3313e48c5293SSteven Rostedt
3314a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
3315a9dd5d63SRabin Vincent    $testlog = "$tmpdir/testlog-$machine";
3316a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
3317a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
331851ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
3319a75fececSSteven Rostedt
3320bb8474b1SSteven Rostedt    if (!$buildonly) {
3321bb8474b1SSteven Rostedt	$target = "$ssh_user\@$machine";
3322a75fececSSteven Rostedt	if ($reboot_type eq "grub") {
3323576f627cSSteven Rostedt	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3324a75fececSSteven Rostedt	} elsif (!defined($reboot_script)) {
3325576f627cSSteven Rostedt	    dodie "REBOOT_SCRIPT not defined"
3326a75fececSSteven Rostedt	}
3327bb8474b1SSteven Rostedt    }
3328a75fececSSteven Rostedt
3329a75fececSSteven Rostedt    my $run_type = $build_type;
3330a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
3331a75fececSSteven Rostedt	$run_type = $opt{"PATCHCHECK_TYPE[$i]"};
3332a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
3333a75fececSSteven Rostedt	$run_type = $opt{"BISECT_TYPE[$i]"};
33340a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
33350a05c769SSteven Rostedt	$run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
3336a75fececSSteven Rostedt    }
3337a75fececSSteven Rostedt
33384c4ab120SSteven Rostedt    if ($test_type eq "make_min_config") {
33394c4ab120SSteven Rostedt	$run_type = "";
33404c4ab120SSteven Rostedt    }
33414c4ab120SSteven Rostedt
3342a75fececSSteven Rostedt    # mistake in config file?
3343a75fececSSteven Rostedt    if (!defined($run_type)) {
3344a75fececSSteven Rostedt	$run_type = "ERROR";
3345a75fececSSteven Rostedt    }
33462545eb61SSteven Rostedt
3347e0a8742eSSteven Rostedt    my $installme = "";
3348e0a8742eSSteven Rostedt    $installme = " no_install" if ($no_install);
3349e0a8742eSSteven Rostedt
33502545eb61SSteven Rostedt    doprint "\n\n";
3351e0a8742eSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
33527faafbd6SSteven Rostedt
33537faafbd6SSteven Rostedt    unlink $dmesg;
33547faafbd6SSteven Rostedt    unlink $buildlog;
3355a9dd5d63SRabin Vincent    unlink $testlog;
33562545eb61SSteven Rostedt
3357250bae8bSSteven Rostedt    if (defined($addconfig)) {
3358250bae8bSSteven Rostedt	my $min = $minconfig;
33592b7d9b21SSteven Rostedt	if (!defined($minconfig)) {
3360250bae8bSSteven Rostedt	    $min = "";
3361250bae8bSSteven Rostedt	}
3362250bae8bSSteven Rostedt	run_command "cat $addconfig $min > $tmpdir/add_config" or
33632b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
33649be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
33652b7d9b21SSteven Rostedt    }
33662b7d9b21SSteven Rostedt
33676c5ee0beSSteven Rostedt    my $checkout = $opt{"CHECKOUT[$i]"};
33686c5ee0beSSteven Rostedt    if (defined($checkout)) {
33696c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
33706c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
33716c5ee0beSSteven Rostedt    }
33726c5ee0beSSteven Rostedt
33734ab1cce5SSteven Rostedt    $no_reboot = 0;
33744ab1cce5SSteven Rostedt
33754ab1cce5SSteven Rostedt
3376a75fececSSteven Rostedt    if ($test_type eq "bisect") {
33775f9b6cedSSteven Rostedt	bisect $i;
33785f9b6cedSSteven Rostedt	next;
33790a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
33800a05c769SSteven Rostedt	config_bisect $i;
33810a05c769SSteven Rostedt	next;
3382a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
33836c5ee0beSSteven Rostedt	patchcheck $i;
33846c5ee0beSSteven Rostedt	next;
33854c4ab120SSteven Rostedt    } elsif ($test_type eq "make_min_config") {
33864c4ab120SSteven Rostedt	make_min_config $i;
33874c4ab120SSteven Rostedt	next;
33885f9b6cedSSteven Rostedt    }
33895f9b6cedSSteven Rostedt
33907faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
33917faafbd6SSteven Rostedt	build $build_type or next;
33922545eb61SSteven Rostedt    }
33932545eb61SSteven Rostedt
3394cd8e368fSSteven Rostedt    if ($test_type eq "install") {
3395cd8e368fSSteven Rostedt	get_version;
3396cd8e368fSSteven Rostedt	install;
3397cd8e368fSSteven Rostedt	success $i;
3398cd8e368fSSteven Rostedt	next;
3399cd8e368fSSteven Rostedt    }
3400cd8e368fSSteven Rostedt
3401a75fececSSteven Rostedt    if ($test_type ne "build") {
34027faafbd6SSteven Rostedt	my $failed = 0;
3403ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
3404a75fececSSteven Rostedt
3405a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
34067faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
34075a391fbfSSteven Rostedt	}
34087faafbd6SSteven Rostedt	end_monitor;
34097faafbd6SSteven Rostedt	next if ($failed);
3410a75fececSSteven Rostedt    }
34115a391fbfSSteven Rostedt
34125f9b6cedSSteven Rostedt    success $i;
341375c3fda7SSteven Rostedt}
34142545eb61SSteven Rostedt
34155c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
341675c3fda7SSteven Rostedt    halt;
3417576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
341875c3fda7SSteven Rostedt    reboot;
34195c42fc5bSSteven Rostedt}
342075c3fda7SSteven Rostedt
3421e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
3422e48c5293SSteven Rostedt
34232545eb61SSteven Rostedtexit 0;
3424