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