ktest.pl (5f9b6ced04a4e9c3ee6b4d4042ac5935ef5a8dbd) | ktest.pl (5a391fbff8755592eb080784ef32ff818d2daa44) |
---|---|
1#!/usr/bin/perl -w 2 3use strict; 4use IPC::Open2; 5use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); 6use FileHandle; 7 8$#ARGV >= 0 || die "usage: autotest.pl config-file\n"; --- 9 unchanged lines hidden (view full) --- 18$opt{"TIMEOUT"} = 50; 19$opt{"TMP_DIR"} = "/tmp/autotest"; 20$opt{"SLEEP_TIME"} = 60; # sleep time between tests 21$opt{"BUILD_NOCLEAN"} = 0; 22$opt{"REBOOT_ON_ERROR"} = 0; 23$opt{"POWEROFF_ON_ERROR"} = 0; 24$opt{"POWEROFF_ON_SUCCESS"} = 0; 25$opt{"BUILD_OPTIONS"} = ""; | 1#!/usr/bin/perl -w 2 3use strict; 4use IPC::Open2; 5use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); 6use FileHandle; 7 8$#ARGV >= 0 || die "usage: autotest.pl config-file\n"; --- 9 unchanged lines hidden (view full) --- 18$opt{"TIMEOUT"} = 50; 19$opt{"TMP_DIR"} = "/tmp/autotest"; 20$opt{"SLEEP_TIME"} = 60; # sleep time between tests 21$opt{"BUILD_NOCLEAN"} = 0; 22$opt{"REBOOT_ON_ERROR"} = 0; 23$opt{"POWEROFF_ON_ERROR"} = 0; 24$opt{"POWEROFF_ON_SUCCESS"} = 0; 25$opt{"BUILD_OPTIONS"} = ""; |
26$opt{"BISECT_SLEEP_TIME"} = 10; # sleep time between bisects |
|
26 27my $version; 28my $grub_number; 29my $target; 30my $make; 31my $noclean; 32my $minconfig; 33my $in_bisect = 0; 34my $bisect_bad = ""; | 27 28my $version; 29my $grub_number; 30my $target; 31my $make; 32my $noclean; 33my $minconfig; 34my $in_bisect = 0; 35my $bisect_bad = ""; |
36my $run_test; |
|
35 36sub read_config { 37 my ($config) = @_; 38 39 open(IN, $config) || die "can't read file $config"; 40 41 while (<IN>) { 42 --- 20 unchanged lines hidden (view full) --- 63} 64 65sub doprint { 66 print @_; 67 logit @_; 68} 69 70sub dodie { | 37 38sub read_config { 39 my ($config) = @_; 40 41 open(IN, $config) || die "can't read file $config"; 42 43 while (<IN>) { 44 --- 20 unchanged lines hidden (view full) --- 65} 66 67sub doprint { 68 print @_; 69 logit @_; 70} 71 72sub dodie { |
71 doprint "CRITICAL FAILURE... ", @_; | 73 doprint "CRITICAL FAILURE... ", @_, "\n"; |
72 73 if ($opt{"REBOOT_ON_ERROR"}) { 74 doprint "REBOOTING\n"; 75 `$opt{"POWER_CYCLE"}`; 76 77 } elsif ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) { 78 doprint "POWERING OFF\n"; 79 `$opt{"POWER_OFF"}`; 80 } 81 82 die @_; 83} 84 85sub run_command { 86 my ($command) = @_; | 74 75 if ($opt{"REBOOT_ON_ERROR"}) { 76 doprint "REBOOTING\n"; 77 `$opt{"POWER_CYCLE"}`; 78 79 } elsif ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) { 80 doprint "POWERING OFF\n"; 81 `$opt{"POWER_OFF"}`; 82 } 83 84 die @_; 85} 86 87sub run_command { 88 my ($command) = @_; |
87 my $redirect = ""; | 89 my $redirect_log = ""; |
88 89 if (defined($opt{"LOG_FILE"})) { | 90 91 if (defined($opt{"LOG_FILE"})) { |
90 $redirect = " >> $opt{LOG_FILE} 2>&1"; | 92 $redirect_log = " >> $opt{LOG_FILE} 2>&1"; |
91 } 92 93 doprint "$command ... "; | 93 } 94 95 doprint "$command ... "; |
94 `$command $redirect`; | 96 `$command $redirect_log`; |
95 96 my $failed = $?; 97 98 if ($failed) { 99 doprint "FAILED!\n"; 100 } else { 101 doprint "SUCCESS\n"; 102 } 103 104 return !$failed; 105} 106 107sub get_grub_index { 108 | 97 98 my $failed = $?; 99 100 if ($failed) { 101 doprint "FAILED!\n"; 102 } else { 103 doprint "SUCCESS\n"; 104 } 105 106 return !$failed; 107} 108 109sub get_grub_index { 110 |
109 return if ($grub_number >= 0); | 111 return if (defined($grub_number)); |
110 111 doprint "Find grub menu ... "; 112 $grub_number = -1; 113 open(IN, "ssh $target cat /boot/grub/menu.lst |") 114 or die "unable to get menu.lst"; 115 while (<IN>) { 116 if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) { 117 $grub_number++; --- 41 unchanged lines hidden (view full) --- 159 160 return $line; 161} 162 163sub reboot_to { 164 run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; 165} 166 | 112 113 doprint "Find grub menu ... "; 114 $grub_number = -1; 115 open(IN, "ssh $target cat /boot/grub/menu.lst |") 116 or die "unable to get menu.lst"; 117 while (<IN>) { 118 if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) { 119 $grub_number++; --- 41 unchanged lines hidden (view full) --- 161 162 return $line; 163} 164 165sub reboot_to { 166 run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; 167} 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; 170 my $bug = 0; 171 my $pid; | 196 my $booted = 0; 197 my $bug = 0; 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) { 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 my $line; 191 my $full_line = ""; 192 193 doprint "Wait for monitor to settle down.\n"; 194 # read the monitor and wait for the system to calm down 195 do { | 204 my $line; 205 my $full_line = ""; 206 207 doprint "Wait for monitor to settle down.\n"; 208 # read the monitor and wait for the system to calm down 209 do { |
196 $line = wait_for_input(\*IN, 5); | 210 $line = wait_for_input($fp, 5); |
197 } while (defined($line)); 198 199 reboot_to; 200 201 for (;;) { 202 | 211 } while (defined($line)); 212 213 reboot_to; 214 215 for (;;) { 216 |
203 $line = wait_for_input(\*IN); | 217 $line = wait_for_input($fp); |
204 205 last if (!defined($line)); 206 207 doprint $line; 208 209 # we are not guaranteed to get a full line 210 $full_line .= $line; 211 --- 17 unchanged lines hidden (view full) --- 229 $bug = 1; 230 } 231 232 if ($line =~ /\n/) { 233 $full_line = ""; 234 } 235 } 236 | 218 219 last if (!defined($line)); 220 221 doprint $line; 222 223 # we are not guaranteed to get a full line 224 $full_line .= $line; 225 --- 17 unchanged lines hidden (view full) --- 243 $bug = 1; 244 } 245 246 if ($line =~ /\n/) { 247 $full_line = ""; 248 } 249 } 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 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"; 246 } 247 248 if ($bug) { | 255 dodie "failed - never got a boot prompt.\n"; 256 } 257 258 if ($bug) { |
249 return 1 if (!$in_bisect); | 259 return 1 if ($in_bisect); |
250 dodie "failed - got a bug report\n"; 251 } 252 253 return 0; 254} 255 256sub install { 257 --- 132 unchanged lines hidden (view full) --- 390sub get_version { 391 # get the release name 392 doprint "$make kernelrelease ... "; 393 $version = `$make kernelrelease | tail -1`; 394 chomp($version); 395 doprint "$version\n"; 396} 397 | 260 dodie "failed - got a bug report\n"; 261 } 262 263 return 0; 264} 265 266sub install { 267 --- 132 unchanged lines hidden (view full) --- 400sub get_version { 401 # get the release name 402 doprint "$make kernelrelease ... "; 403 $version = `$make kernelrelease | tail -1`; 404 chomp($version); 405 doprint "$version\n"; 406} 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 { 399 my ($type) = @_; 400 401 my $failed; 402 my $result; 403 my $output; 404 my $ret; 405 --- 11 unchanged lines hidden (view full) --- 417 # Now boot the box 418 get_grub_index; 419 get_version; 420 install; 421 $failed = monitor; 422 423 if ($type ne "boot") { 424 dodie "Failed on boot" if $failed; | 486sub run_bisect { 487 my ($type) = @_; 488 489 my $failed; 490 my $result; 491 my $output; 492 my $ret; 493 --- 11 unchanged lines hidden (view full) --- 505 # Now boot the box 506 get_grub_index; 507 get_version; 508 install; 509 $failed = monitor; 510 511 if ($type ne "boot") { 512 dodie "Failed on boot" if $failed; |
513 514 $failed = do_run_test; |
|
425 } 426 } 427 428 if ($failed) { 429 $result = "bad"; | 515 } 516 } 517 518 if ($failed) { 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 { 431 $result = "good"; 432 } 433 434 doprint "git bisect $result ... "; 435 $output = `git bisect $result 2>&1`; 436 $ret = $?; 437 438 logit $output; 439 440 if ($ret) { 441 doprint "FAILED\n"; 442 dodie "Failed to git bisect"; 443 } 444 445 doprint "SUCCESS\n"; | 527 } else { 528 $result = "good"; 529 } 530 531 doprint "git bisect $result ... "; 532 $output = `git bisect $result 2>&1`; 533 $ret = $?; 534 535 logit $output; 536 537 if ($ret) { 538 doprint "FAILED\n"; 539 dodie "Failed to git bisect"; 540 } 541 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"; 448 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 449 $bisect_bad = $1; 450 doprint "Found bad commit... $1\n"; 451 return 0; | 544 doprint "$1 [$2]\n"; 545 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 546 $bisect_bad = $1; 547 doprint "Found bad commit... $1\n"; 548 return 0; |
549 } else { 550 # we already logged it, just print it now. 551 print $output; |
|
452 } 453 454 455 return 1; 456} 457 458sub bisect { 459 my ($i) = @_; --- 14 unchanged lines hidden (view full) --- 474 dodie "could not start bisect"; 475 476 run_command "git bisect good $good" or 477 dodie "could not set bisect good to $good"; 478 479 run_command "git bisect bad $bad" or 480 dodie "could not set bisect good to $bad"; 481 | 552 } 553 554 555 return 1; 556} 557 558sub bisect { 559 my ($i) = @_; --- 14 unchanged lines hidden (view full) --- 574 dodie "could not start bisect"; 575 576 run_command "git bisect good $good" or 577 dodie "could not set bisect good to $good"; 578 579 run_command "git bisect bad $bad" or 580 dodie "could not set bisect good to $bad"; 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 { 483 $result = run_bisect $type; 484 } while ($result); 485 486 run_command "git bisect log" or 487 dodie "could not capture git bisect log"; 488 489 run_command "git bisect reset" or --- 24 unchanged lines hidden (view full) --- 514 515$target = "$opt{SSH_USER}\@$opt{MACHINE}"; 516 517doprint "\n\nSTARTING AUTOMATED TESTS\n"; 518 519 520$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}"; 521 | 587 do { 588 $result = run_bisect $type; 589 } while ($result); 590 591 run_command "git bisect log" or 592 dodie "could not capture git bisect log"; 593 594 run_command "git bisect reset" or --- 24 unchanged lines hidden (view full) --- 619 620$target = "$opt{SSH_USER}\@$opt{MACHINE}"; 621 622doprint "\n\nSTARTING AUTOMATED TESTS\n"; 623 624 625$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}"; 626 |
522# First we need to do is the builds 523for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) { 524 my $type = "BUILD_TYPE[$i]"; | 627sub 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 } 540 | 634 } 635 |
541 if (!defined($opt{$type})) { 542 $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"}; | 636 if (defined($opt{$name})) { 637 return $opt{$name}; |
543 } 544 | 638 } 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"; 546 doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n"; 547 548 if ($opt{$type} eq "bisect") { 549 bisect $i; 550 next; 551 } 552 553 if ($opt{$type} ne "nobuild") { 554 build $opt{$type}; 555 } 556 557 get_grub_index; 558 get_version; 559 install; 560 monitor; | 651 doprint "\n\n"; 652 doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n"; 653 654 if ($opt{$type} eq "bisect") { 655 bisect $i; 656 next; 657 } 658 659 if ($opt{$type} ne "nobuild") { 660 build $opt{$type}; 661 } 662 663 get_grub_index; 664 get_version; 665 install; 666 monitor; |
667 668 if (defined($run_test)) { 669 do_run_test; 670 } 671 |
|
561 success $i; 562} 563 564if ($opt{"POWEROFF_ON_SUCCESS"}) { 565 halt; 566} else { 567 reboot; 568} 569 570exit 0; | 672 success $i; 673} 674 675if ($opt{"POWEROFF_ON_SUCCESS"}) { 676 halt; 677} else { 678 reboot; 679} 680 681exit 0; |