Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[pandora-kernel.git] / tools / testing / ktest / ktest.pl
index 7bce412..8b4c253 100755 (executable)
@@ -136,6 +136,9 @@ 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"
  The machine hostname that you will test.
 EOF
@@ -247,6 +250,7 @@ sub read_yn {
 
 sub get_ktest_config {
     my ($config) = @_;
+    my $ans;
 
     return if (defined($opt{$config}));
 
@@ -260,16 +264,17 @@ sub get_ktest_config {
        if (defined($default{$config})) {
            print "\[$default{$config}\] ";
        }
-       $entered_configs{$config} = <STDIN>;
-       $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/;
-       if ($entered_configs{$config} =~ /^\s*$/) {
+       $ans = <STDIN>;
+       $ans =~ s/^\s*(.*\S)\s*$/$1/;
+       if ($ans =~ /^\s*$/) {
            if ($default{$config}) {
-               $entered_configs{$config} = $default{$config};
+               $ans = $default{$config};
            } else {
                print "Your answer can not be blank\n";
                next;
            }
        }
+       $entered_configs{$config} = process_variables($ans);
        last;
     }
 }
@@ -304,7 +309,7 @@ sub get_ktest_configs {
 }
 
 sub process_variables {
-    my ($value) = @_;
+    my ($value, $remove_undef) = @_;
     my $retval = "";
 
     # We want to check for '\', and it is just easier
@@ -322,6 +327,10 @@ sub process_variables {
        $retval = "$retval$begin";
        if (defined($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 {
            # put back the origin piece.
            $retval = "$retval\$\{$var\}";
@@ -396,10 +405,47 @@ sub process_compare {
     return $ret;
 }
 
-sub process_if {
-    my ($name, $value) = @_;
+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 /;
+       }
+    }
 
-    my $val = process_variables($value);
+    $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);
@@ -409,14 +455,31 @@ sub process_if {
        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 variable $val in if statement\n");
-    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;
 }
 
 sub __read_config {
@@ -434,6 +497,7 @@ sub __read_config {
     my $num_tests_set = 0;
     my $skip = 0;
     my $rest;
+    my $line;
     my $test_case = 0;
     my $if = 0;
     my $if_set = 0;
@@ -450,6 +514,7 @@ sub __read_config {
 
            my $type = $1;
            $rest = $2;
+           $line = $2;
 
            my $old_test_num;
            my $old_repeat;
@@ -471,32 +536,28 @@ sub __read_config {
                $default = 1;
            }
 
-           if ($rest =~ /\s+SKIP\b(.*)/) {
-               $rest = $1;
+           # If SKIP is anywhere in the line, the command will be skipped
+           if ($rest =~ s/\s+SKIP\b//) {
                $skip = 1;
            } else {
                $test_case = 1;
                $skip = 0;
            }
 
-           if (!$skip) {
-               if ($type eq "TEST_START") {
-                   if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
-                       $repeat = $1;
-                       $rest = $2;
-                       $repeat_tests{"$test_num"} = $repeat;
-                   }
-               } elsif ($rest =~ /\sOVERRIDE\b(.*)/) {
-                   # DEFAULT only
-                   $rest = $1;
-                   $override = 1;
-                   # Clear previous overrides
-                   %overrides = ();
+           if ($rest =~ s/\sELSE\b//) {
+               if (!$if) {
+                   die "$name: $.: ELSE found with out matching IF section\n$_";
+               }
+               $if = 0;
+
+               if ($if_set) {
+                   $skip = 1;
+               } else {
+                   $skip = 0;
                }
            }
 
-           if ($rest =~ /\sIF\s+(.*)/) {
-               $rest = "";
+           if ($rest =~ s/\sIF\s+(.*)//) {
                if (process_if($name, $1)) {
                    $if_set = 1;
                } else {
@@ -505,9 +566,24 @@ sub __read_config {
                $if = 1;
            } else {
                $if = 0;
+               $if_set = 0;
            }
 
-           if ($rest !~ /^\s*$/) {
+           if (!$skip) {
+               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$_";
            }
 
@@ -671,6 +747,18 @@ sub __eval_option {
     # Add space to evaluate the character before $
     $option = " $option";
     my $retval = "";
+    my $repeated = 0;
+    my $parent = 0;
+
+    foreach my $test (keys %repeat_tests) {
+       if ($i >= $test &&
+           $i < $test + $repeat_tests{$test}) {
+
+           $repeated = 1;
+           $parent = $test;
+           last;
+       }
+    }
 
     while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
        my $start = $1;
@@ -684,10 +772,14 @@ sub __eval_option {
        # otherwise see if the default OPT (without [$i]) exists.
 
        my $o = "$var\[$i\]";
+       my $parento = "$var\[$parent\]";
 
        if (defined($opt{$o})) {
            $o = $opt{$o};
            $retval = "$retval$o";
+       } elsif ($repeated && defined($opt{$parento})) {
+           $o = $opt{$parento};
+           $retval = "$retval$o";
        } elsif (defined($opt{$var})) {
            $o = $opt{$var};
            $retval = "$retval$o";
@@ -1079,7 +1171,8 @@ sub wait_for_input
 
 sub reboot_to {
     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;
     }
 
@@ -1319,6 +1412,11 @@ sub get_version {
 }
 
 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_version;
     install;
@@ -2357,12 +2455,31 @@ sub patchcheck {
 }
 
 my %depends;
+my %depcount;
 my $iflevel = 0;
 my @ifdeps;
 
 # prevent recursion
 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
 sub read_kconfig {
     my ($kconfig) = @_;
@@ -2409,30 +2526,19 @@ sub read_kconfig {
            $config = $2;
 
            for (my $i = 0; $i < $iflevel; $i++) {
-               if ($i) {
-                   $depends{$config} .= " " . $ifdeps[$i];
-               } else {
-                   $depends{$config} = $ifdeps[$i];
-               }
-               $state = "DEP";
+               add_dep $config, $ifdeps[$i];
            }
 
        # collect the depends for the config
        } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
 
-           if (defined($depends{$1})) {
-               $depends{$config} .= " " . $1;
-           } else {
-               $depends{$config} = $1;
-           }
+           add_dep $config, $1;
 
        # Get the configs that select this config
-       } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
-           if (defined($depends{$1})) {
-               $depends{$1} .= " " . $config;
-           } else {
-               $depends{$1} = $config;
-           }
+       } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
+
+           # selected by depends on config
+           add_dep $1, $config;
 
        # Check for if statements
        } elsif (/^if\s+(.*\S)\s*$/) {
@@ -2544,11 +2650,18 @@ sub make_new_config {
     close OUT;
 }
 
+sub chomp_config {
+    my ($config) = @_;
+
+    $config =~ s/CONFIG_//;
+
+    return $config;
+}
+
 sub get_depends {
     my ($dep) = @_;
 
-    my $kconfig = $dep;
-    $kconfig =~ s/CONFIG_//;
+    my $kconfig = chomp_config $dep;
 
     $dep = $depends{"$kconfig"};
 
@@ -2598,8 +2711,7 @@ sub test_this_config {
        return undef;
     }
 
-    my $kconfig = $config;
-    $kconfig =~ s/CONFIG_//;
+    my $kconfig = chomp_config $config;
 
     # Test dependencies first
     if (defined($depends{"$kconfig"})) {
@@ -2689,6 +2801,14 @@ sub make_min_config {
 
     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
     # we shouldn't need them as they get set for us anyway.
     foreach my $config (@config_keys) {
@@ -2727,8 +2847,13 @@ sub make_min_config {
        # Now disable each config one by one and do a make oldconfig
        # 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;
+
+       # 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;
        for (my $i = 0; $i < $#test_configs; $i++) {
            if (!defined($nochange_config{$test_configs[0]})) {