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; 212545eb61SSteven Rostedt 222545eb61SSteven Rostedt#default opts 234f43e0dcSSteven Rostedtmy %default = ( 244f43e0dcSSteven Rostedt "NUM_TESTS" => 1, 254f43e0dcSSteven Rostedt "TEST_TYPE" => "build", 264f43e0dcSSteven Rostedt "BUILD_TYPE" => "randconfig", 274f43e0dcSSteven Rostedt "MAKE_CMD" => "make", 284f43e0dcSSteven Rostedt "TIMEOUT" => 120, 294f43e0dcSSteven Rostedt "TMP_DIR" => "/tmp/ktest/\${MACHINE}", 304f43e0dcSSteven Rostedt "SLEEP_TIME" => 60, # sleep time between tests 314f43e0dcSSteven Rostedt "BUILD_NOCLEAN" => 0, 324f43e0dcSSteven Rostedt "REBOOT_ON_ERROR" => 0, 334f43e0dcSSteven Rostedt "POWEROFF_ON_ERROR" => 0, 344f43e0dcSSteven Rostedt "REBOOT_ON_SUCCESS" => 1, 354f43e0dcSSteven Rostedt "POWEROFF_ON_SUCCESS" => 0, 364f43e0dcSSteven Rostedt "BUILD_OPTIONS" => "", 374f43e0dcSSteven Rostedt "BISECT_SLEEP_TIME" => 60, # sleep time between bisects 384f43e0dcSSteven Rostedt "PATCHCHECK_SLEEP_TIME" => 60, # sleep time between patch checks 394f43e0dcSSteven Rostedt "CLEAR_LOG" => 0, 404f43e0dcSSteven Rostedt "BISECT_MANUAL" => 0, 414f43e0dcSSteven Rostedt "BISECT_SKIP" => 1, 42ccc513b6SSteven Rostedt "MIN_CONFIG_TYPE" => "boot", 434f43e0dcSSteven Rostedt "SUCCESS_LINE" => "login:", 444f43e0dcSSteven Rostedt "DETECT_TRIPLE_FAULT" => 1, 454f43e0dcSSteven Rostedt "NO_INSTALL" => 0, 464f43e0dcSSteven Rostedt "BOOTED_TIMEOUT" => 1, 474f43e0dcSSteven Rostedt "DIE_ON_FAILURE" => 1, 484f43e0dcSSteven Rostedt "SSH_EXEC" => "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND", 494f43e0dcSSteven Rostedt "SCP_TO_TARGET" => "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE", 5002ad2617SSteven Rostedt "SCP_TO_TARGET_INSTALL" => "\${SCP_TO_TARGET}", 514f43e0dcSSteven Rostedt "REBOOT" => "ssh \$SSH_USER\@\$MACHINE reboot", 524f43e0dcSSteven Rostedt "STOP_AFTER_SUCCESS" => 10, 534f43e0dcSSteven Rostedt "STOP_AFTER_FAILURE" => 60, 544f43e0dcSSteven Rostedt "STOP_TEST_AFTER" => 600, 55407b95b7SSteven Rostedt "MAX_MONITOR_WAIT" => 1800, 56*a15ba913SSteven Rostedt "GRUB_REBOOT" => "grub2-reboot", 57600bbf0aSSteven Rostedt 58600bbf0aSSteven Rostedt# required, and we will ask users if they don't have them but we keep the default 59600bbf0aSSteven Rostedt# value something that is common. 604f43e0dcSSteven Rostedt "REBOOT_TYPE" => "grub", 614f43e0dcSSteven Rostedt "LOCALVERSION" => "-test", 624f43e0dcSSteven Rostedt "SSH_USER" => "root", 634f43e0dcSSteven Rostedt "BUILD_TARGET" => "arch/x86/boot/bzImage", 644f43e0dcSSteven Rostedt "TARGET_IMAGE" => "/boot/vmlinuz-test", 659cc9e091SSteven Rostedt 669cc9e091SSteven Rostedt "LOG_FILE" => undef, 679cc9e091SSteven Rostedt "IGNORE_UNUSED" => 0, 684f43e0dcSSteven Rostedt); 692545eb61SSteven Rostedt 708d1491baSSteven Rostedtmy $ktest_config; 712545eb61SSteven Rostedtmy $version; 72683a3e64SSteven Rostedtmy $have_version = 0; 73a75fececSSteven Rostedtmy $machine; 74e48c5293SSteven Rostedtmy $ssh_user; 75a75fececSSteven Rostedtmy $tmpdir; 76a75fececSSteven Rostedtmy $builddir; 77a75fececSSteven Rostedtmy $outputdir; 7851ad1dd1SSteven Rostedtmy $output_config; 79a75fececSSteven Rostedtmy $test_type; 807faafbd6SSteven Rostedtmy $build_type; 81a75fececSSteven Rostedtmy $build_options; 82921ed4c7SSteven Rostedtmy $final_post_ktest; 83921ed4c7SSteven Rostedtmy $pre_ktest; 84921ed4c7SSteven Rostedtmy $post_ktest; 85921ed4c7SSteven Rostedtmy $pre_test; 86921ed4c7SSteven Rostedtmy $post_test; 870bd6c1a3SSteven Rostedtmy $pre_build; 880bd6c1a3SSteven Rostedtmy $post_build; 890bd6c1a3SSteven Rostedtmy $pre_build_die; 900bd6c1a3SSteven Rostedtmy $post_build_die; 91a75fececSSteven Rostedtmy $reboot_type; 92a75fececSSteven Rostedtmy $reboot_script; 93a75fececSSteven Rostedtmy $power_cycle; 94e48c5293SSteven Rostedtmy $reboot; 95a75fececSSteven Rostedtmy $reboot_on_error; 96bc7c5803SSteven Rostedtmy $switch_to_good; 97bc7c5803SSteven Rostedtmy $switch_to_test; 98a75fececSSteven Rostedtmy $poweroff_on_error; 99648a182cSSteven Rostedtmy $reboot_on_success; 100a75fececSSteven Rostedtmy $die_on_failure; 101576f627cSSteven Rostedtmy $powercycle_after_reboot; 102576f627cSSteven Rostedtmy $poweroff_after_halt; 103407b95b7SSteven Rostedtmy $max_monitor_wait; 104e48c5293SSteven Rostedtmy $ssh_exec; 105e48c5293SSteven Rostedtmy $scp_to_target; 10602ad2617SSteven Rostedtmy $scp_to_target_install; 107a75fececSSteven Rostedtmy $power_off; 108a75fececSSteven Rostedtmy $grub_menu; 109*a15ba913SSteven Rostedtmy $grub_file; 1102545eb61SSteven Rostedtmy $grub_number; 111*a15ba913SSteven Rostedtmy $grub_reboot; 1122545eb61SSteven Rostedtmy $target; 1132545eb61SSteven Rostedtmy $make; 114e5c2ec11SSteven Rostedtmy $pre_install; 1158b37ca8cSSteven Rostedtmy $post_install; 116e0a8742eSSteven Rostedtmy $no_install; 1175c42fc5bSSteven Rostedtmy $noclean; 1185f9b6cedSSteven Rostedtmy $minconfig; 1194c4ab120SSteven Rostedtmy $start_minconfig; 12035ce5952SSteven Rostedtmy $start_minconfig_defined; 1214c4ab120SSteven Rostedtmy $output_minconfig; 122ccc513b6SSteven Rostedtmy $minconfig_type; 12343de3316SSteven Rostedtmy $use_output_minconfig; 1244c4ab120SSteven Rostedtmy $ignore_config; 125be405f95SSteven Rostedtmy $ignore_errors; 1262b7d9b21SSteven Rostedtmy $addconfig; 1275f9b6cedSSteven Rostedtmy $in_bisect = 0; 128b5f4aea6SSteven Rostedtmy $bisect_bad_commit = ""; 129d6ce2a0bSSteven Rostedtmy $reverse_bisect; 130c960bb9fSSteven Rostedtmy $bisect_manual; 131c23dca7cSSteven Rostedtmy $bisect_skip; 13230f75da5SSteven Rostedtmy $config_bisect_good; 133c5dacb88SSteven Rostedtmy $bisect_ret_good; 134c5dacb88SSteven Rostedtmy $bisect_ret_bad; 135c5dacb88SSteven Rostedtmy $bisect_ret_skip; 136c5dacb88SSteven Rostedtmy $bisect_ret_abort; 137c5dacb88SSteven Rostedtmy $bisect_ret_default; 1386c5ee0beSSteven Rostedtmy $in_patchcheck = 0; 1395a391fbfSSteven Rostedtmy $run_test; 1406c5ee0beSSteven Rostedtmy $redirect; 1417faafbd6SSteven Rostedtmy $buildlog; 142a9dd5d63SRabin Vincentmy $testlog; 1437faafbd6SSteven Rostedtmy $dmesg; 1447faafbd6SSteven Rostedtmy $monitor_fp; 1457faafbd6SSteven Rostedtmy $monitor_pid; 1467faafbd6SSteven Rostedtmy $monitor_cnt = 0; 147a75fececSSteven Rostedtmy $sleep_time; 148a75fececSSteven Rostedtmy $bisect_sleep_time; 14927d934b2SSteven Rostedtmy $patchcheck_sleep_time; 1501990207dSSteven Rostedtmy $ignore_warnings; 151a75fececSSteven Rostedtmy $store_failures; 152de5b6e3bSRabin Vincentmy $store_successes; 1539064af52SSteven Rostedtmy $test_name; 154a75fececSSteven Rostedtmy $timeout; 155a75fececSSteven Rostedtmy $booted_timeout; 156f1a5b962SSteven Rostedtmy $detect_triplefault; 157a75fececSSteven Rostedtmy $console; 1582b803365SSteven Rostedtmy $reboot_success_line; 159a75fececSSteven Rostedtmy $success_line; 1601c8a617aSSteven Rostedtmy $stop_after_success; 1611c8a617aSSteven Rostedtmy $stop_after_failure; 1622d01b26aSSteven Rostedtmy $stop_test_after; 163a75fececSSteven Rostedtmy $build_target; 164a75fececSSteven Rostedtmy $target_image; 165b5f4aea6SSteven Rostedtmy $checkout; 166a75fececSSteven Rostedtmy $localversion; 167576f627cSSteven Rostedtmy $iteration = 0; 168e48c5293SSteven Rostedtmy $successes = 0; 1692545eb61SSteven Rostedt 170b5f4aea6SSteven Rostedtmy $bisect_good; 171b5f4aea6SSteven Rostedtmy $bisect_bad; 172b5f4aea6SSteven Rostedtmy $bisect_type; 173b5f4aea6SSteven Rostedtmy $bisect_start; 174b5f4aea6SSteven Rostedtmy $bisect_replay; 175b5f4aea6SSteven Rostedtmy $bisect_files; 176b5f4aea6SSteven Rostedtmy $bisect_reverse; 177b5f4aea6SSteven Rostedtmy $bisect_check; 178b5f4aea6SSteven Rostedt 179b5f4aea6SSteven Rostedtmy $config_bisect; 180b5f4aea6SSteven Rostedtmy $config_bisect_type; 181b0918612SSteven Rostedtmy $config_bisect_check; 182b5f4aea6SSteven Rostedt 183b5f4aea6SSteven Rostedtmy $patchcheck_type; 184b5f4aea6SSteven Rostedtmy $patchcheck_start; 185b5f4aea6SSteven Rostedtmy $patchcheck_end; 186b5f4aea6SSteven Rostedt 187165708b2SSteven Rostedt# set when a test is something other that just building or install 188bb8474b1SSteven Rostedt# which would require more options. 189bb8474b1SSteven Rostedtmy $buildonly = 1; 190bb8474b1SSteven Rostedt 191dbd3783bSSteven Rostedt# set when creating a new config 192dbd3783bSSteven Rostedtmy $newconfig = 0; 193dbd3783bSSteven Rostedt 1948d1491baSSteven Rostedtmy %entered_configs; 1958d1491baSSteven Rostedtmy %config_help; 19677d942ceSSteven Rostedtmy %variable; 197cf79fab6SSteven Rostedt 198cf79fab6SSteven Rostedt# force_config is the list of configs that we force enabled (or disabled) 199cf79fab6SSteven Rostedt# in a .config file. The MIN_CONFIG and ADD_CONFIG configs. 200fcb3f16aSSteven Rostedtmy %force_config; 2018d1491baSSteven Rostedt 2024ab1cce5SSteven Rostedt# do not force reboots on config problems 2034ab1cce5SSteven Rostedtmy $no_reboot = 1; 2044ab1cce5SSteven Rostedt 205759a3cc6SSteven Rostedt# reboot on success 206759a3cc6SSteven Rostedtmy $reboot_success = 0; 207759a3cc6SSteven Rostedt 2089cc9e091SSteven Rostedtmy %option_map = ( 2099cc9e091SSteven Rostedt "MACHINE" => \$machine, 2109cc9e091SSteven Rostedt "SSH_USER" => \$ssh_user, 2119cc9e091SSteven Rostedt "TMP_DIR" => \$tmpdir, 2129cc9e091SSteven Rostedt "OUTPUT_DIR" => \$outputdir, 2139cc9e091SSteven Rostedt "BUILD_DIR" => \$builddir, 2149cc9e091SSteven Rostedt "TEST_TYPE" => \$test_type, 215921ed4c7SSteven Rostedt "PRE_KTEST" => \$pre_ktest, 216921ed4c7SSteven Rostedt "POST_KTEST" => \$post_ktest, 217921ed4c7SSteven Rostedt "PRE_TEST" => \$pre_test, 218921ed4c7SSteven Rostedt "POST_TEST" => \$post_test, 2199cc9e091SSteven Rostedt "BUILD_TYPE" => \$build_type, 2209cc9e091SSteven Rostedt "BUILD_OPTIONS" => \$build_options, 2219cc9e091SSteven Rostedt "PRE_BUILD" => \$pre_build, 2229cc9e091SSteven Rostedt "POST_BUILD" => \$post_build, 2239cc9e091SSteven Rostedt "PRE_BUILD_DIE" => \$pre_build_die, 2249cc9e091SSteven Rostedt "POST_BUILD_DIE" => \$post_build_die, 2259cc9e091SSteven Rostedt "POWER_CYCLE" => \$power_cycle, 2269cc9e091SSteven Rostedt "REBOOT" => \$reboot, 2279cc9e091SSteven Rostedt "BUILD_NOCLEAN" => \$noclean, 2289cc9e091SSteven Rostedt "MIN_CONFIG" => \$minconfig, 2299cc9e091SSteven Rostedt "OUTPUT_MIN_CONFIG" => \$output_minconfig, 2309cc9e091SSteven Rostedt "START_MIN_CONFIG" => \$start_minconfig, 231ccc513b6SSteven Rostedt "MIN_CONFIG_TYPE" => \$minconfig_type, 23243de3316SSteven Rostedt "USE_OUTPUT_MIN_CONFIG" => \$use_output_minconfig, 2339cc9e091SSteven Rostedt "IGNORE_CONFIG" => \$ignore_config, 2349cc9e091SSteven Rostedt "TEST" => \$run_test, 2359cc9e091SSteven Rostedt "ADD_CONFIG" => \$addconfig, 2369cc9e091SSteven Rostedt "REBOOT_TYPE" => \$reboot_type, 2379cc9e091SSteven Rostedt "GRUB_MENU" => \$grub_menu, 238*a15ba913SSteven Rostedt "GRUB_FILE" => \$grub_file, 239*a15ba913SSteven Rostedt "GRUB_REBOOT" => \$grub_reboot, 240e5c2ec11SSteven Rostedt "PRE_INSTALL" => \$pre_install, 2419cc9e091SSteven Rostedt "POST_INSTALL" => \$post_install, 2429cc9e091SSteven Rostedt "NO_INSTALL" => \$no_install, 2439cc9e091SSteven Rostedt "REBOOT_SCRIPT" => \$reboot_script, 2449cc9e091SSteven Rostedt "REBOOT_ON_ERROR" => \$reboot_on_error, 2459cc9e091SSteven Rostedt "SWITCH_TO_GOOD" => \$switch_to_good, 2469cc9e091SSteven Rostedt "SWITCH_TO_TEST" => \$switch_to_test, 2479cc9e091SSteven Rostedt "POWEROFF_ON_ERROR" => \$poweroff_on_error, 248648a182cSSteven Rostedt "REBOOT_ON_SUCCESS" => \$reboot_on_success, 2499cc9e091SSteven Rostedt "DIE_ON_FAILURE" => \$die_on_failure, 2509cc9e091SSteven Rostedt "POWER_OFF" => \$power_off, 2519cc9e091SSteven Rostedt "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot, 2529cc9e091SSteven Rostedt "POWEROFF_AFTER_HALT" => \$poweroff_after_halt, 253407b95b7SSteven Rostedt "MAX_MONITOR_WAIT" => \$max_monitor_wait, 2549cc9e091SSteven Rostedt "SLEEP_TIME" => \$sleep_time, 2559cc9e091SSteven Rostedt "BISECT_SLEEP_TIME" => \$bisect_sleep_time, 2569cc9e091SSteven Rostedt "PATCHCHECK_SLEEP_TIME" => \$patchcheck_sleep_time, 2579cc9e091SSteven Rostedt "IGNORE_WARNINGS" => \$ignore_warnings, 258be405f95SSteven Rostedt "IGNORE_ERRORS" => \$ignore_errors, 2599cc9e091SSteven Rostedt "BISECT_MANUAL" => \$bisect_manual, 2609cc9e091SSteven Rostedt "BISECT_SKIP" => \$bisect_skip, 2619cc9e091SSteven Rostedt "CONFIG_BISECT_GOOD" => \$config_bisect_good, 2629cc9e091SSteven Rostedt "BISECT_RET_GOOD" => \$bisect_ret_good, 2639cc9e091SSteven Rostedt "BISECT_RET_BAD" => \$bisect_ret_bad, 2649cc9e091SSteven Rostedt "BISECT_RET_SKIP" => \$bisect_ret_skip, 2659cc9e091SSteven Rostedt "BISECT_RET_ABORT" => \$bisect_ret_abort, 2669cc9e091SSteven Rostedt "BISECT_RET_DEFAULT" => \$bisect_ret_default, 2679cc9e091SSteven Rostedt "STORE_FAILURES" => \$store_failures, 2689cc9e091SSteven Rostedt "STORE_SUCCESSES" => \$store_successes, 2699cc9e091SSteven Rostedt "TEST_NAME" => \$test_name, 2709cc9e091SSteven Rostedt "TIMEOUT" => \$timeout, 2719cc9e091SSteven Rostedt "BOOTED_TIMEOUT" => \$booted_timeout, 2729cc9e091SSteven Rostedt "CONSOLE" => \$console, 2739cc9e091SSteven Rostedt "DETECT_TRIPLE_FAULT" => \$detect_triplefault, 2749cc9e091SSteven Rostedt "SUCCESS_LINE" => \$success_line, 2759cc9e091SSteven Rostedt "REBOOT_SUCCESS_LINE" => \$reboot_success_line, 2769cc9e091SSteven Rostedt "STOP_AFTER_SUCCESS" => \$stop_after_success, 2779cc9e091SSteven Rostedt "STOP_AFTER_FAILURE" => \$stop_after_failure, 2789cc9e091SSteven Rostedt "STOP_TEST_AFTER" => \$stop_test_after, 2799cc9e091SSteven Rostedt "BUILD_TARGET" => \$build_target, 2809cc9e091SSteven Rostedt "SSH_EXEC" => \$ssh_exec, 2819cc9e091SSteven Rostedt "SCP_TO_TARGET" => \$scp_to_target, 28202ad2617SSteven Rostedt "SCP_TO_TARGET_INSTALL" => \$scp_to_target_install, 2839cc9e091SSteven Rostedt "CHECKOUT" => \$checkout, 2849cc9e091SSteven Rostedt "TARGET_IMAGE" => \$target_image, 2859cc9e091SSteven Rostedt "LOCALVERSION" => \$localversion, 2869cc9e091SSteven Rostedt 2879cc9e091SSteven Rostedt "BISECT_GOOD" => \$bisect_good, 2889cc9e091SSteven Rostedt "BISECT_BAD" => \$bisect_bad, 2899cc9e091SSteven Rostedt "BISECT_TYPE" => \$bisect_type, 2909cc9e091SSteven Rostedt "BISECT_START" => \$bisect_start, 2919cc9e091SSteven Rostedt "BISECT_REPLAY" => \$bisect_replay, 2929cc9e091SSteven Rostedt "BISECT_FILES" => \$bisect_files, 2939cc9e091SSteven Rostedt "BISECT_REVERSE" => \$bisect_reverse, 2949cc9e091SSteven Rostedt "BISECT_CHECK" => \$bisect_check, 2959cc9e091SSteven Rostedt 2969cc9e091SSteven Rostedt "CONFIG_BISECT" => \$config_bisect, 2979cc9e091SSteven Rostedt "CONFIG_BISECT_TYPE" => \$config_bisect_type, 298b0918612SSteven Rostedt "CONFIG_BISECT_CHECK" => \$config_bisect_check, 2999cc9e091SSteven Rostedt 3009cc9e091SSteven Rostedt "PATCHCHECK_TYPE" => \$patchcheck_type, 3019cc9e091SSteven Rostedt "PATCHCHECK_START" => \$patchcheck_start, 3029cc9e091SSteven Rostedt "PATCHCHECK_END" => \$patchcheck_end, 3039cc9e091SSteven Rostedt); 3049cc9e091SSteven Rostedt 3059cc9e091SSteven Rostedt# Options may be used by other options, record them. 3069cc9e091SSteven Rostedtmy %used_options; 3079cc9e091SSteven Rostedt 3087bf51073SSteven Rostedt# default variables that can be used 3097bf51073SSteven Rostedtchomp ($variable{"PWD"} = `pwd`); 3107bf51073SSteven Rostedt 3118d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF" 3128d1491baSSteven Rostedt The machine hostname that you will test. 313bb8474b1SSteven Rostedt For build only tests, it is still needed to differentiate log files. 3148d1491baSSteven RostedtEOF 3158d1491baSSteven Rostedt ; 3168d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF" 3178d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user 3188d1491baSSteven Rostedt (most likely root, since you need privileged operations) 3198d1491baSSteven RostedtEOF 3208d1491baSSteven Rostedt ; 3218d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF" 3228d1491baSSteven Rostedt The directory that contains the Linux source code (full path). 3230e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use 3240e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later. 3258d1491baSSteven RostedtEOF 3268d1491baSSteven Rostedt ; 3278d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF" 3288d1491baSSteven Rostedt The directory that the objects will be built (full path). 3298d1491baSSteven Rostedt (can not be same as BUILD_DIR) 3300e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use 3310e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later. 3328d1491baSSteven RostedtEOF 3338d1491baSSteven Rostedt ; 3348d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF" 3358d1491baSSteven Rostedt The location of the compiled file to copy to the target. 3368d1491baSSteven Rostedt (relative to OUTPUT_DIR) 3378d1491baSSteven RostedtEOF 3388d1491baSSteven Rostedt ; 339dbd3783bSSteven Rostedt$config_help{"BUILD_OPTIONS"} = << "EOF" 340dbd3783bSSteven Rostedt Options to add to \"make\" when building. 341dbd3783bSSteven Rostedt i.e. -j20 342dbd3783bSSteven RostedtEOF 343dbd3783bSSteven Rostedt ; 3448d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF" 3458d1491baSSteven Rostedt The place to put your image on the test machine. 3468d1491baSSteven RostedtEOF 3478d1491baSSteven Rostedt ; 3488d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF" 3498d1491baSSteven Rostedt A script or command to reboot the box. 3508d1491baSSteven Rostedt 3518d1491baSSteven Rostedt Here is a digital loggers power switch example 3528d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL' 3538d1491baSSteven Rostedt 3548d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host 3558d1491baSSteven Rostedt with the name "Guest". 3568d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest 3578d1491baSSteven RostedtEOF 3588d1491baSSteven Rostedt ; 3598d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF" 3608d1491baSSteven Rostedt The script or command that reads the console 3618d1491baSSteven Rostedt 3628d1491baSSteven Rostedt If you use ttywatch server, something like the following would work. 3638d1491baSSteven RostedtCONSOLE = nc -d localhost 3001 3648d1491baSSteven Rostedt 3658d1491baSSteven Rostedt For a virtual machine with guest name "Guest". 3668d1491baSSteven RostedtCONSOLE = virsh console Guest 3678d1491baSSteven RostedtEOF 3688d1491baSSteven Rostedt ; 3698d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF" 3708d1491baSSteven Rostedt Required version ending to differentiate the test 3718d1491baSSteven Rostedt from other linux builds on the system. 3728d1491baSSteven RostedtEOF 3738d1491baSSteven Rostedt ; 3748d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF" 3758d1491baSSteven Rostedt Way to reboot the box to the test kernel. 376*a15ba913SSteven Rostedt Only valid options so far are "grub", "grub2", and "script". 3778d1491baSSteven Rostedt 3788d1491baSSteven Rostedt If you specify grub, it will assume grub version 1 3798d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU 3808d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not 3818d1491baSSteven Rostedt your setup, then specify "script" and have a command or script 3828d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target. 3838d1491baSSteven Rostedt 3848d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually. 3858d1491baSSteven Rostedt The test will not modify that file. 386*a15ba913SSteven Rostedt 387*a15ba913SSteven Rostedt If you specify grub2, then you also need to specify both \$GRUB_MENU 388*a15ba913SSteven Rostedt and \$GRUB_FILE. 3898d1491baSSteven RostedtEOF 3908d1491baSSteven Rostedt ; 3918d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF" 3928d1491baSSteven Rostedt The grub title name for the test kernel to boot 393*a15ba913SSteven Rostedt (Only mandatory if REBOOT_TYPE = grub or grub2) 3948d1491baSSteven Rostedt 3958d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to 3968d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search 3978d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to 3988d1491baSSteven Rostedt reboot into. 3998d1491baSSteven Rostedt 4008d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has: 4018d1491baSSteven Rostedt title Test Kernel 4028d1491baSSteven Rostedt kernel vmlinuz-test 4038d1491baSSteven Rostedt GRUB_MENU = Test Kernel 404*a15ba913SSteven Rostedt 405*a15ba913SSteven Rostedt For grub2, a search of \$GRUB_FILE is performed for the lines 406*a15ba913SSteven Rostedt that begin with "menuentry". It will not detect submenus. The 407*a15ba913SSteven Rostedt menu must be a non-nested menu. Add the quotes used in the menu 408*a15ba913SSteven Rostedt to guarantee your selection, as the first menuentry with the content 409*a15ba913SSteven Rostedt of \$GRUB_MENU that is found will be used. 410*a15ba913SSteven RostedtEOF 411*a15ba913SSteven Rostedt ; 412*a15ba913SSteven Rostedt$config_help{"GRUB_FILE"} = << "EOF" 413*a15ba913SSteven Rostedt If grub2 is used, the full path for the grub.cfg file is placed 414*a15ba913SSteven Rostedt here. Use something like /boot/grub2/grub.cfg to search. 4158d1491baSSteven RostedtEOF 4168d1491baSSteven Rostedt ; 4178d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF" 4188d1491baSSteven Rostedt A script to reboot the target into the test kernel 4198d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script) 4208d1491baSSteven RostedtEOF 4218d1491baSSteven Rostedt ; 4228d1491baSSteven Rostedt 423dad98754SSteven Rostedtsub read_prompt { 424dad98754SSteven Rostedt my ($cancel, $prompt) = @_; 42535ce5952SSteven Rostedt 42635ce5952SSteven Rostedt my $ans; 42735ce5952SSteven Rostedt 42835ce5952SSteven Rostedt for (;;) { 429dad98754SSteven Rostedt if ($cancel) { 430dad98754SSteven Rostedt print "$prompt [y/n/C] "; 431dad98754SSteven Rostedt } else { 43235ce5952SSteven Rostedt print "$prompt [Y/n] "; 433dad98754SSteven Rostedt } 43435ce5952SSteven Rostedt $ans = <STDIN>; 43535ce5952SSteven Rostedt chomp $ans; 43635ce5952SSteven Rostedt if ($ans =~ /^\s*$/) { 437dad98754SSteven Rostedt if ($cancel) { 438dad98754SSteven Rostedt $ans = "c"; 439dad98754SSteven Rostedt } else { 44035ce5952SSteven Rostedt $ans = "y"; 44135ce5952SSteven Rostedt } 442dad98754SSteven Rostedt } 44335ce5952SSteven Rostedt last if ($ans =~ /^y$/i || $ans =~ /^n$/i); 444dad98754SSteven Rostedt if ($cancel) { 445dad98754SSteven Rostedt last if ($ans =~ /^c$/i); 446dad98754SSteven Rostedt print "Please answer either 'y', 'n' or 'c'.\n"; 447dad98754SSteven Rostedt } else { 44835ce5952SSteven Rostedt print "Please answer either 'y' or 'n'.\n"; 44935ce5952SSteven Rostedt } 450dad98754SSteven Rostedt } 451dad98754SSteven Rostedt if ($ans =~ /^c/i) { 452dad98754SSteven Rostedt exit; 453dad98754SSteven Rostedt } 45435ce5952SSteven Rostedt if ($ans !~ /^y$/i) { 45535ce5952SSteven Rostedt return 0; 45635ce5952SSteven Rostedt } 45735ce5952SSteven Rostedt return 1; 45835ce5952SSteven Rostedt} 4598d1491baSSteven Rostedt 460dad98754SSteven Rostedtsub read_yn { 461dad98754SSteven Rostedt my ($prompt) = @_; 462dad98754SSteven Rostedt 463dad98754SSteven Rostedt return read_prompt 0, $prompt; 464dad98754SSteven Rostedt} 465dad98754SSteven Rostedt 466dad98754SSteven Rostedtsub read_ync { 467dad98754SSteven Rostedt my ($prompt) = @_; 468dad98754SSteven Rostedt 469dad98754SSteven Rostedt return read_prompt 1, $prompt; 470dad98754SSteven Rostedt} 471dad98754SSteven Rostedt 4728d1491baSSteven Rostedtsub get_ktest_config { 4738d1491baSSteven Rostedt my ($config) = @_; 474815e2bd7SSteven Rostedt my $ans; 4758d1491baSSteven Rostedt 4768d1491baSSteven Rostedt return if (defined($opt{$config})); 4778d1491baSSteven Rostedt 4788d1491baSSteven Rostedt if (defined($config_help{$config})) { 4798d1491baSSteven Rostedt print "\n"; 4808d1491baSSteven Rostedt print $config_help{$config}; 4818d1491baSSteven Rostedt } 4828d1491baSSteven Rostedt 4838d1491baSSteven Rostedt for (;;) { 4848d1491baSSteven Rostedt print "$config = "; 485dbd3783bSSteven Rostedt if (defined($default{$config}) && length($default{$config})) { 4868d1491baSSteven Rostedt print "\[$default{$config}\] "; 4878d1491baSSteven Rostedt } 488815e2bd7SSteven Rostedt $ans = <STDIN>; 489815e2bd7SSteven Rostedt $ans =~ s/^\s*(.*\S)\s*$/$1/; 490815e2bd7SSteven Rostedt if ($ans =~ /^\s*$/) { 4918d1491baSSteven Rostedt if ($default{$config}) { 492815e2bd7SSteven Rostedt $ans = $default{$config}; 4938d1491baSSteven Rostedt } else { 4948d1491baSSteven Rostedt print "Your answer can not be blank\n"; 4958d1491baSSteven Rostedt next; 4968d1491baSSteven Rostedt } 4978d1491baSSteven Rostedt } 4980e7a22deSSteven Rostedt $entered_configs{$config} = ${ans}; 4998d1491baSSteven Rostedt last; 5008d1491baSSteven Rostedt } 5018d1491baSSteven Rostedt} 5028d1491baSSteven Rostedt 5038d1491baSSteven Rostedtsub get_ktest_configs { 5048d1491baSSteven Rostedt get_ktest_config("MACHINE"); 5058d1491baSSteven Rostedt get_ktest_config("BUILD_DIR"); 5068d1491baSSteven Rostedt get_ktest_config("OUTPUT_DIR"); 507bb8474b1SSteven Rostedt 508dbd3783bSSteven Rostedt if ($newconfig) { 509dbd3783bSSteven Rostedt get_ktest_config("BUILD_OPTIONS"); 510dbd3783bSSteven Rostedt } 511dbd3783bSSteven Rostedt 512bb8474b1SSteven Rostedt # options required for other than just building a kernel 513bb8474b1SSteven Rostedt if (!$buildonly) { 514165708b2SSteven Rostedt get_ktest_config("POWER_CYCLE"); 515165708b2SSteven Rostedt get_ktest_config("CONSOLE"); 516165708b2SSteven Rostedt } 517165708b2SSteven Rostedt 518165708b2SSteven Rostedt # options required for install and more 519165708b2SSteven Rostedt if ($buildonly != 1) { 520bb8474b1SSteven Rostedt get_ktest_config("SSH_USER"); 5218d1491baSSteven Rostedt get_ktest_config("BUILD_TARGET"); 5228d1491baSSteven Rostedt get_ktest_config("TARGET_IMAGE"); 523bb8474b1SSteven Rostedt } 524bb8474b1SSteven Rostedt 5258d1491baSSteven Rostedt get_ktest_config("LOCALVERSION"); 5268d1491baSSteven Rostedt 527bb8474b1SSteven Rostedt return if ($buildonly); 528bb8474b1SSteven Rostedt 5298d1491baSSteven Rostedt my $rtype = $opt{"REBOOT_TYPE"}; 5308d1491baSSteven Rostedt 5318d1491baSSteven Rostedt if (!defined($rtype)) { 5328d1491baSSteven Rostedt if (!defined($opt{"GRUB_MENU"})) { 5338d1491baSSteven Rostedt get_ktest_config("REBOOT_TYPE"); 5348d1491baSSteven Rostedt $rtype = $entered_configs{"REBOOT_TYPE"}; 5358d1491baSSteven Rostedt } else { 5368d1491baSSteven Rostedt $rtype = "grub"; 5378d1491baSSteven Rostedt } 5388d1491baSSteven Rostedt } 5398d1491baSSteven Rostedt 5408d1491baSSteven Rostedt if ($rtype eq "grub") { 5418d1491baSSteven Rostedt get_ktest_config("GRUB_MENU"); 5428d1491baSSteven Rostedt } 543*a15ba913SSteven Rostedt 544*a15ba913SSteven Rostedt if ($rtype eq "grub2") { 545*a15ba913SSteven Rostedt get_ktest_config("GRUB_MENU"); 546*a15ba913SSteven Rostedt get_ktest_config("GRUB_FILE"); 547*a15ba913SSteven Rostedt } 5488d1491baSSteven Rostedt} 5498d1491baSSteven Rostedt 55077d942ceSSteven Rostedtsub process_variables { 5518d735212SSteven Rostedt my ($value, $remove_undef) = @_; 55277d942ceSSteven Rostedt my $retval = ""; 55377d942ceSSteven Rostedt 55477d942ceSSteven Rostedt # We want to check for '\', and it is just easier 55577d942ceSSteven Rostedt # to check the previous characet of '$' and not need 55677d942ceSSteven Rostedt # to worry if '$' is the first character. By adding 55777d942ceSSteven Rostedt # a space to $value, we can just check [^\\]\$ and 55877d942ceSSteven Rostedt # it will still work. 55977d942ceSSteven Rostedt $value = " $value"; 56077d942ceSSteven Rostedt 56177d942ceSSteven Rostedt while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 56277d942ceSSteven Rostedt my $begin = $1; 56377d942ceSSteven Rostedt my $var = $2; 56477d942ceSSteven Rostedt my $end = $3; 56577d942ceSSteven Rostedt # append beginning of value to retval 56677d942ceSSteven Rostedt $retval = "$retval$begin"; 56777d942ceSSteven Rostedt if (defined($variable{$var})) { 56877d942ceSSteven Rostedt $retval = "$retval$variable{$var}"; 5698d735212SSteven Rostedt } elsif (defined($remove_undef) && $remove_undef) { 5708d735212SSteven Rostedt # for if statements, any variable that is not defined, 5718d735212SSteven Rostedt # we simple convert to 0 5728d735212SSteven Rostedt $retval = "${retval}0"; 57377d942ceSSteven Rostedt } else { 57477d942ceSSteven Rostedt # put back the origin piece. 57577d942ceSSteven Rostedt $retval = "$retval\$\{$var\}"; 5769cc9e091SSteven Rostedt # This could be an option that is used later, save 5779cc9e091SSteven Rostedt # it so we don't warn if this option is not one of 5789cc9e091SSteven Rostedt # ktests options. 5799cc9e091SSteven Rostedt $used_options{$var} = 1; 58077d942ceSSteven Rostedt } 58177d942ceSSteven Rostedt $value = $end; 58277d942ceSSteven Rostedt } 58377d942ceSSteven Rostedt $retval = "$retval$value"; 58477d942ceSSteven Rostedt 58577d942ceSSteven Rostedt # remove the space added in the beginning 58677d942ceSSteven Rostedt $retval =~ s/ //; 58777d942ceSSteven Rostedt 58877d942ceSSteven Rostedt return "$retval" 58977d942ceSSteven Rostedt} 59077d942ceSSteven Rostedt 591a57419b3SSteven Rostedtsub set_value { 5923d1cc414SSteven Rostedt my ($lvalue, $rvalue, $override, $overrides, $name) = @_; 5932545eb61SSteven Rostedt 594cad96669SSteven Rostedt my $prvalue = process_variables($rvalue); 595cad96669SSteven Rostedt 596cad96669SSteven Rostedt if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") { 597bb8474b1SSteven Rostedt # Note if a test is something other than build, then we 598bb8474b1SSteven Rostedt # will need other manditory options. 599cad96669SSteven Rostedt if ($prvalue ne "install") { 600bb8474b1SSteven Rostedt $buildonly = 0; 601165708b2SSteven Rostedt } else { 602165708b2SSteven Rostedt # install still limits some manditory options. 603165708b2SSteven Rostedt $buildonly = 2; 604165708b2SSteven Rostedt } 605bb8474b1SSteven Rostedt } 606bb8474b1SSteven Rostedt 607a75fececSSteven Rostedt if (defined($opt{$lvalue})) { 6083d1cc414SSteven Rostedt if (!$override || defined(${$overrides}{$lvalue})) { 6093d1cc414SSteven Rostedt my $extra = ""; 6103d1cc414SSteven Rostedt if ($override) { 6113d1cc414SSteven Rostedt $extra = "In the same override section!\n"; 6123d1cc414SSteven Rostedt } 6133d1cc414SSteven Rostedt die "$name: $.: Option $lvalue defined more than once!\n$extra"; 6143d1cc414SSteven Rostedt } 615cad96669SSteven Rostedt ${$overrides}{$lvalue} = $prvalue; 616a75fececSSteven Rostedt } 61721a9679fSSteven Rostedt if ($rvalue =~ /^\s*$/) { 61821a9679fSSteven Rostedt delete $opt{$lvalue}; 61921a9679fSSteven Rostedt } else { 620cad96669SSteven Rostedt $opt{$lvalue} = $prvalue; 62121a9679fSSteven Rostedt } 6222545eb61SSteven Rostedt} 623a57419b3SSteven Rostedt 62477d942ceSSteven Rostedtsub set_variable { 62577d942ceSSteven Rostedt my ($lvalue, $rvalue) = @_; 62677d942ceSSteven Rostedt 62777d942ceSSteven Rostedt if ($rvalue =~ /^\s*$/) { 62877d942ceSSteven Rostedt delete $variable{$lvalue}; 62977d942ceSSteven Rostedt } else { 63077d942ceSSteven Rostedt $rvalue = process_variables($rvalue); 63177d942ceSSteven Rostedt $variable{$lvalue} = $rvalue; 63277d942ceSSteven Rostedt } 63377d942ceSSteven Rostedt} 63477d942ceSSteven Rostedt 635ab7a3f52SSteven Rostedtsub process_compare { 636ab7a3f52SSteven Rostedt my ($lval, $cmp, $rval) = @_; 637ab7a3f52SSteven Rostedt 638ab7a3f52SSteven Rostedt # remove whitespace 639ab7a3f52SSteven Rostedt 640ab7a3f52SSteven Rostedt $lval =~ s/^\s*//; 641ab7a3f52SSteven Rostedt $lval =~ s/\s*$//; 642ab7a3f52SSteven Rostedt 643ab7a3f52SSteven Rostedt $rval =~ s/^\s*//; 644ab7a3f52SSteven Rostedt $rval =~ s/\s*$//; 645ab7a3f52SSteven Rostedt 646ab7a3f52SSteven Rostedt if ($cmp eq "==") { 647ab7a3f52SSteven Rostedt return $lval eq $rval; 648ab7a3f52SSteven Rostedt } elsif ($cmp eq "!=") { 649ab7a3f52SSteven Rostedt return $lval ne $rval; 6508fddbe9bSSteven Rostedt } elsif ($cmp eq "=~") { 6518fddbe9bSSteven Rostedt return $lval =~ m/$rval/; 6528fddbe9bSSteven Rostedt } elsif ($cmp eq "!~") { 6538fddbe9bSSteven Rostedt return $lval !~ m/$rval/; 654ab7a3f52SSteven Rostedt } 655ab7a3f52SSteven Rostedt 656ab7a3f52SSteven Rostedt my $statement = "$lval $cmp $rval"; 657ab7a3f52SSteven Rostedt my $ret = eval $statement; 658ab7a3f52SSteven Rostedt 659ab7a3f52SSteven Rostedt # $@ stores error of eval 660ab7a3f52SSteven Rostedt if ($@) { 661ab7a3f52SSteven Rostedt return -1; 662ab7a3f52SSteven Rostedt } 663ab7a3f52SSteven Rostedt 664ab7a3f52SSteven Rostedt return $ret; 665ab7a3f52SSteven Rostedt} 666ab7a3f52SSteven Rostedt 6679900b5dcSSteven Rostedtsub value_defined { 6689900b5dcSSteven Rostedt my ($val) = @_; 6699900b5dcSSteven Rostedt 6709900b5dcSSteven Rostedt return defined($variable{$2}) || 6719900b5dcSSteven Rostedt defined($opt{$2}); 6729900b5dcSSteven Rostedt} 6739900b5dcSSteven Rostedt 6748d735212SSteven Rostedtmy $d = 0; 6758d735212SSteven Rostedtsub process_expression { 6768d735212SSteven Rostedt my ($name, $val) = @_; 67745d73a5dSSteven Rostedt 6788d735212SSteven Rostedt my $c = $d++; 6798d735212SSteven Rostedt 6808d735212SSteven Rostedt while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) { 6818d735212SSteven Rostedt my $express = $1; 6828d735212SSteven Rostedt 6838d735212SSteven Rostedt if (process_expression($name, $express)) { 6848d735212SSteven Rostedt $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /; 6858d735212SSteven Rostedt } else { 6868d735212SSteven Rostedt $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /; 6878d735212SSteven Rostedt } 6888d735212SSteven Rostedt } 6898d735212SSteven Rostedt 6908d735212SSteven Rostedt $d--; 6918d735212SSteven Rostedt my $OR = "\\|\\|"; 6928d735212SSteven Rostedt my $AND = "\\&\\&"; 6938d735212SSteven Rostedt 6948d735212SSteven Rostedt while ($val =~ s/^(.*?)($OR|$AND)//) { 6958d735212SSteven Rostedt my $express = $1; 6968d735212SSteven Rostedt my $op = $2; 6978d735212SSteven Rostedt 6988d735212SSteven Rostedt if (process_expression($name, $express)) { 6998d735212SSteven Rostedt if ($op eq "||") { 7008d735212SSteven Rostedt return 1; 7018d735212SSteven Rostedt } 7028d735212SSteven Rostedt } else { 7038d735212SSteven Rostedt if ($op eq "&&") { 7048d735212SSteven Rostedt return 0; 7058d735212SSteven Rostedt } 7068d735212SSteven Rostedt } 7078d735212SSteven Rostedt } 70845d73a5dSSteven Rostedt 7098fddbe9bSSteven Rostedt if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) { 710ab7a3f52SSteven Rostedt my $ret = process_compare($1, $2, $3); 711ab7a3f52SSteven Rostedt if ($ret < 0) { 712ab7a3f52SSteven Rostedt die "$name: $.: Unable to process comparison\n"; 713ab7a3f52SSteven Rostedt } 714ab7a3f52SSteven Rostedt return $ret; 715ab7a3f52SSteven Rostedt } 716ab7a3f52SSteven Rostedt 7179900b5dcSSteven Rostedt if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) { 7189900b5dcSSteven Rostedt if (defined $1) { 7199900b5dcSSteven Rostedt return !value_defined($2); 7209900b5dcSSteven Rostedt } else { 7219900b5dcSSteven Rostedt return value_defined($2); 7229900b5dcSSteven Rostedt } 7239900b5dcSSteven Rostedt } 7249900b5dcSSteven Rostedt 72545d73a5dSSteven Rostedt if ($val =~ /^\s*0\s*$/) { 72645d73a5dSSteven Rostedt return 0; 72745d73a5dSSteven Rostedt } elsif ($val =~ /^\s*\d+\s*$/) { 72845d73a5dSSteven Rostedt return 1; 72945d73a5dSSteven Rostedt } 73045d73a5dSSteven Rostedt 7319900b5dcSSteven Rostedt die ("$name: $.: Undefined content $val in if statement\n"); 7328d735212SSteven Rostedt} 7338d735212SSteven Rostedt 7348d735212SSteven Rostedtsub process_if { 7358d735212SSteven Rostedt my ($name, $value) = @_; 7368d735212SSteven Rostedt 7378d735212SSteven Rostedt # Convert variables and replace undefined ones with 0 7388d735212SSteven Rostedt my $val = process_variables($value, 1); 7398d735212SSteven Rostedt my $ret = process_expression $name, $val; 7408d735212SSteven Rostedt 7418d735212SSteven Rostedt return $ret; 74245d73a5dSSteven Rostedt} 74345d73a5dSSteven Rostedt 7442ed3b161SSteven Rostedtsub __read_config { 7452ed3b161SSteven Rostedt my ($config, $current_test_num) = @_; 746a57419b3SSteven Rostedt 7472ed3b161SSteven Rostedt my $in; 7482ed3b161SSteven Rostedt open($in, $config) || die "can't read file $config"; 749a57419b3SSteven Rostedt 750a57419b3SSteven Rostedt my $name = $config; 751a57419b3SSteven Rostedt $name =~ s,.*/(.*),$1,; 752a57419b3SSteven Rostedt 7532ed3b161SSteven Rostedt my $test_num = $$current_test_num; 754a57419b3SSteven Rostedt my $default = 1; 755a57419b3SSteven Rostedt my $repeat = 1; 756a57419b3SSteven Rostedt my $num_tests_set = 0; 757a57419b3SSteven Rostedt my $skip = 0; 758a57419b3SSteven Rostedt my $rest; 759a9f84424SSteven Rostedt my $line; 7600df213caSSteven Rostedt my $test_case = 0; 76145d73a5dSSteven Rostedt my $if = 0; 76245d73a5dSSteven Rostedt my $if_set = 0; 7633d1cc414SSteven Rostedt my $override = 0; 7643d1cc414SSteven Rostedt 7653d1cc414SSteven Rostedt my %overrides; 766a57419b3SSteven Rostedt 7672ed3b161SSteven Rostedt while (<$in>) { 768a57419b3SSteven Rostedt 769a57419b3SSteven Rostedt # ignore blank lines and comments 770a57419b3SSteven Rostedt next if (/^\s*$/ || /\s*\#/); 771a57419b3SSteven Rostedt 7720050b6bbSSteven Rostedt if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) { 773a57419b3SSteven Rostedt 7740050b6bbSSteven Rostedt my $type = $1; 7750050b6bbSSteven Rostedt $rest = $2; 776a9f84424SSteven Rostedt $line = $2; 7770050b6bbSSteven Rostedt 7780050b6bbSSteven Rostedt my $old_test_num; 7790050b6bbSSteven Rostedt my $old_repeat; 7803d1cc414SSteven Rostedt $override = 0; 7810050b6bbSSteven Rostedt 7820050b6bbSSteven Rostedt if ($type eq "TEST_START") { 783a57419b3SSteven Rostedt 784a57419b3SSteven Rostedt if ($num_tests_set) { 785a57419b3SSteven Rostedt die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 786a57419b3SSteven Rostedt } 787a57419b3SSteven Rostedt 7880050b6bbSSteven Rostedt $old_test_num = $test_num; 7890050b6bbSSteven Rostedt $old_repeat = $repeat; 790a57419b3SSteven Rostedt 791a57419b3SSteven Rostedt $test_num += $repeat; 792a57419b3SSteven Rostedt $default = 0; 793a57419b3SSteven Rostedt $repeat = 1; 7940050b6bbSSteven Rostedt } else { 7950050b6bbSSteven Rostedt $default = 1; 7960050b6bbSSteven Rostedt } 797a57419b3SSteven Rostedt 798a9f84424SSteven Rostedt # If SKIP is anywhere in the line, the command will be skipped 799a9f84424SSteven Rostedt if ($rest =~ s/\s+SKIP\b//) { 800a57419b3SSteven Rostedt $skip = 1; 801a57419b3SSteven Rostedt } else { 8020df213caSSteven Rostedt $test_case = 1; 803a57419b3SSteven Rostedt $skip = 0; 804a57419b3SSteven Rostedt } 805a57419b3SSteven Rostedt 806a9f84424SSteven Rostedt if ($rest =~ s/\sELSE\b//) { 807a9f84424SSteven Rostedt if (!$if) { 808a9f84424SSteven Rostedt die "$name: $.: ELSE found with out matching IF section\n$_"; 809a57419b3SSteven Rostedt } 810a9f84424SSteven Rostedt $if = 0; 811a9f84424SSteven Rostedt 812a9f84424SSteven Rostedt if ($if_set) { 813a9f84424SSteven Rostedt $skip = 1; 814a9f84424SSteven Rostedt } else { 815a9f84424SSteven Rostedt $skip = 0; 8163d1cc414SSteven Rostedt } 8173d1cc414SSteven Rostedt } 818a57419b3SSteven Rostedt 819a9f84424SSteven Rostedt if ($rest =~ s/\sIF\s+(.*)//) { 82045d73a5dSSteven Rostedt if (process_if($name, $1)) { 82145d73a5dSSteven Rostedt $if_set = 1; 82245d73a5dSSteven Rostedt } else { 823a57419b3SSteven Rostedt $skip = 1; 824a57419b3SSteven Rostedt } 82545d73a5dSSteven Rostedt $if = 1; 82645d73a5dSSteven Rostedt } else { 82745d73a5dSSteven Rostedt $if = 0; 828a9f84424SSteven Rostedt $if_set = 0; 82945d73a5dSSteven Rostedt } 830a57419b3SSteven Rostedt 831a9f84424SSteven Rostedt if (!$skip) { 832a9f84424SSteven Rostedt if ($type eq "TEST_START") { 833a9f84424SSteven Rostedt if ($rest =~ s/\s+ITERATE\s+(\d+)//) { 834a9f84424SSteven Rostedt $repeat = $1; 835a9f84424SSteven Rostedt $repeat_tests{"$test_num"} = $repeat; 836a9f84424SSteven Rostedt } 837a9f84424SSteven Rostedt } elsif ($rest =~ s/\sOVERRIDE\b//) { 838a9f84424SSteven Rostedt # DEFAULT only 839a9f84424SSteven Rostedt $override = 1; 840a9f84424SSteven Rostedt # Clear previous overrides 841a9f84424SSteven Rostedt %overrides = (); 842a9f84424SSteven Rostedt } 843a9f84424SSteven Rostedt } 844a9f84424SSteven Rostedt 845a9f84424SSteven Rostedt if (!$skip && $rest !~ /^\s*$/) { 8460050b6bbSSteven Rostedt die "$name: $.: Gargbage found after $type\n$_"; 847a57419b3SSteven Rostedt } 848a57419b3SSteven Rostedt 8490050b6bbSSteven Rostedt if ($skip && $type eq "TEST_START") { 850a57419b3SSteven Rostedt $test_num = $old_test_num; 851e48c5293SSteven Rostedt $repeat = $old_repeat; 852a57419b3SSteven Rostedt } 853a57419b3SSteven Rostedt 854ab7a3f52SSteven Rostedt } elsif (/^\s*ELSE\b(.*)$/) { 85545d73a5dSSteven Rostedt if (!$if) { 85645d73a5dSSteven Rostedt die "$name: $.: ELSE found with out matching IF section\n$_"; 85745d73a5dSSteven Rostedt } 85845d73a5dSSteven Rostedt $rest = $1; 85945d73a5dSSteven Rostedt if ($if_set) { 86045d73a5dSSteven Rostedt $skip = 1; 861ab7a3f52SSteven Rostedt $rest = ""; 86245d73a5dSSteven Rostedt } else { 86345d73a5dSSteven Rostedt $skip = 0; 86445d73a5dSSteven Rostedt 865ab7a3f52SSteven Rostedt if ($rest =~ /\sIF\s+(.*)/) { 86645d73a5dSSteven Rostedt # May be a ELSE IF section. 86795f57838SSteven Rostedt if (process_if($name, $1)) { 86895f57838SSteven Rostedt $if_set = 1; 86995f57838SSteven Rostedt } else { 87045d73a5dSSteven Rostedt $skip = 1; 87145d73a5dSSteven Rostedt } 872ab7a3f52SSteven Rostedt $rest = ""; 87345d73a5dSSteven Rostedt } else { 87445d73a5dSSteven Rostedt $if = 0; 87545d73a5dSSteven Rostedt } 87645d73a5dSSteven Rostedt } 87745d73a5dSSteven Rostedt 878ab7a3f52SSteven Rostedt if ($rest !~ /^\s*$/) { 879ab7a3f52SSteven Rostedt die "$name: $.: Gargbage found after DEFAULTS\n$_"; 880ab7a3f52SSteven Rostedt } 881ab7a3f52SSteven Rostedt 8822ed3b161SSteven Rostedt } elsif (/^\s*INCLUDE\s+(\S+)/) { 8832ed3b161SSteven Rostedt 8842ed3b161SSteven Rostedt next if ($skip); 8852ed3b161SSteven Rostedt 8862ed3b161SSteven Rostedt if (!$default) { 8872ed3b161SSteven Rostedt die "$name: $.: INCLUDE can only be done in default sections\n$_"; 8882ed3b161SSteven Rostedt } 8892ed3b161SSteven Rostedt 8902ed3b161SSteven Rostedt my $file = process_variables($1); 8912ed3b161SSteven Rostedt 8922ed3b161SSteven Rostedt if ($file !~ m,^/,) { 8932ed3b161SSteven Rostedt # check the path of the config file first 8942ed3b161SSteven Rostedt if ($config =~ m,(.*)/,) { 8952ed3b161SSteven Rostedt if (-f "$1/$file") { 8962ed3b161SSteven Rostedt $file = "$1/$file"; 8972ed3b161SSteven Rostedt } 8982ed3b161SSteven Rostedt } 8992ed3b161SSteven Rostedt } 9002ed3b161SSteven Rostedt 9012ed3b161SSteven Rostedt if ( ! -r $file ) { 9022ed3b161SSteven Rostedt die "$name: $.: Can't read file $file\n$_"; 9032ed3b161SSteven Rostedt } 9042ed3b161SSteven Rostedt 9052ed3b161SSteven Rostedt if (__read_config($file, \$test_num)) { 9062ed3b161SSteven Rostedt $test_case = 1; 9072ed3b161SSteven Rostedt } 9082ed3b161SSteven Rostedt 909a57419b3SSteven Rostedt } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 910a57419b3SSteven Rostedt 911a57419b3SSteven Rostedt next if ($skip); 912a57419b3SSteven Rostedt 913a57419b3SSteven Rostedt my $lvalue = $1; 914a57419b3SSteven Rostedt my $rvalue = $2; 915a57419b3SSteven Rostedt 916a57419b3SSteven Rostedt if (!$default && 917a57419b3SSteven Rostedt ($lvalue eq "NUM_TESTS" || 918a57419b3SSteven Rostedt $lvalue eq "LOG_FILE" || 919a57419b3SSteven Rostedt $lvalue eq "CLEAR_LOG")) { 920a57419b3SSteven Rostedt die "$name: $.: $lvalue must be set in DEFAULTS section\n"; 921a57419b3SSteven Rostedt } 922a57419b3SSteven Rostedt 923a57419b3SSteven Rostedt if ($lvalue eq "NUM_TESTS") { 924a57419b3SSteven Rostedt if ($test_num) { 925a57419b3SSteven Rostedt die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 926a57419b3SSteven Rostedt } 927a57419b3SSteven Rostedt if (!$default) { 928a57419b3SSteven Rostedt die "$name: $.: NUM_TESTS must be set in default section\n"; 929a57419b3SSteven Rostedt } 930a57419b3SSteven Rostedt $num_tests_set = 1; 931a57419b3SSteven Rostedt } 932a57419b3SSteven Rostedt 933a57419b3SSteven Rostedt if ($default || $lvalue =~ /\[\d+\]$/) { 9343d1cc414SSteven Rostedt set_value($lvalue, $rvalue, $override, \%overrides, $name); 935a57419b3SSteven Rostedt } else { 936a57419b3SSteven Rostedt my $val = "$lvalue\[$test_num\]"; 9373d1cc414SSteven Rostedt set_value($val, $rvalue, $override, \%overrides, $name); 938a57419b3SSteven Rostedt 939a57419b3SSteven Rostedt if ($repeat > 1) { 940a57419b3SSteven Rostedt $repeats{$val} = $repeat; 941a57419b3SSteven Rostedt } 942a57419b3SSteven Rostedt } 94377d942ceSSteven Rostedt } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) { 94477d942ceSSteven Rostedt next if ($skip); 94577d942ceSSteven Rostedt 94677d942ceSSteven Rostedt my $lvalue = $1; 94777d942ceSSteven Rostedt my $rvalue = $2; 94877d942ceSSteven Rostedt 94977d942ceSSteven Rostedt # process config variables. 95077d942ceSSteven Rostedt # Config variables are only active while reading the 95177d942ceSSteven Rostedt # config and can be defined anywhere. They also ignore 95277d942ceSSteven Rostedt # TEST_START and DEFAULTS, but are skipped if they are in 95377d942ceSSteven Rostedt # on of these sections that have SKIP defined. 95477d942ceSSteven Rostedt # The save variable can be 95577d942ceSSteven Rostedt # defined multiple times and the new one simply overrides 95677d942ceSSteven Rostedt # the prevous one. 95777d942ceSSteven Rostedt set_variable($lvalue, $rvalue); 95877d942ceSSteven Rostedt 959a57419b3SSteven Rostedt } else { 960a57419b3SSteven Rostedt die "$name: $.: Garbage found in config\n$_"; 961a57419b3SSteven Rostedt } 9622545eb61SSteven Rostedt } 9632545eb61SSteven Rostedt 964a57419b3SSteven Rostedt if ($test_num) { 965a57419b3SSteven Rostedt $test_num += $repeat - 1; 966a57419b3SSteven Rostedt $opt{"NUM_TESTS"} = $test_num; 967a57419b3SSteven Rostedt } 968a57419b3SSteven Rostedt 9692ed3b161SSteven Rostedt close($in); 9702ed3b161SSteven Rostedt 9712ed3b161SSteven Rostedt $$current_test_num = $test_num; 9722ed3b161SSteven Rostedt 9732ed3b161SSteven Rostedt return $test_case; 9742ed3b161SSteven Rostedt} 9752ed3b161SSteven Rostedt 976c4261d0fSSteven Rostedtsub get_test_case { 977c4261d0fSSteven Rostedt print "What test case would you like to run?\n"; 978c4261d0fSSteven Rostedt print " (build, install or boot)\n"; 979c4261d0fSSteven Rostedt print " Other tests are available but require editing the config file\n"; 980c4261d0fSSteven Rostedt my $ans = <STDIN>; 981c4261d0fSSteven Rostedt chomp $ans; 982c4261d0fSSteven Rostedt $default{"TEST_TYPE"} = $ans; 983c4261d0fSSteven Rostedt} 984c4261d0fSSteven Rostedt 9852ed3b161SSteven Rostedtsub read_config { 9862ed3b161SSteven Rostedt my ($config) = @_; 9872ed3b161SSteven Rostedt 9882ed3b161SSteven Rostedt my $test_case; 9892ed3b161SSteven Rostedt my $test_num = 0; 9902ed3b161SSteven Rostedt 9912ed3b161SSteven Rostedt $test_case = __read_config $config, \$test_num; 9922ed3b161SSteven Rostedt 9938d1491baSSteven Rostedt # make sure we have all mandatory configs 9948d1491baSSteven Rostedt get_ktest_configs; 9958d1491baSSteven Rostedt 9960df213caSSteven Rostedt # was a test specified? 9970df213caSSteven Rostedt if (!$test_case) { 9980df213caSSteven Rostedt print "No test case specified.\n"; 999c4261d0fSSteven Rostedt get_test_case; 10000df213caSSteven Rostedt } 10010df213caSSteven Rostedt 1002a75fececSSteven Rostedt # set any defaults 1003a75fececSSteven Rostedt 1004a75fececSSteven Rostedt foreach my $default (keys %default) { 1005a75fececSSteven Rostedt if (!defined($opt{$default})) { 1006a75fececSSteven Rostedt $opt{$default} = $default{$default}; 1007a75fececSSteven Rostedt } 1008a75fececSSteven Rostedt } 10099cc9e091SSteven Rostedt 10109cc9e091SSteven Rostedt if ($opt{"IGNORE_UNUSED"} == 1) { 10119cc9e091SSteven Rostedt return; 10129cc9e091SSteven Rostedt } 10139cc9e091SSteven Rostedt 10149cc9e091SSteven Rostedt my %not_used; 10159cc9e091SSteven Rostedt 10169cc9e091SSteven Rostedt # check if there are any stragglers (typos?) 10179cc9e091SSteven Rostedt foreach my $option (keys %opt) { 10189cc9e091SSteven Rostedt my $op = $option; 10199cc9e091SSteven Rostedt # remove per test labels. 10209cc9e091SSteven Rostedt $op =~ s/\[.*\]//; 10219cc9e091SSteven Rostedt if (!exists($option_map{$op}) && 10229cc9e091SSteven Rostedt !exists($default{$op}) && 10239cc9e091SSteven Rostedt !exists($used_options{$op})) { 10249cc9e091SSteven Rostedt $not_used{$op} = 1; 10259cc9e091SSteven Rostedt } 10269cc9e091SSteven Rostedt } 10279cc9e091SSteven Rostedt 10289cc9e091SSteven Rostedt if (%not_used) { 10299cc9e091SSteven Rostedt my $s = "s are"; 10309cc9e091SSteven Rostedt $s = " is" if (keys %not_used == 1); 10319cc9e091SSteven Rostedt print "The following option$s not used; could be a typo:\n"; 10329cc9e091SSteven Rostedt foreach my $option (keys %not_used) { 10339cc9e091SSteven Rostedt print "$option\n"; 10349cc9e091SSteven Rostedt } 10359cc9e091SSteven Rostedt print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n"; 10369cc9e091SSteven Rostedt if (!read_yn "Do you want to continue?") { 10379cc9e091SSteven Rostedt exit -1; 10389cc9e091SSteven Rostedt } 10399cc9e091SSteven Rostedt } 10402545eb61SSteven Rostedt} 10412545eb61SSteven Rostedt 104223715c3cSSteven Rostedtsub __eval_option { 104323715c3cSSteven Rostedt my ($option, $i) = @_; 104423715c3cSSteven Rostedt 104523715c3cSSteven Rostedt # Add space to evaluate the character before $ 104623715c3cSSteven Rostedt $option = " $option"; 104723715c3cSSteven Rostedt my $retval = ""; 1048f9dfb65bSRabin Vincent my $repeated = 0; 1049f9dfb65bSRabin Vincent my $parent = 0; 1050f9dfb65bSRabin Vincent 1051f9dfb65bSRabin Vincent foreach my $test (keys %repeat_tests) { 1052f9dfb65bSRabin Vincent if ($i >= $test && 1053f9dfb65bSRabin Vincent $i < $test + $repeat_tests{$test}) { 1054f9dfb65bSRabin Vincent 1055f9dfb65bSRabin Vincent $repeated = 1; 1056f9dfb65bSRabin Vincent $parent = $test; 1057f9dfb65bSRabin Vincent last; 1058f9dfb65bSRabin Vincent } 1059f9dfb65bSRabin Vincent } 106023715c3cSSteven Rostedt 106123715c3cSSteven Rostedt while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 106223715c3cSSteven Rostedt my $start = $1; 106323715c3cSSteven Rostedt my $var = $2; 106423715c3cSSteven Rostedt my $end = $3; 106523715c3cSSteven Rostedt 106623715c3cSSteven Rostedt # Append beginning of line 106723715c3cSSteven Rostedt $retval = "$retval$start"; 106823715c3cSSteven Rostedt 106923715c3cSSteven Rostedt # If the iteration option OPT[$i] exists, then use that. 107023715c3cSSteven Rostedt # otherwise see if the default OPT (without [$i]) exists. 107123715c3cSSteven Rostedt 107223715c3cSSteven Rostedt my $o = "$var\[$i\]"; 1073f9dfb65bSRabin Vincent my $parento = "$var\[$parent\]"; 107423715c3cSSteven Rostedt 107523715c3cSSteven Rostedt if (defined($opt{$o})) { 107623715c3cSSteven Rostedt $o = $opt{$o}; 107723715c3cSSteven Rostedt $retval = "$retval$o"; 1078f9dfb65bSRabin Vincent } elsif ($repeated && defined($opt{$parento})) { 1079f9dfb65bSRabin Vincent $o = $opt{$parento}; 1080f9dfb65bSRabin Vincent $retval = "$retval$o"; 108123715c3cSSteven Rostedt } elsif (defined($opt{$var})) { 108223715c3cSSteven Rostedt $o = $opt{$var}; 108323715c3cSSteven Rostedt $retval = "$retval$o"; 108423715c3cSSteven Rostedt } else { 108523715c3cSSteven Rostedt $retval = "$retval\$\{$var\}"; 108623715c3cSSteven Rostedt } 108723715c3cSSteven Rostedt 108823715c3cSSteven Rostedt $option = $end; 108923715c3cSSteven Rostedt } 109023715c3cSSteven Rostedt 109123715c3cSSteven Rostedt $retval = "$retval$option"; 109223715c3cSSteven Rostedt 109323715c3cSSteven Rostedt $retval =~ s/^ //; 109423715c3cSSteven Rostedt 109523715c3cSSteven Rostedt return $retval; 109623715c3cSSteven Rostedt} 109723715c3cSSteven Rostedt 109823715c3cSSteven Rostedtsub eval_option { 109923715c3cSSteven Rostedt my ($option, $i) = @_; 110023715c3cSSteven Rostedt 110123715c3cSSteven Rostedt my $prev = ""; 110223715c3cSSteven Rostedt 110323715c3cSSteven Rostedt # Since an option can evaluate to another option, 110423715c3cSSteven Rostedt # keep iterating until we do not evaluate any more 110523715c3cSSteven Rostedt # options. 110623715c3cSSteven Rostedt my $r = 0; 110723715c3cSSteven Rostedt while ($prev ne $option) { 110823715c3cSSteven Rostedt # Check for recursive evaluations. 110923715c3cSSteven Rostedt # 100 deep should be more than enough. 111023715c3cSSteven Rostedt if ($r++ > 100) { 111123715c3cSSteven Rostedt die "Over 100 evaluations accurred with $option\n" . 111223715c3cSSteven Rostedt "Check for recursive variables\n"; 111323715c3cSSteven Rostedt } 111423715c3cSSteven Rostedt $prev = $option; 111523715c3cSSteven Rostedt $option = __eval_option($option, $i); 111623715c3cSSteven Rostedt } 111723715c3cSSteven Rostedt 111823715c3cSSteven Rostedt return $option; 111923715c3cSSteven Rostedt} 112023715c3cSSteven Rostedt 1121d1e2f22aSSteven Rostedtsub _logit { 11222545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 11232545eb61SSteven Rostedt open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 11242545eb61SSteven Rostedt print OUT @_; 11252545eb61SSteven Rostedt close(OUT); 11262545eb61SSteven Rostedt } 11272545eb61SSteven Rostedt} 11282545eb61SSteven Rostedt 1129d1e2f22aSSteven Rostedtsub logit { 1130d1e2f22aSSteven Rostedt if (defined($opt{"LOG_FILE"})) { 1131d1e2f22aSSteven Rostedt _logit @_; 1132d1e2f22aSSteven Rostedt } else { 1133d1e2f22aSSteven Rostedt print @_; 1134d1e2f22aSSteven Rostedt } 1135d1e2f22aSSteven Rostedt} 1136d1e2f22aSSteven Rostedt 11375f9b6cedSSteven Rostedtsub doprint { 11385f9b6cedSSteven Rostedt print @_; 1139d1e2f22aSSteven Rostedt _logit @_; 11405f9b6cedSSteven Rostedt} 11415f9b6cedSSteven Rostedt 11427faafbd6SSteven Rostedtsub run_command; 11432728be41SAndrew Jonessub start_monitor; 11442728be41SAndrew Jonessub end_monitor; 11452728be41SAndrew Jonessub wait_for_monitor; 11467faafbd6SSteven Rostedt 11477faafbd6SSteven Rostedtsub reboot { 11482728be41SAndrew Jones my ($time) = @_; 11492728be41SAndrew Jones 11502b803365SSteven Rostedt if (defined($time)) { 11512b803365SSteven Rostedt start_monitor; 11522b803365SSteven Rostedt # flush out current monitor 11532b803365SSteven Rostedt # May contain the reboot success line 11542b803365SSteven Rostedt wait_for_monitor 1; 11552b803365SSteven Rostedt } 11562b803365SSteven Rostedt 11577faafbd6SSteven Rostedt # try to reboot normally 1158e48c5293SSteven Rostedt if (run_command $reboot) { 1159576f627cSSteven Rostedt if (defined($powercycle_after_reboot)) { 1160576f627cSSteven Rostedt sleep $powercycle_after_reboot; 1161576f627cSSteven Rostedt run_command "$power_cycle"; 1162576f627cSSteven Rostedt } 1163576f627cSSteven Rostedt } else { 11647faafbd6SSteven Rostedt # nope? power cycle it. 1165a75fececSSteven Rostedt run_command "$power_cycle"; 11667faafbd6SSteven Rostedt } 11672728be41SAndrew Jones 11682728be41SAndrew Jones if (defined($time)) { 1169407b95b7SSteven Rostedt if (wait_for_monitor($time, $reboot_success_line)) { 1170407b95b7SSteven Rostedt # reboot got stuck? 11718a80c727SSteven Rostedt doprint "Reboot did not finish. Forcing power cycle\n"; 1172407b95b7SSteven Rostedt run_command "$power_cycle"; 1173407b95b7SSteven Rostedt } 11742728be41SAndrew Jones end_monitor; 11752728be41SAndrew Jones } 11767faafbd6SSteven Rostedt} 11777faafbd6SSteven Rostedt 1178bc7c5803SSteven Rostedtsub reboot_to_good { 1179bc7c5803SSteven Rostedt my ($time) = @_; 1180bc7c5803SSteven Rostedt 1181bc7c5803SSteven Rostedt if (defined($switch_to_good)) { 1182bc7c5803SSteven Rostedt run_command $switch_to_good; 1183bc7c5803SSteven Rostedt } 1184bc7c5803SSteven Rostedt 1185bc7c5803SSteven Rostedt reboot $time; 1186bc7c5803SSteven Rostedt} 1187bc7c5803SSteven Rostedt 1188576f627cSSteven Rostedtsub do_not_reboot { 1189576f627cSSteven Rostedt my $i = $iteration; 1190576f627cSSteven Rostedt 11914ab1cce5SSteven Rostedt return $test_type eq "build" || $no_reboot || 1192576f627cSSteven Rostedt ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 1193576f627cSSteven Rostedt ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 1194576f627cSSteven Rostedt} 1195576f627cSSteven Rostedt 11965c42fc5bSSteven Rostedtsub dodie { 11975a391fbfSSteven Rostedt doprint "CRITICAL FAILURE... ", @_, "\n"; 11985c42fc5bSSteven Rostedt 1199576f627cSSteven Rostedt my $i = $iteration; 1200576f627cSSteven Rostedt 1201576f627cSSteven Rostedt if ($reboot_on_error && !do_not_reboot) { 1202576f627cSSteven Rostedt 120375c3fda7SSteven Rostedt doprint "REBOOTING\n"; 1204bc7c5803SSteven Rostedt reboot_to_good; 120575c3fda7SSteven Rostedt 1206a75fececSSteven Rostedt } elsif ($poweroff_on_error && defined($power_off)) { 12075c42fc5bSSteven Rostedt doprint "POWERING OFF\n"; 1208a75fececSSteven Rostedt `$power_off`; 12095c42fc5bSSteven Rostedt } 121075c3fda7SSteven Rostedt 1211f80802cbSSteven Rostedt if (defined($opt{"LOG_FILE"})) { 1212f80802cbSSteven Rostedt print " See $opt{LOG_FILE} for more info.\n"; 1213f80802cbSSteven Rostedt } 1214f80802cbSSteven Rostedt 1215576f627cSSteven Rostedt die @_, "\n"; 12165c42fc5bSSteven Rostedt} 12175c42fc5bSSteven Rostedt 12187faafbd6SSteven Rostedtsub open_console { 12197faafbd6SSteven Rostedt my ($fp) = @_; 12207faafbd6SSteven Rostedt 12217faafbd6SSteven Rostedt my $flags; 12227faafbd6SSteven Rostedt 1223a75fececSSteven Rostedt my $pid = open($fp, "$console|") or 1224a75fececSSteven Rostedt dodie "Can't open console $console"; 12257faafbd6SSteven Rostedt 12267faafbd6SSteven Rostedt $flags = fcntl($fp, F_GETFL, 0) or 1227576f627cSSteven Rostedt dodie "Can't get flags for the socket: $!"; 12287faafbd6SSteven Rostedt $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 1229576f627cSSteven Rostedt dodie "Can't set flags for the socket: $!"; 12307faafbd6SSteven Rostedt 12317faafbd6SSteven Rostedt return $pid; 12327faafbd6SSteven Rostedt} 12337faafbd6SSteven Rostedt 12347faafbd6SSteven Rostedtsub close_console { 12357faafbd6SSteven Rostedt my ($fp, $pid) = @_; 12367faafbd6SSteven Rostedt 12377faafbd6SSteven Rostedt doprint "kill child process $pid\n"; 12387faafbd6SSteven Rostedt kill 2, $pid; 12397faafbd6SSteven Rostedt 12407faafbd6SSteven Rostedt print "closing!\n"; 12417faafbd6SSteven Rostedt close($fp); 12427faafbd6SSteven Rostedt} 12437faafbd6SSteven Rostedt 12447faafbd6SSteven Rostedtsub start_monitor { 12457faafbd6SSteven Rostedt if ($monitor_cnt++) { 12467faafbd6SSteven Rostedt return; 12477faafbd6SSteven Rostedt } 12487faafbd6SSteven Rostedt $monitor_fp = \*MONFD; 12497faafbd6SSteven Rostedt $monitor_pid = open_console $monitor_fp; 1250a75fececSSteven Rostedt 1251a75fececSSteven Rostedt return; 1252a75fececSSteven Rostedt 1253a75fececSSteven Rostedt open(MONFD, "Stop perl from warning about single use of MONFD"); 12547faafbd6SSteven Rostedt} 12557faafbd6SSteven Rostedt 12567faafbd6SSteven Rostedtsub end_monitor { 12577faafbd6SSteven Rostedt if (--$monitor_cnt) { 12587faafbd6SSteven Rostedt return; 12597faafbd6SSteven Rostedt } 12607faafbd6SSteven Rostedt close_console($monitor_fp, $monitor_pid); 12617faafbd6SSteven Rostedt} 12627faafbd6SSteven Rostedt 12637faafbd6SSteven Rostedtsub wait_for_monitor { 12642b803365SSteven Rostedt my ($time, $stop) = @_; 12652b803365SSteven Rostedt my $full_line = ""; 12667faafbd6SSteven Rostedt my $line; 12672b803365SSteven Rostedt my $booted = 0; 1268407b95b7SSteven Rostedt my $start_time = time; 12698a80c727SSteven Rostedt my $skip_call_trace = 0; 12708a80c727SSteven Rostedt my $bug = 0; 12718a80c727SSteven Rostedt my $bug_ignored = 0; 1272407b95b7SSteven Rostedt my $now; 12737faafbd6SSteven Rostedt 1274a75fececSSteven Rostedt doprint "** Wait for monitor to settle down **\n"; 12757faafbd6SSteven Rostedt 12767faafbd6SSteven Rostedt # read the monitor and wait for the system to calm down 12772b803365SSteven Rostedt while (!$booted) { 12787faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 12792b803365SSteven Rostedt last if (!defined($line)); 12802b803365SSteven Rostedt print "$line"; 12812b803365SSteven Rostedt $full_line .= $line; 12822b803365SSteven Rostedt 12832b803365SSteven Rostedt if (defined($stop) && $full_line =~ /$stop/) { 12842b803365SSteven Rostedt doprint "wait for monitor detected $stop\n"; 12852b803365SSteven Rostedt $booted = 1; 12862b803365SSteven Rostedt } 12872b803365SSteven Rostedt 12888a80c727SSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 12898a80c727SSteven Rostedt $skip_call_trace = 1; 12908a80c727SSteven Rostedt } 12918a80c727SSteven Rostedt 12928a80c727SSteven Rostedt if ($full_line =~ /call trace:/i) { 12938a80c727SSteven Rostedt if (!$bug && !$skip_call_trace) { 12948a80c727SSteven Rostedt if ($ignore_errors) { 12958a80c727SSteven Rostedt $bug_ignored = 1; 12968a80c727SSteven Rostedt } else { 12978a80c727SSteven Rostedt $bug = 1; 12988a80c727SSteven Rostedt } 12998a80c727SSteven Rostedt } 13008a80c727SSteven Rostedt } 13018a80c727SSteven Rostedt 13028a80c727SSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 13038a80c727SSteven Rostedt $skip_call_trace = 0; 13048a80c727SSteven Rostedt } 13058a80c727SSteven Rostedt 13068a80c727SSteven Rostedt if ($full_line =~ /Kernel panic -/) { 13078a80c727SSteven Rostedt $bug = 1; 13088a80c727SSteven Rostedt } 13098a80c727SSteven Rostedt 13102b803365SSteven Rostedt if ($line =~ /\n/) { 13112b803365SSteven Rostedt $full_line = ""; 13122b803365SSteven Rostedt } 1313407b95b7SSteven Rostedt $now = time; 1314407b95b7SSteven Rostedt if ($now - $start_time >= $max_monitor_wait) { 1315407b95b7SSteven Rostedt doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n"; 1316407b95b7SSteven Rostedt return 1; 1317407b95b7SSteven Rostedt } 13182b803365SSteven Rostedt } 1319a75fececSSteven Rostedt print "** Monitor flushed **\n"; 13208a80c727SSteven Rostedt return $bug; 13217faafbd6SSteven Rostedt} 13227faafbd6SSteven Rostedt 1323de5b6e3bSRabin Vincentsub save_logs { 1324de5b6e3bSRabin Vincent my ($result, $basedir) = @_; 1325de5b6e3bSRabin Vincent my @t = localtime; 1326de5b6e3bSRabin Vincent my $date = sprintf "%04d%02d%02d%02d%02d%02d", 1327de5b6e3bSRabin Vincent 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 1328de5b6e3bSRabin Vincent 1329de5b6e3bSRabin Vincent my $type = $build_type; 1330de5b6e3bSRabin Vincent if ($type =~ /useconfig/) { 1331de5b6e3bSRabin Vincent $type = "useconfig"; 1332de5b6e3bSRabin Vincent } 1333de5b6e3bSRabin Vincent 1334de5b6e3bSRabin Vincent my $dir = "$machine-$test_type-$type-$result-$date"; 1335de5b6e3bSRabin Vincent 1336de5b6e3bSRabin Vincent $dir = "$basedir/$dir"; 1337de5b6e3bSRabin Vincent 1338de5b6e3bSRabin Vincent if (!-d $dir) { 1339de5b6e3bSRabin Vincent mkpath($dir) or 1340de5b6e3bSRabin Vincent die "can't create $dir"; 1341de5b6e3bSRabin Vincent } 1342de5b6e3bSRabin Vincent 1343de5b6e3bSRabin Vincent my %files = ( 1344de5b6e3bSRabin Vincent "config" => $output_config, 1345de5b6e3bSRabin Vincent "buildlog" => $buildlog, 1346de5b6e3bSRabin Vincent "dmesg" => $dmesg, 1347de5b6e3bSRabin Vincent "testlog" => $testlog, 1348de5b6e3bSRabin Vincent ); 1349de5b6e3bSRabin Vincent 1350de5b6e3bSRabin Vincent while (my ($name, $source) = each(%files)) { 1351de5b6e3bSRabin Vincent if (-f "$source") { 1352de5b6e3bSRabin Vincent cp "$source", "$dir/$name" or 1353de5b6e3bSRabin Vincent die "failed to copy $source"; 1354de5b6e3bSRabin Vincent } 1355de5b6e3bSRabin Vincent } 1356de5b6e3bSRabin Vincent 1357de5b6e3bSRabin Vincent doprint "*** Saved info to $dir ***\n"; 1358de5b6e3bSRabin Vincent} 1359de5b6e3bSRabin Vincent 13602b7d9b21SSteven Rostedtsub fail { 13612b7d9b21SSteven Rostedt 1362921ed4c7SSteven Rostedt if (defined($post_test)) { 1363921ed4c7SSteven Rostedt run_command $post_test; 1364921ed4c7SSteven Rostedt } 1365921ed4c7SSteven Rostedt 1366a75fececSSteven Rostedt if ($die_on_failure) { 13672b7d9b21SSteven Rostedt dodie @_; 13682b7d9b21SSteven Rostedt } 13692b7d9b21SSteven Rostedt 1370a75fececSSteven Rostedt doprint "FAILED\n"; 13717faafbd6SSteven Rostedt 1372576f627cSSteven Rostedt my $i = $iteration; 1373576f627cSSteven Rostedt 1374a75fececSSteven Rostedt # no need to reboot for just building. 1375576f627cSSteven Rostedt if (!do_not_reboot) { 13767faafbd6SSteven Rostedt doprint "REBOOTING\n"; 1377bc7c5803SSteven Rostedt reboot_to_good $sleep_time; 1378a75fececSSteven Rostedt } 13797faafbd6SSteven Rostedt 13809064af52SSteven Rostedt my $name = ""; 13819064af52SSteven Rostedt 13829064af52SSteven Rostedt if (defined($test_name)) { 13839064af52SSteven Rostedt $name = " ($test_name)"; 13849064af52SSteven Rostedt } 13859064af52SSteven Rostedt 1386576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1387576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 13889064af52SSteven Rostedt doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n"; 1389576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1390576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1391a75fececSSteven Rostedt 1392de5b6e3bSRabin Vincent if (defined($store_failures)) { 1393de5b6e3bSRabin Vincent save_logs "fail", $store_failures; 1394cccae1a6SSteven Rostedt } 1395cccae1a6SSteven Rostedt 13962b7d9b21SSteven Rostedt return 1; 13972b7d9b21SSteven Rostedt} 13982b7d9b21SSteven Rostedt 13992545eb61SSteven Rostedtsub run_command { 14002545eb61SSteven Rostedt my ($command) = @_; 1401d6ce2a0bSSteven Rostedt my $dolog = 0; 1402d6ce2a0bSSteven Rostedt my $dord = 0; 1403d6ce2a0bSSteven Rostedt my $pid; 1404d6ce2a0bSSteven Rostedt 1405e48c5293SSteven Rostedt $command =~ s/\$SSH_USER/$ssh_user/g; 1406e48c5293SSteven Rostedt $command =~ s/\$MACHINE/$machine/g; 1407e48c5293SSteven Rostedt 1408d6ce2a0bSSteven Rostedt doprint("$command ... "); 1409d6ce2a0bSSteven Rostedt 1410d6ce2a0bSSteven Rostedt $pid = open(CMD, "$command 2>&1 |") or 14112b7d9b21SSteven Rostedt (fail "unable to exec $command" and return 0); 14122545eb61SSteven Rostedt 14132545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 1414d6ce2a0bSSteven Rostedt open(LOG, ">>$opt{LOG_FILE}") or 1415d6ce2a0bSSteven Rostedt dodie "failed to write to log"; 1416d6ce2a0bSSteven Rostedt $dolog = 1; 14176c5ee0beSSteven Rostedt } 14186c5ee0beSSteven Rostedt 14196c5ee0beSSteven Rostedt if (defined($redirect)) { 1420d6ce2a0bSSteven Rostedt open (RD, ">$redirect") or 1421d6ce2a0bSSteven Rostedt dodie "failed to write to redirect $redirect"; 1422d6ce2a0bSSteven Rostedt $dord = 1; 14232545eb61SSteven Rostedt } 14242545eb61SSteven Rostedt 1425d6ce2a0bSSteven Rostedt while (<CMD>) { 1426d6ce2a0bSSteven Rostedt print LOG if ($dolog); 1427d6ce2a0bSSteven Rostedt print RD if ($dord); 1428d6ce2a0bSSteven Rostedt } 14292545eb61SSteven Rostedt 1430d6ce2a0bSSteven Rostedt waitpid($pid, 0); 14312545eb61SSteven Rostedt my $failed = $?; 14322545eb61SSteven Rostedt 1433d6ce2a0bSSteven Rostedt close(CMD); 1434d6ce2a0bSSteven Rostedt close(LOG) if ($dolog); 1435d6ce2a0bSSteven Rostedt close(RD) if ($dord); 1436d6ce2a0bSSteven Rostedt 14372545eb61SSteven Rostedt if ($failed) { 14382545eb61SSteven Rostedt doprint "FAILED!\n"; 14392545eb61SSteven Rostedt } else { 14402545eb61SSteven Rostedt doprint "SUCCESS\n"; 14412545eb61SSteven Rostedt } 14422545eb61SSteven Rostedt 14435f9b6cedSSteven Rostedt return !$failed; 14445f9b6cedSSteven Rostedt} 14455f9b6cedSSteven Rostedt 1446e48c5293SSteven Rostedtsub run_ssh { 1447e48c5293SSteven Rostedt my ($cmd) = @_; 1448e48c5293SSteven Rostedt my $cp_exec = $ssh_exec; 1449e48c5293SSteven Rostedt 1450e48c5293SSteven Rostedt $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 1451e48c5293SSteven Rostedt return run_command "$cp_exec"; 1452e48c5293SSteven Rostedt} 1453e48c5293SSteven Rostedt 1454e48c5293SSteven Rostedtsub run_scp { 145502ad2617SSteven Rostedt my ($src, $dst, $cp_scp) = @_; 1456e48c5293SSteven Rostedt 1457e48c5293SSteven Rostedt $cp_scp =~ s/\$SRC_FILE/$src/g; 1458e48c5293SSteven Rostedt $cp_scp =~ s/\$DST_FILE/$dst/g; 1459e48c5293SSteven Rostedt 1460e48c5293SSteven Rostedt return run_command "$cp_scp"; 1461e48c5293SSteven Rostedt} 1462e48c5293SSteven Rostedt 146302ad2617SSteven Rostedtsub run_scp_install { 146402ad2617SSteven Rostedt my ($src, $dst) = @_; 146502ad2617SSteven Rostedt 146602ad2617SSteven Rostedt my $cp_scp = $scp_to_target_install; 146702ad2617SSteven Rostedt 146802ad2617SSteven Rostedt return run_scp($src, $dst, $cp_scp); 146902ad2617SSteven Rostedt} 147002ad2617SSteven Rostedt 147102ad2617SSteven Rostedtsub run_scp_mod { 147202ad2617SSteven Rostedt my ($src, $dst) = @_; 147302ad2617SSteven Rostedt 147402ad2617SSteven Rostedt my $cp_scp = $scp_to_target; 147502ad2617SSteven Rostedt 147602ad2617SSteven Rostedt return run_scp($src, $dst, $cp_scp); 147702ad2617SSteven Rostedt} 147802ad2617SSteven Rostedt 1479*a15ba913SSteven Rostedtsub get_grub2_index { 1480*a15ba913SSteven Rostedt 1481*a15ba913SSteven Rostedt return if (defined($grub_number)); 1482*a15ba913SSteven Rostedt 1483*a15ba913SSteven Rostedt doprint "Find grub2 menu ... "; 1484*a15ba913SSteven Rostedt $grub_number = -1; 1485*a15ba913SSteven Rostedt 1486*a15ba913SSteven Rostedt my $ssh_grub = $ssh_exec; 1487*a15ba913SSteven Rostedt $ssh_grub =~ s,\$SSH_COMMAND,cat $grub_file,g; 1488*a15ba913SSteven Rostedt 1489*a15ba913SSteven Rostedt open(IN, "$ssh_grub |") 1490*a15ba913SSteven Rostedt or die "unable to get $grub_file"; 1491*a15ba913SSteven Rostedt 1492*a15ba913SSteven Rostedt my $found = 0; 1493*a15ba913SSteven Rostedt 1494*a15ba913SSteven Rostedt while (<IN>) { 1495*a15ba913SSteven Rostedt if (/^menuentry.*$grub_menu/) { 1496*a15ba913SSteven Rostedt $grub_number++; 1497*a15ba913SSteven Rostedt $found = 1; 1498*a15ba913SSteven Rostedt last; 1499*a15ba913SSteven Rostedt } elsif (/^menuentry\s/) { 1500*a15ba913SSteven Rostedt $grub_number++; 1501*a15ba913SSteven Rostedt } 1502*a15ba913SSteven Rostedt } 1503*a15ba913SSteven Rostedt close(IN); 1504*a15ba913SSteven Rostedt 1505*a15ba913SSteven Rostedt die "Could not find '$grub_menu' in $grub_file on $machine" 1506*a15ba913SSteven Rostedt if (!$found); 1507*a15ba913SSteven Rostedt doprint "$grub_number\n"; 1508*a15ba913SSteven Rostedt} 1509*a15ba913SSteven Rostedt 15105f9b6cedSSteven Rostedtsub get_grub_index { 15115f9b6cedSSteven Rostedt 1512*a15ba913SSteven Rostedt if ($reboot_type eq "grub2") { 1513*a15ba913SSteven Rostedt get_grub2_index; 1514*a15ba913SSteven Rostedt return; 1515*a15ba913SSteven Rostedt } 1516*a15ba913SSteven Rostedt 1517a75fececSSteven Rostedt if ($reboot_type ne "grub") { 1518a75fececSSteven Rostedt return; 1519a75fececSSteven Rostedt } 15205a391fbfSSteven Rostedt return if (defined($grub_number)); 15215f9b6cedSSteven Rostedt 15225f9b6cedSSteven Rostedt doprint "Find grub menu ... "; 15235f9b6cedSSteven Rostedt $grub_number = -1; 1524e48c5293SSteven Rostedt 1525e48c5293SSteven Rostedt my $ssh_grub = $ssh_exec; 1526e48c5293SSteven Rostedt $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 1527e48c5293SSteven Rostedt 1528e48c5293SSteven Rostedt open(IN, "$ssh_grub |") 15295f9b6cedSSteven Rostedt or die "unable to get menu.lst"; 1530e48c5293SSteven Rostedt 1531eaa1fe25SSteven Rostedt my $found = 0; 1532eaa1fe25SSteven Rostedt 15335f9b6cedSSteven Rostedt while (<IN>) { 1534a75fececSSteven Rostedt if (/^\s*title\s+$grub_menu\s*$/) { 15355f9b6cedSSteven Rostedt $grub_number++; 1536eaa1fe25SSteven Rostedt $found = 1; 15375f9b6cedSSteven Rostedt last; 15385f9b6cedSSteven Rostedt } elsif (/^\s*title\s/) { 15395f9b6cedSSteven Rostedt $grub_number++; 15405f9b6cedSSteven Rostedt } 15415f9b6cedSSteven Rostedt } 15425f9b6cedSSteven Rostedt close(IN); 15435f9b6cedSSteven Rostedt 1544a75fececSSteven Rostedt die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 1545eaa1fe25SSteven Rostedt if (!$found); 15465f9b6cedSSteven Rostedt doprint "$grub_number\n"; 15472545eb61SSteven Rostedt} 15482545eb61SSteven Rostedt 15492545eb61SSteven Rostedtsub wait_for_input 15502545eb61SSteven Rostedt{ 15512545eb61SSteven Rostedt my ($fp, $time) = @_; 15522545eb61SSteven Rostedt my $rin; 15532545eb61SSteven Rostedt my $ready; 15542545eb61SSteven Rostedt my $line; 15552545eb61SSteven Rostedt my $ch; 15562545eb61SSteven Rostedt 15572545eb61SSteven Rostedt if (!defined($time)) { 15582545eb61SSteven Rostedt $time = $timeout; 15592545eb61SSteven Rostedt } 15602545eb61SSteven Rostedt 15612545eb61SSteven Rostedt $rin = ''; 15622545eb61SSteven Rostedt vec($rin, fileno($fp), 1) = 1; 15632545eb61SSteven Rostedt $ready = select($rin, undef, undef, $time); 15642545eb61SSteven Rostedt 15652545eb61SSteven Rostedt $line = ""; 15662545eb61SSteven Rostedt 15672545eb61SSteven Rostedt # try to read one char at a time 15682545eb61SSteven Rostedt while (sysread $fp, $ch, 1) { 15692545eb61SSteven Rostedt $line .= $ch; 15702545eb61SSteven Rostedt last if ($ch eq "\n"); 15712545eb61SSteven Rostedt } 15722545eb61SSteven Rostedt 15732545eb61SSteven Rostedt if (!length($line)) { 15742545eb61SSteven Rostedt return undef; 15752545eb61SSteven Rostedt } 15762545eb61SSteven Rostedt 15772545eb61SSteven Rostedt return $line; 15782545eb61SSteven Rostedt} 15792545eb61SSteven Rostedt 158075c3fda7SSteven Rostedtsub reboot_to { 1581bc7c5803SSteven Rostedt if (defined($switch_to_test)) { 1582bc7c5803SSteven Rostedt run_command $switch_to_test; 1583bc7c5803SSteven Rostedt } 1584bc7c5803SSteven Rostedt 1585a75fececSSteven Rostedt if ($reboot_type eq "grub") { 1586c54367f9SSteven Rostedt run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; 1587*a15ba913SSteven Rostedt } elsif ($reboot_type eq "grub2") { 1588*a15ba913SSteven Rostedt run_ssh "$grub_reboot $grub_number"; 158996f6a0dfSSteven Rostedt } elsif (defined $reboot_script) { 1590a75fececSSteven Rostedt run_command "$reboot_script"; 15912545eb61SSteven Rostedt } 159296f6a0dfSSteven Rostedt reboot; 159396f6a0dfSSteven Rostedt} 15942545eb61SSteven Rostedt 1595a57419b3SSteven Rostedtsub get_sha1 { 1596a57419b3SSteven Rostedt my ($commit) = @_; 1597a57419b3SSteven Rostedt 1598a57419b3SSteven Rostedt doprint "git rev-list --max-count=1 $commit ... "; 1599a57419b3SSteven Rostedt my $sha1 = `git rev-list --max-count=1 $commit`; 1600a57419b3SSteven Rostedt my $ret = $?; 1601a57419b3SSteven Rostedt 1602a57419b3SSteven Rostedt logit $sha1; 1603a57419b3SSteven Rostedt 1604a57419b3SSteven Rostedt if ($ret) { 1605a57419b3SSteven Rostedt doprint "FAILED\n"; 1606a57419b3SSteven Rostedt dodie "Failed to get git $commit"; 1607a57419b3SSteven Rostedt } 1608a57419b3SSteven Rostedt 1609a57419b3SSteven Rostedt print "SUCCESS\n"; 1610a57419b3SSteven Rostedt 1611a57419b3SSteven Rostedt chomp $sha1; 1612a57419b3SSteven Rostedt 1613a57419b3SSteven Rostedt return $sha1; 1614a57419b3SSteven Rostedt} 1615a57419b3SSteven Rostedt 16165a391fbfSSteven Rostedtsub monitor { 16172545eb61SSteven Rostedt my $booted = 0; 16182545eb61SSteven Rostedt my $bug = 0; 16196ca996ccSSteven Rostedt my $bug_ignored = 0; 16205c42fc5bSSteven Rostedt my $skip_call_trace = 0; 16212b7d9b21SSteven Rostedt my $loops; 16222545eb61SSteven Rostedt 16237faafbd6SSteven Rostedt wait_for_monitor 5; 16242545eb61SSteven Rostedt 16252545eb61SSteven Rostedt my $line; 16262545eb61SSteven Rostedt my $full_line = ""; 16272545eb61SSteven Rostedt 16287faafbd6SSteven Rostedt open(DMESG, "> $dmesg") or 16297faafbd6SSteven Rostedt die "unable to write to $dmesg"; 16302545eb61SSteven Rostedt 163175c3fda7SSteven Rostedt reboot_to; 16322545eb61SSteven Rostedt 16331c8a617aSSteven Rostedt my $success_start; 16341c8a617aSSteven Rostedt my $failure_start; 16352d01b26aSSteven Rostedt my $monitor_start = time; 16362d01b26aSSteven Rostedt my $done = 0; 1637f1a5b962SSteven Rostedt my $version_found = 0; 16381c8a617aSSteven Rostedt 16392d01b26aSSteven Rostedt while (!$done) { 16402545eb61SSteven Rostedt 1641ecaf8e52SSteven Rostedt if ($bug && defined($stop_after_failure) && 1642ecaf8e52SSteven Rostedt $stop_after_failure >= 0) { 1643ecaf8e52SSteven Rostedt my $time = $stop_after_failure - (time - $failure_start); 1644ecaf8e52SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 1645ecaf8e52SSteven Rostedt if (!defined($line)) { 1646ecaf8e52SSteven Rostedt doprint "bug timed out after $booted_timeout seconds\n"; 1647ecaf8e52SSteven Rostedt doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 1648ecaf8e52SSteven Rostedt last; 1649ecaf8e52SSteven Rostedt } 1650ecaf8e52SSteven Rostedt } elsif ($booted) { 1651a75fececSSteven Rostedt $line = wait_for_input($monitor_fp, $booted_timeout); 1652cd4f1d53SSteven Rostedt if (!defined($line)) { 1653cd4f1d53SSteven Rostedt my $s = $booted_timeout == 1 ? "" : "s"; 1654cd4f1d53SSteven Rostedt doprint "Successful boot found: break after $booted_timeout second$s\n"; 1655cd4f1d53SSteven Rostedt last; 1656cd4f1d53SSteven Rostedt } 16572b7d9b21SSteven Rostedt } else { 16587faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp); 1659cd4f1d53SSteven Rostedt if (!defined($line)) { 1660cd4f1d53SSteven Rostedt my $s = $timeout == 1 ? "" : "s"; 1661cd4f1d53SSteven Rostedt doprint "Timed out after $timeout second$s\n"; 1662cd4f1d53SSteven Rostedt last; 16632b7d9b21SSteven Rostedt } 1664cd4f1d53SSteven Rostedt } 16652545eb61SSteven Rostedt 16662545eb61SSteven Rostedt doprint $line; 16677faafbd6SSteven Rostedt print DMESG $line; 16682545eb61SSteven Rostedt 16692545eb61SSteven Rostedt # we are not guaranteed to get a full line 16702545eb61SSteven Rostedt $full_line .= $line; 16712545eb61SSteven Rostedt 1672a75fececSSteven Rostedt if ($full_line =~ /$success_line/) { 16732545eb61SSteven Rostedt $booted = 1; 16741c8a617aSSteven Rostedt $success_start = time; 16751c8a617aSSteven Rostedt } 16761c8a617aSSteven Rostedt 16771c8a617aSSteven Rostedt if ($booted && defined($stop_after_success) && 16781c8a617aSSteven Rostedt $stop_after_success >= 0) { 16791c8a617aSSteven Rostedt my $now = time; 16801c8a617aSSteven Rostedt if ($now - $success_start >= $stop_after_success) { 16811c8a617aSSteven Rostedt doprint "Test forced to stop after $stop_after_success seconds after success\n"; 16821c8a617aSSteven Rostedt last; 16831c8a617aSSteven Rostedt } 16842545eb61SSteven Rostedt } 16852545eb61SSteven Rostedt 16865c42fc5bSSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 16875c42fc5bSSteven Rostedt $skip_call_trace = 1; 16885c42fc5bSSteven Rostedt } 16895c42fc5bSSteven Rostedt 16902545eb61SSteven Rostedt if ($full_line =~ /call trace:/i) { 16916ca996ccSSteven Rostedt if (!$bug && !$skip_call_trace) { 16926ca996ccSSteven Rostedt if ($ignore_errors) { 16936ca996ccSSteven Rostedt $bug_ignored = 1; 16946ca996ccSSteven Rostedt } else { 16951c8a617aSSteven Rostedt $bug = 1; 16961c8a617aSSteven Rostedt $failure_start = time; 16971c8a617aSSteven Rostedt } 16981c8a617aSSteven Rostedt } 16996ca996ccSSteven Rostedt } 17001c8a617aSSteven Rostedt 17011c8a617aSSteven Rostedt if ($bug && defined($stop_after_failure) && 17021c8a617aSSteven Rostedt $stop_after_failure >= 0) { 17031c8a617aSSteven Rostedt my $now = time; 17041c8a617aSSteven Rostedt if ($now - $failure_start >= $stop_after_failure) { 17051c8a617aSSteven Rostedt doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 17061c8a617aSSteven Rostedt last; 17071c8a617aSSteven Rostedt } 17085c42fc5bSSteven Rostedt } 17095c42fc5bSSteven Rostedt 17105c42fc5bSSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 17115c42fc5bSSteven Rostedt $skip_call_trace = 0; 17125c42fc5bSSteven Rostedt } 17135c42fc5bSSteven Rostedt 17145c42fc5bSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 171510abf118SSteven Rostedt $failure_start = time; 17162545eb61SSteven Rostedt $bug = 1; 17172545eb61SSteven Rostedt } 17182545eb61SSteven Rostedt 1719f1a5b962SSteven Rostedt # Detect triple faults by testing the banner 1720f1a5b962SSteven Rostedt if ($full_line =~ /\bLinux version (\S+).*\n/) { 1721f1a5b962SSteven Rostedt if ($1 eq $version) { 1722f1a5b962SSteven Rostedt $version_found = 1; 1723f1a5b962SSteven Rostedt } elsif ($version_found && $detect_triplefault) { 1724f1a5b962SSteven Rostedt # We already booted into the kernel we are testing, 1725f1a5b962SSteven Rostedt # but now we booted into another kernel? 1726f1a5b962SSteven Rostedt # Consider this a triple fault. 1727f1a5b962SSteven Rostedt doprint "Aleady booted in Linux kernel $version, but now\n"; 1728f1a5b962SSteven Rostedt doprint "we booted into Linux kernel $1.\n"; 1729f1a5b962SSteven Rostedt doprint "Assuming that this is a triple fault.\n"; 1730f1a5b962SSteven Rostedt doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; 1731f1a5b962SSteven Rostedt last; 1732f1a5b962SSteven Rostedt } 1733f1a5b962SSteven Rostedt } 1734f1a5b962SSteven Rostedt 17352545eb61SSteven Rostedt if ($line =~ /\n/) { 17362545eb61SSteven Rostedt $full_line = ""; 17372545eb61SSteven Rostedt } 17382d01b26aSSteven Rostedt 17392d01b26aSSteven Rostedt if ($stop_test_after > 0 && !$booted && !$bug) { 17402d01b26aSSteven Rostedt if (time - $monitor_start > $stop_test_after) { 17414d62bf51SSteven Rostedt doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 17422d01b26aSSteven Rostedt $done = 1; 17432d01b26aSSteven Rostedt } 17442d01b26aSSteven Rostedt } 17452545eb61SSteven Rostedt } 17462545eb61SSteven Rostedt 17477faafbd6SSteven Rostedt close(DMESG); 17482545eb61SSteven Rostedt 17492545eb61SSteven Rostedt if ($bug) { 17502b7d9b21SSteven Rostedt return 0 if ($in_bisect); 1751576f627cSSteven Rostedt fail "failed - got a bug report" and return 0; 17522545eb61SSteven Rostedt } 17535f9b6cedSSteven Rostedt 1754a75fececSSteven Rostedt if (!$booted) { 1755a75fececSSteven Rostedt return 0 if ($in_bisect); 1756576f627cSSteven Rostedt fail "failed - never got a boot prompt." and return 0; 1757a75fececSSteven Rostedt } 1758a75fececSSteven Rostedt 17596ca996ccSSteven Rostedt if ($bug_ignored) { 17606ca996ccSSteven Rostedt doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 17616ca996ccSSteven Rostedt } 17626ca996ccSSteven Rostedt 17632b7d9b21SSteven Rostedt return 1; 17642545eb61SSteven Rostedt} 17652545eb61SSteven Rostedt 17662b29b2f8SSteven Rostedtsub eval_kernel_version { 17672b29b2f8SSteven Rostedt my ($option) = @_; 17682b29b2f8SSteven Rostedt 17692b29b2f8SSteven Rostedt $option =~ s/\$KERNEL_VERSION/$version/g; 17702b29b2f8SSteven Rostedt 17712b29b2f8SSteven Rostedt return $option; 17722b29b2f8SSteven Rostedt} 17732b29b2f8SSteven Rostedt 1774db05cfefSSteven Rostedtsub do_post_install { 1775db05cfefSSteven Rostedt 1776db05cfefSSteven Rostedt return if (!defined($post_install)); 1777db05cfefSSteven Rostedt 17782b29b2f8SSteven Rostedt my $cp_post_install = eval_kernel_version $post_install; 1779db05cfefSSteven Rostedt run_command "$cp_post_install" or 1780db05cfefSSteven Rostedt dodie "Failed to run post install"; 1781db05cfefSSteven Rostedt} 1782db05cfefSSteven Rostedt 17832545eb61SSteven Rostedtsub install { 17842545eb61SSteven Rostedt 1785e0a8742eSSteven Rostedt return if ($no_install); 1786e0a8742eSSteven Rostedt 1787e5c2ec11SSteven Rostedt if (defined($pre_install)) { 1788e5c2ec11SSteven Rostedt my $cp_pre_install = eval_kernel_version $pre_install; 1789e5c2ec11SSteven Rostedt run_command "$cp_pre_install" or 1790e5c2ec11SSteven Rostedt dodie "Failed to run pre install"; 1791e5c2ec11SSteven Rostedt } 1792e5c2ec11SSteven Rostedt 17932b29b2f8SSteven Rostedt my $cp_target = eval_kernel_version $target_image; 17942b29b2f8SSteven Rostedt 179502ad2617SSteven Rostedt run_scp_install "$outputdir/$build_target", "$cp_target" or 17965c42fc5bSSteven Rostedt dodie "failed to copy image"; 17975f9b6cedSSteven Rostedt 17985f9b6cedSSteven Rostedt my $install_mods = 0; 17995f9b6cedSSteven Rostedt 18005f9b6cedSSteven Rostedt # should we process modules? 18015f9b6cedSSteven Rostedt $install_mods = 0; 180251ad1dd1SSteven Rostedt open(IN, "$output_config") or dodie("Can't read config file"); 18035f9b6cedSSteven Rostedt while (<IN>) { 18045f9b6cedSSteven Rostedt if (/CONFIG_MODULES(=y)?/) { 18058bc5e4eaSSteven Rostedt if (defined($1)) { 18068bc5e4eaSSteven Rostedt $install_mods = 1; 18075f9b6cedSSteven Rostedt last; 18085f9b6cedSSteven Rostedt } 18095f9b6cedSSteven Rostedt } 18108bc5e4eaSSteven Rostedt } 18115f9b6cedSSteven Rostedt close(IN); 18125f9b6cedSSteven Rostedt 18135f9b6cedSSteven Rostedt if (!$install_mods) { 1814db05cfefSSteven Rostedt do_post_install; 18155f9b6cedSSteven Rostedt doprint "No modules needed\n"; 18165f9b6cedSSteven Rostedt return; 18172545eb61SSteven Rostedt } 18182545eb61SSteven Rostedt 1819627977d8SSteven Rostedt run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or 18205f9b6cedSSteven Rostedt dodie "Failed to install modules"; 18215f9b6cedSSteven Rostedt 18222545eb61SSteven Rostedt my $modlib = "/lib/modules/$version"; 1823a57419b3SSteven Rostedt my $modtar = "ktest-mods.tar.bz2"; 18242545eb61SSteven Rostedt 1825e48c5293SSteven Rostedt run_ssh "rm -rf $modlib" or 18265c42fc5bSSteven Rostedt dodie "failed to remove old mods: $modlib"; 18272545eb61SSteven Rostedt 18285c42fc5bSSteven Rostedt # would be nice if scp -r did not follow symbolic links 1829a75fececSSteven Rostedt run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 18305c42fc5bSSteven Rostedt dodie "making tarball"; 18315c42fc5bSSteven Rostedt 183202ad2617SSteven Rostedt run_scp_mod "$tmpdir/$modtar", "/tmp" or 18335c42fc5bSSteven Rostedt dodie "failed to copy modules"; 18345c42fc5bSSteven Rostedt 1835a75fececSSteven Rostedt unlink "$tmpdir/$modtar"; 18365c42fc5bSSteven Rostedt 1837e7b13441SSteven Rostedt run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or 18385c42fc5bSSteven Rostedt dodie "failed to tar modules"; 18395c42fc5bSSteven Rostedt 1840e48c5293SSteven Rostedt run_ssh "rm -f /tmp/$modtar"; 18418b37ca8cSSteven Rostedt 1842db05cfefSSteven Rostedt do_post_install; 18432545eb61SSteven Rostedt} 18442545eb61SSteven Rostedt 1845ddf607e5SSteven Rostedtsub get_version { 1846ddf607e5SSteven Rostedt # get the release name 1847683a3e64SSteven Rostedt return if ($have_version); 1848ddf607e5SSteven Rostedt doprint "$make kernelrelease ... "; 1849ddf607e5SSteven Rostedt $version = `$make kernelrelease | tail -1`; 1850ddf607e5SSteven Rostedt chomp($version); 1851ddf607e5SSteven Rostedt doprint "$version\n"; 1852683a3e64SSteven Rostedt $have_version = 1; 1853ddf607e5SSteven Rostedt} 1854ddf607e5SSteven Rostedt 1855ddf607e5SSteven Rostedtsub start_monitor_and_boot { 18569f7424ccSSteven Rostedt # Make sure the stable kernel has finished booting 18579f7424ccSSteven Rostedt start_monitor; 18589f7424ccSSteven Rostedt wait_for_monitor 5; 18599f7424ccSSteven Rostedt end_monitor; 18609f7424ccSSteven Rostedt 1861ddf607e5SSteven Rostedt get_grub_index; 1862ddf607e5SSteven Rostedt get_version; 1863ddf607e5SSteven Rostedt install; 1864ddf607e5SSteven Rostedt 1865ddf607e5SSteven Rostedt start_monitor; 1866ddf607e5SSteven Rostedt return monitor; 1867ddf607e5SSteven Rostedt} 1868ddf607e5SSteven Rostedt 18696c5ee0beSSteven Rostedtsub check_buildlog { 18706c5ee0beSSteven Rostedt my ($patch) = @_; 18716c5ee0beSSteven Rostedt 18726c5ee0beSSteven Rostedt my @files = `git show $patch | diffstat -l`; 18736c5ee0beSSteven Rostedt 18746c5ee0beSSteven Rostedt open(IN, "git show $patch |") or 18756c5ee0beSSteven Rostedt dodie "failed to show $patch"; 18766c5ee0beSSteven Rostedt while (<IN>) { 18776c5ee0beSSteven Rostedt if (m,^--- a/(.*),) { 18786c5ee0beSSteven Rostedt chomp $1; 18796c5ee0beSSteven Rostedt $files[$#files] = $1; 18806c5ee0beSSteven Rostedt } 18816c5ee0beSSteven Rostedt } 18826c5ee0beSSteven Rostedt close(IN); 18836c5ee0beSSteven Rostedt 18846c5ee0beSSteven Rostedt open(IN, $buildlog) or dodie "Can't open $buildlog"; 18856c5ee0beSSteven Rostedt while (<IN>) { 18866c5ee0beSSteven Rostedt if (/^\s*(.*?):.*(warning|error)/) { 18876c5ee0beSSteven Rostedt my $err = $1; 18886c5ee0beSSteven Rostedt foreach my $file (@files) { 1889a75fececSSteven Rostedt my $fullpath = "$builddir/$file"; 18906c5ee0beSSteven Rostedt if ($file eq $err || $fullpath eq $err) { 18912b7d9b21SSteven Rostedt fail "$file built with warnings" and return 0; 18926c5ee0beSSteven Rostedt } 18936c5ee0beSSteven Rostedt } 18946c5ee0beSSteven Rostedt } 18956c5ee0beSSteven Rostedt } 18966c5ee0beSSteven Rostedt close(IN); 18972b7d9b21SSteven Rostedt 18982b7d9b21SSteven Rostedt return 1; 18996c5ee0beSSteven Rostedt} 19006c5ee0beSSteven Rostedt 1901fcb3f16aSSteven Rostedtsub apply_min_config { 1902fcb3f16aSSteven Rostedt my $outconfig = "$output_config.new"; 1903612b9e9bSSteven Rostedt 1904fcb3f16aSSteven Rostedt # Read the config file and remove anything that 1905fcb3f16aSSteven Rostedt # is in the force_config hash (from minconfig and others) 1906fcb3f16aSSteven Rostedt # then add the force config back. 1907fcb3f16aSSteven Rostedt 1908fcb3f16aSSteven Rostedt doprint "Applying minimum configurations into $output_config.new\n"; 1909fcb3f16aSSteven Rostedt 1910fcb3f16aSSteven Rostedt open (OUT, ">$outconfig") or 1911fcb3f16aSSteven Rostedt dodie "Can't create $outconfig"; 1912fcb3f16aSSteven Rostedt 1913fcb3f16aSSteven Rostedt if (-f $output_config) { 1914fcb3f16aSSteven Rostedt open (IN, $output_config) or 1915fcb3f16aSSteven Rostedt dodie "Failed to open $output_config"; 1916fcb3f16aSSteven Rostedt while (<IN>) { 1917fcb3f16aSSteven Rostedt if (/^(# )?(CONFIG_[^\s=]*)/) { 1918fcb3f16aSSteven Rostedt next if (defined($force_config{$2})); 1919fcb3f16aSSteven Rostedt } 1920fcb3f16aSSteven Rostedt print OUT; 1921fcb3f16aSSteven Rostedt } 1922fcb3f16aSSteven Rostedt close IN; 1923fcb3f16aSSteven Rostedt } 1924fcb3f16aSSteven Rostedt foreach my $config (keys %force_config) { 1925fcb3f16aSSteven Rostedt print OUT "$force_config{$config}\n"; 1926fcb3f16aSSteven Rostedt } 1927fcb3f16aSSteven Rostedt close OUT; 1928fcb3f16aSSteven Rostedt 1929fcb3f16aSSteven Rostedt run_command "mv $outconfig $output_config"; 1930fcb3f16aSSteven Rostedt} 1931fcb3f16aSSteven Rostedt 1932fcb3f16aSSteven Rostedtsub make_oldconfig { 1933fcb3f16aSSteven Rostedt 19344c4ab120SSteven Rostedt my @force_list = keys %force_config; 19354c4ab120SSteven Rostedt 19364c4ab120SSteven Rostedt if ($#force_list >= 0) { 1937fcb3f16aSSteven Rostedt apply_min_config; 19384c4ab120SSteven Rostedt } 1939fcb3f16aSSteven Rostedt 1940fb16d891SAdam Lee if (!run_command "$make olddefconfig") { 1941fb16d891SAdam Lee # Perhaps olddefconfig doesn't exist in this version of the kernel 1942612b9e9bSSteven Rostedt # try a yes '' | oldconfig 1943fb16d891SAdam Lee doprint "olddefconfig failed, trying yes '' | make oldconfig\n"; 1944fcb3f16aSSteven Rostedt run_command "yes '' | $make oldconfig" or 1945612b9e9bSSteven Rostedt dodie "failed make config oldconfig"; 1946612b9e9bSSteven Rostedt } 1947612b9e9bSSteven Rostedt} 1948612b9e9bSSteven Rostedt 1949fcb3f16aSSteven Rostedt# read a config file and use this to force new configs. 1950fcb3f16aSSteven Rostedtsub load_force_config { 1951fcb3f16aSSteven Rostedt my ($config) = @_; 1952fcb3f16aSSteven Rostedt 1953cf79fab6SSteven Rostedt doprint "Loading force configs from $config\n"; 1954fcb3f16aSSteven Rostedt open(IN, $config) or 1955fcb3f16aSSteven Rostedt dodie "failed to read $config"; 1956fcb3f16aSSteven Rostedt while (<IN>) { 1957fcb3f16aSSteven Rostedt chomp; 1958fcb3f16aSSteven Rostedt if (/^(CONFIG[^\s=]*)(\s*=.*)/) { 1959fcb3f16aSSteven Rostedt $force_config{$1} = $_; 1960fcb3f16aSSteven Rostedt } elsif (/^# (CONFIG_\S*) is not set/) { 1961fcb3f16aSSteven Rostedt $force_config{$1} = $_; 1962fcb3f16aSSteven Rostedt } 1963fcb3f16aSSteven Rostedt } 1964fcb3f16aSSteven Rostedt close IN; 1965fcb3f16aSSteven Rostedt} 1966fcb3f16aSSteven Rostedt 19672545eb61SSteven Rostedtsub build { 19682545eb61SSteven Rostedt my ($type) = @_; 19692545eb61SSteven Rostedt 19707faafbd6SSteven Rostedt unlink $buildlog; 19717faafbd6SSteven Rostedt 19724ab1cce5SSteven Rostedt # Failed builds should not reboot the target 19734ab1cce5SSteven Rostedt my $save_no_reboot = $no_reboot; 19744ab1cce5SSteven Rostedt $no_reboot = 1; 19754ab1cce5SSteven Rostedt 1976683a3e64SSteven Rostedt # Calculate a new version from here. 1977683a3e64SSteven Rostedt $have_version = 0; 1978683a3e64SSteven Rostedt 19790bd6c1a3SSteven Rostedt if (defined($pre_build)) { 19800bd6c1a3SSteven Rostedt my $ret = run_command $pre_build; 19810bd6c1a3SSteven Rostedt if (!$ret && defined($pre_build_die) && 19820bd6c1a3SSteven Rostedt $pre_build_die) { 19830bd6c1a3SSteven Rostedt dodie "failed to pre_build\n"; 19840bd6c1a3SSteven Rostedt } 19850bd6c1a3SSteven Rostedt } 19860bd6c1a3SSteven Rostedt 198775c3fda7SSteven Rostedt if ($type =~ /^useconfig:(.*)/) { 198851ad1dd1SSteven Rostedt run_command "cp $1 $output_config" or 198975c3fda7SSteven Rostedt dodie "could not copy $1 to .config"; 19905f9b6cedSSteven Rostedt 199175c3fda7SSteven Rostedt $type = "oldconfig"; 199275c3fda7SSteven Rostedt } 199375c3fda7SSteven Rostedt 19945c42fc5bSSteven Rostedt # old config can ask questions 19955c42fc5bSSteven Rostedt if ($type eq "oldconfig") { 1996fb16d891SAdam Lee $type = "olddefconfig"; 199775c3fda7SSteven Rostedt 199875c3fda7SSteven Rostedt # allow for empty configs 199951ad1dd1SSteven Rostedt run_command "touch $output_config"; 200075c3fda7SSteven Rostedt 200113488231SAndrew Jones if (!$noclean) { 200251ad1dd1SSteven Rostedt run_command "mv $output_config $outputdir/config_temp" or 20035c42fc5bSSteven Rostedt dodie "moving .config"; 20045c42fc5bSSteven Rostedt 200513488231SAndrew Jones run_command "$make mrproper" or dodie "make mrproper"; 20065c42fc5bSSteven Rostedt 200751ad1dd1SSteven Rostedt run_command "mv $outputdir/config_temp $output_config" or 20085c42fc5bSSteven Rostedt dodie "moving config_temp"; 200913488231SAndrew Jones } 20105c42fc5bSSteven Rostedt 20115c42fc5bSSteven Rostedt } elsif (!$noclean) { 201251ad1dd1SSteven Rostedt unlink "$output_config"; 20135f9b6cedSSteven Rostedt run_command "$make mrproper" or 20145c42fc5bSSteven Rostedt dodie "make mrproper"; 20155c42fc5bSSteven Rostedt } 20162545eb61SSteven Rostedt 20172545eb61SSteven Rostedt # add something to distinguish this build 2018a75fececSSteven Rostedt open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 2019a75fececSSteven Rostedt print OUT "$localversion\n"; 20202545eb61SSteven Rostedt close(OUT); 20212545eb61SSteven Rostedt 20225f9b6cedSSteven Rostedt if (defined($minconfig)) { 2023fcb3f16aSSteven Rostedt load_force_config($minconfig); 20242545eb61SSteven Rostedt } 20252545eb61SSteven Rostedt 2026fb16d891SAdam Lee if ($type ne "olddefconfig") { 2027fcb3f16aSSteven Rostedt run_command "$make $type" or 20285c42fc5bSSteven Rostedt dodie "failed make config"; 2029612b9e9bSSteven Rostedt } 2030fcb3f16aSSteven Rostedt # Run old config regardless, to enforce min configurations 2031fcb3f16aSSteven Rostedt make_oldconfig; 20322545eb61SSteven Rostedt 2033a75fececSSteven Rostedt $redirect = "$buildlog"; 20340bd6c1a3SSteven Rostedt my $build_ret = run_command "$make $build_options"; 20356c5ee0beSSteven Rostedt undef $redirect; 20360bd6c1a3SSteven Rostedt 20370bd6c1a3SSteven Rostedt if (defined($post_build)) { 2038683a3e64SSteven Rostedt # Because a post build may change the kernel version 2039683a3e64SSteven Rostedt # do it now. 2040683a3e64SSteven Rostedt get_version; 20410bd6c1a3SSteven Rostedt my $ret = run_command $post_build; 20420bd6c1a3SSteven Rostedt if (!$ret && defined($post_build_die) && 20430bd6c1a3SSteven Rostedt $post_build_die) { 20440bd6c1a3SSteven Rostedt dodie "failed to post_build\n"; 20450bd6c1a3SSteven Rostedt } 20460bd6c1a3SSteven Rostedt } 20470bd6c1a3SSteven Rostedt 20480bd6c1a3SSteven Rostedt if (!$build_ret) { 20495f9b6cedSSteven Rostedt # bisect may need this to pass 20504ab1cce5SSteven Rostedt if ($in_bisect) { 20514ab1cce5SSteven Rostedt $no_reboot = $save_no_reboot; 20524ab1cce5SSteven Rostedt return 0; 20534ab1cce5SSteven Rostedt } 20542b7d9b21SSteven Rostedt fail "failed build" and return 0; 20552545eb61SSteven Rostedt } 20565f9b6cedSSteven Rostedt 20574ab1cce5SSteven Rostedt $no_reboot = $save_no_reboot; 20584ab1cce5SSteven Rostedt 20592b7d9b21SSteven Rostedt return 1; 20602545eb61SSteven Rostedt} 20612545eb61SSteven Rostedt 206275c3fda7SSteven Rostedtsub halt { 2063e48c5293SSteven Rostedt if (!run_ssh "halt" or defined($power_off)) { 2064576f627cSSteven Rostedt if (defined($poweroff_after_halt)) { 2065576f627cSSteven Rostedt sleep $poweroff_after_halt; 2066576f627cSSteven Rostedt run_command "$power_off"; 2067576f627cSSteven Rostedt } 2068576f627cSSteven Rostedt } else { 206975c3fda7SSteven Rostedt # nope? the zap it! 2070a75fececSSteven Rostedt run_command "$power_off"; 207175c3fda7SSteven Rostedt } 207275c3fda7SSteven Rostedt} 207375c3fda7SSteven Rostedt 20745f9b6cedSSteven Rostedtsub success { 20755f9b6cedSSteven Rostedt my ($i) = @_; 20765f9b6cedSSteven Rostedt 2077921ed4c7SSteven Rostedt if (defined($post_test)) { 2078921ed4c7SSteven Rostedt run_command $post_test; 2079921ed4c7SSteven Rostedt } 2080921ed4c7SSteven Rostedt 2081e48c5293SSteven Rostedt $successes++; 2082e48c5293SSteven Rostedt 20839064af52SSteven Rostedt my $name = ""; 20849064af52SSteven Rostedt 20859064af52SSteven Rostedt if (defined($test_name)) { 20869064af52SSteven Rostedt $name = " ($test_name)"; 20879064af52SSteven Rostedt } 20889064af52SSteven Rostedt 20895f9b6cedSSteven Rostedt doprint "\n\n*******************************************\n"; 20905f9b6cedSSteven Rostedt doprint "*******************************************\n"; 20919064af52SSteven Rostedt doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; 20925f9b6cedSSteven Rostedt doprint "*******************************************\n"; 20935f9b6cedSSteven Rostedt doprint "*******************************************\n"; 20945f9b6cedSSteven Rostedt 2095de5b6e3bSRabin Vincent if (defined($store_successes)) { 2096de5b6e3bSRabin Vincent save_logs "success", $store_successes; 2097de5b6e3bSRabin Vincent } 2098de5b6e3bSRabin Vincent 2099576f627cSSteven Rostedt if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 2100a75fececSSteven Rostedt doprint "Reboot and wait $sleep_time seconds\n"; 2101bc7c5803SSteven Rostedt reboot_to_good $sleep_time; 21025f9b6cedSSteven Rostedt } 21035f9b6cedSSteven Rostedt} 21045f9b6cedSSteven Rostedt 2105c960bb9fSSteven Rostedtsub answer_bisect { 2106c960bb9fSSteven Rostedt for (;;) { 2107c960bb9fSSteven Rostedt doprint "Pass or fail? [p/f]"; 2108c960bb9fSSteven Rostedt my $ans = <STDIN>; 2109c960bb9fSSteven Rostedt chomp $ans; 2110c960bb9fSSteven Rostedt if ($ans eq "p" || $ans eq "P") { 2111c960bb9fSSteven Rostedt return 1; 2112c960bb9fSSteven Rostedt } elsif ($ans eq "f" || $ans eq "F") { 2113c960bb9fSSteven Rostedt return 0; 2114c960bb9fSSteven Rostedt } else { 2115c960bb9fSSteven Rostedt print "Please answer 'P' or 'F'\n"; 2116c960bb9fSSteven Rostedt } 2117c960bb9fSSteven Rostedt } 2118c960bb9fSSteven Rostedt} 2119c960bb9fSSteven Rostedt 21205a391fbfSSteven Rostedtsub child_run_test { 21217faafbd6SSteven Rostedt my $failed = 0; 21225a391fbfSSteven Rostedt 21237faafbd6SSteven Rostedt # child should have no power 2124a75fececSSteven Rostedt $reboot_on_error = 0; 2125a75fececSSteven Rostedt $poweroff_on_error = 0; 2126a75fececSSteven Rostedt $die_on_failure = 1; 21277faafbd6SSteven Rostedt 2128a9dd5d63SRabin Vincent $redirect = "$testlog"; 21297faafbd6SSteven Rostedt run_command $run_test or $failed = 1; 2130a9dd5d63SRabin Vincent undef $redirect; 2131a9dd5d63SRabin Vincent 21325a391fbfSSteven Rostedt exit $failed; 21335a391fbfSSteven Rostedt} 21345a391fbfSSteven Rostedt 21355a391fbfSSteven Rostedtmy $child_done; 21365a391fbfSSteven Rostedt 21375a391fbfSSteven Rostedtsub child_finished { 21385a391fbfSSteven Rostedt $child_done = 1; 21395a391fbfSSteven Rostedt} 21405a391fbfSSteven Rostedt 21415a391fbfSSteven Rostedtsub do_run_test { 21425a391fbfSSteven Rostedt my $child_pid; 21435a391fbfSSteven Rostedt my $child_exit; 21445a391fbfSSteven Rostedt my $line; 21455a391fbfSSteven Rostedt my $full_line; 21465a391fbfSSteven Rostedt my $bug = 0; 21479b1d367dSSteven Rostedt my $bug_ignored = 0; 21485a391fbfSSteven Rostedt 21497faafbd6SSteven Rostedt wait_for_monitor 1; 21505a391fbfSSteven Rostedt 21517faafbd6SSteven Rostedt doprint "run test $run_test\n"; 21525a391fbfSSteven Rostedt 21535a391fbfSSteven Rostedt $child_done = 0; 21545a391fbfSSteven Rostedt 21555a391fbfSSteven Rostedt $SIG{CHLD} = qw(child_finished); 21565a391fbfSSteven Rostedt 21575a391fbfSSteven Rostedt $child_pid = fork; 21585a391fbfSSteven Rostedt 21595a391fbfSSteven Rostedt child_run_test if (!$child_pid); 21605a391fbfSSteven Rostedt 21615a391fbfSSteven Rostedt $full_line = ""; 21625a391fbfSSteven Rostedt 21635a391fbfSSteven Rostedt do { 21647faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 21655a391fbfSSteven Rostedt if (defined($line)) { 21665a391fbfSSteven Rostedt 21675a391fbfSSteven Rostedt # we are not guaranteed to get a full line 21685a391fbfSSteven Rostedt $full_line .= $line; 21698ea0e063SSteven Rostedt doprint $line; 21705a391fbfSSteven Rostedt 21715a391fbfSSteven Rostedt if ($full_line =~ /call trace:/i) { 21729b1d367dSSteven Rostedt if ($ignore_errors) { 21739b1d367dSSteven Rostedt $bug_ignored = 1; 21749b1d367dSSteven Rostedt } else { 21755a391fbfSSteven Rostedt $bug = 1; 21765a391fbfSSteven Rostedt } 21779b1d367dSSteven Rostedt } 21785a391fbfSSteven Rostedt 21795a391fbfSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 21805a391fbfSSteven Rostedt $bug = 1; 21815a391fbfSSteven Rostedt } 21825a391fbfSSteven Rostedt 21835a391fbfSSteven Rostedt if ($line =~ /\n/) { 21845a391fbfSSteven Rostedt $full_line = ""; 21855a391fbfSSteven Rostedt } 21865a391fbfSSteven Rostedt } 21875a391fbfSSteven Rostedt } while (!$child_done && !$bug); 21885a391fbfSSteven Rostedt 21899b1d367dSSteven Rostedt if (!$bug && $bug_ignored) { 21909b1d367dSSteven Rostedt doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 21919b1d367dSSteven Rostedt } 21929b1d367dSSteven Rostedt 21935a391fbfSSteven Rostedt if ($bug) { 21948ea0e063SSteven Rostedt my $failure_start = time; 21958ea0e063SSteven Rostedt my $now; 21968ea0e063SSteven Rostedt do { 21978ea0e063SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 21988ea0e063SSteven Rostedt if (defined($line)) { 21998ea0e063SSteven Rostedt doprint $line; 22008ea0e063SSteven Rostedt } 22018ea0e063SSteven Rostedt $now = time; 22028ea0e063SSteven Rostedt if ($now - $failure_start >= $stop_after_failure) { 22038ea0e063SSteven Rostedt last; 22048ea0e063SSteven Rostedt } 22058ea0e063SSteven Rostedt } while (defined($line)); 22068ea0e063SSteven Rostedt 22075a391fbfSSteven Rostedt doprint "Detected kernel crash!\n"; 22085a391fbfSSteven Rostedt # kill the child with extreme prejudice 22095a391fbfSSteven Rostedt kill 9, $child_pid; 22105a391fbfSSteven Rostedt } 22115a391fbfSSteven Rostedt 22125a391fbfSSteven Rostedt waitpid $child_pid, 0; 22135a391fbfSSteven Rostedt $child_exit = $?; 22145a391fbfSSteven Rostedt 2215c5dacb88SSteven Rostedt if (!$bug && $in_bisect) { 2216c5dacb88SSteven Rostedt if (defined($bisect_ret_good)) { 2217c5dacb88SSteven Rostedt if ($child_exit == $bisect_ret_good) { 2218c5dacb88SSteven Rostedt return 1; 2219c5dacb88SSteven Rostedt } 2220c5dacb88SSteven Rostedt } 2221c5dacb88SSteven Rostedt if (defined($bisect_ret_skip)) { 2222c5dacb88SSteven Rostedt if ($child_exit == $bisect_ret_skip) { 2223c5dacb88SSteven Rostedt return -1; 2224c5dacb88SSteven Rostedt } 2225c5dacb88SSteven Rostedt } 2226c5dacb88SSteven Rostedt if (defined($bisect_ret_abort)) { 2227c5dacb88SSteven Rostedt if ($child_exit == $bisect_ret_abort) { 2228c5dacb88SSteven Rostedt fail "test abort" and return -2; 2229c5dacb88SSteven Rostedt } 2230c5dacb88SSteven Rostedt } 2231c5dacb88SSteven Rostedt if (defined($bisect_ret_bad)) { 2232c5dacb88SSteven Rostedt if ($child_exit == $bisect_ret_skip) { 2233c5dacb88SSteven Rostedt return 0; 2234c5dacb88SSteven Rostedt } 2235c5dacb88SSteven Rostedt } 2236c5dacb88SSteven Rostedt if (defined($bisect_ret_default)) { 2237c5dacb88SSteven Rostedt if ($bisect_ret_default eq "good") { 2238c5dacb88SSteven Rostedt return 1; 2239c5dacb88SSteven Rostedt } elsif ($bisect_ret_default eq "bad") { 2240c5dacb88SSteven Rostedt return 0; 2241c5dacb88SSteven Rostedt } elsif ($bisect_ret_default eq "skip") { 2242c5dacb88SSteven Rostedt return -1; 2243c5dacb88SSteven Rostedt } elsif ($bisect_ret_default eq "abort") { 2244c5dacb88SSteven Rostedt return -2; 2245c5dacb88SSteven Rostedt } else { 2246c5dacb88SSteven Rostedt fail "unknown default action: $bisect_ret_default" 2247c5dacb88SSteven Rostedt and return -2; 2248c5dacb88SSteven Rostedt } 2249c5dacb88SSteven Rostedt } 2250c5dacb88SSteven Rostedt } 2251c5dacb88SSteven Rostedt 22525a391fbfSSteven Rostedt if ($bug || $child_exit) { 22532b7d9b21SSteven Rostedt return 0 if $in_bisect; 22542b7d9b21SSteven Rostedt fail "test failed" and return 0; 22555a391fbfSSteven Rostedt } 22562b7d9b21SSteven Rostedt return 1; 22575a391fbfSSteven Rostedt} 22585a391fbfSSteven Rostedt 2259a75fececSSteven Rostedtsub run_git_bisect { 2260a75fececSSteven Rostedt my ($command) = @_; 2261a75fececSSteven Rostedt 2262a75fececSSteven Rostedt doprint "$command ... "; 2263a75fececSSteven Rostedt 2264a75fececSSteven Rostedt my $output = `$command 2>&1`; 2265a75fececSSteven Rostedt my $ret = $?; 2266a75fececSSteven Rostedt 2267a75fececSSteven Rostedt logit $output; 2268a75fececSSteven Rostedt 2269a75fececSSteven Rostedt if ($ret) { 2270a75fececSSteven Rostedt doprint "FAILED\n"; 2271a75fececSSteven Rostedt dodie "Failed to git bisect"; 2272a75fececSSteven Rostedt } 2273a75fececSSteven Rostedt 2274a75fececSSteven Rostedt doprint "SUCCESS\n"; 2275a75fececSSteven Rostedt if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 2276a75fececSSteven Rostedt doprint "$1 [$2]\n"; 2277a75fececSSteven Rostedt } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 2278b5f4aea6SSteven Rostedt $bisect_bad_commit = $1; 2279a75fececSSteven Rostedt doprint "Found bad commit... $1\n"; 2280a75fececSSteven Rostedt return 0; 2281a75fececSSteven Rostedt } else { 2282a75fececSSteven Rostedt # we already logged it, just print it now. 2283a75fececSSteven Rostedt print $output; 2284a75fececSSteven Rostedt } 2285a75fececSSteven Rostedt 2286a75fececSSteven Rostedt return 1; 2287a75fececSSteven Rostedt} 2288a75fececSSteven Rostedt 2289c23dca7cSSteven Rostedtsub bisect_reboot { 2290c23dca7cSSteven Rostedt doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 2291bc7c5803SSteven Rostedt reboot_to_good $bisect_sleep_time; 2292c23dca7cSSteven Rostedt} 2293c23dca7cSSteven Rostedt 2294c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip 22950a05c769SSteven Rostedtsub run_bisect_test { 22960a05c769SSteven Rostedt my ($type, $buildtype) = @_; 22975f9b6cedSSteven Rostedt 22982b7d9b21SSteven Rostedt my $failed = 0; 22995f9b6cedSSteven Rostedt my $result; 23005f9b6cedSSteven Rostedt my $output; 23015f9b6cedSSteven Rostedt my $ret; 23025f9b6cedSSteven Rostedt 23030a05c769SSteven Rostedt $in_bisect = 1; 23040a05c769SSteven Rostedt 23050a05c769SSteven Rostedt build $buildtype or $failed = 1; 23065f9b6cedSSteven Rostedt 23075f9b6cedSSteven Rostedt if ($type ne "build") { 2308c23dca7cSSteven Rostedt if ($failed && $bisect_skip) { 2309c23dca7cSSteven Rostedt $in_bisect = 0; 2310c23dca7cSSteven Rostedt return -1; 2311c23dca7cSSteven Rostedt } 23127faafbd6SSteven Rostedt dodie "Failed on build" if $failed; 23135f9b6cedSSteven Rostedt 23145f9b6cedSSteven Rostedt # Now boot the box 2315ddf607e5SSteven Rostedt start_monitor_and_boot or $failed = 1; 23165f9b6cedSSteven Rostedt 23175f9b6cedSSteven Rostedt if ($type ne "boot") { 2318c23dca7cSSteven Rostedt if ($failed && $bisect_skip) { 2319c23dca7cSSteven Rostedt end_monitor; 2320c23dca7cSSteven Rostedt bisect_reboot; 2321c23dca7cSSteven Rostedt $in_bisect = 0; 2322c23dca7cSSteven Rostedt return -1; 2323c23dca7cSSteven Rostedt } 23247faafbd6SSteven Rostedt dodie "Failed on boot" if $failed; 23255a391fbfSSteven Rostedt 23262b7d9b21SSteven Rostedt do_run_test or $failed = 1; 23275f9b6cedSSteven Rostedt } 23287faafbd6SSteven Rostedt end_monitor; 23295f9b6cedSSteven Rostedt } 23305f9b6cedSSteven Rostedt 23315f9b6cedSSteven Rostedt if ($failed) { 23320a05c769SSteven Rostedt $result = 0; 23335f9b6cedSSteven Rostedt } else { 23340a05c769SSteven Rostedt $result = 1; 23355f9b6cedSSteven Rostedt } 23364025bc62SSteven Rostedt 23374025bc62SSteven Rostedt # reboot the box to a kernel we can ssh to 23384025bc62SSteven Rostedt if ($type ne "build") { 23394025bc62SSteven Rostedt bisect_reboot; 23404025bc62SSteven Rostedt } 23410a05c769SSteven Rostedt $in_bisect = 0; 23420a05c769SSteven Rostedt 23430a05c769SSteven Rostedt return $result; 23440a05c769SSteven Rostedt} 23450a05c769SSteven Rostedt 23460a05c769SSteven Rostedtsub run_bisect { 23470a05c769SSteven Rostedt my ($type) = @_; 23480a05c769SSteven Rostedt my $buildtype = "oldconfig"; 23490a05c769SSteven Rostedt 23500a05c769SSteven Rostedt # We should have a minconfig to use? 23510a05c769SSteven Rostedt if (defined($minconfig)) { 23520a05c769SSteven Rostedt $buildtype = "useconfig:$minconfig"; 23530a05c769SSteven Rostedt } 23540a05c769SSteven Rostedt 23550a05c769SSteven Rostedt my $ret = run_bisect_test $type, $buildtype; 23560a05c769SSteven Rostedt 2357c960bb9fSSteven Rostedt if ($bisect_manual) { 2358c960bb9fSSteven Rostedt $ret = answer_bisect; 2359c960bb9fSSteven Rostedt } 23605f9b6cedSSteven Rostedt 2361d6ce2a0bSSteven Rostedt # Are we looking for where it worked, not failed? 23625158ba3eSRuss Dill if ($reverse_bisect && $ret >= 0) { 23630a05c769SSteven Rostedt $ret = !$ret; 2364d6ce2a0bSSteven Rostedt } 2365d6ce2a0bSSteven Rostedt 2366c23dca7cSSteven Rostedt if ($ret > 0) { 23670a05c769SSteven Rostedt return "good"; 2368c23dca7cSSteven Rostedt } elsif ($ret == 0) { 23690a05c769SSteven Rostedt return "bad"; 2370c23dca7cSSteven Rostedt } elsif ($bisect_skip) { 2371c23dca7cSSteven Rostedt doprint "HIT A BAD COMMIT ... SKIPPING\n"; 2372c23dca7cSSteven Rostedt return "skip"; 23730a05c769SSteven Rostedt } 23745f9b6cedSSteven Rostedt} 23755f9b6cedSSteven Rostedt 2376dad98754SSteven Rostedtsub update_bisect_replay { 2377dad98754SSteven Rostedt my $tmp_log = "$tmpdir/ktest_bisect_log"; 2378dad98754SSteven Rostedt run_command "git bisect log > $tmp_log" or 2379dad98754SSteven Rostedt die "can't create bisect log"; 2380dad98754SSteven Rostedt return $tmp_log; 2381dad98754SSteven Rostedt} 2382dad98754SSteven Rostedt 23835f9b6cedSSteven Rostedtsub bisect { 23845f9b6cedSSteven Rostedt my ($i) = @_; 23855f9b6cedSSteven Rostedt 23865f9b6cedSSteven Rostedt my $result; 23875f9b6cedSSteven Rostedt 2388b5f4aea6SSteven Rostedt die "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good)); 2389b5f4aea6SSteven Rostedt die "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad)); 2390b5f4aea6SSteven Rostedt die "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type)); 23915f9b6cedSSteven Rostedt 2392b5f4aea6SSteven Rostedt my $good = $bisect_good; 2393b5f4aea6SSteven Rostedt my $bad = $bisect_bad; 2394b5f4aea6SSteven Rostedt my $type = $bisect_type; 2395b5f4aea6SSteven Rostedt my $start = $bisect_start; 2396b5f4aea6SSteven Rostedt my $replay = $bisect_replay; 2397b5f4aea6SSteven Rostedt my $start_files = $bisect_files; 23983410f6fdSSteven Rostedt 23993410f6fdSSteven Rostedt if (defined($start_files)) { 24003410f6fdSSteven Rostedt $start_files = " -- " . $start_files; 24013410f6fdSSteven Rostedt } else { 24023410f6fdSSteven Rostedt $start_files = ""; 24033410f6fdSSteven Rostedt } 24045f9b6cedSSteven Rostedt 2405a57419b3SSteven Rostedt # convert to true sha1's 2406a57419b3SSteven Rostedt $good = get_sha1($good); 2407a57419b3SSteven Rostedt $bad = get_sha1($bad); 2408a57419b3SSteven Rostedt 2409b5f4aea6SSteven Rostedt if (defined($bisect_reverse) && $bisect_reverse == 1) { 2410d6ce2a0bSSteven Rostedt doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 2411d6ce2a0bSSteven Rostedt $reverse_bisect = 1; 2412d6ce2a0bSSteven Rostedt } else { 2413d6ce2a0bSSteven Rostedt $reverse_bisect = 0; 2414d6ce2a0bSSteven Rostedt } 2415d6ce2a0bSSteven Rostedt 24165a391fbfSSteven Rostedt # Can't have a test without having a test to run 24175a391fbfSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 24185a391fbfSSteven Rostedt $type = "boot"; 24195a391fbfSSteven Rostedt } 24205a391fbfSSteven Rostedt 2421dad98754SSteven Rostedt # Check if a bisect was running 2422dad98754SSteven Rostedt my $bisect_start_file = "$builddir/.git/BISECT_START"; 2423dad98754SSteven Rostedt 2424b5f4aea6SSteven Rostedt my $check = $bisect_check; 2425dad98754SSteven Rostedt my $do_check = defined($check) && $check ne "0"; 2426dad98754SSteven Rostedt 2427dad98754SSteven Rostedt if ( -f $bisect_start_file ) { 2428dad98754SSteven Rostedt print "Bisect in progress found\n"; 2429dad98754SSteven Rostedt if ($do_check) { 2430dad98754SSteven Rostedt print " If you say yes, then no checks of good or bad will be done\n"; 2431dad98754SSteven Rostedt } 2432dad98754SSteven Rostedt if (defined($replay)) { 2433dad98754SSteven Rostedt print "** BISECT_REPLAY is defined in config file **"; 2434dad98754SSteven Rostedt print " Ignore config option and perform new git bisect log?\n"; 2435dad98754SSteven Rostedt if (read_ync " (yes, no, or cancel) ") { 2436dad98754SSteven Rostedt $replay = update_bisect_replay; 2437dad98754SSteven Rostedt $do_check = 0; 2438dad98754SSteven Rostedt } 2439dad98754SSteven Rostedt } elsif (read_yn "read git log and continue?") { 2440dad98754SSteven Rostedt $replay = update_bisect_replay; 2441dad98754SSteven Rostedt $do_check = 0; 2442dad98754SSteven Rostedt } 2443dad98754SSteven Rostedt } 2444dad98754SSteven Rostedt 2445dad98754SSteven Rostedt if ($do_check) { 2446a75fececSSteven Rostedt 2447a75fececSSteven Rostedt # get current HEAD 2448a57419b3SSteven Rostedt my $head = get_sha1("HEAD"); 2449a75fececSSteven Rostedt 2450a75fececSSteven Rostedt if ($check ne "good") { 2451a75fececSSteven Rostedt doprint "TESTING BISECT BAD [$bad]\n"; 2452a75fececSSteven Rostedt run_command "git checkout $bad" or 2453a75fececSSteven Rostedt die "Failed to checkout $bad"; 2454a75fececSSteven Rostedt 2455a75fececSSteven Rostedt $result = run_bisect $type; 2456a75fececSSteven Rostedt 2457a75fececSSteven Rostedt if ($result ne "bad") { 2458a75fececSSteven Rostedt fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 2459a75fececSSteven Rostedt } 2460a75fececSSteven Rostedt } 2461a75fececSSteven Rostedt 2462a75fececSSteven Rostedt if ($check ne "bad") { 2463a75fececSSteven Rostedt doprint "TESTING BISECT GOOD [$good]\n"; 2464a75fececSSteven Rostedt run_command "git checkout $good" or 2465a75fececSSteven Rostedt die "Failed to checkout $good"; 2466a75fececSSteven Rostedt 2467a75fececSSteven Rostedt $result = run_bisect $type; 2468a75fececSSteven Rostedt 2469a75fececSSteven Rostedt if ($result ne "good") { 2470a75fececSSteven Rostedt fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 2471a75fececSSteven Rostedt } 2472a75fececSSteven Rostedt } 2473a75fececSSteven Rostedt 2474a75fececSSteven Rostedt # checkout where we started 2475a75fececSSteven Rostedt run_command "git checkout $head" or 2476a75fececSSteven Rostedt die "Failed to checkout $head"; 2477a75fececSSteven Rostedt } 2478a75fececSSteven Rostedt 24793410f6fdSSteven Rostedt run_command "git bisect start$start_files" or 2480a75fececSSteven Rostedt dodie "could not start bisect"; 2481a75fececSSteven Rostedt 2482a75fececSSteven Rostedt run_command "git bisect good $good" or 2483a75fececSSteven Rostedt dodie "could not set bisect good to $good"; 2484a75fececSSteven Rostedt 2485a75fececSSteven Rostedt run_git_bisect "git bisect bad $bad" or 2486a75fececSSteven Rostedt dodie "could not set bisect bad to $bad"; 2487a75fececSSteven Rostedt 2488a75fececSSteven Rostedt if (defined($replay)) { 2489a75fececSSteven Rostedt run_command "git bisect replay $replay" or 2490a75fececSSteven Rostedt dodie "failed to run replay"; 2491a75fececSSteven Rostedt } 2492a75fececSSteven Rostedt 2493a75fececSSteven Rostedt if (defined($start)) { 2494a75fececSSteven Rostedt run_command "git checkout $start" or 2495a75fececSSteven Rostedt dodie "failed to checkout $start"; 2496a75fececSSteven Rostedt } 2497a75fececSSteven Rostedt 2498a75fececSSteven Rostedt my $test; 24995f9b6cedSSteven Rostedt do { 25005f9b6cedSSteven Rostedt $result = run_bisect $type; 2501a75fececSSteven Rostedt $test = run_git_bisect "git bisect $result"; 2502a75fececSSteven Rostedt } while ($test); 25035f9b6cedSSteven Rostedt 25045f9b6cedSSteven Rostedt run_command "git bisect log" or 25055f9b6cedSSteven Rostedt dodie "could not capture git bisect log"; 25065f9b6cedSSteven Rostedt 25075f9b6cedSSteven Rostedt run_command "git bisect reset" or 25085f9b6cedSSteven Rostedt dodie "could not reset git bisect"; 25095f9b6cedSSteven Rostedt 2510b5f4aea6SSteven Rostedt doprint "Bad commit was [$bisect_bad_commit]\n"; 25115f9b6cedSSteven Rostedt 25120a05c769SSteven Rostedt success $i; 25130a05c769SSteven Rostedt} 25140a05c769SSteven Rostedt 2515cf79fab6SSteven Rostedt# config_ignore holds the configs that were set (or unset) for 2516cf79fab6SSteven Rostedt# a good config and we will ignore these configs for the rest 2517cf79fab6SSteven Rostedt# of a config bisect. These configs stay as they were. 25180a05c769SSteven Rostedtmy %config_ignore; 2519cf79fab6SSteven Rostedt 2520cf79fab6SSteven Rostedt# config_set holds what all configs were set as. 25210a05c769SSteven Rostedtmy %config_set; 25220a05c769SSteven Rostedt 2523cf79fab6SSteven Rostedt# config_off holds the set of configs that the bad config had disabled. 2524cf79fab6SSteven Rostedt# We need to record them and set them in the .config when running 2525fb16d891SAdam Lee# olddefconfig, because olddefconfig keeps the defaults. 2526cf79fab6SSteven Rostedtmy %config_off; 2527cf79fab6SSteven Rostedt 2528cf79fab6SSteven Rostedt# config_off_tmp holds a set of configs to turn off for now 2529cf79fab6SSteven Rostedtmy @config_off_tmp; 2530cf79fab6SSteven Rostedt 2531cf79fab6SSteven Rostedt# config_list is the set of configs that are being tested 25320a05c769SSteven Rostedtmy %config_list; 25330a05c769SSteven Rostedtmy %null_config; 25340a05c769SSteven Rostedt 25350a05c769SSteven Rostedtmy %dependency; 25360a05c769SSteven Rostedt 25374c4ab120SSteven Rostedtsub assign_configs { 25384c4ab120SSteven Rostedt my ($hash, $config) = @_; 25390a05c769SSteven Rostedt 25400a05c769SSteven Rostedt open (IN, $config) 25410a05c769SSteven Rostedt or dodie "Failed to read $config"; 25420a05c769SSteven Rostedt 25430a05c769SSteven Rostedt while (<IN>) { 25449bf71749SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 25454c4ab120SSteven Rostedt ${$hash}{$2} = $1; 25460a05c769SSteven Rostedt } 25470a05c769SSteven Rostedt } 25480a05c769SSteven Rostedt 25490a05c769SSteven Rostedt close(IN); 25500a05c769SSteven Rostedt} 25510a05c769SSteven Rostedt 25524c4ab120SSteven Rostedtsub process_config_ignore { 25534c4ab120SSteven Rostedt my ($config) = @_; 25544c4ab120SSteven Rostedt 25554c4ab120SSteven Rostedt assign_configs \%config_ignore, $config; 25564c4ab120SSteven Rostedt} 25574c4ab120SSteven Rostedt 25580a05c769SSteven Rostedtsub read_current_config { 25590a05c769SSteven Rostedt my ($config_ref) = @_; 25600a05c769SSteven Rostedt 25610a05c769SSteven Rostedt %{$config_ref} = (); 25620a05c769SSteven Rostedt undef %{$config_ref}; 25630a05c769SSteven Rostedt 25640a05c769SSteven Rostedt my @key = keys %{$config_ref}; 25650a05c769SSteven Rostedt if ($#key >= 0) { 25660a05c769SSteven Rostedt print "did not delete!\n"; 25670a05c769SSteven Rostedt exit; 25680a05c769SSteven Rostedt } 25690a05c769SSteven Rostedt open (IN, "$output_config"); 25700a05c769SSteven Rostedt 25710a05c769SSteven Rostedt while (<IN>) { 25720a05c769SSteven Rostedt if (/^(CONFIG\S+)=(.*)/) { 25730a05c769SSteven Rostedt ${$config_ref}{$1} = $2; 25740a05c769SSteven Rostedt } 25750a05c769SSteven Rostedt } 25760a05c769SSteven Rostedt close(IN); 25770a05c769SSteven Rostedt} 25780a05c769SSteven Rostedt 25790a05c769SSteven Rostedtsub get_dependencies { 25800a05c769SSteven Rostedt my ($config) = @_; 25810a05c769SSteven Rostedt 25820a05c769SSteven Rostedt my $arr = $dependency{$config}; 25830a05c769SSteven Rostedt if (!defined($arr)) { 25840a05c769SSteven Rostedt return (); 25850a05c769SSteven Rostedt } 25860a05c769SSteven Rostedt 25870a05c769SSteven Rostedt my @deps = @{$arr}; 25880a05c769SSteven Rostedt 25890a05c769SSteven Rostedt foreach my $dep (@{$arr}) { 25900a05c769SSteven Rostedt print "ADD DEP $dep\n"; 25910a05c769SSteven Rostedt @deps = (@deps, get_dependencies $dep); 25920a05c769SSteven Rostedt } 25930a05c769SSteven Rostedt 25940a05c769SSteven Rostedt return @deps; 25950a05c769SSteven Rostedt} 25960a05c769SSteven Rostedt 25970a05c769SSteven Rostedtsub create_config { 25980a05c769SSteven Rostedt my @configs = @_; 25990a05c769SSteven Rostedt 26000a05c769SSteven Rostedt open(OUT, ">$output_config") or dodie "Can not write to $output_config"; 26010a05c769SSteven Rostedt 26020a05c769SSteven Rostedt foreach my $config (@configs) { 26030a05c769SSteven Rostedt print OUT "$config_set{$config}\n"; 26040a05c769SSteven Rostedt my @deps = get_dependencies $config; 26050a05c769SSteven Rostedt foreach my $dep (@deps) { 26060a05c769SSteven Rostedt print OUT "$config_set{$dep}\n"; 26070a05c769SSteven Rostedt } 26080a05c769SSteven Rostedt } 26090a05c769SSteven Rostedt 2610cf79fab6SSteven Rostedt # turn off configs to keep off 2611cf79fab6SSteven Rostedt foreach my $config (keys %config_off) { 2612cf79fab6SSteven Rostedt print OUT "# $config is not set\n"; 2613cf79fab6SSteven Rostedt } 2614cf79fab6SSteven Rostedt 2615cf79fab6SSteven Rostedt # turn off configs that should be off for now 2616cf79fab6SSteven Rostedt foreach my $config (@config_off_tmp) { 2617cf79fab6SSteven Rostedt print OUT "# $config is not set\n"; 2618cf79fab6SSteven Rostedt } 2619cf79fab6SSteven Rostedt 26200a05c769SSteven Rostedt foreach my $config (keys %config_ignore) { 26210a05c769SSteven Rostedt print OUT "$config_ignore{$config}\n"; 26220a05c769SSteven Rostedt } 26230a05c769SSteven Rostedt close(OUT); 26240a05c769SSteven Rostedt 2625fcb3f16aSSteven Rostedt make_oldconfig; 26260a05c769SSteven Rostedt} 26270a05c769SSteven Rostedt 26280a05c769SSteven Rostedtsub compare_configs { 26290a05c769SSteven Rostedt my (%a, %b) = @_; 26300a05c769SSteven Rostedt 26310a05c769SSteven Rostedt foreach my $item (keys %a) { 26320a05c769SSteven Rostedt if (!defined($b{$item})) { 26330a05c769SSteven Rostedt print "diff $item\n"; 26340a05c769SSteven Rostedt return 1; 26350a05c769SSteven Rostedt } 26360a05c769SSteven Rostedt delete $b{$item}; 26370a05c769SSteven Rostedt } 26380a05c769SSteven Rostedt 26390a05c769SSteven Rostedt my @keys = keys %b; 26400a05c769SSteven Rostedt if ($#keys) { 26410a05c769SSteven Rostedt print "diff2 $keys[0]\n"; 26420a05c769SSteven Rostedt } 26430a05c769SSteven Rostedt return -1 if ($#keys >= 0); 26440a05c769SSteven Rostedt 26450a05c769SSteven Rostedt return 0; 26460a05c769SSteven Rostedt} 26470a05c769SSteven Rostedt 26480a05c769SSteven Rostedtsub run_config_bisect_test { 26490a05c769SSteven Rostedt my ($type) = @_; 26500a05c769SSteven Rostedt 26510a05c769SSteven Rostedt return run_bisect_test $type, "oldconfig"; 26520a05c769SSteven Rostedt} 26530a05c769SSteven Rostedt 26540a05c769SSteven Rostedtsub process_passed { 26550a05c769SSteven Rostedt my (%configs) = @_; 26560a05c769SSteven Rostedt 26570a05c769SSteven Rostedt doprint "These configs had no failure: (Enabling them for further compiles)\n"; 26580a05c769SSteven Rostedt # Passed! All these configs are part of a good compile. 26590a05c769SSteven Rostedt # Add them to the min options. 26600a05c769SSteven Rostedt foreach my $config (keys %configs) { 26610a05c769SSteven Rostedt if (defined($config_list{$config})) { 26620a05c769SSteven Rostedt doprint " removing $config\n"; 26630a05c769SSteven Rostedt $config_ignore{$config} = $config_list{$config}; 26640a05c769SSteven Rostedt delete $config_list{$config}; 26650a05c769SSteven Rostedt } 26660a05c769SSteven Rostedt } 2667f1a27850SSteven Rostedt doprint "config copied to $outputdir/config_good\n"; 2668f1a27850SSteven Rostedt run_command "cp -f $output_config $outputdir/config_good"; 26690a05c769SSteven Rostedt} 26700a05c769SSteven Rostedt 26710a05c769SSteven Rostedtsub process_failed { 26720a05c769SSteven Rostedt my ($config) = @_; 26730a05c769SSteven Rostedt 26740a05c769SSteven Rostedt doprint "\n\n***************************************\n"; 26750a05c769SSteven Rostedt doprint "Found bad config: $config\n"; 26760a05c769SSteven Rostedt doprint "***************************************\n\n"; 26770a05c769SSteven Rostedt} 26780a05c769SSteven Rostedt 26790a05c769SSteven Rostedtsub run_config_bisect { 26800a05c769SSteven Rostedt 26810a05c769SSteven Rostedt my @start_list = keys %config_list; 26820a05c769SSteven Rostedt 26830a05c769SSteven Rostedt if ($#start_list < 0) { 26840a05c769SSteven Rostedt doprint "No more configs to test!!!\n"; 26850a05c769SSteven Rostedt return -1; 26860a05c769SSteven Rostedt } 26870a05c769SSteven Rostedt 26880a05c769SSteven Rostedt doprint "***** RUN TEST ***\n"; 2689b5f4aea6SSteven Rostedt my $type = $config_bisect_type; 26900a05c769SSteven Rostedt my $ret; 26910a05c769SSteven Rostedt my %current_config; 26920a05c769SSteven Rostedt 26930a05c769SSteven Rostedt my $count = $#start_list + 1; 26940a05c769SSteven Rostedt doprint " $count configs to test\n"; 26950a05c769SSteven Rostedt 26960a05c769SSteven Rostedt my $half = int($#start_list / 2); 26970a05c769SSteven Rostedt 26980a05c769SSteven Rostedt do { 26990a05c769SSteven Rostedt my @tophalf = @start_list[0 .. $half]; 27000a05c769SSteven Rostedt 2701cf79fab6SSteven Rostedt # keep the bottom half off 2702cf79fab6SSteven Rostedt if ($half < $#start_list) { 2703cf79fab6SSteven Rostedt @config_off_tmp = @start_list[$half + 1 .. $#start_list]; 2704cf79fab6SSteven Rostedt } else { 2705cf79fab6SSteven Rostedt @config_off_tmp = (); 2706cf79fab6SSteven Rostedt } 2707cf79fab6SSteven Rostedt 27080a05c769SSteven Rostedt create_config @tophalf; 27090a05c769SSteven Rostedt read_current_config \%current_config; 27100a05c769SSteven Rostedt 27110a05c769SSteven Rostedt $count = $#tophalf + 1; 27120a05c769SSteven Rostedt doprint "Testing $count configs\n"; 27130a05c769SSteven Rostedt my $found = 0; 27140a05c769SSteven Rostedt # make sure we test something 27150a05c769SSteven Rostedt foreach my $config (@tophalf) { 27160a05c769SSteven Rostedt if (defined($current_config{$config})) { 27170a05c769SSteven Rostedt logit " $config\n"; 27180a05c769SSteven Rostedt $found = 1; 27190a05c769SSteven Rostedt } 27200a05c769SSteven Rostedt } 27210a05c769SSteven Rostedt if (!$found) { 27220a05c769SSteven Rostedt # try the other half 27230a05c769SSteven Rostedt doprint "Top half produced no set configs, trying bottom half\n"; 2724cf79fab6SSteven Rostedt 2725cf79fab6SSteven Rostedt # keep the top half off 2726cf79fab6SSteven Rostedt @config_off_tmp = @tophalf; 27274c8cc55bSSteven Rostedt @tophalf = @start_list[$half + 1 .. $#start_list]; 2728cf79fab6SSteven Rostedt 27290a05c769SSteven Rostedt create_config @tophalf; 27300a05c769SSteven Rostedt read_current_config \%current_config; 27310a05c769SSteven Rostedt foreach my $config (@tophalf) { 27320a05c769SSteven Rostedt if (defined($current_config{$config})) { 27330a05c769SSteven Rostedt logit " $config\n"; 27340a05c769SSteven Rostedt $found = 1; 27350a05c769SSteven Rostedt } 27360a05c769SSteven Rostedt } 27370a05c769SSteven Rostedt if (!$found) { 27380a05c769SSteven Rostedt doprint "Failed: Can't make new config with current configs\n"; 27390a05c769SSteven Rostedt foreach my $config (@start_list) { 27400a05c769SSteven Rostedt doprint " CONFIG: $config\n"; 27410a05c769SSteven Rostedt } 27420a05c769SSteven Rostedt return -1; 27430a05c769SSteven Rostedt } 27440a05c769SSteven Rostedt $count = $#tophalf + 1; 27450a05c769SSteven Rostedt doprint "Testing $count configs\n"; 27460a05c769SSteven Rostedt } 27470a05c769SSteven Rostedt 27480a05c769SSteven Rostedt $ret = run_config_bisect_test $type; 2749c960bb9fSSteven Rostedt if ($bisect_manual) { 2750c960bb9fSSteven Rostedt $ret = answer_bisect; 2751c960bb9fSSteven Rostedt } 27520a05c769SSteven Rostedt if ($ret) { 27530a05c769SSteven Rostedt process_passed %current_config; 27540a05c769SSteven Rostedt return 0; 27550a05c769SSteven Rostedt } 27560a05c769SSteven Rostedt 27570a05c769SSteven Rostedt doprint "This config had a failure.\n"; 27580a05c769SSteven Rostedt doprint "Removing these configs that were not set in this config:\n"; 2759f1a27850SSteven Rostedt doprint "config copied to $outputdir/config_bad\n"; 2760f1a27850SSteven Rostedt run_command "cp -f $output_config $outputdir/config_bad"; 27610a05c769SSteven Rostedt 27620a05c769SSteven Rostedt # A config exists in this group that was bad. 27630a05c769SSteven Rostedt foreach my $config (keys %config_list) { 27640a05c769SSteven Rostedt if (!defined($current_config{$config})) { 27650a05c769SSteven Rostedt doprint " removing $config\n"; 27660a05c769SSteven Rostedt delete $config_list{$config}; 27670a05c769SSteven Rostedt } 27680a05c769SSteven Rostedt } 27690a05c769SSteven Rostedt 27700a05c769SSteven Rostedt @start_list = @tophalf; 27710a05c769SSteven Rostedt 27720a05c769SSteven Rostedt if ($#start_list == 0) { 27730a05c769SSteven Rostedt process_failed $start_list[0]; 27740a05c769SSteven Rostedt return 1; 27750a05c769SSteven Rostedt } 27760a05c769SSteven Rostedt 27770a05c769SSteven Rostedt # remove half the configs we are looking at and see if 27780a05c769SSteven Rostedt # they are good. 27790a05c769SSteven Rostedt $half = int($#start_list / 2); 27804c8cc55bSSteven Rostedt } while ($#start_list > 0); 27810a05c769SSteven Rostedt 2782c960bb9fSSteven Rostedt # we found a single config, try it again unless we are running manually 2783c960bb9fSSteven Rostedt 2784c960bb9fSSteven Rostedt if ($bisect_manual) { 2785c960bb9fSSteven Rostedt process_failed $start_list[0]; 2786c960bb9fSSteven Rostedt return 1; 2787c960bb9fSSteven Rostedt } 2788c960bb9fSSteven Rostedt 27890a05c769SSteven Rostedt my @tophalf = @start_list[0 .. 0]; 27900a05c769SSteven Rostedt 27910a05c769SSteven Rostedt $ret = run_config_bisect_test $type; 27920a05c769SSteven Rostedt if ($ret) { 27930a05c769SSteven Rostedt process_passed %current_config; 27940a05c769SSteven Rostedt return 0; 27950a05c769SSteven Rostedt } 27960a05c769SSteven Rostedt 27970a05c769SSteven Rostedt process_failed $start_list[0]; 27980a05c769SSteven Rostedt return 1; 27990a05c769SSteven Rostedt} 28000a05c769SSteven Rostedt 28010a05c769SSteven Rostedtsub config_bisect { 28020a05c769SSteven Rostedt my ($i) = @_; 28030a05c769SSteven Rostedt 2804b5f4aea6SSteven Rostedt my $start_config = $config_bisect; 28050a05c769SSteven Rostedt 28060a05c769SSteven Rostedt my $tmpconfig = "$tmpdir/use_config"; 28070a05c769SSteven Rostedt 280830f75da5SSteven Rostedt if (defined($config_bisect_good)) { 280930f75da5SSteven Rostedt process_config_ignore $config_bisect_good; 281030f75da5SSteven Rostedt } 281130f75da5SSteven Rostedt 28120a05c769SSteven Rostedt # Make the file with the bad config and the min config 28130a05c769SSteven Rostedt if (defined($minconfig)) { 28140a05c769SSteven Rostedt # read the min config for things to ignore 28150a05c769SSteven Rostedt run_command "cp $minconfig $tmpconfig" or 28160a05c769SSteven Rostedt dodie "failed to copy $minconfig to $tmpconfig"; 28170a05c769SSteven Rostedt } else { 28180a05c769SSteven Rostedt unlink $tmpconfig; 28190a05c769SSteven Rostedt } 28200a05c769SSteven Rostedt 28210a05c769SSteven Rostedt if (-f $tmpconfig) { 2822fcb3f16aSSteven Rostedt load_force_config($tmpconfig); 28230a05c769SSteven Rostedt process_config_ignore $tmpconfig; 28240a05c769SSteven Rostedt } 28250a05c769SSteven Rostedt 28260a05c769SSteven Rostedt # now process the start config 28270a05c769SSteven Rostedt run_command "cp $start_config $output_config" or 28280a05c769SSteven Rostedt dodie "failed to copy $start_config to $output_config"; 28290a05c769SSteven Rostedt 28300a05c769SSteven Rostedt # read directly what we want to check 28310a05c769SSteven Rostedt my %config_check; 28320a05c769SSteven Rostedt open (IN, $output_config) 2833f9dee311SMasanari Iida or dodie "failed to open $output_config"; 28340a05c769SSteven Rostedt 28350a05c769SSteven Rostedt while (<IN>) { 28360a05c769SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 28370a05c769SSteven Rostedt $config_check{$2} = $1; 28380a05c769SSteven Rostedt } 28390a05c769SSteven Rostedt } 28400a05c769SSteven Rostedt close(IN); 28410a05c769SSteven Rostedt 2842250bae8bSSteven Rostedt # Now run oldconfig with the minconfig 2843fcb3f16aSSteven Rostedt make_oldconfig; 28440a05c769SSteven Rostedt 28450a05c769SSteven Rostedt # check to see what we lost (or gained) 28460a05c769SSteven Rostedt open (IN, $output_config) 28470a05c769SSteven Rostedt or dodie "Failed to read $start_config"; 28480a05c769SSteven Rostedt 28490a05c769SSteven Rostedt my %removed_configs; 28500a05c769SSteven Rostedt my %added_configs; 28510a05c769SSteven Rostedt 28520a05c769SSteven Rostedt while (<IN>) { 28530a05c769SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 28540a05c769SSteven Rostedt # save off all options 28550a05c769SSteven Rostedt $config_set{$2} = $1; 28560a05c769SSteven Rostedt if (defined($config_check{$2})) { 28570a05c769SSteven Rostedt if (defined($config_ignore{$2})) { 28580a05c769SSteven Rostedt $removed_configs{$2} = $1; 28590a05c769SSteven Rostedt } else { 28600a05c769SSteven Rostedt $config_list{$2} = $1; 28610a05c769SSteven Rostedt } 28620a05c769SSteven Rostedt } elsif (!defined($config_ignore{$2})) { 28630a05c769SSteven Rostedt $added_configs{$2} = $1; 28640a05c769SSteven Rostedt $config_list{$2} = $1; 28650a05c769SSteven Rostedt } 2866cf79fab6SSteven Rostedt } elsif (/^# ((CONFIG\S*).*)/) { 2867cf79fab6SSteven Rostedt # Keep these configs disabled 2868cf79fab6SSteven Rostedt $config_set{$2} = $1; 2869cf79fab6SSteven Rostedt $config_off{$2} = $1; 28700a05c769SSteven Rostedt } 28710a05c769SSteven Rostedt } 28720a05c769SSteven Rostedt close(IN); 28730a05c769SSteven Rostedt 28740a05c769SSteven Rostedt my @confs = keys %removed_configs; 28750a05c769SSteven Rostedt if ($#confs >= 0) { 28760a05c769SSteven Rostedt doprint "Configs overridden by default configs and removed from check:\n"; 28770a05c769SSteven Rostedt foreach my $config (@confs) { 28780a05c769SSteven Rostedt doprint " $config\n"; 28790a05c769SSteven Rostedt } 28800a05c769SSteven Rostedt } 28810a05c769SSteven Rostedt @confs = keys %added_configs; 28820a05c769SSteven Rostedt if ($#confs >= 0) { 28830a05c769SSteven Rostedt doprint "Configs appearing in make oldconfig and added:\n"; 28840a05c769SSteven Rostedt foreach my $config (@confs) { 28850a05c769SSteven Rostedt doprint " $config\n"; 28860a05c769SSteven Rostedt } 28870a05c769SSteven Rostedt } 28880a05c769SSteven Rostedt 28890a05c769SSteven Rostedt my %config_test; 28900a05c769SSteven Rostedt my $once = 0; 28910a05c769SSteven Rostedt 2892cf79fab6SSteven Rostedt @config_off_tmp = (); 2893cf79fab6SSteven Rostedt 28940a05c769SSteven Rostedt # Sometimes kconfig does weird things. We must make sure 28950a05c769SSteven Rostedt # that the config we autocreate has everything we need 28960a05c769SSteven Rostedt # to test, otherwise we may miss testing configs, or 28970a05c769SSteven Rostedt # may not be able to create a new config. 28980a05c769SSteven Rostedt # Here we create a config with everything set. 28990a05c769SSteven Rostedt create_config (keys %config_list); 29000a05c769SSteven Rostedt read_current_config \%config_test; 29010a05c769SSteven Rostedt foreach my $config (keys %config_list) { 29020a05c769SSteven Rostedt if (!defined($config_test{$config})) { 29030a05c769SSteven Rostedt if (!$once) { 29040a05c769SSteven Rostedt $once = 1; 29050a05c769SSteven Rostedt doprint "Configs not produced by kconfig (will not be checked):\n"; 29060a05c769SSteven Rostedt } 29070a05c769SSteven Rostedt doprint " $config\n"; 29080a05c769SSteven Rostedt delete $config_list{$config}; 29090a05c769SSteven Rostedt } 29100a05c769SSteven Rostedt } 29110a05c769SSteven Rostedt my $ret; 2912b0918612SSteven Rostedt 2913b0918612SSteven Rostedt if (defined($config_bisect_check) && $config_bisect_check) { 2914b0918612SSteven Rostedt doprint " Checking to make sure bad config with min config fails\n"; 2915b0918612SSteven Rostedt create_config keys %config_list; 2916b0918612SSteven Rostedt $ret = run_config_bisect_test $config_bisect_type; 2917b0918612SSteven Rostedt if ($ret) { 2918b0918612SSteven Rostedt doprint " FAILED! Bad config with min config boots fine\n"; 2919b0918612SSteven Rostedt return -1; 2920b0918612SSteven Rostedt } 2921b0918612SSteven Rostedt doprint " Bad config with min config fails as expected\n"; 2922b0918612SSteven Rostedt } 2923b0918612SSteven Rostedt 29240a05c769SSteven Rostedt do { 29250a05c769SSteven Rostedt $ret = run_config_bisect; 29260a05c769SSteven Rostedt } while (!$ret); 29270a05c769SSteven Rostedt 29280a05c769SSteven Rostedt return $ret if ($ret < 0); 29295f9b6cedSSteven Rostedt 29305f9b6cedSSteven Rostedt success $i; 29315f9b6cedSSteven Rostedt} 29325f9b6cedSSteven Rostedt 293327d934b2SSteven Rostedtsub patchcheck_reboot { 293427d934b2SSteven Rostedt doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 2935bc7c5803SSteven Rostedt reboot_to_good $patchcheck_sleep_time; 293627d934b2SSteven Rostedt} 293727d934b2SSteven Rostedt 29386c5ee0beSSteven Rostedtsub patchcheck { 29396c5ee0beSSteven Rostedt my ($i) = @_; 29406c5ee0beSSteven Rostedt 29416c5ee0beSSteven Rostedt die "PATCHCHECK_START[$i] not defined\n" 2942b5f4aea6SSteven Rostedt if (!defined($patchcheck_start)); 29436c5ee0beSSteven Rostedt die "PATCHCHECK_TYPE[$i] not defined\n" 2944b5f4aea6SSteven Rostedt if (!defined($patchcheck_type)); 29456c5ee0beSSteven Rostedt 2946b5f4aea6SSteven Rostedt my $start = $patchcheck_start; 29476c5ee0beSSteven Rostedt 29486c5ee0beSSteven Rostedt my $end = "HEAD"; 2949b5f4aea6SSteven Rostedt if (defined($patchcheck_end)) { 2950b5f4aea6SSteven Rostedt $end = $patchcheck_end; 29516c5ee0beSSteven Rostedt } 29526c5ee0beSSteven Rostedt 2953a57419b3SSteven Rostedt # Get the true sha1's since we can use things like HEAD~3 2954a57419b3SSteven Rostedt $start = get_sha1($start); 2955a57419b3SSteven Rostedt $end = get_sha1($end); 2956a57419b3SSteven Rostedt 2957b5f4aea6SSteven Rostedt my $type = $patchcheck_type; 29586c5ee0beSSteven Rostedt 29596c5ee0beSSteven Rostedt # Can't have a test without having a test to run 29606c5ee0beSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 29616c5ee0beSSteven Rostedt $type = "boot"; 29626c5ee0beSSteven Rostedt } 29636c5ee0beSSteven Rostedt 29646c5ee0beSSteven Rostedt open (IN, "git log --pretty=oneline $end|") or 29656c5ee0beSSteven Rostedt dodie "could not get git list"; 29666c5ee0beSSteven Rostedt 29676c5ee0beSSteven Rostedt my @list; 29686c5ee0beSSteven Rostedt 29696c5ee0beSSteven Rostedt while (<IN>) { 29706c5ee0beSSteven Rostedt chomp; 29716c5ee0beSSteven Rostedt $list[$#list+1] = $_; 29726c5ee0beSSteven Rostedt last if (/^$start/); 29736c5ee0beSSteven Rostedt } 29746c5ee0beSSteven Rostedt close(IN); 29756c5ee0beSSteven Rostedt 29766c5ee0beSSteven Rostedt if ($list[$#list] !~ /^$start/) { 29772b7d9b21SSteven Rostedt fail "SHA1 $start not found"; 29786c5ee0beSSteven Rostedt } 29796c5ee0beSSteven Rostedt 29806c5ee0beSSteven Rostedt # go backwards in the list 29816c5ee0beSSteven Rostedt @list = reverse @list; 29826c5ee0beSSteven Rostedt 29836c5ee0beSSteven Rostedt my $save_clean = $noclean; 29841990207dSSteven Rostedt my %ignored_warnings; 29851990207dSSteven Rostedt 29861990207dSSteven Rostedt if (defined($ignore_warnings)) { 29871990207dSSteven Rostedt foreach my $sha1 (split /\s+/, $ignore_warnings) { 29881990207dSSteven Rostedt $ignored_warnings{$sha1} = 1; 29891990207dSSteven Rostedt } 29901990207dSSteven Rostedt } 29916c5ee0beSSteven Rostedt 29926c5ee0beSSteven Rostedt $in_patchcheck = 1; 29936c5ee0beSSteven Rostedt foreach my $item (@list) { 29946c5ee0beSSteven Rostedt my $sha1 = $item; 29956c5ee0beSSteven Rostedt $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 29966c5ee0beSSteven Rostedt 29976c5ee0beSSteven Rostedt doprint "\nProcessing commit $item\n\n"; 29986c5ee0beSSteven Rostedt 29996c5ee0beSSteven Rostedt run_command "git checkout $sha1" or 30006c5ee0beSSteven Rostedt die "Failed to checkout $sha1"; 30016c5ee0beSSteven Rostedt 30026c5ee0beSSteven Rostedt # only clean on the first and last patch 30036c5ee0beSSteven Rostedt if ($item eq $list[0] || 30046c5ee0beSSteven Rostedt $item eq $list[$#list]) { 30056c5ee0beSSteven Rostedt $noclean = $save_clean; 30066c5ee0beSSteven Rostedt } else { 30076c5ee0beSSteven Rostedt $noclean = 1; 30086c5ee0beSSteven Rostedt } 30096c5ee0beSSteven Rostedt 30106c5ee0beSSteven Rostedt if (defined($minconfig)) { 30112b7d9b21SSteven Rostedt build "useconfig:$minconfig" or return 0; 30126c5ee0beSSteven Rostedt } else { 30136c5ee0beSSteven Rostedt # ?? no config to use? 30142b7d9b21SSteven Rostedt build "oldconfig" or return 0; 30156c5ee0beSSteven Rostedt } 30166c5ee0beSSteven Rostedt 30171990207dSSteven Rostedt 30181990207dSSteven Rostedt if (!defined($ignored_warnings{$sha1})) { 30192b7d9b21SSteven Rostedt check_buildlog $sha1 or return 0; 30201990207dSSteven Rostedt } 30216c5ee0beSSteven Rostedt 30226c5ee0beSSteven Rostedt next if ($type eq "build"); 30236c5ee0beSSteven Rostedt 30247faafbd6SSteven Rostedt my $failed = 0; 30257faafbd6SSteven Rostedt 3026ddf607e5SSteven Rostedt start_monitor_and_boot or $failed = 1; 30277faafbd6SSteven Rostedt 30287faafbd6SSteven Rostedt if (!$failed && $type ne "boot"){ 30297faafbd6SSteven Rostedt do_run_test or $failed = 1; 30307faafbd6SSteven Rostedt } 30317faafbd6SSteven Rostedt end_monitor; 30327faafbd6SSteven Rostedt return 0 if ($failed); 30337faafbd6SSteven Rostedt 303427d934b2SSteven Rostedt patchcheck_reboot; 303527d934b2SSteven Rostedt 30366c5ee0beSSteven Rostedt } 30376c5ee0beSSteven Rostedt $in_patchcheck = 0; 30386c5ee0beSSteven Rostedt success $i; 30392b7d9b21SSteven Rostedt 30402b7d9b21SSteven Rostedt return 1; 30416c5ee0beSSteven Rostedt} 30426c5ee0beSSteven Rostedt 3043b9066f6cSSteven Rostedtmy %depends; 3044ac6974c7SSteven Rostedtmy %depcount; 3045b9066f6cSSteven Rostedtmy $iflevel = 0; 3046b9066f6cSSteven Rostedtmy @ifdeps; 3047b9066f6cSSteven Rostedt 3048b9066f6cSSteven Rostedt# prevent recursion 3049b9066f6cSSteven Rostedtmy %read_kconfigs; 3050b9066f6cSSteven Rostedt 3051ac6974c7SSteven Rostedtsub add_dep { 3052ac6974c7SSteven Rostedt # $config depends on $dep 3053ac6974c7SSteven Rostedt my ($config, $dep) = @_; 3054ac6974c7SSteven Rostedt 3055ac6974c7SSteven Rostedt if (defined($depends{$config})) { 3056ac6974c7SSteven Rostedt $depends{$config} .= " " . $dep; 3057ac6974c7SSteven Rostedt } else { 3058ac6974c7SSteven Rostedt $depends{$config} = $dep; 3059ac6974c7SSteven Rostedt } 3060ac6974c7SSteven Rostedt 3061ac6974c7SSteven Rostedt # record the number of configs depending on $dep 3062ac6974c7SSteven Rostedt if (defined $depcount{$dep}) { 3063ac6974c7SSteven Rostedt $depcount{$dep}++; 3064ac6974c7SSteven Rostedt } else { 3065ac6974c7SSteven Rostedt $depcount{$dep} = 1; 3066ac6974c7SSteven Rostedt } 3067ac6974c7SSteven Rostedt} 3068ac6974c7SSteven Rostedt 3069b9066f6cSSteven Rostedt# taken from streamline_config.pl 3070b9066f6cSSteven Rostedtsub read_kconfig { 3071b9066f6cSSteven Rostedt my ($kconfig) = @_; 3072b9066f6cSSteven Rostedt 3073b9066f6cSSteven Rostedt my $state = "NONE"; 3074b9066f6cSSteven Rostedt my $config; 3075b9066f6cSSteven Rostedt my @kconfigs; 3076b9066f6cSSteven Rostedt 3077b9066f6cSSteven Rostedt my $cont = 0; 3078b9066f6cSSteven Rostedt my $line; 3079b9066f6cSSteven Rostedt 3080b9066f6cSSteven Rostedt 3081b9066f6cSSteven Rostedt if (! -f $kconfig) { 3082b9066f6cSSteven Rostedt doprint "file $kconfig does not exist, skipping\n"; 3083b9066f6cSSteven Rostedt return; 3084b9066f6cSSteven Rostedt } 3085b9066f6cSSteven Rostedt 3086b9066f6cSSteven Rostedt open(KIN, "$kconfig") 3087b9066f6cSSteven Rostedt or die "Can't open $kconfig"; 3088b9066f6cSSteven Rostedt while (<KIN>) { 3089b9066f6cSSteven Rostedt chomp; 3090b9066f6cSSteven Rostedt 3091b9066f6cSSteven Rostedt # Make sure that lines ending with \ continue 3092b9066f6cSSteven Rostedt if ($cont) { 3093b9066f6cSSteven Rostedt $_ = $line . " " . $_; 3094b9066f6cSSteven Rostedt } 3095b9066f6cSSteven Rostedt 3096b9066f6cSSteven Rostedt if (s/\\$//) { 3097b9066f6cSSteven Rostedt $cont = 1; 3098b9066f6cSSteven Rostedt $line = $_; 3099b9066f6cSSteven Rostedt next; 3100b9066f6cSSteven Rostedt } 3101b9066f6cSSteven Rostedt 3102b9066f6cSSteven Rostedt $cont = 0; 3103b9066f6cSSteven Rostedt 3104b9066f6cSSteven Rostedt # collect any Kconfig sources 3105b9066f6cSSteven Rostedt if (/^source\s*"(.*)"/) { 3106b9066f6cSSteven Rostedt $kconfigs[$#kconfigs+1] = $1; 3107b9066f6cSSteven Rostedt } 3108b9066f6cSSteven Rostedt 3109b9066f6cSSteven Rostedt # configs found 3110b9066f6cSSteven Rostedt if (/^\s*(menu)?config\s+(\S+)\s*$/) { 3111b9066f6cSSteven Rostedt $state = "NEW"; 3112b9066f6cSSteven Rostedt $config = $2; 3113b9066f6cSSteven Rostedt 3114b9066f6cSSteven Rostedt for (my $i = 0; $i < $iflevel; $i++) { 3115ac6974c7SSteven Rostedt add_dep $config, $ifdeps[$i]; 3116b9066f6cSSteven Rostedt } 3117b9066f6cSSteven Rostedt 3118b9066f6cSSteven Rostedt # collect the depends for the config 3119b9066f6cSSteven Rostedt } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { 3120b9066f6cSSteven Rostedt 3121ac6974c7SSteven Rostedt add_dep $config, $1; 3122b9066f6cSSteven Rostedt 3123b9066f6cSSteven Rostedt # Get the configs that select this config 3124ac6974c7SSteven Rostedt } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) { 3125ac6974c7SSteven Rostedt 3126ac6974c7SSteven Rostedt # selected by depends on config 3127ac6974c7SSteven Rostedt add_dep $1, $config; 3128b9066f6cSSteven Rostedt 3129b9066f6cSSteven Rostedt # Check for if statements 3130b9066f6cSSteven Rostedt } elsif (/^if\s+(.*\S)\s*$/) { 3131b9066f6cSSteven Rostedt my $deps = $1; 3132b9066f6cSSteven Rostedt # remove beginning and ending non text 3133b9066f6cSSteven Rostedt $deps =~ s/^[^a-zA-Z0-9_]*//; 3134b9066f6cSSteven Rostedt $deps =~ s/[^a-zA-Z0-9_]*$//; 3135b9066f6cSSteven Rostedt 3136b9066f6cSSteven Rostedt my @deps = split /[^a-zA-Z0-9_]+/, $deps; 3137b9066f6cSSteven Rostedt 3138b9066f6cSSteven Rostedt $ifdeps[$iflevel++] = join ':', @deps; 3139b9066f6cSSteven Rostedt 3140b9066f6cSSteven Rostedt } elsif (/^endif/) { 3141b9066f6cSSteven Rostedt 3142b9066f6cSSteven Rostedt $iflevel-- if ($iflevel); 3143b9066f6cSSteven Rostedt 3144b9066f6cSSteven Rostedt # stop on "help" 3145b9066f6cSSteven Rostedt } elsif (/^\s*help\s*$/) { 3146b9066f6cSSteven Rostedt $state = "NONE"; 3147b9066f6cSSteven Rostedt } 3148b9066f6cSSteven Rostedt } 3149b9066f6cSSteven Rostedt close(KIN); 3150b9066f6cSSteven Rostedt 3151b9066f6cSSteven Rostedt # read in any configs that were found. 3152b9066f6cSSteven Rostedt foreach $kconfig (@kconfigs) { 3153b9066f6cSSteven Rostedt if (!defined($read_kconfigs{$kconfig})) { 3154b9066f6cSSteven Rostedt $read_kconfigs{$kconfig} = 1; 3155b9066f6cSSteven Rostedt read_kconfig("$builddir/$kconfig"); 3156b9066f6cSSteven Rostedt } 3157b9066f6cSSteven Rostedt } 3158b9066f6cSSteven Rostedt} 3159b9066f6cSSteven Rostedt 3160b9066f6cSSteven Rostedtsub read_depends { 3161b9066f6cSSteven Rostedt # find out which arch this is by the kconfig file 3162b9066f6cSSteven Rostedt open (IN, $output_config) 3163b9066f6cSSteven Rostedt or dodie "Failed to read $output_config"; 3164b9066f6cSSteven Rostedt my $arch; 3165b9066f6cSSteven Rostedt while (<IN>) { 3166b9066f6cSSteven Rostedt if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) { 3167b9066f6cSSteven Rostedt $arch = $1; 3168b9066f6cSSteven Rostedt last; 3169b9066f6cSSteven Rostedt } 3170b9066f6cSSteven Rostedt } 3171b9066f6cSSteven Rostedt close IN; 3172b9066f6cSSteven Rostedt 3173b9066f6cSSteven Rostedt if (!defined($arch)) { 3174b9066f6cSSteven Rostedt doprint "Could not find arch from config file\n"; 3175b9066f6cSSteven Rostedt doprint "no dependencies used\n"; 3176b9066f6cSSteven Rostedt return; 3177b9066f6cSSteven Rostedt } 3178b9066f6cSSteven Rostedt 3179b9066f6cSSteven Rostedt # arch is really the subarch, we need to know 3180b9066f6cSSteven Rostedt # what directory to look at. 3181b9066f6cSSteven Rostedt if ($arch eq "i386" || $arch eq "x86_64") { 3182b9066f6cSSteven Rostedt $arch = "x86"; 3183b9066f6cSSteven Rostedt } elsif ($arch =~ /^tile/) { 3184b9066f6cSSteven Rostedt $arch = "tile"; 3185b9066f6cSSteven Rostedt } 3186b9066f6cSSteven Rostedt 3187b9066f6cSSteven Rostedt my $kconfig = "$builddir/arch/$arch/Kconfig"; 3188b9066f6cSSteven Rostedt 3189b9066f6cSSteven Rostedt if (! -f $kconfig && $arch =~ /\d$/) { 3190b9066f6cSSteven Rostedt my $orig = $arch; 3191b9066f6cSSteven Rostedt # some subarchs have numbers, truncate them 3192b9066f6cSSteven Rostedt $arch =~ s/\d*$//; 3193b9066f6cSSteven Rostedt $kconfig = "$builddir/arch/$arch/Kconfig"; 3194b9066f6cSSteven Rostedt if (! -f $kconfig) { 3195b9066f6cSSteven Rostedt doprint "No idea what arch dir $orig is for\n"; 3196b9066f6cSSteven Rostedt doprint "no dependencies used\n"; 3197b9066f6cSSteven Rostedt return; 3198b9066f6cSSteven Rostedt } 3199b9066f6cSSteven Rostedt } 3200b9066f6cSSteven Rostedt 3201b9066f6cSSteven Rostedt read_kconfig($kconfig); 3202b9066f6cSSteven Rostedt} 3203b9066f6cSSteven Rostedt 32044c4ab120SSteven Rostedtsub read_config_list { 32054c4ab120SSteven Rostedt my ($config) = @_; 32064c4ab120SSteven Rostedt 32074c4ab120SSteven Rostedt open (IN, $config) 32084c4ab120SSteven Rostedt or dodie "Failed to read $config"; 32094c4ab120SSteven Rostedt 32104c4ab120SSteven Rostedt while (<IN>) { 32114c4ab120SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 32124c4ab120SSteven Rostedt if (!defined($config_ignore{$2})) { 32134c4ab120SSteven Rostedt $config_list{$2} = $1; 32144c4ab120SSteven Rostedt } 32154c4ab120SSteven Rostedt } 32164c4ab120SSteven Rostedt } 32174c4ab120SSteven Rostedt 32184c4ab120SSteven Rostedt close(IN); 32194c4ab120SSteven Rostedt} 32204c4ab120SSteven Rostedt 32214c4ab120SSteven Rostedtsub read_output_config { 32224c4ab120SSteven Rostedt my ($config) = @_; 32234c4ab120SSteven Rostedt 32244c4ab120SSteven Rostedt assign_configs \%config_ignore, $config; 32254c4ab120SSteven Rostedt} 32264c4ab120SSteven Rostedt 32274c4ab120SSteven Rostedtsub make_new_config { 32284c4ab120SSteven Rostedt my @configs = @_; 32294c4ab120SSteven Rostedt 32304c4ab120SSteven Rostedt open (OUT, ">$output_config") 32314c4ab120SSteven Rostedt or dodie "Failed to write $output_config"; 32324c4ab120SSteven Rostedt 32334c4ab120SSteven Rostedt foreach my $config (@configs) { 32344c4ab120SSteven Rostedt print OUT "$config\n"; 32354c4ab120SSteven Rostedt } 32364c4ab120SSteven Rostedt close OUT; 32374c4ab120SSteven Rostedt} 32384c4ab120SSteven Rostedt 3239ac6974c7SSteven Rostedtsub chomp_config { 3240ac6974c7SSteven Rostedt my ($config) = @_; 3241ac6974c7SSteven Rostedt 3242ac6974c7SSteven Rostedt $config =~ s/CONFIG_//; 3243ac6974c7SSteven Rostedt 3244ac6974c7SSteven Rostedt return $config; 3245ac6974c7SSteven Rostedt} 3246ac6974c7SSteven Rostedt 3247b9066f6cSSteven Rostedtsub get_depends { 3248b9066f6cSSteven Rostedt my ($dep) = @_; 3249b9066f6cSSteven Rostedt 3250ac6974c7SSteven Rostedt my $kconfig = chomp_config $dep; 3251b9066f6cSSteven Rostedt 3252b9066f6cSSteven Rostedt $dep = $depends{"$kconfig"}; 3253b9066f6cSSteven Rostedt 3254b9066f6cSSteven Rostedt # the dep string we have saves the dependencies as they 3255b9066f6cSSteven Rostedt # were found, including expressions like ! && ||. We 3256b9066f6cSSteven Rostedt # want to split this out into just an array of configs. 3257b9066f6cSSteven Rostedt 3258b9066f6cSSteven Rostedt my $valid = "A-Za-z_0-9"; 3259b9066f6cSSteven Rostedt 3260b9066f6cSSteven Rostedt my @configs; 3261b9066f6cSSteven Rostedt 3262b9066f6cSSteven Rostedt while ($dep =~ /[$valid]/) { 3263b9066f6cSSteven Rostedt 3264b9066f6cSSteven Rostedt if ($dep =~ /^[^$valid]*([$valid]+)/) { 3265b9066f6cSSteven Rostedt my $conf = "CONFIG_" . $1; 3266b9066f6cSSteven Rostedt 3267b9066f6cSSteven Rostedt $configs[$#configs + 1] = $conf; 3268b9066f6cSSteven Rostedt 3269b9066f6cSSteven Rostedt $dep =~ s/^[^$valid]*[$valid]+//; 3270b9066f6cSSteven Rostedt } else { 3271b9066f6cSSteven Rostedt die "this should never happen"; 3272b9066f6cSSteven Rostedt } 3273b9066f6cSSteven Rostedt } 3274b9066f6cSSteven Rostedt 3275b9066f6cSSteven Rostedt return @configs; 3276b9066f6cSSteven Rostedt} 3277b9066f6cSSteven Rostedt 3278b9066f6cSSteven Rostedtmy %min_configs; 3279b9066f6cSSteven Rostedtmy %keep_configs; 328043d1b651SSteven Rostedtmy %save_configs; 3281b9066f6cSSteven Rostedtmy %processed_configs; 3282b9066f6cSSteven Rostedtmy %nochange_config; 3283b9066f6cSSteven Rostedt 3284b9066f6cSSteven Rostedtsub test_this_config { 3285b9066f6cSSteven Rostedt my ($config) = @_; 3286b9066f6cSSteven Rostedt 3287b9066f6cSSteven Rostedt my $found; 3288b9066f6cSSteven Rostedt 3289b9066f6cSSteven Rostedt # if we already processed this config, skip it 3290b9066f6cSSteven Rostedt if (defined($processed_configs{$config})) { 3291b9066f6cSSteven Rostedt return undef; 3292b9066f6cSSteven Rostedt } 3293b9066f6cSSteven Rostedt $processed_configs{$config} = 1; 3294b9066f6cSSteven Rostedt 3295b9066f6cSSteven Rostedt # if this config failed during this round, skip it 3296b9066f6cSSteven Rostedt if (defined($nochange_config{$config})) { 3297b9066f6cSSteven Rostedt return undef; 3298b9066f6cSSteven Rostedt } 3299b9066f6cSSteven Rostedt 3300ac6974c7SSteven Rostedt my $kconfig = chomp_config $config; 3301b9066f6cSSteven Rostedt 3302b9066f6cSSteven Rostedt # Test dependencies first 3303b9066f6cSSteven Rostedt if (defined($depends{"$kconfig"})) { 3304b9066f6cSSteven Rostedt my @parents = get_depends $config; 3305b9066f6cSSteven Rostedt foreach my $parent (@parents) { 3306b9066f6cSSteven Rostedt # if the parent is in the min config, check it first 3307b9066f6cSSteven Rostedt next if (!defined($min_configs{$parent})); 3308b9066f6cSSteven Rostedt $found = test_this_config($parent); 3309b9066f6cSSteven Rostedt if (defined($found)) { 3310b9066f6cSSteven Rostedt return $found; 3311b9066f6cSSteven Rostedt } 3312b9066f6cSSteven Rostedt } 3313b9066f6cSSteven Rostedt } 3314b9066f6cSSteven Rostedt 3315b9066f6cSSteven Rostedt # Remove this config from the list of configs 3316fb16d891SAdam Lee # do a make olddefconfig and then read the resulting 3317b9066f6cSSteven Rostedt # .config to make sure it is missing the config that 3318b9066f6cSSteven Rostedt # we had before 3319b9066f6cSSteven Rostedt my %configs = %min_configs; 3320b9066f6cSSteven Rostedt delete $configs{$config}; 3321b9066f6cSSteven Rostedt make_new_config ((values %configs), (values %keep_configs)); 3322b9066f6cSSteven Rostedt make_oldconfig; 3323b9066f6cSSteven Rostedt undef %configs; 3324b9066f6cSSteven Rostedt assign_configs \%configs, $output_config; 3325b9066f6cSSteven Rostedt 3326b9066f6cSSteven Rostedt return $config if (!defined($configs{$config})); 3327b9066f6cSSteven Rostedt 3328b9066f6cSSteven Rostedt doprint "disabling config $config did not change .config\n"; 3329b9066f6cSSteven Rostedt 3330b9066f6cSSteven Rostedt $nochange_config{$config} = 1; 3331b9066f6cSSteven Rostedt 3332b9066f6cSSteven Rostedt return undef; 3333b9066f6cSSteven Rostedt} 3334b9066f6cSSteven Rostedt 33354c4ab120SSteven Rostedtsub make_min_config { 33364c4ab120SSteven Rostedt my ($i) = @_; 33374c4ab120SSteven Rostedt 3338ccc513b6SSteven Rostedt my $type = $minconfig_type; 3339ccc513b6SSteven Rostedt if ($type ne "boot" && $type ne "test") { 3340ccc513b6SSteven Rostedt fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" . 3341ccc513b6SSteven Rostedt " make_min_config works only with 'boot' and 'test'\n" and return; 3342ccc513b6SSteven Rostedt } 3343ccc513b6SSteven Rostedt 33444c4ab120SSteven Rostedt if (!defined($output_minconfig)) { 33454c4ab120SSteven Rostedt fail "OUTPUT_MIN_CONFIG not defined" and return; 33464c4ab120SSteven Rostedt } 334735ce5952SSteven Rostedt 334835ce5952SSteven Rostedt # If output_minconfig exists, and the start_minconfig 334935ce5952SSteven Rostedt # came from min_config, than ask if we should use 335035ce5952SSteven Rostedt # that instead. 335135ce5952SSteven Rostedt if (-f $output_minconfig && !$start_minconfig_defined) { 335235ce5952SSteven Rostedt print "$output_minconfig exists\n"; 335343de3316SSteven Rostedt if (!defined($use_output_minconfig)) { 335435ce5952SSteven Rostedt if (read_yn " Use it as minconfig?") { 335535ce5952SSteven Rostedt $start_minconfig = $output_minconfig; 335635ce5952SSteven Rostedt } 335743de3316SSteven Rostedt } elsif ($use_output_minconfig > 0) { 335843de3316SSteven Rostedt doprint "Using $output_minconfig as MIN_CONFIG\n"; 335943de3316SSteven Rostedt $start_minconfig = $output_minconfig; 336043de3316SSteven Rostedt } else { 336143de3316SSteven Rostedt doprint "Set to still use MIN_CONFIG as starting point\n"; 336243de3316SSteven Rostedt } 336335ce5952SSteven Rostedt } 336435ce5952SSteven Rostedt 33654c4ab120SSteven Rostedt if (!defined($start_minconfig)) { 33664c4ab120SSteven Rostedt fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; 33674c4ab120SSteven Rostedt } 33684c4ab120SSteven Rostedt 336935ce5952SSteven Rostedt my $temp_config = "$tmpdir/temp_config"; 337035ce5952SSteven Rostedt 33714c4ab120SSteven Rostedt # First things first. We build an allnoconfig to find 33724c4ab120SSteven Rostedt # out what the defaults are that we can't touch. 33734c4ab120SSteven Rostedt # Some are selections, but we really can't handle selections. 33744c4ab120SSteven Rostedt 33754c4ab120SSteven Rostedt my $save_minconfig = $minconfig; 33764c4ab120SSteven Rostedt undef $minconfig; 33774c4ab120SSteven Rostedt 33784c4ab120SSteven Rostedt run_command "$make allnoconfig" or return 0; 33794c4ab120SSteven Rostedt 3380b9066f6cSSteven Rostedt read_depends; 3381b9066f6cSSteven Rostedt 33824c4ab120SSteven Rostedt process_config_ignore $output_config; 3383b9066f6cSSteven Rostedt 338443d1b651SSteven Rostedt undef %save_configs; 3385b9066f6cSSteven Rostedt undef %min_configs; 33864c4ab120SSteven Rostedt 33874c4ab120SSteven Rostedt if (defined($ignore_config)) { 33884c4ab120SSteven Rostedt # make sure the file exists 33894c4ab120SSteven Rostedt `touch $ignore_config`; 339043d1b651SSteven Rostedt assign_configs \%save_configs, $ignore_config; 33914c4ab120SSteven Rostedt } 33924c4ab120SSteven Rostedt 339343d1b651SSteven Rostedt %keep_configs = %save_configs; 339443d1b651SSteven Rostedt 33954c4ab120SSteven Rostedt doprint "Load initial configs from $start_minconfig\n"; 33964c4ab120SSteven Rostedt 33974c4ab120SSteven Rostedt # Look at the current min configs, and save off all the 33984c4ab120SSteven Rostedt # ones that were set via the allnoconfig 33994c4ab120SSteven Rostedt assign_configs \%min_configs, $start_minconfig; 34004c4ab120SSteven Rostedt 34014c4ab120SSteven Rostedt my @config_keys = keys %min_configs; 34024c4ab120SSteven Rostedt 3403ac6974c7SSteven Rostedt # All configs need a depcount 3404ac6974c7SSteven Rostedt foreach my $config (@config_keys) { 3405ac6974c7SSteven Rostedt my $kconfig = chomp_config $config; 3406ac6974c7SSteven Rostedt if (!defined $depcount{$kconfig}) { 3407ac6974c7SSteven Rostedt $depcount{$kconfig} = 0; 3408ac6974c7SSteven Rostedt } 3409ac6974c7SSteven Rostedt } 3410ac6974c7SSteven Rostedt 34114c4ab120SSteven Rostedt # Remove anything that was set by the make allnoconfig 34124c4ab120SSteven Rostedt # we shouldn't need them as they get set for us anyway. 34134c4ab120SSteven Rostedt foreach my $config (@config_keys) { 34144c4ab120SSteven Rostedt # Remove anything in the ignore_config 34154c4ab120SSteven Rostedt if (defined($keep_configs{$config})) { 34164c4ab120SSteven Rostedt my $file = $ignore_config; 34174c4ab120SSteven Rostedt $file =~ s,.*/(.*?)$,$1,; 34184c4ab120SSteven Rostedt doprint "$config set by $file ... ignored\n"; 34194c4ab120SSteven Rostedt delete $min_configs{$config}; 34204c4ab120SSteven Rostedt next; 34214c4ab120SSteven Rostedt } 34224c4ab120SSteven Rostedt # But make sure the settings are the same. If a min config 34234c4ab120SSteven Rostedt # sets a selection, we do not want to get rid of it if 34244c4ab120SSteven Rostedt # it is not the same as what we have. Just move it into 34254c4ab120SSteven Rostedt # the keep configs. 34264c4ab120SSteven Rostedt if (defined($config_ignore{$config})) { 34274c4ab120SSteven Rostedt if ($config_ignore{$config} ne $min_configs{$config}) { 34284c4ab120SSteven Rostedt doprint "$config is in allnoconfig as '$config_ignore{$config}'"; 34294c4ab120SSteven Rostedt doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n"; 34304c4ab120SSteven Rostedt $keep_configs{$config} = $min_configs{$config}; 34314c4ab120SSteven Rostedt } else { 34324c4ab120SSteven Rostedt doprint "$config set by allnoconfig ... ignored\n"; 34334c4ab120SSteven Rostedt } 34344c4ab120SSteven Rostedt delete $min_configs{$config}; 34354c4ab120SSteven Rostedt } 34364c4ab120SSteven Rostedt } 34374c4ab120SSteven Rostedt 34384c4ab120SSteven Rostedt my $done = 0; 3439b9066f6cSSteven Rostedt my $take_two = 0; 34404c4ab120SSteven Rostedt 34414c4ab120SSteven Rostedt while (!$done) { 34424c4ab120SSteven Rostedt 34434c4ab120SSteven Rostedt my $config; 34444c4ab120SSteven Rostedt my $found; 34454c4ab120SSteven Rostedt 34464c4ab120SSteven Rostedt # Now disable each config one by one and do a make oldconfig 34474c4ab120SSteven Rostedt # till we find a config that changes our list. 34484c4ab120SSteven Rostedt 34494c4ab120SSteven Rostedt my @test_configs = keys %min_configs; 3450ac6974c7SSteven Rostedt 3451ac6974c7SSteven Rostedt # Sort keys by who is most dependent on 3452ac6974c7SSteven Rostedt @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} } 3453ac6974c7SSteven Rostedt @test_configs ; 3454ac6974c7SSteven Rostedt 3455ac6974c7SSteven Rostedt # Put configs that did not modify the config at the end. 34564c4ab120SSteven Rostedt my $reset = 1; 34574c4ab120SSteven Rostedt for (my $i = 0; $i < $#test_configs; $i++) { 34584c4ab120SSteven Rostedt if (!defined($nochange_config{$test_configs[0]})) { 34594c4ab120SSteven Rostedt $reset = 0; 34604c4ab120SSteven Rostedt last; 34614c4ab120SSteven Rostedt } 34624c4ab120SSteven Rostedt # This config didn't change the .config last time. 34634c4ab120SSteven Rostedt # Place it at the end 34644c4ab120SSteven Rostedt my $config = shift @test_configs; 34654c4ab120SSteven Rostedt push @test_configs, $config; 34664c4ab120SSteven Rostedt } 34674c4ab120SSteven Rostedt 34684c4ab120SSteven Rostedt # if every test config has failed to modify the .config file 34694c4ab120SSteven Rostedt # in the past, then reset and start over. 34704c4ab120SSteven Rostedt if ($reset) { 34714c4ab120SSteven Rostedt undef %nochange_config; 34724c4ab120SSteven Rostedt } 34734c4ab120SSteven Rostedt 3474b9066f6cSSteven Rostedt undef %processed_configs; 3475b9066f6cSSteven Rostedt 34764c4ab120SSteven Rostedt foreach my $config (@test_configs) { 34774c4ab120SSteven Rostedt 3478b9066f6cSSteven Rostedt $found = test_this_config $config; 34794c4ab120SSteven Rostedt 3480b9066f6cSSteven Rostedt last if (defined($found)); 34814c4ab120SSteven Rostedt 34824c4ab120SSteven Rostedt # oh well, try another config 34834c4ab120SSteven Rostedt } 34844c4ab120SSteven Rostedt 34854c4ab120SSteven Rostedt if (!defined($found)) { 3486b9066f6cSSteven Rostedt # we could have failed due to the nochange_config hash 3487b9066f6cSSteven Rostedt # reset and try again 3488b9066f6cSSteven Rostedt if (!$take_two) { 3489b9066f6cSSteven Rostedt undef %nochange_config; 3490b9066f6cSSteven Rostedt $take_two = 1; 3491b9066f6cSSteven Rostedt next; 3492b9066f6cSSteven Rostedt } 34934c4ab120SSteven Rostedt doprint "No more configs found that we can disable\n"; 34944c4ab120SSteven Rostedt $done = 1; 34954c4ab120SSteven Rostedt last; 34964c4ab120SSteven Rostedt } 3497b9066f6cSSteven Rostedt $take_two = 0; 34984c4ab120SSteven Rostedt 34994c4ab120SSteven Rostedt $config = $found; 35004c4ab120SSteven Rostedt 35014c4ab120SSteven Rostedt doprint "Test with $config disabled\n"; 35024c4ab120SSteven Rostedt 35034c4ab120SSteven Rostedt # set in_bisect to keep build and monitor from dieing 35044c4ab120SSteven Rostedt $in_bisect = 1; 35054c4ab120SSteven Rostedt 35064c4ab120SSteven Rostedt my $failed = 0; 3507bf1c95abSSteven Rostedt build "oldconfig" or $failed = 1; 3508bf1c95abSSteven Rostedt if (!$failed) { 35094c4ab120SSteven Rostedt start_monitor_and_boot or $failed = 1; 3510ccc513b6SSteven Rostedt 3511ccc513b6SSteven Rostedt if ($type eq "test" && !$failed) { 3512ccc513b6SSteven Rostedt do_run_test or $failed = 1; 3513ccc513b6SSteven Rostedt } 3514ccc513b6SSteven Rostedt 35154c4ab120SSteven Rostedt end_monitor; 3516bf1c95abSSteven Rostedt } 35174c4ab120SSteven Rostedt 35184c4ab120SSteven Rostedt $in_bisect = 0; 35194c4ab120SSteven Rostedt 35204c4ab120SSteven Rostedt if ($failed) { 3521b9066f6cSSteven Rostedt doprint "$min_configs{$config} is needed to boot the box... keeping\n"; 35224c4ab120SSteven Rostedt # this config is needed, add it to the ignore list. 35234c4ab120SSteven Rostedt $keep_configs{$config} = $min_configs{$config}; 352443d1b651SSteven Rostedt $save_configs{$config} = $min_configs{$config}; 35254c4ab120SSteven Rostedt delete $min_configs{$config}; 352635ce5952SSteven Rostedt 352735ce5952SSteven Rostedt # update new ignore configs 352835ce5952SSteven Rostedt if (defined($ignore_config)) { 352935ce5952SSteven Rostedt open (OUT, ">$temp_config") 353035ce5952SSteven Rostedt or die "Can't write to $temp_config"; 353143d1b651SSteven Rostedt foreach my $config (keys %save_configs) { 353243d1b651SSteven Rostedt print OUT "$save_configs{$config}\n"; 353335ce5952SSteven Rostedt } 353435ce5952SSteven Rostedt close OUT; 353535ce5952SSteven Rostedt run_command "mv $temp_config $ignore_config" or 353635ce5952SSteven Rostedt dodie "failed to copy update to $ignore_config"; 353735ce5952SSteven Rostedt } 353835ce5952SSteven Rostedt 35394c4ab120SSteven Rostedt } else { 35404c4ab120SSteven Rostedt # We booted without this config, remove it from the minconfigs. 35414c4ab120SSteven Rostedt doprint "$config is not needed, disabling\n"; 35424c4ab120SSteven Rostedt 35434c4ab120SSteven Rostedt delete $min_configs{$config}; 35444c4ab120SSteven Rostedt 35454c4ab120SSteven Rostedt # Also disable anything that is not enabled in this config 35464c4ab120SSteven Rostedt my %configs; 35474c4ab120SSteven Rostedt assign_configs \%configs, $output_config; 35484c4ab120SSteven Rostedt my @config_keys = keys %min_configs; 35494c4ab120SSteven Rostedt foreach my $config (@config_keys) { 35504c4ab120SSteven Rostedt if (!defined($configs{$config})) { 35514c4ab120SSteven Rostedt doprint "$config is not set, disabling\n"; 35524c4ab120SSteven Rostedt delete $min_configs{$config}; 35534c4ab120SSteven Rostedt } 35544c4ab120SSteven Rostedt } 35554c4ab120SSteven Rostedt 35564c4ab120SSteven Rostedt # Save off all the current mandidory configs 355735ce5952SSteven Rostedt open (OUT, ">$temp_config") 355835ce5952SSteven Rostedt or die "Can't write to $temp_config"; 35594c4ab120SSteven Rostedt foreach my $config (keys %keep_configs) { 35604c4ab120SSteven Rostedt print OUT "$keep_configs{$config}\n"; 35614c4ab120SSteven Rostedt } 35624c4ab120SSteven Rostedt foreach my $config (keys %min_configs) { 35634c4ab120SSteven Rostedt print OUT "$min_configs{$config}\n"; 35644c4ab120SSteven Rostedt } 35654c4ab120SSteven Rostedt close OUT; 356635ce5952SSteven Rostedt 356735ce5952SSteven Rostedt run_command "mv $temp_config $output_minconfig" or 356835ce5952SSteven Rostedt dodie "failed to copy update to $output_minconfig"; 35694c4ab120SSteven Rostedt } 35704c4ab120SSteven Rostedt 35714c4ab120SSteven Rostedt doprint "Reboot and wait $sleep_time seconds\n"; 3572bc7c5803SSteven Rostedt reboot_to_good $sleep_time; 35734c4ab120SSteven Rostedt } 35744c4ab120SSteven Rostedt 35754c4ab120SSteven Rostedt success $i; 35764c4ab120SSteven Rostedt return 1; 35774c4ab120SSteven Rostedt} 35784c4ab120SSteven Rostedt 35798d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 35802545eb61SSteven Rostedt 35818d1491baSSteven Rostedtif ($#ARGV == 0) { 35828d1491baSSteven Rostedt $ktest_config = $ARGV[0]; 35838d1491baSSteven Rostedt if (! -f $ktest_config) { 35848d1491baSSteven Rostedt print "$ktest_config does not exist.\n"; 358535ce5952SSteven Rostedt if (!read_yn "Create it?") { 35868d1491baSSteven Rostedt exit 0; 35878d1491baSSteven Rostedt } 35888d1491baSSteven Rostedt } 35898d1491baSSteven Rostedt} else { 35908d1491baSSteven Rostedt $ktest_config = "ktest.conf"; 35918d1491baSSteven Rostedt} 35928d1491baSSteven Rostedt 35938d1491baSSteven Rostedtif (! -f $ktest_config) { 3594dbd3783bSSteven Rostedt $newconfig = 1; 3595c4261d0fSSteven Rostedt get_test_case; 35968d1491baSSteven Rostedt open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 35978d1491baSSteven Rostedt print OUT << "EOF" 35988d1491baSSteven Rostedt# Generated by ktest.pl 35998d1491baSSteven Rostedt# 36000e7a22deSSteven Rostedt 36010e7a22deSSteven Rostedt# PWD is a ktest.pl variable that will result in the process working 36020e7a22deSSteven Rostedt# directory that ktest.pl is executed in. 36030e7a22deSSteven Rostedt 36040e7a22deSSteven Rostedt# THIS_DIR is automatically assigned the PWD of the path that generated 36050e7a22deSSteven Rostedt# the config file. It is best to use this variable when assigning other 36060e7a22deSSteven Rostedt# directory paths within this directory. This allows you to easily 36070e7a22deSSteven Rostedt# move the test cases to other locations or to other machines. 36080e7a22deSSteven Rostedt# 36090e7a22deSSteven RostedtTHIS_DIR := $variable{"PWD"} 36100e7a22deSSteven Rostedt 36118d1491baSSteven Rostedt# Define each test with TEST_START 36128d1491baSSteven Rostedt# The config options below it will override the defaults 36138d1491baSSteven RostedtTEST_START 3614c4261d0fSSteven RostedtTEST_TYPE = $default{"TEST_TYPE"} 36158d1491baSSteven Rostedt 36168d1491baSSteven RostedtDEFAULTS 36178d1491baSSteven RostedtEOF 36188d1491baSSteven Rostedt; 36198d1491baSSteven Rostedt close(OUT); 36208d1491baSSteven Rostedt} 36218d1491baSSteven Rostedtread_config $ktest_config; 36228d1491baSSteven Rostedt 362323715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) { 362423715c3cSSteven Rostedt $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1); 362523715c3cSSteven Rostedt} 362623715c3cSSteven Rostedt 36278d1491baSSteven Rostedt# Append any configs entered in manually to the config file. 36288d1491baSSteven Rostedtmy @new_configs = keys %entered_configs; 36298d1491baSSteven Rostedtif ($#new_configs >= 0) { 36308d1491baSSteven Rostedt print "\nAppending entered in configs to $ktest_config\n"; 36318d1491baSSteven Rostedt open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 36328d1491baSSteven Rostedt foreach my $config (@new_configs) { 36338d1491baSSteven Rostedt print OUT "$config = $entered_configs{$config}\n"; 36340e7a22deSSteven Rostedt $opt{$config} = process_variables($entered_configs{$config}); 36358d1491baSSteven Rostedt } 36368d1491baSSteven Rostedt} 36372545eb61SSteven Rostedt 36382b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 36392b7d9b21SSteven Rostedt unlink $opt{"LOG_FILE"}; 36402b7d9b21SSteven Rostedt} 36412545eb61SSteven Rostedt 36422b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 36432b7d9b21SSteven Rostedt 3644a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 3645a57419b3SSteven Rostedt 3646a57419b3SSteven Rostedt if (!$i) { 3647a57419b3SSteven Rostedt doprint "DEFAULT OPTIONS:\n"; 3648a57419b3SSteven Rostedt } else { 3649a57419b3SSteven Rostedt doprint "\nTEST $i OPTIONS"; 3650a57419b3SSteven Rostedt if (defined($repeat_tests{$i})) { 3651a57419b3SSteven Rostedt $repeat = $repeat_tests{$i}; 3652a57419b3SSteven Rostedt doprint " ITERATE $repeat"; 3653a57419b3SSteven Rostedt } 3654a57419b3SSteven Rostedt doprint "\n"; 3655a57419b3SSteven Rostedt } 3656a57419b3SSteven Rostedt 36572b7d9b21SSteven Rostedt foreach my $option (sort keys %opt) { 3658a57419b3SSteven Rostedt 3659a57419b3SSteven Rostedt if ($option =~ /\[(\d+)\]$/) { 3660a57419b3SSteven Rostedt next if ($i != $1); 3661a57419b3SSteven Rostedt } else { 3662a57419b3SSteven Rostedt next if ($i); 3663a57419b3SSteven Rostedt } 3664a57419b3SSteven Rostedt 36652b7d9b21SSteven Rostedt doprint "$option = $opt{$option}\n"; 36662b7d9b21SSteven Rostedt } 3667a57419b3SSteven Rostedt} 36682545eb61SSteven Rostedt 36692a62512bSSteven Rostedtsub __set_test_option { 36705a391fbfSSteven Rostedt my ($name, $i) = @_; 36715a391fbfSSteven Rostedt 36725a391fbfSSteven Rostedt my $option = "$name\[$i\]"; 36735a391fbfSSteven Rostedt 36745a391fbfSSteven Rostedt if (defined($opt{$option})) { 36755a391fbfSSteven Rostedt return $opt{$option}; 36765a391fbfSSteven Rostedt } 36775a391fbfSSteven Rostedt 3678a57419b3SSteven Rostedt foreach my $test (keys %repeat_tests) { 3679a57419b3SSteven Rostedt if ($i >= $test && 3680a57419b3SSteven Rostedt $i < $test + $repeat_tests{$test}) { 3681a57419b3SSteven Rostedt $option = "$name\[$test\]"; 3682a57419b3SSteven Rostedt if (defined($opt{$option})) { 3683a57419b3SSteven Rostedt return $opt{$option}; 3684a57419b3SSteven Rostedt } 3685a57419b3SSteven Rostedt } 3686a57419b3SSteven Rostedt } 3687a57419b3SSteven Rostedt 36885a391fbfSSteven Rostedt if (defined($opt{$name})) { 36895a391fbfSSteven Rostedt return $opt{$name}; 36905a391fbfSSteven Rostedt } 36915a391fbfSSteven Rostedt 36925a391fbfSSteven Rostedt return undef; 36935a391fbfSSteven Rostedt} 36945a391fbfSSteven Rostedt 36952a62512bSSteven Rostedtsub set_test_option { 36962a62512bSSteven Rostedt my ($name, $i) = @_; 36972a62512bSSteven Rostedt 36982a62512bSSteven Rostedt my $option = __set_test_option($name, $i); 36992a62512bSSteven Rostedt return $option if (!defined($option)); 37002a62512bSSteven Rostedt 370123715c3cSSteven Rostedt return eval_option($option, $i); 37022a62512bSSteven Rostedt} 37032a62512bSSteven Rostedt 37042545eb61SSteven Rostedt# First we need to do is the builds 3705a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 37062545eb61SSteven Rostedt 37074ab1cce5SSteven Rostedt # Do not reboot on failing test options 37084ab1cce5SSteven Rostedt $no_reboot = 1; 3709759a3cc6SSteven Rostedt $reboot_success = 0; 37104ab1cce5SSteven Rostedt 3711683a3e64SSteven Rostedt $have_version = 0; 3712683a3e64SSteven Rostedt 3713576f627cSSteven Rostedt $iteration = $i; 3714576f627cSSteven Rostedt 3715c1434dccSSteven Rostedt undef %force_config; 3716c1434dccSSteven Rostedt 3717a75fececSSteven Rostedt my $makecmd = set_test_option("MAKE_CMD", $i); 3718a75fececSSteven Rostedt 37199cc9e091SSteven Rostedt # Load all the options into their mapped variable names 37209cc9e091SSteven Rostedt foreach my $opt (keys %option_map) { 37219cc9e091SSteven Rostedt ${$option_map{$opt}} = set_test_option($opt, $i); 37229cc9e091SSteven Rostedt } 3723b5f4aea6SSteven Rostedt 372435ce5952SSteven Rostedt $start_minconfig_defined = 1; 372535ce5952SSteven Rostedt 3726921ed4c7SSteven Rostedt # The first test may override the PRE_KTEST option 3727921ed4c7SSteven Rostedt if (defined($pre_ktest) && $i == 1) { 3728921ed4c7SSteven Rostedt doprint "\n"; 3729921ed4c7SSteven Rostedt run_command $pre_ktest; 3730921ed4c7SSteven Rostedt } 3731921ed4c7SSteven Rostedt 3732921ed4c7SSteven Rostedt # Any test can override the POST_KTEST option 3733921ed4c7SSteven Rostedt # The last test takes precedence. 3734921ed4c7SSteven Rostedt if (defined($post_ktest)) { 3735921ed4c7SSteven Rostedt $final_post_ktest = $post_ktest; 3736921ed4c7SSteven Rostedt } 3737921ed4c7SSteven Rostedt 37384c4ab120SSteven Rostedt if (!defined($start_minconfig)) { 373935ce5952SSteven Rostedt $start_minconfig_defined = 0; 37404c4ab120SSteven Rostedt $start_minconfig = $minconfig; 37414c4ab120SSteven Rostedt } 37424c4ab120SSteven Rostedt 3743a75fececSSteven Rostedt chdir $builddir || die "can't change directory to $builddir"; 3744a75fececSSteven Rostedt 3745a908a665SAndrew Jones foreach my $dir ($tmpdir, $outputdir) { 3746a908a665SAndrew Jones if (!-d $dir) { 3747a908a665SAndrew Jones mkpath($dir) or 3748a908a665SAndrew Jones die "can't create $dir"; 3749a908a665SAndrew Jones } 3750a75fececSSteven Rostedt } 3751a75fececSSteven Rostedt 3752e48c5293SSteven Rostedt $ENV{"SSH_USER"} = $ssh_user; 3753e48c5293SSteven Rostedt $ENV{"MACHINE"} = $machine; 3754e48c5293SSteven Rostedt 3755a75fececSSteven Rostedt $buildlog = "$tmpdir/buildlog-$machine"; 3756a9dd5d63SRabin Vincent $testlog = "$tmpdir/testlog-$machine"; 3757a75fececSSteven Rostedt $dmesg = "$tmpdir/dmesg-$machine"; 3758a75fececSSteven Rostedt $make = "$makecmd O=$outputdir"; 375951ad1dd1SSteven Rostedt $output_config = "$outputdir/.config"; 3760a75fececSSteven Rostedt 3761bb8474b1SSteven Rostedt if (!$buildonly) { 3762bb8474b1SSteven Rostedt $target = "$ssh_user\@$machine"; 3763a75fececSSteven Rostedt if ($reboot_type eq "grub") { 3764576f627cSSteven Rostedt dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 3765*a15ba913SSteven Rostedt } elsif ($reboot_type eq "grub2") { 3766*a15ba913SSteven Rostedt dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 3767*a15ba913SSteven Rostedt dodie "GRUB_FILE not defined" if (!defined($grub_file)); 3768a75fececSSteven Rostedt } 3769bb8474b1SSteven Rostedt } 3770a75fececSSteven Rostedt 3771a75fececSSteven Rostedt my $run_type = $build_type; 3772a75fececSSteven Rostedt if ($test_type eq "patchcheck") { 3773b5f4aea6SSteven Rostedt $run_type = $patchcheck_type; 3774a75fececSSteven Rostedt } elsif ($test_type eq "bisect") { 3775b5f4aea6SSteven Rostedt $run_type = $bisect_type; 37760a05c769SSteven Rostedt } elsif ($test_type eq "config_bisect") { 3777b5f4aea6SSteven Rostedt $run_type = $config_bisect_type; 3778a75fececSSteven Rostedt } 3779a75fececSSteven Rostedt 37804c4ab120SSteven Rostedt if ($test_type eq "make_min_config") { 37814c4ab120SSteven Rostedt $run_type = ""; 37824c4ab120SSteven Rostedt } 37834c4ab120SSteven Rostedt 3784a75fececSSteven Rostedt # mistake in config file? 3785a75fececSSteven Rostedt if (!defined($run_type)) { 3786a75fececSSteven Rostedt $run_type = "ERROR"; 3787a75fececSSteven Rostedt } 37882545eb61SSteven Rostedt 3789e0a8742eSSteven Rostedt my $installme = ""; 3790e0a8742eSSteven Rostedt $installme = " no_install" if ($no_install); 3791e0a8742eSSteven Rostedt 37922545eb61SSteven Rostedt doprint "\n\n"; 3793e0a8742eSSteven Rostedt doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n"; 37947faafbd6SSteven Rostedt 3795921ed4c7SSteven Rostedt if (defined($pre_test)) { 3796921ed4c7SSteven Rostedt run_command $pre_test; 3797921ed4c7SSteven Rostedt } 3798921ed4c7SSteven Rostedt 37997faafbd6SSteven Rostedt unlink $dmesg; 38007faafbd6SSteven Rostedt unlink $buildlog; 3801a9dd5d63SRabin Vincent unlink $testlog; 38022545eb61SSteven Rostedt 3803250bae8bSSteven Rostedt if (defined($addconfig)) { 3804250bae8bSSteven Rostedt my $min = $minconfig; 38052b7d9b21SSteven Rostedt if (!defined($minconfig)) { 3806250bae8bSSteven Rostedt $min = ""; 3807250bae8bSSteven Rostedt } 3808250bae8bSSteven Rostedt run_command "cat $addconfig $min > $tmpdir/add_config" or 38092b7d9b21SSteven Rostedt dodie "Failed to create temp config"; 38109be2e6b5SSteven Rostedt $minconfig = "$tmpdir/add_config"; 38112b7d9b21SSteven Rostedt } 38122b7d9b21SSteven Rostedt 38136c5ee0beSSteven Rostedt if (defined($checkout)) { 38146c5ee0beSSteven Rostedt run_command "git checkout $checkout" or 38156c5ee0beSSteven Rostedt die "failed to checkout $checkout"; 38166c5ee0beSSteven Rostedt } 38176c5ee0beSSteven Rostedt 3818759a3cc6SSteven Rostedt $no_reboot = 0; 3819759a3cc6SSteven Rostedt 3820648a182cSSteven Rostedt # A test may opt to not reboot the box 3821648a182cSSteven Rostedt if ($reboot_on_success) { 3822759a3cc6SSteven Rostedt $reboot_success = 1; 3823648a182cSSteven Rostedt } 38244ab1cce5SSteven Rostedt 3825a75fececSSteven Rostedt if ($test_type eq "bisect") { 38265f9b6cedSSteven Rostedt bisect $i; 38275f9b6cedSSteven Rostedt next; 38280a05c769SSteven Rostedt } elsif ($test_type eq "config_bisect") { 38290a05c769SSteven Rostedt config_bisect $i; 38300a05c769SSteven Rostedt next; 3831a75fececSSteven Rostedt } elsif ($test_type eq "patchcheck") { 38326c5ee0beSSteven Rostedt patchcheck $i; 38336c5ee0beSSteven Rostedt next; 38344c4ab120SSteven Rostedt } elsif ($test_type eq "make_min_config") { 38354c4ab120SSteven Rostedt make_min_config $i; 38364c4ab120SSteven Rostedt next; 38375f9b6cedSSteven Rostedt } 38385f9b6cedSSteven Rostedt 38397faafbd6SSteven Rostedt if ($build_type ne "nobuild") { 38407faafbd6SSteven Rostedt build $build_type or next; 38412545eb61SSteven Rostedt } 38422545eb61SSteven Rostedt 3843cd8e368fSSteven Rostedt if ($test_type eq "install") { 3844cd8e368fSSteven Rostedt get_version; 3845cd8e368fSSteven Rostedt install; 3846cd8e368fSSteven Rostedt success $i; 3847cd8e368fSSteven Rostedt next; 3848cd8e368fSSteven Rostedt } 3849cd8e368fSSteven Rostedt 3850a75fececSSteven Rostedt if ($test_type ne "build") { 38517faafbd6SSteven Rostedt my $failed = 0; 3852ddf607e5SSteven Rostedt start_monitor_and_boot or $failed = 1; 3853a75fececSSteven Rostedt 3854a75fececSSteven Rostedt if (!$failed && $test_type ne "boot" && defined($run_test)) { 38557faafbd6SSteven Rostedt do_run_test or $failed = 1; 38565a391fbfSSteven Rostedt } 38577faafbd6SSteven Rostedt end_monitor; 38587faafbd6SSteven Rostedt next if ($failed); 3859a75fececSSteven Rostedt } 38605a391fbfSSteven Rostedt 38615f9b6cedSSteven Rostedt success $i; 386275c3fda7SSteven Rostedt} 38632545eb61SSteven Rostedt 3864921ed4c7SSteven Rostedtif (defined($final_post_ktest)) { 3865921ed4c7SSteven Rostedt run_command $final_post_ktest; 3866921ed4c7SSteven Rostedt} 3867921ed4c7SSteven Rostedt 38685c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) { 386975c3fda7SSteven Rostedt halt; 3870759a3cc6SSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) { 3871bc7c5803SSteven Rostedt reboot_to_good; 3872648a182cSSteven Rostedt} elsif (defined($switch_to_good)) { 3873648a182cSSteven Rostedt # still need to get to the good kernel 3874648a182cSSteven Rostedt run_command $switch_to_good; 38755c42fc5bSSteven Rostedt} 387675c3fda7SSteven Rostedt 3877648a182cSSteven Rostedt 3878e48c5293SSteven Rostedtdoprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 3879e48c5293SSteven Rostedt 38802545eb61SSteven Rostedtexit 0; 3881