diff options
Diffstat (limited to 'tools/testing/ktest/ktest.pl')
| -rwxr-xr-x | tools/testing/ktest/ktest.pl | 287 |
1 files changed, 242 insertions, 45 deletions
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 8c8da966c641..112f9ca2444b 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -21,6 +21,8 @@ my %opt; my %repeat_tests; my %repeats; my %evals; +my @command_vars; +my %command_tmp_vars; #default opts my %default = ( @@ -83,6 +85,7 @@ my %default = ( ); my $test_log_start = 0; +my $dry_run = 0; my $ktest_config = "ktest.conf"; my $version; @@ -98,7 +101,9 @@ my $test_type; my $build_type; my $build_options; my $final_post_ktest; +my $post_ktest_done = 0; my $pre_ktest; +my $pre_ktest_die; my $post_ktest; my $pre_test; my $pre_test_die; @@ -216,6 +221,7 @@ my $patchcheck_type; my $patchcheck_start; my $patchcheck_cherry; my $patchcheck_end; +my $patchcheck_skip; my $build_time; my $install_time; @@ -280,6 +286,7 @@ my %option_map = ( "BUILD_DIR" => \$builddir, "TEST_TYPE" => \$test_type, "PRE_KTEST" => \$pre_ktest, + "PRE_KTEST_DIE" => \$pre_ktest_die, "POST_KTEST" => \$post_ktest, "PRE_TEST" => \$pre_test, "PRE_TEST_DIE" => \$pre_test_die, @@ -380,6 +387,7 @@ my %option_map = ( "PATCHCHECK_START" => \$patchcheck_start, "PATCHCHECK_CHERRY" => \$patchcheck_cherry, "PATCHCHECK_END" => \$patchcheck_end, + "PATCHCHECK_SKIP" => \$patchcheck_skip, ); # Options may be used by other options, record them. @@ -580,7 +588,7 @@ sub end_monitor; sub wait_for_monitor; sub _logit { - if (defined($opt{"LOG_FILE"})) { + if (defined($opt{"LOG_FILE"}) && defined(fileno(LOG))) { print LOG @_; } } @@ -900,7 +908,19 @@ sub set_eval { } sub set_variable { - my ($lvalue, $rvalue) = @_; + my ($lvalue, $rvalue, $command) = @_; + + # Command line variables override all others + if (defined($command_tmp_vars{$lvalue})) { + return; + } + + # If a variable is undefined, treat an unescaped self-reference as empty. + if (!defined($variable{$lvalue})) { + $rvalue =~ s/(?<!\\)\$\{\Q$lvalue\E\}//g; + $rvalue =~ s/^\s+//; + $rvalue =~ s/\s+$//; + } if ($rvalue =~ /^\s*$/) { delete $variable{$lvalue}; @@ -908,6 +928,10 @@ sub set_variable { $rvalue = process_variables($rvalue); $variable{$lvalue} = $rvalue; } + + if (defined($command)) { + $command_tmp_vars{$lvalue} = 1; + } } sub process_compare { @@ -1286,6 +1310,19 @@ sub read_config { $test_case = __read_config $config, \$test_num; + foreach my $val (@command_vars) { + chomp $val; + my %command_overrides; + if ($val =~ m/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { + my $lvalue = $1; + my $rvalue = $2; + + set_value($lvalue, $rvalue, 1, \%command_overrides, "COMMAND LINE"); + } else { + die "Invalid option definition '$val'\n"; + } + } + # make sure we have all mandatory configs get_mandatory_configs; @@ -1329,6 +1366,9 @@ sub read_config { print "$option\n"; } print "Set IGNORE_UNUSED = 1 to have ktest ignore unused variables\n"; + if ($dry_run) { + return; + } if (!read_yn "Do you want to continue?") { exit -1; } @@ -1371,7 +1411,10 @@ sub __eval_option { # If a variable contains itself, use the default var if (($var eq $name) && defined($opt{$var})) { $o = $opt{$var}; - $retval = "$retval$o"; + # Only append if the default doesn't contain itself + if ($o !~ m/\$\{$var\}/) { + $retval = "$retval$o"; + } } elsif (defined($opt{$o})) { $o = $opt{$o}; $retval = "$retval$o"; @@ -1463,12 +1506,13 @@ sub reboot { } if ($powercycle) { - run_command "$power_cycle"; - start_monitor; - # flush out current monitor - # May contain the reboot success line - wait_for_monitor 1; + if (defined($time)) { + # Flush stale console output from the old kernel before power-cycling. + wait_for_monitor 1; + } + + run_command "$power_cycle"; } else { # Make sure everything has been written to disk @@ -1547,6 +1591,24 @@ sub get_test_name() { return $name; } +sub run_post_ktest { + my $cmd; + + return if ($post_ktest_done); + + if (defined($final_post_ktest)) { + $cmd = $final_post_ktest; + } elsif (defined($post_ktest)) { + $cmd = $post_ktest; + } else { + return; + } + + my $cp_post_ktest = eval_kernel_version($cmd); + run_command $cp_post_ktest; + $post_ktest_done = 1; +} + sub dodie { # avoid recursion return if ($in_die); @@ -1573,6 +1635,11 @@ sub dodie { print " See $opt{LOG_FILE} for more info.\n"; } + # Fatal paths bypass fail(), so STORE_FAILURES needs to be handled here. + if (defined($store_failures)) { + save_logs("fail", $store_failures); + } + if ($email_on_error) { my $name = get_test_name; my $log_file; @@ -1606,6 +1673,7 @@ sub dodie { if (defined($post_test)) { run_command $post_test; } + run_post_ktest; die @_, "\n"; } @@ -1885,7 +1953,10 @@ sub run_command { doprint("$command ... "); $start_time = time; - $pid = open(CMD, "$command 2>&1 |") or + $pid = open(CMD, "-|", + "sh", "-c", + 'command=$1; shift; exec 2>&1; eval "$command"', + "sh", $command) or (fail "unable to exec $command" and return 0); if (defined($opt{"LOG_FILE"})) { @@ -2480,7 +2551,7 @@ sub check_buildlog { my $save_no_reboot = $no_reboot; $no_reboot = 1; - if (-f $warnings_file) { + if (defined($warnings_file) && -f $warnings_file) { open(IN, $warnings_file) or dodie "Error opening $warnings_file"; @@ -3511,11 +3582,37 @@ sub patchcheck { @list = reverse @list; } + my %skip_list; + my $will_skip = 0; + + if (defined($patchcheck_skip)) { + foreach my $s (split /\s+/, $patchcheck_skip) { + $s = `git log --pretty=oneline $s~1..$s`; + $s =~ s/^(\S+).*/$1/; + chomp $s; + $skip_list{$s} = 1; + $will_skip++; + } + } + doprint("Going to test the following commits:\n"); foreach my $l (@list) { + my $sha1 = $l; + $sha1 =~ s/^([[:xdigit:]]+).*/$1/; + next if (defined($skip_list{$sha1})); doprint "$l\n"; } + if ($will_skip) { + doprint("\nSkipping the following commits:\n"); + foreach my $l (@list) { + my $sha1 = $l; + $sha1 =~ s/^([[:xdigit:]]+).*/$1/; + next if (!defined($skip_list{$sha1})); + doprint "$l\n"; + } + } + my $save_clean = $noclean; my %ignored_warnings; @@ -3530,6 +3627,11 @@ sub patchcheck { my $sha1 = $item; $sha1 =~ s/^([[:xdigit:]]+).*/$1/; + if (defined($skip_list{$sha1})) { + doprint "\nSkipping \"$item\"\n\n"; + next; + } + doprint "\nProcessing commit \"$item\"\n\n"; run_command "git checkout $sha1" or @@ -4124,7 +4226,8 @@ sub __set_test_option { my $option = "$name\[$i\]"; - if (option_defined($option)) { + if (exists($opt{$option})) { + return undef if (!option_defined($option)); return $opt{$option}; } @@ -4132,7 +4235,8 @@ sub __set_test_option { if ($i >= $test && $i < $test + $repeat_tests{$test}) { $option = "$name\[$test\]"; - if (option_defined($option)) { + if (exists($opt{$option})) { + return undef if (!option_defined($option)); return $opt{$option}; } } @@ -4154,6 +4258,53 @@ sub set_test_option { return eval_option($name, $option, $i); } +sub print_test_preamble { + my ($resolved) = @_; + + doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; + + for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { + + if (!$i) { + doprint "DEFAULT OPTIONS:\n"; + } else { + doprint "\nTEST $i OPTIONS"; + if (defined($repeat_tests{$i})) { + $repeat = $repeat_tests{$i}; + doprint " ITERATE $repeat"; + } + doprint "\n"; + } + + foreach my $option (sort keys %opt) { + my $value; + + if ($option =~ /\[(\d+)\]$/) { + next if ($i != $1); + + if ($resolved) { + my $name = $option; + $name =~ s/\[\d+\]$//; + $value = set_test_option($name, $i); + } else { + $value = $opt{$option}; + } + } else { + next if ($i); + + if ($resolved) { + $value = set_test_option($option, 0); + } else { + $value = $opt{$option}; + } + } + + $value = "" if (!defined($value)); + doprint "$option = $value\n"; + } + } +} + sub find_mailer { my ($mailer) = @_; @@ -4239,11 +4390,64 @@ sub cancel_test { send_email("KTEST: Your [$name] test was cancelled", "Your test started at $script_start_time was cancelled: sig int"); } + run_post_ktest; die "\nCaught Sig Int, test interrupted: $!\n" } -$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl [config-file]\n"; +sub die_usage { + die << "EOF" +ktest.pl version: $VERSION + usage: ktest.pl [options] [config-file] + [options]: + -D value: Where value can act as an option override. + -D BUILD_NOCLEAN=1 + Sets global BUILD_NOCLEAN to 1 + -D TEST_TYPE[2]=build + Sets TEST_TYPE of test 2 to "build" + --dry-run + Print resolved test options and exit without running tests. + + It can also override all temp variables. + -D USE_TEMP_DIR:=1 + Will override all variables that use + "USE_TEMP_DIR=" + +EOF +; +} +while ( $#ARGV >= 0 ) { + if ( $ARGV[0] eq "-D" ) { + shift; + die_usage if ($#ARGV < 1); + my $val = shift; + + if ($val =~ m/(.*?):=(.*)$/) { + set_variable($1, $2, 1); + } else { + $command_vars[$#command_vars + 1] = $val; + } + + } elsif ( $ARGV[0] =~ m/^-D(.*)/) { + my $val = $1; + shift; + + if ($val =~ m/(.*?):=(.*)$/) { + set_variable($1, $2, 1); + } else { + $command_vars[$#command_vars + 1] = $val; + } + } elsif ( $ARGV[0] eq "--dry-run" ) { + $dry_run = 1; + shift; + } elsif ( $ARGV[0] eq "-h" ) { + die_usage; + } else { + last; + } +} + +$#ARGV < 1 or die_usage; if ($#ARGV == 0) { $ktest_config = $ARGV[0]; if (! -f $ktest_config) { @@ -4284,8 +4488,13 @@ EOF } read_config $ktest_config; +if ($dry_run) { + print_test_preamble 1; + exit 0; +} + if (defined($opt{"LOG_FILE"})) { - $opt{"LOG_FILE"} = eval_option("LOG_FILE", $opt{"LOG_FILE"}, -1); + $opt{"LOG_FILE"} = set_test_option("LOG_FILE", 1); } # Append any configs entered in manually to the config file. @@ -4303,35 +4512,19 @@ if (defined($opt{"LOG_FILE"})) { if ($opt{"CLEAR_LOG"}) { unlink $opt{"LOG_FILE"}; } + + if (! -e $opt{"LOG_FILE"} && $opt{"LOG_FILE"} =~ m,^(.*/),) { + my $dir = $1; + if (! -d $dir) { + mkpath($dir) or die "Failed to create directories '$dir': $!"; + print "\nThe log directory $dir did not exist, so it was created.\n"; + } + } open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; LOG->autoflush(1); } -doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; - -for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { - - if (!$i) { - doprint "DEFAULT OPTIONS:\n"; - } else { - doprint "\nTEST $i OPTIONS"; - if (defined($repeat_tests{$i})) { - $repeat = $repeat_tests{$i}; - doprint " ITERATE $repeat"; - } - doprint "\n"; - } - - foreach my $option (sort keys %opt) { - if ($option =~ /\[(\d+)\]$/) { - next if ($i != $1); - } else { - next if ($i); - } - - doprint "$option = $opt{$option}\n"; - } -} +print_test_preamble 0; $SIG{INT} = qw(cancel_test); @@ -4378,7 +4571,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { if ($i == 1) { if (defined($pre_ktest)) { doprint "\n"; - run_command $pre_ktest; + my $ret = run_command $pre_ktest; + if (!$ret && defined($pre_ktest_die) && + $pre_ktest_die) { + dodie "failed to pre_ktest\n"; + } } if ($email_when_started) { my $name = get_test_name; @@ -4458,6 +4655,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; + # Always show which build directory and output directory is being used + doprint "BUILD_DIR=$builddir\n"; + doprint "OUTPUT_DIR=$outputdir\n\n"; + if (defined($pre_test)) { my $ret = run_command $pre_test; if (!$ret && defined($pre_test_die) && @@ -4541,11 +4742,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { success $i; } -if (defined($final_post_ktest)) { - - my $cp_final_post_ktest = eval_kernel_version $final_post_ktest; - run_command $cp_final_post_ktest; -} +run_post_ktest; if ($opt{"POWEROFF_ON_SUCCESS"}) { halt; |
