Commit 5a391fbff8755592eb080784ef32ff818d2daa44
Committed by
Steven Rostedt
1 parent
5f9b6ced04
Exists in
master
and in
4 other branches
ktest: Added better console, add test build
Better reading of the console. Added running a script to do testing after build succeeds. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Showing 1 changed file with 159 additions and 48 deletions Side-by-side Diff
tools/testing/ktest/ktest.pl
... | ... | @@ -23,6 +23,7 @@ |
23 | 23 | $opt{"POWEROFF_ON_ERROR"} = 0; |
24 | 24 | $opt{"POWEROFF_ON_SUCCESS"} = 0; |
25 | 25 | $opt{"BUILD_OPTIONS"} = ""; |
26 | +$opt{"BISECT_SLEEP_TIME"} = 10; # sleep time between bisects | |
26 | 27 | |
27 | 28 | my $version; |
28 | 29 | my $grub_number; |
... | ... | @@ -32,6 +33,7 @@ |
32 | 33 | my $minconfig; |
33 | 34 | my $in_bisect = 0; |
34 | 35 | my $bisect_bad = ""; |
36 | +my $run_test; | |
35 | 37 | |
36 | 38 | sub read_config { |
37 | 39 | my ($config) = @_; |
... | ... | @@ -68,7 +70,7 @@ |
68 | 70 | } |
69 | 71 | |
70 | 72 | sub dodie { |
71 | - doprint "CRITICAL FAILURE... ", @_; | |
73 | + doprint "CRITICAL FAILURE... ", @_, "\n"; | |
72 | 74 | |
73 | 75 | if ($opt{"REBOOT_ON_ERROR"}) { |
74 | 76 | doprint "REBOOTING\n"; |
75 | 77 | |
76 | 78 | |
... | ... | @@ -84,14 +86,14 @@ |
84 | 86 | |
85 | 87 | sub run_command { |
86 | 88 | my ($command) = @_; |
87 | - my $redirect = ""; | |
89 | + my $redirect_log = ""; | |
88 | 90 | |
89 | 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 | 95 | doprint "$command ... "; |
94 | - `$command $redirect`; | |
96 | + `$command $redirect_log`; | |
95 | 97 | |
96 | 98 | my $failed = $?; |
97 | 99 | |
... | ... | @@ -106,7 +108,7 @@ |
106 | 108 | |
107 | 109 | sub get_grub_index { |
108 | 110 | |
109 | - return if ($grub_number >= 0); | |
111 | + return if (defined($grub_number)); | |
110 | 112 | |
111 | 113 | doprint "Find grub menu ... "; |
112 | 114 | $grub_number = -1; |
113 | 115 | |
114 | 116 | |
115 | 117 | |
116 | 118 | |
117 | 119 | |
118 | 120 | |
119 | 121 | |
... | ... | @@ -164,43 +166,55 @@ |
164 | 166 | run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; |
165 | 167 | } |
166 | 168 | |
167 | -sub monitor { | |
169 | +sub open_console { | |
170 | + my ($fp) = @_; | |
171 | + | |
168 | 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 | + | |
185 | +sub 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 | + | |
195 | +sub monitor { | |
169 | 196 | my $booted = 0; |
170 | 197 | my $bug = 0; |
171 | 198 | my $pid; |
172 | - my $doopen2 = 0; | |
173 | 199 | my $skip_call_trace = 0; |
200 | + my $fp = \*IN; | |
174 | 201 | |
175 | - if ($doopen2) { | |
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 | - } | |
202 | + $pid = open_console($fp); | |
183 | 203 | |
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 | - | |
190 | 204 | my $line; |
191 | 205 | my $full_line = ""; |
192 | 206 | |
193 | 207 | doprint "Wait for monitor to settle down.\n"; |
194 | 208 | # read the monitor and wait for the system to calm down |
195 | 209 | do { |
196 | - $line = wait_for_input(\*IN, 5); | |
210 | + $line = wait_for_input($fp, 5); | |
197 | 211 | } while (defined($line)); |
198 | 212 | |
199 | 213 | reboot_to; |
200 | 214 | |
201 | 215 | for (;;) { |
202 | 216 | |
203 | - $line = wait_for_input(\*IN); | |
217 | + $line = wait_for_input($fp); | |
204 | 218 | |
205 | 219 | last if (!defined($line)); |
206 | 220 | |
207 | 221 | |
208 | 222 | |
209 | 223 | |
... | ... | @@ -234,19 +248,15 @@ |
234 | 248 | } |
235 | 249 | } |
236 | 250 | |
237 | - doprint "kill child process $pid\n"; | |
238 | - kill 2, $pid; | |
251 | + close_console($fp, $pid); | |
239 | 252 | |
240 | - print "closing!\n"; | |
241 | - close(IN); | |
242 | - | |
243 | 253 | if (!$booted) { |
244 | - return 1 if (!$in_bisect); | |
254 | + return 1 if ($in_bisect); | |
245 | 255 | dodie "failed - never got a boot prompt.\n"; |
246 | 256 | } |
247 | 257 | |
248 | 258 | if ($bug) { |
249 | - return 1 if (!$in_bisect); | |
259 | + return 1 if ($in_bisect); | |
250 | 260 | dodie "failed - got a bug report\n"; |
251 | 261 | } |
252 | 262 | |
... | ... | @@ -395,6 +405,84 @@ |
395 | 405 | doprint "$version\n"; |
396 | 406 | } |
397 | 407 | |
408 | +sub child_run_test { | |
409 | + my $failed; | |
410 | + | |
411 | + $failed = !run_command $run_test; | |
412 | + exit $failed; | |
413 | +} | |
414 | + | |
415 | +my $child_done; | |
416 | + | |
417 | +sub child_finished { | |
418 | + $child_done = 1; | |
419 | +} | |
420 | + | |
421 | +sub 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 | + | |
398 | 486 | sub run_bisect { |
399 | 487 | my ($type) = @_; |
400 | 488 | |
401 | 489 | |
... | ... | @@ -422,11 +510,20 @@ |
422 | 510 | |
423 | 511 | if ($type ne "boot") { |
424 | 512 | dodie "Failed on boot" if $failed; |
513 | + | |
514 | + $failed = do_run_test; | |
425 | 515 | } |
426 | 516 | } |
427 | 517 | |
428 | 518 | if ($failed) { |
429 | 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 | 527 | } else { |
431 | 528 | $result = "good"; |
432 | 529 | } |
433 | 530 | |
... | ... | @@ -443,12 +540,15 @@ |
443 | 540 | } |
444 | 541 | |
445 | 542 | doprint "SUCCESS\n"; |
446 | - if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\)) \[([[:xdigit:]]+)\]/) { | |
543 | + if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { | |
447 | 544 | doprint "$1 [$2]\n"; |
448 | 545 | } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { |
449 | 546 | $bisect_bad = $1; |
450 | 547 | doprint "Found bad commit... $1\n"; |
451 | 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 @@ |
479 | 579 | run_command "git bisect bad $bad" or |
480 | 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 | 587 | do { |
483 | 588 | $result = run_bisect $type; |
484 | 589 | } while ($result); |
485 | 590 | |
486 | 591 | |
487 | 592 | |
488 | 593 | |
... | ... | @@ -519,29 +624,30 @@ |
519 | 624 | |
520 | 625 | $make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}"; |
521 | 626 | |
522 | -# First we need to do is the builds | |
523 | -for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) { | |
524 | - my $type = "BUILD_TYPE[$i]"; | |
627 | +sub set_build_option { | |
628 | + my ($name, $i) = @_; | |
525 | 629 | |
526 | - if (defined($opt{"BUILD_NOCLEAN[$i]"}) && | |
527 | - $opt{"BUILD_NOCLEAN[$i]"} != 0) { | |
528 | - $noclean = 1; | |
529 | - } else { | |
530 | - $noclean = $opt{"BUILD_NOCLEAN"}; | |
531 | - } | |
630 | + my $option = "$name\[$i\]"; | |
532 | 631 | |
533 | - if (defined($opt{"MIN_CONFIG[$i]"})) { | |
534 | - $minconfig = $opt{"MIN_CONFIG[$i]"}; | |
535 | - } elsif (defined($opt{"MIN_CONFIG"})) { | |
536 | - $minconfig = $opt{"MIN_CONFIG"}; | |
537 | - } else { | |
538 | - undef $minconfig; | |
632 | + if (defined($opt{$option})) { | |
633 | + return $opt{$option}; | |
539 | 634 | } |
540 | 635 | |
541 | - if (!defined($opt{$type})) { | |
542 | - $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"}; | |
636 | + if (defined($opt{$name})) { | |
637 | + return $opt{$name}; | |
543 | 638 | } |
544 | 639 | |
640 | + return undef; | |
641 | +} | |
642 | + | |
643 | +# First we need to do is the builds | |
644 | +for (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 | 651 | doprint "\n\n"; |
546 | 652 | doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n"; |
547 | 653 | |
... | ... | @@ -558,6 +664,11 @@ |
558 | 664 | get_version; |
559 | 665 | install; |
560 | 666 | monitor; |
667 | + | |
668 | + if (defined($run_test)) { | |
669 | + do_run_test; | |
670 | + } | |
671 | + | |
561 | 672 | success $i; |
562 | 673 | } |
563 | 674 |