xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision 30f75da5ff475f1f455c0b009f3c06767963c54f)
12545eb61SSteven Rostedt#!/usr/bin/perl -w
2d6ce2a0bSSteven Rostedt#
3cce1dac8SUwe Kleine-König# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
4d6ce2a0bSSteven Rostedt# Licensed under the terms of the GNU GPL License version 2
5d6ce2a0bSSteven Rostedt#
62545eb61SSteven Rostedt
72545eb61SSteven Rostedtuse strict;
82545eb61SSteven Rostedtuse IPC::Open2;
92545eb61SSteven Rostedtuse Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
107faafbd6SSteven Rostedtuse File::Path qw(mkpath);
117faafbd6SSteven Rostedtuse File::Copy qw(cp);
122545eb61SSteven Rostedtuse FileHandle;
132545eb61SSteven Rostedt
14e48c5293SSteven Rostedtmy $VERSION = "0.2";
15e48c5293SSteven Rostedt
162545eb61SSteven Rostedt$| = 1;
172545eb61SSteven Rostedt
182545eb61SSteven Rostedtmy %opt;
19a57419b3SSteven Rostedtmy %repeat_tests;
20a57419b3SSteven Rostedtmy %repeats;
21a75fececSSteven Rostedtmy %default;
222545eb61SSteven Rostedt
232545eb61SSteven Rostedt#default opts
24a57419b3SSteven Rostedt$default{"NUM_TESTS"}		= 1;
25a75fececSSteven Rostedt$default{"REBOOT_TYPE"}		= "grub";
26a75fececSSteven Rostedt$default{"TEST_TYPE"}		= "test";
27a75fececSSteven Rostedt$default{"BUILD_TYPE"}		= "randconfig";
28a75fececSSteven Rostedt$default{"MAKE_CMD"}		= "make";
29a75fececSSteven Rostedt$default{"TIMEOUT"}		= 120;
30a57419b3SSteven Rostedt$default{"TMP_DIR"}		= "/tmp/ktest";
31a75fececSSteven Rostedt$default{"SLEEP_TIME"}		= 60;	# sleep time between tests
32a75fececSSteven Rostedt$default{"BUILD_NOCLEAN"}	= 0;
33a75fececSSteven Rostedt$default{"REBOOT_ON_ERROR"}	= 0;
34a75fececSSteven Rostedt$default{"POWEROFF_ON_ERROR"}	= 0;
35a75fececSSteven Rostedt$default{"REBOOT_ON_SUCCESS"}	= 1;
36a75fececSSteven Rostedt$default{"POWEROFF_ON_SUCCESS"}	= 0;
37a75fececSSteven Rostedt$default{"BUILD_OPTIONS"}	= "";
38a75fececSSteven Rostedt$default{"BISECT_SLEEP_TIME"}	= 60;   # sleep time between bisects
3927d934b2SSteven Rostedt$default{"PATCHCHECK_SLEEP_TIME"} = 60; # sleep time between patch checks
40a75fececSSteven Rostedt$default{"CLEAR_LOG"}		= 0;
41c960bb9fSSteven Rostedt$default{"BISECT_MANUAL"}	= 0;
42c23dca7cSSteven Rostedt$default{"BISECT_SKIP"}		= 1;
43a75fececSSteven Rostedt$default{"SUCCESS_LINE"}	= "login:";
44f1a5b962SSteven Rostedt$default{"DETECT_TRIPLE_FAULT"} = 1;
45a75fececSSteven Rostedt$default{"BOOTED_TIMEOUT"}	= 1;
46a75fececSSteven Rostedt$default{"DIE_ON_FAILURE"}	= 1;
47e48c5293SSteven Rostedt$default{"SSH_EXEC"}		= "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
48e48c5293SSteven Rostedt$default{"SCP_TO_TARGET"}	= "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE";
49e48c5293SSteven Rostedt$default{"REBOOT"}		= "ssh \$SSH_USER\@\$MACHINE reboot";
501c8a617aSSteven Rostedt$default{"STOP_AFTER_SUCCESS"}	= 10;
511c8a617aSSteven Rostedt$default{"STOP_AFTER_FAILURE"}	= 60;
522d01b26aSSteven Rostedt$default{"STOP_TEST_AFTER"}	= 600;
538d1491baSSteven Rostedt$default{"LOCALVERSION"}	= "-test";
542545eb61SSteven Rostedt
558d1491baSSteven Rostedtmy $ktest_config;
562545eb61SSteven Rostedtmy $version;
57a75fececSSteven Rostedtmy $machine;
58e48c5293SSteven Rostedtmy $ssh_user;
59a75fececSSteven Rostedtmy $tmpdir;
60a75fececSSteven Rostedtmy $builddir;
61a75fececSSteven Rostedtmy $outputdir;
6251ad1dd1SSteven Rostedtmy $output_config;
63a75fececSSteven Rostedtmy $test_type;
647faafbd6SSteven Rostedtmy $build_type;
65a75fececSSteven Rostedtmy $build_options;
66a75fececSSteven Rostedtmy $reboot_type;
67a75fececSSteven Rostedtmy $reboot_script;
68a75fececSSteven Rostedtmy $power_cycle;
69e48c5293SSteven Rostedtmy $reboot;
70a75fececSSteven Rostedtmy $reboot_on_error;
71a75fececSSteven Rostedtmy $poweroff_on_error;
72a75fececSSteven Rostedtmy $die_on_failure;
73576f627cSSteven Rostedtmy $powercycle_after_reboot;
74576f627cSSteven Rostedtmy $poweroff_after_halt;
75e48c5293SSteven Rostedtmy $ssh_exec;
76e48c5293SSteven Rostedtmy $scp_to_target;
77a75fececSSteven Rostedtmy $power_off;
78a75fececSSteven Rostedtmy $grub_menu;
792545eb61SSteven Rostedtmy $grub_number;
802545eb61SSteven Rostedtmy $target;
812545eb61SSteven Rostedtmy $make;
828b37ca8cSSteven Rostedtmy $post_install;
835c42fc5bSSteven Rostedtmy $noclean;
845f9b6cedSSteven Rostedtmy $minconfig;
852b7d9b21SSteven Rostedtmy $addconfig;
865f9b6cedSSteven Rostedtmy $in_bisect = 0;
875f9b6cedSSteven Rostedtmy $bisect_bad = "";
88d6ce2a0bSSteven Rostedtmy $reverse_bisect;
89c960bb9fSSteven Rostedtmy $bisect_manual;
90c23dca7cSSteven Rostedtmy $bisect_skip;
91*30f75da5SSteven Rostedtmy $config_bisect_good;
926c5ee0beSSteven Rostedtmy $in_patchcheck = 0;
935a391fbfSSteven Rostedtmy $run_test;
946c5ee0beSSteven Rostedtmy $redirect;
957faafbd6SSteven Rostedtmy $buildlog;
967faafbd6SSteven Rostedtmy $dmesg;
977faafbd6SSteven Rostedtmy $monitor_fp;
987faafbd6SSteven Rostedtmy $monitor_pid;
997faafbd6SSteven Rostedtmy $monitor_cnt = 0;
100a75fececSSteven Rostedtmy $sleep_time;
101a75fececSSteven Rostedtmy $bisect_sleep_time;
10227d934b2SSteven Rostedtmy $patchcheck_sleep_time;
103a75fececSSteven Rostedtmy $store_failures;
104a75fececSSteven Rostedtmy $timeout;
105a75fececSSteven Rostedtmy $booted_timeout;
106f1a5b962SSteven Rostedtmy $detect_triplefault;
107a75fececSSteven Rostedtmy $console;
108a75fececSSteven Rostedtmy $success_line;
1091c8a617aSSteven Rostedtmy $stop_after_success;
1101c8a617aSSteven Rostedtmy $stop_after_failure;
1112d01b26aSSteven Rostedtmy $stop_test_after;
112a75fececSSteven Rostedtmy $build_target;
113a75fececSSteven Rostedtmy $target_image;
114a75fececSSteven Rostedtmy $localversion;
115576f627cSSteven Rostedtmy $iteration = 0;
116e48c5293SSteven Rostedtmy $successes = 0;
1172545eb61SSteven Rostedt
1188d1491baSSteven Rostedtmy %entered_configs;
1198d1491baSSteven Rostedtmy %config_help;
12077d942ceSSteven Rostedtmy %variable;
1218d1491baSSteven Rostedt
1228d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF"
1238d1491baSSteven Rostedt The machine hostname that you will test.
1248d1491baSSteven RostedtEOF
1258d1491baSSteven Rostedt    ;
1268d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF"
1278d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user
1288d1491baSSteven Rostedt  (most likely root, since you need privileged operations)
1298d1491baSSteven RostedtEOF
1308d1491baSSteven Rostedt    ;
1318d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF"
1328d1491baSSteven Rostedt The directory that contains the Linux source code (full path).
1338d1491baSSteven RostedtEOF
1348d1491baSSteven Rostedt    ;
1358d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF"
1368d1491baSSteven Rostedt The directory that the objects will be built (full path).
1378d1491baSSteven Rostedt (can not be same as BUILD_DIR)
1388d1491baSSteven RostedtEOF
1398d1491baSSteven Rostedt    ;
1408d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF"
1418d1491baSSteven Rostedt The location of the compiled file to copy to the target.
1428d1491baSSteven Rostedt (relative to OUTPUT_DIR)
1438d1491baSSteven RostedtEOF
1448d1491baSSteven Rostedt    ;
1458d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF"
1468d1491baSSteven Rostedt The place to put your image on the test machine.
1478d1491baSSteven RostedtEOF
1488d1491baSSteven Rostedt    ;
1498d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF"
1508d1491baSSteven Rostedt A script or command to reboot the box.
1518d1491baSSteven Rostedt
1528d1491baSSteven Rostedt Here is a digital loggers power switch example
1538d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
1548d1491baSSteven Rostedt
1558d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host
1568d1491baSSteven Rostedt with the name "Guest".
1578d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
1588d1491baSSteven RostedtEOF
1598d1491baSSteven Rostedt    ;
1608d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF"
1618d1491baSSteven Rostedt The script or command that reads the console
1628d1491baSSteven Rostedt
1638d1491baSSteven Rostedt  If you use ttywatch server, something like the following would work.
1648d1491baSSteven RostedtCONSOLE = nc -d localhost 3001
1658d1491baSSteven Rostedt
1668d1491baSSteven Rostedt For a virtual machine with guest name "Guest".
1678d1491baSSteven RostedtCONSOLE =  virsh console Guest
1688d1491baSSteven RostedtEOF
1698d1491baSSteven Rostedt    ;
1708d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF"
1718d1491baSSteven Rostedt Required version ending to differentiate the test
1728d1491baSSteven Rostedt from other linux builds on the system.
1738d1491baSSteven RostedtEOF
1748d1491baSSteven Rostedt    ;
1758d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF"
1768d1491baSSteven Rostedt Way to reboot the box to the test kernel.
1778d1491baSSteven Rostedt Only valid options so far are "grub" and "script".
1788d1491baSSteven Rostedt
1798d1491baSSteven Rostedt If you specify grub, it will assume grub version 1
1808d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
1818d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not
1828d1491baSSteven Rostedt your setup, then specify "script" and have a command or script
1838d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target.
1848d1491baSSteven Rostedt
1858d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually.
1868d1491baSSteven Rostedt The test will not modify that file.
1878d1491baSSteven RostedtEOF
1888d1491baSSteven Rostedt    ;
1898d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF"
1908d1491baSSteven Rostedt The grub title name for the test kernel to boot
1918d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = grub)
1928d1491baSSteven Rostedt
1938d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to
1948d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search
1958d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to
1968d1491baSSteven Rostedt reboot into.
1978d1491baSSteven Rostedt
1988d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has:
1998d1491baSSteven Rostedt title Test Kernel
2008d1491baSSteven Rostedt kernel vmlinuz-test
2018d1491baSSteven Rostedt GRUB_MENU = Test Kernel
2028d1491baSSteven RostedtEOF
2038d1491baSSteven Rostedt    ;
2048d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF"
2058d1491baSSteven Rostedt A script to reboot the target into the test kernel
2068d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script)
2078d1491baSSteven RostedtEOF
2088d1491baSSteven Rostedt    ;
2098d1491baSSteven Rostedt
2108d1491baSSteven Rostedt
2118d1491baSSteven Rostedtsub get_ktest_config {
2128d1491baSSteven Rostedt    my ($config) = @_;
2138d1491baSSteven Rostedt
2148d1491baSSteven Rostedt    return if (defined($opt{$config}));
2158d1491baSSteven Rostedt
2168d1491baSSteven Rostedt    if (defined($config_help{$config})) {
2178d1491baSSteven Rostedt	print "\n";
2188d1491baSSteven Rostedt	print $config_help{$config};
2198d1491baSSteven Rostedt    }
2208d1491baSSteven Rostedt
2218d1491baSSteven Rostedt    for (;;) {
2228d1491baSSteven Rostedt	print "$config = ";
2238d1491baSSteven Rostedt	if (defined($default{$config})) {
2248d1491baSSteven Rostedt	    print "\[$default{$config}\] ";
2258d1491baSSteven Rostedt	}
2268d1491baSSteven Rostedt	$entered_configs{$config} = <STDIN>;
2278d1491baSSteven Rostedt	$entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/;
2288d1491baSSteven Rostedt	if ($entered_configs{$config} =~ /^\s*$/) {
2298d1491baSSteven Rostedt	    if ($default{$config}) {
2308d1491baSSteven Rostedt		$entered_configs{$config} = $default{$config};
2318d1491baSSteven Rostedt	    } else {
2328d1491baSSteven Rostedt		print "Your answer can not be blank\n";
2338d1491baSSteven Rostedt		next;
2348d1491baSSteven Rostedt	    }
2358d1491baSSteven Rostedt	}
2368d1491baSSteven Rostedt	last;
2378d1491baSSteven Rostedt    }
2388d1491baSSteven Rostedt}
2398d1491baSSteven Rostedt
2408d1491baSSteven Rostedtsub get_ktest_configs {
2418d1491baSSteven Rostedt    get_ktest_config("MACHINE");
2428d1491baSSteven Rostedt    get_ktest_config("SSH_USER");
2438d1491baSSteven Rostedt    get_ktest_config("BUILD_DIR");
2448d1491baSSteven Rostedt    get_ktest_config("OUTPUT_DIR");
2458d1491baSSteven Rostedt    get_ktest_config("BUILD_TARGET");
2468d1491baSSteven Rostedt    get_ktest_config("TARGET_IMAGE");
2478d1491baSSteven Rostedt    get_ktest_config("POWER_CYCLE");
2488d1491baSSteven Rostedt    get_ktest_config("CONSOLE");
2498d1491baSSteven Rostedt    get_ktest_config("LOCALVERSION");
2508d1491baSSteven Rostedt
2518d1491baSSteven Rostedt    my $rtype = $opt{"REBOOT_TYPE"};
2528d1491baSSteven Rostedt
2538d1491baSSteven Rostedt    if (!defined($rtype)) {
2548d1491baSSteven Rostedt	if (!defined($opt{"GRUB_MENU"})) {
2558d1491baSSteven Rostedt	    get_ktest_config("REBOOT_TYPE");
2568d1491baSSteven Rostedt	    $rtype = $entered_configs{"REBOOT_TYPE"};
2578d1491baSSteven Rostedt	} else {
2588d1491baSSteven Rostedt	    $rtype = "grub";
2598d1491baSSteven Rostedt	}
2608d1491baSSteven Rostedt    }
2618d1491baSSteven Rostedt
2628d1491baSSteven Rostedt    if ($rtype eq "grub") {
2638d1491baSSteven Rostedt	get_ktest_config("GRUB_MENU");
2648d1491baSSteven Rostedt    } else {
2658d1491baSSteven Rostedt	get_ktest_config("REBOOT_SCRIPT");
2668d1491baSSteven Rostedt    }
2678d1491baSSteven Rostedt}
2688d1491baSSteven Rostedt
26977d942ceSSteven Rostedtsub process_variables {
27077d942ceSSteven Rostedt    my ($value) = @_;
27177d942ceSSteven Rostedt    my $retval = "";
27277d942ceSSteven Rostedt
27377d942ceSSteven Rostedt    # We want to check for '\', and it is just easier
27477d942ceSSteven Rostedt    # to check the previous characet of '$' and not need
27577d942ceSSteven Rostedt    # to worry if '$' is the first character. By adding
27677d942ceSSteven Rostedt    # a space to $value, we can just check [^\\]\$ and
27777d942ceSSteven Rostedt    # it will still work.
27877d942ceSSteven Rostedt    $value = " $value";
27977d942ceSSteven Rostedt
28077d942ceSSteven Rostedt    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
28177d942ceSSteven Rostedt	my $begin = $1;
28277d942ceSSteven Rostedt	my $var = $2;
28377d942ceSSteven Rostedt	my $end = $3;
28477d942ceSSteven Rostedt	# append beginning of value to retval
28577d942ceSSteven Rostedt	$retval = "$retval$begin";
28677d942ceSSteven Rostedt	if (defined($variable{$var})) {
28777d942ceSSteven Rostedt	    $retval = "$retval$variable{$var}";
28877d942ceSSteven Rostedt	} else {
28977d942ceSSteven Rostedt	    # put back the origin piece.
29077d942ceSSteven Rostedt	    $retval = "$retval\$\{$var\}";
29177d942ceSSteven Rostedt	}
29277d942ceSSteven Rostedt	$value = $end;
29377d942ceSSteven Rostedt    }
29477d942ceSSteven Rostedt    $retval = "$retval$value";
29577d942ceSSteven Rostedt
29677d942ceSSteven Rostedt    # remove the space added in the beginning
29777d942ceSSteven Rostedt    $retval =~ s/ //;
29877d942ceSSteven Rostedt
29977d942ceSSteven Rostedt    return "$retval"
30077d942ceSSteven Rostedt}
30177d942ceSSteven Rostedt
302a57419b3SSteven Rostedtsub set_value {
303a57419b3SSteven Rostedt    my ($lvalue, $rvalue) = @_;
3042545eb61SSteven Rostedt
305a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
306a75fececSSteven Rostedt	die "Error: Option $lvalue defined more than once!\n";
307a75fececSSteven Rostedt    }
30821a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
30921a9679fSSteven Rostedt	delete $opt{$lvalue};
31021a9679fSSteven Rostedt    } else {
31177d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
31221a9679fSSteven Rostedt	$opt{$lvalue} = $rvalue;
31321a9679fSSteven Rostedt    }
3142545eb61SSteven Rostedt}
315a57419b3SSteven Rostedt
31677d942ceSSteven Rostedtsub set_variable {
31777d942ceSSteven Rostedt    my ($lvalue, $rvalue) = @_;
31877d942ceSSteven Rostedt
31977d942ceSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
32077d942ceSSteven Rostedt	delete $variable{$lvalue};
32177d942ceSSteven Rostedt    } else {
32277d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
32377d942ceSSteven Rostedt	$variable{$lvalue} = $rvalue;
32477d942ceSSteven Rostedt    }
32577d942ceSSteven Rostedt}
32677d942ceSSteven Rostedt
327a57419b3SSteven Rostedtsub read_config {
328a57419b3SSteven Rostedt    my ($config) = @_;
329a57419b3SSteven Rostedt
330a57419b3SSteven Rostedt    open(IN, $config) || die "can't read file $config";
331a57419b3SSteven Rostedt
332a57419b3SSteven Rostedt    my $name = $config;
333a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
334a57419b3SSteven Rostedt
335a57419b3SSteven Rostedt    my $test_num = 0;
336a57419b3SSteven Rostedt    my $default = 1;
337a57419b3SSteven Rostedt    my $repeat = 1;
338a57419b3SSteven Rostedt    my $num_tests_set = 0;
339a57419b3SSteven Rostedt    my $skip = 0;
340a57419b3SSteven Rostedt    my $rest;
341a57419b3SSteven Rostedt
342a57419b3SSteven Rostedt    while (<IN>) {
343a57419b3SSteven Rostedt
344a57419b3SSteven Rostedt	# ignore blank lines and comments
345a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
346a57419b3SSteven Rostedt
347a57419b3SSteven Rostedt	if (/^\s*TEST_START(.*)/) {
348a57419b3SSteven Rostedt
349a57419b3SSteven Rostedt	    $rest = $1;
350a57419b3SSteven Rostedt
351a57419b3SSteven Rostedt	    if ($num_tests_set) {
352a57419b3SSteven Rostedt		die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
353a57419b3SSteven Rostedt	    }
354a57419b3SSteven Rostedt
355a57419b3SSteven Rostedt	    my $old_test_num = $test_num;
356e48c5293SSteven Rostedt	    my $old_repeat = $repeat;
357a57419b3SSteven Rostedt
358a57419b3SSteven Rostedt	    $test_num += $repeat;
359a57419b3SSteven Rostedt	    $default = 0;
360a57419b3SSteven Rostedt	    $repeat = 1;
361a57419b3SSteven Rostedt
362a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
363a57419b3SSteven Rostedt		$rest = $1;
364a57419b3SSteven Rostedt		$skip = 1;
365a57419b3SSteven Rostedt	    } else {
366a57419b3SSteven Rostedt		$skip = 0;
367a57419b3SSteven Rostedt	    }
368a57419b3SSteven Rostedt
369a57419b3SSteven Rostedt	    if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
370a57419b3SSteven Rostedt		$repeat = $1;
371a57419b3SSteven Rostedt		$rest = $2;
372a57419b3SSteven Rostedt		$repeat_tests{"$test_num"} = $repeat;
373a57419b3SSteven Rostedt	    }
374a57419b3SSteven Rostedt
375a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
376a57419b3SSteven Rostedt		$rest = $1;
377a57419b3SSteven Rostedt		$skip = 1;
378a57419b3SSteven Rostedt	    }
379a57419b3SSteven Rostedt
380a57419b3SSteven Rostedt	    if ($rest !~ /^\s*$/) {
381a57419b3SSteven Rostedt		die "$name: $.: Gargbage found after TEST_START\n$_";
382a57419b3SSteven Rostedt	    }
383a57419b3SSteven Rostedt
384a57419b3SSteven Rostedt	    if ($skip) {
385a57419b3SSteven Rostedt		$test_num = $old_test_num;
386e48c5293SSteven Rostedt		$repeat = $old_repeat;
387a57419b3SSteven Rostedt	    }
388a57419b3SSteven Rostedt
389a57419b3SSteven Rostedt	} elsif (/^\s*DEFAULTS(.*)$/) {
390a57419b3SSteven Rostedt	    $default = 1;
391a57419b3SSteven Rostedt
392a57419b3SSteven Rostedt	    $rest = $1;
393a57419b3SSteven Rostedt
394a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
395a57419b3SSteven Rostedt		$rest = $1;
396a57419b3SSteven Rostedt		$skip = 1;
397a57419b3SSteven Rostedt	    } else {
398a57419b3SSteven Rostedt		$skip = 0;
399a57419b3SSteven Rostedt	    }
400a57419b3SSteven Rostedt
401a57419b3SSteven Rostedt	    if ($rest !~ /^\s*$/) {
402a57419b3SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
403a57419b3SSteven Rostedt	    }
404a57419b3SSteven Rostedt
405a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
406a57419b3SSteven Rostedt
407a57419b3SSteven Rostedt	    next if ($skip);
408a57419b3SSteven Rostedt
409a57419b3SSteven Rostedt	    my $lvalue = $1;
410a57419b3SSteven Rostedt	    my $rvalue = $2;
411a57419b3SSteven Rostedt
412a57419b3SSteven Rostedt	    if (!$default &&
413a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
414a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
415a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
416a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
417a57419b3SSteven Rostedt	    }
418a57419b3SSteven Rostedt
419a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
420a57419b3SSteven Rostedt		if ($test_num) {
421a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
422a57419b3SSteven Rostedt		}
423a57419b3SSteven Rostedt		if (!$default) {
424a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
425a57419b3SSteven Rostedt		}
426a57419b3SSteven Rostedt		$num_tests_set = 1;
427a57419b3SSteven Rostedt	    }
428a57419b3SSteven Rostedt
429a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
430a57419b3SSteven Rostedt		set_value($lvalue, $rvalue);
431a57419b3SSteven Rostedt	    } else {
432a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
433a57419b3SSteven Rostedt		set_value($val, $rvalue);
434a57419b3SSteven Rostedt
435a57419b3SSteven Rostedt		if ($repeat > 1) {
436a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
437a57419b3SSteven Rostedt		}
438a57419b3SSteven Rostedt	    }
43977d942ceSSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
44077d942ceSSteven Rostedt	    next if ($skip);
44177d942ceSSteven Rostedt
44277d942ceSSteven Rostedt	    my $lvalue = $1;
44377d942ceSSteven Rostedt	    my $rvalue = $2;
44477d942ceSSteven Rostedt
44577d942ceSSteven Rostedt	    # process config variables.
44677d942ceSSteven Rostedt	    # Config variables are only active while reading the
44777d942ceSSteven Rostedt	    # config and can be defined anywhere. They also ignore
44877d942ceSSteven Rostedt	    # TEST_START and DEFAULTS, but are skipped if they are in
44977d942ceSSteven Rostedt	    # on of these sections that have SKIP defined.
45077d942ceSSteven Rostedt	    # The save variable can be
45177d942ceSSteven Rostedt	    # defined multiple times and the new one simply overrides
45277d942ceSSteven Rostedt	    # the prevous one.
45377d942ceSSteven Rostedt	    set_variable($lvalue, $rvalue);
45477d942ceSSteven Rostedt
455a57419b3SSteven Rostedt	} else {
456a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
457a57419b3SSteven Rostedt	}
4582545eb61SSteven Rostedt    }
4592545eb61SSteven Rostedt
4602545eb61SSteven Rostedt    close(IN);
461a75fececSSteven Rostedt
462a57419b3SSteven Rostedt    if ($test_num) {
463a57419b3SSteven Rostedt	$test_num += $repeat - 1;
464a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
465a57419b3SSteven Rostedt    }
466a57419b3SSteven Rostedt
4678d1491baSSteven Rostedt    # make sure we have all mandatory configs
4688d1491baSSteven Rostedt    get_ktest_configs;
4698d1491baSSteven Rostedt
470a75fececSSteven Rostedt    # set any defaults
471a75fececSSteven Rostedt
472a75fececSSteven Rostedt    foreach my $default (keys %default) {
473a75fececSSteven Rostedt	if (!defined($opt{$default})) {
474a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
475a75fececSSteven Rostedt	}
476a75fececSSteven Rostedt    }
4772545eb61SSteven Rostedt}
4782545eb61SSteven Rostedt
479d1e2f22aSSteven Rostedtsub _logit {
4802545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
4812545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
4822545eb61SSteven Rostedt	print OUT @_;
4832545eb61SSteven Rostedt	close(OUT);
4842545eb61SSteven Rostedt    }
4852545eb61SSteven Rostedt}
4862545eb61SSteven Rostedt
487d1e2f22aSSteven Rostedtsub logit {
488d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
489d1e2f22aSSteven Rostedt	_logit @_;
490d1e2f22aSSteven Rostedt    } else {
491d1e2f22aSSteven Rostedt	print @_;
492d1e2f22aSSteven Rostedt    }
493d1e2f22aSSteven Rostedt}
494d1e2f22aSSteven Rostedt
4955f9b6cedSSteven Rostedtsub doprint {
4965f9b6cedSSteven Rostedt    print @_;
497d1e2f22aSSteven Rostedt    _logit @_;
4985f9b6cedSSteven Rostedt}
4995f9b6cedSSteven Rostedt
5007faafbd6SSteven Rostedtsub run_command;
5017faafbd6SSteven Rostedt
5027faafbd6SSteven Rostedtsub reboot {
5037faafbd6SSteven Rostedt    # try to reboot normally
504e48c5293SSteven Rostedt    if (run_command $reboot) {
505576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
506576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
507576f627cSSteven Rostedt	    run_command "$power_cycle";
508576f627cSSteven Rostedt	}
509576f627cSSteven Rostedt    } else {
5107faafbd6SSteven Rostedt	# nope? power cycle it.
511a75fececSSteven Rostedt	run_command "$power_cycle";
5127faafbd6SSteven Rostedt    }
5137faafbd6SSteven Rostedt}
5147faafbd6SSteven Rostedt
515576f627cSSteven Rostedtsub do_not_reboot {
516576f627cSSteven Rostedt    my $i = $iteration;
517576f627cSSteven Rostedt
518576f627cSSteven Rostedt    return $test_type eq "build" ||
519576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
520576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
521576f627cSSteven Rostedt}
522576f627cSSteven Rostedt
5235c42fc5bSSteven Rostedtsub dodie {
5245a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
5255c42fc5bSSteven Rostedt
526576f627cSSteven Rostedt    my $i = $iteration;
527576f627cSSteven Rostedt
528576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
529576f627cSSteven Rostedt
53075c3fda7SSteven Rostedt	doprint "REBOOTING\n";
5317faafbd6SSteven Rostedt	reboot;
53275c3fda7SSteven Rostedt
533a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
5345c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
535a75fececSSteven Rostedt	`$power_off`;
5365c42fc5bSSteven Rostedt    }
53775c3fda7SSteven Rostedt
538f80802cbSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
539f80802cbSSteven Rostedt	print " See $opt{LOG_FILE} for more info.\n";
540f80802cbSSteven Rostedt    }
541f80802cbSSteven Rostedt
542576f627cSSteven Rostedt    die @_, "\n";
5435c42fc5bSSteven Rostedt}
5445c42fc5bSSteven Rostedt
5457faafbd6SSteven Rostedtsub open_console {
5467faafbd6SSteven Rostedt    my ($fp) = @_;
5477faafbd6SSteven Rostedt
5487faafbd6SSteven Rostedt    my $flags;
5497faafbd6SSteven Rostedt
550a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
551a75fececSSteven Rostedt	dodie "Can't open console $console";
5527faafbd6SSteven Rostedt
5537faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
554576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
5557faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
556576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
5577faafbd6SSteven Rostedt
5587faafbd6SSteven Rostedt    return $pid;
5597faafbd6SSteven Rostedt}
5607faafbd6SSteven Rostedt
5617faafbd6SSteven Rostedtsub close_console {
5627faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
5637faafbd6SSteven Rostedt
5647faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
5657faafbd6SSteven Rostedt    kill 2, $pid;
5667faafbd6SSteven Rostedt
5677faafbd6SSteven Rostedt    print "closing!\n";
5687faafbd6SSteven Rostedt    close($fp);
5697faafbd6SSteven Rostedt}
5707faafbd6SSteven Rostedt
5717faafbd6SSteven Rostedtsub start_monitor {
5727faafbd6SSteven Rostedt    if ($monitor_cnt++) {
5737faafbd6SSteven Rostedt	return;
5747faafbd6SSteven Rostedt    }
5757faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
5767faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
577a75fececSSteven Rostedt
578a75fececSSteven Rostedt    return;
579a75fececSSteven Rostedt
580a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
5817faafbd6SSteven Rostedt}
5827faafbd6SSteven Rostedt
5837faafbd6SSteven Rostedtsub end_monitor {
5847faafbd6SSteven Rostedt    if (--$monitor_cnt) {
5857faafbd6SSteven Rostedt	return;
5867faafbd6SSteven Rostedt    }
5877faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
5887faafbd6SSteven Rostedt}
5897faafbd6SSteven Rostedt
5907faafbd6SSteven Rostedtsub wait_for_monitor {
5917faafbd6SSteven Rostedt    my ($time) = @_;
5927faafbd6SSteven Rostedt    my $line;
5937faafbd6SSteven Rostedt
594a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
5957faafbd6SSteven Rostedt
5967faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
5977faafbd6SSteven Rostedt    do {
5987faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
599a75fececSSteven Rostedt	print "$line" if (defined($line));
6007faafbd6SSteven Rostedt    } while (defined($line));
601a75fececSSteven Rostedt    print "** Monitor flushed **\n";
6027faafbd6SSteven Rostedt}
6037faafbd6SSteven Rostedt
6042b7d9b21SSteven Rostedtsub fail {
6052b7d9b21SSteven Rostedt
606a75fececSSteven Rostedt	if ($die_on_failure) {
6072b7d9b21SSteven Rostedt		dodie @_;
6082b7d9b21SSteven Rostedt	}
6092b7d9b21SSteven Rostedt
610a75fececSSteven Rostedt	doprint "FAILED\n";
6117faafbd6SSteven Rostedt
612576f627cSSteven Rostedt	my $i = $iteration;
613576f627cSSteven Rostedt
614a75fececSSteven Rostedt	# no need to reboot for just building.
615576f627cSSteven Rostedt	if (!do_not_reboot) {
6167faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
6177faafbd6SSteven Rostedt	    reboot;
6187faafbd6SSteven Rostedt	    start_monitor;
619a75fececSSteven Rostedt	    wait_for_monitor $sleep_time;
6207faafbd6SSteven Rostedt	    end_monitor;
621a75fececSSteven Rostedt	}
6227faafbd6SSteven Rostedt
623576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
624576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
6257a849cd9SSteven Rostedt	doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n";
626576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
627576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
628a75fececSSteven Rostedt
629a75fececSSteven Rostedt	return 1 if (!defined($store_failures));
6307faafbd6SSteven Rostedt
6317faafbd6SSteven Rostedt	my @t = localtime;
6327faafbd6SSteven Rostedt	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
6337faafbd6SSteven Rostedt		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
6347faafbd6SSteven Rostedt
635cccae1a6SSteven Rostedt	my $type = $build_type;
636cccae1a6SSteven Rostedt	if ($type =~ /useconfig/) {
637cccae1a6SSteven Rostedt	    $type = "useconfig";
638cccae1a6SSteven Rostedt	}
639cccae1a6SSteven Rostedt
640cccae1a6SSteven Rostedt	my $dir = "$machine-$test_type-$type-fail-$date";
641a75fececSSteven Rostedt	my $faildir = "$store_failures/$dir";
6427faafbd6SSteven Rostedt
6437faafbd6SSteven Rostedt	if (!-d $faildir) {
6447faafbd6SSteven Rostedt	    mkpath($faildir) or
645a75fececSSteven Rostedt		die "can't create $faildir";
6467faafbd6SSteven Rostedt	}
64751ad1dd1SSteven Rostedt	if (-f "$output_config") {
64851ad1dd1SSteven Rostedt	    cp "$output_config", "$faildir/config" or
6497faafbd6SSteven Rostedt		die "failed to copy .config";
6507faafbd6SSteven Rostedt	}
6517faafbd6SSteven Rostedt	if (-f $buildlog) {
6527faafbd6SSteven Rostedt	    cp $buildlog, "$faildir/buildlog" or
6537faafbd6SSteven Rostedt		die "failed to move $buildlog";
6547faafbd6SSteven Rostedt	}
6557faafbd6SSteven Rostedt	if (-f $dmesg) {
6567faafbd6SSteven Rostedt	    cp $dmesg, "$faildir/dmesg" or
6577faafbd6SSteven Rostedt		die "failed to move $dmesg";
6587faafbd6SSteven Rostedt	}
6597faafbd6SSteven Rostedt
6607faafbd6SSteven Rostedt	doprint "*** Saved info to $faildir ***\n";
6617faafbd6SSteven Rostedt
6622b7d9b21SSteven Rostedt	return 1;
6632b7d9b21SSteven Rostedt}
6642b7d9b21SSteven Rostedt
6652545eb61SSteven Rostedtsub run_command {
6662545eb61SSteven Rostedt    my ($command) = @_;
667d6ce2a0bSSteven Rostedt    my $dolog = 0;
668d6ce2a0bSSteven Rostedt    my $dord = 0;
669d6ce2a0bSSteven Rostedt    my $pid;
670d6ce2a0bSSteven Rostedt
671e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
672e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
673e48c5293SSteven Rostedt
674d6ce2a0bSSteven Rostedt    doprint("$command ... ");
675d6ce2a0bSSteven Rostedt
676d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
6772b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
6782545eb61SSteven Rostedt
6792545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
680d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
681d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
682d6ce2a0bSSteven Rostedt	$dolog = 1;
6836c5ee0beSSteven Rostedt    }
6846c5ee0beSSteven Rostedt
6856c5ee0beSSteven Rostedt    if (defined($redirect)) {
686d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
687d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
688d6ce2a0bSSteven Rostedt	$dord = 1;
6892545eb61SSteven Rostedt    }
6902545eb61SSteven Rostedt
691d6ce2a0bSSteven Rostedt    while (<CMD>) {
692d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
693d6ce2a0bSSteven Rostedt	print RD  if ($dord);
694d6ce2a0bSSteven Rostedt    }
6952545eb61SSteven Rostedt
696d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
6972545eb61SSteven Rostedt    my $failed = $?;
6982545eb61SSteven Rostedt
699d6ce2a0bSSteven Rostedt    close(CMD);
700d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
701d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
702d6ce2a0bSSteven Rostedt
7032545eb61SSteven Rostedt    if ($failed) {
7042545eb61SSteven Rostedt	doprint "FAILED!\n";
7052545eb61SSteven Rostedt    } else {
7062545eb61SSteven Rostedt	doprint "SUCCESS\n";
7072545eb61SSteven Rostedt    }
7082545eb61SSteven Rostedt
7095f9b6cedSSteven Rostedt    return !$failed;
7105f9b6cedSSteven Rostedt}
7115f9b6cedSSteven Rostedt
712e48c5293SSteven Rostedtsub run_ssh {
713e48c5293SSteven Rostedt    my ($cmd) = @_;
714e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
715e48c5293SSteven Rostedt
716e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
717e48c5293SSteven Rostedt    return run_command "$cp_exec";
718e48c5293SSteven Rostedt}
719e48c5293SSteven Rostedt
720e48c5293SSteven Rostedtsub run_scp {
721e48c5293SSteven Rostedt    my ($src, $dst) = @_;
722e48c5293SSteven Rostedt    my $cp_scp = $scp_to_target;
723e48c5293SSteven Rostedt
724e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
725e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
726e48c5293SSteven Rostedt
727e48c5293SSteven Rostedt    return run_command "$cp_scp";
728e48c5293SSteven Rostedt}
729e48c5293SSteven Rostedt
7305f9b6cedSSteven Rostedtsub get_grub_index {
7315f9b6cedSSteven Rostedt
732a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
733a75fececSSteven Rostedt	return;
734a75fececSSteven Rostedt    }
7355a391fbfSSteven Rostedt    return if (defined($grub_number));
7365f9b6cedSSteven Rostedt
7375f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
7385f9b6cedSSteven Rostedt    $grub_number = -1;
739e48c5293SSteven Rostedt
740e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
741e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
742e48c5293SSteven Rostedt
743e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
7445f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
745e48c5293SSteven Rostedt
7465f9b6cedSSteven Rostedt    while (<IN>) {
747a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
7485f9b6cedSSteven Rostedt	    $grub_number++;
7495f9b6cedSSteven Rostedt	    last;
7505f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
7515f9b6cedSSteven Rostedt	    $grub_number++;
7525f9b6cedSSteven Rostedt	}
7535f9b6cedSSteven Rostedt    }
7545f9b6cedSSteven Rostedt    close(IN);
7555f9b6cedSSteven Rostedt
756a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
7575f9b6cedSSteven Rostedt	if ($grub_number < 0);
7585f9b6cedSSteven Rostedt    doprint "$grub_number\n";
7592545eb61SSteven Rostedt}
7602545eb61SSteven Rostedt
7612545eb61SSteven Rostedtsub wait_for_input
7622545eb61SSteven Rostedt{
7632545eb61SSteven Rostedt    my ($fp, $time) = @_;
7642545eb61SSteven Rostedt    my $rin;
7652545eb61SSteven Rostedt    my $ready;
7662545eb61SSteven Rostedt    my $line;
7672545eb61SSteven Rostedt    my $ch;
7682545eb61SSteven Rostedt
7692545eb61SSteven Rostedt    if (!defined($time)) {
7702545eb61SSteven Rostedt	$time = $timeout;
7712545eb61SSteven Rostedt    }
7722545eb61SSteven Rostedt
7732545eb61SSteven Rostedt    $rin = '';
7742545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
7752545eb61SSteven Rostedt    $ready = select($rin, undef, undef, $time);
7762545eb61SSteven Rostedt
7772545eb61SSteven Rostedt    $line = "";
7782545eb61SSteven Rostedt
7792545eb61SSteven Rostedt    # try to read one char at a time
7802545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
7812545eb61SSteven Rostedt	$line .= $ch;
7822545eb61SSteven Rostedt	last if ($ch eq "\n");
7832545eb61SSteven Rostedt    }
7842545eb61SSteven Rostedt
7852545eb61SSteven Rostedt    if (!length($line)) {
7862545eb61SSteven Rostedt	return undef;
7872545eb61SSteven Rostedt    }
7882545eb61SSteven Rostedt
7892545eb61SSteven Rostedt    return $line;
7902545eb61SSteven Rostedt}
7912545eb61SSteven Rostedt
79275c3fda7SSteven Rostedtsub reboot_to {
793a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
7944da46da2SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'";
795a75fececSSteven Rostedt	return;
796a75fececSSteven Rostedt    }
797a75fececSSteven Rostedt
798a75fececSSteven Rostedt    run_command "$reboot_script";
7992545eb61SSteven Rostedt}
8002545eb61SSteven Rostedt
801a57419b3SSteven Rostedtsub get_sha1 {
802a57419b3SSteven Rostedt    my ($commit) = @_;
803a57419b3SSteven Rostedt
804a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
805a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
806a57419b3SSteven Rostedt    my $ret = $?;
807a57419b3SSteven Rostedt
808a57419b3SSteven Rostedt    logit $sha1;
809a57419b3SSteven Rostedt
810a57419b3SSteven Rostedt    if ($ret) {
811a57419b3SSteven Rostedt	doprint "FAILED\n";
812a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
813a57419b3SSteven Rostedt    }
814a57419b3SSteven Rostedt
815a57419b3SSteven Rostedt    print "SUCCESS\n";
816a57419b3SSteven Rostedt
817a57419b3SSteven Rostedt    chomp $sha1;
818a57419b3SSteven Rostedt
819a57419b3SSteven Rostedt    return $sha1;
820a57419b3SSteven Rostedt}
821a57419b3SSteven Rostedt
8225a391fbfSSteven Rostedtsub monitor {
8232545eb61SSteven Rostedt    my $booted = 0;
8242545eb61SSteven Rostedt    my $bug = 0;
8255c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
8262b7d9b21SSteven Rostedt    my $loops;
8272545eb61SSteven Rostedt
8287faafbd6SSteven Rostedt    wait_for_monitor 5;
8292545eb61SSteven Rostedt
8302545eb61SSteven Rostedt    my $line;
8312545eb61SSteven Rostedt    my $full_line = "";
8322545eb61SSteven Rostedt
8337faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
8347faafbd6SSteven Rostedt	die "unable to write to $dmesg";
8352545eb61SSteven Rostedt
83675c3fda7SSteven Rostedt    reboot_to;
8372545eb61SSteven Rostedt
8381c8a617aSSteven Rostedt    my $success_start;
8391c8a617aSSteven Rostedt    my $failure_start;
8402d01b26aSSteven Rostedt    my $monitor_start = time;
8412d01b26aSSteven Rostedt    my $done = 0;
842f1a5b962SSteven Rostedt    my $version_found = 0;
8431c8a617aSSteven Rostedt
8442d01b26aSSteven Rostedt    while (!$done) {
8452545eb61SSteven Rostedt
8462b7d9b21SSteven Rostedt	if ($booted) {
847a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
848cd4f1d53SSteven Rostedt	    if (!defined($line)) {
849cd4f1d53SSteven Rostedt		my $s = $booted_timeout == 1 ? "" : "s";
850cd4f1d53SSteven Rostedt		doprint "Successful boot found: break after $booted_timeout second$s\n";
851cd4f1d53SSteven Rostedt		last;
852cd4f1d53SSteven Rostedt	    }
8532b7d9b21SSteven Rostedt	} else {
8547faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
855cd4f1d53SSteven Rostedt	    if (!defined($line)) {
856cd4f1d53SSteven Rostedt		my $s = $timeout == 1 ? "" : "s";
857cd4f1d53SSteven Rostedt		doprint "Timed out after $timeout second$s\n";
858cd4f1d53SSteven Rostedt		last;
8592b7d9b21SSteven Rostedt	    }
860cd4f1d53SSteven Rostedt	}
8612545eb61SSteven Rostedt
8622545eb61SSteven Rostedt	doprint $line;
8637faafbd6SSteven Rostedt	print DMESG $line;
8642545eb61SSteven Rostedt
8652545eb61SSteven Rostedt	# we are not guaranteed to get a full line
8662545eb61SSteven Rostedt	$full_line .= $line;
8672545eb61SSteven Rostedt
868a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
8692545eb61SSteven Rostedt	    $booted = 1;
8701c8a617aSSteven Rostedt	    $success_start = time;
8711c8a617aSSteven Rostedt	}
8721c8a617aSSteven Rostedt
8731c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
8741c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
8751c8a617aSSteven Rostedt	    my $now = time;
8761c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
8771c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
8781c8a617aSSteven Rostedt		last;
8791c8a617aSSteven Rostedt	    }
8802545eb61SSteven Rostedt	}
8812545eb61SSteven Rostedt
8825c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
8835c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
8845c42fc5bSSteven Rostedt	}
8855c42fc5bSSteven Rostedt
8862545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
8874651920eSSteven Rostedt	    if (!$bug && !$skip_call_trace) {
8881c8a617aSSteven Rostedt		$bug = 1;
8891c8a617aSSteven Rostedt		$failure_start = time;
8901c8a617aSSteven Rostedt	    }
8911c8a617aSSteven Rostedt	}
8921c8a617aSSteven Rostedt
8931c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
8941c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
8951c8a617aSSteven Rostedt	    my $now = time;
8961c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
8971c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
8981c8a617aSSteven Rostedt		last;
8991c8a617aSSteven Rostedt	    }
9005c42fc5bSSteven Rostedt	}
9015c42fc5bSSteven Rostedt
9025c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
9035c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
9045c42fc5bSSteven Rostedt	}
9055c42fc5bSSteven Rostedt
9065c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
90710abf118SSteven Rostedt	    $failure_start = time;
9082545eb61SSteven Rostedt	    $bug = 1;
9092545eb61SSteven Rostedt	}
9102545eb61SSteven Rostedt
911f1a5b962SSteven Rostedt	# Detect triple faults by testing the banner
912f1a5b962SSteven Rostedt	if ($full_line =~ /\bLinux version (\S+).*\n/) {
913f1a5b962SSteven Rostedt	    if ($1 eq $version) {
914f1a5b962SSteven Rostedt		$version_found = 1;
915f1a5b962SSteven Rostedt	    } elsif ($version_found && $detect_triplefault) {
916f1a5b962SSteven Rostedt		# We already booted into the kernel we are testing,
917f1a5b962SSteven Rostedt		# but now we booted into another kernel?
918f1a5b962SSteven Rostedt		# Consider this a triple fault.
919f1a5b962SSteven Rostedt		doprint "Aleady booted in Linux kernel $version, but now\n";
920f1a5b962SSteven Rostedt		doprint "we booted into Linux kernel $1.\n";
921f1a5b962SSteven Rostedt		doprint "Assuming that this is a triple fault.\n";
922f1a5b962SSteven Rostedt		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
923f1a5b962SSteven Rostedt		last;
924f1a5b962SSteven Rostedt	    }
925f1a5b962SSteven Rostedt	}
926f1a5b962SSteven Rostedt
9272545eb61SSteven Rostedt	if ($line =~ /\n/) {
9282545eb61SSteven Rostedt	    $full_line = "";
9292545eb61SSteven Rostedt	}
9302d01b26aSSteven Rostedt
9312d01b26aSSteven Rostedt	if ($stop_test_after > 0 && !$booted && !$bug) {
9322d01b26aSSteven Rostedt	    if (time - $monitor_start > $stop_test_after) {
9334d62bf51SSteven Rostedt		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
9342d01b26aSSteven Rostedt		$done = 1;
9352d01b26aSSteven Rostedt	    }
9362d01b26aSSteven Rostedt	}
9372545eb61SSteven Rostedt    }
9382545eb61SSteven Rostedt
9397faafbd6SSteven Rostedt    close(DMESG);
9402545eb61SSteven Rostedt
9412545eb61SSteven Rostedt    if ($bug) {
9422b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
943576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
9442545eb61SSteven Rostedt    }
9455f9b6cedSSteven Rostedt
946a75fececSSteven Rostedt    if (!$booted) {
947a75fececSSteven Rostedt	return 0 if ($in_bisect);
948576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
949a75fececSSteven Rostedt    }
950a75fececSSteven Rostedt
9512b7d9b21SSteven Rostedt    return 1;
9522545eb61SSteven Rostedt}
9532545eb61SSteven Rostedt
9542545eb61SSteven Rostedtsub install {
9552545eb61SSteven Rostedt
956e48c5293SSteven Rostedt    run_scp "$outputdir/$build_target", "$target_image" or
9575c42fc5bSSteven Rostedt	dodie "failed to copy image";
9585f9b6cedSSteven Rostedt
9595f9b6cedSSteven Rostedt    my $install_mods = 0;
9605f9b6cedSSteven Rostedt
9615f9b6cedSSteven Rostedt    # should we process modules?
9625f9b6cedSSteven Rostedt    $install_mods = 0;
96351ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
9645f9b6cedSSteven Rostedt    while (<IN>) {
9655f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
9665f9b6cedSSteven Rostedt	    $install_mods = 1 if (defined($1));
9675f9b6cedSSteven Rostedt	    last;
9685f9b6cedSSteven Rostedt	}
9695f9b6cedSSteven Rostedt    }
9705f9b6cedSSteven Rostedt    close(IN);
9715f9b6cedSSteven Rostedt
9725f9b6cedSSteven Rostedt    if (!$install_mods) {
9735f9b6cedSSteven Rostedt	doprint "No modules needed\n";
9745f9b6cedSSteven Rostedt	return;
9752545eb61SSteven Rostedt    }
9762545eb61SSteven Rostedt
977a75fececSSteven Rostedt    run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
9785f9b6cedSSteven Rostedt	dodie "Failed to install modules";
9795f9b6cedSSteven Rostedt
9802545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
981a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
9822545eb61SSteven Rostedt
983e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
9845c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
9852545eb61SSteven Rostedt
9865c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
987a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
9885c42fc5bSSteven Rostedt	dodie "making tarball";
9895c42fc5bSSteven Rostedt
990e48c5293SSteven Rostedt    run_scp "$tmpdir/$modtar", "/tmp" or
9915c42fc5bSSteven Rostedt	dodie "failed to copy modules";
9925c42fc5bSSteven Rostedt
993a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
9945c42fc5bSSteven Rostedt
995e48c5293SSteven Rostedt    run_ssh "'(cd / && tar xf /tmp/$modtar)'" or
9965c42fc5bSSteven Rostedt	dodie "failed to tar modules";
9975c42fc5bSSteven Rostedt
998e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
9998b37ca8cSSteven Rostedt
10008b37ca8cSSteven Rostedt    return if (!defined($post_install));
10018b37ca8cSSteven Rostedt
1002e48c5293SSteven Rostedt    my $cp_post_install = $post_install;
1003ca6a21f8SSteven Rostedt    $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
1004e48c5293SSteven Rostedt    run_command "$cp_post_install" or
1005576f627cSSteven Rostedt	dodie "Failed to run post install";
10062545eb61SSteven Rostedt}
10072545eb61SSteven Rostedt
10086c5ee0beSSteven Rostedtsub check_buildlog {
10096c5ee0beSSteven Rostedt    my ($patch) = @_;
10106c5ee0beSSteven Rostedt
10116c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
10126c5ee0beSSteven Rostedt
10136c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
10146c5ee0beSSteven Rostedt	dodie "failed to show $patch";
10156c5ee0beSSteven Rostedt    while (<IN>) {
10166c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
10176c5ee0beSSteven Rostedt	    chomp $1;
10186c5ee0beSSteven Rostedt	    $files[$#files] = $1;
10196c5ee0beSSteven Rostedt	}
10206c5ee0beSSteven Rostedt    }
10216c5ee0beSSteven Rostedt    close(IN);
10226c5ee0beSSteven Rostedt
10236c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
10246c5ee0beSSteven Rostedt    while (<IN>) {
10256c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
10266c5ee0beSSteven Rostedt	    my $err = $1;
10276c5ee0beSSteven Rostedt	    foreach my $file (@files) {
1028a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
10296c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
10302b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
10316c5ee0beSSteven Rostedt		}
10326c5ee0beSSteven Rostedt	    }
10336c5ee0beSSteven Rostedt	}
10346c5ee0beSSteven Rostedt    }
10356c5ee0beSSteven Rostedt    close(IN);
10362b7d9b21SSteven Rostedt
10372b7d9b21SSteven Rostedt    return 1;
10386c5ee0beSSteven Rostedt}
10396c5ee0beSSteven Rostedt
1040612b9e9bSSteven Rostedtsub make_oldconfig {
1041612b9e9bSSteven Rostedt    my ($defconfig) = @_;
1042612b9e9bSSteven Rostedt
1043612b9e9bSSteven Rostedt    if (!run_command "$defconfig $make oldnoconfig") {
1044612b9e9bSSteven Rostedt	# Perhaps oldnoconfig doesn't exist in this version of the kernel
1045612b9e9bSSteven Rostedt	# try a yes '' | oldconfig
1046612b9e9bSSteven Rostedt	doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1047612b9e9bSSteven Rostedt	run_command "yes '' | $defconfig $make oldconfig" or
1048612b9e9bSSteven Rostedt	    dodie "failed make config oldconfig";
1049612b9e9bSSteven Rostedt    }
1050612b9e9bSSteven Rostedt}
1051612b9e9bSSteven Rostedt
10522545eb61SSteven Rostedtsub build {
10532545eb61SSteven Rostedt    my ($type) = @_;
10545c42fc5bSSteven Rostedt    my $defconfig = "";
10552545eb61SSteven Rostedt
10567faafbd6SSteven Rostedt    unlink $buildlog;
10577faafbd6SSteven Rostedt
105875c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
105951ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
106075c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
10615f9b6cedSSteven Rostedt
106275c3fda7SSteven Rostedt	$type = "oldconfig";
106375c3fda7SSteven Rostedt    }
106475c3fda7SSteven Rostedt
10655c42fc5bSSteven Rostedt    # old config can ask questions
10665c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
10679386c6abSSteven Rostedt	$type = "oldnoconfig";
106875c3fda7SSteven Rostedt
106975c3fda7SSteven Rostedt	# allow for empty configs
107051ad1dd1SSteven Rostedt	run_command "touch $output_config";
107175c3fda7SSteven Rostedt
107251ad1dd1SSteven Rostedt	run_command "mv $output_config $outputdir/config_temp" or
10735c42fc5bSSteven Rostedt	    dodie "moving .config";
10745c42fc5bSSteven Rostedt
10755f9b6cedSSteven Rostedt	if (!$noclean && !run_command "$make mrproper") {
10765c42fc5bSSteven Rostedt	    dodie "make mrproper";
10775c42fc5bSSteven Rostedt	}
10785c42fc5bSSteven Rostedt
107951ad1dd1SSteven Rostedt	run_command "mv $outputdir/config_temp $output_config" or
10805c42fc5bSSteven Rostedt	    dodie "moving config_temp";
10815c42fc5bSSteven Rostedt
10825c42fc5bSSteven Rostedt    } elsif (!$noclean) {
108351ad1dd1SSteven Rostedt	unlink "$output_config";
10845f9b6cedSSteven Rostedt	run_command "$make mrproper" or
10855c42fc5bSSteven Rostedt	    dodie "make mrproper";
10865c42fc5bSSteven Rostedt    }
10872545eb61SSteven Rostedt
10882545eb61SSteven Rostedt    # add something to distinguish this build
1089a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
1090a75fececSSteven Rostedt    print OUT "$localversion\n";
10912545eb61SSteven Rostedt    close(OUT);
10922545eb61SSteven Rostedt
10935f9b6cedSSteven Rostedt    if (defined($minconfig)) {
10945f9b6cedSSteven Rostedt	$defconfig = "KCONFIG_ALLCONFIG=$minconfig";
10952545eb61SSteven Rostedt    }
10962545eb61SSteven Rostedt
1097612b9e9bSSteven Rostedt    if ($type eq "oldnoconfig") {
1098612b9e9bSSteven Rostedt	make_oldconfig $defconfig;
1099612b9e9bSSteven Rostedt    } else {
11009386c6abSSteven Rostedt	run_command "$defconfig $make $type" or
11015c42fc5bSSteven Rostedt	    dodie "failed make config";
1102612b9e9bSSteven Rostedt    }
11032545eb61SSteven Rostedt
1104a75fececSSteven Rostedt    $redirect = "$buildlog";
1105a75fececSSteven Rostedt    if (!run_command "$make $build_options") {
11066c5ee0beSSteven Rostedt	undef $redirect;
11075f9b6cedSSteven Rostedt	# bisect may need this to pass
11082b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
11092b7d9b21SSteven Rostedt	fail "failed build" and return 0;
11102545eb61SSteven Rostedt    }
11116c5ee0beSSteven Rostedt    undef $redirect;
11125f9b6cedSSteven Rostedt
11132b7d9b21SSteven Rostedt    return 1;
11142545eb61SSteven Rostedt}
11152545eb61SSteven Rostedt
111675c3fda7SSteven Rostedtsub halt {
1117e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
1118576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
1119576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
1120576f627cSSteven Rostedt	    run_command "$power_off";
1121576f627cSSteven Rostedt	}
1122576f627cSSteven Rostedt    } else {
112375c3fda7SSteven Rostedt	# nope? the zap it!
1124a75fececSSteven Rostedt	run_command "$power_off";
112575c3fda7SSteven Rostedt    }
112675c3fda7SSteven Rostedt}
112775c3fda7SSteven Rostedt
11285f9b6cedSSteven Rostedtsub success {
11295f9b6cedSSteven Rostedt    my ($i) = @_;
11305f9b6cedSSteven Rostedt
1131e48c5293SSteven Rostedt    $successes++;
1132e48c5293SSteven Rostedt
11335f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
11345f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
11357a849cd9SSteven Rostedt    doprint     "KTEST RESULT: TEST $i SUCCESS!!!!         **\n";
11365f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
11375f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
11385f9b6cedSSteven Rostedt
1139576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1140a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
11415f9b6cedSSteven Rostedt	reboot;
11427faafbd6SSteven Rostedt	start_monitor;
1143a75fececSSteven Rostedt	wait_for_monitor $sleep_time;
11447faafbd6SSteven Rostedt	end_monitor;
11455f9b6cedSSteven Rostedt    }
11465f9b6cedSSteven Rostedt}
11475f9b6cedSSteven Rostedt
11485f9b6cedSSteven Rostedtsub get_version {
11495f9b6cedSSteven Rostedt    # get the release name
11505f9b6cedSSteven Rostedt    doprint "$make kernelrelease ... ";
11515f9b6cedSSteven Rostedt    $version = `$make kernelrelease | tail -1`;
11525f9b6cedSSteven Rostedt    chomp($version);
11535f9b6cedSSteven Rostedt    doprint "$version\n";
11545f9b6cedSSteven Rostedt}
11555f9b6cedSSteven Rostedt
1156c960bb9fSSteven Rostedtsub answer_bisect {
1157c960bb9fSSteven Rostedt    for (;;) {
1158c960bb9fSSteven Rostedt	doprint "Pass or fail? [p/f]";
1159c960bb9fSSteven Rostedt	my $ans = <STDIN>;
1160c960bb9fSSteven Rostedt	chomp $ans;
1161c960bb9fSSteven Rostedt	if ($ans eq "p" || $ans eq "P") {
1162c960bb9fSSteven Rostedt	    return 1;
1163c960bb9fSSteven Rostedt	} elsif ($ans eq "f" || $ans eq "F") {
1164c960bb9fSSteven Rostedt	    return 0;
1165c960bb9fSSteven Rostedt	} else {
1166c960bb9fSSteven Rostedt	    print "Please answer 'P' or 'F'\n";
1167c960bb9fSSteven Rostedt	}
1168c960bb9fSSteven Rostedt    }
1169c960bb9fSSteven Rostedt}
1170c960bb9fSSteven Rostedt
11715a391fbfSSteven Rostedtsub child_run_test {
11727faafbd6SSteven Rostedt    my $failed = 0;
11735a391fbfSSteven Rostedt
11747faafbd6SSteven Rostedt    # child should have no power
1175a75fececSSteven Rostedt    $reboot_on_error = 0;
1176a75fececSSteven Rostedt    $poweroff_on_error = 0;
1177a75fececSSteven Rostedt    $die_on_failure = 1;
11787faafbd6SSteven Rostedt
11797faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
11805a391fbfSSteven Rostedt    exit $failed;
11815a391fbfSSteven Rostedt}
11825a391fbfSSteven Rostedt
11835a391fbfSSteven Rostedtmy $child_done;
11845a391fbfSSteven Rostedt
11855a391fbfSSteven Rostedtsub child_finished {
11865a391fbfSSteven Rostedt    $child_done = 1;
11875a391fbfSSteven Rostedt}
11885a391fbfSSteven Rostedt
11895a391fbfSSteven Rostedtsub do_run_test {
11905a391fbfSSteven Rostedt    my $child_pid;
11915a391fbfSSteven Rostedt    my $child_exit;
11925a391fbfSSteven Rostedt    my $line;
11935a391fbfSSteven Rostedt    my $full_line;
11945a391fbfSSteven Rostedt    my $bug = 0;
11955a391fbfSSteven Rostedt
11967faafbd6SSteven Rostedt    wait_for_monitor 1;
11975a391fbfSSteven Rostedt
11987faafbd6SSteven Rostedt    doprint "run test $run_test\n";
11995a391fbfSSteven Rostedt
12005a391fbfSSteven Rostedt    $child_done = 0;
12015a391fbfSSteven Rostedt
12025a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
12035a391fbfSSteven Rostedt
12045a391fbfSSteven Rostedt    $child_pid = fork;
12055a391fbfSSteven Rostedt
12065a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
12075a391fbfSSteven Rostedt
12085a391fbfSSteven Rostedt    $full_line = "";
12095a391fbfSSteven Rostedt
12105a391fbfSSteven Rostedt    do {
12117faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
12125a391fbfSSteven Rostedt	if (defined($line)) {
12135a391fbfSSteven Rostedt
12145a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
12155a391fbfSSteven Rostedt	    $full_line .= $line;
12168ea0e063SSteven Rostedt	    doprint $line;
12175a391fbfSSteven Rostedt
12185a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
12195a391fbfSSteven Rostedt		$bug = 1;
12205a391fbfSSteven Rostedt	    }
12215a391fbfSSteven Rostedt
12225a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
12235a391fbfSSteven Rostedt		$bug = 1;
12245a391fbfSSteven Rostedt	    }
12255a391fbfSSteven Rostedt
12265a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
12275a391fbfSSteven Rostedt		$full_line = "";
12285a391fbfSSteven Rostedt	    }
12295a391fbfSSteven Rostedt	}
12305a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
12315a391fbfSSteven Rostedt
12325a391fbfSSteven Rostedt    if ($bug) {
12338ea0e063SSteven Rostedt	my $failure_start = time;
12348ea0e063SSteven Rostedt	my $now;
12358ea0e063SSteven Rostedt	do {
12368ea0e063SSteven Rostedt	    $line = wait_for_input($monitor_fp, 1);
12378ea0e063SSteven Rostedt	    if (defined($line)) {
12388ea0e063SSteven Rostedt		doprint $line;
12398ea0e063SSteven Rostedt	    }
12408ea0e063SSteven Rostedt	    $now = time;
12418ea0e063SSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
12428ea0e063SSteven Rostedt		last;
12438ea0e063SSteven Rostedt	    }
12448ea0e063SSteven Rostedt	} while (defined($line));
12458ea0e063SSteven Rostedt
12465a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
12475a391fbfSSteven Rostedt	# kill the child with extreme prejudice
12485a391fbfSSteven Rostedt	kill 9, $child_pid;
12495a391fbfSSteven Rostedt    }
12505a391fbfSSteven Rostedt
12515a391fbfSSteven Rostedt    waitpid $child_pid, 0;
12525a391fbfSSteven Rostedt    $child_exit = $?;
12535a391fbfSSteven Rostedt
12545a391fbfSSteven Rostedt    if ($bug || $child_exit) {
12552b7d9b21SSteven Rostedt	return 0 if $in_bisect;
12562b7d9b21SSteven Rostedt	fail "test failed" and return 0;
12575a391fbfSSteven Rostedt    }
12582b7d9b21SSteven Rostedt    return 1;
12595a391fbfSSteven Rostedt}
12605a391fbfSSteven Rostedt
1261a75fececSSteven Rostedtsub run_git_bisect {
1262a75fececSSteven Rostedt    my ($command) = @_;
1263a75fececSSteven Rostedt
1264a75fececSSteven Rostedt    doprint "$command ... ";
1265a75fececSSteven Rostedt
1266a75fececSSteven Rostedt    my $output = `$command 2>&1`;
1267a75fececSSteven Rostedt    my $ret = $?;
1268a75fececSSteven Rostedt
1269a75fececSSteven Rostedt    logit $output;
1270a75fececSSteven Rostedt
1271a75fececSSteven Rostedt    if ($ret) {
1272a75fececSSteven Rostedt	doprint "FAILED\n";
1273a75fececSSteven Rostedt	dodie "Failed to git bisect";
1274a75fececSSteven Rostedt    }
1275a75fececSSteven Rostedt
1276a75fececSSteven Rostedt    doprint "SUCCESS\n";
1277a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1278a75fececSSteven Rostedt	doprint "$1 [$2]\n";
1279a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1280a75fececSSteven Rostedt	$bisect_bad = $1;
1281a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
1282a75fececSSteven Rostedt	return 0;
1283a75fececSSteven Rostedt    } else {
1284a75fececSSteven Rostedt	# we already logged it, just print it now.
1285a75fececSSteven Rostedt	print $output;
1286a75fececSSteven Rostedt    }
1287a75fececSSteven Rostedt
1288a75fececSSteven Rostedt    return 1;
1289a75fececSSteven Rostedt}
1290a75fececSSteven Rostedt
1291c23dca7cSSteven Rostedtsub bisect_reboot {
1292c23dca7cSSteven Rostedt    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
1293c23dca7cSSteven Rostedt    reboot;
1294c23dca7cSSteven Rostedt    start_monitor;
1295c23dca7cSSteven Rostedt    wait_for_monitor $bisect_sleep_time;
1296c23dca7cSSteven Rostedt    end_monitor;
1297c23dca7cSSteven Rostedt}
1298c23dca7cSSteven Rostedt
1299c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip
13000a05c769SSteven Rostedtsub run_bisect_test {
13010a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
13025f9b6cedSSteven Rostedt
13032b7d9b21SSteven Rostedt    my $failed = 0;
13045f9b6cedSSteven Rostedt    my $result;
13055f9b6cedSSteven Rostedt    my $output;
13065f9b6cedSSteven Rostedt    my $ret;
13075f9b6cedSSteven Rostedt
13080a05c769SSteven Rostedt    $in_bisect = 1;
13090a05c769SSteven Rostedt
13100a05c769SSteven Rostedt    build $buildtype or $failed = 1;
13115f9b6cedSSteven Rostedt
13125f9b6cedSSteven Rostedt    if ($type ne "build") {
1313c23dca7cSSteven Rostedt	if ($failed && $bisect_skip) {
1314c23dca7cSSteven Rostedt	    $in_bisect = 0;
1315c23dca7cSSteven Rostedt	    return -1;
1316c23dca7cSSteven Rostedt	}
13177faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
13185f9b6cedSSteven Rostedt
13195f9b6cedSSteven Rostedt	# Now boot the box
13205f9b6cedSSteven Rostedt	get_grub_index;
13215f9b6cedSSteven Rostedt	get_version;
13225f9b6cedSSteven Rostedt	install;
13237faafbd6SSteven Rostedt
13247faafbd6SSteven Rostedt	start_monitor;
13252b7d9b21SSteven Rostedt	monitor or $failed = 1;
13265f9b6cedSSteven Rostedt
13275f9b6cedSSteven Rostedt	if ($type ne "boot") {
1328c23dca7cSSteven Rostedt	    if ($failed && $bisect_skip) {
1329c23dca7cSSteven Rostedt		end_monitor;
1330c23dca7cSSteven Rostedt		bisect_reboot;
1331c23dca7cSSteven Rostedt		$in_bisect = 0;
1332c23dca7cSSteven Rostedt		return -1;
1333c23dca7cSSteven Rostedt	    }
13347faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
13355a391fbfSSteven Rostedt
13362b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
13375f9b6cedSSteven Rostedt	}
13387faafbd6SSteven Rostedt	end_monitor;
13395f9b6cedSSteven Rostedt    }
13405f9b6cedSSteven Rostedt
13415f9b6cedSSteven Rostedt    if ($failed) {
13420a05c769SSteven Rostedt	$result = 0;
13435f9b6cedSSteven Rostedt    } else {
13440a05c769SSteven Rostedt	$result = 1;
13455f9b6cedSSteven Rostedt    }
13464025bc62SSteven Rostedt
13474025bc62SSteven Rostedt    # reboot the box to a kernel we can ssh to
13484025bc62SSteven Rostedt    if ($type ne "build") {
13494025bc62SSteven Rostedt	bisect_reboot;
13504025bc62SSteven Rostedt    }
13510a05c769SSteven Rostedt    $in_bisect = 0;
13520a05c769SSteven Rostedt
13530a05c769SSteven Rostedt    return $result;
13540a05c769SSteven Rostedt}
13550a05c769SSteven Rostedt
13560a05c769SSteven Rostedtsub run_bisect {
13570a05c769SSteven Rostedt    my ($type) = @_;
13580a05c769SSteven Rostedt    my $buildtype = "oldconfig";
13590a05c769SSteven Rostedt
13600a05c769SSteven Rostedt    # We should have a minconfig to use?
13610a05c769SSteven Rostedt    if (defined($minconfig)) {
13620a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
13630a05c769SSteven Rostedt    }
13640a05c769SSteven Rostedt
13650a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
13660a05c769SSteven Rostedt
1367c960bb9fSSteven Rostedt    if ($bisect_manual) {
1368c960bb9fSSteven Rostedt	$ret = answer_bisect;
1369c960bb9fSSteven Rostedt    }
13705f9b6cedSSteven Rostedt
1371d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
1372d6ce2a0bSSteven Rostedt    if ($reverse_bisect) {
13730a05c769SSteven Rostedt	$ret = !$ret;
1374d6ce2a0bSSteven Rostedt    }
1375d6ce2a0bSSteven Rostedt
1376c23dca7cSSteven Rostedt    if ($ret > 0) {
13770a05c769SSteven Rostedt	return "good";
1378c23dca7cSSteven Rostedt    } elsif ($ret == 0) {
13790a05c769SSteven Rostedt	return  "bad";
1380c23dca7cSSteven Rostedt    } elsif ($bisect_skip) {
1381c23dca7cSSteven Rostedt	doprint "HIT A BAD COMMIT ... SKIPPING\n";
1382c23dca7cSSteven Rostedt	return "skip";
13830a05c769SSteven Rostedt    }
13845f9b6cedSSteven Rostedt}
13855f9b6cedSSteven Rostedt
13865f9b6cedSSteven Rostedtsub bisect {
13875f9b6cedSSteven Rostedt    my ($i) = @_;
13885f9b6cedSSteven Rostedt
13895f9b6cedSSteven Rostedt    my $result;
13905f9b6cedSSteven Rostedt
13915f9b6cedSSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($opt{"BISECT_GOOD[$i]"}));
13925f9b6cedSSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($opt{"BISECT_BAD[$i]"}));
13935f9b6cedSSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($opt{"BISECT_TYPE[$i]"}));
13945f9b6cedSSteven Rostedt
13955f9b6cedSSteven Rostedt    my $good = $opt{"BISECT_GOOD[$i]"};
13965f9b6cedSSteven Rostedt    my $bad = $opt{"BISECT_BAD[$i]"};
13975f9b6cedSSteven Rostedt    my $type = $opt{"BISECT_TYPE[$i]"};
1398a75fececSSteven Rostedt    my $start = $opt{"BISECT_START[$i]"};
1399a75fececSSteven Rostedt    my $replay = $opt{"BISECT_REPLAY[$i]"};
14003410f6fdSSteven Rostedt    my $start_files = $opt{"BISECT_FILES[$i]"};
14013410f6fdSSteven Rostedt
14023410f6fdSSteven Rostedt    if (defined($start_files)) {
14033410f6fdSSteven Rostedt	$start_files = " -- " . $start_files;
14043410f6fdSSteven Rostedt    } else {
14053410f6fdSSteven Rostedt	$start_files = "";
14063410f6fdSSteven Rostedt    }
14075f9b6cedSSteven Rostedt
1408a57419b3SSteven Rostedt    # convert to true sha1's
1409a57419b3SSteven Rostedt    $good = get_sha1($good);
1410a57419b3SSteven Rostedt    $bad = get_sha1($bad);
1411a57419b3SSteven Rostedt
1412d6ce2a0bSSteven Rostedt    if (defined($opt{"BISECT_REVERSE[$i]"}) &&
1413d6ce2a0bSSteven Rostedt	$opt{"BISECT_REVERSE[$i]"} == 1) {
1414d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1415d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
1416d6ce2a0bSSteven Rostedt    } else {
1417d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
1418d6ce2a0bSSteven Rostedt    }
1419d6ce2a0bSSteven Rostedt
14205a391fbfSSteven Rostedt    # Can't have a test without having a test to run
14215a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
14225a391fbfSSteven Rostedt	$type = "boot";
14235a391fbfSSteven Rostedt    }
14245a391fbfSSteven Rostedt
1425a75fececSSteven Rostedt    my $check = $opt{"BISECT_CHECK[$i]"};
1426a75fececSSteven Rostedt    if (defined($check) && $check ne "0") {
1427a75fececSSteven Rostedt
1428a75fececSSteven Rostedt	# get current HEAD
1429a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
1430a75fececSSteven Rostedt
1431a75fececSSteven Rostedt	if ($check ne "good") {
1432a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
1433a75fececSSteven Rostedt	    run_command "git checkout $bad" or
1434a75fececSSteven Rostedt		die "Failed to checkout $bad";
1435a75fececSSteven Rostedt
1436a75fececSSteven Rostedt	    $result = run_bisect $type;
1437a75fececSSteven Rostedt
1438a75fececSSteven Rostedt	    if ($result ne "bad") {
1439a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
1440a75fececSSteven Rostedt	    }
1441a75fececSSteven Rostedt	}
1442a75fececSSteven Rostedt
1443a75fececSSteven Rostedt	if ($check ne "bad") {
1444a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
1445a75fececSSteven Rostedt	    run_command "git checkout $good" or
1446a75fececSSteven Rostedt		die "Failed to checkout $good";
1447a75fececSSteven Rostedt
1448a75fececSSteven Rostedt	    $result = run_bisect $type;
1449a75fececSSteven Rostedt
1450a75fececSSteven Rostedt	    if ($result ne "good") {
1451a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
1452a75fececSSteven Rostedt	    }
1453a75fececSSteven Rostedt	}
1454a75fececSSteven Rostedt
1455a75fececSSteven Rostedt	# checkout where we started
1456a75fececSSteven Rostedt	run_command "git checkout $head" or
1457a75fececSSteven Rostedt	    die "Failed to checkout $head";
1458a75fececSSteven Rostedt    }
1459a75fececSSteven Rostedt
14603410f6fdSSteven Rostedt    run_command "git bisect start$start_files" or
1461a75fececSSteven Rostedt	dodie "could not start bisect";
1462a75fececSSteven Rostedt
1463a75fececSSteven Rostedt    run_command "git bisect good $good" or
1464a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
1465a75fececSSteven Rostedt
1466a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
1467a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
1468a75fececSSteven Rostedt
1469a75fececSSteven Rostedt    if (defined($replay)) {
1470a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
1471a75fececSSteven Rostedt	    dodie "failed to run replay";
1472a75fececSSteven Rostedt    }
1473a75fececSSteven Rostedt
1474a75fececSSteven Rostedt    if (defined($start)) {
1475a75fececSSteven Rostedt	run_command "git checkout $start" or
1476a75fececSSteven Rostedt	    dodie "failed to checkout $start";
1477a75fececSSteven Rostedt    }
1478a75fececSSteven Rostedt
1479a75fececSSteven Rostedt    my $test;
14805f9b6cedSSteven Rostedt    do {
14815f9b6cedSSteven Rostedt	$result = run_bisect $type;
1482a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
1483a75fececSSteven Rostedt    } while ($test);
14845f9b6cedSSteven Rostedt
14855f9b6cedSSteven Rostedt    run_command "git bisect log" or
14865f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
14875f9b6cedSSteven Rostedt
14885f9b6cedSSteven Rostedt    run_command "git bisect reset" or
14895f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
14905f9b6cedSSteven Rostedt
14915f9b6cedSSteven Rostedt    doprint "Bad commit was [$bisect_bad]\n";
14925f9b6cedSSteven Rostedt
14930a05c769SSteven Rostedt    success $i;
14940a05c769SSteven Rostedt}
14950a05c769SSteven Rostedt
14960a05c769SSteven Rostedtmy %config_ignore;
14970a05c769SSteven Rostedtmy %config_set;
14980a05c769SSteven Rostedt
14990a05c769SSteven Rostedtmy %config_list;
15000a05c769SSteven Rostedtmy %null_config;
15010a05c769SSteven Rostedt
15020a05c769SSteven Rostedtmy %dependency;
15030a05c769SSteven Rostedt
15040a05c769SSteven Rostedtsub process_config_ignore {
15050a05c769SSteven Rostedt    my ($config) = @_;
15060a05c769SSteven Rostedt
15070a05c769SSteven Rostedt    open (IN, $config)
15080a05c769SSteven Rostedt	or dodie "Failed to read $config";
15090a05c769SSteven Rostedt
15100a05c769SSteven Rostedt    while (<IN>) {
15119bf71749SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
15120a05c769SSteven Rostedt	    $config_ignore{$2} = $1;
15130a05c769SSteven Rostedt	}
15140a05c769SSteven Rostedt    }
15150a05c769SSteven Rostedt
15160a05c769SSteven Rostedt    close(IN);
15170a05c769SSteven Rostedt}
15180a05c769SSteven Rostedt
15190a05c769SSteven Rostedtsub read_current_config {
15200a05c769SSteven Rostedt    my ($config_ref) = @_;
15210a05c769SSteven Rostedt
15220a05c769SSteven Rostedt    %{$config_ref} = ();
15230a05c769SSteven Rostedt    undef %{$config_ref};
15240a05c769SSteven Rostedt
15250a05c769SSteven Rostedt    my @key = keys %{$config_ref};
15260a05c769SSteven Rostedt    if ($#key >= 0) {
15270a05c769SSteven Rostedt	print "did not delete!\n";
15280a05c769SSteven Rostedt	exit;
15290a05c769SSteven Rostedt    }
15300a05c769SSteven Rostedt    open (IN, "$output_config");
15310a05c769SSteven Rostedt
15320a05c769SSteven Rostedt    while (<IN>) {
15330a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
15340a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
15350a05c769SSteven Rostedt	}
15360a05c769SSteven Rostedt    }
15370a05c769SSteven Rostedt    close(IN);
15380a05c769SSteven Rostedt}
15390a05c769SSteven Rostedt
15400a05c769SSteven Rostedtsub get_dependencies {
15410a05c769SSteven Rostedt    my ($config) = @_;
15420a05c769SSteven Rostedt
15430a05c769SSteven Rostedt    my $arr = $dependency{$config};
15440a05c769SSteven Rostedt    if (!defined($arr)) {
15450a05c769SSteven Rostedt	return ();
15460a05c769SSteven Rostedt    }
15470a05c769SSteven Rostedt
15480a05c769SSteven Rostedt    my @deps = @{$arr};
15490a05c769SSteven Rostedt
15500a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
15510a05c769SSteven Rostedt	print "ADD DEP $dep\n";
15520a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
15530a05c769SSteven Rostedt    }
15540a05c769SSteven Rostedt
15550a05c769SSteven Rostedt    return @deps;
15560a05c769SSteven Rostedt}
15570a05c769SSteven Rostedt
15580a05c769SSteven Rostedtsub create_config {
15590a05c769SSteven Rostedt    my @configs = @_;
15600a05c769SSteven Rostedt
15610a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
15620a05c769SSteven Rostedt
15630a05c769SSteven Rostedt    foreach my $config (@configs) {
15640a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
15650a05c769SSteven Rostedt	my @deps = get_dependencies $config;
15660a05c769SSteven Rostedt	foreach my $dep (@deps) {
15670a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
15680a05c769SSteven Rostedt	}
15690a05c769SSteven Rostedt    }
15700a05c769SSteven Rostedt
15710a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
15720a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
15730a05c769SSteven Rostedt    }
15740a05c769SSteven Rostedt    close(OUT);
15750a05c769SSteven Rostedt
15760a05c769SSteven Rostedt#    exit;
1577612b9e9bSSteven Rostedt    make_oldconfig "";
15780a05c769SSteven Rostedt}
15790a05c769SSteven Rostedt
15800a05c769SSteven Rostedtsub compare_configs {
15810a05c769SSteven Rostedt    my (%a, %b) = @_;
15820a05c769SSteven Rostedt
15830a05c769SSteven Rostedt    foreach my $item (keys %a) {
15840a05c769SSteven Rostedt	if (!defined($b{$item})) {
15850a05c769SSteven Rostedt	    print "diff $item\n";
15860a05c769SSteven Rostedt	    return 1;
15870a05c769SSteven Rostedt	}
15880a05c769SSteven Rostedt	delete $b{$item};
15890a05c769SSteven Rostedt    }
15900a05c769SSteven Rostedt
15910a05c769SSteven Rostedt    my @keys = keys %b;
15920a05c769SSteven Rostedt    if ($#keys) {
15930a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
15940a05c769SSteven Rostedt    }
15950a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
15960a05c769SSteven Rostedt
15970a05c769SSteven Rostedt    return 0;
15980a05c769SSteven Rostedt}
15990a05c769SSteven Rostedt
16000a05c769SSteven Rostedtsub run_config_bisect_test {
16010a05c769SSteven Rostedt    my ($type) = @_;
16020a05c769SSteven Rostedt
16030a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
16040a05c769SSteven Rostedt}
16050a05c769SSteven Rostedt
16060a05c769SSteven Rostedtsub process_passed {
16070a05c769SSteven Rostedt    my (%configs) = @_;
16080a05c769SSteven Rostedt
16090a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
16100a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
16110a05c769SSteven Rostedt    # Add them to the min options.
16120a05c769SSteven Rostedt    foreach my $config (keys %configs) {
16130a05c769SSteven Rostedt	if (defined($config_list{$config})) {
16140a05c769SSteven Rostedt	    doprint " removing $config\n";
16150a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
16160a05c769SSteven Rostedt	    delete $config_list{$config};
16170a05c769SSteven Rostedt	}
16180a05c769SSteven Rostedt    }
1619f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
1620f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
16210a05c769SSteven Rostedt}
16220a05c769SSteven Rostedt
16230a05c769SSteven Rostedtsub process_failed {
16240a05c769SSteven Rostedt    my ($config) = @_;
16250a05c769SSteven Rostedt
16260a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
16270a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
16280a05c769SSteven Rostedt    doprint "***************************************\n\n";
16290a05c769SSteven Rostedt}
16300a05c769SSteven Rostedt
16310a05c769SSteven Rostedtsub run_config_bisect {
16320a05c769SSteven Rostedt
16330a05c769SSteven Rostedt    my @start_list = keys %config_list;
16340a05c769SSteven Rostedt
16350a05c769SSteven Rostedt    if ($#start_list < 0) {
16360a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
16370a05c769SSteven Rostedt	return -1;
16380a05c769SSteven Rostedt    }
16390a05c769SSteven Rostedt
16400a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
16410a05c769SSteven Rostedt    my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
16420a05c769SSteven Rostedt    my $ret;
16430a05c769SSteven Rostedt    my %current_config;
16440a05c769SSteven Rostedt
16450a05c769SSteven Rostedt    my $count = $#start_list + 1;
16460a05c769SSteven Rostedt    doprint "  $count configs to test\n";
16470a05c769SSteven Rostedt
16480a05c769SSteven Rostedt    my $half = int($#start_list / 2);
16490a05c769SSteven Rostedt
16500a05c769SSteven Rostedt    do {
16510a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
16520a05c769SSteven Rostedt
16530a05c769SSteven Rostedt	create_config @tophalf;
16540a05c769SSteven Rostedt	read_current_config \%current_config;
16550a05c769SSteven Rostedt
16560a05c769SSteven Rostedt	$count = $#tophalf + 1;
16570a05c769SSteven Rostedt	doprint "Testing $count configs\n";
16580a05c769SSteven Rostedt	my $found = 0;
16590a05c769SSteven Rostedt	# make sure we test something
16600a05c769SSteven Rostedt	foreach my $config (@tophalf) {
16610a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
16620a05c769SSteven Rostedt		logit " $config\n";
16630a05c769SSteven Rostedt		$found = 1;
16640a05c769SSteven Rostedt	    }
16650a05c769SSteven Rostedt	}
16660a05c769SSteven Rostedt	if (!$found) {
16670a05c769SSteven Rostedt	    # try the other half
16680a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
16694c8cc55bSSteven Rostedt	    @tophalf = @start_list[$half + 1 .. $#start_list];
16700a05c769SSteven Rostedt	    create_config @tophalf;
16710a05c769SSteven Rostedt	    read_current_config \%current_config;
16720a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
16730a05c769SSteven Rostedt		if (defined($current_config{$config})) {
16740a05c769SSteven Rostedt		    logit " $config\n";
16750a05c769SSteven Rostedt		    $found = 1;
16760a05c769SSteven Rostedt		}
16770a05c769SSteven Rostedt	    }
16780a05c769SSteven Rostedt	    if (!$found) {
16790a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
16800a05c769SSteven Rostedt		foreach my $config (@start_list) {
16810a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
16820a05c769SSteven Rostedt		}
16830a05c769SSteven Rostedt		return -1;
16840a05c769SSteven Rostedt	    }
16850a05c769SSteven Rostedt	    $count = $#tophalf + 1;
16860a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
16870a05c769SSteven Rostedt	}
16880a05c769SSteven Rostedt
16890a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
1690c960bb9fSSteven Rostedt	if ($bisect_manual) {
1691c960bb9fSSteven Rostedt	    $ret = answer_bisect;
1692c960bb9fSSteven Rostedt	}
16930a05c769SSteven Rostedt	if ($ret) {
16940a05c769SSteven Rostedt	    process_passed %current_config;
16950a05c769SSteven Rostedt	    return 0;
16960a05c769SSteven Rostedt	}
16970a05c769SSteven Rostedt
16980a05c769SSteven Rostedt	doprint "This config had a failure.\n";
16990a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
1700f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
1701f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
17020a05c769SSteven Rostedt
17030a05c769SSteven Rostedt	# A config exists in this group that was bad.
17040a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
17050a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
17060a05c769SSteven Rostedt		doprint " removing $config\n";
17070a05c769SSteven Rostedt		delete $config_list{$config};
17080a05c769SSteven Rostedt	    }
17090a05c769SSteven Rostedt	}
17100a05c769SSteven Rostedt
17110a05c769SSteven Rostedt	@start_list = @tophalf;
17120a05c769SSteven Rostedt
17130a05c769SSteven Rostedt	if ($#start_list == 0) {
17140a05c769SSteven Rostedt	    process_failed $start_list[0];
17150a05c769SSteven Rostedt	    return 1;
17160a05c769SSteven Rostedt	}
17170a05c769SSteven Rostedt
17180a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
17190a05c769SSteven Rostedt	# they are good.
17200a05c769SSteven Rostedt	$half = int($#start_list / 2);
17214c8cc55bSSteven Rostedt    } while ($#start_list > 0);
17220a05c769SSteven Rostedt
1723c960bb9fSSteven Rostedt    # we found a single config, try it again unless we are running manually
1724c960bb9fSSteven Rostedt
1725c960bb9fSSteven Rostedt    if ($bisect_manual) {
1726c960bb9fSSteven Rostedt	process_failed $start_list[0];
1727c960bb9fSSteven Rostedt	return 1;
1728c960bb9fSSteven Rostedt    }
1729c960bb9fSSteven Rostedt
17300a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
17310a05c769SSteven Rostedt
17320a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
17330a05c769SSteven Rostedt    if ($ret) {
17340a05c769SSteven Rostedt	process_passed %current_config;
17350a05c769SSteven Rostedt	return 0;
17360a05c769SSteven Rostedt    }
17370a05c769SSteven Rostedt
17380a05c769SSteven Rostedt    process_failed $start_list[0];
17390a05c769SSteven Rostedt    return 1;
17400a05c769SSteven Rostedt}
17410a05c769SSteven Rostedt
17420a05c769SSteven Rostedtsub config_bisect {
17430a05c769SSteven Rostedt    my ($i) = @_;
17440a05c769SSteven Rostedt
17450a05c769SSteven Rostedt    my $start_config = $opt{"CONFIG_BISECT[$i]"};
17460a05c769SSteven Rostedt
17470a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
17480a05c769SSteven Rostedt
1749*30f75da5SSteven Rostedt    if (defined($config_bisect_good)) {
1750*30f75da5SSteven Rostedt	process_config_ignore $config_bisect_good;
1751*30f75da5SSteven Rostedt    }
1752*30f75da5SSteven Rostedt
17530a05c769SSteven Rostedt    # Make the file with the bad config and the min config
17540a05c769SSteven Rostedt    if (defined($minconfig)) {
17550a05c769SSteven Rostedt	# read the min config for things to ignore
17560a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
17570a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
17580a05c769SSteven Rostedt    } else {
17590a05c769SSteven Rostedt	unlink $tmpconfig;
17600a05c769SSteven Rostedt    }
17610a05c769SSteven Rostedt
17620a05c769SSteven Rostedt    # Add other configs
17630a05c769SSteven Rostedt    if (defined($addconfig)) {
17640a05c769SSteven Rostedt	run_command "cat $addconfig >> $tmpconfig" or
17650a05c769SSteven Rostedt	    dodie "failed to append $addconfig";
17660a05c769SSteven Rostedt    }
17670a05c769SSteven Rostedt
17680a05c769SSteven Rostedt    my $defconfig = "";
17690a05c769SSteven Rostedt    if (-f $tmpconfig) {
17700a05c769SSteven Rostedt	$defconfig = "KCONFIG_ALLCONFIG=$tmpconfig";
17710a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
17720a05c769SSteven Rostedt    }
17730a05c769SSteven Rostedt
17740a05c769SSteven Rostedt    # now process the start config
17750a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
17760a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
17770a05c769SSteven Rostedt
17780a05c769SSteven Rostedt    # read directly what we want to check
17790a05c769SSteven Rostedt    my %config_check;
17800a05c769SSteven Rostedt    open (IN, $output_config)
17810a05c769SSteven Rostedt	or dodie "faied to open $output_config";
17820a05c769SSteven Rostedt
17830a05c769SSteven Rostedt    while (<IN>) {
17840a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
17850a05c769SSteven Rostedt	    $config_check{$2} = $1;
17860a05c769SSteven Rostedt	}
17870a05c769SSteven Rostedt    }
17880a05c769SSteven Rostedt    close(IN);
17890a05c769SSteven Rostedt
17900a05c769SSteven Rostedt    # Now run oldconfig with the minconfig (and addconfigs)
1791612b9e9bSSteven Rostedt    make_oldconfig $defconfig;
17920a05c769SSteven Rostedt
17930a05c769SSteven Rostedt    # check to see what we lost (or gained)
17940a05c769SSteven Rostedt    open (IN, $output_config)
17950a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
17960a05c769SSteven Rostedt
17970a05c769SSteven Rostedt    my %removed_configs;
17980a05c769SSteven Rostedt    my %added_configs;
17990a05c769SSteven Rostedt
18000a05c769SSteven Rostedt    while (<IN>) {
18010a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
18020a05c769SSteven Rostedt	    # save off all options
18030a05c769SSteven Rostedt	    $config_set{$2} = $1;
18040a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
18050a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
18060a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
18070a05c769SSteven Rostedt		} else {
18080a05c769SSteven Rostedt		    $config_list{$2} = $1;
18090a05c769SSteven Rostedt		}
18100a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
18110a05c769SSteven Rostedt		$added_configs{$2} = $1;
18120a05c769SSteven Rostedt		$config_list{$2} = $1;
18130a05c769SSteven Rostedt	    }
18140a05c769SSteven Rostedt	}
18150a05c769SSteven Rostedt    }
18160a05c769SSteven Rostedt    close(IN);
18170a05c769SSteven Rostedt
18180a05c769SSteven Rostedt    my @confs = keys %removed_configs;
18190a05c769SSteven Rostedt    if ($#confs >= 0) {
18200a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
18210a05c769SSteven Rostedt	foreach my $config (@confs) {
18220a05c769SSteven Rostedt	    doprint " $config\n";
18230a05c769SSteven Rostedt	}
18240a05c769SSteven Rostedt    }
18250a05c769SSteven Rostedt    @confs = keys %added_configs;
18260a05c769SSteven Rostedt    if ($#confs >= 0) {
18270a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
18280a05c769SSteven Rostedt	foreach my $config (@confs) {
18290a05c769SSteven Rostedt	    doprint " $config\n";
18300a05c769SSteven Rostedt	}
18310a05c769SSteven Rostedt    }
18320a05c769SSteven Rostedt
18330a05c769SSteven Rostedt    my %config_test;
18340a05c769SSteven Rostedt    my $once = 0;
18350a05c769SSteven Rostedt
18360a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
18370a05c769SSteven Rostedt    # that the config we autocreate has everything we need
18380a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
18390a05c769SSteven Rostedt    # may not be able to create a new config.
18400a05c769SSteven Rostedt    # Here we create a config with everything set.
18410a05c769SSteven Rostedt    create_config (keys %config_list);
18420a05c769SSteven Rostedt    read_current_config \%config_test;
18430a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
18440a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
18450a05c769SSteven Rostedt	    if (!$once) {
18460a05c769SSteven Rostedt		$once = 1;
18470a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
18480a05c769SSteven Rostedt	    }
18490a05c769SSteven Rostedt	    doprint "  $config\n";
18500a05c769SSteven Rostedt	    delete $config_list{$config};
18510a05c769SSteven Rostedt	}
18520a05c769SSteven Rostedt    }
18530a05c769SSteven Rostedt    my $ret;
18540a05c769SSteven Rostedt    do {
18550a05c769SSteven Rostedt	$ret = run_config_bisect;
18560a05c769SSteven Rostedt    } while (!$ret);
18570a05c769SSteven Rostedt
18580a05c769SSteven Rostedt    return $ret if ($ret < 0);
18595f9b6cedSSteven Rostedt
18605f9b6cedSSteven Rostedt    success $i;
18615f9b6cedSSteven Rostedt}
18625f9b6cedSSteven Rostedt
186327d934b2SSteven Rostedtsub patchcheck_reboot {
186427d934b2SSteven Rostedt    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
186527d934b2SSteven Rostedt    reboot;
186627d934b2SSteven Rostedt    start_monitor;
186727d934b2SSteven Rostedt    wait_for_monitor $patchcheck_sleep_time;
186827d934b2SSteven Rostedt    end_monitor;
186927d934b2SSteven Rostedt}
187027d934b2SSteven Rostedt
18716c5ee0beSSteven Rostedtsub patchcheck {
18726c5ee0beSSteven Rostedt    my ($i) = @_;
18736c5ee0beSSteven Rostedt
18746c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
18756c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_START[$i]"}));
18766c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
18776c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
18786c5ee0beSSteven Rostedt
18796c5ee0beSSteven Rostedt    my $start = $opt{"PATCHCHECK_START[$i]"};
18806c5ee0beSSteven Rostedt
18816c5ee0beSSteven Rostedt    my $end = "HEAD";
18826c5ee0beSSteven Rostedt    if (defined($opt{"PATCHCHECK_END[$i]"})) {
18836c5ee0beSSteven Rostedt	$end = $opt{"PATCHCHECK_END[$i]"};
18846c5ee0beSSteven Rostedt    }
18856c5ee0beSSteven Rostedt
1886a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
1887a57419b3SSteven Rostedt    $start = get_sha1($start);
1888a57419b3SSteven Rostedt    $end = get_sha1($end);
1889a57419b3SSteven Rostedt
18906c5ee0beSSteven Rostedt    my $type = $opt{"PATCHCHECK_TYPE[$i]"};
18916c5ee0beSSteven Rostedt
18926c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
18936c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
18946c5ee0beSSteven Rostedt	$type = "boot";
18956c5ee0beSSteven Rostedt    }
18966c5ee0beSSteven Rostedt
18976c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
18986c5ee0beSSteven Rostedt	dodie "could not get git list";
18996c5ee0beSSteven Rostedt
19006c5ee0beSSteven Rostedt    my @list;
19016c5ee0beSSteven Rostedt
19026c5ee0beSSteven Rostedt    while (<IN>) {
19036c5ee0beSSteven Rostedt	chomp;
19046c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
19056c5ee0beSSteven Rostedt	last if (/^$start/);
19066c5ee0beSSteven Rostedt    }
19076c5ee0beSSteven Rostedt    close(IN);
19086c5ee0beSSteven Rostedt
19096c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
19102b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
19116c5ee0beSSteven Rostedt    }
19126c5ee0beSSteven Rostedt
19136c5ee0beSSteven Rostedt    # go backwards in the list
19146c5ee0beSSteven Rostedt    @list = reverse @list;
19156c5ee0beSSteven Rostedt
19166c5ee0beSSteven Rostedt    my $save_clean = $noclean;
19176c5ee0beSSteven Rostedt
19186c5ee0beSSteven Rostedt    $in_patchcheck = 1;
19196c5ee0beSSteven Rostedt    foreach my $item (@list) {
19206c5ee0beSSteven Rostedt	my $sha1 = $item;
19216c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
19226c5ee0beSSteven Rostedt
19236c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
19246c5ee0beSSteven Rostedt
19256c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
19266c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
19276c5ee0beSSteven Rostedt
19286c5ee0beSSteven Rostedt	# only clean on the first and last patch
19296c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
19306c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
19316c5ee0beSSteven Rostedt	    $noclean = $save_clean;
19326c5ee0beSSteven Rostedt	} else {
19336c5ee0beSSteven Rostedt	    $noclean = 1;
19346c5ee0beSSteven Rostedt	}
19356c5ee0beSSteven Rostedt
19366c5ee0beSSteven Rostedt	if (defined($minconfig)) {
19372b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
19386c5ee0beSSteven Rostedt	} else {
19396c5ee0beSSteven Rostedt	    # ?? no config to use?
19402b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
19416c5ee0beSSteven Rostedt	}
19426c5ee0beSSteven Rostedt
19432b7d9b21SSteven Rostedt	check_buildlog $sha1 or return 0;
19446c5ee0beSSteven Rostedt
19456c5ee0beSSteven Rostedt	next if ($type eq "build");
19466c5ee0beSSteven Rostedt
19476c5ee0beSSteven Rostedt	get_grub_index;
19486c5ee0beSSteven Rostedt	get_version;
19496c5ee0beSSteven Rostedt	install;
19506c5ee0beSSteven Rostedt
19517faafbd6SSteven Rostedt	my $failed = 0;
19527faafbd6SSteven Rostedt
19537faafbd6SSteven Rostedt	start_monitor;
19547faafbd6SSteven Rostedt	monitor or $failed = 1;
19557faafbd6SSteven Rostedt
19567faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
19577faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
19587faafbd6SSteven Rostedt	}
19597faafbd6SSteven Rostedt	end_monitor;
19607faafbd6SSteven Rostedt	return 0 if ($failed);
19617faafbd6SSteven Rostedt
196227d934b2SSteven Rostedt	patchcheck_reboot;
196327d934b2SSteven Rostedt
19646c5ee0beSSteven Rostedt    }
19656c5ee0beSSteven Rostedt    $in_patchcheck = 0;
19666c5ee0beSSteven Rostedt    success $i;
19672b7d9b21SSteven Rostedt
19682b7d9b21SSteven Rostedt    return 1;
19696c5ee0beSSteven Rostedt}
19706c5ee0beSSteven Rostedt
19718d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
19722545eb61SSteven Rostedt
19738d1491baSSteven Rostedtif ($#ARGV == 0) {
19748d1491baSSteven Rostedt    $ktest_config = $ARGV[0];
19758d1491baSSteven Rostedt    if (! -f $ktest_config) {
19768d1491baSSteven Rostedt	print "$ktest_config does not exist.\n";
19778d1491baSSteven Rostedt	my $ans;
19788d1491baSSteven Rostedt        for (;;) {
19798d1491baSSteven Rostedt	    print "Create it? [Y/n] ";
19808d1491baSSteven Rostedt	    $ans = <STDIN>;
19818d1491baSSteven Rostedt	    chomp $ans;
19828d1491baSSteven Rostedt	    if ($ans =~ /^\s*$/) {
19838d1491baSSteven Rostedt		$ans = "y";
19848d1491baSSteven Rostedt	    }
19858d1491baSSteven Rostedt	    last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
19868d1491baSSteven Rostedt	    print "Please answer either 'y' or 'n'.\n";
19878d1491baSSteven Rostedt	}
19888d1491baSSteven Rostedt	if ($ans !~ /^y$/i) {
19898d1491baSSteven Rostedt	    exit 0;
19908d1491baSSteven Rostedt	}
19918d1491baSSteven Rostedt    }
19928d1491baSSteven Rostedt} else {
19938d1491baSSteven Rostedt    $ktest_config = "ktest.conf";
19948d1491baSSteven Rostedt}
19958d1491baSSteven Rostedt
19968d1491baSSteven Rostedtif (! -f $ktest_config) {
19978d1491baSSteven Rostedt    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
19988d1491baSSteven Rostedt    print OUT << "EOF"
19998d1491baSSteven Rostedt# Generated by ktest.pl
20008d1491baSSteven Rostedt#
20018d1491baSSteven Rostedt# Define each test with TEST_START
20028d1491baSSteven Rostedt# The config options below it will override the defaults
20038d1491baSSteven RostedtTEST_START
20048d1491baSSteven Rostedt
20058d1491baSSteven RostedtDEFAULTS
20068d1491baSSteven RostedtEOF
20078d1491baSSteven Rostedt;
20088d1491baSSteven Rostedt    close(OUT);
20098d1491baSSteven Rostedt}
20108d1491baSSteven Rostedtread_config $ktest_config;
20118d1491baSSteven Rostedt
20128d1491baSSteven Rostedt# Append any configs entered in manually to the config file.
20138d1491baSSteven Rostedtmy @new_configs = keys %entered_configs;
20148d1491baSSteven Rostedtif ($#new_configs >= 0) {
20158d1491baSSteven Rostedt    print "\nAppending entered in configs to $ktest_config\n";
20168d1491baSSteven Rostedt    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
20178d1491baSSteven Rostedt    foreach my $config (@new_configs) {
20188d1491baSSteven Rostedt	print OUT "$config = $entered_configs{$config}\n";
20198d1491baSSteven Rostedt	$opt{$config} = $entered_configs{$config};
20208d1491baSSteven Rostedt    }
20218d1491baSSteven Rostedt}
20222545eb61SSteven Rostedt
20232b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
20242b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
20252b7d9b21SSteven Rostedt}
20262545eb61SSteven Rostedt
20272b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
20282b7d9b21SSteven Rostedt
2029a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
2030a57419b3SSteven Rostedt
2031a57419b3SSteven Rostedt    if (!$i) {
2032a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
2033a57419b3SSteven Rostedt    } else {
2034a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
2035a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
2036a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
2037a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
2038a57419b3SSteven Rostedt	}
2039a57419b3SSteven Rostedt	doprint "\n";
2040a57419b3SSteven Rostedt    }
2041a57419b3SSteven Rostedt
20422b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
2043a57419b3SSteven Rostedt
2044a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
2045a57419b3SSteven Rostedt	    next if ($i != $1);
2046a57419b3SSteven Rostedt	} else {
2047a57419b3SSteven Rostedt	    next if ($i);
2048a57419b3SSteven Rostedt	}
2049a57419b3SSteven Rostedt
20502b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
20512b7d9b21SSteven Rostedt    }
2052a57419b3SSteven Rostedt}
20532545eb61SSteven Rostedt
20542a62512bSSteven Rostedtsub __set_test_option {
20555a391fbfSSteven Rostedt    my ($name, $i) = @_;
20565a391fbfSSteven Rostedt
20575a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
20585a391fbfSSteven Rostedt
20595a391fbfSSteven Rostedt    if (defined($opt{$option})) {
20605a391fbfSSteven Rostedt	return $opt{$option};
20615a391fbfSSteven Rostedt    }
20625a391fbfSSteven Rostedt
2063a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
2064a57419b3SSteven Rostedt	if ($i >= $test &&
2065a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
2066a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
2067a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
2068a57419b3SSteven Rostedt		return $opt{$option};
2069a57419b3SSteven Rostedt	    }
2070a57419b3SSteven Rostedt	}
2071a57419b3SSteven Rostedt    }
2072a57419b3SSteven Rostedt
20735a391fbfSSteven Rostedt    if (defined($opt{$name})) {
20745a391fbfSSteven Rostedt	return $opt{$name};
20755a391fbfSSteven Rostedt    }
20765a391fbfSSteven Rostedt
20775a391fbfSSteven Rostedt    return undef;
20785a391fbfSSteven Rostedt}
20795a391fbfSSteven Rostedt
20802a62512bSSteven Rostedtsub eval_option {
20812a62512bSSteven Rostedt    my ($option, $i) = @_;
20822a62512bSSteven Rostedt
20832a62512bSSteven Rostedt    # Add space to evaluate the character before $
20842a62512bSSteven Rostedt    $option = " $option";
20852a62512bSSteven Rostedt    my $retval = "";
20862a62512bSSteven Rostedt
20872a62512bSSteven Rostedt    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
20882a62512bSSteven Rostedt	my $start = $1;
20892a62512bSSteven Rostedt	my $var = $2;
20902a62512bSSteven Rostedt	my $end = $3;
20912a62512bSSteven Rostedt
20922a62512bSSteven Rostedt	# Append beginning of line
20932a62512bSSteven Rostedt	$retval = "$retval$start";
20942a62512bSSteven Rostedt
20952a62512bSSteven Rostedt	# If the iteration option OPT[$i] exists, then use that.
20962a62512bSSteven Rostedt	# otherwise see if the default OPT (without [$i]) exists.
20972a62512bSSteven Rostedt
20982a62512bSSteven Rostedt	my $o = "$var\[$i\]";
20992a62512bSSteven Rostedt
21002a62512bSSteven Rostedt	if (defined($opt{$o})) {
21012a62512bSSteven Rostedt	    $o = $opt{$o};
21022a62512bSSteven Rostedt	    $retval = "$retval$o";
21032a62512bSSteven Rostedt	} elsif (defined($opt{$var})) {
21042a62512bSSteven Rostedt	    $o = $opt{$var};
21052a62512bSSteven Rostedt	    $retval = "$retval$o";
21062a62512bSSteven Rostedt	} else {
21072a62512bSSteven Rostedt	    $retval = "$retval\$\{$var\}";
21082a62512bSSteven Rostedt	}
21092a62512bSSteven Rostedt
21102a62512bSSteven Rostedt	$option = $end;
21112a62512bSSteven Rostedt    }
21122a62512bSSteven Rostedt
21132a62512bSSteven Rostedt    $retval = "$retval$option";
21142a62512bSSteven Rostedt
21152a62512bSSteven Rostedt    $retval =~ s/^ //;
21162a62512bSSteven Rostedt
21172a62512bSSteven Rostedt    return $retval;
21182a62512bSSteven Rostedt}
21192a62512bSSteven Rostedt
21202a62512bSSteven Rostedtsub set_test_option {
21212a62512bSSteven Rostedt    my ($name, $i) = @_;
21222a62512bSSteven Rostedt
21232a62512bSSteven Rostedt    my $option = __set_test_option($name, $i);
21242a62512bSSteven Rostedt    return $option if (!defined($option));
21252a62512bSSteven Rostedt
21262a62512bSSteven Rostedt    my $prev = "";
21272a62512bSSteven Rostedt
21282a62512bSSteven Rostedt    # Since an option can evaluate to another option,
21292a62512bSSteven Rostedt    # keep iterating until we do not evaluate any more
21302a62512bSSteven Rostedt    # options.
21312a62512bSSteven Rostedt    my $r = 0;
21322a62512bSSteven Rostedt    while ($prev ne $option) {
21332a62512bSSteven Rostedt	# Check for recursive evaluations.
21342a62512bSSteven Rostedt	# 100 deep should be more than enough.
21352a62512bSSteven Rostedt	if ($r++ > 100) {
21362a62512bSSteven Rostedt	    die "Over 100 evaluations accurred with $name\n" .
21372a62512bSSteven Rostedt		"Check for recursive variables\n";
21382a62512bSSteven Rostedt	}
21392a62512bSSteven Rostedt	$prev = $option;
21402a62512bSSteven Rostedt	$option = eval_option($option, $i);
21412a62512bSSteven Rostedt    }
21422a62512bSSteven Rostedt
21432a62512bSSteven Rostedt    return $option;
21442a62512bSSteven Rostedt}
21452a62512bSSteven Rostedt
21462545eb61SSteven Rostedt# First we need to do is the builds
2147a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
21482545eb61SSteven Rostedt
2149576f627cSSteven Rostedt    $iteration = $i;
2150576f627cSSteven Rostedt
2151a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
2152a75fececSSteven Rostedt
2153a75fececSSteven Rostedt    $machine = set_test_option("MACHINE", $i);
2154e48c5293SSteven Rostedt    $ssh_user = set_test_option("SSH_USER", $i);
2155a75fececSSteven Rostedt    $tmpdir = set_test_option("TMP_DIR", $i);
2156a75fececSSteven Rostedt    $outputdir = set_test_option("OUTPUT_DIR", $i);
2157a75fececSSteven Rostedt    $builddir = set_test_option("BUILD_DIR", $i);
2158a75fececSSteven Rostedt    $test_type = set_test_option("TEST_TYPE", $i);
2159a75fececSSteven Rostedt    $build_type = set_test_option("BUILD_TYPE", $i);
2160a75fececSSteven Rostedt    $build_options = set_test_option("BUILD_OPTIONS", $i);
2161a75fececSSteven Rostedt    $power_cycle = set_test_option("POWER_CYCLE", $i);
2162e48c5293SSteven Rostedt    $reboot = set_test_option("REBOOT", $i);
2163a75fececSSteven Rostedt    $noclean = set_test_option("BUILD_NOCLEAN", $i);
2164a75fececSSteven Rostedt    $minconfig = set_test_option("MIN_CONFIG", $i);
2165a75fececSSteven Rostedt    $run_test = set_test_option("TEST", $i);
2166a75fececSSteven Rostedt    $addconfig = set_test_option("ADD_CONFIG", $i);
2167a75fececSSteven Rostedt    $reboot_type = set_test_option("REBOOT_TYPE", $i);
2168a75fececSSteven Rostedt    $grub_menu = set_test_option("GRUB_MENU", $i);
21698b37ca8cSSteven Rostedt    $post_install = set_test_option("POST_INSTALL", $i);
2170a75fececSSteven Rostedt    $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
2171a75fececSSteven Rostedt    $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
2172a75fececSSteven Rostedt    $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
2173a75fececSSteven Rostedt    $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
2174a75fececSSteven Rostedt    $power_off = set_test_option("POWER_OFF", $i);
2175576f627cSSteven Rostedt    $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
2176576f627cSSteven Rostedt    $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
2177a75fececSSteven Rostedt    $sleep_time = set_test_option("SLEEP_TIME", $i);
2178a75fececSSteven Rostedt    $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
217927d934b2SSteven Rostedt    $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
2180c960bb9fSSteven Rostedt    $bisect_manual = set_test_option("BISECT_MANUAL", $i);
2181c23dca7cSSteven Rostedt    $bisect_skip = set_test_option("BISECT_SKIP", $i);
2182*30f75da5SSteven Rostedt    $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
2183a75fececSSteven Rostedt    $store_failures = set_test_option("STORE_FAILURES", $i);
2184a75fececSSteven Rostedt    $timeout = set_test_option("TIMEOUT", $i);
2185a75fececSSteven Rostedt    $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
2186a75fececSSteven Rostedt    $console = set_test_option("CONSOLE", $i);
2187f1a5b962SSteven Rostedt    $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
2188a75fececSSteven Rostedt    $success_line = set_test_option("SUCCESS_LINE", $i);
21891c8a617aSSteven Rostedt    $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
21901c8a617aSSteven Rostedt    $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
21912d01b26aSSteven Rostedt    $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
2192a75fececSSteven Rostedt    $build_target = set_test_option("BUILD_TARGET", $i);
2193e48c5293SSteven Rostedt    $ssh_exec = set_test_option("SSH_EXEC", $i);
2194e48c5293SSteven Rostedt    $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
2195a75fececSSteven Rostedt    $target_image = set_test_option("TARGET_IMAGE", $i);
2196a75fececSSteven Rostedt    $localversion = set_test_option("LOCALVERSION", $i);
2197a75fececSSteven Rostedt
2198a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
2199a75fececSSteven Rostedt
2200a75fececSSteven Rostedt    if (!-d $tmpdir) {
2201a75fececSSteven Rostedt	mkpath($tmpdir) or
2202a75fececSSteven Rostedt	    die "can't create $tmpdir";
2203a75fececSSteven Rostedt    }
2204a75fececSSteven Rostedt
2205e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
2206e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
2207e48c5293SSteven Rostedt
2208a75fececSSteven Rostedt    $target = "$ssh_user\@$machine";
2209a75fececSSteven Rostedt
2210a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
2211a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
2212a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
221351ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
2214a75fececSSteven Rostedt
2215a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
2216576f627cSSteven Rostedt	dodie "GRUB_MENU not defined" if (!defined($grub_menu));
2217a75fececSSteven Rostedt    } elsif (!defined($reboot_script)) {
2218576f627cSSteven Rostedt	dodie "REBOOT_SCRIPT not defined"
2219a75fececSSteven Rostedt    }
2220a75fececSSteven Rostedt
2221a75fececSSteven Rostedt    my $run_type = $build_type;
2222a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
2223a75fececSSteven Rostedt	$run_type = $opt{"PATCHCHECK_TYPE[$i]"};
2224a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
2225a75fececSSteven Rostedt	$run_type = $opt{"BISECT_TYPE[$i]"};
22260a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
22270a05c769SSteven Rostedt	$run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
2228a75fececSSteven Rostedt    }
2229a75fececSSteven Rostedt
2230a75fececSSteven Rostedt    # mistake in config file?
2231a75fececSSteven Rostedt    if (!defined($run_type)) {
2232a75fececSSteven Rostedt	$run_type = "ERROR";
2233a75fececSSteven Rostedt    }
22342545eb61SSteven Rostedt
22352545eb61SSteven Rostedt    doprint "\n\n";
2236a75fececSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
22377faafbd6SSteven Rostedt
22387faafbd6SSteven Rostedt    unlink $dmesg;
22397faafbd6SSteven Rostedt    unlink $buildlog;
22402545eb61SSteven Rostedt
22412b7d9b21SSteven Rostedt    if (!defined($minconfig)) {
22422b7d9b21SSteven Rostedt	$minconfig = $addconfig;
22432b7d9b21SSteven Rostedt
22442b7d9b21SSteven Rostedt    } elsif (defined($addconfig)) {
22459be2e6b5SSteven Rostedt	run_command "cat $addconfig $minconfig > $tmpdir/add_config" or
22462b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
22479be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
22482b7d9b21SSteven Rostedt    }
22492b7d9b21SSteven Rostedt
22506c5ee0beSSteven Rostedt    my $checkout = $opt{"CHECKOUT[$i]"};
22516c5ee0beSSteven Rostedt    if (defined($checkout)) {
22526c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
22536c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
22546c5ee0beSSteven Rostedt    }
22556c5ee0beSSteven Rostedt
2256a75fececSSteven Rostedt    if ($test_type eq "bisect") {
22575f9b6cedSSteven Rostedt	bisect $i;
22585f9b6cedSSteven Rostedt	next;
22590a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
22600a05c769SSteven Rostedt	config_bisect $i;
22610a05c769SSteven Rostedt	next;
2262a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
22636c5ee0beSSteven Rostedt	patchcheck $i;
22646c5ee0beSSteven Rostedt	next;
22655f9b6cedSSteven Rostedt    }
22665f9b6cedSSteven Rostedt
22677faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
22687faafbd6SSteven Rostedt	build $build_type or next;
22692545eb61SSteven Rostedt    }
22702545eb61SSteven Rostedt
2271a75fececSSteven Rostedt    if ($test_type ne "build") {
22725f9b6cedSSteven Rostedt	get_grub_index;
22735f9b6cedSSteven Rostedt	get_version;
22742545eb61SSteven Rostedt	install;
22755a391fbfSSteven Rostedt
22767faafbd6SSteven Rostedt	my $failed = 0;
22777faafbd6SSteven Rostedt	start_monitor;
22787faafbd6SSteven Rostedt	monitor or $failed = 1;;
2279a75fececSSteven Rostedt
2280a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
22817faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
22825a391fbfSSteven Rostedt	}
22837faafbd6SSteven Rostedt	end_monitor;
22847faafbd6SSteven Rostedt	next if ($failed);
2285a75fececSSteven Rostedt    }
22865a391fbfSSteven Rostedt
22875f9b6cedSSteven Rostedt    success $i;
228875c3fda7SSteven Rostedt}
22892545eb61SSteven Rostedt
22905c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
229175c3fda7SSteven Rostedt    halt;
2292576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
229375c3fda7SSteven Rostedt    reboot;
22945c42fc5bSSteven Rostedt}
229575c3fda7SSteven Rostedt
2296e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
2297e48c5293SSteven Rostedt
22982545eb61SSteven Rostedtexit 0;
2299