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