ktest.pl 99.7 KB
Newer Older
S
Steven Rostedt 已提交
1
#!/usr/bin/perl -w
2
# SPDX-License-Identifier: GPL-2.0-only
3
#
4
# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
5
#
S
Steven Rostedt 已提交
6 7 8 9

use strict;
use IPC::Open2;
use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
10 11
use File::Path qw(mkpath);
use File::Copy qw(cp);
S
Steven Rostedt 已提交
12
use FileHandle;
13
use FindBin;
14
use IO::Handle;
S
Steven Rostedt 已提交
15

16 17
my $VERSION = "0.2";

S
Steven Rostedt 已提交
18 19 20
$| = 1;

my %opt;
21 22
my %repeat_tests;
my %repeats;
23
my %evals;
S
Steven Rostedt 已提交
24 25

#default opts
26
my %default = (
27
    "MAILER"			=> "sendmail",  # default mailer
T
Tim Tianyang Chen 已提交
28 29 30 31
    "EMAIL_ON_ERROR"		=> 1,
    "EMAIL_WHEN_FINISHED"	=> 1,
    "EMAIL_WHEN_CANCELED"	=> 0,
    "EMAIL_WHEN_STARTED"	=> 0,
32 33
    "NUM_TESTS"			=> 1,
    "TEST_TYPE"			=> "build",
34
    "BUILD_TYPE"		=> "oldconfig",
35
    "MAKE_CMD"			=> "make",
36
    "CLOSE_CONSOLE_SIGNAL"	=> "INT",
37 38 39 40 41 42 43 44 45 46 47 48 49 50
    "TIMEOUT"			=> 120,
    "TMP_DIR"			=> "/tmp/ktest/\${MACHINE}",
    "SLEEP_TIME"		=> 60,	# sleep time between tests
    "BUILD_NOCLEAN"		=> 0,
    "REBOOT_ON_ERROR"		=> 0,
    "POWEROFF_ON_ERROR"		=> 0,
    "REBOOT_ON_SUCCESS"		=> 1,
    "POWEROFF_ON_SUCCESS"	=> 0,
    "BUILD_OPTIONS"		=> "",
    "BISECT_SLEEP_TIME"		=> 60,   # sleep time between bisects
    "PATCHCHECK_SLEEP_TIME"	=> 60, # sleep time between patch checks
    "CLEAR_LOG"			=> 0,
    "BISECT_MANUAL"		=> 0,
    "BISECT_SKIP"		=> 1,
51
    "BISECT_TRIES"		=> 1,
52
    "MIN_CONFIG_TYPE"		=> "boot",
53 54 55 56 57 58 59
    "SUCCESS_LINE"		=> "login:",
    "DETECT_TRIPLE_FAULT"	=> 1,
    "NO_INSTALL"		=> 0,
    "BOOTED_TIMEOUT"		=> 1,
    "DIE_ON_FAILURE"		=> 1,
    "SSH_EXEC"			=> "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND",
    "SCP_TO_TARGET"		=> "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE",
60
    "SCP_TO_TARGET_INSTALL"	=> "\${SCP_TO_TARGET}",
61
    "REBOOT"			=> "ssh \$SSH_USER\@\$MACHINE reboot",
62
    "REBOOT_RETURN_CODE"	=> 255,
63 64 65
    "STOP_AFTER_SUCCESS"	=> 10,
    "STOP_AFTER_FAILURE"	=> 60,
    "STOP_TEST_AFTER"		=> 600,
66
    "MAX_MONITOR_WAIT"		=> 1800,
S
Steven Rostedt 已提交
67
    "GRUB_REBOOT"		=> "grub2-reboot",
68
    "GRUB_BLS_GET"		=> "grubby --info=ALL",
69 70
    "SYSLINUX"			=> "extlinux",
    "SYSLINUX_PATH"		=> "/boot/extlinux",
71
    "CONNECT_TIMEOUT"		=> 25,
72 73 74

# required, and we will ask users if they don't have them but we keep the default
# value something that is common.
75 76 77 78 79
    "REBOOT_TYPE"		=> "grub",
    "LOCALVERSION"		=> "-test",
    "SSH_USER"			=> "root",
    "BUILD_TARGET"	 	=> "arch/x86/boot/bzImage",
    "TARGET_IMAGE"		=> "/boot/vmlinuz-test",
80 81 82

    "LOG_FILE"			=> undef,
    "IGNORE_UNUSED"		=> 0,
83
);
S
Steven Rostedt 已提交
84

85 86
my $test_log_start = 0;

87
my $ktest_config = "ktest.conf";
S
Steven Rostedt 已提交
88
my $version;
89
my $have_version = 0;
90
my $machine;
91
my $last_machine;
92
my $ssh_user;
93 94 95
my $tmpdir;
my $builddir;
my $outputdir;
96
my $output_config;
97
my $test_type;
98
my $build_type;
99
my $build_options;
100 101 102 103
my $final_post_ktest;
my $pre_ktest;
my $post_ktest;
my $pre_test;
104
my $pre_test_die;
105
my $post_test;
106 107 108 109
my $pre_build;
my $post_build;
my $pre_build_die;
my $post_build_die;
110 111 112
my $reboot_type;
my $reboot_script;
my $power_cycle;
113
my $reboot;
114
my $reboot_return_code;
115
my $reboot_on_error;
116 117
my $switch_to_good;
my $switch_to_test;
118
my $poweroff_on_error;
119
my $reboot_on_success;
120
my $die_on_failure;
121 122
my $powercycle_after_reboot;
my $poweroff_after_halt;
123
my $max_monitor_wait;
124 125
my $ssh_exec;
my $scp_to_target;
126
my $scp_to_target_install;
127 128
my $power_off;
my $grub_menu;
129
my $last_grub_menu;
S
Steven Rostedt 已提交
130
my $grub_file;
S
Steven Rostedt 已提交
131
my $grub_number;
S
Steven Rostedt 已提交
132
my $grub_reboot;
133
my $grub_bls_get;
134 135 136
my $syslinux;
my $syslinux_path;
my $syslinux_label;
S
Steven Rostedt 已提交
137 138
my $target;
my $make;
S
Steven Rostedt 已提交
139
my $pre_install;
140
my $post_install;
141
my $no_install;
142
my $noclean;
143
my $minconfig;
144
my $start_minconfig;
145
my $start_minconfig_defined;
146
my $output_minconfig;
147
my $minconfig_type;
148
my $use_output_minconfig;
149
my $warnings_file;
150
my $ignore_config;
151
my $ignore_errors;
152
my $addconfig;
153
my $in_bisect = 0;
154
my $bisect_bad_commit = "";
155
my $reverse_bisect;
S
Steven Rostedt 已提交
156
my $bisect_manual;
S
Steven Rostedt 已提交
157
my $bisect_skip;
158
my $bisect_tries;
159
my $config_bisect_good;
160 161 162 163 164
my $bisect_ret_good;
my $bisect_ret_bad;
my $bisect_ret_skip;
my $bisect_ret_abort;
my $bisect_ret_default;
S
Steven Rostedt 已提交
165
my $in_patchcheck = 0;
166
my $run_test;
167
my $buildlog;
R
Rabin Vincent 已提交
168
my $testlog;
169 170 171 172
my $dmesg;
my $monitor_fp;
my $monitor_pid;
my $monitor_cnt = 0;
173 174
my $sleep_time;
my $bisect_sleep_time;
175
my $patchcheck_sleep_time;
176
my $ignore_warnings;
177
my $store_failures;
178
my $store_successes;
S
Steven Rostedt 已提交
179
my $test_name;
180
my $timeout;
181
my $connect_timeout;
182
my $config_bisect_exec;
183
my $booted_timeout;
184
my $detect_triplefault;
185
my $console;
186
my $close_console_signal;
187
my $reboot_success_line;
188
my $success_line;
189 190
my $stop_after_success;
my $stop_after_failure;
191
my $stop_test_after;
192 193
my $build_target;
my $target_image;
194
my $checkout;
195
my $localversion;
196
my $iteration = 0;
197
my $successes = 0;
198
my $stty_orig;
199
my $run_command_status = 0;
S
Steven Rostedt 已提交
200

201 202 203 204 205 206 207 208 209 210 211
my $bisect_good;
my $bisect_bad;
my $bisect_type;
my $bisect_start;
my $bisect_replay;
my $bisect_files;
my $bisect_reverse;
my $bisect_check;

my $config_bisect;
my $config_bisect_type;
212
my $config_bisect_check;
213 214 215

my $patchcheck_type;
my $patchcheck_start;
216
my $patchcheck_cherry;
217 218
my $patchcheck_end;

219 220 221 222 223
my $build_time;
my $install_time;
my $reboot_time;
my $test_time;

224 225 226
my $pwd;
my $dirname = $FindBin::Bin;

T
Tim Tianyang Chen 已提交
227 228
my $mailto;
my $mailer;
229
my $mail_path;
230
my $mail_max_size;
231
my $mail_command;
T
Tim Tianyang Chen 已提交
232 233 234 235 236 237 238
my $email_on_error;
my $email_when_finished;
my $email_when_started;
my $email_when_canceled;

my $script_start_time = localtime();

239
# set when a test is something other that just building or install
240 241 242
# which would require more options.
my $buildonly = 1;

243 244 245
# tell build not to worry about warnings, even when WARNINGS_FILE is set
my $warnings_ok = 0;

246 247 248
# set when creating a new config
my $newconfig = 0;

249 250
my %entered_configs;
my %config_help;
251
my %variable;
252 253 254

# force_config is the list of configs that we force enabled (or disabled)
# in a .config file. The MIN_CONFIG and ADD_CONFIG configs.
255
my %force_config;
256

257 258 259
# do not force reboots on config problems
my $no_reboot = 1;

260 261 262
# reboot on success
my $reboot_success = 0;

263
my %option_map = (
264 265 266
    "MAILTO"			=> \$mailto,
    "MAILER"			=> \$mailer,
    "MAIL_PATH"			=> \$mail_path,
267
    "MAIL_MAX_SIZE"		=> \$mail_max_size,
268
    "MAIL_COMMAND"		=> \$mail_command,
T
Tim Tianyang Chen 已提交
269 270 271 272
    "EMAIL_ON_ERROR"		=> \$email_on_error,
    "EMAIL_WHEN_FINISHED"	=> \$email_when_finished,
    "EMAIL_WHEN_STARTED"	=> \$email_when_started,
    "EMAIL_WHEN_CANCELED"	=> \$email_when_canceled,
273 274 275 276 277 278
    "MACHINE"			=> \$machine,
    "SSH_USER"			=> \$ssh_user,
    "TMP_DIR"			=> \$tmpdir,
    "OUTPUT_DIR"		=> \$outputdir,
    "BUILD_DIR"			=> \$builddir,
    "TEST_TYPE"			=> \$test_type,
279 280 281
    "PRE_KTEST"			=> \$pre_ktest,
    "POST_KTEST"		=> \$post_ktest,
    "PRE_TEST"			=> \$pre_test,
282
    "PRE_TEST_DIE"		=> \$pre_test_die,
283
    "POST_TEST"			=> \$post_test,
284 285 286 287 288 289 290 291
    "BUILD_TYPE"		=> \$build_type,
    "BUILD_OPTIONS"		=> \$build_options,
    "PRE_BUILD"			=> \$pre_build,
    "POST_BUILD"		=> \$post_build,
    "PRE_BUILD_DIE"		=> \$pre_build_die,
    "POST_BUILD_DIE"		=> \$post_build_die,
    "POWER_CYCLE"		=> \$power_cycle,
    "REBOOT"			=> \$reboot,
292
    "REBOOT_RETURN_CODE"	=> \$reboot_return_code,
293 294 295 296
    "BUILD_NOCLEAN"		=> \$noclean,
    "MIN_CONFIG"		=> \$minconfig,
    "OUTPUT_MIN_CONFIG"		=> \$output_minconfig,
    "START_MIN_CONFIG"		=> \$start_minconfig,
297
    "MIN_CONFIG_TYPE"		=> \$minconfig_type,
298
    "USE_OUTPUT_MIN_CONFIG"	=> \$use_output_minconfig,
299
    "WARNINGS_FILE"		=> \$warnings_file,
300 301 302 303 304
    "IGNORE_CONFIG"		=> \$ignore_config,
    "TEST"			=> \$run_test,
    "ADD_CONFIG"		=> \$addconfig,
    "REBOOT_TYPE"		=> \$reboot_type,
    "GRUB_MENU"			=> \$grub_menu,
S
Steven Rostedt 已提交
305 306
    "GRUB_FILE"			=> \$grub_file,
    "GRUB_REBOOT"		=> \$grub_reboot,
307
    "GRUB_BLS_GET"		=> \$grub_bls_get,
308 309 310
    "SYSLINUX"			=> \$syslinux,
    "SYSLINUX_PATH"		=> \$syslinux_path,
    "SYSLINUX_LABEL"		=> \$syslinux_label,
S
Steven Rostedt 已提交
311
    "PRE_INSTALL"		=> \$pre_install,
312 313 314 315 316 317 318
    "POST_INSTALL"		=> \$post_install,
    "NO_INSTALL"		=> \$no_install,
    "REBOOT_SCRIPT"		=> \$reboot_script,
    "REBOOT_ON_ERROR"		=> \$reboot_on_error,
    "SWITCH_TO_GOOD"		=> \$switch_to_good,
    "SWITCH_TO_TEST"		=> \$switch_to_test,
    "POWEROFF_ON_ERROR"		=> \$poweroff_on_error,
319
    "REBOOT_ON_SUCCESS"		=> \$reboot_on_success,
320 321 322 323
    "DIE_ON_FAILURE"		=> \$die_on_failure,
    "POWER_OFF"			=> \$power_off,
    "POWERCYCLE_AFTER_REBOOT"	=> \$powercycle_after_reboot,
    "POWEROFF_AFTER_HALT"	=> \$poweroff_after_halt,
324
    "MAX_MONITOR_WAIT"		=> \$max_monitor_wait,
325 326 327 328
    "SLEEP_TIME"		=> \$sleep_time,
    "BISECT_SLEEP_TIME"		=> \$bisect_sleep_time,
    "PATCHCHECK_SLEEP_TIME"	=> \$patchcheck_sleep_time,
    "IGNORE_WARNINGS"		=> \$ignore_warnings,
329
    "IGNORE_ERRORS"		=> \$ignore_errors,
330 331
    "BISECT_MANUAL"		=> \$bisect_manual,
    "BISECT_SKIP"		=> \$bisect_skip,
332
    "BISECT_TRIES"		=> \$bisect_tries,
333 334 335 336 337 338 339 340 341 342
    "CONFIG_BISECT_GOOD"	=> \$config_bisect_good,
    "BISECT_RET_GOOD"		=> \$bisect_ret_good,
    "BISECT_RET_BAD"		=> \$bisect_ret_bad,
    "BISECT_RET_SKIP"		=> \$bisect_ret_skip,
    "BISECT_RET_ABORT"		=> \$bisect_ret_abort,
    "BISECT_RET_DEFAULT"	=> \$bisect_ret_default,
    "STORE_FAILURES"		=> \$store_failures,
    "STORE_SUCCESSES"		=> \$store_successes,
    "TEST_NAME"			=> \$test_name,
    "TIMEOUT"			=> \$timeout,
343
    "CONNECT_TIMEOUT"		=> \$connect_timeout,
344
    "CONFIG_BISECT_EXEC"	=> \$config_bisect_exec,
345 346
    "BOOTED_TIMEOUT"		=> \$booted_timeout,
    "CONSOLE"			=> \$console,
347
    "CLOSE_CONSOLE_SIGNAL"	=> \$close_console_signal,
348 349 350 351 352 353 354 355 356
    "DETECT_TRIPLE_FAULT"	=> \$detect_triplefault,
    "SUCCESS_LINE"		=> \$success_line,
    "REBOOT_SUCCESS_LINE"	=> \$reboot_success_line,
    "STOP_AFTER_SUCCESS"	=> \$stop_after_success,
    "STOP_AFTER_FAILURE"	=> \$stop_after_failure,
    "STOP_TEST_AFTER"		=> \$stop_test_after,
    "BUILD_TARGET"		=> \$build_target,
    "SSH_EXEC"			=> \$ssh_exec,
    "SCP_TO_TARGET"		=> \$scp_to_target,
357
    "SCP_TO_TARGET_INSTALL"	=> \$scp_to_target_install,
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
    "CHECKOUT"			=> \$checkout,
    "TARGET_IMAGE"		=> \$target_image,
    "LOCALVERSION"		=> \$localversion,

    "BISECT_GOOD"		=> \$bisect_good,
    "BISECT_BAD"		=> \$bisect_bad,
    "BISECT_TYPE"		=> \$bisect_type,
    "BISECT_START"		=> \$bisect_start,
    "BISECT_REPLAY"		=> \$bisect_replay,
    "BISECT_FILES"		=> \$bisect_files,
    "BISECT_REVERSE"		=> \$bisect_reverse,
    "BISECT_CHECK"		=> \$bisect_check,

    "CONFIG_BISECT"		=> \$config_bisect,
    "CONFIG_BISECT_TYPE"	=> \$config_bisect_type,
373
    "CONFIG_BISECT_CHECK"	=> \$config_bisect_check,
374 375 376

    "PATCHCHECK_TYPE"		=> \$patchcheck_type,
    "PATCHCHECK_START"		=> \$patchcheck_start,
377
    "PATCHCHECK_CHERRY"		=> \$patchcheck_cherry,
378 379 380 381 382 383
    "PATCHCHECK_END"		=> \$patchcheck_end,
);

# Options may be used by other options, record them.
my %used_options;

S
Steven Rostedt 已提交
384 385
# default variables that can be used
chomp ($variable{"PWD"} = `pwd`);
386
$pwd = $variable{"PWD"};
S
Steven Rostedt 已提交
387

