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 $start_time; 1884 my $rin; 1885 my $rout; 1886 my $nr; 1887 my $buf; 1888 my $line; 1889 my $ch; 1890 1891 if (!defined($time)) { 1892 $time = $timeout; 1893 } 1894 1895 $rin = ''; 1896 vec($rin, fileno($fp), 1) = 1; 1897 vec($rin, fileno(\*STDIN), 1) = 1; 1898 1899 $start_time = time; 1900 1901 while (1) { 1902 $nr = select($rout=$rin, undef, undef, $time); 1903 1904 last if ($nr <= 0); 1905 1906 # copy data from stdin to the console 1907 if (vec($rout, fileno(\*STDIN), 1) == 1) { 1908 $nr = sysread(\*STDIN, $buf, 1000); 1909 syswrite($fp, $buf, $nr) if ($nr > 0); 1910 } 1911 1912 # The timeout is based on time waiting for the fp data 1913 if (vec($rout, fileno($fp), 1) != 1) { 1914 last if (defined($time) && (time - $start_time > $time)); 1915 next; 1916 } 1917 1918 $line = ""; 1919 1920 # try to read one char at a time 1921 while (sysread $fp, $ch, 1) { 1922 $line .= $ch; 1923 last if ($ch eq "\n"); 1924 } 1925 1926 last if (!length($line)); 1927 1928 return $line; 1929 } 1930 return undef; 1931} 1932 1933sub reboot_to { 1934 if (defined($switch_to_test)) { 1935 run_command $switch_to_test; 1936 } 1937 1938 if ($reboot_type eq "grub") { 1939 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; 1940 } elsif ($reboot_type eq "grub2") { 1941 run_ssh "$grub_reboot $grub_number"; 1942 } elsif ($reboot_type eq "syslinux") { 1943 run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path"; 1944 } elsif (defined $reboot_script) { 1945 run_command "$reboot_script"; 1946 } 1947 reboot; 1948} 1949 1950sub get_sha1 { 1951 my ($commit) = @_; 1952 1953 doprint "git rev-list --max-count=1 $commit ... "; 1954 my $sha1 = `git rev-list --max-count=1 $commit`; 1955 my $ret = $?; 1956 1957 logit $sha1; 1958 1959 if ($ret) { 1960 doprint "FAILED\n"; 1961 dodie "Failed to get git $commit"; 1962 } 1963 1964 print "SUCCESS\n"; 1965 1966 chomp $sha1; 1967 1968 return $sha1; 1969} 1970 1971sub monitor { 1972 my $booted = 0; 1973 my $bug = 0; 1974 my $bug_ignored = 0; 1975 my $skip_call_trace = 0; 1976 my $loops; 1977 1978 my $start_time = time; 1979 1980 wait_for_monitor 5; 1981 1982 my $line; 1983 my $full_line = ""; 1984 1985 open(DMESG, "> $dmesg") or 1986 die "unable to write to $dmesg"; 1987 1988 reboot_to; 1989 1990 my $success_start; 1991 my $failure_start; 1992 my $monitor_start = time; 1993 my $done = 0; 1994 my $version_found = 0; 1995 1996 while (!$done) { 1997 1998 if ($bug && defined($stop_after_failure) && 1999 $stop_after_failure >= 0) { 2000 my $time = $stop_after_failure - (time - $failure_start); 2001 $line = wait_for_input($monitor_fp, $time); 2002 if (!defined($line)) { 2003 doprint "bug timed out after $booted_timeout seconds\n"; 2004 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 2005 last; 2006 } 2007 } elsif ($booted) { 2008 $line = wait_for_input($monitor_fp, $booted_timeout); 2009 if (!defined($line)) { 2010 my $s = $booted_timeout == 1 ? "" : "s"; 2011 doprint "Successful boot found: break after $booted_timeout second$s\n"; 2012 last; 2013 } 2014 } else { 2015 $line = wait_for_input($monitor_fp); 2016 if (!defined($line)) { 2017 my $s = $timeout == 1 ? "" : "s"; 2018 doprint "Timed out after $timeout second$s\n"; 2019 last; 2020 } 2021 } 2022 2023 doprint $line; 2024 print DMESG $line; 2025 2026 # we are not guaranteed to get a full line 2027 $full_line .= $line; 2028 2029 if ($full_line =~ /$success_line/) { 2030 $booted = 1; 2031 $success_start = time; 2032 } 2033 2034 if ($booted && defined($stop_after_success) && 2035 $stop_after_success >= 0) { 2036 my $now = time; 2037 if ($now - $success_start >= $stop_after_success) { 2038 doprint "Test forced to stop after $stop_after_success seconds after success\n"; 2039 last; 2040 } 2041 } 2042 2043 if ($full_line =~ /\[ backtrace testing \]/) { 2044 $skip_call_trace = 1; 2045 } 2046 2047 if ($full_line =~ /call trace:/i) { 2048 if (!$bug && !$skip_call_trace) { 2049 if ($ignore_errors) { 2050 $bug_ignored = 1; 2051 } else { 2052 $bug = 1; 2053 $failure_start = time; 2054 } 2055 } 2056 } 2057 2058 if ($bug && defined($stop_after_failure) && 2059 $stop_after_failure >= 0) { 2060 my $now = time; 2061 if ($now - $failure_start >= $stop_after_failure) { 2062 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 2063 last; 2064 } 2065 } 2066 2067 if ($full_line =~ /\[ end of backtrace testing \]/) { 2068 $skip_call_trace = 0; 2069 } 2070 2071 if ($full_line =~ /Kernel panic -/) { 2072 $failure_start = time; 2073 $bug = 1; 2074 } 2075 2076 # Detect triple faults by testing the banner 2077 if ($full_line =~ /\bLinux version (\S+).*\n/) { 2078 if ($1 eq $version) { 2079 $version_found = 1; 2080 } elsif ($version_found && $detect_triplefault) { 2081 # We already booted into the kernel we are testing, 2082 # but now we booted into another kernel? 2083 # Consider this a triple fault. 2084 doprint "Already booted in Linux kernel $version, but now\n"; 2085 doprint "we booted into Linux kernel $1.\n"; 2086 doprint "Assuming that this is a triple fault.\n"; 2087 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; 2088 last; 2089 } 2090 } 2091 2092 if ($line =~ /\n/) { 2093 $full_line = ""; 2094 } 2095 2096 if ($stop_test_after > 0 && !$booted && !$bug) { 2097 if (time - $monitor_start > $stop_test_after) { 2098 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 2099 $done = 1; 2100 } 2101 } 2102 } 2103 2104 my $end_time = time; 2105 $reboot_time = $end_time - $start_time; 2106 2107 close(DMESG); 2108 2109 if ($bug) { 2110 return 0 if ($in_bisect); 2111 fail "failed - got a bug report" and return 0; 2112 } 2113 2114 if (!$booted) { 2115 return 0 if ($in_bisect); 2116 fail "failed - never got a boot prompt." and return 0; 2117 } 2118 2119 if ($bug_ignored) { 2120 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 2121 } 2122 2123 return 1; 2124} 2125 2126sub eval_kernel_version { 2127 my ($option) = @_; 2128 2129 $option =~ s/\$KERNEL_VERSION/$version/g; 2130 2131 return $option; 2132} 2133 2134sub do_post_install { 2135 2136 return if (!defined($post_install)); 2137 2138 my $cp_post_install = eval_kernel_version $post_install; 2139 run_command "$cp_post_install" or 2140 dodie "Failed to run post install"; 2141} 2142 2143# Sometimes the reboot fails, and will hang. We try to ssh to the box 2144# and if we fail, we force another reboot, that should powercycle it. 2145sub test_booted { 2146 if (!run_ssh "echo testing connection") { 2147 reboot $sleep_time; 2148 } 2149} 2150 2151sub install { 2152 2153 return if ($no_install); 2154 2155 my $start_time = time; 2156 2157 if (defined($pre_install)) { 2158 my $cp_pre_install = eval_kernel_version $pre_install; 2159 run_command "$cp_pre_install" or 2160 dodie "Failed to run pre install"; 2161 } 2162 2163 my $cp_target = eval_kernel_version $target_image; 2164 2165 test_booted; 2166 2167 run_scp_install "$outputdir/$build_target", "$cp_target" or 2168 dodie "failed to copy image"; 2169 2170 my $install_mods = 0; 2171 2172 # should we process modules? 2173 $install_mods = 0; 2174 open(IN, "$output_config") or dodie("Can't read config file"); 2175 while (<IN>) { 2176 if (/CONFIG_MODULES(=y)?/) { 2177 if (defined($1)) { 2178 $install_mods = 1; 2179 last; 2180 } 2181 } 2182 } 2183 close(IN); 2184 2185 if (!$install_mods) { 2186 do_post_install; 2187 doprint "No modules needed\n"; 2188 my $end_time = time; 2189 $install_time = $end_time - $start_time; 2190 return; 2191 } 2192 2193 run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or 2194 dodie "Failed to install modules"; 2195 2196 my $modlib = "/lib/modules/$version"; 2197 my $modtar = "ktest-mods.tar.bz2"; 2198 2199 run_ssh "rm -rf $modlib" or 2200 dodie "failed to remove old mods: $modlib"; 2201 2202 # would be nice if scp -r did not follow symbolic links 2203 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 2204 dodie "making tarball"; 2205 2206 run_scp_mod "$tmpdir/$modtar", "/tmp" or 2207 dodie "failed to copy modules"; 2208 2209 unlink "$tmpdir/$modtar"; 2210 2211 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or 2212 dodie "failed to tar modules"; 2213 2214 run_ssh "rm -f /tmp/$modtar"; 2215 2216 do_post_install; 2217 2218 my $end_time = time; 2219 $install_time = $end_time - $start_time; 2220} 2221 2222sub get_version { 2223 # get the release name 2224 return if ($have_version); 2225 doprint "$make kernelrelease ... "; 2226 $version = `$make -s kernelrelease | tail -1`; 2227 chomp($version); 2228 doprint "$version\n"; 2229 $have_version = 1; 2230} 2231 2232sub start_monitor_and_install { 2233 # Make sure the stable kernel has finished booting 2234 2235 # Install bisects, don't need console 2236 if (defined $console) { 2237 start_monitor; 2238 wait_for_monitor 5; 2239 end_monitor; 2240 } 2241 2242 get_grub_index; 2243 get_version; 2244 install; 2245 2246 start_monitor if (defined $console); 2247 return monitor; 2248} 2249 2250my $check_build_re = ".*:.*(warning|error|Error):.*"; 2251my $utf8_quote = "\\x{e2}\\x{80}(\\x{98}|\\x{99})"; 2252 2253sub process_warning_line { 2254 my ($line) = @_; 2255 2256 chomp $line; 2257 2258 # for distcc heterogeneous systems, some compilers 2259 # do things differently causing warning lines 2260 # to be slightly different. This makes an attempt 2261 # to fixe those issues. 2262 2263 # chop off the index into the line 2264 # using distcc, some compilers give different indexes 2265 # depending on white space 2266 $line =~ s/^(\s*\S+:\d+:)\d+/$1/; 2267 2268 # Some compilers use UTF-8 extended for quotes and some don't. 2269 $line =~ s/$utf8_quote/'/g; 2270 2271 return $line; 2272} 2273 2274# Read buildlog and check against warnings file for any 2275# new warnings. 2276# 2277# Returns 1 if OK 2278# 0 otherwise 2279sub check_buildlog { 2280 return 1 if (!defined $warnings_file); 2281 2282 my %warnings_list; 2283 2284 # Failed builds should not reboot the target 2285 my $save_no_reboot = $no_reboot; 2286 $no_reboot = 1; 2287 2288 if (-f $warnings_file) { 2289 open(IN, $warnings_file) or 2290 dodie "Error opening $warnings_file"; 2291 2292 while (<IN>) { 2293 if (/$check_build_re/) { 2294 my $warning = process_warning_line $_; 2295 2296 $warnings_list{$warning} = 1; 2297 } 2298 } 2299 close(IN); 2300 } 2301 2302 # If warnings file didn't exist, and WARNINGS_FILE exist, 2303 # then we fail on any warning! 2304 2305 open(IN, $buildlog) or dodie "Can't open $buildlog"; 2306 while (<IN>) { 2307 if (/$check_build_re/) { 2308 my $warning = process_warning_line $_; 2309 2310 if (!defined $warnings_list{$warning}) { 2311 fail "New warning found (not in $warnings_file)\n$_\n"; 2312 $no_reboot = $save_no_reboot; 2313 return 0; 2314 } 2315 } 2316 } 2317 $no_reboot = $save_no_reboot; 2318 close(IN); 2319} 2320 2321sub check_patch_buildlog { 2322 my ($patch) = @_; 2323 2324 my @files = `git show $patch | diffstat -l`; 2325 2326 foreach my $file (@files) { 2327 chomp $file; 2328 } 2329 2330 open(IN, "git show $patch |") or 2331 dodie "failed to show $patch"; 2332 while (<IN>) { 2333 if (m,^--- a/(.*),) { 2334 chomp $1; 2335 $files[$#files] = $1; 2336 } 2337 } 2338 close(IN); 2339 2340 open(IN, $buildlog) or dodie "Can't open $buildlog"; 2341 while (<IN>) { 2342 if (/^\s*(.*?):.*(warning|error)/) { 2343 my $err = $1; 2344 foreach my $file (@files) { 2345 my $fullpath = "$builddir/$file"; 2346 if ($file eq $err || $fullpath eq $err) { 2347 fail "$file built with warnings" and return 0; 2348 } 2349 } 2350 } 2351 } 2352 close(IN); 2353 2354 return 1; 2355} 2356 2357sub apply_min_config { 2358 my $outconfig = "$output_config.new"; 2359 2360 # Read the config file and remove anything that 2361 # is in the force_config hash (from minconfig and others) 2362 # then add the force config back. 2363 2364 doprint "Applying minimum configurations into $output_config.new\n"; 2365 2366 open (OUT, ">$outconfig") or 2367 dodie "Can't create $outconfig"; 2368 2369 if (-f $output_config) { 2370 open (IN, $output_config) or 2371 dodie "Failed to open $output_config"; 2372 while (<IN>) { 2373 if (/^(# )?(CONFIG_[^\s=]*)/) { 2374 next if (defined($force_config{$2})); 2375 } 2376 print OUT; 2377 } 2378 close IN; 2379 } 2380 foreach my $config (keys %force_config) { 2381 print OUT "$force_config{$config}\n"; 2382 } 2383 close OUT; 2384 2385 run_command "mv $outconfig $output_config"; 2386} 2387 2388sub make_oldconfig { 2389 2390 my @force_list = keys %force_config; 2391 2392 if ($#force_list >= 0) { 2393 apply_min_config; 2394 } 2395 2396 if (!run_command "$make olddefconfig") { 2397 # Perhaps olddefconfig doesn't exist in this version of the kernel 2398 # try oldnoconfig 2399 doprint "olddefconfig failed, trying make oldnoconfig\n"; 2400 if (!run_command "$make oldnoconfig") { 2401 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 2402 # try a yes '' | oldconfig 2403 run_command "yes '' | $make oldconfig" or 2404 dodie "failed make config oldconfig"; 2405 } 2406 } 2407} 2408 2409# read a config file and use this to force new configs. 2410sub load_force_config { 2411 my ($config) = @_; 2412 2413 doprint "Loading force configs from $config\n"; 2414 open(IN, $config) or 2415 dodie "failed to read $config"; 2416 while (<IN>) { 2417 chomp; 2418 if (/^(CONFIG[^\s=]*)(\s*=.*)/) { 2419 $force_config{$1} = $_; 2420 } elsif (/^# (CONFIG_\S*) is not set/) { 2421 $force_config{$1} = $_; 2422 } 2423 } 2424 close IN; 2425} 2426 2427sub build { 2428 my ($type) = @_; 2429 2430 unlink $buildlog; 2431 2432 my $start_time = time; 2433 2434 # Failed builds should not reboot the target 2435 my $save_no_reboot = $no_reboot; 2436 $no_reboot = 1; 2437 2438 # Calculate a new version from here. 2439 $have_version = 0; 2440 2441 if (defined($pre_build)) { 2442 my $ret = run_command $pre_build; 2443 if (!$ret && defined($pre_build_die) && 2444 $pre_build_die) { 2445 dodie "failed to pre_build\n"; 2446 } 2447 } 2448 2449 if ($type =~ /^useconfig:(.*)/) { 2450 run_command "cp $1 $output_config" or 2451 dodie "could not copy $1 to .config"; 2452 2453 $type = "oldconfig"; 2454 } 2455 2456 # old config can ask questions 2457 if ($type eq "oldconfig") { 2458 $type = "olddefconfig"; 2459 2460 # allow for empty configs 2461 run_command "touch $output_config"; 2462 2463 if (!$noclean) { 2464 run_command "mv $output_config $outputdir/config_temp" or 2465 dodie "moving .config"; 2466 2467 run_command "$make mrproper" or dodie "make mrproper"; 2468 2469 run_command "mv $outputdir/config_temp $output_config" or 2470 dodie "moving config_temp"; 2471 } 2472 2473 } elsif (!$noclean) { 2474 unlink "$output_config"; 2475 run_command "$make mrproper" or 2476 dodie "make mrproper"; 2477 } 2478 2479 # add something to distinguish this build 2480 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 2481 print OUT "$localversion\n"; 2482 close(OUT); 2483 2484 if (defined($minconfig)) { 2485 load_force_config($minconfig); 2486 } 2487 2488 if ($type ne "olddefconfig") { 2489 run_command "$make $type" or 2490 dodie "failed make config"; 2491 } 2492 # Run old config regardless, to enforce min configurations 2493 make_oldconfig; 2494 2495 my $build_ret = run_command "$make $build_options", $buildlog; 2496 2497 if (defined($post_build)) { 2498 # Because a post build may change the kernel version 2499 # do it now. 2500 get_version; 2501 my $ret = run_command $post_build; 2502 if (!$ret && defined($post_build_die) && 2503 $post_build_die) { 2504 dodie "failed to post_build\n"; 2505 } 2506 } 2507 2508 if (!$build_ret) { 2509 # bisect may need this to pass 2510 if ($in_bisect) { 2511 $no_reboot = $save_no_reboot; 2512 return 0; 2513 } 2514 fail "failed build" and return 0; 2515 } 2516 2517 $no_reboot = $save_no_reboot; 2518 2519 my $end_time = time; 2520 $build_time = $end_time - $start_time; 2521 2522 return 1; 2523} 2524 2525sub halt { 2526 if (!run_ssh "halt" or defined($power_off)) { 2527 if (defined($poweroff_after_halt)) { 2528 sleep $poweroff_after_halt; 2529 run_command "$power_off"; 2530 } 2531 } else { 2532 # nope? the zap it! 2533 run_command "$power_off"; 2534 } 2535} 2536 2537sub success { 2538 my ($i) = @_; 2539 2540 $successes++; 2541 2542 my $name = ""; 2543 2544 if (defined($test_name)) { 2545 $name = " ($test_name)"; 2546 } 2547 2548 print_times; 2549 2550 doprint "\n\n*******************************************\n"; 2551 doprint "*******************************************\n"; 2552 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; 2553 doprint "*******************************************\n"; 2554 doprint "*******************************************\n"; 2555 2556 if (defined($store_successes)) { 2557 save_logs "success", $store_successes; 2558 } 2559 2560 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 2561 doprint "Reboot and wait $sleep_time seconds\n"; 2562 reboot_to_good $sleep_time; 2563 } 2564 2565 if (defined($post_test)) { 2566 run_command $post_test; 2567 } 2568} 2569 2570sub answer_bisect { 2571 for (;;) { 2572 doprint "Pass, fail, or skip? [p/f/s]"; 2573 my $ans = <STDIN>; 2574 chomp $ans; 2575 if ($ans eq "p" || $ans eq "P") { 2576 return 1; 2577 } elsif ($ans eq "f" || $ans eq "F") { 2578 return 0; 2579 } elsif ($ans eq "s" || $ans eq "S") { 2580 return -1; 2581 } else { 2582 print "Please answer 'p', 'f', or 's'\n"; 2583 } 2584 } 2585} 2586 2587sub child_run_test { 2588 2589 # child should have no power 2590 $reboot_on_error = 0; 2591 $poweroff_on_error = 0; 2592 $die_on_failure = 1; 2593 2594 run_command $run_test, $testlog; 2595 2596 exit $run_command_status; 2597} 2598 2599my $child_done; 2600 2601sub child_finished { 2602 $child_done = 1; 2603} 2604 2605sub do_run_test { 2606 my $child_pid; 2607 my $child_exit; 2608 my $line; 2609 my $full_line; 2610 my $bug = 0; 2611 my $bug_ignored = 0; 2612 2613 my $start_time = time; 2614 2615 wait_for_monitor 1; 2616 2617 doprint "run test $run_test\n"; 2618 2619 $child_done = 0; 2620 2621 $SIG{CHLD} = qw(child_finished); 2622 2623 $child_pid = fork; 2624 2625 child_run_test if (!$child_pid); 2626 2627 $full_line = ""; 2628 2629 do { 2630 $line = wait_for_input($monitor_fp, 1); 2631 if (defined($line)) { 2632 2633 # we are not guaranteed to get a full line 2634 $full_line .= $line; 2635 doprint $line; 2636 2637 if ($full_line =~ /call trace:/i) { 2638 if ($ignore_errors) { 2639 $bug_ignored = 1; 2640 } else { 2641 $bug = 1; 2642 } 2643 } 2644 2645 if ($full_line =~ /Kernel panic -/) { 2646 $bug = 1; 2647 } 2648 2649 if ($line =~ /\n/) { 2650 $full_line = ""; 2651 } 2652 } 2653 } while (!$child_done && !$bug); 2654 2655 if (!$bug && $bug_ignored) { 2656 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 2657 } 2658 2659 if ($bug) { 2660 my $failure_start = time; 2661 my $now; 2662 do { 2663 $line = wait_for_input($monitor_fp, 1); 2664 if (defined($line)) { 2665 doprint $line; 2666 } 2667 $now = time; 2668 if ($now - $failure_start >= $stop_after_failure) { 2669 last; 2670 } 2671 } while (defined($line)); 2672 2673 doprint "Detected kernel crash!\n"; 2674 # kill the child with extreme prejudice 2675 kill 9, $child_pid; 2676 } 2677 2678 waitpid $child_pid, 0; 2679 $child_exit = $? >> 8; 2680 2681 my $end_time = time; 2682 $test_time = $end_time - $start_time; 2683 2684 if (!$bug && $in_bisect) { 2685 if (defined($bisect_ret_good)) { 2686 if ($child_exit == $bisect_ret_good) { 2687 return 1; 2688 } 2689 } 2690 if (defined($bisect_ret_skip)) { 2691 if ($child_exit == $bisect_ret_skip) { 2692 return -1; 2693 } 2694 } 2695 if (defined($bisect_ret_abort)) { 2696 if ($child_exit == $bisect_ret_abort) { 2697 fail "test abort" and return -2; 2698 } 2699 } 2700 if (defined($bisect_ret_bad)) { 2701 if ($child_exit == $bisect_ret_skip) { 2702 return 0; 2703 } 2704 } 2705 if (defined($bisect_ret_default)) { 2706 if ($bisect_ret_default eq "good") { 2707 return 1; 2708 } elsif ($bisect_ret_default eq "bad") { 2709 return 0; 2710 } elsif ($bisect_ret_default eq "skip") { 2711 return -1; 2712 } elsif ($bisect_ret_default eq "abort") { 2713 return -2; 2714 } else { 2715 fail "unknown default action: $bisect_ret_default" 2716 and return -2; 2717 } 2718 } 2719 } 2720 2721 if ($bug || $child_exit) { 2722 return 0 if $in_bisect; 2723 fail "test failed" and return 0; 2724 } 2725 return 1; 2726} 2727 2728sub run_git_bisect { 2729 my ($command) = @_; 2730 2731 doprint "$command ... "; 2732 2733 my $output = `$command 2>&1`; 2734 my $ret = $?; 2735 2736 logit $output; 2737 2738 if ($ret) { 2739 doprint "FAILED\n"; 2740 dodie "Failed to git bisect"; 2741 } 2742 2743 doprint "SUCCESS\n"; 2744 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 2745 doprint "$1 [$2]\n"; 2746 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 2747 $bisect_bad_commit = $1; 2748 doprint "Found bad commit... $1\n"; 2749 return 0; 2750 } else { 2751 # we already logged it, just print it now. 2752 print $output; 2753 } 2754 2755 return 1; 2756} 2757 2758sub bisect_reboot { 2759 doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 2760 reboot_to_good $bisect_sleep_time; 2761} 2762 2763# returns 1 on success, 0 on failure, -1 on skip 2764sub run_bisect_test { 2765 my ($type, $buildtype) = @_; 2766 2767 my $failed = 0; 2768 my $result; 2769 my $output; 2770 my $ret; 2771 2772 $in_bisect = 1; 2773 2774 build $buildtype or $failed = 1; 2775 2776 if ($type ne "build") { 2777 if ($failed && $bisect_skip) { 2778 $in_bisect = 0; 2779 return -1; 2780 } 2781 dodie "Failed on build" if $failed; 2782 2783 # Now boot the box 2784 start_monitor_and_install or $failed = 1; 2785 2786 if ($type ne "boot") { 2787 if ($failed && $bisect_skip) { 2788 end_monitor; 2789 bisect_reboot; 2790 $in_bisect = 0; 2791 return -1; 2792 } 2793 dodie "Failed on boot" if $failed; 2794 2795 do_run_test or $failed = 1; 2796 } 2797 end_monitor; 2798 } 2799 2800 if ($failed) { 2801 $result = 0; 2802 } else { 2803 $result = 1; 2804 } 2805 2806 # reboot the box to a kernel we can ssh to 2807 if ($type ne "build") { 2808 bisect_reboot; 2809 } 2810 $in_bisect = 0; 2811 2812 return $result; 2813} 2814 2815sub run_bisect { 2816 my ($type) = @_; 2817 my $buildtype = "oldconfig"; 2818 2819 # We should have a minconfig to use? 2820 if (defined($minconfig)) { 2821 $buildtype = "useconfig:$minconfig"; 2822 } 2823 2824 # If the user sets bisect_tries to less than 1, then no tries 2825 # is a success. 2826 my $ret = 1; 2827 2828 # Still let the user manually decide that though. 2829 if ($bisect_tries < 1 && $bisect_manual) { 2830 $ret = answer_bisect; 2831 } 2832 2833 for (my $i = 0; $i < $bisect_tries; $i++) { 2834 if ($bisect_tries > 1) { 2835 my $t = $i + 1; 2836 doprint("Running bisect trial $t of $bisect_tries:\n"); 2837 } 2838 $ret = run_bisect_test $type, $buildtype; 2839 2840 if ($bisect_manual) { 2841 $ret = answer_bisect; 2842 } 2843 2844 last if (!$ret); 2845 } 2846 2847 # Are we looking for where it worked, not failed? 2848 if ($reverse_bisect && $ret >= 0) { 2849 $ret = !$ret; 2850 } 2851 2852 if ($ret > 0) { 2853 return "good"; 2854 } elsif ($ret == 0) { 2855 return "bad"; 2856 } elsif ($bisect_skip) { 2857 doprint "HIT A BAD COMMIT ... SKIPPING\n"; 2858 return "skip"; 2859 } 2860} 2861 2862sub update_bisect_replay { 2863 my $tmp_log = "$tmpdir/ktest_bisect_log"; 2864 run_command "git bisect log > $tmp_log" or 2865 die "can't create bisect log"; 2866 return $tmp_log; 2867} 2868 2869sub bisect { 2870 my ($i) = @_; 2871 2872 my $result; 2873 2874 die "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good)); 2875 die "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad)); 2876 die "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type)); 2877 2878 my $good = $bisect_good; 2879 my $bad = $bisect_bad; 2880 my $type = $bisect_type; 2881 my $start = $bisect_start; 2882 my $replay = $bisect_replay; 2883 my $start_files = $bisect_files; 2884 2885 if (defined($start_files)) { 2886 $start_files = " -- " . $start_files; 2887 } else { 2888 $start_files = ""; 2889 } 2890 2891 # convert to true sha1's 2892 $good = get_sha1($good); 2893 $bad = get_sha1($bad); 2894 2895 if (defined($bisect_reverse) && $bisect_reverse == 1) { 2896 doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 2897 $reverse_bisect = 1; 2898 } else { 2899 $reverse_bisect = 0; 2900 } 2901 2902 # Can't have a test without having a test to run 2903 if ($type eq "test" && !defined($run_test)) { 2904 $type = "boot"; 2905 } 2906 2907 # Check if a bisect was running 2908 my $bisect_start_file = "$builddir/.git/BISECT_START"; 2909 2910 my $check = $bisect_check; 2911 my $do_check = defined($check) && $check ne "0"; 2912 2913 if ( -f $bisect_start_file ) { 2914 print "Bisect in progress found\n"; 2915 if ($do_check) { 2916 print " If you say yes, then no checks of good or bad will be done\n"; 2917 } 2918 if (defined($replay)) { 2919 print "** BISECT_REPLAY is defined in config file **"; 2920 print " Ignore config option and perform new git bisect log?\n"; 2921 if (read_ync " (yes, no, or cancel) ") { 2922 $replay = update_bisect_replay; 2923 $do_check = 0; 2924 } 2925 } elsif (read_yn "read git log and continue?") { 2926 $replay = update_bisect_replay; 2927 $do_check = 0; 2928 } 2929 } 2930 2931 if ($do_check) { 2932 2933 # get current HEAD 2934 my $head = get_sha1("HEAD"); 2935 2936 if ($check ne "good") { 2937 doprint "TESTING BISECT BAD [$bad]\n"; 2938 run_command "git checkout $bad" or 2939 die "Failed to checkout $bad"; 2940 2941 $result = run_bisect $type; 2942 2943 if ($result ne "bad") { 2944 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 2945 } 2946 } 2947 2948 if ($check ne "bad") { 2949 doprint "TESTING BISECT GOOD [$good]\n"; 2950 run_command "git checkout $good" or 2951 die "Failed to checkout $good"; 2952 2953 $result = run_bisect $type; 2954 2955 if ($result ne "good") { 2956 fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 2957 } 2958 } 2959 2960 # checkout where we started 2961 run_command "git checkout $head" or 2962 die "Failed to checkout $head"; 2963 } 2964 2965 run_command "git bisect start$start_files" or 2966 dodie "could not start bisect"; 2967 2968 if (defined($replay)) { 2969 run_command "git bisect replay $replay" or 2970 dodie "failed to run replay"; 2971 } else { 2972 2973 run_command "git bisect good $good" or 2974 dodie "could not set bisect good to $good"; 2975 2976 run_git_bisect "git bisect bad $bad" or 2977 dodie "could not set bisect bad to $bad"; 2978 2979 } 2980 2981 if (defined($start)) { 2982 run_command "git checkout $start" or 2983 dodie "failed to checkout $start"; 2984 } 2985 2986 my $test; 2987 do { 2988 $result = run_bisect $type; 2989 $test = run_git_bisect "git bisect $result"; 2990 print_times; 2991 } while ($test); 2992 2993 run_command "git bisect log" or 2994 dodie "could not capture git bisect log"; 2995 2996 run_command "git bisect reset" or 2997 dodie "could not reset git bisect"; 2998 2999 doprint "Bad commit was [$bisect_bad_commit]\n"; 3000 3001 success $i; 3002} 3003 3004# config_ignore holds the configs that were set (or unset) for 3005# a good config and we will ignore these configs for the rest 3006# of a config bisect. These configs stay as they were. 3007my %config_ignore; 3008 3009# config_set holds what all configs were set as. 3010my %config_set; 3011 3012# config_off holds the set of configs that the bad config had disabled. 3013# We need to record them and set them in the .config when running 3014# olddefconfig, because olddefconfig keeps the defaults. 3015my %config_off; 3016 3017# config_off_tmp holds a set of configs to turn off for now 3018my @config_off_tmp; 3019 3020# config_list is the set of configs that are being tested 3021my %config_list; 3022my %null_config; 3023 3024my %dependency; 3025 3026sub assign_configs { 3027 my ($hash, $config) = @_; 3028 3029 doprint "Reading configs from $config\n"; 3030 3031 open (IN, $config) 3032 or dodie "Failed to read $config"; 3033 3034 while (<IN>) { 3035 chomp; 3036 if (/^((CONFIG\S*)=.*)/) { 3037 ${$hash}{$2} = $1; 3038 } elsif (/^(# (CONFIG\S*) is not set)/) { 3039 ${$hash}{$2} = $1; 3040 } 3041 } 3042 3043 close(IN); 3044} 3045 3046sub process_config_ignore { 3047 my ($config) = @_; 3048 3049 assign_configs \%config_ignore, $config; 3050} 3051 3052sub get_dependencies { 3053 my ($config) = @_; 3054 3055 my $arr = $dependency{$config}; 3056 if (!defined($arr)) { 3057 return (); 3058 } 3059 3060 my @deps = @{$arr}; 3061 3062 foreach my $dep (@{$arr}) { 3063 print "ADD DEP $dep\n"; 3064 @deps = (@deps, get_dependencies $dep); 3065 } 3066 3067 return @deps; 3068} 3069 3070sub save_config { 3071 my ($pc, $file) = @_; 3072 3073 my %configs = %{$pc}; 3074 3075 doprint "Saving configs into $file\n"; 3076 3077 open(OUT, ">$file") or dodie "Can not write to $file"; 3078 3079 foreach my $config (keys %configs) { 3080 print OUT "$configs{$config}\n"; 3081 } 3082 close(OUT); 3083} 3084 3085sub create_config { 3086 my ($name, $pc) = @_; 3087 3088 doprint "Creating old config from $name configs\n"; 3089 3090 save_config $pc, $output_config; 3091 3092 make_oldconfig; 3093} 3094 3095# compare two config hashes, and return configs with different vals. 3096# It returns B's config values, but you can use A to see what A was. 3097sub diff_config_vals { 3098 my ($pa, $pb) = @_; 3099 3100 # crappy Perl way to pass in hashes. 3101 my %a = %{$pa}; 3102 my %b = %{$pb}; 3103 3104 my %ret; 3105 3106 foreach my $item (keys %a) { 3107 if (defined($b{$item}) && $b{$item} ne $a{$item}) { 3108 $ret{$item} = $b{$item}; 3109 } 3110 } 3111 3112 return %ret; 3113} 3114 3115# compare two config hashes and return the configs in B but not A 3116sub diff_configs { 3117 my ($pa, $pb) = @_; 3118 3119 my %ret; 3120 3121 # crappy Perl way to pass in hashes. 3122 my %a = %{$pa}; 3123 my %b = %{$pb}; 3124 3125 foreach my $item (keys %b) { 3126 if (!defined($a{$item})) { 3127 $ret{$item} = $b{$item}; 3128 } 3129 } 3130 3131 return %ret; 3132} 3133 3134# return if two configs are equal or not 3135# 0 is equal +1 b has something a does not 3136# +1 if a and b have a different item. 3137# -1 if a has something b does not 3138sub compare_configs { 3139 my ($pa, $pb) = @_; 3140 3141 my %ret; 3142 3143 # crappy Perl way to pass in hashes. 3144 my %a = %{$pa}; 3145 my %b = %{$pb}; 3146 3147 foreach my $item (keys %b) { 3148 if (!defined($a{$item})) { 3149 return 1; 3150 } 3151 if ($a{$item} ne $b{$item}) { 3152 return 1; 3153 } 3154 } 3155 3156 foreach my $item (keys %a) { 3157 if (!defined($b{$item})) { 3158 return -1; 3159 } 3160 } 3161 3162 return 0; 3163} 3164 3165sub run_config_bisect_test { 3166 my ($type) = @_; 3167 3168 my $ret = run_bisect_test $type, "oldconfig"; 3169 3170 if ($bisect_manual) { 3171 $ret = answer_bisect; 3172 } 3173 3174 return $ret; 3175} 3176 3177sub process_failed { 3178 my ($config) = @_; 3179 3180 doprint "\n\n***************************************\n"; 3181 doprint "Found bad config: $config\n"; 3182 doprint "***************************************\n\n"; 3183} 3184 3185# used for config bisecting 3186my $good_config; 3187my $bad_config; 3188 3189sub process_new_config { 3190 my ($tc, $nc, $gc, $bc) = @_; 3191 3192 my %tmp_config = %{$tc}; 3193 my %good_configs = %{$gc}; 3194 my %bad_configs = %{$bc}; 3195 3196 my %new_configs; 3197 3198 my $runtest = 1; 3199 my $ret; 3200 3201 create_config "tmp_configs", \%tmp_config; 3202 assign_configs \%new_configs, $output_config; 3203 3204 $ret = compare_configs \%new_configs, \%bad_configs; 3205 if (!$ret) { 3206 doprint "New config equals bad config, try next test\n"; 3207 $runtest = 0; 3208 } 3209 3210 if ($runtest) { 3211 $ret = compare_configs \%new_configs, \%good_configs; 3212 if (!$ret) { 3213 doprint "New config equals good config, try next test\n"; 3214 $runtest = 0; 3215 } 3216 } 3217 3218 %{$nc} = %new_configs; 3219 3220 return $runtest; 3221} 3222 3223sub run_config_bisect { 3224 my ($pgood, $pbad) = @_; 3225 3226 my $type = $config_bisect_type; 3227 3228 my %good_configs = %{$pgood}; 3229 my %bad_configs = %{$pbad}; 3230 3231 my %diff_configs = diff_config_vals \%good_configs, \%bad_configs; 3232 my %b_configs = diff_configs \%good_configs, \%bad_configs; 3233 my %g_configs = diff_configs \%bad_configs, \%good_configs; 3234 3235 my @diff_arr = keys %diff_configs; 3236 my $len_diff = $#diff_arr + 1; 3237 3238 my @b_arr = keys %b_configs; 3239 my $len_b = $#b_arr + 1; 3240 3241 my @g_arr = keys %g_configs; 3242 my $len_g = $#g_arr + 1; 3243 3244 my $runtest = 1; 3245 my %new_configs; 3246 my $ret; 3247 3248 # First, lets get it down to a single subset. 3249 # Is the problem with a difference in values? 3250 # Is the problem with a missing config? 3251 # Is the problem with a config that breaks things? 3252 3253 # Enable all of one set and see if we get a new bad 3254 # or good config. 3255 3256 # first set the good config to the bad values. 3257 3258 doprint "d=$len_diff g=$len_g b=$len_b\n"; 3259 3260 # first lets enable things in bad config that are enabled in good config 3261 3262 if ($len_diff > 0) { 3263 if ($len_b > 0 || $len_g > 0) { 3264 my %tmp_config = %bad_configs; 3265 3266 doprint "Set tmp config to be bad config with good config values\n"; 3267 foreach my $item (@diff_arr) { 3268 $tmp_config{$item} = $good_configs{$item}; 3269 } 3270 3271 $runtest = process_new_config \%tmp_config, \%new_configs, 3272 \%good_configs, \%bad_configs; 3273 } 3274 } 3275 3276 if (!$runtest && $len_diff > 0) { 3277 3278 if ($len_diff == 1) { 3279 process_failed $diff_arr[0]; 3280 return 1; 3281 } 3282 my %tmp_config = %bad_configs; 3283 3284 my $half = int($#diff_arr / 2); 3285 my @tophalf = @diff_arr[0 .. $half]; 3286 3287 doprint "Settings bisect with top half:\n"; 3288 doprint "Set tmp config to be bad config with some good config values\n"; 3289 foreach my $item (@tophalf) { 3290 $tmp_config{$item} = $good_configs{$item}; 3291 } 3292 3293 $runtest = process_new_config \%tmp_config, \%new_configs, 3294 \%good_configs, \%bad_configs; 3295 3296 if (!$runtest) { 3297 my %tmp_config = %bad_configs; 3298 3299 doprint "Try bottom half\n"; 3300 3301 my @bottomhalf = @diff_arr[$half+1 .. $#diff_arr]; 3302 3303 foreach my $item (@bottomhalf) { 3304 $tmp_config{$item} = $good_configs{$item}; 3305 } 3306 3307 $runtest = process_new_config \%tmp_config, \%new_configs, 3308 \%good_configs, \%bad_configs; 3309 } 3310 } 3311 3312 if ($runtest) { 3313 $ret = run_config_bisect_test $type; 3314 if ($ret) { 3315 doprint "NEW GOOD CONFIG\n"; 3316 %good_configs = %new_configs; 3317 run_command "mv $good_config ${good_config}.last"; 3318 save_config \%good_configs, $good_config; 3319 %{$pgood} = %good_configs; 3320 } else { 3321 doprint "NEW BAD CONFIG\n"; 3322 %bad_configs = %new_configs; 3323 run_command "mv $bad_config ${bad_config}.last"; 3324 save_config \%bad_configs, $bad_config; 3325 %{$pbad} = %bad_configs; 3326 } 3327 return 0; 3328 } 3329 3330 fail "Hmm, need to do a mix match?\n"; 3331 return -1; 3332} 3333 3334sub config_bisect { 3335 my ($i) = @_; 3336 3337 my $type = $config_bisect_type; 3338 my $ret; 3339 3340 $bad_config = $config_bisect; 3341 3342 if (defined($config_bisect_good)) { 3343 $good_config = $config_bisect_good; 3344 } elsif (defined($minconfig)) { 3345 $good_config = $minconfig; 3346 } else { 3347 doprint "No config specified, checking if defconfig works"; 3348 $ret = run_bisect_test $type, "defconfig"; 3349 if (!$ret) { 3350 fail "Have no good config to compare with, please set CONFIG_BISECT_GOOD"; 3351 return 1; 3352 } 3353 $good_config = $output_config; 3354 } 3355 3356 # we don't want min configs to cause issues here. 3357 doprint "Disabling 'MIN_CONFIG' for this test\n"; 3358 undef $minconfig; 3359 3360 my %good_configs; 3361 my %bad_configs; 3362 my %tmp_configs; 3363 3364 doprint "Run good configs through make oldconfig\n"; 3365 assign_configs \%tmp_configs, $good_config; 3366 create_config "$good_config", \%tmp_configs; 3367 assign_configs \%good_configs, $output_config; 3368 3369 doprint "Run bad configs through make oldconfig\n"; 3370 assign_configs \%tmp_configs, $bad_config; 3371 create_config "$bad_config", \%tmp_configs; 3372 assign_configs \%bad_configs, $output_config; 3373 3374 $good_config = "$tmpdir/good_config"; 3375 $bad_config = "$tmpdir/bad_config"; 3376 3377 save_config \%good_configs, $good_config; 3378 save_config \%bad_configs, $bad_config; 3379 3380 if (defined($config_bisect_check) && $config_bisect_check ne "0") { 3381 if ($config_bisect_check ne "good") { 3382 doprint "Testing bad config\n"; 3383 3384 $ret = run_bisect_test $type, "useconfig:$bad_config"; 3385 if ($ret) { 3386 fail "Bad config succeeded when expected to fail!"; 3387 return 0; 3388 } 3389 } 3390 if ($config_bisect_check ne "bad") { 3391 doprint "Testing good config\n"; 3392 3393 $ret = run_bisect_test $type, "useconfig:$good_config"; 3394 if (!$ret) { 3395 fail "Good config failed when expected to succeed!"; 3396 return 0; 3397 } 3398 } 3399 } 3400 3401 do { 3402 $ret = run_config_bisect \%good_configs, \%bad_configs; 3403 print_times; 3404 } while (!$ret); 3405 3406 return $ret if ($ret < 0); 3407 3408 success $i; 3409} 3410 3411sub patchcheck_reboot { 3412 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 3413 reboot_to_good $patchcheck_sleep_time; 3414} 3415 3416sub patchcheck { 3417 my ($i) = @_; 3418 3419 die "PATCHCHECK_START[$i] not defined\n" 3420 if (!defined($patchcheck_start)); 3421 die "PATCHCHECK_TYPE[$i] not defined\n" 3422 if (!defined($patchcheck_type)); 3423 3424 my $start = $patchcheck_start; 3425 3426 my $cherry = $patchcheck_cherry; 3427 if (!defined($cherry)) { 3428 $cherry = 0; 3429 } 3430 3431 my $end = "HEAD"; 3432 if (defined($patchcheck_end)) { 3433 $end = $patchcheck_end; 3434 } elsif ($cherry) { 3435 die "PATCHCHECK_END must be defined with PATCHCHECK_CHERRY\n"; 3436 } 3437 3438 # Get the true sha1's since we can use things like HEAD~3 3439 $start = get_sha1($start); 3440 $end = get_sha1($end); 3441 3442 my $type = $patchcheck_type; 3443 3444 # Can't have a test without having a test to run 3445 if ($type eq "test" && !defined($run_test)) { 3446 $type = "boot"; 3447 } 3448 3449 if ($cherry) { 3450 open (IN, "git cherry -v $start $end|") or 3451 dodie "could not get git list"; 3452 } else { 3453 open (IN, "git log --pretty=oneline $end|") or 3454 dodie "could not get git list"; 3455 } 3456 3457 my @list; 3458 3459 while (<IN>) { 3460 chomp; 3461 # git cherry adds a '+' we want to remove 3462 s/^\+ //; 3463 $list[$#list+1] = $_; 3464 last if (/^$start/); 3465 } 3466 close(IN); 3467 3468 if (!$cherry) { 3469 if ($list[$#list] !~ /^$start/) { 3470 fail "SHA1 $start not found"; 3471 } 3472 3473 # go backwards in the list 3474 @list = reverse @list; 3475 } 3476 3477 doprint("Going to test the following commits:\n"); 3478 foreach my $l (@list) { 3479 doprint "$l\n"; 3480 } 3481 3482 my $save_clean = $noclean; 3483 my %ignored_warnings; 3484 3485 if (defined($ignore_warnings)) { 3486 foreach my $sha1 (split /\s+/, $ignore_warnings) { 3487 $ignored_warnings{$sha1} = 1; 3488 } 3489 } 3490 3491 $in_patchcheck = 1; 3492 foreach my $item (@list) { 3493 my $sha1 = $item; 3494 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 3495 3496 doprint "\nProcessing commit \"$item\"\n\n"; 3497 3498 run_command "git checkout $sha1" or 3499 die "Failed to checkout $sha1"; 3500 3501 # only clean on the first and last patch 3502 if ($item eq $list[0] || 3503 $item eq $list[$#list]) { 3504 $noclean = $save_clean; 3505 } else { 3506 $noclean = 1; 3507 } 3508 3509 if (defined($minconfig)) { 3510 build "useconfig:$minconfig" or return 0; 3511 } else { 3512 # ?? no config to use? 3513 build "oldconfig" or return 0; 3514 } 3515 3516 # No need to do per patch checking if warnings file exists 3517 if (!defined($warnings_file) && !defined($ignored_warnings{$sha1})) { 3518 check_patch_buildlog $sha1 or return 0; 3519 } 3520 3521 check_buildlog or return 0; 3522 3523 next if ($type eq "build"); 3524 3525 my $failed = 0; 3526 3527 start_monitor_and_install or $failed = 1; 3528 3529 if (!$failed && $type ne "boot"){ 3530 do_run_test or $failed = 1; 3531 } 3532 end_monitor; 3533 if ($failed) { 3534 print_times; 3535 return 0; 3536 } 3537 patchcheck_reboot; 3538 print_times; 3539 } 3540 $in_patchcheck = 0; 3541 success $i; 3542 3543 return 1; 3544} 3545 3546my %depends; 3547my %depcount; 3548my $iflevel = 0; 3549my @ifdeps; 3550 3551# prevent recursion 3552my %read_kconfigs; 3553 3554sub add_dep { 3555 # $config depends on $dep 3556 my ($config, $dep) = @_; 3557 3558 if (defined($depends{$config})) { 3559 $depends{$config} .= " " . $dep; 3560 } else { 3561 $depends{$config} = $dep; 3562 } 3563 3564 # record the number of configs depending on $dep 3565 if (defined $depcount{$dep}) { 3566 $depcount{$dep}++; 3567 } else { 3568 $depcount{$dep} = 1; 3569 } 3570} 3571 3572# taken from streamline_config.pl 3573sub read_kconfig { 3574 my ($kconfig) = @_; 3575 3576 my $state = "NONE"; 3577 my $config; 3578 my @kconfigs; 3579 3580 my $cont = 0; 3581 my $line; 3582 3583 3584 if (! -f $kconfig) { 3585 doprint "file $kconfig does not exist, skipping\n"; 3586 return; 3587 } 3588 3589 open(KIN, "$kconfig") 3590 or die "Can't open $kconfig"; 3591 while (<KIN>) { 3592 chomp; 3593 3594 # Make sure that lines ending with \ continue 3595 if ($cont) { 3596 $_ = $line . " " . $_; 3597 } 3598 3599 if (s/\\$//) { 3600 $cont = 1; 3601 $line = $_; 3602 next; 3603 } 3604 3605 $cont = 0; 3606 3607 # collect any Kconfig sources 3608 if (/^source\s*"(.*)"/) { 3609 $kconfigs[$#kconfigs+1] = $1; 3610 } 3611 3612 # configs found 3613 if (/^\s*(menu)?config\s+(\S+)\s*$/) { 3614 $state = "NEW"; 3615 $config = $2; 3616 3617 for (my $i = 0; $i < $iflevel; $i++) { 3618 add_dep $config, $ifdeps[$i]; 3619 } 3620 3621 # collect the depends for the config 3622 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { 3623 3624 add_dep $config, $1; 3625 3626 # Get the configs that select this config 3627 } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) { 3628 3629 # selected by depends on config 3630 add_dep $1, $config; 3631 3632 # Check for if statements 3633 } elsif (/^if\s+(.*\S)\s*$/) { 3634 my $deps = $1; 3635 # remove beginning and ending non text 3636 $deps =~ s/^[^a-zA-Z0-9_]*//; 3637 $deps =~ s/[^a-zA-Z0-9_]*$//; 3638 3639 my @deps = split /[^a-zA-Z0-9_]+/, $deps; 3640 3641 $ifdeps[$iflevel++] = join ':', @deps; 3642 3643 } elsif (/^endif/) { 3644 3645 $iflevel-- if ($iflevel); 3646 3647 # stop on "help" 3648 } elsif (/^\s*help\s*$/) { 3649 $state = "NONE"; 3650 } 3651 } 3652 close(KIN); 3653 3654 # read in any configs that were found. 3655 foreach $kconfig (@kconfigs) { 3656 if (!defined($read_kconfigs{$kconfig})) { 3657 $read_kconfigs{$kconfig} = 1; 3658 read_kconfig("$builddir/$kconfig"); 3659 } 3660 } 3661} 3662 3663sub read_depends { 3664 # find out which arch this is by the kconfig file 3665 open (IN, $output_config) 3666 or dodie "Failed to read $output_config"; 3667 my $arch; 3668 while (<IN>) { 3669 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) { 3670 $arch = $1; 3671 last; 3672 } 3673 } 3674 close IN; 3675 3676 if (!defined($arch)) { 3677 doprint "Could not find arch from config file\n"; 3678 doprint "no dependencies used\n"; 3679 return; 3680 } 3681 3682 # arch is really the subarch, we need to know 3683 # what directory to look at. 3684 if ($arch eq "i386" || $arch eq "x86_64") { 3685 $arch = "x86"; 3686 } 3687 3688 my $kconfig = "$builddir/arch/$arch/Kconfig"; 3689 3690 if (! -f $kconfig && $arch =~ /\d$/) { 3691 my $orig = $arch; 3692 # some subarchs have numbers, truncate them 3693 $arch =~ s/\d*$//; 3694 $kconfig = "$builddir/arch/$arch/Kconfig"; 3695 if (! -f $kconfig) { 3696 doprint "No idea what arch dir $orig is for\n"; 3697 doprint "no dependencies used\n"; 3698 return; 3699 } 3700 } 3701 3702 read_kconfig($kconfig); 3703} 3704 3705sub make_new_config { 3706 my @configs = @_; 3707 3708 open (OUT, ">$output_config") 3709 or dodie "Failed to write $output_config"; 3710 3711 foreach my $config (@configs) { 3712 print OUT "$config\n"; 3713 } 3714 close OUT; 3715} 3716 3717sub chomp_config { 3718 my ($config) = @_; 3719 3720 $config =~ s/CONFIG_//; 3721 3722 return $config; 3723} 3724 3725sub get_depends { 3726 my ($dep) = @_; 3727 3728 my $kconfig = chomp_config $dep; 3729 3730 $dep = $depends{"$kconfig"}; 3731 3732 # the dep string we have saves the dependencies as they 3733 # were found, including expressions like ! && ||. We 3734 # want to split this out into just an array of configs. 3735 3736 my $valid = "A-Za-z_0-9"; 3737 3738 my @configs; 3739 3740 while ($dep =~ /[$valid]/) { 3741 3742 if ($dep =~ /^[^$valid]*([$valid]+)/) { 3743 my $conf = "CONFIG_" . $1; 3744 3745 $configs[$#configs + 1] = $conf; 3746 3747 $dep =~ s/^[^$valid]*[$valid]+//; 3748 } else { 3749 die "this should never happen"; 3750 } 3751 } 3752 3753 return @configs; 3754} 3755 3756my %min_configs; 3757my %keep_configs; 3758my %save_configs; 3759my %processed_configs; 3760my %nochange_config; 3761 3762sub test_this_config { 3763 my ($config) = @_; 3764 3765 my $found; 3766 3767 # if we already processed this config, skip it 3768 if (defined($processed_configs{$config})) { 3769 return undef; 3770 } 3771 $processed_configs{$config} = 1; 3772 3773 # if this config failed during this round, skip it 3774 if (defined($nochange_config{$config})) { 3775 return undef; 3776 } 3777 3778 my $kconfig = chomp_config $config; 3779 3780 # Test dependencies first 3781 if (defined($depends{"$kconfig"})) { 3782 my @parents = get_depends $config; 3783 foreach my $parent (@parents) { 3784 # if the parent is in the min config, check it first 3785 next if (!defined($min_configs{$parent})); 3786 $found = test_this_config($parent); 3787 if (defined($found)) { 3788 return $found; 3789 } 3790 } 3791 } 3792 3793 # Remove this config from the list of configs 3794 # do a make olddefconfig and then read the resulting 3795 # .config to make sure it is missing the config that 3796 # we had before 3797 my %configs = %min_configs; 3798 delete $configs{$config}; 3799 make_new_config ((values %configs), (values %keep_configs)); 3800 make_oldconfig; 3801 undef %configs; 3802 assign_configs \%configs, $output_config; 3803 3804 if (!defined($configs{$config}) || $configs{$config} =~ /^#/) { 3805 return $config; 3806 } 3807 3808 doprint "disabling config $config did not change .config\n"; 3809 3810 $nochange_config{$config} = 1; 3811 3812 return undef; 3813} 3814 3815sub make_min_config { 3816 my ($i) = @_; 3817 3818 my $type = $minconfig_type; 3819 if ($type ne "boot" && $type ne "test") { 3820 fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" . 3821 " make_min_config works only with 'boot' and 'test'\n" and return; 3822 } 3823 3824 if (!defined($output_minconfig)) { 3825 fail "OUTPUT_MIN_CONFIG not defined" and return; 3826 } 3827 3828 # If output_minconfig exists, and the start_minconfig 3829 # came from min_config, than ask if we should use 3830 # that instead. 3831 if (-f $output_minconfig && !$start_minconfig_defined) { 3832 print "$output_minconfig exists\n"; 3833 if (!defined($use_output_minconfig)) { 3834 if (read_yn " Use it as minconfig?") { 3835 $start_minconfig = $output_minconfig; 3836 } 3837 } elsif ($use_output_minconfig > 0) { 3838 doprint "Using $output_minconfig as MIN_CONFIG\n"; 3839 $start_minconfig = $output_minconfig; 3840 } else { 3841 doprint "Set to still use MIN_CONFIG as starting point\n"; 3842 } 3843 } 3844 3845 if (!defined($start_minconfig)) { 3846 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; 3847 } 3848 3849 my $temp_config = "$tmpdir/temp_config"; 3850 3851 # First things first. We build an allnoconfig to find 3852 # out what the defaults are that we can't touch. 3853 # Some are selections, but we really can't handle selections. 3854 3855 my $save_minconfig = $minconfig; 3856 undef $minconfig; 3857 3858 run_command "$make allnoconfig" or return 0; 3859 3860 read_depends; 3861 3862 process_config_ignore $output_config; 3863 3864 undef %save_configs; 3865 undef %min_configs; 3866 3867 if (defined($ignore_config)) { 3868 # make sure the file exists 3869 `touch $ignore_config`; 3870 assign_configs \%save_configs, $ignore_config; 3871 } 3872 3873 %keep_configs = %save_configs; 3874 3875 doprint "Load initial configs from $start_minconfig\n"; 3876 3877 # Look at the current min configs, and save off all the 3878 # ones that were set via the allnoconfig 3879 assign_configs \%min_configs, $start_minconfig; 3880 3881 my @config_keys = keys %min_configs; 3882 3883 # All configs need a depcount 3884 foreach my $config (@config_keys) { 3885 my $kconfig = chomp_config $config; 3886 if (!defined $depcount{$kconfig}) { 3887 $depcount{$kconfig} = 0; 3888 } 3889 } 3890 3891 # Remove anything that was set by the make allnoconfig 3892 # we shouldn't need them as they get set for us anyway. 3893 foreach my $config (@config_keys) { 3894 # Remove anything in the ignore_config 3895 if (defined($keep_configs{$config})) { 3896 my $file = $ignore_config; 3897 $file =~ s,.*/(.*?)$,$1,; 3898 doprint "$config set by $file ... ignored\n"; 3899 delete $min_configs{$config}; 3900 next; 3901 } 3902 # But make sure the settings are the same. If a min config 3903 # sets a selection, we do not want to get rid of it if 3904 # it is not the same as what we have. Just move it into 3905 # the keep configs. 3906 if (defined($config_ignore{$config})) { 3907 if ($config_ignore{$config} ne $min_configs{$config}) { 3908 doprint "$config is in allnoconfig as '$config_ignore{$config}'"; 3909 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n"; 3910 $keep_configs{$config} = $min_configs{$config}; 3911 } else { 3912 doprint "$config set by allnoconfig ... ignored\n"; 3913 } 3914 delete $min_configs{$config}; 3915 } 3916 } 3917 3918 my $done = 0; 3919 my $take_two = 0; 3920 3921 while (!$done) { 3922 3923 my $config; 3924 my $found; 3925 3926 # Now disable each config one by one and do a make oldconfig 3927 # till we find a config that changes our list. 3928 3929 my @test_configs = keys %min_configs; 3930 3931 # Sort keys by who is most dependent on 3932 @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} } 3933 @test_configs ; 3934 3935 # Put configs that did not modify the config at the end. 3936 my $reset = 1; 3937 for (my $i = 0; $i < $#test_configs; $i++) { 3938 if (!defined($nochange_config{$test_configs[0]})) { 3939 $reset = 0; 3940 last; 3941 } 3942 # This config didn't change the .config last time. 3943 # Place it at the end 3944 my $config = shift @test_configs; 3945 push @test_configs, $config; 3946 } 3947 3948 # if every test config has failed to modify the .config file 3949 # in the past, then reset and start over. 3950 if ($reset) { 3951 undef %nochange_config; 3952 } 3953 3954 undef %processed_configs; 3955 3956 foreach my $config (@test_configs) { 3957 3958 $found = test_this_config $config; 3959 3960 last if (defined($found)); 3961 3962 # oh well, try another config 3963 } 3964 3965 if (!defined($found)) { 3966 # we could have failed due to the nochange_config hash 3967 # reset and try again 3968 if (!$take_two) { 3969 undef %nochange_config; 3970 $take_two = 1; 3971 next; 3972 } 3973 doprint "No more configs found that we can disable\n"; 3974 $done = 1; 3975 last; 3976 } 3977 $take_two = 0; 3978 3979 $config = $found; 3980 3981 doprint "Test with $config disabled\n"; 3982 3983 # set in_bisect to keep build and monitor from dieing 3984 $in_bisect = 1; 3985 3986 my $failed = 0; 3987 build "oldconfig" or $failed = 1; 3988 if (!$failed) { 3989 start_monitor_and_install or $failed = 1; 3990 3991 if ($type eq "test" && !$failed) { 3992 do_run_test or $failed = 1; 3993 } 3994 3995 end_monitor; 3996 } 3997 3998 $in_bisect = 0; 3999 4000 if ($failed) { 4001 doprint "$min_configs{$config} is needed to boot the box... keeping\n"; 4002 # this config is needed, add it to the ignore list. 4003 $keep_configs{$config} = $min_configs{$config}; 4004 $save_configs{$config} = $min_configs{$config}; 4005 delete $min_configs{$config}; 4006 4007 # update new ignore configs 4008 if (defined($ignore_config)) { 4009 open (OUT, ">$temp_config") 4010 or die "Can't write to $temp_config"; 4011 foreach my $config (keys %save_configs) { 4012 print OUT "$save_configs{$config}\n"; 4013 } 4014 close OUT; 4015 run_command "mv $temp_config $ignore_config" or 4016 dodie "failed to copy update to $ignore_config"; 4017 } 4018 4019 } else { 4020 # We booted without this config, remove it from the minconfigs. 4021 doprint "$config is not needed, disabling\n"; 4022 4023 delete $min_configs{$config}; 4024 4025 # Also disable anything that is not enabled in this config 4026 my %configs; 4027 assign_configs \%configs, $output_config; 4028 my @config_keys = keys %min_configs; 4029 foreach my $config (@config_keys) { 4030 if (!defined($configs{$config})) { 4031 doprint "$config is not set, disabling\n"; 4032 delete $min_configs{$config}; 4033 } 4034 } 4035 4036 # Save off all the current mandatory configs 4037 open (OUT, ">$temp_config") 4038 or die "Can't write to $temp_config"; 4039 foreach my $config (keys %keep_configs) { 4040 print OUT "$keep_configs{$config}\n"; 4041 } 4042 foreach my $config (keys %min_configs) { 4043 print OUT "$min_configs{$config}\n"; 4044 } 4045 close OUT; 4046 4047 run_command "mv $temp_config $output_minconfig" or 4048 dodie "failed to copy update to $output_minconfig"; 4049 } 4050 4051 doprint "Reboot and wait $sleep_time seconds\n"; 4052 reboot_to_good $sleep_time; 4053 } 4054 4055 success $i; 4056 return 1; 4057} 4058 4059sub make_warnings_file { 4060 my ($i) = @_; 4061 4062 if (!defined($warnings_file)) { 4063 dodie "Must define WARNINGS_FILE for make_warnings_file test"; 4064 } 4065 4066 if ($build_type eq "nobuild") { 4067 dodie "BUILD_TYPE can not be 'nobuild' for make_warnings_file test"; 4068 } 4069 4070 build $build_type or dodie "Failed to build"; 4071 4072 open(OUT, ">$warnings_file") or dodie "Can't create $warnings_file"; 4073 4074 open(IN, $buildlog) or dodie "Can't open $buildlog"; 4075 while (<IN>) { 4076 4077 # Some compilers use UTF-8 extended for quotes 4078 # for distcc heterogeneous systems, this causes issues 4079 s/$utf8_quote/'/g; 4080 4081 if (/$check_build_re/) { 4082 print OUT; 4083 } 4084 } 4085 close(IN); 4086 4087 close(OUT); 4088 4089 success $i; 4090} 4091 4092$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl [config-file]\n"; 4093 4094if ($#ARGV == 0) { 4095 $ktest_config = $ARGV[0]; 4096 if (! -f $ktest_config) { 4097 print "$ktest_config does not exist.\n"; 4098 if (!read_yn "Create it?") { 4099 exit 0; 4100 } 4101 } 4102} 4103 4104if (! -f $ktest_config) { 4105 $newconfig = 1; 4106 get_test_case; 4107 open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 4108 print OUT << "EOF" 4109# Generated by ktest.pl 4110# 4111 4112# PWD is a ktest.pl variable that will result in the process working 4113# directory that ktest.pl is executed in. 4114 4115# THIS_DIR is automatically assigned the PWD of the path that generated 4116# the config file. It is best to use this variable when assigning other 4117# directory paths within this directory. This allows you to easily 4118# move the test cases to other locations or to other machines. 4119# 4120THIS_DIR := $variable{"PWD"} 4121 4122# Define each test with TEST_START 4123# The config options below it will override the defaults 4124TEST_START 4125TEST_TYPE = $default{"TEST_TYPE"} 4126 4127DEFAULTS 4128EOF 4129; 4130 close(OUT); 4131} 4132read_config $ktest_config; 4133 4134if (defined($opt{"LOG_FILE"})) { 4135 $opt{"LOG_FILE"} = eval_option("LOG_FILE", $opt{"LOG_FILE"}, -1); 4136} 4137 4138# Append any configs entered in manually to the config file. 4139my @new_configs = keys %entered_configs; 4140if ($#new_configs >= 0) { 4141 print "\nAppending entered in configs to $ktest_config\n"; 4142 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 4143 foreach my $config (@new_configs) { 4144 print OUT "$config = $entered_configs{$config}\n"; 4145 $opt{$config} = process_variables($entered_configs{$config}); 4146 } 4147} 4148 4149if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 4150 unlink $opt{"LOG_FILE"}; 4151} 4152 4153doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 4154 4155for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 4156 4157 if (!$i) { 4158 doprint "DEFAULT OPTIONS:\n"; 4159 } else { 4160 doprint "\nTEST $i OPTIONS"; 4161 if (defined($repeat_tests{$i})) { 4162 $repeat = $repeat_tests{$i}; 4163 doprint " ITERATE $repeat"; 4164 } 4165 doprint "\n"; 4166 } 4167 4168 foreach my $option (sort keys %opt) { 4169 4170 if ($option =~ /\[(\d+)\]$/) { 4171 next if ($i != $1); 4172 } else { 4173 next if ($i); 4174 } 4175 4176 doprint "$option = $opt{$option}\n"; 4177 } 4178} 4179 4180sub option_defined { 4181 my ($option) = @_; 4182 4183 if (defined($opt{$option}) && $opt{$option} !~ /^\s*$/) { 4184 return 1; 4185 } 4186 4187 return 0; 4188} 4189 4190sub __set_test_option { 4191 my ($name, $i) = @_; 4192 4193 my $option = "$name\[$i\]"; 4194 4195 if (option_defined($option)) { 4196 return $opt{$option}; 4197 } 4198 4199 foreach my $test (keys %repeat_tests) { 4200 if ($i >= $test && 4201 $i < $test + $repeat_tests{$test}) { 4202 $option = "$name\[$test\]"; 4203 if (option_defined($option)) { 4204 return $opt{$option}; 4205 } 4206 } 4207 } 4208 4209 if (option_defined($name)) { 4210 return $opt{$name}; 4211 } 4212 4213 return undef; 4214} 4215 4216sub set_test_option { 4217 my ($name, $i) = @_; 4218 4219 my $option = __set_test_option($name, $i); 4220 return $option if (!defined($option)); 4221 4222 return eval_option($name, $option, $i); 4223} 4224 4225# First we need to do is the builds 4226for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 4227 4228 # Do not reboot on failing test options 4229 $no_reboot = 1; 4230 $reboot_success = 0; 4231 4232 $have_version = 0; 4233 4234 $iteration = $i; 4235 4236 $build_time = 0; 4237 $install_time = 0; 4238 $reboot_time = 0; 4239 $test_time = 0; 4240 4241 undef %force_config; 4242 4243 my $makecmd = set_test_option("MAKE_CMD", $i); 4244 4245 $outputdir = set_test_option("OUTPUT_DIR", $i); 4246 $builddir = set_test_option("BUILD_DIR", $i); 4247 4248 chdir $builddir || die "can't change directory to $builddir"; 4249 4250 if (!-d $outputdir) { 4251 mkpath($outputdir) or 4252 die "can't create $outputdir"; 4253 } 4254 4255 $make = "$makecmd O=$outputdir"; 4256 4257 # Load all the options into their mapped variable names 4258 foreach my $opt (keys %option_map) { 4259 ${$option_map{$opt}} = set_test_option($opt, $i); 4260 } 4261 4262 $start_minconfig_defined = 1; 4263 4264 # The first test may override the PRE_KTEST option 4265 if (defined($pre_ktest) && $i == 1) { 4266 doprint "\n"; 4267 run_command $pre_ktest; 4268 } 4269 4270 # Any test can override the POST_KTEST option 4271 # The last test takes precedence. 4272 if (defined($post_ktest)) { 4273 $final_post_ktest = $post_ktest; 4274 } 4275 4276 if (!defined($start_minconfig)) { 4277 $start_minconfig_defined = 0; 4278 $start_minconfig = $minconfig; 4279 } 4280 4281 if (!-d $tmpdir) { 4282 mkpath($tmpdir) or 4283 die "can't create $tmpdir"; 4284 } 4285 4286 $ENV{"SSH_USER"} = $ssh_user; 4287 $ENV{"MACHINE"} = $machine; 4288 4289 $buildlog = "$tmpdir/buildlog-$machine"; 4290 $testlog = "$tmpdir/testlog-$machine"; 4291 $dmesg = "$tmpdir/dmesg-$machine"; 4292 $output_config = "$outputdir/.config"; 4293 4294 if (!$buildonly) { 4295 $target = "$ssh_user\@$machine"; 4296 if ($reboot_type eq "grub") { 4297 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 4298 } elsif ($reboot_type eq "grub2") { 4299 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 4300 dodie "GRUB_FILE not defined" if (!defined($grub_file)); 4301 } elsif ($reboot_type eq "syslinux") { 4302 dodie "SYSLINUX_LABEL not defined" if (!defined($syslinux_label)); 4303 } 4304 } 4305 4306 my $run_type = $build_type; 4307 if ($test_type eq "patchcheck") { 4308 $run_type = $patchcheck_type; 4309 } elsif ($test_type eq "bisect") { 4310 $run_type = $bisect_type; 4311 } elsif ($test_type eq "config_bisect") { 4312 $run_type = $config_bisect_type; 4313 } elsif ($test_type eq "make_min_config") { 4314 $run_type = ""; 4315 } elsif ($test_type eq "make_warnings_file") { 4316 $run_type = ""; 4317 } 4318 4319 # mistake in config file? 4320 if (!defined($run_type)) { 4321 $run_type = "ERROR"; 4322 } 4323 4324 my $installme = ""; 4325 $installme = " no_install" if ($no_install); 4326 4327 my $name = ""; 4328 4329 if (defined($test_name)) { 4330 $name = " ($test_name)"; 4331 } 4332 4333 doprint "\n\n"; 4334 doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; 4335 4336 if (defined($pre_test)) { 4337 run_command $pre_test; 4338 } 4339 4340 unlink $dmesg; 4341 unlink $buildlog; 4342 unlink $testlog; 4343 4344 if (defined($addconfig)) { 4345 my $min = $minconfig; 4346 if (!defined($minconfig)) { 4347 $min = ""; 4348 } 4349 run_command "cat $addconfig $min > $tmpdir/add_config" or 4350 dodie "Failed to create temp config"; 4351 $minconfig = "$tmpdir/add_config"; 4352 } 4353 4354 if (defined($checkout)) { 4355 run_command "git checkout $checkout" or 4356 die "failed to checkout $checkout"; 4357 } 4358 4359 $no_reboot = 0; 4360 4361 # A test may opt to not reboot the box 4362 if ($reboot_on_success) { 4363 $reboot_success = 1; 4364 } 4365 4366 if ($test_type eq "bisect") { 4367 bisect $i; 4368 next; 4369 } elsif ($test_type eq "config_bisect") { 4370 config_bisect $i; 4371 next; 4372 } elsif ($test_type eq "patchcheck") { 4373 patchcheck $i; 4374 next; 4375 } elsif ($test_type eq "make_min_config") { 4376 make_min_config $i; 4377 next; 4378 } elsif ($test_type eq "make_warnings_file") { 4379 $no_reboot = 1; 4380 make_warnings_file $i; 4381 next; 4382 } 4383 4384 if ($build_type ne "nobuild") { 4385 build $build_type or next; 4386 check_buildlog or next; 4387 } 4388 4389 if ($test_type eq "install") { 4390 get_version; 4391 install; 4392 success $i; 4393 next; 4394 } 4395 4396 if ($test_type ne "build") { 4397 my $failed = 0; 4398 start_monitor_and_install or $failed = 1; 4399 4400 if (!$failed && $test_type ne "boot" && defined($run_test)) { 4401 do_run_test or $failed = 1; 4402 } 4403 end_monitor; 4404 if ($failed) { 4405 print_times; 4406 next; 4407 } 4408 } 4409 4410 print_times; 4411 4412 success $i; 4413} 4414 4415if (defined($final_post_ktest)) { 4416 run_command $final_post_ktest; 4417} 4418 4419if ($opt{"POWEROFF_ON_SUCCESS"}) { 4420 halt; 4421} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) { 4422 reboot_to_good; 4423} elsif (defined($switch_to_good)) { 4424 # still need to get to the good kernel 4425 run_command $switch_to_good; 4426} 4427 4428 4429doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 4430 4431exit 0; 4432