xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision bb8474b181a715182a110c8ed2b3786ea7487f2b)
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;
25*bb8474b1SSteven 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*bb8474b1SSteven Rostedt# set when a test is something other that just building
140*bb8474b1SSteven Rostedt# which would require more options.
141*bb8474b1SSteven Rostedtmy $buildonly = 1;
142*bb8474b1SSteven Rostedt
1438d1491baSSteven Rostedtmy %entered_configs;
1448d1491baSSteven Rostedtmy %config_help;
14577d942ceSSteven Rostedtmy %variable;
146fcb3f16aSSteven Rostedtmy %force_config;
1478d1491baSSteven Rostedt
1484ab1cce5SSteven Rostedt# do not force reboots on config problems
1494ab1cce5SSteven Rostedtmy $no_reboot = 1;
1504ab1cce5SSteven Rostedt
1517bf51073SSteven Rostedt# default variables that can be used
1527bf51073SSteven Rostedtchomp ($variable{"PWD"} = `pwd`);
1537bf51073SSteven Rostedt
1548d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF"
1558d1491baSSteven Rostedt The machine hostname that you will test.
156*bb8474b1SSteven Rostedt For build only tests, it is still needed to differentiate log files.
1578d1491baSSteven RostedtEOF
1588d1491baSSteven Rostedt    ;
1598d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF"
1608d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user
1618d1491baSSteven Rostedt  (most likely root, since you need privileged operations)
1628d1491baSSteven RostedtEOF
1638d1491baSSteven Rostedt    ;
1648d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF"
1658d1491baSSteven Rostedt The directory that contains the Linux source code (full path).
1660e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
1670e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
1688d1491baSSteven RostedtEOF
1698d1491baSSteven Rostedt    ;
1708d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF"
1718d1491baSSteven Rostedt The directory that the objects will be built (full path).
1728d1491baSSteven Rostedt (can not be same as BUILD_DIR)
1730e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
1740e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
1758d1491baSSteven RostedtEOF
1768d1491baSSteven Rostedt    ;
1778d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF"
1788d1491baSSteven Rostedt The location of the compiled file to copy to the target.
1798d1491baSSteven Rostedt (relative to OUTPUT_DIR)
1808d1491baSSteven RostedtEOF
1818d1491baSSteven Rostedt    ;
1828d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF"
1838d1491baSSteven Rostedt The place to put your image on the test machine.
1848d1491baSSteven RostedtEOF
1858d1491baSSteven Rostedt    ;
1868d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF"
1878d1491baSSteven Rostedt A script or command to reboot the box.
1888d1491baSSteven Rostedt
1898d1491baSSteven Rostedt Here is a digital loggers power switch example
1908d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
1918d1491baSSteven Rostedt
1928d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host
1938d1491baSSteven Rostedt with the name "Guest".
1948d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
1958d1491baSSteven RostedtEOF
1968d1491baSSteven Rostedt    ;
1978d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF"
1988d1491baSSteven Rostedt The script or command that reads the console
1998d1491baSSteven Rostedt
2008d1491baSSteven Rostedt  If you use ttywatch server, something like the following would work.
2018d1491baSSteven RostedtCONSOLE = nc -d localhost 3001
2028d1491baSSteven Rostedt
2038d1491baSSteven Rostedt For a virtual machine with guest name "Guest".
2048d1491baSSteven RostedtCONSOLE =  virsh console Guest
2058d1491baSSteven RostedtEOF
2068d1491baSSteven Rostedt    ;
2078d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF"
2088d1491baSSteven Rostedt Required version ending to differentiate the test
2098d1491baSSteven Rostedt from other linux builds on the system.
2108d1491baSSteven RostedtEOF
2118d1491baSSteven Rostedt    ;
2128d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF"
2138d1491baSSteven Rostedt Way to reboot the box to the test kernel.
2148d1491baSSteven Rostedt Only valid options so far are "grub" and "script".
2158d1491baSSteven Rostedt
2168d1491baSSteven Rostedt If you specify grub, it will assume grub version 1
2178d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
2188d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not
2198d1491baSSteven Rostedt your setup, then specify "script" and have a command or script
2208d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target.
2218d1491baSSteven Rostedt
2228d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually.
2238d1491baSSteven Rostedt The test will not modify that file.
2248d1491baSSteven RostedtEOF
2258d1491baSSteven Rostedt    ;
2268d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF"
2278d1491baSSteven Rostedt The grub title name for the test kernel to boot
2288d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = grub)
2298d1491baSSteven Rostedt
2308d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to
2318d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search
2328d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to
2338d1491baSSteven Rostedt reboot into.
2348d1491baSSteven Rostedt
2358d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has:
2368d1491baSSteven Rostedt title Test Kernel
2378d1491baSSteven Rostedt kernel vmlinuz-test
2388d1491baSSteven Rostedt GRUB_MENU = Test Kernel
2398d1491baSSteven RostedtEOF
2408d1491baSSteven Rostedt    ;
2418d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF"
2428d1491baSSteven Rostedt A script to reboot the target into the test kernel
2438d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script)
2448d1491baSSteven RostedtEOF
2458d1491baSSteven Rostedt    ;
2468d1491baSSteven Rostedt
247dad98754SSteven Rostedtsub read_prompt {
248dad98754SSteven Rostedt    my ($cancel, $prompt) = @_;
24935ce5952SSteven Rostedt
25035ce5952SSteven Rostedt    my $ans;
25135ce5952SSteven Rostedt
25235ce5952SSteven Rostedt    for (;;) {
253dad98754SSteven Rostedt	if ($cancel) {
254dad98754SSteven Rostedt	    print "$prompt [y/n/C] ";
255dad98754SSteven Rostedt	} else {
25635ce5952SSteven Rostedt	    print "$prompt [Y/n] ";
257dad98754SSteven Rostedt	}
25835ce5952SSteven Rostedt	$ans = <STDIN>;
25935ce5952SSteven Rostedt	chomp $ans;
26035ce5952SSteven Rostedt	if ($ans =~ /^\s*$/) {
261dad98754SSteven Rostedt	    if ($cancel) {
262dad98754SSteven Rostedt		$ans = "c";
263dad98754SSteven Rostedt	    } else {
26435ce5952SSteven Rostedt		$ans = "y";
26535ce5952SSteven Rostedt	    }
266dad98754SSteven Rostedt	}
26735ce5952SSteven Rostedt	last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
268dad98754SSteven Rostedt	if ($cancel) {
269dad98754SSteven Rostedt	    last if ($ans =~ /^c$/i);
270dad98754SSteven Rostedt	    print "Please answer either 'y', 'n' or 'c'.\n";
271dad98754SSteven Rostedt	} else {
27235ce5952SSteven Rostedt	    print "Please answer either 'y' or 'n'.\n";
27335ce5952SSteven Rostedt	}
274dad98754SSteven Rostedt    }
275dad98754SSteven Rostedt    if ($ans =~ /^c/i) {
276dad98754SSteven Rostedt	exit;
277dad98754SSteven Rostedt    }
27835ce5952SSteven Rostedt    if ($ans !~ /^y$/i) {
27935ce5952SSteven Rostedt	return 0;
28035ce5952SSteven Rostedt    }
28135ce5952SSteven Rostedt    return 1;
28235ce5952SSteven Rostedt}
2838d1491baSSteven Rostedt
284dad98754SSteven Rostedtsub read_yn {
285dad98754SSteven Rostedt    my ($prompt) = @_;
286dad98754SSteven Rostedt
287dad98754SSteven Rostedt    return read_prompt 0, $prompt;
288dad98754SSteven Rostedt}
289dad98754SSteven Rostedt
290dad98754SSteven Rostedtsub read_ync {
291dad98754SSteven Rostedt    my ($prompt) = @_;
292dad98754SSteven Rostedt
293dad98754SSteven Rostedt    return read_prompt 1, $prompt;
294dad98754SSteven Rostedt}
295dad98754SSteven Rostedt
2968d1491baSSteven Rostedtsub get_ktest_config {
2978d1491baSSteven Rostedt    my ($config) = @_;
298815e2bd7SSteven Rostedt    my $ans;
2998d1491baSSteven Rostedt
3008d1491baSSteven Rostedt    return if (defined($opt{$config}));
3018d1491baSSteven Rostedt
3028d1491baSSteven Rostedt    if (defined($config_help{$config})) {
3038d1491baSSteven Rostedt	print "\n";
3048d1491baSSteven Rostedt	print $config_help{$config};
3058d1491baSSteven Rostedt    }
3068d1491baSSteven Rostedt
3078d1491baSSteven Rostedt    for (;;) {
3088d1491baSSteven Rostedt	print "$config = ";
3098d1491baSSteven Rostedt	if (defined($default{$config})) {
3108d1491baSSteven Rostedt	    print "\[$default{$config}\] ";
3118d1491baSSteven Rostedt	}
312815e2bd7SSteven Rostedt	$ans = <STDIN>;
313815e2bd7SSteven Rostedt	$ans =~ s/^\s*(.*\S)\s*$/$1/;
314815e2bd7SSteven Rostedt	if ($ans =~ /^\s*$/) {
3158d1491baSSteven Rostedt	    if ($default{$config}) {
316815e2bd7SSteven Rostedt		$ans = $default{$config};
3178d1491baSSteven Rostedt	    } else {
3188d1491baSSteven Rostedt		print "Your answer can not be blank\n";
3198d1491baSSteven Rostedt		next;
3208d1491baSSteven Rostedt	    }
3218d1491baSSteven Rostedt	}
3220e7a22deSSteven Rostedt	$entered_configs{$config} = ${ans};
3238d1491baSSteven Rostedt	last;
3248d1491baSSteven Rostedt    }
3258d1491baSSteven Rostedt}
3268d1491baSSteven Rostedt
3278d1491baSSteven Rostedtsub get_ktest_configs {
3288d1491baSSteven Rostedt    get_ktest_config("MACHINE");
3298d1491baSSteven Rostedt    get_ktest_config("BUILD_DIR");
3308d1491baSSteven Rostedt    get_ktest_config("OUTPUT_DIR");
331*bb8474b1SSteven Rostedt
332*bb8474b1SSteven Rostedt    # options required for other than just building a kernel
333*bb8474b1SSteven Rostedt    if (!$buildonly) {
334*bb8474b1SSteven Rostedt	get_ktest_config("SSH_USER");
3358d1491baSSteven Rostedt	get_ktest_config("BUILD_TARGET");
3368d1491baSSteven Rostedt	get_ktest_config("TARGET_IMAGE");
3378d1491baSSteven Rostedt	get_ktest_config("POWER_CYCLE");
3388d1491baSSteven Rostedt	get_ktest_config("CONSOLE");
339*bb8474b1SSteven Rostedt    }
340*bb8474b1SSteven Rostedt
3418d1491baSSteven Rostedt    get_ktest_config("LOCALVERSION");
3428d1491baSSteven Rostedt
343*bb8474b1SSteven Rostedt    return if ($buildonly);
344*bb8474b1SSteven Rostedt
3458d1491baSSteven Rostedt    my $rtype = $opt{"REBOOT_TYPE"};
3468d1491baSSteven Rostedt
3478d1491baSSteven Rostedt    if (!defined($rtype)) {
3488d1491baSSteven Rostedt	if (!defined($opt{"GRUB_MENU"})) {
3498d1491baSSteven Rostedt	    get_ktest_config("REBOOT_TYPE");
3508d1491baSSteven Rostedt	    $rtype = $entered_configs{"REBOOT_TYPE"};
3518d1491baSSteven Rostedt	} else {
3528d1491baSSteven Rostedt	    $rtype = "grub";
3538d1491baSSteven Rostedt	}
3548d1491baSSteven Rostedt    }
3558d1491baSSteven Rostedt
3568d1491baSSteven Rostedt    if ($rtype eq "grub") {
3578d1491baSSteven Rostedt	get_ktest_config("GRUB_MENU");
3588d1491baSSteven Rostedt    } else {
3598d1491baSSteven Rostedt	get_ktest_config("REBOOT_SCRIPT");
3608d1491baSSteven Rostedt    }
3618d1491baSSteven Rostedt}
3628d1491baSSteven Rostedt
36377d942ceSSteven Rostedtsub process_variables {
3648d735212SSteven Rostedt    my ($value, $remove_undef) = @_;
36577d942ceSSteven Rostedt    my $retval = "";
36677d942ceSSteven Rostedt
36777d942ceSSteven Rostedt    # We want to check for '\', and it is just easier
36877d942ceSSteven Rostedt    # to check the previous characet of '$' and not need
36977d942ceSSteven Rostedt    # to worry if '$' is the first character. By adding
37077d942ceSSteven Rostedt    # a space to $value, we can just check [^\\]\$ and
37177d942ceSSteven Rostedt    # it will still work.
37277d942ceSSteven Rostedt    $value = " $value";
37377d942ceSSteven Rostedt
37477d942ceSSteven Rostedt    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
37577d942ceSSteven Rostedt	my $begin = $1;
37677d942ceSSteven Rostedt	my $var = $2;
37777d942ceSSteven Rostedt	my $end = $3;
37877d942ceSSteven Rostedt	# append beginning of value to retval
37977d942ceSSteven Rostedt	$retval = "$retval$begin";
38077d942ceSSteven Rostedt	if (defined($variable{$var})) {
38177d942ceSSteven Rostedt	    $retval = "$retval$variable{$var}";
3828d735212SSteven Rostedt	} elsif (defined($remove_undef) && $remove_undef) {
3838d735212SSteven Rostedt	    # for if statements, any variable that is not defined,
3848d735212SSteven Rostedt	    # we simple convert to 0
3858d735212SSteven Rostedt	    $retval = "${retval}0";
38677d942ceSSteven Rostedt	} else {
38777d942ceSSteven Rostedt	    # put back the origin piece.
38877d942ceSSteven Rostedt	    $retval = "$retval\$\{$var\}";
38977d942ceSSteven Rostedt	}
39077d942ceSSteven Rostedt	$value = $end;
39177d942ceSSteven Rostedt    }
39277d942ceSSteven Rostedt    $retval = "$retval$value";
39377d942ceSSteven Rostedt
39477d942ceSSteven Rostedt    # remove the space added in the beginning
39577d942ceSSteven Rostedt    $retval =~ s/ //;
39677d942ceSSteven Rostedt
39777d942ceSSteven Rostedt    return "$retval"
39877d942ceSSteven Rostedt}
39977d942ceSSteven Rostedt
400a57419b3SSteven Rostedtsub set_value {
4013d1cc414SSteven Rostedt    my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
4022545eb61SSteven Rostedt
403*bb8474b1SSteven Rostedt    if ($lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $rvalue ne "build") {
404*bb8474b1SSteven Rostedt	# Note if a test is something other than build, then we
405*bb8474b1SSteven Rostedt	# will need other manditory options.
406*bb8474b1SSteven Rostedt	$buildonly = 0;
407*bb8474b1SSteven Rostedt    }
408*bb8474b1SSteven Rostedt
409a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
4103d1cc414SSteven Rostedt	if (!$override || defined(${$overrides}{$lvalue})) {
4113d1cc414SSteven Rostedt	    my $extra = "";
4123d1cc414SSteven Rostedt	    if ($override) {
4133d1cc414SSteven Rostedt		$extra = "In the same override section!\n";
4143d1cc414SSteven Rostedt	    }
4153d1cc414SSteven Rostedt	    die "$name: $.: Option $lvalue defined more than once!\n$extra";
4163d1cc414SSteven Rostedt	}
4173d1cc414SSteven Rostedt	${$overrides}{$lvalue} = $rvalue;
418a75fececSSteven Rostedt    }
41921a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
42021a9679fSSteven Rostedt	delete $opt{$lvalue};
42121a9679fSSteven Rostedt    } else {
42277d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
42321a9679fSSteven Rostedt	$opt{$lvalue} = $rvalue;
42421a9679fSSteven Rostedt    }
4252545eb61SSteven Rostedt}
426a57419b3SSteven Rostedt
42777d942ceSSteven Rostedtsub set_variable {
42877d942ceSSteven Rostedt    my ($lvalue, $rvalue) = @_;
42977d942ceSSteven Rostedt
43077d942ceSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
43177d942ceSSteven Rostedt	delete $variable{$lvalue};
43277d942ceSSteven Rostedt    } else {
43377d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
43477d942ceSSteven Rostedt	$variable{$lvalue} = $rvalue;
43577d942ceSSteven Rostedt    }
43677d942ceSSteven Rostedt}
43777d942ceSSteven Rostedt
438ab7a3f52SSteven Rostedtsub process_compare {
439ab7a3f52SSteven Rostedt    my ($lval, $cmp, $rval) = @_;
440ab7a3f52SSteven Rostedt
441ab7a3f52SSteven Rostedt    # remove whitespace
442ab7a3f52SSteven Rostedt
443ab7a3f52SSteven Rostedt    $lval =~ s/^\s*//;
444ab7a3f52SSteven Rostedt    $lval =~ s/\s*$//;
445ab7a3f52SSteven Rostedt
446ab7a3f52SSteven Rostedt    $rval =~ s/^\s*//;
447ab7a3f52SSteven Rostedt    $rval =~ s/\s*$//;
448ab7a3f52SSteven Rostedt
449ab7a3f52SSteven Rostedt    if ($cmp eq "==") {
450ab7a3f52SSteven Rostedt	return $lval eq $rval;
451ab7a3f52SSteven Rostedt    } elsif ($cmp eq "!=") {
452ab7a3f52SSteven Rostedt	return $lval ne $rval;
453ab7a3f52SSteven Rostedt    }
454ab7a3f52SSteven Rostedt
455ab7a3f52SSteven Rostedt    my $statement = "$lval $cmp $rval";
456ab7a3f52SSteven Rostedt    my $ret = eval $statement;
457ab7a3f52SSteven Rostedt
458ab7a3f52SSteven Rostedt    # $@ stores error of eval
459ab7a3f52SSteven Rostedt    if ($@) {
460ab7a3f52SSteven Rostedt	return -1;
461ab7a3f52SSteven Rostedt    }
462ab7a3f52SSteven Rostedt
463ab7a3f52SSteven Rostedt    return $ret;
464ab7a3f52SSteven Rostedt}
465ab7a3f52SSteven Rostedt
4669900b5dcSSteven Rostedtsub value_defined {
4679900b5dcSSteven Rostedt    my ($val) = @_;
4689900b5dcSSteven Rostedt
4699900b5dcSSteven Rostedt    return defined($variable{$2}) ||
4709900b5dcSSteven Rostedt	defined($opt{$2});
4719900b5dcSSteven Rostedt}
4729900b5dcSSteven Rostedt
4738d735212SSteven Rostedtmy $d = 0;
4748d735212SSteven Rostedtsub process_expression {
4758d735212SSteven Rostedt    my ($name, $val) = @_;
47645d73a5dSSteven Rostedt
4778d735212SSteven Rostedt    my $c = $d++;
4788d735212SSteven Rostedt
4798d735212SSteven Rostedt    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
4808d735212SSteven Rostedt	my $express = $1;
4818d735212SSteven Rostedt
4828d735212SSteven Rostedt	if (process_expression($name, $express)) {
4838d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
4848d735212SSteven Rostedt	} else {
4858d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
4868d735212SSteven Rostedt	}
4878d735212SSteven Rostedt    }
4888d735212SSteven Rostedt
4898d735212SSteven Rostedt    $d--;
4908d735212SSteven Rostedt    my $OR = "\\|\\|";
4918d735212SSteven Rostedt    my $AND = "\\&\\&";
4928d735212SSteven Rostedt
4938d735212SSteven Rostedt    while ($val =~ s/^(.*?)($OR|$AND)//) {
4948d735212SSteven Rostedt	my $express = $1;
4958d735212SSteven Rostedt	my $op = $2;
4968d735212SSteven Rostedt
4978d735212SSteven Rostedt	if (process_expression($name, $express)) {
4988d735212SSteven Rostedt	    if ($op eq "||") {
4998d735212SSteven Rostedt		return 1;
5008d735212SSteven Rostedt	    }
5018d735212SSteven Rostedt	} else {
5028d735212SSteven Rostedt	    if ($op eq "&&") {
5038d735212SSteven Rostedt		return 0;
5048d735212SSteven Rostedt	    }
5058d735212SSteven Rostedt	}
5068d735212SSteven Rostedt    }
50745d73a5dSSteven Rostedt
508ab7a3f52SSteven Rostedt    if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) {
509ab7a3f52SSteven Rostedt	my $ret = process_compare($1, $2, $3);
510ab7a3f52SSteven Rostedt	if ($ret < 0) {
511ab7a3f52SSteven Rostedt	    die "$name: $.: Unable to process comparison\n";
512ab7a3f52SSteven Rostedt	}
513ab7a3f52SSteven Rostedt	return $ret;
514ab7a3f52SSteven Rostedt    }
515ab7a3f52SSteven Rostedt
5169900b5dcSSteven Rostedt    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
5179900b5dcSSteven Rostedt	if (defined $1) {
5189900b5dcSSteven Rostedt	    return !value_defined($2);
5199900b5dcSSteven Rostedt	} else {
5209900b5dcSSteven Rostedt	    return value_defined($2);
5219900b5dcSSteven Rostedt	}
5229900b5dcSSteven Rostedt    }
5239900b5dcSSteven Rostedt
52445d73a5dSSteven Rostedt    if ($val =~ /^\s*0\s*$/) {
52545d73a5dSSteven Rostedt	return 0;
52645d73a5dSSteven Rostedt    } elsif ($val =~ /^\s*\d+\s*$/) {
52745d73a5dSSteven Rostedt	return 1;
52845d73a5dSSteven Rostedt    }
52945d73a5dSSteven Rostedt
5309900b5dcSSteven Rostedt    die ("$name: $.: Undefined content $val in if statement\n");
5318d735212SSteven Rostedt}
5328d735212SSteven Rostedt
5338d735212SSteven Rostedtsub process_if {
5348d735212SSteven Rostedt    my ($name, $value) = @_;
5358d735212SSteven Rostedt
5368d735212SSteven Rostedt    # Convert variables and replace undefined ones with 0
5378d735212SSteven Rostedt    my $val = process_variables($value, 1);
5388d735212SSteven Rostedt    my $ret = process_expression $name, $val;
5398d735212SSteven Rostedt
5408d735212SSteven Rostedt    return $ret;
54145d73a5dSSteven Rostedt}
54245d73a5dSSteven Rostedt
5432ed3b161SSteven Rostedtsub __read_config {
5442ed3b161SSteven Rostedt    my ($config, $current_test_num) = @_;
545a57419b3SSteven Rostedt
5462ed3b161SSteven Rostedt    my $in;
5472ed3b161SSteven Rostedt    open($in, $config) || die "can't read file $config";
548a57419b3SSteven Rostedt
549a57419b3SSteven Rostedt    my $name = $config;
550a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
551a57419b3SSteven Rostedt
5522ed3b161SSteven Rostedt    my $test_num = $$current_test_num;
553a57419b3SSteven Rostedt    my $default = 1;
554a57419b3SSteven Rostedt    my $repeat = 1;
555a57419b3SSteven Rostedt    my $num_tests_set = 0;
556a57419b3SSteven Rostedt    my $skip = 0;
557a57419b3SSteven Rostedt    my $rest;
558a9f84424SSteven Rostedt    my $line;
5590df213caSSteven Rostedt    my $test_case = 0;
56045d73a5dSSteven Rostedt    my $if = 0;
56145d73a5dSSteven Rostedt    my $if_set = 0;
5623d1cc414SSteven Rostedt    my $override = 0;
5633d1cc414SSteven Rostedt
5643d1cc414SSteven Rostedt    my %overrides;
565a57419b3SSteven Rostedt
5662ed3b161SSteven Rostedt    while (<$in>) {
567a57419b3SSteven Rostedt
568a57419b3SSteven Rostedt	# ignore blank lines and comments
569a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
570a57419b3SSteven Rostedt
5710050b6bbSSteven Rostedt	if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
572a57419b3SSteven Rostedt
5730050b6bbSSteven Rostedt	    my $type = $1;
5740050b6bbSSteven Rostedt	    $rest = $2;
575a9f84424SSteven Rostedt	    $line = $2;
5760050b6bbSSteven Rostedt
5770050b6bbSSteven Rostedt	    my $old_test_num;
5780050b6bbSSteven Rostedt	    my $old_repeat;
5793d1cc414SSteven Rostedt	    $override = 0;
5800050b6bbSSteven Rostedt
5810050b6bbSSteven Rostedt	    if ($type eq "TEST_START") {
582a57419b3SSteven Rostedt
583a57419b3SSteven Rostedt		if ($num_tests_set) {
584a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
585a57419b3SSteven Rostedt		}
586a57419b3SSteven Rostedt
5870050b6bbSSteven Rostedt		$old_test_num = $test_num;
5880050b6bbSSteven Rostedt		$old_repeat = $repeat;
589a57419b3SSteven Rostedt
590a57419b3SSteven Rostedt		$test_num += $repeat;
591a57419b3SSteven Rostedt		$default = 0;
592a57419b3SSteven Rostedt		$repeat = 1;
5930050b6bbSSteven Rostedt	    } else {
5940050b6bbSSteven Rostedt		$default = 1;
5950050b6bbSSteven Rostedt	    }
596a57419b3SSteven Rostedt
597a9f84424SSteven Rostedt	    # If SKIP is anywhere in the line, the command will be skipped
598a9f84424SSteven Rostedt	    if ($rest =~ s/\s+SKIP\b//) {
599a57419b3SSteven Rostedt		$skip = 1;
600a57419b3SSteven Rostedt	    } else {
6010df213caSSteven Rostedt		$test_case = 1;
602a57419b3SSteven Rostedt		$skip = 0;
603a57419b3SSteven Rostedt	    }
604a57419b3SSteven Rostedt
605a9f84424SSteven Rostedt	    if ($rest =~ s/\sELSE\b//) {
606a9f84424SSteven Rostedt		if (!$if) {
607a9f84424SSteven Rostedt		    die "$name: $.: ELSE found with out matching IF section\n$_";
608a57419b3SSteven Rostedt		}
609a9f84424SSteven Rostedt		$if = 0;
610a9f84424SSteven Rostedt
611a9f84424SSteven Rostedt		if ($if_set) {
612a9f84424SSteven Rostedt		    $skip = 1;
613a9f84424SSteven Rostedt		} else {
614a9f84424SSteven Rostedt		    $skip = 0;
6153d1cc414SSteven Rostedt		}
6163d1cc414SSteven Rostedt	    }
617a57419b3SSteven Rostedt
618a9f84424SSteven Rostedt	    if ($rest =~ s/\sIF\s+(.*)//) {
61945d73a5dSSteven Rostedt		if (process_if($name, $1)) {
62045d73a5dSSteven Rostedt		    $if_set = 1;
62145d73a5dSSteven Rostedt		} else {
622a57419b3SSteven Rostedt		    $skip = 1;
623a57419b3SSteven Rostedt		}
62445d73a5dSSteven Rostedt		$if = 1;
62545d73a5dSSteven Rostedt	    } else {
62645d73a5dSSteven Rostedt		$if = 0;
627a9f84424SSteven Rostedt		$if_set = 0;
62845d73a5dSSteven Rostedt	    }
629a57419b3SSteven Rostedt
630a9f84424SSteven Rostedt	    if (!$skip) {
631a9f84424SSteven Rostedt		if ($type eq "TEST_START") {
632a9f84424SSteven Rostedt		    if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
633a9f84424SSteven Rostedt			$repeat = $1;
634a9f84424SSteven Rostedt			$repeat_tests{"$test_num"} = $repeat;
635a9f84424SSteven Rostedt		    }
636a9f84424SSteven Rostedt		} elsif ($rest =~ s/\sOVERRIDE\b//) {
637a9f84424SSteven Rostedt		    # DEFAULT only
638a9f84424SSteven Rostedt		    $override = 1;
639a9f84424SSteven Rostedt		    # Clear previous overrides
640a9f84424SSteven Rostedt		    %overrides = ();
641a9f84424SSteven Rostedt		}
642a9f84424SSteven Rostedt	    }
643a9f84424SSteven Rostedt
644a9f84424SSteven Rostedt	    if (!$skip && $rest !~ /^\s*$/) {
6450050b6bbSSteven Rostedt		die "$name: $.: Gargbage found after $type\n$_";
646a57419b3SSteven Rostedt	    }
647a57419b3SSteven Rostedt
6480050b6bbSSteven Rostedt	    if ($skip && $type eq "TEST_START") {
649a57419b3SSteven Rostedt		$test_num = $old_test_num;
650e48c5293SSteven Rostedt		$repeat = $old_repeat;
651a57419b3SSteven Rostedt	    }
652a57419b3SSteven Rostedt
653ab7a3f52SSteven Rostedt	} elsif (/^\s*ELSE\b(.*)$/) {
65445d73a5dSSteven Rostedt	    if (!$if) {
65545d73a5dSSteven Rostedt		die "$name: $.: ELSE found with out matching IF section\n$_";
65645d73a5dSSteven Rostedt	    }
65745d73a5dSSteven Rostedt	    $rest = $1;
65845d73a5dSSteven Rostedt	    if ($if_set) {
65945d73a5dSSteven Rostedt		$skip = 1;
660ab7a3f52SSteven Rostedt		$rest = "";
66145d73a5dSSteven Rostedt	    } else {
66245d73a5dSSteven Rostedt		$skip = 0;
66345d73a5dSSteven Rostedt
664ab7a3f52SSteven Rostedt		if ($rest =~ /\sIF\s+(.*)/) {
66545d73a5dSSteven Rostedt		    # May be a ELSE IF section.
66645d73a5dSSteven Rostedt		    if (!process_if($name, $1)) {
66745d73a5dSSteven Rostedt			$skip = 1;
66845d73a5dSSteven Rostedt		    }
669ab7a3f52SSteven Rostedt		    $rest = "";
67045d73a5dSSteven Rostedt		} else {
67145d73a5dSSteven Rostedt		    $if = 0;
67245d73a5dSSteven Rostedt		}
67345d73a5dSSteven Rostedt	    }
67445d73a5dSSteven Rostedt
675ab7a3f52SSteven Rostedt	    if ($rest !~ /^\s*$/) {
676ab7a3f52SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
677ab7a3f52SSteven Rostedt	    }
678ab7a3f52SSteven Rostedt
6792ed3b161SSteven Rostedt	} elsif (/^\s*INCLUDE\s+(\S+)/) {
6802ed3b161SSteven Rostedt
6812ed3b161SSteven Rostedt	    next if ($skip);
6822ed3b161SSteven Rostedt
6832ed3b161SSteven Rostedt	    if (!$default) {
6842ed3b161SSteven Rostedt		die "$name: $.: INCLUDE can only be done in default sections\n$_";
6852ed3b161SSteven Rostedt	    }
6862ed3b161SSteven Rostedt
6872ed3b161SSteven Rostedt	    my $file = process_variables($1);
6882ed3b161SSteven Rostedt
6892ed3b161SSteven Rostedt	    if ($file !~ m,^/,) {
6902ed3b161SSteven Rostedt		# check the path of the config file first
6912ed3b161SSteven Rostedt		if ($config =~ m,(.*)/,) {
6922ed3b161SSteven Rostedt		    if (-f "$1/$file") {
6932ed3b161SSteven Rostedt			$file = "$1/$file";
6942ed3b161SSteven Rostedt		    }
6952ed3b161SSteven Rostedt		}
6962ed3b161SSteven Rostedt	    }
6972ed3b161SSteven Rostedt
6982ed3b161SSteven Rostedt	    if ( ! -r $file ) {
6992ed3b161SSteven Rostedt		die "$name: $.: Can't read file $file\n$_";
7002ed3b161SSteven Rostedt	    }
7012ed3b161SSteven Rostedt
7022ed3b161SSteven Rostedt	    if (__read_config($file, \$test_num)) {
7032ed3b161SSteven Rostedt		$test_case = 1;
7042ed3b161SSteven Rostedt	    }
7052ed3b161SSteven Rostedt
706a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
707a57419b3SSteven Rostedt
708a57419b3SSteven Rostedt	    next if ($skip);
709a57419b3SSteven Rostedt
710a57419b3SSteven Rostedt	    my $lvalue = $1;
711a57419b3SSteven Rostedt	    my $rvalue = $2;
712a57419b3SSteven Rostedt
713a57419b3SSteven Rostedt	    if (!$default &&
714a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
715a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
716a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
717a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
718a57419b3SSteven Rostedt	    }
719a57419b3SSteven Rostedt
720a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
721a57419b3SSteven Rostedt		if ($test_num) {
722a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
723a57419b3SSteven Rostedt		}
724a57419b3SSteven Rostedt		if (!$default) {
725a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
726a57419b3SSteven Rostedt		}
727a57419b3SSteven Rostedt		$num_tests_set = 1;
728a57419b3SSteven Rostedt	    }
729a57419b3SSteven Rostedt
730a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
7313d1cc414SSteven Rostedt		set_value($lvalue, $rvalue, $override, \%overrides, $name);
732a57419b3SSteven Rostedt	    } else {
733a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
7343d1cc414SSteven Rostedt		set_value($val, $rvalue, $override, \%overrides, $name);
735a57419b3SSteven Rostedt
736a57419b3SSteven Rostedt		if ($repeat > 1) {
737a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
738a57419b3SSteven Rostedt		}
739a57419b3SSteven Rostedt	    }
74077d942ceSSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
74177d942ceSSteven Rostedt	    next if ($skip);
74277d942ceSSteven Rostedt
74377d942ceSSteven Rostedt	    my $lvalue = $1;
74477d942ceSSteven Rostedt	    my $rvalue = $2;
74577d942ceSSteven Rostedt
74677d942ceSSteven Rostedt	    # process config variables.
74777d942ceSSteven Rostedt	    # Config variables are only active while reading the
74877d942ceSSteven Rostedt	    # config and can be defined anywhere. They also ignore
74977d942ceSSteven Rostedt	    # TEST_START and DEFAULTS, but are skipped if they are in
75077d942ceSSteven Rostedt	    # on of these sections that have SKIP defined.
75177d942ceSSteven Rostedt	    # The save variable can be
75277d942ceSSteven Rostedt	    # defined multiple times and the new one simply overrides
75377d942ceSSteven Rostedt	    # the prevous one.
75477d942ceSSteven Rostedt	    set_variable($lvalue, $rvalue);
75577d942ceSSteven Rostedt
756a57419b3SSteven Rostedt	} else {
757a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
758a57419b3SSteven Rostedt	}
7592545eb61SSteven Rostedt    }
7602545eb61SSteven Rostedt
761a57419b3SSteven Rostedt    if ($test_num) {
762a57419b3SSteven Rostedt	$test_num += $repeat - 1;
763a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
764a57419b3SSteven Rostedt    }
765a57419b3SSteven Rostedt
7662ed3b161SSteven Rostedt    close($in);
7672ed3b161SSteven Rostedt
7682ed3b161SSteven Rostedt    $$current_test_num = $test_num;
7692ed3b161SSteven Rostedt
7702ed3b161SSteven Rostedt    return $test_case;
7712ed3b161SSteven Rostedt}
7722ed3b161SSteven Rostedt
773c4261d0fSSteven Rostedtsub get_test_case {
774c4261d0fSSteven Rostedt	print "What test case would you like to run?\n";
775c4261d0fSSteven Rostedt	print " (build, install or boot)\n";
776c4261d0fSSteven Rostedt	print " Other tests are available but require editing the config file\n";
777c4261d0fSSteven Rostedt	my $ans = <STDIN>;
778c4261d0fSSteven Rostedt	chomp $ans;
779c4261d0fSSteven Rostedt	$default{"TEST_TYPE"} = $ans;
780c4261d0fSSteven Rostedt}
781c4261d0fSSteven Rostedt
7822ed3b161SSteven Rostedtsub read_config {
7832ed3b161SSteven Rostedt    my ($config) = @_;
7842ed3b161SSteven Rostedt
7852ed3b161SSteven Rostedt    my $test_case;
7862ed3b161SSteven Rostedt    my $test_num = 0;
7872ed3b161SSteven Rostedt
7882ed3b161SSteven Rostedt    $test_case = __read_config $config, \$test_num;
7892ed3b161SSteven Rostedt
7908d1491baSSteven Rostedt    # make sure we have all mandatory configs
7918d1491baSSteven Rostedt    get_ktest_configs;
7928d1491baSSteven Rostedt
7930df213caSSteven Rostedt    # was a test specified?
7940df213caSSteven Rostedt    if (!$test_case) {
7950df213caSSteven Rostedt	print "No test case specified.\n";
796c4261d0fSSteven Rostedt	get_test_case;
7970df213caSSteven Rostedt    }
7980df213caSSteven Rostedt
799a75fececSSteven Rostedt    # set any defaults
800a75fececSSteven Rostedt
801a75fececSSteven Rostedt    foreach my $default (keys %default) {
802a75fececSSteven Rostedt	if (!defined($opt{$default})) {
803a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
804a75fececSSteven Rostedt	}
805a75fececSSteven Rostedt    }
8062545eb61SSteven Rostedt}
8072545eb61SSteven Rostedt
80823715c3cSSteven Rostedtsub __eval_option {
80923715c3cSSteven Rostedt    my ($option, $i) = @_;
81023715c3cSSteven Rostedt
81123715c3cSSteven Rostedt    # Add space to evaluate the character before $
81223715c3cSSteven Rostedt    $option = " $option";
81323715c3cSSteven Rostedt    my $retval = "";
814f9dfb65bSRabin Vincent    my $repeated = 0;
815f9dfb65bSRabin Vincent    my $parent = 0;
816f9dfb65bSRabin Vincent
817f9dfb65bSRabin Vincent    foreach my $test (keys %repeat_tests) {
818f9dfb65bSRabin Vincent	if ($i >= $test &&
819f9dfb65bSRabin Vincent	    $i < $test + $repeat_tests{$test}) {
820f9dfb65bSRabin Vincent
821f9dfb65bSRabin Vincent	    $repeated = 1;
822f9dfb65bSRabin Vincent	    $parent = $test;
823f9dfb65bSRabin Vincent	    last;
824f9dfb65bSRabin Vincent	}
825f9dfb65bSRabin Vincent    }
82623715c3cSSteven Rostedt
82723715c3cSSteven Rostedt    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
82823715c3cSSteven Rostedt	my $start = $1;
82923715c3cSSteven Rostedt	my $var = $2;
83023715c3cSSteven Rostedt	my $end = $3;
83123715c3cSSteven Rostedt
83223715c3cSSteven Rostedt	# Append beginning of line
83323715c3cSSteven Rostedt	$retval = "$retval$start";
83423715c3cSSteven Rostedt
83523715c3cSSteven Rostedt	# If the iteration option OPT[$i] exists, then use that.
83623715c3cSSteven Rostedt	# otherwise see if the default OPT (without [$i]) exists.
83723715c3cSSteven Rostedt
83823715c3cSSteven Rostedt	my $o = "$var\[$i\]";
839f9dfb65bSRabin Vincent	my $parento = "$var\[$parent\]";
84023715c3cSSteven Rostedt
84123715c3cSSteven Rostedt	if (defined($opt{$o})) {
84223715c3cSSteven Rostedt	    $o = $opt{$o};
84323715c3cSSteven Rostedt	    $retval = "$retval$o";
844f9dfb65bSRabin Vincent	} elsif ($repeated && defined($opt{$parento})) {
845f9dfb65bSRabin Vincent	    $o = $opt{$parento};
846f9dfb65bSRabin Vincent	    $retval = "$retval$o";
84723715c3cSSteven Rostedt	} elsif (defined($opt{$var})) {
84823715c3cSSteven Rostedt	    $o = $opt{$var};
84923715c3cSSteven Rostedt	    $retval = "$retval$o";
85023715c3cSSteven Rostedt	} else {
85123715c3cSSteven Rostedt	    $retval = "$retval\$\{$var\}";
85223715c3cSSteven Rostedt	}
85323715c3cSSteven Rostedt
85423715c3cSSteven Rostedt	$option = $end;
85523715c3cSSteven Rostedt    }
85623715c3cSSteven Rostedt
85723715c3cSSteven Rostedt    $retval = "$retval$option";
85823715c3cSSteven Rostedt
85923715c3cSSteven Rostedt    $retval =~ s/^ //;
86023715c3cSSteven Rostedt
86123715c3cSSteven Rostedt    return $retval;
86223715c3cSSteven Rostedt}
86323715c3cSSteven Rostedt
86423715c3cSSteven Rostedtsub eval_option {
86523715c3cSSteven Rostedt    my ($option, $i) = @_;
86623715c3cSSteven Rostedt
86723715c3cSSteven Rostedt    my $prev = "";
86823715c3cSSteven Rostedt
86923715c3cSSteven Rostedt    # Since an option can evaluate to another option,
87023715c3cSSteven Rostedt    # keep iterating until we do not evaluate any more
87123715c3cSSteven Rostedt    # options.
87223715c3cSSteven Rostedt    my $r = 0;
87323715c3cSSteven Rostedt    while ($prev ne $option) {
87423715c3cSSteven Rostedt	# Check for recursive evaluations.
87523715c3cSSteven Rostedt	# 100 deep should be more than enough.
87623715c3cSSteven Rostedt	if ($r++ > 100) {
87723715c3cSSteven Rostedt	    die "Over 100 evaluations accurred with $option\n" .
87823715c3cSSteven Rostedt		"Check for recursive variables\n";
87923715c3cSSteven Rostedt	}
88023715c3cSSteven Rostedt	$prev = $option;
88123715c3cSSteven Rostedt	$option = __eval_option($option, $i);
88223715c3cSSteven Rostedt    }
88323715c3cSSteven Rostedt
88423715c3cSSteven Rostedt    return $option;
88523715c3cSSteven Rostedt}
88623715c3cSSteven Rostedt
887d1e2f22aSSteven Rostedtsub _logit {
8882545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
8892545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
8902545eb61SSteven Rostedt	print OUT @_;
8912545eb61SSteven Rostedt	close(OUT);
8922545eb61SSteven Rostedt    }
8932545eb61SSteven Rostedt}
8942545eb61SSteven Rostedt
895d1e2f22aSSteven Rostedtsub logit {
896d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
897d1e2f22aSSteven Rostedt	_logit @_;
898d1e2f22aSSteven Rostedt    } else {
899d1e2f22aSSteven Rostedt	print @_;
900d1e2f22aSSteven Rostedt    }
901d1e2f22aSSteven Rostedt}
902d1e2f22aSSteven Rostedt
9035f9b6cedSSteven Rostedtsub doprint {
9045f9b6cedSSteven Rostedt    print @_;
905d1e2f22aSSteven Rostedt    _logit @_;
9065f9b6cedSSteven Rostedt}
9075f9b6cedSSteven Rostedt
9087faafbd6SSteven Rostedtsub run_command;
9092728be41SAndrew Jonessub start_monitor;
9102728be41SAndrew Jonessub end_monitor;
9112728be41SAndrew Jonessub wait_for_monitor;
9127faafbd6SSteven Rostedt
9137faafbd6SSteven Rostedtsub reboot {
9142728be41SAndrew Jones    my ($time) = @_;
9152728be41SAndrew Jones
9162b803365SSteven Rostedt    if (defined($time)) {
9172b803365SSteven Rostedt	start_monitor;
9182b803365SSteven Rostedt	# flush out current monitor
9192b803365SSteven Rostedt	# May contain the reboot success line
9202b803365SSteven Rostedt	wait_for_monitor 1;
9212b803365SSteven Rostedt    }
9222b803365SSteven Rostedt
9237faafbd6SSteven Rostedt    # try to reboot normally
924e48c5293SSteven Rostedt    if (run_command $reboot) {
925576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
926576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
927576f627cSSteven Rostedt	    run_command "$power_cycle";
928576f627cSSteven Rostedt	}
929576f627cSSteven Rostedt    } else {
9307faafbd6SSteven Rostedt	# nope? power cycle it.
931a75fececSSteven Rostedt	run_command "$power_cycle";
9327faafbd6SSteven Rostedt    }
9332728be41SAndrew Jones
9342728be41SAndrew Jones    if (defined($time)) {
9352b803365SSteven Rostedt	wait_for_monitor($time, $reboot_success_line);
9362728be41SAndrew Jones	end_monitor;
9372728be41SAndrew Jones    }
9387faafbd6SSteven Rostedt}
9397faafbd6SSteven Rostedt
940576f627cSSteven Rostedtsub do_not_reboot {
941576f627cSSteven Rostedt    my $i = $iteration;
942576f627cSSteven Rostedt
9434ab1cce5SSteven Rostedt    return $test_type eq "build" || $no_reboot ||
944576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
945576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
946576f627cSSteven Rostedt}
947576f627cSSteven Rostedt
9485c42fc5bSSteven Rostedtsub dodie {
9495a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
9505c42fc5bSSteven Rostedt
951576f627cSSteven Rostedt    my $i = $iteration;
952576f627cSSteven Rostedt
953576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
954576f627cSSteven Rostedt
95575c3fda7SSteven Rostedt	doprint "REBOOTING\n";
9567faafbd6SSteven Rostedt	reboot;
95775c3fda7SSteven Rostedt
958a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
9595c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
960a75fececSSteven Rostedt	`$power_off`;
9615c42fc5bSSteven Rostedt    }
96275c3fda7SSteven Rostedt
963f80802cbSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
964f80802cbSSteven Rostedt	print " See $opt{LOG_FILE} for more info.\n";
965f80802cbSSteven Rostedt    }
966f80802cbSSteven Rostedt
967576f627cSSteven Rostedt    die @_, "\n";
9685c42fc5bSSteven Rostedt}
9695c42fc5bSSteven Rostedt
9707faafbd6SSteven Rostedtsub open_console {
9717faafbd6SSteven Rostedt    my ($fp) = @_;
9727faafbd6SSteven Rostedt
9737faafbd6SSteven Rostedt    my $flags;
9747faafbd6SSteven Rostedt
975a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
976a75fececSSteven Rostedt	dodie "Can't open console $console";
9777faafbd6SSteven Rostedt
9787faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
979576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
9807faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
981576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
9827faafbd6SSteven Rostedt
9837faafbd6SSteven Rostedt    return $pid;
9847faafbd6SSteven Rostedt}
9857faafbd6SSteven Rostedt
9867faafbd6SSteven Rostedtsub close_console {
9877faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
9887faafbd6SSteven Rostedt
9897faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
9907faafbd6SSteven Rostedt    kill 2, $pid;
9917faafbd6SSteven Rostedt
9927faafbd6SSteven Rostedt    print "closing!\n";
9937faafbd6SSteven Rostedt    close($fp);
9947faafbd6SSteven Rostedt}
9957faafbd6SSteven Rostedt
9967faafbd6SSteven Rostedtsub start_monitor {
9977faafbd6SSteven Rostedt    if ($monitor_cnt++) {
9987faafbd6SSteven Rostedt	return;
9997faafbd6SSteven Rostedt    }
10007faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
10017faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
1002a75fececSSteven Rostedt
1003a75fececSSteven Rostedt    return;
1004a75fececSSteven Rostedt
1005a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
10067faafbd6SSteven Rostedt}
10077faafbd6SSteven Rostedt
10087faafbd6SSteven Rostedtsub end_monitor {
10097faafbd6SSteven Rostedt    if (--$monitor_cnt) {
10107faafbd6SSteven Rostedt	return;
10117faafbd6SSteven Rostedt    }
10127faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
10137faafbd6SSteven Rostedt}
10147faafbd6SSteven Rostedt
10157faafbd6SSteven Rostedtsub wait_for_monitor {
10162b803365SSteven Rostedt    my ($time, $stop) = @_;
10172b803365SSteven Rostedt    my $full_line = "";
10187faafbd6SSteven Rostedt    my $line;
10192b803365SSteven Rostedt    my $booted = 0;
10207faafbd6SSteven Rostedt
1021a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
10227faafbd6SSteven Rostedt
10237faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
10242b803365SSteven Rostedt    while (!$booted) {
10257faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
10262b803365SSteven Rostedt	last if (!defined($line));
10272b803365SSteven Rostedt	print "$line";
10282b803365SSteven Rostedt	$full_line .= $line;
10292b803365SSteven Rostedt
10302b803365SSteven Rostedt	if (defined($stop) && $full_line =~ /$stop/) {
10312b803365SSteven Rostedt	    doprint "wait for monitor detected $stop\n";
10322b803365SSteven Rostedt	    $booted = 1;
10332b803365SSteven Rostedt	}
10342b803365SSteven Rostedt
10352b803365SSteven Rostedt	if ($line =~ /\n/) {
10362b803365SSteven Rostedt	    $full_line = "";
10372b803365SSteven Rostedt	}
10382b803365SSteven Rostedt    }
1039a75fececSSteven Rostedt    print "** Monitor flushed **\n";
10407faafbd6SSteven Rostedt}
10417faafbd6SSteven Rostedt
1042de5b6e3bSRabin Vincentsub save_logs {
1043de5b6e3bSRabin Vincent	my ($result, $basedir) = @_;
1044de5b6e3bSRabin Vincent	my @t = localtime;
1045de5b6e3bSRabin Vincent	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1046de5b6e3bSRabin Vincent		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1047de5b6e3bSRabin Vincent
1048de5b6e3bSRabin Vincent	my $type = $build_type;
1049de5b6e3bSRabin Vincent	if ($type =~ /useconfig/) {
1050de5b6e3bSRabin Vincent	    $type = "useconfig";
1051de5b6e3bSRabin Vincent	}
1052de5b6e3bSRabin Vincent
1053de5b6e3bSRabin Vincent	my $dir = "$machine-$test_type-$type-$result-$date";
1054de5b6e3bSRabin Vincent
1055de5b6e3bSRabin Vincent	$dir = "$basedir/$dir";
1056de5b6e3bSRabin Vincent
1057de5b6e3bSRabin Vincent	if (!-d $dir) {
1058de5b6e3bSRabin Vincent	    mkpath($dir) or
1059de5b6e3bSRabin Vincent		die "can't create $dir";
1060de5b6e3bSRabin Vincent	}
1061de5b6e3bSRabin Vincent
1062de5b6e3bSRabin Vincent	my %files = (
1063de5b6e3bSRabin Vincent		"config" => $output_config,
1064de5b6e3bSRabin Vincent		"buildlog" => $buildlog,
1065de5b6e3bSRabin Vincent		"dmesg" => $dmesg,
1066de5b6e3bSRabin Vincent		"testlog" => $testlog,
1067de5b6e3bSRabin Vincent	);
1068de5b6e3bSRabin Vincent
1069de5b6e3bSRabin Vincent	while (my ($name, $source) = each(%files)) {
1070de5b6e3bSRabin Vincent		if (-f "$source") {
1071de5b6e3bSRabin Vincent			cp "$source", "$dir/$name" or
1072de5b6e3bSRabin Vincent				die "failed to copy $source";
1073de5b6e3bSRabin Vincent		}
1074de5b6e3bSRabin Vincent	}
1075de5b6e3bSRabin Vincent
1076de5b6e3bSRabin Vincent	doprint "*** Saved info to $dir ***\n";
1077de5b6e3bSRabin Vincent}
1078de5b6e3bSRabin Vincent
10792b7d9b21SSteven Rostedtsub fail {
10802b7d9b21SSteven Rostedt
1081a75fececSSteven Rostedt	if ($die_on_failure) {
10822b7d9b21SSteven Rostedt		dodie @_;
10832b7d9b21SSteven Rostedt	}
10842b7d9b21SSteven Rostedt
1085a75fececSSteven Rostedt	doprint "FAILED\n";
10867faafbd6SSteven Rostedt
1087576f627cSSteven Rostedt	my $i = $iteration;
1088576f627cSSteven Rostedt
1089a75fececSSteven Rostedt	# no need to reboot for just building.
1090576f627cSSteven Rostedt	if (!do_not_reboot) {
10917faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
10922728be41SAndrew Jones	    reboot $sleep_time;
1093a75fececSSteven Rostedt	}
10947faafbd6SSteven Rostedt
10959064af52SSteven Rostedt	my $name = "";
10969064af52SSteven Rostedt
10979064af52SSteven Rostedt	if (defined($test_name)) {
10989064af52SSteven Rostedt	    $name = " ($test_name)";
10999064af52SSteven Rostedt	}
11009064af52SSteven Rostedt
1101576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1102576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
11039064af52SSteven Rostedt	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1104576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1105576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1106a75fececSSteven Rostedt
1107de5b6e3bSRabin Vincent	if (defined($store_failures)) {
1108de5b6e3bSRabin Vincent	    save_logs "fail", $store_failures;
1109cccae1a6SSteven Rostedt        }
1110cccae1a6SSteven Rostedt
11112b7d9b21SSteven Rostedt	return 1;
11122b7d9b21SSteven Rostedt}
11132b7d9b21SSteven Rostedt
11142545eb61SSteven Rostedtsub run_command {
11152545eb61SSteven Rostedt    my ($command) = @_;
1116d6ce2a0bSSteven Rostedt    my $dolog = 0;
1117d6ce2a0bSSteven Rostedt    my $dord = 0;
1118d6ce2a0bSSteven Rostedt    my $pid;
1119d6ce2a0bSSteven Rostedt
1120e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
1121e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
1122e48c5293SSteven Rostedt
1123d6ce2a0bSSteven Rostedt    doprint("$command ... ");
1124d6ce2a0bSSteven Rostedt
1125d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
11262b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
11272545eb61SSteven Rostedt
11282545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1129d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
1130d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
1131d6ce2a0bSSteven Rostedt	$dolog = 1;
11326c5ee0beSSteven Rostedt    }
11336c5ee0beSSteven Rostedt
11346c5ee0beSSteven Rostedt    if (defined($redirect)) {
1135d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
1136d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
1137d6ce2a0bSSteven Rostedt	$dord = 1;
11382545eb61SSteven Rostedt    }
11392545eb61SSteven Rostedt
1140d6ce2a0bSSteven Rostedt    while (<CMD>) {
1141d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
1142d6ce2a0bSSteven Rostedt	print RD  if ($dord);
1143d6ce2a0bSSteven Rostedt    }
11442545eb61SSteven Rostedt
1145d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
11462545eb61SSteven Rostedt    my $failed = $?;
11472545eb61SSteven Rostedt
1148d6ce2a0bSSteven Rostedt    close(CMD);
1149d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
1150d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
1151d6ce2a0bSSteven Rostedt
11522545eb61SSteven Rostedt    if ($failed) {
11532545eb61SSteven Rostedt	doprint "FAILED!\n";
11542545eb61SSteven Rostedt    } else {
11552545eb61SSteven Rostedt	doprint "SUCCESS\n";
11562545eb61SSteven Rostedt    }
11572545eb61SSteven Rostedt
11585f9b6cedSSteven Rostedt    return !$failed;
11595f9b6cedSSteven Rostedt}
11605f9b6cedSSteven Rostedt
1161e48c5293SSteven Rostedtsub run_ssh {
1162e48c5293SSteven Rostedt    my ($cmd) = @_;
1163e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
1164e48c5293SSteven Rostedt
1165e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1166e48c5293SSteven Rostedt    return run_command "$cp_exec";
1167e48c5293SSteven Rostedt}
1168e48c5293SSteven Rostedt
1169e48c5293SSteven Rostedtsub run_scp {
1170e48c5293SSteven Rostedt    my ($src, $dst) = @_;
1171e48c5293SSteven Rostedt    my $cp_scp = $scp_to_target;
1172e48c5293SSteven Rostedt
1173e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
1174e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
1175e48c5293SSteven Rostedt
1176e48c5293SSteven Rostedt    return run_command "$cp_scp";
1177e48c5293SSteven Rostedt}
1178e48c5293SSteven Rostedt
11795f9b6cedSSteven Rostedtsub get_grub_index {
11805f9b6cedSSteven Rostedt
1181a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
1182a75fececSSteven Rostedt	return;
1183a75fececSSteven Rostedt    }
11845a391fbfSSteven Rostedt    return if (defined($grub_number));
11855f9b6cedSSteven Rostedt
11865f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
11875f9b6cedSSteven Rostedt    $grub_number = -1;
1188e48c5293SSteven Rostedt
1189e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
1190e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
1191e48c5293SSteven Rostedt
1192e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
11935f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
1194e48c5293SSteven Rostedt
1195eaa1fe25SSteven Rostedt    my $found = 0;
1196eaa1fe25SSteven Rostedt
11975f9b6cedSSteven Rostedt    while (<IN>) {
1198a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
11995f9b6cedSSteven Rostedt	    $grub_number++;
1200eaa1fe25SSteven Rostedt	    $found = 1;
12015f9b6cedSSteven Rostedt	    last;
12025f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
12035f9b6cedSSteven Rostedt	    $grub_number++;
12045f9b6cedSSteven Rostedt	}
12055f9b6cedSSteven Rostedt    }
12065f9b6cedSSteven Rostedt    close(IN);
12075f9b6cedSSteven Rostedt
1208a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
1209eaa1fe25SSteven Rostedt	if (!$found);
12105f9b6cedSSteven Rostedt    doprint "$grub_number\n";
12112545eb61SSteven Rostedt}
12122545eb61SSteven Rostedt
12132545eb61SSteven Rostedtsub wait_for_input
12142545eb61SSteven Rostedt{
12152545eb61SSteven Rostedt    my ($fp, $time) = @_;
12162545eb61SSteven Rostedt    my $rin;
12172545eb61SSteven Rostedt    my $ready;
12182545eb61SSteven Rostedt    my $line;
12192545eb61SSteven Rostedt    my $ch;
12202545eb61SSteven Rostedt
12212545eb61SSteven Rostedt    if (!defined($time)) {
12222545eb61SSteven Rostedt	$time = $timeout;
12232545eb61SSteven Rostedt    }
12242545eb61SSteven Rostedt
12252545eb61SSteven Rostedt    $rin = '';
12262545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
12272545eb61SSteven Rostedt    $ready = select($rin, undef, undef, $time);
12282545eb61SSteven Rostedt
12292545eb61SSteven Rostedt    $line = "";
12302545eb61SSteven Rostedt
12312545eb61SSteven Rostedt    # try to read one char at a time
12322545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
12332545eb61SSteven Rostedt	$line .= $ch;
12342545eb61SSteven Rostedt	last if ($ch eq "\n");
12352545eb61SSteven Rostedt    }
12362545eb61SSteven Rostedt
12372545eb61SSteven Rostedt    if (!length($line)) {
12382545eb61SSteven Rostedt	return undef;
12392545eb61SSteven Rostedt    }
12402545eb61SSteven Rostedt
12412545eb61SSteven Rostedt    return $line;
12422545eb61SSteven Rostedt}
12432545eb61SSteven Rostedt
124475c3fda7SSteven Rostedtsub reboot_to {
1245a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
1246c54367f9SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
1247c54367f9SSteven Rostedt	reboot;
1248a75fececSSteven Rostedt	return;
1249a75fececSSteven Rostedt    }
1250a75fececSSteven Rostedt
1251a75fececSSteven Rostedt    run_command "$reboot_script";
12522545eb61SSteven Rostedt}
12532545eb61SSteven Rostedt
1254a57419b3SSteven Rostedtsub get_sha1 {
1255a57419b3SSteven Rostedt    my ($commit) = @_;
1256a57419b3SSteven Rostedt
1257a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
1258a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
1259a57419b3SSteven Rostedt    my $ret = $?;
1260a57419b3SSteven Rostedt
1261a57419b3SSteven Rostedt    logit $sha1;
1262a57419b3SSteven Rostedt
1263a57419b3SSteven Rostedt    if ($ret) {
1264a57419b3SSteven Rostedt	doprint "FAILED\n";
1265a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
1266a57419b3SSteven Rostedt    }
1267a57419b3SSteven Rostedt
1268a57419b3SSteven Rostedt    print "SUCCESS\n";
1269a57419b3SSteven Rostedt
1270a57419b3SSteven Rostedt    chomp $sha1;
1271a57419b3SSteven Rostedt
1272a57419b3SSteven Rostedt    return $sha1;
1273a57419b3SSteven Rostedt}
1274a57419b3SSteven Rostedt
12755a391fbfSSteven Rostedtsub monitor {
12762545eb61SSteven Rostedt    my $booted = 0;
12772545eb61SSteven Rostedt    my $bug = 0;
12785c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
12792b7d9b21SSteven Rostedt    my $loops;
12802545eb61SSteven Rostedt
12817faafbd6SSteven Rostedt    wait_for_monitor 5;
12822545eb61SSteven Rostedt
12832545eb61SSteven Rostedt    my $line;
12842545eb61SSteven Rostedt    my $full_line = "";
12852545eb61SSteven Rostedt
12867faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
12877faafbd6SSteven Rostedt	die "unable to write to $dmesg";
12882545eb61SSteven Rostedt
128975c3fda7SSteven Rostedt    reboot_to;
12902545eb61SSteven Rostedt
12911c8a617aSSteven Rostedt    my $success_start;
12921c8a617aSSteven Rostedt    my $failure_start;
12932d01b26aSSteven Rostedt    my $monitor_start = time;
12942d01b26aSSteven Rostedt    my $done = 0;
1295f1a5b962SSteven Rostedt    my $version_found = 0;
12961c8a617aSSteven Rostedt
12972d01b26aSSteven Rostedt    while (!$done) {
12982545eb61SSteven Rostedt
1299ecaf8e52SSteven Rostedt	if ($bug && defined($stop_after_failure) &&
1300ecaf8e52SSteven Rostedt	    $stop_after_failure >= 0) {
1301ecaf8e52SSteven Rostedt	    my $time = $stop_after_failure - (time - $failure_start);
1302ecaf8e52SSteven Rostedt	    $line = wait_for_input($monitor_fp, $time);
1303ecaf8e52SSteven Rostedt	    if (!defined($line)) {
1304ecaf8e52SSteven Rostedt		doprint "bug timed out after $booted_timeout seconds\n";
1305ecaf8e52SSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1306ecaf8e52SSteven Rostedt		last;
1307ecaf8e52SSteven Rostedt	    }
1308ecaf8e52SSteven Rostedt	} elsif ($booted) {
1309a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
1310cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1311cd4f1d53SSteven Rostedt		my $s = $booted_timeout == 1 ? "" : "s";
1312cd4f1d53SSteven Rostedt		doprint "Successful boot found: break after $booted_timeout second$s\n";
1313cd4f1d53SSteven Rostedt		last;
1314cd4f1d53SSteven Rostedt	    }
13152b7d9b21SSteven Rostedt	} else {
13167faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
1317cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1318cd4f1d53SSteven Rostedt		my $s = $timeout == 1 ? "" : "s";
1319cd4f1d53SSteven Rostedt		doprint "Timed out after $timeout second$s\n";
1320cd4f1d53SSteven Rostedt		last;
13212b7d9b21SSteven Rostedt	    }
1322cd4f1d53SSteven Rostedt	}
13232545eb61SSteven Rostedt
13242545eb61SSteven Rostedt	doprint $line;
13257faafbd6SSteven Rostedt	print DMESG $line;
13262545eb61SSteven Rostedt
13272545eb61SSteven Rostedt	# we are not guaranteed to get a full line
13282545eb61SSteven Rostedt	$full_line .= $line;
13292545eb61SSteven Rostedt
1330a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
13312545eb61SSteven Rostedt	    $booted = 1;
13321c8a617aSSteven Rostedt	    $success_start = time;
13331c8a617aSSteven Rostedt	}
13341c8a617aSSteven Rostedt
13351c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
13361c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
13371c8a617aSSteven Rostedt	    my $now = time;
13381c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
13391c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
13401c8a617aSSteven Rostedt		last;
13411c8a617aSSteven Rostedt	    }
13422545eb61SSteven Rostedt	}
13432545eb61SSteven Rostedt
13445c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
13455c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
13465c42fc5bSSteven Rostedt	}
13475c42fc5bSSteven Rostedt
13482545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
13494651920eSSteven Rostedt	    if (!$bug && !$skip_call_trace) {
13501c8a617aSSteven Rostedt		$bug = 1;
13511c8a617aSSteven Rostedt		$failure_start = time;
13521c8a617aSSteven Rostedt	    }
13531c8a617aSSteven Rostedt	}
13541c8a617aSSteven Rostedt
13551c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
13561c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
13571c8a617aSSteven Rostedt	    my $now = time;
13581c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
13591c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
13601c8a617aSSteven Rostedt		last;
13611c8a617aSSteven Rostedt	    }
13625c42fc5bSSteven Rostedt	}
13635c42fc5bSSteven Rostedt
13645c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
13655c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
13665c42fc5bSSteven Rostedt	}
13675c42fc5bSSteven Rostedt
13685c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
136910abf118SSteven Rostedt	    $failure_start = time;
13702545eb61SSteven Rostedt	    $bug = 1;
13712545eb61SSteven Rostedt	}
13722545eb61SSteven Rostedt
1373f1a5b962SSteven Rostedt	# Detect triple faults by testing the banner
1374f1a5b962SSteven Rostedt	if ($full_line =~ /\bLinux version (\S+).*\n/) {
1375f1a5b962SSteven Rostedt	    if ($1 eq $version) {
1376f1a5b962SSteven Rostedt		$version_found = 1;
1377f1a5b962SSteven Rostedt	    } elsif ($version_found && $detect_triplefault) {
1378f1a5b962SSteven Rostedt		# We already booted into the kernel we are testing,
1379f1a5b962SSteven Rostedt		# but now we booted into another kernel?
1380f1a5b962SSteven Rostedt		# Consider this a triple fault.
1381f1a5b962SSteven Rostedt		doprint "Aleady booted in Linux kernel $version, but now\n";
1382f1a5b962SSteven Rostedt		doprint "we booted into Linux kernel $1.\n";
1383f1a5b962SSteven Rostedt		doprint "Assuming that this is a triple fault.\n";
1384f1a5b962SSteven Rostedt		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1385f1a5b962SSteven Rostedt		last;
1386f1a5b962SSteven Rostedt	    }
1387f1a5b962SSteven Rostedt	}
1388f1a5b962SSteven Rostedt
13892545eb61SSteven Rostedt	if ($line =~ /\n/) {
13902545eb61SSteven Rostedt	    $full_line = "";
13912545eb61SSteven Rostedt	}
13922d01b26aSSteven Rostedt
13932d01b26aSSteven Rostedt	if ($stop_test_after > 0 && !$booted && !$bug) {
13942d01b26aSSteven Rostedt	    if (time - $monitor_start > $stop_test_after) {
13954d62bf51SSteven Rostedt		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
13962d01b26aSSteven Rostedt		$done = 1;
13972d01b26aSSteven Rostedt	    }
13982d01b26aSSteven Rostedt	}
13992545eb61SSteven Rostedt    }
14002545eb61SSteven Rostedt
14017faafbd6SSteven Rostedt    close(DMESG);
14022545eb61SSteven Rostedt
14032545eb61SSteven Rostedt    if ($bug) {
14042b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
1405576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
14062545eb61SSteven Rostedt    }
14075f9b6cedSSteven Rostedt
1408a75fececSSteven Rostedt    if (!$booted) {
1409a75fececSSteven Rostedt	return 0 if ($in_bisect);
1410576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
1411a75fececSSteven Rostedt    }
1412a75fececSSteven Rostedt
14132b7d9b21SSteven Rostedt    return 1;
14142545eb61SSteven Rostedt}
14152545eb61SSteven Rostedt
1416db05cfefSSteven Rostedtsub do_post_install {
1417db05cfefSSteven Rostedt
1418db05cfefSSteven Rostedt    return if (!defined($post_install));
1419db05cfefSSteven Rostedt
1420db05cfefSSteven Rostedt    my $cp_post_install = $post_install;
1421db05cfefSSteven Rostedt    $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
1422db05cfefSSteven Rostedt    run_command "$cp_post_install" or
1423db05cfefSSteven Rostedt	dodie "Failed to run post install";
1424db05cfefSSteven Rostedt}
1425db05cfefSSteven Rostedt
14262545eb61SSteven Rostedtsub install {
14272545eb61SSteven Rostedt
1428e0a8742eSSteven Rostedt    return if ($no_install);
1429e0a8742eSSteven Rostedt
1430e48c5293SSteven Rostedt    run_scp "$outputdir/$build_target", "$target_image" or
14315c42fc5bSSteven Rostedt	dodie "failed to copy image";
14325f9b6cedSSteven Rostedt
14335f9b6cedSSteven Rostedt    my $install_mods = 0;
14345f9b6cedSSteven Rostedt
14355f9b6cedSSteven Rostedt    # should we process modules?
14365f9b6cedSSteven Rostedt    $install_mods = 0;
143751ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
14385f9b6cedSSteven Rostedt    while (<IN>) {
14395f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
14405f9b6cedSSteven Rostedt	    $install_mods = 1 if (defined($1));
14415f9b6cedSSteven Rostedt	    last;
14425f9b6cedSSteven Rostedt	}
14435f9b6cedSSteven Rostedt    }
14445f9b6cedSSteven Rostedt    close(IN);
14455f9b6cedSSteven Rostedt
14465f9b6cedSSteven Rostedt    if (!$install_mods) {
1447db05cfefSSteven Rostedt	do_post_install;
14485f9b6cedSSteven Rostedt	doprint "No modules needed\n";
14495f9b6cedSSteven Rostedt	return;
14502545eb61SSteven Rostedt    }
14512545eb61SSteven Rostedt
1452a75fececSSteven Rostedt    run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
14535f9b6cedSSteven Rostedt	dodie "Failed to install modules";
14545f9b6cedSSteven Rostedt
14552545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
1456a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
14572545eb61SSteven Rostedt
1458e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
14595c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
14602545eb61SSteven Rostedt
14615c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
1462a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
14635c42fc5bSSteven Rostedt	dodie "making tarball";
14645c42fc5bSSteven Rostedt
1465e48c5293SSteven Rostedt    run_scp "$tmpdir/$modtar", "/tmp" or
14665c42fc5bSSteven Rostedt	dodie "failed to copy modules";
14675c42fc5bSSteven Rostedt
1468a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
14695c42fc5bSSteven Rostedt
1470e7b13441SSteven Rostedt    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
14715c42fc5bSSteven Rostedt	dodie "failed to tar modules";
14725c42fc5bSSteven Rostedt
1473e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
14748b37ca8cSSteven Rostedt
1475db05cfefSSteven Rostedt    do_post_install;
14762545eb61SSteven Rostedt}
14772545eb61SSteven Rostedt
1478ddf607e5SSteven Rostedtsub get_version {
1479ddf607e5SSteven Rostedt    # get the release name
1480ddf607e5SSteven Rostedt    doprint "$make kernelrelease ... ";
1481ddf607e5SSteven Rostedt    $version = `$make kernelrelease | tail -1`;
1482ddf607e5SSteven Rostedt    chomp($version);
1483ddf607e5SSteven Rostedt    doprint "$version\n";
1484ddf607e5SSteven Rostedt}
1485ddf607e5SSteven Rostedt
1486ddf607e5SSteven Rostedtsub start_monitor_and_boot {
14879f7424ccSSteven Rostedt    # Make sure the stable kernel has finished booting
14889f7424ccSSteven Rostedt    start_monitor;
14899f7424ccSSteven Rostedt    wait_for_monitor 5;
14909f7424ccSSteven Rostedt    end_monitor;
14919f7424ccSSteven Rostedt
1492ddf607e5SSteven Rostedt    get_grub_index;
1493ddf607e5SSteven Rostedt    get_version;
1494ddf607e5SSteven Rostedt    install;
1495ddf607e5SSteven Rostedt
1496ddf607e5SSteven Rostedt    start_monitor;
1497ddf607e5SSteven Rostedt    return monitor;
1498ddf607e5SSteven Rostedt}
1499ddf607e5SSteven Rostedt
15006c5ee0beSSteven Rostedtsub check_buildlog {
15016c5ee0beSSteven Rostedt    my ($patch) = @_;
15026c5ee0beSSteven Rostedt
15036c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
15046c5ee0beSSteven Rostedt
15056c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
15066c5ee0beSSteven Rostedt	dodie "failed to show $patch";
15076c5ee0beSSteven Rostedt    while (<IN>) {
15086c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
15096c5ee0beSSteven Rostedt	    chomp $1;
15106c5ee0beSSteven Rostedt	    $files[$#files] = $1;
15116c5ee0beSSteven Rostedt	}
15126c5ee0beSSteven Rostedt    }
15136c5ee0beSSteven Rostedt    close(IN);
15146c5ee0beSSteven Rostedt
15156c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
15166c5ee0beSSteven Rostedt    while (<IN>) {
15176c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
15186c5ee0beSSteven Rostedt	    my $err = $1;
15196c5ee0beSSteven Rostedt	    foreach my $file (@files) {
1520a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
15216c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
15222b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
15236c5ee0beSSteven Rostedt		}
15246c5ee0beSSteven Rostedt	    }
15256c5ee0beSSteven Rostedt	}
15266c5ee0beSSteven Rostedt    }
15276c5ee0beSSteven Rostedt    close(IN);
15282b7d9b21SSteven Rostedt
15292b7d9b21SSteven Rostedt    return 1;
15306c5ee0beSSteven Rostedt}
15316c5ee0beSSteven Rostedt
1532fcb3f16aSSteven Rostedtsub apply_min_config {
1533fcb3f16aSSteven Rostedt    my $outconfig = "$output_config.new";
1534612b9e9bSSteven Rostedt
1535fcb3f16aSSteven Rostedt    # Read the config file and remove anything that
1536fcb3f16aSSteven Rostedt    # is in the force_config hash (from minconfig and others)
1537fcb3f16aSSteven Rostedt    # then add the force config back.
1538fcb3f16aSSteven Rostedt
1539fcb3f16aSSteven Rostedt    doprint "Applying minimum configurations into $output_config.new\n";
1540fcb3f16aSSteven Rostedt
1541fcb3f16aSSteven Rostedt    open (OUT, ">$outconfig") or
1542fcb3f16aSSteven Rostedt	dodie "Can't create $outconfig";
1543fcb3f16aSSteven Rostedt
1544fcb3f16aSSteven Rostedt    if (-f $output_config) {
1545fcb3f16aSSteven Rostedt	open (IN, $output_config) or
1546fcb3f16aSSteven Rostedt	    dodie "Failed to open $output_config";
1547fcb3f16aSSteven Rostedt	while (<IN>) {
1548fcb3f16aSSteven Rostedt	    if (/^(# )?(CONFIG_[^\s=]*)/) {
1549fcb3f16aSSteven Rostedt		next if (defined($force_config{$2}));
1550fcb3f16aSSteven Rostedt	    }
1551fcb3f16aSSteven Rostedt	    print OUT;
1552fcb3f16aSSteven Rostedt	}
1553fcb3f16aSSteven Rostedt	close IN;
1554fcb3f16aSSteven Rostedt    }
1555fcb3f16aSSteven Rostedt    foreach my $config (keys %force_config) {
1556fcb3f16aSSteven Rostedt	print OUT "$force_config{$config}\n";
1557fcb3f16aSSteven Rostedt    }
1558fcb3f16aSSteven Rostedt    close OUT;
1559fcb3f16aSSteven Rostedt
1560fcb3f16aSSteven Rostedt    run_command "mv $outconfig $output_config";
1561fcb3f16aSSteven Rostedt}
1562fcb3f16aSSteven Rostedt
1563fcb3f16aSSteven Rostedtsub make_oldconfig {
1564fcb3f16aSSteven Rostedt
15654c4ab120SSteven Rostedt    my @force_list = keys %force_config;
15664c4ab120SSteven Rostedt
15674c4ab120SSteven Rostedt    if ($#force_list >= 0) {
1568fcb3f16aSSteven Rostedt	apply_min_config;
15694c4ab120SSteven Rostedt    }
1570fcb3f16aSSteven Rostedt
1571fcb3f16aSSteven Rostedt    if (!run_command "$make oldnoconfig") {
1572612b9e9bSSteven Rostedt	# Perhaps oldnoconfig doesn't exist in this version of the kernel
1573612b9e9bSSteven Rostedt	# try a yes '' | oldconfig
1574612b9e9bSSteven Rostedt	doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1575fcb3f16aSSteven Rostedt	run_command "yes '' | $make oldconfig" or
1576612b9e9bSSteven Rostedt	    dodie "failed make config oldconfig";
1577612b9e9bSSteven Rostedt    }
1578612b9e9bSSteven Rostedt}
1579612b9e9bSSteven Rostedt
1580fcb3f16aSSteven Rostedt# read a config file and use this to force new configs.
1581fcb3f16aSSteven Rostedtsub load_force_config {
1582fcb3f16aSSteven Rostedt    my ($config) = @_;
1583fcb3f16aSSteven Rostedt
1584fcb3f16aSSteven Rostedt    open(IN, $config) or
1585fcb3f16aSSteven Rostedt	dodie "failed to read $config";
1586fcb3f16aSSteven Rostedt    while (<IN>) {
1587fcb3f16aSSteven Rostedt	chomp;
1588fcb3f16aSSteven Rostedt	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1589fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1590fcb3f16aSSteven Rostedt	} elsif (/^# (CONFIG_\S*) is not set/) {
1591fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1592fcb3f16aSSteven Rostedt	}
1593fcb3f16aSSteven Rostedt    }
1594fcb3f16aSSteven Rostedt    close IN;
1595fcb3f16aSSteven Rostedt}
1596fcb3f16aSSteven Rostedt
15972545eb61SSteven Rostedtsub build {
15982545eb61SSteven Rostedt    my ($type) = @_;
15992545eb61SSteven Rostedt
16007faafbd6SSteven Rostedt    unlink $buildlog;
16017faafbd6SSteven Rostedt
16024ab1cce5SSteven Rostedt    # Failed builds should not reboot the target
16034ab1cce5SSteven Rostedt    my $save_no_reboot = $no_reboot;
16044ab1cce5SSteven Rostedt    $no_reboot = 1;
16054ab1cce5SSteven Rostedt
16060bd6c1a3SSteven Rostedt    if (defined($pre_build)) {
16070bd6c1a3SSteven Rostedt	my $ret = run_command $pre_build;
16080bd6c1a3SSteven Rostedt	if (!$ret && defined($pre_build_die) &&
16090bd6c1a3SSteven Rostedt	    $pre_build_die) {
16100bd6c1a3SSteven Rostedt	    dodie "failed to pre_build\n";
16110bd6c1a3SSteven Rostedt	}
16120bd6c1a3SSteven Rostedt    }
16130bd6c1a3SSteven Rostedt
161475c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
161551ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
161675c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
16175f9b6cedSSteven Rostedt
161875c3fda7SSteven Rostedt	$type = "oldconfig";
161975c3fda7SSteven Rostedt    }
162075c3fda7SSteven Rostedt
16215c42fc5bSSteven Rostedt    # old config can ask questions
16225c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
16239386c6abSSteven Rostedt	$type = "oldnoconfig";
162475c3fda7SSteven Rostedt
162575c3fda7SSteven Rostedt	# allow for empty configs
162651ad1dd1SSteven Rostedt	run_command "touch $output_config";
162775c3fda7SSteven Rostedt
162813488231SAndrew Jones	if (!$noclean) {
162951ad1dd1SSteven Rostedt	    run_command "mv $output_config $outputdir/config_temp" or
16305c42fc5bSSteven Rostedt		dodie "moving .config";
16315c42fc5bSSteven Rostedt
163213488231SAndrew Jones	    run_command "$make mrproper" or dodie "make mrproper";
16335c42fc5bSSteven Rostedt
163451ad1dd1SSteven Rostedt	    run_command "mv $outputdir/config_temp $output_config" or
16355c42fc5bSSteven Rostedt		dodie "moving config_temp";
163613488231SAndrew Jones	}
16375c42fc5bSSteven Rostedt
16385c42fc5bSSteven Rostedt    } elsif (!$noclean) {
163951ad1dd1SSteven Rostedt	unlink "$output_config";
16405f9b6cedSSteven Rostedt	run_command "$make mrproper" or
16415c42fc5bSSteven Rostedt	    dodie "make mrproper";
16425c42fc5bSSteven Rostedt    }
16432545eb61SSteven Rostedt
16442545eb61SSteven Rostedt    # add something to distinguish this build
1645a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
1646a75fececSSteven Rostedt    print OUT "$localversion\n";
16472545eb61SSteven Rostedt    close(OUT);
16482545eb61SSteven Rostedt
16495f9b6cedSSteven Rostedt    if (defined($minconfig)) {
1650fcb3f16aSSteven Rostedt	load_force_config($minconfig);
16512545eb61SSteven Rostedt    }
16522545eb61SSteven Rostedt
1653fcb3f16aSSteven Rostedt    if ($type ne "oldnoconfig") {
1654fcb3f16aSSteven Rostedt	run_command "$make $type" or
16555c42fc5bSSteven Rostedt	    dodie "failed make config";
1656612b9e9bSSteven Rostedt    }
1657fcb3f16aSSteven Rostedt    # Run old config regardless, to enforce min configurations
1658fcb3f16aSSteven Rostedt    make_oldconfig;
16592545eb61SSteven Rostedt
1660a75fececSSteven Rostedt    $redirect = "$buildlog";
16610bd6c1a3SSteven Rostedt    my $build_ret = run_command "$make $build_options";
16626c5ee0beSSteven Rostedt    undef $redirect;
16630bd6c1a3SSteven Rostedt
16640bd6c1a3SSteven Rostedt    if (defined($post_build)) {
16650bd6c1a3SSteven Rostedt	my $ret = run_command $post_build;
16660bd6c1a3SSteven Rostedt	if (!$ret && defined($post_build_die) &&
16670bd6c1a3SSteven Rostedt	    $post_build_die) {
16680bd6c1a3SSteven Rostedt	    dodie "failed to post_build\n";
16690bd6c1a3SSteven Rostedt	}
16700bd6c1a3SSteven Rostedt    }
16710bd6c1a3SSteven Rostedt
16720bd6c1a3SSteven Rostedt    if (!$build_ret) {
16735f9b6cedSSteven Rostedt	# bisect may need this to pass
16744ab1cce5SSteven Rostedt	if ($in_bisect) {
16754ab1cce5SSteven Rostedt	    $no_reboot = $save_no_reboot;
16764ab1cce5SSteven Rostedt	    return 0;
16774ab1cce5SSteven Rostedt	}
16782b7d9b21SSteven Rostedt	fail "failed build" and return 0;
16792545eb61SSteven Rostedt    }
16805f9b6cedSSteven Rostedt
16814ab1cce5SSteven Rostedt    $no_reboot = $save_no_reboot;
16824ab1cce5SSteven Rostedt
16832b7d9b21SSteven Rostedt    return 1;
16842545eb61SSteven Rostedt}
16852545eb61SSteven Rostedt
168675c3fda7SSteven Rostedtsub halt {
1687e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
1688576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
1689576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
1690576f627cSSteven Rostedt	    run_command "$power_off";
1691576f627cSSteven Rostedt	}
1692576f627cSSteven Rostedt    } else {
169375c3fda7SSteven Rostedt	# nope? the zap it!
1694a75fececSSteven Rostedt	run_command "$power_off";
169575c3fda7SSteven Rostedt    }
169675c3fda7SSteven Rostedt}
169775c3fda7SSteven Rostedt
16985f9b6cedSSteven Rostedtsub success {
16995f9b6cedSSteven Rostedt    my ($i) = @_;
17005f9b6cedSSteven Rostedt
1701e48c5293SSteven Rostedt    $successes++;
1702e48c5293SSteven Rostedt
17039064af52SSteven Rostedt    my $name = "";
17049064af52SSteven Rostedt
17059064af52SSteven Rostedt    if (defined($test_name)) {
17069064af52SSteven Rostedt	$name = " ($test_name)";
17079064af52SSteven Rostedt    }
17089064af52SSteven Rostedt
17095f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
17105f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
17119064af52SSteven Rostedt    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
17125f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
17135f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
17145f9b6cedSSteven Rostedt
1715de5b6e3bSRabin Vincent    if (defined($store_successes)) {
1716de5b6e3bSRabin Vincent        save_logs "success", $store_successes;
1717de5b6e3bSRabin Vincent    }
1718de5b6e3bSRabin Vincent
1719576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1720a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
17212728be41SAndrew Jones	reboot $sleep_time;
17225f9b6cedSSteven Rostedt    }
17235f9b6cedSSteven Rostedt}
17245f9b6cedSSteven Rostedt
1725c960bb9fSSteven Rostedtsub answer_bisect {
1726c960bb9fSSteven Rostedt    for (;;) {
1727c960bb9fSSteven Rostedt	doprint "Pass or fail? [p/f]";
1728c960bb9fSSteven Rostedt	my $ans = <STDIN>;
1729c960bb9fSSteven Rostedt	chomp $ans;
1730c960bb9fSSteven Rostedt	if ($ans eq "p" || $ans eq "P") {
1731c960bb9fSSteven Rostedt	    return 1;
1732c960bb9fSSteven Rostedt	} elsif ($ans eq "f" || $ans eq "F") {
1733c960bb9fSSteven Rostedt	    return 0;
1734c960bb9fSSteven Rostedt	} else {
1735c960bb9fSSteven Rostedt	    print "Please answer 'P' or 'F'\n";
1736c960bb9fSSteven Rostedt	}
1737c960bb9fSSteven Rostedt    }
1738c960bb9fSSteven Rostedt}
1739c960bb9fSSteven Rostedt
17405a391fbfSSteven Rostedtsub child_run_test {
17417faafbd6SSteven Rostedt    my $failed = 0;
17425a391fbfSSteven Rostedt
17437faafbd6SSteven Rostedt    # child should have no power
1744a75fececSSteven Rostedt    $reboot_on_error = 0;
1745a75fececSSteven Rostedt    $poweroff_on_error = 0;
1746a75fececSSteven Rostedt    $die_on_failure = 1;
17477faafbd6SSteven Rostedt
1748a9dd5d63SRabin Vincent    $redirect = "$testlog";
17497faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
1750a9dd5d63SRabin Vincent    undef $redirect;
1751a9dd5d63SRabin Vincent
17525a391fbfSSteven Rostedt    exit $failed;
17535a391fbfSSteven Rostedt}
17545a391fbfSSteven Rostedt
17555a391fbfSSteven Rostedtmy $child_done;
17565a391fbfSSteven Rostedt
17575a391fbfSSteven Rostedtsub child_finished {
17585a391fbfSSteven Rostedt    $child_done = 1;
17595a391fbfSSteven Rostedt}
17605a391fbfSSteven Rostedt
17615a391fbfSSteven Rostedtsub do_run_test {
17625a391fbfSSteven Rostedt    my $child_pid;
17635a391fbfSSteven Rostedt    my $child_exit;
17645a391fbfSSteven Rostedt    my $line;
17655a391fbfSSteven Rostedt    my $full_line;
17665a391fbfSSteven Rostedt    my $bug = 0;
17675a391fbfSSteven Rostedt
17687faafbd6SSteven Rostedt    wait_for_monitor 1;
17695a391fbfSSteven Rostedt
17707faafbd6SSteven Rostedt    doprint "run test $run_test\n";
17715a391fbfSSteven Rostedt
17725a391fbfSSteven Rostedt    $child_done = 0;
17735a391fbfSSteven Rostedt
17745a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
17755a391fbfSSteven Rostedt
17765a391fbfSSteven Rostedt    $child_pid = fork;
17775a391fbfSSteven Rostedt
17785a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
17795a391fbfSSteven Rostedt
17805a391fbfSSteven Rostedt    $full_line = "";
17815a391fbfSSteven Rostedt
17825a391fbfSSteven Rostedt    do {
17837faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
17845a391fbfSSteven Rostedt	if (defined($line)) {
17855a391fbfSSteven Rostedt
17865a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
17875a391fbfSSteven Rostedt	    $full_line .= $line;
17888ea0e063SSteven Rostedt	    doprint $line;
17895a391fbfSSteven Rostedt
17905a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
17915a391fbfSSteven Rostedt		$bug = 1;
17925a391fbfSSteven Rostedt	    }
17935a391fbfSSteven Rostedt
17945a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
17955a391fbfSSteven Rostedt		$bug = 1;
17965a391fbfSSteven Rostedt	    }
17975a391fbfSSteven Rostedt
17985a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
17995a391fbfSSteven Rostedt		$full_line = "";
18005a391fbfSSteven Rostedt	    }
18015a391fbfSSteven Rostedt	}
18025a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
18035a391fbfSSteven Rostedt
18045a391fbfSSteven Rostedt    if ($bug) {
18058ea0e063SSteven Rostedt	my $failure_start = time;
18068ea0e063SSteven Rostedt	my $now;
18078ea0e063SSteven Rostedt	do {
18088ea0e063SSteven Rostedt	    $line = wait_for_input($monitor_fp, 1);
18098ea0e063SSteven Rostedt	    if (defined($line)) {
18108ea0e063SSteven Rostedt		doprint $line;
18118ea0e063SSteven Rostedt	    }
18128ea0e063SSteven Rostedt	    $now = time;
18138ea0e063SSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
18148ea0e063SSteven Rostedt		last;
18158ea0e063SSteven Rostedt	    }
18168ea0e063SSteven Rostedt	} while (defined($line));
18178ea0e063SSteven Rostedt
18185a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
18195a391fbfSSteven Rostedt	# kill the child with extreme prejudice
18205a391fbfSSteven Rostedt	kill 9, $child_pid;
18215a391fbfSSteven Rostedt    }
18225a391fbfSSteven Rostedt
18235a391fbfSSteven Rostedt    waitpid $child_pid, 0;
18245a391fbfSSteven Rostedt    $child_exit = $?;
18255a391fbfSSteven Rostedt
18265a391fbfSSteven Rostedt    if ($bug || $child_exit) {
18272b7d9b21SSteven Rostedt	return 0 if $in_bisect;
18282b7d9b21SSteven Rostedt	fail "test failed" and return 0;
18295a391fbfSSteven Rostedt    }
18302b7d9b21SSteven Rostedt    return 1;
18315a391fbfSSteven Rostedt}
18325a391fbfSSteven Rostedt
1833a75fececSSteven Rostedtsub run_git_bisect {
1834a75fececSSteven Rostedt    my ($command) = @_;
1835a75fececSSteven Rostedt
1836a75fececSSteven Rostedt    doprint "$command ... ";
1837a75fececSSteven Rostedt
1838a75fececSSteven Rostedt    my $output = `$command 2>&1`;
1839a75fececSSteven Rostedt    my $ret = $?;
1840a75fececSSteven Rostedt
1841a75fececSSteven Rostedt    logit $output;
1842a75fececSSteven Rostedt
1843a75fececSSteven Rostedt    if ($ret) {
1844a75fececSSteven Rostedt	doprint "FAILED\n";
1845a75fececSSteven Rostedt	dodie "Failed to git bisect";
1846a75fececSSteven Rostedt    }
1847a75fececSSteven Rostedt
1848a75fececSSteven Rostedt    doprint "SUCCESS\n";
1849a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1850a75fececSSteven Rostedt	doprint "$1 [$2]\n";
1851a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1852a75fececSSteven Rostedt	$bisect_bad = $1;
1853a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
1854a75fececSSteven Rostedt	return 0;
1855a75fececSSteven Rostedt    } else {
1856a75fececSSteven Rostedt	# we already logged it, just print it now.
1857a75fececSSteven Rostedt	print $output;
1858a75fececSSteven Rostedt    }
1859a75fececSSteven Rostedt
1860a75fececSSteven Rostedt    return 1;
1861a75fececSSteven Rostedt}
1862a75fececSSteven Rostedt
1863c23dca7cSSteven Rostedtsub bisect_reboot {
1864c23dca7cSSteven Rostedt    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
18652728be41SAndrew Jones    reboot $bisect_sleep_time;
1866c23dca7cSSteven Rostedt}
1867c23dca7cSSteven Rostedt
1868c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip
18690a05c769SSteven Rostedtsub run_bisect_test {
18700a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
18715f9b6cedSSteven Rostedt
18722b7d9b21SSteven Rostedt    my $failed = 0;
18735f9b6cedSSteven Rostedt    my $result;
18745f9b6cedSSteven Rostedt    my $output;
18755f9b6cedSSteven Rostedt    my $ret;
18765f9b6cedSSteven Rostedt
18770a05c769SSteven Rostedt    $in_bisect = 1;
18780a05c769SSteven Rostedt
18790a05c769SSteven Rostedt    build $buildtype or $failed = 1;
18805f9b6cedSSteven Rostedt
18815f9b6cedSSteven Rostedt    if ($type ne "build") {
1882c23dca7cSSteven Rostedt	if ($failed && $bisect_skip) {
1883c23dca7cSSteven Rostedt	    $in_bisect = 0;
1884c23dca7cSSteven Rostedt	    return -1;
1885c23dca7cSSteven Rostedt	}
18867faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
18875f9b6cedSSteven Rostedt
18885f9b6cedSSteven Rostedt	# Now boot the box
1889ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
18905f9b6cedSSteven Rostedt
18915f9b6cedSSteven Rostedt	if ($type ne "boot") {
1892c23dca7cSSteven Rostedt	    if ($failed && $bisect_skip) {
1893c23dca7cSSteven Rostedt		end_monitor;
1894c23dca7cSSteven Rostedt		bisect_reboot;
1895c23dca7cSSteven Rostedt		$in_bisect = 0;
1896c23dca7cSSteven Rostedt		return -1;
1897c23dca7cSSteven Rostedt	    }
18987faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
18995a391fbfSSteven Rostedt
19002b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
19015f9b6cedSSteven Rostedt	}
19027faafbd6SSteven Rostedt	end_monitor;
19035f9b6cedSSteven Rostedt    }
19045f9b6cedSSteven Rostedt
19055f9b6cedSSteven Rostedt    if ($failed) {
19060a05c769SSteven Rostedt	$result = 0;
19075f9b6cedSSteven Rostedt    } else {
19080a05c769SSteven Rostedt	$result = 1;
19095f9b6cedSSteven Rostedt    }
19104025bc62SSteven Rostedt
19114025bc62SSteven Rostedt    # reboot the box to a kernel we can ssh to
19124025bc62SSteven Rostedt    if ($type ne "build") {
19134025bc62SSteven Rostedt	bisect_reboot;
19144025bc62SSteven Rostedt    }
19150a05c769SSteven Rostedt    $in_bisect = 0;
19160a05c769SSteven Rostedt
19170a05c769SSteven Rostedt    return $result;
19180a05c769SSteven Rostedt}
19190a05c769SSteven Rostedt
19200a05c769SSteven Rostedtsub run_bisect {
19210a05c769SSteven Rostedt    my ($type) = @_;
19220a05c769SSteven Rostedt    my $buildtype = "oldconfig";
19230a05c769SSteven Rostedt
19240a05c769SSteven Rostedt    # We should have a minconfig to use?
19250a05c769SSteven Rostedt    if (defined($minconfig)) {
19260a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
19270a05c769SSteven Rostedt    }
19280a05c769SSteven Rostedt
19290a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
19300a05c769SSteven Rostedt
1931c960bb9fSSteven Rostedt    if ($bisect_manual) {
1932c960bb9fSSteven Rostedt	$ret = answer_bisect;
1933c960bb9fSSteven Rostedt    }
19345f9b6cedSSteven Rostedt
1935d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
1936d6ce2a0bSSteven Rostedt    if ($reverse_bisect) {
19370a05c769SSteven Rostedt	$ret = !$ret;
1938d6ce2a0bSSteven Rostedt    }
1939d6ce2a0bSSteven Rostedt
1940c23dca7cSSteven Rostedt    if ($ret > 0) {
19410a05c769SSteven Rostedt	return "good";
1942c23dca7cSSteven Rostedt    } elsif ($ret == 0) {
19430a05c769SSteven Rostedt	return  "bad";
1944c23dca7cSSteven Rostedt    } elsif ($bisect_skip) {
1945c23dca7cSSteven Rostedt	doprint "HIT A BAD COMMIT ... SKIPPING\n";
1946c23dca7cSSteven Rostedt	return "skip";
19470a05c769SSteven Rostedt    }
19485f9b6cedSSteven Rostedt}
19495f9b6cedSSteven Rostedt
1950dad98754SSteven Rostedtsub update_bisect_replay {
1951dad98754SSteven Rostedt    my $tmp_log = "$tmpdir/ktest_bisect_log";
1952dad98754SSteven Rostedt    run_command "git bisect log > $tmp_log" or
1953dad98754SSteven Rostedt	die "can't create bisect log";
1954dad98754SSteven Rostedt    return $tmp_log;
1955dad98754SSteven Rostedt}
1956dad98754SSteven Rostedt
19575f9b6cedSSteven Rostedtsub bisect {
19585f9b6cedSSteven Rostedt    my ($i) = @_;
19595f9b6cedSSteven Rostedt
19605f9b6cedSSteven Rostedt    my $result;
19615f9b6cedSSteven Rostedt
19625f9b6cedSSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($opt{"BISECT_GOOD[$i]"}));
19635f9b6cedSSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($opt{"BISECT_BAD[$i]"}));
19645f9b6cedSSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($opt{"BISECT_TYPE[$i]"}));
19655f9b6cedSSteven Rostedt
19665f9b6cedSSteven Rostedt    my $good = $opt{"BISECT_GOOD[$i]"};
19675f9b6cedSSteven Rostedt    my $bad = $opt{"BISECT_BAD[$i]"};
19685f9b6cedSSteven Rostedt    my $type = $opt{"BISECT_TYPE[$i]"};
1969a75fececSSteven Rostedt    my $start = $opt{"BISECT_START[$i]"};
1970a75fececSSteven Rostedt    my $replay = $opt{"BISECT_REPLAY[$i]"};
19713410f6fdSSteven Rostedt    my $start_files = $opt{"BISECT_FILES[$i]"};
19723410f6fdSSteven Rostedt
19733410f6fdSSteven Rostedt    if (defined($start_files)) {
19743410f6fdSSteven Rostedt	$start_files = " -- " . $start_files;
19753410f6fdSSteven Rostedt    } else {
19763410f6fdSSteven Rostedt	$start_files = "";
19773410f6fdSSteven Rostedt    }
19785f9b6cedSSteven Rostedt
1979a57419b3SSteven Rostedt    # convert to true sha1's
1980a57419b3SSteven Rostedt    $good = get_sha1($good);
1981a57419b3SSteven Rostedt    $bad = get_sha1($bad);
1982a57419b3SSteven Rostedt
1983d6ce2a0bSSteven Rostedt    if (defined($opt{"BISECT_REVERSE[$i]"}) &&
1984d6ce2a0bSSteven Rostedt	$opt{"BISECT_REVERSE[$i]"} == 1) {
1985d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1986d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
1987d6ce2a0bSSteven Rostedt    } else {
1988d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
1989d6ce2a0bSSteven Rostedt    }
1990d6ce2a0bSSteven Rostedt
19915a391fbfSSteven Rostedt    # Can't have a test without having a test to run
19925a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
19935a391fbfSSteven Rostedt	$type = "boot";
19945a391fbfSSteven Rostedt    }
19955a391fbfSSteven Rostedt
1996dad98754SSteven Rostedt    # Check if a bisect was running
1997dad98754SSteven Rostedt    my $bisect_start_file = "$builddir/.git/BISECT_START";
1998dad98754SSteven Rostedt
1999a75fececSSteven Rostedt    my $check = $opt{"BISECT_CHECK[$i]"};
2000dad98754SSteven Rostedt    my $do_check = defined($check) && $check ne "0";
2001dad98754SSteven Rostedt
2002dad98754SSteven Rostedt    if ( -f $bisect_start_file ) {
2003dad98754SSteven Rostedt	print "Bisect in progress found\n";
2004dad98754SSteven Rostedt	if ($do_check) {
2005dad98754SSteven Rostedt	    print " If you say yes, then no checks of good or bad will be done\n";
2006dad98754SSteven Rostedt	}
2007dad98754SSteven Rostedt	if (defined($replay)) {
2008dad98754SSteven Rostedt	    print "** BISECT_REPLAY is defined in config file **";
2009dad98754SSteven Rostedt	    print " Ignore config option and perform new git bisect log?\n";
2010dad98754SSteven Rostedt	    if (read_ync " (yes, no, or cancel) ") {
2011dad98754SSteven Rostedt		$replay = update_bisect_replay;
2012dad98754SSteven Rostedt		$do_check = 0;
2013dad98754SSteven Rostedt	    }
2014dad98754SSteven Rostedt	} elsif (read_yn "read git log and continue?") {
2015dad98754SSteven Rostedt	    $replay = update_bisect_replay;
2016dad98754SSteven Rostedt	    $do_check = 0;
2017dad98754SSteven Rostedt	}
2018dad98754SSteven Rostedt    }
2019dad98754SSteven Rostedt
2020dad98754SSteven Rostedt    if ($do_check) {
2021a75fececSSteven Rostedt
2022a75fececSSteven Rostedt	# get current HEAD
2023a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
2024a75fececSSteven Rostedt
2025a75fececSSteven Rostedt	if ($check ne "good") {
2026a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
2027a75fececSSteven Rostedt	    run_command "git checkout $bad" or
2028a75fececSSteven Rostedt		die "Failed to checkout $bad";
2029a75fececSSteven Rostedt
2030a75fececSSteven Rostedt	    $result = run_bisect $type;
2031a75fececSSteven Rostedt
2032a75fececSSteven Rostedt	    if ($result ne "bad") {
2033a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
2034a75fececSSteven Rostedt	    }
2035a75fececSSteven Rostedt	}
2036a75fececSSteven Rostedt
2037a75fececSSteven Rostedt	if ($check ne "bad") {
2038a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
2039a75fececSSteven Rostedt	    run_command "git checkout $good" or
2040a75fececSSteven Rostedt		die "Failed to checkout $good";
2041a75fececSSteven Rostedt
2042a75fececSSteven Rostedt	    $result = run_bisect $type;
2043a75fececSSteven Rostedt
2044a75fececSSteven Rostedt	    if ($result ne "good") {
2045a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
2046a75fececSSteven Rostedt	    }
2047a75fececSSteven Rostedt	}
2048a75fececSSteven Rostedt
2049a75fececSSteven Rostedt	# checkout where we started
2050a75fececSSteven Rostedt	run_command "git checkout $head" or
2051a75fececSSteven Rostedt	    die "Failed to checkout $head";
2052a75fececSSteven Rostedt    }
2053a75fececSSteven Rostedt
20543410f6fdSSteven Rostedt    run_command "git bisect start$start_files" or
2055a75fececSSteven Rostedt	dodie "could not start bisect";
2056a75fececSSteven Rostedt
2057a75fececSSteven Rostedt    run_command "git bisect good $good" or
2058a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
2059a75fececSSteven Rostedt
2060a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
2061a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
2062a75fececSSteven Rostedt
2063a75fececSSteven Rostedt    if (defined($replay)) {
2064a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
2065a75fececSSteven Rostedt	    dodie "failed to run replay";
2066a75fececSSteven Rostedt    }
2067a75fececSSteven Rostedt
2068a75fececSSteven Rostedt    if (defined($start)) {
2069a75fececSSteven Rostedt	run_command "git checkout $start" or
2070a75fececSSteven Rostedt	    dodie "failed to checkout $start";
2071a75fececSSteven Rostedt    }
2072a75fececSSteven Rostedt
2073a75fececSSteven Rostedt    my $test;
20745f9b6cedSSteven Rostedt    do {
20755f9b6cedSSteven Rostedt	$result = run_bisect $type;
2076a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
2077a75fececSSteven Rostedt    } while ($test);
20785f9b6cedSSteven Rostedt
20795f9b6cedSSteven Rostedt    run_command "git bisect log" or
20805f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
20815f9b6cedSSteven Rostedt
20825f9b6cedSSteven Rostedt    run_command "git bisect reset" or
20835f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
20845f9b6cedSSteven Rostedt
20855f9b6cedSSteven Rostedt    doprint "Bad commit was [$bisect_bad]\n";
20865f9b6cedSSteven Rostedt
20870a05c769SSteven Rostedt    success $i;
20880a05c769SSteven Rostedt}
20890a05c769SSteven Rostedt
20900a05c769SSteven Rostedtmy %config_ignore;
20910a05c769SSteven Rostedtmy %config_set;
20920a05c769SSteven Rostedt
20930a05c769SSteven Rostedtmy %config_list;
20940a05c769SSteven Rostedtmy %null_config;
20950a05c769SSteven Rostedt
20960a05c769SSteven Rostedtmy %dependency;
20970a05c769SSteven Rostedt
20984c4ab120SSteven Rostedtsub assign_configs {
20994c4ab120SSteven Rostedt    my ($hash, $config) = @_;
21000a05c769SSteven Rostedt
21010a05c769SSteven Rostedt    open (IN, $config)
21020a05c769SSteven Rostedt	or dodie "Failed to read $config";
21030a05c769SSteven Rostedt
21040a05c769SSteven Rostedt    while (<IN>) {
21059bf71749SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
21064c4ab120SSteven Rostedt	    ${$hash}{$2} = $1;
21070a05c769SSteven Rostedt	}
21080a05c769SSteven Rostedt    }
21090a05c769SSteven Rostedt
21100a05c769SSteven Rostedt    close(IN);
21110a05c769SSteven Rostedt}
21120a05c769SSteven Rostedt
21134c4ab120SSteven Rostedtsub process_config_ignore {
21144c4ab120SSteven Rostedt    my ($config) = @_;
21154c4ab120SSteven Rostedt
21164c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
21174c4ab120SSteven Rostedt}
21184c4ab120SSteven Rostedt
21190a05c769SSteven Rostedtsub read_current_config {
21200a05c769SSteven Rostedt    my ($config_ref) = @_;
21210a05c769SSteven Rostedt
21220a05c769SSteven Rostedt    %{$config_ref} = ();
21230a05c769SSteven Rostedt    undef %{$config_ref};
21240a05c769SSteven Rostedt
21250a05c769SSteven Rostedt    my @key = keys %{$config_ref};
21260a05c769SSteven Rostedt    if ($#key >= 0) {
21270a05c769SSteven Rostedt	print "did not delete!\n";
21280a05c769SSteven Rostedt	exit;
21290a05c769SSteven Rostedt    }
21300a05c769SSteven Rostedt    open (IN, "$output_config");
21310a05c769SSteven Rostedt
21320a05c769SSteven Rostedt    while (<IN>) {
21330a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
21340a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
21350a05c769SSteven Rostedt	}
21360a05c769SSteven Rostedt    }
21370a05c769SSteven Rostedt    close(IN);
21380a05c769SSteven Rostedt}
21390a05c769SSteven Rostedt
21400a05c769SSteven Rostedtsub get_dependencies {
21410a05c769SSteven Rostedt    my ($config) = @_;
21420a05c769SSteven Rostedt
21430a05c769SSteven Rostedt    my $arr = $dependency{$config};
21440a05c769SSteven Rostedt    if (!defined($arr)) {
21450a05c769SSteven Rostedt	return ();
21460a05c769SSteven Rostedt    }
21470a05c769SSteven Rostedt
21480a05c769SSteven Rostedt    my @deps = @{$arr};
21490a05c769SSteven Rostedt
21500a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
21510a05c769SSteven Rostedt	print "ADD DEP $dep\n";
21520a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
21530a05c769SSteven Rostedt    }
21540a05c769SSteven Rostedt
21550a05c769SSteven Rostedt    return @deps;
21560a05c769SSteven Rostedt}
21570a05c769SSteven Rostedt
21580a05c769SSteven Rostedtsub create_config {
21590a05c769SSteven Rostedt    my @configs = @_;
21600a05c769SSteven Rostedt
21610a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
21620a05c769SSteven Rostedt
21630a05c769SSteven Rostedt    foreach my $config (@configs) {
21640a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
21650a05c769SSteven Rostedt	my @deps = get_dependencies $config;
21660a05c769SSteven Rostedt	foreach my $dep (@deps) {
21670a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
21680a05c769SSteven Rostedt	}
21690a05c769SSteven Rostedt    }
21700a05c769SSteven Rostedt
21710a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
21720a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
21730a05c769SSteven Rostedt    }
21740a05c769SSteven Rostedt    close(OUT);
21750a05c769SSteven Rostedt
21760a05c769SSteven Rostedt#    exit;
2177fcb3f16aSSteven Rostedt    make_oldconfig;
21780a05c769SSteven Rostedt}
21790a05c769SSteven Rostedt
21800a05c769SSteven Rostedtsub compare_configs {
21810a05c769SSteven Rostedt    my (%a, %b) = @_;
21820a05c769SSteven Rostedt
21830a05c769SSteven Rostedt    foreach my $item (keys %a) {
21840a05c769SSteven Rostedt	if (!defined($b{$item})) {
21850a05c769SSteven Rostedt	    print "diff $item\n";
21860a05c769SSteven Rostedt	    return 1;
21870a05c769SSteven Rostedt	}
21880a05c769SSteven Rostedt	delete $b{$item};
21890a05c769SSteven Rostedt    }
21900a05c769SSteven Rostedt
21910a05c769SSteven Rostedt    my @keys = keys %b;
21920a05c769SSteven Rostedt    if ($#keys) {
21930a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
21940a05c769SSteven Rostedt    }
21950a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
21960a05c769SSteven Rostedt
21970a05c769SSteven Rostedt    return 0;
21980a05c769SSteven Rostedt}
21990a05c769SSteven Rostedt
22000a05c769SSteven Rostedtsub run_config_bisect_test {
22010a05c769SSteven Rostedt    my ($type) = @_;
22020a05c769SSteven Rostedt
22030a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
22040a05c769SSteven Rostedt}
22050a05c769SSteven Rostedt
22060a05c769SSteven Rostedtsub process_passed {
22070a05c769SSteven Rostedt    my (%configs) = @_;
22080a05c769SSteven Rostedt
22090a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
22100a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
22110a05c769SSteven Rostedt    # Add them to the min options.
22120a05c769SSteven Rostedt    foreach my $config (keys %configs) {
22130a05c769SSteven Rostedt	if (defined($config_list{$config})) {
22140a05c769SSteven Rostedt	    doprint " removing $config\n";
22150a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
22160a05c769SSteven Rostedt	    delete $config_list{$config};
22170a05c769SSteven Rostedt	}
22180a05c769SSteven Rostedt    }
2219f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
2220f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
22210a05c769SSteven Rostedt}
22220a05c769SSteven Rostedt
22230a05c769SSteven Rostedtsub process_failed {
22240a05c769SSteven Rostedt    my ($config) = @_;
22250a05c769SSteven Rostedt
22260a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
22270a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
22280a05c769SSteven Rostedt    doprint "***************************************\n\n";
22290a05c769SSteven Rostedt}
22300a05c769SSteven Rostedt
22310a05c769SSteven Rostedtsub run_config_bisect {
22320a05c769SSteven Rostedt
22330a05c769SSteven Rostedt    my @start_list = keys %config_list;
22340a05c769SSteven Rostedt
22350a05c769SSteven Rostedt    if ($#start_list < 0) {
22360a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
22370a05c769SSteven Rostedt	return -1;
22380a05c769SSteven Rostedt    }
22390a05c769SSteven Rostedt
22400a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
22410a05c769SSteven Rostedt    my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
22420a05c769SSteven Rostedt    my $ret;
22430a05c769SSteven Rostedt    my %current_config;
22440a05c769SSteven Rostedt
22450a05c769SSteven Rostedt    my $count = $#start_list + 1;
22460a05c769SSteven Rostedt    doprint "  $count configs to test\n";
22470a05c769SSteven Rostedt
22480a05c769SSteven Rostedt    my $half = int($#start_list / 2);
22490a05c769SSteven Rostedt
22500a05c769SSteven Rostedt    do {
22510a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
22520a05c769SSteven Rostedt
22530a05c769SSteven Rostedt	create_config @tophalf;
22540a05c769SSteven Rostedt	read_current_config \%current_config;
22550a05c769SSteven Rostedt
22560a05c769SSteven Rostedt	$count = $#tophalf + 1;
22570a05c769SSteven Rostedt	doprint "Testing $count configs\n";
22580a05c769SSteven Rostedt	my $found = 0;
22590a05c769SSteven Rostedt	# make sure we test something
22600a05c769SSteven Rostedt	foreach my $config (@tophalf) {
22610a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
22620a05c769SSteven Rostedt		logit " $config\n";
22630a05c769SSteven Rostedt		$found = 1;
22640a05c769SSteven Rostedt	    }
22650a05c769SSteven Rostedt	}
22660a05c769SSteven Rostedt	if (!$found) {
22670a05c769SSteven Rostedt	    # try the other half
22680a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
22694c8cc55bSSteven Rostedt	    @tophalf = @start_list[$half + 1 .. $#start_list];
22700a05c769SSteven Rostedt	    create_config @tophalf;
22710a05c769SSteven Rostedt	    read_current_config \%current_config;
22720a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
22730a05c769SSteven Rostedt		if (defined($current_config{$config})) {
22740a05c769SSteven Rostedt		    logit " $config\n";
22750a05c769SSteven Rostedt		    $found = 1;
22760a05c769SSteven Rostedt		}
22770a05c769SSteven Rostedt	    }
22780a05c769SSteven Rostedt	    if (!$found) {
22790a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
22800a05c769SSteven Rostedt		foreach my $config (@start_list) {
22810a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
22820a05c769SSteven Rostedt		}
22830a05c769SSteven Rostedt		return -1;
22840a05c769SSteven Rostedt	    }
22850a05c769SSteven Rostedt	    $count = $#tophalf + 1;
22860a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
22870a05c769SSteven Rostedt	}
22880a05c769SSteven Rostedt
22890a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
2290c960bb9fSSteven Rostedt	if ($bisect_manual) {
2291c960bb9fSSteven Rostedt	    $ret = answer_bisect;
2292c960bb9fSSteven Rostedt	}
22930a05c769SSteven Rostedt	if ($ret) {
22940a05c769SSteven Rostedt	    process_passed %current_config;
22950a05c769SSteven Rostedt	    return 0;
22960a05c769SSteven Rostedt	}
22970a05c769SSteven Rostedt
22980a05c769SSteven Rostedt	doprint "This config had a failure.\n";
22990a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
2300f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
2301f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
23020a05c769SSteven Rostedt
23030a05c769SSteven Rostedt	# A config exists in this group that was bad.
23040a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
23050a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
23060a05c769SSteven Rostedt		doprint " removing $config\n";
23070a05c769SSteven Rostedt		delete $config_list{$config};
23080a05c769SSteven Rostedt	    }
23090a05c769SSteven Rostedt	}
23100a05c769SSteven Rostedt
23110a05c769SSteven Rostedt	@start_list = @tophalf;
23120a05c769SSteven Rostedt
23130a05c769SSteven Rostedt	if ($#start_list == 0) {
23140a05c769SSteven Rostedt	    process_failed $start_list[0];
23150a05c769SSteven Rostedt	    return 1;
23160a05c769SSteven Rostedt	}
23170a05c769SSteven Rostedt
23180a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
23190a05c769SSteven Rostedt	# they are good.
23200a05c769SSteven Rostedt	$half = int($#start_list / 2);
23214c8cc55bSSteven Rostedt    } while ($#start_list > 0);
23220a05c769SSteven Rostedt
2323c960bb9fSSteven Rostedt    # we found a single config, try it again unless we are running manually
2324c960bb9fSSteven Rostedt
2325c960bb9fSSteven Rostedt    if ($bisect_manual) {
2326c960bb9fSSteven Rostedt	process_failed $start_list[0];
2327c960bb9fSSteven Rostedt	return 1;
2328c960bb9fSSteven Rostedt    }
2329c960bb9fSSteven Rostedt
23300a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
23310a05c769SSteven Rostedt
23320a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
23330a05c769SSteven Rostedt    if ($ret) {
23340a05c769SSteven Rostedt	process_passed %current_config;
23350a05c769SSteven Rostedt	return 0;
23360a05c769SSteven Rostedt    }
23370a05c769SSteven Rostedt
23380a05c769SSteven Rostedt    process_failed $start_list[0];
23390a05c769SSteven Rostedt    return 1;
23400a05c769SSteven Rostedt}
23410a05c769SSteven Rostedt
23420a05c769SSteven Rostedtsub config_bisect {
23430a05c769SSteven Rostedt    my ($i) = @_;
23440a05c769SSteven Rostedt
23450a05c769SSteven Rostedt    my $start_config = $opt{"CONFIG_BISECT[$i]"};
23460a05c769SSteven Rostedt
23470a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
23480a05c769SSteven Rostedt
234930f75da5SSteven Rostedt    if (defined($config_bisect_good)) {
235030f75da5SSteven Rostedt	process_config_ignore $config_bisect_good;
235130f75da5SSteven Rostedt    }
235230f75da5SSteven Rostedt
23530a05c769SSteven Rostedt    # Make the file with the bad config and the min config
23540a05c769SSteven Rostedt    if (defined($minconfig)) {
23550a05c769SSteven Rostedt	# read the min config for things to ignore
23560a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
23570a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
23580a05c769SSteven Rostedt    } else {
23590a05c769SSteven Rostedt	unlink $tmpconfig;
23600a05c769SSteven Rostedt    }
23610a05c769SSteven Rostedt
23620a05c769SSteven Rostedt    if (-f $tmpconfig) {
2363fcb3f16aSSteven Rostedt	load_force_config($tmpconfig);
23640a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
23650a05c769SSteven Rostedt    }
23660a05c769SSteven Rostedt
23670a05c769SSteven Rostedt    # now process the start config
23680a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
23690a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
23700a05c769SSteven Rostedt
23710a05c769SSteven Rostedt    # read directly what we want to check
23720a05c769SSteven Rostedt    my %config_check;
23730a05c769SSteven Rostedt    open (IN, $output_config)
23740a05c769SSteven Rostedt	or dodie "faied to open $output_config";
23750a05c769SSteven Rostedt
23760a05c769SSteven Rostedt    while (<IN>) {
23770a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
23780a05c769SSteven Rostedt	    $config_check{$2} = $1;
23790a05c769SSteven Rostedt	}
23800a05c769SSteven Rostedt    }
23810a05c769SSteven Rostedt    close(IN);
23820a05c769SSteven Rostedt
2383250bae8bSSteven Rostedt    # Now run oldconfig with the minconfig
2384fcb3f16aSSteven Rostedt    make_oldconfig;
23850a05c769SSteven Rostedt
23860a05c769SSteven Rostedt    # check to see what we lost (or gained)
23870a05c769SSteven Rostedt    open (IN, $output_config)
23880a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
23890a05c769SSteven Rostedt
23900a05c769SSteven Rostedt    my %removed_configs;
23910a05c769SSteven Rostedt    my %added_configs;
23920a05c769SSteven Rostedt
23930a05c769SSteven Rostedt    while (<IN>) {
23940a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
23950a05c769SSteven Rostedt	    # save off all options
23960a05c769SSteven Rostedt	    $config_set{$2} = $1;
23970a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
23980a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
23990a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
24000a05c769SSteven Rostedt		} else {
24010a05c769SSteven Rostedt		    $config_list{$2} = $1;
24020a05c769SSteven Rostedt		}
24030a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
24040a05c769SSteven Rostedt		$added_configs{$2} = $1;
24050a05c769SSteven Rostedt		$config_list{$2} = $1;
24060a05c769SSteven Rostedt	    }
24070a05c769SSteven Rostedt	}
24080a05c769SSteven Rostedt    }
24090a05c769SSteven Rostedt    close(IN);
24100a05c769SSteven Rostedt
24110a05c769SSteven Rostedt    my @confs = keys %removed_configs;
24120a05c769SSteven Rostedt    if ($#confs >= 0) {
24130a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
24140a05c769SSteven Rostedt	foreach my $config (@confs) {
24150a05c769SSteven Rostedt	    doprint " $config\n";
24160a05c769SSteven Rostedt	}
24170a05c769SSteven Rostedt    }
24180a05c769SSteven Rostedt    @confs = keys %added_configs;
24190a05c769SSteven Rostedt    if ($#confs >= 0) {
24200a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
24210a05c769SSteven Rostedt	foreach my $config (@confs) {
24220a05c769SSteven Rostedt	    doprint " $config\n";
24230a05c769SSteven Rostedt	}
24240a05c769SSteven Rostedt    }
24250a05c769SSteven Rostedt
24260a05c769SSteven Rostedt    my %config_test;
24270a05c769SSteven Rostedt    my $once = 0;
24280a05c769SSteven Rostedt
24290a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
24300a05c769SSteven Rostedt    # that the config we autocreate has everything we need
24310a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
24320a05c769SSteven Rostedt    # may not be able to create a new config.
24330a05c769SSteven Rostedt    # Here we create a config with everything set.
24340a05c769SSteven Rostedt    create_config (keys %config_list);
24350a05c769SSteven Rostedt    read_current_config \%config_test;
24360a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
24370a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
24380a05c769SSteven Rostedt	    if (!$once) {
24390a05c769SSteven Rostedt		$once = 1;
24400a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
24410a05c769SSteven Rostedt	    }
24420a05c769SSteven Rostedt	    doprint "  $config\n";
24430a05c769SSteven Rostedt	    delete $config_list{$config};
24440a05c769SSteven Rostedt	}
24450a05c769SSteven Rostedt    }
24460a05c769SSteven Rostedt    my $ret;
24470a05c769SSteven Rostedt    do {
24480a05c769SSteven Rostedt	$ret = run_config_bisect;
24490a05c769SSteven Rostedt    } while (!$ret);
24500a05c769SSteven Rostedt
24510a05c769SSteven Rostedt    return $ret if ($ret < 0);
24525f9b6cedSSteven Rostedt
24535f9b6cedSSteven Rostedt    success $i;
24545f9b6cedSSteven Rostedt}
24555f9b6cedSSteven Rostedt
245627d934b2SSteven Rostedtsub patchcheck_reboot {
245727d934b2SSteven Rostedt    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
24582728be41SAndrew Jones    reboot $patchcheck_sleep_time;
245927d934b2SSteven Rostedt}
246027d934b2SSteven Rostedt
24616c5ee0beSSteven Rostedtsub patchcheck {
24626c5ee0beSSteven Rostedt    my ($i) = @_;
24636c5ee0beSSteven Rostedt
24646c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
24656c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_START[$i]"}));
24666c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
24676c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
24686c5ee0beSSteven Rostedt
24696c5ee0beSSteven Rostedt    my $start = $opt{"PATCHCHECK_START[$i]"};
24706c5ee0beSSteven Rostedt
24716c5ee0beSSteven Rostedt    my $end = "HEAD";
24726c5ee0beSSteven Rostedt    if (defined($opt{"PATCHCHECK_END[$i]"})) {
24736c5ee0beSSteven Rostedt	$end = $opt{"PATCHCHECK_END[$i]"};
24746c5ee0beSSteven Rostedt    }
24756c5ee0beSSteven Rostedt
2476a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
2477a57419b3SSteven Rostedt    $start = get_sha1($start);
2478a57419b3SSteven Rostedt    $end = get_sha1($end);
2479a57419b3SSteven Rostedt
24806c5ee0beSSteven Rostedt    my $type = $opt{"PATCHCHECK_TYPE[$i]"};
24816c5ee0beSSteven Rostedt
24826c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
24836c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
24846c5ee0beSSteven Rostedt	$type = "boot";
24856c5ee0beSSteven Rostedt    }
24866c5ee0beSSteven Rostedt
24876c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
24886c5ee0beSSteven Rostedt	dodie "could not get git list";
24896c5ee0beSSteven Rostedt
24906c5ee0beSSteven Rostedt    my @list;
24916c5ee0beSSteven Rostedt
24926c5ee0beSSteven Rostedt    while (<IN>) {
24936c5ee0beSSteven Rostedt	chomp;
24946c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
24956c5ee0beSSteven Rostedt	last if (/^$start/);
24966c5ee0beSSteven Rostedt    }
24976c5ee0beSSteven Rostedt    close(IN);
24986c5ee0beSSteven Rostedt
24996c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
25002b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
25016c5ee0beSSteven Rostedt    }
25026c5ee0beSSteven Rostedt
25036c5ee0beSSteven Rostedt    # go backwards in the list
25046c5ee0beSSteven Rostedt    @list = reverse @list;
25056c5ee0beSSteven Rostedt
25066c5ee0beSSteven Rostedt    my $save_clean = $noclean;
25071990207dSSteven Rostedt    my %ignored_warnings;
25081990207dSSteven Rostedt
25091990207dSSteven Rostedt    if (defined($ignore_warnings)) {
25101990207dSSteven Rostedt	foreach my $sha1 (split /\s+/, $ignore_warnings) {
25111990207dSSteven Rostedt	    $ignored_warnings{$sha1} = 1;
25121990207dSSteven Rostedt	}
25131990207dSSteven Rostedt    }
25146c5ee0beSSteven Rostedt
25156c5ee0beSSteven Rostedt    $in_patchcheck = 1;
25166c5ee0beSSteven Rostedt    foreach my $item (@list) {
25176c5ee0beSSteven Rostedt	my $sha1 = $item;
25186c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
25196c5ee0beSSteven Rostedt
25206c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
25216c5ee0beSSteven Rostedt
25226c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
25236c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
25246c5ee0beSSteven Rostedt
25256c5ee0beSSteven Rostedt	# only clean on the first and last patch
25266c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
25276c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
25286c5ee0beSSteven Rostedt	    $noclean = $save_clean;
25296c5ee0beSSteven Rostedt	} else {
25306c5ee0beSSteven Rostedt	    $noclean = 1;
25316c5ee0beSSteven Rostedt	}
25326c5ee0beSSteven Rostedt
25336c5ee0beSSteven Rostedt	if (defined($minconfig)) {
25342b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
25356c5ee0beSSteven Rostedt	} else {
25366c5ee0beSSteven Rostedt	    # ?? no config to use?
25372b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
25386c5ee0beSSteven Rostedt	}
25396c5ee0beSSteven Rostedt
25401990207dSSteven Rostedt
25411990207dSSteven Rostedt	if (!defined($ignored_warnings{$sha1})) {
25422b7d9b21SSteven Rostedt	    check_buildlog $sha1 or return 0;
25431990207dSSteven Rostedt	}
25446c5ee0beSSteven Rostedt
25456c5ee0beSSteven Rostedt	next if ($type eq "build");
25466c5ee0beSSteven Rostedt
25477faafbd6SSteven Rostedt	my $failed = 0;
25487faafbd6SSteven Rostedt
2549ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
25507faafbd6SSteven Rostedt
25517faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
25527faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
25537faafbd6SSteven Rostedt	}
25547faafbd6SSteven Rostedt	end_monitor;
25557faafbd6SSteven Rostedt	return 0 if ($failed);
25567faafbd6SSteven Rostedt
255727d934b2SSteven Rostedt	patchcheck_reboot;
255827d934b2SSteven Rostedt
25596c5ee0beSSteven Rostedt    }
25606c5ee0beSSteven Rostedt    $in_patchcheck = 0;
25616c5ee0beSSteven Rostedt    success $i;
25622b7d9b21SSteven Rostedt
25632b7d9b21SSteven Rostedt    return 1;
25646c5ee0beSSteven Rostedt}
25656c5ee0beSSteven Rostedt
2566b9066f6cSSteven Rostedtmy %depends;
2567ac6974c7SSteven Rostedtmy %depcount;
2568b9066f6cSSteven Rostedtmy $iflevel = 0;
2569b9066f6cSSteven Rostedtmy @ifdeps;
2570b9066f6cSSteven Rostedt
2571b9066f6cSSteven Rostedt# prevent recursion
2572b9066f6cSSteven Rostedtmy %read_kconfigs;
2573b9066f6cSSteven Rostedt
2574ac6974c7SSteven Rostedtsub add_dep {
2575ac6974c7SSteven Rostedt    # $config depends on $dep
2576ac6974c7SSteven Rostedt    my ($config, $dep) = @_;
2577ac6974c7SSteven Rostedt
2578ac6974c7SSteven Rostedt    if (defined($depends{$config})) {
2579ac6974c7SSteven Rostedt	$depends{$config} .= " " . $dep;
2580ac6974c7SSteven Rostedt    } else {
2581ac6974c7SSteven Rostedt	$depends{$config} = $dep;
2582ac6974c7SSteven Rostedt    }
2583ac6974c7SSteven Rostedt
2584ac6974c7SSteven Rostedt    # record the number of configs depending on $dep
2585ac6974c7SSteven Rostedt    if (defined $depcount{$dep}) {
2586ac6974c7SSteven Rostedt	$depcount{$dep}++;
2587ac6974c7SSteven Rostedt    } else {
2588ac6974c7SSteven Rostedt	$depcount{$dep} = 1;
2589ac6974c7SSteven Rostedt    }
2590ac6974c7SSteven Rostedt}
2591ac6974c7SSteven Rostedt
2592b9066f6cSSteven Rostedt# taken from streamline_config.pl
2593b9066f6cSSteven Rostedtsub read_kconfig {
2594b9066f6cSSteven Rostedt    my ($kconfig) = @_;
2595b9066f6cSSteven Rostedt
2596b9066f6cSSteven Rostedt    my $state = "NONE";
2597b9066f6cSSteven Rostedt    my $config;
2598b9066f6cSSteven Rostedt    my @kconfigs;
2599b9066f6cSSteven Rostedt
2600b9066f6cSSteven Rostedt    my $cont = 0;
2601b9066f6cSSteven Rostedt    my $line;
2602b9066f6cSSteven Rostedt
2603b9066f6cSSteven Rostedt
2604b9066f6cSSteven Rostedt    if (! -f $kconfig) {
2605b9066f6cSSteven Rostedt	doprint "file $kconfig does not exist, skipping\n";
2606b9066f6cSSteven Rostedt	return;
2607b9066f6cSSteven Rostedt    }
2608b9066f6cSSteven Rostedt
2609b9066f6cSSteven Rostedt    open(KIN, "$kconfig")
2610b9066f6cSSteven Rostedt	or die "Can't open $kconfig";
2611b9066f6cSSteven Rostedt    while (<KIN>) {
2612b9066f6cSSteven Rostedt	chomp;
2613b9066f6cSSteven Rostedt
2614b9066f6cSSteven Rostedt	# Make sure that lines ending with \ continue
2615b9066f6cSSteven Rostedt	if ($cont) {
2616b9066f6cSSteven Rostedt	    $_ = $line . " " . $_;
2617b9066f6cSSteven Rostedt	}
2618b9066f6cSSteven Rostedt
2619b9066f6cSSteven Rostedt	if (s/\\$//) {
2620b9066f6cSSteven Rostedt	    $cont = 1;
2621b9066f6cSSteven Rostedt	    $line = $_;
2622b9066f6cSSteven Rostedt	    next;
2623b9066f6cSSteven Rostedt	}
2624b9066f6cSSteven Rostedt
2625b9066f6cSSteven Rostedt	$cont = 0;
2626b9066f6cSSteven Rostedt
2627b9066f6cSSteven Rostedt	# collect any Kconfig sources
2628b9066f6cSSteven Rostedt	if (/^source\s*"(.*)"/) {
2629b9066f6cSSteven Rostedt	    $kconfigs[$#kconfigs+1] = $1;
2630b9066f6cSSteven Rostedt	}
2631b9066f6cSSteven Rostedt
2632b9066f6cSSteven Rostedt	# configs found
2633b9066f6cSSteven Rostedt	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
2634b9066f6cSSteven Rostedt	    $state = "NEW";
2635b9066f6cSSteven Rostedt	    $config = $2;
2636b9066f6cSSteven Rostedt
2637b9066f6cSSteven Rostedt	    for (my $i = 0; $i < $iflevel; $i++) {
2638ac6974c7SSteven Rostedt		add_dep $config, $ifdeps[$i];
2639b9066f6cSSteven Rostedt	    }
2640b9066f6cSSteven Rostedt
2641b9066f6cSSteven Rostedt	# collect the depends for the config
2642b9066f6cSSteven Rostedt	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
2643b9066f6cSSteven Rostedt
2644ac6974c7SSteven Rostedt	    add_dep $config, $1;
2645b9066f6cSSteven Rostedt
2646b9066f6cSSteven Rostedt	# Get the configs that select this config
2647ac6974c7SSteven Rostedt	} elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
2648ac6974c7SSteven Rostedt
2649ac6974c7SSteven Rostedt	    # selected by depends on config
2650ac6974c7SSteven Rostedt	    add_dep $1, $config;
2651b9066f6cSSteven Rostedt
2652b9066f6cSSteven Rostedt	# Check for if statements
2653b9066f6cSSteven Rostedt	} elsif (/^if\s+(.*\S)\s*$/) {
2654b9066f6cSSteven Rostedt	    my $deps = $1;
2655b9066f6cSSteven Rostedt	    # remove beginning and ending non text
2656b9066f6cSSteven Rostedt	    $deps =~ s/^[^a-zA-Z0-9_]*//;
2657b9066f6cSSteven Rostedt	    $deps =~ s/[^a-zA-Z0-9_]*$//;
2658b9066f6cSSteven Rostedt
2659b9066f6cSSteven Rostedt	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
2660b9066f6cSSteven Rostedt
2661b9066f6cSSteven Rostedt	    $ifdeps[$iflevel++] = join ':', @deps;
2662b9066f6cSSteven Rostedt
2663b9066f6cSSteven Rostedt	} elsif (/^endif/) {
2664b9066f6cSSteven Rostedt
2665b9066f6cSSteven Rostedt	    $iflevel-- if ($iflevel);
2666b9066f6cSSteven Rostedt
2667b9066f6cSSteven Rostedt	# stop on "help"
2668b9066f6cSSteven Rostedt	} elsif (/^\s*help\s*$/) {
2669b9066f6cSSteven Rostedt	    $state = "NONE";
2670b9066f6cSSteven Rostedt	}
2671b9066f6cSSteven Rostedt    }
2672b9066f6cSSteven Rostedt    close(KIN);
2673b9066f6cSSteven Rostedt
2674b9066f6cSSteven Rostedt    # read in any configs that were found.
2675b9066f6cSSteven Rostedt    foreach $kconfig (@kconfigs) {
2676b9066f6cSSteven Rostedt	if (!defined($read_kconfigs{$kconfig})) {
2677b9066f6cSSteven Rostedt	    $read_kconfigs{$kconfig} = 1;
2678b9066f6cSSteven Rostedt	    read_kconfig("$builddir/$kconfig");
2679b9066f6cSSteven Rostedt	}
2680b9066f6cSSteven Rostedt    }
2681b9066f6cSSteven Rostedt}
2682b9066f6cSSteven Rostedt
2683b9066f6cSSteven Rostedtsub read_depends {
2684b9066f6cSSteven Rostedt    # find out which arch this is by the kconfig file
2685b9066f6cSSteven Rostedt    open (IN, $output_config)
2686b9066f6cSSteven Rostedt	or dodie "Failed to read $output_config";
2687b9066f6cSSteven Rostedt    my $arch;
2688b9066f6cSSteven Rostedt    while (<IN>) {
2689b9066f6cSSteven Rostedt	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
2690b9066f6cSSteven Rostedt	    $arch = $1;
2691b9066f6cSSteven Rostedt	    last;
2692b9066f6cSSteven Rostedt	}
2693b9066f6cSSteven Rostedt    }
2694b9066f6cSSteven Rostedt    close IN;
2695b9066f6cSSteven Rostedt
2696b9066f6cSSteven Rostedt    if (!defined($arch)) {
2697b9066f6cSSteven Rostedt	doprint "Could not find arch from config file\n";
2698b9066f6cSSteven Rostedt	doprint "no dependencies used\n";
2699b9066f6cSSteven Rostedt	return;
2700b9066f6cSSteven Rostedt    }
2701b9066f6cSSteven Rostedt
2702b9066f6cSSteven Rostedt    # arch is really the subarch, we need to know
2703b9066f6cSSteven Rostedt    # what directory to look at.
2704b9066f6cSSteven Rostedt    if ($arch eq "i386" || $arch eq "x86_64") {
2705b9066f6cSSteven Rostedt	$arch = "x86";
2706b9066f6cSSteven Rostedt    } elsif ($arch =~ /^tile/) {
2707b9066f6cSSteven Rostedt	$arch = "tile";
2708b9066f6cSSteven Rostedt    }
2709b9066f6cSSteven Rostedt
2710b9066f6cSSteven Rostedt    my $kconfig = "$builddir/arch/$arch/Kconfig";
2711b9066f6cSSteven Rostedt
2712b9066f6cSSteven Rostedt    if (! -f $kconfig && $arch =~ /\d$/) {
2713b9066f6cSSteven Rostedt	my $orig = $arch;
2714b9066f6cSSteven Rostedt 	# some subarchs have numbers, truncate them
2715b9066f6cSSteven Rostedt	$arch =~ s/\d*$//;
2716b9066f6cSSteven Rostedt	$kconfig = "$builddir/arch/$arch/Kconfig";
2717b9066f6cSSteven Rostedt	if (! -f $kconfig) {
2718b9066f6cSSteven Rostedt	    doprint "No idea what arch dir $orig is for\n";
2719b9066f6cSSteven Rostedt	    doprint "no dependencies used\n";
2720b9066f6cSSteven Rostedt	    return;
2721b9066f6cSSteven Rostedt	}
2722b9066f6cSSteven Rostedt    }
2723b9066f6cSSteven Rostedt
2724b9066f6cSSteven Rostedt    read_kconfig($kconfig);
2725b9066f6cSSteven Rostedt}
2726b9066f6cSSteven Rostedt
27274c4ab120SSteven Rostedtsub read_config_list {
27284c4ab120SSteven Rostedt    my ($config) = @_;
27294c4ab120SSteven Rostedt
27304c4ab120SSteven Rostedt    open (IN, $config)
27314c4ab120SSteven Rostedt	or dodie "Failed to read $config";
27324c4ab120SSteven Rostedt
27334c4ab120SSteven Rostedt    while (<IN>) {
27344c4ab120SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
27354c4ab120SSteven Rostedt	    if (!defined($config_ignore{$2})) {
27364c4ab120SSteven Rostedt		$config_list{$2} = $1;
27374c4ab120SSteven Rostedt	    }
27384c4ab120SSteven Rostedt	}
27394c4ab120SSteven Rostedt    }
27404c4ab120SSteven Rostedt
27414c4ab120SSteven Rostedt    close(IN);
27424c4ab120SSteven Rostedt}
27434c4ab120SSteven Rostedt
27444c4ab120SSteven Rostedtsub read_output_config {
27454c4ab120SSteven Rostedt    my ($config) = @_;
27464c4ab120SSteven Rostedt
27474c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
27484c4ab120SSteven Rostedt}
27494c4ab120SSteven Rostedt
27504c4ab120SSteven Rostedtsub make_new_config {
27514c4ab120SSteven Rostedt    my @configs = @_;
27524c4ab120SSteven Rostedt
27534c4ab120SSteven Rostedt    open (OUT, ">$output_config")
27544c4ab120SSteven Rostedt	or dodie "Failed to write $output_config";
27554c4ab120SSteven Rostedt
27564c4ab120SSteven Rostedt    foreach my $config (@configs) {
27574c4ab120SSteven Rostedt	print OUT "$config\n";
27584c4ab120SSteven Rostedt    }
27594c4ab120SSteven Rostedt    close OUT;
27604c4ab120SSteven Rostedt}
27614c4ab120SSteven Rostedt
2762ac6974c7SSteven Rostedtsub chomp_config {
2763ac6974c7SSteven Rostedt    my ($config) = @_;
2764ac6974c7SSteven Rostedt
2765ac6974c7SSteven Rostedt    $config =~ s/CONFIG_//;
2766ac6974c7SSteven Rostedt
2767ac6974c7SSteven Rostedt    return $config;
2768ac6974c7SSteven Rostedt}
2769ac6974c7SSteven Rostedt
2770b9066f6cSSteven Rostedtsub get_depends {
2771b9066f6cSSteven Rostedt    my ($dep) = @_;
2772b9066f6cSSteven Rostedt
2773ac6974c7SSteven Rostedt    my $kconfig = chomp_config $dep;
2774b9066f6cSSteven Rostedt
2775b9066f6cSSteven Rostedt    $dep = $depends{"$kconfig"};
2776b9066f6cSSteven Rostedt
2777b9066f6cSSteven Rostedt    # the dep string we have saves the dependencies as they
2778b9066f6cSSteven Rostedt    # were found, including expressions like ! && ||. We
2779b9066f6cSSteven Rostedt    # want to split this out into just an array of configs.
2780b9066f6cSSteven Rostedt
2781b9066f6cSSteven Rostedt    my $valid = "A-Za-z_0-9";
2782b9066f6cSSteven Rostedt
2783b9066f6cSSteven Rostedt    my @configs;
2784b9066f6cSSteven Rostedt
2785b9066f6cSSteven Rostedt    while ($dep =~ /[$valid]/) {
2786b9066f6cSSteven Rostedt
2787b9066f6cSSteven Rostedt	if ($dep =~ /^[^$valid]*([$valid]+)/) {
2788b9066f6cSSteven Rostedt	    my $conf = "CONFIG_" . $1;
2789b9066f6cSSteven Rostedt
2790b9066f6cSSteven Rostedt	    $configs[$#configs + 1] = $conf;
2791b9066f6cSSteven Rostedt
2792b9066f6cSSteven Rostedt	    $dep =~ s/^[^$valid]*[$valid]+//;
2793b9066f6cSSteven Rostedt	} else {
2794b9066f6cSSteven Rostedt	    die "this should never happen";
2795b9066f6cSSteven Rostedt	}
2796b9066f6cSSteven Rostedt    }
2797b9066f6cSSteven Rostedt
2798b9066f6cSSteven Rostedt    return @configs;
2799b9066f6cSSteven Rostedt}
2800b9066f6cSSteven Rostedt
2801b9066f6cSSteven Rostedtmy %min_configs;
2802b9066f6cSSteven Rostedtmy %keep_configs;
280343d1b651SSteven Rostedtmy %save_configs;
2804b9066f6cSSteven Rostedtmy %processed_configs;
2805b9066f6cSSteven Rostedtmy %nochange_config;
2806b9066f6cSSteven Rostedt
2807b9066f6cSSteven Rostedtsub test_this_config {
2808b9066f6cSSteven Rostedt    my ($config) = @_;
2809b9066f6cSSteven Rostedt
2810b9066f6cSSteven Rostedt    my $found;
2811b9066f6cSSteven Rostedt
2812b9066f6cSSteven Rostedt    # if we already processed this config, skip it
2813b9066f6cSSteven Rostedt    if (defined($processed_configs{$config})) {
2814b9066f6cSSteven Rostedt	return undef;
2815b9066f6cSSteven Rostedt    }
2816b9066f6cSSteven Rostedt    $processed_configs{$config} = 1;
2817b9066f6cSSteven Rostedt
2818b9066f6cSSteven Rostedt    # if this config failed during this round, skip it
2819b9066f6cSSteven Rostedt    if (defined($nochange_config{$config})) {
2820b9066f6cSSteven Rostedt	return undef;
2821b9066f6cSSteven Rostedt    }
2822b9066f6cSSteven Rostedt
2823ac6974c7SSteven Rostedt    my $kconfig = chomp_config $config;
2824b9066f6cSSteven Rostedt
2825b9066f6cSSteven Rostedt    # Test dependencies first
2826b9066f6cSSteven Rostedt    if (defined($depends{"$kconfig"})) {
2827b9066f6cSSteven Rostedt	my @parents = get_depends $config;
2828b9066f6cSSteven Rostedt	foreach my $parent (@parents) {
2829b9066f6cSSteven Rostedt	    # if the parent is in the min config, check it first
2830b9066f6cSSteven Rostedt	    next if (!defined($min_configs{$parent}));
2831b9066f6cSSteven Rostedt	    $found = test_this_config($parent);
2832b9066f6cSSteven Rostedt	    if (defined($found)) {
2833b9066f6cSSteven Rostedt		return $found;
2834b9066f6cSSteven Rostedt	    }
2835b9066f6cSSteven Rostedt	}
2836b9066f6cSSteven Rostedt    }
2837b9066f6cSSteven Rostedt
2838b9066f6cSSteven Rostedt    # Remove this config from the list of configs
2839b9066f6cSSteven Rostedt    # do a make oldnoconfig and then read the resulting
2840b9066f6cSSteven Rostedt    # .config to make sure it is missing the config that
2841b9066f6cSSteven Rostedt    # we had before
2842b9066f6cSSteven Rostedt    my %configs = %min_configs;
2843b9066f6cSSteven Rostedt    delete $configs{$config};
2844b9066f6cSSteven Rostedt    make_new_config ((values %configs), (values %keep_configs));
2845b9066f6cSSteven Rostedt    make_oldconfig;
2846b9066f6cSSteven Rostedt    undef %configs;
2847b9066f6cSSteven Rostedt    assign_configs \%configs, $output_config;
2848b9066f6cSSteven Rostedt
2849b9066f6cSSteven Rostedt    return $config if (!defined($configs{$config}));
2850b9066f6cSSteven Rostedt
2851b9066f6cSSteven Rostedt    doprint "disabling config $config did not change .config\n";
2852b9066f6cSSteven Rostedt
2853b9066f6cSSteven Rostedt    $nochange_config{$config} = 1;
2854b9066f6cSSteven Rostedt
2855b9066f6cSSteven Rostedt    return undef;
2856b9066f6cSSteven Rostedt}
2857b9066f6cSSteven Rostedt
28584c4ab120SSteven Rostedtsub make_min_config {
28594c4ab120SSteven Rostedt    my ($i) = @_;
28604c4ab120SSteven Rostedt
28614c4ab120SSteven Rostedt    if (!defined($output_minconfig)) {
28624c4ab120SSteven Rostedt	fail "OUTPUT_MIN_CONFIG not defined" and return;
28634c4ab120SSteven Rostedt    }
286435ce5952SSteven Rostedt
286535ce5952SSteven Rostedt    # If output_minconfig exists, and the start_minconfig
286635ce5952SSteven Rostedt    # came from min_config, than ask if we should use
286735ce5952SSteven Rostedt    # that instead.
286835ce5952SSteven Rostedt    if (-f $output_minconfig && !$start_minconfig_defined) {
286935ce5952SSteven Rostedt	print "$output_minconfig exists\n";
287035ce5952SSteven Rostedt	if (read_yn " Use it as minconfig?") {
287135ce5952SSteven Rostedt	    $start_minconfig = $output_minconfig;
287235ce5952SSteven Rostedt	}
287335ce5952SSteven Rostedt    }
287435ce5952SSteven Rostedt
28754c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
28764c4ab120SSteven Rostedt	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
28774c4ab120SSteven Rostedt    }
28784c4ab120SSteven Rostedt
287935ce5952SSteven Rostedt    my $temp_config = "$tmpdir/temp_config";
288035ce5952SSteven Rostedt
28814c4ab120SSteven Rostedt    # First things first. We build an allnoconfig to find
28824c4ab120SSteven Rostedt    # out what the defaults are that we can't touch.
28834c4ab120SSteven Rostedt    # Some are selections, but we really can't handle selections.
28844c4ab120SSteven Rostedt
28854c4ab120SSteven Rostedt    my $save_minconfig = $minconfig;
28864c4ab120SSteven Rostedt    undef $minconfig;
28874c4ab120SSteven Rostedt
28884c4ab120SSteven Rostedt    run_command "$make allnoconfig" or return 0;
28894c4ab120SSteven Rostedt
2890b9066f6cSSteven Rostedt    read_depends;
2891b9066f6cSSteven Rostedt
28924c4ab120SSteven Rostedt    process_config_ignore $output_config;
2893b9066f6cSSteven Rostedt
289443d1b651SSteven Rostedt    undef %save_configs;
2895b9066f6cSSteven Rostedt    undef %min_configs;
28964c4ab120SSteven Rostedt
28974c4ab120SSteven Rostedt    if (defined($ignore_config)) {
28984c4ab120SSteven Rostedt	# make sure the file exists
28994c4ab120SSteven Rostedt	`touch $ignore_config`;
290043d1b651SSteven Rostedt	assign_configs \%save_configs, $ignore_config;
29014c4ab120SSteven Rostedt    }
29024c4ab120SSteven Rostedt
290343d1b651SSteven Rostedt    %keep_configs = %save_configs;
290443d1b651SSteven Rostedt
29054c4ab120SSteven Rostedt    doprint "Load initial configs from $start_minconfig\n";
29064c4ab120SSteven Rostedt
29074c4ab120SSteven Rostedt    # Look at the current min configs, and save off all the
29084c4ab120SSteven Rostedt    # ones that were set via the allnoconfig
29094c4ab120SSteven Rostedt    assign_configs \%min_configs, $start_minconfig;
29104c4ab120SSteven Rostedt
29114c4ab120SSteven Rostedt    my @config_keys = keys %min_configs;
29124c4ab120SSteven Rostedt
2913ac6974c7SSteven Rostedt    # All configs need a depcount
2914ac6974c7SSteven Rostedt    foreach my $config (@config_keys) {
2915ac6974c7SSteven Rostedt	my $kconfig = chomp_config $config;
2916ac6974c7SSteven Rostedt	if (!defined $depcount{$kconfig}) {
2917ac6974c7SSteven Rostedt		$depcount{$kconfig} = 0;
2918ac6974c7SSteven Rostedt	}
2919ac6974c7SSteven Rostedt    }
2920ac6974c7SSteven Rostedt
29214c4ab120SSteven Rostedt    # Remove anything that was set by the make allnoconfig
29224c4ab120SSteven Rostedt    # we shouldn't need them as they get set for us anyway.
29234c4ab120SSteven Rostedt    foreach my $config (@config_keys) {
29244c4ab120SSteven Rostedt	# Remove anything in the ignore_config
29254c4ab120SSteven Rostedt	if (defined($keep_configs{$config})) {
29264c4ab120SSteven Rostedt	    my $file = $ignore_config;
29274c4ab120SSteven Rostedt	    $file =~ s,.*/(.*?)$,$1,;
29284c4ab120SSteven Rostedt	    doprint "$config set by $file ... ignored\n";
29294c4ab120SSteven Rostedt	    delete $min_configs{$config};
29304c4ab120SSteven Rostedt	    next;
29314c4ab120SSteven Rostedt	}
29324c4ab120SSteven Rostedt	# But make sure the settings are the same. If a min config
29334c4ab120SSteven Rostedt	# sets a selection, we do not want to get rid of it if
29344c4ab120SSteven Rostedt	# it is not the same as what we have. Just move it into
29354c4ab120SSteven Rostedt	# the keep configs.
29364c4ab120SSteven Rostedt	if (defined($config_ignore{$config})) {
29374c4ab120SSteven Rostedt	    if ($config_ignore{$config} ne $min_configs{$config}) {
29384c4ab120SSteven Rostedt		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
29394c4ab120SSteven Rostedt		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
29404c4ab120SSteven Rostedt		$keep_configs{$config} = $min_configs{$config};
29414c4ab120SSteven Rostedt	    } else {
29424c4ab120SSteven Rostedt		doprint "$config set by allnoconfig ... ignored\n";
29434c4ab120SSteven Rostedt	    }
29444c4ab120SSteven Rostedt	    delete $min_configs{$config};
29454c4ab120SSteven Rostedt	}
29464c4ab120SSteven Rostedt    }
29474c4ab120SSteven Rostedt
29484c4ab120SSteven Rostedt    my $done = 0;
2949b9066f6cSSteven Rostedt    my $take_two = 0;
29504c4ab120SSteven Rostedt
29514c4ab120SSteven Rostedt    while (!$done) {
29524c4ab120SSteven Rostedt
29534c4ab120SSteven Rostedt	my $config;
29544c4ab120SSteven Rostedt	my $found;
29554c4ab120SSteven Rostedt
29564c4ab120SSteven Rostedt	# Now disable each config one by one and do a make oldconfig
29574c4ab120SSteven Rostedt	# till we find a config that changes our list.
29584c4ab120SSteven Rostedt
29594c4ab120SSteven Rostedt	my @test_configs = keys %min_configs;
2960ac6974c7SSteven Rostedt
2961ac6974c7SSteven Rostedt	# Sort keys by who is most dependent on
2962ac6974c7SSteven Rostedt	@test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
2963ac6974c7SSteven Rostedt			  @test_configs ;
2964ac6974c7SSteven Rostedt
2965ac6974c7SSteven Rostedt	# Put configs that did not modify the config at the end.
29664c4ab120SSteven Rostedt	my $reset = 1;
29674c4ab120SSteven Rostedt	for (my $i = 0; $i < $#test_configs; $i++) {
29684c4ab120SSteven Rostedt	    if (!defined($nochange_config{$test_configs[0]})) {
29694c4ab120SSteven Rostedt		$reset = 0;
29704c4ab120SSteven Rostedt		last;
29714c4ab120SSteven Rostedt	    }
29724c4ab120SSteven Rostedt	    # This config didn't change the .config last time.
29734c4ab120SSteven Rostedt	    # Place it at the end
29744c4ab120SSteven Rostedt	    my $config = shift @test_configs;
29754c4ab120SSteven Rostedt	    push @test_configs, $config;
29764c4ab120SSteven Rostedt	}
29774c4ab120SSteven Rostedt
29784c4ab120SSteven Rostedt	# if every test config has failed to modify the .config file
29794c4ab120SSteven Rostedt	# in the past, then reset and start over.
29804c4ab120SSteven Rostedt	if ($reset) {
29814c4ab120SSteven Rostedt	    undef %nochange_config;
29824c4ab120SSteven Rostedt	}
29834c4ab120SSteven Rostedt
2984b9066f6cSSteven Rostedt	undef %processed_configs;
2985b9066f6cSSteven Rostedt
29864c4ab120SSteven Rostedt	foreach my $config (@test_configs) {
29874c4ab120SSteven Rostedt
2988b9066f6cSSteven Rostedt	    $found = test_this_config $config;
29894c4ab120SSteven Rostedt
2990b9066f6cSSteven Rostedt	    last if (defined($found));
29914c4ab120SSteven Rostedt
29924c4ab120SSteven Rostedt	    # oh well, try another config
29934c4ab120SSteven Rostedt	}
29944c4ab120SSteven Rostedt
29954c4ab120SSteven Rostedt	if (!defined($found)) {
2996b9066f6cSSteven Rostedt	    # we could have failed due to the nochange_config hash
2997b9066f6cSSteven Rostedt	    # reset and try again
2998b9066f6cSSteven Rostedt	    if (!$take_two) {
2999b9066f6cSSteven Rostedt		undef %nochange_config;
3000b9066f6cSSteven Rostedt		$take_two = 1;
3001b9066f6cSSteven Rostedt		next;
3002b9066f6cSSteven Rostedt	    }
30034c4ab120SSteven Rostedt	    doprint "No more configs found that we can disable\n";
30044c4ab120SSteven Rostedt	    $done = 1;
30054c4ab120SSteven Rostedt	    last;
30064c4ab120SSteven Rostedt	}
3007b9066f6cSSteven Rostedt	$take_two = 0;
30084c4ab120SSteven Rostedt
30094c4ab120SSteven Rostedt	$config = $found;
30104c4ab120SSteven Rostedt
30114c4ab120SSteven Rostedt	doprint "Test with $config disabled\n";
30124c4ab120SSteven Rostedt
30134c4ab120SSteven Rostedt	# set in_bisect to keep build and monitor from dieing
30144c4ab120SSteven Rostedt	$in_bisect = 1;
30154c4ab120SSteven Rostedt
30164c4ab120SSteven Rostedt	my $failed = 0;
30174c4ab120SSteven Rostedt	build "oldconfig";
30184c4ab120SSteven Rostedt	start_monitor_and_boot or $failed = 1;
30194c4ab120SSteven Rostedt	end_monitor;
30204c4ab120SSteven Rostedt
30214c4ab120SSteven Rostedt	$in_bisect = 0;
30224c4ab120SSteven Rostedt
30234c4ab120SSteven Rostedt	if ($failed) {
3024b9066f6cSSteven Rostedt	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
30254c4ab120SSteven Rostedt	    # this config is needed, add it to the ignore list.
30264c4ab120SSteven Rostedt	    $keep_configs{$config} = $min_configs{$config};
302743d1b651SSteven Rostedt	    $save_configs{$config} = $min_configs{$config};
30284c4ab120SSteven Rostedt	    delete $min_configs{$config};
302935ce5952SSteven Rostedt
303035ce5952SSteven Rostedt	    # update new ignore configs
303135ce5952SSteven Rostedt	    if (defined($ignore_config)) {
303235ce5952SSteven Rostedt		open (OUT, ">$temp_config")
303335ce5952SSteven Rostedt		    or die "Can't write to $temp_config";
303443d1b651SSteven Rostedt		foreach my $config (keys %save_configs) {
303543d1b651SSteven Rostedt		    print OUT "$save_configs{$config}\n";
303635ce5952SSteven Rostedt		}
303735ce5952SSteven Rostedt		close OUT;
303835ce5952SSteven Rostedt		run_command "mv $temp_config $ignore_config" or
303935ce5952SSteven Rostedt		    dodie "failed to copy update to $ignore_config";
304035ce5952SSteven Rostedt	    }
304135ce5952SSteven Rostedt
30424c4ab120SSteven Rostedt	} else {
30434c4ab120SSteven Rostedt	    # We booted without this config, remove it from the minconfigs.
30444c4ab120SSteven Rostedt	    doprint "$config is not needed, disabling\n";
30454c4ab120SSteven Rostedt
30464c4ab120SSteven Rostedt	    delete $min_configs{$config};
30474c4ab120SSteven Rostedt
30484c4ab120SSteven Rostedt	    # Also disable anything that is not enabled in this config
30494c4ab120SSteven Rostedt	    my %configs;
30504c4ab120SSteven Rostedt	    assign_configs \%configs, $output_config;
30514c4ab120SSteven Rostedt	    my @config_keys = keys %min_configs;
30524c4ab120SSteven Rostedt	    foreach my $config (@config_keys) {
30534c4ab120SSteven Rostedt		if (!defined($configs{$config})) {
30544c4ab120SSteven Rostedt		    doprint "$config is not set, disabling\n";
30554c4ab120SSteven Rostedt		    delete $min_configs{$config};
30564c4ab120SSteven Rostedt		}
30574c4ab120SSteven Rostedt	    }
30584c4ab120SSteven Rostedt
30594c4ab120SSteven Rostedt	    # Save off all the current mandidory configs
306035ce5952SSteven Rostedt	    open (OUT, ">$temp_config")
306135ce5952SSteven Rostedt		or die "Can't write to $temp_config";
30624c4ab120SSteven Rostedt	    foreach my $config (keys %keep_configs) {
30634c4ab120SSteven Rostedt		print OUT "$keep_configs{$config}\n";
30644c4ab120SSteven Rostedt	    }
30654c4ab120SSteven Rostedt	    foreach my $config (keys %min_configs) {
30664c4ab120SSteven Rostedt		print OUT "$min_configs{$config}\n";
30674c4ab120SSteven Rostedt	    }
30684c4ab120SSteven Rostedt	    close OUT;
306935ce5952SSteven Rostedt
307035ce5952SSteven Rostedt	    run_command "mv $temp_config $output_minconfig" or
307135ce5952SSteven Rostedt		dodie "failed to copy update to $output_minconfig";
30724c4ab120SSteven Rostedt	}
30734c4ab120SSteven Rostedt
30744c4ab120SSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
30752728be41SAndrew Jones	reboot $sleep_time;
30764c4ab120SSteven Rostedt    }
30774c4ab120SSteven Rostedt
30784c4ab120SSteven Rostedt    success $i;
30794c4ab120SSteven Rostedt    return 1;
30804c4ab120SSteven Rostedt}
30814c4ab120SSteven Rostedt
30828d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
30832545eb61SSteven Rostedt
30848d1491baSSteven Rostedtif ($#ARGV == 0) {
30858d1491baSSteven Rostedt    $ktest_config = $ARGV[0];
30868d1491baSSteven Rostedt    if (! -f $ktest_config) {
30878d1491baSSteven Rostedt	print "$ktest_config does not exist.\n";
308835ce5952SSteven Rostedt	if (!read_yn "Create it?") {
30898d1491baSSteven Rostedt	    exit 0;
30908d1491baSSteven Rostedt	}
30918d1491baSSteven Rostedt    }
30928d1491baSSteven Rostedt} else {
30938d1491baSSteven Rostedt    $ktest_config = "ktest.conf";
30948d1491baSSteven Rostedt}
30958d1491baSSteven Rostedt
30968d1491baSSteven Rostedtif (! -f $ktest_config) {
3097c4261d0fSSteven Rostedt    get_test_case;
30988d1491baSSteven Rostedt    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
30998d1491baSSteven Rostedt    print OUT << "EOF"
31008d1491baSSteven Rostedt# Generated by ktest.pl
31018d1491baSSteven Rostedt#
31020e7a22deSSteven Rostedt
31030e7a22deSSteven Rostedt# PWD is a ktest.pl variable that will result in the process working
31040e7a22deSSteven Rostedt# directory that ktest.pl is executed in.
31050e7a22deSSteven Rostedt
31060e7a22deSSteven Rostedt# THIS_DIR is automatically assigned the PWD of the path that generated
31070e7a22deSSteven Rostedt# the config file. It is best to use this variable when assigning other
31080e7a22deSSteven Rostedt# directory paths within this directory. This allows you to easily
31090e7a22deSSteven Rostedt# move the test cases to other locations or to other machines.
31100e7a22deSSteven Rostedt#
31110e7a22deSSteven RostedtTHIS_DIR := $variable{"PWD"}
31120e7a22deSSteven Rostedt
31138d1491baSSteven Rostedt# Define each test with TEST_START
31148d1491baSSteven Rostedt# The config options below it will override the defaults
31158d1491baSSteven RostedtTEST_START
3116c4261d0fSSteven RostedtTEST_TYPE = $default{"TEST_TYPE"}
31178d1491baSSteven Rostedt
31188d1491baSSteven RostedtDEFAULTS
31198d1491baSSteven RostedtEOF
31208d1491baSSteven Rostedt;
31218d1491baSSteven Rostedt    close(OUT);
31228d1491baSSteven Rostedt}
31238d1491baSSteven Rostedtread_config $ktest_config;
31248d1491baSSteven Rostedt
312523715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) {
312623715c3cSSteven Rostedt    $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
312723715c3cSSteven Rostedt}
312823715c3cSSteven Rostedt
31298d1491baSSteven Rostedt# Append any configs entered in manually to the config file.
31308d1491baSSteven Rostedtmy @new_configs = keys %entered_configs;
31318d1491baSSteven Rostedtif ($#new_configs >= 0) {
31328d1491baSSteven Rostedt    print "\nAppending entered in configs to $ktest_config\n";
31338d1491baSSteven Rostedt    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
31348d1491baSSteven Rostedt    foreach my $config (@new_configs) {
31358d1491baSSteven Rostedt	print OUT "$config = $entered_configs{$config}\n";
31360e7a22deSSteven Rostedt	$opt{$config} = process_variables($entered_configs{$config});
31378d1491baSSteven Rostedt    }
31388d1491baSSteven Rostedt}
31392545eb61SSteven Rostedt
31402b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
31412b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
31422b7d9b21SSteven Rostedt}
31432545eb61SSteven Rostedt
31442b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
31452b7d9b21SSteven Rostedt
3146a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
3147a57419b3SSteven Rostedt
3148a57419b3SSteven Rostedt    if (!$i) {
3149a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
3150a57419b3SSteven Rostedt    } else {
3151a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
3152a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
3153a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
3154a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
3155a57419b3SSteven Rostedt	}
3156a57419b3SSteven Rostedt	doprint "\n";
3157a57419b3SSteven Rostedt    }
3158a57419b3SSteven Rostedt
31592b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
3160a57419b3SSteven Rostedt
3161a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
3162a57419b3SSteven Rostedt	    next if ($i != $1);
3163a57419b3SSteven Rostedt	} else {
3164a57419b3SSteven Rostedt	    next if ($i);
3165a57419b3SSteven Rostedt	}
3166a57419b3SSteven Rostedt
31672b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
31682b7d9b21SSteven Rostedt    }
3169a57419b3SSteven Rostedt}
31702545eb61SSteven Rostedt
31712a62512bSSteven Rostedtsub __set_test_option {
31725a391fbfSSteven Rostedt    my ($name, $i) = @_;
31735a391fbfSSteven Rostedt
31745a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
31755a391fbfSSteven Rostedt
31765a391fbfSSteven Rostedt    if (defined($opt{$option})) {
31775a391fbfSSteven Rostedt	return $opt{$option};
31785a391fbfSSteven Rostedt    }
31795a391fbfSSteven Rostedt
3180a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
3181a57419b3SSteven Rostedt	if ($i >= $test &&
3182a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
3183a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
3184a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
3185a57419b3SSteven Rostedt		return $opt{$option};
3186a57419b3SSteven Rostedt	    }
3187a57419b3SSteven Rostedt	}
3188a57419b3SSteven Rostedt    }
3189a57419b3SSteven Rostedt
31905a391fbfSSteven Rostedt    if (defined($opt{$name})) {
31915a391fbfSSteven Rostedt	return $opt{$name};
31925a391fbfSSteven Rostedt    }
31935a391fbfSSteven Rostedt
31945a391fbfSSteven Rostedt    return undef;
31955a391fbfSSteven Rostedt}
31965a391fbfSSteven Rostedt
31972a62512bSSteven Rostedtsub set_test_option {
31982a62512bSSteven Rostedt    my ($name, $i) = @_;
31992a62512bSSteven Rostedt
32002a62512bSSteven Rostedt    my $option = __set_test_option($name, $i);
32012a62512bSSteven Rostedt    return $option if (!defined($option));
32022a62512bSSteven Rostedt
320323715c3cSSteven Rostedt    return eval_option($option, $i);
32042a62512bSSteven Rostedt}
32052a62512bSSteven Rostedt
32062545eb61SSteven Rostedt# First we need to do is the builds
3207a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
32082545eb61SSteven Rostedt
32094ab1cce5SSteven Rostedt    # Do not reboot on failing test options
32104ab1cce5SSteven Rostedt    $no_reboot = 1;
32114ab1cce5SSteven Rostedt
3212576f627cSSteven Rostedt    $iteration = $i;
3213576f627cSSteven Rostedt
3214a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
3215a75fececSSteven Rostedt
3216a75fececSSteven Rostedt    $machine = set_test_option("MACHINE", $i);
3217e48c5293SSteven Rostedt    $ssh_user = set_test_option("SSH_USER", $i);
3218a75fececSSteven Rostedt    $tmpdir = set_test_option("TMP_DIR", $i);
3219a75fececSSteven Rostedt    $outputdir = set_test_option("OUTPUT_DIR", $i);
3220a75fececSSteven Rostedt    $builddir = set_test_option("BUILD_DIR", $i);
3221a75fececSSteven Rostedt    $test_type = set_test_option("TEST_TYPE", $i);
3222a75fececSSteven Rostedt    $build_type = set_test_option("BUILD_TYPE", $i);
3223a75fececSSteven Rostedt    $build_options = set_test_option("BUILD_OPTIONS", $i);
32240bd6c1a3SSteven Rostedt    $pre_build = set_test_option("PRE_BUILD", $i);
32250bd6c1a3SSteven Rostedt    $post_build = set_test_option("POST_BUILD", $i);
32260bd6c1a3SSteven Rostedt    $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
32270bd6c1a3SSteven Rostedt    $post_build_die = set_test_option("POST_BUILD_DIE", $i);
3228a75fececSSteven Rostedt    $power_cycle = set_test_option("POWER_CYCLE", $i);
3229e48c5293SSteven Rostedt    $reboot = set_test_option("REBOOT", $i);
3230a75fececSSteven Rostedt    $noclean = set_test_option("BUILD_NOCLEAN", $i);
3231a75fececSSteven Rostedt    $minconfig = set_test_option("MIN_CONFIG", $i);
32324c4ab120SSteven Rostedt    $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i);
32334c4ab120SSteven Rostedt    $start_minconfig = set_test_option("START_MIN_CONFIG", $i);
32344c4ab120SSteven Rostedt    $ignore_config = set_test_option("IGNORE_CONFIG", $i);
3235a75fececSSteven Rostedt    $run_test = set_test_option("TEST", $i);
3236a75fececSSteven Rostedt    $addconfig = set_test_option("ADD_CONFIG", $i);
3237a75fececSSteven Rostedt    $reboot_type = set_test_option("REBOOT_TYPE", $i);
3238a75fececSSteven Rostedt    $grub_menu = set_test_option("GRUB_MENU", $i);
32398b37ca8cSSteven Rostedt    $post_install = set_test_option("POST_INSTALL", $i);
3240e0a8742eSSteven Rostedt    $no_install = set_test_option("NO_INSTALL", $i);
3241a75fececSSteven Rostedt    $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
3242a75fececSSteven Rostedt    $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
3243a75fececSSteven Rostedt    $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
3244a75fececSSteven Rostedt    $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
3245a75fececSSteven Rostedt    $power_off = set_test_option("POWER_OFF", $i);
3246576f627cSSteven Rostedt    $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
3247576f627cSSteven Rostedt    $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
3248a75fececSSteven Rostedt    $sleep_time = set_test_option("SLEEP_TIME", $i);
3249a75fececSSteven Rostedt    $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
325027d934b2SSteven Rostedt    $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
32511990207dSSteven Rostedt    $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
3252c960bb9fSSteven Rostedt    $bisect_manual = set_test_option("BISECT_MANUAL", $i);
3253c23dca7cSSteven Rostedt    $bisect_skip = set_test_option("BISECT_SKIP", $i);
325430f75da5SSteven Rostedt    $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
3255a75fececSSteven Rostedt    $store_failures = set_test_option("STORE_FAILURES", $i);
3256de5b6e3bSRabin Vincent    $store_successes = set_test_option("STORE_SUCCESSES", $i);
32579064af52SSteven Rostedt    $test_name = set_test_option("TEST_NAME", $i);
3258a75fececSSteven Rostedt    $timeout = set_test_option("TIMEOUT", $i);
3259a75fececSSteven Rostedt    $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
3260a75fececSSteven Rostedt    $console = set_test_option("CONSOLE", $i);
3261f1a5b962SSteven Rostedt    $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
3262a75fececSSteven Rostedt    $success_line = set_test_option("SUCCESS_LINE", $i);
32632b803365SSteven Rostedt    $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i);
32641c8a617aSSteven Rostedt    $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
32651c8a617aSSteven Rostedt    $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
32662d01b26aSSteven Rostedt    $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
3267a75fececSSteven Rostedt    $build_target = set_test_option("BUILD_TARGET", $i);
3268e48c5293SSteven Rostedt    $ssh_exec = set_test_option("SSH_EXEC", $i);
3269e48c5293SSteven Rostedt    $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
3270a75fececSSteven Rostedt    $target_image = set_test_option("TARGET_IMAGE", $i);
3271a75fececSSteven Rostedt    $localversion = set_test_option("LOCALVERSION", $i);
3272a75fececSSteven Rostedt
327335ce5952SSteven Rostedt    $start_minconfig_defined = 1;
327435ce5952SSteven Rostedt
32754c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
327635ce5952SSteven Rostedt	$start_minconfig_defined = 0;
32774c4ab120SSteven Rostedt	$start_minconfig = $minconfig;
32784c4ab120SSteven Rostedt    }
32794c4ab120SSteven Rostedt
3280a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
3281a75fececSSteven Rostedt
3282a908a665SAndrew Jones    foreach my $dir ($tmpdir, $outputdir) {
3283a908a665SAndrew Jones	if (!-d $dir) {
3284a908a665SAndrew Jones	    mkpath($dir) or
3285a908a665SAndrew Jones		die "can't create $dir";
3286a908a665SAndrew Jones	}
3287a75fececSSteven Rostedt    }
3288a75fececSSteven Rostedt
3289e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
3290e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
3291e48c5293SSteven Rostedt
3292a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
3293a9dd5d63SRabin Vincent    $testlog = "$tmpdir/testlog-$machine";
3294a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
3295a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
329651ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
3297a75fececSSteven Rostedt
3298*bb8474b1SSteven Rostedt    if (!$buildonly) {
3299*bb8474b1SSteven Rostedt	$target = "$ssh_user\@$machine";
3300a75fececSSteven Rostedt	if ($reboot_type eq "grub") {
3301576f627cSSteven Rostedt	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3302a75fececSSteven Rostedt	} elsif (!defined($reboot_script)) {
3303576f627cSSteven Rostedt	    dodie "REBOOT_SCRIPT not defined"
3304a75fececSSteven Rostedt	}
3305*bb8474b1SSteven Rostedt    }
3306a75fececSSteven Rostedt
3307a75fececSSteven Rostedt    my $run_type = $build_type;
3308a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
3309a75fececSSteven Rostedt	$run_type = $opt{"PATCHCHECK_TYPE[$i]"};
3310a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
3311a75fececSSteven Rostedt	$run_type = $opt{"BISECT_TYPE[$i]"};
33120a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
33130a05c769SSteven Rostedt	$run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
3314a75fececSSteven Rostedt    }
3315a75fececSSteven Rostedt
33164c4ab120SSteven Rostedt    if ($test_type eq "make_min_config") {
33174c4ab120SSteven Rostedt	$run_type = "";
33184c4ab120SSteven Rostedt    }
33194c4ab120SSteven Rostedt
3320a75fececSSteven Rostedt    # mistake in config file?
3321a75fececSSteven Rostedt    if (!defined($run_type)) {
3322a75fececSSteven Rostedt	$run_type = "ERROR";
3323a75fececSSteven Rostedt    }
33242545eb61SSteven Rostedt
3325e0a8742eSSteven Rostedt    my $installme = "";
3326e0a8742eSSteven Rostedt    $installme = " no_install" if ($no_install);
3327e0a8742eSSteven Rostedt
33282545eb61SSteven Rostedt    doprint "\n\n";
3329e0a8742eSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
33307faafbd6SSteven Rostedt
33317faafbd6SSteven Rostedt    unlink $dmesg;
33327faafbd6SSteven Rostedt    unlink $buildlog;
3333a9dd5d63SRabin Vincent    unlink $testlog;
33342545eb61SSteven Rostedt
3335250bae8bSSteven Rostedt    if (defined($addconfig)) {
3336250bae8bSSteven Rostedt	my $min = $minconfig;
33372b7d9b21SSteven Rostedt	if (!defined($minconfig)) {
3338250bae8bSSteven Rostedt	    $min = "";
3339250bae8bSSteven Rostedt	}
3340250bae8bSSteven Rostedt	run_command "cat $addconfig $min > $tmpdir/add_config" or
33412b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
33429be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
33432b7d9b21SSteven Rostedt    }
33442b7d9b21SSteven Rostedt
33456c5ee0beSSteven Rostedt    my $checkout = $opt{"CHECKOUT[$i]"};
33466c5ee0beSSteven Rostedt    if (defined($checkout)) {
33476c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
33486c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
33496c5ee0beSSteven Rostedt    }
33506c5ee0beSSteven Rostedt
33514ab1cce5SSteven Rostedt    $no_reboot = 0;
33524ab1cce5SSteven Rostedt
33534ab1cce5SSteven Rostedt
3354a75fececSSteven Rostedt    if ($test_type eq "bisect") {
33555f9b6cedSSteven Rostedt	bisect $i;
33565f9b6cedSSteven Rostedt	next;
33570a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
33580a05c769SSteven Rostedt	config_bisect $i;
33590a05c769SSteven Rostedt	next;
3360a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
33616c5ee0beSSteven Rostedt	patchcheck $i;
33626c5ee0beSSteven Rostedt	next;
33634c4ab120SSteven Rostedt    } elsif ($test_type eq "make_min_config") {
33644c4ab120SSteven Rostedt	make_min_config $i;
33654c4ab120SSteven Rostedt	next;
33665f9b6cedSSteven Rostedt    }
33675f9b6cedSSteven Rostedt
33687faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
33697faafbd6SSteven Rostedt	build $build_type or next;
33702545eb61SSteven Rostedt    }
33712545eb61SSteven Rostedt
3372cd8e368fSSteven Rostedt    if ($test_type eq "install") {
3373cd8e368fSSteven Rostedt	get_version;
3374cd8e368fSSteven Rostedt	install;
3375cd8e368fSSteven Rostedt	success $i;
3376cd8e368fSSteven Rostedt	next;
3377cd8e368fSSteven Rostedt    }
3378cd8e368fSSteven Rostedt
3379a75fececSSteven Rostedt    if ($test_type ne "build") {
33807faafbd6SSteven Rostedt	my $failed = 0;
3381ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
3382a75fececSSteven Rostedt
3383a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
33847faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
33855a391fbfSSteven Rostedt	}
33867faafbd6SSteven Rostedt	end_monitor;
33877faafbd6SSteven Rostedt	next if ($failed);
3388a75fececSSteven Rostedt    }
33895a391fbfSSteven Rostedt
33905f9b6cedSSteven Rostedt    success $i;
339175c3fda7SSteven Rostedt}
33922545eb61SSteven Rostedt
33935c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
339475c3fda7SSteven Rostedt    halt;
3395576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
339675c3fda7SSteven Rostedt    reboot;
33975c42fc5bSSteven Rostedt}
339875c3fda7SSteven Rostedt
3399e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
3400e48c5293SSteven Rostedt
34012545eb61SSteven Rostedtexit 0;
3402