388 389
$config_help{"MACHINE"} = << "EOF"
 The machine hostname that you will test.
390
 For build only tests, it is still needed to differentiate log files.
391 392 393 394 395 396 397 398 399
EOF
    ;
$config_help{"SSH_USER"} = << "EOF"
 The box is expected to have ssh on normal bootup, provide the user
  (most likely root, since you need privileged operations)
EOF
    ;
$config_help{"BUILD_DIR"} = << "EOF"
 The directory that contains the Linux source code (full path).
400 401
 You can use \${PWD} that will be the path where ktest.pl is run, or use
 \${THIS_DIR} which is assigned \${PWD} but may be changed later.
402 403 404 405 406
EOF
    ;
$config_help{"OUTPUT_DIR"} = << "EOF"
 The directory that the objects will be built (full path).
 (can not be same as BUILD_DIR)
407 408
 You can use \${PWD} that will be the path where ktest.pl is run, or use
 \${THIS_DIR} which is assigned \${PWD} but may be changed later.
409 410 411 412 413 414 415
EOF
    ;
$config_help{"BUILD_TARGET"} = << "EOF"
 The location of the compiled file to copy to the target.
 (relative to OUTPUT_DIR)
EOF
    ;
416 417 418 419 420
$config_help{"BUILD_OPTIONS"} = << "EOF"
 Options to add to \"make\" when building.
 i.e.  -j20
EOF
    ;
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
$config_help{"TARGET_IMAGE"} = << "EOF"
 The place to put your image on the test machine.
EOF
    ;
$config_help{"POWER_CYCLE"} = << "EOF"
 A script or command to reboot the box.

 Here is a digital loggers power switch example
 POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'

 Here is an example to reboot a virtual box on the current host
 with the name "Guest".
 POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
EOF
    ;
$config_help{"CONSOLE"} = << "EOF"
 The script or command that reads the console

  If you use ttywatch server, something like the following would work.
CONSOLE = nc -d localhost 3001

 For a virtual machine with guest name "Guest".
CONSOLE =  virsh console Guest
EOF
    ;
$config_help{"LOCALVERSION"} = << "EOF"
 Required version ending to differentiate the test
 from other linux builds on the system.
EOF
    ;
$config_help{"REBOOT_TYPE"} = << "EOF"
 Way to reboot the box to the test kernel.
453
 Only valid options so far are "grub", "grub2", "grub2bls", "syslinux", and "script".
454 455 456 457 458 459 460 461 462

 If you specify grub, it will assume grub version 1
 and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
 and select that target to reboot to the kernel. If this is not
 your setup, then specify "script" and have a command or script
 specified in REBOOT_SCRIPT to boot to the target.

 The entry in /boot/grub/menu.lst must be entered in manually.
 The test will not modify that file.
S
Steven Rostedt 已提交
463 464 465

 If you specify grub2, then you also need to specify both \$GRUB_MENU
 and \$GRUB_FILE.
466

467 468
 If you specify grub2bls, then you also need to specify \$GRUB_MENU.

469 470 471 472
 If you specify syslinux, then you may use SYSLINUX to define the syslinux
 command (defaults to extlinux), and SYSLINUX_PATH to specify the path to
 the syslinux install (defaults to /boot/extlinux). But you have to specify
 SYSLINUX_LABEL to define the label to boot to for the test kernel.
473 474 475 476
EOF
    ;
$config_help{"GRUB_MENU"} = << "EOF"
 The grub title name for the test kernel to boot
S
Steven Rostedt 已提交
477
 (Only mandatory if REBOOT_TYPE = grub or grub2)
478 479 480 481 482 483 484 485 486 487

 Note, ktest.pl will not update the grub menu.lst, you need to
 manually add an option for the test. ktest.pl will search
 the grub menu.lst for this option to find what kernel to
 reboot into.

 For example, if in the /boot/grub/menu.lst the test kernel title has:
 title Test Kernel
 kernel vmlinuz-test
 GRUB_MENU = Test Kernel
S
Steven Rostedt 已提交
488 489 490 491 492 493

 For grub2, a search of \$GRUB_FILE is performed for the lines
 that begin with "menuentry". It will not detect submenus. The
 menu must be a non-nested menu. Add the quotes used in the menu
 to guarantee your selection, as the first menuentry with the content
 of \$GRUB_MENU that is found will be used.
494 495 496

 For grub2bls, \$GRUB_MENU is searched on the result of \$GRUB_BLS_GET
 command for the lines that begin with "title".
S
Steven Rostedt 已提交
497 498 499 500 501
EOF
    ;
$config_help{"GRUB_FILE"} = << "EOF"
 If grub2 is used, the full path for the grub.cfg file is placed
 here. Use something like /boot/grub2/grub.cfg to search.
502 503
EOF
    ;
504 505 506 507 508
$config_help{"SYSLINUX_LABEL"} = << "EOF"
 If syslinux is used, the label that boots the target kernel must
 be specified with SYSLINUX_LABEL.
EOF
    ;
509 510 511 512 513 514
$config_help{"REBOOT_SCRIPT"} = << "EOF"
 A script to reboot the target into the test kernel
 (Only mandatory if REBOOT_TYPE = script)
EOF
    ;

515 516
sub _logit {
    if (defined($opt{"LOG_FILE"})) {
517
	print LOG @_;
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
    }
}

sub logit {
    if (defined($opt{"LOG_FILE"})) {
	_logit @_;
    } else {
	print @_;
    }
}

sub doprint {
    print @_;
    _logit @_;
}

534 535
sub read_prompt {
    my ($cancel, $prompt) = @_;
536 537 538 539

    my $ans;

    for (;;) {
540 541 542 543 544
	if ($cancel) {
	    print "$prompt [y/n/C] ";
	} else {
	    print "$prompt [Y/n] ";
	}
545 546 547
	$ans = <STDIN>;
	chomp $ans;
	if ($ans =~ /^\s*$/) {
548 549 550 551 552
	    if ($cancel) {
		$ans = "c";
	    } else {
		$ans = "y";
	    }
553 554
	}
	last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
555 556 557 558 559 560 561 562 563
	if ($cancel) {
	    last if ($ans =~ /^c$/i);
	    print "Please answer either 'y', 'n' or 'c'.\n";
	} else {
	    print "Please answer either 'y' or 'n'.\n";
	}
    }
    if ($ans =~ /^c/i) {
	exit;
564 565 566 567 568 569
    }
    if ($ans !~ /^y$/i) {
	return 0;
    }
    return 1;
}
570

571 572 573 574 575 576 577 578 579 580 581 582
sub read_yn {
    my ($prompt) = @_;

    return read_prompt 0, $prompt;
}

sub read_ync {
    my ($prompt) = @_;

    return read_prompt 1, $prompt;
}

583
sub get_mandatory_config {
584
    my ($config) = @_;
585
    my $ans;
586 587 588 589 590 591 592 593 594 595

    return if (defined($opt{$config}));

    if (defined($config_help{$config})) {
	print "\n";
	print $config_help{$config};
    }

    for (;;) {
	print "$config = ";
596
	if (defined($default{$config}) && length($default{$config})) {
597 598
	    print "\[$default{$config}\] ";
	}
599 600 601
	$ans = <STDIN>;
	$ans =~ s/^\s*(.*\S)\s*$/$1/;
	if ($ans =~ /^\s*$/) {
602
	    if ($default{$config}) {
603
		$ans = $default{$config};
604 605 606 607 608
	    } else {
		print "Your answer can not be blank\n";
		next;
	    }
	}
609
	$entered_configs{$config} = ${ans};
610 611 612 613
	last;
    }
}

614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
sub show_time {
    my ($time) = @_;

    my $hours = 0;
    my $minutes = 0;

    if ($time > 3600) {
	$hours = int($time / 3600);
	$time -= $hours * 3600;
    }
    if ($time > 60) {
	$minutes = int($time / 60);
	$time -= $minutes * 60;
    }

    if ($hours > 0) {
	doprint "$hours hour";
	doprint "s" if ($hours > 1);
	doprint " ";
    }

    if ($minutes > 0) {
	doprint "$minutes minute";
	doprint "s" if ($minutes > 1);
	doprint " ";
    }

    doprint "$time second";
    doprint "s" if ($time != 1);
}

sub print_times {
    doprint "\n";
    if ($build_time) {
	doprint "Build time:   ";
	show_time($build_time);
	doprint "\n";
    }
    if ($install_time) {
	doprint "Install time: ";
	show_time($install_time);
	doprint "\n";
    }
    if ($reboot_time) {
	doprint "Reboot time:  ";
	show_time($reboot_time);
	doprint "\n";
    }
    if ($test_time) {
	doprint "Test time:    ";
	show_time($test_time);
	doprint "\n";
    }
    # reset for iterations like bisect
    $build_time = 0;
    $install_time = 0;
    $reboot_time = 0;
    $test_time = 0;
}

674 675 676 677
sub get_mandatory_configs {
    get_mandatory_config("MACHINE");
    get_mandatory_config("BUILD_DIR");
    get_mandatory_config("OUTPUT_DIR");
678

679
    if ($newconfig) {
680
	get_mandatory_config("BUILD_OPTIONS");
681 682
    }

683 684
    # options required for other than just building a kernel
    if (!$buildonly) {
685 686
	get_mandatory_config("POWER_CYCLE");
	get_mandatory_config("CONSOLE");
687 688 689 690
    }

    # options required for install and more
    if ($buildonly != 1) {
691 692 693
	get_mandatory_config("SSH_USER");
	get_mandatory_config("BUILD_TARGET");
	get_mandatory_config("TARGET_IMAGE");
694 695
    }

696
    get_mandatory_config("LOCALVERSION");
697

698 699
    return if ($buildonly);

700 701 702 703
    my $rtype = $opt{"REBOOT_TYPE"};

    if (!defined($rtype)) {
	if (!defined($opt{"GRUB_MENU"})) {
704
	    get_mandatory_config("REBOOT_TYPE");
705 706 707 708 709 710
	    $rtype = $entered_configs{"REBOOT_TYPE"};
	} else {
	    $rtype = "grub";
	}
    }

711
    if (($rtype eq "grub") or ($rtype eq "grub2bls")) {
712
	get_mandatory_config("GRUB_MENU");
713
    }
S
Steven Rostedt 已提交
714 715

    if ($rtype eq "grub2") {
716 717
	get_mandatory_config("GRUB_MENU");
	get_mandatory_config("GRUB_FILE");
S
Steven Rostedt 已提交
718
    }
719 720

    if ($rtype eq "syslinux") {
721
	get_mandatory_config("SYSLINUX_LABEL");
722
    }
723 724
}

725
sub process_variables {
726
    my ($value, $remove_undef) = @_;
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
    my $retval = "";

    # We want to check for '\', and it is just easier
    # to check the previous characet of '$' and not need
    # to worry if '$' is the first character. By adding
    # a space to $value, we can just check [^\\]\$ and
    # it will still work.
    $value = " $value";

    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
	my $begin = $1;
	my $var = $2;
	my $end = $3;
	# append beginning of value to retval
	$retval = "$retval$begin";
	if (defined($variable{$var})) {
	    $retval = "$retval$variable{$var}";
744 745 746 747
	} elsif (defined($remove_undef) && $remove_undef) {
	    # for if statements, any variable that is not defined,
	    # we simple convert to 0
	    $retval = "${retval}0";
748 749 750
	} else {
	    # put back the origin piece.
	    $retval = "$retval\$\{$var\}";
751 752 753 754
	    # This could be an option that is used later, save
	    # it so we don't warn if this option is not one of
	    # ktests options.
	    $used_options{$var} = 1;
755 756 757 758 759 760 761 762 763 764 765
	}
	$value = $end;
    }
    $retval = "$retval$value";

    # remove the space added in the beginning
    $retval =~ s/ //;

    return "$retval"
}

766
sub set_value {
767
    my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
768

769 770
    my $prvalue = process_variables($rvalue);

771 772 773 774 775
    if ($lvalue =~ /^(TEST|BISECT|CONFIG_BISECT)_TYPE(\[.*\])?$/ &&
	$prvalue !~ /^(config_|)bisect$/ &&
	$prvalue !~ /^build$/ &&
	$buildonly) {

776
	# Note if a test is something other than build, then we
P
Pavel Machek 已提交
777
	# will need other mandatory options.
778
	if ($prvalue ne "install") {
779 780
	    $buildonly = 0;
	} else {
P
Pavel Machek 已提交
781
	    # install still limits some mandatory options.
782 783
	    $buildonly = 2;
	}
784 785
    }

786
    if (defined($opt{$lvalue})) {
787 788 789 790 791 792 793
	if (!$override || defined(${$overrides}{$lvalue})) {
	    my $extra = "";
	    if ($override) {
		$extra = "In the same override section!\n";
	    }
	    die "$name: $.: Option $lvalue defined more than once!\n$extra";
	}
794
	${$overrides}{$lvalue} = $prvalue;
795
    }
796 797

    $opt{$lvalue} = $prvalue;
798 799
}

800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
sub set_eval {
    my ($lvalue, $rvalue, $name) = @_;

    my $prvalue = process_variables($rvalue);
    my $arr;

    if (defined($evals{$lvalue})) {
	$arr = $evals{$lvalue};
    } else {
	$arr = [];
	$evals{$lvalue} = $arr;
    }

    push @{$arr}, $rvalue;
}

816 817 818 819 820 821 822 823 824 825 826
sub set_variable {
    my ($lvalue, $rvalue) = @_;

    if ($rvalue =~ /^\s*$/) {
	delete $variable{$lvalue};
    } else {
	$rvalue = process_variables($rvalue);
	$variable{$lvalue} = $rvalue;
    }
}

827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
sub process_compare {
    my ($lval, $cmp, $rval) = @_;

    # remove whitespace

    $lval =~ s/^\s*//;
    $lval =~ s/\s*$//;

    $rval =~ s/^\s*//;
    $rval =~ s/\s*$//;

    if ($cmp eq "==") {
	return $lval eq $rval;
    } elsif ($cmp eq "!=") {
	return $lval ne $rval;
842 843 844 845
    } elsif ($cmp eq "=~") {
	return $lval =~ m/$rval/;
    } elsif ($cmp eq "!~") {
	return $lval !~ m/$rval/;
846 847 848 849 850 851 852 853 854 855 856 857 858
    }

    my $statement = "$lval $cmp $rval";
    my $ret = eval $statement;

    # $@ stores error of eval
    if ($@) {
	return -1;
    }

    return $ret;
}

859 860 861 862 863 864 865
sub value_defined {
    my ($val) = @_;

    return defined($variable{$2}) ||
	defined($opt{$2});
}

866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
my $d = 0;
sub process_expression {
    my ($name, $val) = @_;

    my $c = $d++;

    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
	my $express = $1;

	if (process_expression($name, $express)) {
	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
	} else {
	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
	}
    }

    $d--;
    my $OR = "\\|\\|";
    my $AND = "\\&\\&";
885

886 887 888 889 890 891 892 893 894 895 896 897 898 899
    while ($val =~ s/^(.*?)($OR|$AND)//) {
	my $express = $1;
	my $op = $2;

	if (process_expression($name, $express)) {
	    if ($op eq "||") {
		return 1;
	    }
	} else {
	    if ($op eq "&&") {
		return 0;
	    }
	}
    }
900

901
    if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) {
902 903 904 905 906 907 908
	my $ret = process_compare($1, $2, $3);
	if ($ret < 0) {
	    die "$name: $.: Unable to process comparison\n";
	}
	return $ret;
    }

909 910 911 912 913 914 915 916
    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
	if (defined $1) {
	    return !value_defined($2);
	} else {
	    return value_defined($2);
	}
    }

917 918 919 920 921 922
    if ($val =~ s/^\s*NOT\s+(.*)//) {
	my $express = $1;
	my $ret = process_expression($name, $express);
	return !$ret;
    }

923 924 925 926 927 928
    if ($val =~ /^\s*0\s*$/) {
	return 0;
    } elsif ($val =~ /^\s*\d+\s*$/) {
	return 1;
    }

929
    die ("$name: $.: Undefined content $val in if statement\n");
930 931 932 933 934 935 936 937 938 939
}

sub process_if {
    my ($name, $value) = @_;

    # Convert variables and replace undefined ones with 0
    my $val = process_variables($value, 1);
    my $ret = process_expression $name, $val;

    return $ret;
940 941
}

