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; 104*9064af52SSteven 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; 1228d1491baSSteven Rostedt 1238d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF" 1248d1491baSSteven Rostedt The machine hostname that you will test. 1258d1491baSSteven RostedtEOF 1268d1491baSSteven Rostedt ; 1278d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF" 1288d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user 1298d1491baSSteven Rostedt (most likely root, since you need privileged operations) 1308d1491baSSteven RostedtEOF 1318d1491baSSteven Rostedt ; 1328d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF" 1338d1491baSSteven Rostedt The directory that contains the Linux source code (full path). 1348d1491baSSteven RostedtEOF 1358d1491baSSteven Rostedt ; 1368d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF" 1378d1491baSSteven Rostedt The directory that the objects will be built (full path). 1388d1491baSSteven Rostedt (can not be same as BUILD_DIR) 1398d1491baSSteven RostedtEOF 1408d1491baSSteven Rostedt ; 1418d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF" 1428d1491baSSteven Rostedt The location of the compiled file to copy to the target. 1438d1491baSSteven Rostedt (relative to OUTPUT_DIR) 1448d1491baSSteven RostedtEOF 1458d1491baSSteven Rostedt ; 1468d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF" 1478d1491baSSteven Rostedt The place to put your image on the test machine. 1488d1491baSSteven RostedtEOF 1498d1491baSSteven Rostedt ; 1508d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF" 1518d1491baSSteven Rostedt A script or command to reboot the box. 1528d1491baSSteven Rostedt 1538d1491baSSteven Rostedt Here is a digital loggers power switch example 1548d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL' 1558d1491baSSteven Rostedt 1568d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host 1578d1491baSSteven Rostedt with the name "Guest". 1588d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest 1598d1491baSSteven RostedtEOF 1608d1491baSSteven Rostedt ; 1618d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF" 1628d1491baSSteven Rostedt The script or command that reads the console 1638d1491baSSteven Rostedt 1648d1491baSSteven Rostedt If you use ttywatch server, something like the following would work. 1658d1491baSSteven RostedtCONSOLE = nc -d localhost 3001 1668d1491baSSteven Rostedt 1678d1491baSSteven Rostedt For a virtual machine with guest name "Guest". 1688d1491baSSteven RostedtCONSOLE = virsh console Guest 1698d1491baSSteven RostedtEOF 1708d1491baSSteven Rostedt ; 1718d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF" 1728d1491baSSteven Rostedt Required version ending to differentiate the test 1738d1491baSSteven Rostedt from other linux builds on the system. 1748d1491baSSteven RostedtEOF 1758d1491baSSteven Rostedt ; 1768d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF" 1778d1491baSSteven Rostedt Way to reboot the box to the test kernel. 1788d1491baSSteven Rostedt Only valid options so far are "grub" and "script". 1798d1491baSSteven Rostedt 1808d1491baSSteven Rostedt If you specify grub, it will assume grub version 1 1818d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU 1828d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not 1838d1491baSSteven Rostedt your setup, then specify "script" and have a command or script 1848d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target. 1858d1491baSSteven Rostedt 1868d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually. 1878d1491baSSteven Rostedt The test will not modify that file. 1888d1491baSSteven RostedtEOF 1898d1491baSSteven Rostedt ; 1908d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF" 1918d1491baSSteven Rostedt The grub title name for the test kernel to boot 1928d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = grub) 1938d1491baSSteven Rostedt 1948d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to 1958d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search 1968d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to 1978d1491baSSteven Rostedt reboot into. 1988d1491baSSteven Rostedt 1998d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has: 2008d1491baSSteven Rostedt title Test Kernel 2018d1491baSSteven Rostedt kernel vmlinuz-test 2028d1491baSSteven Rostedt GRUB_MENU = Test Kernel 2038d1491baSSteven RostedtEOF 2048d1491baSSteven Rostedt ; 2058d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF" 2068d1491baSSteven Rostedt A script to reboot the target into the test kernel 2078d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script) 2088d1491baSSteven RostedtEOF 2098d1491baSSteven Rostedt ; 2108d1491baSSteven Rostedt 2118d1491baSSteven Rostedt 2128d1491baSSteven Rostedtsub get_ktest_config { 2138d1491baSSteven Rostedt my ($config) = @_; 2148d1491baSSteven Rostedt 2158d1491baSSteven Rostedt return if (defined($opt{$config})); 2168d1491baSSteven Rostedt 2178d1491baSSteven Rostedt if (defined($config_help{$config})) { 2188d1491baSSteven Rostedt print "\n"; 2198d1491baSSteven Rostedt print $config_help{$config}; 2208d1491baSSteven Rostedt } 2218d1491baSSteven Rostedt 2228d1491baSSteven Rostedt for (;;) { 2238d1491baSSteven Rostedt print "$config = "; 2248d1491baSSteven Rostedt if (defined($default{$config})) { 2258d1491baSSteven Rostedt print "\[$default{$config}\] "; 2268d1491baSSteven Rostedt } 2278d1491baSSteven Rostedt $entered_configs{$config} = <STDIN>; 2288d1491baSSteven Rostedt $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/; 2298d1491baSSteven Rostedt if ($entered_configs{$config} =~ /^\s*$/) { 2308d1491baSSteven Rostedt if ($default{$config}) { 2318d1491baSSteven Rostedt $entered_configs{$config} = $default{$config}; 2328d1491baSSteven Rostedt } else { 2338d1491baSSteven Rostedt print "Your answer can not be blank\n"; 2348d1491baSSteven Rostedt next; 2358d1491baSSteven Rostedt } 2368d1491baSSteven Rostedt } 2378d1491baSSteven Rostedt last; 2388d1491baSSteven Rostedt } 2398d1491baSSteven Rostedt} 2408d1491baSSteven Rostedt 2418d1491baSSteven Rostedtsub get_ktest_configs { 2428d1491baSSteven Rostedt get_ktest_config("MACHINE"); 2438d1491baSSteven Rostedt get_ktest_config("SSH_USER"); 2448d1491baSSteven Rostedt get_ktest_config("BUILD_DIR"); 2458d1491baSSteven Rostedt get_ktest_config("OUTPUT_DIR"); 2468d1491baSSteven Rostedt get_ktest_config("BUILD_TARGET"); 2478d1491baSSteven Rostedt get_ktest_config("TARGET_IMAGE"); 2488d1491baSSteven Rostedt get_ktest_config("POWER_CYCLE"); 2498d1491baSSteven Rostedt get_ktest_config("CONSOLE"); 2508d1491baSSteven Rostedt get_ktest_config("LOCALVERSION"); 2518d1491baSSteven Rostedt 2528d1491baSSteven Rostedt my $rtype = $opt{"REBOOT_TYPE"}; 2538d1491baSSteven Rostedt 2548d1491baSSteven Rostedt if (!defined($rtype)) { 2558d1491baSSteven Rostedt if (!defined($opt{"GRUB_MENU"})) { 2568d1491baSSteven Rostedt get_ktest_config("REBOOT_TYPE"); 2578d1491baSSteven Rostedt $rtype = $entered_configs{"REBOOT_TYPE"}; 2588d1491baSSteven Rostedt } else { 2598d1491baSSteven Rostedt $rtype = "grub"; 2608d1491baSSteven Rostedt } 2618d1491baSSteven Rostedt } 2628d1491baSSteven Rostedt 2638d1491baSSteven Rostedt if ($rtype eq "grub") { 2648d1491baSSteven Rostedt get_ktest_config("GRUB_MENU"); 2658d1491baSSteven Rostedt } else { 2668d1491baSSteven Rostedt get_ktest_config("REBOOT_SCRIPT"); 2678d1491baSSteven Rostedt } 2688d1491baSSteven Rostedt} 2698d1491baSSteven Rostedt 27077d942ceSSteven Rostedtsub process_variables { 27177d942ceSSteven Rostedt my ($value) = @_; 27277d942ceSSteven Rostedt my $retval = ""; 27377d942ceSSteven Rostedt 27477d942ceSSteven Rostedt # We want to check for '\', and it is just easier 27577d942ceSSteven Rostedt # to check the previous characet of '$' and not need 27677d942ceSSteven Rostedt # to worry if '$' is the first character. By adding 27777d942ceSSteven Rostedt # a space to $value, we can just check [^\\]\$ and 27877d942ceSSteven Rostedt # it will still work. 27977d942ceSSteven Rostedt $value = " $value"; 28077d942ceSSteven Rostedt 28177d942ceSSteven Rostedt while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 28277d942ceSSteven Rostedt my $begin = $1; 28377d942ceSSteven Rostedt my $var = $2; 28477d942ceSSteven Rostedt my $end = $3; 28577d942ceSSteven Rostedt # append beginning of value to retval 28677d942ceSSteven Rostedt $retval = "$retval$begin"; 28777d942ceSSteven Rostedt if (defined($variable{$var})) { 28877d942ceSSteven Rostedt $retval = "$retval$variable{$var}"; 28977d942ceSSteven Rostedt } else { 29077d942ceSSteven Rostedt # put back the origin piece. 29177d942ceSSteven Rostedt $retval = "$retval\$\{$var\}"; 29277d942ceSSteven Rostedt } 29377d942ceSSteven Rostedt $value = $end; 29477d942ceSSteven Rostedt } 29577d942ceSSteven Rostedt $retval = "$retval$value"; 29677d942ceSSteven Rostedt 29777d942ceSSteven Rostedt # remove the space added in the beginning 29877d942ceSSteven Rostedt $retval =~ s/ //; 29977d942ceSSteven Rostedt 30077d942ceSSteven Rostedt return "$retval" 30177d942ceSSteven Rostedt} 30277d942ceSSteven Rostedt 303a57419b3SSteven Rostedtsub set_value { 304a57419b3SSteven Rostedt my ($lvalue, $rvalue) = @_; 3052545eb61SSteven Rostedt 306a75fececSSteven Rostedt if (defined($opt{$lvalue})) { 307a75fececSSteven Rostedt die "Error: Option $lvalue defined more than once!\n"; 308a75fececSSteven Rostedt } 30921a9679fSSteven Rostedt if ($rvalue =~ /^\s*$/) { 31021a9679fSSteven Rostedt delete $opt{$lvalue}; 31121a9679fSSteven Rostedt } else { 31277d942ceSSteven Rostedt $rvalue = process_variables($rvalue); 31321a9679fSSteven Rostedt $opt{$lvalue} = $rvalue; 31421a9679fSSteven Rostedt } 3152545eb61SSteven Rostedt} 316a57419b3SSteven Rostedt 31777d942ceSSteven Rostedtsub set_variable { 31877d942ceSSteven Rostedt my ($lvalue, $rvalue) = @_; 31977d942ceSSteven Rostedt 32077d942ceSSteven Rostedt if ($rvalue =~ /^\s*$/) { 32177d942ceSSteven Rostedt delete $variable{$lvalue}; 32277d942ceSSteven Rostedt } else { 32377d942ceSSteven Rostedt $rvalue = process_variables($rvalue); 32477d942ceSSteven Rostedt $variable{$lvalue} = $rvalue; 32577d942ceSSteven Rostedt } 32677d942ceSSteven Rostedt} 32777d942ceSSteven Rostedt 328a57419b3SSteven Rostedtsub read_config { 329a57419b3SSteven Rostedt my ($config) = @_; 330a57419b3SSteven Rostedt 331a57419b3SSteven Rostedt open(IN, $config) || die "can't read file $config"; 332a57419b3SSteven Rostedt 333a57419b3SSteven Rostedt my $name = $config; 334a57419b3SSteven Rostedt $name =~ s,.*/(.*),$1,; 335a57419b3SSteven Rostedt 336a57419b3SSteven Rostedt my $test_num = 0; 337a57419b3SSteven Rostedt my $default = 1; 338a57419b3SSteven Rostedt my $repeat = 1; 339a57419b3SSteven Rostedt my $num_tests_set = 0; 340a57419b3SSteven Rostedt my $skip = 0; 341a57419b3SSteven Rostedt my $rest; 342a57419b3SSteven Rostedt 343a57419b3SSteven Rostedt while (<IN>) { 344a57419b3SSteven Rostedt 345a57419b3SSteven Rostedt # ignore blank lines and comments 346a57419b3SSteven Rostedt next if (/^\s*$/ || /\s*\#/); 347a57419b3SSteven Rostedt 348a57419b3SSteven Rostedt if (/^\s*TEST_START(.*)/) { 349a57419b3SSteven Rostedt 350a57419b3SSteven Rostedt $rest = $1; 351a57419b3SSteven Rostedt 352a57419b3SSteven Rostedt if ($num_tests_set) { 353a57419b3SSteven Rostedt die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 354a57419b3SSteven Rostedt } 355a57419b3SSteven Rostedt 356a57419b3SSteven Rostedt my $old_test_num = $test_num; 357e48c5293SSteven Rostedt my $old_repeat = $repeat; 358a57419b3SSteven Rostedt 359a57419b3SSteven Rostedt $test_num += $repeat; 360a57419b3SSteven Rostedt $default = 0; 361a57419b3SSteven Rostedt $repeat = 1; 362a57419b3SSteven Rostedt 363a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 364a57419b3SSteven Rostedt $rest = $1; 365a57419b3SSteven Rostedt $skip = 1; 366a57419b3SSteven Rostedt } else { 367a57419b3SSteven Rostedt $skip = 0; 368a57419b3SSteven Rostedt } 369a57419b3SSteven Rostedt 370a57419b3SSteven Rostedt if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) { 371a57419b3SSteven Rostedt $repeat = $1; 372a57419b3SSteven Rostedt $rest = $2; 373a57419b3SSteven Rostedt $repeat_tests{"$test_num"} = $repeat; 374a57419b3SSteven Rostedt } 375a57419b3SSteven Rostedt 376a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 377a57419b3SSteven Rostedt $rest = $1; 378a57419b3SSteven Rostedt $skip = 1; 379a57419b3SSteven Rostedt } 380a57419b3SSteven Rostedt 381a57419b3SSteven Rostedt if ($rest !~ /^\s*$/) { 382a57419b3SSteven Rostedt die "$name: $.: Gargbage found after TEST_START\n$_"; 383a57419b3SSteven Rostedt } 384a57419b3SSteven Rostedt 385a57419b3SSteven Rostedt if ($skip) { 386a57419b3SSteven Rostedt $test_num = $old_test_num; 387e48c5293SSteven Rostedt $repeat = $old_repeat; 388a57419b3SSteven Rostedt } 389a57419b3SSteven Rostedt 390a57419b3SSteven Rostedt } elsif (/^\s*DEFAULTS(.*)$/) { 391a57419b3SSteven Rostedt $default = 1; 392a57419b3SSteven Rostedt 393a57419b3SSteven Rostedt $rest = $1; 394a57419b3SSteven Rostedt 395a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 396a57419b3SSteven Rostedt $rest = $1; 397a57419b3SSteven Rostedt $skip = 1; 398a57419b3SSteven Rostedt } else { 399a57419b3SSteven Rostedt $skip = 0; 400a57419b3SSteven Rostedt } 401a57419b3SSteven Rostedt 402a57419b3SSteven Rostedt if ($rest !~ /^\s*$/) { 403a57419b3SSteven Rostedt die "$name: $.: Gargbage found after DEFAULTS\n$_"; 404a57419b3SSteven Rostedt } 405a57419b3SSteven Rostedt 406a57419b3SSteven Rostedt } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 407a57419b3SSteven Rostedt 408a57419b3SSteven Rostedt next if ($skip); 409a57419b3SSteven Rostedt 410a57419b3SSteven Rostedt my $lvalue = $1; 411a57419b3SSteven Rostedt my $rvalue = $2; 412a57419b3SSteven Rostedt 413a57419b3SSteven Rostedt if (!$default && 414a57419b3SSteven Rostedt ($lvalue eq "NUM_TESTS" || 415a57419b3SSteven Rostedt $lvalue eq "LOG_FILE" || 416a57419b3SSteven Rostedt $lvalue eq "CLEAR_LOG")) { 417a57419b3SSteven Rostedt die "$name: $.: $lvalue must be set in DEFAULTS section\n"; 418a57419b3SSteven Rostedt } 419a57419b3SSteven Rostedt 420a57419b3SSteven Rostedt if ($lvalue eq "NUM_TESTS") { 421a57419b3SSteven Rostedt if ($test_num) { 422a57419b3SSteven Rostedt die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 423a57419b3SSteven Rostedt } 424a57419b3SSteven Rostedt if (!$default) { 425a57419b3SSteven Rostedt die "$name: $.: NUM_TESTS must be set in default section\n"; 426a57419b3SSteven Rostedt } 427a57419b3SSteven Rostedt $num_tests_set = 1; 428a57419b3SSteven Rostedt } 429a57419b3SSteven Rostedt 430a57419b3SSteven Rostedt if ($default || $lvalue =~ /\[\d+\]$/) { 431a57419b3SSteven Rostedt set_value($lvalue, $rvalue); 432a57419b3SSteven Rostedt } else { 433a57419b3SSteven Rostedt my $val = "$lvalue\[$test_num\]"; 434a57419b3SSteven Rostedt set_value($val, $rvalue); 435a57419b3SSteven Rostedt 436a57419b3SSteven Rostedt if ($repeat > 1) { 437a57419b3SSteven Rostedt $repeats{$val} = $repeat; 438a57419b3SSteven Rostedt } 439a57419b3SSteven Rostedt } 44077d942ceSSteven Rostedt } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) { 44177d942ceSSteven Rostedt next if ($skip); 44277d942ceSSteven Rostedt 44377d942ceSSteven Rostedt my $lvalue = $1; 44477d942ceSSteven Rostedt my $rvalue = $2; 44577d942ceSSteven Rostedt 44677d942ceSSteven Rostedt # process config variables. 44777d942ceSSteven Rostedt # Config variables are only active while reading the 44877d942ceSSteven Rostedt # config and can be defined anywhere. They also ignore 44977d942ceSSteven Rostedt # TEST_START and DEFAULTS, but are skipped if they are in 45077d942ceSSteven Rostedt # on of these sections that have SKIP defined. 45177d942ceSSteven Rostedt # The save variable can be 45277d942ceSSteven Rostedt # defined multiple times and the new one simply overrides 45377d942ceSSteven Rostedt # the prevous one. 45477d942ceSSteven Rostedt set_variable($lvalue, $rvalue); 45577d942ceSSteven Rostedt 456a57419b3SSteven Rostedt } else { 457a57419b3SSteven Rostedt die "$name: $.: Garbage found in config\n$_"; 458a57419b3SSteven Rostedt } 4592545eb61SSteven Rostedt } 4602545eb61SSteven Rostedt 4612545eb61SSteven Rostedt close(IN); 462a75fececSSteven Rostedt 463a57419b3SSteven Rostedt if ($test_num) { 464a57419b3SSteven Rostedt $test_num += $repeat - 1; 465a57419b3SSteven Rostedt $opt{"NUM_TESTS"} = $test_num; 466a57419b3SSteven Rostedt } 467a57419b3SSteven Rostedt 4688d1491baSSteven Rostedt # make sure we have all mandatory configs 4698d1491baSSteven Rostedt get_ktest_configs; 4708d1491baSSteven Rostedt 471a75fececSSteven Rostedt # set any defaults 472a75fececSSteven Rostedt 473a75fececSSteven Rostedt foreach my $default (keys %default) { 474a75fececSSteven Rostedt if (!defined($opt{$default})) { 475a75fececSSteven Rostedt $opt{$default} = $default{$default}; 476a75fececSSteven Rostedt } 477a75fececSSteven Rostedt } 4782545eb61SSteven Rostedt} 4792545eb61SSteven Rostedt 480d1e2f22aSSteven Rostedtsub _logit { 4812545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 4822545eb61SSteven Rostedt open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 4832545eb61SSteven Rostedt print OUT @_; 4842545eb61SSteven Rostedt close(OUT); 4852545eb61SSteven Rostedt } 4862545eb61SSteven Rostedt} 4872545eb61SSteven Rostedt 488d1e2f22aSSteven Rostedtsub logit { 489d1e2f22aSSteven Rostedt if (defined($opt{"LOG_FILE"})) { 490d1e2f22aSSteven Rostedt _logit @_; 491d1e2f22aSSteven Rostedt } else { 492d1e2f22aSSteven Rostedt print @_; 493d1e2f22aSSteven Rostedt } 494d1e2f22aSSteven Rostedt} 495d1e2f22aSSteven Rostedt 4965f9b6cedSSteven Rostedtsub doprint { 4975f9b6cedSSteven Rostedt print @_; 498d1e2f22aSSteven Rostedt _logit @_; 4995f9b6cedSSteven Rostedt} 5005f9b6cedSSteven Rostedt 5017faafbd6SSteven Rostedtsub run_command; 5027faafbd6SSteven Rostedt 5037faafbd6SSteven Rostedtsub reboot { 5047faafbd6SSteven Rostedt # try to reboot normally 505e48c5293SSteven Rostedt if (run_command $reboot) { 506576f627cSSteven Rostedt if (defined($powercycle_after_reboot)) { 507576f627cSSteven Rostedt sleep $powercycle_after_reboot; 508576f627cSSteven Rostedt run_command "$power_cycle"; 509576f627cSSteven Rostedt } 510576f627cSSteven Rostedt } else { 5117faafbd6SSteven Rostedt # nope? power cycle it. 512a75fececSSteven Rostedt run_command "$power_cycle"; 5137faafbd6SSteven Rostedt } 5147faafbd6SSteven Rostedt} 5157faafbd6SSteven Rostedt 516576f627cSSteven Rostedtsub do_not_reboot { 517576f627cSSteven Rostedt my $i = $iteration; 518576f627cSSteven Rostedt 519576f627cSSteven Rostedt return $test_type eq "build" || 520576f627cSSteven Rostedt ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 521576f627cSSteven Rostedt ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 522576f627cSSteven Rostedt} 523576f627cSSteven Rostedt 5245c42fc5bSSteven Rostedtsub dodie { 5255a391fbfSSteven Rostedt doprint "CRITICAL FAILURE... ", @_, "\n"; 5265c42fc5bSSteven Rostedt 527576f627cSSteven Rostedt my $i = $iteration; 528576f627cSSteven Rostedt 529576f627cSSteven Rostedt if ($reboot_on_error && !do_not_reboot) { 530576f627cSSteven Rostedt 53175c3fda7SSteven Rostedt doprint "REBOOTING\n"; 5327faafbd6SSteven Rostedt reboot; 53375c3fda7SSteven Rostedt 534a75fececSSteven Rostedt } elsif ($poweroff_on_error && defined($power_off)) { 5355c42fc5bSSteven Rostedt doprint "POWERING OFF\n"; 536a75fececSSteven Rostedt `$power_off`; 5375c42fc5bSSteven Rostedt } 53875c3fda7SSteven Rostedt 539f80802cbSSteven Rostedt if (defined($opt{"LOG_FILE"})) { 540f80802cbSSteven Rostedt print " See $opt{LOG_FILE} for more info.\n"; 541f80802cbSSteven Rostedt } 542f80802cbSSteven Rostedt 543576f627cSSteven Rostedt die @_, "\n"; 5445c42fc5bSSteven Rostedt} 5455c42fc5bSSteven Rostedt 5467faafbd6SSteven Rostedtsub open_console { 5477faafbd6SSteven Rostedt my ($fp) = @_; 5487faafbd6SSteven Rostedt 5497faafbd6SSteven Rostedt my $flags; 5507faafbd6SSteven Rostedt 551a75fececSSteven Rostedt my $pid = open($fp, "$console|") or 552a75fececSSteven Rostedt dodie "Can't open console $console"; 5537faafbd6SSteven Rostedt 5547faafbd6SSteven Rostedt $flags = fcntl($fp, F_GETFL, 0) or 555576f627cSSteven Rostedt dodie "Can't get flags for the socket: $!"; 5567faafbd6SSteven Rostedt $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 557576f627cSSteven Rostedt dodie "Can't set flags for the socket: $!"; 5587faafbd6SSteven Rostedt 5597faafbd6SSteven Rostedt return $pid; 5607faafbd6SSteven Rostedt} 5617faafbd6SSteven Rostedt 5627faafbd6SSteven Rostedtsub close_console { 5637faafbd6SSteven Rostedt my ($fp, $pid) = @_; 5647faafbd6SSteven Rostedt 5657faafbd6SSteven Rostedt doprint "kill child process $pid\n"; 5667faafbd6SSteven Rostedt kill 2, $pid; 5677faafbd6SSteven Rostedt 5687faafbd6SSteven Rostedt print "closing!\n"; 5697faafbd6SSteven Rostedt close($fp); 5707faafbd6SSteven Rostedt} 5717faafbd6SSteven Rostedt 5727faafbd6SSteven Rostedtsub start_monitor { 5737faafbd6SSteven Rostedt if ($monitor_cnt++) { 5747faafbd6SSteven Rostedt return; 5757faafbd6SSteven Rostedt } 5767faafbd6SSteven Rostedt $monitor_fp = \*MONFD; 5777faafbd6SSteven Rostedt $monitor_pid = open_console $monitor_fp; 578a75fececSSteven Rostedt 579a75fececSSteven Rostedt return; 580a75fececSSteven Rostedt 581a75fececSSteven Rostedt open(MONFD, "Stop perl from warning about single use of MONFD"); 5827faafbd6SSteven Rostedt} 5837faafbd6SSteven Rostedt 5847faafbd6SSteven Rostedtsub end_monitor { 5857faafbd6SSteven Rostedt if (--$monitor_cnt) { 5867faafbd6SSteven Rostedt return; 5877faafbd6SSteven Rostedt } 5887faafbd6SSteven Rostedt close_console($monitor_fp, $monitor_pid); 5897faafbd6SSteven Rostedt} 5907faafbd6SSteven Rostedt 5917faafbd6SSteven Rostedtsub wait_for_monitor { 5927faafbd6SSteven Rostedt my ($time) = @_; 5937faafbd6SSteven Rostedt my $line; 5947faafbd6SSteven Rostedt 595a75fececSSteven Rostedt doprint "** Wait for monitor to settle down **\n"; 5967faafbd6SSteven Rostedt 5977faafbd6SSteven Rostedt # read the monitor and wait for the system to calm down 5987faafbd6SSteven Rostedt do { 5997faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 600a75fececSSteven Rostedt print "$line" if (defined($line)); 6017faafbd6SSteven Rostedt } while (defined($line)); 602a75fececSSteven Rostedt print "** Monitor flushed **\n"; 6037faafbd6SSteven Rostedt} 6047faafbd6SSteven Rostedt 6052b7d9b21SSteven Rostedtsub fail { 6062b7d9b21SSteven Rostedt 607a75fececSSteven Rostedt if ($die_on_failure) { 6082b7d9b21SSteven Rostedt dodie @_; 6092b7d9b21SSteven Rostedt } 6102b7d9b21SSteven Rostedt 611a75fececSSteven Rostedt doprint "FAILED\n"; 6127faafbd6SSteven Rostedt 613576f627cSSteven Rostedt my $i = $iteration; 614576f627cSSteven Rostedt 615a75fececSSteven Rostedt # no need to reboot for just building. 616576f627cSSteven Rostedt if (!do_not_reboot) { 6177faafbd6SSteven Rostedt doprint "REBOOTING\n"; 6187faafbd6SSteven Rostedt reboot; 6197faafbd6SSteven Rostedt start_monitor; 620a75fececSSteven Rostedt wait_for_monitor $sleep_time; 6217faafbd6SSteven Rostedt end_monitor; 622a75fececSSteven Rostedt } 6237faafbd6SSteven Rostedt 624*9064af52SSteven Rostedt my $name = ""; 625*9064af52SSteven Rostedt 626*9064af52SSteven Rostedt if (defined($test_name)) { 627*9064af52SSteven Rostedt $name = " ($test_name)"; 628*9064af52SSteven Rostedt } 629*9064af52SSteven Rostedt 630576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 631576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 632*9064af52SSteven Rostedt doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n"; 633576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 634576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 635a75fececSSteven Rostedt 636a75fececSSteven Rostedt return 1 if (!defined($store_failures)); 6377faafbd6SSteven Rostedt 6387faafbd6SSteven Rostedt my @t = localtime; 6397faafbd6SSteven Rostedt my $date = sprintf "%04d%02d%02d%02d%02d%02d", 6407faafbd6SSteven Rostedt 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 6417faafbd6SSteven Rostedt 642cccae1a6SSteven Rostedt my $type = $build_type; 643cccae1a6SSteven Rostedt if ($type =~ /useconfig/) { 644cccae1a6SSteven Rostedt $type = "useconfig"; 645cccae1a6SSteven Rostedt } 646cccae1a6SSteven Rostedt 647cccae1a6SSteven Rostedt my $dir = "$machine-$test_type-$type-fail-$date"; 648a75fececSSteven Rostedt my $faildir = "$store_failures/$dir"; 6497faafbd6SSteven Rostedt 6507faafbd6SSteven Rostedt if (!-d $faildir) { 6517faafbd6SSteven Rostedt mkpath($faildir) or 652a75fececSSteven Rostedt die "can't create $faildir"; 6537faafbd6SSteven Rostedt } 65451ad1dd1SSteven Rostedt if (-f "$output_config") { 65551ad1dd1SSteven Rostedt cp "$output_config", "$faildir/config" or 6567faafbd6SSteven Rostedt die "failed to copy .config"; 6577faafbd6SSteven Rostedt } 6587faafbd6SSteven Rostedt if (-f $buildlog) { 6597faafbd6SSteven Rostedt cp $buildlog, "$faildir/buildlog" or 6607faafbd6SSteven Rostedt die "failed to move $buildlog"; 6617faafbd6SSteven Rostedt } 6627faafbd6SSteven Rostedt if (-f $dmesg) { 6637faafbd6SSteven Rostedt cp $dmesg, "$faildir/dmesg" or 6647faafbd6SSteven Rostedt die "failed to move $dmesg"; 6657faafbd6SSteven Rostedt } 6667faafbd6SSteven Rostedt 6677faafbd6SSteven Rostedt doprint "*** Saved info to $faildir ***\n"; 6687faafbd6SSteven Rostedt 6692b7d9b21SSteven Rostedt return 1; 6702b7d9b21SSteven Rostedt} 6712b7d9b21SSteven Rostedt 6722545eb61SSteven Rostedtsub run_command { 6732545eb61SSteven Rostedt my ($command) = @_; 674d6ce2a0bSSteven Rostedt my $dolog = 0; 675d6ce2a0bSSteven Rostedt my $dord = 0; 676d6ce2a0bSSteven Rostedt my $pid; 677d6ce2a0bSSteven Rostedt 678e48c5293SSteven Rostedt $command =~ s/\$SSH_USER/$ssh_user/g; 679e48c5293SSteven Rostedt $command =~ s/\$MACHINE/$machine/g; 680e48c5293SSteven Rostedt 681d6ce2a0bSSteven Rostedt doprint("$command ... "); 682d6ce2a0bSSteven Rostedt 683d6ce2a0bSSteven Rostedt $pid = open(CMD, "$command 2>&1 |") or 6842b7d9b21SSteven Rostedt (fail "unable to exec $command" and return 0); 6852545eb61SSteven Rostedt 6862545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 687d6ce2a0bSSteven Rostedt open(LOG, ">>$opt{LOG_FILE}") or 688d6ce2a0bSSteven Rostedt dodie "failed to write to log"; 689d6ce2a0bSSteven Rostedt $dolog = 1; 6906c5ee0beSSteven Rostedt } 6916c5ee0beSSteven Rostedt 6926c5ee0beSSteven Rostedt if (defined($redirect)) { 693d6ce2a0bSSteven Rostedt open (RD, ">$redirect") or 694d6ce2a0bSSteven Rostedt dodie "failed to write to redirect $redirect"; 695d6ce2a0bSSteven Rostedt $dord = 1; 6962545eb61SSteven Rostedt } 6972545eb61SSteven Rostedt 698d6ce2a0bSSteven Rostedt while (<CMD>) { 699d6ce2a0bSSteven Rostedt print LOG if ($dolog); 700d6ce2a0bSSteven Rostedt print RD if ($dord); 701d6ce2a0bSSteven Rostedt } 7022545eb61SSteven Rostedt 703d6ce2a0bSSteven Rostedt waitpid($pid, 0); 7042545eb61SSteven Rostedt my $failed = $?; 7052545eb61SSteven Rostedt 706d6ce2a0bSSteven Rostedt close(CMD); 707d6ce2a0bSSteven Rostedt close(LOG) if ($dolog); 708d6ce2a0bSSteven Rostedt close(RD) if ($dord); 709d6ce2a0bSSteven Rostedt 7102545eb61SSteven Rostedt if ($failed) { 7112545eb61SSteven Rostedt doprint "FAILED!\n"; 7122545eb61SSteven Rostedt } else { 7132545eb61SSteven Rostedt doprint "SUCCESS\n"; 7142545eb61SSteven Rostedt } 7152545eb61SSteven Rostedt 7165f9b6cedSSteven Rostedt return !$failed; 7175f9b6cedSSteven Rostedt} 7185f9b6cedSSteven Rostedt 719e48c5293SSteven Rostedtsub run_ssh { 720e48c5293SSteven Rostedt my ($cmd) = @_; 721e48c5293SSteven Rostedt my $cp_exec = $ssh_exec; 722e48c5293SSteven Rostedt 723e48c5293SSteven Rostedt $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 724e48c5293SSteven Rostedt return run_command "$cp_exec"; 725e48c5293SSteven Rostedt} 726e48c5293SSteven Rostedt 727e48c5293SSteven Rostedtsub run_scp { 728e48c5293SSteven Rostedt my ($src, $dst) = @_; 729e48c5293SSteven Rostedt my $cp_scp = $scp_to_target; 730e48c5293SSteven Rostedt 731e48c5293SSteven Rostedt $cp_scp =~ s/\$SRC_FILE/$src/g; 732e48c5293SSteven Rostedt $cp_scp =~ s/\$DST_FILE/$dst/g; 733e48c5293SSteven Rostedt 734e48c5293SSteven Rostedt return run_command "$cp_scp"; 735e48c5293SSteven Rostedt} 736e48c5293SSteven Rostedt 7375f9b6cedSSteven Rostedtsub get_grub_index { 7385f9b6cedSSteven Rostedt 739a75fececSSteven Rostedt if ($reboot_type ne "grub") { 740a75fececSSteven Rostedt return; 741a75fececSSteven Rostedt } 7425a391fbfSSteven Rostedt return if (defined($grub_number)); 7435f9b6cedSSteven Rostedt 7445f9b6cedSSteven Rostedt doprint "Find grub menu ... "; 7455f9b6cedSSteven Rostedt $grub_number = -1; 746e48c5293SSteven Rostedt 747e48c5293SSteven Rostedt my $ssh_grub = $ssh_exec; 748e48c5293SSteven Rostedt $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 749e48c5293SSteven Rostedt 750e48c5293SSteven Rostedt open(IN, "$ssh_grub |") 7515f9b6cedSSteven Rostedt or die "unable to get menu.lst"; 752e48c5293SSteven Rostedt 7535f9b6cedSSteven Rostedt while (<IN>) { 754a75fececSSteven Rostedt if (/^\s*title\s+$grub_menu\s*$/) { 7555f9b6cedSSteven Rostedt $grub_number++; 7565f9b6cedSSteven Rostedt last; 7575f9b6cedSSteven Rostedt } elsif (/^\s*title\s/) { 7585f9b6cedSSteven Rostedt $grub_number++; 7595f9b6cedSSteven Rostedt } 7605f9b6cedSSteven Rostedt } 7615f9b6cedSSteven Rostedt close(IN); 7625f9b6cedSSteven Rostedt 763a75fececSSteven Rostedt die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 7645f9b6cedSSteven Rostedt if ($grub_number < 0); 7655f9b6cedSSteven Rostedt doprint "$grub_number\n"; 7662545eb61SSteven Rostedt} 7672545eb61SSteven Rostedt 7682545eb61SSteven Rostedtsub wait_for_input 7692545eb61SSteven Rostedt{ 7702545eb61SSteven Rostedt my ($fp, $time) = @_; 7712545eb61SSteven Rostedt my $rin; 7722545eb61SSteven Rostedt my $ready; 7732545eb61SSteven Rostedt my $line; 7742545eb61SSteven Rostedt my $ch; 7752545eb61SSteven Rostedt 7762545eb61SSteven Rostedt if (!defined($time)) { 7772545eb61SSteven Rostedt $time = $timeout; 7782545eb61SSteven Rostedt } 7792545eb61SSteven Rostedt 7802545eb61SSteven Rostedt $rin = ''; 7812545eb61SSteven Rostedt vec($rin, fileno($fp), 1) = 1; 7822545eb61SSteven Rostedt $ready = select($rin, undef, undef, $time); 7832545eb61SSteven Rostedt 7842545eb61SSteven Rostedt $line = ""; 7852545eb61SSteven Rostedt 7862545eb61SSteven Rostedt # try to read one char at a time 7872545eb61SSteven Rostedt while (sysread $fp, $ch, 1) { 7882545eb61SSteven Rostedt $line .= $ch; 7892545eb61SSteven Rostedt last if ($ch eq "\n"); 7902545eb61SSteven Rostedt } 7912545eb61SSteven Rostedt 7922545eb61SSteven Rostedt if (!length($line)) { 7932545eb61SSteven Rostedt return undef; 7942545eb61SSteven Rostedt } 7952545eb61SSteven Rostedt 7962545eb61SSteven Rostedt return $line; 7972545eb61SSteven Rostedt} 7982545eb61SSteven Rostedt 79975c3fda7SSteven Rostedtsub reboot_to { 800a75fececSSteven Rostedt if ($reboot_type eq "grub") { 8014da46da2SSteven Rostedt run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'"; 802a75fececSSteven Rostedt return; 803a75fececSSteven Rostedt } 804a75fececSSteven Rostedt 805a75fececSSteven Rostedt run_command "$reboot_script"; 8062545eb61SSteven Rostedt} 8072545eb61SSteven Rostedt 808a57419b3SSteven Rostedtsub get_sha1 { 809a57419b3SSteven Rostedt my ($commit) = @_; 810a57419b3SSteven Rostedt 811a57419b3SSteven Rostedt doprint "git rev-list --max-count=1 $commit ... "; 812a57419b3SSteven Rostedt my $sha1 = `git rev-list --max-count=1 $commit`; 813a57419b3SSteven Rostedt my $ret = $?; 814a57419b3SSteven Rostedt 815a57419b3SSteven Rostedt logit $sha1; 816a57419b3SSteven Rostedt 817a57419b3SSteven Rostedt if ($ret) { 818a57419b3SSteven Rostedt doprint "FAILED\n"; 819a57419b3SSteven Rostedt dodie "Failed to get git $commit"; 820a57419b3SSteven Rostedt } 821a57419b3SSteven Rostedt 822a57419b3SSteven Rostedt print "SUCCESS\n"; 823a57419b3SSteven Rostedt 824a57419b3SSteven Rostedt chomp $sha1; 825a57419b3SSteven Rostedt 826a57419b3SSteven Rostedt return $sha1; 827a57419b3SSteven Rostedt} 828a57419b3SSteven Rostedt 8295a391fbfSSteven Rostedtsub monitor { 8302545eb61SSteven Rostedt my $booted = 0; 8312545eb61SSteven Rostedt my $bug = 0; 8325c42fc5bSSteven Rostedt my $skip_call_trace = 0; 8332b7d9b21SSteven Rostedt my $loops; 8342545eb61SSteven Rostedt 8357faafbd6SSteven Rostedt wait_for_monitor 5; 8362545eb61SSteven Rostedt 8372545eb61SSteven Rostedt my $line; 8382545eb61SSteven Rostedt my $full_line = ""; 8392545eb61SSteven Rostedt 8407faafbd6SSteven Rostedt open(DMESG, "> $dmesg") or 8417faafbd6SSteven Rostedt die "unable to write to $dmesg"; 8422545eb61SSteven Rostedt 84375c3fda7SSteven Rostedt reboot_to; 8442545eb61SSteven Rostedt 8451c8a617aSSteven Rostedt my $success_start; 8461c8a617aSSteven Rostedt my $failure_start; 8472d01b26aSSteven Rostedt my $monitor_start = time; 8482d01b26aSSteven Rostedt my $done = 0; 849f1a5b962SSteven Rostedt my $version_found = 0; 8501c8a617aSSteven Rostedt 8512d01b26aSSteven Rostedt while (!$done) { 8522545eb61SSteven Rostedt 8532b7d9b21SSteven Rostedt if ($booted) { 854a75fececSSteven Rostedt $line = wait_for_input($monitor_fp, $booted_timeout); 855cd4f1d53SSteven Rostedt if (!defined($line)) { 856cd4f1d53SSteven Rostedt my $s = $booted_timeout == 1 ? "" : "s"; 857cd4f1d53SSteven Rostedt doprint "Successful boot found: break after $booted_timeout second$s\n"; 858cd4f1d53SSteven Rostedt last; 859cd4f1d53SSteven Rostedt } 8602b7d9b21SSteven Rostedt } else { 8617faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp); 862cd4f1d53SSteven Rostedt if (!defined($line)) { 863cd4f1d53SSteven Rostedt my $s = $timeout == 1 ? "" : "s"; 864cd4f1d53SSteven Rostedt doprint "Timed out after $timeout second$s\n"; 865cd4f1d53SSteven Rostedt last; 8662b7d9b21SSteven Rostedt } 867cd4f1d53SSteven Rostedt } 8682545eb61SSteven Rostedt 8692545eb61SSteven Rostedt doprint $line; 8707faafbd6SSteven Rostedt print DMESG $line; 8712545eb61SSteven Rostedt 8722545eb61SSteven Rostedt # we are not guaranteed to get a full line 8732545eb61SSteven Rostedt $full_line .= $line; 8742545eb61SSteven Rostedt 875a75fececSSteven Rostedt if ($full_line =~ /$success_line/) { 8762545eb61SSteven Rostedt $booted = 1; 8771c8a617aSSteven Rostedt $success_start = time; 8781c8a617aSSteven Rostedt } 8791c8a617aSSteven Rostedt 8801c8a617aSSteven Rostedt if ($booted && defined($stop_after_success) && 8811c8a617aSSteven Rostedt $stop_after_success >= 0) { 8821c8a617aSSteven Rostedt my $now = time; 8831c8a617aSSteven Rostedt if ($now - $success_start >= $stop_after_success) { 8841c8a617aSSteven Rostedt doprint "Test forced to stop after $stop_after_success seconds after success\n"; 8851c8a617aSSteven Rostedt last; 8861c8a617aSSteven Rostedt } 8872545eb61SSteven Rostedt } 8882545eb61SSteven Rostedt 8895c42fc5bSSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 8905c42fc5bSSteven Rostedt $skip_call_trace = 1; 8915c42fc5bSSteven Rostedt } 8925c42fc5bSSteven Rostedt 8932545eb61SSteven Rostedt if ($full_line =~ /call trace:/i) { 8944651920eSSteven Rostedt if (!$bug && !$skip_call_trace) { 8951c8a617aSSteven Rostedt $bug = 1; 8961c8a617aSSteven Rostedt $failure_start = time; 8971c8a617aSSteven Rostedt } 8981c8a617aSSteven Rostedt } 8991c8a617aSSteven Rostedt 9001c8a617aSSteven Rostedt if ($bug && defined($stop_after_failure) && 9011c8a617aSSteven Rostedt $stop_after_failure >= 0) { 9021c8a617aSSteven Rostedt my $now = time; 9031c8a617aSSteven Rostedt if ($now - $failure_start >= $stop_after_failure) { 9041c8a617aSSteven Rostedt doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 9051c8a617aSSteven Rostedt last; 9061c8a617aSSteven Rostedt } 9075c42fc5bSSteven Rostedt } 9085c42fc5bSSteven Rostedt 9095c42fc5bSSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 9105c42fc5bSSteven Rostedt $skip_call_trace = 0; 9115c42fc5bSSteven Rostedt } 9125c42fc5bSSteven Rostedt 9135c42fc5bSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 91410abf118SSteven Rostedt $failure_start = time; 9152545eb61SSteven Rostedt $bug = 1; 9162545eb61SSteven Rostedt } 9172545eb61SSteven Rostedt 918f1a5b962SSteven Rostedt # Detect triple faults by testing the banner 919f1a5b962SSteven Rostedt if ($full_line =~ /\bLinux version (\S+).*\n/) { 920f1a5b962SSteven Rostedt if ($1 eq $version) { 921f1a5b962SSteven Rostedt $version_found = 1; 922f1a5b962SSteven Rostedt } elsif ($version_found && $detect_triplefault) { 923f1a5b962SSteven Rostedt # We already booted into the kernel we are testing, 924f1a5b962SSteven Rostedt # but now we booted into another kernel? 925f1a5b962SSteven Rostedt # Consider this a triple fault. 926f1a5b962SSteven Rostedt doprint "Aleady booted in Linux kernel $version, but now\n"; 927f1a5b962SSteven Rostedt doprint "we booted into Linux kernel $1.\n"; 928f1a5b962SSteven Rostedt doprint "Assuming that this is a triple fault.\n"; 929f1a5b962SSteven Rostedt doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; 930f1a5b962SSteven Rostedt last; 931f1a5b962SSteven Rostedt } 932f1a5b962SSteven Rostedt } 933f1a5b962SSteven Rostedt 9342545eb61SSteven Rostedt if ($line =~ /\n/) { 9352545eb61SSteven Rostedt $full_line = ""; 9362545eb61SSteven Rostedt } 9372d01b26aSSteven Rostedt 9382d01b26aSSteven Rostedt if ($stop_test_after > 0 && !$booted && !$bug) { 9392d01b26aSSteven Rostedt if (time - $monitor_start > $stop_test_after) { 9404d62bf51SSteven Rostedt doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 9412d01b26aSSteven Rostedt $done = 1; 9422d01b26aSSteven Rostedt } 9432d01b26aSSteven Rostedt } 9442545eb61SSteven Rostedt } 9452545eb61SSteven Rostedt 9467faafbd6SSteven Rostedt close(DMESG); 9472545eb61SSteven Rostedt 9482545eb61SSteven Rostedt if ($bug) { 9492b7d9b21SSteven Rostedt return 0 if ($in_bisect); 950576f627cSSteven Rostedt fail "failed - got a bug report" and return 0; 9512545eb61SSteven Rostedt } 9525f9b6cedSSteven Rostedt 953a75fececSSteven Rostedt if (!$booted) { 954a75fececSSteven Rostedt return 0 if ($in_bisect); 955576f627cSSteven Rostedt fail "failed - never got a boot prompt." and return 0; 956a75fececSSteven Rostedt } 957a75fececSSteven Rostedt 9582b7d9b21SSteven Rostedt return 1; 9592545eb61SSteven Rostedt} 9602545eb61SSteven Rostedt 9612545eb61SSteven Rostedtsub install { 9622545eb61SSteven Rostedt 963e48c5293SSteven Rostedt run_scp "$outputdir/$build_target", "$target_image" or 9645c42fc5bSSteven Rostedt dodie "failed to copy image"; 9655f9b6cedSSteven Rostedt 9665f9b6cedSSteven Rostedt my $install_mods = 0; 9675f9b6cedSSteven Rostedt 9685f9b6cedSSteven Rostedt # should we process modules? 9695f9b6cedSSteven Rostedt $install_mods = 0; 97051ad1dd1SSteven Rostedt open(IN, "$output_config") or dodie("Can't read config file"); 9715f9b6cedSSteven Rostedt while (<IN>) { 9725f9b6cedSSteven Rostedt if (/CONFIG_MODULES(=y)?/) { 9735f9b6cedSSteven Rostedt $install_mods = 1 if (defined($1)); 9745f9b6cedSSteven Rostedt last; 9755f9b6cedSSteven Rostedt } 9765f9b6cedSSteven Rostedt } 9775f9b6cedSSteven Rostedt close(IN); 9785f9b6cedSSteven Rostedt 9795f9b6cedSSteven Rostedt if (!$install_mods) { 9805f9b6cedSSteven Rostedt doprint "No modules needed\n"; 9815f9b6cedSSteven Rostedt return; 9822545eb61SSteven Rostedt } 9832545eb61SSteven Rostedt 984a75fececSSteven Rostedt run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or 9855f9b6cedSSteven Rostedt dodie "Failed to install modules"; 9865f9b6cedSSteven Rostedt 9872545eb61SSteven Rostedt my $modlib = "/lib/modules/$version"; 988a57419b3SSteven Rostedt my $modtar = "ktest-mods.tar.bz2"; 9892545eb61SSteven Rostedt 990e48c5293SSteven Rostedt run_ssh "rm -rf $modlib" or 9915c42fc5bSSteven Rostedt dodie "failed to remove old mods: $modlib"; 9922545eb61SSteven Rostedt 9935c42fc5bSSteven Rostedt # would be nice if scp -r did not follow symbolic links 994a75fececSSteven Rostedt run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 9955c42fc5bSSteven Rostedt dodie "making tarball"; 9965c42fc5bSSteven Rostedt 997e48c5293SSteven Rostedt run_scp "$tmpdir/$modtar", "/tmp" or 9985c42fc5bSSteven Rostedt dodie "failed to copy modules"; 9995c42fc5bSSteven Rostedt 1000a75fececSSteven Rostedt unlink "$tmpdir/$modtar"; 10015c42fc5bSSteven Rostedt 1002e48c5293SSteven Rostedt run_ssh "'(cd / && tar xf /tmp/$modtar)'" or 10035c42fc5bSSteven Rostedt dodie "failed to tar modules"; 10045c42fc5bSSteven Rostedt 1005e48c5293SSteven Rostedt run_ssh "rm -f /tmp/$modtar"; 10068b37ca8cSSteven Rostedt 10078b37ca8cSSteven Rostedt return if (!defined($post_install)); 10088b37ca8cSSteven Rostedt 1009e48c5293SSteven Rostedt my $cp_post_install = $post_install; 1010ca6a21f8SSteven Rostedt $cp_post_install =~ s/\$KERNEL_VERSION/$version/g; 1011e48c5293SSteven Rostedt run_command "$cp_post_install" or 1012576f627cSSteven Rostedt dodie "Failed to run post install"; 10132545eb61SSteven Rostedt} 10142545eb61SSteven Rostedt 10156c5ee0beSSteven Rostedtsub check_buildlog { 10166c5ee0beSSteven Rostedt my ($patch) = @_; 10176c5ee0beSSteven Rostedt 10186c5ee0beSSteven Rostedt my @files = `git show $patch | diffstat -l`; 10196c5ee0beSSteven Rostedt 10206c5ee0beSSteven Rostedt open(IN, "git show $patch |") or 10216c5ee0beSSteven Rostedt dodie "failed to show $patch"; 10226c5ee0beSSteven Rostedt while (<IN>) { 10236c5ee0beSSteven Rostedt if (m,^--- a/(.*),) { 10246c5ee0beSSteven Rostedt chomp $1; 10256c5ee0beSSteven Rostedt $files[$#files] = $1; 10266c5ee0beSSteven Rostedt } 10276c5ee0beSSteven Rostedt } 10286c5ee0beSSteven Rostedt close(IN); 10296c5ee0beSSteven Rostedt 10306c5ee0beSSteven Rostedt open(IN, $buildlog) or dodie "Can't open $buildlog"; 10316c5ee0beSSteven Rostedt while (<IN>) { 10326c5ee0beSSteven Rostedt if (/^\s*(.*?):.*(warning|error)/) { 10336c5ee0beSSteven Rostedt my $err = $1; 10346c5ee0beSSteven Rostedt foreach my $file (@files) { 1035a75fececSSteven Rostedt my $fullpath = "$builddir/$file"; 10366c5ee0beSSteven Rostedt if ($file eq $err || $fullpath eq $err) { 10372b7d9b21SSteven Rostedt fail "$file built with warnings" and return 0; 10386c5ee0beSSteven Rostedt } 10396c5ee0beSSteven Rostedt } 10406c5ee0beSSteven Rostedt } 10416c5ee0beSSteven Rostedt } 10426c5ee0beSSteven Rostedt close(IN); 10432b7d9b21SSteven Rostedt 10442b7d9b21SSteven Rostedt return 1; 10456c5ee0beSSteven Rostedt} 10466c5ee0beSSteven Rostedt 1047612b9e9bSSteven Rostedtsub make_oldconfig { 1048612b9e9bSSteven Rostedt my ($defconfig) = @_; 1049612b9e9bSSteven Rostedt 1050612b9e9bSSteven Rostedt if (!run_command "$defconfig $make oldnoconfig") { 1051612b9e9bSSteven Rostedt # Perhaps oldnoconfig doesn't exist in this version of the kernel 1052612b9e9bSSteven Rostedt # try a yes '' | oldconfig 1053612b9e9bSSteven Rostedt doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 1054612b9e9bSSteven Rostedt run_command "yes '' | $defconfig $make oldconfig" or 1055612b9e9bSSteven Rostedt dodie "failed make config oldconfig"; 1056612b9e9bSSteven Rostedt } 1057612b9e9bSSteven Rostedt} 1058612b9e9bSSteven Rostedt 10592545eb61SSteven Rostedtsub build { 10602545eb61SSteven Rostedt my ($type) = @_; 10615c42fc5bSSteven Rostedt my $defconfig = ""; 10622545eb61SSteven Rostedt 10637faafbd6SSteven Rostedt unlink $buildlog; 10647faafbd6SSteven Rostedt 106575c3fda7SSteven Rostedt if ($type =~ /^useconfig:(.*)/) { 106651ad1dd1SSteven Rostedt run_command "cp $1 $output_config" or 106775c3fda7SSteven Rostedt dodie "could not copy $1 to .config"; 10685f9b6cedSSteven Rostedt 106975c3fda7SSteven Rostedt $type = "oldconfig"; 107075c3fda7SSteven Rostedt } 107175c3fda7SSteven Rostedt 10725c42fc5bSSteven Rostedt # old config can ask questions 10735c42fc5bSSteven Rostedt if ($type eq "oldconfig") { 10749386c6abSSteven Rostedt $type = "oldnoconfig"; 107575c3fda7SSteven Rostedt 107675c3fda7SSteven Rostedt # allow for empty configs 107751ad1dd1SSteven Rostedt run_command "touch $output_config"; 107875c3fda7SSteven Rostedt 107951ad1dd1SSteven Rostedt run_command "mv $output_config $outputdir/config_temp" or 10805c42fc5bSSteven Rostedt dodie "moving .config"; 10815c42fc5bSSteven Rostedt 10825f9b6cedSSteven Rostedt if (!$noclean && !run_command "$make mrproper") { 10835c42fc5bSSteven Rostedt dodie "make mrproper"; 10845c42fc5bSSteven Rostedt } 10855c42fc5bSSteven Rostedt 108651ad1dd1SSteven Rostedt run_command "mv $outputdir/config_temp $output_config" or 10875c42fc5bSSteven Rostedt dodie "moving config_temp"; 10885c42fc5bSSteven Rostedt 10895c42fc5bSSteven Rostedt } elsif (!$noclean) { 109051ad1dd1SSteven Rostedt unlink "$output_config"; 10915f9b6cedSSteven Rostedt run_command "$make mrproper" or 10925c42fc5bSSteven Rostedt dodie "make mrproper"; 10935c42fc5bSSteven Rostedt } 10942545eb61SSteven Rostedt 10952545eb61SSteven Rostedt # add something to distinguish this build 1096a75fececSSteven Rostedt open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 1097a75fececSSteven Rostedt print OUT "$localversion\n"; 10982545eb61SSteven Rostedt close(OUT); 10992545eb61SSteven Rostedt 11005f9b6cedSSteven Rostedt if (defined($minconfig)) { 11015f9b6cedSSteven Rostedt $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; 11022545eb61SSteven Rostedt } 11032545eb61SSteven Rostedt 1104612b9e9bSSteven Rostedt if ($type eq "oldnoconfig") { 1105612b9e9bSSteven Rostedt make_oldconfig $defconfig; 1106612b9e9bSSteven Rostedt } else { 11079386c6abSSteven Rostedt run_command "$defconfig $make $type" or 11085c42fc5bSSteven Rostedt dodie "failed make config"; 1109612b9e9bSSteven Rostedt } 11102545eb61SSteven Rostedt 1111a75fececSSteven Rostedt $redirect = "$buildlog"; 1112a75fececSSteven Rostedt if (!run_command "$make $build_options") { 11136c5ee0beSSteven Rostedt undef $redirect; 11145f9b6cedSSteven Rostedt # bisect may need this to pass 11152b7d9b21SSteven Rostedt return 0 if ($in_bisect); 11162b7d9b21SSteven Rostedt fail "failed build" and return 0; 11172545eb61SSteven Rostedt } 11186c5ee0beSSteven Rostedt undef $redirect; 11195f9b6cedSSteven Rostedt 11202b7d9b21SSteven Rostedt return 1; 11212545eb61SSteven Rostedt} 11222545eb61SSteven Rostedt 112375c3fda7SSteven Rostedtsub halt { 1124e48c5293SSteven Rostedt if (!run_ssh "halt" or defined($power_off)) { 1125576f627cSSteven Rostedt if (defined($poweroff_after_halt)) { 1126576f627cSSteven Rostedt sleep $poweroff_after_halt; 1127576f627cSSteven Rostedt run_command "$power_off"; 1128576f627cSSteven Rostedt } 1129576f627cSSteven Rostedt } else { 113075c3fda7SSteven Rostedt # nope? the zap it! 1131a75fececSSteven Rostedt run_command "$power_off"; 113275c3fda7SSteven Rostedt } 113375c3fda7SSteven Rostedt} 113475c3fda7SSteven Rostedt 11355f9b6cedSSteven Rostedtsub success { 11365f9b6cedSSteven Rostedt my ($i) = @_; 11375f9b6cedSSteven Rostedt 1138e48c5293SSteven Rostedt $successes++; 1139e48c5293SSteven Rostedt 1140*9064af52SSteven Rostedt my $name = ""; 1141*9064af52SSteven Rostedt 1142*9064af52SSteven Rostedt if (defined($test_name)) { 1143*9064af52SSteven Rostedt $name = " ($test_name)"; 1144*9064af52SSteven Rostedt } 1145*9064af52SSteven Rostedt 11465f9b6cedSSteven Rostedt doprint "\n\n*******************************************\n"; 11475f9b6cedSSteven Rostedt doprint "*******************************************\n"; 1148*9064af52SSteven Rostedt doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; 11495f9b6cedSSteven Rostedt doprint "*******************************************\n"; 11505f9b6cedSSteven Rostedt doprint "*******************************************\n"; 11515f9b6cedSSteven Rostedt 1152576f627cSSteven Rostedt if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 1153a75fececSSteven Rostedt doprint "Reboot and wait $sleep_time seconds\n"; 11545f9b6cedSSteven Rostedt reboot; 11557faafbd6SSteven Rostedt start_monitor; 1156a75fececSSteven Rostedt wait_for_monitor $sleep_time; 11577faafbd6SSteven Rostedt end_monitor; 11585f9b6cedSSteven Rostedt } 11595f9b6cedSSteven Rostedt} 11605f9b6cedSSteven Rostedt 11615f9b6cedSSteven Rostedtsub get_version { 11625f9b6cedSSteven Rostedt # get the release name 11635f9b6cedSSteven Rostedt doprint "$make kernelrelease ... "; 11645f9b6cedSSteven Rostedt $version = `$make kernelrelease | tail -1`; 11655f9b6cedSSteven Rostedt chomp($version); 11665f9b6cedSSteven Rostedt doprint "$version\n"; 11675f9b6cedSSteven Rostedt} 11685f9b6cedSSteven Rostedt 1169c960bb9fSSteven Rostedtsub answer_bisect { 1170c960bb9fSSteven Rostedt for (;;) { 1171c960bb9fSSteven Rostedt doprint "Pass or fail? [p/f]"; 1172c960bb9fSSteven Rostedt my $ans = <STDIN>; 1173c960bb9fSSteven Rostedt chomp $ans; 1174c960bb9fSSteven Rostedt if ($ans eq "p" || $ans eq "P") { 1175c960bb9fSSteven Rostedt return 1; 1176c960bb9fSSteven Rostedt } elsif ($ans eq "f" || $ans eq "F") { 1177c960bb9fSSteven Rostedt return 0; 1178c960bb9fSSteven Rostedt } else { 1179c960bb9fSSteven Rostedt print "Please answer 'P' or 'F'\n"; 1180c960bb9fSSteven Rostedt } 1181c960bb9fSSteven Rostedt } 1182c960bb9fSSteven Rostedt} 1183c960bb9fSSteven Rostedt 11845a391fbfSSteven Rostedtsub child_run_test { 11857faafbd6SSteven Rostedt my $failed = 0; 11865a391fbfSSteven Rostedt 11877faafbd6SSteven Rostedt # child should have no power 1188a75fececSSteven Rostedt $reboot_on_error = 0; 1189a75fececSSteven Rostedt $poweroff_on_error = 0; 1190a75fececSSteven Rostedt $die_on_failure = 1; 11917faafbd6SSteven Rostedt 11927faafbd6SSteven Rostedt run_command $run_test or $failed = 1; 11935a391fbfSSteven Rostedt exit $failed; 11945a391fbfSSteven Rostedt} 11955a391fbfSSteven Rostedt 11965a391fbfSSteven Rostedtmy $child_done; 11975a391fbfSSteven Rostedt 11985a391fbfSSteven Rostedtsub child_finished { 11995a391fbfSSteven Rostedt $child_done = 1; 12005a391fbfSSteven Rostedt} 12015a391fbfSSteven Rostedt 12025a391fbfSSteven Rostedtsub do_run_test { 12035a391fbfSSteven Rostedt my $child_pid; 12045a391fbfSSteven Rostedt my $child_exit; 12055a391fbfSSteven Rostedt my $line; 12065a391fbfSSteven Rostedt my $full_line; 12075a391fbfSSteven Rostedt my $bug = 0; 12085a391fbfSSteven Rostedt 12097faafbd6SSteven Rostedt wait_for_monitor 1; 12105a391fbfSSteven Rostedt 12117faafbd6SSteven Rostedt doprint "run test $run_test\n"; 12125a391fbfSSteven Rostedt 12135a391fbfSSteven Rostedt $child_done = 0; 12145a391fbfSSteven Rostedt 12155a391fbfSSteven Rostedt $SIG{CHLD} = qw(child_finished); 12165a391fbfSSteven Rostedt 12175a391fbfSSteven Rostedt $child_pid = fork; 12185a391fbfSSteven Rostedt 12195a391fbfSSteven Rostedt child_run_test if (!$child_pid); 12205a391fbfSSteven Rostedt 12215a391fbfSSteven Rostedt $full_line = ""; 12225a391fbfSSteven Rostedt 12235a391fbfSSteven Rostedt do { 12247faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 12255a391fbfSSteven Rostedt if (defined($line)) { 12265a391fbfSSteven Rostedt 12275a391fbfSSteven Rostedt # we are not guaranteed to get a full line 12285a391fbfSSteven Rostedt $full_line .= $line; 12298ea0e063SSteven Rostedt doprint $line; 12305a391fbfSSteven Rostedt 12315a391fbfSSteven Rostedt if ($full_line =~ /call trace:/i) { 12325a391fbfSSteven Rostedt $bug = 1; 12335a391fbfSSteven Rostedt } 12345a391fbfSSteven Rostedt 12355a391fbfSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 12365a391fbfSSteven Rostedt $bug = 1; 12375a391fbfSSteven Rostedt } 12385a391fbfSSteven Rostedt 12395a391fbfSSteven Rostedt if ($line =~ /\n/) { 12405a391fbfSSteven Rostedt $full_line = ""; 12415a391fbfSSteven Rostedt } 12425a391fbfSSteven Rostedt } 12435a391fbfSSteven Rostedt } while (!$child_done && !$bug); 12445a391fbfSSteven Rostedt 12455a391fbfSSteven Rostedt if ($bug) { 12468ea0e063SSteven Rostedt my $failure_start = time; 12478ea0e063SSteven Rostedt my $now; 12488ea0e063SSteven Rostedt do { 12498ea0e063SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 12508ea0e063SSteven Rostedt if (defined($line)) { 12518ea0e063SSteven Rostedt doprint $line; 12528ea0e063SSteven Rostedt } 12538ea0e063SSteven Rostedt $now = time; 12548ea0e063SSteven Rostedt if ($now - $failure_start >= $stop_after_failure) { 12558ea0e063SSteven Rostedt last; 12568ea0e063SSteven Rostedt } 12578ea0e063SSteven Rostedt } while (defined($line)); 12588ea0e063SSteven Rostedt 12595a391fbfSSteven Rostedt doprint "Detected kernel crash!\n"; 12605a391fbfSSteven Rostedt # kill the child with extreme prejudice 12615a391fbfSSteven Rostedt kill 9, $child_pid; 12625a391fbfSSteven Rostedt } 12635a391fbfSSteven Rostedt 12645a391fbfSSteven Rostedt waitpid $child_pid, 0; 12655a391fbfSSteven Rostedt $child_exit = $?; 12665a391fbfSSteven Rostedt 12675a391fbfSSteven Rostedt if ($bug || $child_exit) { 12682b7d9b21SSteven Rostedt return 0 if $in_bisect; 12692b7d9b21SSteven Rostedt fail "test failed" and return 0; 12705a391fbfSSteven Rostedt } 12712b7d9b21SSteven Rostedt return 1; 12725a391fbfSSteven Rostedt} 12735a391fbfSSteven Rostedt 1274a75fececSSteven Rostedtsub run_git_bisect { 1275a75fececSSteven Rostedt my ($command) = @_; 1276a75fececSSteven Rostedt 1277a75fececSSteven Rostedt doprint "$command ... "; 1278a75fececSSteven Rostedt 1279a75fececSSteven Rostedt my $output = `$command 2>&1`; 1280a75fececSSteven Rostedt my $ret = $?; 1281a75fececSSteven Rostedt 1282a75fececSSteven Rostedt logit $output; 1283a75fececSSteven Rostedt 1284a75fececSSteven Rostedt if ($ret) { 1285a75fececSSteven Rostedt doprint "FAILED\n"; 1286a75fececSSteven Rostedt dodie "Failed to git bisect"; 1287a75fececSSteven Rostedt } 1288a75fececSSteven Rostedt 1289a75fececSSteven Rostedt doprint "SUCCESS\n"; 1290a75fececSSteven Rostedt if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 1291a75fececSSteven Rostedt doprint "$1 [$2]\n"; 1292a75fececSSteven Rostedt } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 1293a75fececSSteven Rostedt $bisect_bad = $1; 1294a75fececSSteven Rostedt doprint "Found bad commit... $1\n"; 1295a75fececSSteven Rostedt return 0; 1296a75fececSSteven Rostedt } else { 1297a75fececSSteven Rostedt # we already logged it, just print it now. 1298a75fececSSteven Rostedt print $output; 1299a75fececSSteven Rostedt } 1300a75fececSSteven Rostedt 1301a75fececSSteven Rostedt return 1; 1302a75fececSSteven Rostedt} 1303a75fececSSteven Rostedt 1304c23dca7cSSteven Rostedtsub bisect_reboot { 1305c23dca7cSSteven Rostedt doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 1306c23dca7cSSteven Rostedt reboot; 1307c23dca7cSSteven Rostedt start_monitor; 1308c23dca7cSSteven Rostedt wait_for_monitor $bisect_sleep_time; 1309c23dca7cSSteven Rostedt end_monitor; 1310c23dca7cSSteven Rostedt} 1311c23dca7cSSteven Rostedt 1312c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip 13130a05c769SSteven Rostedtsub run_bisect_test { 13140a05c769SSteven Rostedt my ($type, $buildtype) = @_; 13155f9b6cedSSteven Rostedt 13162b7d9b21SSteven Rostedt my $failed = 0; 13175f9b6cedSSteven Rostedt my $result; 13185f9b6cedSSteven Rostedt my $output; 13195f9b6cedSSteven Rostedt my $ret; 13205f9b6cedSSteven Rostedt 13210a05c769SSteven Rostedt $in_bisect = 1; 13220a05c769SSteven Rostedt 13230a05c769SSteven Rostedt build $buildtype or $failed = 1; 13245f9b6cedSSteven Rostedt 13255f9b6cedSSteven Rostedt if ($type ne "build") { 1326c23dca7cSSteven Rostedt if ($failed && $bisect_skip) { 1327c23dca7cSSteven Rostedt $in_bisect = 0; 1328c23dca7cSSteven Rostedt return -1; 1329c23dca7cSSteven Rostedt } 13307faafbd6SSteven Rostedt dodie "Failed on build" if $failed; 13315f9b6cedSSteven Rostedt 13325f9b6cedSSteven Rostedt # Now boot the box 13335f9b6cedSSteven Rostedt get_grub_index; 13345f9b6cedSSteven Rostedt get_version; 13355f9b6cedSSteven Rostedt install; 13367faafbd6SSteven Rostedt 13377faafbd6SSteven Rostedt start_monitor; 13382b7d9b21SSteven Rostedt monitor or $failed = 1; 13395f9b6cedSSteven Rostedt 13405f9b6cedSSteven Rostedt if ($type ne "boot") { 1341c23dca7cSSteven Rostedt if ($failed && $bisect_skip) { 1342c23dca7cSSteven Rostedt end_monitor; 1343c23dca7cSSteven Rostedt bisect_reboot; 1344c23dca7cSSteven Rostedt $in_bisect = 0; 1345c23dca7cSSteven Rostedt return -1; 1346c23dca7cSSteven Rostedt } 13477faafbd6SSteven Rostedt dodie "Failed on boot" if $failed; 13485a391fbfSSteven Rostedt 13492b7d9b21SSteven Rostedt do_run_test or $failed = 1; 13505f9b6cedSSteven Rostedt } 13517faafbd6SSteven Rostedt end_monitor; 13525f9b6cedSSteven Rostedt } 13535f9b6cedSSteven Rostedt 13545f9b6cedSSteven Rostedt if ($failed) { 13550a05c769SSteven Rostedt $result = 0; 13565f9b6cedSSteven Rostedt } else { 13570a05c769SSteven Rostedt $result = 1; 13585f9b6cedSSteven Rostedt } 13594025bc62SSteven Rostedt 13604025bc62SSteven Rostedt # reboot the box to a kernel we can ssh to 13614025bc62SSteven Rostedt if ($type ne "build") { 13624025bc62SSteven Rostedt bisect_reboot; 13634025bc62SSteven Rostedt } 13640a05c769SSteven Rostedt $in_bisect = 0; 13650a05c769SSteven Rostedt 13660a05c769SSteven Rostedt return $result; 13670a05c769SSteven Rostedt} 13680a05c769SSteven Rostedt 13690a05c769SSteven Rostedtsub run_bisect { 13700a05c769SSteven Rostedt my ($type) = @_; 13710a05c769SSteven Rostedt my $buildtype = "oldconfig"; 13720a05c769SSteven Rostedt 13730a05c769SSteven Rostedt # We should have a minconfig to use? 13740a05c769SSteven Rostedt if (defined($minconfig)) { 13750a05c769SSteven Rostedt $buildtype = "useconfig:$minconfig"; 13760a05c769SSteven Rostedt } 13770a05c769SSteven Rostedt 13780a05c769SSteven Rostedt my $ret = run_bisect_test $type, $buildtype; 13790a05c769SSteven Rostedt 1380c960bb9fSSteven Rostedt if ($bisect_manual) { 1381c960bb9fSSteven Rostedt $ret = answer_bisect; 1382c960bb9fSSteven Rostedt } 13835f9b6cedSSteven Rostedt 1384d6ce2a0bSSteven Rostedt # Are we looking for where it worked, not failed? 1385d6ce2a0bSSteven Rostedt if ($reverse_bisect) { 13860a05c769SSteven Rostedt $ret = !$ret; 1387d6ce2a0bSSteven Rostedt } 1388d6ce2a0bSSteven Rostedt 1389c23dca7cSSteven Rostedt if ($ret > 0) { 13900a05c769SSteven Rostedt return "good"; 1391c23dca7cSSteven Rostedt } elsif ($ret == 0) { 13920a05c769SSteven Rostedt return "bad"; 1393c23dca7cSSteven Rostedt } elsif ($bisect_skip) { 1394c23dca7cSSteven Rostedt doprint "HIT A BAD COMMIT ... SKIPPING\n"; 1395c23dca7cSSteven Rostedt return "skip"; 13960a05c769SSteven Rostedt } 13975f9b6cedSSteven Rostedt} 13985f9b6cedSSteven Rostedt 13995f9b6cedSSteven Rostedtsub bisect { 14005f9b6cedSSteven Rostedt my ($i) = @_; 14015f9b6cedSSteven Rostedt 14025f9b6cedSSteven Rostedt my $result; 14035f9b6cedSSteven Rostedt 14045f9b6cedSSteven Rostedt die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 14055f9b6cedSSteven Rostedt die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 14065f9b6cedSSteven Rostedt die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 14075f9b6cedSSteven Rostedt 14085f9b6cedSSteven Rostedt my $good = $opt{"BISECT_GOOD[$i]"}; 14095f9b6cedSSteven Rostedt my $bad = $opt{"BISECT_BAD[$i]"}; 14105f9b6cedSSteven Rostedt my $type = $opt{"BISECT_TYPE[$i]"}; 1411a75fececSSteven Rostedt my $start = $opt{"BISECT_START[$i]"}; 1412a75fececSSteven Rostedt my $replay = $opt{"BISECT_REPLAY[$i]"}; 14133410f6fdSSteven Rostedt my $start_files = $opt{"BISECT_FILES[$i]"}; 14143410f6fdSSteven Rostedt 14153410f6fdSSteven Rostedt if (defined($start_files)) { 14163410f6fdSSteven Rostedt $start_files = " -- " . $start_files; 14173410f6fdSSteven Rostedt } else { 14183410f6fdSSteven Rostedt $start_files = ""; 14193410f6fdSSteven Rostedt } 14205f9b6cedSSteven Rostedt 1421a57419b3SSteven Rostedt # convert to true sha1's 1422a57419b3SSteven Rostedt $good = get_sha1($good); 1423a57419b3SSteven Rostedt $bad = get_sha1($bad); 1424a57419b3SSteven Rostedt 1425d6ce2a0bSSteven Rostedt if (defined($opt{"BISECT_REVERSE[$i]"}) && 1426d6ce2a0bSSteven Rostedt $opt{"BISECT_REVERSE[$i]"} == 1) { 1427d6ce2a0bSSteven Rostedt doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 1428d6ce2a0bSSteven Rostedt $reverse_bisect = 1; 1429d6ce2a0bSSteven Rostedt } else { 1430d6ce2a0bSSteven Rostedt $reverse_bisect = 0; 1431d6ce2a0bSSteven Rostedt } 1432d6ce2a0bSSteven Rostedt 14335a391fbfSSteven Rostedt # Can't have a test without having a test to run 14345a391fbfSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 14355a391fbfSSteven Rostedt $type = "boot"; 14365a391fbfSSteven Rostedt } 14375a391fbfSSteven Rostedt 1438a75fececSSteven Rostedt my $check = $opt{"BISECT_CHECK[$i]"}; 1439a75fececSSteven Rostedt if (defined($check) && $check ne "0") { 1440a75fececSSteven Rostedt 1441a75fececSSteven Rostedt # get current HEAD 1442a57419b3SSteven Rostedt my $head = get_sha1("HEAD"); 1443a75fececSSteven Rostedt 1444a75fececSSteven Rostedt if ($check ne "good") { 1445a75fececSSteven Rostedt doprint "TESTING BISECT BAD [$bad]\n"; 1446a75fececSSteven Rostedt run_command "git checkout $bad" or 1447a75fececSSteven Rostedt die "Failed to checkout $bad"; 1448a75fececSSteven Rostedt 1449a75fececSSteven Rostedt $result = run_bisect $type; 1450a75fececSSteven Rostedt 1451a75fececSSteven Rostedt if ($result ne "bad") { 1452a75fececSSteven Rostedt fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 1453a75fececSSteven Rostedt } 1454a75fececSSteven Rostedt } 1455a75fececSSteven Rostedt 1456a75fececSSteven Rostedt if ($check ne "bad") { 1457a75fececSSteven Rostedt doprint "TESTING BISECT GOOD [$good]\n"; 1458a75fececSSteven Rostedt run_command "git checkout $good" or 1459a75fececSSteven Rostedt die "Failed to checkout $good"; 1460a75fececSSteven Rostedt 1461a75fececSSteven Rostedt $result = run_bisect $type; 1462a75fececSSteven Rostedt 1463a75fececSSteven Rostedt if ($result ne "good") { 1464a75fececSSteven Rostedt fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 1465a75fececSSteven Rostedt } 1466a75fececSSteven Rostedt } 1467a75fececSSteven Rostedt 1468a75fececSSteven Rostedt # checkout where we started 1469a75fececSSteven Rostedt run_command "git checkout $head" or 1470a75fececSSteven Rostedt die "Failed to checkout $head"; 1471a75fececSSteven Rostedt } 1472a75fececSSteven Rostedt 14733410f6fdSSteven Rostedt run_command "git bisect start$start_files" or 1474a75fececSSteven Rostedt dodie "could not start bisect"; 1475a75fececSSteven Rostedt 1476a75fececSSteven Rostedt run_command "git bisect good $good" or 1477a75fececSSteven Rostedt dodie "could not set bisect good to $good"; 1478a75fececSSteven Rostedt 1479a75fececSSteven Rostedt run_git_bisect "git bisect bad $bad" or 1480a75fececSSteven Rostedt dodie "could not set bisect bad to $bad"; 1481a75fececSSteven Rostedt 1482a75fececSSteven Rostedt if (defined($replay)) { 1483a75fececSSteven Rostedt run_command "git bisect replay $replay" or 1484a75fececSSteven Rostedt dodie "failed to run replay"; 1485a75fececSSteven Rostedt } 1486a75fececSSteven Rostedt 1487a75fececSSteven Rostedt if (defined($start)) { 1488a75fececSSteven Rostedt run_command "git checkout $start" or 1489a75fececSSteven Rostedt dodie "failed to checkout $start"; 1490a75fececSSteven Rostedt } 1491a75fececSSteven Rostedt 1492a75fececSSteven Rostedt my $test; 14935f9b6cedSSteven Rostedt do { 14945f9b6cedSSteven Rostedt $result = run_bisect $type; 1495a75fececSSteven Rostedt $test = run_git_bisect "git bisect $result"; 1496a75fececSSteven Rostedt } while ($test); 14975f9b6cedSSteven Rostedt 14985f9b6cedSSteven Rostedt run_command "git bisect log" or 14995f9b6cedSSteven Rostedt dodie "could not capture git bisect log"; 15005f9b6cedSSteven Rostedt 15015f9b6cedSSteven Rostedt run_command "git bisect reset" or 15025f9b6cedSSteven Rostedt dodie "could not reset git bisect"; 15035f9b6cedSSteven Rostedt 15045f9b6cedSSteven Rostedt doprint "Bad commit was [$bisect_bad]\n"; 15055f9b6cedSSteven Rostedt 15060a05c769SSteven Rostedt success $i; 15070a05c769SSteven Rostedt} 15080a05c769SSteven Rostedt 15090a05c769SSteven Rostedtmy %config_ignore; 15100a05c769SSteven Rostedtmy %config_set; 15110a05c769SSteven Rostedt 15120a05c769SSteven Rostedtmy %config_list; 15130a05c769SSteven Rostedtmy %null_config; 15140a05c769SSteven Rostedt 15150a05c769SSteven Rostedtmy %dependency; 15160a05c769SSteven Rostedt 15170a05c769SSteven Rostedtsub process_config_ignore { 15180a05c769SSteven Rostedt my ($config) = @_; 15190a05c769SSteven Rostedt 15200a05c769SSteven Rostedt open (IN, $config) 15210a05c769SSteven Rostedt or dodie "Failed to read $config"; 15220a05c769SSteven Rostedt 15230a05c769SSteven Rostedt while (<IN>) { 15249bf71749SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 15250a05c769SSteven Rostedt $config_ignore{$2} = $1; 15260a05c769SSteven Rostedt } 15270a05c769SSteven Rostedt } 15280a05c769SSteven Rostedt 15290a05c769SSteven Rostedt close(IN); 15300a05c769SSteven Rostedt} 15310a05c769SSteven Rostedt 15320a05c769SSteven Rostedtsub read_current_config { 15330a05c769SSteven Rostedt my ($config_ref) = @_; 15340a05c769SSteven Rostedt 15350a05c769SSteven Rostedt %{$config_ref} = (); 15360a05c769SSteven Rostedt undef %{$config_ref}; 15370a05c769SSteven Rostedt 15380a05c769SSteven Rostedt my @key = keys %{$config_ref}; 15390a05c769SSteven Rostedt if ($#key >= 0) { 15400a05c769SSteven Rostedt print "did not delete!\n"; 15410a05c769SSteven Rostedt exit; 15420a05c769SSteven Rostedt } 15430a05c769SSteven Rostedt open (IN, "$output_config"); 15440a05c769SSteven Rostedt 15450a05c769SSteven Rostedt while (<IN>) { 15460a05c769SSteven Rostedt if (/^(CONFIG\S+)=(.*)/) { 15470a05c769SSteven Rostedt ${$config_ref}{$1} = $2; 15480a05c769SSteven Rostedt } 15490a05c769SSteven Rostedt } 15500a05c769SSteven Rostedt close(IN); 15510a05c769SSteven Rostedt} 15520a05c769SSteven Rostedt 15530a05c769SSteven Rostedtsub get_dependencies { 15540a05c769SSteven Rostedt my ($config) = @_; 15550a05c769SSteven Rostedt 15560a05c769SSteven Rostedt my $arr = $dependency{$config}; 15570a05c769SSteven Rostedt if (!defined($arr)) { 15580a05c769SSteven Rostedt return (); 15590a05c769SSteven Rostedt } 15600a05c769SSteven Rostedt 15610a05c769SSteven Rostedt my @deps = @{$arr}; 15620a05c769SSteven Rostedt 15630a05c769SSteven Rostedt foreach my $dep (@{$arr}) { 15640a05c769SSteven Rostedt print "ADD DEP $dep\n"; 15650a05c769SSteven Rostedt @deps = (@deps, get_dependencies $dep); 15660a05c769SSteven Rostedt } 15670a05c769SSteven Rostedt 15680a05c769SSteven Rostedt return @deps; 15690a05c769SSteven Rostedt} 15700a05c769SSteven Rostedt 15710a05c769SSteven Rostedtsub create_config { 15720a05c769SSteven Rostedt my @configs = @_; 15730a05c769SSteven Rostedt 15740a05c769SSteven Rostedt open(OUT, ">$output_config") or dodie "Can not write to $output_config"; 15750a05c769SSteven Rostedt 15760a05c769SSteven Rostedt foreach my $config (@configs) { 15770a05c769SSteven Rostedt print OUT "$config_set{$config}\n"; 15780a05c769SSteven Rostedt my @deps = get_dependencies $config; 15790a05c769SSteven Rostedt foreach my $dep (@deps) { 15800a05c769SSteven Rostedt print OUT "$config_set{$dep}\n"; 15810a05c769SSteven Rostedt } 15820a05c769SSteven Rostedt } 15830a05c769SSteven Rostedt 15840a05c769SSteven Rostedt foreach my $config (keys %config_ignore) { 15850a05c769SSteven Rostedt print OUT "$config_ignore{$config}\n"; 15860a05c769SSteven Rostedt } 15870a05c769SSteven Rostedt close(OUT); 15880a05c769SSteven Rostedt 15890a05c769SSteven Rostedt# exit; 1590612b9e9bSSteven Rostedt make_oldconfig ""; 15910a05c769SSteven Rostedt} 15920a05c769SSteven Rostedt 15930a05c769SSteven Rostedtsub compare_configs { 15940a05c769SSteven Rostedt my (%a, %b) = @_; 15950a05c769SSteven Rostedt 15960a05c769SSteven Rostedt foreach my $item (keys %a) { 15970a05c769SSteven Rostedt if (!defined($b{$item})) { 15980a05c769SSteven Rostedt print "diff $item\n"; 15990a05c769SSteven Rostedt return 1; 16000a05c769SSteven Rostedt } 16010a05c769SSteven Rostedt delete $b{$item}; 16020a05c769SSteven Rostedt } 16030a05c769SSteven Rostedt 16040a05c769SSteven Rostedt my @keys = keys %b; 16050a05c769SSteven Rostedt if ($#keys) { 16060a05c769SSteven Rostedt print "diff2 $keys[0]\n"; 16070a05c769SSteven Rostedt } 16080a05c769SSteven Rostedt return -1 if ($#keys >= 0); 16090a05c769SSteven Rostedt 16100a05c769SSteven Rostedt return 0; 16110a05c769SSteven Rostedt} 16120a05c769SSteven Rostedt 16130a05c769SSteven Rostedtsub run_config_bisect_test { 16140a05c769SSteven Rostedt my ($type) = @_; 16150a05c769SSteven Rostedt 16160a05c769SSteven Rostedt return run_bisect_test $type, "oldconfig"; 16170a05c769SSteven Rostedt} 16180a05c769SSteven Rostedt 16190a05c769SSteven Rostedtsub process_passed { 16200a05c769SSteven Rostedt my (%configs) = @_; 16210a05c769SSteven Rostedt 16220a05c769SSteven Rostedt doprint "These configs had no failure: (Enabling them for further compiles)\n"; 16230a05c769SSteven Rostedt # Passed! All these configs are part of a good compile. 16240a05c769SSteven Rostedt # Add them to the min options. 16250a05c769SSteven Rostedt foreach my $config (keys %configs) { 16260a05c769SSteven Rostedt if (defined($config_list{$config})) { 16270a05c769SSteven Rostedt doprint " removing $config\n"; 16280a05c769SSteven Rostedt $config_ignore{$config} = $config_list{$config}; 16290a05c769SSteven Rostedt delete $config_list{$config}; 16300a05c769SSteven Rostedt } 16310a05c769SSteven Rostedt } 1632f1a27850SSteven Rostedt doprint "config copied to $outputdir/config_good\n"; 1633f1a27850SSteven Rostedt run_command "cp -f $output_config $outputdir/config_good"; 16340a05c769SSteven Rostedt} 16350a05c769SSteven Rostedt 16360a05c769SSteven Rostedtsub process_failed { 16370a05c769SSteven Rostedt my ($config) = @_; 16380a05c769SSteven Rostedt 16390a05c769SSteven Rostedt doprint "\n\n***************************************\n"; 16400a05c769SSteven Rostedt doprint "Found bad config: $config\n"; 16410a05c769SSteven Rostedt doprint "***************************************\n\n"; 16420a05c769SSteven Rostedt} 16430a05c769SSteven Rostedt 16440a05c769SSteven Rostedtsub run_config_bisect { 16450a05c769SSteven Rostedt 16460a05c769SSteven Rostedt my @start_list = keys %config_list; 16470a05c769SSteven Rostedt 16480a05c769SSteven Rostedt if ($#start_list < 0) { 16490a05c769SSteven Rostedt doprint "No more configs to test!!!\n"; 16500a05c769SSteven Rostedt return -1; 16510a05c769SSteven Rostedt } 16520a05c769SSteven Rostedt 16530a05c769SSteven Rostedt doprint "***** RUN TEST ***\n"; 16540a05c769SSteven Rostedt my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"}; 16550a05c769SSteven Rostedt my $ret; 16560a05c769SSteven Rostedt my %current_config; 16570a05c769SSteven Rostedt 16580a05c769SSteven Rostedt my $count = $#start_list + 1; 16590a05c769SSteven Rostedt doprint " $count configs to test\n"; 16600a05c769SSteven Rostedt 16610a05c769SSteven Rostedt my $half = int($#start_list / 2); 16620a05c769SSteven Rostedt 16630a05c769SSteven Rostedt do { 16640a05c769SSteven Rostedt my @tophalf = @start_list[0 .. $half]; 16650a05c769SSteven Rostedt 16660a05c769SSteven Rostedt create_config @tophalf; 16670a05c769SSteven Rostedt read_current_config \%current_config; 16680a05c769SSteven Rostedt 16690a05c769SSteven Rostedt $count = $#tophalf + 1; 16700a05c769SSteven Rostedt doprint "Testing $count configs\n"; 16710a05c769SSteven Rostedt my $found = 0; 16720a05c769SSteven Rostedt # make sure we test something 16730a05c769SSteven Rostedt foreach my $config (@tophalf) { 16740a05c769SSteven Rostedt if (defined($current_config{$config})) { 16750a05c769SSteven Rostedt logit " $config\n"; 16760a05c769SSteven Rostedt $found = 1; 16770a05c769SSteven Rostedt } 16780a05c769SSteven Rostedt } 16790a05c769SSteven Rostedt if (!$found) { 16800a05c769SSteven Rostedt # try the other half 16810a05c769SSteven Rostedt doprint "Top half produced no set configs, trying bottom half\n"; 16824c8cc55bSSteven Rostedt @tophalf = @start_list[$half + 1 .. $#start_list]; 16830a05c769SSteven Rostedt create_config @tophalf; 16840a05c769SSteven Rostedt read_current_config \%current_config; 16850a05c769SSteven Rostedt foreach my $config (@tophalf) { 16860a05c769SSteven Rostedt if (defined($current_config{$config})) { 16870a05c769SSteven Rostedt logit " $config\n"; 16880a05c769SSteven Rostedt $found = 1; 16890a05c769SSteven Rostedt } 16900a05c769SSteven Rostedt } 16910a05c769SSteven Rostedt if (!$found) { 16920a05c769SSteven Rostedt doprint "Failed: Can't make new config with current configs\n"; 16930a05c769SSteven Rostedt foreach my $config (@start_list) { 16940a05c769SSteven Rostedt doprint " CONFIG: $config\n"; 16950a05c769SSteven Rostedt } 16960a05c769SSteven Rostedt return -1; 16970a05c769SSteven Rostedt } 16980a05c769SSteven Rostedt $count = $#tophalf + 1; 16990a05c769SSteven Rostedt doprint "Testing $count configs\n"; 17000a05c769SSteven Rostedt } 17010a05c769SSteven Rostedt 17020a05c769SSteven Rostedt $ret = run_config_bisect_test $type; 1703c960bb9fSSteven Rostedt if ($bisect_manual) { 1704c960bb9fSSteven Rostedt $ret = answer_bisect; 1705c960bb9fSSteven Rostedt } 17060a05c769SSteven Rostedt if ($ret) { 17070a05c769SSteven Rostedt process_passed %current_config; 17080a05c769SSteven Rostedt return 0; 17090a05c769SSteven Rostedt } 17100a05c769SSteven Rostedt 17110a05c769SSteven Rostedt doprint "This config had a failure.\n"; 17120a05c769SSteven Rostedt doprint "Removing these configs that were not set in this config:\n"; 1713f1a27850SSteven Rostedt doprint "config copied to $outputdir/config_bad\n"; 1714f1a27850SSteven Rostedt run_command "cp -f $output_config $outputdir/config_bad"; 17150a05c769SSteven Rostedt 17160a05c769SSteven Rostedt # A config exists in this group that was bad. 17170a05c769SSteven Rostedt foreach my $config (keys %config_list) { 17180a05c769SSteven Rostedt if (!defined($current_config{$config})) { 17190a05c769SSteven Rostedt doprint " removing $config\n"; 17200a05c769SSteven Rostedt delete $config_list{$config}; 17210a05c769SSteven Rostedt } 17220a05c769SSteven Rostedt } 17230a05c769SSteven Rostedt 17240a05c769SSteven Rostedt @start_list = @tophalf; 17250a05c769SSteven Rostedt 17260a05c769SSteven Rostedt if ($#start_list == 0) { 17270a05c769SSteven Rostedt process_failed $start_list[0]; 17280a05c769SSteven Rostedt return 1; 17290a05c769SSteven Rostedt } 17300a05c769SSteven Rostedt 17310a05c769SSteven Rostedt # remove half the configs we are looking at and see if 17320a05c769SSteven Rostedt # they are good. 17330a05c769SSteven Rostedt $half = int($#start_list / 2); 17344c8cc55bSSteven Rostedt } while ($#start_list > 0); 17350a05c769SSteven Rostedt 1736c960bb9fSSteven Rostedt # we found a single config, try it again unless we are running manually 1737c960bb9fSSteven Rostedt 1738c960bb9fSSteven Rostedt if ($bisect_manual) { 1739c960bb9fSSteven Rostedt process_failed $start_list[0]; 1740c960bb9fSSteven Rostedt return 1; 1741c960bb9fSSteven Rostedt } 1742c960bb9fSSteven Rostedt 17430a05c769SSteven Rostedt my @tophalf = @start_list[0 .. 0]; 17440a05c769SSteven Rostedt 17450a05c769SSteven Rostedt $ret = run_config_bisect_test $type; 17460a05c769SSteven Rostedt if ($ret) { 17470a05c769SSteven Rostedt process_passed %current_config; 17480a05c769SSteven Rostedt return 0; 17490a05c769SSteven Rostedt } 17500a05c769SSteven Rostedt 17510a05c769SSteven Rostedt process_failed $start_list[0]; 17520a05c769SSteven Rostedt return 1; 17530a05c769SSteven Rostedt} 17540a05c769SSteven Rostedt 17550a05c769SSteven Rostedtsub config_bisect { 17560a05c769SSteven Rostedt my ($i) = @_; 17570a05c769SSteven Rostedt 17580a05c769SSteven Rostedt my $start_config = $opt{"CONFIG_BISECT[$i]"}; 17590a05c769SSteven Rostedt 17600a05c769SSteven Rostedt my $tmpconfig = "$tmpdir/use_config"; 17610a05c769SSteven Rostedt 176230f75da5SSteven Rostedt if (defined($config_bisect_good)) { 176330f75da5SSteven Rostedt process_config_ignore $config_bisect_good; 176430f75da5SSteven Rostedt } 176530f75da5SSteven Rostedt 17660a05c769SSteven Rostedt # Make the file with the bad config and the min config 17670a05c769SSteven Rostedt if (defined($minconfig)) { 17680a05c769SSteven Rostedt # read the min config for things to ignore 17690a05c769SSteven Rostedt run_command "cp $minconfig $tmpconfig" or 17700a05c769SSteven Rostedt dodie "failed to copy $minconfig to $tmpconfig"; 17710a05c769SSteven Rostedt } else { 17720a05c769SSteven Rostedt unlink $tmpconfig; 17730a05c769SSteven Rostedt } 17740a05c769SSteven Rostedt 17750a05c769SSteven Rostedt # Add other configs 17760a05c769SSteven Rostedt if (defined($addconfig)) { 17770a05c769SSteven Rostedt run_command "cat $addconfig >> $tmpconfig" or 17780a05c769SSteven Rostedt dodie "failed to append $addconfig"; 17790a05c769SSteven Rostedt } 17800a05c769SSteven Rostedt 17810a05c769SSteven Rostedt my $defconfig = ""; 17820a05c769SSteven Rostedt if (-f $tmpconfig) { 17830a05c769SSteven Rostedt $defconfig = "KCONFIG_ALLCONFIG=$tmpconfig"; 17840a05c769SSteven Rostedt process_config_ignore $tmpconfig; 17850a05c769SSteven Rostedt } 17860a05c769SSteven Rostedt 17870a05c769SSteven Rostedt # now process the start config 17880a05c769SSteven Rostedt run_command "cp $start_config $output_config" or 17890a05c769SSteven Rostedt dodie "failed to copy $start_config to $output_config"; 17900a05c769SSteven Rostedt 17910a05c769SSteven Rostedt # read directly what we want to check 17920a05c769SSteven Rostedt my %config_check; 17930a05c769SSteven Rostedt open (IN, $output_config) 17940a05c769SSteven Rostedt or dodie "faied to open $output_config"; 17950a05c769SSteven Rostedt 17960a05c769SSteven Rostedt while (<IN>) { 17970a05c769SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 17980a05c769SSteven Rostedt $config_check{$2} = $1; 17990a05c769SSteven Rostedt } 18000a05c769SSteven Rostedt } 18010a05c769SSteven Rostedt close(IN); 18020a05c769SSteven Rostedt 18030a05c769SSteven Rostedt # Now run oldconfig with the minconfig (and addconfigs) 1804612b9e9bSSteven Rostedt make_oldconfig $defconfig; 18050a05c769SSteven Rostedt 18060a05c769SSteven Rostedt # check to see what we lost (or gained) 18070a05c769SSteven Rostedt open (IN, $output_config) 18080a05c769SSteven Rostedt or dodie "Failed to read $start_config"; 18090a05c769SSteven Rostedt 18100a05c769SSteven Rostedt my %removed_configs; 18110a05c769SSteven Rostedt my %added_configs; 18120a05c769SSteven Rostedt 18130a05c769SSteven Rostedt while (<IN>) { 18140a05c769SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 18150a05c769SSteven Rostedt # save off all options 18160a05c769SSteven Rostedt $config_set{$2} = $1; 18170a05c769SSteven Rostedt if (defined($config_check{$2})) { 18180a05c769SSteven Rostedt if (defined($config_ignore{$2})) { 18190a05c769SSteven Rostedt $removed_configs{$2} = $1; 18200a05c769SSteven Rostedt } else { 18210a05c769SSteven Rostedt $config_list{$2} = $1; 18220a05c769SSteven Rostedt } 18230a05c769SSteven Rostedt } elsif (!defined($config_ignore{$2})) { 18240a05c769SSteven Rostedt $added_configs{$2} = $1; 18250a05c769SSteven Rostedt $config_list{$2} = $1; 18260a05c769SSteven Rostedt } 18270a05c769SSteven Rostedt } 18280a05c769SSteven Rostedt } 18290a05c769SSteven Rostedt close(IN); 18300a05c769SSteven Rostedt 18310a05c769SSteven Rostedt my @confs = keys %removed_configs; 18320a05c769SSteven Rostedt if ($#confs >= 0) { 18330a05c769SSteven Rostedt doprint "Configs overridden by default configs and removed from check:\n"; 18340a05c769SSteven Rostedt foreach my $config (@confs) { 18350a05c769SSteven Rostedt doprint " $config\n"; 18360a05c769SSteven Rostedt } 18370a05c769SSteven Rostedt } 18380a05c769SSteven Rostedt @confs = keys %added_configs; 18390a05c769SSteven Rostedt if ($#confs >= 0) { 18400a05c769SSteven Rostedt doprint "Configs appearing in make oldconfig and added:\n"; 18410a05c769SSteven Rostedt foreach my $config (@confs) { 18420a05c769SSteven Rostedt doprint " $config\n"; 18430a05c769SSteven Rostedt } 18440a05c769SSteven Rostedt } 18450a05c769SSteven Rostedt 18460a05c769SSteven Rostedt my %config_test; 18470a05c769SSteven Rostedt my $once = 0; 18480a05c769SSteven Rostedt 18490a05c769SSteven Rostedt # Sometimes kconfig does weird things. We must make sure 18500a05c769SSteven Rostedt # that the config we autocreate has everything we need 18510a05c769SSteven Rostedt # to test, otherwise we may miss testing configs, or 18520a05c769SSteven Rostedt # may not be able to create a new config. 18530a05c769SSteven Rostedt # Here we create a config with everything set. 18540a05c769SSteven Rostedt create_config (keys %config_list); 18550a05c769SSteven Rostedt read_current_config \%config_test; 18560a05c769SSteven Rostedt foreach my $config (keys %config_list) { 18570a05c769SSteven Rostedt if (!defined($config_test{$config})) { 18580a05c769SSteven Rostedt if (!$once) { 18590a05c769SSteven Rostedt $once = 1; 18600a05c769SSteven Rostedt doprint "Configs not produced by kconfig (will not be checked):\n"; 18610a05c769SSteven Rostedt } 18620a05c769SSteven Rostedt doprint " $config\n"; 18630a05c769SSteven Rostedt delete $config_list{$config}; 18640a05c769SSteven Rostedt } 18650a05c769SSteven Rostedt } 18660a05c769SSteven Rostedt my $ret; 18670a05c769SSteven Rostedt do { 18680a05c769SSteven Rostedt $ret = run_config_bisect; 18690a05c769SSteven Rostedt } while (!$ret); 18700a05c769SSteven Rostedt 18710a05c769SSteven Rostedt return $ret if ($ret < 0); 18725f9b6cedSSteven Rostedt 18735f9b6cedSSteven Rostedt success $i; 18745f9b6cedSSteven Rostedt} 18755f9b6cedSSteven Rostedt 187627d934b2SSteven Rostedtsub patchcheck_reboot { 187727d934b2SSteven Rostedt doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 187827d934b2SSteven Rostedt reboot; 187927d934b2SSteven Rostedt start_monitor; 188027d934b2SSteven Rostedt wait_for_monitor $patchcheck_sleep_time; 188127d934b2SSteven Rostedt end_monitor; 188227d934b2SSteven Rostedt} 188327d934b2SSteven Rostedt 18846c5ee0beSSteven Rostedtsub patchcheck { 18856c5ee0beSSteven Rostedt my ($i) = @_; 18866c5ee0beSSteven Rostedt 18876c5ee0beSSteven Rostedt die "PATCHCHECK_START[$i] not defined\n" 18886c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_START[$i]"})); 18896c5ee0beSSteven Rostedt die "PATCHCHECK_TYPE[$i] not defined\n" 18906c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 18916c5ee0beSSteven Rostedt 18926c5ee0beSSteven Rostedt my $start = $opt{"PATCHCHECK_START[$i]"}; 18936c5ee0beSSteven Rostedt 18946c5ee0beSSteven Rostedt my $end = "HEAD"; 18956c5ee0beSSteven Rostedt if (defined($opt{"PATCHCHECK_END[$i]"})) { 18966c5ee0beSSteven Rostedt $end = $opt{"PATCHCHECK_END[$i]"}; 18976c5ee0beSSteven Rostedt } 18986c5ee0beSSteven Rostedt 1899a57419b3SSteven Rostedt # Get the true sha1's since we can use things like HEAD~3 1900a57419b3SSteven Rostedt $start = get_sha1($start); 1901a57419b3SSteven Rostedt $end = get_sha1($end); 1902a57419b3SSteven Rostedt 19036c5ee0beSSteven Rostedt my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 19046c5ee0beSSteven Rostedt 19056c5ee0beSSteven Rostedt # Can't have a test without having a test to run 19066c5ee0beSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 19076c5ee0beSSteven Rostedt $type = "boot"; 19086c5ee0beSSteven Rostedt } 19096c5ee0beSSteven Rostedt 19106c5ee0beSSteven Rostedt open (IN, "git log --pretty=oneline $end|") or 19116c5ee0beSSteven Rostedt dodie "could not get git list"; 19126c5ee0beSSteven Rostedt 19136c5ee0beSSteven Rostedt my @list; 19146c5ee0beSSteven Rostedt 19156c5ee0beSSteven Rostedt while (<IN>) { 19166c5ee0beSSteven Rostedt chomp; 19176c5ee0beSSteven Rostedt $list[$#list+1] = $_; 19186c5ee0beSSteven Rostedt last if (/^$start/); 19196c5ee0beSSteven Rostedt } 19206c5ee0beSSteven Rostedt close(IN); 19216c5ee0beSSteven Rostedt 19226c5ee0beSSteven Rostedt if ($list[$#list] !~ /^$start/) { 19232b7d9b21SSteven Rostedt fail "SHA1 $start not found"; 19246c5ee0beSSteven Rostedt } 19256c5ee0beSSteven Rostedt 19266c5ee0beSSteven Rostedt # go backwards in the list 19276c5ee0beSSteven Rostedt @list = reverse @list; 19286c5ee0beSSteven Rostedt 19296c5ee0beSSteven Rostedt my $save_clean = $noclean; 19306c5ee0beSSteven Rostedt 19316c5ee0beSSteven Rostedt $in_patchcheck = 1; 19326c5ee0beSSteven Rostedt foreach my $item (@list) { 19336c5ee0beSSteven Rostedt my $sha1 = $item; 19346c5ee0beSSteven Rostedt $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 19356c5ee0beSSteven Rostedt 19366c5ee0beSSteven Rostedt doprint "\nProcessing commit $item\n\n"; 19376c5ee0beSSteven Rostedt 19386c5ee0beSSteven Rostedt run_command "git checkout $sha1" or 19396c5ee0beSSteven Rostedt die "Failed to checkout $sha1"; 19406c5ee0beSSteven Rostedt 19416c5ee0beSSteven Rostedt # only clean on the first and last patch 19426c5ee0beSSteven Rostedt if ($item eq $list[0] || 19436c5ee0beSSteven Rostedt $item eq $list[$#list]) { 19446c5ee0beSSteven Rostedt $noclean = $save_clean; 19456c5ee0beSSteven Rostedt } else { 19466c5ee0beSSteven Rostedt $noclean = 1; 19476c5ee0beSSteven Rostedt } 19486c5ee0beSSteven Rostedt 19496c5ee0beSSteven Rostedt if (defined($minconfig)) { 19502b7d9b21SSteven Rostedt build "useconfig:$minconfig" or return 0; 19516c5ee0beSSteven Rostedt } else { 19526c5ee0beSSteven Rostedt # ?? no config to use? 19532b7d9b21SSteven Rostedt build "oldconfig" or return 0; 19546c5ee0beSSteven Rostedt } 19556c5ee0beSSteven Rostedt 19562b7d9b21SSteven Rostedt check_buildlog $sha1 or return 0; 19576c5ee0beSSteven Rostedt 19586c5ee0beSSteven Rostedt next if ($type eq "build"); 19596c5ee0beSSteven Rostedt 19606c5ee0beSSteven Rostedt get_grub_index; 19616c5ee0beSSteven Rostedt get_version; 19626c5ee0beSSteven Rostedt install; 19636c5ee0beSSteven Rostedt 19647faafbd6SSteven Rostedt my $failed = 0; 19657faafbd6SSteven Rostedt 19667faafbd6SSteven Rostedt start_monitor; 19677faafbd6SSteven Rostedt monitor or $failed = 1; 19687faafbd6SSteven Rostedt 19697faafbd6SSteven Rostedt if (!$failed && $type ne "boot"){ 19707faafbd6SSteven Rostedt do_run_test or $failed = 1; 19717faafbd6SSteven Rostedt } 19727faafbd6SSteven Rostedt end_monitor; 19737faafbd6SSteven Rostedt return 0 if ($failed); 19747faafbd6SSteven Rostedt 197527d934b2SSteven Rostedt patchcheck_reboot; 197627d934b2SSteven Rostedt 19776c5ee0beSSteven Rostedt } 19786c5ee0beSSteven Rostedt $in_patchcheck = 0; 19796c5ee0beSSteven Rostedt success $i; 19802b7d9b21SSteven Rostedt 19812b7d9b21SSteven Rostedt return 1; 19826c5ee0beSSteven Rostedt} 19836c5ee0beSSteven Rostedt 19848d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 19852545eb61SSteven Rostedt 19868d1491baSSteven Rostedtif ($#ARGV == 0) { 19878d1491baSSteven Rostedt $ktest_config = $ARGV[0]; 19888d1491baSSteven Rostedt if (! -f $ktest_config) { 19898d1491baSSteven Rostedt print "$ktest_config does not exist.\n"; 19908d1491baSSteven Rostedt my $ans; 19918d1491baSSteven Rostedt for (;;) { 19928d1491baSSteven Rostedt print "Create it? [Y/n] "; 19938d1491baSSteven Rostedt $ans = <STDIN>; 19948d1491baSSteven Rostedt chomp $ans; 19958d1491baSSteven Rostedt if ($ans =~ /^\s*$/) { 19968d1491baSSteven Rostedt $ans = "y"; 19978d1491baSSteven Rostedt } 19988d1491baSSteven Rostedt last if ($ans =~ /^y$/i || $ans =~ /^n$/i); 19998d1491baSSteven Rostedt print "Please answer either 'y' or 'n'.\n"; 20008d1491baSSteven Rostedt } 20018d1491baSSteven Rostedt if ($ans !~ /^y$/i) { 20028d1491baSSteven Rostedt exit 0; 20038d1491baSSteven Rostedt } 20048d1491baSSteven Rostedt } 20058d1491baSSteven Rostedt} else { 20068d1491baSSteven Rostedt $ktest_config = "ktest.conf"; 20078d1491baSSteven Rostedt} 20088d1491baSSteven Rostedt 20098d1491baSSteven Rostedtif (! -f $ktest_config) { 20108d1491baSSteven Rostedt open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 20118d1491baSSteven Rostedt print OUT << "EOF" 20128d1491baSSteven Rostedt# Generated by ktest.pl 20138d1491baSSteven Rostedt# 20148d1491baSSteven Rostedt# Define each test with TEST_START 20158d1491baSSteven Rostedt# The config options below it will override the defaults 20168d1491baSSteven RostedtTEST_START 20178d1491baSSteven Rostedt 20188d1491baSSteven RostedtDEFAULTS 20198d1491baSSteven RostedtEOF 20208d1491baSSteven Rostedt; 20218d1491baSSteven Rostedt close(OUT); 20228d1491baSSteven Rostedt} 20238d1491baSSteven Rostedtread_config $ktest_config; 20248d1491baSSteven Rostedt 20258d1491baSSteven Rostedt# Append any configs entered in manually to the config file. 20268d1491baSSteven Rostedtmy @new_configs = keys %entered_configs; 20278d1491baSSteven Rostedtif ($#new_configs >= 0) { 20288d1491baSSteven Rostedt print "\nAppending entered in configs to $ktest_config\n"; 20298d1491baSSteven Rostedt open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 20308d1491baSSteven Rostedt foreach my $config (@new_configs) { 20318d1491baSSteven Rostedt print OUT "$config = $entered_configs{$config}\n"; 20328d1491baSSteven Rostedt $opt{$config} = $entered_configs{$config}; 20338d1491baSSteven Rostedt } 20348d1491baSSteven Rostedt} 20352545eb61SSteven Rostedt 20362b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 20372b7d9b21SSteven Rostedt unlink $opt{"LOG_FILE"}; 20382b7d9b21SSteven Rostedt} 20392545eb61SSteven Rostedt 20402b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 20412b7d9b21SSteven Rostedt 2042a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 2043a57419b3SSteven Rostedt 2044a57419b3SSteven Rostedt if (!$i) { 2045a57419b3SSteven Rostedt doprint "DEFAULT OPTIONS:\n"; 2046a57419b3SSteven Rostedt } else { 2047a57419b3SSteven Rostedt doprint "\nTEST $i OPTIONS"; 2048a57419b3SSteven Rostedt if (defined($repeat_tests{$i})) { 2049a57419b3SSteven Rostedt $repeat = $repeat_tests{$i}; 2050a57419b3SSteven Rostedt doprint " ITERATE $repeat"; 2051a57419b3SSteven Rostedt } 2052a57419b3SSteven Rostedt doprint "\n"; 2053a57419b3SSteven Rostedt } 2054a57419b3SSteven Rostedt 20552b7d9b21SSteven Rostedt foreach my $option (sort keys %opt) { 2056a57419b3SSteven Rostedt 2057a57419b3SSteven Rostedt if ($option =~ /\[(\d+)\]$/) { 2058a57419b3SSteven Rostedt next if ($i != $1); 2059a57419b3SSteven Rostedt } else { 2060a57419b3SSteven Rostedt next if ($i); 2061a57419b3SSteven Rostedt } 2062a57419b3SSteven Rostedt 20632b7d9b21SSteven Rostedt doprint "$option = $opt{$option}\n"; 20642b7d9b21SSteven Rostedt } 2065a57419b3SSteven Rostedt} 20662545eb61SSteven Rostedt 20672a62512bSSteven Rostedtsub __set_test_option { 20685a391fbfSSteven Rostedt my ($name, $i) = @_; 20695a391fbfSSteven Rostedt 20705a391fbfSSteven Rostedt my $option = "$name\[$i\]"; 20715a391fbfSSteven Rostedt 20725a391fbfSSteven Rostedt if (defined($opt{$option})) { 20735a391fbfSSteven Rostedt return $opt{$option}; 20745a391fbfSSteven Rostedt } 20755a391fbfSSteven Rostedt 2076a57419b3SSteven Rostedt foreach my $test (keys %repeat_tests) { 2077a57419b3SSteven Rostedt if ($i >= $test && 2078a57419b3SSteven Rostedt $i < $test + $repeat_tests{$test}) { 2079a57419b3SSteven Rostedt $option = "$name\[$test\]"; 2080a57419b3SSteven Rostedt if (defined($opt{$option})) { 2081a57419b3SSteven Rostedt return $opt{$option}; 2082a57419b3SSteven Rostedt } 2083a57419b3SSteven Rostedt } 2084a57419b3SSteven Rostedt } 2085a57419b3SSteven Rostedt 20865a391fbfSSteven Rostedt if (defined($opt{$name})) { 20875a391fbfSSteven Rostedt return $opt{$name}; 20885a391fbfSSteven Rostedt } 20895a391fbfSSteven Rostedt 20905a391fbfSSteven Rostedt return undef; 20915a391fbfSSteven Rostedt} 20925a391fbfSSteven Rostedt 20932a62512bSSteven Rostedtsub eval_option { 20942a62512bSSteven Rostedt my ($option, $i) = @_; 20952a62512bSSteven Rostedt 20962a62512bSSteven Rostedt # Add space to evaluate the character before $ 20972a62512bSSteven Rostedt $option = " $option"; 20982a62512bSSteven Rostedt my $retval = ""; 20992a62512bSSteven Rostedt 21002a62512bSSteven Rostedt while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 21012a62512bSSteven Rostedt my $start = $1; 21022a62512bSSteven Rostedt my $var = $2; 21032a62512bSSteven Rostedt my $end = $3; 21042a62512bSSteven Rostedt 21052a62512bSSteven Rostedt # Append beginning of line 21062a62512bSSteven Rostedt $retval = "$retval$start"; 21072a62512bSSteven Rostedt 21082a62512bSSteven Rostedt # If the iteration option OPT[$i] exists, then use that. 21092a62512bSSteven Rostedt # otherwise see if the default OPT (without [$i]) exists. 21102a62512bSSteven Rostedt 21112a62512bSSteven Rostedt my $o = "$var\[$i\]"; 21122a62512bSSteven Rostedt 21132a62512bSSteven Rostedt if (defined($opt{$o})) { 21142a62512bSSteven Rostedt $o = $opt{$o}; 21152a62512bSSteven Rostedt $retval = "$retval$o"; 21162a62512bSSteven Rostedt } elsif (defined($opt{$var})) { 21172a62512bSSteven Rostedt $o = $opt{$var}; 21182a62512bSSteven Rostedt $retval = "$retval$o"; 21192a62512bSSteven Rostedt } else { 21202a62512bSSteven Rostedt $retval = "$retval\$\{$var\}"; 21212a62512bSSteven Rostedt } 21222a62512bSSteven Rostedt 21232a62512bSSteven Rostedt $option = $end; 21242a62512bSSteven Rostedt } 21252a62512bSSteven Rostedt 21262a62512bSSteven Rostedt $retval = "$retval$option"; 21272a62512bSSteven Rostedt 21282a62512bSSteven Rostedt $retval =~ s/^ //; 21292a62512bSSteven Rostedt 21302a62512bSSteven Rostedt return $retval; 21312a62512bSSteven Rostedt} 21322a62512bSSteven Rostedt 21332a62512bSSteven Rostedtsub set_test_option { 21342a62512bSSteven Rostedt my ($name, $i) = @_; 21352a62512bSSteven Rostedt 21362a62512bSSteven Rostedt my $option = __set_test_option($name, $i); 21372a62512bSSteven Rostedt return $option if (!defined($option)); 21382a62512bSSteven Rostedt 21392a62512bSSteven Rostedt my $prev = ""; 21402a62512bSSteven Rostedt 21412a62512bSSteven Rostedt # Since an option can evaluate to another option, 21422a62512bSSteven Rostedt # keep iterating until we do not evaluate any more 21432a62512bSSteven Rostedt # options. 21442a62512bSSteven Rostedt my $r = 0; 21452a62512bSSteven Rostedt while ($prev ne $option) { 21462a62512bSSteven Rostedt # Check for recursive evaluations. 21472a62512bSSteven Rostedt # 100 deep should be more than enough. 21482a62512bSSteven Rostedt if ($r++ > 100) { 21492a62512bSSteven Rostedt die "Over 100 evaluations accurred with $name\n" . 21502a62512bSSteven Rostedt "Check for recursive variables\n"; 21512a62512bSSteven Rostedt } 21522a62512bSSteven Rostedt $prev = $option; 21532a62512bSSteven Rostedt $option = eval_option($option, $i); 21542a62512bSSteven Rostedt } 21552a62512bSSteven Rostedt 21562a62512bSSteven Rostedt return $option; 21572a62512bSSteven Rostedt} 21582a62512bSSteven Rostedt 21592545eb61SSteven Rostedt# First we need to do is the builds 2160a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 21612545eb61SSteven Rostedt 2162576f627cSSteven Rostedt $iteration = $i; 2163576f627cSSteven Rostedt 2164a75fececSSteven Rostedt my $makecmd = set_test_option("MAKE_CMD", $i); 2165a75fececSSteven Rostedt 2166a75fececSSteven Rostedt $machine = set_test_option("MACHINE", $i); 2167e48c5293SSteven Rostedt $ssh_user = set_test_option("SSH_USER", $i); 2168a75fececSSteven Rostedt $tmpdir = set_test_option("TMP_DIR", $i); 2169a75fececSSteven Rostedt $outputdir = set_test_option("OUTPUT_DIR", $i); 2170a75fececSSteven Rostedt $builddir = set_test_option("BUILD_DIR", $i); 2171a75fececSSteven Rostedt $test_type = set_test_option("TEST_TYPE", $i); 2172a75fececSSteven Rostedt $build_type = set_test_option("BUILD_TYPE", $i); 2173a75fececSSteven Rostedt $build_options = set_test_option("BUILD_OPTIONS", $i); 2174a75fececSSteven Rostedt $power_cycle = set_test_option("POWER_CYCLE", $i); 2175e48c5293SSteven Rostedt $reboot = set_test_option("REBOOT", $i); 2176a75fececSSteven Rostedt $noclean = set_test_option("BUILD_NOCLEAN", $i); 2177a75fececSSteven Rostedt $minconfig = set_test_option("MIN_CONFIG", $i); 2178a75fececSSteven Rostedt $run_test = set_test_option("TEST", $i); 2179a75fececSSteven Rostedt $addconfig = set_test_option("ADD_CONFIG", $i); 2180a75fececSSteven Rostedt $reboot_type = set_test_option("REBOOT_TYPE", $i); 2181a75fececSSteven Rostedt $grub_menu = set_test_option("GRUB_MENU", $i); 21828b37ca8cSSteven Rostedt $post_install = set_test_option("POST_INSTALL", $i); 2183a75fececSSteven Rostedt $reboot_script = set_test_option("REBOOT_SCRIPT", $i); 2184a75fececSSteven Rostedt $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); 2185a75fececSSteven Rostedt $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); 2186a75fececSSteven Rostedt $die_on_failure = set_test_option("DIE_ON_FAILURE", $i); 2187a75fececSSteven Rostedt $power_off = set_test_option("POWER_OFF", $i); 2188576f627cSSteven Rostedt $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i); 2189576f627cSSteven Rostedt $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i); 2190a75fececSSteven Rostedt $sleep_time = set_test_option("SLEEP_TIME", $i); 2191a75fececSSteven Rostedt $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 219227d934b2SSteven Rostedt $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i); 2193c960bb9fSSteven Rostedt $bisect_manual = set_test_option("BISECT_MANUAL", $i); 2194c23dca7cSSteven Rostedt $bisect_skip = set_test_option("BISECT_SKIP", $i); 219530f75da5SSteven Rostedt $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i); 2196a75fececSSteven Rostedt $store_failures = set_test_option("STORE_FAILURES", $i); 2197*9064af52SSteven Rostedt $test_name = set_test_option("TEST_NAME", $i); 2198a75fececSSteven Rostedt $timeout = set_test_option("TIMEOUT", $i); 2199a75fececSSteven Rostedt $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 2200a75fececSSteven Rostedt $console = set_test_option("CONSOLE", $i); 2201f1a5b962SSteven Rostedt $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i); 2202a75fececSSteven Rostedt $success_line = set_test_option("SUCCESS_LINE", $i); 22031c8a617aSSteven Rostedt $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); 22041c8a617aSSteven Rostedt $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); 22052d01b26aSSteven Rostedt $stop_test_after = set_test_option("STOP_TEST_AFTER", $i); 2206a75fececSSteven Rostedt $build_target = set_test_option("BUILD_TARGET", $i); 2207e48c5293SSteven Rostedt $ssh_exec = set_test_option("SSH_EXEC", $i); 2208e48c5293SSteven Rostedt $scp_to_target = set_test_option("SCP_TO_TARGET", $i); 2209a75fececSSteven Rostedt $target_image = set_test_option("TARGET_IMAGE", $i); 2210a75fececSSteven Rostedt $localversion = set_test_option("LOCALVERSION", $i); 2211a75fececSSteven Rostedt 2212a75fececSSteven Rostedt chdir $builddir || die "can't change directory to $builddir"; 2213a75fececSSteven Rostedt 2214a75fececSSteven Rostedt if (!-d $tmpdir) { 2215a75fececSSteven Rostedt mkpath($tmpdir) or 2216a75fececSSteven Rostedt die "can't create $tmpdir"; 2217a75fececSSteven Rostedt } 2218a75fececSSteven Rostedt 2219e48c5293SSteven Rostedt $ENV{"SSH_USER"} = $ssh_user; 2220e48c5293SSteven Rostedt $ENV{"MACHINE"} = $machine; 2221e48c5293SSteven Rostedt 2222a75fececSSteven Rostedt $target = "$ssh_user\@$machine"; 2223a75fececSSteven Rostedt 2224a75fececSSteven Rostedt $buildlog = "$tmpdir/buildlog-$machine"; 2225a75fececSSteven Rostedt $dmesg = "$tmpdir/dmesg-$machine"; 2226a75fececSSteven Rostedt $make = "$makecmd O=$outputdir"; 222751ad1dd1SSteven Rostedt $output_config = "$outputdir/.config"; 2228a75fececSSteven Rostedt 2229a75fececSSteven Rostedt if ($reboot_type eq "grub") { 2230576f627cSSteven Rostedt dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 2231a75fececSSteven Rostedt } elsif (!defined($reboot_script)) { 2232576f627cSSteven Rostedt dodie "REBOOT_SCRIPT not defined" 2233a75fececSSteven Rostedt } 2234a75fececSSteven Rostedt 2235a75fececSSteven Rostedt my $run_type = $build_type; 2236a75fececSSteven Rostedt if ($test_type eq "patchcheck") { 2237a75fececSSteven Rostedt $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 2238a75fececSSteven Rostedt } elsif ($test_type eq "bisect") { 2239a75fececSSteven Rostedt $run_type = $opt{"BISECT_TYPE[$i]"}; 22400a05c769SSteven Rostedt } elsif ($test_type eq "config_bisect") { 22410a05c769SSteven Rostedt $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; 2242a75fececSSteven Rostedt } 2243a75fececSSteven Rostedt 2244a75fececSSteven Rostedt # mistake in config file? 2245a75fececSSteven Rostedt if (!defined($run_type)) { 2246a75fececSSteven Rostedt $run_type = "ERROR"; 2247a75fececSSteven Rostedt } 22482545eb61SSteven Rostedt 22492545eb61SSteven Rostedt doprint "\n\n"; 2250a75fececSSteven Rostedt doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n"; 22517faafbd6SSteven Rostedt 22527faafbd6SSteven Rostedt unlink $dmesg; 22537faafbd6SSteven Rostedt unlink $buildlog; 22542545eb61SSteven Rostedt 22552b7d9b21SSteven Rostedt if (!defined($minconfig)) { 22562b7d9b21SSteven Rostedt $minconfig = $addconfig; 22572b7d9b21SSteven Rostedt 22582b7d9b21SSteven Rostedt } elsif (defined($addconfig)) { 22599be2e6b5SSteven Rostedt run_command "cat $addconfig $minconfig > $tmpdir/add_config" or 22602b7d9b21SSteven Rostedt dodie "Failed to create temp config"; 22619be2e6b5SSteven Rostedt $minconfig = "$tmpdir/add_config"; 22622b7d9b21SSteven Rostedt } 22632b7d9b21SSteven Rostedt 22646c5ee0beSSteven Rostedt my $checkout = $opt{"CHECKOUT[$i]"}; 22656c5ee0beSSteven Rostedt if (defined($checkout)) { 22666c5ee0beSSteven Rostedt run_command "git checkout $checkout" or 22676c5ee0beSSteven Rostedt die "failed to checkout $checkout"; 22686c5ee0beSSteven Rostedt } 22696c5ee0beSSteven Rostedt 2270a75fececSSteven Rostedt if ($test_type eq "bisect") { 22715f9b6cedSSteven Rostedt bisect $i; 22725f9b6cedSSteven Rostedt next; 22730a05c769SSteven Rostedt } elsif ($test_type eq "config_bisect") { 22740a05c769SSteven Rostedt config_bisect $i; 22750a05c769SSteven Rostedt next; 2276a75fececSSteven Rostedt } elsif ($test_type eq "patchcheck") { 22776c5ee0beSSteven Rostedt patchcheck $i; 22786c5ee0beSSteven Rostedt next; 22795f9b6cedSSteven Rostedt } 22805f9b6cedSSteven Rostedt 22817faafbd6SSteven Rostedt if ($build_type ne "nobuild") { 22827faafbd6SSteven Rostedt build $build_type or next; 22832545eb61SSteven Rostedt } 22842545eb61SSteven Rostedt 2285a75fececSSteven Rostedt if ($test_type ne "build") { 22865f9b6cedSSteven Rostedt get_grub_index; 22875f9b6cedSSteven Rostedt get_version; 22882545eb61SSteven Rostedt install; 22895a391fbfSSteven Rostedt 22907faafbd6SSteven Rostedt my $failed = 0; 22917faafbd6SSteven Rostedt start_monitor; 22927faafbd6SSteven Rostedt monitor or $failed = 1;; 2293a75fececSSteven Rostedt 2294a75fececSSteven Rostedt if (!$failed && $test_type ne "boot" && defined($run_test)) { 22957faafbd6SSteven Rostedt do_run_test or $failed = 1; 22965a391fbfSSteven Rostedt } 22977faafbd6SSteven Rostedt end_monitor; 22987faafbd6SSteven Rostedt next if ($failed); 2299a75fececSSteven Rostedt } 23005a391fbfSSteven Rostedt 23015f9b6cedSSteven Rostedt success $i; 230275c3fda7SSteven Rostedt} 23032545eb61SSteven Rostedt 23045c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) { 230575c3fda7SSteven Rostedt halt; 2306576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { 230775c3fda7SSteven Rostedt reboot; 23085c42fc5bSSteven Rostedt} 230975c3fda7SSteven Rostedt 2310e48c5293SSteven Rostedtdoprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 2311e48c5293SSteven Rostedt 23122545eb61SSteven Rostedtexit 0; 2313