xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision 8b513d0cf603c0a9ccf86a92cb22931f05a7bc86)
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;
76df5f7c66SSteven Rostedt (Red Hat)my $last_machine;
77e48c5293SSteven Rostedtmy $ssh_user;
78a75fececSSteven Rostedtmy $tmpdir;
79a75fececSSteven Rostedtmy $builddir;
80a75fececSSteven Rostedtmy $outputdir;
8151ad1dd1SSteven Rostedtmy $output_config;
82a75fececSSteven Rostedtmy $test_type;
837faafbd6SSteven Rostedtmy $build_type;
84a75fececSSteven Rostedtmy $build_options;
85921ed4c7SSteven Rostedtmy $final_post_ktest;
86921ed4c7SSteven Rostedtmy $pre_ktest;
87921ed4c7SSteven Rostedtmy $post_ktest;
88921ed4c7SSteven Rostedtmy $pre_test;
89921ed4c7SSteven Rostedtmy $post_test;
900bd6c1a3SSteven Rostedtmy $pre_build;
910bd6c1a3SSteven Rostedtmy $post_build;
920bd6c1a3SSteven Rostedtmy $pre_build_die;
930bd6c1a3SSteven Rostedtmy $post_build_die;
94a75fececSSteven Rostedtmy $reboot_type;
95a75fececSSteven Rostedtmy $reboot_script;
96a75fececSSteven Rostedtmy $power_cycle;
97e48c5293SSteven Rostedtmy $reboot;
98a75fececSSteven Rostedtmy $reboot_on_error;
99bc7c5803SSteven Rostedtmy $switch_to_good;
100bc7c5803SSteven Rostedtmy $switch_to_test;
101a75fececSSteven Rostedtmy $poweroff_on_error;
102648a182cSSteven Rostedtmy $reboot_on_success;
103a75fececSSteven Rostedtmy $die_on_failure;
104576f627cSSteven Rostedtmy $powercycle_after_reboot;
105576f627cSSteven Rostedtmy $poweroff_after_halt;
106407b95b7SSteven Rostedtmy $max_monitor_wait;
107e48c5293SSteven Rostedtmy $ssh_exec;
108e48c5293SSteven Rostedtmy $scp_to_target;
10902ad2617SSteven Rostedtmy $scp_to_target_install;
110a75fececSSteven Rostedtmy $power_off;
111a75fececSSteven Rostedtmy $grub_menu;
112752d9665SSteven Rostedt (Red Hat)my $last_grub_menu;
113a15ba913SSteven Rostedtmy $grub_file;
1142545eb61SSteven Rostedtmy $grub_number;
115a15ba913SSteven Rostedtmy $grub_reboot;
1167786954cSSteven Rostedtmy $syslinux;
1177786954cSSteven Rostedtmy $syslinux_path;
1187786954cSSteven Rostedtmy $syslinux_label;
1192545eb61SSteven Rostedtmy $target;
1202545eb61SSteven Rostedtmy $make;
121e5c2ec11SSteven Rostedtmy $pre_install;
1228b37ca8cSSteven Rostedtmy $post_install;
123e0a8742eSSteven Rostedtmy $no_install;
1245c42fc5bSSteven Rostedtmy $noclean;
1255f9b6cedSSteven Rostedtmy $minconfig;
1264c4ab120SSteven Rostedtmy $start_minconfig;
12735ce5952SSteven Rostedtmy $start_minconfig_defined;
1284c4ab120SSteven Rostedtmy $output_minconfig;
129ccc513b6SSteven Rostedtmy $minconfig_type;
13043de3316SSteven Rostedtmy $use_output_minconfig;
1314283b169SSteven Rostedt (Red Hat)my $warnings_file;
1324c4ab120SSteven Rostedtmy $ignore_config;
133be405f95SSteven Rostedtmy $ignore_errors;
1342b7d9b21SSteven Rostedtmy $addconfig;
1355f9b6cedSSteven Rostedtmy $in_bisect = 0;
136b5f4aea6SSteven Rostedtmy $bisect_bad_commit = "";
137d6ce2a0bSSteven Rostedtmy $reverse_bisect;
138c960bb9fSSteven Rostedtmy $bisect_manual;
139c23dca7cSSteven Rostedtmy $bisect_skip;
14030f75da5SSteven Rostedtmy $config_bisect_good;
141c5dacb88SSteven Rostedtmy $bisect_ret_good;
142c5dacb88SSteven Rostedtmy $bisect_ret_bad;
143c5dacb88SSteven Rostedtmy $bisect_ret_skip;
144c5dacb88SSteven Rostedtmy $bisect_ret_abort;
145c5dacb88SSteven Rostedtmy $bisect_ret_default;
1466c5ee0beSSteven Rostedtmy $in_patchcheck = 0;
1475a391fbfSSteven Rostedtmy $run_test;
1486c5ee0beSSteven Rostedtmy $redirect;
1497faafbd6SSteven Rostedtmy $buildlog;
150a9dd5d63SRabin Vincentmy $testlog;
1517faafbd6SSteven Rostedtmy $dmesg;
1527faafbd6SSteven Rostedtmy $monitor_fp;
1537faafbd6SSteven Rostedtmy $monitor_pid;
1547faafbd6SSteven Rostedtmy $monitor_cnt = 0;
155a75fececSSteven Rostedtmy $sleep_time;
156a75fececSSteven Rostedtmy $bisect_sleep_time;
15727d934b2SSteven Rostedtmy $patchcheck_sleep_time;
1581990207dSSteven Rostedtmy $ignore_warnings;
159a75fececSSteven Rostedtmy $store_failures;
160de5b6e3bSRabin Vincentmy $store_successes;
1619064af52SSteven Rostedtmy $test_name;
162a75fececSSteven Rostedtmy $timeout;
163a75fececSSteven Rostedtmy $booted_timeout;
164f1a5b962SSteven Rostedtmy $detect_triplefault;
165a75fececSSteven Rostedtmy $console;
1662b803365SSteven Rostedtmy $reboot_success_line;
167a75fececSSteven Rostedtmy $success_line;
1681c8a617aSSteven Rostedtmy $stop_after_success;
1691c8a617aSSteven Rostedtmy $stop_after_failure;
1702d01b26aSSteven Rostedtmy $stop_test_after;
171a75fececSSteven Rostedtmy $build_target;
172a75fececSSteven Rostedtmy $target_image;
173b5f4aea6SSteven Rostedtmy $checkout;
174a75fececSSteven Rostedtmy $localversion;
175576f627cSSteven Rostedtmy $iteration = 0;
176e48c5293SSteven Rostedtmy $successes = 0;
1772545eb61SSteven Rostedt
178b5f4aea6SSteven Rostedtmy $bisect_good;
179b5f4aea6SSteven Rostedtmy $bisect_bad;
180b5f4aea6SSteven Rostedtmy $bisect_type;
181b5f4aea6SSteven Rostedtmy $bisect_start;
182b5f4aea6SSteven Rostedtmy $bisect_replay;
183b5f4aea6SSteven Rostedtmy $bisect_files;
184b5f4aea6SSteven Rostedtmy $bisect_reverse;
185b5f4aea6SSteven Rostedtmy $bisect_check;
186b5f4aea6SSteven Rostedt
187b5f4aea6SSteven Rostedtmy $config_bisect;
188b5f4aea6SSteven Rostedtmy $config_bisect_type;
189b0918612SSteven Rostedtmy $config_bisect_check;
190b5f4aea6SSteven Rostedt
191b5f4aea6SSteven Rostedtmy $patchcheck_type;
192b5f4aea6SSteven Rostedtmy $patchcheck_start;
193b5f4aea6SSteven Rostedtmy $patchcheck_end;
194b5f4aea6SSteven Rostedt
195165708b2SSteven Rostedt# set when a test is something other that just building or install
196bb8474b1SSteven Rostedt# which would require more options.
197bb8474b1SSteven Rostedtmy $buildonly = 1;
198bb8474b1SSteven Rostedt
1994283b169SSteven Rostedt (Red Hat)# tell build not to worry about warnings, even when WARNINGS_FILE is set
2004283b169SSteven Rostedt (Red Hat)my $warnings_ok = 0;
2014283b169SSteven Rostedt (Red Hat)
202dbd3783bSSteven Rostedt# set when creating a new config
203dbd3783bSSteven Rostedtmy $newconfig = 0;
204dbd3783bSSteven Rostedt
2058d1491baSSteven Rostedtmy %entered_configs;
2068d1491baSSteven Rostedtmy %config_help;
20777d942ceSSteven Rostedtmy %variable;
208cf79fab6SSteven Rostedt
209cf79fab6SSteven Rostedt# force_config is the list of configs that we force enabled (or disabled)
210cf79fab6SSteven Rostedt# in a .config file. The MIN_CONFIG and ADD_CONFIG configs.
211fcb3f16aSSteven Rostedtmy %force_config;
2128d1491baSSteven Rostedt
2134ab1cce5SSteven Rostedt# do not force reboots on config problems
2144ab1cce5SSteven Rostedtmy $no_reboot = 1;
2154ab1cce5SSteven Rostedt
216759a3cc6SSteven Rostedt# reboot on success
217759a3cc6SSteven Rostedtmy $reboot_success = 0;
218759a3cc6SSteven Rostedt
2199cc9e091SSteven Rostedtmy %option_map = (
2209cc9e091SSteven Rostedt    "MACHINE"			=> \$machine,
2219cc9e091SSteven Rostedt    "SSH_USER"			=> \$ssh_user,
2229cc9e091SSteven Rostedt    "TMP_DIR"			=> \$tmpdir,
2239cc9e091SSteven Rostedt    "OUTPUT_DIR"		=> \$outputdir,
2249cc9e091SSteven Rostedt    "BUILD_DIR"			=> \$builddir,
2259cc9e091SSteven Rostedt    "TEST_TYPE"			=> \$test_type,
226921ed4c7SSteven Rostedt    "PRE_KTEST"			=> \$pre_ktest,
227921ed4c7SSteven Rostedt    "POST_KTEST"		=> \$post_ktest,
228921ed4c7SSteven Rostedt    "PRE_TEST"			=> \$pre_test,
229921ed4c7SSteven Rostedt    "POST_TEST"			=> \$post_test,
2309cc9e091SSteven Rostedt    "BUILD_TYPE"		=> \$build_type,
2319cc9e091SSteven Rostedt    "BUILD_OPTIONS"		=> \$build_options,
2329cc9e091SSteven Rostedt    "PRE_BUILD"			=> \$pre_build,
2339cc9e091SSteven Rostedt    "POST_BUILD"		=> \$post_build,
2349cc9e091SSteven Rostedt    "PRE_BUILD_DIE"		=> \$pre_build_die,
2359cc9e091SSteven Rostedt    "POST_BUILD_DIE"		=> \$post_build_die,
2369cc9e091SSteven Rostedt    "POWER_CYCLE"		=> \$power_cycle,
2379cc9e091SSteven Rostedt    "REBOOT"			=> \$reboot,
2389cc9e091SSteven Rostedt    "BUILD_NOCLEAN"		=> \$noclean,
2399cc9e091SSteven Rostedt    "MIN_CONFIG"		=> \$minconfig,
2409cc9e091SSteven Rostedt    "OUTPUT_MIN_CONFIG"		=> \$output_minconfig,
2419cc9e091SSteven Rostedt    "START_MIN_CONFIG"		=> \$start_minconfig,
242ccc513b6SSteven Rostedt    "MIN_CONFIG_TYPE"		=> \$minconfig_type,
24343de3316SSteven Rostedt    "USE_OUTPUT_MIN_CONFIG"	=> \$use_output_minconfig,
2444283b169SSteven Rostedt (Red Hat)    "WARNINGS_FILE"		=> \$warnings_file,
2459cc9e091SSteven Rostedt    "IGNORE_CONFIG"		=> \$ignore_config,
2469cc9e091SSteven Rostedt    "TEST"			=> \$run_test,
2479cc9e091SSteven Rostedt    "ADD_CONFIG"		=> \$addconfig,
2489cc9e091SSteven Rostedt    "REBOOT_TYPE"		=> \$reboot_type,
2499cc9e091SSteven Rostedt    "GRUB_MENU"			=> \$grub_menu,
250a15ba913SSteven Rostedt    "GRUB_FILE"			=> \$grub_file,
251a15ba913SSteven Rostedt    "GRUB_REBOOT"		=> \$grub_reboot,
2527786954cSSteven Rostedt    "SYSLINUX"			=> \$syslinux,
2537786954cSSteven Rostedt    "SYSLINUX_PATH"		=> \$syslinux_path,
2547786954cSSteven Rostedt    "SYSLINUX_LABEL"		=> \$syslinux_label,
255e5c2ec11SSteven Rostedt    "PRE_INSTALL"		=> \$pre_install,
2569cc9e091SSteven Rostedt    "POST_INSTALL"		=> \$post_install,
2579cc9e091SSteven Rostedt    "NO_INSTALL"		=> \$no_install,
2589cc9e091SSteven Rostedt    "REBOOT_SCRIPT"		=> \$reboot_script,
2599cc9e091SSteven Rostedt    "REBOOT_ON_ERROR"		=> \$reboot_on_error,
2609cc9e091SSteven Rostedt    "SWITCH_TO_GOOD"		=> \$switch_to_good,
2619cc9e091SSteven Rostedt    "SWITCH_TO_TEST"		=> \$switch_to_test,
2629cc9e091SSteven Rostedt    "POWEROFF_ON_ERROR"		=> \$poweroff_on_error,
263648a182cSSteven Rostedt    "REBOOT_ON_SUCCESS"		=> \$reboot_on_success,
2649cc9e091SSteven Rostedt    "DIE_ON_FAILURE"		=> \$die_on_failure,
2659cc9e091SSteven Rostedt    "POWER_OFF"			=> \$power_off,
2669cc9e091SSteven Rostedt    "POWERCYCLE_AFTER_REBOOT"	=> \$powercycle_after_reboot,
2679cc9e091SSteven Rostedt    "POWEROFF_AFTER_HALT"	=> \$poweroff_after_halt,
268407b95b7SSteven Rostedt    "MAX_MONITOR_WAIT"		=> \$max_monitor_wait,
2699cc9e091SSteven Rostedt    "SLEEP_TIME"		=> \$sleep_time,
2709cc9e091SSteven Rostedt    "BISECT_SLEEP_TIME"		=> \$bisect_sleep_time,
2719cc9e091SSteven Rostedt    "PATCHCHECK_SLEEP_TIME"	=> \$patchcheck_sleep_time,
2729cc9e091SSteven Rostedt    "IGNORE_WARNINGS"		=> \$ignore_warnings,
273be405f95SSteven Rostedt    "IGNORE_ERRORS"		=> \$ignore_errors,
2749cc9e091SSteven Rostedt    "BISECT_MANUAL"		=> \$bisect_manual,
2759cc9e091SSteven Rostedt    "BISECT_SKIP"		=> \$bisect_skip,
2769cc9e091SSteven Rostedt    "CONFIG_BISECT_GOOD"	=> \$config_bisect_good,
2779cc9e091SSteven Rostedt    "BISECT_RET_GOOD"		=> \$bisect_ret_good,
2789cc9e091SSteven Rostedt    "BISECT_RET_BAD"		=> \$bisect_ret_bad,
2799cc9e091SSteven Rostedt    "BISECT_RET_SKIP"		=> \$bisect_ret_skip,
2809cc9e091SSteven Rostedt    "BISECT_RET_ABORT"		=> \$bisect_ret_abort,
2819cc9e091SSteven Rostedt    "BISECT_RET_DEFAULT"	=> \$bisect_ret_default,
2829cc9e091SSteven Rostedt    "STORE_FAILURES"		=> \$store_failures,
2839cc9e091SSteven Rostedt    "STORE_SUCCESSES"		=> \$store_successes,
2849cc9e091SSteven Rostedt    "TEST_NAME"			=> \$test_name,
2859cc9e091SSteven Rostedt    "TIMEOUT"			=> \$timeout,
2869cc9e091SSteven Rostedt    "BOOTED_TIMEOUT"		=> \$booted_timeout,
2879cc9e091SSteven Rostedt    "CONSOLE"			=> \$console,
2889cc9e091SSteven Rostedt    "DETECT_TRIPLE_FAULT"	=> \$detect_triplefault,
2899cc9e091SSteven Rostedt    "SUCCESS_LINE"		=> \$success_line,
2909cc9e091SSteven Rostedt    "REBOOT_SUCCESS_LINE"	=> \$reboot_success_line,
2919cc9e091SSteven Rostedt    "STOP_AFTER_SUCCESS"	=> \$stop_after_success,
2929cc9e091SSteven Rostedt    "STOP_AFTER_FAILURE"	=> \$stop_after_failure,
2939cc9e091SSteven Rostedt    "STOP_TEST_AFTER"		=> \$stop_test_after,
2949cc9e091SSteven Rostedt    "BUILD_TARGET"		=> \$build_target,
2959cc9e091SSteven Rostedt    "SSH_EXEC"			=> \$ssh_exec,
2969cc9e091SSteven Rostedt    "SCP_TO_TARGET"		=> \$scp_to_target,
29702ad2617SSteven Rostedt    "SCP_TO_TARGET_INSTALL"	=> \$scp_to_target_install,
2989cc9e091SSteven Rostedt    "CHECKOUT"			=> \$checkout,
2999cc9e091SSteven Rostedt    "TARGET_IMAGE"		=> \$target_image,
3009cc9e091SSteven Rostedt    "LOCALVERSION"		=> \$localversion,
3019cc9e091SSteven Rostedt
3029cc9e091SSteven Rostedt    "BISECT_GOOD"		=> \$bisect_good,
3039cc9e091SSteven Rostedt    "BISECT_BAD"		=> \$bisect_bad,
3049cc9e091SSteven Rostedt    "BISECT_TYPE"		=> \$bisect_type,
3059cc9e091SSteven Rostedt    "BISECT_START"		=> \$bisect_start,
3069cc9e091SSteven Rostedt    "BISECT_REPLAY"		=> \$bisect_replay,
3079cc9e091SSteven Rostedt    "BISECT_FILES"		=> \$bisect_files,
3089cc9e091SSteven Rostedt    "BISECT_REVERSE"		=> \$bisect_reverse,
3099cc9e091SSteven Rostedt    "BISECT_CHECK"		=> \$bisect_check,
3109cc9e091SSteven Rostedt
3119cc9e091SSteven Rostedt    "CONFIG_BISECT"		=> \$config_bisect,
3129cc9e091SSteven Rostedt    "CONFIG_BISECT_TYPE"	=> \$config_bisect_type,
313b0918612SSteven Rostedt    "CONFIG_BISECT_CHECK"	=> \$config_bisect_check,
3149cc9e091SSteven Rostedt
3159cc9e091SSteven Rostedt    "PATCHCHECK_TYPE"		=> \$patchcheck_type,
3169cc9e091SSteven Rostedt    "PATCHCHECK_START"		=> \$patchcheck_start,
3179cc9e091SSteven Rostedt    "PATCHCHECK_END"		=> \$patchcheck_end,
3189cc9e091SSteven Rostedt);
3199cc9e091SSteven Rostedt
3209cc9e091SSteven Rostedt# Options may be used by other options, record them.
3219cc9e091SSteven Rostedtmy %used_options;
3229cc9e091SSteven Rostedt
3237bf51073SSteven Rostedt# default variables that can be used
3247bf51073SSteven Rostedtchomp ($variable{"PWD"} = `pwd`);
3257bf51073SSteven Rostedt
3268d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF"
3278d1491baSSteven Rostedt The machine hostname that you will test.
328bb8474b1SSteven Rostedt For build only tests, it is still needed to differentiate log files.
3298d1491baSSteven RostedtEOF
3308d1491baSSteven Rostedt    ;
3318d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF"
3328d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user
3338d1491baSSteven Rostedt  (most likely root, since you need privileged operations)
3348d1491baSSteven RostedtEOF
3358d1491baSSteven Rostedt    ;
3368d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF"
3378d1491baSSteven Rostedt The directory that contains the Linux source code (full path).
3380e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
3390e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
3408d1491baSSteven RostedtEOF
3418d1491baSSteven Rostedt    ;
3428d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF"
3438d1491baSSteven Rostedt The directory that the objects will be built (full path).
3448d1491baSSteven Rostedt (can not be same as BUILD_DIR)
3450e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
3460e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
3478d1491baSSteven RostedtEOF
3488d1491baSSteven Rostedt    ;
3498d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF"
3508d1491baSSteven Rostedt The location of the compiled file to copy to the target.
3518d1491baSSteven Rostedt (relative to OUTPUT_DIR)
3528d1491baSSteven RostedtEOF
3538d1491baSSteven Rostedt    ;
354dbd3783bSSteven Rostedt$config_help{"BUILD_OPTIONS"} = << "EOF"
355dbd3783bSSteven Rostedt Options to add to \"make\" when building.
356dbd3783bSSteven Rostedt i.e.  -j20
357dbd3783bSSteven RostedtEOF
358dbd3783bSSteven Rostedt    ;
3598d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF"
3608d1491baSSteven Rostedt The place to put your image on the test machine.
3618d1491baSSteven RostedtEOF
3628d1491baSSteven Rostedt    ;
3638d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF"
3648d1491baSSteven Rostedt A script or command to reboot the box.
3658d1491baSSteven Rostedt
3668d1491baSSteven Rostedt Here is a digital loggers power switch example
3678d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
3688d1491baSSteven Rostedt
3698d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host
3708d1491baSSteven Rostedt with the name "Guest".
3718d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
3728d1491baSSteven RostedtEOF
3738d1491baSSteven Rostedt    ;
3748d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF"
3758d1491baSSteven Rostedt The script or command that reads the console
3768d1491baSSteven Rostedt
3778d1491baSSteven Rostedt  If you use ttywatch server, something like the following would work.
3788d1491baSSteven RostedtCONSOLE = nc -d localhost 3001
3798d1491baSSteven Rostedt
3808d1491baSSteven Rostedt For a virtual machine with guest name "Guest".
3818d1491baSSteven RostedtCONSOLE =  virsh console Guest
3828d1491baSSteven RostedtEOF
3838d1491baSSteven Rostedt    ;
3848d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF"
3858d1491baSSteven Rostedt Required version ending to differentiate the test
3868d1491baSSteven Rostedt from other linux builds on the system.
3878d1491baSSteven RostedtEOF
3888d1491baSSteven Rostedt    ;
3898d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF"
3908d1491baSSteven Rostedt Way to reboot the box to the test kernel.
3917786954cSSteven Rostedt Only valid options so far are "grub", "grub2", "syslinux", and "script".
3928d1491baSSteven Rostedt
3938d1491baSSteven Rostedt If you specify grub, it will assume grub version 1
3948d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
3958d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not
3968d1491baSSteven Rostedt your setup, then specify "script" and have a command or script
3978d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target.
3988d1491baSSteven Rostedt
3998d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually.
4008d1491baSSteven Rostedt The test will not modify that file.
401a15ba913SSteven Rostedt
402a15ba913SSteven Rostedt If you specify grub2, then you also need to specify both \$GRUB_MENU
403a15ba913SSteven Rostedt and \$GRUB_FILE.
4047786954cSSteven Rostedt
4057786954cSSteven Rostedt If you specify syslinux, then you may use SYSLINUX to define the syslinux
4067786954cSSteven Rostedt command (defaults to extlinux), and SYSLINUX_PATH to specify the path to
4077786954cSSteven Rostedt the syslinux install (defaults to /boot/extlinux). But you have to specify
4087786954cSSteven Rostedt SYSLINUX_LABEL to define the label to boot to for the test kernel.
4098d1491baSSteven RostedtEOF
4108d1491baSSteven Rostedt    ;
4118d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF"
4128d1491baSSteven Rostedt The grub title name for the test kernel to boot
413a15ba913SSteven Rostedt (Only mandatory if REBOOT_TYPE = grub or grub2)
4148d1491baSSteven Rostedt
4158d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to
4168d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search
4178d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to
4188d1491baSSteven Rostedt reboot into.
4198d1491baSSteven Rostedt
4208d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has:
4218d1491baSSteven Rostedt title Test Kernel
4228d1491baSSteven Rostedt kernel vmlinuz-test
4238d1491baSSteven Rostedt GRUB_MENU = Test Kernel
424a15ba913SSteven Rostedt
425a15ba913SSteven Rostedt For grub2, a search of \$GRUB_FILE is performed for the lines
426a15ba913SSteven Rostedt that begin with "menuentry". It will not detect submenus. The
427a15ba913SSteven Rostedt menu must be a non-nested menu. Add the quotes used in the menu
428a15ba913SSteven Rostedt to guarantee your selection, as the first menuentry with the content
429a15ba913SSteven Rostedt of \$GRUB_MENU that is found will be used.
430a15ba913SSteven RostedtEOF
431a15ba913SSteven Rostedt    ;
432a15ba913SSteven Rostedt$config_help{"GRUB_FILE"} = << "EOF"
433a15ba913SSteven Rostedt If grub2 is used, the full path for the grub.cfg file is placed
434a15ba913SSteven Rostedt here. Use something like /boot/grub2/grub.cfg to search.
4358d1491baSSteven RostedtEOF
4368d1491baSSteven Rostedt    ;
4377786954cSSteven Rostedt$config_help{"SYSLINUX_LABEL"} = << "EOF"
4387786954cSSteven Rostedt If syslinux is used, the label that boots the target kernel must
4397786954cSSteven Rostedt be specified with SYSLINUX_LABEL.
4407786954cSSteven RostedtEOF
4417786954cSSteven Rostedt    ;
4428d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF"
4438d1491baSSteven Rostedt A script to reboot the target into the test kernel
4448d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script)
4458d1491baSSteven RostedtEOF
4468d1491baSSteven Rostedt    ;
4478d1491baSSteven Rostedt
448dad98754SSteven Rostedtsub read_prompt {
449dad98754SSteven Rostedt    my ($cancel, $prompt) = @_;
45035ce5952SSteven Rostedt
45135ce5952SSteven Rostedt    my $ans;
45235ce5952SSteven Rostedt
45335ce5952SSteven Rostedt    for (;;) {
454dad98754SSteven Rostedt	if ($cancel) {
455dad98754SSteven Rostedt	    print "$prompt [y/n/C] ";
456dad98754SSteven Rostedt	} else {
45735ce5952SSteven Rostedt	    print "$prompt [Y/n] ";
458dad98754SSteven Rostedt	}
45935ce5952SSteven Rostedt	$ans = <STDIN>;
46035ce5952SSteven Rostedt	chomp $ans;
46135ce5952SSteven Rostedt	if ($ans =~ /^\s*$/) {
462dad98754SSteven Rostedt	    if ($cancel) {
463dad98754SSteven Rostedt		$ans = "c";
464dad98754SSteven Rostedt	    } else {
46535ce5952SSteven Rostedt		$ans = "y";
46635ce5952SSteven Rostedt	    }
467dad98754SSteven Rostedt	}
46835ce5952SSteven Rostedt	last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
469dad98754SSteven Rostedt	if ($cancel) {
470dad98754SSteven Rostedt	    last if ($ans =~ /^c$/i);
471dad98754SSteven Rostedt	    print "Please answer either 'y', 'n' or 'c'.\n";
472dad98754SSteven Rostedt	} else {
47335ce5952SSteven Rostedt	    print "Please answer either 'y' or 'n'.\n";
47435ce5952SSteven Rostedt	}
475dad98754SSteven Rostedt    }
476dad98754SSteven Rostedt    if ($ans =~ /^c/i) {
477dad98754SSteven Rostedt	exit;
478dad98754SSteven Rostedt    }
47935ce5952SSteven Rostedt    if ($ans !~ /^y$/i) {
48035ce5952SSteven Rostedt	return 0;
48135ce5952SSteven Rostedt    }
48235ce5952SSteven Rostedt    return 1;
48335ce5952SSteven Rostedt}
4848d1491baSSteven Rostedt
485dad98754SSteven Rostedtsub read_yn {
486dad98754SSteven Rostedt    my ($prompt) = @_;
487dad98754SSteven Rostedt
488dad98754SSteven Rostedt    return read_prompt 0, $prompt;
489dad98754SSteven Rostedt}
490dad98754SSteven Rostedt
491dad98754SSteven Rostedtsub read_ync {
492dad98754SSteven Rostedt    my ($prompt) = @_;
493dad98754SSteven Rostedt
494dad98754SSteven Rostedt    return read_prompt 1, $prompt;
495dad98754SSteven Rostedt}
496dad98754SSteven Rostedt
4978d1491baSSteven Rostedtsub get_ktest_config {
4988d1491baSSteven Rostedt    my ($config) = @_;
499815e2bd7SSteven Rostedt    my $ans;
5008d1491baSSteven Rostedt
5018d1491baSSteven Rostedt    return if (defined($opt{$config}));
5028d1491baSSteven Rostedt
5038d1491baSSteven Rostedt    if (defined($config_help{$config})) {
5048d1491baSSteven Rostedt	print "\n";
5058d1491baSSteven Rostedt	print $config_help{$config};
5068d1491baSSteven Rostedt    }
5078d1491baSSteven Rostedt
5088d1491baSSteven Rostedt    for (;;) {
5098d1491baSSteven Rostedt	print "$config = ";
510dbd3783bSSteven Rostedt	if (defined($default{$config}) && length($default{$config})) {
5118d1491baSSteven Rostedt	    print "\[$default{$config}\] ";
5128d1491baSSteven Rostedt	}
513815e2bd7SSteven Rostedt	$ans = <STDIN>;
514815e2bd7SSteven Rostedt	$ans =~ s/^\s*(.*\S)\s*$/$1/;
515815e2bd7SSteven Rostedt	if ($ans =~ /^\s*$/) {
5168d1491baSSteven Rostedt	    if ($default{$config}) {
517815e2bd7SSteven Rostedt		$ans = $default{$config};
5188d1491baSSteven Rostedt	    } else {
5198d1491baSSteven Rostedt		print "Your answer can not be blank\n";
5208d1491baSSteven Rostedt		next;
5218d1491baSSteven Rostedt	    }
5228d1491baSSteven Rostedt	}
5230e7a22deSSteven Rostedt	$entered_configs{$config} = ${ans};
5248d1491baSSteven Rostedt	last;
5258d1491baSSteven Rostedt    }
5268d1491baSSteven Rostedt}
5278d1491baSSteven Rostedt
5288d1491baSSteven Rostedtsub get_ktest_configs {
5298d1491baSSteven Rostedt    get_ktest_config("MACHINE");
5308d1491baSSteven Rostedt    get_ktest_config("BUILD_DIR");
5318d1491baSSteven Rostedt    get_ktest_config("OUTPUT_DIR");
532bb8474b1SSteven Rostedt
533dbd3783bSSteven Rostedt    if ($newconfig) {
534dbd3783bSSteven Rostedt	get_ktest_config("BUILD_OPTIONS");
535dbd3783bSSteven Rostedt    }
536dbd3783bSSteven Rostedt
537bb8474b1SSteven Rostedt    # options required for other than just building a kernel
538bb8474b1SSteven Rostedt    if (!$buildonly) {
539165708b2SSteven Rostedt	get_ktest_config("POWER_CYCLE");
540165708b2SSteven Rostedt	get_ktest_config("CONSOLE");
541165708b2SSteven Rostedt    }
542165708b2SSteven Rostedt
543165708b2SSteven Rostedt    # options required for install and more
544165708b2SSteven Rostedt    if ($buildonly != 1) {
545bb8474b1SSteven Rostedt	get_ktest_config("SSH_USER");
5468d1491baSSteven Rostedt	get_ktest_config("BUILD_TARGET");
5478d1491baSSteven Rostedt	get_ktest_config("TARGET_IMAGE");
548bb8474b1SSteven Rostedt    }
549bb8474b1SSteven Rostedt
5508d1491baSSteven Rostedt    get_ktest_config("LOCALVERSION");
5518d1491baSSteven Rostedt
552bb8474b1SSteven Rostedt    return if ($buildonly);
553bb8474b1SSteven Rostedt
5548d1491baSSteven Rostedt    my $rtype = $opt{"REBOOT_TYPE"};
5558d1491baSSteven Rostedt
5568d1491baSSteven Rostedt    if (!defined($rtype)) {
5578d1491baSSteven Rostedt	if (!defined($opt{"GRUB_MENU"})) {
5588d1491baSSteven Rostedt	    get_ktest_config("REBOOT_TYPE");
5598d1491baSSteven Rostedt	    $rtype = $entered_configs{"REBOOT_TYPE"};
5608d1491baSSteven Rostedt	} else {
5618d1491baSSteven Rostedt	    $rtype = "grub";
5628d1491baSSteven Rostedt	}
5638d1491baSSteven Rostedt    }
5648d1491baSSteven Rostedt
5658d1491baSSteven Rostedt    if ($rtype eq "grub") {
5668d1491baSSteven Rostedt	get_ktest_config("GRUB_MENU");
5678d1491baSSteven Rostedt    }
568a15ba913SSteven Rostedt
569a15ba913SSteven Rostedt    if ($rtype eq "grub2") {
570a15ba913SSteven Rostedt	get_ktest_config("GRUB_MENU");
571a15ba913SSteven Rostedt	get_ktest_config("GRUB_FILE");
572a15ba913SSteven Rostedt    }
5737786954cSSteven Rostedt
5747786954cSSteven Rostedt    if ($rtype eq "syslinux") {
5757786954cSSteven Rostedt	get_ktest_config("SYSLINUX_LABEL");
5767786954cSSteven Rostedt    }
5778d1491baSSteven Rostedt}
5788d1491baSSteven Rostedt
57977d942ceSSteven Rostedtsub process_variables {
5808d735212SSteven Rostedt    my ($value, $remove_undef) = @_;
58177d942ceSSteven Rostedt    my $retval = "";
58277d942ceSSteven Rostedt
58377d942ceSSteven Rostedt    # We want to check for '\', and it is just easier
58477d942ceSSteven Rostedt    # to check the previous characet of '$' and not need
58577d942ceSSteven Rostedt    # to worry if '$' is the first character. By adding
58677d942ceSSteven Rostedt    # a space to $value, we can just check [^\\]\$ and
58777d942ceSSteven Rostedt    # it will still work.
58877d942ceSSteven Rostedt    $value = " $value";
58977d942ceSSteven Rostedt
59077d942ceSSteven Rostedt    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
59177d942ceSSteven Rostedt	my $begin = $1;
59277d942ceSSteven Rostedt	my $var = $2;
59377d942ceSSteven Rostedt	my $end = $3;
59477d942ceSSteven Rostedt	# append beginning of value to retval
59577d942ceSSteven Rostedt	$retval = "$retval$begin";
59677d942ceSSteven Rostedt	if (defined($variable{$var})) {
59777d942ceSSteven Rostedt	    $retval = "$retval$variable{$var}";
5988d735212SSteven Rostedt	} elsif (defined($remove_undef) && $remove_undef) {
5998d735212SSteven Rostedt	    # for if statements, any variable that is not defined,
6008d735212SSteven Rostedt	    # we simple convert to 0
6018d735212SSteven Rostedt	    $retval = "${retval}0";
60277d942ceSSteven Rostedt	} else {
60377d942ceSSteven Rostedt	    # put back the origin piece.
60477d942ceSSteven Rostedt	    $retval = "$retval\$\{$var\}";
6059cc9e091SSteven Rostedt	    # This could be an option that is used later, save
6069cc9e091SSteven Rostedt	    # it so we don't warn if this option is not one of
6079cc9e091SSteven Rostedt	    # ktests options.
6089cc9e091SSteven Rostedt	    $used_options{$var} = 1;
60977d942ceSSteven Rostedt	}
61077d942ceSSteven Rostedt	$value = $end;
61177d942ceSSteven Rostedt    }
61277d942ceSSteven Rostedt    $retval = "$retval$value";
61377d942ceSSteven Rostedt
61477d942ceSSteven Rostedt    # remove the space added in the beginning
61577d942ceSSteven Rostedt    $retval =~ s/ //;
61677d942ceSSteven Rostedt
61777d942ceSSteven Rostedt    return "$retval"
61877d942ceSSteven Rostedt}
61977d942ceSSteven Rostedt
620a57419b3SSteven Rostedtsub set_value {
6213d1cc414SSteven Rostedt    my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
6222545eb61SSteven Rostedt
623cad96669SSteven Rostedt    my $prvalue = process_variables($rvalue);
624cad96669SSteven Rostedt
625cad96669SSteven Rostedt    if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") {
626bb8474b1SSteven Rostedt	# Note if a test is something other than build, then we
627bb8474b1SSteven Rostedt	# will need other manditory options.
628cad96669SSteven Rostedt	if ($prvalue ne "install") {
629319ab14fSSteven Rostedt (Red Hat)	    # for bisect, we need to check BISECT_TYPE
630319ab14fSSteven Rostedt (Red Hat)	    if ($prvalue ne "bisect") {
631319ab14fSSteven Rostedt (Red Hat)		$buildonly = 0;
632319ab14fSSteven Rostedt (Red Hat)	    }
633319ab14fSSteven Rostedt (Red Hat)	} else {
634319ab14fSSteven Rostedt (Red Hat)	    # install still limits some manditory options.
635319ab14fSSteven Rostedt (Red Hat)	    $buildonly = 2;
636319ab14fSSteven Rostedt (Red Hat)	}
637319ab14fSSteven Rostedt (Red Hat)    }
638319ab14fSSteven Rostedt (Red Hat)
639319ab14fSSteven Rostedt (Red Hat)    if ($buildonly && $lvalue =~ /^BISECT_TYPE(\[.*\])?$/ && $prvalue ne "build") {
640319ab14fSSteven Rostedt (Red Hat)	if ($prvalue ne "install") {
641bb8474b1SSteven Rostedt	    $buildonly = 0;
642165708b2SSteven Rostedt	} else {
643165708b2SSteven Rostedt	    # install still limits some manditory options.
644165708b2SSteven Rostedt	    $buildonly = 2;
645165708b2SSteven Rostedt	}
646bb8474b1SSteven Rostedt    }
647bb8474b1SSteven Rostedt
648a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
6493d1cc414SSteven Rostedt	if (!$override || defined(${$overrides}{$lvalue})) {
6503d1cc414SSteven Rostedt	    my $extra = "";
6513d1cc414SSteven Rostedt	    if ($override) {
6523d1cc414SSteven Rostedt		$extra = "In the same override section!\n";
6533d1cc414SSteven Rostedt	    }
6543d1cc414SSteven Rostedt	    die "$name: $.: Option $lvalue defined more than once!\n$extra";
6553d1cc414SSteven Rostedt	}
656cad96669SSteven Rostedt	${$overrides}{$lvalue} = $prvalue;
657a75fececSSteven Rostedt    }
65821a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
65921a9679fSSteven Rostedt	delete $opt{$lvalue};
66021a9679fSSteven Rostedt    } else {
661cad96669SSteven Rostedt	$opt{$lvalue} = $prvalue;
66221a9679fSSteven Rostedt    }
6632545eb61SSteven Rostedt}
664a57419b3SSteven Rostedt
66577d942ceSSteven Rostedtsub set_variable {
66677d942ceSSteven Rostedt    my ($lvalue, $rvalue) = @_;
66777d942ceSSteven Rostedt
66877d942ceSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
66977d942ceSSteven Rostedt	delete $variable{$lvalue};
67077d942ceSSteven Rostedt    } else {
67177d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
67277d942ceSSteven Rostedt	$variable{$lvalue} = $rvalue;
67377d942ceSSteven Rostedt    }
67477d942ceSSteven Rostedt}
67577d942ceSSteven Rostedt
676ab7a3f52SSteven Rostedtsub process_compare {
677ab7a3f52SSteven Rostedt    my ($lval, $cmp, $rval) = @_;
678ab7a3f52SSteven Rostedt
679ab7a3f52SSteven Rostedt    # remove whitespace
680ab7a3f52SSteven Rostedt
681ab7a3f52SSteven Rostedt    $lval =~ s/^\s*//;
682ab7a3f52SSteven Rostedt    $lval =~ s/\s*$//;
683ab7a3f52SSteven Rostedt
684ab7a3f52SSteven Rostedt    $rval =~ s/^\s*//;
685ab7a3f52SSteven Rostedt    $rval =~ s/\s*$//;
686ab7a3f52SSteven Rostedt
687ab7a3f52SSteven Rostedt    if ($cmp eq "==") {
688ab7a3f52SSteven Rostedt	return $lval eq $rval;
689ab7a3f52SSteven Rostedt    } elsif ($cmp eq "!=") {
690ab7a3f52SSteven Rostedt	return $lval ne $rval;
6918fddbe9bSSteven Rostedt    } elsif ($cmp eq "=~") {
6928fddbe9bSSteven Rostedt	return $lval =~ m/$rval/;
6938fddbe9bSSteven Rostedt    } elsif ($cmp eq "!~") {
6948fddbe9bSSteven Rostedt	return $lval !~ m/$rval/;
695ab7a3f52SSteven Rostedt    }
696ab7a3f52SSteven Rostedt
697ab7a3f52SSteven Rostedt    my $statement = "$lval $cmp $rval";
698ab7a3f52SSteven Rostedt    my $ret = eval $statement;
699ab7a3f52SSteven Rostedt
700ab7a3f52SSteven Rostedt    # $@ stores error of eval
701ab7a3f52SSteven Rostedt    if ($@) {
702ab7a3f52SSteven Rostedt	return -1;
703ab7a3f52SSteven Rostedt    }
704ab7a3f52SSteven Rostedt
705ab7a3f52SSteven Rostedt    return $ret;
706ab7a3f52SSteven Rostedt}
707ab7a3f52SSteven Rostedt
7089900b5dcSSteven Rostedtsub value_defined {
7099900b5dcSSteven Rostedt    my ($val) = @_;
7109900b5dcSSteven Rostedt
7119900b5dcSSteven Rostedt    return defined($variable{$2}) ||
7129900b5dcSSteven Rostedt	defined($opt{$2});
7139900b5dcSSteven Rostedt}
7149900b5dcSSteven Rostedt
7158d735212SSteven Rostedtmy $d = 0;
7168d735212SSteven Rostedtsub process_expression {
7178d735212SSteven Rostedt    my ($name, $val) = @_;
71845d73a5dSSteven Rostedt
7198d735212SSteven Rostedt    my $c = $d++;
7208d735212SSteven Rostedt
7218d735212SSteven Rostedt    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
7228d735212SSteven Rostedt	my $express = $1;
7238d735212SSteven Rostedt
7248d735212SSteven Rostedt	if (process_expression($name, $express)) {
7258d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
7268d735212SSteven Rostedt	} else {
7278d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
7288d735212SSteven Rostedt	}
7298d735212SSteven Rostedt    }
7308d735212SSteven Rostedt
7318d735212SSteven Rostedt    $d--;
7328d735212SSteven Rostedt    my $OR = "\\|\\|";
7338d735212SSteven Rostedt    my $AND = "\\&\\&";
7348d735212SSteven Rostedt
7358d735212SSteven Rostedt    while ($val =~ s/^(.*?)($OR|$AND)//) {
7368d735212SSteven Rostedt	my $express = $1;
7378d735212SSteven Rostedt	my $op = $2;
7388d735212SSteven Rostedt
7398d735212SSteven Rostedt	if (process_expression($name, $express)) {
7408d735212SSteven Rostedt	    if ($op eq "||") {
7418d735212SSteven Rostedt		return 1;
7428d735212SSteven Rostedt	    }
7438d735212SSteven Rostedt	} else {
7448d735212SSteven Rostedt	    if ($op eq "&&") {
7458d735212SSteven Rostedt		return 0;
7468d735212SSteven Rostedt	    }
7478d735212SSteven Rostedt	}
7488d735212SSteven Rostedt    }
74945d73a5dSSteven Rostedt
7508fddbe9bSSteven Rostedt    if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) {
751ab7a3f52SSteven Rostedt	my $ret = process_compare($1, $2, $3);
752ab7a3f52SSteven Rostedt	if ($ret < 0) {
753ab7a3f52SSteven Rostedt	    die "$name: $.: Unable to process comparison\n";
754ab7a3f52SSteven Rostedt	}
755ab7a3f52SSteven Rostedt	return $ret;
756ab7a3f52SSteven Rostedt    }
757ab7a3f52SSteven Rostedt
7589900b5dcSSteven Rostedt    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
7599900b5dcSSteven Rostedt	if (defined $1) {
7609900b5dcSSteven Rostedt	    return !value_defined($2);
7619900b5dcSSteven Rostedt	} else {
7629900b5dcSSteven Rostedt	    return value_defined($2);
7639900b5dcSSteven Rostedt	}
7649900b5dcSSteven Rostedt    }
7659900b5dcSSteven Rostedt
76645d73a5dSSteven Rostedt    if ($val =~ /^\s*0\s*$/) {
76745d73a5dSSteven Rostedt	return 0;
76845d73a5dSSteven Rostedt    } elsif ($val =~ /^\s*\d+\s*$/) {
76945d73a5dSSteven Rostedt	return 1;
77045d73a5dSSteven Rostedt    }
77145d73a5dSSteven Rostedt
7729900b5dcSSteven Rostedt    die ("$name: $.: Undefined content $val in if statement\n");
7738d735212SSteven Rostedt}
7748d735212SSteven Rostedt
7758d735212SSteven Rostedtsub process_if {
7768d735212SSteven Rostedt    my ($name, $value) = @_;
7778d735212SSteven Rostedt
7788d735212SSteven Rostedt    # Convert variables and replace undefined ones with 0
7798d735212SSteven Rostedt    my $val = process_variables($value, 1);
7808d735212SSteven Rostedt    my $ret = process_expression $name, $val;
7818d735212SSteven Rostedt
7828d735212SSteven Rostedt    return $ret;
78345d73a5dSSteven Rostedt}
78445d73a5dSSteven Rostedt
7852ed3b161SSteven Rostedtsub __read_config {
7862ed3b161SSteven Rostedt    my ($config, $current_test_num) = @_;
787a57419b3SSteven Rostedt
7882ed3b161SSteven Rostedt    my $in;
7892ed3b161SSteven Rostedt    open($in, $config) || die "can't read file $config";
790a57419b3SSteven Rostedt
791a57419b3SSteven Rostedt    my $name = $config;
792a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
793a57419b3SSteven Rostedt
7942ed3b161SSteven Rostedt    my $test_num = $$current_test_num;
795a57419b3SSteven Rostedt    my $default = 1;
796a57419b3SSteven Rostedt    my $repeat = 1;
797a57419b3SSteven Rostedt    my $num_tests_set = 0;
798a57419b3SSteven Rostedt    my $skip = 0;
799a57419b3SSteven Rostedt    my $rest;
800a9f84424SSteven Rostedt    my $line;
8010df213caSSteven Rostedt    my $test_case = 0;
80245d73a5dSSteven Rostedt    my $if = 0;
80345d73a5dSSteven Rostedt    my $if_set = 0;
8043d1cc414SSteven Rostedt    my $override = 0;
8053d1cc414SSteven Rostedt
8063d1cc414SSteven Rostedt    my %overrides;
807a57419b3SSteven Rostedt
8082ed3b161SSteven Rostedt    while (<$in>) {
809a57419b3SSteven Rostedt
810a57419b3SSteven Rostedt	# ignore blank lines and comments
811a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
812a57419b3SSteven Rostedt
8130050b6bbSSteven Rostedt	if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
814a57419b3SSteven Rostedt
8150050b6bbSSteven Rostedt	    my $type = $1;
8160050b6bbSSteven Rostedt	    $rest = $2;
817a9f84424SSteven Rostedt	    $line = $2;
8180050b6bbSSteven Rostedt
8190050b6bbSSteven Rostedt	    my $old_test_num;
8200050b6bbSSteven Rostedt	    my $old_repeat;
8213d1cc414SSteven Rostedt	    $override = 0;
8220050b6bbSSteven Rostedt
8230050b6bbSSteven Rostedt	    if ($type eq "TEST_START") {
824a57419b3SSteven Rostedt
825a57419b3SSteven Rostedt		if ($num_tests_set) {
826a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
827a57419b3SSteven Rostedt		}
828a57419b3SSteven Rostedt
8290050b6bbSSteven Rostedt		$old_test_num = $test_num;
8300050b6bbSSteven Rostedt		$old_repeat = $repeat;
831a57419b3SSteven Rostedt
832a57419b3SSteven Rostedt		$test_num += $repeat;
833a57419b3SSteven Rostedt		$default = 0;
834a57419b3SSteven Rostedt		$repeat = 1;
8350050b6bbSSteven Rostedt	    } else {
8360050b6bbSSteven Rostedt		$default = 1;
8370050b6bbSSteven Rostedt	    }
838a57419b3SSteven Rostedt
839a9f84424SSteven Rostedt	    # If SKIP is anywhere in the line, the command will be skipped
840a9f84424SSteven Rostedt	    if ($rest =~ s/\s+SKIP\b//) {
841a57419b3SSteven Rostedt		$skip = 1;
842a57419b3SSteven Rostedt	    } else {
8430df213caSSteven Rostedt		$test_case = 1;
844a57419b3SSteven Rostedt		$skip = 0;
845a57419b3SSteven Rostedt	    }
846a57419b3SSteven Rostedt
847a9f84424SSteven Rostedt	    if ($rest =~ s/\sELSE\b//) {
848a9f84424SSteven Rostedt		if (!$if) {
849a9f84424SSteven Rostedt		    die "$name: $.: ELSE found with out matching IF section\n$_";
850a57419b3SSteven Rostedt		}
851a9f84424SSteven Rostedt		$if = 0;
852a9f84424SSteven Rostedt
853a9f84424SSteven Rostedt		if ($if_set) {
854a9f84424SSteven Rostedt		    $skip = 1;
855a9f84424SSteven Rostedt		} else {
856a9f84424SSteven Rostedt		    $skip = 0;
8573d1cc414SSteven Rostedt		}
8583d1cc414SSteven Rostedt	    }
859a57419b3SSteven Rostedt
860a9f84424SSteven Rostedt	    if ($rest =~ s/\sIF\s+(.*)//) {
86145d73a5dSSteven Rostedt		if (process_if($name, $1)) {
86245d73a5dSSteven Rostedt		    $if_set = 1;
86345d73a5dSSteven Rostedt		} else {
864a57419b3SSteven Rostedt		    $skip = 1;
865a57419b3SSteven Rostedt		}
86645d73a5dSSteven Rostedt		$if = 1;
86745d73a5dSSteven Rostedt	    } else {
86845d73a5dSSteven Rostedt		$if = 0;
869a9f84424SSteven Rostedt		$if_set = 0;
87045d73a5dSSteven Rostedt	    }
871a57419b3SSteven Rostedt
872a9f84424SSteven Rostedt	    if (!$skip) {
873a9f84424SSteven Rostedt		if ($type eq "TEST_START") {
874a9f84424SSteven Rostedt		    if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
875a9f84424SSteven Rostedt			$repeat = $1;
876a9f84424SSteven Rostedt			$repeat_tests{"$test_num"} = $repeat;
877a9f84424SSteven Rostedt		    }
878a9f84424SSteven Rostedt		} elsif ($rest =~ s/\sOVERRIDE\b//) {
879a9f84424SSteven Rostedt		    # DEFAULT only
880a9f84424SSteven Rostedt		    $override = 1;
881a9f84424SSteven Rostedt		    # Clear previous overrides
882a9f84424SSteven Rostedt		    %overrides = ();
883a9f84424SSteven Rostedt		}
884a9f84424SSteven Rostedt	    }
885a9f84424SSteven Rostedt
886a9f84424SSteven Rostedt	    if (!$skip && $rest !~ /^\s*$/) {
8870050b6bbSSteven Rostedt		die "$name: $.: Gargbage found after $type\n$_";
888a57419b3SSteven Rostedt	    }
889a57419b3SSteven Rostedt
8900050b6bbSSteven Rostedt	    if ($skip && $type eq "TEST_START") {
891a57419b3SSteven Rostedt		$test_num = $old_test_num;
892e48c5293SSteven Rostedt		$repeat = $old_repeat;
893a57419b3SSteven Rostedt	    }
894a57419b3SSteven Rostedt
895ab7a3f52SSteven Rostedt	} elsif (/^\s*ELSE\b(.*)$/) {
89645d73a5dSSteven Rostedt	    if (!$if) {
89745d73a5dSSteven Rostedt		die "$name: $.: ELSE found with out matching IF section\n$_";
89845d73a5dSSteven Rostedt	    }
89945d73a5dSSteven Rostedt	    $rest = $1;
90045d73a5dSSteven Rostedt	    if ($if_set) {
90145d73a5dSSteven Rostedt		$skip = 1;
902ab7a3f52SSteven Rostedt		$rest = "";
90345d73a5dSSteven Rostedt	    } else {
90445d73a5dSSteven Rostedt		$skip = 0;
90545d73a5dSSteven Rostedt
906ab7a3f52SSteven Rostedt		if ($rest =~ /\sIF\s+(.*)/) {
90745d73a5dSSteven Rostedt		    # May be a ELSE IF section.
90895f57838SSteven Rostedt		    if (process_if($name, $1)) {
90995f57838SSteven Rostedt			$if_set = 1;
91095f57838SSteven Rostedt		    } else {
91145d73a5dSSteven Rostedt			$skip = 1;
91245d73a5dSSteven Rostedt		    }
913ab7a3f52SSteven Rostedt		    $rest = "";
91445d73a5dSSteven Rostedt		} else {
91545d73a5dSSteven Rostedt		    $if = 0;
91645d73a5dSSteven Rostedt		}
91745d73a5dSSteven Rostedt	    }
91845d73a5dSSteven Rostedt
919ab7a3f52SSteven Rostedt	    if ($rest !~ /^\s*$/) {
920ab7a3f52SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
921ab7a3f52SSteven Rostedt	    }
922ab7a3f52SSteven Rostedt
9232ed3b161SSteven Rostedt	} elsif (/^\s*INCLUDE\s+(\S+)/) {
9242ed3b161SSteven Rostedt
9252ed3b161SSteven Rostedt	    next if ($skip);
9262ed3b161SSteven Rostedt
9272ed3b161SSteven Rostedt	    if (!$default) {
9282ed3b161SSteven Rostedt		die "$name: $.: INCLUDE can only be done in default sections\n$_";
9292ed3b161SSteven Rostedt	    }
9302ed3b161SSteven Rostedt
9312ed3b161SSteven Rostedt	    my $file = process_variables($1);
9322ed3b161SSteven Rostedt
9332ed3b161SSteven Rostedt	    if ($file !~ m,^/,) {
9342ed3b161SSteven Rostedt		# check the path of the config file first
9352ed3b161SSteven Rostedt		if ($config =~ m,(.*)/,) {
9362ed3b161SSteven Rostedt		    if (-f "$1/$file") {
9372ed3b161SSteven Rostedt			$file = "$1/$file";
9382ed3b161SSteven Rostedt		    }
9392ed3b161SSteven Rostedt		}
9402ed3b161SSteven Rostedt	    }
9412ed3b161SSteven Rostedt
9422ed3b161SSteven Rostedt	    if ( ! -r $file ) {
9432ed3b161SSteven Rostedt		die "$name: $.: Can't read file $file\n$_";
9442ed3b161SSteven Rostedt	    }
9452ed3b161SSteven Rostedt
9462ed3b161SSteven Rostedt	    if (__read_config($file, \$test_num)) {
9472ed3b161SSteven Rostedt		$test_case = 1;
9482ed3b161SSteven Rostedt	    }
9492ed3b161SSteven Rostedt
950a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
951a57419b3SSteven Rostedt
952a57419b3SSteven Rostedt	    next if ($skip);
953a57419b3SSteven Rostedt
954a57419b3SSteven Rostedt	    my $lvalue = $1;
955a57419b3SSteven Rostedt	    my $rvalue = $2;
956a57419b3SSteven Rostedt
957a57419b3SSteven Rostedt	    if (!$default &&
958a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
959a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
960a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
961a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
962a57419b3SSteven Rostedt	    }
963a57419b3SSteven Rostedt
964a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
965a57419b3SSteven Rostedt		if ($test_num) {
966a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
967a57419b3SSteven Rostedt		}
968a57419b3SSteven Rostedt		if (!$default) {
969a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
970a57419b3SSteven Rostedt		}
971a57419b3SSteven Rostedt		$num_tests_set = 1;
972a57419b3SSteven Rostedt	    }
973a57419b3SSteven Rostedt
974a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
9753d1cc414SSteven Rostedt		set_value($lvalue, $rvalue, $override, \%overrides, $name);
976a57419b3SSteven Rostedt	    } else {
977a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
9783d1cc414SSteven Rostedt		set_value($val, $rvalue, $override, \%overrides, $name);
979a57419b3SSteven Rostedt
980a57419b3SSteven Rostedt		if ($repeat > 1) {
981a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
982a57419b3SSteven Rostedt		}
983a57419b3SSteven Rostedt	    }
98477d942ceSSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
98577d942ceSSteven Rostedt	    next if ($skip);
98677d942ceSSteven Rostedt
98777d942ceSSteven Rostedt	    my $lvalue = $1;
98877d942ceSSteven Rostedt	    my $rvalue = $2;
98977d942ceSSteven Rostedt
99077d942ceSSteven Rostedt	    # process config variables.
99177d942ceSSteven Rostedt	    # Config variables are only active while reading the
99277d942ceSSteven Rostedt	    # config and can be defined anywhere. They also ignore
99377d942ceSSteven Rostedt	    # TEST_START and DEFAULTS, but are skipped if they are in
99477d942ceSSteven Rostedt	    # on of these sections that have SKIP defined.
99577d942ceSSteven Rostedt	    # The save variable can be
99677d942ceSSteven Rostedt	    # defined multiple times and the new one simply overrides
99777d942ceSSteven Rostedt	    # the prevous one.
99877d942ceSSteven Rostedt	    set_variable($lvalue, $rvalue);
99977d942ceSSteven Rostedt
1000a57419b3SSteven Rostedt	} else {
1001a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
1002a57419b3SSteven Rostedt	}
10032545eb61SSteven Rostedt    }
10042545eb61SSteven Rostedt
1005a57419b3SSteven Rostedt    if ($test_num) {
1006a57419b3SSteven Rostedt	$test_num += $repeat - 1;
1007a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
1008a57419b3SSteven Rostedt    }
1009a57419b3SSteven Rostedt
10102ed3b161SSteven Rostedt    close($in);
10112ed3b161SSteven Rostedt
10122ed3b161SSteven Rostedt    $$current_test_num = $test_num;
10132ed3b161SSteven Rostedt
10142ed3b161SSteven Rostedt    return $test_case;
10152ed3b161SSteven Rostedt}
10162ed3b161SSteven Rostedt
1017c4261d0fSSteven Rostedtsub get_test_case {
1018c4261d0fSSteven Rostedt	print "What test case would you like to run?\n";
1019c4261d0fSSteven Rostedt	print " (build, install or boot)\n";
1020c4261d0fSSteven Rostedt	print " Other tests are available but require editing the config file\n";
1021c4261d0fSSteven Rostedt	my $ans = <STDIN>;
1022c4261d0fSSteven Rostedt	chomp $ans;
1023c4261d0fSSteven Rostedt	$default{"TEST_TYPE"} = $ans;
1024c4261d0fSSteven Rostedt}
1025c4261d0fSSteven Rostedt
10262ed3b161SSteven Rostedtsub read_config {
10272ed3b161SSteven Rostedt    my ($config) = @_;
10282ed3b161SSteven Rostedt
10292ed3b161SSteven Rostedt    my $test_case;
10302ed3b161SSteven Rostedt    my $test_num = 0;
10312ed3b161SSteven Rostedt
10322ed3b161SSteven Rostedt    $test_case = __read_config $config, \$test_num;
10332ed3b161SSteven Rostedt
10348d1491baSSteven Rostedt    # make sure we have all mandatory configs
10358d1491baSSteven Rostedt    get_ktest_configs;
10368d1491baSSteven Rostedt
10370df213caSSteven Rostedt    # was a test specified?
10380df213caSSteven Rostedt    if (!$test_case) {
10390df213caSSteven Rostedt	print "No test case specified.\n";
1040c4261d0fSSteven Rostedt	get_test_case;
10410df213caSSteven Rostedt    }
10420df213caSSteven Rostedt
1043a75fececSSteven Rostedt    # set any defaults
1044a75fececSSteven Rostedt
1045a75fececSSteven Rostedt    foreach my $default (keys %default) {
1046a75fececSSteven Rostedt	if (!defined($opt{$default})) {
1047a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
1048a75fececSSteven Rostedt	}
1049a75fececSSteven Rostedt    }
10509cc9e091SSteven Rostedt
10519cc9e091SSteven Rostedt    if ($opt{"IGNORE_UNUSED"} == 1) {
10529cc9e091SSteven Rostedt	return;
10539cc9e091SSteven Rostedt    }
10549cc9e091SSteven Rostedt
10559cc9e091SSteven Rostedt    my %not_used;
10569cc9e091SSteven Rostedt
10579cc9e091SSteven Rostedt    # check if there are any stragglers (typos?)
10589cc9e091SSteven Rostedt    foreach my $option (keys %opt) {
10599cc9e091SSteven Rostedt	my $op = $option;
10609cc9e091SSteven Rostedt	# remove per test labels.
10619cc9e091SSteven Rostedt	$op =~ s/\[.*\]//;
10629cc9e091SSteven Rostedt	if (!exists($option_map{$op}) &&
10639cc9e091SSteven Rostedt	    !exists($default{$op}) &&
10649cc9e091SSteven Rostedt	    !exists($used_options{$op})) {
10659cc9e091SSteven Rostedt	    $not_used{$op} = 1;
10669cc9e091SSteven Rostedt	}
10679cc9e091SSteven Rostedt    }
10689cc9e091SSteven Rostedt
10699cc9e091SSteven Rostedt    if (%not_used) {
10709cc9e091SSteven Rostedt	my $s = "s are";
10719cc9e091SSteven Rostedt	$s = " is" if (keys %not_used == 1);
10729cc9e091SSteven Rostedt	print "The following option$s not used; could be a typo:\n";
10739cc9e091SSteven Rostedt	foreach my $option (keys %not_used) {
10749cc9e091SSteven Rostedt	    print "$option\n";
10759cc9e091SSteven Rostedt	}
10769cc9e091SSteven Rostedt	print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n";
10779cc9e091SSteven Rostedt	if (!read_yn "Do you want to continue?") {
10789cc9e091SSteven Rostedt	    exit -1;
10799cc9e091SSteven Rostedt	}
10809cc9e091SSteven Rostedt    }
10812545eb61SSteven Rostedt}
10822545eb61SSteven Rostedt
108323715c3cSSteven Rostedtsub __eval_option {
108404262be3SSteven Rostedt (Red Hat)    my ($name, $option, $i) = @_;
108523715c3cSSteven Rostedt
108623715c3cSSteven Rostedt    # Add space to evaluate the character before $
108723715c3cSSteven Rostedt    $option = " $option";
108823715c3cSSteven Rostedt    my $retval = "";
1089f9dfb65bSRabin Vincent    my $repeated = 0;
1090f9dfb65bSRabin Vincent    my $parent = 0;
1091f9dfb65bSRabin Vincent
1092f9dfb65bSRabin Vincent    foreach my $test (keys %repeat_tests) {
1093f9dfb65bSRabin Vincent	if ($i >= $test &&
1094f9dfb65bSRabin Vincent	    $i < $test + $repeat_tests{$test}) {
1095f9dfb65bSRabin Vincent
1096f9dfb65bSRabin Vincent	    $repeated = 1;
1097f9dfb65bSRabin Vincent	    $parent = $test;
1098f9dfb65bSRabin Vincent	    last;
1099f9dfb65bSRabin Vincent	}
1100f9dfb65bSRabin Vincent    }
110123715c3cSSteven Rostedt
110223715c3cSSteven Rostedt    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
110323715c3cSSteven Rostedt	my $start = $1;
110423715c3cSSteven Rostedt	my $var = $2;
110523715c3cSSteven Rostedt	my $end = $3;
110623715c3cSSteven Rostedt
110723715c3cSSteven Rostedt	# Append beginning of line
110823715c3cSSteven Rostedt	$retval = "$retval$start";
110923715c3cSSteven Rostedt
111023715c3cSSteven Rostedt	# If the iteration option OPT[$i] exists, then use that.
111123715c3cSSteven Rostedt	# otherwise see if the default OPT (without [$i]) exists.
111223715c3cSSteven Rostedt
111323715c3cSSteven Rostedt	my $o = "$var\[$i\]";
1114f9dfb65bSRabin Vincent	my $parento = "$var\[$parent\]";
111523715c3cSSteven Rostedt
111604262be3SSteven Rostedt (Red Hat)	# If a variable contains itself, use the default var
111704262be3SSteven Rostedt (Red Hat)	if (($var eq $name) && defined($opt{$var})) {
111804262be3SSteven Rostedt (Red Hat)	    $o = $opt{$var};
111904262be3SSteven Rostedt (Red Hat)	    $retval = "$retval$o";
112004262be3SSteven Rostedt (Red Hat)	} elsif (defined($opt{$o})) {
112123715c3cSSteven Rostedt	    $o = $opt{$o};
112223715c3cSSteven Rostedt	    $retval = "$retval$o";
1123f9dfb65bSRabin Vincent	} elsif ($repeated && defined($opt{$parento})) {
1124f9dfb65bSRabin Vincent	    $o = $opt{$parento};
1125f9dfb65bSRabin Vincent	    $retval = "$retval$o";
112623715c3cSSteven Rostedt	} elsif (defined($opt{$var})) {
112723715c3cSSteven Rostedt	    $o = $opt{$var};
112823715c3cSSteven Rostedt	    $retval = "$retval$o";
112923715c3cSSteven Rostedt	} else {
113023715c3cSSteven Rostedt	    $retval = "$retval\$\{$var\}";
113123715c3cSSteven Rostedt	}
113223715c3cSSteven Rostedt
113323715c3cSSteven Rostedt	$option = $end;
113423715c3cSSteven Rostedt    }
113523715c3cSSteven Rostedt
113623715c3cSSteven Rostedt    $retval = "$retval$option";
113723715c3cSSteven Rostedt
113823715c3cSSteven Rostedt    $retval =~ s/^ //;
113923715c3cSSteven Rostedt
114023715c3cSSteven Rostedt    return $retval;
114123715c3cSSteven Rostedt}
114223715c3cSSteven Rostedt
114323715c3cSSteven Rostedtsub eval_option {
114404262be3SSteven Rostedt (Red Hat)    my ($name, $option, $i) = @_;
114523715c3cSSteven Rostedt
114623715c3cSSteven Rostedt    my $prev = "";
114723715c3cSSteven Rostedt
114823715c3cSSteven Rostedt    # Since an option can evaluate to another option,
114923715c3cSSteven Rostedt    # keep iterating until we do not evaluate any more
115023715c3cSSteven Rostedt    # options.
115123715c3cSSteven Rostedt    my $r = 0;
115223715c3cSSteven Rostedt    while ($prev ne $option) {
115323715c3cSSteven Rostedt	# Check for recursive evaluations.
115423715c3cSSteven Rostedt	# 100 deep should be more than enough.
115523715c3cSSteven Rostedt	if ($r++ > 100) {
115623715c3cSSteven Rostedt	    die "Over 100 evaluations accurred with $option\n" .
115723715c3cSSteven Rostedt		"Check for recursive variables\n";
115823715c3cSSteven Rostedt	}
115923715c3cSSteven Rostedt	$prev = $option;
116004262be3SSteven Rostedt (Red Hat)	$option = __eval_option($name, $option, $i);
116123715c3cSSteven Rostedt    }
116223715c3cSSteven Rostedt
116323715c3cSSteven Rostedt    return $option;
116423715c3cSSteven Rostedt}
116523715c3cSSteven Rostedt
1166d1e2f22aSSteven Rostedtsub _logit {
11672545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
11682545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
11692545eb61SSteven Rostedt	print OUT @_;
11702545eb61SSteven Rostedt	close(OUT);
11712545eb61SSteven Rostedt    }
11722545eb61SSteven Rostedt}
11732545eb61SSteven Rostedt
1174d1e2f22aSSteven Rostedtsub logit {
1175d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1176d1e2f22aSSteven Rostedt	_logit @_;
1177d1e2f22aSSteven Rostedt    } else {
1178d1e2f22aSSteven Rostedt	print @_;
1179d1e2f22aSSteven Rostedt    }
1180d1e2f22aSSteven Rostedt}
1181d1e2f22aSSteven Rostedt
11825f9b6cedSSteven Rostedtsub doprint {
11835f9b6cedSSteven Rostedt    print @_;
1184d1e2f22aSSteven Rostedt    _logit @_;
11855f9b6cedSSteven Rostedt}
11865f9b6cedSSteven Rostedt
11877faafbd6SSteven Rostedtsub run_command;
11882728be41SAndrew Jonessub start_monitor;
11892728be41SAndrew Jonessub end_monitor;
11902728be41SAndrew Jonessub wait_for_monitor;
11917faafbd6SSteven Rostedt
11927faafbd6SSteven Rostedtsub reboot {
11932728be41SAndrew Jones    my ($time) = @_;
11942728be41SAndrew Jones
1195a4968722SSteven Rostedt    # Make sure everything has been written to disk
1196a4968722SSteven Rostedt    run_ssh("sync");
1197a4968722SSteven Rostedt
11982b803365SSteven Rostedt    if (defined($time)) {
11992b803365SSteven Rostedt	start_monitor;
12002b803365SSteven Rostedt	# flush out current monitor
12012b803365SSteven Rostedt	# May contain the reboot success line
12022b803365SSteven Rostedt	wait_for_monitor 1;
12032b803365SSteven Rostedt    }
12042b803365SSteven Rostedt
12057faafbd6SSteven Rostedt    # try to reboot normally
1206e48c5293SSteven Rostedt    if (run_command $reboot) {
1207576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
1208576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
1209576f627cSSteven Rostedt	    run_command "$power_cycle";
1210576f627cSSteven Rostedt	}
1211576f627cSSteven Rostedt    } else {
12127faafbd6SSteven Rostedt	# nope? power cycle it.
1213a75fececSSteven Rostedt	run_command "$power_cycle";
12147faafbd6SSteven Rostedt    }
12152728be41SAndrew Jones
12162728be41SAndrew Jones    if (defined($time)) {
12174c0b67a2SSteven Rostedt (Red Hat)
12184c0b67a2SSteven Rostedt (Red Hat)	# We only want to get to the new kernel, don't fail
12194c0b67a2SSteven Rostedt (Red Hat)	# if we stumble over a call trace.
12204c0b67a2SSteven Rostedt (Red Hat)	my $save_ignore_errors = $ignore_errors;
12214c0b67a2SSteven Rostedt (Red Hat)	$ignore_errors = 1;
12224c0b67a2SSteven Rostedt (Red Hat)
1223d6845536SSteven Rostedt (Red Hat)	# Look for the good kernel to boot
1224d6845536SSteven Rostedt (Red Hat)	if (wait_for_monitor($time, "Linux version")) {
1225407b95b7SSteven Rostedt	    # reboot got stuck?
12268a80c727SSteven Rostedt	    doprint "Reboot did not finish. Forcing power cycle\n";
1227407b95b7SSteven Rostedt	    run_command "$power_cycle";
1228407b95b7SSteven Rostedt	}
1229d6845536SSteven Rostedt (Red Hat)
12304c0b67a2SSteven Rostedt (Red Hat)	$ignore_errors = $save_ignore_errors;
12314c0b67a2SSteven Rostedt (Red Hat)
1232d6845536SSteven Rostedt (Red Hat)	# Still need to wait for the reboot to finish
1233d6845536SSteven Rostedt (Red Hat)	wait_for_monitor($time, $reboot_success_line);
1234d6845536SSteven Rostedt (Red Hat)
12352728be41SAndrew Jones	end_monitor;
12362728be41SAndrew Jones    }
12377faafbd6SSteven Rostedt}
12387faafbd6SSteven Rostedt
1239bc7c5803SSteven Rostedtsub reboot_to_good {
1240bc7c5803SSteven Rostedt    my ($time) = @_;
1241bc7c5803SSteven Rostedt
1242bc7c5803SSteven Rostedt    if (defined($switch_to_good)) {
1243bc7c5803SSteven Rostedt	run_command $switch_to_good;
1244bc7c5803SSteven Rostedt    }
1245bc7c5803SSteven Rostedt
1246bc7c5803SSteven Rostedt    reboot $time;
1247bc7c5803SSteven Rostedt}
1248bc7c5803SSteven Rostedt
1249576f627cSSteven Rostedtsub do_not_reboot {
1250576f627cSSteven Rostedt    my $i = $iteration;
1251576f627cSSteven Rostedt
12524ab1cce5SSteven Rostedt    return $test_type eq "build" || $no_reboot ||
1253576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
1254576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
1255576f627cSSteven Rostedt}
1256576f627cSSteven Rostedt
12575c42fc5bSSteven Rostedtsub dodie {
12585a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
12595c42fc5bSSteven Rostedt
1260576f627cSSteven Rostedt    my $i = $iteration;
1261576f627cSSteven Rostedt
1262576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
1263576f627cSSteven Rostedt
126475c3fda7SSteven Rostedt	doprint "REBOOTING\n";
1265bc7c5803SSteven Rostedt	reboot_to_good;
126675c3fda7SSteven Rostedt
1267a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
12685c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
1269a75fececSSteven Rostedt	`$power_off`;
12705c42fc5bSSteven Rostedt    }
127175c3fda7SSteven Rostedt
1272f80802cbSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1273f80802cbSSteven Rostedt	print " See $opt{LOG_FILE} for more info.\n";
1274f80802cbSSteven Rostedt    }
1275f80802cbSSteven Rostedt
1276576f627cSSteven Rostedt    die @_, "\n";
12775c42fc5bSSteven Rostedt}
12785c42fc5bSSteven Rostedt
12797faafbd6SSteven Rostedtsub open_console {
12807faafbd6SSteven Rostedt    my ($fp) = @_;
12817faafbd6SSteven Rostedt
12827faafbd6SSteven Rostedt    my $flags;
12837faafbd6SSteven Rostedt
1284a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
1285a75fececSSteven Rostedt	dodie "Can't open console $console";
12867faafbd6SSteven Rostedt
12877faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
1288576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
12897faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
1290576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
12917faafbd6SSteven Rostedt
12927faafbd6SSteven Rostedt    return $pid;
12937faafbd6SSteven Rostedt}
12947faafbd6SSteven Rostedt
12957faafbd6SSteven Rostedtsub close_console {
12967faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
12977faafbd6SSteven Rostedt
12987faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
12997faafbd6SSteven Rostedt    kill 2, $pid;
13007faafbd6SSteven Rostedt
13017faafbd6SSteven Rostedt    print "closing!\n";
13027faafbd6SSteven Rostedt    close($fp);
13037faafbd6SSteven Rostedt}
13047faafbd6SSteven Rostedt
13057faafbd6SSteven Rostedtsub start_monitor {
13067faafbd6SSteven Rostedt    if ($monitor_cnt++) {
13077faafbd6SSteven Rostedt	return;
13087faafbd6SSteven Rostedt    }
13097faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
13107faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
1311a75fececSSteven Rostedt
1312a75fececSSteven Rostedt    return;
1313a75fececSSteven Rostedt
1314a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
13157faafbd6SSteven Rostedt}
13167faafbd6SSteven Rostedt
13177faafbd6SSteven Rostedtsub end_monitor {
1318319ab14fSSteven Rostedt (Red Hat)    return if (!defined $console);
13197faafbd6SSteven Rostedt    if (--$monitor_cnt) {
13207faafbd6SSteven Rostedt	return;
13217faafbd6SSteven Rostedt    }
13227faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
13237faafbd6SSteven Rostedt}
13247faafbd6SSteven Rostedt
13257faafbd6SSteven Rostedtsub wait_for_monitor {
13262b803365SSteven Rostedt    my ($time, $stop) = @_;
13272b803365SSteven Rostedt    my $full_line = "";
13287faafbd6SSteven Rostedt    my $line;
13292b803365SSteven Rostedt    my $booted = 0;
1330407b95b7SSteven Rostedt    my $start_time = time;
13318a80c727SSteven Rostedt    my $skip_call_trace = 0;
13328a80c727SSteven Rostedt    my $bug = 0;
13338a80c727SSteven Rostedt    my $bug_ignored = 0;
1334407b95b7SSteven Rostedt    my $now;
13357faafbd6SSteven Rostedt
1336a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
13377faafbd6SSteven Rostedt
13387faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
13392b803365SSteven Rostedt    while (!$booted) {
13407faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
13412b803365SSteven Rostedt	last if (!defined($line));
13422b803365SSteven Rostedt	print "$line";
13432b803365SSteven Rostedt	$full_line .= $line;
13442b803365SSteven Rostedt
13452b803365SSteven Rostedt	if (defined($stop) && $full_line =~ /$stop/) {
13462b803365SSteven Rostedt	    doprint "wait for monitor detected $stop\n";
13472b803365SSteven Rostedt	    $booted = 1;
13482b803365SSteven Rostedt	}
13492b803365SSteven Rostedt
13508a80c727SSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
13518a80c727SSteven Rostedt	    $skip_call_trace = 1;
13528a80c727SSteven Rostedt	}
13538a80c727SSteven Rostedt
13548a80c727SSteven Rostedt	if ($full_line =~ /call trace:/i) {
13558a80c727SSteven Rostedt	    if (!$bug && !$skip_call_trace) {
13568a80c727SSteven Rostedt		if ($ignore_errors) {
13578a80c727SSteven Rostedt		    $bug_ignored = 1;
13588a80c727SSteven Rostedt		} else {
13598a80c727SSteven Rostedt		    $bug = 1;
13608a80c727SSteven Rostedt		}
13618a80c727SSteven Rostedt	    }
13628a80c727SSteven Rostedt	}
13638a80c727SSteven Rostedt
13648a80c727SSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
13658a80c727SSteven Rostedt	    $skip_call_trace = 0;
13668a80c727SSteven Rostedt	}
13678a80c727SSteven Rostedt
13688a80c727SSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
13698a80c727SSteven Rostedt	    $bug = 1;
13708a80c727SSteven Rostedt	}
13718a80c727SSteven Rostedt
13722b803365SSteven Rostedt	if ($line =~ /\n/) {
13732b803365SSteven Rostedt	    $full_line = "";
13742b803365SSteven Rostedt	}
1375407b95b7SSteven Rostedt	$now = time;
1376407b95b7SSteven Rostedt	if ($now - $start_time >= $max_monitor_wait) {
1377407b95b7SSteven Rostedt	    doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n";
1378407b95b7SSteven Rostedt	    return 1;
1379407b95b7SSteven Rostedt	}
13802b803365SSteven Rostedt    }
1381a75fececSSteven Rostedt    print "** Monitor flushed **\n";
13828a80c727SSteven Rostedt    return $bug;
13837faafbd6SSteven Rostedt}
13847faafbd6SSteven Rostedt
1385de5b6e3bSRabin Vincentsub save_logs {
1386de5b6e3bSRabin Vincent	my ($result, $basedir) = @_;
1387de5b6e3bSRabin Vincent	my @t = localtime;
1388de5b6e3bSRabin Vincent	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1389de5b6e3bSRabin Vincent		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1390de5b6e3bSRabin Vincent
1391de5b6e3bSRabin Vincent	my $type = $build_type;
1392de5b6e3bSRabin Vincent	if ($type =~ /useconfig/) {
1393de5b6e3bSRabin Vincent	    $type = "useconfig";
1394de5b6e3bSRabin Vincent	}
1395de5b6e3bSRabin Vincent
1396de5b6e3bSRabin Vincent	my $dir = "$machine-$test_type-$type-$result-$date";
1397de5b6e3bSRabin Vincent
1398de5b6e3bSRabin Vincent	$dir = "$basedir/$dir";
1399de5b6e3bSRabin Vincent
1400de5b6e3bSRabin Vincent	if (!-d $dir) {
1401de5b6e3bSRabin Vincent	    mkpath($dir) or
1402de5b6e3bSRabin Vincent		die "can't create $dir";
1403de5b6e3bSRabin Vincent	}
1404de5b6e3bSRabin Vincent
1405de5b6e3bSRabin Vincent	my %files = (
1406de5b6e3bSRabin Vincent		"config" => $output_config,
1407de5b6e3bSRabin Vincent		"buildlog" => $buildlog,
1408de5b6e3bSRabin Vincent		"dmesg" => $dmesg,
1409de5b6e3bSRabin Vincent		"testlog" => $testlog,
1410de5b6e3bSRabin Vincent	);
1411de5b6e3bSRabin Vincent
1412de5b6e3bSRabin Vincent	while (my ($name, $source) = each(%files)) {
1413de5b6e3bSRabin Vincent		if (-f "$source") {
1414de5b6e3bSRabin Vincent			cp "$source", "$dir/$name" or
1415de5b6e3bSRabin Vincent				die "failed to copy $source";
1416de5b6e3bSRabin Vincent		}
1417de5b6e3bSRabin Vincent	}
1418de5b6e3bSRabin Vincent
1419de5b6e3bSRabin Vincent	doprint "*** Saved info to $dir ***\n";
1420de5b6e3bSRabin Vincent}
1421de5b6e3bSRabin Vincent
14222b7d9b21SSteven Rostedtsub fail {
14232b7d9b21SSteven Rostedt
1424921ed4c7SSteven Rostedt	if (defined($post_test)) {
1425921ed4c7SSteven Rostedt		run_command $post_test;
1426921ed4c7SSteven Rostedt	}
1427921ed4c7SSteven Rostedt
1428a75fececSSteven Rostedt	if ($die_on_failure) {
14292b7d9b21SSteven Rostedt		dodie @_;
14302b7d9b21SSteven Rostedt	}
14312b7d9b21SSteven Rostedt
1432a75fececSSteven Rostedt	doprint "FAILED\n";
14337faafbd6SSteven Rostedt
1434576f627cSSteven Rostedt	my $i = $iteration;
1435576f627cSSteven Rostedt
1436a75fececSSteven Rostedt	# no need to reboot for just building.
1437576f627cSSteven Rostedt	if (!do_not_reboot) {
14387faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
1439bc7c5803SSteven Rostedt	    reboot_to_good $sleep_time;
1440a75fececSSteven Rostedt	}
14417faafbd6SSteven Rostedt
14429064af52SSteven Rostedt	my $name = "";
14439064af52SSteven Rostedt
14449064af52SSteven Rostedt	if (defined($test_name)) {
14459064af52SSteven Rostedt	    $name = " ($test_name)";
14469064af52SSteven Rostedt	}
14479064af52SSteven Rostedt
1448576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1449576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
14509064af52SSteven Rostedt	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1451576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1452576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1453a75fececSSteven Rostedt
1454de5b6e3bSRabin Vincent	if (defined($store_failures)) {
1455de5b6e3bSRabin Vincent	    save_logs "fail", $store_failures;
1456cccae1a6SSteven Rostedt        }
1457cccae1a6SSteven Rostedt
14582b7d9b21SSteven Rostedt	return 1;
14592b7d9b21SSteven Rostedt}
14602b7d9b21SSteven Rostedt
14612545eb61SSteven Rostedtsub run_command {
14622545eb61SSteven Rostedt    my ($command) = @_;
1463d6ce2a0bSSteven Rostedt    my $dolog = 0;
1464d6ce2a0bSSteven Rostedt    my $dord = 0;
1465d6ce2a0bSSteven Rostedt    my $pid;
1466d6ce2a0bSSteven Rostedt
1467e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
1468e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
1469e48c5293SSteven Rostedt
1470d6ce2a0bSSteven Rostedt    doprint("$command ... ");
1471d6ce2a0bSSteven Rostedt
1472d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
14732b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
14742545eb61SSteven Rostedt
14752545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1476d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
1477d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
1478d6ce2a0bSSteven Rostedt	$dolog = 1;
14796c5ee0beSSteven Rostedt    }
14806c5ee0beSSteven Rostedt
14816c5ee0beSSteven Rostedt    if (defined($redirect)) {
1482d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
1483d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
1484d6ce2a0bSSteven Rostedt	$dord = 1;
14852545eb61SSteven Rostedt    }
14862545eb61SSteven Rostedt
1487d6ce2a0bSSteven Rostedt    while (<CMD>) {
1488d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
1489d6ce2a0bSSteven Rostedt	print RD  if ($dord);
1490d6ce2a0bSSteven Rostedt    }
14912545eb61SSteven Rostedt
1492d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
14932545eb61SSteven Rostedt    my $failed = $?;
14942545eb61SSteven Rostedt
1495d6ce2a0bSSteven Rostedt    close(CMD);
1496d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
1497d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
1498d6ce2a0bSSteven Rostedt
14992545eb61SSteven Rostedt    if ($failed) {
15002545eb61SSteven Rostedt	doprint "FAILED!\n";
15012545eb61SSteven Rostedt    } else {
15022545eb61SSteven Rostedt	doprint "SUCCESS\n";
15032545eb61SSteven Rostedt    }
15042545eb61SSteven Rostedt
15055f9b6cedSSteven Rostedt    return !$failed;
15065f9b6cedSSteven Rostedt}
15075f9b6cedSSteven Rostedt
1508e48c5293SSteven Rostedtsub run_ssh {
1509e48c5293SSteven Rostedt    my ($cmd) = @_;
1510e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
1511e48c5293SSteven Rostedt
1512e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1513e48c5293SSteven Rostedt    return run_command "$cp_exec";
1514e48c5293SSteven Rostedt}
1515e48c5293SSteven Rostedt
1516e48c5293SSteven Rostedtsub run_scp {
151702ad2617SSteven Rostedt    my ($src, $dst, $cp_scp) = @_;
1518e48c5293SSteven Rostedt
1519e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
1520e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
1521e48c5293SSteven Rostedt
1522e48c5293SSteven Rostedt    return run_command "$cp_scp";
1523e48c5293SSteven Rostedt}
1524e48c5293SSteven Rostedt
152502ad2617SSteven Rostedtsub run_scp_install {
152602ad2617SSteven Rostedt    my ($src, $dst) = @_;
152702ad2617SSteven Rostedt
152802ad2617SSteven Rostedt    my $cp_scp = $scp_to_target_install;
152902ad2617SSteven Rostedt
153002ad2617SSteven Rostedt    return run_scp($src, $dst, $cp_scp);
153102ad2617SSteven Rostedt}
153202ad2617SSteven Rostedt
153302ad2617SSteven Rostedtsub run_scp_mod {
153402ad2617SSteven Rostedt    my ($src, $dst) = @_;
153502ad2617SSteven Rostedt
153602ad2617SSteven Rostedt    my $cp_scp = $scp_to_target;
153702ad2617SSteven Rostedt
153802ad2617SSteven Rostedt    return run_scp($src, $dst, $cp_scp);
153902ad2617SSteven Rostedt}
154002ad2617SSteven Rostedt
1541a15ba913SSteven Rostedtsub get_grub2_index {
1542a15ba913SSteven Rostedt
1543752d9665SSteven Rostedt (Red Hat)    return if (defined($grub_number) && defined($last_grub_menu) &&
1544df5f7c66SSteven Rostedt (Red Hat)	       $last_grub_menu eq $grub_menu && defined($last_machine) &&
1545df5f7c66SSteven Rostedt (Red Hat)	       $last_machine eq $machine);
1546a15ba913SSteven Rostedt
1547a15ba913SSteven Rostedt    doprint "Find grub2 menu ... ";
1548a15ba913SSteven Rostedt    $grub_number = -1;
1549a15ba913SSteven Rostedt
1550a15ba913SSteven Rostedt    my $ssh_grub = $ssh_exec;
1551a15ba913SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat $grub_file,g;
1552a15ba913SSteven Rostedt
1553a15ba913SSteven Rostedt    open(IN, "$ssh_grub |")
1554a15ba913SSteven Rostedt	or die "unable to get $grub_file";
1555a15ba913SSteven Rostedt
1556a15ba913SSteven Rostedt    my $found = 0;
1557a15ba913SSteven Rostedt
1558a15ba913SSteven Rostedt    while (<IN>) {
1559a15ba913SSteven Rostedt	if (/^menuentry.*$grub_menu/) {
1560a15ba913SSteven Rostedt	    $grub_number++;
1561a15ba913SSteven Rostedt	    $found = 1;
1562a15ba913SSteven Rostedt	    last;
1563a15ba913SSteven Rostedt	} elsif (/^menuentry\s/) {
1564a15ba913SSteven Rostedt	    $grub_number++;
1565a15ba913SSteven Rostedt	}
1566a15ba913SSteven Rostedt    }
1567a15ba913SSteven Rostedt    close(IN);
1568a15ba913SSteven Rostedt
1569a15ba913SSteven Rostedt    die "Could not find '$grub_menu' in $grub_file on $machine"
1570a15ba913SSteven Rostedt	if (!$found);
1571a15ba913SSteven Rostedt    doprint "$grub_number\n";
1572752d9665SSteven Rostedt (Red Hat)    $last_grub_menu = $grub_menu;
1573df5f7c66SSteven Rostedt (Red Hat)    $last_machine = $machine;
1574a15ba913SSteven Rostedt}
1575a15ba913SSteven Rostedt
15765f9b6cedSSteven Rostedtsub get_grub_index {
15775f9b6cedSSteven Rostedt
1578a15ba913SSteven Rostedt    if ($reboot_type eq "grub2") {
1579a15ba913SSteven Rostedt	get_grub2_index;
1580a15ba913SSteven Rostedt	return;
1581a15ba913SSteven Rostedt    }
1582a15ba913SSteven Rostedt
1583a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
1584a75fececSSteven Rostedt	return;
1585a75fececSSteven Rostedt    }
1586752d9665SSteven Rostedt (Red Hat)    return if (defined($grub_number) && defined($last_grub_menu) &&
1587df5f7c66SSteven Rostedt (Red Hat)	       $last_grub_menu eq $grub_menu && defined($last_machine) &&
1588df5f7c66SSteven Rostedt (Red Hat)	       $last_machine eq $machine);
15895f9b6cedSSteven Rostedt
15905f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
15915f9b6cedSSteven Rostedt    $grub_number = -1;
1592e48c5293SSteven Rostedt
1593e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
1594e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
1595e48c5293SSteven Rostedt
1596e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
15975f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
1598e48c5293SSteven Rostedt
1599eaa1fe25SSteven Rostedt    my $found = 0;
1600eaa1fe25SSteven Rostedt
16015f9b6cedSSteven Rostedt    while (<IN>) {
1602a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
16035f9b6cedSSteven Rostedt	    $grub_number++;
1604eaa1fe25SSteven Rostedt	    $found = 1;
16055f9b6cedSSteven Rostedt	    last;
16065f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
16075f9b6cedSSteven Rostedt	    $grub_number++;
16085f9b6cedSSteven Rostedt	}
16095f9b6cedSSteven Rostedt    }
16105f9b6cedSSteven Rostedt    close(IN);
16115f9b6cedSSteven Rostedt
1612a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
1613eaa1fe25SSteven Rostedt	if (!$found);
16145f9b6cedSSteven Rostedt    doprint "$grub_number\n";
1615752d9665SSteven Rostedt (Red Hat)    $last_grub_menu = $grub_menu;
1616df5f7c66SSteven Rostedt (Red Hat)    $last_machine = $machine;
16172545eb61SSteven Rostedt}
16182545eb61SSteven Rostedt
16192545eb61SSteven Rostedtsub wait_for_input
16202545eb61SSteven Rostedt{
16212545eb61SSteven Rostedt    my ($fp, $time) = @_;
16222545eb61SSteven Rostedt    my $rin;
16232545eb61SSteven Rostedt    my $ready;
16242545eb61SSteven Rostedt    my $line;
16252545eb61SSteven Rostedt    my $ch;
16262545eb61SSteven Rostedt
16272545eb61SSteven Rostedt    if (!defined($time)) {
16282545eb61SSteven Rostedt	$time = $timeout;
16292545eb61SSteven Rostedt    }
16302545eb61SSteven Rostedt
16312545eb61SSteven Rostedt    $rin = '';
16322545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
1633319ab14fSSteven Rostedt (Red Hat)    ($ready, $time) = select($rin, undef, undef, $time);
16342545eb61SSteven Rostedt
16352545eb61SSteven Rostedt    $line = "";
16362545eb61SSteven Rostedt
16372545eb61SSteven Rostedt    # try to read one char at a time
16382545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
16392545eb61SSteven Rostedt	$line .= $ch;
16402545eb61SSteven Rostedt	last if ($ch eq "\n");
16412545eb61SSteven Rostedt    }
16422545eb61SSteven Rostedt
16432545eb61SSteven Rostedt    if (!length($line)) {
16442545eb61SSteven Rostedt	return undef;
16452545eb61SSteven Rostedt    }
16462545eb61SSteven Rostedt
16472545eb61SSteven Rostedt    return $line;
16482545eb61SSteven Rostedt}
16492545eb61SSteven Rostedt
165075c3fda7SSteven Rostedtsub reboot_to {
1651bc7c5803SSteven Rostedt    if (defined($switch_to_test)) {
1652bc7c5803SSteven Rostedt	run_command $switch_to_test;
1653bc7c5803SSteven Rostedt    }
1654bc7c5803SSteven Rostedt
1655a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
1656c54367f9SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
1657a15ba913SSteven Rostedt    } elsif ($reboot_type eq "grub2") {
1658a15ba913SSteven Rostedt	run_ssh "$grub_reboot $grub_number";
16597786954cSSteven Rostedt    } elsif ($reboot_type eq "syslinux") {
16607786954cSSteven Rostedt	run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path";
166196f6a0dfSSteven Rostedt    } elsif (defined $reboot_script) {
1662a75fececSSteven Rostedt	run_command "$reboot_script";
16632545eb61SSteven Rostedt    }
166496f6a0dfSSteven Rostedt    reboot;
166596f6a0dfSSteven Rostedt}
16662545eb61SSteven Rostedt
1667a57419b3SSteven Rostedtsub get_sha1 {
1668a57419b3SSteven Rostedt    my ($commit) = @_;
1669a57419b3SSteven Rostedt
1670a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
1671a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
1672a57419b3SSteven Rostedt    my $ret = $?;
1673a57419b3SSteven Rostedt
1674a57419b3SSteven Rostedt    logit $sha1;
1675a57419b3SSteven Rostedt
1676a57419b3SSteven Rostedt    if ($ret) {
1677a57419b3SSteven Rostedt	doprint "FAILED\n";
1678a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
1679a57419b3SSteven Rostedt    }
1680a57419b3SSteven Rostedt
1681a57419b3SSteven Rostedt    print "SUCCESS\n";
1682a57419b3SSteven Rostedt
1683a57419b3SSteven Rostedt    chomp $sha1;
1684a57419b3SSteven Rostedt
1685a57419b3SSteven Rostedt    return $sha1;
1686a57419b3SSteven Rostedt}
1687a57419b3SSteven Rostedt
16885a391fbfSSteven Rostedtsub monitor {
16892545eb61SSteven Rostedt    my $booted = 0;
16902545eb61SSteven Rostedt    my $bug = 0;
16916ca996ccSSteven Rostedt    my $bug_ignored = 0;
16925c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
16932b7d9b21SSteven Rostedt    my $loops;
16942545eb61SSteven Rostedt
16957faafbd6SSteven Rostedt    wait_for_monitor 5;
16962545eb61SSteven Rostedt
16972545eb61SSteven Rostedt    my $line;
16982545eb61SSteven Rostedt    my $full_line = "";
16992545eb61SSteven Rostedt
17007faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
17017faafbd6SSteven Rostedt	die "unable to write to $dmesg";
17022545eb61SSteven Rostedt
170375c3fda7SSteven Rostedt    reboot_to;
17042545eb61SSteven Rostedt
17051c8a617aSSteven Rostedt    my $success_start;
17061c8a617aSSteven Rostedt    my $failure_start;
17072d01b26aSSteven Rostedt    my $monitor_start = time;
17082d01b26aSSteven Rostedt    my $done = 0;
1709f1a5b962SSteven Rostedt    my $version_found = 0;
17101c8a617aSSteven Rostedt
17112d01b26aSSteven Rostedt    while (!$done) {
17122545eb61SSteven Rostedt
1713ecaf8e52SSteven Rostedt	if ($bug && defined($stop_after_failure) &&
1714ecaf8e52SSteven Rostedt	    $stop_after_failure >= 0) {
1715ecaf8e52SSteven Rostedt	    my $time = $stop_after_failure - (time - $failure_start);
1716ecaf8e52SSteven Rostedt	    $line = wait_for_input($monitor_fp, $time);
1717ecaf8e52SSteven Rostedt	    if (!defined($line)) {
1718ecaf8e52SSteven Rostedt		doprint "bug timed out after $booted_timeout seconds\n";
1719ecaf8e52SSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1720ecaf8e52SSteven Rostedt		last;
1721ecaf8e52SSteven Rostedt	    }
1722ecaf8e52SSteven Rostedt	} elsif ($booted) {
1723a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
1724cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1725cd4f1d53SSteven Rostedt		my $s = $booted_timeout == 1 ? "" : "s";
1726cd4f1d53SSteven Rostedt		doprint "Successful boot found: break after $booted_timeout second$s\n";
1727cd4f1d53SSteven Rostedt		last;
1728cd4f1d53SSteven Rostedt	    }
17292b7d9b21SSteven Rostedt	} else {
17307faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
1731cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1732cd4f1d53SSteven Rostedt		my $s = $timeout == 1 ? "" : "s";
1733cd4f1d53SSteven Rostedt		doprint "Timed out after $timeout second$s\n";
1734cd4f1d53SSteven Rostedt		last;
17352b7d9b21SSteven Rostedt	    }
1736cd4f1d53SSteven Rostedt	}
17372545eb61SSteven Rostedt
17382545eb61SSteven Rostedt	doprint $line;
17397faafbd6SSteven Rostedt	print DMESG $line;
17402545eb61SSteven Rostedt
17412545eb61SSteven Rostedt	# we are not guaranteed to get a full line
17422545eb61SSteven Rostedt	$full_line .= $line;
17432545eb61SSteven Rostedt
1744a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
17452545eb61SSteven Rostedt	    $booted = 1;
17461c8a617aSSteven Rostedt	    $success_start = time;
17471c8a617aSSteven Rostedt	}
17481c8a617aSSteven Rostedt
17491c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
17501c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
17511c8a617aSSteven Rostedt	    my $now = time;
17521c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
17531c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
17541c8a617aSSteven Rostedt		last;
17551c8a617aSSteven Rostedt	    }
17562545eb61SSteven Rostedt	}
17572545eb61SSteven Rostedt
17585c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
17595c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
17605c42fc5bSSteven Rostedt	}
17615c42fc5bSSteven Rostedt
17622545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
17636ca996ccSSteven Rostedt	    if (!$bug && !$skip_call_trace) {
17646ca996ccSSteven Rostedt		if ($ignore_errors) {
17656ca996ccSSteven Rostedt		    $bug_ignored = 1;
17666ca996ccSSteven Rostedt		} else {
17671c8a617aSSteven Rostedt		    $bug = 1;
17681c8a617aSSteven Rostedt		    $failure_start = time;
17691c8a617aSSteven Rostedt		}
17701c8a617aSSteven Rostedt	    }
17716ca996ccSSteven Rostedt	}
17721c8a617aSSteven Rostedt
17731c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
17741c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
17751c8a617aSSteven Rostedt	    my $now = time;
17761c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
17771c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
17781c8a617aSSteven Rostedt		last;
17791c8a617aSSteven Rostedt	    }
17805c42fc5bSSteven Rostedt	}
17815c42fc5bSSteven Rostedt
17825c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
17835c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
17845c42fc5bSSteven Rostedt	}
17855c42fc5bSSteven Rostedt
17865c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
178710abf118SSteven Rostedt	    $failure_start = time;
17882545eb61SSteven Rostedt	    $bug = 1;
17892545eb61SSteven Rostedt	}
17902545eb61SSteven Rostedt
1791f1a5b962SSteven Rostedt	# Detect triple faults by testing the banner
1792f1a5b962SSteven Rostedt	if ($full_line =~ /\bLinux version (\S+).*\n/) {
1793f1a5b962SSteven Rostedt	    if ($1 eq $version) {
1794f1a5b962SSteven Rostedt		$version_found = 1;
1795f1a5b962SSteven Rostedt	    } elsif ($version_found && $detect_triplefault) {
1796f1a5b962SSteven Rostedt		# We already booted into the kernel we are testing,
1797f1a5b962SSteven Rostedt		# but now we booted into another kernel?
1798f1a5b962SSteven Rostedt		# Consider this a triple fault.
1799*8b513d0cSMasanari Iida		doprint "Already booted in Linux kernel $version, but now\n";
1800f1a5b962SSteven Rostedt		doprint "we booted into Linux kernel $1.\n";
1801f1a5b962SSteven Rostedt		doprint "Assuming that this is a triple fault.\n";
1802f1a5b962SSteven Rostedt		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1803f1a5b962SSteven Rostedt		last;
1804f1a5b962SSteven Rostedt	    }
1805f1a5b962SSteven Rostedt	}
1806f1a5b962SSteven Rostedt
18072545eb61SSteven Rostedt	if ($line =~ /\n/) {
18082545eb61SSteven Rostedt	    $full_line = "";
18092545eb61SSteven Rostedt	}
18102d01b26aSSteven Rostedt
18112d01b26aSSteven Rostedt	if ($stop_test_after > 0 && !$booted && !$bug) {
18122d01b26aSSteven Rostedt	    if (time - $monitor_start > $stop_test_after) {
18134d62bf51SSteven Rostedt		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
18142d01b26aSSteven Rostedt		$done = 1;
18152d01b26aSSteven Rostedt	    }
18162d01b26aSSteven Rostedt	}
18172545eb61SSteven Rostedt    }
18182545eb61SSteven Rostedt
18197faafbd6SSteven Rostedt    close(DMESG);
18202545eb61SSteven Rostedt
18212545eb61SSteven Rostedt    if ($bug) {
18222b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
1823576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
18242545eb61SSteven Rostedt    }
18255f9b6cedSSteven Rostedt
1826a75fececSSteven Rostedt    if (!$booted) {
1827a75fececSSteven Rostedt	return 0 if ($in_bisect);
1828576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
1829a75fececSSteven Rostedt    }
1830a75fececSSteven Rostedt
18316ca996ccSSteven Rostedt    if ($bug_ignored) {
18326ca996ccSSteven Rostedt	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
18336ca996ccSSteven Rostedt    }
18346ca996ccSSteven Rostedt
18352b7d9b21SSteven Rostedt    return 1;
18362545eb61SSteven Rostedt}
18372545eb61SSteven Rostedt
18382b29b2f8SSteven Rostedtsub eval_kernel_version {
18392b29b2f8SSteven Rostedt    my ($option) = @_;
18402b29b2f8SSteven Rostedt
18412b29b2f8SSteven Rostedt    $option =~ s/\$KERNEL_VERSION/$version/g;
18422b29b2f8SSteven Rostedt
18432b29b2f8SSteven Rostedt    return $option;
18442b29b2f8SSteven Rostedt}
18452b29b2f8SSteven Rostedt
1846db05cfefSSteven Rostedtsub do_post_install {
1847db05cfefSSteven Rostedt
1848db05cfefSSteven Rostedt    return if (!defined($post_install));
1849db05cfefSSteven Rostedt
18502b29b2f8SSteven Rostedt    my $cp_post_install = eval_kernel_version $post_install;
1851db05cfefSSteven Rostedt    run_command "$cp_post_install" or
1852db05cfefSSteven Rostedt	dodie "Failed to run post install";
1853db05cfefSSteven Rostedt}
1854db05cfefSSteven Rostedt
1855e1a6c3d7SSteven Rostedt# Sometimes the reboot fails, and will hang. We try to ssh to the box
1856e1a6c3d7SSteven Rostedt# and if we fail, we force another reboot, that should powercycle it.
1857e1a6c3d7SSteven Rostedtsub test_booted {
1858e1a6c3d7SSteven Rostedt    if (!run_ssh "echo testing connection") {
1859e1a6c3d7SSteven Rostedt	reboot $sleep_time;
1860e1a6c3d7SSteven Rostedt    }
1861e1a6c3d7SSteven Rostedt}
1862e1a6c3d7SSteven Rostedt
18632545eb61SSteven Rostedtsub install {
18642545eb61SSteven Rostedt
1865e0a8742eSSteven Rostedt    return if ($no_install);
1866e0a8742eSSteven Rostedt
1867e5c2ec11SSteven Rostedt    if (defined($pre_install)) {
1868e5c2ec11SSteven Rostedt	my $cp_pre_install = eval_kernel_version $pre_install;
1869e5c2ec11SSteven Rostedt	run_command "$cp_pre_install" or
1870e5c2ec11SSteven Rostedt	    dodie "Failed to run pre install";
1871e5c2ec11SSteven Rostedt    }
1872e5c2ec11SSteven Rostedt
18732b29b2f8SSteven Rostedt    my $cp_target = eval_kernel_version $target_image;
18742b29b2f8SSteven Rostedt
1875e1a6c3d7SSteven Rostedt    test_booted;
1876e1a6c3d7SSteven Rostedt
187702ad2617SSteven Rostedt    run_scp_install "$outputdir/$build_target", "$cp_target" or
18785c42fc5bSSteven Rostedt	dodie "failed to copy image";
18795f9b6cedSSteven Rostedt
18805f9b6cedSSteven Rostedt    my $install_mods = 0;
18815f9b6cedSSteven Rostedt
18825f9b6cedSSteven Rostedt    # should we process modules?
18835f9b6cedSSteven Rostedt    $install_mods = 0;
188451ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
18855f9b6cedSSteven Rostedt    while (<IN>) {
18865f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
18878bc5e4eaSSteven Rostedt	    if (defined($1)) {
18888bc5e4eaSSteven Rostedt		$install_mods = 1;
18895f9b6cedSSteven Rostedt		last;
18905f9b6cedSSteven Rostedt	    }
18915f9b6cedSSteven Rostedt	}
18928bc5e4eaSSteven Rostedt    }
18935f9b6cedSSteven Rostedt    close(IN);
18945f9b6cedSSteven Rostedt
18955f9b6cedSSteven Rostedt    if (!$install_mods) {
1896db05cfefSSteven Rostedt	do_post_install;
18975f9b6cedSSteven Rostedt	doprint "No modules needed\n";
18985f9b6cedSSteven Rostedt	return;
18992545eb61SSteven Rostedt    }
19002545eb61SSteven Rostedt
1901627977d8SSteven Rostedt    run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or
19025f9b6cedSSteven Rostedt	dodie "Failed to install modules";
19035f9b6cedSSteven Rostedt
19042545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
1905a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
19062545eb61SSteven Rostedt
1907e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
19085c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
19092545eb61SSteven Rostedt
19105c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
1911a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
19125c42fc5bSSteven Rostedt	dodie "making tarball";
19135c42fc5bSSteven Rostedt
191402ad2617SSteven Rostedt    run_scp_mod "$tmpdir/$modtar", "/tmp" or
19155c42fc5bSSteven Rostedt	dodie "failed to copy modules";
19165c42fc5bSSteven Rostedt
1917a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
19185c42fc5bSSteven Rostedt
1919e7b13441SSteven Rostedt    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
19205c42fc5bSSteven Rostedt	dodie "failed to tar modules";
19215c42fc5bSSteven Rostedt
1922e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
19238b37ca8cSSteven Rostedt
1924db05cfefSSteven Rostedt    do_post_install;
19252545eb61SSteven Rostedt}
19262545eb61SSteven Rostedt
1927ddf607e5SSteven Rostedtsub get_version {
1928ddf607e5SSteven Rostedt    # get the release name
1929683a3e64SSteven Rostedt    return if ($have_version);
1930ddf607e5SSteven Rostedt    doprint "$make kernelrelease ... ";
1931ddf607e5SSteven Rostedt    $version = `$make kernelrelease | tail -1`;
1932ddf607e5SSteven Rostedt    chomp($version);
1933ddf607e5SSteven Rostedt    doprint "$version\n";
1934683a3e64SSteven Rostedt    $have_version = 1;
1935ddf607e5SSteven Rostedt}
1936ddf607e5SSteven Rostedt
1937ddf607e5SSteven Rostedtsub start_monitor_and_boot {
19389f7424ccSSteven Rostedt    # Make sure the stable kernel has finished booting
1939319ab14fSSteven Rostedt (Red Hat)
1940319ab14fSSteven Rostedt (Red Hat)    # Install bisects, don't need console
1941319ab14fSSteven Rostedt (Red Hat)    if (defined $console) {
19429f7424ccSSteven Rostedt	start_monitor;
19439f7424ccSSteven Rostedt	wait_for_monitor 5;
19449f7424ccSSteven Rostedt	end_monitor;
1945319ab14fSSteven Rostedt (Red Hat)    }
19469f7424ccSSteven Rostedt
1947ddf607e5SSteven Rostedt    get_grub_index;
1948ddf607e5SSteven Rostedt    get_version;
1949ddf607e5SSteven Rostedt    install;
1950ddf607e5SSteven Rostedt
1951319ab14fSSteven Rostedt (Red Hat)    start_monitor if (defined $console);
1952ddf607e5SSteven Rostedt    return monitor;
1953ddf607e5SSteven Rostedt}
1954ddf607e5SSteven Rostedt
19554283b169SSteven Rostedt (Red Hat)my $check_build_re = ".*:.*(warning|error|Error):.*";
19564283b169SSteven Rostedt (Red Hat)my $utf8_quote = "\\x{e2}\\x{80}(\\x{98}|\\x{99})";
19574283b169SSteven Rostedt (Red Hat)
19587328735cSSteven Rostedt (Red Hat)sub process_warning_line {
19597328735cSSteven Rostedt (Red Hat)    my ($line) = @_;
19607328735cSSteven Rostedt (Red Hat)
19617328735cSSteven Rostedt (Red Hat)    chomp $line;
19627328735cSSteven Rostedt (Red Hat)
19637328735cSSteven Rostedt (Red Hat)    # for distcc heterogeneous systems, some compilers
19647328735cSSteven Rostedt (Red Hat)    # do things differently causing warning lines
19657328735cSSteven Rostedt (Red Hat)    # to be slightly different. This makes an attempt
19667328735cSSteven Rostedt (Red Hat)    # to fixe those issues.
19677328735cSSteven Rostedt (Red Hat)
19687328735cSSteven Rostedt (Red Hat)    # chop off the index into the line
19697328735cSSteven Rostedt (Red Hat)    # using distcc, some compilers give different indexes
19707328735cSSteven Rostedt (Red Hat)    # depending on white space
19717328735cSSteven Rostedt (Red Hat)    $line =~ s/^(\s*\S+:\d+:)\d+/$1/;
19727328735cSSteven Rostedt (Red Hat)
19737328735cSSteven Rostedt (Red Hat)    # Some compilers use UTF-8 extended for quotes and some don't.
19747328735cSSteven Rostedt (Red Hat)    $line =~ s/$utf8_quote/'/g;
19757328735cSSteven Rostedt (Red Hat)
19767328735cSSteven Rostedt (Red Hat)    return $line;
19777328735cSSteven Rostedt (Red Hat)}
19787328735cSSteven Rostedt (Red Hat)
19794283b169SSteven Rostedt (Red Hat)# Read buildlog and check against warnings file for any
19804283b169SSteven Rostedt (Red Hat)# new warnings.
19814283b169SSteven Rostedt (Red Hat)#
19824283b169SSteven Rostedt (Red Hat)# Returns 1 if OK
19834283b169SSteven Rostedt (Red Hat)#         0 otherwise
19846c5ee0beSSteven Rostedtsub check_buildlog {
19854283b169SSteven Rostedt (Red Hat)    return 1 if (!defined $warnings_file);
19864283b169SSteven Rostedt (Red Hat)
19874283b169SSteven Rostedt (Red Hat)    my %warnings_list;
19884283b169SSteven Rostedt (Red Hat)
19894283b169SSteven Rostedt (Red Hat)    # Failed builds should not reboot the target
19904283b169SSteven Rostedt (Red Hat)    my $save_no_reboot = $no_reboot;
19914283b169SSteven Rostedt (Red Hat)    $no_reboot = 1;
19924283b169SSteven Rostedt (Red Hat)
19934283b169SSteven Rostedt (Red Hat)    if (-f $warnings_file) {
19944283b169SSteven Rostedt (Red Hat)	open(IN, $warnings_file) or
19954283b169SSteven Rostedt (Red Hat)	    dodie "Error opening $warnings_file";
19964283b169SSteven Rostedt (Red Hat)
19974283b169SSteven Rostedt (Red Hat)	while (<IN>) {
19984283b169SSteven Rostedt (Red Hat)	    if (/$check_build_re/) {
19997328735cSSteven Rostedt (Red Hat)		my $warning = process_warning_line $_;
20007328735cSSteven Rostedt (Red Hat)
20017328735cSSteven Rostedt (Red Hat)		$warnings_list{$warning} = 1;
20024283b169SSteven Rostedt (Red Hat)	    }
20034283b169SSteven Rostedt (Red Hat)	}
20044283b169SSteven Rostedt (Red Hat)	close(IN);
20054283b169SSteven Rostedt (Red Hat)    }
20064283b169SSteven Rostedt (Red Hat)
20074283b169SSteven Rostedt (Red Hat)    # If warnings file didn't exist, and WARNINGS_FILE exist,
20084283b169SSteven Rostedt (Red Hat)    # then we fail on any warning!
20094283b169SSteven Rostedt (Red Hat)
20104283b169SSteven Rostedt (Red Hat)    open(IN, $buildlog) or dodie "Can't open $buildlog";
20114283b169SSteven Rostedt (Red Hat)    while (<IN>) {
20124283b169SSteven Rostedt (Red Hat)	if (/$check_build_re/) {
20137328735cSSteven Rostedt (Red Hat)	    my $warning = process_warning_line $_;
20144283b169SSteven Rostedt (Red Hat)
20157328735cSSteven Rostedt (Red Hat)	    if (!defined $warnings_list{$warning}) {
20164283b169SSteven Rostedt (Red Hat)		fail "New warning found (not in $warnings_file)\n$_\n";
20174283b169SSteven Rostedt (Red Hat)		$no_reboot = $save_no_reboot;
20184283b169SSteven Rostedt (Red Hat)		return 0;
20194283b169SSteven Rostedt (Red Hat)	    }
20204283b169SSteven Rostedt (Red Hat)	}
20214283b169SSteven Rostedt (Red Hat)    }
20224283b169SSteven Rostedt (Red Hat)    $no_reboot = $save_no_reboot;
20234283b169SSteven Rostedt (Red Hat)    close(IN);
20244283b169SSteven Rostedt (Red Hat)}
20254283b169SSteven Rostedt (Red Hat)
20264283b169SSteven Rostedt (Red Hat)sub check_patch_buildlog {
20276c5ee0beSSteven Rostedt    my ($patch) = @_;
20286c5ee0beSSteven Rostedt
20296c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
20306c5ee0beSSteven Rostedt
203135275685SSteven Rostedt (Red Hat)    foreach my $file (@files) {
203235275685SSteven Rostedt (Red Hat)	chomp $file;
203335275685SSteven Rostedt (Red Hat)    }
203435275685SSteven Rostedt (Red Hat)
20356c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
20366c5ee0beSSteven Rostedt	dodie "failed to show $patch";
20376c5ee0beSSteven Rostedt    while (<IN>) {
20386c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
20396c5ee0beSSteven Rostedt	    chomp $1;
20406c5ee0beSSteven Rostedt	    $files[$#files] = $1;
20416c5ee0beSSteven Rostedt	}
20426c5ee0beSSteven Rostedt    }
20436c5ee0beSSteven Rostedt    close(IN);
20446c5ee0beSSteven Rostedt
20456c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
20466c5ee0beSSteven Rostedt    while (<IN>) {
20476c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
20486c5ee0beSSteven Rostedt	    my $err = $1;
20496c5ee0beSSteven Rostedt	    foreach my $file (@files) {
2050a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
20516c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
20522b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
20536c5ee0beSSteven Rostedt		}
20546c5ee0beSSteven Rostedt	    }
20556c5ee0beSSteven Rostedt	}
20566c5ee0beSSteven Rostedt    }
20576c5ee0beSSteven Rostedt    close(IN);
20582b7d9b21SSteven Rostedt
20592b7d9b21SSteven Rostedt    return 1;
20606c5ee0beSSteven Rostedt}
20616c5ee0beSSteven Rostedt
2062fcb3f16aSSteven Rostedtsub apply_min_config {
2063fcb3f16aSSteven Rostedt    my $outconfig = "$output_config.new";
2064612b9e9bSSteven Rostedt
2065fcb3f16aSSteven Rostedt    # Read the config file and remove anything that
2066fcb3f16aSSteven Rostedt    # is in the force_config hash (from minconfig and others)
2067fcb3f16aSSteven Rostedt    # then add the force config back.
2068fcb3f16aSSteven Rostedt
2069fcb3f16aSSteven Rostedt    doprint "Applying minimum configurations into $output_config.new\n";
2070fcb3f16aSSteven Rostedt
2071fcb3f16aSSteven Rostedt    open (OUT, ">$outconfig") or
2072fcb3f16aSSteven Rostedt	dodie "Can't create $outconfig";
2073fcb3f16aSSteven Rostedt
2074fcb3f16aSSteven Rostedt    if (-f $output_config) {
2075fcb3f16aSSteven Rostedt	open (IN, $output_config) or
2076fcb3f16aSSteven Rostedt	    dodie "Failed to open $output_config";
2077fcb3f16aSSteven Rostedt	while (<IN>) {
2078fcb3f16aSSteven Rostedt	    if (/^(# )?(CONFIG_[^\s=]*)/) {
2079fcb3f16aSSteven Rostedt		next if (defined($force_config{$2}));
2080fcb3f16aSSteven Rostedt	    }
2081fcb3f16aSSteven Rostedt	    print OUT;
2082fcb3f16aSSteven Rostedt	}
2083fcb3f16aSSteven Rostedt	close IN;
2084fcb3f16aSSteven Rostedt    }
2085fcb3f16aSSteven Rostedt    foreach my $config (keys %force_config) {
2086fcb3f16aSSteven Rostedt	print OUT "$force_config{$config}\n";
2087fcb3f16aSSteven Rostedt    }
2088fcb3f16aSSteven Rostedt    close OUT;
2089fcb3f16aSSteven Rostedt
2090fcb3f16aSSteven Rostedt    run_command "mv $outconfig $output_config";
2091fcb3f16aSSteven Rostedt}
2092fcb3f16aSSteven Rostedt
2093fcb3f16aSSteven Rostedtsub make_oldconfig {
2094fcb3f16aSSteven Rostedt
20954c4ab120SSteven Rostedt    my @force_list = keys %force_config;
20964c4ab120SSteven Rostedt
20974c4ab120SSteven Rostedt    if ($#force_list >= 0) {
2098fcb3f16aSSteven Rostedt	apply_min_config;
20994c4ab120SSteven Rostedt    }
2100fcb3f16aSSteven Rostedt
2101fb16d891SAdam Lee    if (!run_command "$make olddefconfig") {
2102fb16d891SAdam Lee	# Perhaps olddefconfig doesn't exist in this version of the kernel
210318925170SSteven Rostedt	# try oldnoconfig
210418925170SSteven Rostedt	doprint "olddefconfig failed, trying make oldnoconfig\n";
210518925170SSteven Rostedt	if (!run_command "$make oldnoconfig") {
210618925170SSteven Rostedt	    doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
2107612b9e9bSSteven Rostedt	    # try a yes '' | oldconfig
2108fcb3f16aSSteven Rostedt	    run_command "yes '' | $make oldconfig" or
2109612b9e9bSSteven Rostedt		dodie "failed make config oldconfig";
2110612b9e9bSSteven Rostedt	}
2111612b9e9bSSteven Rostedt    }
211218925170SSteven Rostedt}
2113612b9e9bSSteven Rostedt
2114fcb3f16aSSteven Rostedt# read a config file and use this to force new configs.
2115fcb3f16aSSteven Rostedtsub load_force_config {
2116fcb3f16aSSteven Rostedt    my ($config) = @_;
2117fcb3f16aSSteven Rostedt
2118cf79fab6SSteven Rostedt    doprint "Loading force configs from $config\n";
2119fcb3f16aSSteven Rostedt    open(IN, $config) or
2120fcb3f16aSSteven Rostedt	dodie "failed to read $config";
2121fcb3f16aSSteven Rostedt    while (<IN>) {
2122fcb3f16aSSteven Rostedt	chomp;
2123fcb3f16aSSteven Rostedt	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
2124fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
2125fcb3f16aSSteven Rostedt	} elsif (/^# (CONFIG_\S*) is not set/) {
2126fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
2127fcb3f16aSSteven Rostedt	}
2128fcb3f16aSSteven Rostedt    }
2129fcb3f16aSSteven Rostedt    close IN;
2130fcb3f16aSSteven Rostedt}
2131fcb3f16aSSteven Rostedt
21322545eb61SSteven Rostedtsub build {
21332545eb61SSteven Rostedt    my ($type) = @_;
21342545eb61SSteven Rostedt
21357faafbd6SSteven Rostedt    unlink $buildlog;
21367faafbd6SSteven Rostedt
21374ab1cce5SSteven Rostedt    # Failed builds should not reboot the target
21384ab1cce5SSteven Rostedt    my $save_no_reboot = $no_reboot;
21394ab1cce5SSteven Rostedt    $no_reboot = 1;
21404ab1cce5SSteven Rostedt
2141683a3e64SSteven Rostedt    # Calculate a new version from here.
2142683a3e64SSteven Rostedt    $have_version = 0;
2143683a3e64SSteven Rostedt
21440bd6c1a3SSteven Rostedt    if (defined($pre_build)) {
21450bd6c1a3SSteven Rostedt	my $ret = run_command $pre_build;
21460bd6c1a3SSteven Rostedt	if (!$ret && defined($pre_build_die) &&
21470bd6c1a3SSteven Rostedt	    $pre_build_die) {
21480bd6c1a3SSteven Rostedt	    dodie "failed to pre_build\n";
21490bd6c1a3SSteven Rostedt	}
21500bd6c1a3SSteven Rostedt    }
21510bd6c1a3SSteven Rostedt
215275c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
215351ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
215475c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
21555f9b6cedSSteven Rostedt
215675c3fda7SSteven Rostedt	$type = "oldconfig";
215775c3fda7SSteven Rostedt    }
215875c3fda7SSteven Rostedt
21595c42fc5bSSteven Rostedt    # old config can ask questions
21605c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
2161fb16d891SAdam Lee	$type = "olddefconfig";
216275c3fda7SSteven Rostedt
216375c3fda7SSteven Rostedt	# allow for empty configs
216451ad1dd1SSteven Rostedt	run_command "touch $output_config";
216575c3fda7SSteven Rostedt
216613488231SAndrew Jones	if (!$noclean) {
216751ad1dd1SSteven Rostedt	    run_command "mv $output_config $outputdir/config_temp" or
21685c42fc5bSSteven Rostedt		dodie "moving .config";
21695c42fc5bSSteven Rostedt
217013488231SAndrew Jones	    run_command "$make mrproper" or dodie "make mrproper";
21715c42fc5bSSteven Rostedt
217251ad1dd1SSteven Rostedt	    run_command "mv $outputdir/config_temp $output_config" or
21735c42fc5bSSteven Rostedt		dodie "moving config_temp";
217413488231SAndrew Jones	}
21755c42fc5bSSteven Rostedt
21765c42fc5bSSteven Rostedt    } elsif (!$noclean) {
217751ad1dd1SSteven Rostedt	unlink "$output_config";
21785f9b6cedSSteven Rostedt	run_command "$make mrproper" or
21795c42fc5bSSteven Rostedt	    dodie "make mrproper";
21805c42fc5bSSteven Rostedt    }
21812545eb61SSteven Rostedt
21822545eb61SSteven Rostedt    # add something to distinguish this build
2183a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
2184a75fececSSteven Rostedt    print OUT "$localversion\n";
21852545eb61SSteven Rostedt    close(OUT);
21862545eb61SSteven Rostedt
21875f9b6cedSSteven Rostedt    if (defined($minconfig)) {
2188fcb3f16aSSteven Rostedt	load_force_config($minconfig);
21892545eb61SSteven Rostedt    }
21902545eb61SSteven Rostedt
2191fb16d891SAdam Lee    if ($type ne "olddefconfig") {
2192fcb3f16aSSteven Rostedt	run_command "$make $type" or
21935c42fc5bSSteven Rostedt	    dodie "failed make config";
2194612b9e9bSSteven Rostedt    }
2195fcb3f16aSSteven Rostedt    # Run old config regardless, to enforce min configurations
2196fcb3f16aSSteven Rostedt    make_oldconfig;
21972545eb61SSteven Rostedt
2198a75fececSSteven Rostedt    $redirect = "$buildlog";
21990bd6c1a3SSteven Rostedt    my $build_ret = run_command "$make $build_options";
22006c5ee0beSSteven Rostedt    undef $redirect;
22010bd6c1a3SSteven Rostedt
22020bd6c1a3SSteven Rostedt    if (defined($post_build)) {
2203683a3e64SSteven Rostedt	# Because a post build may change the kernel version
2204683a3e64SSteven Rostedt	# do it now.
2205683a3e64SSteven Rostedt	get_version;
22060bd6c1a3SSteven Rostedt	my $ret = run_command $post_build;
22070bd6c1a3SSteven Rostedt	if (!$ret && defined($post_build_die) &&
22080bd6c1a3SSteven Rostedt	    $post_build_die) {
22090bd6c1a3SSteven Rostedt	    dodie "failed to post_build\n";
22100bd6c1a3SSteven Rostedt	}
22110bd6c1a3SSteven Rostedt    }
22120bd6c1a3SSteven Rostedt
22130bd6c1a3SSteven Rostedt    if (!$build_ret) {
22145f9b6cedSSteven Rostedt	# bisect may need this to pass
22154ab1cce5SSteven Rostedt	if ($in_bisect) {
22164ab1cce5SSteven Rostedt	    $no_reboot = $save_no_reboot;
22174ab1cce5SSteven Rostedt	    return 0;
22184ab1cce5SSteven Rostedt	}
22192b7d9b21SSteven Rostedt	fail "failed build" and return 0;
22202545eb61SSteven Rostedt    }
22215f9b6cedSSteven Rostedt
22224ab1cce5SSteven Rostedt    $no_reboot = $save_no_reboot;
22234ab1cce5SSteven Rostedt
22242b7d9b21SSteven Rostedt    return 1;
22252545eb61SSteven Rostedt}
22262545eb61SSteven Rostedt
222775c3fda7SSteven Rostedtsub halt {
2228e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
2229576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
2230576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
2231576f627cSSteven Rostedt	    run_command "$power_off";
2232576f627cSSteven Rostedt	}
2233576f627cSSteven Rostedt    } else {
223475c3fda7SSteven Rostedt	# nope? the zap it!
2235a75fececSSteven Rostedt	run_command "$power_off";
223675c3fda7SSteven Rostedt    }
223775c3fda7SSteven Rostedt}
223875c3fda7SSteven Rostedt
22395f9b6cedSSteven Rostedtsub success {
22405f9b6cedSSteven Rostedt    my ($i) = @_;
22415f9b6cedSSteven Rostedt
2242921ed4c7SSteven Rostedt    if (defined($post_test)) {
2243921ed4c7SSteven Rostedt	run_command $post_test;
2244921ed4c7SSteven Rostedt    }
2245921ed4c7SSteven Rostedt
2246e48c5293SSteven Rostedt    $successes++;
2247e48c5293SSteven Rostedt
22489064af52SSteven Rostedt    my $name = "";
22499064af52SSteven Rostedt
22509064af52SSteven Rostedt    if (defined($test_name)) {
22519064af52SSteven Rostedt	$name = " ($test_name)";
22529064af52SSteven Rostedt    }
22539064af52SSteven Rostedt
22545f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
22555f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
22569064af52SSteven Rostedt    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
22575f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
22585f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
22595f9b6cedSSteven Rostedt
2260de5b6e3bSRabin Vincent    if (defined($store_successes)) {
2261de5b6e3bSRabin Vincent        save_logs "success", $store_successes;
2262de5b6e3bSRabin Vincent    }
2263de5b6e3bSRabin Vincent
2264576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
2265a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
2266bc7c5803SSteven Rostedt	reboot_to_good $sleep_time;
22675f9b6cedSSteven Rostedt    }
22685f9b6cedSSteven Rostedt}
22695f9b6cedSSteven Rostedt
2270c960bb9fSSteven Rostedtsub answer_bisect {
2271c960bb9fSSteven Rostedt    for (;;) {
2272c960bb9fSSteven Rostedt	doprint "Pass or fail? [p/f]";
2273c960bb9fSSteven Rostedt	my $ans = <STDIN>;
2274c960bb9fSSteven Rostedt	chomp $ans;
2275c960bb9fSSteven Rostedt	if ($ans eq "p" || $ans eq "P") {
2276c960bb9fSSteven Rostedt	    return 1;
2277c960bb9fSSteven Rostedt	} elsif ($ans eq "f" || $ans eq "F") {
2278c960bb9fSSteven Rostedt	    return 0;
2279c960bb9fSSteven Rostedt	} else {
2280c960bb9fSSteven Rostedt	    print "Please answer 'P' or 'F'\n";
2281c960bb9fSSteven Rostedt	}
2282c960bb9fSSteven Rostedt    }
2283c960bb9fSSteven Rostedt}
2284c960bb9fSSteven Rostedt
22855a391fbfSSteven Rostedtsub child_run_test {
22867faafbd6SSteven Rostedt    my $failed = 0;
22875a391fbfSSteven Rostedt
22887faafbd6SSteven Rostedt    # child should have no power
2289a75fececSSteven Rostedt    $reboot_on_error = 0;
2290a75fececSSteven Rostedt    $poweroff_on_error = 0;
2291a75fececSSteven Rostedt    $die_on_failure = 1;
22927faafbd6SSteven Rostedt
2293a9dd5d63SRabin Vincent    $redirect = "$testlog";
22947faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
2295a9dd5d63SRabin Vincent    undef $redirect;
2296a9dd5d63SRabin Vincent
22975a391fbfSSteven Rostedt    exit $failed;
22985a391fbfSSteven Rostedt}
22995a391fbfSSteven Rostedt
23005a391fbfSSteven Rostedtmy $child_done;
23015a391fbfSSteven Rostedt
23025a391fbfSSteven Rostedtsub child_finished {
23035a391fbfSSteven Rostedt    $child_done = 1;
23045a391fbfSSteven Rostedt}
23055a391fbfSSteven Rostedt
23065a391fbfSSteven Rostedtsub do_run_test {
23075a391fbfSSteven Rostedt    my $child_pid;
23085a391fbfSSteven Rostedt    my $child_exit;
23095a391fbfSSteven Rostedt    my $line;
23105a391fbfSSteven Rostedt    my $full_line;
23115a391fbfSSteven Rostedt    my $bug = 0;
23129b1d367dSSteven Rostedt    my $bug_ignored = 0;
23135a391fbfSSteven Rostedt
23147faafbd6SSteven Rostedt    wait_for_monitor 1;
23155a391fbfSSteven Rostedt
23167faafbd6SSteven Rostedt    doprint "run test $run_test\n";
23175a391fbfSSteven Rostedt
23185a391fbfSSteven Rostedt    $child_done = 0;
23195a391fbfSSteven Rostedt
23205a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
23215a391fbfSSteven Rostedt
23225a391fbfSSteven Rostedt    $child_pid = fork;
23235a391fbfSSteven Rostedt
23245a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
23255a391fbfSSteven Rostedt
23265a391fbfSSteven Rostedt    $full_line = "";
23275a391fbfSSteven Rostedt
23285a391fbfSSteven Rostedt    do {
23297faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
23305a391fbfSSteven Rostedt	if (defined($line)) {
23315a391fbfSSteven Rostedt
23325a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
23335a391fbfSSteven Rostedt	    $full_line .= $line;
23348ea0e063SSteven Rostedt	    doprint $line;
23355a391fbfSSteven Rostedt
23365a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
23379b1d367dSSteven Rostedt		if ($ignore_errors) {
23389b1d367dSSteven Rostedt		    $bug_ignored = 1;
23399b1d367dSSteven Rostedt		} else {
23405a391fbfSSteven Rostedt		    $bug = 1;
23415a391fbfSSteven Rostedt		}
23429b1d367dSSteven Rostedt	    }
23435a391fbfSSteven Rostedt
23445a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
23455a391fbfSSteven Rostedt		$bug = 1;
23465a391fbfSSteven Rostedt	    }
23475a391fbfSSteven Rostedt
23485a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
23495a391fbfSSteven Rostedt		$full_line = "";
23505a391fbfSSteven Rostedt	    }
23515a391fbfSSteven Rostedt	}
23525a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
23535a391fbfSSteven Rostedt
23549b1d367dSSteven Rostedt    if (!$bug && $bug_ignored) {
23559b1d367dSSteven Rostedt	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
23569b1d367dSSteven Rostedt    }
23579b1d367dSSteven Rostedt
23585a391fbfSSteven Rostedt    if ($bug) {
23598ea0e063SSteven Rostedt	my $failure_start = time;
23608ea0e063SSteven Rostedt	my $now;
23618ea0e063SSteven Rostedt	do {
23628ea0e063SSteven Rostedt	    $line = wait_for_input($monitor_fp, 1);
23638ea0e063SSteven Rostedt	    if (defined($line)) {
23648ea0e063SSteven Rostedt		doprint $line;
23658ea0e063SSteven Rostedt	    }
23668ea0e063SSteven Rostedt	    $now = time;
23678ea0e063SSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
23688ea0e063SSteven Rostedt		last;
23698ea0e063SSteven Rostedt	    }
23708ea0e063SSteven Rostedt	} while (defined($line));
23718ea0e063SSteven Rostedt
23725a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
23735a391fbfSSteven Rostedt	# kill the child with extreme prejudice
23745a391fbfSSteven Rostedt	kill 9, $child_pid;
23755a391fbfSSteven Rostedt    }
23765a391fbfSSteven Rostedt
23775a391fbfSSteven Rostedt    waitpid $child_pid, 0;
23785a391fbfSSteven Rostedt    $child_exit = $?;
23795a391fbfSSteven Rostedt
2380c5dacb88SSteven Rostedt    if (!$bug && $in_bisect) {
2381c5dacb88SSteven Rostedt	if (defined($bisect_ret_good)) {
2382c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_good) {
2383c5dacb88SSteven Rostedt		return 1;
2384c5dacb88SSteven Rostedt	    }
2385c5dacb88SSteven Rostedt	}
2386c5dacb88SSteven Rostedt	if (defined($bisect_ret_skip)) {
2387c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_skip) {
2388c5dacb88SSteven Rostedt		return -1;
2389c5dacb88SSteven Rostedt	    }
2390c5dacb88SSteven Rostedt	}
2391c5dacb88SSteven Rostedt	if (defined($bisect_ret_abort)) {
2392c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_abort) {
2393c5dacb88SSteven Rostedt		fail "test abort" and return -2;
2394c5dacb88SSteven Rostedt	    }
2395c5dacb88SSteven Rostedt	}
2396c5dacb88SSteven Rostedt	if (defined($bisect_ret_bad)) {
2397c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_skip) {
2398c5dacb88SSteven Rostedt		return 0;
2399c5dacb88SSteven Rostedt	    }
2400c5dacb88SSteven Rostedt	}
2401c5dacb88SSteven Rostedt	if (defined($bisect_ret_default)) {
2402c5dacb88SSteven Rostedt	    if ($bisect_ret_default eq "good") {
2403c5dacb88SSteven Rostedt		return 1;
2404c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "bad") {
2405c5dacb88SSteven Rostedt		return 0;
2406c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "skip") {
2407c5dacb88SSteven Rostedt		return -1;
2408c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "abort") {
2409c5dacb88SSteven Rostedt		return -2;
2410c5dacb88SSteven Rostedt	    } else {
2411c5dacb88SSteven Rostedt		fail "unknown default action: $bisect_ret_default"
2412c5dacb88SSteven Rostedt		    and return -2;
2413c5dacb88SSteven Rostedt	    }
2414c5dacb88SSteven Rostedt	}
2415c5dacb88SSteven Rostedt    }
2416c5dacb88SSteven Rostedt
24175a391fbfSSteven Rostedt    if ($bug || $child_exit) {
24182b7d9b21SSteven Rostedt	return 0 if $in_bisect;
24192b7d9b21SSteven Rostedt	fail "test failed" and return 0;
24205a391fbfSSteven Rostedt    }
24212b7d9b21SSteven Rostedt    return 1;
24225a391fbfSSteven Rostedt}
24235a391fbfSSteven Rostedt
2424a75fececSSteven Rostedtsub run_git_bisect {
2425a75fececSSteven Rostedt    my ($command) = @_;
2426a75fececSSteven Rostedt
2427a75fececSSteven Rostedt    doprint "$command ... ";
2428a75fececSSteven Rostedt
2429a75fececSSteven Rostedt    my $output = `$command 2>&1`;
2430a75fececSSteven Rostedt    my $ret = $?;
2431a75fececSSteven Rostedt
2432a75fececSSteven Rostedt    logit $output;
2433a75fececSSteven Rostedt
2434a75fececSSteven Rostedt    if ($ret) {
2435a75fececSSteven Rostedt	doprint "FAILED\n";
2436a75fececSSteven Rostedt	dodie "Failed to git bisect";
2437a75fececSSteven Rostedt    }
2438a75fececSSteven Rostedt
2439a75fececSSteven Rostedt    doprint "SUCCESS\n";
2440a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
2441a75fececSSteven Rostedt	doprint "$1 [$2]\n";
2442a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
2443b5f4aea6SSteven Rostedt	$bisect_bad_commit = $1;
2444a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
2445a75fececSSteven Rostedt	return 0;
2446a75fececSSteven Rostedt    } else {
2447a75fececSSteven Rostedt	# we already logged it, just print it now.
2448a75fececSSteven Rostedt	print $output;
2449a75fececSSteven Rostedt    }
2450a75fececSSteven Rostedt
2451a75fececSSteven Rostedt    return 1;
2452a75fececSSteven Rostedt}
2453a75fececSSteven Rostedt
2454c23dca7cSSteven Rostedtsub bisect_reboot {
2455c23dca7cSSteven Rostedt    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
2456bc7c5803SSteven Rostedt    reboot_to_good $bisect_sleep_time;
2457c23dca7cSSteven Rostedt}
2458c23dca7cSSteven Rostedt
2459c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip
24600a05c769SSteven Rostedtsub run_bisect_test {
24610a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
24625f9b6cedSSteven Rostedt
24632b7d9b21SSteven Rostedt    my $failed = 0;
24645f9b6cedSSteven Rostedt    my $result;
24655f9b6cedSSteven Rostedt    my $output;
24665f9b6cedSSteven Rostedt    my $ret;
24675f9b6cedSSteven Rostedt
24680a05c769SSteven Rostedt    $in_bisect = 1;
24690a05c769SSteven Rostedt
24700a05c769SSteven Rostedt    build $buildtype or $failed = 1;
24715f9b6cedSSteven Rostedt
24725f9b6cedSSteven Rostedt    if ($type ne "build") {
2473c23dca7cSSteven Rostedt	if ($failed && $bisect_skip) {
2474c23dca7cSSteven Rostedt	    $in_bisect = 0;
2475c23dca7cSSteven Rostedt	    return -1;
2476c23dca7cSSteven Rostedt	}
24777faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
24785f9b6cedSSteven Rostedt
24795f9b6cedSSteven Rostedt	# Now boot the box
2480ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
24815f9b6cedSSteven Rostedt
24825f9b6cedSSteven Rostedt	if ($type ne "boot") {
2483c23dca7cSSteven Rostedt	    if ($failed && $bisect_skip) {
2484c23dca7cSSteven Rostedt		end_monitor;
2485c23dca7cSSteven Rostedt		bisect_reboot;
2486c23dca7cSSteven Rostedt		$in_bisect = 0;
2487c23dca7cSSteven Rostedt		return -1;
2488c23dca7cSSteven Rostedt	    }
24897faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
24905a391fbfSSteven Rostedt
24912b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
24925f9b6cedSSteven Rostedt	}
24937faafbd6SSteven Rostedt	end_monitor;
24945f9b6cedSSteven Rostedt    }
24955f9b6cedSSteven Rostedt
24965f9b6cedSSteven Rostedt    if ($failed) {
24970a05c769SSteven Rostedt	$result = 0;
24985f9b6cedSSteven Rostedt    } else {
24990a05c769SSteven Rostedt	$result = 1;
25005f9b6cedSSteven Rostedt    }
25014025bc62SSteven Rostedt
25024025bc62SSteven Rostedt    # reboot the box to a kernel we can ssh to
25034025bc62SSteven Rostedt    if ($type ne "build") {
25044025bc62SSteven Rostedt	bisect_reboot;
25054025bc62SSteven Rostedt    }
25060a05c769SSteven Rostedt    $in_bisect = 0;
25070a05c769SSteven Rostedt
25080a05c769SSteven Rostedt    return $result;
25090a05c769SSteven Rostedt}
25100a05c769SSteven Rostedt
25110a05c769SSteven Rostedtsub run_bisect {
25120a05c769SSteven Rostedt    my ($type) = @_;
25130a05c769SSteven Rostedt    my $buildtype = "oldconfig";
25140a05c769SSteven Rostedt
25150a05c769SSteven Rostedt    # We should have a minconfig to use?
25160a05c769SSteven Rostedt    if (defined($minconfig)) {
25170a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
25180a05c769SSteven Rostedt    }
25190a05c769SSteven Rostedt
25200a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
25210a05c769SSteven Rostedt
2522c960bb9fSSteven Rostedt    if ($bisect_manual) {
2523c960bb9fSSteven Rostedt	$ret = answer_bisect;
2524c960bb9fSSteven Rostedt    }
25255f9b6cedSSteven Rostedt
2526d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
25275158ba3eSRuss Dill    if ($reverse_bisect && $ret >= 0) {
25280a05c769SSteven Rostedt	$ret = !$ret;
2529d6ce2a0bSSteven Rostedt    }
2530d6ce2a0bSSteven Rostedt
2531c23dca7cSSteven Rostedt    if ($ret > 0) {
25320a05c769SSteven Rostedt	return "good";
2533c23dca7cSSteven Rostedt    } elsif ($ret == 0) {
25340a05c769SSteven Rostedt	return  "bad";
2535c23dca7cSSteven Rostedt    } elsif ($bisect_skip) {
2536c23dca7cSSteven Rostedt	doprint "HIT A BAD COMMIT ... SKIPPING\n";
2537c23dca7cSSteven Rostedt	return "skip";
25380a05c769SSteven Rostedt    }
25395f9b6cedSSteven Rostedt}
25405f9b6cedSSteven Rostedt
2541dad98754SSteven Rostedtsub update_bisect_replay {
2542dad98754SSteven Rostedt    my $tmp_log = "$tmpdir/ktest_bisect_log";
2543dad98754SSteven Rostedt    run_command "git bisect log > $tmp_log" or
2544dad98754SSteven Rostedt	die "can't create bisect log";
2545dad98754SSteven Rostedt    return $tmp_log;
2546dad98754SSteven Rostedt}
2547dad98754SSteven Rostedt
25485f9b6cedSSteven Rostedtsub bisect {
25495f9b6cedSSteven Rostedt    my ($i) = @_;
25505f9b6cedSSteven Rostedt
25515f9b6cedSSteven Rostedt    my $result;
25525f9b6cedSSteven Rostedt
2553b5f4aea6SSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($bisect_good));
2554b5f4aea6SSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($bisect_bad));
2555b5f4aea6SSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($bisect_type));
25565f9b6cedSSteven Rostedt
2557b5f4aea6SSteven Rostedt    my $good = $bisect_good;
2558b5f4aea6SSteven Rostedt    my $bad = $bisect_bad;
2559b5f4aea6SSteven Rostedt    my $type = $bisect_type;
2560b5f4aea6SSteven Rostedt    my $start = $bisect_start;
2561b5f4aea6SSteven Rostedt    my $replay = $bisect_replay;
2562b5f4aea6SSteven Rostedt    my $start_files = $bisect_files;
25633410f6fdSSteven Rostedt
25643410f6fdSSteven Rostedt    if (defined($start_files)) {
25653410f6fdSSteven Rostedt	$start_files = " -- " . $start_files;
25663410f6fdSSteven Rostedt    } else {
25673410f6fdSSteven Rostedt	$start_files = "";
25683410f6fdSSteven Rostedt    }
25695f9b6cedSSteven Rostedt
2570a57419b3SSteven Rostedt    # convert to true sha1's
2571a57419b3SSteven Rostedt    $good = get_sha1($good);
2572a57419b3SSteven Rostedt    $bad = get_sha1($bad);
2573a57419b3SSteven Rostedt
2574b5f4aea6SSteven Rostedt    if (defined($bisect_reverse) && $bisect_reverse == 1) {
2575d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
2576d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
2577d6ce2a0bSSteven Rostedt    } else {
2578d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
2579d6ce2a0bSSteven Rostedt    }
2580d6ce2a0bSSteven Rostedt
25815a391fbfSSteven Rostedt    # Can't have a test without having a test to run
25825a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
25835a391fbfSSteven Rostedt	$type = "boot";
25845a391fbfSSteven Rostedt    }
25855a391fbfSSteven Rostedt
2586dad98754SSteven Rostedt    # Check if a bisect was running
2587dad98754SSteven Rostedt    my $bisect_start_file = "$builddir/.git/BISECT_START";
2588dad98754SSteven Rostedt
2589b5f4aea6SSteven Rostedt    my $check = $bisect_check;
2590dad98754SSteven Rostedt    my $do_check = defined($check) && $check ne "0";
2591dad98754SSteven Rostedt
2592dad98754SSteven Rostedt    if ( -f $bisect_start_file ) {
2593dad98754SSteven Rostedt	print "Bisect in progress found\n";
2594dad98754SSteven Rostedt	if ($do_check) {
2595dad98754SSteven Rostedt	    print " If you say yes, then no checks of good or bad will be done\n";
2596dad98754SSteven Rostedt	}
2597dad98754SSteven Rostedt	if (defined($replay)) {
2598dad98754SSteven Rostedt	    print "** BISECT_REPLAY is defined in config file **";
2599dad98754SSteven Rostedt	    print " Ignore config option and perform new git bisect log?\n";
2600dad98754SSteven Rostedt	    if (read_ync " (yes, no, or cancel) ") {
2601dad98754SSteven Rostedt		$replay = update_bisect_replay;
2602dad98754SSteven Rostedt		$do_check = 0;
2603dad98754SSteven Rostedt	    }
2604dad98754SSteven Rostedt	} elsif (read_yn "read git log and continue?") {
2605dad98754SSteven Rostedt	    $replay = update_bisect_replay;
2606dad98754SSteven Rostedt	    $do_check = 0;
2607dad98754SSteven Rostedt	}
2608dad98754SSteven Rostedt    }
2609dad98754SSteven Rostedt
2610dad98754SSteven Rostedt    if ($do_check) {
2611a75fececSSteven Rostedt
2612a75fececSSteven Rostedt	# get current HEAD
2613a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
2614a75fececSSteven Rostedt
2615a75fececSSteven Rostedt	if ($check ne "good") {
2616a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
2617a75fececSSteven Rostedt	    run_command "git checkout $bad" or
2618a75fececSSteven Rostedt		die "Failed to checkout $bad";
2619a75fececSSteven Rostedt
2620a75fececSSteven Rostedt	    $result = run_bisect $type;
2621a75fececSSteven Rostedt
2622a75fececSSteven Rostedt	    if ($result ne "bad") {
2623a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
2624a75fececSSteven Rostedt	    }
2625a75fececSSteven Rostedt	}
2626a75fececSSteven Rostedt
2627a75fececSSteven Rostedt	if ($check ne "bad") {
2628a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
2629a75fececSSteven Rostedt	    run_command "git checkout $good" or
2630a75fececSSteven Rostedt		die "Failed to checkout $good";
2631a75fececSSteven Rostedt
2632a75fececSSteven Rostedt	    $result = run_bisect $type;
2633a75fececSSteven Rostedt
2634a75fececSSteven Rostedt	    if ($result ne "good") {
2635a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
2636a75fececSSteven Rostedt	    }
2637a75fececSSteven Rostedt	}
2638a75fececSSteven Rostedt
2639a75fececSSteven Rostedt	# checkout where we started
2640a75fececSSteven Rostedt	run_command "git checkout $head" or
2641a75fececSSteven Rostedt	    die "Failed to checkout $head";
2642a75fececSSteven Rostedt    }
2643a75fececSSteven Rostedt
26443410f6fdSSteven Rostedt    run_command "git bisect start$start_files" or
2645a75fececSSteven Rostedt	dodie "could not start bisect";
2646a75fececSSteven Rostedt
2647a75fececSSteven Rostedt    run_command "git bisect good $good" or
2648a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
2649a75fececSSteven Rostedt
2650a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
2651a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
2652a75fececSSteven Rostedt
2653a75fececSSteven Rostedt    if (defined($replay)) {
2654a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
2655a75fececSSteven Rostedt	    dodie "failed to run replay";
2656a75fececSSteven Rostedt    }
2657a75fececSSteven Rostedt
2658a75fececSSteven Rostedt    if (defined($start)) {
2659a75fececSSteven Rostedt	run_command "git checkout $start" or
2660a75fececSSteven Rostedt	    dodie "failed to checkout $start";
2661a75fececSSteven Rostedt    }
2662a75fececSSteven Rostedt
2663a75fececSSteven Rostedt    my $test;
26645f9b6cedSSteven Rostedt    do {
26655f9b6cedSSteven Rostedt	$result = run_bisect $type;
2666a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
2667a75fececSSteven Rostedt    } while ($test);
26685f9b6cedSSteven Rostedt
26695f9b6cedSSteven Rostedt    run_command "git bisect log" or
26705f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
26715f9b6cedSSteven Rostedt
26725f9b6cedSSteven Rostedt    run_command "git bisect reset" or
26735f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
26745f9b6cedSSteven Rostedt
2675b5f4aea6SSteven Rostedt    doprint "Bad commit was [$bisect_bad_commit]\n";
26765f9b6cedSSteven Rostedt
26770a05c769SSteven Rostedt    success $i;
26780a05c769SSteven Rostedt}
26790a05c769SSteven Rostedt
2680cf79fab6SSteven Rostedt# config_ignore holds the configs that were set (or unset) for
2681cf79fab6SSteven Rostedt# a good config and we will ignore these configs for the rest
2682cf79fab6SSteven Rostedt# of a config bisect. These configs stay as they were.
26830a05c769SSteven Rostedtmy %config_ignore;
2684cf79fab6SSteven Rostedt
2685cf79fab6SSteven Rostedt# config_set holds what all configs were set as.
26860a05c769SSteven Rostedtmy %config_set;
26870a05c769SSteven Rostedt
2688cf79fab6SSteven Rostedt# config_off holds the set of configs that the bad config had disabled.
2689cf79fab6SSteven Rostedt# We need to record them and set them in the .config when running
2690fb16d891SAdam Lee# olddefconfig, because olddefconfig keeps the defaults.
2691cf79fab6SSteven Rostedtmy %config_off;
2692cf79fab6SSteven Rostedt
2693cf79fab6SSteven Rostedt# config_off_tmp holds a set of configs to turn off for now
2694cf79fab6SSteven Rostedtmy @config_off_tmp;
2695cf79fab6SSteven Rostedt
2696cf79fab6SSteven Rostedt# config_list is the set of configs that are being tested
26970a05c769SSteven Rostedtmy %config_list;
26980a05c769SSteven Rostedtmy %null_config;
26990a05c769SSteven Rostedt
27000a05c769SSteven Rostedtmy %dependency;
27010a05c769SSteven Rostedt
27024c4ab120SSteven Rostedtsub assign_configs {
27034c4ab120SSteven Rostedt    my ($hash, $config) = @_;
27040a05c769SSteven Rostedt
27050a05c769SSteven Rostedt    open (IN, $config)
27060a05c769SSteven Rostedt	or dodie "Failed to read $config";
27070a05c769SSteven Rostedt
27080a05c769SSteven Rostedt    while (<IN>) {
27099bf71749SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
27104c4ab120SSteven Rostedt	    ${$hash}{$2} = $1;
27110a05c769SSteven Rostedt	}
27120a05c769SSteven Rostedt    }
27130a05c769SSteven Rostedt
27140a05c769SSteven Rostedt    close(IN);
27150a05c769SSteven Rostedt}
27160a05c769SSteven Rostedt
27174c4ab120SSteven Rostedtsub process_config_ignore {
27184c4ab120SSteven Rostedt    my ($config) = @_;
27194c4ab120SSteven Rostedt
27204c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
27214c4ab120SSteven Rostedt}
27224c4ab120SSteven Rostedt
27230a05c769SSteven Rostedtsub read_current_config {
27240a05c769SSteven Rostedt    my ($config_ref) = @_;
27250a05c769SSteven Rostedt
27260a05c769SSteven Rostedt    %{$config_ref} = ();
27270a05c769SSteven Rostedt    undef %{$config_ref};
27280a05c769SSteven Rostedt
27290a05c769SSteven Rostedt    my @key = keys %{$config_ref};
27300a05c769SSteven Rostedt    if ($#key >= 0) {
27310a05c769SSteven Rostedt	print "did not delete!\n";
27320a05c769SSteven Rostedt	exit;
27330a05c769SSteven Rostedt    }
27340a05c769SSteven Rostedt    open (IN, "$output_config");
27350a05c769SSteven Rostedt
27360a05c769SSteven Rostedt    while (<IN>) {
27370a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
27380a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
27390a05c769SSteven Rostedt	}
27400a05c769SSteven Rostedt    }
27410a05c769SSteven Rostedt    close(IN);
27420a05c769SSteven Rostedt}
27430a05c769SSteven Rostedt
27440a05c769SSteven Rostedtsub get_dependencies {
27450a05c769SSteven Rostedt    my ($config) = @_;
27460a05c769SSteven Rostedt
27470a05c769SSteven Rostedt    my $arr = $dependency{$config};
27480a05c769SSteven Rostedt    if (!defined($arr)) {
27490a05c769SSteven Rostedt	return ();
27500a05c769SSteven Rostedt    }
27510a05c769SSteven Rostedt
27520a05c769SSteven Rostedt    my @deps = @{$arr};
27530a05c769SSteven Rostedt
27540a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
27550a05c769SSteven Rostedt	print "ADD DEP $dep\n";
27560a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
27570a05c769SSteven Rostedt    }
27580a05c769SSteven Rostedt
27590a05c769SSteven Rostedt    return @deps;
27600a05c769SSteven Rostedt}
27610a05c769SSteven Rostedt
27620a05c769SSteven Rostedtsub create_config {
27630a05c769SSteven Rostedt    my @configs = @_;
27640a05c769SSteven Rostedt
27650a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
27660a05c769SSteven Rostedt
27670a05c769SSteven Rostedt    foreach my $config (@configs) {
27680a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
27690a05c769SSteven Rostedt	my @deps = get_dependencies $config;
27700a05c769SSteven Rostedt	foreach my $dep (@deps) {
27710a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
27720a05c769SSteven Rostedt	}
27730a05c769SSteven Rostedt    }
27740a05c769SSteven Rostedt
2775cf79fab6SSteven Rostedt    # turn off configs to keep off
2776cf79fab6SSteven Rostedt    foreach my $config (keys %config_off) {
2777cf79fab6SSteven Rostedt	print OUT "# $config is not set\n";
2778cf79fab6SSteven Rostedt    }
2779cf79fab6SSteven Rostedt
2780cf79fab6SSteven Rostedt    # turn off configs that should be off for now
2781cf79fab6SSteven Rostedt    foreach my $config (@config_off_tmp) {
2782cf79fab6SSteven Rostedt	print OUT "# $config is not set\n";
2783cf79fab6SSteven Rostedt    }
2784cf79fab6SSteven Rostedt
27850a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
27860a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
27870a05c769SSteven Rostedt    }
27880a05c769SSteven Rostedt    close(OUT);
27890a05c769SSteven Rostedt
2790fcb3f16aSSteven Rostedt    make_oldconfig;
27910a05c769SSteven Rostedt}
27920a05c769SSteven Rostedt
27930a05c769SSteven Rostedtsub compare_configs {
27940a05c769SSteven Rostedt    my (%a, %b) = @_;
27950a05c769SSteven Rostedt
27960a05c769SSteven Rostedt    foreach my $item (keys %a) {
27970a05c769SSteven Rostedt	if (!defined($b{$item})) {
27980a05c769SSteven Rostedt	    print "diff $item\n";
27990a05c769SSteven Rostedt	    return 1;
28000a05c769SSteven Rostedt	}
28010a05c769SSteven Rostedt	delete $b{$item};
28020a05c769SSteven Rostedt    }
28030a05c769SSteven Rostedt
28040a05c769SSteven Rostedt    my @keys = keys %b;
28050a05c769SSteven Rostedt    if ($#keys) {
28060a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
28070a05c769SSteven Rostedt    }
28080a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
28090a05c769SSteven Rostedt
28100a05c769SSteven Rostedt    return 0;
28110a05c769SSteven Rostedt}
28120a05c769SSteven Rostedt
28130a05c769SSteven Rostedtsub run_config_bisect_test {
28140a05c769SSteven Rostedt    my ($type) = @_;
28150a05c769SSteven Rostedt
28160a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
28170a05c769SSteven Rostedt}
28180a05c769SSteven Rostedt
28190a05c769SSteven Rostedtsub process_passed {
28200a05c769SSteven Rostedt    my (%configs) = @_;
28210a05c769SSteven Rostedt
28220a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
28230a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
28240a05c769SSteven Rostedt    # Add them to the min options.
28250a05c769SSteven Rostedt    foreach my $config (keys %configs) {
28260a05c769SSteven Rostedt	if (defined($config_list{$config})) {
28270a05c769SSteven Rostedt	    doprint " removing $config\n";
28280a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
28290a05c769SSteven Rostedt	    delete $config_list{$config};
28300a05c769SSteven Rostedt	}
28310a05c769SSteven Rostedt    }
2832f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
2833f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
28340a05c769SSteven Rostedt}
28350a05c769SSteven Rostedt
28360a05c769SSteven Rostedtsub process_failed {
28370a05c769SSteven Rostedt    my ($config) = @_;
28380a05c769SSteven Rostedt
28390a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
28400a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
28410a05c769SSteven Rostedt    doprint "***************************************\n\n";
28420a05c769SSteven Rostedt}
28430a05c769SSteven Rostedt
28440a05c769SSteven Rostedtsub run_config_bisect {
28450a05c769SSteven Rostedt
28460a05c769SSteven Rostedt    my @start_list = keys %config_list;
28470a05c769SSteven Rostedt
28480a05c769SSteven Rostedt    if ($#start_list < 0) {
28490a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
28500a05c769SSteven Rostedt	return -1;
28510a05c769SSteven Rostedt    }
28520a05c769SSteven Rostedt
28530a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
2854b5f4aea6SSteven Rostedt    my $type = $config_bisect_type;
28550a05c769SSteven Rostedt    my $ret;
28560a05c769SSteven Rostedt    my %current_config;
28570a05c769SSteven Rostedt
28580a05c769SSteven Rostedt    my $count = $#start_list + 1;
28590a05c769SSteven Rostedt    doprint "  $count configs to test\n";
28600a05c769SSteven Rostedt
28610a05c769SSteven Rostedt    my $half = int($#start_list / 2);
28620a05c769SSteven Rostedt
28630a05c769SSteven Rostedt    do {
28640a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
28650a05c769SSteven Rostedt
2866cf79fab6SSteven Rostedt	# keep the bottom half off
2867cf79fab6SSteven Rostedt	if ($half < $#start_list) {
2868cf79fab6SSteven Rostedt	    @config_off_tmp = @start_list[$half + 1 .. $#start_list];
2869cf79fab6SSteven Rostedt	} else {
2870cf79fab6SSteven Rostedt	    @config_off_tmp = ();
2871cf79fab6SSteven Rostedt	}
2872cf79fab6SSteven Rostedt
28730a05c769SSteven Rostedt	create_config @tophalf;
28740a05c769SSteven Rostedt	read_current_config \%current_config;
28750a05c769SSteven Rostedt
28760a05c769SSteven Rostedt	$count = $#tophalf + 1;
28770a05c769SSteven Rostedt	doprint "Testing $count configs\n";
28780a05c769SSteven Rostedt	my $found = 0;
28790a05c769SSteven Rostedt	# make sure we test something
28800a05c769SSteven Rostedt	foreach my $config (@tophalf) {
28810a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
28820a05c769SSteven Rostedt		logit " $config\n";
28830a05c769SSteven Rostedt		$found = 1;
28840a05c769SSteven Rostedt	    }
28850a05c769SSteven Rostedt	}
28860a05c769SSteven Rostedt	if (!$found) {
28870a05c769SSteven Rostedt	    # try the other half
28880a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
2889cf79fab6SSteven Rostedt
2890cf79fab6SSteven Rostedt	    # keep the top half off
2891cf79fab6SSteven Rostedt	    @config_off_tmp = @tophalf;
28924c8cc55bSSteven Rostedt	    @tophalf = @start_list[$half + 1 .. $#start_list];
2893cf79fab6SSteven Rostedt
28940a05c769SSteven Rostedt	    create_config @tophalf;
28950a05c769SSteven Rostedt	    read_current_config \%current_config;
28960a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
28970a05c769SSteven Rostedt		if (defined($current_config{$config})) {
28980a05c769SSteven Rostedt		    logit " $config\n";
28990a05c769SSteven Rostedt		    $found = 1;
29000a05c769SSteven Rostedt		}
29010a05c769SSteven Rostedt	    }
29020a05c769SSteven Rostedt	    if (!$found) {
29030a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
29040a05c769SSteven Rostedt		foreach my $config (@start_list) {
29050a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
29060a05c769SSteven Rostedt		}
29070a05c769SSteven Rostedt		return -1;
29080a05c769SSteven Rostedt	    }
29090a05c769SSteven Rostedt	    $count = $#tophalf + 1;
29100a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
29110a05c769SSteven Rostedt	}
29120a05c769SSteven Rostedt
29130a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
2914c960bb9fSSteven Rostedt	if ($bisect_manual) {
2915c960bb9fSSteven Rostedt	    $ret = answer_bisect;
2916c960bb9fSSteven Rostedt	}
29170a05c769SSteven Rostedt	if ($ret) {
29180a05c769SSteven Rostedt	    process_passed %current_config;
29190a05c769SSteven Rostedt	    return 0;
29200a05c769SSteven Rostedt	}
29210a05c769SSteven Rostedt
29220a05c769SSteven Rostedt	doprint "This config had a failure.\n";
29230a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
2924f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
2925f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
29260a05c769SSteven Rostedt
29270a05c769SSteven Rostedt	# A config exists in this group that was bad.
29280a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
29290a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
29300a05c769SSteven Rostedt		doprint " removing $config\n";
29310a05c769SSteven Rostedt		delete $config_list{$config};
29320a05c769SSteven Rostedt	    }
29330a05c769SSteven Rostedt	}
29340a05c769SSteven Rostedt
29350a05c769SSteven Rostedt	@start_list = @tophalf;
29360a05c769SSteven Rostedt
29370a05c769SSteven Rostedt	if ($#start_list == 0) {
29380a05c769SSteven Rostedt	    process_failed $start_list[0];
29390a05c769SSteven Rostedt	    return 1;
29400a05c769SSteven Rostedt	}
29410a05c769SSteven Rostedt
29420a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
29430a05c769SSteven Rostedt	# they are good.
29440a05c769SSteven Rostedt	$half = int($#start_list / 2);
29454c8cc55bSSteven Rostedt    } while ($#start_list > 0);
29460a05c769SSteven Rostedt
2947c960bb9fSSteven Rostedt    # we found a single config, try it again unless we are running manually
2948c960bb9fSSteven Rostedt
2949c960bb9fSSteven Rostedt    if ($bisect_manual) {
2950c960bb9fSSteven Rostedt	process_failed $start_list[0];
2951c960bb9fSSteven Rostedt	return 1;
2952c960bb9fSSteven Rostedt    }
2953c960bb9fSSteven Rostedt
29540a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
29550a05c769SSteven Rostedt
29560a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
29570a05c769SSteven Rostedt    if ($ret) {
29580a05c769SSteven Rostedt	process_passed %current_config;
29590a05c769SSteven Rostedt	return 0;
29600a05c769SSteven Rostedt    }
29610a05c769SSteven Rostedt
29620a05c769SSteven Rostedt    process_failed $start_list[0];
29630a05c769SSteven Rostedt    return 1;
29640a05c769SSteven Rostedt}
29650a05c769SSteven Rostedt
29660a05c769SSteven Rostedtsub config_bisect {
29670a05c769SSteven Rostedt    my ($i) = @_;
29680a05c769SSteven Rostedt
2969b5f4aea6SSteven Rostedt    my $start_config = $config_bisect;
29700a05c769SSteven Rostedt
29710a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
29720a05c769SSteven Rostedt
297330f75da5SSteven Rostedt    if (defined($config_bisect_good)) {
297430f75da5SSteven Rostedt	process_config_ignore $config_bisect_good;
297530f75da5SSteven Rostedt    }
297630f75da5SSteven Rostedt
29770a05c769SSteven Rostedt    # Make the file with the bad config and the min config
29780a05c769SSteven Rostedt    if (defined($minconfig)) {
29790a05c769SSteven Rostedt	# read the min config for things to ignore
29800a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
29810a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
29820a05c769SSteven Rostedt    } else {
29830a05c769SSteven Rostedt	unlink $tmpconfig;
29840a05c769SSteven Rostedt    }
29850a05c769SSteven Rostedt
29860a05c769SSteven Rostedt    if (-f $tmpconfig) {
2987fcb3f16aSSteven Rostedt	load_force_config($tmpconfig);
29880a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
29890a05c769SSteven Rostedt    }
29900a05c769SSteven Rostedt
29910a05c769SSteven Rostedt    # now process the start config
29920a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
29930a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
29940a05c769SSteven Rostedt
29950a05c769SSteven Rostedt    # read directly what we want to check
29960a05c769SSteven Rostedt    my %config_check;
29970a05c769SSteven Rostedt    open (IN, $output_config)
2998f9dee311SMasanari Iida	or dodie "failed to open $output_config";
29990a05c769SSteven Rostedt
30000a05c769SSteven Rostedt    while (<IN>) {
30010a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
30020a05c769SSteven Rostedt	    $config_check{$2} = $1;
30030a05c769SSteven Rostedt	}
30040a05c769SSteven Rostedt    }
30050a05c769SSteven Rostedt    close(IN);
30060a05c769SSteven Rostedt
3007250bae8bSSteven Rostedt    # Now run oldconfig with the minconfig
3008fcb3f16aSSteven Rostedt    make_oldconfig;
30090a05c769SSteven Rostedt
30100a05c769SSteven Rostedt    # check to see what we lost (or gained)
30110a05c769SSteven Rostedt    open (IN, $output_config)
30120a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
30130a05c769SSteven Rostedt
30140a05c769SSteven Rostedt    my %removed_configs;
30150a05c769SSteven Rostedt    my %added_configs;
30160a05c769SSteven Rostedt
30170a05c769SSteven Rostedt    while (<IN>) {
30180a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
30190a05c769SSteven Rostedt	    # save off all options
30200a05c769SSteven Rostedt	    $config_set{$2} = $1;
30210a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
30220a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
30230a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
30240a05c769SSteven Rostedt		} else {
30250a05c769SSteven Rostedt		    $config_list{$2} = $1;
30260a05c769SSteven Rostedt		}
30270a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
30280a05c769SSteven Rostedt		$added_configs{$2} = $1;
30290a05c769SSteven Rostedt		$config_list{$2} = $1;
30300a05c769SSteven Rostedt	    }
3031cf79fab6SSteven Rostedt	} elsif (/^# ((CONFIG\S*).*)/) {
3032cf79fab6SSteven Rostedt	    # Keep these configs disabled
3033cf79fab6SSteven Rostedt	    $config_set{$2} = $1;
3034cf79fab6SSteven Rostedt	    $config_off{$2} = $1;
30350a05c769SSteven Rostedt	}
30360a05c769SSteven Rostedt    }
30370a05c769SSteven Rostedt    close(IN);
30380a05c769SSteven Rostedt
30390a05c769SSteven Rostedt    my @confs = keys %removed_configs;
30400a05c769SSteven Rostedt    if ($#confs >= 0) {
30410a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
30420a05c769SSteven Rostedt	foreach my $config (@confs) {
30430a05c769SSteven Rostedt	    doprint " $config\n";
30440a05c769SSteven Rostedt	}
30450a05c769SSteven Rostedt    }
30460a05c769SSteven Rostedt    @confs = keys %added_configs;
30470a05c769SSteven Rostedt    if ($#confs >= 0) {
30480a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
30490a05c769SSteven Rostedt	foreach my $config (@confs) {
30500a05c769SSteven Rostedt	    doprint " $config\n";
30510a05c769SSteven Rostedt	}
30520a05c769SSteven Rostedt    }
30530a05c769SSteven Rostedt
30540a05c769SSteven Rostedt    my %config_test;
30550a05c769SSteven Rostedt    my $once = 0;
30560a05c769SSteven Rostedt
3057cf79fab6SSteven Rostedt    @config_off_tmp = ();
3058cf79fab6SSteven Rostedt
30590a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
30600a05c769SSteven Rostedt    # that the config we autocreate has everything we need
30610a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
30620a05c769SSteven Rostedt    # may not be able to create a new config.
30630a05c769SSteven Rostedt    # Here we create a config with everything set.
30640a05c769SSteven Rostedt    create_config (keys %config_list);
30650a05c769SSteven Rostedt    read_current_config \%config_test;
30660a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
30670a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
30680a05c769SSteven Rostedt	    if (!$once) {
30690a05c769SSteven Rostedt		$once = 1;
30700a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
30710a05c769SSteven Rostedt	    }
30720a05c769SSteven Rostedt	    doprint "  $config\n";
30730a05c769SSteven Rostedt	    delete $config_list{$config};
30740a05c769SSteven Rostedt	}
30750a05c769SSteven Rostedt    }
30760a05c769SSteven Rostedt    my $ret;
3077b0918612SSteven Rostedt
3078b0918612SSteven Rostedt    if (defined($config_bisect_check) && $config_bisect_check) {
3079b0918612SSteven Rostedt	doprint " Checking to make sure bad config with min config fails\n";
3080b0918612SSteven Rostedt	create_config keys %config_list;
3081b0918612SSteven Rostedt	$ret = run_config_bisect_test $config_bisect_type;
3082b0918612SSteven Rostedt	if ($ret) {
3083b0918612SSteven Rostedt	    doprint " FAILED! Bad config with min config boots fine\n";
3084b0918612SSteven Rostedt	    return -1;
3085b0918612SSteven Rostedt	}
3086b0918612SSteven Rostedt	doprint " Bad config with min config fails as expected\n";
3087b0918612SSteven Rostedt    }
3088b0918612SSteven Rostedt
30890a05c769SSteven Rostedt    do {
30900a05c769SSteven Rostedt	$ret = run_config_bisect;
30910a05c769SSteven Rostedt    } while (!$ret);
30920a05c769SSteven Rostedt
30930a05c769SSteven Rostedt    return $ret if ($ret < 0);
30945f9b6cedSSteven Rostedt
30955f9b6cedSSteven Rostedt    success $i;
30965f9b6cedSSteven Rostedt}
30975f9b6cedSSteven Rostedt
309827d934b2SSteven Rostedtsub patchcheck_reboot {
309927d934b2SSteven Rostedt    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
3100bc7c5803SSteven Rostedt    reboot_to_good $patchcheck_sleep_time;
310127d934b2SSteven Rostedt}
310227d934b2SSteven Rostedt
31036c5ee0beSSteven Rostedtsub patchcheck {
31046c5ee0beSSteven Rostedt    my ($i) = @_;
31056c5ee0beSSteven Rostedt
31066c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
3107b5f4aea6SSteven Rostedt	if (!defined($patchcheck_start));
31086c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
3109b5f4aea6SSteven Rostedt	if (!defined($patchcheck_type));
31106c5ee0beSSteven Rostedt
3111b5f4aea6SSteven Rostedt    my $start = $patchcheck_start;
31126c5ee0beSSteven Rostedt
31136c5ee0beSSteven Rostedt    my $end = "HEAD";
3114b5f4aea6SSteven Rostedt    if (defined($patchcheck_end)) {
3115b5f4aea6SSteven Rostedt	$end = $patchcheck_end;
31166c5ee0beSSteven Rostedt    }
31176c5ee0beSSteven Rostedt
3118a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
3119a57419b3SSteven Rostedt    $start = get_sha1($start);
3120a57419b3SSteven Rostedt    $end = get_sha1($end);
3121a57419b3SSteven Rostedt
3122b5f4aea6SSteven Rostedt    my $type = $patchcheck_type;
31236c5ee0beSSteven Rostedt
31246c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
31256c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
31266c5ee0beSSteven Rostedt	$type = "boot";
31276c5ee0beSSteven Rostedt    }
31286c5ee0beSSteven Rostedt
31296c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
31306c5ee0beSSteven Rostedt	dodie "could not get git list";
31316c5ee0beSSteven Rostedt
31326c5ee0beSSteven Rostedt    my @list;
31336c5ee0beSSteven Rostedt
31346c5ee0beSSteven Rostedt    while (<IN>) {
31356c5ee0beSSteven Rostedt	chomp;
31366c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
31376c5ee0beSSteven Rostedt	last if (/^$start/);
31386c5ee0beSSteven Rostedt    }
31396c5ee0beSSteven Rostedt    close(IN);
31406c5ee0beSSteven Rostedt
31416c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
31422b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
31436c5ee0beSSteven Rostedt    }
31446c5ee0beSSteven Rostedt
31456c5ee0beSSteven Rostedt    # go backwards in the list
31466c5ee0beSSteven Rostedt    @list = reverse @list;
31476c5ee0beSSteven Rostedt
31486c5ee0beSSteven Rostedt    my $save_clean = $noclean;
31491990207dSSteven Rostedt    my %ignored_warnings;
31501990207dSSteven Rostedt
31511990207dSSteven Rostedt    if (defined($ignore_warnings)) {
31521990207dSSteven Rostedt	foreach my $sha1 (split /\s+/, $ignore_warnings) {
31531990207dSSteven Rostedt	    $ignored_warnings{$sha1} = 1;
31541990207dSSteven Rostedt	}
31551990207dSSteven Rostedt    }
31566c5ee0beSSteven Rostedt
31576c5ee0beSSteven Rostedt    $in_patchcheck = 1;
31586c5ee0beSSteven Rostedt    foreach my $item (@list) {
31596c5ee0beSSteven Rostedt	my $sha1 = $item;
31606c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
31616c5ee0beSSteven Rostedt
31626c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
31636c5ee0beSSteven Rostedt
31646c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
31656c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
31666c5ee0beSSteven Rostedt
31676c5ee0beSSteven Rostedt	# only clean on the first and last patch
31686c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
31696c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
31706c5ee0beSSteven Rostedt	    $noclean = $save_clean;
31716c5ee0beSSteven Rostedt	} else {
31726c5ee0beSSteven Rostedt	    $noclean = 1;
31736c5ee0beSSteven Rostedt	}
31746c5ee0beSSteven Rostedt
31756c5ee0beSSteven Rostedt	if (defined($minconfig)) {
31762b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
31776c5ee0beSSteven Rostedt	} else {
31786c5ee0beSSteven Rostedt	    # ?? no config to use?
31792b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
31806c5ee0beSSteven Rostedt	}
31816c5ee0beSSteven Rostedt
31824283b169SSteven Rostedt (Red Hat)	# No need to do per patch checking if warnings file exists
31834283b169SSteven Rostedt (Red Hat)	if (!defined($warnings_file) && !defined($ignored_warnings{$sha1})) {
31844283b169SSteven Rostedt (Red Hat)	    check_patch_buildlog $sha1 or return 0;
31851990207dSSteven Rostedt	}
31866c5ee0beSSteven Rostedt
31874283b169SSteven Rostedt (Red Hat)	check_buildlog or return 0;
31884283b169SSteven Rostedt (Red Hat)
31896c5ee0beSSteven Rostedt	next if ($type eq "build");
31906c5ee0beSSteven Rostedt
31917faafbd6SSteven Rostedt	my $failed = 0;
31927faafbd6SSteven Rostedt
3193ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
31947faafbd6SSteven Rostedt
31957faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
31967faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
31977faafbd6SSteven Rostedt	}
31987faafbd6SSteven Rostedt	end_monitor;
31997faafbd6SSteven Rostedt	return 0 if ($failed);
32007faafbd6SSteven Rostedt
320127d934b2SSteven Rostedt	patchcheck_reboot;
320227d934b2SSteven Rostedt
32036c5ee0beSSteven Rostedt    }
32046c5ee0beSSteven Rostedt    $in_patchcheck = 0;
32056c5ee0beSSteven Rostedt    success $i;
32062b7d9b21SSteven Rostedt
32072b7d9b21SSteven Rostedt    return 1;
32086c5ee0beSSteven Rostedt}
32096c5ee0beSSteven Rostedt
3210b9066f6cSSteven Rostedtmy %depends;
3211ac6974c7SSteven Rostedtmy %depcount;
3212b9066f6cSSteven Rostedtmy $iflevel = 0;
3213b9066f6cSSteven Rostedtmy @ifdeps;
3214b9066f6cSSteven Rostedt
3215b9066f6cSSteven Rostedt# prevent recursion
3216b9066f6cSSteven Rostedtmy %read_kconfigs;
3217b9066f6cSSteven Rostedt
3218ac6974c7SSteven Rostedtsub add_dep {
3219ac6974c7SSteven Rostedt    # $config depends on $dep
3220ac6974c7SSteven Rostedt    my ($config, $dep) = @_;
3221ac6974c7SSteven Rostedt
3222ac6974c7SSteven Rostedt    if (defined($depends{$config})) {
3223ac6974c7SSteven Rostedt	$depends{$config} .= " " . $dep;
3224ac6974c7SSteven Rostedt    } else {
3225ac6974c7SSteven Rostedt	$depends{$config} = $dep;
3226ac6974c7SSteven Rostedt    }
3227ac6974c7SSteven Rostedt
3228ac6974c7SSteven Rostedt    # record the number of configs depending on $dep
3229ac6974c7SSteven Rostedt    if (defined $depcount{$dep}) {
3230ac6974c7SSteven Rostedt	$depcount{$dep}++;
3231ac6974c7SSteven Rostedt    } else {
3232ac6974c7SSteven Rostedt	$depcount{$dep} = 1;
3233ac6974c7SSteven Rostedt    }
3234ac6974c7SSteven Rostedt}
3235ac6974c7SSteven Rostedt
3236b9066f6cSSteven Rostedt# taken from streamline_config.pl
3237b9066f6cSSteven Rostedtsub read_kconfig {
3238b9066f6cSSteven Rostedt    my ($kconfig) = @_;
3239b9066f6cSSteven Rostedt
3240b9066f6cSSteven Rostedt    my $state = "NONE";
3241b9066f6cSSteven Rostedt    my $config;
3242b9066f6cSSteven Rostedt    my @kconfigs;
3243b9066f6cSSteven Rostedt
3244b9066f6cSSteven Rostedt    my $cont = 0;
3245b9066f6cSSteven Rostedt    my $line;
3246b9066f6cSSteven Rostedt
3247b9066f6cSSteven Rostedt
3248b9066f6cSSteven Rostedt    if (! -f $kconfig) {
3249b9066f6cSSteven Rostedt	doprint "file $kconfig does not exist, skipping\n";
3250b9066f6cSSteven Rostedt	return;
3251b9066f6cSSteven Rostedt    }
3252b9066f6cSSteven Rostedt
3253b9066f6cSSteven Rostedt    open(KIN, "$kconfig")
3254b9066f6cSSteven Rostedt	or die "Can't open $kconfig";
3255b9066f6cSSteven Rostedt    while (<KIN>) {
3256b9066f6cSSteven Rostedt	chomp;
3257b9066f6cSSteven Rostedt
3258b9066f6cSSteven Rostedt	# Make sure that lines ending with \ continue
3259b9066f6cSSteven Rostedt	if ($cont) {
3260b9066f6cSSteven Rostedt	    $_ = $line . " " . $_;
3261b9066f6cSSteven Rostedt	}
3262b9066f6cSSteven Rostedt
3263b9066f6cSSteven Rostedt	if (s/\\$//) {
3264b9066f6cSSteven Rostedt	    $cont = 1;
3265b9066f6cSSteven Rostedt	    $line = $_;
3266b9066f6cSSteven Rostedt	    next;
3267b9066f6cSSteven Rostedt	}
3268b9066f6cSSteven Rostedt
3269b9066f6cSSteven Rostedt	$cont = 0;
3270b9066f6cSSteven Rostedt
3271b9066f6cSSteven Rostedt	# collect any Kconfig sources
3272b9066f6cSSteven Rostedt	if (/^source\s*"(.*)"/) {
3273b9066f6cSSteven Rostedt	    $kconfigs[$#kconfigs+1] = $1;
3274b9066f6cSSteven Rostedt	}
3275b9066f6cSSteven Rostedt
3276b9066f6cSSteven Rostedt	# configs found
3277b9066f6cSSteven Rostedt	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
3278b9066f6cSSteven Rostedt	    $state = "NEW";
3279b9066f6cSSteven Rostedt	    $config = $2;
3280b9066f6cSSteven Rostedt
3281b9066f6cSSteven Rostedt	    for (my $i = 0; $i < $iflevel; $i++) {
3282ac6974c7SSteven Rostedt		add_dep $config, $ifdeps[$i];
3283b9066f6cSSteven Rostedt	    }
3284b9066f6cSSteven Rostedt
3285b9066f6cSSteven Rostedt	# collect the depends for the config
3286b9066f6cSSteven Rostedt	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
3287b9066f6cSSteven Rostedt
3288ac6974c7SSteven Rostedt	    add_dep $config, $1;
3289b9066f6cSSteven Rostedt
3290b9066f6cSSteven Rostedt	# Get the configs that select this config
3291ac6974c7SSteven Rostedt	} elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
3292ac6974c7SSteven Rostedt
3293ac6974c7SSteven Rostedt	    # selected by depends on config
3294ac6974c7SSteven Rostedt	    add_dep $1, $config;
3295b9066f6cSSteven Rostedt
3296b9066f6cSSteven Rostedt	# Check for if statements
3297b9066f6cSSteven Rostedt	} elsif (/^if\s+(.*\S)\s*$/) {
3298b9066f6cSSteven Rostedt	    my $deps = $1;
3299b9066f6cSSteven Rostedt	    # remove beginning and ending non text
3300b9066f6cSSteven Rostedt	    $deps =~ s/^[^a-zA-Z0-9_]*//;
3301b9066f6cSSteven Rostedt	    $deps =~ s/[^a-zA-Z0-9_]*$//;
3302b9066f6cSSteven Rostedt
3303b9066f6cSSteven Rostedt	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
3304b9066f6cSSteven Rostedt
3305b9066f6cSSteven Rostedt	    $ifdeps[$iflevel++] = join ':', @deps;
3306b9066f6cSSteven Rostedt
3307b9066f6cSSteven Rostedt	} elsif (/^endif/) {
3308b9066f6cSSteven Rostedt
3309b9066f6cSSteven Rostedt	    $iflevel-- if ($iflevel);
3310b9066f6cSSteven Rostedt
3311b9066f6cSSteven Rostedt	# stop on "help"
3312b9066f6cSSteven Rostedt	} elsif (/^\s*help\s*$/) {
3313b9066f6cSSteven Rostedt	    $state = "NONE";
3314b9066f6cSSteven Rostedt	}
3315b9066f6cSSteven Rostedt    }
3316b9066f6cSSteven Rostedt    close(KIN);
3317b9066f6cSSteven Rostedt
3318b9066f6cSSteven Rostedt    # read in any configs that were found.
3319b9066f6cSSteven Rostedt    foreach $kconfig (@kconfigs) {
3320b9066f6cSSteven Rostedt	if (!defined($read_kconfigs{$kconfig})) {
3321b9066f6cSSteven Rostedt	    $read_kconfigs{$kconfig} = 1;
3322b9066f6cSSteven Rostedt	    read_kconfig("$builddir/$kconfig");
3323b9066f6cSSteven Rostedt	}
3324b9066f6cSSteven Rostedt    }
3325b9066f6cSSteven Rostedt}
3326b9066f6cSSteven Rostedt
3327b9066f6cSSteven Rostedtsub read_depends {
3328b9066f6cSSteven Rostedt    # find out which arch this is by the kconfig file
3329b9066f6cSSteven Rostedt    open (IN, $output_config)
3330b9066f6cSSteven Rostedt	or dodie "Failed to read $output_config";
3331b9066f6cSSteven Rostedt    my $arch;
3332b9066f6cSSteven Rostedt    while (<IN>) {
3333b9066f6cSSteven Rostedt	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
3334b9066f6cSSteven Rostedt	    $arch = $1;
3335b9066f6cSSteven Rostedt	    last;
3336b9066f6cSSteven Rostedt	}
3337b9066f6cSSteven Rostedt    }
3338b9066f6cSSteven Rostedt    close IN;
3339b9066f6cSSteven Rostedt
3340b9066f6cSSteven Rostedt    if (!defined($arch)) {
3341b9066f6cSSteven Rostedt	doprint "Could not find arch from config file\n";
3342b9066f6cSSteven Rostedt	doprint "no dependencies used\n";
3343b9066f6cSSteven Rostedt	return;
3344b9066f6cSSteven Rostedt    }
3345b9066f6cSSteven Rostedt
3346b9066f6cSSteven Rostedt    # arch is really the subarch, we need to know
3347b9066f6cSSteven Rostedt    # what directory to look at.
3348b9066f6cSSteven Rostedt    if ($arch eq "i386" || $arch eq "x86_64") {
3349b9066f6cSSteven Rostedt	$arch = "x86";
3350b9066f6cSSteven Rostedt    } elsif ($arch =~ /^tile/) {
3351b9066f6cSSteven Rostedt	$arch = "tile";
3352b9066f6cSSteven Rostedt    }
3353b9066f6cSSteven Rostedt
3354b9066f6cSSteven Rostedt    my $kconfig = "$builddir/arch/$arch/Kconfig";
3355b9066f6cSSteven Rostedt
3356b9066f6cSSteven Rostedt    if (! -f $kconfig && $arch =~ /\d$/) {
3357b9066f6cSSteven Rostedt	my $orig = $arch;
3358b9066f6cSSteven Rostedt 	# some subarchs have numbers, truncate them
3359b9066f6cSSteven Rostedt	$arch =~ s/\d*$//;
3360b9066f6cSSteven Rostedt	$kconfig = "$builddir/arch/$arch/Kconfig";
3361b9066f6cSSteven Rostedt	if (! -f $kconfig) {
3362b9066f6cSSteven Rostedt	    doprint "No idea what arch dir $orig is for\n";
3363b9066f6cSSteven Rostedt	    doprint "no dependencies used\n";
3364b9066f6cSSteven Rostedt	    return;
3365b9066f6cSSteven Rostedt	}
3366b9066f6cSSteven Rostedt    }
3367b9066f6cSSteven Rostedt
3368b9066f6cSSteven Rostedt    read_kconfig($kconfig);
3369b9066f6cSSteven Rostedt}
3370b9066f6cSSteven Rostedt
33714c4ab120SSteven Rostedtsub read_config_list {
33724c4ab120SSteven Rostedt    my ($config) = @_;
33734c4ab120SSteven Rostedt
33744c4ab120SSteven Rostedt    open (IN, $config)
33754c4ab120SSteven Rostedt	or dodie "Failed to read $config";
33764c4ab120SSteven Rostedt
33774c4ab120SSteven Rostedt    while (<IN>) {
33784c4ab120SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
33794c4ab120SSteven Rostedt	    if (!defined($config_ignore{$2})) {
33804c4ab120SSteven Rostedt		$config_list{$2} = $1;
33814c4ab120SSteven Rostedt	    }
33824c4ab120SSteven Rostedt	}
33834c4ab120SSteven Rostedt    }
33844c4ab120SSteven Rostedt
33854c4ab120SSteven Rostedt    close(IN);
33864c4ab120SSteven Rostedt}
33874c4ab120SSteven Rostedt
33884c4ab120SSteven Rostedtsub read_output_config {
33894c4ab120SSteven Rostedt    my ($config) = @_;
33904c4ab120SSteven Rostedt
33914c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
33924c4ab120SSteven Rostedt}
33934c4ab120SSteven Rostedt
33944c4ab120SSteven Rostedtsub make_new_config {
33954c4ab120SSteven Rostedt    my @configs = @_;
33964c4ab120SSteven Rostedt
33974c4ab120SSteven Rostedt    open (OUT, ">$output_config")
33984c4ab120SSteven Rostedt	or dodie "Failed to write $output_config";
33994c4ab120SSteven Rostedt
34004c4ab120SSteven Rostedt    foreach my $config (@configs) {
34014c4ab120SSteven Rostedt	print OUT "$config\n";
34024c4ab120SSteven Rostedt    }
34034c4ab120SSteven Rostedt    close OUT;
34044c4ab120SSteven Rostedt}
34054c4ab120SSteven Rostedt
3406ac6974c7SSteven Rostedtsub chomp_config {
3407ac6974c7SSteven Rostedt    my ($config) = @_;
3408ac6974c7SSteven Rostedt
3409ac6974c7SSteven Rostedt    $config =~ s/CONFIG_//;
3410ac6974c7SSteven Rostedt
3411ac6974c7SSteven Rostedt    return $config;
3412ac6974c7SSteven Rostedt}
3413ac6974c7SSteven Rostedt
3414b9066f6cSSteven Rostedtsub get_depends {
3415b9066f6cSSteven Rostedt    my ($dep) = @_;
3416b9066f6cSSteven Rostedt
3417ac6974c7SSteven Rostedt    my $kconfig = chomp_config $dep;
3418b9066f6cSSteven Rostedt
3419b9066f6cSSteven Rostedt    $dep = $depends{"$kconfig"};
3420b9066f6cSSteven Rostedt
3421b9066f6cSSteven Rostedt    # the dep string we have saves the dependencies as they
3422b9066f6cSSteven Rostedt    # were found, including expressions like ! && ||. We
3423b9066f6cSSteven Rostedt    # want to split this out into just an array of configs.
3424b9066f6cSSteven Rostedt
3425b9066f6cSSteven Rostedt    my $valid = "A-Za-z_0-9";
3426b9066f6cSSteven Rostedt
3427b9066f6cSSteven Rostedt    my @configs;
3428b9066f6cSSteven Rostedt
3429b9066f6cSSteven Rostedt    while ($dep =~ /[$valid]/) {
3430b9066f6cSSteven Rostedt
3431b9066f6cSSteven Rostedt	if ($dep =~ /^[^$valid]*([$valid]+)/) {
3432b9066f6cSSteven Rostedt	    my $conf = "CONFIG_" . $1;
3433b9066f6cSSteven Rostedt
3434b9066f6cSSteven Rostedt	    $configs[$#configs + 1] = $conf;
3435b9066f6cSSteven Rostedt
3436b9066f6cSSteven Rostedt	    $dep =~ s/^[^$valid]*[$valid]+//;
3437b9066f6cSSteven Rostedt	} else {
3438b9066f6cSSteven Rostedt	    die "this should never happen";
3439b9066f6cSSteven Rostedt	}
3440b9066f6cSSteven Rostedt    }
3441b9066f6cSSteven Rostedt
3442b9066f6cSSteven Rostedt    return @configs;
3443b9066f6cSSteven Rostedt}
3444b9066f6cSSteven Rostedt
3445b9066f6cSSteven Rostedtmy %min_configs;
3446b9066f6cSSteven Rostedtmy %keep_configs;
344743d1b651SSteven Rostedtmy %save_configs;
3448b9066f6cSSteven Rostedtmy %processed_configs;
3449b9066f6cSSteven Rostedtmy %nochange_config;
3450b9066f6cSSteven Rostedt
3451b9066f6cSSteven Rostedtsub test_this_config {
3452b9066f6cSSteven Rostedt    my ($config) = @_;
3453b9066f6cSSteven Rostedt
3454b9066f6cSSteven Rostedt    my $found;
3455b9066f6cSSteven Rostedt
3456b9066f6cSSteven Rostedt    # if we already processed this config, skip it
3457b9066f6cSSteven Rostedt    if (defined($processed_configs{$config})) {
3458b9066f6cSSteven Rostedt	return undef;
3459b9066f6cSSteven Rostedt    }
3460b9066f6cSSteven Rostedt    $processed_configs{$config} = 1;
3461b9066f6cSSteven Rostedt
3462b9066f6cSSteven Rostedt    # if this config failed during this round, skip it
3463b9066f6cSSteven Rostedt    if (defined($nochange_config{$config})) {
3464b9066f6cSSteven Rostedt	return undef;
3465b9066f6cSSteven Rostedt    }
3466b9066f6cSSteven Rostedt
3467ac6974c7SSteven Rostedt    my $kconfig = chomp_config $config;
3468b9066f6cSSteven Rostedt
3469b9066f6cSSteven Rostedt    # Test dependencies first
3470b9066f6cSSteven Rostedt    if (defined($depends{"$kconfig"})) {
3471b9066f6cSSteven Rostedt	my @parents = get_depends $config;
3472b9066f6cSSteven Rostedt	foreach my $parent (@parents) {
3473b9066f6cSSteven Rostedt	    # if the parent is in the min config, check it first
3474b9066f6cSSteven Rostedt	    next if (!defined($min_configs{$parent}));
3475b9066f6cSSteven Rostedt	    $found = test_this_config($parent);
3476b9066f6cSSteven Rostedt	    if (defined($found)) {
3477b9066f6cSSteven Rostedt		return $found;
3478b9066f6cSSteven Rostedt	    }
3479b9066f6cSSteven Rostedt	}
3480b9066f6cSSteven Rostedt    }
3481b9066f6cSSteven Rostedt
3482b9066f6cSSteven Rostedt    # Remove this config from the list of configs
3483fb16d891SAdam Lee    # do a make olddefconfig and then read the resulting
3484b9066f6cSSteven Rostedt    # .config to make sure it is missing the config that
3485b9066f6cSSteven Rostedt    # we had before
3486b9066f6cSSteven Rostedt    my %configs = %min_configs;
3487b9066f6cSSteven Rostedt    delete $configs{$config};
3488b9066f6cSSteven Rostedt    make_new_config ((values %configs), (values %keep_configs));
3489b9066f6cSSteven Rostedt    make_oldconfig;
3490b9066f6cSSteven Rostedt    undef %configs;
3491b9066f6cSSteven Rostedt    assign_configs \%configs, $output_config;
3492b9066f6cSSteven Rostedt
3493b9066f6cSSteven Rostedt    return $config if (!defined($configs{$config}));
3494b9066f6cSSteven Rostedt
3495b9066f6cSSteven Rostedt    doprint "disabling config $config did not change .config\n";
3496b9066f6cSSteven Rostedt
3497b9066f6cSSteven Rostedt    $nochange_config{$config} = 1;
3498b9066f6cSSteven Rostedt
3499b9066f6cSSteven Rostedt    return undef;
3500b9066f6cSSteven Rostedt}
3501b9066f6cSSteven Rostedt
35024c4ab120SSteven Rostedtsub make_min_config {
35034c4ab120SSteven Rostedt    my ($i) = @_;
35044c4ab120SSteven Rostedt
3505ccc513b6SSteven Rostedt    my $type = $minconfig_type;
3506ccc513b6SSteven Rostedt    if ($type ne "boot" && $type ne "test") {
3507ccc513b6SSteven Rostedt	fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" .
3508ccc513b6SSteven Rostedt	    " make_min_config works only with 'boot' and 'test'\n" and return;
3509ccc513b6SSteven Rostedt    }
3510ccc513b6SSteven Rostedt
35114c4ab120SSteven Rostedt    if (!defined($output_minconfig)) {
35124c4ab120SSteven Rostedt	fail "OUTPUT_MIN_CONFIG not defined" and return;
35134c4ab120SSteven Rostedt    }
351435ce5952SSteven Rostedt
351535ce5952SSteven Rostedt    # If output_minconfig exists, and the start_minconfig
351635ce5952SSteven Rostedt    # came from min_config, than ask if we should use
351735ce5952SSteven Rostedt    # that instead.
351835ce5952SSteven Rostedt    if (-f $output_minconfig && !$start_minconfig_defined) {
351935ce5952SSteven Rostedt	print "$output_minconfig exists\n";
352043de3316SSteven Rostedt	if (!defined($use_output_minconfig)) {
352135ce5952SSteven Rostedt	    if (read_yn " Use it as minconfig?") {
352235ce5952SSteven Rostedt		$start_minconfig = $output_minconfig;
352335ce5952SSteven Rostedt	    }
352443de3316SSteven Rostedt	} elsif ($use_output_minconfig > 0) {
352543de3316SSteven Rostedt	    doprint "Using $output_minconfig as MIN_CONFIG\n";
352643de3316SSteven Rostedt	    $start_minconfig = $output_minconfig;
352743de3316SSteven Rostedt	} else {
352843de3316SSteven Rostedt	    doprint "Set to still use MIN_CONFIG as starting point\n";
352943de3316SSteven Rostedt	}
353035ce5952SSteven Rostedt    }
353135ce5952SSteven Rostedt
35324c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
35334c4ab120SSteven Rostedt	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
35344c4ab120SSteven Rostedt    }
35354c4ab120SSteven Rostedt
353635ce5952SSteven Rostedt    my $temp_config = "$tmpdir/temp_config";
353735ce5952SSteven Rostedt
35384c4ab120SSteven Rostedt    # First things first. We build an allnoconfig to find
35394c4ab120SSteven Rostedt    # out what the defaults are that we can't touch.
35404c4ab120SSteven Rostedt    # Some are selections, but we really can't handle selections.
35414c4ab120SSteven Rostedt
35424c4ab120SSteven Rostedt    my $save_minconfig = $minconfig;
35434c4ab120SSteven Rostedt    undef $minconfig;
35444c4ab120SSteven Rostedt
35454c4ab120SSteven Rostedt    run_command "$make allnoconfig" or return 0;
35464c4ab120SSteven Rostedt
3547b9066f6cSSteven Rostedt    read_depends;
3548b9066f6cSSteven Rostedt
35494c4ab120SSteven Rostedt    process_config_ignore $output_config;
3550b9066f6cSSteven Rostedt
355143d1b651SSteven Rostedt    undef %save_configs;
3552b9066f6cSSteven Rostedt    undef %min_configs;
35534c4ab120SSteven Rostedt
35544c4ab120SSteven Rostedt    if (defined($ignore_config)) {
35554c4ab120SSteven Rostedt	# make sure the file exists
35564c4ab120SSteven Rostedt	`touch $ignore_config`;
355743d1b651SSteven Rostedt	assign_configs \%save_configs, $ignore_config;
35584c4ab120SSteven Rostedt    }
35594c4ab120SSteven Rostedt
356043d1b651SSteven Rostedt    %keep_configs = %save_configs;
356143d1b651SSteven Rostedt
35624c4ab120SSteven Rostedt    doprint "Load initial configs from $start_minconfig\n";
35634c4ab120SSteven Rostedt
35644c4ab120SSteven Rostedt    # Look at the current min configs, and save off all the
35654c4ab120SSteven Rostedt    # ones that were set via the allnoconfig
35664c4ab120SSteven Rostedt    assign_configs \%min_configs, $start_minconfig;
35674c4ab120SSteven Rostedt
35684c4ab120SSteven Rostedt    my @config_keys = keys %min_configs;
35694c4ab120SSteven Rostedt
3570ac6974c7SSteven Rostedt    # All configs need a depcount
3571ac6974c7SSteven Rostedt    foreach my $config (@config_keys) {
3572ac6974c7SSteven Rostedt	my $kconfig = chomp_config $config;
3573ac6974c7SSteven Rostedt	if (!defined $depcount{$kconfig}) {
3574ac6974c7SSteven Rostedt		$depcount{$kconfig} = 0;
3575ac6974c7SSteven Rostedt	}
3576ac6974c7SSteven Rostedt    }
3577ac6974c7SSteven Rostedt
35784c4ab120SSteven Rostedt    # Remove anything that was set by the make allnoconfig
35794c4ab120SSteven Rostedt    # we shouldn't need them as they get set for us anyway.
35804c4ab120SSteven Rostedt    foreach my $config (@config_keys) {
35814c4ab120SSteven Rostedt	# Remove anything in the ignore_config
35824c4ab120SSteven Rostedt	if (defined($keep_configs{$config})) {
35834c4ab120SSteven Rostedt	    my $file = $ignore_config;
35844c4ab120SSteven Rostedt	    $file =~ s,.*/(.*?)$,$1,;
35854c4ab120SSteven Rostedt	    doprint "$config set by $file ... ignored\n";
35864c4ab120SSteven Rostedt	    delete $min_configs{$config};
35874c4ab120SSteven Rostedt	    next;
35884c4ab120SSteven Rostedt	}
35894c4ab120SSteven Rostedt	# But make sure the settings are the same. If a min config
35904c4ab120SSteven Rostedt	# sets a selection, we do not want to get rid of it if
35914c4ab120SSteven Rostedt	# it is not the same as what we have. Just move it into
35924c4ab120SSteven Rostedt	# the keep configs.
35934c4ab120SSteven Rostedt	if (defined($config_ignore{$config})) {
35944c4ab120SSteven Rostedt	    if ($config_ignore{$config} ne $min_configs{$config}) {
35954c4ab120SSteven Rostedt		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
35964c4ab120SSteven Rostedt		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
35974c4ab120SSteven Rostedt		$keep_configs{$config} = $min_configs{$config};
35984c4ab120SSteven Rostedt	    } else {
35994c4ab120SSteven Rostedt		doprint "$config set by allnoconfig ... ignored\n";
36004c4ab120SSteven Rostedt	    }
36014c4ab120SSteven Rostedt	    delete $min_configs{$config};
36024c4ab120SSteven Rostedt	}
36034c4ab120SSteven Rostedt    }
36044c4ab120SSteven Rostedt
36054c4ab120SSteven Rostedt    my $done = 0;
3606b9066f6cSSteven Rostedt    my $take_two = 0;
36074c4ab120SSteven Rostedt
36084c4ab120SSteven Rostedt    while (!$done) {
36094c4ab120SSteven Rostedt
36104c4ab120SSteven Rostedt	my $config;
36114c4ab120SSteven Rostedt	my $found;
36124c4ab120SSteven Rostedt
36134c4ab120SSteven Rostedt	# Now disable each config one by one and do a make oldconfig
36144c4ab120SSteven Rostedt	# till we find a config that changes our list.
36154c4ab120SSteven Rostedt
36164c4ab120SSteven Rostedt	my @test_configs = keys %min_configs;
3617ac6974c7SSteven Rostedt
3618ac6974c7SSteven Rostedt	# Sort keys by who is most dependent on
3619ac6974c7SSteven Rostedt	@test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
3620ac6974c7SSteven Rostedt			  @test_configs ;
3621ac6974c7SSteven Rostedt
3622ac6974c7SSteven Rostedt	# Put configs that did not modify the config at the end.
36234c4ab120SSteven Rostedt	my $reset = 1;
36244c4ab120SSteven Rostedt	for (my $i = 0; $i < $#test_configs; $i++) {
36254c4ab120SSteven Rostedt	    if (!defined($nochange_config{$test_configs[0]})) {
36264c4ab120SSteven Rostedt		$reset = 0;
36274c4ab120SSteven Rostedt		last;
36284c4ab120SSteven Rostedt	    }
36294c4ab120SSteven Rostedt	    # This config didn't change the .config last time.
36304c4ab120SSteven Rostedt	    # Place it at the end
36314c4ab120SSteven Rostedt	    my $config = shift @test_configs;
36324c4ab120SSteven Rostedt	    push @test_configs, $config;
36334c4ab120SSteven Rostedt	}
36344c4ab120SSteven Rostedt
36354c4ab120SSteven Rostedt	# if every test config has failed to modify the .config file
36364c4ab120SSteven Rostedt	# in the past, then reset and start over.
36374c4ab120SSteven Rostedt	if ($reset) {
36384c4ab120SSteven Rostedt	    undef %nochange_config;
36394c4ab120SSteven Rostedt	}
36404c4ab120SSteven Rostedt
3641b9066f6cSSteven Rostedt	undef %processed_configs;
3642b9066f6cSSteven Rostedt
36434c4ab120SSteven Rostedt	foreach my $config (@test_configs) {
36444c4ab120SSteven Rostedt
3645b9066f6cSSteven Rostedt	    $found = test_this_config $config;
36464c4ab120SSteven Rostedt
3647b9066f6cSSteven Rostedt	    last if (defined($found));
36484c4ab120SSteven Rostedt
36494c4ab120SSteven Rostedt	    # oh well, try another config
36504c4ab120SSteven Rostedt	}
36514c4ab120SSteven Rostedt
36524c4ab120SSteven Rostedt	if (!defined($found)) {
3653b9066f6cSSteven Rostedt	    # we could have failed due to the nochange_config hash
3654b9066f6cSSteven Rostedt	    # reset and try again
3655b9066f6cSSteven Rostedt	    if (!$take_two) {
3656b9066f6cSSteven Rostedt		undef %nochange_config;
3657b9066f6cSSteven Rostedt		$take_two = 1;
3658b9066f6cSSteven Rostedt		next;
3659b9066f6cSSteven Rostedt	    }
36604c4ab120SSteven Rostedt	    doprint "No more configs found that we can disable\n";
36614c4ab120SSteven Rostedt	    $done = 1;
36624c4ab120SSteven Rostedt	    last;
36634c4ab120SSteven Rostedt	}
3664b9066f6cSSteven Rostedt	$take_two = 0;
36654c4ab120SSteven Rostedt
36664c4ab120SSteven Rostedt	$config = $found;
36674c4ab120SSteven Rostedt
36684c4ab120SSteven Rostedt	doprint "Test with $config disabled\n";
36694c4ab120SSteven Rostedt
36704c4ab120SSteven Rostedt	# set in_bisect to keep build and monitor from dieing
36714c4ab120SSteven Rostedt	$in_bisect = 1;
36724c4ab120SSteven Rostedt
36734c4ab120SSteven Rostedt	my $failed = 0;
3674bf1c95abSSteven Rostedt	build "oldconfig" or $failed = 1;
3675bf1c95abSSteven Rostedt	if (!$failed) {
36764c4ab120SSteven Rostedt		start_monitor_and_boot or $failed = 1;
3677ccc513b6SSteven Rostedt
3678ccc513b6SSteven Rostedt		if ($type eq "test" && !$failed) {
3679ccc513b6SSteven Rostedt		    do_run_test or $failed = 1;
3680ccc513b6SSteven Rostedt		}
3681ccc513b6SSteven Rostedt
36824c4ab120SSteven Rostedt		end_monitor;
3683bf1c95abSSteven Rostedt	}
36844c4ab120SSteven Rostedt
36854c4ab120SSteven Rostedt	$in_bisect = 0;
36864c4ab120SSteven Rostedt
36874c4ab120SSteven Rostedt	if ($failed) {
3688b9066f6cSSteven Rostedt	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
36894c4ab120SSteven Rostedt	    # this config is needed, add it to the ignore list.
36904c4ab120SSteven Rostedt	    $keep_configs{$config} = $min_configs{$config};
369143d1b651SSteven Rostedt	    $save_configs{$config} = $min_configs{$config};
36924c4ab120SSteven Rostedt	    delete $min_configs{$config};
369335ce5952SSteven Rostedt
369435ce5952SSteven Rostedt	    # update new ignore configs
369535ce5952SSteven Rostedt	    if (defined($ignore_config)) {
369635ce5952SSteven Rostedt		open (OUT, ">$temp_config")
369735ce5952SSteven Rostedt		    or die "Can't write to $temp_config";
369843d1b651SSteven Rostedt		foreach my $config (keys %save_configs) {
369943d1b651SSteven Rostedt		    print OUT "$save_configs{$config}\n";
370035ce5952SSteven Rostedt		}
370135ce5952SSteven Rostedt		close OUT;
370235ce5952SSteven Rostedt		run_command "mv $temp_config $ignore_config" or
370335ce5952SSteven Rostedt		    dodie "failed to copy update to $ignore_config";
370435ce5952SSteven Rostedt	    }
370535ce5952SSteven Rostedt
37064c4ab120SSteven Rostedt	} else {
37074c4ab120SSteven Rostedt	    # We booted without this config, remove it from the minconfigs.
37084c4ab120SSteven Rostedt	    doprint "$config is not needed, disabling\n";
37094c4ab120SSteven Rostedt
37104c4ab120SSteven Rostedt	    delete $min_configs{$config};
37114c4ab120SSteven Rostedt
37124c4ab120SSteven Rostedt	    # Also disable anything that is not enabled in this config
37134c4ab120SSteven Rostedt	    my %configs;
37144c4ab120SSteven Rostedt	    assign_configs \%configs, $output_config;
37154c4ab120SSteven Rostedt	    my @config_keys = keys %min_configs;
37164c4ab120SSteven Rostedt	    foreach my $config (@config_keys) {
37174c4ab120SSteven Rostedt		if (!defined($configs{$config})) {
37184c4ab120SSteven Rostedt		    doprint "$config is not set, disabling\n";
37194c4ab120SSteven Rostedt		    delete $min_configs{$config};
37204c4ab120SSteven Rostedt		}
37214c4ab120SSteven Rostedt	    }
37224c4ab120SSteven Rostedt
37234c4ab120SSteven Rostedt	    # Save off all the current mandidory configs
372435ce5952SSteven Rostedt	    open (OUT, ">$temp_config")
372535ce5952SSteven Rostedt		or die "Can't write to $temp_config";
37264c4ab120SSteven Rostedt	    foreach my $config (keys %keep_configs) {
37274c4ab120SSteven Rostedt		print OUT "$keep_configs{$config}\n";
37284c4ab120SSteven Rostedt	    }
37294c4ab120SSteven Rostedt	    foreach my $config (keys %min_configs) {
37304c4ab120SSteven Rostedt		print OUT "$min_configs{$config}\n";
37314c4ab120SSteven Rostedt	    }
37324c4ab120SSteven Rostedt	    close OUT;
373335ce5952SSteven Rostedt
373435ce5952SSteven Rostedt	    run_command "mv $temp_config $output_minconfig" or
373535ce5952SSteven Rostedt		dodie "failed to copy update to $output_minconfig";
37364c4ab120SSteven Rostedt	}
37374c4ab120SSteven Rostedt
37384c4ab120SSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
3739bc7c5803SSteven Rostedt	reboot_to_good $sleep_time;
37404c4ab120SSteven Rostedt    }
37414c4ab120SSteven Rostedt
37424c4ab120SSteven Rostedt    success $i;
37434c4ab120SSteven Rostedt    return 1;
37444c4ab120SSteven Rostedt}
37454c4ab120SSteven Rostedt
37464283b169SSteven Rostedt (Red Hat)sub make_warnings_file {
37474283b169SSteven Rostedt (Red Hat)    my ($i) = @_;
37484283b169SSteven Rostedt (Red Hat)
37494283b169SSteven Rostedt (Red Hat)    if (!defined($warnings_file)) {
37504283b169SSteven Rostedt (Red Hat)	dodie "Must define WARNINGS_FILE for make_warnings_file test";
37514283b169SSteven Rostedt (Red Hat)    }
37524283b169SSteven Rostedt (Red Hat)
37534283b169SSteven Rostedt (Red Hat)    if ($build_type eq "nobuild") {
37544283b169SSteven Rostedt (Red Hat)	dodie "BUILD_TYPE can not be 'nobuild' for make_warnings_file test";
37554283b169SSteven Rostedt (Red Hat)    }
37564283b169SSteven Rostedt (Red Hat)
37574283b169SSteven Rostedt (Red Hat)    build $build_type or dodie "Failed to build";
37584283b169SSteven Rostedt (Red Hat)
37594283b169SSteven Rostedt (Red Hat)    open(OUT, ">$warnings_file") or dodie "Can't create $warnings_file";
37604283b169SSteven Rostedt (Red Hat)
37614283b169SSteven Rostedt (Red Hat)    open(IN, $buildlog) or dodie "Can't open $buildlog";
37624283b169SSteven Rostedt (Red Hat)    while (<IN>) {
37634283b169SSteven Rostedt (Red Hat)
37644283b169SSteven Rostedt (Red Hat)	# Some compilers use UTF-8 extended for quotes
37654283b169SSteven Rostedt (Red Hat)	# for distcc heterogeneous systems, this causes issues
37664283b169SSteven Rostedt (Red Hat)	s/$utf8_quote/'/g;
37674283b169SSteven Rostedt (Red Hat)
37684283b169SSteven Rostedt (Red Hat)	if (/$check_build_re/) {
37694283b169SSteven Rostedt (Red Hat)	    print OUT;
37704283b169SSteven Rostedt (Red Hat)	}
37714283b169SSteven Rostedt (Red Hat)    }
37724283b169SSteven Rostedt (Red Hat)    close(IN);
37734283b169SSteven Rostedt (Red Hat)
37744283b169SSteven Rostedt (Red Hat)    close(OUT);
37754283b169SSteven Rostedt (Red Hat)
37764283b169SSteven Rostedt (Red Hat)    success $i;
37774283b169SSteven Rostedt (Red Hat)}
37784283b169SSteven Rostedt (Red Hat)
37798d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
37802545eb61SSteven Rostedt
37818d1491baSSteven Rostedtif ($#ARGV == 0) {
37828d1491baSSteven Rostedt    $ktest_config = $ARGV[0];
37838d1491baSSteven Rostedt    if (! -f $ktest_config) {
37848d1491baSSteven Rostedt	print "$ktest_config does not exist.\n";
378535ce5952SSteven Rostedt	if (!read_yn "Create it?") {
37868d1491baSSteven Rostedt	    exit 0;
37878d1491baSSteven Rostedt	}
37888d1491baSSteven Rostedt    }
37898d1491baSSteven Rostedt} else {
37908d1491baSSteven Rostedt    $ktest_config = "ktest.conf";
37918d1491baSSteven Rostedt}
37928d1491baSSteven Rostedt
37938d1491baSSteven Rostedtif (! -f $ktest_config) {
3794dbd3783bSSteven Rostedt    $newconfig = 1;
3795c4261d0fSSteven Rostedt    get_test_case;
37968d1491baSSteven Rostedt    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
37978d1491baSSteven Rostedt    print OUT << "EOF"
37988d1491baSSteven Rostedt# Generated by ktest.pl
37998d1491baSSteven Rostedt#
38000e7a22deSSteven Rostedt
38010e7a22deSSteven Rostedt# PWD is a ktest.pl variable that will result in the process working
38020e7a22deSSteven Rostedt# directory that ktest.pl is executed in.
38030e7a22deSSteven Rostedt
38040e7a22deSSteven Rostedt# THIS_DIR is automatically assigned the PWD of the path that generated
38050e7a22deSSteven Rostedt# the config file. It is best to use this variable when assigning other
38060e7a22deSSteven Rostedt# directory paths within this directory. This allows you to easily
38070e7a22deSSteven Rostedt# move the test cases to other locations or to other machines.
38080e7a22deSSteven Rostedt#
38090e7a22deSSteven RostedtTHIS_DIR := $variable{"PWD"}
38100e7a22deSSteven Rostedt
38118d1491baSSteven Rostedt# Define each test with TEST_START
38128d1491baSSteven Rostedt# The config options below it will override the defaults
38138d1491baSSteven RostedtTEST_START
3814c4261d0fSSteven RostedtTEST_TYPE = $default{"TEST_TYPE"}
38158d1491baSSteven Rostedt
38168d1491baSSteven RostedtDEFAULTS
38178d1491baSSteven RostedtEOF
38188d1491baSSteven Rostedt;
38198d1491baSSteven Rostedt    close(OUT);
38208d1491baSSteven Rostedt}
38218d1491baSSteven Rostedtread_config $ktest_config;
38228d1491baSSteven Rostedt
382323715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) {
382404262be3SSteven Rostedt (Red Hat)    $opt{"LOG_FILE"} = eval_option("LOG_FILE", $opt{"LOG_FILE"}, -1);
382523715c3cSSteven Rostedt}
382623715c3cSSteven Rostedt
38278d1491baSSteven Rostedt# Append any configs entered in manually to the config file.
38288d1491baSSteven Rostedtmy @new_configs = keys %entered_configs;
38298d1491baSSteven Rostedtif ($#new_configs >= 0) {
38308d1491baSSteven Rostedt    print "\nAppending entered in configs to $ktest_config\n";
38318d1491baSSteven Rostedt    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
38328d1491baSSteven Rostedt    foreach my $config (@new_configs) {
38338d1491baSSteven Rostedt	print OUT "$config = $entered_configs{$config}\n";
38340e7a22deSSteven Rostedt	$opt{$config} = process_variables($entered_configs{$config});
38358d1491baSSteven Rostedt    }
38368d1491baSSteven Rostedt}
38372545eb61SSteven Rostedt
38382b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
38392b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
38402b7d9b21SSteven Rostedt}
38412545eb61SSteven Rostedt
38422b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
38432b7d9b21SSteven Rostedt
3844a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
3845a57419b3SSteven Rostedt
3846a57419b3SSteven Rostedt    if (!$i) {
3847a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
3848a57419b3SSteven Rostedt    } else {
3849a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
3850a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
3851a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
3852a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
3853a57419b3SSteven Rostedt	}
3854a57419b3SSteven Rostedt	doprint "\n";
3855a57419b3SSteven Rostedt    }
3856a57419b3SSteven Rostedt
38572b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
3858a57419b3SSteven Rostedt
3859a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
3860a57419b3SSteven Rostedt	    next if ($i != $1);
3861a57419b3SSteven Rostedt	} else {
3862a57419b3SSteven Rostedt	    next if ($i);
3863a57419b3SSteven Rostedt	}
3864a57419b3SSteven Rostedt
38652b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
38662b7d9b21SSteven Rostedt    }
3867a57419b3SSteven Rostedt}
38682545eb61SSteven Rostedt
38692a62512bSSteven Rostedtsub __set_test_option {
38705a391fbfSSteven Rostedt    my ($name, $i) = @_;
38715a391fbfSSteven Rostedt
38725a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
38735a391fbfSSteven Rostedt
38745a391fbfSSteven Rostedt    if (defined($opt{$option})) {
38755a391fbfSSteven Rostedt	return $opt{$option};
38765a391fbfSSteven Rostedt    }
38775a391fbfSSteven Rostedt
3878a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
3879a57419b3SSteven Rostedt	if ($i >= $test &&
3880a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
3881a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
3882a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
3883a57419b3SSteven Rostedt		return $opt{$option};
3884a57419b3SSteven Rostedt	    }
3885a57419b3SSteven Rostedt	}
3886a57419b3SSteven Rostedt    }
3887a57419b3SSteven Rostedt
38885a391fbfSSteven Rostedt    if (defined($opt{$name})) {
38895a391fbfSSteven Rostedt	return $opt{$name};
38905a391fbfSSteven Rostedt    }
38915a391fbfSSteven Rostedt
38925a391fbfSSteven Rostedt    return undef;
38935a391fbfSSteven Rostedt}
38945a391fbfSSteven Rostedt
38952a62512bSSteven Rostedtsub set_test_option {
38962a62512bSSteven Rostedt    my ($name, $i) = @_;
38972a62512bSSteven Rostedt
38982a62512bSSteven Rostedt    my $option = __set_test_option($name, $i);
38992a62512bSSteven Rostedt    return $option if (!defined($option));
39002a62512bSSteven Rostedt
390104262be3SSteven Rostedt (Red Hat)    return eval_option($name, $option, $i);
39022a62512bSSteven Rostedt}
39032a62512bSSteven Rostedt
39042545eb61SSteven Rostedt# First we need to do is the builds
3905a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
39062545eb61SSteven Rostedt
39074ab1cce5SSteven Rostedt    # Do not reboot on failing test options
39084ab1cce5SSteven Rostedt    $no_reboot = 1;
3909759a3cc6SSteven Rostedt    $reboot_success = 0;
39104ab1cce5SSteven Rostedt
3911683a3e64SSteven Rostedt    $have_version = 0;
3912683a3e64SSteven Rostedt
3913576f627cSSteven Rostedt    $iteration = $i;
3914576f627cSSteven Rostedt
3915c1434dccSSteven Rostedt    undef %force_config;
3916c1434dccSSteven Rostedt
3917a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
3918a75fececSSteven Rostedt
39199cc9e091SSteven Rostedt    # Load all the options into their mapped variable names
39209cc9e091SSteven Rostedt    foreach my $opt (keys %option_map) {
39219cc9e091SSteven Rostedt	${$option_map{$opt}} = set_test_option($opt, $i);
39229cc9e091SSteven Rostedt    }
3923b5f4aea6SSteven Rostedt
392435ce5952SSteven Rostedt    $start_minconfig_defined = 1;
392535ce5952SSteven Rostedt
3926921ed4c7SSteven Rostedt    # The first test may override the PRE_KTEST option
3927921ed4c7SSteven Rostedt    if (defined($pre_ktest) && $i == 1) {
3928921ed4c7SSteven Rostedt	doprint "\n";
3929921ed4c7SSteven Rostedt	run_command $pre_ktest;
3930921ed4c7SSteven Rostedt    }
3931921ed4c7SSteven Rostedt
3932921ed4c7SSteven Rostedt    # Any test can override the POST_KTEST option
3933921ed4c7SSteven Rostedt    # The last test takes precedence.
3934921ed4c7SSteven Rostedt    if (defined($post_ktest)) {
3935921ed4c7SSteven Rostedt	$final_post_ktest = $post_ktest;
3936921ed4c7SSteven Rostedt    }
3937921ed4c7SSteven Rostedt
39384c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
393935ce5952SSteven Rostedt	$start_minconfig_defined = 0;
39404c4ab120SSteven Rostedt	$start_minconfig = $minconfig;
39414c4ab120SSteven Rostedt    }
39424c4ab120SSteven Rostedt
3943a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
3944a75fececSSteven Rostedt
3945a908a665SAndrew Jones    foreach my $dir ($tmpdir, $outputdir) {
3946a908a665SAndrew Jones	if (!-d $dir) {
3947a908a665SAndrew Jones	    mkpath($dir) or
3948a908a665SAndrew Jones		die "can't create $dir";
3949a908a665SAndrew Jones	}
3950a75fececSSteven Rostedt    }
3951a75fececSSteven Rostedt
3952e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
3953e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
3954e48c5293SSteven Rostedt
3955a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
3956a9dd5d63SRabin Vincent    $testlog = "$tmpdir/testlog-$machine";
3957a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
3958a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
395951ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
3960a75fececSSteven Rostedt
3961bb8474b1SSteven Rostedt    if (!$buildonly) {
3962bb8474b1SSteven Rostedt	$target = "$ssh_user\@$machine";
3963a75fececSSteven Rostedt	if ($reboot_type eq "grub") {
3964576f627cSSteven Rostedt	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3965a15ba913SSteven Rostedt	} elsif ($reboot_type eq "grub2") {
3966a15ba913SSteven Rostedt	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3967a15ba913SSteven Rostedt	    dodie "GRUB_FILE not defined" if (!defined($grub_file));
39687786954cSSteven Rostedt	} elsif ($reboot_type eq "syslinux") {
39697786954cSSteven Rostedt	    dodie "SYSLINUX_LABEL not defined" if (!defined($syslinux_label));
3970a75fececSSteven Rostedt	}
3971bb8474b1SSteven Rostedt    }
3972a75fececSSteven Rostedt
3973a75fececSSteven Rostedt    my $run_type = $build_type;
3974a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
3975b5f4aea6SSteven Rostedt	$run_type = $patchcheck_type;
3976a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
3977b5f4aea6SSteven Rostedt	$run_type = $bisect_type;
39780a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
3979b5f4aea6SSteven Rostedt	$run_type = $config_bisect_type;
39804283b169SSteven Rostedt (Red Hat)    } elsif ($test_type eq "make_min_config") {
39814283b169SSteven Rostedt (Red Hat)	$run_type = "";
39824283b169SSteven Rostedt (Red Hat)    } elsif ($test_type eq "make_warnings_file") {
39834c4ab120SSteven Rostedt	$run_type = "";
39844c4ab120SSteven Rostedt    }
39854c4ab120SSteven Rostedt
3986a75fececSSteven Rostedt    # mistake in config file?
3987a75fececSSteven Rostedt    if (!defined($run_type)) {
3988a75fececSSteven Rostedt	$run_type = "ERROR";
3989a75fececSSteven Rostedt    }
39902545eb61SSteven Rostedt
3991e0a8742eSSteven Rostedt    my $installme = "";
3992e0a8742eSSteven Rostedt    $installme = " no_install" if ($no_install);
3993e0a8742eSSteven Rostedt
39942545eb61SSteven Rostedt    doprint "\n\n";
3995e0a8742eSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
39967faafbd6SSteven Rostedt
3997921ed4c7SSteven Rostedt    if (defined($pre_test)) {
3998921ed4c7SSteven Rostedt	run_command $pre_test;
3999921ed4c7SSteven Rostedt    }
4000921ed4c7SSteven Rostedt
40017faafbd6SSteven Rostedt    unlink $dmesg;
40027faafbd6SSteven Rostedt    unlink $buildlog;
4003a9dd5d63SRabin Vincent    unlink $testlog;
40042545eb61SSteven Rostedt
4005250bae8bSSteven Rostedt    if (defined($addconfig)) {
4006250bae8bSSteven Rostedt	my $min = $minconfig;
40072b7d9b21SSteven Rostedt	if (!defined($minconfig)) {
4008250bae8bSSteven Rostedt	    $min = "";
4009250bae8bSSteven Rostedt	}
4010250bae8bSSteven Rostedt	run_command "cat $addconfig $min > $tmpdir/add_config" or
40112b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
40129be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
40132b7d9b21SSteven Rostedt    }
40142b7d9b21SSteven Rostedt
40156c5ee0beSSteven Rostedt    if (defined($checkout)) {
40166c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
40176c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
40186c5ee0beSSteven Rostedt    }
40196c5ee0beSSteven Rostedt
4020759a3cc6SSteven Rostedt    $no_reboot = 0;
4021759a3cc6SSteven Rostedt
4022648a182cSSteven Rostedt    # A test may opt to not reboot the box
4023648a182cSSteven Rostedt    if ($reboot_on_success) {
4024759a3cc6SSteven Rostedt	$reboot_success = 1;
4025648a182cSSteven Rostedt    }
40264ab1cce5SSteven Rostedt
4027a75fececSSteven Rostedt    if ($test_type eq "bisect") {
40285f9b6cedSSteven Rostedt	bisect $i;
40295f9b6cedSSteven Rostedt	next;
40300a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
40310a05c769SSteven Rostedt	config_bisect $i;
40320a05c769SSteven Rostedt	next;
4033a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
40346c5ee0beSSteven Rostedt	patchcheck $i;
40356c5ee0beSSteven Rostedt	next;
40364c4ab120SSteven Rostedt    } elsif ($test_type eq "make_min_config") {
40374c4ab120SSteven Rostedt	make_min_config $i;
40384c4ab120SSteven Rostedt	next;
40394283b169SSteven Rostedt (Red Hat)    } elsif ($test_type eq "make_warnings_file") {
40404283b169SSteven Rostedt (Red Hat)	$no_reboot = 1;
40414283b169SSteven Rostedt (Red Hat)	make_warnings_file $i;
40424283b169SSteven Rostedt (Red Hat)	next;
40435f9b6cedSSteven Rostedt    }
40445f9b6cedSSteven Rostedt
40457faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
40467faafbd6SSteven Rostedt	build $build_type or next;
40474283b169SSteven Rostedt (Red Hat)	check_buildlog or next;
40482545eb61SSteven Rostedt    }
40492545eb61SSteven Rostedt
4050cd8e368fSSteven Rostedt    if ($test_type eq "install") {
4051cd8e368fSSteven Rostedt	get_version;
4052cd8e368fSSteven Rostedt	install;
4053cd8e368fSSteven Rostedt	success $i;
4054cd8e368fSSteven Rostedt	next;
4055cd8e368fSSteven Rostedt    }
4056cd8e368fSSteven Rostedt
4057a75fececSSteven Rostedt    if ($test_type ne "build") {
40587faafbd6SSteven Rostedt	my $failed = 0;
4059ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
4060a75fececSSteven Rostedt
4061a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
40627faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
40635a391fbfSSteven Rostedt	}
40647faafbd6SSteven Rostedt	end_monitor;
40657faafbd6SSteven Rostedt	next if ($failed);
4066a75fececSSteven Rostedt    }
40675a391fbfSSteven Rostedt
40685f9b6cedSSteven Rostedt    success $i;
406975c3fda7SSteven Rostedt}
40702545eb61SSteven Rostedt
4071921ed4c7SSteven Rostedtif (defined($final_post_ktest)) {
4072921ed4c7SSteven Rostedt    run_command $final_post_ktest;
4073921ed4c7SSteven Rostedt}
4074921ed4c7SSteven Rostedt
40755c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
407675c3fda7SSteven Rostedt    halt;
4077759a3cc6SSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) {
4078bc7c5803SSteven Rostedt    reboot_to_good;
4079648a182cSSteven Rostedt} elsif (defined($switch_to_good)) {
4080648a182cSSteven Rostedt    # still need to get to the good kernel
4081648a182cSSteven Rostedt    run_command $switch_to_good;
40825c42fc5bSSteven Rostedt}
408375c3fda7SSteven Rostedt
4084648a182cSSteven Rostedt
4085e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
4086e48c5293SSteven Rostedt
40872545eb61SSteven Rostedtexit 0;
4088