0001
0002
0003
0004
0005
0006
0007 use strict;
0008 use IPC::Open2;
0009 use Fcntl ;
0010 use File::Path ;
0011 use File::Copy ;
0012 use FileHandle;
0013 use FindBin;
0014 use IO::Handle;
0015
0016 my $VERSION = "0.2";
0017
0018 $| = 1;
0019
0020 my %opt;
0021 my %repeat_tests;
0022 my %repeats;
0023 my %evals;
0024
0025
0026 my %default = (
0027 "MAILER" => "sendmail",
0028 "EMAIL_ON_ERROR" => 1,
0029 "EMAIL_WHEN_FINISHED" => 1,
0030 "EMAIL_WHEN_CANCELED" => 0,
0031 "EMAIL_WHEN_STARTED" => 0,
0032 "NUM_TESTS" => 1,
0033 "TEST_TYPE" => "build",
0034 "BUILD_TYPE" => "oldconfig",
0035 "MAKE_CMD" => "make",
0036 "CLOSE_CONSOLE_SIGNAL" => "INT",
0037 "TIMEOUT" => 120,
0038 "TMP_DIR" => "/tmp/ktest/\${MACHINE}",
0039 "SLEEP_TIME" => 60,
0040 "BUILD_NOCLEAN" => 0,
0041 "REBOOT_ON_ERROR" => 0,
0042 "POWEROFF_ON_ERROR" => 0,
0043 "REBOOT_ON_SUCCESS" => 1,
0044 "POWEROFF_ON_SUCCESS" => 0,
0045 "BUILD_OPTIONS" => "",
0046 "BISECT_SLEEP_TIME" => 60,
0047 "PATCHCHECK_SLEEP_TIME" => 60,
0048 "CLEAR_LOG" => 0,
0049 "BISECT_MANUAL" => 0,
0050 "BISECT_SKIP" => 1,
0051 "BISECT_TRIES" => 1,
0052 "MIN_CONFIG_TYPE" => "boot",
0053 "SUCCESS_LINE" => "login:",
0054 "DETECT_TRIPLE_FAULT" => 1,
0055 "NO_INSTALL" => 0,
0056 "BOOTED_TIMEOUT" => 1,
0057 "DIE_ON_FAILURE" => 1,
0058 "SSH_EXEC" => "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND",
0059 "SCP_TO_TARGET" => "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE",
0060 "SCP_TO_TARGET_INSTALL" => "\${SCP_TO_TARGET}",
0061 "REBOOT" => "ssh \$SSH_USER\@\$MACHINE reboot",
0062 "REBOOT_RETURN_CODE" => 255,
0063 "STOP_AFTER_SUCCESS" => 10,
0064 "STOP_AFTER_FAILURE" => 60,
0065 "STOP_TEST_AFTER" => 600,
0066 "MAX_MONITOR_WAIT" => 1800,
0067 "GRUB_REBOOT" => "grub2-reboot",
0068 "GRUB_BLS_GET" => "grubby --info=ALL",
0069 "SYSLINUX" => "extlinux",
0070 "SYSLINUX_PATH" => "/boot/extlinux",
0071 "CONNECT_TIMEOUT" => 25,
0072
0073
0074
0075 "REBOOT_TYPE" => "grub",
0076 "LOCALVERSION" => "-test",
0077 "SSH_USER" => "root",
0078 "BUILD_TARGET" => "arch/x86/boot/bzImage",
0079 "TARGET_IMAGE" => "/boot/vmlinuz-test",
0080
0081 "LOG_FILE" => undef,
0082 "IGNORE_UNUSED" => 0,
0083 );
0084
0085 my $test_log_start = 0;
0086
0087 my $ktest_config = "ktest.conf";
0088 my $version;
0089 my $have_version = 0;
0090 my $machine;
0091 my $last_machine;
0092 my $ssh_user;
0093 my $tmpdir;
0094 my $builddir;
0095 my $outputdir;
0096 my $output_config;
0097 my $test_type;
0098 my $build_type;
0099 my $build_options;
0100 my $final_post_ktest;
0101 my $pre_ktest;
0102 my $post_ktest;
0103 my $pre_test;
0104 my $pre_test_die;
0105 my $post_test;
0106 my $pre_build;
0107 my $post_build;
0108 my $pre_build_die;
0109 my $post_build_die;
0110 my $reboot_type;
0111 my $reboot_script;
0112 my $power_cycle;
0113 my $reboot;
0114 my $reboot_return_code;
0115 my $reboot_on_error;
0116 my $switch_to_good;
0117 my $switch_to_test;
0118 my $poweroff_on_error;
0119 my $reboot_on_success;
0120 my $die_on_failure;
0121 my $powercycle_after_reboot;
0122 my $poweroff_after_halt;
0123 my $max_monitor_wait;
0124 my $ssh_exec;
0125 my $scp_to_target;
0126 my $scp_to_target_install;
0127 my $power_off;
0128 my $grub_menu;
0129 my $last_grub_menu;
0130 my $grub_file;
0131 my $grub_number;
0132 my $grub_reboot;
0133 my $grub_bls_get;
0134 my $syslinux;
0135 my $syslinux_path;
0136 my $syslinux_label;
0137 my $target;
0138 my $make;
0139 my $pre_install;
0140 my $post_install;
0141 my $no_install;
0142 my $noclean;
0143 my $minconfig;
0144 my $start_minconfig;
0145 my $start_minconfig_defined;
0146 my $output_minconfig;
0147 my $minconfig_type;
0148 my $use_output_minconfig;
0149 my $warnings_file;
0150 my $ignore_config;
0151 my $ignore_errors;
0152 my $addconfig;
0153 my $in_bisect = 0;
0154 my $bisect_bad_commit = "";
0155 my $reverse_bisect;
0156 my $bisect_manual;
0157 my $bisect_skip;
0158 my $bisect_tries;
0159 my $config_bisect_good;
0160 my $bisect_ret_good;
0161 my $bisect_ret_bad;
0162 my $bisect_ret_skip;
0163 my $bisect_ret_abort;
0164 my $bisect_ret_default;
0165 my $in_patchcheck = 0;
0166 my $run_test;
0167 my $buildlog;
0168 my $testlog;
0169 my $dmesg;
0170 my $monitor_fp;
0171 my $monitor_pid;
0172 my $monitor_cnt = 0;
0173 my $sleep_time;
0174 my $bisect_sleep_time;
0175 my $patchcheck_sleep_time;
0176 my $ignore_warnings;
0177 my $store_failures;
0178 my $store_successes;
0179 my $test_name;
0180 my $timeout;
0181 my $connect_timeout;
0182 my $config_bisect_exec;
0183 my $booted_timeout;
0184 my $detect_triplefault;
0185 my $console;
0186 my $close_console_signal;
0187 my $reboot_success_line;
0188 my $success_line;
0189 my $stop_after_success;
0190 my $stop_after_failure;
0191 my $stop_test_after;
0192 my $build_target;
0193 my $target_image;
0194 my $checkout;
0195 my $localversion;
0196 my $iteration = 0;
0197 my $successes = 0;
0198 my $stty_orig;
0199 my $run_command_status = 0;
0200
0201 my $bisect_good;
0202 my $bisect_bad;
0203 my $bisect_type;
0204 my $bisect_start;
0205 my $bisect_replay;
0206 my $bisect_files;
0207 my $bisect_reverse;
0208 my $bisect_check;
0209
0210 my $config_bisect;
0211 my $config_bisect_type;
0212 my $config_bisect_check;
0213
0214 my $patchcheck_type;
0215 my $patchcheck_start;
0216 my $patchcheck_cherry;
0217 my $patchcheck_end;
0218
0219 my $build_time;
0220 my $install_time;
0221 my $reboot_time;
0222 my $test_time;
0223
0224 my $pwd;
0225 my $dirname = $FindBin::Bin;
0226
0227 my $mailto;
0228 my $mailer;
0229 my $mail_path;
0230 my $mail_max_size;
0231 my $mail_command;
0232 my $email_on_error;
0233 my $email_when_finished;
0234 my $email_when_started;
0235 my $email_when_canceled;
0236
0237 my $script_start_time = localtime();
0238
0239
0240
0241 my $buildonly = 1;
0242
0243
0244 my $warnings_ok = 0;
0245
0246
0247 my $newconfig = 0;
0248
0249 my %entered_configs;
0250 my %config_help;
0251 my %variable;
0252
0253
0254
0255 my %force_config;
0256
0257
0258 my $no_reboot = 1;
0259
0260
0261 my $reboot_success = 0;
0262
0263 my %option_map = (
0264 "MAILTO" => \$mailto,
0265 "MAILER" => \$mailer,
0266 "MAIL_PATH" => \$mail_path,
0267 "MAIL_MAX_SIZE" => \$mail_max_size,
0268 "MAIL_COMMAND" => \$mail_command,
0269 "EMAIL_ON_ERROR" => \$email_on_error,
0270 "EMAIL_WHEN_FINISHED" => \$email_when_finished,
0271 "EMAIL_WHEN_STARTED" => \$email_when_started,
0272 "EMAIL_WHEN_CANCELED" => \$email_when_canceled,
0273 "MACHINE" => \$machine,
0274 "SSH_USER" => \$ssh_user,
0275 "TMP_DIR" => \$tmpdir,
0276 "OUTPUT_DIR" => \$outputdir,
0277 "BUILD_DIR" => \$builddir,
0278 "TEST_TYPE" => \$test_type,
0279 "PRE_KTEST" => \$pre_ktest,
0280 "POST_KTEST" => \$post_ktest,
0281 "PRE_TEST" => \$pre_test,
0282 "PRE_TEST_DIE" => \$pre_test_die,
0283 "POST_TEST" => \$post_test,
0284 "BUILD_TYPE" => \$build_type,
0285 "BUILD_OPTIONS" => \$build_options,
0286 "PRE_BUILD" => \$pre_build,
0287 "POST_BUILD" => \$post_build,
0288 "PRE_BUILD_DIE" => \$pre_build_die,
0289 "POST_BUILD_DIE" => \$post_build_die,
0290 "POWER_CYCLE" => \$power_cycle,
0291 "REBOOT" => \$reboot,
0292 "REBOOT_RETURN_CODE" => \$reboot_return_code,
0293 "BUILD_NOCLEAN" => \$noclean,
0294 "MIN_CONFIG" => \$minconfig,
0295 "OUTPUT_MIN_CONFIG" => \$output_minconfig,
0296 "START_MIN_CONFIG" => \$start_minconfig,
0297 "MIN_CONFIG_TYPE" => \$minconfig_type,
0298 "USE_OUTPUT_MIN_CONFIG" => \$use_output_minconfig,
0299 "WARNINGS_FILE" => \$warnings_file,
0300 "IGNORE_CONFIG" => \$ignore_config,
0301 "TEST" => \$run_test,
0302 "ADD_CONFIG" => \$addconfig,
0303 "REBOOT_TYPE" => \$reboot_type,
0304 "GRUB_MENU" => \$grub_menu,
0305 "GRUB_FILE" => \$grub_file,
0306 "GRUB_REBOOT" => \$grub_reboot,
0307 "GRUB_BLS_GET" => \$grub_bls_get,
0308 "SYSLINUX" => \$syslinux,
0309 "SYSLINUX_PATH" => \$syslinux_path,
0310 "SYSLINUX_LABEL" => \$syslinux_label,
0311 "PRE_INSTALL" => \$pre_install,
0312 "POST_INSTALL" => \$post_install,
0313 "NO_INSTALL" => \$no_install,
0314 "REBOOT_SCRIPT" => \$reboot_script,
0315 "REBOOT_ON_ERROR" => \$reboot_on_error,
0316 "SWITCH_TO_GOOD" => \$switch_to_good,
0317 "SWITCH_TO_TEST" => \$switch_to_test,
0318 "POWEROFF_ON_ERROR" => \$poweroff_on_error,
0319 "REBOOT_ON_SUCCESS" => \$reboot_on_success,
0320 "DIE_ON_FAILURE" => \$die_on_failure,
0321 "POWER_OFF" => \$power_off,
0322 "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot,
0323 "POWEROFF_AFTER_HALT" => \$poweroff_after_halt,
0324 "MAX_MONITOR_WAIT" => \$max_monitor_wait,
0325 "SLEEP_TIME" => \$sleep_time,
0326 "BISECT_SLEEP_TIME" => \$bisect_sleep_time,
0327 "PATCHCHECK_SLEEP_TIME" => \$patchcheck_sleep_time,
0328 "IGNORE_WARNINGS" => \$ignore_warnings,
0329 "IGNORE_ERRORS" => \$ignore_errors,
0330 "BISECT_MANUAL" => \$bisect_manual,
0331 "BISECT_SKIP" => \$bisect_skip,
0332 "BISECT_TRIES" => \$bisect_tries,
0333 "CONFIG_BISECT_GOOD" => \$config_bisect_good,
0334 "BISECT_RET_GOOD" => \$bisect_ret_good,
0335 "BISECT_RET_BAD" => \$bisect_ret_bad,
0336 "BISECT_RET_SKIP" => \$bisect_ret_skip,
0337 "BISECT_RET_ABORT" => \$bisect_ret_abort,
0338 "BISECT_RET_DEFAULT" => \$bisect_ret_default,
0339 "STORE_FAILURES" => \$store_failures,
0340 "STORE_SUCCESSES" => \$store_successes,
0341 "TEST_NAME" => \$test_name,
0342 "TIMEOUT" => \$timeout,
0343 "CONNECT_TIMEOUT" => \$connect_timeout,
0344 "CONFIG_BISECT_EXEC" => \$config_bisect_exec,
0345 "BOOTED_TIMEOUT" => \$booted_timeout,
0346 "CONSOLE" => \$console,
0347 "CLOSE_CONSOLE_SIGNAL" => \$close_console_signal,
0348 "DETECT_TRIPLE_FAULT" => \$detect_triplefault,
0349 "SUCCESS_LINE" => \$success_line,
0350 "REBOOT_SUCCESS_LINE" => \$reboot_success_line,
0351 "STOP_AFTER_SUCCESS" => \$stop_after_success,
0352 "STOP_AFTER_FAILURE" => \$stop_after_failure,
0353 "STOP_TEST_AFTER" => \$stop_test_after,
0354 "BUILD_TARGET" => \$build_target,
0355 "SSH_EXEC" => \$ssh_exec,
0356 "SCP_TO_TARGET" => \$scp_to_target,
0357 "SCP_TO_TARGET_INSTALL" => \$scp_to_target_install,
0358 "CHECKOUT" => \$checkout,
0359 "TARGET_IMAGE" => \$target_image,
0360 "LOCALVERSION" => \$localversion,
0361
0362 "BISECT_GOOD" => \$bisect_good,
0363 "BISECT_BAD" => \$bisect_bad,
0364 "BISECT_TYPE" => \$bisect_type,
0365 "BISECT_START" => \$bisect_start,
0366 "BISECT_REPLAY" => \$bisect_replay,
0367 "BISECT_FILES" => \$bisect_files,
0368 "BISECT_REVERSE" => \$bisect_reverse,
0369 "BISECT_CHECK" => \$bisect_check,
0370
0371 "CONFIG_BISECT" => \$config_bisect,
0372 "CONFIG_BISECT_TYPE" => \$config_bisect_type,
0373 "CONFIG_BISECT_CHECK" => \$config_bisect_check,
0374
0375 "PATCHCHECK_TYPE" => \$patchcheck_type,
0376 "PATCHCHECK_START" => \$patchcheck_start,
0377 "PATCHCHECK_CHERRY" => \$patchcheck_cherry,
0378 "PATCHCHECK_END" => \$patchcheck_end,
0379 );
0380
0381
0382 my %used_options;
0383
0384
0385 chomp ($variable{"PWD"} = `pwd`);
0386 $pwd = $variable{"PWD"};
0387
0388 $config_help{"MACHINE"} = << "EOF"
0389 The machine hostname that you will test.
0390 For build only tests, it is still needed to differentiate log files.
0391 EOF
0392 ;
0393 $config_help{"SSH_USER"} = << "EOF"
0394 The box is expected to have ssh on normal bootup, provide the user
0395 (most likely root, since you need privileged operations)
0396 EOF
0397 ;
0398 $config_help{"BUILD_DIR"} = << "EOF"
0399 The directory that contains the Linux source code (full path).
0400 You can use \${PWD} that will be the path where ktest.pl is run, or use
0401 \${THIS_DIR} which is assigned \${PWD} but may be changed later.
0402 EOF
0403 ;$config_help{"OUTPUT_DIR"} = << "EOF"
0404
0405 The directory that the objects will be built (full path).
0406 (can not be same as BUILD_DIR)
0407 You can use \${PWD} that will be the path where ktest.pl is run, or use
0408 \${THIS_DIR} which is assigned \${PWD} but may be changed later.
0409 EOF
0410 ;$config_help{"BUILD_TARGET"} = << "EOF"
0411
0412 The location of the compiled file to copy to the target.
0413 (relative to OUTPUT_DIR)
0414 EOF
0415 ;
0416 $config_help{"BUILD_OPTIONS"} = << "EOF"
0417 Options to add to \"make\" when building.
0418 i.e. -j20
0419 EOF
0420 ;
0421 $config_help{"TARGET_IMAGE"} = << "EOF"
0422 The place to put your image on the test machine.
0423 EOF
0424 ;
0425 $config_help{"POWER_CYCLE"} = << "EOF"
0426 A script or command to reboot the box.
0427
0428 Here is a digital loggers power switch example
0429 POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
0430
0431 Here is an example to reboot a virtual box on the current host
0432 with the name "Guest".
0433 POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
0434 EOF
0435 ;
0436 $config_help{"CONSOLE"} = << "EOF"
0437 The script or command that reads the console
0438
0439 If you use ttywatch server, something like the following would work.
0440 CONSOLE = nc -d localhost 3001
0441
0442 For a virtual machine with guest name "Guest".
0443 CONSOLE = virsh console Guest
0444 EOF
0445 ;
0446 $config_help{"LOCALVERSION"} = << "EOF"
0447 Required version ending to differentiate the test
0448 from other linux builds on the system.
0449 EOF
0450 ;
0451 $config_help{"REBOOT_TYPE"} = << "EOF"
0452 Way to reboot the box to the test kernel.
0453 Only valid options so far are "grub", "grub2", "grub2bls", "syslinux", and "script".
0454
0455 If you specify grub, it will assume grub version 1
0456 and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
0457 and select that target to reboot to the kernel. If this is not
0458 your setup, then specify "script" and have a command or script
0459 specified in REBOOT_SCRIPT to boot to the target.
0460
0461 The entry in /boot/grub/menu.lst must be entered in manually.
0462 The test will not modify that file.
0463
0464 If you specify grub2, then you also need to specify both \$GRUB_MENU
0465 and \$GRUB_FILE.
0466
0467 If you specify grub2bls, then you also need to specify \$GRUB_MENU.
0468
0469 If you specify syslinux, then you may use SYSLINUX to define the syslinux
0470 command (defaults to extlinux), and SYSLINUX_PATH to specify the path to
0471 the syslinux install (defaults to /boot/extlinux). But you have to specify
0472 SYSLINUX_LABEL to define the label to boot to for the test kernel.
0473 EOF
0474 ;
0475 $config_help{"GRUB_MENU"} = << "EOF"
0476 The grub title name for the test kernel to boot
0477 (Only mandatory if REBOOT_TYPE = grub or grub2)
0478
0479 Note, ktest.pl will not update the grub menu.lst, you need to
0480 manually add an option for the test. ktest.pl will search
0481 the grub menu.lst for this option to find what kernel to
0482 reboot into.
0483
0484 For example, if in the /boot/grub/menu.lst the test kernel title has:
0485 title Test Kernel
0486 kernel vmlinuz-test
0487 GRUB_MENU = Test Kernel
0488
0489 For grub2, a search of \$GRUB_FILE is performed for the lines
0490 that begin with "menuentry". It will not detect submenus. The
0491 menu must be a non-nested menu. Add the quotes used in the menu
0492 to guarantee your selection, as the first menuentry with the content
0493 of \$GRUB_MENU that is found will be used.
0494
0495 For grub2bls, \$GRUB_MENU is searched on the result of \$GRUB_BLS_GET
0496 command for the lines that begin with "title".
0497 EOF
0498 ;
0499 $config_help{"GRUB_FILE"} = << "EOF"
0500 If grub2 is used, the full path for the grub.cfg file is placed
0501 here. Use something like /boot/grub2/grub.cfg to search.
0502 EOF
0503 ;
0504 $config_help{"SYSLINUX_LABEL"} = << "EOF"
0505 If syslinux is used, the label that boots the target kernel must
0506 be specified with SYSLINUX_LABEL.
0507 EOF
0508 ;
0509 $config_help{"REBOOT_SCRIPT"} = << "EOF"
0510 A script to reboot the target into the test kernel
0511 (Only mandatory if REBOOT_TYPE = script)
0512 EOF
0513 ;
0514
0515 # used with process_expression()
0516 my $d = 0;
0517
0518 # defined before get_test_name()
0519 my $in_die = 0;
0520
0521 # defined before process_warning_line()
0522 my $check_build_re = ".*:.*(warning|error|Error):.*";
0523 my $utf8_quote = "\\x{e2}\\x{80}(\\x{98}|\\x{99})";
0524
0525 # defined before child_finished()
0526 my $child_done;
0527
0528 # config_ignore holds the configs that were set (or unset) for
0529 # a good config and we will ignore these configs for the rest
0530 # of a config bisect. These configs stay as they were.
0531 my %config_ignore;
0532
0533 # config_set holds what all configs were set as.
0534 my %config_set;
0535
0536 # config_off holds the set of configs that the bad config had disabled.
0537 # We need to record them and set them in the .config when running
0538 # olddefconfig, because olddefconfig keeps the defaults.
0539 my %config_off;
0540
0541 # config_off_tmp holds a set of configs to turn off for now
0542 my @config_off_tmp;
0543
0544 # config_list is the set of configs that are being tested
0545 my %config_list;
0546 my %null_config;
0547
0548 my %dependency;
0549
0550 # found above run_config_bisect()
0551 my $pass = 1;
0552
0553 # found above add_dep()
0554
0555 my %depends;
0556 my %depcount;
0557 my $iflevel = 0;
0558 my @ifdeps;
0559
0560 # prevent recursion
0561 my %read_kconfigs;
0562
0563 # found above test_this_config()
0564 my %min_configs;
0565 my %keep_configs;
0566 my %save_configs;
0567 my %processed_configs;
0568 my %nochange_config;
0569
0570 #
0571 # These are first defined here, main function later on
0572 #
0573 sub run_command;
0574 sub start_monitor;
0575 sub end_monitor;
0576 sub wait_for_monitor;
0577
0578 sub _logit {
0579 if (defined($opt{"LOG_FILE"})) {
0580 print LOG @_;
0581 }
0582 }
0583
0584 sub logit {
0585 if (defined($opt{"LOG_FILE"})) {
0586 _logit @_;
0587 } else {
0588 print @_;
0589 }
0590 }
0591
0592 sub doprint {
0593 print @_;
0594 _logit @_;
0595 }
0596
0597 sub read_prompt {
0598 my ($cancel, $prompt) = @_;
0599
0600 my $ans;
0601
0602 for (;;) {
0603 if ($cancel) {
0604 print "$prompt [y/n/C] ";
0605 } else {
0606 print "$prompt [Y/n] ";
0607 }
0608 $ans = <STDIN>;
0609 chomp $ans;
0610 if ($ans =~ /^\s*$/) {
0611 if ($cancel) {
0612 $ans = "c";
0613 } else {
0614 $ans = "y";
0615 }
0616 }
0617 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
0618 if ($cancel) {
0619 last if ($ans =~ /^c$/i);
0620 print "Please answer either 'y', 'n' or 'c'.\n";
0621 } else {
0622 print "Please answer either 'y' or 'n'.\n";
0623 }
0624 }
0625 if ($ans =~ /^c/i) {
0626 exit;
0627 }
0628 if ($ans !~ /^y$/i) {
0629 return 0;
0630 }
0631 return 1;
0632 }
0633
0634 sub read_yn {
0635 my ($prompt) = @_;
0636
0637 return read_prompt 0, $prompt;
0638 }
0639
0640 sub read_ync {
0641 my ($prompt) = @_;
0642
0643 return read_prompt 1, $prompt;
0644 }
0645
0646 sub get_mandatory_config {
0647 my ($config) = @_;
0648 my $ans;
0649
0650 return if (defined($opt{$config}));
0651
0652 if (defined($config_help{$config})) {
0653 print "\n";
0654 print $config_help{$config};
0655 }
0656
0657 for (;;) {
0658 print "$config = ";
0659 if (defined($default{$config}) && length($default{$config})) {
0660 print "\[$default{$config}\] ";
0661 }
0662 $ans = <STDIN>;
0663 $ans =~ s/^\s*(.*\S)\s*$/$1/;
0664 if ($ans =~ /^\s*$/) {
0665 if ($default{$config}) {
0666 $ans = $default{$config};
0667 } else {
0668 print "Your answer can not be blank\n";
0669 next;
0670 }
0671 }
0672 $entered_configs{$config} = ${ans};
0673 last;
0674 }
0675 }
0676
0677 sub show_time {
0678 my ($time) = @_;
0679
0680 my $hours = 0;
0681 my $minutes = 0;
0682
0683 if ($time > 3600) {
0684 $hours = int($time / 3600);
0685 $time -= $hours * 3600;
0686 }
0687 if ($time > 60) {
0688 $minutes = int($time / 60);
0689 $time -= $minutes * 60;
0690 }
0691
0692 if ($hours > 0) {
0693 doprint "$hours hour";
0694 doprint "s" if ($hours > 1);
0695 doprint " ";
0696 }
0697
0698 if ($minutes > 0) {
0699 doprint "$minutes minute";
0700 doprint "s" if ($minutes > 1);
0701 doprint " ";
0702 }
0703
0704 doprint "$time second";
0705 doprint "s" if ($time != 1);
0706 }
0707
0708 sub print_times {
0709 doprint "\n";
0710 if ($build_time) {
0711 doprint "Build time: ";
0712 show_time($build_time);
0713 doprint "\n";
0714 }
0715 if ($install_time) {
0716 doprint "Install time: ";
0717 show_time($install_time);
0718 doprint "\n";
0719 }
0720 if ($reboot_time) {
0721 doprint "Reboot time: ";
0722 show_time($reboot_time);
0723 doprint "\n";
0724 }
0725 if ($test_time) {
0726 doprint "Test time: ";
0727 show_time($test_time);
0728 doprint "\n";
0729 }
0730 # reset for iterations like bisect
0731 $build_time = 0;
0732 $install_time = 0;
0733 $reboot_time = 0;
0734 $test_time = 0;
0735 }
0736
0737 sub get_mandatory_configs {
0738 get_mandatory_config("MACHINE");
0739 get_mandatory_config("BUILD_DIR");
0740 get_mandatory_config("OUTPUT_DIR");
0741
0742 if ($newconfig) {
0743 get_mandatory_config("BUILD_OPTIONS");
0744 }
0745
0746 # options required for other than just building a kernel
0747 if (!$buildonly) {
0748 get_mandatory_config("POWER_CYCLE");
0749 get_mandatory_config("CONSOLE");
0750 }
0751
0752 # options required for install and more
0753 if ($buildonly != 1) {
0754 get_mandatory_config("SSH_USER");
0755 get_mandatory_config("BUILD_TARGET");
0756 get_mandatory_config("TARGET_IMAGE");
0757 }
0758
0759 get_mandatory_config("LOCALVERSION");
0760
0761 return if ($buildonly);
0762
0763 my $rtype = $opt{"REBOOT_TYPE"};
0764
0765 if (!defined($rtype)) {
0766 if (!defined($opt{"GRUB_MENU"})) {
0767 get_mandatory_config("REBOOT_TYPE");
0768 $rtype = $entered_configs{"REBOOT_TYPE"};
0769 } else {
0770 $rtype = "grub";
0771 }
0772 }
0773
0774 if (($rtype eq "grub") or ($rtype eq "grub2bls")) {
0775 get_mandatory_config("GRUB_MENU");
0776 }
0777
0778 if ($rtype eq "grub2") {
0779 get_mandatory_config("GRUB_MENU");
0780 get_mandatory_config("GRUB_FILE");
0781 }
0782
0783 if ($rtype eq "syslinux") {
0784 get_mandatory_config("SYSLINUX_LABEL");
0785 }
0786 }
0787
0788 sub process_variables {
0789 my ($value, $remove_undef) = @_;
0790 my $retval = "";
0791
0792 # We want to check for '\', and it is just easier
0793 # to check the previous characet of '$' and not need
0794 # to worry if '$' is the first character. By adding
0795 # a space to $value, we can just check [^\\]\$ and
0796 # it will still work.
0797 $value = " $value";
0798
0799 while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
0800 my $begin = $1;
0801 my $var = $2;
0802 my $end = $3;
0803 # append beginning of value to retval
0804 $retval = "$retval$begin";
0805 if (defined($variable{$var})) {
0806 $retval = "$retval$variable{$var}";
0807 } elsif (defined($remove_undef) && $remove_undef) {
0808 # for if statements, any variable that is not defined,
0809 # we simple convert to 0
0810 $retval = "${retval}0";
0811 } else {
0812 # put back the origin piece.
0813 $retval = "$retval\$\{$var\}";
0814 # This could be an option that is used later, save
0815 # it so we don't warn if this option is not one of
0816 # ktests options.
0817 $used_options{$var} = 1;
0818 }
0819 $value = $end;
0820 }
0821 $retval = "$retval$value";
0822
0823 # remove the space added in the beginning
0824 $retval =~ s/ //;
0825
0826 return "$retval";
0827 }
0828
0829 sub set_value {
0830 my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
0831
0832 my $prvalue = process_variables($rvalue);
0833
0834 if ($lvalue =~ /^(TEST|BISECT|CONFIG_BISECT)_TYPE(\[.*\])?$/ &&
0835 $prvalue !~ /^(config_|)bisect$/ &&
0836 $prvalue !~ /^build$/ &&
0837 $buildonly) {
0838
0839 # Note if a test is something other than build, then we
0840 # will need other mandatory options.
0841 if ($prvalue ne "install") {
0842 $buildonly = 0;
0843 } else {
0844 # install still limits some mandatory options.
0845 $buildonly = 2;
0846 }
0847 }
0848
0849 if (defined($opt{$lvalue})) {
0850 if (!$override || defined(${$overrides}{$lvalue})) {
0851 my $extra = "";
0852 if ($override) {
0853 $extra = "In the same override section!\n";
0854 }
0855 die "$name: $.: Option $lvalue defined more than once!\n$extra";
0856 }
0857 ${$overrides}{$lvalue} = $prvalue;
0858 }
0859
0860 $opt{$lvalue} = $prvalue;
0861 }
0862
0863 sub set_eval {
0864 my ($lvalue, $rvalue, $name) = @_;
0865
0866 my $prvalue = process_variables($rvalue);
0867 my $arr;
0868
0869 if (defined($evals{$lvalue})) {
0870 $arr = $evals{$lvalue};
0871 } else {
0872 $arr = [];
0873 $evals{$lvalue} = $arr;
0874 }
0875
0876 push @{$arr}, $rvalue;
0877 }
0878
0879 sub set_variable {
0880 my ($lvalue, $rvalue) = @_;
0881
0882 if ($rvalue =~ /^\s*$/) {
0883 delete $variable{$lvalue};
0884 } else {
0885 $rvalue = process_variables($rvalue);
0886 $variable{$lvalue} = $rvalue;
0887 }
0888 }
0889
0890 sub process_compare {
0891 my ($lval, $cmp, $rval) = @_;
0892
0893 # remove whitespace
0894
0895 $lval =~ s/^\s*//;
0896 $lval =~ s/\s*$//;
0897
0898 $rval =~ s/^\s*//;
0899 $rval =~ s/\s*$//;
0900
0901 if ($cmp eq "==") {
0902 return $lval eq $rval;
0903 } elsif ($cmp eq "!=") {
0904 return $lval ne $rval;
0905 } elsif ($cmp eq "=~") {
0906 return $lval =~ m/$rval/;
0907 } elsif ($cmp eq "!~") {
0908 return $lval !~ m/$rval/;
0909 }
0910
0911 my $statement = "$lval $cmp $rval";
0912 my $ret = eval $statement;
0913
0914 # $@ stores error of eval
0915 if ($@) {
0916 return -1;
0917 }
0918
0919 return $ret;
0920 }
0921
0922 sub value_defined {
0923 my ($val) = @_;
0924
0925 return defined($variable{$2}) ||
0926 defined($opt{$2});
0927 }
0928
0929 sub process_expression {
0930 my ($name, $val) = @_;
0931
0932 my $c = $d++;
0933
0934 while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
0935 my $express = $1;
0936
0937 if (process_expression($name, $express)) {
0938 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
0939 } else {
0940 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
0941 }
0942 }
0943
0944 $d--;
0945 my $OR = "\\|\\|";
0946 my $AND = "\\&\\&";
0947
0948 while ($val =~ s/^(.*?)($OR|$AND)//) {
0949 my $express = $1;
0950 my $op = $2;
0951
0952 if (process_expression($name, $express)) {
0953 if ($op eq "||") {
0954 return 1;
0955 }
0956 } else {
0957 if ($op eq "&&") {
0958 return 0;
0959 }
0960 }
0961 }
0962
0963 if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) {
0964 my $ret = process_compare($1, $2, $3);
0965 if ($ret < 0) {
0966 die "$name: $.: Unable to process comparison\n";
0967 }
0968 return $ret;
0969 }
0970
0971 if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
0972 if (defined $1) {
0973 return !value_defined($2);
0974 } else {
0975 return value_defined($2);
0976 }
0977 }
0978
0979 if ($val =~ s/^\s*NOT\s+(.*)//) {
0980 my $express = $1;
0981 my $ret = process_expression($name, $express);
0982 return !$ret;
0983 }
0984
0985 if ($val =~ /^\s*0\s*$/) {
0986 return 0;
0987 } elsif ($val =~ /^\s*\d+\s*$/) {
0988 return 1;
0989 }
0990
0991 die ("$name: $.: Undefined content $val in if statement\n");
0992 }
0993
0994 sub process_if {
0995 my ($name, $value) = @_;
0996
0997 # Convert variables and replace undefined ones with 0
0998 my $val = process_variables($value, 1);
0999 my $ret = process_expression $name, $val;
1000
1001 return $ret;
1002 }
1003
1004 sub __read_config {
1005 my ($config, $current_test_num) = @_;
1006
1007 my $in;
1008 open($in, $config) || die "can't read file $config";
1009
1010 my $name = $config;
1011 $name =~ s,.*/(.*),$1,;
1012
1013 my $test_num = $$current_test_num;
1014 my $default = 1;
1015 my $repeat = 1;
1016 my $num_tests_set = 0;
1017 my $skip = 0;
1018 my $rest;
1019 my $line;
1020 my $test_case = 0;
1021 my $if = 0;
1022 my $if_set = 0;
1023 my $override = 0;
1024
1025 my %overrides;
1026
1027 while (<$in>) {
1028
1029 # ignore blank lines and comments
1030 next if (/^\s*$/ || /\s*\#/);
1031
1032 if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
1033
1034 my $type = $1;
1035 $rest = $2;
1036 $line = $2;
1037
1038 my $old_test_num;
1039 my $old_repeat;
1040 $override = 0;
1041
1042 if ($type eq "TEST_START") {
1043 if ($num_tests_set) {
1044 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
1045 }
1046
1047 $old_test_num = $test_num;
1048 $old_repeat = $repeat;
1049
1050 $test_num += $repeat;
1051 $default = 0;
1052 $repeat = 1;
1053 } else {
1054 $default = 1;
1055 }
1056
1057 # If SKIP is anywhere in the line, the command will be skipped
1058 if ($rest =~ s/\s+SKIP\b//) {
1059 $skip = 1;
1060 } else {
1061 $test_case = 1;
1062 $skip = 0;
1063 }
1064
1065 if ($rest =~ s/\sELSE\b//) {
1066 if (!$if) {
1067 die "$name: $.: ELSE found with out matching IF section\n$_";
1068 }
1069 $if = 0;
1070
1071 if ($if_set) {
1072 $skip = 1;
1073 } else {
1074 $skip = 0;
1075 }
1076 }
1077
1078 if ($rest =~ s/\sIF\s+(.*)//) {
1079 if (process_if($name, $1)) {
1080 $if_set = 1;
1081 } else {
1082 $skip = 1;
1083 }
1084 $if = 1;
1085 } else {
1086 $if = 0;
1087 $if_set = 0;
1088 }
1089
1090 if (!$skip) {
1091 if ($type eq "TEST_START") {
1092 if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
1093 $repeat = $1;
1094 $repeat_tests{"$test_num"} = $repeat;
1095 }
1096 } elsif ($rest =~ s/\sOVERRIDE\b//) {
1097 # DEFAULT only
1098 $override = 1;
1099 # Clear previous overrides
1100 %overrides = ();
1101 }
1102 }
1103
1104 if (!$skip && $rest !~ /^\s*$/) {
1105 die "$name: $.: Garbage found after $type\n$_";
1106 }
1107
1108 if ($skip && $type eq "TEST_START") {
1109 $test_num = $old_test_num;
1110 $repeat = $old_repeat;
1111 }
1112 } elsif (/^\s*ELSE\b(.*)$/) {
1113 if (!$if) {
1114 die "$name: $.: ELSE found with out matching IF section\n$_";
1115 }
1116 $rest = $1;
1117 if ($if_set) {
1118 $skip = 1;
1119 $rest = "";
1120 } else {
1121 $skip = 0;
1122
1123 if ($rest =~ /\sIF\s+(.*)/) {
1124 # May be a ELSE IF section.
1125 if (process_if($name, $1)) {
1126 $if_set = 1;
1127 } else {
1128 $skip = 1;
1129 }
1130 $rest = "";
1131 } else {
1132 $if = 0;
1133 }
1134 }
1135
1136 if ($rest !~ /^\s*$/) {
1137 die "$name: $.: Garbage found after DEFAULTS\n$_";
1138 }
1139
1140 } elsif (/^\s*INCLUDE\s+(\S+)/) {
1141
1142 next if ($skip);
1143
1144 if (!$default) {
1145 die "$name: $.: INCLUDE can only be done in default sections\n$_";
1146 }
1147
1148 my $file = process_variables($1);
1149
1150 if ($file !~ m,^/,) {
1151 # check the path of the config file first
1152 if ($config =~ m,(.*)/,) {
1153 if (-f "$1/$file") {
1154 $file = "$1/$file";
1155 }
1156 }
1157 }
1158
1159 if ( ! -r $file ) {
1160 die "$name: $.: Can't read file $file\n$_";
1161 }
1162
1163 if (__read_config($file, \$test_num)) {
1164 $test_case = 1;
1165 }
1166
1167 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=~\s*(.*?)\s*$/) {
1168
1169 next if ($skip);
1170
1171 my $lvalue = $1;
1172 my $rvalue = $2;
1173
1174 if ($default || $lvalue =~ /\[\d+\]$/) {
1175 set_eval($lvalue, $rvalue, $name);
1176 } else {
1177 my $val = "$lvalue\[$test_num\]";
1178 set_eval($val, $rvalue, $name);
1179 }
1180
1181 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
1182
1183 next if ($skip);
1184
1185 my $lvalue = $1;
1186 my $rvalue = $2;
1187
1188 if (!$default &&
1189 ($lvalue eq "NUM_TESTS" ||
1190 $lvalue eq "LOG_FILE" ||
1191 $lvalue eq "CLEAR_LOG")) {
1192 die "$name: $.: $lvalue must be set in DEFAULTS section\n";
1193 }
1194
1195 if ($lvalue eq "NUM_TESTS") {
1196 if ($test_num) {
1197 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
1198 }
1199 if (!$default) {
1200 die "$name: $.: NUM_TESTS must be set in default section\n";
1201 }
1202 $num_tests_set = 1;
1203 }
1204
1205 if ($default || $lvalue =~ /\[\d+\]$/) {
1206 set_value($lvalue, $rvalue, $override, \%overrides, $name);
1207 } else {
1208 my $val = "$lvalue\[$test_num\]";
1209 set_value($val, $rvalue, $override, \%overrides, $name);
1210
1211 if ($repeat > 1) {
1212 $repeats{$val} = $repeat;
1213 }
1214 }
1215 } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
1216 next if ($skip);
1217
1218 my $lvalue = $1;
1219 my $rvalue = $2;
1220
1221 # process config variables.
1222 # Config variables are only active while reading the
1223 # config and can be defined anywhere. They also ignore
1224 # TEST_START and DEFAULTS, but are skipped if they are in
1225 # on of these sections that have SKIP defined.
1226 # The save variable can be
1227 # defined multiple times and the new one simply overrides
1228 # the previous one.
1229 set_variable($lvalue, $rvalue);
1230
1231 } else {
1232 die "$name: $.: Garbage found in config\n$_";
1233 }
1234 }
1235
1236 if ($test_num) {
1237 $test_num += $repeat - 1;
1238 $opt{"NUM_TESTS"} = $test_num;
1239 }
1240
1241 close($in);
1242
1243 $$current_test_num = $test_num;
1244
1245 return $test_case;
1246 }
1247
1248 sub get_test_case {
1249 print "What test case would you like to run?\n";
1250 print " (build, install or boot)\n";
1251 print " Other tests are available but require editing ktest.conf\n";
1252 print " (see tools/testing/ktest/sample.conf)\n";
1253 my $ans = <STDIN>;
1254 chomp $ans;
1255 $default{"TEST_TYPE"} = $ans;
1256 }
1257
1258 sub read_config {
1259 my ($config) = @_;
1260
1261 my $test_case;
1262 my $test_num = 0;
1263
1264 $test_case = __read_config $config, \$test_num;
1265
1266 # make sure we have all mandatory configs
1267 get_mandatory_configs;
1268
1269 # was a test specified?
1270 if (!$test_case) {
1271 print "No test case specified.\n";
1272 get_test_case;
1273 }
1274
1275 # set any defaults
1276
1277 foreach my $default (keys %default) {
1278 if (!defined($opt{$default})) {
1279 $opt{$default} = $default{$default};
1280 }
1281 }
1282
1283 if ($opt{"IGNORE_UNUSED"} == 1) {
1284 return;
1285 }
1286
1287 my %not_used;
1288
1289 # check if there are any stragglers (typos?)
1290 foreach my $option (keys %opt) {
1291 my $op = $option;
1292 # remove per test labels.
1293 $op =~ s/\[.*\]//;
1294 if (!exists($option_map{$op}) &&
1295 !exists($default{$op}) &&
1296 !exists($used_options{$op})) {
1297 $not_used{$op} = 1;
1298 }
1299 }
1300
1301 if (%not_used) {
1302 my $s = "s are";
1303 $s = " is" if (keys %not_used == 1);
1304 print "The following option$s not used; could be a typo:\n";
1305 foreach my $option (keys %not_used) {
1306 print "$option\n";
1307 }
1308 print "Set IGNORE_UNUSED = 1 to have ktest ignore unused variables\n";
1309 if (!read_yn "Do you want to continue?") {
1310 exit -1;
1311 }
1312 }
1313 }
1314
1315 sub __eval_option {
1316 my ($name, $option, $i) = @_;
1317
1318 # Add space to evaluate the character before $
1319 $option = " $option";
1320 my $retval = "";
1321 my $repeated = 0;
1322 my $parent = 0;
1323
1324 foreach my $test (keys %repeat_tests) {
1325 if ($i >= $test &&
1326 $i < $test + $repeat_tests{$test}) {
1327
1328 $repeated = 1;
1329 $parent = $test;
1330 last;
1331 }
1332 }
1333
1334 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
1335 my $start = $1;
1336 my $var = $2;
1337 my $end = $3;
1338
1339 # Append beginning of line
1340 $retval = "$retval$start";
1341
1342 # If the iteration option OPT[$i] exists, then use that.
1343 # otherwise see if the default OPT (without [$i]) exists.
1344
1345 my $o = "$var\[$i\]";
1346 my $parento = "$var\[$parent\]";
1347
1348 # If a variable contains itself, use the default var
1349 if (($var eq $name) && defined($opt{$var})) {
1350 $o = $opt{$var};
1351 $retval = "$retval$o";
1352 } elsif (defined($opt{$o})) {
1353 $o = $opt{$o};
1354 $retval = "$retval$o";
1355 } elsif ($repeated && defined($opt{$parento})) {
1356 $o = $opt{$parento};
1357 $retval = "$retval$o";
1358 } elsif (defined($opt{$var})) {
1359 $o = $opt{$var};
1360 $retval = "$retval$o";
1361 } elsif ($var eq "KERNEL_VERSION" && defined($make)) {
1362 # special option KERNEL_VERSION uses kernel version
1363 get_version();
1364 $retval = "$retval$version";
1365 } else {
1366 $retval = "$retval\$\{$var\}";
1367 }
1368
1369 $option = $end;
1370 }
1371
1372 $retval = "$retval$option";
1373
1374 $retval =~ s/^ //;
1375
1376 return $retval;
1377 }
1378
1379 sub process_evals {
1380 my ($name, $option, $i) = @_;
1381
1382 my $option_name = "$name\[$i\]";
1383 my $ev;
1384
1385 my $old_option = $option;
1386
1387 if (defined($evals{$option_name})) {
1388 $ev = $evals{$option_name};
1389 } elsif (defined($evals{$name})) {
1390 $ev = $evals{$name};
1391 } else {
1392 return $option;
1393 }
1394
1395 for my $e (@{$ev}) {
1396 eval "\$option =~ $e";
1397 }
1398
1399 if ($option ne $old_option) {
1400 doprint("$name changed from '$old_option' to '$option'\n");
1401 }
1402
1403 return $option;
1404 }
1405
1406 sub eval_option {
1407 my ($name, $option, $i) = @_;
1408
1409 my $prev = "";
1410
1411 # Since an option can evaluate to another option,
1412 # keep iterating until we do not evaluate any more
1413 # options.
1414 my $r = 0;
1415 while ($prev ne $option) {
1416 # Check for recursive evaluations.
1417 # 100 deep should be more than enough.
1418 if ($r++ > 100) {
1419 die "Over 100 evaluations occurred with $option\n" .
1420 "Check for recursive variables\n";
1421 }
1422 $prev = $option;
1423 $option = __eval_option($name, $option, $i);
1424 }
1425
1426 $option = process_evals($name, $option, $i);
1427
1428 return $option;
1429 }
1430
1431 sub reboot {
1432 my ($time) = @_;
1433 my $powercycle = 0;
1434
1435 # test if the machine can be connected to within a few seconds
1436 my $stat = run_ssh("echo check machine status", $connect_timeout);
1437 if (!$stat) {
1438 doprint("power cycle\n");
1439 $powercycle = 1;
1440 }
1441
1442 if ($powercycle) {
1443 run_command "$power_cycle";
1444
1445 start_monitor;
1446 # flush out current monitor
1447 # May contain the reboot success line
1448 wait_for_monitor 1;
1449
1450 } else {
1451 # Make sure everything has been written to disk
1452 run_ssh("sync", 10);
1453
1454 if (defined($time)) {
1455 start_monitor;
1456 # flush out current monitor
1457 # May contain the reboot success line
1458 wait_for_monitor 1;
1459 }
1460
1461 # try to reboot normally
1462 if (run_command $reboot) {
1463 if (defined($powercycle_after_reboot)) {
1464 sleep $powercycle_after_reboot;
1465 run_command "$power_cycle";
1466 }
1467 } else {
1468 # nope? power cycle it.
1469 run_command "$power_cycle";
1470 }
1471 }
1472
1473 if (defined($time)) {
1474
1475 # We only want to get to the new kernel, don't fail
1476 # if we stumble over a call trace.
1477 my $save_ignore_errors = $ignore_errors;
1478 $ignore_errors = 1;
1479
1480 # Look for the good kernel to boot
1481 if (wait_for_monitor($time, "Linux version")) {
1482 # reboot got stuck?
1483 doprint "Reboot did not finish. Forcing power cycle\n";
1484 run_command "$power_cycle";
1485 }
1486
1487 $ignore_errors = $save_ignore_errors;
1488
1489 # Still need to wait for the reboot to finish
1490 wait_for_monitor($time, $reboot_success_line);
1491
1492 end_monitor;
1493 }
1494 }
1495
1496 sub reboot_to_good {
1497 my ($time) = @_;
1498
1499 if (defined($switch_to_good)) {
1500 run_command $switch_to_good;
1501 }
1502
1503 reboot $time;
1504 }
1505
1506 sub do_not_reboot {
1507 my $i = $iteration;
1508
1509 return $test_type eq "build" || $no_reboot ||
1510 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
1511 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build") ||
1512 ($test_type eq "config_bisect" && $opt{"CONFIG_BISECT_TYPE[$i]"} eq "build");
1513 }
1514
1515 sub get_test_name() {
1516 my $name;
1517
1518 if (defined($test_name)) {
1519 $name = "$test_name:$test_type";
1520 } else {
1521 $name = $test_type;
1522 }
1523 return $name;
1524 }
1525
1526 sub dodie {
1527 # avoid recursion
1528 return if ($in_die);
1529 $in_die = 1;
1530
1531 my $i = $iteration;
1532
1533 doprint "CRITICAL FAILURE... [TEST $i] ", @_, "\n";
1534
1535 if ($reboot_on_error && !do_not_reboot) {
1536 doprint "REBOOTING\n";
1537 reboot_to_good;
1538 } elsif ($poweroff_on_error && defined($power_off)) {
1539 doprint "POWERING OFF\n";
1540 `$power_off`;
1541 }
1542
1543 if (defined($opt{"LOG_FILE"})) {
1544 print " See $opt{LOG_FILE} for more info.\n";
1545 }
1546
1547 if ($email_on_error) {
1548 my $name = get_test_name;
1549 my $log_file;
1550
1551 if (defined($opt{"LOG_FILE"})) {
1552 my $whence = 2; # End of file
1553 my $log_size = tell LOG;
1554 my $size = $log_size - $test_log_start;
1555
1556 if (defined($mail_max_size)) {
1557 if ($size > $mail_max_size) {
1558 $size = $mail_max_size;
1559 }
1560 }
1561 my $pos = - $size;
1562 $log_file = "$tmpdir/log";
1563 open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)";
1564 open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n";
1565 seek(L, $pos, $whence);
1566 while (<L>) {
1567 print O;
1568 }
1569 close O;
1570 close L;
1571 }
1572
1573 send_email("KTEST: critical failure for test $i [$name]",
1574 "Your test started at $script_start_time has failed with:\n@_\n", $log_file);
1575 }
1576
1577 if ($monitor_cnt) {
1578 # restore terminal settings
1579 system("stty $stty_orig");
1580 }
1581
1582 if (defined($post_test)) {
1583 run_command $post_test;
1584 }
1585
1586 die @_, "\n";
1587 }
1588
1589 sub create_pty {
1590 my ($ptm, $pts) = @_;
1591 my $tmp;
1592 my $TIOCSPTLCK = 0x40045431;
1593 my $TIOCGPTN = 0x80045430;
1594
1595 sysopen($ptm, "/dev/ptmx", O_RDWR | O_NONBLOCK) or
1596 dodie "Can't open /dev/ptmx";
1597
1598 # unlockpt()
1599 $tmp = pack("i", 0);
1600 ioctl($ptm, $TIOCSPTLCK, $tmp) or
1601 dodie "ioctl TIOCSPTLCK for /dev/ptmx failed";
1602
1603 # ptsname()
1604 ioctl($ptm, $TIOCGPTN, $tmp) or
1605 dodie "ioctl TIOCGPTN for /dev/ptmx failed";
1606 $tmp = unpack("i", $tmp);
1607
1608 sysopen($pts, "/dev/pts/$tmp", O_RDWR | O_NONBLOCK) or
1609 dodie "Can't open /dev/pts/$tmp";
1610 }
1611
1612 sub exec_console {
1613 my ($ptm, $pts) = @_;
1614
1615 close($ptm);
1616
1617 close(\*STDIN);
1618 close(\*STDOUT);
1619 close(\*STDERR);
1620
1621 open(\*STDIN, '<&', $pts);
1622 open(\*STDOUT, '>&', $pts);
1623 open(\*STDERR, '>&', $pts);
1624
1625 close($pts);
1626
1627 exec $console or
1628 dodie "Can't open console $console";
1629 }
1630
1631 sub open_console {
1632 my ($ptm) = @_;
1633 my $pts = \*PTSFD;
1634 my $pid;
1635
1636 # save terminal settings
1637 $stty_orig = `stty -g`;
1638
1639 # place terminal in cbreak mode so that stdin can be read one character at
1640 # a time without having to wait for a newline
1641 system("stty -icanon -echo -icrnl");
1642
1643 create_pty($ptm, $pts);
1644
1645 $pid = fork;
1646
1647 if (!$pid) {
1648 # child
1649 exec_console($ptm, $pts)
1650 }
1651
1652 # parent
1653 close($pts);
1654
1655 return $pid;
1656
1657 open(PTSFD, "Stop perl from warning about single use of PTSFD");
1658 }
1659
1660 sub close_console {
1661 my ($fp, $pid) = @_;
1662
1663 doprint "kill child process $pid\n";
1664 kill $close_console_signal, $pid;
1665
1666 doprint "wait for child process $pid to exit\n";
1667 waitpid($pid, 0);
1668
1669 print "closing!\n";
1670 close($fp);
1671
1672 # restore terminal settings
1673 system("stty $stty_orig");
1674 }
1675
1676 sub start_monitor {
1677 if ($monitor_cnt++) {
1678 return;
1679 }
1680 $monitor_fp = \*MONFD;
1681 $monitor_pid = open_console $monitor_fp;
1682
1683 return;
1684
1685 open(MONFD, "Stop perl from warning about single use of MONFD");
1686 }
1687
1688 sub end_monitor {
1689 return if (!defined $console);
1690 if (--$monitor_cnt) {
1691 return;
1692 }
1693 close_console($monitor_fp, $monitor_pid);
1694 }
1695
1696 sub wait_for_monitor {
1697 my ($time, $stop) = @_;
1698 my $full_line = "";
1699 my $line;
1700 my $booted = 0;
1701 my $start_time = time;
1702 my $skip_call_trace = 0;
1703 my $bug = 0;
1704 my $bug_ignored = 0;
1705 my $now;
1706
1707 doprint "** Wait for monitor to settle down **\n";
1708
1709 # read the monitor and wait for the system to calm down
1710 while (!$booted) {
1711 $line = wait_for_input($monitor_fp, $time);
1712 last if (!defined($line));
1713 print "$line";
1714 $full_line .= $line;
1715
1716 if (defined($stop) && $full_line =~ /$stop/) {
1717 doprint "wait for monitor detected $stop\n";
1718 $booted = 1;
1719 }
1720
1721 if ($full_line =~ /\[ backtrace testing \]/) {
1722 $skip_call_trace = 1;
1723 }
1724
1725 if ($full_line =~ /call trace:/i) {
1726 if (!$bug && !$skip_call_trace) {
1727 if ($ignore_errors) {
1728 $bug_ignored = 1;
1729 } else {
1730 $bug = 1;
1731 }
1732 }
1733 }
1734
1735 if ($full_line =~ /\[ end of backtrace testing \]/) {
1736 $skip_call_trace = 0;
1737 }
1738
1739 if ($full_line =~ /Kernel panic -/) {
1740 $bug = 1;
1741 }
1742
1743 if ($line =~ /\n/) {
1744 $full_line = "";
1745 }
1746 $now = time;
1747 if ($now - $start_time >= $max_monitor_wait) {
1748 doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n";
1749 return 1;
1750 }
1751 }
1752 print "** Monitor flushed **\n";
1753
1754 # if stop is defined but wasn't hit, return error
1755
1756 if (defined($stop) && !$booted) {
1757 $bug = 1;
1758 }
1759 return $bug;
1760 }
1761
1762 sub save_logs {
1763 my ($result, $basedir) = @_;
1764 my @t = localtime;
1765 my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1766 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1767
1768 my $type = $build_type;
1769 if ($type =~ /useconfig/) {
1770 $type = "useconfig";
1771 }
1772
1773 my $dir = "$machine-$test_type-$type-$result-$date";
1774
1775 $dir = "$basedir/$dir";
1776
1777 if (!-d $dir) {
1778 mkpath($dir) or
1779 dodie "can't create $dir";
1780 }
1781
1782 my %files = (
1783 "config" => $output_config,
1784 "buildlog" => $buildlog,
1785 "dmesg" => $dmesg,
1786 "testlog" => $testlog,
1787 );
1788
1789 while (my ($name, $source) = each(%files)) {
1790 if (-f "$source") {
1791 cp "$source", "$dir/$name" or
1792 dodie "failed to copy $source";
1793 }
1794 }
1795
1796 doprint "*** Saved info to $dir ***\n";
1797 }
1798
1799 sub fail {
1800
1801 if ($die_on_failure) {
1802 dodie @_;
1803 }
1804
1805 doprint "FAILED\n";
1806
1807 my $i = $iteration;
1808
1809
1810 if (!do_not_reboot) {
1811 doprint "REBOOTING\n";
1812 reboot_to_good $sleep_time;
1813 }
1814
1815 my $name = "";
1816
1817 if (defined($test_name)) {
1818 $name = " ($test_name)";
1819 }
1820
1821 print_times;
1822
1823 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1824 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1825 doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1826 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1827 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1828
1829 if (defined($store_failures)) {
1830 save_logs "fail", $store_failures;
1831 }
1832
1833 if (defined($post_test)) {
1834 run_command $post_test;
1835 }
1836
1837 return 1;
1838 }
1839
1840 sub run_command {
1841 my ($command, $redirect, $timeout) = @_;
1842 my $start_time;
1843 my $end_time;
1844 my $dolog = 0;
1845 my $dord = 0;
1846 my $dostdout = 0;
1847 my $pid;
1848 my $command_orig = $command;
1849
1850 $command =~ s/\$SSH_USER/$ssh_user/g;
1851 $command =~ s/\$MACHINE/$machine/g;
1852
1853 doprint("$command ... ");
1854 $start_time = time;
1855
1856 $pid = open(CMD, "$command 2>&1 |") or
1857 (fail "unable to exec $command" and return 0);
1858
1859 if (defined($opt{"LOG_FILE"})) {
1860 $dolog = 1;
1861 }
1862
1863 if (defined($redirect)) {
1864 if ($redirect eq 1) {
1865 $dostdout = 1;
1866
1867 doprint "\n";
1868 } else {
1869 open (RD, ">$redirect") or
1870 dodie "failed to write to redirect $redirect";
1871 $dord = 1;
1872 }
1873 }
1874
1875 my $hit_timeout = 0;
1876
1877 while (1) {
1878 my $fp = \*CMD;
1879 if (defined($timeout)) {
1880 doprint "timeout = $timeout\n";
1881 }
1882 my $line = wait_for_input($fp, $timeout);
1883 if (!defined($line)) {
1884 my $now = time;
1885 if (defined($timeout) && (($now - $start_time) >= $timeout)) {
1886 doprint "Hit timeout of $timeout, killing process\n";
1887 $hit_timeout = 1;
1888 kill 9, $pid;
1889 }
1890 last;
1891 }
1892 print LOG $line if ($dolog);
1893 print RD $line if ($dord);
1894 print $line if ($dostdout);
1895 }
1896
1897 waitpid($pid, 0);
1898
1899 $run_command_status = $? >> 8;
1900
1901 if ($command_orig eq $default{REBOOT} &&
1902 $run_command_status == $reboot_return_code) {
1903 $run_command_status = 0;
1904 }
1905
1906 close(CMD);
1907 close(RD) if ($dord);
1908
1909 $end_time = time;
1910 my $delta = $end_time - $start_time;
1911
1912 if ($delta == 1) {
1913 doprint "[1 second] ";
1914 } else {
1915 doprint "[$delta seconds] ";
1916 }
1917
1918 if ($hit_timeout) {
1919 $run_command_status = 1;
1920 }
1921
1922 if ($run_command_status) {
1923 doprint "FAILED!\n";
1924 } else {
1925 doprint "SUCCESS\n";
1926 }
1927
1928 return !$run_command_status;
1929 }
1930
1931 sub run_ssh {
1932 my ($cmd, $timeout) = @_;
1933 my $cp_exec = $ssh_exec;
1934
1935 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1936 return run_command "$cp_exec", undef , $timeout;
1937 }
1938
1939 sub run_scp {
1940 my ($src, $dst, $cp_scp) = @_;
1941
1942 $cp_scp =~ s/\$SRC_FILE/$src/g;
1943 $cp_scp =~ s/\$DST_FILE/$dst/g;
1944
1945 return run_command "$cp_scp";
1946 }
1947
1948 sub run_scp_install {
1949 my ($src, $dst) = @_;
1950
1951 my $cp_scp = $scp_to_target_install;
1952
1953 return run_scp($src, $dst, $cp_scp);
1954 }
1955
1956 sub run_scp_mod {
1957 my ($src, $dst) = @_;
1958
1959 my $cp_scp = $scp_to_target;
1960
1961 return run_scp($src, $dst, $cp_scp);
1962 }
1963
1964 sub _get_grub_index {
1965
1966 my ($command, $target, $skip) = @_;
1967
1968 return if (defined($grub_number) && defined($last_grub_menu) &&
1969 $last_grub_menu eq $grub_menu && defined($last_machine) &&
1970 $last_machine eq $machine);
1971
1972 doprint "Find $reboot_type menu ... ";
1973 $grub_number = -1;
1974
1975 my $ssh_grub = $ssh_exec;
1976 $ssh_grub =~ s,\$SSH_COMMAND,$command,g;
1977
1978 open(IN, "$ssh_grub |") or
1979 dodie "unable to execute $command";
1980
1981 my $found = 0;
1982
1983 while (<IN>) {
1984 if (/$target/) {
1985 $grub_number++;
1986 $found = 1;
1987 last;
1988 } elsif (/$skip/) {
1989 $grub_number++;
1990 }
1991 }
1992 close(IN);
1993
1994 dodie "Could not find '$grub_menu' through $command on $machine"
1995 if (!$found);
1996 doprint "$grub_number\n";
1997 $last_grub_menu = $grub_menu;
1998 $last_machine = $machine;
1999 }
2000
2001 sub get_grub_index {
2002
2003 my $command;
2004 my $target;
2005 my $skip;
2006 my $grub_menu_qt;
2007
2008 if ($reboot_type !~ /^grub/) {
2009 return;
2010 }
2011
2012 $grub_menu_qt = quotemeta($grub_menu);
2013
2014 if ($reboot_type eq "grub") {
2015 $command = "cat /boot/grub/menu.lst";
2016 $target = '^\s*title\s+' . $grub_menu_qt . '\s*$';
2017 $skip = '^\s*title\s';
2018 } elsif ($reboot_type eq "grub2") {
2019 $command = "cat $grub_file";
2020 $target = '^menuentry.*' . $grub_menu_qt;
2021 $skip = '^menuentry\s|^submenu\s';
2022 } elsif ($reboot_type eq "grub2bls") {
2023 $command = $grub_bls_get;
2024 $target = '^title=.*' . $grub_menu_qt;
2025 $skip = '^title=';
2026 } else {
2027 return;
2028 }
2029
2030 _get_grub_index($command, $target, $skip);
2031 }
2032
2033 sub wait_for_input {
2034 my ($fp, $time) = @_;
2035 my $start_time;
2036 my $rin;
2037 my $rout;
2038 my $nr;
2039 my $buf;
2040 my $line;
2041 my $ch;
2042
2043 if (!defined($time)) {
2044 $time = $timeout;
2045 }
2046
2047 $rin = '';
2048 vec($rin, fileno($fp), 1) = 1;
2049 vec($rin, fileno(\*STDIN), 1) = 1;
2050
2051 $start_time = time;
2052
2053 while (1) {
2054 $nr = select($rout=$rin, undef, undef, $time);
2055
2056 last if ($nr <= 0);
2057
2058
2059 if (vec($rout, fileno(\*STDIN), 1) == 1) {
2060 $nr = sysread(\*STDIN, $buf, 1000);
2061 syswrite($fp, $buf, $nr) if ($nr > 0);
2062 }
2063
2064
2065 if (vec($rout, fileno($fp), 1) != 1) {
2066 last if (defined($time) && (time - $start_time > $time));
2067 next;
2068 }
2069
2070 $line = "";
2071
2072
2073 while (sysread $fp, $ch, 1) {
2074 $line .= $ch;
2075 last if ($ch eq "\n");
2076 }
2077
2078 last if (!length($line));
2079
2080 return $line;
2081 }
2082 return undef;
2083 }
2084
2085 sub reboot_to {
2086 if (defined($switch_to_test)) {
2087 run_command $switch_to_test;
2088 }
2089
2090 if ($reboot_type eq "grub") {
2091 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
2092 } elsif (($reboot_type eq "grub2") or ($reboot_type eq "grub2bls")) {
2093 run_ssh "$grub_reboot $grub_number";
2094 } elsif ($reboot_type eq "syslinux") {
2095 run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path";
2096 } elsif (defined $reboot_script) {
2097 run_command "$reboot_script";
2098 }
2099 reboot;
2100 }
2101
2102 sub get_sha1 {
2103 my ($commit) = @_;
2104
2105 doprint "git rev-list --max-count=1 $commit ... ";
2106 my $sha1 = `git rev-list --max-count=1 $commit`;
2107 my $ret = $?;
2108
2109 logit $sha1;
2110
2111 if ($ret) {
2112 doprint "FAILED\n";
2113 dodie "Failed to get git $commit";
2114 }
2115
2116 print "SUCCESS\n";
2117
2118 chomp $sha1;
2119
2120 return $sha1;
2121 }
2122
2123 sub monitor {
2124 my $booted = 0;
2125 my $bug = 0;
2126 my $bug_ignored = 0;
2127 my $skip_call_trace = 0;
2128 my $loops;
2129
2130 my $start_time = time;
2131
2132 wait_for_monitor 5;
2133
2134 my $line;
2135 my $full_line = "";
2136
2137 open(DMESG, "> $dmesg") or
2138 dodie "unable to write to $dmesg";
2139
2140 reboot_to;
2141
2142 my $success_start;
2143 my $failure_start;
2144 my $monitor_start = time;
2145 my $done = 0;
2146 my $version_found = 0;
2147
2148 while (!$done) {
2149 if ($bug && defined($stop_after_failure) &&
2150 $stop_after_failure >= 0) {
2151 my $time = $stop_after_failure - (time - $failure_start);
2152 $line = wait_for_input($monitor_fp, $time);
2153 if (!defined($line)) {
2154 doprint "bug timed out after $booted_timeout seconds\n";
2155 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
2156 last;
2157 }
2158 } elsif ($booted) {
2159 $line = wait_for_input($monitor_fp, $booted_timeout);
2160 if (!defined($line)) {
2161 my $s = $booted_timeout == 1 ? "" : "s";
2162 doprint "Successful boot found: break after $booted_timeout second$s\n";
2163 last;
2164 }
2165 } else {
2166 $line = wait_for_input($monitor_fp);
2167 if (!defined($line)) {
2168 my $s = $timeout == 1 ? "" : "s";
2169 doprint "Timed out after $timeout second$s\n";
2170 last;
2171 }
2172 }
2173
2174 doprint $line;
2175 print DMESG $line;
2176
2177
2178 $full_line .= $line;
2179
2180 if ($full_line =~ /$success_line/) {
2181 $booted = 1;
2182 $success_start = time;
2183 }
2184
2185 if ($booted && defined($stop_after_success) &&
2186 $stop_after_success >= 0) {
2187 my $now = time;
2188 if ($now - $success_start >= $stop_after_success) {
2189 doprint "Test forced to stop after $stop_after_success seconds after success\n";
2190 last;
2191 }
2192 }
2193
2194 if ($full_line =~ /\[ backtrace testing \]/) {
2195 $skip_call_trace = 1;
2196 }
2197
2198 if ($full_line =~ /call trace:/i) {
2199 if (!$bug && !$skip_call_trace) {
2200 if ($ignore_errors) {
2201 $bug_ignored = 1;
2202 } else {
2203 $bug = 1;
2204 $failure_start = time;
2205 }
2206 }
2207 }
2208
2209 if ($bug && defined($stop_after_failure) &&
2210 $stop_after_failure >= 0) {
2211 my $now = time;
2212 if ($now - $failure_start >= $stop_after_failure) {
2213 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
2214 last;
2215 }
2216 }
2217
2218 if ($full_line =~ /\[ end of backtrace testing \]/) {
2219 $skip_call_trace = 0;
2220 }
2221
2222 if ($full_line =~ /Kernel panic -/) {
2223 $failure_start = time;
2224 $bug = 1;
2225 }
2226
2227
2228 if ($full_line =~ /\bLinux version (\S+).*\n/) {
2229 if ($1 eq $version) {
2230 $version_found = 1;
2231 } elsif ($version_found && $detect_triplefault) {
2232
2233
2234
2235 doprint "Already booted in Linux kernel $version, but now\n";
2236 doprint "we booted into Linux kernel $1.\n";
2237 doprint "Assuming that this is a triple fault.\n";
2238 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
2239 last;
2240 }
2241 }
2242
2243 if ($line =~ /\n/) {
2244 $full_line = "";
2245 }
2246
2247 if ($stop_test_after > 0 && !$booted && !$bug) {
2248 if (time - $monitor_start > $stop_test_after) {
2249 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
2250 $done = 1;
2251 }
2252 }
2253 }
2254
2255 my $end_time = time;
2256 $reboot_time = $end_time - $start_time;
2257
2258 close(DMESG);
2259
2260 if ($bug) {
2261 return 0 if ($in_bisect);
2262 fail "failed - got a bug report" and return 0;
2263 }
2264
2265 if (!$booted) {
2266 return 0 if ($in_bisect);
2267 fail "failed - never got a boot prompt." and return 0;
2268 }
2269
2270 if ($bug_ignored) {
2271 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
2272 }
2273
2274 return 1;
2275 }
2276
2277 sub eval_kernel_version {
2278 my ($option) = @_;
2279
2280 $option =~ s/\$KERNEL_VERSION/$version/g;
2281
2282 return $option;
2283 }
2284
2285 sub do_post_install {
2286
2287 return if (!defined($post_install));
2288
2289 my $cp_post_install = eval_kernel_version $post_install;
2290 run_command "$cp_post_install" or
2291 dodie "Failed to run post install";
2292 }
2293
2294
2295
2296 sub test_booted {
2297 if (!run_ssh "echo testing connection") {
2298 reboot $sleep_time;
2299 }
2300 }
2301
2302 sub install {
2303
2304 return if ($no_install);
2305
2306 my $start_time = time;
2307
2308 if (defined($pre_install)) {
2309 my $cp_pre_install = eval_kernel_version $pre_install;
2310 run_command "$cp_pre_install" or
2311 dodie "Failed to run pre install";
2312 }
2313
2314 my $cp_target = eval_kernel_version $target_image;
2315
2316 test_booted;
2317
2318 run_scp_install "$outputdir/$build_target", "$cp_target" or
2319 dodie "failed to copy image";
2320
2321 my $install_mods = 0;
2322
2323
2324 $install_mods = 0;
2325 open(IN, "$output_config") or dodie("Can't read config file");
2326 while (<IN>) {
2327 if (/CONFIG_MODULES(=y)?/) {
2328 if (defined($1)) {
2329 $install_mods = 1;
2330 last;
2331 }
2332 }
2333 }
2334 close(IN);
2335
2336 if (!$install_mods) {
2337 do_post_install;
2338 doprint "No modules needed\n";
2339 my $end_time = time;
2340 $install_time = $end_time - $start_time;
2341 return;
2342 }
2343
2344 run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or
2345 dodie "Failed to install modules";
2346
2347 my $modlib = "/lib/modules/$version";
2348 my $modtar = "ktest-mods.tar.bz2";
2349
2350 run_ssh "rm -rf $modlib" or
2351 dodie "failed to remove old mods: $modlib";
2352
2353
2354 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
2355 dodie "making tarball";
2356
2357 run_scp_mod "$tmpdir/$modtar", "/tmp" or
2358 dodie "failed to copy modules";
2359
2360 unlink "$tmpdir/$modtar";
2361
2362 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
2363 dodie "failed to tar modules";
2364
2365 run_ssh "rm -f /tmp/$modtar";
2366
2367 do_post_install;
2368
2369 my $end_time = time;
2370 $install_time = $end_time - $start_time;
2371 }
2372
2373 sub get_version {
2374
2375 return if ($have_version);
2376 doprint "$make kernelrelease ... ";
2377 $version = `$make -s kernelrelease | tail -1`;
2378 chomp($version);
2379 doprint "$version\n";
2380 $have_version = 1;
2381 }
2382
2383 sub start_monitor_and_install {
2384
2385
2386
2387 if (defined $console) {
2388 start_monitor;
2389 wait_for_monitor 5;
2390 end_monitor;
2391 }
2392
2393 get_grub_index;
2394 get_version;
2395 install;
2396
2397 start_monitor if (defined $console);
2398 return monitor;
2399 }
2400
2401 sub process_warning_line {
2402 my ($line) = @_;
2403
2404 chomp $line;
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414 $line =~ s/^(\s*\S+:\d+:)\d+/$1/;
2415
2416
2417 $line =~ s/$utf8_quote/'/g;
2418
2419 return $line;
2420 }
2421
2422
2423
2424
2425
2426
2427 sub check_buildlog {
2428 return 1 if (!defined $warnings_file);
2429
2430 my %warnings_list;
2431
2432
2433 my $save_no_reboot = $no_reboot;
2434 $no_reboot = 1;
2435
2436 if (-f $warnings_file) {
2437 open(IN, $warnings_file) or
2438 dodie "Error opening $warnings_file";
2439
2440 while (<IN>) {
2441 if (/$check_build_re/) {
2442 my $warning = process_warning_line $_;
2443
2444 $warnings_list{$warning} = 1;
2445 }
2446 }
2447 close(IN);
2448 }
2449
2450
2451
2452
2453 open(IN, $buildlog) or dodie "Can't open $buildlog";
2454 while (<IN>) {
2455 if (/$check_build_re/) {
2456 my $warning = process_warning_line $_;
2457
2458 if (!defined $warnings_list{$warning}) {
2459 fail "New warning found (not in $warnings_file)\n$_\n";
2460 $no_reboot = $save_no_reboot;
2461 return 0;
2462 }
2463 }
2464 }
2465 $no_reboot = $save_no_reboot;
2466 close(IN);
2467 }
2468
2469 sub check_patch_buildlog {
2470 my ($patch) = @_;
2471
2472 my @files = `git show $patch | diffstat -l`;
2473
2474 foreach my $file (@files) {
2475 chomp $file;
2476 }
2477
2478 open(IN, "git show $patch |") or
2479 dodie "failed to show $patch";
2480 while (<IN>) {
2481 if () {
2482 chomp $1;
2483 $files[$#files] = $1;
2484 }
2485 }
2486 close(IN);
2487
2488 open(IN, $buildlog) or dodie "Can't open $buildlog";
2489 while (<IN>) {
2490 if (/^\s*(.*?):.*(warning|error)/) {
2491 my $err = $1;
2492 foreach my $file (@files) {
2493 my $fullpath = "$builddir/$file";
2494 if ($file eq $err || $fullpath eq $err) {
2495 fail "$file built with warnings" and return 0;
2496 }
2497 }
2498 }
2499 }
2500 close(IN);
2501
2502 return 1;
2503 }
2504
2505 sub apply_min_config {
2506 my $outconfig = "$output_config.new";
2507
2508
2509
2510
2511
2512 doprint "Applying minimum configurations into $output_config.new\n";
2513
2514 open (OUT, ">$outconfig") or
2515 dodie "Can't create $outconfig";
2516
2517 if (-f $output_config) {
2518 open (IN, $output_config) or
2519 dodie "Failed to open $output_config";
2520 while (<IN>) {
2521 if (/^(
2522 next if (defined($force_config{$2}));
2523 }
2524 print OUT;
2525 }
2526 close IN;
2527 }
2528 foreach my $config (keys %force_config) {
2529 print OUT "$force_config{$config}\n";
2530 }
2531 close OUT;
2532
2533 run_command "mv $outconfig $output_config";
2534 }
2535
2536 sub make_oldconfig {
2537
2538 my @force_list = keys %force_config;
2539
2540 if ($#force_list >= 0) {
2541 apply_min_config;
2542 }
2543
2544 if (!run_command "$make olddefconfig") {
2545
2546
2547 doprint "olddefconfig failed, trying make oldnoconfig\n";
2548 if (!run_command "$make oldnoconfig") {
2549 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
2550
2551 run_command "yes '' | $make oldconfig" or
2552 dodie "failed make config oldconfig";
2553 }
2554 }
2555 }
2556
2557
2558 sub load_force_config {
2559 my ($config) = @_;
2560
2561 doprint "Loading force configs from $config\n";
2562 open(IN, $config) or
2563 dodie "failed to read $config";
2564 while (<IN>) {
2565 chomp;
2566 if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
2567 $force_config{$1} = $_;
2568 } elsif (/^
2569 $force_config{$1} = $_;
2570 }
2571 }
2572 close IN;
2573 }
2574
2575 sub build {
2576 my ($type) = @_;
2577
2578 unlink $buildlog;
2579
2580 my $start_time = time;
2581
2582
2583 my $save_no_reboot = $no_reboot;
2584 $no_reboot = 1;
2585
2586
2587 $have_version = 0;
2588
2589 if (defined($pre_build)) {
2590 my $ret = run_command $pre_build;
2591 if (!$ret && defined($pre_build_die) &&
2592 $pre_build_die) {
2593 dodie "failed to pre_build\n";
2594 }
2595 }
2596
2597 if ($type =~ /^useconfig:(.*)/) {
2598 run_command "cp $1 $output_config" or
2599 dodie "could not copy $1 to .config";
2600
2601 $type = "oldconfig";
2602 }
2603
2604
2605 if ($type eq "oldconfig") {
2606 $type = "olddefconfig";
2607
2608
2609 run_command "touch $output_config";
2610
2611 if (!$noclean) {
2612 run_command "mv $output_config $outputdir/config_temp" or
2613 dodie "moving .config";
2614
2615 run_command "$make mrproper" or dodie "make mrproper";
2616
2617 run_command "mv $outputdir/config_temp $output_config" or
2618 dodie "moving config_temp";
2619 }
2620 } elsif (!$noclean) {
2621 unlink "$output_config";
2622 run_command "$make mrproper" or
2623 dodie "make mrproper";
2624 }
2625
2626
2627 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
2628 print OUT "$localversion\n";
2629 close(OUT);
2630
2631 if (defined($minconfig)) {
2632 load_force_config($minconfig);
2633 }
2634
2635 if ($type ne "olddefconfig") {
2636 run_command "$make $type" or
2637 dodie "failed make config";
2638 }
2639
2640 make_oldconfig;
2641
2642 if (not defined($build_options)){
2643 $build_options = "";
2644 }
2645 my $build_ret = run_command "$make $build_options", $buildlog;
2646
2647 if (defined($post_build)) {
2648
2649
2650 get_version;
2651 my $ret = run_command $post_build;
2652 if (!$ret && defined($post_build_die) &&
2653 $post_build_die) {
2654 dodie "failed to post_build\n";
2655 }
2656 }
2657
2658 if (!$build_ret) {
2659
2660 if ($in_bisect) {
2661 $no_reboot = $save_no_reboot;
2662 return 0;
2663 }
2664 fail "failed build" and return 0;
2665 }
2666
2667 $no_reboot = $save_no_reboot;
2668
2669 my $end_time = time;
2670 $build_time = $end_time - $start_time;
2671
2672 return 1;
2673 }
2674
2675 sub halt {
2676 if (!run_ssh "halt" or defined($power_off)) {
2677 if (defined($poweroff_after_halt)) {
2678 sleep $poweroff_after_halt;
2679 run_command "$power_off";
2680 }
2681 } else {
2682
2683 run_command "$power_off";
2684 }
2685 }
2686
2687 sub success {
2688 my ($i) = @_;
2689
2690 $successes++;
2691
2692 my $name = "";
2693
2694 if (defined($test_name)) {
2695 $name = " ($test_name)";
2696 }
2697
2698 print_times;
2699
2700 doprint "\n\n";
2701 doprint "*******************************************\n";
2702 doprint "*******************************************\n";
2703 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n";
2704 doprint "*******************************************\n";
2705 doprint "*******************************************\n";
2706
2707 if (defined($store_successes)) {
2708 save_logs "success", $store_successes;
2709 }
2710
2711 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
2712 doprint "Reboot and wait $sleep_time seconds\n";
2713 reboot_to_good $sleep_time;
2714 }
2715
2716 if (defined($post_test)) {
2717 run_command $post_test;
2718 }
2719 }
2720
2721 sub answer_bisect {
2722 for (;;) {
2723 doprint "Pass, fail, or skip? [p/f/s]";
2724 my $ans = <STDIN>;
2725 chomp $ans;
2726 if ($ans eq "p" || $ans eq "P") {
2727 return 1;
2728 } elsif ($ans eq "f" || $ans eq "F") {
2729 return 0;
2730 } elsif ($ans eq "s" || $ans eq "S") {
2731 return -1;
2732 } else {
2733 print "Please answer 'p', 'f', or 's'\n";
2734 }
2735 }
2736 }
2737
2738 sub child_run_test {
2739
2740
2741 $reboot_on_error = 0;
2742 $poweroff_on_error = 0;
2743 $die_on_failure = 1;
2744
2745 run_command $run_test, $testlog;
2746
2747 exit $run_command_status;
2748 }
2749
2750 sub child_finished {
2751 $child_done = 1;
2752 }
2753
2754 sub do_run_test {
2755 my $child_pid;
2756 my $child_exit;
2757 my $line;
2758 my $full_line;
2759 my $bug = 0;
2760 my $bug_ignored = 0;
2761
2762 my $start_time = time;
2763
2764 wait_for_monitor 1;
2765
2766 doprint "run test $run_test\n";
2767
2768 $child_done = 0;
2769
2770 $SIG{CHLD} = ;
2771
2772 $child_pid = fork;
2773
2774 child_run_test if (!$child_pid);
2775
2776 $full_line = "";
2777
2778 do {
2779 $line = wait_for_input($monitor_fp, 1);
2780 if (defined($line)) {
2781
2782
2783 $full_line .= $line;
2784 doprint $line;
2785
2786 if ($full_line =~ /call trace:/i) {
2787 if ($ignore_errors) {
2788 $bug_ignored = 1;
2789 } else {
2790 $bug = 1;
2791 }
2792 }
2793
2794 if ($full_line =~ /Kernel panic -/) {
2795 $bug = 1;
2796 }
2797
2798 if ($line =~ /\n/) {
2799 $full_line = "";
2800 }
2801 }
2802 } while (!$child_done && !$bug);
2803
2804 if (!$bug && $bug_ignored) {
2805 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
2806 }
2807
2808 if ($bug) {
2809 my $failure_start = time;
2810 my $now;
2811 do {
2812 $line = wait_for_input($monitor_fp, 1);
2813 if (defined($line)) {
2814 doprint $line;
2815 }
2816 $now = time;
2817 if ($now - $failure_start >= $stop_after_failure) {
2818 last;
2819 }
2820 } while (defined($line));
2821
2822 doprint "Detected kernel crash!\n";
2823
2824 kill 9, $child_pid;
2825 }
2826
2827 waitpid $child_pid, 0;
2828 $child_exit = $? >> 8;
2829
2830 my $end_time = time;
2831 $test_time = $end_time - $start_time;
2832
2833 if (!$bug && $in_bisect) {
2834 if (defined($bisect_ret_good)) {
2835 if ($child_exit == $bisect_ret_good) {
2836 return 1;
2837 }
2838 }
2839 if (defined($bisect_ret_skip)) {
2840 if ($child_exit == $bisect_ret_skip) {
2841 return -1;
2842 }
2843 }
2844 if (defined($bisect_ret_abort)) {
2845 if ($child_exit == $bisect_ret_abort) {
2846 fail "test abort" and return -2;
2847 }
2848 }
2849 if (defined($bisect_ret_bad)) {
2850 if ($child_exit == $bisect_ret_skip) {
2851 return 0;
2852 }
2853 }
2854 if (defined($bisect_ret_default)) {
2855 if ($bisect_ret_default eq "good") {
2856 return 1;
2857 } elsif ($bisect_ret_default eq "bad") {
2858 return 0;
2859 } elsif ($bisect_ret_default eq "skip") {
2860 return -1;
2861 } elsif ($bisect_ret_default eq "abort") {
2862 return -2;
2863 } else {
2864 fail "unknown default action: $bisect_ret_default"
2865 and return -2;
2866 }
2867 }
2868 }
2869
2870 if ($bug || $child_exit) {
2871 return 0 if $in_bisect;
2872 fail "test failed" and return 0;
2873 }
2874 return 1;
2875 }
2876
2877 sub run_git_bisect {
2878 my ($command) = @_;
2879
2880 doprint "$command ... ";
2881
2882 my $output = `$command 2>&1`;
2883 my $ret = $?;
2884
2885 logit $output;
2886
2887 if ($ret) {
2888 doprint "FAILED\n";
2889 dodie "Failed to git bisect";
2890 }
2891
2892 doprint "SUCCESS\n";
2893 if ($output =~ ) {
2894 doprint "$1 [$2]\n";
2895 } elsif ($output =~ ) {
2896 $bisect_bad_commit = $1;
2897 doprint "Found bad commit... $1\n";
2898 return 0;
2899 } else {
2900
2901 print $output;
2902 }
2903
2904 return 1;
2905 }
2906
2907 sub bisect_reboot {
2908 doprint "Reboot and sleep $bisect_sleep_time seconds\n";
2909 reboot_to_good $bisect_sleep_time;
2910 }
2911
2912
2913 sub run_bisect_test {
2914 my ($type, $buildtype) = @_;
2915
2916 my $failed = 0;
2917 my $result;
2918 my $output;
2919 my $ret;
2920
2921 $in_bisect = 1;
2922
2923 build $buildtype or $failed = 1;
2924
2925 if ($type ne "build") {
2926 if ($failed && $bisect_skip) {
2927 $in_bisect = 0;
2928 return -1;
2929 }
2930 dodie "Failed on build" if $failed;
2931
2932
2933 start_monitor_and_install or $failed = 1;
2934
2935 if ($type ne "boot") {
2936 if ($failed && $bisect_skip) {
2937 end_monitor;
2938 bisect_reboot;
2939 $in_bisect = 0;
2940 return -1;
2941 }
2942 dodie "Failed on boot" if $failed;
2943
2944 do_run_test or $failed = 1;
2945 }
2946 end_monitor;
2947 }
2948
2949 if ($failed) {
2950 $result = 0;
2951 } else {
2952 $result = 1;
2953 }
2954
2955
2956 if ($type ne "build") {
2957 bisect_reboot;
2958 }
2959 $in_bisect = 0;
2960
2961 return $result;
2962 }
2963
2964 sub run_bisect {
2965 my ($type) = @_;
2966 my $buildtype = "oldconfig";
2967
2968
2969 if (defined($minconfig)) {
2970 $buildtype = "useconfig:$minconfig";
2971 }
2972
2973
2974
2975 my $ret = 1;
2976
2977
2978 if ($bisect_tries < 1 && $bisect_manual) {
2979 $ret = answer_bisect;
2980 }
2981
2982 for (my $i = 0; $i < $bisect_tries; $i++) {
2983 if ($bisect_tries > 1) {
2984 my $t = $i + 1;
2985 doprint("Running bisect trial $t of $bisect_tries:\n");
2986 }
2987 $ret = run_bisect_test $type, $buildtype;
2988
2989 if ($bisect_manual) {
2990 $ret = answer_bisect;
2991 }
2992
2993 last if (!$ret);
2994 }
2995
2996
2997 if ($reverse_bisect && $ret >= 0) {
2998 $ret = !$ret;
2999 }
3000
3001 if ($ret > 0) {
3002 return "good";
3003 } elsif ($ret == 0) {
3004 return "bad";
3005 } elsif ($bisect_skip) {
3006 doprint "HIT A BAD COMMIT ... SKIPPING\n";
3007 return "skip";
3008 }
3009 }
3010
3011 sub update_bisect_replay {
3012 my $tmp_log = "$tmpdir/ktest_bisect_log";
3013 run_command "git bisect log > $tmp_log" or
3014 dodie "can't create bisect log";
3015 return $tmp_log;
3016 }
3017
3018 sub bisect {
3019 my ($i) = @_;
3020
3021 my $result;
3022
3023 dodie "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good));
3024 dodie "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad));
3025 dodie "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type));
3026
3027 my $good = $bisect_good;
3028 my $bad = $bisect_bad;
3029 my $type = $bisect_type;
3030 my $start = $bisect_start;
3031 my $replay = $bisect_replay;
3032 my $start_files = $bisect_files;
3033
3034 if (defined($start_files)) {
3035 $start_files = " -- " . $start_files;
3036 } else {
3037 $start_files = "";
3038 }
3039
3040
3041 $good = get_sha1($good);
3042 $bad = get_sha1($bad);
3043
3044 if (defined($bisect_reverse) && $bisect_reverse == 1) {
3045 doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
3046 $reverse_bisect = 1;
3047 } else {
3048 $reverse_bisect = 0;
3049 }
3050
3051
3052 if ($type eq "test" && !defined($run_test)) {
3053 $type = "boot";
3054 }
3055
3056
3057 my $bisect_start_file = "$builddir/.git/BISECT_START";
3058
3059 my $check = $bisect_check;
3060 my $do_check = defined($check) && $check ne "0";
3061
3062 if ( -f $bisect_start_file ) {
3063 print "Bisect in progress found\n";
3064 if ($do_check) {
3065 print " If you say yes, then no checks of good or bad will be done\n";
3066 }
3067 if (defined($replay)) {
3068 print "** BISECT_REPLAY is defined in config file **";
3069 print " Ignore config option and perform new git bisect log?\n";
3070 if (read_ync " (yes, no, or cancel) ") {
3071 $replay = update_bisect_replay;
3072 $do_check = 0;
3073 }
3074 } elsif (read_yn "read git log and continue?") {
3075 $replay = update_bisect_replay;
3076 $do_check = 0;
3077 }
3078 }
3079
3080 if ($do_check) {
3081
3082 my $head = get_sha1("HEAD");
3083
3084 if ($check ne "good") {
3085 doprint "TESTING BISECT BAD [$bad]\n";
3086 run_command "git checkout $bad" or
3087 dodie "Failed to checkout $bad";
3088
3089 $result = run_bisect $type;
3090
3091 if ($result ne "bad") {
3092 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
3093 }
3094 }
3095
3096 if ($check ne "bad") {
3097 doprint "TESTING BISECT GOOD [$good]\n";
3098 run_command "git checkout $good" or
3099 dodie "Failed to checkout $good";
3100
3101 $result = run_bisect $type;
3102
3103 if ($result ne "good") {
3104 fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
3105 }
3106 }
3107
3108
3109 run_command "git checkout $head" or
3110 dodie "Failed to checkout $head";
3111 }
3112
3113 run_command "git bisect start$start_files" or
3114 dodie "could not start bisect";
3115
3116 if (defined($replay)) {
3117 run_command "git bisect replay $replay" or
3118 dodie "failed to run replay";
3119 } else {
3120 run_command "git bisect good $good" or
3121 dodie "could not set bisect good to $good";
3122
3123 run_git_bisect "git bisect bad $bad" or
3124 dodie "could not set bisect bad to $bad";
3125 }
3126
3127 if (defined($start)) {
3128 run_command "git checkout $start" or
3129 dodie "failed to checkout $start";
3130 }
3131
3132 my $test;
3133 do {
3134 $result = run_bisect $type;
3135 $test = run_git_bisect "git bisect $result";
3136 print_times;
3137 } while ($test);
3138
3139 run_command "git bisect log" or
3140 dodie "could not capture git bisect log";
3141
3142 run_command "git bisect reset" or
3143 dodie "could not reset git bisect";
3144
3145 doprint "Bad commit was [$bisect_bad_commit]\n";
3146
3147 success $i;
3148 }
3149
3150 sub assign_configs {
3151 my ($hash, $config) = @_;
3152
3153 doprint "Reading configs from $config\n";
3154
3155 open (IN, $config) or
3156 dodie "Failed to read $config";
3157
3158 while (<IN>) {
3159 chomp;
3160 if (/^((CONFIG\S*)=.*)/) {
3161 ${$hash}{$2} = $1;
3162 } elsif (/^(
3163 ${$hash}{$2} = $1;
3164 }
3165 }
3166
3167 close(IN);
3168 }
3169
3170 sub process_config_ignore {
3171 my ($config) = @_;
3172
3173 assign_configs \%config_ignore, $config;
3174 }
3175
3176 sub get_dependencies {
3177 my ($config) = @_;
3178
3179 my $arr = $dependency{$config};
3180 if (!defined($arr)) {
3181 return ();
3182 }
3183
3184 my @deps = @{$arr};
3185
3186 foreach my $dep (@{$arr}) {
3187 print "ADD DEP $dep\n";
3188 @deps = (@deps, get_dependencies $dep);
3189 }
3190
3191 return @deps;
3192 }
3193
3194 sub save_config {
3195 my ($pc, $file) = @_;
3196
3197 my %configs = %{$pc};
3198
3199 doprint "Saving configs into $file\n";
3200
3201 open(OUT, ">$file") or dodie "Can not write to $file";
3202
3203 foreach my $config (keys %configs) {
3204 print OUT "$configs{$config}\n";
3205 }
3206 close(OUT);
3207 }
3208
3209 sub create_config {
3210 my ($name, $pc) = @_;
3211
3212 doprint "Creating old config from $name configs\n";
3213
3214 save_config $pc, $output_config;
3215
3216 make_oldconfig;
3217 }
3218
3219 sub run_config_bisect_test {
3220 my ($type) = @_;
3221
3222 my $ret = run_bisect_test $type, "oldconfig";
3223
3224 if ($bisect_manual) {
3225 $ret = answer_bisect;
3226 }
3227
3228 return $ret;
3229 }
3230
3231 sub config_bisect_end {
3232 my ($good, $bad) = @_;
3233 my $diffexec = "diff -u";
3234
3235 if (-f "$builddir/scripts/diffconfig") {
3236 $diffexec = "$builddir/scripts/diffconfig";
3237 }
3238 doprint "\n\n***************************************\n";
3239 doprint "No more config bisecting possible.\n";
3240 run_command "$diffexec $good $bad", 1;
3241 doprint "***************************************\n\n";
3242 }
3243
3244 sub run_config_bisect {
3245 my ($good, $bad, $last_result) = @_;
3246 my $reset = "";
3247 my $cmd;
3248 my $ret;
3249
3250 if (!length($last_result)) {
3251 $reset = "-r";
3252 }
3253 run_command "$config_bisect_exec $reset -b $outputdir $good $bad $last_result", 1;
3254
3255
3256
3257
3258
3259
3260 if ($run_command_status) {
3261 return $run_command_status;
3262 }
3263
3264 $ret = run_config_bisect_test $config_bisect_type;
3265 if ($ret) {
3266 doprint "NEW GOOD CONFIG ($pass)\n";
3267 system("cp $output_config $tmpdir/good_config.tmp.$pass");
3268 $pass++;
3269
3270 return 3;
3271 } else {
3272 doprint "NEW BAD CONFIG ($pass)\n";
3273 system("cp $output_config $tmpdir/bad_config.tmp.$pass");
3274 $pass++;
3275
3276 return 4;
3277 }
3278 }
3279
3280 sub config_bisect {
3281 my ($i) = @_;
3282
3283 my $good_config;
3284 my $bad_config;
3285
3286 my $type = $config_bisect_type;
3287 my $ret;
3288
3289 $bad_config = $config_bisect;
3290
3291 if (defined($config_bisect_good)) {
3292 $good_config = $config_bisect_good;
3293 } elsif (defined($minconfig)) {
3294 $good_config = $minconfig;
3295 } else {
3296 doprint "No config specified, checking if defconfig works";
3297 $ret = run_bisect_test $type, "defconfig";
3298 if (!$ret) {
3299 fail "Have no good config to compare with, please set CONFIG_BISECT_GOOD";
3300 return 1;
3301 }
3302 $good_config = $output_config;
3303 }
3304
3305 if (!defined($config_bisect_exec)) {
3306
3307 my @locations = (
3308 "$pwd/config-bisect.pl",
3309 "$dirname/config-bisect.pl",
3310 "$builddir/tools/testing/ktest/config-bisect.pl",
3311 undef );
3312 foreach my $loc (@locations) {
3313 doprint "loc = $loc\n";
3314 $config_bisect_exec = $loc;
3315 last if (defined($config_bisect_exec && -x $config_bisect_exec));
3316 }
3317 if (!defined($config_bisect_exec)) {
3318 fail "Could not find an executable config-bisect.pl\n",
3319 " Set CONFIG_BISECT_EXEC to point to config-bisect.pl";
3320 return 1;
3321 }
3322 }
3323
3324
3325 doprint "Disabling 'MIN_CONFIG' for this test\n";
3326 undef $minconfig;
3327
3328 my %good_configs;
3329 my %bad_configs;
3330 my %tmp_configs;
3331
3332 if (-f "$tmpdir/good_config.tmp" || -f "$tmpdir/bad_config.tmp") {
3333 if (read_yn "Interrupted config-bisect. Continue (n - will start new)?") {
3334 if (-f "$tmpdir/good_config.tmp") {
3335 $good_config = "$tmpdir/good_config.tmp";
3336 } else {
3337 $good_config = "$tmpdir/good_config";
3338 }
3339 if (-f "$tmpdir/bad_config.tmp") {
3340 $bad_config = "$tmpdir/bad_config.tmp";
3341 } else {
3342 $bad_config = "$tmpdir/bad_config";
3343 }
3344 }
3345 }
3346 doprint "Run good configs through make oldconfig\n";
3347 assign_configs \%tmp_configs, $good_config;
3348 create_config "$good_config", \%tmp_configs;
3349 $good_config = "$tmpdir/good_config";
3350 system("cp $output_config $good_config") == 0 or dodie "cp good config";
3351
3352 doprint "Run bad configs through make oldconfig\n";
3353 assign_configs \%tmp_configs, $bad_config;
3354 create_config "$bad_config", \%tmp_configs;
3355 $bad_config = "$tmpdir/bad_config";
3356 system("cp $output_config $bad_config") == 0 or dodie "cp bad config";
3357
3358 if (defined($config_bisect_check) && $config_bisect_check ne "0") {
3359 if ($config_bisect_check ne "good") {
3360 doprint "Testing bad config\n";
3361
3362 $ret = run_bisect_test $type, "useconfig:$bad_config";
3363 if ($ret) {
3364 fail "Bad config succeeded when expected to fail!";
3365 return 0;
3366 }
3367 }
3368 if ($config_bisect_check ne "bad") {
3369 doprint "Testing good config\n";
3370
3371 $ret = run_bisect_test $type, "useconfig:$good_config";
3372 if (!$ret) {
3373 fail "Good config failed when expected to succeed!";
3374 return 0;
3375 }
3376 }
3377 }
3378
3379 my $last_run = "";
3380
3381 do {
3382 $ret = run_config_bisect $good_config, $bad_config, $last_run;
3383 if ($ret == 3) {
3384 $last_run = "good";
3385 } elsif ($ret == 4) {
3386 $last_run = "bad";
3387 }
3388 print_times;
3389 } while ($ret == 3 || $ret == 4);
3390
3391 if ($ret == 2) {
3392 config_bisect_end "$good_config.tmp", "$bad_config.tmp";
3393 }
3394
3395 return $ret if ($ret < 0);
3396
3397 success $i;
3398 }
3399
3400 sub patchcheck_reboot {
3401 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
3402 reboot_to_good $patchcheck_sleep_time;
3403 }
3404
3405 sub patchcheck {
3406 my ($i) = @_;
3407
3408 dodie "PATCHCHECK_START[$i] not defined\n"
3409 if (!defined($patchcheck_start));
3410 dodie "PATCHCHECK_TYPE[$i] not defined\n"
3411 if (!defined($patchcheck_type));
3412
3413 my $start = $patchcheck_start;
3414
3415 my $cherry = $patchcheck_cherry;
3416 if (!defined($cherry)) {
3417 $cherry = 0;
3418 }
3419
3420 my $end = "HEAD";
3421 if (defined($patchcheck_end)) {
3422 $end = $patchcheck_end;
3423 } elsif ($cherry) {
3424 dodie "PATCHCHECK_END must be defined with PATCHCHECK_CHERRY\n";
3425 }
3426
3427
3428 $start = get_sha1($start);
3429 $end = get_sha1($end);
3430
3431 my $type = $patchcheck_type;
3432
3433
3434 if ($type eq "test" && !defined($run_test)) {
3435 $type = "boot";
3436 }
3437
3438 if ($cherry) {
3439 open (IN, "git cherry -v $start $end|") or
3440 dodie "could not get git list";
3441 } else {
3442 open (IN, "git log --pretty=oneline $end|") or
3443 dodie "could not get git list";
3444 }
3445
3446 my @list;
3447
3448 while (<IN>) {
3449 chomp;
3450
3451 s/^\+ //;
3452 $list[$#list+1] = $_;
3453 last if (/^$start/);
3454 }
3455 close(IN);
3456
3457 if (!$cherry) {
3458 if ($list[$#list] !~ /^$start/) {
3459 fail "SHA1 $start not found";
3460 }
3461
3462
3463 @list = reverse @list;
3464 }
3465
3466 doprint("Going to test the following commits:\n");
3467 foreach my $l (@list) {
3468 doprint "$l\n";
3469 }
3470
3471 my $save_clean = $noclean;
3472 my %ignored_warnings;
3473
3474 if (defined($ignore_warnings)) {
3475 foreach my $sha1 (split /\s+/, $ignore_warnings) {
3476 $ignored_warnings{$sha1} = 1;
3477 }
3478 }
3479
3480 $in_patchcheck = 1;
3481 foreach my $item (@list) {
3482 my $sha1 = $item;
3483 $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
3484
3485 doprint "\nProcessing commit \"$item\"\n\n";
3486
3487 run_command "git checkout $sha1" or
3488 dodie "Failed to checkout $sha1";
3489
3490
3491 if ($item eq $list[0] ||
3492 $item eq $list[$#list]) {
3493 $noclean = $save_clean;
3494 } else {
3495 $noclean = 1;
3496 }
3497
3498 if (defined($minconfig)) {
3499 build "useconfig:$minconfig" or return 0;
3500 } else {
3501
3502 build "oldconfig" or return 0;
3503 }
3504
3505
3506 if (!defined($warnings_file) && !defined($ignored_warnings{$sha1})) {
3507 check_patch_buildlog $sha1 or return 0;
3508 }
3509
3510 check_buildlog or return 0;
3511
3512 next if ($type eq "build");
3513
3514 my $failed = 0;
3515
3516 start_monitor_and_install or $failed = 1;
3517
3518 if (!$failed && $type ne "boot"){
3519 do_run_test or $failed = 1;
3520 }
3521 end_monitor;
3522 if ($failed) {
3523 print_times;
3524 return 0;
3525 }
3526 patchcheck_reboot;
3527 print_times;
3528 }
3529 $in_patchcheck = 0;
3530 success $i;
3531
3532 return 1;
3533 }
3534
3535 sub add_dep {
3536
3537 my ($config, $dep) = @_;
3538
3539 if (defined($depends{$config})) {
3540 $depends{$config} .= " " . $dep;
3541 } else {
3542 $depends{$config} = $dep;
3543 }
3544
3545
3546 if (defined $depcount{$dep}) {
3547 $depcount{$dep}++;
3548 } else {
3549 $depcount{$dep} = 1;
3550 }
3551 }
3552
3553
3554 sub read_kconfig {
3555 my ($kconfig) = @_;
3556
3557 my $state = "NONE";
3558 my $config;
3559 my @kconfigs;
3560
3561 my $cont = 0;
3562 my $line;
3563
3564 if (! -f $kconfig) {
3565 doprint "file $kconfig does not exist, skipping\n";
3566 return;
3567 }
3568
3569 open(KIN, "$kconfig")
3570 or dodie "Can't open $kconfig";
3571 while (<KIN>) {
3572 chomp;
3573
3574
3575 if ($cont) {
3576 $_ = $line . " " . $_;
3577 }
3578
3579 if (s/\\$//) {
3580 $cont = 1;
3581 $line = $_;
3582 next;
3583 }
3584
3585 $cont = 0;
3586
3587
3588 if (/^source\s*"(.*)"/) {
3589 $kconfigs[$#kconfigs+1] = $1;
3590 }
3591
3592
3593 if (/^\s*(menu)?config\s+(\S+)\s*$/) {
3594 $state = "NEW";
3595 $config = $2;
3596
3597 for (my $i = 0; $i < $iflevel; $i++) {
3598 add_dep $config, $ifdeps[$i];
3599 }
3600
3601
3602 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
3603
3604 add_dep $config, $1;
3605
3606
3607 } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
3608
3609
3610 add_dep $1, $config;
3611
3612
3613 } elsif (/^if\s+(.*\S)\s*$/) {
3614 my $deps = $1;
3615
3616 $deps =~ s/^[^a-zA-Z0-9_]*//;
3617 $deps =~ s/[^a-zA-Z0-9_]*$//;
3618
3619 my @deps = split /[^a-zA-Z0-9_]+/, $deps;
3620
3621 $ifdeps[$iflevel++] = join ':', @deps;
3622
3623 } elsif (/^endif/) {
3624
3625 $iflevel-- if ($iflevel);
3626
3627
3628 } elsif (/^\s*help\s*$/) {
3629 $state = "NONE";
3630 }
3631 }
3632 close(KIN);
3633
3634
3635 foreach $kconfig (@kconfigs) {
3636 if (!defined($read_kconfigs{$kconfig})) {
3637 $read_kconfigs{$kconfig} = 1;
3638 read_kconfig("$builddir/$kconfig");
3639 }
3640 }
3641 }
3642
3643 sub read_depends {
3644
3645 open (IN, $output_config) or
3646 dodie "Failed to read $output_config";
3647 my $arch;
3648 while (<IN>) {
3649 if () {
3650 $arch = $1;
3651 last;
3652 }
3653 }
3654 close IN;
3655
3656 if (!defined($arch)) {
3657 doprint "Could not find arch from config file\n";
3658 doprint "no dependencies used\n";
3659 return;
3660 }
3661
3662
3663
3664 if ($arch eq "i386" || $arch eq "x86_64") {
3665 $arch = "x86";
3666 }
3667
3668 my $kconfig = "$builddir/arch/$arch/Kconfig";
3669
3670 if (! -f $kconfig && $arch =~ /\d$/) {
3671 my $orig = $arch;
3672
3673 $arch =~ s/\d*$//;
3674 $kconfig = "$builddir/arch/$arch/Kconfig";
3675 if (! -f $kconfig) {
3676 doprint "No idea what arch dir $orig is for\n";
3677 doprint "no dependencies used\n";
3678 return;
3679 }
3680 }
3681
3682 read_kconfig($kconfig);
3683 }
3684
3685 sub make_new_config {
3686 my @configs = @_;
3687
3688 open (OUT, ">$output_config")
3689 or dodie "Failed to write $output_config";
3690
3691 foreach my $config (@configs) {
3692 print OUT "$config\n";
3693 }
3694 close OUT;
3695 }
3696
3697 sub chomp_config {
3698 my ($config) = @_;
3699
3700 $config =~ s/CONFIG_//;
3701
3702 return $config;
3703 }
3704
3705 sub get_depends {
3706 my ($dep) = @_;
3707
3708 my $kconfig = chomp_config $dep;
3709
3710 $dep = $depends{"$kconfig"};
3711
3712
3713
3714
3715
3716 my $valid = "A-Za-z_0-9";
3717
3718 my @configs;
3719
3720 while ($dep =~ /[$valid]/) {
3721 if ($dep =~ /^[^$valid]*([$valid]+)/) {
3722 my $conf = "CONFIG_" . $1;
3723
3724 $configs[$#configs + 1] = $conf;
3725
3726 $dep =~ s/^[^$valid]*[$valid]+//;
3727 } else {
3728 dodie "this should never happen";
3729 }
3730 }
3731
3732 return @configs;
3733 }
3734
3735 sub test_this_config {
3736 my ($config) = @_;
3737
3738 my $found;
3739
3740
3741 if (defined($processed_configs{$config})) {
3742 return undef;
3743 }
3744 $processed_configs{$config} = 1;
3745
3746
3747 if (defined($nochange_config{$config})) {
3748 return undef;
3749 }
3750
3751 my $kconfig = chomp_config $config;
3752
3753
3754 if (defined($depends{"$kconfig"})) {
3755 my @parents = get_depends $config;
3756 foreach my $parent (@parents) {
3757
3758 next if (!defined($min_configs{$parent}));
3759 $found = test_this_config($parent);
3760 if (defined($found)) {
3761 return $found;
3762 }
3763 }
3764 }
3765
3766
3767
3768
3769
3770 my %configs = %min_configs;
3771 delete $configs{$config};
3772 make_new_config ((values %configs), (values %keep_configs));
3773 make_oldconfig;
3774 undef %configs;
3775 assign_configs \%configs, $output_config;
3776
3777 if (!defined($configs{$config}) || $configs{$config} =~ /^
3778 return $config;
3779 }
3780
3781 doprint "disabling config $config did not change .config\n";
3782
3783 $nochange_config{$config} = 1;
3784
3785 return undef;
3786 }
3787
3788 sub make_min_config {
3789 my ($i) = @_;
3790
3791 my $type = $minconfig_type;
3792 if ($type ne "boot" && $type ne "test") {
3793 fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" .
3794 " make_min_config works only with 'boot' and 'test'\n" and return;
3795 }
3796
3797 if (!defined($output_minconfig)) {
3798 fail "OUTPUT_MIN_CONFIG not defined" and return;
3799 }
3800
3801
3802
3803
3804 if (-f $output_minconfig && !$start_minconfig_defined) {
3805 print "$output_minconfig exists\n";
3806 if (!defined($use_output_minconfig)) {
3807 if (read_yn " Use it as minconfig?") {
3808 $start_minconfig = $output_minconfig;
3809 }
3810 } elsif ($use_output_minconfig > 0) {
3811 doprint "Using $output_minconfig as MIN_CONFIG\n";
3812 $start_minconfig = $output_minconfig;
3813 } else {
3814 doprint "Set to still use MIN_CONFIG as starting point\n";
3815 }
3816 }
3817
3818 if (!defined($start_minconfig)) {
3819 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
3820 }
3821
3822 my $temp_config = "$tmpdir/temp_config";
3823
3824
3825
3826
3827
3828 my $save_minconfig = $minconfig;
3829 undef $minconfig;
3830
3831 run_command "$make allnoconfig" or return 0;
3832
3833 read_depends;
3834
3835 process_config_ignore $output_config;
3836
3837 undef %save_configs;
3838 undef %min_configs;
3839
3840 if (defined($ignore_config)) {
3841
3842 `touch $ignore_config`;
3843 assign_configs \%save_configs, $ignore_config;
3844 }
3845
3846 %keep_configs = %save_configs;
3847
3848 doprint "Load initial configs from $start_minconfig\n";
3849
3850
3851
3852 assign_configs \%min_configs, $start_minconfig;
3853
3854 my @config_keys = keys %min_configs;
3855
3856
3857 foreach my $config (@config_keys) {
3858 my $kconfig = chomp_config $config;
3859 if (!defined $depcount{$kconfig}) {
3860 $depcount{$kconfig} = 0;
3861 }
3862 }
3863
3864
3865
3866 foreach my $config (@config_keys) {
3867
3868 if (defined($keep_configs{$config})) {
3869 my $file = $ignore_config;
3870 $file =~ s,.*/(.*?)$,$1,;
3871 doprint "$config set by $file ... ignored\n";
3872 delete $min_configs{$config};
3873 next;
3874 }
3875
3876
3877
3878
3879 if (defined($config_ignore{$config})) {
3880 if ($config_ignore{$config} ne $min_configs{$config}) {
3881 doprint "$config is in allnoconfig as '$config_ignore{$config}'";
3882 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
3883 $keep_configs{$config} = $min_configs{$config};
3884 } else {
3885 doprint "$config set by allnoconfig ... ignored\n";
3886 }
3887 delete $min_configs{$config};
3888 }
3889 }
3890
3891 my $done = 0;
3892 my $take_two = 0;
3893
3894 while (!$done) {
3895 my $config;
3896 my $found;
3897
3898
3899
3900
3901 my @test_configs = keys %min_configs;
3902
3903
3904 @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
3905 @test_configs ;
3906
3907
3908 my $reset = 1;
3909 for (my $i = 0; $i < $#test_configs; $i++) {
3910 if (!defined($nochange_config{$test_configs[0]})) {
3911 $reset = 0;
3912 last;
3913 }
3914
3915
3916 my $config = shift @test_configs;
3917 push @test_configs, $config;
3918 }
3919
3920
3921
3922 if ($reset) {
3923 undef %nochange_config;
3924 }
3925
3926 undef %processed_configs;
3927
3928 foreach my $config (@test_configs) {
3929
3930 $found = test_this_config $config;
3931
3932 last if (defined($found));
3933
3934
3935 }
3936
3937 if (!defined($found)) {
3938
3939
3940 if (!$take_two) {
3941 undef %nochange_config;
3942 $take_two = 1;
3943 next;
3944 }
3945 doprint "No more configs found that we can disable\n";
3946 $done = 1;
3947 last;
3948 }
3949 $take_two = 0;
3950
3951 $config = $found;
3952
3953 doprint "Test with $config disabled\n";
3954
3955
3956 $in_bisect = 1;
3957
3958 my $failed = 0;
3959 build "oldconfig" or $failed = 1;
3960 if (!$failed) {
3961 start_monitor_and_install or $failed = 1;
3962
3963 if ($type eq "test" && !$failed) {
3964 do_run_test or $failed = 1;
3965 }
3966
3967 end_monitor;
3968 }
3969
3970 $in_bisect = 0;
3971
3972 if ($failed) {
3973 doprint "$min_configs{$config} is needed to boot the box... keeping\n";
3974
3975 $keep_configs{$config} = $min_configs{$config};
3976 $save_configs{$config} = $min_configs{$config};
3977 delete $min_configs{$config};
3978
3979
3980 if (defined($ignore_config)) {
3981 open (OUT, ">$temp_config") or
3982 dodie "Can't write to $temp_config";
3983 foreach my $config (keys %save_configs) {
3984 print OUT "$save_configs{$config}\n";
3985 }
3986 close OUT;
3987 run_command "mv $temp_config $ignore_config" or
3988 dodie "failed to copy update to $ignore_config";
3989 }
3990
3991 } else {
3992
3993 doprint "$config is not needed, disabling\n";
3994
3995 delete $min_configs{$config};
3996
3997
3998 my %configs;
3999 assign_configs \%configs, $output_config;
4000 my @config_keys = keys %min_configs;
4001 foreach my $config (@config_keys) {
4002 if (!defined($configs{$config})) {
4003 doprint "$config is not set, disabling\n";
4004 delete $min_configs{$config};
4005 }
4006 }
4007
4008
4009 open (OUT, ">$temp_config") or
4010 dodie "Can't write to $temp_config";
4011 foreach my $config (keys %keep_configs) {
4012 print OUT "$keep_configs{$config}\n";
4013 }
4014 foreach my $config (keys %min_configs) {
4015 print OUT "$min_configs{$config}\n";
4016 }
4017 close OUT;
4018
4019 run_command "mv $temp_config $output_minconfig" or
4020 dodie "failed to copy update to $output_minconfig";
4021 }
4022
4023 doprint "Reboot and wait $sleep_time seconds\n";
4024 reboot_to_good $sleep_time;
4025 }
4026
4027 success $i;
4028 return 1;
4029 }
4030
4031 sub make_warnings_file {
4032 my ($i) = @_;
4033
4034 if (!defined($warnings_file)) {
4035 dodie "Must define WARNINGS_FILE for make_warnings_file test";
4036 }
4037
4038 if ($build_type eq "nobuild") {
4039 dodie "BUILD_TYPE can not be 'nobuild' for make_warnings_file test";
4040 }
4041
4042 build $build_type or dodie "Failed to build";
4043
4044 open(OUT, ">$warnings_file") or dodie "Can't create $warnings_file";
4045
4046 open(IN, $buildlog) or dodie "Can't open $buildlog";
4047 while (<IN>) {
4048
4049
4050 s/$utf8_quote/'/g;
4051
4052 if (/$check_build_re/) {
4053 print OUT;
4054 }
4055 }
4056 close(IN);
4057
4058 close(OUT);
4059
4060 success $i;
4061 }
4062
4063 sub option_defined {
4064 my ($option) = @_;
4065
4066 if (defined($opt{$option}) && $opt{$option} !~ /^\s*$/) {
4067 return 1;
4068 }
4069
4070 return 0;
4071 }
4072
4073 sub __set_test_option {
4074 my ($name, $i) = @_;
4075
4076 my $option = "$name\[$i\]";
4077
4078 if (option_defined($option)) {
4079 return $opt{$option};
4080 }
4081
4082 foreach my $test (keys %repeat_tests) {
4083 if ($i >= $test &&
4084 $i < $test + $repeat_tests{$test}) {
4085 $option = "$name\[$test\]";
4086 if (option_defined($option)) {
4087 return $opt{$option};
4088 }
4089 }
4090 }
4091
4092 if (option_defined($name)) {
4093 return $opt{$name};
4094 }
4095
4096 return undef;
4097 }
4098
4099 sub set_test_option {
4100 my ($name, $i) = @_;
4101
4102 my $option = __set_test_option($name, $i);
4103 return $option if (!defined($option));
4104
4105 return eval_option($name, $option, $i);
4106 }
4107
4108 sub find_mailer {
4109 my ($mailer) = @_;
4110
4111 my @paths = split /:/, $ENV{PATH};
4112
4113
4114 $paths[$#paths + 1] = "/usr/sbin";
4115
4116 foreach my $path (@paths) {
4117 if (-x "$path/$mailer") {
4118 return $path;
4119 }
4120 }
4121
4122 return undef;
4123 }
4124
4125 sub do_send_mail {
4126 my ($subject, $message, $file) = @_;
4127
4128 if (!defined($mail_path)) {
4129
4130 $mail_path = find_mailer $mailer;
4131 if (!defined($mail_path)) {
4132 die "\nCan not find $mailer in PATH\n";
4133 }
4134 }
4135
4136 my $header_file = "$tmpdir/header";
4137 open (HEAD, ">$header_file") or die "Can not create $header_file\n";
4138 print HEAD "To: $mailto\n";
4139 print HEAD "Subject: $subject\n\n";
4140 print HEAD "$message\n";
4141 close HEAD;
4142
4143 if (!defined($mail_command)) {
4144 if ($mailer eq "mail" || $mailer eq "mailx") {
4145 $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO";
4146 } elsif ($mailer eq "sendmail" ) {
4147 $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -t \$MAILTO";
4148 } else {
4149 die "\nYour mailer: $mailer is not supported.\n";
4150 }
4151 }
4152
4153 if (defined($file)) {
4154 $mail_command =~ s/\$BODY_FILE/$file/g;
4155 } else {
4156 $mail_command =~ s/\$BODY_FILE//g;
4157 }
4158
4159 $mail_command =~ s/\$HEADER_FILE/$header_file/g;
4160 $mail_command =~ s/\$MAILER/$mailer/g;
4161 $mail_command =~ s/\$MAIL_PATH/$mail_path/g;
4162 $mail_command =~ s/\$MAILTO/$mailto/g;
4163 $mail_command =~ s/\$SUBJECT/$subject/g;
4164 $mail_command =~ s/\$MESSAGE/$message/g;
4165
4166 my $ret = run_command $mail_command;
4167 if (!$ret && defined($file)) {
4168
4169 $message .= "\n\n*** FAILED TO SEND LOG ***\n\n";
4170 do_send_email($subject, $message);
4171 }
4172 }
4173
4174 sub send_email {
4175 if (defined($mailto)) {
4176 if (!defined($mailer)) {
4177 doprint "No email sent: email or mailer not specified in config.\n";
4178 return;
4179 }
4180 do_send_mail @_;
4181 }
4182 }
4183
4184 sub cancel_test {
4185 if ($email_when_canceled) {
4186 my $name = get_test_name;
4187 send_email("KTEST: Your [$name] test was cancelled",
4188 "Your test started at $script_start_time was cancelled: sig int");
4189 }
4190 die "\nCaught Sig Int, test interrupted: $!\n"
4191 }
4192
4193 $#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl [config-file]\n";
4194
4195 if ($#ARGV == 0) {
4196 $ktest_config = $ARGV[0];
4197 if (! -f $ktest_config) {
4198 print "$ktest_config does not exist.\n";
4199 if (!read_yn "Create it?") {
4200 exit 0;
4201 }
4202 }
4203 }
4204
4205 if (! -f $ktest_config) {
4206 $newconfig = 1;
4207 get_test_case;
4208 open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
4209 print OUT << "EOF"
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221 THIS_DIR := $variable{"PWD"}
4222
4223
4224
4225 TEST_START
4226 TEST_TYPE = $default{"TEST_TYPE"}
4227
4228 DEFAULTS
4229 EOF
4230 ;
4231 close(OUT);
4232 }
4233 read_config $ktest_config;
4234
4235 if (defined($opt{"LOG_FILE"})) {
4236 $opt{"LOG_FILE"} = eval_option("LOG_FILE", $opt{"LOG_FILE"}, -1);
4237 }
4238
4239
4240 my @new_configs = keys %entered_configs;
4241 if ($#new_configs >= 0) {
4242 print "\nAppending entered in configs to $ktest_config\n";
4243 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
4244 foreach my $config (@new_configs) {
4245 print OUT "$config = $entered_configs{$config}\n";
4246 $opt{$config} = process_variables($entered_configs{$config});
4247 }
4248 }
4249
4250 if (defined($opt{"LOG_FILE"})) {
4251 if ($opt{"CLEAR_LOG"}) {
4252 unlink $opt{"LOG_FILE"};
4253 }
4254 open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
4255 LOG->autoflush(1);
4256 }
4257
4258 doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
4259
4260 for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
4261
4262 if (!$i) {
4263 doprint "DEFAULT OPTIONS:\n";
4264 } else {
4265 doprint "\nTEST $i OPTIONS";
4266 if (defined($repeat_tests{$i})) {
4267 $repeat = $repeat_tests{$i};
4268 doprint " ITERATE $repeat";
4269 }
4270 doprint "\n";
4271 }
4272
4273 foreach my $option (sort keys %opt) {
4274 if ($option =~ /\[(\d+)\]$/) {
4275 next if ($i != $1);
4276 } else {
4277 next if ($i);
4278 }
4279
4280 doprint "$option = $opt{$option}\n";
4281 }
4282 }
4283
4284 $SIG{INT} = ;
4285
4286
4287 for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
4288
4289
4290 $no_reboot = 1;
4291 $reboot_success = 0;
4292
4293 $have_version = 0;
4294
4295 $iteration = $i;
4296
4297 $build_time = 0;
4298 $install_time = 0;
4299 $reboot_time = 0;
4300 $test_time = 0;
4301
4302 undef %force_config;
4303
4304 my $makecmd = set_test_option("MAKE_CMD", $i);
4305
4306 $outputdir = set_test_option("OUTPUT_DIR", $i);
4307 $builddir = set_test_option("BUILD_DIR", $i);
4308
4309 chdir $builddir || dodie "can't change directory to $builddir";
4310
4311 if (!-d $outputdir) {
4312 mkpath($outputdir) or
4313 dodie "can't create $outputdir";
4314 }
4315
4316 $make = "$makecmd O=$outputdir";
4317
4318
4319 foreach my $opt (keys %option_map) {
4320 ${$option_map{$opt}} = set_test_option($opt, $i);
4321 }
4322
4323 $start_minconfig_defined = 1;
4324
4325
4326 if ($i == 1) {
4327 if (defined($pre_ktest)) {
4328 doprint "\n";
4329 run_command $pre_ktest;
4330 }
4331 if ($email_when_started) {
4332 my $name = get_test_name;
4333 send_email("KTEST: Your [$name] test was started",
4334 "Your test was started on $script_start_time");
4335 }
4336 }
4337
4338
4339
4340 if (defined($post_ktest)) {
4341 $final_post_ktest = $post_ktest;
4342 }
4343
4344 if (!defined($start_minconfig)) {
4345 $start_minconfig_defined = 0;
4346 $start_minconfig = $minconfig;
4347 }
4348
4349 if (!-d $tmpdir) {
4350 mkpath($tmpdir) or
4351 dodie "can't create $tmpdir";
4352 }
4353
4354 $ENV{"SSH_USER"} = $ssh_user;
4355 $ENV{"MACHINE"} = $machine;
4356
4357 $buildlog = "$tmpdir/buildlog-$machine";
4358 $testlog = "$tmpdir/testlog-$machine";
4359 $dmesg = "$tmpdir/dmesg-$machine";
4360 $output_config = "$outputdir/.config";
4361
4362 if (!$buildonly) {
4363 $target = "$ssh_user\@$machine";
4364 if (($reboot_type eq "grub") or ($reboot_type eq "grub2bls")) {
4365 dodie "GRUB_MENU not defined" if (!defined($grub_menu));
4366 } elsif ($reboot_type eq "grub2") {
4367 dodie "GRUB_MENU not defined" if (!defined($grub_menu));
4368 dodie "GRUB_FILE not defined" if (!defined($grub_file));
4369 } elsif ($reboot_type eq "syslinux") {
4370 dodie "SYSLINUX_LABEL not defined" if (!defined($syslinux_label));
4371 }
4372 }
4373
4374 my $run_type = $build_type;
4375 if ($test_type eq "patchcheck") {
4376 $run_type = $patchcheck_type;
4377 } elsif ($test_type eq "bisect") {
4378 $run_type = $bisect_type;
4379 } elsif ($test_type eq "config_bisect") {
4380 $run_type = $config_bisect_type;
4381 } elsif ($test_type eq "make_min_config") {
4382 $run_type = "";
4383 } elsif ($test_type eq "make_warnings_file") {
4384 $run_type = "";
4385 }
4386
4387
4388 if (!defined($run_type)) {
4389 $run_type = "ERROR";
4390 }
4391
4392 my $installme = "";
4393 $installme = " no_install" if ($no_install);
4394
4395 my $name = "";
4396
4397 if (defined($test_name)) {
4398 $name = " ($test_name)";
4399 }
4400
4401 doprint "\n\n";
4402
4403 if (defined($opt{"LOG_FILE"})) {
4404 $test_log_start = tell(LOG);
4405 }
4406
4407 doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n";
4408
4409 if (defined($pre_test)) {
4410 my $ret = run_command $pre_test;
4411 if (!$ret && defined($pre_test_die) &&
4412 $pre_test_die) {
4413 dodie "failed to pre_test\n";
4414 }
4415 }
4416
4417 unlink $dmesg;
4418 unlink $buildlog;
4419 unlink $testlog;
4420
4421 if (defined($addconfig)) {
4422 my $min = $minconfig;
4423 if (!defined($minconfig)) {
4424 $min = "";
4425 }
4426 run_command "cat $addconfig $min > $tmpdir/add_config" or
4427 dodie "Failed to create temp config";
4428 $minconfig = "$tmpdir/add_config";
4429 }
4430
4431 if (defined($checkout)) {
4432 run_command "git checkout $checkout" or
4433 dodie "failed to checkout $checkout";
4434 }
4435
4436 $no_reboot = 0;
4437
4438
4439 if ($reboot_on_success) {
4440 $reboot_success = 1;
4441 }
4442
4443 if ($test_type eq "bisect") {
4444 bisect $i;
4445 next;
4446 } elsif ($test_type eq "config_bisect") {
4447 config_bisect $i;
4448 next;
4449 } elsif ($test_type eq "patchcheck") {
4450 patchcheck $i;
4451 next;
4452 } elsif ($test_type eq "make_min_config") {
4453 make_min_config $i;
4454 next;
4455 } elsif ($test_type eq "make_warnings_file") {
4456 $no_reboot = 1;
4457 make_warnings_file $i;
4458 next;
4459 }
4460
4461 if ($build_type ne "nobuild") {
4462 build $build_type or next;
4463 check_buildlog or next;
4464 }
4465
4466 if ($test_type eq "install") {
4467 get_version;
4468 install;
4469 success $i;
4470 next;
4471 }
4472
4473 if ($test_type ne "build") {
4474 my $failed = 0;
4475 start_monitor_and_install or $failed = 1;
4476
4477 if (!$failed && $test_type ne "boot" && defined($run_test)) {
4478 do_run_test or $failed = 1;
4479 }
4480 end_monitor;
4481 if ($failed) {
4482 print_times;
4483 next;
4484 }
4485 }
4486
4487 print_times;
4488
4489 success $i;
4490 }
4491
4492 if (defined($final_post_ktest)) {
4493
4494 my $cp_final_post_ktest = eval_kernel_version $final_post_ktest;
4495 run_command $cp_final_post_ktest;
4496 }
4497
4498 if ($opt{"POWEROFF_ON_SUCCESS"}) {
4499 halt;
4500 } elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) {
4501 reboot_to_good;
4502 } elsif (defined($switch_to_good)) {
4503
4504 run_command $switch_to_good;
4505 }
4506
4507 doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n";
4508
4509 if ($email_when_finished) {
4510 send_email("KTEST: Your test has finished!",
4511 "$successes of $opt{NUM_TESTS} tests started at $script_start_time were successful!");
4512 }
4513
4514 if (defined($opt{"LOG_FILE"})) {
4515 print "\n See $opt{LOG_FILE} for the record of results.\n\n";
4516 close LOG;
4517 }
4518
4519 exit 0;
4520
4521
4522
4523
4524
4525
4526
4527
4528