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