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, 56a15ba913SSteven 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; 109a15ba913SSteven Rostedtmy $grub_file; 1102545eb61SSteven Rostedtmy $grub_number; 111a15ba913SSteven 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, 238a15ba913SSteven Rostedt "GRUB_FILE" => \$grub_file, 239a15ba913SSteven 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. 376a15ba913SSteven 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. 386a15ba913SSteven Rostedt 387a15ba913SSteven Rostedt If you specify grub2, then you also need to specify both \$GRUB_MENU 388a15ba913SSteven 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 393a15ba913SSteven 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 404a15ba913SSteven Rostedt 405a15ba913SSteven Rostedt For grub2, a search of \$GRUB_FILE is performed for the lines 406a15ba913SSteven Rostedt that begin with "menuentry". It will not detect submenus. The 407a15ba913SSteven Rostedt menu must be a non-nested menu. Add the quotes used in the menu 408a15ba913SSteven Rostedt to guarantee your selection, as the first menuentry with the content 409a15ba913SSteven Rostedt of \$GRUB_MENU that is found will be used. 410a15ba913SSteven RostedtEOF 411a15ba913SSteven Rostedt ; 412a15ba913SSteven Rostedt$config_help{"GRUB_FILE"} = << "EOF" 413a15ba913SSteven Rostedt If grub2 is used, the full path for the grub.cfg file is placed 414a15ba913SSteven 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 } 543a15ba913SSteven Rostedt 544a15ba913SSteven Rostedt if ($rtype eq "grub2") { 545a15ba913SSteven Rostedt get_ktest_config("GRUB_MENU"); 546a15ba913SSteven Rostedt get_ktest_config("GRUB_FILE"); 547a15ba913SSteven 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 1150*a4968722SSteven Rostedt # Make sure everything has been written to disk 1151*a4968722SSteven Rostedt run_ssh("sync"); 1152*a4968722SSteven Rostedt 11532b803365SSteven Rostedt if (defined($time)) { 11542b803365SSteven Rostedt start_monitor; 11552b803365SSteven Rostedt # flush out current monitor 11562b803365SSteven Rostedt # May contain the reboot success line 11572b803365SSteven Rostedt wait_for_monitor 1; 11582b803365SSteven Rostedt } 11592b803365SSteven Rostedt 11607faafbd6SSteven Rostedt # try to reboot normally 1161e48c5293SSteven Rostedt if (run_command $reboot) { 1162576f627cSSteven Rostedt if (defined($powercycle_after_reboot)) { 1163576f627cSSteven Rostedt sleep $powercycle_after_reboot; 1164576f627cSSteven Rostedt run_command "$power_cycle"; 1165576f627cSSteven Rostedt } 1166576f627cSSteven Rostedt } else { 11677faafbd6SSteven Rostedt # nope? power cycle it. 1168a75fececSSteven Rostedt run_command "$power_cycle"; 11697faafbd6SSteven Rostedt } 11702728be41SAndrew Jones 11712728be41SAndrew Jones if (defined($time)) { 1172407b95b7SSteven Rostedt if (wait_for_monitor($time, $reboot_success_line)) { 1173407b95b7SSteven Rostedt # reboot got stuck? 11748a80c727SSteven Rostedt doprint "Reboot did not finish. Forcing power cycle\n"; 1175407b95b7SSteven Rostedt run_command "$power_cycle"; 1176407b95b7SSteven Rostedt } 11772728be41SAndrew Jones end_monitor; 11782728be41SAndrew Jones } 11797faafbd6SSteven Rostedt} 11807faafbd6SSteven Rostedt 1181bc7c5803SSteven Rostedtsub reboot_to_good { 1182bc7c5803SSteven Rostedt my ($time) = @_; 1183bc7c5803SSteven Rostedt 1184bc7c5803SSteven Rostedt if (defined($switch_to_good)) { 1185bc7c5803SSteven Rostedt run_command $switch_to_good; 1186bc7c5803SSteven Rostedt } 1187bc7c5803SSteven Rostedt 1188bc7c5803SSteven Rostedt reboot $time; 1189bc7c5803SSteven Rostedt} 1190bc7c5803SSteven Rostedt 1191576f627cSSteven Rostedtsub do_not_reboot { 1192576f627cSSteven Rostedt my $i = $iteration; 1193576f627cSSteven Rostedt 11944ab1cce5SSteven Rostedt return $test_type eq "build" || $no_reboot || 1195576f627cSSteven Rostedt ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 1196576f627cSSteven Rostedt ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 1197576f627cSSteven Rostedt} 1198576f627cSSteven Rostedt 11995c42fc5bSSteven Rostedtsub dodie { 12005a391fbfSSteven Rostedt doprint "CRITICAL FAILURE... ", @_, "\n"; 12015c42fc5bSSteven Rostedt 1202576f627cSSteven Rostedt my $i = $iteration; 1203576f627cSSteven Rostedt 1204576f627cSSteven Rostedt if ($reboot_on_error && !do_not_reboot) { 1205576f627cSSteven Rostedt 120675c3fda7SSteven Rostedt doprint "REBOOTING\n"; 1207bc7c5803SSteven Rostedt reboot_to_good; 120875c3fda7SSteven Rostedt 1209a75fececSSteven Rostedt } elsif ($poweroff_on_error && defined($power_off)) { 12105c42fc5bSSteven Rostedt doprint "POWERING OFF\n"; 1211a75fececSSteven Rostedt `$power_off`; 12125c42fc5bSSteven Rostedt } 121375c3fda7SSteven Rostedt 1214f80802cbSSteven Rostedt if (defined($opt{"LOG_FILE"})) { 1215f80802cbSSteven Rostedt print " See $opt{LOG_FILE} for more info.\n"; 1216f80802cbSSteven Rostedt } 1217f80802cbSSteven Rostedt 1218576f627cSSteven Rostedt die @_, "\n"; 12195c42fc5bSSteven Rostedt} 12205c42fc5bSSteven Rostedt 12217faafbd6SSteven Rostedtsub open_console { 12227faafbd6SSteven Rostedt my ($fp) = @_; 12237faafbd6SSteven Rostedt 12247faafbd6SSteven Rostedt my $flags; 12257faafbd6SSteven Rostedt 1226a75fececSSteven Rostedt my $pid = open($fp, "$console|") or 1227a75fececSSteven Rostedt dodie "Can't open console $console"; 12287faafbd6SSteven Rostedt 12297faafbd6SSteven Rostedt $flags = fcntl($fp, F_GETFL, 0) or 1230576f627cSSteven Rostedt dodie "Can't get flags for the socket: $!"; 12317faafbd6SSteven Rostedt $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 1232576f627cSSteven Rostedt dodie "Can't set flags for the socket: $!"; 12337faafbd6SSteven Rostedt 12347faafbd6SSteven Rostedt return $pid; 12357faafbd6SSteven Rostedt} 12367faafbd6SSteven Rostedt 12377faafbd6SSteven Rostedtsub close_console { 12387faafbd6SSteven Rostedt my ($fp, $pid) = @_; 12397faafbd6SSteven Rostedt 12407faafbd6SSteven Rostedt doprint "kill child process $pid\n"; 12417faafbd6SSteven Rostedt kill 2, $pid; 12427faafbd6SSteven Rostedt 12437faafbd6SSteven Rostedt print "closing!\n"; 12447faafbd6SSteven Rostedt close($fp); 12457faafbd6SSteven Rostedt} 12467faafbd6SSteven Rostedt 12477faafbd6SSteven Rostedtsub start_monitor { 12487faafbd6SSteven Rostedt if ($monitor_cnt++) { 12497faafbd6SSteven Rostedt return; 12507faafbd6SSteven Rostedt } 12517faafbd6SSteven Rostedt $monitor_fp = \*MONFD; 12527faafbd6SSteven Rostedt $monitor_pid = open_console $monitor_fp; 1253a75fececSSteven Rostedt 1254a75fececSSteven Rostedt return; 1255a75fececSSteven Rostedt 1256a75fececSSteven Rostedt open(MONFD, "Stop perl from warning about single use of MONFD"); 12577faafbd6SSteven Rostedt} 12587faafbd6SSteven Rostedt 12597faafbd6SSteven Rostedtsub end_monitor { 12607faafbd6SSteven Rostedt if (--$monitor_cnt) { 12617faafbd6SSteven Rostedt return; 12627faafbd6SSteven Rostedt } 12637faafbd6SSteven Rostedt close_console($monitor_fp, $monitor_pid); 12647faafbd6SSteven Rostedt} 12657faafbd6SSteven Rostedt 12667faafbd6SSteven Rostedtsub wait_for_monitor { 12672b803365SSteven Rostedt my ($time, $stop) = @_; 12682b803365SSteven Rostedt my $full_line = ""; 12697faafbd6SSteven Rostedt my $line; 12702b803365SSteven Rostedt my $booted = 0; 1271407b95b7SSteven Rostedt my $start_time = time; 12728a80c727SSteven Rostedt my $skip_call_trace = 0; 12738a80c727SSteven Rostedt my $bug = 0; 12748a80c727SSteven Rostedt my $bug_ignored = 0; 1275407b95b7SSteven Rostedt my $now; 12767faafbd6SSteven Rostedt 1277a75fececSSteven Rostedt doprint "** Wait for monitor to settle down **\n"; 12787faafbd6SSteven Rostedt 12797faafbd6SSteven Rostedt # read the monitor and wait for the system to calm down 12802b803365SSteven Rostedt while (!$booted) { 12817faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 12822b803365SSteven Rostedt last if (!defined($line)); 12832b803365SSteven Rostedt print "$line"; 12842b803365SSteven Rostedt $full_line .= $line; 12852b803365SSteven Rostedt 12862b803365SSteven Rostedt if (defined($stop) && $full_line =~ /$stop/) { 12872b803365SSteven Rostedt doprint "wait for monitor detected $stop\n"; 12882b803365SSteven Rostedt $booted = 1; 12892b803365SSteven Rostedt } 12902b803365SSteven Rostedt 12918a80c727SSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 12928a80c727SSteven Rostedt $skip_call_trace = 1; 12938a80c727SSteven Rostedt } 12948a80c727SSteven Rostedt 12958a80c727SSteven Rostedt if ($full_line =~ /call trace:/i) { 12968a80c727SSteven Rostedt if (!$bug && !$skip_call_trace) { 12978a80c727SSteven Rostedt if ($ignore_errors) { 12988a80c727SSteven Rostedt $bug_ignored = 1; 12998a80c727SSteven Rostedt } else { 13008a80c727SSteven Rostedt $bug = 1; 13018a80c727SSteven Rostedt } 13028a80c727SSteven Rostedt } 13038a80c727SSteven Rostedt } 13048a80c727SSteven Rostedt 13058a80c727SSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 13068a80c727SSteven Rostedt $skip_call_trace = 0; 13078a80c727SSteven Rostedt } 13088a80c727SSteven Rostedt 13098a80c727SSteven Rostedt if ($full_line =~ /Kernel panic -/) { 13108a80c727SSteven Rostedt $bug = 1; 13118a80c727SSteven Rostedt } 13128a80c727SSteven Rostedt 13132b803365SSteven Rostedt if ($line =~ /\n/) { 13142b803365SSteven Rostedt $full_line = ""; 13152b803365SSteven Rostedt } 1316407b95b7SSteven Rostedt $now = time; 1317407b95b7SSteven Rostedt if ($now - $start_time >= $max_monitor_wait) { 1318407b95b7SSteven Rostedt doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n"; 1319407b95b7SSteven Rostedt return 1; 1320407b95b7SSteven Rostedt } 13212b803365SSteven Rostedt } 1322a75fececSSteven Rostedt print "** Monitor flushed **\n"; 13238a80c727SSteven Rostedt return $bug; 13247faafbd6SSteven Rostedt} 13257faafbd6SSteven Rostedt 1326de5b6e3bSRabin Vincentsub save_logs { 1327de5b6e3bSRabin Vincent my ($result, $basedir) = @_; 1328de5b6e3bSRabin Vincent my @t = localtime; 1329de5b6e3bSRabin Vincent my $date = sprintf "%04d%02d%02d%02d%02d%02d", 1330de5b6e3bSRabin Vincent 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 1331de5b6e3bSRabin Vincent 1332de5b6e3bSRabin Vincent my $type = $build_type; 1333de5b6e3bSRabin Vincent if ($type =~ /useconfig/) { 1334de5b6e3bSRabin Vincent $type = "useconfig"; 1335de5b6e3bSRabin Vincent } 1336de5b6e3bSRabin Vincent 1337de5b6e3bSRabin Vincent my $dir = "$machine-$test_type-$type-$result-$date"; 1338de5b6e3bSRabin Vincent 1339de5b6e3bSRabin Vincent $dir = "$basedir/$dir"; 1340de5b6e3bSRabin Vincent 1341de5b6e3bSRabin Vincent if (!-d $dir) { 1342de5b6e3bSRabin Vincent mkpath($dir) or 1343de5b6e3bSRabin Vincent die "can't create $dir"; 1344de5b6e3bSRabin Vincent } 1345de5b6e3bSRabin Vincent 1346de5b6e3bSRabin Vincent my %files = ( 1347de5b6e3bSRabin Vincent "config" => $output_config, 1348de5b6e3bSRabin Vincent "buildlog" => $buildlog, 1349de5b6e3bSRabin Vincent "dmesg" => $dmesg, 1350de5b6e3bSRabin Vincent "testlog" => $testlog, 1351de5b6e3bSRabin Vincent ); 1352de5b6e3bSRabin Vincent 1353de5b6e3bSRabin Vincent while (my ($name, $source) = each(%files)) { 1354de5b6e3bSRabin Vincent if (-f "$source") { 1355de5b6e3bSRabin Vincent cp "$source", "$dir/$name" or 1356de5b6e3bSRabin Vincent die "failed to copy $source"; 1357de5b6e3bSRabin Vincent } 1358de5b6e3bSRabin Vincent } 1359de5b6e3bSRabin Vincent 1360de5b6e3bSRabin Vincent doprint "*** Saved info to $dir ***\n"; 1361de5b6e3bSRabin Vincent} 1362de5b6e3bSRabin Vincent 13632b7d9b21SSteven Rostedtsub fail { 13642b7d9b21SSteven Rostedt 1365921ed4c7SSteven Rostedt if (defined($post_test)) { 1366921ed4c7SSteven Rostedt run_command $post_test; 1367921ed4c7SSteven Rostedt } 1368921ed4c7SSteven Rostedt 1369a75fececSSteven Rostedt if ($die_on_failure) { 13702b7d9b21SSteven Rostedt dodie @_; 13712b7d9b21SSteven Rostedt } 13722b7d9b21SSteven Rostedt 1373a75fececSSteven Rostedt doprint "FAILED\n"; 13747faafbd6SSteven Rostedt 1375576f627cSSteven Rostedt my $i = $iteration; 1376576f627cSSteven Rostedt 1377a75fececSSteven Rostedt # no need to reboot for just building. 1378576f627cSSteven Rostedt if (!do_not_reboot) { 13797faafbd6SSteven Rostedt doprint "REBOOTING\n"; 1380bc7c5803SSteven Rostedt reboot_to_good $sleep_time; 1381a75fececSSteven Rostedt } 13827faafbd6SSteven Rostedt 13839064af52SSteven Rostedt my $name = ""; 13849064af52SSteven Rostedt 13859064af52SSteven Rostedt if (defined($test_name)) { 13869064af52SSteven Rostedt $name = " ($test_name)"; 13879064af52SSteven Rostedt } 13889064af52SSteven Rostedt 1389576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1390576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 13919064af52SSteven Rostedt doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n"; 1392576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1393576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1394a75fececSSteven Rostedt 1395de5b6e3bSRabin Vincent if (defined($store_failures)) { 1396de5b6e3bSRabin Vincent save_logs "fail", $store_failures; 1397cccae1a6SSteven Rostedt } 1398cccae1a6SSteven Rostedt 13992b7d9b21SSteven Rostedt return 1; 14002b7d9b21SSteven Rostedt} 14012b7d9b21SSteven Rostedt 14022545eb61SSteven Rostedtsub run_command { 14032545eb61SSteven Rostedt my ($command) = @_; 1404d6ce2a0bSSteven Rostedt my $dolog = 0; 1405d6ce2a0bSSteven Rostedt my $dord = 0; 1406d6ce2a0bSSteven Rostedt my $pid; 1407d6ce2a0bSSteven Rostedt 1408e48c5293SSteven Rostedt $command =~ s/\$SSH_USER/$ssh_user/g; 1409e48c5293SSteven Rostedt $command =~ s/\$MACHINE/$machine/g; 1410e48c5293SSteven Rostedt 1411d6ce2a0bSSteven Rostedt doprint("$command ... "); 1412d6ce2a0bSSteven Rostedt 1413d6ce2a0bSSteven Rostedt $pid = open(CMD, "$command 2>&1 |") or 14142b7d9b21SSteven Rostedt (fail "unable to exec $command" and return 0); 14152545eb61SSteven Rostedt 14162545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 1417d6ce2a0bSSteven Rostedt open(LOG, ">>$opt{LOG_FILE}") or 1418d6ce2a0bSSteven Rostedt dodie "failed to write to log"; 1419d6ce2a0bSSteven Rostedt $dolog = 1; 14206c5ee0beSSteven Rostedt } 14216c5ee0beSSteven Rostedt 14226c5ee0beSSteven Rostedt if (defined($redirect)) { 1423d6ce2a0bSSteven Rostedt open (RD, ">$redirect") or 1424d6ce2a0bSSteven Rostedt dodie "failed to write to redirect $redirect"; 1425d6ce2a0bSSteven Rostedt $dord = 1; 14262545eb61SSteven Rostedt } 14272545eb61SSteven Rostedt 1428d6ce2a0bSSteven Rostedt while (<CMD>) { 1429d6ce2a0bSSteven Rostedt print LOG if ($dolog); 1430d6ce2a0bSSteven Rostedt print RD if ($dord); 1431d6ce2a0bSSteven Rostedt } 14322545eb61SSteven Rostedt 1433d6ce2a0bSSteven Rostedt waitpid($pid, 0); 14342545eb61SSteven Rostedt my $failed = $?; 14352545eb61SSteven Rostedt 1436d6ce2a0bSSteven Rostedt close(CMD); 1437d6ce2a0bSSteven Rostedt close(LOG) if ($dolog); 1438d6ce2a0bSSteven Rostedt close(RD) if ($dord); 1439d6ce2a0bSSteven Rostedt 14402545eb61SSteven Rostedt if ($failed) { 14412545eb61SSteven Rostedt doprint "FAILED!\n"; 14422545eb61SSteven Rostedt } else { 14432545eb61SSteven Rostedt doprint "SUCCESS\n"; 14442545eb61SSteven Rostedt } 14452545eb61SSteven Rostedt 14465f9b6cedSSteven Rostedt return !$failed; 14475f9b6cedSSteven Rostedt} 14485f9b6cedSSteven Rostedt 1449e48c5293SSteven Rostedtsub run_ssh { 1450e48c5293SSteven Rostedt my ($cmd) = @_; 1451e48c5293SSteven Rostedt my $cp_exec = $ssh_exec; 1452e48c5293SSteven Rostedt 1453e48c5293SSteven Rostedt $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 1454e48c5293SSteven Rostedt return run_command "$cp_exec"; 1455e48c5293SSteven Rostedt} 1456e48c5293SSteven Rostedt 1457e48c5293SSteven Rostedtsub run_scp { 145802ad2617SSteven Rostedt my ($src, $dst, $cp_scp) = @_; 1459e48c5293SSteven Rostedt 1460e48c5293SSteven Rostedt $cp_scp =~ s/\$SRC_FILE/$src/g; 1461e48c5293SSteven Rostedt $cp_scp =~ s/\$DST_FILE/$dst/g; 1462e48c5293SSteven Rostedt 1463e48c5293SSteven Rostedt return run_command "$cp_scp"; 1464e48c5293SSteven Rostedt} 1465e48c5293SSteven Rostedt 146602ad2617SSteven Rostedtsub run_scp_install { 146702ad2617SSteven Rostedt my ($src, $dst) = @_; 146802ad2617SSteven Rostedt 146902ad2617SSteven Rostedt my $cp_scp = $scp_to_target_install; 147002ad2617SSteven Rostedt 147102ad2617SSteven Rostedt return run_scp($src, $dst, $cp_scp); 147202ad2617SSteven Rostedt} 147302ad2617SSteven Rostedt 147402ad2617SSteven Rostedtsub run_scp_mod { 147502ad2617SSteven Rostedt my ($src, $dst) = @_; 147602ad2617SSteven Rostedt 147702ad2617SSteven Rostedt my $cp_scp = $scp_to_target; 147802ad2617SSteven Rostedt 147902ad2617SSteven Rostedt return run_scp($src, $dst, $cp_scp); 148002ad2617SSteven Rostedt} 148102ad2617SSteven Rostedt 1482a15ba913SSteven Rostedtsub get_grub2_index { 1483a15ba913SSteven Rostedt 1484a15ba913SSteven Rostedt return if (defined($grub_number)); 1485a15ba913SSteven Rostedt 1486a15ba913SSteven Rostedt doprint "Find grub2 menu ... "; 1487a15ba913SSteven Rostedt $grub_number = -1; 1488a15ba913SSteven Rostedt 1489a15ba913SSteven Rostedt my $ssh_grub = $ssh_exec; 1490a15ba913SSteven Rostedt $ssh_grub =~ s,\$SSH_COMMAND,cat $grub_file,g; 1491a15ba913SSteven Rostedt 1492a15ba913SSteven Rostedt open(IN, "$ssh_grub |") 1493a15ba913SSteven Rostedt or die "unable to get $grub_file"; 1494a15ba913SSteven Rostedt 1495a15ba913SSteven Rostedt my $found = 0; 1496a15ba913SSteven Rostedt 1497a15ba913SSteven Rostedt while (<IN>) { 1498a15ba913SSteven Rostedt if (/^menuentry.*$grub_menu/) { 1499a15ba913SSteven Rostedt $grub_number++; 1500a15ba913SSteven Rostedt $found = 1; 1501a15ba913SSteven Rostedt last; 1502a15ba913SSteven Rostedt } elsif (/^menuentry\s/) { 1503a15ba913SSteven Rostedt $grub_number++; 1504a15ba913SSteven Rostedt } 1505a15ba913SSteven Rostedt } 1506a15ba913SSteven Rostedt close(IN); 1507a15ba913SSteven Rostedt 1508a15ba913SSteven Rostedt die "Could not find '$grub_menu' in $grub_file on $machine" 1509a15ba913SSteven Rostedt if (!$found); 1510a15ba913SSteven Rostedt doprint "$grub_number\n"; 1511a15ba913SSteven Rostedt} 1512a15ba913SSteven Rostedt 15135f9b6cedSSteven Rostedtsub get_grub_index { 15145f9b6cedSSteven Rostedt 1515a15ba913SSteven Rostedt if ($reboot_type eq "grub2") { 1516a15ba913SSteven Rostedt get_grub2_index; 1517a15ba913SSteven Rostedt return; 1518a15ba913SSteven Rostedt } 1519a15ba913SSteven Rostedt 1520a75fececSSteven Rostedt if ($reboot_type ne "grub") { 1521a75fececSSteven Rostedt return; 1522a75fececSSteven Rostedt } 15235a391fbfSSteven Rostedt return if (defined($grub_number)); 15245f9b6cedSSteven Rostedt 15255f9b6cedSSteven Rostedt doprint "Find grub menu ... "; 15265f9b6cedSSteven Rostedt $grub_number = -1; 1527e48c5293SSteven Rostedt 1528e48c5293SSteven Rostedt my $ssh_grub = $ssh_exec; 1529e48c5293SSteven Rostedt $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 1530e48c5293SSteven Rostedt 1531e48c5293SSteven Rostedt open(IN, "$ssh_grub |") 15325f9b6cedSSteven Rostedt or die "unable to get menu.lst"; 1533e48c5293SSteven Rostedt 1534eaa1fe25SSteven Rostedt my $found = 0; 1535eaa1fe25SSteven Rostedt 15365f9b6cedSSteven Rostedt while (<IN>) { 1537a75fececSSteven Rostedt if (/^\s*title\s+$grub_menu\s*$/) { 15385f9b6cedSSteven Rostedt $grub_number++; 1539eaa1fe25SSteven Rostedt $found = 1; 15405f9b6cedSSteven Rostedt last; 15415f9b6cedSSteven Rostedt } elsif (/^\s*title\s/) { 15425f9b6cedSSteven Rostedt $grub_number++; 15435f9b6cedSSteven Rostedt } 15445f9b6cedSSteven Rostedt } 15455f9b6cedSSteven Rostedt close(IN); 15465f9b6cedSSteven Rostedt 1547a75fececSSteven Rostedt die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 1548eaa1fe25SSteven Rostedt if (!$found); 15495f9b6cedSSteven Rostedt doprint "$grub_number\n"; 15502545eb61SSteven Rostedt} 15512545eb61SSteven Rostedt 15522545eb61SSteven Rostedtsub wait_for_input 15532545eb61SSteven Rostedt{ 15542545eb61SSteven Rostedt my ($fp, $time) = @_; 15552545eb61SSteven Rostedt my $rin; 15562545eb61SSteven Rostedt my $ready; 15572545eb61SSteven Rostedt my $line; 15582545eb61SSteven Rostedt my $ch; 15592545eb61SSteven Rostedt 15602545eb61SSteven Rostedt if (!defined($time)) { 15612545eb61SSteven Rostedt $time = $timeout; 15622545eb61SSteven Rostedt } 15632545eb61SSteven Rostedt 15642545eb61SSteven Rostedt $rin = ''; 15652545eb61SSteven Rostedt vec($rin, fileno($fp), 1) = 1; 15662545eb61SSteven Rostedt $ready = select($rin, undef, undef, $time); 15672545eb61SSteven Rostedt 15682545eb61SSteven Rostedt $line = ""; 15692545eb61SSteven Rostedt 15702545eb61SSteven Rostedt # try to read one char at a time 15712545eb61SSteven Rostedt while (sysread $fp, $ch, 1) { 15722545eb61SSteven Rostedt $line .= $ch; 15732545eb61SSteven Rostedt last if ($ch eq "\n"); 15742545eb61SSteven Rostedt } 15752545eb61SSteven Rostedt 15762545eb61SSteven Rostedt if (!length($line)) { 15772545eb61SSteven Rostedt return undef; 15782545eb61SSteven Rostedt } 15792545eb61SSteven Rostedt 15802545eb61SSteven Rostedt return $line; 15812545eb61SSteven Rostedt} 15822545eb61SSteven Rostedt 158375c3fda7SSteven Rostedtsub reboot_to { 1584bc7c5803SSteven Rostedt if (defined($switch_to_test)) { 1585bc7c5803SSteven Rostedt run_command $switch_to_test; 1586bc7c5803SSteven Rostedt } 1587bc7c5803SSteven Rostedt 1588a75fececSSteven Rostedt if ($reboot_type eq "grub") { 1589c54367f9SSteven Rostedt run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; 1590a15ba913SSteven Rostedt } elsif ($reboot_type eq "grub2") { 1591a15ba913SSteven Rostedt run_ssh "$grub_reboot $grub_number"; 159296f6a0dfSSteven Rostedt } elsif (defined $reboot_script) { 1593a75fececSSteven Rostedt run_command "$reboot_script"; 15942545eb61SSteven Rostedt } 159596f6a0dfSSteven Rostedt reboot; 159696f6a0dfSSteven Rostedt} 15972545eb61SSteven Rostedt 1598a57419b3SSteven Rostedtsub get_sha1 { 1599a57419b3SSteven Rostedt my ($commit) = @_; 1600a57419b3SSteven Rostedt 1601a57419b3SSteven Rostedt doprint "git rev-list --max-count=1 $commit ... "; 1602a57419b3SSteven Rostedt my $sha1 = `git rev-list --max-count=1 $commit`; 1603a57419b3SSteven Rostedt my $ret = $?; 1604a57419b3SSteven Rostedt 1605a57419b3SSteven Rostedt logit $sha1; 1606a57419b3SSteven Rostedt 1607a57419b3SSteven Rostedt if ($ret) { 1608a57419b3SSteven Rostedt doprint "FAILED\n"; 1609a57419b3SSteven Rostedt dodie "Failed to get git $commit"; 1610a57419b3SSteven Rostedt } 1611a57419b3SSteven Rostedt 1612a57419b3SSteven Rostedt print "SUCCESS\n"; 1613a57419b3SSteven Rostedt 1614a57419b3SSteven Rostedt chomp $sha1; 1615a57419b3SSteven Rostedt 1616a57419b3SSteven Rostedt return $sha1; 1617a57419b3SSteven Rostedt} 1618a57419b3SSteven Rostedt 16195a391fbfSSteven Rostedtsub monitor { 16202545eb61SSteven Rostedt my $booted = 0; 16212545eb61SSteven Rostedt my $bug = 0; 16226ca996ccSSteven Rostedt my $bug_ignored = 0; 16235c42fc5bSSteven Rostedt my $skip_call_trace = 0; 16242b7d9b21SSteven Rostedt my $loops; 16252545eb61SSteven Rostedt 16267faafbd6SSteven Rostedt wait_for_monitor 5; 16272545eb61SSteven Rostedt 16282545eb61SSteven Rostedt my $line; 16292545eb61SSteven Rostedt my $full_line = ""; 16302545eb61SSteven Rostedt 16317faafbd6SSteven Rostedt open(DMESG, "> $dmesg") or 16327faafbd6SSteven Rostedt die "unable to write to $dmesg"; 16332545eb61SSteven Rostedt 163475c3fda7SSteven Rostedt reboot_to; 16352545eb61SSteven Rostedt 16361c8a617aSSteven Rostedt my $success_start; 16371c8a617aSSteven Rostedt my $failure_start; 16382d01b26aSSteven Rostedt my $monitor_start = time; 16392d01b26aSSteven Rostedt my $done = 0; 1640f1a5b962SSteven Rostedt my $version_found = 0; 16411c8a617aSSteven Rostedt 16422d01b26aSSteven Rostedt while (!$done) { 16432545eb61SSteven Rostedt 1644ecaf8e52SSteven Rostedt if ($bug && defined($stop_after_failure) && 1645ecaf8e52SSteven Rostedt $stop_after_failure >= 0) { 1646ecaf8e52SSteven Rostedt my $time = $stop_after_failure - (time - $failure_start); 1647ecaf8e52SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 1648ecaf8e52SSteven Rostedt if (!defined($line)) { 1649ecaf8e52SSteven Rostedt doprint "bug timed out after $booted_timeout seconds\n"; 1650ecaf8e52SSteven Rostedt doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 1651ecaf8e52SSteven Rostedt last; 1652ecaf8e52SSteven Rostedt } 1653ecaf8e52SSteven Rostedt } elsif ($booted) { 1654a75fececSSteven Rostedt $line = wait_for_input($monitor_fp, $booted_timeout); 1655cd4f1d53SSteven Rostedt if (!defined($line)) { 1656cd4f1d53SSteven Rostedt my $s = $booted_timeout == 1 ? "" : "s"; 1657cd4f1d53SSteven Rostedt doprint "Successful boot found: break after $booted_timeout second$s\n"; 1658cd4f1d53SSteven Rostedt last; 1659cd4f1d53SSteven Rostedt } 16602b7d9b21SSteven Rostedt } else { 16617faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp); 1662cd4f1d53SSteven Rostedt if (!defined($line)) { 1663cd4f1d53SSteven Rostedt my $s = $timeout == 1 ? "" : "s"; 1664cd4f1d53SSteven Rostedt doprint "Timed out after $timeout second$s\n"; 1665cd4f1d53SSteven Rostedt last; 16662b7d9b21SSteven Rostedt } 1667cd4f1d53SSteven Rostedt } 16682545eb61SSteven Rostedt 16692545eb61SSteven Rostedt doprint $line; 16707faafbd6SSteven Rostedt print DMESG $line; 16712545eb61SSteven Rostedt 16722545eb61SSteven Rostedt # we are not guaranteed to get a full line 16732545eb61SSteven Rostedt $full_line .= $line; 16742545eb61SSteven Rostedt 1675a75fececSSteven Rostedt if ($full_line =~ /$success_line/) { 16762545eb61SSteven Rostedt $booted = 1; 16771c8a617aSSteven Rostedt $success_start = time; 16781c8a617aSSteven Rostedt } 16791c8a617aSSteven Rostedt 16801c8a617aSSteven Rostedt if ($booted && defined($stop_after_success) && 16811c8a617aSSteven Rostedt $stop_after_success >= 0) { 16821c8a617aSSteven Rostedt my $now = time; 16831c8a617aSSteven Rostedt if ($now - $success_start >= $stop_after_success) { 16841c8a617aSSteven Rostedt doprint "Test forced to stop after $stop_after_success seconds after success\n"; 16851c8a617aSSteven Rostedt last; 16861c8a617aSSteven Rostedt } 16872545eb61SSteven Rostedt } 16882545eb61SSteven Rostedt 16895c42fc5bSSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 16905c42fc5bSSteven Rostedt $skip_call_trace = 1; 16915c42fc5bSSteven Rostedt } 16925c42fc5bSSteven Rostedt 16932545eb61SSteven Rostedt if ($full_line =~ /call trace:/i) { 16946ca996ccSSteven Rostedt if (!$bug && !$skip_call_trace) { 16956ca996ccSSteven Rostedt if ($ignore_errors) { 16966ca996ccSSteven Rostedt $bug_ignored = 1; 16976ca996ccSSteven Rostedt } else { 16981c8a617aSSteven Rostedt $bug = 1; 16991c8a617aSSteven Rostedt $failure_start = time; 17001c8a617aSSteven Rostedt } 17011c8a617aSSteven Rostedt } 17026ca996ccSSteven Rostedt } 17031c8a617aSSteven Rostedt 17041c8a617aSSteven Rostedt if ($bug && defined($stop_after_failure) && 17051c8a617aSSteven Rostedt $stop_after_failure >= 0) { 17061c8a617aSSteven Rostedt my $now = time; 17071c8a617aSSteven Rostedt if ($now - $failure_start >= $stop_after_failure) { 17081c8a617aSSteven Rostedt doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 17091c8a617aSSteven Rostedt last; 17101c8a617aSSteven Rostedt } 17115c42fc5bSSteven Rostedt } 17125c42fc5bSSteven Rostedt 17135c42fc5bSSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 17145c42fc5bSSteven Rostedt $skip_call_trace = 0; 17155c42fc5bSSteven Rostedt } 17165c42fc5bSSteven Rostedt 17175c42fc5bSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 171810abf118SSteven Rostedt $failure_start = time; 17192545eb61SSteven Rostedt $bug = 1; 17202545eb61SSteven Rostedt } 17212545eb61SSteven Rostedt 1722f1a5b962SSteven Rostedt # Detect triple faults by testing the banner 1723f1a5b962SSteven Rostedt if ($full_line =~ /\bLinux version (\S+).*\n/) { 1724f1a5b962SSteven Rostedt if ($1 eq $version) { 1725f1a5b962SSteven Rostedt $version_found = 1; 1726f1a5b962SSteven Rostedt } elsif ($version_found && $detect_triplefault) { 1727f1a5b962SSteven Rostedt # We already booted into the kernel we are testing, 1728f1a5b962SSteven Rostedt # but now we booted into another kernel? 1729f1a5b962SSteven Rostedt # Consider this a triple fault. 1730f1a5b962SSteven Rostedt doprint "Aleady booted in Linux kernel $version, but now\n"; 1731f1a5b962SSteven Rostedt doprint "we booted into Linux kernel $1.\n"; 1732f1a5b962SSteven Rostedt doprint "Assuming that this is a triple fault.\n"; 1733f1a5b962SSteven Rostedt doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; 1734f1a5b962SSteven Rostedt last; 1735f1a5b962SSteven Rostedt } 1736f1a5b962SSteven Rostedt } 1737f1a5b962SSteven Rostedt 17382545eb61SSteven Rostedt if ($line =~ /\n/) { 17392545eb61SSteven Rostedt $full_line = ""; 17402545eb61SSteven Rostedt } 17412d01b26aSSteven Rostedt 17422d01b26aSSteven Rostedt if ($stop_test_after > 0 && !$booted && !$bug) { 17432d01b26aSSteven Rostedt if (time - $monitor_start > $stop_test_after) { 17444d62bf51SSteven Rostedt doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 17452d01b26aSSteven Rostedt $done = 1; 17462d01b26aSSteven Rostedt } 17472d01b26aSSteven Rostedt } 17482545eb61SSteven Rostedt } 17492545eb61SSteven Rostedt 17507faafbd6SSteven Rostedt close(DMESG); 17512545eb61SSteven Rostedt 17522545eb61SSteven Rostedt if ($bug) { 17532b7d9b21SSteven Rostedt return 0 if ($in_bisect); 1754576f627cSSteven Rostedt fail "failed - got a bug report" and return 0; 17552545eb61SSteven Rostedt } 17565f9b6cedSSteven Rostedt 1757a75fececSSteven Rostedt if (!$booted) { 1758a75fececSSteven Rostedt return 0 if ($in_bisect); 1759576f627cSSteven Rostedt fail "failed - never got a boot prompt." and return 0; 1760a75fececSSteven Rostedt } 1761a75fececSSteven Rostedt 17626ca996ccSSteven Rostedt if ($bug_ignored) { 17636ca996ccSSteven Rostedt doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 17646ca996ccSSteven Rostedt } 17656ca996ccSSteven Rostedt 17662b7d9b21SSteven Rostedt return 1; 17672545eb61SSteven Rostedt} 17682545eb61SSteven Rostedt 17692b29b2f8SSteven Rostedtsub eval_kernel_version { 17702b29b2f8SSteven Rostedt my ($option) = @_; 17712b29b2f8SSteven Rostedt 17722b29b2f8SSteven Rostedt $option =~ s/\$KERNEL_VERSION/$version/g; 17732b29b2f8SSteven Rostedt 17742b29b2f8SSteven Rostedt return $option; 17752b29b2f8SSteven Rostedt} 17762b29b2f8SSteven Rostedt 1777db05cfefSSteven Rostedtsub do_post_install { 1778db05cfefSSteven Rostedt 1779db05cfefSSteven Rostedt return if (!defined($post_install)); 1780db05cfefSSteven Rostedt 17812b29b2f8SSteven Rostedt my $cp_post_install = eval_kernel_version $post_install; 1782db05cfefSSteven Rostedt run_command "$cp_post_install" or 1783db05cfefSSteven Rostedt dodie "Failed to run post install"; 1784db05cfefSSteven Rostedt} 1785db05cfefSSteven Rostedt 17862545eb61SSteven Rostedtsub install { 17872545eb61SSteven Rostedt 1788e0a8742eSSteven Rostedt return if ($no_install); 1789e0a8742eSSteven Rostedt 1790e5c2ec11SSteven Rostedt if (defined($pre_install)) { 1791e5c2ec11SSteven Rostedt my $cp_pre_install = eval_kernel_version $pre_install; 1792e5c2ec11SSteven Rostedt run_command "$cp_pre_install" or 1793e5c2ec11SSteven Rostedt dodie "Failed to run pre install"; 1794e5c2ec11SSteven Rostedt } 1795e5c2ec11SSteven Rostedt 17962b29b2f8SSteven Rostedt my $cp_target = eval_kernel_version $target_image; 17972b29b2f8SSteven Rostedt 179802ad2617SSteven Rostedt run_scp_install "$outputdir/$build_target", "$cp_target" or 17995c42fc5bSSteven Rostedt dodie "failed to copy image"; 18005f9b6cedSSteven Rostedt 18015f9b6cedSSteven Rostedt my $install_mods = 0; 18025f9b6cedSSteven Rostedt 18035f9b6cedSSteven Rostedt # should we process modules? 18045f9b6cedSSteven Rostedt $install_mods = 0; 180551ad1dd1SSteven Rostedt open(IN, "$output_config") or dodie("Can't read config file"); 18065f9b6cedSSteven Rostedt while (<IN>) { 18075f9b6cedSSteven Rostedt if (/CONFIG_MODULES(=y)?/) { 18088bc5e4eaSSteven Rostedt if (defined($1)) { 18098bc5e4eaSSteven Rostedt $install_mods = 1; 18105f9b6cedSSteven Rostedt last; 18115f9b6cedSSteven Rostedt } 18125f9b6cedSSteven Rostedt } 18138bc5e4eaSSteven Rostedt } 18145f9b6cedSSteven Rostedt close(IN); 18155f9b6cedSSteven Rostedt 18165f9b6cedSSteven Rostedt if (!$install_mods) { 1817db05cfefSSteven Rostedt do_post_install; 18185f9b6cedSSteven Rostedt doprint "No modules needed\n"; 18195f9b6cedSSteven Rostedt return; 18202545eb61SSteven Rostedt } 18212545eb61SSteven Rostedt 1822627977d8SSteven Rostedt run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or 18235f9b6cedSSteven Rostedt dodie "Failed to install modules"; 18245f9b6cedSSteven Rostedt 18252545eb61SSteven Rostedt my $modlib = "/lib/modules/$version"; 1826a57419b3SSteven Rostedt my $modtar = "ktest-mods.tar.bz2"; 18272545eb61SSteven Rostedt 1828e48c5293SSteven Rostedt run_ssh "rm -rf $modlib" or 18295c42fc5bSSteven Rostedt dodie "failed to remove old mods: $modlib"; 18302545eb61SSteven Rostedt 18315c42fc5bSSteven Rostedt # would be nice if scp -r did not follow symbolic links 1832a75fececSSteven Rostedt run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 18335c42fc5bSSteven Rostedt dodie "making tarball"; 18345c42fc5bSSteven Rostedt 183502ad2617SSteven Rostedt run_scp_mod "$tmpdir/$modtar", "/tmp" or 18365c42fc5bSSteven Rostedt dodie "failed to copy modules"; 18375c42fc5bSSteven Rostedt 1838a75fececSSteven Rostedt unlink "$tmpdir/$modtar"; 18395c42fc5bSSteven Rostedt 1840e7b13441SSteven Rostedt run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or 18415c42fc5bSSteven Rostedt dodie "failed to tar modules"; 18425c42fc5bSSteven Rostedt 1843e48c5293SSteven Rostedt run_ssh "rm -f /tmp/$modtar"; 18448b37ca8cSSteven Rostedt 1845db05cfefSSteven Rostedt do_post_install; 18462545eb61SSteven Rostedt} 18472545eb61SSteven Rostedt 1848ddf607e5SSteven Rostedtsub get_version { 1849ddf607e5SSteven Rostedt # get the release name 1850683a3e64SSteven Rostedt return if ($have_version); 1851ddf607e5SSteven Rostedt doprint "$make kernelrelease ... "; 1852ddf607e5SSteven Rostedt $version = `$make kernelrelease | tail -1`; 1853ddf607e5SSteven Rostedt chomp($version); 1854ddf607e5SSteven Rostedt doprint "$version\n"; 1855683a3e64SSteven Rostedt $have_version = 1; 1856ddf607e5SSteven Rostedt} 1857ddf607e5SSteven Rostedt 1858ddf607e5SSteven Rostedtsub start_monitor_and_boot { 18599f7424ccSSteven Rostedt # Make sure the stable kernel has finished booting 18609f7424ccSSteven Rostedt start_monitor; 18619f7424ccSSteven Rostedt wait_for_monitor 5; 18629f7424ccSSteven Rostedt end_monitor; 18639f7424ccSSteven Rostedt 1864ddf607e5SSteven Rostedt get_grub_index; 1865ddf607e5SSteven Rostedt get_version; 1866ddf607e5SSteven Rostedt install; 1867ddf607e5SSteven Rostedt 1868ddf607e5SSteven Rostedt start_monitor; 1869ddf607e5SSteven Rostedt return monitor; 1870ddf607e5SSteven Rostedt} 1871ddf607e5SSteven Rostedt 18726c5ee0beSSteven Rostedtsub check_buildlog { 18736c5ee0beSSteven Rostedt my ($patch) = @_; 18746c5ee0beSSteven Rostedt 18756c5ee0beSSteven Rostedt my @files = `git show $patch | diffstat -l`; 18766c5ee0beSSteven Rostedt 18776c5ee0beSSteven Rostedt open(IN, "git show $patch |") or 18786c5ee0beSSteven Rostedt dodie "failed to show $patch"; 18796c5ee0beSSteven Rostedt while (<IN>) { 18806c5ee0beSSteven Rostedt if (m,^--- a/(.*),) { 18816c5ee0beSSteven Rostedt chomp $1; 18826c5ee0beSSteven Rostedt $files[$#files] = $1; 18836c5ee0beSSteven Rostedt } 18846c5ee0beSSteven Rostedt } 18856c5ee0beSSteven Rostedt close(IN); 18866c5ee0beSSteven Rostedt 18876c5ee0beSSteven Rostedt open(IN, $buildlog) or dodie "Can't open $buildlog"; 18886c5ee0beSSteven Rostedt while (<IN>) { 18896c5ee0beSSteven Rostedt if (/^\s*(.*?):.*(warning|error)/) { 18906c5ee0beSSteven Rostedt my $err = $1; 18916c5ee0beSSteven Rostedt foreach my $file (@files) { 1892a75fececSSteven Rostedt my $fullpath = "$builddir/$file"; 18936c5ee0beSSteven Rostedt if ($file eq $err || $fullpath eq $err) { 18942b7d9b21SSteven Rostedt fail "$file built with warnings" and return 0; 18956c5ee0beSSteven Rostedt } 18966c5ee0beSSteven Rostedt } 18976c5ee0beSSteven Rostedt } 18986c5ee0beSSteven Rostedt } 18996c5ee0beSSteven Rostedt close(IN); 19002b7d9b21SSteven Rostedt 19012b7d9b21SSteven Rostedt return 1; 19026c5ee0beSSteven Rostedt} 19036c5ee0beSSteven Rostedt 1904fcb3f16aSSteven Rostedtsub apply_min_config { 1905fcb3f16aSSteven Rostedt my $outconfig = "$output_config.new"; 1906612b9e9bSSteven Rostedt 1907fcb3f16aSSteven Rostedt # Read the config file and remove anything that 1908fcb3f16aSSteven Rostedt # is in the force_config hash (from minconfig and others) 1909fcb3f16aSSteven Rostedt # then add the force config back. 1910fcb3f16aSSteven Rostedt 1911fcb3f16aSSteven Rostedt doprint "Applying minimum configurations into $output_config.new\n"; 1912fcb3f16aSSteven Rostedt 1913fcb3f16aSSteven Rostedt open (OUT, ">$outconfig") or 1914fcb3f16aSSteven Rostedt dodie "Can't create $outconfig"; 1915fcb3f16aSSteven Rostedt 1916fcb3f16aSSteven Rostedt if (-f $output_config) { 1917fcb3f16aSSteven Rostedt open (IN, $output_config) or 1918fcb3f16aSSteven Rostedt dodie "Failed to open $output_config"; 1919fcb3f16aSSteven Rostedt while (<IN>) { 1920fcb3f16aSSteven Rostedt if (/^(# )?(CONFIG_[^\s=]*)/) { 1921fcb3f16aSSteven Rostedt next if (defined($force_config{$2})); 1922fcb3f16aSSteven Rostedt } 1923fcb3f16aSSteven Rostedt print OUT; 1924fcb3f16aSSteven Rostedt } 1925fcb3f16aSSteven Rostedt close IN; 1926fcb3f16aSSteven Rostedt } 1927fcb3f16aSSteven Rostedt foreach my $config (keys %force_config) { 1928fcb3f16aSSteven Rostedt print OUT "$force_config{$config}\n"; 1929fcb3f16aSSteven Rostedt } 1930fcb3f16aSSteven Rostedt close OUT; 1931fcb3f16aSSteven Rostedt 1932fcb3f16aSSteven Rostedt run_command "mv $outconfig $output_config"; 1933fcb3f16aSSteven Rostedt} 1934fcb3f16aSSteven Rostedt 1935fcb3f16aSSteven Rostedtsub make_oldconfig { 1936fcb3f16aSSteven Rostedt 19374c4ab120SSteven Rostedt my @force_list = keys %force_config; 19384c4ab120SSteven Rostedt 19394c4ab120SSteven Rostedt if ($#force_list >= 0) { 1940fcb3f16aSSteven Rostedt apply_min_config; 19414c4ab120SSteven Rostedt } 1942fcb3f16aSSteven Rostedt 1943fb16d891SAdam Lee if (!run_command "$make olddefconfig") { 1944fb16d891SAdam Lee # Perhaps olddefconfig doesn't exist in this version of the kernel 1945612b9e9bSSteven Rostedt # try a yes '' | oldconfig 1946fb16d891SAdam Lee doprint "olddefconfig failed, trying yes '' | make oldconfig\n"; 1947fcb3f16aSSteven Rostedt run_command "yes '' | $make oldconfig" or 1948612b9e9bSSteven Rostedt dodie "failed make config oldconfig"; 1949612b9e9bSSteven Rostedt } 1950612b9e9bSSteven Rostedt} 1951612b9e9bSSteven Rostedt 1952fcb3f16aSSteven Rostedt# read a config file and use this to force new configs. 1953fcb3f16aSSteven Rostedtsub load_force_config { 1954fcb3f16aSSteven Rostedt my ($config) = @_; 1955fcb3f16aSSteven Rostedt 1956cf79fab6SSteven Rostedt doprint "Loading force configs from $config\n"; 1957fcb3f16aSSteven Rostedt open(IN, $config) or 1958fcb3f16aSSteven Rostedt dodie "failed to read $config"; 1959fcb3f16aSSteven Rostedt while (<IN>) { 1960fcb3f16aSSteven Rostedt chomp; 1961fcb3f16aSSteven Rostedt if (/^(CONFIG[^\s=]*)(\s*=.*)/) { 1962fcb3f16aSSteven Rostedt $force_config{$1} = $_; 1963fcb3f16aSSteven Rostedt } elsif (/^# (CONFIG_\S*) is not set/) { 1964fcb3f16aSSteven Rostedt $force_config{$1} = $_; 1965fcb3f16aSSteven Rostedt } 1966fcb3f16aSSteven Rostedt } 1967fcb3f16aSSteven Rostedt close IN; 1968fcb3f16aSSteven Rostedt} 1969fcb3f16aSSteven Rostedt 19702545eb61SSteven Rostedtsub build { 19712545eb61SSteven Rostedt my ($type) = @_; 19722545eb61SSteven Rostedt 19737faafbd6SSteven Rostedt unlink $buildlog; 19747faafbd6SSteven Rostedt 19754ab1cce5SSteven Rostedt # Failed builds should not reboot the target 19764ab1cce5SSteven Rostedt my $save_no_reboot = $no_reboot; 19774ab1cce5SSteven Rostedt $no_reboot = 1; 19784ab1cce5SSteven Rostedt 1979683a3e64SSteven Rostedt # Calculate a new version from here. 1980683a3e64SSteven Rostedt $have_version = 0; 1981683a3e64SSteven Rostedt 19820bd6c1a3SSteven Rostedt if (defined($pre_build)) { 19830bd6c1a3SSteven Rostedt my $ret = run_command $pre_build; 19840bd6c1a3SSteven Rostedt if (!$ret && defined($pre_build_die) && 19850bd6c1a3SSteven Rostedt $pre_build_die) { 19860bd6c1a3SSteven Rostedt dodie "failed to pre_build\n"; 19870bd6c1a3SSteven Rostedt } 19880bd6c1a3SSteven Rostedt } 19890bd6c1a3SSteven Rostedt 199075c3fda7SSteven Rostedt if ($type =~ /^useconfig:(.*)/) { 199151ad1dd1SSteven Rostedt run_command "cp $1 $output_config" or 199275c3fda7SSteven Rostedt dodie "could not copy $1 to .config"; 19935f9b6cedSSteven Rostedt 199475c3fda7SSteven Rostedt $type = "oldconfig"; 199575c3fda7SSteven Rostedt } 199675c3fda7SSteven Rostedt 19975c42fc5bSSteven Rostedt # old config can ask questions 19985c42fc5bSSteven Rostedt if ($type eq "oldconfig") { 1999fb16d891SAdam Lee $type = "olddefconfig"; 200075c3fda7SSteven Rostedt 200175c3fda7SSteven Rostedt # allow for empty configs 200251ad1dd1SSteven Rostedt run_command "touch $output_config"; 200375c3fda7SSteven Rostedt 200413488231SAndrew Jones if (!$noclean) { 200551ad1dd1SSteven Rostedt run_command "mv $output_config $outputdir/config_temp" or 20065c42fc5bSSteven Rostedt dodie "moving .config"; 20075c42fc5bSSteven Rostedt 200813488231SAndrew Jones run_command "$make mrproper" or dodie "make mrproper"; 20095c42fc5bSSteven Rostedt 201051ad1dd1SSteven Rostedt run_command "mv $outputdir/config_temp $output_config" or 20115c42fc5bSSteven Rostedt dodie "moving config_temp"; 201213488231SAndrew Jones } 20135c42fc5bSSteven Rostedt 20145c42fc5bSSteven Rostedt } elsif (!$noclean) { 201551ad1dd1SSteven Rostedt unlink "$output_config"; 20165f9b6cedSSteven Rostedt run_command "$make mrproper" or 20175c42fc5bSSteven Rostedt dodie "make mrproper"; 20185c42fc5bSSteven Rostedt } 20192545eb61SSteven Rostedt 20202545eb61SSteven Rostedt # add something to distinguish this build 2021a75fececSSteven Rostedt open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 2022a75fececSSteven Rostedt print OUT "$localversion\n"; 20232545eb61SSteven Rostedt close(OUT); 20242545eb61SSteven Rostedt 20255f9b6cedSSteven Rostedt if (defined($minconfig)) { 2026fcb3f16aSSteven Rostedt load_force_config($minconfig); 20272545eb61SSteven Rostedt } 20282545eb61SSteven Rostedt 2029fb16d891SAdam Lee if ($type ne "olddefconfig") { 2030fcb3f16aSSteven Rostedt run_command "$make $type" or 20315c42fc5bSSteven Rostedt dodie "failed make config"; 2032612b9e9bSSteven Rostedt } 2033fcb3f16aSSteven Rostedt # Run old config regardless, to enforce min configurations 2034fcb3f16aSSteven Rostedt make_oldconfig; 20352545eb61SSteven Rostedt 2036a75fececSSteven Rostedt $redirect = "$buildlog"; 20370bd6c1a3SSteven Rostedt my $build_ret = run_command "$make $build_options"; 20386c5ee0beSSteven Rostedt undef $redirect; 20390bd6c1a3SSteven Rostedt 20400bd6c1a3SSteven Rostedt if (defined($post_build)) { 2041683a3e64SSteven Rostedt # Because a post build may change the kernel version 2042683a3e64SSteven Rostedt # do it now. 2043683a3e64SSteven Rostedt get_version; 20440bd6c1a3SSteven Rostedt my $ret = run_command $post_build; 20450bd6c1a3SSteven Rostedt if (!$ret && defined($post_build_die) && 20460bd6c1a3SSteven Rostedt $post_build_die) { 20470bd6c1a3SSteven Rostedt dodie "failed to post_build\n"; 20480bd6c1a3SSteven Rostedt } 20490bd6c1a3SSteven Rostedt } 20500bd6c1a3SSteven Rostedt 20510bd6c1a3SSteven Rostedt if (!$build_ret) { 20525f9b6cedSSteven Rostedt # bisect may need this to pass 20534ab1cce5SSteven Rostedt if ($in_bisect) { 20544ab1cce5SSteven Rostedt $no_reboot = $save_no_reboot; 20554ab1cce5SSteven Rostedt return 0; 20564ab1cce5SSteven Rostedt } 20572b7d9b21SSteven Rostedt fail "failed build" and return 0; 20582545eb61SSteven Rostedt } 20595f9b6cedSSteven Rostedt 20604ab1cce5SSteven Rostedt $no_reboot = $save_no_reboot; 20614ab1cce5SSteven Rostedt 20622b7d9b21SSteven Rostedt return 1; 20632545eb61SSteven Rostedt} 20642545eb61SSteven Rostedt 206575c3fda7SSteven Rostedtsub halt { 2066e48c5293SSteven Rostedt if (!run_ssh "halt" or defined($power_off)) { 2067576f627cSSteven Rostedt if (defined($poweroff_after_halt)) { 2068576f627cSSteven Rostedt sleep $poweroff_after_halt; 2069576f627cSSteven Rostedt run_command "$power_off"; 2070576f627cSSteven Rostedt } 2071576f627cSSteven Rostedt } else { 207275c3fda7SSteven Rostedt # nope? the zap it! 2073a75fececSSteven Rostedt run_command "$power_off"; 207475c3fda7SSteven Rostedt } 207575c3fda7SSteven Rostedt} 207675c3fda7SSteven Rostedt 20775f9b6cedSSteven Rostedtsub success { 20785f9b6cedSSteven Rostedt my ($i) = @_; 20795f9b6cedSSteven Rostedt 2080921ed4c7SSteven Rostedt if (defined($post_test)) { 2081921ed4c7SSteven Rostedt run_command $post_test; 2082921ed4c7SSteven Rostedt } 2083921ed4c7SSteven Rostedt 2084e48c5293SSteven Rostedt $successes++; 2085e48c5293SSteven Rostedt 20869064af52SSteven Rostedt my $name = ""; 20879064af52SSteven Rostedt 20889064af52SSteven Rostedt if (defined($test_name)) { 20899064af52SSteven Rostedt $name = " ($test_name)"; 20909064af52SSteven Rostedt } 20919064af52SSteven Rostedt 20925f9b6cedSSteven Rostedt doprint "\n\n*******************************************\n"; 20935f9b6cedSSteven Rostedt doprint "*******************************************\n"; 20949064af52SSteven Rostedt doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; 20955f9b6cedSSteven Rostedt doprint "*******************************************\n"; 20965f9b6cedSSteven Rostedt doprint "*******************************************\n"; 20975f9b6cedSSteven Rostedt 2098de5b6e3bSRabin Vincent if (defined($store_successes)) { 2099de5b6e3bSRabin Vincent save_logs "success", $store_successes; 2100de5b6e3bSRabin Vincent } 2101de5b6e3bSRabin Vincent 2102576f627cSSteven Rostedt if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 2103a75fececSSteven Rostedt doprint "Reboot and wait $sleep_time seconds\n"; 2104bc7c5803SSteven Rostedt reboot_to_good $sleep_time; 21055f9b6cedSSteven Rostedt } 21065f9b6cedSSteven Rostedt} 21075f9b6cedSSteven Rostedt 2108c960bb9fSSteven Rostedtsub answer_bisect { 2109c960bb9fSSteven Rostedt for (;;) { 2110c960bb9fSSteven Rostedt doprint "Pass or fail? [p/f]"; 2111c960bb9fSSteven Rostedt my $ans = <STDIN>; 2112c960bb9fSSteven Rostedt chomp $ans; 2113c960bb9fSSteven Rostedt if ($ans eq "p" || $ans eq "P") { 2114c960bb9fSSteven Rostedt return 1; 2115c960bb9fSSteven Rostedt } elsif ($ans eq "f" || $ans eq "F") { 2116c960bb9fSSteven Rostedt return 0; 2117c960bb9fSSteven Rostedt } else { 2118c960bb9fSSteven Rostedt print "Please answer 'P' or 'F'\n"; 2119c960bb9fSSteven Rostedt } 2120c960bb9fSSteven Rostedt } 2121c960bb9fSSteven Rostedt} 2122c960bb9fSSteven Rostedt 21235a391fbfSSteven Rostedtsub child_run_test { 21247faafbd6SSteven Rostedt my $failed = 0; 21255a391fbfSSteven Rostedt 21267faafbd6SSteven Rostedt # child should have no power 2127a75fececSSteven Rostedt $reboot_on_error = 0; 2128a75fececSSteven Rostedt $poweroff_on_error = 0; 2129a75fececSSteven Rostedt $die_on_failure = 1; 21307faafbd6SSteven Rostedt 2131a9dd5d63SRabin Vincent $redirect = "$testlog"; 21327faafbd6SSteven Rostedt run_command $run_test or $failed = 1; 2133a9dd5d63SRabin Vincent undef $redirect; 2134a9dd5d63SRabin Vincent 21355a391fbfSSteven Rostedt exit $failed; 21365a391fbfSSteven Rostedt} 21375a391fbfSSteven Rostedt 21385a391fbfSSteven Rostedtmy $child_done; 21395a391fbfSSteven Rostedt 21405a391fbfSSteven Rostedtsub child_finished { 21415a391fbfSSteven Rostedt $child_done = 1; 21425a391fbfSSteven Rostedt} 21435a391fbfSSteven Rostedt 21445a391fbfSSteven Rostedtsub do_run_test { 21455a391fbfSSteven Rostedt my $child_pid; 21465a391fbfSSteven Rostedt my $child_exit; 21475a391fbfSSteven Rostedt my $line; 21485a391fbfSSteven Rostedt my $full_line; 21495a391fbfSSteven Rostedt my $bug = 0; 21509b1d367dSSteven Rostedt my $bug_ignored = 0; 21515a391fbfSSteven Rostedt 21527faafbd6SSteven Rostedt wait_for_monitor 1; 21535a391fbfSSteven Rostedt 21547faafbd6SSteven Rostedt doprint "run test $run_test\n"; 21555a391fbfSSteven Rostedt 21565a391fbfSSteven Rostedt $child_done = 0; 21575a391fbfSSteven Rostedt 21585a391fbfSSteven Rostedt $SIG{CHLD} = qw(child_finished); 21595a391fbfSSteven Rostedt 21605a391fbfSSteven Rostedt $child_pid = fork; 21615a391fbfSSteven Rostedt 21625a391fbfSSteven Rostedt child_run_test if (!$child_pid); 21635a391fbfSSteven Rostedt 21645a391fbfSSteven Rostedt $full_line = ""; 21655a391fbfSSteven Rostedt 21665a391fbfSSteven Rostedt do { 21677faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 21685a391fbfSSteven Rostedt if (defined($line)) { 21695a391fbfSSteven Rostedt 21705a391fbfSSteven Rostedt # we are not guaranteed to get a full line 21715a391fbfSSteven Rostedt $full_line .= $line; 21728ea0e063SSteven Rostedt doprint $line; 21735a391fbfSSteven Rostedt 21745a391fbfSSteven Rostedt if ($full_line =~ /call trace:/i) { 21759b1d367dSSteven Rostedt if ($ignore_errors) { 21769b1d367dSSteven Rostedt $bug_ignored = 1; 21779b1d367dSSteven Rostedt } else { 21785a391fbfSSteven Rostedt $bug = 1; 21795a391fbfSSteven Rostedt } 21809b1d367dSSteven Rostedt } 21815a391fbfSSteven Rostedt 21825a391fbfSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 21835a391fbfSSteven Rostedt $bug = 1; 21845a391fbfSSteven Rostedt } 21855a391fbfSSteven Rostedt 21865a391fbfSSteven Rostedt if ($line =~ /\n/) { 21875a391fbfSSteven Rostedt $full_line = ""; 21885a391fbfSSteven Rostedt } 21895a391fbfSSteven Rostedt } 21905a391fbfSSteven Rostedt } while (!$child_done && !$bug); 21915a391fbfSSteven Rostedt 21929b1d367dSSteven Rostedt if (!$bug && $bug_ignored) { 21939b1d367dSSteven Rostedt doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 21949b1d367dSSteven Rostedt } 21959b1d367dSSteven Rostedt 21965a391fbfSSteven Rostedt if ($bug) { 21978ea0e063SSteven Rostedt my $failure_start = time; 21988ea0e063SSteven Rostedt my $now; 21998ea0e063SSteven Rostedt do { 22008ea0e063SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 22018ea0e063SSteven Rostedt if (defined($line)) { 22028ea0e063SSteven Rostedt doprint $line; 22038ea0e063SSteven Rostedt } 22048ea0e063SSteven Rostedt $now = time; 22058ea0e063SSteven Rostedt if ($now - $failure_start >= $stop_after_failure) { 22068ea0e063SSteven Rostedt last; 22078ea0e063SSteven Rostedt } 22088ea0e063SSteven Rostedt } while (defined($line)); 22098ea0e063SSteven Rostedt 22105a391fbfSSteven Rostedt doprint "Detected kernel crash!\n"; 22115a391fbfSSteven Rostedt # kill the child with extreme prejudice 22125a391fbfSSteven Rostedt kill 9, $child_pid; 22135a391fbfSSteven Rostedt } 22145a391fbfSSteven Rostedt 22155a391fbfSSteven Rostedt waitpid $child_pid, 0; 22165a391fbfSSteven Rostedt $child_exit = $?; 22175a391fbfSSteven Rostedt 2218c5dacb88SSteven Rostedt if (!$bug && $in_bisect) { 2219c5dacb88SSteven Rostedt if (defined($bisect_ret_good)) { 2220c5dacb88SSteven Rostedt if ($child_exit == $bisect_ret_good) { 2221c5dacb88SSteven Rostedt return 1; 2222c5dacb88SSteven Rostedt } 2223c5dacb88SSteven Rostedt } 2224c5dacb88SSteven Rostedt if (defined($bisect_ret_skip)) { 2225c5dacb88SSteven Rostedt if ($child_exit == $bisect_ret_skip) { 2226c5dacb88SSteven Rostedt return -1; 2227c5dacb88SSteven Rostedt } 2228c5dacb88SSteven Rostedt } 2229c5dacb88SSteven Rostedt if (defined($bisect_ret_abort)) { 2230c5dacb88SSteven Rostedt if ($child_exit == $bisect_ret_abort) { 2231c5dacb88SSteven Rostedt fail "test abort" and return -2; 2232c5dacb88SSteven Rostedt } 2233c5dacb88SSteven Rostedt } 2234c5dacb88SSteven Rostedt if (defined($bisect_ret_bad)) { 2235c5dacb88SSteven Rostedt if ($child_exit == $bisect_ret_skip) { 2236c5dacb88SSteven Rostedt return 0; 2237c5dacb88SSteven Rostedt } 2238c5dacb88SSteven Rostedt } 2239c5dacb88SSteven Rostedt if (defined($bisect_ret_default)) { 2240c5dacb88SSteven Rostedt if ($bisect_ret_default eq "good") { 2241c5dacb88SSteven Rostedt return 1; 2242c5dacb88SSteven Rostedt } elsif ($bisect_ret_default eq "bad") { 2243c5dacb88SSteven Rostedt return 0; 2244c5dacb88SSteven Rostedt } elsif ($bisect_ret_default eq "skip") { 2245c5dacb88SSteven Rostedt return -1; 2246c5dacb88SSteven Rostedt } elsif ($bisect_ret_default eq "abort") { 2247c5dacb88SSteven Rostedt return -2; 2248c5dacb88SSteven Rostedt } else { 2249c5dacb88SSteven Rostedt fail "unknown default action: $bisect_ret_default" 2250c5dacb88SSteven Rostedt and return -2; 2251c5dacb88SSteven Rostedt } 2252c5dacb88SSteven Rostedt } 2253c5dacb88SSteven Rostedt } 2254c5dacb88SSteven Rostedt 22555a391fbfSSteven Rostedt if ($bug || $child_exit) { 22562b7d9b21SSteven Rostedt return 0 if $in_bisect; 22572b7d9b21SSteven Rostedt fail "test failed" and return 0; 22585a391fbfSSteven Rostedt } 22592b7d9b21SSteven Rostedt return 1; 22605a391fbfSSteven Rostedt} 22615a391fbfSSteven Rostedt 2262a75fececSSteven Rostedtsub run_git_bisect { 2263a75fececSSteven Rostedt my ($command) = @_; 2264a75fececSSteven Rostedt 2265a75fececSSteven Rostedt doprint "$command ... "; 2266a75fececSSteven Rostedt 2267a75fececSSteven Rostedt my $output = `$command 2>&1`; 2268a75fececSSteven Rostedt my $ret = $?; 2269a75fececSSteven Rostedt 2270a75fececSSteven Rostedt logit $output; 2271a75fececSSteven Rostedt 2272a75fececSSteven Rostedt if ($ret) { 2273a75fececSSteven Rostedt doprint "FAILED\n"; 2274a75fececSSteven Rostedt dodie "Failed to git bisect"; 2275a75fececSSteven Rostedt } 2276a75fececSSteven Rostedt 2277a75fececSSteven Rostedt doprint "SUCCESS\n"; 2278a75fececSSteven Rostedt if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 2279a75fececSSteven Rostedt doprint "$1 [$2]\n"; 2280a75fececSSteven Rostedt } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 2281b5f4aea6SSteven Rostedt $bisect_bad_commit = $1; 2282a75fececSSteven Rostedt doprint "Found bad commit... $1\n"; 2283a75fececSSteven Rostedt return 0; 2284a75fececSSteven Rostedt } else { 2285a75fececSSteven Rostedt # we already logged it, just print it now. 2286a75fececSSteven Rostedt print $output; 2287a75fececSSteven Rostedt } 2288a75fececSSteven Rostedt 2289a75fececSSteven Rostedt return 1; 2290a75fececSSteven Rostedt} 2291a75fececSSteven Rostedt 2292c23dca7cSSteven Rostedtsub bisect_reboot { 2293c23dca7cSSteven Rostedt doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 2294bc7c5803SSteven Rostedt reboot_to_good $bisect_sleep_time; 2295c23dca7cSSteven Rostedt} 2296c23dca7cSSteven Rostedt 2297c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip 22980a05c769SSteven Rostedtsub run_bisect_test { 22990a05c769SSteven Rostedt my ($type, $buildtype) = @_; 23005f9b6cedSSteven Rostedt 23012b7d9b21SSteven Rostedt my $failed = 0; 23025f9b6cedSSteven Rostedt my $result; 23035f9b6cedSSteven Rostedt my $output; 23045f9b6cedSSteven Rostedt my $ret; 23055f9b6cedSSteven Rostedt 23060a05c769SSteven Rostedt $in_bisect = 1; 23070a05c769SSteven Rostedt 23080a05c769SSteven Rostedt build $buildtype or $failed = 1; 23095f9b6cedSSteven Rostedt 23105f9b6cedSSteven Rostedt if ($type ne "build") { 2311c23dca7cSSteven Rostedt if ($failed && $bisect_skip) { 2312c23dca7cSSteven Rostedt $in_bisect = 0; 2313c23dca7cSSteven Rostedt return -1; 2314c23dca7cSSteven Rostedt } 23157faafbd6SSteven Rostedt dodie "Failed on build" if $failed; 23165f9b6cedSSteven Rostedt 23175f9b6cedSSteven Rostedt # Now boot the box 2318ddf607e5SSteven Rostedt start_monitor_and_boot or $failed = 1; 23195f9b6cedSSteven Rostedt 23205f9b6cedSSteven Rostedt if ($type ne "boot") { 2321c23dca7cSSteven Rostedt if ($failed && $bisect_skip) { 2322c23dca7cSSteven Rostedt end_monitor; 2323c23dca7cSSteven Rostedt bisect_reboot; 2324c23dca7cSSteven Rostedt $in_bisect = 0; 2325c23dca7cSSteven Rostedt return -1; 2326c23dca7cSSteven Rostedt } 23277faafbd6SSteven Rostedt dodie "Failed on boot" if $failed; 23285a391fbfSSteven Rostedt 23292b7d9b21SSteven Rostedt do_run_test or $failed = 1; 23305f9b6cedSSteven Rostedt } 23317faafbd6SSteven Rostedt end_monitor; 23325f9b6cedSSteven Rostedt } 23335f9b6cedSSteven Rostedt 23345f9b6cedSSteven Rostedt if ($failed) { 23350a05c769SSteven Rostedt $result = 0; 23365f9b6cedSSteven Rostedt } else { 23370a05c769SSteven Rostedt $result = 1; 23385f9b6cedSSteven Rostedt } 23394025bc62SSteven Rostedt 23404025bc62SSteven Rostedt # reboot the box to a kernel we can ssh to 23414025bc62SSteven Rostedt if ($type ne "build") { 23424025bc62SSteven Rostedt bisect_reboot; 23434025bc62SSteven Rostedt } 23440a05c769SSteven Rostedt $in_bisect = 0; 23450a05c769SSteven Rostedt 23460a05c769SSteven Rostedt return $result; 23470a05c769SSteven Rostedt} 23480a05c769SSteven Rostedt 23490a05c769SSteven Rostedtsub run_bisect { 23500a05c769SSteven Rostedt my ($type) = @_; 23510a05c769SSteven Rostedt my $buildtype = "oldconfig"; 23520a05c769SSteven Rostedt 23530a05c769SSteven Rostedt # We should have a minconfig to use? 23540a05c769SSteven Rostedt if (defined($minconfig)) { 23550a05c769SSteven Rostedt $buildtype = "useconfig:$minconfig"; 23560a05c769SSteven Rostedt } 23570a05c769SSteven Rostedt 23580a05c769SSteven Rostedt my $ret = run_bisect_test $type, $buildtype; 23590a05c769SSteven Rostedt 2360c960bb9fSSteven Rostedt if ($bisect_manual) { 2361c960bb9fSSteven Rostedt $ret = answer_bisect; 2362c960bb9fSSteven Rostedt } 23635f9b6cedSSteven Rostedt 2364d6ce2a0bSSteven Rostedt # Are we looking for where it worked, not failed? 23655158ba3eSRuss Dill if ($reverse_bisect && $ret >= 0) { 23660a05c769SSteven Rostedt $ret = !$ret; 2367d6ce2a0bSSteven Rostedt } 2368d6ce2a0bSSteven Rostedt 2369c23dca7cSSteven Rostedt if ($ret > 0) { 23700a05c769SSteven Rostedt return "good"; 2371c23dca7cSSteven Rostedt } elsif ($ret == 0) { 23720a05c769SSteven Rostedt return "bad"; 2373c23dca7cSSteven Rostedt } elsif ($bisect_skip) { 2374c23dca7cSSteven Rostedt doprint "HIT A BAD COMMIT ... SKIPPING\n"; 2375c23dca7cSSteven Rostedt return "skip"; 23760a05c769SSteven Rostedt } 23775f9b6cedSSteven Rostedt} 23785f9b6cedSSteven Rostedt 2379dad98754SSteven Rostedtsub update_bisect_replay { 2380dad98754SSteven Rostedt my $tmp_log = "$tmpdir/ktest_bisect_log"; 2381dad98754SSteven Rostedt run_command "git bisect log > $tmp_log" or 2382dad98754SSteven Rostedt die "can't create bisect log"; 2383dad98754SSteven Rostedt return $tmp_log; 2384dad98754SSteven Rostedt} 2385dad98754SSteven Rostedt 23865f9b6cedSSteven Rostedtsub bisect { 23875f9b6cedSSteven Rostedt my ($i) = @_; 23885f9b6cedSSteven Rostedt 23895f9b6cedSSteven Rostedt my $result; 23905f9b6cedSSteven Rostedt 2391b5f4aea6SSteven Rostedt die "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good)); 2392b5f4aea6SSteven Rostedt die "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad)); 2393b5f4aea6SSteven Rostedt die "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type)); 23945f9b6cedSSteven Rostedt 2395b5f4aea6SSteven Rostedt my $good = $bisect_good; 2396b5f4aea6SSteven Rostedt my $bad = $bisect_bad; 2397b5f4aea6SSteven Rostedt my $type = $bisect_type; 2398b5f4aea6SSteven Rostedt my $start = $bisect_start; 2399b5f4aea6SSteven Rostedt my $replay = $bisect_replay; 2400b5f4aea6SSteven Rostedt my $start_files = $bisect_files; 24013410f6fdSSteven Rostedt 24023410f6fdSSteven Rostedt if (defined($start_files)) { 24033410f6fdSSteven Rostedt $start_files = " -- " . $start_files; 24043410f6fdSSteven Rostedt } else { 24053410f6fdSSteven Rostedt $start_files = ""; 24063410f6fdSSteven Rostedt } 24075f9b6cedSSteven Rostedt 2408a57419b3SSteven Rostedt # convert to true sha1's 2409a57419b3SSteven Rostedt $good = get_sha1($good); 2410a57419b3SSteven Rostedt $bad = get_sha1($bad); 2411a57419b3SSteven Rostedt 2412b5f4aea6SSteven Rostedt if (defined($bisect_reverse) && $bisect_reverse == 1) { 2413d6ce2a0bSSteven Rostedt doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 2414d6ce2a0bSSteven Rostedt $reverse_bisect = 1; 2415d6ce2a0bSSteven Rostedt } else { 2416d6ce2a0bSSteven Rostedt $reverse_bisect = 0; 2417d6ce2a0bSSteven Rostedt } 2418d6ce2a0bSSteven Rostedt 24195a391fbfSSteven Rostedt # Can't have a test without having a test to run 24205a391fbfSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 24215a391fbfSSteven Rostedt $type = "boot"; 24225a391fbfSSteven Rostedt } 24235a391fbfSSteven Rostedt 2424dad98754SSteven Rostedt # Check if a bisect was running 2425dad98754SSteven Rostedt my $bisect_start_file = "$builddir/.git/BISECT_START"; 2426dad98754SSteven Rostedt 2427b5f4aea6SSteven Rostedt my $check = $bisect_check; 2428dad98754SSteven Rostedt my $do_check = defined($check) && $check ne "0"; 2429dad98754SSteven Rostedt 2430dad98754SSteven Rostedt if ( -f $bisect_start_file ) { 2431dad98754SSteven Rostedt print "Bisect in progress found\n"; 2432dad98754SSteven Rostedt if ($do_check) { 2433dad98754SSteven Rostedt print " If you say yes, then no checks of good or bad will be done\n"; 2434dad98754SSteven Rostedt } 2435dad98754SSteven Rostedt if (defined($replay)) { 2436dad98754SSteven Rostedt print "** BISECT_REPLAY is defined in config file **"; 2437dad98754SSteven Rostedt print " Ignore config option and perform new git bisect log?\n"; 2438dad98754SSteven Rostedt if (read_ync " (yes, no, or cancel) ") { 2439dad98754SSteven Rostedt $replay = update_bisect_replay; 2440dad98754SSteven Rostedt $do_check = 0; 2441dad98754SSteven Rostedt } 2442dad98754SSteven Rostedt } elsif (read_yn "read git log and continue?") { 2443dad98754SSteven Rostedt $replay = update_bisect_replay; 2444dad98754SSteven Rostedt $do_check = 0; 2445dad98754SSteven Rostedt } 2446dad98754SSteven Rostedt } 2447dad98754SSteven Rostedt 2448dad98754SSteven Rostedt if ($do_check) { 2449a75fececSSteven Rostedt 2450a75fececSSteven Rostedt # get current HEAD 2451a57419b3SSteven Rostedt my $head = get_sha1("HEAD"); 2452a75fececSSteven Rostedt 2453a75fececSSteven Rostedt if ($check ne "good") { 2454a75fececSSteven Rostedt doprint "TESTING BISECT BAD [$bad]\n"; 2455a75fececSSteven Rostedt run_command "git checkout $bad" or 2456a75fececSSteven Rostedt die "Failed to checkout $bad"; 2457a75fececSSteven Rostedt 2458a75fececSSteven Rostedt $result = run_bisect $type; 2459a75fececSSteven Rostedt 2460a75fececSSteven Rostedt if ($result ne "bad") { 2461a75fececSSteven Rostedt fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 2462a75fececSSteven Rostedt } 2463a75fececSSteven Rostedt } 2464a75fececSSteven Rostedt 2465a75fececSSteven Rostedt if ($check ne "bad") { 2466a75fececSSteven Rostedt doprint "TESTING BISECT GOOD [$good]\n"; 2467a75fececSSteven Rostedt run_command "git checkout $good" or 2468a75fececSSteven Rostedt die "Failed to checkout $good"; 2469a75fececSSteven Rostedt 2470a75fececSSteven Rostedt $result = run_bisect $type; 2471a75fececSSteven Rostedt 2472a75fececSSteven Rostedt if ($result ne "good") { 2473a75fececSSteven Rostedt fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 2474a75fececSSteven Rostedt } 2475a75fececSSteven Rostedt } 2476a75fececSSteven Rostedt 2477a75fececSSteven Rostedt # checkout where we started 2478a75fececSSteven Rostedt run_command "git checkout $head" or 2479a75fececSSteven Rostedt die "Failed to checkout $head"; 2480a75fececSSteven Rostedt } 2481a75fececSSteven Rostedt 24823410f6fdSSteven Rostedt run_command "git bisect start$start_files" or 2483a75fececSSteven Rostedt dodie "could not start bisect"; 2484a75fececSSteven Rostedt 2485a75fececSSteven Rostedt run_command "git bisect good $good" or 2486a75fececSSteven Rostedt dodie "could not set bisect good to $good"; 2487a75fececSSteven Rostedt 2488a75fececSSteven Rostedt run_git_bisect "git bisect bad $bad" or 2489a75fececSSteven Rostedt dodie "could not set bisect bad to $bad"; 2490a75fececSSteven Rostedt 2491a75fececSSteven Rostedt if (defined($replay)) { 2492a75fececSSteven Rostedt run_command "git bisect replay $replay" or 2493a75fececSSteven Rostedt dodie "failed to run replay"; 2494a75fececSSteven Rostedt } 2495a75fececSSteven Rostedt 2496a75fececSSteven Rostedt if (defined($start)) { 2497a75fececSSteven Rostedt run_command "git checkout $start" or 2498a75fececSSteven Rostedt dodie "failed to checkout $start"; 2499a75fececSSteven Rostedt } 2500a75fececSSteven Rostedt 2501a75fececSSteven Rostedt my $test; 25025f9b6cedSSteven Rostedt do { 25035f9b6cedSSteven Rostedt $result = run_bisect $type; 2504a75fececSSteven Rostedt $test = run_git_bisect "git bisect $result"; 2505a75fececSSteven Rostedt } while ($test); 25065f9b6cedSSteven Rostedt 25075f9b6cedSSteven Rostedt run_command "git bisect log" or 25085f9b6cedSSteven Rostedt dodie "could not capture git bisect log"; 25095f9b6cedSSteven Rostedt 25105f9b6cedSSteven Rostedt run_command "git bisect reset" or 25115f9b6cedSSteven Rostedt dodie "could not reset git bisect"; 25125f9b6cedSSteven Rostedt 2513b5f4aea6SSteven Rostedt doprint "Bad commit was [$bisect_bad_commit]\n"; 25145f9b6cedSSteven Rostedt 25150a05c769SSteven Rostedt success $i; 25160a05c769SSteven Rostedt} 25170a05c769SSteven Rostedt 2518cf79fab6SSteven Rostedt# config_ignore holds the configs that were set (or unset) for 2519cf79fab6SSteven Rostedt# a good config and we will ignore these configs for the rest 2520cf79fab6SSteven Rostedt# of a config bisect. These configs stay as they were. 25210a05c769SSteven Rostedtmy %config_ignore; 2522cf79fab6SSteven Rostedt 2523cf79fab6SSteven Rostedt# config_set holds what all configs were set as. 25240a05c769SSteven Rostedtmy %config_set; 25250a05c769SSteven Rostedt 2526cf79fab6SSteven Rostedt# config_off holds the set of configs that the bad config had disabled. 2527cf79fab6SSteven Rostedt# We need to record them and set them in the .config when running 2528fb16d891SAdam Lee# olddefconfig, because olddefconfig keeps the defaults. 2529cf79fab6SSteven Rostedtmy %config_off; 2530cf79fab6SSteven Rostedt 2531cf79fab6SSteven Rostedt# config_off_tmp holds a set of configs to turn off for now 2532cf79fab6SSteven Rostedtmy @config_off_tmp; 2533cf79fab6SSteven Rostedt 2534cf79fab6SSteven Rostedt# config_list is the set of configs that are being tested 25350a05c769SSteven Rostedtmy %config_list; 25360a05c769SSteven Rostedtmy %null_config; 25370a05c769SSteven Rostedt 25380a05c769SSteven Rostedtmy %dependency; 25390a05c769SSteven Rostedt 25404c4ab120SSteven Rostedtsub assign_configs { 25414c4ab120SSteven Rostedt my ($hash, $config) = @_; 25420a05c769SSteven Rostedt 25430a05c769SSteven Rostedt open (IN, $config) 25440a05c769SSteven Rostedt or dodie "Failed to read $config"; 25450a05c769SSteven Rostedt 25460a05c769SSteven Rostedt while (<IN>) { 25479bf71749SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 25484c4ab120SSteven Rostedt ${$hash}{$2} = $1; 25490a05c769SSteven Rostedt } 25500a05c769SSteven Rostedt } 25510a05c769SSteven Rostedt 25520a05c769SSteven Rostedt close(IN); 25530a05c769SSteven Rostedt} 25540a05c769SSteven Rostedt 25554c4ab120SSteven Rostedtsub process_config_ignore { 25564c4ab120SSteven Rostedt my ($config) = @_; 25574c4ab120SSteven Rostedt 25584c4ab120SSteven Rostedt assign_configs \%config_ignore, $config; 25594c4ab120SSteven Rostedt} 25604c4ab120SSteven Rostedt 25610a05c769SSteven Rostedtsub read_current_config { 25620a05c769SSteven Rostedt my ($config_ref) = @_; 25630a05c769SSteven Rostedt 25640a05c769SSteven Rostedt %{$config_ref} = (); 25650a05c769SSteven Rostedt undef %{$config_ref}; 25660a05c769SSteven Rostedt 25670a05c769SSteven Rostedt my @key = keys %{$config_ref}; 25680a05c769SSteven Rostedt if ($#key >= 0) { 25690a05c769SSteven Rostedt print "did not delete!\n"; 25700a05c769SSteven Rostedt exit; 25710a05c769SSteven Rostedt } 25720a05c769SSteven Rostedt open (IN, "$output_config"); 25730a05c769SSteven Rostedt 25740a05c769SSteven Rostedt while (<IN>) { 25750a05c769SSteven Rostedt if (/^(CONFIG\S+)=(.*)/) { 25760a05c769SSteven Rostedt ${$config_ref}{$1} = $2; 25770a05c769SSteven Rostedt } 25780a05c769SSteven Rostedt } 25790a05c769SSteven Rostedt close(IN); 25800a05c769SSteven Rostedt} 25810a05c769SSteven Rostedt 25820a05c769SSteven Rostedtsub get_dependencies { 25830a05c769SSteven Rostedt my ($config) = @_; 25840a05c769SSteven Rostedt 25850a05c769SSteven Rostedt my $arr = $dependency{$config}; 25860a05c769SSteven Rostedt if (!defined($arr)) { 25870a05c769SSteven Rostedt return (); 25880a05c769SSteven Rostedt } 25890a05c769SSteven Rostedt 25900a05c769SSteven Rostedt my @deps = @{$arr}; 25910a05c769SSteven Rostedt 25920a05c769SSteven Rostedt foreach my $dep (@{$arr}) { 25930a05c769SSteven Rostedt print "ADD DEP $dep\n"; 25940a05c769SSteven Rostedt @deps = (@deps, get_dependencies $dep); 25950a05c769SSteven Rostedt } 25960a05c769SSteven Rostedt 25970a05c769SSteven Rostedt return @deps; 25980a05c769SSteven Rostedt} 25990a05c769SSteven Rostedt 26000a05c769SSteven Rostedtsub create_config { 26010a05c769SSteven Rostedt my @configs = @_; 26020a05c769SSteven Rostedt 26030a05c769SSteven Rostedt open(OUT, ">$output_config") or dodie "Can not write to $output_config"; 26040a05c769SSteven Rostedt 26050a05c769SSteven Rostedt foreach my $config (@configs) { 26060a05c769SSteven Rostedt print OUT "$config_set{$config}\n"; 26070a05c769SSteven Rostedt my @deps = get_dependencies $config; 26080a05c769SSteven Rostedt foreach my $dep (@deps) { 26090a05c769SSteven Rostedt print OUT "$config_set{$dep}\n"; 26100a05c769SSteven Rostedt } 26110a05c769SSteven Rostedt } 26120a05c769SSteven Rostedt 2613cf79fab6SSteven Rostedt # turn off configs to keep off 2614cf79fab6SSteven Rostedt foreach my $config (keys %config_off) { 2615cf79fab6SSteven Rostedt print OUT "# $config is not set\n"; 2616cf79fab6SSteven Rostedt } 2617cf79fab6SSteven Rostedt 2618cf79fab6SSteven Rostedt # turn off configs that should be off for now 2619cf79fab6SSteven Rostedt foreach my $config (@config_off_tmp) { 2620cf79fab6SSteven Rostedt print OUT "# $config is not set\n"; 2621cf79fab6SSteven Rostedt } 2622cf79fab6SSteven Rostedt 26230a05c769SSteven Rostedt foreach my $config (keys %config_ignore) { 26240a05c769SSteven Rostedt print OUT "$config_ignore{$config}\n"; 26250a05c769SSteven Rostedt } 26260a05c769SSteven Rostedt close(OUT); 26270a05c769SSteven Rostedt 2628fcb3f16aSSteven Rostedt make_oldconfig; 26290a05c769SSteven Rostedt} 26300a05c769SSteven Rostedt 26310a05c769SSteven Rostedtsub compare_configs { 26320a05c769SSteven Rostedt my (%a, %b) = @_; 26330a05c769SSteven Rostedt 26340a05c769SSteven Rostedt foreach my $item (keys %a) { 26350a05c769SSteven Rostedt if (!defined($b{$item})) { 26360a05c769SSteven Rostedt print "diff $item\n"; 26370a05c769SSteven Rostedt return 1; 26380a05c769SSteven Rostedt } 26390a05c769SSteven Rostedt delete $b{$item}; 26400a05c769SSteven Rostedt } 26410a05c769SSteven Rostedt 26420a05c769SSteven Rostedt my @keys = keys %b; 26430a05c769SSteven Rostedt if ($#keys) { 26440a05c769SSteven Rostedt print "diff2 $keys[0]\n"; 26450a05c769SSteven Rostedt } 26460a05c769SSteven Rostedt return -1 if ($#keys >= 0); 26470a05c769SSteven Rostedt 26480a05c769SSteven Rostedt return 0; 26490a05c769SSteven Rostedt} 26500a05c769SSteven Rostedt 26510a05c769SSteven Rostedtsub run_config_bisect_test { 26520a05c769SSteven Rostedt my ($type) = @_; 26530a05c769SSteven Rostedt 26540a05c769SSteven Rostedt return run_bisect_test $type, "oldconfig"; 26550a05c769SSteven Rostedt} 26560a05c769SSteven Rostedt 26570a05c769SSteven Rostedtsub process_passed { 26580a05c769SSteven Rostedt my (%configs) = @_; 26590a05c769SSteven Rostedt 26600a05c769SSteven Rostedt doprint "These configs had no failure: (Enabling them for further compiles)\n"; 26610a05c769SSteven Rostedt # Passed! All these configs are part of a good compile. 26620a05c769SSteven Rostedt # Add them to the min options. 26630a05c769SSteven Rostedt foreach my $config (keys %configs) { 26640a05c769SSteven Rostedt if (defined($config_list{$config})) { 26650a05c769SSteven Rostedt doprint " removing $config\n"; 26660a05c769SSteven Rostedt $config_ignore{$config} = $config_list{$config}; 26670a05c769SSteven Rostedt delete $config_list{$config}; 26680a05c769SSteven Rostedt } 26690a05c769SSteven Rostedt } 2670f1a27850SSteven Rostedt doprint "config copied to $outputdir/config_good\n"; 2671f1a27850SSteven Rostedt run_command "cp -f $output_config $outputdir/config_good"; 26720a05c769SSteven Rostedt} 26730a05c769SSteven Rostedt 26740a05c769SSteven Rostedtsub process_failed { 26750a05c769SSteven Rostedt my ($config) = @_; 26760a05c769SSteven Rostedt 26770a05c769SSteven Rostedt doprint "\n\n***************************************\n"; 26780a05c769SSteven Rostedt doprint "Found bad config: $config\n"; 26790a05c769SSteven Rostedt doprint "***************************************\n\n"; 26800a05c769SSteven Rostedt} 26810a05c769SSteven Rostedt 26820a05c769SSteven Rostedtsub run_config_bisect { 26830a05c769SSteven Rostedt 26840a05c769SSteven Rostedt my @start_list = keys %config_list; 26850a05c769SSteven Rostedt 26860a05c769SSteven Rostedt if ($#start_list < 0) { 26870a05c769SSteven Rostedt doprint "No more configs to test!!!\n"; 26880a05c769SSteven Rostedt return -1; 26890a05c769SSteven Rostedt } 26900a05c769SSteven Rostedt 26910a05c769SSteven Rostedt doprint "***** RUN TEST ***\n"; 2692b5f4aea6SSteven Rostedt my $type = $config_bisect_type; 26930a05c769SSteven Rostedt my $ret; 26940a05c769SSteven Rostedt my %current_config; 26950a05c769SSteven Rostedt 26960a05c769SSteven Rostedt my $count = $#start_list + 1; 26970a05c769SSteven Rostedt doprint " $count configs to test\n"; 26980a05c769SSteven Rostedt 26990a05c769SSteven Rostedt my $half = int($#start_list / 2); 27000a05c769SSteven Rostedt 27010a05c769SSteven Rostedt do { 27020a05c769SSteven Rostedt my @tophalf = @start_list[0 .. $half]; 27030a05c769SSteven Rostedt 2704cf79fab6SSteven Rostedt # keep the bottom half off 2705cf79fab6SSteven Rostedt if ($half < $#start_list) { 2706cf79fab6SSteven Rostedt @config_off_tmp = @start_list[$half + 1 .. $#start_list]; 2707cf79fab6SSteven Rostedt } else { 2708cf79fab6SSteven Rostedt @config_off_tmp = (); 2709cf79fab6SSteven Rostedt } 2710cf79fab6SSteven Rostedt 27110a05c769SSteven Rostedt create_config @tophalf; 27120a05c769SSteven Rostedt read_current_config \%current_config; 27130a05c769SSteven Rostedt 27140a05c769SSteven Rostedt $count = $#tophalf + 1; 27150a05c769SSteven Rostedt doprint "Testing $count configs\n"; 27160a05c769SSteven Rostedt my $found = 0; 27170a05c769SSteven Rostedt # make sure we test something 27180a05c769SSteven Rostedt foreach my $config (@tophalf) { 27190a05c769SSteven Rostedt if (defined($current_config{$config})) { 27200a05c769SSteven Rostedt logit " $config\n"; 27210a05c769SSteven Rostedt $found = 1; 27220a05c769SSteven Rostedt } 27230a05c769SSteven Rostedt } 27240a05c769SSteven Rostedt if (!$found) { 27250a05c769SSteven Rostedt # try the other half 27260a05c769SSteven Rostedt doprint "Top half produced no set configs, trying bottom half\n"; 2727cf79fab6SSteven Rostedt 2728cf79fab6SSteven Rostedt # keep the top half off 2729cf79fab6SSteven Rostedt @config_off_tmp = @tophalf; 27304c8cc55bSSteven Rostedt @tophalf = @start_list[$half + 1 .. $#start_list]; 2731cf79fab6SSteven Rostedt 27320a05c769SSteven Rostedt create_config @tophalf; 27330a05c769SSteven Rostedt read_current_config \%current_config; 27340a05c769SSteven Rostedt foreach my $config (@tophalf) { 27350a05c769SSteven Rostedt if (defined($current_config{$config})) { 27360a05c769SSteven Rostedt logit " $config\n"; 27370a05c769SSteven Rostedt $found = 1; 27380a05c769SSteven Rostedt } 27390a05c769SSteven Rostedt } 27400a05c769SSteven Rostedt if (!$found) { 27410a05c769SSteven Rostedt doprint "Failed: Can't make new config with current configs\n"; 27420a05c769SSteven Rostedt foreach my $config (@start_list) { 27430a05c769SSteven Rostedt doprint " CONFIG: $config\n"; 27440a05c769SSteven Rostedt } 27450a05c769SSteven Rostedt return -1; 27460a05c769SSteven Rostedt } 27470a05c769SSteven Rostedt $count = $#tophalf + 1; 27480a05c769SSteven Rostedt doprint "Testing $count configs\n"; 27490a05c769SSteven Rostedt } 27500a05c769SSteven Rostedt 27510a05c769SSteven Rostedt $ret = run_config_bisect_test $type; 2752c960bb9fSSteven Rostedt if ($bisect_manual) { 2753c960bb9fSSteven Rostedt $ret = answer_bisect; 2754c960bb9fSSteven Rostedt } 27550a05c769SSteven Rostedt if ($ret) { 27560a05c769SSteven Rostedt process_passed %current_config; 27570a05c769SSteven Rostedt return 0; 27580a05c769SSteven Rostedt } 27590a05c769SSteven Rostedt 27600a05c769SSteven Rostedt doprint "This config had a failure.\n"; 27610a05c769SSteven Rostedt doprint "Removing these configs that were not set in this config:\n"; 2762f1a27850SSteven Rostedt doprint "config copied to $outputdir/config_bad\n"; 2763f1a27850SSteven Rostedt run_command "cp -f $output_config $outputdir/config_bad"; 27640a05c769SSteven Rostedt 27650a05c769SSteven Rostedt # A config exists in this group that was bad. 27660a05c769SSteven Rostedt foreach my $config (keys %config_list) { 27670a05c769SSteven Rostedt if (!defined($current_config{$config})) { 27680a05c769SSteven Rostedt doprint " removing $config\n"; 27690a05c769SSteven Rostedt delete $config_list{$config}; 27700a05c769SSteven Rostedt } 27710a05c769SSteven Rostedt } 27720a05c769SSteven Rostedt 27730a05c769SSteven Rostedt @start_list = @tophalf; 27740a05c769SSteven Rostedt 27750a05c769SSteven Rostedt if ($#start_list == 0) { 27760a05c769SSteven Rostedt process_failed $start_list[0]; 27770a05c769SSteven Rostedt return 1; 27780a05c769SSteven Rostedt } 27790a05c769SSteven Rostedt 27800a05c769SSteven Rostedt # remove half the configs we are looking at and see if 27810a05c769SSteven Rostedt # they are good. 27820a05c769SSteven Rostedt $half = int($#start_list / 2); 27834c8cc55bSSteven Rostedt } while ($#start_list > 0); 27840a05c769SSteven Rostedt 2785c960bb9fSSteven Rostedt # we found a single config, try it again unless we are running manually 2786c960bb9fSSteven Rostedt 2787c960bb9fSSteven Rostedt if ($bisect_manual) { 2788c960bb9fSSteven Rostedt process_failed $start_list[0]; 2789c960bb9fSSteven Rostedt return 1; 2790c960bb9fSSteven Rostedt } 2791c960bb9fSSteven Rostedt 27920a05c769SSteven Rostedt my @tophalf = @start_list[0 .. 0]; 27930a05c769SSteven Rostedt 27940a05c769SSteven Rostedt $ret = run_config_bisect_test $type; 27950a05c769SSteven Rostedt if ($ret) { 27960a05c769SSteven Rostedt process_passed %current_config; 27970a05c769SSteven Rostedt return 0; 27980a05c769SSteven Rostedt } 27990a05c769SSteven Rostedt 28000a05c769SSteven Rostedt process_failed $start_list[0]; 28010a05c769SSteven Rostedt return 1; 28020a05c769SSteven Rostedt} 28030a05c769SSteven Rostedt 28040a05c769SSteven Rostedtsub config_bisect { 28050a05c769SSteven Rostedt my ($i) = @_; 28060a05c769SSteven Rostedt 2807b5f4aea6SSteven Rostedt my $start_config = $config_bisect; 28080a05c769SSteven Rostedt 28090a05c769SSteven Rostedt my $tmpconfig = "$tmpdir/use_config"; 28100a05c769SSteven Rostedt 281130f75da5SSteven Rostedt if (defined($config_bisect_good)) { 281230f75da5SSteven Rostedt process_config_ignore $config_bisect_good; 281330f75da5SSteven Rostedt } 281430f75da5SSteven Rostedt 28150a05c769SSteven Rostedt # Make the file with the bad config and the min config 28160a05c769SSteven Rostedt if (defined($minconfig)) { 28170a05c769SSteven Rostedt # read the min config for things to ignore 28180a05c769SSteven Rostedt run_command "cp $minconfig $tmpconfig" or 28190a05c769SSteven Rostedt dodie "failed to copy $minconfig to $tmpconfig"; 28200a05c769SSteven Rostedt } else { 28210a05c769SSteven Rostedt unlink $tmpconfig; 28220a05c769SSteven Rostedt } 28230a05c769SSteven Rostedt 28240a05c769SSteven Rostedt if (-f $tmpconfig) { 2825fcb3f16aSSteven Rostedt load_force_config($tmpconfig); 28260a05c769SSteven Rostedt process_config_ignore $tmpconfig; 28270a05c769SSteven Rostedt } 28280a05c769SSteven Rostedt 28290a05c769SSteven Rostedt # now process the start config 28300a05c769SSteven Rostedt run_command "cp $start_config $output_config" or 28310a05c769SSteven Rostedt dodie "failed to copy $start_config to $output_config"; 28320a05c769SSteven Rostedt 28330a05c769SSteven Rostedt # read directly what we want to check 28340a05c769SSteven Rostedt my %config_check; 28350a05c769SSteven Rostedt open (IN, $output_config) 2836f9dee311SMasanari Iida or dodie "failed to open $output_config"; 28370a05c769SSteven Rostedt 28380a05c769SSteven Rostedt while (<IN>) { 28390a05c769SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 28400a05c769SSteven Rostedt $config_check{$2} = $1; 28410a05c769SSteven Rostedt } 28420a05c769SSteven Rostedt } 28430a05c769SSteven Rostedt close(IN); 28440a05c769SSteven Rostedt 2845250bae8bSSteven Rostedt # Now run oldconfig with the minconfig 2846fcb3f16aSSteven Rostedt make_oldconfig; 28470a05c769SSteven Rostedt 28480a05c769SSteven Rostedt # check to see what we lost (or gained) 28490a05c769SSteven Rostedt open (IN, $output_config) 28500a05c769SSteven Rostedt or dodie "Failed to read $start_config"; 28510a05c769SSteven Rostedt 28520a05c769SSteven Rostedt my %removed_configs; 28530a05c769SSteven Rostedt my %added_configs; 28540a05c769SSteven Rostedt 28550a05c769SSteven Rostedt while (<IN>) { 28560a05c769SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 28570a05c769SSteven Rostedt # save off all options 28580a05c769SSteven Rostedt $config_set{$2} = $1; 28590a05c769SSteven Rostedt if (defined($config_check{$2})) { 28600a05c769SSteven Rostedt if (defined($config_ignore{$2})) { 28610a05c769SSteven Rostedt $removed_configs{$2} = $1; 28620a05c769SSteven Rostedt } else { 28630a05c769SSteven Rostedt $config_list{$2} = $1; 28640a05c769SSteven Rostedt } 28650a05c769SSteven Rostedt } elsif (!defined($config_ignore{$2})) { 28660a05c769SSteven Rostedt $added_configs{$2} = $1; 28670a05c769SSteven Rostedt $config_list{$2} = $1; 28680a05c769SSteven Rostedt } 2869cf79fab6SSteven Rostedt } elsif (/^# ((CONFIG\S*).*)/) { 2870cf79fab6SSteven Rostedt # Keep these configs disabled 2871cf79fab6SSteven Rostedt $config_set{$2} = $1; 2872cf79fab6SSteven Rostedt $config_off{$2} = $1; 28730a05c769SSteven Rostedt } 28740a05c769SSteven Rostedt } 28750a05c769SSteven Rostedt close(IN); 28760a05c769SSteven Rostedt 28770a05c769SSteven Rostedt my @confs = keys %removed_configs; 28780a05c769SSteven Rostedt if ($#confs >= 0) { 28790a05c769SSteven Rostedt doprint "Configs overridden by default configs and removed from check:\n"; 28800a05c769SSteven Rostedt foreach my $config (@confs) { 28810a05c769SSteven Rostedt doprint " $config\n"; 28820a05c769SSteven Rostedt } 28830a05c769SSteven Rostedt } 28840a05c769SSteven Rostedt @confs = keys %added_configs; 28850a05c769SSteven Rostedt if ($#confs >= 0) { 28860a05c769SSteven Rostedt doprint "Configs appearing in make oldconfig and added:\n"; 28870a05c769SSteven Rostedt foreach my $config (@confs) { 28880a05c769SSteven Rostedt doprint " $config\n"; 28890a05c769SSteven Rostedt } 28900a05c769SSteven Rostedt } 28910a05c769SSteven Rostedt 28920a05c769SSteven Rostedt my %config_test; 28930a05c769SSteven Rostedt my $once = 0; 28940a05c769SSteven Rostedt 2895cf79fab6SSteven Rostedt @config_off_tmp = (); 2896cf79fab6SSteven Rostedt 28970a05c769SSteven Rostedt # Sometimes kconfig does weird things. We must make sure 28980a05c769SSteven Rostedt # that the config we autocreate has everything we need 28990a05c769SSteven Rostedt # to test, otherwise we may miss testing configs, or 29000a05c769SSteven Rostedt # may not be able to create a new config. 29010a05c769SSteven Rostedt # Here we create a config with everything set. 29020a05c769SSteven Rostedt create_config (keys %config_list); 29030a05c769SSteven Rostedt read_current_config \%config_test; 29040a05c769SSteven Rostedt foreach my $config (keys %config_list) { 29050a05c769SSteven Rostedt if (!defined($config_test{$config})) { 29060a05c769SSteven Rostedt if (!$once) { 29070a05c769SSteven Rostedt $once = 1; 29080a05c769SSteven Rostedt doprint "Configs not produced by kconfig (will not be checked):\n"; 29090a05c769SSteven Rostedt } 29100a05c769SSteven Rostedt doprint " $config\n"; 29110a05c769SSteven Rostedt delete $config_list{$config}; 29120a05c769SSteven Rostedt } 29130a05c769SSteven Rostedt } 29140a05c769SSteven Rostedt my $ret; 2915b0918612SSteven Rostedt 2916b0918612SSteven Rostedt if (defined($config_bisect_check) && $config_bisect_check) { 2917b0918612SSteven Rostedt doprint " Checking to make sure bad config with min config fails\n"; 2918b0918612SSteven Rostedt create_config keys %config_list; 2919b0918612SSteven Rostedt $ret = run_config_bisect_test $config_bisect_type; 2920b0918612SSteven Rostedt if ($ret) { 2921b0918612SSteven Rostedt doprint " FAILED! Bad config with min config boots fine\n"; 2922b0918612SSteven Rostedt return -1; 2923b0918612SSteven Rostedt } 2924b0918612SSteven Rostedt doprint " Bad config with min config fails as expected\n"; 2925b0918612SSteven Rostedt } 2926b0918612SSteven Rostedt 29270a05c769SSteven Rostedt do { 29280a05c769SSteven Rostedt $ret = run_config_bisect; 29290a05c769SSteven Rostedt } while (!$ret); 29300a05c769SSteven Rostedt 29310a05c769SSteven Rostedt return $ret if ($ret < 0); 29325f9b6cedSSteven Rostedt 29335f9b6cedSSteven Rostedt success $i; 29345f9b6cedSSteven Rostedt} 29355f9b6cedSSteven Rostedt 293627d934b2SSteven Rostedtsub patchcheck_reboot { 293727d934b2SSteven Rostedt doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 2938bc7c5803SSteven Rostedt reboot_to_good $patchcheck_sleep_time; 293927d934b2SSteven Rostedt} 294027d934b2SSteven Rostedt 29416c5ee0beSSteven Rostedtsub patchcheck { 29426c5ee0beSSteven Rostedt my ($i) = @_; 29436c5ee0beSSteven Rostedt 29446c5ee0beSSteven Rostedt die "PATCHCHECK_START[$i] not defined\n" 2945b5f4aea6SSteven Rostedt if (!defined($patchcheck_start)); 29466c5ee0beSSteven Rostedt die "PATCHCHECK_TYPE[$i] not defined\n" 2947b5f4aea6SSteven Rostedt if (!defined($patchcheck_type)); 29486c5ee0beSSteven Rostedt 2949b5f4aea6SSteven Rostedt my $start = $patchcheck_start; 29506c5ee0beSSteven Rostedt 29516c5ee0beSSteven Rostedt my $end = "HEAD"; 2952b5f4aea6SSteven Rostedt if (defined($patchcheck_end)) { 2953b5f4aea6SSteven Rostedt $end = $patchcheck_end; 29546c5ee0beSSteven Rostedt } 29556c5ee0beSSteven Rostedt 2956a57419b3SSteven Rostedt # Get the true sha1's since we can use things like HEAD~3 2957a57419b3SSteven Rostedt $start = get_sha1($start); 2958a57419b3SSteven Rostedt $end = get_sha1($end); 2959a57419b3SSteven Rostedt 2960b5f4aea6SSteven Rostedt my $type = $patchcheck_type; 29616c5ee0beSSteven Rostedt 29626c5ee0beSSteven Rostedt # Can't have a test without having a test to run 29636c5ee0beSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 29646c5ee0beSSteven Rostedt $type = "boot"; 29656c5ee0beSSteven Rostedt } 29666c5ee0beSSteven Rostedt 29676c5ee0beSSteven Rostedt open (IN, "git log --pretty=oneline $end|") or 29686c5ee0beSSteven Rostedt dodie "could not get git list"; 29696c5ee0beSSteven Rostedt 29706c5ee0beSSteven Rostedt my @list; 29716c5ee0beSSteven Rostedt 29726c5ee0beSSteven Rostedt while (<IN>) { 29736c5ee0beSSteven Rostedt chomp; 29746c5ee0beSSteven Rostedt $list[$#list+1] = $_; 29756c5ee0beSSteven Rostedt last if (/^$start/); 29766c5ee0beSSteven Rostedt } 29776c5ee0beSSteven Rostedt close(IN); 29786c5ee0beSSteven Rostedt 29796c5ee0beSSteven Rostedt if ($list[$#list] !~ /^$start/) { 29802b7d9b21SSteven Rostedt fail "SHA1 $start not found"; 29816c5ee0beSSteven Rostedt } 29826c5ee0beSSteven Rostedt 29836c5ee0beSSteven Rostedt # go backwards in the list 29846c5ee0beSSteven Rostedt @list = reverse @list; 29856c5ee0beSSteven Rostedt 29866c5ee0beSSteven Rostedt my $save_clean = $noclean; 29871990207dSSteven Rostedt my %ignored_warnings; 29881990207dSSteven Rostedt 29891990207dSSteven Rostedt if (defined($ignore_warnings)) { 29901990207dSSteven Rostedt foreach my $sha1 (split /\s+/, $ignore_warnings) { 29911990207dSSteven Rostedt $ignored_warnings{$sha1} = 1; 29921990207dSSteven Rostedt } 29931990207dSSteven Rostedt } 29946c5ee0beSSteven Rostedt 29956c5ee0beSSteven Rostedt $in_patchcheck = 1; 29966c5ee0beSSteven Rostedt foreach my $item (@list) { 29976c5ee0beSSteven Rostedt my $sha1 = $item; 29986c5ee0beSSteven Rostedt $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 29996c5ee0beSSteven Rostedt 30006c5ee0beSSteven Rostedt doprint "\nProcessing commit $item\n\n"; 30016c5ee0beSSteven Rostedt 30026c5ee0beSSteven Rostedt run_command "git checkout $sha1" or 30036c5ee0beSSteven Rostedt die "Failed to checkout $sha1"; 30046c5ee0beSSteven Rostedt 30056c5ee0beSSteven Rostedt # only clean on the first and last patch 30066c5ee0beSSteven Rostedt if ($item eq $list[0] || 30076c5ee0beSSteven Rostedt $item eq $list[$#list]) { 30086c5ee0beSSteven Rostedt $noclean = $save_clean; 30096c5ee0beSSteven Rostedt } else { 30106c5ee0beSSteven Rostedt $noclean = 1; 30116c5ee0beSSteven Rostedt } 30126c5ee0beSSteven Rostedt 30136c5ee0beSSteven Rostedt if (defined($minconfig)) { 30142b7d9b21SSteven Rostedt build "useconfig:$minconfig" or return 0; 30156c5ee0beSSteven Rostedt } else { 30166c5ee0beSSteven Rostedt # ?? no config to use? 30172b7d9b21SSteven Rostedt build "oldconfig" or return 0; 30186c5ee0beSSteven Rostedt } 30196c5ee0beSSteven Rostedt 30201990207dSSteven Rostedt 30211990207dSSteven Rostedt if (!defined($ignored_warnings{$sha1})) { 30222b7d9b21SSteven Rostedt check_buildlog $sha1 or return 0; 30231990207dSSteven Rostedt } 30246c5ee0beSSteven Rostedt 30256c5ee0beSSteven Rostedt next if ($type eq "build"); 30266c5ee0beSSteven Rostedt 30277faafbd6SSteven Rostedt my $failed = 0; 30287faafbd6SSteven Rostedt 3029ddf607e5SSteven Rostedt start_monitor_and_boot or $failed = 1; 30307faafbd6SSteven Rostedt 30317faafbd6SSteven Rostedt if (!$failed && $type ne "boot"){ 30327faafbd6SSteven Rostedt do_run_test or $failed = 1; 30337faafbd6SSteven Rostedt } 30347faafbd6SSteven Rostedt end_monitor; 30357faafbd6SSteven Rostedt return 0 if ($failed); 30367faafbd6SSteven Rostedt 303727d934b2SSteven Rostedt patchcheck_reboot; 303827d934b2SSteven Rostedt 30396c5ee0beSSteven Rostedt } 30406c5ee0beSSteven Rostedt $in_patchcheck = 0; 30416c5ee0beSSteven Rostedt success $i; 30422b7d9b21SSteven Rostedt 30432b7d9b21SSteven Rostedt return 1; 30446c5ee0beSSteven Rostedt} 30456c5ee0beSSteven Rostedt 3046b9066f6cSSteven Rostedtmy %depends; 3047ac6974c7SSteven Rostedtmy %depcount; 3048b9066f6cSSteven Rostedtmy $iflevel = 0; 3049b9066f6cSSteven Rostedtmy @ifdeps; 3050b9066f6cSSteven Rostedt 3051b9066f6cSSteven Rostedt# prevent recursion 3052b9066f6cSSteven Rostedtmy %read_kconfigs; 3053b9066f6cSSteven Rostedt 3054ac6974c7SSteven Rostedtsub add_dep { 3055ac6974c7SSteven Rostedt # $config depends on $dep 3056ac6974c7SSteven Rostedt my ($config, $dep) = @_; 3057ac6974c7SSteven Rostedt 3058ac6974c7SSteven Rostedt if (defined($depends{$config})) { 3059ac6974c7SSteven Rostedt $depends{$config} .= " " . $dep; 3060ac6974c7SSteven Rostedt } else { 3061ac6974c7SSteven Rostedt $depends{$config} = $dep; 3062ac6974c7SSteven Rostedt } 3063ac6974c7SSteven Rostedt 3064ac6974c7SSteven Rostedt # record the number of configs depending on $dep 3065ac6974c7SSteven Rostedt if (defined $depcount{$dep}) { 3066ac6974c7SSteven Rostedt $depcount{$dep}++; 3067ac6974c7SSteven Rostedt } else { 3068ac6974c7SSteven Rostedt $depcount{$dep} = 1; 3069ac6974c7SSteven Rostedt } 3070ac6974c7SSteven Rostedt} 3071ac6974c7SSteven Rostedt 3072b9066f6cSSteven Rostedt# taken from streamline_config.pl 3073b9066f6cSSteven Rostedtsub read_kconfig { 3074b9066f6cSSteven Rostedt my ($kconfig) = @_; 3075b9066f6cSSteven Rostedt 3076b9066f6cSSteven Rostedt my $state = "NONE"; 3077b9066f6cSSteven Rostedt my $config; 3078b9066f6cSSteven Rostedt my @kconfigs; 3079b9066f6cSSteven Rostedt 3080b9066f6cSSteven Rostedt my $cont = 0; 3081b9066f6cSSteven Rostedt my $line; 3082b9066f6cSSteven Rostedt 3083b9066f6cSSteven Rostedt 3084b9066f6cSSteven Rostedt if (! -f $kconfig) { 3085b9066f6cSSteven Rostedt doprint "file $kconfig does not exist, skipping\n"; 3086b9066f6cSSteven Rostedt return; 3087b9066f6cSSteven Rostedt } 3088b9066f6cSSteven Rostedt 3089b9066f6cSSteven Rostedt open(KIN, "$kconfig") 3090b9066f6cSSteven Rostedt or die "Can't open $kconfig"; 3091b9066f6cSSteven Rostedt while (<KIN>) { 3092b9066f6cSSteven Rostedt chomp; 3093b9066f6cSSteven Rostedt 3094b9066f6cSSteven Rostedt # Make sure that lines ending with \ continue 3095b9066f6cSSteven Rostedt if ($cont) { 3096b9066f6cSSteven Rostedt $_ = $line . " " . $_; 3097b9066f6cSSteven Rostedt } 3098b9066f6cSSteven Rostedt 3099b9066f6cSSteven Rostedt if (s/\\$//) { 3100b9066f6cSSteven Rostedt $cont = 1; 3101b9066f6cSSteven Rostedt $line = $_; 3102b9066f6cSSteven Rostedt next; 3103b9066f6cSSteven Rostedt } 3104b9066f6cSSteven Rostedt 3105b9066f6cSSteven Rostedt $cont = 0; 3106b9066f6cSSteven Rostedt 3107b9066f6cSSteven Rostedt # collect any Kconfig sources 3108b9066f6cSSteven Rostedt if (/^source\s*"(.*)"/) { 3109b9066f6cSSteven Rostedt $kconfigs[$#kconfigs+1] = $1; 3110b9066f6cSSteven Rostedt } 3111b9066f6cSSteven Rostedt 3112b9066f6cSSteven Rostedt # configs found 3113b9066f6cSSteven Rostedt if (/^\s*(menu)?config\s+(\S+)\s*$/) { 3114b9066f6cSSteven Rostedt $state = "NEW"; 3115b9066f6cSSteven Rostedt $config = $2; 3116b9066f6cSSteven Rostedt 3117b9066f6cSSteven Rostedt for (my $i = 0; $i < $iflevel; $i++) { 3118ac6974c7SSteven Rostedt add_dep $config, $ifdeps[$i]; 3119b9066f6cSSteven Rostedt } 3120b9066f6cSSteven Rostedt 3121b9066f6cSSteven Rostedt # collect the depends for the config 3122b9066f6cSSteven Rostedt } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { 3123b9066f6cSSteven Rostedt 3124ac6974c7SSteven Rostedt add_dep $config, $1; 3125b9066f6cSSteven Rostedt 3126b9066f6cSSteven Rostedt # Get the configs that select this config 3127ac6974c7SSteven Rostedt } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) { 3128ac6974c7SSteven Rostedt 3129ac6974c7SSteven Rostedt # selected by depends on config 3130ac6974c7SSteven Rostedt add_dep $1, $config; 3131b9066f6cSSteven Rostedt 3132b9066f6cSSteven Rostedt # Check for if statements 3133b9066f6cSSteven Rostedt } elsif (/^if\s+(.*\S)\s*$/) { 3134b9066f6cSSteven Rostedt my $deps = $1; 3135b9066f6cSSteven Rostedt # remove beginning and ending non text 3136b9066f6cSSteven Rostedt $deps =~ s/^[^a-zA-Z0-9_]*//; 3137b9066f6cSSteven Rostedt $deps =~ s/[^a-zA-Z0-9_]*$//; 3138b9066f6cSSteven Rostedt 3139b9066f6cSSteven Rostedt my @deps = split /[^a-zA-Z0-9_]+/, $deps; 3140b9066f6cSSteven Rostedt 3141b9066f6cSSteven Rostedt $ifdeps[$iflevel++] = join ':', @deps; 3142b9066f6cSSteven Rostedt 3143b9066f6cSSteven Rostedt } elsif (/^endif/) { 3144b9066f6cSSteven Rostedt 3145b9066f6cSSteven Rostedt $iflevel-- if ($iflevel); 3146b9066f6cSSteven Rostedt 3147b9066f6cSSteven Rostedt # stop on "help" 3148b9066f6cSSteven Rostedt } elsif (/^\s*help\s*$/) { 3149b9066f6cSSteven Rostedt $state = "NONE"; 3150b9066f6cSSteven Rostedt } 3151b9066f6cSSteven Rostedt } 3152b9066f6cSSteven Rostedt close(KIN); 3153b9066f6cSSteven Rostedt 3154b9066f6cSSteven Rostedt # read in any configs that were found. 3155b9066f6cSSteven Rostedt foreach $kconfig (@kconfigs) { 3156b9066f6cSSteven Rostedt if (!defined($read_kconfigs{$kconfig})) { 3157b9066f6cSSteven Rostedt $read_kconfigs{$kconfig} = 1; 3158b9066f6cSSteven Rostedt read_kconfig("$builddir/$kconfig"); 3159b9066f6cSSteven Rostedt } 3160b9066f6cSSteven Rostedt } 3161b9066f6cSSteven Rostedt} 3162b9066f6cSSteven Rostedt 3163b9066f6cSSteven Rostedtsub read_depends { 3164b9066f6cSSteven Rostedt # find out which arch this is by the kconfig file 3165b9066f6cSSteven Rostedt open (IN, $output_config) 3166b9066f6cSSteven Rostedt or dodie "Failed to read $output_config"; 3167b9066f6cSSteven Rostedt my $arch; 3168b9066f6cSSteven Rostedt while (<IN>) { 3169b9066f6cSSteven Rostedt if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) { 3170b9066f6cSSteven Rostedt $arch = $1; 3171b9066f6cSSteven Rostedt last; 3172b9066f6cSSteven Rostedt } 3173b9066f6cSSteven Rostedt } 3174b9066f6cSSteven Rostedt close IN; 3175b9066f6cSSteven Rostedt 3176b9066f6cSSteven Rostedt if (!defined($arch)) { 3177b9066f6cSSteven Rostedt doprint "Could not find arch from config file\n"; 3178b9066f6cSSteven Rostedt doprint "no dependencies used\n"; 3179b9066f6cSSteven Rostedt return; 3180b9066f6cSSteven Rostedt } 3181b9066f6cSSteven Rostedt 3182b9066f6cSSteven Rostedt # arch is really the subarch, we need to know 3183b9066f6cSSteven Rostedt # what directory to look at. 3184b9066f6cSSteven Rostedt if ($arch eq "i386" || $arch eq "x86_64") { 3185b9066f6cSSteven Rostedt $arch = "x86"; 3186b9066f6cSSteven Rostedt } elsif ($arch =~ /^tile/) { 3187b9066f6cSSteven Rostedt $arch = "tile"; 3188b9066f6cSSteven Rostedt } 3189b9066f6cSSteven Rostedt 3190b9066f6cSSteven Rostedt my $kconfig = "$builddir/arch/$arch/Kconfig"; 3191b9066f6cSSteven Rostedt 3192b9066f6cSSteven Rostedt if (! -f $kconfig && $arch =~ /\d$/) { 3193b9066f6cSSteven Rostedt my $orig = $arch; 3194b9066f6cSSteven Rostedt # some subarchs have numbers, truncate them 3195b9066f6cSSteven Rostedt $arch =~ s/\d*$//; 3196b9066f6cSSteven Rostedt $kconfig = "$builddir/arch/$arch/Kconfig"; 3197b9066f6cSSteven Rostedt if (! -f $kconfig) { 3198b9066f6cSSteven Rostedt doprint "No idea what arch dir $orig is for\n"; 3199b9066f6cSSteven Rostedt doprint "no dependencies used\n"; 3200b9066f6cSSteven Rostedt return; 3201b9066f6cSSteven Rostedt } 3202b9066f6cSSteven Rostedt } 3203b9066f6cSSteven Rostedt 3204b9066f6cSSteven Rostedt read_kconfig($kconfig); 3205b9066f6cSSteven Rostedt} 3206b9066f6cSSteven Rostedt 32074c4ab120SSteven Rostedtsub read_config_list { 32084c4ab120SSteven Rostedt my ($config) = @_; 32094c4ab120SSteven Rostedt 32104c4ab120SSteven Rostedt open (IN, $config) 32114c4ab120SSteven Rostedt or dodie "Failed to read $config"; 32124c4ab120SSteven Rostedt 32134c4ab120SSteven Rostedt while (<IN>) { 32144c4ab120SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 32154c4ab120SSteven Rostedt if (!defined($config_ignore{$2})) { 32164c4ab120SSteven Rostedt $config_list{$2} = $1; 32174c4ab120SSteven Rostedt } 32184c4ab120SSteven Rostedt } 32194c4ab120SSteven Rostedt } 32204c4ab120SSteven Rostedt 32214c4ab120SSteven Rostedt close(IN); 32224c4ab120SSteven Rostedt} 32234c4ab120SSteven Rostedt 32244c4ab120SSteven Rostedtsub read_output_config { 32254c4ab120SSteven Rostedt my ($config) = @_; 32264c4ab120SSteven Rostedt 32274c4ab120SSteven Rostedt assign_configs \%config_ignore, $config; 32284c4ab120SSteven Rostedt} 32294c4ab120SSteven Rostedt 32304c4ab120SSteven Rostedtsub make_new_config { 32314c4ab120SSteven Rostedt my @configs = @_; 32324c4ab120SSteven Rostedt 32334c4ab120SSteven Rostedt open (OUT, ">$output_config") 32344c4ab120SSteven Rostedt or dodie "Failed to write $output_config"; 32354c4ab120SSteven Rostedt 32364c4ab120SSteven Rostedt foreach my $config (@configs) { 32374c4ab120SSteven Rostedt print OUT "$config\n"; 32384c4ab120SSteven Rostedt } 32394c4ab120SSteven Rostedt close OUT; 32404c4ab120SSteven Rostedt} 32414c4ab120SSteven Rostedt 3242ac6974c7SSteven Rostedtsub chomp_config { 3243ac6974c7SSteven Rostedt my ($config) = @_; 3244ac6974c7SSteven Rostedt 3245ac6974c7SSteven Rostedt $config =~ s/CONFIG_//; 3246ac6974c7SSteven Rostedt 3247ac6974c7SSteven Rostedt return $config; 3248ac6974c7SSteven Rostedt} 3249ac6974c7SSteven Rostedt 3250b9066f6cSSteven Rostedtsub get_depends { 3251b9066f6cSSteven Rostedt my ($dep) = @_; 3252b9066f6cSSteven Rostedt 3253ac6974c7SSteven Rostedt my $kconfig = chomp_config $dep; 3254b9066f6cSSteven Rostedt 3255b9066f6cSSteven Rostedt $dep = $depends{"$kconfig"}; 3256b9066f6cSSteven Rostedt 3257b9066f6cSSteven Rostedt # the dep string we have saves the dependencies as they 3258b9066f6cSSteven Rostedt # were found, including expressions like ! && ||. We 3259b9066f6cSSteven Rostedt # want to split this out into just an array of configs. 3260b9066f6cSSteven Rostedt 3261b9066f6cSSteven Rostedt my $valid = "A-Za-z_0-9"; 3262b9066f6cSSteven Rostedt 3263b9066f6cSSteven Rostedt my @configs; 3264b9066f6cSSteven Rostedt 3265b9066f6cSSteven Rostedt while ($dep =~ /[$valid]/) { 3266b9066f6cSSteven Rostedt 3267b9066f6cSSteven Rostedt if ($dep =~ /^[^$valid]*([$valid]+)/) { 3268b9066f6cSSteven Rostedt my $conf = "CONFIG_" . $1; 3269b9066f6cSSteven Rostedt 3270b9066f6cSSteven Rostedt $configs[$#configs + 1] = $conf; 3271b9066f6cSSteven Rostedt 3272b9066f6cSSteven Rostedt $dep =~ s/^[^$valid]*[$valid]+//; 3273b9066f6cSSteven Rostedt } else { 3274b9066f6cSSteven Rostedt die "this should never happen"; 3275b9066f6cSSteven Rostedt } 3276b9066f6cSSteven Rostedt } 3277b9066f6cSSteven Rostedt 3278b9066f6cSSteven Rostedt return @configs; 3279b9066f6cSSteven Rostedt} 3280b9066f6cSSteven Rostedt 3281b9066f6cSSteven Rostedtmy %min_configs; 3282b9066f6cSSteven Rostedtmy %keep_configs; 328343d1b651SSteven Rostedtmy %save_configs; 3284b9066f6cSSteven Rostedtmy %processed_configs; 3285b9066f6cSSteven Rostedtmy %nochange_config; 3286b9066f6cSSteven Rostedt 3287b9066f6cSSteven Rostedtsub test_this_config { 3288b9066f6cSSteven Rostedt my ($config) = @_; 3289b9066f6cSSteven Rostedt 3290b9066f6cSSteven Rostedt my $found; 3291b9066f6cSSteven Rostedt 3292b9066f6cSSteven Rostedt # if we already processed this config, skip it 3293b9066f6cSSteven Rostedt if (defined($processed_configs{$config})) { 3294b9066f6cSSteven Rostedt return undef; 3295b9066f6cSSteven Rostedt } 3296b9066f6cSSteven Rostedt $processed_configs{$config} = 1; 3297b9066f6cSSteven Rostedt 3298b9066f6cSSteven Rostedt # if this config failed during this round, skip it 3299b9066f6cSSteven Rostedt if (defined($nochange_config{$config})) { 3300b9066f6cSSteven Rostedt return undef; 3301b9066f6cSSteven Rostedt } 3302b9066f6cSSteven Rostedt 3303ac6974c7SSteven Rostedt my $kconfig = chomp_config $config; 3304b9066f6cSSteven Rostedt 3305b9066f6cSSteven Rostedt # Test dependencies first 3306b9066f6cSSteven Rostedt if (defined($depends{"$kconfig"})) { 3307b9066f6cSSteven Rostedt my @parents = get_depends $config; 3308b9066f6cSSteven Rostedt foreach my $parent (@parents) { 3309b9066f6cSSteven Rostedt # if the parent is in the min config, check it first 3310b9066f6cSSteven Rostedt next if (!defined($min_configs{$parent})); 3311b9066f6cSSteven Rostedt $found = test_this_config($parent); 3312b9066f6cSSteven Rostedt if (defined($found)) { 3313b9066f6cSSteven Rostedt return $found; 3314b9066f6cSSteven Rostedt } 3315b9066f6cSSteven Rostedt } 3316b9066f6cSSteven Rostedt } 3317b9066f6cSSteven Rostedt 3318b9066f6cSSteven Rostedt # Remove this config from the list of configs 3319fb16d891SAdam Lee # do a make olddefconfig and then read the resulting 3320b9066f6cSSteven Rostedt # .config to make sure it is missing the config that 3321b9066f6cSSteven Rostedt # we had before 3322b9066f6cSSteven Rostedt my %configs = %min_configs; 3323b9066f6cSSteven Rostedt delete $configs{$config}; 3324b9066f6cSSteven Rostedt make_new_config ((values %configs), (values %keep_configs)); 3325b9066f6cSSteven Rostedt make_oldconfig; 3326b9066f6cSSteven Rostedt undef %configs; 3327b9066f6cSSteven Rostedt assign_configs \%configs, $output_config; 3328b9066f6cSSteven Rostedt 3329b9066f6cSSteven Rostedt return $config if (!defined($configs{$config})); 3330b9066f6cSSteven Rostedt 3331b9066f6cSSteven Rostedt doprint "disabling config $config did not change .config\n"; 3332b9066f6cSSteven Rostedt 3333b9066f6cSSteven Rostedt $nochange_config{$config} = 1; 3334b9066f6cSSteven Rostedt 3335b9066f6cSSteven Rostedt return undef; 3336b9066f6cSSteven Rostedt} 3337b9066f6cSSteven Rostedt 33384c4ab120SSteven Rostedtsub make_min_config { 33394c4ab120SSteven Rostedt my ($i) = @_; 33404c4ab120SSteven Rostedt 3341ccc513b6SSteven Rostedt my $type = $minconfig_type; 3342ccc513b6SSteven Rostedt if ($type ne "boot" && $type ne "test") { 3343ccc513b6SSteven Rostedt fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" . 3344ccc513b6SSteven Rostedt " make_min_config works only with 'boot' and 'test'\n" and return; 3345ccc513b6SSteven Rostedt } 3346ccc513b6SSteven Rostedt 33474c4ab120SSteven Rostedt if (!defined($output_minconfig)) { 33484c4ab120SSteven Rostedt fail "OUTPUT_MIN_CONFIG not defined" and return; 33494c4ab120SSteven Rostedt } 335035ce5952SSteven Rostedt 335135ce5952SSteven Rostedt # If output_minconfig exists, and the start_minconfig 335235ce5952SSteven Rostedt # came from min_config, than ask if we should use 335335ce5952SSteven Rostedt # that instead. 335435ce5952SSteven Rostedt if (-f $output_minconfig && !$start_minconfig_defined) { 335535ce5952SSteven Rostedt print "$output_minconfig exists\n"; 335643de3316SSteven Rostedt if (!defined($use_output_minconfig)) { 335735ce5952SSteven Rostedt if (read_yn " Use it as minconfig?") { 335835ce5952SSteven Rostedt $start_minconfig = $output_minconfig; 335935ce5952SSteven Rostedt } 336043de3316SSteven Rostedt } elsif ($use_output_minconfig > 0) { 336143de3316SSteven Rostedt doprint "Using $output_minconfig as MIN_CONFIG\n"; 336243de3316SSteven Rostedt $start_minconfig = $output_minconfig; 336343de3316SSteven Rostedt } else { 336443de3316SSteven Rostedt doprint "Set to still use MIN_CONFIG as starting point\n"; 336543de3316SSteven Rostedt } 336635ce5952SSteven Rostedt } 336735ce5952SSteven Rostedt 33684c4ab120SSteven Rostedt if (!defined($start_minconfig)) { 33694c4ab120SSteven Rostedt fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; 33704c4ab120SSteven Rostedt } 33714c4ab120SSteven Rostedt 337235ce5952SSteven Rostedt my $temp_config = "$tmpdir/temp_config"; 337335ce5952SSteven Rostedt 33744c4ab120SSteven Rostedt # First things first. We build an allnoconfig to find 33754c4ab120SSteven Rostedt # out what the defaults are that we can't touch. 33764c4ab120SSteven Rostedt # Some are selections, but we really can't handle selections. 33774c4ab120SSteven Rostedt 33784c4ab120SSteven Rostedt my $save_minconfig = $minconfig; 33794c4ab120SSteven Rostedt undef $minconfig; 33804c4ab120SSteven Rostedt 33814c4ab120SSteven Rostedt run_command "$make allnoconfig" or return 0; 33824c4ab120SSteven Rostedt 3383b9066f6cSSteven Rostedt read_depends; 3384b9066f6cSSteven Rostedt 33854c4ab120SSteven Rostedt process_config_ignore $output_config; 3386b9066f6cSSteven Rostedt 338743d1b651SSteven Rostedt undef %save_configs; 3388b9066f6cSSteven Rostedt undef %min_configs; 33894c4ab120SSteven Rostedt 33904c4ab120SSteven Rostedt if (defined($ignore_config)) { 33914c4ab120SSteven Rostedt # make sure the file exists 33924c4ab120SSteven Rostedt `touch $ignore_config`; 339343d1b651SSteven Rostedt assign_configs \%save_configs, $ignore_config; 33944c4ab120SSteven Rostedt } 33954c4ab120SSteven Rostedt 339643d1b651SSteven Rostedt %keep_configs = %save_configs; 339743d1b651SSteven Rostedt 33984c4ab120SSteven Rostedt doprint "Load initial configs from $start_minconfig\n"; 33994c4ab120SSteven Rostedt 34004c4ab120SSteven Rostedt # Look at the current min configs, and save off all the 34014c4ab120SSteven Rostedt # ones that were set via the allnoconfig 34024c4ab120SSteven Rostedt assign_configs \%min_configs, $start_minconfig; 34034c4ab120SSteven Rostedt 34044c4ab120SSteven Rostedt my @config_keys = keys %min_configs; 34054c4ab120SSteven Rostedt 3406ac6974c7SSteven Rostedt # All configs need a depcount 3407ac6974c7SSteven Rostedt foreach my $config (@config_keys) { 3408ac6974c7SSteven Rostedt my $kconfig = chomp_config $config; 3409ac6974c7SSteven Rostedt if (!defined $depcount{$kconfig}) { 3410ac6974c7SSteven Rostedt $depcount{$kconfig} = 0; 3411ac6974c7SSteven Rostedt } 3412ac6974c7SSteven Rostedt } 3413ac6974c7SSteven Rostedt 34144c4ab120SSteven Rostedt # Remove anything that was set by the make allnoconfig 34154c4ab120SSteven Rostedt # we shouldn't need them as they get set for us anyway. 34164c4ab120SSteven Rostedt foreach my $config (@config_keys) { 34174c4ab120SSteven Rostedt # Remove anything in the ignore_config 34184c4ab120SSteven Rostedt if (defined($keep_configs{$config})) { 34194c4ab120SSteven Rostedt my $file = $ignore_config; 34204c4ab120SSteven Rostedt $file =~ s,.*/(.*?)$,$1,; 34214c4ab120SSteven Rostedt doprint "$config set by $file ... ignored\n"; 34224c4ab120SSteven Rostedt delete $min_configs{$config}; 34234c4ab120SSteven Rostedt next; 34244c4ab120SSteven Rostedt } 34254c4ab120SSteven Rostedt # But make sure the settings are the same. If a min config 34264c4ab120SSteven Rostedt # sets a selection, we do not want to get rid of it if 34274c4ab120SSteven Rostedt # it is not the same as what we have. Just move it into 34284c4ab120SSteven Rostedt # the keep configs. 34294c4ab120SSteven Rostedt if (defined($config_ignore{$config})) { 34304c4ab120SSteven Rostedt if ($config_ignore{$config} ne $min_configs{$config}) { 34314c4ab120SSteven Rostedt doprint "$config is in allnoconfig as '$config_ignore{$config}'"; 34324c4ab120SSteven Rostedt doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n"; 34334c4ab120SSteven Rostedt $keep_configs{$config} = $min_configs{$config}; 34344c4ab120SSteven Rostedt } else { 34354c4ab120SSteven Rostedt doprint "$config set by allnoconfig ... ignored\n"; 34364c4ab120SSteven Rostedt } 34374c4ab120SSteven Rostedt delete $min_configs{$config}; 34384c4ab120SSteven Rostedt } 34394c4ab120SSteven Rostedt } 34404c4ab120SSteven Rostedt 34414c4ab120SSteven Rostedt my $done = 0; 3442b9066f6cSSteven Rostedt my $take_two = 0; 34434c4ab120SSteven Rostedt 34444c4ab120SSteven Rostedt while (!$done) { 34454c4ab120SSteven Rostedt 34464c4ab120SSteven Rostedt my $config; 34474c4ab120SSteven Rostedt my $found; 34484c4ab120SSteven Rostedt 34494c4ab120SSteven Rostedt # Now disable each config one by one and do a make oldconfig 34504c4ab120SSteven Rostedt # till we find a config that changes our list. 34514c4ab120SSteven Rostedt 34524c4ab120SSteven Rostedt my @test_configs = keys %min_configs; 3453ac6974c7SSteven Rostedt 3454ac6974c7SSteven Rostedt # Sort keys by who is most dependent on 3455ac6974c7SSteven Rostedt @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} } 3456ac6974c7SSteven Rostedt @test_configs ; 3457ac6974c7SSteven Rostedt 3458ac6974c7SSteven Rostedt # Put configs that did not modify the config at the end. 34594c4ab120SSteven Rostedt my $reset = 1; 34604c4ab120SSteven Rostedt for (my $i = 0; $i < $#test_configs; $i++) { 34614c4ab120SSteven Rostedt if (!defined($nochange_config{$test_configs[0]})) { 34624c4ab120SSteven Rostedt $reset = 0; 34634c4ab120SSteven Rostedt last; 34644c4ab120SSteven Rostedt } 34654c4ab120SSteven Rostedt # This config didn't change the .config last time. 34664c4ab120SSteven Rostedt # Place it at the end 34674c4ab120SSteven Rostedt my $config = shift @test_configs; 34684c4ab120SSteven Rostedt push @test_configs, $config; 34694c4ab120SSteven Rostedt } 34704c4ab120SSteven Rostedt 34714c4ab120SSteven Rostedt # if every test config has failed to modify the .config file 34724c4ab120SSteven Rostedt # in the past, then reset and start over. 34734c4ab120SSteven Rostedt if ($reset) { 34744c4ab120SSteven Rostedt undef %nochange_config; 34754c4ab120SSteven Rostedt } 34764c4ab120SSteven Rostedt 3477b9066f6cSSteven Rostedt undef %processed_configs; 3478b9066f6cSSteven Rostedt 34794c4ab120SSteven Rostedt foreach my $config (@test_configs) { 34804c4ab120SSteven Rostedt 3481b9066f6cSSteven Rostedt $found = test_this_config $config; 34824c4ab120SSteven Rostedt 3483b9066f6cSSteven Rostedt last if (defined($found)); 34844c4ab120SSteven Rostedt 34854c4ab120SSteven Rostedt # oh well, try another config 34864c4ab120SSteven Rostedt } 34874c4ab120SSteven Rostedt 34884c4ab120SSteven Rostedt if (!defined($found)) { 3489b9066f6cSSteven Rostedt # we could have failed due to the nochange_config hash 3490b9066f6cSSteven Rostedt # reset and try again 3491b9066f6cSSteven Rostedt if (!$take_two) { 3492b9066f6cSSteven Rostedt undef %nochange_config; 3493b9066f6cSSteven Rostedt $take_two = 1; 3494b9066f6cSSteven Rostedt next; 3495b9066f6cSSteven Rostedt } 34964c4ab120SSteven Rostedt doprint "No more configs found that we can disable\n"; 34974c4ab120SSteven Rostedt $done = 1; 34984c4ab120SSteven Rostedt last; 34994c4ab120SSteven Rostedt } 3500b9066f6cSSteven Rostedt $take_two = 0; 35014c4ab120SSteven Rostedt 35024c4ab120SSteven Rostedt $config = $found; 35034c4ab120SSteven Rostedt 35044c4ab120SSteven Rostedt doprint "Test with $config disabled\n"; 35054c4ab120SSteven Rostedt 35064c4ab120SSteven Rostedt # set in_bisect to keep build and monitor from dieing 35074c4ab120SSteven Rostedt $in_bisect = 1; 35084c4ab120SSteven Rostedt 35094c4ab120SSteven Rostedt my $failed = 0; 3510bf1c95abSSteven Rostedt build "oldconfig" or $failed = 1; 3511bf1c95abSSteven Rostedt if (!$failed) { 35124c4ab120SSteven Rostedt start_monitor_and_boot or $failed = 1; 3513ccc513b6SSteven Rostedt 3514ccc513b6SSteven Rostedt if ($type eq "test" && !$failed) { 3515ccc513b6SSteven Rostedt do_run_test or $failed = 1; 3516ccc513b6SSteven Rostedt } 3517ccc513b6SSteven Rostedt 35184c4ab120SSteven Rostedt end_monitor; 3519bf1c95abSSteven Rostedt } 35204c4ab120SSteven Rostedt 35214c4ab120SSteven Rostedt $in_bisect = 0; 35224c4ab120SSteven Rostedt 35234c4ab120SSteven Rostedt if ($failed) { 3524b9066f6cSSteven Rostedt doprint "$min_configs{$config} is needed to boot the box... keeping\n"; 35254c4ab120SSteven Rostedt # this config is needed, add it to the ignore list. 35264c4ab120SSteven Rostedt $keep_configs{$config} = $min_configs{$config}; 352743d1b651SSteven Rostedt $save_configs{$config} = $min_configs{$config}; 35284c4ab120SSteven Rostedt delete $min_configs{$config}; 352935ce5952SSteven Rostedt 353035ce5952SSteven Rostedt # update new ignore configs 353135ce5952SSteven Rostedt if (defined($ignore_config)) { 353235ce5952SSteven Rostedt open (OUT, ">$temp_config") 353335ce5952SSteven Rostedt or die "Can't write to $temp_config"; 353443d1b651SSteven Rostedt foreach my $config (keys %save_configs) { 353543d1b651SSteven Rostedt print OUT "$save_configs{$config}\n"; 353635ce5952SSteven Rostedt } 353735ce5952SSteven Rostedt close OUT; 353835ce5952SSteven Rostedt run_command "mv $temp_config $ignore_config" or 353935ce5952SSteven Rostedt dodie "failed to copy update to $ignore_config"; 354035ce5952SSteven Rostedt } 354135ce5952SSteven Rostedt 35424c4ab120SSteven Rostedt } else { 35434c4ab120SSteven Rostedt # We booted without this config, remove it from the minconfigs. 35444c4ab120SSteven Rostedt doprint "$config is not needed, disabling\n"; 35454c4ab120SSteven Rostedt 35464c4ab120SSteven Rostedt delete $min_configs{$config}; 35474c4ab120SSteven Rostedt 35484c4ab120SSteven Rostedt # Also disable anything that is not enabled in this config 35494c4ab120SSteven Rostedt my %configs; 35504c4ab120SSteven Rostedt assign_configs \%configs, $output_config; 35514c4ab120SSteven Rostedt my @config_keys = keys %min_configs; 35524c4ab120SSteven Rostedt foreach my $config (@config_keys) { 35534c4ab120SSteven Rostedt if (!defined($configs{$config})) { 35544c4ab120SSteven Rostedt doprint "$config is not set, disabling\n"; 35554c4ab120SSteven Rostedt delete $min_configs{$config}; 35564c4ab120SSteven Rostedt } 35574c4ab120SSteven Rostedt } 35584c4ab120SSteven Rostedt 35594c4ab120SSteven Rostedt # Save off all the current mandidory configs 356035ce5952SSteven Rostedt open (OUT, ">$temp_config") 356135ce5952SSteven Rostedt or die "Can't write to $temp_config"; 35624c4ab120SSteven Rostedt foreach my $config (keys %keep_configs) { 35634c4ab120SSteven Rostedt print OUT "$keep_configs{$config}\n"; 35644c4ab120SSteven Rostedt } 35654c4ab120SSteven Rostedt foreach my $config (keys %min_configs) { 35664c4ab120SSteven Rostedt print OUT "$min_configs{$config}\n"; 35674c4ab120SSteven Rostedt } 35684c4ab120SSteven Rostedt close OUT; 356935ce5952SSteven Rostedt 357035ce5952SSteven Rostedt run_command "mv $temp_config $output_minconfig" or 357135ce5952SSteven Rostedt dodie "failed to copy update to $output_minconfig"; 35724c4ab120SSteven Rostedt } 35734c4ab120SSteven Rostedt 35744c4ab120SSteven Rostedt doprint "Reboot and wait $sleep_time seconds\n"; 3575bc7c5803SSteven Rostedt reboot_to_good $sleep_time; 35764c4ab120SSteven Rostedt } 35774c4ab120SSteven Rostedt 35784c4ab120SSteven Rostedt success $i; 35794c4ab120SSteven Rostedt return 1; 35804c4ab120SSteven Rostedt} 35814c4ab120SSteven Rostedt 35828d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 35832545eb61SSteven Rostedt 35848d1491baSSteven Rostedtif ($#ARGV == 0) { 35858d1491baSSteven Rostedt $ktest_config = $ARGV[0]; 35868d1491baSSteven Rostedt if (! -f $ktest_config) { 35878d1491baSSteven Rostedt print "$ktest_config does not exist.\n"; 358835ce5952SSteven Rostedt if (!read_yn "Create it?") { 35898d1491baSSteven Rostedt exit 0; 35908d1491baSSteven Rostedt } 35918d1491baSSteven Rostedt } 35928d1491baSSteven Rostedt} else { 35938d1491baSSteven Rostedt $ktest_config = "ktest.conf"; 35948d1491baSSteven Rostedt} 35958d1491baSSteven Rostedt 35968d1491baSSteven Rostedtif (! -f $ktest_config) { 3597dbd3783bSSteven Rostedt $newconfig = 1; 3598c4261d0fSSteven Rostedt get_test_case; 35998d1491baSSteven Rostedt open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 36008d1491baSSteven Rostedt print OUT << "EOF" 36018d1491baSSteven Rostedt# Generated by ktest.pl 36028d1491baSSteven Rostedt# 36030e7a22deSSteven Rostedt 36040e7a22deSSteven Rostedt# PWD is a ktest.pl variable that will result in the process working 36050e7a22deSSteven Rostedt# directory that ktest.pl is executed in. 36060e7a22deSSteven Rostedt 36070e7a22deSSteven Rostedt# THIS_DIR is automatically assigned the PWD of the path that generated 36080e7a22deSSteven Rostedt# the config file. It is best to use this variable when assigning other 36090e7a22deSSteven Rostedt# directory paths within this directory. This allows you to easily 36100e7a22deSSteven Rostedt# move the test cases to other locations or to other machines. 36110e7a22deSSteven Rostedt# 36120e7a22deSSteven RostedtTHIS_DIR := $variable{"PWD"} 36130e7a22deSSteven Rostedt 36148d1491baSSteven Rostedt# Define each test with TEST_START 36158d1491baSSteven Rostedt# The config options below it will override the defaults 36168d1491baSSteven RostedtTEST_START 3617c4261d0fSSteven RostedtTEST_TYPE = $default{"TEST_TYPE"} 36188d1491baSSteven Rostedt 36198d1491baSSteven RostedtDEFAULTS 36208d1491baSSteven RostedtEOF 36218d1491baSSteven Rostedt; 36228d1491baSSteven Rostedt close(OUT); 36238d1491baSSteven Rostedt} 36248d1491baSSteven Rostedtread_config $ktest_config; 36258d1491baSSteven Rostedt 362623715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) { 362723715c3cSSteven Rostedt $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1); 362823715c3cSSteven Rostedt} 362923715c3cSSteven Rostedt 36308d1491baSSteven Rostedt# Append any configs entered in manually to the config file. 36318d1491baSSteven Rostedtmy @new_configs = keys %entered_configs; 36328d1491baSSteven Rostedtif ($#new_configs >= 0) { 36338d1491baSSteven Rostedt print "\nAppending entered in configs to $ktest_config\n"; 36348d1491baSSteven Rostedt open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 36358d1491baSSteven Rostedt foreach my $config (@new_configs) { 36368d1491baSSteven Rostedt print OUT "$config = $entered_configs{$config}\n"; 36370e7a22deSSteven Rostedt $opt{$config} = process_variables($entered_configs{$config}); 36388d1491baSSteven Rostedt } 36398d1491baSSteven Rostedt} 36402545eb61SSteven Rostedt 36412b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 36422b7d9b21SSteven Rostedt unlink $opt{"LOG_FILE"}; 36432b7d9b21SSteven Rostedt} 36442545eb61SSteven Rostedt 36452b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 36462b7d9b21SSteven Rostedt 3647a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 3648a57419b3SSteven Rostedt 3649a57419b3SSteven Rostedt if (!$i) { 3650a57419b3SSteven Rostedt doprint "DEFAULT OPTIONS:\n"; 3651a57419b3SSteven Rostedt } else { 3652a57419b3SSteven Rostedt doprint "\nTEST $i OPTIONS"; 3653a57419b3SSteven Rostedt if (defined($repeat_tests{$i})) { 3654a57419b3SSteven Rostedt $repeat = $repeat_tests{$i}; 3655a57419b3SSteven Rostedt doprint " ITERATE $repeat"; 3656a57419b3SSteven Rostedt } 3657a57419b3SSteven Rostedt doprint "\n"; 3658a57419b3SSteven Rostedt } 3659a57419b3SSteven Rostedt 36602b7d9b21SSteven Rostedt foreach my $option (sort keys %opt) { 3661a57419b3SSteven Rostedt 3662a57419b3SSteven Rostedt if ($option =~ /\[(\d+)\]$/) { 3663a57419b3SSteven Rostedt next if ($i != $1); 3664a57419b3SSteven Rostedt } else { 3665a57419b3SSteven Rostedt next if ($i); 3666a57419b3SSteven Rostedt } 3667a57419b3SSteven Rostedt 36682b7d9b21SSteven Rostedt doprint "$option = $opt{$option}\n"; 36692b7d9b21SSteven Rostedt } 3670a57419b3SSteven Rostedt} 36712545eb61SSteven Rostedt 36722a62512bSSteven Rostedtsub __set_test_option { 36735a391fbfSSteven Rostedt my ($name, $i) = @_; 36745a391fbfSSteven Rostedt 36755a391fbfSSteven Rostedt my $option = "$name\[$i\]"; 36765a391fbfSSteven Rostedt 36775a391fbfSSteven Rostedt if (defined($opt{$option})) { 36785a391fbfSSteven Rostedt return $opt{$option}; 36795a391fbfSSteven Rostedt } 36805a391fbfSSteven Rostedt 3681a57419b3SSteven Rostedt foreach my $test (keys %repeat_tests) { 3682a57419b3SSteven Rostedt if ($i >= $test && 3683a57419b3SSteven Rostedt $i < $test + $repeat_tests{$test}) { 3684a57419b3SSteven Rostedt $option = "$name\[$test\]"; 3685a57419b3SSteven Rostedt if (defined($opt{$option})) { 3686a57419b3SSteven Rostedt return $opt{$option}; 3687a57419b3SSteven Rostedt } 3688a57419b3SSteven Rostedt } 3689a57419b3SSteven Rostedt } 3690a57419b3SSteven Rostedt 36915a391fbfSSteven Rostedt if (defined($opt{$name})) { 36925a391fbfSSteven Rostedt return $opt{$name}; 36935a391fbfSSteven Rostedt } 36945a391fbfSSteven Rostedt 36955a391fbfSSteven Rostedt return undef; 36965a391fbfSSteven Rostedt} 36975a391fbfSSteven Rostedt 36982a62512bSSteven Rostedtsub set_test_option { 36992a62512bSSteven Rostedt my ($name, $i) = @_; 37002a62512bSSteven Rostedt 37012a62512bSSteven Rostedt my $option = __set_test_option($name, $i); 37022a62512bSSteven Rostedt return $option if (!defined($option)); 37032a62512bSSteven Rostedt 370423715c3cSSteven Rostedt return eval_option($option, $i); 37052a62512bSSteven Rostedt} 37062a62512bSSteven Rostedt 37072545eb61SSteven Rostedt# First we need to do is the builds 3708a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 37092545eb61SSteven Rostedt 37104ab1cce5SSteven Rostedt # Do not reboot on failing test options 37114ab1cce5SSteven Rostedt $no_reboot = 1; 3712759a3cc6SSteven Rostedt $reboot_success = 0; 37134ab1cce5SSteven Rostedt 3714683a3e64SSteven Rostedt $have_version = 0; 3715683a3e64SSteven Rostedt 3716576f627cSSteven Rostedt $iteration = $i; 3717576f627cSSteven Rostedt 3718c1434dccSSteven Rostedt undef %force_config; 3719c1434dccSSteven Rostedt 3720a75fececSSteven Rostedt my $makecmd = set_test_option("MAKE_CMD", $i); 3721a75fececSSteven Rostedt 37229cc9e091SSteven Rostedt # Load all the options into their mapped variable names 37239cc9e091SSteven Rostedt foreach my $opt (keys %option_map) { 37249cc9e091SSteven Rostedt ${$option_map{$opt}} = set_test_option($opt, $i); 37259cc9e091SSteven Rostedt } 3726b5f4aea6SSteven Rostedt 372735ce5952SSteven Rostedt $start_minconfig_defined = 1; 372835ce5952SSteven Rostedt 3729921ed4c7SSteven Rostedt # The first test may override the PRE_KTEST option 3730921ed4c7SSteven Rostedt if (defined($pre_ktest) && $i == 1) { 3731921ed4c7SSteven Rostedt doprint "\n"; 3732921ed4c7SSteven Rostedt run_command $pre_ktest; 3733921ed4c7SSteven Rostedt } 3734921ed4c7SSteven Rostedt 3735921ed4c7SSteven Rostedt # Any test can override the POST_KTEST option 3736921ed4c7SSteven Rostedt # The last test takes precedence. 3737921ed4c7SSteven Rostedt if (defined($post_ktest)) { 3738921ed4c7SSteven Rostedt $final_post_ktest = $post_ktest; 3739921ed4c7SSteven Rostedt } 3740921ed4c7SSteven Rostedt 37414c4ab120SSteven Rostedt if (!defined($start_minconfig)) { 374235ce5952SSteven Rostedt $start_minconfig_defined = 0; 37434c4ab120SSteven Rostedt $start_minconfig = $minconfig; 37444c4ab120SSteven Rostedt } 37454c4ab120SSteven Rostedt 3746a75fececSSteven Rostedt chdir $builddir || die "can't change directory to $builddir"; 3747a75fececSSteven Rostedt 3748a908a665SAndrew Jones foreach my $dir ($tmpdir, $outputdir) { 3749a908a665SAndrew Jones if (!-d $dir) { 3750a908a665SAndrew Jones mkpath($dir) or 3751a908a665SAndrew Jones die "can't create $dir"; 3752a908a665SAndrew Jones } 3753a75fececSSteven Rostedt } 3754a75fececSSteven Rostedt 3755e48c5293SSteven Rostedt $ENV{"SSH_USER"} = $ssh_user; 3756e48c5293SSteven Rostedt $ENV{"MACHINE"} = $machine; 3757e48c5293SSteven Rostedt 3758a75fececSSteven Rostedt $buildlog = "$tmpdir/buildlog-$machine"; 3759a9dd5d63SRabin Vincent $testlog = "$tmpdir/testlog-$machine"; 3760a75fececSSteven Rostedt $dmesg = "$tmpdir/dmesg-$machine"; 3761a75fececSSteven Rostedt $make = "$makecmd O=$outputdir"; 376251ad1dd1SSteven Rostedt $output_config = "$outputdir/.config"; 3763a75fececSSteven Rostedt 3764bb8474b1SSteven Rostedt if (!$buildonly) { 3765bb8474b1SSteven Rostedt $target = "$ssh_user\@$machine"; 3766a75fececSSteven Rostedt if ($reboot_type eq "grub") { 3767576f627cSSteven Rostedt dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 3768a15ba913SSteven Rostedt } elsif ($reboot_type eq "grub2") { 3769a15ba913SSteven Rostedt dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 3770a15ba913SSteven Rostedt dodie "GRUB_FILE not defined" if (!defined($grub_file)); 3771a75fececSSteven Rostedt } 3772bb8474b1SSteven Rostedt } 3773a75fececSSteven Rostedt 3774a75fececSSteven Rostedt my $run_type = $build_type; 3775a75fececSSteven Rostedt if ($test_type eq "patchcheck") { 3776b5f4aea6SSteven Rostedt $run_type = $patchcheck_type; 3777a75fececSSteven Rostedt } elsif ($test_type eq "bisect") { 3778b5f4aea6SSteven Rostedt $run_type = $bisect_type; 37790a05c769SSteven Rostedt } elsif ($test_type eq "config_bisect") { 3780b5f4aea6SSteven Rostedt $run_type = $config_bisect_type; 3781a75fececSSteven Rostedt } 3782a75fececSSteven Rostedt 37834c4ab120SSteven Rostedt if ($test_type eq "make_min_config") { 37844c4ab120SSteven Rostedt $run_type = ""; 37854c4ab120SSteven Rostedt } 37864c4ab120SSteven Rostedt 3787a75fececSSteven Rostedt # mistake in config file? 3788a75fececSSteven Rostedt if (!defined($run_type)) { 3789a75fececSSteven Rostedt $run_type = "ERROR"; 3790a75fececSSteven Rostedt } 37912545eb61SSteven Rostedt 3792e0a8742eSSteven Rostedt my $installme = ""; 3793e0a8742eSSteven Rostedt $installme = " no_install" if ($no_install); 3794e0a8742eSSteven Rostedt 37952545eb61SSteven Rostedt doprint "\n\n"; 3796e0a8742eSSteven Rostedt doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n"; 37977faafbd6SSteven Rostedt 3798921ed4c7SSteven Rostedt if (defined($pre_test)) { 3799921ed4c7SSteven Rostedt run_command $pre_test; 3800921ed4c7SSteven Rostedt } 3801921ed4c7SSteven Rostedt 38027faafbd6SSteven Rostedt unlink $dmesg; 38037faafbd6SSteven Rostedt unlink $buildlog; 3804a9dd5d63SRabin Vincent unlink $testlog; 38052545eb61SSteven Rostedt 3806250bae8bSSteven Rostedt if (defined($addconfig)) { 3807250bae8bSSteven Rostedt my $min = $minconfig; 38082b7d9b21SSteven Rostedt if (!defined($minconfig)) { 3809250bae8bSSteven Rostedt $min = ""; 3810250bae8bSSteven Rostedt } 3811250bae8bSSteven Rostedt run_command "cat $addconfig $min > $tmpdir/add_config" or 38122b7d9b21SSteven Rostedt dodie "Failed to create temp config"; 38139be2e6b5SSteven Rostedt $minconfig = "$tmpdir/add_config"; 38142b7d9b21SSteven Rostedt } 38152b7d9b21SSteven Rostedt 38166c5ee0beSSteven Rostedt if (defined($checkout)) { 38176c5ee0beSSteven Rostedt run_command "git checkout $checkout" or 38186c5ee0beSSteven Rostedt die "failed to checkout $checkout"; 38196c5ee0beSSteven Rostedt } 38206c5ee0beSSteven Rostedt 3821759a3cc6SSteven Rostedt $no_reboot = 0; 3822759a3cc6SSteven Rostedt 3823648a182cSSteven Rostedt # A test may opt to not reboot the box 3824648a182cSSteven Rostedt if ($reboot_on_success) { 3825759a3cc6SSteven Rostedt $reboot_success = 1; 3826648a182cSSteven Rostedt } 38274ab1cce5SSteven Rostedt 3828a75fececSSteven Rostedt if ($test_type eq "bisect") { 38295f9b6cedSSteven Rostedt bisect $i; 38305f9b6cedSSteven Rostedt next; 38310a05c769SSteven Rostedt } elsif ($test_type eq "config_bisect") { 38320a05c769SSteven Rostedt config_bisect $i; 38330a05c769SSteven Rostedt next; 3834a75fececSSteven Rostedt } elsif ($test_type eq "patchcheck") { 38356c5ee0beSSteven Rostedt patchcheck $i; 38366c5ee0beSSteven Rostedt next; 38374c4ab120SSteven Rostedt } elsif ($test_type eq "make_min_config") { 38384c4ab120SSteven Rostedt make_min_config $i; 38394c4ab120SSteven Rostedt next; 38405f9b6cedSSteven Rostedt } 38415f9b6cedSSteven Rostedt 38427faafbd6SSteven Rostedt if ($build_type ne "nobuild") { 38437faafbd6SSteven Rostedt build $build_type or next; 38442545eb61SSteven Rostedt } 38452545eb61SSteven Rostedt 3846cd8e368fSSteven Rostedt if ($test_type eq "install") { 3847cd8e368fSSteven Rostedt get_version; 3848cd8e368fSSteven Rostedt install; 3849cd8e368fSSteven Rostedt success $i; 3850cd8e368fSSteven Rostedt next; 3851cd8e368fSSteven Rostedt } 3852cd8e368fSSteven Rostedt 3853a75fececSSteven Rostedt if ($test_type ne "build") { 38547faafbd6SSteven Rostedt my $failed = 0; 3855ddf607e5SSteven Rostedt start_monitor_and_boot or $failed = 1; 3856a75fececSSteven Rostedt 3857a75fececSSteven Rostedt if (!$failed && $test_type ne "boot" && defined($run_test)) { 38587faafbd6SSteven Rostedt do_run_test or $failed = 1; 38595a391fbfSSteven Rostedt } 38607faafbd6SSteven Rostedt end_monitor; 38617faafbd6SSteven Rostedt next if ($failed); 3862a75fececSSteven Rostedt } 38635a391fbfSSteven Rostedt 38645f9b6cedSSteven Rostedt success $i; 386575c3fda7SSteven Rostedt} 38662545eb61SSteven Rostedt 3867921ed4c7SSteven Rostedtif (defined($final_post_ktest)) { 3868921ed4c7SSteven Rostedt run_command $final_post_ktest; 3869921ed4c7SSteven Rostedt} 3870921ed4c7SSteven Rostedt 38715c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) { 387275c3fda7SSteven Rostedt halt; 3873759a3cc6SSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) { 3874bc7c5803SSteven Rostedt reboot_to_good; 3875648a182cSSteven Rostedt} elsif (defined($switch_to_good)) { 3876648a182cSSteven Rostedt # still need to get to the good kernel 3877648a182cSSteven Rostedt run_command $switch_to_good; 38785c42fc5bSSteven Rostedt} 387975c3fda7SSteven Rostedt 3880648a182cSSteven Rostedt 3881e48c5293SSteven Rostedtdoprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 3882e48c5293SSteven Rostedt 38832545eb61SSteven Rostedtexit 0; 3884