942 943
sub __read_config {
    my ($config, $current_test_num) = @_;
S
Steven Rostedt 已提交
944

945 946
    my $in;
    open($in, $config) || die "can't read file $config";
S
Steven Rostedt 已提交
947

948 949 950
    my $name = $config;
    $name =~ s,.*/(.*),$1,;

951
    my $test_num = $$current_test_num;
952 953 954 955 956
    my $default = 1;
    my $repeat = 1;
    my $num_tests_set = 0;
    my $skip = 0;
    my $rest;
957
    my $line;
958
    my $test_case = 0;
959 960
    my $if = 0;
    my $if_set = 0;
961 962 963
    my $override = 0;

    my %overrides;
964

965
    while (<$in>) {
S
Steven Rostedt 已提交
966 967 968 969

	# ignore blank lines and comments
	next if (/^\s*$/ || /\s*\#/);

970
	if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
971

972 973
	    my $type = $1;
	    $rest = $2;
974
	    $line = $2;
975

976 977
	    my $old_test_num;
	    my $old_repeat;
978
	    $override = 0;
979 980 981 982 983 984

	    if ($type eq "TEST_START") {

		if ($num_tests_set) {
		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
		}
985

986 987
		$old_test_num = $test_num;
		$old_repeat = $repeat;
988

989 990 991 992 993 994
		$test_num += $repeat;
		$default = 0;
		$repeat = 1;
	    } else {
		$default = 1;
	    }
995

996 997
	    # If SKIP is anywhere in the line, the command will be skipped
	    if ($rest =~ s/\s+SKIP\b//) {
998 999
		$skip = 1;
	    } else {
1000
		$test_case = 1;
1001 1002 1003
		$skip = 0;
	    }

1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
	    if ($rest =~ s/\sELSE\b//) {
		if (!$if) {
		    die "$name: $.: ELSE found with out matching IF section\n$_";
		}
		$if = 0;

		if ($if_set) {
		    $skip = 1;
		} else {
		    $skip = 0;
1014
		}
1015 1016
	    }

1017
	    if ($rest =~ s/\sIF\s+(.*)//) {
1018 1019 1020 1021 1022 1023 1024 1025
		if (process_if($name, $1)) {
		    $if_set = 1;
		} else {
		    $skip = 1;
		}
		$if = 1;
	    } else {
		$if = 0;
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
		$if_set = 0;
	    }

	    if (!$skip) {
		if ($type eq "TEST_START") {
		    if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
			$repeat = $1;
			$repeat_tests{"$test_num"} = $repeat;
		    }
		} elsif ($rest =~ s/\sOVERRIDE\b//) {
		    # DEFAULT only
		    $override = 1;
		    # Clear previous overrides
		    %overrides = ();
		}
1041 1042
	    }

1043
	    if (!$skip && $rest !~ /^\s*$/) {
M
Masanari Iida 已提交
1044
		die "$name: $.: Garbage found after $type\n$_";
1045 1046
	    }

1047
	    if ($skip && $type eq "TEST_START") {
1048
		$test_num = $old_test_num;
1049
		$repeat = $old_repeat;
1050 1051
	    }

1052
	} elsif (/^\s*ELSE\b(.*)$/) {
1053 1054 1055 1056 1057 1058
	    if (!$if) {
		die "$name: $.: ELSE found with out matching IF section\n$_";
	    }
	    $rest = $1;
	    if ($if_set) {
		$skip = 1;
1059
		$rest = "";
1060 1061 1062
	    } else {
		$skip = 0;

1063
		if ($rest =~ /\sIF\s+(.*)/) {
1064
		    # May be a ELSE IF section.
S
Steven Rostedt 已提交
1065 1066 1067
		    if (process_if($name, $1)) {
			$if_set = 1;
		    } else {
1068 1069
			$skip = 1;
		    }
1070
		    $rest = "";
1071 1072 1073 1074 1075
		} else {
		    $if = 0;
		}
	    }

1076
	    if ($rest !~ /^\s*$/) {
M
Masanari Iida 已提交
1077
		die "$name: $.: Garbage found after DEFAULTS\n$_";
1078 1079
	    }

1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
	} elsif (/^\s*INCLUDE\s+(\S+)/) {

	    next if ($skip);

	    if (!$default) {
		die "$name: $.: INCLUDE can only be done in default sections\n$_";
	    }

	    my $file = process_variables($1);

	    if ($file !~ m,^/,) {
		# check the path of the config file first
		if ($config =~ m,(.*)/,) {
		    if (-f "$1/$file") {
			$file = "$1/$file";
		    }
		}
	    }
		
	    if ( ! -r $file ) {
		die "$name: $.: Can't read file $file\n$_";
	    }

	    if (__read_config($file, \$test_num)) {
		$test_case = 1;
	    }

1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=~\s*(.*?)\s*$/) {

	    next if ($skip);

	    my $lvalue = $1;
	    my $rvalue = $2;

	    if ($default || $lvalue =~ /\[\d+\]$/) {
		set_eval($lvalue, $rvalue, $name);
	    } else {
		my $val = "$lvalue\[$test_num\]";
		set_eval($val, $rvalue, $name);
	    }

1121 1122 1123 1124
	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {

	    next if ($skip);

S
Steven Rostedt 已提交
1125 1126 1127
	    my $lvalue = $1;
	    my $rvalue = $2;

1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
	    if (!$default &&
		($lvalue eq "NUM_TESTS" ||
		 $lvalue eq "LOG_FILE" ||
		 $lvalue eq "CLEAR_LOG")) {
		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
	    }

	    if ($lvalue eq "NUM_TESTS") {
		if ($test_num) {
		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
		}
		if (!$default) {
		    die "$name: $.: NUM_TESTS must be set in default section\n";
		}
		$num_tests_set = 1;
	    }

	    if ($default || $lvalue =~ /\[\d+\]$/) {
1146
		set_value($lvalue, $rvalue, $override, \%overrides, $name);
1147 1148
	    } else {
		my $val = "$lvalue\[$test_num\]";
1149
		set_value($val, $rvalue, $override, \%overrides, $name);
1150 1151 1152 1153

		if ($repeat > 1) {
		    $repeats{$val} = $repeat;
		}
1154
	    }
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167
	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
	    next if ($skip);

	    my $lvalue = $1;
	    my $rvalue = $2;

	    # process config variables.
	    # Config variables are only active while reading the
	    # config and can be defined anywhere. They also ignore
	    # TEST_START and DEFAULTS, but are skipped if they are in
	    # on of these sections that have SKIP defined.
	    # The save variable can be
	    # defined multiple times and the new one simply overrides
M
Masanari Iida 已提交
1168
	    # the previous one.
1169 1170
	    set_variable($lvalue, $rvalue);

1171 1172
	} else {
	    die "$name: $.: Garbage found in config\n$_";
S
Steven Rostedt 已提交
1173 1174 1175
	}
    }

1176 1177 1178 1179 1180
    if ($test_num) {
	$test_num += $repeat - 1;
	$opt{"NUM_TESTS"} = $test_num;
    }

1181 1182 1183 1184 1185 1186 1187
    close($in);

    $$current_test_num = $test_num;

    return $test_case;
}

1188 1189 1190
sub get_test_case {
	print "What test case would you like to run?\n";
	print " (build, install or boot)\n";
S
Scott Wood 已提交
1191 1192
	print " Other tests are available but require editing ktest.conf\n";
	print " (see tools/testing/ktest/sample.conf)\n";
1193 1194 1195 1196 1197
	my $ans = <STDIN>;
	chomp $ans;
	$default{"TEST_TYPE"} = $ans;
}

1198 1199 1200 1201 1202 1203 1204 1205
sub read_config {
    my ($config) = @_;

    my $test_case;
    my $test_num = 0;

    $test_case = __read_config $config, \$test_num;

1206
    # make sure we have all mandatory configs
1207
    get_mandatory_configs;
1208

1209 1210 1211
    # was a test specified?
    if (!$test_case) {
	print "No test case specified.\n";
1212
	get_test_case;
1213 1214
    }

1215 1216 1217 1218 1219 1220 1221
    # set any defaults

    foreach my $default (keys %default) {
	if (!defined($opt{$default})) {
	    $opt{$default} = $default{$default};
	}
    }
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247

    if ($opt{"IGNORE_UNUSED"} == 1) {
	return;
    }

    my %not_used;

    # check if there are any stragglers (typos?)
    foreach my $option (keys %opt) {
	my $op = $option;
	# remove per test labels.
	$op =~ s/\[.*\]//;
	if (!exists($option_map{$op}) &&
	    !exists($default{$op}) &&
	    !exists($used_options{$op})) {
	    $not_used{$op} = 1;
	}
    }

    if (%not_used) {
	my $s = "s are";
	$s = " is" if (keys %not_used == 1);
	print "The following option$s not used; could be a typo:\n";
	foreach my $option (keys %not_used) {
	    print "$option\n";
	}
M
Masanari Iida 已提交
1248
	print "Set IGNORE_UNUSED = 1 to have ktest ignore unused variables\n";
1249 1250 1251 1252
	if (!read_yn "Do you want to continue?") {
	    exit -1;
	}
    }
S
Steven Rostedt 已提交
1253 1254
}

1255
sub __eval_option {
1256
    my ($name, $option, $i) = @_;
1257 1258 1259 1260

    # Add space to evaluate the character before $
    $option = " $option";
    my $retval = "";
1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272
    my $repeated = 0;
    my $parent = 0;

    foreach my $test (keys %repeat_tests) {
	if ($i >= $test &&
	    $i < $test + $repeat_tests{$test}) {

	    $repeated = 1;
	    $parent = $test;
	    last;
	}
    }
1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285

    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
	my $start = $1;
	my $var = $2;
	my $end = $3;

	# Append beginning of line
	$retval = "$retval$start";

	# If the iteration option OPT[$i] exists, then use that.
	# otherwise see if the default OPT (without [$i]) exists.

	my $o = "$var\[$i\]";
1286
	my $parento = "$var\[$parent\]";
1287

1288 1289 1290 1291 1292
	# If a variable contains itself, use the default var
	if (($var eq $name) && defined($opt{$var})) {
	    $o = $opt{$var};
	    $retval = "$retval$o";
	} elsif (defined($opt{$o})) {
1293 1294
	    $o = $opt{$o};
	    $retval = "$retval$o";
1295 1296 1297
	} elsif ($repeated && defined($opt{$parento})) {
	    $o = $opt{$parento};
	    $retval = "$retval$o";
1298 1299 1300
	} elsif (defined($opt{$var})) {
	    $o = $opt{$var};
	    $retval = "$retval$o";
1301 1302 1303 1304
	} elsif ($var eq "KERNEL_VERSION" && defined($make)) {
	    # special option KERNEL_VERSION uses kernel version
	    get_version();
	    $retval = "$retval$version";
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318
	} else {
	    $retval = "$retval\$\{$var\}";
	}

	$option = $end;
    }

    $retval = "$retval$option";

    $retval =~ s/^ //;

    return $retval;
}

1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345
sub process_evals {
    my ($name, $option, $i) = @_;

    my $option_name = "$name\[$i\]";
    my $ev;

    my $old_option = $option;

    if (defined($evals{$option_name})) {
	$ev = $evals{$option_name};
    } elsif (defined($evals{$name})) {
	$ev = $evals{$name};
    } else {
	return $option;
    }

    for my $e (@{$ev}) {
	eval "\$option =~ $e";
    }

    if ($option ne $old_option) {
	doprint("$name changed from '$old_option' to '$option'\n");
    }

    return $option;
}

1346
sub eval_option {
1347
    my ($name, $option, $i) = @_;
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358

    my $prev = "";

    # Since an option can evaluate to another option,
    # keep iterating until we do not evaluate any more
    # options.
    my $r = 0;
    while ($prev ne $option) {
	# Check for recursive evaluations.
	# 100 deep should be more than enough.
	if ($r++ > 100) {
M
Masanari Iida 已提交
1359
	    die "Over 100 evaluations occurred with $option\n" .
1360 1361 1362
		"Check for recursive variables\n";
	}
	$prev = $option;
1363
	$option = __eval_option($name, $option, $i);
1364 1365
    }

1366
    $option = process_evals($name, $option, $i);
1367

1368
    return $option;
1369 1370
}

1371
sub run_command;
1372 1373 1374
sub start_monitor;
sub end_monitor;
sub wait_for_monitor;
1375 1376

sub reboot {
1377
    my ($time) = @_;
1378
    my $powercycle = 0;
1379

1380 1381
    # test if the machine can be connected to within a few seconds
    my $stat = run_ssh("echo check machine status", $connect_timeout);
1382 1383 1384 1385 1386 1387 1388
    if (!$stat) {
	doprint("power cycle\n");
	$powercycle = 1;
    }

    if ($powercycle) {
	run_command "$power_cycle";
S
Steven Rostedt 已提交
1389

1390 1391 1392 1393 1394
	start_monitor;
	# flush out current monitor
	# May contain the reboot success line
	wait_for_monitor 1;

1395 1396
    } else {
	# Make sure everything has been written to disk
1397
	run_ssh("sync", 10);
1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413

	if (defined($time)) {
	    start_monitor;
	    # flush out current monitor
	    # May contain the reboot success line
	    wait_for_monitor 1;
	}

	# try to reboot normally
	if (run_command $reboot) {
	    if (defined($powercycle_after_reboot)) {
		sleep $powercycle_after_reboot;
		run_command "$power_cycle";
	    }
	} else {
	    # nope? power cycle it.
1414 1415
	    run_command "$power_cycle";
	}
1416
    }
1417 1418

    if (defined($time)) {
1419 1420 1421 1422 1423 1424

	# We only want to get to the new kernel, don't fail
	# if we stumble over a call trace.
	my $save_ignore_errors = $ignore_errors;
	$ignore_errors = 1;

1425 1426
	# Look for the good kernel to boot
	if (wait_for_monitor($time, "Linux version")) {
1427
	    # reboot got stuck?
1428
	    doprint "Reboot did not finish. Forcing power cycle\n";
1429 1430
	    run_command "$power_cycle";
	}
1431

1432 1433
	$ignore_errors = $save_ignore_errors;

1434 1435 1436
	# Still need to wait for the reboot to finish
	wait_for_monitor($time, $reboot_success_line);

1437 1438
	end_monitor;
    }
1439 1440
}

1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
sub reboot_to_good {
    my ($time) = @_;

    if (defined($switch_to_good)) {
	run_command $switch_to_good;
    }

    reboot $time;
}

1451 1452 1453
sub do_not_reboot {
    my $i = $iteration;

1454
    return $test_type eq "build" || $no_reboot ||
1455
	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
1456 1457
	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build") ||
	($test_type eq "config_bisect" && $opt{"CONFIG_BISECT_TYPE[$i]"} eq "build");
1458 1459
}

1460 1461
my $in_die = 0;

1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472
sub get_test_name() {
    my $name;

    if (defined($test_name)) {
	$name = "$test_name:$test_type";
    } else {
	$name = $test_type;
    }
    return $name;
}

1473
sub dodie {
1474

M
Masanari Iida 已提交
1475
    # avoid recursion
1476 1477 1478
    return if ($in_die);
    $in_die = 1;

1479 1480
    my $i = $iteration;

1481 1482
    doprint "CRITICAL FAILURE... [TEST $i] ", @_, "\n";

1483 1484
    if ($reboot_on_error && !do_not_reboot) {

1485
	doprint "REBOOTING\n";
1486
	reboot_to_good;
1487

1488
    } elsif ($poweroff_on_error && defined($power_off)) {
1489
	doprint "POWERING OFF\n";
1490
	`$power_off`;
1491
    }
1492

1493 1494 1495 1496
    if (defined($opt{"LOG_FILE"})) {
	print " See $opt{LOG_FILE} for more info.\n";
    }

T
Tim Tianyang Chen 已提交
1497
    if ($email_on_error) {
1498
	my $name = get_test_name;
1499 1500 1501
	my $log_file;

	if (defined($opt{"LOG_FILE"})) {
1502 1503 1504
	    my $whence = 0; # beginning of file
	    my $pos = $test_log_start;

1505 1506 1507 1508
	    if (defined($mail_max_size)) {
		my $log_size = tell LOG;
		$log_size -= $test_log_start;
		if ($log_size > $mail_max_size) {
1509 1510
		    $whence = 2; # end of file
		    $pos = - $mail_max_size;
1511 1512
		}
	    }
1513 1514 1515
	    $log_file = "$tmpdir/log";
	    open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)";
	    open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n";
1516
	    seek(L, $pos, $whence);
1517 1518 1519 1520 1521 1522
	    while (<L>) {
		print O;
	    }
	    close O;
	    close L;
	}
1523
        send_email("KTEST: critical failure for test $i [$name]",
1524
                "Your test started at $script_start_time has failed with:\n@_\n", $log_file);
T
Tim Tianyang Chen 已提交
1525 1526
    }

1527 1528 1529 1530 1531
    if ($monitor_cnt) {
	    # restore terminal settings
	    system("stty $stty_orig");
    }

1532 1533 1534 1535
    if (defined($post_test)) {
	run_command $post_test;
    }

1536
    die @_, "\n";
1537 1538
}

1539 1540 1541 1542 1543 1544 1545
sub create_pty {
    my ($ptm, $pts) = @_;
    my $tmp;
    my $TIOCSPTLCK = 0x40045431;
    my $TIOCGPTN = 0x80045430;

    sysopen($ptm, "/dev/ptmx", O_RDWR | O_NONBLOCK) or
1546
	dodie "Can't open /dev/ptmx";
1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577

    # unlockpt()
    $tmp = pack("i", 0);
    ioctl($ptm, $TIOCSPTLCK, $tmp) or
	dodie "ioctl TIOCSPTLCK for /dev/ptmx failed";

    # ptsname()
    ioctl($ptm, $TIOCGPTN, $tmp) or
	dodie "ioctl TIOCGPTN for /dev/ptmx failed";
    $tmp = unpack("i", $tmp);

    sysopen($pts, "/dev/pts/$tmp", O_RDWR | O_NONBLOCK) or
	dodie "Can't open /dev/pts/$tmp";
}

sub exec_console {
    my ($ptm, $pts) = @_;

    close($ptm);

    close(\*STDIN);
    close(\*STDOUT);
    close(\*STDERR);

    open(\*STDIN, '<&', $pts);
    open(\*STDOUT, '>&', $pts);
    open(\*STDERR, '>&', $pts);

    close($pts);

    exec $console or
1578
	dodie "Can't open console $console";
1579
}
1580

1581 1582 1583 1584
sub open_console {
    my ($ptm) = @_;
    my $pts = \*PTSFD;
    my $pid;
1585

1586
    # save terminal settings
1587 1588 1589 1590 1591
    $stty_orig = `stty -g`;

    # place terminal in cbreak mode so that stdin can be read one character at
    # a time without having to wait for a newline
    system("stty -icanon -echo -icrnl");
1592

1593
    create_pty($ptm, $pts);
1594

1595 1596 1597 1598 1599 1600 1601 1602 1603
    $pid = fork;

    if (!$pid) {
	# child
	exec_console($ptm, $pts)
    }

    # parent
    close($pts);
1604 1605

    return $pid;
1606 1607

    open(PTSFD, "Stop perl from warning about single use of PTSFD");
1608 1609 1610 1611 1612 1613
}

