xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision 8bc5e4ea3ea0e24142db2dc941233eab2a223ed4)
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,
56600bbf0aSSteven Rostedt
57600bbf0aSSteven Rostedt# required, and we will ask users if they don't have them but we keep the default
58600bbf0aSSteven Rostedt# value something that is common.
594f43e0dcSSteven Rostedt    "REBOOT_TYPE"		=> "grub",
604f43e0dcSSteven Rostedt    "LOCALVERSION"		=> "-test",
614f43e0dcSSteven Rostedt    "SSH_USER"			=> "root",
624f43e0dcSSteven Rostedt    "BUILD_TARGET"	 	=> "arch/x86/boot/bzImage",
634f43e0dcSSteven Rostedt    "TARGET_IMAGE"		=> "/boot/vmlinuz-test",
649cc9e091SSteven Rostedt
659cc9e091SSteven Rostedt    "LOG_FILE"			=> undef,
669cc9e091SSteven Rostedt    "IGNORE_UNUSED"		=> 0,
674f43e0dcSSteven Rostedt);
682545eb61SSteven Rostedt
698d1491baSSteven Rostedtmy $ktest_config;
702545eb61SSteven Rostedtmy $version;
71683a3e64SSteven Rostedtmy $have_version = 0;
72a75fececSSteven Rostedtmy $machine;
73e48c5293SSteven Rostedtmy $ssh_user;
74a75fececSSteven Rostedtmy $tmpdir;
75a75fececSSteven Rostedtmy $builddir;
76a75fececSSteven Rostedtmy $outputdir;
7751ad1dd1SSteven Rostedtmy $output_config;
78a75fececSSteven Rostedtmy $test_type;
797faafbd6SSteven Rostedtmy $build_type;
80a75fececSSteven Rostedtmy $build_options;
81921ed4c7SSteven Rostedtmy $final_post_ktest;
82921ed4c7SSteven Rostedtmy $pre_ktest;
83921ed4c7SSteven Rostedtmy $post_ktest;
84921ed4c7SSteven Rostedtmy $pre_test;
85921ed4c7SSteven Rostedtmy $post_test;
860bd6c1a3SSteven Rostedtmy $pre_build;
870bd6c1a3SSteven Rostedtmy $post_build;
880bd6c1a3SSteven Rostedtmy $pre_build_die;
890bd6c1a3SSteven Rostedtmy $post_build_die;
90a75fececSSteven Rostedtmy $reboot_type;
91a75fececSSteven Rostedtmy $reboot_script;
92a75fececSSteven Rostedtmy $power_cycle;
93e48c5293SSteven Rostedtmy $reboot;
94a75fececSSteven Rostedtmy $reboot_on_error;
95bc7c5803SSteven Rostedtmy $switch_to_good;
96bc7c5803SSteven Rostedtmy $switch_to_test;
97a75fececSSteven Rostedtmy $poweroff_on_error;
98648a182cSSteven Rostedtmy $reboot_on_success;
99a75fececSSteven Rostedtmy $die_on_failure;
100576f627cSSteven Rostedtmy $powercycle_after_reboot;
101576f627cSSteven Rostedtmy $poweroff_after_halt;
102407b95b7SSteven Rostedtmy $max_monitor_wait;
103e48c5293SSteven Rostedtmy $ssh_exec;
104e48c5293SSteven Rostedtmy $scp_to_target;
10502ad2617SSteven Rostedtmy $scp_to_target_install;
106a75fececSSteven Rostedtmy $power_off;
107a75fececSSteven Rostedtmy $grub_menu;
1082545eb61SSteven Rostedtmy $grub_number;
1092545eb61SSteven Rostedtmy $target;
1102545eb61SSteven Rostedtmy $make;
111e5c2ec11SSteven Rostedtmy $pre_install;
1128b37ca8cSSteven Rostedtmy $post_install;
113e0a8742eSSteven Rostedtmy $no_install;
1145c42fc5bSSteven Rostedtmy $noclean;
1155f9b6cedSSteven Rostedtmy $minconfig;
1164c4ab120SSteven Rostedtmy $start_minconfig;
11735ce5952SSteven Rostedtmy $start_minconfig_defined;
1184c4ab120SSteven Rostedtmy $output_minconfig;
119ccc513b6SSteven Rostedtmy $minconfig_type;
12043de3316SSteven Rostedtmy $use_output_minconfig;
1214c4ab120SSteven Rostedtmy $ignore_config;
122be405f95SSteven Rostedtmy $ignore_errors;
1232b7d9b21SSteven Rostedtmy $addconfig;
1245f9b6cedSSteven Rostedtmy $in_bisect = 0;
125b5f4aea6SSteven Rostedtmy $bisect_bad_commit = "";
126d6ce2a0bSSteven Rostedtmy $reverse_bisect;
127c960bb9fSSteven Rostedtmy $bisect_manual;
128c23dca7cSSteven Rostedtmy $bisect_skip;
12930f75da5SSteven Rostedtmy $config_bisect_good;
130c5dacb88SSteven Rostedtmy $bisect_ret_good;
131c5dacb88SSteven Rostedtmy $bisect_ret_bad;
132c5dacb88SSteven Rostedtmy $bisect_ret_skip;
133c5dacb88SSteven Rostedtmy $bisect_ret_abort;
134c5dacb88SSteven Rostedtmy $bisect_ret_default;
1356c5ee0beSSteven Rostedtmy $in_patchcheck = 0;
1365a391fbfSSteven Rostedtmy $run_test;
1376c5ee0beSSteven Rostedtmy $redirect;
1387faafbd6SSteven Rostedtmy $buildlog;
139a9dd5d63SRabin Vincentmy $testlog;
1407faafbd6SSteven Rostedtmy $dmesg;
1417faafbd6SSteven Rostedtmy $monitor_fp;
1427faafbd6SSteven Rostedtmy $monitor_pid;
1437faafbd6SSteven Rostedtmy $monitor_cnt = 0;
144a75fececSSteven Rostedtmy $sleep_time;
145a75fececSSteven Rostedtmy $bisect_sleep_time;
14627d934b2SSteven Rostedtmy $patchcheck_sleep_time;
1471990207dSSteven Rostedtmy $ignore_warnings;
148a75fececSSteven Rostedtmy $store_failures;
149de5b6e3bSRabin Vincentmy $store_successes;
1509064af52SSteven Rostedtmy $test_name;
151a75fececSSteven Rostedtmy $timeout;
152a75fececSSteven Rostedtmy $booted_timeout;
153f1a5b962SSteven Rostedtmy $detect_triplefault;
154a75fececSSteven Rostedtmy $console;
1552b803365SSteven Rostedtmy $reboot_success_line;
156a75fececSSteven Rostedtmy $success_line;
1571c8a617aSSteven Rostedtmy $stop_after_success;
1581c8a617aSSteven Rostedtmy $stop_after_failure;
1592d01b26aSSteven Rostedtmy $stop_test_after;
160a75fececSSteven Rostedtmy $build_target;
161a75fececSSteven Rostedtmy $target_image;
162b5f4aea6SSteven Rostedtmy $checkout;
163a75fececSSteven Rostedtmy $localversion;
164576f627cSSteven Rostedtmy $iteration = 0;
165e48c5293SSteven Rostedtmy $successes = 0;
1662545eb61SSteven Rostedt
167b5f4aea6SSteven Rostedtmy $bisect_good;
168b5f4aea6SSteven Rostedtmy $bisect_bad;
169b5f4aea6SSteven Rostedtmy $bisect_type;
170b5f4aea6SSteven Rostedtmy $bisect_start;
171b5f4aea6SSteven Rostedtmy $bisect_replay;
172b5f4aea6SSteven Rostedtmy $bisect_files;
173b5f4aea6SSteven Rostedtmy $bisect_reverse;
174b5f4aea6SSteven Rostedtmy $bisect_check;
175b5f4aea6SSteven Rostedt
176b5f4aea6SSteven Rostedtmy $config_bisect;
177b5f4aea6SSteven Rostedtmy $config_bisect_type;
178b0918612SSteven Rostedtmy $config_bisect_check;
179b5f4aea6SSteven Rostedt
180b5f4aea6SSteven Rostedtmy $patchcheck_type;
181b5f4aea6SSteven Rostedtmy $patchcheck_start;
182b5f4aea6SSteven Rostedtmy $patchcheck_end;
183b5f4aea6SSteven Rostedt
184165708b2SSteven Rostedt# set when a test is something other that just building or install
185bb8474b1SSteven Rostedt# which would require more options.
186bb8474b1SSteven Rostedtmy $buildonly = 1;
187bb8474b1SSteven Rostedt
188dbd3783bSSteven Rostedt# set when creating a new config
189dbd3783bSSteven Rostedtmy $newconfig = 0;
190dbd3783bSSteven Rostedt
1918d1491baSSteven Rostedtmy %entered_configs;
1928d1491baSSteven Rostedtmy %config_help;
19377d942ceSSteven Rostedtmy %variable;
194cf79fab6SSteven Rostedt
195cf79fab6SSteven Rostedt# force_config is the list of configs that we force enabled (or disabled)
196cf79fab6SSteven Rostedt# in a .config file. The MIN_CONFIG and ADD_CONFIG configs.
197fcb3f16aSSteven Rostedtmy %force_config;
1988d1491baSSteven Rostedt
1994ab1cce5SSteven Rostedt# do not force reboots on config problems
2004ab1cce5SSteven Rostedtmy $no_reboot = 1;
2014ab1cce5SSteven Rostedt
202759a3cc6SSteven Rostedt# reboot on success
203759a3cc6SSteven Rostedtmy $reboot_success = 0;
204759a3cc6SSteven Rostedt
2059cc9e091SSteven Rostedtmy %option_map = (
2069cc9e091SSteven Rostedt    "MACHINE"			=> \$machine,
2079cc9e091SSteven Rostedt    "SSH_USER"			=> \$ssh_user,
2089cc9e091SSteven Rostedt    "TMP_DIR"			=> \$tmpdir,
2099cc9e091SSteven Rostedt    "OUTPUT_DIR"		=> \$outputdir,
2109cc9e091SSteven Rostedt    "BUILD_DIR"			=> \$builddir,
2119cc9e091SSteven Rostedt    "TEST_TYPE"			=> \$test_type,
212921ed4c7SSteven Rostedt    "PRE_KTEST"			=> \$pre_ktest,
213921ed4c7SSteven Rostedt    "POST_KTEST"		=> \$post_ktest,
214921ed4c7SSteven Rostedt    "PRE_TEST"			=> \$pre_test,
215921ed4c7SSteven Rostedt    "POST_TEST"			=> \$post_test,
2169cc9e091SSteven Rostedt    "BUILD_TYPE"		=> \$build_type,
2179cc9e091SSteven Rostedt    "BUILD_OPTIONS"		=> \$build_options,
2189cc9e091SSteven Rostedt    "PRE_BUILD"			=> \$pre_build,
2199cc9e091SSteven Rostedt    "POST_BUILD"		=> \$post_build,
2209cc9e091SSteven Rostedt    "PRE_BUILD_DIE"		=> \$pre_build_die,
2219cc9e091SSteven Rostedt    "POST_BUILD_DIE"		=> \$post_build_die,
2229cc9e091SSteven Rostedt    "POWER_CYCLE"		=> \$power_cycle,
2239cc9e091SSteven Rostedt    "REBOOT"			=> \$reboot,
2249cc9e091SSteven Rostedt    "BUILD_NOCLEAN"		=> \$noclean,
2259cc9e091SSteven Rostedt    "MIN_CONFIG"		=> \$minconfig,
2269cc9e091SSteven Rostedt    "OUTPUT_MIN_CONFIG"		=> \$output_minconfig,
2279cc9e091SSteven Rostedt    "START_MIN_CONFIG"		=> \$start_minconfig,
228ccc513b6SSteven Rostedt    "MIN_CONFIG_TYPE"		=> \$minconfig_type,
22943de3316SSteven Rostedt    "USE_OUTPUT_MIN_CONFIG"	=> \$use_output_minconfig,
2309cc9e091SSteven Rostedt    "IGNORE_CONFIG"		=> \$ignore_config,
2319cc9e091SSteven Rostedt    "TEST"			=> \$run_test,
2329cc9e091SSteven Rostedt    "ADD_CONFIG"		=> \$addconfig,
2339cc9e091SSteven Rostedt    "REBOOT_TYPE"		=> \$reboot_type,
2349cc9e091SSteven Rostedt    "GRUB_MENU"			=> \$grub_menu,
235e5c2ec11SSteven Rostedt    "PRE_INSTALL"		=> \$pre_install,
2369cc9e091SSteven Rostedt    "POST_INSTALL"		=> \$post_install,
2379cc9e091SSteven Rostedt    "NO_INSTALL"		=> \$no_install,
2389cc9e091SSteven Rostedt    "REBOOT_SCRIPT"		=> \$reboot_script,
2399cc9e091SSteven Rostedt    "REBOOT_ON_ERROR"		=> \$reboot_on_error,
2409cc9e091SSteven Rostedt    "SWITCH_TO_GOOD"		=> \$switch_to_good,
2419cc9e091SSteven Rostedt    "SWITCH_TO_TEST"		=> \$switch_to_test,
2429cc9e091SSteven Rostedt    "POWEROFF_ON_ERROR"		=> \$poweroff_on_error,
243648a182cSSteven Rostedt    "REBOOT_ON_SUCCESS"		=> \$reboot_on_success,
2449cc9e091SSteven Rostedt    "DIE_ON_FAILURE"		=> \$die_on_failure,
2459cc9e091SSteven Rostedt    "POWER_OFF"			=> \$power_off,
2469cc9e091SSteven Rostedt    "POWERCYCLE_AFTER_REBOOT"	=> \$powercycle_after_reboot,
2479cc9e091SSteven Rostedt    "POWEROFF_AFTER_HALT"	=> \$poweroff_after_halt,
248407b95b7SSteven Rostedt    "MAX_MONITOR_WAIT"		=> \$max_monitor_wait,
2499cc9e091SSteven Rostedt    "SLEEP_TIME"		=> \$sleep_time,
2509cc9e091SSteven Rostedt    "BISECT_SLEEP_TIME"		=> \$bisect_sleep_time,
2519cc9e091SSteven Rostedt    "PATCHCHECK_SLEEP_TIME"	=> \$patchcheck_sleep_time,
2529cc9e091SSteven Rostedt    "IGNORE_WARNINGS"		=> \$ignore_warnings,
253be405f95SSteven Rostedt    "IGNORE_ERRORS"		=> \$ignore_errors,
2549cc9e091SSteven Rostedt    "BISECT_MANUAL"		=> \$bisect_manual,
2559cc9e091SSteven Rostedt    "BISECT_SKIP"		=> \$bisect_skip,
2569cc9e091SSteven Rostedt    "CONFIG_BISECT_GOOD"	=> \$config_bisect_good,
2579cc9e091SSteven Rostedt    "BISECT_RET_GOOD"		=> \$bisect_ret_good,
2589cc9e091SSteven Rostedt    "BISECT_RET_BAD"		=> \$bisect_ret_bad,
2599cc9e091SSteven Rostedt    "BISECT_RET_SKIP"		=> \$bisect_ret_skip,
2609cc9e091SSteven Rostedt    "BISECT_RET_ABORT"		=> \$bisect_ret_abort,
2619cc9e091SSteven Rostedt    "BISECT_RET_DEFAULT"	=> \$bisect_ret_default,
2629cc9e091SSteven Rostedt    "STORE_FAILURES"		=> \$store_failures,
2639cc9e091SSteven Rostedt    "STORE_SUCCESSES"		=> \$store_successes,
2649cc9e091SSteven Rostedt    "TEST_NAME"			=> \$test_name,
2659cc9e091SSteven Rostedt    "TIMEOUT"			=> \$timeout,
2669cc9e091SSteven Rostedt    "BOOTED_TIMEOUT"		=> \$booted_timeout,
2679cc9e091SSteven Rostedt    "CONSOLE"			=> \$console,
2689cc9e091SSteven Rostedt    "DETECT_TRIPLE_FAULT"	=> \$detect_triplefault,
2699cc9e091SSteven Rostedt    "SUCCESS_LINE"		=> \$success_line,
2709cc9e091SSteven Rostedt    "REBOOT_SUCCESS_LINE"	=> \$reboot_success_line,
2719cc9e091SSteven Rostedt    "STOP_AFTER_SUCCESS"	=> \$stop_after_success,
2729cc9e091SSteven Rostedt    "STOP_AFTER_FAILURE"	=> \$stop_after_failure,
2739cc9e091SSteven Rostedt    "STOP_TEST_AFTER"		=> \$stop_test_after,
2749cc9e091SSteven Rostedt    "BUILD_TARGET"		=> \$build_target,
2759cc9e091SSteven Rostedt    "SSH_EXEC"			=> \$ssh_exec,
2769cc9e091SSteven Rostedt    "SCP_TO_TARGET"		=> \$scp_to_target,
27702ad2617SSteven Rostedt    "SCP_TO_TARGET_INSTALL"	=> \$scp_to_target_install,
2789cc9e091SSteven Rostedt    "CHECKOUT"			=> \$checkout,
2799cc9e091SSteven Rostedt    "TARGET_IMAGE"		=> \$target_image,
2809cc9e091SSteven Rostedt    "LOCALVERSION"		=> \$localversion,
2819cc9e091SSteven Rostedt
2829cc9e091SSteven Rostedt    "BISECT_GOOD"		=> \$bisect_good,
2839cc9e091SSteven Rostedt    "BISECT_BAD"		=> \$bisect_bad,
2849cc9e091SSteven Rostedt    "BISECT_TYPE"		=> \$bisect_type,
2859cc9e091SSteven Rostedt    "BISECT_START"		=> \$bisect_start,
2869cc9e091SSteven Rostedt    "BISECT_REPLAY"		=> \$bisect_replay,
2879cc9e091SSteven Rostedt    "BISECT_FILES"		=> \$bisect_files,
2889cc9e091SSteven Rostedt    "BISECT_REVERSE"		=> \$bisect_reverse,
2899cc9e091SSteven Rostedt    "BISECT_CHECK"		=> \$bisect_check,
2909cc9e091SSteven Rostedt
2919cc9e091SSteven Rostedt    "CONFIG_BISECT"		=> \$config_bisect,
2929cc9e091SSteven Rostedt    "CONFIG_BISECT_TYPE"	=> \$config_bisect_type,
293b0918612SSteven Rostedt    "CONFIG_BISECT_CHECK"	=> \$config_bisect_check,
2949cc9e091SSteven Rostedt
2959cc9e091SSteven Rostedt    "PATCHCHECK_TYPE"		=> \$patchcheck_type,
2969cc9e091SSteven Rostedt    "PATCHCHECK_START"		=> \$patchcheck_start,
2979cc9e091SSteven Rostedt    "PATCHCHECK_END"		=> \$patchcheck_end,
2989cc9e091SSteven Rostedt);
2999cc9e091SSteven Rostedt
3009cc9e091SSteven Rostedt# Options may be used by other options, record them.
3019cc9e091SSteven Rostedtmy %used_options;
3029cc9e091SSteven Rostedt
3037bf51073SSteven Rostedt# default variables that can be used
3047bf51073SSteven Rostedtchomp ($variable{"PWD"} = `pwd`);
3057bf51073SSteven Rostedt
3068d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF"
3078d1491baSSteven Rostedt The machine hostname that you will test.
308bb8474b1SSteven Rostedt For build only tests, it is still needed to differentiate log files.
3098d1491baSSteven RostedtEOF
3108d1491baSSteven Rostedt    ;
3118d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF"
3128d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user
3138d1491baSSteven Rostedt  (most likely root, since you need privileged operations)
3148d1491baSSteven RostedtEOF
3158d1491baSSteven Rostedt    ;
3168d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF"
3178d1491baSSteven Rostedt The directory that contains the Linux source code (full path).
3180e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
3190e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
3208d1491baSSteven RostedtEOF
3218d1491baSSteven Rostedt    ;
3228d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF"
3238d1491baSSteven Rostedt The directory that the objects will be built (full path).
3248d1491baSSteven Rostedt (can not be same as BUILD_DIR)
3250e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
3260e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
3278d1491baSSteven RostedtEOF
3288d1491baSSteven Rostedt    ;
3298d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF"
3308d1491baSSteven Rostedt The location of the compiled file to copy to the target.
3318d1491baSSteven Rostedt (relative to OUTPUT_DIR)
3328d1491baSSteven RostedtEOF
3338d1491baSSteven Rostedt    ;
334dbd3783bSSteven Rostedt$config_help{"BUILD_OPTIONS"} = << "EOF"
335dbd3783bSSteven Rostedt Options to add to \"make\" when building.
336dbd3783bSSteven Rostedt i.e.  -j20
337dbd3783bSSteven RostedtEOF
338dbd3783bSSteven Rostedt    ;
3398d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF"
3408d1491baSSteven Rostedt The place to put your image on the test machine.
3418d1491baSSteven RostedtEOF
3428d1491baSSteven Rostedt    ;
3438d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF"
3448d1491baSSteven Rostedt A script or command to reboot the box.
3458d1491baSSteven Rostedt
3468d1491baSSteven Rostedt Here is a digital loggers power switch example
3478d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
3488d1491baSSteven Rostedt
3498d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host
3508d1491baSSteven Rostedt with the name "Guest".
3518d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
3528d1491baSSteven RostedtEOF
3538d1491baSSteven Rostedt    ;
3548d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF"
3558d1491baSSteven Rostedt The script or command that reads the console
3568d1491baSSteven Rostedt
3578d1491baSSteven Rostedt  If you use ttywatch server, something like the following would work.
3588d1491baSSteven RostedtCONSOLE = nc -d localhost 3001
3598d1491baSSteven Rostedt
3608d1491baSSteven Rostedt For a virtual machine with guest name "Guest".
3618d1491baSSteven RostedtCONSOLE =  virsh console Guest
3628d1491baSSteven RostedtEOF
3638d1491baSSteven Rostedt    ;
3648d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF"
3658d1491baSSteven Rostedt Required version ending to differentiate the test
3668d1491baSSteven Rostedt from other linux builds on the system.
3678d1491baSSteven RostedtEOF
3688d1491baSSteven Rostedt    ;
3698d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF"
3708d1491baSSteven Rostedt Way to reboot the box to the test kernel.
3718d1491baSSteven Rostedt Only valid options so far are "grub" and "script".
3728d1491baSSteven Rostedt
3738d1491baSSteven Rostedt If you specify grub, it will assume grub version 1
3748d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
3758d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not
3768d1491baSSteven Rostedt your setup, then specify "script" and have a command or script
3778d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target.
3788d1491baSSteven Rostedt
3798d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually.
3808d1491baSSteven Rostedt The test will not modify that file.
3818d1491baSSteven RostedtEOF
3828d1491baSSteven Rostedt    ;
3838d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF"
3848d1491baSSteven Rostedt The grub title name for the test kernel to boot
3858d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = grub)
3868d1491baSSteven Rostedt
3878d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to
3888d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search
3898d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to
3908d1491baSSteven Rostedt reboot into.
3918d1491baSSteven Rostedt
3928d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has:
3938d1491baSSteven Rostedt title Test Kernel
3948d1491baSSteven Rostedt kernel vmlinuz-test
3958d1491baSSteven Rostedt GRUB_MENU = Test Kernel
3968d1491baSSteven RostedtEOF
3978d1491baSSteven Rostedt    ;
3988d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF"
3998d1491baSSteven Rostedt A script to reboot the target into the test kernel
4008d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script)
4018d1491baSSteven RostedtEOF
4028d1491baSSteven Rostedt    ;
4038d1491baSSteven Rostedt
404dad98754SSteven Rostedtsub read_prompt {
405dad98754SSteven Rostedt    my ($cancel, $prompt) = @_;
40635ce5952SSteven Rostedt
40735ce5952SSteven Rostedt    my $ans;
40835ce5952SSteven Rostedt
40935ce5952SSteven Rostedt    for (;;) {
410dad98754SSteven Rostedt	if ($cancel) {
411dad98754SSteven Rostedt	    print "$prompt [y/n/C] ";
412dad98754SSteven Rostedt	} else {
41335ce5952SSteven Rostedt	    print "$prompt [Y/n] ";
414dad98754SSteven Rostedt	}
41535ce5952SSteven Rostedt	$ans = <STDIN>;
41635ce5952SSteven Rostedt	chomp $ans;
41735ce5952SSteven Rostedt	if ($ans =~ /^\s*$/) {
418dad98754SSteven Rostedt	    if ($cancel) {
419dad98754SSteven Rostedt		$ans = "c";
420dad98754SSteven Rostedt	    } else {
42135ce5952SSteven Rostedt		$ans = "y";
42235ce5952SSteven Rostedt	    }
423dad98754SSteven Rostedt	}
42435ce5952SSteven Rostedt	last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
425dad98754SSteven Rostedt	if ($cancel) {
426dad98754SSteven Rostedt	    last if ($ans =~ /^c$/i);
427dad98754SSteven Rostedt	    print "Please answer either 'y', 'n' or 'c'.\n";
428dad98754SSteven Rostedt	} else {
42935ce5952SSteven Rostedt	    print "Please answer either 'y' or 'n'.\n";
43035ce5952SSteven Rostedt	}
431dad98754SSteven Rostedt    }
432dad98754SSteven Rostedt    if ($ans =~ /^c/i) {
433dad98754SSteven Rostedt	exit;
434dad98754SSteven Rostedt    }
43535ce5952SSteven Rostedt    if ($ans !~ /^y$/i) {
43635ce5952SSteven Rostedt	return 0;
43735ce5952SSteven Rostedt    }
43835ce5952SSteven Rostedt    return 1;
43935ce5952SSteven Rostedt}
4408d1491baSSteven Rostedt
441dad98754SSteven Rostedtsub read_yn {
442dad98754SSteven Rostedt    my ($prompt) = @_;
443dad98754SSteven Rostedt
444dad98754SSteven Rostedt    return read_prompt 0, $prompt;
445dad98754SSteven Rostedt}
446dad98754SSteven Rostedt
447dad98754SSteven Rostedtsub read_ync {
448dad98754SSteven Rostedt    my ($prompt) = @_;
449dad98754SSteven Rostedt
450dad98754SSteven Rostedt    return read_prompt 1, $prompt;
451dad98754SSteven Rostedt}
452dad98754SSteven Rostedt
4538d1491baSSteven Rostedtsub get_ktest_config {
4548d1491baSSteven Rostedt    my ($config) = @_;
455815e2bd7SSteven Rostedt    my $ans;
4568d1491baSSteven Rostedt
4578d1491baSSteven Rostedt    return if (defined($opt{$config}));
4588d1491baSSteven Rostedt
4598d1491baSSteven Rostedt    if (defined($config_help{$config})) {
4608d1491baSSteven Rostedt	print "\n";
4618d1491baSSteven Rostedt	print $config_help{$config};
4628d1491baSSteven Rostedt    }
4638d1491baSSteven Rostedt
4648d1491baSSteven Rostedt    for (;;) {
4658d1491baSSteven Rostedt	print "$config = ";
466dbd3783bSSteven Rostedt	if (defined($default{$config}) && length($default{$config})) {
4678d1491baSSteven Rostedt	    print "\[$default{$config}\] ";
4688d1491baSSteven Rostedt	}
469815e2bd7SSteven Rostedt	$ans = <STDIN>;
470815e2bd7SSteven Rostedt	$ans =~ s/^\s*(.*\S)\s*$/$1/;
471815e2bd7SSteven Rostedt	if ($ans =~ /^\s*$/) {
4728d1491baSSteven Rostedt	    if ($default{$config}) {
473815e2bd7SSteven Rostedt		$ans = $default{$config};
4748d1491baSSteven Rostedt	    } else {
4758d1491baSSteven Rostedt		print "Your answer can not be blank\n";
4768d1491baSSteven Rostedt		next;
4778d1491baSSteven Rostedt	    }
4788d1491baSSteven Rostedt	}
4790e7a22deSSteven Rostedt	$entered_configs{$config} = ${ans};
4808d1491baSSteven Rostedt	last;
4818d1491baSSteven Rostedt    }
4828d1491baSSteven Rostedt}
4838d1491baSSteven Rostedt
4848d1491baSSteven Rostedtsub get_ktest_configs {
4858d1491baSSteven Rostedt    get_ktest_config("MACHINE");
4868d1491baSSteven Rostedt    get_ktest_config("BUILD_DIR");
4878d1491baSSteven Rostedt    get_ktest_config("OUTPUT_DIR");
488bb8474b1SSteven Rostedt
489dbd3783bSSteven Rostedt    if ($newconfig) {
490dbd3783bSSteven Rostedt	get_ktest_config("BUILD_OPTIONS");
491dbd3783bSSteven Rostedt    }
492dbd3783bSSteven Rostedt
493bb8474b1SSteven Rostedt    # options required for other than just building a kernel
494bb8474b1SSteven Rostedt    if (!$buildonly) {
495165708b2SSteven Rostedt	get_ktest_config("POWER_CYCLE");
496165708b2SSteven Rostedt	get_ktest_config("CONSOLE");
497165708b2SSteven Rostedt    }
498165708b2SSteven Rostedt
499165708b2SSteven Rostedt    # options required for install and more
500165708b2SSteven Rostedt    if ($buildonly != 1) {
501bb8474b1SSteven Rostedt	get_ktest_config("SSH_USER");
5028d1491baSSteven Rostedt	get_ktest_config("BUILD_TARGET");
5038d1491baSSteven Rostedt	get_ktest_config("TARGET_IMAGE");
504bb8474b1SSteven Rostedt    }
505bb8474b1SSteven Rostedt
5068d1491baSSteven Rostedt    get_ktest_config("LOCALVERSION");
5078d1491baSSteven Rostedt
508bb8474b1SSteven Rostedt    return if ($buildonly);
509bb8474b1SSteven Rostedt
5108d1491baSSteven Rostedt    my $rtype = $opt{"REBOOT_TYPE"};
5118d1491baSSteven Rostedt
5128d1491baSSteven Rostedt    if (!defined($rtype)) {
5138d1491baSSteven Rostedt	if (!defined($opt{"GRUB_MENU"})) {
5148d1491baSSteven Rostedt	    get_ktest_config("REBOOT_TYPE");
5158d1491baSSteven Rostedt	    $rtype = $entered_configs{"REBOOT_TYPE"};
5168d1491baSSteven Rostedt	} else {
5178d1491baSSteven Rostedt	    $rtype = "grub";
5188d1491baSSteven Rostedt	}
5198d1491baSSteven Rostedt    }
5208d1491baSSteven Rostedt
5218d1491baSSteven Rostedt    if ($rtype eq "grub") {
5228d1491baSSteven Rostedt	get_ktest_config("GRUB_MENU");
5238d1491baSSteven Rostedt    }
5248d1491baSSteven Rostedt}
5258d1491baSSteven Rostedt
52677d942ceSSteven Rostedtsub process_variables {
5278d735212SSteven Rostedt    my ($value, $remove_undef) = @_;
52877d942ceSSteven Rostedt    my $retval = "";
52977d942ceSSteven Rostedt
53077d942ceSSteven Rostedt    # We want to check for '\', and it is just easier
53177d942ceSSteven Rostedt    # to check the previous characet of '$' and not need
53277d942ceSSteven Rostedt    # to worry if '$' is the first character. By adding
53377d942ceSSteven Rostedt    # a space to $value, we can just check [^\\]\$ and
53477d942ceSSteven Rostedt    # it will still work.
53577d942ceSSteven Rostedt    $value = " $value";
53677d942ceSSteven Rostedt
53777d942ceSSteven Rostedt    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
53877d942ceSSteven Rostedt	my $begin = $1;
53977d942ceSSteven Rostedt	my $var = $2;
54077d942ceSSteven Rostedt	my $end = $3;
54177d942ceSSteven Rostedt	# append beginning of value to retval
54277d942ceSSteven Rostedt	$retval = "$retval$begin";
54377d942ceSSteven Rostedt	if (defined($variable{$var})) {
54477d942ceSSteven Rostedt	    $retval = "$retval$variable{$var}";
5458d735212SSteven Rostedt	} elsif (defined($remove_undef) && $remove_undef) {
5468d735212SSteven Rostedt	    # for if statements, any variable that is not defined,
5478d735212SSteven Rostedt	    # we simple convert to 0
5488d735212SSteven Rostedt	    $retval = "${retval}0";
54977d942ceSSteven Rostedt	} else {
55077d942ceSSteven Rostedt	    # put back the origin piece.
55177d942ceSSteven Rostedt	    $retval = "$retval\$\{$var\}";
5529cc9e091SSteven Rostedt	    # This could be an option that is used later, save
5539cc9e091SSteven Rostedt	    # it so we don't warn if this option is not one of
5549cc9e091SSteven Rostedt	    # ktests options.
5559cc9e091SSteven Rostedt	    $used_options{$var} = 1;
55677d942ceSSteven Rostedt	}
55777d942ceSSteven Rostedt	$value = $end;
55877d942ceSSteven Rostedt    }
55977d942ceSSteven Rostedt    $retval = "$retval$value";
56077d942ceSSteven Rostedt
56177d942ceSSteven Rostedt    # remove the space added in the beginning
56277d942ceSSteven Rostedt    $retval =~ s/ //;
56377d942ceSSteven Rostedt
56477d942ceSSteven Rostedt    return "$retval"
56577d942ceSSteven Rostedt}
56677d942ceSSteven Rostedt
567a57419b3SSteven Rostedtsub set_value {
5683d1cc414SSteven Rostedt    my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
5692545eb61SSteven Rostedt
570cad96669SSteven Rostedt    my $prvalue = process_variables($rvalue);
571cad96669SSteven Rostedt
572cad96669SSteven Rostedt    if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") {
573bb8474b1SSteven Rostedt	# Note if a test is something other than build, then we
574bb8474b1SSteven Rostedt	# will need other manditory options.
575cad96669SSteven Rostedt	if ($prvalue ne "install") {
576bb8474b1SSteven Rostedt	    $buildonly = 0;
577165708b2SSteven Rostedt	} else {
578165708b2SSteven Rostedt	    # install still limits some manditory options.
579165708b2SSteven Rostedt	    $buildonly = 2;
580165708b2SSteven Rostedt	}
581bb8474b1SSteven Rostedt    }
582bb8474b1SSteven Rostedt
583a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
5843d1cc414SSteven Rostedt	if (!$override || defined(${$overrides}{$lvalue})) {
5853d1cc414SSteven Rostedt	    my $extra = "";
5863d1cc414SSteven Rostedt	    if ($override) {
5873d1cc414SSteven Rostedt		$extra = "In the same override section!\n";
5883d1cc414SSteven Rostedt	    }
5893d1cc414SSteven Rostedt	    die "$name: $.: Option $lvalue defined more than once!\n$extra";
5903d1cc414SSteven Rostedt	}
591cad96669SSteven Rostedt	${$overrides}{$lvalue} = $prvalue;
592a75fececSSteven Rostedt    }
59321a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
59421a9679fSSteven Rostedt	delete $opt{$lvalue};
59521a9679fSSteven Rostedt    } else {
596cad96669SSteven Rostedt	$opt{$lvalue} = $prvalue;
59721a9679fSSteven Rostedt    }
5982545eb61SSteven Rostedt}
599a57419b3SSteven Rostedt
60077d942ceSSteven Rostedtsub set_variable {
60177d942ceSSteven Rostedt    my ($lvalue, $rvalue) = @_;
60277d942ceSSteven Rostedt
60377d942ceSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
60477d942ceSSteven Rostedt	delete $variable{$lvalue};
60577d942ceSSteven Rostedt    } else {
60677d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
60777d942ceSSteven Rostedt	$variable{$lvalue} = $rvalue;
60877d942ceSSteven Rostedt    }
60977d942ceSSteven Rostedt}
61077d942ceSSteven Rostedt
611ab7a3f52SSteven Rostedtsub process_compare {
612ab7a3f52SSteven Rostedt    my ($lval, $cmp, $rval) = @_;
613ab7a3f52SSteven Rostedt
614ab7a3f52SSteven Rostedt    # remove whitespace
615ab7a3f52SSteven Rostedt
616ab7a3f52SSteven Rostedt    $lval =~ s/^\s*//;
617ab7a3f52SSteven Rostedt    $lval =~ s/\s*$//;
618ab7a3f52SSteven Rostedt
619ab7a3f52SSteven Rostedt    $rval =~ s/^\s*//;
620ab7a3f52SSteven Rostedt    $rval =~ s/\s*$//;
621ab7a3f52SSteven Rostedt
622ab7a3f52SSteven Rostedt    if ($cmp eq "==") {
623ab7a3f52SSteven Rostedt	return $lval eq $rval;
624ab7a3f52SSteven Rostedt    } elsif ($cmp eq "!=") {
625ab7a3f52SSteven Rostedt	return $lval ne $rval;
6268fddbe9bSSteven Rostedt    } elsif ($cmp eq "=~") {
6278fddbe9bSSteven Rostedt	return $lval =~ m/$rval/;
6288fddbe9bSSteven Rostedt    } elsif ($cmp eq "!~") {
6298fddbe9bSSteven Rostedt	return $lval !~ m/$rval/;
630ab7a3f52SSteven Rostedt    }
631ab7a3f52SSteven Rostedt
632ab7a3f52SSteven Rostedt    my $statement = "$lval $cmp $rval";
633ab7a3f52SSteven Rostedt    my $ret = eval $statement;
634ab7a3f52SSteven Rostedt
635ab7a3f52SSteven Rostedt    # $@ stores error of eval
636ab7a3f52SSteven Rostedt    if ($@) {
637ab7a3f52SSteven Rostedt	return -1;
638ab7a3f52SSteven Rostedt    }
639ab7a3f52SSteven Rostedt
640ab7a3f52SSteven Rostedt    return $ret;
641ab7a3f52SSteven Rostedt}
642ab7a3f52SSteven Rostedt
6439900b5dcSSteven Rostedtsub value_defined {
6449900b5dcSSteven Rostedt    my ($val) = @_;
6459900b5dcSSteven Rostedt
6469900b5dcSSteven Rostedt    return defined($variable{$2}) ||
6479900b5dcSSteven Rostedt	defined($opt{$2});
6489900b5dcSSteven Rostedt}
6499900b5dcSSteven Rostedt
6508d735212SSteven Rostedtmy $d = 0;
6518d735212SSteven Rostedtsub process_expression {
6528d735212SSteven Rostedt    my ($name, $val) = @_;
65345d73a5dSSteven Rostedt
6548d735212SSteven Rostedt    my $c = $d++;
6558d735212SSteven Rostedt
6568d735212SSteven Rostedt    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
6578d735212SSteven Rostedt	my $express = $1;
6588d735212SSteven Rostedt
6598d735212SSteven Rostedt	if (process_expression($name, $express)) {
6608d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
6618d735212SSteven Rostedt	} else {
6628d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
6638d735212SSteven Rostedt	}
6648d735212SSteven Rostedt    }
6658d735212SSteven Rostedt
6668d735212SSteven Rostedt    $d--;
6678d735212SSteven Rostedt    my $OR = "\\|\\|";
6688d735212SSteven Rostedt    my $AND = "\\&\\&";
6698d735212SSteven Rostedt
6708d735212SSteven Rostedt    while ($val =~ s/^(.*?)($OR|$AND)//) {
6718d735212SSteven Rostedt	my $express = $1;
6728d735212SSteven Rostedt	my $op = $2;
6738d735212SSteven Rostedt
6748d735212SSteven Rostedt	if (process_expression($name, $express)) {
6758d735212SSteven Rostedt	    if ($op eq "||") {
6768d735212SSteven Rostedt		return 1;
6778d735212SSteven Rostedt	    }
6788d735212SSteven Rostedt	} else {
6798d735212SSteven Rostedt	    if ($op eq "&&") {
6808d735212SSteven Rostedt		return 0;
6818d735212SSteven Rostedt	    }
6828d735212SSteven Rostedt	}
6838d735212SSteven Rostedt    }
68445d73a5dSSteven Rostedt
6858fddbe9bSSteven Rostedt    if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) {
686ab7a3f52SSteven Rostedt	my $ret = process_compare($1, $2, $3);
687ab7a3f52SSteven Rostedt	if ($ret < 0) {
688ab7a3f52SSteven Rostedt	    die "$name: $.: Unable to process comparison\n";
689ab7a3f52SSteven Rostedt	}
690ab7a3f52SSteven Rostedt	return $ret;
691ab7a3f52SSteven Rostedt    }
692ab7a3f52SSteven Rostedt
6939900b5dcSSteven Rostedt    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
6949900b5dcSSteven Rostedt	if (defined $1) {
6959900b5dcSSteven Rostedt	    return !value_defined($2);
6969900b5dcSSteven Rostedt	} else {
6979900b5dcSSteven Rostedt	    return value_defined($2);
6989900b5dcSSteven Rostedt	}
6999900b5dcSSteven Rostedt    }
7009900b5dcSSteven Rostedt
70145d73a5dSSteven Rostedt    if ($val =~ /^\s*0\s*$/) {
70245d73a5dSSteven Rostedt	return 0;
70345d73a5dSSteven Rostedt    } elsif ($val =~ /^\s*\d+\s*$/) {
70445d73a5dSSteven Rostedt	return 1;
70545d73a5dSSteven Rostedt    }
70645d73a5dSSteven Rostedt
7079900b5dcSSteven Rostedt    die ("$name: $.: Undefined content $val in if statement\n");
7088d735212SSteven Rostedt}
7098d735212SSteven Rostedt
7108d735212SSteven Rostedtsub process_if {
7118d735212SSteven Rostedt    my ($name, $value) = @_;
7128d735212SSteven Rostedt
7138d735212SSteven Rostedt    # Convert variables and replace undefined ones with 0
7148d735212SSteven Rostedt    my $val = process_variables($value, 1);
7158d735212SSteven Rostedt    my $ret = process_expression $name, $val;
7168d735212SSteven Rostedt
7178d735212SSteven Rostedt    return $ret;
71845d73a5dSSteven Rostedt}
71945d73a5dSSteven Rostedt
7202ed3b161SSteven Rostedtsub __read_config {
7212ed3b161SSteven Rostedt    my ($config, $current_test_num) = @_;
722a57419b3SSteven Rostedt
7232ed3b161SSteven Rostedt    my $in;
7242ed3b161SSteven Rostedt    open($in, $config) || die "can't read file $config";
725a57419b3SSteven Rostedt
726a57419b3SSteven Rostedt    my $name = $config;
727a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
728a57419b3SSteven Rostedt
7292ed3b161SSteven Rostedt    my $test_num = $$current_test_num;
730a57419b3SSteven Rostedt    my $default = 1;
731a57419b3SSteven Rostedt    my $repeat = 1;
732a57419b3SSteven Rostedt    my $num_tests_set = 0;
733a57419b3SSteven Rostedt    my $skip = 0;
734a57419b3SSteven Rostedt    my $rest;
735a9f84424SSteven Rostedt    my $line;
7360df213caSSteven Rostedt    my $test_case = 0;
73745d73a5dSSteven Rostedt    my $if = 0;
73845d73a5dSSteven Rostedt    my $if_set = 0;
7393d1cc414SSteven Rostedt    my $override = 0;
7403d1cc414SSteven Rostedt
7413d1cc414SSteven Rostedt    my %overrides;
742a57419b3SSteven Rostedt
7432ed3b161SSteven Rostedt    while (<$in>) {
744a57419b3SSteven Rostedt
745a57419b3SSteven Rostedt	# ignore blank lines and comments
746a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
747a57419b3SSteven Rostedt
7480050b6bbSSteven Rostedt	if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
749a57419b3SSteven Rostedt
7500050b6bbSSteven Rostedt	    my $type = $1;
7510050b6bbSSteven Rostedt	    $rest = $2;
752a9f84424SSteven Rostedt	    $line = $2;
7530050b6bbSSteven Rostedt
7540050b6bbSSteven Rostedt	    my $old_test_num;
7550050b6bbSSteven Rostedt	    my $old_repeat;
7563d1cc414SSteven Rostedt	    $override = 0;
7570050b6bbSSteven Rostedt
7580050b6bbSSteven Rostedt	    if ($type eq "TEST_START") {
759a57419b3SSteven Rostedt
760a57419b3SSteven Rostedt		if ($num_tests_set) {
761a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
762a57419b3SSteven Rostedt		}
763a57419b3SSteven Rostedt
7640050b6bbSSteven Rostedt		$old_test_num = $test_num;
7650050b6bbSSteven Rostedt		$old_repeat = $repeat;
766a57419b3SSteven Rostedt
767a57419b3SSteven Rostedt		$test_num += $repeat;
768a57419b3SSteven Rostedt		$default = 0;
769a57419b3SSteven Rostedt		$repeat = 1;
7700050b6bbSSteven Rostedt	    } else {
7710050b6bbSSteven Rostedt		$default = 1;
7720050b6bbSSteven Rostedt	    }
773a57419b3SSteven Rostedt
774a9f84424SSteven Rostedt	    # If SKIP is anywhere in the line, the command will be skipped
775a9f84424SSteven Rostedt	    if ($rest =~ s/\s+SKIP\b//) {
776a57419b3SSteven Rostedt		$skip = 1;
777a57419b3SSteven Rostedt	    } else {
7780df213caSSteven Rostedt		$test_case = 1;
779a57419b3SSteven Rostedt		$skip = 0;
780a57419b3SSteven Rostedt	    }
781a57419b3SSteven Rostedt
782a9f84424SSteven Rostedt	    if ($rest =~ s/\sELSE\b//) {
783a9f84424SSteven Rostedt		if (!$if) {
784a9f84424SSteven Rostedt		    die "$name: $.: ELSE found with out matching IF section\n$_";
785a57419b3SSteven Rostedt		}
786a9f84424SSteven Rostedt		$if = 0;
787a9f84424SSteven Rostedt
788a9f84424SSteven Rostedt		if ($if_set) {
789a9f84424SSteven Rostedt		    $skip = 1;
790a9f84424SSteven Rostedt		} else {
791a9f84424SSteven Rostedt		    $skip = 0;
7923d1cc414SSteven Rostedt		}
7933d1cc414SSteven Rostedt	    }
794a57419b3SSteven Rostedt
795a9f84424SSteven Rostedt	    if ($rest =~ s/\sIF\s+(.*)//) {
79645d73a5dSSteven Rostedt		if (process_if($name, $1)) {
79745d73a5dSSteven Rostedt		    $if_set = 1;
79845d73a5dSSteven Rostedt		} else {
799a57419b3SSteven Rostedt		    $skip = 1;
800a57419b3SSteven Rostedt		}
80145d73a5dSSteven Rostedt		$if = 1;
80245d73a5dSSteven Rostedt	    } else {
80345d73a5dSSteven Rostedt		$if = 0;
804a9f84424SSteven Rostedt		$if_set = 0;
80545d73a5dSSteven Rostedt	    }
806a57419b3SSteven Rostedt
807a9f84424SSteven Rostedt	    if (!$skip) {
808a9f84424SSteven Rostedt		if ($type eq "TEST_START") {
809a9f84424SSteven Rostedt		    if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
810a9f84424SSteven Rostedt			$repeat = $1;
811a9f84424SSteven Rostedt			$repeat_tests{"$test_num"} = $repeat;
812a9f84424SSteven Rostedt		    }
813a9f84424SSteven Rostedt		} elsif ($rest =~ s/\sOVERRIDE\b//) {
814a9f84424SSteven Rostedt		    # DEFAULT only
815a9f84424SSteven Rostedt		    $override = 1;
816a9f84424SSteven Rostedt		    # Clear previous overrides
817a9f84424SSteven Rostedt		    %overrides = ();
818a9f84424SSteven Rostedt		}
819a9f84424SSteven Rostedt	    }
820a9f84424SSteven Rostedt
821a9f84424SSteven Rostedt	    if (!$skip && $rest !~ /^\s*$/) {
8220050b6bbSSteven Rostedt		die "$name: $.: Gargbage found after $type\n$_";
823a57419b3SSteven Rostedt	    }
824a57419b3SSteven Rostedt
8250050b6bbSSteven Rostedt	    if ($skip && $type eq "TEST_START") {
826a57419b3SSteven Rostedt		$test_num = $old_test_num;
827e48c5293SSteven Rostedt		$repeat = $old_repeat;
828a57419b3SSteven Rostedt	    }
829a57419b3SSteven Rostedt
830ab7a3f52SSteven Rostedt	} elsif (/^\s*ELSE\b(.*)$/) {
83145d73a5dSSteven Rostedt	    if (!$if) {
83245d73a5dSSteven Rostedt		die "$name: $.: ELSE found with out matching IF section\n$_";
83345d73a5dSSteven Rostedt	    }
83445d73a5dSSteven Rostedt	    $rest = $1;
83545d73a5dSSteven Rostedt	    if ($if_set) {
83645d73a5dSSteven Rostedt		$skip = 1;
837ab7a3f52SSteven Rostedt		$rest = "";
83845d73a5dSSteven Rostedt	    } else {
83945d73a5dSSteven Rostedt		$skip = 0;
84045d73a5dSSteven Rostedt
841ab7a3f52SSteven Rostedt		if ($rest =~ /\sIF\s+(.*)/) {
84245d73a5dSSteven Rostedt		    # May be a ELSE IF section.
84395f57838SSteven Rostedt		    if (process_if($name, $1)) {
84495f57838SSteven Rostedt			$if_set = 1;
84595f57838SSteven Rostedt		    } else {
84645d73a5dSSteven Rostedt			$skip = 1;
84745d73a5dSSteven Rostedt		    }
848ab7a3f52SSteven Rostedt		    $rest = "";
84945d73a5dSSteven Rostedt		} else {
85045d73a5dSSteven Rostedt		    $if = 0;
85145d73a5dSSteven Rostedt		}
85245d73a5dSSteven Rostedt	    }
85345d73a5dSSteven Rostedt
854ab7a3f52SSteven Rostedt	    if ($rest !~ /^\s*$/) {
855ab7a3f52SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
856ab7a3f52SSteven Rostedt	    }
857ab7a3f52SSteven Rostedt
8582ed3b161SSteven Rostedt	} elsif (/^\s*INCLUDE\s+(\S+)/) {
8592ed3b161SSteven Rostedt
8602ed3b161SSteven Rostedt	    next if ($skip);
8612ed3b161SSteven Rostedt
8622ed3b161SSteven Rostedt	    if (!$default) {
8632ed3b161SSteven Rostedt		die "$name: $.: INCLUDE can only be done in default sections\n$_";
8642ed3b161SSteven Rostedt	    }
8652ed3b161SSteven Rostedt
8662ed3b161SSteven Rostedt	    my $file = process_variables($1);
8672ed3b161SSteven Rostedt
8682ed3b161SSteven Rostedt	    if ($file !~ m,^/,) {
8692ed3b161SSteven Rostedt		# check the path of the config file first
8702ed3b161SSteven Rostedt		if ($config =~ m,(.*)/,) {
8712ed3b161SSteven Rostedt		    if (-f "$1/$file") {
8722ed3b161SSteven Rostedt			$file = "$1/$file";
8732ed3b161SSteven Rostedt		    }
8742ed3b161SSteven Rostedt		}
8752ed3b161SSteven Rostedt	    }
8762ed3b161SSteven Rostedt
8772ed3b161SSteven Rostedt	    if ( ! -r $file ) {
8782ed3b161SSteven Rostedt		die "$name: $.: Can't read file $file\n$_";
8792ed3b161SSteven Rostedt	    }
8802ed3b161SSteven Rostedt
8812ed3b161SSteven Rostedt	    if (__read_config($file, \$test_num)) {
8822ed3b161SSteven Rostedt		$test_case = 1;
8832ed3b161SSteven Rostedt	    }
8842ed3b161SSteven Rostedt
885a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
886a57419b3SSteven Rostedt
887a57419b3SSteven Rostedt	    next if ($skip);
888a57419b3SSteven Rostedt
889a57419b3SSteven Rostedt	    my $lvalue = $1;
890a57419b3SSteven Rostedt	    my $rvalue = $2;
891a57419b3SSteven Rostedt
892a57419b3SSteven Rostedt	    if (!$default &&
893a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
894a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
895a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
896a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
897a57419b3SSteven Rostedt	    }
898a57419b3SSteven Rostedt
899a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
900a57419b3SSteven Rostedt		if ($test_num) {
901a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
902a57419b3SSteven Rostedt		}
903a57419b3SSteven Rostedt		if (!$default) {
904a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
905a57419b3SSteven Rostedt		}
906a57419b3SSteven Rostedt		$num_tests_set = 1;
907a57419b3SSteven Rostedt	    }
908a57419b3SSteven Rostedt
909a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
9103d1cc414SSteven Rostedt		set_value($lvalue, $rvalue, $override, \%overrides, $name);
911a57419b3SSteven Rostedt	    } else {
912a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
9133d1cc414SSteven Rostedt		set_value($val, $rvalue, $override, \%overrides, $name);
914a57419b3SSteven Rostedt
915a57419b3SSteven Rostedt		if ($repeat > 1) {
916a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
917a57419b3SSteven Rostedt		}
918a57419b3SSteven Rostedt	    }
91977d942ceSSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
92077d942ceSSteven Rostedt	    next if ($skip);
92177d942ceSSteven Rostedt
92277d942ceSSteven Rostedt	    my $lvalue = $1;
92377d942ceSSteven Rostedt	    my $rvalue = $2;
92477d942ceSSteven Rostedt
92577d942ceSSteven Rostedt	    # process config variables.
92677d942ceSSteven Rostedt	    # Config variables are only active while reading the
92777d942ceSSteven Rostedt	    # config and can be defined anywhere. They also ignore
92877d942ceSSteven Rostedt	    # TEST_START and DEFAULTS, but are skipped if they are in
92977d942ceSSteven Rostedt	    # on of these sections that have SKIP defined.
93077d942ceSSteven Rostedt	    # The save variable can be
93177d942ceSSteven Rostedt	    # defined multiple times and the new one simply overrides
93277d942ceSSteven Rostedt	    # the prevous one.
93377d942ceSSteven Rostedt	    set_variable($lvalue, $rvalue);
93477d942ceSSteven Rostedt
935a57419b3SSteven Rostedt	} else {
936a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
937a57419b3SSteven Rostedt	}
9382545eb61SSteven Rostedt    }
9392545eb61SSteven Rostedt
940a57419b3SSteven Rostedt    if ($test_num) {
941a57419b3SSteven Rostedt	$test_num += $repeat - 1;
942a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
943a57419b3SSteven Rostedt    }
944a57419b3SSteven Rostedt
9452ed3b161SSteven Rostedt    close($in);
9462ed3b161SSteven Rostedt
9472ed3b161SSteven Rostedt    $$current_test_num = $test_num;
9482ed3b161SSteven Rostedt
9492ed3b161SSteven Rostedt    return $test_case;
9502ed3b161SSteven Rostedt}
9512ed3b161SSteven Rostedt
952c4261d0fSSteven Rostedtsub get_test_case {
953c4261d0fSSteven Rostedt	print "What test case would you like to run?\n";
954c4261d0fSSteven Rostedt	print " (build, install or boot)\n";
955c4261d0fSSteven Rostedt	print " Other tests are available but require editing the config file\n";
956c4261d0fSSteven Rostedt	my $ans = <STDIN>;
957c4261d0fSSteven Rostedt	chomp $ans;
958c4261d0fSSteven Rostedt	$default{"TEST_TYPE"} = $ans;
959c4261d0fSSteven Rostedt}
960c4261d0fSSteven Rostedt
9612ed3b161SSteven Rostedtsub read_config {
9622ed3b161SSteven Rostedt    my ($config) = @_;
9632ed3b161SSteven Rostedt
9642ed3b161SSteven Rostedt    my $test_case;
9652ed3b161SSteven Rostedt    my $test_num = 0;
9662ed3b161SSteven Rostedt
9672ed3b161SSteven Rostedt    $test_case = __read_config $config, \$test_num;
9682ed3b161SSteven Rostedt
9698d1491baSSteven Rostedt    # make sure we have all mandatory configs
9708d1491baSSteven Rostedt    get_ktest_configs;
9718d1491baSSteven Rostedt
9720df213caSSteven Rostedt    # was a test specified?
9730df213caSSteven Rostedt    if (!$test_case) {
9740df213caSSteven Rostedt	print "No test case specified.\n";
975c4261d0fSSteven Rostedt	get_test_case;
9760df213caSSteven Rostedt    }
9770df213caSSteven Rostedt
978a75fececSSteven Rostedt    # set any defaults
979a75fececSSteven Rostedt
980a75fececSSteven Rostedt    foreach my $default (keys %default) {
981a75fececSSteven Rostedt	if (!defined($opt{$default})) {
982a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
983a75fececSSteven Rostedt	}
984a75fececSSteven Rostedt    }
9859cc9e091SSteven Rostedt
9869cc9e091SSteven Rostedt    if ($opt{"IGNORE_UNUSED"} == 1) {
9879cc9e091SSteven Rostedt	return;
9889cc9e091SSteven Rostedt    }
9899cc9e091SSteven Rostedt
9909cc9e091SSteven Rostedt    my %not_used;
9919cc9e091SSteven Rostedt
9929cc9e091SSteven Rostedt    # check if there are any stragglers (typos?)
9939cc9e091SSteven Rostedt    foreach my $option (keys %opt) {
9949cc9e091SSteven Rostedt	my $op = $option;
9959cc9e091SSteven Rostedt	# remove per test labels.
9969cc9e091SSteven Rostedt	$op =~ s/\[.*\]//;
9979cc9e091SSteven Rostedt	if (!exists($option_map{$op}) &&
9989cc9e091SSteven Rostedt	    !exists($default{$op}) &&
9999cc9e091SSteven Rostedt	    !exists($used_options{$op})) {
10009cc9e091SSteven Rostedt	    $not_used{$op} = 1;
10019cc9e091SSteven Rostedt	}
10029cc9e091SSteven Rostedt    }
10039cc9e091SSteven Rostedt
10049cc9e091SSteven Rostedt    if (%not_used) {
10059cc9e091SSteven Rostedt	my $s = "s are";
10069cc9e091SSteven Rostedt	$s = " is" if (keys %not_used == 1);
10079cc9e091SSteven Rostedt	print "The following option$s not used; could be a typo:\n";
10089cc9e091SSteven Rostedt	foreach my $option (keys %not_used) {
10099cc9e091SSteven Rostedt	    print "$option\n";
10109cc9e091SSteven Rostedt	}
10119cc9e091SSteven Rostedt	print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n";
10129cc9e091SSteven Rostedt	if (!read_yn "Do you want to continue?") {
10139cc9e091SSteven Rostedt	    exit -1;
10149cc9e091SSteven Rostedt	}
10159cc9e091SSteven Rostedt    }
10162545eb61SSteven Rostedt}
10172545eb61SSteven Rostedt
101823715c3cSSteven Rostedtsub __eval_option {
101923715c3cSSteven Rostedt    my ($option, $i) = @_;
102023715c3cSSteven Rostedt
102123715c3cSSteven Rostedt    # Add space to evaluate the character before $
102223715c3cSSteven Rostedt    $option = " $option";
102323715c3cSSteven Rostedt    my $retval = "";
1024f9dfb65bSRabin Vincent    my $repeated = 0;
1025f9dfb65bSRabin Vincent    my $parent = 0;
1026f9dfb65bSRabin Vincent
1027f9dfb65bSRabin Vincent    foreach my $test (keys %repeat_tests) {
1028f9dfb65bSRabin Vincent	if ($i >= $test &&
1029f9dfb65bSRabin Vincent	    $i < $test + $repeat_tests{$test}) {
1030f9dfb65bSRabin Vincent
1031f9dfb65bSRabin Vincent	    $repeated = 1;
1032f9dfb65bSRabin Vincent	    $parent = $test;
1033f9dfb65bSRabin Vincent	    last;
1034f9dfb65bSRabin Vincent	}
1035f9dfb65bSRabin Vincent    }
103623715c3cSSteven Rostedt
103723715c3cSSteven Rostedt    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
103823715c3cSSteven Rostedt	my $start = $1;
103923715c3cSSteven Rostedt	my $var = $2;
104023715c3cSSteven Rostedt	my $end = $3;
104123715c3cSSteven Rostedt
104223715c3cSSteven Rostedt	# Append beginning of line
104323715c3cSSteven Rostedt	$retval = "$retval$start";
104423715c3cSSteven Rostedt
104523715c3cSSteven Rostedt	# If the iteration option OPT[$i] exists, then use that.
104623715c3cSSteven Rostedt	# otherwise see if the default OPT (without [$i]) exists.
104723715c3cSSteven Rostedt
104823715c3cSSteven Rostedt	my $o = "$var\[$i\]";
1049f9dfb65bSRabin Vincent	my $parento = "$var\[$parent\]";
105023715c3cSSteven Rostedt
105123715c3cSSteven Rostedt	if (defined($opt{$o})) {
105223715c3cSSteven Rostedt	    $o = $opt{$o};
105323715c3cSSteven Rostedt	    $retval = "$retval$o";
1054f9dfb65bSRabin Vincent	} elsif ($repeated && defined($opt{$parento})) {
1055f9dfb65bSRabin Vincent	    $o = $opt{$parento};
1056f9dfb65bSRabin Vincent	    $retval = "$retval$o";
105723715c3cSSteven Rostedt	} elsif (defined($opt{$var})) {
105823715c3cSSteven Rostedt	    $o = $opt{$var};
105923715c3cSSteven Rostedt	    $retval = "$retval$o";
106023715c3cSSteven Rostedt	} else {
106123715c3cSSteven Rostedt	    $retval = "$retval\$\{$var\}";
106223715c3cSSteven Rostedt	}
106323715c3cSSteven Rostedt
106423715c3cSSteven Rostedt	$option = $end;
106523715c3cSSteven Rostedt    }
106623715c3cSSteven Rostedt
106723715c3cSSteven Rostedt    $retval = "$retval$option";
106823715c3cSSteven Rostedt
106923715c3cSSteven Rostedt    $retval =~ s/^ //;
107023715c3cSSteven Rostedt
107123715c3cSSteven Rostedt    return $retval;
107223715c3cSSteven Rostedt}
107323715c3cSSteven Rostedt
107423715c3cSSteven Rostedtsub eval_option {
107523715c3cSSteven Rostedt    my ($option, $i) = @_;
107623715c3cSSteven Rostedt
107723715c3cSSteven Rostedt    my $prev = "";
107823715c3cSSteven Rostedt
107923715c3cSSteven Rostedt    # Since an option can evaluate to another option,
108023715c3cSSteven Rostedt    # keep iterating until we do not evaluate any more
108123715c3cSSteven Rostedt    # options.
108223715c3cSSteven Rostedt    my $r = 0;
108323715c3cSSteven Rostedt    while ($prev ne $option) {
108423715c3cSSteven Rostedt	# Check for recursive evaluations.
108523715c3cSSteven Rostedt	# 100 deep should be more than enough.
108623715c3cSSteven Rostedt	if ($r++ > 100) {
108723715c3cSSteven Rostedt	    die "Over 100 evaluations accurred with $option\n" .
108823715c3cSSteven Rostedt		"Check for recursive variables\n";
108923715c3cSSteven Rostedt	}
109023715c3cSSteven Rostedt	$prev = $option;
109123715c3cSSteven Rostedt	$option = __eval_option($option, $i);
109223715c3cSSteven Rostedt    }
109323715c3cSSteven Rostedt
109423715c3cSSteven Rostedt    return $option;
109523715c3cSSteven Rostedt}
109623715c3cSSteven Rostedt
1097d1e2f22aSSteven Rostedtsub _logit {
10982545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
10992545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
11002545eb61SSteven Rostedt	print OUT @_;
11012545eb61SSteven Rostedt	close(OUT);
11022545eb61SSteven Rostedt    }
11032545eb61SSteven Rostedt}
11042545eb61SSteven Rostedt
1105d1e2f22aSSteven Rostedtsub logit {
1106d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1107d1e2f22aSSteven Rostedt	_logit @_;
1108d1e2f22aSSteven Rostedt    } else {
1109d1e2f22aSSteven Rostedt	print @_;
1110d1e2f22aSSteven Rostedt    }
1111d1e2f22aSSteven Rostedt}
1112d1e2f22aSSteven Rostedt
11135f9b6cedSSteven Rostedtsub doprint {
11145f9b6cedSSteven Rostedt    print @_;
1115d1e2f22aSSteven Rostedt    _logit @_;
11165f9b6cedSSteven Rostedt}
11175f9b6cedSSteven Rostedt
11187faafbd6SSteven Rostedtsub run_command;
11192728be41SAndrew Jonessub start_monitor;
11202728be41SAndrew Jonessub end_monitor;
11212728be41SAndrew Jonessub wait_for_monitor;
11227faafbd6SSteven Rostedt
11237faafbd6SSteven Rostedtsub reboot {
11242728be41SAndrew Jones    my ($time) = @_;
11252728be41SAndrew Jones
11262b803365SSteven Rostedt    if (defined($time)) {
11272b803365SSteven Rostedt	start_monitor;
11282b803365SSteven Rostedt	# flush out current monitor
11292b803365SSteven Rostedt	# May contain the reboot success line
11302b803365SSteven Rostedt	wait_for_monitor 1;
11312b803365SSteven Rostedt    }
11322b803365SSteven Rostedt
11337faafbd6SSteven Rostedt    # try to reboot normally
1134e48c5293SSteven Rostedt    if (run_command $reboot) {
1135576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
1136576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
1137576f627cSSteven Rostedt	    run_command "$power_cycle";
1138576f627cSSteven Rostedt	}
1139576f627cSSteven Rostedt    } else {
11407faafbd6SSteven Rostedt	# nope? power cycle it.
1141a75fececSSteven Rostedt	run_command "$power_cycle";
11427faafbd6SSteven Rostedt    }
11432728be41SAndrew Jones
11442728be41SAndrew Jones    if (defined($time)) {
1145407b95b7SSteven Rostedt	if (wait_for_monitor($time, $reboot_success_line)) {
1146407b95b7SSteven Rostedt	    # reboot got stuck?
11478a80c727SSteven Rostedt	    doprint "Reboot did not finish. Forcing power cycle\n";
1148407b95b7SSteven Rostedt	    run_command "$power_cycle";
1149407b95b7SSteven Rostedt	}
11502728be41SAndrew Jones	end_monitor;
11512728be41SAndrew Jones    }
11527faafbd6SSteven Rostedt}
11537faafbd6SSteven Rostedt
1154bc7c5803SSteven Rostedtsub reboot_to_good {
1155bc7c5803SSteven Rostedt    my ($time) = @_;
1156bc7c5803SSteven Rostedt
1157bc7c5803SSteven Rostedt    if (defined($switch_to_good)) {
1158bc7c5803SSteven Rostedt	run_command $switch_to_good;
1159bc7c5803SSteven Rostedt    }
1160bc7c5803SSteven Rostedt
1161bc7c5803SSteven Rostedt    reboot $time;
1162bc7c5803SSteven Rostedt}
1163bc7c5803SSteven Rostedt
1164576f627cSSteven Rostedtsub do_not_reboot {
1165576f627cSSteven Rostedt    my $i = $iteration;
1166576f627cSSteven Rostedt
11674ab1cce5SSteven Rostedt    return $test_type eq "build" || $no_reboot ||
1168576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
1169576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
1170576f627cSSteven Rostedt}
1171576f627cSSteven Rostedt
11725c42fc5bSSteven Rostedtsub dodie {
11735a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
11745c42fc5bSSteven Rostedt
1175576f627cSSteven Rostedt    my $i = $iteration;
1176576f627cSSteven Rostedt
1177576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
1178576f627cSSteven Rostedt
117975c3fda7SSteven Rostedt	doprint "REBOOTING\n";
1180bc7c5803SSteven Rostedt	reboot_to_good;
118175c3fda7SSteven Rostedt
1182a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
11835c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
1184a75fececSSteven Rostedt	`$power_off`;
11855c42fc5bSSteven Rostedt    }
118675c3fda7SSteven Rostedt
1187f80802cbSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1188f80802cbSSteven Rostedt	print " See $opt{LOG_FILE} for more info.\n";
1189f80802cbSSteven Rostedt    }
1190f80802cbSSteven Rostedt
1191576f627cSSteven Rostedt    die @_, "\n";
11925c42fc5bSSteven Rostedt}
11935c42fc5bSSteven Rostedt
11947faafbd6SSteven Rostedtsub open_console {
11957faafbd6SSteven Rostedt    my ($fp) = @_;
11967faafbd6SSteven Rostedt
11977faafbd6SSteven Rostedt    my $flags;
11987faafbd6SSteven Rostedt
1199a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
1200a75fececSSteven Rostedt	dodie "Can't open console $console";
12017faafbd6SSteven Rostedt
12027faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
1203576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
12047faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
1205576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
12067faafbd6SSteven Rostedt
12077faafbd6SSteven Rostedt    return $pid;
12087faafbd6SSteven Rostedt}
12097faafbd6SSteven Rostedt
12107faafbd6SSteven Rostedtsub close_console {
12117faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
12127faafbd6SSteven Rostedt
12137faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
12147faafbd6SSteven Rostedt    kill 2, $pid;
12157faafbd6SSteven Rostedt
12167faafbd6SSteven Rostedt    print "closing!\n";
12177faafbd6SSteven Rostedt    close($fp);
12187faafbd6SSteven Rostedt}
12197faafbd6SSteven Rostedt
12207faafbd6SSteven Rostedtsub start_monitor {
12217faafbd6SSteven Rostedt    if ($monitor_cnt++) {
12227faafbd6SSteven Rostedt	return;
12237faafbd6SSteven Rostedt    }
12247faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
12257faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
1226a75fececSSteven Rostedt
1227a75fececSSteven Rostedt    return;
1228a75fececSSteven Rostedt
1229a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
12307faafbd6SSteven Rostedt}
12317faafbd6SSteven Rostedt
12327faafbd6SSteven Rostedtsub end_monitor {
12337faafbd6SSteven Rostedt    if (--$monitor_cnt) {
12347faafbd6SSteven Rostedt	return;
12357faafbd6SSteven Rostedt    }
12367faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
12377faafbd6SSteven Rostedt}
12387faafbd6SSteven Rostedt
12397faafbd6SSteven Rostedtsub wait_for_monitor {
12402b803365SSteven Rostedt    my ($time, $stop) = @_;
12412b803365SSteven Rostedt    my $full_line = "";
12427faafbd6SSteven Rostedt    my $line;
12432b803365SSteven Rostedt    my $booted = 0;
1244407b95b7SSteven Rostedt    my $start_time = time;
12458a80c727SSteven Rostedt    my $skip_call_trace = 0;
12468a80c727SSteven Rostedt    my $bug = 0;
12478a80c727SSteven Rostedt    my $bug_ignored = 0;
1248407b95b7SSteven Rostedt    my $now;
12497faafbd6SSteven Rostedt
1250a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
12517faafbd6SSteven Rostedt
12527faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
12532b803365SSteven Rostedt    while (!$booted) {
12547faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
12552b803365SSteven Rostedt	last if (!defined($line));
12562b803365SSteven Rostedt	print "$line";
12572b803365SSteven Rostedt	$full_line .= $line;
12582b803365SSteven Rostedt
12592b803365SSteven Rostedt	if (defined($stop) && $full_line =~ /$stop/) {
12602b803365SSteven Rostedt	    doprint "wait for monitor detected $stop\n";
12612b803365SSteven Rostedt	    $booted = 1;
12622b803365SSteven Rostedt	}
12632b803365SSteven Rostedt
12648a80c727SSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
12658a80c727SSteven Rostedt	    $skip_call_trace = 1;
12668a80c727SSteven Rostedt	}
12678a80c727SSteven Rostedt
12688a80c727SSteven Rostedt	if ($full_line =~ /call trace:/i) {
12698a80c727SSteven Rostedt	    if (!$bug && !$skip_call_trace) {
12708a80c727SSteven Rostedt		if ($ignore_errors) {
12718a80c727SSteven Rostedt		    $bug_ignored = 1;
12728a80c727SSteven Rostedt		} else {
12738a80c727SSteven Rostedt		    $bug = 1;
12748a80c727SSteven Rostedt		}
12758a80c727SSteven Rostedt	    }
12768a80c727SSteven Rostedt	}
12778a80c727SSteven Rostedt
12788a80c727SSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
12798a80c727SSteven Rostedt	    $skip_call_trace = 0;
12808a80c727SSteven Rostedt	}
12818a80c727SSteven Rostedt
12828a80c727SSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
12838a80c727SSteven Rostedt	    $bug = 1;
12848a80c727SSteven Rostedt	}
12858a80c727SSteven Rostedt
12862b803365SSteven Rostedt	if ($line =~ /\n/) {
12872b803365SSteven Rostedt	    $full_line = "";
12882b803365SSteven Rostedt	}
1289407b95b7SSteven Rostedt	$now = time;
1290407b95b7SSteven Rostedt	if ($now - $start_time >= $max_monitor_wait) {
1291407b95b7SSteven Rostedt	    doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n";
1292407b95b7SSteven Rostedt	    return 1;
1293407b95b7SSteven Rostedt	}
12942b803365SSteven Rostedt    }
1295a75fececSSteven Rostedt    print "** Monitor flushed **\n";
12968a80c727SSteven Rostedt    return $bug;
12977faafbd6SSteven Rostedt}
12987faafbd6SSteven Rostedt
1299de5b6e3bSRabin Vincentsub save_logs {
1300de5b6e3bSRabin Vincent	my ($result, $basedir) = @_;
1301de5b6e3bSRabin Vincent	my @t = localtime;
1302de5b6e3bSRabin Vincent	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1303de5b6e3bSRabin Vincent		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1304de5b6e3bSRabin Vincent
1305de5b6e3bSRabin Vincent	my $type = $build_type;
1306de5b6e3bSRabin Vincent	if ($type =~ /useconfig/) {
1307de5b6e3bSRabin Vincent	    $type = "useconfig";
1308de5b6e3bSRabin Vincent	}
1309de5b6e3bSRabin Vincent
1310de5b6e3bSRabin Vincent	my $dir = "$machine-$test_type-$type-$result-$date";
1311de5b6e3bSRabin Vincent
1312de5b6e3bSRabin Vincent	$dir = "$basedir/$dir";
1313de5b6e3bSRabin Vincent
1314de5b6e3bSRabin Vincent	if (!-d $dir) {
1315de5b6e3bSRabin Vincent	    mkpath($dir) or
1316de5b6e3bSRabin Vincent		die "can't create $dir";
1317de5b6e3bSRabin Vincent	}
1318de5b6e3bSRabin Vincent
1319de5b6e3bSRabin Vincent	my %files = (
1320de5b6e3bSRabin Vincent		"config" => $output_config,
1321de5b6e3bSRabin Vincent		"buildlog" => $buildlog,
1322de5b6e3bSRabin Vincent		"dmesg" => $dmesg,
1323de5b6e3bSRabin Vincent		"testlog" => $testlog,
1324de5b6e3bSRabin Vincent	);
1325de5b6e3bSRabin Vincent
1326de5b6e3bSRabin Vincent	while (my ($name, $source) = each(%files)) {
1327de5b6e3bSRabin Vincent		if (-f "$source") {
1328de5b6e3bSRabin Vincent			cp "$source", "$dir/$name" or
1329de5b6e3bSRabin Vincent				die "failed to copy $source";
1330de5b6e3bSRabin Vincent		}
1331de5b6e3bSRabin Vincent	}
1332de5b6e3bSRabin Vincent
1333de5b6e3bSRabin Vincent	doprint "*** Saved info to $dir ***\n";
1334de5b6e3bSRabin Vincent}
1335de5b6e3bSRabin Vincent
13362b7d9b21SSteven Rostedtsub fail {
13372b7d9b21SSteven Rostedt
1338921ed4c7SSteven Rostedt	if (defined($post_test)) {
1339921ed4c7SSteven Rostedt		run_command $post_test;
1340921ed4c7SSteven Rostedt	}
1341921ed4c7SSteven Rostedt
1342a75fececSSteven Rostedt	if ($die_on_failure) {
13432b7d9b21SSteven Rostedt		dodie @_;
13442b7d9b21SSteven Rostedt	}
13452b7d9b21SSteven Rostedt
1346a75fececSSteven Rostedt	doprint "FAILED\n";
13477faafbd6SSteven Rostedt
1348576f627cSSteven Rostedt	my $i = $iteration;
1349576f627cSSteven Rostedt
1350a75fececSSteven Rostedt	# no need to reboot for just building.
1351576f627cSSteven Rostedt	if (!do_not_reboot) {
13527faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
1353bc7c5803SSteven Rostedt	    reboot_to_good $sleep_time;
1354a75fececSSteven Rostedt	}
13557faafbd6SSteven Rostedt
13569064af52SSteven Rostedt	my $name = "";
13579064af52SSteven Rostedt
13589064af52SSteven Rostedt	if (defined($test_name)) {
13599064af52SSteven Rostedt	    $name = " ($test_name)";
13609064af52SSteven Rostedt	}
13619064af52SSteven Rostedt
1362576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1363576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
13649064af52SSteven Rostedt	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1365576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1366576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1367a75fececSSteven Rostedt
1368de5b6e3bSRabin Vincent	if (defined($store_failures)) {
1369de5b6e3bSRabin Vincent	    save_logs "fail", $store_failures;
1370cccae1a6SSteven Rostedt        }
1371cccae1a6SSteven Rostedt
13722b7d9b21SSteven Rostedt	return 1;
13732b7d9b21SSteven Rostedt}
13742b7d9b21SSteven Rostedt
13752545eb61SSteven Rostedtsub run_command {
13762545eb61SSteven Rostedt    my ($command) = @_;
1377d6ce2a0bSSteven Rostedt    my $dolog = 0;
1378d6ce2a0bSSteven Rostedt    my $dord = 0;
1379d6ce2a0bSSteven Rostedt    my $pid;
1380d6ce2a0bSSteven Rostedt
1381e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
1382e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
1383e48c5293SSteven Rostedt
1384d6ce2a0bSSteven Rostedt    doprint("$command ... ");
1385d6ce2a0bSSteven Rostedt
1386d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
13872b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
13882545eb61SSteven Rostedt
13892545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1390d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
1391d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
1392d6ce2a0bSSteven Rostedt	$dolog = 1;
13936c5ee0beSSteven Rostedt    }
13946c5ee0beSSteven Rostedt
13956c5ee0beSSteven Rostedt    if (defined($redirect)) {
1396d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
1397d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
1398d6ce2a0bSSteven Rostedt	$dord = 1;
13992545eb61SSteven Rostedt    }
14002545eb61SSteven Rostedt
1401d6ce2a0bSSteven Rostedt    while (<CMD>) {
1402d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
1403d6ce2a0bSSteven Rostedt	print RD  if ($dord);
1404d6ce2a0bSSteven Rostedt    }
14052545eb61SSteven Rostedt
1406d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
14072545eb61SSteven Rostedt    my $failed = $?;
14082545eb61SSteven Rostedt
1409d6ce2a0bSSteven Rostedt    close(CMD);
1410d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
1411d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
1412d6ce2a0bSSteven Rostedt
14132545eb61SSteven Rostedt    if ($failed) {
14142545eb61SSteven Rostedt	doprint "FAILED!\n";
14152545eb61SSteven Rostedt    } else {
14162545eb61SSteven Rostedt	doprint "SUCCESS\n";
14172545eb61SSteven Rostedt    }
14182545eb61SSteven Rostedt
14195f9b6cedSSteven Rostedt    return !$failed;
14205f9b6cedSSteven Rostedt}
14215f9b6cedSSteven Rostedt
1422e48c5293SSteven Rostedtsub run_ssh {
1423e48c5293SSteven Rostedt    my ($cmd) = @_;
1424e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
1425e48c5293SSteven Rostedt
1426e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1427e48c5293SSteven Rostedt    return run_command "$cp_exec";
1428e48c5293SSteven Rostedt}
1429e48c5293SSteven Rostedt
1430e48c5293SSteven Rostedtsub run_scp {
143102ad2617SSteven Rostedt    my ($src, $dst, $cp_scp) = @_;
1432e48c5293SSteven Rostedt
1433e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
1434e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
1435e48c5293SSteven Rostedt
1436e48c5293SSteven Rostedt    return run_command "$cp_scp";
1437e48c5293SSteven Rostedt}
1438e48c5293SSteven Rostedt
143902ad2617SSteven Rostedtsub run_scp_install {
144002ad2617SSteven Rostedt    my ($src, $dst) = @_;
144102ad2617SSteven Rostedt
144202ad2617SSteven Rostedt    my $cp_scp = $scp_to_target_install;
144302ad2617SSteven Rostedt
144402ad2617SSteven Rostedt    return run_scp($src, $dst, $cp_scp);
144502ad2617SSteven Rostedt}
144602ad2617SSteven Rostedt
144702ad2617SSteven Rostedtsub run_scp_mod {
144802ad2617SSteven Rostedt    my ($src, $dst) = @_;
144902ad2617SSteven Rostedt
145002ad2617SSteven Rostedt    my $cp_scp = $scp_to_target;
145102ad2617SSteven Rostedt
145202ad2617SSteven Rostedt    return run_scp($src, $dst, $cp_scp);
145302ad2617SSteven Rostedt}
145402ad2617SSteven Rostedt
14555f9b6cedSSteven Rostedtsub get_grub_index {
14565f9b6cedSSteven Rostedt
1457a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
1458a75fececSSteven Rostedt	return;
1459a75fececSSteven Rostedt    }
14605a391fbfSSteven Rostedt    return if (defined($grub_number));
14615f9b6cedSSteven Rostedt
14625f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
14635f9b6cedSSteven Rostedt    $grub_number = -1;
1464e48c5293SSteven Rostedt
1465e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
1466e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
1467e48c5293SSteven Rostedt
1468e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
14695f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
1470e48c5293SSteven Rostedt
1471eaa1fe25SSteven Rostedt    my $found = 0;
1472eaa1fe25SSteven Rostedt
14735f9b6cedSSteven Rostedt    while (<IN>) {
1474a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
14755f9b6cedSSteven Rostedt	    $grub_number++;
1476eaa1fe25SSteven Rostedt	    $found = 1;
14775f9b6cedSSteven Rostedt	    last;
14785f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
14795f9b6cedSSteven Rostedt	    $grub_number++;
14805f9b6cedSSteven Rostedt	}
14815f9b6cedSSteven Rostedt    }
14825f9b6cedSSteven Rostedt    close(IN);
14835f9b6cedSSteven Rostedt
1484a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
1485eaa1fe25SSteven Rostedt	if (!$found);
14865f9b6cedSSteven Rostedt    doprint "$grub_number\n";
14872545eb61SSteven Rostedt}
14882545eb61SSteven Rostedt
14892545eb61SSteven Rostedtsub wait_for_input
14902545eb61SSteven Rostedt{
14912545eb61SSteven Rostedt    my ($fp, $time) = @_;
14922545eb61SSteven Rostedt    my $rin;
14932545eb61SSteven Rostedt    my $ready;
14942545eb61SSteven Rostedt    my $line;
14952545eb61SSteven Rostedt    my $ch;
14962545eb61SSteven Rostedt
14972545eb61SSteven Rostedt    if (!defined($time)) {
14982545eb61SSteven Rostedt	$time = $timeout;
14992545eb61SSteven Rostedt    }
15002545eb61SSteven Rostedt
15012545eb61SSteven Rostedt    $rin = '';
15022545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
15032545eb61SSteven Rostedt    $ready = select($rin, undef, undef, $time);
15042545eb61SSteven Rostedt
15052545eb61SSteven Rostedt    $line = "";
15062545eb61SSteven Rostedt
15072545eb61SSteven Rostedt    # try to read one char at a time
15082545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
15092545eb61SSteven Rostedt	$line .= $ch;
15102545eb61SSteven Rostedt	last if ($ch eq "\n");
15112545eb61SSteven Rostedt    }
15122545eb61SSteven Rostedt
15132545eb61SSteven Rostedt    if (!length($line)) {
15142545eb61SSteven Rostedt	return undef;
15152545eb61SSteven Rostedt    }
15162545eb61SSteven Rostedt
15172545eb61SSteven Rostedt    return $line;
15182545eb61SSteven Rostedt}
15192545eb61SSteven Rostedt
152075c3fda7SSteven Rostedtsub reboot_to {
1521bc7c5803SSteven Rostedt    if (defined($switch_to_test)) {
1522bc7c5803SSteven Rostedt	run_command $switch_to_test;
1523bc7c5803SSteven Rostedt    }
1524bc7c5803SSteven Rostedt
1525a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
1526c54367f9SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
152796f6a0dfSSteven Rostedt    } elsif (defined $reboot_script) {
1528a75fececSSteven Rostedt	run_command "$reboot_script";
15292545eb61SSteven Rostedt    }
153096f6a0dfSSteven Rostedt    reboot;
153196f6a0dfSSteven Rostedt}
15322545eb61SSteven Rostedt
1533a57419b3SSteven Rostedtsub get_sha1 {
1534a57419b3SSteven Rostedt    my ($commit) = @_;
1535a57419b3SSteven Rostedt
1536a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
1537a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
1538a57419b3SSteven Rostedt    my $ret = $?;
1539a57419b3SSteven Rostedt
1540a57419b3SSteven Rostedt    logit $sha1;
1541a57419b3SSteven Rostedt
1542a57419b3SSteven Rostedt    if ($ret) {
1543a57419b3SSteven Rostedt	doprint "FAILED\n";
1544a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
1545a57419b3SSteven Rostedt    }
1546a57419b3SSteven Rostedt
1547a57419b3SSteven Rostedt    print "SUCCESS\n";
1548a57419b3SSteven Rostedt
1549a57419b3SSteven Rostedt    chomp $sha1;
1550a57419b3SSteven Rostedt
1551a57419b3SSteven Rostedt    return $sha1;
1552a57419b3SSteven Rostedt}
1553a57419b3SSteven Rostedt
15545a391fbfSSteven Rostedtsub monitor {
15552545eb61SSteven Rostedt    my $booted = 0;
15562545eb61SSteven Rostedt    my $bug = 0;
15576ca996ccSSteven Rostedt    my $bug_ignored = 0;
15585c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
15592b7d9b21SSteven Rostedt    my $loops;
15602545eb61SSteven Rostedt
15617faafbd6SSteven Rostedt    wait_for_monitor 5;
15622545eb61SSteven Rostedt
15632545eb61SSteven Rostedt    my $line;
15642545eb61SSteven Rostedt    my $full_line = "";
15652545eb61SSteven Rostedt
15667faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
15677faafbd6SSteven Rostedt	die "unable to write to $dmesg";
15682545eb61SSteven Rostedt
156975c3fda7SSteven Rostedt    reboot_to;
15702545eb61SSteven Rostedt
15711c8a617aSSteven Rostedt    my $success_start;
15721c8a617aSSteven Rostedt    my $failure_start;
15732d01b26aSSteven Rostedt    my $monitor_start = time;
15742d01b26aSSteven Rostedt    my $done = 0;
1575f1a5b962SSteven Rostedt    my $version_found = 0;
15761c8a617aSSteven Rostedt
15772d01b26aSSteven Rostedt    while (!$done) {
15782545eb61SSteven Rostedt
1579ecaf8e52SSteven Rostedt	if ($bug && defined($stop_after_failure) &&
1580ecaf8e52SSteven Rostedt	    $stop_after_failure >= 0) {
1581ecaf8e52SSteven Rostedt	    my $time = $stop_after_failure - (time - $failure_start);
1582ecaf8e52SSteven Rostedt	    $line = wait_for_input($monitor_fp, $time);
1583ecaf8e52SSteven Rostedt	    if (!defined($line)) {
1584ecaf8e52SSteven Rostedt		doprint "bug timed out after $booted_timeout seconds\n";
1585ecaf8e52SSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1586ecaf8e52SSteven Rostedt		last;
1587ecaf8e52SSteven Rostedt	    }
1588ecaf8e52SSteven Rostedt	} elsif ($booted) {
1589a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
1590cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1591cd4f1d53SSteven Rostedt		my $s = $booted_timeout == 1 ? "" : "s";
1592cd4f1d53SSteven Rostedt		doprint "Successful boot found: break after $booted_timeout second$s\n";
1593cd4f1d53SSteven Rostedt		last;
1594cd4f1d53SSteven Rostedt	    }
15952b7d9b21SSteven Rostedt	} else {
15967faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
1597cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1598cd4f1d53SSteven Rostedt		my $s = $timeout == 1 ? "" : "s";
1599cd4f1d53SSteven Rostedt		doprint "Timed out after $timeout second$s\n";
1600cd4f1d53SSteven Rostedt		last;
16012b7d9b21SSteven Rostedt	    }
1602cd4f1d53SSteven Rostedt	}
16032545eb61SSteven Rostedt
16042545eb61SSteven Rostedt	doprint $line;
16057faafbd6SSteven Rostedt	print DMESG $line;
16062545eb61SSteven Rostedt
16072545eb61SSteven Rostedt	# we are not guaranteed to get a full line
16082545eb61SSteven Rostedt	$full_line .= $line;
16092545eb61SSteven Rostedt
1610a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
16112545eb61SSteven Rostedt	    $booted = 1;
16121c8a617aSSteven Rostedt	    $success_start = time;
16131c8a617aSSteven Rostedt	}
16141c8a617aSSteven Rostedt
16151c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
16161c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
16171c8a617aSSteven Rostedt	    my $now = time;
16181c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
16191c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
16201c8a617aSSteven Rostedt		last;
16211c8a617aSSteven Rostedt	    }
16222545eb61SSteven Rostedt	}
16232545eb61SSteven Rostedt
16245c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
16255c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
16265c42fc5bSSteven Rostedt	}
16275c42fc5bSSteven Rostedt
16282545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
16296ca996ccSSteven Rostedt	    if (!$bug && !$skip_call_trace) {
16306ca996ccSSteven Rostedt		if ($ignore_errors) {
16316ca996ccSSteven Rostedt		    $bug_ignored = 1;
16326ca996ccSSteven Rostedt		} else {
16331c8a617aSSteven Rostedt		    $bug = 1;
16341c8a617aSSteven Rostedt		    $failure_start = time;
16351c8a617aSSteven Rostedt		}
16361c8a617aSSteven Rostedt	    }
16376ca996ccSSteven Rostedt	}
16381c8a617aSSteven Rostedt
16391c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
16401c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
16411c8a617aSSteven Rostedt	    my $now = time;
16421c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
16431c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
16441c8a617aSSteven Rostedt		last;
16451c8a617aSSteven Rostedt	    }
16465c42fc5bSSteven Rostedt	}
16475c42fc5bSSteven Rostedt
16485c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
16495c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
16505c42fc5bSSteven Rostedt	}
16515c42fc5bSSteven Rostedt
16525c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
165310abf118SSteven Rostedt	    $failure_start = time;
16542545eb61SSteven Rostedt	    $bug = 1;
16552545eb61SSteven Rostedt	}
16562545eb61SSteven Rostedt
1657f1a5b962SSteven Rostedt	# Detect triple faults by testing the banner
1658f1a5b962SSteven Rostedt	if ($full_line =~ /\bLinux version (\S+).*\n/) {
1659f1a5b962SSteven Rostedt	    if ($1 eq $version) {
1660f1a5b962SSteven Rostedt		$version_found = 1;
1661f1a5b962SSteven Rostedt	    } elsif ($version_found && $detect_triplefault) {
1662f1a5b962SSteven Rostedt		# We already booted into the kernel we are testing,
1663f1a5b962SSteven Rostedt		# but now we booted into another kernel?
1664f1a5b962SSteven Rostedt		# Consider this a triple fault.
1665f1a5b962SSteven Rostedt		doprint "Aleady booted in Linux kernel $version, but now\n";
1666f1a5b962SSteven Rostedt		doprint "we booted into Linux kernel $1.\n";
1667f1a5b962SSteven Rostedt		doprint "Assuming that this is a triple fault.\n";
1668f1a5b962SSteven Rostedt		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1669f1a5b962SSteven Rostedt		last;
1670f1a5b962SSteven Rostedt	    }
1671f1a5b962SSteven Rostedt	}
1672f1a5b962SSteven Rostedt
16732545eb61SSteven Rostedt	if ($line =~ /\n/) {
16742545eb61SSteven Rostedt	    $full_line = "";
16752545eb61SSteven Rostedt	}
16762d01b26aSSteven Rostedt
16772d01b26aSSteven Rostedt	if ($stop_test_after > 0 && !$booted && !$bug) {
16782d01b26aSSteven Rostedt	    if (time - $monitor_start > $stop_test_after) {
16794d62bf51SSteven Rostedt		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
16802d01b26aSSteven Rostedt		$done = 1;
16812d01b26aSSteven Rostedt	    }
16822d01b26aSSteven Rostedt	}
16832545eb61SSteven Rostedt    }
16842545eb61SSteven Rostedt
16857faafbd6SSteven Rostedt    close(DMESG);
16862545eb61SSteven Rostedt
16872545eb61SSteven Rostedt    if ($bug) {
16882b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
1689576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
16902545eb61SSteven Rostedt    }
16915f9b6cedSSteven Rostedt
1692a75fececSSteven Rostedt    if (!$booted) {
1693a75fececSSteven Rostedt	return 0 if ($in_bisect);
1694576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
1695a75fececSSteven Rostedt    }
1696a75fececSSteven Rostedt
16976ca996ccSSteven Rostedt    if ($bug_ignored) {
16986ca996ccSSteven Rostedt	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
16996ca996ccSSteven Rostedt    }
17006ca996ccSSteven Rostedt
17012b7d9b21SSteven Rostedt    return 1;
17022545eb61SSteven Rostedt}
17032545eb61SSteven Rostedt
17042b29b2f8SSteven Rostedtsub eval_kernel_version {
17052b29b2f8SSteven Rostedt    my ($option) = @_;
17062b29b2f8SSteven Rostedt
17072b29b2f8SSteven Rostedt    $option =~ s/\$KERNEL_VERSION/$version/g;
17082b29b2f8SSteven Rostedt
17092b29b2f8SSteven Rostedt    return $option;
17102b29b2f8SSteven Rostedt}
17112b29b2f8SSteven Rostedt
1712db05cfefSSteven Rostedtsub do_post_install {
1713db05cfefSSteven Rostedt
1714db05cfefSSteven Rostedt    return if (!defined($post_install));
1715db05cfefSSteven Rostedt
17162b29b2f8SSteven Rostedt    my $cp_post_install = eval_kernel_version $post_install;
1717db05cfefSSteven Rostedt    run_command "$cp_post_install" or
1718db05cfefSSteven Rostedt	dodie "Failed to run post install";
1719db05cfefSSteven Rostedt}
1720db05cfefSSteven Rostedt
17212545eb61SSteven Rostedtsub install {
17222545eb61SSteven Rostedt
1723e0a8742eSSteven Rostedt    return if ($no_install);
1724e0a8742eSSteven Rostedt
1725e5c2ec11SSteven Rostedt    if (defined($pre_install)) {
1726e5c2ec11SSteven Rostedt	my $cp_pre_install = eval_kernel_version $pre_install;
1727e5c2ec11SSteven Rostedt	run_command "$cp_pre_install" or
1728e5c2ec11SSteven Rostedt	    dodie "Failed to run pre install";
1729e5c2ec11SSteven Rostedt    }
1730e5c2ec11SSteven Rostedt
17312b29b2f8SSteven Rostedt    my $cp_target = eval_kernel_version $target_image;
17322b29b2f8SSteven Rostedt
173302ad2617SSteven Rostedt    run_scp_install "$outputdir/$build_target", "$cp_target" or
17345c42fc5bSSteven Rostedt	dodie "failed to copy image";
17355f9b6cedSSteven Rostedt
17365f9b6cedSSteven Rostedt    my $install_mods = 0;
17375f9b6cedSSteven Rostedt
17385f9b6cedSSteven Rostedt    # should we process modules?
17395f9b6cedSSteven Rostedt    $install_mods = 0;
174051ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
17415f9b6cedSSteven Rostedt    while (<IN>) {
17425f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
1743*8bc5e4eaSSteven Rostedt	    if (defined($1)) {
1744*8bc5e4eaSSteven Rostedt		$install_mods = 1;
17455f9b6cedSSteven Rostedt		last;
17465f9b6cedSSteven Rostedt	    }
17475f9b6cedSSteven Rostedt	}
1748*8bc5e4eaSSteven Rostedt    }
17495f9b6cedSSteven Rostedt    close(IN);
17505f9b6cedSSteven Rostedt
17515f9b6cedSSteven Rostedt    if (!$install_mods) {
1752db05cfefSSteven Rostedt	do_post_install;
17535f9b6cedSSteven Rostedt	doprint "No modules needed\n";
17545f9b6cedSSteven Rostedt	return;
17552545eb61SSteven Rostedt    }
17562545eb61SSteven Rostedt
1757627977d8SSteven Rostedt    run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or
17585f9b6cedSSteven Rostedt	dodie "Failed to install modules";
17595f9b6cedSSteven Rostedt
17602545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
1761a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
17622545eb61SSteven Rostedt
1763e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
17645c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
17652545eb61SSteven Rostedt
17665c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
1767a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
17685c42fc5bSSteven Rostedt	dodie "making tarball";
17695c42fc5bSSteven Rostedt
177002ad2617SSteven Rostedt    run_scp_mod "$tmpdir/$modtar", "/tmp" or
17715c42fc5bSSteven Rostedt	dodie "failed to copy modules";
17725c42fc5bSSteven Rostedt
1773a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
17745c42fc5bSSteven Rostedt
1775e7b13441SSteven Rostedt    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
17765c42fc5bSSteven Rostedt	dodie "failed to tar modules";
17775c42fc5bSSteven Rostedt
1778e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
17798b37ca8cSSteven Rostedt
1780db05cfefSSteven Rostedt    do_post_install;
17812545eb61SSteven Rostedt}
17822545eb61SSteven Rostedt
1783ddf607e5SSteven Rostedtsub get_version {
1784ddf607e5SSteven Rostedt    # get the release name
1785683a3e64SSteven Rostedt    return if ($have_version);
1786ddf607e5SSteven Rostedt    doprint "$make kernelrelease ... ";
1787ddf607e5SSteven Rostedt    $version = `$make kernelrelease | tail -1`;
1788ddf607e5SSteven Rostedt    chomp($version);
1789ddf607e5SSteven Rostedt    doprint "$version\n";
1790683a3e64SSteven Rostedt    $have_version = 1;
1791ddf607e5SSteven Rostedt}
1792ddf607e5SSteven Rostedt
1793ddf607e5SSteven Rostedtsub start_monitor_and_boot {
17949f7424ccSSteven Rostedt    # Make sure the stable kernel has finished booting
17959f7424ccSSteven Rostedt    start_monitor;
17969f7424ccSSteven Rostedt    wait_for_monitor 5;
17979f7424ccSSteven Rostedt    end_monitor;
17989f7424ccSSteven Rostedt
1799ddf607e5SSteven Rostedt    get_grub_index;
1800ddf607e5SSteven Rostedt    get_version;
1801ddf607e5SSteven Rostedt    install;
1802ddf607e5SSteven Rostedt
1803ddf607e5SSteven Rostedt    start_monitor;
1804ddf607e5SSteven Rostedt    return monitor;
1805ddf607e5SSteven Rostedt}
1806ddf607e5SSteven Rostedt
18076c5ee0beSSteven Rostedtsub check_buildlog {
18086c5ee0beSSteven Rostedt    my ($patch) = @_;
18096c5ee0beSSteven Rostedt
18106c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
18116c5ee0beSSteven Rostedt
18126c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
18136c5ee0beSSteven Rostedt	dodie "failed to show $patch";
18146c5ee0beSSteven Rostedt    while (<IN>) {
18156c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
18166c5ee0beSSteven Rostedt	    chomp $1;
18176c5ee0beSSteven Rostedt	    $files[$#files] = $1;
18186c5ee0beSSteven Rostedt	}
18196c5ee0beSSteven Rostedt    }
18206c5ee0beSSteven Rostedt    close(IN);
18216c5ee0beSSteven Rostedt
18226c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
18236c5ee0beSSteven Rostedt    while (<IN>) {
18246c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
18256c5ee0beSSteven Rostedt	    my $err = $1;
18266c5ee0beSSteven Rostedt	    foreach my $file (@files) {
1827a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
18286c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
18292b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
18306c5ee0beSSteven Rostedt		}
18316c5ee0beSSteven Rostedt	    }
18326c5ee0beSSteven Rostedt	}
18336c5ee0beSSteven Rostedt    }
18346c5ee0beSSteven Rostedt    close(IN);
18352b7d9b21SSteven Rostedt
18362b7d9b21SSteven Rostedt    return 1;
18376c5ee0beSSteven Rostedt}
18386c5ee0beSSteven Rostedt
1839fcb3f16aSSteven Rostedtsub apply_min_config {
1840fcb3f16aSSteven Rostedt    my $outconfig = "$output_config.new";
1841612b9e9bSSteven Rostedt
1842fcb3f16aSSteven Rostedt    # Read the config file and remove anything that
1843fcb3f16aSSteven Rostedt    # is in the force_config hash (from minconfig and others)
1844fcb3f16aSSteven Rostedt    # then add the force config back.
1845fcb3f16aSSteven Rostedt
1846fcb3f16aSSteven Rostedt    doprint "Applying minimum configurations into $output_config.new\n";
1847fcb3f16aSSteven Rostedt
1848fcb3f16aSSteven Rostedt    open (OUT, ">$outconfig") or
1849fcb3f16aSSteven Rostedt	dodie "Can't create $outconfig";
1850fcb3f16aSSteven Rostedt
1851fcb3f16aSSteven Rostedt    if (-f $output_config) {
1852fcb3f16aSSteven Rostedt	open (IN, $output_config) or
1853fcb3f16aSSteven Rostedt	    dodie "Failed to open $output_config";
1854fcb3f16aSSteven Rostedt	while (<IN>) {
1855fcb3f16aSSteven Rostedt	    if (/^(# )?(CONFIG_[^\s=]*)/) {
1856fcb3f16aSSteven Rostedt		next if (defined($force_config{$2}));
1857fcb3f16aSSteven Rostedt	    }
1858fcb3f16aSSteven Rostedt	    print OUT;
1859fcb3f16aSSteven Rostedt	}
1860fcb3f16aSSteven Rostedt	close IN;
1861fcb3f16aSSteven Rostedt    }
1862fcb3f16aSSteven Rostedt    foreach my $config (keys %force_config) {
1863fcb3f16aSSteven Rostedt	print OUT "$force_config{$config}\n";
1864fcb3f16aSSteven Rostedt    }
1865fcb3f16aSSteven Rostedt    close OUT;
1866fcb3f16aSSteven Rostedt
1867fcb3f16aSSteven Rostedt    run_command "mv $outconfig $output_config";
1868fcb3f16aSSteven Rostedt}
1869fcb3f16aSSteven Rostedt
1870fcb3f16aSSteven Rostedtsub make_oldconfig {
1871fcb3f16aSSteven Rostedt
18724c4ab120SSteven Rostedt    my @force_list = keys %force_config;
18734c4ab120SSteven Rostedt
18744c4ab120SSteven Rostedt    if ($#force_list >= 0) {
1875fcb3f16aSSteven Rostedt	apply_min_config;
18764c4ab120SSteven Rostedt    }
1877fcb3f16aSSteven Rostedt
1878fb16d891SAdam Lee    if (!run_command "$make olddefconfig") {
1879fb16d891SAdam Lee	# Perhaps olddefconfig doesn't exist in this version of the kernel
1880612b9e9bSSteven Rostedt	# try a yes '' | oldconfig
1881fb16d891SAdam Lee	doprint "olddefconfig failed, trying yes '' | make oldconfig\n";
1882fcb3f16aSSteven Rostedt	run_command "yes '' | $make oldconfig" or
1883612b9e9bSSteven Rostedt	    dodie "failed make config oldconfig";
1884612b9e9bSSteven Rostedt    }
1885612b9e9bSSteven Rostedt}
1886612b9e9bSSteven Rostedt
1887fcb3f16aSSteven Rostedt# read a config file and use this to force new configs.
1888fcb3f16aSSteven Rostedtsub load_force_config {
1889fcb3f16aSSteven Rostedt    my ($config) = @_;
1890fcb3f16aSSteven Rostedt
1891cf79fab6SSteven Rostedt    doprint "Loading force configs from $config\n";
1892fcb3f16aSSteven Rostedt    open(IN, $config) or
1893fcb3f16aSSteven Rostedt	dodie "failed to read $config";
1894fcb3f16aSSteven Rostedt    while (<IN>) {
1895fcb3f16aSSteven Rostedt	chomp;
1896fcb3f16aSSteven Rostedt	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1897fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1898fcb3f16aSSteven Rostedt	} elsif (/^# (CONFIG_\S*) is not set/) {
1899fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1900fcb3f16aSSteven Rostedt	}
1901fcb3f16aSSteven Rostedt    }
1902fcb3f16aSSteven Rostedt    close IN;
1903fcb3f16aSSteven Rostedt}
1904fcb3f16aSSteven Rostedt
19052545eb61SSteven Rostedtsub build {
19062545eb61SSteven Rostedt    my ($type) = @_;
19072545eb61SSteven Rostedt
19087faafbd6SSteven Rostedt    unlink $buildlog;
19097faafbd6SSteven Rostedt
19104ab1cce5SSteven Rostedt    # Failed builds should not reboot the target
19114ab1cce5SSteven Rostedt    my $save_no_reboot = $no_reboot;
19124ab1cce5SSteven Rostedt    $no_reboot = 1;
19134ab1cce5SSteven Rostedt
1914683a3e64SSteven Rostedt    # Calculate a new version from here.
1915683a3e64SSteven Rostedt    $have_version = 0;
1916683a3e64SSteven Rostedt
19170bd6c1a3SSteven Rostedt    if (defined($pre_build)) {
19180bd6c1a3SSteven Rostedt	my $ret = run_command $pre_build;
19190bd6c1a3SSteven Rostedt	if (!$ret && defined($pre_build_die) &&
19200bd6c1a3SSteven Rostedt	    $pre_build_die) {
19210bd6c1a3SSteven Rostedt	    dodie "failed to pre_build\n";
19220bd6c1a3SSteven Rostedt	}
19230bd6c1a3SSteven Rostedt    }
19240bd6c1a3SSteven Rostedt
192575c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
192651ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
192775c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
19285f9b6cedSSteven Rostedt
192975c3fda7SSteven Rostedt	$type = "oldconfig";
193075c3fda7SSteven Rostedt    }
193175c3fda7SSteven Rostedt
19325c42fc5bSSteven Rostedt    # old config can ask questions
19335c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
1934fb16d891SAdam Lee	$type = "olddefconfig";
193575c3fda7SSteven Rostedt
193675c3fda7SSteven Rostedt	# allow for empty configs
193751ad1dd1SSteven Rostedt	run_command "touch $output_config";
193875c3fda7SSteven Rostedt
193913488231SAndrew Jones	if (!$noclean) {
194051ad1dd1SSteven Rostedt	    run_command "mv $output_config $outputdir/config_temp" or
19415c42fc5bSSteven Rostedt		dodie "moving .config";
19425c42fc5bSSteven Rostedt
194313488231SAndrew Jones	    run_command "$make mrproper" or dodie "make mrproper";
19445c42fc5bSSteven Rostedt
194551ad1dd1SSteven Rostedt	    run_command "mv $outputdir/config_temp $output_config" or
19465c42fc5bSSteven Rostedt		dodie "moving config_temp";
194713488231SAndrew Jones	}
19485c42fc5bSSteven Rostedt
19495c42fc5bSSteven Rostedt    } elsif (!$noclean) {
195051ad1dd1SSteven Rostedt	unlink "$output_config";
19515f9b6cedSSteven Rostedt	run_command "$make mrproper" or
19525c42fc5bSSteven Rostedt	    dodie "make mrproper";
19535c42fc5bSSteven Rostedt    }
19542545eb61SSteven Rostedt
19552545eb61SSteven Rostedt    # add something to distinguish this build
1956a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
1957a75fececSSteven Rostedt    print OUT "$localversion\n";
19582545eb61SSteven Rostedt    close(OUT);
19592545eb61SSteven Rostedt
19605f9b6cedSSteven Rostedt    if (defined($minconfig)) {
1961fcb3f16aSSteven Rostedt	load_force_config($minconfig);
19622545eb61SSteven Rostedt    }
19632545eb61SSteven Rostedt
1964fb16d891SAdam Lee    if ($type ne "olddefconfig") {
1965fcb3f16aSSteven Rostedt	run_command "$make $type" or
19665c42fc5bSSteven Rostedt	    dodie "failed make config";
1967612b9e9bSSteven Rostedt    }
1968fcb3f16aSSteven Rostedt    # Run old config regardless, to enforce min configurations
1969fcb3f16aSSteven Rostedt    make_oldconfig;
19702545eb61SSteven Rostedt
1971a75fececSSteven Rostedt    $redirect = "$buildlog";
19720bd6c1a3SSteven Rostedt    my $build_ret = run_command "$make $build_options";
19736c5ee0beSSteven Rostedt    undef $redirect;
19740bd6c1a3SSteven Rostedt
19750bd6c1a3SSteven Rostedt    if (defined($post_build)) {
1976683a3e64SSteven Rostedt	# Because a post build may change the kernel version
1977683a3e64SSteven Rostedt	# do it now.
1978683a3e64SSteven Rostedt	get_version;
19790bd6c1a3SSteven Rostedt	my $ret = run_command $post_build;
19800bd6c1a3SSteven Rostedt	if (!$ret && defined($post_build_die) &&
19810bd6c1a3SSteven Rostedt	    $post_build_die) {
19820bd6c1a3SSteven Rostedt	    dodie "failed to post_build\n";
19830bd6c1a3SSteven Rostedt	}
19840bd6c1a3SSteven Rostedt    }
19850bd6c1a3SSteven Rostedt
19860bd6c1a3SSteven Rostedt    if (!$build_ret) {
19875f9b6cedSSteven Rostedt	# bisect may need this to pass
19884ab1cce5SSteven Rostedt	if ($in_bisect) {
19894ab1cce5SSteven Rostedt	    $no_reboot = $save_no_reboot;
19904ab1cce5SSteven Rostedt	    return 0;
19914ab1cce5SSteven Rostedt	}
19922b7d9b21SSteven Rostedt	fail "failed build" and return 0;
19932545eb61SSteven Rostedt    }
19945f9b6cedSSteven Rostedt
19954ab1cce5SSteven Rostedt    $no_reboot = $save_no_reboot;
19964ab1cce5SSteven Rostedt
19972b7d9b21SSteven Rostedt    return 1;
19982545eb61SSteven Rostedt}
19992545eb61SSteven Rostedt
200075c3fda7SSteven Rostedtsub halt {
2001e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
2002576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
2003576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
2004576f627cSSteven Rostedt	    run_command "$power_off";
2005576f627cSSteven Rostedt	}
2006576f627cSSteven Rostedt    } else {
200775c3fda7SSteven Rostedt	# nope? the zap it!
2008a75fececSSteven Rostedt	run_command "$power_off";
200975c3fda7SSteven Rostedt    }
201075c3fda7SSteven Rostedt}
201175c3fda7SSteven Rostedt
20125f9b6cedSSteven Rostedtsub success {
20135f9b6cedSSteven Rostedt    my ($i) = @_;
20145f9b6cedSSteven Rostedt
2015921ed4c7SSteven Rostedt    if (defined($post_test)) {
2016921ed4c7SSteven Rostedt	run_command $post_test;
2017921ed4c7SSteven Rostedt    }
2018921ed4c7SSteven Rostedt
2019e48c5293SSteven Rostedt    $successes++;
2020e48c5293SSteven Rostedt
20219064af52SSteven Rostedt    my $name = "";
20229064af52SSteven Rostedt
20239064af52SSteven Rostedt    if (defined($test_name)) {
20249064af52SSteven Rostedt	$name = " ($test_name)";
20259064af52SSteven Rostedt    }
20269064af52SSteven Rostedt
20275f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
20285f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
20299064af52SSteven Rostedt    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
20305f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
20315f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
20325f9b6cedSSteven Rostedt
2033de5b6e3bSRabin Vincent    if (defined($store_successes)) {
2034de5b6e3bSRabin Vincent        save_logs "success", $store_successes;
2035de5b6e3bSRabin Vincent    }
2036de5b6e3bSRabin Vincent
2037576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
2038a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
2039bc7c5803SSteven Rostedt	reboot_to_good $sleep_time;
20405f9b6cedSSteven Rostedt    }
20415f9b6cedSSteven Rostedt}
20425f9b6cedSSteven Rostedt
2043c960bb9fSSteven Rostedtsub answer_bisect {
2044c960bb9fSSteven Rostedt    for (;;) {
2045c960bb9fSSteven Rostedt	doprint "Pass or fail? [p/f]";
2046c960bb9fSSteven Rostedt	my $ans = <STDIN>;
2047c960bb9fSSteven Rostedt	chomp $ans;
2048c960bb9fSSteven Rostedt	if ($ans eq "p" || $ans eq "P") {
2049c960bb9fSSteven Rostedt	    return 1;
2050c960bb9fSSteven Rostedt	} elsif ($ans eq "f" || $ans eq "F") {
2051c960bb9fSSteven Rostedt	    return 0;
2052c960bb9fSSteven Rostedt	} else {
2053c960bb9fSSteven Rostedt	    print "Please answer 'P' or 'F'\n";
2054c960bb9fSSteven Rostedt	}
2055c960bb9fSSteven Rostedt    }
2056c960bb9fSSteven Rostedt}
2057c960bb9fSSteven Rostedt
20585a391fbfSSteven Rostedtsub child_run_test {
20597faafbd6SSteven Rostedt    my $failed = 0;
20605a391fbfSSteven Rostedt
20617faafbd6SSteven Rostedt    # child should have no power
2062a75fececSSteven Rostedt    $reboot_on_error = 0;
2063a75fececSSteven Rostedt    $poweroff_on_error = 0;
2064a75fececSSteven Rostedt    $die_on_failure = 1;
20657faafbd6SSteven Rostedt
2066a9dd5d63SRabin Vincent    $redirect = "$testlog";
20677faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
2068a9dd5d63SRabin Vincent    undef $redirect;
2069a9dd5d63SRabin Vincent
20705a391fbfSSteven Rostedt    exit $failed;
20715a391fbfSSteven Rostedt}
20725a391fbfSSteven Rostedt
20735a391fbfSSteven Rostedtmy $child_done;
20745a391fbfSSteven Rostedt
20755a391fbfSSteven Rostedtsub child_finished {
20765a391fbfSSteven Rostedt    $child_done = 1;
20775a391fbfSSteven Rostedt}
20785a391fbfSSteven Rostedt
20795a391fbfSSteven Rostedtsub do_run_test {
20805a391fbfSSteven Rostedt    my $child_pid;
20815a391fbfSSteven Rostedt    my $child_exit;
20825a391fbfSSteven Rostedt    my $line;
20835a391fbfSSteven Rostedt    my $full_line;
20845a391fbfSSteven Rostedt    my $bug = 0;
20859b1d367dSSteven Rostedt    my $bug_ignored = 0;
20865a391fbfSSteven Rostedt
20877faafbd6SSteven Rostedt    wait_for_monitor 1;
20885a391fbfSSteven Rostedt
20897faafbd6SSteven Rostedt    doprint "run test $run_test\n";
20905a391fbfSSteven Rostedt
20915a391fbfSSteven Rostedt    $child_done = 0;
20925a391fbfSSteven Rostedt
20935a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
20945a391fbfSSteven Rostedt
20955a391fbfSSteven Rostedt    $child_pid = fork;
20965a391fbfSSteven Rostedt
20975a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
20985a391fbfSSteven Rostedt
20995a391fbfSSteven Rostedt    $full_line = "";
21005a391fbfSSteven Rostedt
21015a391fbfSSteven Rostedt    do {
21027faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
21035a391fbfSSteven Rostedt	if (defined($line)) {
21045a391fbfSSteven Rostedt
21055a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
21065a391fbfSSteven Rostedt	    $full_line .= $line;
21078ea0e063SSteven Rostedt	    doprint $line;
21085a391fbfSSteven Rostedt
21095a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
21109b1d367dSSteven Rostedt		if ($ignore_errors) {
21119b1d367dSSteven Rostedt		    $bug_ignored = 1;
21129b1d367dSSteven Rostedt		} else {
21135a391fbfSSteven Rostedt		    $bug = 1;
21145a391fbfSSteven Rostedt		}
21159b1d367dSSteven Rostedt	    }
21165a391fbfSSteven Rostedt
21175a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
21185a391fbfSSteven Rostedt		$bug = 1;
21195a391fbfSSteven Rostedt	    }
21205a391fbfSSteven Rostedt
21215a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
21225a391fbfSSteven Rostedt		$full_line = "";
21235a391fbfSSteven Rostedt	    }
21245a391fbfSSteven Rostedt	}
21255a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
21265a391fbfSSteven Rostedt
21279b1d367dSSteven Rostedt    if (!$bug && $bug_ignored) {
21289b1d367dSSteven Rostedt	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
21299b1d367dSSteven Rostedt    }
21309b1d367dSSteven Rostedt
21315a391fbfSSteven Rostedt    if ($bug) {
21328ea0e063SSteven Rostedt	my $failure_start = time;
21338ea0e063SSteven Rostedt	my $now;
21348ea0e063SSteven Rostedt	do {
21358ea0e063SSteven Rostedt	    $line = wait_for_input($monitor_fp, 1);
21368ea0e063SSteven Rostedt	    if (defined($line)) {
21378ea0e063SSteven Rostedt		doprint $line;
21388ea0e063SSteven Rostedt	    }
21398ea0e063SSteven Rostedt	    $now = time;
21408ea0e063SSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
21418ea0e063SSteven Rostedt		last;
21428ea0e063SSteven Rostedt	    }
21438ea0e063SSteven Rostedt	} while (defined($line));
21448ea0e063SSteven Rostedt
21455a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
21465a391fbfSSteven Rostedt	# kill the child with extreme prejudice
21475a391fbfSSteven Rostedt	kill 9, $child_pid;
21485a391fbfSSteven Rostedt    }
21495a391fbfSSteven Rostedt
21505a391fbfSSteven Rostedt    waitpid $child_pid, 0;
21515a391fbfSSteven Rostedt    $child_exit = $?;
21525a391fbfSSteven Rostedt
2153c5dacb88SSteven Rostedt    if (!$bug && $in_bisect) {
2154c5dacb88SSteven Rostedt	if (defined($bisect_ret_good)) {
2155c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_good) {
2156c5dacb88SSteven Rostedt		return 1;
2157c5dacb88SSteven Rostedt	    }
2158c5dacb88SSteven Rostedt	}
2159c5dacb88SSteven Rostedt	if (defined($bisect_ret_skip)) {
2160c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_skip) {
2161c5dacb88SSteven Rostedt		return -1;
2162c5dacb88SSteven Rostedt	    }
2163c5dacb88SSteven Rostedt	}
2164c5dacb88SSteven Rostedt	if (defined($bisect_ret_abort)) {
2165c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_abort) {
2166c5dacb88SSteven Rostedt		fail "test abort" and return -2;
2167c5dacb88SSteven Rostedt	    }
2168c5dacb88SSteven Rostedt	}
2169c5dacb88SSteven Rostedt	if (defined($bisect_ret_bad)) {
2170c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_skip) {
2171c5dacb88SSteven Rostedt		return 0;
2172c5dacb88SSteven Rostedt	    }
2173c5dacb88SSteven Rostedt	}
2174c5dacb88SSteven Rostedt	if (defined($bisect_ret_default)) {
2175c5dacb88SSteven Rostedt	    if ($bisect_ret_default eq "good") {
2176c5dacb88SSteven Rostedt		return 1;
2177c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "bad") {
2178c5dacb88SSteven Rostedt		return 0;
2179c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "skip") {
2180c5dacb88SSteven Rostedt		return -1;
2181c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "abort") {
2182c5dacb88SSteven Rostedt		return -2;
2183c5dacb88SSteven Rostedt	    } else {
2184c5dacb88SSteven Rostedt		fail "unknown default action: $bisect_ret_default"
2185c5dacb88SSteven Rostedt		    and return -2;
2186c5dacb88SSteven Rostedt	    }
2187c5dacb88SSteven Rostedt	}
2188c5dacb88SSteven Rostedt    }
2189c5dacb88SSteven Rostedt
21905a391fbfSSteven Rostedt    if ($bug || $child_exit) {
21912b7d9b21SSteven Rostedt	return 0 if $in_bisect;
21922b7d9b21SSteven Rostedt	fail "test failed" and return 0;
21935a391fbfSSteven Rostedt    }
21942b7d9b21SSteven Rostedt    return 1;
21955a391fbfSSteven Rostedt}
21965a391fbfSSteven Rostedt
2197a75fececSSteven Rostedtsub run_git_bisect {
2198a75fececSSteven Rostedt    my ($command) = @_;
2199a75fececSSteven Rostedt
2200a75fececSSteven Rostedt    doprint "$command ... ";
2201a75fececSSteven Rostedt
2202a75fececSSteven Rostedt    my $output = `$command 2>&1`;
2203a75fececSSteven Rostedt    my $ret = $?;
2204a75fececSSteven Rostedt
2205a75fececSSteven Rostedt    logit $output;
2206a75fececSSteven Rostedt
2207a75fececSSteven Rostedt    if ($ret) {
2208a75fececSSteven Rostedt	doprint "FAILED\n";
2209a75fececSSteven Rostedt	dodie "Failed to git bisect";
2210a75fececSSteven Rostedt    }
2211a75fececSSteven Rostedt
2212a75fececSSteven Rostedt    doprint "SUCCESS\n";
2213a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
2214a75fececSSteven Rostedt	doprint "$1 [$2]\n";
2215a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
2216b5f4aea6SSteven Rostedt	$bisect_bad_commit = $1;
2217a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
2218a75fececSSteven Rostedt	return 0;
2219a75fececSSteven Rostedt    } else {
2220a75fececSSteven Rostedt	# we already logged it, just print it now.
2221a75fececSSteven Rostedt	print $output;
2222a75fececSSteven Rostedt    }
2223a75fececSSteven Rostedt
2224a75fececSSteven Rostedt    return 1;
2225a75fececSSteven Rostedt}
2226a75fececSSteven Rostedt
2227c23dca7cSSteven Rostedtsub bisect_reboot {
2228c23dca7cSSteven Rostedt    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
2229bc7c5803SSteven Rostedt    reboot_to_good $bisect_sleep_time;
2230c23dca7cSSteven Rostedt}
2231c23dca7cSSteven Rostedt
2232c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip
22330a05c769SSteven Rostedtsub run_bisect_test {
22340a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
22355f9b6cedSSteven Rostedt
22362b7d9b21SSteven Rostedt    my $failed = 0;
22375f9b6cedSSteven Rostedt    my $result;
22385f9b6cedSSteven Rostedt    my $output;
22395f9b6cedSSteven Rostedt    my $ret;
22405f9b6cedSSteven Rostedt
22410a05c769SSteven Rostedt    $in_bisect = 1;
22420a05c769SSteven Rostedt
22430a05c769SSteven Rostedt    build $buildtype or $failed = 1;
22445f9b6cedSSteven Rostedt
22455f9b6cedSSteven Rostedt    if ($type ne "build") {
2246c23dca7cSSteven Rostedt	if ($failed && $bisect_skip) {
2247c23dca7cSSteven Rostedt	    $in_bisect = 0;
2248c23dca7cSSteven Rostedt	    return -1;
2249c23dca7cSSteven Rostedt	}
22507faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
22515f9b6cedSSteven Rostedt
22525f9b6cedSSteven Rostedt	# Now boot the box
2253ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
22545f9b6cedSSteven Rostedt
22555f9b6cedSSteven Rostedt	if ($type ne "boot") {
2256c23dca7cSSteven Rostedt	    if ($failed && $bisect_skip) {
2257c23dca7cSSteven Rostedt		end_monitor;
2258c23dca7cSSteven Rostedt		bisect_reboot;
2259c23dca7cSSteven Rostedt		$in_bisect = 0;
2260c23dca7cSSteven Rostedt		return -1;
2261c23dca7cSSteven Rostedt	    }
22627faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
22635a391fbfSSteven Rostedt
22642b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
22655f9b6cedSSteven Rostedt	}
22667faafbd6SSteven Rostedt	end_monitor;
22675f9b6cedSSteven Rostedt    }
22685f9b6cedSSteven Rostedt
22695f9b6cedSSteven Rostedt    if ($failed) {
22700a05c769SSteven Rostedt	$result = 0;
22715f9b6cedSSteven Rostedt    } else {
22720a05c769SSteven Rostedt	$result = 1;
22735f9b6cedSSteven Rostedt    }
22744025bc62SSteven Rostedt
22754025bc62SSteven Rostedt    # reboot the box to a kernel we can ssh to
22764025bc62SSteven Rostedt    if ($type ne "build") {
22774025bc62SSteven Rostedt	bisect_reboot;
22784025bc62SSteven Rostedt    }
22790a05c769SSteven Rostedt    $in_bisect = 0;
22800a05c769SSteven Rostedt
22810a05c769SSteven Rostedt    return $result;
22820a05c769SSteven Rostedt}
22830a05c769SSteven Rostedt
22840a05c769SSteven Rostedtsub run_bisect {
22850a05c769SSteven Rostedt    my ($type) = @_;
22860a05c769SSteven Rostedt    my $buildtype = "oldconfig";
22870a05c769SSteven Rostedt
22880a05c769SSteven Rostedt    # We should have a minconfig to use?
22890a05c769SSteven Rostedt    if (defined($minconfig)) {
22900a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
22910a05c769SSteven Rostedt    }
22920a05c769SSteven Rostedt
22930a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
22940a05c769SSteven Rostedt
2295c960bb9fSSteven Rostedt    if ($bisect_manual) {
2296c960bb9fSSteven Rostedt	$ret = answer_bisect;
2297c960bb9fSSteven Rostedt    }
22985f9b6cedSSteven Rostedt
2299d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
23005158ba3eSRuss Dill    if ($reverse_bisect && $ret >= 0) {
23010a05c769SSteven Rostedt	$ret = !$ret;
2302d6ce2a0bSSteven Rostedt    }
2303d6ce2a0bSSteven Rostedt
2304c23dca7cSSteven Rostedt    if ($ret > 0) {
23050a05c769SSteven Rostedt	return "good";
2306c23dca7cSSteven Rostedt    } elsif ($ret == 0) {
23070a05c769SSteven Rostedt	return  "bad";
2308c23dca7cSSteven Rostedt    } elsif ($bisect_skip) {
2309c23dca7cSSteven Rostedt	doprint "HIT A BAD COMMIT ... SKIPPING\n";
2310c23dca7cSSteven Rostedt	return "skip";
23110a05c769SSteven Rostedt    }
23125f9b6cedSSteven Rostedt}
23135f9b6cedSSteven Rostedt
2314dad98754SSteven Rostedtsub update_bisect_replay {
2315dad98754SSteven Rostedt    my $tmp_log = "$tmpdir/ktest_bisect_log";
2316dad98754SSteven Rostedt    run_command "git bisect log > $tmp_log" or
2317dad98754SSteven Rostedt	die "can't create bisect log";
2318dad98754SSteven Rostedt    return $tmp_log;
2319dad98754SSteven Rostedt}
2320dad98754SSteven Rostedt
23215f9b6cedSSteven Rostedtsub bisect {
23225f9b6cedSSteven Rostedt    my ($i) = @_;
23235f9b6cedSSteven Rostedt
23245f9b6cedSSteven Rostedt    my $result;
23255f9b6cedSSteven Rostedt
2326b5f4aea6SSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($bisect_good));
2327b5f4aea6SSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($bisect_bad));
2328b5f4aea6SSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($bisect_type));
23295f9b6cedSSteven Rostedt
2330b5f4aea6SSteven Rostedt    my $good = $bisect_good;
2331b5f4aea6SSteven Rostedt    my $bad = $bisect_bad;
2332b5f4aea6SSteven Rostedt    my $type = $bisect_type;
2333b5f4aea6SSteven Rostedt    my $start = $bisect_start;
2334b5f4aea6SSteven Rostedt    my $replay = $bisect_replay;
2335b5f4aea6SSteven Rostedt    my $start_files = $bisect_files;
23363410f6fdSSteven Rostedt
23373410f6fdSSteven Rostedt    if (defined($start_files)) {
23383410f6fdSSteven Rostedt	$start_files = " -- " . $start_files;
23393410f6fdSSteven Rostedt    } else {
23403410f6fdSSteven Rostedt	$start_files = "";
23413410f6fdSSteven Rostedt    }
23425f9b6cedSSteven Rostedt
2343a57419b3SSteven Rostedt    # convert to true sha1's
2344a57419b3SSteven Rostedt    $good = get_sha1($good);
2345a57419b3SSteven Rostedt    $bad = get_sha1($bad);
2346a57419b3SSteven Rostedt
2347b5f4aea6SSteven Rostedt    if (defined($bisect_reverse) && $bisect_reverse == 1) {
2348d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
2349d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
2350d6ce2a0bSSteven Rostedt    } else {
2351d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
2352d6ce2a0bSSteven Rostedt    }
2353d6ce2a0bSSteven Rostedt
23545a391fbfSSteven Rostedt    # Can't have a test without having a test to run
23555a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
23565a391fbfSSteven Rostedt	$type = "boot";
23575a391fbfSSteven Rostedt    }
23585a391fbfSSteven Rostedt
2359dad98754SSteven Rostedt    # Check if a bisect was running
2360dad98754SSteven Rostedt    my $bisect_start_file = "$builddir/.git/BISECT_START";
2361dad98754SSteven Rostedt
2362b5f4aea6SSteven Rostedt    my $check = $bisect_check;
2363dad98754SSteven Rostedt    my $do_check = defined($check) && $check ne "0";
2364dad98754SSteven Rostedt
2365dad98754SSteven Rostedt    if ( -f $bisect_start_file ) {
2366dad98754SSteven Rostedt	print "Bisect in progress found\n";
2367dad98754SSteven Rostedt	if ($do_check) {
2368dad98754SSteven Rostedt	    print " If you say yes, then no checks of good or bad will be done\n";
2369dad98754SSteven Rostedt	}
2370dad98754SSteven Rostedt	if (defined($replay)) {
2371dad98754SSteven Rostedt	    print "** BISECT_REPLAY is defined in config file **";
2372dad98754SSteven Rostedt	    print " Ignore config option and perform new git bisect log?\n";
2373dad98754SSteven Rostedt	    if (read_ync " (yes, no, or cancel) ") {
2374dad98754SSteven Rostedt		$replay = update_bisect_replay;
2375dad98754SSteven Rostedt		$do_check = 0;
2376dad98754SSteven Rostedt	    }
2377dad98754SSteven Rostedt	} elsif (read_yn "read git log and continue?") {
2378dad98754SSteven Rostedt	    $replay = update_bisect_replay;
2379dad98754SSteven Rostedt	    $do_check = 0;
2380dad98754SSteven Rostedt	}
2381dad98754SSteven Rostedt    }
2382dad98754SSteven Rostedt
2383dad98754SSteven Rostedt    if ($do_check) {
2384a75fececSSteven Rostedt
2385a75fececSSteven Rostedt	# get current HEAD
2386a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
2387a75fececSSteven Rostedt
2388a75fececSSteven Rostedt	if ($check ne "good") {
2389a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
2390a75fececSSteven Rostedt	    run_command "git checkout $bad" or
2391a75fececSSteven Rostedt		die "Failed to checkout $bad";
2392a75fececSSteven Rostedt
2393a75fececSSteven Rostedt	    $result = run_bisect $type;
2394a75fececSSteven Rostedt
2395a75fececSSteven Rostedt	    if ($result ne "bad") {
2396a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
2397a75fececSSteven Rostedt	    }
2398a75fececSSteven Rostedt	}
2399a75fececSSteven Rostedt
2400a75fececSSteven Rostedt	if ($check ne "bad") {
2401a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
2402a75fececSSteven Rostedt	    run_command "git checkout $good" or
2403a75fececSSteven Rostedt		die "Failed to checkout $good";
2404a75fececSSteven Rostedt
2405a75fececSSteven Rostedt	    $result = run_bisect $type;
2406a75fececSSteven Rostedt
2407a75fececSSteven Rostedt	    if ($result ne "good") {
2408a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
2409a75fececSSteven Rostedt	    }
2410a75fececSSteven Rostedt	}
2411a75fececSSteven Rostedt
2412a75fececSSteven Rostedt	# checkout where we started
2413a75fececSSteven Rostedt	run_command "git checkout $head" or
2414a75fececSSteven Rostedt	    die "Failed to checkout $head";
2415a75fececSSteven Rostedt    }
2416a75fececSSteven Rostedt
24173410f6fdSSteven Rostedt    run_command "git bisect start$start_files" or
2418a75fececSSteven Rostedt	dodie "could not start bisect";
2419a75fececSSteven Rostedt
2420a75fececSSteven Rostedt    run_command "git bisect good $good" or
2421a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
2422a75fececSSteven Rostedt
2423a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
2424a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
2425a75fececSSteven Rostedt
2426a75fececSSteven Rostedt    if (defined($replay)) {
2427a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
2428a75fececSSteven Rostedt	    dodie "failed to run replay";
2429a75fececSSteven Rostedt    }
2430a75fececSSteven Rostedt
2431a75fececSSteven Rostedt    if (defined($start)) {
2432a75fececSSteven Rostedt	run_command "git checkout $start" or
2433a75fececSSteven Rostedt	    dodie "failed to checkout $start";
2434a75fececSSteven Rostedt    }
2435a75fececSSteven Rostedt
2436a75fececSSteven Rostedt    my $test;
24375f9b6cedSSteven Rostedt    do {
24385f9b6cedSSteven Rostedt	$result = run_bisect $type;
2439a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
2440a75fececSSteven Rostedt    } while ($test);
24415f9b6cedSSteven Rostedt
24425f9b6cedSSteven Rostedt    run_command "git bisect log" or
24435f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
24445f9b6cedSSteven Rostedt
24455f9b6cedSSteven Rostedt    run_command "git bisect reset" or
24465f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
24475f9b6cedSSteven Rostedt
2448b5f4aea6SSteven Rostedt    doprint "Bad commit was [$bisect_bad_commit]\n";
24495f9b6cedSSteven Rostedt
24500a05c769SSteven Rostedt    success $i;
24510a05c769SSteven Rostedt}
24520a05c769SSteven Rostedt
2453cf79fab6SSteven Rostedt# config_ignore holds the configs that were set (or unset) for
2454cf79fab6SSteven Rostedt# a good config and we will ignore these configs for the rest
2455cf79fab6SSteven Rostedt# of a config bisect. These configs stay as they were.
24560a05c769SSteven Rostedtmy %config_ignore;
2457cf79fab6SSteven Rostedt
2458cf79fab6SSteven Rostedt# config_set holds what all configs were set as.
24590a05c769SSteven Rostedtmy %config_set;
24600a05c769SSteven Rostedt
2461cf79fab6SSteven Rostedt# config_off holds the set of configs that the bad config had disabled.
2462cf79fab6SSteven Rostedt# We need to record them and set them in the .config when running
2463fb16d891SAdam Lee# olddefconfig, because olddefconfig keeps the defaults.
2464cf79fab6SSteven Rostedtmy %config_off;
2465cf79fab6SSteven Rostedt
2466cf79fab6SSteven Rostedt# config_off_tmp holds a set of configs to turn off for now
2467cf79fab6SSteven Rostedtmy @config_off_tmp;
2468cf79fab6SSteven Rostedt
2469cf79fab6SSteven Rostedt# config_list is the set of configs that are being tested
24700a05c769SSteven Rostedtmy %config_list;
24710a05c769SSteven Rostedtmy %null_config;
24720a05c769SSteven Rostedt
24730a05c769SSteven Rostedtmy %dependency;
24740a05c769SSteven Rostedt
24754c4ab120SSteven Rostedtsub assign_configs {
24764c4ab120SSteven Rostedt    my ($hash, $config) = @_;
24770a05c769SSteven Rostedt
24780a05c769SSteven Rostedt    open (IN, $config)
24790a05c769SSteven Rostedt	or dodie "Failed to read $config";
24800a05c769SSteven Rostedt
24810a05c769SSteven Rostedt    while (<IN>) {
24829bf71749SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
24834c4ab120SSteven Rostedt	    ${$hash}{$2} = $1;
24840a05c769SSteven Rostedt	}
24850a05c769SSteven Rostedt    }
24860a05c769SSteven Rostedt
24870a05c769SSteven Rostedt    close(IN);
24880a05c769SSteven Rostedt}
24890a05c769SSteven Rostedt
24904c4ab120SSteven Rostedtsub process_config_ignore {
24914c4ab120SSteven Rostedt    my ($config) = @_;
24924c4ab120SSteven Rostedt
24934c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
24944c4ab120SSteven Rostedt}
24954c4ab120SSteven Rostedt
24960a05c769SSteven Rostedtsub read_current_config {
24970a05c769SSteven Rostedt    my ($config_ref) = @_;
24980a05c769SSteven Rostedt
24990a05c769SSteven Rostedt    %{$config_ref} = ();
25000a05c769SSteven Rostedt    undef %{$config_ref};
25010a05c769SSteven Rostedt
25020a05c769SSteven Rostedt    my @key = keys %{$config_ref};
25030a05c769SSteven Rostedt    if ($#key >= 0) {
25040a05c769SSteven Rostedt	print "did not delete!\n";
25050a05c769SSteven Rostedt	exit;
25060a05c769SSteven Rostedt    }
25070a05c769SSteven Rostedt    open (IN, "$output_config");
25080a05c769SSteven Rostedt
25090a05c769SSteven Rostedt    while (<IN>) {
25100a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
25110a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
25120a05c769SSteven Rostedt	}
25130a05c769SSteven Rostedt    }
25140a05c769SSteven Rostedt    close(IN);
25150a05c769SSteven Rostedt}
25160a05c769SSteven Rostedt
25170a05c769SSteven Rostedtsub get_dependencies {
25180a05c769SSteven Rostedt    my ($config) = @_;
25190a05c769SSteven Rostedt
25200a05c769SSteven Rostedt    my $arr = $dependency{$config};
25210a05c769SSteven Rostedt    if (!defined($arr)) {
25220a05c769SSteven Rostedt	return ();
25230a05c769SSteven Rostedt    }
25240a05c769SSteven Rostedt
25250a05c769SSteven Rostedt    my @deps = @{$arr};
25260a05c769SSteven Rostedt
25270a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
25280a05c769SSteven Rostedt	print "ADD DEP $dep\n";
25290a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
25300a05c769SSteven Rostedt    }
25310a05c769SSteven Rostedt
25320a05c769SSteven Rostedt    return @deps;
25330a05c769SSteven Rostedt}
25340a05c769SSteven Rostedt
25350a05c769SSteven Rostedtsub create_config {
25360a05c769SSteven Rostedt    my @configs = @_;
25370a05c769SSteven Rostedt
25380a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
25390a05c769SSteven Rostedt
25400a05c769SSteven Rostedt    foreach my $config (@configs) {
25410a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
25420a05c769SSteven Rostedt	my @deps = get_dependencies $config;
25430a05c769SSteven Rostedt	foreach my $dep (@deps) {
25440a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
25450a05c769SSteven Rostedt	}
25460a05c769SSteven Rostedt    }
25470a05c769SSteven Rostedt
2548cf79fab6SSteven Rostedt    # turn off configs to keep off
2549cf79fab6SSteven Rostedt    foreach my $config (keys %config_off) {
2550cf79fab6SSteven Rostedt	print OUT "# $config is not set\n";
2551cf79fab6SSteven Rostedt    }
2552cf79fab6SSteven Rostedt
2553cf79fab6SSteven Rostedt    # turn off configs that should be off for now
2554cf79fab6SSteven Rostedt    foreach my $config (@config_off_tmp) {
2555cf79fab6SSteven Rostedt	print OUT "# $config is not set\n";
2556cf79fab6SSteven Rostedt    }
2557cf79fab6SSteven Rostedt
25580a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
25590a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
25600a05c769SSteven Rostedt    }
25610a05c769SSteven Rostedt    close(OUT);
25620a05c769SSteven Rostedt
2563fcb3f16aSSteven Rostedt    make_oldconfig;
25640a05c769SSteven Rostedt}
25650a05c769SSteven Rostedt
25660a05c769SSteven Rostedtsub compare_configs {
25670a05c769SSteven Rostedt    my (%a, %b) = @_;
25680a05c769SSteven Rostedt
25690a05c769SSteven Rostedt    foreach my $item (keys %a) {
25700a05c769SSteven Rostedt	if (!defined($b{$item})) {
25710a05c769SSteven Rostedt	    print "diff $item\n";
25720a05c769SSteven Rostedt	    return 1;
25730a05c769SSteven Rostedt	}
25740a05c769SSteven Rostedt	delete $b{$item};
25750a05c769SSteven Rostedt    }
25760a05c769SSteven Rostedt
25770a05c769SSteven Rostedt    my @keys = keys %b;
25780a05c769SSteven Rostedt    if ($#keys) {
25790a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
25800a05c769SSteven Rostedt    }
25810a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
25820a05c769SSteven Rostedt
25830a05c769SSteven Rostedt    return 0;
25840a05c769SSteven Rostedt}
25850a05c769SSteven Rostedt
25860a05c769SSteven Rostedtsub run_config_bisect_test {
25870a05c769SSteven Rostedt    my ($type) = @_;
25880a05c769SSteven Rostedt
25890a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
25900a05c769SSteven Rostedt}
25910a05c769SSteven Rostedt
25920a05c769SSteven Rostedtsub process_passed {
25930a05c769SSteven Rostedt    my (%configs) = @_;
25940a05c769SSteven Rostedt
25950a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
25960a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
25970a05c769SSteven Rostedt    # Add them to the min options.
25980a05c769SSteven Rostedt    foreach my $config (keys %configs) {
25990a05c769SSteven Rostedt	if (defined($config_list{$config})) {
26000a05c769SSteven Rostedt	    doprint " removing $config\n";
26010a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
26020a05c769SSteven Rostedt	    delete $config_list{$config};
26030a05c769SSteven Rostedt	}
26040a05c769SSteven Rostedt    }
2605f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
2606f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
26070a05c769SSteven Rostedt}
26080a05c769SSteven Rostedt
26090a05c769SSteven Rostedtsub process_failed {
26100a05c769SSteven Rostedt    my ($config) = @_;
26110a05c769SSteven Rostedt
26120a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
26130a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
26140a05c769SSteven Rostedt    doprint "***************************************\n\n";
26150a05c769SSteven Rostedt}
26160a05c769SSteven Rostedt
26170a05c769SSteven Rostedtsub run_config_bisect {
26180a05c769SSteven Rostedt
26190a05c769SSteven Rostedt    my @start_list = keys %config_list;
26200a05c769SSteven Rostedt
26210a05c769SSteven Rostedt    if ($#start_list < 0) {
26220a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
26230a05c769SSteven Rostedt	return -1;
26240a05c769SSteven Rostedt    }
26250a05c769SSteven Rostedt
26260a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
2627b5f4aea6SSteven Rostedt    my $type = $config_bisect_type;
26280a05c769SSteven Rostedt    my $ret;
26290a05c769SSteven Rostedt    my %current_config;
26300a05c769SSteven Rostedt
26310a05c769SSteven Rostedt    my $count = $#start_list + 1;
26320a05c769SSteven Rostedt    doprint "  $count configs to test\n";
26330a05c769SSteven Rostedt
26340a05c769SSteven Rostedt    my $half = int($#start_list / 2);
26350a05c769SSteven Rostedt
26360a05c769SSteven Rostedt    do {
26370a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
26380a05c769SSteven Rostedt
2639cf79fab6SSteven Rostedt	# keep the bottom half off
2640cf79fab6SSteven Rostedt	if ($half < $#start_list) {
2641cf79fab6SSteven Rostedt	    @config_off_tmp = @start_list[$half + 1 .. $#start_list];
2642cf79fab6SSteven Rostedt	} else {
2643cf79fab6SSteven Rostedt	    @config_off_tmp = ();
2644cf79fab6SSteven Rostedt	}
2645cf79fab6SSteven Rostedt
26460a05c769SSteven Rostedt	create_config @tophalf;
26470a05c769SSteven Rostedt	read_current_config \%current_config;
26480a05c769SSteven Rostedt
26490a05c769SSteven Rostedt	$count = $#tophalf + 1;
26500a05c769SSteven Rostedt	doprint "Testing $count configs\n";
26510a05c769SSteven Rostedt	my $found = 0;
26520a05c769SSteven Rostedt	# make sure we test something
26530a05c769SSteven Rostedt	foreach my $config (@tophalf) {
26540a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
26550a05c769SSteven Rostedt		logit " $config\n";
26560a05c769SSteven Rostedt		$found = 1;
26570a05c769SSteven Rostedt	    }
26580a05c769SSteven Rostedt	}
26590a05c769SSteven Rostedt	if (!$found) {
26600a05c769SSteven Rostedt	    # try the other half
26610a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
2662cf79fab6SSteven Rostedt
2663cf79fab6SSteven Rostedt	    # keep the top half off
2664cf79fab6SSteven Rostedt	    @config_off_tmp = @tophalf;
26654c8cc55bSSteven Rostedt	    @tophalf = @start_list[$half + 1 .. $#start_list];
2666cf79fab6SSteven Rostedt
26670a05c769SSteven Rostedt	    create_config @tophalf;
26680a05c769SSteven Rostedt	    read_current_config \%current_config;
26690a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
26700a05c769SSteven Rostedt		if (defined($current_config{$config})) {
26710a05c769SSteven Rostedt		    logit " $config\n";
26720a05c769SSteven Rostedt		    $found = 1;
26730a05c769SSteven Rostedt		}
26740a05c769SSteven Rostedt	    }
26750a05c769SSteven Rostedt	    if (!$found) {
26760a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
26770a05c769SSteven Rostedt		foreach my $config (@start_list) {
26780a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
26790a05c769SSteven Rostedt		}
26800a05c769SSteven Rostedt		return -1;
26810a05c769SSteven Rostedt	    }
26820a05c769SSteven Rostedt	    $count = $#tophalf + 1;
26830a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
26840a05c769SSteven Rostedt	}
26850a05c769SSteven Rostedt
26860a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
2687c960bb9fSSteven Rostedt	if ($bisect_manual) {
2688c960bb9fSSteven Rostedt	    $ret = answer_bisect;
2689c960bb9fSSteven Rostedt	}
26900a05c769SSteven Rostedt	if ($ret) {
26910a05c769SSteven Rostedt	    process_passed %current_config;
26920a05c769SSteven Rostedt	    return 0;
26930a05c769SSteven Rostedt	}
26940a05c769SSteven Rostedt
26950a05c769SSteven Rostedt	doprint "This config had a failure.\n";
26960a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
2697f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
2698f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
26990a05c769SSteven Rostedt
27000a05c769SSteven Rostedt	# A config exists in this group that was bad.
27010a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
27020a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
27030a05c769SSteven Rostedt		doprint " removing $config\n";
27040a05c769SSteven Rostedt		delete $config_list{$config};
27050a05c769SSteven Rostedt	    }
27060a05c769SSteven Rostedt	}
27070a05c769SSteven Rostedt
27080a05c769SSteven Rostedt	@start_list = @tophalf;
27090a05c769SSteven Rostedt
27100a05c769SSteven Rostedt	if ($#start_list == 0) {
27110a05c769SSteven Rostedt	    process_failed $start_list[0];
27120a05c769SSteven Rostedt	    return 1;
27130a05c769SSteven Rostedt	}
27140a05c769SSteven Rostedt
27150a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
27160a05c769SSteven Rostedt	# they are good.
27170a05c769SSteven Rostedt	$half = int($#start_list / 2);
27184c8cc55bSSteven Rostedt    } while ($#start_list > 0);
27190a05c769SSteven Rostedt
2720c960bb9fSSteven Rostedt    # we found a single config, try it again unless we are running manually
2721c960bb9fSSteven Rostedt
2722c960bb9fSSteven Rostedt    if ($bisect_manual) {
2723c960bb9fSSteven Rostedt	process_failed $start_list[0];
2724c960bb9fSSteven Rostedt	return 1;
2725c960bb9fSSteven Rostedt    }
2726c960bb9fSSteven Rostedt
27270a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
27280a05c769SSteven Rostedt
27290a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
27300a05c769SSteven Rostedt    if ($ret) {
27310a05c769SSteven Rostedt	process_passed %current_config;
27320a05c769SSteven Rostedt	return 0;
27330a05c769SSteven Rostedt    }
27340a05c769SSteven Rostedt
27350a05c769SSteven Rostedt    process_failed $start_list[0];
27360a05c769SSteven Rostedt    return 1;
27370a05c769SSteven Rostedt}
27380a05c769SSteven Rostedt
27390a05c769SSteven Rostedtsub config_bisect {
27400a05c769SSteven Rostedt    my ($i) = @_;
27410a05c769SSteven Rostedt
2742b5f4aea6SSteven Rostedt    my $start_config = $config_bisect;
27430a05c769SSteven Rostedt
27440a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
27450a05c769SSteven Rostedt
274630f75da5SSteven Rostedt    if (defined($config_bisect_good)) {
274730f75da5SSteven Rostedt	process_config_ignore $config_bisect_good;
274830f75da5SSteven Rostedt    }
274930f75da5SSteven Rostedt
27500a05c769SSteven Rostedt    # Make the file with the bad config and the min config
27510a05c769SSteven Rostedt    if (defined($minconfig)) {
27520a05c769SSteven Rostedt	# read the min config for things to ignore
27530a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
27540a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
27550a05c769SSteven Rostedt    } else {
27560a05c769SSteven Rostedt	unlink $tmpconfig;
27570a05c769SSteven Rostedt    }
27580a05c769SSteven Rostedt
27590a05c769SSteven Rostedt    if (-f $tmpconfig) {
2760fcb3f16aSSteven Rostedt	load_force_config($tmpconfig);
27610a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
27620a05c769SSteven Rostedt    }
27630a05c769SSteven Rostedt
27640a05c769SSteven Rostedt    # now process the start config
27650a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
27660a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
27670a05c769SSteven Rostedt
27680a05c769SSteven Rostedt    # read directly what we want to check
27690a05c769SSteven Rostedt    my %config_check;
27700a05c769SSteven Rostedt    open (IN, $output_config)
2771f9dee311SMasanari Iida	or dodie "failed to open $output_config";
27720a05c769SSteven Rostedt
27730a05c769SSteven Rostedt    while (<IN>) {
27740a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
27750a05c769SSteven Rostedt	    $config_check{$2} = $1;
27760a05c769SSteven Rostedt	}
27770a05c769SSteven Rostedt    }
27780a05c769SSteven Rostedt    close(IN);
27790a05c769SSteven Rostedt
2780250bae8bSSteven Rostedt    # Now run oldconfig with the minconfig
2781fcb3f16aSSteven Rostedt    make_oldconfig;
27820a05c769SSteven Rostedt
27830a05c769SSteven Rostedt    # check to see what we lost (or gained)
27840a05c769SSteven Rostedt    open (IN, $output_config)
27850a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
27860a05c769SSteven Rostedt
27870a05c769SSteven Rostedt    my %removed_configs;
27880a05c769SSteven Rostedt    my %added_configs;
27890a05c769SSteven Rostedt
27900a05c769SSteven Rostedt    while (<IN>) {
27910a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
27920a05c769SSteven Rostedt	    # save off all options
27930a05c769SSteven Rostedt	    $config_set{$2} = $1;
27940a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
27950a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
27960a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
27970a05c769SSteven Rostedt		} else {
27980a05c769SSteven Rostedt		    $config_list{$2} = $1;
27990a05c769SSteven Rostedt		}
28000a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
28010a05c769SSteven Rostedt		$added_configs{$2} = $1;
28020a05c769SSteven Rostedt		$config_list{$2} = $1;
28030a05c769SSteven Rostedt	    }
2804cf79fab6SSteven Rostedt	} elsif (/^# ((CONFIG\S*).*)/) {
2805cf79fab6SSteven Rostedt	    # Keep these configs disabled
2806cf79fab6SSteven Rostedt	    $config_set{$2} = $1;
2807cf79fab6SSteven Rostedt	    $config_off{$2} = $1;
28080a05c769SSteven Rostedt	}
28090a05c769SSteven Rostedt    }
28100a05c769SSteven Rostedt    close(IN);
28110a05c769SSteven Rostedt
28120a05c769SSteven Rostedt    my @confs = keys %removed_configs;
28130a05c769SSteven Rostedt    if ($#confs >= 0) {
28140a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
28150a05c769SSteven Rostedt	foreach my $config (@confs) {
28160a05c769SSteven Rostedt	    doprint " $config\n";
28170a05c769SSteven Rostedt	}
28180a05c769SSteven Rostedt    }
28190a05c769SSteven Rostedt    @confs = keys %added_configs;
28200a05c769SSteven Rostedt    if ($#confs >= 0) {
28210a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
28220a05c769SSteven Rostedt	foreach my $config (@confs) {
28230a05c769SSteven Rostedt	    doprint " $config\n";
28240a05c769SSteven Rostedt	}
28250a05c769SSteven Rostedt    }
28260a05c769SSteven Rostedt
28270a05c769SSteven Rostedt    my %config_test;
28280a05c769SSteven Rostedt    my $once = 0;
28290a05c769SSteven Rostedt
2830cf79fab6SSteven Rostedt    @config_off_tmp = ();
2831cf79fab6SSteven Rostedt
28320a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
28330a05c769SSteven Rostedt    # that the config we autocreate has everything we need
28340a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
28350a05c769SSteven Rostedt    # may not be able to create a new config.
28360a05c769SSteven Rostedt    # Here we create a config with everything set.
28370a05c769SSteven Rostedt    create_config (keys %config_list);
28380a05c769SSteven Rostedt    read_current_config \%config_test;
28390a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
28400a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
28410a05c769SSteven Rostedt	    if (!$once) {
28420a05c769SSteven Rostedt		$once = 1;
28430a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
28440a05c769SSteven Rostedt	    }
28450a05c769SSteven Rostedt	    doprint "  $config\n";
28460a05c769SSteven Rostedt	    delete $config_list{$config};
28470a05c769SSteven Rostedt	}
28480a05c769SSteven Rostedt    }
28490a05c769SSteven Rostedt    my $ret;
2850b0918612SSteven Rostedt
2851b0918612SSteven Rostedt    if (defined($config_bisect_check) && $config_bisect_check) {
2852b0918612SSteven Rostedt	doprint " Checking to make sure bad config with min config fails\n";
2853b0918612SSteven Rostedt	create_config keys %config_list;
2854b0918612SSteven Rostedt	$ret = run_config_bisect_test $config_bisect_type;
2855b0918612SSteven Rostedt	if ($ret) {
2856b0918612SSteven Rostedt	    doprint " FAILED! Bad config with min config boots fine\n";
2857b0918612SSteven Rostedt	    return -1;
2858b0918612SSteven Rostedt	}
2859b0918612SSteven Rostedt	doprint " Bad config with min config fails as expected\n";
2860b0918612SSteven Rostedt    }
2861b0918612SSteven Rostedt
28620a05c769SSteven Rostedt    do {
28630a05c769SSteven Rostedt	$ret = run_config_bisect;
28640a05c769SSteven Rostedt    } while (!$ret);
28650a05c769SSteven Rostedt
28660a05c769SSteven Rostedt    return $ret if ($ret < 0);
28675f9b6cedSSteven Rostedt
28685f9b6cedSSteven Rostedt    success $i;
28695f9b6cedSSteven Rostedt}
28705f9b6cedSSteven Rostedt
287127d934b2SSteven Rostedtsub patchcheck_reboot {
287227d934b2SSteven Rostedt    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
2873bc7c5803SSteven Rostedt    reboot_to_good $patchcheck_sleep_time;
287427d934b2SSteven Rostedt}
287527d934b2SSteven Rostedt
28766c5ee0beSSteven Rostedtsub patchcheck {
28776c5ee0beSSteven Rostedt    my ($i) = @_;
28786c5ee0beSSteven Rostedt
28796c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
2880b5f4aea6SSteven Rostedt	if (!defined($patchcheck_start));
28816c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
2882b5f4aea6SSteven Rostedt	if (!defined($patchcheck_type));
28836c5ee0beSSteven Rostedt
2884b5f4aea6SSteven Rostedt    my $start = $patchcheck_start;
28856c5ee0beSSteven Rostedt
28866c5ee0beSSteven Rostedt    my $end = "HEAD";
2887b5f4aea6SSteven Rostedt    if (defined($patchcheck_end)) {
2888b5f4aea6SSteven Rostedt	$end = $patchcheck_end;
28896c5ee0beSSteven Rostedt    }
28906c5ee0beSSteven Rostedt
2891a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
2892a57419b3SSteven Rostedt    $start = get_sha1($start);
2893a57419b3SSteven Rostedt    $end = get_sha1($end);
2894a57419b3SSteven Rostedt
2895b5f4aea6SSteven Rostedt    my $type = $patchcheck_type;
28966c5ee0beSSteven Rostedt
28976c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
28986c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
28996c5ee0beSSteven Rostedt	$type = "boot";
29006c5ee0beSSteven Rostedt    }
29016c5ee0beSSteven Rostedt
29026c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
29036c5ee0beSSteven Rostedt	dodie "could not get git list";
29046c5ee0beSSteven Rostedt
29056c5ee0beSSteven Rostedt    my @list;
29066c5ee0beSSteven Rostedt
29076c5ee0beSSteven Rostedt    while (<IN>) {
29086c5ee0beSSteven Rostedt	chomp;
29096c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
29106c5ee0beSSteven Rostedt	last if (/^$start/);
29116c5ee0beSSteven Rostedt    }
29126c5ee0beSSteven Rostedt    close(IN);
29136c5ee0beSSteven Rostedt
29146c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
29152b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
29166c5ee0beSSteven Rostedt    }
29176c5ee0beSSteven Rostedt
29186c5ee0beSSteven Rostedt    # go backwards in the list
29196c5ee0beSSteven Rostedt    @list = reverse @list;
29206c5ee0beSSteven Rostedt
29216c5ee0beSSteven Rostedt    my $save_clean = $noclean;
29221990207dSSteven Rostedt    my %ignored_warnings;
29231990207dSSteven Rostedt
29241990207dSSteven Rostedt    if (defined($ignore_warnings)) {
29251990207dSSteven Rostedt	foreach my $sha1 (split /\s+/, $ignore_warnings) {
29261990207dSSteven Rostedt	    $ignored_warnings{$sha1} = 1;
29271990207dSSteven Rostedt	}
29281990207dSSteven Rostedt    }
29296c5ee0beSSteven Rostedt
29306c5ee0beSSteven Rostedt    $in_patchcheck = 1;
29316c5ee0beSSteven Rostedt    foreach my $item (@list) {
29326c5ee0beSSteven Rostedt	my $sha1 = $item;
29336c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
29346c5ee0beSSteven Rostedt
29356c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
29366c5ee0beSSteven Rostedt
29376c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
29386c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
29396c5ee0beSSteven Rostedt
29406c5ee0beSSteven Rostedt	# only clean on the first and last patch
29416c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
29426c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
29436c5ee0beSSteven Rostedt	    $noclean = $save_clean;
29446c5ee0beSSteven Rostedt	} else {
29456c5ee0beSSteven Rostedt	    $noclean = 1;
29466c5ee0beSSteven Rostedt	}
29476c5ee0beSSteven Rostedt
29486c5ee0beSSteven Rostedt	if (defined($minconfig)) {
29492b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
29506c5ee0beSSteven Rostedt	} else {
29516c5ee0beSSteven Rostedt	    # ?? no config to use?
29522b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
29536c5ee0beSSteven Rostedt	}
29546c5ee0beSSteven Rostedt
29551990207dSSteven Rostedt
29561990207dSSteven Rostedt	if (!defined($ignored_warnings{$sha1})) {
29572b7d9b21SSteven Rostedt	    check_buildlog $sha1 or return 0;
29581990207dSSteven Rostedt	}
29596c5ee0beSSteven Rostedt
29606c5ee0beSSteven Rostedt	next if ($type eq "build");
29616c5ee0beSSteven Rostedt
29627faafbd6SSteven Rostedt	my $failed = 0;
29637faafbd6SSteven Rostedt
2964ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
29657faafbd6SSteven Rostedt
29667faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
29677faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
29687faafbd6SSteven Rostedt	}
29697faafbd6SSteven Rostedt	end_monitor;
29707faafbd6SSteven Rostedt	return 0 if ($failed);
29717faafbd6SSteven Rostedt
297227d934b2SSteven Rostedt	patchcheck_reboot;
297327d934b2SSteven Rostedt
29746c5ee0beSSteven Rostedt    }
29756c5ee0beSSteven Rostedt    $in_patchcheck = 0;
29766c5ee0beSSteven Rostedt    success $i;
29772b7d9b21SSteven Rostedt
29782b7d9b21SSteven Rostedt    return 1;
29796c5ee0beSSteven Rostedt}
29806c5ee0beSSteven Rostedt
2981b9066f6cSSteven Rostedtmy %depends;
2982ac6974c7SSteven Rostedtmy %depcount;
2983b9066f6cSSteven Rostedtmy $iflevel = 0;
2984b9066f6cSSteven Rostedtmy @ifdeps;
2985b9066f6cSSteven Rostedt
2986b9066f6cSSteven Rostedt# prevent recursion
2987b9066f6cSSteven Rostedtmy %read_kconfigs;
2988b9066f6cSSteven Rostedt
2989ac6974c7SSteven Rostedtsub add_dep {
2990ac6974c7SSteven Rostedt    # $config depends on $dep
2991ac6974c7SSteven Rostedt    my ($config, $dep) = @_;
2992ac6974c7SSteven Rostedt
2993ac6974c7SSteven Rostedt    if (defined($depends{$config})) {
2994ac6974c7SSteven Rostedt	$depends{$config} .= " " . $dep;
2995ac6974c7SSteven Rostedt    } else {
2996ac6974c7SSteven Rostedt	$depends{$config} = $dep;
2997ac6974c7SSteven Rostedt    }
2998ac6974c7SSteven Rostedt
2999ac6974c7SSteven Rostedt    # record the number of configs depending on $dep
3000ac6974c7SSteven Rostedt    if (defined $depcount{$dep}) {
3001ac6974c7SSteven Rostedt	$depcount{$dep}++;
3002ac6974c7SSteven Rostedt    } else {
3003ac6974c7SSteven Rostedt	$depcount{$dep} = 1;
3004ac6974c7SSteven Rostedt    }
3005ac6974c7SSteven Rostedt}
3006ac6974c7SSteven Rostedt
3007b9066f6cSSteven Rostedt# taken from streamline_config.pl
3008b9066f6cSSteven Rostedtsub read_kconfig {
3009b9066f6cSSteven Rostedt    my ($kconfig) = @_;
3010b9066f6cSSteven Rostedt
3011b9066f6cSSteven Rostedt    my $state = "NONE";
3012b9066f6cSSteven Rostedt    my $config;
3013b9066f6cSSteven Rostedt    my @kconfigs;
3014b9066f6cSSteven Rostedt
3015b9066f6cSSteven Rostedt    my $cont = 0;
3016b9066f6cSSteven Rostedt    my $line;
3017b9066f6cSSteven Rostedt
3018b9066f6cSSteven Rostedt
3019b9066f6cSSteven Rostedt    if (! -f $kconfig) {
3020b9066f6cSSteven Rostedt	doprint "file $kconfig does not exist, skipping\n";
3021b9066f6cSSteven Rostedt	return;
3022b9066f6cSSteven Rostedt    }
3023b9066f6cSSteven Rostedt
3024b9066f6cSSteven Rostedt    open(KIN, "$kconfig")
3025b9066f6cSSteven Rostedt	or die "Can't open $kconfig";
3026b9066f6cSSteven Rostedt    while (<KIN>) {
3027b9066f6cSSteven Rostedt	chomp;
3028b9066f6cSSteven Rostedt
3029b9066f6cSSteven Rostedt	# Make sure that lines ending with \ continue
3030b9066f6cSSteven Rostedt	if ($cont) {
3031b9066f6cSSteven Rostedt	    $_ = $line . " " . $_;
3032b9066f6cSSteven Rostedt	}
3033b9066f6cSSteven Rostedt
3034b9066f6cSSteven Rostedt	if (s/\\$//) {
3035b9066f6cSSteven Rostedt	    $cont = 1;
3036b9066f6cSSteven Rostedt	    $line = $_;
3037b9066f6cSSteven Rostedt	    next;
3038b9066f6cSSteven Rostedt	}
3039b9066f6cSSteven Rostedt
3040b9066f6cSSteven Rostedt	$cont = 0;
3041b9066f6cSSteven Rostedt
3042b9066f6cSSteven Rostedt	# collect any Kconfig sources
3043b9066f6cSSteven Rostedt	if (/^source\s*"(.*)"/) {
3044b9066f6cSSteven Rostedt	    $kconfigs[$#kconfigs+1] = $1;
3045b9066f6cSSteven Rostedt	}
3046b9066f6cSSteven Rostedt
3047b9066f6cSSteven Rostedt	# configs found
3048b9066f6cSSteven Rostedt	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
3049b9066f6cSSteven Rostedt	    $state = "NEW";
3050b9066f6cSSteven Rostedt	    $config = $2;
3051b9066f6cSSteven Rostedt
3052b9066f6cSSteven Rostedt	    for (my $i = 0; $i < $iflevel; $i++) {
3053ac6974c7SSteven Rostedt		add_dep $config, $ifdeps[$i];
3054b9066f6cSSteven Rostedt	    }
3055b9066f6cSSteven Rostedt
3056b9066f6cSSteven Rostedt	# collect the depends for the config
3057b9066f6cSSteven Rostedt	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
3058b9066f6cSSteven Rostedt
3059ac6974c7SSteven Rostedt	    add_dep $config, $1;
3060b9066f6cSSteven Rostedt
3061b9066f6cSSteven Rostedt	# Get the configs that select this config
3062ac6974c7SSteven Rostedt	} elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
3063ac6974c7SSteven Rostedt
3064ac6974c7SSteven Rostedt	    # selected by depends on config
3065ac6974c7SSteven Rostedt	    add_dep $1, $config;
3066b9066f6cSSteven Rostedt
3067b9066f6cSSteven Rostedt	# Check for if statements
3068b9066f6cSSteven Rostedt	} elsif (/^if\s+(.*\S)\s*$/) {
3069b9066f6cSSteven Rostedt	    my $deps = $1;
3070b9066f6cSSteven Rostedt	    # remove beginning and ending non text
3071b9066f6cSSteven Rostedt	    $deps =~ s/^[^a-zA-Z0-9_]*//;
3072b9066f6cSSteven Rostedt	    $deps =~ s/[^a-zA-Z0-9_]*$//;
3073b9066f6cSSteven Rostedt
3074b9066f6cSSteven Rostedt	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
3075b9066f6cSSteven Rostedt
3076b9066f6cSSteven Rostedt	    $ifdeps[$iflevel++] = join ':', @deps;
3077b9066f6cSSteven Rostedt
3078b9066f6cSSteven Rostedt	} elsif (/^endif/) {
3079b9066f6cSSteven Rostedt
3080b9066f6cSSteven Rostedt	    $iflevel-- if ($iflevel);
3081b9066f6cSSteven Rostedt
3082b9066f6cSSteven Rostedt	# stop on "help"
3083b9066f6cSSteven Rostedt	} elsif (/^\s*help\s*$/) {
3084b9066f6cSSteven Rostedt	    $state = "NONE";
3085b9066f6cSSteven Rostedt	}
3086b9066f6cSSteven Rostedt    }
3087b9066f6cSSteven Rostedt    close(KIN);
3088b9066f6cSSteven Rostedt
3089b9066f6cSSteven Rostedt    # read in any configs that were found.
3090b9066f6cSSteven Rostedt    foreach $kconfig (@kconfigs) {
3091b9066f6cSSteven Rostedt	if (!defined($read_kconfigs{$kconfig})) {
3092b9066f6cSSteven Rostedt	    $read_kconfigs{$kconfig} = 1;
3093b9066f6cSSteven Rostedt	    read_kconfig("$builddir/$kconfig");
3094b9066f6cSSteven Rostedt	}
3095b9066f6cSSteven Rostedt    }
3096b9066f6cSSteven Rostedt}
3097b9066f6cSSteven Rostedt
3098b9066f6cSSteven Rostedtsub read_depends {
3099b9066f6cSSteven Rostedt    # find out which arch this is by the kconfig file
3100b9066f6cSSteven Rostedt    open (IN, $output_config)
3101b9066f6cSSteven Rostedt	or dodie "Failed to read $output_config";
3102b9066f6cSSteven Rostedt    my $arch;
3103b9066f6cSSteven Rostedt    while (<IN>) {
3104b9066f6cSSteven Rostedt	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
3105b9066f6cSSteven Rostedt	    $arch = $1;
3106b9066f6cSSteven Rostedt	    last;
3107b9066f6cSSteven Rostedt	}
3108b9066f6cSSteven Rostedt    }
3109b9066f6cSSteven Rostedt    close IN;
3110b9066f6cSSteven Rostedt
3111b9066f6cSSteven Rostedt    if (!defined($arch)) {
3112b9066f6cSSteven Rostedt	doprint "Could not find arch from config file\n";
3113b9066f6cSSteven Rostedt	doprint "no dependencies used\n";
3114b9066f6cSSteven Rostedt	return;
3115b9066f6cSSteven Rostedt    }
3116b9066f6cSSteven Rostedt
3117b9066f6cSSteven Rostedt    # arch is really the subarch, we need to know
3118b9066f6cSSteven Rostedt    # what directory to look at.
3119b9066f6cSSteven Rostedt    if ($arch eq "i386" || $arch eq "x86_64") {
3120b9066f6cSSteven Rostedt	$arch = "x86";
3121b9066f6cSSteven Rostedt    } elsif ($arch =~ /^tile/) {
3122b9066f6cSSteven Rostedt	$arch = "tile";
3123b9066f6cSSteven Rostedt    }
3124b9066f6cSSteven Rostedt
3125b9066f6cSSteven Rostedt    my $kconfig = "$builddir/arch/$arch/Kconfig";
3126b9066f6cSSteven Rostedt
3127b9066f6cSSteven Rostedt    if (! -f $kconfig && $arch =~ /\d$/) {
3128b9066f6cSSteven Rostedt	my $orig = $arch;
3129b9066f6cSSteven Rostedt 	# some subarchs have numbers, truncate them
3130b9066f6cSSteven Rostedt	$arch =~ s/\d*$//;
3131b9066f6cSSteven Rostedt	$kconfig = "$builddir/arch/$arch/Kconfig";
3132b9066f6cSSteven Rostedt	if (! -f $kconfig) {
3133b9066f6cSSteven Rostedt	    doprint "No idea what arch dir $orig is for\n";
3134b9066f6cSSteven Rostedt	    doprint "no dependencies used\n";
3135b9066f6cSSteven Rostedt	    return;
3136b9066f6cSSteven Rostedt	}
3137b9066f6cSSteven Rostedt    }
3138b9066f6cSSteven Rostedt
3139b9066f6cSSteven Rostedt    read_kconfig($kconfig);
3140b9066f6cSSteven Rostedt}
3141b9066f6cSSteven Rostedt
31424c4ab120SSteven Rostedtsub read_config_list {
31434c4ab120SSteven Rostedt    my ($config) = @_;
31444c4ab120SSteven Rostedt
31454c4ab120SSteven Rostedt    open (IN, $config)
31464c4ab120SSteven Rostedt	or dodie "Failed to read $config";
31474c4ab120SSteven Rostedt
31484c4ab120SSteven Rostedt    while (<IN>) {
31494c4ab120SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
31504c4ab120SSteven Rostedt	    if (!defined($config_ignore{$2})) {
31514c4ab120SSteven Rostedt		$config_list{$2} = $1;
31524c4ab120SSteven Rostedt	    }
31534c4ab120SSteven Rostedt	}
31544c4ab120SSteven Rostedt    }
31554c4ab120SSteven Rostedt
31564c4ab120SSteven Rostedt    close(IN);
31574c4ab120SSteven Rostedt}
31584c4ab120SSteven Rostedt
31594c4ab120SSteven Rostedtsub read_output_config {
31604c4ab120SSteven Rostedt    my ($config) = @_;
31614c4ab120SSteven Rostedt
31624c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
31634c4ab120SSteven Rostedt}
31644c4ab120SSteven Rostedt
31654c4ab120SSteven Rostedtsub make_new_config {
31664c4ab120SSteven Rostedt    my @configs = @_;
31674c4ab120SSteven Rostedt
31684c4ab120SSteven Rostedt    open (OUT, ">$output_config")
31694c4ab120SSteven Rostedt	or dodie "Failed to write $output_config";
31704c4ab120SSteven Rostedt
31714c4ab120SSteven Rostedt    foreach my $config (@configs) {
31724c4ab120SSteven Rostedt	print OUT "$config\n";
31734c4ab120SSteven Rostedt    }
31744c4ab120SSteven Rostedt    close OUT;
31754c4ab120SSteven Rostedt}
31764c4ab120SSteven Rostedt
3177ac6974c7SSteven Rostedtsub chomp_config {
3178ac6974c7SSteven Rostedt    my ($config) = @_;
3179ac6974c7SSteven Rostedt
3180ac6974c7SSteven Rostedt    $config =~ s/CONFIG_//;
3181ac6974c7SSteven Rostedt
3182ac6974c7SSteven Rostedt    return $config;
3183ac6974c7SSteven Rostedt}
3184ac6974c7SSteven Rostedt
3185b9066f6cSSteven Rostedtsub get_depends {
3186b9066f6cSSteven Rostedt    my ($dep) = @_;
3187b9066f6cSSteven Rostedt
3188ac6974c7SSteven Rostedt    my $kconfig = chomp_config $dep;
3189b9066f6cSSteven Rostedt
3190b9066f6cSSteven Rostedt    $dep = $depends{"$kconfig"};
3191b9066f6cSSteven Rostedt
3192b9066f6cSSteven Rostedt    # the dep string we have saves the dependencies as they
3193b9066f6cSSteven Rostedt    # were found, including expressions like ! && ||. We
3194b9066f6cSSteven Rostedt    # want to split this out into just an array of configs.
3195b9066f6cSSteven Rostedt
3196b9066f6cSSteven Rostedt    my $valid = "A-Za-z_0-9";
3197b9066f6cSSteven Rostedt
3198b9066f6cSSteven Rostedt    my @configs;
3199b9066f6cSSteven Rostedt
3200b9066f6cSSteven Rostedt    while ($dep =~ /[$valid]/) {
3201b9066f6cSSteven Rostedt
3202b9066f6cSSteven Rostedt	if ($dep =~ /^[^$valid]*([$valid]+)/) {
3203b9066f6cSSteven Rostedt	    my $conf = "CONFIG_" . $1;
3204b9066f6cSSteven Rostedt
3205b9066f6cSSteven Rostedt	    $configs[$#configs + 1] = $conf;
3206b9066f6cSSteven Rostedt
3207b9066f6cSSteven Rostedt	    $dep =~ s/^[^$valid]*[$valid]+//;
3208b9066f6cSSteven Rostedt	} else {
3209b9066f6cSSteven Rostedt	    die "this should never happen";
3210b9066f6cSSteven Rostedt	}
3211b9066f6cSSteven Rostedt    }
3212b9066f6cSSteven Rostedt
3213b9066f6cSSteven Rostedt    return @configs;
3214b9066f6cSSteven Rostedt}
3215b9066f6cSSteven Rostedt
3216b9066f6cSSteven Rostedtmy %min_configs;
3217b9066f6cSSteven Rostedtmy %keep_configs;
321843d1b651SSteven Rostedtmy %save_configs;
3219b9066f6cSSteven Rostedtmy %processed_configs;
3220b9066f6cSSteven Rostedtmy %nochange_config;
3221b9066f6cSSteven Rostedt
3222b9066f6cSSteven Rostedtsub test_this_config {
3223b9066f6cSSteven Rostedt    my ($config) = @_;
3224b9066f6cSSteven Rostedt
3225b9066f6cSSteven Rostedt    my $found;
3226b9066f6cSSteven Rostedt
3227b9066f6cSSteven Rostedt    # if we already processed this config, skip it
3228b9066f6cSSteven Rostedt    if (defined($processed_configs{$config})) {
3229b9066f6cSSteven Rostedt	return undef;
3230b9066f6cSSteven Rostedt    }
3231b9066f6cSSteven Rostedt    $processed_configs{$config} = 1;
3232b9066f6cSSteven Rostedt
3233b9066f6cSSteven Rostedt    # if this config failed during this round, skip it
3234b9066f6cSSteven Rostedt    if (defined($nochange_config{$config})) {
3235b9066f6cSSteven Rostedt	return undef;
3236b9066f6cSSteven Rostedt    }
3237b9066f6cSSteven Rostedt
3238ac6974c7SSteven Rostedt    my $kconfig = chomp_config $config;
3239b9066f6cSSteven Rostedt
3240b9066f6cSSteven Rostedt    # Test dependencies first
3241b9066f6cSSteven Rostedt    if (defined($depends{"$kconfig"})) {
3242b9066f6cSSteven Rostedt	my @parents = get_depends $config;
3243b9066f6cSSteven Rostedt	foreach my $parent (@parents) {
3244b9066f6cSSteven Rostedt	    # if the parent is in the min config, check it first
3245b9066f6cSSteven Rostedt	    next if (!defined($min_configs{$parent}));
3246b9066f6cSSteven Rostedt	    $found = test_this_config($parent);
3247b9066f6cSSteven Rostedt	    if (defined($found)) {
3248b9066f6cSSteven Rostedt		return $found;
3249b9066f6cSSteven Rostedt	    }
3250b9066f6cSSteven Rostedt	}
3251b9066f6cSSteven Rostedt    }
3252b9066f6cSSteven Rostedt
3253b9066f6cSSteven Rostedt    # Remove this config from the list of configs
3254fb16d891SAdam Lee    # do a make olddefconfig and then read the resulting
3255b9066f6cSSteven Rostedt    # .config to make sure it is missing the config that
3256b9066f6cSSteven Rostedt    # we had before
3257b9066f6cSSteven Rostedt    my %configs = %min_configs;
3258b9066f6cSSteven Rostedt    delete $configs{$config};
3259b9066f6cSSteven Rostedt    make_new_config ((values %configs), (values %keep_configs));
3260b9066f6cSSteven Rostedt    make_oldconfig;
3261b9066f6cSSteven Rostedt    undef %configs;
3262b9066f6cSSteven Rostedt    assign_configs \%configs, $output_config;
3263b9066f6cSSteven Rostedt
3264b9066f6cSSteven Rostedt    return $config if (!defined($configs{$config}));
3265b9066f6cSSteven Rostedt
3266b9066f6cSSteven Rostedt    doprint "disabling config $config did not change .config\n";
3267b9066f6cSSteven Rostedt
3268b9066f6cSSteven Rostedt    $nochange_config{$config} = 1;
3269b9066f6cSSteven Rostedt
3270b9066f6cSSteven Rostedt    return undef;
3271b9066f6cSSteven Rostedt}
3272b9066f6cSSteven Rostedt
32734c4ab120SSteven Rostedtsub make_min_config {
32744c4ab120SSteven Rostedt    my ($i) = @_;
32754c4ab120SSteven Rostedt
3276ccc513b6SSteven Rostedt    my $type = $minconfig_type;
3277ccc513b6SSteven Rostedt    if ($type ne "boot" && $type ne "test") {
3278ccc513b6SSteven Rostedt	fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" .
3279ccc513b6SSteven Rostedt	    " make_min_config works only with 'boot' and 'test'\n" and return;
3280ccc513b6SSteven Rostedt    }
3281ccc513b6SSteven Rostedt
32824c4ab120SSteven Rostedt    if (!defined($output_minconfig)) {
32834c4ab120SSteven Rostedt	fail "OUTPUT_MIN_CONFIG not defined" and return;
32844c4ab120SSteven Rostedt    }
328535ce5952SSteven Rostedt
328635ce5952SSteven Rostedt    # If output_minconfig exists, and the start_minconfig
328735ce5952SSteven Rostedt    # came from min_config, than ask if we should use
328835ce5952SSteven Rostedt    # that instead.
328935ce5952SSteven Rostedt    if (-f $output_minconfig && !$start_minconfig_defined) {
329035ce5952SSteven Rostedt	print "$output_minconfig exists\n";
329143de3316SSteven Rostedt	if (!defined($use_output_minconfig)) {
329235ce5952SSteven Rostedt	    if (read_yn " Use it as minconfig?") {
329335ce5952SSteven Rostedt		$start_minconfig = $output_minconfig;
329435ce5952SSteven Rostedt	    }
329543de3316SSteven Rostedt	} elsif ($use_output_minconfig > 0) {
329643de3316SSteven Rostedt	    doprint "Using $output_minconfig as MIN_CONFIG\n";
329743de3316SSteven Rostedt	    $start_minconfig = $output_minconfig;
329843de3316SSteven Rostedt	} else {
329943de3316SSteven Rostedt	    doprint "Set to still use MIN_CONFIG as starting point\n";
330043de3316SSteven Rostedt	}
330135ce5952SSteven Rostedt    }
330235ce5952SSteven Rostedt
33034c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
33044c4ab120SSteven Rostedt	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
33054c4ab120SSteven Rostedt    }
33064c4ab120SSteven Rostedt
330735ce5952SSteven Rostedt    my $temp_config = "$tmpdir/temp_config";
330835ce5952SSteven Rostedt
33094c4ab120SSteven Rostedt    # First things first. We build an allnoconfig to find
33104c4ab120SSteven Rostedt    # out what the defaults are that we can't touch.
33114c4ab120SSteven Rostedt    # Some are selections, but we really can't handle selections.
33124c4ab120SSteven Rostedt
33134c4ab120SSteven Rostedt    my $save_minconfig = $minconfig;
33144c4ab120SSteven Rostedt    undef $minconfig;
33154c4ab120SSteven Rostedt
33164c4ab120SSteven Rostedt    run_command "$make allnoconfig" or return 0;
33174c4ab120SSteven Rostedt
3318b9066f6cSSteven Rostedt    read_depends;
3319b9066f6cSSteven Rostedt
33204c4ab120SSteven Rostedt    process_config_ignore $output_config;
3321b9066f6cSSteven Rostedt
332243d1b651SSteven Rostedt    undef %save_configs;
3323b9066f6cSSteven Rostedt    undef %min_configs;
33244c4ab120SSteven Rostedt
33254c4ab120SSteven Rostedt    if (defined($ignore_config)) {
33264c4ab120SSteven Rostedt	# make sure the file exists
33274c4ab120SSteven Rostedt	`touch $ignore_config`;
332843d1b651SSteven Rostedt	assign_configs \%save_configs, $ignore_config;
33294c4ab120SSteven Rostedt    }
33304c4ab120SSteven Rostedt
333143d1b651SSteven Rostedt    %keep_configs = %save_configs;
333243d1b651SSteven Rostedt
33334c4ab120SSteven Rostedt    doprint "Load initial configs from $start_minconfig\n";
33344c4ab120SSteven Rostedt
33354c4ab120SSteven Rostedt    # Look at the current min configs, and save off all the
33364c4ab120SSteven Rostedt    # ones that were set via the allnoconfig
33374c4ab120SSteven Rostedt    assign_configs \%min_configs, $start_minconfig;
33384c4ab120SSteven Rostedt
33394c4ab120SSteven Rostedt    my @config_keys = keys %min_configs;
33404c4ab120SSteven Rostedt
3341ac6974c7SSteven Rostedt    # All configs need a depcount
3342ac6974c7SSteven Rostedt    foreach my $config (@config_keys) {
3343ac6974c7SSteven Rostedt	my $kconfig = chomp_config $config;
3344ac6974c7SSteven Rostedt	if (!defined $depcount{$kconfig}) {
3345ac6974c7SSteven Rostedt		$depcount{$kconfig} = 0;
3346ac6974c7SSteven Rostedt	}
3347ac6974c7SSteven Rostedt    }
3348ac6974c7SSteven Rostedt
33494c4ab120SSteven Rostedt    # Remove anything that was set by the make allnoconfig
33504c4ab120SSteven Rostedt    # we shouldn't need them as they get set for us anyway.
33514c4ab120SSteven Rostedt    foreach my $config (@config_keys) {
33524c4ab120SSteven Rostedt	# Remove anything in the ignore_config
33534c4ab120SSteven Rostedt	if (defined($keep_configs{$config})) {
33544c4ab120SSteven Rostedt	    my $file = $ignore_config;
33554c4ab120SSteven Rostedt	    $file =~ s,.*/(.*?)$,$1,;
33564c4ab120SSteven Rostedt	    doprint "$config set by $file ... ignored\n";
33574c4ab120SSteven Rostedt	    delete $min_configs{$config};
33584c4ab120SSteven Rostedt	    next;
33594c4ab120SSteven Rostedt	}
33604c4ab120SSteven Rostedt	# But make sure the settings are the same. If a min config
33614c4ab120SSteven Rostedt	# sets a selection, we do not want to get rid of it if
33624c4ab120SSteven Rostedt	# it is not the same as what we have. Just move it into
33634c4ab120SSteven Rostedt	# the keep configs.
33644c4ab120SSteven Rostedt	if (defined($config_ignore{$config})) {
33654c4ab120SSteven Rostedt	    if ($config_ignore{$config} ne $min_configs{$config}) {
33664c4ab120SSteven Rostedt		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
33674c4ab120SSteven Rostedt		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
33684c4ab120SSteven Rostedt		$keep_configs{$config} = $min_configs{$config};
33694c4ab120SSteven Rostedt	    } else {
33704c4ab120SSteven Rostedt		doprint "$config set by allnoconfig ... ignored\n";
33714c4ab120SSteven Rostedt	    }
33724c4ab120SSteven Rostedt	    delete $min_configs{$config};
33734c4ab120SSteven Rostedt	}
33744c4ab120SSteven Rostedt    }
33754c4ab120SSteven Rostedt
33764c4ab120SSteven Rostedt    my $done = 0;
3377b9066f6cSSteven Rostedt    my $take_two = 0;
33784c4ab120SSteven Rostedt
33794c4ab120SSteven Rostedt    while (!$done) {
33804c4ab120SSteven Rostedt
33814c4ab120SSteven Rostedt	my $config;
33824c4ab120SSteven Rostedt	my $found;
33834c4ab120SSteven Rostedt
33844c4ab120SSteven Rostedt	# Now disable each config one by one and do a make oldconfig
33854c4ab120SSteven Rostedt	# till we find a config that changes our list.
33864c4ab120SSteven Rostedt
33874c4ab120SSteven Rostedt	my @test_configs = keys %min_configs;
3388ac6974c7SSteven Rostedt
3389ac6974c7SSteven Rostedt	# Sort keys by who is most dependent on
3390ac6974c7SSteven Rostedt	@test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
3391ac6974c7SSteven Rostedt			  @test_configs ;
3392ac6974c7SSteven Rostedt
3393ac6974c7SSteven Rostedt	# Put configs that did not modify the config at the end.
33944c4ab120SSteven Rostedt	my $reset = 1;
33954c4ab120SSteven Rostedt	for (my $i = 0; $i < $#test_configs; $i++) {
33964c4ab120SSteven Rostedt	    if (!defined($nochange_config{$test_configs[0]})) {
33974c4ab120SSteven Rostedt		$reset = 0;
33984c4ab120SSteven Rostedt		last;
33994c4ab120SSteven Rostedt	    }
34004c4ab120SSteven Rostedt	    # This config didn't change the .config last time.
34014c4ab120SSteven Rostedt	    # Place it at the end
34024c4ab120SSteven Rostedt	    my $config = shift @test_configs;
34034c4ab120SSteven Rostedt	    push @test_configs, $config;
34044c4ab120SSteven Rostedt	}
34054c4ab120SSteven Rostedt
34064c4ab120SSteven Rostedt	# if every test config has failed to modify the .config file
34074c4ab120SSteven Rostedt	# in the past, then reset and start over.
34084c4ab120SSteven Rostedt	if ($reset) {
34094c4ab120SSteven Rostedt	    undef %nochange_config;
34104c4ab120SSteven Rostedt	}
34114c4ab120SSteven Rostedt
3412b9066f6cSSteven Rostedt	undef %processed_configs;
3413b9066f6cSSteven Rostedt
34144c4ab120SSteven Rostedt	foreach my $config (@test_configs) {
34154c4ab120SSteven Rostedt
3416b9066f6cSSteven Rostedt	    $found = test_this_config $config;
34174c4ab120SSteven Rostedt
3418b9066f6cSSteven Rostedt	    last if (defined($found));
34194c4ab120SSteven Rostedt
34204c4ab120SSteven Rostedt	    # oh well, try another config
34214c4ab120SSteven Rostedt	}
34224c4ab120SSteven Rostedt
34234c4ab120SSteven Rostedt	if (!defined($found)) {
3424b9066f6cSSteven Rostedt	    # we could have failed due to the nochange_config hash
3425b9066f6cSSteven Rostedt	    # reset and try again
3426b9066f6cSSteven Rostedt	    if (!$take_two) {
3427b9066f6cSSteven Rostedt		undef %nochange_config;
3428b9066f6cSSteven Rostedt		$take_two = 1;
3429b9066f6cSSteven Rostedt		next;
3430b9066f6cSSteven Rostedt	    }
34314c4ab120SSteven Rostedt	    doprint "No more configs found that we can disable\n";
34324c4ab120SSteven Rostedt	    $done = 1;
34334c4ab120SSteven Rostedt	    last;
34344c4ab120SSteven Rostedt	}
3435b9066f6cSSteven Rostedt	$take_two = 0;
34364c4ab120SSteven Rostedt
34374c4ab120SSteven Rostedt	$config = $found;
34384c4ab120SSteven Rostedt
34394c4ab120SSteven Rostedt	doprint "Test with $config disabled\n";
34404c4ab120SSteven Rostedt
34414c4ab120SSteven Rostedt	# set in_bisect to keep build and monitor from dieing
34424c4ab120SSteven Rostedt	$in_bisect = 1;
34434c4ab120SSteven Rostedt
34444c4ab120SSteven Rostedt	my $failed = 0;
3445bf1c95abSSteven Rostedt	build "oldconfig" or $failed = 1;
3446bf1c95abSSteven Rostedt	if (!$failed) {
34474c4ab120SSteven Rostedt		start_monitor_and_boot or $failed = 1;
3448ccc513b6SSteven Rostedt
3449ccc513b6SSteven Rostedt		if ($type eq "test" && !$failed) {
3450ccc513b6SSteven Rostedt		    do_run_test or $failed = 1;
3451ccc513b6SSteven Rostedt		}
3452ccc513b6SSteven Rostedt
34534c4ab120SSteven Rostedt		end_monitor;
3454bf1c95abSSteven Rostedt	}
34554c4ab120SSteven Rostedt
34564c4ab120SSteven Rostedt	$in_bisect = 0;
34574c4ab120SSteven Rostedt
34584c4ab120SSteven Rostedt	if ($failed) {
3459b9066f6cSSteven Rostedt	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
34604c4ab120SSteven Rostedt	    # this config is needed, add it to the ignore list.
34614c4ab120SSteven Rostedt	    $keep_configs{$config} = $min_configs{$config};
346243d1b651SSteven Rostedt	    $save_configs{$config} = $min_configs{$config};
34634c4ab120SSteven Rostedt	    delete $min_configs{$config};
346435ce5952SSteven Rostedt
346535ce5952SSteven Rostedt	    # update new ignore configs
346635ce5952SSteven Rostedt	    if (defined($ignore_config)) {
346735ce5952SSteven Rostedt		open (OUT, ">$temp_config")
346835ce5952SSteven Rostedt		    or die "Can't write to $temp_config";
346943d1b651SSteven Rostedt		foreach my $config (keys %save_configs) {
347043d1b651SSteven Rostedt		    print OUT "$save_configs{$config}\n";
347135ce5952SSteven Rostedt		}
347235ce5952SSteven Rostedt		close OUT;
347335ce5952SSteven Rostedt		run_command "mv $temp_config $ignore_config" or
347435ce5952SSteven Rostedt		    dodie "failed to copy update to $ignore_config";
347535ce5952SSteven Rostedt	    }
347635ce5952SSteven Rostedt
34774c4ab120SSteven Rostedt	} else {
34784c4ab120SSteven Rostedt	    # We booted without this config, remove it from the minconfigs.
34794c4ab120SSteven Rostedt	    doprint "$config is not needed, disabling\n";
34804c4ab120SSteven Rostedt
34814c4ab120SSteven Rostedt	    delete $min_configs{$config};
34824c4ab120SSteven Rostedt
34834c4ab120SSteven Rostedt	    # Also disable anything that is not enabled in this config
34844c4ab120SSteven Rostedt	    my %configs;
34854c4ab120SSteven Rostedt	    assign_configs \%configs, $output_config;
34864c4ab120SSteven Rostedt	    my @config_keys = keys %min_configs;
34874c4ab120SSteven Rostedt	    foreach my $config (@config_keys) {
34884c4ab120SSteven Rostedt		if (!defined($configs{$config})) {
34894c4ab120SSteven Rostedt		    doprint "$config is not set, disabling\n";
34904c4ab120SSteven Rostedt		    delete $min_configs{$config};
34914c4ab120SSteven Rostedt		}
34924c4ab120SSteven Rostedt	    }
34934c4ab120SSteven Rostedt
34944c4ab120SSteven Rostedt	    # Save off all the current mandidory configs
349535ce5952SSteven Rostedt	    open (OUT, ">$temp_config")
349635ce5952SSteven Rostedt		or die "Can't write to $temp_config";
34974c4ab120SSteven Rostedt	    foreach my $config (keys %keep_configs) {
34984c4ab120SSteven Rostedt		print OUT "$keep_configs{$config}\n";
34994c4ab120SSteven Rostedt	    }
35004c4ab120SSteven Rostedt	    foreach my $config (keys %min_configs) {
35014c4ab120SSteven Rostedt		print OUT "$min_configs{$config}\n";
35024c4ab120SSteven Rostedt	    }
35034c4ab120SSteven Rostedt	    close OUT;
350435ce5952SSteven Rostedt
350535ce5952SSteven Rostedt	    run_command "mv $temp_config $output_minconfig" or
350635ce5952SSteven Rostedt		dodie "failed to copy update to $output_minconfig";
35074c4ab120SSteven Rostedt	}
35084c4ab120SSteven Rostedt
35094c4ab120SSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
3510bc7c5803SSteven Rostedt	reboot_to_good $sleep_time;
35114c4ab120SSteven Rostedt    }
35124c4ab120SSteven Rostedt
35134c4ab120SSteven Rostedt    success $i;
35144c4ab120SSteven Rostedt    return 1;
35154c4ab120SSteven Rostedt}
35164c4ab120SSteven Rostedt
35178d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
35182545eb61SSteven Rostedt
35198d1491baSSteven Rostedtif ($#ARGV == 0) {
35208d1491baSSteven Rostedt    $ktest_config = $ARGV[0];
35218d1491baSSteven Rostedt    if (! -f $ktest_config) {
35228d1491baSSteven Rostedt	print "$ktest_config does not exist.\n";
352335ce5952SSteven Rostedt	if (!read_yn "Create it?") {
35248d1491baSSteven Rostedt	    exit 0;
35258d1491baSSteven Rostedt	}
35268d1491baSSteven Rostedt    }
35278d1491baSSteven Rostedt} else {
35288d1491baSSteven Rostedt    $ktest_config = "ktest.conf";
35298d1491baSSteven Rostedt}
35308d1491baSSteven Rostedt
35318d1491baSSteven Rostedtif (! -f $ktest_config) {
3532dbd3783bSSteven Rostedt    $newconfig = 1;
3533c4261d0fSSteven Rostedt    get_test_case;
35348d1491baSSteven Rostedt    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
35358d1491baSSteven Rostedt    print OUT << "EOF"
35368d1491baSSteven Rostedt# Generated by ktest.pl
35378d1491baSSteven Rostedt#
35380e7a22deSSteven Rostedt
35390e7a22deSSteven Rostedt# PWD is a ktest.pl variable that will result in the process working
35400e7a22deSSteven Rostedt# directory that ktest.pl is executed in.
35410e7a22deSSteven Rostedt
35420e7a22deSSteven Rostedt# THIS_DIR is automatically assigned the PWD of the path that generated
35430e7a22deSSteven Rostedt# the config file. It is best to use this variable when assigning other
35440e7a22deSSteven Rostedt# directory paths within this directory. This allows you to easily
35450e7a22deSSteven Rostedt# move the test cases to other locations or to other machines.
35460e7a22deSSteven Rostedt#
35470e7a22deSSteven RostedtTHIS_DIR := $variable{"PWD"}
35480e7a22deSSteven Rostedt
35498d1491baSSteven Rostedt# Define each test with TEST_START
35508d1491baSSteven Rostedt# The config options below it will override the defaults
35518d1491baSSteven RostedtTEST_START
3552c4261d0fSSteven RostedtTEST_TYPE = $default{"TEST_TYPE"}
35538d1491baSSteven Rostedt
35548d1491baSSteven RostedtDEFAULTS
35558d1491baSSteven RostedtEOF
35568d1491baSSteven Rostedt;
35578d1491baSSteven Rostedt    close(OUT);
35588d1491baSSteven Rostedt}
35598d1491baSSteven Rostedtread_config $ktest_config;
35608d1491baSSteven Rostedt
356123715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) {
356223715c3cSSteven Rostedt    $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
356323715c3cSSteven Rostedt}
356423715c3cSSteven Rostedt
35658d1491baSSteven Rostedt# Append any configs entered in manually to the config file.
35668d1491baSSteven Rostedtmy @new_configs = keys %entered_configs;
35678d1491baSSteven Rostedtif ($#new_configs >= 0) {
35688d1491baSSteven Rostedt    print "\nAppending entered in configs to $ktest_config\n";
35698d1491baSSteven Rostedt    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
35708d1491baSSteven Rostedt    foreach my $config (@new_configs) {
35718d1491baSSteven Rostedt	print OUT "$config = $entered_configs{$config}\n";
35720e7a22deSSteven Rostedt	$opt{$config} = process_variables($entered_configs{$config});
35738d1491baSSteven Rostedt    }
35748d1491baSSteven Rostedt}
35752545eb61SSteven Rostedt
35762b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
35772b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
35782b7d9b21SSteven Rostedt}
35792545eb61SSteven Rostedt
35802b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
35812b7d9b21SSteven Rostedt
3582a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
3583a57419b3SSteven Rostedt
3584a57419b3SSteven Rostedt    if (!$i) {
3585a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
3586a57419b3SSteven Rostedt    } else {
3587a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
3588a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
3589a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
3590a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
3591a57419b3SSteven Rostedt	}
3592a57419b3SSteven Rostedt	doprint "\n";
3593a57419b3SSteven Rostedt    }
3594a57419b3SSteven Rostedt
35952b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
3596a57419b3SSteven Rostedt
3597a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
3598a57419b3SSteven Rostedt	    next if ($i != $1);
3599a57419b3SSteven Rostedt	} else {
3600a57419b3SSteven Rostedt	    next if ($i);
3601a57419b3SSteven Rostedt	}
3602a57419b3SSteven Rostedt
36032b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
36042b7d9b21SSteven Rostedt    }
3605a57419b3SSteven Rostedt}
36062545eb61SSteven Rostedt
36072a62512bSSteven Rostedtsub __set_test_option {
36085a391fbfSSteven Rostedt    my ($name, $i) = @_;
36095a391fbfSSteven Rostedt
36105a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
36115a391fbfSSteven Rostedt
36125a391fbfSSteven Rostedt    if (defined($opt{$option})) {
36135a391fbfSSteven Rostedt	return $opt{$option};
36145a391fbfSSteven Rostedt    }
36155a391fbfSSteven Rostedt
3616a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
3617a57419b3SSteven Rostedt	if ($i >= $test &&
3618a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
3619a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
3620a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
3621a57419b3SSteven Rostedt		return $opt{$option};
3622a57419b3SSteven Rostedt	    }
3623a57419b3SSteven Rostedt	}
3624a57419b3SSteven Rostedt    }
3625a57419b3SSteven Rostedt
36265a391fbfSSteven Rostedt    if (defined($opt{$name})) {
36275a391fbfSSteven Rostedt	return $opt{$name};
36285a391fbfSSteven Rostedt    }
36295a391fbfSSteven Rostedt
36305a391fbfSSteven Rostedt    return undef;
36315a391fbfSSteven Rostedt}
36325a391fbfSSteven Rostedt
36332a62512bSSteven Rostedtsub set_test_option {
36342a62512bSSteven Rostedt    my ($name, $i) = @_;
36352a62512bSSteven Rostedt
36362a62512bSSteven Rostedt    my $option = __set_test_option($name, $i);
36372a62512bSSteven Rostedt    return $option if (!defined($option));
36382a62512bSSteven Rostedt
363923715c3cSSteven Rostedt    return eval_option($option, $i);
36402a62512bSSteven Rostedt}
36412a62512bSSteven Rostedt
36422545eb61SSteven Rostedt# First we need to do is the builds
3643a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
36442545eb61SSteven Rostedt
36454ab1cce5SSteven Rostedt    # Do not reboot on failing test options
36464ab1cce5SSteven Rostedt    $no_reboot = 1;
3647759a3cc6SSteven Rostedt    $reboot_success = 0;
36484ab1cce5SSteven Rostedt
3649683a3e64SSteven Rostedt    $have_version = 0;
3650683a3e64SSteven Rostedt
3651576f627cSSteven Rostedt    $iteration = $i;
3652576f627cSSteven Rostedt
3653c1434dccSSteven Rostedt    undef %force_config;
3654c1434dccSSteven Rostedt
3655a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
3656a75fececSSteven Rostedt
36579cc9e091SSteven Rostedt    # Load all the options into their mapped variable names
36589cc9e091SSteven Rostedt    foreach my $opt (keys %option_map) {
36599cc9e091SSteven Rostedt	${$option_map{$opt}} = set_test_option($opt, $i);
36609cc9e091SSteven Rostedt    }
3661b5f4aea6SSteven Rostedt
366235ce5952SSteven Rostedt    $start_minconfig_defined = 1;
366335ce5952SSteven Rostedt
3664921ed4c7SSteven Rostedt    # The first test may override the PRE_KTEST option
3665921ed4c7SSteven Rostedt    if (defined($pre_ktest) && $i == 1) {
3666921ed4c7SSteven Rostedt	doprint "\n";
3667921ed4c7SSteven Rostedt	run_command $pre_ktest;
3668921ed4c7SSteven Rostedt    }
3669921ed4c7SSteven Rostedt
3670921ed4c7SSteven Rostedt    # Any test can override the POST_KTEST option
3671921ed4c7SSteven Rostedt    # The last test takes precedence.
3672921ed4c7SSteven Rostedt    if (defined($post_ktest)) {
3673921ed4c7SSteven Rostedt	$final_post_ktest = $post_ktest;
3674921ed4c7SSteven Rostedt    }
3675921ed4c7SSteven Rostedt
36764c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
367735ce5952SSteven Rostedt	$start_minconfig_defined = 0;
36784c4ab120SSteven Rostedt	$start_minconfig = $minconfig;
36794c4ab120SSteven Rostedt    }
36804c4ab120SSteven Rostedt
3681a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
3682a75fececSSteven Rostedt
3683a908a665SAndrew Jones    foreach my $dir ($tmpdir, $outputdir) {
3684a908a665SAndrew Jones	if (!-d $dir) {
3685a908a665SAndrew Jones	    mkpath($dir) or
3686a908a665SAndrew Jones		die "can't create $dir";
3687a908a665SAndrew Jones	}
3688a75fececSSteven Rostedt    }
3689a75fececSSteven Rostedt
3690e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
3691e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
3692e48c5293SSteven Rostedt
3693a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
3694a9dd5d63SRabin Vincent    $testlog = "$tmpdir/testlog-$machine";
3695a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
3696a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
369751ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
3698a75fececSSteven Rostedt
3699bb8474b1SSteven Rostedt    if (!$buildonly) {
3700bb8474b1SSteven Rostedt	$target = "$ssh_user\@$machine";
3701a75fececSSteven Rostedt	if ($reboot_type eq "grub") {
3702576f627cSSteven Rostedt	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3703a75fececSSteven Rostedt	}
3704bb8474b1SSteven Rostedt    }
3705a75fececSSteven Rostedt
3706a75fececSSteven Rostedt    my $run_type = $build_type;
3707a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
3708b5f4aea6SSteven Rostedt	$run_type = $patchcheck_type;
3709a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
3710b5f4aea6SSteven Rostedt	$run_type = $bisect_type;
37110a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
3712b5f4aea6SSteven Rostedt	$run_type = $config_bisect_type;
3713a75fececSSteven Rostedt    }
3714a75fececSSteven Rostedt
37154c4ab120SSteven Rostedt    if ($test_type eq "make_min_config") {
37164c4ab120SSteven Rostedt	$run_type = "";
37174c4ab120SSteven Rostedt    }
37184c4ab120SSteven Rostedt
3719a75fececSSteven Rostedt    # mistake in config file?
3720a75fececSSteven Rostedt    if (!defined($run_type)) {
3721a75fececSSteven Rostedt	$run_type = "ERROR";
3722a75fececSSteven Rostedt    }
37232545eb61SSteven Rostedt
3724e0a8742eSSteven Rostedt    my $installme = "";
3725e0a8742eSSteven Rostedt    $installme = " no_install" if ($no_install);
3726e0a8742eSSteven Rostedt
37272545eb61SSteven Rostedt    doprint "\n\n";
3728e0a8742eSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
37297faafbd6SSteven Rostedt
3730921ed4c7SSteven Rostedt    if (defined($pre_test)) {
3731921ed4c7SSteven Rostedt	run_command $pre_test;
3732921ed4c7SSteven Rostedt    }
3733921ed4c7SSteven Rostedt
37347faafbd6SSteven Rostedt    unlink $dmesg;
37357faafbd6SSteven Rostedt    unlink $buildlog;
3736a9dd5d63SRabin Vincent    unlink $testlog;
37372545eb61SSteven Rostedt
3738250bae8bSSteven Rostedt    if (defined($addconfig)) {
3739250bae8bSSteven Rostedt	my $min = $minconfig;
37402b7d9b21SSteven Rostedt	if (!defined($minconfig)) {
3741250bae8bSSteven Rostedt	    $min = "";
3742250bae8bSSteven Rostedt	}
3743250bae8bSSteven Rostedt	run_command "cat $addconfig $min > $tmpdir/add_config" or
37442b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
37459be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
37462b7d9b21SSteven Rostedt    }
37472b7d9b21SSteven Rostedt
37486c5ee0beSSteven Rostedt    if (defined($checkout)) {
37496c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
37506c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
37516c5ee0beSSteven Rostedt    }
37526c5ee0beSSteven Rostedt
3753759a3cc6SSteven Rostedt    $no_reboot = 0;
3754759a3cc6SSteven Rostedt
3755648a182cSSteven Rostedt    # A test may opt to not reboot the box
3756648a182cSSteven Rostedt    if ($reboot_on_success) {
3757759a3cc6SSteven Rostedt	$reboot_success = 1;
3758648a182cSSteven Rostedt    }
37594ab1cce5SSteven Rostedt
3760a75fececSSteven Rostedt    if ($test_type eq "bisect") {
37615f9b6cedSSteven Rostedt	bisect $i;
37625f9b6cedSSteven Rostedt	next;
37630a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
37640a05c769SSteven Rostedt	config_bisect $i;
37650a05c769SSteven Rostedt	next;
3766a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
37676c5ee0beSSteven Rostedt	patchcheck $i;
37686c5ee0beSSteven Rostedt	next;
37694c4ab120SSteven Rostedt    } elsif ($test_type eq "make_min_config") {
37704c4ab120SSteven Rostedt	make_min_config $i;
37714c4ab120SSteven Rostedt	next;
37725f9b6cedSSteven Rostedt    }
37735f9b6cedSSteven Rostedt
37747faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
37757faafbd6SSteven Rostedt	build $build_type or next;
37762545eb61SSteven Rostedt    }
37772545eb61SSteven Rostedt
3778cd8e368fSSteven Rostedt    if ($test_type eq "install") {
3779cd8e368fSSteven Rostedt	get_version;
3780cd8e368fSSteven Rostedt	install;
3781cd8e368fSSteven Rostedt	success $i;
3782cd8e368fSSteven Rostedt	next;
3783cd8e368fSSteven Rostedt    }
3784cd8e368fSSteven Rostedt
3785a75fececSSteven Rostedt    if ($test_type ne "build") {
37867faafbd6SSteven Rostedt	my $failed = 0;
3787ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
3788a75fececSSteven Rostedt
3789a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
37907faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
37915a391fbfSSteven Rostedt	}
37927faafbd6SSteven Rostedt	end_monitor;
37937faafbd6SSteven Rostedt	next if ($failed);
3794a75fececSSteven Rostedt    }
37955a391fbfSSteven Rostedt
37965f9b6cedSSteven Rostedt    success $i;
379775c3fda7SSteven Rostedt}
37982545eb61SSteven Rostedt
3799921ed4c7SSteven Rostedtif (defined($final_post_ktest)) {
3800921ed4c7SSteven Rostedt    run_command $final_post_ktest;
3801921ed4c7SSteven Rostedt}
3802921ed4c7SSteven Rostedt
38035c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
380475c3fda7SSteven Rostedt    halt;
3805759a3cc6SSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) {
3806bc7c5803SSteven Rostedt    reboot_to_good;
3807648a182cSSteven Rostedt} elsif (defined($switch_to_good)) {
3808648a182cSSteven Rostedt    # still need to get to the good kernel
3809648a182cSSteven Rostedt    run_command $switch_to_good;
38105c42fc5bSSteven Rostedt}
381175c3fda7SSteven Rostedt
3812648a182cSSteven Rostedt
3813e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
3814e48c5293SSteven Rostedt
38152545eb61SSteven Rostedtexit 0;
3816