ktest: Add open and close console and start stop monitor
authorSteven Rostedt <srostedt@redhat.com>
Tue, 2 Nov 2010 18:58:22 +0000 (14:58 -0400)
committerSteven Rostedt <rostedt@goodmis.org>
Thu, 18 Nov 2010 16:23:08 +0000 (11:23 -0500)
It is much better to keep the monitor running throughout a
test than to constantly start and stop it. Some console readers
will show everything that has happened before when opening the
console, and by opening it several times, causes the old content to
be read multiple times in a single test.

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
tools/testing/ktest/ktest.pl

index 0a0b1b16fccd3718e40dc3444ffca5f0737a15fb..ff6283a44847a0a8c4580e7effce6031ca20b8a8 100644 (file)
@@ -7,6 +7,8 @@
 use strict;
 use IPC::Open2;
 use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
+use File::Path qw(mkpath);
+use File::Copy qw(cp);
 use FileHandle;
 
 $#ARGV >= 0 || die "usage: autotest.pl config-file\n";
@@ -17,7 +19,7 @@ my %opt;
 
 #default opts
 $opt{"NUM_BUILDS"}             = 5;
-$opt{"DEFAULT_BUILD_TYPE"}     = "randconfig";
+$opt{"BUILD_TYPE"}             = "randconfig";
 $opt{"MAKE_CMD"}               = "make";
 $opt{"TIMEOUT"}                        = 120;
 $opt{"TMP_DIR"}                        = "/tmp/autotest";
@@ -35,6 +37,7 @@ $opt{"BOOTED_TIMEOUT"}                = 1;
 $opt{"DIE_ON_FAILURE"}         = 1;
 
 my $version;
+my $build_type;
 my $grub_number;
 my $target;
 my $make;
@@ -47,6 +50,11 @@ my $reverse_bisect;
 my $in_patchcheck = 0;
 my $run_test;
 my $redirect;