sub close_console {
    my ($fp, $pid) = @_;

    doprint "kill child process $pid\n";
1614
    kill $close_console_signal, $pid;
1615

1616 1617 1618
    doprint "wait for child process $pid to exit\n";
    waitpid($pid, 0);

1619 1620
    print "closing!\n";
    close($fp);
1621 1622

    # restore terminal settings
1623
    system("stty $stty_orig");
1624 1625 1626 1627 1628 1629 1630 1631
}

sub start_monitor {
    if ($monitor_cnt++) {
	return;
    }
    $monitor_fp = \*MONFD;
    $monitor_pid = open_console $monitor_fp;
1632 1633 1634 1635

    return;

    open(MONFD, "Stop perl from warning about single use of MONFD");
1636 1637 1638
}

sub end_monitor {
1639
    return if (!defined $console);
1640 1641 1642 1643 1644 1645 1646
    if (--$monitor_cnt) {
	return;
    }
    close_console($monitor_fp, $monitor_pid);
}

sub wait_for_monitor {
1647 1648
    my ($time, $stop) = @_;
    my $full_line = "";
1649
    my $line;
1650
    my $booted = 0;
1651
    my $start_time = time;
1652 1653 1654
    my $skip_call_trace = 0;
    my $bug = 0;
    my $bug_ignored = 0;
1655
    my $now;
1656

1657
    doprint "** Wait for monitor to settle down **\n";
1658 1659

    # read the monitor and wait for the system to calm down
1660
    while (!$booted) {
1661
	$line = wait_for_input($monitor_fp, $time);
1662 1663 1664 1665 1666 1667 1668 1669 1670
	last if (!defined($line));
	print "$line";
	$full_line .= $line;

	if (defined($stop) && $full_line =~ /$stop/) {
	    doprint "wait for monitor detected $stop\n";
	    $booted = 1;
	}

1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692
	if ($full_line =~ /\[ backtrace testing \]/) {
	    $skip_call_trace = 1;
	}

	if ($full_line =~ /call trace:/i) {
	    if (!$bug && !$skip_call_trace) {
		if ($ignore_errors) {
		    $bug_ignored = 1;
		} else {
		    $bug = 1;
		}
	    }
	}

	if ($full_line =~ /\[ end of backtrace testing \]/) {
	    $skip_call_trace = 0;
	}

	if ($full_line =~ /Kernel panic -/) {
	    $bug = 1;
	}

1693 1694 1695
	if ($line =~ /\n/) {
	    $full_line = "";
	}
1696 1697 1698 1699 1700
	$now = time;
	if ($now - $start_time >= $max_monitor_wait) {
	    doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n";
	    return 1;
	}
1701
    }
1702
    print "** Monitor flushed **\n";
1703 1704 1705 1706 1707 1708

    # if stop is defined but wasn't hit, return error
    # used by reboot (which wants to see a reboot)
    if (defined($stop) && !$booted) {
	$bug = 1;
    }
1709
    return $bug;
1710 1711
}

1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728
sub save_logs {
	my ($result, $basedir) = @_;
	my @t = localtime;
	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];

	my $type = $build_type;
	if ($type =~ /useconfig/) {
	    $type = "useconfig";
	}

	my $dir = "$machine-$test_type-$type-$result-$date";

	$dir = "$basedir/$dir";

	if (!-d $dir) {
	    mkpath($dir) or
1729
		dodie "can't create $dir";
1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741
	}

	my %files = (
		"config" => $output_config,
		"buildlog" => $buildlog,
		"dmesg" => $dmesg,
		"testlog" => $testlog,
	);

	while (my ($name, $source) = each(%files)) {
		if (-f "$source") {
			cp "$source", "$dir/$name" or
1742
				dodie "failed to copy $source";
1743 1744 1745 1746 1747 1748
		}
	}

	doprint "*** Saved info to $dir ***\n";
}

1749 1750
sub fail {

1751
	if ($die_on_failure) {
1752 1753 1754
		dodie @_;
	}

1755
	doprint "FAILED\n";
1756

1757 1758
	my $i = $iteration;

1759
	# no need to reboot for just building.
1760
	if (!do_not_reboot) {
1761
	    doprint "REBOOTING\n";
1762
	    reboot_to_good $sleep_time;
1763
	}
1764

S
Steven Rostedt 已提交
1765 1766 1767 1768 1769 1770
	my $name = "";

	if (defined($test_name)) {
	    $name = " ($test_name)";
	}

1771 1772
	print_times;

1773 1774
	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
S
Steven Rostedt 已提交
1775
	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1776 1777
	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1778

1779 1780 1781
	if (defined($store_failures)) {
	    save_logs "fail", $store_failures;
        }
1782

1783 1784 1785 1786
	if (defined($post_test)) {
		run_command $post_test;
	}

1787 1788 1789
	return 1;
}

S
Steven Rostedt 已提交
1790
sub run_command {
1791
    my ($command, $redirect, $timeout) = @_;
1792 1793
    my $start_time;
    my $end_time;
1794 1795
    my $dolog = 0;
    my $dord = 0;
1796
    my $dostdout = 0;
1797
    my $pid;
1798
    my $command_orig = $command;
1799

1800 1801 1802
    $command =~ s/\$SSH_USER/$ssh_user/g;
    $command =~ s/\$MACHINE/$machine/g;

1803
    doprint("$command ... ");
1804
    $start_time = time;
1805 1806

    $pid = open(CMD, "$command 2>&1 |") or
1807
	(fail "unable to exec $command" and return 0);
S
Steven Rostedt 已提交
1808 1809

    if (defined($opt{"LOG_FILE"})) {
1810
	$dolog = 1;
S
Steven Rostedt 已提交
1811 1812 1813
    }

    if (defined($redirect)) {
1814 1815 1816 1817 1818 1819 1820 1821 1822
	if ($redirect eq 1) {
	    $dostdout = 1;
	    # Have the output of the command on its own line
	    doprint "\n";
	} else {
	    open (RD, ">$redirect") or
		dodie "failed to write to redirect $redirect";
	    $dord = 1;
	}
S
Steven Rostedt 已提交
1823 1824
    }

1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843
    my $hit_timeout = 0;

    while (1) {
	my $fp = \*CMD;
	if (defined($timeout)) {
	    doprint "timeout = $timeout\n";
	}
	my $line = wait_for_input($fp, $timeout);
	if (!defined($line)) {
	    my $now = time;
	    if (defined($timeout) && (($now - $start_time) >= $timeout)) {
		doprint "Hit timeout of $timeout, killing process\n";
		$hit_timeout = 1;
		kill 9, $pid;
	    }
	    last;
	}
	print LOG $line if ($dolog);
	print RD $line if ($dord);
1844
	print $line if ($dostdout);
1845
    }
S
Steven Rostedt 已提交
1846

1847
    waitpid($pid, 0);
1848 1849
    # shift 8 for real exit status
    $run_command_status = $? >> 8;
S
Steven Rostedt 已提交
1850

1851 1852 1853 1854 1855
    if ($command_orig eq $default{REBOOT} &&
	$run_command_status == $reboot_return_code) {
	$run_command_status = 0;
    }

1856 1857 1858
    close(CMD);
    close(RD)  if ($dord);

1859 1860 1861 1862 1863 1864 1865 1866 1867
    $end_time = time;
    my $delta = $end_time - $start_time;

    if ($delta == 1) {
	doprint "[1 second] ";
    } else {
	doprint "[$delta seconds] ";
    }

1868 1869 1870 1871 1872
    if ($hit_timeout) {
	$run_command_status = 1;
    }

    if ($run_command_status) {
S
Steven Rostedt 已提交
1873 1874 1875 1876 1877
	doprint "FAILED!\n";
    } else {
	doprint "SUCCESS\n";
    }

1878
    return !$run_command_status;
1879 1880
}

1881
sub run_ssh {
1882
    my ($cmd, $timeout) = @_;
1883 1884 1885
    my $cp_exec = $ssh_exec;

    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1886
    return run_command "$cp_exec", undef , $timeout;
1887 1888 1889
}

sub run_scp {
1890
    my ($src, $dst, $cp_scp) = @_;
1891 1892 1893 1894 1895 1896 1897

    $cp_scp =~ s/\$SRC_FILE/$src/g;
    $cp_scp =~ s/\$DST_FILE/$dst/g;

    return run_command "$cp_scp";
}

1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913
sub run_scp_install {
    my ($src, $dst) = @_;

    my $cp_scp = $scp_to_target_install;

    return run_scp($src, $dst, $cp_scp);
}

sub run_scp_mod {
    my ($src, $dst) = @_;

    my $cp_scp = $scp_to_target;

    return run_scp($src, $dst, $cp_scp);
}

1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950
sub _get_grub_index {

    my ($command, $target, $skip) = @_;

    return if (defined($grub_number) && defined($last_grub_menu) &&
	       $last_grub_menu eq $grub_menu && defined($last_machine) &&
	       $last_machine eq $machine);

    doprint "Find $reboot_type menu ... ";
    $grub_number = -1;

    my $ssh_grub = $ssh_exec;
    $ssh_grub =~ s,\$SSH_COMMAND,$command,g;

    open(IN, "$ssh_grub |")
	or dodie "unable to execute $command";

    my $found = 0;

    while (<IN>) {
	if (/$target/) {
	    $grub_number++;
	    $found = 1;
	    last;
	} elsif (/$skip/) {
	    $grub_number++;
	}
    }
    close(IN);

    dodie "Could not find '$grub_menu' through $command on $machine"
	if (!$found);
    doprint "$grub_number\n";
    $last_grub_menu = $grub_menu;
    $last_machine = $machine;
}

1951 1952
sub get_grub_index {

M
Masayoshi Mizuma 已提交
1953 1954 1955 1956
    my $command;
    my $target;
    my $skip;
    my $grub_menu_qt;
S
Steven Rostedt 已提交
1957

M
Masayoshi Mizuma 已提交
1958
    if ($reboot_type !~ /^grub/) {
1959 1960
	return;
    }
1961

M
Masayoshi Mizuma 已提交
1962
    $grub_menu_qt = quotemeta($grub_menu);
1963

M
Masayoshi Mizuma 已提交
1964 1965 1966 1967 1968 1969 1970 1971
    if ($reboot_type eq "grub") {
	$command = "cat /boot/grub/menu.lst";
	$target = '^\s*title\s+' . $grub_menu_qt . '\s*$';
	$skip = '^\s*title\s';
    } elsif ($reboot_type eq "grub2") {
	$command = "cat $grub_file";
	$target = '^menuentry.*' . $grub_menu_qt;
	$skip = '^menuentry\s|^submenu\s';
1972 1973 1974 1975
    } elsif ($reboot_type eq "grub2bls") {
        $command = $grub_bls_get;
        $target = '^title=.*' . $grub_menu_qt;
        $skip = '^title=';
M
Masayoshi Mizuma 已提交
1976 1977
    } else {
	return;
1978 1979
    }

M
Masayoshi Mizuma 已提交
1980
    _get_grub_index($command, $target, $skip);
S
Steven Rostedt 已提交
1981 1982 1983 1984 1985
}

sub wait_for_input
{
    my ($fp, $time) = @_;
1986
    my $start_time;
S
Steven Rostedt 已提交
1987
    my $rin;
1988 1989 1990
    my $rout;
    my $nr;
    my $buf;
S
Steven Rostedt 已提交
1991 1992 1993 1994 1995 1996 1997 1998 1999
    my $line;
    my $ch;

    if (!defined($time)) {
	$time = $timeout;
    }

    $rin = '';
    vec($rin, fileno($fp), 1) = 1;
2000
    vec($rin, fileno(\*STDIN), 1) = 1;
S
Steven Rostedt 已提交
2001

2002 2003
    $start_time = time;

2004 2005
    while (1) {
	$nr = select($rout=$rin, undef, undef, $time);
S
Steven Rostedt 已提交
2006

2007
	last if ($nr <= 0);
S
Steven Rostedt 已提交
2008

2009 2010
	# copy data from stdin to the console
	if (vec($rout, fileno(\*STDIN), 1) == 1) {
2011 2012
	    $nr = sysread(\*STDIN, $buf, 1000);
	    syswrite($fp, $buf, $nr) if ($nr > 0);
2013 2014
	}

2015 2016 2017
	# The timeout is based on time waiting for the fp data
	if (vec($rout, fileno($fp), 1) != 1) {
	    last if (defined($time) && (time - $start_time > $time));
2018 2019 2020 2021
	    next;
	}

	$line = "";
S
Steven Rostedt 已提交
2022

2023 2024 2025 2026 2027 2028
	# try to read one char at a time
	while (sysread $fp, $ch, 1) {
	    $line .= $ch;
	    last if ($ch eq "\n");
	}

2029
	last if (!length($line));
2030 2031 2032

	return $line;
    }
2033
    return undef;
S
Steven Rostedt 已提交
2034 2035
}

2036
sub reboot_to {
2037 2038 2039 2040
    if (defined($switch_to_test)) {
	run_command $switch_to_test;
    }

2041
    if ($reboot_type eq "grub") {
2042
	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
S
Steven Rostedt 已提交
2043 2044
    } elsif ($reboot_type eq "grub2") {
	run_ssh "$grub_reboot $grub_number";
2045 2046
    } elsif ($reboot_type eq "syslinux") {
	run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path";
2047 2048
    } elsif (defined $reboot_script) {
	run_command "$reboot_script";
2049
    }
2050
    reboot;
S
Steven Rostedt 已提交
2051 2052
}

2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073
sub get_sha1 {
    my ($commit) = @_;

    doprint "git rev-list --max-count=1 $commit ... ";
    my $sha1 = `git rev-list --max-count=1 $commit`;
    my $ret = $?;

    logit $sha1;

    if ($ret) {
	doprint "FAILED\n";
	dodie "Failed to get git $commit";
    }

    print "SUCCESS\n";

    chomp $sha1;

    return $sha1;
}

2074
sub monitor {
S
Steven Rostedt 已提交
2075 2076
    my $booted = 0;
    my $bug = 0;
2077
    my $bug_ignored = 0;
2078
    my $skip_call_trace = 0;
2079
    my $loops;
S
Steven Rostedt 已提交
2080

2081 2082
    my $start_time = time;

2083
    wait_for_monitor 5;
S
Steven Rostedt 已提交
2084 2085 2086 2087

    my $line;
    my $full_line = "";

2088
    open(DMESG, "> $dmesg") or
2089
	dodie "unable to write to $dmesg";
S
Steven Rostedt 已提交
2090

2091
    reboot_to;
S
Steven Rostedt 已提交
2092

2093 2094
    my $success_start;
    my $failure_start;
2095 2096
    my $monitor_start = time;
    my $done = 0;
2097
    my $version_found = 0;
2098

2099
    while (!$done) {
S
Steven Rostedt 已提交
2100

2101 2102 2103 2104 2105 2106 2107 2108 2109 2110
	if ($bug && defined($stop_after_failure) &&
	    $stop_after_failure >= 0) {
	    my $time = $stop_after_failure - (time - $failure_start);
	    $line = wait_for_input($monitor_fp, $time);
	    if (!defined($line)) {
		doprint "bug timed out after $booted_timeout seconds\n";
		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
		last;
	    }
	} elsif ($booted) {
2111
	    $line = wait_for_input($monitor_fp, $booted_timeout);
2112 2113 2114 2115 2116
	    if (!defined($line)) {
		my $s = $booted_timeout == 1 ? "" : "s";
		doprint "Successful boot found: break after $booted_timeout second$s\n";
		last;
	    }
2117
	} else {
2118
	    $line = wait_for_input($monitor_fp);
2119 2120 2121 2122 2123
	    if (!defined($line)) {
		my $s = $timeout == 1 ? "" : "s";
		doprint "Timed out after $timeout second$s\n";
		last;
	    }
2124
	}
S
Steven Rostedt 已提交
2125 2126

	doprint $line;
2127
	print DMESG $line;
S
Steven Rostedt 已提交
2128 2129 2130 2131

	# we are not guaranteed to get a full line
	$full_line .= $line;

2132
	if ($full_line =~ /$success_line/) {
S
Steven Rostedt 已提交
2133
	    $booted = 1;
2134 2135 2136 2137 2138 2139 2140 2141 2142 2143
	    $success_start = time;
	}

	if ($booted && defined($stop_after_success) &&
	    $stop_after_success >= 0) {
	    my $now = time;
	    if ($now - $success_start >= $stop_after_success) {
		doprint "Test forced to stop after $stop_after_success seconds after success\n";
		last;
	    }
S
Steven Rostedt 已提交
2144 2145
	}

2146 2147 2148 2149
	if ($full_line =~ /\[ backtrace testing \]/) {
	    $skip_call_trace = 1;
	}

S
Steven Rostedt 已提交
2150
	if ($full_line =~ /call trace:/i) {
2151 2152 2153 2154 2155 2156 2157
	    if (!$bug && !$skip_call_trace) {
		if ($ignore_errors) {
		    $bug_ignored = 1;
		} else {
		    $bug = 1;
		    $failure_start = time;
		}
2158 2159 2160 2161 2162 2163 2164 2165 2166 2167
	    }
	}

	if ($bug && defined($stop_after_failure) &&
	    $stop_after_failure >= 0) {
	    my $now = time;
	    if ($now - $failure_start >= $stop_after_failure) {
		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
		last;
	    }
2168 2169 2170 2171 2172 2173 2174
	}

	if ($full_line =~ /\[ end of backtrace testing \]/) {
	    $skip_call_trace = 0;
	}

	if ($full_line =~ /Kernel panic -/) {
2175
	    $failure_start = time;
S
Steven Rostedt 已提交
2176 2177 2178
	    $bug = 1;
	}

2179 2180 2181 2182 2183 2184 2185 2186
	# Detect triple faults by testing the banner
	if ($full_line =~ /\bLinux version (\S+).*\n/) {
	    if ($1 eq $version) {
		$version_found = 1;
	    } elsif ($version_found && $detect_triplefault) {
		# We already booted into the kernel we are testing,
		# but now we booted into another kernel?
		# Consider this a triple fault.
M
Masanari Iida 已提交
2187
		doprint "Already booted in Linux kernel $version, but now\n";
2188 2189 2190 2191 2192 2193 2194
		doprint "we booted into Linux kernel $1.\n";
		doprint "Assuming that this is a triple fault.\n";
		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
		last;
	    }
	}

S
Steven Rostedt 已提交
2195 2196 2197
	if ($line =~ /\n/) {
	    $full_line = "";
	}
2198 2199 2200

	if ($stop_test_after > 0 && !$booted && !$bug) {
	    if (time - $monitor_start > $stop_test_after) {
2201
		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
2202 2203 2204
		$done = 1;
	    }
	}
S
Steven Rostedt 已提交
2205 2206
    }

2207 2208 2209
    my $end_time = time;
    $reboot_time = $end_time - $start_time;

2210
    close(DMESG);
S
Steven Rostedt 已提交
2211

2212
    if ($bug) {
2213
	return 0 if ($in_bisect);
2214
	fail "failed - got a bug report" and return 0;
S
Steven Rostedt 已提交
2215 2216
    }

2217
    if (!$booted) {
2218
	return 0 if ($in_bisect);
2219
	fail "failed - never got a boot prompt." and return 0;
S
Steven Rostedt 已提交
2220
    }
2221

2222 2223 2224 2225
    if ($bug_ignored) {
	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
    }

2226
    return 1;
S
Steven Rostedt 已提交
2227 2228
}

