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