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