aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/testing/ktest/ktest.pl207
1 files changed, 159 insertions, 48 deletions
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index a34f6f4193df..9eaf8d05c749 100644
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -23,6 +23,7 @@ $opt{"REBOOT_ON_ERROR"} = 0;
23$opt{"POWEROFF_ON_ERROR"} = 0; 23$opt{"POWEROFF_ON_ERROR"} = 0;
24$opt{"POWEROFF_ON_SUCCESS"} = 0; 24$opt{"POWEROFF_ON_SUCCESS"} = 0;
25$opt{"BUILD_OPTIONS"} = ""; 25$opt{"BUILD_OPTIONS"} = "";
26$opt{"BISECT_SLEEP_TIME"} = 10; # sleep time between bisects
26 27
27my $version; 28my $version;
28my $grub_number; 29my $grub_number;
@@ -32,6 +33,7 @@ my $noclean;
32my $minconfig; 33my $minconfig;
33my $in_bisect = 0; 34my $in_bisect = 0;
34my $bisect_bad = ""; 35my $bisect_bad = "";
36my $run_test;
35 37
36sub read_config { 38sub read_config {
37 my ($config) = @_; 39 my ($config) = @_;
@@ -68,7 +70,7 @@ sub doprint {
68} 70}
69 71
70sub dodie { 72sub dodie {
71 doprint "CRITICAL FAILURE... ", @_; 73 doprint "CRITICAL FAILURE... ", @_, "\n";
72 74
73 if ($opt{"REBOOT_ON_ERROR"}) { 75 if ($opt{"REBOOT_ON_ERROR"}) {
74 doprint "REBOOTING\n"; 76 doprint "REBOOTING\n";
@@ -84,14 +86,14 @@ sub dodie {
84 86
85sub run_command { 87sub run_command {
86 my ($command) = @_; 88 my ($command) = @_;
87 my $redirect = ""; 89 my $redirect_log = "";
88 90
89 if (defined($opt{"LOG_FILE"})) { 91 if (defined($opt{"LOG_FILE"})) {
90 $redirect = " >> $opt{LOG_FILE} 2>&1"; 92 $redirect_log = " >> $opt{LOG_FILE} 2>&1";
91 } 93 }
92 94
93 doprint "$command ... "; 95 doprint "$command ... ";
94 `$command $redirect`; 96 `$command $redirect_log`;
95 97
96 my $failed = $?; 98 my $failed = $?;
97 99
@@ -106,7 +108,7 @@ sub run_command {
106 108
107sub get_grub_index { 109sub get_grub_index {
108 110
109 return if ($grub_number >= 0); 111 return if (defined($grub_number));
110 112
111 doprint "Find grub menu ... "; 113 doprint "Find grub menu ... ";
112 $grub_number = -1; 114 $grub_number = -1;
@@ -164,28 +166,40 @@ sub reboot_to {
164 run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; 166 run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
165} 167}
166 168
167sub monitor { 169sub open_console {
170 my ($fp) = @_;
171
168 my $flags; 172 my $flags;
173
174 my $pid = open($fp, "$opt{CONSOLE}|") or
175 dodie "Can't open console $opt{CONSOLE}";
176
177 $flags = fcntl($fp, F_GETFL, 0) or
178 dodie "Can't get flags for the socket: $!\n";
179 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
180 dodie "Can't set flags for the socket: $!\n";
181
182 return $pid;
183}
184
185sub close_console {
186 my ($fp, $pid) = @_;
187
188 doprint "kill child process $pid\n";
189 kill 2, $pid;
190
191 print "closing!\n";
192 close($fp);
193}
194
195sub monitor {
169 my $booted = 0; 196 my $booted = 0;
170 my $bug = 0; 197 my $bug = 0;
171 my $pid; 198 my $pid;
172 my $doopen2 = 0;
173 my $skip_call_trace = 0; 199 my $skip_call_trace = 0;
200 my $fp = \*IN;
174 201
175 if ($doopen2) { 202 $pid = open_console($fp);
176 $pid = open2(\*IN, \*OUT, $opt{"CONSOLE"});
177 if ($pid < 0) {
178 dodie "Failed to connect to the console";
179 }
180 } else {
181 $pid = open(IN, "$opt{CONSOLE} |");
182 }
183
184 $flags = fcntl(IN, F_GETFL, 0) or
185 dodie "Can't get flags for the socket: $!\n";
186
187 $flags = fcntl(IN, F_SETFL, $flags | O_NONBLOCK) or
188 dodie "Can't set flags for the socket: $!\n";
189 203
190 my $line; 204 my $line;
191 my $full_line = ""; 205 my $full_line = "";
@@ -193,14 +207,14 @@ sub monitor {
193 doprint "Wait for monitor to settle down.\n"; 207 doprint "Wait for monitor to settle down.\n";
194 # read the monitor and wait for the system to calm down 208 # read the monitor and wait for the system to calm down
195 do { 209 do {
196 $line = wait_for_input(\*IN, 5); 210 $line = wait_for_input($fp, 5);
197 } while (defined($line)); 211 } while (defined($line));
198 212
199 reboot_to; 213 reboot_to;
200 214
201 for (;;) { 215 for (;;) {
202 216
203 $line = wait_for_input(\*IN); 217 $line = wait_for_input($fp);
204 218
205 last if (!defined($line)); 219 last if (!defined($line));
206 220
@@ -234,19 +248,15 @@ sub monitor {
234 } 248 }
235 } 249 }
236 250
237 doprint "kill child process $pid\n"; 251 close_console($fp, $pid);
238 kill 2, $pid;
239
240 print "closing!\n";
241 close(IN);
242 252
243 if (!$booted) { 253 if (!$booted) {
244 return 1 if (!$in_bisect); 254 return 1 if ($in_bisect);
245 dodie "failed - never got a boot prompt.\n"; 255 dodie "failed - never got a boot prompt.\n";
246 } 256 }
247 257
248 if ($bug) { 258 if ($bug) {
249 return 1 if (!$in_bisect); 259 return 1 if ($in_bisect);
250 dodie "failed - got a bug report\n"; 260 dodie "failed - got a bug report\n";
251 } 261 }
252 262
@@ -395,6 +405,84 @@ sub get_version {
395 doprint "$version\n"; 405 doprint "$version\n";
396} 406}
397 407
408sub child_run_test {
409 my $failed;
410
411 $failed = !run_command $run_test;
412 exit $failed;
413}
414
415my $child_done;
416
417sub child_finished {
418 $child_done = 1;
419}
420
421sub do_run_test {
422 my $child_pid;
423 my $child_exit;
424 my $pid;
425 my $line;
426 my $full_line;
427 my $bug = 0;
428 my $fp = \*IN;
429
430 $pid = open_console($fp);
431
432 # read the monitor and wait for the system to calm down
433 do {
434 $line = wait_for_input($fp, 1);
435 } while (defined($line));
436
437 $child_done = 0;
438
439 $SIG{CHLD} = qw(child_finished);
440
441 $child_pid = fork;
442
443 child_run_test if (!$child_pid);
444
445 $full_line = "";
446
447 do {
448 $line = wait_for_input($fp, 1);
449 if (defined($line)) {
450
451 # we are not guaranteed to get a full line
452 $full_line .= $line;
453
454 if ($full_line =~ /call trace:/i) {
455 $bug = 1;
456 }
457
458 if ($full_line =~ /Kernel panic -/) {
459 $bug = 1;
460 }
461
462 if ($line =~ /\n/) {
463 $full_line = "";
464 }
465 }
466 } while (!$child_done && !$bug);
467
468 if ($bug) {
469 doprint "Detected kernel crash!\n";
470 # kill the child with extreme prejudice
471 kill 9, $child_pid;
472 }
473
474 waitpid $child_pid, 0;
475 $child_exit = $?;
476
477 close_console($fp, $pid);
478
479 if ($bug || $child_exit) {
480 return 1 if $in_bisect;
481 dodie "test failed";
482 }
483 return 0;
484}
485
398sub run_bisect { 486sub run_bisect {
399 my ($type) = @_; 487 my ($type) = @_;
400 488
@@ -422,11 +510,20 @@ sub run_bisect {
422 510
423 if ($type ne "boot") { 511 if ($type ne "boot") {
424 dodie "Failed on boot" if $failed; 512 dodie "Failed on boot" if $failed;
513
514 $failed = do_run_test;
425 } 515 }
426 } 516 }
427 517
428 if ($failed) { 518 if ($failed) {
429 $result = "bad"; 519 $result = "bad";
520
521 # reboot the box to a good kernel
522 if ($type eq "boot") {
523 reboot;
524 doprint "sleep a little for reboot\n";
525 sleep $opt{"BISECT_SLEEP_TIME"};
526 }
430 } else { 527 } else {
431 $result = "good"; 528 $result = "good";
432 } 529 }
@@ -443,12 +540,15 @@ sub run_bisect {
443 } 540 }
444 541
445 doprint "SUCCESS\n"; 542 doprint "SUCCESS\n";
446 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\)) \[([[:xdigit:]]+)\]/) { 543 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
447 doprint "$1 [$2]\n"; 544 doprint "$1 [$2]\n";
448 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 545 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
449 $bisect_bad = $1; 546 $bisect_bad = $1;
450 doprint "Found bad commit... $1\n"; 547 doprint "Found bad commit... $1\n";
451 return 0; 548 return 0;
549 } else {
550 # we already logged it, just print it now.
551 print $output;
452 } 552 }
453 553
454 554
@@ -479,6 +579,11 @@ sub bisect {
479 run_command "git bisect bad $bad" or 579 run_command "git bisect bad $bad" or
480 dodie "could not set bisect good to $bad"; 580 dodie "could not set bisect good to $bad";
481 581
582 # Can't have a test without having a test to run
583 if ($type eq "test" && !defined($run_test)) {
584 $type = "boot";
585 }
586
482 do { 587 do {
483 $result = run_bisect $type; 588 $result = run_bisect $type;
484 } while ($result); 589 } while ($result);
@@ -519,29 +624,30 @@ doprint "\n\nSTARTING AUTOMATED TESTS\n";
519 624
520$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}"; 625$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}";
521 626
522# First we need to do is the builds 627sub set_build_option {
523for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) { 628 my ($name, $i) = @_;
524 my $type = "BUILD_TYPE[$i]";
525 629
526 if (defined($opt{"BUILD_NOCLEAN[$i]"}) && 630 my $option = "$name\[$i\]";
527 $opt{"BUILD_NOCLEAN[$i]"} != 0) {
528 $noclean = 1;
529 } else {
530 $noclean = $opt{"BUILD_NOCLEAN"};
531 }
532 631
533 if (defined($opt{"MIN_CONFIG[$i]"})) { 632 if (defined($opt{$option})) {
534 $minconfig = $opt{"MIN_CONFIG[$i]"}; 633 return $opt{$option};
535 } elsif (defined($opt{"MIN_CONFIG"})) {
536 $minconfig = $opt{"MIN_CONFIG"};
537 } else {
538 undef $minconfig;
539 } 634 }
540 635
541 if (!defined($opt{$type})) { 636 if (defined($opt{$name})) {
542 $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"}; 637 return $opt{$name};
543 } 638 }
544 639
640 return undef;
641}
642
643# First we need to do is the builds
644for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
645 my $type = "BUILD_TYPE[$i]";
646
647 $noclean = set_build_option("BUILD_NOCLEAN", $i);
648 $minconfig = set_build_option("MIN_CONFIG", $i);
649 $run_test = set_build_option("TEST", $i);
650
545 doprint "\n\n"; 651 doprint "\n\n";
546 doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n"; 652 doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n";
547 653
@@ -558,6 +664,11 @@ for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
558 get_version; 664 get_version;
559 install; 665 install;
560 monitor; 666 monitor;
667
668 if (defined($run_test)) {
669 do_run_test;
670 }
671
561 success $i; 672 success $i;
562} 673}
563 674