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; 13use FindBin; 14 15my $VERSION = "0.2"; 16 17$| = 1; 18 19my %opt; 20my %repeat_tests; 21my %repeats; 22my %evals; 23 24#default opts 25my %default = ( 26 "MAILER" => "sendmail", # default mailer 27 "EMAIL_ON_ERROR" => 1, 28 "EMAIL_WHEN_FINISHED" => 1, 29 "EMAIL_WHEN_CANCELED" => 0, 30 "EMAIL_WHEN_STARTED" => 0, 31 "NUM_TESTS" => 1, 32 "TEST_TYPE" => "build", 33 "BUILD_TYPE" => "randconfig", 34 "MAKE_CMD" => "make", 35 "CLOSE_CONSOLE_SIGNAL" => "INT", 36 "TIMEOUT" => 120, 37 "TMP_DIR" => "/tmp/ktest/\${MACHINE}", 38 "SLEEP_TIME" => 60, # sleep time between tests 39 "BUILD_NOCLEAN" => 0, 40 "REBOOT_ON_ERROR" => 0, 41 "POWEROFF_ON_ERROR" => 0, 42 "REBOOT_ON_SUCCESS" => 1, 43 "POWEROFF_ON_SUCCESS" => 0, 44 "BUILD_OPTIONS" => "", 45 "BISECT_SLEEP_TIME" => 60, # sleep time between bisects 46 "PATCHCHECK_SLEEP_TIME" => 60, # sleep time between patch checks 47 "CLEAR_LOG" => 0, 48 "BISECT_MANUAL" => 0, 49 "BISECT_SKIP" => 1, 50 "BISECT_TRIES" => 1, 51 "MIN_CONFIG_TYPE" => "boot", 52 "SUCCESS_LINE" => "login:", 53 "DETECT_TRIPLE_FAULT" => 1, 54 "NO_INSTALL" => 0, 55 "BOOTED_TIMEOUT" => 1, 56 "DIE_ON_FAILURE" => 1, 57 "SSH_EXEC" => "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND", 58 "SCP_TO_TARGET" => "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE", 59 "SCP_TO_TARGET_INSTALL" => "\${SCP_TO_TARGET}", 60 "REBOOT" => "ssh \$SSH_USER\@\$MACHINE reboot", 61 "REBOOT_RETURN_CODE" => 255, 62 "STOP_AFTER_SUCCESS" => 10, 63 "STOP_AFTER_FAILURE" => 60, 64 "STOP_TEST_AFTER" => 600, 65 "MAX_MONITOR_WAIT" => 1800, 66 "GRUB_REBOOT" => "grub2-reboot", 67 "SYSLINUX" => "extlinux", 68 "SYSLINUX_PATH" => "/boot/extlinux", 69 "CONNECT_TIMEOUT" => 25, 70 71# required, and we will ask users if they don't have them but we keep the default 72# value something that is common. 73 "REBOOT_TYPE" => "grub", 74 "LOCALVERSION" => "-test", 75 "SSH_USER" => "root", 76 "BUILD_TARGET" => "arch/x86/boot/bzImage", 77 "TARGET_IMAGE" => "/boot/vmlinuz-test", 78 79 "LOG_FILE" => undef, 80 "IGNORE_UNUSED" => 0, 81); 82 83my $ktest_config = "ktest.conf"; 84my $version; 85my $have_version = 0; 86my $machine; 87my $last_machine; 88my $ssh_user; 89my $tmpdir; 90my $builddir; 91my $outputdir; 92my $output_config; 93my $test_type; 94my $build_type; 95my $build_options; 96my $final_post_ktest; 97my $pre_ktest; 98my $post_ktest; 99my $pre_test; 100my $post_test; 101my $pre_build; 102my $post_build; 103my $pre_build_die; 104my $post_build_die; 105my $reboot_type; 106my $reboot_script; 107my $power_cycle; 108my $reboot; 109my $reboot_return_code; 110my $reboot_on_error; 111my $switch_to_good; 112my $switch_to_test; 113my $poweroff_on_error; 114my $reboot_on_success; 115my $die_on_failure; 116my $powercycle_after_reboot; 117my $poweroff_after_halt; 118my $max_monitor_wait; 119my $ssh_exec; 120my $scp_to_target; 121my $scp_to_target_install; 122my $power_off; 123my $grub_menu; 124my $last_grub_menu; 125my $grub_file; 126my $grub_number; 127my $grub_reboot; 128my $syslinux; 129my $syslinux_path; 130my $syslinux_label; 131my $target; 132my $make; 133my $pre_install; 134my $post_install; 135my $no_install; 136my $noclean; 137my $minconfig; 138my $start_minconfig; 139my $start_minconfig_defined; 140my $output_minconfig; 141my $minconfig_type; 142my $use_output_minconfig; 143my $warnings_file; 144my $ignore_config; 145my $ignore_errors; 146my $addconfig; 147my $in_bisect = 0; 148my $bisect_bad_commit = ""; 149my $reverse_bisect; 150my $bisect_manual; 151my $bisect_skip; 152my $bisect_tries; 153my $config_bisect_good; 154my $bisect_ret_good; 155my $bisect_ret_bad; 156my $bisect_ret_skip; 157my $bisect_ret_abort; 158my $bisect_ret_default; 159my $in_patchcheck = 0; 160my $run_test; 161my $buildlog; 162my $testlog; 163my $dmesg; 164my $monitor_fp; 165my $monitor_pid; 166my $monitor_cnt = 0; 167my $sleep_time; 168my $bisect_sleep_time; 169my $patchcheck_sleep_time; 170my $ignore_warnings; 171my $store_failures; 172my $store_successes; 173my $test_name; 174my $timeout; 175my $connect_timeout; 176my $config_bisect_exec; 177my $booted_timeout; 178my $detect_triplefault; 179my $console; 180my $close_console_signal; 181my $reboot_success_line; 182my $success_line; 183my $stop_after_success; 184my $stop_after_failure; 185my $stop_test_after; 186my $build_target; 187my $target_image; 188my $checkout; 189my $localversion; 190my $iteration = 0; 191my $successes = 0; 192my $stty_orig; 193my $run_command_status = 0; 194 195my $bisect_good; 196my $bisect_bad; 197my $bisect_type; 198my $bisect_start; 199my $bisect_replay; 200my $bisect_files; 201my $bisect_reverse; 202my $bisect_check; 203 204my $config_bisect; 205my $config_bisect_type; 206my $config_bisect_check; 207 208my $patchcheck_type; 209my $patchcheck_start; 210my $patchcheck_cherry; 211my $patchcheck_end; 212 213my $build_time; 214my $install_time; 215my $reboot_time; 216my $test_time; 217 218my $pwd; 219my $dirname = $FindBin::Bin; 220 221my $mailto; 222my $mailer; 223my $mail_path; 224my $mail_command; 225my $email_on_error; 226my $email_when_finished; 227my $email_when_started; 228my $email_when_canceled; 229 230my $script_start_time = localtime(); 231 232# set when a test is something other that just building or install 233# which would require more options. 234my $buildonly = 1; 235 236# tell build not to worry about warnings, even when WARNINGS_FILE is set 237my $warnings_ok = 0; 238 239# set when creating a new config 240my $newconfig = 0; 241 242my %entered_configs; 243my %config_help; 244my %variable; 245 246# force_config is the list of configs that we force enabled (or disabled) 247# in a .config file. The MIN_CONFIG and ADD_CONFIG configs. 248my %force_config; 249 250# do not force reboots on config problems 251my $no_reboot = 1; 252 253# reboot on success 254my $reboot_success = 0; 255 256my %option_map = ( 257 "MAILTO" => \$mailto, 258 "MAILER" => \$mailer, 259 "MAIL_PATH" => \$mail_path, 260 "MAIL_COMMAND" => \$mail_command, 261 "EMAIL_ON_ERROR" => \$email_on_error, 262 "EMAIL_WHEN_FINISHED" => \$email_when_finished, 263 "EMAIL_WHEN_STARTED" => \$email_when_started, 264 "EMAIL_WHEN_CANCELED" => \$email_when_canceled, 265 "MACHINE" => \$machine, 266 "SSH_USER" => \$ssh_user, 267 "TMP_DIR" => \$tmpdir, 268 "OUTPUT_DIR" => \$outputdir, 269 "BUILD_DIR" => \$builddir, 270 "TEST_TYPE" => \$test_type, 271 "PRE_KTEST" => \$pre_ktest, 272 "POST_KTEST" => \$post_ktest, 273 "PRE_TEST" => \$pre_test, 274 "POST_TEST" => \$post_test, 275 "BUILD_TYPE" => \$build_type, 276 "BUILD_OPTIONS" => \$build_options, 277 "PRE_BUILD" => \$pre_build, 278 "POST_BUILD" => \$post_build, 279 "PRE_BUILD_DIE" => \$pre_build_die, 280 "POST_BUILD_DIE" => \$post_build_die, 281 "POWER_CYCLE" => \$power_cycle, 282 "REBOOT" => \$reboot, 283 "REBOOT_RETURN_CODE" => \$reboot_return_code, 284 "BUILD_NOCLEAN" => \$noclean, 285 "MIN_CONFIG" => \$minconfig, 286 "OUTPUT_MIN_CONFIG" => \$output_minconfig, 287 "START_MIN_CONFIG" => \$start_minconfig, 288 "MIN_CONFIG_TYPE" => \$minconfig_type, 289 "USE_OUTPUT_MIN_CONFIG" => \$use_output_minconfig, 290 "WARNINGS_FILE" => \$warnings_file, 291 "IGNORE_CONFIG" => \$ignore_config, 292 "TEST" => \$run_test, 293 "ADD_CONFIG" => \$addconfig, 294 "REBOOT_TYPE" => \$reboot_type, 295 "GRUB_MENU" => \$grub_menu, 296 "GRUB_FILE" => \$grub_file, 297 "GRUB_REBOOT" => \$grub_reboot, 298 "SYSLINUX" => \$syslinux, 299 "SYSLINUX_PATH" => \$syslinux_path, 300 "SYSLINUX_LABEL" => \$syslinux_label, 301 "PRE_INSTALL" => \$pre_install, 302 "POST_INSTALL" => \$post_install, 303 "NO_INSTALL" => \$no_install, 304 "REBOOT_SCRIPT" => \$reboot_script, 305 "REBOOT_ON_ERROR" => \$reboot_on_error, 306 "SWITCH_TO_GOOD" => \$switch_to_good, 307 "SWITCH_TO_TEST" => \$switch_to_test, 308 "POWEROFF_ON_ERROR" => \$poweroff_on_error, 309 "REBOOT_ON_SUCCESS" => \$reboot_on_success, 310 "DIE_ON_FAILURE" => \$die_on_failure, 311 "POWER_OFF" => \$power_off, 312 "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot, 313 "POWEROFF_AFTER_HALT" => \$poweroff_after_halt, 314 "MAX_MONITOR_WAIT" => \$max_monitor_wait, 315 "SLEEP_TIME" => \$sleep_time, 316 "BISECT_SLEEP_TIME" => \$bisect_sleep_time, 317 "PATCHCHECK_SLEEP_TIME" => \$patchcheck_sleep_time, 318 "IGNORE_WARNINGS" => \$ignore_warnings, 319 "IGNORE_ERRORS" => \$ignore_errors, 320 "BISECT_MANUAL" => \$bisect_manual, 321 "BISECT_SKIP" => \$bisect_skip, 322 "BISECT_TRIES" => \$bisect_tries, 323 "CONFIG_BISECT_GOOD" => \$config_bisect_good, 324 "BISECT_RET_GOOD" => \$bisect_ret_good, 325 "BISECT_RET_BAD" => \$bisect_ret_bad, 326 "BISECT_RET_SKIP" => \$bisect_ret_skip, 327 "BISECT_RET_ABORT" => \$bisect_ret_abort, 328 "BISECT_RET_DEFAULT" => \$bisect_ret_default, 329 "STORE_FAILURES" => \$store_failures, 330 "STORE_SUCCESSES" => \$store_successes, 331 "TEST_NAME" => \$test_name, 332 "TIMEOUT" => \$timeout, 333 "CONNECT_TIMEOUT" => \$connect_timeout, 334 "CONFIG_BISECT_EXEC" => \$config_bisect_exec, 335 "BOOTED_TIMEOUT" => \$booted_timeout, 336 "CONSOLE" => \$console, 337 "CLOSE_CONSOLE_SIGNAL" => \$close_console_signal, 338 "DETECT_TRIPLE_FAULT" => \$detect_triplefault, 339 "SUCCESS_LINE" => \$success_line, 340 "REBOOT_SUCCESS_LINE" => \$reboot_success_line, 341 "STOP_AFTER_SUCCESS" => \$stop_after_success, 342 "STOP_AFTER_FAILURE" => \$stop_after_failure, 343 "STOP_TEST_AFTER" => \$stop_test_after, 344 "BUILD_TARGET" => \$build_target, 345 "SSH_EXEC" => \$ssh_exec, 346 "SCP_TO_TARGET" => \$scp_to_target, 347 "SCP_TO_TARGET_INSTALL" => \$scp_to_target_install, 348 "CHECKOUT" => \$checkout, 349 "TARGET_IMAGE" => \$target_image, 350 "LOCALVERSION" => \$localversion, 351 352 "BISECT_GOOD" => \$bisect_good, 353 "BISECT_BAD" => \$bisect_bad, 354 "BISECT_TYPE" => \$bisect_type, 355 "BISECT_START" => \$bisect_start, 356 "BISECT_REPLAY" => \$bisect_replay, 357 "BISECT_FILES" => \$bisect_files, 358 "BISECT_REVERSE" => \$bisect_reverse, 359 "BISECT_CHECK" => \$bisect_check, 360 361 "CONFIG_BISECT" => \$config_bisect, 362 "CONFIG_BISECT_TYPE" => \$config_bisect_type, 363 "CONFIG_BISECT_CHECK" => \$config_bisect_check, 364 365 "PATCHCHECK_TYPE" => \$patchcheck_type, 366 "PATCHCHECK_START" => \$patchcheck_start, 367 "PATCHCHECK_CHERRY" => \$patchcheck_cherry, 368 "PATCHCHECK_END" => \$patchcheck_end, 369); 370 371# Options may be used by other options, record them. 372my %used_options; 373 374# default variables that can be used 375chomp ($variable{"PWD"} = `pwd`); 376$pwd = $variable{"PWD"}; 377 378$config_help{"MACHINE"} = << "EOF" 379 The machine hostname that you will test. 380 For build only tests, it is still needed to differentiate log files. 381EOF 382 ; 383$config_help{"SSH_USER"} = << "EOF" 384 The box is expected to have ssh on normal bootup, provide the user 385 (most likely root, since you need privileged operations) 386EOF 387 ; 388$config_help{"BUILD_DIR"} = << "EOF" 389 The directory that contains the Linux source code (full path). 390 You can use \${PWD} that will be the path where ktest.pl is run, or use 391 \${THIS_DIR} which is assigned \${PWD} but may be changed later. 392EOF 393 ; 394$config_help{"OUTPUT_DIR"} = << "EOF" 395 The directory that the objects will be built (full path). 396 (can not be same as BUILD_DIR) 397 You can use \${PWD} that will be the path where ktest.pl is run, or use 398 \${THIS_DIR} which is assigned \${PWD} but may be changed later. 399EOF 400 ; 401$config_help{"BUILD_TARGET"} = << "EOF" 402 The location of the compiled file to copy to the target. 403 (relative to OUTPUT_DIR) 404EOF 405 ; 406$config_help{"BUILD_OPTIONS"} = << "EOF" 407 Options to add to \"make\" when building. 408 i.e. -j20 409EOF 410 ; 411$config_help{"TARGET_IMAGE"} = << "EOF" 412 The place to put your image on the test machine. 413EOF 414 ; 415$config_help{"POWER_CYCLE"} = << "EOF" 416 A script or command to reboot the box. 417 418 Here is a digital loggers power switch example 419 POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL' 420 421 Here is an example to reboot a virtual box on the current host 422 with the name "Guest". 423 POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest 424EOF 425 ; 426$config_help{"CONSOLE"} = << "EOF" 427 The script or command that reads the console 428 429 If you use ttywatch server, something like the following would work. 430CONSOLE = nc -d localhost 3001 431 432 For a virtual machine with guest name "Guest". 433CONSOLE = virsh console Guest 434EOF 435 ; 436$config_help{"LOCALVERSION"} = << "EOF" 437 Required version ending to differentiate the test 438 from other linux builds on the system. 439EOF 440 ; 441$config_help{"REBOOT_TYPE"} = << "EOF" 442 Way to reboot the box to the test kernel. 443 Only valid options so far are "grub", "grub2", "syslinux", and "script". 444 445 If you specify grub, it will assume grub version 1 446 and will search in /boot/grub/menu.lst for the title \$GRUB_MENU 447 and select that target to reboot to the kernel. If this is not 448 your setup, then specify "script" and have a command or script 449 specified in REBOOT_SCRIPT to boot to the target. 450 451 The entry in /boot/grub/menu.lst must be entered in manually. 452 The test will not modify that file. 453 454 If you specify grub2, then you also need to specify both \$GRUB_MENU 455 and \$GRUB_FILE. 456 457 If you specify syslinux, then you may use SYSLINUX to define the syslinux 458 command (defaults to extlinux), and SYSLINUX_PATH to specify the path to 459 the syslinux install (defaults to /boot/extlinux). But you have to specify 460 SYSLINUX_LABEL to define the label to boot to for the test kernel. 461EOF 462 ; 463$config_help{"GRUB_MENU"} = << "EOF" 464 The grub title name for the test kernel to boot 465 (Only mandatory if REBOOT_TYPE = grub or grub2) 466 467 Note, ktest.pl will not update the grub menu.lst, you need to 468 manually add an option for the test. ktest.pl will search 469 the grub menu.lst for this option to find what kernel to 470 reboot into. 471 472 For example, if in the /boot/grub/menu.lst the test kernel title has: 473 title Test Kernel 474 kernel vmlinuz-test 475 GRUB_MENU = Test Kernel 476 477 For grub2, a search of \$GRUB_FILE is performed for the lines 478 that begin with "menuentry". It will not detect submenus. The 479 menu must be a non-nested menu. Add the quotes used in the menu 480 to guarantee your selection, as the first menuentry with the content 481 of \$GRUB_MENU that is found will be used. 482EOF 483 ; 484$config_help{"GRUB_FILE"} = << "EOF" 485 If grub2 is used, the full path for the grub.cfg file is placed 486 here. Use something like /boot/grub2/grub.cfg to search. 487EOF 488 ; 489$config_help{"SYSLINUX_LABEL"} = << "EOF" 490 If syslinux is used, the label that boots the target kernel must 491 be specified with SYSLINUX_LABEL. 492EOF 493 ; 494$config_help{"REBOOT_SCRIPT"} = << "EOF" 495 A script to reboot the target into the test kernel 496 (Only mandatory if REBOOT_TYPE = script) 497EOF 498 ; 499 500sub _logit { 501 if (defined($opt{"LOG_FILE"})) { 502 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 503 print OUT @_; 504 close(OUT); 505 } 506} 507 508sub logit { 509 if (defined($opt{"LOG_FILE"})) { 510 _logit @_; 511 } else { 512 print @_; 513 } 514} 515 516sub doprint { 517 print @_; 518 _logit @_; 519} 520 521sub read_prompt { 522 my ($cancel, $prompt) = @_; 523 524 my $ans; 525 526 for (;;) { 527 if ($cancel) { 528 print "$prompt [y/n/C] "; 529 } else { 530 print "$prompt [Y/n] "; 531 } 532 $ans = <STDIN>; 533 chomp $ans; 534 if ($ans =~ /^\s*$/) { 535 if ($cancel) { 536 $ans = "c"; 537 } else { 538 $ans = "y"; 539 } 540 } 541 last if ($ans =~ /^y$/i || $ans =~ /^n$/i); 542 if ($cancel) { 543 last if ($ans =~ /^c$/i); 544 print "Please answer either 'y', 'n' or 'c'.\n"; 545 } else { 546 print "Please answer either 'y' or 'n'.\n"; 547 } 548 } 549 if ($ans =~ /^c/i) { 550 exit; 551 } 552 if ($ans !~ /^y$/i) { 553 return 0; 554 } 555 return 1; 556} 557 558sub read_yn { 559 my ($prompt) = @_; 560 561 return read_prompt 0, $prompt; 562} 563 564sub read_ync { 565 my ($prompt) = @_; 566 567 return read_prompt 1, $prompt; 568} 569 570sub get_mandatory_config { 571 my ($config) = @_; 572 my $ans; 573 574 return if (defined($opt{$config})); 575 576 if (defined($config_help{$config})) { 577 print "\n"; 578 print $config_help{$config}; 579 } 580 581 for (;;) { 582 print "$config = "; 583 if (defined($default{$config}) && length($default{$config})) { 584 print "\[$default{$config}\] "; 585 } 586 $ans = <STDIN>; 587 $ans =~ s/^\s*(.*\S)\s*$/$1/; 588 if ($ans =~ /^\s*$/) { 589 if ($default{$config}) { 590 $ans = $default{$config}; 591 } else { 592 print "Your answer can not be blank\n"; 593 next; 594 } 595 } 596 $entered_configs{$config} = ${ans}; 597 last; 598 } 599} 600 601sub show_time { 602 my ($time) = @_; 603 604 my $hours = 0; 605 my $minutes = 0; 606 607 if ($time > 3600) { 608 $hours = int($time / 3600); 609 $time -= $hours * 3600; 610 } 611 if ($time > 60) { 612 $minutes = int($time / 60); 613 $time -= $minutes * 60; 614 } 615 616 if ($hours > 0) { 617 doprint "$hours hour"; 618 doprint "s" if ($hours > 1); 619 doprint " "; 620 } 621 622 if ($minutes > 0) { 623 doprint "$minutes minute"; 624 doprint "s" if ($minutes > 1); 625 doprint " "; 626 } 627 628 doprint "$time second"; 629 doprint "s" if ($time != 1); 630} 631 632sub print_times { 633 doprint "\n"; 634 if ($build_time) { 635 doprint "Build time: "; 636 show_time($build_time); 637 doprint "\n"; 638 } 639 if ($install_time) { 640 doprint "Install time: "; 641 show_time($install_time); 642 doprint "\n"; 643 } 644 if ($reboot_time) { 645 doprint "Reboot time: "; 646 show_time($reboot_time); 647 doprint "\n"; 648 } 649 if ($test_time) { 650 doprint "Test time: "; 651 show_time($test_time); 652 doprint "\n"; 653 } 654 # reset for iterations like bisect 655 $build_time = 0; 656 $install_time = 0; 657 $reboot_time = 0; 658 $test_time = 0; 659} 660 661sub get_mandatory_configs { 662 get_mandatory_config("MACHINE"); 663 get_mandatory_config("BUILD_DIR"); 664 get_mandatory_config("OUTPUT_DIR"); 665 666 if ($newconfig) { 667 get_mandatory_config("BUILD_OPTIONS"); 668 } 669 670 # options required for other than just building a kernel 671 if (!$buildonly) { 672 get_mandatory_config("POWER_CYCLE"); 673 get_mandatory_config("CONSOLE"); 674 } 675 676 # options required for install and more 677 if ($buildonly != 1) { 678 get_mandatory_config("SSH_USER"); 679 get_mandatory_config("BUILD_TARGET"); 680 get_mandatory_config("TARGET_IMAGE"); 681 } 682 683 get_mandatory_config("LOCALVERSION"); 684 685 return if ($buildonly); 686 687 my $rtype = $opt{"REBOOT_TYPE"}; 688 689 if (!defined($rtype)) { 690 if (!defined($opt{"GRUB_MENU"})) { 691 get_mandatory_config("REBOOT_TYPE"); 692 $rtype = $entered_configs{"REBOOT_TYPE"}; 693 } else { 694 $rtype = "grub"; 695 } 696 } 697 698 if ($rtype eq "grub") { 699 get_mandatory_config("GRUB_MENU"); 700 } 701 702 if ($rtype eq "grub2") { 703 get_mandatory_config("GRUB_MENU"); 704 get_mandatory_config("GRUB_FILE"); 705 } 706 707 if ($rtype eq "syslinux") { 708 get_mandatory_config("SYSLINUX_LABEL"); 709 } 710} 711 712sub process_variables { 713 my ($value, $remove_undef) = @_; 714 my $retval = ""; 715 716 # We want to check for '\', and it is just easier 717 # to check the previous characet of '$' and not need 718 # to worry if '$' is the first character. By adding 719 # a space to $value, we can just check [^\\]\$ and 720 # it will still work. 721 $value = " $value"; 722 723 while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 724 my $begin = $1; 725 my $var = $2; 726 my $end = $3; 727 # append beginning of value to retval 728 $retval = "$retval$begin"; 729 if (defined($variable{$var})) { 730 $retval = "$retval$variable{$var}"; 731 } elsif (defined($remove_undef) && $remove_undef) { 732 # for if statements, any variable that is not defined, 733 # we simple convert to 0 734 $retval = "${retval}0"; 735 } else { 736 # put back the origin piece. 737 $retval = "$retval\$\{$var\}"; 738 # This could be an option that is used later, save 739 # it so we don't warn if this option is not one of 740 # ktests options. 741 $used_options{$var} = 1; 742 } 743 $value = $end; 744 } 745 $retval = "$retval$value"; 746 747 # remove the space added in the beginning 748 $retval =~ s/ //; 749 750 return "$retval" 751} 752 753sub set_value { 754 my ($lvalue, $rvalue, $override, $overrides, $name) = @_; 755 756 my $prvalue = process_variables($rvalue); 757 758 if ($lvalue =~ /^(TEST|BISECT|CONFIG_BISECT)_TYPE(\[.*\])?$/ && 759 $prvalue !~ /^(config_|)bisect$/ && 760 $prvalue !~ /^build$/ && 761 $buildonly) { 762 763 # Note if a test is something other than build, then we 764 # will need other mandatory options. 765 if ($prvalue ne "install") { 766 $buildonly = 0; 767 } else { 768 # install still limits some mandatory options. 769 $buildonly = 2; 770 } 771 } 772 773 if (defined($opt{$lvalue})) { 774 if (!$override || defined(${$overrides}{$lvalue})) { 775 my $extra = ""; 776 if ($override) { 777 $extra = "In the same override section!\n"; 778 } 779 die "$name: $.: Option $lvalue defined more than once!\n$extra"; 780 } 781 ${$overrides}{$lvalue} = $prvalue; 782 } 783 784 $opt{$lvalue} = $prvalue; 785} 786 787sub set_eval { 788 my ($lvalue, $rvalue, $name) = @_; 789 790 my $prvalue = process_variables($rvalue); 791 my $arr; 792 793 if (defined($evals{$lvalue})) { 794 $arr = $evals{$lvalue}; 795 } else { 796 $arr = []; 797 $evals{$lvalue} = $arr; 798 } 799 800 push @{$arr}, $rvalue; 801} 802 803sub set_variable { 804 my ($lvalue, $rvalue) = @_; 805 806 if ($rvalue =~ /^\s*$/) { 807 delete $variable{$lvalue}; 808 } else { 809 $rvalue = process_variables($rvalue); 810 $variable{$lvalue} = $rvalue; 811 } 812} 813 814sub process_compare { 815 my ($lval, $cmp, $rval) = @_; 816 817 # remove whitespace 818 819 $lval =~ s/^\s*//; 820 $lval =~ s/\s*$//; 821 822 $rval =~ s/^\s*//; 823 $rval =~ s/\s*$//; 824 825 if ($cmp eq "==") { 826 return $lval eq $rval; 827 } elsif ($cmp eq "!=") { 828 return $lval ne $rval; 829 } elsif ($cmp eq "=~") { 830 return $lval =~ m/$rval/; 831 } elsif ($cmp eq "!~") { 832 return $lval !~ m/$rval/; 833 } 834 835 my $statement = "$lval $cmp $rval"; 836 my $ret = eval $statement; 837 838 # $@ stores error of eval 839 if ($@) { 840 return -1; 841 } 842 843 return $ret; 844} 845 846sub value_defined { 847 my ($val) = @_; 848 849 return defined($variable{$2}) || 850 defined($opt{$2}); 851} 852 853my $d = 0; 854sub process_expression { 855 my ($name, $val) = @_; 856 857 my $c = $d++; 858 859 while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) { 860 my $express = $1; 861 862 if (process_expression($name, $express)) { 863 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /; 864 } else { 865 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /; 866 } 867 } 868 869 $d--; 870 my $OR = "\\|\\|"; 871 my $AND = "\\&\\&"; 872 873 while ($val =~ s/^(.*?)($OR|$AND)//) { 874 my $express = $1; 875 my $op = $2; 876 877 if (process_expression($name, $express)) { 878 if ($op eq "||") { 879 return 1; 880 } 881 } else { 882 if ($op eq "&&") { 883 return 0; 884 } 885 } 886 } 887 888 if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) { 889 my $ret = process_compare($1, $2, $3); 890 if ($ret < 0) { 891 die "$name: $.: Unable to process comparison\n"; 892 } 893 return $ret; 894 } 895 896 if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) { 897 if (defined $1) { 898 return !value_defined($2); 899 } else { 900 return value_defined($2); 901 } 902 } 903 904 if ($val =~ /^\s*0\s*$/) { 905 return 0; 906 } elsif ($val =~ /^\s*\d+\s*$/) { 907 return 1; 908 } 909 910 die ("$name: $.: Undefined content $val in if statement\n"); 911} 912 913sub process_if { 914 my ($name, $value) = @_; 915 916 # Convert variables and replace undefined ones with 0 917 my $val = process_variables($value, 1); 918 my $ret = process_expression $name, $val; 919 920 return $ret; 921} 922 923sub __read_config { 924 my ($config, $current_test_num) = @_; 925 926 my $in; 927 open($in, $config) || die "can't read file $config"; 928 929 my $name = $config; 930 $name =~ s,.*/(.*),$1,; 931 932 my $test_num = $$current_test_num; 933 my $default = 1; 934 my $repeat = 1; 935 my $num_tests_set = 0; 936 my $skip = 0; 937 my $rest; 938 my $line; 939 my $test_case = 0; 940 my $if = 0; 941 my $if_set = 0; 942 my $override = 0; 943 944 my %overrides; 945 946 while (<$in>) { 947 948 # ignore blank lines and comments 949 next if (/^\s*$/ || /\s*\#/); 950 951 if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) { 952 953 my $type = $1; 954 $rest = $2; 955 $line = $2; 956 957 my $old_test_num; 958 my $old_repeat; 959 $override = 0; 960 961 if ($type eq "TEST_START") { 962 963 if ($num_tests_set) { 964 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 965 } 966 967 $old_test_num = $test_num; 968 $old_repeat = $repeat; 969 970 $test_num += $repeat; 971 $default = 0; 972 $repeat = 1; 973 } else { 974 $default = 1; 975 } 976 977 # If SKIP is anywhere in the line, the command will be skipped 978 if ($rest =~ s/\s+SKIP\b//) { 979 $skip = 1; 980 } else { 981 $test_case = 1; 982 $skip = 0; 983 } 984 985 if ($rest =~ s/\sELSE\b//) { 986 if (!$if) { 987 die "$name: $.: ELSE found with out matching IF section\n$_"; 988 } 989 $if = 0; 990 991 if ($if_set) { 992 $skip = 1; 993 } else { 994 $skip = 0; 995 } 996 } 997 998 if ($rest =~ s/\sIF\s+(.*)//) { 999 if (process_if($name, $1)) { 1000 $if_set = 1; 1001 } else { 1002 $skip = 1; 1003 } 1004 $if = 1; 1005 } else { 1006 $if = 0; 1007 $if_set = 0; 1008 } 1009 1010 if (!$skip) { 1011 if ($type eq "TEST_START") { 1012 if ($rest =~ s/\s+ITERATE\s+(\d+)//) { 1013 $repeat = $1; 1014 $repeat_tests{"$test_num"} = $repeat; 1015 } 1016 } elsif ($rest =~ s/\sOVERRIDE\b//) { 1017 # DEFAULT only 1018 $override = 1; 1019 # Clear previous overrides 1020 %overrides = (); 1021 } 1022 } 1023 1024 if (!$skip && $rest !~ /^\s*$/) { 1025 die "$name: $.: Gargbage found after $type\n$_"; 1026 } 1027 1028 if ($skip && $type eq "TEST_START") { 1029 $test_num = $old_test_num; 1030 $repeat = $old_repeat; 1031 } 1032 1033 } elsif (/^\s*ELSE\b(.*)$/) { 1034 if (!$if) { 1035 die "$name: $.: ELSE found with out matching IF section\n$_"; 1036 } 1037 $rest = $1; 1038 if ($if_set) { 1039 $skip = 1; 1040 $rest = ""; 1041 } else { 1042 $skip = 0; 1043 1044 if ($rest =~ /\sIF\s+(.*)/) { 1045 # May be a ELSE IF section. 1046 if (process_if($name, $1)) { 1047 $if_set = 1; 1048 } else { 1049 $skip = 1; 1050 } 1051 $rest = ""; 1052 } else { 1053 $if = 0; 1054 } 1055 } 1056 1057 if ($rest !~ /^\s*$/) { 1058 die "$name: $.: Gargbage found after DEFAULTS\n$_"; 1059 } 1060 1061 } elsif (/^\s*INCLUDE\s+(\S+)/) { 1062 1063 next if ($skip); 1064 1065 if (!$default) { 1066 die "$name: $.: INCLUDE can only be done in default sections\n$_"; 1067 } 1068 1069 my $file = process_variables($1); 1070 1071 if ($file !~ m,^/,) { 1072 # check the path of the config file first 1073 if ($config =~ m,(.*)/,) { 1074 if (-f "$1/$file") { 1075 $file = "$1/$file"; 1076 } 1077 } 1078 } 1079 1080 if ( ! -r $file ) { 1081 die "$name: $.: Can't read file $file\n$_"; 1082 } 1083 1084 if (__read_config($file, \$test_num)) { 1085 $test_case = 1; 1086 } 1087 1088 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=~\s*(.*?)\s*$/) { 1089 1090 next if ($skip); 1091 1092 my $lvalue = $1; 1093 my $rvalue = $2; 1094 1095 if ($default || $lvalue =~ /\[\d+\]$/) { 1096 set_eval($lvalue, $rvalue, $name); 1097 } else { 1098 my $val = "$lvalue\[$test_num\]"; 1099 set_eval($val, $rvalue, $name); 1100 } 1101 1102 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 1103 1104 next if ($skip); 1105 1106 my $lvalue = $1; 1107 my $rvalue = $2; 1108 1109 if (!$default && 1110 ($lvalue eq "NUM_TESTS" || 1111 $lvalue eq "LOG_FILE" || 1112 $lvalue eq "CLEAR_LOG")) { 1113 die "$name: $.: $lvalue must be set in DEFAULTS section\n"; 1114 } 1115 1116 if ($lvalue eq "NUM_TESTS") { 1117 if ($test_num) { 1118 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 1119 } 1120 if (!$default) { 1121 die "$name: $.: NUM_TESTS must be set in default section\n"; 1122 } 1123 $num_tests_set = 1; 1124 } 1125 1126 if ($default || $lvalue =~ /\[\d+\]$/) { 1127 set_value($lvalue, $rvalue, $override, \%overrides, $name); 1128 } else { 1129 my $val = "$lvalue\[$test_num\]"; 1130 set_value($val, $rvalue, $override, \%overrides, $name); 1131 1132 if ($repeat > 1) { 1133 $repeats{$val} = $repeat; 1134 } 1135 } 1136 } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) { 1137 next if ($skip); 1138 1139 my $lvalue = $1; 1140 my $rvalue = $2; 1141 1142 # process config variables. 1143 # Config variables are only active while reading the 1144 # config and can be defined anywhere. They also ignore 1145 # TEST_START and DEFAULTS, but are skipped if they are in 1146 # on of these sections that have SKIP defined. 1147 # The save variable can be 1148 # defined multiple times and the new one simply overrides 1149 # the prevous one. 1150 set_variable($lvalue, $rvalue); 1151 1152 } else { 1153 die "$name: $.: Garbage found in config\n$_"; 1154 } 1155 } 1156 1157 if ($test_num) { 1158 $test_num += $repeat - 1; 1159 $opt{"NUM_TESTS"} = $test_num; 1160 } 1161 1162 close($in); 1163 1164 $$current_test_num = $test_num; 1165 1166 return $test_case; 1167} 1168 1169sub get_test_case { 1170 print "What test case would you like to run?\n"; 1171 print " (build, install or boot)\n"; 1172 print " Other tests are available but require editing ktest.conf\n"; 1173 print " (see tools/testing/ktest/sample.conf)\n"; 1174 my $ans = <STDIN>; 1175 chomp $ans; 1176 $default{"TEST_TYPE"} = $ans; 1177} 1178 1179sub read_config { 1180 my ($config) = @_; 1181 1182 my $test_case; 1183 my $test_num = 0; 1184 1185 $test_case = __read_config $config, \$test_num; 1186 1187 # make sure we have all mandatory configs 1188 get_mandatory_configs; 1189 1190 # was a test specified? 1191 if (!$test_case) { 1192 print "No test case specified.\n"; 1193 get_test_case; 1194 } 1195 1196 # set any defaults 1197 1198 foreach my $default (keys %default) { 1199 if (!defined($opt{$default})) { 1200 $opt{$default} = $default{$default}; 1201 } 1202 } 1203 1204 if ($opt{"IGNORE_UNUSED"} == 1) { 1205 return; 1206 } 1207 1208 my %not_used; 1209 1210 # check if there are any stragglers (typos?) 1211 foreach my $option (keys %opt) { 1212 my $op = $option; 1213 # remove per test labels. 1214 $op =~ s/\[.*\]//; 1215 if (!exists($option_map{$op}) && 1216 !exists($default{$op}) && 1217 !exists($used_options{$op})) { 1218 $not_used{$op} = 1; 1219 } 1220 } 1221 1222 if (%not_used) { 1223 my $s = "s are"; 1224 $s = " is" if (keys %not_used == 1); 1225 print "The following option$s not used; could be a typo:\n"; 1226 foreach my $option (keys %not_used) { 1227 print "$option\n"; 1228 } 1229 print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n"; 1230 if (!read_yn "Do you want to continue?") { 1231 exit -1; 1232 } 1233 } 1234} 1235 1236sub __eval_option { 1237 my ($name, $option, $i) = @_; 1238 1239 # Add space to evaluate the character before $ 1240 $option = " $option"; 1241 my $retval = ""; 1242 my $repeated = 0; 1243 my $parent = 0; 1244 1245 foreach my $test (keys %repeat_tests) { 1246 if ($i >= $test && 1247 $i < $test + $repeat_tests{$test}) { 1248 1249 $repeated = 1; 1250 $parent = $test; 1251 last; 1252 } 1253 } 1254 1255 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { 1256 my $start = $1; 1257 my $var = $2; 1258 my $end = $3; 1259 1260 # Append beginning of line 1261 $retval = "$retval$start"; 1262 1263 # If the iteration option OPT[$i] exists, then use that. 1264 # otherwise see if the default OPT (without [$i]) exists. 1265 1266 my $o = "$var\[$i\]"; 1267 my $parento = "$var\[$parent\]"; 1268 1269 # If a variable contains itself, use the default var 1270 if (($var eq $name) && defined($opt{$var})) { 1271 $o = $opt{$var}; 1272 $retval = "$retval$o"; 1273 } elsif (defined($opt{$o})) { 1274 $o = $opt{$o}; 1275 $retval = "$retval$o"; 1276 } elsif ($repeated && defined($opt{$parento})) { 1277 $o = $opt{$parento}; 1278 $retval = "$retval$o"; 1279 } elsif (defined($opt{$var})) { 1280 $o = $opt{$var}; 1281 $retval = "$retval$o"; 1282 } elsif ($var eq "KERNEL_VERSION" && defined($make)) { 1283 # special option KERNEL_VERSION uses kernel version 1284 get_version(); 1285 $retval = "$retval$version"; 1286 } else { 1287 $retval = "$retval\$\{$var\}"; 1288 } 1289 1290 $option = $end; 1291 } 1292 1293 $retval = "$retval$option"; 1294 1295 $retval =~ s/^ //; 1296 1297 return $retval; 1298} 1299 1300sub process_evals { 1301 my ($name, $option, $i) = @_; 1302 1303 my $option_name = "$name\[$i\]"; 1304 my $ev; 1305 1306 my $old_option = $option; 1307 1308 if (defined($evals{$option_name})) { 1309 $ev = $evals{$option_name}; 1310 } elsif (defined($evals{$name})) { 1311 $ev = $evals{$name}; 1312 } else { 1313 return $option; 1314 } 1315 1316 for my $e (@{$ev}) { 1317 eval "\$option =~ $e"; 1318 } 1319 1320 if ($option ne $old_option) { 1321 doprint("$name changed from '$old_option' to '$option'\n"); 1322 } 1323 1324 return $option; 1325} 1326 1327sub eval_option { 1328 my ($name, $option, $i) = @_; 1329 1330 my $prev = ""; 1331 1332 # Since an option can evaluate to another option, 1333 # keep iterating until we do not evaluate any more 1334 # options. 1335 my $r = 0; 1336 while ($prev ne $option) { 1337 # Check for recursive evaluations. 1338 # 100 deep should be more than enough. 1339 if ($r++ > 100) { 1340 die "Over 100 evaluations accurred with $option\n" . 1341 "Check for recursive variables\n"; 1342 } 1343 $prev = $option; 1344 $option = __eval_option($name, $option, $i); 1345 } 1346 1347 $option = process_evals($name, $option, $i); 1348 1349 return $option; 1350} 1351 1352sub run_command; 1353sub start_monitor; 1354sub end_monitor; 1355sub wait_for_monitor; 1356 1357sub reboot { 1358 my ($time) = @_; 1359 my $powercycle = 0; 1360 1361 # test if the machine can be connected to within a few seconds 1362 my $stat = run_ssh("echo check machine status", $connect_timeout); 1363 if (!$stat) { 1364 doprint("power cycle\n"); 1365 $powercycle = 1; 1366 } 1367 1368 if ($powercycle) { 1369 run_command "$power_cycle"; 1370 1371 start_monitor; 1372 # flush out current monitor 1373 # May contain the reboot success line 1374 wait_for_monitor 1; 1375 1376 } else { 1377 # Make sure everything has been written to disk 1378 run_ssh("sync"); 1379 1380 if (defined($time)) { 1381 start_monitor; 1382 # flush out current monitor 1383 # May contain the reboot success line 1384 wait_for_monitor 1; 1385 } 1386 1387 # try to reboot normally 1388 if (run_command $reboot) { 1389 if (defined($powercycle_after_reboot)) { 1390 sleep $powercycle_after_reboot; 1391 run_command "$power_cycle"; 1392 } 1393 } else { 1394 # nope? power cycle it. 1395 run_command "$power_cycle"; 1396 } 1397 } 1398 1399 if (defined($time)) { 1400 1401 # We only want to get to the new kernel, don't fail 1402 # if we stumble over a call trace. 1403 my $save_ignore_errors = $ignore_errors; 1404 $ignore_errors = 1; 1405 1406 # Look for the good kernel to boot 1407 if (wait_for_monitor($time, "Linux version")) { 1408 # reboot got stuck? 1409 doprint "Reboot did not finish. Forcing power cycle\n"; 1410 run_command "$power_cycle"; 1411 } 1412 1413 $ignore_errors = $save_ignore_errors; 1414 1415 # Still need to wait for the reboot to finish 1416 wait_for_monitor($time, $reboot_success_line); 1417 1418 end_monitor; 1419 } 1420} 1421 1422sub reboot_to_good { 1423 my ($time) = @_; 1424 1425 if (defined($switch_to_good)) { 1426 run_command $switch_to_good; 1427 } 1428 1429 reboot $time; 1430} 1431 1432sub do_not_reboot { 1433 my $i = $iteration; 1434 1435 return $test_type eq "build" || $no_reboot || 1436 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 1437 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build") || 1438 ($test_type eq "config_bisect" && $opt{"CONFIG_BISECT_TYPE[$i]"} eq "build"); 1439} 1440 1441my $in_die = 0; 1442 1443sub get_test_name() { 1444 my $name; 1445 1446 if (defined($test_name)) { 1447 $name = "$test_name:$test_type"; 1448 } else { 1449 $name = $test_type; 1450 } 1451 return $name; 1452} 1453 1454sub dodie { 1455 1456 # avoid recusion 1457 return if ($in_die); 1458 $in_die = 1; 1459 1460 my $i = $iteration; 1461 1462 doprint "CRITICAL FAILURE... [TEST $i] ", @_, "\n"; 1463 1464 if ($reboot_on_error && !do_not_reboot) { 1465 1466 doprint "REBOOTING\n"; 1467 reboot_to_good; 1468 1469 } elsif ($poweroff_on_error && defined($power_off)) { 1470 doprint "POWERING OFF\n"; 1471 `$power_off`; 1472 } 1473 1474 if (defined($opt{"LOG_FILE"})) { 1475 print " See $opt{LOG_FILE} for more info.\n"; 1476 } 1477 1478 if ($email_on_error) { 1479 my $name = get_test_name; 1480 send_email("KTEST: critical failure for test $i [$name]", 1481 "Your test started at $script_start_time has failed with:\n@_\n"); 1482 } 1483 1484 if ($monitor_cnt) { 1485 # restore terminal settings 1486 system("stty $stty_orig"); 1487 } 1488 1489 if (defined($post_test)) { 1490 run_command $post_test; 1491 } 1492 1493 die @_, "\n"; 1494} 1495 1496sub create_pty { 1497 my ($ptm, $pts) = @_; 1498 my $tmp; 1499 my $TIOCSPTLCK = 0x40045431; 1500 my $TIOCGPTN = 0x80045430; 1501 1502 sysopen($ptm, "/dev/ptmx", O_RDWR | O_NONBLOCK) or 1503 dodie "Cant open /dev/ptmx"; 1504 1505 # unlockpt() 1506 $tmp = pack("i", 0); 1507 ioctl($ptm, $TIOCSPTLCK, $tmp) or 1508 dodie "ioctl TIOCSPTLCK for /dev/ptmx failed"; 1509 1510 # ptsname() 1511 ioctl($ptm, $TIOCGPTN, $tmp) or 1512 dodie "ioctl TIOCGPTN for /dev/ptmx failed"; 1513 $tmp = unpack("i", $tmp); 1514 1515 sysopen($pts, "/dev/pts/$tmp", O_RDWR | O_NONBLOCK) or 1516 dodie "Can't open /dev/pts/$tmp"; 1517} 1518 1519sub exec_console { 1520 my ($ptm, $pts) = @_; 1521 1522 close($ptm); 1523 1524 close(\*STDIN); 1525 close(\*STDOUT); 1526 close(\*STDERR); 1527 1528 open(\*STDIN, '<&', $pts); 1529 open(\*STDOUT, '>&', $pts); 1530 open(\*STDERR, '>&', $pts); 1531 1532 close($pts); 1533 1534 exec $console or 1535 dodie "Can't open console $console"; 1536} 1537 1538sub open_console { 1539 my ($ptm) = @_; 1540 my $pts = \*PTSFD; 1541 my $pid; 1542 1543 # save terminal settings 1544 $stty_orig = `stty -g`; 1545 1546 # place terminal in cbreak mode so that stdin can be read one character at 1547 # a time without having to wait for a newline 1548 system("stty -icanon -echo -icrnl"); 1549 1550 create_pty($ptm, $pts); 1551 1552 $pid = fork; 1553 1554 if (!$pid) { 1555 # child 1556 exec_console($ptm, $pts) 1557 } 1558 1559 # parent 1560 close($pts); 1561 1562 return $pid; 1563 1564 open(PTSFD, "Stop perl from warning about single use of PTSFD"); 1565} 1566 1567sub close_console { 1568 my ($fp, $pid) = @_; 1569 1570 doprint "kill child process $pid\n"; 1571 kill $close_console_signal, $pid; 1572 1573 doprint "wait for child process $pid to exit\n"; 1574 waitpid($pid, 0); 1575 1576 print "closing!\n"; 1577 close($fp); 1578 1579 # restore terminal settings 1580 system("stty $stty_orig"); 1581} 1582 1583sub start_monitor { 1584 if ($monitor_cnt++) { 1585 return; 1586 } 1587 $monitor_fp = \*MONFD; 1588 $monitor_pid = open_console $monitor_fp; 1589 1590 return; 1591 1592 open(MONFD, "Stop perl from warning about single use of MONFD"); 1593} 1594 1595sub end_monitor { 1596 return if (!defined $console); 1597 if (--$monitor_cnt) { 1598 return; 1599 } 1600 close_console($monitor_fp, $monitor_pid); 1601} 1602 1603sub wait_for_monitor { 1604 my ($time, $stop) = @_; 1605 my $full_line = ""; 1606 my $line; 1607 my $booted = 0; 1608 my $start_time = time; 1609 my $skip_call_trace = 0; 1610 my $bug = 0; 1611 my $bug_ignored = 0; 1612 my $now; 1613 1614 doprint "** Wait for monitor to settle down **\n"; 1615 1616 # read the monitor and wait for the system to calm down 1617 while (!$booted) { 1618 $line = wait_for_input($monitor_fp, $time); 1619 last if (!defined($line)); 1620 print "$line"; 1621 $full_line .= $line; 1622 1623 if (defined($stop) && $full_line =~ /$stop/) { 1624 doprint "wait for monitor detected $stop\n"; 1625 $booted = 1; 1626 } 1627 1628 if ($full_line =~ /\[ backtrace testing \]/) { 1629 $skip_call_trace = 1; 1630 } 1631 1632 if ($full_line =~ /call trace:/i) { 1633 if (!$bug && !$skip_call_trace) { 1634 if ($ignore_errors) { 1635 $bug_ignored = 1; 1636 } else { 1637 $bug = 1; 1638 } 1639 } 1640 } 1641 1642 if ($full_line =~ /\[ end of backtrace testing \]/) { 1643 $skip_call_trace = 0; 1644 } 1645 1646 if ($full_line =~ /Kernel panic -/) { 1647 $bug = 1; 1648 } 1649 1650 if ($line =~ /\n/) { 1651 $full_line = ""; 1652 } 1653 $now = time; 1654 if ($now - $start_time >= $max_monitor_wait) { 1655 doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n"; 1656 return 1; 1657 } 1658 } 1659 print "** Monitor flushed **\n"; 1660 1661 # if stop is defined but wasn't hit, return error 1662 # used by reboot (which wants to see a reboot) 1663 if (defined($stop) && !$booted) { 1664 $bug = 1; 1665 } 1666 return $bug; 1667} 1668 1669sub save_logs { 1670 my ($result, $basedir) = @_; 1671 my @t = localtime; 1672 my $date = sprintf "%04d%02d%02d%02d%02d%02d", 1673 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 1674 1675 my $type = $build_type; 1676 if ($type =~ /useconfig/) { 1677 $type = "useconfig"; 1678 } 1679 1680 my $dir = "$machine-$test_type-$type-$result-$date"; 1681 1682 $dir = "$basedir/$dir"; 1683 1684 if (!-d $dir) { 1685 mkpath($dir) or 1686 dodie "can't create $dir"; 1687 } 1688 1689 my %files = ( 1690 "config" => $output_config, 1691 "buildlog" => $buildlog, 1692 "dmesg" => $dmesg, 1693 "testlog" => $testlog, 1694 ); 1695 1696 while (my ($name, $source) = each(%files)) { 1697 if (-f "$source") { 1698 cp "$source", "$dir/$name" or 1699 dodie "failed to copy $source"; 1700 } 1701 } 1702 1703 doprint "*** Saved info to $dir ***\n"; 1704} 1705 1706sub fail { 1707 1708 if ($die_on_failure) { 1709 dodie @_; 1710 } 1711 1712 doprint "FAILED\n"; 1713 1714 my $i = $iteration; 1715 1716 # no need to reboot for just building. 1717 if (!do_not_reboot) { 1718 doprint "REBOOTING\n"; 1719 reboot_to_good $sleep_time; 1720 } 1721 1722 my $name = ""; 1723 1724 if (defined($test_name)) { 1725 $name = " ($test_name)"; 1726 } 1727 1728 print_times; 1729 1730 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1731 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1732 doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n"; 1733 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1734 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 1735 1736 if (defined($store_failures)) { 1737 save_logs "fail", $store_failures; 1738 } 1739 1740 if (defined($post_test)) { 1741 run_command $post_test; 1742 } 1743 1744 return 1; 1745} 1746 1747sub run_command { 1748 my ($command, $redirect, $timeout) = @_; 1749 my $start_time; 1750 my $end_time; 1751 my $dolog = 0; 1752 my $dord = 0; 1753 my $dostdout = 0; 1754 my $pid; 1755 my $command_orig = $command; 1756 1757 $command =~ s/\$SSH_USER/$ssh_user/g; 1758 $command =~ s/\$MACHINE/$machine/g; 1759 1760 doprint("$command ... "); 1761 $start_time = time; 1762 1763 $pid = open(CMD, "$command 2>&1 |") or 1764 (fail "unable to exec $command" and return 0); 1765 1766 if (defined($opt{"LOG_FILE"})) { 1767 open(LOG, ">>$opt{LOG_FILE}") or 1768 dodie "failed to write to log"; 1769 $dolog = 1; 1770 } 1771 1772 if (defined($redirect)) { 1773 if ($redirect eq 1) { 1774 $dostdout = 1; 1775 # Have the output of the command on its own line 1776 doprint "\n"; 1777 } else { 1778 open (RD, ">$redirect") or 1779 dodie "failed to write to redirect $redirect"; 1780 $dord = 1; 1781 } 1782 } 1783 1784 my $hit_timeout = 0; 1785 1786 while (1) { 1787 my $fp = \*CMD; 1788 if (defined($timeout)) { 1789 doprint "timeout = $timeout\n"; 1790 } 1791 my $line = wait_for_input($fp, $timeout); 1792 if (!defined($line)) { 1793 my $now = time; 1794 if (defined($timeout) && (($now - $start_time) >= $timeout)) { 1795 doprint "Hit timeout of $timeout, killing process\n"; 1796 $hit_timeout = 1; 1797 kill 9, $pid; 1798 } 1799 last; 1800 } 1801 print LOG $line if ($dolog); 1802 print RD $line if ($dord); 1803 print $line if ($dostdout); 1804 } 1805 1806 waitpid($pid, 0); 1807 # shift 8 for real exit status 1808 $run_command_status = $? >> 8; 1809 1810 if ($command_orig eq $default{REBOOT} && 1811 $run_command_status == $reboot_return_code) { 1812 $run_command_status = 0; 1813 } 1814 1815 close(CMD); 1816 close(LOG) if ($dolog); 1817 close(RD) if ($dord); 1818 1819 $end_time = time; 1820 my $delta = $end_time - $start_time; 1821 1822 if ($delta == 1) { 1823 doprint "[1 second] "; 1824 } else { 1825 doprint "[$delta seconds] "; 1826 } 1827 1828 if ($hit_timeout) { 1829 $run_command_status = 1; 1830 } 1831 1832 if ($run_command_status) { 1833 doprint "FAILED!\n"; 1834 } else { 1835 doprint "SUCCESS\n"; 1836 } 1837 1838 return !$run_command_status; 1839} 1840 1841sub run_ssh { 1842 my ($cmd, $timeout) = @_; 1843 my $cp_exec = $ssh_exec; 1844 1845 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 1846 return run_command "$cp_exec", undef , $timeout; 1847} 1848 1849sub run_scp { 1850 my ($src, $dst, $cp_scp) = @_; 1851 1852 $cp_scp =~ s/\$SRC_FILE/$src/g; 1853 $cp_scp =~ s/\$DST_FILE/$dst/g; 1854 1855 return run_command "$cp_scp"; 1856} 1857 1858sub run_scp_install { 1859 my ($src, $dst) = @_; 1860 1861 my $cp_scp = $scp_to_target_install; 1862 1863 return run_scp($src, $dst, $cp_scp); 1864} 1865 1866sub run_scp_mod { 1867 my ($src, $dst) = @_; 1868 1869 my $cp_scp = $scp_to_target; 1870 1871 return run_scp($src, $dst, $cp_scp); 1872} 1873 1874sub get_grub2_index { 1875 1876 return if (defined($grub_number) && defined($last_grub_menu) && 1877 $last_grub_menu eq $grub_menu && defined($last_machine) && 1878 $last_machine eq $machine); 1879 1880 doprint "Find grub2 menu ... "; 1881 $grub_number = -1; 1882 1883 my $ssh_grub = $ssh_exec; 1884 $ssh_grub =~ s,\$SSH_COMMAND,cat $grub_file,g; 1885 1886 open(IN, "$ssh_grub |") 1887 or dodie "unable to get $grub_file"; 1888 1889 my $found = 0; 1890 my $grub_menu_qt = quotemeta($grub_menu); 1891 1892 while (<IN>) { 1893 if (/^menuentry.*$grub_menu_qt/) { 1894 $grub_number++; 1895 $found = 1; 1896 last; 1897 } elsif (/^menuentry\s|^submenu\s/) { 1898 $grub_number++; 1899 } 1900 } 1901 close(IN); 1902 1903 dodie "Could not find '$grub_menu' in $grub_file on $machine" 1904 if (!$found); 1905 doprint "$grub_number\n"; 1906 $last_grub_menu = $grub_menu; 1907 $last_machine = $machine; 1908} 1909 1910sub get_grub_index { 1911 1912 if ($reboot_type eq "grub2") { 1913 get_grub2_index; 1914 return; 1915 } 1916 1917 if ($reboot_type ne "grub") { 1918 return; 1919 } 1920 return if (defined($grub_number) && defined($last_grub_menu) && 1921 $last_grub_menu eq $grub_menu && defined($last_machine) && 1922 $last_machine eq $machine); 1923 1924 doprint "Find grub menu ... "; 1925 $grub_number = -1; 1926 1927 my $ssh_grub = $ssh_exec; 1928 $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 1929 1930 open(IN, "$ssh_grub |") 1931 or dodie "unable to get menu.lst"; 1932 1933 my $found = 0; 1934 my $grub_menu_qt = quotemeta($grub_menu); 1935 1936 while (<IN>) { 1937 if (/^\s*title\s+$grub_menu_qt\s*$/) { 1938 $grub_number++; 1939 $found = 1; 1940 last; 1941 } elsif (/^\s*title\s/) { 1942 $grub_number++; 1943 } 1944 } 1945 close(IN); 1946 1947 dodie "Could not find '$grub_menu' in /boot/grub/menu on $machine" 1948 if (!$found); 1949 doprint "$grub_number\n"; 1950 $last_grub_menu = $grub_menu; 1951 $last_machine = $machine; 1952} 1953 1954sub wait_for_input 1955{ 1956 my ($fp, $time) = @_; 1957 my $start_time; 1958 my $rin; 1959 my $rout; 1960 my $nr; 1961 my $buf; 1962 my $line; 1963 my $ch; 1964 1965 if (!defined($time)) { 1966 $time = $timeout; 1967 } 1968 1969 $rin = ''; 1970 vec($rin, fileno($fp), 1) = 1; 1971 vec($rin, fileno(\*STDIN), 1) = 1; 1972 1973 $start_time = time; 1974 1975 while (1) { 1976 $nr = select($rout=$rin, undef, undef, $time); 1977 1978 last if ($nr <= 0); 1979 1980 # copy data from stdin to the console 1981 if (vec($rout, fileno(\*STDIN), 1) == 1) { 1982 $nr = sysread(\*STDIN, $buf, 1000); 1983 syswrite($fp, $buf, $nr) if ($nr > 0); 1984 } 1985 1986 # The timeout is based on time waiting for the fp data 1987 if (vec($rout, fileno($fp), 1) != 1) { 1988 last if (defined($time) && (time - $start_time > $time)); 1989 next; 1990 } 1991 1992 $line = ""; 1993 1994 # try to read one char at a time 1995 while (sysread $fp, $ch, 1) { 1996 $line .= $ch; 1997 last if ($ch eq "\n"); 1998 } 1999 2000 last if (!length($line)); 2001 2002 return $line; 2003 } 2004 return undef; 2005} 2006 2007sub reboot_to { 2008 if (defined($switch_to_test)) { 2009 run_command $switch_to_test; 2010 } 2011 2012 if ($reboot_type eq "grub") { 2013 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; 2014 } elsif ($reboot_type eq "grub2") { 2015 run_ssh "$grub_reboot $grub_number"; 2016 } elsif ($reboot_type eq "syslinux") { 2017 run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path"; 2018 } elsif (defined $reboot_script) { 2019 run_command "$reboot_script"; 2020 } 2021 reboot; 2022} 2023 2024sub get_sha1 { 2025 my ($commit) = @_; 2026 2027 doprint "git rev-list --max-count=1 $commit ... "; 2028 my $sha1 = `git rev-list --max-count=1 $commit`; 2029 my $ret = $?; 2030 2031 logit $sha1; 2032 2033 if ($ret) { 2034 doprint "FAILED\n"; 2035 dodie "Failed to get git $commit"; 2036 } 2037 2038 print "SUCCESS\n"; 2039 2040 chomp $sha1; 2041 2042 return $sha1; 2043} 2044 2045sub monitor { 2046 my $booted = 0; 2047 my $bug = 0; 2048 my $bug_ignored = 0; 2049 my $skip_call_trace = 0; 2050 my $loops; 2051 2052 my $start_time = time; 2053 2054 wait_for_monitor 5; 2055 2056 my $line; 2057 my $full_line = ""; 2058 2059 open(DMESG, "> $dmesg") or 2060 dodie "unable to write to $dmesg"; 2061 2062 reboot_to; 2063 2064 my $success_start; 2065 my $failure_start; 2066 my $monitor_start = time; 2067 my $done = 0; 2068 my $version_found = 0; 2069 2070 while (!$done) { 2071 2072 if ($bug && defined($stop_after_failure) && 2073 $stop_after_failure >= 0) { 2074 my $time = $stop_after_failure - (time - $failure_start); 2075 $line = wait_for_input($monitor_fp, $time); 2076 if (!defined($line)) { 2077 doprint "bug timed out after $booted_timeout seconds\n"; 2078 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 2079 last; 2080 } 2081 } elsif ($booted) { 2082 $line = wait_for_input($monitor_fp, $booted_timeout); 2083 if (!defined($line)) { 2084 my $s = $booted_timeout == 1 ? "" : "s"; 2085 doprint "Successful boot found: break after $booted_timeout second$s\n"; 2086 last; 2087 } 2088 } else { 2089 $line = wait_for_input($monitor_fp); 2090 if (!defined($line)) { 2091 my $s = $timeout == 1 ? "" : "s"; 2092 doprint "Timed out after $timeout second$s\n"; 2093 last; 2094 } 2095 } 2096 2097 doprint $line; 2098 print DMESG $line; 2099 2100 # we are not guaranteed to get a full line 2101 $full_line .= $line; 2102 2103 if ($full_line =~ /$success_line/) { 2104 $booted = 1; 2105 $success_start = time; 2106 } 2107 2108 if ($booted && defined($stop_after_success) && 2109 $stop_after_success >= 0) { 2110 my $now = time; 2111 if ($now - $success_start >= $stop_after_success) { 2112 doprint "Test forced to stop after $stop_after_success seconds after success\n"; 2113 last; 2114 } 2115 } 2116 2117 if ($full_line =~ /\[ backtrace testing \]/) { 2118 $skip_call_trace = 1; 2119 } 2120 2121 if ($full_line =~ /call trace:/i) { 2122 if (!$bug && !$skip_call_trace) { 2123 if ($ignore_errors) { 2124 $bug_ignored = 1; 2125 } else { 2126 $bug = 1; 2127 $failure_start = time; 2128 } 2129 } 2130 } 2131 2132 if ($bug && defined($stop_after_failure) && 2133 $stop_after_failure >= 0) { 2134 my $now = time; 2135 if ($now - $failure_start >= $stop_after_failure) { 2136 doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 2137 last; 2138 } 2139 } 2140 2141 if ($full_line =~ /\[ end of backtrace testing \]/) { 2142 $skip_call_trace = 0; 2143 } 2144 2145 if ($full_line =~ /Kernel panic -/) { 2146 $failure_start = time; 2147 $bug = 1; 2148 } 2149 2150 # Detect triple faults by testing the banner 2151 if ($full_line =~ /\bLinux version (\S+).*\n/) { 2152 if ($1 eq $version) { 2153 $version_found = 1; 2154 } elsif ($version_found && $detect_triplefault) { 2155 # We already booted into the kernel we are testing, 2156 # but now we booted into another kernel? 2157 # Consider this a triple fault. 2158 doprint "Already booted in Linux kernel $version, but now\n"; 2159 doprint "we booted into Linux kernel $1.\n"; 2160 doprint "Assuming that this is a triple fault.\n"; 2161 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; 2162 last; 2163 } 2164 } 2165 2166 if ($line =~ /\n/) { 2167 $full_line = ""; 2168 } 2169 2170 if ($stop_test_after > 0 && !$booted && !$bug) { 2171 if (time - $monitor_start > $stop_test_after) { 2172 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n"; 2173 $done = 1; 2174 } 2175 } 2176 } 2177 2178 my $end_time = time; 2179 $reboot_time = $end_time - $start_time; 2180 2181 close(DMESG); 2182 2183 if ($bug) { 2184 return 0 if ($in_bisect); 2185 fail "failed - got a bug report" and return 0; 2186 } 2187 2188 if (!$booted) { 2189 return 0 if ($in_bisect); 2190 fail "failed - never got a boot prompt." and return 0; 2191 } 2192 2193 if ($bug_ignored) { 2194 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 2195 } 2196 2197 return 1; 2198} 2199 2200sub eval_kernel_version { 2201 my ($option) = @_; 2202 2203 $option =~ s/\$KERNEL_VERSION/$version/g; 2204 2205 return $option; 2206} 2207 2208sub do_post_install { 2209 2210 return if (!defined($post_install)); 2211 2212 my $cp_post_install = eval_kernel_version $post_install; 2213 run_command "$cp_post_install" or 2214 dodie "Failed to run post install"; 2215} 2216 2217# Sometimes the reboot fails, and will hang. We try to ssh to the box 2218# and if we fail, we force another reboot, that should powercycle it. 2219sub test_booted { 2220 if (!run_ssh "echo testing connection") { 2221 reboot $sleep_time; 2222 } 2223} 2224 2225sub install { 2226 2227 return if ($no_install); 2228 2229 my $start_time = time; 2230 2231 if (defined($pre_install)) { 2232 my $cp_pre_install = eval_kernel_version $pre_install; 2233 run_command "$cp_pre_install" or 2234 dodie "Failed to run pre install"; 2235 } 2236 2237 my $cp_target = eval_kernel_version $target_image; 2238 2239 test_booted; 2240 2241 run_scp_install "$outputdir/$build_target", "$cp_target" or 2242 dodie "failed to copy image"; 2243 2244 my $install_mods = 0; 2245 2246 # should we process modules? 2247 $install_mods = 0; 2248 open(IN, "$output_config") or dodie("Can't read config file"); 2249 while (<IN>) { 2250 if (/CONFIG_MODULES(=y)?/) { 2251 if (defined($1)) { 2252 $install_mods = 1; 2253 last; 2254 } 2255 } 2256 } 2257 close(IN); 2258 2259 if (!$install_mods) { 2260 do_post_install; 2261 doprint "No modules needed\n"; 2262 my $end_time = time; 2263 $install_time = $end_time - $start_time; 2264 return; 2265 } 2266 2267 run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or 2268 dodie "Failed to install modules"; 2269 2270 my $modlib = "/lib/modules/$version"; 2271 my $modtar = "ktest-mods.tar.bz2"; 2272 2273 run_ssh "rm -rf $modlib" or 2274 dodie "failed to remove old mods: $modlib"; 2275 2276 # would be nice if scp -r did not follow symbolic links 2277 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 2278 dodie "making tarball"; 2279 2280 run_scp_mod "$tmpdir/$modtar", "/tmp" or 2281 dodie "failed to copy modules"; 2282 2283 unlink "$tmpdir/$modtar"; 2284 2285 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or 2286 dodie "failed to tar modules"; 2287 2288 run_ssh "rm -f /tmp/$modtar"; 2289 2290 do_post_install; 2291 2292 my $end_time = time; 2293 $install_time = $end_time - $start_time; 2294} 2295 2296sub get_version { 2297 # get the release name 2298 return if ($have_version); 2299 doprint "$make kernelrelease ... "; 2300 $version = `$make -s kernelrelease | tail -1`; 2301 chomp($version); 2302 doprint "$version\n"; 2303 $have_version = 1; 2304} 2305 2306sub start_monitor_and_install { 2307 # Make sure the stable kernel has finished booting 2308 2309 # Install bisects, don't need console 2310 if (defined $console) { 2311 start_monitor; 2312 wait_for_monitor 5; 2313 end_monitor; 2314 } 2315 2316 get_grub_index; 2317 get_version; 2318 install; 2319 2320 start_monitor if (defined $console); 2321 return monitor; 2322} 2323 2324my $check_build_re = ".*:.*(warning|error|Error):.*"; 2325my $utf8_quote = "\\x{e2}\\x{80}(\\x{98}|\\x{99})"; 2326 2327sub process_warning_line { 2328 my ($line) = @_; 2329 2330 chomp $line; 2331 2332 # for distcc heterogeneous systems, some compilers 2333 # do things differently causing warning lines 2334 # to be slightly different. This makes an attempt 2335 # to fixe those issues. 2336 2337 # chop off the index into the line 2338 # using distcc, some compilers give different indexes 2339 # depending on white space 2340 $line =~ s/^(\s*\S+:\d+:)\d+/$1/; 2341 2342 # Some compilers use UTF-8 extended for quotes and some don't. 2343 $line =~ s/$utf8_quote/'/g; 2344 2345 return $line; 2346} 2347 2348# Read buildlog and check against warnings file for any 2349# new warnings. 2350# 2351# Returns 1 if OK 2352# 0 otherwise 2353sub check_buildlog { 2354 return 1 if (!defined $warnings_file); 2355 2356 my %warnings_list; 2357 2358 # Failed builds should not reboot the target 2359 my $save_no_reboot = $no_reboot; 2360 $no_reboot = 1; 2361 2362 if (-f $warnings_file) { 2363 open(IN, $warnings_file) or 2364 dodie "Error opening $warnings_file"; 2365 2366 while (<IN>) { 2367 if (/$check_build_re/) { 2368 my $warning = process_warning_line $_; 2369 2370 $warnings_list{$warning} = 1; 2371 } 2372 } 2373 close(IN); 2374 } 2375 2376 # If warnings file didn't exist, and WARNINGS_FILE exist, 2377 # then we fail on any warning! 2378 2379 open(IN, $buildlog) or dodie "Can't open $buildlog"; 2380 while (<IN>) { 2381 if (/$check_build_re/) { 2382 my $warning = process_warning_line $_; 2383 2384 if (!defined $warnings_list{$warning}) { 2385 fail "New warning found (not in $warnings_file)\n$_\n"; 2386 $no_reboot = $save_no_reboot; 2387 return 0; 2388 } 2389 } 2390 } 2391 $no_reboot = $save_no_reboot; 2392 close(IN); 2393} 2394 2395sub check_patch_buildlog { 2396 my ($patch) = @_; 2397 2398 my @files = `git show $patch | diffstat -l`; 2399 2400 foreach my $file (@files) { 2401 chomp $file; 2402 } 2403 2404 open(IN, "git show $patch |") or 2405 dodie "failed to show $patch"; 2406 while (<IN>) { 2407 if (m,^--- a/(.*),) { 2408 chomp $1; 2409 $files[$#files] = $1; 2410 } 2411 } 2412 close(IN); 2413 2414 open(IN, $buildlog) or dodie "Can't open $buildlog"; 2415 while (<IN>) { 2416 if (/^\s*(.*?):.*(warning|error)/) { 2417 my $err = $1; 2418 foreach my $file (@files) { 2419 my $fullpath = "$builddir/$file"; 2420 if ($file eq $err || $fullpath eq $err) { 2421 fail "$file built with warnings" and return 0; 2422 } 2423 } 2424 } 2425 } 2426 close(IN); 2427 2428 return 1; 2429} 2430 2431sub apply_min_config { 2432 my $outconfig = "$output_config.new"; 2433 2434 # Read the config file and remove anything that 2435 # is in the force_config hash (from minconfig and others) 2436 # then add the force config back. 2437 2438 doprint "Applying minimum configurations into $output_config.new\n"; 2439 2440 open (OUT, ">$outconfig") or 2441 dodie "Can't create $outconfig"; 2442 2443 if (-f $output_config) { 2444 open (IN, $output_config) or 2445 dodie "Failed to open $output_config"; 2446 while (<IN>) { 2447 if (/^(# )?(CONFIG_[^\s=]*)/) { 2448 next if (defined($force_config{$2})); 2449 } 2450 print OUT; 2451 } 2452 close IN; 2453 } 2454 foreach my $config (keys %force_config) { 2455 print OUT "$force_config{$config}\n"; 2456 } 2457 close OUT; 2458 2459 run_command "mv $outconfig $output_config"; 2460} 2461 2462sub make_oldconfig { 2463 2464 my @force_list = keys %force_config; 2465 2466 if ($#force_list >= 0) { 2467 apply_min_config; 2468 } 2469 2470 if (!run_command "$make olddefconfig") { 2471 # Perhaps olddefconfig doesn't exist in this version of the kernel 2472 # try oldnoconfig 2473 doprint "olddefconfig failed, trying make oldnoconfig\n"; 2474 if (!run_command "$make oldnoconfig") { 2475 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 2476 # try a yes '' | oldconfig 2477 run_command "yes '' | $make oldconfig" or 2478 dodie "failed make config oldconfig"; 2479 } 2480 } 2481} 2482 2483# read a config file and use this to force new configs. 2484sub load_force_config { 2485 my ($config) = @_; 2486 2487 doprint "Loading force configs from $config\n"; 2488 open(IN, $config) or 2489 dodie "failed to read $config"; 2490 while (<IN>) { 2491 chomp; 2492 if (/^(CONFIG[^\s=]*)(\s*=.*)/) { 2493 $force_config{$1} = $_; 2494 } elsif (/^# (CONFIG_\S*) is not set/) { 2495 $force_config{$1} = $_; 2496 } 2497 } 2498 close IN; 2499} 2500 2501sub build { 2502 my ($type) = @_; 2503 2504 unlink $buildlog; 2505 2506 my $start_time = time; 2507 2508 # Failed builds should not reboot the target 2509 my $save_no_reboot = $no_reboot; 2510 $no_reboot = 1; 2511 2512 # Calculate a new version from here. 2513 $have_version = 0; 2514 2515 if (defined($pre_build)) { 2516 my $ret = run_command $pre_build; 2517 if (!$ret && defined($pre_build_die) && 2518 $pre_build_die) { 2519 dodie "failed to pre_build\n"; 2520 } 2521 } 2522 2523 if ($type =~ /^useconfig:(.*)/) { 2524 run_command "cp $1 $output_config" or 2525 dodie "could not copy $1 to .config"; 2526 2527 $type = "oldconfig"; 2528 } 2529 2530 # old config can ask questions 2531 if ($type eq "oldconfig") { 2532 $type = "olddefconfig"; 2533 2534 # allow for empty configs 2535 run_command "touch $output_config"; 2536 2537 if (!$noclean) { 2538 run_command "mv $output_config $outputdir/config_temp" or 2539 dodie "moving .config"; 2540 2541 run_command "$make mrproper" or dodie "make mrproper"; 2542 2543 run_command "mv $outputdir/config_temp $output_config" or 2544 dodie "moving config_temp"; 2545 } 2546 2547 } elsif (!$noclean) { 2548 unlink "$output_config"; 2549 run_command "$make mrproper" or 2550 dodie "make mrproper"; 2551 } 2552 2553 # add something to distinguish this build 2554 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 2555 print OUT "$localversion\n"; 2556 close(OUT); 2557 2558 if (defined($minconfig)) { 2559 load_force_config($minconfig); 2560 } 2561 2562 if ($type ne "olddefconfig") { 2563 run_command "$make $type" or 2564 dodie "failed make config"; 2565 } 2566 # Run old config regardless, to enforce min configurations 2567 make_oldconfig; 2568 2569 my $build_ret = run_command "$make $build_options", $buildlog; 2570 2571 if (defined($post_build)) { 2572 # Because a post build may change the kernel version 2573 # do it now. 2574 get_version; 2575 my $ret = run_command $post_build; 2576 if (!$ret && defined($post_build_die) && 2577 $post_build_die) { 2578 dodie "failed to post_build\n"; 2579 } 2580 } 2581 2582 if (!$build_ret) { 2583 # bisect may need this to pass 2584 if ($in_bisect) { 2585 $no_reboot = $save_no_reboot; 2586 return 0; 2587 } 2588 fail "failed build" and return 0; 2589 } 2590 2591 $no_reboot = $save_no_reboot; 2592 2593 my $end_time = time; 2594 $build_time = $end_time - $start_time; 2595 2596 return 1; 2597} 2598 2599sub halt { 2600 if (!run_ssh "halt" or defined($power_off)) { 2601 if (defined($poweroff_after_halt)) { 2602 sleep $poweroff_after_halt; 2603 run_command "$power_off"; 2604 } 2605 } else { 2606 # nope? the zap it! 2607 run_command "$power_off"; 2608 } 2609} 2610 2611sub success { 2612 my ($i) = @_; 2613 2614 $successes++; 2615 2616 my $name = ""; 2617 2618 if (defined($test_name)) { 2619 $name = " ($test_name)"; 2620 } 2621 2622 print_times; 2623 2624 doprint "\n\n*******************************************\n"; 2625 doprint "*******************************************\n"; 2626 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; 2627 doprint "*******************************************\n"; 2628 doprint "*******************************************\n"; 2629 2630 if (defined($store_successes)) { 2631 save_logs "success", $store_successes; 2632 } 2633 2634 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 2635 doprint "Reboot and wait $sleep_time seconds\n"; 2636 reboot_to_good $sleep_time; 2637 } 2638 2639 if (defined($post_test)) { 2640 run_command $post_test; 2641 } 2642} 2643 2644sub answer_bisect { 2645 for (;;) { 2646 doprint "Pass, fail, or skip? [p/f/s]"; 2647 my $ans = <STDIN>; 2648 chomp $ans; 2649 if ($ans eq "p" || $ans eq "P") { 2650 return 1; 2651 } elsif ($ans eq "f" || $ans eq "F") { 2652 return 0; 2653 } elsif ($ans eq "s" || $ans eq "S") { 2654 return -1; 2655 } else { 2656 print "Please answer 'p', 'f', or 's'\n"; 2657 } 2658 } 2659} 2660 2661sub child_run_test { 2662 2663 # child should have no power 2664 $reboot_on_error = 0; 2665 $poweroff_on_error = 0; 2666 $die_on_failure = 1; 2667 2668 run_command $run_test, $testlog; 2669 2670 exit $run_command_status; 2671} 2672 2673my $child_done; 2674 2675sub child_finished { 2676 $child_done = 1; 2677} 2678 2679sub do_run_test { 2680 my $child_pid; 2681 my $child_exit; 2682 my $line; 2683 my $full_line; 2684 my $bug = 0; 2685 my $bug_ignored = 0; 2686 2687 my $start_time = time; 2688 2689 wait_for_monitor 1; 2690 2691 doprint "run test $run_test\n"; 2692 2693 $child_done = 0; 2694 2695 $SIG{CHLD} = qw(child_finished); 2696 2697 $child_pid = fork; 2698 2699 child_run_test if (!$child_pid); 2700 2701 $full_line = ""; 2702 2703 do { 2704 $line = wait_for_input($monitor_fp, 1); 2705 if (defined($line)) { 2706 2707 # we are not guaranteed to get a full line 2708 $full_line .= $line; 2709 doprint $line; 2710 2711 if ($full_line =~ /call trace:/i) { 2712 if ($ignore_errors) { 2713 $bug_ignored = 1; 2714 } else { 2715 $bug = 1; 2716 } 2717 } 2718 2719 if ($full_line =~ /Kernel panic -/) { 2720 $bug = 1; 2721 } 2722 2723 if ($line =~ /\n/) { 2724 $full_line = ""; 2725 } 2726 } 2727 } while (!$child_done && !$bug); 2728 2729 if (!$bug && $bug_ignored) { 2730 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; 2731 } 2732 2733 if ($bug) { 2734 my $failure_start = time; 2735 my $now; 2736 do { 2737 $line = wait_for_input($monitor_fp, 1); 2738 if (defined($line)) { 2739 doprint $line; 2740 } 2741 $now = time; 2742 if ($now - $failure_start >= $stop_after_failure) { 2743 last; 2744 } 2745 } while (defined($line)); 2746 2747 doprint "Detected kernel crash!\n"; 2748 # kill the child with extreme prejudice 2749 kill 9, $child_pid; 2750 } 2751 2752 waitpid $child_pid, 0; 2753 $child_exit = $? >> 8; 2754 2755 my $end_time = time; 2756 $test_time = $end_time - $start_time; 2757 2758 if (!$bug && $in_bisect) { 2759 if (defined($bisect_ret_good)) { 2760 if ($child_exit == $bisect_ret_good) { 2761 return 1; 2762 } 2763 } 2764 if (defined($bisect_ret_skip)) { 2765 if ($child_exit == $bisect_ret_skip) { 2766 return -1; 2767 } 2768 } 2769 if (defined($bisect_ret_abort)) { 2770 if ($child_exit == $bisect_ret_abort) { 2771 fail "test abort" and return -2; 2772 } 2773 } 2774 if (defined($bisect_ret_bad)) { 2775 if ($child_exit == $bisect_ret_skip) { 2776 return 0; 2777 } 2778 } 2779 if (defined($bisect_ret_default)) { 2780 if ($bisect_ret_default eq "good") { 2781 return 1; 2782 } elsif ($bisect_ret_default eq "bad") { 2783 return 0; 2784 } elsif ($bisect_ret_default eq "skip") { 2785 return -1; 2786 } elsif ($bisect_ret_default eq "abort") { 2787 return -2; 2788 } else { 2789 fail "unknown default action: $bisect_ret_default" 2790 and return -2; 2791 } 2792 } 2793 } 2794 2795 if ($bug || $child_exit) { 2796 return 0 if $in_bisect; 2797 fail "test failed" and return 0; 2798 } 2799 return 1; 2800} 2801 2802sub run_git_bisect { 2803 my ($command) = @_; 2804 2805 doprint "$command ... "; 2806 2807 my $output = `$command 2>&1`; 2808 my $ret = $?; 2809 2810 logit $output; 2811 2812 if ($ret) { 2813 doprint "FAILED\n"; 2814 dodie "Failed to git bisect"; 2815 } 2816 2817 doprint "SUCCESS\n"; 2818 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 2819 doprint "$1 [$2]\n"; 2820 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 2821 $bisect_bad_commit = $1; 2822 doprint "Found bad commit... $1\n"; 2823 return 0; 2824 } else { 2825 # we already logged it, just print it now. 2826 print $output; 2827 } 2828 2829 return 1; 2830} 2831 2832sub bisect_reboot { 2833 doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 2834 reboot_to_good $bisect_sleep_time; 2835} 2836 2837# returns 1 on success, 0 on failure, -1 on skip 2838sub run_bisect_test { 2839 my ($type, $buildtype) = @_; 2840 2841 my $failed = 0; 2842 my $result; 2843 my $output; 2844 my $ret; 2845 2846 $in_bisect = 1; 2847 2848 build $buildtype or $failed = 1; 2849 2850 if ($type ne "build") { 2851 if ($failed && $bisect_skip) { 2852 $in_bisect = 0; 2853 return -1; 2854 } 2855 dodie "Failed on build" if $failed; 2856 2857 # Now boot the box 2858 start_monitor_and_install or $failed = 1; 2859 2860 if ($type ne "boot") { 2861 if ($failed && $bisect_skip) { 2862 end_monitor; 2863 bisect_reboot; 2864 $in_bisect = 0; 2865 return -1; 2866 } 2867 dodie "Failed on boot" if $failed; 2868 2869 do_run_test or $failed = 1; 2870 } 2871 end_monitor; 2872 } 2873 2874 if ($failed) { 2875 $result = 0; 2876 } else { 2877 $result = 1; 2878 } 2879 2880 # reboot the box to a kernel we can ssh to 2881 if ($type ne "build") { 2882 bisect_reboot; 2883 } 2884 $in_bisect = 0; 2885 2886 return $result; 2887} 2888 2889sub run_bisect { 2890 my ($type) = @_; 2891 my $buildtype = "oldconfig"; 2892 2893 # We should have a minconfig to use? 2894 if (defined($minconfig)) { 2895 $buildtype = "useconfig:$minconfig"; 2896 } 2897 2898 # If the user sets bisect_tries to less than 1, then no tries 2899 # is a success. 2900 my $ret = 1; 2901 2902 # Still let the user manually decide that though. 2903 if ($bisect_tries < 1 && $bisect_manual) { 2904 $ret = answer_bisect; 2905 } 2906 2907 for (my $i = 0; $i < $bisect_tries; $i++) { 2908 if ($bisect_tries > 1) { 2909 my $t = $i + 1; 2910 doprint("Running bisect trial $t of $bisect_tries:\n"); 2911 } 2912 $ret = run_bisect_test $type, $buildtype; 2913 2914 if ($bisect_manual) { 2915 $ret = answer_bisect; 2916 } 2917 2918 last if (!$ret); 2919 } 2920 2921 # Are we looking for where it worked, not failed? 2922 if ($reverse_bisect && $ret >= 0) { 2923 $ret = !$ret; 2924 } 2925 2926 if ($ret > 0) { 2927 return "good"; 2928 } elsif ($ret == 0) { 2929 return "bad"; 2930 } elsif ($bisect_skip) { 2931 doprint "HIT A BAD COMMIT ... SKIPPING\n"; 2932 return "skip"; 2933 } 2934} 2935 2936sub update_bisect_replay { 2937 my $tmp_log = "$tmpdir/ktest_bisect_log"; 2938 run_command "git bisect log > $tmp_log" or 2939 dodie "can't create bisect log"; 2940 return $tmp_log; 2941} 2942 2943sub bisect { 2944 my ($i) = @_; 2945 2946 my $result; 2947 2948 dodie "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good)); 2949 dodie "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad)); 2950 dodie "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type)); 2951 2952 my $good = $bisect_good; 2953 my $bad = $bisect_bad; 2954 my $type = $bisect_type; 2955 my $start = $bisect_start; 2956 my $replay = $bisect_replay; 2957 my $start_files = $bisect_files; 2958 2959 if (defined($start_files)) { 2960 $start_files = " -- " . $start_files; 2961 } else { 2962 $start_files = ""; 2963 } 2964 2965 # convert to true sha1's 2966 $good = get_sha1($good); 2967 $bad = get_sha1($bad); 2968 2969 if (defined($bisect_reverse) && $bisect_reverse == 1) { 2970 doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 2971 $reverse_bisect = 1; 2972 } else { 2973 $reverse_bisect = 0; 2974 } 2975 2976 # Can't have a test without having a test to run 2977 if ($type eq "test" && !defined($run_test)) { 2978 $type = "boot"; 2979 } 2980 2981 # Check if a bisect was running 2982 my $bisect_start_file = "$builddir/.git/BISECT_START"; 2983 2984 my $check = $bisect_check; 2985 my $do_check = defined($check) && $check ne "0"; 2986 2987 if ( -f $bisect_start_file ) { 2988 print "Bisect in progress found\n"; 2989 if ($do_check) { 2990 print " If you say yes, then no checks of good or bad will be done\n"; 2991 } 2992 if (defined($replay)) { 2993 print "** BISECT_REPLAY is defined in config file **"; 2994 print " Ignore config option and perform new git bisect log?\n"; 2995 if (read_ync " (yes, no, or cancel) ") { 2996 $replay = update_bisect_replay; 2997 $do_check = 0; 2998 } 2999 } elsif (read_yn "read git log and continue?") { 3000 $replay = update_bisect_replay; 3001 $do_check = 0; 3002 } 3003 } 3004 3005 if ($do_check) { 3006 3007 # get current HEAD 3008 my $head = get_sha1("HEAD"); 3009 3010 if ($check ne "good") { 3011 doprint "TESTING BISECT BAD [$bad]\n"; 3012 run_command "git checkout $bad" or 3013 dodie "Failed to checkout $bad"; 3014 3015 $result = run_bisect $type; 3016 3017 if ($result ne "bad") { 3018 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 3019 } 3020 } 3021 3022 if ($check ne "bad") { 3023 doprint "TESTING BISECT GOOD [$good]\n"; 3024 run_command "git checkout $good" or 3025 dodie "Failed to checkout $good"; 3026 3027 $result = run_bisect $type; 3028 3029 if ($result ne "good") { 3030 fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 3031 } 3032 } 3033 3034 # checkout where we started 3035 run_command "git checkout $head" or 3036 dodie "Failed to checkout $head"; 3037 } 3038 3039 run_command "git bisect start$start_files" or 3040 dodie "could not start bisect"; 3041 3042 if (defined($replay)) { 3043 run_command "git bisect replay $replay" or 3044 dodie "failed to run replay"; 3045 } else { 3046 3047 run_command "git bisect good $good" or 3048 dodie "could not set bisect good to $good"; 3049 3050 run_git_bisect "git bisect bad $bad" or 3051 dodie "could not set bisect bad to $bad"; 3052 3053 } 3054 3055 if (defined($start)) { 3056 run_command "git checkout $start" or 3057 dodie "failed to checkout $start"; 3058 } 3059 3060 my $test; 3061 do { 3062 $result = run_bisect $type; 3063 $test = run_git_bisect "git bisect $result"; 3064 print_times; 3065 } while ($test); 3066 3067 run_command "git bisect log" or 3068 dodie "could not capture git bisect log"; 3069 3070 run_command "git bisect reset" or 3071 dodie "could not reset git bisect"; 3072 3073 doprint "Bad commit was [$bisect_bad_commit]\n"; 3074 3075 success $i; 3076} 3077 3078# config_ignore holds the configs that were set (or unset) for 3079# a good config and we will ignore these configs for the rest 3080# of a config bisect. These configs stay as they were. 3081my %config_ignore; 3082 3083# config_set holds what all configs were set as. 3084my %config_set; 3085 3086# config_off holds the set of configs that the bad config had disabled. 3087# We need to record them and set them in the .config when running 3088# olddefconfig, because olddefconfig keeps the defaults. 3089my %config_off; 3090 3091# config_off_tmp holds a set of configs to turn off for now 3092my @config_off_tmp; 3093 3094# config_list is the set of configs that are being tested 3095my %config_list; 3096my %null_config; 3097 3098my %dependency; 3099 3100sub assign_configs { 3101 my ($hash, $config) = @_; 3102 3103 doprint "Reading configs from $config\n"; 3104 3105 open (IN, $config) 3106 or dodie "Failed to read $config"; 3107 3108 while (<IN>) { 3109 chomp; 3110 if (/^((CONFIG\S*)=.*)/) { 3111 ${$hash}{$2} = $1; 3112 } elsif (/^(# (CONFIG\S*) is not set)/) { 3113 ${$hash}{$2} = $1; 3114 } 3115 } 3116 3117 close(IN); 3118} 3119 3120sub process_config_ignore { 3121 my ($config) = @_; 3122 3123 assign_configs \%config_ignore, $config; 3124} 3125 3126sub get_dependencies { 3127 my ($config) = @_; 3128 3129 my $arr = $dependency{$config}; 3130 if (!defined($arr)) { 3131 return (); 3132 } 3133 3134 my @deps = @{$arr}; 3135 3136 foreach my $dep (@{$arr}) { 3137 print "ADD DEP $dep\n"; 3138 @deps = (@deps, get_dependencies $dep); 3139 } 3140 3141 return @deps; 3142} 3143 3144sub save_config { 3145 my ($pc, $file) = @_; 3146 3147 my %configs = %{$pc}; 3148 3149 doprint "Saving configs into $file\n"; 3150 3151 open(OUT, ">$file") or dodie "Can not write to $file"; 3152 3153 foreach my $config (keys %configs) { 3154 print OUT "$configs{$config}\n"; 3155 } 3156 close(OUT); 3157} 3158 3159sub create_config { 3160 my ($name, $pc) = @_; 3161 3162 doprint "Creating old config from $name configs\n"; 3163 3164 save_config $pc, $output_config; 3165 3166 make_oldconfig; 3167} 3168 3169sub run_config_bisect_test { 3170 my ($type) = @_; 3171 3172 my $ret = run_bisect_test $type, "oldconfig"; 3173 3174 if ($bisect_manual) { 3175 $ret = answer_bisect; 3176 } 3177 3178 return $ret; 3179} 3180 3181sub config_bisect_end { 3182 my ($good, $bad) = @_; 3183 my $diffexec = "diff -u"; 3184 3185 if (-f "$builddir/scripts/diffconfig") { 3186 $diffexec = "$builddir/scripts/diffconfig"; 3187 } 3188 doprint "\n\n***************************************\n"; 3189 doprint "No more config bisecting possible.\n"; 3190 run_command "$diffexec $good $bad", 1; 3191 doprint "***************************************\n\n"; 3192} 3193 3194sub run_config_bisect { 3195 my ($good, $bad, $last_result) = @_; 3196 my $reset = ""; 3197 my $cmd; 3198 my $ret; 3199 3200 if (!length($last_result)) { 3201 $reset = "-r"; 3202 } 3203 run_command "$config_bisect_exec $reset -b $outputdir $good $bad $last_result", 1; 3204 3205 # config-bisect returns: 3206 # 0 if there is more to bisect 3207 # 1 for finding a good config 3208 # 2 if it can not find any more configs 3209 # -1 (255) on error 3210 if ($run_command_status) { 3211 return $run_command_status; 3212 } 3213 3214 $ret = run_config_bisect_test $config_bisect_type; 3215 if ($ret) { 3216 doprint "NEW GOOD CONFIG\n"; 3217 # Return 3 for good config 3218 return 3; 3219 } else { 3220 doprint "NEW BAD CONFIG\n"; 3221 # Return 4 for bad config 3222 return 4; 3223 } 3224} 3225 3226sub config_bisect { 3227 my ($i) = @_; 3228 3229 my $good_config; 3230 my $bad_config; 3231 3232 my $type = $config_bisect_type; 3233 my $ret; 3234 3235 $bad_config = $config_bisect; 3236 3237 if (defined($config_bisect_good)) { 3238 $good_config = $config_bisect_good; 3239 } elsif (defined($minconfig)) { 3240 $good_config = $minconfig; 3241 } else { 3242 doprint "No config specified, checking if defconfig works"; 3243 $ret = run_bisect_test $type, "defconfig"; 3244 if (!$ret) { 3245 fail "Have no good config to compare with, please set CONFIG_BISECT_GOOD"; 3246 return 1; 3247 } 3248 $good_config = $output_config; 3249 } 3250 3251 if (!defined($config_bisect_exec)) { 3252 # First check the location that ktest.pl ran 3253 my @locations = ( "$pwd/config-bisect.pl", 3254 "$dirname/config-bisect.pl", 3255 "$builddir/tools/testing/ktest/config-bisect.pl", 3256 undef ); 3257 foreach my $loc (@locations) { 3258 doprint "loc = $loc\n"; 3259 $config_bisect_exec = $loc; 3260 last if (defined($config_bisect_exec && -x $config_bisect_exec)); 3261 } 3262 if (!defined($config_bisect_exec)) { 3263 fail "Could not find an executable config-bisect.pl\n", 3264 " Set CONFIG_BISECT_EXEC to point to config-bisect.pl"; 3265 return 1; 3266 } 3267 } 3268 3269 # we don't want min configs to cause issues here. 3270 doprint "Disabling 'MIN_CONFIG' for this test\n"; 3271 undef $minconfig; 3272 3273 my %good_configs; 3274 my %bad_configs; 3275 my %tmp_configs; 3276 3277 if (-f "$tmpdir/good_config.tmp" || -f "$tmpdir/bad_config.tmp") { 3278 if (read_yn "Interrupted config-bisect. Continue (n - will start new)?") { 3279 if (-f "$tmpdir/good_config.tmp") { 3280 $good_config = "$tmpdir/good_config.tmp"; 3281 } else { 3282 $good_config = "$tmpdir/good_config"; 3283 } 3284 if (-f "$tmpdir/bad_config.tmp") { 3285 $bad_config = "$tmpdir/bad_config.tmp"; 3286 } else { 3287 $bad_config = "$tmpdir/bad_config"; 3288 } 3289 } 3290 } 3291 doprint "Run good configs through make oldconfig\n"; 3292 assign_configs \%tmp_configs, $good_config; 3293 create_config "$good_config", \%tmp_configs; 3294 $good_config = "$tmpdir/good_config"; 3295 system("cp $output_config $good_config") == 0 or dodie "cp good config"; 3296 3297 doprint "Run bad configs through make oldconfig\n"; 3298 assign_configs \%tmp_configs, $bad_config; 3299 create_config "$bad_config", \%tmp_configs; 3300 $bad_config = "$tmpdir/bad_config"; 3301 system("cp $output_config $bad_config") == 0 or dodie "cp bad config"; 3302 3303 if (defined($config_bisect_check) && $config_bisect_check ne "0") { 3304 if ($config_bisect_check ne "good") { 3305 doprint "Testing bad config\n"; 3306 3307 $ret = run_bisect_test $type, "useconfig:$bad_config"; 3308 if ($ret) { 3309 fail "Bad config succeeded when expected to fail!"; 3310 return 0; 3311 } 3312 } 3313 if ($config_bisect_check ne "bad") { 3314 doprint "Testing good config\n"; 3315 3316 $ret = run_bisect_test $type, "useconfig:$good_config"; 3317 if (!$ret) { 3318 fail "Good config failed when expected to succeed!"; 3319 return 0; 3320 } 3321 } 3322 } 3323 3324 my $last_run = ""; 3325 3326 do { 3327 $ret = run_config_bisect $good_config, $bad_config, $last_run; 3328 if ($ret == 3) { 3329 $last_run = "good"; 3330 } elsif ($ret == 4) { 3331 $last_run = "bad"; 3332 } 3333 print_times; 3334 } while ($ret == 3 || $ret == 4); 3335 3336 if ($ret == 2) { 3337 config_bisect_end "$good_config.tmp", "$bad_config.tmp"; 3338 } 3339 3340 return $ret if ($ret < 0); 3341 3342 success $i; 3343} 3344 3345sub patchcheck_reboot { 3346 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; 3347 reboot_to_good $patchcheck_sleep_time; 3348} 3349 3350sub patchcheck { 3351 my ($i) = @_; 3352 3353 dodie "PATCHCHECK_START[$i] not defined\n" 3354 if (!defined($patchcheck_start)); 3355 dodie "PATCHCHECK_TYPE[$i] not defined\n" 3356 if (!defined($patchcheck_type)); 3357 3358 my $start = $patchcheck_start; 3359 3360 my $cherry = $patchcheck_cherry; 3361 if (!defined($cherry)) { 3362 $cherry = 0; 3363 } 3364 3365 my $end = "HEAD"; 3366 if (defined($patchcheck_end)) { 3367 $end = $patchcheck_end; 3368 } elsif ($cherry) { 3369 dodie "PATCHCHECK_END must be defined with PATCHCHECK_CHERRY\n"; 3370 } 3371 3372 # Get the true sha1's since we can use things like HEAD~3 3373 $start = get_sha1($start); 3374 $end = get_sha1($end); 3375 3376 my $type = $patchcheck_type; 3377 3378 # Can't have a test without having a test to run 3379 if ($type eq "test" && !defined($run_test)) { 3380 $type = "boot"; 3381 } 3382 3383 if ($cherry) { 3384 open (IN, "git cherry -v $start $end|") or 3385 dodie "could not get git list"; 3386 } else { 3387 open (IN, "git log --pretty=oneline $end|") or 3388 dodie "could not get git list"; 3389 } 3390 3391 my @list; 3392 3393 while (<IN>) { 3394 chomp; 3395 # git cherry adds a '+' we want to remove 3396 s/^\+ //; 3397 $list[$#list+1] = $_; 3398 last if (/^$start/); 3399 } 3400 close(IN); 3401 3402 if (!$cherry) { 3403 if ($list[$#list] !~ /^$start/) { 3404 fail "SHA1 $start not found"; 3405 } 3406 3407 # go backwards in the list 3408 @list = reverse @list; 3409 } 3410 3411 doprint("Going to test the following commits:\n"); 3412 foreach my $l (@list) { 3413 doprint "$l\n"; 3414 } 3415 3416 my $save_clean = $noclean; 3417 my %ignored_warnings; 3418 3419 if (defined($ignore_warnings)) { 3420 foreach my $sha1 (split /\s+/, $ignore_warnings) { 3421 $ignored_warnings{$sha1} = 1; 3422 } 3423 } 3424 3425 $in_patchcheck = 1; 3426 foreach my $item (@list) { 3427 my $sha1 = $item; 3428 $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 3429 3430 doprint "\nProcessing commit \"$item\"\n\n"; 3431 3432 run_command "git checkout $sha1" or 3433 dodie "Failed to checkout $sha1"; 3434 3435 # only clean on the first and last patch 3436 if ($item eq $list[0] || 3437 $item eq $list[$#list]) { 3438 $noclean = $save_clean; 3439 } else { 3440 $noclean = 1; 3441 } 3442 3443 if (defined($minconfig)) { 3444 build "useconfig:$minconfig" or return 0; 3445 } else { 3446 # ?? no config to use? 3447 build "oldconfig" or return 0; 3448 } 3449 3450 # No need to do per patch checking if warnings file exists 3451 if (!defined($warnings_file) && !defined($ignored_warnings{$sha1})) { 3452 check_patch_buildlog $sha1 or return 0; 3453 } 3454 3455 check_buildlog or return 0; 3456 3457 next if ($type eq "build"); 3458 3459 my $failed = 0; 3460 3461 start_monitor_and_install or $failed = 1; 3462 3463 if (!$failed && $type ne "boot"){ 3464 do_run_test or $failed = 1; 3465 } 3466 end_monitor; 3467 if ($failed) { 3468 print_times; 3469 return 0; 3470 } 3471 patchcheck_reboot; 3472 print_times; 3473 } 3474 $in_patchcheck = 0; 3475 success $i; 3476 3477 return 1; 3478} 3479 3480my %depends; 3481my %depcount; 3482my $iflevel = 0; 3483my @ifdeps; 3484 3485# prevent recursion 3486my %read_kconfigs; 3487 3488sub add_dep { 3489 # $config depends on $dep 3490 my ($config, $dep) = @_; 3491 3492 if (defined($depends{$config})) { 3493 $depends{$config} .= " " . $dep; 3494 } else { 3495 $depends{$config} = $dep; 3496 } 3497 3498 # record the number of configs depending on $dep 3499 if (defined $depcount{$dep}) { 3500 $depcount{$dep}++; 3501 } else { 3502 $depcount{$dep} = 1; 3503 } 3504} 3505 3506# taken from streamline_config.pl 3507sub read_kconfig { 3508 my ($kconfig) = @_; 3509 3510 my $state = "NONE"; 3511 my $config; 3512 my @kconfigs; 3513 3514 my $cont = 0; 3515 my $line; 3516 3517 3518 if (! -f $kconfig) { 3519 doprint "file $kconfig does not exist, skipping\n"; 3520 return; 3521 } 3522 3523 open(KIN, "$kconfig") 3524 or dodie "Can't open $kconfig"; 3525 while (<KIN>) { 3526 chomp; 3527 3528 # Make sure that lines ending with \ continue 3529 if ($cont) { 3530 $_ = $line . " " . $_; 3531 } 3532 3533 if (s/\\$//) { 3534 $cont = 1; 3535 $line = $_; 3536 next; 3537 } 3538 3539 $cont = 0; 3540 3541 # collect any Kconfig sources 3542 if (/^source\s*"(.*)"/) { 3543 $kconfigs[$#kconfigs+1] = $1; 3544 } 3545 3546 # configs found 3547 if (/^\s*(menu)?config\s+(\S+)\s*$/) { 3548 $state = "NEW"; 3549 $config = $2; 3550 3551 for (my $i = 0; $i < $iflevel; $i++) { 3552 add_dep $config, $ifdeps[$i]; 3553 } 3554 3555 # collect the depends for the config 3556 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { 3557 3558 add_dep $config, $1; 3559 3560 # Get the configs that select this config 3561 } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) { 3562 3563 # selected by depends on config 3564 add_dep $1, $config; 3565 3566 # Check for if statements 3567 } elsif (/^if\s+(.*\S)\s*$/) { 3568 my $deps = $1; 3569 # remove beginning and ending non text 3570 $deps =~ s/^[^a-zA-Z0-9_]*//; 3571 $deps =~ s/[^a-zA-Z0-9_]*$//; 3572 3573 my @deps = split /[^a-zA-Z0-9_]+/, $deps; 3574 3575 $ifdeps[$iflevel++] = join ':', @deps; 3576 3577 } elsif (/^endif/) { 3578 3579 $iflevel-- if ($iflevel); 3580 3581 # stop on "help" 3582 } elsif (/^\s*help\s*$/) { 3583 $state = "NONE"; 3584 } 3585 } 3586 close(KIN); 3587 3588 # read in any configs that were found. 3589 foreach $kconfig (@kconfigs) { 3590 if (!defined($read_kconfigs{$kconfig})) { 3591 $read_kconfigs{$kconfig} = 1; 3592 read_kconfig("$builddir/$kconfig"); 3593 } 3594 } 3595} 3596 3597sub read_depends { 3598 # find out which arch this is by the kconfig file 3599 open (IN, $output_config) 3600 or dodie "Failed to read $output_config"; 3601 my $arch; 3602 while (<IN>) { 3603 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) { 3604 $arch = $1; 3605 last; 3606 } 3607 } 3608 close IN; 3609 3610 if (!defined($arch)) { 3611 doprint "Could not find arch from config file\n"; 3612 doprint "no dependencies used\n"; 3613 return; 3614 } 3615 3616 # arch is really the subarch, we need to know 3617 # what directory to look at. 3618 if ($arch eq "i386" || $arch eq "x86_64") { 3619 $arch = "x86"; 3620 } 3621 3622 my $kconfig = "$builddir/arch/$arch/Kconfig"; 3623 3624 if (! -f $kconfig && $arch =~ /\d$/) { 3625 my $orig = $arch; 3626 # some subarchs have numbers, truncate them 3627 $arch =~ s/\d*$//; 3628 $kconfig = "$builddir/arch/$arch/Kconfig"; 3629 if (! -f $kconfig) { 3630 doprint "No idea what arch dir $orig is for\n"; 3631 doprint "no dependencies used\n"; 3632 return; 3633 } 3634 } 3635 3636 read_kconfig($kconfig); 3637} 3638 3639sub make_new_config { 3640 my @configs = @_; 3641 3642 open (OUT, ">$output_config") 3643 or dodie "Failed to write $output_config"; 3644 3645 foreach my $config (@configs) { 3646 print OUT "$config\n"; 3647 } 3648 close OUT; 3649} 3650 3651sub chomp_config { 3652 my ($config) = @_; 3653 3654 $config =~ s/CONFIG_//; 3655 3656 return $config; 3657} 3658 3659sub get_depends { 3660 my ($dep) = @_; 3661 3662 my $kconfig = chomp_config $dep; 3663 3664 $dep = $depends{"$kconfig"}; 3665 3666 # the dep string we have saves the dependencies as they 3667 # were found, including expressions like ! && ||. We 3668 # want to split this out into just an array of configs. 3669 3670 my $valid = "A-Za-z_0-9"; 3671 3672 my @configs; 3673 3674 while ($dep =~ /[$valid]/) { 3675 3676 if ($dep =~ /^[^$valid]*([$valid]+)/) { 3677 my $conf = "CONFIG_" . $1; 3678 3679 $configs[$#configs + 1] = $conf; 3680 3681 $dep =~ s/^[^$valid]*[$valid]+//; 3682 } else { 3683 dodie "this should never happen"; 3684 } 3685 } 3686 3687 return @configs; 3688} 3689 3690my %min_configs; 3691my %keep_configs; 3692my %save_configs; 3693my %processed_configs; 3694my %nochange_config; 3695 3696sub test_this_config { 3697 my ($config) = @_; 3698 3699 my $found; 3700 3701 # if we already processed this config, skip it 3702 if (defined($processed_configs{$config})) { 3703 return undef; 3704 } 3705 $processed_configs{$config} = 1; 3706 3707 # if this config failed during this round, skip it 3708 if (defined($nochange_config{$config})) { 3709 return undef; 3710 } 3711 3712 my $kconfig = chomp_config $config; 3713 3714 # Test dependencies first 3715 if (defined($depends{"$kconfig"})) { 3716 my @parents = get_depends $config; 3717 foreach my $parent (@parents) { 3718 # if the parent is in the min config, check it first 3719 next if (!defined($min_configs{$parent})); 3720 $found = test_this_config($parent); 3721 if (defined($found)) { 3722 return $found; 3723 } 3724 } 3725 } 3726 3727 # Remove this config from the list of configs 3728 # do a make olddefconfig and then read the resulting 3729 # .config to make sure it is missing the config that 3730 # we had before 3731 my %configs = %min_configs; 3732 delete $configs{$config}; 3733 make_new_config ((values %configs), (values %keep_configs)); 3734 make_oldconfig; 3735 undef %configs; 3736 assign_configs \%configs, $output_config; 3737 3738 if (!defined($configs{$config}) || $configs{$config} =~ /^#/) { 3739 return $config; 3740 } 3741 3742 doprint "disabling config $config did not change .config\n"; 3743 3744 $nochange_config{$config} = 1; 3745 3746 return undef; 3747} 3748 3749sub make_min_config { 3750 my ($i) = @_; 3751 3752 my $type = $minconfig_type; 3753 if ($type ne "boot" && $type ne "test") { 3754 fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" . 3755 " make_min_config works only with 'boot' and 'test'\n" and return; 3756 } 3757 3758 if (!defined($output_minconfig)) { 3759 fail "OUTPUT_MIN_CONFIG not defined" and return; 3760 } 3761 3762 # If output_minconfig exists, and the start_minconfig 3763 # came from min_config, than ask if we should use 3764 # that instead. 3765 if (-f $output_minconfig && !$start_minconfig_defined) { 3766 print "$output_minconfig exists\n"; 3767 if (!defined($use_output_minconfig)) { 3768 if (read_yn " Use it as minconfig?") { 3769 $start_minconfig = $output_minconfig; 3770 } 3771 } elsif ($use_output_minconfig > 0) { 3772 doprint "Using $output_minconfig as MIN_CONFIG\n"; 3773 $start_minconfig = $output_minconfig; 3774 } else { 3775 doprint "Set to still use MIN_CONFIG as starting point\n"; 3776 } 3777 } 3778 3779 if (!defined($start_minconfig)) { 3780 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; 3781 } 3782 3783 my $temp_config = "$tmpdir/temp_config"; 3784 3785 # First things first. We build an allnoconfig to find 3786 # out what the defaults are that we can't touch. 3787 # Some are selections, but we really can't handle selections. 3788 3789 my $save_minconfig = $minconfig; 3790 undef $minconfig; 3791 3792 run_command "$make allnoconfig" or return 0; 3793 3794 read_depends; 3795 3796 process_config_ignore $output_config; 3797 3798 undef %save_configs; 3799 undef %min_configs; 3800 3801 if (defined($ignore_config)) { 3802 # make sure the file exists 3803 `touch $ignore_config`; 3804 assign_configs \%save_configs, $ignore_config; 3805 } 3806 3807 %keep_configs = %save_configs; 3808 3809 doprint "Load initial configs from $start_minconfig\n"; 3810 3811 # Look at the current min configs, and save off all the 3812 # ones that were set via the allnoconfig 3813 assign_configs \%min_configs, $start_minconfig; 3814 3815 my @config_keys = keys %min_configs; 3816 3817 # All configs need a depcount 3818 foreach my $config (@config_keys) { 3819 my $kconfig = chomp_config $config; 3820 if (!defined $depcount{$kconfig}) { 3821 $depcount{$kconfig} = 0; 3822 } 3823 } 3824 3825 # Remove anything that was set by the make allnoconfig 3826 # we shouldn't need them as they get set for us anyway. 3827 foreach my $config (@config_keys) { 3828 # Remove anything in the ignore_config 3829 if (defined($keep_configs{$config})) { 3830 my $file = $ignore_config; 3831 $file =~ s,.*/(.*?)$,$1,; 3832 doprint "$config set by $file ... ignored\n"; 3833 delete $min_configs{$config}; 3834 next; 3835 } 3836 # But make sure the settings are the same. If a min config 3837 # sets a selection, we do not want to get rid of it if 3838 # it is not the same as what we have. Just move it into 3839 # the keep configs. 3840 if (defined($config_ignore{$config})) { 3841 if ($config_ignore{$config} ne $min_configs{$config}) { 3842 doprint "$config is in allnoconfig as '$config_ignore{$config}'"; 3843 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n"; 3844 $keep_configs{$config} = $min_configs{$config}; 3845 } else { 3846 doprint "$config set by allnoconfig ... ignored\n"; 3847 } 3848 delete $min_configs{$config}; 3849 } 3850 } 3851 3852 my $done = 0; 3853 my $take_two = 0; 3854 3855 while (!$done) { 3856 3857 my $config; 3858 my $found; 3859 3860 # Now disable each config one by one and do a make oldconfig 3861 # till we find a config that changes our list. 3862 3863 my @test_configs = keys %min_configs; 3864 3865 # Sort keys by who is most dependent on 3866 @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} } 3867 @test_configs ; 3868 3869 # Put configs that did not modify the config at the end. 3870 my $reset = 1; 3871 for (my $i = 0; $i < $#test_configs; $i++) { 3872 if (!defined($nochange_config{$test_configs[0]})) { 3873 $reset = 0; 3874 last; 3875 } 3876 # This config didn't change the .config last time. 3877 # Place it at the end 3878 my $config = shift @test_configs; 3879 push @test_configs, $config; 3880 } 3881 3882 # if every test config has failed to modify the .config file 3883 # in the past, then reset and start over. 3884 if ($reset) { 3885 undef %nochange_config; 3886 } 3887 3888 undef %processed_configs; 3889 3890 foreach my $config (@test_configs) { 3891 3892 $found = test_this_config $config; 3893 3894 last if (defined($found)); 3895 3896 # oh well, try another config 3897 } 3898 3899 if (!defined($found)) { 3900 # we could have failed due to the nochange_config hash 3901 # reset and try again 3902 if (!$take_two) { 3903 undef %nochange_config; 3904 $take_two = 1; 3905 next; 3906 } 3907 doprint "No more configs found that we can disable\n"; 3908 $done = 1; 3909 last; 3910 } 3911 $take_two = 0; 3912 3913 $config = $found; 3914 3915 doprint "Test with $config disabled\n"; 3916 3917 # set in_bisect to keep build and monitor from dieing 3918 $in_bisect = 1; 3919 3920 my $failed = 0; 3921 build "oldconfig" or $failed = 1; 3922 if (!$failed) { 3923 start_monitor_and_install or $failed = 1; 3924 3925 if ($type eq "test" && !$failed) { 3926 do_run_test or $failed = 1; 3927 } 3928 3929 end_monitor; 3930 } 3931 3932 $in_bisect = 0; 3933 3934 if ($failed) { 3935 doprint "$min_configs{$config} is needed to boot the box... keeping\n"; 3936 # this config is needed, add it to the ignore list. 3937 $keep_configs{$config} = $min_configs{$config}; 3938 $save_configs{$config} = $min_configs{$config}; 3939 delete $min_configs{$config}; 3940 3941 # update new ignore configs 3942 if (defined($ignore_config)) { 3943 open (OUT, ">$temp_config") 3944 or dodie "Can't write to $temp_config"; 3945 foreach my $config (keys %save_configs) { 3946 print OUT "$save_configs{$config}\n"; 3947 } 3948 close OUT; 3949 run_command "mv $temp_config $ignore_config" or 3950 dodie "failed to copy update to $ignore_config"; 3951 } 3952 3953 } else { 3954 # We booted without this config, remove it from the minconfigs. 3955 doprint "$config is not needed, disabling\n"; 3956 3957 delete $min_configs{$config}; 3958 3959 # Also disable anything that is not enabled in this config 3960 my %configs; 3961 assign_configs \%configs, $output_config; 3962 my @config_keys = keys %min_configs; 3963 foreach my $config (@config_keys) { 3964 if (!defined($configs{$config})) { 3965 doprint "$config is not set, disabling\n"; 3966 delete $min_configs{$config}; 3967 } 3968 } 3969 3970 # Save off all the current mandatory configs 3971 open (OUT, ">$temp_config") 3972 or dodie "Can't write to $temp_config"; 3973 foreach my $config (keys %keep_configs) { 3974 print OUT "$keep_configs{$config}\n"; 3975 } 3976 foreach my $config (keys %min_configs) { 3977 print OUT "$min_configs{$config}\n"; 3978 } 3979 close OUT; 3980 3981 run_command "mv $temp_config $output_minconfig" or 3982 dodie "failed to copy update to $output_minconfig"; 3983 } 3984 3985 doprint "Reboot and wait $sleep_time seconds\n"; 3986 reboot_to_good $sleep_time; 3987 } 3988 3989 success $i; 3990 return 1; 3991} 3992 3993sub make_warnings_file { 3994 my ($i) = @_; 3995 3996 if (!defined($warnings_file)) { 3997 dodie "Must define WARNINGS_FILE for make_warnings_file test"; 3998 } 3999 4000 if ($build_type eq "nobuild") { 4001 dodie "BUILD_TYPE can not be 'nobuild' for make_warnings_file test"; 4002 } 4003 4004 build $build_type or dodie "Failed to build"; 4005 4006 open(OUT, ">$warnings_file") or dodie "Can't create $warnings_file"; 4007 4008 open(IN, $buildlog) or dodie "Can't open $buildlog"; 4009 while (<IN>) { 4010 4011 # Some compilers use UTF-8 extended for quotes 4012 # for distcc heterogeneous systems, this causes issues 4013 s/$utf8_quote/'/g; 4014 4015 if (/$check_build_re/) { 4016 print OUT; 4017 } 4018 } 4019 close(IN); 4020 4021 close(OUT); 4022 4023 success $i; 4024} 4025 4026$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl [config-file]\n"; 4027 4028if ($#ARGV == 0) { 4029 $ktest_config = $ARGV[0]; 4030 if (! -f $ktest_config) { 4031 print "$ktest_config does not exist.\n"; 4032 if (!read_yn "Create it?") { 4033 exit 0; 4034 } 4035 } 4036} 4037 4038if (! -f $ktest_config) { 4039 $newconfig = 1; 4040 get_test_case; 4041 open(OUT, ">$ktest_config") or die "Can not create $ktest_config"; 4042 print OUT << "EOF" 4043# Generated by ktest.pl 4044# 4045 4046# PWD is a ktest.pl variable that will result in the process working 4047# directory that ktest.pl is executed in. 4048 4049# THIS_DIR is automatically assigned the PWD of the path that generated 4050# the config file. It is best to use this variable when assigning other 4051# directory paths within this directory. This allows you to easily 4052# move the test cases to other locations or to other machines. 4053# 4054THIS_DIR := $variable{"PWD"} 4055 4056# Define each test with TEST_START 4057# The config options below it will override the defaults 4058TEST_START 4059TEST_TYPE = $default{"TEST_TYPE"} 4060 4061DEFAULTS 4062EOF 4063; 4064 close(OUT); 4065} 4066read_config $ktest_config; 4067 4068if (defined($opt{"LOG_FILE"})) { 4069 $opt{"LOG_FILE"} = eval_option("LOG_FILE", $opt{"LOG_FILE"}, -1); 4070} 4071 4072# Append any configs entered in manually to the config file. 4073my @new_configs = keys %entered_configs; 4074if ($#new_configs >= 0) { 4075 print "\nAppending entered in configs to $ktest_config\n"; 4076 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; 4077 foreach my $config (@new_configs) { 4078 print OUT "$config = $entered_configs{$config}\n"; 4079 $opt{$config} = process_variables($entered_configs{$config}); 4080 } 4081} 4082 4083if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 4084 unlink $opt{"LOG_FILE"}; 4085} 4086 4087doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 4088 4089for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 4090 4091 if (!$i) { 4092 doprint "DEFAULT OPTIONS:\n"; 4093 } else { 4094 doprint "\nTEST $i OPTIONS"; 4095 if (defined($repeat_tests{$i})) { 4096 $repeat = $repeat_tests{$i}; 4097 doprint " ITERATE $repeat"; 4098 } 4099 doprint "\n"; 4100 } 4101 4102 foreach my $option (sort keys %opt) { 4103 4104 if ($option =~ /\[(\d+)\]$/) { 4105 next if ($i != $1); 4106 } else { 4107 next if ($i); 4108 } 4109 4110 doprint "$option = $opt{$option}\n"; 4111 } 4112} 4113 4114sub option_defined { 4115 my ($option) = @_; 4116 4117 if (defined($opt{$option}) && $opt{$option} !~ /^\s*$/) { 4118 return 1; 4119 } 4120 4121 return 0; 4122} 4123 4124sub __set_test_option { 4125 my ($name, $i) = @_; 4126 4127 my $option = "$name\[$i\]"; 4128 4129 if (option_defined($option)) { 4130 return $opt{$option}; 4131 } 4132 4133 foreach my $test (keys %repeat_tests) { 4134 if ($i >= $test && 4135 $i < $test + $repeat_tests{$test}) { 4136 $option = "$name\[$test\]"; 4137 if (option_defined($option)) { 4138 return $opt{$option}; 4139 } 4140 } 4141 } 4142 4143 if (option_defined($name)) { 4144 return $opt{$name}; 4145 } 4146 4147 return undef; 4148} 4149 4150sub set_test_option { 4151 my ($name, $i) = @_; 4152 4153 my $option = __set_test_option($name, $i); 4154 return $option if (!defined($option)); 4155 4156 return eval_option($name, $option, $i); 4157} 4158 4159sub find_mailer { 4160 my ($mailer) = @_; 4161 4162 my @paths = split /:/, $ENV{PATH}; 4163 4164 # sendmail is usually in /usr/sbin 4165 $paths[$#paths + 1] = "/usr/sbin"; 4166 4167 foreach my $path (@paths) { 4168 if (-x "$path/$mailer") { 4169 return $path; 4170 } 4171 } 4172 4173 return undef; 4174} 4175 4176sub do_send_mail { 4177 my ($subject, $message) = @_; 4178 4179 if (!defined($mail_path)) { 4180 # find the mailer 4181 $mail_path = find_mailer $mailer; 4182 if (!defined($mail_path)) { 4183 die "\nCan not find $mailer in PATH\n"; 4184 } 4185 } 4186 4187 if (!defined($mail_command)) { 4188 if ($mailer eq "mail" || $mailer eq "mailx") { 4189 $mail_command = "\$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO <<< \'\$MESSAGE\'"; 4190 } elsif ($mailer eq "sendmail" ) { 4191 $mail_command = "echo \'Subject: \$SUBJECT\n\n\$MESSAGE\' | \$MAIL_PATH/\$MAILER -t \$MAILTO"; 4192 } else { 4193 die "\nYour mailer: $mailer is not supported.\n"; 4194 } 4195 } 4196 4197 $mail_command =~ s/\$MAILER/$mailer/g; 4198 $mail_command =~ s/\$MAIL_PATH/$mail_path/g; 4199 $mail_command =~ s/\$MAILTO/$mailto/g; 4200 $mail_command =~ s/\$SUBJECT/$subject/g; 4201 $mail_command =~ s/\$MESSAGE/$message/g; 4202 4203 run_command $mail_command; 4204} 4205 4206sub send_email { 4207 4208 if (defined($mailto)) { 4209 if (!defined($mailer)) { 4210 doprint "No email sent: email or mailer not specified in config.\n"; 4211 return; 4212 } 4213 do_send_mail @_; 4214 } 4215} 4216 4217sub cancel_test { 4218 if ($email_when_canceled) { 4219 my $name = get_test_name; 4220 send_email("KTEST: Your [$name] test was cancelled", 4221 "Your test started at $script_start_time was cancelled: sig int"); 4222 } 4223 die "\nCaught Sig Int, test interrupted: $!\n" 4224} 4225 4226$SIG{INT} = qw(cancel_test); 4227 4228# First we need to do is the builds 4229for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 4230 4231 # Do not reboot on failing test options 4232 $no_reboot = 1; 4233 $reboot_success = 0; 4234 4235 $have_version = 0; 4236 4237 $iteration = $i; 4238 4239 $build_time = 0; 4240 $install_time = 0; 4241 $reboot_time = 0; 4242 $test_time = 0; 4243 4244 undef %force_config; 4245 4246 my $makecmd = set_test_option("MAKE_CMD", $i); 4247 4248 $outputdir = set_test_option("OUTPUT_DIR", $i); 4249 $builddir = set_test_option("BUILD_DIR", $i); 4250 4251 chdir $builddir || dodie "can't change directory to $builddir"; 4252 4253 if (!-d $outputdir) { 4254 mkpath($outputdir) or 4255 dodie "can't create $outputdir"; 4256 } 4257 4258 $make = "$makecmd O=$outputdir"; 4259 4260 # Load all the options into their mapped variable names 4261 foreach my $opt (keys %option_map) { 4262 ${$option_map{$opt}} = set_test_option($opt, $i); 4263 } 4264 4265 $start_minconfig_defined = 1; 4266 4267 # The first test may override the PRE_KTEST option 4268 if ($i == 1) { 4269 if (defined($pre_ktest)) { 4270 doprint "\n"; 4271 run_command $pre_ktest; 4272 } 4273 if ($email_when_started) { 4274 my $name = get_test_name; 4275 send_email("KTEST: Your [$name] test was started", 4276 "Your test was started on $script_start_time"); 4277 } 4278 } 4279 4280 # Any test can override the POST_KTEST option 4281 # The last test takes precedence. 4282 if (defined($post_ktest)) { 4283 $final_post_ktest = $post_ktest; 4284 } 4285 4286 if (!defined($start_minconfig)) { 4287 $start_minconfig_defined = 0; 4288 $start_minconfig = $minconfig; 4289 } 4290 4291 if (!-d $tmpdir) { 4292 mkpath($tmpdir) or 4293 dodie "can't create $tmpdir"; 4294 } 4295 4296 $ENV{"SSH_USER"} = $ssh_user; 4297 $ENV{"MACHINE"} = $machine; 4298 4299 $buildlog = "$tmpdir/buildlog-$machine"; 4300 $testlog = "$tmpdir/testlog-$machine"; 4301 $dmesg = "$tmpdir/dmesg-$machine"; 4302 $output_config = "$outputdir/.config"; 4303 4304 if (!$buildonly) { 4305 $target = "$ssh_user\@$machine"; 4306 if ($reboot_type eq "grub") { 4307 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 4308 } elsif ($reboot_type eq "grub2") { 4309 dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 4310 dodie "GRUB_FILE not defined" if (!defined($grub_file)); 4311 } elsif ($reboot_type eq "syslinux") { 4312 dodie "SYSLINUX_LABEL not defined" if (!defined($syslinux_label)); 4313 } 4314 } 4315 4316 my $run_type = $build_type; 4317 if ($test_type eq "patchcheck") { 4318 $run_type = $patchcheck_type; 4319 } elsif ($test_type eq "bisect") { 4320 $run_type = $bisect_type; 4321 } elsif ($test_type eq "config_bisect") { 4322 $run_type = $config_bisect_type; 4323 } elsif ($test_type eq "make_min_config") { 4324 $run_type = ""; 4325 } elsif ($test_type eq "make_warnings_file") { 4326 $run_type = ""; 4327 } 4328 4329 # mistake in config file? 4330 if (!defined($run_type)) { 4331 $run_type = "ERROR"; 4332 } 4333 4334 my $installme = ""; 4335 $installme = " no_install" if ($no_install); 4336 4337 my $name = ""; 4338 4339 if (defined($test_name)) { 4340 $name = " ($test_name)"; 4341 } 4342 4343 doprint "\n\n"; 4344 doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; 4345 4346 if (defined($pre_test)) { 4347 run_command $pre_test; 4348 } 4349 4350 unlink $dmesg; 4351 unlink $buildlog; 4352 unlink $testlog; 4353 4354 if (defined($addconfig)) { 4355 my $min = $minconfig; 4356 if (!defined($minconfig)) { 4357 $min = ""; 4358 } 4359 run_command "cat $addconfig $min > $tmpdir/add_config" or 4360 dodie "Failed to create temp config"; 4361 $minconfig = "$tmpdir/add_config"; 4362 } 4363 4364 if (defined($checkout)) { 4365 run_command "git checkout $checkout" or 4366 dodie "failed to checkout $checkout"; 4367 } 4368 4369 $no_reboot = 0; 4370 4371 # A test may opt to not reboot the box 4372 if ($reboot_on_success) { 4373 $reboot_success = 1; 4374 } 4375 4376 if ($test_type eq "bisect") { 4377 bisect $i; 4378 next; 4379 } elsif ($test_type eq "config_bisect") { 4380 config_bisect $i; 4381 next; 4382 } elsif ($test_type eq "patchcheck") { 4383 patchcheck $i; 4384 next; 4385 } elsif ($test_type eq "make_min_config") { 4386 make_min_config $i; 4387 next; 4388 } elsif ($test_type eq "make_warnings_file") { 4389 $no_reboot = 1; 4390 make_warnings_file $i; 4391 next; 4392 } 4393 4394 if ($build_type ne "nobuild") { 4395 build $build_type or next; 4396 check_buildlog or next; 4397 } 4398 4399 if ($test_type eq "install") { 4400 get_version; 4401 install; 4402 success $i; 4403 next; 4404 } 4405 4406 if ($test_type ne "build") { 4407 my $failed = 0; 4408 start_monitor_and_install or $failed = 1; 4409 4410 if (!$failed && $test_type ne "boot" && defined($run_test)) { 4411 do_run_test or $failed = 1; 4412 } 4413 end_monitor; 4414 if ($failed) { 4415 print_times; 4416 next; 4417 } 4418 } 4419 4420 print_times; 4421 4422 success $i; 4423} 4424 4425if (defined($final_post_ktest)) { 4426 run_command $final_post_ktest; 4427} 4428 4429if ($opt{"POWEROFF_ON_SUCCESS"}) { 4430 halt; 4431} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) { 4432 reboot_to_good; 4433} elsif (defined($switch_to_good)) { 4434 # still need to get to the good kernel 4435 run_command $switch_to_good; 4436} 4437 4438 4439doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 4440 4441if ($email_when_finished) { 4442 send_email("KTEST: Your test has finished!", 4443 "$successes of $opt{NUM_TESTS} tests started at $script_start_time were successful!"); 4444} 4445exit 0; 4446