162306a36Sopenharmony_ci#!/usr/bin/perl -w
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0-only
362306a36Sopenharmony_ci#
462306a36Sopenharmony_ci# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
562306a36Sopenharmony_ci#
662306a36Sopenharmony_ci
762306a36Sopenharmony_ciuse strict;
862306a36Sopenharmony_ciuse IPC::Open2;
962306a36Sopenharmony_ciuse Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
1062306a36Sopenharmony_ciuse File::Path qw(mkpath);
1162306a36Sopenharmony_ciuse File::Copy qw(cp);
1262306a36Sopenharmony_ciuse FileHandle;
1362306a36Sopenharmony_ciuse FindBin;
1462306a36Sopenharmony_ciuse IO::Handle;
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cimy $VERSION = "0.2";
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci$| = 1;
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cimy %opt;
2162306a36Sopenharmony_cimy %repeat_tests;
2262306a36Sopenharmony_cimy %repeats;
2362306a36Sopenharmony_cimy %evals;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#default opts
2662306a36Sopenharmony_cimy %default = (
2762306a36Sopenharmony_ci    "MAILER"			=> "sendmail",	# default mailer
2862306a36Sopenharmony_ci    "EMAIL_ON_ERROR"		=> 1,
2962306a36Sopenharmony_ci    "EMAIL_WHEN_FINISHED"	=> 1,
3062306a36Sopenharmony_ci    "EMAIL_WHEN_CANCELED"	=> 0,
3162306a36Sopenharmony_ci    "EMAIL_WHEN_STARTED"	=> 0,
3262306a36Sopenharmony_ci    "NUM_TESTS"			=> 1,
3362306a36Sopenharmony_ci    "TEST_TYPE"			=> "build",
3462306a36Sopenharmony_ci    "BUILD_TYPE"		=> "oldconfig",
3562306a36Sopenharmony_ci    "MAKE_CMD"			=> "make",
3662306a36Sopenharmony_ci    "CLOSE_CONSOLE_SIGNAL"	=> "INT",
3762306a36Sopenharmony_ci    "TIMEOUT"			=> 120,
3862306a36Sopenharmony_ci    "TMP_DIR"			=> "/tmp/ktest/\${MACHINE}",
3962306a36Sopenharmony_ci    "SLEEP_TIME"		=> 60,		# sleep time between tests
4062306a36Sopenharmony_ci    "BUILD_NOCLEAN"		=> 0,
4162306a36Sopenharmony_ci    "REBOOT_ON_ERROR"		=> 0,
4262306a36Sopenharmony_ci    "POWEROFF_ON_ERROR"		=> 0,
4362306a36Sopenharmony_ci    "REBOOT_ON_SUCCESS"		=> 1,
4462306a36Sopenharmony_ci    "POWEROFF_ON_SUCCESS"	=> 0,
4562306a36Sopenharmony_ci    "BUILD_OPTIONS"		=> "",
4662306a36Sopenharmony_ci    "BISECT_SLEEP_TIME"		=> 60,		# sleep time between bisects
4762306a36Sopenharmony_ci    "PATCHCHECK_SLEEP_TIME"	=> 60, 		# sleep time between patch checks
4862306a36Sopenharmony_ci    "CLEAR_LOG"			=> 0,
4962306a36Sopenharmony_ci    "BISECT_MANUAL"		=> 0,
5062306a36Sopenharmony_ci    "BISECT_SKIP"		=> 1,
5162306a36Sopenharmony_ci    "BISECT_TRIES"		=> 1,
5262306a36Sopenharmony_ci    "MIN_CONFIG_TYPE"		=> "boot",
5362306a36Sopenharmony_ci    "SUCCESS_LINE"		=> "login:",
5462306a36Sopenharmony_ci    "DETECT_TRIPLE_FAULT"	=> 1,
5562306a36Sopenharmony_ci    "NO_INSTALL"		=> 0,
5662306a36Sopenharmony_ci    "BOOTED_TIMEOUT"		=> 1,
5762306a36Sopenharmony_ci    "DIE_ON_FAILURE"		=> 1,
5862306a36Sopenharmony_ci    "SSH_EXEC"			=> "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND",
5962306a36Sopenharmony_ci    "SCP_TO_TARGET"		=> "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE",
6062306a36Sopenharmony_ci    "SCP_TO_TARGET_INSTALL"	=> "\${SCP_TO_TARGET}",
6162306a36Sopenharmony_ci    "REBOOT"			=> "ssh \$SSH_USER\@\$MACHINE reboot",
6262306a36Sopenharmony_ci    "REBOOT_RETURN_CODE"	=> 255,
6362306a36Sopenharmony_ci    "STOP_AFTER_SUCCESS"	=> 10,
6462306a36Sopenharmony_ci    "STOP_AFTER_FAILURE"	=> 60,
6562306a36Sopenharmony_ci    "STOP_TEST_AFTER"		=> 600,
6662306a36Sopenharmony_ci    "MAX_MONITOR_WAIT"		=> 1800,
6762306a36Sopenharmony_ci    "GRUB_REBOOT"		=> "grub2-reboot",
6862306a36Sopenharmony_ci    "GRUB_BLS_GET"		=> "grubby --info=ALL",
6962306a36Sopenharmony_ci    "SYSLINUX"			=> "extlinux",
7062306a36Sopenharmony_ci    "SYSLINUX_PATH"		=> "/boot/extlinux",
7162306a36Sopenharmony_ci    "CONNECT_TIMEOUT"		=> 25,
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci# required, and we will ask users if they don't have them but we keep the default
7462306a36Sopenharmony_ci# value something that is common.
7562306a36Sopenharmony_ci    "REBOOT_TYPE"		=> "grub",
7662306a36Sopenharmony_ci    "LOCALVERSION"		=> "-test",
7762306a36Sopenharmony_ci    "SSH_USER"			=> "root",
7862306a36Sopenharmony_ci    "BUILD_TARGET"	 	=> "arch/x86/boot/bzImage",
7962306a36Sopenharmony_ci    "TARGET_IMAGE"		=> "/boot/vmlinuz-test",
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci    "LOG_FILE"			=> undef,
8262306a36Sopenharmony_ci    "IGNORE_UNUSED"		=> 0,
8362306a36Sopenharmony_ci);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cimy $test_log_start = 0;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cimy $ktest_config = "ktest.conf";
8862306a36Sopenharmony_cimy $version;
8962306a36Sopenharmony_cimy $have_version = 0;
9062306a36Sopenharmony_cimy $machine;
9162306a36Sopenharmony_cimy $last_machine;
9262306a36Sopenharmony_cimy $ssh_user;
9362306a36Sopenharmony_cimy $tmpdir;
9462306a36Sopenharmony_cimy $builddir;
9562306a36Sopenharmony_cimy $outputdir;
9662306a36Sopenharmony_cimy $output_config;
9762306a36Sopenharmony_cimy $test_type;
9862306a36Sopenharmony_cimy $build_type;
9962306a36Sopenharmony_cimy $build_options;
10062306a36Sopenharmony_cimy $final_post_ktest;
10162306a36Sopenharmony_cimy $pre_ktest;
10262306a36Sopenharmony_cimy $post_ktest;
10362306a36Sopenharmony_cimy $pre_test;
10462306a36Sopenharmony_cimy $pre_test_die;
10562306a36Sopenharmony_cimy $post_test;
10662306a36Sopenharmony_cimy $pre_build;
10762306a36Sopenharmony_cimy $post_build;
10862306a36Sopenharmony_cimy $pre_build_die;
10962306a36Sopenharmony_cimy $post_build_die;
11062306a36Sopenharmony_cimy $reboot_type;
11162306a36Sopenharmony_cimy $reboot_script;
11262306a36Sopenharmony_cimy $power_cycle;
11362306a36Sopenharmony_cimy $reboot;
11462306a36Sopenharmony_cimy $reboot_return_code;
11562306a36Sopenharmony_cimy $reboot_on_error;
11662306a36Sopenharmony_cimy $switch_to_good;
11762306a36Sopenharmony_cimy $switch_to_test;
11862306a36Sopenharmony_cimy $poweroff_on_error;
11962306a36Sopenharmony_cimy $reboot_on_success;
12062306a36Sopenharmony_cimy $die_on_failure;
12162306a36Sopenharmony_cimy $powercycle_after_reboot;
12262306a36Sopenharmony_cimy $poweroff_after_halt;
12362306a36Sopenharmony_cimy $max_monitor_wait;
12462306a36Sopenharmony_cimy $ssh_exec;
12562306a36Sopenharmony_cimy $scp_to_target;
12662306a36Sopenharmony_cimy $scp_to_target_install;
12762306a36Sopenharmony_cimy $power_off;
12862306a36Sopenharmony_cimy $grub_menu;
12962306a36Sopenharmony_cimy $last_grub_menu;
13062306a36Sopenharmony_cimy $grub_file;
13162306a36Sopenharmony_cimy $grub_number;
13262306a36Sopenharmony_cimy $grub_reboot;
13362306a36Sopenharmony_cimy $grub_bls_get;
13462306a36Sopenharmony_cimy $syslinux;
13562306a36Sopenharmony_cimy $syslinux_path;
13662306a36Sopenharmony_cimy $syslinux_label;
13762306a36Sopenharmony_cimy $target;
13862306a36Sopenharmony_cimy $make;
13962306a36Sopenharmony_cimy $pre_install;
14062306a36Sopenharmony_cimy $post_install;
14162306a36Sopenharmony_cimy $no_install;
14262306a36Sopenharmony_cimy $noclean;
14362306a36Sopenharmony_cimy $minconfig;
14462306a36Sopenharmony_cimy $start_minconfig;
14562306a36Sopenharmony_cimy $start_minconfig_defined;
14662306a36Sopenharmony_cimy $output_minconfig;
14762306a36Sopenharmony_cimy $minconfig_type;
14862306a36Sopenharmony_cimy $use_output_minconfig;
14962306a36Sopenharmony_cimy $warnings_file;
15062306a36Sopenharmony_cimy $ignore_config;
15162306a36Sopenharmony_cimy $ignore_errors;
15262306a36Sopenharmony_cimy $addconfig;
15362306a36Sopenharmony_cimy $in_bisect = 0;
15462306a36Sopenharmony_cimy $bisect_bad_commit = "";
15562306a36Sopenharmony_cimy $reverse_bisect;
15662306a36Sopenharmony_cimy $bisect_manual;
15762306a36Sopenharmony_cimy $bisect_skip;
15862306a36Sopenharmony_cimy $bisect_tries;
15962306a36Sopenharmony_cimy $config_bisect_good;
16062306a36Sopenharmony_cimy $bisect_ret_good;
16162306a36Sopenharmony_cimy $bisect_ret_bad;
16262306a36Sopenharmony_cimy $bisect_ret_skip;
16362306a36Sopenharmony_cimy $bisect_ret_abort;
16462306a36Sopenharmony_cimy $bisect_ret_default;
16562306a36Sopenharmony_cimy $in_patchcheck = 0;
16662306a36Sopenharmony_cimy $run_test;
16762306a36Sopenharmony_cimy $buildlog;
16862306a36Sopenharmony_cimy $testlog;
16962306a36Sopenharmony_cimy $dmesg;
17062306a36Sopenharmony_cimy $monitor_fp;
17162306a36Sopenharmony_cimy $monitor_pid;
17262306a36Sopenharmony_cimy $monitor_cnt = 0;
17362306a36Sopenharmony_cimy $sleep_time;
17462306a36Sopenharmony_cimy $bisect_sleep_time;
17562306a36Sopenharmony_cimy $patchcheck_sleep_time;
17662306a36Sopenharmony_cimy $ignore_warnings;
17762306a36Sopenharmony_cimy $store_failures;
17862306a36Sopenharmony_cimy $store_successes;
17962306a36Sopenharmony_cimy $test_name;
18062306a36Sopenharmony_cimy $timeout;
18162306a36Sopenharmony_cimy $run_timeout;
18262306a36Sopenharmony_cimy $connect_timeout;
18362306a36Sopenharmony_cimy $config_bisect_exec;
18462306a36Sopenharmony_cimy $booted_timeout;
18562306a36Sopenharmony_cimy $detect_triplefault;
18662306a36Sopenharmony_cimy $console;
18762306a36Sopenharmony_cimy $close_console_signal;
18862306a36Sopenharmony_cimy $reboot_success_line;
18962306a36Sopenharmony_cimy $success_line;
19062306a36Sopenharmony_cimy $stop_after_success;
19162306a36Sopenharmony_cimy $stop_after_failure;
19262306a36Sopenharmony_cimy $stop_test_after;
19362306a36Sopenharmony_cimy $build_target;
19462306a36Sopenharmony_cimy $target_image;
19562306a36Sopenharmony_cimy $checkout;
19662306a36Sopenharmony_cimy $localversion;
19762306a36Sopenharmony_cimy $iteration = 0;
19862306a36Sopenharmony_cimy $successes = 0;
19962306a36Sopenharmony_cimy $stty_orig;
20062306a36Sopenharmony_cimy $run_command_status = 0;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_cimy $bisect_good;
20362306a36Sopenharmony_cimy $bisect_bad;
20462306a36Sopenharmony_cimy $bisect_type;
20562306a36Sopenharmony_cimy $bisect_start;
20662306a36Sopenharmony_cimy $bisect_replay;
20762306a36Sopenharmony_cimy $bisect_files;
20862306a36Sopenharmony_cimy $bisect_reverse;
20962306a36Sopenharmony_cimy $bisect_check;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_cimy $config_bisect;
21262306a36Sopenharmony_cimy $config_bisect_type;
21362306a36Sopenharmony_cimy $config_bisect_check;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_cimy $patchcheck_type;
21662306a36Sopenharmony_cimy $patchcheck_start;
21762306a36Sopenharmony_cimy $patchcheck_cherry;
21862306a36Sopenharmony_cimy $patchcheck_end;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_cimy $build_time;
22162306a36Sopenharmony_cimy $install_time;
22262306a36Sopenharmony_cimy $reboot_time;
22362306a36Sopenharmony_cimy $test_time;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_cimy $pwd;
22662306a36Sopenharmony_cimy $dirname = $FindBin::Bin;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cimy $mailto;
22962306a36Sopenharmony_cimy $mailer;
23062306a36Sopenharmony_cimy $mail_path;
23162306a36Sopenharmony_cimy $mail_max_size;
23262306a36Sopenharmony_cimy $mail_command;
23362306a36Sopenharmony_cimy $email_on_error;
23462306a36Sopenharmony_cimy $email_when_finished;
23562306a36Sopenharmony_cimy $email_when_started;
23662306a36Sopenharmony_cimy $email_when_canceled;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cimy $script_start_time = localtime();
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci# set when a test is something other that just building or install
24162306a36Sopenharmony_ci# which would require more options.
24262306a36Sopenharmony_cimy $buildonly = 1;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci# tell build not to worry about warnings, even when WARNINGS_FILE is set
24562306a36Sopenharmony_cimy $warnings_ok = 0;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci# set when creating a new config
24862306a36Sopenharmony_cimy $newconfig = 0;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_cimy %entered_configs;
25162306a36Sopenharmony_cimy %config_help;
25262306a36Sopenharmony_cimy %variable;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci# force_config is the list of configs that we force enabled (or disabled)
25562306a36Sopenharmony_ci# in a .config file. The MIN_CONFIG and ADD_CONFIG configs.
25662306a36Sopenharmony_cimy %force_config;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci# do not force reboots on config problems
25962306a36Sopenharmony_cimy $no_reboot = 1;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci# reboot on success
26262306a36Sopenharmony_cimy $reboot_success = 0;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cimy %option_map = (
26562306a36Sopenharmony_ci    "MAILTO"			=> \$mailto,
26662306a36Sopenharmony_ci    "MAILER"			=> \$mailer,
26762306a36Sopenharmony_ci    "MAIL_PATH"			=> \$mail_path,
26862306a36Sopenharmony_ci    "MAIL_MAX_SIZE"		=> \$mail_max_size,
26962306a36Sopenharmony_ci    "MAIL_COMMAND"		=> \$mail_command,
27062306a36Sopenharmony_ci    "EMAIL_ON_ERROR"		=> \$email_on_error,
27162306a36Sopenharmony_ci    "EMAIL_WHEN_FINISHED"	=> \$email_when_finished,
27262306a36Sopenharmony_ci    "EMAIL_WHEN_STARTED"	=> \$email_when_started,
27362306a36Sopenharmony_ci    "EMAIL_WHEN_CANCELED"	=> \$email_when_canceled,
27462306a36Sopenharmony_ci    "MACHINE"			=> \$machine,
27562306a36Sopenharmony_ci    "SSH_USER"			=> \$ssh_user,
27662306a36Sopenharmony_ci    "TMP_DIR"			=> \$tmpdir,
27762306a36Sopenharmony_ci    "OUTPUT_DIR"		=> \$outputdir,
27862306a36Sopenharmony_ci    "BUILD_DIR"			=> \$builddir,
27962306a36Sopenharmony_ci    "TEST_TYPE"			=> \$test_type,
28062306a36Sopenharmony_ci    "PRE_KTEST"			=> \$pre_ktest,
28162306a36Sopenharmony_ci    "POST_KTEST"		=> \$post_ktest,
28262306a36Sopenharmony_ci    "PRE_TEST"			=> \$pre_test,
28362306a36Sopenharmony_ci    "PRE_TEST_DIE"		=> \$pre_test_die,
28462306a36Sopenharmony_ci    "POST_TEST"			=> \$post_test,
28562306a36Sopenharmony_ci    "BUILD_TYPE"		=> \$build_type,
28662306a36Sopenharmony_ci    "BUILD_OPTIONS"		=> \$build_options,
28762306a36Sopenharmony_ci    "PRE_BUILD"			=> \$pre_build,
28862306a36Sopenharmony_ci    "POST_BUILD"		=> \$post_build,
28962306a36Sopenharmony_ci    "PRE_BUILD_DIE"		=> \$pre_build_die,
29062306a36Sopenharmony_ci    "POST_BUILD_DIE"		=> \$post_build_die,
29162306a36Sopenharmony_ci    "POWER_CYCLE"		=> \$power_cycle,
29262306a36Sopenharmony_ci    "REBOOT"			=> \$reboot,
29362306a36Sopenharmony_ci    "REBOOT_RETURN_CODE"	=> \$reboot_return_code,
29462306a36Sopenharmony_ci    "BUILD_NOCLEAN"		=> \$noclean,
29562306a36Sopenharmony_ci    "MIN_CONFIG"		=> \$minconfig,
29662306a36Sopenharmony_ci    "OUTPUT_MIN_CONFIG"		=> \$output_minconfig,
29762306a36Sopenharmony_ci    "START_MIN_CONFIG"		=> \$start_minconfig,
29862306a36Sopenharmony_ci    "MIN_CONFIG_TYPE"		=> \$minconfig_type,
29962306a36Sopenharmony_ci    "USE_OUTPUT_MIN_CONFIG"	=> \$use_output_minconfig,
30062306a36Sopenharmony_ci    "WARNINGS_FILE"		=> \$warnings_file,
30162306a36Sopenharmony_ci    "IGNORE_CONFIG"		=> \$ignore_config,
30262306a36Sopenharmony_ci    "TEST"			=> \$run_test,
30362306a36Sopenharmony_ci    "ADD_CONFIG"		=> \$addconfig,
30462306a36Sopenharmony_ci    "REBOOT_TYPE"		=> \$reboot_type,
30562306a36Sopenharmony_ci    "GRUB_MENU"			=> \$grub_menu,
30662306a36Sopenharmony_ci    "GRUB_FILE"			=> \$grub_file,
30762306a36Sopenharmony_ci    "GRUB_REBOOT"		=> \$grub_reboot,
30862306a36Sopenharmony_ci    "GRUB_BLS_GET"		=> \$grub_bls_get,
30962306a36Sopenharmony_ci    "SYSLINUX"			=> \$syslinux,
31062306a36Sopenharmony_ci    "SYSLINUX_PATH"		=> \$syslinux_path,
31162306a36Sopenharmony_ci    "SYSLINUX_LABEL"		=> \$syslinux_label,
31262306a36Sopenharmony_ci    "PRE_INSTALL"		=> \$pre_install,
31362306a36Sopenharmony_ci    "POST_INSTALL"		=> \$post_install,
31462306a36Sopenharmony_ci    "NO_INSTALL"		=> \$no_install,
31562306a36Sopenharmony_ci    "REBOOT_SCRIPT"		=> \$reboot_script,
31662306a36Sopenharmony_ci    "REBOOT_ON_ERROR"		=> \$reboot_on_error,
31762306a36Sopenharmony_ci    "SWITCH_TO_GOOD"		=> \$switch_to_good,
31862306a36Sopenharmony_ci    "SWITCH_TO_TEST"		=> \$switch_to_test,
31962306a36Sopenharmony_ci    "POWEROFF_ON_ERROR"		=> \$poweroff_on_error,
32062306a36Sopenharmony_ci    "REBOOT_ON_SUCCESS"		=> \$reboot_on_success,
32162306a36Sopenharmony_ci    "DIE_ON_FAILURE"		=> \$die_on_failure,
32262306a36Sopenharmony_ci    "POWER_OFF"			=> \$power_off,
32362306a36Sopenharmony_ci    "POWERCYCLE_AFTER_REBOOT"	=> \$powercycle_after_reboot,
32462306a36Sopenharmony_ci    "POWEROFF_AFTER_HALT"	=> \$poweroff_after_halt,
32562306a36Sopenharmony_ci    "MAX_MONITOR_WAIT"		=> \$max_monitor_wait,
32662306a36Sopenharmony_ci    "SLEEP_TIME"		=> \$sleep_time,
32762306a36Sopenharmony_ci    "BISECT_SLEEP_TIME"		=> \$bisect_sleep_time,
32862306a36Sopenharmony_ci    "PATCHCHECK_SLEEP_TIME"	=> \$patchcheck_sleep_time,
32962306a36Sopenharmony_ci    "IGNORE_WARNINGS"		=> \$ignore_warnings,
33062306a36Sopenharmony_ci    "IGNORE_ERRORS"		=> \$ignore_errors,
33162306a36Sopenharmony_ci    "BISECT_MANUAL"		=> \$bisect_manual,
33262306a36Sopenharmony_ci    "BISECT_SKIP"		=> \$bisect_skip,
33362306a36Sopenharmony_ci    "BISECT_TRIES"		=> \$bisect_tries,
33462306a36Sopenharmony_ci    "CONFIG_BISECT_GOOD"	=> \$config_bisect_good,
33562306a36Sopenharmony_ci    "BISECT_RET_GOOD"		=> \$bisect_ret_good,
33662306a36Sopenharmony_ci    "BISECT_RET_BAD"		=> \$bisect_ret_bad,
33762306a36Sopenharmony_ci    "BISECT_RET_SKIP"		=> \$bisect_ret_skip,
33862306a36Sopenharmony_ci    "BISECT_RET_ABORT"		=> \$bisect_ret_abort,
33962306a36Sopenharmony_ci    "BISECT_RET_DEFAULT"	=> \$bisect_ret_default,
34062306a36Sopenharmony_ci    "STORE_FAILURES"		=> \$store_failures,
34162306a36Sopenharmony_ci    "STORE_SUCCESSES"		=> \$store_successes,
34262306a36Sopenharmony_ci    "TEST_NAME"			=> \$test_name,
34362306a36Sopenharmony_ci    "TIMEOUT"			=> \$timeout,
34462306a36Sopenharmony_ci    "RUN_TIMEOUT"		=> \$run_timeout,
34562306a36Sopenharmony_ci    "CONNECT_TIMEOUT"		=> \$connect_timeout,
34662306a36Sopenharmony_ci    "CONFIG_BISECT_EXEC"	=> \$config_bisect_exec,
34762306a36Sopenharmony_ci    "BOOTED_TIMEOUT"		=> \$booted_timeout,
34862306a36Sopenharmony_ci    "CONSOLE"			=> \$console,
34962306a36Sopenharmony_ci    "CLOSE_CONSOLE_SIGNAL"	=> \$close_console_signal,
35062306a36Sopenharmony_ci    "DETECT_TRIPLE_FAULT"	=> \$detect_triplefault,
35162306a36Sopenharmony_ci    "SUCCESS_LINE"		=> \$success_line,
35262306a36Sopenharmony_ci    "REBOOT_SUCCESS_LINE"	=> \$reboot_success_line,
35362306a36Sopenharmony_ci    "STOP_AFTER_SUCCESS"	=> \$stop_after_success,
35462306a36Sopenharmony_ci    "STOP_AFTER_FAILURE"	=> \$stop_after_failure,
35562306a36Sopenharmony_ci    "STOP_TEST_AFTER"		=> \$stop_test_after,
35662306a36Sopenharmony_ci    "BUILD_TARGET"		=> \$build_target,
35762306a36Sopenharmony_ci    "SSH_EXEC"			=> \$ssh_exec,
35862306a36Sopenharmony_ci    "SCP_TO_TARGET"		=> \$scp_to_target,
35962306a36Sopenharmony_ci    "SCP_TO_TARGET_INSTALL"	=> \$scp_to_target_install,
36062306a36Sopenharmony_ci    "CHECKOUT"			=> \$checkout,
36162306a36Sopenharmony_ci    "TARGET_IMAGE"		=> \$target_image,
36262306a36Sopenharmony_ci    "LOCALVERSION"		=> \$localversion,
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci    "BISECT_GOOD"		=> \$bisect_good,
36562306a36Sopenharmony_ci    "BISECT_BAD"		=> \$bisect_bad,
36662306a36Sopenharmony_ci    "BISECT_TYPE"		=> \$bisect_type,
36762306a36Sopenharmony_ci    "BISECT_START"		=> \$bisect_start,
36862306a36Sopenharmony_ci    "BISECT_REPLAY"		=> \$bisect_replay,
36962306a36Sopenharmony_ci    "BISECT_FILES"		=> \$bisect_files,
37062306a36Sopenharmony_ci    "BISECT_REVERSE"		=> \$bisect_reverse,
37162306a36Sopenharmony_ci    "BISECT_CHECK"		=> \$bisect_check,
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci    "CONFIG_BISECT"		=> \$config_bisect,
37462306a36Sopenharmony_ci    "CONFIG_BISECT_TYPE"	=> \$config_bisect_type,
37562306a36Sopenharmony_ci    "CONFIG_BISECT_CHECK"	=> \$config_bisect_check,
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci    "PATCHCHECK_TYPE"		=> \$patchcheck_type,
37862306a36Sopenharmony_ci    "PATCHCHECK_START"		=> \$patchcheck_start,
37962306a36Sopenharmony_ci    "PATCHCHECK_CHERRY"		=> \$patchcheck_cherry,
38062306a36Sopenharmony_ci    "PATCHCHECK_END"		=> \$patchcheck_end,
38162306a36Sopenharmony_ci);
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci# Options may be used by other options, record them.
38462306a36Sopenharmony_cimy %used_options;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci# default variables that can be used
38762306a36Sopenharmony_cichomp ($variable{"PWD"} = `pwd`);
38862306a36Sopenharmony_ci$pwd = $variable{"PWD"};
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci$config_help{"MACHINE"} = << "EOF"
39162306a36Sopenharmony_ci The machine hostname that you will test.
39262306a36Sopenharmony_ci For build only tests, it is still needed to differentiate log files.
39362306a36Sopenharmony_ciEOF
39462306a36Sopenharmony_ci    ;
39562306a36Sopenharmony_ci$config_help{"SSH_USER"} = << "EOF"
39662306a36Sopenharmony_ci The box is expected to have ssh on normal bootup, provide the user
39762306a36Sopenharmony_ci  (most likely root, since you need privileged operations)
39862306a36Sopenharmony_ciEOF
39962306a36Sopenharmony_ci    ;
40062306a36Sopenharmony_ci$config_help{"BUILD_DIR"} = << "EOF"
40162306a36Sopenharmony_ci The directory that contains the Linux source code (full path).
40262306a36Sopenharmony_ci You can use \${PWD} that will be the path where ktest.pl is run, or use
40362306a36Sopenharmony_ci \${THIS_DIR} which is assigned \${PWD} but may be changed later.
40462306a36Sopenharmony_ciEOF
40562306a36Sopenharmony_ci    ;
40662306a36Sopenharmony_ci$config_help{"OUTPUT_DIR"} = << "EOF"
40762306a36Sopenharmony_ci The directory that the objects will be built (full path).
40862306a36Sopenharmony_ci (can not be same as BUILD_DIR)
40962306a36Sopenharmony_ci You can use \${PWD} that will be the path where ktest.pl is run, or use
41062306a36Sopenharmony_ci \${THIS_DIR} which is assigned \${PWD} but may be changed later.
41162306a36Sopenharmony_ciEOF
41262306a36Sopenharmony_ci    ;
41362306a36Sopenharmony_ci$config_help{"BUILD_TARGET"} = << "EOF"
41462306a36Sopenharmony_ci The location of the compiled file to copy to the target.
41562306a36Sopenharmony_ci (relative to OUTPUT_DIR)
41662306a36Sopenharmony_ciEOF
41762306a36Sopenharmony_ci    ;
41862306a36Sopenharmony_ci$config_help{"BUILD_OPTIONS"} = << "EOF"
41962306a36Sopenharmony_ci Options to add to \"make\" when building.
42062306a36Sopenharmony_ci i.e.  -j20
42162306a36Sopenharmony_ciEOF
42262306a36Sopenharmony_ci    ;
42362306a36Sopenharmony_ci$config_help{"TARGET_IMAGE"} = << "EOF"
42462306a36Sopenharmony_ci The place to put your image on the test machine.
42562306a36Sopenharmony_ciEOF
42662306a36Sopenharmony_ci    ;
42762306a36Sopenharmony_ci$config_help{"POWER_CYCLE"} = << "EOF"
42862306a36Sopenharmony_ci A script or command to reboot the box.
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci Here is a digital loggers power switch example
43162306a36Sopenharmony_ci POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci Here is an example to reboot a virtual box on the current host
43462306a36Sopenharmony_ci with the name "Guest".
43562306a36Sopenharmony_ci POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
43662306a36Sopenharmony_ciEOF
43762306a36Sopenharmony_ci    ;
43862306a36Sopenharmony_ci$config_help{"CONSOLE"} = << "EOF"
43962306a36Sopenharmony_ci The script or command that reads the console
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci  If you use ttywatch server, something like the following would work.
44262306a36Sopenharmony_ciCONSOLE = nc -d localhost 3001
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci For a virtual machine with guest name "Guest".
44562306a36Sopenharmony_ciCONSOLE =  virsh console Guest
44662306a36Sopenharmony_ciEOF
44762306a36Sopenharmony_ci    ;
44862306a36Sopenharmony_ci$config_help{"LOCALVERSION"} = << "EOF"
44962306a36Sopenharmony_ci Required version ending to differentiate the test
45062306a36Sopenharmony_ci from other linux builds on the system.
45162306a36Sopenharmony_ciEOF
45262306a36Sopenharmony_ci    ;
45362306a36Sopenharmony_ci$config_help{"REBOOT_TYPE"} = << "EOF"
45462306a36Sopenharmony_ci Way to reboot the box to the test kernel.
45562306a36Sopenharmony_ci Only valid options so far are "grub", "grub2", "grub2bls", "syslinux", and "script".
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci If you specify grub, it will assume grub version 1
45862306a36Sopenharmony_ci and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
45962306a36Sopenharmony_ci and select that target to reboot to the kernel. If this is not
46062306a36Sopenharmony_ci your setup, then specify "script" and have a command or script
46162306a36Sopenharmony_ci specified in REBOOT_SCRIPT to boot to the target.
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci The entry in /boot/grub/menu.lst must be entered in manually.
46462306a36Sopenharmony_ci The test will not modify that file.
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci If you specify grub2, then you also need to specify both \$GRUB_MENU
46762306a36Sopenharmony_ci and \$GRUB_FILE.
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci If you specify grub2bls, then you also need to specify \$GRUB_MENU.
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci If you specify syslinux, then you may use SYSLINUX to define the syslinux
47262306a36Sopenharmony_ci command (defaults to extlinux), and SYSLINUX_PATH to specify the path to
47362306a36Sopenharmony_ci the syslinux install (defaults to /boot/extlinux). But you have to specify
47462306a36Sopenharmony_ci SYSLINUX_LABEL to define the label to boot to for the test kernel.
47562306a36Sopenharmony_ciEOF
47662306a36Sopenharmony_ci    ;
47762306a36Sopenharmony_ci$config_help{"GRUB_MENU"} = << "EOF"
47862306a36Sopenharmony_ci The grub title name for the test kernel to boot
47962306a36Sopenharmony_ci (Only mandatory if REBOOT_TYPE = grub or grub2)
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci Note, ktest.pl will not update the grub menu.lst, you need to
48262306a36Sopenharmony_ci manually add an option for the test. ktest.pl will search
48362306a36Sopenharmony_ci the grub menu.lst for this option to find what kernel to
48462306a36Sopenharmony_ci reboot into.
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci For example, if in the /boot/grub/menu.lst the test kernel title has:
48762306a36Sopenharmony_ci title Test Kernel
48862306a36Sopenharmony_ci kernel vmlinuz-test
48962306a36Sopenharmony_ci GRUB_MENU = Test Kernel
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci For grub2, a search of \$GRUB_FILE is performed for the lines
49262306a36Sopenharmony_ci that begin with "menuentry". It will not detect submenus. The
49362306a36Sopenharmony_ci menu must be a non-nested menu. Add the quotes used in the menu
49462306a36Sopenharmony_ci to guarantee your selection, as the first menuentry with the content
49562306a36Sopenharmony_ci of \$GRUB_MENU that is found will be used.
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci For grub2bls, \$GRUB_MENU is searched on the result of \$GRUB_BLS_GET
49862306a36Sopenharmony_ci command for the lines that begin with "title".
49962306a36Sopenharmony_ciEOF
50062306a36Sopenharmony_ci    ;
50162306a36Sopenharmony_ci$config_help{"GRUB_FILE"} = << "EOF"
50262306a36Sopenharmony_ci If grub2 is used, the full path for the grub.cfg file is placed
50362306a36Sopenharmony_ci here. Use something like /boot/grub2/grub.cfg to search.
50462306a36Sopenharmony_ciEOF
50562306a36Sopenharmony_ci    ;
50662306a36Sopenharmony_ci$config_help{"SYSLINUX_LABEL"} = << "EOF"
50762306a36Sopenharmony_ci If syslinux is used, the label that boots the target kernel must
50862306a36Sopenharmony_ci be specified with SYSLINUX_LABEL.
50962306a36Sopenharmony_ciEOF
51062306a36Sopenharmony_ci    ;
51162306a36Sopenharmony_ci$config_help{"REBOOT_SCRIPT"} = << "EOF"
51262306a36Sopenharmony_ci A script to reboot the target into the test kernel
51362306a36Sopenharmony_ci (Only mandatory if REBOOT_TYPE = script)
51462306a36Sopenharmony_ciEOF
51562306a36Sopenharmony_ci    ;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci# used with process_expression()
51862306a36Sopenharmony_cimy $d = 0;
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci# defined before get_test_name()
52162306a36Sopenharmony_cimy $in_die = 0;
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci# defined before process_warning_line()
52462306a36Sopenharmony_cimy $check_build_re = ".*:.*(warning|error|Error):.*";
52562306a36Sopenharmony_cimy $utf8_quote = "\\x{e2}\\x{80}(\\x{98}|\\x{99})";
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci# defined before child_finished()
52862306a36Sopenharmony_cimy $child_done;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci# config_ignore holds the configs that were set (or unset) for
53162306a36Sopenharmony_ci# a good config and we will ignore these configs for the rest
53262306a36Sopenharmony_ci# of a config bisect. These configs stay as they were.
53362306a36Sopenharmony_cimy %config_ignore;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci# config_set holds what all configs were set as.
53662306a36Sopenharmony_cimy %config_set;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci# config_off holds the set of configs that the bad config had disabled.
53962306a36Sopenharmony_ci# We need to record them and set them in the .config when running
54062306a36Sopenharmony_ci# olddefconfig, because olddefconfig keeps the defaults.
54162306a36Sopenharmony_cimy %config_off;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci# config_off_tmp holds a set of configs to turn off for now
54462306a36Sopenharmony_cimy @config_off_tmp;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci# config_list is the set of configs that are being tested
54762306a36Sopenharmony_cimy %config_list;
54862306a36Sopenharmony_cimy %null_config;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_cimy %dependency;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci# found above run_config_bisect()
55362306a36Sopenharmony_cimy $pass = 1;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci# found above add_dep()
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_cimy %depends;
55862306a36Sopenharmony_cimy %depcount;
55962306a36Sopenharmony_cimy $iflevel = 0;
56062306a36Sopenharmony_cimy @ifdeps;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci# prevent recursion
56362306a36Sopenharmony_cimy %read_kconfigs;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci# found above test_this_config()
56662306a36Sopenharmony_cimy %min_configs;
56762306a36Sopenharmony_cimy %keep_configs;
56862306a36Sopenharmony_cimy %save_configs;
56962306a36Sopenharmony_cimy %processed_configs;
57062306a36Sopenharmony_cimy %nochange_config;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci#
57362306a36Sopenharmony_ci# These are first defined here, main function later on
57462306a36Sopenharmony_ci#
57562306a36Sopenharmony_cisub run_command;
57662306a36Sopenharmony_cisub start_monitor;
57762306a36Sopenharmony_cisub end_monitor;
57862306a36Sopenharmony_cisub wait_for_monitor;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_cisub _logit {
58162306a36Sopenharmony_ci    if (defined($opt{"LOG_FILE"})) {
58262306a36Sopenharmony_ci	print LOG @_;
58362306a36Sopenharmony_ci    }
58462306a36Sopenharmony_ci}
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_cisub logit {
58762306a36Sopenharmony_ci    if (defined($opt{"LOG_FILE"})) {
58862306a36Sopenharmony_ci	_logit @_;
58962306a36Sopenharmony_ci    } else {
59062306a36Sopenharmony_ci	print @_;
59162306a36Sopenharmony_ci    }
59262306a36Sopenharmony_ci}
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_cisub doprint {
59562306a36Sopenharmony_ci    print @_;
59662306a36Sopenharmony_ci    _logit @_;
59762306a36Sopenharmony_ci}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_cisub read_prompt {
60062306a36Sopenharmony_ci    my ($cancel, $prompt) = @_;
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci    my $ans;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci    for (;;) {
60562306a36Sopenharmony_ci        if ($cancel) {
60662306a36Sopenharmony_ci	    print "$prompt [y/n/C] ";
60762306a36Sopenharmony_ci	} else {
60862306a36Sopenharmony_ci	    print "$prompt [Y/n] ";
60962306a36Sopenharmony_ci	}
61062306a36Sopenharmony_ci	$ans = <STDIN>;
61162306a36Sopenharmony_ci	chomp $ans;
61262306a36Sopenharmony_ci	if ($ans =~ /^\s*$/) {
61362306a36Sopenharmony_ci	    if ($cancel) {
61462306a36Sopenharmony_ci		$ans = "c";
61562306a36Sopenharmony_ci	    } else {
61662306a36Sopenharmony_ci		$ans = "y";
61762306a36Sopenharmony_ci	    }
61862306a36Sopenharmony_ci	}
61962306a36Sopenharmony_ci	last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
62062306a36Sopenharmony_ci	if ($cancel) {
62162306a36Sopenharmony_ci	    last if ($ans =~ /^c$/i);
62262306a36Sopenharmony_ci	    print "Please answer either 'y', 'n' or 'c'.\n";
62362306a36Sopenharmony_ci	} else {
62462306a36Sopenharmony_ci	    print "Please answer either 'y' or 'n'.\n";
62562306a36Sopenharmony_ci	}
62662306a36Sopenharmony_ci    }
62762306a36Sopenharmony_ci    if ($ans =~ /^c/i) {
62862306a36Sopenharmony_ci	exit;
62962306a36Sopenharmony_ci    }
63062306a36Sopenharmony_ci    if ($ans !~ /^y$/i) {
63162306a36Sopenharmony_ci	return 0;
63262306a36Sopenharmony_ci    }
63362306a36Sopenharmony_ci    return 1;
63462306a36Sopenharmony_ci}
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_cisub read_yn {
63762306a36Sopenharmony_ci    my ($prompt) = @_;
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci    return read_prompt 0, $prompt;
64062306a36Sopenharmony_ci}
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_cisub read_ync {
64362306a36Sopenharmony_ci    my ($prompt) = @_;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci    return read_prompt 1, $prompt;
64662306a36Sopenharmony_ci}
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_cisub get_mandatory_config {
64962306a36Sopenharmony_ci    my ($config) = @_;
65062306a36Sopenharmony_ci    my $ans;
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci    return if (defined($opt{$config}));
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci    if (defined($config_help{$config})) {
65562306a36Sopenharmony_ci	print "\n";
65662306a36Sopenharmony_ci	print $config_help{$config};
65762306a36Sopenharmony_ci    }
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci    for (;;) {
66062306a36Sopenharmony_ci	print "$config = ";
66162306a36Sopenharmony_ci	if (defined($default{$config}) && length($default{$config})) {
66262306a36Sopenharmony_ci	    print "\[$default{$config}\] ";
66362306a36Sopenharmony_ci	}
66462306a36Sopenharmony_ci	$ans = <STDIN>;
66562306a36Sopenharmony_ci	$ans =~ s/^\s*(.*\S)\s*$/$1/;
66662306a36Sopenharmony_ci	if ($ans =~ /^\s*$/) {
66762306a36Sopenharmony_ci	    if ($default{$config}) {
66862306a36Sopenharmony_ci		$ans = $default{$config};
66962306a36Sopenharmony_ci	    } else {
67062306a36Sopenharmony_ci		print "Your answer can not be blank\n";
67162306a36Sopenharmony_ci		next;
67262306a36Sopenharmony_ci	    }
67362306a36Sopenharmony_ci	}
67462306a36Sopenharmony_ci	$entered_configs{$config} = ${ans};
67562306a36Sopenharmony_ci	last;
67662306a36Sopenharmony_ci    }
67762306a36Sopenharmony_ci}
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_cisub show_time {
68062306a36Sopenharmony_ci    my ($time) = @_;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci    my $hours = 0;
68362306a36Sopenharmony_ci    my $minutes = 0;
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci    if ($time > 3600) {
68662306a36Sopenharmony_ci	$hours = int($time / 3600);
68762306a36Sopenharmony_ci	$time -= $hours * 3600;
68862306a36Sopenharmony_ci    }
68962306a36Sopenharmony_ci    if ($time > 60) {
69062306a36Sopenharmony_ci	$minutes = int($time / 60);
69162306a36Sopenharmony_ci	$time -= $minutes * 60;
69262306a36Sopenharmony_ci    }
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci    if ($hours > 0) {
69562306a36Sopenharmony_ci	doprint "$hours hour";
69662306a36Sopenharmony_ci	doprint "s" if ($hours > 1);
69762306a36Sopenharmony_ci	doprint " ";
69862306a36Sopenharmony_ci    }
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci    if ($minutes > 0) {
70162306a36Sopenharmony_ci	doprint "$minutes minute";
70262306a36Sopenharmony_ci	doprint "s" if ($minutes > 1);
70362306a36Sopenharmony_ci	doprint " ";
70462306a36Sopenharmony_ci    }
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci    doprint "$time second";
70762306a36Sopenharmony_ci    doprint "s" if ($time != 1);
70862306a36Sopenharmony_ci}
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_cisub print_times {
71162306a36Sopenharmony_ci    doprint "\n";
71262306a36Sopenharmony_ci    if ($build_time) {
71362306a36Sopenharmony_ci	doprint "Build time:   ";
71462306a36Sopenharmony_ci	show_time($build_time);
71562306a36Sopenharmony_ci	doprint "\n";
71662306a36Sopenharmony_ci    }
71762306a36Sopenharmony_ci    if ($install_time) {
71862306a36Sopenharmony_ci	doprint "Install time: ";
71962306a36Sopenharmony_ci	show_time($install_time);
72062306a36Sopenharmony_ci	doprint "\n";
72162306a36Sopenharmony_ci    }
72262306a36Sopenharmony_ci    if ($reboot_time) {
72362306a36Sopenharmony_ci	doprint "Reboot time:  ";
72462306a36Sopenharmony_ci	show_time($reboot_time);
72562306a36Sopenharmony_ci	doprint "\n";
72662306a36Sopenharmony_ci    }
72762306a36Sopenharmony_ci    if ($test_time) {
72862306a36Sopenharmony_ci	doprint "Test time:    ";
72962306a36Sopenharmony_ci	show_time($test_time);
73062306a36Sopenharmony_ci	doprint "\n";
73162306a36Sopenharmony_ci    }
73262306a36Sopenharmony_ci    # reset for iterations like bisect
73362306a36Sopenharmony_ci    $build_time = 0;
73462306a36Sopenharmony_ci    $install_time = 0;
73562306a36Sopenharmony_ci    $reboot_time = 0;
73662306a36Sopenharmony_ci    $test_time = 0;
73762306a36Sopenharmony_ci}
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_cisub get_mandatory_configs {
74062306a36Sopenharmony_ci    get_mandatory_config("MACHINE");
74162306a36Sopenharmony_ci    get_mandatory_config("BUILD_DIR");
74262306a36Sopenharmony_ci    get_mandatory_config("OUTPUT_DIR");
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci    if ($newconfig) {
74562306a36Sopenharmony_ci	get_mandatory_config("BUILD_OPTIONS");
74662306a36Sopenharmony_ci    }
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci    # options required for other than just building a kernel
74962306a36Sopenharmony_ci    if (!$buildonly) {
75062306a36Sopenharmony_ci	get_mandatory_config("POWER_CYCLE");
75162306a36Sopenharmony_ci	get_mandatory_config("CONSOLE");
75262306a36Sopenharmony_ci    }
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci    # options required for install and more
75562306a36Sopenharmony_ci    if ($buildonly != 1) {
75662306a36Sopenharmony_ci	get_mandatory_config("SSH_USER");
75762306a36Sopenharmony_ci	get_mandatory_config("BUILD_TARGET");
75862306a36Sopenharmony_ci	get_mandatory_config("TARGET_IMAGE");
75962306a36Sopenharmony_ci    }
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci    get_mandatory_config("LOCALVERSION");
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci    return if ($buildonly);
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci    my $rtype = $opt{"REBOOT_TYPE"};
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci    if (!defined($rtype)) {
76862306a36Sopenharmony_ci	if (!defined($opt{"GRUB_MENU"})) {
76962306a36Sopenharmony_ci	    get_mandatory_config("REBOOT_TYPE");
77062306a36Sopenharmony_ci	    $rtype = $entered_configs{"REBOOT_TYPE"};
77162306a36Sopenharmony_ci	} else {
77262306a36Sopenharmony_ci	    $rtype = "grub";
77362306a36Sopenharmony_ci	}
77462306a36Sopenharmony_ci    }
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci    if (($rtype eq "grub") or ($rtype eq "grub2bls")) {
77762306a36Sopenharmony_ci	get_mandatory_config("GRUB_MENU");
77862306a36Sopenharmony_ci    }
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci    if ($rtype eq "grub2") {
78162306a36Sopenharmony_ci	get_mandatory_config("GRUB_MENU");
78262306a36Sopenharmony_ci	get_mandatory_config("GRUB_FILE");
78362306a36Sopenharmony_ci    }
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci    if ($rtype eq "syslinux") {
78662306a36Sopenharmony_ci	get_mandatory_config("SYSLINUX_LABEL");
78762306a36Sopenharmony_ci    }
78862306a36Sopenharmony_ci}
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_cisub process_variables {
79162306a36Sopenharmony_ci    my ($value, $remove_undef) = @_;
79262306a36Sopenharmony_ci    my $retval = "";
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci    # We want to check for '\', and it is just easier
79562306a36Sopenharmony_ci    # to check the previous characet of '$' and not need
79662306a36Sopenharmony_ci    # to worry if '$' is the first character. By adding
79762306a36Sopenharmony_ci    # a space to $value, we can just check [^\\]\$ and
79862306a36Sopenharmony_ci    # it will still work.
79962306a36Sopenharmony_ci    $value = " $value";
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
80262306a36Sopenharmony_ci	my $begin = $1;
80362306a36Sopenharmony_ci	my $var = $2;
80462306a36Sopenharmony_ci	my $end = $3;
80562306a36Sopenharmony_ci	# append beginning of value to retval
80662306a36Sopenharmony_ci	$retval = "$retval$begin";
80762306a36Sopenharmony_ci	if ($var =~ s/^shell\s+//) {
80862306a36Sopenharmony_ci	    $retval = `$var`;
80962306a36Sopenharmony_ci	    if ($?) {
81062306a36Sopenharmony_ci		doprint "WARNING: $var returned an error\n";
81162306a36Sopenharmony_ci	    } else {
81262306a36Sopenharmony_ci		chomp $retval;
81362306a36Sopenharmony_ci	    }
81462306a36Sopenharmony_ci	} elsif (defined($variable{$var})) {
81562306a36Sopenharmony_ci	    $retval = "$retval$variable{$var}";
81662306a36Sopenharmony_ci	} elsif (defined($remove_undef) && $remove_undef) {
81762306a36Sopenharmony_ci	    # for if statements, any variable that is not defined,
81862306a36Sopenharmony_ci	    # we simple convert to 0
81962306a36Sopenharmony_ci	    $retval = "${retval}0";
82062306a36Sopenharmony_ci	} else {
82162306a36Sopenharmony_ci	    # put back the origin piece.
82262306a36Sopenharmony_ci	    $retval = "$retval\$\{$var\}";
82362306a36Sopenharmony_ci	    # This could be an option that is used later, save
82462306a36Sopenharmony_ci	    # it so we don't warn if this option is not one of
82562306a36Sopenharmony_ci	    # ktests options.
82662306a36Sopenharmony_ci	    $used_options{$var} = 1;
82762306a36Sopenharmony_ci	}
82862306a36Sopenharmony_ci	$value = $end;
82962306a36Sopenharmony_ci    }
83062306a36Sopenharmony_ci    $retval = "$retval$value";
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci    # remove the space added in the beginning
83362306a36Sopenharmony_ci    $retval =~ s/ //;
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ci    return "$retval";
83662306a36Sopenharmony_ci}
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_cisub set_value {
83962306a36Sopenharmony_ci    my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci    my $prvalue = process_variables($rvalue);
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci    if ($lvalue =~ /^(TEST|BISECT|CONFIG_BISECT)_TYPE(\[.*\])?$/ &&
84462306a36Sopenharmony_ci	$prvalue !~ /^(config_|)bisect$/ &&
84562306a36Sopenharmony_ci	$prvalue !~ /^build$/ &&
84662306a36Sopenharmony_ci	$buildonly) {
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	# Note if a test is something other than build, then we
84962306a36Sopenharmony_ci	# will need other mandatory options.
85062306a36Sopenharmony_ci	if ($prvalue ne "install") {
85162306a36Sopenharmony_ci	    $buildonly = 0;
85262306a36Sopenharmony_ci	} else {
85362306a36Sopenharmony_ci	    # install still limits some mandatory options.
85462306a36Sopenharmony_ci	    $buildonly = 2;
85562306a36Sopenharmony_ci	}
85662306a36Sopenharmony_ci    }
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci    if (defined($opt{$lvalue})) {
85962306a36Sopenharmony_ci	if (!$override || defined(${$overrides}{$lvalue})) {
86062306a36Sopenharmony_ci	    my $extra = "";
86162306a36Sopenharmony_ci	    if ($override) {
86262306a36Sopenharmony_ci		$extra = "In the same override section!\n";
86362306a36Sopenharmony_ci	    }
86462306a36Sopenharmony_ci	    die "$name: $.: Option $lvalue defined more than once!\n$extra";
86562306a36Sopenharmony_ci	}
86662306a36Sopenharmony_ci	${$overrides}{$lvalue} = $prvalue;
86762306a36Sopenharmony_ci    }
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci    $opt{$lvalue} = $prvalue;
87062306a36Sopenharmony_ci}
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_cisub set_eval {
87362306a36Sopenharmony_ci    my ($lvalue, $rvalue, $name) = @_;
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci    my $prvalue = process_variables($rvalue);
87662306a36Sopenharmony_ci    my $arr;
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci    if (defined($evals{$lvalue})) {
87962306a36Sopenharmony_ci	$arr = $evals{$lvalue};
88062306a36Sopenharmony_ci    } else {
88162306a36Sopenharmony_ci	$arr = [];
88262306a36Sopenharmony_ci	$evals{$lvalue} = $arr;
88362306a36Sopenharmony_ci    }
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci    push @{$arr}, $rvalue;
88662306a36Sopenharmony_ci}
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_cisub set_variable {
88962306a36Sopenharmony_ci    my ($lvalue, $rvalue) = @_;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci    if ($rvalue =~ /^\s*$/) {
89262306a36Sopenharmony_ci	delete $variable{$lvalue};
89362306a36Sopenharmony_ci    } else {
89462306a36Sopenharmony_ci	$rvalue = process_variables($rvalue);
89562306a36Sopenharmony_ci	$variable{$lvalue} = $rvalue;
89662306a36Sopenharmony_ci    }
89762306a36Sopenharmony_ci}
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_cisub process_compare {
90062306a36Sopenharmony_ci    my ($lval, $cmp, $rval) = @_;
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci    # remove whitespace
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci    $lval =~ s/^\s*//;
90562306a36Sopenharmony_ci    $lval =~ s/\s*$//;
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci    $rval =~ s/^\s*//;
90862306a36Sopenharmony_ci    $rval =~ s/\s*$//;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci    if ($cmp eq "==") {
91162306a36Sopenharmony_ci	return $lval eq $rval;
91262306a36Sopenharmony_ci    } elsif ($cmp eq "!=") {
91362306a36Sopenharmony_ci	return $lval ne $rval;
91462306a36Sopenharmony_ci    } elsif ($cmp eq "=~") {
91562306a36Sopenharmony_ci	return $lval =~ m/$rval/;
91662306a36Sopenharmony_ci    } elsif ($cmp eq "!~") {
91762306a36Sopenharmony_ci	return $lval !~ m/$rval/;
91862306a36Sopenharmony_ci    }
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci    my $statement = "$lval $cmp $rval";
92162306a36Sopenharmony_ci    my $ret = eval $statement;
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci    # $@ stores error of eval
92462306a36Sopenharmony_ci    if ($@) {
92562306a36Sopenharmony_ci	return -1;
92662306a36Sopenharmony_ci    }
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci    return $ret;
92962306a36Sopenharmony_ci}
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_cisub value_defined {
93262306a36Sopenharmony_ci    my ($val) = @_;
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci    return defined($variable{$2}) ||
93562306a36Sopenharmony_ci	defined($opt{$2});
93662306a36Sopenharmony_ci}
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_cisub process_expression {
93962306a36Sopenharmony_ci    my ($name, $val) = @_;
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci    my $c = $d++;
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
94462306a36Sopenharmony_ci	my $express = $1;
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	if (process_expression($name, $express)) {
94762306a36Sopenharmony_ci	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
94862306a36Sopenharmony_ci	} else {
94962306a36Sopenharmony_ci	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
95062306a36Sopenharmony_ci	}
95162306a36Sopenharmony_ci    }
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci    $d--;
95462306a36Sopenharmony_ci    my $OR = "\\|\\|";
95562306a36Sopenharmony_ci    my $AND = "\\&\\&";
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci    while ($val =~ s/^(.*?)($OR|$AND)//) {
95862306a36Sopenharmony_ci	my $express = $1;
95962306a36Sopenharmony_ci	my $op = $2;
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	if (process_expression($name, $express)) {
96262306a36Sopenharmony_ci	    if ($op eq "||") {
96362306a36Sopenharmony_ci		return 1;
96462306a36Sopenharmony_ci	    }
96562306a36Sopenharmony_ci	} else {
96662306a36Sopenharmony_ci	    if ($op eq "&&") {
96762306a36Sopenharmony_ci		return 0;
96862306a36Sopenharmony_ci	    }
96962306a36Sopenharmony_ci	}
97062306a36Sopenharmony_ci    }
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci    if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) {
97362306a36Sopenharmony_ci	my $ret = process_compare($1, $2, $3);
97462306a36Sopenharmony_ci	if ($ret < 0) {
97562306a36Sopenharmony_ci	    die "$name: $.: Unable to process comparison\n";
97662306a36Sopenharmony_ci	}
97762306a36Sopenharmony_ci	return $ret;
97862306a36Sopenharmony_ci    }
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
98162306a36Sopenharmony_ci	if (defined $1) {
98262306a36Sopenharmony_ci	    return !value_defined($2);
98362306a36Sopenharmony_ci	} else {
98462306a36Sopenharmony_ci	    return value_defined($2);
98562306a36Sopenharmony_ci	}
98662306a36Sopenharmony_ci    }
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci    if ($val =~ s/^\s*NOT\s+(.*)//) {
98962306a36Sopenharmony_ci	my $express = $1;
99062306a36Sopenharmony_ci	my $ret = process_expression($name, $express);
99162306a36Sopenharmony_ci	return !$ret;
99262306a36Sopenharmony_ci    }
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci    if ($val =~ /^\s*0\s*$/) {
99562306a36Sopenharmony_ci	return 0;
99662306a36Sopenharmony_ci    } elsif ($val =~ /^\s*\d+\s*$/) {
99762306a36Sopenharmony_ci	return 1;
99862306a36Sopenharmony_ci    }
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci    die ("$name: $.: Undefined content $val in if statement\n");
100162306a36Sopenharmony_ci}
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_cisub process_if {
100462306a36Sopenharmony_ci    my ($name, $value) = @_;
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci    # Convert variables and replace undefined ones with 0
100762306a36Sopenharmony_ci    my $val = process_variables($value, 1);
100862306a36Sopenharmony_ci    my $ret = process_expression $name, $val;
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci    return $ret;
101162306a36Sopenharmony_ci}
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_cisub __read_config {
101462306a36Sopenharmony_ci    my ($config, $current_test_num) = @_;
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci    my $in;
101762306a36Sopenharmony_ci    open($in, $config) || die "can't read file $config";
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci    my $name = $config;
102062306a36Sopenharmony_ci    $name =~ s,.*/(.*),$1,;
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci    my $test_num = $$current_test_num;
102362306a36Sopenharmony_ci    my $default = 1;
102462306a36Sopenharmony_ci    my $repeat = 1;
102562306a36Sopenharmony_ci    my $num_tests_set = 0;
102662306a36Sopenharmony_ci    my $skip = 0;
102762306a36Sopenharmony_ci    my $rest;
102862306a36Sopenharmony_ci    my $line;
102962306a36Sopenharmony_ci    my $test_case = 0;
103062306a36Sopenharmony_ci    my $if = 0;
103162306a36Sopenharmony_ci    my $if_set = 0;
103262306a36Sopenharmony_ci    my $override = 0;
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci    my %overrides;
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci    while (<$in>) {
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	# ignore blank lines and comments
103962306a36Sopenharmony_ci	next if (/^\s*$/ || /\s*\#/);
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	    my $type = $1;
104462306a36Sopenharmony_ci	    $rest = $2;
104562306a36Sopenharmony_ci	    $line = $2;
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	    my $old_test_num;
104862306a36Sopenharmony_ci	    my $old_repeat;
104962306a36Sopenharmony_ci	    $override = 0;
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci	    if ($type eq "TEST_START") {
105262306a36Sopenharmony_ci		if ($num_tests_set) {
105362306a36Sopenharmony_ci		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
105462306a36Sopenharmony_ci		}
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci		$old_test_num = $test_num;
105762306a36Sopenharmony_ci		$old_repeat = $repeat;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci		$test_num += $repeat;
106062306a36Sopenharmony_ci		$default = 0;
106162306a36Sopenharmony_ci		$repeat = 1;
106262306a36Sopenharmony_ci	    } else {
106362306a36Sopenharmony_ci		$default = 1;
106462306a36Sopenharmony_ci	    }
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	    # If SKIP is anywhere in the line, the command will be skipped
106762306a36Sopenharmony_ci	    if ($rest =~ s/\s+SKIP\b//) {
106862306a36Sopenharmony_ci		$skip = 1;
106962306a36Sopenharmony_ci	    } else {
107062306a36Sopenharmony_ci		$test_case = 1;
107162306a36Sopenharmony_ci		$skip = 0;
107262306a36Sopenharmony_ci	    }
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci	    if ($rest =~ s/\sELSE\b//) {
107562306a36Sopenharmony_ci		if (!$if) {
107662306a36Sopenharmony_ci		    die "$name: $.: ELSE found with out matching IF section\n$_";
107762306a36Sopenharmony_ci		}
107862306a36Sopenharmony_ci		$if = 0;
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci		if ($if_set) {
108162306a36Sopenharmony_ci		    $skip = 1;
108262306a36Sopenharmony_ci		} else {
108362306a36Sopenharmony_ci		    $skip = 0;
108462306a36Sopenharmony_ci		}
108562306a36Sopenharmony_ci	    }
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci	    if ($rest =~ s/\sIF\s+(.*)//) {
108862306a36Sopenharmony_ci		if (process_if($name, $1)) {
108962306a36Sopenharmony_ci		    $if_set = 1;
109062306a36Sopenharmony_ci		} else {
109162306a36Sopenharmony_ci		    $skip = 1;
109262306a36Sopenharmony_ci		}
109362306a36Sopenharmony_ci		$if = 1;
109462306a36Sopenharmony_ci	    } else {
109562306a36Sopenharmony_ci		$if = 0;
109662306a36Sopenharmony_ci		$if_set = 0;
109762306a36Sopenharmony_ci	    }
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci	    if (!$skip) {
110062306a36Sopenharmony_ci		if ($type eq "TEST_START") {
110162306a36Sopenharmony_ci		    if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
110262306a36Sopenharmony_ci			$repeat = $1;
110362306a36Sopenharmony_ci			$repeat_tests{"$test_num"} = $repeat;
110462306a36Sopenharmony_ci		    }
110562306a36Sopenharmony_ci		} elsif ($rest =~ s/\sOVERRIDE\b//) {
110662306a36Sopenharmony_ci		    # DEFAULT only
110762306a36Sopenharmony_ci		    $override = 1;
110862306a36Sopenharmony_ci		    # Clear previous overrides
110962306a36Sopenharmony_ci		    %overrides = ();
111062306a36Sopenharmony_ci		}
111162306a36Sopenharmony_ci	    }
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	    if (!$skip && $rest !~ /^\s*$/) {
111462306a36Sopenharmony_ci		die "$name: $.: Garbage found after $type\n$_";
111562306a36Sopenharmony_ci	    }
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci	    if ($skip && $type eq "TEST_START") {
111862306a36Sopenharmony_ci		$test_num = $old_test_num;
111962306a36Sopenharmony_ci		$repeat = $old_repeat;
112062306a36Sopenharmony_ci	    }
112162306a36Sopenharmony_ci	} elsif (/^\s*ELSE\b(.*)$/) {
112262306a36Sopenharmony_ci	    if (!$if) {
112362306a36Sopenharmony_ci		die "$name: $.: ELSE found with out matching IF section\n$_";
112462306a36Sopenharmony_ci	    }
112562306a36Sopenharmony_ci	    $rest = $1;
112662306a36Sopenharmony_ci	    if ($if_set) {
112762306a36Sopenharmony_ci		$skip = 1;
112862306a36Sopenharmony_ci		$rest = "";
112962306a36Sopenharmony_ci	    } else {
113062306a36Sopenharmony_ci		$skip = 0;
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci		if ($rest =~ /\sIF\s+(.*)/) {
113362306a36Sopenharmony_ci		    # May be a ELSE IF section.
113462306a36Sopenharmony_ci		    if (process_if($name, $1)) {
113562306a36Sopenharmony_ci			$if_set = 1;
113662306a36Sopenharmony_ci		    } else {
113762306a36Sopenharmony_ci			$skip = 1;
113862306a36Sopenharmony_ci		    }
113962306a36Sopenharmony_ci		    $rest = "";
114062306a36Sopenharmony_ci		} else {
114162306a36Sopenharmony_ci		    $if = 0;
114262306a36Sopenharmony_ci		}
114362306a36Sopenharmony_ci	    }
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	    if ($rest !~ /^\s*$/) {
114662306a36Sopenharmony_ci		die "$name: $.: Garbage found after DEFAULTS\n$_";
114762306a36Sopenharmony_ci	    }
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci	} elsif (/^\s*INCLUDE\s+(\S+)/) {
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	    next if ($skip);
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	    if (!$default) {
115462306a36Sopenharmony_ci		die "$name: $.: INCLUDE can only be done in default sections\n$_";
115562306a36Sopenharmony_ci	    }
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	    my $file = process_variables($1);
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci	    if ($file !~ m,^/,) {
116062306a36Sopenharmony_ci		# check the path of the config file first
116162306a36Sopenharmony_ci		if ($config =~ m,(.*)/,) {
116262306a36Sopenharmony_ci		    if (-f "$1/$file") {
116362306a36Sopenharmony_ci			$file = "$1/$file";
116462306a36Sopenharmony_ci		    }
116562306a36Sopenharmony_ci		}
116662306a36Sopenharmony_ci	    }
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	    if ( ! -r $file ) {
116962306a36Sopenharmony_ci		die "$name: $.: Can't read file $file\n$_";
117062306a36Sopenharmony_ci	    }
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci	    if (__read_config($file, \$test_num)) {
117362306a36Sopenharmony_ci		$test_case = 1;
117462306a36Sopenharmony_ci	    }
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=~\s*(.*?)\s*$/) {
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	    next if ($skip);
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci	    my $lvalue = $1;
118162306a36Sopenharmony_ci	    my $rvalue = $2;
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	    if ($default || $lvalue =~ /\[\d+\]$/) {
118462306a36Sopenharmony_ci		set_eval($lvalue, $rvalue, $name);
118562306a36Sopenharmony_ci	    } else {
118662306a36Sopenharmony_ci		my $val = "$lvalue\[$test_num\]";
118762306a36Sopenharmony_ci		set_eval($val, $rvalue, $name);
118862306a36Sopenharmony_ci	    }
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci	    next if ($skip);
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci	    my $lvalue = $1;
119562306a36Sopenharmony_ci	    my $rvalue = $2;
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	    if (!$default &&
119862306a36Sopenharmony_ci		($lvalue eq "NUM_TESTS" ||
119962306a36Sopenharmony_ci		 $lvalue eq "LOG_FILE" ||
120062306a36Sopenharmony_ci		 $lvalue eq "CLEAR_LOG")) {
120162306a36Sopenharmony_ci		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
120262306a36Sopenharmony_ci	    }
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	    if ($lvalue eq "NUM_TESTS") {
120562306a36Sopenharmony_ci		if ($test_num) {
120662306a36Sopenharmony_ci		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
120762306a36Sopenharmony_ci		}
120862306a36Sopenharmony_ci		if (!$default) {
120962306a36Sopenharmony_ci		    die "$name: $.: NUM_TESTS must be set in default section\n";
121062306a36Sopenharmony_ci		}
121162306a36Sopenharmony_ci		$num_tests_set = 1;
121262306a36Sopenharmony_ci	    }
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	    if ($default || $lvalue =~ /\[\d+\]$/) {
121562306a36Sopenharmony_ci		set_value($lvalue, $rvalue, $override, \%overrides, $name);
121662306a36Sopenharmony_ci	    } else {
121762306a36Sopenharmony_ci		my $val = "$lvalue\[$test_num\]";
121862306a36Sopenharmony_ci		set_value($val, $rvalue, $override, \%overrides, $name);
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci		if ($repeat > 1) {
122162306a36Sopenharmony_ci		    $repeats{$val} = $repeat;
122262306a36Sopenharmony_ci		}
122362306a36Sopenharmony_ci	    }
122462306a36Sopenharmony_ci	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
122562306a36Sopenharmony_ci	    next if ($skip);
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	    my $lvalue = $1;
122862306a36Sopenharmony_ci	    my $rvalue = $2;
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	    # process config variables.
123162306a36Sopenharmony_ci	    # Config variables are only active while reading the
123262306a36Sopenharmony_ci	    # config and can be defined anywhere. They also ignore
123362306a36Sopenharmony_ci	    # TEST_START and DEFAULTS, but are skipped if they are in
123462306a36Sopenharmony_ci	    # on of these sections that have SKIP defined.
123562306a36Sopenharmony_ci	    # The save variable can be
123662306a36Sopenharmony_ci	    # defined multiple times and the new one simply overrides
123762306a36Sopenharmony_ci	    # the previous one.
123862306a36Sopenharmony_ci	    set_variable($lvalue, $rvalue);
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	} else {
124162306a36Sopenharmony_ci	    die "$name: $.: Garbage found in config\n$_";
124262306a36Sopenharmony_ci	}
124362306a36Sopenharmony_ci    }
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci    if ($test_num) {
124662306a36Sopenharmony_ci	$test_num += $repeat - 1;
124762306a36Sopenharmony_ci	$opt{"NUM_TESTS"} = $test_num;
124862306a36Sopenharmony_ci    }
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci    close($in);
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_ci    $$current_test_num = $test_num;
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci    return $test_case;
125562306a36Sopenharmony_ci}
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_cisub get_test_case {
125862306a36Sopenharmony_ci    print "What test case would you like to run?\n";
125962306a36Sopenharmony_ci    print " (build, install or boot)\n";
126062306a36Sopenharmony_ci    print " Other tests are available but require editing ktest.conf\n";
126162306a36Sopenharmony_ci    print " (see tools/testing/ktest/sample.conf)\n";
126262306a36Sopenharmony_ci    my $ans = <STDIN>;
126362306a36Sopenharmony_ci    chomp $ans;
126462306a36Sopenharmony_ci    $default{"TEST_TYPE"} = $ans;
126562306a36Sopenharmony_ci}
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_cisub read_config {
126862306a36Sopenharmony_ci    my ($config) = @_;
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci    my $test_case;
127162306a36Sopenharmony_ci    my $test_num = 0;
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_ci    $test_case = __read_config $config, \$test_num;
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_ci    # make sure we have all mandatory configs
127662306a36Sopenharmony_ci    get_mandatory_configs;
127762306a36Sopenharmony_ci
127862306a36Sopenharmony_ci    # was a test specified?
127962306a36Sopenharmony_ci    if (!$test_case) {
128062306a36Sopenharmony_ci	print "No test case specified.\n";
128162306a36Sopenharmony_ci	get_test_case;
128262306a36Sopenharmony_ci    }
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_ci    # set any defaults
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci    foreach my $default (keys %default) {
128762306a36Sopenharmony_ci	if (!defined($opt{$default})) {
128862306a36Sopenharmony_ci	    $opt{$default} = $default{$default};
128962306a36Sopenharmony_ci	}
129062306a36Sopenharmony_ci    }
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci    if ($opt{"IGNORE_UNUSED"} == 1) {
129362306a36Sopenharmony_ci	return;
129462306a36Sopenharmony_ci    }
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci    my %not_used;
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci    # check if there are any stragglers (typos?)
129962306a36Sopenharmony_ci    foreach my $option (keys %opt) {
130062306a36Sopenharmony_ci	my $op = $option;
130162306a36Sopenharmony_ci	# remove per test labels.
130262306a36Sopenharmony_ci	$op =~ s/\[.*\]//;
130362306a36Sopenharmony_ci	if (!exists($option_map{$op}) &&
130462306a36Sopenharmony_ci	    !exists($default{$op}) &&
130562306a36Sopenharmony_ci	    !exists($used_options{$op})) {
130662306a36Sopenharmony_ci	    $not_used{$op} = 1;
130762306a36Sopenharmony_ci	}
130862306a36Sopenharmony_ci    }
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci    if (%not_used) {
131162306a36Sopenharmony_ci	my $s = "s are";
131262306a36Sopenharmony_ci	$s = " is" if (keys %not_used == 1);
131362306a36Sopenharmony_ci	print "The following option$s not used; could be a typo:\n";
131462306a36Sopenharmony_ci	foreach my $option (keys %not_used) {
131562306a36Sopenharmony_ci	    print "$option\n";
131662306a36Sopenharmony_ci	}
131762306a36Sopenharmony_ci	print "Set IGNORE_UNUSED = 1 to have ktest ignore unused variables\n";
131862306a36Sopenharmony_ci	if (!read_yn "Do you want to continue?") {
131962306a36Sopenharmony_ci	    exit -1;
132062306a36Sopenharmony_ci	}
132162306a36Sopenharmony_ci    }
132262306a36Sopenharmony_ci}
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_cisub __eval_option {
132562306a36Sopenharmony_ci    my ($name, $option, $i) = @_;
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci    # Add space to evaluate the character before $
132862306a36Sopenharmony_ci    $option = " $option";
132962306a36Sopenharmony_ci    my $retval = "";
133062306a36Sopenharmony_ci    my $repeated = 0;
133162306a36Sopenharmony_ci    my $parent = 0;
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci    foreach my $test (keys %repeat_tests) {
133462306a36Sopenharmony_ci	if ($i >= $test &&
133562306a36Sopenharmony_ci	    $i < $test + $repeat_tests{$test}) {
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci	    $repeated = 1;
133862306a36Sopenharmony_ci	    $parent = $test;
133962306a36Sopenharmony_ci	    last;
134062306a36Sopenharmony_ci	}
134162306a36Sopenharmony_ci    }
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
134462306a36Sopenharmony_ci	my $start = $1;
134562306a36Sopenharmony_ci	my $var = $2;
134662306a36Sopenharmony_ci	my $end = $3;
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	# Append beginning of line
134962306a36Sopenharmony_ci	$retval = "$retval$start";
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci	# If the iteration option OPT[$i] exists, then use that.
135262306a36Sopenharmony_ci	# otherwise see if the default OPT (without [$i]) exists.
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_ci	my $o = "$var\[$i\]";
135562306a36Sopenharmony_ci	my $parento = "$var\[$parent\]";
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci	# If a variable contains itself, use the default var
135862306a36Sopenharmony_ci	if (($var eq $name) && defined($opt{$var})) {
135962306a36Sopenharmony_ci	    $o = $opt{$var};
136062306a36Sopenharmony_ci	    $retval = "$retval$o";
136162306a36Sopenharmony_ci	} elsif (defined($opt{$o})) {
136262306a36Sopenharmony_ci	    $o = $opt{$o};
136362306a36Sopenharmony_ci	    $retval = "$retval$o";
136462306a36Sopenharmony_ci	} elsif ($repeated && defined($opt{$parento})) {
136562306a36Sopenharmony_ci	    $o = $opt{$parento};
136662306a36Sopenharmony_ci	    $retval = "$retval$o";
136762306a36Sopenharmony_ci	} elsif (defined($opt{$var})) {
136862306a36Sopenharmony_ci	    $o = $opt{$var};
136962306a36Sopenharmony_ci	    $retval = "$retval$o";
137062306a36Sopenharmony_ci	} elsif ($var eq "KERNEL_VERSION" && defined($make)) {
137162306a36Sopenharmony_ci	    # special option KERNEL_VERSION uses kernel version
137262306a36Sopenharmony_ci	    get_version();
137362306a36Sopenharmony_ci	    $retval = "$retval$version";
137462306a36Sopenharmony_ci	} else {
137562306a36Sopenharmony_ci	    $retval = "$retval\$\{$var\}";
137662306a36Sopenharmony_ci	}
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	$option = $end;
137962306a36Sopenharmony_ci    }
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci    $retval = "$retval$option";
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci    $retval =~ s/^ //;
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_ci    return $retval;
138662306a36Sopenharmony_ci}
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_cisub process_evals {
138962306a36Sopenharmony_ci    my ($name, $option, $i) = @_;
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_ci    my $option_name = "$name\[$i\]";
139262306a36Sopenharmony_ci    my $ev;
139362306a36Sopenharmony_ci
139462306a36Sopenharmony_ci    my $old_option = $option;
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci    if (defined($evals{$option_name})) {
139762306a36Sopenharmony_ci	$ev = $evals{$option_name};
139862306a36Sopenharmony_ci    } elsif (defined($evals{$name})) {
139962306a36Sopenharmony_ci	$ev = $evals{$name};
140062306a36Sopenharmony_ci    } else {
140162306a36Sopenharmony_ci	return $option;
140262306a36Sopenharmony_ci    }
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci    for my $e (@{$ev}) {
140562306a36Sopenharmony_ci	eval "\$option =~ $e";
140662306a36Sopenharmony_ci    }
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci    if ($option ne $old_option) {
140962306a36Sopenharmony_ci	doprint("$name changed from '$old_option' to '$option'\n");
141062306a36Sopenharmony_ci    }
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ci    return $option;
141362306a36Sopenharmony_ci}
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_cisub eval_option {
141662306a36Sopenharmony_ci    my ($name, $option, $i) = @_;
141762306a36Sopenharmony_ci
141862306a36Sopenharmony_ci    my $prev = "";
141962306a36Sopenharmony_ci
142062306a36Sopenharmony_ci    # Since an option can evaluate to another option,
142162306a36Sopenharmony_ci    # keep iterating until we do not evaluate any more
142262306a36Sopenharmony_ci    # options.
142362306a36Sopenharmony_ci    my $r = 0;
142462306a36Sopenharmony_ci    while ($prev ne $option) {
142562306a36Sopenharmony_ci	# Check for recursive evaluations.
142662306a36Sopenharmony_ci	# 100 deep should be more than enough.
142762306a36Sopenharmony_ci	if ($r++ > 100) {
142862306a36Sopenharmony_ci	    die "Over 100 evaluations occurred with $option\n" .
142962306a36Sopenharmony_ci		"Check for recursive variables\n";
143062306a36Sopenharmony_ci	}
143162306a36Sopenharmony_ci	$prev = $option;
143262306a36Sopenharmony_ci	$option = __eval_option($name, $option, $i);
143362306a36Sopenharmony_ci    }
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_ci    $option = process_evals($name, $option, $i);
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci    return $option;
143862306a36Sopenharmony_ci}
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_cisub reboot {
144162306a36Sopenharmony_ci    my ($time) = @_;
144262306a36Sopenharmony_ci    my $powercycle = 0;
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci    # test if the machine can be connected to within a few seconds
144562306a36Sopenharmony_ci    my $stat = run_ssh("echo check machine status", $connect_timeout);
144662306a36Sopenharmony_ci    if (!$stat) {
144762306a36Sopenharmony_ci	doprint("power cycle\n");
144862306a36Sopenharmony_ci	$powercycle = 1;
144962306a36Sopenharmony_ci    }
145062306a36Sopenharmony_ci
145162306a36Sopenharmony_ci    if ($powercycle) {
145262306a36Sopenharmony_ci	run_command "$power_cycle";
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	start_monitor;
145562306a36Sopenharmony_ci	# flush out current monitor
145662306a36Sopenharmony_ci	# May contain the reboot success line
145762306a36Sopenharmony_ci	wait_for_monitor 1;
145862306a36Sopenharmony_ci
145962306a36Sopenharmony_ci    } else {
146062306a36Sopenharmony_ci	# Make sure everything has been written to disk
146162306a36Sopenharmony_ci	run_ssh("sync", 10);
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	if (defined($time)) {
146462306a36Sopenharmony_ci	    start_monitor;
146562306a36Sopenharmony_ci	    # flush out current monitor
146662306a36Sopenharmony_ci	    # May contain the reboot success line
146762306a36Sopenharmony_ci	    wait_for_monitor 1;
146862306a36Sopenharmony_ci	}
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	# try to reboot normally
147162306a36Sopenharmony_ci	if (run_command $reboot) {
147262306a36Sopenharmony_ci	    if (defined($powercycle_after_reboot)) {
147362306a36Sopenharmony_ci		sleep $powercycle_after_reboot;
147462306a36Sopenharmony_ci		run_command "$power_cycle";
147562306a36Sopenharmony_ci	    }
147662306a36Sopenharmony_ci	} else {
147762306a36Sopenharmony_ci	    # nope? power cycle it.
147862306a36Sopenharmony_ci	    run_command "$power_cycle";
147962306a36Sopenharmony_ci	}
148062306a36Sopenharmony_ci    }
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci    if (defined($time)) {
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_ci	# We only want to get to the new kernel, don't fail
148562306a36Sopenharmony_ci	# if we stumble over a call trace.
148662306a36Sopenharmony_ci	my $save_ignore_errors = $ignore_errors;
148762306a36Sopenharmony_ci	$ignore_errors = 1;
148862306a36Sopenharmony_ci
148962306a36Sopenharmony_ci	# Look for the good kernel to boot
149062306a36Sopenharmony_ci	if (wait_for_monitor($time, "Linux version")) {
149162306a36Sopenharmony_ci	    # reboot got stuck?
149262306a36Sopenharmony_ci	    doprint "Reboot did not finish. Forcing power cycle\n";
149362306a36Sopenharmony_ci	    run_command "$power_cycle";
149462306a36Sopenharmony_ci	}
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	$ignore_errors = $save_ignore_errors;
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci	# Still need to wait for the reboot to finish
149962306a36Sopenharmony_ci	wait_for_monitor($time, $reboot_success_line);
150062306a36Sopenharmony_ci    }
150162306a36Sopenharmony_ci    if ($powercycle || $time) {
150262306a36Sopenharmony_ci	end_monitor;
150362306a36Sopenharmony_ci    }
150462306a36Sopenharmony_ci}
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_cisub reboot_to_good {
150762306a36Sopenharmony_ci    my ($time) = @_;
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci    if (defined($switch_to_good)) {
151062306a36Sopenharmony_ci	run_command $switch_to_good;
151162306a36Sopenharmony_ci    }
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci    reboot $time;
151462306a36Sopenharmony_ci}
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_cisub do_not_reboot {
151762306a36Sopenharmony_ci    my $i = $iteration;
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci    return $test_type eq "build" || $no_reboot ||
152062306a36Sopenharmony_ci	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
152162306a36Sopenharmony_ci	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build") ||
152262306a36Sopenharmony_ci	($test_type eq "config_bisect" && $opt{"CONFIG_BISECT_TYPE[$i]"} eq "build");
152362306a36Sopenharmony_ci}
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_cisub get_test_name() {
152662306a36Sopenharmony_ci    my $name;
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci    if (defined($test_name)) {
152962306a36Sopenharmony_ci	$name = "$test_name:$test_type";
153062306a36Sopenharmony_ci    } else {
153162306a36Sopenharmony_ci	$name = $test_type;
153262306a36Sopenharmony_ci    }
153362306a36Sopenharmony_ci    return $name;
153462306a36Sopenharmony_ci}
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_cisub dodie {
153762306a36Sopenharmony_ci    # avoid recursion
153862306a36Sopenharmony_ci    return if ($in_die);
153962306a36Sopenharmony_ci    $in_die = 1;
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci    if ($monitor_cnt) {
154262306a36Sopenharmony_ci	# restore terminal settings
154362306a36Sopenharmony_ci	system("stty $stty_orig");
154462306a36Sopenharmony_ci    }
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci    my $i = $iteration;
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci    doprint "CRITICAL FAILURE... [TEST $i] ", @_, "\n";
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_ci    if ($reboot_on_error && !do_not_reboot) {
155162306a36Sopenharmony_ci	doprint "REBOOTING\n";
155262306a36Sopenharmony_ci	reboot_to_good;
155362306a36Sopenharmony_ci    } elsif ($poweroff_on_error && defined($power_off)) {
155462306a36Sopenharmony_ci	doprint "POWERING OFF\n";
155562306a36Sopenharmony_ci	`$power_off`;
155662306a36Sopenharmony_ci    }
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci    if (defined($opt{"LOG_FILE"})) {
155962306a36Sopenharmony_ci	print " See $opt{LOG_FILE} for more info.\n";
156062306a36Sopenharmony_ci    }
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci    if ($email_on_error) {
156362306a36Sopenharmony_ci	my $name = get_test_name;
156462306a36Sopenharmony_ci	my $log_file;
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	if (defined($opt{"LOG_FILE"})) {
156762306a36Sopenharmony_ci	    my $whence = 2; # End of file
156862306a36Sopenharmony_ci	    my $log_size = tell LOG;
156962306a36Sopenharmony_ci	    my $size = $log_size - $test_log_start;
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	    if (defined($mail_max_size)) {
157262306a36Sopenharmony_ci		if ($size > $mail_max_size) {
157362306a36Sopenharmony_ci		    $size = $mail_max_size;
157462306a36Sopenharmony_ci		}
157562306a36Sopenharmony_ci	    }
157662306a36Sopenharmony_ci	    my $pos = - $size;
157762306a36Sopenharmony_ci	    $log_file = "$tmpdir/log";
157862306a36Sopenharmony_ci	    open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)";
157962306a36Sopenharmony_ci	    open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n";
158062306a36Sopenharmony_ci	    seek(L, $pos, $whence);
158162306a36Sopenharmony_ci	    while (<L>) {
158262306a36Sopenharmony_ci		print O;
158362306a36Sopenharmony_ci	    }
158462306a36Sopenharmony_ci	    close O;
158562306a36Sopenharmony_ci	    close L;
158662306a36Sopenharmony_ci	}
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci	send_email("KTEST: critical failure for test $i [$name]",
158962306a36Sopenharmony_ci		"Your test started at $script_start_time has failed with:\n@_\n", $log_file);
159062306a36Sopenharmony_ci    }
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_ci    if (defined($post_test)) {
159362306a36Sopenharmony_ci	run_command $post_test;
159462306a36Sopenharmony_ci    }
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci    die @_, "\n";
159762306a36Sopenharmony_ci}
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_cisub create_pty {
160062306a36Sopenharmony_ci    my ($ptm, $pts) = @_;
160162306a36Sopenharmony_ci    my $tmp;
160262306a36Sopenharmony_ci    my $TIOCSPTLCK = 0x40045431;
160362306a36Sopenharmony_ci    my $TIOCGPTN = 0x80045430;
160462306a36Sopenharmony_ci
160562306a36Sopenharmony_ci    sysopen($ptm, "/dev/ptmx", O_RDWR | O_NONBLOCK) or
160662306a36Sopenharmony_ci	dodie "Can't open /dev/ptmx";
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci    # unlockpt()
160962306a36Sopenharmony_ci    $tmp = pack("i", 0);
161062306a36Sopenharmony_ci    ioctl($ptm, $TIOCSPTLCK, $tmp) or
161162306a36Sopenharmony_ci	dodie "ioctl TIOCSPTLCK for /dev/ptmx failed";
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_ci    # ptsname()
161462306a36Sopenharmony_ci    ioctl($ptm, $TIOCGPTN, $tmp) or
161562306a36Sopenharmony_ci	dodie "ioctl TIOCGPTN for /dev/ptmx failed";
161662306a36Sopenharmony_ci    $tmp = unpack("i", $tmp);
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci    sysopen($pts, "/dev/pts/$tmp", O_RDWR | O_NONBLOCK) or
161962306a36Sopenharmony_ci	dodie "Can't open /dev/pts/$tmp";
162062306a36Sopenharmony_ci}
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_cisub exec_console {
162362306a36Sopenharmony_ci    my ($ptm, $pts) = @_;
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci    close($ptm);
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci    close(\*STDIN);
162862306a36Sopenharmony_ci    close(\*STDOUT);
162962306a36Sopenharmony_ci    close(\*STDERR);
163062306a36Sopenharmony_ci
163162306a36Sopenharmony_ci    open(\*STDIN, '<&', $pts);
163262306a36Sopenharmony_ci    open(\*STDOUT, '>&', $pts);
163362306a36Sopenharmony_ci    open(\*STDERR, '>&', $pts);
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_ci    close($pts);
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_ci    exec $console or
163862306a36Sopenharmony_ci	dodie "Can't open console $console";
163962306a36Sopenharmony_ci}
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_cisub open_console {
164262306a36Sopenharmony_ci    my ($ptm) = @_;
164362306a36Sopenharmony_ci    my $pts = \*PTSFD;
164462306a36Sopenharmony_ci    my $pid;
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_ci    # save terminal settings
164762306a36Sopenharmony_ci    $stty_orig = `stty -g`;
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci    # place terminal in cbreak mode so that stdin can be read one character at
165062306a36Sopenharmony_ci    # a time without having to wait for a newline
165162306a36Sopenharmony_ci    system("stty -icanon -echo -icrnl");
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci    create_pty($ptm, $pts);
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci    $pid = fork;
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_ci    if (!$pid) {
165862306a36Sopenharmony_ci	# child
165962306a36Sopenharmony_ci	exec_console($ptm, $pts)
166062306a36Sopenharmony_ci    }
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci    # parent
166362306a36Sopenharmony_ci    close($pts);
166462306a36Sopenharmony_ci
166562306a36Sopenharmony_ci    return $pid;
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci    open(PTSFD, "Stop perl from warning about single use of PTSFD");
166862306a36Sopenharmony_ci}
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_cisub close_console {
167162306a36Sopenharmony_ci    my ($fp, $pid) = @_;
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci    doprint "kill child process $pid\n";
167462306a36Sopenharmony_ci    kill $close_console_signal, $pid;
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_ci    doprint "wait for child process $pid to exit\n";
167762306a36Sopenharmony_ci    waitpid($pid, 0);
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci    print "closing!\n";
168062306a36Sopenharmony_ci    close($fp);
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci    # restore terminal settings
168362306a36Sopenharmony_ci    system("stty $stty_orig");
168462306a36Sopenharmony_ci}
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_cisub start_monitor {
168762306a36Sopenharmony_ci    if ($monitor_cnt++) {
168862306a36Sopenharmony_ci	return;
168962306a36Sopenharmony_ci    }
169062306a36Sopenharmony_ci    $monitor_fp = \*MONFD;
169162306a36Sopenharmony_ci    $monitor_pid = open_console $monitor_fp;
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_ci    return;
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_ci    open(MONFD, "Stop perl from warning about single use of MONFD");
169662306a36Sopenharmony_ci}
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_cisub end_monitor {
169962306a36Sopenharmony_ci    return if (!defined $console);
170062306a36Sopenharmony_ci    if (--$monitor_cnt) {
170162306a36Sopenharmony_ci	return;
170262306a36Sopenharmony_ci    }
170362306a36Sopenharmony_ci    close_console($monitor_fp, $monitor_pid);
170462306a36Sopenharmony_ci}
170562306a36Sopenharmony_ci
170662306a36Sopenharmony_cisub wait_for_monitor {
170762306a36Sopenharmony_ci    my ($time, $stop) = @_;
170862306a36Sopenharmony_ci    my $full_line = "";
170962306a36Sopenharmony_ci    my $line;
171062306a36Sopenharmony_ci    my $booted = 0;
171162306a36Sopenharmony_ci    my $start_time = time;
171262306a36Sopenharmony_ci    my $skip_call_trace = 0;
171362306a36Sopenharmony_ci    my $bug = 0;
171462306a36Sopenharmony_ci    my $bug_ignored = 0;
171562306a36Sopenharmony_ci    my $now;
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_ci    doprint "** Wait for monitor to settle down **\n";
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci    # read the monitor and wait for the system to calm down
172062306a36Sopenharmony_ci    while (!$booted) {
172162306a36Sopenharmony_ci	$line = wait_for_input($monitor_fp, $time);
172262306a36Sopenharmony_ci	last if (!defined($line));
172362306a36Sopenharmony_ci	print "$line";
172462306a36Sopenharmony_ci	$full_line .= $line;
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	if (defined($stop) && $full_line =~ /$stop/) {
172762306a36Sopenharmony_ci	    doprint "wait for monitor detected $stop\n";
172862306a36Sopenharmony_ci	    $booted = 1;
172962306a36Sopenharmony_ci	}
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci	if ($full_line =~ /\[ backtrace testing \]/) {
173262306a36Sopenharmony_ci	    $skip_call_trace = 1;
173362306a36Sopenharmony_ci	}
173462306a36Sopenharmony_ci
173562306a36Sopenharmony_ci	if ($full_line =~ /call trace:/i) {
173662306a36Sopenharmony_ci	    if (!$bug && !$skip_call_trace) {
173762306a36Sopenharmony_ci		if ($ignore_errors) {
173862306a36Sopenharmony_ci		    $bug_ignored = 1;
173962306a36Sopenharmony_ci		} else {
174062306a36Sopenharmony_ci		    $bug = 1;
174162306a36Sopenharmony_ci		}
174262306a36Sopenharmony_ci	    }
174362306a36Sopenharmony_ci	}
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	if ($full_line =~ /\[ end of backtrace testing \]/) {
174662306a36Sopenharmony_ci	    $skip_call_trace = 0;
174762306a36Sopenharmony_ci	}
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci	if ($full_line =~ /Kernel panic -/) {
175062306a36Sopenharmony_ci	    $bug = 1;
175162306a36Sopenharmony_ci	}
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	if ($line =~ /\n/) {
175462306a36Sopenharmony_ci	    $full_line = "";
175562306a36Sopenharmony_ci	}
175662306a36Sopenharmony_ci	$now = time;
175762306a36Sopenharmony_ci	if ($now - $start_time >= $max_monitor_wait) {
175862306a36Sopenharmony_ci	    doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n";
175962306a36Sopenharmony_ci	    return 1;
176062306a36Sopenharmony_ci	}
176162306a36Sopenharmony_ci    }
176262306a36Sopenharmony_ci    print "** Monitor flushed **\n";
176362306a36Sopenharmony_ci
176462306a36Sopenharmony_ci    # if stop is defined but wasn't hit, return error
176562306a36Sopenharmony_ci    # used by reboot (which wants to see a reboot)
176662306a36Sopenharmony_ci    if (defined($stop) && !$booted) {
176762306a36Sopenharmony_ci	$bug = 1;
176862306a36Sopenharmony_ci    }
176962306a36Sopenharmony_ci    return $bug;
177062306a36Sopenharmony_ci}
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_cisub save_logs {
177362306a36Sopenharmony_ci    my ($result, $basedir) = @_;
177462306a36Sopenharmony_ci    my @t = localtime;
177562306a36Sopenharmony_ci    my $date = sprintf "%04d%02d%02d%02d%02d%02d",
177662306a36Sopenharmony_ci	1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci    my $type = $build_type;
177962306a36Sopenharmony_ci    if ($type =~ /useconfig/) {
178062306a36Sopenharmony_ci	$type = "useconfig";
178162306a36Sopenharmony_ci    }
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci    my $dir = "$machine-$test_type-$type-$result-$date";
178462306a36Sopenharmony_ci
178562306a36Sopenharmony_ci    $dir = "$basedir/$dir";
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci    if (!-d $dir) {
178862306a36Sopenharmony_ci	mkpath($dir) or
178962306a36Sopenharmony_ci	    dodie "can't create $dir";
179062306a36Sopenharmony_ci    }
179162306a36Sopenharmony_ci
179262306a36Sopenharmony_ci    my %files = (
179362306a36Sopenharmony_ci	"config" => $output_config,
179462306a36Sopenharmony_ci	"buildlog" => $buildlog,
179562306a36Sopenharmony_ci	"dmesg" => $dmesg,
179662306a36Sopenharmony_ci	"testlog" => $testlog,
179762306a36Sopenharmony_ci    );
179862306a36Sopenharmony_ci
179962306a36Sopenharmony_ci    while (my ($name, $source) = each(%files)) {
180062306a36Sopenharmony_ci	if (-f "$source") {
180162306a36Sopenharmony_ci	    cp "$source", "$dir/$name" or
180262306a36Sopenharmony_ci		dodie "failed to copy $source";
180362306a36Sopenharmony_ci	}
180462306a36Sopenharmony_ci    }
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_ci    doprint "*** Saved info to $dir ***\n";
180762306a36Sopenharmony_ci}
180862306a36Sopenharmony_ci
180962306a36Sopenharmony_cisub fail {
181062306a36Sopenharmony_ci
181162306a36Sopenharmony_ci    if ($die_on_failure) {
181262306a36Sopenharmony_ci	dodie @_;
181362306a36Sopenharmony_ci    }
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci    doprint "FAILED\n";
181662306a36Sopenharmony_ci
181762306a36Sopenharmony_ci    my $i = $iteration;
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci    # no need to reboot for just building.
182062306a36Sopenharmony_ci    if (!do_not_reboot) {
182162306a36Sopenharmony_ci	doprint "REBOOTING\n";
182262306a36Sopenharmony_ci	reboot_to_good $sleep_time;
182362306a36Sopenharmony_ci    }
182462306a36Sopenharmony_ci
182562306a36Sopenharmony_ci    my $name = "";
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_ci    if (defined($test_name)) {
182862306a36Sopenharmony_ci	$name = " ($test_name)";
182962306a36Sopenharmony_ci    }
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci    print_times;
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_ci    doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
183462306a36Sopenharmony_ci    doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
183562306a36Sopenharmony_ci    doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
183662306a36Sopenharmony_ci    doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
183762306a36Sopenharmony_ci    doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
183862306a36Sopenharmony_ci
183962306a36Sopenharmony_ci    if (defined($store_failures)) {
184062306a36Sopenharmony_ci	save_logs "fail", $store_failures;
184162306a36Sopenharmony_ci    }
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_ci    if (defined($post_test)) {
184462306a36Sopenharmony_ci	run_command $post_test;
184562306a36Sopenharmony_ci    }
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_ci    return 1;
184862306a36Sopenharmony_ci}
184962306a36Sopenharmony_ci
185062306a36Sopenharmony_cisub run_command {
185162306a36Sopenharmony_ci    my ($command, $redirect, $timeout) = @_;
185262306a36Sopenharmony_ci    my $start_time;
185362306a36Sopenharmony_ci    my $end_time;
185462306a36Sopenharmony_ci    my $dolog = 0;
185562306a36Sopenharmony_ci    my $dord = 0;
185662306a36Sopenharmony_ci    my $dostdout = 0;
185762306a36Sopenharmony_ci    my $pid;
185862306a36Sopenharmony_ci    my $command_orig = $command;
185962306a36Sopenharmony_ci
186062306a36Sopenharmony_ci    $command =~ s/\$SSH_USER/$ssh_user/g;
186162306a36Sopenharmony_ci    $command =~ s/\$MACHINE/$machine/g;
186262306a36Sopenharmony_ci
186362306a36Sopenharmony_ci    if (!defined($timeout)) {
186462306a36Sopenharmony_ci	$timeout = $run_timeout;
186562306a36Sopenharmony_ci    }
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci    if (!defined($timeout)) {
186862306a36Sopenharmony_ci	$timeout = -1; # tell wait_for_input to wait indefinitely
186962306a36Sopenharmony_ci    }
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci    doprint("$command ... ");
187262306a36Sopenharmony_ci    $start_time = time;
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci    $pid = open(CMD, "$command 2>&1 |") or
187562306a36Sopenharmony_ci	(fail "unable to exec $command" and return 0);
187662306a36Sopenharmony_ci
187762306a36Sopenharmony_ci    if (defined($opt{"LOG_FILE"})) {
187862306a36Sopenharmony_ci	$dolog = 1;
187962306a36Sopenharmony_ci    }
188062306a36Sopenharmony_ci
188162306a36Sopenharmony_ci    if (defined($redirect)) {
188262306a36Sopenharmony_ci	if ($redirect eq 1) {
188362306a36Sopenharmony_ci	    $dostdout = 1;
188462306a36Sopenharmony_ci	    # Have the output of the command on its own line
188562306a36Sopenharmony_ci	    doprint "\n";
188662306a36Sopenharmony_ci	} else {
188762306a36Sopenharmony_ci	    open (RD, ">$redirect") or
188862306a36Sopenharmony_ci		dodie "failed to write to redirect $redirect";
188962306a36Sopenharmony_ci	    $dord = 1;
189062306a36Sopenharmony_ci	}
189162306a36Sopenharmony_ci    }
189262306a36Sopenharmony_ci
189362306a36Sopenharmony_ci    my $hit_timeout = 0;
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci    while (1) {
189662306a36Sopenharmony_ci	my $fp = \*CMD;
189762306a36Sopenharmony_ci	my $line = wait_for_input($fp, $timeout);
189862306a36Sopenharmony_ci	if (!defined($line)) {
189962306a36Sopenharmony_ci	    my $now = time;
190062306a36Sopenharmony_ci	    if ($timeout >= 0 && (($now - $start_time) >= $timeout)) {
190162306a36Sopenharmony_ci		doprint "Hit timeout of $timeout, killing process\n";
190262306a36Sopenharmony_ci		$hit_timeout = 1;
190362306a36Sopenharmony_ci		kill 9, $pid;
190462306a36Sopenharmony_ci	    }
190562306a36Sopenharmony_ci	    last;
190662306a36Sopenharmony_ci	}
190762306a36Sopenharmony_ci	print LOG $line if ($dolog);
190862306a36Sopenharmony_ci	print RD $line if ($dord);
190962306a36Sopenharmony_ci	print $line if ($dostdout);
191062306a36Sopenharmony_ci    }
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci    waitpid($pid, 0);
191362306a36Sopenharmony_ci    # shift 8 for real exit status
191462306a36Sopenharmony_ci    $run_command_status = $? >> 8;
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_ci    if ($command_orig eq $default{REBOOT} &&
191762306a36Sopenharmony_ci	$run_command_status == $reboot_return_code) {
191862306a36Sopenharmony_ci	$run_command_status = 0;
191962306a36Sopenharmony_ci    }
192062306a36Sopenharmony_ci
192162306a36Sopenharmony_ci    close(CMD);
192262306a36Sopenharmony_ci    close(RD)  if ($dord);
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci    $end_time = time;
192562306a36Sopenharmony_ci    my $delta = $end_time - $start_time;
192662306a36Sopenharmony_ci
192762306a36Sopenharmony_ci    if ($delta == 1) {
192862306a36Sopenharmony_ci	doprint "[1 second] ";
192962306a36Sopenharmony_ci    } else {
193062306a36Sopenharmony_ci	doprint "[$delta seconds] ";
193162306a36Sopenharmony_ci    }
193262306a36Sopenharmony_ci
193362306a36Sopenharmony_ci    if ($hit_timeout) {
193462306a36Sopenharmony_ci	$run_command_status = 1;
193562306a36Sopenharmony_ci    }
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci    if ($run_command_status) {
193862306a36Sopenharmony_ci	doprint "FAILED!\n";
193962306a36Sopenharmony_ci    } else {
194062306a36Sopenharmony_ci	doprint "SUCCESS\n";
194162306a36Sopenharmony_ci    }
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci    return !$run_command_status;
194462306a36Sopenharmony_ci}
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_cisub run_ssh {
194762306a36Sopenharmony_ci    my ($cmd, $timeout) = @_;
194862306a36Sopenharmony_ci    my $cp_exec = $ssh_exec;
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
195162306a36Sopenharmony_ci    return run_command "$cp_exec", undef , $timeout;
195262306a36Sopenharmony_ci}
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_cisub run_scp {
195562306a36Sopenharmony_ci    my ($src, $dst, $cp_scp) = @_;
195662306a36Sopenharmony_ci
195762306a36Sopenharmony_ci    $cp_scp =~ s/\$SRC_FILE/$src/g;
195862306a36Sopenharmony_ci    $cp_scp =~ s/\$DST_FILE/$dst/g;
195962306a36Sopenharmony_ci
196062306a36Sopenharmony_ci    return run_command "$cp_scp";
196162306a36Sopenharmony_ci}
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_cisub run_scp_install {
196462306a36Sopenharmony_ci    my ($src, $dst) = @_;
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci    my $cp_scp = $scp_to_target_install;
196762306a36Sopenharmony_ci
196862306a36Sopenharmony_ci    return run_scp($src, $dst, $cp_scp);
196962306a36Sopenharmony_ci}
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_cisub run_scp_mod {
197262306a36Sopenharmony_ci    my ($src, $dst) = @_;
197362306a36Sopenharmony_ci
197462306a36Sopenharmony_ci    my $cp_scp = $scp_to_target;
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci    return run_scp($src, $dst, $cp_scp);
197762306a36Sopenharmony_ci}
197862306a36Sopenharmony_ci
197962306a36Sopenharmony_cisub _get_grub_index {
198062306a36Sopenharmony_ci
198162306a36Sopenharmony_ci    my ($command, $target, $skip, $submenu) = @_;
198262306a36Sopenharmony_ci
198362306a36Sopenharmony_ci    return if (defined($grub_number) && defined($last_grub_menu) &&
198462306a36Sopenharmony_ci	$last_grub_menu eq $grub_menu && defined($last_machine) &&
198562306a36Sopenharmony_ci	$last_machine eq $machine);
198662306a36Sopenharmony_ci
198762306a36Sopenharmony_ci    doprint "Find $reboot_type menu ... ";
198862306a36Sopenharmony_ci    $grub_number = -1;
198962306a36Sopenharmony_ci
199062306a36Sopenharmony_ci    my $ssh_grub = $ssh_exec;
199162306a36Sopenharmony_ci    $ssh_grub =~ s,\$SSH_COMMAND,$command,g;
199262306a36Sopenharmony_ci
199362306a36Sopenharmony_ci    open(IN, "$ssh_grub |") or
199462306a36Sopenharmony_ci	dodie "unable to execute $command";
199562306a36Sopenharmony_ci
199662306a36Sopenharmony_ci    my $found = 0;
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_ci    my $submenu_number = 0;
199962306a36Sopenharmony_ci
200062306a36Sopenharmony_ci    while (<IN>) {
200162306a36Sopenharmony_ci	if (/$target/) {
200262306a36Sopenharmony_ci	    $grub_number++;
200362306a36Sopenharmony_ci	    $found = 1;
200462306a36Sopenharmony_ci	    last;
200562306a36Sopenharmony_ci	} elsif (defined($submenu) && /$submenu/) {
200662306a36Sopenharmony_ci		$submenu_number++;
200762306a36Sopenharmony_ci		$grub_number = -1;
200862306a36Sopenharmony_ci	} elsif (/$skip/) {
200962306a36Sopenharmony_ci	    $grub_number++;
201062306a36Sopenharmony_ci	}
201162306a36Sopenharmony_ci    }
201262306a36Sopenharmony_ci    close(IN);
201362306a36Sopenharmony_ci
201462306a36Sopenharmony_ci    dodie "Could not find '$grub_menu' through $command on $machine"
201562306a36Sopenharmony_ci	if (!$found);
201662306a36Sopenharmony_ci    if ($submenu_number > 0) {
201762306a36Sopenharmony_ci	$grub_number = "$submenu_number>$grub_number";
201862306a36Sopenharmony_ci    }
201962306a36Sopenharmony_ci    doprint "$grub_number\n";
202062306a36Sopenharmony_ci    $last_grub_menu = $grub_menu;
202162306a36Sopenharmony_ci    $last_machine = $machine;
202262306a36Sopenharmony_ci}
202362306a36Sopenharmony_ci
202462306a36Sopenharmony_cisub get_grub_index {
202562306a36Sopenharmony_ci
202662306a36Sopenharmony_ci    my $command;
202762306a36Sopenharmony_ci    my $target;
202862306a36Sopenharmony_ci    my $skip;
202962306a36Sopenharmony_ci    my $submenu;
203062306a36Sopenharmony_ci    my $grub_menu_qt;
203162306a36Sopenharmony_ci
203262306a36Sopenharmony_ci    if ($reboot_type !~ /^grub/) {
203362306a36Sopenharmony_ci	return;
203462306a36Sopenharmony_ci    }
203562306a36Sopenharmony_ci
203662306a36Sopenharmony_ci    $grub_menu_qt = quotemeta($grub_menu);
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ci    if ($reboot_type eq "grub") {
203962306a36Sopenharmony_ci	$command = "cat /boot/grub/menu.lst";
204062306a36Sopenharmony_ci	$target = '^\s*title\s+' . $grub_menu_qt . '\s*$';
204162306a36Sopenharmony_ci	$skip = '^\s*title\s';
204262306a36Sopenharmony_ci    } elsif ($reboot_type eq "grub2") {
204362306a36Sopenharmony_ci	$command = "cat $grub_file";
204462306a36Sopenharmony_ci	$target = '^\s*menuentry.*' . $grub_menu_qt;
204562306a36Sopenharmony_ci	$skip = '^\s*menuentry';
204662306a36Sopenharmony_ci	$submenu = '^\s*submenu\s';
204762306a36Sopenharmony_ci    } elsif ($reboot_type eq "grub2bls") {
204862306a36Sopenharmony_ci	$command = $grub_bls_get;
204962306a36Sopenharmony_ci	$target = '^title=.*' . $grub_menu_qt;
205062306a36Sopenharmony_ci	$skip = '^title=';
205162306a36Sopenharmony_ci    } else {
205262306a36Sopenharmony_ci	return;
205362306a36Sopenharmony_ci    }
205462306a36Sopenharmony_ci
205562306a36Sopenharmony_ci    _get_grub_index($command, $target, $skip, $submenu);
205662306a36Sopenharmony_ci}
205762306a36Sopenharmony_ci
205862306a36Sopenharmony_cisub wait_for_input {
205962306a36Sopenharmony_ci    my ($fp, $time) = @_;
206062306a36Sopenharmony_ci    my $start_time;
206162306a36Sopenharmony_ci    my $rin;
206262306a36Sopenharmony_ci    my $rout;
206362306a36Sopenharmony_ci    my $nr;
206462306a36Sopenharmony_ci    my $buf;
206562306a36Sopenharmony_ci    my $line;
206662306a36Sopenharmony_ci    my $ch;
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci    if (!defined($time)) {
206962306a36Sopenharmony_ci	$time = $timeout;
207062306a36Sopenharmony_ci    }
207162306a36Sopenharmony_ci
207262306a36Sopenharmony_ci    if ($time < 0) {
207362306a36Sopenharmony_ci	# Negative number means wait indefinitely
207462306a36Sopenharmony_ci	undef $time;
207562306a36Sopenharmony_ci    }
207662306a36Sopenharmony_ci
207762306a36Sopenharmony_ci    $rin = '';
207862306a36Sopenharmony_ci    vec($rin, fileno($fp), 1) = 1;
207962306a36Sopenharmony_ci    vec($rin, fileno(\*STDIN), 1) = 1;
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci    $start_time = time;
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci    while (1) {
208462306a36Sopenharmony_ci	$nr = select($rout=$rin, undef, undef, $time);
208562306a36Sopenharmony_ci
208662306a36Sopenharmony_ci	last if ($nr <= 0);
208762306a36Sopenharmony_ci
208862306a36Sopenharmony_ci	# copy data from stdin to the console
208962306a36Sopenharmony_ci	if (vec($rout, fileno(\*STDIN), 1) == 1) {
209062306a36Sopenharmony_ci	    $nr = sysread(\*STDIN, $buf, 1000);
209162306a36Sopenharmony_ci	    syswrite($fp, $buf, $nr) if ($nr > 0);
209262306a36Sopenharmony_ci	}
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_ci	# The timeout is based on time waiting for the fp data
209562306a36Sopenharmony_ci	if (vec($rout, fileno($fp), 1) != 1) {
209662306a36Sopenharmony_ci	    last if (defined($time) && (time - $start_time > $time));
209762306a36Sopenharmony_ci	    next;
209862306a36Sopenharmony_ci	}
209962306a36Sopenharmony_ci
210062306a36Sopenharmony_ci	$line = "";
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_ci	# try to read one char at a time
210362306a36Sopenharmony_ci	while (sysread $fp, $ch, 1) {
210462306a36Sopenharmony_ci	    $line .= $ch;
210562306a36Sopenharmony_ci	    last if ($ch eq "\n");
210662306a36Sopenharmony_ci	}
210762306a36Sopenharmony_ci
210862306a36Sopenharmony_ci	last if (!length($line));
210962306a36Sopenharmony_ci
211062306a36Sopenharmony_ci	return $line;
211162306a36Sopenharmony_ci    }
211262306a36Sopenharmony_ci    return undef;
211362306a36Sopenharmony_ci}
211462306a36Sopenharmony_ci
211562306a36Sopenharmony_cisub reboot_to {
211662306a36Sopenharmony_ci    if (defined($switch_to_test)) {
211762306a36Sopenharmony_ci	run_command $switch_to_test;
211862306a36Sopenharmony_ci    }
211962306a36Sopenharmony_ci
212062306a36Sopenharmony_ci    if ($reboot_type eq "grub") {
212162306a36Sopenharmony_ci	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
212262306a36Sopenharmony_ci    } elsif (($reboot_type eq "grub2") or ($reboot_type eq "grub2bls")) {
212362306a36Sopenharmony_ci	run_ssh "$grub_reboot \"'$grub_number'\"";
212462306a36Sopenharmony_ci    } elsif ($reboot_type eq "syslinux") {
212562306a36Sopenharmony_ci	run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path";
212662306a36Sopenharmony_ci    } elsif (defined $reboot_script) {
212762306a36Sopenharmony_ci	run_command "$reboot_script";
212862306a36Sopenharmony_ci    }
212962306a36Sopenharmony_ci    reboot;
213062306a36Sopenharmony_ci}
213162306a36Sopenharmony_ci
213262306a36Sopenharmony_cisub get_sha1 {
213362306a36Sopenharmony_ci    my ($commit) = @_;
213462306a36Sopenharmony_ci
213562306a36Sopenharmony_ci    doprint "git rev-list --max-count=1 $commit ... ";
213662306a36Sopenharmony_ci    my $sha1 = `git rev-list --max-count=1 $commit`;
213762306a36Sopenharmony_ci    my $ret = $?;
213862306a36Sopenharmony_ci
213962306a36Sopenharmony_ci    logit $sha1;
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci    if ($ret) {
214262306a36Sopenharmony_ci	doprint "FAILED\n";
214362306a36Sopenharmony_ci	dodie "Failed to get git $commit";
214462306a36Sopenharmony_ci    }
214562306a36Sopenharmony_ci
214662306a36Sopenharmony_ci    print "SUCCESS\n";
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_ci    chomp $sha1;
214962306a36Sopenharmony_ci
215062306a36Sopenharmony_ci    return $sha1;
215162306a36Sopenharmony_ci}
215262306a36Sopenharmony_ci
215362306a36Sopenharmony_cisub monitor {
215462306a36Sopenharmony_ci    my $booted = 0;
215562306a36Sopenharmony_ci    my $bug = 0;
215662306a36Sopenharmony_ci    my $bug_ignored = 0;
215762306a36Sopenharmony_ci    my $skip_call_trace = 0;
215862306a36Sopenharmony_ci    my $loops;
215962306a36Sopenharmony_ci
216062306a36Sopenharmony_ci    my $start_time = time;
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_ci    wait_for_monitor 5;
216362306a36Sopenharmony_ci
216462306a36Sopenharmony_ci    my $line;
216562306a36Sopenharmony_ci    my $full_line = "";
216662306a36Sopenharmony_ci
216762306a36Sopenharmony_ci    open(DMESG, "> $dmesg") or
216862306a36Sopenharmony_ci	dodie "unable to write to $dmesg";
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_ci    reboot_to;
217162306a36Sopenharmony_ci
217262306a36Sopenharmony_ci    my $success_start;
217362306a36Sopenharmony_ci    my $failure_start;
217462306a36Sopenharmony_ci    my $monitor_start = time;
217562306a36Sopenharmony_ci    my $done = 0;
217662306a36Sopenharmony_ci    my $version_found = 0;
217762306a36Sopenharmony_ci
217862306a36Sopenharmony_ci    while (!$done) {
217962306a36Sopenharmony_ci	if ($bug && defined($stop_after_failure) &&
218062306a36Sopenharmony_ci	    $stop_after_failure >= 0) {
218162306a36Sopenharmony_ci	    my $time = $stop_after_failure - (time - $failure_start);
218262306a36Sopenharmony_ci	    $line = wait_for_input($monitor_fp, $time);
218362306a36Sopenharmony_ci	    if (!defined($line)) {
218462306a36Sopenharmony_ci		doprint "bug timed out after $booted_timeout seconds\n";
218562306a36Sopenharmony_ci		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
218662306a36Sopenharmony_ci		last;
218762306a36Sopenharmony_ci	    }
218862306a36Sopenharmony_ci	} elsif ($booted) {
218962306a36Sopenharmony_ci	    $line = wait_for_input($monitor_fp, $booted_timeout);
219062306a36Sopenharmony_ci	    if (!defined($line)) {
219162306a36Sopenharmony_ci		my $s = $booted_timeout == 1 ? "" : "s";
219262306a36Sopenharmony_ci		doprint "Successful boot found: break after $booted_timeout second$s\n";
219362306a36Sopenharmony_ci		last;
219462306a36Sopenharmony_ci	    }
219562306a36Sopenharmony_ci	} else {
219662306a36Sopenharmony_ci	    $line = wait_for_input($monitor_fp);
219762306a36Sopenharmony_ci	    if (!defined($line)) {
219862306a36Sopenharmony_ci		my $s = $timeout == 1 ? "" : "s";
219962306a36Sopenharmony_ci		doprint "Timed out after $timeout second$s\n";
220062306a36Sopenharmony_ci		last;
220162306a36Sopenharmony_ci	    }
220262306a36Sopenharmony_ci	}
220362306a36Sopenharmony_ci
220462306a36Sopenharmony_ci	doprint $line;
220562306a36Sopenharmony_ci	print DMESG $line;
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci	# we are not guaranteed to get a full line
220862306a36Sopenharmony_ci	$full_line .= $line;
220962306a36Sopenharmony_ci
221062306a36Sopenharmony_ci	if ($full_line =~ /$success_line/) {
221162306a36Sopenharmony_ci	    $booted = 1;
221262306a36Sopenharmony_ci	    $success_start = time;
221362306a36Sopenharmony_ci	}
221462306a36Sopenharmony_ci
221562306a36Sopenharmony_ci	if ($booted && defined($stop_after_success) &&
221662306a36Sopenharmony_ci	    $stop_after_success >= 0) {
221762306a36Sopenharmony_ci	    my $now = time;
221862306a36Sopenharmony_ci	    if ($now - $success_start >= $stop_after_success) {
221962306a36Sopenharmony_ci		doprint "Test forced to stop after $stop_after_success seconds after success\n";
222062306a36Sopenharmony_ci		last;
222162306a36Sopenharmony_ci	    }
222262306a36Sopenharmony_ci	}
222362306a36Sopenharmony_ci
222462306a36Sopenharmony_ci	if ($full_line =~ /\[ backtrace testing \]/) {
222562306a36Sopenharmony_ci	    $skip_call_trace = 1;
222662306a36Sopenharmony_ci	}
222762306a36Sopenharmony_ci
222862306a36Sopenharmony_ci	if ($full_line =~ /call trace:/i) {
222962306a36Sopenharmony_ci	    if (!$bug && !$skip_call_trace) {
223062306a36Sopenharmony_ci		if ($ignore_errors) {
223162306a36Sopenharmony_ci		    $bug_ignored = 1;
223262306a36Sopenharmony_ci		} else {
223362306a36Sopenharmony_ci		    $bug = 1;
223462306a36Sopenharmony_ci		    $failure_start = time;
223562306a36Sopenharmony_ci		}
223662306a36Sopenharmony_ci	    }
223762306a36Sopenharmony_ci	}
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_ci	if ($bug && defined($stop_after_failure) &&
224062306a36Sopenharmony_ci	    $stop_after_failure >= 0) {
224162306a36Sopenharmony_ci	    my $now = time;
224262306a36Sopenharmony_ci	    if ($now - $failure_start >= $stop_after_failure) {
224362306a36Sopenharmony_ci		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
224462306a36Sopenharmony_ci		last;
224562306a36Sopenharmony_ci	    }
224662306a36Sopenharmony_ci	}
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci	if ($full_line =~ /\[ end of backtrace testing \]/) {
224962306a36Sopenharmony_ci	    $skip_call_trace = 0;
225062306a36Sopenharmony_ci	}
225162306a36Sopenharmony_ci
225262306a36Sopenharmony_ci	if ($full_line =~ /Kernel panic -/) {
225362306a36Sopenharmony_ci	    $failure_start = time;
225462306a36Sopenharmony_ci	    $bug = 1;
225562306a36Sopenharmony_ci	}
225662306a36Sopenharmony_ci
225762306a36Sopenharmony_ci	# Detect triple faults by testing the banner
225862306a36Sopenharmony_ci	if ($full_line =~ /\bLinux version (\S+).*\n/) {
225962306a36Sopenharmony_ci	    if ($1 eq $version) {
226062306a36Sopenharmony_ci		$version_found = 1;
226162306a36Sopenharmony_ci	    } elsif ($version_found && $detect_triplefault) {
226262306a36Sopenharmony_ci		# We already booted into the kernel we are testing,
226362306a36Sopenharmony_ci		# but now we booted into another kernel?
226462306a36Sopenharmony_ci		# Consider this a triple fault.
226562306a36Sopenharmony_ci		doprint "Already booted in Linux kernel $version, but now\n";
226662306a36Sopenharmony_ci		doprint "we booted into Linux kernel $1.\n";
226762306a36Sopenharmony_ci		doprint "Assuming that this is a triple fault.\n";
226862306a36Sopenharmony_ci		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
226962306a36Sopenharmony_ci		last;
227062306a36Sopenharmony_ci	    }
227162306a36Sopenharmony_ci	}
227262306a36Sopenharmony_ci
227362306a36Sopenharmony_ci	if ($line =~ /\n/) {
227462306a36Sopenharmony_ci	    $full_line = "";
227562306a36Sopenharmony_ci	}
227662306a36Sopenharmony_ci
227762306a36Sopenharmony_ci	if ($stop_test_after > 0 && !$booted && !$bug) {
227862306a36Sopenharmony_ci	    if (time - $monitor_start > $stop_test_after) {
227962306a36Sopenharmony_ci		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
228062306a36Sopenharmony_ci		$done = 1;
228162306a36Sopenharmony_ci	    }
228262306a36Sopenharmony_ci	}
228362306a36Sopenharmony_ci    }
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci    my $end_time = time;
228662306a36Sopenharmony_ci    $reboot_time = $end_time - $start_time;
228762306a36Sopenharmony_ci
228862306a36Sopenharmony_ci    close(DMESG);
228962306a36Sopenharmony_ci
229062306a36Sopenharmony_ci    if ($bug) {
229162306a36Sopenharmony_ci	return 0 if ($in_bisect);
229262306a36Sopenharmony_ci	fail "failed - got a bug report" and return 0;
229362306a36Sopenharmony_ci    }
229462306a36Sopenharmony_ci
229562306a36Sopenharmony_ci    if (!$booted) {
229662306a36Sopenharmony_ci	return 0 if ($in_bisect);
229762306a36Sopenharmony_ci	fail "failed - never got a boot prompt." and return 0;
229862306a36Sopenharmony_ci    }
229962306a36Sopenharmony_ci
230062306a36Sopenharmony_ci    if ($bug_ignored) {
230162306a36Sopenharmony_ci	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
230262306a36Sopenharmony_ci    }
230362306a36Sopenharmony_ci
230462306a36Sopenharmony_ci    return 1;
230562306a36Sopenharmony_ci}
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_cisub eval_kernel_version {
230862306a36Sopenharmony_ci    my ($option) = @_;
230962306a36Sopenharmony_ci
231062306a36Sopenharmony_ci    $option =~ s/\$KERNEL_VERSION/$version/g;
231162306a36Sopenharmony_ci
231262306a36Sopenharmony_ci    return $option;
231362306a36Sopenharmony_ci}
231462306a36Sopenharmony_ci
231562306a36Sopenharmony_cisub do_post_install {
231662306a36Sopenharmony_ci
231762306a36Sopenharmony_ci    return if (!defined($post_install));
231862306a36Sopenharmony_ci
231962306a36Sopenharmony_ci    my $cp_post_install = eval_kernel_version $post_install;
232062306a36Sopenharmony_ci    run_command "$cp_post_install" or
232162306a36Sopenharmony_ci	dodie "Failed to run post install";
232262306a36Sopenharmony_ci}
232362306a36Sopenharmony_ci
232462306a36Sopenharmony_ci# Sometimes the reboot fails, and will hang. We try to ssh to the box
232562306a36Sopenharmony_ci# and if we fail, we force another reboot, that should powercycle it.
232662306a36Sopenharmony_cisub test_booted {
232762306a36Sopenharmony_ci    if (!run_ssh "echo testing connection") {
232862306a36Sopenharmony_ci	reboot $sleep_time;
232962306a36Sopenharmony_ci    }
233062306a36Sopenharmony_ci}
233162306a36Sopenharmony_ci
233262306a36Sopenharmony_cisub install {
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci    return if ($no_install);
233562306a36Sopenharmony_ci
233662306a36Sopenharmony_ci    my $start_time = time;
233762306a36Sopenharmony_ci
233862306a36Sopenharmony_ci    if (defined($pre_install)) {
233962306a36Sopenharmony_ci	my $cp_pre_install = eval_kernel_version $pre_install;
234062306a36Sopenharmony_ci	run_command "$cp_pre_install" or
234162306a36Sopenharmony_ci	    dodie "Failed to run pre install";
234262306a36Sopenharmony_ci    }
234362306a36Sopenharmony_ci
234462306a36Sopenharmony_ci    my $cp_target = eval_kernel_version $target_image;
234562306a36Sopenharmony_ci
234662306a36Sopenharmony_ci    test_booted;
234762306a36Sopenharmony_ci
234862306a36Sopenharmony_ci    run_scp_install "$outputdir/$build_target", "$cp_target" or
234962306a36Sopenharmony_ci	dodie "failed to copy image";
235062306a36Sopenharmony_ci
235162306a36Sopenharmony_ci    my $install_mods = 0;
235262306a36Sopenharmony_ci
235362306a36Sopenharmony_ci    # should we process modules?
235462306a36Sopenharmony_ci    $install_mods = 0;
235562306a36Sopenharmony_ci    open(IN, "$output_config") or dodie("Can't read config file");
235662306a36Sopenharmony_ci    while (<IN>) {
235762306a36Sopenharmony_ci	if (/CONFIG_MODULES(=y)?/) {
235862306a36Sopenharmony_ci	    if (defined($1)) {
235962306a36Sopenharmony_ci		$install_mods = 1;
236062306a36Sopenharmony_ci		last;
236162306a36Sopenharmony_ci	    }
236262306a36Sopenharmony_ci	}
236362306a36Sopenharmony_ci    }
236462306a36Sopenharmony_ci    close(IN);
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci    if (!$install_mods) {
236762306a36Sopenharmony_ci	do_post_install;
236862306a36Sopenharmony_ci	doprint "No modules needed\n";
236962306a36Sopenharmony_ci	my $end_time = time;
237062306a36Sopenharmony_ci	$install_time = $end_time - $start_time;
237162306a36Sopenharmony_ci	return;
237262306a36Sopenharmony_ci    }
237362306a36Sopenharmony_ci
237462306a36Sopenharmony_ci    run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or
237562306a36Sopenharmony_ci	dodie "Failed to install modules";
237662306a36Sopenharmony_ci
237762306a36Sopenharmony_ci    my $modlib = "/lib/modules/$version";
237862306a36Sopenharmony_ci    my $modtar = "ktest-mods.tar.bz2";
237962306a36Sopenharmony_ci
238062306a36Sopenharmony_ci    run_ssh "rm -rf $modlib" or
238162306a36Sopenharmony_ci	dodie "failed to remove old mods: $modlib";
238262306a36Sopenharmony_ci
238362306a36Sopenharmony_ci    # would be nice if scp -r did not follow symbolic links
238462306a36Sopenharmony_ci    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
238562306a36Sopenharmony_ci	dodie "making tarball";
238662306a36Sopenharmony_ci
238762306a36Sopenharmony_ci    run_scp_mod "$tmpdir/$modtar", "/tmp" or
238862306a36Sopenharmony_ci	dodie "failed to copy modules";
238962306a36Sopenharmony_ci
239062306a36Sopenharmony_ci    unlink "$tmpdir/$modtar";
239162306a36Sopenharmony_ci
239262306a36Sopenharmony_ci    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
239362306a36Sopenharmony_ci	dodie "failed to tar modules";
239462306a36Sopenharmony_ci
239562306a36Sopenharmony_ci    run_ssh "rm -f /tmp/$modtar";
239662306a36Sopenharmony_ci
239762306a36Sopenharmony_ci    do_post_install;
239862306a36Sopenharmony_ci
239962306a36Sopenharmony_ci    my $end_time = time;
240062306a36Sopenharmony_ci    $install_time = $end_time - $start_time;
240162306a36Sopenharmony_ci}
240262306a36Sopenharmony_ci
240362306a36Sopenharmony_cisub get_version {
240462306a36Sopenharmony_ci    # get the release name
240562306a36Sopenharmony_ci    return if ($have_version);
240662306a36Sopenharmony_ci    doprint "$make kernelrelease ... ";
240762306a36Sopenharmony_ci    $version = `$make -s kernelrelease | tail -1`;
240862306a36Sopenharmony_ci    chomp($version);
240962306a36Sopenharmony_ci    doprint "$version\n";
241062306a36Sopenharmony_ci    $have_version = 1;
241162306a36Sopenharmony_ci}
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_cisub start_monitor_and_install {
241462306a36Sopenharmony_ci    # Make sure the stable kernel has finished booting
241562306a36Sopenharmony_ci
241662306a36Sopenharmony_ci    # Install bisects, don't need console
241762306a36Sopenharmony_ci    if (defined $console) {
241862306a36Sopenharmony_ci	start_monitor;
241962306a36Sopenharmony_ci	wait_for_monitor 5;
242062306a36Sopenharmony_ci	end_monitor;
242162306a36Sopenharmony_ci    }
242262306a36Sopenharmony_ci
242362306a36Sopenharmony_ci    get_grub_index;
242462306a36Sopenharmony_ci    get_version;
242562306a36Sopenharmony_ci    install;
242662306a36Sopenharmony_ci
242762306a36Sopenharmony_ci    start_monitor if (defined $console);
242862306a36Sopenharmony_ci    return monitor;
242962306a36Sopenharmony_ci}
243062306a36Sopenharmony_ci
243162306a36Sopenharmony_cisub process_warning_line {
243262306a36Sopenharmony_ci    my ($line) = @_;
243362306a36Sopenharmony_ci
243462306a36Sopenharmony_ci    chomp $line;
243562306a36Sopenharmony_ci
243662306a36Sopenharmony_ci    # for distcc heterogeneous systems, some compilers
243762306a36Sopenharmony_ci    # do things differently causing warning lines
243862306a36Sopenharmony_ci    # to be slightly different. This makes an attempt
243962306a36Sopenharmony_ci    # to fixe those issues.
244062306a36Sopenharmony_ci
244162306a36Sopenharmony_ci    # chop off the index into the line
244262306a36Sopenharmony_ci    # using distcc, some compilers give different indexes
244362306a36Sopenharmony_ci    # depending on white space
244462306a36Sopenharmony_ci    $line =~ s/^(\s*\S+:\d+:)\d+/$1/;
244562306a36Sopenharmony_ci
244662306a36Sopenharmony_ci    # Some compilers use UTF-8 extended for quotes and some don't.
244762306a36Sopenharmony_ci    $line =~ s/$utf8_quote/'/g;
244862306a36Sopenharmony_ci
244962306a36Sopenharmony_ci    return $line;
245062306a36Sopenharmony_ci}
245162306a36Sopenharmony_ci
245262306a36Sopenharmony_ci# Read buildlog and check against warnings file for any
245362306a36Sopenharmony_ci# new warnings.
245462306a36Sopenharmony_ci#
245562306a36Sopenharmony_ci# Returns 1 if OK
245662306a36Sopenharmony_ci#         0 otherwise
245762306a36Sopenharmony_cisub check_buildlog {
245862306a36Sopenharmony_ci    return 1 if (!defined $warnings_file);
245962306a36Sopenharmony_ci
246062306a36Sopenharmony_ci    my %warnings_list;
246162306a36Sopenharmony_ci
246262306a36Sopenharmony_ci    # Failed builds should not reboot the target
246362306a36Sopenharmony_ci    my $save_no_reboot = $no_reboot;
246462306a36Sopenharmony_ci    $no_reboot = 1;
246562306a36Sopenharmony_ci
246662306a36Sopenharmony_ci    if (-f $warnings_file) {
246762306a36Sopenharmony_ci	open(IN, $warnings_file) or
246862306a36Sopenharmony_ci	    dodie "Error opening $warnings_file";
246962306a36Sopenharmony_ci
247062306a36Sopenharmony_ci	while (<IN>) {
247162306a36Sopenharmony_ci	    if (/$check_build_re/) {
247262306a36Sopenharmony_ci		my $warning = process_warning_line $_;
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_ci		$warnings_list{$warning} = 1;
247562306a36Sopenharmony_ci	    }
247662306a36Sopenharmony_ci	}
247762306a36Sopenharmony_ci	close(IN);
247862306a36Sopenharmony_ci    }
247962306a36Sopenharmony_ci
248062306a36Sopenharmony_ci    # If warnings file didn't exist, and WARNINGS_FILE exist,
248162306a36Sopenharmony_ci    # then we fail on any warning!
248262306a36Sopenharmony_ci
248362306a36Sopenharmony_ci    open(IN, $buildlog) or dodie "Can't open $buildlog";
248462306a36Sopenharmony_ci    while (<IN>) {
248562306a36Sopenharmony_ci	if (/$check_build_re/) {
248662306a36Sopenharmony_ci	    my $warning = process_warning_line $_;
248762306a36Sopenharmony_ci
248862306a36Sopenharmony_ci	    if (!defined $warnings_list{$warning}) {
248962306a36Sopenharmony_ci		fail "New warning found (not in $warnings_file)\n$_\n";
249062306a36Sopenharmony_ci		$no_reboot = $save_no_reboot;
249162306a36Sopenharmony_ci		return 0;
249262306a36Sopenharmony_ci	    }
249362306a36Sopenharmony_ci	}
249462306a36Sopenharmony_ci    }
249562306a36Sopenharmony_ci    $no_reboot = $save_no_reboot;
249662306a36Sopenharmony_ci    close(IN);
249762306a36Sopenharmony_ci}
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_cisub check_patch_buildlog {
250062306a36Sopenharmony_ci    my ($patch) = @_;
250162306a36Sopenharmony_ci
250262306a36Sopenharmony_ci    my @files = `git show $patch | diffstat -l`;
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_ci    foreach my $file (@files) {
250562306a36Sopenharmony_ci	chomp $file;
250662306a36Sopenharmony_ci    }
250762306a36Sopenharmony_ci
250862306a36Sopenharmony_ci    open(IN, "git show $patch |") or
250962306a36Sopenharmony_ci	dodie "failed to show $patch";
251062306a36Sopenharmony_ci    while (<IN>) {
251162306a36Sopenharmony_ci	if (m,^--- a/(.*),) {
251262306a36Sopenharmony_ci	    chomp $1;
251362306a36Sopenharmony_ci	    $files[$#files] = $1;
251462306a36Sopenharmony_ci	}
251562306a36Sopenharmony_ci    }
251662306a36Sopenharmony_ci    close(IN);
251762306a36Sopenharmony_ci
251862306a36Sopenharmony_ci    open(IN, $buildlog) or dodie "Can't open $buildlog";
251962306a36Sopenharmony_ci    while (<IN>) {
252062306a36Sopenharmony_ci	if (/^\s*(.*?):.*(warning|error)/) {
252162306a36Sopenharmony_ci	    my $err = $1;
252262306a36Sopenharmony_ci	    foreach my $file (@files) {
252362306a36Sopenharmony_ci		my $fullpath = "$builddir/$file";
252462306a36Sopenharmony_ci		if ($file eq $err || $fullpath eq $err) {
252562306a36Sopenharmony_ci		    fail "$file built with warnings" and return 0;
252662306a36Sopenharmony_ci		}
252762306a36Sopenharmony_ci	    }
252862306a36Sopenharmony_ci	}
252962306a36Sopenharmony_ci    }
253062306a36Sopenharmony_ci    close(IN);
253162306a36Sopenharmony_ci
253262306a36Sopenharmony_ci    return 1;
253362306a36Sopenharmony_ci}
253462306a36Sopenharmony_ci
253562306a36Sopenharmony_cisub apply_min_config {
253662306a36Sopenharmony_ci    my $outconfig = "$output_config.new";
253762306a36Sopenharmony_ci
253862306a36Sopenharmony_ci    # Read the config file and remove anything that
253962306a36Sopenharmony_ci    # is in the force_config hash (from minconfig and others)
254062306a36Sopenharmony_ci    # then add the force config back.
254162306a36Sopenharmony_ci
254262306a36Sopenharmony_ci    doprint "Applying minimum configurations into $output_config.new\n";
254362306a36Sopenharmony_ci
254462306a36Sopenharmony_ci    open (OUT, ">$outconfig") or
254562306a36Sopenharmony_ci	dodie "Can't create $outconfig";
254662306a36Sopenharmony_ci
254762306a36Sopenharmony_ci    if (-f $output_config) {
254862306a36Sopenharmony_ci	open (IN, $output_config) or
254962306a36Sopenharmony_ci	    dodie "Failed to open $output_config";
255062306a36Sopenharmony_ci	while (<IN>) {
255162306a36Sopenharmony_ci	    if (/^(# )?(CONFIG_[^\s=]*)/) {
255262306a36Sopenharmony_ci		next if (defined($force_config{$2}));
255362306a36Sopenharmony_ci	    }
255462306a36Sopenharmony_ci	    print OUT;
255562306a36Sopenharmony_ci	}
255662306a36Sopenharmony_ci	close IN;
255762306a36Sopenharmony_ci    }
255862306a36Sopenharmony_ci    foreach my $config (keys %force_config) {
255962306a36Sopenharmony_ci	print OUT "$force_config{$config}\n";
256062306a36Sopenharmony_ci    }
256162306a36Sopenharmony_ci    close OUT;
256262306a36Sopenharmony_ci
256362306a36Sopenharmony_ci    run_command "mv $outconfig $output_config";
256462306a36Sopenharmony_ci}
256562306a36Sopenharmony_ci
256662306a36Sopenharmony_cisub make_oldconfig {
256762306a36Sopenharmony_ci
256862306a36Sopenharmony_ci    my @force_list = keys %force_config;
256962306a36Sopenharmony_ci
257062306a36Sopenharmony_ci    if ($#force_list >= 0) {
257162306a36Sopenharmony_ci	apply_min_config;
257262306a36Sopenharmony_ci    }
257362306a36Sopenharmony_ci
257462306a36Sopenharmony_ci    if (!run_command "$make olddefconfig") {
257562306a36Sopenharmony_ci	# Perhaps olddefconfig doesn't exist in this version of the kernel
257662306a36Sopenharmony_ci	# try oldnoconfig
257762306a36Sopenharmony_ci	doprint "olddefconfig failed, trying make oldnoconfig\n";
257862306a36Sopenharmony_ci	if (!run_command "$make oldnoconfig") {
257962306a36Sopenharmony_ci	    doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
258062306a36Sopenharmony_ci	    # try a yes '' | oldconfig
258162306a36Sopenharmony_ci	    run_command "yes '' | $make oldconfig" or
258262306a36Sopenharmony_ci		dodie "failed make config oldconfig";
258362306a36Sopenharmony_ci	}
258462306a36Sopenharmony_ci    }
258562306a36Sopenharmony_ci}
258662306a36Sopenharmony_ci
258762306a36Sopenharmony_ci# read a config file and use this to force new configs.
258862306a36Sopenharmony_cisub load_force_config {
258962306a36Sopenharmony_ci    my ($config) = @_;
259062306a36Sopenharmony_ci
259162306a36Sopenharmony_ci    doprint "Loading force configs from $config\n";
259262306a36Sopenharmony_ci    open(IN, $config) or
259362306a36Sopenharmony_ci	dodie "failed to read $config";
259462306a36Sopenharmony_ci    while (<IN>) {
259562306a36Sopenharmony_ci	chomp;
259662306a36Sopenharmony_ci	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
259762306a36Sopenharmony_ci	    $force_config{$1} = $_;
259862306a36Sopenharmony_ci	} elsif (/^# (CONFIG_\S*) is not set/) {
259962306a36Sopenharmony_ci	    $force_config{$1} = $_;
260062306a36Sopenharmony_ci	}
260162306a36Sopenharmony_ci    }
260262306a36Sopenharmony_ci    close IN;
260362306a36Sopenharmony_ci}
260462306a36Sopenharmony_ci
260562306a36Sopenharmony_cisub build {
260662306a36Sopenharmony_ci    my ($type) = @_;
260762306a36Sopenharmony_ci
260862306a36Sopenharmony_ci    unlink $buildlog;
260962306a36Sopenharmony_ci
261062306a36Sopenharmony_ci    my $start_time = time;
261162306a36Sopenharmony_ci
261262306a36Sopenharmony_ci    # Failed builds should not reboot the target
261362306a36Sopenharmony_ci    my $save_no_reboot = $no_reboot;
261462306a36Sopenharmony_ci    $no_reboot = 1;
261562306a36Sopenharmony_ci
261662306a36Sopenharmony_ci    # Calculate a new version from here.
261762306a36Sopenharmony_ci    $have_version = 0;
261862306a36Sopenharmony_ci
261962306a36Sopenharmony_ci    if (defined($pre_build)) {
262062306a36Sopenharmony_ci	my $ret = run_command $pre_build;
262162306a36Sopenharmony_ci	if (!$ret && defined($pre_build_die) &&
262262306a36Sopenharmony_ci	    $pre_build_die) {
262362306a36Sopenharmony_ci	    dodie "failed to pre_build\n";
262462306a36Sopenharmony_ci	}
262562306a36Sopenharmony_ci    }
262662306a36Sopenharmony_ci
262762306a36Sopenharmony_ci    if ($type =~ /^useconfig:(.*)/) {
262862306a36Sopenharmony_ci	run_command "cp $1 $output_config" or
262962306a36Sopenharmony_ci	    dodie "could not copy $1 to .config";
263062306a36Sopenharmony_ci
263162306a36Sopenharmony_ci	$type = "oldconfig";
263262306a36Sopenharmony_ci    }
263362306a36Sopenharmony_ci
263462306a36Sopenharmony_ci    # old config can ask questions
263562306a36Sopenharmony_ci    if ($type eq "oldconfig") {
263662306a36Sopenharmony_ci	$type = "olddefconfig";
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_ci	# allow for empty configs
263962306a36Sopenharmony_ci	run_command "touch $output_config";
264062306a36Sopenharmony_ci
264162306a36Sopenharmony_ci	if (!$noclean) {
264262306a36Sopenharmony_ci	    run_command "mv $output_config $outputdir/config_temp" or
264362306a36Sopenharmony_ci		dodie "moving .config";
264462306a36Sopenharmony_ci
264562306a36Sopenharmony_ci	    run_command "$make mrproper" or dodie "make mrproper";
264662306a36Sopenharmony_ci
264762306a36Sopenharmony_ci	    run_command "mv $outputdir/config_temp $output_config" or
264862306a36Sopenharmony_ci		dodie "moving config_temp";
264962306a36Sopenharmony_ci	}
265062306a36Sopenharmony_ci    } elsif (!$noclean) {
265162306a36Sopenharmony_ci	unlink "$output_config";
265262306a36Sopenharmony_ci	run_command "$make mrproper" or
265362306a36Sopenharmony_ci	    dodie "make mrproper";
265462306a36Sopenharmony_ci    }
265562306a36Sopenharmony_ci
265662306a36Sopenharmony_ci    # add something to distinguish this build
265762306a36Sopenharmony_ci    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
265862306a36Sopenharmony_ci    print OUT "$localversion\n";
265962306a36Sopenharmony_ci    close(OUT);
266062306a36Sopenharmony_ci
266162306a36Sopenharmony_ci    if (defined($minconfig)) {
266262306a36Sopenharmony_ci	load_force_config($minconfig);
266362306a36Sopenharmony_ci    }
266462306a36Sopenharmony_ci
266562306a36Sopenharmony_ci    if ($type ne "olddefconfig") {
266662306a36Sopenharmony_ci	run_command "$make $type" or
266762306a36Sopenharmony_ci	    dodie "failed make config";
266862306a36Sopenharmony_ci    }
266962306a36Sopenharmony_ci    # Run old config regardless, to enforce min configurations
267062306a36Sopenharmony_ci    make_oldconfig;
267162306a36Sopenharmony_ci
267262306a36Sopenharmony_ci    if (not defined($build_options)){
267362306a36Sopenharmony_ci	$build_options = "";
267462306a36Sopenharmony_ci    }
267562306a36Sopenharmony_ci    my $build_ret = run_command "$make $build_options", $buildlog;
267662306a36Sopenharmony_ci
267762306a36Sopenharmony_ci    if (defined($post_build)) {
267862306a36Sopenharmony_ci	# Because a post build may change the kernel version
267962306a36Sopenharmony_ci	# do it now.
268062306a36Sopenharmony_ci	get_version;
268162306a36Sopenharmony_ci	my $ret = run_command $post_build;
268262306a36Sopenharmony_ci	if (!$ret && defined($post_build_die) &&
268362306a36Sopenharmony_ci	    $post_build_die) {
268462306a36Sopenharmony_ci	    dodie "failed to post_build\n";
268562306a36Sopenharmony_ci	}
268662306a36Sopenharmony_ci    }
268762306a36Sopenharmony_ci
268862306a36Sopenharmony_ci    if (!$build_ret) {
268962306a36Sopenharmony_ci	# bisect may need this to pass
269062306a36Sopenharmony_ci	if ($in_bisect) {
269162306a36Sopenharmony_ci	    $no_reboot = $save_no_reboot;
269262306a36Sopenharmony_ci	    return 0;
269362306a36Sopenharmony_ci	}
269462306a36Sopenharmony_ci	fail "failed build" and return 0;
269562306a36Sopenharmony_ci    }
269662306a36Sopenharmony_ci
269762306a36Sopenharmony_ci    $no_reboot = $save_no_reboot;
269862306a36Sopenharmony_ci
269962306a36Sopenharmony_ci    my $end_time = time;
270062306a36Sopenharmony_ci    $build_time = $end_time - $start_time;
270162306a36Sopenharmony_ci
270262306a36Sopenharmony_ci    return 1;
270362306a36Sopenharmony_ci}
270462306a36Sopenharmony_ci
270562306a36Sopenharmony_cisub halt {
270662306a36Sopenharmony_ci    if (!run_ssh "halt" or defined($power_off)) {
270762306a36Sopenharmony_ci	if (defined($poweroff_after_halt)) {
270862306a36Sopenharmony_ci	    sleep $poweroff_after_halt;
270962306a36Sopenharmony_ci	    run_command "$power_off";
271062306a36Sopenharmony_ci	}
271162306a36Sopenharmony_ci    } else {
271262306a36Sopenharmony_ci	# nope? the zap it!
271362306a36Sopenharmony_ci	run_command "$power_off";
271462306a36Sopenharmony_ci    }
271562306a36Sopenharmony_ci}
271662306a36Sopenharmony_ci
271762306a36Sopenharmony_cisub success {
271862306a36Sopenharmony_ci    my ($i) = @_;
271962306a36Sopenharmony_ci
272062306a36Sopenharmony_ci    $successes++;
272162306a36Sopenharmony_ci
272262306a36Sopenharmony_ci    my $name = "";
272362306a36Sopenharmony_ci
272462306a36Sopenharmony_ci    if (defined($test_name)) {
272562306a36Sopenharmony_ci	$name = " ($test_name)";
272662306a36Sopenharmony_ci    }
272762306a36Sopenharmony_ci
272862306a36Sopenharmony_ci    print_times;
272962306a36Sopenharmony_ci
273062306a36Sopenharmony_ci    doprint "\n\n";
273162306a36Sopenharmony_ci    doprint "*******************************************\n";
273262306a36Sopenharmony_ci    doprint "*******************************************\n";
273362306a36Sopenharmony_ci    doprint "KTEST RESULT: TEST $i$name SUCCESS!!!!   **\n";
273462306a36Sopenharmony_ci    doprint "*******************************************\n";
273562306a36Sopenharmony_ci    doprint "*******************************************\n";
273662306a36Sopenharmony_ci
273762306a36Sopenharmony_ci    if (defined($store_successes)) {
273862306a36Sopenharmony_ci	save_logs "success", $store_successes;
273962306a36Sopenharmony_ci    }
274062306a36Sopenharmony_ci
274162306a36Sopenharmony_ci    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
274262306a36Sopenharmony_ci	doprint "Reboot and wait $sleep_time seconds\n";
274362306a36Sopenharmony_ci	reboot_to_good $sleep_time;
274462306a36Sopenharmony_ci    }
274562306a36Sopenharmony_ci
274662306a36Sopenharmony_ci    if (defined($post_test)) {
274762306a36Sopenharmony_ci	run_command $post_test;
274862306a36Sopenharmony_ci    }
274962306a36Sopenharmony_ci}
275062306a36Sopenharmony_ci
275162306a36Sopenharmony_cisub answer_bisect {
275262306a36Sopenharmony_ci    for (;;) {
275362306a36Sopenharmony_ci	doprint "Pass, fail, or skip? [p/f/s]";
275462306a36Sopenharmony_ci	my $ans = <STDIN>;
275562306a36Sopenharmony_ci	chomp $ans;
275662306a36Sopenharmony_ci	if ($ans eq "p" || $ans eq "P") {
275762306a36Sopenharmony_ci	    return 1;
275862306a36Sopenharmony_ci	} elsif ($ans eq "f" || $ans eq "F") {
275962306a36Sopenharmony_ci	    return 0;
276062306a36Sopenharmony_ci	} elsif ($ans eq "s" || $ans eq "S") {
276162306a36Sopenharmony_ci	    return -1;
276262306a36Sopenharmony_ci	} else {
276362306a36Sopenharmony_ci	    print "Please answer 'p', 'f', or 's'\n";
276462306a36Sopenharmony_ci	}
276562306a36Sopenharmony_ci    }
276662306a36Sopenharmony_ci}
276762306a36Sopenharmony_ci
276862306a36Sopenharmony_cisub child_run_test {
276962306a36Sopenharmony_ci
277062306a36Sopenharmony_ci    # child should have no power
277162306a36Sopenharmony_ci    $reboot_on_error = 0;
277262306a36Sopenharmony_ci    $poweroff_on_error = 0;
277362306a36Sopenharmony_ci    $die_on_failure = 1;
277462306a36Sopenharmony_ci
277562306a36Sopenharmony_ci    run_command $run_test, $testlog;
277662306a36Sopenharmony_ci
277762306a36Sopenharmony_ci    exit $run_command_status;
277862306a36Sopenharmony_ci}
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_cisub child_finished {
278162306a36Sopenharmony_ci    $child_done = 1;
278262306a36Sopenharmony_ci}
278362306a36Sopenharmony_ci
278462306a36Sopenharmony_cisub do_run_test {
278562306a36Sopenharmony_ci    my $child_pid;
278662306a36Sopenharmony_ci    my $child_exit;
278762306a36Sopenharmony_ci    my $line;
278862306a36Sopenharmony_ci    my $full_line;
278962306a36Sopenharmony_ci    my $bug = 0;
279062306a36Sopenharmony_ci    my $bug_ignored = 0;
279162306a36Sopenharmony_ci
279262306a36Sopenharmony_ci    my $start_time = time;
279362306a36Sopenharmony_ci
279462306a36Sopenharmony_ci    wait_for_monitor 1;
279562306a36Sopenharmony_ci
279662306a36Sopenharmony_ci    doprint "run test $run_test\n";
279762306a36Sopenharmony_ci
279862306a36Sopenharmony_ci    $child_done = 0;
279962306a36Sopenharmony_ci
280062306a36Sopenharmony_ci    $SIG{CHLD} = qw(child_finished);
280162306a36Sopenharmony_ci
280262306a36Sopenharmony_ci    $child_pid = fork;
280362306a36Sopenharmony_ci
280462306a36Sopenharmony_ci    child_run_test if (!$child_pid);
280562306a36Sopenharmony_ci
280662306a36Sopenharmony_ci    $full_line = "";
280762306a36Sopenharmony_ci
280862306a36Sopenharmony_ci    do {
280962306a36Sopenharmony_ci	$line = wait_for_input($monitor_fp, 1);
281062306a36Sopenharmony_ci	if (defined($line)) {
281162306a36Sopenharmony_ci
281262306a36Sopenharmony_ci	    # we are not guaranteed to get a full line
281362306a36Sopenharmony_ci	    $full_line .= $line;
281462306a36Sopenharmony_ci	    doprint $line;
281562306a36Sopenharmony_ci
281662306a36Sopenharmony_ci	    if ($full_line =~ /call trace:/i) {
281762306a36Sopenharmony_ci		if ($ignore_errors) {
281862306a36Sopenharmony_ci		    $bug_ignored = 1;
281962306a36Sopenharmony_ci		} else {
282062306a36Sopenharmony_ci		    $bug = 1;
282162306a36Sopenharmony_ci		}
282262306a36Sopenharmony_ci	    }
282362306a36Sopenharmony_ci
282462306a36Sopenharmony_ci	    if ($full_line =~ /Kernel panic -/) {
282562306a36Sopenharmony_ci		$bug = 1;
282662306a36Sopenharmony_ci	    }
282762306a36Sopenharmony_ci
282862306a36Sopenharmony_ci	    if ($line =~ /\n/) {
282962306a36Sopenharmony_ci		$full_line = "";
283062306a36Sopenharmony_ci	    }
283162306a36Sopenharmony_ci	}
283262306a36Sopenharmony_ci    } while (!$child_done && !$bug);
283362306a36Sopenharmony_ci
283462306a36Sopenharmony_ci    if (!$bug && $bug_ignored) {
283562306a36Sopenharmony_ci	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
283662306a36Sopenharmony_ci    }
283762306a36Sopenharmony_ci
283862306a36Sopenharmony_ci    if ($bug) {
283962306a36Sopenharmony_ci	my $failure_start = time;
284062306a36Sopenharmony_ci	my $now;
284162306a36Sopenharmony_ci	do {
284262306a36Sopenharmony_ci	    $line = wait_for_input($monitor_fp, 1);
284362306a36Sopenharmony_ci	    if (defined($line)) {
284462306a36Sopenharmony_ci		doprint $line;
284562306a36Sopenharmony_ci	    }
284662306a36Sopenharmony_ci	    $now = time;
284762306a36Sopenharmony_ci	    if ($now - $failure_start >= $stop_after_failure) {
284862306a36Sopenharmony_ci		last;
284962306a36Sopenharmony_ci	    }
285062306a36Sopenharmony_ci	} while (defined($line));
285162306a36Sopenharmony_ci
285262306a36Sopenharmony_ci	doprint "Detected kernel crash!\n";
285362306a36Sopenharmony_ci	# kill the child with extreme prejudice
285462306a36Sopenharmony_ci	kill 9, $child_pid;
285562306a36Sopenharmony_ci    }
285662306a36Sopenharmony_ci
285762306a36Sopenharmony_ci    waitpid $child_pid, 0;
285862306a36Sopenharmony_ci    $child_exit = $? >> 8;
285962306a36Sopenharmony_ci
286062306a36Sopenharmony_ci    my $end_time = time;
286162306a36Sopenharmony_ci    $test_time = $end_time - $start_time;
286262306a36Sopenharmony_ci
286362306a36Sopenharmony_ci    if (!$bug && $in_bisect) {
286462306a36Sopenharmony_ci	if (defined($bisect_ret_good)) {
286562306a36Sopenharmony_ci	    if ($child_exit == $bisect_ret_good) {
286662306a36Sopenharmony_ci		return 1;
286762306a36Sopenharmony_ci	    }
286862306a36Sopenharmony_ci	}
286962306a36Sopenharmony_ci	if (defined($bisect_ret_skip)) {
287062306a36Sopenharmony_ci	    if ($child_exit == $bisect_ret_skip) {
287162306a36Sopenharmony_ci		return -1;
287262306a36Sopenharmony_ci	    }
287362306a36Sopenharmony_ci	}
287462306a36Sopenharmony_ci	if (defined($bisect_ret_abort)) {
287562306a36Sopenharmony_ci	    if ($child_exit == $bisect_ret_abort) {
287662306a36Sopenharmony_ci		fail "test abort" and return -2;
287762306a36Sopenharmony_ci	    }
287862306a36Sopenharmony_ci	}
287962306a36Sopenharmony_ci	if (defined($bisect_ret_bad)) {
288062306a36Sopenharmony_ci	    if ($child_exit == $bisect_ret_skip) {
288162306a36Sopenharmony_ci		return 0;
288262306a36Sopenharmony_ci	    }
288362306a36Sopenharmony_ci	}
288462306a36Sopenharmony_ci	if (defined($bisect_ret_default)) {
288562306a36Sopenharmony_ci	    if ($bisect_ret_default eq "good") {
288662306a36Sopenharmony_ci		return 1;
288762306a36Sopenharmony_ci	    } elsif ($bisect_ret_default eq "bad") {
288862306a36Sopenharmony_ci		return 0;
288962306a36Sopenharmony_ci	    } elsif ($bisect_ret_default eq "skip") {
289062306a36Sopenharmony_ci		return -1;
289162306a36Sopenharmony_ci	    } elsif ($bisect_ret_default eq "abort") {
289262306a36Sopenharmony_ci		return -2;
289362306a36Sopenharmony_ci	    } else {
289462306a36Sopenharmony_ci		fail "unknown default action: $bisect_ret_default"
289562306a36Sopenharmony_ci		    and return -2;
289662306a36Sopenharmony_ci	    }
289762306a36Sopenharmony_ci	}
289862306a36Sopenharmony_ci    }
289962306a36Sopenharmony_ci
290062306a36Sopenharmony_ci    if ($bug || $child_exit) {
290162306a36Sopenharmony_ci	return 0 if $in_bisect;
290262306a36Sopenharmony_ci	fail "test failed" and return 0;
290362306a36Sopenharmony_ci    }
290462306a36Sopenharmony_ci    return 1;
290562306a36Sopenharmony_ci}
290662306a36Sopenharmony_ci
290762306a36Sopenharmony_cisub run_git_bisect {
290862306a36Sopenharmony_ci    my ($command) = @_;
290962306a36Sopenharmony_ci
291062306a36Sopenharmony_ci    doprint "$command ... ";
291162306a36Sopenharmony_ci
291262306a36Sopenharmony_ci    my $output = `$command 2>&1`;
291362306a36Sopenharmony_ci    my $ret = $?;
291462306a36Sopenharmony_ci
291562306a36Sopenharmony_ci    logit $output;
291662306a36Sopenharmony_ci
291762306a36Sopenharmony_ci    if ($ret) {
291862306a36Sopenharmony_ci	doprint "FAILED\n";
291962306a36Sopenharmony_ci	dodie "Failed to git bisect";
292062306a36Sopenharmony_ci    }
292162306a36Sopenharmony_ci
292262306a36Sopenharmony_ci    doprint "SUCCESS\n";
292362306a36Sopenharmony_ci    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
292462306a36Sopenharmony_ci	doprint "$1 [$2]\n";
292562306a36Sopenharmony_ci    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
292662306a36Sopenharmony_ci	$bisect_bad_commit = $1;
292762306a36Sopenharmony_ci	doprint "Found bad commit... $1\n";
292862306a36Sopenharmony_ci	return 0;
292962306a36Sopenharmony_ci    } else {
293062306a36Sopenharmony_ci	# we already logged it, just print it now.
293162306a36Sopenharmony_ci	print $output;
293262306a36Sopenharmony_ci    }
293362306a36Sopenharmony_ci
293462306a36Sopenharmony_ci    return 1;
293562306a36Sopenharmony_ci}
293662306a36Sopenharmony_ci
293762306a36Sopenharmony_cisub bisect_reboot {
293862306a36Sopenharmony_ci    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
293962306a36Sopenharmony_ci    reboot_to_good $bisect_sleep_time;
294062306a36Sopenharmony_ci}
294162306a36Sopenharmony_ci
294262306a36Sopenharmony_ci# returns 1 on success, 0 on failure, -1 on skip
294362306a36Sopenharmony_cisub run_bisect_test {
294462306a36Sopenharmony_ci    my ($type, $buildtype) = @_;
294562306a36Sopenharmony_ci
294662306a36Sopenharmony_ci    my $failed = 0;
294762306a36Sopenharmony_ci    my $result;
294862306a36Sopenharmony_ci    my $output;
294962306a36Sopenharmony_ci    my $ret;
295062306a36Sopenharmony_ci
295162306a36Sopenharmony_ci    $in_bisect = 1;
295262306a36Sopenharmony_ci
295362306a36Sopenharmony_ci    build $buildtype or $failed = 1;
295462306a36Sopenharmony_ci
295562306a36Sopenharmony_ci    if ($type ne "build") {
295662306a36Sopenharmony_ci	if ($failed && $bisect_skip) {
295762306a36Sopenharmony_ci	    $in_bisect = 0;
295862306a36Sopenharmony_ci	    return -1;
295962306a36Sopenharmony_ci	}
296062306a36Sopenharmony_ci	dodie "Failed on build" if $failed;
296162306a36Sopenharmony_ci
296262306a36Sopenharmony_ci	# Now boot the box
296362306a36Sopenharmony_ci	start_monitor_and_install or $failed = 1;
296462306a36Sopenharmony_ci
296562306a36Sopenharmony_ci	if ($type ne "boot") {
296662306a36Sopenharmony_ci	    if ($failed && $bisect_skip) {
296762306a36Sopenharmony_ci		end_monitor;
296862306a36Sopenharmony_ci		bisect_reboot;
296962306a36Sopenharmony_ci		$in_bisect = 0;
297062306a36Sopenharmony_ci		return -1;
297162306a36Sopenharmony_ci	    }
297262306a36Sopenharmony_ci	    dodie "Failed on boot" if $failed;
297362306a36Sopenharmony_ci
297462306a36Sopenharmony_ci	    do_run_test or $failed = 1;
297562306a36Sopenharmony_ci	}
297662306a36Sopenharmony_ci	end_monitor;
297762306a36Sopenharmony_ci    }
297862306a36Sopenharmony_ci
297962306a36Sopenharmony_ci    if ($failed) {
298062306a36Sopenharmony_ci	$result = 0;
298162306a36Sopenharmony_ci    } else {
298262306a36Sopenharmony_ci	$result = 1;
298362306a36Sopenharmony_ci    }
298462306a36Sopenharmony_ci
298562306a36Sopenharmony_ci    # reboot the box to a kernel we can ssh to
298662306a36Sopenharmony_ci    if ($type ne "build") {
298762306a36Sopenharmony_ci	bisect_reboot;
298862306a36Sopenharmony_ci    }
298962306a36Sopenharmony_ci    $in_bisect = 0;
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_ci    return $result;
299262306a36Sopenharmony_ci}
299362306a36Sopenharmony_ci
299462306a36Sopenharmony_cisub run_bisect {
299562306a36Sopenharmony_ci    my ($type) = @_;
299662306a36Sopenharmony_ci    my $buildtype = "oldconfig";
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci    # We should have a minconfig to use?
299962306a36Sopenharmony_ci    if (defined($minconfig)) {
300062306a36Sopenharmony_ci	$buildtype = "useconfig:$minconfig";
300162306a36Sopenharmony_ci    }
300262306a36Sopenharmony_ci
300362306a36Sopenharmony_ci    # If the user sets bisect_tries to less than 1, then no tries
300462306a36Sopenharmony_ci    # is a success.
300562306a36Sopenharmony_ci    my $ret = 1;
300662306a36Sopenharmony_ci
300762306a36Sopenharmony_ci    # Still let the user manually decide that though.
300862306a36Sopenharmony_ci    if ($bisect_tries < 1 && $bisect_manual) {
300962306a36Sopenharmony_ci	$ret = answer_bisect;
301062306a36Sopenharmony_ci    }
301162306a36Sopenharmony_ci
301262306a36Sopenharmony_ci    for (my $i = 0; $i < $bisect_tries; $i++) {
301362306a36Sopenharmony_ci	if ($bisect_tries > 1) {
301462306a36Sopenharmony_ci	    my $t = $i + 1;
301562306a36Sopenharmony_ci	    doprint("Running bisect trial $t of $bisect_tries:\n");
301662306a36Sopenharmony_ci	}
301762306a36Sopenharmony_ci	$ret = run_bisect_test $type, $buildtype;
301862306a36Sopenharmony_ci
301962306a36Sopenharmony_ci	if ($bisect_manual) {
302062306a36Sopenharmony_ci	    $ret = answer_bisect;
302162306a36Sopenharmony_ci	}
302262306a36Sopenharmony_ci
302362306a36Sopenharmony_ci	last if (!$ret);
302462306a36Sopenharmony_ci    }
302562306a36Sopenharmony_ci
302662306a36Sopenharmony_ci    # Are we looking for where it worked, not failed?
302762306a36Sopenharmony_ci    if ($reverse_bisect && $ret >= 0) {
302862306a36Sopenharmony_ci	$ret = !$ret;
302962306a36Sopenharmony_ci    }
303062306a36Sopenharmony_ci
303162306a36Sopenharmony_ci    if ($ret > 0) {
303262306a36Sopenharmony_ci	return "good";
303362306a36Sopenharmony_ci    } elsif ($ret == 0) {
303462306a36Sopenharmony_ci	return  "bad";
303562306a36Sopenharmony_ci    } elsif ($bisect_skip) {
303662306a36Sopenharmony_ci	doprint "HIT A BAD COMMIT ... SKIPPING\n";
303762306a36Sopenharmony_ci	return "skip";
303862306a36Sopenharmony_ci    }
303962306a36Sopenharmony_ci}
304062306a36Sopenharmony_ci
304162306a36Sopenharmony_cisub update_bisect_replay {
304262306a36Sopenharmony_ci    my $tmp_log = "$tmpdir/ktest_bisect_log";
304362306a36Sopenharmony_ci    run_command "git bisect log > $tmp_log" or
304462306a36Sopenharmony_ci	dodie "can't create bisect log";
304562306a36Sopenharmony_ci    return $tmp_log;
304662306a36Sopenharmony_ci}
304762306a36Sopenharmony_ci
304862306a36Sopenharmony_cisub bisect {
304962306a36Sopenharmony_ci    my ($i) = @_;
305062306a36Sopenharmony_ci
305162306a36Sopenharmony_ci    my $result;
305262306a36Sopenharmony_ci
305362306a36Sopenharmony_ci    dodie "BISECT_GOOD[$i] not defined\n"	if (!defined($bisect_good));
305462306a36Sopenharmony_ci    dodie "BISECT_BAD[$i] not defined\n"	if (!defined($bisect_bad));
305562306a36Sopenharmony_ci    dodie "BISECT_TYPE[$i] not defined\n"	if (!defined($bisect_type));
305662306a36Sopenharmony_ci
305762306a36Sopenharmony_ci    my $good = $bisect_good;
305862306a36Sopenharmony_ci    my $bad = $bisect_bad;
305962306a36Sopenharmony_ci    my $type = $bisect_type;
306062306a36Sopenharmony_ci    my $start = $bisect_start;
306162306a36Sopenharmony_ci    my $replay = $bisect_replay;
306262306a36Sopenharmony_ci    my $start_files = $bisect_files;
306362306a36Sopenharmony_ci
306462306a36Sopenharmony_ci    if (defined($start_files)) {
306562306a36Sopenharmony_ci	$start_files = " -- " . $start_files;
306662306a36Sopenharmony_ci    } else {
306762306a36Sopenharmony_ci	$start_files = "";
306862306a36Sopenharmony_ci    }
306962306a36Sopenharmony_ci
307062306a36Sopenharmony_ci    # convert to true sha1's
307162306a36Sopenharmony_ci    $good = get_sha1($good);
307262306a36Sopenharmony_ci    $bad = get_sha1($bad);
307362306a36Sopenharmony_ci
307462306a36Sopenharmony_ci    if (defined($bisect_reverse) && $bisect_reverse == 1) {
307562306a36Sopenharmony_ci	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
307662306a36Sopenharmony_ci	$reverse_bisect = 1;
307762306a36Sopenharmony_ci    } else {
307862306a36Sopenharmony_ci	$reverse_bisect = 0;
307962306a36Sopenharmony_ci    }
308062306a36Sopenharmony_ci
308162306a36Sopenharmony_ci    # Can't have a test without having a test to run
308262306a36Sopenharmony_ci    if ($type eq "test" && !defined($run_test)) {
308362306a36Sopenharmony_ci	$type = "boot";
308462306a36Sopenharmony_ci    }
308562306a36Sopenharmony_ci
308662306a36Sopenharmony_ci    # Check if a bisect was running
308762306a36Sopenharmony_ci    my $bisect_start_file = "$builddir/.git/BISECT_START";
308862306a36Sopenharmony_ci
308962306a36Sopenharmony_ci    my $check = $bisect_check;
309062306a36Sopenharmony_ci    my $do_check = defined($check) && $check ne "0";
309162306a36Sopenharmony_ci
309262306a36Sopenharmony_ci    if ( -f $bisect_start_file ) {
309362306a36Sopenharmony_ci	print "Bisect in progress found\n";
309462306a36Sopenharmony_ci	if ($do_check) {
309562306a36Sopenharmony_ci	    print " If you say yes, then no checks of good or bad will be done\n";
309662306a36Sopenharmony_ci	}
309762306a36Sopenharmony_ci	if (defined($replay)) {
309862306a36Sopenharmony_ci	    print "** BISECT_REPLAY is defined in config file **";
309962306a36Sopenharmony_ci	    print " Ignore config option and perform new git bisect log?\n";
310062306a36Sopenharmony_ci	    if (read_ync " (yes, no, or cancel) ") {
310162306a36Sopenharmony_ci		$replay = update_bisect_replay;
310262306a36Sopenharmony_ci		$do_check = 0;
310362306a36Sopenharmony_ci	    }
310462306a36Sopenharmony_ci	} elsif (read_yn "read git log and continue?") {
310562306a36Sopenharmony_ci	    $replay = update_bisect_replay;
310662306a36Sopenharmony_ci	    $do_check = 0;
310762306a36Sopenharmony_ci	}
310862306a36Sopenharmony_ci    }
310962306a36Sopenharmony_ci
311062306a36Sopenharmony_ci    if ($do_check) {
311162306a36Sopenharmony_ci	# get current HEAD
311262306a36Sopenharmony_ci	my $head = get_sha1("HEAD");
311362306a36Sopenharmony_ci
311462306a36Sopenharmony_ci	if ($check ne "good") {
311562306a36Sopenharmony_ci	    doprint "TESTING BISECT BAD [$bad]\n";
311662306a36Sopenharmony_ci	    run_command "git checkout $bad" or
311762306a36Sopenharmony_ci		dodie "Failed to checkout $bad";
311862306a36Sopenharmony_ci
311962306a36Sopenharmony_ci	    $result = run_bisect $type;
312062306a36Sopenharmony_ci
312162306a36Sopenharmony_ci	    if ($result ne "bad") {
312262306a36Sopenharmony_ci		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
312362306a36Sopenharmony_ci	    }
312462306a36Sopenharmony_ci	}
312562306a36Sopenharmony_ci
312662306a36Sopenharmony_ci	if ($check ne "bad") {
312762306a36Sopenharmony_ci	    doprint "TESTING BISECT GOOD [$good]\n";
312862306a36Sopenharmony_ci	    run_command "git checkout $good" or
312962306a36Sopenharmony_ci		dodie "Failed to checkout $good";
313062306a36Sopenharmony_ci
313162306a36Sopenharmony_ci	    $result = run_bisect $type;
313262306a36Sopenharmony_ci
313362306a36Sopenharmony_ci	    if ($result ne "good") {
313462306a36Sopenharmony_ci		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
313562306a36Sopenharmony_ci	    }
313662306a36Sopenharmony_ci	}
313762306a36Sopenharmony_ci
313862306a36Sopenharmony_ci	# checkout where we started
313962306a36Sopenharmony_ci	run_command "git checkout $head" or
314062306a36Sopenharmony_ci	    dodie "Failed to checkout $head";
314162306a36Sopenharmony_ci    }
314262306a36Sopenharmony_ci
314362306a36Sopenharmony_ci    run_command "git bisect start$start_files" or
314462306a36Sopenharmony_ci	dodie "could not start bisect";
314562306a36Sopenharmony_ci
314662306a36Sopenharmony_ci    if (defined($replay)) {
314762306a36Sopenharmony_ci	run_command "git bisect replay $replay" or
314862306a36Sopenharmony_ci	    dodie "failed to run replay";
314962306a36Sopenharmony_ci    } else {
315062306a36Sopenharmony_ci	run_command "git bisect good $good" or
315162306a36Sopenharmony_ci	    dodie "could not set bisect good to $good";
315262306a36Sopenharmony_ci
315362306a36Sopenharmony_ci	run_git_bisect "git bisect bad $bad" or
315462306a36Sopenharmony_ci	    dodie "could not set bisect bad to $bad";
315562306a36Sopenharmony_ci    }
315662306a36Sopenharmony_ci
315762306a36Sopenharmony_ci    if (defined($start)) {
315862306a36Sopenharmony_ci	run_command "git checkout $start" or
315962306a36Sopenharmony_ci	    dodie "failed to checkout $start";
316062306a36Sopenharmony_ci    }
316162306a36Sopenharmony_ci
316262306a36Sopenharmony_ci    my $test;
316362306a36Sopenharmony_ci    do {
316462306a36Sopenharmony_ci	$result = run_bisect $type;
316562306a36Sopenharmony_ci	$test = run_git_bisect "git bisect $result";
316662306a36Sopenharmony_ci	print_times;
316762306a36Sopenharmony_ci    } while ($test);
316862306a36Sopenharmony_ci
316962306a36Sopenharmony_ci    run_command "git bisect log" or
317062306a36Sopenharmony_ci	dodie "could not capture git bisect log";
317162306a36Sopenharmony_ci
317262306a36Sopenharmony_ci    run_command "git bisect reset" or
317362306a36Sopenharmony_ci	dodie "could not reset git bisect";
317462306a36Sopenharmony_ci
317562306a36Sopenharmony_ci    doprint "Bad commit was [$bisect_bad_commit]\n";
317662306a36Sopenharmony_ci
317762306a36Sopenharmony_ci    success $i;
317862306a36Sopenharmony_ci}
317962306a36Sopenharmony_ci
318062306a36Sopenharmony_cisub assign_configs {
318162306a36Sopenharmony_ci    my ($hash, $config) = @_;
318262306a36Sopenharmony_ci
318362306a36Sopenharmony_ci    doprint "Reading configs from $config\n";
318462306a36Sopenharmony_ci
318562306a36Sopenharmony_ci    open (IN, $config) or
318662306a36Sopenharmony_ci	dodie "Failed to read $config";
318762306a36Sopenharmony_ci
318862306a36Sopenharmony_ci    while (<IN>) {
318962306a36Sopenharmony_ci	chomp;
319062306a36Sopenharmony_ci	if (/^((CONFIG\S*)=.*)/) {
319162306a36Sopenharmony_ci	    ${$hash}{$2} = $1;
319262306a36Sopenharmony_ci	} elsif (/^(# (CONFIG\S*) is not set)/) {
319362306a36Sopenharmony_ci	    ${$hash}{$2} = $1;
319462306a36Sopenharmony_ci	}
319562306a36Sopenharmony_ci    }
319662306a36Sopenharmony_ci
319762306a36Sopenharmony_ci    close(IN);
319862306a36Sopenharmony_ci}
319962306a36Sopenharmony_ci
320062306a36Sopenharmony_cisub process_config_ignore {
320162306a36Sopenharmony_ci    my ($config) = @_;
320262306a36Sopenharmony_ci
320362306a36Sopenharmony_ci    assign_configs \%config_ignore, $config;
320462306a36Sopenharmony_ci}
320562306a36Sopenharmony_ci
320662306a36Sopenharmony_cisub get_dependencies {
320762306a36Sopenharmony_ci    my ($config) = @_;
320862306a36Sopenharmony_ci
320962306a36Sopenharmony_ci    my $arr = $dependency{$config};
321062306a36Sopenharmony_ci    if (!defined($arr)) {
321162306a36Sopenharmony_ci	return ();
321262306a36Sopenharmony_ci    }
321362306a36Sopenharmony_ci
321462306a36Sopenharmony_ci    my @deps = @{$arr};
321562306a36Sopenharmony_ci
321662306a36Sopenharmony_ci    foreach my $dep (@{$arr}) {
321762306a36Sopenharmony_ci	print "ADD DEP $dep\n";
321862306a36Sopenharmony_ci	@deps = (@deps, get_dependencies $dep);
321962306a36Sopenharmony_ci    }
322062306a36Sopenharmony_ci
322162306a36Sopenharmony_ci    return @deps;
322262306a36Sopenharmony_ci}
322362306a36Sopenharmony_ci
322462306a36Sopenharmony_cisub save_config {
322562306a36Sopenharmony_ci    my ($pc, $file) = @_;
322662306a36Sopenharmony_ci
322762306a36Sopenharmony_ci    my %configs = %{$pc};
322862306a36Sopenharmony_ci
322962306a36Sopenharmony_ci    doprint "Saving configs into $file\n";
323062306a36Sopenharmony_ci
323162306a36Sopenharmony_ci    open(OUT, ">$file") or dodie "Can not write to $file";
323262306a36Sopenharmony_ci
323362306a36Sopenharmony_ci    foreach my $config (keys %configs) {
323462306a36Sopenharmony_ci	print OUT "$configs{$config}\n";
323562306a36Sopenharmony_ci    }
323662306a36Sopenharmony_ci    close(OUT);
323762306a36Sopenharmony_ci}
323862306a36Sopenharmony_ci
323962306a36Sopenharmony_cisub create_config {
324062306a36Sopenharmony_ci    my ($name, $pc) = @_;
324162306a36Sopenharmony_ci
324262306a36Sopenharmony_ci    doprint "Creating old config from $name configs\n";
324362306a36Sopenharmony_ci
324462306a36Sopenharmony_ci    save_config $pc, $output_config;
324562306a36Sopenharmony_ci
324662306a36Sopenharmony_ci    make_oldconfig;
324762306a36Sopenharmony_ci}
324862306a36Sopenharmony_ci
324962306a36Sopenharmony_cisub run_config_bisect_test {
325062306a36Sopenharmony_ci    my ($type) = @_;
325162306a36Sopenharmony_ci
325262306a36Sopenharmony_ci    my $ret = run_bisect_test $type, "oldconfig";
325362306a36Sopenharmony_ci
325462306a36Sopenharmony_ci    if ($bisect_manual) {
325562306a36Sopenharmony_ci	$ret = answer_bisect;
325662306a36Sopenharmony_ci    }
325762306a36Sopenharmony_ci
325862306a36Sopenharmony_ci    return $ret;
325962306a36Sopenharmony_ci}
326062306a36Sopenharmony_ci
326162306a36Sopenharmony_cisub config_bisect_end {
326262306a36Sopenharmony_ci    my ($good, $bad) = @_;
326362306a36Sopenharmony_ci    my $diffexec = "diff -u";
326462306a36Sopenharmony_ci
326562306a36Sopenharmony_ci    if (-f "$builddir/scripts/diffconfig") {
326662306a36Sopenharmony_ci	$diffexec = "$builddir/scripts/diffconfig";
326762306a36Sopenharmony_ci    }
326862306a36Sopenharmony_ci    doprint "\n\n***************************************\n";
326962306a36Sopenharmony_ci    doprint "No more config bisecting possible.\n";
327062306a36Sopenharmony_ci    run_command "$diffexec $good $bad", 1;
327162306a36Sopenharmony_ci    doprint "***************************************\n\n";
327262306a36Sopenharmony_ci}
327362306a36Sopenharmony_ci
327462306a36Sopenharmony_cisub run_config_bisect {
327562306a36Sopenharmony_ci    my ($good, $bad, $last_result) = @_;
327662306a36Sopenharmony_ci    my $reset = "";
327762306a36Sopenharmony_ci    my $cmd;
327862306a36Sopenharmony_ci    my $ret;
327962306a36Sopenharmony_ci
328062306a36Sopenharmony_ci    if (!length($last_result)) {
328162306a36Sopenharmony_ci	$reset = "-r";
328262306a36Sopenharmony_ci    }
328362306a36Sopenharmony_ci    run_command "$config_bisect_exec $reset -b $outputdir $good $bad $last_result", 1;
328462306a36Sopenharmony_ci
328562306a36Sopenharmony_ci    # config-bisect returns:
328662306a36Sopenharmony_ci    #   0 if there is more to bisect
328762306a36Sopenharmony_ci    #   1 for finding a good config
328862306a36Sopenharmony_ci    #   2 if it can not find any more configs
328962306a36Sopenharmony_ci    #  -1 (255) on error
329062306a36Sopenharmony_ci    if ($run_command_status) {
329162306a36Sopenharmony_ci	return $run_command_status;
329262306a36Sopenharmony_ci    }
329362306a36Sopenharmony_ci
329462306a36Sopenharmony_ci    $ret = run_config_bisect_test $config_bisect_type;
329562306a36Sopenharmony_ci    if ($ret) {
329662306a36Sopenharmony_ci	doprint "NEW GOOD CONFIG ($pass)\n";
329762306a36Sopenharmony_ci	system("cp $output_config $tmpdir/good_config.tmp.$pass");
329862306a36Sopenharmony_ci	$pass++;
329962306a36Sopenharmony_ci	# Return 3 for good config
330062306a36Sopenharmony_ci	return 3;
330162306a36Sopenharmony_ci    } else {
330262306a36Sopenharmony_ci	doprint "NEW BAD CONFIG ($pass)\n";
330362306a36Sopenharmony_ci	system("cp $output_config $tmpdir/bad_config.tmp.$pass");
330462306a36Sopenharmony_ci	$pass++;
330562306a36Sopenharmony_ci	# Return 4 for bad config
330662306a36Sopenharmony_ci	return 4;
330762306a36Sopenharmony_ci    }
330862306a36Sopenharmony_ci}
330962306a36Sopenharmony_ci
331062306a36Sopenharmony_cisub config_bisect {
331162306a36Sopenharmony_ci    my ($i) = @_;
331262306a36Sopenharmony_ci
331362306a36Sopenharmony_ci    my $good_config;
331462306a36Sopenharmony_ci    my $bad_config;
331562306a36Sopenharmony_ci
331662306a36Sopenharmony_ci    my $type = $config_bisect_type;
331762306a36Sopenharmony_ci    my $ret;
331862306a36Sopenharmony_ci
331962306a36Sopenharmony_ci    $bad_config = $config_bisect;
332062306a36Sopenharmony_ci
332162306a36Sopenharmony_ci    if (defined($config_bisect_good)) {
332262306a36Sopenharmony_ci	$good_config = $config_bisect_good;
332362306a36Sopenharmony_ci    } elsif (defined($minconfig)) {
332462306a36Sopenharmony_ci	$good_config = $minconfig;
332562306a36Sopenharmony_ci    } else {
332662306a36Sopenharmony_ci	doprint "No config specified, checking if defconfig works";
332762306a36Sopenharmony_ci	$ret = run_bisect_test $type, "defconfig";
332862306a36Sopenharmony_ci	if (!$ret) {
332962306a36Sopenharmony_ci	    fail "Have no good config to compare with, please set CONFIG_BISECT_GOOD";
333062306a36Sopenharmony_ci	    return 1;
333162306a36Sopenharmony_ci	}
333262306a36Sopenharmony_ci	$good_config = $output_config;
333362306a36Sopenharmony_ci    }
333462306a36Sopenharmony_ci
333562306a36Sopenharmony_ci    if (!defined($config_bisect_exec)) {
333662306a36Sopenharmony_ci	# First check the location that ktest.pl ran
333762306a36Sopenharmony_ci	my @locations = (
333862306a36Sopenharmony_ci		"$pwd/config-bisect.pl",
333962306a36Sopenharmony_ci		"$dirname/config-bisect.pl",
334062306a36Sopenharmony_ci		"$builddir/tools/testing/ktest/config-bisect.pl",
334162306a36Sopenharmony_ci		undef );
334262306a36Sopenharmony_ci	foreach my $loc (@locations) {
334362306a36Sopenharmony_ci	    doprint "loc = $loc\n";
334462306a36Sopenharmony_ci	    $config_bisect_exec = $loc;
334562306a36Sopenharmony_ci	    last if (defined($config_bisect_exec && -x $config_bisect_exec));
334662306a36Sopenharmony_ci	}
334762306a36Sopenharmony_ci	if (!defined($config_bisect_exec)) {
334862306a36Sopenharmony_ci	    fail "Could not find an executable config-bisect.pl\n",
334962306a36Sopenharmony_ci		"  Set CONFIG_BISECT_EXEC to point to config-bisect.pl";
335062306a36Sopenharmony_ci	    return 1;
335162306a36Sopenharmony_ci	}
335262306a36Sopenharmony_ci    }
335362306a36Sopenharmony_ci
335462306a36Sopenharmony_ci    # we don't want min configs to cause issues here.
335562306a36Sopenharmony_ci    doprint "Disabling 'MIN_CONFIG' for this test\n";
335662306a36Sopenharmony_ci    undef $minconfig;
335762306a36Sopenharmony_ci
335862306a36Sopenharmony_ci    my %good_configs;
335962306a36Sopenharmony_ci    my %bad_configs;
336062306a36Sopenharmony_ci    my %tmp_configs;
336162306a36Sopenharmony_ci
336262306a36Sopenharmony_ci    if (-f "$tmpdir/good_config.tmp" || -f "$tmpdir/bad_config.tmp") {
336362306a36Sopenharmony_ci	if (read_yn "Interrupted config-bisect. Continue (n - will start new)?") {
336462306a36Sopenharmony_ci	    if (-f "$tmpdir/good_config.tmp") {
336562306a36Sopenharmony_ci		$good_config = "$tmpdir/good_config.tmp";
336662306a36Sopenharmony_ci	    } else {
336762306a36Sopenharmony_ci		$good_config = "$tmpdir/good_config";
336862306a36Sopenharmony_ci	    }
336962306a36Sopenharmony_ci	    if (-f "$tmpdir/bad_config.tmp") {
337062306a36Sopenharmony_ci		$bad_config = "$tmpdir/bad_config.tmp";
337162306a36Sopenharmony_ci	    } else {
337262306a36Sopenharmony_ci		$bad_config = "$tmpdir/bad_config";
337362306a36Sopenharmony_ci	    }
337462306a36Sopenharmony_ci	}
337562306a36Sopenharmony_ci    }
337662306a36Sopenharmony_ci    doprint "Run good configs through make oldconfig\n";
337762306a36Sopenharmony_ci    assign_configs \%tmp_configs, $good_config;
337862306a36Sopenharmony_ci    create_config "$good_config", \%tmp_configs;
337962306a36Sopenharmony_ci    $good_config = "$tmpdir/good_config";
338062306a36Sopenharmony_ci    system("cp $output_config $good_config") == 0 or dodie "cp good config";
338162306a36Sopenharmony_ci
338262306a36Sopenharmony_ci    doprint "Run bad configs through make oldconfig\n";
338362306a36Sopenharmony_ci    assign_configs \%tmp_configs, $bad_config;
338462306a36Sopenharmony_ci    create_config "$bad_config", \%tmp_configs;
338562306a36Sopenharmony_ci    $bad_config = "$tmpdir/bad_config";
338662306a36Sopenharmony_ci    system("cp $output_config $bad_config") == 0 or dodie "cp bad config";
338762306a36Sopenharmony_ci
338862306a36Sopenharmony_ci    if (defined($config_bisect_check) && $config_bisect_check ne "0") {
338962306a36Sopenharmony_ci	if ($config_bisect_check ne "good") {
339062306a36Sopenharmony_ci	    doprint "Testing bad config\n";
339162306a36Sopenharmony_ci
339262306a36Sopenharmony_ci	    $ret = run_bisect_test $type, "useconfig:$bad_config";
339362306a36Sopenharmony_ci	    if ($ret) {
339462306a36Sopenharmony_ci		fail "Bad config succeeded when expected to fail!";
339562306a36Sopenharmony_ci		return 0;
339662306a36Sopenharmony_ci	    }
339762306a36Sopenharmony_ci	}
339862306a36Sopenharmony_ci	if ($config_bisect_check ne "bad") {
339962306a36Sopenharmony_ci	    doprint "Testing good config\n";
340062306a36Sopenharmony_ci
340162306a36Sopenharmony_ci	    $ret = run_bisect_test $type, "useconfig:$good_config";
340262306a36Sopenharmony_ci	    if (!$ret) {
340362306a36Sopenharmony_ci		fail "Good config failed when expected to succeed!";
340462306a36Sopenharmony_ci		return 0;
340562306a36Sopenharmony_ci	    }
340662306a36Sopenharmony_ci	}
340762306a36Sopenharmony_ci    }
340862306a36Sopenharmony_ci
340962306a36Sopenharmony_ci    my $last_run = "";
341062306a36Sopenharmony_ci
341162306a36Sopenharmony_ci    do {
341262306a36Sopenharmony_ci	$ret = run_config_bisect $good_config, $bad_config, $last_run;
341362306a36Sopenharmony_ci	if ($ret == 3) {
341462306a36Sopenharmony_ci	    $last_run = "good";
341562306a36Sopenharmony_ci	} elsif ($ret == 4) {
341662306a36Sopenharmony_ci	    $last_run = "bad";
341762306a36Sopenharmony_ci	}
341862306a36Sopenharmony_ci	print_times;
341962306a36Sopenharmony_ci    } while ($ret == 3 || $ret == 4);
342062306a36Sopenharmony_ci
342162306a36Sopenharmony_ci    if ($ret == 2) {
342262306a36Sopenharmony_ci	config_bisect_end "$good_config.tmp", "$bad_config.tmp";
342362306a36Sopenharmony_ci    }
342462306a36Sopenharmony_ci
342562306a36Sopenharmony_ci    return $ret if ($ret < 0);
342662306a36Sopenharmony_ci
342762306a36Sopenharmony_ci    success $i;
342862306a36Sopenharmony_ci}
342962306a36Sopenharmony_ci
343062306a36Sopenharmony_cisub patchcheck_reboot {
343162306a36Sopenharmony_ci    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
343262306a36Sopenharmony_ci    reboot_to_good $patchcheck_sleep_time;
343362306a36Sopenharmony_ci}
343462306a36Sopenharmony_ci
343562306a36Sopenharmony_cisub patchcheck {
343662306a36Sopenharmony_ci    my ($i) = @_;
343762306a36Sopenharmony_ci
343862306a36Sopenharmony_ci    dodie "PATCHCHECK_START[$i] not defined\n"
343962306a36Sopenharmony_ci	if (!defined($patchcheck_start));
344062306a36Sopenharmony_ci    dodie "PATCHCHECK_TYPE[$i] not defined\n"
344162306a36Sopenharmony_ci	if (!defined($patchcheck_type));
344262306a36Sopenharmony_ci
344362306a36Sopenharmony_ci    my $start = $patchcheck_start;
344462306a36Sopenharmony_ci
344562306a36Sopenharmony_ci    my $cherry = $patchcheck_cherry;
344662306a36Sopenharmony_ci    if (!defined($cherry)) {
344762306a36Sopenharmony_ci	$cherry = 0;
344862306a36Sopenharmony_ci    }
344962306a36Sopenharmony_ci
345062306a36Sopenharmony_ci    my $end = "HEAD";
345162306a36Sopenharmony_ci    if (defined($patchcheck_end)) {
345262306a36Sopenharmony_ci	$end = $patchcheck_end;
345362306a36Sopenharmony_ci    } elsif ($cherry) {
345462306a36Sopenharmony_ci	dodie "PATCHCHECK_END must be defined with PATCHCHECK_CHERRY\n";
345562306a36Sopenharmony_ci    }
345662306a36Sopenharmony_ci
345762306a36Sopenharmony_ci    # Get the true sha1's since we can use things like HEAD~3
345862306a36Sopenharmony_ci    $start = get_sha1($start);
345962306a36Sopenharmony_ci    $end = get_sha1($end);
346062306a36Sopenharmony_ci
346162306a36Sopenharmony_ci    my $type = $patchcheck_type;
346262306a36Sopenharmony_ci
346362306a36Sopenharmony_ci    # Can't have a test without having a test to run
346462306a36Sopenharmony_ci    if ($type eq "test" && !defined($run_test)) {
346562306a36Sopenharmony_ci	$type = "boot";
346662306a36Sopenharmony_ci    }
346762306a36Sopenharmony_ci
346862306a36Sopenharmony_ci    if ($cherry) {
346962306a36Sopenharmony_ci	open (IN, "git cherry -v $start $end|") or
347062306a36Sopenharmony_ci	    dodie "could not get git list";
347162306a36Sopenharmony_ci    } else {
347262306a36Sopenharmony_ci	open (IN, "git log --pretty=oneline $end|") or
347362306a36Sopenharmony_ci	    dodie "could not get git list";
347462306a36Sopenharmony_ci    }
347562306a36Sopenharmony_ci
347662306a36Sopenharmony_ci    my @list;
347762306a36Sopenharmony_ci
347862306a36Sopenharmony_ci    while (<IN>) {
347962306a36Sopenharmony_ci	chomp;
348062306a36Sopenharmony_ci	# git cherry adds a '+' we want to remove
348162306a36Sopenharmony_ci	s/^\+ //;
348262306a36Sopenharmony_ci	$list[$#list+1] = $_;
348362306a36Sopenharmony_ci	last if (/^$start/);
348462306a36Sopenharmony_ci    }
348562306a36Sopenharmony_ci    close(IN);
348662306a36Sopenharmony_ci
348762306a36Sopenharmony_ci    if (!$cherry) {
348862306a36Sopenharmony_ci	if ($list[$#list] !~ /^$start/) {
348962306a36Sopenharmony_ci	    fail "SHA1 $start not found";
349062306a36Sopenharmony_ci	}
349162306a36Sopenharmony_ci
349262306a36Sopenharmony_ci	# go backwards in the list
349362306a36Sopenharmony_ci	@list = reverse @list;
349462306a36Sopenharmony_ci    }
349562306a36Sopenharmony_ci
349662306a36Sopenharmony_ci    doprint("Going to test the following commits:\n");
349762306a36Sopenharmony_ci    foreach my $l (@list) {
349862306a36Sopenharmony_ci	doprint "$l\n";
349962306a36Sopenharmony_ci    }
350062306a36Sopenharmony_ci
350162306a36Sopenharmony_ci    my $save_clean = $noclean;
350262306a36Sopenharmony_ci    my %ignored_warnings;
350362306a36Sopenharmony_ci
350462306a36Sopenharmony_ci    if (defined($ignore_warnings)) {
350562306a36Sopenharmony_ci	foreach my $sha1 (split /\s+/, $ignore_warnings) {
350662306a36Sopenharmony_ci	    $ignored_warnings{$sha1} = 1;
350762306a36Sopenharmony_ci	}
350862306a36Sopenharmony_ci    }
350962306a36Sopenharmony_ci
351062306a36Sopenharmony_ci    $in_patchcheck = 1;
351162306a36Sopenharmony_ci    foreach my $item (@list) {
351262306a36Sopenharmony_ci	my $sha1 = $item;
351362306a36Sopenharmony_ci	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
351462306a36Sopenharmony_ci
351562306a36Sopenharmony_ci	doprint "\nProcessing commit \"$item\"\n\n";
351662306a36Sopenharmony_ci
351762306a36Sopenharmony_ci	run_command "git checkout $sha1" or
351862306a36Sopenharmony_ci	    dodie "Failed to checkout $sha1";
351962306a36Sopenharmony_ci
352062306a36Sopenharmony_ci	# only clean on the first and last patch
352162306a36Sopenharmony_ci	if ($item eq $list[0] ||
352262306a36Sopenharmony_ci	    $item eq $list[$#list]) {
352362306a36Sopenharmony_ci	    $noclean = $save_clean;
352462306a36Sopenharmony_ci	} else {
352562306a36Sopenharmony_ci	    $noclean = 1;
352662306a36Sopenharmony_ci	}
352762306a36Sopenharmony_ci
352862306a36Sopenharmony_ci	if (defined($minconfig)) {
352962306a36Sopenharmony_ci	    build "useconfig:$minconfig" or return 0;
353062306a36Sopenharmony_ci	} else {
353162306a36Sopenharmony_ci	    # ?? no config to use?
353262306a36Sopenharmony_ci	    build "oldconfig" or return 0;
353362306a36Sopenharmony_ci	}
353462306a36Sopenharmony_ci
353562306a36Sopenharmony_ci	# No need to do per patch checking if warnings file exists
353662306a36Sopenharmony_ci	if (!defined($warnings_file) && !defined($ignored_warnings{$sha1})) {
353762306a36Sopenharmony_ci	    check_patch_buildlog $sha1 or return 0;
353862306a36Sopenharmony_ci	}
353962306a36Sopenharmony_ci
354062306a36Sopenharmony_ci	check_buildlog or return 0;
354162306a36Sopenharmony_ci
354262306a36Sopenharmony_ci	next if ($type eq "build");
354362306a36Sopenharmony_ci
354462306a36Sopenharmony_ci	my $failed = 0;
354562306a36Sopenharmony_ci
354662306a36Sopenharmony_ci	start_monitor_and_install or $failed = 1;
354762306a36Sopenharmony_ci
354862306a36Sopenharmony_ci	if (!$failed && $type ne "boot"){
354962306a36Sopenharmony_ci	    do_run_test or $failed = 1;
355062306a36Sopenharmony_ci	}
355162306a36Sopenharmony_ci	end_monitor;
355262306a36Sopenharmony_ci	if ($failed) {
355362306a36Sopenharmony_ci	    print_times;
355462306a36Sopenharmony_ci	    return 0;
355562306a36Sopenharmony_ci	}
355662306a36Sopenharmony_ci	patchcheck_reboot;
355762306a36Sopenharmony_ci	print_times;
355862306a36Sopenharmony_ci    }
355962306a36Sopenharmony_ci    $in_patchcheck = 0;
356062306a36Sopenharmony_ci    success $i;
356162306a36Sopenharmony_ci
356262306a36Sopenharmony_ci    return 1;
356362306a36Sopenharmony_ci}
356462306a36Sopenharmony_ci
356562306a36Sopenharmony_cisub add_dep {
356662306a36Sopenharmony_ci    # $config depends on $dep
356762306a36Sopenharmony_ci    my ($config, $dep) = @_;
356862306a36Sopenharmony_ci
356962306a36Sopenharmony_ci    if (defined($depends{$config})) {
357062306a36Sopenharmony_ci	$depends{$config} .= " " . $dep;
357162306a36Sopenharmony_ci    } else {
357262306a36Sopenharmony_ci	$depends{$config} = $dep;
357362306a36Sopenharmony_ci    }
357462306a36Sopenharmony_ci
357562306a36Sopenharmony_ci    # record the number of configs depending on $dep
357662306a36Sopenharmony_ci    if (defined $depcount{$dep}) {
357762306a36Sopenharmony_ci	$depcount{$dep}++;
357862306a36Sopenharmony_ci    } else {
357962306a36Sopenharmony_ci	$depcount{$dep} = 1;
358062306a36Sopenharmony_ci    }
358162306a36Sopenharmony_ci}
358262306a36Sopenharmony_ci
358362306a36Sopenharmony_ci# taken from streamline_config.pl
358462306a36Sopenharmony_cisub read_kconfig {
358562306a36Sopenharmony_ci    my ($kconfig) = @_;
358662306a36Sopenharmony_ci
358762306a36Sopenharmony_ci    my $state = "NONE";
358862306a36Sopenharmony_ci    my $config;
358962306a36Sopenharmony_ci    my @kconfigs;
359062306a36Sopenharmony_ci
359162306a36Sopenharmony_ci    my $cont = 0;
359262306a36Sopenharmony_ci    my $line;
359362306a36Sopenharmony_ci
359462306a36Sopenharmony_ci    if (! -f $kconfig) {
359562306a36Sopenharmony_ci	doprint "file $kconfig does not exist, skipping\n";
359662306a36Sopenharmony_ci	return;
359762306a36Sopenharmony_ci    }
359862306a36Sopenharmony_ci
359962306a36Sopenharmony_ci    open(KIN, "$kconfig")
360062306a36Sopenharmony_ci	or dodie "Can't open $kconfig";
360162306a36Sopenharmony_ci    while (<KIN>) {
360262306a36Sopenharmony_ci	chomp;
360362306a36Sopenharmony_ci
360462306a36Sopenharmony_ci	# Make sure that lines ending with \ continue
360562306a36Sopenharmony_ci	if ($cont) {
360662306a36Sopenharmony_ci	    $_ = $line . " " . $_;
360762306a36Sopenharmony_ci	}
360862306a36Sopenharmony_ci
360962306a36Sopenharmony_ci	if (s/\\$//) {
361062306a36Sopenharmony_ci	    $cont = 1;
361162306a36Sopenharmony_ci	    $line = $_;
361262306a36Sopenharmony_ci	    next;
361362306a36Sopenharmony_ci	}
361462306a36Sopenharmony_ci
361562306a36Sopenharmony_ci	$cont = 0;
361662306a36Sopenharmony_ci
361762306a36Sopenharmony_ci	# collect any Kconfig sources
361862306a36Sopenharmony_ci	if (/^source\s*"(.*)"/) {
361962306a36Sopenharmony_ci	    $kconfigs[$#kconfigs+1] = $1;
362062306a36Sopenharmony_ci	}
362162306a36Sopenharmony_ci
362262306a36Sopenharmony_ci	# configs found
362362306a36Sopenharmony_ci	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
362462306a36Sopenharmony_ci	    $state = "NEW";
362562306a36Sopenharmony_ci	    $config = $2;
362662306a36Sopenharmony_ci
362762306a36Sopenharmony_ci	    for (my $i = 0; $i < $iflevel; $i++) {
362862306a36Sopenharmony_ci		add_dep $config, $ifdeps[$i];
362962306a36Sopenharmony_ci	    }
363062306a36Sopenharmony_ci
363162306a36Sopenharmony_ci	# collect the depends for the config
363262306a36Sopenharmony_ci	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
363362306a36Sopenharmony_ci
363462306a36Sopenharmony_ci	    add_dep $config, $1;
363562306a36Sopenharmony_ci
363662306a36Sopenharmony_ci	# Get the configs that select this config
363762306a36Sopenharmony_ci	} elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
363862306a36Sopenharmony_ci
363962306a36Sopenharmony_ci	    # selected by depends on config
364062306a36Sopenharmony_ci	    add_dep $1, $config;
364162306a36Sopenharmony_ci
364262306a36Sopenharmony_ci	# Check for if statements
364362306a36Sopenharmony_ci	} elsif (/^if\s+(.*\S)\s*$/) {
364462306a36Sopenharmony_ci	    my $deps = $1;
364562306a36Sopenharmony_ci	    # remove beginning and ending non text
364662306a36Sopenharmony_ci	    $deps =~ s/^[^a-zA-Z0-9_]*//;
364762306a36Sopenharmony_ci	    $deps =~ s/[^a-zA-Z0-9_]*$//;
364862306a36Sopenharmony_ci
364962306a36Sopenharmony_ci	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
365062306a36Sopenharmony_ci
365162306a36Sopenharmony_ci	    $ifdeps[$iflevel++] = join ':', @deps;
365262306a36Sopenharmony_ci
365362306a36Sopenharmony_ci	} elsif (/^endif/) {
365462306a36Sopenharmony_ci
365562306a36Sopenharmony_ci	    $iflevel-- if ($iflevel);
365662306a36Sopenharmony_ci
365762306a36Sopenharmony_ci	# stop on "help"
365862306a36Sopenharmony_ci	} elsif (/^\s*help\s*$/) {
365962306a36Sopenharmony_ci	    $state = "NONE";
366062306a36Sopenharmony_ci	}
366162306a36Sopenharmony_ci    }
366262306a36Sopenharmony_ci    close(KIN);
366362306a36Sopenharmony_ci
366462306a36Sopenharmony_ci    # read in any configs that were found.
366562306a36Sopenharmony_ci    foreach $kconfig (@kconfigs) {
366662306a36Sopenharmony_ci	if (!defined($read_kconfigs{$kconfig})) {
366762306a36Sopenharmony_ci	    $read_kconfigs{$kconfig} = 1;
366862306a36Sopenharmony_ci	    read_kconfig("$builddir/$kconfig");
366962306a36Sopenharmony_ci	}
367062306a36Sopenharmony_ci    }
367162306a36Sopenharmony_ci}
367262306a36Sopenharmony_ci
367362306a36Sopenharmony_cisub read_depends {
367462306a36Sopenharmony_ci    # find out which arch this is by the kconfig file
367562306a36Sopenharmony_ci    open (IN, $output_config) or
367662306a36Sopenharmony_ci	dodie "Failed to read $output_config";
367762306a36Sopenharmony_ci    my $arch;
367862306a36Sopenharmony_ci    while (<IN>) {
367962306a36Sopenharmony_ci	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
368062306a36Sopenharmony_ci	    $arch = $1;
368162306a36Sopenharmony_ci	    last;
368262306a36Sopenharmony_ci	}
368362306a36Sopenharmony_ci    }
368462306a36Sopenharmony_ci    close IN;
368562306a36Sopenharmony_ci
368662306a36Sopenharmony_ci    if (!defined($arch)) {
368762306a36Sopenharmony_ci	doprint "Could not find arch from config file\n";
368862306a36Sopenharmony_ci	doprint "no dependencies used\n";
368962306a36Sopenharmony_ci	return;
369062306a36Sopenharmony_ci    }
369162306a36Sopenharmony_ci
369262306a36Sopenharmony_ci    # arch is really the subarch, we need to know
369362306a36Sopenharmony_ci    # what directory to look at.
369462306a36Sopenharmony_ci    if ($arch eq "i386" || $arch eq "x86_64") {
369562306a36Sopenharmony_ci	$arch = "x86";
369662306a36Sopenharmony_ci    }
369762306a36Sopenharmony_ci
369862306a36Sopenharmony_ci    my $kconfig = "$builddir/arch/$arch/Kconfig";
369962306a36Sopenharmony_ci
370062306a36Sopenharmony_ci    if (! -f $kconfig && $arch =~ /\d$/) {
370162306a36Sopenharmony_ci	my $orig = $arch;
370262306a36Sopenharmony_ci	# some subarchs have numbers, truncate them
370362306a36Sopenharmony_ci	$arch =~ s/\d*$//;
370462306a36Sopenharmony_ci	$kconfig = "$builddir/arch/$arch/Kconfig";
370562306a36Sopenharmony_ci	if (! -f $kconfig) {
370662306a36Sopenharmony_ci	    doprint "No idea what arch dir $orig is for\n";
370762306a36Sopenharmony_ci	    doprint "no dependencies used\n";
370862306a36Sopenharmony_ci	    return;
370962306a36Sopenharmony_ci	}
371062306a36Sopenharmony_ci    }
371162306a36Sopenharmony_ci
371262306a36Sopenharmony_ci    read_kconfig($kconfig);
371362306a36Sopenharmony_ci}
371462306a36Sopenharmony_ci
371562306a36Sopenharmony_cisub make_new_config {
371662306a36Sopenharmony_ci    my @configs = @_;
371762306a36Sopenharmony_ci
371862306a36Sopenharmony_ci    open (OUT, ">$output_config")
371962306a36Sopenharmony_ci	or dodie "Failed to write $output_config";
372062306a36Sopenharmony_ci
372162306a36Sopenharmony_ci    foreach my $config (@configs) {
372262306a36Sopenharmony_ci	print OUT "$config\n";
372362306a36Sopenharmony_ci    }
372462306a36Sopenharmony_ci    close OUT;
372562306a36Sopenharmony_ci}
372662306a36Sopenharmony_ci
372762306a36Sopenharmony_cisub chomp_config {
372862306a36Sopenharmony_ci    my ($config) = @_;
372962306a36Sopenharmony_ci
373062306a36Sopenharmony_ci    $config =~ s/CONFIG_//;
373162306a36Sopenharmony_ci
373262306a36Sopenharmony_ci    return $config;
373362306a36Sopenharmony_ci}
373462306a36Sopenharmony_ci
373562306a36Sopenharmony_cisub get_depends {
373662306a36Sopenharmony_ci    my ($dep) = @_;
373762306a36Sopenharmony_ci
373862306a36Sopenharmony_ci    my $kconfig = chomp_config $dep;
373962306a36Sopenharmony_ci
374062306a36Sopenharmony_ci    $dep = $depends{"$kconfig"};
374162306a36Sopenharmony_ci
374262306a36Sopenharmony_ci    # the dep string we have saves the dependencies as they
374362306a36Sopenharmony_ci    # were found, including expressions like ! && ||. We
374462306a36Sopenharmony_ci    # want to split this out into just an array of configs.
374562306a36Sopenharmony_ci
374662306a36Sopenharmony_ci    my $valid = "A-Za-z_0-9";
374762306a36Sopenharmony_ci
374862306a36Sopenharmony_ci    my @configs;
374962306a36Sopenharmony_ci
375062306a36Sopenharmony_ci    while ($dep =~ /[$valid]/) {
375162306a36Sopenharmony_ci	if ($dep =~ /^[^$valid]*([$valid]+)/) {
375262306a36Sopenharmony_ci	    my $conf = "CONFIG_" . $1;
375362306a36Sopenharmony_ci
375462306a36Sopenharmony_ci	    $configs[$#configs + 1] = $conf;
375562306a36Sopenharmony_ci
375662306a36Sopenharmony_ci	    $dep =~ s/^[^$valid]*[$valid]+//;
375762306a36Sopenharmony_ci	} else {
375862306a36Sopenharmony_ci	    dodie "this should never happen";
375962306a36Sopenharmony_ci	}
376062306a36Sopenharmony_ci    }
376162306a36Sopenharmony_ci
376262306a36Sopenharmony_ci    return @configs;
376362306a36Sopenharmony_ci}
376462306a36Sopenharmony_ci
376562306a36Sopenharmony_cisub test_this_config {
376662306a36Sopenharmony_ci    my ($config) = @_;
376762306a36Sopenharmony_ci
376862306a36Sopenharmony_ci    my $found;
376962306a36Sopenharmony_ci
377062306a36Sopenharmony_ci    # if we already processed this config, skip it
377162306a36Sopenharmony_ci    if (defined($processed_configs{$config})) {
377262306a36Sopenharmony_ci	return undef;
377362306a36Sopenharmony_ci    }
377462306a36Sopenharmony_ci    $processed_configs{$config} = 1;
377562306a36Sopenharmony_ci
377662306a36Sopenharmony_ci    # if this config failed during this round, skip it
377762306a36Sopenharmony_ci    if (defined($nochange_config{$config})) {
377862306a36Sopenharmony_ci	return undef;
377962306a36Sopenharmony_ci    }
378062306a36Sopenharmony_ci
378162306a36Sopenharmony_ci    my $kconfig = chomp_config $config;
378262306a36Sopenharmony_ci
378362306a36Sopenharmony_ci    # Test dependencies first
378462306a36Sopenharmony_ci    if (defined($depends{"$kconfig"})) {
378562306a36Sopenharmony_ci	my @parents = get_depends $config;
378662306a36Sopenharmony_ci	foreach my $parent (@parents) {
378762306a36Sopenharmony_ci	    # if the parent is in the min config, check it first
378862306a36Sopenharmony_ci	    next if (!defined($min_configs{$parent}));
378962306a36Sopenharmony_ci	    $found = test_this_config($parent);
379062306a36Sopenharmony_ci	    if (defined($found)) {
379162306a36Sopenharmony_ci		return $found;
379262306a36Sopenharmony_ci	    }
379362306a36Sopenharmony_ci	}
379462306a36Sopenharmony_ci    }
379562306a36Sopenharmony_ci
379662306a36Sopenharmony_ci    # Remove this config from the list of configs
379762306a36Sopenharmony_ci    # do a make olddefconfig and then read the resulting
379862306a36Sopenharmony_ci    # .config to make sure it is missing the config that
379962306a36Sopenharmony_ci    # we had before
380062306a36Sopenharmony_ci    my %configs = %min_configs;
380162306a36Sopenharmony_ci    $configs{$config} = "# $config is not set";
380262306a36Sopenharmony_ci    make_new_config ((values %configs), (values %keep_configs));
380362306a36Sopenharmony_ci    make_oldconfig;
380462306a36Sopenharmony_ci    delete $configs{$config};
380562306a36Sopenharmony_ci    undef %configs;
380662306a36Sopenharmony_ci    assign_configs \%configs, $output_config;
380762306a36Sopenharmony_ci
380862306a36Sopenharmony_ci    if (!defined($configs{$config}) || $configs{$config} =~ /^#/) {
380962306a36Sopenharmony_ci	return $config;
381062306a36Sopenharmony_ci    }
381162306a36Sopenharmony_ci
381262306a36Sopenharmony_ci    doprint "disabling config $config did not change .config\n";
381362306a36Sopenharmony_ci
381462306a36Sopenharmony_ci    $nochange_config{$config} = 1;
381562306a36Sopenharmony_ci
381662306a36Sopenharmony_ci    return undef;
381762306a36Sopenharmony_ci}
381862306a36Sopenharmony_ci
381962306a36Sopenharmony_cisub make_min_config {
382062306a36Sopenharmony_ci    my ($i) = @_;
382162306a36Sopenharmony_ci
382262306a36Sopenharmony_ci    my $type = $minconfig_type;
382362306a36Sopenharmony_ci    if ($type ne "boot" && $type ne "test") {
382462306a36Sopenharmony_ci	fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" .
382562306a36Sopenharmony_ci	    " make_min_config works only with 'boot' and 'test'\n" and return;
382662306a36Sopenharmony_ci    }
382762306a36Sopenharmony_ci
382862306a36Sopenharmony_ci    if (!defined($output_minconfig)) {
382962306a36Sopenharmony_ci	fail "OUTPUT_MIN_CONFIG not defined" and return;
383062306a36Sopenharmony_ci    }
383162306a36Sopenharmony_ci
383262306a36Sopenharmony_ci    # If output_minconfig exists, and the start_minconfig
383362306a36Sopenharmony_ci    # came from min_config, than ask if we should use
383462306a36Sopenharmony_ci    # that instead.
383562306a36Sopenharmony_ci    if (-f $output_minconfig && !$start_minconfig_defined) {
383662306a36Sopenharmony_ci	print "$output_minconfig exists\n";
383762306a36Sopenharmony_ci	if (!defined($use_output_minconfig)) {
383862306a36Sopenharmony_ci	    if (read_yn " Use it as minconfig?") {
383962306a36Sopenharmony_ci		$start_minconfig = $output_minconfig;
384062306a36Sopenharmony_ci	    }
384162306a36Sopenharmony_ci	} elsif ($use_output_minconfig > 0) {
384262306a36Sopenharmony_ci	    doprint "Using $output_minconfig as MIN_CONFIG\n";
384362306a36Sopenharmony_ci	    $start_minconfig = $output_minconfig;
384462306a36Sopenharmony_ci	} else {
384562306a36Sopenharmony_ci	    doprint "Set to still use MIN_CONFIG as starting point\n";
384662306a36Sopenharmony_ci	}
384762306a36Sopenharmony_ci    }
384862306a36Sopenharmony_ci
384962306a36Sopenharmony_ci    if (!defined($start_minconfig)) {
385062306a36Sopenharmony_ci	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
385162306a36Sopenharmony_ci    }
385262306a36Sopenharmony_ci
385362306a36Sopenharmony_ci    my $temp_config = "$tmpdir/temp_config";
385462306a36Sopenharmony_ci
385562306a36Sopenharmony_ci    # First things first. We build an allnoconfig to find
385662306a36Sopenharmony_ci    # out what the defaults are that we can't touch.
385762306a36Sopenharmony_ci    # Some are selections, but we really can't handle selections.
385862306a36Sopenharmony_ci
385962306a36Sopenharmony_ci    my $save_minconfig = $minconfig;
386062306a36Sopenharmony_ci    undef $minconfig;
386162306a36Sopenharmony_ci
386262306a36Sopenharmony_ci    run_command "$make allnoconfig" or return 0;
386362306a36Sopenharmony_ci
386462306a36Sopenharmony_ci    read_depends;
386562306a36Sopenharmony_ci
386662306a36Sopenharmony_ci    process_config_ignore $output_config;
386762306a36Sopenharmony_ci
386862306a36Sopenharmony_ci    undef %save_configs;
386962306a36Sopenharmony_ci    undef %min_configs;
387062306a36Sopenharmony_ci
387162306a36Sopenharmony_ci    if (defined($ignore_config)) {
387262306a36Sopenharmony_ci	# make sure the file exists
387362306a36Sopenharmony_ci	`touch $ignore_config`;
387462306a36Sopenharmony_ci	assign_configs \%save_configs, $ignore_config;
387562306a36Sopenharmony_ci    }
387662306a36Sopenharmony_ci
387762306a36Sopenharmony_ci    %keep_configs = %save_configs;
387862306a36Sopenharmony_ci
387962306a36Sopenharmony_ci    doprint "Load initial configs from $start_minconfig\n";
388062306a36Sopenharmony_ci
388162306a36Sopenharmony_ci    # Look at the current min configs, and save off all the
388262306a36Sopenharmony_ci    # ones that were set via the allnoconfig
388362306a36Sopenharmony_ci    assign_configs \%min_configs, $start_minconfig;
388462306a36Sopenharmony_ci
388562306a36Sopenharmony_ci    my @config_keys = keys %min_configs;
388662306a36Sopenharmony_ci
388762306a36Sopenharmony_ci    # All configs need a depcount
388862306a36Sopenharmony_ci    foreach my $config (@config_keys) {
388962306a36Sopenharmony_ci	my $kconfig = chomp_config $config;
389062306a36Sopenharmony_ci	if (!defined $depcount{$kconfig}) {
389162306a36Sopenharmony_ci	    $depcount{$kconfig} = 0;
389262306a36Sopenharmony_ci	}
389362306a36Sopenharmony_ci    }
389462306a36Sopenharmony_ci
389562306a36Sopenharmony_ci    # Remove anything that was set by the make allnoconfig
389662306a36Sopenharmony_ci    # we shouldn't need them as they get set for us anyway.
389762306a36Sopenharmony_ci    foreach my $config (@config_keys) {
389862306a36Sopenharmony_ci	# Remove anything in the ignore_config
389962306a36Sopenharmony_ci	if (defined($keep_configs{$config})) {
390062306a36Sopenharmony_ci	    my $file = $ignore_config;
390162306a36Sopenharmony_ci	    $file =~ s,.*/(.*?)$,$1,;
390262306a36Sopenharmony_ci	    doprint "$config set by $file ... ignored\n";
390362306a36Sopenharmony_ci	    delete $min_configs{$config};
390462306a36Sopenharmony_ci	    next;
390562306a36Sopenharmony_ci	}
390662306a36Sopenharmony_ci	# But make sure the settings are the same. If a min config
390762306a36Sopenharmony_ci	# sets a selection, we do not want to get rid of it if
390862306a36Sopenharmony_ci	# it is not the same as what we have. Just move it into
390962306a36Sopenharmony_ci	# the keep configs.
391062306a36Sopenharmony_ci	if (defined($config_ignore{$config})) {
391162306a36Sopenharmony_ci	    if ($config_ignore{$config} ne $min_configs{$config}) {
391262306a36Sopenharmony_ci		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
391362306a36Sopenharmony_ci		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
391462306a36Sopenharmony_ci		$keep_configs{$config} = $min_configs{$config};
391562306a36Sopenharmony_ci	    } else {
391662306a36Sopenharmony_ci		doprint "$config set by allnoconfig ... ignored\n";
391762306a36Sopenharmony_ci	    }
391862306a36Sopenharmony_ci	    delete $min_configs{$config};
391962306a36Sopenharmony_ci	}
392062306a36Sopenharmony_ci    }
392162306a36Sopenharmony_ci
392262306a36Sopenharmony_ci    my $done = 0;
392362306a36Sopenharmony_ci    my $take_two = 0;
392462306a36Sopenharmony_ci
392562306a36Sopenharmony_ci    while (!$done) {
392662306a36Sopenharmony_ci	my $config;
392762306a36Sopenharmony_ci	my $found;
392862306a36Sopenharmony_ci
392962306a36Sopenharmony_ci	# Now disable each config one by one and do a make oldconfig
393062306a36Sopenharmony_ci	# till we find a config that changes our list.
393162306a36Sopenharmony_ci
393262306a36Sopenharmony_ci	my @test_configs = keys %min_configs;
393362306a36Sopenharmony_ci
393462306a36Sopenharmony_ci	# Sort keys by who is most dependent on
393562306a36Sopenharmony_ci	@test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
393662306a36Sopenharmony_ci	    @test_configs ;
393762306a36Sopenharmony_ci
393862306a36Sopenharmony_ci	# Put configs that did not modify the config at the end.
393962306a36Sopenharmony_ci	my $reset = 1;
394062306a36Sopenharmony_ci	for (my $i = 0; $i < $#test_configs; $i++) {
394162306a36Sopenharmony_ci	    if (!defined($nochange_config{$test_configs[0]})) {
394262306a36Sopenharmony_ci		$reset = 0;
394362306a36Sopenharmony_ci		last;
394462306a36Sopenharmony_ci	    }
394562306a36Sopenharmony_ci	    # This config didn't change the .config last time.
394662306a36Sopenharmony_ci	    # Place it at the end
394762306a36Sopenharmony_ci	    my $config = shift @test_configs;
394862306a36Sopenharmony_ci	    push @test_configs, $config;
394962306a36Sopenharmony_ci	}
395062306a36Sopenharmony_ci
395162306a36Sopenharmony_ci	# if every test config has failed to modify the .config file
395262306a36Sopenharmony_ci	# in the past, then reset and start over.
395362306a36Sopenharmony_ci	if ($reset) {
395462306a36Sopenharmony_ci	    undef %nochange_config;
395562306a36Sopenharmony_ci	}
395662306a36Sopenharmony_ci
395762306a36Sopenharmony_ci	undef %processed_configs;
395862306a36Sopenharmony_ci
395962306a36Sopenharmony_ci	foreach my $config (@test_configs) {
396062306a36Sopenharmony_ci
396162306a36Sopenharmony_ci	    $found = test_this_config $config;
396262306a36Sopenharmony_ci
396362306a36Sopenharmony_ci	    last if (defined($found));
396462306a36Sopenharmony_ci
396562306a36Sopenharmony_ci	    # oh well, try another config
396662306a36Sopenharmony_ci	}
396762306a36Sopenharmony_ci
396862306a36Sopenharmony_ci	if (!defined($found)) {
396962306a36Sopenharmony_ci	    # we could have failed due to the nochange_config hash
397062306a36Sopenharmony_ci	    # reset and try again
397162306a36Sopenharmony_ci	    if (!$take_two) {
397262306a36Sopenharmony_ci		undef %nochange_config;
397362306a36Sopenharmony_ci		$take_two = 1;
397462306a36Sopenharmony_ci		next;
397562306a36Sopenharmony_ci	    }
397662306a36Sopenharmony_ci	    doprint "No more configs found that we can disable\n";
397762306a36Sopenharmony_ci	    $done = 1;
397862306a36Sopenharmony_ci	    last;
397962306a36Sopenharmony_ci	}
398062306a36Sopenharmony_ci	$take_two = 0;
398162306a36Sopenharmony_ci
398262306a36Sopenharmony_ci	$config = $found;
398362306a36Sopenharmony_ci
398462306a36Sopenharmony_ci	doprint "Test with $config disabled\n";
398562306a36Sopenharmony_ci
398662306a36Sopenharmony_ci	# set in_bisect to keep build and monitor from dieing
398762306a36Sopenharmony_ci	$in_bisect = 1;
398862306a36Sopenharmony_ci
398962306a36Sopenharmony_ci	my $failed = 0;
399062306a36Sopenharmony_ci	build "oldconfig" or $failed = 1;
399162306a36Sopenharmony_ci	if (!$failed) {
399262306a36Sopenharmony_ci	    start_monitor_and_install or $failed = 1;
399362306a36Sopenharmony_ci
399462306a36Sopenharmony_ci	    if ($type eq "test" && !$failed) {
399562306a36Sopenharmony_ci		do_run_test or $failed = 1;
399662306a36Sopenharmony_ci	    }
399762306a36Sopenharmony_ci
399862306a36Sopenharmony_ci	    end_monitor;
399962306a36Sopenharmony_ci	}
400062306a36Sopenharmony_ci
400162306a36Sopenharmony_ci	$in_bisect = 0;
400262306a36Sopenharmony_ci
400362306a36Sopenharmony_ci	if ($failed) {
400462306a36Sopenharmony_ci	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
400562306a36Sopenharmony_ci	    # this config is needed, add it to the ignore list.
400662306a36Sopenharmony_ci	    $keep_configs{$config} = $min_configs{$config};
400762306a36Sopenharmony_ci	    $save_configs{$config} = $min_configs{$config};
400862306a36Sopenharmony_ci	    delete $min_configs{$config};
400962306a36Sopenharmony_ci
401062306a36Sopenharmony_ci	    # update new ignore configs
401162306a36Sopenharmony_ci	    if (defined($ignore_config)) {
401262306a36Sopenharmony_ci		open (OUT, ">$temp_config") or
401362306a36Sopenharmony_ci		    dodie "Can't write to $temp_config";
401462306a36Sopenharmony_ci		foreach my $config (keys %save_configs) {
401562306a36Sopenharmony_ci		    print OUT "$save_configs{$config}\n";
401662306a36Sopenharmony_ci		}
401762306a36Sopenharmony_ci		close OUT;
401862306a36Sopenharmony_ci		run_command "mv $temp_config $ignore_config" or
401962306a36Sopenharmony_ci		    dodie "failed to copy update to $ignore_config";
402062306a36Sopenharmony_ci	    }
402162306a36Sopenharmony_ci
402262306a36Sopenharmony_ci	} else {
402362306a36Sopenharmony_ci	    # We booted without this config, remove it from the minconfigs.
402462306a36Sopenharmony_ci	    doprint "$config is not needed, disabling\n";
402562306a36Sopenharmony_ci
402662306a36Sopenharmony_ci	    delete $min_configs{$config};
402762306a36Sopenharmony_ci
402862306a36Sopenharmony_ci	    # Also disable anything that is not enabled in this config
402962306a36Sopenharmony_ci	    my %configs;
403062306a36Sopenharmony_ci	    assign_configs \%configs, $output_config;
403162306a36Sopenharmony_ci	    my @config_keys = keys %min_configs;
403262306a36Sopenharmony_ci	    foreach my $config (@config_keys) {
403362306a36Sopenharmony_ci		if (!defined($configs{$config})) {
403462306a36Sopenharmony_ci		    doprint "$config is not set, disabling\n";
403562306a36Sopenharmony_ci		    delete $min_configs{$config};
403662306a36Sopenharmony_ci		}
403762306a36Sopenharmony_ci	    }
403862306a36Sopenharmony_ci
403962306a36Sopenharmony_ci	    # Save off all the current mandatory configs
404062306a36Sopenharmony_ci	    open (OUT, ">$temp_config") or
404162306a36Sopenharmony_ci		dodie "Can't write to $temp_config";
404262306a36Sopenharmony_ci	    foreach my $config (keys %keep_configs) {
404362306a36Sopenharmony_ci		print OUT "$keep_configs{$config}\n";
404462306a36Sopenharmony_ci	    }
404562306a36Sopenharmony_ci	    foreach my $config (keys %min_configs) {
404662306a36Sopenharmony_ci		print OUT "$min_configs{$config}\n";
404762306a36Sopenharmony_ci	    }
404862306a36Sopenharmony_ci	    close OUT;
404962306a36Sopenharmony_ci
405062306a36Sopenharmony_ci	    run_command "mv $temp_config $output_minconfig" or
405162306a36Sopenharmony_ci		dodie "failed to copy update to $output_minconfig";
405262306a36Sopenharmony_ci	}
405362306a36Sopenharmony_ci
405462306a36Sopenharmony_ci	doprint "Reboot and wait $sleep_time seconds\n";
405562306a36Sopenharmony_ci	reboot_to_good $sleep_time;
405662306a36Sopenharmony_ci    }
405762306a36Sopenharmony_ci
405862306a36Sopenharmony_ci    success $i;
405962306a36Sopenharmony_ci    return 1;
406062306a36Sopenharmony_ci}
406162306a36Sopenharmony_ci
406262306a36Sopenharmony_cisub make_warnings_file {
406362306a36Sopenharmony_ci    my ($i) = @_;
406462306a36Sopenharmony_ci
406562306a36Sopenharmony_ci    if (!defined($warnings_file)) {
406662306a36Sopenharmony_ci	dodie "Must define WARNINGS_FILE for make_warnings_file test";
406762306a36Sopenharmony_ci    }
406862306a36Sopenharmony_ci
406962306a36Sopenharmony_ci    if ($build_type eq "nobuild") {
407062306a36Sopenharmony_ci	dodie "BUILD_TYPE can not be 'nobuild' for make_warnings_file test";
407162306a36Sopenharmony_ci    }
407262306a36Sopenharmony_ci
407362306a36Sopenharmony_ci    build $build_type or dodie "Failed to build";
407462306a36Sopenharmony_ci
407562306a36Sopenharmony_ci    open(OUT, ">$warnings_file") or dodie "Can't create $warnings_file";
407662306a36Sopenharmony_ci
407762306a36Sopenharmony_ci    open(IN, $buildlog) or dodie "Can't open $buildlog";
407862306a36Sopenharmony_ci    while (<IN>) {
407962306a36Sopenharmony_ci	# Some compilers use UTF-8 extended for quotes
408062306a36Sopenharmony_ci	# for distcc heterogeneous systems, this causes issues
408162306a36Sopenharmony_ci	s/$utf8_quote/'/g;
408262306a36Sopenharmony_ci
408362306a36Sopenharmony_ci	if (/$check_build_re/) {
408462306a36Sopenharmony_ci	    print OUT;
408562306a36Sopenharmony_ci	}
408662306a36Sopenharmony_ci    }
408762306a36Sopenharmony_ci    close(IN);
408862306a36Sopenharmony_ci
408962306a36Sopenharmony_ci    close(OUT);
409062306a36Sopenharmony_ci
409162306a36Sopenharmony_ci    success $i;
409262306a36Sopenharmony_ci}
409362306a36Sopenharmony_ci
409462306a36Sopenharmony_cisub option_defined {
409562306a36Sopenharmony_ci    my ($option) = @_;
409662306a36Sopenharmony_ci
409762306a36Sopenharmony_ci    if (defined($opt{$option}) && $opt{$option} !~ /^\s*$/) {
409862306a36Sopenharmony_ci	return 1;
409962306a36Sopenharmony_ci    }
410062306a36Sopenharmony_ci
410162306a36Sopenharmony_ci    return 0;
410262306a36Sopenharmony_ci}
410362306a36Sopenharmony_ci
410462306a36Sopenharmony_cisub __set_test_option {
410562306a36Sopenharmony_ci    my ($name, $i) = @_;
410662306a36Sopenharmony_ci
410762306a36Sopenharmony_ci    my $option = "$name\[$i\]";
410862306a36Sopenharmony_ci
410962306a36Sopenharmony_ci    if (option_defined($option)) {
411062306a36Sopenharmony_ci	return $opt{$option};
411162306a36Sopenharmony_ci    }
411262306a36Sopenharmony_ci
411362306a36Sopenharmony_ci    foreach my $test (keys %repeat_tests) {
411462306a36Sopenharmony_ci	if ($i >= $test &&
411562306a36Sopenharmony_ci	    $i < $test + $repeat_tests{$test}) {
411662306a36Sopenharmony_ci	    $option = "$name\[$test\]";
411762306a36Sopenharmony_ci	    if (option_defined($option)) {
411862306a36Sopenharmony_ci		return $opt{$option};
411962306a36Sopenharmony_ci	    }
412062306a36Sopenharmony_ci	}
412162306a36Sopenharmony_ci    }
412262306a36Sopenharmony_ci
412362306a36Sopenharmony_ci    if (option_defined($name)) {
412462306a36Sopenharmony_ci	return $opt{$name};
412562306a36Sopenharmony_ci    }
412662306a36Sopenharmony_ci
412762306a36Sopenharmony_ci    return undef;
412862306a36Sopenharmony_ci}
412962306a36Sopenharmony_ci
413062306a36Sopenharmony_cisub set_test_option {
413162306a36Sopenharmony_ci    my ($name, $i) = @_;
413262306a36Sopenharmony_ci
413362306a36Sopenharmony_ci    my $option = __set_test_option($name, $i);
413462306a36Sopenharmony_ci    return $option if (!defined($option));
413562306a36Sopenharmony_ci
413662306a36Sopenharmony_ci    return eval_option($name, $option, $i);
413762306a36Sopenharmony_ci}
413862306a36Sopenharmony_ci
413962306a36Sopenharmony_cisub find_mailer {
414062306a36Sopenharmony_ci    my ($mailer) = @_;
414162306a36Sopenharmony_ci
414262306a36Sopenharmony_ci    my @paths = split /:/, $ENV{PATH};
414362306a36Sopenharmony_ci
414462306a36Sopenharmony_ci    # sendmail is usually in /usr/sbin
414562306a36Sopenharmony_ci    $paths[$#paths + 1] = "/usr/sbin";
414662306a36Sopenharmony_ci
414762306a36Sopenharmony_ci    foreach my $path (@paths) {
414862306a36Sopenharmony_ci	if (-x "$path/$mailer") {
414962306a36Sopenharmony_ci	    return $path;
415062306a36Sopenharmony_ci	}
415162306a36Sopenharmony_ci    }
415262306a36Sopenharmony_ci
415362306a36Sopenharmony_ci    return undef;
415462306a36Sopenharmony_ci}
415562306a36Sopenharmony_ci
415662306a36Sopenharmony_cisub do_send_mail {
415762306a36Sopenharmony_ci    my ($subject, $message, $file) = @_;
415862306a36Sopenharmony_ci
415962306a36Sopenharmony_ci    if (!defined($mail_path)) {
416062306a36Sopenharmony_ci	# find the mailer
416162306a36Sopenharmony_ci	$mail_path = find_mailer $mailer;
416262306a36Sopenharmony_ci	if (!defined($mail_path)) {
416362306a36Sopenharmony_ci	    die "\nCan not find $mailer in PATH\n";
416462306a36Sopenharmony_ci	}
416562306a36Sopenharmony_ci    }
416662306a36Sopenharmony_ci
416762306a36Sopenharmony_ci    my $header_file = "$tmpdir/header";
416862306a36Sopenharmony_ci    open (HEAD, ">$header_file") or die "Can not create $header_file\n";
416962306a36Sopenharmony_ci    print HEAD "To: $mailto\n";
417062306a36Sopenharmony_ci    print HEAD "Subject: $subject\n\n";
417162306a36Sopenharmony_ci    print HEAD "$message\n";
417262306a36Sopenharmony_ci    close HEAD;
417362306a36Sopenharmony_ci
417462306a36Sopenharmony_ci    if (!defined($mail_command)) {
417562306a36Sopenharmony_ci	if ($mailer eq "mail" || $mailer eq "mailx") {
417662306a36Sopenharmony_ci	    $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO";
417762306a36Sopenharmony_ci	} elsif ($mailer eq "sendmail" ) {
417862306a36Sopenharmony_ci	    $mail_command =  "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -t \$MAILTO";
417962306a36Sopenharmony_ci	} else {
418062306a36Sopenharmony_ci	    die "\nYour mailer: $mailer is not supported.\n";
418162306a36Sopenharmony_ci	}
418262306a36Sopenharmony_ci    }
418362306a36Sopenharmony_ci
418462306a36Sopenharmony_ci    if (defined($file)) {
418562306a36Sopenharmony_ci	$mail_command =~ s/\$BODY_FILE/$file/g;
418662306a36Sopenharmony_ci    } else {
418762306a36Sopenharmony_ci	$mail_command =~ s/\$BODY_FILE//g;
418862306a36Sopenharmony_ci    }
418962306a36Sopenharmony_ci
419062306a36Sopenharmony_ci    $mail_command =~ s/\$HEADER_FILE/$header_file/g;
419162306a36Sopenharmony_ci    $mail_command =~ s/\$MAILER/$mailer/g;
419262306a36Sopenharmony_ci    $mail_command =~ s/\$MAIL_PATH/$mail_path/g;
419362306a36Sopenharmony_ci    $mail_command =~ s/\$MAILTO/$mailto/g;
419462306a36Sopenharmony_ci    $mail_command =~ s/\$SUBJECT/$subject/g;
419562306a36Sopenharmony_ci    $mail_command =~ s/\$MESSAGE/$message/g;
419662306a36Sopenharmony_ci
419762306a36Sopenharmony_ci    my $ret = run_command $mail_command;
419862306a36Sopenharmony_ci    if (!$ret && defined($file)) {
419962306a36Sopenharmony_ci	# try again without the file
420062306a36Sopenharmony_ci	$message .= "\n\n*** FAILED TO SEND LOG ***\n\n";
420162306a36Sopenharmony_ci	do_send_email($subject, $message);
420262306a36Sopenharmony_ci    }
420362306a36Sopenharmony_ci}
420462306a36Sopenharmony_ci
420562306a36Sopenharmony_cisub send_email {
420662306a36Sopenharmony_ci    if (defined($mailto)) {
420762306a36Sopenharmony_ci	if (!defined($mailer)) {
420862306a36Sopenharmony_ci	    doprint "No email sent: email or mailer not specified in config.\n";
420962306a36Sopenharmony_ci	    return;
421062306a36Sopenharmony_ci	}
421162306a36Sopenharmony_ci	do_send_mail @_;
421262306a36Sopenharmony_ci    }
421362306a36Sopenharmony_ci}
421462306a36Sopenharmony_ci
421562306a36Sopenharmony_cisub cancel_test {
421662306a36Sopenharmony_ci    if ($monitor_cnt) {
421762306a36Sopenharmony_ci	end_monitor;
421862306a36Sopenharmony_ci    }
421962306a36Sopenharmony_ci    if ($email_when_canceled) {
422062306a36Sopenharmony_ci	my $name = get_test_name;
422162306a36Sopenharmony_ci	send_email("KTEST: Your [$name] test was cancelled",
422262306a36Sopenharmony_ci	    "Your test started at $script_start_time was cancelled: sig int");
422362306a36Sopenharmony_ci    }
422462306a36Sopenharmony_ci    die "\nCaught Sig Int, test interrupted: $!\n"
422562306a36Sopenharmony_ci}
422662306a36Sopenharmony_ci
422762306a36Sopenharmony_ci$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl [config-file]\n";
422862306a36Sopenharmony_ci
422962306a36Sopenharmony_ciif ($#ARGV == 0) {
423062306a36Sopenharmony_ci    $ktest_config = $ARGV[0];
423162306a36Sopenharmony_ci    if (! -f $ktest_config) {
423262306a36Sopenharmony_ci	print "$ktest_config does not exist.\n";
423362306a36Sopenharmony_ci	if (!read_yn "Create it?") {
423462306a36Sopenharmony_ci	    exit 0;
423562306a36Sopenharmony_ci	}
423662306a36Sopenharmony_ci    }
423762306a36Sopenharmony_ci}
423862306a36Sopenharmony_ci
423962306a36Sopenharmony_ciif (! -f $ktest_config) {
424062306a36Sopenharmony_ci    $newconfig = 1;
424162306a36Sopenharmony_ci    get_test_case;
424262306a36Sopenharmony_ci    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
424362306a36Sopenharmony_ci    print OUT << "EOF"
424462306a36Sopenharmony_ci# Generated by ktest.pl
424562306a36Sopenharmony_ci#
424662306a36Sopenharmony_ci
424762306a36Sopenharmony_ci# PWD is a ktest.pl variable that will result in the process working
424862306a36Sopenharmony_ci# directory that ktest.pl is executed in.
424962306a36Sopenharmony_ci
425062306a36Sopenharmony_ci# THIS_DIR is automatically assigned the PWD of the path that generated
425162306a36Sopenharmony_ci# the config file. It is best to use this variable when assigning other
425262306a36Sopenharmony_ci# directory paths within this directory. This allows you to easily
425362306a36Sopenharmony_ci# move the test cases to other locations or to other machines.
425462306a36Sopenharmony_ci#
425562306a36Sopenharmony_ciTHIS_DIR := $variable{"PWD"}
425662306a36Sopenharmony_ci
425762306a36Sopenharmony_ci# Define each test with TEST_START
425862306a36Sopenharmony_ci# The config options below it will override the defaults
425962306a36Sopenharmony_ciTEST_START
426062306a36Sopenharmony_ciTEST_TYPE = $default{"TEST_TYPE"}
426162306a36Sopenharmony_ci
426262306a36Sopenharmony_ciDEFAULTS
426362306a36Sopenharmony_ciEOF
426462306a36Sopenharmony_ci;
426562306a36Sopenharmony_ci    close(OUT);
426662306a36Sopenharmony_ci}
426762306a36Sopenharmony_ciread_config $ktest_config;
426862306a36Sopenharmony_ci
426962306a36Sopenharmony_ciif (defined($opt{"LOG_FILE"})) {
427062306a36Sopenharmony_ci    $opt{"LOG_FILE"} = eval_option("LOG_FILE", $opt{"LOG_FILE"}, -1);
427162306a36Sopenharmony_ci}
427262306a36Sopenharmony_ci
427362306a36Sopenharmony_ci# Append any configs entered in manually to the config file.
427462306a36Sopenharmony_cimy @new_configs = keys %entered_configs;
427562306a36Sopenharmony_ciif ($#new_configs >= 0) {
427662306a36Sopenharmony_ci    print "\nAppending entered in configs to $ktest_config\n";
427762306a36Sopenharmony_ci    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
427862306a36Sopenharmony_ci    foreach my $config (@new_configs) {
427962306a36Sopenharmony_ci	print OUT "$config = $entered_configs{$config}\n";
428062306a36Sopenharmony_ci	$opt{$config} = process_variables($entered_configs{$config});
428162306a36Sopenharmony_ci    }
428262306a36Sopenharmony_ci}
428362306a36Sopenharmony_ci
428462306a36Sopenharmony_ciif (defined($opt{"LOG_FILE"})) {
428562306a36Sopenharmony_ci    if ($opt{"CLEAR_LOG"}) {
428662306a36Sopenharmony_ci	unlink $opt{"LOG_FILE"};
428762306a36Sopenharmony_ci    }
428862306a36Sopenharmony_ci    open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
428962306a36Sopenharmony_ci    LOG->autoflush(1);
429062306a36Sopenharmony_ci}
429162306a36Sopenharmony_ci
429262306a36Sopenharmony_cidoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
429362306a36Sopenharmony_ci
429462306a36Sopenharmony_cifor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
429562306a36Sopenharmony_ci
429662306a36Sopenharmony_ci    if (!$i) {
429762306a36Sopenharmony_ci	doprint "DEFAULT OPTIONS:\n";
429862306a36Sopenharmony_ci    } else {
429962306a36Sopenharmony_ci	doprint "\nTEST $i OPTIONS";
430062306a36Sopenharmony_ci	if (defined($repeat_tests{$i})) {
430162306a36Sopenharmony_ci	    $repeat = $repeat_tests{$i};
430262306a36Sopenharmony_ci	    doprint " ITERATE $repeat";
430362306a36Sopenharmony_ci	}
430462306a36Sopenharmony_ci	doprint "\n";
430562306a36Sopenharmony_ci    }
430662306a36Sopenharmony_ci
430762306a36Sopenharmony_ci    foreach my $option (sort keys %opt) {
430862306a36Sopenharmony_ci	if ($option =~ /\[(\d+)\]$/) {
430962306a36Sopenharmony_ci	    next if ($i != $1);
431062306a36Sopenharmony_ci	} else {
431162306a36Sopenharmony_ci	    next if ($i);
431262306a36Sopenharmony_ci	}
431362306a36Sopenharmony_ci
431462306a36Sopenharmony_ci	doprint "$option = $opt{$option}\n";
431562306a36Sopenharmony_ci    }
431662306a36Sopenharmony_ci}
431762306a36Sopenharmony_ci
431862306a36Sopenharmony_ci$SIG{INT} = qw(cancel_test);
431962306a36Sopenharmony_ci
432062306a36Sopenharmony_ci# First we need to do is the builds
432162306a36Sopenharmony_cifor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
432262306a36Sopenharmony_ci
432362306a36Sopenharmony_ci    # Do not reboot on failing test options
432462306a36Sopenharmony_ci    $no_reboot = 1;
432562306a36Sopenharmony_ci    $reboot_success = 0;
432662306a36Sopenharmony_ci
432762306a36Sopenharmony_ci    $have_version = 0;
432862306a36Sopenharmony_ci
432962306a36Sopenharmony_ci    $iteration = $i;
433062306a36Sopenharmony_ci
433162306a36Sopenharmony_ci    $build_time = 0;
433262306a36Sopenharmony_ci    $install_time = 0;
433362306a36Sopenharmony_ci    $reboot_time = 0;
433462306a36Sopenharmony_ci    $test_time = 0;
433562306a36Sopenharmony_ci
433662306a36Sopenharmony_ci    undef %force_config;
433762306a36Sopenharmony_ci
433862306a36Sopenharmony_ci    my $makecmd = set_test_option("MAKE_CMD", $i);
433962306a36Sopenharmony_ci
434062306a36Sopenharmony_ci    $outputdir = set_test_option("OUTPUT_DIR", $i);
434162306a36Sopenharmony_ci    $builddir = set_test_option("BUILD_DIR", $i);
434262306a36Sopenharmony_ci
434362306a36Sopenharmony_ci    chdir $builddir || dodie "can't change directory to $builddir";
434462306a36Sopenharmony_ci
434562306a36Sopenharmony_ci    if (!-d $outputdir) {
434662306a36Sopenharmony_ci	mkpath($outputdir) or
434762306a36Sopenharmony_ci	    dodie "can't create $outputdir";
434862306a36Sopenharmony_ci    }
434962306a36Sopenharmony_ci
435062306a36Sopenharmony_ci    $make = "$makecmd O=$outputdir";
435162306a36Sopenharmony_ci
435262306a36Sopenharmony_ci    # Load all the options into their mapped variable names
435362306a36Sopenharmony_ci    foreach my $opt (keys %option_map) {
435462306a36Sopenharmony_ci	${$option_map{$opt}} = set_test_option($opt, $i);
435562306a36Sopenharmony_ci    }
435662306a36Sopenharmony_ci
435762306a36Sopenharmony_ci    $start_minconfig_defined = 1;
435862306a36Sopenharmony_ci
435962306a36Sopenharmony_ci    # The first test may override the PRE_KTEST option
436062306a36Sopenharmony_ci    if ($i == 1) {
436162306a36Sopenharmony_ci	if (defined($pre_ktest)) {
436262306a36Sopenharmony_ci	    doprint "\n";
436362306a36Sopenharmony_ci	    run_command $pre_ktest;
436462306a36Sopenharmony_ci	}
436562306a36Sopenharmony_ci	if ($email_when_started) {
436662306a36Sopenharmony_ci	    my $name = get_test_name;
436762306a36Sopenharmony_ci	    send_email("KTEST: Your [$name] test was started",
436862306a36Sopenharmony_ci		"Your test was started on $script_start_time");
436962306a36Sopenharmony_ci	}
437062306a36Sopenharmony_ci    }
437162306a36Sopenharmony_ci
437262306a36Sopenharmony_ci    # Any test can override the POST_KTEST option
437362306a36Sopenharmony_ci    # The last test takes precedence.
437462306a36Sopenharmony_ci    if (defined($post_ktest)) {
437562306a36Sopenharmony_ci	$final_post_ktest = $post_ktest;
437662306a36Sopenharmony_ci    }
437762306a36Sopenharmony_ci
437862306a36Sopenharmony_ci    if (!defined($start_minconfig)) {
437962306a36Sopenharmony_ci	$start_minconfig_defined = 0;
438062306a36Sopenharmony_ci	$start_minconfig = $minconfig;
438162306a36Sopenharmony_ci    }
438262306a36Sopenharmony_ci
438362306a36Sopenharmony_ci    if (!-d $tmpdir) {
438462306a36Sopenharmony_ci	mkpath($tmpdir) or
438562306a36Sopenharmony_ci	    dodie "can't create $tmpdir";
438662306a36Sopenharmony_ci    }
438762306a36Sopenharmony_ci
438862306a36Sopenharmony_ci    $ENV{"SSH_USER"} = $ssh_user;
438962306a36Sopenharmony_ci    $ENV{"MACHINE"} = $machine;
439062306a36Sopenharmony_ci
439162306a36Sopenharmony_ci    $buildlog = "$tmpdir/buildlog-$machine";
439262306a36Sopenharmony_ci    $testlog = "$tmpdir/testlog-$machine";
439362306a36Sopenharmony_ci    $dmesg = "$tmpdir/dmesg-$machine";
439462306a36Sopenharmony_ci    $output_config = "$outputdir/.config";
439562306a36Sopenharmony_ci
439662306a36Sopenharmony_ci    if (!$buildonly) {
439762306a36Sopenharmony_ci	$target = "$ssh_user\@$machine";
439862306a36Sopenharmony_ci	if (($reboot_type eq "grub") or ($reboot_type eq "grub2bls")) {
439962306a36Sopenharmony_ci	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
440062306a36Sopenharmony_ci	} elsif ($reboot_type eq "grub2") {
440162306a36Sopenharmony_ci	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
440262306a36Sopenharmony_ci	    dodie "GRUB_FILE not defined" if (!defined($grub_file));
440362306a36Sopenharmony_ci	} elsif ($reboot_type eq "syslinux") {
440462306a36Sopenharmony_ci	    dodie "SYSLINUX_LABEL not defined" if (!defined($syslinux_label));
440562306a36Sopenharmony_ci	}
440662306a36Sopenharmony_ci    }
440762306a36Sopenharmony_ci
440862306a36Sopenharmony_ci    my $run_type = $build_type;
440962306a36Sopenharmony_ci    if ($test_type eq "patchcheck") {
441062306a36Sopenharmony_ci	$run_type = $patchcheck_type;
441162306a36Sopenharmony_ci    } elsif ($test_type eq "bisect") {
441262306a36Sopenharmony_ci	$run_type = $bisect_type;
441362306a36Sopenharmony_ci    } elsif ($test_type eq "config_bisect") {
441462306a36Sopenharmony_ci	$run_type = $config_bisect_type;
441562306a36Sopenharmony_ci    } elsif ($test_type eq "make_min_config") {
441662306a36Sopenharmony_ci	$run_type = "";
441762306a36Sopenharmony_ci    } elsif ($test_type eq "make_warnings_file") {
441862306a36Sopenharmony_ci	$run_type = "";
441962306a36Sopenharmony_ci    }
442062306a36Sopenharmony_ci
442162306a36Sopenharmony_ci    # mistake in config file?
442262306a36Sopenharmony_ci    if (!defined($run_type)) {
442362306a36Sopenharmony_ci	$run_type = "ERROR";
442462306a36Sopenharmony_ci    }
442562306a36Sopenharmony_ci
442662306a36Sopenharmony_ci    my $installme = "";
442762306a36Sopenharmony_ci    $installme = " no_install" if ($no_install);
442862306a36Sopenharmony_ci
442962306a36Sopenharmony_ci    my $name = "";
443062306a36Sopenharmony_ci
443162306a36Sopenharmony_ci    if (defined($test_name)) {
443262306a36Sopenharmony_ci	$name = " ($test_name)";
443362306a36Sopenharmony_ci    }
443462306a36Sopenharmony_ci
443562306a36Sopenharmony_ci    doprint "\n\n";
443662306a36Sopenharmony_ci
443762306a36Sopenharmony_ci    if (defined($opt{"LOG_FILE"})) {
443862306a36Sopenharmony_ci	$test_log_start = tell(LOG);
443962306a36Sopenharmony_ci    }
444062306a36Sopenharmony_ci
444162306a36Sopenharmony_ci    doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n";
444262306a36Sopenharmony_ci
444362306a36Sopenharmony_ci    if (defined($pre_test)) {
444462306a36Sopenharmony_ci	my $ret = run_command $pre_test;
444562306a36Sopenharmony_ci	if (!$ret && defined($pre_test_die) &&
444662306a36Sopenharmony_ci	    $pre_test_die) {
444762306a36Sopenharmony_ci		dodie "failed to pre_test\n";
444862306a36Sopenharmony_ci	}
444962306a36Sopenharmony_ci    }
445062306a36Sopenharmony_ci
445162306a36Sopenharmony_ci    unlink $dmesg;
445262306a36Sopenharmony_ci    unlink $buildlog;
445362306a36Sopenharmony_ci    unlink $testlog;
445462306a36Sopenharmony_ci
445562306a36Sopenharmony_ci    if (defined($addconfig)) {
445662306a36Sopenharmony_ci	my $min = $minconfig;
445762306a36Sopenharmony_ci	if (!defined($minconfig)) {
445862306a36Sopenharmony_ci	    $min = "";
445962306a36Sopenharmony_ci	}
446062306a36Sopenharmony_ci	run_command "cat $addconfig $min > $tmpdir/add_config" or
446162306a36Sopenharmony_ci	    dodie "Failed to create temp config";
446262306a36Sopenharmony_ci	$minconfig = "$tmpdir/add_config";
446362306a36Sopenharmony_ci    }
446462306a36Sopenharmony_ci
446562306a36Sopenharmony_ci    if (defined($checkout)) {
446662306a36Sopenharmony_ci	run_command "git checkout $checkout" or
446762306a36Sopenharmony_ci	    dodie "failed to checkout $checkout";
446862306a36Sopenharmony_ci    }
446962306a36Sopenharmony_ci
447062306a36Sopenharmony_ci    $no_reboot = 0;
447162306a36Sopenharmony_ci
447262306a36Sopenharmony_ci    # A test may opt to not reboot the box
447362306a36Sopenharmony_ci    if ($reboot_on_success) {
447462306a36Sopenharmony_ci	$reboot_success = 1;
447562306a36Sopenharmony_ci    }
447662306a36Sopenharmony_ci
447762306a36Sopenharmony_ci    if ($test_type eq "bisect") {
447862306a36Sopenharmony_ci	bisect $i;
447962306a36Sopenharmony_ci	next;
448062306a36Sopenharmony_ci    } elsif ($test_type eq "config_bisect") {
448162306a36Sopenharmony_ci	config_bisect $i;
448262306a36Sopenharmony_ci	next;
448362306a36Sopenharmony_ci    } elsif ($test_type eq "patchcheck") {
448462306a36Sopenharmony_ci	patchcheck $i;
448562306a36Sopenharmony_ci	next;
448662306a36Sopenharmony_ci    } elsif ($test_type eq "make_min_config") {
448762306a36Sopenharmony_ci	make_min_config $i;
448862306a36Sopenharmony_ci	next;
448962306a36Sopenharmony_ci    } elsif ($test_type eq "make_warnings_file") {
449062306a36Sopenharmony_ci	$no_reboot = 1;
449162306a36Sopenharmony_ci	make_warnings_file $i;
449262306a36Sopenharmony_ci	next;
449362306a36Sopenharmony_ci    }
449462306a36Sopenharmony_ci
449562306a36Sopenharmony_ci    if ($build_type ne "nobuild") {
449662306a36Sopenharmony_ci	build $build_type or next;
449762306a36Sopenharmony_ci	check_buildlog or next;
449862306a36Sopenharmony_ci    }
449962306a36Sopenharmony_ci
450062306a36Sopenharmony_ci    if ($test_type eq "install") {
450162306a36Sopenharmony_ci	get_version;
450262306a36Sopenharmony_ci	install;
450362306a36Sopenharmony_ci	success $i;
450462306a36Sopenharmony_ci	next;
450562306a36Sopenharmony_ci    }
450662306a36Sopenharmony_ci
450762306a36Sopenharmony_ci    if ($test_type ne "build") {
450862306a36Sopenharmony_ci	my $failed = 0;
450962306a36Sopenharmony_ci	start_monitor_and_install or $failed = 1;
451062306a36Sopenharmony_ci
451162306a36Sopenharmony_ci	if (!$failed && $test_type ne "boot" && defined($run_test)) {
451262306a36Sopenharmony_ci	    do_run_test or $failed = 1;
451362306a36Sopenharmony_ci	}
451462306a36Sopenharmony_ci	end_monitor;
451562306a36Sopenharmony_ci	if ($failed) {
451662306a36Sopenharmony_ci	    print_times;
451762306a36Sopenharmony_ci	    next;
451862306a36Sopenharmony_ci	}
451962306a36Sopenharmony_ci    }
452062306a36Sopenharmony_ci
452162306a36Sopenharmony_ci    print_times;
452262306a36Sopenharmony_ci
452362306a36Sopenharmony_ci    success $i;
452462306a36Sopenharmony_ci}
452562306a36Sopenharmony_ci
452662306a36Sopenharmony_ciif (defined($final_post_ktest)) {
452762306a36Sopenharmony_ci
452862306a36Sopenharmony_ci    my $cp_final_post_ktest = eval_kernel_version $final_post_ktest;
452962306a36Sopenharmony_ci    run_command $cp_final_post_ktest;
453062306a36Sopenharmony_ci}
453162306a36Sopenharmony_ci
453262306a36Sopenharmony_ciif ($opt{"POWEROFF_ON_SUCCESS"}) {
453362306a36Sopenharmony_ci    halt;
453462306a36Sopenharmony_ci} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) {
453562306a36Sopenharmony_ci    reboot_to_good;
453662306a36Sopenharmony_ci} elsif (defined($switch_to_good)) {
453762306a36Sopenharmony_ci    # still need to get to the good kernel
453862306a36Sopenharmony_ci    run_command $switch_to_good;
453962306a36Sopenharmony_ci}
454062306a36Sopenharmony_ci
454162306a36Sopenharmony_cidoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
454262306a36Sopenharmony_ci
454362306a36Sopenharmony_ciif ($email_when_finished) {
454462306a36Sopenharmony_ci    send_email("KTEST: Your test has finished!",
454562306a36Sopenharmony_ci	"$successes of $opt{NUM_TESTS} tests started at $script_start_time were successful!");
454662306a36Sopenharmony_ci}
454762306a36Sopenharmony_ci
454862306a36Sopenharmony_ciif (defined($opt{"LOG_FILE"})) {
454962306a36Sopenharmony_ci    print "\n See $opt{LOG_FILE} for the record of results.\n\n";
455062306a36Sopenharmony_ci    close LOG;
455162306a36Sopenharmony_ci}
455262306a36Sopenharmony_ci
455362306a36Sopenharmony_ciexit 0;
455462306a36Sopenharmony_ci
455562306a36Sopenharmony_ci##
455662306a36Sopenharmony_ci# The following are here to standardize tabs/spaces/etc across the most likely editors
455762306a36Sopenharmony_ci###
455862306a36Sopenharmony_ci
455962306a36Sopenharmony_ci# Local Variables:
456062306a36Sopenharmony_ci# mode: perl
456162306a36Sopenharmony_ci# End:
456262306a36Sopenharmony_ci# vim: softtabstop=4
4563