2229 2230 2231 2232 2233 2234 2235 2236
sub eval_kernel_version {
    my ($option) = @_;

    $option =~ s/\$KERNEL_VERSION/$version/g;

    return $option;
}

2237 2238 2239 2240
sub do_post_install {

    return if (!defined($post_install));

2241
    my $cp_post_install = eval_kernel_version $post_install;
2242 2243 2244 2245
    run_command "$cp_post_install" or
	dodie "Failed to run post install";
}

2246 2247 2248 2249 2250 2251 2252 2253
# Sometimes the reboot fails, and will hang. We try to ssh to the box
# and if we fail, we force another reboot, that should powercycle it.
sub test_booted {
    if (!run_ssh "echo testing connection") {
	reboot $sleep_time;
    }
}

S
Steven Rostedt 已提交
2254 2255
sub install {

2256 2257
    return if ($no_install);

2258 2259
    my $start_time = time;

S
Steven Rostedt 已提交
2260 2261 2262 2263 2264 2265
    if (defined($pre_install)) {
	my $cp_pre_install = eval_kernel_version $pre_install;
	run_command "$cp_pre_install" or
	    dodie "Failed to run pre install";
    }

2266 2267
    my $cp_target = eval_kernel_version $target_image;

2268 2269
    test_booted;

2270
    run_scp_install "$outputdir/$build_target", "$cp_target" or
2271
	dodie "failed to copy image";
S
Steven Rostedt 已提交
2272

2273
    my $install_mods = 0;
S
Steven Rostedt 已提交
2274

2275 2276
    # should we process modules?
    $install_mods = 0;
2277
    open(IN, "$output_config") or dodie("Can't read config file");
2278 2279
    while (<IN>) {
	if (/CONFIG_MODULES(=y)?/) {
2280 2281 2282 2283
	    if (defined($1)) {
		$install_mods = 1;
		last;
	    }
2284
	}
2285 2286
    }
    close(IN);
2287

2288
    if (!$install_mods) {
2289
	do_post_install;
2290
	doprint "No modules needed\n";
2291 2292
	my $end_time = time;
	$install_time = $end_time - $start_time;
2293 2294
	return;
    }
S
Steven Rostedt 已提交
2295

2296
    run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or
2297
	dodie "Failed to install modules";
2298

2299
    my $modlib = "/lib/modules/$version";
2300
    my $modtar = "ktest-mods.tar.bz2";
2301

2302
    run_ssh "rm -rf $modlib" or
2303
	dodie "failed to remove old mods: $modlib";
2304

2305
    # would be nice if scp -r did not follow symbolic links
2306
    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
2307 2308
	dodie "making tarball";

2309
    run_scp_mod "$tmpdir/$modtar", "/tmp" or
2310 2311
	dodie "failed to copy modules";

2312
    unlink "$tmpdir/$modtar";
2313

2314
    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
2315
	dodie "failed to tar modules";
S
Steven Rostedt 已提交
2316

2317
    run_ssh "rm -f /tmp/$modtar";
2318

2319
    do_post_install;
2320 2321 2322

    my $end_time = time;
    $install_time = $end_time - $start_time;
S
Steven Rostedt 已提交
2323 2324
}

2325 2326
sub get_version {
    # get the release name
2327
    return if ($have_version);
2328
    doprint "$make kernelrelease ... ";
2329
    $version = `$make -s kernelrelease | tail -1`;
2330 2331
    chomp($version);
    doprint "$version\n";
2332
    $have_version = 1;
2333 2334
}

2335
sub start_monitor_and_install {
2336
    # Make sure the stable kernel has finished booting
2337 2338 2339 2340 2341 2342 2343

    # Install bisects, don't need console
    if (defined $console) {
	start_monitor;
	wait_for_monitor 5;
	end_monitor;
    }
2344

2345 2346 2347 2348
    get_grub_index;
    get_version;
    install;

2349
    start_monitor if (defined $console);
2350 2351 2352
    return monitor;
}

2353 2354 2355
my $check_build_re = ".*:.*(warning|error|Error):.*";
my $utf8_quote = "\\x{e2}\\x{80}(\\x{98}|\\x{99})";

2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376
sub process_warning_line {
    my ($line) = @_;

    chomp $line;

    # for distcc heterogeneous systems, some compilers
    # do things differently causing warning lines
    # to be slightly different. This makes an attempt
    # to fixe those issues.

    # chop off the index into the line
    # using distcc, some compilers give different indexes
    # depending on white space
    $line =~ s/^(\s*\S+:\d+:)\d+/$1/;

    # Some compilers use UTF-8 extended for quotes and some don't.
    $line =~ s/$utf8_quote/'/g;

    return $line;
}

2377 2378 2379 2380 2381
# Read buildlog and check against warnings file for any
# new warnings.
#
# Returns 1 if OK
#         0 otherwise
S
Steven Rostedt 已提交
2382
sub check_buildlog {
2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396
    return 1 if (!defined $warnings_file);

    my %warnings_list;

    # Failed builds should not reboot the target
    my $save_no_reboot = $no_reboot;
    $no_reboot = 1;

    if (-f $warnings_file) {
	open(IN, $warnings_file) or
	    dodie "Error opening $warnings_file";

	while (<IN>) {
	    if (/$check_build_re/) {
2397 2398 2399
		my $warning = process_warning_line $_;
		
		$warnings_list{$warning} = 1;
2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410
	    }
	}
	close(IN);
    }

    # If warnings file didn't exist, and WARNINGS_FILE exist,
    # then we fail on any warning!

    open(IN, $buildlog) or dodie "Can't open $buildlog";
    while (<IN>) {
	if (/$check_build_re/) {
2411
	    my $warning = process_warning_line $_;
2412

2413
	    if (!defined $warnings_list{$warning}) {
2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424
		fail "New warning found (not in $warnings_file)\n$_\n";
		$no_reboot = $save_no_reboot;
		return 0;
	    }
	}
    }
    $no_reboot = $save_no_reboot;
    close(IN);
}

sub check_patch_buildlog {
S
Steven Rostedt 已提交
2425 2426 2427 2428
    my ($patch) = @_;

    my @files = `git show $patch | diffstat -l`;

2429 2430 2431 2432
    foreach my $file (@files) {
	chomp $file;
    }

S
Steven Rostedt 已提交
2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447
    open(IN, "git show $patch |") or
	dodie "failed to show $patch";
    while (<IN>) {
	if (m,^--- a/(.*),) {
	    chomp $1;
	    $files[$#files] = $1;
	}
    }
    close(IN);

    open(IN, $buildlog) or dodie "Can't open $buildlog";
    while (<IN>) {
	if (/^\s*(.*?):.*(warning|error)/) {
	    my $err = $1;
	    foreach my $file (@files) {
2448
		my $fullpath = "$builddir/$file";
S
Steven Rostedt 已提交
2449
		if ($file eq $err || $fullpath eq $err) {
2450
		    fail "$file built with warnings" and return 0;
S
Steven Rostedt 已提交
2451 2452 2453 2454 2455
		}
	    }
	}
    }
    close(IN);
2456 2457

    return 1;
S
Steven Rostedt 已提交
2458 2459
}

2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490
sub apply_min_config {
    my $outconfig = "$output_config.new";

    # Read the config file and remove anything that
    # is in the force_config hash (from minconfig and others)
    # then add the force config back.

    doprint "Applying minimum configurations into $output_config.new\n";

    open (OUT, ">$outconfig") or
	dodie "Can't create $outconfig";

    if (-f $output_config) {
	open (IN, $output_config) or
	    dodie "Failed to open $output_config";
	while (<IN>) {
	    if (/^(# )?(CONFIG_[^\s=]*)/) {
		next if (defined($force_config{$2}));
	    }
	    print OUT;
	}
	close IN;
    }
    foreach my $config (keys %force_config) {
	print OUT "$force_config{$config}\n";
    }
    close OUT;

    run_command "mv $outconfig $output_config";
}

2491 2492
sub make_oldconfig {

2493 2494 2495 2496 2497
    my @force_list = keys %force_config;

    if ($#force_list >= 0) {
	apply_min_config;
    }
2498

2499 2500
    if (!run_command "$make olddefconfig") {
	# Perhaps olddefconfig doesn't exist in this version of the kernel
2501 2502 2503 2504 2505 2506 2507 2508
	# try oldnoconfig
	doprint "olddefconfig failed, trying make oldnoconfig\n";
	if (!run_command "$make oldnoconfig") {
	    doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
	    # try a yes '' | oldconfig
	    run_command "yes '' | $make oldconfig" or
		dodie "failed make config oldconfig";
	}
2509 2510 2511
    }
}

2512 2513 2514 2515
# read a config file and use this to force new configs.
sub load_force_config {
    my ($config) = @_;

2516
    doprint "Loading force configs from $config\n";
2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529
    open(IN, $config) or
	dodie "failed to read $config";
    while (<IN>) {
	chomp;
	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
	    $force_config{$1} = $_;
	} elsif (/^# (CONFIG_\S*) is not set/) {
	    $force_config{$1} = $_;
	}
    }
    close IN;
}

S
Steven Rostedt 已提交
2530 2531
sub build {
    my ($type) = @_;
2532

2533 2534
    unlink $buildlog;

2535 2536
    my $start_time = time;

2537 2538 2539 2540
    # Failed builds should not reboot the target
    my $save_no_reboot = $no_reboot;
    $no_reboot = 1;

2541 2542 2543
    # Calculate a new version from here.
    $have_version = 0;

2544 2545 2546 2547 2548 2549 2550 2551
    if (defined($pre_build)) {
	my $ret = run_command $pre_build;
	if (!$ret && defined($pre_build_die) &&
	    $pre_build_die) {
	    dodie "failed to pre_build\n";
	}
    }

2552
    if ($type =~ /^useconfig:(.*)/) {
2553
	run_command "cp $1 $output_config" or
2554
	    dodie "could not copy $1 to .config";
2555

2556 2557 2558
	$type = "oldconfig";
    }

2559 2560
    # old config can ask questions
    if ($type eq "oldconfig") {
2561
	$type = "olddefconfig";
2562 2563

	# allow for empty configs
2564
	run_command "touch $output_config";
2565

2566 2567 2568
	if (!$noclean) {
	    run_command "mv $output_config $outputdir/config_temp" or
		dodie "moving .config";
S
Steven Rostedt 已提交
2569

2570
	    run_command "$make mrproper" or dodie "make mrproper";
S
Steven Rostedt 已提交
2571

2572 2573 2574
	    run_command "mv $outputdir/config_temp $output_config" or
		dodie "moving config_temp";
	}
2575 2576

    } elsif (!$noclean) {
2577
	unlink "$output_config";
2578
	run_command "$make mrproper" or
2579 2580
	    dodie "make mrproper";
    }
S
Steven Rostedt 已提交
2581 2582

    # add something to distinguish this build
2583 2584
    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
    print OUT "$localversion\n";
S
Steven Rostedt 已提交
2585 2586
    close(OUT);

2587
    if (defined($minconfig)) {
2588
	load_force_config($minconfig);
S
Steven Rostedt 已提交
2589 2590
    }

2591
    if ($type ne "olddefconfig") {
2592
	run_command "$make $type" or
2593 2594
	    dodie "failed make config";
    }
2595 2596
    # Run old config regardless, to enforce min configurations
    make_oldconfig;
S
Steven Rostedt 已提交
2597

2598
    my $build_ret = run_command "$make $build_options", $buildlog;
2599 2600

    if (defined($post_build)) {
2601 2602 2603
	# Because a post build may change the kernel version
	# do it now.
	get_version;
2604 2605 2606 2607 2608 2609 2610 2611
	my $ret = run_command $post_build;
	if (!$ret && defined($post_build_die) &&
	    $post_build_die) {
	    dodie "failed to post_build\n";
	}
    }

    if (!$build_ret) {
2612
	# bisect may need this to pass
2613 2614 2615 2616
	if ($in_bisect) {
	    $no_reboot = $save_no_reboot;
	    return 0;
	}
2617
	fail "failed build" and return 0;
S
Steven Rostedt 已提交
2618
    }
2619

2620 2621
    $no_reboot = $save_no_reboot;

2622 2623 2624
    my $end_time = time;
    $build_time = $end_time - $start_time;

2625
    return 1;
S
Steven Rostedt 已提交
2626 2627
}

2628
sub halt {
2629
    if (!run_ssh "halt" or defined($power_off)) {
2630 2631 2632 2633 2634
	if (defined($poweroff_after_halt)) {
	    sleep $poweroff_after_halt;
	    run_command "$power_off";
	}
    } else {
2635
	# nope? the zap it!
2636
	run_command "$power_off";
2637 2638 2639
    }
}

2640 2641 2642
sub success {
    my ($i) = @_;

2643 2644
    $successes++;

S
Steven Rostedt 已提交
2645 2646 2647 2648 2649 2650
    my $name = "";

    if (defined($test_name)) {
	$name = " ($test_name)";
    }

2651 2652
    print_times;

2653 2654
    doprint "\n\n*******************************************\n";
    doprint     "*******************************************\n";
S
Steven Rostedt 已提交
2655
    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
2656 2657 2658
    doprint     "*******************************************\n";
    doprint     "*******************************************\n";

2659 2660 2661 2662
    if (defined($store_successes)) {
        save_logs "success", $store_successes;
    }

2663
    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
2664
	doprint "Reboot and wait $sleep_time seconds\n";
2665
	reboot_to_good $sleep_time;
2666
    }
2667 2668 2669 2670

    if (defined($post_test)) {
	run_command $post_test;
    }
2671 2672
}

S
Steven Rostedt 已提交
2673 2674
sub answer_bisect {
    for (;;) {
2675
	doprint "Pass, fail, or skip? [p/f/s]";
S
Steven Rostedt 已提交
2676 2677 2678 2679 2680 2681
	my $ans = <STDIN>;
	chomp $ans;
	if ($ans eq "p" || $ans eq "P") {
	    return 1;
	} elsif ($ans eq "f" || $ans eq "F") {
	    return 0;
2682 2683
	} elsif ($ans eq "s" || $ans eq "S") {
	    return -1;
S
Steven Rostedt 已提交
2684
	} else {
2685
	    print "Please answer 'p', 'f', or 's'\n";
S
Steven Rostedt 已提交
2686 2687 2688 2689
	}
    }
}

2690 2691
sub child_run_test {

2692
    # child should have no power
2693 2694 2695
    $reboot_on_error = 0;
    $poweroff_on_error = 0;
    $die_on_failure = 1;
2696

2697
    run_command $run_test, $testlog;
R
Rabin Vincent 已提交
2698

2699
    exit $run_command_status;
2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713
}

my $child_done;

sub child_finished {
    $child_done = 1;
}

sub do_run_test {
    my $child_pid;
    my $child_exit;
    my $line;
    my $full_line;
    my $bug = 0;
2714
    my $bug_ignored = 0;
2715

2716 2717
    my $start_time = time;

2718
    wait_for_monitor 1;
2719

2720
    doprint "run test $run_test\n";
2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732

    $child_done = 0;

    $SIG{CHLD} = qw(child_finished);

    $child_pid = fork;

    child_run_test if (!$child_pid);

    $full_line = "";

    do {
2733
	$line = wait_for_input($monitor_fp, 1);
2734 2735 2736 2737
	if (defined($line)) {

	    # we are not guaranteed to get a full line
	    $full_line .= $line;
2738
	    doprint $line;
2739 2740

	    if ($full_line =~ /call trace:/i) {
2741 2742 2743 2744 2745
		if ($ignore_errors) {
		    $bug_ignored = 1;
		} else {
		    $bug = 1;
		}
2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757
	    }

	    if ($full_line =~ /Kernel panic -/) {
		$bug = 1;
	    }

	    if ($line =~ /\n/) {
		$full_line = "";
	    }
	}
    } while (!$child_done && !$bug);

2758 2759 2760 2761
    if (!$bug && $bug_ignored) {
	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
    }

2762
    if ($bug) {
2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775
	my $failure_start = time;
	my $now;
	do {
	    $line = wait_for_input($monitor_fp, 1);
	    if (defined($line)) {
		doprint $line;
	    }
	    $now = time;
	    if ($now - $failure_start >= $stop_after_failure) {
		last;
	    }
	} while (defined($line));

2776 2777 2778 2779 2780 2781
	doprint "Detected kernel crash!\n";
	# kill the child with extreme prejudice
	kill 9, $child_pid;
    }

    waitpid $child_pid, 0;
2782
    $child_exit = $? >> 8;
2783

2784 2785 2786
    my $end_time = time;
    $test_time = $end_time - $start_time;

2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823
    if (!$bug && $in_bisect) {
	if (defined($bisect_ret_good)) {
	    if ($child_exit == $bisect_ret_good) {
		return 1;
	    }
	}
	if (defined($bisect_ret_skip)) {
	    if ($child_exit == $bisect_ret_skip) {
		return -1;
	    }
	}
	if (defined($bisect_ret_abort)) {
	    if ($child_exit == $bisect_ret_abort) {
		fail "test abort" and return -2;
	    }
	}
	if (defined($bisect_ret_bad)) {
	    if ($child_exit == $bisect_ret_skip) {
		return 0;
	    }
	}
	if (defined($bisect_ret_default)) {
	    if ($bisect_ret_default eq "good") {
		return 1;
	    } elsif ($bisect_ret_default eq "bad") {
		return 0;
	    } elsif ($bisect_ret_default eq "skip") {
		return -1;
	    } elsif ($bisect_ret_default eq "abort") {
		return -2;
	    } else {
		fail "unknown default action: $bisect_ret_default"
		    and return -2;
	    }
	}
    }

2824
    if ($bug || $child_exit) {
2825 2826
	return 0 if $in_bisect;
	fail "test failed" and return 0;
2827
    }
2828
    return 1;
2829 2830
}

