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{"REBOOT_TYPE"} = "grub"; 26$default{"TEST_TYPE"} = "test"; 27$default{"BUILD_TYPE"} = "randconfig"; 28$default{"MAKE_CMD"} = "make"; 29$default{"TIMEOUT"} = 120; 30$default{"TMP_DIR"} = "/tmp/ktest"; 31$default{"SLEEP_TIME"} = 60; # sleep time between tests 32$default{"BUILD_NOCLEAN"} = 0; 33$default{"REBOOT_ON_ERROR"} = 0; 34$default{"POWEROFF_ON_ERROR"} = 0; 35$default{"REBOOT_ON_SUCCESS"} = 1; 36$default{"POWEROFF_ON_SUCCESS"} = 0; 37$default{"BUILD_OPTIONS"} = ""; 38$default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects 39$default{"CLEAR_LOG"} = 0; 40$default{"BISECT_MANUAL"} = 0; 41$default{"BISECT_SKIP"} = 1; 42$default{"SUCCESS_LINE"} = "login:"; 43$default{"BOOTED_TIMEOUT"} = 1; 44$default{"DIE_ON_FAILURE"} = 1; 45$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND"; 46$default{"SCP_TO_TARGET"} = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE"; 47$default{"REBOOT"} = "ssh \$SSH_USER\@\$MACHINE reboot"; 48$default{"STOP_AFTER_SUCCESS"} = 10; 49$default{"STOP_AFTER_FAILURE"} = 60; 50$default{"STOP_TEST_AFTER"} = 600; 51$default{"LOCALVERSION"} = "-test"; 52 53my $ktest_config; 54my $version; 55my $machine; 56my $ssh_user; 57my $tmpdir; 58my $builddir; 59my $outputdir; 60my $output_config; 61my $test_type; 62my $build_type; 63my $build_options; 64my $reboot_type; 65my $reboot_script; 66my $power_cycle; 67my $reboot; 68my $reboot_on_error; 69my $poweroff_on_error; 70my $die_on_failure; 71my $powercycle_after_reboot; 72my $poweroff_after_halt; 73my $ssh_exec; 74my $scp_to_target; 75my $power_off; 76my $grub_menu; 77my $grub_number; 78my $target; 79my $make; 80my $post_install; 81my $noclean; 82my $minconfig; 83my $addconfig; 84my $in_bisect = 0; 85my $bisect_bad = ""; 86my $reverse_bisect; 87my $bisect_manual; 88my $bisect_skip; 89my $in_patchcheck = 0; 90my $run_test; 91my $redirect; 92my $buildlog; 93my $dmesg; 94my $monitor_fp; 95my $monitor_pid; 96my $monitor_cnt = 0; 97my $sleep_time; 98my $bisect_sleep_time; 99my $store_failures; 100my $timeout; 101my $booted_timeout; 102my $console; 103my $success_line; 104my $stop_after_success; 105my $stop_after_failure; 106my $stop_test_after; 107my $build_target; 108my $target_image; 109my $localversion; 110my $iteration = 0; 111my $successes = 0; 112 113my %entered_configs; 114my %config_help; 115 116$config_help{"MACHINE"} = << "EOF" 117 The machine hostname that you will test. 118EOF 119 ; 120$config_help{"SSH_USER"} = << "EOF" 121 The box is expected to have ssh on normal bootup, provide the user 122 (most likely root, since you need privileged operations) 123EOF 124 ; 125$config_help{"BUILD_DIR"} = << "EOF" 126 The directory that contains the Linux source code (full path). 127EOF 128 ; 129$config_help{"OUTPUT_DIR"} = << "EOF" 130 The directory that the objects will be built (full path). 131 (can not be same as BUILD_DIR) 132EOF 133 ; 134$config_help{"BUILD_TARGET"} = << "EOF" 135 The location of the compiled file to copy to the target. 136 (relative to OUTPUT_DIR) 137EOF 138 ; 139$config_help{"TARGET_IMAGE"} = << "EOF" 140 The place to put your image on the test machine. 141EOF 142 ; 143$config_help{"POWER_CYCLE"} = << "EOF" 144 A script or command to reboot the box. 145 146 Here is a digital loggers power switch example 147 POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL' 148 149 Here is an example to reboot a virtual box on the current host 150 with the name "Guest". 151 POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest 152EOF 153 ; 154$config_help{"CONSOLE"} = << "EOF" 155 The script or command that reads the console 156 157 If you use ttywatch server, something like the following would work. 158CONSOLE = nc -d localhost 3001 159 160 For a virtual machine with guest name "Guest". 161CONSOLE = virsh console Guest 162EOF 163 ; 164$config_help{"LOCALVERSION"} = << "EOF" 165 Required version ending to differentiate the test 166 from other linux builds on the system. 167EOF 168 ; 169$config_help{"REBOOT_TYPE"} = << "EOF" 170 Way to reboot the box to the test kernel. 171 Only valid options so far are "grub" and "script". 172 173 If you specify grub, it will assume grub version 1 174 and will search in /boot/grub/menu.lst for the title \$GRUB_MENU 175 and select that target to reboot to the kernel. If this is not 176 your setup, then specify "script" and have a command or script 177 specified in REBOOT_SCRIPT to boot to the target. 178 179 The entry in /boot/grub/menu.lst must be entered in manually. 180 The test will not modify that file. 181EOF 182 ; 183$config_help{"GRUB_MENU"} = << "EOF" 184 The grub title name for the test kernel to boot 185 (Only mandatory if REBOOT_TYPE = grub) 186 187 Note, ktest.pl will not update the grub menu.lst, you need to 188 manually add an option for the test. ktest.pl will search 189 the grub menu.lst for this option to find what kernel to 190 reboot into. 191 192 For example, if in the /boot/grub/menu.lst the test kernel title has: 193 title Test Kernel 194 kernel vmlinuz-test 195 GRUB_MENU = Test Kernel 196EOF 197 ; 198$config_help{"REBOOT_SCRIPT"} = << "EOF" 199 A script to reboot the target into the test kernel 200 (Only mandatory if REBOOT_TYPE = script) 201EOF 202 ; 203 204 205sub get_ktest_config { 206 my ($config) = @_; 207 208 return if (defined($opt{$config})); 209 210 if (defined($config_help{$config})) { 211 print "\n"; 212 print $config_help{$config}; 213 } 214 215 for (;;) { 216 print "$config = "; 217 if (defined($default{$config})) { 218 print "\[$default{$config}\] "; 219 } 220 $entered_configs{$config} = <STDIN>; 221 $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/; 222 if ($entered_configs{$config} =~ /^\s*$/) { 223 if ($default{$config}) { 224 $entered_configs{$config} = $default{$config}; 225 } else { 226 print "Your answer can not be blank\n"; 227 next; 228 } 229 } 230 last; 231 } 232} 233 234sub get_ktest_configs { 235 get_ktest_config("MACHINE"); 236 get_ktest_config("SSH_USER"); 237 get_ktest_config("BUILD_DIR"); 238 get_ktest_config("OUTPUT_DIR"); 239 get_ktest_config("BUILD_TARGET"); 240 get_ktest_config("TARGET_IMAGE"); 241 get_ktest_config("POWER_CYCLE"); 242 get_ktest_config("CONSOLE"); 243 get_ktest_config("LOCALVERSION"); 244 245 my $rtype = $opt{"REBOOT_TYPE"}; 246 247 if (!defined($rtype)) { 248 if (!defined($opt{"GRUB_MENU"})) { 249 get_ktest_config("REBOOT_TYPE"); 250 $rtype = $entered_configs{"REBOOT_TYPE"}; 251 } else { 252 $rtype = "grub"; 253 } 254 } 255 256 if ($rtype eq "grub") { 257 get_ktest_config("GRUB_MENU"); 258 } else { 259 get_ktest_config("REBOOT_SCRIPT"); 260 } 261} 262 263sub set_value { 264 my ($lvalue, $rvalue) = @_; 265 266 if (defined($opt{$lvalue})) { 267 die "Error: Option $lvalue defined more than once!\n"; 268 } 269 if ($rvalue =~ /^\s*$/) { 270 delete $opt{$lvalue}; 271 } else { 272 $opt{$lvalue} = $rvalue; 273 } 274} 275 276sub read_config { 277 my ($config) = @_; 278 279 open(IN, $config) || die "can't read file $config"; 280 281 my $name = $config; 282 $name =~ s,.*/(.*),$1,; 283 284 my $test_num = 0; 285 my $default = 1; 286 my $repeat = 1; 287 my $num_tests_set = 0; 288 my $skip = 0; 289 my $rest; 290 291 while (<IN>) { 292 293 # ignore blank lines and comments 294 next if (/^\s*$/ || /\s*\#/); 295 296 if (/^\s*TEST_START(.*)/) { 297 298 $rest = $1; 299 300 if ($num_tests_set) { 301 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 302 } 303 304 my $old_test_num = $test_num; 305 my $old_repeat = $repeat; 306 307 $test_num += $repeat; 308 $default = 0; 309 $repeat = 1; 310 311 if ($rest =~ /\s+SKIP(.*)/) { 312 $rest = $1; 313 $skip = 1; 314 } else { 315 $skip = 0; 316 } 317 318 if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) { 319 $repeat = $1; 320 $rest = $2; 321 $repeat_tests{"$test_num"} = $repeat; 322 } 323 324 if ($rest =~ /\s+SKIP(.*)/) { 325 $rest = $1; 326 $skip = 1; 327 } 328 329 if ($rest !~ /^\s*$/) { 330 die "$name: $.: Gargbage found after TEST_START\n$_"; 331 } 332 333 if ($skip) { 334 $test_num = $old_test_num; 335 $repeat = $old_repeat; 336 } 337 338 } elsif (/^\s*DEFAULTS(.*)$/) { 339 $default = 1; 340 341 $rest = $1; 342 343 if ($rest =~ /\s+SKIP(.*)/) { 344 $rest = $1; 345 $skip = 1; 346 } else { 347 $skip = 0; 348 } 349 350 if ($rest !~ /^\s*$/) { 351 die "$name: $.: Gargbage found after DEFAULTS\n$_"; 352 } 353 354 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 355 356 next if ($skip); 357 358 my $lvalue = $1; 359 my $rvalue = $2; 360 361 if (!$default && 362 ($lvalue eq "NUM_TESTS" || 363 $lvalue eq "LOG_FILE" || 364 $lvalue eq "CLEAR_LOG")) { 365 die "$name: $.: $lvalue must be set in DEFAULTS section\n"; 366 } 367 368 if ($lvalue eq "NUM_TESTS") { 369 if ($test_num) { 370 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 371 } 372 if (!$default) { 373 die "$name: $.: NUM_TESTS must be set in default section\n"; 374 } 375 $num_tests_set = 1; 376 } 377 378 if ($default || $lvalue =~ /\[\d+\]$/) { 379 set_value($lvalue, $rvalue); 380 } else { 381 my $val = "$lvalue\[$test_num\]"; 382 set_value($val, $rvalue); 383 384 if ($repeat > 1) { 385 $repeats{$val} = $repeat; 386 } 387 } 388 } else { 389 die "$name: $.: Garbage found in config\n$_"; 390 } 391 } 392 393 close(IN); 394 395 if ($test_num) { 396 $test_num += $repeat - 1; 397 $opt{"NUM_TESTS"} = $test_num; 398 } 399 400 # make sure we have all mandatory configs 401 get_ktest_configs; 402 403 # set any defaults 404 405 foreach my $default (keys %default) { 406 if (!defined($opt{$default})) { 407 $opt{$default} = $default{$default}; 408 } 409 } 410} 411 412sub _logit { 413 if (defined($opt{"LOG_FILE"})) { 414 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 415 print OUT @_; 416 close(OUT); 417 } 418} 419 420sub logit { 421 if (defined($opt{"LOG_FILE"})) { 422 _logit @_; 423 } else { 424 print @_; 425 } 426} 427 428sub doprint { 429 print @_; 430 _logit @_; 431} 432 433sub run_command; 434 435sub reboot { 436 # try to reboot normally 437 if (run_command $reboot) { 438 if (defined($powercycle_after_reboot)) { 439 sleep $powercycle_after_reboot; 440 run_command "$power_cycle"; 441 } 442 } else { 443 # nope? power cycle it. 444 run_command "$power_cycle"; 445 } 446} 447 448sub do_not_reboot { 449 my $i = $iteration; 450 451 return $test_type eq "build" || 452 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 453 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 454} 455 456sub dodie { 457 doprint "CRITICAL FAILURE... ", @_, "\n"; 458 459 my $i = $iteration; 460 461 if ($reboot_on_error && !do_not_reboot) { 462 463 doprint "REBOOTING\n"; 464 reboot; 465 466 } elsif ($poweroff_on_error && defined($power_off)) { 467 doprint "POWERING OFF\n"; 468 `$power_off`; 469 } 470 471 if (defined($opt{"LOG_FILE"})) { 472 print " See $opt{LOG_FILE} for more info.\n"; 473 } 474 475 die @_, "\n"; 476} 477 478sub open_console { 479 my ($fp) = @_; 480 481 my $flags; 482 483 my $pid = open($fp, "$console|") or 484 dodie "Can't open console $console"; 485 486 $flags = fcntl($fp, F_GETFL, 0) or 487 dodie "Can't get flags for the socket: $!"; 488 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 489 dodie "Can't set flags for the socket: $!"; 490 491 return $pid; 492} 493 494sub close_console { 495 my ($fp, $pid) = @_; 496 497 doprint "kill child process $pid\n"; 498 kill 2, $pid; 499 500 print "closing!\n"; 501 close($fp); 502} 503 504sub start_monitor { 505 if ($monitor_cnt++) { 506 return; 507 } 508 $monitor_fp = \*MONFD; 509 $monitor_pid = open_console $monitor_fp; 510 511 return; 512 513 open(MONFD, "Stop perl from warning about single use of MONFD"); 514} 515 516sub end_monitor { 517 if (--$monitor_cnt) { 518 return; 519 } 520 close_console($monitor_fp, $monitor_pid); 521} 522 523sub wait_for_monitor { 524 my ($time) = @_; 525 my $line; 526 527 doprint "** Wait for monitor to settle down **\n"; 528 529 # read the monitor and wait for the system to calm down 530 do { 531 $line = wait_for_input($monitor_fp, $time); 532 print "$line" if (defined($line)); 533 } while (defined($line)); 534 print "** Monitor flushed **\n"; 535} 536 537sub fail { 538 539 if ($die_on_failure) { 540 dodie @_; 541 } 542 543 doprint "FAILED\n"; 544 545 my $i = $iteration; 546 547 # no need to reboot for just building. 548 if (!do_not_reboot) { 549 doprint "REBOOTING\n"; 550 reboot; 551 start_monitor; 552 wait_for_monitor $sleep_time; 553 end_monitor; 554 } 555 556 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 557 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 558 doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n"; 559 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 560 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 561 562 return 1 if (!defined($store_failures)); 563 564 my @t = localtime; 565 my $date = sprintf "%04d%02d%02d%02d%02d%02d", 566 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 567 568 my $type = $build_type; 569 if ($type =~ /useconfig/) { 570 $type = "useconfig"; 571 } 572 573 my $dir = "$machine-$test_type-$type-fail-$date"; 574 my $faildir = "$store_failures/$dir"; 575 576 if (!-d $faildir) { 577 mkpath($faildir) or 578 die "can't create $faildir"; 579 } 580 if (-f "$output_config") { 581 cp "$output_config", "$faildir/config" or 582 die "failed to copy .config"; 583 } 584 if (-f $buildlog) { 585 cp $buildlog, "$faildir/buildlog" or 586 die "failed to move $buildlog"; 587 } 588 if (-f $dmesg) { 589 cp $dmesg, "$faildir/dmesg" or 590 die "failed to move $dmesg"; 591 } 592 593 doprint "*** Saved info to $faildir ***\n"; 594 595 return 1; 596} 597 598sub run_command { 599 my ($command) = @_; 600 my $dolog = 0; 601 my $dord = 0; 602 my $pid; 603 604 $command =~ s/\$SSH_USER/$ssh_user/g; 605 $command =~ s/\$MACHINE/$machine/g; 606 607 doprint("$command ... "); 608 609 $pid = open(CMD, "$command 2>&1 |") or 610 (fail "unable to exec $command" and return 0); 611 612 if (defined($opt{"LOG_FILE"})) { 613 open(LOG, ">>$opt{LOG_FILE}") or 614 dodie "failed to write to log"; 615 $dolog = 1; 616 } 617 618 if (defined($redirect)) { 619 open (RD, ">$redirect") or 620 dodie "failed to write to redirect $redirect"; 621 $dord = 1; 622 } 623 624 while (<CMD>) { 625 print LOG if ($dolog); 626 print RD if ($dord); 627 } 628 629 waitpid($pid, 0); 630 my $failed = $?; 631 632 close(CMD); 633 close(LOG) if ($dolog); 634 close(RD) if ($dord); 635 636 if ($failed) { 637 doprint "FAILED!\n"; 638 } else { 639 doprint "SUCCESS\n"; 640 } 641 642 return !$failed; 643} 644 645sub run_ssh { 646 my ($cmd) = @_; 647 my $cp_exec = $ssh_exec; 648 649 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 650 return run_command "$cp_exec"; 651} 652 653sub run_scp { 654 my ($src, $dst) = @_; 655 my $cp_scp = $scp_to_target; 656 657 $cp_scp =~ s/\$SRC_FILE/$src/g; 658 $cp_scp =~ s/\$DST_FILE/$dst/g; 659 660 return run_command "$cp_scp"; 661} 662 663sub get_grub_index { 664 665 if ($reboot_type ne "grub") { 666 return; 667 } 668 return if (defined($grub_number)); 669 670 doprint "Find grub menu ... "; 671 $grub_number = -1; 672 673 my $ssh_grub = $ssh_exec; 674 $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 675 676 open(IN, "$ssh_grub |") 677 or die "unable to get menu.lst"; 678 679 while (<IN>) { 680 if (/^\s*title\s+$grub_menu\s*$/) { 681 $grub_number++; 682 last; 683 } elsif (/^\s*title\s/) { 684 $grub_number++; 685 } 686 } 687 close(IN); 688 689 die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 690 if ($grub_number < 0); 691 doprint "$grub_number\n"; 692} 693 694sub wait_for_input 695{ 696 my ($fp, $time) = @_; 697 my $rin; 698 my $ready; 699 my $line; 700 my $ch; 701 702 if (!defined($time)) { 703 $time = $timeout; 704 } 705 706 $rin = ''; 707 vec($rin, fileno($fp), 1) = 1; 708 $ready = select($rin, undef, undef, $time); 709 710 $line = ""; 711 712 # try to read one char at a time 713 while (sysread $fp, $ch, 1) { 714 $line .= $ch; 715 last if ($ch eq "\n"); 716 } 717 718 if (!length($line)) { 719 return undef; 720 } 721 722 return $line; 723} 724 725sub reboot_to { 726 if ($reboot_type eq "grub") { 727 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; 728 return; 729 } 730 731 run_command "$reboot_script"; 732} 733 734sub get_sha1 { 735 my ($commit) = @_; 736 737 doprint "git rev-list --max-count=1 $commit ... "; 738 my $sha1 = `git rev-list --max-count=1 $commit`; 739 my $ret = $?; 740 741 logit $sha1; 742 743 if ($ret) { 744 doprint "FAILED\n"; 745 dodie "Failed to get git $commit"; 746 } 747 748 print "SUCCESS\n"; 749 750 chomp $sha1; 751 752 return $sha1; 753} 754 755sub monitor { 756 my $booted = 0; 757 my $bug = 0; 758 my $skip_call_trace = 0; 759 my $loops; 760 761 wait_for_monitor 5; 762 763 my $line; 764 my $full_line = ""; 765 766 open(DMESG, "> $dmesg") or 767 die "unable to write to $dmesg"; 768 769 reboot_to; 770 771 my $success_start; 772 my $failure_start; 773 my $monitor_start = time; 774 my $done = 0; 775 776 while (!$done) { 777 778 if ($booted) { 779 $line = wait_for_input($monitor_fp, $booted_timeout); 780 } else { 781 $line = wait_for_input($monitor_fp); 782 } 783 784 last if (!defined($line)); 785 786 doprint $line; 787 print DMESG $line; 788 789 # we are not guaranteed to get a full line 790 $full_line .= $line; 791 792 if ($full_line =~ /$success_line/) { 793 $booted = 1; 794 $success_start = time; 795 } 796 797 if ($booted && defined($stop_after_success) && 798 $stop_after_success >= 0) { 799 my $now = time; 800 if ($now - $success_start >= $stop_after_success) { 801 doprint "Test forced to stop after $stop_after_success seconds after success\n"; 802 last; 803 } 804 } 805 806 if ($full_line =~ /\[ backtrace testing \]/) { 807 $skip_call_trace = 1; 808 } 809 810 if ($full_line =~ /call trace:/i) { 811 if (!$bug && !$skip_call_trace) { 812 $bug = 1; 813 $failure_start = time; 814 } 815 } 816 817 if ($bug && defined($stop_after_failure) && 818 $stop_after_failure >= 0) { 819 my $now = time; 820 if ($now - $failure_start >= $stop_after_failure) { 821 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 822 last; 823 } 824 } 825 826 if ($full_line =~ /\[ end of backtrace testing \]/) { 827 $skip_call_trace = 0; 828 } 829 830 if ($full_line =~ /Kernel panic -/) { 831 $failure_start = time; 832 $bug = 1; 833 } 834 835 if ($line =~ /\n/) { 836 $full_line = ""; 837 } 838 839 if ($stop_test_after > 0 && !$booted && !$bug) { 840 if (time - $monitor_start > $stop_test_after) { 841 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 842 $done = 1; 843 } 844 } 845 } 846 847 close(DMESG); 848 849 if ($bug) { 850 return 0 if ($in_bisect); 851 fail "failed - got a bug report" and return 0; 852 } 853 854 if (!$booted) { 855 return 0 if ($in_bisect); 856 fail "failed - never got a boot prompt." and return 0; 857 } 858 859 return 1; 860} 861 862sub install { 863 864 run_scp "$outputdir/$build_target", "$target_image" or 865 dodie "failed to copy image"; 866 867 my $install_mods = 0; 868 869 # should we process modules? 870 $install_mods = 0; 871 open(IN, "$output_config") or dodie("Can't read config file"); 872 while (<IN>) { 873 if (/CONFIG_MODULES(=y)?/) { 874 $install_mods = 1 if (defined($1)); 875 last; 876 } 877 } 878 close(IN); 879 880 if (!$install_mods) { 881 doprint "No modules needed\n"; 882 return; 883 } 884 885 run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or 886 dodie "Failed to install modules"; 887 888 my $modlib = "/lib/modules/$version"; 889 my $modtar = "ktest-mods.tar.bz2"; 890 891 run_ssh "rm -rf $modlib" or 892 dodie "failed to remove old mods: $modlib"; 893 894 # would be nice if scp -r did not follow symbolic links 895 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 896 dodie "making tarball"; 897 898 run_scp "$tmpdir/$modtar", "/tmp" or 899 dodie "failed to copy modules"; 900 901 unlink "$tmpdir/$modtar"; 902 903 run_ssh "'(cd / && tar xf /tmp/$modtar)'" or 904 dodie "failed to tar modules"; 905 906 run_ssh "rm -f /tmp/$modtar"; 907 908 return if (!defined($post_install)); 909 910 my $cp_post_install = $post_install; 911 $cp_post_install =~ s/\$KERNEL_VERSION/$version/g; 912 run_command "$cp_post_install" or 913 dodie "Failed to run post install"; 914} 915 916sub check_buildlog { 917 my ($patch) = @_; 918 919 my @files = `git show $patch | diffstat -l`; 920 921 open(IN, "git show $patch |") or 922 dodie "failed to show $patch"; 923 while (<IN>) { 924 if (m,^--- a/(.*),) { 925 chomp $1; 926 $files[$#files] = $1; 927 } 928 } 929 close(IN); 930 931 open(IN, $buildlog) or dodie "Can't open $buildlog"; 932 while (<IN>) { 933 if (/^\s*(.*?):.*(warning|error)/) { 934 my $err = $1; 935 foreach my $file (@files) { 936 my $fullpath = "$builddir/$file"; 937 if ($file eq $err || $fullpath eq $err) { 938 fail "$file built with warnings" and return 0; 939 } 940 } 941 } 942 } 943 close(IN); 944 945 return 1; 946} 947 948sub make_oldconfig { 949 my ($defconfig) = @_; 950 951 if (!run_command "$defconfig $make oldnoconfig") { 952 # Perhaps oldnoconfig doesn't exist in this version of the kernel 953 # try a yes '' | oldconfig 954 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 955 run_command "yes '' | $defconfig $make oldconfig" or 956 dodie "failed make config oldconfig"; 957 } 958} 959 960sub build { 961 my ($type) = @_; 962 my $defconfig = ""; 963 964 unlink $buildlog; 965 966 if ($type =~ /^useconfig:(.*)/) { 967 run_command "cp $1 $output_config" or 968 dodie "could not copy $1 to .config"; 969 970 $type = "oldconfig"; 971 } 972 973 # old config can ask questions 974 if ($type eq "oldconfig") { 975 $type = "oldnoconfig"; 976 977 # allow for empty configs 978 run_command "touch $output_config"; 979 980 run_command "mv $output_config $outputdir/config_temp" or 981 dodie "moving .config"; 982 983 if (!$noclean && !run_command "$make mrproper") { 984 dodie "make mrproper"; 985 } 986 987 run_command "mv $outputdir/config_temp $output_config" or 988 dodie "moving config_temp"; 989 990 } elsif (!$noclean) { 991 unlink "$output_config"; 992 run_command "$make mrproper" or 993 dodie "make mrproper"; 994 } 995 996 # add something to distinguish this build 997 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 998 print OUT "$localversion\n"; 999 close(OUT); 1000 1001 if (defined($minconfig)) { 1002 $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; 1003 } 1004 1005 if ($type eq "oldnoconfig") { 1006 make_oldconfig $defconfig; 1007 } else { 1008 run_command "$defconfig $make $type" or 1009 dodie "failed make config"; 1010 } 1011 1012 $redirect = "$buildlog"; 1013 if (!run_command "$make $build_options") { 1014 undef $redirect; 1015 # bisect may need this to pass 1016 return 0 if ($in_bisect); 1017 fail "failed build" and return 0; 1018 } 1019 undef $redirect; 1020 1021 return 1; 1022} 1023 1024sub halt { 1025 if (!run_ssh "halt" or defined($power_off)) { 1026 if (defined($poweroff_after_halt)) { 1027 sleep $poweroff_after_halt; 1028 run_command "$power_off"; 1029 } 1030 } else { 1031 # nope? the zap it! 1032 run_command "$power_off"; 1033 } 1034} 1035 1036sub success { 1037 my ($i) = @_; 1038 1039 $successes++; 1040 1041 doprint "\n\n*******************************************\n"; 1042 doprint "*******************************************\n"; 1043 doprint "KTEST RESULT: TEST $i SUCCESS!!!! **\n"; 1044 doprint "*******************************************\n"; 1045 doprint "*******************************************\n"; 1046 1047 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 1048 doprint "Reboot and wait $sleep_time seconds\n"; 1049 reboot; 1050 start_monitor; 1051 wait_for_monitor $sleep_time; 1052 end_monitor; 1053 } 1054} 1055 1056sub get_version { 1057 # get the release name 1058 doprint "$make kernelrelease ... "; 1059 $version = `$make kernelrelease | tail -1`; 1060 chomp($version); 1061 doprint "$version\n"; 1062} 1063 1064sub answer_bisect { 1065 for (;;) { 1066 doprint "Pass or fail? [p/f]"; 1067 my $ans = <STDIN>; 1068 chomp $ans; 1069 if ($ans eq "p" || $ans eq "P") { 1070 return 1; 1071 } elsif ($ans eq "f" || $ans eq "F") { 1072 return 0; 1073 } else { 1074 print "Please answer 'P' or 'F'\n"; 1075 } 1076 } 1077} 1078 1079sub child_run_test { 1080 my $failed = 0; 1081 1082 # child should have no power 1083 $reboot_on_error = 0; 1084 $poweroff_on_error = 0; 1085 $die_on_failure = 1; 1086 1087 run_command $run_test or $failed = 1; 1088 exit $failed; 1089} 1090 1091my $child_done; 1092 1093sub child_finished { 1094 $child_done = 1; 1095} 1096 1097sub do_run_test { 1098 my $child_pid; 1099 my $child_exit; 1100 my $line; 1101 my $full_line; 1102 my $bug = 0; 1103 1104 wait_for_monitor 1; 1105 1106 doprint "run test $run_test\n"; 1107 1108 $child_done = 0; 1109 1110 $SIG{CHLD} = qw(child_finished); 1111 1112 $child_pid = fork; 1113 1114 child_run_test if (!$child_pid); 1115 1116 $full_line = ""; 1117 1118 do { 1119 $line = wait_for_input($monitor_fp, 1); 1120 if (defined($line)) { 1121 1122 # we are not guaranteed to get a full line 1123 $full_line .= $line; 1124 doprint $line; 1125 1126 if ($full_line =~ /call trace:/i) { 1127 $bug = 1; 1128 } 1129 1130 if ($full_line =~ /Kernel panic -/) { 1131 $bug = 1; 1132 } 1133 1134 if ($line =~ /\n/) { 1135 $full_line = ""; 1136 } 1137 } 1138 } while (!$child_done && !$bug); 1139 1140 if ($bug) { 1141 my $failure_start = time; 1142 my $now; 1143 do { 1144 $line = wait_for_input($monitor_fp, 1); 1145 if (defined($line)) { 1146 doprint $line; 1147 } 1148 $now = time; 1149 if ($now - $failure_start >= $stop_after_failure) { 1150 last; 1151 } 1152 } while (defined($line)); 1153 1154 doprint "Detected kernel crash!\n"; 1155 # kill the child with extreme prejudice 1156 kill 9, $child_pid; 1157 } 1158 1159 waitpid $child_pid, 0; 1160 $child_exit = $?; 1161 1162 if ($bug || $child_exit) { 1163 return 0 if $in_bisect; 1164 fail "test failed" and return 0; 1165 } 1166 return 1; 1167} 1168 1169sub run_git_bisect { 1170 my ($command) = @_; 1171 1172 doprint "$command ... "; 1173 1174 my $output = `$command 2>&1`; 1175 my $ret = $?; 1176 1177 logit $output; 1178 1179 if ($ret) { 1180 doprint "FAILED\n"; 1181 dodie "Failed to git bisect"; 1182 } 1183 1184 doprint "SUCCESS\n"; 1185 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 1186 doprint "$1 [$2]\n"; 1187 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 1188 $bisect_bad = $1; 1189 doprint "Found bad commit... $1\n"; 1190 return 0; 1191 } else { 1192 # we already logged it, just print it now. 1193 print $output; 1194 } 1195 1196 return 1; 1197} 1198 1199sub bisect_reboot { 1200 doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 1201 reboot; 1202 start_monitor; 1203 wait_for_monitor $bisect_sleep_time; 1204 end_monitor; 1205} 1206 1207# returns 1 on success, 0 on failure, -1 on skip 1208sub run_bisect_test { 1209 my ($type, $buildtype) = @_; 1210 1211 my $failed = 0; 1212 my $result; 1213 my $output; 1214 my $ret; 1215 1216 $in_bisect = 1; 1217 1218 build $buildtype or $failed = 1; 1219 1220 if ($type ne "build") { 1221 if ($failed && $bisect_skip) { 1222 $in_bisect = 0; 1223 return -1; 1224 } 1225 dodie "Failed on build" if $failed; 1226 1227 # Now boot the box 1228 get_grub_index; 1229 get_version; 1230 install; 1231 1232 start_monitor; 1233 monitor or $failed = 1; 1234 1235 if ($type ne "boot") { 1236 if ($failed && $bisect_skip) { 1237 end_monitor; 1238 bisect_reboot; 1239 $in_bisect = 0; 1240 return -1; 1241 } 1242 dodie "Failed on boot" if $failed; 1243 1244 do_run_test or $failed = 1; 1245 } 1246 end_monitor; 1247 } 1248 1249 if ($failed) { 1250 $result = 0; 1251 } else { 1252 $result = 1; 1253 } 1254 1255 # reboot the box to a kernel we can ssh to 1256 if ($type ne "build") { 1257 bisect_reboot; 1258 } 1259 $in_bisect = 0; 1260 1261 return $result; 1262} 1263 1264sub run_bisect { 1265 my ($type) = @_; 1266 my $buildtype = "oldconfig"; 1267 1268 # We should have a minconfig to use? 1269 if (defined($minconfig)) { 1270 $buildtype = "useconfig:$minconfig"; 1271 } 1272 1273 my $ret = run_bisect_test $type, $buildtype; 1274 1275 if ($bisect_manual) { 1276 $ret = answer_bisect; 1277 } 1278 1279 # Are we looking for where it worked, not failed? 1280 if ($reverse_bisect) { 1281 $ret = !$ret; 1282 } 1283 1284 if ($ret > 0) { 1285 return "good"; 1286 } elsif ($ret == 0) { 1287 return "bad"; 1288 } elsif ($bisect_skip) { 1289 doprint "HIT A BAD COMMIT ... SKIPPING\n"; 1290 return "skip"; 1291 } 1292} 1293 1294sub bisect { 1295 my ($i) = @_; 1296 1297 my $result; 1298 1299 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 1300 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 1301 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 1302 1303 my $good = $opt{"BISECT_GOOD[$i]"}; 1304 my $bad = $opt{"BISECT_BAD[$i]"}; 1305 my $type = $opt{"BISECT_TYPE[$i]"}; 1306 my $start = $opt{"BISECT_START[$i]"}; 1307 my $replay = $opt{"BISECT_REPLAY[$i]"}; 1308 my $start_files = $opt{"BISECT_FILES[$i]"}; 1309 1310 if (defined($start_files)) { 1311 $start_files = " -- " . $start_files; 1312 } else { 1313 $start_files = ""; 1314 } 1315 1316 # convert to true sha1's 1317 $good = get_sha1($good); 1318 $bad = get_sha1($bad); 1319 1320 if (defined($opt{"BISECT_REVERSE[$i]"}) && 1321 $opt{"BISECT_REVERSE[$i]"} == 1) { 1322 doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 1323 $reverse_bisect = 1; 1324 } else { 1325 $reverse_bisect = 0; 1326 } 1327 1328 # Can't have a test without having a test to run 1329 if ($type eq "test" && !defined($run_test)) { 1330 $type = "boot"; 1331 } 1332 1333 my $check = $opt{"BISECT_CHECK[$i]"}; 1334 if (defined($check) && $check ne "0") { 1335 1336 # get current HEAD 1337 my $head = get_sha1("HEAD"); 1338 1339 if ($check ne "good") { 1340 doprint "TESTING BISECT BAD [$bad]\n"; 1341 run_command "git checkout $bad" or 1342 die "Failed to checkout $bad"; 1343 1344 $result = run_bisect $type; 1345 1346 if ($result ne "bad") { 1347 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 1348 } 1349 } 1350 1351 if ($check ne "bad") { 1352 doprint "TESTING BISECT GOOD [$good]\n"; 1353 run_command "git checkout $good" or 1354 die "Failed to checkout $good"; 1355 1356 $result = run_bisect $type; 1357 1358 if ($result ne "good") { 1359 fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 1360 } 1361 } 1362 1363 # checkout where we started 1364 run_command "git checkout $head" or 1365 die "Failed to checkout $head"; 1366 } 1367 1368 run_command "git bisect start$start_files" or 1369 dodie "could not start bisect"; 1370 1371 run_command "git bisect good $good" or 1372 dodie "could not set bisect good to $good"; 1373 1374 run_git_bisect "git bisect bad $bad" or 1375 dodie "could not set bisect bad to $bad"; 1376 1377 if (defined($replay)) { 1378 run_command "git bisect replay $replay" or 1379 dodie "failed to run replay"; 1380 } 1381 1382 if (defined($start)) { 1383 run_command "git checkout $start" or 1384 dodie "failed to checkout $start"; 1385 } 1386 1387 my $test; 1388 do { 1389 $result = run_bisect $type; 1390 $test = run_git_bisect "git bisect $result"; 1391 } while ($test); 1392 1393 run_command "git bisect log" or 1394 dodie "could not capture git bisect log"; 1395 1396 run_command "git bisect reset" or 1397 dodie "could not reset git bisect"; 1398 1399 doprint "Bad commit was [$bisect_bad]\n"; 1400 1401 success $i; 1402} 1403 1404my %config_ignore; 1405my %config_set; 1406 1407my %config_list; 1408my %null_config; 1409 1410my %dependency; 1411 1412sub process_config_ignore { 1413 my ($config) = @_; 1414 1415 open (IN, $config) 1416 or dodie "Failed to read $config"; 1417 1418 while (<IN>) { 1419 if (/^(.*?(CONFIG\S*)(=.*| is not set))/) { 1420 $config_ignore{$2} = $1; 1421 } 1422 } 1423 1424 close(IN); 1425} 1426 1427sub read_current_config { 1428 my ($config_ref) = @_; 1429 1430 %{$config_ref} = (); 1431 undef %{$config_ref}; 1432 1433 my @key = keys %{$config_ref}; 1434 if ($#key >= 0) { 1435 print "did not delete!\n"; 1436 exit; 1437 } 1438 open (IN, "$output_config"); 1439 1440 while (<IN>) { 1441 if (/^(CONFIG\S+)=(.*)/) { 1442 ${$config_ref}{$1} = $2; 1443 } 1444 } 1445 close(IN); 1446} 1447 1448sub get_dependencies { 1449 my ($config) = @_; 1450 1451 my $arr = $dependency{$config}; 1452 if (!defined($arr)) { 1453 return (); 1454 } 1455 1456 my @deps = @{$arr}; 1457 1458 foreach my $dep (@{$arr}) { 1459 print "ADD DEP $dep\n"; 1460 @deps = (@deps, get_dependencies $dep); 1461 } 1462 1463 return @deps; 1464} 1465 1466sub create_config { 1467 my @configs = @_; 1468 1469 open(OUT, ">$output_config") or dodie "Can not write to $output_config"; 1470 1471 foreach my $config (@configs) { 1472 print OUT "$config_set{$config}\n"; 1473 my @deps = get_dependencies $config; 1474 foreach my $dep (@deps) { 1475 print OUT "$config_set{$dep}\n"; 1476 } 1477 } 1478 1479 foreach my $config (keys %config_ignore) { 1480 print OUT "$config_ignore{$config}\n"; 1481 } 1482 close(OUT); 1483 1484# exit; 1485 make_oldconfig ""; 1486} 1487 1488sub compare_configs { 1489 my (%a, %b) = @_; 1490 1491 foreach my $item (keys %a) { 1492 if (!defined($b{$item})) { 1493 print "diff $item\n"; 1494 return 1; 1495 } 1496 delete $b{$item}; 1497 } 1498 1499 my @keys = keys %b; 1500 if ($#keys) { 1501 print "diff2 $keys[0]\n"; 1502 } 1503 return -1 if ($#keys >= 0); 1504 1505 return 0; 1506} 1507 1508sub run_config_bisect_test { 1509 my ($type) = @_; 1510 1511 return run_bisect_test $type, "oldconfig"; 1512} 1513 1514sub process_passed { 1515 my (%configs) = @_; 1516 1517 doprint "These configs had no failure: (Enabling them for further compiles)\n"; 1518 # Passed! All these configs are part of a good compile. 1519 # Add them to the min options. 1520 foreach my $config (keys %configs) { 1521 if (defined($config_list{$config})) { 1522 doprint " removing $config\n"; 1523 $config_ignore{$config} = $config_list{$config}; 1524 delete $config_list{$config}; 1525 } 1526 } 1527 doprint "config copied to $outputdir/config_good\n"; 1528 run_command "cp -f $output_config $outputdir/config_good"; 1529} 1530 1531sub process_failed { 1532 my ($config) = @_; 1533 1534 doprint "\n\n***************************************\n"; 1535 doprint "Found bad config: $config\n"; 1536 doprint "***************************************\n\n"; 1537} 1538 1539sub run_config_bisect { 1540 1541 my @start_list = keys %config_list; 1542 1543 if ($#start_list < 0) { 1544 doprint "No more configs to test!!!\n"; 1545 return -1; 1546 } 1547 1548 doprint "***** RUN TEST ***\n"; 1549 my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"}; 1550 my $ret; 1551 my %current_config; 1552 1553 my $count = $#start_list + 1; 1554 doprint " $count configs to test\n"; 1555 1556 my $half = int($#start_list / 2); 1557 1558 do { 1559 my @tophalf = @start_list[0 .. $half]; 1560 1561 create_config @tophalf; 1562 read_current_config \%current_config; 1563 1564 $count = $#tophalf + 1; 1565 doprint "Testing $count configs\n"; 1566 my $found = 0; 1567 # make sure we test something 1568 foreach my $config (@tophalf) { 1569 if (defined($current_config{$config})) { 1570 logit " $config\n"; 1571 $found = 1; 1572 } 1573 } 1574 if (!$found) { 1575 # try the other half 1576 doprint "Top half produced no set configs, trying bottom half\n"; 1577 @tophalf = @start_list[$half .. $#start_list]; 1578 create_config @tophalf; 1579 read_current_config \%current_config; 1580 foreach my $config (@tophalf) { 1581 if (defined($current_config{$config})) { 1582 logit " $config\n"; 1583 $found = 1; 1584 } 1585 } 1586 if (!$found) { 1587 doprint "Failed: Can't make new config with current configs\n"; 1588 foreach my $config (@start_list) { 1589 doprint " CONFIG: $config\n"; 1590 } 1591 return -1; 1592 } 1593 $count = $#tophalf + 1; 1594 doprint "Testing $count configs\n"; 1595 } 1596 1597 $ret = run_config_bisect_test $type; 1598 if ($bisect_manual) { 1599 $ret = answer_bisect; 1600 } 1601 if ($ret) { 1602 process_passed %current_config; 1603 return 0; 1604 } 1605 1606 doprint "This config had a failure.\n"; 1607 doprint "Removing these configs that were not set in this config:\n"; 1608 doprint "config copied to $outputdir/config_bad\n"; 1609 run_command "cp -f $output_config $outputdir/config_bad"; 1610 1611 # A config exists in this group that was bad. 1612 foreach my $config (keys %config_list) { 1613 if (!defined($current_config{$config})) { 1614 doprint " removing $config\n"; 1615 delete $config_list{$config}; 1616 } 1617 } 1618 1619 @start_list = @tophalf; 1620 1621 if ($#start_list == 0) { 1622 process_failed $start_list[0]; 1623 return 1; 1624 } 1625 1626 # remove half the configs we are looking at and see if 1627 # they are good. 1628 $half = int($#start_list / 2); 1629 } while ($half > 0); 1630 1631 # we found a single config, try it again unless we are running manually 1632 1633 if ($bisect_manual) { 1634 process_failed $start_list[0]; 1635 return 1; 1636 } 1637 1638 my @tophalf = @start_list[0 .. 0]; 1639 1640 $ret = run_config_bisect_test $type; 1641 if ($ret) { 1642 process_passed %current_config; 1643 return 0; 1644 } 1645 1646 process_failed $start_list[0]; 1647 return 1; 1648} 1649 1650sub config_bisect { 1651 my ($i) = @_; 1652 1653 my $start_config = $opt{"CONFIG_BISECT[$i]"}; 1654 1655 my $tmpconfig = "$tmpdir/use_config"; 1656 1657 # Make the file with the bad config and the min config 1658 if (defined($minconfig)) { 1659 # read the min config for things to ignore 1660 run_command "cp $minconfig $tmpconfig" or 1661 dodie "failed to copy $minconfig to $tmpconfig"; 1662 } else { 1663 unlink $tmpconfig; 1664 } 1665 1666 # Add other configs 1667 if (defined($addconfig)) { 1668 run_command "cat $addconfig >> $tmpconfig" or 1669 dodie "failed to append $addconfig"; 1670 } 1671 1672 my $defconfig = ""; 1673 if (-f $tmpconfig) { 1674 $defconfig = "KCONFIG_ALLCONFIG=$tmpconfig"; 1675 process_config_ignore $tmpconfig; 1676 } 1677 1678 # now process the start config 1679 run_command "cp $start_config $output_config" or 1680 dodie "failed to copy $start_config to $output_config"; 1681 1682 # read directly what we want to check 1683 my %config_check; 1684 open (IN, $output_config) 1685 or dodie "faied to open $output_config"; 1686 1687 while (<IN>) { 1688 if (/^((CONFIG\S*)=.*)/) { 1689 $config_check{$2} = $1; 1690 } 1691 } 1692 close(IN); 1693 1694 # Now run oldconfig with the minconfig (and addconfigs) 1695 make_oldconfig $defconfig; 1696 1697 # check to see what we lost (or gained) 1698 open (IN, $output_config) 1699 or dodie "Failed to read $start_config"; 1700 1701 my %removed_configs; 1702 my %added_configs; 1703 1704 while (<IN>) { 1705 if (/^((CONFIG\S*)=.*)/) { 1706 # save off all options 1707 $config_set{$2} = $1; 1708 if (defined($config_check{$2})) { 1709 if (defined($config_ignore{$2})) { 1710 $removed_configs{$2} = $1; 1711 } else { 1712 $config_list{$2} = $1; 1713 } 1714 } elsif (!defined($config_ignore{$2})) { 1715 $added_configs{$2} = $1; 1716 $config_list{$2} = $1; 1717 } 1718 } 1719 } 1720 close(IN); 1721 1722 my @confs = keys %removed_configs; 1723 if ($#confs >= 0) { 1724 doprint "Configs overridden by default configs and removed from check:\n"; 1725 foreach my $config (@confs) { 1726 doprint " $config\n"; 1727 } 1728 } 1729 @confs = keys %added_configs; 1730 if ($#confs >= 0) { 1731 doprint "Configs appearing in make oldconfig and added:\n"; 1732 foreach my $config (@confs) { 1733 doprint " $config\n"; 1734 } 1735 } 1736 1737 my %config_test; 1738 my $once = 0; 1739 1740 # Sometimes kconfig does weird things. We must make sure 1741 # that the config we autocreate has everything we need 1742 # to test, otherwise we may miss testing configs, or 1743 # may not be able to create a new config. 1744 # Here we create a config with everything set. 1745 create_config (keys %config_list); 1746 read_current_config \%config_test; 1747 foreach my $config (keys %config_list) { 1748 if (!defined($config_test{$config})) { 1749 if (!$once) { 1750 $once = 1; 1751 doprint "Configs not produced by kconfig (will not be checked):\n"; 1752 } 1753 doprint " $config\n"; 1754 delete $config_list{$config}; 1755 } 1756 } 1757 my $ret; 1758 do { 1759 $ret = run_config_bisect; 1760 } while (!$ret); 1761 1762 return $ret if ($ret < 0); 1763 1764 success $i; 1765} 1766 1767sub patchcheck { 1768 my ($i) = @_; 1769 1770 die "PATCHCHECK_START[$i] not defined\n" 1771 if (!defined($opt{"PATCHCHECK_START[$i]"})); 1772 die "PATCHCHECK_TYPE[$i] not defined\n" 1773 if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 1774 1775 my $start = $opt{"PATCHCHECK_START[$i]"}; 1776 1777 my $end = "HEAD"; 1778 if (defined($opt{"PATCHCHECK_END[$i]"})) { 1779 $end = $opt{"PATCHCHECK_END[$i]"}; 1780 } 1781 1782 # Get the true sha1's since we can use things like HEAD~3 1783 $start = get_sha1($start); 1784 $end = get_sha1($end); 1785 1786 my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 1787 1788 # Can't have a test without having a test to run 1789 if ($type eq "test" && !defined($run_test)) { 1790 $type = "boot"; 1791 } 1792 1793 open (IN, "git log --pretty=oneline $end|") or 1794 dodie "could not get git list"; 1795 1796 my @list; 1797 1798 while (<IN>) { 1799 chomp; 1800 $list[$#list+1] = $_; 1801 last if (/^$start/); 1802 } 1803 close(IN); 1804 1805 if ($list[$#list] !~ /^$start/) { 1806 fail "SHA1 $start not found"; 1807 } 1808 1809 # go backwards in the list 1810 @list = reverse @list; 1811 1812 my $save_clean = $noclean; 1813 1814 $in_patchcheck = 1; 1815 foreach my $item (@list) { 1816 my $sha1 = $item; 1817 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 1818 1819 doprint "\nProcessing commit $item\n\n"; 1820 1821 run_command "git checkout $sha1" or 1822 die "Failed to checkout $sha1"; 1823 1824 # only clean on the first and last patch 1825 if ($item eq $list[0] || 1826 $item eq $list[$#list]) { 1827 $noclean = $save_clean; 1828 } else { 1829 $noclean = 1; 1830 } 1831 1832 if (defined($minconfig)) { 1833 build "useconfig:$minconfig" or return 0; 1834 } else { 1835 # ?? no config to use? 1836 build "oldconfig" or return 0; 1837 } 1838 1839 check_buildlog $sha1 or return 0; 1840 1841 next if ($type eq "build"); 1842 1843 get_grub_index; 1844 get_version; 1845 install; 1846 1847 my $failed = 0; 1848 1849 start_monitor; 1850 monitor or $failed = 1; 1851 1852 if (!$failed && $type ne "boot"){ 1853 do_run_test or $failed = 1; 1854 } 1855 end_monitor; 1856 return 0 if ($failed); 1857 1858 } 1859 $in_patchcheck = 0; 1860 success $i; 1861 1862 return 1; 1863} 1864 1865$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 1866 1867if ($#ARGV == 0) { 1868 $ktest_config = $ARGV[0]; 1869 if (! -f $ktest_config) { 1870 print "$ktest_config does not exist.\n"; 1871 my $ans; 1872 for (;;) { 1873 print "Create it? [Y/n] "; 1874 $ans = <STDIN>; 1875 chomp $ans; 1876 if ($ans =~ /^\s*$/) { 1877 $ans = "y"; 1878 } 1879 last if ($ans =~ /^y$/i || $ans =~ /^n$/i); 1880 print "Please answer either 'y' or 'n'.\n"; 1881 } 1882 if ($ans !~ /^y$/i) { 1883 exit 0; 1884 } 1885 } 1886} else { 1887 $ktest_config = "ktest.conf"; 1888} 1889 1890if (! -f $ktest_config) { 1891 open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 1892 print OUT << "EOF" 1893# Generated by ktest.pl 1894# 1895# Define each test with TEST_START 1896# The config options below it will override the defaults 1897TEST_START 1898 1899DEFAULTS 1900EOF 1901; 1902 close(OUT); 1903} 1904read_config $ktest_config; 1905 1906# Append any configs entered in manually to the config file. 1907my @new_configs = keys %entered_configs; 1908if ($#new_configs >= 0) { 1909 print "\nAppending entered in configs to $ktest_config\n"; 1910 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 1911 foreach my $config (@new_configs) { 1912 print OUT "$config = $entered_configs{$config}\n"; 1913 $opt{$config} = $entered_configs{$config}; 1914 } 1915} 1916 1917if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 1918 unlink $opt{"LOG_FILE"}; 1919} 1920 1921doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 1922 1923for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 1924 1925 if (!$i) { 1926 doprint "DEFAULT OPTIONS:\n"; 1927 } else { 1928 doprint "\nTEST $i OPTIONS"; 1929 if (defined($repeat_tests{$i})) { 1930 $repeat = $repeat_tests{$i}; 1931 doprint " ITERATE $repeat"; 1932 } 1933 doprint "\n"; 1934 } 1935 1936 foreach my $option (sort keys %opt) { 1937 1938 if ($option =~ /\[(\d+)\]$/) { 1939 next if ($i != $1); 1940 } else { 1941 next if ($i); 1942 } 1943 1944 doprint "$option = $opt{$option}\n"; 1945 } 1946} 1947 1948sub set_test_option { 1949 my ($name, $i) = @_; 1950 1951 my $option = "$name\[$i\]"; 1952 1953 if (defined($opt{$option})) { 1954 return $opt{$option}; 1955 } 1956 1957 foreach my $test (keys %repeat_tests) { 1958 if ($i >= $test && 1959 $i < $test + $repeat_tests{$test}) { 1960 $option = "$name\[$test\]"; 1961 if (defined($opt{$option})) { 1962 return $opt{$option}; 1963 } 1964 } 1965 } 1966 1967 if (defined($opt{$name})) { 1968 return $opt{$name}; 1969 } 1970 1971 return undef; 1972} 1973 1974# First we need to do is the builds 1975for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 1976 1977 $iteration = $i; 1978 1979 my $makecmd = set_test_option("MAKE_CMD", $i); 1980 1981 $machine = set_test_option("MACHINE", $i); 1982 $ssh_user = set_test_option("SSH_USER", $i); 1983 $tmpdir = set_test_option("TMP_DIR", $i); 1984 $outputdir = set_test_option("OUTPUT_DIR", $i); 1985 $builddir = set_test_option("BUILD_DIR", $i); 1986 $test_type = set_test_option("TEST_TYPE", $i); 1987 $build_type = set_test_option("BUILD_TYPE", $i); 1988 $build_options = set_test_option("BUILD_OPTIONS", $i); 1989 $power_cycle = set_test_option("POWER_CYCLE", $i); 1990 $reboot = set_test_option("REBOOT", $i); 1991 $noclean = set_test_option("BUILD_NOCLEAN", $i); 1992 $minconfig = set_test_option("MIN_CONFIG", $i); 1993 $run_test = set_test_option("TEST", $i); 1994 $addconfig = set_test_option("ADD_CONFIG", $i); 1995 $reboot_type = set_test_option("REBOOT_TYPE", $i); 1996 $grub_menu = set_test_option("GRUB_MENU", $i); 1997 $post_install = set_test_option("POST_INSTALL", $i); 1998 $reboot_script = set_test_option("REBOOT_SCRIPT", $i); 1999 $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); 2000 $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); 2001 $die_on_failure = set_test_option("DIE_ON_FAILURE", $i); 2002 $power_off = set_test_option("POWER_OFF", $i); 2003 $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i); 2004 $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i); 2005 $sleep_time = set_test_option("SLEEP_TIME", $i); 2006 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 2007 $bisect_manual = set_test_option("BISECT_MANUAL", $i); 2008 $bisect_skip = set_test_option("BISECT_SKIP", $i); 2009 $store_failures = set_test_option("STORE_FAILURES", $i); 2010 $timeout = set_test_option("TIMEOUT", $i); 2011 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 2012 $console = set_test_option("CONSOLE", $i); 2013 $success_line = set_test_option("SUCCESS_LINE", $i); 2014 $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); 2015 $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); 2016 $stop_test_after = set_test_option("STOP_TEST_AFTER", $i); 2017 $build_target = set_test_option("BUILD_TARGET", $i); 2018 $ssh_exec = set_test_option("SSH_EXEC", $i); 2019 $scp_to_target = set_test_option("SCP_TO_TARGET", $i); 2020 $target_image = set_test_option("TARGET_IMAGE", $i); 2021 $localversion = set_test_option("LOCALVERSION", $i); 2022 2023 chdir $builddir || die "can't change directory to $builddir"; 2024 2025 if (!-d $tmpdir) { 2026 mkpath($tmpdir) or 2027 die "can't create $tmpdir"; 2028 } 2029 2030 $ENV{"SSH_USER"} = $ssh_user; 2031 $ENV{"MACHINE"} = $machine; 2032 2033 $target = "$ssh_user\@$machine"; 2034 2035 $buildlog = "$tmpdir/buildlog-$machine"; 2036 $dmesg = "$tmpdir/dmesg-$machine"; 2037 $make = "$makecmd O=$outputdir"; 2038 $output_config = "$outputdir/.config"; 2039 2040 if ($reboot_type eq "grub") { 2041 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 2042 } elsif (!defined($reboot_script)) { 2043 dodie "REBOOT_SCRIPT not defined" 2044 } 2045 2046 my $run_type = $build_type; 2047 if ($test_type eq "patchcheck") { 2048 $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 2049 } elsif ($test_type eq "bisect") { 2050 $run_type = $opt{"BISECT_TYPE[$i]"}; 2051 } elsif ($test_type eq "config_bisect") { 2052 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; 2053 } 2054 2055 # mistake in config file? 2056 if (!defined($run_type)) { 2057 $run_type = "ERROR"; 2058 } 2059 2060 doprint "\n\n"; 2061 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n"; 2062 2063 unlink $dmesg; 2064 unlink $buildlog; 2065 2066 if (!defined($minconfig)) { 2067 $minconfig = $addconfig; 2068 2069 } elsif (defined($addconfig)) { 2070 run_command "cat $addconfig $minconfig > $tmpdir/add_config" or 2071 dodie "Failed to create temp config"; 2072 $minconfig = "$tmpdir/add_config"; 2073 } 2074 2075 my $checkout = $opt{"CHECKOUT[$i]"}; 2076 if (defined($checkout)) { 2077 run_command "git checkout $checkout" or 2078 die "failed to checkout $checkout"; 2079 } 2080 2081 if ($test_type eq "bisect") { 2082 bisect $i; 2083 next; 2084 } elsif ($test_type eq "config_bisect") { 2085 config_bisect $i; 2086 next; 2087 } elsif ($test_type eq "patchcheck") { 2088 patchcheck $i; 2089 next; 2090 } 2091 2092 if ($build_type ne "nobuild") { 2093 build $build_type or next; 2094 } 2095 2096 if ($test_type ne "build") { 2097 get_grub_index; 2098 get_version; 2099 install; 2100 2101 my $failed = 0; 2102 start_monitor; 2103 monitor or $failed = 1;; 2104 2105 if (!$failed && $test_type ne "boot" && defined($run_test)) { 2106 do_run_test or $failed = 1; 2107 } 2108 end_monitor; 2109 next if ($failed); 2110 } 2111 2112 success $i; 2113} 2114 2115if ($opt{"POWEROFF_ON_SUCCESS"}) { 2116 halt; 2117} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { 2118 reboot; 2119} 2120 2121doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 2122 2123exit 0; 2124