xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision 752d96657cf4844793ac4d62d02a0733396ef16c)
12545eb61SSteven Rostedt#!/usr/bin/perl -w
2d6ce2a0bSSteven Rostedt#
3cce1dac8SUwe Kleine-König# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
4d6ce2a0bSSteven Rostedt# Licensed under the terms of the GNU GPL License version 2
5d6ce2a0bSSteven Rostedt#
62545eb61SSteven Rostedt
72545eb61SSteven Rostedtuse strict;
82545eb61SSteven Rostedtuse IPC::Open2;
92545eb61SSteven Rostedtuse Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
107faafbd6SSteven Rostedtuse File::Path qw(mkpath);
117faafbd6SSteven Rostedtuse File::Copy qw(cp);
122545eb61SSteven Rostedtuse FileHandle;
132545eb61SSteven Rostedt
14e48c5293SSteven Rostedtmy $VERSION = "0.2";
15e48c5293SSteven Rostedt
162545eb61SSteven Rostedt$| = 1;
172545eb61SSteven Rostedt
182545eb61SSteven Rostedtmy %opt;
19a57419b3SSteven Rostedtmy %repeat_tests;
20a57419b3SSteven Rostedtmy %repeats;
212545eb61SSteven Rostedt
222545eb61SSteven Rostedt#default opts
234f43e0dcSSteven Rostedtmy %default = (
244f43e0dcSSteven Rostedt    "NUM_TESTS"			=> 1,
254f43e0dcSSteven Rostedt    "TEST_TYPE"			=> "build",
264f43e0dcSSteven Rostedt    "BUILD_TYPE"		=> "randconfig",
274f43e0dcSSteven Rostedt    "MAKE_CMD"			=> "make",
284f43e0dcSSteven Rostedt    "TIMEOUT"			=> 120,
294f43e0dcSSteven Rostedt    "TMP_DIR"			=> "/tmp/ktest/\${MACHINE}",
304f43e0dcSSteven Rostedt    "SLEEP_TIME"		=> 60,	# sleep time between tests
314f43e0dcSSteven Rostedt    "BUILD_NOCLEAN"		=> 0,
324f43e0dcSSteven Rostedt    "REBOOT_ON_ERROR"		=> 0,
334f43e0dcSSteven Rostedt    "POWEROFF_ON_ERROR"		=> 0,
344f43e0dcSSteven Rostedt    "REBOOT_ON_SUCCESS"		=> 1,
354f43e0dcSSteven Rostedt    "POWEROFF_ON_SUCCESS"	=> 0,
364f43e0dcSSteven Rostedt    "BUILD_OPTIONS"		=> "",
374f43e0dcSSteven Rostedt    "BISECT_SLEEP_TIME"		=> 60,   # sleep time between bisects
384f43e0dcSSteven Rostedt    "PATCHCHECK_SLEEP_TIME"	=> 60, # sleep time between patch checks
394f43e0dcSSteven Rostedt    "CLEAR_LOG"			=> 0,
404f43e0dcSSteven Rostedt    "BISECT_MANUAL"		=> 0,
414f43e0dcSSteven Rostedt    "BISECT_SKIP"		=> 1,
42ccc513b6SSteven Rostedt    "MIN_CONFIG_TYPE"		=> "boot",
434f43e0dcSSteven Rostedt    "SUCCESS_LINE"		=> "login:",
444f43e0dcSSteven Rostedt    "DETECT_TRIPLE_FAULT"	=> 1,
454f43e0dcSSteven Rostedt    "NO_INSTALL"		=> 0,
464f43e0dcSSteven Rostedt    "BOOTED_TIMEOUT"		=> 1,
474f43e0dcSSteven Rostedt    "DIE_ON_FAILURE"		=> 1,
484f43e0dcSSteven Rostedt    "SSH_EXEC"			=> "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND",
494f43e0dcSSteven Rostedt    "SCP_TO_TARGET"		=> "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE",
5002ad2617SSteven Rostedt    "SCP_TO_TARGET_INSTALL"	=> "\${SCP_TO_TARGET}",
514f43e0dcSSteven Rostedt    "REBOOT"			=> "ssh \$SSH_USER\@\$MACHINE reboot",
524f43e0dcSSteven Rostedt    "STOP_AFTER_SUCCESS"	=> 10,
534f43e0dcSSteven Rostedt    "STOP_AFTER_FAILURE"	=> 60,
544f43e0dcSSteven Rostedt    "STOP_TEST_AFTER"		=> 600,
55407b95b7SSteven Rostedt    "MAX_MONITOR_WAIT"		=> 1800,
56a15ba913SSteven Rostedt    "GRUB_REBOOT"		=> "grub2-reboot",
577786954cSSteven Rostedt    "SYSLINUX"			=> "extlinux",
587786954cSSteven Rostedt    "SYSLINUX_PATH"		=> "/boot/extlinux",
59600bbf0aSSteven Rostedt
60600bbf0aSSteven Rostedt# required, and we will ask users if they don't have them but we keep the default
61600bbf0aSSteven Rostedt# value something that is common.
624f43e0dcSSteven Rostedt    "REBOOT_TYPE"		=> "grub",
634f43e0dcSSteven Rostedt    "LOCALVERSION"		=> "-test",
644f43e0dcSSteven Rostedt    "SSH_USER"			=> "root",
654f43e0dcSSteven Rostedt    "BUILD_TARGET"	 	=> "arch/x86/boot/bzImage",
664f43e0dcSSteven Rostedt    "TARGET_IMAGE"		=> "/boot/vmlinuz-test",
679cc9e091SSteven Rostedt
689cc9e091SSteven Rostedt    "LOG_FILE"			=> undef,
699cc9e091SSteven Rostedt    "IGNORE_UNUSED"		=> 0,
704f43e0dcSSteven Rostedt);
712545eb61SSteven Rostedt
728d1491baSSteven Rostedtmy $ktest_config;
732545eb61SSteven Rostedtmy $version;
74683a3e64SSteven Rostedtmy $have_version = 0;
75a75fececSSteven Rostedtmy $machine;
76e48c5293SSteven Rostedtmy $ssh_user;
77a75fececSSteven Rostedtmy $tmpdir;
78a75fececSSteven Rostedtmy $builddir;
79a75fececSSteven Rostedtmy $outputdir;
8051ad1dd1SSteven Rostedtmy $output_config;
81a75fececSSteven Rostedtmy $test_type;
827faafbd6SSteven Rostedtmy $build_type;
83a75fececSSteven Rostedtmy $build_options;
84921ed4c7SSteven Rostedtmy $final_post_ktest;
85921ed4c7SSteven Rostedtmy $pre_ktest;
86921ed4c7SSteven Rostedtmy $post_ktest;
87921ed4c7SSteven Rostedtmy $pre_test;
88921ed4c7SSteven Rostedtmy $post_test;
890bd6c1a3SSteven Rostedtmy $pre_build;
900bd6c1a3SSteven Rostedtmy $post_build;
910bd6c1a3SSteven Rostedtmy $pre_build_die;
920bd6c1a3SSteven Rostedtmy $post_build_die;
93a75fececSSteven Rostedtmy $reboot_type;
94a75fececSSteven Rostedtmy $reboot_script;
95a75fececSSteven Rostedtmy $power_cycle;
96e48c5293SSteven Rostedtmy $reboot;
97a75fececSSteven Rostedtmy $reboot_on_error;
98bc7c5803SSteven Rostedtmy $switch_to_good;
99bc7c5803SSteven Rostedtmy $switch_to_test;
100a75fececSSteven Rostedtmy $poweroff_on_error;
101648a182cSSteven Rostedtmy $reboot_on_success;
102a75fececSSteven Rostedtmy $die_on_failure;
103576f627cSSteven Rostedtmy $powercycle_after_reboot;
104576f627cSSteven Rostedtmy $poweroff_after_halt;
105407b95b7SSteven Rostedtmy $max_monitor_wait;
106e48c5293SSteven Rostedtmy $ssh_exec;
107e48c5293SSteven Rostedtmy $scp_to_target;
10802ad2617SSteven Rostedtmy $scp_to_target_install;
109a75fececSSteven Rostedtmy $power_off;
110a75fececSSteven Rostedtmy $grub_menu;
111*752d9665SSteven Rostedt (Red Hat)my $last_grub_menu;
112a15ba913SSteven Rostedtmy $grub_file;
1132545eb61SSteven Rostedtmy $grub_number;
114a15ba913SSteven Rostedtmy $grub_reboot;
1157786954cSSteven Rostedtmy $syslinux;
1167786954cSSteven Rostedtmy $syslinux_path;
1177786954cSSteven Rostedtmy $syslinux_label;
1182545eb61SSteven Rostedtmy $target;
1192545eb61SSteven Rostedtmy $make;
120e5c2ec11SSteven Rostedtmy $pre_install;
1218b37ca8cSSteven Rostedtmy $post_install;
122e0a8742eSSteven Rostedtmy $no_install;
1235c42fc5bSSteven Rostedtmy $noclean;
1245f9b6cedSSteven Rostedtmy $minconfig;
1254c4ab120SSteven Rostedtmy $start_minconfig;
12635ce5952SSteven Rostedtmy $start_minconfig_defined;
1274c4ab120SSteven Rostedtmy $output_minconfig;
128ccc513b6SSteven Rostedtmy $minconfig_type;
12943de3316SSteven Rostedtmy $use_output_minconfig;
1304283b169SSteven Rostedt (Red Hat)my $warnings_file;
1314c4ab120SSteven Rostedtmy $ignore_config;
132be405f95SSteven Rostedtmy $ignore_errors;
1332b7d9b21SSteven Rostedtmy $addconfig;
1345f9b6cedSSteven Rostedtmy $in_bisect = 0;
135b5f4aea6SSteven Rostedtmy $bisect_bad_commit = "";
136d6ce2a0bSSteven Rostedtmy $reverse_bisect;
137c960bb9fSSteven Rostedtmy $bisect_manual;
138c23dca7cSSteven Rostedtmy $bisect_skip;
13930f75da5SSteven Rostedtmy $config_bisect_good;
140c5dacb88SSteven Rostedtmy $bisect_ret_good;
141c5dacb88SSteven Rostedtmy $bisect_ret_bad;
142c5dacb88SSteven Rostedtmy $bisect_ret_skip;
143c5dacb88SSteven Rostedtmy $bisect_ret_abort;
144c5dacb88SSteven Rostedtmy $bisect_ret_default;
1456c5ee0beSSteven Rostedtmy $in_patchcheck = 0;
1465a391fbfSSteven Rostedtmy $run_test;
1476c5ee0beSSteven Rostedtmy $redirect;
1487faafbd6SSteven Rostedtmy $buildlog;
149a9dd5d63SRabin Vincentmy $testlog;
1507faafbd6SSteven Rostedtmy $dmesg;
1517faafbd6SSteven Rostedtmy $monitor_fp;
1527faafbd6SSteven Rostedtmy $monitor_pid;
1537faafbd6SSteven Rostedtmy $monitor_cnt = 0;
154a75fececSSteven Rostedtmy $sleep_time;
155a75fececSSteven Rostedtmy $bisect_sleep_time;
15627d934b2SSteven Rostedtmy $patchcheck_sleep_time;
1571990207dSSteven Rostedtmy $ignore_warnings;
158a75fececSSteven Rostedtmy $store_failures;
159de5b6e3bSRabin Vincentmy $store_successes;
1609064af52SSteven Rostedtmy $test_name;
161a75fececSSteven Rostedtmy $timeout;
162a75fececSSteven Rostedtmy $booted_timeout;
163f1a5b962SSteven Rostedtmy $detect_triplefault;
164a75fececSSteven Rostedtmy $console;
1652b803365SSteven Rostedtmy $reboot_success_line;
166a75fececSSteven Rostedtmy $success_line;
1671c8a617aSSteven Rostedtmy $stop_after_success;
1681c8a617aSSteven Rostedtmy $stop_after_failure;
1692d01b26aSSteven Rostedtmy $stop_test_after;
170a75fececSSteven Rostedtmy $build_target;
171a75fececSSteven Rostedtmy $target_image;
172b5f4aea6SSteven Rostedtmy $checkout;
173a75fececSSteven Rostedtmy $localversion;
174576f627cSSteven Rostedtmy $iteration = 0;
175e48c5293SSteven Rostedtmy $successes = 0;
1762545eb61SSteven Rostedt
177b5f4aea6SSteven Rostedtmy $bisect_good;
178b5f4aea6SSteven Rostedtmy $bisect_bad;
179b5f4aea6SSteven Rostedtmy $bisect_type;
180b5f4aea6SSteven Rostedtmy $bisect_start;
181b5f4aea6SSteven Rostedtmy $bisect_replay;
182b5f4aea6SSteven Rostedtmy $bisect_files;
183b5f4aea6SSteven Rostedtmy $bisect_reverse;
184b5f4aea6SSteven Rostedtmy $bisect_check;
185b5f4aea6SSteven Rostedt
186b5f4aea6SSteven Rostedtmy $config_bisect;
187b5f4aea6SSteven Rostedtmy $config_bisect_type;
188b0918612SSteven Rostedtmy $config_bisect_check;
189b5f4aea6SSteven Rostedt
190b5f4aea6SSteven Rostedtmy $patchcheck_type;
191b5f4aea6SSteven Rostedtmy $patchcheck_start;
192b5f4aea6SSteven Rostedtmy $patchcheck_end;
193b5f4aea6SSteven Rostedt
194165708b2SSteven Rostedt# set when a test is something other that just building or install
195bb8474b1SSteven Rostedt# which would require more options.
196bb8474b1SSteven Rostedtmy $buildonly = 1;
197bb8474b1SSteven Rostedt
1984283b169SSteven Rostedt (Red Hat)# tell build not to worry about warnings, even when WARNINGS_FILE is set
1994283b169SSteven Rostedt (Red Hat)my $warnings_ok = 0;
2004283b169SSteven Rostedt (Red Hat)
201dbd3783bSSteven Rostedt# set when creating a new config
202dbd3783bSSteven Rostedtmy $newconfig = 0;
203dbd3783bSSteven Rostedt
2048d1491baSSteven Rostedtmy %entered_configs;
2058d1491baSSteven Rostedtmy %config_help;
20677d942ceSSteven Rostedtmy %variable;
207cf79fab6SSteven Rostedt
208cf79fab6SSteven Rostedt# force_config is the list of configs that we force enabled (or disabled)
209cf79fab6SSteven Rostedt# in a .config file. The MIN_CONFIG and ADD_CONFIG configs.
210fcb3f16aSSteven Rostedtmy %force_config;
2118d1491baSSteven Rostedt
2124ab1cce5SSteven Rostedt# do not force reboots on config problems
2134ab1cce5SSteven Rostedtmy $no_reboot = 1;
2144ab1cce5SSteven Rostedt
215759a3cc6SSteven Rostedt# reboot on success
216759a3cc6SSteven Rostedtmy $reboot_success = 0;
217759a3cc6SSteven Rostedt
2189cc9e091SSteven Rostedtmy %option_map = (
2199cc9e091SSteven Rostedt    "MACHINE"			=> \$machine,
2209cc9e091SSteven Rostedt    "SSH_USER"			=> \$ssh_user,
2219cc9e091SSteven Rostedt    "TMP_DIR"			=> \$tmpdir,
2229cc9e091SSteven Rostedt    "OUTPUT_DIR"		=> \$outputdir,
2239cc9e091SSteven Rostedt    "BUILD_DIR"			=> \$builddir,
2249cc9e091SSteven Rostedt    "TEST_TYPE"			=> \$test_type,
225921ed4c7SSteven Rostedt    "PRE_KTEST"			=> \$pre_ktest,
226921ed4c7SSteven Rostedt    "POST_KTEST"		=> \$post_ktest,
227921ed4c7SSteven Rostedt    "PRE_TEST"			=> \$pre_test,
228921ed4c7SSteven Rostedt    "POST_TEST"			=> \$post_test,
2299cc9e091SSteven Rostedt    "BUILD_TYPE"		=> \$build_type,
2309cc9e091SSteven Rostedt    "BUILD_OPTIONS"		=> \$build_options,
2319cc9e091SSteven Rostedt    "PRE_BUILD"			=> \$pre_build,
2329cc9e091SSteven Rostedt    "POST_BUILD"		=> \$post_build,
2339cc9e091SSteven Rostedt    "PRE_BUILD_DIE"		=> \$pre_build_die,
2349cc9e091SSteven Rostedt    "POST_BUILD_DIE"		=> \$post_build_die,
2359cc9e091SSteven Rostedt    "POWER_CYCLE"		=> \$power_cycle,
2369cc9e091SSteven Rostedt    "REBOOT"			=> \$reboot,
2379cc9e091SSteven Rostedt    "BUILD_NOCLEAN"		=> \$noclean,
2389cc9e091SSteven Rostedt    "MIN_CONFIG"		=> \$minconfig,
2399cc9e091SSteven Rostedt    "OUTPUT_MIN_CONFIG"		=> \$output_minconfig,
2409cc9e091SSteven Rostedt    "START_MIN_CONFIG"		=> \$start_minconfig,
241ccc513b6SSteven Rostedt    "MIN_CONFIG_TYPE"		=> \$minconfig_type,
24243de3316SSteven Rostedt    "USE_OUTPUT_MIN_CONFIG"	=> \$use_output_minconfig,
2434283b169SSteven Rostedt (Red Hat)    "WARNINGS_FILE"		=> \$warnings_file,
2449cc9e091SSteven Rostedt    "IGNORE_CONFIG"		=> \$ignore_config,
2459cc9e091SSteven Rostedt    "TEST"			=> \$run_test,
2469cc9e091SSteven Rostedt    "ADD_CONFIG"		=> \$addconfig,
2479cc9e091SSteven Rostedt    "REBOOT_TYPE"		=> \$reboot_type,
2489cc9e091SSteven Rostedt    "GRUB_MENU"			=> \$grub_menu,
249a15ba913SSteven Rostedt    "GRUB_FILE"			=> \$grub_file,
250a15ba913SSteven Rostedt    "GRUB_REBOOT"		=> \$grub_reboot,
2517786954cSSteven Rostedt    "SYSLINUX"			=> \$syslinux,
2527786954cSSteven Rostedt    "SYSLINUX_PATH"		=> \$syslinux_path,
2537786954cSSteven Rostedt    "SYSLINUX_LABEL"		=> \$syslinux_label,
254e5c2ec11SSteven Rostedt    "PRE_INSTALL"		=> \$pre_install,
2559cc9e091SSteven Rostedt    "POST_INSTALL"		=> \$post_install,
2569cc9e091SSteven Rostedt    "NO_INSTALL"		=> \$no_install,
2579cc9e091SSteven Rostedt    "REBOOT_SCRIPT"		=> \$reboot_script,
2589cc9e091SSteven Rostedt    "REBOOT_ON_ERROR"		=> \$reboot_on_error,
2599cc9e091SSteven Rostedt    "SWITCH_TO_GOOD"		=> \$switch_to_good,
2609cc9e091SSteven Rostedt    "SWITCH_TO_TEST"		=> \$switch_to_test,
2619cc9e091SSteven Rostedt    "POWEROFF_ON_ERROR"		=> \$poweroff_on_error,
262648a182cSSteven Rostedt    "REBOOT_ON_SUCCESS"		=> \$reboot_on_success,
2639cc9e091SSteven Rostedt    "DIE_ON_FAILURE"		=> \$die_on_failure,
2649cc9e091SSteven Rostedt    "POWER_OFF"			=> \$power_off,
2659cc9e091SSteven Rostedt    "POWERCYCLE_AFTER_REBOOT"	=> \$powercycle_after_reboot,
2669cc9e091SSteven Rostedt    "POWEROFF_AFTER_HALT"	=> \$poweroff_after_halt,
267407b95b7SSteven Rostedt    "MAX_MONITOR_WAIT"		=> \$max_monitor_wait,
2689cc9e091SSteven Rostedt    "SLEEP_TIME"		=> \$sleep_time,
2699cc9e091SSteven Rostedt    "BISECT_SLEEP_TIME"		=> \$bisect_sleep_time,
2709cc9e091SSteven Rostedt    "PATCHCHECK_SLEEP_TIME"	=> \$patchcheck_sleep_time,
2719cc9e091SSteven Rostedt    "IGNORE_WARNINGS"		=> \$ignore_warnings,
272be405f95SSteven Rostedt    "IGNORE_ERRORS"		=> \$ignore_errors,
2739cc9e091SSteven Rostedt    "BISECT_MANUAL"		=> \$bisect_manual,
2749cc9e091SSteven Rostedt    "BISECT_SKIP"		=> \$bisect_skip,
2759cc9e091SSteven Rostedt    "CONFIG_BISECT_GOOD"	=> \$config_bisect_good,
2769cc9e091SSteven Rostedt    "BISECT_RET_GOOD"		=> \$bisect_ret_good,
2779cc9e091SSteven Rostedt    "BISECT_RET_BAD"		=> \$bisect_ret_bad,
2789cc9e091SSteven Rostedt    "BISECT_RET_SKIP"		=> \$bisect_ret_skip,
2799cc9e091SSteven Rostedt    "BISECT_RET_ABORT"		=> \$bisect_ret_abort,
2809cc9e091SSteven Rostedt    "BISECT_RET_DEFAULT"	=> \$bisect_ret_default,
2819cc9e091SSteven Rostedt    "STORE_FAILURES"		=> \$store_failures,
2829cc9e091SSteven Rostedt    "STORE_SUCCESSES"		=> \$store_successes,
2839cc9e091SSteven Rostedt    "TEST_NAME"			=> \$test_name,
2849cc9e091SSteven Rostedt    "TIMEOUT"			=> \$timeout,
2859cc9e091SSteven Rostedt    "BOOTED_TIMEOUT"		=> \$booted_timeout,
2869cc9e091SSteven Rostedt    "CONSOLE"			=> \$console,
2879cc9e091SSteven Rostedt    "DETECT_TRIPLE_FAULT"	=> \$detect_triplefault,
2889cc9e091SSteven Rostedt    "SUCCESS_LINE"		=> \$success_line,
2899cc9e091SSteven Rostedt    "REBOOT_SUCCESS_LINE"	=> \$reboot_success_line,
2909cc9e091SSteven Rostedt    "STOP_AFTER_SUCCESS"	=> \$stop_after_success,
2919cc9e091SSteven Rostedt    "STOP_AFTER_FAILURE"	=> \$stop_after_failure,
2929cc9e091SSteven Rostedt    "STOP_TEST_AFTER"		=> \$stop_test_after,
2939cc9e091SSteven Rostedt    "BUILD_TARGET"		=> \$build_target,
2949cc9e091SSteven Rostedt    "SSH_EXEC"			=> \$ssh_exec,
2959cc9e091SSteven Rostedt    "SCP_TO_TARGET"		=> \$scp_to_target,
29602ad2617SSteven Rostedt    "SCP_TO_TARGET_INSTALL"	=> \$scp_to_target_install,
2979cc9e091SSteven Rostedt    "CHECKOUT"			=> \$checkout,
2989cc9e091SSteven Rostedt    "TARGET_IMAGE"		=> \$target_image,
2999cc9e091SSteven Rostedt    "LOCALVERSION"		=> \$localversion,
3009cc9e091SSteven Rostedt
3019cc9e091SSteven Rostedt    "BISECT_GOOD"		=> \$bisect_good,
3029cc9e091SSteven Rostedt    "BISECT_BAD"		=> \$bisect_bad,
3039cc9e091SSteven Rostedt    "BISECT_TYPE"		=> \$bisect_type,
3049cc9e091SSteven Rostedt    "BISECT_START"		=> \$bisect_start,
3059cc9e091SSteven Rostedt    "BISECT_REPLAY"		=> \$bisect_replay,
3069cc9e091SSteven Rostedt    "BISECT_FILES"		=> \$bisect_files,
3079cc9e091SSteven Rostedt    "BISECT_REVERSE"		=> \$bisect_reverse,
3089cc9e091SSteven Rostedt    "BISECT_CHECK"		=> \$bisect_check,
3099cc9e091SSteven Rostedt
3109cc9e091SSteven Rostedt    "CONFIG_BISECT"		=> \$config_bisect,
3119cc9e091SSteven Rostedt    "CONFIG_BISECT_TYPE"	=> \$config_bisect_type,
312b0918612SSteven Rostedt    "CONFIG_BISECT_CHECK"	=> \$config_bisect_check,
3139cc9e091SSteven Rostedt
3149cc9e091SSteven Rostedt    "PATCHCHECK_TYPE"		=> \$patchcheck_type,
3159cc9e091SSteven Rostedt    "PATCHCHECK_START"		=> \$patchcheck_start,
3169cc9e091SSteven Rostedt    "PATCHCHECK_END"		=> \$patchcheck_end,
3179cc9e091SSteven Rostedt);
3189cc9e091SSteven Rostedt
3199cc9e091SSteven Rostedt# Options may be used by other options, record them.
3209cc9e091SSteven Rostedtmy %used_options;
3219cc9e091SSteven Rostedt
3227bf51073SSteven Rostedt# default variables that can be used
3237bf51073SSteven Rostedtchomp ($variable{"PWD"} = `pwd`);
3247bf51073SSteven Rostedt
3258d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF"
3268d1491baSSteven Rostedt The machine hostname that you will test.
327bb8474b1SSteven Rostedt For build only tests, it is still needed to differentiate log files.
3288d1491baSSteven RostedtEOF
3298d1491baSSteven Rostedt    ;
3308d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF"
3318d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user
3328d1491baSSteven Rostedt  (most likely root, since you need privileged operations)
3338d1491baSSteven RostedtEOF
3348d1491baSSteven Rostedt    ;
3358d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF"
3368d1491baSSteven Rostedt The directory that contains the Linux source code (full path).
3370e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
3380e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
3398d1491baSSteven RostedtEOF
3408d1491baSSteven Rostedt    ;
3418d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF"
3428d1491baSSteven Rostedt The directory that the objects will be built (full path).
3438d1491baSSteven Rostedt (can not be same as BUILD_DIR)
3440e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
3450e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
3468d1491baSSteven RostedtEOF
3478d1491baSSteven Rostedt    ;
3488d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF"
3498d1491baSSteven Rostedt The location of the compiled file to copy to the target.
3508d1491baSSteven Rostedt (relative to OUTPUT_DIR)
3518d1491baSSteven RostedtEOF
3528d1491baSSteven Rostedt    ;
353dbd3783bSSteven Rostedt$config_help{"BUILD_OPTIONS"} = << "EOF"
354dbd3783bSSteven Rostedt Options to add to \"make\" when building.
355dbd3783bSSteven Rostedt i.e.  -j20
356dbd3783bSSteven RostedtEOF
357dbd3783bSSteven Rostedt    ;
3588d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF"
3598d1491baSSteven Rostedt The place to put your image on the test machine.
3608d1491baSSteven RostedtEOF
3618d1491baSSteven Rostedt    ;
3628d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF"
3638d1491baSSteven Rostedt A script or command to reboot the box.
3648d1491baSSteven Rostedt
3658d1491baSSteven Rostedt Here is a digital loggers power switch example
3668d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
3678d1491baSSteven Rostedt
3688d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host
3698d1491baSSteven Rostedt with the name "Guest".
3708d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
3718d1491baSSteven RostedtEOF
3728d1491baSSteven Rostedt    ;
3738d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF"
3748d1491baSSteven Rostedt The script or command that reads the console
3758d1491baSSteven Rostedt
3768d1491baSSteven Rostedt  If you use ttywatch server, something like the following would work.
3778d1491baSSteven RostedtCONSOLE = nc -d localhost 3001
3788d1491baSSteven Rostedt
3798d1491baSSteven Rostedt For a virtual machine with guest name "Guest".
3808d1491baSSteven RostedtCONSOLE =  virsh console Guest
3818d1491baSSteven RostedtEOF
3828d1491baSSteven Rostedt    ;
3838d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF"
3848d1491baSSteven Rostedt Required version ending to differentiate the test
3858d1491baSSteven Rostedt from other linux builds on the system.
3868d1491baSSteven RostedtEOF
3878d1491baSSteven Rostedt    ;
3888d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF"
3898d1491baSSteven Rostedt Way to reboot the box to the test kernel.
3907786954cSSteven Rostedt Only valid options so far are "grub", "grub2", "syslinux", and "script".
3918d1491baSSteven Rostedt
3928d1491baSSteven Rostedt If you specify grub, it will assume grub version 1
3938d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
3948d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not
3958d1491baSSteven Rostedt your setup, then specify "script" and have a command or script
3968d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target.
3978d1491baSSteven Rostedt
3988d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually.
3998d1491baSSteven Rostedt The test will not modify that file.
400a15ba913SSteven Rostedt
401a15ba913SSteven Rostedt If you specify grub2, then you also need to specify both \$GRUB_MENU
402a15ba913SSteven Rostedt and \$GRUB_FILE.
4037786954cSSteven Rostedt
4047786954cSSteven Rostedt If you specify syslinux, then you may use SYSLINUX to define the syslinux
4057786954cSSteven Rostedt command (defaults to extlinux), and SYSLINUX_PATH to specify the path to
4067786954cSSteven Rostedt the syslinux install (defaults to /boot/extlinux). But you have to specify
4077786954cSSteven Rostedt SYSLINUX_LABEL to define the label to boot to for the test kernel.
4088d1491baSSteven RostedtEOF
4098d1491baSSteven Rostedt    ;
4108d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF"
4118d1491baSSteven Rostedt The grub title name for the test kernel to boot
412a15ba913SSteven Rostedt (Only mandatory if REBOOT_TYPE = grub or grub2)
4138d1491baSSteven Rostedt
4148d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to
4158d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search
4168d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to
4178d1491baSSteven Rostedt reboot into.
4188d1491baSSteven Rostedt
4198d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has:
4208d1491baSSteven Rostedt title Test Kernel
4218d1491baSSteven Rostedt kernel vmlinuz-test
4228d1491baSSteven Rostedt GRUB_MENU = Test Kernel
423a15ba913SSteven Rostedt
424a15ba913SSteven Rostedt For grub2, a search of \$GRUB_FILE is performed for the lines
425a15ba913SSteven Rostedt that begin with "menuentry". It will not detect submenus. The
426a15ba913SSteven Rostedt menu must be a non-nested menu. Add the quotes used in the menu
427a15ba913SSteven Rostedt to guarantee your selection, as the first menuentry with the content
428a15ba913SSteven Rostedt of \$GRUB_MENU that is found will be used.
429a15ba913SSteven RostedtEOF
430a15ba913SSteven Rostedt    ;
431a15ba913SSteven Rostedt$config_help{"GRUB_FILE"} = << "EOF"
432a15ba913SSteven Rostedt If grub2 is used, the full path for the grub.cfg file is placed
433a15ba913SSteven Rostedt here. Use something like /boot/grub2/grub.cfg to search.
4348d1491baSSteven RostedtEOF
4358d1491baSSteven Rostedt    ;
4367786954cSSteven Rostedt$config_help{"SYSLINUX_LABEL"} = << "EOF"
4377786954cSSteven Rostedt If syslinux is used, the label that boots the target kernel must
4387786954cSSteven Rostedt be specified with SYSLINUX_LABEL.
4397786954cSSteven RostedtEOF
4407786954cSSteven Rostedt    ;
4418d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF"
4428d1491baSSteven Rostedt A script to reboot the target into the test kernel
4438d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script)
4448d1491baSSteven RostedtEOF
4458d1491baSSteven Rostedt    ;
4468d1491baSSteven Rostedt
447dad98754SSteven Rostedtsub read_prompt {
448dad98754SSteven Rostedt    my ($cancel, $prompt) = @_;
44935ce5952SSteven Rostedt
45035ce5952SSteven Rostedt    my $ans;
45135ce5952SSteven Rostedt
45235ce5952SSteven Rostedt    for (;;) {
453dad98754SSteven Rostedt	if ($cancel) {
454dad98754SSteven Rostedt	    print "$prompt [y/n/C] ";
455dad98754SSteven Rostedt	} else {
45635ce5952SSteven Rostedt	    print "$prompt [Y/n] ";
457dad98754SSteven Rostedt	}
45835ce5952SSteven Rostedt	$ans = <STDIN>;
45935ce5952SSteven Rostedt	chomp $ans;
46035ce5952SSteven Rostedt	if ($ans =~ /^\s*$/) {
461dad98754SSteven Rostedt	    if ($cancel) {
462dad98754SSteven Rostedt		$ans = "c";
463dad98754SSteven Rostedt	    } else {
46435ce5952SSteven Rostedt		$ans = "y";
46535ce5952SSteven Rostedt	    }
466dad98754SSteven Rostedt	}
46735ce5952SSteven Rostedt	last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
468dad98754SSteven Rostedt	if ($cancel) {
469dad98754SSteven Rostedt	    last if ($ans =~ /^c$/i);
470dad98754SSteven Rostedt	    print "Please answer either 'y', 'n' or 'c'.\n";
471dad98754SSteven Rostedt	} else {
47235ce5952SSteven Rostedt	    print "Please answer either 'y' or 'n'.\n";
47335ce5952SSteven Rostedt	}
474dad98754SSteven Rostedt    }
475dad98754SSteven Rostedt    if ($ans =~ /^c/i) {
476dad98754SSteven Rostedt	exit;
477dad98754SSteven Rostedt    }
47835ce5952SSteven Rostedt    if ($ans !~ /^y$/i) {
47935ce5952SSteven Rostedt	return 0;
48035ce5952SSteven Rostedt    }
48135ce5952SSteven Rostedt    return 1;
48235ce5952SSteven Rostedt}
4838d1491baSSteven Rostedt
484dad98754SSteven Rostedtsub read_yn {
485dad98754SSteven Rostedt    my ($prompt) = @_;
486dad98754SSteven Rostedt
487dad98754SSteven Rostedt    return read_prompt 0, $prompt;
488dad98754SSteven Rostedt}
489dad98754SSteven Rostedt
490dad98754SSteven Rostedtsub read_ync {
491dad98754SSteven Rostedt    my ($prompt) = @_;
492dad98754SSteven Rostedt
493dad98754SSteven Rostedt    return read_prompt 1, $prompt;
494dad98754SSteven Rostedt}
495dad98754SSteven Rostedt
4968d1491baSSteven Rostedtsub get_ktest_config {
4978d1491baSSteven Rostedt    my ($config) = @_;
498815e2bd7SSteven Rostedt    my $ans;
4998d1491baSSteven Rostedt
5008d1491baSSteven Rostedt    return if (defined($opt{$config}));
5018d1491baSSteven Rostedt
5028d1491baSSteven Rostedt    if (defined($config_help{$config})) {
5038d1491baSSteven Rostedt	print "\n";
5048d1491baSSteven Rostedt	print $config_help{$config};
5058d1491baSSteven Rostedt    }
5068d1491baSSteven Rostedt
5078d1491baSSteven Rostedt    for (;;) {
5088d1491baSSteven Rostedt	print "$config = ";
509dbd3783bSSteven Rostedt	if (defined($default{$config}) && length($default{$config})) {
5108d1491baSSteven Rostedt	    print "\[$default{$config}\] ";
5118d1491baSSteven Rostedt	}
512815e2bd7SSteven Rostedt	$ans = <STDIN>;
513815e2bd7SSteven Rostedt	$ans =~ s/^\s*(.*\S)\s*$/$1/;
514815e2bd7SSteven Rostedt	if ($ans =~ /^\s*$/) {
5158d1491baSSteven Rostedt	    if ($default{$config}) {
516815e2bd7SSteven Rostedt		$ans = $default{$config};
5178d1491baSSteven Rostedt	    } else {
5188d1491baSSteven Rostedt		print "Your answer can not be blank\n";
5198d1491baSSteven Rostedt		next;
5208d1491baSSteven Rostedt	    }
5218d1491baSSteven Rostedt	}
5220e7a22deSSteven Rostedt	$entered_configs{$config} = ${ans};
5238d1491baSSteven Rostedt	last;
5248d1491baSSteven Rostedt    }
5258d1491baSSteven Rostedt}
5268d1491baSSteven Rostedt
5278d1491baSSteven Rostedtsub get_ktest_configs {
5288d1491baSSteven Rostedt    get_ktest_config("MACHINE");
5298d1491baSSteven Rostedt    get_ktest_config("BUILD_DIR");
5308d1491baSSteven Rostedt    get_ktest_config("OUTPUT_DIR");
531bb8474b1SSteven Rostedt
532dbd3783bSSteven Rostedt    if ($newconfig) {
533dbd3783bSSteven Rostedt	get_ktest_config("BUILD_OPTIONS");
534dbd3783bSSteven Rostedt    }
535dbd3783bSSteven Rostedt
536bb8474b1SSteven Rostedt    # options required for other than just building a kernel
537bb8474b1SSteven Rostedt    if (!$buildonly) {
538165708b2SSteven Rostedt	get_ktest_config("POWER_CYCLE");
539165708b2SSteven Rostedt	get_ktest_config("CONSOLE");
540165708b2SSteven Rostedt    }
541165708b2SSteven Rostedt
542165708b2SSteven Rostedt    # options required for install and more
543165708b2SSteven Rostedt    if ($buildonly != 1) {
544bb8474b1SSteven Rostedt	get_ktest_config("SSH_USER");
5458d1491baSSteven Rostedt	get_ktest_config("BUILD_TARGET");
5468d1491baSSteven Rostedt	get_ktest_config("TARGET_IMAGE");
547bb8474b1SSteven Rostedt    }
548bb8474b1SSteven Rostedt
5498d1491baSSteven Rostedt    get_ktest_config("LOCALVERSION");
5508d1491baSSteven Rostedt
551bb8474b1SSteven Rostedt    return if ($buildonly);
552bb8474b1SSteven Rostedt
5538d1491baSSteven Rostedt    my $rtype = $opt{"REBOOT_TYPE"};
5548d1491baSSteven Rostedt
5558d1491baSSteven Rostedt    if (!defined($rtype)) {
5568d1491baSSteven Rostedt	if (!defined($opt{"GRUB_MENU"})) {
5578d1491baSSteven Rostedt	    get_ktest_config("REBOOT_TYPE");
5588d1491baSSteven Rostedt	    $rtype = $entered_configs{"REBOOT_TYPE"};
5598d1491baSSteven Rostedt	} else {
5608d1491baSSteven Rostedt	    $rtype = "grub";
5618d1491baSSteven Rostedt	}
5628d1491baSSteven Rostedt    }
5638d1491baSSteven Rostedt
5648d1491baSSteven Rostedt    if ($rtype eq "grub") {
5658d1491baSSteven Rostedt	get_ktest_config("GRUB_MENU");
5668d1491baSSteven Rostedt    }
567a15ba913SSteven Rostedt
568a15ba913SSteven Rostedt    if ($rtype eq "grub2") {
569a15ba913SSteven Rostedt	get_ktest_config("GRUB_MENU");
570a15ba913SSteven Rostedt	get_ktest_config("GRUB_FILE");
571a15ba913SSteven Rostedt    }
5727786954cSSteven Rostedt
5737786954cSSteven Rostedt    if ($rtype eq "syslinux") {
5747786954cSSteven Rostedt	get_ktest_config("SYSLINUX_LABEL");
5757786954cSSteven Rostedt    }
5768d1491baSSteven Rostedt}
5778d1491baSSteven Rostedt
57877d942ceSSteven Rostedtsub process_variables {
5798d735212SSteven Rostedt    my ($value, $remove_undef) = @_;
58077d942ceSSteven Rostedt    my $retval = "";
58177d942ceSSteven Rostedt
58277d942ceSSteven Rostedt    # We want to check for '\', and it is just easier
58377d942ceSSteven Rostedt    # to check the previous characet of '$' and not need
58477d942ceSSteven Rostedt    # to worry if '$' is the first character. By adding
58577d942ceSSteven Rostedt    # a space to $value, we can just check [^\\]\$ and
58677d942ceSSteven Rostedt    # it will still work.
58777d942ceSSteven Rostedt    $value = " $value";
58877d942ceSSteven Rostedt
58977d942ceSSteven Rostedt    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
59077d942ceSSteven Rostedt	my $begin = $1;
59177d942ceSSteven Rostedt	my $var = $2;
59277d942ceSSteven Rostedt	my $end = $3;
59377d942ceSSteven Rostedt	# append beginning of value to retval
59477d942ceSSteven Rostedt	$retval = "$retval$begin";
59577d942ceSSteven Rostedt	if (defined($variable{$var})) {
59677d942ceSSteven Rostedt	    $retval = "$retval$variable{$var}";
5978d735212SSteven Rostedt	} elsif (defined($remove_undef) && $remove_undef) {
5988d735212SSteven Rostedt	    # for if statements, any variable that is not defined,
5998d735212SSteven Rostedt	    # we simple convert to 0
6008d735212SSteven Rostedt	    $retval = "${retval}0";
60177d942ceSSteven Rostedt	} else {
60277d942ceSSteven Rostedt	    # put back the origin piece.
60377d942ceSSteven Rostedt	    $retval = "$retval\$\{$var\}";
6049cc9e091SSteven Rostedt	    # This could be an option that is used later, save
6059cc9e091SSteven Rostedt	    # it so we don't warn if this option is not one of
6069cc9e091SSteven Rostedt	    # ktests options.
6079cc9e091SSteven Rostedt	    $used_options{$var} = 1;
60877d942ceSSteven Rostedt	}
60977d942ceSSteven Rostedt	$value = $end;
61077d942ceSSteven Rostedt    }
61177d942ceSSteven Rostedt    $retval = "$retval$value";
61277d942ceSSteven Rostedt
61377d942ceSSteven Rostedt    # remove the space added in the beginning
61477d942ceSSteven Rostedt    $retval =~ s/ //;
61577d942ceSSteven Rostedt
61677d942ceSSteven Rostedt    return "$retval"
61777d942ceSSteven Rostedt}
61877d942ceSSteven Rostedt
619a57419b3SSteven Rostedtsub set_value {
6203d1cc414SSteven Rostedt    my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
6212545eb61SSteven Rostedt
622cad96669SSteven Rostedt    my $prvalue = process_variables($rvalue);
623cad96669SSteven Rostedt
624cad96669SSteven Rostedt    if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") {
625bb8474b1SSteven Rostedt	# Note if a test is something other than build, then we
626bb8474b1SSteven Rostedt	# will need other manditory options.
627cad96669SSteven Rostedt	if ($prvalue ne "install") {
628319ab14fSSteven Rostedt (Red Hat)	    # for bisect, we need to check BISECT_TYPE
629319ab14fSSteven Rostedt (Red Hat)	    if ($prvalue ne "bisect") {
630319ab14fSSteven Rostedt (Red Hat)		$buildonly = 0;
631319ab14fSSteven Rostedt (Red Hat)	    }
632319ab14fSSteven Rostedt (Red Hat)	} else {
633319ab14fSSteven Rostedt (Red Hat)	    # install still limits some manditory options.
634319ab14fSSteven Rostedt (Red Hat)	    $buildonly = 2;
635319ab14fSSteven Rostedt (Red Hat)	}
636319ab14fSSteven Rostedt (Red Hat)    }
637319ab14fSSteven Rostedt (Red Hat)
638319ab14fSSteven Rostedt (Red Hat)    if ($buildonly && $lvalue =~ /^BISECT_TYPE(\[.*\])?$/ && $prvalue ne "build") {
639319ab14fSSteven Rostedt (Red Hat)	if ($prvalue ne "install") {
640bb8474b1SSteven Rostedt	    $buildonly = 0;
641165708b2SSteven Rostedt	} else {
642165708b2SSteven Rostedt	    # install still limits some manditory options.
643165708b2SSteven Rostedt	    $buildonly = 2;
644165708b2SSteven Rostedt	}
645bb8474b1SSteven Rostedt    }
646bb8474b1SSteven Rostedt
647a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
6483d1cc414SSteven Rostedt	if (!$override || defined(${$overrides}{$lvalue})) {
6493d1cc414SSteven Rostedt	    my $extra = "";
6503d1cc414SSteven Rostedt	    if ($override) {
6513d1cc414SSteven Rostedt		$extra = "In the same override section!\n";
6523d1cc414SSteven Rostedt	    }
6533d1cc414SSteven Rostedt	    die "$name: $.: Option $lvalue defined more than once!\n$extra";
6543d1cc414SSteven Rostedt	}
655cad96669SSteven Rostedt	${$overrides}{$lvalue} = $prvalue;
656a75fececSSteven Rostedt    }
65721a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
65821a9679fSSteven Rostedt	delete $opt{$lvalue};
65921a9679fSSteven Rostedt    } else {
660cad96669SSteven Rostedt	$opt{$lvalue} = $prvalue;
66121a9679fSSteven Rostedt    }
6622545eb61SSteven Rostedt}
663a57419b3SSteven Rostedt
66477d942ceSSteven Rostedtsub set_variable {
66577d942ceSSteven Rostedt    my ($lvalue, $rvalue) = @_;
66677d942ceSSteven Rostedt
66777d942ceSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
66877d942ceSSteven Rostedt	delete $variable{$lvalue};
66977d942ceSSteven Rostedt    } else {
67077d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
67177d942ceSSteven Rostedt	$variable{$lvalue} = $rvalue;
67277d942ceSSteven Rostedt    }
67377d942ceSSteven Rostedt}
67477d942ceSSteven Rostedt
675ab7a3f52SSteven Rostedtsub process_compare {
676ab7a3f52SSteven Rostedt    my ($lval, $cmp, $rval) = @_;
677ab7a3f52SSteven Rostedt
678ab7a3f52SSteven Rostedt    # remove whitespace
679ab7a3f52SSteven Rostedt
680ab7a3f52SSteven Rostedt    $lval =~ s/^\s*//;
681ab7a3f52SSteven Rostedt    $lval =~ s/\s*$//;
682ab7a3f52SSteven Rostedt
683ab7a3f52SSteven Rostedt    $rval =~ s/^\s*//;
684ab7a3f52SSteven Rostedt    $rval =~ s/\s*$//;
685ab7a3f52SSteven Rostedt
686ab7a3f52SSteven Rostedt    if ($cmp eq "==") {
687ab7a3f52SSteven Rostedt	return $lval eq $rval;
688ab7a3f52SSteven Rostedt    } elsif ($cmp eq "!=") {
689ab7a3f52SSteven Rostedt	return $lval ne $rval;
6908fddbe9bSSteven Rostedt    } elsif ($cmp eq "=~") {
6918fddbe9bSSteven Rostedt	return $lval =~ m/$rval/;
6928fddbe9bSSteven Rostedt    } elsif ($cmp eq "!~") {
6938fddbe9bSSteven Rostedt	return $lval !~ m/$rval/;
694ab7a3f52SSteven Rostedt    }
695ab7a3f52SSteven Rostedt
696ab7a3f52SSteven Rostedt    my $statement = "$lval $cmp $rval";
697ab7a3f52SSteven Rostedt    my $ret = eval $statement;
698ab7a3f52SSteven Rostedt
699ab7a3f52SSteven Rostedt    # $@ stores error of eval
700ab7a3f52SSteven Rostedt    if ($@) {
701ab7a3f52SSteven Rostedt	return -1;
702ab7a3f52SSteven Rostedt    }
703ab7a3f52SSteven Rostedt
704ab7a3f52SSteven Rostedt    return $ret;
705ab7a3f52SSteven Rostedt}
706ab7a3f52SSteven Rostedt
7079900b5dcSSteven Rostedtsub value_defined {
7089900b5dcSSteven Rostedt    my ($val) = @_;
7099900b5dcSSteven Rostedt
7109900b5dcSSteven Rostedt    return defined($variable{$2}) ||
7119900b5dcSSteven Rostedt	defined($opt{$2});
7129900b5dcSSteven Rostedt}
7139900b5dcSSteven Rostedt
7148d735212SSteven Rostedtmy $d = 0;
7158d735212SSteven Rostedtsub process_expression {
7168d735212SSteven Rostedt    my ($name, $val) = @_;
71745d73a5dSSteven Rostedt
7188d735212SSteven Rostedt    my $c = $d++;
7198d735212SSteven Rostedt
7208d735212SSteven Rostedt    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
7218d735212SSteven Rostedt	my $express = $1;
7228d735212SSteven Rostedt
7238d735212SSteven Rostedt	if (process_expression($name, $express)) {
7248d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
7258d735212SSteven Rostedt	} else {
7268d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
7278d735212SSteven Rostedt	}
7288d735212SSteven Rostedt    }
7298d735212SSteven Rostedt
7308d735212SSteven Rostedt    $d--;
7318d735212SSteven Rostedt    my $OR = "\\|\\|";
7328d735212SSteven Rostedt    my $AND = "\\&\\&";
7338d735212SSteven Rostedt
7348d735212SSteven Rostedt    while ($val =~ s/^(.*?)($OR|$AND)//) {
7358d735212SSteven Rostedt	my $express = $1;
7368d735212SSteven Rostedt	my $op = $2;
7378d735212SSteven Rostedt
7388d735212SSteven Rostedt	if (process_expression($name, $express)) {
7398d735212SSteven Rostedt	    if ($op eq "||") {
7408d735212SSteven Rostedt		return 1;
7418d735212SSteven Rostedt	    }
7428d735212SSteven Rostedt	} else {
7438d735212SSteven Rostedt	    if ($op eq "&&") {
7448d735212SSteven Rostedt		return 0;
7458d735212SSteven Rostedt	    }
7468d735212SSteven Rostedt	}
7478d735212SSteven Rostedt    }
74845d73a5dSSteven Rostedt
7498fddbe9bSSteven Rostedt    if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) {
750ab7a3f52SSteven Rostedt	my $ret = process_compare($1, $2, $3);
751ab7a3f52SSteven Rostedt	if ($ret < 0) {
752ab7a3f52SSteven Rostedt	    die "$name: $.: Unable to process comparison\n";
753ab7a3f52SSteven Rostedt	}
754ab7a3f52SSteven Rostedt	return $ret;
755ab7a3f52SSteven Rostedt    }
756ab7a3f52SSteven Rostedt
7579900b5dcSSteven Rostedt    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
7589900b5dcSSteven Rostedt	if (defined $1) {
7599900b5dcSSteven Rostedt	    return !value_defined($2);
7609900b5dcSSteven Rostedt	} else {
7619900b5dcSSteven Rostedt	    return value_defined($2);
7629900b5dcSSteven Rostedt	}
7639900b5dcSSteven Rostedt    }
7649900b5dcSSteven Rostedt
76545d73a5dSSteven Rostedt    if ($val =~ /^\s*0\s*$/) {
76645d73a5dSSteven Rostedt	return 0;
76745d73a5dSSteven Rostedt    } elsif ($val =~ /^\s*\d+\s*$/) {
76845d73a5dSSteven Rostedt	return 1;
76945d73a5dSSteven Rostedt    }
77045d73a5dSSteven Rostedt
7719900b5dcSSteven Rostedt    die ("$name: $.: Undefined content $val in if statement\n");
7728d735212SSteven Rostedt}
7738d735212SSteven Rostedt
7748d735212SSteven Rostedtsub process_if {
7758d735212SSteven Rostedt    my ($name, $value) = @_;
7768d735212SSteven Rostedt
7778d735212SSteven Rostedt    # Convert variables and replace undefined ones with 0
7788d735212SSteven Rostedt    my $val = process_variables($value, 1);
7798d735212SSteven Rostedt    my $ret = process_expression $name, $val;
7808d735212SSteven Rostedt
7818d735212SSteven Rostedt    return $ret;
78245d73a5dSSteven Rostedt}
78345d73a5dSSteven Rostedt
7842ed3b161SSteven Rostedtsub __read_config {
7852ed3b161SSteven Rostedt    my ($config, $current_test_num) = @_;
786a57419b3SSteven Rostedt
7872ed3b161SSteven Rostedt    my $in;
7882ed3b161SSteven Rostedt    open($in, $config) || die "can't read file $config";
789a57419b3SSteven Rostedt
790a57419b3SSteven Rostedt    my $name = $config;
791a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
792a57419b3SSteven Rostedt
7932ed3b161SSteven Rostedt    my $test_num = $$current_test_num;
794a57419b3SSteven Rostedt    my $default = 1;
795a57419b3SSteven Rostedt    my $repeat = 1;
796a57419b3SSteven Rostedt    my $num_tests_set = 0;
797a57419b3SSteven Rostedt    my $skip = 0;
798a57419b3SSteven Rostedt    my $rest;
799a9f84424SSteven Rostedt    my $line;
8000df213caSSteven Rostedt    my $test_case = 0;
80145d73a5dSSteven Rostedt    my $if = 0;
80245d73a5dSSteven Rostedt    my $if_set = 0;
8033d1cc414SSteven Rostedt    my $override = 0;
8043d1cc414SSteven Rostedt
8053d1cc414SSteven Rostedt    my %overrides;
806a57419b3SSteven Rostedt
8072ed3b161SSteven Rostedt    while (<$in>) {
808a57419b3SSteven Rostedt
809a57419b3SSteven Rostedt	# ignore blank lines and comments
810a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
811a57419b3SSteven Rostedt
8120050b6bbSSteven Rostedt	if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
813a57419b3SSteven Rostedt
8140050b6bbSSteven Rostedt	    my $type = $1;
8150050b6bbSSteven Rostedt	    $rest = $2;
816a9f84424SSteven Rostedt	    $line = $2;
8170050b6bbSSteven Rostedt
8180050b6bbSSteven Rostedt	    my $old_test_num;
8190050b6bbSSteven Rostedt	    my $old_repeat;
8203d1cc414SSteven Rostedt	    $override = 0;
8210050b6bbSSteven Rostedt
8220050b6bbSSteven Rostedt	    if ($type eq "TEST_START") {
823a57419b3SSteven Rostedt
824a57419b3SSteven Rostedt		if ($num_tests_set) {
825a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
826a57419b3SSteven Rostedt		}
827a57419b3SSteven Rostedt
8280050b6bbSSteven Rostedt		$old_test_num = $test_num;
8290050b6bbSSteven Rostedt		$old_repeat = $repeat;
830a57419b3SSteven Rostedt
831a57419b3SSteven Rostedt		$test_num += $repeat;
832a57419b3SSteven Rostedt		$default = 0;
833a57419b3SSteven Rostedt		$repeat = 1;
8340050b6bbSSteven Rostedt	    } else {
8350050b6bbSSteven Rostedt		$default = 1;
8360050b6bbSSteven Rostedt	    }
837a57419b3SSteven Rostedt
838a9f84424SSteven Rostedt	    # If SKIP is anywhere in the line, the command will be skipped
839a9f84424SSteven Rostedt	    if ($rest =~ s/\s+SKIP\b//) {
840a57419b3SSteven Rostedt		$skip = 1;
841a57419b3SSteven Rostedt	    } else {
8420df213caSSteven Rostedt		$test_case = 1;
843a57419b3SSteven Rostedt		$skip = 0;
844a57419b3SSteven Rostedt	    }
845a57419b3SSteven Rostedt
846a9f84424SSteven Rostedt	    if ($rest =~ s/\sELSE\b//) {
847a9f84424SSteven Rostedt		if (!$if) {
848a9f84424SSteven Rostedt		    die "$name: $.: ELSE found with out matching IF section\n$_";
849a57419b3SSteven Rostedt		}
850a9f84424SSteven Rostedt		$if = 0;
851a9f84424SSteven Rostedt
852a9f84424SSteven Rostedt		if ($if_set) {
853a9f84424SSteven Rostedt		    $skip = 1;
854a9f84424SSteven Rostedt		} else {
855a9f84424SSteven Rostedt		    $skip = 0;
8563d1cc414SSteven Rostedt		}
8573d1cc414SSteven Rostedt	    }
858a57419b3SSteven Rostedt
859a9f84424SSteven Rostedt	    if ($rest =~ s/\sIF\s+(.*)//) {
86045d73a5dSSteven Rostedt		if (process_if($name, $1)) {
86145d73a5dSSteven Rostedt		    $if_set = 1;
86245d73a5dSSteven Rostedt		} else {
863a57419b3SSteven Rostedt		    $skip = 1;
864a57419b3SSteven Rostedt		}
86545d73a5dSSteven Rostedt		$if = 1;
86645d73a5dSSteven Rostedt	    } else {
86745d73a5dSSteven Rostedt		$if = 0;
868a9f84424SSteven Rostedt		$if_set = 0;
86945d73a5dSSteven Rostedt	    }
870a57419b3SSteven Rostedt
871a9f84424SSteven Rostedt	    if (!$skip) {
872a9f84424SSteven Rostedt		if ($type eq "TEST_START") {
873a9f84424SSteven Rostedt		    if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
874a9f84424SSteven Rostedt			$repeat = $1;
875a9f84424SSteven Rostedt			$repeat_tests{"$test_num"} = $repeat;
876a9f84424SSteven Rostedt		    }
877a9f84424SSteven Rostedt		} elsif ($rest =~ s/\sOVERRIDE\b//) {
878a9f84424SSteven Rostedt		    # DEFAULT only
879a9f84424SSteven Rostedt		    $override = 1;
880a9f84424SSteven Rostedt		    # Clear previous overrides
881a9f84424SSteven Rostedt		    %overrides = ();
882a9f84424SSteven Rostedt		}
883a9f84424SSteven Rostedt	    }
884a9f84424SSteven Rostedt
885a9f84424SSteven Rostedt	    if (!$skip && $rest !~ /^\s*$/) {
8860050b6bbSSteven Rostedt		die "$name: $.: Gargbage found after $type\n$_";
887a57419b3SSteven Rostedt	    }
888a57419b3SSteven Rostedt
8890050b6bbSSteven Rostedt	    if ($skip && $type eq "TEST_START") {
890a57419b3SSteven Rostedt		$test_num = $old_test_num;
891e48c5293SSteven Rostedt		$repeat = $old_repeat;
892a57419b3SSteven Rostedt	    }
893a57419b3SSteven Rostedt
894ab7a3f52SSteven Rostedt	} elsif (/^\s*ELSE\b(.*)$/) {
89545d73a5dSSteven Rostedt	    if (!$if) {
89645d73a5dSSteven Rostedt		die "$name: $.: ELSE found with out matching IF section\n$_";
89745d73a5dSSteven Rostedt	    }
89845d73a5dSSteven Rostedt	    $rest = $1;
89945d73a5dSSteven Rostedt	    if ($if_set) {
90045d73a5dSSteven Rostedt		$skip = 1;
901ab7a3f52SSteven Rostedt		$rest = "";
90245d73a5dSSteven Rostedt	    } else {
90345d73a5dSSteven Rostedt		$skip = 0;
90445d73a5dSSteven Rostedt
905ab7a3f52SSteven Rostedt		if ($rest =~ /\sIF\s+(.*)/) {
90645d73a5dSSteven Rostedt		    # May be a ELSE IF section.
90795f57838SSteven Rostedt		    if (process_if($name, $1)) {
90895f57838SSteven Rostedt			$if_set = 1;
90995f57838SSteven Rostedt		    } else {
91045d73a5dSSteven Rostedt			$skip = 1;
91145d73a5dSSteven Rostedt		    }
912ab7a3f52SSteven Rostedt		    $rest = "";
91345d73a5dSSteven Rostedt		} else {
91445d73a5dSSteven Rostedt		    $if = 0;
91545d73a5dSSteven Rostedt		}
91645d73a5dSSteven Rostedt	    }
91745d73a5dSSteven Rostedt
918ab7a3f52SSteven Rostedt	    if ($rest !~ /^\s*$/) {
919ab7a3f52SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
920ab7a3f52SSteven Rostedt	    }
921ab7a3f52SSteven Rostedt
9222ed3b161SSteven Rostedt	} elsif (/^\s*INCLUDE\s+(\S+)/) {
9232ed3b161SSteven Rostedt
9242ed3b161SSteven Rostedt	    next if ($skip);
9252ed3b161SSteven Rostedt
9262ed3b161SSteven Rostedt	    if (!$default) {
9272ed3b161SSteven Rostedt		die "$name: $.: INCLUDE can only be done in default sections\n$_";
9282ed3b161SSteven Rostedt	    }
9292ed3b161SSteven Rostedt
9302ed3b161SSteven Rostedt	    my $file = process_variables($1);
9312ed3b161SSteven Rostedt
9322ed3b161SSteven Rostedt	    if ($file !~ m,^/,) {
9332ed3b161SSteven Rostedt		# check the path of the config file first
9342ed3b161SSteven Rostedt		if ($config =~ m,(.*)/,) {
9352ed3b161SSteven Rostedt		    if (-f "$1/$file") {
9362ed3b161SSteven Rostedt			$file = "$1/$file";
9372ed3b161SSteven Rostedt		    }
9382ed3b161SSteven Rostedt		}
9392ed3b161SSteven Rostedt	    }
9402ed3b161SSteven Rostedt
9412ed3b161SSteven Rostedt	    if ( ! -r $file ) {
9422ed3b161SSteven Rostedt		die "$name: $.: Can't read file $file\n$_";
9432ed3b161SSteven Rostedt	    }
9442ed3b161SSteven Rostedt
9452ed3b161SSteven Rostedt	    if (__read_config($file, \$test_num)) {
9462ed3b161SSteven Rostedt		$test_case = 1;
9472ed3b161SSteven Rostedt	    }
9482ed3b161SSteven Rostedt
949a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
950a57419b3SSteven Rostedt
951a57419b3SSteven Rostedt	    next if ($skip);
952a57419b3SSteven Rostedt
953a57419b3SSteven Rostedt	    my $lvalue = $1;
954a57419b3SSteven Rostedt	    my $rvalue = $2;
955a57419b3SSteven Rostedt
956a57419b3SSteven Rostedt	    if (!$default &&
957a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
958a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
959a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
960a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
961a57419b3SSteven Rostedt	    }
962a57419b3SSteven Rostedt
963a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
964a57419b3SSteven Rostedt		if ($test_num) {
965a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
966a57419b3SSteven Rostedt		}
967a57419b3SSteven Rostedt		if (!$default) {
968a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
969a57419b3SSteven Rostedt		}
970a57419b3SSteven Rostedt		$num_tests_set = 1;
971a57419b3SSteven Rostedt	    }
972a57419b3SSteven Rostedt
973a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
9743d1cc414SSteven Rostedt		set_value($lvalue, $rvalue, $override, \%overrides, $name);
975a57419b3SSteven Rostedt	    } else {
976a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
9773d1cc414SSteven Rostedt		set_value($val, $rvalue, $override, \%overrides, $name);
978a57419b3SSteven Rostedt
979a57419b3SSteven Rostedt		if ($repeat > 1) {
980a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
981a57419b3SSteven Rostedt		}
982a57419b3SSteven Rostedt	    }
98377d942ceSSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
98477d942ceSSteven Rostedt	    next if ($skip);
98577d942ceSSteven Rostedt
98677d942ceSSteven Rostedt	    my $lvalue = $1;
98777d942ceSSteven Rostedt	    my $rvalue = $2;
98877d942ceSSteven Rostedt
98977d942ceSSteven Rostedt	    # process config variables.
99077d942ceSSteven Rostedt	    # Config variables are only active while reading the
99177d942ceSSteven Rostedt	    # config and can be defined anywhere. They also ignore
99277d942ceSSteven Rostedt	    # TEST_START and DEFAULTS, but are skipped if they are in
99377d942ceSSteven Rostedt	    # on of these sections that have SKIP defined.
99477d942ceSSteven Rostedt	    # The save variable can be
99577d942ceSSteven Rostedt	    # defined multiple times and the new one simply overrides
99677d942ceSSteven Rostedt	    # the prevous one.
99777d942ceSSteven Rostedt	    set_variable($lvalue, $rvalue);
99877d942ceSSteven Rostedt
999a57419b3SSteven Rostedt	} else {
1000a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
1001a57419b3SSteven Rostedt	}
10022545eb61SSteven Rostedt    }
10032545eb61SSteven Rostedt
1004a57419b3SSteven Rostedt    if ($test_num) {
1005a57419b3SSteven Rostedt	$test_num += $repeat - 1;
1006a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
1007a57419b3SSteven Rostedt    }
1008a57419b3SSteven Rostedt
10092ed3b161SSteven Rostedt    close($in);
10102ed3b161SSteven Rostedt
10112ed3b161SSteven Rostedt    $$current_test_num = $test_num;
10122ed3b161SSteven Rostedt
10132ed3b161SSteven Rostedt    return $test_case;
10142ed3b161SSteven Rostedt}
10152ed3b161SSteven Rostedt
1016c4261d0fSSteven Rostedtsub get_test_case {
1017c4261d0fSSteven Rostedt	print "What test case would you like to run?\n";
1018c4261d0fSSteven Rostedt	print " (build, install or boot)\n";
1019c4261d0fSSteven Rostedt	print " Other tests are available but require editing the config file\n";
1020c4261d0fSSteven Rostedt	my $ans = <STDIN>;
1021c4261d0fSSteven Rostedt	chomp $ans;
1022c4261d0fSSteven Rostedt	$default{"TEST_TYPE"} = $ans;
1023c4261d0fSSteven Rostedt}
1024c4261d0fSSteven Rostedt
10252ed3b161SSteven Rostedtsub read_config {
10262ed3b161SSteven Rostedt    my ($config) = @_;
10272ed3b161SSteven Rostedt
10282ed3b161SSteven Rostedt    my $test_case;
10292ed3b161SSteven Rostedt    my $test_num = 0;
10302ed3b161SSteven Rostedt
10312ed3b161SSteven Rostedt    $test_case = __read_config $config, \$test_num;
10322ed3b161SSteven Rostedt
10338d1491baSSteven Rostedt    # make sure we have all mandatory configs
10348d1491baSSteven Rostedt    get_ktest_configs;
10358d1491baSSteven Rostedt
10360df213caSSteven Rostedt    # was a test specified?
10370df213caSSteven Rostedt    if (!$test_case) {
10380df213caSSteven Rostedt	print "No test case specified.\n";
1039c4261d0fSSteven Rostedt	get_test_case;
10400df213caSSteven Rostedt    }
10410df213caSSteven Rostedt
1042a75fececSSteven Rostedt    # set any defaults
1043a75fececSSteven Rostedt
1044a75fececSSteven Rostedt    foreach my $default (keys %default) {
1045a75fececSSteven Rostedt	if (!defined($opt{$default})) {
1046a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
1047a75fececSSteven Rostedt	}
1048a75fececSSteven Rostedt    }
10499cc9e091SSteven Rostedt
10509cc9e091SSteven Rostedt    if ($opt{"IGNORE_UNUSED"} == 1) {
10519cc9e091SSteven Rostedt	return;
10529cc9e091SSteven Rostedt    }
10539cc9e091SSteven Rostedt
10549cc9e091SSteven Rostedt    my %not_used;
10559cc9e091SSteven Rostedt
10569cc9e091SSteven Rostedt    # check if there are any stragglers (typos?)
10579cc9e091SSteven Rostedt    foreach my $option (keys %opt) {
10589cc9e091SSteven Rostedt	my $op = $option;
10599cc9e091SSteven Rostedt	# remove per test labels.
10609cc9e091SSteven Rostedt	$op =~ s/\[.*\]//;
10619cc9e091SSteven Rostedt	if (!exists($option_map{$op}) &&
10629cc9e091SSteven Rostedt	    !exists($default{$op}) &&
10639cc9e091SSteven Rostedt	    !exists($used_options{$op})) {
10649cc9e091SSteven Rostedt	    $not_used{$op} = 1;
10659cc9e091SSteven Rostedt	}
10669cc9e091SSteven Rostedt    }
10679cc9e091SSteven Rostedt
10689cc9e091SSteven Rostedt    if (%not_used) {
10699cc9e091SSteven Rostedt	my $s = "s are";
10709cc9e091SSteven Rostedt	$s = " is" if (keys %not_used == 1);
10719cc9e091SSteven Rostedt	print "The following option$s not used; could be a typo:\n";
10729cc9e091SSteven Rostedt	foreach my $option (keys %not_used) {
10739cc9e091SSteven Rostedt	    print "$option\n";
10749cc9e091SSteven Rostedt	}
10759cc9e091SSteven Rostedt	print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n";
10769cc9e091SSteven Rostedt	if (!read_yn "Do you want to continue?") {
10779cc9e091SSteven Rostedt	    exit -1;
10789cc9e091SSteven Rostedt	}
10799cc9e091SSteven Rostedt    }
10802545eb61SSteven Rostedt}
10812545eb61SSteven Rostedt
108223715c3cSSteven Rostedtsub __eval_option {
108304262be3SSteven Rostedt (Red Hat)    my ($name, $option, $i) = @_;
108423715c3cSSteven Rostedt
108523715c3cSSteven Rostedt    # Add space to evaluate the character before $
108623715c3cSSteven Rostedt    $option = " $option";
108723715c3cSSteven Rostedt    my $retval = "";
1088f9dfb65bSRabin Vincent    my $repeated = 0;
1089f9dfb65bSRabin Vincent    my $parent = 0;
1090f9dfb65bSRabin Vincent
1091f9dfb65bSRabin Vincent    foreach my $test (keys %repeat_tests) {
1092f9dfb65bSRabin Vincent	if ($i >= $test &&
1093f9dfb65bSRabin Vincent	    $i < $test + $repeat_tests{$test}) {
1094f9dfb65bSRabin Vincent
1095f9dfb65bSRabin Vincent	    $repeated = 1;
1096f9dfb65bSRabin Vincent	    $parent = $test;
1097f9dfb65bSRabin Vincent	    last;
1098f9dfb65bSRabin Vincent	}
1099f9dfb65bSRabin Vincent    }
110023715c3cSSteven Rostedt
110123715c3cSSteven Rostedt    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
110223715c3cSSteven Rostedt	my $start = $1;
110323715c3cSSteven Rostedt	my $var = $2;
110423715c3cSSteven Rostedt	my $end = $3;
110523715c3cSSteven Rostedt
110623715c3cSSteven Rostedt	# Append beginning of line
110723715c3cSSteven Rostedt	$retval = "$retval$start";
110823715c3cSSteven Rostedt
110923715c3cSSteven Rostedt	# If the iteration option OPT[$i] exists, then use that.
111023715c3cSSteven Rostedt	# otherwise see if the default OPT (without [$i]) exists.
111123715c3cSSteven Rostedt
111223715c3cSSteven Rostedt	my $o = "$var\[$i\]";
1113f9dfb65bSRabin Vincent	my $parento = "$var\[$parent\]";
111423715c3cSSteven Rostedt
111504262be3SSteven Rostedt (Red Hat)	# If a variable contains itself, use the default var
111604262be3SSteven Rostedt (Red Hat)	if (($var eq $name) && defined($opt{$var})) {
111704262be3SSteven Rostedt (Red Hat)	    $o = $opt{$var};
111804262be3SSteven Rostedt (Red Hat)	    $retval = "$retval$o";
111904262be3SSteven Rostedt (Red Hat)	} elsif (defined($opt{$o})) {
112023715c3cSSteven Rostedt	    $o = $opt{$o};
112123715c3cSSteven Rostedt	    $retval = "$retval$o";
1122f9dfb65bSRabin Vincent	} elsif ($repeated && defined($opt{$parento})) {
1123f9dfb65bSRabin Vincent	    $o = $opt{$parento};
1124f9dfb65bSRabin Vincent	    $retval = "$retval$o";
112523715c3cSSteven Rostedt	} elsif (defined($opt{$var})) {
112623715c3cSSteven Rostedt	    $o = $opt{$var};
112723715c3cSSteven Rostedt	    $retval = "$retval$o";
112823715c3cSSteven Rostedt	} else {
112923715c3cSSteven Rostedt	    $retval = "$retval\$\{$var\}";
113023715c3cSSteven Rostedt	}
113123715c3cSSteven Rostedt
113223715c3cSSteven Rostedt	$option = $end;
113323715c3cSSteven Rostedt    }
113423715c3cSSteven Rostedt
113523715c3cSSteven Rostedt    $retval = "$retval$option";
113623715c3cSSteven Rostedt
113723715c3cSSteven Rostedt    $retval =~ s/^ //;
113823715c3cSSteven Rostedt
113923715c3cSSteven Rostedt    return $retval;
114023715c3cSSteven Rostedt}
114123715c3cSSteven Rostedt
114223715c3cSSteven Rostedtsub eval_option {
114304262be3SSteven Rostedt (Red Hat)    my ($name, $option, $i) = @_;
114423715c3cSSteven Rostedt
114523715c3cSSteven Rostedt    my $prev = "";
114623715c3cSSteven Rostedt
114723715c3cSSteven Rostedt    # Since an option can evaluate to another option,
114823715c3cSSteven Rostedt    # keep iterating until we do not evaluate any more
114923715c3cSSteven Rostedt    # options.
115023715c3cSSteven Rostedt    my $r = 0;
115123715c3cSSteven Rostedt    while ($prev ne $option) {
115223715c3cSSteven Rostedt	# Check for recursive evaluations.
115323715c3cSSteven Rostedt	# 100 deep should be more than enough.
115423715c3cSSteven Rostedt	if ($r++ > 100) {
115523715c3cSSteven Rostedt	    die "Over 100 evaluations accurred with $option\n" .
115623715c3cSSteven Rostedt		"Check for recursive variables\n";
115723715c3cSSteven Rostedt	}
115823715c3cSSteven Rostedt	$prev = $option;
115904262be3SSteven Rostedt (Red Hat)	$option = __eval_option($name, $option, $i);
116023715c3cSSteven Rostedt    }
116123715c3cSSteven Rostedt
116223715c3cSSteven Rostedt    return $option;
116323715c3cSSteven Rostedt}
116423715c3cSSteven Rostedt
1165d1e2f22aSSteven Rostedtsub _logit {
11662545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
11672545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
11682545eb61SSteven Rostedt	print OUT @_;
11692545eb61SSteven Rostedt	close(OUT);
11702545eb61SSteven Rostedt    }
11712545eb61SSteven Rostedt}
11722545eb61SSteven Rostedt
1173d1e2f22aSSteven Rostedtsub logit {
1174d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1175d1e2f22aSSteven Rostedt	_logit @_;
1176d1e2f22aSSteven Rostedt    } else {
1177d1e2f22aSSteven Rostedt	print @_;
1178d1e2f22aSSteven Rostedt    }
1179d1e2f22aSSteven Rostedt}
1180d1e2f22aSSteven Rostedt
11815f9b6cedSSteven Rostedtsub doprint {
11825f9b6cedSSteven Rostedt    print @_;
1183d1e2f22aSSteven Rostedt    _logit @_;
11845f9b6cedSSteven Rostedt}
11855f9b6cedSSteven Rostedt
11867faafbd6SSteven Rostedtsub run_command;
11872728be41SAndrew Jonessub start_monitor;
11882728be41SAndrew Jonessub end_monitor;
11892728be41SAndrew Jonessub wait_for_monitor;
11907faafbd6SSteven Rostedt
11917faafbd6SSteven Rostedtsub reboot {
11922728be41SAndrew Jones    my ($time) = @_;
11932728be41SAndrew Jones
1194a4968722SSteven Rostedt    # Make sure everything has been written to disk
1195a4968722SSteven Rostedt    run_ssh("sync");
1196a4968722SSteven Rostedt
11972b803365SSteven Rostedt    if (defined($time)) {
11982b803365SSteven Rostedt	start_monitor;
11992b803365SSteven Rostedt	# flush out current monitor
12002b803365SSteven Rostedt	# May contain the reboot success line
12012b803365SSteven Rostedt	wait_for_monitor 1;
12022b803365SSteven Rostedt    }
12032b803365SSteven Rostedt
12047faafbd6SSteven Rostedt    # try to reboot normally
1205e48c5293SSteven Rostedt    if (run_command $reboot) {
1206576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
1207576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
1208576f627cSSteven Rostedt	    run_command "$power_cycle";
1209576f627cSSteven Rostedt	}
1210576f627cSSteven Rostedt    } else {
12117faafbd6SSteven Rostedt	# nope? power cycle it.
1212a75fececSSteven Rostedt	run_command "$power_cycle";
12137faafbd6SSteven Rostedt    }
12142728be41SAndrew Jones
12152728be41SAndrew Jones    if (defined($time)) {
12164c0b67a2SSteven Rostedt (Red Hat)
12174c0b67a2SSteven Rostedt (Red Hat)	# We only want to get to the new kernel, don't fail
12184c0b67a2SSteven Rostedt (Red Hat)	# if we stumble over a call trace.
12194c0b67a2SSteven Rostedt (Red Hat)	my $save_ignore_errors = $ignore_errors;
12204c0b67a2SSteven Rostedt (Red Hat)	$ignore_errors = 1;
12214c0b67a2SSteven Rostedt (Red Hat)
1222d6845536SSteven Rostedt (Red Hat)	# Look for the good kernel to boot
1223d6845536SSteven Rostedt (Red Hat)	if (wait_for_monitor($time, "Linux version")) {
1224407b95b7SSteven Rostedt	    # reboot got stuck?
12258a80c727SSteven Rostedt	    doprint "Reboot did not finish. Forcing power cycle\n";
1226407b95b7SSteven Rostedt	    run_command "$power_cycle";
1227407b95b7SSteven Rostedt	}
1228d6845536SSteven Rostedt (Red Hat)
12294c0b67a2SSteven Rostedt (Red Hat)	$ignore_errors = $save_ignore_errors;
12304c0b67a2SSteven Rostedt (Red Hat)
1231d6845536SSteven Rostedt (Red Hat)	# Still need to wait for the reboot to finish
1232d6845536SSteven Rostedt (Red Hat)	wait_for_monitor($time, $reboot_success_line);
1233d6845536SSteven Rostedt (Red Hat)
12342728be41SAndrew Jones	end_monitor;
12352728be41SAndrew Jones    }
12367faafbd6SSteven Rostedt}
12377faafbd6SSteven Rostedt
1238bc7c5803SSteven Rostedtsub reboot_to_good {
1239bc7c5803SSteven Rostedt    my ($time) = @_;
1240bc7c5803SSteven Rostedt
1241bc7c5803SSteven Rostedt    if (defined($switch_to_good)) {
1242bc7c5803SSteven Rostedt	run_command $switch_to_good;
1243bc7c5803SSteven Rostedt    }
1244bc7c5803SSteven Rostedt
1245bc7c5803SSteven Rostedt    reboot $time;
1246bc7c5803SSteven Rostedt}
1247bc7c5803SSteven Rostedt
1248576f627cSSteven Rostedtsub do_not_reboot {
1249576f627cSSteven Rostedt    my $i = $iteration;
1250576f627cSSteven Rostedt
12514ab1cce5SSteven Rostedt    return $test_type eq "build" || $no_reboot ||
1252576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
1253576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
1254576f627cSSteven Rostedt}
1255576f627cSSteven Rostedt
12565c42fc5bSSteven Rostedtsub dodie {
12575a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
12585c42fc5bSSteven Rostedt
1259576f627cSSteven Rostedt    my $i = $iteration;
1260576f627cSSteven Rostedt
1261576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
1262576f627cSSteven Rostedt
126375c3fda7SSteven Rostedt	doprint "REBOOTING\n";
1264bc7c5803SSteven Rostedt	reboot_to_good;
126575c3fda7SSteven Rostedt
1266a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
12675c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
1268a75fececSSteven Rostedt	`$power_off`;
12695c42fc5bSSteven Rostedt    }
127075c3fda7SSteven Rostedt
1271f80802cbSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1272f80802cbSSteven Rostedt	print " See $opt{LOG_FILE} for more info.\n";
1273f80802cbSSteven Rostedt    }
1274f80802cbSSteven Rostedt
1275576f627cSSteven Rostedt    die @_, "\n";
12765c42fc5bSSteven Rostedt}
12775c42fc5bSSteven Rostedt
12787faafbd6SSteven Rostedtsub open_console {
12797faafbd6SSteven Rostedt    my ($fp) = @_;
12807faafbd6SSteven Rostedt
12817faafbd6SSteven Rostedt    my $flags;
12827faafbd6SSteven Rostedt
1283a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
1284a75fececSSteven Rostedt	dodie "Can't open console $console";
12857faafbd6SSteven Rostedt
12867faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
1287576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
12887faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
1289576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
12907faafbd6SSteven Rostedt
12917faafbd6SSteven Rostedt    return $pid;
12927faafbd6SSteven Rostedt}
12937faafbd6SSteven Rostedt
12947faafbd6SSteven Rostedtsub close_console {
12957faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
12967faafbd6SSteven Rostedt
12977faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
12987faafbd6SSteven Rostedt    kill 2, $pid;
12997faafbd6SSteven Rostedt
13007faafbd6SSteven Rostedt    print "closing!\n";
13017faafbd6SSteven Rostedt    close($fp);
13027faafbd6SSteven Rostedt}
13037faafbd6SSteven Rostedt
13047faafbd6SSteven Rostedtsub start_monitor {
13057faafbd6SSteven Rostedt    if ($monitor_cnt++) {
13067faafbd6SSteven Rostedt	return;
13077faafbd6SSteven Rostedt    }
13087faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
13097faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
1310a75fececSSteven Rostedt
1311a75fececSSteven Rostedt    return;
1312a75fececSSteven Rostedt
1313a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
13147faafbd6SSteven Rostedt}
13157faafbd6SSteven Rostedt
13167faafbd6SSteven Rostedtsub end_monitor {
1317319ab14fSSteven Rostedt (Red Hat)    return if (!defined $console);
13187faafbd6SSteven Rostedt    if (--$monitor_cnt) {
13197faafbd6SSteven Rostedt	return;
13207faafbd6SSteven Rostedt    }
13217faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
13227faafbd6SSteven Rostedt}
13237faafbd6SSteven Rostedt
13247faafbd6SSteven Rostedtsub wait_for_monitor {
13252b803365SSteven Rostedt    my ($time, $stop) = @_;
13262b803365SSteven Rostedt    my $full_line = "";
13277faafbd6SSteven Rostedt    my $line;
13282b803365SSteven Rostedt    my $booted = 0;
1329407b95b7SSteven Rostedt    my $start_time = time;
13308a80c727SSteven Rostedt    my $skip_call_trace = 0;
13318a80c727SSteven Rostedt    my $bug = 0;
13328a80c727SSteven Rostedt    my $bug_ignored = 0;
1333407b95b7SSteven Rostedt    my $now;
13347faafbd6SSteven Rostedt
1335a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
13367faafbd6SSteven Rostedt
13377faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
13382b803365SSteven Rostedt    while (!$booted) {
13397faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
13402b803365SSteven Rostedt	last if (!defined($line));
13412b803365SSteven Rostedt	print "$line";
13422b803365SSteven Rostedt	$full_line .= $line;
13432b803365SSteven Rostedt
13442b803365SSteven Rostedt	if (defined($stop) && $full_line =~ /$stop/) {
13452b803365SSteven Rostedt	    doprint "wait for monitor detected $stop\n";
13462b803365SSteven Rostedt	    $booted = 1;
13472b803365SSteven Rostedt	}
13482b803365SSteven Rostedt
13498a80c727SSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
13508a80c727SSteven Rostedt	    $skip_call_trace = 1;
13518a80c727SSteven Rostedt	}
13528a80c727SSteven Rostedt
13538a80c727SSteven Rostedt	if ($full_line =~ /call trace:/i) {
13548a80c727SSteven Rostedt	    if (!$bug && !$skip_call_trace) {
13558a80c727SSteven Rostedt		if ($ignore_errors) {
13568a80c727SSteven Rostedt		    $bug_ignored = 1;
13578a80c727SSteven Rostedt		} else {
13588a80c727SSteven Rostedt		    $bug = 1;
13598a80c727SSteven Rostedt		}
13608a80c727SSteven Rostedt	    }
13618a80c727SSteven Rostedt	}
13628a80c727SSteven Rostedt
13638a80c727SSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
13648a80c727SSteven Rostedt	    $skip_call_trace = 0;
13658a80c727SSteven Rostedt	}
13668a80c727SSteven Rostedt
13678a80c727SSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
13688a80c727SSteven Rostedt	    $bug = 1;
13698a80c727SSteven Rostedt	}
13708a80c727SSteven Rostedt
13712b803365SSteven Rostedt	if ($line =~ /\n/) {
13722b803365SSteven Rostedt	    $full_line = "";
13732b803365SSteven Rostedt	}
1374407b95b7SSteven Rostedt	$now = time;
1375407b95b7SSteven Rostedt	if ($now - $start_time >= $max_monitor_wait) {
1376407b95b7SSteven Rostedt	    doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n";
1377407b95b7SSteven Rostedt	    return 1;
1378407b95b7SSteven Rostedt	}
13792b803365SSteven Rostedt    }
1380a75fececSSteven Rostedt    print "** Monitor flushed **\n";
13818a80c727SSteven Rostedt    return $bug;
13827faafbd6SSteven Rostedt}
13837faafbd6SSteven Rostedt
1384de5b6e3bSRabin Vincentsub save_logs {
1385de5b6e3bSRabin Vincent	my ($result, $basedir) = @_;
1386de5b6e3bSRabin Vincent	my @t = localtime;
1387de5b6e3bSRabin Vincent	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1388de5b6e3bSRabin Vincent		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1389de5b6e3bSRabin Vincent
1390de5b6e3bSRabin Vincent	my $type = $build_type;
1391de5b6e3bSRabin Vincent	if ($type =~ /useconfig/) {
1392de5b6e3bSRabin Vincent	    $type = "useconfig";
1393de5b6e3bSRabin Vincent	}
1394de5b6e3bSRabin Vincent
1395de5b6e3bSRabin Vincent	my $dir = "$machine-$test_type-$type-$result-$date";
1396de5b6e3bSRabin Vincent
1397de5b6e3bSRabin Vincent	$dir = "$basedir/$dir";
1398de5b6e3bSRabin Vincent
1399de5b6e3bSRabin Vincent	if (!-d $dir) {
1400de5b6e3bSRabin Vincent	    mkpath($dir) or
1401de5b6e3bSRabin Vincent		die "can't create $dir";
1402de5b6e3bSRabin Vincent	}
1403de5b6e3bSRabin Vincent
1404de5b6e3bSRabin Vincent	my %files = (
1405de5b6e3bSRabin Vincent		"config" => $output_config,
1406de5b6e3bSRabin Vincent		"buildlog" => $buildlog,
1407de5b6e3bSRabin Vincent		"dmesg" => $dmesg,
1408de5b6e3bSRabin Vincent		"testlog" => $testlog,
1409de5b6e3bSRabin Vincent	);
1410de5b6e3bSRabin Vincent
1411de5b6e3bSRabin Vincent	while (my ($name, $source) = each(%files)) {
1412de5b6e3bSRabin Vincent		if (-f "$source") {
1413de5b6e3bSRabin Vincent			cp "$source", "$dir/$name" or
1414de5b6e3bSRabin Vincent				die "failed to copy $source";
1415de5b6e3bSRabin Vincent		}
1416de5b6e3bSRabin Vincent	}
1417de5b6e3bSRabin Vincent
1418de5b6e3bSRabin Vincent	doprint "*** Saved info to $dir ***\n";
1419de5b6e3bSRabin Vincent}
1420de5b6e3bSRabin Vincent
14212b7d9b21SSteven Rostedtsub fail {
14222b7d9b21SSteven Rostedt
1423921ed4c7SSteven Rostedt	if (defined($post_test)) {
1424921ed4c7SSteven Rostedt		run_command $post_test;
1425921ed4c7SSteven Rostedt	}
1426921ed4c7SSteven Rostedt
1427a75fececSSteven Rostedt	if ($die_on_failure) {
14282b7d9b21SSteven Rostedt		dodie @_;
14292b7d9b21SSteven Rostedt	}
14302b7d9b21SSteven Rostedt
1431a75fececSSteven Rostedt	doprint "FAILED\n";
14327faafbd6SSteven Rostedt
1433576f627cSSteven Rostedt	my $i = $iteration;
1434576f627cSSteven Rostedt
1435a75fececSSteven Rostedt	# no need to reboot for just building.
1436576f627cSSteven Rostedt	if (!do_not_reboot) {
14377faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
1438bc7c5803SSteven Rostedt	    reboot_to_good $sleep_time;
1439a75fececSSteven Rostedt	}
14407faafbd6SSteven Rostedt
14419064af52SSteven Rostedt	my $name = "";
14429064af52SSteven Rostedt
14439064af52SSteven Rostedt	if (defined($test_name)) {
14449064af52SSteven Rostedt	    $name = " ($test_name)";
14459064af52SSteven Rostedt	}
14469064af52SSteven Rostedt
1447576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1448576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
14499064af52SSteven Rostedt	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1450576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1451576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1452a75fececSSteven Rostedt
1453de5b6e3bSRabin Vincent	if (defined($store_failures)) {
1454de5b6e3bSRabin Vincent	    save_logs "fail", $store_failures;
1455cccae1a6SSteven Rostedt        }
1456cccae1a6SSteven Rostedt
14572b7d9b21SSteven Rostedt	return 1;
14582b7d9b21SSteven Rostedt}
14592b7d9b21SSteven Rostedt
14602545eb61SSteven Rostedtsub run_command {
14612545eb61SSteven Rostedt    my ($command) = @_;
1462d6ce2a0bSSteven Rostedt    my $dolog = 0;
1463d6ce2a0bSSteven Rostedt    my $dord = 0;
1464d6ce2a0bSSteven Rostedt    my $pid;
1465d6ce2a0bSSteven Rostedt
1466e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
1467e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
1468e48c5293SSteven Rostedt
1469d6ce2a0bSSteven Rostedt    doprint("$command ... ");
1470d6ce2a0bSSteven Rostedt
1471d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
14722b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
14732545eb61SSteven Rostedt
14742545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1475d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
1476d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
1477d6ce2a0bSSteven Rostedt	$dolog = 1;
14786c5ee0beSSteven Rostedt    }
14796c5ee0beSSteven Rostedt
14806c5ee0beSSteven Rostedt    if (defined($redirect)) {
1481d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
1482d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
1483d6ce2a0bSSteven Rostedt	$dord = 1;
14842545eb61SSteven Rostedt    }
14852545eb61SSteven Rostedt
1486d6ce2a0bSSteven Rostedt    while (<CMD>) {
1487d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
1488d6ce2a0bSSteven Rostedt	print RD  if ($dord);
1489d6ce2a0bSSteven Rostedt    }
14902545eb61SSteven Rostedt
1491d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
14922545eb61SSteven Rostedt    my $failed = $?;
14932545eb61SSteven Rostedt
1494d6ce2a0bSSteven Rostedt    close(CMD);
1495d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
1496d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
1497d6ce2a0bSSteven Rostedt
14982545eb61SSteven Rostedt    if ($failed) {
14992545eb61SSteven Rostedt	doprint "FAILED!\n";
15002545eb61SSteven Rostedt    } else {
15012545eb61SSteven Rostedt	doprint "SUCCESS\n";
15022545eb61SSteven Rostedt    }
15032545eb61SSteven Rostedt
15045f9b6cedSSteven Rostedt    return !$failed;
15055f9b6cedSSteven Rostedt}
15065f9b6cedSSteven Rostedt
1507e48c5293SSteven Rostedtsub run_ssh {
1508e48c5293SSteven Rostedt    my ($cmd) = @_;
1509e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
1510e48c5293SSteven Rostedt
1511e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1512e48c5293SSteven Rostedt    return run_command "$cp_exec";
1513e48c5293SSteven Rostedt}
1514e48c5293SSteven Rostedt
1515e48c5293SSteven Rostedtsub run_scp {
151602ad2617SSteven Rostedt    my ($src, $dst, $cp_scp) = @_;
1517e48c5293SSteven Rostedt
1518e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
1519e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
1520e48c5293SSteven Rostedt
1521e48c5293SSteven Rostedt    return run_command "$cp_scp";
1522e48c5293SSteven Rostedt}
1523e48c5293SSteven Rostedt
152402ad2617SSteven Rostedtsub run_scp_install {
152502ad2617SSteven Rostedt    my ($src, $dst) = @_;
152602ad2617SSteven Rostedt
152702ad2617SSteven Rostedt    my $cp_scp = $scp_to_target_install;
152802ad2617SSteven Rostedt
152902ad2617SSteven Rostedt    return run_scp($src, $dst, $cp_scp);
153002ad2617SSteven Rostedt}
153102ad2617SSteven Rostedt
153202ad2617SSteven Rostedtsub run_scp_mod {
153302ad2617SSteven Rostedt    my ($src, $dst) = @_;
153402ad2617SSteven Rostedt
153502ad2617SSteven Rostedt    my $cp_scp = $scp_to_target;
153602ad2617SSteven Rostedt
153702ad2617SSteven Rostedt    return run_scp($src, $dst, $cp_scp);
153802ad2617SSteven Rostedt}
153902ad2617SSteven Rostedt
1540a15ba913SSteven Rostedtsub get_grub2_index {
1541a15ba913SSteven Rostedt
1542*752d9665SSteven Rostedt (Red Hat)    return if (defined($grub_number) && defined($last_grub_menu) &&
1543*752d9665SSteven Rostedt (Red Hat)	       $last_grub_menu eq $grub_menu);
1544a15ba913SSteven Rostedt
1545a15ba913SSteven Rostedt    doprint "Find grub2 menu ... ";
1546a15ba913SSteven Rostedt    $grub_number = -1;
1547a15ba913SSteven Rostedt
1548a15ba913SSteven Rostedt    my $ssh_grub = $ssh_exec;
1549a15ba913SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat $grub_file,g;
1550a15ba913SSteven Rostedt
1551a15ba913SSteven Rostedt    open(IN, "$ssh_grub |")
1552a15ba913SSteven Rostedt	or die "unable to get $grub_file";
1553a15ba913SSteven Rostedt
1554a15ba913SSteven Rostedt    my $found = 0;
1555a15ba913SSteven Rostedt
1556a15ba913SSteven Rostedt    while (<IN>) {
1557a15ba913SSteven Rostedt	if (/^menuentry.*$grub_menu/) {
1558a15ba913SSteven Rostedt	    $grub_number++;
1559a15ba913SSteven Rostedt	    $found = 1;
1560a15ba913SSteven Rostedt	    last;
1561a15ba913SSteven Rostedt	} elsif (/^menuentry\s/) {
1562a15ba913SSteven Rostedt	    $grub_number++;
1563a15ba913SSteven Rostedt	}
1564a15ba913SSteven Rostedt    }
1565a15ba913SSteven Rostedt    close(IN);
1566a15ba913SSteven Rostedt
1567a15ba913SSteven Rostedt    die "Could not find '$grub_menu' in $grub_file on $machine"
1568a15ba913SSteven Rostedt	if (!$found);
1569a15ba913SSteven Rostedt    doprint "$grub_number\n";
1570*752d9665SSteven Rostedt (Red Hat)    $last_grub_menu = $grub_menu;
1571a15ba913SSteven Rostedt}
1572a15ba913SSteven Rostedt
15735f9b6cedSSteven Rostedtsub get_grub_index {
15745f9b6cedSSteven Rostedt
1575a15ba913SSteven Rostedt    if ($reboot_type eq "grub2") {
1576a15ba913SSteven Rostedt	get_grub2_index;
1577a15ba913SSteven Rostedt	return;
1578a15ba913SSteven Rostedt    }
1579a15ba913SSteven Rostedt
1580a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
1581a75fececSSteven Rostedt	return;
1582a75fececSSteven Rostedt    }
1583*752d9665SSteven Rostedt (Red Hat)    return if (defined($grub_number) && defined($last_grub_menu) &&
1584*752d9665SSteven Rostedt (Red Hat)	       $last_grub_menu eq $grub_menu);
15855f9b6cedSSteven Rostedt
15865f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
15875f9b6cedSSteven Rostedt    $grub_number = -1;
1588e48c5293SSteven Rostedt
1589e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
1590e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
1591e48c5293SSteven Rostedt
1592e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
15935f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
1594e48c5293SSteven Rostedt
1595eaa1fe25SSteven Rostedt    my $found = 0;
1596eaa1fe25SSteven Rostedt
15975f9b6cedSSteven Rostedt    while (<IN>) {
1598a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
15995f9b6cedSSteven Rostedt	    $grub_number++;
1600eaa1fe25SSteven Rostedt	    $found = 1;
16015f9b6cedSSteven Rostedt	    last;
16025f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
16035f9b6cedSSteven Rostedt	    $grub_number++;
16045f9b6cedSSteven Rostedt	}
16055f9b6cedSSteven Rostedt    }
16065f9b6cedSSteven Rostedt    close(IN);
16075f9b6cedSSteven Rostedt
1608a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
1609eaa1fe25SSteven Rostedt	if (!$found);
16105f9b6cedSSteven Rostedt    doprint "$grub_number\n";
1611*752d9665SSteven Rostedt (Red Hat)    $last_grub_menu = $grub_menu;
16122545eb61SSteven Rostedt}
16132545eb61SSteven Rostedt
16142545eb61SSteven Rostedtsub wait_for_input
16152545eb61SSteven Rostedt{
16162545eb61SSteven Rostedt    my ($fp, $time) = @_;
16172545eb61SSteven Rostedt    my $rin;
16182545eb61SSteven Rostedt    my $ready;
16192545eb61SSteven Rostedt    my $line;
16202545eb61SSteven Rostedt    my $ch;
16212545eb61SSteven Rostedt
16222545eb61SSteven Rostedt    if (!defined($time)) {
16232545eb61SSteven Rostedt	$time = $timeout;
16242545eb61SSteven Rostedt    }
16252545eb61SSteven Rostedt
16262545eb61SSteven Rostedt    $rin = '';
16272545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
1628319ab14fSSteven Rostedt (Red Hat)    ($ready, $time) = select($rin, undef, undef, $time);
16292545eb61SSteven Rostedt
16302545eb61SSteven Rostedt    $line = "";
16312545eb61SSteven Rostedt
16322545eb61SSteven Rostedt    # try to read one char at a time
16332545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
16342545eb61SSteven Rostedt	$line .= $ch;
16352545eb61SSteven Rostedt	last if ($ch eq "\n");
16362545eb61SSteven Rostedt    }
16372545eb61SSteven Rostedt
16382545eb61SSteven Rostedt    if (!length($line)) {
16392545eb61SSteven Rostedt	return undef;
16402545eb61SSteven Rostedt    }
16412545eb61SSteven Rostedt
16422545eb61SSteven Rostedt    return $line;
16432545eb61SSteven Rostedt}
16442545eb61SSteven Rostedt
164575c3fda7SSteven Rostedtsub reboot_to {
1646bc7c5803SSteven Rostedt    if (defined($switch_to_test)) {
1647bc7c5803SSteven Rostedt	run_command $switch_to_test;
1648bc7c5803SSteven Rostedt    }
1649bc7c5803SSteven Rostedt
1650a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
1651c54367f9SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
1652a15ba913SSteven Rostedt    } elsif ($reboot_type eq "grub2") {
1653a15ba913SSteven Rostedt	run_ssh "$grub_reboot $grub_number";
16547786954cSSteven Rostedt    } elsif ($reboot_type eq "syslinux") {
16557786954cSSteven Rostedt	run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path";
165696f6a0dfSSteven Rostedt    } elsif (defined $reboot_script) {
1657a75fececSSteven Rostedt	run_command "$reboot_script";
16582545eb61SSteven Rostedt    }
165996f6a0dfSSteven Rostedt    reboot;
166096f6a0dfSSteven Rostedt}
16612545eb61SSteven Rostedt
1662a57419b3SSteven Rostedtsub get_sha1 {
1663a57419b3SSteven Rostedt    my ($commit) = @_;
1664a57419b3SSteven Rostedt
1665a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
1666a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
1667a57419b3SSteven Rostedt    my $ret = $?;
1668a57419b3SSteven Rostedt
1669a57419b3SSteven Rostedt    logit $sha1;
1670a57419b3SSteven Rostedt
1671a57419b3SSteven Rostedt    if ($ret) {
1672a57419b3SSteven Rostedt	doprint "FAILED\n";
1673a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
1674a57419b3SSteven Rostedt    }
1675a57419b3SSteven Rostedt
1676a57419b3SSteven Rostedt    print "SUCCESS\n";
1677a57419b3SSteven Rostedt
1678a57419b3SSteven Rostedt    chomp $sha1;
1679a57419b3SSteven Rostedt
1680a57419b3SSteven Rostedt    return $sha1;
1681a57419b3SSteven Rostedt}
1682a57419b3SSteven Rostedt
16835a391fbfSSteven Rostedtsub monitor {
16842545eb61SSteven Rostedt    my $booted = 0;
16852545eb61SSteven Rostedt    my $bug = 0;
16866ca996ccSSteven Rostedt    my $bug_ignored = 0;
16875c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
16882b7d9b21SSteven Rostedt    my $loops;
16892545eb61SSteven Rostedt
16907faafbd6SSteven Rostedt    wait_for_monitor 5;
16912545eb61SSteven Rostedt
16922545eb61SSteven Rostedt    my $line;
16932545eb61SSteven Rostedt    my $full_line = "";
16942545eb61SSteven Rostedt
16957faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
16967faafbd6SSteven Rostedt	die "unable to write to $dmesg";
16972545eb61SSteven Rostedt
169875c3fda7SSteven Rostedt    reboot_to;
16992545eb61SSteven Rostedt
17001c8a617aSSteven Rostedt    my $success_start;
17011c8a617aSSteven Rostedt    my $failure_start;
17022d01b26aSSteven Rostedt    my $monitor_start = time;
17032d01b26aSSteven Rostedt    my $done = 0;
1704f1a5b962SSteven Rostedt    my $version_found = 0;
17051c8a617aSSteven Rostedt
17062d01b26aSSteven Rostedt    while (!$done) {
17072545eb61SSteven Rostedt
1708ecaf8e52SSteven Rostedt	if ($bug && defined($stop_after_failure) &&
1709ecaf8e52SSteven Rostedt	    $stop_after_failure >= 0) {
1710ecaf8e52SSteven Rostedt	    my $time = $stop_after_failure - (time - $failure_start);
1711ecaf8e52SSteven Rostedt	    $line = wait_for_input($monitor_fp, $time);
1712ecaf8e52SSteven Rostedt	    if (!defined($line)) {
1713ecaf8e52SSteven Rostedt		doprint "bug timed out after $booted_timeout seconds\n";
1714ecaf8e52SSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1715ecaf8e52SSteven Rostedt		last;
1716ecaf8e52SSteven Rostedt	    }
1717ecaf8e52SSteven Rostedt	} elsif ($booted) {
1718a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
1719cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1720cd4f1d53SSteven Rostedt		my $s = $booted_timeout == 1 ? "" : "s";
1721cd4f1d53SSteven Rostedt		doprint "Successful boot found: break after $booted_timeout second$s\n";
1722cd4f1d53SSteven Rostedt		last;
1723cd4f1d53SSteven Rostedt	    }
17242b7d9b21SSteven Rostedt	} else {
17257faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
1726cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1727cd4f1d53SSteven Rostedt		my $s = $timeout == 1 ? "" : "s";
1728cd4f1d53SSteven Rostedt		doprint "Timed out after $timeout second$s\n";
1729cd4f1d53SSteven Rostedt		last;
17302b7d9b21SSteven Rostedt	    }
1731cd4f1d53SSteven Rostedt	}
17322545eb61SSteven Rostedt
17332545eb61SSteven Rostedt	doprint $line;
17347faafbd6SSteven Rostedt	print DMESG $line;
17352545eb61SSteven Rostedt
17362545eb61SSteven Rostedt	# we are not guaranteed to get a full line
17372545eb61SSteven Rostedt	$full_line .= $line;
17382545eb61SSteven Rostedt
1739a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
17402545eb61SSteven Rostedt	    $booted = 1;
17411c8a617aSSteven Rostedt	    $success_start = time;
17421c8a617aSSteven Rostedt	}
17431c8a617aSSteven Rostedt
17441c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
17451c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
17461c8a617aSSteven Rostedt	    my $now = time;
17471c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
17481c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
17491c8a617aSSteven Rostedt		last;
17501c8a617aSSteven Rostedt	    }
17512545eb61SSteven Rostedt	}
17522545eb61SSteven Rostedt
17535c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
17545c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
17555c42fc5bSSteven Rostedt	}
17565c42fc5bSSteven Rostedt
17572545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
17586ca996ccSSteven Rostedt	    if (!$bug && !$skip_call_trace) {
17596ca996ccSSteven Rostedt		if ($ignore_errors) {
17606ca996ccSSteven Rostedt		    $bug_ignored = 1;
17616ca996ccSSteven Rostedt		} else {
17621c8a617aSSteven Rostedt		    $bug = 1;
17631c8a617aSSteven Rostedt		    $failure_start = time;
17641c8a617aSSteven Rostedt		}
17651c8a617aSSteven Rostedt	    }
17666ca996ccSSteven Rostedt	}
17671c8a617aSSteven Rostedt
17681c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
17691c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
17701c8a617aSSteven Rostedt	    my $now = time;
17711c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
17721c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
17731c8a617aSSteven Rostedt		last;
17741c8a617aSSteven Rostedt	    }
17755c42fc5bSSteven Rostedt	}
17765c42fc5bSSteven Rostedt
17775c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
17785c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
17795c42fc5bSSteven Rostedt	}
17805c42fc5bSSteven Rostedt
17815c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
178210abf118SSteven Rostedt	    $failure_start = time;
17832545eb61SSteven Rostedt	    $bug = 1;
17842545eb61SSteven Rostedt	}
17852545eb61SSteven Rostedt
1786f1a5b962SSteven Rostedt	# Detect triple faults by testing the banner
1787f1a5b962SSteven Rostedt	if ($full_line =~ /\bLinux version (\S+).*\n/) {
1788f1a5b962SSteven Rostedt	    if ($1 eq $version) {
1789f1a5b962SSteven Rostedt		$version_found = 1;
1790f1a5b962SSteven Rostedt	    } elsif ($version_found && $detect_triplefault) {
1791f1a5b962SSteven Rostedt		# We already booted into the kernel we are testing,
1792f1a5b962SSteven Rostedt		# but now we booted into another kernel?
1793f1a5b962SSteven Rostedt		# Consider this a triple fault.
1794f1a5b962SSteven Rostedt		doprint "Aleady booted in Linux kernel $version, but now\n";
1795f1a5b962SSteven Rostedt		doprint "we booted into Linux kernel $1.\n";
1796f1a5b962SSteven Rostedt		doprint "Assuming that this is a triple fault.\n";
1797f1a5b962SSteven Rostedt		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1798f1a5b962SSteven Rostedt		last;
1799f1a5b962SSteven Rostedt	    }
1800f1a5b962SSteven Rostedt	}
1801f1a5b962SSteven Rostedt
18022545eb61SSteven Rostedt	if ($line =~ /\n/) {
18032545eb61SSteven Rostedt	    $full_line = "";
18042545eb61SSteven Rostedt	}
18052d01b26aSSteven Rostedt
18062d01b26aSSteven Rostedt	if ($stop_test_after > 0 && !$booted && !$bug) {
18072d01b26aSSteven Rostedt	    if (time - $monitor_start > $stop_test_after) {
18084d62bf51SSteven Rostedt		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
18092d01b26aSSteven Rostedt		$done = 1;
18102d01b26aSSteven Rostedt	    }
18112d01b26aSSteven Rostedt	}
18122545eb61SSteven Rostedt    }
18132545eb61SSteven Rostedt
18147faafbd6SSteven Rostedt    close(DMESG);
18152545eb61SSteven Rostedt
18162545eb61SSteven Rostedt    if ($bug) {
18172b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
1818576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
18192545eb61SSteven Rostedt    }
18205f9b6cedSSteven Rostedt
1821a75fececSSteven Rostedt    if (!$booted) {
1822a75fececSSteven Rostedt	return 0 if ($in_bisect);
1823576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
1824a75fececSSteven Rostedt    }
1825a75fececSSteven Rostedt
18266ca996ccSSteven Rostedt    if ($bug_ignored) {
18276ca996ccSSteven Rostedt	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
18286ca996ccSSteven Rostedt    }
18296ca996ccSSteven Rostedt
18302b7d9b21SSteven Rostedt    return 1;
18312545eb61SSteven Rostedt}
18322545eb61SSteven Rostedt
18332b29b2f8SSteven Rostedtsub eval_kernel_version {
18342b29b2f8SSteven Rostedt    my ($option) = @_;
18352b29b2f8SSteven Rostedt
18362b29b2f8SSteven Rostedt    $option =~ s/\$KERNEL_VERSION/$version/g;
18372b29b2f8SSteven Rostedt
18382b29b2f8SSteven Rostedt    return $option;
18392b29b2f8SSteven Rostedt}
18402b29b2f8SSteven Rostedt
1841db05cfefSSteven Rostedtsub do_post_install {
1842db05cfefSSteven Rostedt
1843db05cfefSSteven Rostedt    return if (!defined($post_install));
1844db05cfefSSteven Rostedt
18452b29b2f8SSteven Rostedt    my $cp_post_install = eval_kernel_version $post_install;
1846db05cfefSSteven Rostedt    run_command "$cp_post_install" or
1847db05cfefSSteven Rostedt	dodie "Failed to run post install";
1848db05cfefSSteven Rostedt}
1849db05cfefSSteven Rostedt
1850e1a6c3d7SSteven Rostedt# Sometimes the reboot fails, and will hang. We try to ssh to the box
1851e1a6c3d7SSteven Rostedt# and if we fail, we force another reboot, that should powercycle it.
1852e1a6c3d7SSteven Rostedtsub test_booted {
1853e1a6c3d7SSteven Rostedt    if (!run_ssh "echo testing connection") {
1854e1a6c3d7SSteven Rostedt	reboot $sleep_time;
1855e1a6c3d7SSteven Rostedt    }
1856e1a6c3d7SSteven Rostedt}
1857e1a6c3d7SSteven Rostedt
18582545eb61SSteven Rostedtsub install {
18592545eb61SSteven Rostedt
1860e0a8742eSSteven Rostedt    return if ($no_install);
1861e0a8742eSSteven Rostedt
1862e5c2ec11SSteven Rostedt    if (defined($pre_install)) {
1863e5c2ec11SSteven Rostedt	my $cp_pre_install = eval_kernel_version $pre_install;
1864e5c2ec11SSteven Rostedt	run_command "$cp_pre_install" or
1865e5c2ec11SSteven Rostedt	    dodie "Failed to run pre install";
1866e5c2ec11SSteven Rostedt    }
1867e5c2ec11SSteven Rostedt
18682b29b2f8SSteven Rostedt    my $cp_target = eval_kernel_version $target_image;
18692b29b2f8SSteven Rostedt
1870e1a6c3d7SSteven Rostedt    test_booted;
1871e1a6c3d7SSteven Rostedt
187202ad2617SSteven Rostedt    run_scp_install "$outputdir/$build_target", "$cp_target" or
18735c42fc5bSSteven Rostedt	dodie "failed to copy image";
18745f9b6cedSSteven Rostedt
18755f9b6cedSSteven Rostedt    my $install_mods = 0;
18765f9b6cedSSteven Rostedt
18775f9b6cedSSteven Rostedt    # should we process modules?
18785f9b6cedSSteven Rostedt    $install_mods = 0;
187951ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
18805f9b6cedSSteven Rostedt    while (<IN>) {
18815f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
18828bc5e4eaSSteven Rostedt	    if (defined($1)) {
18838bc5e4eaSSteven Rostedt		$install_mods = 1;
18845f9b6cedSSteven Rostedt		last;
18855f9b6cedSSteven Rostedt	    }
18865f9b6cedSSteven Rostedt	}
18878bc5e4eaSSteven Rostedt    }
18885f9b6cedSSteven Rostedt    close(IN);
18895f9b6cedSSteven Rostedt
18905f9b6cedSSteven Rostedt    if (!$install_mods) {
1891db05cfefSSteven Rostedt	do_post_install;
18925f9b6cedSSteven Rostedt	doprint "No modules needed\n";
18935f9b6cedSSteven Rostedt	return;
18942545eb61SSteven Rostedt    }
18952545eb61SSteven Rostedt
1896627977d8SSteven Rostedt    run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or
18975f9b6cedSSteven Rostedt	dodie "Failed to install modules";
18985f9b6cedSSteven Rostedt
18992545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
1900a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
19012545eb61SSteven Rostedt
1902e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
19035c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
19042545eb61SSteven Rostedt
19055c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
1906a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
19075c42fc5bSSteven Rostedt	dodie "making tarball";
19085c42fc5bSSteven Rostedt
190902ad2617SSteven Rostedt    run_scp_mod "$tmpdir/$modtar", "/tmp" or
19105c42fc5bSSteven Rostedt	dodie "failed to copy modules";
19115c42fc5bSSteven Rostedt
1912a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
19135c42fc5bSSteven Rostedt
1914e7b13441SSteven Rostedt    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
19155c42fc5bSSteven Rostedt	dodie "failed to tar modules";
19165c42fc5bSSteven Rostedt
1917e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
19188b37ca8cSSteven Rostedt
1919db05cfefSSteven Rostedt    do_post_install;
19202545eb61SSteven Rostedt}
19212545eb61SSteven Rostedt
1922ddf607e5SSteven Rostedtsub get_version {
1923ddf607e5SSteven Rostedt    # get the release name
1924683a3e64SSteven Rostedt    return if ($have_version);
1925ddf607e5SSteven Rostedt    doprint "$make kernelrelease ... ";
1926ddf607e5SSteven Rostedt    $version = `$make kernelrelease | tail -1`;
1927ddf607e5SSteven Rostedt    chomp($version);
1928ddf607e5SSteven Rostedt    doprint "$version\n";
1929683a3e64SSteven Rostedt    $have_version = 1;
1930ddf607e5SSteven Rostedt}
1931ddf607e5SSteven Rostedt
1932ddf607e5SSteven Rostedtsub start_monitor_and_boot {
19339f7424ccSSteven Rostedt    # Make sure the stable kernel has finished booting
1934319ab14fSSteven Rostedt (Red Hat)
1935319ab14fSSteven Rostedt (Red Hat)    # Install bisects, don't need console
1936319ab14fSSteven Rostedt (Red Hat)    if (defined $console) {
19379f7424ccSSteven Rostedt	start_monitor;
19389f7424ccSSteven Rostedt	wait_for_monitor 5;
19399f7424ccSSteven Rostedt	end_monitor;
1940319ab14fSSteven Rostedt (Red Hat)    }
19419f7424ccSSteven Rostedt
1942ddf607e5SSteven Rostedt    get_grub_index;
1943ddf607e5SSteven Rostedt    get_version;
1944ddf607e5SSteven Rostedt    install;
1945ddf607e5SSteven Rostedt
1946319ab14fSSteven Rostedt (Red Hat)    start_monitor if (defined $console);
1947ddf607e5SSteven Rostedt    return monitor;
1948ddf607e5SSteven Rostedt}
1949ddf607e5SSteven Rostedt
19504283b169SSteven Rostedt (Red Hat)my $check_build_re = ".*:.*(warning|error|Error):.*";
19514283b169SSteven Rostedt (Red Hat)my $utf8_quote = "\\x{e2}\\x{80}(\\x{98}|\\x{99})";
19524283b169SSteven Rostedt (Red Hat)
19537328735cSSteven Rostedt (Red Hat)sub process_warning_line {
19547328735cSSteven Rostedt (Red Hat)    my ($line) = @_;
19557328735cSSteven Rostedt (Red Hat)
19567328735cSSteven Rostedt (Red Hat)    chomp $line;
19577328735cSSteven Rostedt (Red Hat)
19587328735cSSteven Rostedt (Red Hat)    # for distcc heterogeneous systems, some compilers
19597328735cSSteven Rostedt (Red Hat)    # do things differently causing warning lines
19607328735cSSteven Rostedt (Red Hat)    # to be slightly different. This makes an attempt
19617328735cSSteven Rostedt (Red Hat)    # to fixe those issues.
19627328735cSSteven Rostedt (Red Hat)
19637328735cSSteven Rostedt (Red Hat)    # chop off the index into the line
19647328735cSSteven Rostedt (Red Hat)    # using distcc, some compilers give different indexes
19657328735cSSteven Rostedt (Red Hat)    # depending on white space
19667328735cSSteven Rostedt (Red Hat)    $line =~ s/^(\s*\S+:\d+:)\d+/$1/;
19677328735cSSteven Rostedt (Red Hat)
19687328735cSSteven Rostedt (Red Hat)    # Some compilers use UTF-8 extended for quotes and some don't.
19697328735cSSteven Rostedt (Red Hat)    $line =~ s/$utf8_quote/'/g;
19707328735cSSteven Rostedt (Red Hat)
19717328735cSSteven Rostedt (Red Hat)    return $line;
19727328735cSSteven Rostedt (Red Hat)}
19737328735cSSteven Rostedt (Red Hat)
19744283b169SSteven Rostedt (Red Hat)# Read buildlog and check against warnings file for any
19754283b169SSteven Rostedt (Red Hat)# new warnings.
19764283b169SSteven Rostedt (Red Hat)#
19774283b169SSteven Rostedt (Red Hat)# Returns 1 if OK
19784283b169SSteven Rostedt (Red Hat)#         0 otherwise
19796c5ee0beSSteven Rostedtsub check_buildlog {
19804283b169SSteven Rostedt (Red Hat)    return 1 if (!defined $warnings_file);
19814283b169SSteven Rostedt (Red Hat)
19824283b169SSteven Rostedt (Red Hat)    my %warnings_list;
19834283b169SSteven Rostedt (Red Hat)
19844283b169SSteven Rostedt (Red Hat)    # Failed builds should not reboot the target
19854283b169SSteven Rostedt (Red Hat)    my $save_no_reboot = $no_reboot;
19864283b169SSteven Rostedt (Red Hat)    $no_reboot = 1;
19874283b169SSteven Rostedt (Red Hat)
19884283b169SSteven Rostedt (Red Hat)    if (-f $warnings_file) {
19894283b169SSteven Rostedt (Red Hat)	open(IN, $warnings_file) or
19904283b169SSteven Rostedt (Red Hat)	    dodie "Error opening $warnings_file";
19914283b169SSteven Rostedt (Red Hat)
19924283b169SSteven Rostedt (Red Hat)	while (<IN>) {
19934283b169SSteven Rostedt (Red Hat)	    if (/$check_build_re/) {
19947328735cSSteven Rostedt (Red Hat)		my $warning = process_warning_line $_;
19957328735cSSteven Rostedt (Red Hat)
19967328735cSSteven Rostedt (Red Hat)		$warnings_list{$warning} = 1;
19974283b169SSteven Rostedt (Red Hat)	    }
19984283b169SSteven Rostedt (Red Hat)	}
19994283b169SSteven Rostedt (Red Hat)	close(IN);
20004283b169SSteven Rostedt (Red Hat)    }
20014283b169SSteven Rostedt (Red Hat)
20024283b169SSteven Rostedt (Red Hat)    # If warnings file didn't exist, and WARNINGS_FILE exist,
20034283b169SSteven Rostedt (Red Hat)    # then we fail on any warning!
20044283b169SSteven Rostedt (Red Hat)
20054283b169SSteven Rostedt (Red Hat)    open(IN, $buildlog) or dodie "Can't open $buildlog";
20064283b169SSteven Rostedt (Red Hat)    while (<IN>) {
20074283b169SSteven Rostedt (Red Hat)	if (/$check_build_re/) {
20087328735cSSteven Rostedt (Red Hat)	    my $warning = process_warning_line $_;
20094283b169SSteven Rostedt (Red Hat)
20107328735cSSteven Rostedt (Red Hat)	    if (!defined $warnings_list{$warning}) {
20114283b169SSteven Rostedt (Red Hat)		fail "New warning found (not in $warnings_file)\n$_\n";
20124283b169SSteven Rostedt (Red Hat)		$no_reboot = $save_no_reboot;
20134283b169SSteven Rostedt (Red Hat)		return 0;
20144283b169SSteven Rostedt (Red Hat)	    }
20154283b169SSteven Rostedt (Red Hat)	}
20164283b169SSteven Rostedt (Red Hat)    }
20174283b169SSteven Rostedt (Red Hat)    $no_reboot = $save_no_reboot;
20184283b169SSteven Rostedt (Red Hat)    close(IN);
20194283b169SSteven Rostedt (Red Hat)}
20204283b169SSteven Rostedt (Red Hat)
20214283b169SSteven Rostedt (Red Hat)sub check_patch_buildlog {
20226c5ee0beSSteven Rostedt    my ($patch) = @_;
20236c5ee0beSSteven Rostedt
20246c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
20256c5ee0beSSteven Rostedt
202635275685SSteven Rostedt (Red Hat)    foreach my $file (@files) {
202735275685SSteven Rostedt (Red Hat)	chomp $file;
202835275685SSteven Rostedt (Red Hat)    }
202935275685SSteven Rostedt (Red Hat)
20306c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
20316c5ee0beSSteven Rostedt	dodie "failed to show $patch";
20326c5ee0beSSteven Rostedt    while (<IN>) {
20336c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
20346c5ee0beSSteven Rostedt	    chomp $1;
20356c5ee0beSSteven Rostedt	    $files[$#files] = $1;
20366c5ee0beSSteven Rostedt	}
20376c5ee0beSSteven Rostedt    }
20386c5ee0beSSteven Rostedt    close(IN);
20396c5ee0beSSteven Rostedt
20406c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
20416c5ee0beSSteven Rostedt    while (<IN>) {
20426c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
20436c5ee0beSSteven Rostedt	    my $err = $1;
20446c5ee0beSSteven Rostedt	    foreach my $file (@files) {
2045a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
20466c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
20472b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
20486c5ee0beSSteven Rostedt		}
20496c5ee0beSSteven Rostedt	    }
20506c5ee0beSSteven Rostedt	}
20516c5ee0beSSteven Rostedt    }
20526c5ee0beSSteven Rostedt    close(IN);
20532b7d9b21SSteven Rostedt
20542b7d9b21SSteven Rostedt    return 1;
20556c5ee0beSSteven Rostedt}
20566c5ee0beSSteven Rostedt
2057fcb3f16aSSteven Rostedtsub apply_min_config {
2058fcb3f16aSSteven Rostedt    my $outconfig = "$output_config.new";
2059612b9e9bSSteven Rostedt
2060fcb3f16aSSteven Rostedt    # Read the config file and remove anything that
2061fcb3f16aSSteven Rostedt    # is in the force_config hash (from minconfig and others)
2062fcb3f16aSSteven Rostedt    # then add the force config back.
2063fcb3f16aSSteven Rostedt
2064fcb3f16aSSteven Rostedt    doprint "Applying minimum configurations into $output_config.new\n";
2065fcb3f16aSSteven Rostedt
2066fcb3f16aSSteven Rostedt    open (OUT, ">$outconfig") or
2067fcb3f16aSSteven Rostedt	dodie "Can't create $outconfig";
2068fcb3f16aSSteven Rostedt
2069fcb3f16aSSteven Rostedt    if (-f $output_config) {
2070fcb3f16aSSteven Rostedt	open (IN, $output_config) or
2071fcb3f16aSSteven Rostedt	    dodie "Failed to open $output_config";
2072fcb3f16aSSteven Rostedt	while (<IN>) {
2073fcb3f16aSSteven Rostedt	    if (/^(# )?(CONFIG_[^\s=]*)/) {
2074fcb3f16aSSteven Rostedt		next if (defined($force_config{$2}));
2075fcb3f16aSSteven Rostedt	    }
2076fcb3f16aSSteven Rostedt	    print OUT;
2077fcb3f16aSSteven Rostedt	}
2078fcb3f16aSSteven Rostedt	close IN;
2079fcb3f16aSSteven Rostedt    }
2080fcb3f16aSSteven Rostedt    foreach my $config (keys %force_config) {
2081fcb3f16aSSteven Rostedt	print OUT "$force_config{$config}\n";
2082fcb3f16aSSteven Rostedt    }
2083fcb3f16aSSteven Rostedt    close OUT;
2084fcb3f16aSSteven Rostedt
2085fcb3f16aSSteven Rostedt    run_command "mv $outconfig $output_config";
2086fcb3f16aSSteven Rostedt}
2087fcb3f16aSSteven Rostedt
2088fcb3f16aSSteven Rostedtsub make_oldconfig {
2089fcb3f16aSSteven Rostedt
20904c4ab120SSteven Rostedt    my @force_list = keys %force_config;
20914c4ab120SSteven Rostedt
20924c4ab120SSteven Rostedt    if ($#force_list >= 0) {
2093fcb3f16aSSteven Rostedt	apply_min_config;
20944c4ab120SSteven Rostedt    }
2095fcb3f16aSSteven Rostedt
2096fb16d891SAdam Lee    if (!run_command "$make olddefconfig") {
2097fb16d891SAdam Lee	# Perhaps olddefconfig doesn't exist in this version of the kernel
209818925170SSteven Rostedt	# try oldnoconfig
209918925170SSteven Rostedt	doprint "olddefconfig failed, trying make oldnoconfig\n";
210018925170SSteven Rostedt	if (!run_command "$make oldnoconfig") {
210118925170SSteven Rostedt	    doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
2102612b9e9bSSteven Rostedt	    # try a yes '' | oldconfig
2103fcb3f16aSSteven Rostedt	    run_command "yes '' | $make oldconfig" or
2104612b9e9bSSteven Rostedt		dodie "failed make config oldconfig";
2105612b9e9bSSteven Rostedt	}
2106612b9e9bSSteven Rostedt    }
210718925170SSteven Rostedt}
2108612b9e9bSSteven Rostedt
2109fcb3f16aSSteven Rostedt# read a config file and use this to force new configs.
2110fcb3f16aSSteven Rostedtsub load_force_config {
2111fcb3f16aSSteven Rostedt    my ($config) = @_;
2112fcb3f16aSSteven Rostedt
2113cf79fab6SSteven Rostedt    doprint "Loading force configs from $config\n";
2114fcb3f16aSSteven Rostedt    open(IN, $config) or
2115fcb3f16aSSteven Rostedt	dodie "failed to read $config";
2116fcb3f16aSSteven Rostedt    while (<IN>) {
2117fcb3f16aSSteven Rostedt	chomp;
2118fcb3f16aSSteven Rostedt	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
2119fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
2120fcb3f16aSSteven Rostedt	} elsif (/^# (CONFIG_\S*) is not set/) {
2121fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
2122fcb3f16aSSteven Rostedt	}
2123fcb3f16aSSteven Rostedt    }
2124fcb3f16aSSteven Rostedt    close IN;
2125fcb3f16aSSteven Rostedt}
2126fcb3f16aSSteven Rostedt
21272545eb61SSteven Rostedtsub build {
21282545eb61SSteven Rostedt    my ($type) = @_;
21292545eb61SSteven Rostedt
21307faafbd6SSteven Rostedt    unlink $buildlog;
21317faafbd6SSteven Rostedt
21324ab1cce5SSteven Rostedt    # Failed builds should not reboot the target
21334ab1cce5SSteven Rostedt    my $save_no_reboot = $no_reboot;
21344ab1cce5SSteven Rostedt    $no_reboot = 1;
21354ab1cce5SSteven Rostedt
2136683a3e64SSteven Rostedt    # Calculate a new version from here.
2137683a3e64SSteven Rostedt    $have_version = 0;
2138683a3e64SSteven Rostedt
21390bd6c1a3SSteven Rostedt    if (defined($pre_build)) {
21400bd6c1a3SSteven Rostedt	my $ret = run_command $pre_build;
21410bd6c1a3SSteven Rostedt	if (!$ret && defined($pre_build_die) &&
21420bd6c1a3SSteven Rostedt	    $pre_build_die) {
21430bd6c1a3SSteven Rostedt	    dodie "failed to pre_build\n";
21440bd6c1a3SSteven Rostedt	}
21450bd6c1a3SSteven Rostedt    }
21460bd6c1a3SSteven Rostedt
214775c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
214851ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
214975c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
21505f9b6cedSSteven Rostedt
215175c3fda7SSteven Rostedt	$type = "oldconfig";
215275c3fda7SSteven Rostedt    }
215375c3fda7SSteven Rostedt
21545c42fc5bSSteven Rostedt    # old config can ask questions
21555c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
2156fb16d891SAdam Lee	$type = "olddefconfig";
215775c3fda7SSteven Rostedt
215875c3fda7SSteven Rostedt	# allow for empty configs
215951ad1dd1SSteven Rostedt	run_command "touch $output_config";
216075c3fda7SSteven Rostedt
216113488231SAndrew Jones	if (!$noclean) {
216251ad1dd1SSteven Rostedt	    run_command "mv $output_config $outputdir/config_temp" or
21635c42fc5bSSteven Rostedt		dodie "moving .config";
21645c42fc5bSSteven Rostedt
216513488231SAndrew Jones	    run_command "$make mrproper" or dodie "make mrproper";
21665c42fc5bSSteven Rostedt
216751ad1dd1SSteven Rostedt	    run_command "mv $outputdir/config_temp $output_config" or
21685c42fc5bSSteven Rostedt		dodie "moving config_temp";
216913488231SAndrew Jones	}
21705c42fc5bSSteven Rostedt
21715c42fc5bSSteven Rostedt    } elsif (!$noclean) {
217251ad1dd1SSteven Rostedt	unlink "$output_config";
21735f9b6cedSSteven Rostedt	run_command "$make mrproper" or
21745c42fc5bSSteven Rostedt	    dodie "make mrproper";
21755c42fc5bSSteven Rostedt    }
21762545eb61SSteven Rostedt
21772545eb61SSteven Rostedt    # add something to distinguish this build
2178a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
2179a75fececSSteven Rostedt    print OUT "$localversion\n";
21802545eb61SSteven Rostedt    close(OUT);
21812545eb61SSteven Rostedt
21825f9b6cedSSteven Rostedt    if (defined($minconfig)) {
2183fcb3f16aSSteven Rostedt	load_force_config($minconfig);
21842545eb61SSteven Rostedt    }
21852545eb61SSteven Rostedt
2186fb16d891SAdam Lee    if ($type ne "olddefconfig") {
2187fcb3f16aSSteven Rostedt	run_command "$make $type" or
21885c42fc5bSSteven Rostedt	    dodie "failed make config";
2189612b9e9bSSteven Rostedt    }
2190fcb3f16aSSteven Rostedt    # Run old config regardless, to enforce min configurations
2191fcb3f16aSSteven Rostedt    make_oldconfig;
21922545eb61SSteven Rostedt
2193a75fececSSteven Rostedt    $redirect = "$buildlog";
21940bd6c1a3SSteven Rostedt    my $build_ret = run_command "$make $build_options";
21956c5ee0beSSteven Rostedt    undef $redirect;
21960bd6c1a3SSteven Rostedt
21970bd6c1a3SSteven Rostedt    if (defined($post_build)) {
2198683a3e64SSteven Rostedt	# Because a post build may change the kernel version
2199683a3e64SSteven Rostedt	# do it now.
2200683a3e64SSteven Rostedt	get_version;
22010bd6c1a3SSteven Rostedt	my $ret = run_command $post_build;
22020bd6c1a3SSteven Rostedt	if (!$ret && defined($post_build_die) &&
22030bd6c1a3SSteven Rostedt	    $post_build_die) {
22040bd6c1a3SSteven Rostedt	    dodie "failed to post_build\n";
22050bd6c1a3SSteven Rostedt	}
22060bd6c1a3SSteven Rostedt    }
22070bd6c1a3SSteven Rostedt
22080bd6c1a3SSteven Rostedt    if (!$build_ret) {
22095f9b6cedSSteven Rostedt	# bisect may need this to pass
22104ab1cce5SSteven Rostedt	if ($in_bisect) {
22114ab1cce5SSteven Rostedt	    $no_reboot = $save_no_reboot;
22124ab1cce5SSteven Rostedt	    return 0;
22134ab1cce5SSteven Rostedt	}
22142b7d9b21SSteven Rostedt	fail "failed build" and return 0;
22152545eb61SSteven Rostedt    }
22165f9b6cedSSteven Rostedt
22174ab1cce5SSteven Rostedt    $no_reboot = $save_no_reboot;
22184ab1cce5SSteven Rostedt
22192b7d9b21SSteven Rostedt    return 1;
22202545eb61SSteven Rostedt}
22212545eb61SSteven Rostedt
222275c3fda7SSteven Rostedtsub halt {
2223e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
2224576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
2225576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
2226576f627cSSteven Rostedt	    run_command "$power_off";
2227576f627cSSteven Rostedt	}
2228576f627cSSteven Rostedt    } else {
222975c3fda7SSteven Rostedt	# nope? the zap it!
2230a75fececSSteven Rostedt	run_command "$power_off";
223175c3fda7SSteven Rostedt    }
223275c3fda7SSteven Rostedt}
223375c3fda7SSteven Rostedt
22345f9b6cedSSteven Rostedtsub success {
22355f9b6cedSSteven Rostedt    my ($i) = @_;
22365f9b6cedSSteven Rostedt
2237921ed4c7SSteven Rostedt    if (defined($post_test)) {
2238921ed4c7SSteven Rostedt	run_command $post_test;
2239921ed4c7SSteven Rostedt    }
2240921ed4c7SSteven Rostedt
2241e48c5293SSteven Rostedt    $successes++;
2242e48c5293SSteven Rostedt
22439064af52SSteven Rostedt    my $name = "";
22449064af52SSteven Rostedt
22459064af52SSteven Rostedt    if (defined($test_name)) {
22469064af52SSteven Rostedt	$name = " ($test_name)";
22479064af52SSteven Rostedt    }
22489064af52SSteven Rostedt
22495f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
22505f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
22519064af52SSteven Rostedt    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
22525f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
22535f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
22545f9b6cedSSteven Rostedt
2255de5b6e3bSRabin Vincent    if (defined($store_successes)) {
2256de5b6e3bSRabin Vincent        save_logs "success", $store_successes;
2257de5b6e3bSRabin Vincent    }
2258de5b6e3bSRabin Vincent
2259576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
2260a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
2261bc7c5803SSteven Rostedt	reboot_to_good $sleep_time;
22625f9b6cedSSteven Rostedt    }
22635f9b6cedSSteven Rostedt}
22645f9b6cedSSteven Rostedt
2265c960bb9fSSteven Rostedtsub answer_bisect {
2266c960bb9fSSteven Rostedt    for (;;) {
2267c960bb9fSSteven Rostedt	doprint "Pass or fail? [p/f]";
2268c960bb9fSSteven Rostedt	my $ans = <STDIN>;
2269c960bb9fSSteven Rostedt	chomp $ans;
2270c960bb9fSSteven Rostedt	if ($ans eq "p" || $ans eq "P") {
2271c960bb9fSSteven Rostedt	    return 1;
2272c960bb9fSSteven Rostedt	} elsif ($ans eq "f" || $ans eq "F") {
2273c960bb9fSSteven Rostedt	    return 0;
2274c960bb9fSSteven Rostedt	} else {
2275c960bb9fSSteven Rostedt	    print "Please answer 'P' or 'F'\n";
2276c960bb9fSSteven Rostedt	}
2277c960bb9fSSteven Rostedt    }
2278c960bb9fSSteven Rostedt}
2279c960bb9fSSteven Rostedt
22805a391fbfSSteven Rostedtsub child_run_test {
22817faafbd6SSteven Rostedt    my $failed = 0;
22825a391fbfSSteven Rostedt
22837faafbd6SSteven Rostedt    # child should have no power
2284a75fececSSteven Rostedt    $reboot_on_error = 0;
2285a75fececSSteven Rostedt    $poweroff_on_error = 0;
2286a75fececSSteven Rostedt    $die_on_failure = 1;
22877faafbd6SSteven Rostedt
2288a9dd5d63SRabin Vincent    $redirect = "$testlog";
22897faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
2290a9dd5d63SRabin Vincent    undef $redirect;
2291a9dd5d63SRabin Vincent
22925a391fbfSSteven Rostedt    exit $failed;
22935a391fbfSSteven Rostedt}
22945a391fbfSSteven Rostedt
22955a391fbfSSteven Rostedtmy $child_done;
22965a391fbfSSteven Rostedt
22975a391fbfSSteven Rostedtsub child_finished {
22985a391fbfSSteven Rostedt    $child_done = 1;
22995a391fbfSSteven Rostedt}
23005a391fbfSSteven Rostedt
23015a391fbfSSteven Rostedtsub do_run_test {
23025a391fbfSSteven Rostedt    my $child_pid;
23035a391fbfSSteven Rostedt    my $child_exit;
23045a391fbfSSteven Rostedt    my $line;
23055a391fbfSSteven Rostedt    my $full_line;
23065a391fbfSSteven Rostedt    my $bug = 0;
23079b1d367dSSteven Rostedt    my $bug_ignored = 0;
23085a391fbfSSteven Rostedt
23097faafbd6SSteven Rostedt    wait_for_monitor 1;
23105a391fbfSSteven Rostedt
23117faafbd6SSteven Rostedt    doprint "run test $run_test\n";
23125a391fbfSSteven Rostedt
23135a391fbfSSteven Rostedt    $child_done = 0;
23145a391fbfSSteven Rostedt
23155a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
23165a391fbfSSteven Rostedt
23175a391fbfSSteven Rostedt    $child_pid = fork;
23185a391fbfSSteven Rostedt
23195a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
23205a391fbfSSteven Rostedt
23215a391fbfSSteven Rostedt    $full_line = "";
23225a391fbfSSteven Rostedt
23235a391fbfSSteven Rostedt    do {
23247faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
23255a391fbfSSteven Rostedt	if (defined($line)) {
23265a391fbfSSteven Rostedt
23275a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
23285a391fbfSSteven Rostedt	    $full_line .= $line;
23298ea0e063SSteven Rostedt	    doprint $line;
23305a391fbfSSteven Rostedt
23315a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
23329b1d367dSSteven Rostedt		if ($ignore_errors) {
23339b1d367dSSteven Rostedt		    $bug_ignored = 1;
23349b1d367dSSteven Rostedt		} else {
23355a391fbfSSteven Rostedt		    $bug = 1;
23365a391fbfSSteven Rostedt		}
23379b1d367dSSteven Rostedt	    }
23385a391fbfSSteven Rostedt
23395a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
23405a391fbfSSteven Rostedt		$bug = 1;
23415a391fbfSSteven Rostedt	    }
23425a391fbfSSteven Rostedt
23435a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
23445a391fbfSSteven Rostedt		$full_line = "";
23455a391fbfSSteven Rostedt	    }
23465a391fbfSSteven Rostedt	}
23475a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
23485a391fbfSSteven Rostedt
23499b1d367dSSteven Rostedt    if (!$bug && $bug_ignored) {
23509b1d367dSSteven Rostedt	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
23519b1d367dSSteven Rostedt    }
23529b1d367dSSteven Rostedt
23535a391fbfSSteven Rostedt    if ($bug) {
23548ea0e063SSteven Rostedt	my $failure_start = time;
23558ea0e063SSteven Rostedt	my $now;
23568ea0e063SSteven Rostedt	do {
23578ea0e063SSteven Rostedt	    $line = wait_for_input($monitor_fp, 1);
23588ea0e063SSteven Rostedt	    if (defined($line)) {
23598ea0e063SSteven Rostedt		doprint $line;
23608ea0e063SSteven Rostedt	    }
23618ea0e063SSteven Rostedt	    $now = time;
23628ea0e063SSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
23638ea0e063SSteven Rostedt		last;
23648ea0e063SSteven Rostedt	    }
23658ea0e063SSteven Rostedt	} while (defined($line));
23668ea0e063SSteven Rostedt
23675a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
23685a391fbfSSteven Rostedt	# kill the child with extreme prejudice
23695a391fbfSSteven Rostedt	kill 9, $child_pid;
23705a391fbfSSteven Rostedt    }
23715a391fbfSSteven Rostedt
23725a391fbfSSteven Rostedt    waitpid $child_pid, 0;
23735a391fbfSSteven Rostedt    $child_exit = $?;
23745a391fbfSSteven Rostedt
2375c5dacb88SSteven Rostedt    if (!$bug && $in_bisect) {
2376c5dacb88SSteven Rostedt	if (defined($bisect_ret_good)) {
2377c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_good) {
2378c5dacb88SSteven Rostedt		return 1;
2379c5dacb88SSteven Rostedt	    }
2380c5dacb88SSteven Rostedt	}
2381c5dacb88SSteven Rostedt	if (defined($bisect_ret_skip)) {
2382c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_skip) {
2383c5dacb88SSteven Rostedt		return -1;
2384c5dacb88SSteven Rostedt	    }
2385c5dacb88SSteven Rostedt	}
2386c5dacb88SSteven Rostedt	if (defined($bisect_ret_abort)) {
2387c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_abort) {
2388c5dacb88SSteven Rostedt		fail "test abort" and return -2;
2389c5dacb88SSteven Rostedt	    }
2390c5dacb88SSteven Rostedt	}
2391c5dacb88SSteven Rostedt	if (defined($bisect_ret_bad)) {
2392c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_skip) {
2393c5dacb88SSteven Rostedt		return 0;
2394c5dacb88SSteven Rostedt	    }
2395c5dacb88SSteven Rostedt	}
2396c5dacb88SSteven Rostedt	if (defined($bisect_ret_default)) {
2397c5dacb88SSteven Rostedt	    if ($bisect_ret_default eq "good") {
2398c5dacb88SSteven Rostedt		return 1;
2399c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "bad") {
2400c5dacb88SSteven Rostedt		return 0;
2401c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "skip") {
2402c5dacb88SSteven Rostedt		return -1;
2403c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "abort") {
2404c5dacb88SSteven Rostedt		return -2;
2405c5dacb88SSteven Rostedt	    } else {
2406c5dacb88SSteven Rostedt		fail "unknown default action: $bisect_ret_default"
2407c5dacb88SSteven Rostedt		    and return -2;
2408c5dacb88SSteven Rostedt	    }
2409c5dacb88SSteven Rostedt	}
2410c5dacb88SSteven Rostedt    }
2411c5dacb88SSteven Rostedt
24125a391fbfSSteven Rostedt    if ($bug || $child_exit) {
24132b7d9b21SSteven Rostedt	return 0 if $in_bisect;
24142b7d9b21SSteven Rostedt	fail "test failed" and return 0;
24155a391fbfSSteven Rostedt    }
24162b7d9b21SSteven Rostedt    return 1;
24175a391fbfSSteven Rostedt}
24185a391fbfSSteven Rostedt
2419a75fececSSteven Rostedtsub run_git_bisect {
2420a75fececSSteven Rostedt    my ($command) = @_;
2421a75fececSSteven Rostedt
2422a75fececSSteven Rostedt    doprint "$command ... ";
2423a75fececSSteven Rostedt
2424a75fececSSteven Rostedt    my $output = `$command 2>&1`;
2425a75fececSSteven Rostedt    my $ret = $?;
2426a75fececSSteven Rostedt
2427a75fececSSteven Rostedt    logit $output;
2428a75fececSSteven Rostedt
2429a75fececSSteven Rostedt    if ($ret) {
2430a75fececSSteven Rostedt	doprint "FAILED\n";
2431a75fececSSteven Rostedt	dodie "Failed to git bisect";
2432a75fececSSteven Rostedt    }
2433a75fececSSteven Rostedt
2434a75fececSSteven Rostedt    doprint "SUCCESS\n";
2435a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
2436a75fececSSteven Rostedt	doprint "$1 [$2]\n";
2437a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
2438b5f4aea6SSteven Rostedt	$bisect_bad_commit = $1;
2439a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
2440a75fececSSteven Rostedt	return 0;
2441a75fececSSteven Rostedt    } else {
2442a75fececSSteven Rostedt	# we already logged it, just print it now.
2443a75fececSSteven Rostedt	print $output;
2444a75fececSSteven Rostedt    }
2445a75fececSSteven Rostedt
2446a75fececSSteven Rostedt    return 1;
2447a75fececSSteven Rostedt}
2448a75fececSSteven Rostedt
2449c23dca7cSSteven Rostedtsub bisect_reboot {
2450c23dca7cSSteven Rostedt    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
2451bc7c5803SSteven Rostedt    reboot_to_good $bisect_sleep_time;
2452c23dca7cSSteven Rostedt}
2453c23dca7cSSteven Rostedt
2454c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip
24550a05c769SSteven Rostedtsub run_bisect_test {
24560a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
24575f9b6cedSSteven Rostedt
24582b7d9b21SSteven Rostedt    my $failed = 0;
24595f9b6cedSSteven Rostedt    my $result;
24605f9b6cedSSteven Rostedt    my $output;
24615f9b6cedSSteven Rostedt    my $ret;
24625f9b6cedSSteven Rostedt
24630a05c769SSteven Rostedt    $in_bisect = 1;
24640a05c769SSteven Rostedt
24650a05c769SSteven Rostedt    build $buildtype or $failed = 1;
24665f9b6cedSSteven Rostedt
24675f9b6cedSSteven Rostedt    if ($type ne "build") {
2468c23dca7cSSteven Rostedt	if ($failed && $bisect_skip) {
2469c23dca7cSSteven Rostedt	    $in_bisect = 0;
2470c23dca7cSSteven Rostedt	    return -1;
2471c23dca7cSSteven Rostedt	}
24727faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
24735f9b6cedSSteven Rostedt
24745f9b6cedSSteven Rostedt	# Now boot the box
2475ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
24765f9b6cedSSteven Rostedt
24775f9b6cedSSteven Rostedt	if ($type ne "boot") {
2478c23dca7cSSteven Rostedt	    if ($failed && $bisect_skip) {
2479c23dca7cSSteven Rostedt		end_monitor;
2480c23dca7cSSteven Rostedt		bisect_reboot;
2481c23dca7cSSteven Rostedt		$in_bisect = 0;
2482c23dca7cSSteven Rostedt		return -1;
2483c23dca7cSSteven Rostedt	    }
24847faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
24855a391fbfSSteven Rostedt
24862b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
24875f9b6cedSSteven Rostedt	}
24887faafbd6SSteven Rostedt	end_monitor;
24895f9b6cedSSteven Rostedt    }
24905f9b6cedSSteven Rostedt
24915f9b6cedSSteven Rostedt    if ($failed) {
24920a05c769SSteven Rostedt	$result = 0;
24935f9b6cedSSteven Rostedt    } else {
24940a05c769SSteven Rostedt	$result = 1;
24955f9b6cedSSteven Rostedt    }
24964025bc62SSteven Rostedt
24974025bc62SSteven Rostedt    # reboot the box to a kernel we can ssh to
24984025bc62SSteven Rostedt    if ($type ne "build") {
24994025bc62SSteven Rostedt	bisect_reboot;
25004025bc62SSteven Rostedt    }
25010a05c769SSteven Rostedt    $in_bisect = 0;
25020a05c769SSteven Rostedt
25030a05c769SSteven Rostedt    return $result;
25040a05c769SSteven Rostedt}
25050a05c769SSteven Rostedt
25060a05c769SSteven Rostedtsub run_bisect {
25070a05c769SSteven Rostedt    my ($type) = @_;
25080a05c769SSteven Rostedt    my $buildtype = "oldconfig";
25090a05c769SSteven Rostedt
25100a05c769SSteven Rostedt    # We should have a minconfig to use?
25110a05c769SSteven Rostedt    if (defined($minconfig)) {
25120a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
25130a05c769SSteven Rostedt    }
25140a05c769SSteven Rostedt
25150a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
25160a05c769SSteven Rostedt
2517c960bb9fSSteven Rostedt    if ($bisect_manual) {
2518c960bb9fSSteven Rostedt	$ret = answer_bisect;
2519c960bb9fSSteven Rostedt    }
25205f9b6cedSSteven Rostedt
2521d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
25225158ba3eSRuss Dill    if ($reverse_bisect && $ret >= 0) {
25230a05c769SSteven Rostedt	$ret = !$ret;
2524d6ce2a0bSSteven Rostedt    }
2525d6ce2a0bSSteven Rostedt
2526c23dca7cSSteven Rostedt    if ($ret > 0) {
25270a05c769SSteven Rostedt	return "good";
2528c23dca7cSSteven Rostedt    } elsif ($ret == 0) {
25290a05c769SSteven Rostedt	return  "bad";
2530c23dca7cSSteven Rostedt    } elsif ($bisect_skip) {
2531c23dca7cSSteven Rostedt	doprint "HIT A BAD COMMIT ... SKIPPING\n";
2532c23dca7cSSteven Rostedt	return "skip";
25330a05c769SSteven Rostedt    }
25345f9b6cedSSteven Rostedt}
25355f9b6cedSSteven Rostedt
2536dad98754SSteven Rostedtsub update_bisect_replay {
2537dad98754SSteven Rostedt    my $tmp_log = "$tmpdir/ktest_bisect_log";
2538dad98754SSteven Rostedt    run_command "git bisect log > $tmp_log" or
2539dad98754SSteven Rostedt	die "can't create bisect log";
2540dad98754SSteven Rostedt    return $tmp_log;
2541dad98754SSteven Rostedt}
2542dad98754SSteven Rostedt
25435f9b6cedSSteven Rostedtsub bisect {
25445f9b6cedSSteven Rostedt    my ($i) = @_;
25455f9b6cedSSteven Rostedt
25465f9b6cedSSteven Rostedt    my $result;
25475f9b6cedSSteven Rostedt
2548b5f4aea6SSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($bisect_good));
2549b5f4aea6SSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($bisect_bad));
2550b5f4aea6SSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($bisect_type));
25515f9b6cedSSteven Rostedt
2552b5f4aea6SSteven Rostedt    my $good = $bisect_good;
2553b5f4aea6SSteven Rostedt    my $bad = $bisect_bad;
2554b5f4aea6SSteven Rostedt    my $type = $bisect_type;
2555b5f4aea6SSteven Rostedt    my $start = $bisect_start;
2556b5f4aea6SSteven Rostedt    my $replay = $bisect_replay;
2557b5f4aea6SSteven Rostedt    my $start_files = $bisect_files;
25583410f6fdSSteven Rostedt
25593410f6fdSSteven Rostedt    if (defined($start_files)) {
25603410f6fdSSteven Rostedt	$start_files = " -- " . $start_files;
25613410f6fdSSteven Rostedt    } else {
25623410f6fdSSteven Rostedt	$start_files = "";
25633410f6fdSSteven Rostedt    }
25645f9b6cedSSteven Rostedt
2565a57419b3SSteven Rostedt    # convert to true sha1's
2566a57419b3SSteven Rostedt    $good = get_sha1($good);
2567a57419b3SSteven Rostedt    $bad = get_sha1($bad);
2568a57419b3SSteven Rostedt
2569b5f4aea6SSteven Rostedt    if (defined($bisect_reverse) && $bisect_reverse == 1) {
2570d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
2571d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
2572d6ce2a0bSSteven Rostedt    } else {
2573d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
2574d6ce2a0bSSteven Rostedt    }
2575d6ce2a0bSSteven Rostedt
25765a391fbfSSteven Rostedt    # Can't have a test without having a test to run
25775a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
25785a391fbfSSteven Rostedt	$type = "boot";
25795a391fbfSSteven Rostedt    }
25805a391fbfSSteven Rostedt
2581dad98754SSteven Rostedt    # Check if a bisect was running
2582dad98754SSteven Rostedt    my $bisect_start_file = "$builddir/.git/BISECT_START";
2583dad98754SSteven Rostedt
2584b5f4aea6SSteven Rostedt    my $check = $bisect_check;
2585dad98754SSteven Rostedt    my $do_check = defined($check) && $check ne "0";
2586dad98754SSteven Rostedt
2587dad98754SSteven Rostedt    if ( -f $bisect_start_file ) {
2588dad98754SSteven Rostedt	print "Bisect in progress found\n";
2589dad98754SSteven Rostedt	if ($do_check) {
2590dad98754SSteven Rostedt	    print " If you say yes, then no checks of good or bad will be done\n";
2591dad98754SSteven Rostedt	}
2592dad98754SSteven Rostedt	if (defined($replay)) {
2593dad98754SSteven Rostedt	    print "** BISECT_REPLAY is defined in config file **";
2594dad98754SSteven Rostedt	    print " Ignore config option and perform new git bisect log?\n";
2595dad98754SSteven Rostedt	    if (read_ync " (yes, no, or cancel) ") {
2596dad98754SSteven Rostedt		$replay = update_bisect_replay;
2597dad98754SSteven Rostedt		$do_check = 0;
2598dad98754SSteven Rostedt	    }
2599dad98754SSteven Rostedt	} elsif (read_yn "read git log and continue?") {
2600dad98754SSteven Rostedt	    $replay = update_bisect_replay;
2601dad98754SSteven Rostedt	    $do_check = 0;
2602dad98754SSteven Rostedt	}
2603dad98754SSteven Rostedt    }
2604dad98754SSteven Rostedt
2605dad98754SSteven Rostedt    if ($do_check) {
2606a75fececSSteven Rostedt
2607a75fececSSteven Rostedt	# get current HEAD
2608a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
2609a75fececSSteven Rostedt
2610a75fececSSteven Rostedt	if ($check ne "good") {
2611a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
2612a75fececSSteven Rostedt	    run_command "git checkout $bad" or
2613a75fececSSteven Rostedt		die "Failed to checkout $bad";
2614a75fececSSteven Rostedt
2615a75fececSSteven Rostedt	    $result = run_bisect $type;
2616a75fececSSteven Rostedt
2617a75fececSSteven Rostedt	    if ($result ne "bad") {
2618a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
2619a75fececSSteven Rostedt	    }
2620a75fececSSteven Rostedt	}
2621a75fececSSteven Rostedt
2622a75fececSSteven Rostedt	if ($check ne "bad") {
2623a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
2624a75fececSSteven Rostedt	    run_command "git checkout $good" or
2625a75fececSSteven Rostedt		die "Failed to checkout $good";
2626a75fececSSteven Rostedt
2627a75fececSSteven Rostedt	    $result = run_bisect $type;
2628a75fececSSteven Rostedt
2629a75fececSSteven Rostedt	    if ($result ne "good") {
2630a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
2631a75fececSSteven Rostedt	    }
2632a75fececSSteven Rostedt	}
2633a75fececSSteven Rostedt
2634a75fececSSteven Rostedt	# checkout where we started
2635a75fececSSteven Rostedt	run_command "git checkout $head" or
2636a75fececSSteven Rostedt	    die "Failed to checkout $head";
2637a75fececSSteven Rostedt    }
2638a75fececSSteven Rostedt
26393410f6fdSSteven Rostedt    run_command "git bisect start$start_files" or
2640a75fececSSteven Rostedt	dodie "could not start bisect";
2641a75fececSSteven Rostedt
2642a75fececSSteven Rostedt    run_command "git bisect good $good" or
2643a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
2644a75fececSSteven Rostedt
2645a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
2646a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
2647a75fececSSteven Rostedt
2648a75fececSSteven Rostedt    if (defined($replay)) {
2649a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
2650a75fececSSteven Rostedt	    dodie "failed to run replay";
2651a75fececSSteven Rostedt    }
2652a75fececSSteven Rostedt
2653a75fececSSteven Rostedt    if (defined($start)) {
2654a75fececSSteven Rostedt	run_command "git checkout $start" or
2655a75fececSSteven Rostedt	    dodie "failed to checkout $start";
2656a75fececSSteven Rostedt    }
2657a75fececSSteven Rostedt
2658a75fececSSteven Rostedt    my $test;
26595f9b6cedSSteven Rostedt    do {
26605f9b6cedSSteven Rostedt	$result = run_bisect $type;
2661a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
2662a75fececSSteven Rostedt    } while ($test);
26635f9b6cedSSteven Rostedt
26645f9b6cedSSteven Rostedt    run_command "git bisect log" or
26655f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
26665f9b6cedSSteven Rostedt
26675f9b6cedSSteven Rostedt    run_command "git bisect reset" or
26685f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
26695f9b6cedSSteven Rostedt
2670b5f4aea6SSteven Rostedt    doprint "Bad commit was [$bisect_bad_commit]\n";
26715f9b6cedSSteven Rostedt
26720a05c769SSteven Rostedt    success $i;
26730a05c769SSteven Rostedt}
26740a05c769SSteven Rostedt
2675cf79fab6SSteven Rostedt# config_ignore holds the configs that were set (or unset) for
2676cf79fab6SSteven Rostedt# a good config and we will ignore these configs for the rest
2677cf79fab6SSteven Rostedt# of a config bisect. These configs stay as they were.
26780a05c769SSteven Rostedtmy %config_ignore;
2679cf79fab6SSteven Rostedt
2680cf79fab6SSteven Rostedt# config_set holds what all configs were set as.
26810a05c769SSteven Rostedtmy %config_set;
26820a05c769SSteven Rostedt
2683cf79fab6SSteven Rostedt# config_off holds the set of configs that the bad config had disabled.
2684cf79fab6SSteven Rostedt# We need to record them and set them in the .config when running
2685fb16d891SAdam Lee# olddefconfig, because olddefconfig keeps the defaults.
2686cf79fab6SSteven Rostedtmy %config_off;
2687cf79fab6SSteven Rostedt
2688cf79fab6SSteven Rostedt# config_off_tmp holds a set of configs to turn off for now
2689cf79fab6SSteven Rostedtmy @config_off_tmp;
2690cf79fab6SSteven Rostedt
2691cf79fab6SSteven Rostedt# config_list is the set of configs that are being tested
26920a05c769SSteven Rostedtmy %config_list;
26930a05c769SSteven Rostedtmy %null_config;
26940a05c769SSteven Rostedt
26950a05c769SSteven Rostedtmy %dependency;
26960a05c769SSteven Rostedt
26974c4ab120SSteven Rostedtsub assign_configs {
26984c4ab120SSteven Rostedt    my ($hash, $config) = @_;
26990a05c769SSteven Rostedt
27000a05c769SSteven Rostedt    open (IN, $config)
27010a05c769SSteven Rostedt	or dodie "Failed to read $config";
27020a05c769SSteven Rostedt
27030a05c769SSteven Rostedt    while (<IN>) {
27049bf71749SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
27054c4ab120SSteven Rostedt	    ${$hash}{$2} = $1;
27060a05c769SSteven Rostedt	}
27070a05c769SSteven Rostedt    }
27080a05c769SSteven Rostedt
27090a05c769SSteven Rostedt    close(IN);
27100a05c769SSteven Rostedt}
27110a05c769SSteven Rostedt
27124c4ab120SSteven Rostedtsub process_config_ignore {
27134c4ab120SSteven Rostedt    my ($config) = @_;
27144c4ab120SSteven Rostedt
27154c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
27164c4ab120SSteven Rostedt}
27174c4ab120SSteven Rostedt
27180a05c769SSteven Rostedtsub read_current_config {
27190a05c769SSteven Rostedt    my ($config_ref) = @_;
27200a05c769SSteven Rostedt
27210a05c769SSteven Rostedt    %{$config_ref} = ();
27220a05c769SSteven Rostedt    undef %{$config_ref};
27230a05c769SSteven Rostedt
27240a05c769SSteven Rostedt    my @key = keys %{$config_ref};
27250a05c769SSteven Rostedt    if ($#key >= 0) {
27260a05c769SSteven Rostedt	print "did not delete!\n";
27270a05c769SSteven Rostedt	exit;
27280a05c769SSteven Rostedt    }
27290a05c769SSteven Rostedt    open (IN, "$output_config");
27300a05c769SSteven Rostedt
27310a05c769SSteven Rostedt    while (<IN>) {
27320a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
27330a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
27340a05c769SSteven Rostedt	}
27350a05c769SSteven Rostedt    }
27360a05c769SSteven Rostedt    close(IN);
27370a05c769SSteven Rostedt}
27380a05c769SSteven Rostedt
27390a05c769SSteven Rostedtsub get_dependencies {
27400a05c769SSteven Rostedt    my ($config) = @_;
27410a05c769SSteven Rostedt
27420a05c769SSteven Rostedt    my $arr = $dependency{$config};
27430a05c769SSteven Rostedt    if (!defined($arr)) {
27440a05c769SSteven Rostedt	return ();
27450a05c769SSteven Rostedt    }
27460a05c769SSteven Rostedt
27470a05c769SSteven Rostedt    my @deps = @{$arr};
27480a05c769SSteven Rostedt
27490a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
27500a05c769SSteven Rostedt	print "ADD DEP $dep\n";
27510a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
27520a05c769SSteven Rostedt    }
27530a05c769SSteven Rostedt
27540a05c769SSteven Rostedt    return @deps;
27550a05c769SSteven Rostedt}
27560a05c769SSteven Rostedt
27570a05c769SSteven Rostedtsub create_config {
27580a05c769SSteven Rostedt    my @configs = @_;
27590a05c769SSteven Rostedt
27600a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
27610a05c769SSteven Rostedt
27620a05c769SSteven Rostedt    foreach my $config (@configs) {
27630a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
27640a05c769SSteven Rostedt	my @deps = get_dependencies $config;
27650a05c769SSteven Rostedt	foreach my $dep (@deps) {
27660a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
27670a05c769SSteven Rostedt	}
27680a05c769SSteven Rostedt    }
27690a05c769SSteven Rostedt
2770cf79fab6SSteven Rostedt    # turn off configs to keep off
2771cf79fab6SSteven Rostedt    foreach my $config (keys %config_off) {
2772cf79fab6SSteven Rostedt	print OUT "# $config is not set\n";
2773cf79fab6SSteven Rostedt    }
2774cf79fab6SSteven Rostedt
2775cf79fab6SSteven Rostedt    # turn off configs that should be off for now
2776cf79fab6SSteven Rostedt    foreach my $config (@config_off_tmp) {
2777cf79fab6SSteven Rostedt	print OUT "# $config is not set\n";
2778cf79fab6SSteven Rostedt    }
2779cf79fab6SSteven Rostedt
27800a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
27810a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
27820a05c769SSteven Rostedt    }
27830a05c769SSteven Rostedt    close(OUT);
27840a05c769SSteven Rostedt
2785fcb3f16aSSteven Rostedt    make_oldconfig;
27860a05c769SSteven Rostedt}
27870a05c769SSteven Rostedt
27880a05c769SSteven Rostedtsub compare_configs {
27890a05c769SSteven Rostedt    my (%a, %b) = @_;
27900a05c769SSteven Rostedt
27910a05c769SSteven Rostedt    foreach my $item (keys %a) {
27920a05c769SSteven Rostedt	if (!defined($b{$item})) {
27930a05c769SSteven Rostedt	    print "diff $item\n";
27940a05c769SSteven Rostedt	    return 1;
27950a05c769SSteven Rostedt	}
27960a05c769SSteven Rostedt	delete $b{$item};
27970a05c769SSteven Rostedt    }
27980a05c769SSteven Rostedt
27990a05c769SSteven Rostedt    my @keys = keys %b;
28000a05c769SSteven Rostedt    if ($#keys) {
28010a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
28020a05c769SSteven Rostedt    }
28030a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
28040a05c769SSteven Rostedt
28050a05c769SSteven Rostedt    return 0;
28060a05c769SSteven Rostedt}
28070a05c769SSteven Rostedt
28080a05c769SSteven Rostedtsub run_config_bisect_test {
28090a05c769SSteven Rostedt    my ($type) = @_;
28100a05c769SSteven Rostedt
28110a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
28120a05c769SSteven Rostedt}
28130a05c769SSteven Rostedt
28140a05c769SSteven Rostedtsub process_passed {
28150a05c769SSteven Rostedt    my (%configs) = @_;
28160a05c769SSteven Rostedt
28170a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
28180a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
28190a05c769SSteven Rostedt    # Add them to the min options.
28200a05c769SSteven Rostedt    foreach my $config (keys %configs) {
28210a05c769SSteven Rostedt	if (defined($config_list{$config})) {
28220a05c769SSteven Rostedt	    doprint " removing $config\n";
28230a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
28240a05c769SSteven Rostedt	    delete $config_list{$config};
28250a05c769SSteven Rostedt	}
28260a05c769SSteven Rostedt    }
2827f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
2828f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
28290a05c769SSteven Rostedt}
28300a05c769SSteven Rostedt
28310a05c769SSteven Rostedtsub process_failed {
28320a05c769SSteven Rostedt    my ($config) = @_;
28330a05c769SSteven Rostedt
28340a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
28350a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
28360a05c769SSteven Rostedt    doprint "***************************************\n\n";
28370a05c769SSteven Rostedt}
28380a05c769SSteven Rostedt
28390a05c769SSteven Rostedtsub run_config_bisect {
28400a05c769SSteven Rostedt
28410a05c769SSteven Rostedt    my @start_list = keys %config_list;
28420a05c769SSteven Rostedt
28430a05c769SSteven Rostedt    if ($#start_list < 0) {
28440a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
28450a05c769SSteven Rostedt	return -1;
28460a05c769SSteven Rostedt    }
28470a05c769SSteven Rostedt
28480a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
2849b5f4aea6SSteven Rostedt    my $type = $config_bisect_type;
28500a05c769SSteven Rostedt    my $ret;
28510a05c769SSteven Rostedt    my %current_config;
28520a05c769SSteven Rostedt
28530a05c769SSteven Rostedt    my $count = $#start_list + 1;
28540a05c769SSteven Rostedt    doprint "  $count configs to test\n";
28550a05c769SSteven Rostedt
28560a05c769SSteven Rostedt    my $half = int($#start_list / 2);
28570a05c769SSteven Rostedt
28580a05c769SSteven Rostedt    do {
28590a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
28600a05c769SSteven Rostedt
2861cf79fab6SSteven Rostedt	# keep the bottom half off
2862cf79fab6SSteven Rostedt	if ($half < $#start_list) {
2863cf79fab6SSteven Rostedt	    @config_off_tmp = @start_list[$half + 1 .. $#start_list];
2864cf79fab6SSteven Rostedt	} else {
2865cf79fab6SSteven Rostedt	    @config_off_tmp = ();
2866cf79fab6SSteven Rostedt	}
2867cf79fab6SSteven Rostedt
28680a05c769SSteven Rostedt	create_config @tophalf;
28690a05c769SSteven Rostedt	read_current_config \%current_config;
28700a05c769SSteven Rostedt
28710a05c769SSteven Rostedt	$count = $#tophalf + 1;
28720a05c769SSteven Rostedt	doprint "Testing $count configs\n";
28730a05c769SSteven Rostedt	my $found = 0;
28740a05c769SSteven Rostedt	# make sure we test something
28750a05c769SSteven Rostedt	foreach my $config (@tophalf) {
28760a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
28770a05c769SSteven Rostedt		logit " $config\n";
28780a05c769SSteven Rostedt		$found = 1;
28790a05c769SSteven Rostedt	    }
28800a05c769SSteven Rostedt	}
28810a05c769SSteven Rostedt	if (!$found) {
28820a05c769SSteven Rostedt	    # try the other half
28830a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
2884cf79fab6SSteven Rostedt
2885cf79fab6SSteven Rostedt	    # keep the top half off
2886cf79fab6SSteven Rostedt	    @config_off_tmp = @tophalf;
28874c8cc55bSSteven Rostedt	    @tophalf = @start_list[$half + 1 .. $#start_list];
2888cf79fab6SSteven Rostedt
28890a05c769SSteven Rostedt	    create_config @tophalf;
28900a05c769SSteven Rostedt	    read_current_config \%current_config;
28910a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
28920a05c769SSteven Rostedt		if (defined($current_config{$config})) {
28930a05c769SSteven Rostedt		    logit " $config\n";
28940a05c769SSteven Rostedt		    $found = 1;
28950a05c769SSteven Rostedt		}
28960a05c769SSteven Rostedt	    }
28970a05c769SSteven Rostedt	    if (!$found) {
28980a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
28990a05c769SSteven Rostedt		foreach my $config (@start_list) {
29000a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
29010a05c769SSteven Rostedt		}
29020a05c769SSteven Rostedt		return -1;
29030a05c769SSteven Rostedt	    }
29040a05c769SSteven Rostedt	    $count = $#tophalf + 1;
29050a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
29060a05c769SSteven Rostedt	}
29070a05c769SSteven Rostedt
29080a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
2909c960bb9fSSteven Rostedt	if ($bisect_manual) {
2910c960bb9fSSteven Rostedt	    $ret = answer_bisect;
2911c960bb9fSSteven Rostedt	}
29120a05c769SSteven Rostedt	if ($ret) {
29130a05c769SSteven Rostedt	    process_passed %current_config;
29140a05c769SSteven Rostedt	    return 0;
29150a05c769SSteven Rostedt	}
29160a05c769SSteven Rostedt
29170a05c769SSteven Rostedt	doprint "This config had a failure.\n";
29180a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
2919f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
2920f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
29210a05c769SSteven Rostedt
29220a05c769SSteven Rostedt	# A config exists in this group that was bad.
29230a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
29240a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
29250a05c769SSteven Rostedt		doprint " removing $config\n";
29260a05c769SSteven Rostedt		delete $config_list{$config};
29270a05c769SSteven Rostedt	    }
29280a05c769SSteven Rostedt	}
29290a05c769SSteven Rostedt
29300a05c769SSteven Rostedt	@start_list = @tophalf;
29310a05c769SSteven Rostedt
29320a05c769SSteven Rostedt	if ($#start_list == 0) {
29330a05c769SSteven Rostedt	    process_failed $start_list[0];
29340a05c769SSteven Rostedt	    return 1;
29350a05c769SSteven Rostedt	}
29360a05c769SSteven Rostedt
29370a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
29380a05c769SSteven Rostedt	# they are good.
29390a05c769SSteven Rostedt	$half = int($#start_list / 2);
29404c8cc55bSSteven Rostedt    } while ($#start_list > 0);
29410a05c769SSteven Rostedt
2942c960bb9fSSteven Rostedt    # we found a single config, try it again unless we are running manually
2943c960bb9fSSteven Rostedt
2944c960bb9fSSteven Rostedt    if ($bisect_manual) {
2945c960bb9fSSteven Rostedt	process_failed $start_list[0];
2946c960bb9fSSteven Rostedt	return 1;
2947c960bb9fSSteven Rostedt    }
2948c960bb9fSSteven Rostedt
29490a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
29500a05c769SSteven Rostedt
29510a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
29520a05c769SSteven Rostedt    if ($ret) {
29530a05c769SSteven Rostedt	process_passed %current_config;
29540a05c769SSteven Rostedt	return 0;
29550a05c769SSteven Rostedt    }
29560a05c769SSteven Rostedt
29570a05c769SSteven Rostedt    process_failed $start_list[0];
29580a05c769SSteven Rostedt    return 1;
29590a05c769SSteven Rostedt}
29600a05c769SSteven Rostedt
29610a05c769SSteven Rostedtsub config_bisect {
29620a05c769SSteven Rostedt    my ($i) = @_;
29630a05c769SSteven Rostedt
2964b5f4aea6SSteven Rostedt    my $start_config = $config_bisect;
29650a05c769SSteven Rostedt
29660a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
29670a05c769SSteven Rostedt
296830f75da5SSteven Rostedt    if (defined($config_bisect_good)) {
296930f75da5SSteven Rostedt	process_config_ignore $config_bisect_good;
297030f75da5SSteven Rostedt    }
297130f75da5SSteven Rostedt
29720a05c769SSteven Rostedt    # Make the file with the bad config and the min config
29730a05c769SSteven Rostedt    if (defined($minconfig)) {
29740a05c769SSteven Rostedt	# read the min config for things to ignore
29750a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
29760a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
29770a05c769SSteven Rostedt    } else {
29780a05c769SSteven Rostedt	unlink $tmpconfig;
29790a05c769SSteven Rostedt    }
29800a05c769SSteven Rostedt
29810a05c769SSteven Rostedt    if (-f $tmpconfig) {
2982fcb3f16aSSteven Rostedt	load_force_config($tmpconfig);
29830a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
29840a05c769SSteven Rostedt    }
29850a05c769SSteven Rostedt
29860a05c769SSteven Rostedt    # now process the start config
29870a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
29880a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
29890a05c769SSteven Rostedt
29900a05c769SSteven Rostedt    # read directly what we want to check
29910a05c769SSteven Rostedt    my %config_check;
29920a05c769SSteven Rostedt    open (IN, $output_config)
2993f9dee311SMasanari Iida	or dodie "failed to open $output_config";
29940a05c769SSteven Rostedt
29950a05c769SSteven Rostedt    while (<IN>) {
29960a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
29970a05c769SSteven Rostedt	    $config_check{$2} = $1;
29980a05c769SSteven Rostedt	}
29990a05c769SSteven Rostedt    }
30000a05c769SSteven Rostedt    close(IN);
30010a05c769SSteven Rostedt
3002250bae8bSSteven Rostedt    # Now run oldconfig with the minconfig
3003fcb3f16aSSteven Rostedt    make_oldconfig;
30040a05c769SSteven Rostedt
30050a05c769SSteven Rostedt    # check to see what we lost (or gained)
30060a05c769SSteven Rostedt    open (IN, $output_config)
30070a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
30080a05c769SSteven Rostedt
30090a05c769SSteven Rostedt    my %removed_configs;
30100a05c769SSteven Rostedt    my %added_configs;
30110a05c769SSteven Rostedt
30120a05c769SSteven Rostedt    while (<IN>) {
30130a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
30140a05c769SSteven Rostedt	    # save off all options
30150a05c769SSteven Rostedt	    $config_set{$2} = $1;
30160a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
30170a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
30180a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
30190a05c769SSteven Rostedt		} else {
30200a05c769SSteven Rostedt		    $config_list{$2} = $1;
30210a05c769SSteven Rostedt		}
30220a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
30230a05c769SSteven Rostedt		$added_configs{$2} = $1;
30240a05c769SSteven Rostedt		$config_list{$2} = $1;
30250a05c769SSteven Rostedt	    }
3026cf79fab6SSteven Rostedt	} elsif (/^# ((CONFIG\S*).*)/) {
3027cf79fab6SSteven Rostedt	    # Keep these configs disabled
3028cf79fab6SSteven Rostedt	    $config_set{$2} = $1;
3029cf79fab6SSteven Rostedt	    $config_off{$2} = $1;
30300a05c769SSteven Rostedt	}
30310a05c769SSteven Rostedt    }
30320a05c769SSteven Rostedt    close(IN);
30330a05c769SSteven Rostedt
30340a05c769SSteven Rostedt    my @confs = keys %removed_configs;
30350a05c769SSteven Rostedt    if ($#confs >= 0) {
30360a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
30370a05c769SSteven Rostedt	foreach my $config (@confs) {
30380a05c769SSteven Rostedt	    doprint " $config\n";
30390a05c769SSteven Rostedt	}
30400a05c769SSteven Rostedt    }
30410a05c769SSteven Rostedt    @confs = keys %added_configs;
30420a05c769SSteven Rostedt    if ($#confs >= 0) {
30430a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
30440a05c769SSteven Rostedt	foreach my $config (@confs) {
30450a05c769SSteven Rostedt	    doprint " $config\n";
30460a05c769SSteven Rostedt	}
30470a05c769SSteven Rostedt    }
30480a05c769SSteven Rostedt
30490a05c769SSteven Rostedt    my %config_test;
30500a05c769SSteven Rostedt    my $once = 0;
30510a05c769SSteven Rostedt
3052cf79fab6SSteven Rostedt    @config_off_tmp = ();
3053cf79fab6SSteven Rostedt
30540a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
30550a05c769SSteven Rostedt    # that the config we autocreate has everything we need
30560a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
30570a05c769SSteven Rostedt    # may not be able to create a new config.
30580a05c769SSteven Rostedt    # Here we create a config with everything set.
30590a05c769SSteven Rostedt    create_config (keys %config_list);
30600a05c769SSteven Rostedt    read_current_config \%config_test;
30610a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
30620a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
30630a05c769SSteven Rostedt	    if (!$once) {
30640a05c769SSteven Rostedt		$once = 1;
30650a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
30660a05c769SSteven Rostedt	    }
30670a05c769SSteven Rostedt	    doprint "  $config\n";
30680a05c769SSteven Rostedt	    delete $config_list{$config};
30690a05c769SSteven Rostedt	}
30700a05c769SSteven Rostedt    }
30710a05c769SSteven Rostedt    my $ret;
3072b0918612SSteven Rostedt
3073b0918612SSteven Rostedt    if (defined($config_bisect_check) && $config_bisect_check) {
3074b0918612SSteven Rostedt	doprint " Checking to make sure bad config with min config fails\n";
3075b0918612SSteven Rostedt	create_config keys %config_list;
3076b0918612SSteven Rostedt	$ret = run_config_bisect_test $config_bisect_type;
3077b0918612SSteven Rostedt	if ($ret) {
3078b0918612SSteven Rostedt	    doprint " FAILED! Bad config with min config boots fine\n";
3079b0918612SSteven Rostedt	    return -1;
3080b0918612SSteven Rostedt	}
3081b0918612SSteven Rostedt	doprint " Bad config with min config fails as expected\n";
3082b0918612SSteven Rostedt    }
3083b0918612SSteven Rostedt
30840a05c769SSteven Rostedt    do {
30850a05c769SSteven Rostedt	$ret = run_config_bisect;
30860a05c769SSteven Rostedt    } while (!$ret);
30870a05c769SSteven Rostedt
30880a05c769SSteven Rostedt    return $ret if ($ret < 0);
30895f9b6cedSSteven Rostedt
30905f9b6cedSSteven Rostedt    success $i;
30915f9b6cedSSteven Rostedt}
30925f9b6cedSSteven Rostedt
309327d934b2SSteven Rostedtsub patchcheck_reboot {
309427d934b2SSteven Rostedt    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
3095bc7c5803SSteven Rostedt    reboot_to_good $patchcheck_sleep_time;
309627d934b2SSteven Rostedt}
309727d934b2SSteven Rostedt
30986c5ee0beSSteven Rostedtsub patchcheck {
30996c5ee0beSSteven Rostedt    my ($i) = @_;
31006c5ee0beSSteven Rostedt
31016c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
3102b5f4aea6SSteven Rostedt	if (!defined($patchcheck_start));
31036c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
3104b5f4aea6SSteven Rostedt	if (!defined($patchcheck_type));
31056c5ee0beSSteven Rostedt
3106b5f4aea6SSteven Rostedt    my $start = $patchcheck_start;
31076c5ee0beSSteven Rostedt
31086c5ee0beSSteven Rostedt    my $end = "HEAD";
3109b5f4aea6SSteven Rostedt    if (defined($patchcheck_end)) {
3110b5f4aea6SSteven Rostedt	$end = $patchcheck_end;
31116c5ee0beSSteven Rostedt    }
31126c5ee0beSSteven Rostedt
3113a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
3114a57419b3SSteven Rostedt    $start = get_sha1($start);
3115a57419b3SSteven Rostedt    $end = get_sha1($end);
3116a57419b3SSteven Rostedt
3117b5f4aea6SSteven Rostedt    my $type = $patchcheck_type;
31186c5ee0beSSteven Rostedt
31196c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
31206c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
31216c5ee0beSSteven Rostedt	$type = "boot";
31226c5ee0beSSteven Rostedt    }
31236c5ee0beSSteven Rostedt
31246c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
31256c5ee0beSSteven Rostedt	dodie "could not get git list";
31266c5ee0beSSteven Rostedt
31276c5ee0beSSteven Rostedt    my @list;
31286c5ee0beSSteven Rostedt
31296c5ee0beSSteven Rostedt    while (<IN>) {
31306c5ee0beSSteven Rostedt	chomp;
31316c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
31326c5ee0beSSteven Rostedt	last if (/^$start/);
31336c5ee0beSSteven Rostedt    }
31346c5ee0beSSteven Rostedt    close(IN);
31356c5ee0beSSteven Rostedt
31366c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
31372b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
31386c5ee0beSSteven Rostedt    }
31396c5ee0beSSteven Rostedt
31406c5ee0beSSteven Rostedt    # go backwards in the list
31416c5ee0beSSteven Rostedt    @list = reverse @list;
31426c5ee0beSSteven Rostedt
31436c5ee0beSSteven Rostedt    my $save_clean = $noclean;
31441990207dSSteven Rostedt    my %ignored_warnings;
31451990207dSSteven Rostedt
31461990207dSSteven Rostedt    if (defined($ignore_warnings)) {
31471990207dSSteven Rostedt	foreach my $sha1 (split /\s+/, $ignore_warnings) {
31481990207dSSteven Rostedt	    $ignored_warnings{$sha1} = 1;
31491990207dSSteven Rostedt	}
31501990207dSSteven Rostedt    }
31516c5ee0beSSteven Rostedt
31526c5ee0beSSteven Rostedt    $in_patchcheck = 1;
31536c5ee0beSSteven Rostedt    foreach my $item (@list) {
31546c5ee0beSSteven Rostedt	my $sha1 = $item;
31556c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
31566c5ee0beSSteven Rostedt
31576c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
31586c5ee0beSSteven Rostedt
31596c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
31606c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
31616c5ee0beSSteven Rostedt
31626c5ee0beSSteven Rostedt	# only clean on the first and last patch
31636c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
31646c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
31656c5ee0beSSteven Rostedt	    $noclean = $save_clean;
31666c5ee0beSSteven Rostedt	} else {
31676c5ee0beSSteven Rostedt	    $noclean = 1;
31686c5ee0beSSteven Rostedt	}
31696c5ee0beSSteven Rostedt
31706c5ee0beSSteven Rostedt	if (defined($minconfig)) {
31712b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
31726c5ee0beSSteven Rostedt	} else {
31736c5ee0beSSteven Rostedt	    # ?? no config to use?
31742b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
31756c5ee0beSSteven Rostedt	}
31766c5ee0beSSteven Rostedt
31774283b169SSteven Rostedt (Red Hat)	# No need to do per patch checking if warnings file exists
31784283b169SSteven Rostedt (Red Hat)	if (!defined($warnings_file) && !defined($ignored_warnings{$sha1})) {
31794283b169SSteven Rostedt (Red Hat)	    check_patch_buildlog $sha1 or return 0;
31801990207dSSteven Rostedt	}
31816c5ee0beSSteven Rostedt
31824283b169SSteven Rostedt (Red Hat)	check_buildlog or return 0;
31834283b169SSteven Rostedt (Red Hat)
31846c5ee0beSSteven Rostedt	next if ($type eq "build");
31856c5ee0beSSteven Rostedt
31867faafbd6SSteven Rostedt	my $failed = 0;
31877faafbd6SSteven Rostedt
3188ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
31897faafbd6SSteven Rostedt
31907faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
31917faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
31927faafbd6SSteven Rostedt	}
31937faafbd6SSteven Rostedt	end_monitor;
31947faafbd6SSteven Rostedt	return 0 if ($failed);
31957faafbd6SSteven Rostedt
319627d934b2SSteven Rostedt	patchcheck_reboot;
319727d934b2SSteven Rostedt
31986c5ee0beSSteven Rostedt    }
31996c5ee0beSSteven Rostedt    $in_patchcheck = 0;
32006c5ee0beSSteven Rostedt    success $i;
32012b7d9b21SSteven Rostedt
32022b7d9b21SSteven Rostedt    return 1;
32036c5ee0beSSteven Rostedt}
32046c5ee0beSSteven Rostedt
3205b9066f6cSSteven Rostedtmy %depends;
3206ac6974c7SSteven Rostedtmy %depcount;
3207b9066f6cSSteven Rostedtmy $iflevel = 0;
3208b9066f6cSSteven Rostedtmy @ifdeps;
3209b9066f6cSSteven Rostedt
3210b9066f6cSSteven Rostedt# prevent recursion
3211b9066f6cSSteven Rostedtmy %read_kconfigs;
3212b9066f6cSSteven Rostedt
3213ac6974c7SSteven Rostedtsub add_dep {
3214ac6974c7SSteven Rostedt    # $config depends on $dep
3215ac6974c7SSteven Rostedt    my ($config, $dep) = @_;
3216ac6974c7SSteven Rostedt
3217ac6974c7SSteven Rostedt    if (defined($depends{$config})) {
3218ac6974c7SSteven Rostedt	$depends{$config} .= " " . $dep;
3219ac6974c7SSteven Rostedt    } else {
3220ac6974c7SSteven Rostedt	$depends{$config} = $dep;
3221ac6974c7SSteven Rostedt    }
3222ac6974c7SSteven Rostedt
3223ac6974c7SSteven Rostedt    # record the number of configs depending on $dep
3224ac6974c7SSteven Rostedt    if (defined $depcount{$dep}) {
3225ac6974c7SSteven Rostedt	$depcount{$dep}++;
3226ac6974c7SSteven Rostedt    } else {
3227ac6974c7SSteven Rostedt	$depcount{$dep} = 1;
3228ac6974c7SSteven Rostedt    }
3229ac6974c7SSteven Rostedt}
3230ac6974c7SSteven Rostedt
3231b9066f6cSSteven Rostedt# taken from streamline_config.pl
3232b9066f6cSSteven Rostedtsub read_kconfig {
3233b9066f6cSSteven Rostedt    my ($kconfig) = @_;
3234b9066f6cSSteven Rostedt
3235b9066f6cSSteven Rostedt    my $state = "NONE";
3236b9066f6cSSteven Rostedt    my $config;
3237b9066f6cSSteven Rostedt    my @kconfigs;
3238b9066f6cSSteven Rostedt
3239b9066f6cSSteven Rostedt    my $cont = 0;
3240b9066f6cSSteven Rostedt    my $line;
3241b9066f6cSSteven Rostedt
3242b9066f6cSSteven Rostedt
3243b9066f6cSSteven Rostedt    if (! -f $kconfig) {
3244b9066f6cSSteven Rostedt	doprint "file $kconfig does not exist, skipping\n";
3245b9066f6cSSteven Rostedt	return;
3246b9066f6cSSteven Rostedt    }
3247b9066f6cSSteven Rostedt
3248b9066f6cSSteven Rostedt    open(KIN, "$kconfig")
3249b9066f6cSSteven Rostedt	or die "Can't open $kconfig";
3250b9066f6cSSteven Rostedt    while (<KIN>) {
3251b9066f6cSSteven Rostedt	chomp;
3252b9066f6cSSteven Rostedt
3253b9066f6cSSteven Rostedt	# Make sure that lines ending with \ continue
3254b9066f6cSSteven Rostedt	if ($cont) {
3255b9066f6cSSteven Rostedt	    $_ = $line . " " . $_;
3256b9066f6cSSteven Rostedt	}
3257b9066f6cSSteven Rostedt
3258b9066f6cSSteven Rostedt	if (s/\\$//) {
3259b9066f6cSSteven Rostedt	    $cont = 1;
3260b9066f6cSSteven Rostedt	    $line = $_;
3261b9066f6cSSteven Rostedt	    next;
3262b9066f6cSSteven Rostedt	}
3263b9066f6cSSteven Rostedt
3264b9066f6cSSteven Rostedt	$cont = 0;
3265b9066f6cSSteven Rostedt
3266b9066f6cSSteven Rostedt	# collect any Kconfig sources
3267b9066f6cSSteven Rostedt	if (/^source\s*"(.*)"/) {
3268b9066f6cSSteven Rostedt	    $kconfigs[$#kconfigs+1] = $1;
3269b9066f6cSSteven Rostedt	}
3270b9066f6cSSteven Rostedt
3271b9066f6cSSteven Rostedt	# configs found
3272b9066f6cSSteven Rostedt	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
3273b9066f6cSSteven Rostedt	    $state = "NEW";
3274b9066f6cSSteven Rostedt	    $config = $2;
3275b9066f6cSSteven Rostedt
3276b9066f6cSSteven Rostedt	    for (my $i = 0; $i < $iflevel; $i++) {
3277ac6974c7SSteven Rostedt		add_dep $config, $ifdeps[$i];
3278b9066f6cSSteven Rostedt	    }
3279b9066f6cSSteven Rostedt
3280b9066f6cSSteven Rostedt	# collect the depends for the config
3281b9066f6cSSteven Rostedt	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
3282b9066f6cSSteven Rostedt
3283ac6974c7SSteven Rostedt	    add_dep $config, $1;
3284b9066f6cSSteven Rostedt
3285b9066f6cSSteven Rostedt	# Get the configs that select this config
3286ac6974c7SSteven Rostedt	} elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
3287ac6974c7SSteven Rostedt
3288ac6974c7SSteven Rostedt	    # selected by depends on config
3289ac6974c7SSteven Rostedt	    add_dep $1, $config;
3290b9066f6cSSteven Rostedt
3291b9066f6cSSteven Rostedt	# Check for if statements
3292b9066f6cSSteven Rostedt	} elsif (/^if\s+(.*\S)\s*$/) {
3293b9066f6cSSteven Rostedt	    my $deps = $1;
3294b9066f6cSSteven Rostedt	    # remove beginning and ending non text
3295b9066f6cSSteven Rostedt	    $deps =~ s/^[^a-zA-Z0-9_]*//;
3296b9066f6cSSteven Rostedt	    $deps =~ s/[^a-zA-Z0-9_]*$//;
3297b9066f6cSSteven Rostedt
3298b9066f6cSSteven Rostedt	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
3299b9066f6cSSteven Rostedt
3300b9066f6cSSteven Rostedt	    $ifdeps[$iflevel++] = join ':', @deps;
3301b9066f6cSSteven Rostedt
3302b9066f6cSSteven Rostedt	} elsif (/^endif/) {
3303b9066f6cSSteven Rostedt
3304b9066f6cSSteven Rostedt	    $iflevel-- if ($iflevel);
3305b9066f6cSSteven Rostedt
3306b9066f6cSSteven Rostedt	# stop on "help"
3307b9066f6cSSteven Rostedt	} elsif (/^\s*help\s*$/) {
3308b9066f6cSSteven Rostedt	    $state = "NONE";
3309b9066f6cSSteven Rostedt	}
3310b9066f6cSSteven Rostedt    }
3311b9066f6cSSteven Rostedt    close(KIN);
3312b9066f6cSSteven Rostedt
3313b9066f6cSSteven Rostedt    # read in any configs that were found.
3314b9066f6cSSteven Rostedt    foreach $kconfig (@kconfigs) {
3315b9066f6cSSteven Rostedt	if (!defined($read_kconfigs{$kconfig})) {
3316b9066f6cSSteven Rostedt	    $read_kconfigs{$kconfig} = 1;
3317b9066f6cSSteven Rostedt	    read_kconfig("$builddir/$kconfig");
3318b9066f6cSSteven Rostedt	}
3319b9066f6cSSteven Rostedt    }
3320b9066f6cSSteven Rostedt}
3321b9066f6cSSteven Rostedt
3322b9066f6cSSteven Rostedtsub read_depends {
3323b9066f6cSSteven Rostedt    # find out which arch this is by the kconfig file
3324b9066f6cSSteven Rostedt    open (IN, $output_config)
3325b9066f6cSSteven Rostedt	or dodie "Failed to read $output_config";
3326b9066f6cSSteven Rostedt    my $arch;
3327b9066f6cSSteven Rostedt    while (<IN>) {
3328b9066f6cSSteven Rostedt	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
3329b9066f6cSSteven Rostedt	    $arch = $1;
3330b9066f6cSSteven Rostedt	    last;
3331b9066f6cSSteven Rostedt	}
3332b9066f6cSSteven Rostedt    }
3333b9066f6cSSteven Rostedt    close IN;
3334b9066f6cSSteven Rostedt
3335b9066f6cSSteven Rostedt    if (!defined($arch)) {
3336b9066f6cSSteven Rostedt	doprint "Could not find arch from config file\n";
3337b9066f6cSSteven Rostedt	doprint "no dependencies used\n";
3338b9066f6cSSteven Rostedt	return;
3339b9066f6cSSteven Rostedt    }
3340b9066f6cSSteven Rostedt
3341b9066f6cSSteven Rostedt    # arch is really the subarch, we need to know
3342b9066f6cSSteven Rostedt    # what directory to look at.
3343b9066f6cSSteven Rostedt    if ($arch eq "i386" || $arch eq "x86_64") {
3344b9066f6cSSteven Rostedt	$arch = "x86";
3345b9066f6cSSteven Rostedt    } elsif ($arch =~ /^tile/) {
3346b9066f6cSSteven Rostedt	$arch = "tile";
3347b9066f6cSSteven Rostedt    }
3348b9066f6cSSteven Rostedt
3349b9066f6cSSteven Rostedt    my $kconfig = "$builddir/arch/$arch/Kconfig";
3350b9066f6cSSteven Rostedt
3351b9066f6cSSteven Rostedt    if (! -f $kconfig && $arch =~ /\d$/) {
3352b9066f6cSSteven Rostedt	my $orig = $arch;
3353b9066f6cSSteven Rostedt 	# some subarchs have numbers, truncate them
3354b9066f6cSSteven Rostedt	$arch =~ s/\d*$//;
3355b9066f6cSSteven Rostedt	$kconfig = "$builddir/arch/$arch/Kconfig";
3356b9066f6cSSteven Rostedt	if (! -f $kconfig) {
3357b9066f6cSSteven Rostedt	    doprint "No idea what arch dir $orig is for\n";
3358b9066f6cSSteven Rostedt	    doprint "no dependencies used\n";
3359b9066f6cSSteven Rostedt	    return;
3360b9066f6cSSteven Rostedt	}
3361b9066f6cSSteven Rostedt    }
3362b9066f6cSSteven Rostedt
3363b9066f6cSSteven Rostedt    read_kconfig($kconfig);
3364b9066f6cSSteven Rostedt}
3365b9066f6cSSteven Rostedt
33664c4ab120SSteven Rostedtsub read_config_list {
33674c4ab120SSteven Rostedt    my ($config) = @_;
33684c4ab120SSteven Rostedt
33694c4ab120SSteven Rostedt    open (IN, $config)
33704c4ab120SSteven Rostedt	or dodie "Failed to read $config";
33714c4ab120SSteven Rostedt
33724c4ab120SSteven Rostedt    while (<IN>) {
33734c4ab120SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
33744c4ab120SSteven Rostedt	    if (!defined($config_ignore{$2})) {
33754c4ab120SSteven Rostedt		$config_list{$2} = $1;
33764c4ab120SSteven Rostedt	    }
33774c4ab120SSteven Rostedt	}
33784c4ab120SSteven Rostedt    }
33794c4ab120SSteven Rostedt
33804c4ab120SSteven Rostedt    close(IN);
33814c4ab120SSteven Rostedt}
33824c4ab120SSteven Rostedt
33834c4ab120SSteven Rostedtsub read_output_config {
33844c4ab120SSteven Rostedt    my ($config) = @_;
33854c4ab120SSteven Rostedt
33864c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
33874c4ab120SSteven Rostedt}
33884c4ab120SSteven Rostedt
33894c4ab120SSteven Rostedtsub make_new_config {
33904c4ab120SSteven Rostedt    my @configs = @_;
33914c4ab120SSteven Rostedt
33924c4ab120SSteven Rostedt    open (OUT, ">$output_config")
33934c4ab120SSteven Rostedt	or dodie "Failed to write $output_config";
33944c4ab120SSteven Rostedt
33954c4ab120SSteven Rostedt    foreach my $config (@configs) {
33964c4ab120SSteven Rostedt	print OUT "$config\n";
33974c4ab120SSteven Rostedt    }
33984c4ab120SSteven Rostedt    close OUT;
33994c4ab120SSteven Rostedt}
34004c4ab120SSteven Rostedt
3401ac6974c7SSteven Rostedtsub chomp_config {
3402ac6974c7SSteven Rostedt    my ($config) = @_;
3403ac6974c7SSteven Rostedt
3404ac6974c7SSteven Rostedt    $config =~ s/CONFIG_//;
3405ac6974c7SSteven Rostedt
3406ac6974c7SSteven Rostedt    return $config;
3407ac6974c7SSteven Rostedt}
3408ac6974c7SSteven Rostedt
3409b9066f6cSSteven Rostedtsub get_depends {
3410b9066f6cSSteven Rostedt    my ($dep) = @_;
3411b9066f6cSSteven Rostedt
3412ac6974c7SSteven Rostedt    my $kconfig = chomp_config $dep;
3413b9066f6cSSteven Rostedt
3414b9066f6cSSteven Rostedt    $dep = $depends{"$kconfig"};
3415b9066f6cSSteven Rostedt
3416b9066f6cSSteven Rostedt    # the dep string we have saves the dependencies as they
3417b9066f6cSSteven Rostedt    # were found, including expressions like ! && ||. We
3418b9066f6cSSteven Rostedt    # want to split this out into just an array of configs.
3419b9066f6cSSteven Rostedt
3420b9066f6cSSteven Rostedt    my $valid = "A-Za-z_0-9";
3421b9066f6cSSteven Rostedt
3422b9066f6cSSteven Rostedt    my @configs;
3423b9066f6cSSteven Rostedt
3424b9066f6cSSteven Rostedt    while ($dep =~ /[$valid]/) {
3425b9066f6cSSteven Rostedt
3426b9066f6cSSteven Rostedt	if ($dep =~ /^[^$valid]*([$valid]+)/) {
3427b9066f6cSSteven Rostedt	    my $conf = "CONFIG_" . $1;
3428b9066f6cSSteven Rostedt
3429b9066f6cSSteven Rostedt	    $configs[$#configs + 1] = $conf;
3430b9066f6cSSteven Rostedt
3431b9066f6cSSteven Rostedt	    $dep =~ s/^[^$valid]*[$valid]+//;
3432b9066f6cSSteven Rostedt	} else {
3433b9066f6cSSteven Rostedt	    die "this should never happen";
3434b9066f6cSSteven Rostedt	}
3435b9066f6cSSteven Rostedt    }
3436b9066f6cSSteven Rostedt
3437b9066f6cSSteven Rostedt    return @configs;
3438b9066f6cSSteven Rostedt}
3439b9066f6cSSteven Rostedt
3440b9066f6cSSteven Rostedtmy %min_configs;
3441b9066f6cSSteven Rostedtmy %keep_configs;
344243d1b651SSteven Rostedtmy %save_configs;
3443b9066f6cSSteven Rostedtmy %processed_configs;
3444b9066f6cSSteven Rostedtmy %nochange_config;
3445b9066f6cSSteven Rostedt
3446b9066f6cSSteven Rostedtsub test_this_config {
3447b9066f6cSSteven Rostedt    my ($config) = @_;
3448b9066f6cSSteven Rostedt
3449b9066f6cSSteven Rostedt    my $found;
3450b9066f6cSSteven Rostedt
3451b9066f6cSSteven Rostedt    # if we already processed this config, skip it
3452b9066f6cSSteven Rostedt    if (defined($processed_configs{$config})) {
3453b9066f6cSSteven Rostedt	return undef;
3454b9066f6cSSteven Rostedt    }
3455b9066f6cSSteven Rostedt    $processed_configs{$config} = 1;
3456b9066f6cSSteven Rostedt
3457b9066f6cSSteven Rostedt    # if this config failed during this round, skip it
3458b9066f6cSSteven Rostedt    if (defined($nochange_config{$config})) {
3459b9066f6cSSteven Rostedt	return undef;
3460b9066f6cSSteven Rostedt    }
3461b9066f6cSSteven Rostedt
3462ac6974c7SSteven Rostedt    my $kconfig = chomp_config $config;
3463b9066f6cSSteven Rostedt
3464b9066f6cSSteven Rostedt    # Test dependencies first
3465b9066f6cSSteven Rostedt    if (defined($depends{"$kconfig"})) {
3466b9066f6cSSteven Rostedt	my @parents = get_depends $config;
3467b9066f6cSSteven Rostedt	foreach my $parent (@parents) {
3468b9066f6cSSteven Rostedt	    # if the parent is in the min config, check it first
3469b9066f6cSSteven Rostedt	    next if (!defined($min_configs{$parent}));
3470b9066f6cSSteven Rostedt	    $found = test_this_config($parent);
3471b9066f6cSSteven Rostedt	    if (defined($found)) {
3472b9066f6cSSteven Rostedt		return $found;
3473b9066f6cSSteven Rostedt	    }
3474b9066f6cSSteven Rostedt	}
3475b9066f6cSSteven Rostedt    }
3476b9066f6cSSteven Rostedt
3477b9066f6cSSteven Rostedt    # Remove this config from the list of configs
3478fb16d891SAdam Lee    # do a make olddefconfig and then read the resulting
3479b9066f6cSSteven Rostedt    # .config to make sure it is missing the config that
3480b9066f6cSSteven Rostedt    # we had before
3481b9066f6cSSteven Rostedt    my %configs = %min_configs;
3482b9066f6cSSteven Rostedt    delete $configs{$config};
3483b9066f6cSSteven Rostedt    make_new_config ((values %configs), (values %keep_configs));
3484b9066f6cSSteven Rostedt    make_oldconfig;
3485b9066f6cSSteven Rostedt    undef %configs;
3486b9066f6cSSteven Rostedt    assign_configs \%configs, $output_config;
3487b9066f6cSSteven Rostedt
3488b9066f6cSSteven Rostedt    return $config if (!defined($configs{$config}));
3489b9066f6cSSteven Rostedt
3490b9066f6cSSteven Rostedt    doprint "disabling config $config did not change .config\n";
3491b9066f6cSSteven Rostedt
3492b9066f6cSSteven Rostedt    $nochange_config{$config} = 1;
3493b9066f6cSSteven Rostedt
3494b9066f6cSSteven Rostedt    return undef;
3495b9066f6cSSteven Rostedt}
3496b9066f6cSSteven Rostedt
34974c4ab120SSteven Rostedtsub make_min_config {
34984c4ab120SSteven Rostedt    my ($i) = @_;
34994c4ab120SSteven Rostedt
3500ccc513b6SSteven Rostedt    my $type = $minconfig_type;
3501ccc513b6SSteven Rostedt    if ($type ne "boot" && $type ne "test") {
3502ccc513b6SSteven Rostedt	fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" .
3503ccc513b6SSteven Rostedt	    " make_min_config works only with 'boot' and 'test'\n" and return;
3504ccc513b6SSteven Rostedt    }
3505ccc513b6SSteven Rostedt
35064c4ab120SSteven Rostedt    if (!defined($output_minconfig)) {
35074c4ab120SSteven Rostedt	fail "OUTPUT_MIN_CONFIG not defined" and return;
35084c4ab120SSteven Rostedt    }
350935ce5952SSteven Rostedt
351035ce5952SSteven Rostedt    # If output_minconfig exists, and the start_minconfig
351135ce5952SSteven Rostedt    # came from min_config, than ask if we should use
351235ce5952SSteven Rostedt    # that instead.
351335ce5952SSteven Rostedt    if (-f $output_minconfig && !$start_minconfig_defined) {
351435ce5952SSteven Rostedt	print "$output_minconfig exists\n";
351543de3316SSteven Rostedt	if (!defined($use_output_minconfig)) {
351635ce5952SSteven Rostedt	    if (read_yn " Use it as minconfig?") {
351735ce5952SSteven Rostedt		$start_minconfig = $output_minconfig;
351835ce5952SSteven Rostedt	    }
351943de3316SSteven Rostedt	} elsif ($use_output_minconfig > 0) {
352043de3316SSteven Rostedt	    doprint "Using $output_minconfig as MIN_CONFIG\n";
352143de3316SSteven Rostedt	    $start_minconfig = $output_minconfig;
352243de3316SSteven Rostedt	} else {
352343de3316SSteven Rostedt	    doprint "Set to still use MIN_CONFIG as starting point\n";
352443de3316SSteven Rostedt	}
352535ce5952SSteven Rostedt    }
352635ce5952SSteven Rostedt
35274c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
35284c4ab120SSteven Rostedt	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
35294c4ab120SSteven Rostedt    }
35304c4ab120SSteven Rostedt
353135ce5952SSteven Rostedt    my $temp_config = "$tmpdir/temp_config";
353235ce5952SSteven Rostedt
35334c4ab120SSteven Rostedt    # First things first. We build an allnoconfig to find
35344c4ab120SSteven Rostedt    # out what the defaults are that we can't touch.
35354c4ab120SSteven Rostedt    # Some are selections, but we really can't handle selections.
35364c4ab120SSteven Rostedt
35374c4ab120SSteven Rostedt    my $save_minconfig = $minconfig;
35384c4ab120SSteven Rostedt    undef $minconfig;
35394c4ab120SSteven Rostedt
35404c4ab120SSteven Rostedt    run_command "$make allnoconfig" or return 0;
35414c4ab120SSteven Rostedt
3542b9066f6cSSteven Rostedt    read_depends;
3543b9066f6cSSteven Rostedt
35444c4ab120SSteven Rostedt    process_config_ignore $output_config;
3545b9066f6cSSteven Rostedt
354643d1b651SSteven Rostedt    undef %save_configs;
3547b9066f6cSSteven Rostedt    undef %min_configs;
35484c4ab120SSteven Rostedt
35494c4ab120SSteven Rostedt    if (defined($ignore_config)) {
35504c4ab120SSteven Rostedt	# make sure the file exists
35514c4ab120SSteven Rostedt	`touch $ignore_config`;
355243d1b651SSteven Rostedt	assign_configs \%save_configs, $ignore_config;
35534c4ab120SSteven Rostedt    }
35544c4ab120SSteven Rostedt
355543d1b651SSteven Rostedt    %keep_configs = %save_configs;
355643d1b651SSteven Rostedt
35574c4ab120SSteven Rostedt    doprint "Load initial configs from $start_minconfig\n";
35584c4ab120SSteven Rostedt
35594c4ab120SSteven Rostedt    # Look at the current min configs, and save off all the
35604c4ab120SSteven Rostedt    # ones that were set via the allnoconfig
35614c4ab120SSteven Rostedt    assign_configs \%min_configs, $start_minconfig;
35624c4ab120SSteven Rostedt
35634c4ab120SSteven Rostedt    my @config_keys = keys %min_configs;
35644c4ab120SSteven Rostedt
3565ac6974c7SSteven Rostedt    # All configs need a depcount
3566ac6974c7SSteven Rostedt    foreach my $config (@config_keys) {
3567ac6974c7SSteven Rostedt	my $kconfig = chomp_config $config;
3568ac6974c7SSteven Rostedt	if (!defined $depcount{$kconfig}) {
3569ac6974c7SSteven Rostedt		$depcount{$kconfig} = 0;
3570ac6974c7SSteven Rostedt	}
3571ac6974c7SSteven Rostedt    }
3572ac6974c7SSteven Rostedt
35734c4ab120SSteven Rostedt    # Remove anything that was set by the make allnoconfig
35744c4ab120SSteven Rostedt    # we shouldn't need them as they get set for us anyway.
35754c4ab120SSteven Rostedt    foreach my $config (@config_keys) {
35764c4ab120SSteven Rostedt	# Remove anything in the ignore_config
35774c4ab120SSteven Rostedt	if (defined($keep_configs{$config})) {
35784c4ab120SSteven Rostedt	    my $file = $ignore_config;
35794c4ab120SSteven Rostedt	    $file =~ s,.*/(.*?)$,$1,;
35804c4ab120SSteven Rostedt	    doprint "$config set by $file ... ignored\n";
35814c4ab120SSteven Rostedt	    delete $min_configs{$config};
35824c4ab120SSteven Rostedt	    next;
35834c4ab120SSteven Rostedt	}
35844c4ab120SSteven Rostedt	# But make sure the settings are the same. If a min config
35854c4ab120SSteven Rostedt	# sets a selection, we do not want to get rid of it if
35864c4ab120SSteven Rostedt	# it is not the same as what we have. Just move it into
35874c4ab120SSteven Rostedt	# the keep configs.
35884c4ab120SSteven Rostedt	if (defined($config_ignore{$config})) {
35894c4ab120SSteven Rostedt	    if ($config_ignore{$config} ne $min_configs{$config}) {
35904c4ab120SSteven Rostedt		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
35914c4ab120SSteven Rostedt		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
35924c4ab120SSteven Rostedt		$keep_configs{$config} = $min_configs{$config};
35934c4ab120SSteven Rostedt	    } else {
35944c4ab120SSteven Rostedt		doprint "$config set by allnoconfig ... ignored\n";
35954c4ab120SSteven Rostedt	    }
35964c4ab120SSteven Rostedt	    delete $min_configs{$config};
35974c4ab120SSteven Rostedt	}
35984c4ab120SSteven Rostedt    }
35994c4ab120SSteven Rostedt
36004c4ab120SSteven Rostedt    my $done = 0;
3601b9066f6cSSteven Rostedt    my $take_two = 0;
36024c4ab120SSteven Rostedt
36034c4ab120SSteven Rostedt    while (!$done) {
36044c4ab120SSteven Rostedt
36054c4ab120SSteven Rostedt	my $config;
36064c4ab120SSteven Rostedt	my $found;
36074c4ab120SSteven Rostedt
36084c4ab120SSteven Rostedt	# Now disable each config one by one and do a make oldconfig
36094c4ab120SSteven Rostedt	# till we find a config that changes our list.
36104c4ab120SSteven Rostedt
36114c4ab120SSteven Rostedt	my @test_configs = keys %min_configs;
3612ac6974c7SSteven Rostedt
3613ac6974c7SSteven Rostedt	# Sort keys by who is most dependent on
3614ac6974c7SSteven Rostedt	@test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
3615ac6974c7SSteven Rostedt			  @test_configs ;
3616ac6974c7SSteven Rostedt
3617ac6974c7SSteven Rostedt	# Put configs that did not modify the config at the end.
36184c4ab120SSteven Rostedt	my $reset = 1;
36194c4ab120SSteven Rostedt	for (my $i = 0; $i < $#test_configs; $i++) {
36204c4ab120SSteven Rostedt	    if (!defined($nochange_config{$test_configs[0]})) {
36214c4ab120SSteven Rostedt		$reset = 0;
36224c4ab120SSteven Rostedt		last;
36234c4ab120SSteven Rostedt	    }
36244c4ab120SSteven Rostedt	    # This config didn't change the .config last time.
36254c4ab120SSteven Rostedt	    # Place it at the end
36264c4ab120SSteven Rostedt	    my $config = shift @test_configs;
36274c4ab120SSteven Rostedt	    push @test_configs, $config;
36284c4ab120SSteven Rostedt	}
36294c4ab120SSteven Rostedt
36304c4ab120SSteven Rostedt	# if every test config has failed to modify the .config file
36314c4ab120SSteven Rostedt	# in the past, then reset and start over.
36324c4ab120SSteven Rostedt	if ($reset) {
36334c4ab120SSteven Rostedt	    undef %nochange_config;
36344c4ab120SSteven Rostedt	}
36354c4ab120SSteven Rostedt
3636b9066f6cSSteven Rostedt	undef %processed_configs;
3637b9066f6cSSteven Rostedt
36384c4ab120SSteven Rostedt	foreach my $config (@test_configs) {
36394c4ab120SSteven Rostedt
3640b9066f6cSSteven Rostedt	    $found = test_this_config $config;
36414c4ab120SSteven Rostedt
3642b9066f6cSSteven Rostedt	    last if (defined($found));
36434c4ab120SSteven Rostedt
36444c4ab120SSteven Rostedt	    # oh well, try another config
36454c4ab120SSteven Rostedt	}
36464c4ab120SSteven Rostedt
36474c4ab120SSteven Rostedt	if (!defined($found)) {
3648b9066f6cSSteven Rostedt	    # we could have failed due to the nochange_config hash
3649b9066f6cSSteven Rostedt	    # reset and try again
3650b9066f6cSSteven Rostedt	    if (!$take_two) {
3651b9066f6cSSteven Rostedt		undef %nochange_config;
3652b9066f6cSSteven Rostedt		$take_two = 1;
3653b9066f6cSSteven Rostedt		next;
3654b9066f6cSSteven Rostedt	    }
36554c4ab120SSteven Rostedt	    doprint "No more configs found that we can disable\n";
36564c4ab120SSteven Rostedt	    $done = 1;
36574c4ab120SSteven Rostedt	    last;
36584c4ab120SSteven Rostedt	}
3659b9066f6cSSteven Rostedt	$take_two = 0;
36604c4ab120SSteven Rostedt
36614c4ab120SSteven Rostedt	$config = $found;
36624c4ab120SSteven Rostedt
36634c4ab120SSteven Rostedt	doprint "Test with $config disabled\n";
36644c4ab120SSteven Rostedt
36654c4ab120SSteven Rostedt	# set in_bisect to keep build and monitor from dieing
36664c4ab120SSteven Rostedt	$in_bisect = 1;
36674c4ab120SSteven Rostedt
36684c4ab120SSteven Rostedt	my $failed = 0;
3669bf1c95abSSteven Rostedt	build "oldconfig" or $failed = 1;
3670bf1c95abSSteven Rostedt	if (!$failed) {
36714c4ab120SSteven Rostedt		start_monitor_and_boot or $failed = 1;
3672ccc513b6SSteven Rostedt
3673ccc513b6SSteven Rostedt		if ($type eq "test" && !$failed) {
3674ccc513b6SSteven Rostedt		    do_run_test or $failed = 1;
3675ccc513b6SSteven Rostedt		}
3676ccc513b6SSteven Rostedt
36774c4ab120SSteven Rostedt		end_monitor;
3678bf1c95abSSteven Rostedt	}
36794c4ab120SSteven Rostedt
36804c4ab120SSteven Rostedt	$in_bisect = 0;
36814c4ab120SSteven Rostedt
36824c4ab120SSteven Rostedt	if ($failed) {
3683b9066f6cSSteven Rostedt	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
36844c4ab120SSteven Rostedt	    # this config is needed, add it to the ignore list.
36854c4ab120SSteven Rostedt	    $keep_configs{$config} = $min_configs{$config};
368643d1b651SSteven Rostedt	    $save_configs{$config} = $min_configs{$config};
36874c4ab120SSteven Rostedt	    delete $min_configs{$config};
368835ce5952SSteven Rostedt
368935ce5952SSteven Rostedt	    # update new ignore configs
369035ce5952SSteven Rostedt	    if (defined($ignore_config)) {
369135ce5952SSteven Rostedt		open (OUT, ">$temp_config")
369235ce5952SSteven Rostedt		    or die "Can't write to $temp_config";
369343d1b651SSteven Rostedt		foreach my $config (keys %save_configs) {
369443d1b651SSteven Rostedt		    print OUT "$save_configs{$config}\n";
369535ce5952SSteven Rostedt		}
369635ce5952SSteven Rostedt		close OUT;
369735ce5952SSteven Rostedt		run_command "mv $temp_config $ignore_config" or
369835ce5952SSteven Rostedt		    dodie "failed to copy update to $ignore_config";
369935ce5952SSteven Rostedt	    }
370035ce5952SSteven Rostedt
37014c4ab120SSteven Rostedt	} else {
37024c4ab120SSteven Rostedt	    # We booted without this config, remove it from the minconfigs.
37034c4ab120SSteven Rostedt	    doprint "$config is not needed, disabling\n";
37044c4ab120SSteven Rostedt
37054c4ab120SSteven Rostedt	    delete $min_configs{$config};
37064c4ab120SSteven Rostedt
37074c4ab120SSteven Rostedt	    # Also disable anything that is not enabled in this config
37084c4ab120SSteven Rostedt	    my %configs;
37094c4ab120SSteven Rostedt	    assign_configs \%configs, $output_config;
37104c4ab120SSteven Rostedt	    my @config_keys = keys %min_configs;
37114c4ab120SSteven Rostedt	    foreach my $config (@config_keys) {
37124c4ab120SSteven Rostedt		if (!defined($configs{$config})) {
37134c4ab120SSteven Rostedt		    doprint "$config is not set, disabling\n";
37144c4ab120SSteven Rostedt		    delete $min_configs{$config};
37154c4ab120SSteven Rostedt		}
37164c4ab120SSteven Rostedt	    }
37174c4ab120SSteven Rostedt
37184c4ab120SSteven Rostedt	    # Save off all the current mandidory configs
371935ce5952SSteven Rostedt	    open (OUT, ">$temp_config")
372035ce5952SSteven Rostedt		or die "Can't write to $temp_config";
37214c4ab120SSteven Rostedt	    foreach my $config (keys %keep_configs) {
37224c4ab120SSteven Rostedt		print OUT "$keep_configs{$config}\n";
37234c4ab120SSteven Rostedt	    }
37244c4ab120SSteven Rostedt	    foreach my $config (keys %min_configs) {
37254c4ab120SSteven Rostedt		print OUT "$min_configs{$config}\n";
37264c4ab120SSteven Rostedt	    }
37274c4ab120SSteven Rostedt	    close OUT;
372835ce5952SSteven Rostedt
372935ce5952SSteven Rostedt	    run_command "mv $temp_config $output_minconfig" or
373035ce5952SSteven Rostedt		dodie "failed to copy update to $output_minconfig";
37314c4ab120SSteven Rostedt	}
37324c4ab120SSteven Rostedt
37334c4ab120SSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
3734bc7c5803SSteven Rostedt	reboot_to_good $sleep_time;
37354c4ab120SSteven Rostedt    }
37364c4ab120SSteven Rostedt
37374c4ab120SSteven Rostedt    success $i;
37384c4ab120SSteven Rostedt    return 1;
37394c4ab120SSteven Rostedt}
37404c4ab120SSteven Rostedt
37414283b169SSteven Rostedt (Red Hat)sub make_warnings_file {
37424283b169SSteven Rostedt (Red Hat)    my ($i) = @_;
37434283b169SSteven Rostedt (Red Hat)
37444283b169SSteven Rostedt (Red Hat)    if (!defined($warnings_file)) {
37454283b169SSteven Rostedt (Red Hat)	dodie "Must define WARNINGS_FILE for make_warnings_file test";
37464283b169SSteven Rostedt (Red Hat)    }
37474283b169SSteven Rostedt (Red Hat)
37484283b169SSteven Rostedt (Red Hat)    if ($build_type eq "nobuild") {
37494283b169SSteven Rostedt (Red Hat)	dodie "BUILD_TYPE can not be 'nobuild' for make_warnings_file test";
37504283b169SSteven Rostedt (Red Hat)    }
37514283b169SSteven Rostedt (Red Hat)
37524283b169SSteven Rostedt (Red Hat)    build $build_type or dodie "Failed to build";
37534283b169SSteven Rostedt (Red Hat)
37544283b169SSteven Rostedt (Red Hat)    open(OUT, ">$warnings_file") or dodie "Can't create $warnings_file";
37554283b169SSteven Rostedt (Red Hat)
37564283b169SSteven Rostedt (Red Hat)    open(IN, $buildlog) or dodie "Can't open $buildlog";
37574283b169SSteven Rostedt (Red Hat)    while (<IN>) {
37584283b169SSteven Rostedt (Red Hat)
37594283b169SSteven Rostedt (Red Hat)	# Some compilers use UTF-8 extended for quotes
37604283b169SSteven Rostedt (Red Hat)	# for distcc heterogeneous systems, this causes issues
37614283b169SSteven Rostedt (Red Hat)	s/$utf8_quote/'/g;
37624283b169SSteven Rostedt (Red Hat)
37634283b169SSteven Rostedt (Red Hat)	if (/$check_build_re/) {
37644283b169SSteven Rostedt (Red Hat)	    print OUT;
37654283b169SSteven Rostedt (Red Hat)	}
37664283b169SSteven Rostedt (Red Hat)    }
37674283b169SSteven Rostedt (Red Hat)    close(IN);
37684283b169SSteven Rostedt (Red Hat)
37694283b169SSteven Rostedt (Red Hat)    close(OUT);
37704283b169SSteven Rostedt (Red Hat)
37714283b169SSteven Rostedt (Red Hat)    success $i;
37724283b169SSteven Rostedt (Red Hat)}
37734283b169SSteven Rostedt (Red Hat)
37748d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
37752545eb61SSteven Rostedt
37768d1491baSSteven Rostedtif ($#ARGV == 0) {
37778d1491baSSteven Rostedt    $ktest_config = $ARGV[0];
37788d1491baSSteven Rostedt    if (! -f $ktest_config) {
37798d1491baSSteven Rostedt	print "$ktest_config does not exist.\n";
378035ce5952SSteven Rostedt	if (!read_yn "Create it?") {
37818d1491baSSteven Rostedt	    exit 0;
37828d1491baSSteven Rostedt	}
37838d1491baSSteven Rostedt    }
37848d1491baSSteven Rostedt} else {
37858d1491baSSteven Rostedt    $ktest_config = "ktest.conf";
37868d1491baSSteven Rostedt}
37878d1491baSSteven Rostedt
37888d1491baSSteven Rostedtif (! -f $ktest_config) {
3789dbd3783bSSteven Rostedt    $newconfig = 1;
3790c4261d0fSSteven Rostedt    get_test_case;
37918d1491baSSteven Rostedt    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
37928d1491baSSteven Rostedt    print OUT << "EOF"
37938d1491baSSteven Rostedt# Generated by ktest.pl
37948d1491baSSteven Rostedt#
37950e7a22deSSteven Rostedt
37960e7a22deSSteven Rostedt# PWD is a ktest.pl variable that will result in the process working
37970e7a22deSSteven Rostedt# directory that ktest.pl is executed in.
37980e7a22deSSteven Rostedt
37990e7a22deSSteven Rostedt# THIS_DIR is automatically assigned the PWD of the path that generated
38000e7a22deSSteven Rostedt# the config file. It is best to use this variable when assigning other
38010e7a22deSSteven Rostedt# directory paths within this directory. This allows you to easily
38020e7a22deSSteven Rostedt# move the test cases to other locations or to other machines.
38030e7a22deSSteven Rostedt#
38040e7a22deSSteven RostedtTHIS_DIR := $variable{"PWD"}
38050e7a22deSSteven Rostedt
38068d1491baSSteven Rostedt# Define each test with TEST_START
38078d1491baSSteven Rostedt# The config options below it will override the defaults
38088d1491baSSteven RostedtTEST_START
3809c4261d0fSSteven RostedtTEST_TYPE = $default{"TEST_TYPE"}
38108d1491baSSteven Rostedt
38118d1491baSSteven RostedtDEFAULTS
38128d1491baSSteven RostedtEOF
38138d1491baSSteven Rostedt;
38148d1491baSSteven Rostedt    close(OUT);
38158d1491baSSteven Rostedt}
38168d1491baSSteven Rostedtread_config $ktest_config;
38178d1491baSSteven Rostedt
381823715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) {
381904262be3SSteven Rostedt (Red Hat)    $opt{"LOG_FILE"} = eval_option("LOG_FILE", $opt{"LOG_FILE"}, -1);
382023715c3cSSteven Rostedt}
382123715c3cSSteven Rostedt
38228d1491baSSteven Rostedt# Append any configs entered in manually to the config file.
38238d1491baSSteven Rostedtmy @new_configs = keys %entered_configs;
38248d1491baSSteven Rostedtif ($#new_configs >= 0) {
38258d1491baSSteven Rostedt    print "\nAppending entered in configs to $ktest_config\n";
38268d1491baSSteven Rostedt    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
38278d1491baSSteven Rostedt    foreach my $config (@new_configs) {
38288d1491baSSteven Rostedt	print OUT "$config = $entered_configs{$config}\n";
38290e7a22deSSteven Rostedt	$opt{$config} = process_variables($entered_configs{$config});
38308d1491baSSteven Rostedt    }
38318d1491baSSteven Rostedt}
38322545eb61SSteven Rostedt
38332b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
38342b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
38352b7d9b21SSteven Rostedt}
38362545eb61SSteven Rostedt
38372b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
38382b7d9b21SSteven Rostedt
3839a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
3840a57419b3SSteven Rostedt
3841a57419b3SSteven Rostedt    if (!$i) {
3842a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
3843a57419b3SSteven Rostedt    } else {
3844a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
3845a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
3846a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
3847a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
3848a57419b3SSteven Rostedt	}
3849a57419b3SSteven Rostedt	doprint "\n";
3850a57419b3SSteven Rostedt    }
3851a57419b3SSteven Rostedt
38522b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
3853a57419b3SSteven Rostedt
3854a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
3855a57419b3SSteven Rostedt	    next if ($i != $1);
3856a57419b3SSteven Rostedt	} else {
3857a57419b3SSteven Rostedt	    next if ($i);
3858a57419b3SSteven Rostedt	}
3859a57419b3SSteven Rostedt
38602b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
38612b7d9b21SSteven Rostedt    }
3862a57419b3SSteven Rostedt}
38632545eb61SSteven Rostedt
38642a62512bSSteven Rostedtsub __set_test_option {
38655a391fbfSSteven Rostedt    my ($name, $i) = @_;
38665a391fbfSSteven Rostedt
38675a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
38685a391fbfSSteven Rostedt
38695a391fbfSSteven Rostedt    if (defined($opt{$option})) {
38705a391fbfSSteven Rostedt	return $opt{$option};
38715a391fbfSSteven Rostedt    }
38725a391fbfSSteven Rostedt
3873a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
3874a57419b3SSteven Rostedt	if ($i >= $test &&
3875a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
3876a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
3877a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
3878a57419b3SSteven Rostedt		return $opt{$option};
3879a57419b3SSteven Rostedt	    }
3880a57419b3SSteven Rostedt	}
3881a57419b3SSteven Rostedt    }
3882a57419b3SSteven Rostedt
38835a391fbfSSteven Rostedt    if (defined($opt{$name})) {
38845a391fbfSSteven Rostedt	return $opt{$name};
38855a391fbfSSteven Rostedt    }
38865a391fbfSSteven Rostedt
38875a391fbfSSteven Rostedt    return undef;
38885a391fbfSSteven Rostedt}
38895a391fbfSSteven Rostedt
38902a62512bSSteven Rostedtsub set_test_option {
38912a62512bSSteven Rostedt    my ($name, $i) = @_;
38922a62512bSSteven Rostedt
38932a62512bSSteven Rostedt    my $option = __set_test_option($name, $i);
38942a62512bSSteven Rostedt    return $option if (!defined($option));
38952a62512bSSteven Rostedt
389604262be3SSteven Rostedt (Red Hat)    return eval_option($name, $option, $i);
38972a62512bSSteven Rostedt}
38982a62512bSSteven Rostedt
38992545eb61SSteven Rostedt# First we need to do is the builds
3900a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
39012545eb61SSteven Rostedt
39024ab1cce5SSteven Rostedt    # Do not reboot on failing test options
39034ab1cce5SSteven Rostedt    $no_reboot = 1;
3904759a3cc6SSteven Rostedt    $reboot_success = 0;
39054ab1cce5SSteven Rostedt
3906683a3e64SSteven Rostedt    $have_version = 0;
3907683a3e64SSteven Rostedt
3908576f627cSSteven Rostedt    $iteration = $i;
3909576f627cSSteven Rostedt
3910c1434dccSSteven Rostedt    undef %force_config;
3911c1434dccSSteven Rostedt
3912a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
3913a75fececSSteven Rostedt
39149cc9e091SSteven Rostedt    # Load all the options into their mapped variable names
39159cc9e091SSteven Rostedt    foreach my $opt (keys %option_map) {
39169cc9e091SSteven Rostedt	${$option_map{$opt}} = set_test_option($opt, $i);
39179cc9e091SSteven Rostedt    }
3918b5f4aea6SSteven Rostedt
391935ce5952SSteven Rostedt    $start_minconfig_defined = 1;
392035ce5952SSteven Rostedt
3921921ed4c7SSteven Rostedt    # The first test may override the PRE_KTEST option
3922921ed4c7SSteven Rostedt    if (defined($pre_ktest) && $i == 1) {
3923921ed4c7SSteven Rostedt	doprint "\n";
3924921ed4c7SSteven Rostedt	run_command $pre_ktest;
3925921ed4c7SSteven Rostedt    }
3926921ed4c7SSteven Rostedt
3927921ed4c7SSteven Rostedt    # Any test can override the POST_KTEST option
3928921ed4c7SSteven Rostedt    # The last test takes precedence.
3929921ed4c7SSteven Rostedt    if (defined($post_ktest)) {
3930921ed4c7SSteven Rostedt	$final_post_ktest = $post_ktest;
3931921ed4c7SSteven Rostedt    }
3932921ed4c7SSteven Rostedt
39334c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
393435ce5952SSteven Rostedt	$start_minconfig_defined = 0;
39354c4ab120SSteven Rostedt	$start_minconfig = $minconfig;
39364c4ab120SSteven Rostedt    }
39374c4ab120SSteven Rostedt
3938a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
3939a75fececSSteven Rostedt
3940a908a665SAndrew Jones    foreach my $dir ($tmpdir, $outputdir) {
3941a908a665SAndrew Jones	if (!-d $dir) {
3942a908a665SAndrew Jones	    mkpath($dir) or
3943a908a665SAndrew Jones		die "can't create $dir";
3944a908a665SAndrew Jones	}
3945a75fececSSteven Rostedt    }
3946a75fececSSteven Rostedt
3947e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
3948e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
3949e48c5293SSteven Rostedt
3950a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
3951a9dd5d63SRabin Vincent    $testlog = "$tmpdir/testlog-$machine";
3952a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
3953a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
395451ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
3955a75fececSSteven Rostedt
3956bb8474b1SSteven Rostedt    if (!$buildonly) {
3957bb8474b1SSteven Rostedt	$target = "$ssh_user\@$machine";
3958a75fececSSteven Rostedt	if ($reboot_type eq "grub") {
3959576f627cSSteven Rostedt	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3960a15ba913SSteven Rostedt	} elsif ($reboot_type eq "grub2") {
3961a15ba913SSteven Rostedt	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3962a15ba913SSteven Rostedt	    dodie "GRUB_FILE not defined" if (!defined($grub_file));
39637786954cSSteven Rostedt	} elsif ($reboot_type eq "syslinux") {
39647786954cSSteven Rostedt	    dodie "SYSLINUX_LABEL not defined" if (!defined($syslinux_label));
3965a75fececSSteven Rostedt	}
3966bb8474b1SSteven Rostedt    }
3967a75fececSSteven Rostedt
3968a75fececSSteven Rostedt    my $run_type = $build_type;
3969a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
3970b5f4aea6SSteven Rostedt	$run_type = $patchcheck_type;
3971a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
3972b5f4aea6SSteven Rostedt	$run_type = $bisect_type;
39730a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
3974b5f4aea6SSteven Rostedt	$run_type = $config_bisect_type;
39754283b169SSteven Rostedt (Red Hat)    } elsif ($test_type eq "make_min_config") {
39764283b169SSteven Rostedt (Red Hat)	$run_type = "";
39774283b169SSteven Rostedt (Red Hat)    } elsif ($test_type eq "make_warnings_file") {
39784c4ab120SSteven Rostedt	$run_type = "";
39794c4ab120SSteven Rostedt    }
39804c4ab120SSteven Rostedt
3981a75fececSSteven Rostedt    # mistake in config file?
3982a75fececSSteven Rostedt    if (!defined($run_type)) {
3983a75fececSSteven Rostedt	$run_type = "ERROR";
3984a75fececSSteven Rostedt    }
39852545eb61SSteven Rostedt
3986e0a8742eSSteven Rostedt    my $installme = "";
3987e0a8742eSSteven Rostedt    $installme = " no_install" if ($no_install);
3988e0a8742eSSteven Rostedt
39892545eb61SSteven Rostedt    doprint "\n\n";
3990e0a8742eSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
39917faafbd6SSteven Rostedt
3992921ed4c7SSteven Rostedt    if (defined($pre_test)) {
3993921ed4c7SSteven Rostedt	run_command $pre_test;
3994921ed4c7SSteven Rostedt    }
3995921ed4c7SSteven Rostedt
39967faafbd6SSteven Rostedt    unlink $dmesg;
39977faafbd6SSteven Rostedt    unlink $buildlog;
3998a9dd5d63SRabin Vincent    unlink $testlog;
39992545eb61SSteven Rostedt
4000250bae8bSSteven Rostedt    if (defined($addconfig)) {
4001250bae8bSSteven Rostedt	my $min = $minconfig;
40022b7d9b21SSteven Rostedt	if (!defined($minconfig)) {
4003250bae8bSSteven Rostedt	    $min = "";
4004250bae8bSSteven Rostedt	}
4005250bae8bSSteven Rostedt	run_command "cat $addconfig $min > $tmpdir/add_config" or
40062b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
40079be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
40082b7d9b21SSteven Rostedt    }
40092b7d9b21SSteven Rostedt
40106c5ee0beSSteven Rostedt    if (defined($checkout)) {
40116c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
40126c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
40136c5ee0beSSteven Rostedt    }
40146c5ee0beSSteven Rostedt
4015759a3cc6SSteven Rostedt    $no_reboot = 0;
4016759a3cc6SSteven Rostedt
4017648a182cSSteven Rostedt    # A test may opt to not reboot the box
4018648a182cSSteven Rostedt    if ($reboot_on_success) {
4019759a3cc6SSteven Rostedt	$reboot_success = 1;
4020648a182cSSteven Rostedt    }
40214ab1cce5SSteven Rostedt
4022a75fececSSteven Rostedt    if ($test_type eq "bisect") {
40235f9b6cedSSteven Rostedt	bisect $i;
40245f9b6cedSSteven Rostedt	next;
40250a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
40260a05c769SSteven Rostedt	config_bisect $i;
40270a05c769SSteven Rostedt	next;
4028a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
40296c5ee0beSSteven Rostedt	patchcheck $i;
40306c5ee0beSSteven Rostedt	next;
40314c4ab120SSteven Rostedt    } elsif ($test_type eq "make_min_config") {
40324c4ab120SSteven Rostedt	make_min_config $i;
40334c4ab120SSteven Rostedt	next;
40344283b169SSteven Rostedt (Red Hat)    } elsif ($test_type eq "make_warnings_file") {
40354283b169SSteven Rostedt (Red Hat)	$no_reboot = 1;
40364283b169SSteven Rostedt (Red Hat)	make_warnings_file $i;
40374283b169SSteven Rostedt (Red Hat)	next;
40385f9b6cedSSteven Rostedt    }
40395f9b6cedSSteven Rostedt
40407faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
40417faafbd6SSteven Rostedt	build $build_type or next;
40424283b169SSteven Rostedt (Red Hat)	check_buildlog or next;
40432545eb61SSteven Rostedt    }
40442545eb61SSteven Rostedt
4045cd8e368fSSteven Rostedt    if ($test_type eq "install") {
4046cd8e368fSSteven Rostedt	get_version;
4047cd8e368fSSteven Rostedt	install;
4048cd8e368fSSteven Rostedt	success $i;
4049cd8e368fSSteven Rostedt	next;
4050cd8e368fSSteven Rostedt    }
4051cd8e368fSSteven Rostedt
4052a75fececSSteven Rostedt    if ($test_type ne "build") {
40537faafbd6SSteven Rostedt	my $failed = 0;
4054ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
4055a75fececSSteven Rostedt
4056a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
40577faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
40585a391fbfSSteven Rostedt	}
40597faafbd6SSteven Rostedt	end_monitor;
40607faafbd6SSteven Rostedt	next if ($failed);
4061a75fececSSteven Rostedt    }
40625a391fbfSSteven Rostedt
40635f9b6cedSSteven Rostedt    success $i;
406475c3fda7SSteven Rostedt}
40652545eb61SSteven Rostedt
4066921ed4c7SSteven Rostedtif (defined($final_post_ktest)) {
4067921ed4c7SSteven Rostedt    run_command $final_post_ktest;
4068921ed4c7SSteven Rostedt}
4069921ed4c7SSteven Rostedt
40705c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
407175c3fda7SSteven Rostedt    halt;
4072759a3cc6SSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) {
4073bc7c5803SSteven Rostedt    reboot_to_good;
4074648a182cSSteven Rostedt} elsif (defined($switch_to_good)) {
4075648a182cSSteven Rostedt    # still need to get to the good kernel
4076648a182cSSteven Rostedt    run_command $switch_to_good;
40775c42fc5bSSteven Rostedt}
407875c3fda7SSteven Rostedt
4079648a182cSSteven Rostedt
4080e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
4081e48c5293SSteven Rostedt
40822545eb61SSteven Rostedtexit 0;
4083