2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849
sub run_git_bisect {
    my ($command) = @_;

    doprint "$command ... ";

    my $output = `$command 2>&1`;
    my $ret = $?;

    logit $output;

    if ($ret) {
	doprint "FAILED\n";
	dodie "Failed to git bisect";
    }

    doprint "SUCCESS\n";
    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
	doprint "$1 [$2]\n";
    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
2850
	$bisect_bad_commit = $1;
2851 2852 2853 2854 2855 2856 2857 2858 2859 2860
	doprint "Found bad commit... $1\n";
	return 0;
    } else {
	# we already logged it, just print it now.
	print $output;
    }

    return 1;
}

S
Steven Rostedt 已提交
2861 2862
sub bisect_reboot {
    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
2863
    reboot_to_good $bisect_sleep_time;
S
Steven Rostedt 已提交
2864 2865 2866
}

# returns 1 on success, 0 on failure, -1 on skip
2867 2868
sub run_bisect_test {
    my ($type, $buildtype) = @_;
2869

2870
    my $failed = 0;
2871 2872 2873 2874
    my $result;
    my $output;
    my $ret;

2875 2876 2877
    $in_bisect = 1;

    build $buildtype or $failed = 1;
2878 2879

    if ($type ne "build") {
S
Steven Rostedt 已提交
2880 2881 2882 2883
	if ($failed && $bisect_skip) {
	    $in_bisect = 0;
	    return -1;
	}
2884
	dodie "Failed on build" if $failed;
2885 2886

	# Now boot the box
2887
	start_monitor_and_install or $failed = 1;
2888 2889

	if ($type ne "boot") {
S
Steven Rostedt 已提交
2890 2891 2892 2893 2894 2895
	    if ($failed && $bisect_skip) {
		end_monitor;
		bisect_reboot;
		$in_bisect = 0;
		return -1;
	    }
2896
	    dodie "Failed on boot" if $failed;
2897

2898
	    do_run_test or $failed = 1;
2899
	}
2900
	end_monitor;
2901 2902 2903
    }

    if ($failed) {
2904
	$result = 0;
2905
    } else {
2906 2907
	$result = 1;
    }
2908 2909 2910 2911 2912

    # reboot the box to a kernel we can ssh to
    if ($type ne "build") {
	bisect_reboot;
    }
2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924
    $in_bisect = 0;

    return $result;
}

sub run_bisect {
    my ($type) = @_;
    my $buildtype = "oldconfig";

    # We should have a minconfig to use?
    if (defined($minconfig)) {
	$buildtype = "useconfig:$minconfig";
2925 2926
    }

2927 2928 2929
    # If the user sets bisect_tries to less than 1, then no tries
    # is a success.
    my $ret = 1;
2930

2931 2932
    # Still let the user manually decide that though.
    if ($bisect_tries < 1 && $bisect_manual) {
S
Steven Rostedt 已提交
2933 2934
	$ret = answer_bisect;
    }
2935

2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949
    for (my $i = 0; $i < $bisect_tries; $i++) {
	if ($bisect_tries > 1) {
	    my $t = $i + 1;
	    doprint("Running bisect trial $t of $bisect_tries:\n");
	}
	$ret = run_bisect_test $type, $buildtype;

	if ($bisect_manual) {
	    $ret = answer_bisect;
	}

	last if (!$ret);
    }

2950
    # Are we looking for where it worked, not failed?
2951
    if ($reverse_bisect && $ret >= 0) {
2952
	$ret = !$ret;
2953 2954
    }

S
Steven Rostedt 已提交
2955
    if ($ret > 0) {
2956
	return "good";
S
Steven Rostedt 已提交
2957
    } elsif ($ret == 0) {
2958
	return  "bad";
S
Steven Rostedt 已提交
2959 2960 2961
    } elsif ($bisect_skip) {
	doprint "HIT A BAD COMMIT ... SKIPPING\n";
	return "skip";
2962
    }
2963 2964
}

2965 2966 2967
sub update_bisect_replay {
    my $tmp_log = "$tmpdir/ktest_bisect_log";
    run_command "git bisect log > $tmp_log" or
2968
	dodie "can't create bisect log";
2969 2970 2971
    return $tmp_log;
}

2972 2973 2974 2975 2976
sub bisect {
    my ($i) = @_;

    my $result;

2977 2978 2979
    dodie "BISECT_GOOD[$i] not defined\n"	if (!defined($bisect_good));
    dodie "BISECT_BAD[$i] not defined\n"	if (!defined($bisect_bad));
    dodie "BISECT_TYPE[$i] not defined\n"	if (!defined($bisect_type));
2980

2981 2982 2983 2984 2985 2986
    my $good = $bisect_good;
    my $bad = $bisect_bad;
    my $type = $bisect_type;
    my $start = $bisect_start;
    my $replay = $bisect_replay;
    my $start_files = $bisect_files;
2987 2988 2989 2990 2991 2992

    if (defined($start_files)) {
	$start_files = " -- " . $start_files;
    } else {
	$start_files = "";
    }
2993

2994 2995 2996 2997
    # convert to true sha1's
    $good = get_sha1($good);
    $bad = get_sha1($bad);

2998
    if (defined($bisect_reverse) && $bisect_reverse == 1) {
2999 3000 3001 3002 3003 3004
	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
	$reverse_bisect = 1;
    } else {
	$reverse_bisect = 0;
    }

3005 3006 3007 3008 3009
    # Can't have a test without having a test to run
    if ($type eq "test" && !defined($run_test)) {
	$type = "boot";
    }

3010 3011 3012
    # Check if a bisect was running
    my $bisect_start_file = "$builddir/.git/BISECT_START";

3013
    my $check = $bisect_check;
3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034
    my $do_check = defined($check) && $check ne "0";

    if ( -f $bisect_start_file ) {
	print "Bisect in progress found\n";
	if ($do_check) {
	    print " If you say yes, then no checks of good or bad will be done\n";
	}
	if (defined($replay)) {
	    print "** BISECT_REPLAY is defined in config file **";
	    print " Ignore config option and perform new git bisect log?\n";
	    if (read_ync " (yes, no, or cancel) ") {
		$replay = update_bisect_replay;
		$do_check = 0;
	    }
	} elsif (read_yn "read git log and continue?") {
	    $replay = update_bisect_replay;
	    $do_check = 0;
	}
    }

    if ($do_check) {
3035 3036

	# get current HEAD
3037
	my $head = get_sha1("HEAD");
3038 3039 3040 3041

	if ($check ne "good") {
	    doprint "TESTING BISECT BAD [$bad]\n";
	    run_command "git checkout $bad" or
3042
		dodie "Failed to checkout $bad";
3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053

	    $result = run_bisect $type;

	    if ($result ne "bad") {
		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
	    }
	}

	if ($check ne "bad") {
	    doprint "TESTING BISECT GOOD [$good]\n";
	    run_command "git checkout $good" or
3054
		dodie "Failed to checkout $good";
3055 3056 3057 3058 3059 3060 3061 3062 3063 3064

	    $result = run_bisect $type;

	    if ($result ne "good") {
		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
	    }
	}

	# checkout where we started
	run_command "git checkout $head" or
3065
	    dodie "Failed to checkout $head";
3066 3067
    }

3068
    run_command "git bisect start$start_files" or
3069
	dodie "could not start bisect";
3070

3071 3072 3073
    if (defined($replay)) {
	run_command "git bisect replay $replay" or
	    dodie "failed to run replay";
3074 3075 3076 3077 3078 3079 3080 3081
    } else {

	run_command "git bisect good $good" or
	    dodie "could not set bisect good to $good";

	run_git_bisect "git bisect bad $bad" or
	    dodie "could not set bisect bad to $bad";

3082 3083
    }

3084 3085 3086 3087 3088 3089
    if (defined($start)) {
	run_command "git checkout $start" or
	    dodie "failed to checkout $start";
    }

    my $test;
3090 3091
    do {
	$result = run_bisect $type;
3092
	$test = run_git_bisect "git bisect $result";
3093
	print_times;
3094
    } while ($test);
3095 3096 3097 3098 3099 3100 3101

    run_command "git bisect log" or
	dodie "could not capture git bisect log";

    run_command "git bisect reset" or
	dodie "could not reset git bisect";

3102
    doprint "Bad commit was [$bisect_bad_commit]\n";
3103

3104 3105 3106
    success $i;
}

3107 3108 3109
# config_ignore holds the configs that were set (or unset) for
# a good config and we will ignore these configs for the rest
# of a config bisect. These configs stay as they were.
3110
my %config_ignore;
3111 3112

# config_set holds what all configs were set as.
3113 3114
my %config_set;

3115 3116
# config_off holds the set of configs that the bad config had disabled.
# We need to record them and set them in the .config when running
3117
# olddefconfig, because olddefconfig keeps the defaults.
3118 3119 3120 3121 3122 3123
my %config_off;

# config_off_tmp holds a set of configs to turn off for now
my @config_off_tmp;

# config_list is the set of configs that are being tested
3124 3125 3126 3127 3128
my %config_list;
my %null_config;

my %dependency;

