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