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