2 # SPDX-License-Identifier: GPL-2.0-only
4 # Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
9 use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
10 use File::Path qw(mkpath);
11 use File::Copy qw(cp);
27 "MAILER" => "sendmail", # default mailer
28 "EMAIL_ON_ERROR" => 1,
29 "EMAIL_WHEN_FINISHED" => 1,
30 "EMAIL_WHEN_CANCELED" => 0,
31 "EMAIL_WHEN_STARTED" => 0,
33 "TEST_TYPE" => "build",
34 "BUILD_TYPE" => "oldconfig",
36 "CLOSE_CONSOLE_SIGNAL" => "INT",
38 "TMP_DIR" => "/tmp/ktest/\${MACHINE}",
39 "SLEEP_TIME" => 60, # sleep time between tests
41 "REBOOT_ON_ERROR" => 0,
42 "POWEROFF_ON_ERROR" => 0,
43 "REBOOT_ON_SUCCESS" => 1,
44 "POWEROFF_ON_SUCCESS" => 0,
45 "BUILD_OPTIONS" => "",
46 "BISECT_SLEEP_TIME" => 60, # sleep time between bisects
47 "PATCHCHECK_SLEEP_TIME" => 60, # sleep time between patch checks
52 "MIN_CONFIG_TYPE" => "boot",
53 "SUCCESS_LINE" => "login:",
54 "DETECT_TRIPLE_FAULT" => 1,
56 "BOOTED_TIMEOUT" => 1,
57 "DIE_ON_FAILURE" => 1,
58 "SSH_EXEC" => "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND",
59 "SCP_TO_TARGET" => "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE",
60 "SCP_TO_TARGET_INSTALL" => "\${SCP_TO_TARGET}",
61 "REBOOT" => "ssh \$SSH_USER\@\$MACHINE reboot",
62 "REBOOT_RETURN_CODE" => 255,
63 "STOP_AFTER_SUCCESS" => 10,
64 "STOP_AFTER_FAILURE" => 60,
65 "STOP_TEST_AFTER" => 600,
66 "MAX_MONITOR_WAIT" => 1800,
67 "GRUB_REBOOT" => "grub2-reboot",
68 "GRUB_BLS_GET" => "grubby --info=ALL",
69 "SYSLINUX" => "extlinux",
70 "SYSLINUX_PATH" => "/boot/extlinux",
71 "CONNECT_TIMEOUT" => 25,
73 # required, and we will ask users if they don't have them but we keep the default
74 # value something that is common.
75 "REBOOT_TYPE" => "grub",
76 "LOCALVERSION" => "-test",
78 "BUILD_TARGET" => "arch/x86/boot/bzImage",
79 "TARGET_IMAGE" => "/boot/vmlinuz-test",
85 my $test_log_start = 0;
87 my $ktest_config = "ktest.conf";
100 my $final_post_ktest;
114 my $reboot_return_code;
118 my $poweroff_on_error;
119 my $reboot_on_success;
121 my $powercycle_after_reboot;
122 my $poweroff_after_halt;
123 my $max_monitor_wait;
126 my $scp_to_target_install;
145 my $start_minconfig_defined;
146 my $output_minconfig;
148 my $use_output_minconfig;
154 my $bisect_bad_commit = "";
159 my $config_bisect_good;
163 my $bisect_ret_abort;
164 my $bisect_ret_default;
165 my $in_patchcheck = 0;
174 my $bisect_sleep_time;
175 my $patchcheck_sleep_time;
182 my $config_bisect_exec;
184 my $detect_triplefault;
186 my $close_console_signal;
187 my $reboot_success_line;
189 my $stop_after_success;
190 my $stop_after_failure;
199 my $run_command_status = 0;
211 my $config_bisect_type;
212 my $config_bisect_check;
215 my $patchcheck_start;
216 my $patchcheck_cherry;
225 my $dirname = $FindBin::Bin;
233 my $email_when_finished;
234 my $email_when_started;
235 my $email_when_canceled;
237 my $script_start_time = localtime();
239 # set when a test is something other that just building or install
240 # which would require more options.
243 # tell build not to worry about warnings, even when WARNINGS_FILE is set
246 # set when creating a new config
253 # force_config is the list of configs that we force enabled (or disabled)
254 # in a .config file. The MIN_CONFIG and ADD_CONFIG configs.
257 # do not force reboots on config problems
261 my $reboot_success = 0;
264 "MAILTO" => \$mailto,
265 "MAILER" => \$mailer,
266 "MAIL_PATH" => \$mail_path,
267 "MAIL_MAX_SIZE" => \$mail_max_size,
268 "MAIL_COMMAND" => \$mail_command,
269 "EMAIL_ON_ERROR" => \$email_on_error,
270 "EMAIL_WHEN_FINISHED" => \$email_when_finished,
271 "EMAIL_WHEN_STARTED" => \$email_when_started,
272 "EMAIL_WHEN_CANCELED" => \$email_when_canceled,
273 "MACHINE" => \$machine,
274 "SSH_USER" => \$ssh_user,
275 "TMP_DIR" => \$tmpdir,
276 "OUTPUT_DIR" => \$outputdir,
277 "BUILD_DIR" => \$builddir,
278 "TEST_TYPE" => \$test_type,
279 "PRE_KTEST" => \$pre_ktest,
280 "POST_KTEST" => \$post_ktest,
281 "PRE_TEST" => \$pre_test,
282 "PRE_TEST_DIE" => \$pre_test_die,
283 "POST_TEST" => \$post_test,
284 "BUILD_TYPE" => \$build_type,
285 "BUILD_OPTIONS" => \$build_options,
286 "PRE_BUILD" => \$pre_build,
287 "POST_BUILD" => \$post_build,
288 "PRE_BUILD_DIE" => \$pre_build_die,
289 "POST_BUILD_DIE" => \$post_build_die,
290 "POWER_CYCLE" => \$power_cycle,
291 "REBOOT" => \$reboot,
292 "REBOOT_RETURN_CODE" => \$reboot_return_code,
293 "BUILD_NOCLEAN" => \$noclean,
294 "MIN_CONFIG" => \$minconfig,
295 "OUTPUT_MIN_CONFIG" => \$output_minconfig,
296 "START_MIN_CONFIG" => \$start_minconfig,
297 "MIN_CONFIG_TYPE" => \$minconfig_type,
298 "USE_OUTPUT_MIN_CONFIG" => \$use_output_minconfig,
299 "WARNINGS_FILE" => \$warnings_file,
300 "IGNORE_CONFIG" => \$ignore_config,
301 "TEST" => \$run_test,
302 "ADD_CONFIG" => \$addconfig,
303 "REBOOT_TYPE" => \$reboot_type,
304 "GRUB_MENU" => \$grub_menu,
305 "GRUB_FILE" => \$grub_file,
306 "GRUB_REBOOT" => \$grub_reboot,
307 "GRUB_BLS_GET" => \$grub_bls_get,
308 "SYSLINUX" => \$syslinux,
309 "SYSLINUX_PATH" => \$syslinux_path,
310 "SYSLINUX_LABEL" => \$syslinux_label,
311 "PRE_INSTALL" => \$pre_install,
312 "POST_INSTALL" => \$post_install,
313 "NO_INSTALL" => \$no_install,
314 "REBOOT_SCRIPT" => \$reboot_script,
315 "REBOOT_ON_ERROR" => \$reboot_on_error,
316 "SWITCH_TO_GOOD" => \$switch_to_good,
317 "SWITCH_TO_TEST" => \$switch_to_test,
318 "POWEROFF_ON_ERROR" => \$poweroff_on_error,
319 "REBOOT_ON_SUCCESS" => \$reboot_on_success,
320 "DIE_ON_FAILURE" => \$die_on_failure,
321 "POWER_OFF" => \$power_off,
322 "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot,
323 "POWEROFF_AFTER_HALT" => \$poweroff_after_halt,
324 "MAX_MONITOR_WAIT" => \$max_monitor_wait,
325 "SLEEP_TIME" => \$sleep_time,
326 "BISECT_SLEEP_TIME" => \$bisect_sleep_time,
327 "PATCHCHECK_SLEEP_TIME" => \$patchcheck_sleep_time,
328 "IGNORE_WARNINGS" => \$ignore_warnings,
329 "IGNORE_ERRORS" => \$ignore_errors,
330 "BISECT_MANUAL" => \$bisect_manual,
331 "BISECT_SKIP" => \$bisect_skip,
332 "BISECT_TRIES" => \$bisect_tries,
333 "CONFIG_BISECT_GOOD" => \$config_bisect_good,
334 "BISECT_RET_GOOD" => \$bisect_ret_good,
335 "BISECT_RET_BAD" => \$bisect_ret_bad,
336 "BISECT_RET_SKIP" => \$bisect_ret_skip,
337 "BISECT_RET_ABORT" => \$bisect_ret_abort,
338 "BISECT_RET_DEFAULT" => \$bisect_ret_default,
339 "STORE_FAILURES" => \$store_failures,
340 "STORE_SUCCESSES" => \$store_successes,
341 "TEST_NAME" => \$test_name,
342 "TIMEOUT" => \$timeout,
343 "CONNECT_TIMEOUT" => \$connect_timeout,
344 "CONFIG_BISECT_EXEC" => \$config_bisect_exec,
345 "BOOTED_TIMEOUT" => \$booted_timeout,
346 "CONSOLE" => \$console,
347 "CLOSE_CONSOLE_SIGNAL" => \$close_console_signal,
348 "DETECT_TRIPLE_FAULT" => \$detect_triplefault,
349 "SUCCESS_LINE" => \$success_line,
350 "REBOOT_SUCCESS_LINE" => \$reboot_success_line,
351 "STOP_AFTER_SUCCESS" => \$stop_after_success,
352 "STOP_AFTER_FAILURE" => \$stop_after_failure,
353 "STOP_TEST_AFTER" => \$stop_test_after,
354 "BUILD_TARGET" => \$build_target,
355 "SSH_EXEC" => \$ssh_exec,
356 "SCP_TO_TARGET" => \$scp_to_target,
357 "SCP_TO_TARGET_INSTALL" => \$scp_to_target_install,
358 "CHECKOUT" => \$checkout,
359 "TARGET_IMAGE" => \$target_image,
360 "LOCALVERSION" => \$localversion,
362 "BISECT_GOOD" => \$bisect_good,
363 "BISECT_BAD" => \$bisect_bad,
364 "BISECT_TYPE" => \$bisect_type,
365 "BISECT_START" => \$bisect_start,
366 "BISECT_REPLAY" => \$bisect_replay,
367 "BISECT_FILES" => \$bisect_files,
368 "BISECT_REVERSE" => \$bisect_reverse,
369 "BISECT_CHECK" => \$bisect_check,
371 "CONFIG_BISECT" => \$config_bisect,
372 "CONFIG_BISECT_TYPE" => \$config_bisect_type,
373 "CONFIG_BISECT_CHECK" => \$config_bisect_check,
375 "PATCHCHECK_TYPE" => \$patchcheck_type,
376 "PATCHCHECK_START" => \$patchcheck_start,
377 "PATCHCHECK_CHERRY" => \$patchcheck_cherry,
378 "PATCHCHECK_END" => \$patchcheck_end,
381 # Options may be used by other options, record them.
384 # default variables that can be used
385 chomp ($variable{"PWD"} = `pwd`);
386 $pwd = $variable{"PWD"};
388 $config_help{"MACHINE"} = << "EOF"
389 The machine hostname that you will test.
390 For build only tests, it is still needed to differentiate log files.
393 $config_help{"SSH_USER"} = << "EOF"
394 The box is expected to have ssh on normal bootup, provide the user
395 (most likely root, since you need privileged operations)
398 $config_help{"BUILD_DIR"} = << "EOF"
399 The directory that contains the Linux source code (full path).
400 You can use \${PWD} that will be the path where ktest.pl is run, or use
401 \${THIS_DIR} which is assigned \${PWD} but may be changed later.
404 $config_help{"OUTPUT_DIR"} = << "EOF"
405 The directory that the objects will be built (full path).
406 (can not be same as BUILD_DIR)
407 You can use \${PWD} that will be the path where ktest.pl is run, or use
408 \${THIS_DIR} which is assigned \${PWD} but may be changed later.
411 $config_help{"BUILD_TARGET"} = << "EOF"
412 The location of the compiled file to copy to the target.
413 (relative to OUTPUT_DIR)
416 $config_help{"BUILD_OPTIONS"} = << "EOF"
417 Options to add to \"make\" when building.
421 $config_help{"TARGET_IMAGE"} = << "EOF"
422 The place to put your image on the test machine.
425 $config_help{"POWER_CYCLE"} = << "EOF"
426 A script or command to reboot the box.
428 Here is a digital loggers power switch example
429 POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
431 Here is an example to reboot a virtual box on the current host
432 with the name "Guest".
433 POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
436 $config_help{"CONSOLE"} = << "EOF"
437 The script or command that reads the console
439 If you use ttywatch server, something like the following would work.
440 CONSOLE = nc -d localhost 3001
442 For a virtual machine with guest name "Guest".
443 CONSOLE = virsh console Guest
446 $config_help{"LOCALVERSION"} = << "EOF"
447 Required version ending to differentiate the test
448 from other linux builds on the system.
451 $config_help{"REBOOT_TYPE"} = << "EOF"
452 Way to reboot the box to the test kernel.
453 Only valid options so far are "grub", "grub2", "grub2bls", "syslinux", and "script".
455 If you specify grub, it will assume grub version 1
456 and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
457 and select that target to reboot to the kernel. If this is not
458 your setup, then specify "script" and have a command or script
459 specified in REBOOT_SCRIPT to boot to the target.
461 The entry in /boot/grub/menu.lst must be entered in manually.
462 The test will not modify that file.
464 If you specify grub2, then you also need to specify both \$GRUB_MENU
467 If you specify grub2bls, then you also need to specify \$GRUB_MENU.
469 If you specify syslinux, then you may use SYSLINUX to define the syslinux
470 command (defaults to extlinux), and SYSLINUX_PATH to specify the path to
471 the syslinux install (defaults to /boot/extlinux). But you have to specify
472 SYSLINUX_LABEL to define the label to boot to for the test kernel.
475 $config_help{"GRUB_MENU"} = << "EOF"
476 The grub title name for the test kernel to boot
477 (Only mandatory if REBOOT_TYPE = grub or grub2)
479 Note, ktest.pl will not update the grub menu.lst, you need to
480 manually add an option for the test. ktest.pl will search
481 the grub menu.lst for this option to find what kernel to
484 For example, if in the /boot/grub/menu.lst the test kernel title has:
487 GRUB_MENU = Test Kernel
489 For grub2, a search of \$GRUB_FILE is performed for the lines
490 that begin with "menuentry". It will not detect submenus. The
491 menu must be a non-nested menu. Add the quotes used in the menu
492 to guarantee your selection, as the first menuentry with the content
493 of \$GRUB_MENU that is found will be used.
495 For grub2bls, \$GRUB_MENU is searched on the result of \$GRUB_BLS_GET
496 command for the lines that begin with "title".
499 $config_help{"GRUB_FILE"} = << "EOF"
500 If grub2 is used, the full path for the grub.cfg file is placed
501 here. Use something like /boot/grub2/grub.cfg to search.
504 $config_help{"SYSLINUX_LABEL"} = << "EOF"
505 If syslinux is used, the label that boots the target kernel must
506 be specified with SYSLINUX_LABEL.
509 $config_help{"REBOOT_SCRIPT"} = << "EOF"
510 A script to reboot the target into the test kernel
511 (Only mandatory if REBOOT_TYPE = script)
515 # used with process_expression()
518 # defined before get_test_name()
521 # defined before process_warning_line()
522 my $check_build_re = ".*:.*(warning|error|Error):.*";
523 my $utf8_quote = "\\x{e2}\\x{80}(\\x{98}|\\x{99})";
525 # defined before child_finished()
528 # config_ignore holds the configs that were set (or unset) for
529 # a good config and we will ignore these configs for the rest
530 # of a config bisect. These configs stay as they were.
533 # config_set holds what all configs were set as.
536 # config_off holds the set of configs that the bad config had disabled.
537 # We need to record them and set them in the .config when running
538 # olddefconfig, because olddefconfig keeps the defaults.
541 # config_off_tmp holds a set of configs to turn off for now
544 # config_list is the set of configs that are being tested
550 # found above run_config_bisect()
553 # found above add_dep()
563 # found above test_this_config()
567 my %processed_configs;
571 # These are first defined here, main function later on
576 sub wait_for_monitor;
579 if (defined($opt{"LOG_FILE"})) {
585 if (defined($opt{"LOG_FILE"})) {
598 my ($cancel, $prompt) = @_;
604 print "$prompt [y/n/C] ";
606 print "$prompt [Y/n] ";
610 if ($ans =~ /^\s*$/) {
617 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
619 last if ($ans =~ /^c$/i);
620 print "Please answer either 'y', 'n' or 'c'.\n";
622 print "Please answer either 'y' or 'n'.\n";
628 if ($ans !~ /^y$/i) {
637 return read_prompt 0, $prompt;
643 return read_prompt 1, $prompt;
646 sub get_mandatory_config {
650 return if (defined($opt{$config}));
652 if (defined($config_help{$config})) {
654 print $config_help{$config};
659 if (defined($default{$config}) && length($default{$config})) {
660 print "\[$default{$config}\] ";
663 $ans =~ s/^\s*(.*\S)\s*$/$1/;
664 if ($ans =~ /^\s*$/) {
665 if ($default{$config}) {
666 $ans = $default{$config};
668 print "Your answer can not be blank\n";
672 $entered_configs{$config} = ${ans};
684 $hours = int($time / 3600);
685 $time -= $hours * 3600;
688 $minutes = int($time / 60);
689 $time -= $minutes * 60;
693 doprint "$hours hour";
694 doprint "s" if ($hours > 1);
699 doprint "$minutes minute";
700 doprint "s" if ($minutes > 1);
704 doprint "$time second";
705 doprint "s" if ($time != 1);
711 doprint "Build time: ";
712 show_time($build_time);
716 doprint "Install time: ";
717 show_time($install_time);
721 doprint "Reboot time: ";
722 show_time($reboot_time);
726 doprint "Test time: ";
727 show_time($test_time);
730 # reset for iterations like bisect
737 sub get_mandatory_configs {
738 get_mandatory_config("MACHINE");
739 get_mandatory_config("BUILD_DIR");
740 get_mandatory_config("OUTPUT_DIR");
743 get_mandatory_config("BUILD_OPTIONS");
746 # options required for other than just building a kernel
748 get_mandatory_config("POWER_CYCLE");
749 get_mandatory_config("CONSOLE");
752 # options required for install and more
753 if ($buildonly != 1) {
754 get_mandatory_config("SSH_USER");
755 get_mandatory_config("BUILD_TARGET");
756 get_mandatory_config("TARGET_IMAGE");
759 get_mandatory_config("LOCALVERSION");
761 return if ($buildonly);
763 my $rtype = $opt{"REBOOT_TYPE"};
765 if (!defined($rtype)) {
766 if (!defined($opt{"GRUB_MENU"})) {
767 get_mandatory_config("REBOOT_TYPE");
768 $rtype = $entered_configs{"REBOOT_TYPE"};
774 if (($rtype eq "grub") or ($rtype eq "grub2bls")) {
775 get_mandatory_config("GRUB_MENU");
778 if ($rtype eq "grub2") {
779 get_mandatory_config("GRUB_MENU");
780 get_mandatory_config("GRUB_FILE");
783 if ($rtype eq "syslinux") {
784 get_mandatory_config("SYSLINUX_LABEL");
788 sub process_variables {
789 my ($value, $remove_undef) = @_;
792 # We want to check for '\', and it is just easier
793 # to check the previous characet of '$' and not need
794 # to worry if '$' is the first character. By adding
795 # a space to $value, we can just check [^\\]\$ and
796 # it will still work.
799 while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
803 # append beginning of value to retval
804 $retval = "$retval$begin";
805 if (defined($variable{$var})) {
806 $retval = "$retval$variable{$var}";
807 } elsif (defined($remove_undef) && $remove_undef) {
808 # for if statements, any variable that is not defined,
809 # we simple convert to 0
810 $retval = "${retval}0";
812 # put back the origin piece.
813 $retval = "$retval\$\{$var\}";
814 # This could be an option that is used later, save
815 # it so we don't warn if this option is not one of
817 $used_options{$var} = 1;
821 $retval = "$retval$value";
823 # remove the space added in the beginning
830 my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
832 my $prvalue = process_variables($rvalue);
834 if ($lvalue =~ /^(TEST|BISECT|CONFIG_BISECT)_TYPE(\[.*\])?$/ &&
835 $prvalue !~ /^(config_|)bisect$/ &&
836 $prvalue !~ /^build$/ &&
839 # Note if a test is something other than build, then we
840 # will need other mandatory options.
841 if ($prvalue ne "install") {
844 # install still limits some mandatory options.
849 if (defined($opt{$lvalue})) {
850 if (!$override || defined(${$overrides}{$lvalue})) {
853 $extra = "In the same override section!\n";
855 die "$name: $.: Option $lvalue defined more than once!\n$extra";
857 ${$overrides}{$lvalue} = $prvalue;
860 $opt{$lvalue} = $prvalue;
864 my ($lvalue, $rvalue, $name) = @_;
866 my $prvalue = process_variables($rvalue);
869 if (defined($evals{$lvalue})) {
870 $arr = $evals{$lvalue};
873 $evals{$lvalue} = $arr;
876 push @{$arr}, $rvalue;
880 my ($lvalue, $rvalue) = @_;
882 if ($rvalue =~ /^\s*$/) {
883 delete $variable{$lvalue};
885 $rvalue = process_variables($rvalue);
886 $variable{$lvalue} = $rvalue;
890 sub process_compare {
891 my ($lval, $cmp, $rval) = @_;
902 return $lval eq $rval;
903 } elsif ($cmp eq "!=") {
904 return $lval ne $rval;
905 } elsif ($cmp eq "=~") {
906 return $lval =~ m/$rval/;
907 } elsif ($cmp eq "!~") {
908 return $lval !~ m/$rval/;
911 my $statement = "$lval $cmp $rval";
912 my $ret = eval $statement;
914 # $@ stores error of eval
925 return defined($variable{$2}) ||
929 sub process_expression {
930 my ($name, $val) = @_;
934 while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
937 if (process_expression($name, $express)) {
938 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
940 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
948 while ($val =~ s/^(.*?)($OR|$AND)//) {
952 if (process_expression($name, $express)) {
963 if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) {
964 my $ret = process_compare($1, $2, $3);
966 die "$name: $.: Unable to process comparison\n";
971 if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
973 return !value_defined($2);
975 return value_defined($2);
979 if ($val =~ s/^\s*NOT\s+(.*)//) {
981 my $ret = process_expression($name, $express);
985 if ($val =~ /^\s*0\s*$/) {
987 } elsif ($val =~ /^\s*\d+\s*$/) {
991 die ("$name: $.: Undefined content $val in if statement\n");
995 my ($name, $value) = @_;
997 # Convert variables and replace undefined ones with 0
998 my $val = process_variables($value, 1);
999 my $ret = process_expression $name, $val;
1005 my ($config, $current_test_num) = @_;
1008 open($in, $config) || die "can't read file $config";
1011 $name =~ s,.*/(.*),$1,;
1013 my $test_num = $$current_test_num;
1016 my $num_tests_set = 0;
1029 # ignore blank lines and comments
1030 next if (/^\s*$/ || /\s*\#/);
1032 if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
1042 if ($type eq "TEST_START") {
1043 if ($num_tests_set) {
1044 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
1047 $old_test_num = $test_num;
1048 $old_repeat = $repeat;
1050 $test_num += $repeat;
1057 # If SKIP is anywhere in the line, the command will be skipped
1058 if ($rest =~ s/\s+SKIP\b//) {
1065 if ($rest =~ s/\sELSE\b//) {
1067 die "$name: $.: ELSE found with out matching IF section\n$_";
1078 if ($rest =~ s/\sIF\s+(.*)//) {
1079 if (process_if($name, $1)) {
1091 if ($type eq "TEST_START") {
1092 if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
1094 $repeat_tests{"$test_num"} = $repeat;
1096 } elsif ($rest =~ s/\sOVERRIDE\b//) {
1099 # Clear previous overrides
1104 if (!$skip && $rest !~ /^\s*$/) {
1105 die "$name: $.: Garbage found after $type\n$_";
1108 if ($skip && $type eq "TEST_START") {
1109 $test_num = $old_test_num;
1110 $repeat = $old_repeat;
1112 } elsif (/^\s*ELSE\b(.*)$/) {
1114 die "$name: $.: ELSE found with out matching IF section\n$_";
1123 if ($rest =~ /\sIF\s+(.*)/) {
1124 # May be a ELSE IF section.
1125 if (process_if($name, $1)) {
1136 if ($rest !~ /^\s*$/) {
1137 die "$name: $.: Garbage found after DEFAULTS\n$_";
1140 } elsif (/^\s*INCLUDE\s+(\S+)/) {
1145 die "$name: $.: INCLUDE can only be done in default sections\n$_";
1148 my $file = process_variables($1);
1150 if ($file !~ m,^/,) {
1151 # check the path of the config file first
1152 if ($config =~ m,(.*)/,) {
1153 if (-f "$1/$file") {
1160 die "$name: $.: Can't read file $file\n$_";
1163 if (__read_config($file, \$test_num)) {
1167 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=~\s*(.*?)\s*$/) {
1174 if ($default || $lvalue =~ /\[\d+\]$/) {
1175 set_eval($lvalue, $rvalue, $name);
1177 my $val = "$lvalue\[$test_num\]";
1178 set_eval($val, $rvalue, $name);
1181 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
1189 ($lvalue eq "NUM_TESTS" ||
1190 $lvalue eq "LOG_FILE" ||
1191 $lvalue eq "CLEAR_LOG")) {
1192 die "$name: $.: $lvalue must be set in DEFAULTS section\n";
1195 if ($lvalue eq "NUM_TESTS") {
1197 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
1200 die "$name: $.: NUM_TESTS must be set in default section\n";
1205 if ($default || $lvalue =~ /\[\d+\]$/) {
1206 set_value($lvalue, $rvalue, $override, \%overrides, $name);
1208 my $val = "$lvalue\[$test_num\]";
1209 set_value($val, $rvalue, $override, \%overrides, $name);
1212 $repeats{$val} = $repeat;
1215 } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
1221 # process config variables.
1222 # Config variables are only active while reading the
1223 # config and can be defined anywhere. They also ignore
1224 # TEST_START and DEFAULTS, but are skipped if they are in
1225 # on of these sections that have SKIP defined.
1226 # The save variable can be
1227 # defined multiple times and the new one simply overrides
1229 set_variable($lvalue, $rvalue);
1232 die "$name: $.: Garbage found in config\n$_";
1237 $test_num += $repeat - 1;
1238 $opt{"NUM_TESTS"} = $test_num;
1243 $$current_test_num = $test_num;
1249 print "What test case would you like to run?\n";
1250 print " (build, install or boot)\n";
1251 print " Other tests are available but require editing ktest.conf\n";
1252 print " (see tools/testing/ktest/sample.conf)\n";
1255 $default{"TEST_TYPE"} = $ans;
1264 $test_case = __read_config $config, \$test_num;
1266 # make sure we have all mandatory configs
1267 get_mandatory_configs;
1269 # was a test specified?
1271 print "No test case specified.\n";
1277 foreach my $default (keys %default) {
1278 if (!defined($opt{$default})) {
1279 $opt{$default} = $default{$default};
1283 if ($opt{"IGNORE_UNUSED"} == 1) {
1289 # check if there are any stragglers (typos?)
1290 foreach my $option (keys %opt) {
1292 # remove per test labels.
1294 if (!exists($option_map{$op}) &&
1295 !exists($default{$op}) &&
1296 !exists($used_options{$op})) {
1303 $s = " is" if (keys %not_used == 1);
1304 print "The following option$s not used; could be a typo:\n";
1305 foreach my $option (keys %not_used) {
1308 print "Set IGNORE_UNUSED = 1 to have ktest ignore unused variables\n";
1309 if (!read_yn "Do you want to continue?") {
1316 my ($name, $option, $i) = @_;
1318 # Add space to evaluate the character before $
1319 $option = " $option";
1324 foreach my $test (keys %repeat_tests) {
1326 $i < $test + $repeat_tests{$test}) {
1334 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
1339 # Append beginning of line
1340 $retval = "$retval$start";
1342 # If the iteration option OPT[$i] exists, then use that.
1343 # otherwise see if the default OPT (without [$i]) exists.
1345 my $o = "$var\[$i\]";
1346 my $parento = "$var\[$parent\]";
1348 # If a variable contains itself, use the default var
1349 if (($var eq $name) && defined($opt{$var})) {
1351 $retval = "$retval$o";
1352 } elsif (defined($opt{$o})) {
1354 $retval = "$retval$o";
1355 } elsif ($repeated && defined($opt{$parento})) {
1356 $o = $opt{$parento};
1357 $retval = "$retval$o";
1358 } elsif (defined($opt{$var})) {
1360 $retval = "$retval$o";
1361 } elsif ($var eq "KERNEL_VERSION" && defined($make)) {
1362 # special option KERNEL_VERSION uses kernel version
1364 $retval = "$retval$version";
1366 $retval = "$retval\$\{$var\}";
1372 $retval = "$retval$option";
1380 my ($name, $option, $i) = @_;
1382 my $option_name = "$name\[$i\]";
1385 my $old_option = $option;
1387 if (defined($evals{$option_name})) {
1388 $ev = $evals{$option_name};
1389 } elsif (defined($evals{$name})) {
1390 $ev = $evals{$name};
1395 for my $e (@{$ev}) {
1396 eval "\$option =~ $e";
1399 if ($option ne $old_option) {
1400 doprint("$name changed from '$old_option' to '$option'\n");
1407 my ($name, $option, $i) = @_;
1411 # Since an option can evaluate to another option,
1412 # keep iterating until we do not evaluate any more
1415 while ($prev ne $option) {
1416 # Check for recursive evaluations.
1417 # 100 deep should be more than enough.
1419 die "Over 100 evaluations occurred with $option\n" .
1420 "Check for recursive variables\n";
1423 $option = __eval_option($name, $option, $i);
1426 $option = process_evals($name, $option, $i);
1435 # test if the machine can be connected to within a few seconds
1436 my $stat = run_ssh("echo check machine status", $connect_timeout);
1438 doprint("power cycle\n");
1443 run_command "$power_cycle";
1446 # flush out current monitor
1447 # May contain the reboot success line
1451 # Make sure everything has been written to disk
1452 run_ssh("sync", 10);
1454 if (defined($time)) {
1456 # flush out current monitor
1457 # May contain the reboot success line
1461 # try to reboot normally
1462 if (run_command $reboot) {
1463 if (defined($powercycle_after_reboot)) {
1464 sleep $powercycle_after_reboot;
1465 run_command "$power_cycle";
1468 # nope? power cycle it.
1469 run_command "$power_cycle";
1473 if (defined($time)) {
1475 # We only want to get to the new kernel, don't fail
1476 # if we stumble over a call trace.
1477 my $save_ignore_errors = $ignore_errors;
1480 # Look for the good kernel to boot
1481 if (wait_for_monitor($time, "Linux version")) {
1483 doprint "Reboot did not finish. Forcing power cycle\n";
1484 run_command "$power_cycle";
1487 $ignore_errors = $save_ignore_errors;
1489 # Still need to wait for the reboot to finish
1490 wait_for_monitor($time, $reboot_success_line);
1496 sub reboot_to_good {
1499 if (defined($switch_to_good)) {
1500 run_command $switch_to_good;
1509 return $test_type eq "build" || $no_reboot ||
1510 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
1511 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build") ||
1512 ($test_type eq "config_bisect" && $opt{"CONFIG_BISECT_TYPE[$i]"} eq "build");
1515 sub get_test_name() {
1518 if (defined($test_name)) {
1519 $name = "$test_name:$test_type";
1528 return if ($in_die);
1533 doprint "CRITICAL FAILURE... [TEST $i] ", @_, "\n";
1535 if ($reboot_on_error && !do_not_reboot) {
1536 doprint "REBOOTING\n";
1538 } elsif ($poweroff_on_error && defined($power_off)) {
1539 doprint "POWERING OFF\n";
1543 if (defined($opt{"LOG_FILE"})) {
1544 print " See $opt{LOG_FILE} for more info.\n";
1547 if ($email_on_error) {
1548 my $name = get_test_name;
1551 if (defined($opt{"LOG_FILE"})) {
1552 my $whence = 2; # End of file
1553 my $log_size = tell LOG;
1554 my $size = $log_size - $test_log_start;
1556 if (defined($mail_max_size)) {
1557 if ($size > $mail_max_size) {
1558 $size = $mail_max_size;
1562 $log_file = "$tmpdir/log";
1563 open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)";
1564 open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n";
1565 seek(L, $pos, $whence);
1573 send_email("KTEST: critical failure for test $i [$name]",
1574 "Your test started at $script_start_time has failed with:\n@_\n", $log_file);
1578 # restore terminal settings
1579 system("stty $stty_orig");
1582 if (defined($post_test)) {
1583 run_command $post_test;
1590 my ($ptm, $pts) = @_;
1592 my $TIOCSPTLCK = 0x40045431;
1593 my $TIOCGPTN = 0x80045430;
1595 sysopen($ptm, "/dev/ptmx", O_RDWR | O_NONBLOCK) or
1596 dodie "Can't open /dev/ptmx";
1599 $tmp = pack("i", 0);
1600 ioctl($ptm, $TIOCSPTLCK, $tmp) or
1601 dodie "ioctl TIOCSPTLCK for /dev/ptmx failed";
1604 ioctl($ptm, $TIOCGPTN, $tmp) or
1605 dodie "ioctl TIOCGPTN for /dev/ptmx failed";
1606 $tmp = unpack("i", $tmp);
1608 sysopen($pts, "/dev/pts/$tmp", O_RDWR | O_NONBLOCK) or
1609 dodie "Can't open /dev/pts/$tmp";
1613 my ($ptm, $pts) = @_;
1621 open(\*STDIN, '<&', $pts);
1622 open(\*STDOUT, '>&', $pts);
1623 open(\*STDERR, '>&', $pts);
1628 dodie "Can't open console $console";
1636 # save terminal settings
1637 $stty_orig = `stty -g`;
1639 # place terminal in cbreak mode so that stdin can be read one character at
1640 # a time without having to wait for a newline
1641 system("stty -icanon -echo -icrnl");
1643 create_pty($ptm, $pts);
1649 exec_console($ptm, $pts)
1657 open(PTSFD, "Stop perl from warning about single use of PTSFD");
1661 my ($fp, $pid) = @_;
1663 doprint "kill child process $pid\n";
1664 kill $close_console_signal, $pid;
1666 doprint "wait for child process $pid to exit\n";
1672 # restore terminal settings
1673 system("stty $stty_orig");
1677 if ($monitor_cnt++) {
1680 $monitor_fp = \*MONFD;
1681 $monitor_pid = open_console $monitor_fp;
1685 open(MONFD, "Stop perl from warning about single use of MONFD");
1689 return if (!defined $console);
1690 if (--$monitor_cnt) {
1693 close_console($monitor_fp, $monitor_pid);
1696 sub wait_for_monitor {
1697 my ($time, $stop) = @_;
1701 my $start_time = time;
1702 my $skip_call_trace = 0;
1704 my $bug_ignored = 0;
1707 doprint "** Wait for monitor to settle down **\n";
1709 # read the monitor and wait for the system to calm down
1711 $line = wait_for_input($monitor_fp, $time);
1712 last if (!defined($line));
1714 $full_line .= $line;
1716 if (defined($stop) && $full_line =~ /$stop/) {
1717 doprint "wait for monitor detected $stop\n";
1721 if ($full_line =~ /\[ backtrace testing \]/) {
1722 $skip_call_trace = 1;
1725 if ($full_line =~ /call trace:/i) {
1726 if (!$bug && !$skip_call_trace) {
1727 if ($ignore_errors) {
1735 if ($full_line =~ /\[ end of backtrace testing \]/) {
1736 $skip_call_trace = 0;
1739 if ($full_line =~ /Kernel panic -/) {
1743 if ($line =~ /\n/) {
1747 if ($now - $start_time >= $max_monitor_wait) {
1748 doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n";
1752 print "** Monitor flushed **\n";
1754 # if stop is defined but wasn't hit, return error
1755 # used by reboot (which wants to see a reboot)
1756 if (defined($stop) && !$booted) {
1763 my ($result, $basedir) = @_;
1765 my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1766 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1768 my $type = $build_type;
1769 if ($type =~ /useconfig/) {
1770 $type = "useconfig";
1773 my $dir = "$machine-$test_type-$type-$result-$date";
1775 $dir = "$basedir/$dir";
1779 dodie "can't create $dir";
1783 "config" => $output_config,
1784 "buildlog" => $buildlog,
1786 "testlog" => $testlog,
1789 while (my ($name, $source) = each(%files)) {
1791 cp "$source", "$dir/$name" or
1792 dodie "failed to copy $source";
1796 doprint "*** Saved info to $dir ***\n";
1801 if ($die_on_failure) {
1809 # no need to reboot for just building.
1810 if (!do_not_reboot) {
1811 doprint "REBOOTING\n";
1812 reboot_to_good $sleep_time;
1817 if (defined($test_name)) {
1818 $name = " ($test_name)";
1823 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1824 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1825 doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1826 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1827 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1829 if (defined($store_failures)) {
1830 save_logs "fail", $store_failures;
1833 if (defined($post_test)) {
1834 run_command $post_test;
1841 my ($command, $redirect, $timeout) = @_;
1848 my $command_orig = $command;
1850 $command =~ s/\$SSH_USER/$ssh_user/g;
1851 $command =~ s/\$MACHINE/$machine/g;
1853 doprint("$command ... ");
1856 $pid = open(CMD, "$command 2>&1 |") or
1857 (fail "unable to exec $command" and return 0);
1859 if (defined($opt{"LOG_FILE"})) {
1863 if (defined($redirect)) {
1864 if ($redirect eq 1) {
1866 # Have the output of the command on its own line
1869 open (RD, ">$redirect") or
1870 dodie "failed to write to redirect $redirect";
1875 my $hit_timeout = 0;
1879 if (defined($timeout)) {
1880 doprint "timeout = $timeout\n";
1882 my $line = wait_for_input($fp, $timeout);
1883 if (!defined($line)) {
1885 if (defined($timeout) && (($now - $start_time) >= $timeout)) {
1886 doprint "Hit timeout of $timeout, killing process\n";
1892 print LOG $line if ($dolog);
1893 print RD $line if ($dord);
1894 print $line if ($dostdout);
1898 # shift 8 for real exit status
1899 $run_command_status = $? >> 8;
1901 if ($command_orig eq $default{REBOOT} &&
1902 $run_command_status == $reboot_return_code) {
1903 $run_command_status = 0;
1907 close(RD) if ($dord);
1910 my $delta = $end_time - $start_time;
1913 doprint "[1 second] ";
1915 doprint "[$delta seconds] ";
1919 $run_command_status = 1;
1922 if ($run_command_status) {
1923 doprint "FAILED!\n";
1925 doprint "SUCCESS\n";
1928 return !$run_command_status;
1932 my ($cmd, $timeout) = @_;
1933 my $cp_exec = $ssh_exec;
1935 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1936 return run_command "$cp_exec", undef , $timeout;
1940 my ($src, $dst, $cp_scp) = @_;
1942 $cp_scp =~ s/\$SRC_FILE/$src/g;
1943 $cp_scp =~ s/\$DST_FILE/$dst/g;
1945 return run_command "$cp_scp";
1948 sub run_scp_install {
1949 my ($src, $dst) = @_;
1951 my $cp_scp = $scp_to_target_install;
1953 return run_scp($src, $dst, $cp_scp);
1957 my ($src, $dst) = @_;
1959 my $cp_scp = $scp_to_target;
1961 return run_scp($src, $dst, $cp_scp);
1964 sub _get_grub_index {
1966 my ($command, $target, $skip) = @_;
1968 return if (defined($grub_number) && defined($last_grub_menu) &&
1969 $last_grub_menu eq $grub_menu && defined($last_machine) &&
1970 $last_machine eq $machine);
1972 doprint "Find $reboot_type menu ... ";
1975 my $ssh_grub = $ssh_exec;
1976 $ssh_grub =~ s,\$SSH_COMMAND,$command,g;
1978 open(IN, "$ssh_grub |") or
1979 dodie "unable to execute $command";
1994 dodie "Could not find '$grub_menu' through $command on $machine"
1996 doprint "$grub_number\n";
1997 $last_grub_menu = $grub_menu;
1998 $last_machine = $machine;
2001 sub get_grub_index {
2008 if ($reboot_type !~ /^grub/) {
2012 $grub_menu_qt = quotemeta($grub_menu);
2014 if ($reboot_type eq "grub") {
2015 $command = "cat /boot/grub/menu.lst";
2016 $target = '^\s*title\s+' . $grub_menu_qt . '\s*$';
2017 $skip = '^\s*title\s';
2018 } elsif ($reboot_type eq "grub2") {
2019 $command = "cat $grub_file";
2020 $target = '^menuentry.*' . $grub_menu_qt;
2021 $skip = '^menuentry\s|^submenu\s';
2022 } elsif ($reboot_type eq "grub2bls") {
2023 $command = $grub_bls_get;
2024 $target = '^title=.*' . $grub_menu_qt;
2030 _get_grub_index($command, $target, $skip);
2033 sub wait_for_input {
2034 my ($fp, $time) = @_;
2043 if (!defined($time)) {
2048 vec($rin, fileno($fp), 1) = 1;
2049 vec($rin, fileno(\*STDIN), 1) = 1;
2054 $nr = select($rout=$rin, undef, undef, $time);
2058 # copy data from stdin to the console
2059 if (vec($rout, fileno(\*STDIN), 1) == 1) {
2060 $nr = sysread(\*STDIN, $buf, 1000);
2061 syswrite($fp, $buf, $nr) if ($nr > 0);
2064 # The timeout is based on time waiting for the fp data
2065 if (vec($rout, fileno($fp), 1) != 1) {
2066 last if (defined($time) && (time - $start_time > $time));
2072 # try to read one char at a time
2073 while (sysread $fp, $ch, 1) {
2075 last if ($ch eq "\n");
2078 last if (!length($line));
2086 if (defined($switch_to_test)) {
2087 run_command $switch_to_test;
2090 if ($reboot_type eq "grub") {
2091 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
2092 } elsif (($reboot_type eq "grub2") or ($reboot_type eq "grub2bls")) {
2093 run_ssh "$grub_reboot $grub_number";
2094 } elsif ($reboot_type eq "syslinux") {
2095 run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path";
2096 } elsif (defined $reboot_script) {
2097 run_command "$reboot_script";
2105 doprint "git rev-list --max-count=1 $commit ... ";
2106 my $sha1 = `git rev-list --max-count=1 $commit`;
2113 dodie "Failed to get git $commit";
2126 my $bug_ignored = 0;
2127 my $skip_call_trace = 0;
2130 my $start_time = time;
2137 open(DMESG, "> $dmesg") or
2138 dodie "unable to write to $dmesg";
2144 my $monitor_start = time;
2146 my $version_found = 0;
2149 if ($bug && defined($stop_after_failure) &&
2150 $stop_after_failure >= 0) {
2151 my $time = $stop_after_failure - (time - $failure_start);
2152 $line = wait_for_input($monitor_fp, $time);
2153 if (!defined($line)) {
2154 doprint "bug timed out after $booted_timeout seconds\n";
2155 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
2159 $line = wait_for_input($monitor_fp, $booted_timeout);
2160 if (!defined($line)) {
2161 my $s = $booted_timeout == 1 ? "" : "s";
2162 doprint "Successful boot found: break after $booted_timeout second$s\n";
2166 $line = wait_for_input($monitor_fp);
2167 if (!defined($line)) {
2168 my $s = $timeout == 1 ? "" : "s";
2169 doprint "Timed out after $timeout second$s\n";
2177 # we are not guaranteed to get a full line
2178 $full_line .= $line;
2180 if ($full_line =~ /$success_line/) {
2182 $success_start = time;
2185 if ($booted && defined($stop_after_success) &&
2186 $stop_after_success >= 0) {
2188 if ($now - $success_start >= $stop_after_success) {
2189 doprint "Test forced to stop after $stop_after_success seconds after success\n";
2194 if ($full_line =~ /\[ backtrace testing \]/) {
2195 $skip_call_trace = 1;
2198 if ($full_line =~ /call trace:/i) {
2199 if (!$bug && !$skip_call_trace) {
2200 if ($ignore_errors) {
2204 $failure_start = time;
2209 if ($bug && defined($stop_after_failure) &&
2210 $stop_after_failure >= 0) {
2212 if ($now - $failure_start >= $stop_after_failure) {
2213 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
2218 if ($full_line =~ /\[ end of backtrace testing \]/) {
2219 $skip_call_trace = 0;
2222 if ($full_line =~ /Kernel panic -/) {
2223 $failure_start = time;
2227 # Detect triple faults by testing the banner
2228 if ($full_line =~ /\bLinux version (\S+).*\n/) {
2229 if ($1 eq $version) {
2231 } elsif ($version_found && $detect_triplefault) {
2232 # We already booted into the kernel we are testing,
2233 # but now we booted into another kernel?
2234 # Consider this a triple fault.
2235 doprint "Already booted in Linux kernel $version, but now\n";
2236 doprint "we booted into Linux kernel $1.\n";
2237 doprint "Assuming that this is a triple fault.\n";
2238 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
2243 if ($line =~ /\n/) {
2247 if ($stop_test_after > 0 && !$booted && !$bug) {
2248 if (time - $monitor_start > $stop_test_after) {
2249 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
2255 my $end_time = time;
2256 $reboot_time = $end_time - $start_time;
2261 return 0 if ($in_bisect);
2262 fail "failed - got a bug report" and return 0;
2266 return 0 if ($in_bisect);
2267 fail "failed - never got a boot prompt." and return 0;
2271 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
2277 sub eval_kernel_version {
2280 $option =~ s/\$KERNEL_VERSION/$version/g;
2285 sub do_post_install {
2287 return if (!defined($post_install));
2289 my $cp_post_install = eval_kernel_version $post_install;
2290 run_command "$cp_post_install" or
2291 dodie "Failed to run post install";
2294 # Sometimes the reboot fails, and will hang. We try to ssh to the box
2295 # and if we fail, we force another reboot, that should powercycle it.
2297 if (!run_ssh "echo testing connection") {
2304 return if ($no_install);
2306 my $start_time = time;
2308 if (defined($pre_install)) {
2309 my $cp_pre_install = eval_kernel_version $pre_install;
2310 run_command "$cp_pre_install" or
2311 dodie "Failed to run pre install";
2314 my $cp_target = eval_kernel_version $target_image;
2318 run_scp_install "$outputdir/$build_target", "$cp_target" or
2319 dodie "failed to copy image";
2321 my $install_mods = 0;
2323 # should we process modules?
2325 open(IN, "$output_config") or dodie("Can't read config file");
2327 if (/CONFIG_MODULES(=y)?/) {
2336 if (!$install_mods) {
2338 doprint "No modules needed\n";
2339 my $end_time = time;
2340 $install_time = $end_time - $start_time;
2344 run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or
2345 dodie "Failed to install modules";
2347 my $modlib = "/lib/modules/$version";
2348 my $modtar = "ktest-mods.tar.bz2";
2350 run_ssh "rm -rf $modlib" or
2351 dodie "failed to remove old mods: $modlib";
2353 # would be nice if scp -r did not follow symbolic links
2354 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
2355 dodie "making tarball";
2357 run_scp_mod "$tmpdir/$modtar", "/tmp" or
2358 dodie "failed to copy modules";
2360 unlink "$tmpdir/$modtar";
2362 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
2363 dodie "failed to tar modules";
2365 run_ssh "rm -f /tmp/$modtar";
2369 my $end_time = time;
2370 $install_time = $end_time - $start_time;
2374 # get the release name
2375 return if ($have_version);
2376 doprint "$make kernelrelease ... ";
2377 $version = `$make -s kernelrelease | tail -1`;
2379 doprint "$version\n";
2383 sub start_monitor_and_install {
2384 # Make sure the stable kernel has finished booting
2386 # Install bisects, don't need console
2387 if (defined $console) {
2397 start_monitor if (defined $console);
2401 sub process_warning_line {
2406 # for distcc heterogeneous systems, some compilers
2407 # do things differently causing warning lines
2408 # to be slightly different. This makes an attempt
2409 # to fixe those issues.
2411 # chop off the index into the line
2412 # using distcc, some compilers give different indexes
2413 # depending on white space
2414 $line =~ s/^(\s*\S+:\d+:)\d+/$1/;
2416 # Some compilers use UTF-8 extended for quotes and some don't.
2417 $line =~ s/$utf8_quote/'/g;
2422 # Read buildlog and check against warnings file for any
2427 sub check_buildlog {
2428 return 1 if (!defined $warnings_file);
2432 # Failed builds should not reboot the target
2433 my $save_no_reboot = $no_reboot;
2436 if (-f $warnings_file) {
2437 open(IN, $warnings_file) or
2438 dodie "Error opening $warnings_file";
2441 if (/$check_build_re/) {
2442 my $warning = process_warning_line $_;
2444 $warnings_list{$warning} = 1;
2450 # If warnings file didn't exist, and WARNINGS_FILE exist,
2451 # then we fail on any warning!
2453 open(IN, $buildlog) or dodie "Can't open $buildlog";
2455 if (/$check_build_re/) {
2456 my $warning = process_warning_line $_;
2458 if (!defined $warnings_list{$warning}) {
2459 fail "New warning found (not in $warnings_file)\n$_\n";
2460 $no_reboot = $save_no_reboot;
2465 $no_reboot = $save_no_reboot;
2469 sub check_patch_buildlog {
2472 my @files = `git show $patch | diffstat -l`;
2474 foreach my $file (@files) {
2478 open(IN, "git show $patch |") or
2479 dodie "failed to show $patch";
2481 if (m,^--- a/(.*),) {
2483 $files[$#files] = $1;
2488 open(IN, $buildlog) or dodie "Can't open $buildlog";
2490 if (/^\s*(.*?):.*(warning|error)/) {
2492 foreach my $file (@files) {
2493 my $fullpath = "$builddir/$file";
2494 if ($file eq $err || $fullpath eq $err) {
2495 fail "$file built with warnings" and return 0;
2505 sub apply_min_config {
2506 my $outconfig = "$output_config.new";
2508 # Read the config file and remove anything that
2509 # is in the force_config hash (from minconfig and others)
2510 # then add the force config back.
2512 doprint "Applying minimum configurations into $output_config.new\n";
2514 open (OUT, ">$outconfig") or
2515 dodie "Can't create $outconfig";
2517 if (-f $output_config) {
2518 open (IN, $output_config) or
2519 dodie "Failed to open $output_config";
2521 if (/^(# )?(CONFIG_[^\s=]*)/) {
2522 next if (defined($force_config{$2}));
2528 foreach my $config (keys %force_config) {
2529 print OUT "$force_config{$config}\n";
2533 run_command "mv $outconfig $output_config";
2536 sub make_oldconfig {
2538 my @force_list = keys %force_config;
2540 if ($#force_list >= 0) {
2544 if (!run_command "$make olddefconfig") {
2545 # Perhaps olddefconfig doesn't exist in this version of the kernel
2547 doprint "olddefconfig failed, trying make oldnoconfig\n";
2548 if (!run_command "$make oldnoconfig") {
2549 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
2550 # try a yes '' | oldconfig
2551 run_command "yes '' | $make oldconfig" or
2552 dodie "failed make config oldconfig";
2557 # read a config file and use this to force new configs.
2558 sub load_force_config {
2561 doprint "Loading force configs from $config\n";
2562 open(IN, $config) or
2563 dodie "failed to read $config";
2566 if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
2567 $force_config{$1} = $_;
2568 } elsif (/^# (CONFIG_\S*) is not set/) {
2569 $force_config{$1} = $_;
2580 my $start_time = time;
2582 # Failed builds should not reboot the target
2583 my $save_no_reboot = $no_reboot;
2586 # Calculate a new version from here.
2589 if (defined($pre_build)) {
2590 my $ret = run_command $pre_build;
2591 if (!$ret && defined($pre_build_die) &&
2593 dodie "failed to pre_build\n";
2597 if ($type =~ /^useconfig:(.*)/) {
2598 run_command "cp $1 $output_config" or
2599 dodie "could not copy $1 to .config";
2601 $type = "oldconfig";
2604 # old config can ask questions
2605 if ($type eq "oldconfig") {
2606 $type = "olddefconfig";
2608 # allow for empty configs
2609 run_command "touch $output_config";
2612 run_command "mv $output_config $outputdir/config_temp" or
2613 dodie "moving .config";
2615 run_command "$make mrproper" or dodie "make mrproper";
2617 run_command "mv $outputdir/config_temp $output_config" or
2618 dodie "moving config_temp";
2620 } elsif (!$noclean) {
2621 unlink "$output_config";
2622 run_command "$make mrproper" or
2623 dodie "make mrproper";
2626 # add something to distinguish this build
2627 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
2628 print OUT "$localversion\n";
2631 if (defined($minconfig)) {
2632 load_force_config($minconfig);
2635 if ($type ne "olddefconfig") {
2636 run_command "$make $type" or
2637 dodie "failed make config";
2639 # Run old config regardless, to enforce min configurations
2642 if (not defined($build_options)){
2643 $build_options = "";
2645 my $build_ret = run_command "$make $build_options", $buildlog;
2647 if (defined($post_build)) {
2648 # Because a post build may change the kernel version
2651 my $ret = run_command $post_build;
2652 if (!$ret && defined($post_build_die) &&
2654 dodie "failed to post_build\n";
2659 # bisect may need this to pass
2661 $no_reboot = $save_no_reboot;
2664 fail "failed build" and return 0;
2667 $no_reboot = $save_no_reboot;
2669 my $end_time = time;
2670 $build_time = $end_time - $start_time;
2676 if (!run_ssh "halt" or defined($power_off)) {
2677 if (defined($poweroff_after_halt)) {
2678 sleep $poweroff_after_halt;
2679 run_command "$power_off";
2683 run_command "$power_off";
2694 if (defined($test_name)) {
2695 $name = " ($test_name)";
2701 doprint "*******************************************\n";
2702 doprint "*******************************************\n";
2703 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n";
2704 doprint "*******************************************\n";
2705 doprint "*******************************************\n";
2707 if (defined($store_successes)) {
2708 save_logs "success", $store_successes;
2711 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
2712 doprint "Reboot and wait $sleep_time seconds\n";
2713 reboot_to_good $sleep_time;
2716 if (defined($post_test)) {
2717 run_command $post_test;
2723 doprint "Pass, fail, or skip? [p/f/s]";
2726 if ($ans eq "p" || $ans eq "P") {
2728 } elsif ($ans eq "f" || $ans eq "F") {
2730 } elsif ($ans eq "s" || $ans eq "S") {
2733 print "Please answer 'p', 'f', or 's'\n";
2738 sub child_run_test {
2740 # child should have no power
2741 $reboot_on_error = 0;
2742 $poweroff_on_error = 0;
2743 $die_on_failure = 1;
2745 run_command $run_test, $testlog;
2747 exit $run_command_status;
2750 sub child_finished {
2760 my $bug_ignored = 0;
2762 my $start_time = time;
2766 doprint "run test $run_test\n";
2770 $SIG{CHLD} = qw(child_finished);
2774 child_run_test if (!$child_pid);
2779 $line = wait_for_input($monitor_fp, 1);
2780 if (defined($line)) {
2782 # we are not guaranteed to get a full line
2783 $full_line .= $line;
2786 if ($full_line =~ /call trace:/i) {
2787 if ($ignore_errors) {
2794 if ($full_line =~ /Kernel panic -/) {
2798 if ($line =~ /\n/) {
2802 } while (!$child_done && !$bug);
2804 if (!$bug && $bug_ignored) {
2805 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
2809 my $failure_start = time;
2812 $line = wait_for_input($monitor_fp, 1);
2813 if (defined($line)) {
2817 if ($now - $failure_start >= $stop_after_failure) {
2820 } while (defined($line));
2822 doprint "Detected kernel crash!\n";
2823 # kill the child with extreme prejudice
2827 waitpid $child_pid, 0;
2828 $child_exit = $? >> 8;
2830 my $end_time = time;
2831 $test_time = $end_time - $start_time;
2833 if (!$bug && $in_bisect) {
2834 if (defined($bisect_ret_good)) {
2835 if ($child_exit == $bisect_ret_good) {
2839 if (defined($bisect_ret_skip)) {
2840 if ($child_exit == $bisect_ret_skip) {
2844 if (defined($bisect_ret_abort)) {
2845 if ($child_exit == $bisect_ret_abort) {
2846 fail "test abort" and return -2;
2849 if (defined($bisect_ret_bad)) {
2850 if ($child_exit == $bisect_ret_skip) {
2854 if (defined($bisect_ret_default)) {
2855 if ($bisect_ret_default eq "good") {
2857 } elsif ($bisect_ret_default eq "bad") {
2859 } elsif ($bisect_ret_default eq "skip") {
2861 } elsif ($bisect_ret_default eq "abort") {
2864 fail "unknown default action: $bisect_ret_default"
2870 if ($bug || $child_exit) {
2871 return 0 if $in_bisect;
2872 fail "test failed" and return 0;
2877 sub run_git_bisect {
2880 doprint "$command ... ";
2882 my $output = `$command 2>&1`;
2889 dodie "Failed to git bisect";
2892 doprint "SUCCESS\n";
2893 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
2894 doprint "$1 [$2]\n";
2895 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
2896 $bisect_bad_commit = $1;
2897 doprint "Found bad commit... $1\n";
2900 # we already logged it, just print it now.
2908 doprint "Reboot and sleep $bisect_sleep_time seconds\n";
2909 reboot_to_good $bisect_sleep_time;
2912 # returns 1 on success, 0 on failure, -1 on skip
2913 sub run_bisect_test {
2914 my ($type, $buildtype) = @_;
2923 build $buildtype or $failed = 1;
2925 if ($type ne "build") {
2926 if ($failed && $bisect_skip) {
2930 dodie "Failed on build" if $failed;
2933 start_monitor_and_install or $failed = 1;
2935 if ($type ne "boot") {
2936 if ($failed && $bisect_skip) {
2942 dodie "Failed on boot" if $failed;
2944 do_run_test or $failed = 1;
2955 # reboot the box to a kernel we can ssh to
2956 if ($type ne "build") {
2966 my $buildtype = "oldconfig";
2968 # We should have a minconfig to use?
2969 if (defined($minconfig)) {
2970 $buildtype = "useconfig:$minconfig";
2973 # If the user sets bisect_tries to less than 1, then no tries
2977 # Still let the user manually decide that though.
2978 if ($bisect_tries < 1 && $bisect_manual) {
2979 $ret = answer_bisect;
2982 for (my $i = 0; $i < $bisect_tries; $i++) {
2983 if ($bisect_tries > 1) {
2985 doprint("Running bisect trial $t of $bisect_tries:\n");
2987 $ret = run_bisect_test $type, $buildtype;
2989 if ($bisect_manual) {
2990 $ret = answer_bisect;
2996 # Are we looking for where it worked, not failed?
2997 if ($reverse_bisect && $ret >= 0) {
3003 } elsif ($ret == 0) {
3005 } elsif ($bisect_skip) {
3006 doprint "HIT A BAD COMMIT ... SKIPPING\n";
3011 sub update_bisect_replay {
3012 my $tmp_log = "$tmpdir/ktest_bisect_log";
3013 run_command "git bisect log > $tmp_log" or
3014 dodie "can't create bisect log";
3023 dodie "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good));
3024 dodie "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad));
3025 dodie "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type));
3027 my $good = $bisect_good;
3028 my $bad = $bisect_bad;
3029 my $type = $bisect_type;
3030 my $start = $bisect_start;
3031 my $replay = $bisect_replay;
3032 my $start_files = $bisect_files;
3034 if (defined($start_files)) {
3035 $start_files = " -- " . $start_files;
3040 # convert to true sha1's
3041 $good = get_sha1($good);
3042 $bad = get_sha1($bad);
3044 if (defined($bisect_reverse) && $bisect_reverse == 1) {
3045 doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
3046 $reverse_bisect = 1;
3048 $reverse_bisect = 0;
3051 # Can't have a test without having a test to run
3052 if ($type eq "test" && !defined($run_test)) {
3056 # Check if a bisect was running
3057 my $bisect_start_file = "$builddir/.git/BISECT_START";
3059 my $check = $bisect_check;
3060 my $do_check = defined($check) && $check ne "0";
3062 if ( -f $bisect_start_file ) {
3063 print "Bisect in progress found\n";
3065 print " If you say yes, then no checks of good or bad will be done\n";
3067 if (defined($replay)) {
3068 print "** BISECT_REPLAY is defined in config file **";
3069 print " Ignore config option and perform new git bisect log?\n";
3070 if (read_ync " (yes, no, or cancel) ") {
3071 $replay = update_bisect_replay;
3074 } elsif (read_yn "read git log and continue?") {
3075 $replay = update_bisect_replay;
3082 my $head = get_sha1("HEAD");
3084 if ($check ne "good") {
3085 doprint "TESTING BISECT BAD [$bad]\n";
3086 run_command "git checkout $bad" or
3087 dodie "Failed to checkout $bad";
3089 $result = run_bisect $type;
3091 if ($result ne "bad") {
3092 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
3096 if ($check ne "bad") {
3097 doprint "TESTING BISECT GOOD [$good]\n";
3098 run_command "git checkout $good" or
3099 dodie "Failed to checkout $good";
3101 $result = run_bisect $type;
3103 if ($result ne "good") {
3104 fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
3108 # checkout where we started
3109 run_command "git checkout $head" or
3110 dodie "Failed to checkout $head";
3113 run_command "git bisect start$start_files" or
3114 dodie "could not start bisect";
3116 if (defined($replay)) {
3117 run_command "git bisect replay $replay" or
3118 dodie "failed to run replay";
3120 run_command "git bisect good $good" or
3121 dodie "could not set bisect good to $good";
3123 run_git_bisect "git bisect bad $bad" or
3124 dodie "could not set bisect bad to $bad";
3127 if (defined($start)) {
3128 run_command "git checkout $start" or
3129 dodie "failed to checkout $start";
3134 $result = run_bisect $type;
3135 $test = run_git_bisect "git bisect $result";
3139 run_command "git bisect log" or
3140 dodie "could not capture git bisect log";
3142 run_command "git bisect reset" or
3143 dodie "could not reset git bisect";
3145 doprint "Bad commit was [$bisect_bad_commit]\n";
3150 sub assign_configs {
3151 my ($hash, $config) = @_;
3153 doprint "Reading configs from $config\n";
3155 open (IN, $config) or
3156 dodie "Failed to read $config";
3160 if (/^((CONFIG\S*)=.*)/) {
3162 } elsif (/^(# (CONFIG\S*) is not set)/) {
3170 sub process_config_ignore {
3173 assign_configs \%config_ignore, $config;
3176 sub get_dependencies {
3179 my $arr = $dependency{$config};
3180 if (!defined($arr)) {
3186 foreach my $dep (@{$arr}) {
3187 print "ADD DEP $dep\n";
3188 @deps = (@deps, get_dependencies $dep);
3195 my ($pc, $file) = @_;
3197 my %configs = %{$pc};
3199 doprint "Saving configs into $file\n";
3201 open(OUT, ">$file") or dodie "Can not write to $file";
3203 foreach my $config (keys %configs) {
3204 print OUT "$configs{$config}\n";
3210 my ($name, $pc) = @_;
3212 doprint "Creating old config from $name configs\n";
3214 save_config $pc, $output_config;
3219 sub run_config_bisect_test {
3222 my $ret = run_bisect_test $type, "oldconfig";
3224 if ($bisect_manual) {
3225 $ret = answer_bisect;
3231 sub config_bisect_end {
3232 my ($good, $bad) = @_;
3233 my $diffexec = "diff -u";
3235 if (-f "$builddir/scripts/diffconfig") {
3236 $diffexec = "$builddir/scripts/diffconfig";
3238 doprint "\n\n***************************************\n";
3239 doprint "No more config bisecting possible.\n";
3240 run_command "$diffexec $good $bad", 1;
3241 doprint "***************************************\n\n";
3244 sub run_config_bisect {
3245 my ($good, $bad, $last_result) = @_;
3250 if (!length($last_result)) {
3253 run_command "$config_bisect_exec $reset -b $outputdir $good $bad $last_result", 1;
3255 # config-bisect returns:
3256 # 0 if there is more to bisect
3257 # 1 for finding a good config
3258 # 2 if it can not find any more configs
3260 if ($run_command_status) {
3261 return $run_command_status;
3264 $ret = run_config_bisect_test $config_bisect_type;
3266 doprint "NEW GOOD CONFIG ($pass)\n";
3267 system("cp $output_config $tmpdir/good_config.tmp.$pass");
3269 # Return 3 for good config
3272 doprint "NEW BAD CONFIG ($pass)\n";
3273 system("cp $output_config $tmpdir/bad_config.tmp.$pass");
3275 # Return 4 for bad config
3286 my $type = $config_bisect_type;
3289 $bad_config = $config_bisect;
3291 if (defined($config_bisect_good)) {
3292 $good_config = $config_bisect_good;
3293 } elsif (defined($minconfig)) {
3294 $good_config = $minconfig;
3296 doprint "No config specified, checking if defconfig works";
3297 $ret = run_bisect_test $type, "defconfig";
3299 fail "Have no good config to compare with, please set CONFIG_BISECT_GOOD";
3302 $good_config = $output_config;
3305 if (!defined($config_bisect_exec)) {
3306 # First check the location that ktest.pl ran
3308 "$pwd/config-bisect.pl",
3309 "$dirname/config-bisect.pl",
3310 "$builddir/tools/testing/ktest/config-bisect.pl",
3312 foreach my $loc (@locations) {
3313 doprint "loc = $loc\n";
3314 $config_bisect_exec = $loc;
3315 last if (defined($config_bisect_exec && -x $config_bisect_exec));
3317 if (!defined($config_bisect_exec)) {
3318 fail "Could not find an executable config-bisect.pl\n",
3319 " Set CONFIG_BISECT_EXEC to point to config-bisect.pl";
3324 # we don't want min configs to cause issues here.
3325 doprint "Disabling 'MIN_CONFIG' for this test\n";
3332 if (-f "$tmpdir/good_config.tmp" || -f "$tmpdir/bad_config.tmp") {
3333 if (read_yn "Interrupted config-bisect. Continue (n - will start new)?") {
3334 if (-f "$tmpdir/good_config.tmp") {
3335 $good_config = "$tmpdir/good_config.tmp";
3337 $good_config = "$tmpdir/good_config";
3339 if (-f "$tmpdir/bad_config.tmp") {
3340 $bad_config = "$tmpdir/bad_config.tmp";
3342 $bad_config = "$tmpdir/bad_config";
3346 doprint "Run good configs through make oldconfig\n";
3347 assign_configs \%tmp_configs, $good_config;
3348 create_config "$good_config", \%tmp_configs;
3349 $good_config = "$tmpdir/good_config";
3350 system("cp $output_config $good_config") == 0 or dodie "cp good config";
3352 doprint "Run bad configs through make oldconfig\n";
3353 assign_configs \%tmp_configs, $bad_config;
3354 create_config "$bad_config", \%tmp_configs;
3355 $bad_config = "$tmpdir/bad_config";
3356 system("cp $output_config $bad_config") == 0 or dodie "cp bad config";
3358 if (defined($config_bisect_check) && $config_bisect_check ne "0") {
3359 if ($config_bisect_check ne "good") {
3360 doprint "Testing bad config\n";
3362 $ret = run_bisect_test $type, "useconfig:$bad_config";
3364 fail "Bad config succeeded when expected to fail!";
3368 if ($config_bisect_check ne "bad") {
3369 doprint "Testing good config\n";
3371 $ret = run_bisect_test $type, "useconfig:$good_config";
3373 fail "Good config failed when expected to succeed!";
3382 $ret = run_config_bisect $good_config, $bad_config, $last_run;
3385 } elsif ($ret == 4) {
3389 } while ($ret == 3 || $ret == 4);
3392 config_bisect_end "$good_config.tmp", "$bad_config.tmp";
3395 return $ret if ($ret < 0);
3400 sub patchcheck_reboot {
3401 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
3402 reboot_to_good $patchcheck_sleep_time;
3408 dodie "PATCHCHECK_START[$i] not defined\n"
3409 if (!defined($patchcheck_start));
3410 dodie "PATCHCHECK_TYPE[$i] not defined\n"
3411 if (!defined($patchcheck_type));
3413 my $start = $patchcheck_start;
3415 my $cherry = $patchcheck_cherry;
3416 if (!defined($cherry)) {
3421 if (defined($patchcheck_end)) {
3422 $end = $patchcheck_end;
3424 dodie "PATCHCHECK_END must be defined with PATCHCHECK_CHERRY\n";
3427 # Get the true sha1's since we can use things like HEAD~3
3428 $start = get_sha1($start);
3429 $end = get_sha1($end);
3431 my $type = $patchcheck_type;
3433 # Can't have a test without having a test to run
3434 if ($type eq "test" && !defined($run_test)) {
3439 open (IN, "git cherry -v $start $end|") or
3440 dodie "could not get git list";
3442 open (IN, "git log --pretty=oneline $end|") or
3443 dodie "could not get git list";
3450 # git cherry adds a '+' we want to remove
3452 $list[$#list+1] = $_;
3453 last if (/^$start/);
3458 if ($list[$#list] !~ /^$start/) {
3459 fail "SHA1 $start not found";
3462 # go backwards in the list
3463 @list = reverse @list;
3466 doprint("Going to test the following commits:\n");
3467 foreach my $l (@list) {
3471 my $save_clean = $noclean;
3472 my %ignored_warnings;
3474 if (defined($ignore_warnings)) {
3475 foreach my $sha1 (split /\s+/, $ignore_warnings) {
3476 $ignored_warnings{$sha1} = 1;
3481 foreach my $item (@list) {
3483 $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
3485 doprint "\nProcessing commit \"$item\"\n\n";
3487 run_command "git checkout $sha1" or
3488 dodie "Failed to checkout $sha1";
3490 # only clean on the first and last patch
3491 if ($item eq $list[0] ||
3492 $item eq $list[$#list]) {
3493 $noclean = $save_clean;
3498 if (defined($minconfig)) {
3499 build "useconfig:$minconfig" or return 0;
3501 # ?? no config to use?
3502 build "oldconfig" or return 0;
3505 # No need to do per patch checking if warnings file exists
3506 if (!defined($warnings_file) && !defined($ignored_warnings{$sha1})) {
3507 check_patch_buildlog $sha1 or return 0;
3510 check_buildlog or return 0;
3512 next if ($type eq "build");
3516 start_monitor_and_install or $failed = 1;
3518 if (!$failed && $type ne "boot"){
3519 do_run_test or $failed = 1;
3536 # $config depends on $dep
3537 my ($config, $dep) = @_;
3539 if (defined($depends{$config})) {
3540 $depends{$config} .= " " . $dep;
3542 $depends{$config} = $dep;
3545 # record the number of configs depending on $dep
3546 if (defined $depcount{$dep}) {
3549 $depcount{$dep} = 1;
3553 # taken from streamline_config.pl
3564 if (! -f $kconfig) {
3565 doprint "file $kconfig does not exist, skipping\n";
3569 open(KIN, "$kconfig")
3570 or dodie "Can't open $kconfig";
3574 # Make sure that lines ending with \ continue
3576 $_ = $line . " " . $_;
3587 # collect any Kconfig sources
3588 if (/^source\s*"(.*)"/) {
3589 $kconfigs[$#kconfigs+1] = $1;
3593 if (/^\s*(menu)?config\s+(\S+)\s*$/) {
3597 for (my $i = 0; $i < $iflevel; $i++) {
3598 add_dep $config, $ifdeps[$i];
3601 # collect the depends for the config
3602 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
3604 add_dep $config, $1;
3606 # Get the configs that select this config
3607 } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
3609 # selected by depends on config
3610 add_dep $1, $config;
3612 # Check for if statements
3613 } elsif (/^if\s+(.*\S)\s*$/) {
3615 # remove beginning and ending non text
3616 $deps =~ s/^[^a-zA-Z0-9_]*//;
3617 $deps =~ s/[^a-zA-Z0-9_]*$//;
3619 my @deps = split /[^a-zA-Z0-9_]+/, $deps;
3621 $ifdeps[$iflevel++] = join ':', @deps;
3623 } elsif (/^endif/) {
3625 $iflevel-- if ($iflevel);
3628 } elsif (/^\s*help\s*$/) {
3634 # read in any configs that were found.
3635 foreach $kconfig (@kconfigs) {
3636 if (!defined($read_kconfigs{$kconfig})) {
3637 $read_kconfigs{$kconfig} = 1;
3638 read_kconfig("$builddir/$kconfig");
3644 # find out which arch this is by the kconfig file
3645 open (IN, $output_config) or
3646 dodie "Failed to read $output_config";
3649 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
3656 if (!defined($arch)) {
3657 doprint "Could not find arch from config file\n";
3658 doprint "no dependencies used\n";
3662 # arch is really the subarch, we need to know
3663 # what directory to look at.
3664 if ($arch eq "i386" || $arch eq "x86_64") {
3668 my $kconfig = "$builddir/arch/$arch/Kconfig";
3670 if (! -f $kconfig && $arch =~ /\d$/) {
3672 # some subarchs have numbers, truncate them
3674 $kconfig = "$builddir/arch/$arch/Kconfig";
3675 if (! -f $kconfig) {
3676 doprint "No idea what arch dir $orig is for\n";
3677 doprint "no dependencies used\n";
3682 read_kconfig($kconfig);
3685 sub make_new_config {
3688 open (OUT, ">$output_config")
3689 or dodie "Failed to write $output_config";
3691 foreach my $config (@configs) {
3692 print OUT "$config\n";
3700 $config =~ s/CONFIG_//;
3708 my $kconfig = chomp_config $dep;
3710 $dep = $depends{"$kconfig"};
3712 # the dep string we have saves the dependencies as they
3713 # were found, including expressions like ! && ||. We
3714 # want to split this out into just an array of configs.
3716 my $valid = "A-Za-z_0-9";
3720 while ($dep =~ /[$valid]/) {
3721 if ($dep =~ /^[^$valid]*([$valid]+)/) {
3722 my $conf = "CONFIG_" . $1;
3724 $configs[$#configs + 1] = $conf;
3726 $dep =~ s/^[^$valid]*[$valid]+//;
3728 dodie "this should never happen";
3735 sub test_this_config {
3740 # if we already processed this config, skip it
3741 if (defined($processed_configs{$config})) {
3744 $processed_configs{$config} = 1;
3746 # if this config failed during this round, skip it
3747 if (defined($nochange_config{$config})) {
3751 my $kconfig = chomp_config $config;
3753 # Test dependencies first
3754 if (defined($depends{"$kconfig"})) {
3755 my @parents = get_depends $config;
3756 foreach my $parent (@parents) {
3757 # if the parent is in the min config, check it first
3758 next if (!defined($min_configs{$parent}));
3759 $found = test_this_config($parent);
3760 if (defined($found)) {
3766 # Remove this config from the list of configs
3767 # do a make olddefconfig and then read the resulting
3768 # .config to make sure it is missing the config that
3770 my %configs = %min_configs;
3771 delete $configs{$config};
3772 make_new_config ((values %configs), (values %keep_configs));
3775 assign_configs \%configs, $output_config;
3777 if (!defined($configs{$config}) || $configs{$config} =~ /^#/) {
3781 doprint "disabling config $config did not change .config\n";
3783 $nochange_config{$config} = 1;
3788 sub make_min_config {
3791 my $type = $minconfig_type;
3792 if ($type ne "boot" && $type ne "test") {
3793 fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" .
3794 " make_min_config works only with 'boot' and 'test'\n" and return;
3797 if (!defined($output_minconfig)) {
3798 fail "OUTPUT_MIN_CONFIG not defined" and return;
3801 # If output_minconfig exists, and the start_minconfig
3802 # came from min_config, than ask if we should use
3804 if (-f $output_minconfig && !$start_minconfig_defined) {
3805 print "$output_minconfig exists\n";
3806 if (!defined($use_output_minconfig)) {
3807 if (read_yn " Use it as minconfig?") {
3808 $start_minconfig = $output_minconfig;
3810 } elsif ($use_output_minconfig > 0) {
3811 doprint "Using $output_minconfig as MIN_CONFIG\n";
3812 $start_minconfig = $output_minconfig;
3814 doprint "Set to still use MIN_CONFIG as starting point\n";
3818 if (!defined($start_minconfig)) {
3819 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
3822 my $temp_config = "$tmpdir/temp_config";
3824 # First things first. We build an allnoconfig to find
3825 # out what the defaults are that we can't touch.
3826 # Some are selections, but we really can't handle selections.
3828 my $save_minconfig = $minconfig;
3831 run_command "$make allnoconfig" or return 0;
3835 process_config_ignore $output_config;
3837 undef %save_configs;
3840 if (defined($ignore_config)) {
3841 # make sure the file exists
3842 `touch $ignore_config`;
3843 assign_configs \%save_configs, $ignore_config;
3846 %keep_configs = %save_configs;
3848 doprint "Load initial configs from $start_minconfig\n";
3850 # Look at the current min configs, and save off all the
3851 # ones that were set via the allnoconfig
3852 assign_configs \%min_configs, $start_minconfig;
3854 my @config_keys = keys %min_configs;
3856 # All configs need a depcount
3857 foreach my $config (@config_keys) {
3858 my $kconfig = chomp_config $config;
3859 if (!defined $depcount{$kconfig}) {
3860 $depcount{$kconfig} = 0;
3864 # Remove anything that was set by the make allnoconfig
3865 # we shouldn't need them as they get set for us anyway.
3866 foreach my $config (@config_keys) {
3867 # Remove anything in the ignore_config
3868 if (defined($keep_configs{$config})) {
3869 my $file = $ignore_config;
3870 $file =~ s,.*/(.*?)$,$1,;
3871 doprint "$config set by $file ... ignored\n";
3872 delete $min_configs{$config};
3875 # But make sure the settings are the same. If a min config
3876 # sets a selection, we do not want to get rid of it if
3877 # it is not the same as what we have. Just move it into
3879 if (defined($config_ignore{$config})) {
3880 if ($config_ignore{$config} ne $min_configs{$config}) {
3881 doprint "$config is in allnoconfig as '$config_ignore{$config}'";
3882 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
3883 $keep_configs{$config} = $min_configs{$config};
3885 doprint "$config set by allnoconfig ... ignored\n";
3887 delete $min_configs{$config};
3898 # Now disable each config one by one and do a make oldconfig
3899 # till we find a config that changes our list.
3901 my @test_configs = keys %min_configs;
3903 # Sort keys by who is most dependent on
3904 @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
3907 # Put configs that did not modify the config at the end.
3909 for (my $i = 0; $i < $#test_configs; $i++) {
3910 if (!defined($nochange_config{$test_configs[0]})) {
3914 # This config didn't change the .config last time.
3915 # Place it at the end
3916 my $config = shift @test_configs;
3917 push @test_configs, $config;
3920 # if every test config has failed to modify the .config file
3921 # in the past, then reset and start over.
3923 undef %nochange_config;
3926 undef %processed_configs;
3928 foreach my $config (@test_configs) {
3930 $found = test_this_config $config;
3932 last if (defined($found));
3934 # oh well, try another config
3937 if (!defined($found)) {
3938 # we could have failed due to the nochange_config hash
3939 # reset and try again
3941 undef %nochange_config;
3945 doprint "No more configs found that we can disable\n";
3953 doprint "Test with $config disabled\n";
3955 # set in_bisect to keep build and monitor from dieing
3959 build "oldconfig" or $failed = 1;
3961 start_monitor_and_install or $failed = 1;
3963 if ($type eq "test" && !$failed) {
3964 do_run_test or $failed = 1;
3973 doprint "$min_configs{$config} is needed to boot the box... keeping\n";
3974 # this config is needed, add it to the ignore list.
3975 $keep_configs{$config} = $min_configs{$config};
3976 $save_configs{$config} = $min_configs{$config};
3977 delete $min_configs{$config};
3979 # update new ignore configs
3980 if (defined($ignore_config)) {
3981 open (OUT, ">$temp_config") or
3982 dodie "Can't write to $temp_config";
3983 foreach my $config (keys %save_configs) {
3984 print OUT "$save_configs{$config}\n";
3987 run_command "mv $temp_config $ignore_config" or
3988 dodie "failed to copy update to $ignore_config";
3992 # We booted without this config, remove it from the minconfigs.
3993 doprint "$config is not needed, disabling\n";
3995 delete $min_configs{$config};
3997 # Also disable anything that is not enabled in this config
3999 assign_configs \%configs, $output_config;
4000 my @config_keys = keys %min_configs;
4001 foreach my $config (@config_keys) {
4002 if (!defined($configs{$config})) {
4003 doprint "$config is not set, disabling\n";
4004 delete $min_configs{$config};
4008 # Save off all the current mandatory configs
4009 open (OUT, ">$temp_config") or
4010 dodie "Can't write to $temp_config";
4011 foreach my $config (keys %keep_configs) {
4012 print OUT "$keep_configs{$config}\n";
4014 foreach my $config (keys %min_configs) {
4015 print OUT "$min_configs{$config}\n";
4019 run_command "mv $temp_config $output_minconfig" or
4020 dodie "failed to copy update to $output_minconfig";
4023 doprint "Reboot and wait $sleep_time seconds\n";
4024 reboot_to_good $sleep_time;
4031 sub make_warnings_file {
4034 if (!defined($warnings_file)) {
4035 dodie "Must define WARNINGS_FILE for make_warnings_file test";
4038 if ($build_type eq "nobuild") {
4039 dodie "BUILD_TYPE can not be 'nobuild' for make_warnings_file test";
4042 build $build_type or dodie "Failed to build";
4044 open(OUT, ">$warnings_file") or dodie "Can't create $warnings_file";
4046 open(IN, $buildlog) or dodie "Can't open $buildlog";
4048 # Some compilers use UTF-8 extended for quotes
4049 # for distcc heterogeneous systems, this causes issues
4052 if (/$check_build_re/) {
4063 sub option_defined {
4066 if (defined($opt{$option}) && $opt{$option} !~ /^\s*$/) {
4073 sub __set_test_option {
4074 my ($name, $i) = @_;
4076 my $option = "$name\[$i\]";
4078 if (option_defined($option)) {
4079 return $opt{$option};
4082 foreach my $test (keys %repeat_tests) {
4084 $i < $test + $repeat_tests{$test}) {
4085 $option = "$name\[$test\]";
4086 if (option_defined($option)) {
4087 return $opt{$option};
4092 if (option_defined($name)) {
4099 sub set_test_option {
4100 my ($name, $i) = @_;
4102 my $option = __set_test_option($name, $i);
4103 return $option if (!defined($option));
4105 return eval_option($name, $option, $i);
4111 my @paths = split /:/, $ENV{PATH};
4113 # sendmail is usually in /usr/sbin
4114 $paths[$#paths + 1] = "/usr/sbin";
4116 foreach my $path (@paths) {
4117 if (-x "$path/$mailer") {
4126 my ($subject, $message, $file) = @_;
4128 if (!defined($mail_path)) {
4130 $mail_path = find_mailer $mailer;
4131 if (!defined($mail_path)) {
4132 die "\nCan not find $mailer in PATH\n";
4136 my $header_file = "$tmpdir/header";
4137 open (HEAD, ">$header_file") or die "Can not create $header_file\n";
4138 print HEAD "To: $mailto\n";
4139 print HEAD "Subject: $subject\n\n";
4140 print HEAD "$message\n";
4143 if (!defined($mail_command)) {
4144 if ($mailer eq "mail" || $mailer eq "mailx") {
4145 $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO";
4146 } elsif ($mailer eq "sendmail" ) {
4147 $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -t \$MAILTO";
4149 die "\nYour mailer: $mailer is not supported.\n";
4153 if (defined($file)) {
4154 $mail_command =~ s/\$BODY_FILE/$file/g;
4156 $mail_command =~ s/\$BODY_FILE//g;
4159 $mail_command =~ s/\$HEADER_FILE/$header_file/g;
4160 $mail_command =~ s/\$MAILER/$mailer/g;
4161 $mail_command =~ s/\$MAIL_PATH/$mail_path/g;
4162 $mail_command =~ s/\$MAILTO/$mailto/g;
4163 $mail_command =~ s/\$SUBJECT/$subject/g;
4164 $mail_command =~ s/\$MESSAGE/$message/g;
4166 my $ret = run_command $mail_command;
4167 if (!$ret && defined($file)) {
4168 # try again without the file
4169 $message .= "\n\n*** FAILED TO SEND LOG ***\n\n";
4170 do_send_email($subject, $message);
4175 if (defined($mailto)) {
4176 if (!defined($mailer)) {
4177 doprint "No email sent: email or mailer not specified in config.\n";
4185 if ($email_when_canceled) {
4186 my $name = get_test_name;
4187 send_email("KTEST: Your [$name] test was cancelled",
4188 "Your test started at $script_start_time was cancelled: sig int");
4190 die "\nCaught Sig Int, test interrupted: $!\n"
4193 $#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl [config-file]\n";
4196 $ktest_config = $ARGV[0];
4197 if (! -f $ktest_config) {
4198 print "$ktest_config does not exist.\n";
4199 if (!read_yn "Create it?") {
4205 if (! -f $ktest_config) {
4208 open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
4210 # Generated by ktest.pl
4213 # PWD is a ktest.pl variable that will result in the process working
4214 # directory that ktest.pl is executed in.
4216 # THIS_DIR is automatically assigned the PWD of the path that generated
4217 # the config file. It is best to use this variable when assigning other
4218 # directory paths within this directory. This allows you to easily
4219 # move the test cases to other locations or to other machines.
4221 THIS_DIR := $variable{"PWD"}
4223 # Define each test with TEST_START
4224 # The config options below it will override the defaults
4226 TEST_TYPE = $default{"TEST_TYPE"}
4233 read_config $ktest_config;
4235 if (defined($opt{"LOG_FILE"})) {
4236 $opt{"LOG_FILE"} = eval_option("LOG_FILE", $opt{"LOG_FILE"}, -1);
4239 # Append any configs entered in manually to the config file.
4240 my @new_configs = keys %entered_configs;
4241 if ($#new_configs >= 0) {
4242 print "\nAppending entered in configs to $ktest_config\n";
4243 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
4244 foreach my $config (@new_configs) {
4245 print OUT "$config = $entered_configs{$config}\n";
4246 $opt{$config} = process_variables($entered_configs{$config});
4250 if (defined($opt{"LOG_FILE"})) {
4251 if ($opt{"CLEAR_LOG"}) {
4252 unlink $opt{"LOG_FILE"};
4254 open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
4258 doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
4260 for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
4263 doprint "DEFAULT OPTIONS:\n";
4265 doprint "\nTEST $i OPTIONS";
4266 if (defined($repeat_tests{$i})) {
4267 $repeat = $repeat_tests{$i};
4268 doprint " ITERATE $repeat";
4273 foreach my $option (sort keys %opt) {
4274 if ($option =~ /\[(\d+)\]$/) {
4280 doprint "$option = $opt{$option}\n";
4284 $SIG{INT} = qw(cancel_test);
4286 # First we need to do is the builds
4287 for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
4289 # Do not reboot on failing test options
4291 $reboot_success = 0;
4302 undef %force_config;
4304 my $makecmd = set_test_option("MAKE_CMD", $i);
4306 $outputdir = set_test_option("OUTPUT_DIR", $i);
4307 $builddir = set_test_option("BUILD_DIR", $i);
4309 chdir $builddir || dodie "can't change directory to $builddir";
4311 if (!-d $outputdir) {
4312 mkpath($outputdir) or
4313 dodie "can't create $outputdir";
4316 $make = "$makecmd O=$outputdir";
4318 # Load all the options into their mapped variable names
4319 foreach my $opt (keys %option_map) {
4320 ${$option_map{$opt}} = set_test_option($opt, $i);
4323 $start_minconfig_defined = 1;
4325 # The first test may override the PRE_KTEST option
4327 if (defined($pre_ktest)) {
4329 run_command $pre_ktest;
4331 if ($email_when_started) {
4332 my $name = get_test_name;
4333 send_email("KTEST: Your [$name] test was started",
4334 "Your test was started on $script_start_time");
4338 # Any test can override the POST_KTEST option
4339 # The last test takes precedence.
4340 if (defined($post_ktest)) {
4341 $final_post_ktest = $post_ktest;
4344 if (!defined($start_minconfig)) {
4345 $start_minconfig_defined = 0;
4346 $start_minconfig = $minconfig;
4351 dodie "can't create $tmpdir";
4354 $ENV{"SSH_USER"} = $ssh_user;
4355 $ENV{"MACHINE"} = $machine;
4357 $buildlog = "$tmpdir/buildlog-$machine";
4358 $testlog = "$tmpdir/testlog-$machine";
4359 $dmesg = "$tmpdir/dmesg-$machine";
4360 $output_config = "$outputdir/.config";
4363 $target = "$ssh_user\@$machine";
4364 if (($reboot_type eq "grub") or ($reboot_type eq "grub2bls")) {
4365 dodie "GRUB_MENU not defined" if (!defined($grub_menu));
4366 } elsif ($reboot_type eq "grub2") {
4367 dodie "GRUB_MENU not defined" if (!defined($grub_menu));
4368 dodie "GRUB_FILE not defined" if (!defined($grub_file));
4369 } elsif ($reboot_type eq "syslinux") {
4370 dodie "SYSLINUX_LABEL not defined" if (!defined($syslinux_label));
4374 my $run_type = $build_type;
4375 if ($test_type eq "patchcheck") {
4376 $run_type = $patchcheck_type;
4377 } elsif ($test_type eq "bisect") {
4378 $run_type = $bisect_type;
4379 } elsif ($test_type eq "config_bisect") {
4380 $run_type = $config_bisect_type;
4381 } elsif ($test_type eq "make_min_config") {
4383 } elsif ($test_type eq "make_warnings_file") {
4387 # mistake in config file?
4388 if (!defined($run_type)) {
4389 $run_type = "ERROR";
4393 $installme = " no_install" if ($no_install);
4397 if (defined($test_name)) {
4398 $name = " ($test_name)";
4403 if (defined($opt{"LOG_FILE"})) {
4404 $test_log_start = tell(LOG);
4407 doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n";
4409 if (defined($pre_test)) {
4410 my $ret = run_command $pre_test;
4411 if (!$ret && defined($pre_test_die) &&
4413 dodie "failed to pre_test\n";
4421 if (defined($addconfig)) {
4422 my $min = $minconfig;
4423 if (!defined($minconfig)) {
4426 run_command "cat $addconfig $min > $tmpdir/add_config" or
4427 dodie "Failed to create temp config";
4428 $minconfig = "$tmpdir/add_config";
4431 if (defined($checkout)) {
4432 run_command "git checkout $checkout" or
4433 dodie "failed to checkout $checkout";
4438 # A test may opt to not reboot the box
4439 if ($reboot_on_success) {
4440 $reboot_success = 1;
4443 if ($test_type eq "bisect") {
4446 } elsif ($test_type eq "config_bisect") {
4449 } elsif ($test_type eq "patchcheck") {
4452 } elsif ($test_type eq "make_min_config") {
4455 } elsif ($test_type eq "make_warnings_file") {
4457 make_warnings_file $i;
4461 if ($build_type ne "nobuild") {
4462 build $build_type or next;
4463 check_buildlog or next;
4466 if ($test_type eq "install") {
4473 if ($test_type ne "build") {
4475 start_monitor_and_install or $failed = 1;
4477 if (!$failed && $test_type ne "boot" && defined($run_test)) {
4478 do_run_test or $failed = 1;
4492 if (defined($final_post_ktest)) {
4494 my $cp_final_post_ktest = eval_kernel_version $final_post_ktest;
4495 run_command $cp_final_post_ktest;
4498 if ($opt{"POWEROFF_ON_SUCCESS"}) {
4500 } elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) {
4502 } elsif (defined($switch_to_good)) {
4503 # still need to get to the good kernel
4504 run_command $switch_to_good;
4507 doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n";
4509 if ($email_when_finished) {
4510 send_email("KTEST: Your test has finished!",
4511 "$successes of $opt{NUM_TESTS} tests started at $script_start_time were successful!");
4514 if (defined($opt{"LOG_FILE"})) {
4515 print "\n See $opt{LOG_FILE} for the record of results.\n\n";
4522 # The following are here to standardize tabs/spaces/etc across the most likely editors
4528 # vim: softtabstop=4