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