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; 9130f75da5SSteven 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; 1049064af52SSteven Rostedtmy $test_name; 105a75fececSSteven Rostedtmy $timeout; 106a75fececSSteven Rostedtmy $booted_timeout; 107f1a5b962SSteven Rostedtmy $detect_triplefault; 108a75fececSSteven Rostedtmy $console; 109a75fececSSteven Rostedtmy $success_line; 1101c8a617aSSteven Rostedtmy $stop_after_success; 1111c8a617aSSteven Rostedtmy $stop_after_failure; 1122d01b26aSSteven Rostedtmy $stop_test_after; 113a75fececSSteven Rostedtmy $build_target; 114a75fececSSteven Rostedtmy $target_image; 115a75fececSSteven Rostedtmy $localversion; 116576f627cSSteven Rostedtmy $iteration = 0; 117e48c5293SSteven Rostedtmy $successes = 0; 1182545eb61SSteven Rostedt 1198d1491baSSteven Rostedtmy %entered_configs; 1208d1491baSSteven Rostedtmy %config_help; 12177d942ceSSteven Rostedtmy %variable; 122*fcb3f16aSSteven Rostedtmy %force_config; 1238d1491baSSteven Rostedt 1248d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF" 1258d1491baSSteven Rostedt The machine hostname that you will test. 1268d1491baSSteven RostedtEOF 1278d1491baSSteven Rostedt ; 1288d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF" 1298d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user 1308d1491baSSteven Rostedt (most likely root, since you need privileged operations) 1318d1491baSSteven RostedtEOF 1328d1491baSSteven Rostedt ; 1338d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF" 1348d1491baSSteven Rostedt The directory that contains the Linux source code (full path). 1358d1491baSSteven RostedtEOF 1368d1491baSSteven Rostedt ; 1378d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF" 1388d1491baSSteven Rostedt The directory that the objects will be built (full path). 1398d1491baSSteven Rostedt (can not be same as BUILD_DIR) 1408d1491baSSteven RostedtEOF 1418d1491baSSteven Rostedt ; 1428d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF" 1438d1491baSSteven Rostedt The location of the compiled file to copy to the target. 1448d1491baSSteven Rostedt (relative to OUTPUT_DIR) 1458d1491baSSteven RostedtEOF 1468d1491baSSteven Rostedt ; 1478d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF" 1488d1491baSSteven Rostedt The place to put your image on the test machine. 1498d1491baSSteven RostedtEOF 1508d1491baSSteven Rostedt ; 1518d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF" 1528d1491baSSteven Rostedt A script or command to reboot the box. 1538d1491baSSteven Rostedt 1548d1491baSSteven Rostedt Here is a digital loggers power switch example 1558d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL' 1568d1491baSSteven Rostedt 1578d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host 1588d1491baSSteven Rostedt with the name "Guest". 1598d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest 1608d1491baSSteven RostedtEOF 1618d1491baSSteven Rostedt ; 1628d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF" 1638d1491baSSteven Rostedt The script or command that reads the console 1648d1491baSSteven Rostedt 1658d1491baSSteven Rostedt If you use ttywatch server, something like the following would work. 1668d1491baSSteven RostedtCONSOLE = nc -d localhost 3001 1678d1491baSSteven Rostedt 1688d1491baSSteven Rostedt For a virtual machine with guest name "Guest". 1698d1491baSSteven RostedtCONSOLE = virsh console Guest 1708d1491baSSteven RostedtEOF 1718d1491baSSteven Rostedt ; 1728d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF" 1738d1491baSSteven Rostedt Required version ending to differentiate the test 1748d1491baSSteven Rostedt from other linux builds on the system. 1758d1491baSSteven RostedtEOF 1768d1491baSSteven Rostedt ; 1778d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF" 1788d1491baSSteven Rostedt Way to reboot the box to the test kernel. 1798d1491baSSteven Rostedt Only valid options so far are "grub" and "script". 1808d1491baSSteven Rostedt 1818d1491baSSteven Rostedt If you specify grub, it will assume grub version 1 1828d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU 1838d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not 1848d1491baSSteven Rostedt your setup, then specify "script" and have a command or script 1858d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target. 1868d1491baSSteven Rostedt 1878d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually. 1888d1491baSSteven Rostedt The test will not modify that file. 1898d1491baSSteven RostedtEOF 1908d1491baSSteven Rostedt ; 1918d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF" 1928d1491baSSteven Rostedt The grub title name for the test kernel to boot 1938d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = grub) 1948d1491baSSteven Rostedt 1958d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to 1968d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search 1978d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to 1988d1491baSSteven Rostedt reboot into. 1998d1491baSSteven Rostedt 2008d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has: 2018d1491baSSteven Rostedt title Test Kernel 2028d1491baSSteven Rostedt kernel vmlinuz-test 2038d1491baSSteven Rostedt GRUB_MENU = Test Kernel 2048d1491baSSteven RostedtEOF 2058d1491baSSteven Rostedt ; 2068d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF" 2078d1491baSSteven Rostedt A script to reboot the target into the test kernel 2088d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script) 2098d1491baSSteven RostedtEOF 2108d1491baSSteven Rostedt ; 2118d1491baSSteven Rostedt 2128d1491baSSteven Rostedt 2138d1491baSSteven Rostedtsub get_ktest_config { 2148d1491baSSteven Rostedt my ($config) = @_; 2158d1491baSSteven Rostedt 2168d1491baSSteven Rostedt return if (defined($opt{$config})); 2178d1491baSSteven Rostedt 2188d1491baSSteven Rostedt if (defined($config_help{$config})) { 2198d1491baSSteven Rostedt print "\n"; 2208d1491baSSteven Rostedt print $config_help{$config}; 2218d1491baSSteven Rostedt } 2228d1491baSSteven Rostedt 2238d1491baSSteven Rostedt for (;;) { 2248d1491baSSteven Rostedt print "$config = "; 2258d1491baSSteven Rostedt if (defined($default{$config})) { 2268d1491baSSteven Rostedt print "\[$default{$config}\] "; 2278d1491baSSteven Rostedt } 2288d1491baSSteven Rostedt $entered_configs{$config} = <STDIN>; 2298d1491baSSteven Rostedt $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/; 2308d1491baSSteven Rostedt if ($entered_configs{$config} =~ /^\s*$/) { 2318d1491baSSteven Rostedt if ($default{$config}) { 2328d1491baSSteven Rostedt $entered_configs{$config} = $default{$config}; 2338d1491baSSteven Rostedt } else { 2348d1491baSSteven Rostedt print "Your answer can not be blank\n"; 2358d1491baSSteven Rostedt next; 2368d1491baSSteven Rostedt } 2378d1491baSSteven Rostedt } 2388d1491baSSteven Rostedt last; 2398d1491baSSteven Rostedt } 2408d1491baSSteven Rostedt} 2418d1491baSSteven Rostedt 2428d1491baSSteven Rostedtsub get_ktest_configs { 2438d1491baSSteven Rostedt get_ktest_config("MACHINE"); 2448d1491baSSteven Rostedt get_ktest_config("SSH_USER"); 2458d1491baSSteven Rostedt get_ktest_config("BUILD_DIR"); 2468d1491baSSteven Rostedt get_ktest_config("OUTPUT_DIR"); 2478d1491baSSteven Rostedt get_ktest_config("BUILD_TARGET"); 2488d1491baSSteven Rostedt get_ktest_config("TARGET_IMAGE"); 2498d1491baSSteven Rostedt get_ktest_config("POWER_CYCLE"); 2508d1491baSSteven Rostedt get_ktest_config("CONSOLE"); 2518d1491baSSteven Rostedt get_ktest_config("LOCALVERSION"); 2528d1491baSSteven Rostedt 2538d1491baSSteven Rostedt my $rtype = $opt{"REBOOT_TYPE"}; 2548d1491baSSteven Rostedt 2558d1491baSSteven Rostedt if (!defined($rtype)) { 2568d1491baSSteven Rostedt if (!defined($opt{"GRUB_MENU"})) { 2578d1491baSSteven Rostedt get_ktest_config("REBOOT_TYPE"); 2588d1491baSSteven Rostedt $rtype = $entered_configs{"REBOOT_TYPE"}; 2598d1491baSSteven Rostedt } else { 2608d1491baSSteven Rostedt $rtype = "grub"; 2618d1491baSSteven Rostedt } 2628d1491baSSteven Rostedt } 2638d1491baSSteven Rostedt 2648d1491baSSteven Rostedt if ($rtype eq "grub") { 2658d1491baSSteven Rostedt get_ktest_config("GRUB_MENU"); 2668d1491baSSteven Rostedt } else { 2678d1491baSSteven Rostedt get_ktest_config("REBOOT_SCRIPT"); 2688d1491baSSteven Rostedt } 2698d1491baSSteven Rostedt} 2708d1491baSSteven Rostedt 27177d942ceSSteven Rostedtsub process_variables { 27277d942ceSSteven Rostedt my ($value) = @_; 27377d942ceSSteven Rostedt my $retval = ""; 27477d942ceSSteven Rostedt 27577d942ceSSteven Rostedt # We want to check for '\', and it is just easier 27677d942ceSSteven Rostedt # to check the previous characet of '$' and not need 27777d942ceSSteven Rostedt # to worry if '$' is the first character. By adding 27877d942ceSSteven Rostedt # a space to $value, we can just check [^\\]\$ and 27977d942ceSSteven Rostedt # it will still work. 28077d942ceSSteven Rostedt $value = " $value"; 28177d942ceSSteven Rostedt 28277d942ceSSteven Rostedt while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 28377d942ceSSteven Rostedt my $begin = $1; 28477d942ceSSteven Rostedt my $var = $2; 28577d942ceSSteven Rostedt my $end = $3; 28677d942ceSSteven Rostedt # append beginning of value to retval 28777d942ceSSteven Rostedt $retval = "$retval$begin"; 28877d942ceSSteven Rostedt if (defined($variable{$var})) { 28977d942ceSSteven Rostedt $retval = "$retval$variable{$var}"; 29077d942ceSSteven Rostedt } else { 29177d942ceSSteven Rostedt # put back the origin piece. 29277d942ceSSteven Rostedt $retval = "$retval\$\{$var\}"; 29377d942ceSSteven Rostedt } 29477d942ceSSteven Rostedt $value = $end; 29577d942ceSSteven Rostedt } 29677d942ceSSteven Rostedt $retval = "$retval$value"; 29777d942ceSSteven Rostedt 29877d942ceSSteven Rostedt # remove the space added in the beginning 29977d942ceSSteven Rostedt $retval =~ s/ //; 30077d942ceSSteven Rostedt 30177d942ceSSteven Rostedt return "$retval" 30277d942ceSSteven Rostedt} 30377d942ceSSteven Rostedt 304a57419b3SSteven Rostedtsub set_value { 305a57419b3SSteven Rostedt my ($lvalue, $rvalue) = @_; 3062545eb61SSteven Rostedt 307a75fececSSteven Rostedt if (defined($opt{$lvalue})) { 308a75fececSSteven Rostedt die "Error: Option $lvalue defined more than once!\n"; 309a75fececSSteven Rostedt } 31021a9679fSSteven Rostedt if ($rvalue =~ /^\s*$/) { 31121a9679fSSteven Rostedt delete $opt{$lvalue}; 31221a9679fSSteven Rostedt } else { 31377d942ceSSteven Rostedt $rvalue = process_variables($rvalue); 31421a9679fSSteven Rostedt $opt{$lvalue} = $rvalue; 31521a9679fSSteven Rostedt } 3162545eb61SSteven Rostedt} 317a57419b3SSteven Rostedt 31877d942ceSSteven Rostedtsub set_variable { 31977d942ceSSteven Rostedt my ($lvalue, $rvalue) = @_; 32077d942ceSSteven Rostedt 32177d942ceSSteven Rostedt if ($rvalue =~ /^\s*$/) { 32277d942ceSSteven Rostedt delete $variable{$lvalue}; 32377d942ceSSteven Rostedt } else { 32477d942ceSSteven Rostedt $rvalue = process_variables($rvalue); 32577d942ceSSteven Rostedt $variable{$lvalue} = $rvalue; 32677d942ceSSteven Rostedt } 32777d942ceSSteven Rostedt} 32877d942ceSSteven Rostedt 329a57419b3SSteven Rostedtsub read_config { 330a57419b3SSteven Rostedt my ($config) = @_; 331a57419b3SSteven Rostedt 332a57419b3SSteven Rostedt open(IN, $config) || die "can't read file $config"; 333a57419b3SSteven Rostedt 334a57419b3SSteven Rostedt my $name = $config; 335a57419b3SSteven Rostedt $name =~ s,.*/(.*),$1,; 336a57419b3SSteven Rostedt 337a57419b3SSteven Rostedt my $test_num = 0; 338a57419b3SSteven Rostedt my $default = 1; 339a57419b3SSteven Rostedt my $repeat = 1; 340a57419b3SSteven Rostedt my $num_tests_set = 0; 341a57419b3SSteven Rostedt my $skip = 0; 342a57419b3SSteven Rostedt my $rest; 343a57419b3SSteven Rostedt 344a57419b3SSteven Rostedt while (<IN>) { 345a57419b3SSteven Rostedt 346a57419b3SSteven Rostedt # ignore blank lines and comments 347a57419b3SSteven Rostedt next if (/^\s*$/ || /\s*\#/); 348a57419b3SSteven Rostedt 349a57419b3SSteven Rostedt if (/^\s*TEST_START(.*)/) { 350a57419b3SSteven Rostedt 351a57419b3SSteven Rostedt $rest = $1; 352a57419b3SSteven Rostedt 353a57419b3SSteven Rostedt if ($num_tests_set) { 354a57419b3SSteven Rostedt die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 355a57419b3SSteven Rostedt } 356a57419b3SSteven Rostedt 357a57419b3SSteven Rostedt my $old_test_num = $test_num; 358e48c5293SSteven Rostedt my $old_repeat = $repeat; 359a57419b3SSteven Rostedt 360a57419b3SSteven Rostedt $test_num += $repeat; 361a57419b3SSteven Rostedt $default = 0; 362a57419b3SSteven Rostedt $repeat = 1; 363a57419b3SSteven Rostedt 364a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 365a57419b3SSteven Rostedt $rest = $1; 366a57419b3SSteven Rostedt $skip = 1; 367a57419b3SSteven Rostedt } else { 368a57419b3SSteven Rostedt $skip = 0; 369a57419b3SSteven Rostedt } 370a57419b3SSteven Rostedt 371a57419b3SSteven Rostedt if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) { 372a57419b3SSteven Rostedt $repeat = $1; 373a57419b3SSteven Rostedt $rest = $2; 374a57419b3SSteven Rostedt $repeat_tests{"$test_num"} = $repeat; 375a57419b3SSteven Rostedt } 376a57419b3SSteven Rostedt 377a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 378a57419b3SSteven Rostedt $rest = $1; 379a57419b3SSteven Rostedt $skip = 1; 380a57419b3SSteven Rostedt } 381a57419b3SSteven Rostedt 382a57419b3SSteven Rostedt if ($rest !~ /^\s*$/) { 383a57419b3SSteven Rostedt die "$name: $.: Gargbage found after TEST_START\n$_"; 384a57419b3SSteven Rostedt } 385a57419b3SSteven Rostedt 386a57419b3SSteven Rostedt if ($skip) { 387a57419b3SSteven Rostedt $test_num = $old_test_num; 388e48c5293SSteven Rostedt $repeat = $old_repeat; 389a57419b3SSteven Rostedt } 390a57419b3SSteven Rostedt 391a57419b3SSteven Rostedt } elsif (/^\s*DEFAULTS(.*)$/) { 392a57419b3SSteven Rostedt $default = 1; 393a57419b3SSteven Rostedt 394a57419b3SSteven Rostedt $rest = $1; 395a57419b3SSteven Rostedt 396a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 397a57419b3SSteven Rostedt $rest = $1; 398a57419b3SSteven Rostedt $skip = 1; 399a57419b3SSteven Rostedt } else { 400a57419b3SSteven Rostedt $skip = 0; 401a57419b3SSteven Rostedt } 402a57419b3SSteven Rostedt 403a57419b3SSteven Rostedt if ($rest !~ /^\s*$/) { 404a57419b3SSteven Rostedt die "$name: $.: Gargbage found after DEFAULTS\n$_"; 405a57419b3SSteven Rostedt } 406a57419b3SSteven Rostedt 407a57419b3SSteven Rostedt } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 408a57419b3SSteven Rostedt 409a57419b3SSteven Rostedt next if ($skip); 410a57419b3SSteven Rostedt 411a57419b3SSteven Rostedt my $lvalue = $1; 412a57419b3SSteven Rostedt my $rvalue = $2; 413a57419b3SSteven Rostedt 414a57419b3SSteven Rostedt if (!$default && 415a57419b3SSteven Rostedt ($lvalue eq "NUM_TESTS" || 416a57419b3SSteven Rostedt $lvalue eq "LOG_FILE" || 417a57419b3SSteven Rostedt $lvalue eq "CLEAR_LOG")) { 418a57419b3SSteven Rostedt die "$name: $.: $lvalue must be set in DEFAULTS section\n"; 419a57419b3SSteven Rostedt } 420a57419b3SSteven Rostedt 421a57419b3SSteven Rostedt if ($lvalue eq "NUM_TESTS") { 422a57419b3SSteven Rostedt if ($test_num) { 423a57419b3SSteven Rostedt die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 424a57419b3SSteven Rostedt } 425a57419b3SSteven Rostedt if (!$default) { 426a57419b3SSteven Rostedt die "$name: $.: NUM_TESTS must be set in default section\n"; 427a57419b3SSteven Rostedt } 428a57419b3SSteven Rostedt $num_tests_set = 1; 429a57419b3SSteven Rostedt } 430a57419b3SSteven Rostedt 431a57419b3SSteven Rostedt if ($default || $lvalue =~ /\[\d+\]$/) { 432a57419b3SSteven Rostedt set_value($lvalue, $rvalue); 433a57419b3SSteven Rostedt } else { 434a57419b3SSteven Rostedt my $val = "$lvalue\[$test_num\]"; 435a57419b3SSteven Rostedt set_value($val, $rvalue); 436a57419b3SSteven Rostedt 437a57419b3SSteven Rostedt if ($repeat > 1) { 438a57419b3SSteven Rostedt $repeats{$val} = $repeat; 439a57419b3SSteven Rostedt } 440a57419b3SSteven Rostedt } 44177d942ceSSteven Rostedt } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) { 44277d942ceSSteven Rostedt next if ($skip); 44377d942ceSSteven Rostedt 44477d942ceSSteven Rostedt my $lvalue = $1; 44577d942ceSSteven Rostedt my $rvalue = $2; 44677d942ceSSteven Rostedt 44777d942ceSSteven Rostedt # process config variables. 44877d942ceSSteven Rostedt # Config variables are only active while reading the 44977d942ceSSteven Rostedt # config and can be defined anywhere. They also ignore 45077d942ceSSteven Rostedt # TEST_START and DEFAULTS, but are skipped if they are in 45177d942ceSSteven Rostedt # on of these sections that have SKIP defined. 45277d942ceSSteven Rostedt # The save variable can be 45377d942ceSSteven Rostedt # defined multiple times and the new one simply overrides 45477d942ceSSteven Rostedt # the prevous one. 45577d942ceSSteven Rostedt set_variable($lvalue, $rvalue); 45677d942ceSSteven Rostedt 457a57419b3SSteven Rostedt } else { 458a57419b3SSteven Rostedt die "$name: $.: Garbage found in config\n$_"; 459a57419b3SSteven Rostedt } 4602545eb61SSteven Rostedt } 4612545eb61SSteven Rostedt 4622545eb61SSteven Rostedt close(IN); 463a75fececSSteven Rostedt 464a57419b3SSteven Rostedt if ($test_num) { 465a57419b3SSteven Rostedt $test_num += $repeat - 1; 466a57419b3SSteven Rostedt $opt{"NUM_TESTS"} = $test_num; 467a57419b3SSteven Rostedt } 468a57419b3SSteven Rostedt 4698d1491baSSteven Rostedt # make sure we have all mandatory configs 4708d1491baSSteven Rostedt get_ktest_configs; 4718d1491baSSteven Rostedt 472a75fececSSteven Rostedt # set any defaults 473a75fececSSteven Rostedt 474a75fececSSteven Rostedt foreach my $default (keys %default) { 475a75fececSSteven Rostedt if (!defined($opt{$default})) { 476a75fececSSteven Rostedt $opt{$default} = $default{$default}; 477a75fececSSteven Rostedt } 478a75fececSSteven Rostedt } 4792545eb61SSteven Rostedt} 4802545eb61SSteven Rostedt 481d1e2f22aSSteven Rostedtsub _logit { 4822545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 4832545eb61SSteven Rostedt open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 4842545eb61SSteven Rostedt print OUT @_; 4852545eb61SSteven Rostedt close(OUT); 4862545eb61SSteven Rostedt } 4872545eb61SSteven Rostedt} 4882545eb61SSteven Rostedt 489d1e2f22aSSteven Rostedtsub logit { 490d1e2f22aSSteven Rostedt if (defined($opt{"LOG_FILE"})) { 491d1e2f22aSSteven Rostedt _logit @_; 492d1e2f22aSSteven Rostedt } else { 493d1e2f22aSSteven Rostedt print @_; 494d1e2f22aSSteven Rostedt } 495d1e2f22aSSteven Rostedt} 496d1e2f22aSSteven Rostedt 4975f9b6cedSSteven Rostedtsub doprint { 4985f9b6cedSSteven Rostedt print @_; 499d1e2f22aSSteven Rostedt _logit @_; 5005f9b6cedSSteven Rostedt} 5015f9b6cedSSteven Rostedt 5027faafbd6SSteven Rostedtsub run_command; 5037faafbd6SSteven Rostedt 5047faafbd6SSteven Rostedtsub reboot { 5057faafbd6SSteven Rostedt # try to reboot normally 506e48c5293SSteven Rostedt if (run_command $reboot) { 507576f627cSSteven Rostedt if (defined($powercycle_after_reboot)) { 508576f627cSSteven Rostedt sleep $powercycle_after_reboot; 509576f627cSSteven Rostedt run_command "$power_cycle"; 510576f627cSSteven Rostedt } 511576f627cSSteven Rostedt } else { 5127faafbd6SSteven Rostedt # nope? power cycle it. 513a75fececSSteven Rostedt run_command "$power_cycle"; 5147faafbd6SSteven Rostedt } 5157faafbd6SSteven Rostedt} 5167faafbd6SSteven Rostedt 517576f627cSSteven Rostedtsub do_not_reboot { 518576f627cSSteven Rostedt my $i = $iteration; 519576f627cSSteven Rostedt 520576f627cSSteven Rostedt return $test_type eq "build" || 521576f627cSSteven Rostedt ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 522576f627cSSteven Rostedt ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 523576f627cSSteven Rostedt} 524576f627cSSteven Rostedt 5255c42fc5bSSteven Rostedtsub dodie { 5265a391fbfSSteven Rostedt doprint "CRITICAL FAILURE... ", @_, "\n"; 5275c42fc5bSSteven Rostedt 528576f627cSSteven Rostedt my $i = $iteration; 529576f627cSSteven Rostedt 530576f627cSSteven Rostedt if ($reboot_on_error && !do_not_reboot) { 531576f627cSSteven Rostedt 53275c3fda7SSteven Rostedt doprint "REBOOTING\n"; 5337faafbd6SSteven Rostedt reboot; 53475c3fda7SSteven Rostedt 535a75fececSSteven Rostedt } elsif ($poweroff_on_error && defined($power_off)) { 5365c42fc5bSSteven Rostedt doprint "POWERING OFF\n"; 537a75fececSSteven Rostedt `$power_off`; 5385c42fc5bSSteven Rostedt } 53975c3fda7SSteven Rostedt 540f80802cbSSteven Rostedt if (defined($opt{"LOG_FILE"})) { 541f80802cbSSteven Rostedt print " See $opt{LOG_FILE} for more info.\n"; 542f80802cbSSteven Rostedt } 543f80802cbSSteven Rostedt 544576f627cSSteven Rostedt die @_, "\n"; 5455c42fc5bSSteven Rostedt} 5465c42fc5bSSteven Rostedt 5477faafbd6SSteven Rostedtsub open_console { 5487faafbd6SSteven Rostedt my ($fp) = @_; 5497faafbd6SSteven Rostedt 5507faafbd6SSteven Rostedt my $flags; 5517faafbd6SSteven Rostedt 552a75fececSSteven Rostedt my $pid = open($fp, "$console|") or 553a75fececSSteven Rostedt dodie "Can't open console $console"; 5547faafbd6SSteven Rostedt 5557faafbd6SSteven Rostedt $flags = fcntl($fp, F_GETFL, 0) or 556576f627cSSteven Rostedt dodie "Can't get flags for the socket: $!"; 5577faafbd6SSteven Rostedt $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 558576f627cSSteven Rostedt dodie "Can't set flags for the socket: $!"; 5597faafbd6SSteven Rostedt 5607faafbd6SSteven Rostedt return $pid; 5617faafbd6SSteven Rostedt} 5627faafbd6SSteven Rostedt 5637faafbd6SSteven Rostedtsub close_console { 5647faafbd6SSteven Rostedt my ($fp, $pid) = @_; 5657faafbd6SSteven Rostedt 5667faafbd6SSteven Rostedt doprint "kill child process $pid\n"; 5677faafbd6SSteven Rostedt kill 2, $pid; 5687faafbd6SSteven Rostedt 5697faafbd6SSteven Rostedt print "closing!\n"; 5707faafbd6SSteven Rostedt close($fp); 5717faafbd6SSteven Rostedt} 5727faafbd6SSteven Rostedt 5737faafbd6SSteven Rostedtsub start_monitor { 5747faafbd6SSteven Rostedt if ($monitor_cnt++) { 5757faafbd6SSteven Rostedt return; 5767faafbd6SSteven Rostedt } 5777faafbd6SSteven Rostedt $monitor_fp = \*MONFD; 5787faafbd6SSteven Rostedt $monitor_pid = open_console $monitor_fp; 579a75fececSSteven Rostedt 580a75fececSSteven Rostedt return; 581a75fececSSteven Rostedt 582a75fececSSteven Rostedt open(MONFD, "Stop perl from warning about single use of MONFD"); 5837faafbd6SSteven Rostedt} 5847faafbd6SSteven Rostedt 5857faafbd6SSteven Rostedtsub end_monitor { 5867faafbd6SSteven Rostedt if (--$monitor_cnt) { 5877faafbd6SSteven Rostedt return; 5887faafbd6SSteven Rostedt } 5897faafbd6SSteven Rostedt close_console($monitor_fp, $monitor_pid); 5907faafbd6SSteven Rostedt} 5917faafbd6SSteven Rostedt 5927faafbd6SSteven Rostedtsub wait_for_monitor { 5937faafbd6SSteven Rostedt my ($time) = @_; 5947faafbd6SSteven Rostedt my $line; 5957faafbd6SSteven Rostedt 596a75fececSSteven Rostedt doprint "** Wait for monitor to settle down **\n"; 5977faafbd6SSteven Rostedt 5987faafbd6SSteven Rostedt # read the monitor and wait for the system to calm down 5997faafbd6SSteven Rostedt do { 6007faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 601a75fececSSteven Rostedt print "$line" if (defined($line)); 6027faafbd6SSteven Rostedt } while (defined($line)); 603a75fececSSteven Rostedt print "** Monitor flushed **\n"; 6047faafbd6SSteven Rostedt} 6057faafbd6SSteven Rostedt 6062b7d9b21SSteven Rostedtsub fail { 6072b7d9b21SSteven Rostedt 608a75fececSSteven Rostedt if ($die_on_failure) { 6092b7d9b21SSteven Rostedt dodie @_; 6102b7d9b21SSteven Rostedt } 6112b7d9b21SSteven Rostedt 612a75fececSSteven Rostedt doprint "FAILED\n"; 6137faafbd6SSteven Rostedt 614576f627cSSteven Rostedt my $i = $iteration; 615576f627cSSteven Rostedt 616a75fececSSteven Rostedt # no need to reboot for just building. 617576f627cSSteven Rostedt if (!do_not_reboot) { 6187faafbd6SSteven Rostedt doprint "REBOOTING\n"; 6197faafbd6SSteven Rostedt reboot; 6207faafbd6SSteven Rostedt start_monitor; 621a75fececSSteven Rostedt wait_for_monitor $sleep_time; 6227faafbd6SSteven Rostedt end_monitor; 623a75fececSSteven Rostedt } 6247faafbd6SSteven Rostedt 6259064af52SSteven Rostedt my $name = ""; 6269064af52SSteven Rostedt 6279064af52SSteven Rostedt if (defined($test_name)) { 6289064af52SSteven Rostedt $name = " ($test_name)"; 6299064af52SSteven Rostedt } 6309064af52SSteven Rostedt 631576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 632576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 6339064af52SSteven Rostedt doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n"; 634576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 635576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 636a75fececSSteven Rostedt 637a75fececSSteven Rostedt return 1 if (!defined($store_failures)); 6387faafbd6SSteven Rostedt 6397faafbd6SSteven Rostedt my @t = localtime; 6407faafbd6SSteven Rostedt my $date = sprintf "%04d%02d%02d%02d%02d%02d", 6417faafbd6SSteven Rostedt 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 6427faafbd6SSteven Rostedt 643cccae1a6SSteven Rostedt my $type = $build_type; 644cccae1a6SSteven Rostedt if ($type =~ /useconfig/) { 645cccae1a6SSteven Rostedt $type = "useconfig"; 646cccae1a6SSteven Rostedt } 647cccae1a6SSteven Rostedt 648cccae1a6SSteven Rostedt my $dir = "$machine-$test_type-$type-fail-$date"; 649a75fececSSteven Rostedt my $faildir = "$store_failures/$dir"; 6507faafbd6SSteven Rostedt 6517faafbd6SSteven Rostedt if (!-d $faildir) { 6527faafbd6SSteven Rostedt mkpath($faildir) or 653a75fececSSteven Rostedt die "can't create $faildir"; 6547faafbd6SSteven Rostedt } 65551ad1dd1SSteven Rostedt if (-f "$output_config") { 65651ad1dd1SSteven Rostedt cp "$output_config", "$faildir/config" or 6577faafbd6SSteven Rostedt die "failed to copy .config"; 6587faafbd6SSteven Rostedt } 6597faafbd6SSteven Rostedt if (-f $buildlog) { 6607faafbd6SSteven Rostedt cp $buildlog, "$faildir/buildlog" or 6617faafbd6SSteven Rostedt die "failed to move $buildlog"; 6627faafbd6SSteven Rostedt } 6637faafbd6SSteven Rostedt if (-f $dmesg) { 6647faafbd6SSteven Rostedt cp $dmesg, "$faildir/dmesg" or 6657faafbd6SSteven Rostedt die "failed to move $dmesg"; 6667faafbd6SSteven Rostedt } 6677faafbd6SSteven Rostedt 6687faafbd6SSteven Rostedt doprint "*** Saved info to $faildir ***\n"; 6697faafbd6SSteven Rostedt 6702b7d9b21SSteven Rostedt return 1; 6712b7d9b21SSteven Rostedt} 6722b7d9b21SSteven Rostedt 6732545eb61SSteven Rostedtsub run_command { 6742545eb61SSteven Rostedt my ($command) = @_; 675d6ce2a0bSSteven Rostedt my $dolog = 0; 676d6ce2a0bSSteven Rostedt my $dord = 0; 677d6ce2a0bSSteven Rostedt my $pid; 678d6ce2a0bSSteven Rostedt 679e48c5293SSteven Rostedt $command =~ s/\$SSH_USER/$ssh_user/g; 680e48c5293SSteven Rostedt $command =~ s/\$MACHINE/$machine/g; 681e48c5293SSteven Rostedt 682d6ce2a0bSSteven Rostedt doprint("$command ... "); 683d6ce2a0bSSteven Rostedt 684d6ce2a0bSSteven Rostedt $pid = open(CMD, "$command 2>&1 |") or 6852b7d9b21SSteven Rostedt (fail "unable to exec $command" and return 0); 6862545eb61SSteven Rostedt 6872545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 688d6ce2a0bSSteven Rostedt open(LOG, ">>$opt{LOG_FILE}") or 689d6ce2a0bSSteven Rostedt dodie "failed to write to log"; 690d6ce2a0bSSteven Rostedt $dolog = 1; 6916c5ee0beSSteven Rostedt } 6926c5ee0beSSteven Rostedt 6936c5ee0beSSteven Rostedt if (defined($redirect)) { 694d6ce2a0bSSteven Rostedt open (RD, ">$redirect") or 695d6ce2a0bSSteven Rostedt dodie "failed to write to redirect $redirect"; 696d6ce2a0bSSteven Rostedt $dord = 1; 6972545eb61SSteven Rostedt } 6982545eb61SSteven Rostedt 699d6ce2a0bSSteven Rostedt while (<CMD>) { 700d6ce2a0bSSteven Rostedt print LOG if ($dolog); 701d6ce2a0bSSteven Rostedt print RD if ($dord); 702d6ce2a0bSSteven Rostedt } 7032545eb61SSteven Rostedt 704d6ce2a0bSSteven Rostedt waitpid($pid, 0); 7052545eb61SSteven Rostedt my $failed = $?; 7062545eb61SSteven Rostedt 707d6ce2a0bSSteven Rostedt close(CMD); 708d6ce2a0bSSteven Rostedt close(LOG) if ($dolog); 709d6ce2a0bSSteven Rostedt close(RD) if ($dord); 710d6ce2a0bSSteven Rostedt 7112545eb61SSteven Rostedt if ($failed) { 7122545eb61SSteven Rostedt doprint "FAILED!\n"; 7132545eb61SSteven Rostedt } else { 7142545eb61SSteven Rostedt doprint "SUCCESS\n"; 7152545eb61SSteven Rostedt } 7162545eb61SSteven Rostedt 7175f9b6cedSSteven Rostedt return !$failed; 7185f9b6cedSSteven Rostedt} 7195f9b6cedSSteven Rostedt 720e48c5293SSteven Rostedtsub run_ssh { 721e48c5293SSteven Rostedt my ($cmd) = @_; 722e48c5293SSteven Rostedt my $cp_exec = $ssh_exec; 723e48c5293SSteven Rostedt 724e48c5293SSteven Rostedt $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 725e48c5293SSteven Rostedt return run_command "$cp_exec"; 726e48c5293SSteven Rostedt} 727e48c5293SSteven Rostedt 728e48c5293SSteven Rostedtsub run_scp { 729e48c5293SSteven Rostedt my ($src, $dst) = @_; 730e48c5293SSteven Rostedt my $cp_scp = $scp_to_target; 731e48c5293SSteven Rostedt 732e48c5293SSteven Rostedt $cp_scp =~ s/\$SRC_FILE/$src/g; 733e48c5293SSteven Rostedt $cp_scp =~ s/\$DST_FILE/$dst/g; 734e48c5293SSteven Rostedt 735e48c5293SSteven Rostedt return run_command "$cp_scp"; 736e48c5293SSteven Rostedt} 737e48c5293SSteven Rostedt 7385f9b6cedSSteven Rostedtsub get_grub_index { 7395f9b6cedSSteven Rostedt 740a75fececSSteven Rostedt if ($reboot_type ne "grub") { 741a75fececSSteven Rostedt return; 742a75fececSSteven Rostedt } 7435a391fbfSSteven Rostedt return if (defined($grub_number)); 7445f9b6cedSSteven Rostedt 7455f9b6cedSSteven Rostedt doprint "Find grub menu ... "; 7465f9b6cedSSteven Rostedt $grub_number = -1; 747e48c5293SSteven Rostedt 748e48c5293SSteven Rostedt my $ssh_grub = $ssh_exec; 749e48c5293SSteven Rostedt $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 750e48c5293SSteven Rostedt 751e48c5293SSteven Rostedt open(IN, "$ssh_grub |") 7525f9b6cedSSteven Rostedt or die "unable to get menu.lst"; 753e48c5293SSteven Rostedt 7545f9b6cedSSteven Rostedt while (<IN>) { 755a75fececSSteven Rostedt if (/^\s*title\s+$grub_menu\s*$/) { 7565f9b6cedSSteven Rostedt $grub_number++; 7575f9b6cedSSteven Rostedt last; 7585f9b6cedSSteven Rostedt } elsif (/^\s*title\s/) { 7595f9b6cedSSteven Rostedt $grub_number++; 7605f9b6cedSSteven Rostedt } 7615f9b6cedSSteven Rostedt } 7625f9b6cedSSteven Rostedt close(IN); 7635f9b6cedSSteven Rostedt 764a75fececSSteven Rostedt die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 7655f9b6cedSSteven Rostedt if ($grub_number < 0); 7665f9b6cedSSteven Rostedt doprint "$grub_number\n"; 7672545eb61SSteven Rostedt} 7682545eb61SSteven Rostedt 7692545eb61SSteven Rostedtsub wait_for_input 7702545eb61SSteven Rostedt{ 7712545eb61SSteven Rostedt my ($fp, $time) = @_; 7722545eb61SSteven Rostedt my $rin; 7732545eb61SSteven Rostedt my $ready; 7742545eb61SSteven Rostedt my $line; 7752545eb61SSteven Rostedt my $ch; 7762545eb61SSteven Rostedt 7772545eb61SSteven Rostedt if (!defined($time)) { 7782545eb61SSteven Rostedt $time = $timeout; 7792545eb61SSteven Rostedt } 7802545eb61SSteven Rostedt 7812545eb61SSteven Rostedt $rin = ''; 7822545eb61SSteven Rostedt vec($rin, fileno($fp), 1) = 1; 7832545eb61SSteven Rostedt $ready = select($rin, undef, undef, $time); 7842545eb61SSteven Rostedt 7852545eb61SSteven Rostedt $line = ""; 7862545eb61SSteven Rostedt 7872545eb61SSteven Rostedt # try to read one char at a time 7882545eb61SSteven Rostedt while (sysread $fp, $ch, 1) { 7892545eb61SSteven Rostedt $line .= $ch; 7902545eb61SSteven Rostedt last if ($ch eq "\n"); 7912545eb61SSteven Rostedt } 7922545eb61SSteven Rostedt 7932545eb61SSteven Rostedt if (!length($line)) { 7942545eb61SSteven Rostedt return undef; 7952545eb61SSteven Rostedt } 7962545eb61SSteven Rostedt 7972545eb61SSteven Rostedt return $line; 7982545eb61SSteven Rostedt} 7992545eb61SSteven Rostedt 80075c3fda7SSteven Rostedtsub reboot_to { 801a75fececSSteven Rostedt if ($reboot_type eq "grub") { 8024da46da2SSteven Rostedt run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'"; 803a75fececSSteven Rostedt return; 804a75fececSSteven Rostedt } 805a75fececSSteven Rostedt 806a75fececSSteven Rostedt run_command "$reboot_script"; 8072545eb61SSteven Rostedt} 8082545eb61SSteven Rostedt 809a57419b3SSteven Rostedtsub get_sha1 { 810a57419b3SSteven Rostedt my ($commit) = @_; 811a57419b3SSteven Rostedt 812a57419b3SSteven Rostedt doprint "git rev-list --max-count=1 $commit ... "; 813a57419b3SSteven Rostedt my $sha1 = `git rev-list --max-count=1 $commit`; 814a57419b3SSteven Rostedt my $ret = $?; 815a57419b3SSteven Rostedt 816a57419b3SSteven Rostedt logit $sha1; 817a57419b3SSteven Rostedt 818a57419b3SSteven Rostedt if ($ret) { 819a57419b3SSteven Rostedt doprint "FAILED\n"; 820a57419b3SSteven Rostedt dodie "Failed to get git $commit"; 821a57419b3SSteven Rostedt } 822a57419b3SSteven Rostedt 823a57419b3SSteven Rostedt print "SUCCESS\n"; 824a57419b3SSteven Rostedt 825a57419b3SSteven Rostedt chomp $sha1; 826a57419b3SSteven Rostedt 827a57419b3SSteven Rostedt return $sha1; 828a57419b3SSteven Rostedt} 829a57419b3SSteven Rostedt 8305a391fbfSSteven Rostedtsub monitor { 8312545eb61SSteven Rostedt my $booted = 0; 8322545eb61SSteven Rostedt my $bug = 0; 8335c42fc5bSSteven Rostedt my $skip_call_trace = 0; 8342b7d9b21SSteven Rostedt my $loops; 8352545eb61SSteven Rostedt 8367faafbd6SSteven Rostedt wait_for_monitor 5; 8372545eb61SSteven Rostedt 8382545eb61SSteven Rostedt my $line; 8392545eb61SSteven Rostedt my $full_line = ""; 8402545eb61SSteven Rostedt 8417faafbd6SSteven Rostedt open(DMESG, "> $dmesg") or 8427faafbd6SSteven Rostedt die "unable to write to $dmesg"; 8432545eb61SSteven Rostedt 84475c3fda7SSteven Rostedt reboot_to; 8452545eb61SSteven Rostedt 8461c8a617aSSteven Rostedt my $success_start; 8471c8a617aSSteven Rostedt my $failure_start; 8482d01b26aSSteven Rostedt my $monitor_start = time; 8492d01b26aSSteven Rostedt my $done = 0; 850f1a5b962SSteven Rostedt my $version_found = 0; 8511c8a617aSSteven Rostedt 8522d01b26aSSteven Rostedt while (!$done) { 8532545eb61SSteven Rostedt 8542b7d9b21SSteven Rostedt if ($booted) { 855a75fececSSteven Rostedt $line = wait_for_input($monitor_fp, $booted_timeout); 856cd4f1d53SSteven Rostedt if (!defined($line)) { 857cd4f1d53SSteven Rostedt my $s = $booted_timeout == 1 ? "" : "s"; 858cd4f1d53SSteven Rostedt doprint "Successful boot found: break after $booted_timeout second$s\n"; 859cd4f1d53SSteven Rostedt last; 860cd4f1d53SSteven Rostedt } 8612b7d9b21SSteven Rostedt } else { 8627faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp); 863cd4f1d53SSteven Rostedt if (!defined($line)) { 864cd4f1d53SSteven Rostedt my $s = $timeout == 1 ? "" : "s"; 865cd4f1d53SSteven Rostedt doprint "Timed out after $timeout second$s\n"; 866cd4f1d53SSteven Rostedt last; 8672b7d9b21SSteven Rostedt } 868cd4f1d53SSteven Rostedt } 8692545eb61SSteven Rostedt 8702545eb61SSteven Rostedt doprint $line; 8717faafbd6SSteven Rostedt print DMESG $line; 8722545eb61SSteven Rostedt 8732545eb61SSteven Rostedt # we are not guaranteed to get a full line 8742545eb61SSteven Rostedt $full_line .= $line; 8752545eb61SSteven Rostedt 876a75fececSSteven Rostedt if ($full_line =~ /$success_line/) { 8772545eb61SSteven Rostedt $booted = 1; 8781c8a617aSSteven Rostedt $success_start = time; 8791c8a617aSSteven Rostedt } 8801c8a617aSSteven Rostedt 8811c8a617aSSteven Rostedt if ($booted && defined($stop_after_success) && 8821c8a617aSSteven Rostedt $stop_after_success >= 0) { 8831c8a617aSSteven Rostedt my $now = time; 8841c8a617aSSteven Rostedt if ($now - $success_start >= $stop_after_success) { 8851c8a617aSSteven Rostedt doprint "Test forced to stop after $stop_after_success seconds after success\n"; 8861c8a617aSSteven Rostedt last; 8871c8a617aSSteven Rostedt } 8882545eb61SSteven Rostedt } 8892545eb61SSteven Rostedt 8905c42fc5bSSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 8915c42fc5bSSteven Rostedt $skip_call_trace = 1; 8925c42fc5bSSteven Rostedt } 8935c42fc5bSSteven Rostedt 8942545eb61SSteven Rostedt if ($full_line =~ /call trace:/i) { 8954651920eSSteven Rostedt if (!$bug && !$skip_call_trace) { 8961c8a617aSSteven Rostedt $bug = 1; 8971c8a617aSSteven Rostedt $failure_start = time; 8981c8a617aSSteven Rostedt } 8991c8a617aSSteven Rostedt } 9001c8a617aSSteven Rostedt 9011c8a617aSSteven Rostedt if ($bug && defined($stop_after_failure) && 9021c8a617aSSteven Rostedt $stop_after_failure >= 0) { 9031c8a617aSSteven Rostedt my $now = time; 9041c8a617aSSteven Rostedt if ($now - $failure_start >= $stop_after_failure) { 9051c8a617aSSteven Rostedt doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 9061c8a617aSSteven Rostedt last; 9071c8a617aSSteven Rostedt } 9085c42fc5bSSteven Rostedt } 9095c42fc5bSSteven Rostedt 9105c42fc5bSSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 9115c42fc5bSSteven Rostedt $skip_call_trace = 0; 9125c42fc5bSSteven Rostedt } 9135c42fc5bSSteven Rostedt 9145c42fc5bSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 91510abf118SSteven Rostedt $failure_start = time; 9162545eb61SSteven Rostedt $bug = 1; 9172545eb61SSteven Rostedt } 9182545eb61SSteven Rostedt 919f1a5b962SSteven Rostedt # Detect triple faults by testing the banner 920f1a5b962SSteven Rostedt if ($full_line =~ /\bLinux version (\S+).*\n/) { 921f1a5b962SSteven Rostedt if ($1 eq $version) { 922f1a5b962SSteven Rostedt $version_found = 1; 923f1a5b962SSteven Rostedt } elsif ($version_found && $detect_triplefault) { 924f1a5b962SSteven Rostedt # We already booted into the kernel we are testing, 925f1a5b962SSteven Rostedt # but now we booted into another kernel? 926f1a5b962SSteven Rostedt # Consider this a triple fault. 927f1a5b962SSteven Rostedt doprint "Aleady booted in Linux kernel $version, but now\n"; 928f1a5b962SSteven Rostedt doprint "we booted into Linux kernel $1.\n"; 929f1a5b962SSteven Rostedt doprint "Assuming that this is a triple fault.\n"; 930f1a5b962SSteven Rostedt doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; 931f1a5b962SSteven Rostedt last; 932f1a5b962SSteven Rostedt } 933f1a5b962SSteven Rostedt } 934f1a5b962SSteven Rostedt 9352545eb61SSteven Rostedt if ($line =~ /\n/) { 9362545eb61SSteven Rostedt $full_line = ""; 9372545eb61SSteven Rostedt } 9382d01b26aSSteven Rostedt 9392d01b26aSSteven Rostedt if ($stop_test_after > 0 && !$booted && !$bug) { 9402d01b26aSSteven Rostedt if (time - $monitor_start > $stop_test_after) { 9414d62bf51SSteven Rostedt doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 9422d01b26aSSteven Rostedt $done = 1; 9432d01b26aSSteven Rostedt } 9442d01b26aSSteven Rostedt } 9452545eb61SSteven Rostedt } 9462545eb61SSteven Rostedt 9477faafbd6SSteven Rostedt close(DMESG); 9482545eb61SSteven Rostedt 9492545eb61SSteven Rostedt if ($bug) { 9502b7d9b21SSteven Rostedt return 0 if ($in_bisect); 951576f627cSSteven Rostedt fail "failed - got a bug report" and return 0; 9522545eb61SSteven Rostedt } 9535f9b6cedSSteven Rostedt 954a75fececSSteven Rostedt if (!$booted) { 955a75fececSSteven Rostedt return 0 if ($in_bisect); 956576f627cSSteven Rostedt fail "failed - never got a boot prompt." and return 0; 957a75fececSSteven Rostedt } 958a75fececSSteven Rostedt 9592b7d9b21SSteven Rostedt return 1; 9602545eb61SSteven Rostedt} 9612545eb61SSteven Rostedt 9622545eb61SSteven Rostedtsub install { 9632545eb61SSteven Rostedt 964e48c5293SSteven Rostedt run_scp "$outputdir/$build_target", "$target_image" or 9655c42fc5bSSteven Rostedt dodie "failed to copy image"; 9665f9b6cedSSteven Rostedt 9675f9b6cedSSteven Rostedt my $install_mods = 0; 9685f9b6cedSSteven Rostedt 9695f9b6cedSSteven Rostedt # should we process modules? 9705f9b6cedSSteven Rostedt $install_mods = 0; 97151ad1dd1SSteven Rostedt open(IN, "$output_config") or dodie("Can't read config file"); 9725f9b6cedSSteven Rostedt while (<IN>) { 9735f9b6cedSSteven Rostedt if (/CONFIG_MODULES(=y)?/) { 9745f9b6cedSSteven Rostedt $install_mods = 1 if (defined($1)); 9755f9b6cedSSteven Rostedt last; 9765f9b6cedSSteven Rostedt } 9775f9b6cedSSteven Rostedt } 9785f9b6cedSSteven Rostedt close(IN); 9795f9b6cedSSteven Rostedt 9805f9b6cedSSteven Rostedt if (!$install_mods) { 9815f9b6cedSSteven Rostedt doprint "No modules needed\n"; 9825f9b6cedSSteven Rostedt return; 9832545eb61SSteven Rostedt } 9842545eb61SSteven Rostedt 985a75fececSSteven Rostedt run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or 9865f9b6cedSSteven Rostedt dodie "Failed to install modules"; 9875f9b6cedSSteven Rostedt 9882545eb61SSteven Rostedt my $modlib = "/lib/modules/$version"; 989a57419b3SSteven Rostedt my $modtar = "ktest-mods.tar.bz2"; 9902545eb61SSteven Rostedt 991e48c5293SSteven Rostedt run_ssh "rm -rf $modlib" or 9925c42fc5bSSteven Rostedt dodie "failed to remove old mods: $modlib"; 9932545eb61SSteven Rostedt 9945c42fc5bSSteven Rostedt # would be nice if scp -r did not follow symbolic links 995a75fececSSteven Rostedt run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 9965c42fc5bSSteven Rostedt dodie "making tarball"; 9975c42fc5bSSteven Rostedt 998e48c5293SSteven Rostedt run_scp "$tmpdir/$modtar", "/tmp" or 9995c42fc5bSSteven Rostedt dodie "failed to copy modules"; 10005c42fc5bSSteven Rostedt 1001a75fececSSteven Rostedt unlink "$tmpdir/$modtar"; 10025c42fc5bSSteven Rostedt 1003e48c5293SSteven Rostedt run_ssh "'(cd / && tar xf /tmp/$modtar)'" or 10045c42fc5bSSteven Rostedt dodie "failed to tar modules"; 10055c42fc5bSSteven Rostedt 1006e48c5293SSteven Rostedt run_ssh "rm -f /tmp/$modtar"; 10078b37ca8cSSteven Rostedt 10088b37ca8cSSteven Rostedt return if (!defined($post_install)); 10098b37ca8cSSteven Rostedt 1010e48c5293SSteven Rostedt my $cp_post_install = $post_install; 1011ca6a21f8SSteven Rostedt $cp_post_install =~ s/\$KERNEL_VERSION/$version/g; 1012e48c5293SSteven Rostedt run_command "$cp_post_install" or 1013576f627cSSteven Rostedt dodie "Failed to run post install"; 10142545eb61SSteven Rostedt} 10152545eb61SSteven Rostedt 10166c5ee0beSSteven Rostedtsub check_buildlog { 10176c5ee0beSSteven Rostedt my ($patch) = @_; 10186c5ee0beSSteven Rostedt 10196c5ee0beSSteven Rostedt my @files = `git show $patch | diffstat -l`; 10206c5ee0beSSteven Rostedt 10216c5ee0beSSteven Rostedt open(IN, "git show $patch |") or 10226c5ee0beSSteven Rostedt dodie "failed to show $patch"; 10236c5ee0beSSteven Rostedt while (<IN>) { 10246c5ee0beSSteven Rostedt if (m,^--- a/(.*),) { 10256c5ee0beSSteven Rostedt chomp $1; 10266c5ee0beSSteven Rostedt $files[$#files] = $1; 10276c5ee0beSSteven Rostedt } 10286c5ee0beSSteven Rostedt } 10296c5ee0beSSteven Rostedt close(IN); 10306c5ee0beSSteven Rostedt 10316c5ee0beSSteven Rostedt open(IN, $buildlog) or dodie "Can't open $buildlog"; 10326c5ee0beSSteven Rostedt while (<IN>) { 10336c5ee0beSSteven Rostedt if (/^\s*(.*?):.*(warning|error)/) { 10346c5ee0beSSteven Rostedt my $err = $1; 10356c5ee0beSSteven Rostedt foreach my $file (@files) { 1036a75fececSSteven Rostedt my $fullpath = "$builddir/$file"; 10376c5ee0beSSteven Rostedt if ($file eq $err || $fullpath eq $err) { 10382b7d9b21SSteven Rostedt fail "$file built with warnings" and return 0; 10396c5ee0beSSteven Rostedt } 10406c5ee0beSSteven Rostedt } 10416c5ee0beSSteven Rostedt } 10426c5ee0beSSteven Rostedt } 10436c5ee0beSSteven Rostedt close(IN); 10442b7d9b21SSteven Rostedt 10452b7d9b21SSteven Rostedt return 1; 10466c5ee0beSSteven Rostedt} 10476c5ee0beSSteven Rostedt 1048*fcb3f16aSSteven Rostedtsub apply_min_config { 1049*fcb3f16aSSteven Rostedt my $outconfig = "$output_config.new"; 1050612b9e9bSSteven Rostedt 1051*fcb3f16aSSteven Rostedt # Read the config file and remove anything that 1052*fcb3f16aSSteven Rostedt # is in the force_config hash (from minconfig and others) 1053*fcb3f16aSSteven Rostedt # then add the force config back. 1054*fcb3f16aSSteven Rostedt 1055*fcb3f16aSSteven Rostedt doprint "Applying minimum configurations into $output_config.new\n"; 1056*fcb3f16aSSteven Rostedt 1057*fcb3f16aSSteven Rostedt open (OUT, ">$outconfig") or 1058*fcb3f16aSSteven Rostedt dodie "Can't create $outconfig"; 1059*fcb3f16aSSteven Rostedt 1060*fcb3f16aSSteven Rostedt if (-f $output_config) { 1061*fcb3f16aSSteven Rostedt open (IN, $output_config) or 1062*fcb3f16aSSteven Rostedt dodie "Failed to open $output_config"; 1063*fcb3f16aSSteven Rostedt while (<IN>) { 1064*fcb3f16aSSteven Rostedt if (/^(# )?(CONFIG_[^\s=]*)/) { 1065*fcb3f16aSSteven Rostedt next if (defined($force_config{$2})); 1066*fcb3f16aSSteven Rostedt } 1067*fcb3f16aSSteven Rostedt print OUT; 1068*fcb3f16aSSteven Rostedt } 1069*fcb3f16aSSteven Rostedt close IN; 1070*fcb3f16aSSteven Rostedt } 1071*fcb3f16aSSteven Rostedt foreach my $config (keys %force_config) { 1072*fcb3f16aSSteven Rostedt print OUT "$force_config{$config}\n"; 1073*fcb3f16aSSteven Rostedt } 1074*fcb3f16aSSteven Rostedt close OUT; 1075*fcb3f16aSSteven Rostedt 1076*fcb3f16aSSteven Rostedt run_command "mv $outconfig $output_config"; 1077*fcb3f16aSSteven Rostedt} 1078*fcb3f16aSSteven Rostedt 1079*fcb3f16aSSteven Rostedtsub make_oldconfig { 1080*fcb3f16aSSteven Rostedt 1081*fcb3f16aSSteven Rostedt apply_min_config; 1082*fcb3f16aSSteven Rostedt 1083*fcb3f16aSSteven Rostedt if (!run_command "$make oldnoconfig") { 1084612b9e9bSSteven Rostedt # Perhaps oldnoconfig doesn't exist in this version of the kernel 1085612b9e9bSSteven Rostedt # try a yes '' | oldconfig 1086612b9e9bSSteven Rostedt doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 1087*fcb3f16aSSteven Rostedt run_command "yes '' | $make oldconfig" or 1088612b9e9bSSteven Rostedt dodie "failed make config oldconfig"; 1089612b9e9bSSteven Rostedt } 1090612b9e9bSSteven Rostedt} 1091612b9e9bSSteven Rostedt 1092*fcb3f16aSSteven Rostedt# read a config file and use this to force new configs. 1093*fcb3f16aSSteven Rostedtsub load_force_config { 1094*fcb3f16aSSteven Rostedt my ($config) = @_; 1095*fcb3f16aSSteven Rostedt 1096*fcb3f16aSSteven Rostedt open(IN, $config) or 1097*fcb3f16aSSteven Rostedt dodie "failed to read $config"; 1098*fcb3f16aSSteven Rostedt while (<IN>) { 1099*fcb3f16aSSteven Rostedt chomp; 1100*fcb3f16aSSteven Rostedt if (/^(CONFIG[^\s=]*)(\s*=.*)/) { 1101*fcb3f16aSSteven Rostedt $force_config{$1} = $_; 1102*fcb3f16aSSteven Rostedt } elsif (/^# (CONFIG_\S*) is not set/) { 1103*fcb3f16aSSteven Rostedt $force_config{$1} = $_; 1104*fcb3f16aSSteven Rostedt } 1105*fcb3f16aSSteven Rostedt } 1106*fcb3f16aSSteven Rostedt close IN; 1107*fcb3f16aSSteven Rostedt} 1108*fcb3f16aSSteven Rostedt 11092545eb61SSteven Rostedtsub build { 11102545eb61SSteven Rostedt my ($type) = @_; 11112545eb61SSteven Rostedt 11127faafbd6SSteven Rostedt unlink $buildlog; 11137faafbd6SSteven Rostedt 111475c3fda7SSteven Rostedt if ($type =~ /^useconfig:(.*)/) { 111551ad1dd1SSteven Rostedt run_command "cp $1 $output_config" or 111675c3fda7SSteven Rostedt dodie "could not copy $1 to .config"; 11175f9b6cedSSteven Rostedt 111875c3fda7SSteven Rostedt $type = "oldconfig"; 111975c3fda7SSteven Rostedt } 112075c3fda7SSteven Rostedt 11215c42fc5bSSteven Rostedt # old config can ask questions 11225c42fc5bSSteven Rostedt if ($type eq "oldconfig") { 11239386c6abSSteven Rostedt $type = "oldnoconfig"; 112475c3fda7SSteven Rostedt 112575c3fda7SSteven Rostedt # allow for empty configs 112651ad1dd1SSteven Rostedt run_command "touch $output_config"; 112775c3fda7SSteven Rostedt 112851ad1dd1SSteven Rostedt run_command "mv $output_config $outputdir/config_temp" or 11295c42fc5bSSteven Rostedt dodie "moving .config"; 11305c42fc5bSSteven Rostedt 11315f9b6cedSSteven Rostedt if (!$noclean && !run_command "$make mrproper") { 11325c42fc5bSSteven Rostedt dodie "make mrproper"; 11335c42fc5bSSteven Rostedt } 11345c42fc5bSSteven Rostedt 113551ad1dd1SSteven Rostedt run_command "mv $outputdir/config_temp $output_config" or 11365c42fc5bSSteven Rostedt dodie "moving config_temp"; 11375c42fc5bSSteven Rostedt 11385c42fc5bSSteven Rostedt } elsif (!$noclean) { 113951ad1dd1SSteven Rostedt unlink "$output_config"; 11405f9b6cedSSteven Rostedt run_command "$make mrproper" or 11415c42fc5bSSteven Rostedt dodie "make mrproper"; 11425c42fc5bSSteven Rostedt } 11432545eb61SSteven Rostedt 11442545eb61SSteven Rostedt # add something to distinguish this build 1145a75fececSSteven Rostedt open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 1146a75fececSSteven Rostedt print OUT "$localversion\n"; 11472545eb61SSteven Rostedt close(OUT); 11482545eb61SSteven Rostedt 11495f9b6cedSSteven Rostedt if (defined($minconfig)) { 1150*fcb3f16aSSteven Rostedt load_force_config($minconfig); 11512545eb61SSteven Rostedt } 11522545eb61SSteven Rostedt 1153*fcb3f16aSSteven Rostedt if ($type ne "oldnoconfig") { 1154*fcb3f16aSSteven Rostedt run_command "$make $type" or 11555c42fc5bSSteven Rostedt dodie "failed make config"; 1156612b9e9bSSteven Rostedt } 1157*fcb3f16aSSteven Rostedt # Run old config regardless, to enforce min configurations 1158*fcb3f16aSSteven Rostedt make_oldconfig; 11592545eb61SSteven Rostedt 1160a75fececSSteven Rostedt $redirect = "$buildlog"; 1161a75fececSSteven Rostedt if (!run_command "$make $build_options") { 11626c5ee0beSSteven Rostedt undef $redirect; 11635f9b6cedSSteven Rostedt # bisect may need this to pass 11642b7d9b21SSteven Rostedt return 0 if ($in_bisect); 11652b7d9b21SSteven Rostedt fail "failed build" and return 0; 11662545eb61SSteven Rostedt } 11676c5ee0beSSteven Rostedt undef $redirect; 11685f9b6cedSSteven Rostedt 11692b7d9b21SSteven Rostedt return 1; 11702545eb61SSteven Rostedt} 11712545eb61SSteven Rostedt 117275c3fda7SSteven Rostedtsub halt { 1173e48c5293SSteven Rostedt if (!run_ssh "halt" or defined($power_off)) { 1174576f627cSSteven Rostedt if (defined($poweroff_after_halt)) { 1175576f627cSSteven Rostedt sleep $poweroff_after_halt; 1176576f627cSSteven Rostedt run_command "$power_off"; 1177576f627cSSteven Rostedt } 1178576f627cSSteven Rostedt } else { 117975c3fda7SSteven Rostedt # nope? the zap it! 1180a75fececSSteven Rostedt run_command "$power_off"; 118175c3fda7SSteven Rostedt } 118275c3fda7SSteven Rostedt} 118375c3fda7SSteven Rostedt 11845f9b6cedSSteven Rostedtsub success { 11855f9b6cedSSteven Rostedt my ($i) = @_; 11865f9b6cedSSteven Rostedt 1187e48c5293SSteven Rostedt $successes++; 1188e48c5293SSteven Rostedt 11899064af52SSteven Rostedt my $name = ""; 11909064af52SSteven Rostedt 11919064af52SSteven Rostedt if (defined($test_name)) { 11929064af52SSteven Rostedt $name = " ($test_name)"; 11939064af52SSteven Rostedt } 11949064af52SSteven Rostedt 11955f9b6cedSSteven Rostedt doprint "\n\n*******************************************\n"; 11965f9b6cedSSteven Rostedt doprint "*******************************************\n"; 11979064af52SSteven Rostedt doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; 11985f9b6cedSSteven Rostedt doprint "*******************************************\n"; 11995f9b6cedSSteven Rostedt doprint "*******************************************\n"; 12005f9b6cedSSteven Rostedt 1201576f627cSSteven Rostedt if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 1202a75fececSSteven Rostedt doprint "Reboot and wait $sleep_time seconds\n"; 12035f9b6cedSSteven Rostedt reboot; 12047faafbd6SSteven Rostedt start_monitor; 1205a75fececSSteven Rostedt wait_for_monitor $sleep_time; 12067faafbd6SSteven Rostedt end_monitor; 12075f9b6cedSSteven Rostedt } 12085f9b6cedSSteven Rostedt} 12095f9b6cedSSteven Rostedt 12105f9b6cedSSteven Rostedtsub get_version { 12115f9b6cedSSteven Rostedt # get the release name 12125f9b6cedSSteven Rostedt doprint "$make kernelrelease ... "; 12135f9b6cedSSteven Rostedt $version = `$make kernelrelease | tail -1`; 12145f9b6cedSSteven Rostedt chomp($version); 12155f9b6cedSSteven Rostedt doprint "$version\n"; 12165f9b6cedSSteven Rostedt} 12175f9b6cedSSteven Rostedt 1218c960bb9fSSteven Rostedtsub answer_bisect { 1219c960bb9fSSteven Rostedt for (;;) { 1220c960bb9fSSteven Rostedt doprint "Pass or fail? [p/f]"; 1221c960bb9fSSteven Rostedt my $ans = <STDIN>; 1222c960bb9fSSteven Rostedt chomp $ans; 1223c960bb9fSSteven Rostedt if ($ans eq "p" || $ans eq "P") { 1224c960bb9fSSteven Rostedt return 1; 1225c960bb9fSSteven Rostedt } elsif ($ans eq "f" || $ans eq "F") { 1226c960bb9fSSteven Rostedt return 0; 1227c960bb9fSSteven Rostedt } else { 1228c960bb9fSSteven Rostedt print "Please answer 'P' or 'F'\n"; 1229c960bb9fSSteven Rostedt } 1230c960bb9fSSteven Rostedt } 1231c960bb9fSSteven Rostedt} 1232c960bb9fSSteven Rostedt 12335a391fbfSSteven Rostedtsub child_run_test { 12347faafbd6SSteven Rostedt my $failed = 0; 12355a391fbfSSteven Rostedt 12367faafbd6SSteven Rostedt # child should have no power 1237a75fececSSteven Rostedt $reboot_on_error = 0; 1238a75fececSSteven Rostedt $poweroff_on_error = 0; 1239a75fececSSteven Rostedt $die_on_failure = 1; 12407faafbd6SSteven Rostedt 12417faafbd6SSteven Rostedt run_command $run_test or $failed = 1; 12425a391fbfSSteven Rostedt exit $failed; 12435a391fbfSSteven Rostedt} 12445a391fbfSSteven Rostedt 12455a391fbfSSteven Rostedtmy $child_done; 12465a391fbfSSteven Rostedt 12475a391fbfSSteven Rostedtsub child_finished { 12485a391fbfSSteven Rostedt $child_done = 1; 12495a391fbfSSteven Rostedt} 12505a391fbfSSteven Rostedt 12515a391fbfSSteven Rostedtsub do_run_test { 12525a391fbfSSteven Rostedt my $child_pid; 12535a391fbfSSteven Rostedt my $child_exit; 12545a391fbfSSteven Rostedt my $line; 12555a391fbfSSteven Rostedt my $full_line; 12565a391fbfSSteven Rostedt my $bug = 0; 12575a391fbfSSteven Rostedt 12587faafbd6SSteven Rostedt wait_for_monitor 1; 12595a391fbfSSteven Rostedt 12607faafbd6SSteven Rostedt doprint "run test $run_test\n"; 12615a391fbfSSteven Rostedt 12625a391fbfSSteven Rostedt $child_done = 0; 12635a391fbfSSteven Rostedt 12645a391fbfSSteven Rostedt $SIG{CHLD} = qw(child_finished); 12655a391fbfSSteven Rostedt 12665a391fbfSSteven Rostedt $child_pid = fork; 12675a391fbfSSteven Rostedt 12685a391fbfSSteven Rostedt child_run_test if (!$child_pid); 12695a391fbfSSteven Rostedt 12705a391fbfSSteven Rostedt $full_line = ""; 12715a391fbfSSteven Rostedt 12725a391fbfSSteven Rostedt do { 12737faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 12745a391fbfSSteven Rostedt if (defined($line)) { 12755a391fbfSSteven Rostedt 12765a391fbfSSteven Rostedt # we are not guaranteed to get a full line 12775a391fbfSSteven Rostedt $full_line .= $line; 12788ea0e063SSteven Rostedt doprint $line; 12795a391fbfSSteven Rostedt 12805a391fbfSSteven Rostedt if ($full_line =~ /call trace:/i) { 12815a391fbfSSteven Rostedt $bug = 1; 12825a391fbfSSteven Rostedt } 12835a391fbfSSteven Rostedt 12845a391fbfSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 12855a391fbfSSteven Rostedt $bug = 1; 12865a391fbfSSteven Rostedt } 12875a391fbfSSteven Rostedt 12885a391fbfSSteven Rostedt if ($line =~ /\n/) { 12895a391fbfSSteven Rostedt $full_line = ""; 12905a391fbfSSteven Rostedt } 12915a391fbfSSteven Rostedt } 12925a391fbfSSteven Rostedt } while (!$child_done && !$bug); 12935a391fbfSSteven Rostedt 12945a391fbfSSteven Rostedt if ($bug) { 12958ea0e063SSteven Rostedt my $failure_start = time; 12968ea0e063SSteven Rostedt my $now; 12978ea0e063SSteven Rostedt do { 12988ea0e063SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 12998ea0e063SSteven Rostedt if (defined($line)) { 13008ea0e063SSteven Rostedt doprint $line; 13018ea0e063SSteven Rostedt } 13028ea0e063SSteven Rostedt $now = time; 13038ea0e063SSteven Rostedt if ($now - $failure_start >= $stop_after_failure) { 13048ea0e063SSteven Rostedt last; 13058ea0e063SSteven Rostedt } 13068ea0e063SSteven Rostedt } while (defined($line)); 13078ea0e063SSteven Rostedt 13085a391fbfSSteven Rostedt doprint "Detected kernel crash!\n"; 13095a391fbfSSteven Rostedt # kill the child with extreme prejudice 13105a391fbfSSteven Rostedt kill 9, $child_pid; 13115a391fbfSSteven Rostedt } 13125a391fbfSSteven Rostedt 13135a391fbfSSteven Rostedt waitpid $child_pid, 0; 13145a391fbfSSteven Rostedt $child_exit = $?; 13155a391fbfSSteven Rostedt 13165a391fbfSSteven Rostedt if ($bug || $child_exit) { 13172b7d9b21SSteven Rostedt return 0 if $in_bisect; 13182b7d9b21SSteven Rostedt fail "test failed" and return 0; 13195a391fbfSSteven Rostedt } 13202b7d9b21SSteven Rostedt return 1; 13215a391fbfSSteven Rostedt} 13225a391fbfSSteven Rostedt 1323a75fececSSteven Rostedtsub run_git_bisect { 1324a75fececSSteven Rostedt my ($command) = @_; 1325a75fececSSteven Rostedt 1326a75fececSSteven Rostedt doprint "$command ... "; 1327a75fececSSteven Rostedt 1328a75fececSSteven Rostedt my $output = `$command 2>&1`; 1329a75fececSSteven Rostedt my $ret = $?; 1330a75fececSSteven Rostedt 1331a75fececSSteven Rostedt logit $output; 1332a75fececSSteven Rostedt 1333a75fececSSteven Rostedt if ($ret) { 1334a75fececSSteven Rostedt doprint "FAILED\n"; 1335a75fececSSteven Rostedt dodie "Failed to git bisect"; 1336a75fececSSteven Rostedt } 1337a75fececSSteven Rostedt 1338a75fececSSteven Rostedt doprint "SUCCESS\n"; 1339a75fececSSteven Rostedt if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 1340a75fececSSteven Rostedt doprint "$1 [$2]\n"; 1341a75fececSSteven Rostedt } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 1342a75fececSSteven Rostedt $bisect_bad = $1; 1343a75fececSSteven Rostedt doprint "Found bad commit... $1\n"; 1344a75fececSSteven Rostedt return 0; 1345a75fececSSteven Rostedt } else { 1346a75fececSSteven Rostedt # we already logged it, just print it now. 1347a75fececSSteven Rostedt print $output; 1348a75fececSSteven Rostedt } 1349a75fececSSteven Rostedt 1350a75fececSSteven Rostedt return 1; 1351a75fececSSteven Rostedt} 1352a75fececSSteven Rostedt 1353c23dca7cSSteven Rostedtsub bisect_reboot { 1354c23dca7cSSteven Rostedt doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 1355c23dca7cSSteven Rostedt reboot; 1356c23dca7cSSteven Rostedt start_monitor; 1357c23dca7cSSteven Rostedt wait_for_monitor $bisect_sleep_time; 1358c23dca7cSSteven Rostedt end_monitor; 1359c23dca7cSSteven Rostedt} 1360c23dca7cSSteven Rostedt 1361c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip 13620a05c769SSteven Rostedtsub run_bisect_test { 13630a05c769SSteven Rostedt my ($type, $buildtype) = @_; 13645f9b6cedSSteven Rostedt 13652b7d9b21SSteven Rostedt my $failed = 0; 13665f9b6cedSSteven Rostedt my $result; 13675f9b6cedSSteven Rostedt my $output; 13685f9b6cedSSteven Rostedt my $ret; 13695f9b6cedSSteven Rostedt 13700a05c769SSteven Rostedt $in_bisect = 1; 13710a05c769SSteven Rostedt 13720a05c769SSteven Rostedt build $buildtype or $failed = 1; 13735f9b6cedSSteven Rostedt 13745f9b6cedSSteven Rostedt if ($type ne "build") { 1375c23dca7cSSteven Rostedt if ($failed && $bisect_skip) { 1376c23dca7cSSteven Rostedt $in_bisect = 0; 1377c23dca7cSSteven Rostedt return -1; 1378c23dca7cSSteven Rostedt } 13797faafbd6SSteven Rostedt dodie "Failed on build" if $failed; 13805f9b6cedSSteven Rostedt 13815f9b6cedSSteven Rostedt # Now boot the box 13825f9b6cedSSteven Rostedt get_grub_index; 13835f9b6cedSSteven Rostedt get_version; 13845f9b6cedSSteven Rostedt install; 13857faafbd6SSteven Rostedt 13867faafbd6SSteven Rostedt start_monitor; 13872b7d9b21SSteven Rostedt monitor or $failed = 1; 13885f9b6cedSSteven Rostedt 13895f9b6cedSSteven Rostedt if ($type ne "boot") { 1390c23dca7cSSteven Rostedt if ($failed && $bisect_skip) { 1391c23dca7cSSteven Rostedt end_monitor; 1392c23dca7cSSteven Rostedt bisect_reboot; 1393c23dca7cSSteven Rostedt $in_bisect = 0; 1394c23dca7cSSteven Rostedt return -1; 1395c23dca7cSSteven Rostedt } 13967faafbd6SSteven Rostedt dodie "Failed on boot" if $failed; 13975a391fbfSSteven Rostedt 13982b7d9b21SSteven Rostedt do_run_test or $failed = 1; 13995f9b6cedSSteven Rostedt } 14007faafbd6SSteven Rostedt end_monitor; 14015f9b6cedSSteven Rostedt } 14025f9b6cedSSteven Rostedt 14035f9b6cedSSteven Rostedt if ($failed) { 14040a05c769SSteven Rostedt $result = 0; 14055f9b6cedSSteven Rostedt } else { 14060a05c769SSteven Rostedt $result = 1; 14075f9b6cedSSteven Rostedt } 14084025bc62SSteven Rostedt 14094025bc62SSteven Rostedt # reboot the box to a kernel we can ssh to 14104025bc62SSteven Rostedt if ($type ne "build") { 14114025bc62SSteven Rostedt bisect_reboot; 14124025bc62SSteven Rostedt } 14130a05c769SSteven Rostedt $in_bisect = 0; 14140a05c769SSteven Rostedt 14150a05c769SSteven Rostedt return $result; 14160a05c769SSteven Rostedt} 14170a05c769SSteven Rostedt 14180a05c769SSteven Rostedtsub run_bisect { 14190a05c769SSteven Rostedt my ($type) = @_; 14200a05c769SSteven Rostedt my $buildtype = "oldconfig"; 14210a05c769SSteven Rostedt 14220a05c769SSteven Rostedt # We should have a minconfig to use? 14230a05c769SSteven Rostedt if (defined($minconfig)) { 14240a05c769SSteven Rostedt $buildtype = "useconfig:$minconfig"; 14250a05c769SSteven Rostedt } 14260a05c769SSteven Rostedt 14270a05c769SSteven Rostedt my $ret = run_bisect_test $type, $buildtype; 14280a05c769SSteven Rostedt 1429c960bb9fSSteven Rostedt if ($bisect_manual) { 1430c960bb9fSSteven Rostedt $ret = answer_bisect; 1431c960bb9fSSteven Rostedt } 14325f9b6cedSSteven Rostedt 1433d6ce2a0bSSteven Rostedt # Are we looking for where it worked, not failed? 1434d6ce2a0bSSteven Rostedt if ($reverse_bisect) { 14350a05c769SSteven Rostedt $ret = !$ret; 1436d6ce2a0bSSteven Rostedt } 1437d6ce2a0bSSteven Rostedt 1438c23dca7cSSteven Rostedt if ($ret > 0) { 14390a05c769SSteven Rostedt return "good"; 1440c23dca7cSSteven Rostedt } elsif ($ret == 0) { 14410a05c769SSteven Rostedt return "bad"; 1442c23dca7cSSteven Rostedt } elsif ($bisect_skip) { 1443c23dca7cSSteven Rostedt doprint "HIT A BAD COMMIT ... SKIPPING\n"; 1444c23dca7cSSteven Rostedt return "skip"; 14450a05c769SSteven Rostedt } 14465f9b6cedSSteven Rostedt} 14475f9b6cedSSteven Rostedt 14485f9b6cedSSteven Rostedtsub bisect { 14495f9b6cedSSteven Rostedt my ($i) = @_; 14505f9b6cedSSteven Rostedt 14515f9b6cedSSteven Rostedt my $result; 14525f9b6cedSSteven Rostedt 14535f9b6cedSSteven Rostedt die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 14545f9b6cedSSteven Rostedt die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 14555f9b6cedSSteven Rostedt die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 14565f9b6cedSSteven Rostedt 14575f9b6cedSSteven Rostedt my $good = $opt{"BISECT_GOOD[$i]"}; 14585f9b6cedSSteven Rostedt my $bad = $opt{"BISECT_BAD[$i]"}; 14595f9b6cedSSteven Rostedt my $type = $opt{"BISECT_TYPE[$i]"}; 1460a75fececSSteven Rostedt my $start = $opt{"BISECT_START[$i]"}; 1461a75fececSSteven Rostedt my $replay = $opt{"BISECT_REPLAY[$i]"}; 14623410f6fdSSteven Rostedt my $start_files = $opt{"BISECT_FILES[$i]"}; 14633410f6fdSSteven Rostedt 14643410f6fdSSteven Rostedt if (defined($start_files)) { 14653410f6fdSSteven Rostedt $start_files = " -- " . $start_files; 14663410f6fdSSteven Rostedt } else { 14673410f6fdSSteven Rostedt $start_files = ""; 14683410f6fdSSteven Rostedt } 14695f9b6cedSSteven Rostedt 1470a57419b3SSteven Rostedt # convert to true sha1's 1471a57419b3SSteven Rostedt $good = get_sha1($good); 1472a57419b3SSteven Rostedt $bad = get_sha1($bad); 1473a57419b3SSteven Rostedt 1474d6ce2a0bSSteven Rostedt if (defined($opt{"BISECT_REVERSE[$i]"}) && 1475d6ce2a0bSSteven Rostedt $opt{"BISECT_REVERSE[$i]"} == 1) { 1476d6ce2a0bSSteven Rostedt doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 1477d6ce2a0bSSteven Rostedt $reverse_bisect = 1; 1478d6ce2a0bSSteven Rostedt } else { 1479d6ce2a0bSSteven Rostedt $reverse_bisect = 0; 1480d6ce2a0bSSteven Rostedt } 1481d6ce2a0bSSteven Rostedt 14825a391fbfSSteven Rostedt # Can't have a test without having a test to run 14835a391fbfSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 14845a391fbfSSteven Rostedt $type = "boot"; 14855a391fbfSSteven Rostedt } 14865a391fbfSSteven Rostedt 1487a75fececSSteven Rostedt my $check = $opt{"BISECT_CHECK[$i]"}; 1488a75fececSSteven Rostedt if (defined($check) && $check ne "0") { 1489a75fececSSteven Rostedt 1490a75fececSSteven Rostedt # get current HEAD 1491a57419b3SSteven Rostedt my $head = get_sha1("HEAD"); 1492a75fececSSteven Rostedt 1493a75fececSSteven Rostedt if ($check ne "good") { 1494a75fececSSteven Rostedt doprint "TESTING BISECT BAD [$bad]\n"; 1495a75fececSSteven Rostedt run_command "git checkout $bad" or 1496a75fececSSteven Rostedt die "Failed to checkout $bad"; 1497a75fececSSteven Rostedt 1498a75fececSSteven Rostedt $result = run_bisect $type; 1499a75fececSSteven Rostedt 1500a75fececSSteven Rostedt if ($result ne "bad") { 1501a75fececSSteven Rostedt fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 1502a75fececSSteven Rostedt } 1503a75fececSSteven Rostedt } 1504a75fececSSteven Rostedt 1505a75fececSSteven Rostedt if ($check ne "bad") { 1506a75fececSSteven Rostedt doprint "TESTING BISECT GOOD [$good]\n"; 1507a75fececSSteven Rostedt run_command "git checkout $good" or 1508a75fececSSteven Rostedt die "Failed to checkout $good"; 1509a75fececSSteven Rostedt 1510a75fececSSteven Rostedt $result = run_bisect $type; 1511a75fececSSteven Rostedt 1512a75fececSSteven Rostedt if ($result ne "good") { 1513a75fececSSteven Rostedt fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 1514a75fececSSteven Rostedt } 1515a75fececSSteven Rostedt } 1516a75fececSSteven Rostedt 1517a75fececSSteven Rostedt # checkout where we started 1518a75fececSSteven Rostedt run_command "git checkout $head" or 1519a75fececSSteven Rostedt die "Failed to checkout $head"; 1520a75fececSSteven Rostedt } 1521a75fececSSteven Rostedt 15223410f6fdSSteven Rostedt run_command "git bisect start$start_files" or 1523a75fececSSteven Rostedt dodie "could not start bisect"; 1524a75fececSSteven Rostedt 1525a75fececSSteven Rostedt run_command "git bisect good $good" or 1526a75fececSSteven Rostedt dodie "could not set bisect good to $good"; 1527a75fececSSteven Rostedt 1528a75fececSSteven Rostedt run_git_bisect "git bisect bad $bad" or 1529a75fececSSteven Rostedt dodie "could not set bisect bad to $bad"; 1530a75fececSSteven Rostedt 1531a75fececSSteven Rostedt if (defined($replay)) { 1532a75fececSSteven Rostedt run_command "git bisect replay $replay" or 1533a75fececSSteven Rostedt dodie "failed to run replay"; 1534a75fececSSteven Rostedt } 1535a75fececSSteven Rostedt 1536a75fececSSteven Rostedt if (defined($start)) { 1537a75fececSSteven Rostedt run_command "git checkout $start" or 1538a75fececSSteven Rostedt dodie "failed to checkout $start"; 1539a75fececSSteven Rostedt } 1540a75fececSSteven Rostedt 1541a75fececSSteven Rostedt my $test; 15425f9b6cedSSteven Rostedt do { 15435f9b6cedSSteven Rostedt $result = run_bisect $type; 1544a75fececSSteven Rostedt $test = run_git_bisect "git bisect $result"; 1545a75fececSSteven Rostedt } while ($test); 15465f9b6cedSSteven Rostedt 15475f9b6cedSSteven Rostedt run_command "git bisect log" or 15485f9b6cedSSteven Rostedt dodie "could not capture git bisect log"; 15495f9b6cedSSteven Rostedt 15505f9b6cedSSteven Rostedt run_command "git bisect reset" or 15515f9b6cedSSteven Rostedt dodie "could not reset git bisect"; 15525f9b6cedSSteven Rostedt 15535f9b6cedSSteven Rostedt doprint "Bad commit was [$bisect_bad]\n"; 15545f9b6cedSSteven Rostedt 15550a05c769SSteven Rostedt success $i; 15560a05c769SSteven Rostedt} 15570a05c769SSteven Rostedt 15580a05c769SSteven Rostedtmy %config_ignore; 15590a05c769SSteven Rostedtmy %config_set; 15600a05c769SSteven Rostedt 15610a05c769SSteven Rostedtmy %config_list; 15620a05c769SSteven Rostedtmy %null_config; 15630a05c769SSteven Rostedt 15640a05c769SSteven Rostedtmy %dependency; 15650a05c769SSteven Rostedt 15660a05c769SSteven Rostedtsub process_config_ignore { 15670a05c769SSteven Rostedt my ($config) = @_; 15680a05c769SSteven Rostedt 15690a05c769SSteven Rostedt open (IN, $config) 15700a05c769SSteven Rostedt or dodie "Failed to read $config"; 15710a05c769SSteven Rostedt 15720a05c769SSteven Rostedt while (<IN>) { 15739bf71749SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 15740a05c769SSteven Rostedt $config_ignore{$2} = $1; 15750a05c769SSteven Rostedt } 15760a05c769SSteven Rostedt } 15770a05c769SSteven Rostedt 15780a05c769SSteven Rostedt close(IN); 15790a05c769SSteven Rostedt} 15800a05c769SSteven Rostedt 15810a05c769SSteven Rostedtsub read_current_config { 15820a05c769SSteven Rostedt my ($config_ref) = @_; 15830a05c769SSteven Rostedt 15840a05c769SSteven Rostedt %{$config_ref} = (); 15850a05c769SSteven Rostedt undef %{$config_ref}; 15860a05c769SSteven Rostedt 15870a05c769SSteven Rostedt my @key = keys %{$config_ref}; 15880a05c769SSteven Rostedt if ($#key >= 0) { 15890a05c769SSteven Rostedt print "did not delete!\n"; 15900a05c769SSteven Rostedt exit; 15910a05c769SSteven Rostedt } 15920a05c769SSteven Rostedt open (IN, "$output_config"); 15930a05c769SSteven Rostedt 15940a05c769SSteven Rostedt while (<IN>) { 15950a05c769SSteven Rostedt if (/^(CONFIG\S+)=(.*)/) { 15960a05c769SSteven Rostedt ${$config_ref}{$1} = $2; 15970a05c769SSteven Rostedt } 15980a05c769SSteven Rostedt } 15990a05c769SSteven Rostedt close(IN); 16000a05c769SSteven Rostedt} 16010a05c769SSteven Rostedt 16020a05c769SSteven Rostedtsub get_dependencies { 16030a05c769SSteven Rostedt my ($config) = @_; 16040a05c769SSteven Rostedt 16050a05c769SSteven Rostedt my $arr = $dependency{$config}; 16060a05c769SSteven Rostedt if (!defined($arr)) { 16070a05c769SSteven Rostedt return (); 16080a05c769SSteven Rostedt } 16090a05c769SSteven Rostedt 16100a05c769SSteven Rostedt my @deps = @{$arr}; 16110a05c769SSteven Rostedt 16120a05c769SSteven Rostedt foreach my $dep (@{$arr}) { 16130a05c769SSteven Rostedt print "ADD DEP $dep\n"; 16140a05c769SSteven Rostedt @deps = (@deps, get_dependencies $dep); 16150a05c769SSteven Rostedt } 16160a05c769SSteven Rostedt 16170a05c769SSteven Rostedt return @deps; 16180a05c769SSteven Rostedt} 16190a05c769SSteven Rostedt 16200a05c769SSteven Rostedtsub create_config { 16210a05c769SSteven Rostedt my @configs = @_; 16220a05c769SSteven Rostedt 16230a05c769SSteven Rostedt open(OUT, ">$output_config") or dodie "Can not write to $output_config"; 16240a05c769SSteven Rostedt 16250a05c769SSteven Rostedt foreach my $config (@configs) { 16260a05c769SSteven Rostedt print OUT "$config_set{$config}\n"; 16270a05c769SSteven Rostedt my @deps = get_dependencies $config; 16280a05c769SSteven Rostedt foreach my $dep (@deps) { 16290a05c769SSteven Rostedt print OUT "$config_set{$dep}\n"; 16300a05c769SSteven Rostedt } 16310a05c769SSteven Rostedt } 16320a05c769SSteven Rostedt 16330a05c769SSteven Rostedt foreach my $config (keys %config_ignore) { 16340a05c769SSteven Rostedt print OUT "$config_ignore{$config}\n"; 16350a05c769SSteven Rostedt } 16360a05c769SSteven Rostedt close(OUT); 16370a05c769SSteven Rostedt 16380a05c769SSteven Rostedt# exit; 1639*fcb3f16aSSteven Rostedt make_oldconfig; 16400a05c769SSteven Rostedt} 16410a05c769SSteven Rostedt 16420a05c769SSteven Rostedtsub compare_configs { 16430a05c769SSteven Rostedt my (%a, %b) = @_; 16440a05c769SSteven Rostedt 16450a05c769SSteven Rostedt foreach my $item (keys %a) { 16460a05c769SSteven Rostedt if (!defined($b{$item})) { 16470a05c769SSteven Rostedt print "diff $item\n"; 16480a05c769SSteven Rostedt return 1; 16490a05c769SSteven Rostedt } 16500a05c769SSteven Rostedt delete $b{$item}; 16510a05c769SSteven Rostedt } 16520a05c769SSteven Rostedt 16530a05c769SSteven Rostedt my @keys = keys %b; 16540a05c769SSteven Rostedt if ($#keys) { 16550a05c769SSteven Rostedt print "diff2 $keys[0]\n"; 16560a05c769SSteven Rostedt } 16570a05c769SSteven Rostedt return -1 if ($#keys >= 0); 16580a05c769SSteven Rostedt 16590a05c769SSteven Rostedt return 0; 16600a05c769SSteven Rostedt} 16610a05c769SSteven Rostedt 16620a05c769SSteven Rostedtsub run_config_bisect_test { 16630a05c769SSteven Rostedt my ($type) = @_; 16640a05c769SSteven Rostedt 16650a05c769SSteven Rostedt return run_bisect_test $type, "oldconfig"; 16660a05c769SSteven Rostedt} 16670a05c769SSteven Rostedt 16680a05c769SSteven Rostedtsub process_passed { 16690a05c769SSteven Rostedt my (%configs) = @_; 16700a05c769SSteven Rostedt 16710a05c769SSteven Rostedt doprint "These configs had no failure: (Enabling them for further compiles)\n"; 16720a05c769SSteven Rostedt # Passed! All these configs are part of a good compile. 16730a05c769SSteven Rostedt # Add them to the min options. 16740a05c769SSteven Rostedt foreach my $config (keys %configs) { 16750a05c769SSteven Rostedt if (defined($config_list{$config})) { 16760a05c769SSteven Rostedt doprint " removing $config\n"; 16770a05c769SSteven Rostedt $config_ignore{$config} = $config_list{$config}; 16780a05c769SSteven Rostedt delete $config_list{$config}; 16790a05c769SSteven Rostedt } 16800a05c769SSteven Rostedt } 1681f1a27850SSteven Rostedt doprint "config copied to $outputdir/config_good\n"; 1682f1a27850SSteven Rostedt run_command "cp -f $output_config $outputdir/config_good"; 16830a05c769SSteven Rostedt} 16840a05c769SSteven Rostedt 16850a05c769SSteven Rostedtsub process_failed { 16860a05c769SSteven Rostedt my ($config) = @_; 16870a05c769SSteven Rostedt 16880a05c769SSteven Rostedt doprint "\n\n***************************************\n"; 16890a05c769SSteven Rostedt doprint "Found bad config: $config\n"; 16900a05c769SSteven Rostedt doprint "***************************************\n\n"; 16910a05c769SSteven Rostedt} 16920a05c769SSteven Rostedt 16930a05c769SSteven Rostedtsub run_config_bisect { 16940a05c769SSteven Rostedt 16950a05c769SSteven Rostedt my @start_list = keys %config_list; 16960a05c769SSteven Rostedt 16970a05c769SSteven Rostedt if ($#start_list < 0) { 16980a05c769SSteven Rostedt doprint "No more configs to test!!!\n"; 16990a05c769SSteven Rostedt return -1; 17000a05c769SSteven Rostedt } 17010a05c769SSteven Rostedt 17020a05c769SSteven Rostedt doprint "***** RUN TEST ***\n"; 17030a05c769SSteven Rostedt my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"}; 17040a05c769SSteven Rostedt my $ret; 17050a05c769SSteven Rostedt my %current_config; 17060a05c769SSteven Rostedt 17070a05c769SSteven Rostedt my $count = $#start_list + 1; 17080a05c769SSteven Rostedt doprint " $count configs to test\n"; 17090a05c769SSteven Rostedt 17100a05c769SSteven Rostedt my $half = int($#start_list / 2); 17110a05c769SSteven Rostedt 17120a05c769SSteven Rostedt do { 17130a05c769SSteven Rostedt my @tophalf = @start_list[0 .. $half]; 17140a05c769SSteven Rostedt 17150a05c769SSteven Rostedt create_config @tophalf; 17160a05c769SSteven Rostedt read_current_config \%current_config; 17170a05c769SSteven Rostedt 17180a05c769SSteven Rostedt $count = $#tophalf + 1; 17190a05c769SSteven Rostedt doprint "Testing $count configs\n"; 17200a05c769SSteven Rostedt my $found = 0; 17210a05c769SSteven Rostedt # make sure we test something 17220a05c769SSteven Rostedt foreach my $config (@tophalf) { 17230a05c769SSteven Rostedt if (defined($current_config{$config})) { 17240a05c769SSteven Rostedt logit " $config\n"; 17250a05c769SSteven Rostedt $found = 1; 17260a05c769SSteven Rostedt } 17270a05c769SSteven Rostedt } 17280a05c769SSteven Rostedt if (!$found) { 17290a05c769SSteven Rostedt # try the other half 17300a05c769SSteven Rostedt doprint "Top half produced no set configs, trying bottom half\n"; 17314c8cc55bSSteven Rostedt @tophalf = @start_list[$half + 1 .. $#start_list]; 17320a05c769SSteven Rostedt create_config @tophalf; 17330a05c769SSteven Rostedt read_current_config \%current_config; 17340a05c769SSteven Rostedt foreach my $config (@tophalf) { 17350a05c769SSteven Rostedt if (defined($current_config{$config})) { 17360a05c769SSteven Rostedt logit " $config\n"; 17370a05c769SSteven Rostedt $found = 1; 17380a05c769SSteven Rostedt } 17390a05c769SSteven Rostedt } 17400a05c769SSteven Rostedt if (!$found) { 17410a05c769SSteven Rostedt doprint "Failed: Can't make new config with current configs\n"; 17420a05c769SSteven Rostedt foreach my $config (@start_list) { 17430a05c769SSteven Rostedt doprint " CONFIG: $config\n"; 17440a05c769SSteven Rostedt } 17450a05c769SSteven Rostedt return -1; 17460a05c769SSteven Rostedt } 17470a05c769SSteven Rostedt $count = $#tophalf + 1; 17480a05c769SSteven Rostedt doprint "Testing $count configs\n"; 17490a05c769SSteven Rostedt } 17500a05c769SSteven Rostedt 17510a05c769SSteven Rostedt $ret = run_config_bisect_test $type; 1752c960bb9fSSteven Rostedt if ($bisect_manual) { 1753c960bb9fSSteven Rostedt $ret = answer_bisect; 1754c960bb9fSSteven Rostedt } 17550a05c769SSteven Rostedt if ($ret) { 17560a05c769SSteven Rostedt process_passed %current_config; 17570a05c769SSteven Rostedt return 0; 17580a05c769SSteven Rostedt } 17590a05c769SSteven Rostedt 17600a05c769SSteven Rostedt doprint "This config had a failure.\n"; 17610a05c769SSteven Rostedt doprint "Removing these configs that were not set in this config:\n"; 1762f1a27850SSteven Rostedt doprint "config copied to $outputdir/config_bad\n"; 1763f1a27850SSteven Rostedt run_command "cp -f $output_config $outputdir/config_bad"; 17640a05c769SSteven Rostedt 17650a05c769SSteven Rostedt # A config exists in this group that was bad. 17660a05c769SSteven Rostedt foreach my $config (keys %config_list) { 17670a05c769SSteven Rostedt if (!defined($current_config{$config})) { 17680a05c769SSteven Rostedt doprint " removing $config\n"; 17690a05c769SSteven Rostedt delete $config_list{$config}; 17700a05c769SSteven Rostedt } 17710a05c769SSteven Rostedt } 17720a05c769SSteven Rostedt 17730a05c769SSteven Rostedt @start_list = @tophalf; 17740a05c769SSteven Rostedt 17750a05c769SSteven Rostedt if ($#start_list == 0) { 17760a05c769SSteven Rostedt process_failed $start_list[0]; 17770a05c769SSteven Rostedt return 1; 17780a05c769SSteven Rostedt } 17790a05c769SSteven Rostedt 17800a05c769SSteven Rostedt # remove half the configs we are looking at and see if 17810a05c769SSteven Rostedt # they are good. 17820a05c769SSteven Rostedt $half = int($#start_list / 2); 17834c8cc55bSSteven Rostedt } while ($#start_list > 0); 17840a05c769SSteven Rostedt 1785c960bb9fSSteven Rostedt # we found a single config, try it again unless we are running manually 1786c960bb9fSSteven Rostedt 1787c960bb9fSSteven Rostedt if ($bisect_manual) { 1788c960bb9fSSteven Rostedt process_failed $start_list[0]; 1789c960bb9fSSteven Rostedt return 1; 1790c960bb9fSSteven Rostedt } 1791c960bb9fSSteven Rostedt 17920a05c769SSteven Rostedt my @tophalf = @start_list[0 .. 0]; 17930a05c769SSteven Rostedt 17940a05c769SSteven Rostedt $ret = run_config_bisect_test $type; 17950a05c769SSteven Rostedt if ($ret) { 17960a05c769SSteven Rostedt process_passed %current_config; 17970a05c769SSteven Rostedt return 0; 17980a05c769SSteven Rostedt } 17990a05c769SSteven Rostedt 18000a05c769SSteven Rostedt process_failed $start_list[0]; 18010a05c769SSteven Rostedt return 1; 18020a05c769SSteven Rostedt} 18030a05c769SSteven Rostedt 18040a05c769SSteven Rostedtsub config_bisect { 18050a05c769SSteven Rostedt my ($i) = @_; 18060a05c769SSteven Rostedt 18070a05c769SSteven Rostedt my $start_config = $opt{"CONFIG_BISECT[$i]"}; 18080a05c769SSteven Rostedt 18090a05c769SSteven Rostedt my $tmpconfig = "$tmpdir/use_config"; 18100a05c769SSteven Rostedt 181130f75da5SSteven Rostedt if (defined($config_bisect_good)) { 181230f75da5SSteven Rostedt process_config_ignore $config_bisect_good; 181330f75da5SSteven Rostedt } 181430f75da5SSteven Rostedt 18150a05c769SSteven Rostedt # Make the file with the bad config and the min config 18160a05c769SSteven Rostedt if (defined($minconfig)) { 18170a05c769SSteven Rostedt # read the min config for things to ignore 18180a05c769SSteven Rostedt run_command "cp $minconfig $tmpconfig" or 18190a05c769SSteven Rostedt dodie "failed to copy $minconfig to $tmpconfig"; 18200a05c769SSteven Rostedt } else { 18210a05c769SSteven Rostedt unlink $tmpconfig; 18220a05c769SSteven Rostedt } 18230a05c769SSteven Rostedt 18240a05c769SSteven Rostedt # Add other configs 18250a05c769SSteven Rostedt if (defined($addconfig)) { 18260a05c769SSteven Rostedt run_command "cat $addconfig >> $tmpconfig" or 18270a05c769SSteven Rostedt dodie "failed to append $addconfig"; 18280a05c769SSteven Rostedt } 18290a05c769SSteven Rostedt 18300a05c769SSteven Rostedt if (-f $tmpconfig) { 1831*fcb3f16aSSteven Rostedt load_force_config($tmpconfig); 18320a05c769SSteven Rostedt process_config_ignore $tmpconfig; 18330a05c769SSteven Rostedt } 18340a05c769SSteven Rostedt 18350a05c769SSteven Rostedt # now process the start config 18360a05c769SSteven Rostedt run_command "cp $start_config $output_config" or 18370a05c769SSteven Rostedt dodie "failed to copy $start_config to $output_config"; 18380a05c769SSteven Rostedt 18390a05c769SSteven Rostedt # read directly what we want to check 18400a05c769SSteven Rostedt my %config_check; 18410a05c769SSteven Rostedt open (IN, $output_config) 18420a05c769SSteven Rostedt or dodie "faied to open $output_config"; 18430a05c769SSteven Rostedt 18440a05c769SSteven Rostedt while (<IN>) { 18450a05c769SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 18460a05c769SSteven Rostedt $config_check{$2} = $1; 18470a05c769SSteven Rostedt } 18480a05c769SSteven Rostedt } 18490a05c769SSteven Rostedt close(IN); 18500a05c769SSteven Rostedt 18510a05c769SSteven Rostedt # Now run oldconfig with the minconfig (and addconfigs) 1852*fcb3f16aSSteven Rostedt make_oldconfig; 18530a05c769SSteven Rostedt 18540a05c769SSteven Rostedt # check to see what we lost (or gained) 18550a05c769SSteven Rostedt open (IN, $output_config) 18560a05c769SSteven Rostedt or dodie "Failed to read $start_config"; 18570a05c769SSteven Rostedt 18580a05c769SSteven Rostedt my %removed_configs; 18590a05c769SSteven Rostedt my %added_configs; 18600a05c769SSteven Rostedt 18610a05c769SSteven Rostedt while (<IN>) { 18620a05c769SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 18630a05c769SSteven Rostedt # save off all options 18640a05c769SSteven Rostedt $config_set{$2} = $1; 18650a05c769SSteven Rostedt if (defined($config_check{$2})) { 18660a05c769SSteven Rostedt if (defined($config_ignore{$2})) { 18670a05c769SSteven Rostedt $removed_configs{$2} = $1; 18680a05c769SSteven Rostedt } else { 18690a05c769SSteven Rostedt $config_list{$2} = $1; 18700a05c769SSteven Rostedt } 18710a05c769SSteven Rostedt } elsif (!defined($config_ignore{$2})) { 18720a05c769SSteven Rostedt $added_configs{$2} = $1; 18730a05c769SSteven Rostedt $config_list{$2} = $1; 18740a05c769SSteven Rostedt } 18750a05c769SSteven Rostedt } 18760a05c769SSteven Rostedt } 18770a05c769SSteven Rostedt close(IN); 18780a05c769SSteven Rostedt 18790a05c769SSteven Rostedt my @confs = keys %removed_configs; 18800a05c769SSteven Rostedt if ($#confs >= 0) { 18810a05c769SSteven Rostedt doprint "Configs overridden by default configs and removed from check:\n"; 18820a05c769SSteven Rostedt foreach my $config (@confs) { 18830a05c769SSteven Rostedt doprint " $config\n"; 18840a05c769SSteven Rostedt } 18850a05c769SSteven Rostedt } 18860a05c769SSteven Rostedt @confs = keys %added_configs; 18870a05c769SSteven Rostedt if ($#confs >= 0) { 18880a05c769SSteven Rostedt doprint "Configs appearing in make oldconfig and added:\n"; 18890a05c769SSteven Rostedt foreach my $config (@confs) { 18900a05c769SSteven Rostedt doprint " $config\n"; 18910a05c769SSteven Rostedt } 18920a05c769SSteven Rostedt } 18930a05c769SSteven Rostedt 18940a05c769SSteven Rostedt my %config_test; 18950a05c769SSteven Rostedt my $once = 0; 18960a05c769SSteven Rostedt 18970a05c769SSteven Rostedt # Sometimes kconfig does weird things. We must make sure 18980a05c769SSteven Rostedt # that the config we autocreate has everything we need 18990a05c769SSteven Rostedt # to test, otherwise we may miss testing configs, or 19000a05c769SSteven Rostedt # may not be able to create a new config. 19010a05c769SSteven Rostedt # Here we create a config with everything set. 19020a05c769SSteven Rostedt create_config (keys %config_list); 19030a05c769SSteven Rostedt read_current_config \%config_test; 19040a05c769SSteven Rostedt foreach my $config (keys %config_list) { 19050a05c769SSteven Rostedt if (!defined($config_test{$config})) { 19060a05c769SSteven Rostedt if (!$once) { 19070a05c769SSteven Rostedt $once = 1; 19080a05c769SSteven Rostedt doprint "Configs not produced by kconfig (will not be checked):\n"; 19090a05c769SSteven Rostedt } 19100a05c769SSteven Rostedt doprint " $config\n"; 19110a05c769SSteven Rostedt delete $config_list{$config}; 19120a05c769SSteven Rostedt } 19130a05c769SSteven Rostedt } 19140a05c769SSteven Rostedt my $ret; 19150a05c769SSteven Rostedt do { 19160a05c769SSteven Rostedt $ret = run_config_bisect; 19170a05c769SSteven Rostedt } while (!$ret); 19180a05c769SSteven Rostedt 19190a05c769SSteven Rostedt return $ret if ($ret < 0); 19205f9b6cedSSteven Rostedt 19215f9b6cedSSteven Rostedt success $i; 19225f9b6cedSSteven Rostedt} 19235f9b6cedSSteven Rostedt 192427d934b2SSteven Rostedtsub patchcheck_reboot { 192527d934b2SSteven Rostedt doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 192627d934b2SSteven Rostedt reboot; 192727d934b2SSteven Rostedt start_monitor; 192827d934b2SSteven Rostedt wait_for_monitor $patchcheck_sleep_time; 192927d934b2SSteven Rostedt end_monitor; 193027d934b2SSteven Rostedt} 193127d934b2SSteven Rostedt 19326c5ee0beSSteven Rostedtsub patchcheck { 19336c5ee0beSSteven Rostedt my ($i) = @_; 19346c5ee0beSSteven Rostedt 19356c5ee0beSSteven Rostedt die "PATCHCHECK_START[$i] not defined\n" 19366c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_START[$i]"})); 19376c5ee0beSSteven Rostedt die "PATCHCHECK_TYPE[$i] not defined\n" 19386c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 19396c5ee0beSSteven Rostedt 19406c5ee0beSSteven Rostedt my $start = $opt{"PATCHCHECK_START[$i]"}; 19416c5ee0beSSteven Rostedt 19426c5ee0beSSteven Rostedt my $end = "HEAD"; 19436c5ee0beSSteven Rostedt if (defined($opt{"PATCHCHECK_END[$i]"})) { 19446c5ee0beSSteven Rostedt $end = $opt{"PATCHCHECK_END[$i]"}; 19456c5ee0beSSteven Rostedt } 19466c5ee0beSSteven Rostedt 1947a57419b3SSteven Rostedt # Get the true sha1's since we can use things like HEAD~3 1948a57419b3SSteven Rostedt $start = get_sha1($start); 1949a57419b3SSteven Rostedt $end = get_sha1($end); 1950a57419b3SSteven Rostedt 19516c5ee0beSSteven Rostedt my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 19526c5ee0beSSteven Rostedt 19536c5ee0beSSteven Rostedt # Can't have a test without having a test to run 19546c5ee0beSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 19556c5ee0beSSteven Rostedt $type = "boot"; 19566c5ee0beSSteven Rostedt } 19576c5ee0beSSteven Rostedt 19586c5ee0beSSteven Rostedt open (IN, "git log --pretty=oneline $end|") or 19596c5ee0beSSteven Rostedt dodie "could not get git list"; 19606c5ee0beSSteven Rostedt 19616c5ee0beSSteven Rostedt my @list; 19626c5ee0beSSteven Rostedt 19636c5ee0beSSteven Rostedt while (<IN>) { 19646c5ee0beSSteven Rostedt chomp; 19656c5ee0beSSteven Rostedt $list[$#list+1] = $_; 19666c5ee0beSSteven Rostedt last if (/^$start/); 19676c5ee0beSSteven Rostedt } 19686c5ee0beSSteven Rostedt close(IN); 19696c5ee0beSSteven Rostedt 19706c5ee0beSSteven Rostedt if ($list[$#list] !~ /^$start/) { 19712b7d9b21SSteven Rostedt fail "SHA1 $start not found"; 19726c5ee0beSSteven Rostedt } 19736c5ee0beSSteven Rostedt 19746c5ee0beSSteven Rostedt # go backwards in the list 19756c5ee0beSSteven Rostedt @list = reverse @list; 19766c5ee0beSSteven Rostedt 19776c5ee0beSSteven Rostedt my $save_clean = $noclean; 19786c5ee0beSSteven Rostedt 19796c5ee0beSSteven Rostedt $in_patchcheck = 1; 19806c5ee0beSSteven Rostedt foreach my $item (@list) { 19816c5ee0beSSteven Rostedt my $sha1 = $item; 19826c5ee0beSSteven Rostedt $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 19836c5ee0beSSteven Rostedt 19846c5ee0beSSteven Rostedt doprint "\nProcessing commit $item\n\n"; 19856c5ee0beSSteven Rostedt 19866c5ee0beSSteven Rostedt run_command "git checkout $sha1" or 19876c5ee0beSSteven Rostedt die "Failed to checkout $sha1"; 19886c5ee0beSSteven Rostedt 19896c5ee0beSSteven Rostedt # only clean on the first and last patch 19906c5ee0beSSteven Rostedt if ($item eq $list[0] || 19916c5ee0beSSteven Rostedt $item eq $list[$#list]) { 19926c5ee0beSSteven Rostedt $noclean = $save_clean; 19936c5ee0beSSteven Rostedt } else { 19946c5ee0beSSteven Rostedt $noclean = 1; 19956c5ee0beSSteven Rostedt } 19966c5ee0beSSteven Rostedt 19976c5ee0beSSteven Rostedt if (defined($minconfig)) { 19982b7d9b21SSteven Rostedt build "useconfig:$minconfig" or return 0; 19996c5ee0beSSteven Rostedt } else { 20006c5ee0beSSteven Rostedt # ?? no config to use? 20012b7d9b21SSteven Rostedt build "oldconfig" or return 0; 20026c5ee0beSSteven Rostedt } 20036c5ee0beSSteven Rostedt 20042b7d9b21SSteven Rostedt check_buildlog $sha1 or return 0; 20056c5ee0beSSteven Rostedt 20066c5ee0beSSteven Rostedt next if ($type eq "build"); 20076c5ee0beSSteven Rostedt 20086c5ee0beSSteven Rostedt get_grub_index; 20096c5ee0beSSteven Rostedt get_version; 20106c5ee0beSSteven Rostedt install; 20116c5ee0beSSteven Rostedt 20127faafbd6SSteven Rostedt my $failed = 0; 20137faafbd6SSteven Rostedt 20147faafbd6SSteven Rostedt start_monitor; 20157faafbd6SSteven Rostedt monitor or $failed = 1; 20167faafbd6SSteven Rostedt 20177faafbd6SSteven Rostedt if (!$failed && $type ne "boot"){ 20187faafbd6SSteven Rostedt do_run_test or $failed = 1; 20197faafbd6SSteven Rostedt } 20207faafbd6SSteven Rostedt end_monitor; 20217faafbd6SSteven Rostedt return 0 if ($failed); 20227faafbd6SSteven Rostedt 202327d934b2SSteven Rostedt patchcheck_reboot; 202427d934b2SSteven Rostedt 20256c5ee0beSSteven Rostedt } 20266c5ee0beSSteven Rostedt $in_patchcheck = 0; 20276c5ee0beSSteven Rostedt success $i; 20282b7d9b21SSteven Rostedt 20292b7d9b21SSteven Rostedt return 1; 20306c5ee0beSSteven Rostedt} 20316c5ee0beSSteven Rostedt 20328d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 20332545eb61SSteven Rostedt 20348d1491baSSteven Rostedtif ($#ARGV == 0) { 20358d1491baSSteven Rostedt $ktest_config = $ARGV[0]; 20368d1491baSSteven Rostedt if (! -f $ktest_config) { 20378d1491baSSteven Rostedt print "$ktest_config does not exist.\n"; 20388d1491baSSteven Rostedt my $ans; 20398d1491baSSteven Rostedt for (;;) { 20408d1491baSSteven Rostedt print "Create it? [Y/n] "; 20418d1491baSSteven Rostedt $ans = <STDIN>; 20428d1491baSSteven Rostedt chomp $ans; 20438d1491baSSteven Rostedt if ($ans =~ /^\s*$/) { 20448d1491baSSteven Rostedt $ans = "y"; 20458d1491baSSteven Rostedt } 20468d1491baSSteven Rostedt last if ($ans =~ /^y$/i || $ans =~ /^n$/i); 20478d1491baSSteven Rostedt print "Please answer either 'y' or 'n'.\n"; 20488d1491baSSteven Rostedt } 20498d1491baSSteven Rostedt if ($ans !~ /^y$/i) { 20508d1491baSSteven Rostedt exit 0; 20518d1491baSSteven Rostedt } 20528d1491baSSteven Rostedt } 20538d1491baSSteven Rostedt} else { 20548d1491baSSteven Rostedt $ktest_config = "ktest.conf"; 20558d1491baSSteven Rostedt} 20568d1491baSSteven Rostedt 20578d1491baSSteven Rostedtif (! -f $ktest_config) { 20588d1491baSSteven Rostedt open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 20598d1491baSSteven Rostedt print OUT << "EOF" 20608d1491baSSteven Rostedt# Generated by ktest.pl 20618d1491baSSteven Rostedt# 20628d1491baSSteven Rostedt# Define each test with TEST_START 20638d1491baSSteven Rostedt# The config options below it will override the defaults 20648d1491baSSteven RostedtTEST_START 20658d1491baSSteven Rostedt 20668d1491baSSteven RostedtDEFAULTS 20678d1491baSSteven RostedtEOF 20688d1491baSSteven Rostedt; 20698d1491baSSteven Rostedt close(OUT); 20708d1491baSSteven Rostedt} 20718d1491baSSteven Rostedtread_config $ktest_config; 20728d1491baSSteven Rostedt 20738d1491baSSteven Rostedt# Append any configs entered in manually to the config file. 20748d1491baSSteven Rostedtmy @new_configs = keys %entered_configs; 20758d1491baSSteven Rostedtif ($#new_configs >= 0) { 20768d1491baSSteven Rostedt print "\nAppending entered in configs to $ktest_config\n"; 20778d1491baSSteven Rostedt open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 20788d1491baSSteven Rostedt foreach my $config (@new_configs) { 20798d1491baSSteven Rostedt print OUT "$config = $entered_configs{$config}\n"; 20808d1491baSSteven Rostedt $opt{$config} = $entered_configs{$config}; 20818d1491baSSteven Rostedt } 20828d1491baSSteven Rostedt} 20832545eb61SSteven Rostedt 20842b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 20852b7d9b21SSteven Rostedt unlink $opt{"LOG_FILE"}; 20862b7d9b21SSteven Rostedt} 20872545eb61SSteven Rostedt 20882b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 20892b7d9b21SSteven Rostedt 2090a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 2091a57419b3SSteven Rostedt 2092a57419b3SSteven Rostedt if (!$i) { 2093a57419b3SSteven Rostedt doprint "DEFAULT OPTIONS:\n"; 2094a57419b3SSteven Rostedt } else { 2095a57419b3SSteven Rostedt doprint "\nTEST $i OPTIONS"; 2096a57419b3SSteven Rostedt if (defined($repeat_tests{$i})) { 2097a57419b3SSteven Rostedt $repeat = $repeat_tests{$i}; 2098a57419b3SSteven Rostedt doprint " ITERATE $repeat"; 2099a57419b3SSteven Rostedt } 2100a57419b3SSteven Rostedt doprint "\n"; 2101a57419b3SSteven Rostedt } 2102a57419b3SSteven Rostedt 21032b7d9b21SSteven Rostedt foreach my $option (sort keys %opt) { 2104a57419b3SSteven Rostedt 2105a57419b3SSteven Rostedt if ($option =~ /\[(\d+)\]$/) { 2106a57419b3SSteven Rostedt next if ($i != $1); 2107a57419b3SSteven Rostedt } else { 2108a57419b3SSteven Rostedt next if ($i); 2109a57419b3SSteven Rostedt } 2110a57419b3SSteven Rostedt 21112b7d9b21SSteven Rostedt doprint "$option = $opt{$option}\n"; 21122b7d9b21SSteven Rostedt } 2113a57419b3SSteven Rostedt} 21142545eb61SSteven Rostedt 21152a62512bSSteven Rostedtsub __set_test_option { 21165a391fbfSSteven Rostedt my ($name, $i) = @_; 21175a391fbfSSteven Rostedt 21185a391fbfSSteven Rostedt my $option = "$name\[$i\]"; 21195a391fbfSSteven Rostedt 21205a391fbfSSteven Rostedt if (defined($opt{$option})) { 21215a391fbfSSteven Rostedt return $opt{$option}; 21225a391fbfSSteven Rostedt } 21235a391fbfSSteven Rostedt 2124a57419b3SSteven Rostedt foreach my $test (keys %repeat_tests) { 2125a57419b3SSteven Rostedt if ($i >= $test && 2126a57419b3SSteven Rostedt $i < $test + $repeat_tests{$test}) { 2127a57419b3SSteven Rostedt $option = "$name\[$test\]"; 2128a57419b3SSteven Rostedt if (defined($opt{$option})) { 2129a57419b3SSteven Rostedt return $opt{$option}; 2130a57419b3SSteven Rostedt } 2131a57419b3SSteven Rostedt } 2132a57419b3SSteven Rostedt } 2133a57419b3SSteven Rostedt 21345a391fbfSSteven Rostedt if (defined($opt{$name})) { 21355a391fbfSSteven Rostedt return $opt{$name}; 21365a391fbfSSteven Rostedt } 21375a391fbfSSteven Rostedt 21385a391fbfSSteven Rostedt return undef; 21395a391fbfSSteven Rostedt} 21405a391fbfSSteven Rostedt 21412a62512bSSteven Rostedtsub eval_option { 21422a62512bSSteven Rostedt my ($option, $i) = @_; 21432a62512bSSteven Rostedt 21442a62512bSSteven Rostedt # Add space to evaluate the character before $ 21452a62512bSSteven Rostedt $option = " $option"; 21462a62512bSSteven Rostedt my $retval = ""; 21472a62512bSSteven Rostedt 21482a62512bSSteven Rostedt while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 21492a62512bSSteven Rostedt my $start = $1; 21502a62512bSSteven Rostedt my $var = $2; 21512a62512bSSteven Rostedt my $end = $3; 21522a62512bSSteven Rostedt 21532a62512bSSteven Rostedt # Append beginning of line 21542a62512bSSteven Rostedt $retval = "$retval$start"; 21552a62512bSSteven Rostedt 21562a62512bSSteven Rostedt # If the iteration option OPT[$i] exists, then use that. 21572a62512bSSteven Rostedt # otherwise see if the default OPT (without [$i]) exists. 21582a62512bSSteven Rostedt 21592a62512bSSteven Rostedt my $o = "$var\[$i\]"; 21602a62512bSSteven Rostedt 21612a62512bSSteven Rostedt if (defined($opt{$o})) { 21622a62512bSSteven Rostedt $o = $opt{$o}; 21632a62512bSSteven Rostedt $retval = "$retval$o"; 21642a62512bSSteven Rostedt } elsif (defined($opt{$var})) { 21652a62512bSSteven Rostedt $o = $opt{$var}; 21662a62512bSSteven Rostedt $retval = "$retval$o"; 21672a62512bSSteven Rostedt } else { 21682a62512bSSteven Rostedt $retval = "$retval\$\{$var\}"; 21692a62512bSSteven Rostedt } 21702a62512bSSteven Rostedt 21712a62512bSSteven Rostedt $option = $end; 21722a62512bSSteven Rostedt } 21732a62512bSSteven Rostedt 21742a62512bSSteven Rostedt $retval = "$retval$option"; 21752a62512bSSteven Rostedt 21762a62512bSSteven Rostedt $retval =~ s/^ //; 21772a62512bSSteven Rostedt 21782a62512bSSteven Rostedt return $retval; 21792a62512bSSteven Rostedt} 21802a62512bSSteven Rostedt 21812a62512bSSteven Rostedtsub set_test_option { 21822a62512bSSteven Rostedt my ($name, $i) = @_; 21832a62512bSSteven Rostedt 21842a62512bSSteven Rostedt my $option = __set_test_option($name, $i); 21852a62512bSSteven Rostedt return $option if (!defined($option)); 21862a62512bSSteven Rostedt 21872a62512bSSteven Rostedt my $prev = ""; 21882a62512bSSteven Rostedt 21892a62512bSSteven Rostedt # Since an option can evaluate to another option, 21902a62512bSSteven Rostedt # keep iterating until we do not evaluate any more 21912a62512bSSteven Rostedt # options. 21922a62512bSSteven Rostedt my $r = 0; 21932a62512bSSteven Rostedt while ($prev ne $option) { 21942a62512bSSteven Rostedt # Check for recursive evaluations. 21952a62512bSSteven Rostedt # 100 deep should be more than enough. 21962a62512bSSteven Rostedt if ($r++ > 100) { 21972a62512bSSteven Rostedt die "Over 100 evaluations accurred with $name\n" . 21982a62512bSSteven Rostedt "Check for recursive variables\n"; 21992a62512bSSteven Rostedt } 22002a62512bSSteven Rostedt $prev = $option; 22012a62512bSSteven Rostedt $option = eval_option($option, $i); 22022a62512bSSteven Rostedt } 22032a62512bSSteven Rostedt 22042a62512bSSteven Rostedt return $option; 22052a62512bSSteven Rostedt} 22062a62512bSSteven Rostedt 22072545eb61SSteven Rostedt# First we need to do is the builds 2208a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 22092545eb61SSteven Rostedt 2210576f627cSSteven Rostedt $iteration = $i; 2211576f627cSSteven Rostedt 2212a75fececSSteven Rostedt my $makecmd = set_test_option("MAKE_CMD", $i); 2213a75fececSSteven Rostedt 2214a75fececSSteven Rostedt $machine = set_test_option("MACHINE", $i); 2215e48c5293SSteven Rostedt $ssh_user = set_test_option("SSH_USER", $i); 2216a75fececSSteven Rostedt $tmpdir = set_test_option("TMP_DIR", $i); 2217a75fececSSteven Rostedt $outputdir = set_test_option("OUTPUT_DIR", $i); 2218a75fececSSteven Rostedt $builddir = set_test_option("BUILD_DIR", $i); 2219a75fececSSteven Rostedt $test_type = set_test_option("TEST_TYPE", $i); 2220a75fececSSteven Rostedt $build_type = set_test_option("BUILD_TYPE", $i); 2221a75fececSSteven Rostedt $build_options = set_test_option("BUILD_OPTIONS", $i); 2222a75fececSSteven Rostedt $power_cycle = set_test_option("POWER_CYCLE", $i); 2223e48c5293SSteven Rostedt $reboot = set_test_option("REBOOT", $i); 2224a75fececSSteven Rostedt $noclean = set_test_option("BUILD_NOCLEAN", $i); 2225a75fececSSteven Rostedt $minconfig = set_test_option("MIN_CONFIG", $i); 2226a75fececSSteven Rostedt $run_test = set_test_option("TEST", $i); 2227a75fececSSteven Rostedt $addconfig = set_test_option("ADD_CONFIG", $i); 2228a75fececSSteven Rostedt $reboot_type = set_test_option("REBOOT_TYPE", $i); 2229a75fececSSteven Rostedt $grub_menu = set_test_option("GRUB_MENU", $i); 22308b37ca8cSSteven Rostedt $post_install = set_test_option("POST_INSTALL", $i); 2231a75fececSSteven Rostedt $reboot_script = set_test_option("REBOOT_SCRIPT", $i); 2232a75fececSSteven Rostedt $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); 2233a75fececSSteven Rostedt $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); 2234a75fececSSteven Rostedt $die_on_failure = set_test_option("DIE_ON_FAILURE", $i); 2235a75fececSSteven Rostedt $power_off = set_test_option("POWER_OFF", $i); 2236576f627cSSteven Rostedt $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i); 2237576f627cSSteven Rostedt $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i); 2238a75fececSSteven Rostedt $sleep_time = set_test_option("SLEEP_TIME", $i); 2239a75fececSSteven Rostedt $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 224027d934b2SSteven Rostedt $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i); 2241c960bb9fSSteven Rostedt $bisect_manual = set_test_option("BISECT_MANUAL", $i); 2242c23dca7cSSteven Rostedt $bisect_skip = set_test_option("BISECT_SKIP", $i); 224330f75da5SSteven Rostedt $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i); 2244a75fececSSteven Rostedt $store_failures = set_test_option("STORE_FAILURES", $i); 22459064af52SSteven Rostedt $test_name = set_test_option("TEST_NAME", $i); 2246a75fececSSteven Rostedt $timeout = set_test_option("TIMEOUT", $i); 2247a75fececSSteven Rostedt $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 2248a75fececSSteven Rostedt $console = set_test_option("CONSOLE", $i); 2249f1a5b962SSteven Rostedt $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i); 2250a75fececSSteven Rostedt $success_line = set_test_option("SUCCESS_LINE", $i); 22511c8a617aSSteven Rostedt $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); 22521c8a617aSSteven Rostedt $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); 22532d01b26aSSteven Rostedt $stop_test_after = set_test_option("STOP_TEST_AFTER", $i); 2254a75fececSSteven Rostedt $build_target = set_test_option("BUILD_TARGET", $i); 2255e48c5293SSteven Rostedt $ssh_exec = set_test_option("SSH_EXEC", $i); 2256e48c5293SSteven Rostedt $scp_to_target = set_test_option("SCP_TO_TARGET", $i); 2257a75fececSSteven Rostedt $target_image = set_test_option("TARGET_IMAGE", $i); 2258a75fececSSteven Rostedt $localversion = set_test_option("LOCALVERSION", $i); 2259a75fececSSteven Rostedt 2260a75fececSSteven Rostedt chdir $builddir || die "can't change directory to $builddir"; 2261a75fececSSteven Rostedt 2262a75fececSSteven Rostedt if (!-d $tmpdir) { 2263a75fececSSteven Rostedt mkpath($tmpdir) or 2264a75fececSSteven Rostedt die "can't create $tmpdir"; 2265a75fececSSteven Rostedt } 2266a75fececSSteven Rostedt 2267e48c5293SSteven Rostedt $ENV{"SSH_USER"} = $ssh_user; 2268e48c5293SSteven Rostedt $ENV{"MACHINE"} = $machine; 2269e48c5293SSteven Rostedt 2270a75fececSSteven Rostedt $target = "$ssh_user\@$machine"; 2271a75fececSSteven Rostedt 2272a75fececSSteven Rostedt $buildlog = "$tmpdir/buildlog-$machine"; 2273a75fececSSteven Rostedt $dmesg = "$tmpdir/dmesg-$machine"; 2274a75fececSSteven Rostedt $make = "$makecmd O=$outputdir"; 227551ad1dd1SSteven Rostedt $output_config = "$outputdir/.config"; 2276a75fececSSteven Rostedt 2277a75fececSSteven Rostedt if ($reboot_type eq "grub") { 2278576f627cSSteven Rostedt dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 2279a75fececSSteven Rostedt } elsif (!defined($reboot_script)) { 2280576f627cSSteven Rostedt dodie "REBOOT_SCRIPT not defined" 2281a75fececSSteven Rostedt } 2282a75fececSSteven Rostedt 2283a75fececSSteven Rostedt my $run_type = $build_type; 2284a75fececSSteven Rostedt if ($test_type eq "patchcheck") { 2285a75fececSSteven Rostedt $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 2286a75fececSSteven Rostedt } elsif ($test_type eq "bisect") { 2287a75fececSSteven Rostedt $run_type = $opt{"BISECT_TYPE[$i]"}; 22880a05c769SSteven Rostedt } elsif ($test_type eq "config_bisect") { 22890a05c769SSteven Rostedt $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; 2290a75fececSSteven Rostedt } 2291a75fececSSteven Rostedt 2292a75fececSSteven Rostedt # mistake in config file? 2293a75fececSSteven Rostedt if (!defined($run_type)) { 2294a75fececSSteven Rostedt $run_type = "ERROR"; 2295a75fececSSteven Rostedt } 22962545eb61SSteven Rostedt 22972545eb61SSteven Rostedt doprint "\n\n"; 2298a75fececSSteven Rostedt doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n"; 22997faafbd6SSteven Rostedt 23007faafbd6SSteven Rostedt unlink $dmesg; 23017faafbd6SSteven Rostedt unlink $buildlog; 23022545eb61SSteven Rostedt 23032b7d9b21SSteven Rostedt if (!defined($minconfig)) { 23042b7d9b21SSteven Rostedt $minconfig = $addconfig; 23052b7d9b21SSteven Rostedt 23062b7d9b21SSteven Rostedt } elsif (defined($addconfig)) { 23079be2e6b5SSteven Rostedt run_command "cat $addconfig $minconfig > $tmpdir/add_config" or 23082b7d9b21SSteven Rostedt dodie "Failed to create temp config"; 23099be2e6b5SSteven Rostedt $minconfig = "$tmpdir/add_config"; 23102b7d9b21SSteven Rostedt } 23112b7d9b21SSteven Rostedt 23126c5ee0beSSteven Rostedt my $checkout = $opt{"CHECKOUT[$i]"}; 23136c5ee0beSSteven Rostedt if (defined($checkout)) { 23146c5ee0beSSteven Rostedt run_command "git checkout $checkout" or 23156c5ee0beSSteven Rostedt die "failed to checkout $checkout"; 23166c5ee0beSSteven Rostedt } 23176c5ee0beSSteven Rostedt 2318a75fececSSteven Rostedt if ($test_type eq "bisect") { 23195f9b6cedSSteven Rostedt bisect $i; 23205f9b6cedSSteven Rostedt next; 23210a05c769SSteven Rostedt } elsif ($test_type eq "config_bisect") { 23220a05c769SSteven Rostedt config_bisect $i; 23230a05c769SSteven Rostedt next; 2324a75fececSSteven Rostedt } elsif ($test_type eq "patchcheck") { 23256c5ee0beSSteven Rostedt patchcheck $i; 23266c5ee0beSSteven Rostedt next; 23275f9b6cedSSteven Rostedt } 23285f9b6cedSSteven Rostedt 23297faafbd6SSteven Rostedt if ($build_type ne "nobuild") { 23307faafbd6SSteven Rostedt build $build_type or next; 23312545eb61SSteven Rostedt } 23322545eb61SSteven Rostedt 2333a75fececSSteven Rostedt if ($test_type ne "build") { 23345f9b6cedSSteven Rostedt get_grub_index; 23355f9b6cedSSteven Rostedt get_version; 23362545eb61SSteven Rostedt install; 23375a391fbfSSteven Rostedt 23387faafbd6SSteven Rostedt my $failed = 0; 23397faafbd6SSteven Rostedt start_monitor; 23407faafbd6SSteven Rostedt monitor or $failed = 1;; 2341a75fececSSteven Rostedt 2342a75fececSSteven Rostedt if (!$failed && $test_type ne "boot" && defined($run_test)) { 23437faafbd6SSteven Rostedt do_run_test or $failed = 1; 23445a391fbfSSteven Rostedt } 23457faafbd6SSteven Rostedt end_monitor; 23467faafbd6SSteven Rostedt next if ($failed); 2347a75fececSSteven Rostedt } 23485a391fbfSSteven Rostedt 23495f9b6cedSSteven Rostedt success $i; 235075c3fda7SSteven Rostedt} 23512545eb61SSteven Rostedt 23525c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) { 235375c3fda7SSteven Rostedt halt; 2354576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { 235575c3fda7SSteven Rostedt reboot; 23565c42fc5bSSteven Rostedt} 235775c3fda7SSteven Rostedt 2358e48c5293SSteven Rostedtdoprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 2359e48c5293SSteven Rostedt 23602545eb61SSteven Rostedtexit 0; 2361