1#!/usr/bin/perl -w 2# SPDX-License-Identifier: GPL-2.0-only 3# 4# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. 5# 6 7use strict; 8use IPC::Open2; 9use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); 10use File::Path qw(mkpath); 11use File::Copy qw(cp); 12use FileHandle; 13use FindBin; 14use IO::Handle; 15 16my $VERSION = "0.2"; 17 18$| = 1; 19 20my %opt; 21my %repeat_tests; 22my %repeats; 23my %evals; 24my @command_vars; 25my %command_tmp_vars; 26 27#default opts 28my %default = ( 29 "MAILER" => "sendmail", # default mailer 30 "EMAIL_ON_ERROR" => 1, 31 "EMAIL_WHEN_FINISHED" => 1, 32 "EMAIL_WHEN_CANCELED" => 0, 33 "EMAIL_WHEN_STARTED" => 0, 34 "NUM_TESTS" => 1, 35 "TEST_TYPE" => "build", 36 "BUILD_TYPE" => "oldconfig", 37 "MAKE_CMD" => "make", 38 "CLOSE_CONSOLE_SIGNAL" => "INT", 39 "TIMEOUT" => 120, 40 "TMP_DIR" => "/tmp/ktest/\${MACHINE}", 41 "SLEEP_TIME" => 60, # sleep time between tests 42 "BUILD_NOCLEAN" => 0, 43 "REBOOT_ON_ERROR" => 0, 44 "POWEROFF_ON_ERROR" => 0, 45 "REBOOT_ON_SUCCESS" => 1, 46 "POWEROFF_ON_SUCCESS" => 0, 47 "BUILD_OPTIONS" => "", 48 "BISECT_SLEEP_TIME" => 60, # sleep time between bisects 49 "PATCHCHECK_SLEEP_TIME" => 60, # sleep time between patch checks 50 "CLEAR_LOG" => 0, 51 "BISECT_MANUAL" => 0, 52 "BISECT_SKIP" => 1, 53 "BISECT_TRIES" => 1, 54 "MIN_CONFIG_TYPE" => "boot", 55 "SUCCESS_LINE" => "login:", 56 "DETECT_TRIPLE_FAULT" => 1, 57 "NO_INSTALL" => 0, 58 "BOOTED_TIMEOUT" => 1, 59 "DIE_ON_FAILURE" => 1, 60 "SSH_EXEC" => "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND", 61 "SCP_TO_TARGET" => "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE", 62 "SCP_TO_TARGET_INSTALL" => "\${SCP_TO_TARGET}", 63 "REBOOT" => "ssh \$SSH_USER\@\$MACHINE reboot", 64 "REBOOT_RETURN_CODE" => 255, 65 "STOP_AFTER_SUCCESS" => 10, 66 "STOP_AFTER_FAILURE" => 60, 67 "STOP_TEST_AFTER" => 600, 68 "MAX_MONITOR_WAIT" => 1800, 69 "GRUB_REBOOT" => "grub2-reboot", 70 "GRUB_BLS_GET" => "grubby --info=ALL", 71 "SYSLINUX" => "extlinux", 72 "SYSLINUX_PATH" => "/boot/extlinux", 73 "CONNECT_TIMEOUT" => 25, 74 75# required, and we will ask users if they don't have them but we keep the default 76# value something that is common. 77 "REBOOT_TYPE" => "grub", 78 "LOCALVERSION" => "-test", 79 "SSH_USER" => "root", 80 "BUILD_TARGET" => "arch/x86/boot/bzImage", 81 "TARGET_IMAGE" => "/boot/vmlinuz-test", 82 83 "LOG_FILE" => undef, 84 "IGNORE_UNUSED" => 0, 85); 86 87my $test_log_start = 0; 88my $dry_run = 0; 89 90my $ktest_config = "ktest.conf"; 91my $version; 92my $have_version = 0; 93my $machine; 94my $last_machine; 95my $ssh_user; 96my $tmpdir; 97my $builddir; 98my $outputdir; 99my $output_config; 100my $test_type; 101my $build_type; 102my $build_options; 103my $final_post_ktest; 104my $post_ktest_done = 0; 105my $pre_ktest; 106my $pre_ktest_die; 107my $post_ktest; 108my $pre_test; 109my $pre_test_die; 110my $post_test; 111my $pre_build; 112my $post_build; 113my $pre_build_die; 114my $post_build_die; 115my $reboot_type; 116my $reboot_script; 117my $power_cycle; 118my $reboot; 119my $reboot_return_code; 120my $reboot_on_error; 121my $switch_to_good; 122my $switch_to_test; 123my $poweroff_on_error; 124my $reboot_on_success; 125my $die_on_failure; 126my $powercycle_after_reboot; 127my $poweroff_after_halt; 128my $max_monitor_wait; 129my $ssh_exec; 130my $scp_to_target; 131my $scp_to_target_install; 132my $power_off; 133my $grub_menu; 134my $last_grub_menu; 135my $grub_file; 136my $grub_number; 137my $grub_reboot; 138my $grub_bls_get; 139my $syslinux; 140my $syslinux_path; 141my $syslinux_label; 142my $target; 143my $make; 144my $pre_install; 145my $post_install; 146my $no_install; 147my $noclean; 148my $minconfig; 149my $start_minconfig; 150my $start_minconfig_defined; 151my $output_minconfig; 152my $minconfig_type; 153my $use_output_minconfig; 154my $warnings_file; 155my $ignore_config; 156my $ignore_errors; 157my $addconfig; 158my $in_bisect = 0; 159my $bisect_bad_commit = ""; 160my $reverse_bisect; 161my $bisect_manual; 162my $bisect_skip; 163my $bisect_tries; 164my $config_bisect_good; 165my $bisect_ret_good; 166my $bisect_ret_bad; 167my $bisect_ret_skip; 168my $bisect_ret_abort; 169my $bisect_ret_default; 170my $in_patchcheck = 0; 171my $run_test; 172my $buildlog; 173my $testlog; 174my $dmesg; 175my $monitor_fp; 176my $monitor_pid; 177my $monitor_cnt = 0; 178my $sleep_time; 179my $bisect_sleep_time; 180my $patchcheck_sleep_time; 181my $ignore_warnings; 182my $store_failures; 183my $store_successes; 184my $test_name; 185my $timeout; 186my $run_timeout; 187my $connect_timeout; 188my $config_bisect_exec; 189my $booted_timeout; 190my $detect_triplefault; 191my $console; 192my $close_console_signal; 193my $reboot_success_line; 194my $success_line; 195my $stop_after_success; 196my $stop_after_failure; 197my $stop_test_after; 198my $build_target; 199my $target_image; 200my $checkout; 201my $localversion; 202my $iteration = 0; 203my $successes = 0; 204my $stty_orig; 205my $run_command_status = 0; 206 207my $bisect_good; 208my $bisect_bad; 209my $bisect_type; 210my $bisect_start; 211my $bisect_replay; 212my $bisect_files; 213my $bisect_reverse; 214my $bisect_check; 215 216my $config_bisect; 217my $config_bisect_type; 218my $config_bisect_check; 219 220my $patchcheck_type; 221my $patchcheck_start; 222my $patchcheck_cherry; 223my $patchcheck_end; 224my $patchcheck_skip; 225 226my $build_time; 227my $install_time; 228my $reboot_time; 229my $test_time; 230 231my $warning_found = 0; 232 233my $pwd; 234my $dirname = $FindBin::Bin; 235 236my $mailto; 237my $mailer; 238my $mail_path; 239my $mail_max_size; 240my $mail_command; 241my $email_on_error; 242my $email_when_finished; 243my $email_when_started; 244my $email_when_canceled; 245 246my $script_start_time = localtime(); 247 248# set when a test is something other that just building or install 249# which would require more options. 250my $buildonly = 1; 251 252# tell build not to worry about warnings, even when WARNINGS_FILE is set 253my $warnings_ok = 0; 254 255# set when creating a new config 256my $newconfig = 0; 257 258my %entered_configs; 259my %config_help; 260my %variable; 261 262# force_config is the list of configs that we force enabled (or disabled) 263# in a .config file. The MIN_CONFIG and ADD_CONFIG configs. 264my %force_config; 265 266# do not force reboots on config problems 267my $no_reboot = 1; 268 269# reboot on success 270my $reboot_success = 0; 271 272my %option_map = ( 273 "MAILTO" => \$mailto, 274 "MAILER" => \$mailer, 275 "MAIL_PATH" => \$mail_path, 276 "MAIL_MAX_SIZE" => \$mail_max_size, 277 "MAIL_COMMAND" => \$mail_command, 278 "EMAIL_ON_ERROR" => \$email_on_error, 279 "EMAIL_WHEN_FINISHED" => \$email_when_finished, 280 "EMAIL_WHEN_STARTED" => \$email_when_started, 281 "EMAIL_WHEN_CANCELED" => \$email_when_canceled, 282 "MACHINE" => \$machine, 283 "SSH_USER" => \$ssh_user, 284 "TMP_DIR" => \$tmpdir, 285 "OUTPUT_DIR" => \$outputdir, 286 "BUILD_DIR" => \$builddir, 287 "TEST_TYPE" => \$test_type, 288 "PRE_KTEST" => \$pre_ktest, 289 "PRE_KTEST_DIE" => \$pre_ktest_die, 290 "POST_KTEST" => \$post_ktest, 291 "PRE_TEST" => \$pre_test, 292 "PRE_TEST_DIE" => \$pre_test_die, 293 "POST_TEST" => \$post_test, 294 "BUILD_TYPE" => \$build_type, 295 "BUILD_OPTIONS" => \$build_options, 296 "PRE_BUILD" => \$pre_build, 297 "POST_BUILD" => \$post_build, 298 "PRE_BUILD_DIE" => \$pre_build_die, 299 "POST_BUILD_DIE" => \$post_build_die, 300 "POWER_CYCLE" => \$power_cycle, 301 "REBOOT" => \$reboot, 302 "REBOOT_RETURN_CODE" => \$reboot_return_code, 303 "BUILD_NOCLEAN" => \$noclean, 304 "MIN_CONFIG" => \$minconfig, 305 "OUTPUT_MIN_CONFIG" => \$output_minconfig, 306 "START_MIN_CONFIG" => \$start_minconfig, 307 "MIN_CONFIG_TYPE" => \$minconfig_type, 308 "USE_OUTPUT_MIN_CONFIG" => \$use_output_minconfig, 309 "WARNINGS_FILE" => \$warnings_file, 310 "IGNORE_CONFIG" => \$ignore_config, 311 "TEST" => \$run_test, 312 "ADD_CONFIG" => \$addconfig, 313 "REBOOT_TYPE" => \$reboot_type, 314 "GRUB_MENU" => \$grub_menu, 315 "GRUB_FILE" => \$grub_file, 316 "GRUB_REBOOT" => \$grub_reboot, 317 "GRUB_BLS_GET" => \$grub_bls_get, 318 "SYSLINUX" => \$syslinux, 319 "SYSLINUX_PATH" => \$syslinux_path, 320 "SYSLINUX_LABEL" => \$syslinux_label, 321 "PRE_INSTALL" => \$pre_install, 322 "POST_INSTALL" => \$post_install, 323 "NO_INSTALL" => \$no_install, 324 "REBOOT_SCRIPT" => \$reboot_script, 325 "REBOOT_ON_ERROR" => \$reboot_on_error, 326 "SWITCH_TO_GOOD" => \$switch_to_good, 327 "SWITCH_TO_TEST" => \$switch_to_test, 328 "POWEROFF_ON_ERROR" => \$poweroff_on_error, 329 "REBOOT_ON_SUCCESS" => \$reboot_on_success, 330 "DIE_ON_FAILURE" => \$die_on_failure, 331 "POWER_OFF" => \$power_off, 332 "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot, 333 "POWEROFF_AFTER_HALT" => \$poweroff_after_halt, 334 "MAX_MONITOR_WAIT" => \$max_monitor_wait, 335 "SLEEP_TIME" => \$sleep_time, 336 "BISECT_SLEEP_TIME" => \$bisect_sleep_time, 337 "PATCHCHECK_SLEEP_TIME" => \$patchcheck_sleep_time, 338 "IGNORE_WARNINGS" => \$ignore_warnings, 339 "IGNORE_ERRORS" => \$ignore_errors, 340 "BISECT_MANUAL" => \$bisect_manual, 341 "BISECT_SKIP" => \$bisect_skip, 342 "BISECT_TRIES" => \$bisect_tries, 343 "CONFIG_BISECT_GOOD" => \$config_bisect_good, 344 "BISECT_RET_GOOD" => \$bisect_ret_good, 345 "BISECT_RET_BAD" => \$bisect_ret_bad, 346 "BISECT_RET_SKIP" => \$bisect_ret_skip, 347 "BISECT_RET_ABORT" => \$bisect_ret_abort, 348 "BISECT_RET_DEFAULT" => \$bisect_ret_default, 349 "STORE_FAILURES" => \$store_failures, 350 "STORE_SUCCESSES" => \$store_successes, 351 "TEST_NAME" => \$test_name, 352 "TIMEOUT" => \$timeout, 353 "RUN_TIMEOUT" => \$run_timeout, 354 "CONNECT_TIMEOUT" => \$connect_timeout, 355 "CONFIG_BISECT_EXEC" => \$config_bisect_exec, 356 "BOOTED_TIMEOUT" => \$booted_timeout, 357 "CONSOLE" => \$console, 358 "CLOSE_CONSOLE_SIGNAL" => \$close_console_signal, 359 "DETECT_TRIPLE_FAULT" => \$detect_triplefault, 360 "SUCCESS_LINE" => \$success_line, 361 "REBOOT_SUCCESS_LINE" => \$reboot_success_line, 362 "STOP_AFTER_SUCCESS" => \$stop_after_success, 363 "STOP_AFTER_FAILURE" => \$stop_after_failure, 364 "STOP_TEST_AFTER" => \$stop_test_after, 365 "BUILD_TARGET" => \$build_target, 366 "SSH_EXEC" => \$ssh_exec, 367 "SCP_TO_TARGET" => \$scp_to_target, 368 "SCP_TO_TARGET_INSTALL" => \$scp_to_target_install, 369 "CHECKOUT" => \$checkout, 370 "TARGET_IMAGE" => \$target_image, 371 "LOCALVERSION" => \$localversion, 372 373 "BISECT_GOOD" => \$bisect_good, 374 "BISECT_BAD" => \$bisect_bad, 375 "BISECT_TYPE" => \$bisect_type, 376 "BISECT_START" => \$bisect_start, 377 "BISECT_REPLAY" => \$bisect_replay, 378 "BISECT_FILES" => \$bisect_files, 379 "BISECT_REVERSE" => \$bisect_reverse, 380 "BISECT_CHECK" => \$bisect_check, 381 382 "CONFIG_BISECT" => \$config_bisect, 383 "CONFIG_BISECT_TYPE" => \$config_bisect_type, 384 "CONFIG_BISECT_CHECK" => \$config_bisect_check, 385 386 "PATCHCHECK_TYPE" => \$patchcheck_type, 387 "PATCHCHECK_START" => \$patchcheck_start, 388 "PATCHCHECK_CHERRY" => \$patchcheck_cherry, 389 "PATCHCHECK_END" => \$patchcheck_end, 390 "PATCHCHECK_SKIP" => \$patchcheck_skip, 391); 392 393# Options may be used by other options, record them. 394my %used_options; 395 396# default variables that can be used 397chomp ($variable{"PWD"} = `pwd`); 398$pwd = $variable{"PWD"}; 399 400$config_help{"MACHINE"} = << "EOF" 401 The machine hostname that you will test. 402 For build only tests, it is still needed to differentiate log files. 403EOF 404 ; 405$config_help{"SSH_USER"} = << "EOF" 406 The box is expected to have ssh on normal bootup, provide the user 407 (most likely root, since you need privileged operations) 408EOF 409 ; 410$config_help{"BUILD_DIR"} = << "EOF" 411 The directory that contains the Linux source code (full path). 412 You can use \${PWD} that will be the path where ktest.pl is run, or use 413 \${THIS_DIR} which is assigned \${PWD} but may be changed later. 414EOF 415 ; 416$config_help{"OUTPUT_DIR"} = << "EOF" 417 The directory that the objects will be built (full path). 418 (can not be same as BUILD_DIR) 419 You can use \${PWD} that will be the path where ktest.pl is run, or use 420 \${THIS_DIR} which is assigned \${PWD} but may be changed later. 421EOF 422 ; 423$config_help{"BUILD_TARGET"} = << "EOF" 424 The location of the compiled file to copy to the target. 425 (relative to OUTPUT_DIR) 426EOF 427 ; 428$config_help{"BUILD_OPTIONS"} = << "EOF" 429 Options to add to \"make\" when building. 430 i.e. -j20 431EOF 432 ; 433$config_help{"TARGET_IMAGE"} = << "EOF" 434 The place to put your image on the test machine. 435EOF 436 ; 437$config_help{"POWER_CYCLE"} = << "EOF" 438 A script or command to reboot the box. 439 440 Here is a digital loggers power switch example 441 POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL' 442 443 Here is an example to reboot a virtual box on the current host 444 with the name "Guest". 445 POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest 446EOF 447 ; 448$config_help{"CONSOLE"} = << "EOF" 449 The script or command that reads the console 450 451 If you use ttywatch server, something like the following would work. 452CONSOLE = nc -d localhost 3001 453 454 For a virtual machine with guest name "Guest". 455CONSOLE = virsh console Guest 456EOF 457 ; 458$config_help{"LOCALVERSION"} = << "EOF" 459 Required version ending to differentiate the test 460 from other linux builds on the system. 461EOF 462 ; 463$config_help{"REBOOT_TYPE"} = << "EOF" 464 Way to reboot the box to the test kernel. 465 Only valid options so far are "grub", "grub2", "grub2bls", "syslinux", and "script". 466 467 If you specify grub, it will assume grub version 1 468 and will search in /boot/grub/menu.lst for the title \$GRUB_MENU 469 and select that target to reboot to the kernel. If this is not 470 your setup, then specify "script" and have a command or script 471 specified in REBOOT_SCRIPT to boot to the target. 472 473 The entry in /boot/grub/menu.lst must be entered in manually. 474 The test will not modify that file. 475 476 If you specify grub2, then you also need to specify both \$GRUB_MENU 477 and \$GRUB_FILE. 478 479 If you specify grub2bls, then you also need to specify \$GRUB_MENU. 480 481 If you specify syslinux, then you may use SYSLINUX to define the syslinux 482 command (defaults to extlinux), and SYSLINUX_PATH to specify the path to 483 the syslinux install (defaults to /boot/extlinux). But you have to specify 484 SYSLINUX_LABEL to define the label to boot to for the test kernel. 485EOF 486 ; 487$config_help{"GRUB_MENU"} = << "EOF" 488 The grub title name for the test kernel to boot 489 (Only mandatory if REBOOT_TYPE = grub or grub2) 490 491 Note, ktest.pl will not update the grub menu.lst, you need to 492 manually add an option for the test. ktest.pl will search 493 the grub menu.lst for this option to find what kernel to 494 reboot into. 495 496 For example, if in the /boot/grub/menu.lst the test kernel title has: 497 title Test Kernel 498 kernel vmlinuz-test 499 GRUB_MENU = Test Kernel 500 501 For grub2, a search of \$GRUB_FILE is performed for the lines 502 that begin with "menuentry". It will not detect submenus. The 503 menu must be a non-nested menu. Add the quotes used in the menu 504 to guarantee your selection, as the first menuentry with the content 505 of \$GRUB_MENU that is found will be used. 506 507 For grub2bls, \$GRUB_MENU is searched on the result of \$GRUB_BLS_GET 508 command for the lines that begin with "title". 509EOF 510 ; 511$config_help{"GRUB_FILE"} = << "EOF" 512 If grub2 is used, the full path for the grub.cfg file is placed 513 here. Use something like /boot/grub2/grub.cfg to search. 514EOF 515 ; 516$config_help{"SYSLINUX_LABEL"} = << "EOF" 517 If syslinux is used, the label that boots the target kernel must 518 be specified with SYSLINUX_LABEL. 519EOF 520 ; 521$config_help{"REBOOT_SCRIPT"} = << "EOF" 522 A script to reboot the target into the test kernel 523 (Only mandatory if REBOOT_TYPE = script) 524EOF 525 ; 526 527# used with process_expression() 528my $d = 0; 529 530# defined before get_test_name() 531my $in_die = 0; 532 533# defined before process_warning_line() 534my $check_build_re = ".*:.*(warning|error|Error):.*"; 535my $utf8_quote = "\\x{e2}\\x{80}(\\x{98}|\\x{99})"; 536 537# defined before child_finished() 538my $child_done; 539 540# config_ignore holds the configs that were set (or unset) for 541# a good config and we will ignore these configs for the rest 542# of a config bisect. These configs stay as they were. 543my %config_ignore; 544 545# config_set holds what all configs were set as. 546my %config_set; 547 548# config_off holds the set of configs that the bad config had disabled. 549# We need to record them and set them in the .config when running 550# olddefconfig, because olddefconfig keeps the defaults. 551my %config_off; 552 553# config_off_tmp holds a set of configs to turn off for now 554my @config_off_tmp; 555 556# config_list is the set of configs that are being tested 557my %config_list; 558my %null_config; 559 560my %dependency; 561 562# found above run_config_bisect() 563my $pass = 1; 564 565# found above add_dep() 566 567my %depends; 568my %depcount; 569my $iflevel = 0; 570my @ifdeps; 571 572# prevent recursion 573my %read_kconfigs; 574 575# found above test_this_config() 576my %min_configs; 577my %keep_configs; 578my %save_configs; 579my %processed_configs; 580my %nochange_config; 581 582# 583# These are first defined here, main function later on 584# 585sub run_command; 586sub start_monitor; 587sub end_monitor; 588sub wait_for_monitor; 589 590sub _logit { 591 if (defined($opt{"LOG_FILE"}) && defined(fileno(LOG))) { 592 print LOG @_; 593 } 594} 595 596sub logit { 597 if (defined($opt{"LOG_FILE"})) { 598 _logit @_; 599 } else { 600 print @_; 601 } 602} 603 604sub doprint { 605 print @_; 606 _logit @_; 607} 608 609sub read_prompt { 610 my ($cancel, $prompt) = @_; 611 612 my $ans; 613 614 for (;;) { 615 if ($cancel) { 616 print "$prompt [y/n/C] "; 617 } else { 618 print "$prompt [Y/n] "; 619 } 620 $ans = <STDIN>; 621 chomp $ans; 622 if ($ans =~ /^\s*$/) { 623 if ($cancel) { 624 $ans = "c"; 625 } else { 626 $ans = "y"; 627 } 628 } 629 last if ($ans =~ /^y$/i || $ans =~ /^n$/i); 630 if ($cancel) { 631 last if ($ans =~ /^c$/i); 632 print "Please answer either 'y', 'n' or 'c'.\n"; 633 } else { 634 print "Please answer either 'y' or 'n'.\n"; 635 } 636 } 637 if ($ans =~ /^c/i) { 638 exit; 639 } 640 if ($ans !~ /^y$/i) { 641 return 0; 642 } 643 return 1; 644} 645 646sub read_yn { 647 my ($prompt) = @_; 648 649 return read_prompt 0, $prompt; 650} 651 652sub read_ync { 653 my ($prompt) = @_; 654 655 return read_prompt 1, $prompt; 656} 657 658sub get_mandatory_config { 659 my ($config) = @_; 660 my $ans; 661 662 return if (defined($opt{$config})); 663 664 if (defined($config_help{$config})) { 665 print "\n"; 666 print $config_help{$config}; 667 } 668 669 for (;;) { 670 print "$config = "; 671 if (defined($default{$config}) && length($default{$config})) { 672 print "\[$default{$config}\] "; 673 } 674 $ans = <STDIN>; 675 $ans =~ s/^\s*(.*\S)\s*$/$1/; 676 if ($ans =~ /^\s*$/) { 677 if ($default{$config}) { 678 $ans = $default{$config}; 679 } else { 680 print "Your answer can not be blank\n"; 681 next; 682 } 683 } 684 $entered_configs{$config} = ${ans}; 685 last; 686 } 687} 688 689sub show_time { 690 my ($time) = @_; 691 692 my $hours = 0; 693 my $minutes = 0; 694 695 if ($time > 3600) { 696 $hours = int($time / 3600); 697 $time -= $hours * 3600; 698 } 699 if ($time > 60) { 700 $minutes = int($time / 60); 701 $time -= $minutes * 60; 702 } 703 704 if ($hours > 0) { 705 doprint "$hours hour"; 706 doprint "s" if ($hours > 1); 707 doprint " "; 708 } 709 710 if ($minutes > 0) { 711 doprint "$minutes minute"; 712 doprint "s" if ($minutes > 1); 713 doprint " "; 714 } 715 716 doprint "$time second"; 717 doprint "s" if ($time != 1); 718} 719 720sub print_times { 721 doprint "\n"; 722 if ($build_time) { 723 doprint "Build time: "; 724 show_time($build_time); 725 doprint "\n"; 726 } 727 if ($install_time) { 728 doprint "Install time: "; 729 show_time($install_time); 730 doprint "\n"; 731 } 732 if ($reboot_time) { 733 doprint "Reboot time: "; 734 show_time($reboot_time); 735 doprint "\n"; 736 } 737 if ($test_time) { 738 doprint "Test time: "; 739 show_time($test_time); 740 doprint "\n"; 741 } 742 if ($warning_found) { 743 doprint "\n*** WARNING"; 744 doprint "S" if ($warning_found > 1); 745 doprint " found in build: $warning_found ***\n\n"; 746 } 747 748 # reset for iterations like bisect 749 $build_time = 0; 750 $install_time = 0; 751 $reboot_time = 0; 752 $test_time = 0; 753 $warning_found = 0; 754} 755 756sub get_mandatory_configs { 757 get_mandatory_config("MACHINE"); 758 get_mandatory_config("BUILD_DIR"); 759 get_mandatory_config("OUTPUT_DIR"); 760 761 if ($newconfig) { 762 get_mandatory_config("BUILD_OPTIONS"); 763 } 764 765 # options required for other than just building a kernel 766 if (!$buildonly) { 767 get_mandatory_config("POWER_CYCLE"); 768 get_mandatory_config("CONSOLE"); 769 } 770 771 # options required for install and more 772 if ($buildonly != 1) { 773 get_mandatory_config("SSH_USER"); 774 get_mandatory_config("BUILD_TARGET"); 775 get_mandatory_config("TARGET_IMAGE"); 776 } 777 778 get_mandatory_config("LOCALVERSION"); 779 780 return if ($buildonly); 781 782 my $rtype = $opt{"REBOOT_TYPE"}; 783 784 if (!defined($rtype)) { 785 if (!defined($opt{"GRUB_MENU"})) { 786 get_mandatory_config("REBOOT_TYPE"); 787 $rtype = $entered_configs{"REBOOT_TYPE"}; 788 } else { 789 $rtype = "grub"; 790 } 791 } 792 793 if (($rtype eq "grub") or ($rtype eq "grub2bls")) { 794 get_mandatory_config("GRUB_MENU"); 795 } 796 797 if ($rtype eq "grub2") { 798 get_mandatory_config("GRUB_MENU"); 799 get_mandatory_config("GRUB_FILE"); 800 } 801 802 if ($rtype eq "syslinux") { 803 get_mandatory_config("SYSLINUX_LABEL"); 804 } 805} 806 807sub process_variables { 808 my ($value, $remove_undef) = @_; 809 my $retval = ""; 810 811 # We want to check for '\', and it is just easier 812 # to check the previous character of '$' and not need 813 # to worry if '$' is the first character. By adding 814 # a space to $value, we can just check [^\\]\$ and 815 # it will still work. 816 $value = " $value"; 817 818 while ($value =~ /(.*?[^\\])\$\{([^\{]*?)\}(.*)/) { 819 my $begin = $1; 820 my $var = $2; 821 my $end = $3; 822 # append beginning of value to retval 823 $retval = "$retval$begin"; 824 if ($var =~ s/^shell\s+//) { 825 $retval = `$var`; 826 if ($?) { 827 doprint "WARNING: $var returned an error\n"; 828 } else { 829 chomp $retval; 830 } 831 } elsif (defined($variable{$var})) { 832 $retval = "$retval$variable{$var}"; 833 } elsif (defined($remove_undef) && $remove_undef) { 834 # for if statements, any variable that is not defined, 835 # we simple convert to 0 836 $retval = "${retval}0"; 837 } else { 838 # put back the origin piece, but with $#### to not reprocess it 839 $retval = "$retval\$####\{$var\}"; 840 # This could be an option that is used later, save 841 # it so we don't warn if this option is not one of 842 # ktests options. 843 $used_options{$var} = 1; 844 } 845 $value = "$retval$end"; 846 $retval = ""; 847 } 848 $retval = $value; 849 850 # Convert the saved variables with $####{var} back to ${var} 851 $retval =~ s/\$####/\$/g; 852 853 # remove the space added in the beginning 854 $retval =~ s/ //; 855 856 return "$retval"; 857} 858 859sub set_value { 860 my ($lvalue, $rvalue, $override, $overrides, $name) = @_; 861 862 my $prvalue = process_variables($rvalue); 863 864 if ($lvalue =~ /^(TEST|BISECT|CONFIG_BISECT)_TYPE(\[.*\])?$/ && 865 $prvalue !~ /^(config_|)bisect$/ && 866 $prvalue !~ /^build$/ && 867 $prvalue !~ /^make_warnings_file$/ && 868 $buildonly) { 869 870 # Note if a test is something other than build, then we 871 # will need other mandatory options. 872 if ($prvalue ne "install") { 873 $buildonly = 0; 874 } else { 875 # install still limits some mandatory options. 876 $buildonly = 2; 877 } 878 } 879 880 if (defined($opt{$lvalue})) { 881 if (!$override || defined(${$overrides}{$lvalue})) { 882 my $extra = ""; 883 if ($override) { 884 $extra = "In the same override section!\n"; 885 } 886 die "$name: $.: Option $lvalue defined more than once!\n$extra"; 887 } 888 ${$overrides}{$lvalue} = $prvalue; 889 } 890 891 $opt{$lvalue} = $prvalue; 892} 893 894sub set_eval { 895 my ($lvalue, $rvalue, $name) = @_; 896 897 my $prvalue = process_variables($rvalue); 898 my $arr; 899 900 if (defined($evals{$lvalue})) { 901 $arr = $evals{$lvalue}; 902 } else { 903 $arr = []; 904 $evals{$lvalue} = $arr; 905 } 906 907 push @{$arr}, $rvalue; 908} 909 910sub set_variable { 911 my ($lvalue, $rvalue, $command) = @_; 912 913 # Command line variables override all others 914 if (defined($command_tmp_vars{$lvalue})) { 915 return; 916 } 917 918 # If a variable is undefined, treat an unescaped self-reference as empty. 919 if (!defined($variable{$lvalue})) { 920 $rvalue =~ s/(?<!\\)\$\{\Q$lvalue\E\}//g; 921 $rvalue =~ s/^\s+//; 922 $rvalue =~ s/\s+$//; 923 } 924 925 if ($rvalue =~ /^\s*$/) { 926 delete $variable{$lvalue}; 927 } else { 928 $rvalue = process_variables($rvalue); 929 $variable{$lvalue} = $rvalue; 930 } 931 932 if (defined($command)) { 933 $command_tmp_vars{$lvalue} = 1; 934 } 935} 936 937sub process_compare { 938 my ($lval, $cmp, $rval) = @_; 939 940 # remove whitespace 941 942 $lval =~ s/^\s*//; 943 $lval =~ s/\s*$//; 944 945 $rval =~ s/^\s*//; 946 $rval =~ s/\s*$//; 947 948 if ($cmp eq "==") { 949 return $lval eq $rval; 950 } elsif ($cmp eq "!=") { 951 return $lval ne $rval; 952 } elsif ($cmp eq "=~") { 953 return $lval =~ m/$rval/; 954 } elsif ($cmp eq "!~") { 955 return $lval !~ m/$rval/; 956 } 957 958 my $statement = "$lval $cmp $rval"; 959 my $ret = eval $statement; 960 961 # $@ stores error of eval 962 if ($@) { 963 return -1; 964 } 965 966 return $ret; 967} 968 969sub value_defined { 970 my ($val) = @_; 971 972 return defined($variable{$2}) || 973 defined($opt{$2}); 974} 975 976sub process_expression { 977 my ($name, $val) = @_; 978 979 my $c = $d++; 980 981 while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) { 982 my $express = $1; 983 984 if (process_expression($name, $express)) { 985 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /; 986 } else { 987 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /; 988 } 989 } 990 991 $d--; 992 my $OR = "\\|\\|"; 993 my $AND = "\\&\\&"; 994 995 while ($val =~ s/^(.*?)($OR|$AND)//) { 996 my $express = $1; 997 my $op = $2; 998 999 if (process_expression($name, $express)) { 1000 if ($op eq "||") { 1001 return 1; 1002 } 1003 } else { 1004 if ($op eq "&&") { 1005 return 0; 1006 } 1007 } 1008 } 1009 1010 if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) { 1011 my $ret = process_compare($1, $2, $3); 1012 if ($ret < 0) { 1013 die "$name: $.: Unable to process comparison\n"; 1014 } 1015 return $ret; 1016 } 1017 1018 if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) { 1019 if (defined $1) { 1020 return !value_defined($2); 1021 } else { 1022 return value_defined($2); 1023 } 1024 } 1025 1026 if ($val =~ s/^\s*NOT\s+(.*)//) { 1027 my $express = $1; 1028 my $ret = process_expression($name, $express); 1029 return !$ret; 1030 } 1031 1032 if ($val =~ /^\s*0\s*$/) { 1033 return 0; 1034 } elsif ($val =~ /^\s*\d+\s*$/) { 1035 return 1; 1036 } 1037 1038 die ("$name: $.: Undefined content $val in if statement\n"); 1039} 1040 1041sub process_if { 1042 my ($name, $value) = @_; 1043 1044 # Convert variables and replace undefined ones with 0 1045 my $val = process_variables($value, 1); 1046 my $ret = process_expression $name, $val; 1047 1048 return $ret; 1049} 1050 1051sub __read_config { 1052 my ($config, $current_test_num) = @_; 1053 1054 my $in; 1055 open($in, $config) || die "can't read file $config"; 1056 1057 my $name = $config; 1058 $name =~ s,.*/(.*),$1,; 1059 1060 my $test_num = $$current_test_num; 1061 my $default = 1; 1062 my $repeat = 1; 1063 my $num_tests_set = 0; 1064 my $skip = 0; 1065 my $rest; 1066 my $line; 1067 my $test_case = 0; 1068 my $if = 0; 1069 my $if_set = 0; 1070 my $override = 0; 1071 1072 my %overrides; 1073 1074 while (<$in>) { 1075 1076 # ignore blank lines and comments 1077 next if (/^\s*$/ || /\s*\#/); 1078 1079 if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) { 1080 1081 my $type = $1; 1082 $rest = $2; 1083 $line = $2; 1084 1085 my $old_test_num; 1086 my $old_repeat; 1087 $override = 0; 1088 1089 if ($type eq "TEST_START") { 1090 if ($num_tests_set) { 1091 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 1092 } 1093 1094 $old_test_num = $test_num; 1095 $old_repeat = $repeat; 1096 1097 $test_num += $repeat; 1098 $default = 0; 1099 $repeat = 1; 1100 } else { 1101 $default = 1; 1102 } 1103 1104 # If SKIP is anywhere in the line, the command will be skipped 1105 if ($rest =~ s/\s+SKIP\b//) { 1106 $skip = 1; 1107 } else { 1108 $test_case = 1; 1109 $skip = 0; 1110 } 1111 1112 if ($rest =~ s/\sELSE\b//) { 1113 if (!$if) { 1114 die "$name: $.: ELSE found with out matching IF section\n$_"; 1115 } 1116 $if = 0; 1117 1118 if ($if_set) { 1119 $skip = 1; 1120 } else { 1121 $skip = 0; 1122 } 1123 } 1124 1125 if ($rest =~ s/\sIF\s+(.*)//) { 1126 if (process_if($name, $1)) { 1127 $if_set = 1; 1128 } else { 1129 $skip = 1; 1130 } 1131 $if = 1; 1132 } else { 1133 $if = 0; 1134 $if_set = 0; 1135 } 1136 1137 if (!$skip) { 1138 if ($type eq "TEST_START") { 1139 if ($rest =~ s/\s+ITERATE\s+(\d+)//) { 1140 $repeat = $1; 1141 $repeat_tests{"$test_num"} = $repeat; 1142 } 1143 } elsif ($rest =~ s/\sOVERRIDE\b//) { 1144 # DEFAULT only 1145 $override = 1; 1146 # Clear previous overrides 1147 %overrides = (); 1148 } 1149 } 1150 1151 if (!$skip && $rest !~ /^\s*$/) { 1152 die "$name: $.: Garbage found after $type\n$_"; 1153 } 1154 1155 if ($skip && $type eq "TEST_START") { 1156 $test_num = $old_test_num; 1157 $repeat = $old_repeat; 1158 } 1159 } elsif (/^\s*ELSE\b(.*)$/) { 1160 if (!$if) { 1161 die "$name: $.: ELSE found with out matching IF section\n$_"; 1162 } 1163 $rest = $1; 1164 if ($if_set) { 1165 $skip = 1; 1166 $rest = ""; 1167 } else { 1168 $skip = 0; 1169 1170 if ($rest =~ /\sIF\s+(.*)/) { 1171 # May be a ELSE IF section. 1172 if (process_if($name, $1)) { 1173 $if_set = 1; 1174 } else { 1175 $skip = 1; 1176 } 1177 $rest = ""; 1178 } else { 1179 $if = 0; 1180 } 1181 } 1182 1183 if ($rest !~ /^\s*$/) { 1184 die "$name: $.: Garbage found after DEFAULTS\n$_"; 1185 } 1186 1187 } elsif (/^\s*INCLUDE\s+(\S+)/) { 1188 1189 next if ($skip); 1190 1191 if (!$default) { 1192 die "$name: $.: INCLUDE can only be done in default sections\n$_"; 1193 } 1194 1195 my $file = process_variables($1); 1196 1197 if ($file !~ m,^/,) { 1198 # check the path of the config file first 1199 if ($config =~ m,(.*)/,) { 1200 if (-f "$1/$file") { 1201 $file = "$1/$file"; 1202 } 1203 } 1204 } 1205 1206 if ( ! -r $file ) { 1207 die "$name: $.: Can't read file $file\n$_"; 1208 } 1209 1210 if (__read_config($file, \$test_num)) { 1211 $test_case = 1; 1212 } 1213 1214 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=~\s*(.*?)\s*$/) { 1215 1216 next if ($skip); 1217 1218 my $lvalue = $1; 1219 my $rvalue = $2; 1220 1221 if ($default || $lvalue =~ /\[\d+\]$/) { 1222 set_eval($lvalue, $rvalue, $name); 1223 } else { 1224 my $val = "$lvalue\[$test_num\]"; 1225 set_eval($val, $rvalue, $name); 1226 } 1227 1228 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 1229 1230 next if ($skip); 1231 1232 my $lvalue = $1; 1233 my $rvalue = $2; 1234 1235 if (!$default && 1236 ($lvalue eq "NUM_TESTS" || 1237 $lvalue eq "LOG_FILE" || 1238 $lvalue eq "CLEAR_LOG")) { 1239 die "$name: $.: $lvalue must be set in DEFAULTS section\n"; 1240 } 1241 1242 if ($lvalue eq "NUM_TESTS") { 1243 if ($test_num) { 1244 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 1245 } 1246 if (!$default) { 1247 die "$name: $.: NUM_TESTS must be set in default section\n"; 1248 } 1249 $num_tests_set = 1; 1250 } 1251 1252 if ($default || $lvalue =~ /\[\d+\]$/) { 1253 set_value($lvalue, $rvalue, $override, \%overrides, $name); 1254 } else { 1255 my $val = "$lvalue\[$test_num\]"; 1256 set_value($val, $rvalue, $override, \%overrides, $name); 1257 1258 if ($repeat > 1) { 1259 $repeats{$val} = $repeat; 1260 } 1261 } 1262 } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) { 1263 next if ($skip); 1264 1265 my $lvalue = $1; 1266 my $rvalue = $2; 1267 1268 # process config variables. 1269 # Config variables are only active while reading the 1270 # config and can be defined anywhere. They also ignore 1271 # TEST_START and DEFAULTS, but are skipped if they are in 1272 # one of these sections that have SKIP defined. 1273 # The save variable can be 1274 # defined multiple times and the new one simply overrides 1275 # the previous one. 1276 set_variable($lvalue, $rvalue); 1277 1278 } else { 1279 die "$name: $.: Garbage found in config\n$_"; 1280 } 1281 } 1282 1283 if ($test_num) { 1284 $test_num += $repeat - 1; 1285 $opt{"NUM_TESTS"} = $test_num; 1286 } 1287 1288 close($in); 1289 1290 $$current_test_num = $test_num; 1291 1292 return $test_case; 1293} 1294 1295sub get_test_case { 1296 print "What test case would you like to run?\n"; 1297 print " (build, install or boot)\n"; 1298 print " Other tests are available but require editing ktest.conf\n"; 1299 print " (see tools/testing/ktest/sample.conf)\n"; 1300 my $ans = <STDIN>; 1301 chomp $ans; 1302 $default{"TEST_TYPE"} = $ans; 1303} 1304 1305sub read_config { 1306 my ($config) = @_; 1307 1308 my $test_case; 1309 my $test_num = 0; 1310 1311 $test_case = __read_config $config, \$test_num; 1312 1313 foreach my $val (@command_vars) { 1314 chomp $val; 1315 my %command_overrides; 1316 if ($val =~ m/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 1317 my $lvalue = $1; 1318 my $rvalue = $2; 1319 1320 set_value($lvalue, $rvalue, 1, \%command_overrides, "COMMAND LINE"); 1321 } else { 1322 die "Invalid option definition '$val'\n"; 1323 } 1324 } 1325 1326 # make sure we have all mandatory configs 1327 get_mandatory_configs; 1328 1329 # was a test specified? 1330 if (!$test_case) { 1331 print "No test case specified.\n"; 1332 get_test_case; 1333 } 1334 1335 # set any defaults 1336 1337 foreach my $default (keys %default) { 1338 if (!defined($opt{$default})) { 1339 $opt{$default} = $default{$default}; 1340 } 1341 } 1342 1343 if ($opt{"IGNORE_UNUSED"} == 1) { 1344 return; 1345 } 1346 1347 my %not_used; 1348 1349 # check if there are any stragglers (typos?) 1350 foreach my $option (keys %opt) { 1351 my $op = $option; 1352 # remove per test labels. 1353 $op =~ s/\[.*\]//; 1354 if (!exists($option_map{$op}) && 1355 !exists($default{$op}) && 1356 !exists($used_options{$op})) { 1357 $not_used{$op} = 1; 1358 } 1359 } 1360 1361 if (%not_used) { 1362 my $s = "s are"; 1363 $s = " is" if (keys %not_used == 1); 1364 print "The following option$s not used; could be a typo:\n"; 1365 foreach my $option (keys %not_used) { 1366 print "$option\n"; 1367 } 1368 print "Set IGNORE_UNUSED = 1 to have ktest ignore unused variables\n"; 1369 if ($dry_run) { 1370 return; 1371 } 1372 if (!read_yn "Do you want to continue?") { 1373 exit -1; 1374 } 1375 } 1376} 1377 1378sub __eval_option { 1379 my ($name, $option, $i) = @_; 1380 1381 # Add space to evaluate the character before $ 1382 $option = " $option"; 1383 my $retval = ""; 1384 my $repeated = 0; 1385 my $parent = 0; 1386 1387 foreach my $test (keys %repeat_tests) { 1388 if ($i >= $test && 1389 $i < $test + $repeat_tests{$test}) { 1390 1391 $repeated = 1; 1392 $parent = $test; 1393 last; 1394 } 1395 } 1396 1397 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 1398 my $start = $1; 1399 my $var = $2; 1400 my $end = $3; 1401 1402 # Append beginning of line 1403 $retval = "$retval$start"; 1404 1405 # If the iteration option OPT[$i] exists, then use that. 1406 # otherwise see if the default OPT (without [$i]) exists. 1407 1408 my $o = "$var\[$i\]"; 1409 my $parento = "$var\[$parent\]"; 1410 1411 # If a variable contains itself, use the default var 1412 if (($var eq $name) && defined($opt{$var})) { 1413 $o = $opt{$var}; 1414 # Only append if the default doesn't contain itself 1415 if ($o !~ m/\$\{$var\}/) { 1416 $retval = "$retval$o"; 1417 } 1418 } elsif (defined($opt{$o})) { 1419 $o = $opt{$o}; 1420 $retval = "$retval$o"; 1421 } elsif ($repeated && defined($opt{$parento})) { 1422 $o = $opt{$parento}; 1423 $retval = "$retval$o"; 1424 } elsif (defined($opt{$var})) { 1425 $o = $opt{$var}; 1426 $retval = "$retval$o"; 1427 } elsif ($var eq "KERNEL_VERSION" && defined($make)) { 1428 # special option KERNEL_VERSION uses kernel version 1429 get_version(); 1430 $retval = "$retval$version"; 1431 } else { 1432 $retval = "$retval\$\{$var\}"; 1433 } 1434 1435 $option = $end; 1436 } 1437 1438 $retval = "$retval$option"; 1439 1440 $retval =~ s/^ //; 1441 1442 return $retval; 1443} 1444 1445sub process_evals { 1446 my ($name, $option, $i) = @_; 1447 1448 my $option_name = "$name\[$i\]"; 1449 my $ev; 1450 1451 my $old_option = $option; 1452 1453 if (defined($evals{$option_name})) { 1454 $ev = $evals{$option_name}; 1455 } elsif (defined($evals{$name})) { 1456 $ev = $evals{$name}; 1457 } else { 1458 return $option; 1459 } 1460 1461 for my $e (@{$ev}) { 1462 eval "\$option =~ $e"; 1463 } 1464 1465 if ($option ne $old_option) { 1466 doprint("$name changed from '$old_option' to '$option'\n"); 1467 } 1468 1469 return $option; 1470} 1471 1472sub eval_option { 1473 my ($name, $option, $i) = @_; 1474 1475 my $prev = ""; 1476 1477 # Since an option can evaluate to another option, 1478 # keep iterating until we do not evaluate any more 1479 # options. 1480 my $r = 0; 1481 while ($prev ne $option) { 1482 # Check for recursive evaluations. 1483 # 100 deep should be more than enough. 1484 if ($r++ > 100) { 1485 die "Over 100 evaluations occurred with $option\n" . 1486 "Check for recursive variables\n"; 1487 } 1488 $prev = $option; 1489 $option = __eval_option($name, $option, $i); 1490 } 1491 1492 $option = process_evals($name, $option, $i); 1493 1494 return $option; 1495} 1496 1497sub reboot { 1498 my ($time) = @_; 1499 my $powercycle = 0; 1500 1501 # test if the machine can be connected to within a few seconds 1502 my $stat = run_ssh("echo check machine status", $connect_timeout); 1503 if (!$stat) { 1504 doprint("power cycle\n"); 1505 $powercycle = 1; 1506 } 1507 1508 if ($powercycle) { 1509 start_monitor; 1510 if (defined($time)) { 1511 # Flush stale console output from the old kernel before power-cycling. 1512 wait_for_monitor 1; 1513 } 1514 1515 run_command "$power_cycle"; 1516 1517 } else { 1518 # Make sure everything has been written to disk 1519 run_ssh("sync", 10); 1520 1521 if (defined($time)) { 1522 start_monitor; 1523 # flush out current monitor 1524 # May contain the reboot success line 1525 wait_for_monitor 1; 1526 } 1527 1528 # try to reboot normally 1529 if (run_command $reboot) { 1530 if (defined($powercycle_after_reboot)) { 1531 sleep $powercycle_after_reboot; 1532 run_command "$power_cycle"; 1533 } 1534 } else { 1535 # nope? power cycle it. 1536 run_command "$power_cycle"; 1537 } 1538 } 1539 1540 if (defined($time)) { 1541 1542 # We only want to get to the new kernel, don't fail 1543 # if we stumble over a call trace. 1544 my $save_ignore_errors = $ignore_errors; 1545 $ignore_errors = 1; 1546 1547 # Look for the good kernel to boot 1548 if (wait_for_monitor($time, "Linux version")) { 1549 # reboot got stuck? 1550 doprint "Reboot did not finish. Forcing power cycle\n"; 1551 run_command "$power_cycle"; 1552 } 1553 1554 $ignore_errors = $save_ignore_errors; 1555 1556 # Still need to wait for the reboot to finish 1557 wait_for_monitor($time, $reboot_success_line); 1558 } 1559 if ($powercycle || $time) { 1560 end_monitor; 1561 } 1562} 1563 1564sub reboot_to_good { 1565 my ($time) = @_; 1566 1567 if (defined($switch_to_good)) { 1568 run_command $switch_to_good; 1569 } 1570 1571 reboot $time; 1572} 1573 1574sub do_not_reboot { 1575 my $i = $iteration; 1576 1577 return $test_type eq "build" || $no_reboot || 1578 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 1579 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build") || 1580 ($test_type eq "config_bisect" && $opt{"CONFIG_BISECT_TYPE[$i]"} eq "build"); 1581} 1582 1583sub get_test_name() { 1584 my $name; 1585 1586 if (defined($test_name)) { 1587 $name = "$test_name:$test_type"; 1588 } else { 1589 $name = $test_type; 1590 } 1591 return $name; 1592} 1593 1594sub run_post_ktest { 1595 my $cmd; 1596 1597 return if ($post_ktest_done); 1598 1599 if (defined($final_post_ktest)) { 1600 $cmd = $final_post_ktest; 1601 } elsif (defined($post_ktest)) { 1602 $cmd = $post_ktest; 1603 } else { 1604 return; 1605 } 1606 1607 my $cp_post_ktest = eval_kernel_version($cmd); 1608 run_command $cp_post_ktest; 1609 $post_ktest_done = 1; 1610} 1611 1612sub dodie { 1613 # avoid recursion 1614 return if ($in_die); 1615 $in_die = 1; 1616 1617 if ($monitor_cnt) { 1618 # restore terminal settings 1619 system("stty $stty_orig"); 1620 } 1621 1622 my $i = $iteration; 1623 1624 doprint "CRITICAL FAILURE... [TEST $i] ", @_, "\n"; 1625 1626 if ($reboot_on_error && !do_not_reboot) { 1627 doprint "REBOOTING\n"; 1628 reboot_to_good; 1629 } elsif ($poweroff_on_error && defined($power_off)) { 1630 doprint "POWERING OFF\n"; 1631 `$power_off`; 1632 } 1633 1634 if (defined($opt{"LOG_FILE"})) { 1635 print " See $opt{LOG_FILE} for more info.\n"; 1636 } 1637 1638 # Fatal paths bypass fail(), so STORE_FAILURES needs to be handled here. 1639 if (defined($store_failures)) { 1640 save_logs("fail", $store_failures); 1641 } 1642 1643 if ($email_on_error) { 1644 my $name = get_test_name; 1645 my $log_file; 1646 1647 if (defined($opt{"LOG_FILE"})) { 1648 my $whence = 2; # End of file 1649 my $log_size = tell LOG; 1650 my $size = $log_size - $test_log_start; 1651 1652 if (defined($mail_max_size)) { 1653 if ($size > $mail_max_size) { 1654 $size = $mail_max_size; 1655 } 1656 } 1657 my $pos = - $size; 1658 $log_file = "$tmpdir/log"; 1659 open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)"; 1660 open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n"; 1661 seek(L, $pos, $whence); 1662 while (<L>) { 1663 print O; 1664 } 1665 close O; 1666 close L; 1667 } 1668 1669 send_email("KTEST: critical failure for test $i [$name]", 1670 "Your test started at $script_start_time has failed with:\n@_\n", $log_file); 1671 } 1672 1673 if (defined($post_test)) { 1674 run_command $post_test; 1675 } 1676 run_post_ktest; 1677 1678 die @_, "\n"; 1679} 1680 1681sub create_pty { 1682 my ($ptm, $pts) = @_; 1683 my $tmp; 1684 my $TIOCSPTLCK = 0x40045431; 1685 my $TIOCGPTN = 0x80045430; 1686 1687 sysopen($ptm, "/dev/ptmx", O_RDWR | O_NONBLOCK) or 1688 dodie "Can't open /dev/ptmx"; 1689 1690 # unlockpt() 1691 $tmp = pack("i", 0); 1692 ioctl($ptm, $TIOCSPTLCK, $tmp) or 1693 dodie "ioctl TIOCSPTLCK for /dev/ptmx failed"; 1694 1695 # ptsname() 1696 ioctl($ptm, $TIOCGPTN, $tmp) or 1697 dodie "ioctl TIOCGPTN for /dev/ptmx failed"; 1698 $tmp = unpack("i", $tmp); 1699 1700 sysopen($pts, "/dev/pts/$tmp", O_RDWR | O_NONBLOCK) or 1701 dodie "Can't open /dev/pts/$tmp"; 1702} 1703 1704sub exec_console { 1705 my ($ptm, $pts) = @_; 1706 1707 close($ptm); 1708 1709 close(\*STDIN); 1710 close(\*STDOUT); 1711 close(\*STDERR); 1712 1713 open(\*STDIN, '<&', $pts); 1714 open(\*STDOUT, '>&', $pts); 1715 open(\*STDERR, '>&', $pts); 1716 1717 close($pts); 1718 1719 exec $console or 1720 dodie "Can't open console $console"; 1721} 1722 1723sub open_console { 1724 my ($ptm) = @_; 1725 my $pts = \*PTSFD; 1726 my $pid; 1727 1728 # save terminal settings 1729 $stty_orig = `stty -g`; 1730 1731 # place terminal in cbreak mode so that stdin can be read one character at 1732 # a time without having to wait for a newline 1733 system("stty -icanon -echo -icrnl"); 1734 1735 create_pty($ptm, $pts); 1736 1737 $pid = fork; 1738 1739 if (!$pid) { 1740 # child 1741 exec_console($ptm, $pts) 1742 } 1743 1744 # parent 1745 close($pts); 1746 1747 return $pid; 1748 1749 open(PTSFD, "Stop perl from warning about single use of PTSFD"); 1750} 1751 1752sub close_console { 1753 my ($fp, $pid) = @_; 1754 1755 doprint "kill child process $pid\n"; 1756 kill $close_console_signal, $pid; 1757 1758 doprint "wait for child process $pid to exit\n"; 1759 waitpid($pid, 0); 1760 1761 print "closing!\n"; 1762 close($fp); 1763 1764 # restore terminal settings 1765 system("stty $stty_orig"); 1766} 1767 1768sub start_monitor { 1769 if ($monitor_cnt++) { 1770 return; 1771 } 1772 $monitor_fp = \*MONFD; 1773 $monitor_pid = open_console $monitor_fp; 1774 1775 return; 1776 1777 open(MONFD, "Stop perl from warning about single use of MONFD"); 1778} 1779 1780sub end_monitor { 1781 return if (!defined $console); 1782 if (--$monitor_cnt) { 1783 return; 1784 } 1785 close_console($monitor_fp, $monitor_pid); 1786} 1787 1788sub wait_for_monitor { 1789 my ($time, $stop) = @_; 1790 my $full_line = ""; 1791 my $line; 1792 my $booted = 0; 1793 my $start_time = time; 1794 my $skip_call_trace = 0; 1795 my $bug = 0; 1796 my $bug_ignored = 0; 1797 my $now; 1798 1799 doprint "** Wait for monitor to settle down **\n"; 1800 1801 # read the monitor and wait for the system to calm down 1802 while (!$booted) { 1803 $line = wait_for_input($monitor_fp, $time); 1804 last if (!defined($line)); 1805 print "$line"; 1806 $full_line .= $line; 1807 1808 if (defined($stop) && $full_line =~ /$stop/) { 1809 doprint "wait for monitor detected $stop\n"; 1810 $booted = 1; 1811 } 1812 1813 if ($full_line =~ /\[ backtrace testing \]/) { 1814 $skip_call_trace = 1; 1815 } 1816 1817 if ($full_line =~ /call trace:/i) { 1818 if (!$bug && !$skip_call_trace) { 1819 if ($ignore_errors) { 1820 $bug_ignored = 1; 1821 } else { 1822 $bug = 1; 1823 } 1824 } 1825 } 1826 1827 if ($full_line =~ /\[ end of backtrace testing \]/) { 1828 $skip_call_trace = 0; 1829 } 1830 1831 if ($full_line =~ /Kernel panic -/) { 1832 $bug = 1; 1833 } 1834 1835 if ($line =~ /\n/) { 1836 $full_line = ""; 1837 } 1838 $now = time; 1839 if ($now - $start_time >= $max_monitor_wait) { 1840 doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n"; 1841 return 1; 1842 } 1843 } 1844 print "** Monitor flushed **\n"; 1845 1846 # if stop is defined but wasn't hit, return error 1847 # used by reboot (which wants to see a reboot) 1848 if (defined($stop) && !$booted) { 1849 $bug = 1; 1850 } 1851 return $bug; 1852} 1853 1854sub save_logs { 1855 my ($result, $basedir) = @_; 1856 my @t = localtime; 1857 my $date = sprintf "%04d%02d%02d%02d%02d%02d", 1858 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 1859 1860 my $type = $build_type; 1861 if ($type =~ /useconfig/) { 1862 $type = "useconfig"; 1863 } 1864 1865 my $dir = "$machine-$test_type-$type-$result-$date"; 1866 1867 $dir = "$basedir/$dir"; 1868 1869 if (!-d $dir) { 1870 mkpath($dir) or 1871 dodie "can't create $dir"; 1872 } 1873 1874 my %files = ( 1875 "config" => $output_config, 1876 "buildlog" => $buildlog, 1877 "dmesg" => $dmesg, 1878 "testlog" => $testlog, 1879 ); 1880 1881 while (my ($name, $source) = each(%files)) { 1882 if (-f "$source") { 1883 cp "$source", "$dir/$name" or 1884 dodie "failed to copy $source"; 1885 } 1886 } 1887 1888 doprint "*** Saved info to $dir ***\n"; 1889} 1890 1891sub fail { 1892 1893 if ($die_on_failure) { 1894 dodie @_; 1895 } 1896 1897 doprint "FAILED\n"; 1898 1899 my $i = $iteration; 1900 1901 # no need to reboot for just building. 1902 if (!do_not_reboot) { 1903 doprint "REBOOTING\n"; 1904 reboot_to_good $sleep_time; 1905 } 1906 1907 my $name = ""; 1908 1909 if (defined($test_name)) { 1910 $name = " ($test_name)"; 1911 } 1912 1913 print_times; 1914 1915 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1916 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1917 doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n"; 1918 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1919 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1920 1921 if (defined($store_failures)) { 1922 save_logs "fail", $store_failures; 1923 } 1924 1925 if (defined($post_test)) { 1926 run_command $post_test; 1927 } 1928 1929 return 1; 1930} 1931 1932sub run_command { 1933 my ($command, $redirect, $timeout) = @_; 1934 my $start_time; 1935 my $end_time; 1936 my $dolog = 0; 1937 my $dord = 0; 1938 my $dostdout = 0; 1939 my $pid; 1940 my $command_orig = $command; 1941 1942 $command =~ s/\$SSH_USER/$ssh_user/g; 1943 $command =~ s/\$MACHINE/$machine/g; 1944 1945 if (!defined($timeout)) { 1946 $timeout = $run_timeout; 1947 } 1948 1949 if (!defined($timeout)) { 1950 $timeout = -1; # tell wait_for_input to wait indefinitely 1951 } 1952 1953 doprint("$command ... "); 1954 $start_time = time; 1955 1956 $pid = open(CMD, "-|", 1957 "sh", "-c", 1958 'command=$1; shift; exec 2>&1; eval "$command"', 1959 "sh", $command) or 1960 (fail "unable to exec $command" and return 0); 1961 1962 if (defined($opt{"LOG_FILE"})) { 1963 $dolog = 1; 1964 } 1965 1966 if (defined($redirect)) { 1967 if ($redirect eq 1) { 1968 $dostdout = 1; 1969 # Have the output of the command on its own line 1970 doprint "\n"; 1971 } else { 1972 open (RD, ">$redirect") or 1973 dodie "failed to write to redirect $redirect"; 1974 $dord = 1; 1975 } 1976 } 1977 1978 my $hit_timeout = 0; 1979 1980 while (1) { 1981 my $fp = \*CMD; 1982 my $line = wait_for_input($fp, $timeout); 1983 if (!defined($line)) { 1984 my $now = time; 1985 if ($timeout >= 0 && (($now - $start_time) >= $timeout)) { 1986 doprint "Hit timeout of $timeout, killing process\n"; 1987 $hit_timeout = 1; 1988 kill 9, $pid; 1989 } 1990 last; 1991 } 1992 print LOG $line if ($dolog); 1993 print RD $line if ($dord); 1994 print $line if ($dostdout); 1995 } 1996 1997 waitpid($pid, 0); 1998 # shift 8 for real exit status 1999 $run_command_status = $? >> 8; 2000 2001 if ($command_orig eq $default{REBOOT} && 2002 $run_command_status == $reboot_return_code) { 2003 $run_command_status = 0; 2004 } 2005 2006 close(CMD); 2007 close(RD) if ($dord); 2008 2009 $end_time = time; 2010 my $delta = $end_time - $start_time; 2011 2012 if ($delta == 1) { 2013 doprint "[1 second] "; 2014 } else { 2015 doprint "[$delta seconds] "; 2016 } 2017 2018 if ($hit_timeout) { 2019 $run_command_status = 1; 2020 } 2021 2022 if ($run_command_status) { 2023 doprint "FAILED!\n"; 2024 } else { 2025 doprint "SUCCESS\n"; 2026 } 2027 2028 return !$run_command_status; 2029} 2030 2031sub run_ssh { 2032 my ($cmd, $timeout) = @_; 2033 my $cp_exec = $ssh_exec; 2034 2035 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 2036 return run_command "$cp_exec", undef , $timeout; 2037} 2038 2039sub run_scp { 2040 my ($src, $dst, $cp_scp) = @_; 2041 2042 $cp_scp =~ s/\$SRC_FILE/$src/g; 2043 $cp_scp =~ s/\$DST_FILE/$dst/g; 2044 2045 return run_command "$cp_scp"; 2046} 2047 2048sub run_scp_install { 2049 my ($src, $dst) = @_; 2050 2051 my $cp_scp = $scp_to_target_install; 2052 2053 return run_scp($src, $dst, $cp_scp); 2054} 2055 2056sub run_scp_mod { 2057 my ($src, $dst) = @_; 2058 2059 my $cp_scp = $scp_to_target; 2060 2061 return run_scp($src, $dst, $cp_scp); 2062} 2063 2064sub _get_grub_index { 2065 2066 my ($command, $target, $skip, $submenu) = @_; 2067 2068 return if (defined($grub_number) && defined($last_grub_menu) && 2069 $last_grub_menu eq $grub_menu && defined($last_machine) && 2070 $last_machine eq $machine); 2071 2072 doprint "Find $reboot_type menu ... "; 2073 $grub_number = -1; 2074 2075 my $ssh_grub = $ssh_exec; 2076 $ssh_grub =~ s,\$SSH_COMMAND,$command,g; 2077 2078 open(IN, "$ssh_grub |") or 2079 dodie "unable to execute $command"; 2080 2081 my $found = 0; 2082 2083 my $submenu_number = 0; 2084 2085 while (<IN>) { 2086 if (/$target/) { 2087 $grub_number++; 2088 $found = 1; 2089 last; 2090 } elsif (defined($submenu) && /$submenu/) { 2091 $submenu_number++; 2092 $grub_number = -1; 2093 } elsif (/$skip/) { 2094 $grub_number++; 2095 } 2096 } 2097 close(IN); 2098 2099 dodie "Could not find '$grub_menu' through $command on $machine" 2100 if (!$found); 2101 if ($submenu_number > 0) { 2102 $grub_number = "$submenu_number>$grub_number"; 2103 } 2104 doprint "$grub_number\n"; 2105 $last_grub_menu = $grub_menu; 2106 $last_machine = $machine; 2107} 2108 2109sub get_grub_index { 2110 2111 my $command; 2112 my $target; 2113 my $skip; 2114 my $submenu; 2115 my $grub_menu_qt; 2116 2117 if ($reboot_type !~ /^grub/) { 2118 return; 2119 } 2120 2121 $grub_menu_qt = quotemeta($grub_menu); 2122 2123 if ($reboot_type eq "grub") { 2124 $command = "cat /boot/grub/menu.lst"; 2125 $target = '^\s*title\s+' . $grub_menu_qt . '\s*$'; 2126 $skip = '^\s*title\s'; 2127 } elsif ($reboot_type eq "grub2") { 2128 $command = "cat $grub_file"; 2129 $target = '^\s*menuentry.*' . $grub_menu_qt; 2130 $skip = '^\s*menuentry\s'; 2131 $submenu = '^\s*submenu\s'; 2132 } elsif ($reboot_type eq "grub2bls") { 2133 $command = $grub_bls_get; 2134 $target = '^title=.*' . $grub_menu_qt; 2135 $skip = '^title='; 2136 } else { 2137 return; 2138 } 2139 2140 _get_grub_index($command, $target, $skip, $submenu); 2141} 2142 2143sub wait_for_input { 2144 my ($fp, $time) = @_; 2145 my $start_time; 2146 my $rin; 2147 my $rout; 2148 my $nr; 2149 my $buf; 2150 my $line; 2151 my $ch; 2152 2153 if (!defined($time)) { 2154 $time = $timeout; 2155 } 2156 2157 if ($time < 0) { 2158 # Negative number means wait indefinitely 2159 undef $time; 2160 } 2161 2162 $rin = ''; 2163 vec($rin, fileno($fp), 1) = 1; 2164 vec($rin, fileno(\*STDIN), 1) = 1; 2165 2166 $start_time = time; 2167 2168 while (1) { 2169 $nr = select($rout=$rin, undef, undef, $time); 2170 2171 last if ($nr <= 0); 2172 2173 # copy data from stdin to the console 2174 if (vec($rout, fileno(\*STDIN), 1) == 1) { 2175 $nr = sysread(\*STDIN, $buf, 1000); 2176 syswrite($fp, $buf, $nr) if ($nr > 0); 2177 } 2178 2179 # The timeout is based on time waiting for the fp data 2180 if (vec($rout, fileno($fp), 1) != 1) { 2181 last if (defined($time) && (time - $start_time > $time)); 2182 next; 2183 } 2184 2185 $line = ""; 2186 2187 # try to read one char at a time 2188 while (sysread $fp, $ch, 1) { 2189 $line .= $ch; 2190 last if ($ch eq "\n"); 2191 } 2192 2193 last if (!length($line)); 2194 2195 return $line; 2196 } 2197 return undef; 2198} 2199 2200sub reboot_to { 2201 if (defined($switch_to_test)) { 2202 run_command $switch_to_test; 2203 } 2204 2205 if ($reboot_type eq "grub") { 2206 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; 2207 } elsif (($reboot_type eq "grub2") or ($reboot_type eq "grub2bls")) { 2208 run_ssh "$grub_reboot \"'$grub_number'\""; 2209 } elsif ($reboot_type eq "syslinux") { 2210 run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path"; 2211 } elsif (defined $reboot_script) { 2212 run_command "$reboot_script"; 2213 } 2214 reboot; 2215} 2216 2217sub get_sha1 { 2218 my ($commit) = @_; 2219 2220 doprint "git rev-list --max-count=1 $commit ... "; 2221 my $sha1 = `git rev-list --max-count=1 $commit`; 2222 my $ret = $?; 2223 2224 logit $sha1; 2225 2226 if ($ret) { 2227 doprint "FAILED\n"; 2228 dodie "Failed to get git $commit"; 2229 } 2230 2231 print "SUCCESS\n"; 2232 2233 chomp $sha1; 2234 2235 return $sha1; 2236} 2237 2238sub monitor { 2239 my $booted = 0; 2240 my $bug = 0; 2241 my $bug_ignored = 0; 2242 my $skip_call_trace = 0; 2243 my $loops; 2244 2245 my $start_time = time; 2246 2247 wait_for_monitor 5; 2248 2249 my $line; 2250 my $full_line = ""; 2251 2252 open(DMESG, "> $dmesg") or 2253 dodie "unable to write to $dmesg"; 2254 2255 reboot_to; 2256 2257 my $success_start; 2258 my $failure_start; 2259 my $monitor_start = time; 2260 my $done = 0; 2261 my $version_found = 0; 2262 2263 while (!$done) { 2264 if ($bug && defined($stop_after_failure) && 2265 $stop_after_failure >= 0) { 2266 my $time = $stop_after_failure - (time - $failure_start); 2267 $line = wait_for_input($monitor_fp, $time); 2268 if (!defined($line)) { 2269 doprint "bug timed out after $booted_timeout seconds\n"; 2270 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 2271 last; 2272 } 2273 } elsif ($booted) { 2274 $line = wait_for_input($monitor_fp, $booted_timeout); 2275 if (!defined($line)) { 2276 my $s = $booted_timeout == 1 ? "" : "s"; 2277 doprint "Successful boot found: break after $booted_timeout second$s\n"; 2278 last; 2279 } 2280 } else { 2281 $line = wait_for_input($monitor_fp); 2282 if (!defined($line)) { 2283 my $s = $timeout == 1 ? "" : "s"; 2284 doprint "Timed out after $timeout second$s\n"; 2285 last; 2286 } 2287 } 2288 2289 doprint $line; 2290 print DMESG $line; 2291 2292 # we are not guaranteed to get a full line 2293 $full_line .= $line; 2294 2295 if ($full_line =~ /$success_line/) { 2296 $booted = 1; 2297 $success_start = time; 2298 } 2299 2300 if ($booted && defined($stop_after_success) && 2301 $stop_after_success >= 0) { 2302 my $now = time; 2303 if ($now - $success_start >= $stop_after_success) { 2304 doprint "Test forced to stop after $stop_after_success seconds after success\n"; 2305 last; 2306 } 2307 } 2308 2309 if ($full_line =~ /\[ backtrace testing \]/) { 2310 $skip_call_trace = 1; 2311 } 2312 2313 if ($full_line =~ /call trace:/i) { 2314 if (!$bug && !$skip_call_trace) { 2315 if ($ignore_errors) { 2316 $bug_ignored = 1; 2317 } else { 2318 $bug = 1; 2319 $failure_start = time; 2320 } 2321 } 2322 } 2323 2324 if ($bug && defined($stop_after_failure) && 2325 $stop_after_failure >= 0) { 2326 my $now = time; 2327 if ($now - $failure_start >= $stop_after_failure) { 2328 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 2329 last; 2330 } 2331 } 2332 2333 if ($full_line =~ /\[ end of backtrace testing \]/) { 2334 $skip_call_trace = 0; 2335 } 2336 2337 if ($full_line =~ /Kernel panic -/) { 2338 $failure_start = time; 2339 $bug = 1; 2340 } 2341 2342 # Detect triple faults by testing the banner 2343 if ($full_line =~ /\bLinux version (\S+).*\n/) { 2344 if ($1 eq $version) { 2345 $version_found = 1; 2346 } elsif ($version_found && $detect_triplefault) { 2347 # We already booted into the kernel we are testing, 2348 # but now we booted into another kernel? 2349 # Consider this a triple fault. 2350 doprint "Already booted in Linux kernel $version, but now\n"; 2351 doprint "we booted into Linux kernel $1.\n"; 2352 doprint "Assuming that this is a triple fault.\n"; 2353 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; 2354 last; 2355 } 2356 } 2357 2358 if ($line =~ /\n/) { 2359 $full_line = ""; 2360 } 2361 2362 if ($stop_test_after > 0 && !$booted && !$bug) { 2363 if (time - $monitor_start > $stop_test_after) { 2364 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 2365 $done = 1; 2366 } 2367 } 2368 } 2369 2370 my $end_time = time; 2371 $reboot_time = $end_time - $start_time; 2372 2373 close(DMESG); 2374 2375 if ($bug) { 2376 return 0 if ($in_bisect); 2377 fail "failed - got a bug report" and return 0; 2378 } 2379 2380 if (!$booted) { 2381 return 0 if ($in_bisect); 2382 fail "failed - never got a boot prompt." and return 0; 2383 } 2384 2385 if ($bug_ignored) { 2386 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 2387 } 2388 2389 return 1; 2390} 2391 2392sub eval_kernel_version { 2393 my ($option) = @_; 2394 2395 $option =~ s/\$KERNEL_VERSION/$version/g; 2396 2397 return $option; 2398} 2399 2400sub do_post_install { 2401 2402 return if (!defined($post_install)); 2403 2404 my $cp_post_install = eval_kernel_version $post_install; 2405 run_command "$cp_post_install" or 2406 dodie "Failed to run post install"; 2407} 2408 2409# Sometimes the reboot fails, and will hang. We try to ssh to the box 2410# and if we fail, we force another reboot, that should powercycle it. 2411sub test_booted { 2412 if (!run_ssh "echo testing connection") { 2413 reboot $sleep_time; 2414 } 2415} 2416 2417sub install { 2418 2419 return if ($no_install); 2420 2421 my $start_time = time; 2422 2423 if (defined($pre_install)) { 2424 my $cp_pre_install = eval_kernel_version $pre_install; 2425 run_command "$cp_pre_install" or 2426 dodie "Failed to run pre install"; 2427 } 2428 2429 my $cp_target = eval_kernel_version $target_image; 2430 2431 test_booted; 2432 2433 run_scp_install "$outputdir/$build_target", "$cp_target" or 2434 dodie "failed to copy image"; 2435 2436 my $install_mods = 0; 2437 2438 # should we process modules? 2439 $install_mods = 0; 2440 open(IN, "$output_config") or dodie("Can't read config file"); 2441 while (<IN>) { 2442 if (/CONFIG_MODULES(=y)?/) { 2443 if (defined($1)) { 2444 $install_mods = 1; 2445 last; 2446 } 2447 } 2448 } 2449 close(IN); 2450 2451 if (!$install_mods) { 2452 do_post_install; 2453 doprint "No modules needed\n"; 2454 my $end_time = time; 2455 $install_time = $end_time - $start_time; 2456 return; 2457 } 2458 2459 run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or 2460 dodie "Failed to install modules"; 2461 2462 my $modlib = "/lib/modules/$version"; 2463 my $modtar = "ktest-mods.tar.bz2"; 2464 2465 run_ssh "rm -rf $modlib" or 2466 dodie "failed to remove old mods: $modlib"; 2467 2468 # would be nice if scp -r did not follow symbolic links 2469 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 2470 dodie "making tarball"; 2471 2472 run_scp_mod "$tmpdir/$modtar", "/tmp" or 2473 dodie "failed to copy modules"; 2474 2475 unlink "$tmpdir/$modtar"; 2476 2477 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or 2478 dodie "failed to tar modules"; 2479 2480 run_ssh "rm -f /tmp/$modtar"; 2481 2482 do_post_install; 2483 2484 my $end_time = time; 2485 $install_time = $end_time - $start_time; 2486} 2487 2488sub get_version { 2489 # get the release name 2490 return if ($have_version); 2491 doprint "$make kernelrelease ... "; 2492 $version = `$make -s kernelrelease | tail -1`; 2493 if (!length($version)) { 2494 run_command "$make allnoconfig" or return 0; 2495 doprint "$make kernelrelease ... "; 2496 $version = `$make -s kernelrelease | tail -1`; 2497 } 2498 chomp($version); 2499 doprint "$version\n"; 2500 $have_version = 1; 2501} 2502 2503sub start_monitor_and_install { 2504 # Make sure the stable kernel has finished booting 2505 2506 # Install bisects, don't need console 2507 if (defined $console) { 2508 start_monitor; 2509 wait_for_monitor 5; 2510 end_monitor; 2511 } 2512 2513 get_grub_index; 2514 get_version; 2515 install; 2516 2517 start_monitor if (defined $console); 2518 return monitor; 2519} 2520 2521sub process_warning_line { 2522 my ($line) = @_; 2523 2524 chomp $line; 2525 2526 # for distcc heterogeneous systems, some compilers 2527 # do things differently causing warning lines 2528 # to be slightly different. This makes an attempt 2529 # to fixe those issues. 2530 2531 # chop off the index into the line 2532 # using distcc, some compilers give different indexes 2533 # depending on white space 2534 $line =~ s/^(\s*\S+:\d+:)\d+/$1/; 2535 2536 # Some compilers use UTF-8 extended for quotes and some don't. 2537 $line =~ s/$utf8_quote/'/g; 2538 2539 return $line; 2540} 2541 2542# Read buildlog and check against warnings file for any 2543# new warnings. 2544# 2545# Returns 1 if OK 2546# 0 otherwise 2547sub check_buildlog { 2548 my %warnings_list; 2549 2550 # Failed builds should not reboot the target 2551 my $save_no_reboot = $no_reboot; 2552 $no_reboot = 1; 2553 2554 if (defined($warnings_file) && -f $warnings_file) { 2555 open(IN, $warnings_file) or 2556 dodie "Error opening $warnings_file"; 2557 2558 while (<IN>) { 2559 if (/$check_build_re/) { 2560 my $warning = process_warning_line $_; 2561 2562 $warnings_list{$warning} = 1; 2563 } 2564 } 2565 close(IN); 2566 } 2567 2568 open(IN, $buildlog) or dodie "Can't open $buildlog"; 2569 while (<IN>) { 2570 if (/$check_build_re/) { 2571 my $warning = process_warning_line $_; 2572 2573 if (!defined $warnings_list{$warning}) { 2574 $warning_found++; 2575 2576 # If warnings file didn't exist, and WARNINGS_FILE exist, 2577 # then we fail on any warning! 2578 if (defined $warnings_file) { 2579 fail "New warning found (not in $warnings_file)\n$_\n"; 2580 $no_reboot = $save_no_reboot; 2581 return 0; 2582 } 2583 } 2584 } 2585 } 2586 $no_reboot = $save_no_reboot; 2587 close(IN); 2588} 2589 2590sub check_patch_buildlog { 2591 my ($patch) = @_; 2592 2593 my @files = `git show $patch | diffstat -l`; 2594 2595 foreach my $file (@files) { 2596 chomp $file; 2597 } 2598 2599 open(IN, "git show $patch |") or 2600 dodie "failed to show $patch"; 2601 while (<IN>) { 2602 if (m,^--- a/(.*),) { 2603 chomp $1; 2604 $files[$#files] = $1; 2605 } 2606 } 2607 close(IN); 2608 2609 open(IN, $buildlog) or dodie "Can't open $buildlog"; 2610 while (<IN>) { 2611 if (/^\s*(.*?):.*(warning|error)/) { 2612 my $err = $1; 2613 foreach my $file (@files) { 2614 my $fullpath = "$builddir/$file"; 2615 if ($file eq $err || $fullpath eq $err) { 2616 fail "$file built with warnings" and return 0; 2617 } 2618 } 2619 } 2620 } 2621 close(IN); 2622 2623 return 1; 2624} 2625 2626sub apply_min_config { 2627 my $outconfig = "$output_config.new"; 2628 2629 # Read the config file and remove anything that 2630 # is in the force_config hash (from minconfig and others) 2631 # then add the force config back. 2632 2633 doprint "Applying minimum configurations into $output_config.new\n"; 2634 2635 open (OUT, ">$outconfig") or 2636 dodie "Can't create $outconfig"; 2637 2638 if (-f $output_config) { 2639 open (IN, $output_config) or 2640 dodie "Failed to open $output_config"; 2641 while (<IN>) { 2642 if (/^(# )?(CONFIG_[^\s=]*)/) { 2643 next if (defined($force_config{$2})); 2644 } 2645 print OUT; 2646 } 2647 close IN; 2648 } 2649 foreach my $config (keys %force_config) { 2650 print OUT "$force_config{$config}\n"; 2651 } 2652 close OUT; 2653 2654 run_command "mv $outconfig $output_config"; 2655} 2656 2657sub make_oldconfig { 2658 2659 my @force_list = keys %force_config; 2660 2661 if ($#force_list >= 0) { 2662 apply_min_config; 2663 } 2664 2665 if (!run_command "$make olddefconfig") { 2666 # Perhaps olddefconfig doesn't exist in this version of the kernel 2667 # try oldnoconfig 2668 doprint "olddefconfig failed, trying make oldnoconfig\n"; 2669 if (!run_command "$make oldnoconfig") { 2670 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 2671 # try a yes '' | oldconfig 2672 run_command "yes '' | $make oldconfig" or 2673 dodie "failed make config oldconfig"; 2674 } 2675 } 2676} 2677 2678# read a config file and use this to force new configs. 2679sub load_force_config { 2680 my ($config) = @_; 2681 2682 doprint "Loading force configs from $config\n"; 2683 open(IN, $config) or 2684 dodie "failed to read $config"; 2685 while (<IN>) { 2686 chomp; 2687 if (/^(CONFIG[^\s=]*)(\s*=.*)/) { 2688 $force_config{$1} = $_; 2689 } elsif (/^# (CONFIG_\S*) is not set/) { 2690 $force_config{$1} = $_; 2691 } 2692 } 2693 close IN; 2694} 2695 2696sub build { 2697 my ($type) = @_; 2698 2699 unlink $buildlog; 2700 2701 my $start_time = time; 2702 2703 # Failed builds should not reboot the target 2704 my $save_no_reboot = $no_reboot; 2705 $no_reboot = 1; 2706 2707 # Calculate a new version from here. 2708 $have_version = 0; 2709 2710 if (defined($pre_build)) { 2711 my $ret = run_command $pre_build; 2712 if (!$ret && defined($pre_build_die) && 2713 $pre_build_die) { 2714 dodie "failed to pre_build\n"; 2715 } 2716 } 2717 2718 if ($type =~ /^useconfig:(.*)/) { 2719 run_command "cp $1 $output_config" or 2720 dodie "could not copy $1 to .config"; 2721 2722 $type = "oldconfig"; 2723 } 2724 2725 # old config can ask questions 2726 if ($type eq "oldconfig") { 2727 $type = "olddefconfig"; 2728 2729 # allow for empty configs 2730 run_command "touch $output_config"; 2731 2732 if (!$noclean) { 2733 run_command "mv $output_config $outputdir/config_temp" or 2734 dodie "moving .config"; 2735 2736 run_command "$make mrproper" or dodie "make mrproper"; 2737 2738 run_command "mv $outputdir/config_temp $output_config" or 2739 dodie "moving config_temp"; 2740 } 2741 } elsif (!$noclean) { 2742 unlink "$output_config"; 2743 run_command "$make mrproper" or 2744 dodie "make mrproper"; 2745 } 2746 2747 # add something to distinguish this build 2748 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 2749 print OUT "$localversion\n"; 2750 close(OUT); 2751 2752 if (defined($minconfig)) { 2753 load_force_config($minconfig); 2754 } 2755 2756 if ($type ne "olddefconfig") { 2757 run_command "$make $type" or 2758 dodie "failed make config"; 2759 } 2760 # Run old config regardless, to enforce min configurations 2761 make_oldconfig; 2762 2763 if (not defined($build_options)){ 2764 $build_options = ""; 2765 } 2766 my $build_ret = run_command "$make $build_options", $buildlog; 2767 2768 if (defined($post_build)) { 2769 # Because a post build may change the kernel version 2770 # do it now. 2771 get_version; 2772 my $ret = run_command $post_build; 2773 if (!$ret && defined($post_build_die) && 2774 $post_build_die) { 2775 dodie "failed to post_build\n"; 2776 } 2777 } 2778 2779 if (!$build_ret) { 2780 # bisect may need this to pass 2781 if ($in_bisect) { 2782 $no_reboot = $save_no_reboot; 2783 return 0; 2784 } 2785 fail "failed build" and return 0; 2786 } 2787 2788 $no_reboot = $save_no_reboot; 2789 2790 my $end_time = time; 2791 $build_time = $end_time - $start_time; 2792 2793 return 1; 2794} 2795 2796sub halt { 2797 if (!run_ssh "halt" or defined($power_off)) { 2798 if (defined($poweroff_after_halt)) { 2799 sleep $poweroff_after_halt; 2800 run_command "$power_off"; 2801 } 2802 } else { 2803 # nope? the zap it! 2804 run_command "$power_off"; 2805 } 2806} 2807 2808sub success { 2809 my ($i) = @_; 2810 2811 $successes++; 2812 2813 my $name = ""; 2814 2815 if (defined($test_name)) { 2816 $name = " ($test_name)"; 2817 } 2818 2819 print_times; 2820 2821 doprint "\n\n"; 2822 doprint "*******************************************\n"; 2823 doprint "*******************************************\n"; 2824 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; 2825 doprint "*******************************************\n"; 2826 doprint "*******************************************\n"; 2827 2828 if (defined($store_successes)) { 2829 save_logs "success", $store_successes; 2830 } 2831 2832 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 2833 doprint "Reboot and wait $sleep_time seconds\n"; 2834 reboot_to_good $sleep_time; 2835 } 2836 2837 if (defined($post_test)) { 2838 run_command $post_test; 2839 } 2840} 2841 2842sub answer_bisect { 2843 for (;;) { 2844 doprint "Pass, fail, or skip? [p/f/s]"; 2845 my $ans = <STDIN>; 2846 chomp $ans; 2847 if ($ans eq "p" || $ans eq "P") { 2848 return 1; 2849 } elsif ($ans eq "f" || $ans eq "F") { 2850 return 0; 2851 } elsif ($ans eq "s" || $ans eq "S") { 2852 return -1; 2853 } else { 2854 print "Please answer 'p', 'f', or 's'\n"; 2855 } 2856 } 2857} 2858 2859sub child_run_test { 2860 2861 # child should have no power 2862 $reboot_on_error = 0; 2863 $poweroff_on_error = 0; 2864 $die_on_failure = 1; 2865 2866 run_command $run_test, $testlog; 2867 2868 exit $run_command_status; 2869} 2870 2871sub child_finished { 2872 $child_done = 1; 2873} 2874 2875sub do_run_test { 2876 my $child_pid; 2877 my $child_exit; 2878 my $line; 2879 my $full_line; 2880 my $bug = 0; 2881 my $bug_ignored = 0; 2882 2883 my $start_time = time; 2884 2885 wait_for_monitor 1; 2886 2887 doprint "run test $run_test\n"; 2888 2889 $child_done = 0; 2890 2891 $SIG{CHLD} = qw(child_finished); 2892 2893 $child_pid = fork; 2894 2895 child_run_test if (!$child_pid); 2896 2897 $full_line = ""; 2898 2899 do { 2900 $line = wait_for_input($monitor_fp, 1); 2901 if (defined($line)) { 2902 2903 # we are not guaranteed to get a full line 2904 $full_line .= $line; 2905 doprint $line; 2906 2907 if ($full_line =~ /call trace:/i) { 2908 if ($ignore_errors) { 2909 $bug_ignored = 1; 2910 } else { 2911 $bug = 1; 2912 } 2913 } 2914 2915 if ($full_line =~ /Kernel panic -/) { 2916 $bug = 1; 2917 } 2918 2919 if ($line =~ /\n/) { 2920 $full_line = ""; 2921 } 2922 } 2923 } while (!$child_done && !$bug); 2924 2925 if (!$bug && $bug_ignored) { 2926 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 2927 } 2928 2929 if ($bug) { 2930 my $failure_start = time; 2931 my $now; 2932 do { 2933 $line = wait_for_input($monitor_fp, 1); 2934 if (defined($line)) { 2935 doprint $line; 2936 } 2937 $now = time; 2938 if ($now - $failure_start >= $stop_after_failure) { 2939 last; 2940 } 2941 } while (defined($line)); 2942 2943 doprint "Detected kernel crash!\n"; 2944 # kill the child with extreme prejudice 2945 kill 9, $child_pid; 2946 } 2947 2948 waitpid $child_pid, 0; 2949 $child_exit = $? >> 8; 2950 2951 my $end_time = time; 2952 $test_time = $end_time - $start_time; 2953 2954 if (!$bug && $in_bisect) { 2955 if (defined($bisect_ret_good)) { 2956 if ($child_exit == $bisect_ret_good) { 2957 return 1; 2958 } 2959 } 2960 if (defined($bisect_ret_skip)) { 2961 if ($child_exit == $bisect_ret_skip) { 2962 return -1; 2963 } 2964 } 2965 if (defined($bisect_ret_abort)) { 2966 if ($child_exit == $bisect_ret_abort) { 2967 fail "test abort" and return -2; 2968 } 2969 } 2970 if (defined($bisect_ret_bad)) { 2971 if ($child_exit == $bisect_ret_skip) { 2972 return 0; 2973 } 2974 } 2975 if (defined($bisect_ret_default)) { 2976 if ($bisect_ret_default eq "good") { 2977 return 1; 2978 } elsif ($bisect_ret_default eq "bad") { 2979 return 0; 2980 } elsif ($bisect_ret_default eq "skip") { 2981 return -1; 2982 } elsif ($bisect_ret_default eq "abort") { 2983 return -2; 2984 } else { 2985 fail "unknown default action: $bisect_ret_default" 2986 and return -2; 2987 } 2988 } 2989 } 2990 2991 if ($bug || $child_exit) { 2992 return 0 if $in_bisect; 2993 fail "test failed" and return 0; 2994 } 2995 return 1; 2996} 2997 2998sub run_git_bisect { 2999 my ($command) = @_; 3000 3001 doprint "$command ... "; 3002 3003 my $output = `$command 2>&1`; 3004 my $ret = $?; 3005 3006 logit $output; 3007 3008 if ($ret) { 3009 doprint "FAILED\n"; 3010 dodie "Failed to git bisect"; 3011 } 3012 3013 doprint "SUCCESS\n"; 3014 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 3015 doprint "$1 [$2]\n"; 3016 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 3017 $bisect_bad_commit = $1; 3018 doprint "Found bad commit... $1\n"; 3019 return 0; 3020 } else { 3021 # we already logged it, just print it now. 3022 print $output; 3023 } 3024 3025 return 1; 3026} 3027 3028sub bisect_reboot { 3029 doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 3030 reboot_to_good $bisect_sleep_time; 3031} 3032 3033# returns 1 on success, 0 on failure, -1 on skip 3034sub run_bisect_test { 3035 my ($type, $buildtype) = @_; 3036 3037 my $failed = 0; 3038 my $result; 3039 3040 $in_bisect = 1; 3041 3042 build $buildtype or $failed = 1; 3043 3044 if ($type ne "build") { 3045 if ($failed && $bisect_skip) { 3046 $in_bisect = 0; 3047 return -1; 3048 } 3049 dodie "Failed on build" if $failed; 3050 3051 # Now boot the box 3052 start_monitor_and_install or $failed = 1; 3053 3054 if ($type ne "boot") { 3055 if ($failed && $bisect_skip) { 3056 end_monitor; 3057 bisect_reboot; 3058 $in_bisect = 0; 3059 return -1; 3060 } 3061 dodie "Failed on boot" if $failed; 3062 3063 do_run_test or $failed = 1; 3064 } 3065 end_monitor; 3066 } 3067 3068 if ($failed) { 3069 $result = 0; 3070 } else { 3071 $result = 1; 3072 } 3073 3074 # reboot the box to a kernel we can ssh to 3075 if ($type ne "build") { 3076 bisect_reboot; 3077 } 3078 $in_bisect = 0; 3079 3080 return $result; 3081} 3082 3083sub run_bisect { 3084 my ($type) = @_; 3085 my $buildtype = "oldconfig"; 3086 3087 # We should have a minconfig to use? 3088 if (defined($minconfig)) { 3089 $buildtype = "useconfig:$minconfig"; 3090 } 3091 3092 # If the user sets bisect_tries to less than 1, then no tries 3093 # is a success. 3094 my $ret = 1; 3095 3096 # Still let the user manually decide that though. 3097 if ($bisect_tries < 1 && $bisect_manual) { 3098 $ret = answer_bisect; 3099 } 3100 3101 for (my $i = 0; $i < $bisect_tries; $i++) { 3102 if ($bisect_tries > 1) { 3103 my $t = $i + 1; 3104 doprint("Running bisect trial $t of $bisect_tries:\n"); 3105 } 3106 $ret = run_bisect_test $type, $buildtype; 3107 3108 if ($bisect_manual) { 3109 $ret = answer_bisect; 3110 } 3111 3112 last if (!$ret); 3113 } 3114 3115 # Are we looking for where it worked, not failed? 3116 if ($reverse_bisect && $ret >= 0) { 3117 $ret = !$ret; 3118 } 3119 3120 if ($ret > 0) { 3121 return "good"; 3122 } elsif ($ret == 0) { 3123 return "bad"; 3124 } elsif ($bisect_skip) { 3125 doprint "HIT A BAD COMMIT ... SKIPPING\n"; 3126 return "skip"; 3127 } 3128} 3129 3130sub update_bisect_replay { 3131 my $tmp_log = "$tmpdir/ktest_bisect_log"; 3132 run_command "git bisect log > $tmp_log" or 3133 dodie "can't create bisect log"; 3134 return $tmp_log; 3135} 3136 3137sub bisect { 3138 my ($i) = @_; 3139 3140 my $result; 3141 3142 dodie "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good)); 3143 dodie "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad)); 3144 dodie "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type)); 3145 3146 my $good = $bisect_good; 3147 my $bad = $bisect_bad; 3148 my $type = $bisect_type; 3149 my $start = $bisect_start; 3150 my $replay = $bisect_replay; 3151 my $start_files = $bisect_files; 3152 3153 if (defined($start_files)) { 3154 $start_files = " -- " . $start_files; 3155 } else { 3156 $start_files = ""; 3157 } 3158 3159 # convert to true sha1's 3160 $good = get_sha1($good); 3161 $bad = get_sha1($bad); 3162 3163 if (defined($bisect_reverse) && $bisect_reverse == 1) { 3164 doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 3165 $reverse_bisect = 1; 3166 } else { 3167 $reverse_bisect = 0; 3168 } 3169 3170 # Can't have a test without having a test to run 3171 if ($type eq "test" && !defined($run_test)) { 3172 $type = "boot"; 3173 } 3174 3175 # Check if a bisect was running 3176 my $bisect_start_file = "$builddir/.git/BISECT_START"; 3177 3178 my $check = $bisect_check; 3179 my $do_check = defined($check) && $check ne "0"; 3180 3181 if ( -f $bisect_start_file ) { 3182 print "Bisect in progress found\n"; 3183 if ($do_check) { 3184 print " If you say yes, then no checks of good or bad will be done\n"; 3185 } 3186 if (defined($replay)) { 3187 print "** BISECT_REPLAY is defined in config file **"; 3188 print " Ignore config option and perform new git bisect log?\n"; 3189 if (read_ync " (yes, no, or cancel) ") { 3190 $replay = update_bisect_replay; 3191 $do_check = 0; 3192 } 3193 } elsif (read_yn "read git log and continue?") { 3194 $replay = update_bisect_replay; 3195 $do_check = 0; 3196 } 3197 } 3198 3199 if ($do_check) { 3200 # get current HEAD 3201 my $head = get_sha1("HEAD"); 3202 3203 if ($check ne "good") { 3204 doprint "TESTING BISECT BAD [$bad]\n"; 3205 run_command "git checkout $bad" or 3206 dodie "Failed to checkout $bad"; 3207 3208 $result = run_bisect $type; 3209 3210 if ($result ne "bad") { 3211 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 3212 } 3213 } 3214 3215 if ($check ne "bad") { 3216 doprint "TESTING BISECT GOOD [$good]\n"; 3217 run_command "git checkout $good" or 3218 dodie "Failed to checkout $good"; 3219 3220 $result = run_bisect $type; 3221 3222 if ($result ne "good") { 3223 fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 3224 } 3225 } 3226 3227 # checkout where we started 3228 run_command "git checkout $head" or 3229 dodie "Failed to checkout $head"; 3230 } 3231 3232 run_command "git bisect start$start_files" or 3233 dodie "could not start bisect"; 3234 3235 if (defined($replay)) { 3236 run_command "git bisect replay $replay" or 3237 dodie "failed to run replay"; 3238 } else { 3239 run_command "git bisect good $good" or 3240 dodie "could not set bisect good to $good"; 3241 3242 run_git_bisect "git bisect bad $bad" or 3243 dodie "could not set bisect bad to $bad"; 3244 } 3245 3246 if (defined($start)) { 3247 run_command "git checkout $start" or 3248 dodie "failed to checkout $start"; 3249 } 3250 3251 my $test; 3252 do { 3253 $result = run_bisect $type; 3254 $test = run_git_bisect "git bisect $result"; 3255 print_times; 3256 } while ($test); 3257 3258 run_command "git bisect log" or 3259 dodie "could not capture git bisect log"; 3260 3261 run_command "git bisect reset" or 3262 dodie "could not reset git bisect"; 3263 3264 doprint "Bad commit was [$bisect_bad_commit]\n"; 3265 3266 success $i; 3267} 3268 3269sub assign_configs { 3270 my ($hash, $config) = @_; 3271 3272 doprint "Reading configs from $config\n"; 3273 3274 open (IN, $config) or 3275 dodie "Failed to read $config"; 3276 3277 while (<IN>) { 3278 chomp; 3279 if (/^((CONFIG\S*)=.*)/) { 3280 ${$hash}{$2} = $1; 3281 } elsif (/^(# (CONFIG\S*) is not set)/) { 3282 ${$hash}{$2} = $1; 3283 } 3284 } 3285 3286 close(IN); 3287} 3288 3289sub process_config_ignore { 3290 my ($config) = @_; 3291 3292 assign_configs \%config_ignore, $config; 3293} 3294 3295sub get_dependencies { 3296 my ($config) = @_; 3297 3298 my $arr = $dependency{$config}; 3299 if (!defined($arr)) { 3300 return (); 3301 } 3302 3303 my @deps = @{$arr}; 3304 3305 foreach my $dep (@{$arr}) { 3306 print "ADD DEP $dep\n"; 3307 @deps = (@deps, get_dependencies $dep); 3308 } 3309 3310 return @deps; 3311} 3312 3313sub save_config { 3314 my ($pc, $file) = @_; 3315 3316 my %configs = %{$pc}; 3317 3318 doprint "Saving configs into $file\n"; 3319 3320 open(OUT, ">$file") or dodie "Can not write to $file"; 3321 3322 foreach my $config (keys %configs) { 3323 print OUT "$configs{$config}\n"; 3324 } 3325 close(OUT); 3326} 3327 3328sub create_config { 3329 my ($name, $pc) = @_; 3330 3331 doprint "Creating old config from $name configs\n"; 3332 3333 save_config $pc, $output_config; 3334 3335 make_oldconfig; 3336} 3337 3338sub run_config_bisect_test { 3339 my ($type) = @_; 3340 3341 my $ret = run_bisect_test $type, "oldconfig"; 3342 3343 if ($bisect_manual) { 3344 $ret = answer_bisect; 3345 } 3346 3347 return $ret; 3348} 3349 3350sub config_bisect_end { 3351 my ($good, $bad) = @_; 3352 my $diffexec = "diff -u"; 3353 3354 if (-f "$builddir/scripts/diffconfig") { 3355 $diffexec = "$builddir/scripts/diffconfig"; 3356 } 3357 doprint "\n\n***************************************\n"; 3358 doprint "No more config bisecting possible.\n"; 3359 run_command "$diffexec $good $bad", 1; 3360 doprint "***************************************\n\n"; 3361} 3362 3363sub run_config_bisect { 3364 my ($good, $bad, $last_result) = @_; 3365 my $reset = ""; 3366 my $cmd; 3367 my $ret; 3368 3369 if (!length($last_result)) { 3370 $reset = "-r"; 3371 } 3372 run_command "$config_bisect_exec $reset -b $outputdir $good $bad $last_result", 1; 3373 3374 # config-bisect returns: 3375 # 0 if there is more to bisect 3376 # 1 for finding a good config 3377 # 2 if it can not find any more configs 3378 # -1 (255) on error 3379 if ($run_command_status) { 3380 return $run_command_status; 3381 } 3382 3383 $ret = run_config_bisect_test $config_bisect_type; 3384 if ($ret) { 3385 doprint "NEW GOOD CONFIG ($pass)\n"; 3386 system("cp $output_config $tmpdir/good_config.tmp.$pass"); 3387 $pass++; 3388 # Return 3 for good config 3389 return 3; 3390 } else { 3391 doprint "NEW BAD CONFIG ($pass)\n"; 3392 system("cp $output_config $tmpdir/bad_config.tmp.$pass"); 3393 $pass++; 3394 # Return 4 for bad config 3395 return 4; 3396 } 3397} 3398 3399sub config_bisect { 3400 my ($i) = @_; 3401 3402 my $good_config; 3403 my $bad_config; 3404 3405 my $type = $config_bisect_type; 3406 my $ret; 3407 3408 $bad_config = $config_bisect; 3409 3410 if (defined($config_bisect_good)) { 3411 $good_config = $config_bisect_good; 3412 } elsif (defined($minconfig)) { 3413 $good_config = $minconfig; 3414 } else { 3415 doprint "No config specified, checking if defconfig works"; 3416 $ret = run_bisect_test $type, "defconfig"; 3417 if (!$ret) { 3418 fail "Have no good config to compare with, please set CONFIG_BISECT_GOOD"; 3419 return 1; 3420 } 3421 $good_config = $output_config; 3422 } 3423 3424 if (!defined($config_bisect_exec)) { 3425 # First check the location that ktest.pl ran 3426 my @locations = ( 3427 "$pwd/config-bisect.pl", 3428 "$dirname/config-bisect.pl", 3429 "$builddir/tools/testing/ktest/config-bisect.pl", 3430 undef ); 3431 foreach my $loc (@locations) { 3432 doprint "loc = $loc\n"; 3433 $config_bisect_exec = $loc; 3434 last if (defined($config_bisect_exec && -x $config_bisect_exec)); 3435 } 3436 if (!defined($config_bisect_exec)) { 3437 fail "Could not find an executable config-bisect.pl\n", 3438 " Set CONFIG_BISECT_EXEC to point to config-bisect.pl"; 3439 return 1; 3440 } 3441 } 3442 3443 # we don't want min configs to cause issues here. 3444 doprint "Disabling 'MIN_CONFIG' for this test\n"; 3445 undef $minconfig; 3446 3447 my %good_configs; 3448 my %bad_configs; 3449 my %tmp_configs; 3450 3451 if (-f "$tmpdir/good_config.tmp" || -f "$tmpdir/bad_config.tmp") { 3452 if (read_yn "Interrupted config-bisect. Continue (n - will start new)?") { 3453 if (-f "$tmpdir/good_config.tmp") { 3454 $good_config = "$tmpdir/good_config.tmp"; 3455 } else { 3456 $good_config = "$tmpdir/good_config"; 3457 } 3458 if (-f "$tmpdir/bad_config.tmp") { 3459 $bad_config = "$tmpdir/bad_config.tmp"; 3460 } else { 3461 $bad_config = "$tmpdir/bad_config"; 3462 } 3463 } 3464 } 3465 doprint "Run good configs through make oldconfig\n"; 3466 assign_configs \%tmp_configs, $good_config; 3467 create_config "$good_config", \%tmp_configs; 3468 $good_config = "$tmpdir/good_config"; 3469 system("cp $output_config $good_config") == 0 or dodie "cp good config"; 3470 3471 doprint "Run bad configs through make oldconfig\n"; 3472 assign_configs \%tmp_configs, $bad_config; 3473 create_config "$bad_config", \%tmp_configs; 3474 $bad_config = "$tmpdir/bad_config"; 3475 system("cp $output_config $bad_config") == 0 or dodie "cp bad config"; 3476 3477 if (defined($config_bisect_check) && $config_bisect_check ne "0") { 3478 if ($config_bisect_check ne "good") { 3479 doprint "Testing bad config\n"; 3480 3481 $ret = run_bisect_test $type, "useconfig:$bad_config"; 3482 if ($ret) { 3483 fail "Bad config succeeded when expected to fail!"; 3484 return 0; 3485 } 3486 } 3487 if ($config_bisect_check ne "bad") { 3488 doprint "Testing good config\n"; 3489 3490 $ret = run_bisect_test $type, "useconfig:$good_config"; 3491 if (!$ret) { 3492 fail "Good config failed when expected to succeed!"; 3493 return 0; 3494 } 3495 } 3496 } 3497 3498 my $last_run = ""; 3499 3500 do { 3501 $ret = run_config_bisect $good_config, $bad_config, $last_run; 3502 if ($ret == 3) { 3503 $last_run = "good"; 3504 } elsif ($ret == 4) { 3505 $last_run = "bad"; 3506 } 3507 print_times; 3508 } while ($ret == 3 || $ret == 4); 3509 3510 if ($ret == 2) { 3511 config_bisect_end "$good_config.tmp", "$bad_config.tmp"; 3512 } 3513 3514 return $ret if ($ret < 0); 3515 3516 success $i; 3517} 3518 3519sub patchcheck_reboot { 3520 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 3521 reboot_to_good $patchcheck_sleep_time; 3522} 3523 3524sub patchcheck { 3525 my ($i) = @_; 3526 3527 dodie "PATCHCHECK_START[$i] not defined\n" 3528 if (!defined($patchcheck_start)); 3529 dodie "PATCHCHECK_TYPE[$i] not defined\n" 3530 if (!defined($patchcheck_type)); 3531 3532 my $start = $patchcheck_start; 3533 3534 my $cherry = $patchcheck_cherry; 3535 if (!defined($cherry)) { 3536 $cherry = 0; 3537 } 3538 3539 my $end = "HEAD"; 3540 if (defined($patchcheck_end)) { 3541 $end = $patchcheck_end; 3542 } elsif ($cherry) { 3543 dodie "PATCHCHECK_END must be defined with PATCHCHECK_CHERRY\n"; 3544 } 3545 3546 # Get the true sha1's since we can use things like HEAD~3 3547 $start = get_sha1($start); 3548 $end = get_sha1($end); 3549 3550 my $type = $patchcheck_type; 3551 3552 # Can't have a test without having a test to run 3553 if ($type eq "test" && !defined($run_test)) { 3554 $type = "boot"; 3555 } 3556 3557 if ($cherry) { 3558 open (IN, "git cherry -v $start $end|") or 3559 dodie "could not get git list"; 3560 } else { 3561 open (IN, "git log --pretty=oneline $end|") or 3562 dodie "could not get git list"; 3563 } 3564 3565 my @list; 3566 3567 while (<IN>) { 3568 chomp; 3569 # git cherry adds a '+' we want to remove 3570 s/^\+ //; 3571 $list[$#list+1] = $_; 3572 last if (/^$start/); 3573 } 3574 close(IN); 3575 3576 if (!$cherry) { 3577 if ($list[$#list] !~ /^$start/) { 3578 fail "SHA1 $start not found"; 3579 } 3580 3581 # go backwards in the list 3582 @list = reverse @list; 3583 } 3584 3585 my %skip_list; 3586 my $will_skip = 0; 3587 3588 if (defined($patchcheck_skip)) { 3589 foreach my $s (split /\s+/, $patchcheck_skip) { 3590 $s = `git log --pretty=oneline $s~1..$s`; 3591 $s =~ s/^(\S+).*/$1/; 3592 chomp $s; 3593 $skip_list{$s} = 1; 3594 $will_skip++; 3595 } 3596 } 3597 3598 doprint("Going to test the following commits:\n"); 3599 foreach my $l (@list) { 3600 my $sha1 = $l; 3601 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 3602 next if (defined($skip_list{$sha1})); 3603 doprint "$l\n"; 3604 } 3605 3606 if ($will_skip) { 3607 doprint("\nSkipping the following commits:\n"); 3608 foreach my $l (@list) { 3609 my $sha1 = $l; 3610 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 3611 next if (!defined($skip_list{$sha1})); 3612 doprint "$l\n"; 3613 } 3614 } 3615 3616 my $save_clean = $noclean; 3617 my %ignored_warnings; 3618 3619 if (defined($ignore_warnings)) { 3620 foreach my $sha1 (split /\s+/, $ignore_warnings) { 3621 $ignored_warnings{$sha1} = 1; 3622 } 3623 } 3624 3625 $in_patchcheck = 1; 3626 foreach my $item (@list) { 3627 my $sha1 = $item; 3628 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 3629 3630 if (defined($skip_list{$sha1})) { 3631 doprint "\nSkipping \"$item\"\n\n"; 3632 next; 3633 } 3634 3635 doprint "\nProcessing commit \"$item\"\n\n"; 3636 3637 run_command "git checkout $sha1" or 3638 dodie "Failed to checkout $sha1"; 3639 3640 # only clean on the first and last patch 3641 if ($item eq $list[0] || 3642 $item eq $list[$#list]) { 3643 $noclean = $save_clean; 3644 } else { 3645 $noclean = 1; 3646 } 3647 3648 if (defined($minconfig)) { 3649 build "useconfig:$minconfig" or return 0; 3650 } else { 3651 # ?? no config to use? 3652 build "oldconfig" or return 0; 3653 } 3654 3655 # No need to do per patch checking if warnings file exists 3656 if (!defined($warnings_file) && !defined($ignored_warnings{$sha1})) { 3657 check_patch_buildlog $sha1 or return 0; 3658 } 3659 3660 check_buildlog or return 0; 3661 3662 next if ($type eq "build"); 3663 3664 my $failed = 0; 3665 3666 start_monitor_and_install or $failed = 1; 3667 3668 if (!$failed && $type ne "boot"){ 3669 do_run_test or $failed = 1; 3670 } 3671 end_monitor; 3672 if ($failed) { 3673 print_times; 3674 return 0; 3675 } 3676 patchcheck_reboot; 3677 print_times; 3678 } 3679 $in_patchcheck = 0; 3680 success $i; 3681 3682 return 1; 3683} 3684 3685sub add_dep { 3686 # $config depends on $dep 3687 my ($config, $dep) = @_; 3688 3689 if (defined($depends{$config})) { 3690 $depends{$config} .= " " . $dep; 3691 } else { 3692 $depends{$config} = $dep; 3693 } 3694 3695 # record the number of configs depending on $dep 3696 if (defined $depcount{$dep}) { 3697 $depcount{$dep}++; 3698 } else { 3699 $depcount{$dep} = 1; 3700 } 3701} 3702 3703# taken from streamline_config.pl 3704sub read_kconfig { 3705 my ($kconfig) = @_; 3706 3707 my $state = "NONE"; 3708 my $config; 3709 my @kconfigs; 3710 3711 my $cont = 0; 3712 my $line; 3713 3714 if (! -f $kconfig) { 3715 doprint "file $kconfig does not exist, skipping\n"; 3716 return; 3717 } 3718 3719 open(KIN, "$kconfig") 3720 or dodie "Can't open $kconfig"; 3721 while (<KIN>) { 3722 chomp; 3723 3724 # Make sure that lines ending with \ continue 3725 if ($cont) { 3726 $_ = $line . " " . $_; 3727 } 3728 3729 if (s/\\$//) { 3730 $cont = 1; 3731 $line = $_; 3732 next; 3733 } 3734 3735 $cont = 0; 3736 3737 # collect any Kconfig sources 3738 if (/^source\s*"(.*)"/) { 3739 $kconfigs[$#kconfigs+1] = $1; 3740 } 3741 3742 # configs found 3743 if (/^\s*(menu)?config\s+(\S+)\s*$/) { 3744 $state = "NEW"; 3745 $config = $2; 3746 3747 for (my $i = 0; $i < $iflevel; $i++) { 3748 add_dep $config, $ifdeps[$i]; 3749 } 3750 3751 # collect the depends for the config 3752 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { 3753 3754 add_dep $config, $1; 3755 3756 # Get the configs that select this config 3757 } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) { 3758 3759 # selected by depends on config 3760 add_dep $1, $config; 3761 3762 # Check for if statements 3763 } elsif (/^if\s+(.*\S)\s*$/) { 3764 my $deps = $1; 3765 # remove beginning and ending non text 3766 $deps =~ s/^[^a-zA-Z0-9_]*//; 3767 $deps =~ s/[^a-zA-Z0-9_]*$//; 3768 3769 my @deps = split /[^a-zA-Z0-9_]+/, $deps; 3770 3771 $ifdeps[$iflevel++] = join ':', @deps; 3772 3773 } elsif (/^endif/) { 3774 3775 $iflevel-- if ($iflevel); 3776 3777 # stop on "help" 3778 } elsif (/^\s*help\s*$/) { 3779 $state = "NONE"; 3780 } 3781 } 3782 close(KIN); 3783 3784 # read in any configs that were found. 3785 foreach $kconfig (@kconfigs) { 3786 if (!defined($read_kconfigs{$kconfig})) { 3787 $read_kconfigs{$kconfig} = 1; 3788 read_kconfig("$builddir/$kconfig"); 3789 } 3790 } 3791} 3792 3793sub read_depends { 3794 # find out which arch this is by the kconfig file 3795 open (IN, $output_config) or 3796 dodie "Failed to read $output_config"; 3797 my $arch; 3798 while (<IN>) { 3799 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) { 3800 $arch = $1; 3801 last; 3802 } 3803 } 3804 close IN; 3805 3806 if (!defined($arch)) { 3807 doprint "Could not find arch from config file\n"; 3808 doprint "no dependencies used\n"; 3809 return; 3810 } 3811 3812 # arch is really the subarch, we need to know 3813 # what directory to look at. 3814 if ($arch eq "i386" || $arch eq "x86_64") { 3815 $arch = "x86"; 3816 } 3817 3818 my $kconfig = "$builddir/arch/$arch/Kconfig"; 3819 3820 if (! -f $kconfig && $arch =~ /\d$/) { 3821 my $orig = $arch; 3822 # some subarchs have numbers, truncate them 3823 $arch =~ s/\d*$//; 3824 $kconfig = "$builddir/arch/$arch/Kconfig"; 3825 if (! -f $kconfig) { 3826 doprint "No idea what arch dir $orig is for\n"; 3827 doprint "no dependencies used\n"; 3828 return; 3829 } 3830 } 3831 3832 read_kconfig($kconfig); 3833} 3834 3835sub make_new_config { 3836 my @configs = @_; 3837 3838 open (OUT, ">$output_config") 3839 or dodie "Failed to write $output_config"; 3840 3841 foreach my $config (@configs) { 3842 print OUT "$config\n"; 3843 } 3844 close OUT; 3845} 3846 3847sub chomp_config { 3848 my ($config) = @_; 3849 3850 $config =~ s/CONFIG_//; 3851 3852 return $config; 3853} 3854 3855sub get_depends { 3856 my ($dep) = @_; 3857 3858 my $kconfig = chomp_config $dep; 3859 3860 $dep = $depends{"$kconfig"}; 3861 3862 # the dep string we have saves the dependencies as they 3863 # were found, including expressions like ! && ||. We 3864 # want to split this out into just an array of configs. 3865 3866 my $valid = "A-Za-z_0-9"; 3867 3868 my @configs; 3869 3870 while ($dep =~ /[$valid]/) { 3871 if ($dep =~ /^[^$valid]*([$valid]+)/) { 3872 my $conf = "CONFIG_" . $1; 3873 3874 $configs[$#configs + 1] = $conf; 3875 3876 $dep =~ s/^[^$valid]*[$valid]+//; 3877 } else { 3878 dodie "this should never happen"; 3879 } 3880 } 3881 3882 return @configs; 3883} 3884 3885sub test_this_config { 3886 my ($config) = @_; 3887 3888 my $found; 3889 3890 # if we already processed this config, skip it 3891 if (defined($processed_configs{$config})) { 3892 return undef; 3893 } 3894 $processed_configs{$config} = 1; 3895 3896 # if this config failed during this round, skip it 3897 if (defined($nochange_config{$config})) { 3898 return undef; 3899 } 3900 3901 my $kconfig = chomp_config $config; 3902 3903 # Test dependencies first 3904 if (defined($depends{"$kconfig"})) { 3905 my @parents = get_depends $config; 3906 foreach my $parent (@parents) { 3907 # if the parent is in the min config, check it first 3908 next if (!defined($min_configs{$parent})); 3909 $found = test_this_config($parent); 3910 if (defined($found)) { 3911 return $found; 3912 } 3913 } 3914 } 3915 3916 # Remove this config from the list of configs 3917 # do a make olddefconfig and then read the resulting 3918 # .config to make sure it is missing the config that 3919 # we had before 3920 my %configs = %min_configs; 3921 $configs{$config} = "# $config is not set"; 3922 make_new_config ((values %configs), (values %keep_configs)); 3923 make_oldconfig; 3924 delete $configs{$config}; 3925 undef %configs; 3926 assign_configs \%configs, $output_config; 3927 3928 if (!defined($configs{$config}) || $configs{$config} =~ /^#/) { 3929 return $config; 3930 } 3931 3932 doprint "disabling config $config did not change .config\n"; 3933 3934 $nochange_config{$config} = 1; 3935 3936 return undef; 3937} 3938 3939sub make_min_config { 3940 my ($i) = @_; 3941 3942 my $type = $minconfig_type; 3943 if ($type ne "boot" && $type ne "test") { 3944 fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" . 3945 " make_min_config works only with 'boot' and 'test'\n" and return; 3946 } 3947 3948 if (!defined($output_minconfig)) { 3949 fail "OUTPUT_MIN_CONFIG not defined" and return; 3950 } 3951 3952 # If output_minconfig exists, and the start_minconfig 3953 # came from min_config, than ask if we should use 3954 # that instead. 3955 if (-f $output_minconfig && !$start_minconfig_defined) { 3956 print "$output_minconfig exists\n"; 3957 if (!defined($use_output_minconfig)) { 3958 if (read_yn " Use it as minconfig?") { 3959 $start_minconfig = $output_minconfig; 3960 } 3961 } elsif ($use_output_minconfig > 0) { 3962 doprint "Using $output_minconfig as MIN_CONFIG\n"; 3963 $start_minconfig = $output_minconfig; 3964 } else { 3965 doprint "Set to still use MIN_CONFIG as starting point\n"; 3966 } 3967 } 3968 3969 if (!defined($start_minconfig)) { 3970 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; 3971 } 3972 3973 my $temp_config = "$tmpdir/temp_config"; 3974 3975 # First things first. We build an allnoconfig to find 3976 # out what the defaults are that we can't touch. 3977 # Some are selections, but we really can't handle selections. 3978 3979 my $save_minconfig = $minconfig; 3980 undef $minconfig; 3981 3982 run_command "$make allnoconfig" or return 0; 3983 3984 read_depends; 3985 3986 process_config_ignore $output_config; 3987 3988 undef %save_configs; 3989 undef %min_configs; 3990 3991 if (defined($ignore_config)) { 3992 # make sure the file exists 3993 `touch $ignore_config`; 3994 assign_configs \%save_configs, $ignore_config; 3995 } 3996 3997 %keep_configs = %save_configs; 3998 3999 doprint "Load initial configs from $start_minconfig\n"; 4000 4001 # Look at the current min configs, and save off all the 4002 # ones that were set via the allnoconfig 4003 assign_configs \%min_configs, $start_minconfig; 4004 4005 my @config_keys = keys %min_configs; 4006 4007 # All configs need a depcount 4008 foreach my $config (@config_keys) { 4009 my $kconfig = chomp_config $config; 4010 if (!defined $depcount{$kconfig}) { 4011 $depcount{$kconfig} = 0; 4012 } 4013 } 4014 4015 # Remove anything that was set by the make allnoconfig 4016 # we shouldn't need them as they get set for us anyway. 4017 foreach my $config (@config_keys) { 4018 # Remove anything in the ignore_config 4019 if (defined($keep_configs{$config})) { 4020 my $file = $ignore_config; 4021 $file =~ s,.*/(.*?)$,$1,; 4022 doprint "$config set by $file ... ignored\n"; 4023 delete $min_configs{$config}; 4024 next; 4025 } 4026 # But make sure the settings are the same. If a min config 4027 # sets a selection, we do not want to get rid of it if 4028 # it is not the same as what we have. Just move it into 4029 # the keep configs. 4030 if (defined($config_ignore{$config})) { 4031 if ($config_ignore{$config} ne $min_configs{$config}) { 4032 doprint "$config is in allnoconfig as '$config_ignore{$config}'"; 4033 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n"; 4034 $keep_configs{$config} = $min_configs{$config}; 4035 } else { 4036 doprint "$config set by allnoconfig ... ignored\n"; 4037 } 4038 delete $min_configs{$config}; 4039 } 4040 } 4041 4042 my $done = 0; 4043 my $take_two = 0; 4044 4045 while (!$done) { 4046 my $config; 4047 my $found; 4048 4049 # Now disable each config one by one and do a make oldconfig 4050 # till we find a config that changes our list. 4051 4052 my @test_configs = keys %min_configs; 4053 4054 # Sort keys by who is most dependent on 4055 @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} } 4056 @test_configs ; 4057 4058 # Put configs that did not modify the config at the end. 4059 my $reset = 1; 4060 for (my $i = 0; $i < $#test_configs; $i++) { 4061 if (!defined($nochange_config{$test_configs[0]})) { 4062 $reset = 0; 4063 last; 4064 } 4065 # This config didn't change the .config last time. 4066 # Place it at the end 4067 my $config = shift @test_configs; 4068 push @test_configs, $config; 4069 } 4070 4071 # if every test config has failed to modify the .config file 4072 # in the past, then reset and start over. 4073 if ($reset) { 4074 undef %nochange_config; 4075 } 4076 4077 undef %processed_configs; 4078 4079 foreach my $config (@test_configs) { 4080 4081 $found = test_this_config $config; 4082 4083 last if (defined($found)); 4084 4085 # oh well, try another config 4086 } 4087 4088 if (!defined($found)) { 4089 # we could have failed due to the nochange_config hash 4090 # reset and try again 4091 if (!$take_two) { 4092 undef %nochange_config; 4093 $take_two = 1; 4094 next; 4095 } 4096 doprint "No more configs found that we can disable\n"; 4097 $done = 1; 4098 last; 4099 } 4100 $take_two = 0; 4101 4102 $config = $found; 4103 4104 doprint "Test with $config disabled\n"; 4105 4106 # set in_bisect to keep build and monitor from dieing 4107 $in_bisect = 1; 4108 4109 my $failed = 0; 4110 build "oldconfig" or $failed = 1; 4111 if (!$failed) { 4112 start_monitor_and_install or $failed = 1; 4113 4114 if ($type eq "test" && !$failed) { 4115 do_run_test or $failed = 1; 4116 } 4117 4118 end_monitor; 4119 } 4120 4121 $in_bisect = 0; 4122 4123 if ($failed) { 4124 doprint "$min_configs{$config} is needed to boot the box... keeping\n"; 4125 # this config is needed, add it to the ignore list. 4126 $keep_configs{$config} = $min_configs{$config}; 4127 $save_configs{$config} = $min_configs{$config}; 4128 delete $min_configs{$config}; 4129 4130 # update new ignore configs 4131 if (defined($ignore_config)) { 4132 open (OUT, ">$temp_config") or 4133 dodie "Can't write to $temp_config"; 4134 foreach my $config (keys %save_configs) { 4135 print OUT "$save_configs{$config}\n"; 4136 } 4137 close OUT; 4138 run_command "mv $temp_config $ignore_config" or 4139 dodie "failed to copy update to $ignore_config"; 4140 } 4141 4142 } else { 4143 # We booted without this config, remove it from the minconfigs. 4144 doprint "$config is not needed, disabling\n"; 4145 4146 delete $min_configs{$config}; 4147 4148 # Also disable anything that is not enabled in this config 4149 my %configs; 4150 assign_configs \%configs, $output_config; 4151 my @config_keys = keys %min_configs; 4152 foreach my $config (@config_keys) { 4153 if (!defined($configs{$config})) { 4154 doprint "$config is not set, disabling\n"; 4155 delete $min_configs{$config}; 4156 } 4157 } 4158 4159 # Save off all the current mandatory configs 4160 open (OUT, ">$temp_config") or 4161 dodie "Can't write to $temp_config"; 4162 foreach my $config (keys %keep_configs) { 4163 print OUT "$keep_configs{$config}\n"; 4164 } 4165 foreach my $config (keys %min_configs) { 4166 print OUT "$min_configs{$config}\n"; 4167 } 4168 close OUT; 4169 4170 run_command "mv $temp_config $output_minconfig" or 4171 dodie "failed to copy update to $output_minconfig"; 4172 } 4173 4174 doprint "Reboot and wait $sleep_time seconds\n"; 4175 reboot_to_good $sleep_time; 4176 } 4177 4178 success $i; 4179 return 1; 4180} 4181 4182sub make_warnings_file { 4183 my ($i) = @_; 4184 4185 if (!defined($warnings_file)) { 4186 dodie "Must define WARNINGS_FILE for make_warnings_file test"; 4187 } 4188 4189 if ($build_type eq "nobuild") { 4190 dodie "BUILD_TYPE can not be 'nobuild' for make_warnings_file test"; 4191 } 4192 4193 build $build_type or dodie "Failed to build"; 4194 4195 open(OUT, ">$warnings_file") or dodie "Can't create $warnings_file"; 4196 4197 open(IN, $buildlog) or dodie "Can't open $buildlog"; 4198 while (<IN>) { 4199 # Some compilers use UTF-8 extended for quotes 4200 # for distcc heterogeneous systems, this causes issues 4201 s/$utf8_quote/'/g; 4202 4203 if (/$check_build_re/) { 4204 print OUT; 4205 } 4206 } 4207 close(IN); 4208 4209 close(OUT); 4210 4211 success $i; 4212} 4213 4214sub option_defined { 4215 my ($option) = @_; 4216 4217 if (defined($opt{$option}) && $opt{$option} !~ /^\s*$/) { 4218 return 1; 4219 } 4220 4221 return 0; 4222} 4223 4224sub __set_test_option { 4225 my ($name, $i) = @_; 4226 4227 my $option = "$name\[$i\]"; 4228 4229 if (exists($opt{$option})) { 4230 return undef if (!option_defined($option)); 4231 return $opt{$option}; 4232 } 4233 4234 foreach my $test (keys %repeat_tests) { 4235 if ($i >= $test && 4236 $i < $test + $repeat_tests{$test}) { 4237 $option = "$name\[$test\]"; 4238 if (exists($opt{$option})) { 4239 return undef if (!option_defined($option)); 4240 return $opt{$option}; 4241 } 4242 } 4243 } 4244 4245 if (option_defined($name)) { 4246 return $opt{$name}; 4247 } 4248 4249 return undef; 4250} 4251 4252sub set_test_option { 4253 my ($name, $i) = @_; 4254 4255 my $option = __set_test_option($name, $i); 4256 return $option if (!defined($option)); 4257 4258 return eval_option($name, $option, $i); 4259} 4260 4261sub print_test_preamble { 4262 my ($resolved) = @_; 4263 4264 doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 4265 4266 for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 4267 4268 if (!$i) { 4269 doprint "DEFAULT OPTIONS:\n"; 4270 } else { 4271 doprint "\nTEST $i OPTIONS"; 4272 if (defined($repeat_tests{$i})) { 4273 $repeat = $repeat_tests{$i}; 4274 doprint " ITERATE $repeat"; 4275 } 4276 doprint "\n"; 4277 } 4278 4279 foreach my $option (sort keys %opt) { 4280 my $value; 4281 4282 if ($option =~ /\[(\d+)\]$/) { 4283 next if ($i != $1); 4284 4285 if ($resolved) { 4286 my $name = $option; 4287 $name =~ s/\[\d+\]$//; 4288 $value = set_test_option($name, $i); 4289 } else { 4290 $value = $opt{$option}; 4291 } 4292 } else { 4293 next if ($i); 4294 4295 if ($resolved) { 4296 $value = set_test_option($option, 0); 4297 } else { 4298 $value = $opt{$option}; 4299 } 4300 } 4301 4302 $value = "" if (!defined($value)); 4303 doprint "$option = $value\n"; 4304 } 4305 } 4306} 4307 4308sub find_mailer { 4309 my ($mailer) = @_; 4310 4311 my @paths = split /:/, $ENV{PATH}; 4312 4313 # sendmail is usually in /usr/sbin 4314 $paths[$#paths + 1] = "/usr/sbin"; 4315 4316 foreach my $path (@paths) { 4317 if (-x "$path/$mailer") { 4318 return $path; 4319 } 4320 } 4321 4322 return undef; 4323} 4324 4325sub do_send_mail { 4326 my ($subject, $message, $file) = @_; 4327 4328 if (!defined($mail_path)) { 4329 # find the mailer 4330 $mail_path = find_mailer $mailer; 4331 if (!defined($mail_path)) { 4332 die "\nCan not find $mailer in PATH\n"; 4333 } 4334 } 4335 4336 my $header_file = "$tmpdir/header"; 4337 open (HEAD, ">$header_file") or die "Can not create $header_file\n"; 4338 print HEAD "To: $mailto\n"; 4339 print HEAD "Subject: $subject\n\n"; 4340 print HEAD "$message\n"; 4341 close HEAD; 4342 4343 if (!defined($mail_command)) { 4344 if ($mailer eq "mail" || $mailer eq "mailx") { 4345 $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO"; 4346 } elsif ($mailer eq "sendmail" ) { 4347 $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -t \$MAILTO"; 4348 } else { 4349 die "\nYour mailer: $mailer is not supported.\n"; 4350 } 4351 } 4352 4353 if (defined($file)) { 4354 $mail_command =~ s/\$BODY_FILE/$file/g; 4355 } else { 4356 $mail_command =~ s/\$BODY_FILE//g; 4357 } 4358 4359 $mail_command =~ s/\$HEADER_FILE/$header_file/g; 4360 $mail_command =~ s/\$MAILER/$mailer/g; 4361 $mail_command =~ s/\$MAIL_PATH/$mail_path/g; 4362 $mail_command =~ s/\$MAILTO/$mailto/g; 4363 $mail_command =~ s/\$SUBJECT/$subject/g; 4364 $mail_command =~ s/\$MESSAGE/$message/g; 4365 4366 my $ret = run_command $mail_command; 4367 if (!$ret && defined($file)) { 4368 # try again without the file 4369 $message .= "\n\n*** FAILED TO SEND LOG ***\n\n"; 4370 do_send_email($subject, $message); 4371 } 4372} 4373 4374sub send_email { 4375 if (defined($mailto)) { 4376 if (!defined($mailer)) { 4377 doprint "No email sent: email or mailer not specified in config.\n"; 4378 return; 4379 } 4380 do_send_mail @_; 4381 } 4382} 4383 4384sub cancel_test { 4385 if ($monitor_cnt) { 4386 end_monitor; 4387 } 4388 if ($email_when_canceled) { 4389 my $name = get_test_name; 4390 send_email("KTEST: Your [$name] test was cancelled", 4391 "Your test started at $script_start_time was cancelled: sig int"); 4392 } 4393 run_post_ktest; 4394 die "\nCaught Sig Int, test interrupted: $!\n" 4395} 4396 4397sub die_usage { 4398 die << "EOF" 4399ktest.pl version: $VERSION 4400 usage: ktest.pl [options] [config-file] 4401 [options]: 4402 -D value: Where value can act as an option override. 4403 -D BUILD_NOCLEAN=1 4404 Sets global BUILD_NOCLEAN to 1 4405 -D TEST_TYPE[2]=build 4406 Sets TEST_TYPE of test 2 to "build" 4407 --dry-run 4408 Print resolved test options and exit without running tests. 4409 4410 It can also override all temp variables. 4411 -D USE_TEMP_DIR:=1 4412 Will override all variables that use 4413 "USE_TEMP_DIR=" 4414 4415EOF 4416; 4417} 4418 4419while ( $#ARGV >= 0 ) { 4420 if ( $ARGV[0] eq "-D" ) { 4421 shift; 4422 die_usage if ($#ARGV < 1); 4423 my $val = shift; 4424 4425 if ($val =~ m/(.*?):=(.*)$/) { 4426 set_variable($1, $2, 1); 4427 } else { 4428 $command_vars[$#command_vars + 1] = $val; 4429 } 4430 4431 } elsif ( $ARGV[0] =~ m/^-D(.*)/) { 4432 my $val = $1; 4433 shift; 4434 4435 if ($val =~ m/(.*?):=(.*)$/) { 4436 set_variable($1, $2, 1); 4437 } else { 4438 $command_vars[$#command_vars + 1] = $val; 4439 } 4440 } elsif ( $ARGV[0] eq "--dry-run" ) { 4441 $dry_run = 1; 4442 shift; 4443 } elsif ( $ARGV[0] eq "-h" ) { 4444 die_usage; 4445 } else { 4446 last; 4447 } 4448} 4449 4450$#ARGV < 1 or die_usage; 4451if ($#ARGV == 0) { 4452 $ktest_config = $ARGV[0]; 4453 if (! -f $ktest_config) { 4454 print "$ktest_config does not exist.\n"; 4455 if (!read_yn "Create it?") { 4456 exit 0; 4457 } 4458 } 4459} 4460 4461if (! -f $ktest_config) { 4462 $newconfig = 1; 4463 get_test_case; 4464 open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 4465 print OUT << "EOF" 4466# Generated by ktest.pl 4467# 4468 4469# PWD is a ktest.pl variable that will result in the process working 4470# directory that ktest.pl is executed in. 4471 4472# THIS_DIR is automatically assigned the PWD of the path that generated 4473# the config file. It is best to use this variable when assigning other 4474# directory paths within this directory. This allows you to easily 4475# move the test cases to other locations or to other machines. 4476# 4477THIS_DIR := $variable{"PWD"} 4478 4479# Define each test with TEST_START 4480# The config options below it will override the defaults 4481TEST_START 4482TEST_TYPE = $default{"TEST_TYPE"} 4483 4484DEFAULTS 4485EOF 4486; 4487 close(OUT); 4488} 4489read_config $ktest_config; 4490 4491if ($dry_run) { 4492 print_test_preamble 1; 4493 exit 0; 4494} 4495 4496if (defined($opt{"LOG_FILE"})) { 4497 $opt{"LOG_FILE"} = set_test_option("LOG_FILE", 1); 4498} 4499 4500# Append any configs entered in manually to the config file. 4501my @new_configs = keys %entered_configs; 4502if ($#new_configs >= 0) { 4503 print "\nAppending entered in configs to $ktest_config\n"; 4504 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 4505 foreach my $config (@new_configs) { 4506 print OUT "$config = $entered_configs{$config}\n"; 4507 $opt{$config} = process_variables($entered_configs{$config}); 4508 } 4509} 4510 4511if (defined($opt{"LOG_FILE"})) { 4512 if ($opt{"CLEAR_LOG"}) { 4513 unlink $opt{"LOG_FILE"}; 4514 } 4515 4516 if (! -e $opt{"LOG_FILE"} && $opt{"LOG_FILE"} =~ m,^(.*/),) { 4517 my $dir = $1; 4518 if (! -d $dir) { 4519 mkpath($dir) or die "Failed to create directories '$dir': $!"; 4520 print "\nThe log directory $dir did not exist, so it was created.\n"; 4521 } 4522 } 4523 open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 4524 LOG->autoflush(1); 4525} 4526 4527print_test_preamble 0; 4528 4529$SIG{INT} = qw(cancel_test); 4530 4531# First we need to do is the builds 4532for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 4533 4534 # Do not reboot on failing test options 4535 $no_reboot = 1; 4536 $reboot_success = 0; 4537 4538 $have_version = 0; 4539 4540 $iteration = $i; 4541 4542 $build_time = 0; 4543 $install_time = 0; 4544 $reboot_time = 0; 4545 $test_time = 0; 4546 4547 undef %force_config; 4548 4549 my $makecmd = set_test_option("MAKE_CMD", $i); 4550 4551 $outputdir = set_test_option("OUTPUT_DIR", $i); 4552 $builddir = set_test_option("BUILD_DIR", $i); 4553 4554 chdir $builddir || dodie "can't change directory to $builddir"; 4555 4556 if (!-d $outputdir) { 4557 mkpath($outputdir) or 4558 dodie "can't create $outputdir"; 4559 } 4560 4561 $make = "$makecmd O=$outputdir"; 4562 4563 # Load all the options into their mapped variable names 4564 foreach my $opt (keys %option_map) { 4565 ${$option_map{$opt}} = set_test_option($opt, $i); 4566 } 4567 4568 $start_minconfig_defined = 1; 4569 4570 # The first test may override the PRE_KTEST option 4571 if ($i == 1) { 4572 if (defined($pre_ktest)) { 4573 doprint "\n"; 4574 my $ret = run_command $pre_ktest; 4575 if (!$ret && defined($pre_ktest_die) && 4576 $pre_ktest_die) { 4577 dodie "failed to pre_ktest\n"; 4578 } 4579 } 4580 if ($email_when_started) { 4581 my $name = get_test_name; 4582 send_email("KTEST: Your [$name] test was started", 4583 "Your test was started on $script_start_time"); 4584 } 4585 } 4586 4587 # Any test can override the POST_KTEST option 4588 # The last test takes precedence. 4589 if (defined($post_ktest)) { 4590 $final_post_ktest = $post_ktest; 4591 } 4592 4593 if (!defined($start_minconfig)) { 4594 $start_minconfig_defined = 0; 4595 $start_minconfig = $minconfig; 4596 } 4597 4598 if (!-d $tmpdir) { 4599 mkpath($tmpdir) or 4600 dodie "can't create $tmpdir"; 4601 } 4602 4603 $ENV{"SSH_USER"} = $ssh_user; 4604 $ENV{"MACHINE"} = $machine; 4605 4606 $buildlog = "$tmpdir/buildlog-$machine"; 4607 $testlog = "$tmpdir/testlog-$machine"; 4608 $dmesg = "$tmpdir/dmesg-$machine"; 4609 $output_config = "$outputdir/.config"; 4610 4611 if (!$buildonly) { 4612 $target = "$ssh_user\@$machine"; 4613 if (($reboot_type eq "grub") or ($reboot_type eq "grub2bls")) { 4614 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 4615 } elsif ($reboot_type eq "grub2") { 4616 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 4617 dodie "GRUB_FILE not defined" if (!defined($grub_file)); 4618 } elsif ($reboot_type eq "syslinux") { 4619 dodie "SYSLINUX_LABEL not defined" if (!defined($syslinux_label)); 4620 } 4621 } 4622 4623 my $run_type = $build_type; 4624 if ($test_type eq "patchcheck") { 4625 $run_type = $patchcheck_type; 4626 } elsif ($test_type eq "bisect") { 4627 $run_type = $bisect_type; 4628 } elsif ($test_type eq "config_bisect") { 4629 $run_type = $config_bisect_type; 4630 } elsif ($test_type eq "make_min_config") { 4631 $run_type = ""; 4632 } elsif ($test_type eq "make_warnings_file") { 4633 $run_type = ""; 4634 } 4635 4636 # mistake in config file? 4637 if (!defined($run_type)) { 4638 $run_type = "ERROR"; 4639 } 4640 4641 my $installme = ""; 4642 $installme = " no_install" if ($no_install); 4643 4644 my $name = ""; 4645 4646 if (defined($test_name)) { 4647 $name = " ($test_name)"; 4648 } 4649 4650 doprint "\n\n"; 4651 4652 if (defined($opt{"LOG_FILE"})) { 4653 $test_log_start = tell(LOG); 4654 } 4655 4656 doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; 4657 4658 # Always show which build directory and output directory is being used 4659 doprint "BUILD_DIR=$builddir\n"; 4660 doprint "OUTPUT_DIR=$outputdir\n\n"; 4661 4662 if (defined($pre_test)) { 4663 my $ret = run_command $pre_test; 4664 if (!$ret && defined($pre_test_die) && 4665 $pre_test_die) { 4666 dodie "failed to pre_test\n"; 4667 } 4668 } 4669 4670 unlink $dmesg; 4671 unlink $buildlog; 4672 unlink $testlog; 4673 4674 if (defined($addconfig)) { 4675 my $min = $minconfig; 4676 if (!defined($minconfig)) { 4677 $min = ""; 4678 } 4679 run_command "cat $addconfig $min > $tmpdir/add_config" or 4680 dodie "Failed to create temp config"; 4681 $minconfig = "$tmpdir/add_config"; 4682 } 4683 4684 if (defined($checkout)) { 4685 run_command "git checkout $checkout" or 4686 dodie "failed to checkout $checkout"; 4687 } 4688 4689 $no_reboot = 0; 4690 4691 # A test may opt to not reboot the box 4692 if ($reboot_on_success) { 4693 $reboot_success = 1; 4694 } 4695 4696 if ($test_type eq "bisect") { 4697 bisect $i; 4698 next; 4699 } elsif ($test_type eq "config_bisect") { 4700 config_bisect $i; 4701 next; 4702 } elsif ($test_type eq "patchcheck") { 4703 patchcheck $i; 4704 next; 4705 } elsif ($test_type eq "make_min_config") { 4706 make_min_config $i; 4707 next; 4708 } elsif ($test_type eq "make_warnings_file") { 4709 $no_reboot = 1; 4710 make_warnings_file $i; 4711 next; 4712 } 4713 4714 if ($build_type ne "nobuild") { 4715 build $build_type or next; 4716 check_buildlog or next; 4717 } 4718 4719 if ($test_type eq "install") { 4720 get_version; 4721 install; 4722 success $i; 4723 next; 4724 } 4725 4726 if ($test_type ne "build") { 4727 my $failed = 0; 4728 start_monitor_and_install or $failed = 1; 4729 4730 if (!$failed && $test_type ne "boot" && defined($run_test)) { 4731 do_run_test or $failed = 1; 4732 } 4733 end_monitor; 4734 if ($failed) { 4735 print_times; 4736 next; 4737 } 4738 } 4739 4740 print_times; 4741 4742 success $i; 4743} 4744 4745run_post_ktest; 4746 4747if ($opt{"POWEROFF_ON_SUCCESS"}) { 4748 halt; 4749} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) { 4750 reboot_to_good; 4751} elsif (defined($switch_to_good)) { 4752 # still need to get to the good kernel 4753 run_command $switch_to_good; 4754} 4755 4756doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 4757 4758if ($email_when_finished) { 4759 send_email("KTEST: Your test has finished!", 4760 "$successes of $opt{NUM_TESTS} tests started at $script_start_time were successful!"); 4761} 4762 4763if (defined($opt{"LOG_FILE"})) { 4764 print "\n See $opt{LOG_FILE} for the record of results.\n\n"; 4765 close LOG; 4766} 4767 4768exit 0; 4769 4770## 4771# The following are here to standardize tabs/spaces/etc across the most likely editors 4772### 4773 4774# Local Variables: 4775# mode: perl 4776# End: 4777# vim: softtabstop=4 4778