3129 3130
sub assign_configs {
    my ($hash, $config) = @_;
3131

3132 3133
    doprint "Reading configs from $config\n";

3134 3135 3136 3137
    open (IN, $config)
	or dodie "Failed to read $config";

    while (<IN>) {
3138
	chomp;
3139
	if (/^((CONFIG\S*)=.*)/) {
3140
	    ${$hash}{$2} = $1;
3141 3142
	} elsif (/^(# (CONFIG\S*) is not set)/) {
	    ${$hash}{$2} = $1;
3143 3144 3145 3146 3147 3148
	}
    }

    close(IN);
}

3149 3150 3151 3152 3153 3154
sub process_config_ignore {
    my ($config) = @_;

    assign_configs \%config_ignore, $config;
}

3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172
sub get_dependencies {
    my ($config) = @_;

    my $arr = $dependency{$config};
    if (!defined($arr)) {
	return ();
    }

    my @deps = @{$arr};

    foreach my $dep (@{$arr}) {
	print "ADD DEP $dep\n";
	@deps = (@deps, get_dependencies $dep);
    }

    return @deps;
}

3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187
sub save_config {
    my ($pc, $file) = @_;

    my %configs = %{$pc};

    doprint "Saving configs into $file\n";

    open(OUT, ">$file") or dodie "Can not write to $file";

    foreach my $config (keys %configs) {
	print OUT "$configs{$config}\n";
    }
    close(OUT);
}

3188
sub create_config {
3189 3190 3191 3192 3193 3194 3195 3196
    my ($name, $pc) = @_;

    doprint "Creating old config from $name configs\n";

    save_config $pc, $output_config;

    make_oldconfig;
}
3197 3198 3199 3200

sub run_config_bisect_test {
    my ($type) = @_;

3201 3202 3203 3204 3205 3206 3207
    my $ret = run_bisect_test $type, "oldconfig";

    if ($bisect_manual) {
	$ret = answer_bisect;
    }

    return $ret;
3208 3209
}

3210 3211
sub config_bisect_end {
    my ($good, $bad) = @_;
3212
    my $diffexec = "diff -u";
3213

3214 3215 3216
    if (-f "$builddir/scripts/diffconfig") {
	$diffexec = "$builddir/scripts/diffconfig";
    }
3217
    doprint "\n\n***************************************\n";
3218
    doprint "No more config bisecting possible.\n";
3219
    run_command "$diffexec $good $bad", 1;
3220 3221 3222
    doprint "***************************************\n\n";
}

3223 3224
my $pass = 1;

3225
sub run_config_bisect {
3226
    my ($good, $bad, $last_result) = @_;
3227
    my $reset = "";
3228
    my $cmd;
3229
    my $ret;
3230

3231 3232
    if (!length($last_result)) {
	$reset = "-r";
3233
    }
3234
    run_command "$config_bisect_exec $reset -b $outputdir $good $bad $last_result", 1;
3235

3236 3237 3238 3239 3240 3241 3242
    # config-bisect returns:
    #   0 if there is more to bisect
    #   1 for finding a good config
    #   2 if it can not find any more configs
    #  -1 (255) on error
    if ($run_command_status) {
	return $run_command_status;
3243 3244
    }

3245 3246
    $ret = run_config_bisect_test $config_bisect_type;
    if ($ret) {
3247 3248 3249
        doprint "NEW GOOD CONFIG ($pass)\n";
	system("cp $output_config $tmpdir/good_config.tmp.$pass");
	$pass++;
3250 3251 3252
	# Return 3 for good config
	return 3;
    } else {
3253 3254 3255
        doprint "NEW BAD CONFIG ($pass)\n";
	system("cp $output_config $tmpdir/bad_config.tmp.$pass");
	$pass++;
3256 3257
	# Return 4 for bad config
	return 4;
3258 3259 3260 3261 3262 3263
    }
}

sub config_bisect {
    my ($i) = @_;

3264 3265 3266
    my $good_config;
    my $bad_config;

3267
    my $type = $config_bisect_type;
3268
    my $ret;
3269

3270
    $bad_config = $config_bisect;
3271

3272
    if (defined($config_bisect_good)) {
3273 3274 3275
	$good_config = $config_bisect_good;
    } elsif (defined($minconfig)) {
	$good_config = $minconfig;
3276
    } else {
3277
	doprint "No config specified, checking if defconfig works";
3278
	$ret = run_bisect_test $type, "defconfig";
3279 3280 3281
	if (!$ret) {
	    fail "Have no good config to compare with, please set CONFIG_BISECT_GOOD";
	    return 1;
3282
	}
3283
	$good_config = $output_config;
3284 3285
    }

3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303
    if (!defined($config_bisect_exec)) {
	# First check the location that ktest.pl ran
	my @locations = ( "$pwd/config-bisect.pl",
			  "$dirname/config-bisect.pl",
			  "$builddir/tools/testing/ktest/config-bisect.pl",
			  undef );
	foreach my $loc (@locations) {
	    doprint "loc = $loc\n";
	    $config_bisect_exec = $loc;
	    last if (defined($config_bisect_exec && -x $config_bisect_exec));
	}
	if (!defined($config_bisect_exec)) {
	    fail "Could not find an executable config-bisect.pl\n",
		"  Set CONFIG_BISECT_EXEC to point to config-bisect.pl";
	    return 1;
	}
    }

3304 3305 3306
    # we don't want min configs to cause issues here.
    doprint "Disabling 'MIN_CONFIG' for this test\n";
    undef $minconfig;
3307

3308 3309 3310
    my %good_configs;
    my %bad_configs;
    my %tmp_configs;
3311

3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325
    if (-f "$tmpdir/good_config.tmp" || -f "$tmpdir/bad_config.tmp") {
	if (read_yn "Interrupted config-bisect. Continue (n - will start new)?") {
	    if (-f "$tmpdir/good_config.tmp") {
		$good_config = "$tmpdir/good_config.tmp";
	    } else {
		$good_config = "$tmpdir/good_config";
	    }
	    if (-f "$tmpdir/bad_config.tmp") {
		$bad_config = "$tmpdir/bad_config.tmp";
	    } else {
		$bad_config = "$tmpdir/bad_config";
	    }
	}
    }
3326 3327 3328
    doprint "Run good configs through make oldconfig\n";
    assign_configs \%tmp_configs, $good_config;
    create_config "$good_config", \%tmp_configs;
3329 3330
    $good_config = "$tmpdir/good_config";
    system("cp $output_config $good_config") == 0 or dodie "cp good config";
3331

3332 3333 3334 3335
    doprint "Run bad configs through make oldconfig\n";
    assign_configs \%tmp_configs, $bad_config;
    create_config "$bad_config", \%tmp_configs;
    $bad_config = "$tmpdir/bad_config";
3336
    system("cp $output_config $bad_config") == 0 or dodie "cp bad config";
3337

3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357
    if (defined($config_bisect_check) && $config_bisect_check ne "0") {
	if ($config_bisect_check ne "good") {
	    doprint "Testing bad config\n";

	    $ret = run_bisect_test $type, "useconfig:$bad_config";
	    if ($ret) {
		fail "Bad config succeeded when expected to fail!";
		return 0;
	    }
	}
	if ($config_bisect_check ne "bad") {
	    doprint "Testing good config\n";

	    $ret = run_bisect_test $type, "useconfig:$good_config";
	    if (!$ret) {
		fail "Good config failed when expected to succeed!";
		return 0;
	    }
	}
    }
3358

3359 3360
    my $last_run = "";

3361
    do {
3362 3363 3364 3365 3366 3367
	$ret = run_config_bisect $good_config, $bad_config, $last_run;
	if ($ret == 3) {
	    $last_run = "good";
	} elsif ($ret == 4) {
	    $last_run = "bad";
	}
3368
	print_times;
3369 3370 3371 3372 3373
    } while ($ret == 3 || $ret == 4);

    if ($ret == 2) {
        config_bisect_end "$good_config.tmp", "$bad_config.tmp";
    }
3374 3375

    return $ret if ($ret < 0);
3376 3377 3378 3379

    success $i;
}

3380 3381
sub patchcheck_reboot {
    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
3382
    reboot_to_good $patchcheck_sleep_time;
3383 3384
}

S
Steven Rostedt 已提交
3385 3386 3387
sub patchcheck {
    my ($i) = @_;

3388
    dodie "PATCHCHECK_START[$i] not defined\n"
3389
	if (!defined($patchcheck_start));
3390
    dodie "PATCHCHECK_TYPE[$i] not defined\n"
3391
	if (!defined($patchcheck_type));
S
Steven Rostedt 已提交
3392

3393
    my $start = $patchcheck_start;
S
Steven Rostedt 已提交
3394

3395 3396 3397 3398 3399
    my $cherry = $patchcheck_cherry;
    if (!defined($cherry)) {
	$cherry = 0;
    }

S
Steven Rostedt 已提交
3400
    my $end = "HEAD";
3401 3402
    if (defined($patchcheck_end)) {
	$end = $patchcheck_end;
3403
    } elsif ($cherry) {
3404
	dodie "PATCHCHECK_END must be defined with PATCHCHECK_CHERRY\n";
S
Steven Rostedt 已提交
3405 3406
    }

3407 3408 3409 3410
    # Get the true sha1's since we can use things like HEAD~3
    $start = get_sha1($start);
    $end = get_sha1($end);

3411
    my $type = $patchcheck_type;
S
Steven Rostedt 已提交
3412 3413 3414 3415 3416 3417

    # Can't have a test without having a test to run
    if ($type eq "test" && !defined($run_test)) {
	$type = "boot";
    }

3418 3419 3420 3421 3422 3423 3424
    if ($cherry) {
	open (IN, "git cherry -v $start $end|") or
	    dodie "could not get git list";
    } else {
	open (IN, "git log --pretty=oneline $end|") or
	    dodie "could not get git list";
    }
S
Steven Rostedt 已提交
3425 3426 3427 3428 3429

    my @list;

    while (<IN>) {
	chomp;
3430 3431
	# git cherry adds a '+' we want to remove
	s/^\+ //;
S
Steven Rostedt 已提交
3432 3433 3434 3435 3436
	$list[$#list+1] = $_;
	last if (/^$start/);
    }
    close(IN);

3437 3438 3439 3440 3441 3442 3443
    if (!$cherry) {
	if ($list[$#list] !~ /^$start/) {
	    fail "SHA1 $start not found";
	}

	# go backwards in the list
	@list = reverse @list;
S
Steven Rostedt 已提交
3444 3445
    }

3446 3447 3448 3449
    doprint("Going to test the following commits:\n");
    foreach my $l (@list) {
	doprint "$l\n";
    }
S
Steven Rostedt 已提交
3450 3451

    my $save_clean = $noclean;
3452 3453 3454 3455 3456 3457 3458
    my %ignored_warnings;

    if (defined($ignore_warnings)) {
	foreach my $sha1 (split /\s+/, $ignore_warnings) {
	    $ignored_warnings{$sha1} = 1;
	}
    }
S
Steven Rostedt 已提交
3459 3460 3461 3462 3463 3464

    $in_patchcheck = 1;
    foreach my $item (@list) {
	my $sha1 = $item;
	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;

3465
	doprint "\nProcessing commit \"$item\"\n\n";
S
Steven Rostedt 已提交
3466 3467

	run_command "git checkout $sha1" or
3468
	    dodie "Failed to checkout $sha1";
S
Steven Rostedt 已提交
3469 3470 3471 3472 3473 3474 3475 3476 3477 3478

	# only clean on the first and last patch
	if ($item eq $list[0] ||
	    $item eq $list[$#list]) {
	    $noclean = $save_clean;
	} else {
	    $noclean = 1;
	}

	if (defined($minconfig)) {
3479
	    build "useconfig:$minconfig" or return 0;
S
Steven Rostedt 已提交
3480 3481
	} else {
	    # ?? no config to use?
3482
	    build "oldconfig" or return 0;
S
Steven Rostedt 已提交
3483 3484
	}

3485 3486 3487
	# No need to do per patch checking if warnings file exists
	if (!defined($warnings_file) && !defined($ignored_warnings{$sha1})) {
	    check_patch_buildlog $sha1 or return 0;
3488
	}
S
Steven Rostedt 已提交
3489

3490 3491
	check_buildlog or return 0;

S
Steven Rostedt 已提交
3492 3493
	next if ($type eq "build");

3494 3495
	my $failed = 0;

3496
	start_monitor_and_install or $failed = 1;
3497 3498 3499 3500 3501

	if (!$failed && $type ne "boot"){
	    do_run_test or $failed = 1;
	}
	end_monitor;
3502 3503 3504 3505
	if ($failed) {
	    print_times;
	    return 0;
	}
3506
	patchcheck_reboot;
3507
	print_times;
S
Steven Rostedt 已提交
3508 3509 3510
    }
    $in_patchcheck = 0;
    success $i;
3511 3512

    return 1;
S
Steven Rostedt 已提交
3513 3514
}

3515
my %depends;
3516
my %depcount;
3517 3518 3519 3520 3521 3522
my $iflevel = 0;
my @ifdeps;

# prevent recursion
my %read_kconfigs;

3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540
sub add_dep {
    # $config depends on $dep
    my ($config, $dep) = @_;

    if (defined($depends{$config})) {
	$depends{$config} .= " " . $dep;
    } else {
	$depends{$config} = $dep;
    }

    # record the number of configs depending on $dep
    if (defined $depcount{$dep}) {
	$depcount{$dep}++;
    } else {
	$depcount{$dep} = 1;
    } 
}

3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558
# taken from streamline_config.pl
sub read_kconfig {
    my ($kconfig) = @_;

    my $state = "NONE";
    my $config;
    my @kconfigs;

    my $cont = 0;
    my $line;


    if (! -f $kconfig) {
	doprint "file $kconfig does not exist, skipping\n";
	return;
    }

    open(KIN, "$kconfig")
3559
	or dodie "Can't open $kconfig";
3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586
    while (<KIN>) {
	chomp;

	# Make sure that lines ending with \ continue
	if ($cont) {
	    $_ = $line . " " . $_;
	}

	if (s/\\$//) {
	    $cont = 1;
	    $line = $_;
	    next;
	}

	$cont = 0;

	# collect any Kconfig sources
	if (/^source\s*"(.*)"/) {
	    $kconfigs[$#kconfigs+1] = $1;
	}

	# configs found
	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
	    $state = "NEW";
	    $config = $2;

	    for (my $i = 0; $i < $iflevel; $i++) {
3587
		add_dep $config, $ifdeps[$i];
3588 3589 3590 3591 3592
	    }

	# collect the depends for the config
	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {

3593
	    add_dep $config, $1;
3594 3595

	# Get the configs that select this config
3596 3597 3598 3599
	} elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {

	    # selected by depends on config
	    add_dep $1, $config;
3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673

	# Check for if statements
	} elsif (/^if\s+(.*\S)\s*$/) {
	    my $deps = $1;
	    # remove beginning and ending non text
	    $deps =~ s/^[^a-zA-Z0-9_]*//;
	    $deps =~ s/[^a-zA-Z0-9_]*$//;

	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;

	    $ifdeps[$iflevel++] = join ':', @deps;

	} elsif (/^endif/) {

	    $iflevel-- if ($iflevel);

	# stop on "help"
	} elsif (/^\s*help\s*$/) {
	    $state = "NONE";
	}
    }
    close(KIN);

    # read in any configs that were found.
    foreach $kconfig (@kconfigs) {
	if (!defined($read_kconfigs{$kconfig})) {
	    $read_kconfigs{$kconfig} = 1;
	    read_kconfig("$builddir/$kconfig");
	}
    }
}

sub read_depends {
    # find out which arch this is by the kconfig file
    open (IN, $output_config)
	or dodie "Failed to read $output_config";
    my $arch;
    while (<IN>) {
	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
	    $arch = $1;
	    last;
	}
    }
    close IN;

    if (!defined($arch)) {
	doprint "Could not find arch from config file\n";
	doprint "no dependencies used\n";
	return;
    }

    # arch is really the subarch, we need to know
    # what directory to look at.
    if ($arch eq "i386" || $arch eq "x86_64") {
	$arch = "x86";
    }

    my $kconfig = "$builddir/arch/$arch/Kconfig";

    if (! -f $kconfig && $arch =~ /\d$/) {
	my $orig = $arch;
 	# some subarchs have numbers, truncate them
	$arch =~ s/\d*$//;
	$kconfig = "$builddir/arch/$arch/Kconfig";
	if (! -f $kconfig) {
	    doprint "No idea what arch dir $orig is for\n";
	    doprint "no dependencies used\n";
	    return;
	}
    }

    read_kconfig($kconfig);
}

3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685
sub make_new_config {
    my @configs = @_;

    open (OUT, ">$output_config")
	or dodie "Failed to write $output_config";

    foreach my $config (@configs) {
	print OUT "$config\n";
    }
    close OUT;
}

3686 3687 3688 3689 3690 3691 3692 3693
sub chomp_config {
    my ($config) = @_;

    $config =~ s/CONFIG_//;

    return $config;
}

3694 3695 3696
sub get_depends {
    my ($dep) = @_;

3697
    my $kconfig = chomp_config $dep;
3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717

    $dep = $depends{"$kconfig"};

    # the dep string we have saves the dependencies as they
    # were found, including expressions like ! && ||. We
    # want to split this out into just an array of configs.

    my $valid = "A-Za-z_0-9";

    my @configs;

    while ($dep =~ /[$valid]/) {

	if ($dep =~ /^[^$valid]*([$valid]+)/) {
	    my $conf = "CONFIG_" . $1;

	    $configs[$#configs + 1] = $conf;

	    $dep =~ s/^[^$valid]*[$valid]+//;
	} else {
3718
	    dodie "this should never happen";
3719 3720 3721 3722 3723 3724 3725 3726
	}
    }

    return @configs;
}

my %min_configs;
my %keep_configs;
3727
my %save_configs;
3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746
my %processed_configs;
my %nochange_config;

sub test_this_config {
    my ($config) = @_;

    my $found;

    # if we already processed this config, skip it
    if (defined($processed_configs{$config})) {
	return undef;
    }
    $processed_configs{$config} = 1;

    # if this config failed during this round, skip it
    if (defined($nochange_config{$config})) {
	return undef;
    }

3747
    my $kconfig = chomp_config $config;
3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762

    # Test dependencies first
    if (defined($depends{"$kconfig"})) {
	my @parents = get_depends $config;
	foreach my $parent (@parents) {
	    # if the parent is in the min config, check it first
	    next if (!defined($min_configs{$parent}));
	    $found = test_this_config($parent);
	    if (defined($found)) {
		return $found;
	    }
	}
    }

    # Remove this config from the list of configs
3763
    # do a make olddefconfig and then read the resulting
3764 3765 3766 3767 3768 3769 3770 3771 3772
    # .config to make sure it is missing the config that
    # we had before
    my %configs = %min_configs;
    delete $configs{$config};
    make_new_config ((values %configs), (values %keep_configs));
    make_oldconfig;
    undef %configs;
    assign_configs \%configs, $output_config;

3773 3774 3775
    if (!defined($configs{$config}) || $configs{$config} =~ /^#/) {
	return $config;
    }
3776 3777 3778 3779 3780 3781 3782 3783

    doprint "disabling config $config did not change .config\n";

    $nochange_config{$config} = 1;

    return undef;
}

3784 3785 3786
sub make_min_config {
    my ($i) = @_;

3787 3788 3789 3790 3791 3792
    my $type = $minconfig_type;
    if ($type ne "boot" && $type ne "test") {
	fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" .
	    " make_min_config works only with 'boot' and 'test'\n" and return;
    }

3793 3794 3795
    if (!defined($output_minconfig)) {
	fail "OUTPUT_MIN_CONFIG not defined" and return;
    }
3796 3797 3798 3799 3800 3801

    # If output_minconfig exists, and the start_minconfig
    # came from min_config, than ask if we should use
    # that instead.
    if (-f $output_minconfig && !$start_minconfig_defined) {
	print "$output_minconfig exists\n";
3802 3803 3804 3805 3806 3807
	if (!defined($use_output_minconfig)) {
	    if (read_yn " Use it as minconfig?") {
		$start_minconfig = $output_minconfig;
	    }
	} elsif ($use_output_minconfig > 0) {
	    doprint "Using $output_minconfig as MIN_CONFIG\n";
3808
	    $start_minconfig = $output_minconfig;
3809 3810
	} else {
	    doprint "Set to still use MIN_CONFIG as starting point\n";
3811 3812 3813
	}
    }

3814 3815 3816 3817
    if (!defined($start_minconfig)) {
	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
    }

3818 3819
    my $temp_config = "$tmpdir/temp_config";

3820 3821 3822 3823 3824 3825 3826 3827 3828
    # First things first. We build an allnoconfig to find
    # out what the defaults are that we can't touch.
    # Some are selections, but we really can't handle selections.

    my $save_minconfig = $minconfig;
    undef $minconfig;

    run_command "$make allnoconfig" or return 0;

3829 3830
    read_depends;

3831
    process_config_ignore $output_config;
3832

3833
    undef %save_configs;
3834
    undef %min_configs;
3835 3836 3837 3838

    if (defined($ignore_config)) {
	# make sure the file exists
	`touch $ignore_config`;
3839
	assign_configs \%save_configs, $ignore_config;
3840 3841
    }

3842 3843
    %keep_configs = %save_configs;

3844 3845 3846 3847 3848 3849 3850 3851
    doprint "Load initial configs from $start_minconfig\n";

    # Look at the current min configs, and save off all the
    # ones that were set via the allnoconfig
    assign_configs \%min_configs, $start_minconfig;

    my @config_keys = keys %min_configs;

3852 3853 3854 3855 3856 3857 3858 3859
    # All configs need a depcount
    foreach my $config (@config_keys) {
	my $kconfig = chomp_config $config;
	if (!defined $depcount{$kconfig}) {
		$depcount{$kconfig} = 0;
	}
    }

3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887
    # Remove anything that was set by the make allnoconfig
    # we shouldn't need them as they get set for us anyway.
    foreach my $config (@config_keys) {
	# Remove anything in the ignore_config
	if (defined($keep_configs{$config})) {
	    my $file = $ignore_config;
	    $file =~ s,.*/(.*?)$,$1,;
	    doprint "$config set by $file ... ignored\n";
	    delete $min_configs{$config};
	    next;
	}
	# But make sure the settings are the same. If a min config
	# sets a selection, we do not want to get rid of it if
	# it is not the same as what we have. Just move it into
	# the keep configs.
	if (defined($config_ignore{$config})) {
	    if ($config_ignore{$config} ne $min_configs{$config}) {
		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
		$keep_configs{$config} = $min_configs{$config};
	    } else {
		doprint "$config set by allnoconfig ... ignored\n";
	    }
	    delete $min_configs{$config};
	}
    }

    my $done = 0;
3888
    my $take_two = 0;
3889 3890 3891 3892 3893 3894 3895 3896 3897 3898

    while (!$done) {

	my $config;
	my $found;

	# Now disable each config one by one and do a make oldconfig
	# till we find a config that changes our list.

	my @test_configs = keys %min_configs;
3899 3900 3901 3902 3903 3904

	# Sort keys by who is most dependent on
	@test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
			  @test_configs ;

	# Put configs that did not modify the config at the end.
3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922
	my $reset = 1;
	for (my $i = 0; $i < $#test_configs; $i++) {
	    if (!defined($nochange_config{$test_configs[0]})) {
		$reset = 0;
		last;
	    }
	    # This config didn't change the .config last time.
	    # Place it at the end
	    my $config = shift @test_configs;
	    push @test_configs, $config;
	}

	# if every test config has failed to modify the .config file
	# in the past, then reset and start over.
	if ($reset) {
	    undef %nochange_config;
	}

3923 3924
	undef %processed_configs;

3925 3926
	foreach my $config (@test_configs) {

3927
	    $found = test_this_config $config;
3928

3929
	    last if (defined($found));
3930 3931 3932 3933 3934

	    # oh well, try another config
	}

	if (!defined($found)) {
3935 3936 3937 3938 3939 3940 3941
	    # we could have failed due to the nochange_config hash
	    # reset and try again
	    if (!$take_two) {
		undef %nochange_config;
		$take_two = 1;
		next;
	    }
3942 3943 3944 3945
	    doprint "No more configs found that we can disable\n";
	    $done = 1;
	    last;
	}
3946
	$take_two = 0;
3947 3948 3949 3950 3951 3952 3953 3954 3955

	$config = $found;

	doprint "Test with $config disabled\n";

	# set in_bisect to keep build and monitor from dieing
	$in_bisect = 1;

	my $failed = 0;
3956 3957
	build "oldconfig" or $failed = 1;
	if (!$failed) {
3958
		start_monitor_and_install or $failed = 1;
3959 3960 3961 3962 3963

		if ($type eq "test" && !$failed) {
		    do_run_test or $failed = 1;
		}

3964 3965
		end_monitor;
	}
3966 3967 3968 3969

	$in_bisect = 0;

	if ($failed) {
3970
	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
3971 3972
	    # this config is needed, add it to the ignore list.
	    $keep_configs{$config} = $min_configs{$config};
3973
	    $save_configs{$config} = $min_configs{$config};
3974
	    delete $min_configs{$config};
3975 3976 3977 3978

	    # update new ignore configs
	    if (defined($ignore_config)) {
		open (OUT, ">$temp_config")
3979
		    or dodie "Can't write to $temp_config";
3980 3981
		foreach my $config (keys %save_configs) {
		    print OUT "$save_configs{$config}\n";
3982 3983 3984 3985 3986 3987
		}
		close OUT;
		run_command "mv $temp_config $ignore_config" or
		    dodie "failed to copy update to $ignore_config";
	    }

3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004
	} else {
	    # We booted without this config, remove it from the minconfigs.
	    doprint "$config is not needed, disabling\n";

	    delete $min_configs{$config};

	    # Also disable anything that is not enabled in this config
	    my %configs;
	    assign_configs \%configs, $output_config;
	    my @config_keys = keys %min_configs;
	    foreach my $config (@config_keys) {
		if (!defined($configs{$config})) {
		    doprint "$config is not set, disabling\n";
		    delete $min_configs{$config};
		}
	    }

P
Pavel Machek 已提交
4005
	    # Save off all the current mandatory configs
4006
	    open (OUT, ">$temp_config")
4007
		or dodie "Can't write to $temp_config";
4008 4009 4010 4011 4012 4013 4014
	    foreach my $config (keys %keep_configs) {
		print OUT "$keep_configs{$config}\n";
	    }
	    foreach my $config (keys %min_configs) {
		print OUT "$min_configs{$config}\n";
	    }
	    close OUT;
4015 4016 4017

	    run_command "mv $temp_config $output_minconfig" or
		dodie "failed to copy update to $output_minconfig";
4018 4019 4020
	}

	doprint "Reboot and wait $sleep_time seconds\n";
4021
	reboot_to_good $sleep_time;
4022 4023 4024 4025 4026 4027
    }

    success $i;
    return 1;
}

4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060
sub make_warnings_file {
    my ($i) = @_;

    if (!defined($warnings_file)) {
	dodie "Must define WARNINGS_FILE for make_warnings_file test";
    }

    if ($build_type eq "nobuild") {
	dodie "BUILD_TYPE can not be 'nobuild' for make_warnings_file test";
    }

    build $build_type or dodie "Failed to build";

    open(OUT, ">$warnings_file") or dodie "Can't create $warnings_file";

    open(IN, $buildlog) or dodie "Can't open $buildlog";
    while (<IN>) {

	# Some compilers use UTF-8 extended for quotes
	# for distcc heterogeneous systems, this causes issues
	s/$utf8_quote/'/g;

	if (/$check_build_re/) {
	    print OUT;
	}
    }
    close(IN);

    close(OUT);

    success $i;
}

4061
$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl [config-file]\n";
4062 4063 4064 4065 4066

if ($#ARGV == 0) {
    $ktest_config = $ARGV[0];
    if (! -f $ktest_config) {
	print "$ktest_config does not exist.\n";
4067
	if (!read_yn "Create it?") {
4068 4069 4070 4071 4072 4073
	    exit 0;
	}
    }
}

if (! -f $ktest_config) {
4074
    $newconfig = 1;
4075
    get_test_case;
4076 4077 4078 4079
    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
    print OUT << "EOF"
# Generated by ktest.pl
#
4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090

# PWD is a ktest.pl variable that will result in the process working
# directory that ktest.pl is executed in.

# THIS_DIR is automatically assigned the PWD of the path that generated
# the config file. It is best to use this variable when assigning other
# directory paths within this directory. This allows you to easily
# move the test cases to other locations or to other machines.
#
THIS_DIR := $variable{"PWD"}

4091 4092 4093
# Define each test with TEST_START
# The config options below it will override the defaults
TEST_START
4094
TEST_TYPE = $default{"TEST_TYPE"}
4095 4096 4097 4098 4099 4100 4101 4102

DEFAULTS
EOF
;
    close(OUT);
}
read_config $ktest_config;

4103
if (defined($opt{"LOG_FILE"})) {
4104
    $opt{"LOG_FILE"} = eval_option("LOG_FILE", $opt{"LOG_FILE"}, -1);
4105 4106
}

4107 4108 4109 4110 4111 4112 4113
# Append any configs entered in manually to the config file.
my @new_configs = keys %entered_configs;
if ($#new_configs >= 0) {
    print "\nAppending entered in configs to $ktest_config\n";
    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
    foreach my $config (@new_configs) {
	print OUT "$config = $entered_configs{$config}\n";
4114
	$opt{$config} = process_variables($entered_configs{$config});
4115 4116
    }
}
S
Steven Rostedt 已提交
4117

4118 4119 4120 4121 4122
if (defined($opt{"LOG_FILE"})) {
    if ($opt{"CLEAR_LOG"}) {
	unlink $opt{"LOG_FILE"};
    }
    open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
4123
    LOG->autoflush(1);
4124
}
S
Steven Rostedt 已提交
4125

4126 4127
doprint "\n\nSTARTING AUTOMATED TESTS\n\n";

4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150
for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {

    if (!$i) {
	doprint "DEFAULT OPTIONS:\n";
    } else {
	doprint "\nTEST $i OPTIONS";
	if (defined($repeat_tests{$i})) {
	    $repeat = $repeat_tests{$i};
	    doprint " ITERATE $repeat";
	}
	doprint "\n";
    }

    foreach my $option (sort keys %opt) {

	if ($option =~ /\[(\d+)\]$/) {
	    next if ($i != $1);
	} else {
	    next if ($i);
	}

	doprint "$option = $opt{$option}\n";
    }
4151
}
S
Steven Rostedt 已提交
4152

4153 4154 4155 4156 4157 4158 4159 4160 4161 4162
sub option_defined {
    my ($option) = @_;

    if (defined($opt{$option}) && $opt{$option} !~ /^\s*$/) {
	return 1;
    }

    return 0;
}

4163
sub __set_test_option {
4164
    my ($name, $i) = @_;
S
Steven Rostedt 已提交
4165

4166
    my $option = "$name\[$i\]";
4167

4168
    if (option_defined($option)) {
4169
	return $opt{$option};
4170 4171
    }

4172 4173 4174 4175
    foreach my $test (keys %repeat_tests) {
	if ($i >= $test &&
	    $i < $test + $repeat_tests{$test}) {
	    $option = "$name\[$test\]";
4176
	    if (option_defined($option)) {
4177 4178 4179 4180 4181
		return $opt{$option};
	    }
	}
    }

4182
    if (option_defined($name)) {
4183
	return $opt{$name};
S
Steven Rostedt 已提交
4184 4185
    }

4186 4187 4188
    return undef;
}

4189 4190 4191 4192 4193 4194
sub set_test_option {
    my ($name, $i) = @_;

    my $option = __set_test_option($name, $i);
    return $option if (!defined($option));

4195
    return eval_option($name, $option, $i);
4196 4197
}

4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212
sub find_mailer {
    my ($mailer) = @_;

    my @paths = split /:/, $ENV{PATH};

    # sendmail is usually in /usr/sbin
    $paths[$#paths + 1] = "/usr/sbin";

    foreach my $path (@paths) {
	if (-x "$path/$mailer") {
	    return $path;
	}
    }

    return undef;
T
Tim Tianyang Chen 已提交
4213 4214
}

4215
sub do_send_mail {
4216
    my ($subject, $message, $file) = @_;
4217 4218 4219 4220 4221 4222 4223 4224 4225

    if (!defined($mail_path)) {
	# find the mailer
	$mail_path = find_mailer $mailer;
	if (!defined($mail_path)) {
	    die "\nCan not find $mailer in PATH\n";
	}
    }

4226 4227 4228 4229 4230 4231 4232
    my $header_file = "$tmpdir/header";
    open (HEAD, ">$header_file") or die "Can not create $header_file\n";
    print HEAD "To: $mailto\n";
    print HEAD "Subject: $subject\n\n";
    print HEAD "$message\n";
    close HEAD;

4233 4234
    if (!defined($mail_command)) {
	if ($mailer eq "mail" || $mailer eq "mailx") {
4235
	    $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO";
4236
	} elsif ($mailer eq "sendmail" ) {
4237
	    $mail_command =  "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -t \$MAILTO";
4238 4239 4240 4241 4242
	} else {
	    die "\nYour mailer: $mailer is not supported.\n";
	}
    }

4243 4244 4245 4246 4247 4248 4249
    if (defined($file)) {
	$mail_command =~ s/\$BODY_FILE/$file/g;
    } else {
	$mail_command =~ s/\$BODY_FILE//g;
    }

    $mail_command =~ s/\$HEADER_FILE/$header_file/g;
4250 4251 4252 4253 4254 4255 4256 4257 4258
    $mail_command =~ s/\$MAILER/$mailer/g;
    $mail_command =~ s/\$MAIL_PATH/$mail_path/g;
    $mail_command =~ s/\$MAILTO/$mailto/g;
    $mail_command =~ s/\$SUBJECT/$subject/g;
    $mail_command =~ s/\$MESSAGE/$message/g;

    run_command $mail_command;
}

T
Tim Tianyang Chen 已提交
4259
sub send_email {
4260

4261 4262 4263 4264 4265
    if (defined($mailto)) {
	if (!defined($mailer)) {
	    doprint "No email sent: email or mailer not specified in config.\n";
	    return;
	}
4266
	do_send_mail @_;
T
Tim Tianyang Chen 已提交
4267 4268 4269
    }
}

T
Tim Tianyang Chen 已提交
4270 4271
sub cancel_test {
    if ($email_when_canceled) {
4272 4273
	my $name = get_test_name;
        send_email("KTEST: Your [$name] test was cancelled",
T
Tim Tianyang Chen 已提交
4274 4275 4276 4277 4278 4279 4280
                "Your test started at $script_start_time was cancelled: sig int");
    }
    die "\nCaught Sig Int, test interrupted: $!\n"
}

$SIG{INT} = qw(cancel_test);

4281
# First we need to do is the builds
4282 4283
for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {

4284 4285
    # Do not reboot on failing test options
    $no_reboot = 1;
4286
    $reboot_success = 0;
4287

4288 4289
    $have_version = 0;

4290 4291
    $iteration = $i;

4292 4293 4294 4295 4296
    $build_time = 0;
    $install_time = 0;
    $reboot_time = 0;
    $test_time = 0;

4297 4298
    undef %force_config;

4299 4300
    my $makecmd = set_test_option("MAKE_CMD", $i);

4301 4302 4303
    $outputdir = set_test_option("OUTPUT_DIR", $i);
    $builddir = set_test_option("BUILD_DIR", $i);

4304
    chdir $builddir || dodie "can't change directory to $builddir";
4305 4306 4307

    if (!-d $outputdir) {
	mkpath($outputdir) or
4308
	    dodie "can't create $outputdir";
4309 4310 4311 4312
    }

    $make = "$makecmd O=$outputdir";

4313 4314 4315 4316
    # Load all the options into their mapped variable names
    foreach my $opt (keys %option_map) {
	${$option_map{$opt}} = set_test_option($opt, $i);
    }
4317

4318 4319
    $start_minconfig_defined = 1;

4320
    # The first test may override the PRE_KTEST option
T
Tim Tianyang Chen 已提交
4321 4322 4323 4324 4325 4326
    if ($i == 1) {
        if (defined($pre_ktest)) {
            doprint "\n";
            run_command $pre_ktest;
        }
        if ($email_when_started) {
4327 4328
	    my $name = get_test_name;
            send_email("KTEST: Your [$name] test was started",
T
Tim Tianyang Chen 已提交
4329 4330
                "Your test was started on $script_start_time");
        }
4331 4332 4333 4334 4335 4336 4337 4338
    }

    # Any test can override the POST_KTEST option
    # The last test takes precedence.
    if (defined($post_ktest)) {
	$final_post_ktest = $post_ktest;
    }

4339
    if (!defined($start_minconfig)) {
4340
	$start_minconfig_defined = 0;
4341 4342 4343
	$start_minconfig = $minconfig;
    }

4344 4345
    if (!-d $tmpdir) {
	mkpath($tmpdir) or
4346
	    dodie "can't create $tmpdir";
4347
    }
S
Steven Rostedt 已提交
4348

4349 4350 4351
    $ENV{"SSH_USER"} = $ssh_user;
    $ENV{"MACHINE"} = $machine;

4352
    $buildlog = "$tmpdir/buildlog-$machine";
R
Rabin Vincent 已提交
4353
    $testlog = "$tmpdir/testlog-$machine";
4354
    $dmesg = "$tmpdir/dmesg-$machine";
4355
    $output_config = "$outputdir/.config";
4356

4357 4358
    if (!$buildonly) {
	$target = "$ssh_user\@$machine";
4359
	if (($reboot_type eq "grub") or ($reboot_type eq "grub2bls")) {
4360
	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
S
Steven Rostedt 已提交
4361 4362 4363
	} elsif ($reboot_type eq "grub2") {
	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
	    dodie "GRUB_FILE not defined" if (!defined($grub_file));
4364 4365
	} elsif ($reboot_type eq "syslinux") {
	    dodie "SYSLINUX_LABEL not defined" if (!defined($syslinux_label));
4366
	}
4367 4368 4369 4370
    }

    my $run_type = $build_type;
    if ($test_type eq "patchcheck") {
4371
	$run_type = $patchcheck_type;
4372
    } elsif ($test_type eq "bisect") {
4373
	$run_type = $bisect_type;
4374
    } elsif ($test_type eq "config_bisect") {
4375
	$run_type = $config_bisect_type;
4376 4377 4378
    } elsif ($test_type eq "make_min_config") {
	$run_type = "";
    } elsif ($test_type eq "make_warnings_file") {
4379 4380 4381
	$run_type = "";
    }

4382 4383 4384 4385
    # mistake in config file?
    if (!defined($run_type)) {
	$run_type = "ERROR";
    }
4386

4387 4388 4389
    my $installme = "";
    $installme = " no_install" if ($no_install);

4390 4391 4392 4393 4394 4395
    my $name = "";

    if (defined($test_name)) {
	$name = " ($test_name)";
    }

S
Steven Rostedt 已提交
4396
    doprint "\n\n";
4397 4398 4399 4400 4401

    if (defined($opt{"LOG_FILE"})) {
	$test_log_start = tell(LOG);
    }

4402
    doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n";
4403

4404
    if (defined($pre_test)) {
4405 4406 4407 4408 4409
	my $ret = run_command $pre_test;
	if (!$ret && defined($pre_test_die) &&
	    $pre_test_die) {
	    dodie "failed to pre_test\n";
	}
4410 4411
    }

4412 4413
    unlink $dmesg;
    unlink $buildlog;
R
Rabin Vincent 已提交
4414
    unlink $testlog;
S
Steven Rostedt 已提交
4415

4416 4417 4418 4419 4420 4421
    if (defined($addconfig)) {
	my $min = $minconfig;
	if (!defined($minconfig)) {
	    $min = "";
	}
	run_command "cat $addconfig $min > $tmpdir/add_config" or
4422
	    dodie "Failed to create temp config";
4423
	$minconfig = "$tmpdir/add_config";
4424 4425
    }

S
Steven Rostedt 已提交
4426 4427
    if (defined($checkout)) {
	run_command "git checkout $checkout" or
4428
	    dodie "failed to checkout $checkout";
S
Steven Rostedt 已提交
4429 4430
    }

4431 4432
    $no_reboot = 0;

4433 4434
    # A test may opt to not reboot the box
    if ($reboot_on_success) {
4435
	$reboot_success = 1;
4436
    }
4437

4438
    if ($test_type eq "bisect") {
4439 4440
	bisect $i;
	next;
4441 4442 4443
    } elsif ($test_type eq "config_bisect") {
	config_bisect $i;
	next;
4444
    } elsif ($test_type eq "patchcheck") {
S
Steven Rostedt 已提交
4445 4446
	patchcheck $i;
	next;
4447 4448 4449
    } elsif ($test_type eq "make_min_config") {
	make_min_config $i;
	next;
4450 4451 4452 4453
    } elsif ($test_type eq "make_warnings_file") {
	$no_reboot = 1;
	make_warnings_file $i;
	next;
S
Steven Rostedt 已提交
4454 4455
    }

4456 4457
    if ($build_type ne "nobuild") {
	build $build_type or next;
4458
	check_buildlog or next;
S
Steven Rostedt 已提交
4459 4460
    }

4461 4462 4463 4464 4465 4466 4467
    if ($test_type eq "install") {
	get_version;
	install;
	success $i;
	next;
    }

4468 4469
    if ($test_type ne "build") {
	my $failed = 0;
4470
	start_monitor_and_install or $failed = 1;
4471 4472 4473 4474 4475

	if (!$failed && $test_type ne "boot" && defined($run_test)) {
	    do_run_test or $failed = 1;
	}
	end_monitor;
4476 4477 4478 4479
	if ($failed) {
	    print_times;
	    next;
	}
4480 4481
    }

4482 4483
    print_times;

4484
    success $i;
S
Steven Rostedt 已提交
4485 4486
}

4487
if (defined($final_post_ktest)) {
4488 4489 4490

    my $cp_final_post_ktest = eval_kernel_version $final_post_ktest;
    run_command $cp_final_post_ktest;
4491 4492
}

4493
if ($opt{"POWEROFF_ON_SUCCESS"}) {
4494
    halt;
4495
} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) {
4496
    reboot_to_good;
4497 4498 4499
} elsif (defined($switch_to_good)) {
    # still need to get to the good kernel
    run_command $switch_to_good;
4500
}
4501

4502

4503 4504
doprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";

T
Tim Tianyang Chen 已提交
4505
if ($email_when_finished) {
4506
    send_email("KTEST: Your test has finished!",
T
Tim Tianyang Chen 已提交
4507 4508
            "$successes of $opt{NUM_TESTS} tests started at $script_start_time were successful!");
}
4509 4510 4511 4512 4513 4514

if (defined($opt{"LOG_FILE"})) {
    print "\n See $opt{LOG_FILE} for the record of results.\n\n";
    close LOG;
}

S
Steven Rostedt 已提交
4515
exit 0;