xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision a496872212e50a7e543a027faf35b0909459ec9e)
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