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 $done = 1; 842 } 843 } 844 } 845 846 close(DMESG); 847 848 if ($bug) { 849 return 0 if ($in_bisect); 850 fail "failed - got a bug report" and return 0; 851 } 852 853 if (!$booted) { 854 return 0 if ($in_bisect); 855 fail "failed - never got a boot prompt." and return 0; 856 } 857 858 return 1; 859} 860 861sub install { 862 863 run_scp "$outputdir/$build_target", "$target_image" or 864 dodie "failed to copy image"; 865 866 my $install_mods = 0; 867 868 # should we process modules? 869 $install_mods = 0; 870 open(IN, "$output_config") or dodie("Can't read config file"); 871 while (<IN>) { 872 if (/CONFIG_MODULES(=y)?/) { 873 $install_mods = 1 if (defined($1)); 874 last; 875 } 876 } 877 close(IN); 878 879 if (!$install_mods) { 880 doprint "No modules needed\n"; 881 return; 882 } 883 884 run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or 885 dodie "Failed to install modules"; 886 887 my $modlib = "/lib/modules/$version"; 888 my $modtar = "ktest-mods.tar.bz2"; 889 890 run_ssh "rm -rf $modlib" or 891 dodie "failed to remove old mods: $modlib"; 892 893 # would be nice if scp -r did not follow symbolic links 894 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 895 dodie "making tarball"; 896 897 run_scp "$tmpdir/$modtar", "/tmp" or 898 dodie "failed to copy modules"; 899 900 unlink "$tmpdir/$modtar"; 901 902 run_ssh "'(cd / && tar xf /tmp/$modtar)'" or 903 dodie "failed to tar modules"; 904 905 run_ssh "rm -f /tmp/$modtar"; 906 907 return if (!defined($post_install)); 908 909 my $cp_post_install = $post_install; 910 $cp_post_install = s/\$KERNEL_VERSION/$version/g; 911 run_command "$cp_post_install" or 912 dodie "Failed to run post install"; 913} 914 915sub check_buildlog { 916 my ($patch) = @_; 917 918 my @files = `git show $patch | diffstat -l`; 919 920 open(IN, "git show $patch |") or 921 dodie "failed to show $patch"; 922 while (<IN>) { 923 if (m,^--- a/(.*),) { 924 chomp $1; 925 $files[$#files] = $1; 926 } 927 } 928 close(IN); 929 930 open(IN, $buildlog) or dodie "Can't open $buildlog"; 931 while (<IN>) { 932 if (/^\s*(.*?):.*(warning|error)/) { 933 my $err = $1; 934 foreach my $file (@files) { 935 my $fullpath = "$builddir/$file"; 936 if ($file eq $err || $fullpath eq $err) { 937 fail "$file built with warnings" and return 0; 938 } 939 } 940 } 941 } 942 close(IN); 943 944 return 1; 945} 946 947sub make_oldconfig { 948 my ($defconfig) = @_; 949 950 if (!run_command "$defconfig $make oldnoconfig") { 951 # Perhaps oldnoconfig doesn't exist in this version of the kernel 952 # try a yes '' | oldconfig 953 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 954 run_command "yes '' | $defconfig $make oldconfig" or 955 dodie "failed make config oldconfig"; 956 } 957} 958 959sub build { 960 my ($type) = @_; 961 my $defconfig = ""; 962 963 unlink $buildlog; 964 965 if ($type =~ /^useconfig:(.*)/) { 966 run_command "cp $1 $output_config" or 967 dodie "could not copy $1 to .config"; 968 969 $type = "oldconfig"; 970 } 971 972 # old config can ask questions 973 if ($type eq "oldconfig") { 974 $type = "oldnoconfig"; 975 976 # allow for empty configs 977 run_command "touch $output_config"; 978 979 run_command "mv $output_config $outputdir/config_temp" or 980 dodie "moving .config"; 981 982 if (!$noclean && !run_command "$make mrproper") { 983 dodie "make mrproper"; 984 } 985 986 run_command "mv $outputdir/config_temp $output_config" or 987 dodie "moving config_temp"; 988 989 } elsif (!$noclean) { 990 unlink "$output_config"; 991 run_command "$make mrproper" or 992 dodie "make mrproper"; 993 } 994 995 # add something to distinguish this build 996 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 997 print OUT "$localversion\n"; 998 close(OUT); 999 1000 if (defined($minconfig)) { 1001 $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; 1002 } 1003 1004 if ($type eq "oldnoconfig") { 1005 make_oldconfig $defconfig; 1006 } else { 1007 run_command "$defconfig $make $type" or 1008 dodie "failed make config"; 1009 } 1010 1011 $redirect = "$buildlog"; 1012 if (!run_command "$make $build_options") { 1013 undef $redirect; 1014 # bisect may need this to pass 1015 return 0 if ($in_bisect); 1016 fail "failed build" and return 0; 1017 } 1018 undef $redirect; 1019 1020 return 1; 1021} 1022 1023sub halt { 1024 if (!run_ssh "halt" or defined($power_off)) { 1025 if (defined($poweroff_after_halt)) { 1026 sleep $poweroff_after_halt; 1027 run_command "$power_off"; 1028 } 1029 } else { 1030 # nope? the zap it! 1031 run_command "$power_off"; 1032 } 1033} 1034 1035sub success { 1036 my ($i) = @_; 1037 1038 $successes++; 1039 1040 doprint "\n\n*******************************************\n"; 1041 doprint "*******************************************\n"; 1042 doprint "KTEST RESULT: TEST $i SUCCESS!!!! **\n"; 1043 doprint "*******************************************\n"; 1044 doprint "*******************************************\n"; 1045 1046 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 1047 doprint "Reboot and wait $sleep_time seconds\n"; 1048 reboot; 1049 start_monitor; 1050 wait_for_monitor $sleep_time; 1051 end_monitor; 1052 } 1053} 1054 1055sub get_version { 1056 # get the release name 1057 doprint "$make kernelrelease ... "; 1058 $version = `$make kernelrelease | tail -1`; 1059 chomp($version); 1060 doprint "$version\n"; 1061} 1062 1063sub answer_bisect { 1064 for (;;) { 1065 doprint "Pass or fail? [p/f]"; 1066 my $ans = <STDIN>; 1067 chomp $ans; 1068 if ($ans eq "p" || $ans eq "P") { 1069 return 1; 1070 } elsif ($ans eq "f" || $ans eq "F") { 1071 return 0; 1072 } else { 1073 print "Please answer 'P' or 'F'\n"; 1074 } 1075 } 1076} 1077 1078sub child_run_test { 1079 my $failed = 0; 1080 1081 # child should have no power 1082 $reboot_on_error = 0; 1083 $poweroff_on_error = 0; 1084 $die_on_failure = 1; 1085 1086 run_command $run_test or $failed = 1; 1087 exit $failed; 1088} 1089 1090my $child_done; 1091 1092sub child_finished { 1093 $child_done = 1; 1094} 1095 1096sub do_run_test { 1097 my $child_pid; 1098 my $child_exit; 1099 my $line; 1100 my $full_line; 1101 my $bug = 0; 1102 1103 wait_for_monitor 1; 1104 1105 doprint "run test $run_test\n"; 1106 1107 $child_done = 0; 1108 1109 $SIG{CHLD} = qw(child_finished); 1110 1111 $child_pid = fork; 1112 1113 child_run_test if (!$child_pid); 1114 1115 $full_line = ""; 1116 1117 do { 1118 $line = wait_for_input($monitor_fp, 1); 1119 if (defined($line)) { 1120 1121 # we are not guaranteed to get a full line 1122 $full_line .= $line; 1123 doprint $line; 1124 1125 if ($full_line =~ /call trace:/i) { 1126 $bug = 1; 1127 } 1128 1129 if ($full_line =~ /Kernel panic -/) { 1130 $bug = 1; 1131 } 1132 1133 if ($line =~ /\n/) { 1134 $full_line = ""; 1135 } 1136 } 1137 } while (!$child_done && !$bug); 1138 1139 if ($bug) { 1140 my $failure_start = time; 1141 my $now; 1142 do { 1143 $line = wait_for_input($monitor_fp, 1); 1144 if (defined($line)) { 1145 doprint $line; 1146 } 1147 $now = time; 1148 if ($now - $failure_start >= $stop_after_failure) { 1149 last; 1150 } 1151 } while (defined($line)); 1152 1153 doprint "Detected kernel crash!\n"; 1154 # kill the child with extreme prejudice 1155 kill 9, $child_pid; 1156 } 1157 1158 waitpid $child_pid, 0; 1159 $child_exit = $?; 1160 1161 if ($bug || $child_exit) { 1162 return 0 if $in_bisect; 1163 fail "test failed" and return 0; 1164 } 1165 return 1; 1166} 1167 1168sub run_git_bisect { 1169 my ($command) = @_; 1170 1171 doprint "$command ... "; 1172 1173 my $output = `$command 2>&1`; 1174 my $ret = $?; 1175 1176 logit $output; 1177 1178 if ($ret) { 1179 doprint "FAILED\n"; 1180 dodie "Failed to git bisect"; 1181 } 1182 1183 doprint "SUCCESS\n"; 1184 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 1185 doprint "$1 [$2]\n"; 1186 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 1187 $bisect_bad = $1; 1188 doprint "Found bad commit... $1\n"; 1189 return 0; 1190 } else { 1191 # we already logged it, just print it now. 1192 print $output; 1193 } 1194 1195 return 1; 1196} 1197 1198sub bisect_reboot { 1199 doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 1200 reboot; 1201 start_monitor; 1202 wait_for_monitor $bisect_sleep_time; 1203 end_monitor; 1204} 1205 1206# returns 1 on success, 0 on failure, -1 on skip 1207sub run_bisect_test { 1208 my ($type, $buildtype) = @_; 1209 1210 my $failed = 0; 1211 my $result; 1212 my $output; 1213 my $ret; 1214 1215 $in_bisect = 1; 1216 1217 build $buildtype or $failed = 1; 1218 1219 if ($type ne "build") { 1220 if ($failed && $bisect_skip) { 1221 $in_bisect = 0; 1222 return -1; 1223 } 1224 dodie "Failed on build" if $failed; 1225 1226 # Now boot the box 1227 get_grub_index; 1228 get_version; 1229 install; 1230 1231 start_monitor; 1232 monitor or $failed = 1; 1233 1234 if ($type ne "boot") { 1235 if ($failed && $bisect_skip) { 1236 end_monitor; 1237 bisect_reboot; 1238 $in_bisect = 0; 1239 return -1; 1240 } 1241 dodie "Failed on boot" if $failed; 1242 1243 do_run_test or $failed = 1; 1244 } 1245 end_monitor; 1246 } 1247 1248 if ($failed) { 1249 $result = 0; 1250 1251 # reboot the box to a good kernel 1252 if ($type ne "build") { 1253 bisect_reboot; 1254 } 1255 } else { 1256 $result = 1; 1257 } 1258 $in_bisect = 0; 1259 1260 return $result; 1261} 1262 1263sub run_bisect { 1264 my ($type) = @_; 1265 my $buildtype = "oldconfig"; 1266 1267 # We should have a minconfig to use? 1268 if (defined($minconfig)) { 1269 $buildtype = "useconfig:$minconfig"; 1270 } 1271 1272 my $ret = run_bisect_test $type, $buildtype; 1273 1274 if ($bisect_manual) { 1275 $ret = answer_bisect; 1276 } 1277 1278 # Are we looking for where it worked, not failed? 1279 if ($reverse_bisect) { 1280 $ret = !$ret; 1281 } 1282 1283 if ($ret > 0) { 1284 return "good"; 1285 } elsif ($ret == 0) { 1286 return "bad"; 1287 } elsif ($bisect_skip) { 1288 doprint "HIT A BAD COMMIT ... SKIPPING\n"; 1289 return "skip"; 1290 } 1291} 1292 1293sub bisect { 1294 my ($i) = @_; 1295 1296 my $result; 1297 1298 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 1299 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 1300 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 1301 1302 my $good = $opt{"BISECT_GOOD[$i]"}; 1303 my $bad = $opt{"BISECT_BAD[$i]"}; 1304 my $type = $opt{"BISECT_TYPE[$i]"}; 1305 my $start = $opt{"BISECT_START[$i]"}; 1306 my $replay = $opt{"BISECT_REPLAY[$i]"}; 1307 my $start_files = $opt{"BISECT_FILES[$i]"}; 1308 1309 if (defined($start_files)) { 1310 $start_files = " -- " . $start_files; 1311 } else { 1312 $start_files = ""; 1313 } 1314 1315 # convert to true sha1's 1316 $good = get_sha1($good); 1317 $bad = get_sha1($bad); 1318 1319 if (defined($opt{"BISECT_REVERSE[$i]"}) && 1320 $opt{"BISECT_REVERSE[$i]"} == 1) { 1321 doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 1322 $reverse_bisect = 1; 1323 } else { 1324 $reverse_bisect = 0; 1325 } 1326 1327 # Can't have a test without having a test to run 1328 if ($type eq "test" && !defined($run_test)) { 1329 $type = "boot"; 1330 } 1331 1332 my $check = $opt{"BISECT_CHECK[$i]"}; 1333 if (defined($check) && $check ne "0") { 1334 1335 # get current HEAD 1336 my $head = get_sha1("HEAD"); 1337 1338 if ($check ne "good") { 1339 doprint "TESTING BISECT BAD [$bad]\n"; 1340 run_command "git checkout $bad" or 1341 die "Failed to checkout $bad"; 1342 1343 $result = run_bisect $type; 1344 1345 if ($result ne "bad") { 1346 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 1347 } 1348 } 1349 1350 if ($check ne "bad") { 1351 doprint "TESTING BISECT GOOD [$good]\n"; 1352 run_command "git checkout $good" or 1353 die "Failed to checkout $good"; 1354 1355 $result = run_bisect $type; 1356 1357 if ($result ne "good") { 1358 fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 1359 } 1360 } 1361 1362 # checkout where we started 1363 run_command "git checkout $head" or 1364 die "Failed to checkout $head"; 1365 } 1366 1367 run_command "git bisect start$start_files" or 1368 dodie "could not start bisect"; 1369 1370 run_command "git bisect good $good" or 1371 dodie "could not set bisect good to $good"; 1372 1373 run_git_bisect "git bisect bad $bad" or 1374 dodie "could not set bisect bad to $bad"; 1375 1376 if (defined($replay)) { 1377 run_command "git bisect replay $replay" or 1378 dodie "failed to run replay"; 1379 } 1380 1381 if (defined($start)) { 1382 run_command "git checkout $start" or 1383 dodie "failed to checkout $start"; 1384 } 1385 1386 my $test; 1387 do { 1388 $result = run_bisect $type; 1389 $test = run_git_bisect "git bisect $result"; 1390 } while ($test); 1391 1392 run_command "git bisect log" or 1393 dodie "could not capture git bisect log"; 1394 1395 run_command "git bisect reset" or 1396 dodie "could not reset git bisect"; 1397 1398 doprint "Bad commit was [$bisect_bad]\n"; 1399 1400 success $i; 1401} 1402 1403my %config_ignore; 1404my %config_set; 1405 1406my %config_list; 1407my %null_config; 1408 1409my %dependency; 1410 1411sub process_config_ignore { 1412 my ($config) = @_; 1413 1414 open (IN, $config) 1415 or dodie "Failed to read $config"; 1416 1417 while (<IN>) { 1418 if (/^(.*?(CONFIG\S*)(=.*| is not set))/) { 1419 $config_ignore{$2} = $1; 1420 } 1421 } 1422 1423 close(IN); 1424} 1425 1426sub read_current_config { 1427 my ($config_ref) = @_; 1428 1429 %{$config_ref} = (); 1430 undef %{$config_ref}; 1431 1432 my @key = keys %{$config_ref}; 1433 if ($#key >= 0) { 1434 print "did not delete!\n"; 1435 exit; 1436 } 1437 open (IN, "$output_config"); 1438 1439 while (<IN>) { 1440 if (/^(CONFIG\S+)=(.*)/) { 1441 ${$config_ref}{$1} = $2; 1442 } 1443 } 1444 close(IN); 1445} 1446 1447sub get_dependencies { 1448 my ($config) = @_; 1449 1450 my $arr = $dependency{$config}; 1451 if (!defined($arr)) { 1452 return (); 1453 } 1454 1455 my @deps = @{$arr}; 1456 1457 foreach my $dep (@{$arr}) { 1458 print "ADD DEP $dep\n"; 1459 @deps = (@deps, get_dependencies $dep); 1460 } 1461 1462 return @deps; 1463} 1464 1465sub create_config { 1466 my @configs = @_; 1467 1468 open(OUT, ">$output_config") or dodie "Can not write to $output_config"; 1469 1470 foreach my $config (@configs) { 1471 print OUT "$config_set{$config}\n"; 1472 my @deps = get_dependencies $config; 1473 foreach my $dep (@deps) { 1474 print OUT "$config_set{$dep}\n"; 1475 } 1476 } 1477 1478 foreach my $config (keys %config_ignore) { 1479 print OUT "$config_ignore{$config}\n"; 1480 } 1481 close(OUT); 1482 1483# exit; 1484 make_oldconfig ""; 1485} 1486 1487sub compare_configs { 1488 my (%a, %b) = @_; 1489 1490 foreach my $item (keys %a) { 1491 if (!defined($b{$item})) { 1492 print "diff $item\n"; 1493 return 1; 1494 } 1495 delete $b{$item}; 1496 } 1497 1498 my @keys = keys %b; 1499 if ($#keys) { 1500 print "diff2 $keys[0]\n"; 1501 } 1502 return -1 if ($#keys >= 0); 1503 1504 return 0; 1505} 1506 1507sub run_config_bisect_test { 1508 my ($type) = @_; 1509 1510 return run_bisect_test $type, "oldconfig"; 1511} 1512 1513sub process_passed { 1514 my (%configs) = @_; 1515 1516 doprint "These configs had no failure: (Enabling them for further compiles)\n"; 1517 # Passed! All these configs are part of a good compile. 1518 # Add them to the min options. 1519 foreach my $config (keys %configs) { 1520 if (defined($config_list{$config})) { 1521 doprint " removing $config\n"; 1522 $config_ignore{$config} = $config_list{$config}; 1523 delete $config_list{$config}; 1524 } 1525 } 1526 doprint "config copied to $outputdir/config_good\n"; 1527 run_command "cp -f $output_config $outputdir/config_good"; 1528} 1529 1530sub process_failed { 1531 my ($config) = @_; 1532 1533 doprint "\n\n***************************************\n"; 1534 doprint "Found bad config: $config\n"; 1535 doprint "***************************************\n\n"; 1536} 1537 1538sub run_config_bisect { 1539 1540 my @start_list = keys %config_list; 1541 1542 if ($#start_list < 0) { 1543 doprint "No more configs to test!!!\n"; 1544 return -1; 1545 } 1546 1547 doprint "***** RUN TEST ***\n"; 1548 my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"}; 1549 my $ret; 1550 my %current_config; 1551 1552 my $count = $#start_list + 1; 1553 doprint " $count configs to test\n"; 1554 1555 my $half = int($#start_list / 2); 1556 1557 do { 1558 my @tophalf = @start_list[0 .. $half]; 1559 1560 create_config @tophalf; 1561 read_current_config \%current_config; 1562 1563 $count = $#tophalf + 1; 1564 doprint "Testing $count configs\n"; 1565 my $found = 0; 1566 # make sure we test something 1567 foreach my $config (@tophalf) { 1568 if (defined($current_config{$config})) { 1569 logit " $config\n"; 1570 $found = 1; 1571 } 1572 } 1573 if (!$found) { 1574 # try the other half 1575 doprint "Top half produced no set configs, trying bottom half\n"; 1576 @tophalf = @start_list[$half .. $#start_list]; 1577 create_config @tophalf; 1578 read_current_config \%current_config; 1579 foreach my $config (@tophalf) { 1580 if (defined($current_config{$config})) { 1581 logit " $config\n"; 1582 $found = 1; 1583 } 1584 } 1585 if (!$found) { 1586 doprint "Failed: Can't make new config with current configs\n"; 1587 foreach my $config (@start_list) { 1588 doprint " CONFIG: $config\n"; 1589 } 1590 return -1; 1591 } 1592 $count = $#tophalf + 1; 1593 doprint "Testing $count configs\n"; 1594 } 1595 1596 $ret = run_config_bisect_test $type; 1597 if ($bisect_manual) { 1598 $ret = answer_bisect; 1599 } 1600 if ($ret) { 1601 process_passed %current_config; 1602 return 0; 1603 } 1604 1605 doprint "This config had a failure.\n"; 1606 doprint "Removing these configs that were not set in this config:\n"; 1607 doprint "config copied to $outputdir/config_bad\n"; 1608 run_command "cp -f $output_config $outputdir/config_bad"; 1609 1610 # A config exists in this group that was bad. 1611 foreach my $config (keys %config_list) { 1612 if (!defined($current_config{$config})) { 1613 doprint " removing $config\n"; 1614 delete $config_list{$config}; 1615 } 1616 } 1617 1618 @start_list = @tophalf; 1619 1620 if ($#start_list == 0) { 1621 process_failed $start_list[0]; 1622 return 1; 1623 } 1624 1625 # remove half the configs we are looking at and see if 1626 # they are good. 1627 $half = int($#start_list / 2); 1628 } while ($half > 0); 1629 1630 # we found a single config, try it again unless we are running manually 1631 1632 if ($bisect_manual) { 1633 process_failed $start_list[0]; 1634 return 1; 1635 } 1636 1637 my @tophalf = @start_list[0 .. 0]; 1638 1639 $ret = run_config_bisect_test $type; 1640 if ($ret) { 1641 process_passed %current_config; 1642 return 0; 1643 } 1644 1645 process_failed $start_list[0]; 1646 return 1; 1647} 1648 1649sub config_bisect { 1650 my ($i) = @_; 1651 1652 my $start_config = $opt{"CONFIG_BISECT[$i]"}; 1653 1654 my $tmpconfig = "$tmpdir/use_config"; 1655 1656 # Make the file with the bad config and the min config 1657 if (defined($minconfig)) { 1658 # read the min config for things to ignore 1659 run_command "cp $minconfig $tmpconfig" or 1660 dodie "failed to copy $minconfig to $tmpconfig"; 1661 } else { 1662 unlink $tmpconfig; 1663 } 1664 1665 # Add other configs 1666 if (defined($addconfig)) { 1667 run_command "cat $addconfig >> $tmpconfig" or 1668 dodie "failed to append $addconfig"; 1669 } 1670 1671 my $defconfig = ""; 1672 if (-f $tmpconfig) { 1673 $defconfig = "KCONFIG_ALLCONFIG=$tmpconfig"; 1674 process_config_ignore $tmpconfig; 1675 } 1676 1677 # now process the start config 1678 run_command "cp $start_config $output_config" or 1679 dodie "failed to copy $start_config to $output_config"; 1680 1681 # read directly what we want to check 1682 my %config_check; 1683 open (IN, $output_config) 1684 or dodie "faied to open $output_config"; 1685 1686 while (<IN>) { 1687 if (/^((CONFIG\S*)=.*)/) { 1688 $config_check{$2} = $1; 1689 } 1690 } 1691 close(IN); 1692 1693 # Now run oldconfig with the minconfig (and addconfigs) 1694 make_oldconfig $defconfig; 1695 1696 # check to see what we lost (or gained) 1697 open (IN, $output_config) 1698 or dodie "Failed to read $start_config"; 1699 1700 my %removed_configs; 1701 my %added_configs; 1702 1703 while (<IN>) { 1704 if (/^((CONFIG\S*)=.*)/) { 1705 # save off all options 1706 $config_set{$2} = $1; 1707 if (defined($config_check{$2})) { 1708 if (defined($config_ignore{$2})) { 1709 $removed_configs{$2} = $1; 1710 } else { 1711 $config_list{$2} = $1; 1712 } 1713 } elsif (!defined($config_ignore{$2})) { 1714 $added_configs{$2} = $1; 1715 $config_list{$2} = $1; 1716 } 1717 } 1718 } 1719 close(IN); 1720 1721 my @confs = keys %removed_configs; 1722 if ($#confs >= 0) { 1723 doprint "Configs overridden by default configs and removed from check:\n"; 1724 foreach my $config (@confs) { 1725 doprint " $config\n"; 1726 } 1727 } 1728 @confs = keys %added_configs; 1729 if ($#confs >= 0) { 1730 doprint "Configs appearing in make oldconfig and added:\n"; 1731 foreach my $config (@confs) { 1732 doprint " $config\n"; 1733 } 1734 } 1735 1736 my %config_test; 1737 my $once = 0; 1738 1739 # Sometimes kconfig does weird things. We must make sure 1740 # that the config we autocreate has everything we need 1741 # to test, otherwise we may miss testing configs, or 1742 # may not be able to create a new config. 1743 # Here we create a config with everything set. 1744 create_config (keys %config_list); 1745 read_current_config \%config_test; 1746 foreach my $config (keys %config_list) { 1747 if (!defined($config_test{$config})) { 1748 if (!$once) { 1749 $once = 1; 1750 doprint "Configs not produced by kconfig (will not be checked):\n"; 1751 } 1752 doprint " $config\n"; 1753 delete $config_list{$config}; 1754 } 1755 } 1756 my $ret; 1757 do { 1758 $ret = run_config_bisect; 1759 } while (!$ret); 1760 1761 return $ret if ($ret < 0); 1762 1763 success $i; 1764} 1765 1766sub patchcheck { 1767 my ($i) = @_; 1768 1769 die "PATCHCHECK_START[$i] not defined\n" 1770 if (!defined($opt{"PATCHCHECK_START[$i]"})); 1771 die "PATCHCHECK_TYPE[$i] not defined\n" 1772 if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 1773 1774 my $start = $opt{"PATCHCHECK_START[$i]"}; 1775 1776 my $end = "HEAD"; 1777 if (defined($opt{"PATCHCHECK_END[$i]"})) { 1778 $end = $opt{"PATCHCHECK_END[$i]"}; 1779 } 1780 1781 # Get the true sha1's since we can use things like HEAD~3 1782 $start = get_sha1($start); 1783 $end = get_sha1($end); 1784 1785 my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 1786 1787 # Can't have a test without having a test to run 1788 if ($type eq "test" && !defined($run_test)) { 1789 $type = "boot"; 1790 } 1791 1792 open (IN, "git log --pretty=oneline $end|") or 1793 dodie "could not get git list"; 1794 1795 my @list; 1796 1797 while (<IN>) { 1798 chomp; 1799 $list[$#list+1] = $_; 1800 last if (/^$start/); 1801 } 1802 close(IN); 1803 1804 if ($list[$#list] !~ /^$start/) { 1805 fail "SHA1 $start not found"; 1806 } 1807 1808 # go backwards in the list 1809 @list = reverse @list; 1810 1811 my $save_clean = $noclean; 1812 1813 $in_patchcheck = 1; 1814 foreach my $item (@list) { 1815 my $sha1 = $item; 1816 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 1817 1818 doprint "\nProcessing commit $item\n\n"; 1819 1820 run_command "git checkout $sha1" or 1821 die "Failed to checkout $sha1"; 1822 1823 # only clean on the first and last patch 1824 if ($item eq $list[0] || 1825 $item eq $list[$#list]) { 1826 $noclean = $save_clean; 1827 } else { 1828 $noclean = 1; 1829 } 1830 1831 if (defined($minconfig)) { 1832 build "useconfig:$minconfig" or return 0; 1833 } else { 1834 # ?? no config to use? 1835 build "oldconfig" or return 0; 1836 } 1837 1838 check_buildlog $sha1 or return 0; 1839 1840 next if ($type eq "build"); 1841 1842 get_grub_index; 1843 get_version; 1844 install; 1845 1846 my $failed = 0; 1847 1848 start_monitor; 1849 monitor or $failed = 1; 1850 1851 if (!$failed && $type ne "boot"){ 1852 do_run_test or $failed = 1; 1853 } 1854 end_monitor; 1855 return 0 if ($failed); 1856 1857 } 1858 $in_patchcheck = 0; 1859 success $i; 1860 1861 return 1; 1862} 1863 1864$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 1865 1866if ($#ARGV == 0) { 1867 $ktest_config = $ARGV[0]; 1868 if (! -f $ktest_config) { 1869 print "$ktest_config does not exist.\n"; 1870 my $ans; 1871 for (;;) { 1872 print "Create it? [Y/n] "; 1873 $ans = <STDIN>; 1874 chomp $ans; 1875 if ($ans =~ /^\s*$/) { 1876 $ans = "y"; 1877 } 1878 last if ($ans =~ /^y$/i || $ans =~ /^n$/i); 1879 print "Please answer either 'y' or 'n'.\n"; 1880 } 1881 if ($ans !~ /^y$/i) { 1882 exit 0; 1883 } 1884 } 1885} else { 1886 $ktest_config = "ktest.conf"; 1887} 1888 1889if (! -f $ktest_config) { 1890 open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 1891 print OUT << "EOF" 1892# Generated by ktest.pl 1893# 1894# Define each test with TEST_START 1895# The config options below it will override the defaults 1896TEST_START 1897 1898DEFAULTS 1899EOF 1900; 1901 close(OUT); 1902} 1903read_config $ktest_config; 1904 1905# Append any configs entered in manually to the config file. 1906my @new_configs = keys %entered_configs; 1907if ($#new_configs >= 0) { 1908 print "\nAppending entered in configs to $ktest_config\n"; 1909 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 1910 foreach my $config (@new_configs) { 1911 print OUT "$config = $entered_configs{$config}\n"; 1912 $opt{$config} = $entered_configs{$config}; 1913 } 1914} 1915 1916if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 1917 unlink $opt{"LOG_FILE"}; 1918} 1919 1920doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 1921 1922for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 1923 1924 if (!$i) { 1925 doprint "DEFAULT OPTIONS:\n"; 1926 } else { 1927 doprint "\nTEST $i OPTIONS"; 1928 if (defined($repeat_tests{$i})) { 1929 $repeat = $repeat_tests{$i}; 1930 doprint " ITERATE $repeat"; 1931 } 1932 doprint "\n"; 1933 } 1934 1935 foreach my $option (sort keys %opt) { 1936 1937 if ($option =~ /\[(\d+)\]$/) { 1938 next if ($i != $1); 1939 } else { 1940 next if ($i); 1941 } 1942 1943 doprint "$option = $opt{$option}\n"; 1944 } 1945} 1946 1947sub set_test_option { 1948 my ($name, $i) = @_; 1949 1950 my $option = "$name\[$i\]"; 1951 1952 if (defined($opt{$option})) { 1953 return $opt{$option}; 1954 } 1955 1956 foreach my $test (keys %repeat_tests) { 1957 if ($i >= $test && 1958 $i < $test + $repeat_tests{$test}) { 1959 $option = "$name\[$test\]"; 1960 if (defined($opt{$option})) { 1961 return $opt{$option}; 1962 } 1963 } 1964 } 1965 1966 if (defined($opt{$name})) { 1967 return $opt{$name}; 1968 } 1969 1970 return undef; 1971} 1972 1973# First we need to do is the builds 1974for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 1975 1976 $iteration = $i; 1977 1978 my $makecmd = set_test_option("MAKE_CMD", $i); 1979 1980 $machine = set_test_option("MACHINE", $i); 1981 $ssh_user = set_test_option("SSH_USER", $i); 1982 $tmpdir = set_test_option("TMP_DIR", $i); 1983 $outputdir = set_test_option("OUTPUT_DIR", $i); 1984 $builddir = set_test_option("BUILD_DIR", $i); 1985 $test_type = set_test_option("TEST_TYPE", $i); 1986 $build_type = set_test_option("BUILD_TYPE", $i); 1987 $build_options = set_test_option("BUILD_OPTIONS", $i); 1988 $power_cycle = set_test_option("POWER_CYCLE", $i); 1989 $reboot = set_test_option("REBOOT", $i); 1990 $noclean = set_test_option("BUILD_NOCLEAN", $i); 1991 $minconfig = set_test_option("MIN_CONFIG", $i); 1992 $run_test = set_test_option("TEST", $i); 1993 $addconfig = set_test_option("ADD_CONFIG", $i); 1994 $reboot_type = set_test_option("REBOOT_TYPE", $i); 1995 $grub_menu = set_test_option("GRUB_MENU", $i); 1996 $post_install = set_test_option("POST_INSTALL", $i); 1997 $reboot_script = set_test_option("REBOOT_SCRIPT", $i); 1998 $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); 1999 $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); 2000 $die_on_failure = set_test_option("DIE_ON_FAILURE", $i); 2001 $power_off = set_test_option("POWER_OFF", $i); 2002 $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i); 2003 $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i); 2004 $sleep_time = set_test_option("SLEEP_TIME", $i); 2005 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 2006 $bisect_manual = set_test_option("BISECT_MANUAL", $i); 2007 $bisect_skip = set_test_option("BISECT_SKIP", $i); 2008 $store_failures = set_test_option("STORE_FAILURES", $i); 2009 $timeout = set_test_option("TIMEOUT", $i); 2010 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 2011 $console = set_test_option("CONSOLE", $i); 2012 $success_line = set_test_option("SUCCESS_LINE", $i); 2013 $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); 2014 $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); 2015 $stop_test_after = set_test_option("STOP_TEST_AFTER", $i); 2016 $build_target = set_test_option("BUILD_TARGET", $i); 2017 $ssh_exec = set_test_option("SSH_EXEC", $i); 2018 $scp_to_target = set_test_option("SCP_TO_TARGET", $i); 2019 $target_image = set_test_option("TARGET_IMAGE", $i); 2020 $localversion = set_test_option("LOCALVERSION", $i); 2021 2022 chdir $builddir || die "can't change directory to $builddir"; 2023 2024 if (!-d $tmpdir) { 2025 mkpath($tmpdir) or 2026 die "can't create $tmpdir"; 2027 } 2028 2029 $ENV{"SSH_USER"} = $ssh_user; 2030 $ENV{"MACHINE"} = $machine; 2031 2032 $target = "$ssh_user\@$machine"; 2033 2034 $buildlog = "$tmpdir/buildlog-$machine"; 2035 $dmesg = "$tmpdir/dmesg-$machine"; 2036 $make = "$makecmd O=$outputdir"; 2037 $output_config = "$outputdir/.config"; 2038 2039 if ($reboot_type eq "grub") { 2040 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 2041 } elsif (!defined($reboot_script)) { 2042 dodie "REBOOT_SCRIPT not defined" 2043 } 2044 2045 my $run_type = $build_type; 2046 if ($test_type eq "patchcheck") { 2047 $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 2048 } elsif ($test_type eq "bisect") { 2049 $run_type = $opt{"BISECT_TYPE[$i]"}; 2050 } elsif ($test_type eq "config_bisect") { 2051 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; 2052 } 2053 2054 # mistake in config file? 2055 if (!defined($run_type)) { 2056 $run_type = "ERROR"; 2057 } 2058 2059 doprint "\n\n"; 2060 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n"; 2061 2062 unlink $dmesg; 2063 unlink $buildlog; 2064 2065 if (!defined($minconfig)) { 2066 $minconfig = $addconfig; 2067 2068 } elsif (defined($addconfig)) { 2069 run_command "cat $addconfig $minconfig > $tmpdir/add_config" or 2070 dodie "Failed to create temp config"; 2071 $minconfig = "$tmpdir/add_config"; 2072 } 2073 2074 my $checkout = $opt{"CHECKOUT[$i]"}; 2075 if (defined($checkout)) { 2076 run_command "git checkout $checkout" or 2077 die "failed to checkout $checkout"; 2078 } 2079 2080 if ($test_type eq "bisect") { 2081 bisect $i; 2082 next; 2083 } elsif ($test_type eq "config_bisect") { 2084 config_bisect $i; 2085 next; 2086 } elsif ($test_type eq "patchcheck") { 2087 patchcheck $i; 2088 next; 2089 } 2090 2091 if ($build_type ne "nobuild") { 2092 build $build_type or next; 2093 } 2094 2095 if ($test_type ne "build") { 2096 get_grub_index; 2097 get_version; 2098 install; 2099 2100 my $failed = 0; 2101 start_monitor; 2102 monitor or $failed = 1;; 2103 2104 if (!$failed && $test_type ne "boot" && defined($run_test)) { 2105 do_run_test or $failed = 1; 2106 } 2107 end_monitor; 2108 next if ($failed); 2109 } 2110 2111 success $i; 2112} 2113 2114if ($opt{"POWEROFF_ON_SUCCESS"}) { 2115 halt; 2116} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { 2117 reboot; 2118} 2119 2120doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 2121 2122exit 0; 2123