Commit 98393b8f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-ktest

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-ktest: (21 commits)
  ktest: Evaluate variables entered on the command line
  ktest: Add variable ${PWD}
  ktest: Add another monitor flush before installing kernel
  ktest: Do not opencode reboot in grub setting
  ktest: Add processing of complex conditionals
  ktest: Fix parsing of config section lines
  ktest: Sort make_min_config configs by dependecies
  ktest: Add DEFINED keyword for IF statements
  ktest: Add OVERRIDE keyword to DEFAULTS section
  ktest: Consolidate TEST_TYPE and DEFAULT code
  ktest: Add INCLUDE keyword to include other config files
  ktest: Let IF keyword take comparisons
  ktest: Add IF and ELSE to config sections
  ktest: Do not reboot on config or build issues
  ktest: Add option REBOOT_SUCCESS_LINE to stop waiting after a reboot
  ktest: Add NO_INSTALL option to not install for a test
  ktest: Fail when grub menu not found
  ktest: Include monitor in reboot code
  ktest: Only need to save .config when doing mrproper
  ktest: Create outputdir if it does not exist
  ...
parents 3b754621 815e2bd7
...@@ -42,6 +42,7 @@ $default{"BISECT_MANUAL"} = 0; ...@@ -42,6 +42,7 @@ $default{"BISECT_MANUAL"} = 0;
$default{"BISECT_SKIP"} = 1; $default{"BISECT_SKIP"} = 1;
$default{"SUCCESS_LINE"} = "login:"; $default{"SUCCESS_LINE"} = "login:";
$default{"DETECT_TRIPLE_FAULT"} = 1; $default{"DETECT_TRIPLE_FAULT"} = 1;
$default{"NO_INSTALL"} = 0;
$default{"BOOTED_TIMEOUT"} = 1; $default{"BOOTED_TIMEOUT"} = 1;
$default{"DIE_ON_FAILURE"} = 1; $default{"DIE_ON_FAILURE"} = 1;
$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND"; $default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
...@@ -84,6 +85,7 @@ my $grub_number; ...@@ -84,6 +85,7 @@ my $grub_number;
my $target; my $target;
my $make; my $make;
my $post_install; my $post_install;
my $no_install;
my $noclean; my $noclean;
my $minconfig; my $minconfig;
my $start_minconfig; my $start_minconfig;
...@@ -115,6 +117,7 @@ my $timeout; ...@@ -115,6 +117,7 @@ my $timeout;
my $booted_timeout; my $booted_timeout;
my $detect_triplefault; my $detect_triplefault;
my $console; my $console;
my $reboot_success_line;
my $success_line; my $success_line;
my $stop_after_success; my $stop_after_success;
my $stop_after_failure; my $stop_after_failure;
...@@ -130,6 +133,12 @@ my %config_help; ...@@ -130,6 +133,12 @@ my %config_help;
my %variable; my %variable;
my %force_config; my %force_config;
# do not force reboots on config problems
my $no_reboot = 1;
# default variables that can be used
chomp ($variable{"PWD"} = `pwd`);
$config_help{"MACHINE"} = << "EOF" $config_help{"MACHINE"} = << "EOF"
The machine hostname that you will test. The machine hostname that you will test.
EOF EOF
...@@ -241,6 +250,7 @@ sub read_yn { ...@@ -241,6 +250,7 @@ sub read_yn {
sub get_ktest_config { sub get_ktest_config {
my ($config) = @_; my ($config) = @_;
my $ans;
return if (defined($opt{$config})); return if (defined($opt{$config}));
...@@ -254,16 +264,17 @@ sub get_ktest_config { ...@@ -254,16 +264,17 @@ sub get_ktest_config {
if (defined($default{$config})) { if (defined($default{$config})) {
print "\[$default{$config}\] "; print "\[$default{$config}\] ";
} }
$entered_configs{$config} = <STDIN>; $ans = <STDIN>;
$entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/; $ans =~ s/^\s*(.*\S)\s*$/$1/;
if ($entered_configs{$config} =~ /^\s*$/) { if ($ans =~ /^\s*$/) {
if ($default{$config}) { if ($default{$config}) {
$entered_configs{$config} = $default{$config}; $ans = $default{$config};
} else { } else {
print "Your answer can not be blank\n"; print "Your answer can not be blank\n";
next; next;
} }
} }
$entered_configs{$config} = process_variables($ans);
last; last;
} }
} }
...@@ -298,7 +309,7 @@ sub get_ktest_configs { ...@@ -298,7 +309,7 @@ sub get_ktest_configs {
} }
sub process_variables { sub process_variables {
my ($value) = @_; my ($value, $remove_undef) = @_;
my $retval = ""; my $retval = "";
# We want to check for '\', and it is just easier # We want to check for '\', and it is just easier
...@@ -316,6 +327,10 @@ sub process_variables { ...@@ -316,6 +327,10 @@ sub process_variables {
$retval = "$retval$begin"; $retval = "$retval$begin";
if (defined($variable{$var})) { if (defined($variable{$var})) {
$retval = "$retval$variable{$var}"; $retval = "$retval$variable{$var}";
} elsif (defined($remove_undef) && $remove_undef) {
# for if statements, any variable that is not defined,
# we simple convert to 0
$retval = "${retval}0";
} else { } else {
# put back the origin piece. # put back the origin piece.
$retval = "$retval\$\{$var\}"; $retval = "$retval\$\{$var\}";
...@@ -331,10 +346,17 @@ sub process_variables { ...@@ -331,10 +346,17 @@ sub process_variables {
} }
sub set_value { sub set_value {
my ($lvalue, $rvalue) = @_; my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
if (defined($opt{$lvalue})) { if (defined($opt{$lvalue})) {
die "Error: Option $lvalue defined more than once!\n"; if (!$override || defined(${$overrides}{$lvalue})) {
my $extra = "";
if ($override) {
$extra = "In the same override section!\n";
}
die "$name: $.: Option $lvalue defined more than once!\n$extra";
}
${$overrides}{$lvalue} = $rvalue;
} }
if ($rvalue =~ /^\s*$/) { if ($rvalue =~ /^\s*$/) {
delete $opt{$lvalue}; delete $opt{$lvalue};
...@@ -355,86 +377,274 @@ sub set_variable { ...@@ -355,86 +377,274 @@ sub set_variable {
} }
} }
sub read_config { sub process_compare {
my ($config) = @_; my ($lval, $cmp, $rval) = @_;
# remove whitespace
$lval =~ s/^\s*//;
$lval =~ s/\s*$//;
$rval =~ s/^\s*//;
$rval =~ s/\s*$//;
if ($cmp eq "==") {
return $lval eq $rval;
} elsif ($cmp eq "!=") {
return $lval ne $rval;
}
my $statement = "$lval $cmp $rval";
my $ret = eval $statement;
# $@ stores error of eval
if ($@) {
return -1;
}
return $ret;
}
sub value_defined {
my ($val) = @_;
return defined($variable{$2}) ||
defined($opt{$2});
}
my $d = 0;
sub process_expression {
my ($name, $val) = @_;
my $c = $d++;
while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
my $express = $1;
if (process_expression($name, $express)) {
$val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
} else {
$val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
}
}
$d--;
my $OR = "\\|\\|";
my $AND = "\\&\\&";
while ($val =~ s/^(.*?)($OR|$AND)//) {
my $express = $1;
my $op = $2;
if (process_expression($name, $express)) {
if ($op eq "||") {
return 1;
}
} else {
if ($op eq "&&") {
return 0;
}
}
}
if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) {
my $ret = process_compare($1, $2, $3);
if ($ret < 0) {
die "$name: $.: Unable to process comparison\n";
}
return $ret;
}
if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
if (defined $1) {
return !value_defined($2);
} else {
return value_defined($2);
}
}
if ($val =~ /^\s*0\s*$/) {
return 0;
} elsif ($val =~ /^\s*\d+\s*$/) {
return 1;
}
die ("$name: $.: Undefined content $val in if statement\n");
}
sub process_if {
my ($name, $value) = @_;
# Convert variables and replace undefined ones with 0
my $val = process_variables($value, 1);
my $ret = process_expression $name, $val;
return $ret;
}
open(IN, $config) || die "can't read file $config"; sub __read_config {
my ($config, $current_test_num) = @_;
my $in;
open($in, $config) || die "can't read file $config";
my $name = $config; my $name = $config;
$name =~ s,.*/(.*),$1,; $name =~ s,.*/(.*),$1,;
my $test_num = 0; my $test_num = $$current_test_num;
my $default = 1; my $default = 1;
my $repeat = 1; my $repeat = 1;
my $num_tests_set = 0; my $num_tests_set = 0;
my $skip = 0; my $skip = 0;
my $rest; my $rest;
my $line;
my $test_case = 0; my $test_case = 0;
my $if = 0;
my $if_set = 0;
my $override = 0;
while (<IN>) { my %overrides;
while (<$in>) {
# ignore blank lines and comments # ignore blank lines and comments
next if (/^\s*$/ || /\s*\#/); next if (/^\s*$/ || /\s*\#/);
if (/^\s*TEST_START(.*)/) { if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
$rest = $1; my $type = $1;
$rest = $2;
$line = $2;
if ($num_tests_set) { my $old_test_num;
die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; my $old_repeat;
} $override = 0;
if ($type eq "TEST_START") {
if ($num_tests_set) {
die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
}
my $old_test_num = $test_num; $old_test_num = $test_num;
my $old_repeat = $repeat; $old_repeat = $repeat;
$test_num += $repeat; $test_num += $repeat;
$default = 0; $default = 0;
$repeat = 1; $repeat = 1;
} else {
$default = 1;
}
if ($rest =~ /\s+SKIP(.*)/) { # If SKIP is anywhere in the line, the command will be skipped
$rest = $1; if ($rest =~ s/\s+SKIP\b//) {
$skip = 1; $skip = 1;
} else { } else {
$test_case = 1; $test_case = 1;
$skip = 0; $skip = 0;
} }
if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) { if ($rest =~ s/\sELSE\b//) {
$repeat = $1; if (!$if) {
$rest = $2; die "$name: $.: ELSE found with out matching IF section\n$_";
$repeat_tests{"$test_num"} = $repeat; }
$if = 0;
if ($if_set) {
$skip = 1;
} else {
$skip = 0;
}
} }
if ($rest =~ /\s+SKIP(.*)/) { if ($rest =~ s/\sIF\s+(.*)//) {
$rest = $1; if (process_if($name, $1)) {
$skip = 1; $if_set = 1;
} else {
$skip = 1;
}
$if = 1;
} else {
$if = 0;
$if_set = 0;
} }
if ($rest !~ /^\s*$/) { if (!$skip) {
die "$name: $.: Gargbage found after TEST_START\n$_"; if ($type eq "TEST_START") {
if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
$repeat = $1;
$repeat_tests{"$test_num"} = $repeat;
}
} elsif ($rest =~ s/\sOVERRIDE\b//) {
# DEFAULT only
$override = 1;
# Clear previous overrides
%overrides = ();
}
}
if (!$skip && $rest !~ /^\s*$/) {
die "$name: $.: Gargbage found after $type\n$_";
} }
if ($skip) { if ($skip && $type eq "TEST_START") {
$test_num = $old_test_num; $test_num = $old_test_num;
$repeat = $old_repeat; $repeat = $old_repeat;
} }
} elsif (/^\s*DEFAULTS(.*)$/) { } elsif (/^\s*ELSE\b(.*)$/) {
$default = 1; if (!$if) {
die "$name: $.: ELSE found with out matching IF section\n$_";
}
$rest = $1; $rest = $1;
if ($if_set) {
if ($rest =~ /\s+SKIP(.*)/) {
$rest = $1;
$skip = 1; $skip = 1;
$rest = "";
} else { } else {
$skip = 0; $skip = 0;
if ($rest =~ /\sIF\s+(.*)/) {
# May be a ELSE IF section.
if (!process_if($name, $1)) {
$skip = 1;
}
$rest = "";
} else {
$if = 0;
}
} }
if ($rest !~ /^\s*$/) { if ($rest !~ /^\s*$/) {
die "$name: $.: Gargbage found after DEFAULTS\n$_"; die "$name: $.: Gargbage found after DEFAULTS\n$_";
} }
} elsif (/^\s*INCLUDE\s+(\S+)/) {
next if ($skip);
if (!$default) {
die "$name: $.: INCLUDE can only be done in default sections\n$_";
}
my $file = process_variables($1);
if ($file !~ m,^/,) {
# check the path of the config file first
if ($config =~ m,(.*)/,) {
if (-f "$1/$file") {
$file = "$1/$file";
}
}
}
if ( ! -r $file ) {
die "$name: $.: Can't read file $file\n$_";
}
if (__read_config($file, \$test_num)) {
$test_case = 1;
}
} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
next if ($skip); next if ($skip);
...@@ -460,10 +670,10 @@ sub read_config { ...@@ -460,10 +670,10 @@ sub read_config {
} }
if ($default || $lvalue =~ /\[\d+\]$/) { if ($default || $lvalue =~ /\[\d+\]$/) {
set_value($lvalue, $rvalue); set_value($lvalue, $rvalue, $override, \%overrides, $name);
} else { } else {
my $val = "$lvalue\[$test_num\]"; my $val = "$lvalue\[$test_num\]";
set_value($val, $rvalue); set_value($val, $rvalue, $override, \%overrides, $name);
if ($repeat > 1) { if ($repeat > 1) {
$repeats{$val} = $repeat; $repeats{$val} = $repeat;
...@@ -490,13 +700,26 @@ sub read_config { ...@@ -490,13 +700,26 @@ sub read_config {
} }
} }
close(IN);
if ($test_num) { if ($test_num) {
$test_num += $repeat - 1; $test_num += $repeat - 1;
$opt{"NUM_TESTS"} = $test_num; $opt{"NUM_TESTS"} = $test_num;
} }
close($in);
$$current_test_num = $test_num;
return $test_case;
}
sub read_config {
my ($config) = @_;
my $test_case;
my $test_num = 0;
$test_case = __read_config $config, \$test_num;
# make sure we have all mandatory configs # make sure we have all mandatory configs
get_ktest_configs; get_ktest_configs;
...@@ -603,8 +826,20 @@ sub doprint { ...@@ -603,8 +826,20 @@ sub doprint {
} }
sub run_command; sub run_command;
sub start_monitor;
sub end_monitor;
sub wait_for_monitor;
sub reboot { sub reboot {
my ($time) = @_;
if (defined($time)) {
start_monitor;
# flush out current monitor
# May contain the reboot success line
wait_for_monitor 1;
}
# try to reboot normally # try to reboot normally
if (run_command $reboot) { if (run_command $reboot) {
if (defined($powercycle_after_reboot)) { if (defined($powercycle_after_reboot)) {
...@@ -615,12 +850,17 @@ sub reboot { ...@@ -615,12 +850,17 @@ sub reboot {
# nope? power cycle it. # nope? power cycle it.
run_command "$power_cycle"; run_command "$power_cycle";
} }
if (defined($time)) {
wait_for_monitor($time, $reboot_success_line);
end_monitor;
}
} }
sub do_not_reboot { sub do_not_reboot {
my $i = $iteration; my $i = $iteration;
return $test_type eq "build" || return $test_type eq "build" || $no_reboot ||
($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
} }
...@@ -693,16 +933,29 @@ sub end_monitor { ...@@ -693,16 +933,29 @@ sub end_monitor {
} }
sub wait_for_monitor { sub wait_for_monitor {
my ($time) = @_; my ($time, $stop) = @_;
my $full_line = "";
my $line; my $line;
my $booted = 0;
doprint "** Wait for monitor to settle down **\n"; doprint "** Wait for monitor to settle down **\n";
# read the monitor and wait for the system to calm down # read the monitor and wait for the system to calm down
do { while (!$booted) {
$line = wait_for_input($monitor_fp, $time); $line = wait_for_input($monitor_fp, $time);
print "$line" if (defined($line)); last if (!defined($line));
} while (defined($line)); print "$line";
$full_line .= $line;
if (defined($stop) && $full_line =~ /$stop/) {
doprint "wait for monitor detected $stop\n";
$booted = 1;
}
if ($line =~ /\n/) {
$full_line = "";
}
}
print "** Monitor flushed **\n"; print "** Monitor flushed **\n";
} }
...@@ -719,10 +972,7 @@ sub fail { ...@@ -719,10 +972,7 @@ sub fail {
# no need to reboot for just building. # no need to reboot for just building.
if (!do_not_reboot) { if (!do_not_reboot) {
doprint "REBOOTING\n"; doprint "REBOOTING\n";
reboot; reboot $sleep_time;
start_monitor;
wait_for_monitor $sleep_time;
end_monitor;
} }
my $name = ""; my $name = "";
...@@ -854,9 +1104,12 @@ sub get_grub_index { ...@@ -854,9 +1104,12 @@ sub get_grub_index {
open(IN, "$ssh_grub |") open(IN, "$ssh_grub |")
or die "unable to get menu.lst"; or die "unable to get menu.lst";
my $found = 0;
while (<IN>) { while (<IN>) {
if (/^\s*title\s+$grub_menu\s*$/) { if (/^\s*title\s+$grub_menu\s*$/) {
$grub_number++; $grub_number++;
$found = 1;
last; last;
} elsif (/^\s*title\s/) { } elsif (/^\s*title\s/) {
$grub_number++; $grub_number++;
...@@ -865,7 +1118,7 @@ sub get_grub_index { ...@@ -865,7 +1118,7 @@ sub get_grub_index {
close(IN); close(IN);
die "Could not find '$grub_menu' in /boot/grub/menu on $machine" die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
if ($grub_number < 0); if (!$found);
doprint "$grub_number\n"; doprint "$grub_number\n";
} }
...@@ -902,7 +1155,8 @@ sub wait_for_input ...@@ -902,7 +1155,8 @@ sub wait_for_input
sub reboot_to { sub reboot_to {
if ($reboot_type eq "grub") { if ($reboot_type eq "grub") {
run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'"; run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
reboot;
return; return;
} }
...@@ -1083,6 +1337,8 @@ sub do_post_install { ...@@ -1083,6 +1337,8 @@ sub do_post_install {
sub install { sub install {
return if ($no_install);
run_scp "$outputdir/$build_target", "$target_image" or run_scp "$outputdir/$build_target", "$target_image" or
dodie "failed to copy image"; dodie "failed to copy image";
...@@ -1140,6 +1396,11 @@ sub get_version { ...@@ -1140,6 +1396,11 @@ sub get_version {
} }
sub start_monitor_and_boot { sub start_monitor_and_boot {
# Make sure the stable kernel has finished booting
start_monitor;
wait_for_monitor 5;
end_monitor;
get_grub_index; get_grub_index;
get_version; get_version;
install; install;
...@@ -1250,6 +1511,10 @@ sub build { ...@@ -1250,6 +1511,10 @@ sub build {
unlink $buildlog; unlink $buildlog;
# Failed builds should not reboot the target
my $save_no_reboot = $no_reboot;
$no_reboot = 1;
if (defined($pre_build)) { if (defined($pre_build)) {
my $ret = run_command $pre_build; my $ret = run_command $pre_build;
if (!$ret && defined($pre_build_die) && if (!$ret && defined($pre_build_die) &&
...@@ -1272,15 +1537,15 @@ sub build { ...@@ -1272,15 +1537,15 @@ sub build {
# allow for empty configs # allow for empty configs
run_command "touch $output_config"; run_command "touch $output_config";
run_command "mv $output_config $outputdir/config_temp" or if (!$noclean) {
dodie "moving .config"; run_command "mv $output_config $outputdir/config_temp" or
dodie "moving .config";
if (!$noclean && !run_command "$make mrproper") { run_command "$make mrproper" or dodie "make mrproper";
dodie "make mrproper";
}
run_command "mv $outputdir/config_temp $output_config" or run_command "mv $outputdir/config_temp $output_config" or
dodie "moving config_temp"; dodie "moving config_temp";
}
} elsif (!$noclean) { } elsif (!$noclean) {
unlink "$output_config"; unlink "$output_config";
...@@ -1318,10 +1583,15 @@ sub build { ...@@ -1318,10 +1583,15 @@ sub build {
if (!$build_ret) { if (!$build_ret) {
# bisect may need this to pass # bisect may need this to pass
return 0 if ($in_bisect); if ($in_bisect) {
$no_reboot = $save_no_reboot;
return 0;
}
fail "failed build" and return 0; fail "failed build" and return 0;
} }
$no_reboot = $save_no_reboot;
return 1; return 1;
} }
...@@ -1356,10 +1626,7 @@ sub success { ...@@ -1356,10 +1626,7 @@ sub success {
if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
doprint "Reboot and wait $sleep_time seconds\n"; doprint "Reboot and wait $sleep_time seconds\n";
reboot; reboot $sleep_time;
start_monitor;
wait_for_monitor $sleep_time;
end_monitor;
} }
} }
...@@ -1500,10 +1767,7 @@ sub run_git_bisect { ...@@ -1500,10 +1767,7 @@ sub run_git_bisect {
sub bisect_reboot { sub bisect_reboot {
doprint "Reboot and sleep $bisect_sleep_time seconds\n"; doprint "Reboot and sleep $bisect_sleep_time seconds\n";
reboot; reboot $bisect_sleep_time;
start_monitor;
wait_for_monitor $bisect_sleep_time;
end_monitor;
} }
# returns 1 on success, 0 on failure, -1 on skip # returns 1 on success, 0 on failure, -1 on skip
...@@ -2066,10 +2330,7 @@ sub config_bisect { ...@@ -2066,10 +2330,7 @@ sub config_bisect {
sub patchcheck_reboot { sub patchcheck_reboot {
doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
reboot; reboot $patchcheck_sleep_time;
start_monitor;
wait_for_monitor $patchcheck_sleep_time;
end_monitor;
} }
sub patchcheck { sub patchcheck {
...@@ -2178,12 +2439,31 @@ sub patchcheck { ...@@ -2178,12 +2439,31 @@ sub patchcheck {
} }
my %depends; my %depends;
my %depcount;
my $iflevel = 0; my $iflevel = 0;
my @ifdeps; my @ifdeps;
# prevent recursion # prevent recursion
my %read_kconfigs; my %read_kconfigs;
sub add_dep {
# $config depends on $dep
my ($config, $dep) = @_;
if (defined($depends{$config})) {
$depends{$config} .= " " . $dep;
} else {
$depends{$config} = $dep;
}
# record the number of configs depending on $dep
if (defined $depcount{$dep}) {
$depcount{$dep}++;
} else {
$depcount{$dep} = 1;
}
}
# taken from streamline_config.pl # taken from streamline_config.pl
sub read_kconfig { sub read_kconfig {
my ($kconfig) = @_; my ($kconfig) = @_;
...@@ -2230,30 +2510,19 @@ sub read_kconfig { ...@@ -2230,30 +2510,19 @@ sub read_kconfig {
$config = $2; $config = $2;
for (my $i = 0; $i < $iflevel; $i++) { for (my $i = 0; $i < $iflevel; $i++) {
if ($i) { add_dep $config, $ifdeps[$i];
$depends{$config} .= " " . $ifdeps[$i];
} else {
$depends{$config} = $ifdeps[$i];
}
$state = "DEP";
} }
# collect the depends for the config # collect the depends for the config
} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
if (defined($depends{$1})) { add_dep $config, $1;
$depends{$config} .= " " . $1;
} else {
$depends{$config} = $1;
}
# Get the configs that select this config # Get the configs that select this config
} elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
if (defined($depends{$1})) {
$depends{$1} .= " " . $config; # selected by depends on config
} else { add_dep $1, $config;
$depends{$1} = $config;
}
# Check for if statements # Check for if statements
} elsif (/^if\s+(.*\S)\s*$/) { } elsif (/^if\s+(.*\S)\s*$/) {
...@@ -2365,11 +2634,18 @@ sub make_new_config { ...@@ -2365,11 +2634,18 @@ sub make_new_config {
close OUT; close OUT;
} }
sub chomp_config {
my ($config) = @_;
$config =~ s/CONFIG_//;
return $config;
}
sub get_depends { sub get_depends {
my ($dep) = @_; my ($dep) = @_;
my $kconfig = $dep; my $kconfig = chomp_config $dep;
$kconfig =~ s/CONFIG_//;
$dep = $depends{"$kconfig"}; $dep = $depends{"$kconfig"};
...@@ -2419,8 +2695,7 @@ sub test_this_config { ...@@ -2419,8 +2695,7 @@ sub test_this_config {
return undef; return undef;
} }
my $kconfig = $config; my $kconfig = chomp_config $config;
$kconfig =~ s/CONFIG_//;
# Test dependencies first # Test dependencies first
if (defined($depends{"$kconfig"})) { if (defined($depends{"$kconfig"})) {
...@@ -2510,6 +2785,14 @@ sub make_min_config { ...@@ -2510,6 +2785,14 @@ sub make_min_config {
my @config_keys = keys %min_configs; my @config_keys = keys %min_configs;
# All configs need a depcount
foreach my $config (@config_keys) {
my $kconfig = chomp_config $config;
if (!defined $depcount{$kconfig}) {
$depcount{$kconfig} = 0;
}
}
# Remove anything that was set by the make allnoconfig # Remove anything that was set by the make allnoconfig
# we shouldn't need them as they get set for us anyway. # we shouldn't need them as they get set for us anyway.
foreach my $config (@config_keys) { foreach my $config (@config_keys) {
...@@ -2548,8 +2831,13 @@ sub make_min_config { ...@@ -2548,8 +2831,13 @@ sub make_min_config {
# Now disable each config one by one and do a make oldconfig # Now disable each config one by one and do a make oldconfig
# till we find a config that changes our list. # till we find a config that changes our list.
# Put configs that did not modify the config at the end.
my @test_configs = keys %min_configs; my @test_configs = keys %min_configs;
# Sort keys by who is most dependent on
@test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
@test_configs ;
# Put configs that did not modify the config at the end.
my $reset = 1; my $reset = 1;
for (my $i = 0; $i < $#test_configs; $i++) { for (my $i = 0; $i < $#test_configs; $i++) {
if (!defined($nochange_config{$test_configs[0]})) { if (!defined($nochange_config{$test_configs[0]})) {
...@@ -2659,10 +2947,7 @@ sub make_min_config { ...@@ -2659,10 +2947,7 @@ sub make_min_config {
} }
doprint "Reboot and wait $sleep_time seconds\n"; doprint "Reboot and wait $sleep_time seconds\n";
reboot; reboot $sleep_time;
start_monitor;
wait_for_monitor $sleep_time;
end_monitor;
} }
success $i; success $i;
...@@ -2783,6 +3068,9 @@ sub set_test_option { ...@@ -2783,6 +3068,9 @@ sub set_test_option {
# First we need to do is the builds # First we need to do is the builds
for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
# Do not reboot on failing test options
$no_reboot = 1;
$iteration = $i; $iteration = $i;
my $makecmd = set_test_option("MAKE_CMD", $i); my $makecmd = set_test_option("MAKE_CMD", $i);
...@@ -2811,6 +3099,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { ...@@ -2811,6 +3099,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
$reboot_type = set_test_option("REBOOT_TYPE", $i); $reboot_type = set_test_option("REBOOT_TYPE", $i);
$grub_menu = set_test_option("GRUB_MENU", $i); $grub_menu = set_test_option("GRUB_MENU", $i);
$post_install = set_test_option("POST_INSTALL", $i); $post_install = set_test_option("POST_INSTALL", $i);
$no_install = set_test_option("NO_INSTALL", $i);
$reboot_script = set_test_option("REBOOT_SCRIPT", $i); $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
$reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
$poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
...@@ -2832,6 +3121,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { ...@@ -2832,6 +3121,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
$console = set_test_option("CONSOLE", $i); $console = set_test_option("CONSOLE", $i);
$detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i); $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
$success_line = set_test_option("SUCCESS_LINE", $i); $success_line = set_test_option("SUCCESS_LINE", $i);
$reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i);
$stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
$stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
$stop_test_after = set_test_option("STOP_TEST_AFTER", $i); $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
...@@ -2850,9 +3140,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { ...@@ -2850,9 +3140,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
chdir $builddir || die "can't change directory to $builddir"; chdir $builddir || die "can't change directory to $builddir";
if (!-d $tmpdir) { foreach my $dir ($tmpdir, $outputdir) {
mkpath($tmpdir) or if (!-d $dir) {
die "can't create $tmpdir"; mkpath($dir) or
die "can't create $dir";
}
} }
$ENV{"SSH_USER"} = $ssh_user; $ENV{"SSH_USER"} = $ssh_user;
...@@ -2889,8 +3181,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { ...@@ -2889,8 +3181,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
$run_type = "ERROR"; $run_type = "ERROR";
} }
my $installme = "";
$installme = " no_install" if ($no_install);
doprint "\n\n"; doprint "\n\n";
doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n"; doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
unlink $dmesg; unlink $dmesg;
unlink $buildlog; unlink $buildlog;
...@@ -2911,6 +3206,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { ...@@ -2911,6 +3206,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
die "failed to checkout $checkout"; die "failed to checkout $checkout";
} }
$no_reboot = 0;
if ($test_type eq "bisect") { if ($test_type eq "bisect") {
bisect $i; bisect $i;
next; next;
...@@ -2929,6 +3227,13 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { ...@@ -2929,6 +3227,13 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
build $build_type or next; build $build_type or next;
} }
if ($test_type eq "install") {
get_version;
install;
success $i;
next;
}
if ($test_type ne "build") { if ($test_type ne "build") {
my $failed = 0; my $failed = 0;
start_monitor_and_boot or $failed = 1; start_monitor_and_boot or $failed = 1;
......
...@@ -72,6 +72,128 @@ ...@@ -72,6 +72,128 @@
# the same option name under the same test or as default # the same option name under the same test or as default
# ktest will fail to execute, and no tests will run. # ktest will fail to execute, and no tests will run.
# #
# DEFAULTS OVERRIDE
#
# Options defined in the DEFAULTS section can not be duplicated
# even if they are defined in two different DEFAULT sections.
# This is done to catch mistakes where an option is added but
# the previous option was forgotten about and not commented.
#
# The OVERRIDE keyword can be added to a section to allow this
# section to override other DEFAULT sections values that have
# been defined previously. It will only override options that
# have been defined before its use. Options defined later
# in a non override section will still error. The same option
# can not be defined in the same section even if that section
# is marked OVERRIDE.
#
#
#
# Both TEST_START and DEFAULTS sections can also have the IF keyword
# The value after the IF must evaluate into a 0 or non 0 positive
# integer, and can use the config variables (explained below).
#
# DEFAULTS IF ${IS_X86_32}
#
# The above will process the DEFAULTS section if the config
# variable IS_X86_32 evaluates to a non zero positive integer
# otherwise if it evaluates to zero, it will act the same
# as if the SKIP keyword was used.
#
# The ELSE keyword can be used directly after a section with
# a IF statement.
#
# TEST_START IF ${RUN_NET_TESTS}
# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network
#
# ELSE
#
# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-normal
#
#
# The ELSE keyword can also contain an IF statement to allow multiple
# if then else sections. But all the sections must be either
# DEFAULT or TEST_START, they can not be a mixture.
#
# TEST_START IF ${RUN_NET_TESTS}
# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network
#
# ELSE IF ${RUN_DISK_TESTS}
# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-tests
#
# ELSE IF ${RUN_CPU_TESTS}
# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-cpu
#
# ELSE
# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network
#
# The if statement may also have comparisons that will and for
# == and !=, strings may be used for both sides.
#
# BOX_TYPE := x86_32
#
# DEFAULTS IF ${BOX_TYPE} == x86_32
# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-32
# ELSE
# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-64
#
# The DEFINED keyword can be used by the IF statements too.
# It returns true if the given config variable or option has been defined
# or false otherwise.
#
#
# DEFAULTS IF DEFINED USE_CC
# CC := ${USE_CC}
# ELSE
# CC := gcc
#
#
# As well as NOT DEFINED.
#
# DEFAULTS IF NOT DEFINED MAKE_CMD
# MAKE_CMD := make ARCH=x86
#
#
# And/or ops (&&,||) may also be used to make complex conditionals.
#
# TEST_START IF (DEFINED ALL_TESTS || ${MYTEST} == boottest) && ${MACHINE} == gandalf
#
# Notice the use of paranthesis. Without any paranthesis the above would be
# processed the same as:
#
# TEST_START IF DEFINED ALL_TESTS || (${MYTEST} == boottest && ${MACHINE} == gandalf)
#
#
#
# INCLUDE file
#
# The INCLUDE keyword may be used in DEFAULT sections. This will
# read another config file and process that file as well. The included
# file can include other files, add new test cases or default
# statements. Config variables will be passed to these files and changes
# to config variables will be seen by top level config files. Including
# a file is processed just like the contents of the file was cut and pasted
# into the top level file, except, that include files that end with
# TEST_START sections will have that section ended at the end of
# the include file. That is, an included file is included followed
# by another DEFAULT keyword.
#
# Unlike other files referenced in this config, the file path does not need
# to be absolute. If the file does not start with '/', then the directory
# that the current config file was located in is used. If no config by the
# given name is found there, then the current directory is searched.
#
# INCLUDE myfile
# DEFAULT
#
# is the same as:
#
# INCLUDE myfile
#
# Note, if the include file does not contain a full path, the file is
# searched first by the location of the original include file, and then
# by the location that ktest.pl was executed in.
#
#### Config variables #### #### Config variables ####
# #
...@@ -253,9 +375,10 @@ ...@@ -253,9 +375,10 @@
# The default test type (default test) # The default test type (default test)
# The test types may be: # The test types may be:
# build - only build the kernel, do nothing else # build - only build the kernel, do nothing else
# boot - build and boot the kernel # install - build and install, but do nothing else (does not reboot)
# test - build, boot and if TEST is set, run the test script # boot - build, install, and boot the kernel
# test - build, boot and if TEST is set, run the test script
# (If TEST is not set, it defaults back to boot) # (If TEST is not set, it defaults back to boot)
# bisect - Perform a bisect on the kernel (see BISECT_TYPE below) # bisect - Perform a bisect on the kernel (see BISECT_TYPE below)
# patchcheck - Do a test on a series of commits in git (see PATCHCHECK below) # patchcheck - Do a test on a series of commits in git (see PATCHCHECK below)
...@@ -293,6 +416,13 @@ ...@@ -293,6 +416,13 @@
# or on some systems: # or on some systems:
#POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION #POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION
# If for some reason you just want to boot the kernel and you do not
# want the test to install anything new. For example, you may just want
# to boot test the same kernel over and over and do not want to go through
# the hassle of installing anything, you can set this option to 1
# (default 0)
#NO_INSTALL = 1
# If there is a script that you require to run before the build is done # If there is a script that you require to run before the build is done
# you can specify it with PRE_BUILD. # you can specify it with PRE_BUILD.
# #
...@@ -415,6 +545,14 @@ ...@@ -415,6 +545,14 @@
# (default "login:") # (default "login:")
#SUCCESS_LINE = login: #SUCCESS_LINE = login:
# To speed up between reboots, defining a line that the
# default kernel produces that represents that the default
# kernel has successfully booted and can be used to pass
# a new test kernel to it. Otherwise ktest.pl will wait till
# SLEEP_TIME to continue.
# (default undefined)
#REBOOT_SUCCESS_LINE = login:
# In case the console constantly fills the screen, having # In case the console constantly fills the screen, having
# a specified time to stop the test after success is recommended. # a specified time to stop the test after success is recommended.
# (in seconds) # (in seconds)
...@@ -480,6 +618,8 @@ ...@@ -480,6 +618,8 @@
# another test. If a reboot to the reliable kernel happens, # another test. If a reboot to the reliable kernel happens,
# we wait SLEEP_TIME for the console to stop producing output # we wait SLEEP_TIME for the console to stop producing output
# before starting the next test. # before starting the next test.
#
# You can speed up reboot times even more by setting REBOOT_SUCCESS_LINE.
# (default 60) # (default 60)
#SLEEP_TIME = 60 #SLEEP_TIME = 60
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment