xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision 7328735cbf68b7cd4d7ef16e172013743cdc2bc4)
12545eb61SSteven Rostedt#!/usr/bin/perl -w
2d6ce2a0bSSteven Rostedt#
3cce1dac8SUwe Kleine-König# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
4d6ce2a0bSSteven Rostedt# Licensed under the terms of the GNU GPL License version 2
5d6ce2a0bSSteven Rostedt#
62545eb61SSteven Rostedt
72545eb61SSteven Rostedtuse strict;
82545eb61SSteven Rostedtuse IPC::Open2;
92545eb61SSteven Rostedtuse Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
107faafbd6SSteven Rostedtuse File::Path qw(mkpath);
117faafbd6SSteven Rostedtuse File::Copy qw(cp);
122545eb61SSteven Rostedtuse FileHandle;
132545eb61SSteven Rostedt
14e48c5293SSteven Rostedtmy $VERSION = "0.2";
15e48c5293SSteven Rostedt
162545eb61SSteven Rostedt$| = 1;
172545eb61SSteven Rostedt
182545eb61SSteven Rostedtmy %opt;
19a57419b3SSteven Rostedtmy %repeat_tests;
20a57419b3SSteven Rostedtmy %repeats;
212545eb61SSteven Rostedt
222545eb61SSteven Rostedt#default opts
234f43e0dcSSteven Rostedtmy %default = (
244f43e0dcSSteven Rostedt    "NUM_TESTS"			=> 1,
254f43e0dcSSteven Rostedt    "TEST_TYPE"			=> "build",
264f43e0dcSSteven Rostedt    "BUILD_TYPE"		=> "randconfig",
274f43e0dcSSteven Rostedt    "MAKE_CMD"			=> "make",
284f43e0dcSSteven Rostedt    "TIMEOUT"			=> 120,
294f43e0dcSSteven Rostedt    "TMP_DIR"			=> "/tmp/ktest/\${MACHINE}",
304f43e0dcSSteven Rostedt    "SLEEP_TIME"		=> 60,	# sleep time between tests
314f43e0dcSSteven Rostedt    "BUILD_NOCLEAN"		=> 0,
324f43e0dcSSteven Rostedt    "REBOOT_ON_ERROR"		=> 0,
334f43e0dcSSteven Rostedt    "POWEROFF_ON_ERROR"		=> 0,
344f43e0dcSSteven Rostedt    "REBOOT_ON_SUCCESS"		=> 1,
354f43e0dcSSteven Rostedt    "POWEROFF_ON_SUCCESS"	=> 0,
364f43e0dcSSteven Rostedt    "BUILD_OPTIONS"		=> "",
374f43e0dcSSteven Rostedt    "BISECT_SLEEP_TIME"		=> 60,   # sleep time between bisects
384f43e0dcSSteven Rostedt    "PATCHCHECK_SLEEP_TIME"	=> 60, # sleep time between patch checks
394f43e0dcSSteven Rostedt    "CLEAR_LOG"			=> 0,
404f43e0dcSSteven Rostedt    "BISECT_MANUAL"		=> 0,
414f43e0dcSSteven Rostedt    "BISECT_SKIP"		=> 1,
42ccc513b6SSteven Rostedt    "MIN_CONFIG_TYPE"		=> "boot",
434f43e0dcSSteven Rostedt    "SUCCESS_LINE"		=> "login:",
444f43e0dcSSteven Rostedt    "DETECT_TRIPLE_FAULT"	=> 1,
454f43e0dcSSteven Rostedt    "NO_INSTALL"		=> 0,
464f43e0dcSSteven Rostedt    "BOOTED_TIMEOUT"		=> 1,
474f43e0dcSSteven Rostedt    "DIE_ON_FAILURE"		=> 1,
484f43e0dcSSteven Rostedt    "SSH_EXEC"			=> "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND",
494f43e0dcSSteven Rostedt    "SCP_TO_TARGET"		=> "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE",
5002ad2617SSteven Rostedt    "SCP_TO_TARGET_INSTALL"	=> "\${SCP_TO_TARGET}",
514f43e0dcSSteven Rostedt    "REBOOT"			=> "ssh \$SSH_USER\@\$MACHINE reboot",
524f43e0dcSSteven Rostedt    "STOP_AFTER_SUCCESS"	=> 10,
534f43e0dcSSteven Rostedt    "STOP_AFTER_FAILURE"	=> 60,
544f43e0dcSSteven Rostedt    "STOP_TEST_AFTER"		=> 600,
55407b95b7SSteven Rostedt    "MAX_MONITOR_WAIT"		=> 1800,
56a15ba913SSteven Rostedt    "GRUB_REBOOT"		=> "grub2-reboot",
577786954cSSteven Rostedt    "SYSLINUX"			=> "extlinux",
587786954cSSteven Rostedt    "SYSLINUX_PATH"		=> "/boot/extlinux",
59600bbf0aSSteven Rostedt
60600bbf0aSSteven Rostedt# required, and we will ask users if they don't have them but we keep the default
61600bbf0aSSteven Rostedt# value something that is common.
624f43e0dcSSteven Rostedt    "REBOOT_TYPE"		=> "grub",
634f43e0dcSSteven Rostedt    "LOCALVERSION"		=> "-test",
644f43e0dcSSteven Rostedt    "SSH_USER"			=> "root",
654f43e0dcSSteven Rostedt    "BUILD_TARGET"	 	=> "arch/x86/boot/bzImage",
664f43e0dcSSteven Rostedt    "TARGET_IMAGE"		=> "/boot/vmlinuz-test",
679cc9e091SSteven Rostedt
689cc9e091SSteven Rostedt    "LOG_FILE"			=> undef,
699cc9e091SSteven Rostedt    "IGNORE_UNUSED"		=> 0,
704f43e0dcSSteven Rostedt);
712545eb61SSteven Rostedt
728d1491baSSteven Rostedtmy $ktest_config;
732545eb61SSteven Rostedtmy $version;
74683a3e64SSteven Rostedtmy $have_version = 0;
75a75fececSSteven Rostedtmy $machine;
76e48c5293SSteven Rostedtmy $ssh_user;
77a75fececSSteven Rostedtmy $tmpdir;
78a75fececSSteven Rostedtmy $builddir;
79a75fececSSteven Rostedtmy $outputdir;
8051ad1dd1SSteven Rostedtmy $output_config;
81a75fececSSteven Rostedtmy $test_type;
827faafbd6SSteven Rostedtmy $build_type;
83a75fececSSteven Rostedtmy $build_options;
84921ed4c7SSteven Rostedtmy $final_post_ktest;
85921ed4c7SSteven Rostedtmy $pre_ktest;
86921ed4c7SSteven Rostedtmy $post_ktest;
87921ed4c7SSteven Rostedtmy $pre_test;
88921ed4c7SSteven Rostedtmy $post_test;
890bd6c1a3SSteven Rostedtmy $pre_build;
900bd6c1a3SSteven Rostedtmy $post_build;
910bd6c1a3SSteven Rostedtmy $pre_build_die;
920bd6c1a3SSteven Rostedtmy $post_build_die;
93a75fececSSteven Rostedtmy $reboot_type;
94a75fececSSteven Rostedtmy $reboot_script;
95a75fececSSteven Rostedtmy $power_cycle;
96e48c5293SSteven Rostedtmy $reboot;
97a75fececSSteven Rostedtmy $reboot_on_error;
98bc7c5803SSteven Rostedtmy $switch_to_good;
99bc7c5803SSteven Rostedtmy $switch_to_test;
100a75fececSSteven Rostedtmy $poweroff_on_error;
101648a182cSSteven Rostedtmy $reboot_on_success;
102a75fececSSteven Rostedtmy $die_on_failure;
103576f627cSSteven Rostedtmy $powercycle_after_reboot;
104576f627cSSteven Rostedtmy $poweroff_after_halt;
105407b95b7SSteven Rostedtmy $max_monitor_wait;
106e48c5293SSteven Rostedtmy $ssh_exec;
107e48c5293SSteven Rostedtmy $scp_to_target;
10802ad2617SSteven Rostedtmy $scp_to_target_install;
109a75fececSSteven Rostedtmy $power_off;
110a75fececSSteven Rostedtmy $grub_menu;
111a15ba913SSteven Rostedtmy $grub_file;
1122545eb61SSteven Rostedtmy $grub_number;
113a15ba913SSteven Rostedtmy $grub_reboot;
1147786954cSSteven Rostedtmy $syslinux;
1157786954cSSteven Rostedtmy $syslinux_path;
1167786954cSSteven Rostedtmy $syslinux_label;
1172545eb61SSteven Rostedtmy $target;
1182545eb61SSteven Rostedtmy $make;
119e5c2ec11SSteven Rostedtmy $pre_install;
1208b37ca8cSSteven Rostedtmy $post_install;
121e0a8742eSSteven Rostedtmy $no_install;
1225c42fc5bSSteven Rostedtmy $noclean;
1235f9b6cedSSteven Rostedtmy $minconfig;
1244c4ab120SSteven Rostedtmy $start_minconfig;
12535ce5952SSteven Rostedtmy $start_minconfig_defined;
1264c4ab120SSteven Rostedtmy $output_minconfig;
127ccc513b6SSteven Rostedtmy $minconfig_type;
12843de3316SSteven Rostedtmy $use_output_minconfig;
1294283b169SSteven Rostedt (Red Hat)my $warnings_file;
1304c4ab120SSteven Rostedtmy $ignore_config;
131be405f95SSteven Rostedtmy $ignore_errors;
1322b7d9b21SSteven Rostedtmy $addconfig;
1335f9b6cedSSteven Rostedtmy $in_bisect = 0;
134b5f4aea6SSteven Rostedtmy $bisect_bad_commit = "";
135d6ce2a0bSSteven Rostedtmy $reverse_bisect;
136c960bb9fSSteven Rostedtmy $bisect_manual;
137c23dca7cSSteven Rostedtmy $bisect_skip;
13830f75da5SSteven Rostedtmy $config_bisect_good;
139c5dacb88SSteven Rostedtmy $bisect_ret_good;
140c5dacb88SSteven Rostedtmy $bisect_ret_bad;
141c5dacb88SSteven Rostedtmy $bisect_ret_skip;
142c5dacb88SSteven Rostedtmy $bisect_ret_abort;
143c5dacb88SSteven Rostedtmy $bisect_ret_default;
1446c5ee0beSSteven Rostedtmy $in_patchcheck = 0;
1455a391fbfSSteven Rostedtmy $run_test;
1466c5ee0beSSteven Rostedtmy $redirect;
1477faafbd6SSteven Rostedtmy $buildlog;
148a9dd5d63SRabin Vincentmy $testlog;
1497faafbd6SSteven Rostedtmy $dmesg;
1507faafbd6SSteven Rostedtmy $monitor_fp;
1517faafbd6SSteven Rostedtmy $monitor_pid;
1527faafbd6SSteven Rostedtmy $monitor_cnt = 0;
153a75fececSSteven Rostedtmy $sleep_time;
154a75fececSSteven Rostedtmy $bisect_sleep_time;
15527d934b2SSteven Rostedtmy $patchcheck_sleep_time;
1561990207dSSteven Rostedtmy $ignore_warnings;
157a75fececSSteven Rostedtmy $store_failures;
158de5b6e3bSRabin Vincentmy $store_successes;
1599064af52SSteven Rostedtmy $test_name;
160a75fececSSteven Rostedtmy $timeout;
161a75fececSSteven Rostedtmy $booted_timeout;
162f1a5b962SSteven Rostedtmy $detect_triplefault;
163a75fececSSteven Rostedtmy $console;
1642b803365SSteven Rostedtmy $reboot_success_line;
165a75fececSSteven Rostedtmy $success_line;
1661c8a617aSSteven Rostedtmy $stop_after_success;
1671c8a617aSSteven Rostedtmy $stop_after_failure;
1682d01b26aSSteven Rostedtmy $stop_test_after;
169a75fececSSteven Rostedtmy $build_target;
170a75fececSSteven Rostedtmy $target_image;
171b5f4aea6SSteven Rostedtmy $checkout;
172a75fececSSteven Rostedtmy $localversion;
173576f627cSSteven Rostedtmy $iteration = 0;
174e48c5293SSteven Rostedtmy $successes = 0;
1752545eb61SSteven Rostedt
176b5f4aea6SSteven Rostedtmy $bisect_good;
177b5f4aea6SSteven Rostedtmy $bisect_bad;
178b5f4aea6SSteven Rostedtmy $bisect_type;
179b5f4aea6SSteven Rostedtmy $bisect_start;
180b5f4aea6SSteven Rostedtmy $bisect_replay;
181b5f4aea6SSteven Rostedtmy $bisect_files;
182b5f4aea6SSteven Rostedtmy $bisect_reverse;
183b5f4aea6SSteven Rostedtmy $bisect_check;
184b5f4aea6SSteven Rostedt
185b5f4aea6SSteven Rostedtmy $config_bisect;
186b5f4aea6SSteven Rostedtmy $config_bisect_type;
187b0918612SSteven Rostedtmy $config_bisect_check;
188b5f4aea6SSteven Rostedt
189b5f4aea6SSteven Rostedtmy $patchcheck_type;
190b5f4aea6SSteven Rostedtmy $patchcheck_start;
191b5f4aea6SSteven Rostedtmy $patchcheck_end;
192b5f4aea6SSteven Rostedt
193165708b2SSteven Rostedt# set when a test is something other that just building or install
194bb8474b1SSteven Rostedt# which would require more options.
195bb8474b1SSteven Rostedtmy $buildonly = 1;
196bb8474b1SSteven Rostedt
1974283b169SSteven Rostedt (Red Hat)# tell build not to worry about warnings, even when WARNINGS_FILE is set
1984283b169SSteven Rostedt (Red Hat)my $warnings_ok = 0;
1994283b169SSteven Rostedt (Red Hat)
200dbd3783bSSteven Rostedt# set when creating a new config
201dbd3783bSSteven Rostedtmy $newconfig = 0;
202dbd3783bSSteven Rostedt
2038d1491baSSteven Rostedtmy %entered_configs;
2048d1491baSSteven Rostedtmy %config_help;
20577d942ceSSteven Rostedtmy %variable;
206cf79fab6SSteven Rostedt
207cf79fab6SSteven Rostedt# force_config is the list of configs that we force enabled (or disabled)
208cf79fab6SSteven Rostedt# in a .config file. The MIN_CONFIG and ADD_CONFIG configs.
209fcb3f16aSSteven Rostedtmy %force_config;
2108d1491baSSteven Rostedt
2114ab1cce5SSteven Rostedt# do not force reboots on config problems
2124ab1cce5SSteven Rostedtmy $no_reboot = 1;
2134ab1cce5SSteven Rostedt
214759a3cc6SSteven Rostedt# reboot on success
215759a3cc6SSteven Rostedtmy $reboot_success = 0;
216759a3cc6SSteven Rostedt
2179cc9e091SSteven Rostedtmy %option_map = (
2189cc9e091SSteven Rostedt    "MACHINE"			=> \$machine,
2199cc9e091SSteven Rostedt    "SSH_USER"			=> \$ssh_user,
2209cc9e091SSteven Rostedt    "TMP_DIR"			=> \$tmpdir,
2219cc9e091SSteven Rostedt    "OUTPUT_DIR"		=> \$outputdir,
2229cc9e091SSteven Rostedt    "BUILD_DIR"			=> \$builddir,
2239cc9e091SSteven Rostedt    "TEST_TYPE"			=> \$test_type,
224921ed4c7SSteven Rostedt    "PRE_KTEST"			=> \$pre_ktest,
225921ed4c7SSteven Rostedt    "POST_KTEST"		=> \$post_ktest,
226921ed4c7SSteven Rostedt    "PRE_TEST"			=> \$pre_test,
227921ed4c7SSteven Rostedt    "POST_TEST"			=> \$post_test,
2289cc9e091SSteven Rostedt    "BUILD_TYPE"		=> \$build_type,
2299cc9e091SSteven Rostedt    "BUILD_OPTIONS"		=> \$build_options,
2309cc9e091SSteven Rostedt    "PRE_BUILD"			=> \$pre_build,
2319cc9e091SSteven Rostedt    "POST_BUILD"		=> \$post_build,
2329cc9e091SSteven Rostedt    "PRE_BUILD_DIE"		=> \$pre_build_die,
2339cc9e091SSteven Rostedt    "POST_BUILD_DIE"		=> \$post_build_die,
2349cc9e091SSteven Rostedt    "POWER_CYCLE"		=> \$power_cycle,
2359cc9e091SSteven Rostedt    "REBOOT"			=> \$reboot,
2369cc9e091SSteven Rostedt    "BUILD_NOCLEAN"		=> \$noclean,
2379cc9e091SSteven Rostedt    "MIN_CONFIG"		=> \$minconfig,
2389cc9e091SSteven Rostedt    "OUTPUT_MIN_CONFIG"		=> \$output_minconfig,
2399cc9e091SSteven Rostedt    "START_MIN_CONFIG"		=> \$start_minconfig,
240ccc513b6SSteven Rostedt    "MIN_CONFIG_TYPE"		=> \$minconfig_type,
24143de3316SSteven Rostedt    "USE_OUTPUT_MIN_CONFIG"	=> \$use_output_minconfig,
2424283b169SSteven Rostedt (Red Hat)    "WARNINGS_FILE"		=> \$warnings_file,
2439cc9e091SSteven Rostedt    "IGNORE_CONFIG"		=> \$ignore_config,
2449cc9e091SSteven Rostedt    "TEST"			=> \$run_test,
2459cc9e091SSteven Rostedt    "ADD_CONFIG"		=> \$addconfig,
2469cc9e091SSteven Rostedt    "REBOOT_TYPE"		=> \$reboot_type,
2479cc9e091SSteven Rostedt    "GRUB_MENU"			=> \$grub_menu,
248a15ba913SSteven Rostedt    "GRUB_FILE"			=> \$grub_file,
249a15ba913SSteven Rostedt    "GRUB_REBOOT"		=> \$grub_reboot,
2507786954cSSteven Rostedt    "SYSLINUX"			=> \$syslinux,
2517786954cSSteven Rostedt    "SYSLINUX_PATH"		=> \$syslinux_path,
2527786954cSSteven Rostedt    "SYSLINUX_LABEL"		=> \$syslinux_label,
253e5c2ec11SSteven Rostedt    "PRE_INSTALL"		=> \$pre_install,
2549cc9e091SSteven Rostedt    "POST_INSTALL"		=> \$post_install,
2559cc9e091SSteven Rostedt    "NO_INSTALL"		=> \$no_install,
2569cc9e091SSteven Rostedt    "REBOOT_SCRIPT"		=> \$reboot_script,
2579cc9e091SSteven Rostedt    "REBOOT_ON_ERROR"		=> \$reboot_on_error,
2589cc9e091SSteven Rostedt    "SWITCH_TO_GOOD"		=> \$switch_to_good,
2599cc9e091SSteven Rostedt    "SWITCH_TO_TEST"		=> \$switch_to_test,
2609cc9e091SSteven Rostedt    "POWEROFF_ON_ERROR"		=> \$poweroff_on_error,
261648a182cSSteven Rostedt    "REBOOT_ON_SUCCESS"		=> \$reboot_on_success,
2629cc9e091SSteven Rostedt    "DIE_ON_FAILURE"		=> \$die_on_failure,
2639cc9e091SSteven Rostedt    "POWER_OFF"			=> \$power_off,
2649cc9e091SSteven Rostedt    "POWERCYCLE_AFTER_REBOOT"	=> \$powercycle_after_reboot,
2659cc9e091SSteven Rostedt    "POWEROFF_AFTER_HALT"	=> \$poweroff_after_halt,
266407b95b7SSteven Rostedt    "MAX_MONITOR_WAIT"		=> \$max_monitor_wait,
2679cc9e091SSteven Rostedt    "SLEEP_TIME"		=> \$sleep_time,
2689cc9e091SSteven Rostedt    "BISECT_SLEEP_TIME"		=> \$bisect_sleep_time,
2699cc9e091SSteven Rostedt    "PATCHCHECK_SLEEP_TIME"	=> \$patchcheck_sleep_time,
2709cc9e091SSteven Rostedt    "IGNORE_WARNINGS"		=> \$ignore_warnings,
271be405f95SSteven Rostedt    "IGNORE_ERRORS"		=> \$ignore_errors,
2729cc9e091SSteven Rostedt    "BISECT_MANUAL"		=> \$bisect_manual,
2739cc9e091SSteven Rostedt    "BISECT_SKIP"		=> \$bisect_skip,
2749cc9e091SSteven Rostedt    "CONFIG_BISECT_GOOD"	=> \$config_bisect_good,
2759cc9e091SSteven Rostedt    "BISECT_RET_GOOD"		=> \$bisect_ret_good,
2769cc9e091SSteven Rostedt    "BISECT_RET_BAD"		=> \$bisect_ret_bad,
2779cc9e091SSteven Rostedt    "BISECT_RET_SKIP"		=> \$bisect_ret_skip,
2789cc9e091SSteven Rostedt    "BISECT_RET_ABORT"		=> \$bisect_ret_abort,
2799cc9e091SSteven Rostedt    "BISECT_RET_DEFAULT"	=> \$bisect_ret_default,
2809cc9e091SSteven Rostedt    "STORE_FAILURES"		=> \$store_failures,
2819cc9e091SSteven Rostedt    "STORE_SUCCESSES"		=> \$store_successes,
2829cc9e091SSteven Rostedt    "TEST_NAME"			=> \$test_name,
2839cc9e091SSteven Rostedt    "TIMEOUT"			=> \$timeout,
2849cc9e091SSteven Rostedt    "BOOTED_TIMEOUT"		=> \$booted_timeout,
2859cc9e091SSteven Rostedt    "CONSOLE"			=> \$console,
2869cc9e091SSteven Rostedt    "DETECT_TRIPLE_FAULT"	=> \$detect_triplefault,
2879cc9e091SSteven Rostedt    "SUCCESS_LINE"		=> \$success_line,
2889cc9e091SSteven Rostedt    "REBOOT_SUCCESS_LINE"	=> \$reboot_success_line,
2899cc9e091SSteven Rostedt    "STOP_AFTER_SUCCESS"	=> \$stop_after_success,
2909cc9e091SSteven Rostedt    "STOP_AFTER_FAILURE"	=> \$stop_after_failure,
2919cc9e091SSteven Rostedt    "STOP_TEST_AFTER"		=> \$stop_test_after,
2929cc9e091SSteven Rostedt    "BUILD_TARGET"		=> \$build_target,
2939cc9e091SSteven Rostedt    "SSH_EXEC"			=> \$ssh_exec,
2949cc9e091SSteven Rostedt    "SCP_TO_TARGET"		=> \$scp_to_target,
29502ad2617SSteven Rostedt    "SCP_TO_TARGET_INSTALL"	=> \$scp_to_target_install,
2969cc9e091SSteven Rostedt    "CHECKOUT"			=> \$checkout,
2979cc9e091SSteven Rostedt    "TARGET_IMAGE"		=> \$target_image,
2989cc9e091SSteven Rostedt    "LOCALVERSION"		=> \$localversion,
2999cc9e091SSteven Rostedt
3009cc9e091SSteven Rostedt    "BISECT_GOOD"		=> \$bisect_good,
3019cc9e091SSteven Rostedt    "BISECT_BAD"		=> \$bisect_bad,
3029cc9e091SSteven Rostedt    "BISECT_TYPE"		=> \$bisect_type,
3039cc9e091SSteven Rostedt    "BISECT_START"		=> \$bisect_start,
3049cc9e091SSteven Rostedt    "BISECT_REPLAY"		=> \$bisect_replay,
3059cc9e091SSteven Rostedt    "BISECT_FILES"		=> \$bisect_files,
3069cc9e091SSteven Rostedt    "BISECT_REVERSE"		=> \$bisect_reverse,
3079cc9e091SSteven Rostedt    "BISECT_CHECK"		=> \$bisect_check,
3089cc9e091SSteven Rostedt
3099cc9e091SSteven Rostedt    "CONFIG_BISECT"		=> \$config_bisect,
3109cc9e091SSteven Rostedt    "CONFIG_BISECT_TYPE"	=> \$config_bisect_type,
311b0918612SSteven Rostedt    "CONFIG_BISECT_CHECK"	=> \$config_bisect_check,
3129cc9e091SSteven Rostedt
3139cc9e091SSteven Rostedt    "PATCHCHECK_TYPE"		=> \$patchcheck_type,
3149cc9e091SSteven Rostedt    "PATCHCHECK_START"		=> \$patchcheck_start,
3159cc9e091SSteven Rostedt    "PATCHCHECK_END"		=> \$patchcheck_end,
3169cc9e091SSteven Rostedt);
3179cc9e091SSteven Rostedt
3189cc9e091SSteven Rostedt# Options may be used by other options, record them.
3199cc9e091SSteven Rostedtmy %used_options;
3209cc9e091SSteven Rostedt
3217bf51073SSteven Rostedt# default variables that can be used
3227bf51073SSteven Rostedtchomp ($variable{"PWD"} = `pwd`);
3237bf51073SSteven Rostedt
3248d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF"
3258d1491baSSteven Rostedt The machine hostname that you will test.
326bb8474b1SSteven Rostedt For build only tests, it is still needed to differentiate log files.
3278d1491baSSteven RostedtEOF
3288d1491baSSteven Rostedt    ;
3298d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF"
3308d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user
3318d1491baSSteven Rostedt  (most likely root, since you need privileged operations)
3328d1491baSSteven RostedtEOF
3338d1491baSSteven Rostedt    ;
3348d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF"
3358d1491baSSteven Rostedt The directory that contains the Linux source code (full path).
3360e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
3370e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
3388d1491baSSteven RostedtEOF
3398d1491baSSteven Rostedt    ;
3408d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF"
3418d1491baSSteven Rostedt The directory that the objects will be built (full path).
3428d1491baSSteven Rostedt (can not be same as BUILD_DIR)
3430e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
3440e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
3458d1491baSSteven RostedtEOF
3468d1491baSSteven Rostedt    ;
3478d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF"
3488d1491baSSteven Rostedt The location of the compiled file to copy to the target.
3498d1491baSSteven Rostedt (relative to OUTPUT_DIR)
3508d1491baSSteven RostedtEOF
3518d1491baSSteven Rostedt    ;
352dbd3783bSSteven Rostedt$config_help{"BUILD_OPTIONS"} = << "EOF"
353dbd3783bSSteven Rostedt Options to add to \"make\" when building.
354dbd3783bSSteven Rostedt i.e.  -j20
355dbd3783bSSteven RostedtEOF
356dbd3783bSSteven Rostedt    ;
3578d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF"
3588d1491baSSteven Rostedt The place to put your image on the test machine.
3598d1491baSSteven RostedtEOF
3608d1491baSSteven Rostedt    ;
3618d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF"
3628d1491baSSteven Rostedt A script or command to reboot the box.
3638d1491baSSteven Rostedt
3648d1491baSSteven Rostedt Here is a digital loggers power switch example
3658d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
3668d1491baSSteven Rostedt
3678d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host
3688d1491baSSteven Rostedt with the name "Guest".
3698d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
3708d1491baSSteven RostedtEOF
3718d1491baSSteven Rostedt    ;
3728d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF"
3738d1491baSSteven Rostedt The script or command that reads the console
3748d1491baSSteven Rostedt
3758d1491baSSteven Rostedt  If you use ttywatch server, something like the following would work.
3768d1491baSSteven RostedtCONSOLE = nc -d localhost 3001
3778d1491baSSteven Rostedt
3788d1491baSSteven Rostedt For a virtual machine with guest name "Guest".
3798d1491baSSteven RostedtCONSOLE =  virsh console Guest
3808d1491baSSteven RostedtEOF
3818d1491baSSteven Rostedt    ;
3828d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF"
3838d1491baSSteven Rostedt Required version ending to differentiate the test
3848d1491baSSteven Rostedt from other linux builds on the system.
3858d1491baSSteven RostedtEOF
3868d1491baSSteven Rostedt    ;
3878d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF"
3888d1491baSSteven Rostedt Way to reboot the box to the test kernel.
3897786954cSSteven Rostedt Only valid options so far are "grub", "grub2", "syslinux", and "script".
3908d1491baSSteven Rostedt
3918d1491baSSteven Rostedt If you specify grub, it will assume grub version 1
3928d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
3938d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not
3948d1491baSSteven Rostedt your setup, then specify "script" and have a command or script
3958d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target.
3968d1491baSSteven Rostedt
3978d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually.
3988d1491baSSteven Rostedt The test will not modify that file.
399a15ba913SSteven Rostedt
400a15ba913SSteven Rostedt If you specify grub2, then you also need to specify both \$GRUB_MENU
401a15ba913SSteven Rostedt and \$GRUB_FILE.
4027786954cSSteven Rostedt
4037786954cSSteven Rostedt If you specify syslinux, then you may use SYSLINUX to define the syslinux
4047786954cSSteven Rostedt command (defaults to extlinux), and SYSLINUX_PATH to specify the path to
4057786954cSSteven Rostedt the syslinux install (defaults to /boot/extlinux). But you have to specify
4067786954cSSteven Rostedt SYSLINUX_LABEL to define the label to boot to for the test kernel.
4078d1491baSSteven RostedtEOF
4088d1491baSSteven Rostedt    ;
4098d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF"
4108d1491baSSteven Rostedt The grub title name for the test kernel to boot
411a15ba913SSteven Rostedt (Only mandatory if REBOOT_TYPE = grub or grub2)
4128d1491baSSteven Rostedt
4138d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to
4148d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search
4158d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to
4168d1491baSSteven Rostedt reboot into.
4178d1491baSSteven Rostedt
4188d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has:
4198d1491baSSteven Rostedt title Test Kernel
4208d1491baSSteven Rostedt kernel vmlinuz-test
4218d1491baSSteven Rostedt GRUB_MENU = Test Kernel
422a15ba913SSteven Rostedt
423a15ba913SSteven Rostedt For grub2, a search of \$GRUB_FILE is performed for the lines
424a15ba913SSteven Rostedt that begin with "menuentry". It will not detect submenus. The
425a15ba913SSteven Rostedt menu must be a non-nested menu. Add the quotes used in the menu
426a15ba913SSteven Rostedt to guarantee your selection, as the first menuentry with the content
427a15ba913SSteven Rostedt of \$GRUB_MENU that is found will be used.
428a15ba913SSteven RostedtEOF
429a15ba913SSteven Rostedt    ;
430a15ba913SSteven Rostedt$config_help{"GRUB_FILE"} = << "EOF"
431a15ba913SSteven Rostedt If grub2 is used, the full path for the grub.cfg file is placed
432a15ba913SSteven Rostedt here. Use something like /boot/grub2/grub.cfg to search.
4338d1491baSSteven RostedtEOF
4348d1491baSSteven Rostedt    ;
4357786954cSSteven Rostedt$config_help{"SYSLINUX_LABEL"} = << "EOF"
4367786954cSSteven Rostedt If syslinux is used, the label that boots the target kernel must
4377786954cSSteven Rostedt be specified with SYSLINUX_LABEL.
4387786954cSSteven RostedtEOF
4397786954cSSteven Rostedt    ;
4408d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF"
4418d1491baSSteven Rostedt A script to reboot the target into the test kernel
4428d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script)
4438d1491baSSteven RostedtEOF
4448d1491baSSteven Rostedt    ;
4458d1491baSSteven Rostedt
446dad98754SSteven Rostedtsub read_prompt {
447dad98754SSteven Rostedt    my ($cancel, $prompt) = @_;
44835ce5952SSteven Rostedt
44935ce5952SSteven Rostedt    my $ans;
45035ce5952SSteven Rostedt
45135ce5952SSteven Rostedt    for (;;) {
452dad98754SSteven Rostedt	if ($cancel) {
453dad98754SSteven Rostedt	    print "$prompt [y/n/C] ";
454dad98754SSteven Rostedt	} else {
45535ce5952SSteven Rostedt	    print "$prompt [Y/n] ";
456dad98754SSteven Rostedt	}
45735ce5952SSteven Rostedt	$ans = <STDIN>;
45835ce5952SSteven Rostedt	chomp $ans;
45935ce5952SSteven Rostedt	if ($ans =~ /^\s*$/) {
460dad98754SSteven Rostedt	    if ($cancel) {
461dad98754SSteven Rostedt		$ans = "c";
462dad98754SSteven Rostedt	    } else {
46335ce5952SSteven Rostedt		$ans = "y";
46435ce5952SSteven Rostedt	    }
465dad98754SSteven Rostedt	}
46635ce5952SSteven Rostedt	last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
467dad98754SSteven Rostedt	if ($cancel) {
468dad98754SSteven Rostedt	    last if ($ans =~ /^c$/i);
469dad98754SSteven Rostedt	    print "Please answer either 'y', 'n' or 'c'.\n";
470dad98754SSteven Rostedt	} else {
47135ce5952SSteven Rostedt	    print "Please answer either 'y' or 'n'.\n";
47235ce5952SSteven Rostedt	}
473dad98754SSteven Rostedt    }
474dad98754SSteven Rostedt    if ($ans =~ /^c/i) {
475dad98754SSteven Rostedt	exit;
476dad98754SSteven Rostedt    }
47735ce5952SSteven Rostedt    if ($ans !~ /^y$/i) {
47835ce5952SSteven Rostedt	return 0;
47935ce5952SSteven Rostedt    }
48035ce5952SSteven Rostedt    return 1;
48135ce5952SSteven Rostedt}
4828d1491baSSteven Rostedt
483dad98754SSteven Rostedtsub read_yn {
484dad98754SSteven Rostedt    my ($prompt) = @_;
485dad98754SSteven Rostedt
486dad98754SSteven Rostedt    return read_prompt 0, $prompt;
487dad98754SSteven Rostedt}
488dad98754SSteven Rostedt
489dad98754SSteven Rostedtsub read_ync {
490dad98754SSteven Rostedt    my ($prompt) = @_;
491dad98754SSteven Rostedt
492dad98754SSteven Rostedt    return read_prompt 1, $prompt;
493dad98754SSteven Rostedt}
494dad98754SSteven Rostedt
4958d1491baSSteven Rostedtsub get_ktest_config {
4968d1491baSSteven Rostedt    my ($config) = @_;
497815e2bd7SSteven Rostedt    my $ans;
4988d1491baSSteven Rostedt
4998d1491baSSteven Rostedt    return if (defined($opt{$config}));
5008d1491baSSteven Rostedt
5018d1491baSSteven Rostedt    if (defined($config_help{$config})) {
5028d1491baSSteven Rostedt	print "\n";
5038d1491baSSteven Rostedt	print $config_help{$config};
5048d1491baSSteven Rostedt    }
5058d1491baSSteven Rostedt
5068d1491baSSteven Rostedt    for (;;) {
5078d1491baSSteven Rostedt	print "$config = ";
508dbd3783bSSteven Rostedt	if (defined($default{$config}) && length($default{$config})) {
5098d1491baSSteven Rostedt	    print "\[$default{$config}\] ";
5108d1491baSSteven Rostedt	}
511815e2bd7SSteven Rostedt	$ans = <STDIN>;
512815e2bd7SSteven Rostedt	$ans =~ s/^\s*(.*\S)\s*$/$1/;
513815e2bd7SSteven Rostedt	if ($ans =~ /^\s*$/) {
5148d1491baSSteven Rostedt	    if ($default{$config}) {
515815e2bd7SSteven Rostedt		$ans = $default{$config};
5168d1491baSSteven Rostedt	    } else {
5178d1491baSSteven Rostedt		print "Your answer can not be blank\n";
5188d1491baSSteven Rostedt		next;
5198d1491baSSteven Rostedt	    }
5208d1491baSSteven Rostedt	}
5210e7a22deSSteven Rostedt	$entered_configs{$config} = ${ans};
5228d1491baSSteven Rostedt	last;
5238d1491baSSteven Rostedt    }
5248d1491baSSteven Rostedt}
5258d1491baSSteven Rostedt
5268d1491baSSteven Rostedtsub get_ktest_configs {
5278d1491baSSteven Rostedt    get_ktest_config("MACHINE");
5288d1491baSSteven Rostedt    get_ktest_config("BUILD_DIR");
5298d1491baSSteven Rostedt    get_ktest_config("OUTPUT_DIR");
530bb8474b1SSteven Rostedt
531dbd3783bSSteven Rostedt    if ($newconfig) {
532dbd3783bSSteven Rostedt	get_ktest_config("BUILD_OPTIONS");
533dbd3783bSSteven Rostedt    }
534dbd3783bSSteven Rostedt
535bb8474b1SSteven Rostedt    # options required for other than just building a kernel
536bb8474b1SSteven Rostedt    if (!$buildonly) {
537165708b2SSteven Rostedt	get_ktest_config("POWER_CYCLE");
538165708b2SSteven Rostedt	get_ktest_config("CONSOLE");
539165708b2SSteven Rostedt    }
540165708b2SSteven Rostedt
541165708b2SSteven Rostedt    # options required for install and more
542165708b2SSteven Rostedt    if ($buildonly != 1) {
543bb8474b1SSteven Rostedt	get_ktest_config("SSH_USER");
5448d1491baSSteven Rostedt	get_ktest_config("BUILD_TARGET");
5458d1491baSSteven Rostedt	get_ktest_config("TARGET_IMAGE");
546bb8474b1SSteven Rostedt    }
547bb8474b1SSteven Rostedt
5488d1491baSSteven Rostedt    get_ktest_config("LOCALVERSION");
5498d1491baSSteven Rostedt
550bb8474b1SSteven Rostedt    return if ($buildonly);
551bb8474b1SSteven Rostedt
5528d1491baSSteven Rostedt    my $rtype = $opt{"REBOOT_TYPE"};
5538d1491baSSteven Rostedt
5548d1491baSSteven Rostedt    if (!defined($rtype)) {
5558d1491baSSteven Rostedt	if (!defined($opt{"GRUB_MENU"})) {
5568d1491baSSteven Rostedt	    get_ktest_config("REBOOT_TYPE");
5578d1491baSSteven Rostedt	    $rtype = $entered_configs{"REBOOT_TYPE"};
5588d1491baSSteven Rostedt	} else {
5598d1491baSSteven Rostedt	    $rtype = "grub";
5608d1491baSSteven Rostedt	}
5618d1491baSSteven Rostedt    }
5628d1491baSSteven Rostedt
5638d1491baSSteven Rostedt    if ($rtype eq "grub") {
5648d1491baSSteven Rostedt	get_ktest_config("GRUB_MENU");
5658d1491baSSteven Rostedt    }
566a15ba913SSteven Rostedt
567a15ba913SSteven Rostedt    if ($rtype eq "grub2") {
568a15ba913SSteven Rostedt	get_ktest_config("GRUB_MENU");
569a15ba913SSteven Rostedt	get_ktest_config("GRUB_FILE");
570a15ba913SSteven Rostedt    }
5717786954cSSteven Rostedt
5727786954cSSteven Rostedt    if ($rtype eq "syslinux") {
5737786954cSSteven Rostedt	get_ktest_config("SYSLINUX_LABEL");
5747786954cSSteven Rostedt    }
5758d1491baSSteven Rostedt}
5768d1491baSSteven Rostedt
57777d942ceSSteven Rostedtsub process_variables {
5788d735212SSteven Rostedt    my ($value, $remove_undef) = @_;
57977d942ceSSteven Rostedt    my $retval = "";
58077d942ceSSteven Rostedt
58177d942ceSSteven Rostedt    # We want to check for '\', and it is just easier
58277d942ceSSteven Rostedt    # to check the previous characet of '$' and not need
58377d942ceSSteven Rostedt    # to worry if '$' is the first character. By adding
58477d942ceSSteven Rostedt    # a space to $value, we can just check [^\\]\$ and
58577d942ceSSteven Rostedt    # it will still work.
58677d942ceSSteven Rostedt    $value = " $value";
58777d942ceSSteven Rostedt
58877d942ceSSteven Rostedt    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
58977d942ceSSteven Rostedt	my $begin = $1;
59077d942ceSSteven Rostedt	my $var = $2;
59177d942ceSSteven Rostedt	my $end = $3;
59277d942ceSSteven Rostedt	# append beginning of value to retval
59377d942ceSSteven Rostedt	$retval = "$retval$begin";
59477d942ceSSteven Rostedt	if (defined($variable{$var})) {
59577d942ceSSteven Rostedt	    $retval = "$retval$variable{$var}";
5968d735212SSteven Rostedt	} elsif (defined($remove_undef) && $remove_undef) {
5978d735212SSteven Rostedt	    # for if statements, any variable that is not defined,
5988d735212SSteven Rostedt	    # we simple convert to 0
5998d735212SSteven Rostedt	    $retval = "${retval}0";
60077d942ceSSteven Rostedt	} else {
60177d942ceSSteven Rostedt	    # put back the origin piece.
60277d942ceSSteven Rostedt	    $retval = "$retval\$\{$var\}";
6039cc9e091SSteven Rostedt	    # This could be an option that is used later, save
6049cc9e091SSteven Rostedt	    # it so we don't warn if this option is not one of
6059cc9e091SSteven Rostedt	    # ktests options.
6069cc9e091SSteven Rostedt	    $used_options{$var} = 1;
60777d942ceSSteven Rostedt	}
60877d942ceSSteven Rostedt	$value = $end;
60977d942ceSSteven Rostedt    }
61077d942ceSSteven Rostedt    $retval = "$retval$value";
61177d942ceSSteven Rostedt
61277d942ceSSteven Rostedt    # remove the space added in the beginning
61377d942ceSSteven Rostedt    $retval =~ s/ //;
61477d942ceSSteven Rostedt
61577d942ceSSteven Rostedt    return "$retval"
61677d942ceSSteven Rostedt}
61777d942ceSSteven Rostedt
618a57419b3SSteven Rostedtsub set_value {
6193d1cc414SSteven Rostedt    my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
6202545eb61SSteven Rostedt
621cad96669SSteven Rostedt    my $prvalue = process_variables($rvalue);
622cad96669SSteven Rostedt
623cad96669SSteven Rostedt    if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") {
624bb8474b1SSteven Rostedt	# Note if a test is something other than build, then we
625bb8474b1SSteven Rostedt	# will need other manditory options.
626cad96669SSteven Rostedt	if ($prvalue ne "install") {
627319ab14fSSteven Rostedt (Red Hat)	    # for bisect, we need to check BISECT_TYPE
628319ab14fSSteven Rostedt (Red Hat)	    if ($prvalue ne "bisect") {
629319ab14fSSteven Rostedt (Red Hat)		$buildonly = 0;
630319ab14fSSteven Rostedt (Red Hat)	    }
631319ab14fSSteven Rostedt (Red Hat)	} else {
632319ab14fSSteven Rostedt (Red Hat)	    # install still limits some manditory options.
633319ab14fSSteven Rostedt (Red Hat)	    $buildonly = 2;
634319ab14fSSteven Rostedt (Red Hat)	}
635319ab14fSSteven Rostedt (Red Hat)    }
636319ab14fSSteven Rostedt (Red Hat)
637319ab14fSSteven Rostedt (Red Hat)    if ($buildonly && $lvalue =~ /^BISECT_TYPE(\[.*\])?$/ && $prvalue ne "build") {
638319ab14fSSteven Rostedt (Red Hat)	if ($prvalue ne "install") {
639bb8474b1SSteven Rostedt	    $buildonly = 0;
640165708b2SSteven Rostedt	} else {
641165708b2SSteven Rostedt	    # install still limits some manditory options.
642165708b2SSteven Rostedt	    $buildonly = 2;
643165708b2SSteven Rostedt	}
644bb8474b1SSteven Rostedt    }
645bb8474b1SSteven Rostedt
646a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
6473d1cc414SSteven Rostedt	if (!$override || defined(${$overrides}{$lvalue})) {
6483d1cc414SSteven Rostedt	    my $extra = "";
6493d1cc414SSteven Rostedt	    if ($override) {
6503d1cc414SSteven Rostedt		$extra = "In the same override section!\n";
6513d1cc414SSteven Rostedt	    }
6523d1cc414SSteven Rostedt	    die "$name: $.: Option $lvalue defined more than once!\n$extra";
6533d1cc414SSteven Rostedt	}
654cad96669SSteven Rostedt	${$overrides}{$lvalue} = $prvalue;
655a75fececSSteven Rostedt    }
65621a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
65721a9679fSSteven Rostedt	delete $opt{$lvalue};
65821a9679fSSteven Rostedt    } else {
659cad96669SSteven Rostedt	$opt{$lvalue} = $prvalue;
66021a9679fSSteven Rostedt    }
6612545eb61SSteven Rostedt}
662a57419b3SSteven Rostedt
66377d942ceSSteven Rostedtsub set_variable {
66477d942ceSSteven Rostedt    my ($lvalue, $rvalue) = @_;
66577d942ceSSteven Rostedt
66677d942ceSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
66777d942ceSSteven Rostedt	delete $variable{$lvalue};
66877d942ceSSteven Rostedt    } else {
66977d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
67077d942ceSSteven Rostedt	$variable{$lvalue} = $rvalue;
67177d942ceSSteven Rostedt    }
67277d942ceSSteven Rostedt}
67377d942ceSSteven Rostedt
674ab7a3f52SSteven Rostedtsub process_compare {
675ab7a3f52SSteven Rostedt    my ($lval, $cmp, $rval) = @_;
676ab7a3f52SSteven Rostedt
677ab7a3f52SSteven Rostedt    # remove whitespace
678ab7a3f52SSteven Rostedt
679ab7a3f52SSteven Rostedt    $lval =~ s/^\s*//;
680ab7a3f52SSteven Rostedt    $lval =~ s/\s*$//;
681ab7a3f52SSteven Rostedt
682ab7a3f52SSteven Rostedt    $rval =~ s/^\s*//;
683ab7a3f52SSteven Rostedt    $rval =~ s/\s*$//;
684ab7a3f52SSteven Rostedt
685ab7a3f52SSteven Rostedt    if ($cmp eq "==") {
686ab7a3f52SSteven Rostedt	return $lval eq $rval;
687ab7a3f52SSteven Rostedt    } elsif ($cmp eq "!=") {
688ab7a3f52SSteven Rostedt	return $lval ne $rval;
6898fddbe9bSSteven Rostedt    } elsif ($cmp eq "=~") {
6908fddbe9bSSteven Rostedt	return $lval =~ m/$rval/;
6918fddbe9bSSteven Rostedt    } elsif ($cmp eq "!~") {
6928fddbe9bSSteven Rostedt	return $lval !~ m/$rval/;
693ab7a3f52SSteven Rostedt    }
694ab7a3f52SSteven Rostedt
695ab7a3f52SSteven Rostedt    my $statement = "$lval $cmp $rval";
696ab7a3f52SSteven Rostedt    my $ret = eval $statement;
697ab7a3f52SSteven Rostedt
698ab7a3f52SSteven Rostedt    # $@ stores error of eval
699ab7a3f52SSteven Rostedt    if ($@) {
700ab7a3f52SSteven Rostedt	return -1;
701ab7a3f52SSteven Rostedt    }
702ab7a3f52SSteven Rostedt
703ab7a3f52SSteven Rostedt    return $ret;
704ab7a3f52SSteven Rostedt}
705ab7a3f52SSteven Rostedt
7069900b5dcSSteven Rostedtsub value_defined {
7079900b5dcSSteven Rostedt    my ($val) = @_;
7089900b5dcSSteven Rostedt
7099900b5dcSSteven Rostedt    return defined($variable{$2}) ||
7109900b5dcSSteven Rostedt	defined($opt{$2});
7119900b5dcSSteven Rostedt}
7129900b5dcSSteven Rostedt
7138d735212SSteven Rostedtmy $d = 0;
7148d735212SSteven Rostedtsub process_expression {
7158d735212SSteven Rostedt    my ($name, $val) = @_;
71645d73a5dSSteven Rostedt
7178d735212SSteven Rostedt    my $c = $d++;
7188d735212SSteven Rostedt
7198d735212SSteven Rostedt    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
7208d735212SSteven Rostedt	my $express = $1;
7218d735212SSteven Rostedt
7228d735212SSteven Rostedt	if (process_expression($name, $express)) {
7238d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
7248d735212SSteven Rostedt	} else {
7258d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
7268d735212SSteven Rostedt	}
7278d735212SSteven Rostedt    }
7288d735212SSteven Rostedt
7298d735212SSteven Rostedt    $d--;
7308d735212SSteven Rostedt    my $OR = "\\|\\|";
7318d735212SSteven Rostedt    my $AND = "\\&\\&";
7328d735212SSteven Rostedt
7338d735212SSteven Rostedt    while ($val =~ s/^(.*?)($OR|$AND)//) {
7348d735212SSteven Rostedt	my $express = $1;
7358d735212SSteven Rostedt	my $op = $2;
7368d735212SSteven Rostedt
7378d735212SSteven Rostedt	if (process_expression($name, $express)) {
7388d735212SSteven Rostedt	    if ($op eq "||") {
7398d735212SSteven Rostedt		return 1;
7408d735212SSteven Rostedt	    }
7418d735212SSteven Rostedt	} else {
7428d735212SSteven Rostedt	    if ($op eq "&&") {
7438d735212SSteven Rostedt		return 0;
7448d735212SSteven Rostedt	    }
7458d735212SSteven Rostedt	}
7468d735212SSteven Rostedt    }
74745d73a5dSSteven Rostedt
7488fddbe9bSSteven Rostedt    if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) {
749ab7a3f52SSteven Rostedt	my $ret = process_compare($1, $2, $3);
750ab7a3f52SSteven Rostedt	if ($ret < 0) {
751ab7a3f52SSteven Rostedt	    die "$name: $.: Unable to process comparison\n";
752ab7a3f52SSteven Rostedt	}
753ab7a3f52SSteven Rostedt	return $ret;
754ab7a3f52SSteven Rostedt    }
755ab7a3f52SSteven Rostedt
7569900b5dcSSteven Rostedt    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
7579900b5dcSSteven Rostedt	if (defined $1) {
7589900b5dcSSteven Rostedt	    return !value_defined($2);
7599900b5dcSSteven Rostedt	} else {
7609900b5dcSSteven Rostedt	    return value_defined($2);
7619900b5dcSSteven Rostedt	}
7629900b5dcSSteven Rostedt    }
7639900b5dcSSteven Rostedt
76445d73a5dSSteven Rostedt    if ($val =~ /^\s*0\s*$/) {
76545d73a5dSSteven Rostedt	return 0;
76645d73a5dSSteven Rostedt    } elsif ($val =~ /^\s*\d+\s*$/) {
76745d73a5dSSteven Rostedt	return 1;
76845d73a5dSSteven Rostedt    }
76945d73a5dSSteven Rostedt
7709900b5dcSSteven Rostedt    die ("$name: $.: Undefined content $val in if statement\n");
7718d735212SSteven Rostedt}
7728d735212SSteven Rostedt
7738d735212SSteven Rostedtsub process_if {
7748d735212SSteven Rostedt    my ($name, $value) = @_;
7758d735212SSteven Rostedt
7768d735212SSteven Rostedt    # Convert variables and replace undefined ones with 0
7778d735212SSteven Rostedt    my $val = process_variables($value, 1);
7788d735212SSteven Rostedt    my $ret = process_expression $name, $val;
7798d735212SSteven Rostedt
7808d735212SSteven Rostedt    return $ret;
78145d73a5dSSteven Rostedt}
78245d73a5dSSteven Rostedt
7832ed3b161SSteven Rostedtsub __read_config {
7842ed3b161SSteven Rostedt    my ($config, $current_test_num) = @_;
785a57419b3SSteven Rostedt
7862ed3b161SSteven Rostedt    my $in;
7872ed3b161SSteven Rostedt    open($in, $config) || die "can't read file $config";
788a57419b3SSteven Rostedt
789a57419b3SSteven Rostedt    my $name = $config;
790a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
791a57419b3SSteven Rostedt
7922ed3b161SSteven Rostedt    my $test_num = $$current_test_num;
793a57419b3SSteven Rostedt    my $default = 1;
794a57419b3SSteven Rostedt    my $repeat = 1;
795a57419b3SSteven Rostedt    my $num_tests_set = 0;
796a57419b3SSteven Rostedt    my $skip = 0;
797a57419b3SSteven Rostedt    my $rest;
798a9f84424SSteven Rostedt    my $line;
7990df213caSSteven Rostedt    my $test_case = 0;
80045d73a5dSSteven Rostedt    my $if = 0;
80145d73a5dSSteven Rostedt    my $if_set = 0;
8023d1cc414SSteven Rostedt    my $override = 0;
8033d1cc414SSteven Rostedt
8043d1cc414SSteven Rostedt    my %overrides;
805a57419b3SSteven Rostedt
8062ed3b161SSteven Rostedt    while (<$in>) {
807a57419b3SSteven Rostedt
808a57419b3SSteven Rostedt	# ignore blank lines and comments
809a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
810a57419b3SSteven Rostedt
8110050b6bbSSteven Rostedt	if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
812a57419b3SSteven Rostedt
8130050b6bbSSteven Rostedt	    my $type = $1;
8140050b6bbSSteven Rostedt	    $rest = $2;
815a9f84424SSteven Rostedt	    $line = $2;
8160050b6bbSSteven Rostedt
8170050b6bbSSteven Rostedt	    my $old_test_num;
8180050b6bbSSteven Rostedt	    my $old_repeat;
8193d1cc414SSteven Rostedt	    $override = 0;
8200050b6bbSSteven Rostedt
8210050b6bbSSteven Rostedt	    if ($type eq "TEST_START") {
822a57419b3SSteven Rostedt
823a57419b3SSteven Rostedt		if ($num_tests_set) {
824a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
825a57419b3SSteven Rostedt		}
826a57419b3SSteven Rostedt
8270050b6bbSSteven Rostedt		$old_test_num = $test_num;
8280050b6bbSSteven Rostedt		$old_repeat = $repeat;
829a57419b3SSteven Rostedt
830a57419b3SSteven Rostedt		$test_num += $repeat;
831a57419b3SSteven Rostedt		$default = 0;
832a57419b3SSteven Rostedt		$repeat = 1;
8330050b6bbSSteven Rostedt	    } else {
8340050b6bbSSteven Rostedt		$default = 1;
8350050b6bbSSteven Rostedt	    }
836a57419b3SSteven Rostedt
837a9f84424SSteven Rostedt	    # If SKIP is anywhere in the line, the command will be skipped
838a9f84424SSteven Rostedt	    if ($rest =~ s/\s+SKIP\b//) {
839a57419b3SSteven Rostedt		$skip = 1;
840a57419b3SSteven Rostedt	    } else {
8410df213caSSteven Rostedt		$test_case = 1;
842a57419b3SSteven Rostedt		$skip = 0;
843a57419b3SSteven Rostedt	    }
844a57419b3SSteven Rostedt
845a9f84424SSteven Rostedt	    if ($rest =~ s/\sELSE\b//) {
846a9f84424SSteven Rostedt		if (!$if) {
847a9f84424SSteven Rostedt		    die "$name: $.: ELSE found with out matching IF section\n$_";
848a57419b3SSteven Rostedt		}
849a9f84424SSteven Rostedt		$if = 0;
850a9f84424SSteven Rostedt
851a9f84424SSteven Rostedt		if ($if_set) {
852a9f84424SSteven Rostedt		    $skip = 1;
853a9f84424SSteven Rostedt		} else {
854a9f84424SSteven Rostedt		    $skip = 0;
8553d1cc414SSteven Rostedt		}
8563d1cc414SSteven Rostedt	    }
857a57419b3SSteven Rostedt
858a9f84424SSteven Rostedt	    if ($rest =~ s/\sIF\s+(.*)//) {
85945d73a5dSSteven Rostedt		if (process_if($name, $1)) {
86045d73a5dSSteven Rostedt		    $if_set = 1;
86145d73a5dSSteven Rostedt		} else {
862a57419b3SSteven Rostedt		    $skip = 1;
863a57419b3SSteven Rostedt		}
86445d73a5dSSteven Rostedt		$if = 1;
86545d73a5dSSteven Rostedt	    } else {
86645d73a5dSSteven Rostedt		$if = 0;
867a9f84424SSteven Rostedt		$if_set = 0;
86845d73a5dSSteven Rostedt	    }
869a57419b3SSteven Rostedt
870a9f84424SSteven Rostedt	    if (!$skip) {
871a9f84424SSteven Rostedt		if ($type eq "TEST_START") {
872a9f84424SSteven Rostedt		    if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
873a9f84424SSteven Rostedt			$repeat = $1;
874a9f84424SSteven Rostedt			$repeat_tests{"$test_num"} = $repeat;
875a9f84424SSteven Rostedt		    }
876a9f84424SSteven Rostedt		} elsif ($rest =~ s/\sOVERRIDE\b//) {
877a9f84424SSteven Rostedt		    # DEFAULT only
878a9f84424SSteven Rostedt		    $override = 1;
879a9f84424SSteven Rostedt		    # Clear previous overrides
880a9f84424SSteven Rostedt		    %overrides = ();
881a9f84424SSteven Rostedt		}
882a9f84424SSteven Rostedt	    }
883a9f84424SSteven Rostedt
884a9f84424SSteven Rostedt	    if (!$skip && $rest !~ /^\s*$/) {
8850050b6bbSSteven Rostedt		die "$name: $.: Gargbage found after $type\n$_";
886a57419b3SSteven Rostedt	    }
887a57419b3SSteven Rostedt
8880050b6bbSSteven Rostedt	    if ($skip && $type eq "TEST_START") {
889a57419b3SSteven Rostedt		$test_num = $old_test_num;
890e48c5293SSteven Rostedt		$repeat = $old_repeat;
891a57419b3SSteven Rostedt	    }
892a57419b3SSteven Rostedt
893ab7a3f52SSteven Rostedt	} elsif (/^\s*ELSE\b(.*)$/) {
89445d73a5dSSteven Rostedt	    if (!$if) {
89545d73a5dSSteven Rostedt		die "$name: $.: ELSE found with out matching IF section\n$_";
89645d73a5dSSteven Rostedt	    }
89745d73a5dSSteven Rostedt	    $rest = $1;
89845d73a5dSSteven Rostedt	    if ($if_set) {
89945d73a5dSSteven Rostedt		$skip = 1;
900ab7a3f52SSteven Rostedt		$rest = "";
90145d73a5dSSteven Rostedt	    } else {
90245d73a5dSSteven Rostedt		$skip = 0;
90345d73a5dSSteven Rostedt
904ab7a3f52SSteven Rostedt		if ($rest =~ /\sIF\s+(.*)/) {
90545d73a5dSSteven Rostedt		    # May be a ELSE IF section.
90695f57838SSteven Rostedt		    if (process_if($name, $1)) {
90795f57838SSteven Rostedt			$if_set = 1;
90895f57838SSteven Rostedt		    } else {
90945d73a5dSSteven Rostedt			$skip = 1;
91045d73a5dSSteven Rostedt		    }
911ab7a3f52SSteven Rostedt		    $rest = "";
91245d73a5dSSteven Rostedt		} else {
91345d73a5dSSteven Rostedt		    $if = 0;
91445d73a5dSSteven Rostedt		}
91545d73a5dSSteven Rostedt	    }
91645d73a5dSSteven Rostedt
917ab7a3f52SSteven Rostedt	    if ($rest !~ /^\s*$/) {
918ab7a3f52SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
919ab7a3f52SSteven Rostedt	    }
920ab7a3f52SSteven Rostedt
9212ed3b161SSteven Rostedt	} elsif (/^\s*INCLUDE\s+(\S+)/) {
9222ed3b161SSteven Rostedt
9232ed3b161SSteven Rostedt	    next if ($skip);
9242ed3b161SSteven Rostedt
9252ed3b161SSteven Rostedt	    if (!$default) {
9262ed3b161SSteven Rostedt		die "$name: $.: INCLUDE can only be done in default sections\n$_";
9272ed3b161SSteven Rostedt	    }
9282ed3b161SSteven Rostedt
9292ed3b161SSteven Rostedt	    my $file = process_variables($1);
9302ed3b161SSteven Rostedt
9312ed3b161SSteven Rostedt	    if ($file !~ m,^/,) {
9322ed3b161SSteven Rostedt		# check the path of the config file first
9332ed3b161SSteven Rostedt		if ($config =~ m,(.*)/,) {
9342ed3b161SSteven Rostedt		    if (-f "$1/$file") {
9352ed3b161SSteven Rostedt			$file = "$1/$file";
9362ed3b161SSteven Rostedt		    }
9372ed3b161SSteven Rostedt		}
9382ed3b161SSteven Rostedt	    }
9392ed3b161SSteven Rostedt
9402ed3b161SSteven Rostedt	    if ( ! -r $file ) {
9412ed3b161SSteven Rostedt		die "$name: $.: Can't read file $file\n$_";
9422ed3b161SSteven Rostedt	    }
9432ed3b161SSteven Rostedt
9442ed3b161SSteven Rostedt	    if (__read_config($file, \$test_num)) {
9452ed3b161SSteven Rostedt		$test_case = 1;
9462ed3b161SSteven Rostedt	    }
9472ed3b161SSteven Rostedt
948a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
949a57419b3SSteven Rostedt
950a57419b3SSteven Rostedt	    next if ($skip);
951a57419b3SSteven Rostedt
952a57419b3SSteven Rostedt	    my $lvalue = $1;
953a57419b3SSteven Rostedt	    my $rvalue = $2;
954a57419b3SSteven Rostedt
955a57419b3SSteven Rostedt	    if (!$default &&
956a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
957a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
958a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
959a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
960a57419b3SSteven Rostedt	    }
961a57419b3SSteven Rostedt
962a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
963a57419b3SSteven Rostedt		if ($test_num) {
964a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
965a57419b3SSteven Rostedt		}
966a57419b3SSteven Rostedt		if (!$default) {
967a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
968a57419b3SSteven Rostedt		}
969a57419b3SSteven Rostedt		$num_tests_set = 1;
970a57419b3SSteven Rostedt	    }
971a57419b3SSteven Rostedt
972a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
9733d1cc414SSteven Rostedt		set_value($lvalue, $rvalue, $override, \%overrides, $name);
974a57419b3SSteven Rostedt	    } else {
975a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
9763d1cc414SSteven Rostedt		set_value($val, $rvalue, $override, \%overrides, $name);
977a57419b3SSteven Rostedt
978a57419b3SSteven Rostedt		if ($repeat > 1) {
979a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
980a57419b3SSteven Rostedt		}
981a57419b3SSteven Rostedt	    }
98277d942ceSSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
98377d942ceSSteven Rostedt	    next if ($skip);
98477d942ceSSteven Rostedt
98577d942ceSSteven Rostedt	    my $lvalue = $1;
98677d942ceSSteven Rostedt	    my $rvalue = $2;
98777d942ceSSteven Rostedt
98877d942ceSSteven Rostedt	    # process config variables.
98977d942ceSSteven Rostedt	    # Config variables are only active while reading the
99077d942ceSSteven Rostedt	    # config and can be defined anywhere. They also ignore
99177d942ceSSteven Rostedt	    # TEST_START and DEFAULTS, but are skipped if they are in
99277d942ceSSteven Rostedt	    # on of these sections that have SKIP defined.
99377d942ceSSteven Rostedt	    # The save variable can be
99477d942ceSSteven Rostedt	    # defined multiple times and the new one simply overrides
99577d942ceSSteven Rostedt	    # the prevous one.
99677d942ceSSteven Rostedt	    set_variable($lvalue, $rvalue);
99777d942ceSSteven Rostedt
998a57419b3SSteven Rostedt	} else {
999a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
1000a57419b3SSteven Rostedt	}
10012545eb61SSteven Rostedt    }
10022545eb61SSteven Rostedt
1003a57419b3SSteven Rostedt    if ($test_num) {
1004a57419b3SSteven Rostedt	$test_num += $repeat - 1;
1005a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
1006a57419b3SSteven Rostedt    }
1007a57419b3SSteven Rostedt
10082ed3b161SSteven Rostedt    close($in);
10092ed3b161SSteven Rostedt
10102ed3b161SSteven Rostedt    $$current_test_num = $test_num;
10112ed3b161SSteven Rostedt
10122ed3b161SSteven Rostedt    return $test_case;
10132ed3b161SSteven Rostedt}
10142ed3b161SSteven Rostedt
1015c4261d0fSSteven Rostedtsub get_test_case {
1016c4261d0fSSteven Rostedt	print "What test case would you like to run?\n";
1017c4261d0fSSteven Rostedt	print " (build, install or boot)\n";
1018c4261d0fSSteven Rostedt	print " Other tests are available but require editing the config file\n";
1019c4261d0fSSteven Rostedt	my $ans = <STDIN>;
1020c4261d0fSSteven Rostedt	chomp $ans;
1021c4261d0fSSteven Rostedt	$default{"TEST_TYPE"} = $ans;
1022c4261d0fSSteven Rostedt}
1023c4261d0fSSteven Rostedt
10242ed3b161SSteven Rostedtsub read_config {
10252ed3b161SSteven Rostedt    my ($config) = @_;
10262ed3b161SSteven Rostedt
10272ed3b161SSteven Rostedt    my $test_case;
10282ed3b161SSteven Rostedt    my $test_num = 0;
10292ed3b161SSteven Rostedt
10302ed3b161SSteven Rostedt    $test_case = __read_config $config, \$test_num;
10312ed3b161SSteven Rostedt
10328d1491baSSteven Rostedt    # make sure we have all mandatory configs
10338d1491baSSteven Rostedt    get_ktest_configs;
10348d1491baSSteven Rostedt
10350df213caSSteven Rostedt    # was a test specified?
10360df213caSSteven Rostedt    if (!$test_case) {
10370df213caSSteven Rostedt	print "No test case specified.\n";
1038c4261d0fSSteven Rostedt	get_test_case;
10390df213caSSteven Rostedt    }
10400df213caSSteven Rostedt
1041a75fececSSteven Rostedt    # set any defaults
1042a75fececSSteven Rostedt
1043a75fececSSteven Rostedt    foreach my $default (keys %default) {
1044a75fececSSteven Rostedt	if (!defined($opt{$default})) {
1045a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
1046a75fececSSteven Rostedt	}
1047a75fececSSteven Rostedt    }
10489cc9e091SSteven Rostedt
10499cc9e091SSteven Rostedt    if ($opt{"IGNORE_UNUSED"} == 1) {
10509cc9e091SSteven Rostedt	return;
10519cc9e091SSteven Rostedt    }
10529cc9e091SSteven Rostedt
10539cc9e091SSteven Rostedt    my %not_used;
10549cc9e091SSteven Rostedt
10559cc9e091SSteven Rostedt    # check if there are any stragglers (typos?)
10569cc9e091SSteven Rostedt    foreach my $option (keys %opt) {
10579cc9e091SSteven Rostedt	my $op = $option;
10589cc9e091SSteven Rostedt	# remove per test labels.
10599cc9e091SSteven Rostedt	$op =~ s/\[.*\]//;
10609cc9e091SSteven Rostedt	if (!exists($option_map{$op}) &&
10619cc9e091SSteven Rostedt	    !exists($default{$op}) &&
10629cc9e091SSteven Rostedt	    !exists($used_options{$op})) {
10639cc9e091SSteven Rostedt	    $not_used{$op} = 1;
10649cc9e091SSteven Rostedt	}
10659cc9e091SSteven Rostedt    }
10669cc9e091SSteven Rostedt
10679cc9e091SSteven Rostedt    if (%not_used) {
10689cc9e091SSteven Rostedt	my $s = "s are";
10699cc9e091SSteven Rostedt	$s = " is" if (keys %not_used == 1);
10709cc9e091SSteven Rostedt	print "The following option$s not used; could be a typo:\n";
10719cc9e091SSteven Rostedt	foreach my $option (keys %not_used) {
10729cc9e091SSteven Rostedt	    print "$option\n";
10739cc9e091SSteven Rostedt	}
10749cc9e091SSteven Rostedt	print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n";
10759cc9e091SSteven Rostedt	if (!read_yn "Do you want to continue?") {
10769cc9e091SSteven Rostedt	    exit -1;
10779cc9e091SSteven Rostedt	}
10789cc9e091SSteven Rostedt    }
10792545eb61SSteven Rostedt}
10802545eb61SSteven Rostedt
108123715c3cSSteven Rostedtsub __eval_option {
108204262be3SSteven Rostedt (Red Hat)    my ($name, $option, $i) = @_;
108323715c3cSSteven Rostedt
108423715c3cSSteven Rostedt    # Add space to evaluate the character before $
108523715c3cSSteven Rostedt    $option = " $option";
108623715c3cSSteven Rostedt    my $retval = "";
1087f9dfb65bSRabin Vincent    my $repeated = 0;
1088f9dfb65bSRabin Vincent    my $parent = 0;
1089f9dfb65bSRabin Vincent
1090f9dfb65bSRabin Vincent    foreach my $test (keys %repeat_tests) {
1091f9dfb65bSRabin Vincent	if ($i >= $test &&
1092f9dfb65bSRabin Vincent	    $i < $test + $repeat_tests{$test}) {
1093f9dfb65bSRabin Vincent
1094f9dfb65bSRabin Vincent	    $repeated = 1;
1095f9dfb65bSRabin Vincent	    $parent = $test;
1096f9dfb65bSRabin Vincent	    last;
1097f9dfb65bSRabin Vincent	}
1098f9dfb65bSRabin Vincent    }
109923715c3cSSteven Rostedt
110023715c3cSSteven Rostedt    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
110123715c3cSSteven Rostedt	my $start = $1;
110223715c3cSSteven Rostedt	my $var = $2;
110323715c3cSSteven Rostedt	my $end = $3;
110423715c3cSSteven Rostedt
110523715c3cSSteven Rostedt	# Append beginning of line
110623715c3cSSteven Rostedt	$retval = "$retval$start";
110723715c3cSSteven Rostedt
110823715c3cSSteven Rostedt	# If the iteration option OPT[$i] exists, then use that.
110923715c3cSSteven Rostedt	# otherwise see if the default OPT (without [$i]) exists.
111023715c3cSSteven Rostedt
111123715c3cSSteven Rostedt	my $o = "$var\[$i\]";
1112f9dfb65bSRabin Vincent	my $parento = "$var\[$parent\]";
111323715c3cSSteven Rostedt
111404262be3SSteven Rostedt (Red Hat)	# If a variable contains itself, use the default var
111504262be3SSteven Rostedt (Red Hat)	if (($var eq $name) && defined($opt{$var})) {
111604262be3SSteven Rostedt (Red Hat)	    $o = $opt{$var};
111704262be3SSteven Rostedt (Red Hat)	    $retval = "$retval$o";
111804262be3SSteven Rostedt (Red Hat)	} elsif (defined($opt{$o})) {
111923715c3cSSteven Rostedt	    $o = $opt{$o};
112023715c3cSSteven Rostedt	    $retval = "$retval$o";
1121f9dfb65bSRabin Vincent	} elsif ($repeated && defined($opt{$parento})) {
1122f9dfb65bSRabin Vincent	    $o = $opt{$parento};
1123f9dfb65bSRabin Vincent	    $retval = "$retval$o";
112423715c3cSSteven Rostedt	} elsif (defined($opt{$var})) {
112523715c3cSSteven Rostedt	    $o = $opt{$var};
112623715c3cSSteven Rostedt	    $retval = "$retval$o";
112723715c3cSSteven Rostedt	} else {
112823715c3cSSteven Rostedt	    $retval = "$retval\$\{$var\}";
112923715c3cSSteven Rostedt	}
113023715c3cSSteven Rostedt
113123715c3cSSteven Rostedt	$option = $end;
113223715c3cSSteven Rostedt    }
113323715c3cSSteven Rostedt
113423715c3cSSteven Rostedt    $retval = "$retval$option";
113523715c3cSSteven Rostedt
113623715c3cSSteven Rostedt    $retval =~ s/^ //;
113723715c3cSSteven Rostedt
113823715c3cSSteven Rostedt    return $retval;
113923715c3cSSteven Rostedt}
114023715c3cSSteven Rostedt
114123715c3cSSteven Rostedtsub eval_option {
114204262be3SSteven Rostedt (Red Hat)    my ($name, $option, $i) = @_;
114323715c3cSSteven Rostedt
114423715c3cSSteven Rostedt    my $prev = "";
114523715c3cSSteven Rostedt
114623715c3cSSteven Rostedt    # Since an option can evaluate to another option,
114723715c3cSSteven Rostedt    # keep iterating until we do not evaluate any more
114823715c3cSSteven Rostedt    # options.
114923715c3cSSteven Rostedt    my $r = 0;
115023715c3cSSteven Rostedt    while ($prev ne $option) {
115123715c3cSSteven Rostedt	# Check for recursive evaluations.
115223715c3cSSteven Rostedt	# 100 deep should be more than enough.
115323715c3cSSteven Rostedt	if ($r++ > 100) {
115423715c3cSSteven Rostedt	    die "Over 100 evaluations accurred with $option\n" .
115523715c3cSSteven Rostedt		"Check for recursive variables\n";
115623715c3cSSteven Rostedt	}
115723715c3cSSteven Rostedt	$prev = $option;
115804262be3SSteven Rostedt (Red Hat)	$option = __eval_option($name, $option, $i);
115923715c3cSSteven Rostedt    }
116023715c3cSSteven Rostedt
116123715c3cSSteven Rostedt    return $option;
116223715c3cSSteven Rostedt}
116323715c3cSSteven Rostedt
1164d1e2f22aSSteven Rostedtsub _logit {
11652545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
11662545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
11672545eb61SSteven Rostedt	print OUT @_;
11682545eb61SSteven Rostedt	close(OUT);
11692545eb61SSteven Rostedt    }
11702545eb61SSteven Rostedt}
11712545eb61SSteven Rostedt
1172d1e2f22aSSteven Rostedtsub logit {
1173d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1174d1e2f22aSSteven Rostedt	_logit @_;
1175d1e2f22aSSteven Rostedt    } else {
1176d1e2f22aSSteven Rostedt	print @_;
1177d1e2f22aSSteven Rostedt    }
1178d1e2f22aSSteven Rostedt}
1179d1e2f22aSSteven Rostedt
11805f9b6cedSSteven Rostedtsub doprint {
11815f9b6cedSSteven Rostedt    print @_;
1182d1e2f22aSSteven Rostedt    _logit @_;
11835f9b6cedSSteven Rostedt}
11845f9b6cedSSteven Rostedt
11857faafbd6SSteven Rostedtsub run_command;
11862728be41SAndrew Jonessub start_monitor;
11872728be41SAndrew Jonessub end_monitor;
11882728be41SAndrew Jonessub wait_for_monitor;
11897faafbd6SSteven Rostedt
11907faafbd6SSteven Rostedtsub reboot {
11912728be41SAndrew Jones    my ($time) = @_;
11922728be41SAndrew Jones
1193a4968722SSteven Rostedt    # Make sure everything has been written to disk
1194a4968722SSteven Rostedt    run_ssh("sync");
1195a4968722SSteven Rostedt
11962b803365SSteven Rostedt    if (defined($time)) {
11972b803365SSteven Rostedt	start_monitor;
11982b803365SSteven Rostedt	# flush out current monitor
11992b803365SSteven Rostedt	# May contain the reboot success line
12002b803365SSteven Rostedt	wait_for_monitor 1;
12012b803365SSteven Rostedt    }
12022b803365SSteven Rostedt
12037faafbd6SSteven Rostedt    # try to reboot normally
1204e48c5293SSteven Rostedt    if (run_command $reboot) {
1205576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
1206576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
1207576f627cSSteven Rostedt	    run_command "$power_cycle";
1208576f627cSSteven Rostedt	}
1209576f627cSSteven Rostedt    } else {
12107faafbd6SSteven Rostedt	# nope? power cycle it.
1211a75fececSSteven Rostedt	run_command "$power_cycle";
12127faafbd6SSteven Rostedt    }
12132728be41SAndrew Jones
12142728be41SAndrew Jones    if (defined($time)) {
12154c0b67a2SSteven Rostedt (Red Hat)
12164c0b67a2SSteven Rostedt (Red Hat)	# We only want to get to the new kernel, don't fail
12174c0b67a2SSteven Rostedt (Red Hat)	# if we stumble over a call trace.
12184c0b67a2SSteven Rostedt (Red Hat)	my $save_ignore_errors = $ignore_errors;
12194c0b67a2SSteven Rostedt (Red Hat)	$ignore_errors = 1;
12204c0b67a2SSteven Rostedt (Red Hat)
1221d6845536SSteven Rostedt (Red Hat)	# Look for the good kernel to boot
1222d6845536SSteven Rostedt (Red Hat)	if (wait_for_monitor($time, "Linux version")) {
1223407b95b7SSteven Rostedt	    # reboot got stuck?
12248a80c727SSteven Rostedt	    doprint "Reboot did not finish. Forcing power cycle\n";
1225407b95b7SSteven Rostedt	    run_command "$power_cycle";
1226407b95b7SSteven Rostedt	}
1227d6845536SSteven Rostedt (Red Hat)
12284c0b67a2SSteven Rostedt (Red Hat)	$ignore_errors = $save_ignore_errors;
12294c0b67a2SSteven Rostedt (Red Hat)
1230d6845536SSteven Rostedt (Red Hat)	# Still need to wait for the reboot to finish
1231d6845536SSteven Rostedt (Red Hat)	wait_for_monitor($time, $reboot_success_line);
1232d6845536SSteven Rostedt (Red Hat)
12332728be41SAndrew Jones	end_monitor;
12342728be41SAndrew Jones    }
12357faafbd6SSteven Rostedt}
12367faafbd6SSteven Rostedt
1237bc7c5803SSteven Rostedtsub reboot_to_good {
1238bc7c5803SSteven Rostedt    my ($time) = @_;
1239bc7c5803SSteven Rostedt
1240bc7c5803SSteven Rostedt    if (defined($switch_to_good)) {
1241bc7c5803SSteven Rostedt	run_command $switch_to_good;
1242bc7c5803SSteven Rostedt    }
1243bc7c5803SSteven Rostedt
1244bc7c5803SSteven Rostedt    reboot $time;
1245bc7c5803SSteven Rostedt}
1246bc7c5803SSteven Rostedt
1247576f627cSSteven Rostedtsub do_not_reboot {
1248576f627cSSteven Rostedt    my $i = $iteration;
1249576f627cSSteven Rostedt
12504ab1cce5SSteven Rostedt    return $test_type eq "build" || $no_reboot ||
1251576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
1252576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
1253576f627cSSteven Rostedt}
1254576f627cSSteven Rostedt
12555c42fc5bSSteven Rostedtsub dodie {
12565a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
12575c42fc5bSSteven Rostedt
1258576f627cSSteven Rostedt    my $i = $iteration;
1259576f627cSSteven Rostedt
1260576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
1261576f627cSSteven Rostedt
126275c3fda7SSteven Rostedt	doprint "REBOOTING\n";
1263bc7c5803SSteven Rostedt	reboot_to_good;
126475c3fda7SSteven Rostedt
1265a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
12665c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
1267a75fececSSteven Rostedt	`$power_off`;
12685c42fc5bSSteven Rostedt    }
126975c3fda7SSteven Rostedt
1270f80802cbSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1271f80802cbSSteven Rostedt	print " See $opt{LOG_FILE} for more info.\n";
1272f80802cbSSteven Rostedt    }
1273f80802cbSSteven Rostedt
1274576f627cSSteven Rostedt    die @_, "\n";
12755c42fc5bSSteven Rostedt}
12765c42fc5bSSteven Rostedt
12777faafbd6SSteven Rostedtsub open_console {
12787faafbd6SSteven Rostedt    my ($fp) = @_;
12797faafbd6SSteven Rostedt
12807faafbd6SSteven Rostedt    my $flags;
12817faafbd6SSteven Rostedt
1282a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
1283a75fececSSteven Rostedt	dodie "Can't open console $console";
12847faafbd6SSteven Rostedt
12857faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
1286576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
12877faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
1288576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
12897faafbd6SSteven Rostedt
12907faafbd6SSteven Rostedt    return $pid;
12917faafbd6SSteven Rostedt}
12927faafbd6SSteven Rostedt
12937faafbd6SSteven Rostedtsub close_console {
12947faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
12957faafbd6SSteven Rostedt
12967faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
12977faafbd6SSteven Rostedt    kill 2, $pid;
12987faafbd6SSteven Rostedt
12997faafbd6SSteven Rostedt    print "closing!\n";
13007faafbd6SSteven Rostedt    close($fp);
13017faafbd6SSteven Rostedt}
13027faafbd6SSteven Rostedt
13037faafbd6SSteven Rostedtsub start_monitor {
13047faafbd6SSteven Rostedt    if ($monitor_cnt++) {
13057faafbd6SSteven Rostedt	return;
13067faafbd6SSteven Rostedt    }
13077faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
13087faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
1309a75fececSSteven Rostedt
1310a75fececSSteven Rostedt    return;
1311a75fececSSteven Rostedt
1312a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
13137faafbd6SSteven Rostedt}
13147faafbd6SSteven Rostedt
13157faafbd6SSteven Rostedtsub end_monitor {
1316319ab14fSSteven Rostedt (Red Hat)    return if (!defined $console);
13177faafbd6SSteven Rostedt    if (--$monitor_cnt) {
13187faafbd6SSteven Rostedt	return;
13197faafbd6SSteven Rostedt    }
13207faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
13217faafbd6SSteven Rostedt}
13227faafbd6SSteven Rostedt
13237faafbd6SSteven Rostedtsub wait_for_monitor {
13242b803365SSteven Rostedt    my ($time, $stop) = @_;
13252b803365SSteven Rostedt    my $full_line = "";
13267faafbd6SSteven Rostedt    my $line;
13272b803365SSteven Rostedt    my $booted = 0;
1328407b95b7SSteven Rostedt    my $start_time = time;
13298a80c727SSteven Rostedt    my $skip_call_trace = 0;
13308a80c727SSteven Rostedt    my $bug = 0;
13318a80c727SSteven Rostedt    my $bug_ignored = 0;
1332407b95b7SSteven Rostedt    my $now;
13337faafbd6SSteven Rostedt
1334a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
13357faafbd6SSteven Rostedt
13367faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
13372b803365SSteven Rostedt    while (!$booted) {
13387faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
13392b803365SSteven Rostedt	last if (!defined($line));
13402b803365SSteven Rostedt	print "$line";
13412b803365SSteven Rostedt	$full_line .= $line;
13422b803365SSteven Rostedt
13432b803365SSteven Rostedt	if (defined($stop) && $full_line =~ /$stop/) {
13442b803365SSteven Rostedt	    doprint "wait for monitor detected $stop\n";
13452b803365SSteven Rostedt	    $booted = 1;
13462b803365SSteven Rostedt	}
13472b803365SSteven Rostedt
13488a80c727SSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
13498a80c727SSteven Rostedt	    $skip_call_trace = 1;
13508a80c727SSteven Rostedt	}
13518a80c727SSteven Rostedt
13528a80c727SSteven Rostedt	if ($full_line =~ /call trace:/i) {
13538a80c727SSteven Rostedt	    if (!$bug && !$skip_call_trace) {
13548a80c727SSteven Rostedt		if ($ignore_errors) {
13558a80c727SSteven Rostedt		    $bug_ignored = 1;
13568a80c727SSteven Rostedt		} else {
13578a80c727SSteven Rostedt		    $bug = 1;
13588a80c727SSteven Rostedt		}
13598a80c727SSteven Rostedt	    }
13608a80c727SSteven Rostedt	}
13618a80c727SSteven Rostedt
13628a80c727SSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
13638a80c727SSteven Rostedt	    $skip_call_trace = 0;
13648a80c727SSteven Rostedt	}
13658a80c727SSteven Rostedt
13668a80c727SSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
13678a80c727SSteven Rostedt	    $bug = 1;
13688a80c727SSteven Rostedt	}
13698a80c727SSteven Rostedt
13702b803365SSteven Rostedt	if ($line =~ /\n/) {
13712b803365SSteven Rostedt	    $full_line = "";
13722b803365SSteven Rostedt	}
1373407b95b7SSteven Rostedt	$now = time;
1374407b95b7SSteven Rostedt	if ($now - $start_time >= $max_monitor_wait) {
1375407b95b7SSteven Rostedt	    doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n";
1376407b95b7SSteven Rostedt	    return 1;
1377407b95b7SSteven Rostedt	}
13782b803365SSteven Rostedt    }
1379a75fececSSteven Rostedt    print "** Monitor flushed **\n";
13808a80c727SSteven Rostedt    return $bug;
13817faafbd6SSteven Rostedt}
13827faafbd6SSteven Rostedt
1383de5b6e3bSRabin Vincentsub save_logs {
1384de5b6e3bSRabin Vincent	my ($result, $basedir) = @_;
1385de5b6e3bSRabin Vincent	my @t = localtime;
1386de5b6e3bSRabin Vincent	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1387de5b6e3bSRabin Vincent		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1388de5b6e3bSRabin Vincent
1389de5b6e3bSRabin Vincent	my $type = $build_type;
1390de5b6e3bSRabin Vincent	if ($type =~ /useconfig/) {
1391de5b6e3bSRabin Vincent	    $type = "useconfig";
1392de5b6e3bSRabin Vincent	}
1393de5b6e3bSRabin Vincent
1394de5b6e3bSRabin Vincent	my $dir = "$machine-$test_type-$type-$result-$date";
1395de5b6e3bSRabin Vincent
1396de5b6e3bSRabin Vincent	$dir = "$basedir/$dir";
1397de5b6e3bSRabin Vincent
1398de5b6e3bSRabin Vincent	if (!-d $dir) {
1399de5b6e3bSRabin Vincent	    mkpath($dir) or
1400de5b6e3bSRabin Vincent		die "can't create $dir";
1401de5b6e3bSRabin Vincent	}
1402de5b6e3bSRabin Vincent
1403de5b6e3bSRabin Vincent	my %files = (
1404de5b6e3bSRabin Vincent		"config" => $output_config,
1405de5b6e3bSRabin Vincent		"buildlog" => $buildlog,
1406de5b6e3bSRabin Vincent		"dmesg" => $dmesg,
1407de5b6e3bSRabin Vincent		"testlog" => $testlog,
1408de5b6e3bSRabin Vincent	);
1409de5b6e3bSRabin Vincent
1410de5b6e3bSRabin Vincent	while (my ($name, $source) = each(%files)) {
1411de5b6e3bSRabin Vincent		if (-f "$source") {
1412de5b6e3bSRabin Vincent			cp "$source", "$dir/$name" or
1413de5b6e3bSRabin Vincent				die "failed to copy $source";
1414de5b6e3bSRabin Vincent		}
1415de5b6e3bSRabin Vincent	}
1416de5b6e3bSRabin Vincent
1417de5b6e3bSRabin Vincent	doprint "*** Saved info to $dir ***\n";
1418de5b6e3bSRabin Vincent}
1419de5b6e3bSRabin Vincent
14202b7d9b21SSteven Rostedtsub fail {
14212b7d9b21SSteven Rostedt
1422921ed4c7SSteven Rostedt	if (defined($post_test)) {
1423921ed4c7SSteven Rostedt		run_command $post_test;
1424921ed4c7SSteven Rostedt	}
1425921ed4c7SSteven Rostedt
1426a75fececSSteven Rostedt	if ($die_on_failure) {
14272b7d9b21SSteven Rostedt		dodie @_;
14282b7d9b21SSteven Rostedt	}
14292b7d9b21SSteven Rostedt
1430a75fececSSteven Rostedt	doprint "FAILED\n";
14317faafbd6SSteven Rostedt
1432576f627cSSteven Rostedt	my $i = $iteration;
1433576f627cSSteven Rostedt
1434a75fececSSteven Rostedt	# no need to reboot for just building.
1435576f627cSSteven Rostedt	if (!do_not_reboot) {
14367faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
1437bc7c5803SSteven Rostedt	    reboot_to_good $sleep_time;
1438a75fececSSteven Rostedt	}
14397faafbd6SSteven Rostedt
14409064af52SSteven Rostedt	my $name = "";
14419064af52SSteven Rostedt
14429064af52SSteven Rostedt	if (defined($test_name)) {
14439064af52SSteven Rostedt	    $name = " ($test_name)";
14449064af52SSteven Rostedt	}
14459064af52SSteven Rostedt
1446576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1447576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
14489064af52SSteven Rostedt	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1449576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1450576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1451a75fececSSteven Rostedt
1452de5b6e3bSRabin Vincent	if (defined($store_failures)) {
1453de5b6e3bSRabin Vincent	    save_logs "fail", $store_failures;
1454cccae1a6SSteven Rostedt        }
1455cccae1a6SSteven Rostedt
14562b7d9b21SSteven Rostedt	return 1;
14572b7d9b21SSteven Rostedt}
14582b7d9b21SSteven Rostedt
14592545eb61SSteven Rostedtsub run_command {
14602545eb61SSteven Rostedt    my ($command) = @_;
1461d6ce2a0bSSteven Rostedt    my $dolog = 0;
1462d6ce2a0bSSteven Rostedt    my $dord = 0;
1463d6ce2a0bSSteven Rostedt    my $pid;
1464d6ce2a0bSSteven Rostedt
1465e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
1466e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
1467e48c5293SSteven Rostedt
1468d6ce2a0bSSteven Rostedt    doprint("$command ... ");
1469d6ce2a0bSSteven Rostedt
1470d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
14712b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
14722545eb61SSteven Rostedt
14732545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1474d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
1475d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
1476d6ce2a0bSSteven Rostedt	$dolog = 1;
14776c5ee0beSSteven Rostedt    }
14786c5ee0beSSteven Rostedt
14796c5ee0beSSteven Rostedt    if (defined($redirect)) {
1480d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
1481d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
1482d6ce2a0bSSteven Rostedt	$dord = 1;
14832545eb61SSteven Rostedt    }
14842545eb61SSteven Rostedt
1485d6ce2a0bSSteven Rostedt    while (<CMD>) {
1486d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
1487d6ce2a0bSSteven Rostedt	print RD  if ($dord);
1488d6ce2a0bSSteven Rostedt    }
14892545eb61SSteven Rostedt
1490d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
14912545eb61SSteven Rostedt    my $failed = $?;
14922545eb61SSteven Rostedt
1493d6ce2a0bSSteven Rostedt    close(CMD);
1494d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
1495d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
1496d6ce2a0bSSteven Rostedt
14972545eb61SSteven Rostedt    if ($failed) {
14982545eb61SSteven Rostedt	doprint "FAILED!\n";
14992545eb61SSteven Rostedt    } else {
15002545eb61SSteven Rostedt	doprint "SUCCESS\n";
15012545eb61SSteven Rostedt    }
15022545eb61SSteven Rostedt
15035f9b6cedSSteven Rostedt    return !$failed;
15045f9b6cedSSteven Rostedt}
15055f9b6cedSSteven Rostedt
1506e48c5293SSteven Rostedtsub run_ssh {
1507e48c5293SSteven Rostedt    my ($cmd) = @_;
1508e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
1509e48c5293SSteven Rostedt
1510e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1511e48c5293SSteven Rostedt    return run_command "$cp_exec";
1512e48c5293SSteven Rostedt}
1513e48c5293SSteven Rostedt
1514e48c5293SSteven Rostedtsub run_scp {
151502ad2617SSteven Rostedt    my ($src, $dst, $cp_scp) = @_;
1516e48c5293SSteven Rostedt
1517e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
1518e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
1519e48c5293SSteven Rostedt
1520e48c5293SSteven Rostedt    return run_command "$cp_scp";
1521e48c5293SSteven Rostedt}
1522e48c5293SSteven Rostedt
152302ad2617SSteven Rostedtsub run_scp_install {
152402ad2617SSteven Rostedt    my ($src, $dst) = @_;
152502ad2617SSteven Rostedt
152602ad2617SSteven Rostedt    my $cp_scp = $scp_to_target_install;
152702ad2617SSteven Rostedt
152802ad2617SSteven Rostedt    return run_scp($src, $dst, $cp_scp);
152902ad2617SSteven Rostedt}
153002ad2617SSteven Rostedt
153102ad2617SSteven Rostedtsub run_scp_mod {
153202ad2617SSteven Rostedt    my ($src, $dst) = @_;
153302ad2617SSteven Rostedt
153402ad2617SSteven Rostedt    my $cp_scp = $scp_to_target;
153502ad2617SSteven Rostedt
153602ad2617SSteven Rostedt    return run_scp($src, $dst, $cp_scp);
153702ad2617SSteven Rostedt}
153802ad2617SSteven Rostedt
1539a15ba913SSteven Rostedtsub get_grub2_index {
1540a15ba913SSteven Rostedt
1541a15ba913SSteven Rostedt    return if (defined($grub_number));
1542a15ba913SSteven Rostedt
1543a15ba913SSteven Rostedt    doprint "Find grub2 menu ... ";
1544a15ba913SSteven Rostedt    $grub_number = -1;
1545a15ba913SSteven Rostedt
1546a15ba913SSteven Rostedt    my $ssh_grub = $ssh_exec;
1547a15ba913SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat $grub_file,g;
1548a15ba913SSteven Rostedt
1549a15ba913SSteven Rostedt    open(IN, "$ssh_grub |")
1550a15ba913SSteven Rostedt	or die "unable to get $grub_file";
1551a15ba913SSteven Rostedt
1552a15ba913SSteven Rostedt    my $found = 0;
1553a15ba913SSteven Rostedt
1554a15ba913SSteven Rostedt    while (<IN>) {
1555a15ba913SSteven Rostedt	if (/^menuentry.*$grub_menu/) {
1556a15ba913SSteven Rostedt	    $grub_number++;
1557a15ba913SSteven Rostedt	    $found = 1;
1558a15ba913SSteven Rostedt	    last;
1559a15ba913SSteven Rostedt	} elsif (/^menuentry\s/) {
1560a15ba913SSteven Rostedt	    $grub_number++;
1561a15ba913SSteven Rostedt	}
1562a15ba913SSteven Rostedt    }
1563a15ba913SSteven Rostedt    close(IN);
1564a15ba913SSteven Rostedt
1565a15ba913SSteven Rostedt    die "Could not find '$grub_menu' in $grub_file on $machine"
1566a15ba913SSteven Rostedt	if (!$found);
1567a15ba913SSteven Rostedt    doprint "$grub_number\n";
1568a15ba913SSteven Rostedt}
1569a15ba913SSteven Rostedt
15705f9b6cedSSteven Rostedtsub get_grub_index {
15715f9b6cedSSteven Rostedt
1572a15ba913SSteven Rostedt    if ($reboot_type eq "grub2") {
1573a15ba913SSteven Rostedt	get_grub2_index;
1574a15ba913SSteven Rostedt	return;
1575a15ba913SSteven Rostedt    }
1576a15ba913SSteven Rostedt
1577a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
1578a75fececSSteven Rostedt	return;
1579a75fececSSteven Rostedt    }
15805a391fbfSSteven Rostedt    return if (defined($grub_number));
15815f9b6cedSSteven Rostedt
15825f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
15835f9b6cedSSteven Rostedt    $grub_number = -1;
1584e48c5293SSteven Rostedt
1585e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
1586e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
1587e48c5293SSteven Rostedt
1588e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
15895f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
1590e48c5293SSteven Rostedt
1591eaa1fe25SSteven Rostedt    my $found = 0;
1592eaa1fe25SSteven Rostedt
15935f9b6cedSSteven Rostedt    while (<IN>) {
1594a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
15955f9b6cedSSteven Rostedt	    $grub_number++;
1596eaa1fe25SSteven Rostedt	    $found = 1;
15975f9b6cedSSteven Rostedt	    last;
15985f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
15995f9b6cedSSteven Rostedt	    $grub_number++;
16005f9b6cedSSteven Rostedt	}
16015f9b6cedSSteven Rostedt    }
16025f9b6cedSSteven Rostedt    close(IN);
16035f9b6cedSSteven Rostedt
1604a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
1605eaa1fe25SSteven Rostedt	if (!$found);
16065f9b6cedSSteven Rostedt    doprint "$grub_number\n";
16072545eb61SSteven Rostedt}
16082545eb61SSteven Rostedt
16092545eb61SSteven Rostedtsub wait_for_input
16102545eb61SSteven Rostedt{
16112545eb61SSteven Rostedt    my ($fp, $time) = @_;
16122545eb61SSteven Rostedt    my $rin;
16132545eb61SSteven Rostedt    my $ready;
16142545eb61SSteven Rostedt    my $line;
16152545eb61SSteven Rostedt    my $ch;
16162545eb61SSteven Rostedt
16172545eb61SSteven Rostedt    if (!defined($time)) {
16182545eb61SSteven Rostedt	$time = $timeout;
16192545eb61SSteven Rostedt    }
16202545eb61SSteven Rostedt
16212545eb61SSteven Rostedt    $rin = '';
16222545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
1623319ab14fSSteven Rostedt (Red Hat)    ($ready, $time) = select($rin, undef, undef, $time);
16242545eb61SSteven Rostedt
16252545eb61SSteven Rostedt    $line = "";
16262545eb61SSteven Rostedt
16272545eb61SSteven Rostedt    # try to read one char at a time
16282545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
16292545eb61SSteven Rostedt	$line .= $ch;
16302545eb61SSteven Rostedt	last if ($ch eq "\n");
16312545eb61SSteven Rostedt    }
16322545eb61SSteven Rostedt
16332545eb61SSteven Rostedt    if (!length($line)) {
16342545eb61SSteven Rostedt	return undef;
16352545eb61SSteven Rostedt    }
16362545eb61SSteven Rostedt
16372545eb61SSteven Rostedt    return $line;
16382545eb61SSteven Rostedt}
16392545eb61SSteven Rostedt
164075c3fda7SSteven Rostedtsub reboot_to {
1641bc7c5803SSteven Rostedt    if (defined($switch_to_test)) {
1642bc7c5803SSteven Rostedt	run_command $switch_to_test;
1643bc7c5803SSteven Rostedt    }
1644bc7c5803SSteven Rostedt
1645a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
1646c54367f9SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
1647a15ba913SSteven Rostedt    } elsif ($reboot_type eq "grub2") {
1648a15ba913SSteven Rostedt	run_ssh "$grub_reboot $grub_number";
16497786954cSSteven Rostedt    } elsif ($reboot_type eq "syslinux") {
16507786954cSSteven Rostedt	run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path";
165196f6a0dfSSteven Rostedt    } elsif (defined $reboot_script) {
1652a75fececSSteven Rostedt	run_command "$reboot_script";
16532545eb61SSteven Rostedt    }
165496f6a0dfSSteven Rostedt    reboot;
165596f6a0dfSSteven Rostedt}
16562545eb61SSteven Rostedt
1657a57419b3SSteven Rostedtsub get_sha1 {
1658a57419b3SSteven Rostedt    my ($commit) = @_;
1659a57419b3SSteven Rostedt
1660a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
1661a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
1662a57419b3SSteven Rostedt    my $ret = $?;
1663a57419b3SSteven Rostedt
1664a57419b3SSteven Rostedt    logit $sha1;
1665a57419b3SSteven Rostedt
1666a57419b3SSteven Rostedt    if ($ret) {
1667a57419b3SSteven Rostedt	doprint "FAILED\n";
1668a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
1669a57419b3SSteven Rostedt    }
1670a57419b3SSteven Rostedt
1671a57419b3SSteven Rostedt    print "SUCCESS\n";
1672a57419b3SSteven Rostedt
1673a57419b3SSteven Rostedt    chomp $sha1;
1674a57419b3SSteven Rostedt
1675a57419b3SSteven Rostedt    return $sha1;
1676a57419b3SSteven Rostedt}
1677a57419b3SSteven Rostedt
16785a391fbfSSteven Rostedtsub monitor {
16792545eb61SSteven Rostedt    my $booted = 0;
16802545eb61SSteven Rostedt    my $bug = 0;
16816ca996ccSSteven Rostedt    my $bug_ignored = 0;
16825c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
16832b7d9b21SSteven Rostedt    my $loops;
16842545eb61SSteven Rostedt
16857faafbd6SSteven Rostedt    wait_for_monitor 5;
16862545eb61SSteven Rostedt
16872545eb61SSteven Rostedt    my $line;
16882545eb61SSteven Rostedt    my $full_line = "";
16892545eb61SSteven Rostedt
16907faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
16917faafbd6SSteven Rostedt	die "unable to write to $dmesg";
16922545eb61SSteven Rostedt
169375c3fda7SSteven Rostedt    reboot_to;
16942545eb61SSteven Rostedt
16951c8a617aSSteven Rostedt    my $success_start;
16961c8a617aSSteven Rostedt    my $failure_start;
16972d01b26aSSteven Rostedt    my $monitor_start = time;
16982d01b26aSSteven Rostedt    my $done = 0;
1699f1a5b962SSteven Rostedt    my $version_found = 0;
17001c8a617aSSteven Rostedt
17012d01b26aSSteven Rostedt    while (!$done) {
17022545eb61SSteven Rostedt
1703ecaf8e52SSteven Rostedt	if ($bug && defined($stop_after_failure) &&
1704ecaf8e52SSteven Rostedt	    $stop_after_failure >= 0) {
1705ecaf8e52SSteven Rostedt	    my $time = $stop_after_failure - (time - $failure_start);
1706ecaf8e52SSteven Rostedt	    $line = wait_for_input($monitor_fp, $time);
1707ecaf8e52SSteven Rostedt	    if (!defined($line)) {
1708ecaf8e52SSteven Rostedt		doprint "bug timed out after $booted_timeout seconds\n";
1709ecaf8e52SSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1710ecaf8e52SSteven Rostedt		last;
1711ecaf8e52SSteven Rostedt	    }
1712ecaf8e52SSteven Rostedt	} elsif ($booted) {
1713a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
1714cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1715cd4f1d53SSteven Rostedt		my $s = $booted_timeout == 1 ? "" : "s";
1716cd4f1d53SSteven Rostedt		doprint "Successful boot found: break after $booted_timeout second$s\n";
1717cd4f1d53SSteven Rostedt		last;
1718cd4f1d53SSteven Rostedt	    }
17192b7d9b21SSteven Rostedt	} else {
17207faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
1721cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1722cd4f1d53SSteven Rostedt		my $s = $timeout == 1 ? "" : "s";
1723cd4f1d53SSteven Rostedt		doprint "Timed out after $timeout second$s\n";
1724cd4f1d53SSteven Rostedt		last;
17252b7d9b21SSteven Rostedt	    }
1726cd4f1d53SSteven Rostedt	}
17272545eb61SSteven Rostedt
17282545eb61SSteven Rostedt	doprint $line;
17297faafbd6SSteven Rostedt	print DMESG $line;
17302545eb61SSteven Rostedt
17312545eb61SSteven Rostedt	# we are not guaranteed to get a full line
17322545eb61SSteven Rostedt	$full_line .= $line;
17332545eb61SSteven Rostedt
1734a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
17352545eb61SSteven Rostedt	    $booted = 1;
17361c8a617aSSteven Rostedt	    $success_start = time;
17371c8a617aSSteven Rostedt	}
17381c8a617aSSteven Rostedt
17391c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
17401c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
17411c8a617aSSteven Rostedt	    my $now = time;
17421c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
17431c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
17441c8a617aSSteven Rostedt		last;
17451c8a617aSSteven Rostedt	    }
17462545eb61SSteven Rostedt	}
17472545eb61SSteven Rostedt
17485c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
17495c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
17505c42fc5bSSteven Rostedt	}
17515c42fc5bSSteven Rostedt
17522545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
17536ca996ccSSteven Rostedt	    if (!$bug && !$skip_call_trace) {
17546ca996ccSSteven Rostedt		if ($ignore_errors) {
17556ca996ccSSteven Rostedt		    $bug_ignored = 1;
17566ca996ccSSteven Rostedt		} else {
17571c8a617aSSteven Rostedt		    $bug = 1;
17581c8a617aSSteven Rostedt		    $failure_start = time;
17591c8a617aSSteven Rostedt		}
17601c8a617aSSteven Rostedt	    }
17616ca996ccSSteven Rostedt	}
17621c8a617aSSteven Rostedt
17631c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
17641c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
17651c8a617aSSteven Rostedt	    my $now = time;
17661c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
17671c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
17681c8a617aSSteven Rostedt		last;
17691c8a617aSSteven Rostedt	    }
17705c42fc5bSSteven Rostedt	}
17715c42fc5bSSteven Rostedt
17725c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
17735c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
17745c42fc5bSSteven Rostedt	}
17755c42fc5bSSteven Rostedt
17765c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
177710abf118SSteven Rostedt	    $failure_start = time;
17782545eb61SSteven Rostedt	    $bug = 1;
17792545eb61SSteven Rostedt	}
17802545eb61SSteven Rostedt
1781f1a5b962SSteven Rostedt	# Detect triple faults by testing the banner
1782f1a5b962SSteven Rostedt	if ($full_line =~ /\bLinux version (\S+).*\n/) {
1783f1a5b962SSteven Rostedt	    if ($1 eq $version) {
1784f1a5b962SSteven Rostedt		$version_found = 1;
1785f1a5b962SSteven Rostedt	    } elsif ($version_found && $detect_triplefault) {
1786f1a5b962SSteven Rostedt		# We already booted into the kernel we are testing,
1787f1a5b962SSteven Rostedt		# but now we booted into another kernel?
1788f1a5b962SSteven Rostedt		# Consider this a triple fault.
1789f1a5b962SSteven Rostedt		doprint "Aleady booted in Linux kernel $version, but now\n";
1790f1a5b962SSteven Rostedt		doprint "we booted into Linux kernel $1.\n";
1791f1a5b962SSteven Rostedt		doprint "Assuming that this is a triple fault.\n";
1792f1a5b962SSteven Rostedt		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1793f1a5b962SSteven Rostedt		last;
1794f1a5b962SSteven Rostedt	    }
1795f1a5b962SSteven Rostedt	}
1796f1a5b962SSteven Rostedt
17972545eb61SSteven Rostedt	if ($line =~ /\n/) {
17982545eb61SSteven Rostedt	    $full_line = "";
17992545eb61SSteven Rostedt	}
18002d01b26aSSteven Rostedt
18012d01b26aSSteven Rostedt	if ($stop_test_after > 0 && !$booted && !$bug) {
18022d01b26aSSteven Rostedt	    if (time - $monitor_start > $stop_test_after) {
18034d62bf51SSteven Rostedt		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
18042d01b26aSSteven Rostedt		$done = 1;
18052d01b26aSSteven Rostedt	    }
18062d01b26aSSteven Rostedt	}
18072545eb61SSteven Rostedt    }
18082545eb61SSteven Rostedt
18097faafbd6SSteven Rostedt    close(DMESG);
18102545eb61SSteven Rostedt
18112545eb61SSteven Rostedt    if ($bug) {
18122b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
1813576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
18142545eb61SSteven Rostedt    }
18155f9b6cedSSteven Rostedt
1816a75fececSSteven Rostedt    if (!$booted) {
1817a75fececSSteven Rostedt	return 0 if ($in_bisect);
1818576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
1819a75fececSSteven Rostedt    }
1820a75fececSSteven Rostedt
18216ca996ccSSteven Rostedt    if ($bug_ignored) {
18226ca996ccSSteven Rostedt	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
18236ca996ccSSteven Rostedt    }
18246ca996ccSSteven Rostedt
18252b7d9b21SSteven Rostedt    return 1;
18262545eb61SSteven Rostedt}
18272545eb61SSteven Rostedt
18282b29b2f8SSteven Rostedtsub eval_kernel_version {
18292b29b2f8SSteven Rostedt    my ($option) = @_;
18302b29b2f8SSteven Rostedt
18312b29b2f8SSteven Rostedt    $option =~ s/\$KERNEL_VERSION/$version/g;
18322b29b2f8SSteven Rostedt
18332b29b2f8SSteven Rostedt    return $option;
18342b29b2f8SSteven Rostedt}
18352b29b2f8SSteven Rostedt
1836db05cfefSSteven Rostedtsub do_post_install {
1837db05cfefSSteven Rostedt
1838db05cfefSSteven Rostedt    return if (!defined($post_install));
1839db05cfefSSteven Rostedt
18402b29b2f8SSteven Rostedt    my $cp_post_install = eval_kernel_version $post_install;
1841db05cfefSSteven Rostedt    run_command "$cp_post_install" or
1842db05cfefSSteven Rostedt	dodie "Failed to run post install";
1843db05cfefSSteven Rostedt}
1844db05cfefSSteven Rostedt
1845e1a6c3d7SSteven Rostedt# Sometimes the reboot fails, and will hang. We try to ssh to the box
1846e1a6c3d7SSteven Rostedt# and if we fail, we force another reboot, that should powercycle it.
1847e1a6c3d7SSteven Rostedtsub test_booted {
1848e1a6c3d7SSteven Rostedt    if (!run_ssh "echo testing connection") {
1849e1a6c3d7SSteven Rostedt	reboot $sleep_time;
1850e1a6c3d7SSteven Rostedt    }
1851e1a6c3d7SSteven Rostedt}
1852e1a6c3d7SSteven Rostedt
18532545eb61SSteven Rostedtsub install {
18542545eb61SSteven Rostedt
1855e0a8742eSSteven Rostedt    return if ($no_install);
1856e0a8742eSSteven Rostedt
1857e5c2ec11SSteven Rostedt    if (defined($pre_install)) {
1858e5c2ec11SSteven Rostedt	my $cp_pre_install = eval_kernel_version $pre_install;
1859e5c2ec11SSteven Rostedt	run_command "$cp_pre_install" or
1860e5c2ec11SSteven Rostedt	    dodie "Failed to run pre install";
1861e5c2ec11SSteven Rostedt    }
1862e5c2ec11SSteven Rostedt
18632b29b2f8SSteven Rostedt    my $cp_target = eval_kernel_version $target_image;
18642b29b2f8SSteven Rostedt
1865e1a6c3d7SSteven Rostedt    test_booted;
1866e1a6c3d7SSteven Rostedt
186702ad2617SSteven Rostedt    run_scp_install "$outputdir/$build_target", "$cp_target" or
18685c42fc5bSSteven Rostedt	dodie "failed to copy image";
18695f9b6cedSSteven Rostedt
18705f9b6cedSSteven Rostedt    my $install_mods = 0;
18715f9b6cedSSteven Rostedt
18725f9b6cedSSteven Rostedt    # should we process modules?
18735f9b6cedSSteven Rostedt    $install_mods = 0;
187451ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
18755f9b6cedSSteven Rostedt    while (<IN>) {
18765f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
18778bc5e4eaSSteven Rostedt	    if (defined($1)) {
18788bc5e4eaSSteven Rostedt		$install_mods = 1;
18795f9b6cedSSteven Rostedt		last;
18805f9b6cedSSteven Rostedt	    }
18815f9b6cedSSteven Rostedt	}
18828bc5e4eaSSteven Rostedt    }
18835f9b6cedSSteven Rostedt    close(IN);
18845f9b6cedSSteven Rostedt
18855f9b6cedSSteven Rostedt    if (!$install_mods) {
1886db05cfefSSteven Rostedt	do_post_install;
18875f9b6cedSSteven Rostedt	doprint "No modules needed\n";
18885f9b6cedSSteven Rostedt	return;
18892545eb61SSteven Rostedt    }
18902545eb61SSteven Rostedt
1891627977d8SSteven Rostedt    run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or
18925f9b6cedSSteven Rostedt	dodie "Failed to install modules";
18935f9b6cedSSteven Rostedt
18942545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
1895a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
18962545eb61SSteven Rostedt
1897e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
18985c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
18992545eb61SSteven Rostedt
19005c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
1901a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
19025c42fc5bSSteven Rostedt	dodie "making tarball";
19035c42fc5bSSteven Rostedt
190402ad2617SSteven Rostedt    run_scp_mod "$tmpdir/$modtar", "/tmp" or
19055c42fc5bSSteven Rostedt	dodie "failed to copy modules";
19065c42fc5bSSteven Rostedt
1907a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
19085c42fc5bSSteven Rostedt
1909e7b13441SSteven Rostedt    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
19105c42fc5bSSteven Rostedt	dodie "failed to tar modules";
19115c42fc5bSSteven Rostedt
1912e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
19138b37ca8cSSteven Rostedt
1914db05cfefSSteven Rostedt    do_post_install;
19152545eb61SSteven Rostedt}
19162545eb61SSteven Rostedt
1917ddf607e5SSteven Rostedtsub get_version {
1918ddf607e5SSteven Rostedt    # get the release name
1919683a3e64SSteven Rostedt    return if ($have_version);
1920ddf607e5SSteven Rostedt    doprint "$make kernelrelease ... ";
1921ddf607e5SSteven Rostedt    $version = `$make kernelrelease | tail -1`;
1922ddf607e5SSteven Rostedt    chomp($version);
1923ddf607e5SSteven Rostedt    doprint "$version\n";
1924683a3e64SSteven Rostedt    $have_version = 1;
1925ddf607e5SSteven Rostedt}
1926ddf607e5SSteven Rostedt
1927ddf607e5SSteven Rostedtsub start_monitor_and_boot {
19289f7424ccSSteven Rostedt    # Make sure the stable kernel has finished booting
1929319ab14fSSteven Rostedt (Red Hat)
1930319ab14fSSteven Rostedt (Red Hat)    # Install bisects, don't need console
1931319ab14fSSteven Rostedt (Red Hat)    if (defined $console) {
19329f7424ccSSteven Rostedt	start_monitor;
19339f7424ccSSteven Rostedt	wait_for_monitor 5;
19349f7424ccSSteven Rostedt	end_monitor;
1935319ab14fSSteven Rostedt (Red Hat)    }
19369f7424ccSSteven Rostedt
1937ddf607e5SSteven Rostedt    get_grub_index;
1938ddf607e5SSteven Rostedt    get_version;
1939ddf607e5SSteven Rostedt    install;
1940ddf607e5SSteven Rostedt
1941319ab14fSSteven Rostedt (Red Hat)    start_monitor if (defined $console);
1942ddf607e5SSteven Rostedt    return monitor;
1943ddf607e5SSteven Rostedt}
1944ddf607e5SSteven Rostedt
19454283b169SSteven Rostedt (Red Hat)my $check_build_re = ".*:.*(warning|error|Error):.*";
19464283b169SSteven Rostedt (Red Hat)my $utf8_quote = "\\x{e2}\\x{80}(\\x{98}|\\x{99})";
19474283b169SSteven Rostedt (Red Hat)
1948*7328735cSSteven Rostedt (Red Hat)sub process_warning_line {
1949*7328735cSSteven Rostedt (Red Hat)    my ($line) = @_;
1950*7328735cSSteven Rostedt (Red Hat)
1951*7328735cSSteven Rostedt (Red Hat)    chomp $line;
1952*7328735cSSteven Rostedt (Red Hat)
1953*7328735cSSteven Rostedt (Red Hat)    # for distcc heterogeneous systems, some compilers
1954*7328735cSSteven Rostedt (Red Hat)    # do things differently causing warning lines
1955*7328735cSSteven Rostedt (Red Hat)    # to be slightly different. This makes an attempt
1956*7328735cSSteven Rostedt (Red Hat)    # to fixe those issues.
1957*7328735cSSteven Rostedt (Red Hat)
1958*7328735cSSteven Rostedt (Red Hat)    # chop off the index into the line
1959*7328735cSSteven Rostedt (Red Hat)    # using distcc, some compilers give different indexes
1960*7328735cSSteven Rostedt (Red Hat)    # depending on white space
1961*7328735cSSteven Rostedt (Red Hat)    $line =~ s/^(\s*\S+:\d+:)\d+/$1/;
1962*7328735cSSteven Rostedt (Red Hat)
1963*7328735cSSteven Rostedt (Red Hat)    # Some compilers use UTF-8 extended for quotes and some don't.
1964*7328735cSSteven Rostedt (Red Hat)    $line =~ s/$utf8_quote/'/g;
1965*7328735cSSteven Rostedt (Red Hat)
1966*7328735cSSteven Rostedt (Red Hat)    return $line;
1967*7328735cSSteven Rostedt (Red Hat)}
1968*7328735cSSteven Rostedt (Red Hat)
19694283b169SSteven Rostedt (Red Hat)# Read buildlog and check against warnings file for any
19704283b169SSteven Rostedt (Red Hat)# new warnings.
19714283b169SSteven Rostedt (Red Hat)#
19724283b169SSteven Rostedt (Red Hat)# Returns 1 if OK
19734283b169SSteven Rostedt (Red Hat)#         0 otherwise
19746c5ee0beSSteven Rostedtsub check_buildlog {
19754283b169SSteven Rostedt (Red Hat)    return 1 if (!defined $warnings_file);
19764283b169SSteven Rostedt (Red Hat)
19774283b169SSteven Rostedt (Red Hat)    my %warnings_list;
19784283b169SSteven Rostedt (Red Hat)
19794283b169SSteven Rostedt (Red Hat)    # Failed builds should not reboot the target
19804283b169SSteven Rostedt (Red Hat)    my $save_no_reboot = $no_reboot;
19814283b169SSteven Rostedt (Red Hat)    $no_reboot = 1;
19824283b169SSteven Rostedt (Red Hat)
19834283b169SSteven Rostedt (Red Hat)    if (-f $warnings_file) {
19844283b169SSteven Rostedt (Red Hat)	open(IN, $warnings_file) or
19854283b169SSteven Rostedt (Red Hat)	    dodie "Error opening $warnings_file";
19864283b169SSteven Rostedt (Red Hat)
19874283b169SSteven Rostedt (Red Hat)	while (<IN>) {
19884283b169SSteven Rostedt (Red Hat)	    if (/$check_build_re/) {
1989*7328735cSSteven Rostedt (Red Hat)		my $warning = process_warning_line $_;
1990*7328735cSSteven Rostedt (Red Hat)
1991*7328735cSSteven Rostedt (Red Hat)		$warnings_list{$warning} = 1;
19924283b169SSteven Rostedt (Red Hat)	    }
19934283b169SSteven Rostedt (Red Hat)	}
19944283b169SSteven Rostedt (Red Hat)	close(IN);
19954283b169SSteven Rostedt (Red Hat)    }
19964283b169SSteven Rostedt (Red Hat)
19974283b169SSteven Rostedt (Red Hat)    # If warnings file didn't exist, and WARNINGS_FILE exist,
19984283b169SSteven Rostedt (Red Hat)    # then we fail on any warning!
19994283b169SSteven Rostedt (Red Hat)
20004283b169SSteven Rostedt (Red Hat)    open(IN, $buildlog) or dodie "Can't open $buildlog";
20014283b169SSteven Rostedt (Red Hat)    while (<IN>) {
20024283b169SSteven Rostedt (Red Hat)	if (/$check_build_re/) {
2003*7328735cSSteven Rostedt (Red Hat)	    my $warning = process_warning_line $_;
20044283b169SSteven Rostedt (Red Hat)
2005*7328735cSSteven Rostedt (Red Hat)	    if (!defined $warnings_list{$warning}) {
20064283b169SSteven Rostedt (Red Hat)		fail "New warning found (not in $warnings_file)\n$_\n";
20074283b169SSteven Rostedt (Red Hat)		$no_reboot = $save_no_reboot;
20084283b169SSteven Rostedt (Red Hat)		return 0;
20094283b169SSteven Rostedt (Red Hat)	    }
20104283b169SSteven Rostedt (Red Hat)	}
20114283b169SSteven Rostedt (Red Hat)    }
20124283b169SSteven Rostedt (Red Hat)    $no_reboot = $save_no_reboot;
20134283b169SSteven Rostedt (Red Hat)    close(IN);
20144283b169SSteven Rostedt (Red Hat)}
20154283b169SSteven Rostedt (Red Hat)
20164283b169SSteven Rostedt (Red Hat)sub check_patch_buildlog {
20176c5ee0beSSteven Rostedt    my ($patch) = @_;
20186c5ee0beSSteven Rostedt
20196c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
20206c5ee0beSSteven Rostedt
202135275685SSteven Rostedt (Red Hat)    foreach my $file (@files) {
202235275685SSteven Rostedt (Red Hat)	chomp $file;
202335275685SSteven Rostedt (Red Hat)    }
202435275685SSteven Rostedt (Red Hat)
20256c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
20266c5ee0beSSteven Rostedt	dodie "failed to show $patch";
20276c5ee0beSSteven Rostedt    while (<IN>) {
20286c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
20296c5ee0beSSteven Rostedt	    chomp $1;
20306c5ee0beSSteven Rostedt	    $files[$#files] = $1;
20316c5ee0beSSteven Rostedt	}
20326c5ee0beSSteven Rostedt    }
20336c5ee0beSSteven Rostedt    close(IN);
20346c5ee0beSSteven Rostedt
20356c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
20366c5ee0beSSteven Rostedt    while (<IN>) {
20376c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
20386c5ee0beSSteven Rostedt	    my $err = $1;
20396c5ee0beSSteven Rostedt	    foreach my $file (@files) {
2040a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
20416c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
20422b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
20436c5ee0beSSteven Rostedt		}
20446c5ee0beSSteven Rostedt	    }
20456c5ee0beSSteven Rostedt	}
20466c5ee0beSSteven Rostedt    }
20476c5ee0beSSteven Rostedt    close(IN);
20482b7d9b21SSteven Rostedt
20492b7d9b21SSteven Rostedt    return 1;
20506c5ee0beSSteven Rostedt}
20516c5ee0beSSteven Rostedt
2052fcb3f16aSSteven Rostedtsub apply_min_config {
2053fcb3f16aSSteven Rostedt    my $outconfig = "$output_config.new";
2054612b9e9bSSteven Rostedt
2055fcb3f16aSSteven Rostedt    # Read the config file and remove anything that
2056fcb3f16aSSteven Rostedt    # is in the force_config hash (from minconfig and others)
2057fcb3f16aSSteven Rostedt    # then add the force config back.
2058fcb3f16aSSteven Rostedt
2059fcb3f16aSSteven Rostedt    doprint "Applying minimum configurations into $output_config.new\n";
2060fcb3f16aSSteven Rostedt
2061fcb3f16aSSteven Rostedt    open (OUT, ">$outconfig") or
2062fcb3f16aSSteven Rostedt	dodie "Can't create $outconfig";
2063fcb3f16aSSteven Rostedt
2064fcb3f16aSSteven Rostedt    if (-f $output_config) {
2065fcb3f16aSSteven Rostedt	open (IN, $output_config) or
2066fcb3f16aSSteven Rostedt	    dodie "Failed to open $output_config";
2067fcb3f16aSSteven Rostedt	while (<IN>) {
2068fcb3f16aSSteven Rostedt	    if (/^(# )?(CONFIG_[^\s=]*)/) {
2069fcb3f16aSSteven Rostedt		next if (defined($force_config{$2}));
2070fcb3f16aSSteven Rostedt	    }
2071fcb3f16aSSteven Rostedt	    print OUT;
2072fcb3f16aSSteven Rostedt	}
2073fcb3f16aSSteven Rostedt	close IN;
2074fcb3f16aSSteven Rostedt    }
2075fcb3f16aSSteven Rostedt    foreach my $config (keys %force_config) {
2076fcb3f16aSSteven Rostedt	print OUT "$force_config{$config}\n";
2077fcb3f16aSSteven Rostedt    }
2078fcb3f16aSSteven Rostedt    close OUT;
2079fcb3f16aSSteven Rostedt
2080fcb3f16aSSteven Rostedt    run_command "mv $outconfig $output_config";
2081fcb3f16aSSteven Rostedt}
2082fcb3f16aSSteven Rostedt
2083fcb3f16aSSteven Rostedtsub make_oldconfig {
2084fcb3f16aSSteven Rostedt
20854c4ab120SSteven Rostedt    my @force_list = keys %force_config;
20864c4ab120SSteven Rostedt
20874c4ab120SSteven Rostedt    if ($#force_list >= 0) {
2088fcb3f16aSSteven Rostedt	apply_min_config;
20894c4ab120SSteven Rostedt    }
2090fcb3f16aSSteven Rostedt
2091fb16d891SAdam Lee    if (!run_command "$make olddefconfig") {
2092fb16d891SAdam Lee	# Perhaps olddefconfig doesn't exist in this version of the kernel
209318925170SSteven Rostedt	# try oldnoconfig
209418925170SSteven Rostedt	doprint "olddefconfig failed, trying make oldnoconfig\n";
209518925170SSteven Rostedt	if (!run_command "$make oldnoconfig") {
209618925170SSteven Rostedt	    doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
2097612b9e9bSSteven Rostedt	    # try a yes '' | oldconfig
2098fcb3f16aSSteven Rostedt	    run_command "yes '' | $make oldconfig" or
2099612b9e9bSSteven Rostedt		dodie "failed make config oldconfig";
2100612b9e9bSSteven Rostedt	}
2101612b9e9bSSteven Rostedt    }
210218925170SSteven Rostedt}
2103612b9e9bSSteven Rostedt
2104fcb3f16aSSteven Rostedt# read a config file and use this to force new configs.
2105fcb3f16aSSteven Rostedtsub load_force_config {
2106fcb3f16aSSteven Rostedt    my ($config) = @_;
2107fcb3f16aSSteven Rostedt
2108cf79fab6SSteven Rostedt    doprint "Loading force configs from $config\n";
2109fcb3f16aSSteven Rostedt    open(IN, $config) or
2110fcb3f16aSSteven Rostedt	dodie "failed to read $config";
2111fcb3f16aSSteven Rostedt    while (<IN>) {
2112fcb3f16aSSteven Rostedt	chomp;
2113fcb3f16aSSteven Rostedt	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
2114fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
2115fcb3f16aSSteven Rostedt	} elsif (/^# (CONFIG_\S*) is not set/) {
2116fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
2117fcb3f16aSSteven Rostedt	}
2118fcb3f16aSSteven Rostedt    }
2119fcb3f16aSSteven Rostedt    close IN;
2120fcb3f16aSSteven Rostedt}
2121fcb3f16aSSteven Rostedt
21222545eb61SSteven Rostedtsub build {
21232545eb61SSteven Rostedt    my ($type) = @_;
21242545eb61SSteven Rostedt
21257faafbd6SSteven Rostedt    unlink $buildlog;
21267faafbd6SSteven Rostedt
21274ab1cce5SSteven Rostedt    # Failed builds should not reboot the target
21284ab1cce5SSteven Rostedt    my $save_no_reboot = $no_reboot;
21294ab1cce5SSteven Rostedt    $no_reboot = 1;
21304ab1cce5SSteven Rostedt
2131683a3e64SSteven Rostedt    # Calculate a new version from here.
2132683a3e64SSteven Rostedt    $have_version = 0;
2133683a3e64SSteven Rostedt
21340bd6c1a3SSteven Rostedt    if (defined($pre_build)) {
21350bd6c1a3SSteven Rostedt	my $ret = run_command $pre_build;
21360bd6c1a3SSteven Rostedt	if (!$ret && defined($pre_build_die) &&
21370bd6c1a3SSteven Rostedt	    $pre_build_die) {
21380bd6c1a3SSteven Rostedt	    dodie "failed to pre_build\n";
21390bd6c1a3SSteven Rostedt	}
21400bd6c1a3SSteven Rostedt    }
21410bd6c1a3SSteven Rostedt
214275c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
214351ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
214475c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
21455f9b6cedSSteven Rostedt
214675c3fda7SSteven Rostedt	$type = "oldconfig";
214775c3fda7SSteven Rostedt    }
214875c3fda7SSteven Rostedt
21495c42fc5bSSteven Rostedt    # old config can ask questions
21505c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
2151fb16d891SAdam Lee	$type = "olddefconfig";
215275c3fda7SSteven Rostedt
215375c3fda7SSteven Rostedt	# allow for empty configs
215451ad1dd1SSteven Rostedt	run_command "touch $output_config";
215575c3fda7SSteven Rostedt
215613488231SAndrew Jones	if (!$noclean) {
215751ad1dd1SSteven Rostedt	    run_command "mv $output_config $outputdir/config_temp" or
21585c42fc5bSSteven Rostedt		dodie "moving .config";
21595c42fc5bSSteven Rostedt
216013488231SAndrew Jones	    run_command "$make mrproper" or dodie "make mrproper";
21615c42fc5bSSteven Rostedt
216251ad1dd1SSteven Rostedt	    run_command "mv $outputdir/config_temp $output_config" or
21635c42fc5bSSteven Rostedt		dodie "moving config_temp";
216413488231SAndrew Jones	}
21655c42fc5bSSteven Rostedt
21665c42fc5bSSteven Rostedt    } elsif (!$noclean) {
216751ad1dd1SSteven Rostedt	unlink "$output_config";
21685f9b6cedSSteven Rostedt	run_command "$make mrproper" or
21695c42fc5bSSteven Rostedt	    dodie "make mrproper";
21705c42fc5bSSteven Rostedt    }
21712545eb61SSteven Rostedt
21722545eb61SSteven Rostedt    # add something to distinguish this build
2173a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
2174a75fececSSteven Rostedt    print OUT "$localversion\n";
21752545eb61SSteven Rostedt    close(OUT);
21762545eb61SSteven Rostedt
21775f9b6cedSSteven Rostedt    if (defined($minconfig)) {
2178fcb3f16aSSteven Rostedt	load_force_config($minconfig);
21792545eb61SSteven Rostedt    }
21802545eb61SSteven Rostedt
2181fb16d891SAdam Lee    if ($type ne "olddefconfig") {
2182fcb3f16aSSteven Rostedt	run_command "$make $type" or
21835c42fc5bSSteven Rostedt	    dodie "failed make config";
2184612b9e9bSSteven Rostedt    }
2185fcb3f16aSSteven Rostedt    # Run old config regardless, to enforce min configurations
2186fcb3f16aSSteven Rostedt    make_oldconfig;
21872545eb61SSteven Rostedt
2188a75fececSSteven Rostedt    $redirect = "$buildlog";
21890bd6c1a3SSteven Rostedt    my $build_ret = run_command "$make $build_options";
21906c5ee0beSSteven Rostedt    undef $redirect;
21910bd6c1a3SSteven Rostedt
21920bd6c1a3SSteven Rostedt    if (defined($post_build)) {
2193683a3e64SSteven Rostedt	# Because a post build may change the kernel version
2194683a3e64SSteven Rostedt	# do it now.
2195683a3e64SSteven Rostedt	get_version;
21960bd6c1a3SSteven Rostedt	my $ret = run_command $post_build;
21970bd6c1a3SSteven Rostedt	if (!$ret && defined($post_build_die) &&
21980bd6c1a3SSteven Rostedt	    $post_build_die) {
21990bd6c1a3SSteven Rostedt	    dodie "failed to post_build\n";
22000bd6c1a3SSteven Rostedt	}
22010bd6c1a3SSteven Rostedt    }
22020bd6c1a3SSteven Rostedt
22030bd6c1a3SSteven Rostedt    if (!$build_ret) {
22045f9b6cedSSteven Rostedt	# bisect may need this to pass
22054ab1cce5SSteven Rostedt	if ($in_bisect) {
22064ab1cce5SSteven Rostedt	    $no_reboot = $save_no_reboot;
22074ab1cce5SSteven Rostedt	    return 0;
22084ab1cce5SSteven Rostedt	}
22092b7d9b21SSteven Rostedt	fail "failed build" and return 0;
22102545eb61SSteven Rostedt    }
22115f9b6cedSSteven Rostedt
22124ab1cce5SSteven Rostedt    $no_reboot = $save_no_reboot;
22134ab1cce5SSteven Rostedt
22142b7d9b21SSteven Rostedt    return 1;
22152545eb61SSteven Rostedt}
22162545eb61SSteven Rostedt
221775c3fda7SSteven Rostedtsub halt {
2218e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
2219576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
2220576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
2221576f627cSSteven Rostedt	    run_command "$power_off";
2222576f627cSSteven Rostedt	}
2223576f627cSSteven Rostedt    } else {
222475c3fda7SSteven Rostedt	# nope? the zap it!
2225a75fececSSteven Rostedt	run_command "$power_off";
222675c3fda7SSteven Rostedt    }
222775c3fda7SSteven Rostedt}
222875c3fda7SSteven Rostedt
22295f9b6cedSSteven Rostedtsub success {
22305f9b6cedSSteven Rostedt    my ($i) = @_;
22315f9b6cedSSteven Rostedt
2232921ed4c7SSteven Rostedt    if (defined($post_test)) {
2233921ed4c7SSteven Rostedt	run_command $post_test;
2234921ed4c7SSteven Rostedt    }
2235921ed4c7SSteven Rostedt
2236e48c5293SSteven Rostedt    $successes++;
2237e48c5293SSteven Rostedt
22389064af52SSteven Rostedt    my $name = "";
22399064af52SSteven Rostedt
22409064af52SSteven Rostedt    if (defined($test_name)) {
22419064af52SSteven Rostedt	$name = " ($test_name)";
22429064af52SSteven Rostedt    }
22439064af52SSteven Rostedt
22445f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
22455f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
22469064af52SSteven Rostedt    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
22475f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
22485f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
22495f9b6cedSSteven Rostedt
2250de5b6e3bSRabin Vincent    if (defined($store_successes)) {
2251de5b6e3bSRabin Vincent        save_logs "success", $store_successes;
2252de5b6e3bSRabin Vincent    }
2253de5b6e3bSRabin Vincent
2254576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
2255a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
2256bc7c5803SSteven Rostedt	reboot_to_good $sleep_time;
22575f9b6cedSSteven Rostedt    }
22585f9b6cedSSteven Rostedt}
22595f9b6cedSSteven Rostedt
2260c960bb9fSSteven Rostedtsub answer_bisect {
2261c960bb9fSSteven Rostedt    for (;;) {
2262c960bb9fSSteven Rostedt	doprint "Pass or fail? [p/f]";
2263c960bb9fSSteven Rostedt	my $ans = <STDIN>;
2264c960bb9fSSteven Rostedt	chomp $ans;
2265c960bb9fSSteven Rostedt	if ($ans eq "p" || $ans eq "P") {
2266c960bb9fSSteven Rostedt	    return 1;
2267c960bb9fSSteven Rostedt	} elsif ($ans eq "f" || $ans eq "F") {
2268c960bb9fSSteven Rostedt	    return 0;
2269c960bb9fSSteven Rostedt	} else {
2270c960bb9fSSteven Rostedt	    print "Please answer 'P' or 'F'\n";
2271c960bb9fSSteven Rostedt	}
2272c960bb9fSSteven Rostedt    }
2273c960bb9fSSteven Rostedt}
2274c960bb9fSSteven Rostedt
22755a391fbfSSteven Rostedtsub child_run_test {
22767faafbd6SSteven Rostedt    my $failed = 0;
22775a391fbfSSteven Rostedt
22787faafbd6SSteven Rostedt    # child should have no power
2279a75fececSSteven Rostedt    $reboot_on_error = 0;
2280a75fececSSteven Rostedt    $poweroff_on_error = 0;
2281a75fececSSteven Rostedt    $die_on_failure = 1;
22827faafbd6SSteven Rostedt
2283a9dd5d63SRabin Vincent    $redirect = "$testlog";
22847faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
2285a9dd5d63SRabin Vincent    undef $redirect;
2286a9dd5d63SRabin Vincent
22875a391fbfSSteven Rostedt    exit $failed;
22885a391fbfSSteven Rostedt}
22895a391fbfSSteven Rostedt
22905a391fbfSSteven Rostedtmy $child_done;
22915a391fbfSSteven Rostedt
22925a391fbfSSteven Rostedtsub child_finished {
22935a391fbfSSteven Rostedt    $child_done = 1;
22945a391fbfSSteven Rostedt}
22955a391fbfSSteven Rostedt
22965a391fbfSSteven Rostedtsub do_run_test {
22975a391fbfSSteven Rostedt    my $child_pid;
22985a391fbfSSteven Rostedt    my $child_exit;
22995a391fbfSSteven Rostedt    my $line;
23005a391fbfSSteven Rostedt    my $full_line;
23015a391fbfSSteven Rostedt    my $bug = 0;
23029b1d367dSSteven Rostedt    my $bug_ignored = 0;
23035a391fbfSSteven Rostedt
23047faafbd6SSteven Rostedt    wait_for_monitor 1;
23055a391fbfSSteven Rostedt
23067faafbd6SSteven Rostedt    doprint "run test $run_test\n";
23075a391fbfSSteven Rostedt
23085a391fbfSSteven Rostedt    $child_done = 0;
23095a391fbfSSteven Rostedt
23105a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
23115a391fbfSSteven Rostedt
23125a391fbfSSteven Rostedt    $child_pid = fork;
23135a391fbfSSteven Rostedt
23145a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
23155a391fbfSSteven Rostedt
23165a391fbfSSteven Rostedt    $full_line = "";
23175a391fbfSSteven Rostedt
23185a391fbfSSteven Rostedt    do {
23197faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
23205a391fbfSSteven Rostedt	if (defined($line)) {
23215a391fbfSSteven Rostedt
23225a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
23235a391fbfSSteven Rostedt	    $full_line .= $line;
23248ea0e063SSteven Rostedt	    doprint $line;
23255a391fbfSSteven Rostedt
23265a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
23279b1d367dSSteven Rostedt		if ($ignore_errors) {
23289b1d367dSSteven Rostedt		    $bug_ignored = 1;
23299b1d367dSSteven Rostedt		} else {
23305a391fbfSSteven Rostedt		    $bug = 1;
23315a391fbfSSteven Rostedt		}
23329b1d367dSSteven Rostedt	    }
23335a391fbfSSteven Rostedt
23345a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
23355a391fbfSSteven Rostedt		$bug = 1;
23365a391fbfSSteven Rostedt	    }
23375a391fbfSSteven Rostedt
23385a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
23395a391fbfSSteven Rostedt		$full_line = "";
23405a391fbfSSteven Rostedt	    }
23415a391fbfSSteven Rostedt	}
23425a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
23435a391fbfSSteven Rostedt
23449b1d367dSSteven Rostedt    if (!$bug && $bug_ignored) {
23459b1d367dSSteven Rostedt	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
23469b1d367dSSteven Rostedt    }
23479b1d367dSSteven Rostedt
23485a391fbfSSteven Rostedt    if ($bug) {
23498ea0e063SSteven Rostedt	my $failure_start = time;
23508ea0e063SSteven Rostedt	my $now;
23518ea0e063SSteven Rostedt	do {
23528ea0e063SSteven Rostedt	    $line = wait_for_input($monitor_fp, 1);
23538ea0e063SSteven Rostedt	    if (defined($line)) {
23548ea0e063SSteven Rostedt		doprint $line;
23558ea0e063SSteven Rostedt	    }
23568ea0e063SSteven Rostedt	    $now = time;
23578ea0e063SSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
23588ea0e063SSteven Rostedt		last;
23598ea0e063SSteven Rostedt	    }
23608ea0e063SSteven Rostedt	} while (defined($line));
23618ea0e063SSteven Rostedt
23625a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
23635a391fbfSSteven Rostedt	# kill the child with extreme prejudice
23645a391fbfSSteven Rostedt	kill 9, $child_pid;
23655a391fbfSSteven Rostedt    }
23665a391fbfSSteven Rostedt
23675a391fbfSSteven Rostedt    waitpid $child_pid, 0;
23685a391fbfSSteven Rostedt    $child_exit = $?;
23695a391fbfSSteven Rostedt
2370c5dacb88SSteven Rostedt    if (!$bug && $in_bisect) {
2371c5dacb88SSteven Rostedt	if (defined($bisect_ret_good)) {
2372c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_good) {
2373c5dacb88SSteven Rostedt		return 1;
2374c5dacb88SSteven Rostedt	    }
2375c5dacb88SSteven Rostedt	}
2376c5dacb88SSteven Rostedt	if (defined($bisect_ret_skip)) {
2377c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_skip) {
2378c5dacb88SSteven Rostedt		return -1;
2379c5dacb88SSteven Rostedt	    }
2380c5dacb88SSteven Rostedt	}
2381c5dacb88SSteven Rostedt	if (defined($bisect_ret_abort)) {
2382c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_abort) {
2383c5dacb88SSteven Rostedt		fail "test abort" and return -2;
2384c5dacb88SSteven Rostedt	    }
2385c5dacb88SSteven Rostedt	}
2386c5dacb88SSteven Rostedt	if (defined($bisect_ret_bad)) {
2387c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_skip) {
2388c5dacb88SSteven Rostedt		return 0;
2389c5dacb88SSteven Rostedt	    }
2390c5dacb88SSteven Rostedt	}
2391c5dacb88SSteven Rostedt	if (defined($bisect_ret_default)) {
2392c5dacb88SSteven Rostedt	    if ($bisect_ret_default eq "good") {
2393c5dacb88SSteven Rostedt		return 1;
2394c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "bad") {
2395c5dacb88SSteven Rostedt		return 0;
2396c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "skip") {
2397c5dacb88SSteven Rostedt		return -1;
2398c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "abort") {
2399c5dacb88SSteven Rostedt		return -2;
2400c5dacb88SSteven Rostedt	    } else {
2401c5dacb88SSteven Rostedt		fail "unknown default action: $bisect_ret_default"
2402c5dacb88SSteven Rostedt		    and return -2;
2403c5dacb88SSteven Rostedt	    }
2404c5dacb88SSteven Rostedt	}
2405c5dacb88SSteven Rostedt    }
2406c5dacb88SSteven Rostedt
24075a391fbfSSteven Rostedt    if ($bug || $child_exit) {
24082b7d9b21SSteven Rostedt	return 0 if $in_bisect;
24092b7d9b21SSteven Rostedt	fail "test failed" and return 0;
24105a391fbfSSteven Rostedt    }
24112b7d9b21SSteven Rostedt    return 1;
24125a391fbfSSteven Rostedt}
24135a391fbfSSteven Rostedt
2414a75fececSSteven Rostedtsub run_git_bisect {
2415a75fececSSteven Rostedt    my ($command) = @_;
2416a75fececSSteven Rostedt
2417a75fececSSteven Rostedt    doprint "$command ... ";
2418a75fececSSteven Rostedt
2419a75fececSSteven Rostedt    my $output = `$command 2>&1`;
2420a75fececSSteven Rostedt    my $ret = $?;
2421a75fececSSteven Rostedt
2422a75fececSSteven Rostedt    logit $output;
2423a75fececSSteven Rostedt
2424a75fececSSteven Rostedt    if ($ret) {
2425a75fececSSteven Rostedt	doprint "FAILED\n";
2426a75fececSSteven Rostedt	dodie "Failed to git bisect";
2427a75fececSSteven Rostedt    }
2428a75fececSSteven Rostedt
2429a75fececSSteven Rostedt    doprint "SUCCESS\n";
2430a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
2431a75fececSSteven Rostedt	doprint "$1 [$2]\n";
2432a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
2433b5f4aea6SSteven Rostedt	$bisect_bad_commit = $1;
2434a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
2435a75fececSSteven Rostedt	return 0;
2436a75fececSSteven Rostedt    } else {
2437a75fececSSteven Rostedt	# we already logged it, just print it now.
2438a75fececSSteven Rostedt	print $output;
2439a75fececSSteven Rostedt    }
2440a75fececSSteven Rostedt
2441a75fececSSteven Rostedt    return 1;
2442a75fececSSteven Rostedt}
2443a75fececSSteven Rostedt
2444c23dca7cSSteven Rostedtsub bisect_reboot {
2445c23dca7cSSteven Rostedt    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
2446bc7c5803SSteven Rostedt    reboot_to_good $bisect_sleep_time;
2447c23dca7cSSteven Rostedt}
2448c23dca7cSSteven Rostedt
2449c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip
24500a05c769SSteven Rostedtsub run_bisect_test {
24510a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
24525f9b6cedSSteven Rostedt
24532b7d9b21SSteven Rostedt    my $failed = 0;
24545f9b6cedSSteven Rostedt    my $result;
24555f9b6cedSSteven Rostedt    my $output;
24565f9b6cedSSteven Rostedt    my $ret;
24575f9b6cedSSteven Rostedt
24580a05c769SSteven Rostedt    $in_bisect = 1;
24590a05c769SSteven Rostedt
24600a05c769SSteven Rostedt    build $buildtype or $failed = 1;
24615f9b6cedSSteven Rostedt
24625f9b6cedSSteven Rostedt    if ($type ne "build") {
2463c23dca7cSSteven Rostedt	if ($failed && $bisect_skip) {
2464c23dca7cSSteven Rostedt	    $in_bisect = 0;
2465c23dca7cSSteven Rostedt	    return -1;
2466c23dca7cSSteven Rostedt	}
24677faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
24685f9b6cedSSteven Rostedt
24695f9b6cedSSteven Rostedt	# Now boot the box
2470ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
24715f9b6cedSSteven Rostedt
24725f9b6cedSSteven Rostedt	if ($type ne "boot") {
2473c23dca7cSSteven Rostedt	    if ($failed && $bisect_skip) {
2474c23dca7cSSteven Rostedt		end_monitor;
2475c23dca7cSSteven Rostedt		bisect_reboot;
2476c23dca7cSSteven Rostedt		$in_bisect = 0;
2477c23dca7cSSteven Rostedt		return -1;
2478c23dca7cSSteven Rostedt	    }
24797faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
24805a391fbfSSteven Rostedt
24812b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
24825f9b6cedSSteven Rostedt	}
24837faafbd6SSteven Rostedt	end_monitor;
24845f9b6cedSSteven Rostedt    }
24855f9b6cedSSteven Rostedt
24865f9b6cedSSteven Rostedt    if ($failed) {
24870a05c769SSteven Rostedt	$result = 0;
24885f9b6cedSSteven Rostedt    } else {
24890a05c769SSteven Rostedt	$result = 1;
24905f9b6cedSSteven Rostedt    }
24914025bc62SSteven Rostedt
24924025bc62SSteven Rostedt    # reboot the box to a kernel we can ssh to
24934025bc62SSteven Rostedt    if ($type ne "build") {
24944025bc62SSteven Rostedt	bisect_reboot;
24954025bc62SSteven Rostedt    }
24960a05c769SSteven Rostedt    $in_bisect = 0;
24970a05c769SSteven Rostedt
24980a05c769SSteven Rostedt    return $result;
24990a05c769SSteven Rostedt}
25000a05c769SSteven Rostedt
25010a05c769SSteven Rostedtsub run_bisect {
25020a05c769SSteven Rostedt    my ($type) = @_;
25030a05c769SSteven Rostedt    my $buildtype = "oldconfig";
25040a05c769SSteven Rostedt
25050a05c769SSteven Rostedt    # We should have a minconfig to use?
25060a05c769SSteven Rostedt    if (defined($minconfig)) {
25070a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
25080a05c769SSteven Rostedt    }
25090a05c769SSteven Rostedt
25100a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
25110a05c769SSteven Rostedt
2512c960bb9fSSteven Rostedt    if ($bisect_manual) {
2513c960bb9fSSteven Rostedt	$ret = answer_bisect;
2514c960bb9fSSteven Rostedt    }
25155f9b6cedSSteven Rostedt
2516d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
25175158ba3eSRuss Dill    if ($reverse_bisect && $ret >= 0) {
25180a05c769SSteven Rostedt	$ret = !$ret;
2519d6ce2a0bSSteven Rostedt    }
2520d6ce2a0bSSteven Rostedt
2521c23dca7cSSteven Rostedt    if ($ret > 0) {
25220a05c769SSteven Rostedt	return "good";
2523c23dca7cSSteven Rostedt    } elsif ($ret == 0) {
25240a05c769SSteven Rostedt	return  "bad";
2525c23dca7cSSteven Rostedt    } elsif ($bisect_skip) {
2526c23dca7cSSteven Rostedt	doprint "HIT A BAD COMMIT ... SKIPPING\n";
2527c23dca7cSSteven Rostedt	return "skip";
25280a05c769SSteven Rostedt    }
25295f9b6cedSSteven Rostedt}
25305f9b6cedSSteven Rostedt
2531dad98754SSteven Rostedtsub update_bisect_replay {
2532dad98754SSteven Rostedt    my $tmp_log = "$tmpdir/ktest_bisect_log";
2533dad98754SSteven Rostedt    run_command "git bisect log > $tmp_log" or
2534dad98754SSteven Rostedt	die "can't create bisect log";
2535dad98754SSteven Rostedt    return $tmp_log;
2536dad98754SSteven Rostedt}
2537dad98754SSteven Rostedt
25385f9b6cedSSteven Rostedtsub bisect {
25395f9b6cedSSteven Rostedt    my ($i) = @_;
25405f9b6cedSSteven Rostedt
25415f9b6cedSSteven Rostedt    my $result;
25425f9b6cedSSteven Rostedt
2543b5f4aea6SSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($bisect_good));
2544b5f4aea6SSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($bisect_bad));
2545b5f4aea6SSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($bisect_type));
25465f9b6cedSSteven Rostedt
2547b5f4aea6SSteven Rostedt    my $good = $bisect_good;
2548b5f4aea6SSteven Rostedt    my $bad = $bisect_bad;
2549b5f4aea6SSteven Rostedt    my $type = $bisect_type;
2550b5f4aea6SSteven Rostedt    my $start = $bisect_start;
2551b5f4aea6SSteven Rostedt    my $replay = $bisect_replay;
2552b5f4aea6SSteven Rostedt    my $start_files = $bisect_files;
25533410f6fdSSteven Rostedt
25543410f6fdSSteven Rostedt    if (defined($start_files)) {
25553410f6fdSSteven Rostedt	$start_files = " -- " . $start_files;
25563410f6fdSSteven Rostedt    } else {
25573410f6fdSSteven Rostedt	$start_files = "";
25583410f6fdSSteven Rostedt    }
25595f9b6cedSSteven Rostedt
2560a57419b3SSteven Rostedt    # convert to true sha1's
2561a57419b3SSteven Rostedt    $good = get_sha1($good);
2562a57419b3SSteven Rostedt    $bad = get_sha1($bad);
2563a57419b3SSteven Rostedt
2564b5f4aea6SSteven Rostedt    if (defined($bisect_reverse) && $bisect_reverse == 1) {
2565d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
2566d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
2567d6ce2a0bSSteven Rostedt    } else {
2568d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
2569d6ce2a0bSSteven Rostedt    }
2570d6ce2a0bSSteven Rostedt
25715a391fbfSSteven Rostedt    # Can't have a test without having a test to run
25725a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
25735a391fbfSSteven Rostedt	$type = "boot";
25745a391fbfSSteven Rostedt    }
25755a391fbfSSteven Rostedt
2576dad98754SSteven Rostedt    # Check if a bisect was running
2577dad98754SSteven Rostedt    my $bisect_start_file = "$builddir/.git/BISECT_START";
2578dad98754SSteven Rostedt
2579b5f4aea6SSteven Rostedt    my $check = $bisect_check;
2580dad98754SSteven Rostedt    my $do_check = defined($check) && $check ne "0";
2581dad98754SSteven Rostedt
2582dad98754SSteven Rostedt    if ( -f $bisect_start_file ) {
2583dad98754SSteven Rostedt	print "Bisect in progress found\n";
2584dad98754SSteven Rostedt	if ($do_check) {
2585dad98754SSteven Rostedt	    print " If you say yes, then no checks of good or bad will be done\n";
2586dad98754SSteven Rostedt	}
2587dad98754SSteven Rostedt	if (defined($replay)) {
2588dad98754SSteven Rostedt	    print "** BISECT_REPLAY is defined in config file **";
2589dad98754SSteven Rostedt	    print " Ignore config option and perform new git bisect log?\n";
2590dad98754SSteven Rostedt	    if (read_ync " (yes, no, or cancel) ") {
2591dad98754SSteven Rostedt		$replay = update_bisect_replay;
2592dad98754SSteven Rostedt		$do_check = 0;
2593dad98754SSteven Rostedt	    }
2594dad98754SSteven Rostedt	} elsif (read_yn "read git log and continue?") {
2595dad98754SSteven Rostedt	    $replay = update_bisect_replay;
2596dad98754SSteven Rostedt	    $do_check = 0;
2597dad98754SSteven Rostedt	}
2598dad98754SSteven Rostedt    }
2599dad98754SSteven Rostedt
2600dad98754SSteven Rostedt    if ($do_check) {
2601a75fececSSteven Rostedt
2602a75fececSSteven Rostedt	# get current HEAD
2603a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
2604a75fececSSteven Rostedt
2605a75fececSSteven Rostedt	if ($check ne "good") {
2606a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
2607a75fececSSteven Rostedt	    run_command "git checkout $bad" or
2608a75fececSSteven Rostedt		die "Failed to checkout $bad";
2609a75fececSSteven Rostedt
2610a75fececSSteven Rostedt	    $result = run_bisect $type;
2611a75fececSSteven Rostedt
2612a75fececSSteven Rostedt	    if ($result ne "bad") {
2613a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
2614a75fececSSteven Rostedt	    }
2615a75fececSSteven Rostedt	}
2616a75fececSSteven Rostedt
2617a75fececSSteven Rostedt	if ($check ne "bad") {
2618a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
2619a75fececSSteven Rostedt	    run_command "git checkout $good" or
2620a75fececSSteven Rostedt		die "Failed to checkout $good";
2621a75fececSSteven Rostedt
2622a75fececSSteven Rostedt	    $result = run_bisect $type;
2623a75fececSSteven Rostedt
2624a75fececSSteven Rostedt	    if ($result ne "good") {
2625a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
2626a75fececSSteven Rostedt	    }
2627a75fececSSteven Rostedt	}
2628a75fececSSteven Rostedt
2629a75fececSSteven Rostedt	# checkout where we started
2630a75fececSSteven Rostedt	run_command "git checkout $head" or
2631a75fececSSteven Rostedt	    die "Failed to checkout $head";
2632a75fececSSteven Rostedt    }
2633a75fececSSteven Rostedt
26343410f6fdSSteven Rostedt    run_command "git bisect start$start_files" or
2635a75fececSSteven Rostedt	dodie "could not start bisect";
2636a75fececSSteven Rostedt
2637a75fececSSteven Rostedt    run_command "git bisect good $good" or
2638a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
2639a75fececSSteven Rostedt
2640a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
2641a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
2642a75fececSSteven Rostedt
2643a75fececSSteven Rostedt    if (defined($replay)) {
2644a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
2645a75fececSSteven Rostedt	    dodie "failed to run replay";
2646a75fececSSteven Rostedt    }
2647a75fececSSteven Rostedt
2648a75fececSSteven Rostedt    if (defined($start)) {
2649a75fececSSteven Rostedt	run_command "git checkout $start" or
2650a75fececSSteven Rostedt	    dodie "failed to checkout $start";
2651a75fececSSteven Rostedt    }
2652a75fececSSteven Rostedt
2653a75fececSSteven Rostedt    my $test;
26545f9b6cedSSteven Rostedt    do {
26555f9b6cedSSteven Rostedt	$result = run_bisect $type;
2656a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
2657a75fececSSteven Rostedt    } while ($test);
26585f9b6cedSSteven Rostedt
26595f9b6cedSSteven Rostedt    run_command "git bisect log" or
26605f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
26615f9b6cedSSteven Rostedt
26625f9b6cedSSteven Rostedt    run_command "git bisect reset" or
26635f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
26645f9b6cedSSteven Rostedt
2665b5f4aea6SSteven Rostedt    doprint "Bad commit was [$bisect_bad_commit]\n";
26665f9b6cedSSteven Rostedt
26670a05c769SSteven Rostedt    success $i;
26680a05c769SSteven Rostedt}
26690a05c769SSteven Rostedt
2670cf79fab6SSteven Rostedt# config_ignore holds the configs that were set (or unset) for
2671cf79fab6SSteven Rostedt# a good config and we will ignore these configs for the rest
2672cf79fab6SSteven Rostedt# of a config bisect. These configs stay as they were.
26730a05c769SSteven Rostedtmy %config_ignore;
2674cf79fab6SSteven Rostedt
2675cf79fab6SSteven Rostedt# config_set holds what all configs were set as.
26760a05c769SSteven Rostedtmy %config_set;
26770a05c769SSteven Rostedt
2678cf79fab6SSteven Rostedt# config_off holds the set of configs that the bad config had disabled.
2679cf79fab6SSteven Rostedt# We need to record them and set them in the .config when running
2680fb16d891SAdam Lee# olddefconfig, because olddefconfig keeps the defaults.
2681cf79fab6SSteven Rostedtmy %config_off;
2682cf79fab6SSteven Rostedt
2683cf79fab6SSteven Rostedt# config_off_tmp holds a set of configs to turn off for now
2684cf79fab6SSteven Rostedtmy @config_off_tmp;
2685cf79fab6SSteven Rostedt
2686cf79fab6SSteven Rostedt# config_list is the set of configs that are being tested
26870a05c769SSteven Rostedtmy %config_list;
26880a05c769SSteven Rostedtmy %null_config;
26890a05c769SSteven Rostedt
26900a05c769SSteven Rostedtmy %dependency;
26910a05c769SSteven Rostedt
26924c4ab120SSteven Rostedtsub assign_configs {
26934c4ab120SSteven Rostedt    my ($hash, $config) = @_;
26940a05c769SSteven Rostedt
26950a05c769SSteven Rostedt    open (IN, $config)
26960a05c769SSteven Rostedt	or dodie "Failed to read $config";
26970a05c769SSteven Rostedt
26980a05c769SSteven Rostedt    while (<IN>) {
26999bf71749SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
27004c4ab120SSteven Rostedt	    ${$hash}{$2} = $1;
27010a05c769SSteven Rostedt	}
27020a05c769SSteven Rostedt    }
27030a05c769SSteven Rostedt
27040a05c769SSteven Rostedt    close(IN);
27050a05c769SSteven Rostedt}
27060a05c769SSteven Rostedt
27074c4ab120SSteven Rostedtsub process_config_ignore {
27084c4ab120SSteven Rostedt    my ($config) = @_;
27094c4ab120SSteven Rostedt
27104c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
27114c4ab120SSteven Rostedt}
27124c4ab120SSteven Rostedt
27130a05c769SSteven Rostedtsub read_current_config {
27140a05c769SSteven Rostedt    my ($config_ref) = @_;
27150a05c769SSteven Rostedt
27160a05c769SSteven Rostedt    %{$config_ref} = ();
27170a05c769SSteven Rostedt    undef %{$config_ref};
27180a05c769SSteven Rostedt
27190a05c769SSteven Rostedt    my @key = keys %{$config_ref};
27200a05c769SSteven Rostedt    if ($#key >= 0) {
27210a05c769SSteven Rostedt	print "did not delete!\n";
27220a05c769SSteven Rostedt	exit;
27230a05c769SSteven Rostedt    }
27240a05c769SSteven Rostedt    open (IN, "$output_config");
27250a05c769SSteven Rostedt
27260a05c769SSteven Rostedt    while (<IN>) {
27270a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
27280a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
27290a05c769SSteven Rostedt	}
27300a05c769SSteven Rostedt    }
27310a05c769SSteven Rostedt    close(IN);
27320a05c769SSteven Rostedt}
27330a05c769SSteven Rostedt
27340a05c769SSteven Rostedtsub get_dependencies {
27350a05c769SSteven Rostedt    my ($config) = @_;
27360a05c769SSteven Rostedt
27370a05c769SSteven Rostedt    my $arr = $dependency{$config};
27380a05c769SSteven Rostedt    if (!defined($arr)) {
27390a05c769SSteven Rostedt	return ();
27400a05c769SSteven Rostedt    }
27410a05c769SSteven Rostedt
27420a05c769SSteven Rostedt    my @deps = @{$arr};
27430a05c769SSteven Rostedt
27440a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
27450a05c769SSteven Rostedt	print "ADD DEP $dep\n";
27460a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
27470a05c769SSteven Rostedt    }
27480a05c769SSteven Rostedt
27490a05c769SSteven Rostedt    return @deps;
27500a05c769SSteven Rostedt}
27510a05c769SSteven Rostedt
27520a05c769SSteven Rostedtsub create_config {
27530a05c769SSteven Rostedt    my @configs = @_;
27540a05c769SSteven Rostedt
27550a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
27560a05c769SSteven Rostedt
27570a05c769SSteven Rostedt    foreach my $config (@configs) {
27580a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
27590a05c769SSteven Rostedt	my @deps = get_dependencies $config;
27600a05c769SSteven Rostedt	foreach my $dep (@deps) {
27610a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
27620a05c769SSteven Rostedt	}
27630a05c769SSteven Rostedt    }
27640a05c769SSteven Rostedt
2765cf79fab6SSteven Rostedt    # turn off configs to keep off
2766cf79fab6SSteven Rostedt    foreach my $config (keys %config_off) {
2767cf79fab6SSteven Rostedt	print OUT "# $config is not set\n";
2768cf79fab6SSteven Rostedt    }
2769cf79fab6SSteven Rostedt
2770cf79fab6SSteven Rostedt    # turn off configs that should be off for now
2771cf79fab6SSteven Rostedt    foreach my $config (@config_off_tmp) {
2772cf79fab6SSteven Rostedt	print OUT "# $config is not set\n";
2773cf79fab6SSteven Rostedt    }
2774cf79fab6SSteven Rostedt
27750a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
27760a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
27770a05c769SSteven Rostedt    }
27780a05c769SSteven Rostedt    close(OUT);
27790a05c769SSteven Rostedt
2780fcb3f16aSSteven Rostedt    make_oldconfig;
27810a05c769SSteven Rostedt}
27820a05c769SSteven Rostedt
27830a05c769SSteven Rostedtsub compare_configs {
27840a05c769SSteven Rostedt    my (%a, %b) = @_;
27850a05c769SSteven Rostedt
27860a05c769SSteven Rostedt    foreach my $item (keys %a) {
27870a05c769SSteven Rostedt	if (!defined($b{$item})) {
27880a05c769SSteven Rostedt	    print "diff $item\n";
27890a05c769SSteven Rostedt	    return 1;
27900a05c769SSteven Rostedt	}
27910a05c769SSteven Rostedt	delete $b{$item};
27920a05c769SSteven Rostedt    }
27930a05c769SSteven Rostedt
27940a05c769SSteven Rostedt    my @keys = keys %b;
27950a05c769SSteven Rostedt    if ($#keys) {
27960a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
27970a05c769SSteven Rostedt    }
27980a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
27990a05c769SSteven Rostedt
28000a05c769SSteven Rostedt    return 0;
28010a05c769SSteven Rostedt}
28020a05c769SSteven Rostedt
28030a05c769SSteven Rostedtsub run_config_bisect_test {
28040a05c769SSteven Rostedt    my ($type) = @_;
28050a05c769SSteven Rostedt
28060a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
28070a05c769SSteven Rostedt}
28080a05c769SSteven Rostedt
28090a05c769SSteven Rostedtsub process_passed {
28100a05c769SSteven Rostedt    my (%configs) = @_;
28110a05c769SSteven Rostedt
28120a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
28130a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
28140a05c769SSteven Rostedt    # Add them to the min options.
28150a05c769SSteven Rostedt    foreach my $config (keys %configs) {
28160a05c769SSteven Rostedt	if (defined($config_list{$config})) {
28170a05c769SSteven Rostedt	    doprint " removing $config\n";
28180a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
28190a05c769SSteven Rostedt	    delete $config_list{$config};
28200a05c769SSteven Rostedt	}
28210a05c769SSteven Rostedt    }
2822f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
2823f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
28240a05c769SSteven Rostedt}
28250a05c769SSteven Rostedt
28260a05c769SSteven Rostedtsub process_failed {
28270a05c769SSteven Rostedt    my ($config) = @_;
28280a05c769SSteven Rostedt
28290a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
28300a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
28310a05c769SSteven Rostedt    doprint "***************************************\n\n";
28320a05c769SSteven Rostedt}
28330a05c769SSteven Rostedt
28340a05c769SSteven Rostedtsub run_config_bisect {
28350a05c769SSteven Rostedt
28360a05c769SSteven Rostedt    my @start_list = keys %config_list;
28370a05c769SSteven Rostedt
28380a05c769SSteven Rostedt    if ($#start_list < 0) {
28390a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
28400a05c769SSteven Rostedt	return -1;
28410a05c769SSteven Rostedt    }
28420a05c769SSteven Rostedt
28430a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
2844b5f4aea6SSteven Rostedt    my $type = $config_bisect_type;
28450a05c769SSteven Rostedt    my $ret;
28460a05c769SSteven Rostedt    my %current_config;
28470a05c769SSteven Rostedt
28480a05c769SSteven Rostedt    my $count = $#start_list + 1;
28490a05c769SSteven Rostedt    doprint "  $count configs to test\n";
28500a05c769SSteven Rostedt
28510a05c769SSteven Rostedt    my $half = int($#start_list / 2);
28520a05c769SSteven Rostedt
28530a05c769SSteven Rostedt    do {
28540a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
28550a05c769SSteven Rostedt
2856cf79fab6SSteven Rostedt	# keep the bottom half off
2857cf79fab6SSteven Rostedt	if ($half < $#start_list) {
2858cf79fab6SSteven Rostedt	    @config_off_tmp = @start_list[$half + 1 .. $#start_list];
2859cf79fab6SSteven Rostedt	} else {
2860cf79fab6SSteven Rostedt	    @config_off_tmp = ();
2861cf79fab6SSteven Rostedt	}
2862cf79fab6SSteven Rostedt
28630a05c769SSteven Rostedt	create_config @tophalf;
28640a05c769SSteven Rostedt	read_current_config \%current_config;
28650a05c769SSteven Rostedt
28660a05c769SSteven Rostedt	$count = $#tophalf + 1;
28670a05c769SSteven Rostedt	doprint "Testing $count configs\n";
28680a05c769SSteven Rostedt	my $found = 0;
28690a05c769SSteven Rostedt	# make sure we test something
28700a05c769SSteven Rostedt	foreach my $config (@tophalf) {
28710a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
28720a05c769SSteven Rostedt		logit " $config\n";
28730a05c769SSteven Rostedt		$found = 1;
28740a05c769SSteven Rostedt	    }
28750a05c769SSteven Rostedt	}
28760a05c769SSteven Rostedt	if (!$found) {
28770a05c769SSteven Rostedt	    # try the other half
28780a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
2879cf79fab6SSteven Rostedt
2880cf79fab6SSteven Rostedt	    # keep the top half off
2881cf79fab6SSteven Rostedt	    @config_off_tmp = @tophalf;
28824c8cc55bSSteven Rostedt	    @tophalf = @start_list[$half + 1 .. $#start_list];
2883cf79fab6SSteven Rostedt
28840a05c769SSteven Rostedt	    create_config @tophalf;
28850a05c769SSteven Rostedt	    read_current_config \%current_config;
28860a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
28870a05c769SSteven Rostedt		if (defined($current_config{$config})) {
28880a05c769SSteven Rostedt		    logit " $config\n";
28890a05c769SSteven Rostedt		    $found = 1;
28900a05c769SSteven Rostedt		}
28910a05c769SSteven Rostedt	    }
28920a05c769SSteven Rostedt	    if (!$found) {
28930a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
28940a05c769SSteven Rostedt		foreach my $config (@start_list) {
28950a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
28960a05c769SSteven Rostedt		}
28970a05c769SSteven Rostedt		return -1;
28980a05c769SSteven Rostedt	    }
28990a05c769SSteven Rostedt	    $count = $#tophalf + 1;
29000a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
29010a05c769SSteven Rostedt	}
29020a05c769SSteven Rostedt
29030a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
2904c960bb9fSSteven Rostedt	if ($bisect_manual) {
2905c960bb9fSSteven Rostedt	    $ret = answer_bisect;
2906c960bb9fSSteven Rostedt	}
29070a05c769SSteven Rostedt	if ($ret) {
29080a05c769SSteven Rostedt	    process_passed %current_config;
29090a05c769SSteven Rostedt	    return 0;
29100a05c769SSteven Rostedt	}
29110a05c769SSteven Rostedt
29120a05c769SSteven Rostedt	doprint "This config had a failure.\n";
29130a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
2914f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
2915f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
29160a05c769SSteven Rostedt
29170a05c769SSteven Rostedt	# A config exists in this group that was bad.
29180a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
29190a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
29200a05c769SSteven Rostedt		doprint " removing $config\n";
29210a05c769SSteven Rostedt		delete $config_list{$config};
29220a05c769SSteven Rostedt	    }
29230a05c769SSteven Rostedt	}
29240a05c769SSteven Rostedt
29250a05c769SSteven Rostedt	@start_list = @tophalf;
29260a05c769SSteven Rostedt
29270a05c769SSteven Rostedt	if ($#start_list == 0) {
29280a05c769SSteven Rostedt	    process_failed $start_list[0];
29290a05c769SSteven Rostedt	    return 1;
29300a05c769SSteven Rostedt	}
29310a05c769SSteven Rostedt
29320a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
29330a05c769SSteven Rostedt	# they are good.
29340a05c769SSteven Rostedt	$half = int($#start_list / 2);
29354c8cc55bSSteven Rostedt    } while ($#start_list > 0);
29360a05c769SSteven Rostedt
2937c960bb9fSSteven Rostedt    # we found a single config, try it again unless we are running manually
2938c960bb9fSSteven Rostedt
2939c960bb9fSSteven Rostedt    if ($bisect_manual) {
2940c960bb9fSSteven Rostedt	process_failed $start_list[0];
2941c960bb9fSSteven Rostedt	return 1;
2942c960bb9fSSteven Rostedt    }
2943c960bb9fSSteven Rostedt
29440a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
29450a05c769SSteven Rostedt
29460a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
29470a05c769SSteven Rostedt    if ($ret) {
29480a05c769SSteven Rostedt	process_passed %current_config;
29490a05c769SSteven Rostedt	return 0;
29500a05c769SSteven Rostedt    }
29510a05c769SSteven Rostedt
29520a05c769SSteven Rostedt    process_failed $start_list[0];
29530a05c769SSteven Rostedt    return 1;
29540a05c769SSteven Rostedt}
29550a05c769SSteven Rostedt
29560a05c769SSteven Rostedtsub config_bisect {
29570a05c769SSteven Rostedt    my ($i) = @_;
29580a05c769SSteven Rostedt
2959b5f4aea6SSteven Rostedt    my $start_config = $config_bisect;
29600a05c769SSteven Rostedt
29610a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
29620a05c769SSteven Rostedt
296330f75da5SSteven Rostedt    if (defined($config_bisect_good)) {
296430f75da5SSteven Rostedt	process_config_ignore $config_bisect_good;
296530f75da5SSteven Rostedt    }
296630f75da5SSteven Rostedt
29670a05c769SSteven Rostedt    # Make the file with the bad config and the min config
29680a05c769SSteven Rostedt    if (defined($minconfig)) {
29690a05c769SSteven Rostedt	# read the min config for things to ignore
29700a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
29710a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
29720a05c769SSteven Rostedt    } else {
29730a05c769SSteven Rostedt	unlink $tmpconfig;
29740a05c769SSteven Rostedt    }
29750a05c769SSteven Rostedt
29760a05c769SSteven Rostedt    if (-f $tmpconfig) {
2977fcb3f16aSSteven Rostedt	load_force_config($tmpconfig);
29780a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
29790a05c769SSteven Rostedt    }
29800a05c769SSteven Rostedt
29810a05c769SSteven Rostedt    # now process the start config
29820a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
29830a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
29840a05c769SSteven Rostedt
29850a05c769SSteven Rostedt    # read directly what we want to check
29860a05c769SSteven Rostedt    my %config_check;
29870a05c769SSteven Rostedt    open (IN, $output_config)
2988f9dee311SMasanari Iida	or dodie "failed to open $output_config";
29890a05c769SSteven Rostedt
29900a05c769SSteven Rostedt    while (<IN>) {
29910a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
29920a05c769SSteven Rostedt	    $config_check{$2} = $1;
29930a05c769SSteven Rostedt	}
29940a05c769SSteven Rostedt    }
29950a05c769SSteven Rostedt    close(IN);
29960a05c769SSteven Rostedt
2997250bae8bSSteven Rostedt    # Now run oldconfig with the minconfig
2998fcb3f16aSSteven Rostedt    make_oldconfig;
29990a05c769SSteven Rostedt
30000a05c769SSteven Rostedt    # check to see what we lost (or gained)
30010a05c769SSteven Rostedt    open (IN, $output_config)
30020a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
30030a05c769SSteven Rostedt
30040a05c769SSteven Rostedt    my %removed_configs;
30050a05c769SSteven Rostedt    my %added_configs;
30060a05c769SSteven Rostedt
30070a05c769SSteven Rostedt    while (<IN>) {
30080a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
30090a05c769SSteven Rostedt	    # save off all options
30100a05c769SSteven Rostedt	    $config_set{$2} = $1;
30110a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
30120a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
30130a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
30140a05c769SSteven Rostedt		} else {
30150a05c769SSteven Rostedt		    $config_list{$2} = $1;
30160a05c769SSteven Rostedt		}
30170a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
30180a05c769SSteven Rostedt		$added_configs{$2} = $1;
30190a05c769SSteven Rostedt		$config_list{$2} = $1;
30200a05c769SSteven Rostedt	    }
3021cf79fab6SSteven Rostedt	} elsif (/^# ((CONFIG\S*).*)/) {
3022cf79fab6SSteven Rostedt	    # Keep these configs disabled
3023cf79fab6SSteven Rostedt	    $config_set{$2} = $1;
3024cf79fab6SSteven Rostedt	    $config_off{$2} = $1;
30250a05c769SSteven Rostedt	}
30260a05c769SSteven Rostedt    }
30270a05c769SSteven Rostedt    close(IN);
30280a05c769SSteven Rostedt
30290a05c769SSteven Rostedt    my @confs = keys %removed_configs;
30300a05c769SSteven Rostedt    if ($#confs >= 0) {
30310a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
30320a05c769SSteven Rostedt	foreach my $config (@confs) {
30330a05c769SSteven Rostedt	    doprint " $config\n";
30340a05c769SSteven Rostedt	}
30350a05c769SSteven Rostedt    }
30360a05c769SSteven Rostedt    @confs = keys %added_configs;
30370a05c769SSteven Rostedt    if ($#confs >= 0) {
30380a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
30390a05c769SSteven Rostedt	foreach my $config (@confs) {
30400a05c769SSteven Rostedt	    doprint " $config\n";
30410a05c769SSteven Rostedt	}
30420a05c769SSteven Rostedt    }
30430a05c769SSteven Rostedt
30440a05c769SSteven Rostedt    my %config_test;
30450a05c769SSteven Rostedt    my $once = 0;
30460a05c769SSteven Rostedt
3047cf79fab6SSteven Rostedt    @config_off_tmp = ();
3048cf79fab6SSteven Rostedt
30490a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
30500a05c769SSteven Rostedt    # that the config we autocreate has everything we need
30510a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
30520a05c769SSteven Rostedt    # may not be able to create a new config.
30530a05c769SSteven Rostedt    # Here we create a config with everything set.
30540a05c769SSteven Rostedt    create_config (keys %config_list);
30550a05c769SSteven Rostedt    read_current_config \%config_test;
30560a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
30570a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
30580a05c769SSteven Rostedt	    if (!$once) {
30590a05c769SSteven Rostedt		$once = 1;
30600a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
30610a05c769SSteven Rostedt	    }
30620a05c769SSteven Rostedt	    doprint "  $config\n";
30630a05c769SSteven Rostedt	    delete $config_list{$config};
30640a05c769SSteven Rostedt	}
30650a05c769SSteven Rostedt    }
30660a05c769SSteven Rostedt    my $ret;
3067b0918612SSteven Rostedt
3068b0918612SSteven Rostedt    if (defined($config_bisect_check) && $config_bisect_check) {
3069b0918612SSteven Rostedt	doprint " Checking to make sure bad config with min config fails\n";
3070b0918612SSteven Rostedt	create_config keys %config_list;
3071b0918612SSteven Rostedt	$ret = run_config_bisect_test $config_bisect_type;
3072b0918612SSteven Rostedt	if ($ret) {
3073b0918612SSteven Rostedt	    doprint " FAILED! Bad config with min config boots fine\n";
3074b0918612SSteven Rostedt	    return -1;
3075b0918612SSteven Rostedt	}
3076b0918612SSteven Rostedt	doprint " Bad config with min config fails as expected\n";
3077b0918612SSteven Rostedt    }
3078b0918612SSteven Rostedt
30790a05c769SSteven Rostedt    do {
30800a05c769SSteven Rostedt	$ret = run_config_bisect;
30810a05c769SSteven Rostedt    } while (!$ret);
30820a05c769SSteven Rostedt
30830a05c769SSteven Rostedt    return $ret if ($ret < 0);
30845f9b6cedSSteven Rostedt
30855f9b6cedSSteven Rostedt    success $i;
30865f9b6cedSSteven Rostedt}
30875f9b6cedSSteven Rostedt
308827d934b2SSteven Rostedtsub patchcheck_reboot {
308927d934b2SSteven Rostedt    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
3090bc7c5803SSteven Rostedt    reboot_to_good $patchcheck_sleep_time;
309127d934b2SSteven Rostedt}
309227d934b2SSteven Rostedt
30936c5ee0beSSteven Rostedtsub patchcheck {
30946c5ee0beSSteven Rostedt    my ($i) = @_;
30956c5ee0beSSteven Rostedt
30966c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
3097b5f4aea6SSteven Rostedt	if (!defined($patchcheck_start));
30986c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
3099b5f4aea6SSteven Rostedt	if (!defined($patchcheck_type));
31006c5ee0beSSteven Rostedt
3101b5f4aea6SSteven Rostedt    my $start = $patchcheck_start;
31026c5ee0beSSteven Rostedt
31036c5ee0beSSteven Rostedt    my $end = "HEAD";
3104b5f4aea6SSteven Rostedt    if (defined($patchcheck_end)) {
3105b5f4aea6SSteven Rostedt	$end = $patchcheck_end;
31066c5ee0beSSteven Rostedt    }
31076c5ee0beSSteven Rostedt
3108a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
3109a57419b3SSteven Rostedt    $start = get_sha1($start);
3110a57419b3SSteven Rostedt    $end = get_sha1($end);
3111a57419b3SSteven Rostedt
3112b5f4aea6SSteven Rostedt    my $type = $patchcheck_type;
31136c5ee0beSSteven Rostedt
31146c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
31156c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
31166c5ee0beSSteven Rostedt	$type = "boot";
31176c5ee0beSSteven Rostedt    }
31186c5ee0beSSteven Rostedt
31196c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
31206c5ee0beSSteven Rostedt	dodie "could not get git list";
31216c5ee0beSSteven Rostedt
31226c5ee0beSSteven Rostedt    my @list;
31236c5ee0beSSteven Rostedt
31246c5ee0beSSteven Rostedt    while (<IN>) {
31256c5ee0beSSteven Rostedt	chomp;
31266c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
31276c5ee0beSSteven Rostedt	last if (/^$start/);
31286c5ee0beSSteven Rostedt    }
31296c5ee0beSSteven Rostedt    close(IN);
31306c5ee0beSSteven Rostedt
31316c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
31322b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
31336c5ee0beSSteven Rostedt    }
31346c5ee0beSSteven Rostedt
31356c5ee0beSSteven Rostedt    # go backwards in the list
31366c5ee0beSSteven Rostedt    @list = reverse @list;
31376c5ee0beSSteven Rostedt
31386c5ee0beSSteven Rostedt    my $save_clean = $noclean;
31391990207dSSteven Rostedt    my %ignored_warnings;
31401990207dSSteven Rostedt
31411990207dSSteven Rostedt    if (defined($ignore_warnings)) {
31421990207dSSteven Rostedt	foreach my $sha1 (split /\s+/, $ignore_warnings) {
31431990207dSSteven Rostedt	    $ignored_warnings{$sha1} = 1;
31441990207dSSteven Rostedt	}
31451990207dSSteven Rostedt    }
31466c5ee0beSSteven Rostedt
31476c5ee0beSSteven Rostedt    $in_patchcheck = 1;
31486c5ee0beSSteven Rostedt    foreach my $item (@list) {
31496c5ee0beSSteven Rostedt	my $sha1 = $item;
31506c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
31516c5ee0beSSteven Rostedt
31526c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
31536c5ee0beSSteven Rostedt
31546c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
31556c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
31566c5ee0beSSteven Rostedt
31576c5ee0beSSteven Rostedt	# only clean on the first and last patch
31586c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
31596c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
31606c5ee0beSSteven Rostedt	    $noclean = $save_clean;
31616c5ee0beSSteven Rostedt	} else {
31626c5ee0beSSteven Rostedt	    $noclean = 1;
31636c5ee0beSSteven Rostedt	}
31646c5ee0beSSteven Rostedt
31656c5ee0beSSteven Rostedt	if (defined($minconfig)) {
31662b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
31676c5ee0beSSteven Rostedt	} else {
31686c5ee0beSSteven Rostedt	    # ?? no config to use?
31692b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
31706c5ee0beSSteven Rostedt	}
31716c5ee0beSSteven Rostedt
31724283b169SSteven Rostedt (Red Hat)	# No need to do per patch checking if warnings file exists
31734283b169SSteven Rostedt (Red Hat)	if (!defined($warnings_file) && !defined($ignored_warnings{$sha1})) {
31744283b169SSteven Rostedt (Red Hat)	    check_patch_buildlog $sha1 or return 0;
31751990207dSSteven Rostedt	}
31766c5ee0beSSteven Rostedt
31774283b169SSteven Rostedt (Red Hat)	check_buildlog or return 0;
31784283b169SSteven Rostedt (Red Hat)
31796c5ee0beSSteven Rostedt	next if ($type eq "build");
31806c5ee0beSSteven Rostedt
31817faafbd6SSteven Rostedt	my $failed = 0;
31827faafbd6SSteven Rostedt
3183ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
31847faafbd6SSteven Rostedt
31857faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
31867faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
31877faafbd6SSteven Rostedt	}
31887faafbd6SSteven Rostedt	end_monitor;
31897faafbd6SSteven Rostedt	return 0 if ($failed);
31907faafbd6SSteven Rostedt
319127d934b2SSteven Rostedt	patchcheck_reboot;
319227d934b2SSteven Rostedt
31936c5ee0beSSteven Rostedt    }
31946c5ee0beSSteven Rostedt    $in_patchcheck = 0;
31956c5ee0beSSteven Rostedt    success $i;
31962b7d9b21SSteven Rostedt
31972b7d9b21SSteven Rostedt    return 1;
31986c5ee0beSSteven Rostedt}
31996c5ee0beSSteven Rostedt
3200b9066f6cSSteven Rostedtmy %depends;
3201ac6974c7SSteven Rostedtmy %depcount;
3202b9066f6cSSteven Rostedtmy $iflevel = 0;
3203b9066f6cSSteven Rostedtmy @ifdeps;
3204b9066f6cSSteven Rostedt
3205b9066f6cSSteven Rostedt# prevent recursion
3206b9066f6cSSteven Rostedtmy %read_kconfigs;
3207b9066f6cSSteven Rostedt
3208ac6974c7SSteven Rostedtsub add_dep {
3209ac6974c7SSteven Rostedt    # $config depends on $dep
3210ac6974c7SSteven Rostedt    my ($config, $dep) = @_;
3211ac6974c7SSteven Rostedt
3212ac6974c7SSteven Rostedt    if (defined($depends{$config})) {
3213ac6974c7SSteven Rostedt	$depends{$config} .= " " . $dep;
3214ac6974c7SSteven Rostedt    } else {
3215ac6974c7SSteven Rostedt	$depends{$config} = $dep;
3216ac6974c7SSteven Rostedt    }
3217ac6974c7SSteven Rostedt
3218ac6974c7SSteven Rostedt    # record the number of configs depending on $dep
3219ac6974c7SSteven Rostedt    if (defined $depcount{$dep}) {
3220ac6974c7SSteven Rostedt	$depcount{$dep}++;
3221ac6974c7SSteven Rostedt    } else {
3222ac6974c7SSteven Rostedt	$depcount{$dep} = 1;
3223ac6974c7SSteven Rostedt    }
3224ac6974c7SSteven Rostedt}
3225ac6974c7SSteven Rostedt
3226b9066f6cSSteven Rostedt# taken from streamline_config.pl
3227b9066f6cSSteven Rostedtsub read_kconfig {
3228b9066f6cSSteven Rostedt    my ($kconfig) = @_;
3229b9066f6cSSteven Rostedt
3230b9066f6cSSteven Rostedt    my $state = "NONE";
3231b9066f6cSSteven Rostedt    my $config;
3232b9066f6cSSteven Rostedt    my @kconfigs;
3233b9066f6cSSteven Rostedt
3234b9066f6cSSteven Rostedt    my $cont = 0;
3235b9066f6cSSteven Rostedt    my $line;
3236b9066f6cSSteven Rostedt
3237b9066f6cSSteven Rostedt
3238b9066f6cSSteven Rostedt    if (! -f $kconfig) {
3239b9066f6cSSteven Rostedt	doprint "file $kconfig does not exist, skipping\n";
3240b9066f6cSSteven Rostedt	return;
3241b9066f6cSSteven Rostedt    }
3242b9066f6cSSteven Rostedt
3243b9066f6cSSteven Rostedt    open(KIN, "$kconfig")
3244b9066f6cSSteven Rostedt	or die "Can't open $kconfig";
3245b9066f6cSSteven Rostedt    while (<KIN>) {
3246b9066f6cSSteven Rostedt	chomp;
3247b9066f6cSSteven Rostedt
3248b9066f6cSSteven Rostedt	# Make sure that lines ending with \ continue
3249b9066f6cSSteven Rostedt	if ($cont) {
3250b9066f6cSSteven Rostedt	    $_ = $line . " " . $_;
3251b9066f6cSSteven Rostedt	}
3252b9066f6cSSteven Rostedt
3253b9066f6cSSteven Rostedt	if (s/\\$//) {
3254b9066f6cSSteven Rostedt	    $cont = 1;
3255b9066f6cSSteven Rostedt	    $line = $_;
3256b9066f6cSSteven Rostedt	    next;
3257b9066f6cSSteven Rostedt	}
3258b9066f6cSSteven Rostedt
3259b9066f6cSSteven Rostedt	$cont = 0;
3260b9066f6cSSteven Rostedt
3261b9066f6cSSteven Rostedt	# collect any Kconfig sources
3262b9066f6cSSteven Rostedt	if (/^source\s*"(.*)"/) {
3263b9066f6cSSteven Rostedt	    $kconfigs[$#kconfigs+1] = $1;
3264b9066f6cSSteven Rostedt	}
3265b9066f6cSSteven Rostedt
3266b9066f6cSSteven Rostedt	# configs found
3267b9066f6cSSteven Rostedt	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
3268b9066f6cSSteven Rostedt	    $state = "NEW";
3269b9066f6cSSteven Rostedt	    $config = $2;
3270b9066f6cSSteven Rostedt
3271b9066f6cSSteven Rostedt	    for (my $i = 0; $i < $iflevel; $i++) {
3272ac6974c7SSteven Rostedt		add_dep $config, $ifdeps[$i];
3273b9066f6cSSteven Rostedt	    }
3274b9066f6cSSteven Rostedt
3275b9066f6cSSteven Rostedt	# collect the depends for the config
3276b9066f6cSSteven Rostedt	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
3277b9066f6cSSteven Rostedt
3278ac6974c7SSteven Rostedt	    add_dep $config, $1;
3279b9066f6cSSteven Rostedt
3280b9066f6cSSteven Rostedt	# Get the configs that select this config
3281ac6974c7SSteven Rostedt	} elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
3282ac6974c7SSteven Rostedt
3283ac6974c7SSteven Rostedt	    # selected by depends on config
3284ac6974c7SSteven Rostedt	    add_dep $1, $config;
3285b9066f6cSSteven Rostedt
3286b9066f6cSSteven Rostedt	# Check for if statements
3287b9066f6cSSteven Rostedt	} elsif (/^if\s+(.*\S)\s*$/) {
3288b9066f6cSSteven Rostedt	    my $deps = $1;
3289b9066f6cSSteven Rostedt	    # remove beginning and ending non text
3290b9066f6cSSteven Rostedt	    $deps =~ s/^[^a-zA-Z0-9_]*//;
3291b9066f6cSSteven Rostedt	    $deps =~ s/[^a-zA-Z0-9_]*$//;
3292b9066f6cSSteven Rostedt
3293b9066f6cSSteven Rostedt	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
3294b9066f6cSSteven Rostedt
3295b9066f6cSSteven Rostedt	    $ifdeps[$iflevel++] = join ':', @deps;
3296b9066f6cSSteven Rostedt
3297b9066f6cSSteven Rostedt	} elsif (/^endif/) {
3298b9066f6cSSteven Rostedt
3299b9066f6cSSteven Rostedt	    $iflevel-- if ($iflevel);
3300b9066f6cSSteven Rostedt
3301b9066f6cSSteven Rostedt	# stop on "help"
3302b9066f6cSSteven Rostedt	} elsif (/^\s*help\s*$/) {
3303b9066f6cSSteven Rostedt	    $state = "NONE";
3304b9066f6cSSteven Rostedt	}
3305b9066f6cSSteven Rostedt    }
3306b9066f6cSSteven Rostedt    close(KIN);
3307b9066f6cSSteven Rostedt
3308b9066f6cSSteven Rostedt    # read in any configs that were found.
3309b9066f6cSSteven Rostedt    foreach $kconfig (@kconfigs) {
3310b9066f6cSSteven Rostedt	if (!defined($read_kconfigs{$kconfig})) {
3311b9066f6cSSteven Rostedt	    $read_kconfigs{$kconfig} = 1;
3312b9066f6cSSteven Rostedt	    read_kconfig("$builddir/$kconfig");
3313b9066f6cSSteven Rostedt	}
3314b9066f6cSSteven Rostedt    }
3315b9066f6cSSteven Rostedt}
3316b9066f6cSSteven Rostedt
3317b9066f6cSSteven Rostedtsub read_depends {
3318b9066f6cSSteven Rostedt    # find out which arch this is by the kconfig file
3319b9066f6cSSteven Rostedt    open (IN, $output_config)
3320b9066f6cSSteven Rostedt	or dodie "Failed to read $output_config";
3321b9066f6cSSteven Rostedt    my $arch;
3322b9066f6cSSteven Rostedt    while (<IN>) {
3323b9066f6cSSteven Rostedt	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
3324b9066f6cSSteven Rostedt	    $arch = $1;
3325b9066f6cSSteven Rostedt	    last;
3326b9066f6cSSteven Rostedt	}
3327b9066f6cSSteven Rostedt    }
3328b9066f6cSSteven Rostedt    close IN;
3329b9066f6cSSteven Rostedt
3330b9066f6cSSteven Rostedt    if (!defined($arch)) {
3331b9066f6cSSteven Rostedt	doprint "Could not find arch from config file\n";
3332b9066f6cSSteven Rostedt	doprint "no dependencies used\n";
3333b9066f6cSSteven Rostedt	return;
3334b9066f6cSSteven Rostedt    }
3335b9066f6cSSteven Rostedt
3336b9066f6cSSteven Rostedt    # arch is really the subarch, we need to know
3337b9066f6cSSteven Rostedt    # what directory to look at.
3338b9066f6cSSteven Rostedt    if ($arch eq "i386" || $arch eq "x86_64") {
3339b9066f6cSSteven Rostedt	$arch = "x86";
3340b9066f6cSSteven Rostedt    } elsif ($arch =~ /^tile/) {
3341b9066f6cSSteven Rostedt	$arch = "tile";
3342b9066f6cSSteven Rostedt    }
3343b9066f6cSSteven Rostedt
3344b9066f6cSSteven Rostedt    my $kconfig = "$builddir/arch/$arch/Kconfig";
3345b9066f6cSSteven Rostedt
3346b9066f6cSSteven Rostedt    if (! -f $kconfig && $arch =~ /\d$/) {
3347b9066f6cSSteven Rostedt	my $orig = $arch;
3348b9066f6cSSteven Rostedt 	# some subarchs have numbers, truncate them
3349b9066f6cSSteven Rostedt	$arch =~ s/\d*$//;
3350b9066f6cSSteven Rostedt	$kconfig = "$builddir/arch/$arch/Kconfig";
3351b9066f6cSSteven Rostedt	if (! -f $kconfig) {
3352b9066f6cSSteven Rostedt	    doprint "No idea what arch dir $orig is for\n";
3353b9066f6cSSteven Rostedt	    doprint "no dependencies used\n";
3354b9066f6cSSteven Rostedt	    return;
3355b9066f6cSSteven Rostedt	}
3356b9066f6cSSteven Rostedt    }
3357b9066f6cSSteven Rostedt
3358b9066f6cSSteven Rostedt    read_kconfig($kconfig);
3359b9066f6cSSteven Rostedt}
3360b9066f6cSSteven Rostedt
33614c4ab120SSteven Rostedtsub read_config_list {
33624c4ab120SSteven Rostedt    my ($config) = @_;
33634c4ab120SSteven Rostedt
33644c4ab120SSteven Rostedt    open (IN, $config)
33654c4ab120SSteven Rostedt	or dodie "Failed to read $config";
33664c4ab120SSteven Rostedt
33674c4ab120SSteven Rostedt    while (<IN>) {
33684c4ab120SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
33694c4ab120SSteven Rostedt	    if (!defined($config_ignore{$2})) {
33704c4ab120SSteven Rostedt		$config_list{$2} = $1;
33714c4ab120SSteven Rostedt	    }
33724c4ab120SSteven Rostedt	}
33734c4ab120SSteven Rostedt    }
33744c4ab120SSteven Rostedt
33754c4ab120SSteven Rostedt    close(IN);
33764c4ab120SSteven Rostedt}
33774c4ab120SSteven Rostedt
33784c4ab120SSteven Rostedtsub read_output_config {
33794c4ab120SSteven Rostedt    my ($config) = @_;
33804c4ab120SSteven Rostedt
33814c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
33824c4ab120SSteven Rostedt}
33834c4ab120SSteven Rostedt
33844c4ab120SSteven Rostedtsub make_new_config {
33854c4ab120SSteven Rostedt    my @configs = @_;
33864c4ab120SSteven Rostedt
33874c4ab120SSteven Rostedt    open (OUT, ">$output_config")
33884c4ab120SSteven Rostedt	or dodie "Failed to write $output_config";
33894c4ab120SSteven Rostedt
33904c4ab120SSteven Rostedt    foreach my $config (@configs) {
33914c4ab120SSteven Rostedt	print OUT "$config\n";
33924c4ab120SSteven Rostedt    }
33934c4ab120SSteven Rostedt    close OUT;
33944c4ab120SSteven Rostedt}
33954c4ab120SSteven Rostedt
3396ac6974c7SSteven Rostedtsub chomp_config {
3397ac6974c7SSteven Rostedt    my ($config) = @_;
3398ac6974c7SSteven Rostedt
3399ac6974c7SSteven Rostedt    $config =~ s/CONFIG_//;
3400ac6974c7SSteven Rostedt
3401ac6974c7SSteven Rostedt    return $config;
3402ac6974c7SSteven Rostedt}
3403ac6974c7SSteven Rostedt
3404b9066f6cSSteven Rostedtsub get_depends {
3405b9066f6cSSteven Rostedt    my ($dep) = @_;
3406b9066f6cSSteven Rostedt
3407ac6974c7SSteven Rostedt    my $kconfig = chomp_config $dep;
3408b9066f6cSSteven Rostedt
3409b9066f6cSSteven Rostedt    $dep = $depends{"$kconfig"};
3410b9066f6cSSteven Rostedt
3411b9066f6cSSteven Rostedt    # the dep string we have saves the dependencies as they
3412b9066f6cSSteven Rostedt    # were found, including expressions like ! && ||. We
3413b9066f6cSSteven Rostedt    # want to split this out into just an array of configs.
3414b9066f6cSSteven Rostedt
3415b9066f6cSSteven Rostedt    my $valid = "A-Za-z_0-9";
3416b9066f6cSSteven Rostedt
3417b9066f6cSSteven Rostedt    my @configs;
3418b9066f6cSSteven Rostedt
3419b9066f6cSSteven Rostedt    while ($dep =~ /[$valid]/) {
3420b9066f6cSSteven Rostedt
3421b9066f6cSSteven Rostedt	if ($dep =~ /^[^$valid]*([$valid]+)/) {
3422b9066f6cSSteven Rostedt	    my $conf = "CONFIG_" . $1;
3423b9066f6cSSteven Rostedt
3424b9066f6cSSteven Rostedt	    $configs[$#configs + 1] = $conf;
3425b9066f6cSSteven Rostedt
3426b9066f6cSSteven Rostedt	    $dep =~ s/^[^$valid]*[$valid]+//;
3427b9066f6cSSteven Rostedt	} else {
3428b9066f6cSSteven Rostedt	    die "this should never happen";
3429b9066f6cSSteven Rostedt	}
3430b9066f6cSSteven Rostedt    }
3431b9066f6cSSteven Rostedt
3432b9066f6cSSteven Rostedt    return @configs;
3433b9066f6cSSteven Rostedt}
3434b9066f6cSSteven Rostedt
3435b9066f6cSSteven Rostedtmy %min_configs;
3436b9066f6cSSteven Rostedtmy %keep_configs;
343743d1b651SSteven Rostedtmy %save_configs;
3438b9066f6cSSteven Rostedtmy %processed_configs;
3439b9066f6cSSteven Rostedtmy %nochange_config;
3440b9066f6cSSteven Rostedt
3441b9066f6cSSteven Rostedtsub test_this_config {
3442b9066f6cSSteven Rostedt    my ($config) = @_;
3443b9066f6cSSteven Rostedt
3444b9066f6cSSteven Rostedt    my $found;
3445b9066f6cSSteven Rostedt
3446b9066f6cSSteven Rostedt    # if we already processed this config, skip it
3447b9066f6cSSteven Rostedt    if (defined($processed_configs{$config})) {
3448b9066f6cSSteven Rostedt	return undef;
3449b9066f6cSSteven Rostedt    }
3450b9066f6cSSteven Rostedt    $processed_configs{$config} = 1;
3451b9066f6cSSteven Rostedt
3452b9066f6cSSteven Rostedt    # if this config failed during this round, skip it
3453b9066f6cSSteven Rostedt    if (defined($nochange_config{$config})) {
3454b9066f6cSSteven Rostedt	return undef;
3455b9066f6cSSteven Rostedt    }
3456b9066f6cSSteven Rostedt
3457ac6974c7SSteven Rostedt    my $kconfig = chomp_config $config;
3458b9066f6cSSteven Rostedt
3459b9066f6cSSteven Rostedt    # Test dependencies first
3460b9066f6cSSteven Rostedt    if (defined($depends{"$kconfig"})) {
3461b9066f6cSSteven Rostedt	my @parents = get_depends $config;
3462b9066f6cSSteven Rostedt	foreach my $parent (@parents) {
3463b9066f6cSSteven Rostedt	    # if the parent is in the min config, check it first
3464b9066f6cSSteven Rostedt	    next if (!defined($min_configs{$parent}));
3465b9066f6cSSteven Rostedt	    $found = test_this_config($parent);
3466b9066f6cSSteven Rostedt	    if (defined($found)) {
3467b9066f6cSSteven Rostedt		return $found;
3468b9066f6cSSteven Rostedt	    }
3469b9066f6cSSteven Rostedt	}
3470b9066f6cSSteven Rostedt    }
3471b9066f6cSSteven Rostedt
3472b9066f6cSSteven Rostedt    # Remove this config from the list of configs
3473fb16d891SAdam Lee    # do a make olddefconfig and then read the resulting
3474b9066f6cSSteven Rostedt    # .config to make sure it is missing the config that
3475b9066f6cSSteven Rostedt    # we had before
3476b9066f6cSSteven Rostedt    my %configs = %min_configs;
3477b9066f6cSSteven Rostedt    delete $configs{$config};
3478b9066f6cSSteven Rostedt    make_new_config ((values %configs), (values %keep_configs));
3479b9066f6cSSteven Rostedt    make_oldconfig;
3480b9066f6cSSteven Rostedt    undef %configs;
3481b9066f6cSSteven Rostedt    assign_configs \%configs, $output_config;
3482b9066f6cSSteven Rostedt
3483b9066f6cSSteven Rostedt    return $config if (!defined($configs{$config}));
3484b9066f6cSSteven Rostedt
3485b9066f6cSSteven Rostedt    doprint "disabling config $config did not change .config\n";
3486b9066f6cSSteven Rostedt
3487b9066f6cSSteven Rostedt    $nochange_config{$config} = 1;
3488b9066f6cSSteven Rostedt
3489b9066f6cSSteven Rostedt    return undef;
3490b9066f6cSSteven Rostedt}
3491b9066f6cSSteven Rostedt
34924c4ab120SSteven Rostedtsub make_min_config {
34934c4ab120SSteven Rostedt    my ($i) = @_;
34944c4ab120SSteven Rostedt
3495ccc513b6SSteven Rostedt    my $type = $minconfig_type;
3496ccc513b6SSteven Rostedt    if ($type ne "boot" && $type ne "test") {
3497ccc513b6SSteven Rostedt	fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" .
3498ccc513b6SSteven Rostedt	    " make_min_config works only with 'boot' and 'test'\n" and return;
3499ccc513b6SSteven Rostedt    }
3500ccc513b6SSteven Rostedt
35014c4ab120SSteven Rostedt    if (!defined($output_minconfig)) {
35024c4ab120SSteven Rostedt	fail "OUTPUT_MIN_CONFIG not defined" and return;
35034c4ab120SSteven Rostedt    }
350435ce5952SSteven Rostedt
350535ce5952SSteven Rostedt    # If output_minconfig exists, and the start_minconfig
350635ce5952SSteven Rostedt    # came from min_config, than ask if we should use
350735ce5952SSteven Rostedt    # that instead.
350835ce5952SSteven Rostedt    if (-f $output_minconfig && !$start_minconfig_defined) {
350935ce5952SSteven Rostedt	print "$output_minconfig exists\n";
351043de3316SSteven Rostedt	if (!defined($use_output_minconfig)) {
351135ce5952SSteven Rostedt	    if (read_yn " Use it as minconfig?") {
351235ce5952SSteven Rostedt		$start_minconfig = $output_minconfig;
351335ce5952SSteven Rostedt	    }
351443de3316SSteven Rostedt	} elsif ($use_output_minconfig > 0) {
351543de3316SSteven Rostedt	    doprint "Using $output_minconfig as MIN_CONFIG\n";
351643de3316SSteven Rostedt	    $start_minconfig = $output_minconfig;
351743de3316SSteven Rostedt	} else {
351843de3316SSteven Rostedt	    doprint "Set to still use MIN_CONFIG as starting point\n";
351943de3316SSteven Rostedt	}
352035ce5952SSteven Rostedt    }
352135ce5952SSteven Rostedt
35224c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
35234c4ab120SSteven Rostedt	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
35244c4ab120SSteven Rostedt    }
35254c4ab120SSteven Rostedt
352635ce5952SSteven Rostedt    my $temp_config = "$tmpdir/temp_config";
352735ce5952SSteven Rostedt
35284c4ab120SSteven Rostedt    # First things first. We build an allnoconfig to find
35294c4ab120SSteven Rostedt    # out what the defaults are that we can't touch.
35304c4ab120SSteven Rostedt    # Some are selections, but we really can't handle selections.
35314c4ab120SSteven Rostedt
35324c4ab120SSteven Rostedt    my $save_minconfig = $minconfig;
35334c4ab120SSteven Rostedt    undef $minconfig;
35344c4ab120SSteven Rostedt
35354c4ab120SSteven Rostedt    run_command "$make allnoconfig" or return 0;
35364c4ab120SSteven Rostedt
3537b9066f6cSSteven Rostedt    read_depends;
3538b9066f6cSSteven Rostedt
35394c4ab120SSteven Rostedt    process_config_ignore $output_config;
3540b9066f6cSSteven Rostedt
354143d1b651SSteven Rostedt    undef %save_configs;
3542b9066f6cSSteven Rostedt    undef %min_configs;
35434c4ab120SSteven Rostedt
35444c4ab120SSteven Rostedt    if (defined($ignore_config)) {
35454c4ab120SSteven Rostedt	# make sure the file exists
35464c4ab120SSteven Rostedt	`touch $ignore_config`;
354743d1b651SSteven Rostedt	assign_configs \%save_configs, $ignore_config;
35484c4ab120SSteven Rostedt    }
35494c4ab120SSteven Rostedt
355043d1b651SSteven Rostedt    %keep_configs = %save_configs;
355143d1b651SSteven Rostedt
35524c4ab120SSteven Rostedt    doprint "Load initial configs from $start_minconfig\n";
35534c4ab120SSteven Rostedt
35544c4ab120SSteven Rostedt    # Look at the current min configs, and save off all the
35554c4ab120SSteven Rostedt    # ones that were set via the allnoconfig
35564c4ab120SSteven Rostedt    assign_configs \%min_configs, $start_minconfig;
35574c4ab120SSteven Rostedt
35584c4ab120SSteven Rostedt    my @config_keys = keys %min_configs;
35594c4ab120SSteven Rostedt
3560ac6974c7SSteven Rostedt    # All configs need a depcount
3561ac6974c7SSteven Rostedt    foreach my $config (@config_keys) {
3562ac6974c7SSteven Rostedt	my $kconfig = chomp_config $config;
3563ac6974c7SSteven Rostedt	if (!defined $depcount{$kconfig}) {
3564ac6974c7SSteven Rostedt		$depcount{$kconfig} = 0;
3565ac6974c7SSteven Rostedt	}
3566ac6974c7SSteven Rostedt    }
3567ac6974c7SSteven Rostedt
35684c4ab120SSteven Rostedt    # Remove anything that was set by the make allnoconfig
35694c4ab120SSteven Rostedt    # we shouldn't need them as they get set for us anyway.
35704c4ab120SSteven Rostedt    foreach my $config (@config_keys) {
35714c4ab120SSteven Rostedt	# Remove anything in the ignore_config
35724c4ab120SSteven Rostedt	if (defined($keep_configs{$config})) {
35734c4ab120SSteven Rostedt	    my $file = $ignore_config;
35744c4ab120SSteven Rostedt	    $file =~ s,.*/(.*?)$,$1,;
35754c4ab120SSteven Rostedt	    doprint "$config set by $file ... ignored\n";
35764c4ab120SSteven Rostedt	    delete $min_configs{$config};
35774c4ab120SSteven Rostedt	    next;
35784c4ab120SSteven Rostedt	}
35794c4ab120SSteven Rostedt	# But make sure the settings are the same. If a min config
35804c4ab120SSteven Rostedt	# sets a selection, we do not want to get rid of it if
35814c4ab120SSteven Rostedt	# it is not the same as what we have. Just move it into
35824c4ab120SSteven Rostedt	# the keep configs.
35834c4ab120SSteven Rostedt	if (defined($config_ignore{$config})) {
35844c4ab120SSteven Rostedt	    if ($config_ignore{$config} ne $min_configs{$config}) {
35854c4ab120SSteven Rostedt		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
35864c4ab120SSteven Rostedt		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
35874c4ab120SSteven Rostedt		$keep_configs{$config} = $min_configs{$config};
35884c4ab120SSteven Rostedt	    } else {
35894c4ab120SSteven Rostedt		doprint "$config set by allnoconfig ... ignored\n";
35904c4ab120SSteven Rostedt	    }
35914c4ab120SSteven Rostedt	    delete $min_configs{$config};
35924c4ab120SSteven Rostedt	}
35934c4ab120SSteven Rostedt    }
35944c4ab120SSteven Rostedt
35954c4ab120SSteven Rostedt    my $done = 0;
3596b9066f6cSSteven Rostedt    my $take_two = 0;
35974c4ab120SSteven Rostedt
35984c4ab120SSteven Rostedt    while (!$done) {
35994c4ab120SSteven Rostedt
36004c4ab120SSteven Rostedt	my $config;
36014c4ab120SSteven Rostedt	my $found;
36024c4ab120SSteven Rostedt
36034c4ab120SSteven Rostedt	# Now disable each config one by one and do a make oldconfig
36044c4ab120SSteven Rostedt	# till we find a config that changes our list.
36054c4ab120SSteven Rostedt
36064c4ab120SSteven Rostedt	my @test_configs = keys %min_configs;
3607ac6974c7SSteven Rostedt
3608ac6974c7SSteven Rostedt	# Sort keys by who is most dependent on
3609ac6974c7SSteven Rostedt	@test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
3610ac6974c7SSteven Rostedt			  @test_configs ;
3611ac6974c7SSteven Rostedt
3612ac6974c7SSteven Rostedt	# Put configs that did not modify the config at the end.
36134c4ab120SSteven Rostedt	my $reset = 1;
36144c4ab120SSteven Rostedt	for (my $i = 0; $i < $#test_configs; $i++) {
36154c4ab120SSteven Rostedt	    if (!defined($nochange_config{$test_configs[0]})) {
36164c4ab120SSteven Rostedt		$reset = 0;
36174c4ab120SSteven Rostedt		last;
36184c4ab120SSteven Rostedt	    }
36194c4ab120SSteven Rostedt	    # This config didn't change the .config last time.
36204c4ab120SSteven Rostedt	    # Place it at the end
36214c4ab120SSteven Rostedt	    my $config = shift @test_configs;
36224c4ab120SSteven Rostedt	    push @test_configs, $config;
36234c4ab120SSteven Rostedt	}
36244c4ab120SSteven Rostedt
36254c4ab120SSteven Rostedt	# if every test config has failed to modify the .config file
36264c4ab120SSteven Rostedt	# in the past, then reset and start over.
36274c4ab120SSteven Rostedt	if ($reset) {
36284c4ab120SSteven Rostedt	    undef %nochange_config;
36294c4ab120SSteven Rostedt	}
36304c4ab120SSteven Rostedt
3631b9066f6cSSteven Rostedt	undef %processed_configs;
3632b9066f6cSSteven Rostedt
36334c4ab120SSteven Rostedt	foreach my $config (@test_configs) {
36344c4ab120SSteven Rostedt
3635b9066f6cSSteven Rostedt	    $found = test_this_config $config;
36364c4ab120SSteven Rostedt
3637b9066f6cSSteven Rostedt	    last if (defined($found));
36384c4ab120SSteven Rostedt
36394c4ab120SSteven Rostedt	    # oh well, try another config
36404c4ab120SSteven Rostedt	}
36414c4ab120SSteven Rostedt
36424c4ab120SSteven Rostedt	if (!defined($found)) {
3643b9066f6cSSteven Rostedt	    # we could have failed due to the nochange_config hash
3644b9066f6cSSteven Rostedt	    # reset and try again
3645b9066f6cSSteven Rostedt	    if (!$take_two) {
3646b9066f6cSSteven Rostedt		undef %nochange_config;
3647b9066f6cSSteven Rostedt		$take_two = 1;
3648b9066f6cSSteven Rostedt		next;
3649b9066f6cSSteven Rostedt	    }
36504c4ab120SSteven Rostedt	    doprint "No more configs found that we can disable\n";
36514c4ab120SSteven Rostedt	    $done = 1;
36524c4ab120SSteven Rostedt	    last;
36534c4ab120SSteven Rostedt	}
3654b9066f6cSSteven Rostedt	$take_two = 0;
36554c4ab120SSteven Rostedt
36564c4ab120SSteven Rostedt	$config = $found;
36574c4ab120SSteven Rostedt
36584c4ab120SSteven Rostedt	doprint "Test with $config disabled\n";
36594c4ab120SSteven Rostedt
36604c4ab120SSteven Rostedt	# set in_bisect to keep build and monitor from dieing
36614c4ab120SSteven Rostedt	$in_bisect = 1;
36624c4ab120SSteven Rostedt
36634c4ab120SSteven Rostedt	my $failed = 0;
3664bf1c95abSSteven Rostedt	build "oldconfig" or $failed = 1;
3665bf1c95abSSteven Rostedt	if (!$failed) {
36664c4ab120SSteven Rostedt		start_monitor_and_boot or $failed = 1;
3667ccc513b6SSteven Rostedt
3668ccc513b6SSteven Rostedt		if ($type eq "test" && !$failed) {
3669ccc513b6SSteven Rostedt		    do_run_test or $failed = 1;
3670ccc513b6SSteven Rostedt		}
3671ccc513b6SSteven Rostedt
36724c4ab120SSteven Rostedt		end_monitor;
3673bf1c95abSSteven Rostedt	}
36744c4ab120SSteven Rostedt
36754c4ab120SSteven Rostedt	$in_bisect = 0;
36764c4ab120SSteven Rostedt
36774c4ab120SSteven Rostedt	if ($failed) {
3678b9066f6cSSteven Rostedt	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
36794c4ab120SSteven Rostedt	    # this config is needed, add it to the ignore list.
36804c4ab120SSteven Rostedt	    $keep_configs{$config} = $min_configs{$config};
368143d1b651SSteven Rostedt	    $save_configs{$config} = $min_configs{$config};
36824c4ab120SSteven Rostedt	    delete $min_configs{$config};
368335ce5952SSteven Rostedt
368435ce5952SSteven Rostedt	    # update new ignore configs
368535ce5952SSteven Rostedt	    if (defined($ignore_config)) {
368635ce5952SSteven Rostedt		open (OUT, ">$temp_config")
368735ce5952SSteven Rostedt		    or die "Can't write to $temp_config";
368843d1b651SSteven Rostedt		foreach my $config (keys %save_configs) {
368943d1b651SSteven Rostedt		    print OUT "$save_configs{$config}\n";
369035ce5952SSteven Rostedt		}
369135ce5952SSteven Rostedt		close OUT;
369235ce5952SSteven Rostedt		run_command "mv $temp_config $ignore_config" or
369335ce5952SSteven Rostedt		    dodie "failed to copy update to $ignore_config";
369435ce5952SSteven Rostedt	    }
369535ce5952SSteven Rostedt
36964c4ab120SSteven Rostedt	} else {
36974c4ab120SSteven Rostedt	    # We booted without this config, remove it from the minconfigs.
36984c4ab120SSteven Rostedt	    doprint "$config is not needed, disabling\n";
36994c4ab120SSteven Rostedt
37004c4ab120SSteven Rostedt	    delete $min_configs{$config};
37014c4ab120SSteven Rostedt
37024c4ab120SSteven Rostedt	    # Also disable anything that is not enabled in this config
37034c4ab120SSteven Rostedt	    my %configs;
37044c4ab120SSteven Rostedt	    assign_configs \%configs, $output_config;
37054c4ab120SSteven Rostedt	    my @config_keys = keys %min_configs;
37064c4ab120SSteven Rostedt	    foreach my $config (@config_keys) {
37074c4ab120SSteven Rostedt		if (!defined($configs{$config})) {
37084c4ab120SSteven Rostedt		    doprint "$config is not set, disabling\n";
37094c4ab120SSteven Rostedt		    delete $min_configs{$config};
37104c4ab120SSteven Rostedt		}
37114c4ab120SSteven Rostedt	    }
37124c4ab120SSteven Rostedt
37134c4ab120SSteven Rostedt	    # Save off all the current mandidory configs
371435ce5952SSteven Rostedt	    open (OUT, ">$temp_config")
371535ce5952SSteven Rostedt		or die "Can't write to $temp_config";
37164c4ab120SSteven Rostedt	    foreach my $config (keys %keep_configs) {
37174c4ab120SSteven Rostedt		print OUT "$keep_configs{$config}\n";
37184c4ab120SSteven Rostedt	    }
37194c4ab120SSteven Rostedt	    foreach my $config (keys %min_configs) {
37204c4ab120SSteven Rostedt		print OUT "$min_configs{$config}\n";
37214c4ab120SSteven Rostedt	    }
37224c4ab120SSteven Rostedt	    close OUT;
372335ce5952SSteven Rostedt
372435ce5952SSteven Rostedt	    run_command "mv $temp_config $output_minconfig" or
372535ce5952SSteven Rostedt		dodie "failed to copy update to $output_minconfig";
37264c4ab120SSteven Rostedt	}
37274c4ab120SSteven Rostedt
37284c4ab120SSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
3729bc7c5803SSteven Rostedt	reboot_to_good $sleep_time;
37304c4ab120SSteven Rostedt    }
37314c4ab120SSteven Rostedt
37324c4ab120SSteven Rostedt    success $i;
37334c4ab120SSteven Rostedt    return 1;
37344c4ab120SSteven Rostedt}
37354c4ab120SSteven Rostedt
37364283b169SSteven Rostedt (Red Hat)sub make_warnings_file {
37374283b169SSteven Rostedt (Red Hat)    my ($i) = @_;
37384283b169SSteven Rostedt (Red Hat)
37394283b169SSteven Rostedt (Red Hat)    if (!defined($warnings_file)) {
37404283b169SSteven Rostedt (Red Hat)	dodie "Must define WARNINGS_FILE for make_warnings_file test";
37414283b169SSteven Rostedt (Red Hat)    }
37424283b169SSteven Rostedt (Red Hat)
37434283b169SSteven Rostedt (Red Hat)    if ($build_type eq "nobuild") {
37444283b169SSteven Rostedt (Red Hat)	dodie "BUILD_TYPE can not be 'nobuild' for make_warnings_file test";
37454283b169SSteven Rostedt (Red Hat)    }
37464283b169SSteven Rostedt (Red Hat)
37474283b169SSteven Rostedt (Red Hat)    build $build_type or dodie "Failed to build";
37484283b169SSteven Rostedt (Red Hat)
37494283b169SSteven Rostedt (Red Hat)    open(OUT, ">$warnings_file") or dodie "Can't create $warnings_file";
37504283b169SSteven Rostedt (Red Hat)
37514283b169SSteven Rostedt (Red Hat)    open(IN, $buildlog) or dodie "Can't open $buildlog";
37524283b169SSteven Rostedt (Red Hat)    while (<IN>) {
37534283b169SSteven Rostedt (Red Hat)
37544283b169SSteven Rostedt (Red Hat)	# Some compilers use UTF-8 extended for quotes
37554283b169SSteven Rostedt (Red Hat)	# for distcc heterogeneous systems, this causes issues
37564283b169SSteven Rostedt (Red Hat)	s/$utf8_quote/'/g;
37574283b169SSteven Rostedt (Red Hat)
37584283b169SSteven Rostedt (Red Hat)	if (/$check_build_re/) {
37594283b169SSteven Rostedt (Red Hat)	    print OUT;
37604283b169SSteven Rostedt (Red Hat)	}
37614283b169SSteven Rostedt (Red Hat)    }
37624283b169SSteven Rostedt (Red Hat)    close(IN);
37634283b169SSteven Rostedt (Red Hat)
37644283b169SSteven Rostedt (Red Hat)    close(OUT);
37654283b169SSteven Rostedt (Red Hat)
37664283b169SSteven Rostedt (Red Hat)    success $i;
37674283b169SSteven Rostedt (Red Hat)}
37684283b169SSteven Rostedt (Red Hat)
37698d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
37702545eb61SSteven Rostedt
37718d1491baSSteven Rostedtif ($#ARGV == 0) {
37728d1491baSSteven Rostedt    $ktest_config = $ARGV[0];
37738d1491baSSteven Rostedt    if (! -f $ktest_config) {
37748d1491baSSteven Rostedt	print "$ktest_config does not exist.\n";
377535ce5952SSteven Rostedt	if (!read_yn "Create it?") {
37768d1491baSSteven Rostedt	    exit 0;
37778d1491baSSteven Rostedt	}
37788d1491baSSteven Rostedt    }
37798d1491baSSteven Rostedt} else {
37808d1491baSSteven Rostedt    $ktest_config = "ktest.conf";
37818d1491baSSteven Rostedt}
37828d1491baSSteven Rostedt
37838d1491baSSteven Rostedtif (! -f $ktest_config) {
3784dbd3783bSSteven Rostedt    $newconfig = 1;
3785c4261d0fSSteven Rostedt    get_test_case;
37868d1491baSSteven Rostedt    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
37878d1491baSSteven Rostedt    print OUT << "EOF"
37888d1491baSSteven Rostedt# Generated by ktest.pl
37898d1491baSSteven Rostedt#
37900e7a22deSSteven Rostedt
37910e7a22deSSteven Rostedt# PWD is a ktest.pl variable that will result in the process working
37920e7a22deSSteven Rostedt# directory that ktest.pl is executed in.
37930e7a22deSSteven Rostedt
37940e7a22deSSteven Rostedt# THIS_DIR is automatically assigned the PWD of the path that generated
37950e7a22deSSteven Rostedt# the config file. It is best to use this variable when assigning other
37960e7a22deSSteven Rostedt# directory paths within this directory. This allows you to easily
37970e7a22deSSteven Rostedt# move the test cases to other locations or to other machines.
37980e7a22deSSteven Rostedt#
37990e7a22deSSteven RostedtTHIS_DIR := $variable{"PWD"}
38000e7a22deSSteven Rostedt
38018d1491baSSteven Rostedt# Define each test with TEST_START
38028d1491baSSteven Rostedt# The config options below it will override the defaults
38038d1491baSSteven RostedtTEST_START
3804c4261d0fSSteven RostedtTEST_TYPE = $default{"TEST_TYPE"}
38058d1491baSSteven Rostedt
38068d1491baSSteven RostedtDEFAULTS
38078d1491baSSteven RostedtEOF
38088d1491baSSteven Rostedt;
38098d1491baSSteven Rostedt    close(OUT);
38108d1491baSSteven Rostedt}
38118d1491baSSteven Rostedtread_config $ktest_config;
38128d1491baSSteven Rostedt
381323715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) {
381404262be3SSteven Rostedt (Red Hat)    $opt{"LOG_FILE"} = eval_option("LOG_FILE", $opt{"LOG_FILE"}, -1);
381523715c3cSSteven Rostedt}
381623715c3cSSteven Rostedt
38178d1491baSSteven Rostedt# Append any configs entered in manually to the config file.
38188d1491baSSteven Rostedtmy @new_configs = keys %entered_configs;
38198d1491baSSteven Rostedtif ($#new_configs >= 0) {
38208d1491baSSteven Rostedt    print "\nAppending entered in configs to $ktest_config\n";
38218d1491baSSteven Rostedt    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
38228d1491baSSteven Rostedt    foreach my $config (@new_configs) {
38238d1491baSSteven Rostedt	print OUT "$config = $entered_configs{$config}\n";
38240e7a22deSSteven Rostedt	$opt{$config} = process_variables($entered_configs{$config});
38258d1491baSSteven Rostedt    }
38268d1491baSSteven Rostedt}
38272545eb61SSteven Rostedt
38282b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
38292b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
38302b7d9b21SSteven Rostedt}
38312545eb61SSteven Rostedt
38322b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
38332b7d9b21SSteven Rostedt
3834a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
3835a57419b3SSteven Rostedt
3836a57419b3SSteven Rostedt    if (!$i) {
3837a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
3838a57419b3SSteven Rostedt    } else {
3839a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
3840a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
3841a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
3842a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
3843a57419b3SSteven Rostedt	}
3844a57419b3SSteven Rostedt	doprint "\n";
3845a57419b3SSteven Rostedt    }
3846a57419b3SSteven Rostedt
38472b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
3848a57419b3SSteven Rostedt
3849a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
3850a57419b3SSteven Rostedt	    next if ($i != $1);
3851a57419b3SSteven Rostedt	} else {
3852a57419b3SSteven Rostedt	    next if ($i);
3853a57419b3SSteven Rostedt	}
3854a57419b3SSteven Rostedt
38552b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
38562b7d9b21SSteven Rostedt    }
3857a57419b3SSteven Rostedt}
38582545eb61SSteven Rostedt
38592a62512bSSteven Rostedtsub __set_test_option {
38605a391fbfSSteven Rostedt    my ($name, $i) = @_;
38615a391fbfSSteven Rostedt
38625a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
38635a391fbfSSteven Rostedt
38645a391fbfSSteven Rostedt    if (defined($opt{$option})) {
38655a391fbfSSteven Rostedt	return $opt{$option};
38665a391fbfSSteven Rostedt    }
38675a391fbfSSteven Rostedt
3868a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
3869a57419b3SSteven Rostedt	if ($i >= $test &&
3870a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
3871a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
3872a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
3873a57419b3SSteven Rostedt		return $opt{$option};
3874a57419b3SSteven Rostedt	    }
3875a57419b3SSteven Rostedt	}
3876a57419b3SSteven Rostedt    }
3877a57419b3SSteven Rostedt
38785a391fbfSSteven Rostedt    if (defined($opt{$name})) {
38795a391fbfSSteven Rostedt	return $opt{$name};
38805a391fbfSSteven Rostedt    }
38815a391fbfSSteven Rostedt
38825a391fbfSSteven Rostedt    return undef;
38835a391fbfSSteven Rostedt}
38845a391fbfSSteven Rostedt
38852a62512bSSteven Rostedtsub set_test_option {
38862a62512bSSteven Rostedt    my ($name, $i) = @_;
38872a62512bSSteven Rostedt
38882a62512bSSteven Rostedt    my $option = __set_test_option($name, $i);
38892a62512bSSteven Rostedt    return $option if (!defined($option));
38902a62512bSSteven Rostedt
389104262be3SSteven Rostedt (Red Hat)    return eval_option($name, $option, $i);
38922a62512bSSteven Rostedt}
38932a62512bSSteven Rostedt
38942545eb61SSteven Rostedt# First we need to do is the builds
3895a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
38962545eb61SSteven Rostedt
38974ab1cce5SSteven Rostedt    # Do not reboot on failing test options
38984ab1cce5SSteven Rostedt    $no_reboot = 1;
3899759a3cc6SSteven Rostedt    $reboot_success = 0;
39004ab1cce5SSteven Rostedt
3901683a3e64SSteven Rostedt    $have_version = 0;
3902683a3e64SSteven Rostedt
3903576f627cSSteven Rostedt    $iteration = $i;
3904576f627cSSteven Rostedt
3905c1434dccSSteven Rostedt    undef %force_config;
3906c1434dccSSteven Rostedt
3907a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
3908a75fececSSteven Rostedt
39099cc9e091SSteven Rostedt    # Load all the options into their mapped variable names
39109cc9e091SSteven Rostedt    foreach my $opt (keys %option_map) {
39119cc9e091SSteven Rostedt	${$option_map{$opt}} = set_test_option($opt, $i);
39129cc9e091SSteven Rostedt    }
3913b5f4aea6SSteven Rostedt
391435ce5952SSteven Rostedt    $start_minconfig_defined = 1;
391535ce5952SSteven Rostedt
3916921ed4c7SSteven Rostedt    # The first test may override the PRE_KTEST option
3917921ed4c7SSteven Rostedt    if (defined($pre_ktest) && $i == 1) {
3918921ed4c7SSteven Rostedt	doprint "\n";
3919921ed4c7SSteven Rostedt	run_command $pre_ktest;
3920921ed4c7SSteven Rostedt    }
3921921ed4c7SSteven Rostedt
3922921ed4c7SSteven Rostedt    # Any test can override the POST_KTEST option
3923921ed4c7SSteven Rostedt    # The last test takes precedence.
3924921ed4c7SSteven Rostedt    if (defined($post_ktest)) {
3925921ed4c7SSteven Rostedt	$final_post_ktest = $post_ktest;
3926921ed4c7SSteven Rostedt    }
3927921ed4c7SSteven Rostedt
39284c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
392935ce5952SSteven Rostedt	$start_minconfig_defined = 0;
39304c4ab120SSteven Rostedt	$start_minconfig = $minconfig;
39314c4ab120SSteven Rostedt    }
39324c4ab120SSteven Rostedt
3933a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
3934a75fececSSteven Rostedt
3935a908a665SAndrew Jones    foreach my $dir ($tmpdir, $outputdir) {
3936a908a665SAndrew Jones	if (!-d $dir) {
3937a908a665SAndrew Jones	    mkpath($dir) or
3938a908a665SAndrew Jones		die "can't create $dir";
3939a908a665SAndrew Jones	}
3940a75fececSSteven Rostedt    }
3941a75fececSSteven Rostedt
3942e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
3943e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
3944e48c5293SSteven Rostedt
3945a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
3946a9dd5d63SRabin Vincent    $testlog = "$tmpdir/testlog-$machine";
3947a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
3948a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
394951ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
3950a75fececSSteven Rostedt
3951bb8474b1SSteven Rostedt    if (!$buildonly) {
3952bb8474b1SSteven Rostedt	$target = "$ssh_user\@$machine";
3953a75fececSSteven Rostedt	if ($reboot_type eq "grub") {
3954576f627cSSteven Rostedt	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3955a15ba913SSteven Rostedt	} elsif ($reboot_type eq "grub2") {
3956a15ba913SSteven Rostedt	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3957a15ba913SSteven Rostedt	    dodie "GRUB_FILE not defined" if (!defined($grub_file));
39587786954cSSteven Rostedt	} elsif ($reboot_type eq "syslinux") {
39597786954cSSteven Rostedt	    dodie "SYSLINUX_LABEL not defined" if (!defined($syslinux_label));
3960a75fececSSteven Rostedt	}
3961bb8474b1SSteven Rostedt    }
3962a75fececSSteven Rostedt
3963a75fececSSteven Rostedt    my $run_type = $build_type;
3964a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
3965b5f4aea6SSteven Rostedt	$run_type = $patchcheck_type;
3966a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
3967b5f4aea6SSteven Rostedt	$run_type = $bisect_type;
39680a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
3969b5f4aea6SSteven Rostedt	$run_type = $config_bisect_type;
39704283b169SSteven Rostedt (Red Hat)    } elsif ($test_type eq "make_min_config") {
39714283b169SSteven Rostedt (Red Hat)	$run_type = "";
39724283b169SSteven Rostedt (Red Hat)    } elsif ($test_type eq "make_warnings_file") {
39734c4ab120SSteven Rostedt	$run_type = "";
39744c4ab120SSteven Rostedt    }
39754c4ab120SSteven Rostedt
3976a75fececSSteven Rostedt    # mistake in config file?
3977a75fececSSteven Rostedt    if (!defined($run_type)) {
3978a75fececSSteven Rostedt	$run_type = "ERROR";
3979a75fececSSteven Rostedt    }
39802545eb61SSteven Rostedt
3981e0a8742eSSteven Rostedt    my $installme = "";
3982e0a8742eSSteven Rostedt    $installme = " no_install" if ($no_install);
3983e0a8742eSSteven Rostedt
39842545eb61SSteven Rostedt    doprint "\n\n";
3985e0a8742eSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
39867faafbd6SSteven Rostedt
3987921ed4c7SSteven Rostedt    if (defined($pre_test)) {
3988921ed4c7SSteven Rostedt	run_command $pre_test;
3989921ed4c7SSteven Rostedt    }
3990921ed4c7SSteven Rostedt
39917faafbd6SSteven Rostedt    unlink $dmesg;
39927faafbd6SSteven Rostedt    unlink $buildlog;
3993a9dd5d63SRabin Vincent    unlink $testlog;
39942545eb61SSteven Rostedt
3995250bae8bSSteven Rostedt    if (defined($addconfig)) {
3996250bae8bSSteven Rostedt	my $min = $minconfig;
39972b7d9b21SSteven Rostedt	if (!defined($minconfig)) {
3998250bae8bSSteven Rostedt	    $min = "";
3999250bae8bSSteven Rostedt	}
4000250bae8bSSteven Rostedt	run_command "cat $addconfig $min > $tmpdir/add_config" or
40012b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
40029be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
40032b7d9b21SSteven Rostedt    }
40042b7d9b21SSteven Rostedt
40056c5ee0beSSteven Rostedt    if (defined($checkout)) {
40066c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
40076c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
40086c5ee0beSSteven Rostedt    }
40096c5ee0beSSteven Rostedt
4010759a3cc6SSteven Rostedt    $no_reboot = 0;
4011759a3cc6SSteven Rostedt
4012648a182cSSteven Rostedt    # A test may opt to not reboot the box
4013648a182cSSteven Rostedt    if ($reboot_on_success) {
4014759a3cc6SSteven Rostedt	$reboot_success = 1;
4015648a182cSSteven Rostedt    }
40164ab1cce5SSteven Rostedt
4017a75fececSSteven Rostedt    if ($test_type eq "bisect") {
40185f9b6cedSSteven Rostedt	bisect $i;
40195f9b6cedSSteven Rostedt	next;
40200a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
40210a05c769SSteven Rostedt	config_bisect $i;
40220a05c769SSteven Rostedt	next;
4023a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
40246c5ee0beSSteven Rostedt	patchcheck $i;
40256c5ee0beSSteven Rostedt	next;
40264c4ab120SSteven Rostedt    } elsif ($test_type eq "make_min_config") {
40274c4ab120SSteven Rostedt	make_min_config $i;
40284c4ab120SSteven Rostedt	next;
40294283b169SSteven Rostedt (Red Hat)    } elsif ($test_type eq "make_warnings_file") {
40304283b169SSteven Rostedt (Red Hat)	$no_reboot = 1;
40314283b169SSteven Rostedt (Red Hat)	make_warnings_file $i;
40324283b169SSteven Rostedt (Red Hat)	next;
40335f9b6cedSSteven Rostedt    }
40345f9b6cedSSteven Rostedt
40357faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
40367faafbd6SSteven Rostedt	build $build_type or next;
40374283b169SSteven Rostedt (Red Hat)	check_buildlog or next;
40382545eb61SSteven Rostedt    }
40392545eb61SSteven Rostedt
4040cd8e368fSSteven Rostedt    if ($test_type eq "install") {
4041cd8e368fSSteven Rostedt	get_version;
4042cd8e368fSSteven Rostedt	install;
4043cd8e368fSSteven Rostedt	success $i;
4044cd8e368fSSteven Rostedt	next;
4045cd8e368fSSteven Rostedt    }
4046cd8e368fSSteven Rostedt
4047a75fececSSteven Rostedt    if ($test_type ne "build") {
40487faafbd6SSteven Rostedt	my $failed = 0;
4049ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
4050a75fececSSteven Rostedt
4051a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
40527faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
40535a391fbfSSteven Rostedt	}
40547faafbd6SSteven Rostedt	end_monitor;
40557faafbd6SSteven Rostedt	next if ($failed);
4056a75fececSSteven Rostedt    }
40575a391fbfSSteven Rostedt
40585f9b6cedSSteven Rostedt    success $i;
405975c3fda7SSteven Rostedt}
40602545eb61SSteven Rostedt
4061921ed4c7SSteven Rostedtif (defined($final_post_ktest)) {
4062921ed4c7SSteven Rostedt    run_command $final_post_ktest;
4063921ed4c7SSteven Rostedt}
4064921ed4c7SSteven Rostedt
40655c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
406675c3fda7SSteven Rostedt    halt;
4067759a3cc6SSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) {
4068bc7c5803SSteven Rostedt    reboot_to_good;
4069648a182cSSteven Rostedt} elsif (defined($switch_to_good)) {
4070648a182cSSteven Rostedt    # still need to get to the good kernel
4071648a182cSSteven Rostedt    run_command $switch_to_good;
40725c42fc5bSSteven Rostedt}
407375c3fda7SSteven Rostedt
4074648a182cSSteven Rostedt
4075e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
4076e48c5293SSteven Rostedt
40772545eb61SSteven Rostedtexit 0;
4078