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; 3048920630SSteven Rostedt$default{"TMP_DIR"} = "/tmp/ktest/\${MACHINE}"; 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; 45e0a8742eSSteven Rostedt$default{"NO_INSTALL"} = 0; 46a75fececSSteven Rostedt$default{"BOOTED_TIMEOUT"} = 1; 47a75fececSSteven Rostedt$default{"DIE_ON_FAILURE"} = 1; 48e48c5293SSteven Rostedt$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND"; 49e48c5293SSteven Rostedt$default{"SCP_TO_TARGET"} = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE"; 50e48c5293SSteven Rostedt$default{"REBOOT"} = "ssh \$SSH_USER\@\$MACHINE reboot"; 511c8a617aSSteven Rostedt$default{"STOP_AFTER_SUCCESS"} = 10; 521c8a617aSSteven Rostedt$default{"STOP_AFTER_FAILURE"} = 60; 532d01b26aSSteven Rostedt$default{"STOP_TEST_AFTER"} = 600; 548d1491baSSteven Rostedt$default{"LOCALVERSION"} = "-test"; 552545eb61SSteven Rostedt 568d1491baSSteven Rostedtmy $ktest_config; 572545eb61SSteven Rostedtmy $version; 58a75fececSSteven Rostedtmy $machine; 59e48c5293SSteven Rostedtmy $ssh_user; 60a75fececSSteven Rostedtmy $tmpdir; 61a75fececSSteven Rostedtmy $builddir; 62a75fececSSteven Rostedtmy $outputdir; 6351ad1dd1SSteven Rostedtmy $output_config; 64a75fececSSteven Rostedtmy $test_type; 657faafbd6SSteven Rostedtmy $build_type; 66a75fececSSteven Rostedtmy $build_options; 670bd6c1a3SSteven Rostedtmy $pre_build; 680bd6c1a3SSteven Rostedtmy $post_build; 690bd6c1a3SSteven Rostedtmy $pre_build_die; 700bd6c1a3SSteven Rostedtmy $post_build_die; 71a75fececSSteven Rostedtmy $reboot_type; 72a75fececSSteven Rostedtmy $reboot_script; 73a75fececSSteven Rostedtmy $power_cycle; 74e48c5293SSteven Rostedtmy $reboot; 75a75fececSSteven Rostedtmy $reboot_on_error; 76a75fececSSteven Rostedtmy $poweroff_on_error; 77a75fececSSteven Rostedtmy $die_on_failure; 78576f627cSSteven Rostedtmy $powercycle_after_reboot; 79576f627cSSteven Rostedtmy $poweroff_after_halt; 80e48c5293SSteven Rostedtmy $ssh_exec; 81e48c5293SSteven Rostedtmy $scp_to_target; 82a75fececSSteven Rostedtmy $power_off; 83a75fececSSteven Rostedtmy $grub_menu; 842545eb61SSteven Rostedtmy $grub_number; 852545eb61SSteven Rostedtmy $target; 862545eb61SSteven Rostedtmy $make; 878b37ca8cSSteven Rostedtmy $post_install; 88e0a8742eSSteven Rostedtmy $no_install; 895c42fc5bSSteven Rostedtmy $noclean; 905f9b6cedSSteven Rostedtmy $minconfig; 914c4ab120SSteven Rostedtmy $start_minconfig; 9235ce5952SSteven Rostedtmy $start_minconfig_defined; 934c4ab120SSteven Rostedtmy $output_minconfig; 944c4ab120SSteven Rostedtmy $ignore_config; 952b7d9b21SSteven Rostedtmy $addconfig; 965f9b6cedSSteven Rostedtmy $in_bisect = 0; 975f9b6cedSSteven Rostedtmy $bisect_bad = ""; 98d6ce2a0bSSteven Rostedtmy $reverse_bisect; 99c960bb9fSSteven Rostedtmy $bisect_manual; 100c23dca7cSSteven Rostedtmy $bisect_skip; 10130f75da5SSteven Rostedtmy $config_bisect_good; 1026c5ee0beSSteven Rostedtmy $in_patchcheck = 0; 1035a391fbfSSteven Rostedtmy $run_test; 1046c5ee0beSSteven Rostedtmy $redirect; 1057faafbd6SSteven Rostedtmy $buildlog; 1067faafbd6SSteven Rostedtmy $dmesg; 1077faafbd6SSteven Rostedtmy $monitor_fp; 1087faafbd6SSteven Rostedtmy $monitor_pid; 1097faafbd6SSteven Rostedtmy $monitor_cnt = 0; 110a75fececSSteven Rostedtmy $sleep_time; 111a75fececSSteven Rostedtmy $bisect_sleep_time; 11227d934b2SSteven Rostedtmy $patchcheck_sleep_time; 1131990207dSSteven Rostedtmy $ignore_warnings; 114a75fececSSteven Rostedtmy $store_failures; 1159064af52SSteven Rostedtmy $test_name; 116a75fececSSteven Rostedtmy $timeout; 117a75fececSSteven Rostedtmy $booted_timeout; 118f1a5b962SSteven Rostedtmy $detect_triplefault; 119a75fececSSteven Rostedtmy $console; 1202b803365SSteven Rostedtmy $reboot_success_line; 121a75fececSSteven Rostedtmy $success_line; 1221c8a617aSSteven Rostedtmy $stop_after_success; 1231c8a617aSSteven Rostedtmy $stop_after_failure; 1242d01b26aSSteven Rostedtmy $stop_test_after; 125a75fececSSteven Rostedtmy $build_target; 126a75fececSSteven Rostedtmy $target_image; 127a75fececSSteven Rostedtmy $localversion; 128576f627cSSteven Rostedtmy $iteration = 0; 129e48c5293SSteven Rostedtmy $successes = 0; 1302545eb61SSteven Rostedt 1318d1491baSSteven Rostedtmy %entered_configs; 1328d1491baSSteven Rostedtmy %config_help; 13377d942ceSSteven Rostedtmy %variable; 134fcb3f16aSSteven Rostedtmy %force_config; 1358d1491baSSteven Rostedt 136*4ab1cce5SSteven Rostedt# do not force reboots on config problems 137*4ab1cce5SSteven Rostedtmy $no_reboot = 1; 138*4ab1cce5SSteven Rostedt 1398d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF" 1408d1491baSSteven Rostedt The machine hostname that you will test. 1418d1491baSSteven RostedtEOF 1428d1491baSSteven Rostedt ; 1438d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF" 1448d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user 1458d1491baSSteven Rostedt (most likely root, since you need privileged operations) 1468d1491baSSteven RostedtEOF 1478d1491baSSteven Rostedt ; 1488d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF" 1498d1491baSSteven Rostedt The directory that contains the Linux source code (full path). 1508d1491baSSteven RostedtEOF 1518d1491baSSteven Rostedt ; 1528d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF" 1538d1491baSSteven Rostedt The directory that the objects will be built (full path). 1548d1491baSSteven Rostedt (can not be same as BUILD_DIR) 1558d1491baSSteven RostedtEOF 1568d1491baSSteven Rostedt ; 1578d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF" 1588d1491baSSteven Rostedt The location of the compiled file to copy to the target. 1598d1491baSSteven Rostedt (relative to OUTPUT_DIR) 1608d1491baSSteven RostedtEOF 1618d1491baSSteven Rostedt ; 1628d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF" 1638d1491baSSteven Rostedt The place to put your image on the test machine. 1648d1491baSSteven RostedtEOF 1658d1491baSSteven Rostedt ; 1668d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF" 1678d1491baSSteven Rostedt A script or command to reboot the box. 1688d1491baSSteven Rostedt 1698d1491baSSteven Rostedt Here is a digital loggers power switch example 1708d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL' 1718d1491baSSteven Rostedt 1728d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host 1738d1491baSSteven Rostedt with the name "Guest". 1748d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest 1758d1491baSSteven RostedtEOF 1768d1491baSSteven Rostedt ; 1778d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF" 1788d1491baSSteven Rostedt The script or command that reads the console 1798d1491baSSteven Rostedt 1808d1491baSSteven Rostedt If you use ttywatch server, something like the following would work. 1818d1491baSSteven RostedtCONSOLE = nc -d localhost 3001 1828d1491baSSteven Rostedt 1838d1491baSSteven Rostedt For a virtual machine with guest name "Guest". 1848d1491baSSteven RostedtCONSOLE = virsh console Guest 1858d1491baSSteven RostedtEOF 1868d1491baSSteven Rostedt ; 1878d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF" 1888d1491baSSteven Rostedt Required version ending to differentiate the test 1898d1491baSSteven Rostedt from other linux builds on the system. 1908d1491baSSteven RostedtEOF 1918d1491baSSteven Rostedt ; 1928d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF" 1938d1491baSSteven Rostedt Way to reboot the box to the test kernel. 1948d1491baSSteven Rostedt Only valid options so far are "grub" and "script". 1958d1491baSSteven Rostedt 1968d1491baSSteven Rostedt If you specify grub, it will assume grub version 1 1978d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU 1988d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not 1998d1491baSSteven Rostedt your setup, then specify "script" and have a command or script 2008d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target. 2018d1491baSSteven Rostedt 2028d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually. 2038d1491baSSteven Rostedt The test will not modify that file. 2048d1491baSSteven RostedtEOF 2058d1491baSSteven Rostedt ; 2068d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF" 2078d1491baSSteven Rostedt The grub title name for the test kernel to boot 2088d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = grub) 2098d1491baSSteven Rostedt 2108d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to 2118d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search 2128d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to 2138d1491baSSteven Rostedt reboot into. 2148d1491baSSteven Rostedt 2158d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has: 2168d1491baSSteven Rostedt title Test Kernel 2178d1491baSSteven Rostedt kernel vmlinuz-test 2188d1491baSSteven Rostedt GRUB_MENU = Test Kernel 2198d1491baSSteven RostedtEOF 2208d1491baSSteven Rostedt ; 2218d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF" 2228d1491baSSteven Rostedt A script to reboot the target into the test kernel 2238d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script) 2248d1491baSSteven RostedtEOF 2258d1491baSSteven Rostedt ; 2268d1491baSSteven Rostedt 22735ce5952SSteven Rostedtsub read_yn { 22835ce5952SSteven Rostedt my ($prompt) = @_; 22935ce5952SSteven Rostedt 23035ce5952SSteven Rostedt my $ans; 23135ce5952SSteven Rostedt 23235ce5952SSteven Rostedt for (;;) { 23335ce5952SSteven Rostedt print "$prompt [Y/n] "; 23435ce5952SSteven Rostedt $ans = <STDIN>; 23535ce5952SSteven Rostedt chomp $ans; 23635ce5952SSteven Rostedt if ($ans =~ /^\s*$/) { 23735ce5952SSteven Rostedt $ans = "y"; 23835ce5952SSteven Rostedt } 23935ce5952SSteven Rostedt last if ($ans =~ /^y$/i || $ans =~ /^n$/i); 24035ce5952SSteven Rostedt print "Please answer either 'y' or 'n'.\n"; 24135ce5952SSteven Rostedt } 24235ce5952SSteven Rostedt if ($ans !~ /^y$/i) { 24335ce5952SSteven Rostedt return 0; 24435ce5952SSteven Rostedt } 24535ce5952SSteven Rostedt return 1; 24635ce5952SSteven Rostedt} 2478d1491baSSteven Rostedt 2488d1491baSSteven Rostedtsub get_ktest_config { 2498d1491baSSteven Rostedt my ($config) = @_; 2508d1491baSSteven Rostedt 2518d1491baSSteven Rostedt return if (defined($opt{$config})); 2528d1491baSSteven Rostedt 2538d1491baSSteven Rostedt if (defined($config_help{$config})) { 2548d1491baSSteven Rostedt print "\n"; 2558d1491baSSteven Rostedt print $config_help{$config}; 2568d1491baSSteven Rostedt } 2578d1491baSSteven Rostedt 2588d1491baSSteven Rostedt for (;;) { 2598d1491baSSteven Rostedt print "$config = "; 2608d1491baSSteven Rostedt if (defined($default{$config})) { 2618d1491baSSteven Rostedt print "\[$default{$config}\] "; 2628d1491baSSteven Rostedt } 2638d1491baSSteven Rostedt $entered_configs{$config} = <STDIN>; 2648d1491baSSteven Rostedt $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/; 2658d1491baSSteven Rostedt if ($entered_configs{$config} =~ /^\s*$/) { 2668d1491baSSteven Rostedt if ($default{$config}) { 2678d1491baSSteven Rostedt $entered_configs{$config} = $default{$config}; 2688d1491baSSteven Rostedt } else { 2698d1491baSSteven Rostedt print "Your answer can not be blank\n"; 2708d1491baSSteven Rostedt next; 2718d1491baSSteven Rostedt } 2728d1491baSSteven Rostedt } 2738d1491baSSteven Rostedt last; 2748d1491baSSteven Rostedt } 2758d1491baSSteven Rostedt} 2768d1491baSSteven Rostedt 2778d1491baSSteven Rostedtsub get_ktest_configs { 2788d1491baSSteven Rostedt get_ktest_config("MACHINE"); 2798d1491baSSteven Rostedt get_ktest_config("SSH_USER"); 2808d1491baSSteven Rostedt get_ktest_config("BUILD_DIR"); 2818d1491baSSteven Rostedt get_ktest_config("OUTPUT_DIR"); 2828d1491baSSteven Rostedt get_ktest_config("BUILD_TARGET"); 2838d1491baSSteven Rostedt get_ktest_config("TARGET_IMAGE"); 2848d1491baSSteven Rostedt get_ktest_config("POWER_CYCLE"); 2858d1491baSSteven Rostedt get_ktest_config("CONSOLE"); 2868d1491baSSteven Rostedt get_ktest_config("LOCALVERSION"); 2878d1491baSSteven Rostedt 2888d1491baSSteven Rostedt my $rtype = $opt{"REBOOT_TYPE"}; 2898d1491baSSteven Rostedt 2908d1491baSSteven Rostedt if (!defined($rtype)) { 2918d1491baSSteven Rostedt if (!defined($opt{"GRUB_MENU"})) { 2928d1491baSSteven Rostedt get_ktest_config("REBOOT_TYPE"); 2938d1491baSSteven Rostedt $rtype = $entered_configs{"REBOOT_TYPE"}; 2948d1491baSSteven Rostedt } else { 2958d1491baSSteven Rostedt $rtype = "grub"; 2968d1491baSSteven Rostedt } 2978d1491baSSteven Rostedt } 2988d1491baSSteven Rostedt 2998d1491baSSteven Rostedt if ($rtype eq "grub") { 3008d1491baSSteven Rostedt get_ktest_config("GRUB_MENU"); 3018d1491baSSteven Rostedt } else { 3028d1491baSSteven Rostedt get_ktest_config("REBOOT_SCRIPT"); 3038d1491baSSteven Rostedt } 3048d1491baSSteven Rostedt} 3058d1491baSSteven Rostedt 30677d942ceSSteven Rostedtsub process_variables { 30777d942ceSSteven Rostedt my ($value) = @_; 30877d942ceSSteven Rostedt my $retval = ""; 30977d942ceSSteven Rostedt 31077d942ceSSteven Rostedt # We want to check for '\', and it is just easier 31177d942ceSSteven Rostedt # to check the previous characet of '$' and not need 31277d942ceSSteven Rostedt # to worry if '$' is the first character. By adding 31377d942ceSSteven Rostedt # a space to $value, we can just check [^\\]\$ and 31477d942ceSSteven Rostedt # it will still work. 31577d942ceSSteven Rostedt $value = " $value"; 31677d942ceSSteven Rostedt 31777d942ceSSteven Rostedt while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 31877d942ceSSteven Rostedt my $begin = $1; 31977d942ceSSteven Rostedt my $var = $2; 32077d942ceSSteven Rostedt my $end = $3; 32177d942ceSSteven Rostedt # append beginning of value to retval 32277d942ceSSteven Rostedt $retval = "$retval$begin"; 32377d942ceSSteven Rostedt if (defined($variable{$var})) { 32477d942ceSSteven Rostedt $retval = "$retval$variable{$var}"; 32577d942ceSSteven Rostedt } else { 32677d942ceSSteven Rostedt # put back the origin piece. 32777d942ceSSteven Rostedt $retval = "$retval\$\{$var\}"; 32877d942ceSSteven Rostedt } 32977d942ceSSteven Rostedt $value = $end; 33077d942ceSSteven Rostedt } 33177d942ceSSteven Rostedt $retval = "$retval$value"; 33277d942ceSSteven Rostedt 33377d942ceSSteven Rostedt # remove the space added in the beginning 33477d942ceSSteven Rostedt $retval =~ s/ //; 33577d942ceSSteven Rostedt 33677d942ceSSteven Rostedt return "$retval" 33777d942ceSSteven Rostedt} 33877d942ceSSteven Rostedt 339a57419b3SSteven Rostedtsub set_value { 340a57419b3SSteven Rostedt my ($lvalue, $rvalue) = @_; 3412545eb61SSteven Rostedt 342a75fececSSteven Rostedt if (defined($opt{$lvalue})) { 343a75fececSSteven Rostedt die "Error: Option $lvalue defined more than once!\n"; 344a75fececSSteven Rostedt } 34521a9679fSSteven Rostedt if ($rvalue =~ /^\s*$/) { 34621a9679fSSteven Rostedt delete $opt{$lvalue}; 34721a9679fSSteven Rostedt } else { 34877d942ceSSteven Rostedt $rvalue = process_variables($rvalue); 34921a9679fSSteven Rostedt $opt{$lvalue} = $rvalue; 35021a9679fSSteven Rostedt } 3512545eb61SSteven Rostedt} 352a57419b3SSteven Rostedt 35377d942ceSSteven Rostedtsub set_variable { 35477d942ceSSteven Rostedt my ($lvalue, $rvalue) = @_; 35577d942ceSSteven Rostedt 35677d942ceSSteven Rostedt if ($rvalue =~ /^\s*$/) { 35777d942ceSSteven Rostedt delete $variable{$lvalue}; 35877d942ceSSteven Rostedt } else { 35977d942ceSSteven Rostedt $rvalue = process_variables($rvalue); 36077d942ceSSteven Rostedt $variable{$lvalue} = $rvalue; 36177d942ceSSteven Rostedt } 36277d942ceSSteven Rostedt} 36377d942ceSSteven Rostedt 364a57419b3SSteven Rostedtsub read_config { 365a57419b3SSteven Rostedt my ($config) = @_; 366a57419b3SSteven Rostedt 367a57419b3SSteven Rostedt open(IN, $config) || die "can't read file $config"; 368a57419b3SSteven Rostedt 369a57419b3SSteven Rostedt my $name = $config; 370a57419b3SSteven Rostedt $name =~ s,.*/(.*),$1,; 371a57419b3SSteven Rostedt 372a57419b3SSteven Rostedt my $test_num = 0; 373a57419b3SSteven Rostedt my $default = 1; 374a57419b3SSteven Rostedt my $repeat = 1; 375a57419b3SSteven Rostedt my $num_tests_set = 0; 376a57419b3SSteven Rostedt my $skip = 0; 377a57419b3SSteven Rostedt my $rest; 3780df213caSSteven Rostedt my $test_case = 0; 379a57419b3SSteven Rostedt 380a57419b3SSteven Rostedt while (<IN>) { 381a57419b3SSteven Rostedt 382a57419b3SSteven Rostedt # ignore blank lines and comments 383a57419b3SSteven Rostedt next if (/^\s*$/ || /\s*\#/); 384a57419b3SSteven Rostedt 385a57419b3SSteven Rostedt if (/^\s*TEST_START(.*)/) { 386a57419b3SSteven Rostedt 387a57419b3SSteven Rostedt $rest = $1; 388a57419b3SSteven Rostedt 389a57419b3SSteven Rostedt if ($num_tests_set) { 390a57419b3SSteven Rostedt die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 391a57419b3SSteven Rostedt } 392a57419b3SSteven Rostedt 393a57419b3SSteven Rostedt my $old_test_num = $test_num; 394e48c5293SSteven Rostedt my $old_repeat = $repeat; 395a57419b3SSteven Rostedt 396a57419b3SSteven Rostedt $test_num += $repeat; 397a57419b3SSteven Rostedt $default = 0; 398a57419b3SSteven Rostedt $repeat = 1; 399a57419b3SSteven Rostedt 400a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 401a57419b3SSteven Rostedt $rest = $1; 402a57419b3SSteven Rostedt $skip = 1; 403a57419b3SSteven Rostedt } else { 4040df213caSSteven Rostedt $test_case = 1; 405a57419b3SSteven Rostedt $skip = 0; 406a57419b3SSteven Rostedt } 407a57419b3SSteven Rostedt 408a57419b3SSteven Rostedt if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) { 409a57419b3SSteven Rostedt $repeat = $1; 410a57419b3SSteven Rostedt $rest = $2; 411a57419b3SSteven Rostedt $repeat_tests{"$test_num"} = $repeat; 412a57419b3SSteven Rostedt } 413a57419b3SSteven Rostedt 414a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 415a57419b3SSteven Rostedt $rest = $1; 416a57419b3SSteven Rostedt $skip = 1; 417a57419b3SSteven Rostedt } 418a57419b3SSteven Rostedt 419a57419b3SSteven Rostedt if ($rest !~ /^\s*$/) { 420a57419b3SSteven Rostedt die "$name: $.: Gargbage found after TEST_START\n$_"; 421a57419b3SSteven Rostedt } 422a57419b3SSteven Rostedt 423a57419b3SSteven Rostedt if ($skip) { 424a57419b3SSteven Rostedt $test_num = $old_test_num; 425e48c5293SSteven Rostedt $repeat = $old_repeat; 426a57419b3SSteven Rostedt } 427a57419b3SSteven Rostedt 428a57419b3SSteven Rostedt } elsif (/^\s*DEFAULTS(.*)$/) { 429a57419b3SSteven Rostedt $default = 1; 430a57419b3SSteven Rostedt 431a57419b3SSteven Rostedt $rest = $1; 432a57419b3SSteven Rostedt 433a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 434a57419b3SSteven Rostedt $rest = $1; 435a57419b3SSteven Rostedt $skip = 1; 436a57419b3SSteven Rostedt } else { 437a57419b3SSteven Rostedt $skip = 0; 438a57419b3SSteven Rostedt } 439a57419b3SSteven Rostedt 440a57419b3SSteven Rostedt if ($rest !~ /^\s*$/) { 441a57419b3SSteven Rostedt die "$name: $.: Gargbage found after DEFAULTS\n$_"; 442a57419b3SSteven Rostedt } 443a57419b3SSteven Rostedt 444a57419b3SSteven Rostedt } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 445a57419b3SSteven Rostedt 446a57419b3SSteven Rostedt next if ($skip); 447a57419b3SSteven Rostedt 448a57419b3SSteven Rostedt my $lvalue = $1; 449a57419b3SSteven Rostedt my $rvalue = $2; 450a57419b3SSteven Rostedt 451a57419b3SSteven Rostedt if (!$default && 452a57419b3SSteven Rostedt ($lvalue eq "NUM_TESTS" || 453a57419b3SSteven Rostedt $lvalue eq "LOG_FILE" || 454a57419b3SSteven Rostedt $lvalue eq "CLEAR_LOG")) { 455a57419b3SSteven Rostedt die "$name: $.: $lvalue must be set in DEFAULTS section\n"; 456a57419b3SSteven Rostedt } 457a57419b3SSteven Rostedt 458a57419b3SSteven Rostedt if ($lvalue eq "NUM_TESTS") { 459a57419b3SSteven Rostedt if ($test_num) { 460a57419b3SSteven Rostedt die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 461a57419b3SSteven Rostedt } 462a57419b3SSteven Rostedt if (!$default) { 463a57419b3SSteven Rostedt die "$name: $.: NUM_TESTS must be set in default section\n"; 464a57419b3SSteven Rostedt } 465a57419b3SSteven Rostedt $num_tests_set = 1; 466a57419b3SSteven Rostedt } 467a57419b3SSteven Rostedt 468a57419b3SSteven Rostedt if ($default || $lvalue =~ /\[\d+\]$/) { 469a57419b3SSteven Rostedt set_value($lvalue, $rvalue); 470a57419b3SSteven Rostedt } else { 471a57419b3SSteven Rostedt my $val = "$lvalue\[$test_num\]"; 472a57419b3SSteven Rostedt set_value($val, $rvalue); 473a57419b3SSteven Rostedt 474a57419b3SSteven Rostedt if ($repeat > 1) { 475a57419b3SSteven Rostedt $repeats{$val} = $repeat; 476a57419b3SSteven Rostedt } 477a57419b3SSteven Rostedt } 47877d942ceSSteven Rostedt } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) { 47977d942ceSSteven Rostedt next if ($skip); 48077d942ceSSteven Rostedt 48177d942ceSSteven Rostedt my $lvalue = $1; 48277d942ceSSteven Rostedt my $rvalue = $2; 48377d942ceSSteven Rostedt 48477d942ceSSteven Rostedt # process config variables. 48577d942ceSSteven Rostedt # Config variables are only active while reading the 48677d942ceSSteven Rostedt # config and can be defined anywhere. They also ignore 48777d942ceSSteven Rostedt # TEST_START and DEFAULTS, but are skipped if they are in 48877d942ceSSteven Rostedt # on of these sections that have SKIP defined. 48977d942ceSSteven Rostedt # The save variable can be 49077d942ceSSteven Rostedt # defined multiple times and the new one simply overrides 49177d942ceSSteven Rostedt # the prevous one. 49277d942ceSSteven Rostedt set_variable($lvalue, $rvalue); 49377d942ceSSteven Rostedt 494a57419b3SSteven Rostedt } else { 495a57419b3SSteven Rostedt die "$name: $.: Garbage found in config\n$_"; 496a57419b3SSteven Rostedt } 4972545eb61SSteven Rostedt } 4982545eb61SSteven Rostedt 4992545eb61SSteven Rostedt close(IN); 500a75fececSSteven Rostedt 501a57419b3SSteven Rostedt if ($test_num) { 502a57419b3SSteven Rostedt $test_num += $repeat - 1; 503a57419b3SSteven Rostedt $opt{"NUM_TESTS"} = $test_num; 504a57419b3SSteven Rostedt } 505a57419b3SSteven Rostedt 5068d1491baSSteven Rostedt # make sure we have all mandatory configs 5078d1491baSSteven Rostedt get_ktest_configs; 5088d1491baSSteven Rostedt 5090df213caSSteven Rostedt # was a test specified? 5100df213caSSteven Rostedt if (!$test_case) { 5110df213caSSteven Rostedt print "No test case specified.\n"; 5120df213caSSteven Rostedt print "What test case would you like to run?\n"; 5130df213caSSteven Rostedt my $ans = <STDIN>; 5140df213caSSteven Rostedt chomp $ans; 5150df213caSSteven Rostedt $default{"TEST_TYPE"} = $ans; 5160df213caSSteven Rostedt } 5170df213caSSteven Rostedt 518a75fececSSteven Rostedt # set any defaults 519a75fececSSteven Rostedt 520a75fececSSteven Rostedt foreach my $default (keys %default) { 521a75fececSSteven Rostedt if (!defined($opt{$default})) { 522a75fececSSteven Rostedt $opt{$default} = $default{$default}; 523a75fececSSteven Rostedt } 524a75fececSSteven Rostedt } 5252545eb61SSteven Rostedt} 5262545eb61SSteven Rostedt 52723715c3cSSteven Rostedtsub __eval_option { 52823715c3cSSteven Rostedt my ($option, $i) = @_; 52923715c3cSSteven Rostedt 53023715c3cSSteven Rostedt # Add space to evaluate the character before $ 53123715c3cSSteven Rostedt $option = " $option"; 53223715c3cSSteven Rostedt my $retval = ""; 53323715c3cSSteven Rostedt 53423715c3cSSteven Rostedt while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 53523715c3cSSteven Rostedt my $start = $1; 53623715c3cSSteven Rostedt my $var = $2; 53723715c3cSSteven Rostedt my $end = $3; 53823715c3cSSteven Rostedt 53923715c3cSSteven Rostedt # Append beginning of line 54023715c3cSSteven Rostedt $retval = "$retval$start"; 54123715c3cSSteven Rostedt 54223715c3cSSteven Rostedt # If the iteration option OPT[$i] exists, then use that. 54323715c3cSSteven Rostedt # otherwise see if the default OPT (without [$i]) exists. 54423715c3cSSteven Rostedt 54523715c3cSSteven Rostedt my $o = "$var\[$i\]"; 54623715c3cSSteven Rostedt 54723715c3cSSteven Rostedt if (defined($opt{$o})) { 54823715c3cSSteven Rostedt $o = $opt{$o}; 54923715c3cSSteven Rostedt $retval = "$retval$o"; 55023715c3cSSteven Rostedt } elsif (defined($opt{$var})) { 55123715c3cSSteven Rostedt $o = $opt{$var}; 55223715c3cSSteven Rostedt $retval = "$retval$o"; 55323715c3cSSteven Rostedt } else { 55423715c3cSSteven Rostedt $retval = "$retval\$\{$var\}"; 55523715c3cSSteven Rostedt } 55623715c3cSSteven Rostedt 55723715c3cSSteven Rostedt $option = $end; 55823715c3cSSteven Rostedt } 55923715c3cSSteven Rostedt 56023715c3cSSteven Rostedt $retval = "$retval$option"; 56123715c3cSSteven Rostedt 56223715c3cSSteven Rostedt $retval =~ s/^ //; 56323715c3cSSteven Rostedt 56423715c3cSSteven Rostedt return $retval; 56523715c3cSSteven Rostedt} 56623715c3cSSteven Rostedt 56723715c3cSSteven Rostedtsub eval_option { 56823715c3cSSteven Rostedt my ($option, $i) = @_; 56923715c3cSSteven Rostedt 57023715c3cSSteven Rostedt my $prev = ""; 57123715c3cSSteven Rostedt 57223715c3cSSteven Rostedt # Since an option can evaluate to another option, 57323715c3cSSteven Rostedt # keep iterating until we do not evaluate any more 57423715c3cSSteven Rostedt # options. 57523715c3cSSteven Rostedt my $r = 0; 57623715c3cSSteven Rostedt while ($prev ne $option) { 57723715c3cSSteven Rostedt # Check for recursive evaluations. 57823715c3cSSteven Rostedt # 100 deep should be more than enough. 57923715c3cSSteven Rostedt if ($r++ > 100) { 58023715c3cSSteven Rostedt die "Over 100 evaluations accurred with $option\n" . 58123715c3cSSteven Rostedt "Check for recursive variables\n"; 58223715c3cSSteven Rostedt } 58323715c3cSSteven Rostedt $prev = $option; 58423715c3cSSteven Rostedt $option = __eval_option($option, $i); 58523715c3cSSteven Rostedt } 58623715c3cSSteven Rostedt 58723715c3cSSteven Rostedt return $option; 58823715c3cSSteven Rostedt} 58923715c3cSSteven Rostedt 590d1e2f22aSSteven Rostedtsub _logit { 5912545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 5922545eb61SSteven Rostedt open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 5932545eb61SSteven Rostedt print OUT @_; 5942545eb61SSteven Rostedt close(OUT); 5952545eb61SSteven Rostedt } 5962545eb61SSteven Rostedt} 5972545eb61SSteven Rostedt 598d1e2f22aSSteven Rostedtsub logit { 599d1e2f22aSSteven Rostedt if (defined($opt{"LOG_FILE"})) { 600d1e2f22aSSteven Rostedt _logit @_; 601d1e2f22aSSteven Rostedt } else { 602d1e2f22aSSteven Rostedt print @_; 603d1e2f22aSSteven Rostedt } 604d1e2f22aSSteven Rostedt} 605d1e2f22aSSteven Rostedt 6065f9b6cedSSteven Rostedtsub doprint { 6075f9b6cedSSteven Rostedt print @_; 608d1e2f22aSSteven Rostedt _logit @_; 6095f9b6cedSSteven Rostedt} 6105f9b6cedSSteven Rostedt 6117faafbd6SSteven Rostedtsub run_command; 6122728be41SAndrew Jonessub start_monitor; 6132728be41SAndrew Jonessub end_monitor; 6142728be41SAndrew Jonessub wait_for_monitor; 6157faafbd6SSteven Rostedt 6167faafbd6SSteven Rostedtsub reboot { 6172728be41SAndrew Jones my ($time) = @_; 6182728be41SAndrew Jones 6192b803365SSteven Rostedt if (defined($time)) { 6202b803365SSteven Rostedt start_monitor; 6212b803365SSteven Rostedt # flush out current monitor 6222b803365SSteven Rostedt # May contain the reboot success line 6232b803365SSteven Rostedt wait_for_monitor 1; 6242b803365SSteven Rostedt } 6252b803365SSteven Rostedt 6267faafbd6SSteven Rostedt # try to reboot normally 627e48c5293SSteven Rostedt if (run_command $reboot) { 628576f627cSSteven Rostedt if (defined($powercycle_after_reboot)) { 629576f627cSSteven Rostedt sleep $powercycle_after_reboot; 630576f627cSSteven Rostedt run_command "$power_cycle"; 631576f627cSSteven Rostedt } 632576f627cSSteven Rostedt } else { 6337faafbd6SSteven Rostedt # nope? power cycle it. 634a75fececSSteven Rostedt run_command "$power_cycle"; 6357faafbd6SSteven Rostedt } 6362728be41SAndrew Jones 6372728be41SAndrew Jones if (defined($time)) { 6382b803365SSteven Rostedt wait_for_monitor($time, $reboot_success_line); 6392728be41SAndrew Jones end_monitor; 6402728be41SAndrew Jones } 6417faafbd6SSteven Rostedt} 6427faafbd6SSteven Rostedt 643576f627cSSteven Rostedtsub do_not_reboot { 644576f627cSSteven Rostedt my $i = $iteration; 645576f627cSSteven Rostedt 646*4ab1cce5SSteven Rostedt return $test_type eq "build" || $no_reboot || 647576f627cSSteven Rostedt ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 648576f627cSSteven Rostedt ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 649576f627cSSteven Rostedt} 650576f627cSSteven Rostedt 6515c42fc5bSSteven Rostedtsub dodie { 6525a391fbfSSteven Rostedt doprint "CRITICAL FAILURE... ", @_, "\n"; 6535c42fc5bSSteven Rostedt 654576f627cSSteven Rostedt my $i = $iteration; 655576f627cSSteven Rostedt 656576f627cSSteven Rostedt if ($reboot_on_error && !do_not_reboot) { 657576f627cSSteven Rostedt 65875c3fda7SSteven Rostedt doprint "REBOOTING\n"; 6597faafbd6SSteven Rostedt reboot; 66075c3fda7SSteven Rostedt 661a75fececSSteven Rostedt } elsif ($poweroff_on_error && defined($power_off)) { 6625c42fc5bSSteven Rostedt doprint "POWERING OFF\n"; 663a75fececSSteven Rostedt `$power_off`; 6645c42fc5bSSteven Rostedt } 66575c3fda7SSteven Rostedt 666f80802cbSSteven Rostedt if (defined($opt{"LOG_FILE"})) { 667f80802cbSSteven Rostedt print " See $opt{LOG_FILE} for more info.\n"; 668f80802cbSSteven Rostedt } 669f80802cbSSteven Rostedt 670576f627cSSteven Rostedt die @_, "\n"; 6715c42fc5bSSteven Rostedt} 6725c42fc5bSSteven Rostedt 6737faafbd6SSteven Rostedtsub open_console { 6747faafbd6SSteven Rostedt my ($fp) = @_; 6757faafbd6SSteven Rostedt 6767faafbd6SSteven Rostedt my $flags; 6777faafbd6SSteven Rostedt 678a75fececSSteven Rostedt my $pid = open($fp, "$console|") or 679a75fececSSteven Rostedt dodie "Can't open console $console"; 6807faafbd6SSteven Rostedt 6817faafbd6SSteven Rostedt $flags = fcntl($fp, F_GETFL, 0) or 682576f627cSSteven Rostedt dodie "Can't get flags for the socket: $!"; 6837faafbd6SSteven Rostedt $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 684576f627cSSteven Rostedt dodie "Can't set flags for the socket: $!"; 6857faafbd6SSteven Rostedt 6867faafbd6SSteven Rostedt return $pid; 6877faafbd6SSteven Rostedt} 6887faafbd6SSteven Rostedt 6897faafbd6SSteven Rostedtsub close_console { 6907faafbd6SSteven Rostedt my ($fp, $pid) = @_; 6917faafbd6SSteven Rostedt 6927faafbd6SSteven Rostedt doprint "kill child process $pid\n"; 6937faafbd6SSteven Rostedt kill 2, $pid; 6947faafbd6SSteven Rostedt 6957faafbd6SSteven Rostedt print "closing!\n"; 6967faafbd6SSteven Rostedt close($fp); 6977faafbd6SSteven Rostedt} 6987faafbd6SSteven Rostedt 6997faafbd6SSteven Rostedtsub start_monitor { 7007faafbd6SSteven Rostedt if ($monitor_cnt++) { 7017faafbd6SSteven Rostedt return; 7027faafbd6SSteven Rostedt } 7037faafbd6SSteven Rostedt $monitor_fp = \*MONFD; 7047faafbd6SSteven Rostedt $monitor_pid = open_console $monitor_fp; 705a75fececSSteven Rostedt 706a75fececSSteven Rostedt return; 707a75fececSSteven Rostedt 708a75fececSSteven Rostedt open(MONFD, "Stop perl from warning about single use of MONFD"); 7097faafbd6SSteven Rostedt} 7107faafbd6SSteven Rostedt 7117faafbd6SSteven Rostedtsub end_monitor { 7127faafbd6SSteven Rostedt if (--$monitor_cnt) { 7137faafbd6SSteven Rostedt return; 7147faafbd6SSteven Rostedt } 7157faafbd6SSteven Rostedt close_console($monitor_fp, $monitor_pid); 7167faafbd6SSteven Rostedt} 7177faafbd6SSteven Rostedt 7187faafbd6SSteven Rostedtsub wait_for_monitor { 7192b803365SSteven Rostedt my ($time, $stop) = @_; 7202b803365SSteven Rostedt my $full_line = ""; 7217faafbd6SSteven Rostedt my $line; 7222b803365SSteven Rostedt my $booted = 0; 7237faafbd6SSteven Rostedt 724a75fececSSteven Rostedt doprint "** Wait for monitor to settle down **\n"; 7257faafbd6SSteven Rostedt 7267faafbd6SSteven Rostedt # read the monitor and wait for the system to calm down 7272b803365SSteven Rostedt while (!$booted) { 7287faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 7292b803365SSteven Rostedt last if (!defined($line)); 7302b803365SSteven Rostedt print "$line"; 7312b803365SSteven Rostedt $full_line .= $line; 7322b803365SSteven Rostedt 7332b803365SSteven Rostedt if (defined($stop) && $full_line =~ /$stop/) { 7342b803365SSteven Rostedt doprint "wait for monitor detected $stop\n"; 7352b803365SSteven Rostedt $booted = 1; 7362b803365SSteven Rostedt } 7372b803365SSteven Rostedt 7382b803365SSteven Rostedt if ($line =~ /\n/) { 7392b803365SSteven Rostedt $full_line = ""; 7402b803365SSteven Rostedt } 7412b803365SSteven Rostedt } 742a75fececSSteven Rostedt print "** Monitor flushed **\n"; 7437faafbd6SSteven Rostedt} 7447faafbd6SSteven Rostedt 7452b7d9b21SSteven Rostedtsub fail { 7462b7d9b21SSteven Rostedt 747a75fececSSteven Rostedt if ($die_on_failure) { 7482b7d9b21SSteven Rostedt dodie @_; 7492b7d9b21SSteven Rostedt } 7502b7d9b21SSteven Rostedt 751a75fececSSteven Rostedt doprint "FAILED\n"; 7527faafbd6SSteven Rostedt 753576f627cSSteven Rostedt my $i = $iteration; 754576f627cSSteven Rostedt 755a75fececSSteven Rostedt # no need to reboot for just building. 756576f627cSSteven Rostedt if (!do_not_reboot) { 7577faafbd6SSteven Rostedt doprint "REBOOTING\n"; 7582728be41SAndrew Jones reboot $sleep_time; 759a75fececSSteven Rostedt } 7607faafbd6SSteven Rostedt 7619064af52SSteven Rostedt my $name = ""; 7629064af52SSteven Rostedt 7639064af52SSteven Rostedt if (defined($test_name)) { 7649064af52SSteven Rostedt $name = " ($test_name)"; 7659064af52SSteven Rostedt } 7669064af52SSteven Rostedt 767576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 768576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 7699064af52SSteven Rostedt doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n"; 770576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 771576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 772a75fececSSteven Rostedt 773a75fececSSteven Rostedt return 1 if (!defined($store_failures)); 7747faafbd6SSteven Rostedt 7757faafbd6SSteven Rostedt my @t = localtime; 7767faafbd6SSteven Rostedt my $date = sprintf "%04d%02d%02d%02d%02d%02d", 7777faafbd6SSteven Rostedt 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 7787faafbd6SSteven Rostedt 779cccae1a6SSteven Rostedt my $type = $build_type; 780cccae1a6SSteven Rostedt if ($type =~ /useconfig/) { 781cccae1a6SSteven Rostedt $type = "useconfig"; 782cccae1a6SSteven Rostedt } 783cccae1a6SSteven Rostedt 784cccae1a6SSteven Rostedt my $dir = "$machine-$test_type-$type-fail-$date"; 785a75fececSSteven Rostedt my $faildir = "$store_failures/$dir"; 7867faafbd6SSteven Rostedt 7877faafbd6SSteven Rostedt if (!-d $faildir) { 7887faafbd6SSteven Rostedt mkpath($faildir) or 789a75fececSSteven Rostedt die "can't create $faildir"; 7907faafbd6SSteven Rostedt } 79151ad1dd1SSteven Rostedt if (-f "$output_config") { 79251ad1dd1SSteven Rostedt cp "$output_config", "$faildir/config" or 7937faafbd6SSteven Rostedt die "failed to copy .config"; 7947faafbd6SSteven Rostedt } 7957faafbd6SSteven Rostedt if (-f $buildlog) { 7967faafbd6SSteven Rostedt cp $buildlog, "$faildir/buildlog" or 7977faafbd6SSteven Rostedt die "failed to move $buildlog"; 7987faafbd6SSteven Rostedt } 7997faafbd6SSteven Rostedt if (-f $dmesg) { 8007faafbd6SSteven Rostedt cp $dmesg, "$faildir/dmesg" or 8017faafbd6SSteven Rostedt die "failed to move $dmesg"; 8027faafbd6SSteven Rostedt } 8037faafbd6SSteven Rostedt 8047faafbd6SSteven Rostedt doprint "*** Saved info to $faildir ***\n"; 8057faafbd6SSteven Rostedt 8062b7d9b21SSteven Rostedt return 1; 8072b7d9b21SSteven Rostedt} 8082b7d9b21SSteven Rostedt 8092545eb61SSteven Rostedtsub run_command { 8102545eb61SSteven Rostedt my ($command) = @_; 811d6ce2a0bSSteven Rostedt my $dolog = 0; 812d6ce2a0bSSteven Rostedt my $dord = 0; 813d6ce2a0bSSteven Rostedt my $pid; 814d6ce2a0bSSteven Rostedt 815e48c5293SSteven Rostedt $command =~ s/\$SSH_USER/$ssh_user/g; 816e48c5293SSteven Rostedt $command =~ s/\$MACHINE/$machine/g; 817e48c5293SSteven Rostedt 818d6ce2a0bSSteven Rostedt doprint("$command ... "); 819d6ce2a0bSSteven Rostedt 820d6ce2a0bSSteven Rostedt $pid = open(CMD, "$command 2>&1 |") or 8212b7d9b21SSteven Rostedt (fail "unable to exec $command" and return 0); 8222545eb61SSteven Rostedt 8232545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 824d6ce2a0bSSteven Rostedt open(LOG, ">>$opt{LOG_FILE}") or 825d6ce2a0bSSteven Rostedt dodie "failed to write to log"; 826d6ce2a0bSSteven Rostedt $dolog = 1; 8276c5ee0beSSteven Rostedt } 8286c5ee0beSSteven Rostedt 8296c5ee0beSSteven Rostedt if (defined($redirect)) { 830d6ce2a0bSSteven Rostedt open (RD, ">$redirect") or 831d6ce2a0bSSteven Rostedt dodie "failed to write to redirect $redirect"; 832d6ce2a0bSSteven Rostedt $dord = 1; 8332545eb61SSteven Rostedt } 8342545eb61SSteven Rostedt 835d6ce2a0bSSteven Rostedt while (<CMD>) { 836d6ce2a0bSSteven Rostedt print LOG if ($dolog); 837d6ce2a0bSSteven Rostedt print RD if ($dord); 838d6ce2a0bSSteven Rostedt } 8392545eb61SSteven Rostedt 840d6ce2a0bSSteven Rostedt waitpid($pid, 0); 8412545eb61SSteven Rostedt my $failed = $?; 8422545eb61SSteven Rostedt 843d6ce2a0bSSteven Rostedt close(CMD); 844d6ce2a0bSSteven Rostedt close(LOG) if ($dolog); 845d6ce2a0bSSteven Rostedt close(RD) if ($dord); 846d6ce2a0bSSteven Rostedt 8472545eb61SSteven Rostedt if ($failed) { 8482545eb61SSteven Rostedt doprint "FAILED!\n"; 8492545eb61SSteven Rostedt } else { 8502545eb61SSteven Rostedt doprint "SUCCESS\n"; 8512545eb61SSteven Rostedt } 8522545eb61SSteven Rostedt 8535f9b6cedSSteven Rostedt return !$failed; 8545f9b6cedSSteven Rostedt} 8555f9b6cedSSteven Rostedt 856e48c5293SSteven Rostedtsub run_ssh { 857e48c5293SSteven Rostedt my ($cmd) = @_; 858e48c5293SSteven Rostedt my $cp_exec = $ssh_exec; 859e48c5293SSteven Rostedt 860e48c5293SSteven Rostedt $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 861e48c5293SSteven Rostedt return run_command "$cp_exec"; 862e48c5293SSteven Rostedt} 863e48c5293SSteven Rostedt 864e48c5293SSteven Rostedtsub run_scp { 865e48c5293SSteven Rostedt my ($src, $dst) = @_; 866e48c5293SSteven Rostedt my $cp_scp = $scp_to_target; 867e48c5293SSteven Rostedt 868e48c5293SSteven Rostedt $cp_scp =~ s/\$SRC_FILE/$src/g; 869e48c5293SSteven Rostedt $cp_scp =~ s/\$DST_FILE/$dst/g; 870e48c5293SSteven Rostedt 871e48c5293SSteven Rostedt return run_command "$cp_scp"; 872e48c5293SSteven Rostedt} 873e48c5293SSteven Rostedt 8745f9b6cedSSteven Rostedtsub get_grub_index { 8755f9b6cedSSteven Rostedt 876a75fececSSteven Rostedt if ($reboot_type ne "grub") { 877a75fececSSteven Rostedt return; 878a75fececSSteven Rostedt } 8795a391fbfSSteven Rostedt return if (defined($grub_number)); 8805f9b6cedSSteven Rostedt 8815f9b6cedSSteven Rostedt doprint "Find grub menu ... "; 8825f9b6cedSSteven Rostedt $grub_number = -1; 883e48c5293SSteven Rostedt 884e48c5293SSteven Rostedt my $ssh_grub = $ssh_exec; 885e48c5293SSteven Rostedt $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 886e48c5293SSteven Rostedt 887e48c5293SSteven Rostedt open(IN, "$ssh_grub |") 8885f9b6cedSSteven Rostedt or die "unable to get menu.lst"; 889e48c5293SSteven Rostedt 890eaa1fe25SSteven Rostedt my $found = 0; 891eaa1fe25SSteven Rostedt 8925f9b6cedSSteven Rostedt while (<IN>) { 893a75fececSSteven Rostedt if (/^\s*title\s+$grub_menu\s*$/) { 8945f9b6cedSSteven Rostedt $grub_number++; 895eaa1fe25SSteven Rostedt $found = 1; 8965f9b6cedSSteven Rostedt last; 8975f9b6cedSSteven Rostedt } elsif (/^\s*title\s/) { 8985f9b6cedSSteven Rostedt $grub_number++; 8995f9b6cedSSteven Rostedt } 9005f9b6cedSSteven Rostedt } 9015f9b6cedSSteven Rostedt close(IN); 9025f9b6cedSSteven Rostedt 903a75fececSSteven Rostedt die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 904eaa1fe25SSteven Rostedt if (!$found); 9055f9b6cedSSteven Rostedt doprint "$grub_number\n"; 9062545eb61SSteven Rostedt} 9072545eb61SSteven Rostedt 9082545eb61SSteven Rostedtsub wait_for_input 9092545eb61SSteven Rostedt{ 9102545eb61SSteven Rostedt my ($fp, $time) = @_; 9112545eb61SSteven Rostedt my $rin; 9122545eb61SSteven Rostedt my $ready; 9132545eb61SSteven Rostedt my $line; 9142545eb61SSteven Rostedt my $ch; 9152545eb61SSteven Rostedt 9162545eb61SSteven Rostedt if (!defined($time)) { 9172545eb61SSteven Rostedt $time = $timeout; 9182545eb61SSteven Rostedt } 9192545eb61SSteven Rostedt 9202545eb61SSteven Rostedt $rin = ''; 9212545eb61SSteven Rostedt vec($rin, fileno($fp), 1) = 1; 9222545eb61SSteven Rostedt $ready = select($rin, undef, undef, $time); 9232545eb61SSteven Rostedt 9242545eb61SSteven Rostedt $line = ""; 9252545eb61SSteven Rostedt 9262545eb61SSteven Rostedt # try to read one char at a time 9272545eb61SSteven Rostedt while (sysread $fp, $ch, 1) { 9282545eb61SSteven Rostedt $line .= $ch; 9292545eb61SSteven Rostedt last if ($ch eq "\n"); 9302545eb61SSteven Rostedt } 9312545eb61SSteven Rostedt 9322545eb61SSteven Rostedt if (!length($line)) { 9332545eb61SSteven Rostedt return undef; 9342545eb61SSteven Rostedt } 9352545eb61SSteven Rostedt 9362545eb61SSteven Rostedt return $line; 9372545eb61SSteven Rostedt} 9382545eb61SSteven Rostedt 93975c3fda7SSteven Rostedtsub reboot_to { 940a75fececSSteven Rostedt if ($reboot_type eq "grub") { 9414da46da2SSteven Rostedt run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'"; 942a75fececSSteven Rostedt return; 943a75fececSSteven Rostedt } 944a75fececSSteven Rostedt 945a75fececSSteven Rostedt run_command "$reboot_script"; 9462545eb61SSteven Rostedt} 9472545eb61SSteven Rostedt 948a57419b3SSteven Rostedtsub get_sha1 { 949a57419b3SSteven Rostedt my ($commit) = @_; 950a57419b3SSteven Rostedt 951a57419b3SSteven Rostedt doprint "git rev-list --max-count=1 $commit ... "; 952a57419b3SSteven Rostedt my $sha1 = `git rev-list --max-count=1 $commit`; 953a57419b3SSteven Rostedt my $ret = $?; 954a57419b3SSteven Rostedt 955a57419b3SSteven Rostedt logit $sha1; 956a57419b3SSteven Rostedt 957a57419b3SSteven Rostedt if ($ret) { 958a57419b3SSteven Rostedt doprint "FAILED\n"; 959a57419b3SSteven Rostedt dodie "Failed to get git $commit"; 960a57419b3SSteven Rostedt } 961a57419b3SSteven Rostedt 962a57419b3SSteven Rostedt print "SUCCESS\n"; 963a57419b3SSteven Rostedt 964a57419b3SSteven Rostedt chomp $sha1; 965a57419b3SSteven Rostedt 966a57419b3SSteven Rostedt return $sha1; 967a57419b3SSteven Rostedt} 968a57419b3SSteven Rostedt 9695a391fbfSSteven Rostedtsub monitor { 9702545eb61SSteven Rostedt my $booted = 0; 9712545eb61SSteven Rostedt my $bug = 0; 9725c42fc5bSSteven Rostedt my $skip_call_trace = 0; 9732b7d9b21SSteven Rostedt my $loops; 9742545eb61SSteven Rostedt 9757faafbd6SSteven Rostedt wait_for_monitor 5; 9762545eb61SSteven Rostedt 9772545eb61SSteven Rostedt my $line; 9782545eb61SSteven Rostedt my $full_line = ""; 9792545eb61SSteven Rostedt 9807faafbd6SSteven Rostedt open(DMESG, "> $dmesg") or 9817faafbd6SSteven Rostedt die "unable to write to $dmesg"; 9822545eb61SSteven Rostedt 98375c3fda7SSteven Rostedt reboot_to; 9842545eb61SSteven Rostedt 9851c8a617aSSteven Rostedt my $success_start; 9861c8a617aSSteven Rostedt my $failure_start; 9872d01b26aSSteven Rostedt my $monitor_start = time; 9882d01b26aSSteven Rostedt my $done = 0; 989f1a5b962SSteven Rostedt my $version_found = 0; 9901c8a617aSSteven Rostedt 9912d01b26aSSteven Rostedt while (!$done) { 9922545eb61SSteven Rostedt 993ecaf8e52SSteven Rostedt if ($bug && defined($stop_after_failure) && 994ecaf8e52SSteven Rostedt $stop_after_failure >= 0) { 995ecaf8e52SSteven Rostedt my $time = $stop_after_failure - (time - $failure_start); 996ecaf8e52SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 997ecaf8e52SSteven Rostedt if (!defined($line)) { 998ecaf8e52SSteven Rostedt doprint "bug timed out after $booted_timeout seconds\n"; 999ecaf8e52SSteven Rostedt doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 1000ecaf8e52SSteven Rostedt last; 1001ecaf8e52SSteven Rostedt } 1002ecaf8e52SSteven Rostedt } elsif ($booted) { 1003a75fececSSteven Rostedt $line = wait_for_input($monitor_fp, $booted_timeout); 1004cd4f1d53SSteven Rostedt if (!defined($line)) { 1005cd4f1d53SSteven Rostedt my $s = $booted_timeout == 1 ? "" : "s"; 1006cd4f1d53SSteven Rostedt doprint "Successful boot found: break after $booted_timeout second$s\n"; 1007cd4f1d53SSteven Rostedt last; 1008cd4f1d53SSteven Rostedt } 10092b7d9b21SSteven Rostedt } else { 10107faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp); 1011cd4f1d53SSteven Rostedt if (!defined($line)) { 1012cd4f1d53SSteven Rostedt my $s = $timeout == 1 ? "" : "s"; 1013cd4f1d53SSteven Rostedt doprint "Timed out after $timeout second$s\n"; 1014cd4f1d53SSteven Rostedt last; 10152b7d9b21SSteven Rostedt } 1016cd4f1d53SSteven Rostedt } 10172545eb61SSteven Rostedt 10182545eb61SSteven Rostedt doprint $line; 10197faafbd6SSteven Rostedt print DMESG $line; 10202545eb61SSteven Rostedt 10212545eb61SSteven Rostedt # we are not guaranteed to get a full line 10222545eb61SSteven Rostedt $full_line .= $line; 10232545eb61SSteven Rostedt 1024a75fececSSteven Rostedt if ($full_line =~ /$success_line/) { 10252545eb61SSteven Rostedt $booted = 1; 10261c8a617aSSteven Rostedt $success_start = time; 10271c8a617aSSteven Rostedt } 10281c8a617aSSteven Rostedt 10291c8a617aSSteven Rostedt if ($booted && defined($stop_after_success) && 10301c8a617aSSteven Rostedt $stop_after_success >= 0) { 10311c8a617aSSteven Rostedt my $now = time; 10321c8a617aSSteven Rostedt if ($now - $success_start >= $stop_after_success) { 10331c8a617aSSteven Rostedt doprint "Test forced to stop after $stop_after_success seconds after success\n"; 10341c8a617aSSteven Rostedt last; 10351c8a617aSSteven Rostedt } 10362545eb61SSteven Rostedt } 10372545eb61SSteven Rostedt 10385c42fc5bSSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 10395c42fc5bSSteven Rostedt $skip_call_trace = 1; 10405c42fc5bSSteven Rostedt } 10415c42fc5bSSteven Rostedt 10422545eb61SSteven Rostedt if ($full_line =~ /call trace:/i) { 10434651920eSSteven Rostedt if (!$bug && !$skip_call_trace) { 10441c8a617aSSteven Rostedt $bug = 1; 10451c8a617aSSteven Rostedt $failure_start = time; 10461c8a617aSSteven Rostedt } 10471c8a617aSSteven Rostedt } 10481c8a617aSSteven Rostedt 10491c8a617aSSteven Rostedt if ($bug && defined($stop_after_failure) && 10501c8a617aSSteven Rostedt $stop_after_failure >= 0) { 10511c8a617aSSteven Rostedt my $now = time; 10521c8a617aSSteven Rostedt if ($now - $failure_start >= $stop_after_failure) { 10531c8a617aSSteven Rostedt doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 10541c8a617aSSteven Rostedt last; 10551c8a617aSSteven Rostedt } 10565c42fc5bSSteven Rostedt } 10575c42fc5bSSteven Rostedt 10585c42fc5bSSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 10595c42fc5bSSteven Rostedt $skip_call_trace = 0; 10605c42fc5bSSteven Rostedt } 10615c42fc5bSSteven Rostedt 10625c42fc5bSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 106310abf118SSteven Rostedt $failure_start = time; 10642545eb61SSteven Rostedt $bug = 1; 10652545eb61SSteven Rostedt } 10662545eb61SSteven Rostedt 1067f1a5b962SSteven Rostedt # Detect triple faults by testing the banner 1068f1a5b962SSteven Rostedt if ($full_line =~ /\bLinux version (\S+).*\n/) { 1069f1a5b962SSteven Rostedt if ($1 eq $version) { 1070f1a5b962SSteven Rostedt $version_found = 1; 1071f1a5b962SSteven Rostedt } elsif ($version_found && $detect_triplefault) { 1072f1a5b962SSteven Rostedt # We already booted into the kernel we are testing, 1073f1a5b962SSteven Rostedt # but now we booted into another kernel? 1074f1a5b962SSteven Rostedt # Consider this a triple fault. 1075f1a5b962SSteven Rostedt doprint "Aleady booted in Linux kernel $version, but now\n"; 1076f1a5b962SSteven Rostedt doprint "we booted into Linux kernel $1.\n"; 1077f1a5b962SSteven Rostedt doprint "Assuming that this is a triple fault.\n"; 1078f1a5b962SSteven Rostedt doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; 1079f1a5b962SSteven Rostedt last; 1080f1a5b962SSteven Rostedt } 1081f1a5b962SSteven Rostedt } 1082f1a5b962SSteven Rostedt 10832545eb61SSteven Rostedt if ($line =~ /\n/) { 10842545eb61SSteven Rostedt $full_line = ""; 10852545eb61SSteven Rostedt } 10862d01b26aSSteven Rostedt 10872d01b26aSSteven Rostedt if ($stop_test_after > 0 && !$booted && !$bug) { 10882d01b26aSSteven Rostedt if (time - $monitor_start > $stop_test_after) { 10894d62bf51SSteven Rostedt doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 10902d01b26aSSteven Rostedt $done = 1; 10912d01b26aSSteven Rostedt } 10922d01b26aSSteven Rostedt } 10932545eb61SSteven Rostedt } 10942545eb61SSteven Rostedt 10957faafbd6SSteven Rostedt close(DMESG); 10962545eb61SSteven Rostedt 10972545eb61SSteven Rostedt if ($bug) { 10982b7d9b21SSteven Rostedt return 0 if ($in_bisect); 1099576f627cSSteven Rostedt fail "failed - got a bug report" and return 0; 11002545eb61SSteven Rostedt } 11015f9b6cedSSteven Rostedt 1102a75fececSSteven Rostedt if (!$booted) { 1103a75fececSSteven Rostedt return 0 if ($in_bisect); 1104576f627cSSteven Rostedt fail "failed - never got a boot prompt." and return 0; 1105a75fececSSteven Rostedt } 1106a75fececSSteven Rostedt 11072b7d9b21SSteven Rostedt return 1; 11082545eb61SSteven Rostedt} 11092545eb61SSteven Rostedt 1110db05cfefSSteven Rostedtsub do_post_install { 1111db05cfefSSteven Rostedt 1112db05cfefSSteven Rostedt return if (!defined($post_install)); 1113db05cfefSSteven Rostedt 1114db05cfefSSteven Rostedt my $cp_post_install = $post_install; 1115db05cfefSSteven Rostedt $cp_post_install =~ s/\$KERNEL_VERSION/$version/g; 1116db05cfefSSteven Rostedt run_command "$cp_post_install" or 1117db05cfefSSteven Rostedt dodie "Failed to run post install"; 1118db05cfefSSteven Rostedt} 1119db05cfefSSteven Rostedt 11202545eb61SSteven Rostedtsub install { 11212545eb61SSteven Rostedt 1122e0a8742eSSteven Rostedt return if ($no_install); 1123e0a8742eSSteven Rostedt 1124e48c5293SSteven Rostedt run_scp "$outputdir/$build_target", "$target_image" or 11255c42fc5bSSteven Rostedt dodie "failed to copy image"; 11265f9b6cedSSteven Rostedt 11275f9b6cedSSteven Rostedt my $install_mods = 0; 11285f9b6cedSSteven Rostedt 11295f9b6cedSSteven Rostedt # should we process modules? 11305f9b6cedSSteven Rostedt $install_mods = 0; 113151ad1dd1SSteven Rostedt open(IN, "$output_config") or dodie("Can't read config file"); 11325f9b6cedSSteven Rostedt while (<IN>) { 11335f9b6cedSSteven Rostedt if (/CONFIG_MODULES(=y)?/) { 11345f9b6cedSSteven Rostedt $install_mods = 1 if (defined($1)); 11355f9b6cedSSteven Rostedt last; 11365f9b6cedSSteven Rostedt } 11375f9b6cedSSteven Rostedt } 11385f9b6cedSSteven Rostedt close(IN); 11395f9b6cedSSteven Rostedt 11405f9b6cedSSteven Rostedt if (!$install_mods) { 1141db05cfefSSteven Rostedt do_post_install; 11425f9b6cedSSteven Rostedt doprint "No modules needed\n"; 11435f9b6cedSSteven Rostedt return; 11442545eb61SSteven Rostedt } 11452545eb61SSteven Rostedt 1146a75fececSSteven Rostedt run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or 11475f9b6cedSSteven Rostedt dodie "Failed to install modules"; 11485f9b6cedSSteven Rostedt 11492545eb61SSteven Rostedt my $modlib = "/lib/modules/$version"; 1150a57419b3SSteven Rostedt my $modtar = "ktest-mods.tar.bz2"; 11512545eb61SSteven Rostedt 1152e48c5293SSteven Rostedt run_ssh "rm -rf $modlib" or 11535c42fc5bSSteven Rostedt dodie "failed to remove old mods: $modlib"; 11542545eb61SSteven Rostedt 11555c42fc5bSSteven Rostedt # would be nice if scp -r did not follow symbolic links 1156a75fececSSteven Rostedt run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 11575c42fc5bSSteven Rostedt dodie "making tarball"; 11585c42fc5bSSteven Rostedt 1159e48c5293SSteven Rostedt run_scp "$tmpdir/$modtar", "/tmp" or 11605c42fc5bSSteven Rostedt dodie "failed to copy modules"; 11615c42fc5bSSteven Rostedt 1162a75fececSSteven Rostedt unlink "$tmpdir/$modtar"; 11635c42fc5bSSteven Rostedt 1164e7b13441SSteven Rostedt run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or 11655c42fc5bSSteven Rostedt dodie "failed to tar modules"; 11665c42fc5bSSteven Rostedt 1167e48c5293SSteven Rostedt run_ssh "rm -f /tmp/$modtar"; 11688b37ca8cSSteven Rostedt 1169db05cfefSSteven Rostedt do_post_install; 11702545eb61SSteven Rostedt} 11712545eb61SSteven Rostedt 1172ddf607e5SSteven Rostedtsub get_version { 1173ddf607e5SSteven Rostedt # get the release name 1174ddf607e5SSteven Rostedt doprint "$make kernelrelease ... "; 1175ddf607e5SSteven Rostedt $version = `$make kernelrelease | tail -1`; 1176ddf607e5SSteven Rostedt chomp($version); 1177ddf607e5SSteven Rostedt doprint "$version\n"; 1178ddf607e5SSteven Rostedt} 1179ddf607e5SSteven Rostedt 1180ddf607e5SSteven Rostedtsub start_monitor_and_boot { 1181ddf607e5SSteven Rostedt get_grub_index; 1182ddf607e5SSteven Rostedt get_version; 1183ddf607e5SSteven Rostedt install; 1184ddf607e5SSteven Rostedt 1185ddf607e5SSteven Rostedt start_monitor; 1186ddf607e5SSteven Rostedt return monitor; 1187ddf607e5SSteven Rostedt} 1188ddf607e5SSteven Rostedt 11896c5ee0beSSteven Rostedtsub check_buildlog { 11906c5ee0beSSteven Rostedt my ($patch) = @_; 11916c5ee0beSSteven Rostedt 11926c5ee0beSSteven Rostedt my @files = `git show $patch | diffstat -l`; 11936c5ee0beSSteven Rostedt 11946c5ee0beSSteven Rostedt open(IN, "git show $patch |") or 11956c5ee0beSSteven Rostedt dodie "failed to show $patch"; 11966c5ee0beSSteven Rostedt while (<IN>) { 11976c5ee0beSSteven Rostedt if (m,^--- a/(.*),) { 11986c5ee0beSSteven Rostedt chomp $1; 11996c5ee0beSSteven Rostedt $files[$#files] = $1; 12006c5ee0beSSteven Rostedt } 12016c5ee0beSSteven Rostedt } 12026c5ee0beSSteven Rostedt close(IN); 12036c5ee0beSSteven Rostedt 12046c5ee0beSSteven Rostedt open(IN, $buildlog) or dodie "Can't open $buildlog"; 12056c5ee0beSSteven Rostedt while (<IN>) { 12066c5ee0beSSteven Rostedt if (/^\s*(.*?):.*(warning|error)/) { 12076c5ee0beSSteven Rostedt my $err = $1; 12086c5ee0beSSteven Rostedt foreach my $file (@files) { 1209a75fececSSteven Rostedt my $fullpath = "$builddir/$file"; 12106c5ee0beSSteven Rostedt if ($file eq $err || $fullpath eq $err) { 12112b7d9b21SSteven Rostedt fail "$file built with warnings" and return 0; 12126c5ee0beSSteven Rostedt } 12136c5ee0beSSteven Rostedt } 12146c5ee0beSSteven Rostedt } 12156c5ee0beSSteven Rostedt } 12166c5ee0beSSteven Rostedt close(IN); 12172b7d9b21SSteven Rostedt 12182b7d9b21SSteven Rostedt return 1; 12196c5ee0beSSteven Rostedt} 12206c5ee0beSSteven Rostedt 1221fcb3f16aSSteven Rostedtsub apply_min_config { 1222fcb3f16aSSteven Rostedt my $outconfig = "$output_config.new"; 1223612b9e9bSSteven Rostedt 1224fcb3f16aSSteven Rostedt # Read the config file and remove anything that 1225fcb3f16aSSteven Rostedt # is in the force_config hash (from minconfig and others) 1226fcb3f16aSSteven Rostedt # then add the force config back. 1227fcb3f16aSSteven Rostedt 1228fcb3f16aSSteven Rostedt doprint "Applying minimum configurations into $output_config.new\n"; 1229fcb3f16aSSteven Rostedt 1230fcb3f16aSSteven Rostedt open (OUT, ">$outconfig") or 1231fcb3f16aSSteven Rostedt dodie "Can't create $outconfig"; 1232fcb3f16aSSteven Rostedt 1233fcb3f16aSSteven Rostedt if (-f $output_config) { 1234fcb3f16aSSteven Rostedt open (IN, $output_config) or 1235fcb3f16aSSteven Rostedt dodie "Failed to open $output_config"; 1236fcb3f16aSSteven Rostedt while (<IN>) { 1237fcb3f16aSSteven Rostedt if (/^(# )?(CONFIG_[^\s=]*)/) { 1238fcb3f16aSSteven Rostedt next if (defined($force_config{$2})); 1239fcb3f16aSSteven Rostedt } 1240fcb3f16aSSteven Rostedt print OUT; 1241fcb3f16aSSteven Rostedt } 1242fcb3f16aSSteven Rostedt close IN; 1243fcb3f16aSSteven Rostedt } 1244fcb3f16aSSteven Rostedt foreach my $config (keys %force_config) { 1245fcb3f16aSSteven Rostedt print OUT "$force_config{$config}\n"; 1246fcb3f16aSSteven Rostedt } 1247fcb3f16aSSteven Rostedt close OUT; 1248fcb3f16aSSteven Rostedt 1249fcb3f16aSSteven Rostedt run_command "mv $outconfig $output_config"; 1250fcb3f16aSSteven Rostedt} 1251fcb3f16aSSteven Rostedt 1252fcb3f16aSSteven Rostedtsub make_oldconfig { 1253fcb3f16aSSteven Rostedt 12544c4ab120SSteven Rostedt my @force_list = keys %force_config; 12554c4ab120SSteven Rostedt 12564c4ab120SSteven Rostedt if ($#force_list >= 0) { 1257fcb3f16aSSteven Rostedt apply_min_config; 12584c4ab120SSteven Rostedt } 1259fcb3f16aSSteven Rostedt 1260fcb3f16aSSteven Rostedt if (!run_command "$make oldnoconfig") { 1261612b9e9bSSteven Rostedt # Perhaps oldnoconfig doesn't exist in this version of the kernel 1262612b9e9bSSteven Rostedt # try a yes '' | oldconfig 1263612b9e9bSSteven Rostedt doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 1264fcb3f16aSSteven Rostedt run_command "yes '' | $make oldconfig" or 1265612b9e9bSSteven Rostedt dodie "failed make config oldconfig"; 1266612b9e9bSSteven Rostedt } 1267612b9e9bSSteven Rostedt} 1268612b9e9bSSteven Rostedt 1269fcb3f16aSSteven Rostedt# read a config file and use this to force new configs. 1270fcb3f16aSSteven Rostedtsub load_force_config { 1271fcb3f16aSSteven Rostedt my ($config) = @_; 1272fcb3f16aSSteven Rostedt 1273fcb3f16aSSteven Rostedt open(IN, $config) or 1274fcb3f16aSSteven Rostedt dodie "failed to read $config"; 1275fcb3f16aSSteven Rostedt while (<IN>) { 1276fcb3f16aSSteven Rostedt chomp; 1277fcb3f16aSSteven Rostedt if (/^(CONFIG[^\s=]*)(\s*=.*)/) { 1278fcb3f16aSSteven Rostedt $force_config{$1} = $_; 1279fcb3f16aSSteven Rostedt } elsif (/^# (CONFIG_\S*) is not set/) { 1280fcb3f16aSSteven Rostedt $force_config{$1} = $_; 1281fcb3f16aSSteven Rostedt } 1282fcb3f16aSSteven Rostedt } 1283fcb3f16aSSteven Rostedt close IN; 1284fcb3f16aSSteven Rostedt} 1285fcb3f16aSSteven Rostedt 12862545eb61SSteven Rostedtsub build { 12872545eb61SSteven Rostedt my ($type) = @_; 12882545eb61SSteven Rostedt 12897faafbd6SSteven Rostedt unlink $buildlog; 12907faafbd6SSteven Rostedt 1291*4ab1cce5SSteven Rostedt # Failed builds should not reboot the target 1292*4ab1cce5SSteven Rostedt my $save_no_reboot = $no_reboot; 1293*4ab1cce5SSteven Rostedt $no_reboot = 1; 1294*4ab1cce5SSteven Rostedt 12950bd6c1a3SSteven Rostedt if (defined($pre_build)) { 12960bd6c1a3SSteven Rostedt my $ret = run_command $pre_build; 12970bd6c1a3SSteven Rostedt if (!$ret && defined($pre_build_die) && 12980bd6c1a3SSteven Rostedt $pre_build_die) { 12990bd6c1a3SSteven Rostedt dodie "failed to pre_build\n"; 13000bd6c1a3SSteven Rostedt } 13010bd6c1a3SSteven Rostedt } 13020bd6c1a3SSteven Rostedt 130375c3fda7SSteven Rostedt if ($type =~ /^useconfig:(.*)/) { 130451ad1dd1SSteven Rostedt run_command "cp $1 $output_config" or 130575c3fda7SSteven Rostedt dodie "could not copy $1 to .config"; 13065f9b6cedSSteven Rostedt 130775c3fda7SSteven Rostedt $type = "oldconfig"; 130875c3fda7SSteven Rostedt } 130975c3fda7SSteven Rostedt 13105c42fc5bSSteven Rostedt # old config can ask questions 13115c42fc5bSSteven Rostedt if ($type eq "oldconfig") { 13129386c6abSSteven Rostedt $type = "oldnoconfig"; 131375c3fda7SSteven Rostedt 131475c3fda7SSteven Rostedt # allow for empty configs 131551ad1dd1SSteven Rostedt run_command "touch $output_config"; 131675c3fda7SSteven Rostedt 131713488231SAndrew Jones if (!$noclean) { 131851ad1dd1SSteven Rostedt run_command "mv $output_config $outputdir/config_temp" or 13195c42fc5bSSteven Rostedt dodie "moving .config"; 13205c42fc5bSSteven Rostedt 132113488231SAndrew Jones run_command "$make mrproper" or dodie "make mrproper"; 13225c42fc5bSSteven Rostedt 132351ad1dd1SSteven Rostedt run_command "mv $outputdir/config_temp $output_config" or 13245c42fc5bSSteven Rostedt dodie "moving config_temp"; 132513488231SAndrew Jones } 13265c42fc5bSSteven Rostedt 13275c42fc5bSSteven Rostedt } elsif (!$noclean) { 132851ad1dd1SSteven Rostedt unlink "$output_config"; 13295f9b6cedSSteven Rostedt run_command "$make mrproper" or 13305c42fc5bSSteven Rostedt dodie "make mrproper"; 13315c42fc5bSSteven Rostedt } 13322545eb61SSteven Rostedt 13332545eb61SSteven Rostedt # add something to distinguish this build 1334a75fececSSteven Rostedt open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 1335a75fececSSteven Rostedt print OUT "$localversion\n"; 13362545eb61SSteven Rostedt close(OUT); 13372545eb61SSteven Rostedt 13385f9b6cedSSteven Rostedt if (defined($minconfig)) { 1339fcb3f16aSSteven Rostedt load_force_config($minconfig); 13402545eb61SSteven Rostedt } 13412545eb61SSteven Rostedt 1342fcb3f16aSSteven Rostedt if ($type ne "oldnoconfig") { 1343fcb3f16aSSteven Rostedt run_command "$make $type" or 13445c42fc5bSSteven Rostedt dodie "failed make config"; 1345612b9e9bSSteven Rostedt } 1346fcb3f16aSSteven Rostedt # Run old config regardless, to enforce min configurations 1347fcb3f16aSSteven Rostedt make_oldconfig; 13482545eb61SSteven Rostedt 1349a75fececSSteven Rostedt $redirect = "$buildlog"; 13500bd6c1a3SSteven Rostedt my $build_ret = run_command "$make $build_options"; 13516c5ee0beSSteven Rostedt undef $redirect; 13520bd6c1a3SSteven Rostedt 13530bd6c1a3SSteven Rostedt if (defined($post_build)) { 13540bd6c1a3SSteven Rostedt my $ret = run_command $post_build; 13550bd6c1a3SSteven Rostedt if (!$ret && defined($post_build_die) && 13560bd6c1a3SSteven Rostedt $post_build_die) { 13570bd6c1a3SSteven Rostedt dodie "failed to post_build\n"; 13580bd6c1a3SSteven Rostedt } 13590bd6c1a3SSteven Rostedt } 13600bd6c1a3SSteven Rostedt 13610bd6c1a3SSteven Rostedt if (!$build_ret) { 13625f9b6cedSSteven Rostedt # bisect may need this to pass 1363*4ab1cce5SSteven Rostedt if ($in_bisect) { 1364*4ab1cce5SSteven Rostedt $no_reboot = $save_no_reboot; 1365*4ab1cce5SSteven Rostedt return 0; 1366*4ab1cce5SSteven Rostedt } 13672b7d9b21SSteven Rostedt fail "failed build" and return 0; 13682545eb61SSteven Rostedt } 13695f9b6cedSSteven Rostedt 1370*4ab1cce5SSteven Rostedt $no_reboot = $save_no_reboot; 1371*4ab1cce5SSteven Rostedt 13722b7d9b21SSteven Rostedt return 1; 13732545eb61SSteven Rostedt} 13742545eb61SSteven Rostedt 137575c3fda7SSteven Rostedtsub halt { 1376e48c5293SSteven Rostedt if (!run_ssh "halt" or defined($power_off)) { 1377576f627cSSteven Rostedt if (defined($poweroff_after_halt)) { 1378576f627cSSteven Rostedt sleep $poweroff_after_halt; 1379576f627cSSteven Rostedt run_command "$power_off"; 1380576f627cSSteven Rostedt } 1381576f627cSSteven Rostedt } else { 138275c3fda7SSteven Rostedt # nope? the zap it! 1383a75fececSSteven Rostedt run_command "$power_off"; 138475c3fda7SSteven Rostedt } 138575c3fda7SSteven Rostedt} 138675c3fda7SSteven Rostedt 13875f9b6cedSSteven Rostedtsub success { 13885f9b6cedSSteven Rostedt my ($i) = @_; 13895f9b6cedSSteven Rostedt 1390e48c5293SSteven Rostedt $successes++; 1391e48c5293SSteven Rostedt 13929064af52SSteven Rostedt my $name = ""; 13939064af52SSteven Rostedt 13949064af52SSteven Rostedt if (defined($test_name)) { 13959064af52SSteven Rostedt $name = " ($test_name)"; 13969064af52SSteven Rostedt } 13979064af52SSteven Rostedt 13985f9b6cedSSteven Rostedt doprint "\n\n*******************************************\n"; 13995f9b6cedSSteven Rostedt doprint "*******************************************\n"; 14009064af52SSteven Rostedt doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; 14015f9b6cedSSteven Rostedt doprint "*******************************************\n"; 14025f9b6cedSSteven Rostedt doprint "*******************************************\n"; 14035f9b6cedSSteven Rostedt 1404576f627cSSteven Rostedt if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 1405a75fececSSteven Rostedt doprint "Reboot and wait $sleep_time seconds\n"; 14062728be41SAndrew Jones reboot $sleep_time; 14075f9b6cedSSteven Rostedt } 14085f9b6cedSSteven Rostedt} 14095f9b6cedSSteven Rostedt 1410c960bb9fSSteven Rostedtsub answer_bisect { 1411c960bb9fSSteven Rostedt for (;;) { 1412c960bb9fSSteven Rostedt doprint "Pass or fail? [p/f]"; 1413c960bb9fSSteven Rostedt my $ans = <STDIN>; 1414c960bb9fSSteven Rostedt chomp $ans; 1415c960bb9fSSteven Rostedt if ($ans eq "p" || $ans eq "P") { 1416c960bb9fSSteven Rostedt return 1; 1417c960bb9fSSteven Rostedt } elsif ($ans eq "f" || $ans eq "F") { 1418c960bb9fSSteven Rostedt return 0; 1419c960bb9fSSteven Rostedt } else { 1420c960bb9fSSteven Rostedt print "Please answer 'P' or 'F'\n"; 1421c960bb9fSSteven Rostedt } 1422c960bb9fSSteven Rostedt } 1423c960bb9fSSteven Rostedt} 1424c960bb9fSSteven Rostedt 14255a391fbfSSteven Rostedtsub child_run_test { 14267faafbd6SSteven Rostedt my $failed = 0; 14275a391fbfSSteven Rostedt 14287faafbd6SSteven Rostedt # child should have no power 1429a75fececSSteven Rostedt $reboot_on_error = 0; 1430a75fececSSteven Rostedt $poweroff_on_error = 0; 1431a75fececSSteven Rostedt $die_on_failure = 1; 14327faafbd6SSteven Rostedt 14337faafbd6SSteven Rostedt run_command $run_test or $failed = 1; 14345a391fbfSSteven Rostedt exit $failed; 14355a391fbfSSteven Rostedt} 14365a391fbfSSteven Rostedt 14375a391fbfSSteven Rostedtmy $child_done; 14385a391fbfSSteven Rostedt 14395a391fbfSSteven Rostedtsub child_finished { 14405a391fbfSSteven Rostedt $child_done = 1; 14415a391fbfSSteven Rostedt} 14425a391fbfSSteven Rostedt 14435a391fbfSSteven Rostedtsub do_run_test { 14445a391fbfSSteven Rostedt my $child_pid; 14455a391fbfSSteven Rostedt my $child_exit; 14465a391fbfSSteven Rostedt my $line; 14475a391fbfSSteven Rostedt my $full_line; 14485a391fbfSSteven Rostedt my $bug = 0; 14495a391fbfSSteven Rostedt 14507faafbd6SSteven Rostedt wait_for_monitor 1; 14515a391fbfSSteven Rostedt 14527faafbd6SSteven Rostedt doprint "run test $run_test\n"; 14535a391fbfSSteven Rostedt 14545a391fbfSSteven Rostedt $child_done = 0; 14555a391fbfSSteven Rostedt 14565a391fbfSSteven Rostedt $SIG{CHLD} = qw(child_finished); 14575a391fbfSSteven Rostedt 14585a391fbfSSteven Rostedt $child_pid = fork; 14595a391fbfSSteven Rostedt 14605a391fbfSSteven Rostedt child_run_test if (!$child_pid); 14615a391fbfSSteven Rostedt 14625a391fbfSSteven Rostedt $full_line = ""; 14635a391fbfSSteven Rostedt 14645a391fbfSSteven Rostedt do { 14657faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 14665a391fbfSSteven Rostedt if (defined($line)) { 14675a391fbfSSteven Rostedt 14685a391fbfSSteven Rostedt # we are not guaranteed to get a full line 14695a391fbfSSteven Rostedt $full_line .= $line; 14708ea0e063SSteven Rostedt doprint $line; 14715a391fbfSSteven Rostedt 14725a391fbfSSteven Rostedt if ($full_line =~ /call trace:/i) { 14735a391fbfSSteven Rostedt $bug = 1; 14745a391fbfSSteven Rostedt } 14755a391fbfSSteven Rostedt 14765a391fbfSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 14775a391fbfSSteven Rostedt $bug = 1; 14785a391fbfSSteven Rostedt } 14795a391fbfSSteven Rostedt 14805a391fbfSSteven Rostedt if ($line =~ /\n/) { 14815a391fbfSSteven Rostedt $full_line = ""; 14825a391fbfSSteven Rostedt } 14835a391fbfSSteven Rostedt } 14845a391fbfSSteven Rostedt } while (!$child_done && !$bug); 14855a391fbfSSteven Rostedt 14865a391fbfSSteven Rostedt if ($bug) { 14878ea0e063SSteven Rostedt my $failure_start = time; 14888ea0e063SSteven Rostedt my $now; 14898ea0e063SSteven Rostedt do { 14908ea0e063SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 14918ea0e063SSteven Rostedt if (defined($line)) { 14928ea0e063SSteven Rostedt doprint $line; 14938ea0e063SSteven Rostedt } 14948ea0e063SSteven Rostedt $now = time; 14958ea0e063SSteven Rostedt if ($now - $failure_start >= $stop_after_failure) { 14968ea0e063SSteven Rostedt last; 14978ea0e063SSteven Rostedt } 14988ea0e063SSteven Rostedt } while (defined($line)); 14998ea0e063SSteven Rostedt 15005a391fbfSSteven Rostedt doprint "Detected kernel crash!\n"; 15015a391fbfSSteven Rostedt # kill the child with extreme prejudice 15025a391fbfSSteven Rostedt kill 9, $child_pid; 15035a391fbfSSteven Rostedt } 15045a391fbfSSteven Rostedt 15055a391fbfSSteven Rostedt waitpid $child_pid, 0; 15065a391fbfSSteven Rostedt $child_exit = $?; 15075a391fbfSSteven Rostedt 15085a391fbfSSteven Rostedt if ($bug || $child_exit) { 15092b7d9b21SSteven Rostedt return 0 if $in_bisect; 15102b7d9b21SSteven Rostedt fail "test failed" and return 0; 15115a391fbfSSteven Rostedt } 15122b7d9b21SSteven Rostedt return 1; 15135a391fbfSSteven Rostedt} 15145a391fbfSSteven Rostedt 1515a75fececSSteven Rostedtsub run_git_bisect { 1516a75fececSSteven Rostedt my ($command) = @_; 1517a75fececSSteven Rostedt 1518a75fececSSteven Rostedt doprint "$command ... "; 1519a75fececSSteven Rostedt 1520a75fececSSteven Rostedt my $output = `$command 2>&1`; 1521a75fececSSteven Rostedt my $ret = $?; 1522a75fececSSteven Rostedt 1523a75fececSSteven Rostedt logit $output; 1524a75fececSSteven Rostedt 1525a75fececSSteven Rostedt if ($ret) { 1526a75fececSSteven Rostedt doprint "FAILED\n"; 1527a75fececSSteven Rostedt dodie "Failed to git bisect"; 1528a75fececSSteven Rostedt } 1529a75fececSSteven Rostedt 1530a75fececSSteven Rostedt doprint "SUCCESS\n"; 1531a75fececSSteven Rostedt if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 1532a75fececSSteven Rostedt doprint "$1 [$2]\n"; 1533a75fececSSteven Rostedt } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 1534a75fececSSteven Rostedt $bisect_bad = $1; 1535a75fececSSteven Rostedt doprint "Found bad commit... $1\n"; 1536a75fececSSteven Rostedt return 0; 1537a75fececSSteven Rostedt } else { 1538a75fececSSteven Rostedt # we already logged it, just print it now. 1539a75fececSSteven Rostedt print $output; 1540a75fececSSteven Rostedt } 1541a75fececSSteven Rostedt 1542a75fececSSteven Rostedt return 1; 1543a75fececSSteven Rostedt} 1544a75fececSSteven Rostedt 1545c23dca7cSSteven Rostedtsub bisect_reboot { 1546c23dca7cSSteven Rostedt doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 15472728be41SAndrew Jones reboot $bisect_sleep_time; 1548c23dca7cSSteven Rostedt} 1549c23dca7cSSteven Rostedt 1550c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip 15510a05c769SSteven Rostedtsub run_bisect_test { 15520a05c769SSteven Rostedt my ($type, $buildtype) = @_; 15535f9b6cedSSteven Rostedt 15542b7d9b21SSteven Rostedt my $failed = 0; 15555f9b6cedSSteven Rostedt my $result; 15565f9b6cedSSteven Rostedt my $output; 15575f9b6cedSSteven Rostedt my $ret; 15585f9b6cedSSteven Rostedt 15590a05c769SSteven Rostedt $in_bisect = 1; 15600a05c769SSteven Rostedt 15610a05c769SSteven Rostedt build $buildtype or $failed = 1; 15625f9b6cedSSteven Rostedt 15635f9b6cedSSteven Rostedt if ($type ne "build") { 1564c23dca7cSSteven Rostedt if ($failed && $bisect_skip) { 1565c23dca7cSSteven Rostedt $in_bisect = 0; 1566c23dca7cSSteven Rostedt return -1; 1567c23dca7cSSteven Rostedt } 15687faafbd6SSteven Rostedt dodie "Failed on build" if $failed; 15695f9b6cedSSteven Rostedt 15705f9b6cedSSteven Rostedt # Now boot the box 1571ddf607e5SSteven Rostedt start_monitor_and_boot or $failed = 1; 15725f9b6cedSSteven Rostedt 15735f9b6cedSSteven Rostedt if ($type ne "boot") { 1574c23dca7cSSteven Rostedt if ($failed && $bisect_skip) { 1575c23dca7cSSteven Rostedt end_monitor; 1576c23dca7cSSteven Rostedt bisect_reboot; 1577c23dca7cSSteven Rostedt $in_bisect = 0; 1578c23dca7cSSteven Rostedt return -1; 1579c23dca7cSSteven Rostedt } 15807faafbd6SSteven Rostedt dodie "Failed on boot" if $failed; 15815a391fbfSSteven Rostedt 15822b7d9b21SSteven Rostedt do_run_test or $failed = 1; 15835f9b6cedSSteven Rostedt } 15847faafbd6SSteven Rostedt end_monitor; 15855f9b6cedSSteven Rostedt } 15865f9b6cedSSteven Rostedt 15875f9b6cedSSteven Rostedt if ($failed) { 15880a05c769SSteven Rostedt $result = 0; 15895f9b6cedSSteven Rostedt } else { 15900a05c769SSteven Rostedt $result = 1; 15915f9b6cedSSteven Rostedt } 15924025bc62SSteven Rostedt 15934025bc62SSteven Rostedt # reboot the box to a kernel we can ssh to 15944025bc62SSteven Rostedt if ($type ne "build") { 15954025bc62SSteven Rostedt bisect_reboot; 15964025bc62SSteven Rostedt } 15970a05c769SSteven Rostedt $in_bisect = 0; 15980a05c769SSteven Rostedt 15990a05c769SSteven Rostedt return $result; 16000a05c769SSteven Rostedt} 16010a05c769SSteven Rostedt 16020a05c769SSteven Rostedtsub run_bisect { 16030a05c769SSteven Rostedt my ($type) = @_; 16040a05c769SSteven Rostedt my $buildtype = "oldconfig"; 16050a05c769SSteven Rostedt 16060a05c769SSteven Rostedt # We should have a minconfig to use? 16070a05c769SSteven Rostedt if (defined($minconfig)) { 16080a05c769SSteven Rostedt $buildtype = "useconfig:$minconfig"; 16090a05c769SSteven Rostedt } 16100a05c769SSteven Rostedt 16110a05c769SSteven Rostedt my $ret = run_bisect_test $type, $buildtype; 16120a05c769SSteven Rostedt 1613c960bb9fSSteven Rostedt if ($bisect_manual) { 1614c960bb9fSSteven Rostedt $ret = answer_bisect; 1615c960bb9fSSteven Rostedt } 16165f9b6cedSSteven Rostedt 1617d6ce2a0bSSteven Rostedt # Are we looking for where it worked, not failed? 1618d6ce2a0bSSteven Rostedt if ($reverse_bisect) { 16190a05c769SSteven Rostedt $ret = !$ret; 1620d6ce2a0bSSteven Rostedt } 1621d6ce2a0bSSteven Rostedt 1622c23dca7cSSteven Rostedt if ($ret > 0) { 16230a05c769SSteven Rostedt return "good"; 1624c23dca7cSSteven Rostedt } elsif ($ret == 0) { 16250a05c769SSteven Rostedt return "bad"; 1626c23dca7cSSteven Rostedt } elsif ($bisect_skip) { 1627c23dca7cSSteven Rostedt doprint "HIT A BAD COMMIT ... SKIPPING\n"; 1628c23dca7cSSteven Rostedt return "skip"; 16290a05c769SSteven Rostedt } 16305f9b6cedSSteven Rostedt} 16315f9b6cedSSteven Rostedt 16325f9b6cedSSteven Rostedtsub bisect { 16335f9b6cedSSteven Rostedt my ($i) = @_; 16345f9b6cedSSteven Rostedt 16355f9b6cedSSteven Rostedt my $result; 16365f9b6cedSSteven Rostedt 16375f9b6cedSSteven Rostedt die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 16385f9b6cedSSteven Rostedt die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 16395f9b6cedSSteven Rostedt die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 16405f9b6cedSSteven Rostedt 16415f9b6cedSSteven Rostedt my $good = $opt{"BISECT_GOOD[$i]"}; 16425f9b6cedSSteven Rostedt my $bad = $opt{"BISECT_BAD[$i]"}; 16435f9b6cedSSteven Rostedt my $type = $opt{"BISECT_TYPE[$i]"}; 1644a75fececSSteven Rostedt my $start = $opt{"BISECT_START[$i]"}; 1645a75fececSSteven Rostedt my $replay = $opt{"BISECT_REPLAY[$i]"}; 16463410f6fdSSteven Rostedt my $start_files = $opt{"BISECT_FILES[$i]"}; 16473410f6fdSSteven Rostedt 16483410f6fdSSteven Rostedt if (defined($start_files)) { 16493410f6fdSSteven Rostedt $start_files = " -- " . $start_files; 16503410f6fdSSteven Rostedt } else { 16513410f6fdSSteven Rostedt $start_files = ""; 16523410f6fdSSteven Rostedt } 16535f9b6cedSSteven Rostedt 1654a57419b3SSteven Rostedt # convert to true sha1's 1655a57419b3SSteven Rostedt $good = get_sha1($good); 1656a57419b3SSteven Rostedt $bad = get_sha1($bad); 1657a57419b3SSteven Rostedt 1658d6ce2a0bSSteven Rostedt if (defined($opt{"BISECT_REVERSE[$i]"}) && 1659d6ce2a0bSSteven Rostedt $opt{"BISECT_REVERSE[$i]"} == 1) { 1660d6ce2a0bSSteven Rostedt doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 1661d6ce2a0bSSteven Rostedt $reverse_bisect = 1; 1662d6ce2a0bSSteven Rostedt } else { 1663d6ce2a0bSSteven Rostedt $reverse_bisect = 0; 1664d6ce2a0bSSteven Rostedt } 1665d6ce2a0bSSteven Rostedt 16665a391fbfSSteven Rostedt # Can't have a test without having a test to run 16675a391fbfSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 16685a391fbfSSteven Rostedt $type = "boot"; 16695a391fbfSSteven Rostedt } 16705a391fbfSSteven Rostedt 1671a75fececSSteven Rostedt my $check = $opt{"BISECT_CHECK[$i]"}; 1672a75fececSSteven Rostedt if (defined($check) && $check ne "0") { 1673a75fececSSteven Rostedt 1674a75fececSSteven Rostedt # get current HEAD 1675a57419b3SSteven Rostedt my $head = get_sha1("HEAD"); 1676a75fececSSteven Rostedt 1677a75fececSSteven Rostedt if ($check ne "good") { 1678a75fececSSteven Rostedt doprint "TESTING BISECT BAD [$bad]\n"; 1679a75fececSSteven Rostedt run_command "git checkout $bad" or 1680a75fececSSteven Rostedt die "Failed to checkout $bad"; 1681a75fececSSteven Rostedt 1682a75fececSSteven Rostedt $result = run_bisect $type; 1683a75fececSSteven Rostedt 1684a75fececSSteven Rostedt if ($result ne "bad") { 1685a75fececSSteven Rostedt fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 1686a75fececSSteven Rostedt } 1687a75fececSSteven Rostedt } 1688a75fececSSteven Rostedt 1689a75fececSSteven Rostedt if ($check ne "bad") { 1690a75fececSSteven Rostedt doprint "TESTING BISECT GOOD [$good]\n"; 1691a75fececSSteven Rostedt run_command "git checkout $good" or 1692a75fececSSteven Rostedt die "Failed to checkout $good"; 1693a75fececSSteven Rostedt 1694a75fececSSteven Rostedt $result = run_bisect $type; 1695a75fececSSteven Rostedt 1696a75fececSSteven Rostedt if ($result ne "good") { 1697a75fececSSteven Rostedt fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 1698a75fececSSteven Rostedt } 1699a75fececSSteven Rostedt } 1700a75fececSSteven Rostedt 1701a75fececSSteven Rostedt # checkout where we started 1702a75fececSSteven Rostedt run_command "git checkout $head" or 1703a75fececSSteven Rostedt die "Failed to checkout $head"; 1704a75fececSSteven Rostedt } 1705a75fececSSteven Rostedt 17063410f6fdSSteven Rostedt run_command "git bisect start$start_files" or 1707a75fececSSteven Rostedt dodie "could not start bisect"; 1708a75fececSSteven Rostedt 1709a75fececSSteven Rostedt run_command "git bisect good $good" or 1710a75fececSSteven Rostedt dodie "could not set bisect good to $good"; 1711a75fececSSteven Rostedt 1712a75fececSSteven Rostedt run_git_bisect "git bisect bad $bad" or 1713a75fececSSteven Rostedt dodie "could not set bisect bad to $bad"; 1714a75fececSSteven Rostedt 1715a75fececSSteven Rostedt if (defined($replay)) { 1716a75fececSSteven Rostedt run_command "git bisect replay $replay" or 1717a75fececSSteven Rostedt dodie "failed to run replay"; 1718a75fececSSteven Rostedt } 1719a75fececSSteven Rostedt 1720a75fececSSteven Rostedt if (defined($start)) { 1721a75fececSSteven Rostedt run_command "git checkout $start" or 1722a75fececSSteven Rostedt dodie "failed to checkout $start"; 1723a75fececSSteven Rostedt } 1724a75fececSSteven Rostedt 1725a75fececSSteven Rostedt my $test; 17265f9b6cedSSteven Rostedt do { 17275f9b6cedSSteven Rostedt $result = run_bisect $type; 1728a75fececSSteven Rostedt $test = run_git_bisect "git bisect $result"; 1729a75fececSSteven Rostedt } while ($test); 17305f9b6cedSSteven Rostedt 17315f9b6cedSSteven Rostedt run_command "git bisect log" or 17325f9b6cedSSteven Rostedt dodie "could not capture git bisect log"; 17335f9b6cedSSteven Rostedt 17345f9b6cedSSteven Rostedt run_command "git bisect reset" or 17355f9b6cedSSteven Rostedt dodie "could not reset git bisect"; 17365f9b6cedSSteven Rostedt 17375f9b6cedSSteven Rostedt doprint "Bad commit was [$bisect_bad]\n"; 17385f9b6cedSSteven Rostedt 17390a05c769SSteven Rostedt success $i; 17400a05c769SSteven Rostedt} 17410a05c769SSteven Rostedt 17420a05c769SSteven Rostedtmy %config_ignore; 17430a05c769SSteven Rostedtmy %config_set; 17440a05c769SSteven Rostedt 17450a05c769SSteven Rostedtmy %config_list; 17460a05c769SSteven Rostedtmy %null_config; 17470a05c769SSteven Rostedt 17480a05c769SSteven Rostedtmy %dependency; 17490a05c769SSteven Rostedt 17504c4ab120SSteven Rostedtsub assign_configs { 17514c4ab120SSteven Rostedt my ($hash, $config) = @_; 17520a05c769SSteven Rostedt 17530a05c769SSteven Rostedt open (IN, $config) 17540a05c769SSteven Rostedt or dodie "Failed to read $config"; 17550a05c769SSteven Rostedt 17560a05c769SSteven Rostedt while (<IN>) { 17579bf71749SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 17584c4ab120SSteven Rostedt ${$hash}{$2} = $1; 17590a05c769SSteven Rostedt } 17600a05c769SSteven Rostedt } 17610a05c769SSteven Rostedt 17620a05c769SSteven Rostedt close(IN); 17630a05c769SSteven Rostedt} 17640a05c769SSteven Rostedt 17654c4ab120SSteven Rostedtsub process_config_ignore { 17664c4ab120SSteven Rostedt my ($config) = @_; 17674c4ab120SSteven Rostedt 17684c4ab120SSteven Rostedt assign_configs \%config_ignore, $config; 17694c4ab120SSteven Rostedt} 17704c4ab120SSteven Rostedt 17710a05c769SSteven Rostedtsub read_current_config { 17720a05c769SSteven Rostedt my ($config_ref) = @_; 17730a05c769SSteven Rostedt 17740a05c769SSteven Rostedt %{$config_ref} = (); 17750a05c769SSteven Rostedt undef %{$config_ref}; 17760a05c769SSteven Rostedt 17770a05c769SSteven Rostedt my @key = keys %{$config_ref}; 17780a05c769SSteven Rostedt if ($#key >= 0) { 17790a05c769SSteven Rostedt print "did not delete!\n"; 17800a05c769SSteven Rostedt exit; 17810a05c769SSteven Rostedt } 17820a05c769SSteven Rostedt open (IN, "$output_config"); 17830a05c769SSteven Rostedt 17840a05c769SSteven Rostedt while (<IN>) { 17850a05c769SSteven Rostedt if (/^(CONFIG\S+)=(.*)/) { 17860a05c769SSteven Rostedt ${$config_ref}{$1} = $2; 17870a05c769SSteven Rostedt } 17880a05c769SSteven Rostedt } 17890a05c769SSteven Rostedt close(IN); 17900a05c769SSteven Rostedt} 17910a05c769SSteven Rostedt 17920a05c769SSteven Rostedtsub get_dependencies { 17930a05c769SSteven Rostedt my ($config) = @_; 17940a05c769SSteven Rostedt 17950a05c769SSteven Rostedt my $arr = $dependency{$config}; 17960a05c769SSteven Rostedt if (!defined($arr)) { 17970a05c769SSteven Rostedt return (); 17980a05c769SSteven Rostedt } 17990a05c769SSteven Rostedt 18000a05c769SSteven Rostedt my @deps = @{$arr}; 18010a05c769SSteven Rostedt 18020a05c769SSteven Rostedt foreach my $dep (@{$arr}) { 18030a05c769SSteven Rostedt print "ADD DEP $dep\n"; 18040a05c769SSteven Rostedt @deps = (@deps, get_dependencies $dep); 18050a05c769SSteven Rostedt } 18060a05c769SSteven Rostedt 18070a05c769SSteven Rostedt return @deps; 18080a05c769SSteven Rostedt} 18090a05c769SSteven Rostedt 18100a05c769SSteven Rostedtsub create_config { 18110a05c769SSteven Rostedt my @configs = @_; 18120a05c769SSteven Rostedt 18130a05c769SSteven Rostedt open(OUT, ">$output_config") or dodie "Can not write to $output_config"; 18140a05c769SSteven Rostedt 18150a05c769SSteven Rostedt foreach my $config (@configs) { 18160a05c769SSteven Rostedt print OUT "$config_set{$config}\n"; 18170a05c769SSteven Rostedt my @deps = get_dependencies $config; 18180a05c769SSteven Rostedt foreach my $dep (@deps) { 18190a05c769SSteven Rostedt print OUT "$config_set{$dep}\n"; 18200a05c769SSteven Rostedt } 18210a05c769SSteven Rostedt } 18220a05c769SSteven Rostedt 18230a05c769SSteven Rostedt foreach my $config (keys %config_ignore) { 18240a05c769SSteven Rostedt print OUT "$config_ignore{$config}\n"; 18250a05c769SSteven Rostedt } 18260a05c769SSteven Rostedt close(OUT); 18270a05c769SSteven Rostedt 18280a05c769SSteven Rostedt# exit; 1829fcb3f16aSSteven Rostedt make_oldconfig; 18300a05c769SSteven Rostedt} 18310a05c769SSteven Rostedt 18320a05c769SSteven Rostedtsub compare_configs { 18330a05c769SSteven Rostedt my (%a, %b) = @_; 18340a05c769SSteven Rostedt 18350a05c769SSteven Rostedt foreach my $item (keys %a) { 18360a05c769SSteven Rostedt if (!defined($b{$item})) { 18370a05c769SSteven Rostedt print "diff $item\n"; 18380a05c769SSteven Rostedt return 1; 18390a05c769SSteven Rostedt } 18400a05c769SSteven Rostedt delete $b{$item}; 18410a05c769SSteven Rostedt } 18420a05c769SSteven Rostedt 18430a05c769SSteven Rostedt my @keys = keys %b; 18440a05c769SSteven Rostedt if ($#keys) { 18450a05c769SSteven Rostedt print "diff2 $keys[0]\n"; 18460a05c769SSteven Rostedt } 18470a05c769SSteven Rostedt return -1 if ($#keys >= 0); 18480a05c769SSteven Rostedt 18490a05c769SSteven Rostedt return 0; 18500a05c769SSteven Rostedt} 18510a05c769SSteven Rostedt 18520a05c769SSteven Rostedtsub run_config_bisect_test { 18530a05c769SSteven Rostedt my ($type) = @_; 18540a05c769SSteven Rostedt 18550a05c769SSteven Rostedt return run_bisect_test $type, "oldconfig"; 18560a05c769SSteven Rostedt} 18570a05c769SSteven Rostedt 18580a05c769SSteven Rostedtsub process_passed { 18590a05c769SSteven Rostedt my (%configs) = @_; 18600a05c769SSteven Rostedt 18610a05c769SSteven Rostedt doprint "These configs had no failure: (Enabling them for further compiles)\n"; 18620a05c769SSteven Rostedt # Passed! All these configs are part of a good compile. 18630a05c769SSteven Rostedt # Add them to the min options. 18640a05c769SSteven Rostedt foreach my $config (keys %configs) { 18650a05c769SSteven Rostedt if (defined($config_list{$config})) { 18660a05c769SSteven Rostedt doprint " removing $config\n"; 18670a05c769SSteven Rostedt $config_ignore{$config} = $config_list{$config}; 18680a05c769SSteven Rostedt delete $config_list{$config}; 18690a05c769SSteven Rostedt } 18700a05c769SSteven Rostedt } 1871f1a27850SSteven Rostedt doprint "config copied to $outputdir/config_good\n"; 1872f1a27850SSteven Rostedt run_command "cp -f $output_config $outputdir/config_good"; 18730a05c769SSteven Rostedt} 18740a05c769SSteven Rostedt 18750a05c769SSteven Rostedtsub process_failed { 18760a05c769SSteven Rostedt my ($config) = @_; 18770a05c769SSteven Rostedt 18780a05c769SSteven Rostedt doprint "\n\n***************************************\n"; 18790a05c769SSteven Rostedt doprint "Found bad config: $config\n"; 18800a05c769SSteven Rostedt doprint "***************************************\n\n"; 18810a05c769SSteven Rostedt} 18820a05c769SSteven Rostedt 18830a05c769SSteven Rostedtsub run_config_bisect { 18840a05c769SSteven Rostedt 18850a05c769SSteven Rostedt my @start_list = keys %config_list; 18860a05c769SSteven Rostedt 18870a05c769SSteven Rostedt if ($#start_list < 0) { 18880a05c769SSteven Rostedt doprint "No more configs to test!!!\n"; 18890a05c769SSteven Rostedt return -1; 18900a05c769SSteven Rostedt } 18910a05c769SSteven Rostedt 18920a05c769SSteven Rostedt doprint "***** RUN TEST ***\n"; 18930a05c769SSteven Rostedt my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"}; 18940a05c769SSteven Rostedt my $ret; 18950a05c769SSteven Rostedt my %current_config; 18960a05c769SSteven Rostedt 18970a05c769SSteven Rostedt my $count = $#start_list + 1; 18980a05c769SSteven Rostedt doprint " $count configs to test\n"; 18990a05c769SSteven Rostedt 19000a05c769SSteven Rostedt my $half = int($#start_list / 2); 19010a05c769SSteven Rostedt 19020a05c769SSteven Rostedt do { 19030a05c769SSteven Rostedt my @tophalf = @start_list[0 .. $half]; 19040a05c769SSteven Rostedt 19050a05c769SSteven Rostedt create_config @tophalf; 19060a05c769SSteven Rostedt read_current_config \%current_config; 19070a05c769SSteven Rostedt 19080a05c769SSteven Rostedt $count = $#tophalf + 1; 19090a05c769SSteven Rostedt doprint "Testing $count configs\n"; 19100a05c769SSteven Rostedt my $found = 0; 19110a05c769SSteven Rostedt # make sure we test something 19120a05c769SSteven Rostedt foreach my $config (@tophalf) { 19130a05c769SSteven Rostedt if (defined($current_config{$config})) { 19140a05c769SSteven Rostedt logit " $config\n"; 19150a05c769SSteven Rostedt $found = 1; 19160a05c769SSteven Rostedt } 19170a05c769SSteven Rostedt } 19180a05c769SSteven Rostedt if (!$found) { 19190a05c769SSteven Rostedt # try the other half 19200a05c769SSteven Rostedt doprint "Top half produced no set configs, trying bottom half\n"; 19214c8cc55bSSteven Rostedt @tophalf = @start_list[$half + 1 .. $#start_list]; 19220a05c769SSteven Rostedt create_config @tophalf; 19230a05c769SSteven Rostedt read_current_config \%current_config; 19240a05c769SSteven Rostedt foreach my $config (@tophalf) { 19250a05c769SSteven Rostedt if (defined($current_config{$config})) { 19260a05c769SSteven Rostedt logit " $config\n"; 19270a05c769SSteven Rostedt $found = 1; 19280a05c769SSteven Rostedt } 19290a05c769SSteven Rostedt } 19300a05c769SSteven Rostedt if (!$found) { 19310a05c769SSteven Rostedt doprint "Failed: Can't make new config with current configs\n"; 19320a05c769SSteven Rostedt foreach my $config (@start_list) { 19330a05c769SSteven Rostedt doprint " CONFIG: $config\n"; 19340a05c769SSteven Rostedt } 19350a05c769SSteven Rostedt return -1; 19360a05c769SSteven Rostedt } 19370a05c769SSteven Rostedt $count = $#tophalf + 1; 19380a05c769SSteven Rostedt doprint "Testing $count configs\n"; 19390a05c769SSteven Rostedt } 19400a05c769SSteven Rostedt 19410a05c769SSteven Rostedt $ret = run_config_bisect_test $type; 1942c960bb9fSSteven Rostedt if ($bisect_manual) { 1943c960bb9fSSteven Rostedt $ret = answer_bisect; 1944c960bb9fSSteven Rostedt } 19450a05c769SSteven Rostedt if ($ret) { 19460a05c769SSteven Rostedt process_passed %current_config; 19470a05c769SSteven Rostedt return 0; 19480a05c769SSteven Rostedt } 19490a05c769SSteven Rostedt 19500a05c769SSteven Rostedt doprint "This config had a failure.\n"; 19510a05c769SSteven Rostedt doprint "Removing these configs that were not set in this config:\n"; 1952f1a27850SSteven Rostedt doprint "config copied to $outputdir/config_bad\n"; 1953f1a27850SSteven Rostedt run_command "cp -f $output_config $outputdir/config_bad"; 19540a05c769SSteven Rostedt 19550a05c769SSteven Rostedt # A config exists in this group that was bad. 19560a05c769SSteven Rostedt foreach my $config (keys %config_list) { 19570a05c769SSteven Rostedt if (!defined($current_config{$config})) { 19580a05c769SSteven Rostedt doprint " removing $config\n"; 19590a05c769SSteven Rostedt delete $config_list{$config}; 19600a05c769SSteven Rostedt } 19610a05c769SSteven Rostedt } 19620a05c769SSteven Rostedt 19630a05c769SSteven Rostedt @start_list = @tophalf; 19640a05c769SSteven Rostedt 19650a05c769SSteven Rostedt if ($#start_list == 0) { 19660a05c769SSteven Rostedt process_failed $start_list[0]; 19670a05c769SSteven Rostedt return 1; 19680a05c769SSteven Rostedt } 19690a05c769SSteven Rostedt 19700a05c769SSteven Rostedt # remove half the configs we are looking at and see if 19710a05c769SSteven Rostedt # they are good. 19720a05c769SSteven Rostedt $half = int($#start_list / 2); 19734c8cc55bSSteven Rostedt } while ($#start_list > 0); 19740a05c769SSteven Rostedt 1975c960bb9fSSteven Rostedt # we found a single config, try it again unless we are running manually 1976c960bb9fSSteven Rostedt 1977c960bb9fSSteven Rostedt if ($bisect_manual) { 1978c960bb9fSSteven Rostedt process_failed $start_list[0]; 1979c960bb9fSSteven Rostedt return 1; 1980c960bb9fSSteven Rostedt } 1981c960bb9fSSteven Rostedt 19820a05c769SSteven Rostedt my @tophalf = @start_list[0 .. 0]; 19830a05c769SSteven Rostedt 19840a05c769SSteven Rostedt $ret = run_config_bisect_test $type; 19850a05c769SSteven Rostedt if ($ret) { 19860a05c769SSteven Rostedt process_passed %current_config; 19870a05c769SSteven Rostedt return 0; 19880a05c769SSteven Rostedt } 19890a05c769SSteven Rostedt 19900a05c769SSteven Rostedt process_failed $start_list[0]; 19910a05c769SSteven Rostedt return 1; 19920a05c769SSteven Rostedt} 19930a05c769SSteven Rostedt 19940a05c769SSteven Rostedtsub config_bisect { 19950a05c769SSteven Rostedt my ($i) = @_; 19960a05c769SSteven Rostedt 19970a05c769SSteven Rostedt my $start_config = $opt{"CONFIG_BISECT[$i]"}; 19980a05c769SSteven Rostedt 19990a05c769SSteven Rostedt my $tmpconfig = "$tmpdir/use_config"; 20000a05c769SSteven Rostedt 200130f75da5SSteven Rostedt if (defined($config_bisect_good)) { 200230f75da5SSteven Rostedt process_config_ignore $config_bisect_good; 200330f75da5SSteven Rostedt } 200430f75da5SSteven Rostedt 20050a05c769SSteven Rostedt # Make the file with the bad config and the min config 20060a05c769SSteven Rostedt if (defined($minconfig)) { 20070a05c769SSteven Rostedt # read the min config for things to ignore 20080a05c769SSteven Rostedt run_command "cp $minconfig $tmpconfig" or 20090a05c769SSteven Rostedt dodie "failed to copy $minconfig to $tmpconfig"; 20100a05c769SSteven Rostedt } else { 20110a05c769SSteven Rostedt unlink $tmpconfig; 20120a05c769SSteven Rostedt } 20130a05c769SSteven Rostedt 20140a05c769SSteven Rostedt if (-f $tmpconfig) { 2015fcb3f16aSSteven Rostedt load_force_config($tmpconfig); 20160a05c769SSteven Rostedt process_config_ignore $tmpconfig; 20170a05c769SSteven Rostedt } 20180a05c769SSteven Rostedt 20190a05c769SSteven Rostedt # now process the start config 20200a05c769SSteven Rostedt run_command "cp $start_config $output_config" or 20210a05c769SSteven Rostedt dodie "failed to copy $start_config to $output_config"; 20220a05c769SSteven Rostedt 20230a05c769SSteven Rostedt # read directly what we want to check 20240a05c769SSteven Rostedt my %config_check; 20250a05c769SSteven Rostedt open (IN, $output_config) 20260a05c769SSteven Rostedt or dodie "faied to open $output_config"; 20270a05c769SSteven Rostedt 20280a05c769SSteven Rostedt while (<IN>) { 20290a05c769SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 20300a05c769SSteven Rostedt $config_check{$2} = $1; 20310a05c769SSteven Rostedt } 20320a05c769SSteven Rostedt } 20330a05c769SSteven Rostedt close(IN); 20340a05c769SSteven Rostedt 2035250bae8bSSteven Rostedt # Now run oldconfig with the minconfig 2036fcb3f16aSSteven Rostedt make_oldconfig; 20370a05c769SSteven Rostedt 20380a05c769SSteven Rostedt # check to see what we lost (or gained) 20390a05c769SSteven Rostedt open (IN, $output_config) 20400a05c769SSteven Rostedt or dodie "Failed to read $start_config"; 20410a05c769SSteven Rostedt 20420a05c769SSteven Rostedt my %removed_configs; 20430a05c769SSteven Rostedt my %added_configs; 20440a05c769SSteven Rostedt 20450a05c769SSteven Rostedt while (<IN>) { 20460a05c769SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 20470a05c769SSteven Rostedt # save off all options 20480a05c769SSteven Rostedt $config_set{$2} = $1; 20490a05c769SSteven Rostedt if (defined($config_check{$2})) { 20500a05c769SSteven Rostedt if (defined($config_ignore{$2})) { 20510a05c769SSteven Rostedt $removed_configs{$2} = $1; 20520a05c769SSteven Rostedt } else { 20530a05c769SSteven Rostedt $config_list{$2} = $1; 20540a05c769SSteven Rostedt } 20550a05c769SSteven Rostedt } elsif (!defined($config_ignore{$2})) { 20560a05c769SSteven Rostedt $added_configs{$2} = $1; 20570a05c769SSteven Rostedt $config_list{$2} = $1; 20580a05c769SSteven Rostedt } 20590a05c769SSteven Rostedt } 20600a05c769SSteven Rostedt } 20610a05c769SSteven Rostedt close(IN); 20620a05c769SSteven Rostedt 20630a05c769SSteven Rostedt my @confs = keys %removed_configs; 20640a05c769SSteven Rostedt if ($#confs >= 0) { 20650a05c769SSteven Rostedt doprint "Configs overridden by default configs and removed from check:\n"; 20660a05c769SSteven Rostedt foreach my $config (@confs) { 20670a05c769SSteven Rostedt doprint " $config\n"; 20680a05c769SSteven Rostedt } 20690a05c769SSteven Rostedt } 20700a05c769SSteven Rostedt @confs = keys %added_configs; 20710a05c769SSteven Rostedt if ($#confs >= 0) { 20720a05c769SSteven Rostedt doprint "Configs appearing in make oldconfig and added:\n"; 20730a05c769SSteven Rostedt foreach my $config (@confs) { 20740a05c769SSteven Rostedt doprint " $config\n"; 20750a05c769SSteven Rostedt } 20760a05c769SSteven Rostedt } 20770a05c769SSteven Rostedt 20780a05c769SSteven Rostedt my %config_test; 20790a05c769SSteven Rostedt my $once = 0; 20800a05c769SSteven Rostedt 20810a05c769SSteven Rostedt # Sometimes kconfig does weird things. We must make sure 20820a05c769SSteven Rostedt # that the config we autocreate has everything we need 20830a05c769SSteven Rostedt # to test, otherwise we may miss testing configs, or 20840a05c769SSteven Rostedt # may not be able to create a new config. 20850a05c769SSteven Rostedt # Here we create a config with everything set. 20860a05c769SSteven Rostedt create_config (keys %config_list); 20870a05c769SSteven Rostedt read_current_config \%config_test; 20880a05c769SSteven Rostedt foreach my $config (keys %config_list) { 20890a05c769SSteven Rostedt if (!defined($config_test{$config})) { 20900a05c769SSteven Rostedt if (!$once) { 20910a05c769SSteven Rostedt $once = 1; 20920a05c769SSteven Rostedt doprint "Configs not produced by kconfig (will not be checked):\n"; 20930a05c769SSteven Rostedt } 20940a05c769SSteven Rostedt doprint " $config\n"; 20950a05c769SSteven Rostedt delete $config_list{$config}; 20960a05c769SSteven Rostedt } 20970a05c769SSteven Rostedt } 20980a05c769SSteven Rostedt my $ret; 20990a05c769SSteven Rostedt do { 21000a05c769SSteven Rostedt $ret = run_config_bisect; 21010a05c769SSteven Rostedt } while (!$ret); 21020a05c769SSteven Rostedt 21030a05c769SSteven Rostedt return $ret if ($ret < 0); 21045f9b6cedSSteven Rostedt 21055f9b6cedSSteven Rostedt success $i; 21065f9b6cedSSteven Rostedt} 21075f9b6cedSSteven Rostedt 210827d934b2SSteven Rostedtsub patchcheck_reboot { 210927d934b2SSteven Rostedt doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 21102728be41SAndrew Jones reboot $patchcheck_sleep_time; 211127d934b2SSteven Rostedt} 211227d934b2SSteven Rostedt 21136c5ee0beSSteven Rostedtsub patchcheck { 21146c5ee0beSSteven Rostedt my ($i) = @_; 21156c5ee0beSSteven Rostedt 21166c5ee0beSSteven Rostedt die "PATCHCHECK_START[$i] not defined\n" 21176c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_START[$i]"})); 21186c5ee0beSSteven Rostedt die "PATCHCHECK_TYPE[$i] not defined\n" 21196c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 21206c5ee0beSSteven Rostedt 21216c5ee0beSSteven Rostedt my $start = $opt{"PATCHCHECK_START[$i]"}; 21226c5ee0beSSteven Rostedt 21236c5ee0beSSteven Rostedt my $end = "HEAD"; 21246c5ee0beSSteven Rostedt if (defined($opt{"PATCHCHECK_END[$i]"})) { 21256c5ee0beSSteven Rostedt $end = $opt{"PATCHCHECK_END[$i]"}; 21266c5ee0beSSteven Rostedt } 21276c5ee0beSSteven Rostedt 2128a57419b3SSteven Rostedt # Get the true sha1's since we can use things like HEAD~3 2129a57419b3SSteven Rostedt $start = get_sha1($start); 2130a57419b3SSteven Rostedt $end = get_sha1($end); 2131a57419b3SSteven Rostedt 21326c5ee0beSSteven Rostedt my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 21336c5ee0beSSteven Rostedt 21346c5ee0beSSteven Rostedt # Can't have a test without having a test to run 21356c5ee0beSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 21366c5ee0beSSteven Rostedt $type = "boot"; 21376c5ee0beSSteven Rostedt } 21386c5ee0beSSteven Rostedt 21396c5ee0beSSteven Rostedt open (IN, "git log --pretty=oneline $end|") or 21406c5ee0beSSteven Rostedt dodie "could not get git list"; 21416c5ee0beSSteven Rostedt 21426c5ee0beSSteven Rostedt my @list; 21436c5ee0beSSteven Rostedt 21446c5ee0beSSteven Rostedt while (<IN>) { 21456c5ee0beSSteven Rostedt chomp; 21466c5ee0beSSteven Rostedt $list[$#list+1] = $_; 21476c5ee0beSSteven Rostedt last if (/^$start/); 21486c5ee0beSSteven Rostedt } 21496c5ee0beSSteven Rostedt close(IN); 21506c5ee0beSSteven Rostedt 21516c5ee0beSSteven Rostedt if ($list[$#list] !~ /^$start/) { 21522b7d9b21SSteven Rostedt fail "SHA1 $start not found"; 21536c5ee0beSSteven Rostedt } 21546c5ee0beSSteven Rostedt 21556c5ee0beSSteven Rostedt # go backwards in the list 21566c5ee0beSSteven Rostedt @list = reverse @list; 21576c5ee0beSSteven Rostedt 21586c5ee0beSSteven Rostedt my $save_clean = $noclean; 21591990207dSSteven Rostedt my %ignored_warnings; 21601990207dSSteven Rostedt 21611990207dSSteven Rostedt if (defined($ignore_warnings)) { 21621990207dSSteven Rostedt foreach my $sha1 (split /\s+/, $ignore_warnings) { 21631990207dSSteven Rostedt $ignored_warnings{$sha1} = 1; 21641990207dSSteven Rostedt } 21651990207dSSteven Rostedt } 21666c5ee0beSSteven Rostedt 21676c5ee0beSSteven Rostedt $in_patchcheck = 1; 21686c5ee0beSSteven Rostedt foreach my $item (@list) { 21696c5ee0beSSteven Rostedt my $sha1 = $item; 21706c5ee0beSSteven Rostedt $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 21716c5ee0beSSteven Rostedt 21726c5ee0beSSteven Rostedt doprint "\nProcessing commit $item\n\n"; 21736c5ee0beSSteven Rostedt 21746c5ee0beSSteven Rostedt run_command "git checkout $sha1" or 21756c5ee0beSSteven Rostedt die "Failed to checkout $sha1"; 21766c5ee0beSSteven Rostedt 21776c5ee0beSSteven Rostedt # only clean on the first and last patch 21786c5ee0beSSteven Rostedt if ($item eq $list[0] || 21796c5ee0beSSteven Rostedt $item eq $list[$#list]) { 21806c5ee0beSSteven Rostedt $noclean = $save_clean; 21816c5ee0beSSteven Rostedt } else { 21826c5ee0beSSteven Rostedt $noclean = 1; 21836c5ee0beSSteven Rostedt } 21846c5ee0beSSteven Rostedt 21856c5ee0beSSteven Rostedt if (defined($minconfig)) { 21862b7d9b21SSteven Rostedt build "useconfig:$minconfig" or return 0; 21876c5ee0beSSteven Rostedt } else { 21886c5ee0beSSteven Rostedt # ?? no config to use? 21892b7d9b21SSteven Rostedt build "oldconfig" or return 0; 21906c5ee0beSSteven Rostedt } 21916c5ee0beSSteven Rostedt 21921990207dSSteven Rostedt 21931990207dSSteven Rostedt if (!defined($ignored_warnings{$sha1})) { 21942b7d9b21SSteven Rostedt check_buildlog $sha1 or return 0; 21951990207dSSteven Rostedt } 21966c5ee0beSSteven Rostedt 21976c5ee0beSSteven Rostedt next if ($type eq "build"); 21986c5ee0beSSteven Rostedt 21997faafbd6SSteven Rostedt my $failed = 0; 22007faafbd6SSteven Rostedt 2201ddf607e5SSteven Rostedt start_monitor_and_boot or $failed = 1; 22027faafbd6SSteven Rostedt 22037faafbd6SSteven Rostedt if (!$failed && $type ne "boot"){ 22047faafbd6SSteven Rostedt do_run_test or $failed = 1; 22057faafbd6SSteven Rostedt } 22067faafbd6SSteven Rostedt end_monitor; 22077faafbd6SSteven Rostedt return 0 if ($failed); 22087faafbd6SSteven Rostedt 220927d934b2SSteven Rostedt patchcheck_reboot; 221027d934b2SSteven Rostedt 22116c5ee0beSSteven Rostedt } 22126c5ee0beSSteven Rostedt $in_patchcheck = 0; 22136c5ee0beSSteven Rostedt success $i; 22142b7d9b21SSteven Rostedt 22152b7d9b21SSteven Rostedt return 1; 22166c5ee0beSSteven Rostedt} 22176c5ee0beSSteven Rostedt 2218b9066f6cSSteven Rostedtmy %depends; 2219b9066f6cSSteven Rostedtmy $iflevel = 0; 2220b9066f6cSSteven Rostedtmy @ifdeps; 2221b9066f6cSSteven Rostedt 2222b9066f6cSSteven Rostedt# prevent recursion 2223b9066f6cSSteven Rostedtmy %read_kconfigs; 2224b9066f6cSSteven Rostedt 2225b9066f6cSSteven Rostedt# taken from streamline_config.pl 2226b9066f6cSSteven Rostedtsub read_kconfig { 2227b9066f6cSSteven Rostedt my ($kconfig) = @_; 2228b9066f6cSSteven Rostedt 2229b9066f6cSSteven Rostedt my $state = "NONE"; 2230b9066f6cSSteven Rostedt my $config; 2231b9066f6cSSteven Rostedt my @kconfigs; 2232b9066f6cSSteven Rostedt 2233b9066f6cSSteven Rostedt my $cont = 0; 2234b9066f6cSSteven Rostedt my $line; 2235b9066f6cSSteven Rostedt 2236b9066f6cSSteven Rostedt 2237b9066f6cSSteven Rostedt if (! -f $kconfig) { 2238b9066f6cSSteven Rostedt doprint "file $kconfig does not exist, skipping\n"; 2239b9066f6cSSteven Rostedt return; 2240b9066f6cSSteven Rostedt } 2241b9066f6cSSteven Rostedt 2242b9066f6cSSteven Rostedt open(KIN, "$kconfig") 2243b9066f6cSSteven Rostedt or die "Can't open $kconfig"; 2244b9066f6cSSteven Rostedt while (<KIN>) { 2245b9066f6cSSteven Rostedt chomp; 2246b9066f6cSSteven Rostedt 2247b9066f6cSSteven Rostedt # Make sure that lines ending with \ continue 2248b9066f6cSSteven Rostedt if ($cont) { 2249b9066f6cSSteven Rostedt $_ = $line . " " . $_; 2250b9066f6cSSteven Rostedt } 2251b9066f6cSSteven Rostedt 2252b9066f6cSSteven Rostedt if (s/\\$//) { 2253b9066f6cSSteven Rostedt $cont = 1; 2254b9066f6cSSteven Rostedt $line = $_; 2255b9066f6cSSteven Rostedt next; 2256b9066f6cSSteven Rostedt } 2257b9066f6cSSteven Rostedt 2258b9066f6cSSteven Rostedt $cont = 0; 2259b9066f6cSSteven Rostedt 2260b9066f6cSSteven Rostedt # collect any Kconfig sources 2261b9066f6cSSteven Rostedt if (/^source\s*"(.*)"/) { 2262b9066f6cSSteven Rostedt $kconfigs[$#kconfigs+1] = $1; 2263b9066f6cSSteven Rostedt } 2264b9066f6cSSteven Rostedt 2265b9066f6cSSteven Rostedt # configs found 2266b9066f6cSSteven Rostedt if (/^\s*(menu)?config\s+(\S+)\s*$/) { 2267b9066f6cSSteven Rostedt $state = "NEW"; 2268b9066f6cSSteven Rostedt $config = $2; 2269b9066f6cSSteven Rostedt 2270b9066f6cSSteven Rostedt for (my $i = 0; $i < $iflevel; $i++) { 2271b9066f6cSSteven Rostedt if ($i) { 2272b9066f6cSSteven Rostedt $depends{$config} .= " " . $ifdeps[$i]; 2273b9066f6cSSteven Rostedt } else { 2274b9066f6cSSteven Rostedt $depends{$config} = $ifdeps[$i]; 2275b9066f6cSSteven Rostedt } 2276b9066f6cSSteven Rostedt $state = "DEP"; 2277b9066f6cSSteven Rostedt } 2278b9066f6cSSteven Rostedt 2279b9066f6cSSteven Rostedt # collect the depends for the config 2280b9066f6cSSteven Rostedt } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { 2281b9066f6cSSteven Rostedt 2282b9066f6cSSteven Rostedt if (defined($depends{$1})) { 2283b9066f6cSSteven Rostedt $depends{$config} .= " " . $1; 2284b9066f6cSSteven Rostedt } else { 2285b9066f6cSSteven Rostedt $depends{$config} = $1; 2286b9066f6cSSteven Rostedt } 2287b9066f6cSSteven Rostedt 2288b9066f6cSSteven Rostedt # Get the configs that select this config 2289b9066f6cSSteven Rostedt } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { 2290b9066f6cSSteven Rostedt if (defined($depends{$1})) { 2291b9066f6cSSteven Rostedt $depends{$1} .= " " . $config; 2292b9066f6cSSteven Rostedt } else { 2293b9066f6cSSteven Rostedt $depends{$1} = $config; 2294b9066f6cSSteven Rostedt } 2295b9066f6cSSteven Rostedt 2296b9066f6cSSteven Rostedt # Check for if statements 2297b9066f6cSSteven Rostedt } elsif (/^if\s+(.*\S)\s*$/) { 2298b9066f6cSSteven Rostedt my $deps = $1; 2299b9066f6cSSteven Rostedt # remove beginning and ending non text 2300b9066f6cSSteven Rostedt $deps =~ s/^[^a-zA-Z0-9_]*//; 2301b9066f6cSSteven Rostedt $deps =~ s/[^a-zA-Z0-9_]*$//; 2302b9066f6cSSteven Rostedt 2303b9066f6cSSteven Rostedt my @deps = split /[^a-zA-Z0-9_]+/, $deps; 2304b9066f6cSSteven Rostedt 2305b9066f6cSSteven Rostedt $ifdeps[$iflevel++] = join ':', @deps; 2306b9066f6cSSteven Rostedt 2307b9066f6cSSteven Rostedt } elsif (/^endif/) { 2308b9066f6cSSteven Rostedt 2309b9066f6cSSteven Rostedt $iflevel-- if ($iflevel); 2310b9066f6cSSteven Rostedt 2311b9066f6cSSteven Rostedt # stop on "help" 2312b9066f6cSSteven Rostedt } elsif (/^\s*help\s*$/) { 2313b9066f6cSSteven Rostedt $state = "NONE"; 2314b9066f6cSSteven Rostedt } 2315b9066f6cSSteven Rostedt } 2316b9066f6cSSteven Rostedt close(KIN); 2317b9066f6cSSteven Rostedt 2318b9066f6cSSteven Rostedt # read in any configs that were found. 2319b9066f6cSSteven Rostedt foreach $kconfig (@kconfigs) { 2320b9066f6cSSteven Rostedt if (!defined($read_kconfigs{$kconfig})) { 2321b9066f6cSSteven Rostedt $read_kconfigs{$kconfig} = 1; 2322b9066f6cSSteven Rostedt read_kconfig("$builddir/$kconfig"); 2323b9066f6cSSteven Rostedt } 2324b9066f6cSSteven Rostedt } 2325b9066f6cSSteven Rostedt} 2326b9066f6cSSteven Rostedt 2327b9066f6cSSteven Rostedtsub read_depends { 2328b9066f6cSSteven Rostedt # find out which arch this is by the kconfig file 2329b9066f6cSSteven Rostedt open (IN, $output_config) 2330b9066f6cSSteven Rostedt or dodie "Failed to read $output_config"; 2331b9066f6cSSteven Rostedt my $arch; 2332b9066f6cSSteven Rostedt while (<IN>) { 2333b9066f6cSSteven Rostedt if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) { 2334b9066f6cSSteven Rostedt $arch = $1; 2335b9066f6cSSteven Rostedt last; 2336b9066f6cSSteven Rostedt } 2337b9066f6cSSteven Rostedt } 2338b9066f6cSSteven Rostedt close IN; 2339b9066f6cSSteven Rostedt 2340b9066f6cSSteven Rostedt if (!defined($arch)) { 2341b9066f6cSSteven Rostedt doprint "Could not find arch from config file\n"; 2342b9066f6cSSteven Rostedt doprint "no dependencies used\n"; 2343b9066f6cSSteven Rostedt return; 2344b9066f6cSSteven Rostedt } 2345b9066f6cSSteven Rostedt 2346b9066f6cSSteven Rostedt # arch is really the subarch, we need to know 2347b9066f6cSSteven Rostedt # what directory to look at. 2348b9066f6cSSteven Rostedt if ($arch eq "i386" || $arch eq "x86_64") { 2349b9066f6cSSteven Rostedt $arch = "x86"; 2350b9066f6cSSteven Rostedt } elsif ($arch =~ /^tile/) { 2351b9066f6cSSteven Rostedt $arch = "tile"; 2352b9066f6cSSteven Rostedt } 2353b9066f6cSSteven Rostedt 2354b9066f6cSSteven Rostedt my $kconfig = "$builddir/arch/$arch/Kconfig"; 2355b9066f6cSSteven Rostedt 2356b9066f6cSSteven Rostedt if (! -f $kconfig && $arch =~ /\d$/) { 2357b9066f6cSSteven Rostedt my $orig = $arch; 2358b9066f6cSSteven Rostedt # some subarchs have numbers, truncate them 2359b9066f6cSSteven Rostedt $arch =~ s/\d*$//; 2360b9066f6cSSteven Rostedt $kconfig = "$builddir/arch/$arch/Kconfig"; 2361b9066f6cSSteven Rostedt if (! -f $kconfig) { 2362b9066f6cSSteven Rostedt doprint "No idea what arch dir $orig is for\n"; 2363b9066f6cSSteven Rostedt doprint "no dependencies used\n"; 2364b9066f6cSSteven Rostedt return; 2365b9066f6cSSteven Rostedt } 2366b9066f6cSSteven Rostedt } 2367b9066f6cSSteven Rostedt 2368b9066f6cSSteven Rostedt read_kconfig($kconfig); 2369b9066f6cSSteven Rostedt} 2370b9066f6cSSteven Rostedt 23714c4ab120SSteven Rostedtsub read_config_list { 23724c4ab120SSteven Rostedt my ($config) = @_; 23734c4ab120SSteven Rostedt 23744c4ab120SSteven Rostedt open (IN, $config) 23754c4ab120SSteven Rostedt or dodie "Failed to read $config"; 23764c4ab120SSteven Rostedt 23774c4ab120SSteven Rostedt while (<IN>) { 23784c4ab120SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 23794c4ab120SSteven Rostedt if (!defined($config_ignore{$2})) { 23804c4ab120SSteven Rostedt $config_list{$2} = $1; 23814c4ab120SSteven Rostedt } 23824c4ab120SSteven Rostedt } 23834c4ab120SSteven Rostedt } 23844c4ab120SSteven Rostedt 23854c4ab120SSteven Rostedt close(IN); 23864c4ab120SSteven Rostedt} 23874c4ab120SSteven Rostedt 23884c4ab120SSteven Rostedtsub read_output_config { 23894c4ab120SSteven Rostedt my ($config) = @_; 23904c4ab120SSteven Rostedt 23914c4ab120SSteven Rostedt assign_configs \%config_ignore, $config; 23924c4ab120SSteven Rostedt} 23934c4ab120SSteven Rostedt 23944c4ab120SSteven Rostedtsub make_new_config { 23954c4ab120SSteven Rostedt my @configs = @_; 23964c4ab120SSteven Rostedt 23974c4ab120SSteven Rostedt open (OUT, ">$output_config") 23984c4ab120SSteven Rostedt or dodie "Failed to write $output_config"; 23994c4ab120SSteven Rostedt 24004c4ab120SSteven Rostedt foreach my $config (@configs) { 24014c4ab120SSteven Rostedt print OUT "$config\n"; 24024c4ab120SSteven Rostedt } 24034c4ab120SSteven Rostedt close OUT; 24044c4ab120SSteven Rostedt} 24054c4ab120SSteven Rostedt 2406b9066f6cSSteven Rostedtsub get_depends { 2407b9066f6cSSteven Rostedt my ($dep) = @_; 2408b9066f6cSSteven Rostedt 2409b9066f6cSSteven Rostedt my $kconfig = $dep; 2410b9066f6cSSteven Rostedt $kconfig =~ s/CONFIG_//; 2411b9066f6cSSteven Rostedt 2412b9066f6cSSteven Rostedt $dep = $depends{"$kconfig"}; 2413b9066f6cSSteven Rostedt 2414b9066f6cSSteven Rostedt # the dep string we have saves the dependencies as they 2415b9066f6cSSteven Rostedt # were found, including expressions like ! && ||. We 2416b9066f6cSSteven Rostedt # want to split this out into just an array of configs. 2417b9066f6cSSteven Rostedt 2418b9066f6cSSteven Rostedt my $valid = "A-Za-z_0-9"; 2419b9066f6cSSteven Rostedt 2420b9066f6cSSteven Rostedt my @configs; 2421b9066f6cSSteven Rostedt 2422b9066f6cSSteven Rostedt while ($dep =~ /[$valid]/) { 2423b9066f6cSSteven Rostedt 2424b9066f6cSSteven Rostedt if ($dep =~ /^[^$valid]*([$valid]+)/) { 2425b9066f6cSSteven Rostedt my $conf = "CONFIG_" . $1; 2426b9066f6cSSteven Rostedt 2427b9066f6cSSteven Rostedt $configs[$#configs + 1] = $conf; 2428b9066f6cSSteven Rostedt 2429b9066f6cSSteven Rostedt $dep =~ s/^[^$valid]*[$valid]+//; 2430b9066f6cSSteven Rostedt } else { 2431b9066f6cSSteven Rostedt die "this should never happen"; 2432b9066f6cSSteven Rostedt } 2433b9066f6cSSteven Rostedt } 2434b9066f6cSSteven Rostedt 2435b9066f6cSSteven Rostedt return @configs; 2436b9066f6cSSteven Rostedt} 2437b9066f6cSSteven Rostedt 2438b9066f6cSSteven Rostedtmy %min_configs; 2439b9066f6cSSteven Rostedtmy %keep_configs; 244043d1b651SSteven Rostedtmy %save_configs; 2441b9066f6cSSteven Rostedtmy %processed_configs; 2442b9066f6cSSteven Rostedtmy %nochange_config; 2443b9066f6cSSteven Rostedt 2444b9066f6cSSteven Rostedtsub test_this_config { 2445b9066f6cSSteven Rostedt my ($config) = @_; 2446b9066f6cSSteven Rostedt 2447b9066f6cSSteven Rostedt my $found; 2448b9066f6cSSteven Rostedt 2449b9066f6cSSteven Rostedt # if we already processed this config, skip it 2450b9066f6cSSteven Rostedt if (defined($processed_configs{$config})) { 2451b9066f6cSSteven Rostedt return undef; 2452b9066f6cSSteven Rostedt } 2453b9066f6cSSteven Rostedt $processed_configs{$config} = 1; 2454b9066f6cSSteven Rostedt 2455b9066f6cSSteven Rostedt # if this config failed during this round, skip it 2456b9066f6cSSteven Rostedt if (defined($nochange_config{$config})) { 2457b9066f6cSSteven Rostedt return undef; 2458b9066f6cSSteven Rostedt } 2459b9066f6cSSteven Rostedt 2460b9066f6cSSteven Rostedt my $kconfig = $config; 2461b9066f6cSSteven Rostedt $kconfig =~ s/CONFIG_//; 2462b9066f6cSSteven Rostedt 2463b9066f6cSSteven Rostedt # Test dependencies first 2464b9066f6cSSteven Rostedt if (defined($depends{"$kconfig"})) { 2465b9066f6cSSteven Rostedt my @parents = get_depends $config; 2466b9066f6cSSteven Rostedt foreach my $parent (@parents) { 2467b9066f6cSSteven Rostedt # if the parent is in the min config, check it first 2468b9066f6cSSteven Rostedt next if (!defined($min_configs{$parent})); 2469b9066f6cSSteven Rostedt $found = test_this_config($parent); 2470b9066f6cSSteven Rostedt if (defined($found)) { 2471b9066f6cSSteven Rostedt return $found; 2472b9066f6cSSteven Rostedt } 2473b9066f6cSSteven Rostedt } 2474b9066f6cSSteven Rostedt } 2475b9066f6cSSteven Rostedt 2476b9066f6cSSteven Rostedt # Remove this config from the list of configs 2477b9066f6cSSteven Rostedt # do a make oldnoconfig and then read the resulting 2478b9066f6cSSteven Rostedt # .config to make sure it is missing the config that 2479b9066f6cSSteven Rostedt # we had before 2480b9066f6cSSteven Rostedt my %configs = %min_configs; 2481b9066f6cSSteven Rostedt delete $configs{$config}; 2482b9066f6cSSteven Rostedt make_new_config ((values %configs), (values %keep_configs)); 2483b9066f6cSSteven Rostedt make_oldconfig; 2484b9066f6cSSteven Rostedt undef %configs; 2485b9066f6cSSteven Rostedt assign_configs \%configs, $output_config; 2486b9066f6cSSteven Rostedt 2487b9066f6cSSteven Rostedt return $config if (!defined($configs{$config})); 2488b9066f6cSSteven Rostedt 2489b9066f6cSSteven Rostedt doprint "disabling config $config did not change .config\n"; 2490b9066f6cSSteven Rostedt 2491b9066f6cSSteven Rostedt $nochange_config{$config} = 1; 2492b9066f6cSSteven Rostedt 2493b9066f6cSSteven Rostedt return undef; 2494b9066f6cSSteven Rostedt} 2495b9066f6cSSteven Rostedt 24964c4ab120SSteven Rostedtsub make_min_config { 24974c4ab120SSteven Rostedt my ($i) = @_; 24984c4ab120SSteven Rostedt 24994c4ab120SSteven Rostedt if (!defined($output_minconfig)) { 25004c4ab120SSteven Rostedt fail "OUTPUT_MIN_CONFIG not defined" and return; 25014c4ab120SSteven Rostedt } 250235ce5952SSteven Rostedt 250335ce5952SSteven Rostedt # If output_minconfig exists, and the start_minconfig 250435ce5952SSteven Rostedt # came from min_config, than ask if we should use 250535ce5952SSteven Rostedt # that instead. 250635ce5952SSteven Rostedt if (-f $output_minconfig && !$start_minconfig_defined) { 250735ce5952SSteven Rostedt print "$output_minconfig exists\n"; 250835ce5952SSteven Rostedt if (read_yn " Use it as minconfig?") { 250935ce5952SSteven Rostedt $start_minconfig = $output_minconfig; 251035ce5952SSteven Rostedt } 251135ce5952SSteven Rostedt } 251235ce5952SSteven Rostedt 25134c4ab120SSteven Rostedt if (!defined($start_minconfig)) { 25144c4ab120SSteven Rostedt fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; 25154c4ab120SSteven Rostedt } 25164c4ab120SSteven Rostedt 251735ce5952SSteven Rostedt my $temp_config = "$tmpdir/temp_config"; 251835ce5952SSteven Rostedt 25194c4ab120SSteven Rostedt # First things first. We build an allnoconfig to find 25204c4ab120SSteven Rostedt # out what the defaults are that we can't touch. 25214c4ab120SSteven Rostedt # Some are selections, but we really can't handle selections. 25224c4ab120SSteven Rostedt 25234c4ab120SSteven Rostedt my $save_minconfig = $minconfig; 25244c4ab120SSteven Rostedt undef $minconfig; 25254c4ab120SSteven Rostedt 25264c4ab120SSteven Rostedt run_command "$make allnoconfig" or return 0; 25274c4ab120SSteven Rostedt 2528b9066f6cSSteven Rostedt read_depends; 2529b9066f6cSSteven Rostedt 25304c4ab120SSteven Rostedt process_config_ignore $output_config; 2531b9066f6cSSteven Rostedt 253243d1b651SSteven Rostedt undef %save_configs; 2533b9066f6cSSteven Rostedt undef %min_configs; 25344c4ab120SSteven Rostedt 25354c4ab120SSteven Rostedt if (defined($ignore_config)) { 25364c4ab120SSteven Rostedt # make sure the file exists 25374c4ab120SSteven Rostedt `touch $ignore_config`; 253843d1b651SSteven Rostedt assign_configs \%save_configs, $ignore_config; 25394c4ab120SSteven Rostedt } 25404c4ab120SSteven Rostedt 254143d1b651SSteven Rostedt %keep_configs = %save_configs; 254243d1b651SSteven Rostedt 25434c4ab120SSteven Rostedt doprint "Load initial configs from $start_minconfig\n"; 25444c4ab120SSteven Rostedt 25454c4ab120SSteven Rostedt # Look at the current min configs, and save off all the 25464c4ab120SSteven Rostedt # ones that were set via the allnoconfig 25474c4ab120SSteven Rostedt assign_configs \%min_configs, $start_minconfig; 25484c4ab120SSteven Rostedt 25494c4ab120SSteven Rostedt my @config_keys = keys %min_configs; 25504c4ab120SSteven Rostedt 25514c4ab120SSteven Rostedt # Remove anything that was set by the make allnoconfig 25524c4ab120SSteven Rostedt # we shouldn't need them as they get set for us anyway. 25534c4ab120SSteven Rostedt foreach my $config (@config_keys) { 25544c4ab120SSteven Rostedt # Remove anything in the ignore_config 25554c4ab120SSteven Rostedt if (defined($keep_configs{$config})) { 25564c4ab120SSteven Rostedt my $file = $ignore_config; 25574c4ab120SSteven Rostedt $file =~ s,.*/(.*?)$,$1,; 25584c4ab120SSteven Rostedt doprint "$config set by $file ... ignored\n"; 25594c4ab120SSteven Rostedt delete $min_configs{$config}; 25604c4ab120SSteven Rostedt next; 25614c4ab120SSteven Rostedt } 25624c4ab120SSteven Rostedt # But make sure the settings are the same. If a min config 25634c4ab120SSteven Rostedt # sets a selection, we do not want to get rid of it if 25644c4ab120SSteven Rostedt # it is not the same as what we have. Just move it into 25654c4ab120SSteven Rostedt # the keep configs. 25664c4ab120SSteven Rostedt if (defined($config_ignore{$config})) { 25674c4ab120SSteven Rostedt if ($config_ignore{$config} ne $min_configs{$config}) { 25684c4ab120SSteven Rostedt doprint "$config is in allnoconfig as '$config_ignore{$config}'"; 25694c4ab120SSteven Rostedt doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n"; 25704c4ab120SSteven Rostedt $keep_configs{$config} = $min_configs{$config}; 25714c4ab120SSteven Rostedt } else { 25724c4ab120SSteven Rostedt doprint "$config set by allnoconfig ... ignored\n"; 25734c4ab120SSteven Rostedt } 25744c4ab120SSteven Rostedt delete $min_configs{$config}; 25754c4ab120SSteven Rostedt } 25764c4ab120SSteven Rostedt } 25774c4ab120SSteven Rostedt 25784c4ab120SSteven Rostedt my $done = 0; 2579b9066f6cSSteven Rostedt my $take_two = 0; 25804c4ab120SSteven Rostedt 25814c4ab120SSteven Rostedt while (!$done) { 25824c4ab120SSteven Rostedt 25834c4ab120SSteven Rostedt my $config; 25844c4ab120SSteven Rostedt my $found; 25854c4ab120SSteven Rostedt 25864c4ab120SSteven Rostedt # Now disable each config one by one and do a make oldconfig 25874c4ab120SSteven Rostedt # till we find a config that changes our list. 25884c4ab120SSteven Rostedt 25894c4ab120SSteven Rostedt # Put configs that did not modify the config at the end. 25904c4ab120SSteven Rostedt my @test_configs = keys %min_configs; 25914c4ab120SSteven Rostedt my $reset = 1; 25924c4ab120SSteven Rostedt for (my $i = 0; $i < $#test_configs; $i++) { 25934c4ab120SSteven Rostedt if (!defined($nochange_config{$test_configs[0]})) { 25944c4ab120SSteven Rostedt $reset = 0; 25954c4ab120SSteven Rostedt last; 25964c4ab120SSteven Rostedt } 25974c4ab120SSteven Rostedt # This config didn't change the .config last time. 25984c4ab120SSteven Rostedt # Place it at the end 25994c4ab120SSteven Rostedt my $config = shift @test_configs; 26004c4ab120SSteven Rostedt push @test_configs, $config; 26014c4ab120SSteven Rostedt } 26024c4ab120SSteven Rostedt 26034c4ab120SSteven Rostedt # if every test config has failed to modify the .config file 26044c4ab120SSteven Rostedt # in the past, then reset and start over. 26054c4ab120SSteven Rostedt if ($reset) { 26064c4ab120SSteven Rostedt undef %nochange_config; 26074c4ab120SSteven Rostedt } 26084c4ab120SSteven Rostedt 2609b9066f6cSSteven Rostedt undef %processed_configs; 2610b9066f6cSSteven Rostedt 26114c4ab120SSteven Rostedt foreach my $config (@test_configs) { 26124c4ab120SSteven Rostedt 2613b9066f6cSSteven Rostedt $found = test_this_config $config; 26144c4ab120SSteven Rostedt 2615b9066f6cSSteven Rostedt last if (defined($found)); 26164c4ab120SSteven Rostedt 26174c4ab120SSteven Rostedt # oh well, try another config 26184c4ab120SSteven Rostedt } 26194c4ab120SSteven Rostedt 26204c4ab120SSteven Rostedt if (!defined($found)) { 2621b9066f6cSSteven Rostedt # we could have failed due to the nochange_config hash 2622b9066f6cSSteven Rostedt # reset and try again 2623b9066f6cSSteven Rostedt if (!$take_two) { 2624b9066f6cSSteven Rostedt undef %nochange_config; 2625b9066f6cSSteven Rostedt $take_two = 1; 2626b9066f6cSSteven Rostedt next; 2627b9066f6cSSteven Rostedt } 26284c4ab120SSteven Rostedt doprint "No more configs found that we can disable\n"; 26294c4ab120SSteven Rostedt $done = 1; 26304c4ab120SSteven Rostedt last; 26314c4ab120SSteven Rostedt } 2632b9066f6cSSteven Rostedt $take_two = 0; 26334c4ab120SSteven Rostedt 26344c4ab120SSteven Rostedt $config = $found; 26354c4ab120SSteven Rostedt 26364c4ab120SSteven Rostedt doprint "Test with $config disabled\n"; 26374c4ab120SSteven Rostedt 26384c4ab120SSteven Rostedt # set in_bisect to keep build and monitor from dieing 26394c4ab120SSteven Rostedt $in_bisect = 1; 26404c4ab120SSteven Rostedt 26414c4ab120SSteven Rostedt my $failed = 0; 26424c4ab120SSteven Rostedt build "oldconfig"; 26434c4ab120SSteven Rostedt start_monitor_and_boot or $failed = 1; 26444c4ab120SSteven Rostedt end_monitor; 26454c4ab120SSteven Rostedt 26464c4ab120SSteven Rostedt $in_bisect = 0; 26474c4ab120SSteven Rostedt 26484c4ab120SSteven Rostedt if ($failed) { 2649b9066f6cSSteven Rostedt doprint "$min_configs{$config} is needed to boot the box... keeping\n"; 26504c4ab120SSteven Rostedt # this config is needed, add it to the ignore list. 26514c4ab120SSteven Rostedt $keep_configs{$config} = $min_configs{$config}; 265243d1b651SSteven Rostedt $save_configs{$config} = $min_configs{$config}; 26534c4ab120SSteven Rostedt delete $min_configs{$config}; 265435ce5952SSteven Rostedt 265535ce5952SSteven Rostedt # update new ignore configs 265635ce5952SSteven Rostedt if (defined($ignore_config)) { 265735ce5952SSteven Rostedt open (OUT, ">$temp_config") 265835ce5952SSteven Rostedt or die "Can't write to $temp_config"; 265943d1b651SSteven Rostedt foreach my $config (keys %save_configs) { 266043d1b651SSteven Rostedt print OUT "$save_configs{$config}\n"; 266135ce5952SSteven Rostedt } 266235ce5952SSteven Rostedt close OUT; 266335ce5952SSteven Rostedt run_command "mv $temp_config $ignore_config" or 266435ce5952SSteven Rostedt dodie "failed to copy update to $ignore_config"; 266535ce5952SSteven Rostedt } 266635ce5952SSteven Rostedt 26674c4ab120SSteven Rostedt } else { 26684c4ab120SSteven Rostedt # We booted without this config, remove it from the minconfigs. 26694c4ab120SSteven Rostedt doprint "$config is not needed, disabling\n"; 26704c4ab120SSteven Rostedt 26714c4ab120SSteven Rostedt delete $min_configs{$config}; 26724c4ab120SSteven Rostedt 26734c4ab120SSteven Rostedt # Also disable anything that is not enabled in this config 26744c4ab120SSteven Rostedt my %configs; 26754c4ab120SSteven Rostedt assign_configs \%configs, $output_config; 26764c4ab120SSteven Rostedt my @config_keys = keys %min_configs; 26774c4ab120SSteven Rostedt foreach my $config (@config_keys) { 26784c4ab120SSteven Rostedt if (!defined($configs{$config})) { 26794c4ab120SSteven Rostedt doprint "$config is not set, disabling\n"; 26804c4ab120SSteven Rostedt delete $min_configs{$config}; 26814c4ab120SSteven Rostedt } 26824c4ab120SSteven Rostedt } 26834c4ab120SSteven Rostedt 26844c4ab120SSteven Rostedt # Save off all the current mandidory configs 268535ce5952SSteven Rostedt open (OUT, ">$temp_config") 268635ce5952SSteven Rostedt or die "Can't write to $temp_config"; 26874c4ab120SSteven Rostedt foreach my $config (keys %keep_configs) { 26884c4ab120SSteven Rostedt print OUT "$keep_configs{$config}\n"; 26894c4ab120SSteven Rostedt } 26904c4ab120SSteven Rostedt foreach my $config (keys %min_configs) { 26914c4ab120SSteven Rostedt print OUT "$min_configs{$config}\n"; 26924c4ab120SSteven Rostedt } 26934c4ab120SSteven Rostedt close OUT; 269435ce5952SSteven Rostedt 269535ce5952SSteven Rostedt run_command "mv $temp_config $output_minconfig" or 269635ce5952SSteven Rostedt dodie "failed to copy update to $output_minconfig"; 26974c4ab120SSteven Rostedt } 26984c4ab120SSteven Rostedt 26994c4ab120SSteven Rostedt doprint "Reboot and wait $sleep_time seconds\n"; 27002728be41SAndrew Jones reboot $sleep_time; 27014c4ab120SSteven Rostedt } 27024c4ab120SSteven Rostedt 27034c4ab120SSteven Rostedt success $i; 27044c4ab120SSteven Rostedt return 1; 27054c4ab120SSteven Rostedt} 27064c4ab120SSteven Rostedt 27078d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 27082545eb61SSteven Rostedt 27098d1491baSSteven Rostedtif ($#ARGV == 0) { 27108d1491baSSteven Rostedt $ktest_config = $ARGV[0]; 27118d1491baSSteven Rostedt if (! -f $ktest_config) { 27128d1491baSSteven Rostedt print "$ktest_config does not exist.\n"; 271335ce5952SSteven Rostedt if (!read_yn "Create it?") { 27148d1491baSSteven Rostedt exit 0; 27158d1491baSSteven Rostedt } 27168d1491baSSteven Rostedt } 27178d1491baSSteven Rostedt} else { 27188d1491baSSteven Rostedt $ktest_config = "ktest.conf"; 27198d1491baSSteven Rostedt} 27208d1491baSSteven Rostedt 27218d1491baSSteven Rostedtif (! -f $ktest_config) { 27228d1491baSSteven Rostedt open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 27238d1491baSSteven Rostedt print OUT << "EOF" 27248d1491baSSteven Rostedt# Generated by ktest.pl 27258d1491baSSteven Rostedt# 27268d1491baSSteven Rostedt# Define each test with TEST_START 27278d1491baSSteven Rostedt# The config options below it will override the defaults 27288d1491baSSteven RostedtTEST_START 27298d1491baSSteven Rostedt 27308d1491baSSteven RostedtDEFAULTS 27318d1491baSSteven RostedtEOF 27328d1491baSSteven Rostedt; 27338d1491baSSteven Rostedt close(OUT); 27348d1491baSSteven Rostedt} 27358d1491baSSteven Rostedtread_config $ktest_config; 27368d1491baSSteven Rostedt 273723715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) { 273823715c3cSSteven Rostedt $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1); 273923715c3cSSteven Rostedt} 274023715c3cSSteven Rostedt 27418d1491baSSteven Rostedt# Append any configs entered in manually to the config file. 27428d1491baSSteven Rostedtmy @new_configs = keys %entered_configs; 27438d1491baSSteven Rostedtif ($#new_configs >= 0) { 27448d1491baSSteven Rostedt print "\nAppending entered in configs to $ktest_config\n"; 27458d1491baSSteven Rostedt open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 27468d1491baSSteven Rostedt foreach my $config (@new_configs) { 27478d1491baSSteven Rostedt print OUT "$config = $entered_configs{$config}\n"; 27488d1491baSSteven Rostedt $opt{$config} = $entered_configs{$config}; 27498d1491baSSteven Rostedt } 27508d1491baSSteven Rostedt} 27512545eb61SSteven Rostedt 27522b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 27532b7d9b21SSteven Rostedt unlink $opt{"LOG_FILE"}; 27542b7d9b21SSteven Rostedt} 27552545eb61SSteven Rostedt 27562b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 27572b7d9b21SSteven Rostedt 2758a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 2759a57419b3SSteven Rostedt 2760a57419b3SSteven Rostedt if (!$i) { 2761a57419b3SSteven Rostedt doprint "DEFAULT OPTIONS:\n"; 2762a57419b3SSteven Rostedt } else { 2763a57419b3SSteven Rostedt doprint "\nTEST $i OPTIONS"; 2764a57419b3SSteven Rostedt if (defined($repeat_tests{$i})) { 2765a57419b3SSteven Rostedt $repeat = $repeat_tests{$i}; 2766a57419b3SSteven Rostedt doprint " ITERATE $repeat"; 2767a57419b3SSteven Rostedt } 2768a57419b3SSteven Rostedt doprint "\n"; 2769a57419b3SSteven Rostedt } 2770a57419b3SSteven Rostedt 27712b7d9b21SSteven Rostedt foreach my $option (sort keys %opt) { 2772a57419b3SSteven Rostedt 2773a57419b3SSteven Rostedt if ($option =~ /\[(\d+)\]$/) { 2774a57419b3SSteven Rostedt next if ($i != $1); 2775a57419b3SSteven Rostedt } else { 2776a57419b3SSteven Rostedt next if ($i); 2777a57419b3SSteven Rostedt } 2778a57419b3SSteven Rostedt 27792b7d9b21SSteven Rostedt doprint "$option = $opt{$option}\n"; 27802b7d9b21SSteven Rostedt } 2781a57419b3SSteven Rostedt} 27822545eb61SSteven Rostedt 27832a62512bSSteven Rostedtsub __set_test_option { 27845a391fbfSSteven Rostedt my ($name, $i) = @_; 27855a391fbfSSteven Rostedt 27865a391fbfSSteven Rostedt my $option = "$name\[$i\]"; 27875a391fbfSSteven Rostedt 27885a391fbfSSteven Rostedt if (defined($opt{$option})) { 27895a391fbfSSteven Rostedt return $opt{$option}; 27905a391fbfSSteven Rostedt } 27915a391fbfSSteven Rostedt 2792a57419b3SSteven Rostedt foreach my $test (keys %repeat_tests) { 2793a57419b3SSteven Rostedt if ($i >= $test && 2794a57419b3SSteven Rostedt $i < $test + $repeat_tests{$test}) { 2795a57419b3SSteven Rostedt $option = "$name\[$test\]"; 2796a57419b3SSteven Rostedt if (defined($opt{$option})) { 2797a57419b3SSteven Rostedt return $opt{$option}; 2798a57419b3SSteven Rostedt } 2799a57419b3SSteven Rostedt } 2800a57419b3SSteven Rostedt } 2801a57419b3SSteven Rostedt 28025a391fbfSSteven Rostedt if (defined($opt{$name})) { 28035a391fbfSSteven Rostedt return $opt{$name}; 28045a391fbfSSteven Rostedt } 28055a391fbfSSteven Rostedt 28065a391fbfSSteven Rostedt return undef; 28075a391fbfSSteven Rostedt} 28085a391fbfSSteven Rostedt 28092a62512bSSteven Rostedtsub set_test_option { 28102a62512bSSteven Rostedt my ($name, $i) = @_; 28112a62512bSSteven Rostedt 28122a62512bSSteven Rostedt my $option = __set_test_option($name, $i); 28132a62512bSSteven Rostedt return $option if (!defined($option)); 28142a62512bSSteven Rostedt 281523715c3cSSteven Rostedt return eval_option($option, $i); 28162a62512bSSteven Rostedt} 28172a62512bSSteven Rostedt 28182545eb61SSteven Rostedt# First we need to do is the builds 2819a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 28202545eb61SSteven Rostedt 2821*4ab1cce5SSteven Rostedt # Do not reboot on failing test options 2822*4ab1cce5SSteven Rostedt $no_reboot = 1; 2823*4ab1cce5SSteven Rostedt 2824576f627cSSteven Rostedt $iteration = $i; 2825576f627cSSteven Rostedt 2826a75fececSSteven Rostedt my $makecmd = set_test_option("MAKE_CMD", $i); 2827a75fececSSteven Rostedt 2828a75fececSSteven Rostedt $machine = set_test_option("MACHINE", $i); 2829e48c5293SSteven Rostedt $ssh_user = set_test_option("SSH_USER", $i); 2830a75fececSSteven Rostedt $tmpdir = set_test_option("TMP_DIR", $i); 2831a75fececSSteven Rostedt $outputdir = set_test_option("OUTPUT_DIR", $i); 2832a75fececSSteven Rostedt $builddir = set_test_option("BUILD_DIR", $i); 2833a75fececSSteven Rostedt $test_type = set_test_option("TEST_TYPE", $i); 2834a75fececSSteven Rostedt $build_type = set_test_option("BUILD_TYPE", $i); 2835a75fececSSteven Rostedt $build_options = set_test_option("BUILD_OPTIONS", $i); 28360bd6c1a3SSteven Rostedt $pre_build = set_test_option("PRE_BUILD", $i); 28370bd6c1a3SSteven Rostedt $post_build = set_test_option("POST_BUILD", $i); 28380bd6c1a3SSteven Rostedt $pre_build_die = set_test_option("PRE_BUILD_DIE", $i); 28390bd6c1a3SSteven Rostedt $post_build_die = set_test_option("POST_BUILD_DIE", $i); 2840a75fececSSteven Rostedt $power_cycle = set_test_option("POWER_CYCLE", $i); 2841e48c5293SSteven Rostedt $reboot = set_test_option("REBOOT", $i); 2842a75fececSSteven Rostedt $noclean = set_test_option("BUILD_NOCLEAN", $i); 2843a75fececSSteven Rostedt $minconfig = set_test_option("MIN_CONFIG", $i); 28444c4ab120SSteven Rostedt $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i); 28454c4ab120SSteven Rostedt $start_minconfig = set_test_option("START_MIN_CONFIG", $i); 28464c4ab120SSteven Rostedt $ignore_config = set_test_option("IGNORE_CONFIG", $i); 2847a75fececSSteven Rostedt $run_test = set_test_option("TEST", $i); 2848a75fececSSteven Rostedt $addconfig = set_test_option("ADD_CONFIG", $i); 2849a75fececSSteven Rostedt $reboot_type = set_test_option("REBOOT_TYPE", $i); 2850a75fececSSteven Rostedt $grub_menu = set_test_option("GRUB_MENU", $i); 28518b37ca8cSSteven Rostedt $post_install = set_test_option("POST_INSTALL", $i); 2852e0a8742eSSteven Rostedt $no_install = set_test_option("NO_INSTALL", $i); 2853a75fececSSteven Rostedt $reboot_script = set_test_option("REBOOT_SCRIPT", $i); 2854a75fececSSteven Rostedt $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); 2855a75fececSSteven Rostedt $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); 2856a75fececSSteven Rostedt $die_on_failure = set_test_option("DIE_ON_FAILURE", $i); 2857a75fececSSteven Rostedt $power_off = set_test_option("POWER_OFF", $i); 2858576f627cSSteven Rostedt $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i); 2859576f627cSSteven Rostedt $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i); 2860a75fececSSteven Rostedt $sleep_time = set_test_option("SLEEP_TIME", $i); 2861a75fececSSteven Rostedt $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 286227d934b2SSteven Rostedt $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i); 28631990207dSSteven Rostedt $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i); 2864c960bb9fSSteven Rostedt $bisect_manual = set_test_option("BISECT_MANUAL", $i); 2865c23dca7cSSteven Rostedt $bisect_skip = set_test_option("BISECT_SKIP", $i); 286630f75da5SSteven Rostedt $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i); 2867a75fececSSteven Rostedt $store_failures = set_test_option("STORE_FAILURES", $i); 28689064af52SSteven Rostedt $test_name = set_test_option("TEST_NAME", $i); 2869a75fececSSteven Rostedt $timeout = set_test_option("TIMEOUT", $i); 2870a75fececSSteven Rostedt $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 2871a75fececSSteven Rostedt $console = set_test_option("CONSOLE", $i); 2872f1a5b962SSteven Rostedt $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i); 2873a75fececSSteven Rostedt $success_line = set_test_option("SUCCESS_LINE", $i); 28742b803365SSteven Rostedt $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i); 28751c8a617aSSteven Rostedt $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); 28761c8a617aSSteven Rostedt $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); 28772d01b26aSSteven Rostedt $stop_test_after = set_test_option("STOP_TEST_AFTER", $i); 2878a75fececSSteven Rostedt $build_target = set_test_option("BUILD_TARGET", $i); 2879e48c5293SSteven Rostedt $ssh_exec = set_test_option("SSH_EXEC", $i); 2880e48c5293SSteven Rostedt $scp_to_target = set_test_option("SCP_TO_TARGET", $i); 2881a75fececSSteven Rostedt $target_image = set_test_option("TARGET_IMAGE", $i); 2882a75fececSSteven Rostedt $localversion = set_test_option("LOCALVERSION", $i); 2883a75fececSSteven Rostedt 288435ce5952SSteven Rostedt $start_minconfig_defined = 1; 288535ce5952SSteven Rostedt 28864c4ab120SSteven Rostedt if (!defined($start_minconfig)) { 288735ce5952SSteven Rostedt $start_minconfig_defined = 0; 28884c4ab120SSteven Rostedt $start_minconfig = $minconfig; 28894c4ab120SSteven Rostedt } 28904c4ab120SSteven Rostedt 2891a75fececSSteven Rostedt chdir $builddir || die "can't change directory to $builddir"; 2892a75fececSSteven Rostedt 2893a908a665SAndrew Jones foreach my $dir ($tmpdir, $outputdir) { 2894a908a665SAndrew Jones if (!-d $dir) { 2895a908a665SAndrew Jones mkpath($dir) or 2896a908a665SAndrew Jones die "can't create $dir"; 2897a908a665SAndrew Jones } 2898a75fececSSteven Rostedt } 2899a75fececSSteven Rostedt 2900e48c5293SSteven Rostedt $ENV{"SSH_USER"} = $ssh_user; 2901e48c5293SSteven Rostedt $ENV{"MACHINE"} = $machine; 2902e48c5293SSteven Rostedt 2903a75fececSSteven Rostedt $target = "$ssh_user\@$machine"; 2904a75fececSSteven Rostedt 2905a75fececSSteven Rostedt $buildlog = "$tmpdir/buildlog-$machine"; 2906a75fececSSteven Rostedt $dmesg = "$tmpdir/dmesg-$machine"; 2907a75fececSSteven Rostedt $make = "$makecmd O=$outputdir"; 290851ad1dd1SSteven Rostedt $output_config = "$outputdir/.config"; 2909a75fececSSteven Rostedt 2910a75fececSSteven Rostedt if ($reboot_type eq "grub") { 2911576f627cSSteven Rostedt dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 2912a75fececSSteven Rostedt } elsif (!defined($reboot_script)) { 2913576f627cSSteven Rostedt dodie "REBOOT_SCRIPT not defined" 2914a75fececSSteven Rostedt } 2915a75fececSSteven Rostedt 2916a75fececSSteven Rostedt my $run_type = $build_type; 2917a75fececSSteven Rostedt if ($test_type eq "patchcheck") { 2918a75fececSSteven Rostedt $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 2919a75fececSSteven Rostedt } elsif ($test_type eq "bisect") { 2920a75fececSSteven Rostedt $run_type = $opt{"BISECT_TYPE[$i]"}; 29210a05c769SSteven Rostedt } elsif ($test_type eq "config_bisect") { 29220a05c769SSteven Rostedt $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; 2923a75fececSSteven Rostedt } 2924a75fececSSteven Rostedt 29254c4ab120SSteven Rostedt if ($test_type eq "make_min_config") { 29264c4ab120SSteven Rostedt $run_type = ""; 29274c4ab120SSteven Rostedt } 29284c4ab120SSteven Rostedt 2929a75fececSSteven Rostedt # mistake in config file? 2930a75fececSSteven Rostedt if (!defined($run_type)) { 2931a75fececSSteven Rostedt $run_type = "ERROR"; 2932a75fececSSteven Rostedt } 29332545eb61SSteven Rostedt 2934e0a8742eSSteven Rostedt my $installme = ""; 2935e0a8742eSSteven Rostedt $installme = " no_install" if ($no_install); 2936e0a8742eSSteven Rostedt 29372545eb61SSteven Rostedt doprint "\n\n"; 2938e0a8742eSSteven Rostedt doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n"; 29397faafbd6SSteven Rostedt 29407faafbd6SSteven Rostedt unlink $dmesg; 29417faafbd6SSteven Rostedt unlink $buildlog; 29422545eb61SSteven Rostedt 2943250bae8bSSteven Rostedt if (defined($addconfig)) { 2944250bae8bSSteven Rostedt my $min = $minconfig; 29452b7d9b21SSteven Rostedt if (!defined($minconfig)) { 2946250bae8bSSteven Rostedt $min = ""; 2947250bae8bSSteven Rostedt } 2948250bae8bSSteven Rostedt run_command "cat $addconfig $min > $tmpdir/add_config" or 29492b7d9b21SSteven Rostedt dodie "Failed to create temp config"; 29509be2e6b5SSteven Rostedt $minconfig = "$tmpdir/add_config"; 29512b7d9b21SSteven Rostedt } 29522b7d9b21SSteven Rostedt 29536c5ee0beSSteven Rostedt my $checkout = $opt{"CHECKOUT[$i]"}; 29546c5ee0beSSteven Rostedt if (defined($checkout)) { 29556c5ee0beSSteven Rostedt run_command "git checkout $checkout" or 29566c5ee0beSSteven Rostedt die "failed to checkout $checkout"; 29576c5ee0beSSteven Rostedt } 29586c5ee0beSSteven Rostedt 2959*4ab1cce5SSteven Rostedt $no_reboot = 0; 2960*4ab1cce5SSteven Rostedt 2961*4ab1cce5SSteven Rostedt 2962a75fececSSteven Rostedt if ($test_type eq "bisect") { 29635f9b6cedSSteven Rostedt bisect $i; 29645f9b6cedSSteven Rostedt next; 29650a05c769SSteven Rostedt } elsif ($test_type eq "config_bisect") { 29660a05c769SSteven Rostedt config_bisect $i; 29670a05c769SSteven Rostedt next; 2968a75fececSSteven Rostedt } elsif ($test_type eq "patchcheck") { 29696c5ee0beSSteven Rostedt patchcheck $i; 29706c5ee0beSSteven Rostedt next; 29714c4ab120SSteven Rostedt } elsif ($test_type eq "make_min_config") { 29724c4ab120SSteven Rostedt make_min_config $i; 29734c4ab120SSteven Rostedt next; 29745f9b6cedSSteven Rostedt } 29755f9b6cedSSteven Rostedt 29767faafbd6SSteven Rostedt if ($build_type ne "nobuild") { 29777faafbd6SSteven Rostedt build $build_type or next; 29782545eb61SSteven Rostedt } 29792545eb61SSteven Rostedt 2980cd8e368fSSteven Rostedt if ($test_type eq "install") { 2981cd8e368fSSteven Rostedt get_version; 2982cd8e368fSSteven Rostedt install; 2983cd8e368fSSteven Rostedt success $i; 2984cd8e368fSSteven Rostedt next; 2985cd8e368fSSteven Rostedt } 2986cd8e368fSSteven Rostedt 2987a75fececSSteven Rostedt if ($test_type ne "build") { 29887faafbd6SSteven Rostedt my $failed = 0; 2989ddf607e5SSteven Rostedt start_monitor_and_boot or $failed = 1; 2990a75fececSSteven Rostedt 2991a75fececSSteven Rostedt if (!$failed && $test_type ne "boot" && defined($run_test)) { 29927faafbd6SSteven Rostedt do_run_test or $failed = 1; 29935a391fbfSSteven Rostedt } 29947faafbd6SSteven Rostedt end_monitor; 29957faafbd6SSteven Rostedt next if ($failed); 2996a75fececSSteven Rostedt } 29975a391fbfSSteven Rostedt 29985f9b6cedSSteven Rostedt success $i; 299975c3fda7SSteven Rostedt} 30002545eb61SSteven Rostedt 30015c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) { 300275c3fda7SSteven Rostedt halt; 3003576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { 300475c3fda7SSteven Rostedt reboot; 30055c42fc5bSSteven Rostedt} 300675c3fda7SSteven Rostedt 3007e48c5293SSteven Rostedtdoprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 3008e48c5293SSteven Rostedt 30092545eb61SSteven Rostedtexit 0; 3010