+my $buildlog;
+my $dmesg;
+my $monitor_fp;
+my $monitor_pid;
+my $monitor_cnt = 0;
 
 sub read_config {
     my ($config) = @_;
@@ -82,12 +90,22 @@ sub doprint {
     logit @_;
 }
 
+sub run_command;
+
+sub reboot {
+    # try to reboot normally
+    if (!run_command "ssh $target reboot") {
+       # nope? power cycle it.
+       run_command "$opt{POWER_CYCLE}";
+    }
+}
+
 sub dodie {
     doprint "CRITICAL FAILURE... ", @_, "\n";
 
     if ($opt{"REBOOT_ON_ERROR"}) {
        doprint "REBOOTING\n";
-       `$opt{"POWER_CYCLE"}`;
+       reboot;
 
     } elsif ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) {
        doprint "POWERING OFF\n";
@@ -97,6 +115,59 @@ sub dodie {
     die @_;
 }
 
+sub open_console {
+    my ($fp) = @_;
+
+    my $flags;
+
+    my $pid = open($fp, "$opt{CONSOLE}|") or
+       dodie "Can't open console $opt{CONSOLE}";
+
+    $flags = fcntl($fp, F_GETFL, 0) or
+       dodie "Can't get flags for the socket: $!\n";
+    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
+       dodie "Can't set flags for the socket: $!\n";
+
+    return $pid;
+}
+
+sub close_console {
+    my ($fp, $pid) = @_;
+
+    doprint "kill child process $pid\n";
+    kill 2, $pid;
+
+    print "closing!\n";
+    close($fp);
+}
+
+sub start_monitor {
+    if ($monitor_cnt++) {
+       return;
+    }
+    $monitor_fp = \*MONFD;
+    $monitor_pid = open_console $monitor_fp;
+}
+
+sub end_monitor {
+    if (--$monitor_cnt) {
+       return;
+    }
+    close_console($monitor_fp, $monitor_pid);
+}
+
+sub wait_for_monitor {
+    my ($time) = @_;
+    my $line;
+
+    doprint "Wait for monitor to settle down.\n";
+
+    # read the monitor and wait for the system to calm down
+    do {
+       $line = wait_for_input($monitor_fp, $time);
+    } while (defined($line));
+}
+
 sub fail {
 
        if ($opt{"DIE_ON_FAILURE"}) {
@@ -104,6 +175,41 @@ sub fail {
        }
 
        doprint "Failed: ", @_, "\n";
+
+       doprint "REBOOTING\n";
+       reboot;
+       start_monitor;
+       wait_for_monitor $opt{"SLEEP_TIME"};
+       end_monitor;
+
+       return 1 if (!defined($opt{"STORE_FAILURES"}));
+
+       my @t = localtime;
+       my $date = sprintf "%04d%02d%02d%02d%02d%02d",
+               1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
+
+       my $dir = "$opt{MACHINE}-$build_type-fail-$date";
+       my $faildir = "$opt{STORE_FAILURES}/$dir";
+
+       if (!-d $faildir) {
+           mkpath($faildir) or
+               die "can't create $opt{STORE_FAILURES}";
+       }
+       if (-f "$opt{OUTPUT_DIR}/.config") {
+           cp "$opt{OUTPUT_DIR}/.config", "$faildir/config" or
+               die "failed to copy .config";
+       }
+       if (-f $buildlog) {
+           cp $buildlog, "$faildir/buildlog" or
+               die "failed to move $buildlog";
+       }
+       if (-f $dmesg) {
+           cp $dmesg, "$faildir/dmesg" or
+               die "failed to move $dmesg";
+       }
+
+       doprint "*** Saved info to $faildir ***\n";
+
        return 1;
 }
 
@@ -211,64 +317,34 @@ sub reboot_to {
     run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
 }
 
-sub open_console {
-    my ($fp) = @_;
-
-    my $flags;
-
-    my $pid = open($fp, "$opt{CONSOLE}|") or
-       dodie "Can't open console $opt{CONSOLE}";
-
-    $flags = fcntl($fp, F_GETFL, 0) or
-       dodie "Can't get flags for the socket: $!\n";
-    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
-       dodie "Can't set flags for the socket: $!\n";
-
-    return $pid;
-}
-
-sub close_console {
-    my ($fp, $pid) = @_;
-
-    doprint "kill child process $pid\n";
-    kill 2, $pid;
-
-    print "closing!\n";
-    close($fp);
-}
-
 sub monitor {
     my $booted = 0;
     my $bug = 0;
-    my $pid;
     my $skip_call_trace = 0;
-    my $fp = \*IN;
     my $loops;
 
-    $pid = open_console($fp);
+    wait_for_monitor 5;
 
     my $line;
     my $full_line = "";
 
-    doprint "Wait for monitor to settle down.\n";
-    # read the monitor and wait for the system to calm down
-    do {
-       $line = wait_for_input($fp, 5);
-    } while (defined($line));
+    open(DMESG, "> $dmesg") or
+       die "unable to write to $dmesg";
 
     reboot_to;
 
     for (;;) {
 
        if ($booted) {
-           $line = wait_for_input($fp, $opt{"BOOTED_TIMEOUT"});
+           $line = wait_for_input($monitor_fp, $opt{"BOOTED_TIMEOUT"});
        } else {
-           $line = wait_for_input($fp);
+           $line = wait_for_input($monitor_fp);
        }
 
        last if (!defined($line));
 
        doprint $line;
+       print DMESG $line;
 
        # we are not guaranteed to get a full line
        $full_line .= $line;
@@ -298,7 +374,7 @@ sub monitor {
        }
     }
 
-    close_console($fp, $pid);
+    close(DMESG);
 
     if (!$booted) {
        return 0 if ($in_bisect);
@@ -363,7 +439,6 @@ sub install {
 sub check_buildlog {
     my ($patch) = @_;
 
-    my $buildlog = "$opt{TMP_DIR}/buildlog";
     my @files = `git show $patch | diffstat -l`;
 
     open(IN, "git show $patch |") or
@@ -398,6 +473,8 @@ sub build {
     my $defconfig = "";
     my $append = "";
 
+    unlink $buildlog;
+
     if ($type =~ /^useconfig:(.*)/) {
        run_command "cp $1 $opt{OUTPUT_DIR}/.config" or
            dodie "could not copy $1 to .config";
@@ -440,11 +517,7 @@ sub build {
     run_command "$defconfig $append $make $type" or
        dodie "failed make config";
 
-    # patch check will examine the log
-    if ($in_patchcheck) {
-       $redirect = "$opt{TMP_DIR}/buildlog";
-    }
-
+    $redirect = "$opt{TMP_DIR}/buildlog";
     if (!run_command "$make $opt{BUILD_OPTIONS}") {
        undef $redirect;
        # bisect may need this to pass
@@ -456,14 +529,6 @@ sub build {
     return 1;
 }
 
-sub reboot {
-    # try to reboot normally
-    if (!run_command "ssh $target reboot") {
-       # nope? power cycle it.
-       run_command "$opt{POWER_CYCLE}";
-    }
-}
-
 sub halt {
     if (!run_command "ssh $target halt" or defined($opt{"POWER_OFF"})) {
        # nope? the zap it!
@@ -481,9 +546,11 @@ sub success {
     doprint     "*******************************************\n";
 
     if ($i != $opt{"NUM_BUILDS"}) {
+       doprint "Reboot and wait $opt{SLEEP_TIME} seconds\n";
        reboot;
-       doprint "Sleeping $opt{SLEEP_TIME} seconds\n";
-       sleep "$opt{SLEEP_TIME}";
+       start_monitor;
+       wait_for_monitor $opt{"SLEEP_TIME"};
+       end_monitor;
     }
 }
 
@@ -496,9 +563,14 @@ sub get_version {
 }
 
 sub child_run_test {
-    my $failed;
+    my $failed = 0;
 
-    $failed = !run_command $run_test;
+    # child should have no power
+    $opt{"REBOOT_ON_ERROR"} = 0;
+    $opt{"POWEROFF_ON_ERROR"} = 0;
+    $opt{"DIE_ON_FAILURE"} = 1;
+
+    run_command $run_test or $failed = 1;
     exit $failed;
 }
 
@@ -511,18 +583,13 @@ sub child_finished {
 sub do_run_test {
     my $child_pid;
     my $child_exit;
-    my $pid;
     my $line;
     my $full_line;
     my $bug = 0;
-    my $fp = \*IN;
 
-    $pid = open_console($fp);
+    wait_for_monitor 1;
 
-    # read the monitor and wait for the system to calm down
-    do {
-       $line = wait_for_input($fp, 1);
-    } while (defined($line));
+    doprint "run test $run_test\n";
 
     $child_done = 0;
 
@@ -535,7 +602,7 @@ sub do_run_test {
     $full_line = "";
 
     do {
-       $line = wait_for_input($fp, 1);
+       $line = wait_for_input($monitor_fp, 1);
        if (defined($line)) {
 
            # we are not guaranteed to get a full line
@@ -564,8 +631,6 @@ sub do_run_test {
     waitpid $child_pid, 0;
     $child_exit = $?;
 
-    close_console($fp, $pid);
-
     if ($bug || $child_exit) {
        return 0 if $in_bisect;
        fail "test failed" and return 0;
@@ -589,19 +654,22 @@ sub run_bisect {
     }
 
     if ($type ne "build") {
-       fail "Failed on build" if $failed;
+       dodie "Failed on build" if $failed;
 
        # Now boot the box
        get_grub_index;
        get_version;
        install;
+
+       start_monitor;
        monitor or $failed = 1;
 
        if ($type ne "boot") {
-           fail "Failed on boot" if $failed;
+           dodie "Failed on boot" if $failed;
 
            do_run_test or $failed = 1;
        }
+       end_monitor;
     }
 
     if ($failed) {
@@ -609,9 +677,11 @@ sub run_bisect {
 
        # reboot the box to a good kernel
        if ($type eq "boot") {
+           doprint "Reboot and sleep $opt{BISECT_SLEEP_TIME} seconds\n";
            reboot;
-           doprint "sleep a little for reboot\n";
-           sleep $opt{"BISECT_SLEEP_TIME"};
+           start_monitor;
+           wait_for_monitor $opt{"BISECT_SLEEP_TIME"};
+           end_monitor;
        }
     } else {
        $result = "good";
@@ -782,10 +852,18 @@ sub patchcheck {
        get_grub_index;
        get_version;
        install;
-       monitor or return 0;
 
-       next if ($type eq "boot");
-       do_run_test or next;
+       my $failed = 0;
+
+       start_monitor;
+       monitor or $failed = 1;
+
+       if (!$failed && $type ne "boot"){
+           do_run_test or $failed = 1;
+       }
+       end_monitor;
+       return 0 if ($failed);
+
     }
     $in_patchcheck = 0;
     success $i;
@@ -821,6 +899,8 @@ foreach my $option (sort keys %opt) {
     doprint "$option = $opt{$option}\n";
 }
 
+$buildlog = "$opt{TMP_DIR}/buildlog";
+$dmesg = "$opt{TMP_DIR}/dmesg";
 $make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}";
 
 sub set_build_option {
@@ -841,19 +921,18 @@ sub set_build_option {
 
 # First we need to do is the builds
 for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
-    my $type = "BUILD_TYPE[$i]";
-
-    if (!defined($opt{$type})) {
-       $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"};
-    }
 
+    $build_type = set_build_option("BUILD_TYPE", $i);
     $noclean = set_build_option("BUILD_NOCLEAN", $i);
     $minconfig = set_build_option("MIN_CONFIG", $i);
     $run_test = set_build_option("TEST", $i);
     $addconfig = set_build_option("ADD_CONFIG", $i);
 
     doprint "\n\n";
-    doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n";
+    doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $build_type\n\n";
+
+    unlink $dmesg;
+    unlink $buildlog;
 
     if (!defined($minconfig)) {
        $minconfig = $addconfig;
@@ -870,26 +949,30 @@ for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
            die "failed to checkout $checkout";
     }
 
-    if ($opt{$type} eq "bisect") {
+    if ($build_type eq "bisect") {
        bisect $i;
        next;
-    } elsif ($opt{$type} eq "patchcheck") {
+    } elsif ($build_type eq "patchcheck") {
        patchcheck $i;
        next;
     }
 
-    if ($opt{$type} ne "nobuild") {
-       build $opt{$type} or next;
+    if ($build_type ne "nobuild") {
+       build $build_type or next;
     }
 
     get_grub_index;
     get_version;
     install;
-    monitor or next;
 
-    if (defined($run_test)) {
-       do_run_test or next;
+    my $failed = 0;
+    start_monitor;
+    monitor or $failed = 1;;
+    if (!$failed && defined($run_test)) {
+       do_run_test or $failed = 1;
     }
+    end_monitor;
+    next if ($failed);
 
     success $i;
 }