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 $skip = 1; 845 } 846 $rest = ""; 847 } else { 848 $if = 0; 849 } 850 } 851 852 if ($rest !~ /^\s*$/) { 853 die "$name: $.: Gargbage found after DEFAULTS\n$_"; 854 } 855 856 } elsif (/^\s*INCLUDE\s+(\S+)/) { 857 858 next if ($skip); 859 860 if (!$default) { 861 die "$name: $.: INCLUDE can only be done in default sections\n$_"; 862 } 863 864 my $file = process_variables($1); 865 866 if ($file !~ m,^/,) { 867 # check the path of the config file first 868 if ($config =~ m,(.*)/,) { 869 if (-f "$1/$file") { 870 $file = "$1/$file"; 871 } 872 } 873 } 874 875 if ( ! -r $file ) { 876 die "$name: $.: Can't read file $file\n$_"; 877 } 878 879 if (__read_config($file, \$test_num)) { 880 $test_case = 1; 881 } 882 883 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 884 885 next if ($skip); 886 887 my $lvalue = $1; 888 my $rvalue = $2; 889 890 if (!$default && 891 ($lvalue eq "NUM_TESTS" || 892 $lvalue eq "LOG_FILE" || 893 $lvalue eq "CLEAR_LOG")) { 894 die "$name: $.: $lvalue must be set in DEFAULTS section\n"; 895 } 896 897 if ($lvalue eq "NUM_TESTS") { 898 if ($test_num) { 899 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 900 } 901 if (!$default) { 902 die "$name: $.: NUM_TESTS must be set in default section\n"; 903 } 904 $num_tests_set = 1; 905 } 906 907 if ($default || $lvalue =~ /\[\d+\]$/) { 908 set_value($lvalue, $rvalue, $override, \%overrides, $name); 909 } else { 910 my $val = "$lvalue\[$test_num\]"; 911 set_value($val, $rvalue, $override, \%overrides, $name); 912 913 if ($repeat > 1) { 914 $repeats{$val} = $repeat; 915 } 916 } 917 } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) { 918 next if ($skip); 919 920 my $lvalue = $1; 921 my $rvalue = $2; 922 923 # process config variables. 924 # Config variables are only active while reading the 925 # config and can be defined anywhere. They also ignore 926 # TEST_START and DEFAULTS, but are skipped if they are in 927 # on of these sections that have SKIP defined. 928 # The save variable can be 929 # defined multiple times and the new one simply overrides 930 # the prevous one. 931 set_variable($lvalue, $rvalue); 932 933 } else { 934 die "$name: $.: Garbage found in config\n$_"; 935 } 936 } 937 938 if ($test_num) { 939 $test_num += $repeat - 1; 940 $opt{"NUM_TESTS"} = $test_num; 941 } 942 943 close($in); 944 945 $$current_test_num = $test_num; 946 947 return $test_case; 948} 949 950sub get_test_case { 951 print "What test case would you like to run?\n"; 952 print " (build, install or boot)\n"; 953 print " Other tests are available but require editing the config file\n"; 954 my $ans = <STDIN>; 955 chomp $ans; 956 $default{"TEST_TYPE"} = $ans; 957} 958 959sub read_config { 960 my ($config) = @_; 961 962 my $test_case; 963 my $test_num = 0; 964 965 $test_case = __read_config $config, \$test_num; 966 967 # make sure we have all mandatory configs 968 get_ktest_configs; 969 970 # was a test specified? 971 if (!$test_case) { 972 print "No test case specified.\n"; 973 get_test_case; 974 } 975 976 # set any defaults 977 978 foreach my $default (keys %default) { 979 if (!defined($opt{$default})) { 980 $opt{$default} = $default{$default}; 981 } 982 } 983 984 if ($opt{"IGNORE_UNUSED"} == 1) { 985 return; 986 } 987 988 my %not_used; 989 990 # check if there are any stragglers (typos?) 991 foreach my $option (keys %opt) { 992 my $op = $option; 993 # remove per test labels. 994 $op =~ s/\[.*\]//; 995 if (!exists($option_map{$op}) && 996 !exists($default{$op}) && 997 !exists($used_options{$op})) { 998 $not_used{$op} = 1; 999 } 1000 } 1001 1002 if (%not_used) { 1003 my $s = "s are"; 1004 $s = " is" if (keys %not_used == 1); 1005 print "The following option$s not used; could be a typo:\n"; 1006 foreach my $option (keys %not_used) { 1007 print "$option\n"; 1008 } 1009 print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n"; 1010 if (!read_yn "Do you want to continue?") { 1011 exit -1; 1012 } 1013 } 1014} 1015 1016sub __eval_option { 1017 my ($option, $i) = @_; 1018 1019 # Add space to evaluate the character before $ 1020 $option = " $option"; 1021 my $retval = ""; 1022 my $repeated = 0; 1023 my $parent = 0; 1024 1025 foreach my $test (keys %repeat_tests) { 1026 if ($i >= $test && 1027 $i < $test + $repeat_tests{$test}) { 1028 1029 $repeated = 1; 1030 $parent = $test; 1031 last; 1032 } 1033 } 1034 1035 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 1036 my $start = $1; 1037 my $var = $2; 1038 my $end = $3; 1039 1040 # Append beginning of line 1041 $retval = "$retval$start"; 1042 1043 # If the iteration option OPT[$i] exists, then use that. 1044 # otherwise see if the default OPT (without [$i]) exists. 1045 1046 my $o = "$var\[$i\]"; 1047 my $parento = "$var\[$parent\]"; 1048 1049 if (defined($opt{$o})) { 1050 $o = $opt{$o}; 1051 $retval = "$retval$o"; 1052 } elsif ($repeated && defined($opt{$parento})) { 1053 $o = $opt{$parento}; 1054 $retval = "$retval$o"; 1055 } elsif (defined($opt{$var})) { 1056 $o = $opt{$var}; 1057 $retval = "$retval$o"; 1058 } else { 1059 $retval = "$retval\$\{$var\}"; 1060 } 1061 1062 $option = $end; 1063 } 1064 1065 $retval = "$retval$option"; 1066 1067 $retval =~ s/^ //; 1068 1069 return $retval; 1070} 1071 1072sub eval_option { 1073 my ($option, $i) = @_; 1074 1075 my $prev = ""; 1076 1077 # Since an option can evaluate to another option, 1078 # keep iterating until we do not evaluate any more 1079 # options. 1080 my $r = 0; 1081 while ($prev ne $option) { 1082 # Check for recursive evaluations. 1083 # 100 deep should be more than enough. 1084 if ($r++ > 100) { 1085 die "Over 100 evaluations accurred with $option\n" . 1086 "Check for recursive variables\n"; 1087 } 1088 $prev = $option; 1089 $option = __eval_option($option, $i); 1090 } 1091 1092 return $option; 1093} 1094 1095sub _logit { 1096 if (defined($opt{"LOG_FILE"})) { 1097 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 1098 print OUT @_; 1099 close(OUT); 1100 } 1101} 1102 1103sub logit { 1104 if (defined($opt{"LOG_FILE"})) { 1105 _logit @_; 1106 } else { 1107 print @_; 1108 } 1109} 1110 1111sub doprint { 1112 print @_; 1113 _logit @_; 1114} 1115 1116sub run_command; 1117sub start_monitor; 1118sub end_monitor; 1119sub wait_for_monitor; 1120 1121sub reboot { 1122 my ($time) = @_; 1123 1124 if (defined($time)) { 1125 start_monitor; 1126 # flush out current monitor 1127 # May contain the reboot success line 1128 wait_for_monitor 1; 1129 } 1130 1131 # try to reboot normally 1132 if (run_command $reboot) { 1133 if (defined($powercycle_after_reboot)) { 1134 sleep $powercycle_after_reboot; 1135 run_command "$power_cycle"; 1136 } 1137 } else { 1138 # nope? power cycle it. 1139 run_command "$power_cycle"; 1140 } 1141 1142 if (defined($time)) { 1143 if (wait_for_monitor($time, $reboot_success_line)) { 1144 # reboot got stuck? 1145 doprint "Reboot did not finish. Forcing power cycle\n"; 1146 run_command "$power_cycle"; 1147 } 1148 end_monitor; 1149 } 1150} 1151 1152sub reboot_to_good { 1153 my ($time) = @_; 1154 1155 if (defined($switch_to_good)) { 1156 run_command $switch_to_good; 1157 } 1158 1159 reboot $time; 1160} 1161 1162sub do_not_reboot { 1163 my $i = $iteration; 1164 1165 return $test_type eq "build" || $no_reboot || 1166 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 1167 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 1168} 1169 1170sub dodie { 1171 doprint "CRITICAL FAILURE... ", @_, "\n"; 1172 1173 my $i = $iteration; 1174 1175 if ($reboot_on_error && !do_not_reboot) { 1176 1177 doprint "REBOOTING\n"; 1178 reboot_to_good; 1179 1180 } elsif ($poweroff_on_error && defined($power_off)) { 1181 doprint "POWERING OFF\n"; 1182 `$power_off`; 1183 } 1184 1185 if (defined($opt{"LOG_FILE"})) { 1186 print " See $opt{LOG_FILE} for more info.\n"; 1187 } 1188 1189 die @_, "\n"; 1190} 1191 1192sub open_console { 1193 my ($fp) = @_; 1194 1195 my $flags; 1196 1197 my $pid = open($fp, "$console|") or 1198 dodie "Can't open console $console"; 1199 1200 $flags = fcntl($fp, F_GETFL, 0) or 1201 dodie "Can't get flags for the socket: $!"; 1202 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 1203 dodie "Can't set flags for the socket: $!"; 1204 1205 return $pid; 1206} 1207 1208sub close_console { 1209 my ($fp, $pid) = @_; 1210 1211 doprint "kill child process $pid\n"; 1212 kill 2, $pid; 1213 1214 print "closing!\n"; 1215 close($fp); 1216} 1217 1218sub start_monitor { 1219 if ($monitor_cnt++) { 1220 return; 1221 } 1222 $monitor_fp = \*MONFD; 1223 $monitor_pid = open_console $monitor_fp; 1224 1225 return; 1226 1227 open(MONFD, "Stop perl from warning about single use of MONFD"); 1228} 1229 1230sub end_monitor { 1231 if (--$monitor_cnt) { 1232 return; 1233 } 1234 close_console($monitor_fp, $monitor_pid); 1235} 1236 1237sub wait_for_monitor { 1238 my ($time, $stop) = @_; 1239 my $full_line = ""; 1240 my $line; 1241 my $booted = 0; 1242 my $start_time = time; 1243 my $skip_call_trace = 0; 1244 my $bug = 0; 1245 my $bug_ignored = 0; 1246 my $now; 1247 1248 doprint "** Wait for monitor to settle down **\n"; 1249 1250 # read the monitor and wait for the system to calm down 1251 while (!$booted) { 1252 $line = wait_for_input($monitor_fp, $time); 1253 last if (!defined($line)); 1254 print "$line"; 1255 $full_line .= $line; 1256 1257 if (defined($stop) && $full_line =~ /$stop/) { 1258 doprint "wait for monitor detected $stop\n"; 1259 $booted = 1; 1260 } 1261 1262 if ($full_line =~ /\[ backtrace testing \]/) { 1263 $skip_call_trace = 1; 1264 } 1265 1266 if ($full_line =~ /call trace:/i) { 1267 if (!$bug && !$skip_call_trace) { 1268 if ($ignore_errors) { 1269 $bug_ignored = 1; 1270 } else { 1271 $bug = 1; 1272 } 1273 } 1274 } 1275 1276 if ($full_line =~ /\[ end of backtrace testing \]/) { 1277 $skip_call_trace = 0; 1278 } 1279 1280 if ($full_line =~ /Kernel panic -/) { 1281 $bug = 1; 1282 } 1283 1284 if ($line =~ /\n/) { 1285 $full_line = ""; 1286 } 1287 $now = time; 1288 if ($now - $start_time >= $max_monitor_wait) { 1289 doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n"; 1290 return 1; 1291 } 1292 } 1293 print "** Monitor flushed **\n"; 1294 return $bug; 1295} 1296 1297sub save_logs { 1298 my ($result, $basedir) = @_; 1299 my @t = localtime; 1300 my $date = sprintf "%04d%02d%02d%02d%02d%02d", 1301 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 1302 1303 my $type = $build_type; 1304 if ($type =~ /useconfig/) { 1305 $type = "useconfig"; 1306 } 1307 1308 my $dir = "$machine-$test_type-$type-$result-$date"; 1309 1310 $dir = "$basedir/$dir"; 1311 1312 if (!-d $dir) { 1313 mkpath($dir) or 1314 die "can't create $dir"; 1315 } 1316 1317 my %files = ( 1318 "config" => $output_config, 1319 "buildlog" => $buildlog, 1320 "dmesg" => $dmesg, 1321 "testlog" => $testlog, 1322 ); 1323 1324 while (my ($name, $source) = each(%files)) { 1325 if (-f "$source") { 1326 cp "$source", "$dir/$name" or 1327 die "failed to copy $source"; 1328 } 1329 } 1330 1331 doprint "*** Saved info to $dir ***\n"; 1332} 1333 1334sub fail { 1335 1336 if (defined($post_test)) { 1337 run_command $post_test; 1338 } 1339 1340 if ($die_on_failure) { 1341 dodie @_; 1342 } 1343 1344 doprint "FAILED\n"; 1345 1346 my $i = $iteration; 1347 1348 # no need to reboot for just building. 1349 if (!do_not_reboot) { 1350 doprint "REBOOTING\n"; 1351 reboot_to_good $sleep_time; 1352 } 1353 1354 my $name = ""; 1355 1356 if (defined($test_name)) { 1357 $name = " ($test_name)"; 1358 } 1359 1360 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1361 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1362 doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n"; 1363 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1364 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1365 1366 if (defined($store_failures)) { 1367 save_logs "fail", $store_failures; 1368 } 1369 1370 return 1; 1371} 1372 1373sub run_command { 1374 my ($command) = @_; 1375 my $dolog = 0; 1376 my $dord = 0; 1377 my $pid; 1378 1379 $command =~ s/\$SSH_USER/$ssh_user/g; 1380 $command =~ s/\$MACHINE/$machine/g; 1381 1382 doprint("$command ... "); 1383 1384 $pid = open(CMD, "$command 2>&1 |") or 1385 (fail "unable to exec $command" and return 0); 1386 1387 if (defined($opt{"LOG_FILE"})) { 1388 open(LOG, ">>$opt{LOG_FILE}") or 1389 dodie "failed to write to log"; 1390 $dolog = 1; 1391 } 1392 1393 if (defined($redirect)) { 1394 open (RD, ">$redirect") or 1395 dodie "failed to write to redirect $redirect"; 1396 $dord = 1; 1397 } 1398 1399 while (<CMD>) { 1400 print LOG if ($dolog); 1401 print RD if ($dord); 1402 } 1403 1404 waitpid($pid, 0); 1405 my $failed = $?; 1406 1407 close(CMD); 1408 close(LOG) if ($dolog); 1409 close(RD) if ($dord); 1410 1411 if ($failed) { 1412 doprint "FAILED!\n"; 1413 } else { 1414 doprint "SUCCESS\n"; 1415 } 1416 1417 return !$failed; 1418} 1419 1420sub run_ssh { 1421 my ($cmd) = @_; 1422 my $cp_exec = $ssh_exec; 1423 1424 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 1425 return run_command "$cp_exec"; 1426} 1427 1428sub run_scp { 1429 my ($src, $dst, $cp_scp) = @_; 1430 1431 $cp_scp =~ s/\$SRC_FILE/$src/g; 1432 $cp_scp =~ s/\$DST_FILE/$dst/g; 1433 1434 return run_command "$cp_scp"; 1435} 1436 1437sub run_scp_install { 1438 my ($src, $dst) = @_; 1439 1440 my $cp_scp = $scp_to_target_install; 1441 1442 return run_scp($src, $dst, $cp_scp); 1443} 1444 1445sub run_scp_mod { 1446 my ($src, $dst) = @_; 1447 1448 my $cp_scp = $scp_to_target; 1449 1450 return run_scp($src, $dst, $cp_scp); 1451} 1452 1453sub get_grub_index { 1454 1455 if ($reboot_type ne "grub") { 1456 return; 1457 } 1458 return if (defined($grub_number)); 1459 1460 doprint "Find grub menu ... "; 1461 $grub_number = -1; 1462 1463 my $ssh_grub = $ssh_exec; 1464 $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 1465 1466 open(IN, "$ssh_grub |") 1467 or die "unable to get menu.lst"; 1468 1469 my $found = 0; 1470 1471 while (<IN>) { 1472 if (/^\s*title\s+$grub_menu\s*$/) { 1473 $grub_number++; 1474 $found = 1; 1475 last; 1476 } elsif (/^\s*title\s/) { 1477 $grub_number++; 1478 } 1479 } 1480 close(IN); 1481 1482 die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 1483 if (!$found); 1484 doprint "$grub_number\n"; 1485} 1486 1487sub wait_for_input 1488{ 1489 my ($fp, $time) = @_; 1490 my $rin; 1491 my $ready; 1492 my $line; 1493 my $ch; 1494 1495 if (!defined($time)) { 1496 $time = $timeout; 1497 } 1498 1499 $rin = ''; 1500 vec($rin, fileno($fp), 1) = 1; 1501 $ready = select($rin, undef, undef, $time); 1502 1503 $line = ""; 1504 1505 # try to read one char at a time 1506 while (sysread $fp, $ch, 1) { 1507 $line .= $ch; 1508 last if ($ch eq "\n"); 1509 } 1510 1511 if (!length($line)) { 1512 return undef; 1513 } 1514 1515 return $line; 1516} 1517 1518sub reboot_to { 1519 if (defined($switch_to_test)) { 1520 run_command $switch_to_test; 1521 } 1522 1523 if ($reboot_type eq "grub") { 1524 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; 1525 } elsif (defined $reboot_script) { 1526 run_command "$reboot_script"; 1527 } 1528 reboot; 1529} 1530 1531sub get_sha1 { 1532 my ($commit) = @_; 1533 1534 doprint "git rev-list --max-count=1 $commit ... "; 1535 my $sha1 = `git rev-list --max-count=1 $commit`; 1536 my $ret = $?; 1537 1538 logit $sha1; 1539 1540 if ($ret) { 1541 doprint "FAILED\n"; 1542 dodie "Failed to get git $commit"; 1543 } 1544 1545 print "SUCCESS\n"; 1546 1547 chomp $sha1; 1548 1549 return $sha1; 1550} 1551 1552sub monitor { 1553 my $booted = 0; 1554 my $bug = 0; 1555 my $bug_ignored = 0; 1556 my $skip_call_trace = 0; 1557 my $loops; 1558 1559 wait_for_monitor 5; 1560 1561 my $line; 1562 my $full_line = ""; 1563 1564 open(DMESG, "> $dmesg") or 1565 die "unable to write to $dmesg"; 1566 1567 reboot_to; 1568 1569 my $success_start; 1570 my $failure_start; 1571 my $monitor_start = time; 1572 my $done = 0; 1573 my $version_found = 0; 1574 1575 while (!$done) { 1576 1577 if ($bug && defined($stop_after_failure) && 1578 $stop_after_failure >= 0) { 1579 my $time = $stop_after_failure - (time - $failure_start); 1580 $line = wait_for_input($monitor_fp, $time); 1581 if (!defined($line)) { 1582 doprint "bug timed out after $booted_timeout seconds\n"; 1583 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 1584 last; 1585 } 1586 } elsif ($booted) { 1587 $line = wait_for_input($monitor_fp, $booted_timeout); 1588 if (!defined($line)) { 1589 my $s = $booted_timeout == 1 ? "" : "s"; 1590 doprint "Successful boot found: break after $booted_timeout second$s\n"; 1591 last; 1592 } 1593 } else { 1594 $line = wait_for_input($monitor_fp); 1595 if (!defined($line)) { 1596 my $s = $timeout == 1 ? "" : "s"; 1597 doprint "Timed out after $timeout second$s\n"; 1598 last; 1599 } 1600 } 1601 1602 doprint $line; 1603 print DMESG $line; 1604 1605 # we are not guaranteed to get a full line 1606 $full_line .= $line; 1607 1608 if ($full_line =~ /$success_line/) { 1609 $booted = 1; 1610 $success_start = time; 1611 } 1612 1613 if ($booted && defined($stop_after_success) && 1614 $stop_after_success >= 0) { 1615 my $now = time; 1616 if ($now - $success_start >= $stop_after_success) { 1617 doprint "Test forced to stop after $stop_after_success seconds after success\n"; 1618 last; 1619 } 1620 } 1621 1622 if ($full_line =~ /\[ backtrace testing \]/) { 1623 $skip_call_trace = 1; 1624 } 1625 1626 if ($full_line =~ /call trace:/i) { 1627 if (!$bug && !$skip_call_trace) { 1628 if ($ignore_errors) { 1629 $bug_ignored = 1; 1630 } else { 1631 $bug = 1; 1632 $failure_start = time; 1633 } 1634 } 1635 } 1636 1637 if ($bug && defined($stop_after_failure) && 1638 $stop_after_failure >= 0) { 1639 my $now = time; 1640 if ($now - $failure_start >= $stop_after_failure) { 1641 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 1642 last; 1643 } 1644 } 1645 1646 if ($full_line =~ /\[ end of backtrace testing \]/) { 1647 $skip_call_trace = 0; 1648 } 1649 1650 if ($full_line =~ /Kernel panic -/) { 1651 $failure_start = time; 1652 $bug = 1; 1653 } 1654 1655 # Detect triple faults by testing the banner 1656 if ($full_line =~ /\bLinux version (\S+).*\n/) { 1657 if ($1 eq $version) { 1658 $version_found = 1; 1659 } elsif ($version_found && $detect_triplefault) { 1660 # We already booted into the kernel we are testing, 1661 # but now we booted into another kernel? 1662 # Consider this a triple fault. 1663 doprint "Aleady booted in Linux kernel $version, but now\n"; 1664 doprint "we booted into Linux kernel $1.\n"; 1665 doprint "Assuming that this is a triple fault.\n"; 1666 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; 1667 last; 1668 } 1669 } 1670 1671 if ($line =~ /\n/) { 1672 $full_line = ""; 1673 } 1674 1675 if ($stop_test_after > 0 && !$booted && !$bug) { 1676 if (time - $monitor_start > $stop_test_after) { 1677 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 1678 $done = 1; 1679 } 1680 } 1681 } 1682 1683 close(DMESG); 1684 1685 if ($bug) { 1686 return 0 if ($in_bisect); 1687 fail "failed - got a bug report" and return 0; 1688 } 1689 1690 if (!$booted) { 1691 return 0 if ($in_bisect); 1692 fail "failed - never got a boot prompt." and return 0; 1693 } 1694 1695 if ($bug_ignored) { 1696 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 1697 } 1698 1699 return 1; 1700} 1701 1702sub eval_kernel_version { 1703 my ($option) = @_; 1704 1705 $option =~ s/\$KERNEL_VERSION/$version/g; 1706 1707 return $option; 1708} 1709 1710sub do_post_install { 1711 1712 return if (!defined($post_install)); 1713 1714 my $cp_post_install = eval_kernel_version $post_install; 1715 run_command "$cp_post_install" or 1716 dodie "Failed to run post install"; 1717} 1718 1719sub install { 1720 1721 return if ($no_install); 1722 1723 if (defined($pre_install)) { 1724 my $cp_pre_install = eval_kernel_version $pre_install; 1725 run_command "$cp_pre_install" or 1726 dodie "Failed to run pre install"; 1727 } 1728 1729 my $cp_target = eval_kernel_version $target_image; 1730 1731 run_scp_install "$outputdir/$build_target", "$cp_target" or 1732 dodie "failed to copy image"; 1733 1734 my $install_mods = 0; 1735 1736 # should we process modules? 1737 $install_mods = 0; 1738 open(IN, "$output_config") or dodie("Can't read config file"); 1739 while (<IN>) { 1740 if (/CONFIG_MODULES(=y)?/) { 1741 $install_mods = 1 if (defined($1)); 1742 last; 1743 } 1744 } 1745 close(IN); 1746 1747 if (!$install_mods) { 1748 do_post_install; 1749 doprint "No modules needed\n"; 1750 return; 1751 } 1752 1753 run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or 1754 dodie "Failed to install modules"; 1755 1756 my $modlib = "/lib/modules/$version"; 1757 my $modtar = "ktest-mods.tar.bz2"; 1758 1759 run_ssh "rm -rf $modlib" or 1760 dodie "failed to remove old mods: $modlib"; 1761 1762 # would be nice if scp -r did not follow symbolic links 1763 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 1764 dodie "making tarball"; 1765 1766 run_scp_mod "$tmpdir/$modtar", "/tmp" or 1767 dodie "failed to copy modules"; 1768 1769 unlink "$tmpdir/$modtar"; 1770 1771 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or 1772 dodie "failed to tar modules"; 1773 1774 run_ssh "rm -f /tmp/$modtar"; 1775 1776 do_post_install; 1777} 1778 1779sub get_version { 1780 # get the release name 1781 return if ($have_version); 1782 doprint "$make kernelrelease ... "; 1783 $version = `$make kernelrelease | tail -1`; 1784 chomp($version); 1785 doprint "$version\n"; 1786 $have_version = 1; 1787} 1788 1789sub start_monitor_and_boot { 1790 # Make sure the stable kernel has finished booting 1791 start_monitor; 1792 wait_for_monitor 5; 1793 end_monitor; 1794 1795 get_grub_index; 1796 get_version; 1797 install; 1798 1799 start_monitor; 1800 return monitor; 1801} 1802 1803sub check_buildlog { 1804 my ($patch) = @_; 1805 1806 my @files = `git show $patch | diffstat -l`; 1807 1808 open(IN, "git show $patch |") or 1809 dodie "failed to show $patch"; 1810 while (<IN>) { 1811 if (m,^--- a/(.*),) { 1812 chomp $1; 1813 $files[$#files] = $1; 1814 } 1815 } 1816 close(IN); 1817 1818 open(IN, $buildlog) or dodie "Can't open $buildlog"; 1819 while (<IN>) { 1820 if (/^\s*(.*?):.*(warning|error)/) { 1821 my $err = $1; 1822 foreach my $file (@files) { 1823 my $fullpath = "$builddir/$file"; 1824 if ($file eq $err || $fullpath eq $err) { 1825 fail "$file built with warnings" and return 0; 1826 } 1827 } 1828 } 1829 } 1830 close(IN); 1831 1832 return 1; 1833} 1834 1835sub apply_min_config { 1836 my $outconfig = "$output_config.new"; 1837 1838 # Read the config file and remove anything that 1839 # is in the force_config hash (from minconfig and others) 1840 # then add the force config back. 1841 1842 doprint "Applying minimum configurations into $output_config.new\n"; 1843 1844 open (OUT, ">$outconfig") or 1845 dodie "Can't create $outconfig"; 1846 1847 if (-f $output_config) { 1848 open (IN, $output_config) or 1849 dodie "Failed to open $output_config"; 1850 while (<IN>) { 1851 if (/^(# )?(CONFIG_[^\s=]*)/) { 1852 next if (defined($force_config{$2})); 1853 } 1854 print OUT; 1855 } 1856 close IN; 1857 } 1858 foreach my $config (keys %force_config) { 1859 print OUT "$force_config{$config}\n"; 1860 } 1861 close OUT; 1862 1863 run_command "mv $outconfig $output_config"; 1864} 1865 1866sub make_oldconfig { 1867 1868 my @force_list = keys %force_config; 1869 1870 if ($#force_list >= 0) { 1871 apply_min_config; 1872 } 1873 1874 if (!run_command "$make oldnoconfig") { 1875 # Perhaps oldnoconfig doesn't exist in this version of the kernel 1876 # try a yes '' | oldconfig 1877 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 1878 run_command "yes '' | $make oldconfig" or 1879 dodie "failed make config oldconfig"; 1880 } 1881} 1882 1883# read a config file and use this to force new configs. 1884sub load_force_config { 1885 my ($config) = @_; 1886 1887 doprint "Loading force configs from $config\n"; 1888 open(IN, $config) or 1889 dodie "failed to read $config"; 1890 while (<IN>) { 1891 chomp; 1892 if (/^(CONFIG[^\s=]*)(\s*=.*)/) { 1893 $force_config{$1} = $_; 1894 } elsif (/^# (CONFIG_\S*) is not set/) { 1895 $force_config{$1} = $_; 1896 } 1897 } 1898 close IN; 1899} 1900 1901sub build { 1902 my ($type) = @_; 1903 1904 unlink $buildlog; 1905 1906 # Failed builds should not reboot the target 1907 my $save_no_reboot = $no_reboot; 1908 $no_reboot = 1; 1909 1910 # Calculate a new version from here. 1911 $have_version = 0; 1912 1913 if (defined($pre_build)) { 1914 my $ret = run_command $pre_build; 1915 if (!$ret && defined($pre_build_die) && 1916 $pre_build_die) { 1917 dodie "failed to pre_build\n"; 1918 } 1919 } 1920 1921 if ($type =~ /^useconfig:(.*)/) { 1922 run_command "cp $1 $output_config" or 1923 dodie "could not copy $1 to .config"; 1924 1925 $type = "oldconfig"; 1926 } 1927 1928 # old config can ask questions 1929 if ($type eq "oldconfig") { 1930 $type = "oldnoconfig"; 1931 1932 # allow for empty configs 1933 run_command "touch $output_config"; 1934 1935 if (!$noclean) { 1936 run_command "mv $output_config $outputdir/config_temp" or 1937 dodie "moving .config"; 1938 1939 run_command "$make mrproper" or dodie "make mrproper"; 1940 1941 run_command "mv $outputdir/config_temp $output_config" or 1942 dodie "moving config_temp"; 1943 } 1944 1945 } elsif (!$noclean) { 1946 unlink "$output_config"; 1947 run_command "$make mrproper" or 1948 dodie "make mrproper"; 1949 } 1950 1951 # add something to distinguish this build 1952 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 1953 print OUT "$localversion\n"; 1954 close(OUT); 1955 1956 if (defined($minconfig)) { 1957 load_force_config($minconfig); 1958 } 1959 1960 if ($type ne "oldnoconfig") { 1961 run_command "$make $type" or 1962 dodie "failed make config"; 1963 } 1964 # Run old config regardless, to enforce min configurations 1965 make_oldconfig; 1966 1967 $redirect = "$buildlog"; 1968 my $build_ret = run_command "$make $build_options"; 1969 undef $redirect; 1970 1971 if (defined($post_build)) { 1972 # Because a post build may change the kernel version 1973 # do it now. 1974 get_version; 1975 my $ret = run_command $post_build; 1976 if (!$ret && defined($post_build_die) && 1977 $post_build_die) { 1978 dodie "failed to post_build\n"; 1979 } 1980 } 1981 1982 if (!$build_ret) { 1983 # bisect may need this to pass 1984 if ($in_bisect) { 1985 $no_reboot = $save_no_reboot; 1986 return 0; 1987 } 1988 fail "failed build" and return 0; 1989 } 1990 1991 $no_reboot = $save_no_reboot; 1992 1993 return 1; 1994} 1995 1996sub halt { 1997 if (!run_ssh "halt" or defined($power_off)) { 1998 if (defined($poweroff_after_halt)) { 1999 sleep $poweroff_after_halt; 2000 run_command "$power_off"; 2001 } 2002 } else { 2003 # nope? the zap it! 2004 run_command "$power_off"; 2005 } 2006} 2007 2008sub success { 2009 my ($i) = @_; 2010 2011 if (defined($post_test)) { 2012 run_command $post_test; 2013 } 2014 2015 $successes++; 2016 2017 my $name = ""; 2018 2019 if (defined($test_name)) { 2020 $name = " ($test_name)"; 2021 } 2022 2023 doprint "\n\n*******************************************\n"; 2024 doprint "*******************************************\n"; 2025 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; 2026 doprint "*******************************************\n"; 2027 doprint "*******************************************\n"; 2028 2029 if (defined($store_successes)) { 2030 save_logs "success", $store_successes; 2031 } 2032 2033 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 2034 doprint "Reboot and wait $sleep_time seconds\n"; 2035 reboot_to_good $sleep_time; 2036 } 2037} 2038 2039sub answer_bisect { 2040 for (;;) { 2041 doprint "Pass or fail? [p/f]"; 2042 my $ans = <STDIN>; 2043 chomp $ans; 2044 if ($ans eq "p" || $ans eq "P") { 2045 return 1; 2046 } elsif ($ans eq "f" || $ans eq "F") { 2047 return 0; 2048 } else { 2049 print "Please answer 'P' or 'F'\n"; 2050 } 2051 } 2052} 2053 2054sub child_run_test { 2055 my $failed = 0; 2056 2057 # child should have no power 2058 $reboot_on_error = 0; 2059 $poweroff_on_error = 0; 2060 $die_on_failure = 1; 2061 2062 $redirect = "$testlog"; 2063 run_command $run_test or $failed = 1; 2064 undef $redirect; 2065 2066 exit $failed; 2067} 2068 2069my $child_done; 2070 2071sub child_finished { 2072 $child_done = 1; 2073} 2074 2075sub do_run_test { 2076 my $child_pid; 2077 my $child_exit; 2078 my $line; 2079 my $full_line; 2080 my $bug = 0; 2081 my $bug_ignored = 0; 2082 2083 wait_for_monitor 1; 2084 2085 doprint "run test $run_test\n"; 2086 2087 $child_done = 0; 2088 2089 $SIG{CHLD} = qw(child_finished); 2090 2091 $child_pid = fork; 2092 2093 child_run_test if (!$child_pid); 2094 2095 $full_line = ""; 2096 2097 do { 2098 $line = wait_for_input($monitor_fp, 1); 2099 if (defined($line)) { 2100 2101 # we are not guaranteed to get a full line 2102 $full_line .= $line; 2103 doprint $line; 2104 2105 if ($full_line =~ /call trace:/i) { 2106 if ($ignore_errors) { 2107 $bug_ignored = 1; 2108 } else { 2109 $bug = 1; 2110 } 2111 } 2112 2113 if ($full_line =~ /Kernel panic -/) { 2114 $bug = 1; 2115 } 2116 2117 if ($line =~ /\n/) { 2118 $full_line = ""; 2119 } 2120 } 2121 } while (!$child_done && !$bug); 2122 2123 if (!$bug && $bug_ignored) { 2124 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 2125 } 2126 2127 if ($bug) { 2128 my $failure_start = time; 2129 my $now; 2130 do { 2131 $line = wait_for_input($monitor_fp, 1); 2132 if (defined($line)) { 2133 doprint $line; 2134 } 2135 $now = time; 2136 if ($now - $failure_start >= $stop_after_failure) { 2137 last; 2138 } 2139 } while (defined($line)); 2140 2141 doprint "Detected kernel crash!\n"; 2142 # kill the child with extreme prejudice 2143 kill 9, $child_pid; 2144 } 2145 2146 waitpid $child_pid, 0; 2147 $child_exit = $?; 2148 2149 if (!$bug && $in_bisect) { 2150 if (defined($bisect_ret_good)) { 2151 if ($child_exit == $bisect_ret_good) { 2152 return 1; 2153 } 2154 } 2155 if (defined($bisect_ret_skip)) { 2156 if ($child_exit == $bisect_ret_skip) { 2157 return -1; 2158 } 2159 } 2160 if (defined($bisect_ret_abort)) { 2161 if ($child_exit == $bisect_ret_abort) { 2162 fail "test abort" and return -2; 2163 } 2164 } 2165 if (defined($bisect_ret_bad)) { 2166 if ($child_exit == $bisect_ret_skip) { 2167 return 0; 2168 } 2169 } 2170 if (defined($bisect_ret_default)) { 2171 if ($bisect_ret_default eq "good") { 2172 return 1; 2173 } elsif ($bisect_ret_default eq "bad") { 2174 return 0; 2175 } elsif ($bisect_ret_default eq "skip") { 2176 return -1; 2177 } elsif ($bisect_ret_default eq "abort") { 2178 return -2; 2179 } else { 2180 fail "unknown default action: $bisect_ret_default" 2181 and return -2; 2182 } 2183 } 2184 } 2185 2186 if ($bug || $child_exit) { 2187 return 0 if $in_bisect; 2188 fail "test failed" and return 0; 2189 } 2190 return 1; 2191} 2192 2193sub run_git_bisect { 2194 my ($command) = @_; 2195 2196 doprint "$command ... "; 2197 2198 my $output = `$command 2>&1`; 2199 my $ret = $?; 2200 2201 logit $output; 2202 2203 if ($ret) { 2204 doprint "FAILED\n"; 2205 dodie "Failed to git bisect"; 2206 } 2207 2208 doprint "SUCCESS\n"; 2209 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 2210 doprint "$1 [$2]\n"; 2211 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 2212 $bisect_bad_commit = $1; 2213 doprint "Found bad commit... $1\n"; 2214 return 0; 2215 } else { 2216 # we already logged it, just print it now. 2217 print $output; 2218 } 2219 2220 return 1; 2221} 2222 2223sub bisect_reboot { 2224 doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 2225 reboot_to_good $bisect_sleep_time; 2226} 2227 2228# returns 1 on success, 0 on failure, -1 on skip 2229sub run_bisect_test { 2230 my ($type, $buildtype) = @_; 2231 2232 my $failed = 0; 2233 my $result; 2234 my $output; 2235 my $ret; 2236 2237 $in_bisect = 1; 2238 2239 build $buildtype or $failed = 1; 2240 2241 if ($type ne "build") { 2242 if ($failed && $bisect_skip) { 2243 $in_bisect = 0; 2244 return -1; 2245 } 2246 dodie "Failed on build" if $failed; 2247 2248 # Now boot the box 2249 start_monitor_and_boot or $failed = 1; 2250 2251 if ($type ne "boot") { 2252 if ($failed && $bisect_skip) { 2253 end_monitor; 2254 bisect_reboot; 2255 $in_bisect = 0; 2256 return -1; 2257 } 2258 dodie "Failed on boot" if $failed; 2259 2260 do_run_test or $failed = 1; 2261 } 2262 end_monitor; 2263 } 2264 2265 if ($failed) { 2266 $result = 0; 2267 } else { 2268 $result = 1; 2269 } 2270 2271 # reboot the box to a kernel we can ssh to 2272 if ($type ne "build") { 2273 bisect_reboot; 2274 } 2275 $in_bisect = 0; 2276 2277 return $result; 2278} 2279 2280sub run_bisect { 2281 my ($type) = @_; 2282 my $buildtype = "oldconfig"; 2283 2284 # We should have a minconfig to use? 2285 if (defined($minconfig)) { 2286 $buildtype = "useconfig:$minconfig"; 2287 } 2288 2289 my $ret = run_bisect_test $type, $buildtype; 2290 2291 if ($bisect_manual) { 2292 $ret = answer_bisect; 2293 } 2294 2295 # Are we looking for where it worked, not failed? 2296 if ($reverse_bisect && $ret >= 0) { 2297 $ret = !$ret; 2298 } 2299 2300 if ($ret > 0) { 2301 return "good"; 2302 } elsif ($ret == 0) { 2303 return "bad"; 2304 } elsif ($bisect_skip) { 2305 doprint "HIT A BAD COMMIT ... SKIPPING\n"; 2306 return "skip"; 2307 } 2308} 2309 2310sub update_bisect_replay { 2311 my $tmp_log = "$tmpdir/ktest_bisect_log"; 2312 run_command "git bisect log > $tmp_log" or 2313 die "can't create bisect log"; 2314 return $tmp_log; 2315} 2316 2317sub bisect { 2318 my ($i) = @_; 2319 2320 my $result; 2321 2322 die "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good)); 2323 die "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad)); 2324 die "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type)); 2325 2326 my $good = $bisect_good; 2327 my $bad = $bisect_bad; 2328 my $type = $bisect_type; 2329 my $start = $bisect_start; 2330 my $replay = $bisect_replay; 2331 my $start_files = $bisect_files; 2332 2333 if (defined($start_files)) { 2334 $start_files = " -- " . $start_files; 2335 } else { 2336 $start_files = ""; 2337 } 2338 2339 # convert to true sha1's 2340 $good = get_sha1($good); 2341 $bad = get_sha1($bad); 2342 2343 if (defined($bisect_reverse) && $bisect_reverse == 1) { 2344 doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 2345 $reverse_bisect = 1; 2346 } else { 2347 $reverse_bisect = 0; 2348 } 2349 2350 # Can't have a test without having a test to run 2351 if ($type eq "test" && !defined($run_test)) { 2352 $type = "boot"; 2353 } 2354 2355 # Check if a bisect was running 2356 my $bisect_start_file = "$builddir/.git/BISECT_START"; 2357 2358 my $check = $bisect_check; 2359 my $do_check = defined($check) && $check ne "0"; 2360 2361 if ( -f $bisect_start_file ) { 2362 print "Bisect in progress found\n"; 2363 if ($do_check) { 2364 print " If you say yes, then no checks of good or bad will be done\n"; 2365 } 2366 if (defined($replay)) { 2367 print "** BISECT_REPLAY is defined in config file **"; 2368 print " Ignore config option and perform new git bisect log?\n"; 2369 if (read_ync " (yes, no, or cancel) ") { 2370 $replay = update_bisect_replay; 2371 $do_check = 0; 2372 } 2373 } elsif (read_yn "read git log and continue?") { 2374 $replay = update_bisect_replay; 2375 $do_check = 0; 2376 } 2377 } 2378 2379 if ($do_check) { 2380 2381 # get current HEAD 2382 my $head = get_sha1("HEAD"); 2383 2384 if ($check ne "good") { 2385 doprint "TESTING BISECT BAD [$bad]\n"; 2386 run_command "git checkout $bad" or 2387 die "Failed to checkout $bad"; 2388 2389 $result = run_bisect $type; 2390 2391 if ($result ne "bad") { 2392 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 2393 } 2394 } 2395 2396 if ($check ne "bad") { 2397 doprint "TESTING BISECT GOOD [$good]\n"; 2398 run_command "git checkout $good" or 2399 die "Failed to checkout $good"; 2400 2401 $result = run_bisect $type; 2402 2403 if ($result ne "good") { 2404 fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 2405 } 2406 } 2407 2408 # checkout where we started 2409 run_command "git checkout $head" or 2410 die "Failed to checkout $head"; 2411 } 2412 2413 run_command "git bisect start$start_files" or 2414 dodie "could not start bisect"; 2415 2416 run_command "git bisect good $good" or 2417 dodie "could not set bisect good to $good"; 2418 2419 run_git_bisect "git bisect bad $bad" or 2420 dodie "could not set bisect bad to $bad"; 2421 2422 if (defined($replay)) { 2423 run_command "git bisect replay $replay" or 2424 dodie "failed to run replay"; 2425 } 2426 2427 if (defined($start)) { 2428 run_command "git checkout $start" or 2429 dodie "failed to checkout $start"; 2430 } 2431 2432 my $test; 2433 do { 2434 $result = run_bisect $type; 2435 $test = run_git_bisect "git bisect $result"; 2436 } while ($test); 2437 2438 run_command "git bisect log" or 2439 dodie "could not capture git bisect log"; 2440 2441 run_command "git bisect reset" or 2442 dodie "could not reset git bisect"; 2443 2444 doprint "Bad commit was [$bisect_bad_commit]\n"; 2445 2446 success $i; 2447} 2448 2449# config_ignore holds the configs that were set (or unset) for 2450# a good config and we will ignore these configs for the rest 2451# of a config bisect. These configs stay as they were. 2452my %config_ignore; 2453 2454# config_set holds what all configs were set as. 2455my %config_set; 2456 2457# config_off holds the set of configs that the bad config had disabled. 2458# We need to record them and set them in the .config when running 2459# oldnoconfig, because oldnoconfig does not turn off new symbols, but 2460# instead just keeps the defaults. 2461my %config_off; 2462 2463# config_off_tmp holds a set of configs to turn off for now 2464my @config_off_tmp; 2465 2466# config_list is the set of configs that are being tested 2467my %config_list; 2468my %null_config; 2469 2470my %dependency; 2471 2472sub assign_configs { 2473 my ($hash, $config) = @_; 2474 2475 open (IN, $config) 2476 or dodie "Failed to read $config"; 2477 2478 while (<IN>) { 2479 if (/^((CONFIG\S*)=.*)/) { 2480 ${$hash}{$2} = $1; 2481 } 2482 } 2483 2484 close(IN); 2485} 2486 2487sub process_config_ignore { 2488 my ($config) = @_; 2489 2490 assign_configs \%config_ignore, $config; 2491} 2492 2493sub read_current_config { 2494 my ($config_ref) = @_; 2495 2496 %{$config_ref} = (); 2497 undef %{$config_ref}; 2498 2499 my @key = keys %{$config_ref}; 2500 if ($#key >= 0) { 2501 print "did not delete!\n"; 2502 exit; 2503 } 2504 open (IN, "$output_config"); 2505 2506 while (<IN>) { 2507 if (/^(CONFIG\S+)=(.*)/) { 2508 ${$config_ref}{$1} = $2; 2509 } 2510 } 2511 close(IN); 2512} 2513 2514sub get_dependencies { 2515 my ($config) = @_; 2516 2517 my $arr = $dependency{$config}; 2518 if (!defined($arr)) { 2519 return (); 2520 } 2521 2522 my @deps = @{$arr}; 2523 2524 foreach my $dep (@{$arr}) { 2525 print "ADD DEP $dep\n"; 2526 @deps = (@deps, get_dependencies $dep); 2527 } 2528 2529 return @deps; 2530} 2531 2532sub create_config { 2533 my @configs = @_; 2534 2535 open(OUT, ">$output_config") or dodie "Can not write to $output_config"; 2536 2537 foreach my $config (@configs) { 2538 print OUT "$config_set{$config}\n"; 2539 my @deps = get_dependencies $config; 2540 foreach my $dep (@deps) { 2541 print OUT "$config_set{$dep}\n"; 2542 } 2543 } 2544 2545 # turn off configs to keep off 2546 foreach my $config (keys %config_off) { 2547 print OUT "# $config is not set\n"; 2548 } 2549 2550 # turn off configs that should be off for now 2551 foreach my $config (@config_off_tmp) { 2552 print OUT "# $config is not set\n"; 2553 } 2554 2555 foreach my $config (keys %config_ignore) { 2556 print OUT "$config_ignore{$config}\n"; 2557 } 2558 close(OUT); 2559 2560 make_oldconfig; 2561} 2562 2563sub compare_configs { 2564 my (%a, %b) = @_; 2565 2566 foreach my $item (keys %a) { 2567 if (!defined($b{$item})) { 2568 print "diff $item\n"; 2569 return 1; 2570 } 2571 delete $b{$item}; 2572 } 2573 2574 my @keys = keys %b; 2575 if ($#keys) { 2576 print "diff2 $keys[0]\n"; 2577 } 2578 return -1 if ($#keys >= 0); 2579 2580 return 0; 2581} 2582 2583sub run_config_bisect_test { 2584 my ($type) = @_; 2585 2586 return run_bisect_test $type, "oldconfig"; 2587} 2588 2589sub process_passed { 2590 my (%configs) = @_; 2591 2592 doprint "These configs had no failure: (Enabling them for further compiles)\n"; 2593 # Passed! All these configs are part of a good compile. 2594 # Add them to the min options. 2595 foreach my $config (keys %configs) { 2596 if (defined($config_list{$config})) { 2597 doprint " removing $config\n"; 2598 $config_ignore{$config} = $config_list{$config}; 2599 delete $config_list{$config}; 2600 } 2601 } 2602 doprint "config copied to $outputdir/config_good\n"; 2603 run_command "cp -f $output_config $outputdir/config_good"; 2604} 2605 2606sub process_failed { 2607 my ($config) = @_; 2608 2609 doprint "\n\n***************************************\n"; 2610 doprint "Found bad config: $config\n"; 2611 doprint "***************************************\n\n"; 2612} 2613 2614sub run_config_bisect { 2615 2616 my @start_list = keys %config_list; 2617 2618 if ($#start_list < 0) { 2619 doprint "No more configs to test!!!\n"; 2620 return -1; 2621 } 2622 2623 doprint "***** RUN TEST ***\n"; 2624 my $type = $config_bisect_type; 2625 my $ret; 2626 my %current_config; 2627 2628 my $count = $#start_list + 1; 2629 doprint " $count configs to test\n"; 2630 2631 my $half = int($#start_list / 2); 2632 2633 do { 2634 my @tophalf = @start_list[0 .. $half]; 2635 2636 # keep the bottom half off 2637 if ($half < $#start_list) { 2638 @config_off_tmp = @start_list[$half + 1 .. $#start_list]; 2639 } else { 2640 @config_off_tmp = (); 2641 } 2642 2643 create_config @tophalf; 2644 read_current_config \%current_config; 2645 2646 $count = $#tophalf + 1; 2647 doprint "Testing $count configs\n"; 2648 my $found = 0; 2649 # make sure we test something 2650 foreach my $config (@tophalf) { 2651 if (defined($current_config{$config})) { 2652 logit " $config\n"; 2653 $found = 1; 2654 } 2655 } 2656 if (!$found) { 2657 # try the other half 2658 doprint "Top half produced no set configs, trying bottom half\n"; 2659 2660 # keep the top half off 2661 @config_off_tmp = @tophalf; 2662 @tophalf = @start_list[$half + 1 .. $#start_list]; 2663 2664 create_config @tophalf; 2665 read_current_config \%current_config; 2666 foreach my $config (@tophalf) { 2667 if (defined($current_config{$config})) { 2668 logit " $config\n"; 2669 $found = 1; 2670 } 2671 } 2672 if (!$found) { 2673 doprint "Failed: Can't make new config with current configs\n"; 2674 foreach my $config (@start_list) { 2675 doprint " CONFIG: $config\n"; 2676 } 2677 return -1; 2678 } 2679 $count = $#tophalf + 1; 2680 doprint "Testing $count configs\n"; 2681 } 2682 2683 $ret = run_config_bisect_test $type; 2684 if ($bisect_manual) { 2685 $ret = answer_bisect; 2686 } 2687 if ($ret) { 2688 process_passed %current_config; 2689 return 0; 2690 } 2691 2692 doprint "This config had a failure.\n"; 2693 doprint "Removing these configs that were not set in this config:\n"; 2694 doprint "config copied to $outputdir/config_bad\n"; 2695 run_command "cp -f $output_config $outputdir/config_bad"; 2696 2697 # A config exists in this group that was bad. 2698 foreach my $config (keys %config_list) { 2699 if (!defined($current_config{$config})) { 2700 doprint " removing $config\n"; 2701 delete $config_list{$config}; 2702 } 2703 } 2704 2705 @start_list = @tophalf; 2706 2707 if ($#start_list == 0) { 2708 process_failed $start_list[0]; 2709 return 1; 2710 } 2711 2712 # remove half the configs we are looking at and see if 2713 # they are good. 2714 $half = int($#start_list / 2); 2715 } while ($#start_list > 0); 2716 2717 # we found a single config, try it again unless we are running manually 2718 2719 if ($bisect_manual) { 2720 process_failed $start_list[0]; 2721 return 1; 2722 } 2723 2724 my @tophalf = @start_list[0 .. 0]; 2725 2726 $ret = run_config_bisect_test $type; 2727 if ($ret) { 2728 process_passed %current_config; 2729 return 0; 2730 } 2731 2732 process_failed $start_list[0]; 2733 return 1; 2734} 2735 2736sub config_bisect { 2737 my ($i) = @_; 2738 2739 my $start_config = $config_bisect; 2740 2741 my $tmpconfig = "$tmpdir/use_config"; 2742 2743 if (defined($config_bisect_good)) { 2744 process_config_ignore $config_bisect_good; 2745 } 2746 2747 # Make the file with the bad config and the min config 2748 if (defined($minconfig)) { 2749 # read the min config for things to ignore 2750 run_command "cp $minconfig $tmpconfig" or 2751 dodie "failed to copy $minconfig to $tmpconfig"; 2752 } else { 2753 unlink $tmpconfig; 2754 } 2755 2756 if (-f $tmpconfig) { 2757 load_force_config($tmpconfig); 2758 process_config_ignore $tmpconfig; 2759 } 2760 2761 # now process the start config 2762 run_command "cp $start_config $output_config" or 2763 dodie "failed to copy $start_config to $output_config"; 2764 2765 # read directly what we want to check 2766 my %config_check; 2767 open (IN, $output_config) 2768 or dodie "failed to open $output_config"; 2769 2770 while (<IN>) { 2771 if (/^((CONFIG\S*)=.*)/) { 2772 $config_check{$2} = $1; 2773 } 2774 } 2775 close(IN); 2776 2777 # Now run oldconfig with the minconfig 2778 make_oldconfig; 2779 2780 # check to see what we lost (or gained) 2781 open (IN, $output_config) 2782 or dodie "Failed to read $start_config"; 2783 2784 my %removed_configs; 2785 my %added_configs; 2786 2787 while (<IN>) { 2788 if (/^((CONFIG\S*)=.*)/) { 2789 # save off all options 2790 $config_set{$2} = $1; 2791 if (defined($config_check{$2})) { 2792 if (defined($config_ignore{$2})) { 2793 $removed_configs{$2} = $1; 2794 } else { 2795 $config_list{$2} = $1; 2796 } 2797 } elsif (!defined($config_ignore{$2})) { 2798 $added_configs{$2} = $1; 2799 $config_list{$2} = $1; 2800 } 2801 } elsif (/^# ((CONFIG\S*).*)/) { 2802 # Keep these configs disabled 2803 $config_set{$2} = $1; 2804 $config_off{$2} = $1; 2805 } 2806 } 2807 close(IN); 2808 2809 my @confs = keys %removed_configs; 2810 if ($#confs >= 0) { 2811 doprint "Configs overridden by default configs and removed from check:\n"; 2812 foreach my $config (@confs) { 2813 doprint " $config\n"; 2814 } 2815 } 2816 @confs = keys %added_configs; 2817 if ($#confs >= 0) { 2818 doprint "Configs appearing in make oldconfig and added:\n"; 2819 foreach my $config (@confs) { 2820 doprint " $config\n"; 2821 } 2822 } 2823 2824 my %config_test; 2825 my $once = 0; 2826 2827 @config_off_tmp = (); 2828 2829 # Sometimes kconfig does weird things. We must make sure 2830 # that the config we autocreate has everything we need 2831 # to test, otherwise we may miss testing configs, or 2832 # may not be able to create a new config. 2833 # Here we create a config with everything set. 2834 create_config (keys %config_list); 2835 read_current_config \%config_test; 2836 foreach my $config (keys %config_list) { 2837 if (!defined($config_test{$config})) { 2838 if (!$once) { 2839 $once = 1; 2840 doprint "Configs not produced by kconfig (will not be checked):\n"; 2841 } 2842 doprint " $config\n"; 2843 delete $config_list{$config}; 2844 } 2845 } 2846 my $ret; 2847 2848 if (defined($config_bisect_check) && $config_bisect_check) { 2849 doprint " Checking to make sure bad config with min config fails\n"; 2850 create_config keys %config_list; 2851 $ret = run_config_bisect_test $config_bisect_type; 2852 if ($ret) { 2853 doprint " FAILED! Bad config with min config boots fine\n"; 2854 return -1; 2855 } 2856 doprint " Bad config with min config fails as expected\n"; 2857 } 2858 2859 do { 2860 $ret = run_config_bisect; 2861 } while (!$ret); 2862 2863 return $ret if ($ret < 0); 2864 2865 success $i; 2866} 2867 2868sub patchcheck_reboot { 2869 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 2870 reboot_to_good $patchcheck_sleep_time; 2871} 2872 2873sub patchcheck { 2874 my ($i) = @_; 2875 2876 die "PATCHCHECK_START[$i] not defined\n" 2877 if (!defined($patchcheck_start)); 2878 die "PATCHCHECK_TYPE[$i] not defined\n" 2879 if (!defined($patchcheck_type)); 2880 2881 my $start = $patchcheck_start; 2882 2883 my $end = "HEAD"; 2884 if (defined($patchcheck_end)) { 2885 $end = $patchcheck_end; 2886 } 2887 2888 # Get the true sha1's since we can use things like HEAD~3 2889 $start = get_sha1($start); 2890 $end = get_sha1($end); 2891 2892 my $type = $patchcheck_type; 2893 2894 # Can't have a test without having a test to run 2895 if ($type eq "test" && !defined($run_test)) { 2896 $type = "boot"; 2897 } 2898 2899 open (IN, "git log --pretty=oneline $end|") or 2900 dodie "could not get git list"; 2901 2902 my @list; 2903 2904 while (<IN>) { 2905 chomp; 2906 $list[$#list+1] = $_; 2907 last if (/^$start/); 2908 } 2909 close(IN); 2910 2911 if ($list[$#list] !~ /^$start/) { 2912 fail "SHA1 $start not found"; 2913 } 2914 2915 # go backwards in the list 2916 @list = reverse @list; 2917 2918 my $save_clean = $noclean; 2919 my %ignored_warnings; 2920 2921 if (defined($ignore_warnings)) { 2922 foreach my $sha1 (split /\s+/, $ignore_warnings) { 2923 $ignored_warnings{$sha1} = 1; 2924 } 2925 } 2926 2927 $in_patchcheck = 1; 2928 foreach my $item (@list) { 2929 my $sha1 = $item; 2930 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 2931 2932 doprint "\nProcessing commit $item\n\n"; 2933 2934 run_command "git checkout $sha1" or 2935 die "Failed to checkout $sha1"; 2936 2937 # only clean on the first and last patch 2938 if ($item eq $list[0] || 2939 $item eq $list[$#list]) { 2940 $noclean = $save_clean; 2941 } else { 2942 $noclean = 1; 2943 } 2944 2945 if (defined($minconfig)) { 2946 build "useconfig:$minconfig" or return 0; 2947 } else { 2948 # ?? no config to use? 2949 build "oldconfig" or return 0; 2950 } 2951 2952 2953 if (!defined($ignored_warnings{$sha1})) { 2954 check_buildlog $sha1 or return 0; 2955 } 2956 2957 next if ($type eq "build"); 2958 2959 my $failed = 0; 2960 2961 start_monitor_and_boot or $failed = 1; 2962 2963 if (!$failed && $type ne "boot"){ 2964 do_run_test or $failed = 1; 2965 } 2966 end_monitor; 2967 return 0 if ($failed); 2968 2969 patchcheck_reboot; 2970 2971 } 2972 $in_patchcheck = 0; 2973 success $i; 2974 2975 return 1; 2976} 2977 2978my %depends; 2979my %depcount; 2980my $iflevel = 0; 2981my @ifdeps; 2982 2983# prevent recursion 2984my %read_kconfigs; 2985 2986sub add_dep { 2987 # $config depends on $dep 2988 my ($config, $dep) = @_; 2989 2990 if (defined($depends{$config})) { 2991 $depends{$config} .= " " . $dep; 2992 } else { 2993 $depends{$config} = $dep; 2994 } 2995 2996 # record the number of configs depending on $dep 2997 if (defined $depcount{$dep}) { 2998 $depcount{$dep}++; 2999 } else { 3000 $depcount{$dep} = 1; 3001 } 3002} 3003 3004# taken from streamline_config.pl 3005sub read_kconfig { 3006 my ($kconfig) = @_; 3007 3008 my $state = "NONE"; 3009 my $config; 3010 my @kconfigs; 3011 3012 my $cont = 0; 3013 my $line; 3014 3015 3016 if (! -f $kconfig) { 3017 doprint "file $kconfig does not exist, skipping\n"; 3018 return; 3019 } 3020 3021 open(KIN, "$kconfig") 3022 or die "Can't open $kconfig"; 3023 while (<KIN>) { 3024 chomp; 3025 3026 # Make sure that lines ending with \ continue 3027 if ($cont) { 3028 $_ = $line . " " . $_; 3029 } 3030 3031 if (s/\\$//) { 3032 $cont = 1; 3033 $line = $_; 3034 next; 3035 } 3036 3037 $cont = 0; 3038 3039 # collect any Kconfig sources 3040 if (/^source\s*"(.*)"/) { 3041 $kconfigs[$#kconfigs+1] = $1; 3042 } 3043 3044 # configs found 3045 if (/^\s*(menu)?config\s+(\S+)\s*$/) { 3046 $state = "NEW"; 3047 $config = $2; 3048 3049 for (my $i = 0; $i < $iflevel; $i++) { 3050 add_dep $config, $ifdeps[$i]; 3051 } 3052 3053 # collect the depends for the config 3054 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { 3055 3056 add_dep $config, $1; 3057 3058 # Get the configs that select this config 3059 } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) { 3060 3061 # selected by depends on config 3062 add_dep $1, $config; 3063 3064 # Check for if statements 3065 } elsif (/^if\s+(.*\S)\s*$/) { 3066 my $deps = $1; 3067 # remove beginning and ending non text 3068 $deps =~ s/^[^a-zA-Z0-9_]*//; 3069 $deps =~ s/[^a-zA-Z0-9_]*$//; 3070 3071 my @deps = split /[^a-zA-Z0-9_]+/, $deps; 3072 3073 $ifdeps[$iflevel++] = join ':', @deps; 3074 3075 } elsif (/^endif/) { 3076 3077 $iflevel-- if ($iflevel); 3078 3079 # stop on "help" 3080 } elsif (/^\s*help\s*$/) { 3081 $state = "NONE"; 3082 } 3083 } 3084 close(KIN); 3085 3086 # read in any configs that were found. 3087 foreach $kconfig (@kconfigs) { 3088 if (!defined($read_kconfigs{$kconfig})) { 3089 $read_kconfigs{$kconfig} = 1; 3090 read_kconfig("$builddir/$kconfig"); 3091 } 3092 } 3093} 3094 3095sub read_depends { 3096 # find out which arch this is by the kconfig file 3097 open (IN, $output_config) 3098 or dodie "Failed to read $output_config"; 3099 my $arch; 3100 while (<IN>) { 3101 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) { 3102 $arch = $1; 3103 last; 3104 } 3105 } 3106 close IN; 3107 3108 if (!defined($arch)) { 3109 doprint "Could not find arch from config file\n"; 3110 doprint "no dependencies used\n"; 3111 return; 3112 } 3113 3114 # arch is really the subarch, we need to know 3115 # what directory to look at. 3116 if ($arch eq "i386" || $arch eq "x86_64") { 3117 $arch = "x86"; 3118 } elsif ($arch =~ /^tile/) { 3119 $arch = "tile"; 3120 } 3121 3122 my $kconfig = "$builddir/arch/$arch/Kconfig"; 3123 3124 if (! -f $kconfig && $arch =~ /\d$/) { 3125 my $orig = $arch; 3126 # some subarchs have numbers, truncate them 3127 $arch =~ s/\d*$//; 3128 $kconfig = "$builddir/arch/$arch/Kconfig"; 3129 if (! -f $kconfig) { 3130 doprint "No idea what arch dir $orig is for\n"; 3131 doprint "no dependencies used\n"; 3132 return; 3133 } 3134 } 3135 3136 read_kconfig($kconfig); 3137} 3138 3139sub read_config_list { 3140 my ($config) = @_; 3141 3142 open (IN, $config) 3143 or dodie "Failed to read $config"; 3144 3145 while (<IN>) { 3146 if (/^((CONFIG\S*)=.*)/) { 3147 if (!defined($config_ignore{$2})) { 3148 $config_list{$2} = $1; 3149 } 3150 } 3151 } 3152 3153 close(IN); 3154} 3155 3156sub read_output_config { 3157 my ($config) = @_; 3158 3159 assign_configs \%config_ignore, $config; 3160} 3161 3162sub make_new_config { 3163 my @configs = @_; 3164 3165 open (OUT, ">$output_config") 3166 or dodie "Failed to write $output_config"; 3167 3168 foreach my $config (@configs) { 3169 print OUT "$config\n"; 3170 } 3171 close OUT; 3172} 3173 3174sub chomp_config { 3175 my ($config) = @_; 3176 3177 $config =~ s/CONFIG_//; 3178 3179 return $config; 3180} 3181 3182sub get_depends { 3183 my ($dep) = @_; 3184 3185 my $kconfig = chomp_config $dep; 3186 3187 $dep = $depends{"$kconfig"}; 3188 3189 # the dep string we have saves the dependencies as they 3190 # were found, including expressions like ! && ||. We 3191 # want to split this out into just an array of configs. 3192 3193 my $valid = "A-Za-z_0-9"; 3194 3195 my @configs; 3196 3197 while ($dep =~ /[$valid]/) { 3198 3199 if ($dep =~ /^[^$valid]*([$valid]+)/) { 3200 my $conf = "CONFIG_" . $1; 3201 3202 $configs[$#configs + 1] = $conf; 3203 3204 $dep =~ s/^[^$valid]*[$valid]+//; 3205 } else { 3206 die "this should never happen"; 3207 } 3208 } 3209 3210 return @configs; 3211} 3212 3213my %min_configs; 3214my %keep_configs; 3215my %save_configs; 3216my %processed_configs; 3217my %nochange_config; 3218 3219sub test_this_config { 3220 my ($config) = @_; 3221 3222 my $found; 3223 3224 # if we already processed this config, skip it 3225 if (defined($processed_configs{$config})) { 3226 return undef; 3227 } 3228 $processed_configs{$config} = 1; 3229 3230 # if this config failed during this round, skip it 3231 if (defined($nochange_config{$config})) { 3232 return undef; 3233 } 3234 3235 my $kconfig = chomp_config $config; 3236 3237 # Test dependencies first 3238 if (defined($depends{"$kconfig"})) { 3239 my @parents = get_depends $config; 3240 foreach my $parent (@parents) { 3241 # if the parent is in the min config, check it first 3242 next if (!defined($min_configs{$parent})); 3243 $found = test_this_config($parent); 3244 if (defined($found)) { 3245 return $found; 3246 } 3247 } 3248 } 3249 3250 # Remove this config from the list of configs 3251 # do a make oldnoconfig and then read the resulting 3252 # .config to make sure it is missing the config that 3253 # we had before 3254 my %configs = %min_configs; 3255 delete $configs{$config}; 3256 make_new_config ((values %configs), (values %keep_configs)); 3257 make_oldconfig; 3258 undef %configs; 3259 assign_configs \%configs, $output_config; 3260 3261 return $config if (!defined($configs{$config})); 3262 3263 doprint "disabling config $config did not change .config\n"; 3264 3265 $nochange_config{$config} = 1; 3266 3267 return undef; 3268} 3269 3270sub make_min_config { 3271 my ($i) = @_; 3272 3273 my $type = $minconfig_type; 3274 if ($type ne "boot" && $type ne "test") { 3275 fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" . 3276 " make_min_config works only with 'boot' and 'test'\n" and return; 3277 } 3278 3279 if (!defined($output_minconfig)) { 3280 fail "OUTPUT_MIN_CONFIG not defined" and return; 3281 } 3282 3283 # If output_minconfig exists, and the start_minconfig 3284 # came from min_config, than ask if we should use 3285 # that instead. 3286 if (-f $output_minconfig && !$start_minconfig_defined) { 3287 print "$output_minconfig exists\n"; 3288 if (!defined($use_output_minconfig)) { 3289 if (read_yn " Use it as minconfig?") { 3290 $start_minconfig = $output_minconfig; 3291 } 3292 } elsif ($use_output_minconfig > 0) { 3293 doprint "Using $output_minconfig as MIN_CONFIG\n"; 3294 $start_minconfig = $output_minconfig; 3295 } else { 3296 doprint "Set to still use MIN_CONFIG as starting point\n"; 3297 } 3298 } 3299 3300 if (!defined($start_minconfig)) { 3301 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; 3302 } 3303 3304 my $temp_config = "$tmpdir/temp_config"; 3305 3306 # First things first. We build an allnoconfig to find 3307 # out what the defaults are that we can't touch. 3308 # Some are selections, but we really can't handle selections. 3309 3310 my $save_minconfig = $minconfig; 3311 undef $minconfig; 3312 3313 run_command "$make allnoconfig" or return 0; 3314 3315 read_depends; 3316 3317 process_config_ignore $output_config; 3318 3319 undef %save_configs; 3320 undef %min_configs; 3321 3322 if (defined($ignore_config)) { 3323 # make sure the file exists 3324 `touch $ignore_config`; 3325 assign_configs \%save_configs, $ignore_config; 3326 } 3327 3328 %keep_configs = %save_configs; 3329 3330 doprint "Load initial configs from $start_minconfig\n"; 3331 3332 # Look at the current min configs, and save off all the 3333 # ones that were set via the allnoconfig 3334 assign_configs \%min_configs, $start_minconfig; 3335 3336 my @config_keys = keys %min_configs; 3337 3338 # All configs need a depcount 3339 foreach my $config (@config_keys) { 3340 my $kconfig = chomp_config $config; 3341 if (!defined $depcount{$kconfig}) { 3342 $depcount{$kconfig} = 0; 3343 } 3344 } 3345 3346 # Remove anything that was set by the make allnoconfig 3347 # we shouldn't need them as they get set for us anyway. 3348 foreach my $config (@config_keys) { 3349 # Remove anything in the ignore_config 3350 if (defined($keep_configs{$config})) { 3351 my $file = $ignore_config; 3352 $file =~ s,.*/(.*?)$,$1,; 3353 doprint "$config set by $file ... ignored\n"; 3354 delete $min_configs{$config}; 3355 next; 3356 } 3357 # But make sure the settings are the same. If a min config 3358 # sets a selection, we do not want to get rid of it if 3359 # it is not the same as what we have. Just move it into 3360 # the keep configs. 3361 if (defined($config_ignore{$config})) { 3362 if ($config_ignore{$config} ne $min_configs{$config}) { 3363 doprint "$config is in allnoconfig as '$config_ignore{$config}'"; 3364 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n"; 3365 $keep_configs{$config} = $min_configs{$config}; 3366 } else { 3367 doprint "$config set by allnoconfig ... ignored\n"; 3368 } 3369 delete $min_configs{$config}; 3370 } 3371 } 3372 3373 my $done = 0; 3374 my $take_two = 0; 3375 3376 while (!$done) { 3377 3378 my $config; 3379 my $found; 3380 3381 # Now disable each config one by one and do a make oldconfig 3382 # till we find a config that changes our list. 3383 3384 my @test_configs = keys %min_configs; 3385 3386 # Sort keys by who is most dependent on 3387 @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} } 3388 @test_configs ; 3389 3390 # Put configs that did not modify the config at the end. 3391 my $reset = 1; 3392 for (my $i = 0; $i < $#test_configs; $i++) { 3393 if (!defined($nochange_config{$test_configs[0]})) { 3394 $reset = 0; 3395 last; 3396 } 3397 # This config didn't change the .config last time. 3398 # Place it at the end 3399 my $config = shift @test_configs; 3400 push @test_configs, $config; 3401 } 3402 3403 # if every test config has failed to modify the .config file 3404 # in the past, then reset and start over. 3405 if ($reset) { 3406 undef %nochange_config; 3407 } 3408 3409 undef %processed_configs; 3410 3411 foreach my $config (@test_configs) { 3412 3413 $found = test_this_config $config; 3414 3415 last if (defined($found)); 3416 3417 # oh well, try another config 3418 } 3419 3420 if (!defined($found)) { 3421 # we could have failed due to the nochange_config hash 3422 # reset and try again 3423 if (!$take_two) { 3424 undef %nochange_config; 3425 $take_two = 1; 3426 next; 3427 } 3428 doprint "No more configs found that we can disable\n"; 3429 $done = 1; 3430 last; 3431 } 3432 $take_two = 0; 3433 3434 $config = $found; 3435 3436 doprint "Test with $config disabled\n"; 3437 3438 # set in_bisect to keep build and monitor from dieing 3439 $in_bisect = 1; 3440 3441 my $failed = 0; 3442 build "oldconfig" or $failed = 1; 3443 if (!$failed) { 3444 start_monitor_and_boot or $failed = 1; 3445 3446 if ($type eq "test" && !$failed) { 3447 do_run_test or $failed = 1; 3448 } 3449 3450 end_monitor; 3451 } 3452 3453 $in_bisect = 0; 3454 3455 if ($failed) { 3456 doprint "$min_configs{$config} is needed to boot the box... keeping\n"; 3457 # this config is needed, add it to the ignore list. 3458 $keep_configs{$config} = $min_configs{$config}; 3459 $save_configs{$config} = $min_configs{$config}; 3460 delete $min_configs{$config}; 3461 3462 # update new ignore configs 3463 if (defined($ignore_config)) { 3464 open (OUT, ">$temp_config") 3465 or die "Can't write to $temp_config"; 3466 foreach my $config (keys %save_configs) { 3467 print OUT "$save_configs{$config}\n"; 3468 } 3469 close OUT; 3470 run_command "mv $temp_config $ignore_config" or 3471 dodie "failed to copy update to $ignore_config"; 3472 } 3473 3474 } else { 3475 # We booted without this config, remove it from the minconfigs. 3476 doprint "$config is not needed, disabling\n"; 3477 3478 delete $min_configs{$config}; 3479 3480 # Also disable anything that is not enabled in this config 3481 my %configs; 3482 assign_configs \%configs, $output_config; 3483 my @config_keys = keys %min_configs; 3484 foreach my $config (@config_keys) { 3485 if (!defined($configs{$config})) { 3486 doprint "$config is not set, disabling\n"; 3487 delete $min_configs{$config}; 3488 } 3489 } 3490 3491 # Save off all the current mandidory configs 3492 open (OUT, ">$temp_config") 3493 or die "Can't write to $temp_config"; 3494 foreach my $config (keys %keep_configs) { 3495 print OUT "$keep_configs{$config}\n"; 3496 } 3497 foreach my $config (keys %min_configs) { 3498 print OUT "$min_configs{$config}\n"; 3499 } 3500 close OUT; 3501 3502 run_command "mv $temp_config $output_minconfig" or 3503 dodie "failed to copy update to $output_minconfig"; 3504 } 3505 3506 doprint "Reboot and wait $sleep_time seconds\n"; 3507 reboot_to_good $sleep_time; 3508 } 3509 3510 success $i; 3511 return 1; 3512} 3513 3514$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 3515 3516if ($#ARGV == 0) { 3517 $ktest_config = $ARGV[0]; 3518 if (! -f $ktest_config) { 3519 print "$ktest_config does not exist.\n"; 3520 if (!read_yn "Create it?") { 3521 exit 0; 3522 } 3523 } 3524} else { 3525 $ktest_config = "ktest.conf"; 3526} 3527 3528if (! -f $ktest_config) { 3529 $newconfig = 1; 3530 get_test_case; 3531 open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 3532 print OUT << "EOF" 3533# Generated by ktest.pl 3534# 3535 3536# PWD is a ktest.pl variable that will result in the process working 3537# directory that ktest.pl is executed in. 3538 3539# THIS_DIR is automatically assigned the PWD of the path that generated 3540# the config file. It is best to use this variable when assigning other 3541# directory paths within this directory. This allows you to easily 3542# move the test cases to other locations or to other machines. 3543# 3544THIS_DIR := $variable{"PWD"} 3545 3546# Define each test with TEST_START 3547# The config options below it will override the defaults 3548TEST_START 3549TEST_TYPE = $default{"TEST_TYPE"} 3550 3551DEFAULTS 3552EOF 3553; 3554 close(OUT); 3555} 3556read_config $ktest_config; 3557 3558if (defined($opt{"LOG_FILE"})) { 3559 $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1); 3560} 3561 3562# Append any configs entered in manually to the config file. 3563my @new_configs = keys %entered_configs; 3564if ($#new_configs >= 0) { 3565 print "\nAppending entered in configs to $ktest_config\n"; 3566 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 3567 foreach my $config (@new_configs) { 3568 print OUT "$config = $entered_configs{$config}\n"; 3569 $opt{$config} = process_variables($entered_configs{$config}); 3570 } 3571} 3572 3573if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 3574 unlink $opt{"LOG_FILE"}; 3575} 3576 3577doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 3578 3579for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 3580 3581 if (!$i) { 3582 doprint "DEFAULT OPTIONS:\n"; 3583 } else { 3584 doprint "\nTEST $i OPTIONS"; 3585 if (defined($repeat_tests{$i})) { 3586 $repeat = $repeat_tests{$i}; 3587 doprint " ITERATE $repeat"; 3588 } 3589 doprint "\n"; 3590 } 3591 3592 foreach my $option (sort keys %opt) { 3593 3594 if ($option =~ /\[(\d+)\]$/) { 3595 next if ($i != $1); 3596 } else { 3597 next if ($i); 3598 } 3599 3600 doprint "$option = $opt{$option}\n"; 3601 } 3602} 3603 3604sub __set_test_option { 3605 my ($name, $i) = @_; 3606 3607 my $option = "$name\[$i\]"; 3608 3609 if (defined($opt{$option})) { 3610 return $opt{$option}; 3611 } 3612 3613 foreach my $test (keys %repeat_tests) { 3614 if ($i >= $test && 3615 $i < $test + $repeat_tests{$test}) { 3616 $option = "$name\[$test\]"; 3617 if (defined($opt{$option})) { 3618 return $opt{$option}; 3619 } 3620 } 3621 } 3622 3623 if (defined($opt{$name})) { 3624 return $opt{$name}; 3625 } 3626 3627 return undef; 3628} 3629 3630sub set_test_option { 3631 my ($name, $i) = @_; 3632 3633 my $option = __set_test_option($name, $i); 3634 return $option if (!defined($option)); 3635 3636 return eval_option($option, $i); 3637} 3638 3639# First we need to do is the builds 3640for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 3641 3642 # Do not reboot on failing test options 3643 $no_reboot = 1; 3644 $reboot_success = 0; 3645 3646 $have_version = 0; 3647 3648 $iteration = $i; 3649 3650 undef %force_config; 3651 3652 my $makecmd = set_test_option("MAKE_CMD", $i); 3653 3654 # Load all the options into their mapped variable names 3655 foreach my $opt (keys %option_map) { 3656 ${$option_map{$opt}} = set_test_option($opt, $i); 3657 } 3658 3659 $start_minconfig_defined = 1; 3660 3661 # The first test may override the PRE_KTEST option 3662 if (defined($pre_ktest) && $i == 1) { 3663 doprint "\n"; 3664 run_command $pre_ktest; 3665 } 3666 3667 # Any test can override the POST_KTEST option 3668 # The last test takes precedence. 3669 if (defined($post_ktest)) { 3670 $final_post_ktest = $post_ktest; 3671 } 3672 3673 if (!defined($start_minconfig)) { 3674 $start_minconfig_defined = 0; 3675 $start_minconfig = $minconfig; 3676 } 3677 3678 chdir $builddir || die "can't change directory to $builddir"; 3679 3680 foreach my $dir ($tmpdir, $outputdir) { 3681 if (!-d $dir) { 3682 mkpath($dir) or 3683 die "can't create $dir"; 3684 } 3685 } 3686 3687 $ENV{"SSH_USER"} = $ssh_user; 3688 $ENV{"MACHINE"} = $machine; 3689 3690 $buildlog = "$tmpdir/buildlog-$machine"; 3691 $testlog = "$tmpdir/testlog-$machine"; 3692 $dmesg = "$tmpdir/dmesg-$machine"; 3693 $make = "$makecmd O=$outputdir"; 3694 $output_config = "$outputdir/.config"; 3695 3696 if (!$buildonly) { 3697 $target = "$ssh_user\@$machine"; 3698 if ($reboot_type eq "grub") { 3699 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 3700 } 3701 } 3702 3703 my $run_type = $build_type; 3704 if ($test_type eq "patchcheck") { 3705 $run_type = $patchcheck_type; 3706 } elsif ($test_type eq "bisect") { 3707 $run_type = $bisect_type; 3708 } elsif ($test_type eq "config_bisect") { 3709 $run_type = $config_bisect_type; 3710 } 3711 3712 if ($test_type eq "make_min_config") { 3713 $run_type = ""; 3714 } 3715 3716 # mistake in config file? 3717 if (!defined($run_type)) { 3718 $run_type = "ERROR"; 3719 } 3720 3721 my $installme = ""; 3722 $installme = " no_install" if ($no_install); 3723 3724 doprint "\n\n"; 3725 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n"; 3726 3727 if (defined($pre_test)) { 3728 run_command $pre_test; 3729 } 3730 3731 unlink $dmesg; 3732 unlink $buildlog; 3733 unlink $testlog; 3734 3735 if (defined($addconfig)) { 3736 my $min = $minconfig; 3737 if (!defined($minconfig)) { 3738 $min = ""; 3739 } 3740 run_command "cat $addconfig $min > $tmpdir/add_config" or 3741 dodie "Failed to create temp config"; 3742 $minconfig = "$tmpdir/add_config"; 3743 } 3744 3745 if (defined($checkout)) { 3746 run_command "git checkout $checkout" or 3747 die "failed to checkout $checkout"; 3748 } 3749 3750 $no_reboot = 0; 3751 3752 # A test may opt to not reboot the box 3753 if ($reboot_on_success) { 3754 $reboot_success = 1; 3755 } 3756 3757 if ($test_type eq "bisect") { 3758 bisect $i; 3759 next; 3760 } elsif ($test_type eq "config_bisect") { 3761 config_bisect $i; 3762 next; 3763 } elsif ($test_type eq "patchcheck") { 3764 patchcheck $i; 3765 next; 3766 } elsif ($test_type eq "make_min_config") { 3767 make_min_config $i; 3768 next; 3769 } 3770 3771 if ($build_type ne "nobuild") { 3772 build $build_type or next; 3773 } 3774 3775 if ($test_type eq "install") { 3776 get_version; 3777 install; 3778 success $i; 3779 next; 3780 } 3781 3782 if ($test_type ne "build") { 3783 my $failed = 0; 3784 start_monitor_and_boot or $failed = 1; 3785 3786 if (!$failed && $test_type ne "boot" && defined($run_test)) { 3787 do_run_test or $failed = 1; 3788 } 3789 end_monitor; 3790 next if ($failed); 3791 } 3792 3793 success $i; 3794} 3795 3796if (defined($final_post_ktest)) { 3797 run_command $final_post_ktest; 3798} 3799 3800if ($opt{"POWEROFF_ON_SUCCESS"}) { 3801 halt; 3802} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) { 3803 reboot_to_good; 3804} elsif (defined($switch_to_good)) { 3805 # still need to get to the good kernel 3806 run_command $switch_to_good; 3807} 3808 3809 3810doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 3811 3812exit 0; 3813