summaryrefslogtreecommitdiff
path: root/tools/testing/ktest/ktest.pl
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing/ktest/ktest.pl')
-rwxr-xr-xtools/testing/ktest/ktest.pl287
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;