6166f3a0f2ea53e40df99eeb800f4592a9bb4026
[pandora-kernel.git] / tools / testing / ktest / ktest.pl
1 #!/usr/bin/perl -w
2 #
3 # Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
4 # Licensed under the terms of the GNU GPL License version 2
5 #
6
7 use strict;
8 use IPC::Open2;
9 use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
10 use File::Path qw(mkpath);
11 use File::Copy qw(cp);
12 use FileHandle;
13
14 my $VERSION = "0.2";
15
16 $| = 1;
17
18 my %opt;
19 my %repeat_tests;
20 my %repeats;
21 my %default;
22
23 #default opts
24 $default{"NUM_TESTS"}           = 1;
25 $default{"REBOOT_TYPE"}         = "grub";
26 $default{"TEST_TYPE"}           = "test";
27 $default{"BUILD_TYPE"}          = "randconfig";
28 $default{"MAKE_CMD"}            = "make";
29 $default{"TIMEOUT"}             = 120;
30 $default{"TMP_DIR"}             = "/tmp/ktest/\${MACHINE}";
31 $default{"SLEEP_TIME"}          = 60;   # sleep time between tests
32 $default{"BUILD_NOCLEAN"}       = 0;
33 $default{"REBOOT_ON_ERROR"}     = 0;
34 $default{"POWEROFF_ON_ERROR"}   = 0;
35 $default{"REBOOT_ON_SUCCESS"}   = 1;
36 $default{"POWEROFF_ON_SUCCESS"} = 0;
37 $default{"BUILD_OPTIONS"}       = "";
38 $default{"BISECT_SLEEP_TIME"}   = 60;   # sleep time between bisects
39 $default{"PATCHCHECK_SLEEP_TIME"} = 60; # sleep time between patch checks
40 $default{"CLEAR_LOG"}           = 0;
41 $default{"BISECT_MANUAL"}       = 0;
42 $default{"BISECT_SKIP"}         = 1;
43 $default{"SUCCESS_LINE"}        = "login:";
44 $default{"DETECT_TRIPLE_FAULT"} = 1;
45 $default{"BOOTED_TIMEOUT"}      = 1;
46 $default{"DIE_ON_FAILURE"}      = 1;
47 $default{"SSH_EXEC"}            = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
48 $default{"SCP_TO_TARGET"}       = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE";
49 $default{"REBOOT"}              = "ssh \$SSH_USER\@\$MACHINE reboot";
50 $default{"STOP_AFTER_SUCCESS"}  = 10;
51 $default{"STOP_AFTER_FAILURE"}  = 60;
52 $default{"STOP_TEST_AFTER"}     = 600;
53 $default{"LOCALVERSION"}        = "-test";
54
55 my $ktest_config;
56 my $version;
57 my $machine;
58 my $ssh_user;
59 my $tmpdir;
60 my $builddir;
61 my $outputdir;
62 my $output_config;
63 my $test_type;
64 my $build_type;
65 my $build_options;
66 my $pre_build;
67 my $post_build;
68 my $pre_build_die;
69 my $post_build_die;
70 my $reboot_type;
71 my $reboot_script;
72 my $power_cycle;
73 my $reboot;
74 my $reboot_on_error;
75 my $poweroff_on_error;
76 my $die_on_failure;
77 my $powercycle_after_reboot;
78 my $poweroff_after_halt;
79 my $ssh_exec;
80 my $scp_to_target;
81 my $power_off;
82 my $grub_menu;
83 my $grub_number;
84 my $target;
85 my $make;
86 my $post_install;
87 my $noclean;
88 my $minconfig;
89 my $addconfig;
90 my $in_bisect = 0;
91 my $bisect_bad = "";
92 my $reverse_bisect;
93 my $bisect_manual;
94 my $bisect_skip;
95 my $config_bisect_good;
96 my $in_patchcheck = 0;
97 my $run_test;
98 my $redirect;
99 my $buildlog;
100 my $dmesg;
101 my $monitor_fp;
102 my $monitor_pid;
103 my $monitor_cnt = 0;
104 my $sleep_time;
105 my $bisect_sleep_time;
106 my $patchcheck_sleep_time;
107 my $ignore_warnings;
108 my $store_failures;
109 my $test_name;
110 my $timeout;
111 my $booted_timeout;
112 my $detect_triplefault;
113 my $console;
114 my $success_line;
115 my $stop_after_success;
116 my $stop_after_failure;
117 my $stop_test_after;
118 my $build_target;
119 my $target_image;
120 my $localversion;
121 my $iteration = 0;
122 my $successes = 0;
123
124 my %entered_configs;
125 my %config_help;
126 my %variable;
127 my %force_config;
128
129 $config_help{"MACHINE"} = << "EOF"
130  The machine hostname that you will test.
131 EOF
132     ;
133 $config_help{"SSH_USER"} = << "EOF"
134  The box is expected to have ssh on normal bootup, provide the user
135   (most likely root, since you need privileged operations)
136 EOF
137     ;
138 $config_help{"BUILD_DIR"} = << "EOF"
139  The directory that contains the Linux source code (full path).
140 EOF
141     ;
142 $config_help{"OUTPUT_DIR"} = << "EOF"
143  The directory that the objects will be built (full path).
144  (can not be same as BUILD_DIR)
145 EOF
146     ;
147 $config_help{"BUILD_TARGET"} = << "EOF"
148  The location of the compiled file to copy to the target.
149  (relative to OUTPUT_DIR)
150 EOF
151     ;
152 $config_help{"TARGET_IMAGE"} = << "EOF"
153  The place to put your image on the test machine.
154 EOF
155     ;
156 $config_help{"POWER_CYCLE"} = << "EOF"
157  A script or command to reboot the box.
158
159  Here is a digital loggers power switch example
160  POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
161
162  Here is an example to reboot a virtual box on the current host
163  with the name "Guest".
164  POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
165 EOF
166     ;
167 $config_help{"CONSOLE"} = << "EOF"
168  The script or command that reads the console
169
170   If you use ttywatch server, something like the following would work.
171 CONSOLE = nc -d localhost 3001
172
173  For a virtual machine with guest name "Guest".
174 CONSOLE =  virsh console Guest
175 EOF
176     ;
177 $config_help{"LOCALVERSION"} = << "EOF"
178  Required version ending to differentiate the test
179  from other linux builds on the system.
180 EOF
181     ;
182 $config_help{"REBOOT_TYPE"} = << "EOF"
183  Way to reboot the box to the test kernel.
184  Only valid options so far are "grub" and "script".
185
186  If you specify grub, it will assume grub version 1
187  and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
188  and select that target to reboot to the kernel. If this is not
189  your setup, then specify "script" and have a command or script
190  specified in REBOOT_SCRIPT to boot to the target.
191
192  The entry in /boot/grub/menu.lst must be entered in manually.
193  The test will not modify that file.
194 EOF
195     ;
196 $config_help{"GRUB_MENU"} = << "EOF"
197  The grub title name for the test kernel to boot
198  (Only mandatory if REBOOT_TYPE = grub)
199
200  Note, ktest.pl will not update the grub menu.lst, you need to
201  manually add an option for the test. ktest.pl will search
202  the grub menu.lst for this option to find what kernel to
203  reboot into.
204
205  For example, if in the /boot/grub/menu.lst the test kernel title has:
206  title Test Kernel
207  kernel vmlinuz-test
208  GRUB_MENU = Test Kernel
209 EOF
210     ;
211 $config_help{"REBOOT_SCRIPT"} = << "EOF"
212  A script to reboot the target into the test kernel
213  (Only mandatory if REBOOT_TYPE = script)
214 EOF
215     ;
216
217
218 sub get_ktest_config {
219     my ($config) = @_;
220
221     return if (defined($opt{$config}));
222
223     if (defined($config_help{$config})) {
224         print "\n";
225         print $config_help{$config};
226     }
227
228     for (;;) {
229         print "$config = ";
230         if (defined($default{$config})) {
231             print "\[$default{$config}\] ";
232         }
233         $entered_configs{$config} = <STDIN>;
234         $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/;
235         if ($entered_configs{$config} =~ /^\s*$/) {
236             if ($default{$config}) {
237                 $entered_configs{$config} = $default{$config};
238             } else {
239                 print "Your answer can not be blank\n";
240                 next;
241             }
242         }
243         last;
244     }
245 }
246
247 sub get_ktest_configs {
248     get_ktest_config("MACHINE");
249     get_ktest_config("SSH_USER");
250     get_ktest_config("BUILD_DIR");
251     get_ktest_config("OUTPUT_DIR");
252     get_ktest_config("BUILD_TARGET");
253     get_ktest_config("TARGET_IMAGE");
254     get_ktest_config("POWER_CYCLE");
255     get_ktest_config("CONSOLE");
256     get_ktest_config("LOCALVERSION");
257
258     my $rtype = $opt{"REBOOT_TYPE"};
259
260     if (!defined($rtype)) {
261         if (!defined($opt{"GRUB_MENU"})) {
262             get_ktest_config("REBOOT_TYPE");
263             $rtype = $entered_configs{"REBOOT_TYPE"};
264         } else {
265             $rtype = "grub";
266         }
267     }
268
269     if ($rtype eq "grub") {
270         get_ktest_config("GRUB_MENU");
271     } else {
272         get_ktest_config("REBOOT_SCRIPT");
273     }
274 }
275
276 sub process_variables {
277     my ($value) = @_;
278     my $retval = "";
279
280     # We want to check for '\', and it is just easier
281     # to check the previous characet of '$' and not need
282     # to worry if '$' is the first character. By adding
283     # a space to $value, we can just check [^\\]\$ and
284     # it will still work.
285     $value = " $value";
286
287     while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
288         my $begin = $1;
289         my $var = $2;
290         my $end = $3;
291         # append beginning of value to retval
292         $retval = "$retval$begin";
293         if (defined($variable{$var})) {
294             $retval = "$retval$variable{$var}";
295         } else {
296             # put back the origin piece.
297             $retval = "$retval\$\{$var\}";
298         }
299         $value = $end;
300     }
301     $retval = "$retval$value";
302
303     # remove the space added in the beginning
304     $retval =~ s/ //;
305
306     return "$retval"
307 }
308
309 sub set_value {
310     my ($lvalue, $rvalue) = @_;
311
312     if (defined($opt{$lvalue})) {
313         die "Error: Option $lvalue defined more than once!\n";
314     }
315     if ($rvalue =~ /^\s*$/) {
316         delete $opt{$lvalue};
317     } else {
318         $rvalue = process_variables($rvalue);
319         $opt{$lvalue} = $rvalue;
320     }
321 }
322
323 sub set_variable {
324     my ($lvalue, $rvalue) = @_;
325
326     if ($rvalue =~ /^\s*$/) {
327         delete $variable{$lvalue};
328     } else {
329         $rvalue = process_variables($rvalue);
330         $variable{$lvalue} = $rvalue;
331     }
332 }
333
334 sub read_config {
335     my ($config) = @_;
336
337     open(IN, $config) || die "can't read file $config";
338
339     my $name = $config;
340     $name =~ s,.*/(.*),$1,;
341
342     my $test_num = 0;
343     my $default = 1;
344     my $repeat = 1;
345     my $num_tests_set = 0;
346     my $skip = 0;
347     my $rest;
348     my $test_case = 0;
349
350     while (<IN>) {
351
352         # ignore blank lines and comments
353         next if (/^\s*$/ || /\s*\#/);
354
355         if (/^\s*TEST_START(.*)/) {
356
357             $rest = $1;
358
359             if ($num_tests_set) {
360                 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
361             }
362
363             my $old_test_num = $test_num;
364             my $old_repeat = $repeat;
365
366             $test_num += $repeat;
367             $default = 0;
368             $repeat = 1;
369
370             if ($rest =~ /\s+SKIP(.*)/) {
371                 $rest = $1;
372                 $skip = 1;
373             } else {
374                 $test_case = 1;
375                 $skip = 0;
376             }
377
378             if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
379                 $repeat = $1;
380                 $rest = $2;
381                 $repeat_tests{"$test_num"} = $repeat;
382             }
383
384             if ($rest =~ /\s+SKIP(.*)/) {
385                 $rest = $1;
386                 $skip = 1;
387             }
388
389             if ($rest !~ /^\s*$/) {
390                 die "$name: $.: Gargbage found after TEST_START\n$_";
391             }
392
393             if ($skip) {
394                 $test_num = $old_test_num;
395                 $repeat = $old_repeat;
396             }
397
398         } elsif (/^\s*DEFAULTS(.*)$/) {
399             $default = 1;
400
401             $rest = $1;
402
403             if ($rest =~ /\s+SKIP(.*)/) {
404                 $rest = $1;
405                 $skip = 1;
406             } else {
407                 $skip = 0;
408             }
409
410             if ($rest !~ /^\s*$/) {
411                 die "$name: $.: Gargbage found after DEFAULTS\n$_";
412             }
413
414         } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
415
416             next if ($skip);
417
418             my $lvalue = $1;
419             my $rvalue = $2;
420
421             if (!$default &&
422                 ($lvalue eq "NUM_TESTS" ||
423                  $lvalue eq "LOG_FILE" ||
424                  $lvalue eq "CLEAR_LOG")) {
425                 die "$name: $.: $lvalue must be set in DEFAULTS section\n";
426             }
427
428             if ($lvalue eq "NUM_TESTS") {
429                 if ($test_num) {
430                     die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
431                 }
432                 if (!$default) {
433                     die "$name: $.: NUM_TESTS must be set in default section\n";
434                 }
435                 $num_tests_set = 1;
436             }
437
438             if ($default || $lvalue =~ /\[\d+\]$/) {
439                 set_value($lvalue, $rvalue);
440             } else {
441                 my $val = "$lvalue\[$test_num\]";
442                 set_value($val, $rvalue);
443
444                 if ($repeat > 1) {
445                     $repeats{$val} = $repeat;
446                 }
447             }
448         } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
449             next if ($skip);
450
451             my $lvalue = $1;
452             my $rvalue = $2;
453
454             # process config variables.
455             # Config variables are only active while reading the
456             # config and can be defined anywhere. They also ignore
457             # TEST_START and DEFAULTS, but are skipped if they are in
458             # on of these sections that have SKIP defined.
459             # The save variable can be
460             # defined multiple times and the new one simply overrides
461             # the prevous one.
462             set_variable($lvalue, $rvalue);
463
464         } else {
465             die "$name: $.: Garbage found in config\n$_";
466         }
467     }
468
469     close(IN);
470
471     if ($test_num) {
472         $test_num += $repeat - 1;
473         $opt{"NUM_TESTS"} = $test_num;
474     }
475
476     # make sure we have all mandatory configs
477     get_ktest_configs;
478
479     # was a test specified?
480     if (!$test_case) {
481         print "No test case specified.\n";
482         print "What test case would you like to run?\n";
483         my $ans = <STDIN>;
484         chomp $ans;
485         $default{"TEST_TYPE"} = $ans;
486     }
487
488     # set any defaults
489
490     foreach my $default (keys %default) {
491         if (!defined($opt{$default})) {
492             $opt{$default} = $default{$default};
493         }
494     }
495 }
496
497 sub __eval_option {
498     my ($option, $i) = @_;
499
500     # Add space to evaluate the character before $
501     $option = " $option";
502     my $retval = "";
503
504     while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
505         my $start = $1;
506         my $var = $2;
507         my $end = $3;
508
509         # Append beginning of line
510         $retval = "$retval$start";
511
512         # If the iteration option OPT[$i] exists, then use that.
513         # otherwise see if the default OPT (without [$i]) exists.
514
515         my $o = "$var\[$i\]";
516
517         if (defined($opt{$o})) {
518             $o = $opt{$o};
519             $retval = "$retval$o";
520         } elsif (defined($opt{$var})) {
521             $o = $opt{$var};
522             $retval = "$retval$o";
523         } else {
524             $retval = "$retval\$\{$var\}";
525         }
526
527         $option = $end;
528     }
529
530     $retval = "$retval$option";
531
532     $retval =~ s/^ //;
533
534     return $retval;
535 }
536
537 sub eval_option {
538     my ($option, $i) = @_;
539
540     my $prev = "";
541
542     # Since an option can evaluate to another option,
543     # keep iterating until we do not evaluate any more
544     # options.
545     my $r = 0;
546     while ($prev ne $option) {
547         # Check for recursive evaluations.
548         # 100 deep should be more than enough.
549         if ($r++ > 100) {
550             die "Over 100 evaluations accurred with $option\n" .
551                 "Check for recursive variables\n";
552         }
553         $prev = $option;
554         $option = __eval_option($option, $i);
555     }
556
557     return $option;
558 }
559
560 sub _logit {
561     if (defined($opt{"LOG_FILE"})) {
562         open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
563         print OUT @_;
564         close(OUT);
565     }
566 }
567
568 sub logit {
569     if (defined($opt{"LOG_FILE"})) {
570         _logit @_;
571     } else {
572         print @_;
573     }
574 }
575
576 sub doprint {
577     print @_;
578     _logit @_;
579 }
580
581 sub run_command;
582
583 sub reboot {
584     # try to reboot normally
585     if (run_command $reboot) {
586         if (defined($powercycle_after_reboot)) {
587             sleep $powercycle_after_reboot;
588             run_command "$power_cycle";
589         }
590     } else {
591         # nope? power cycle it.
592         run_command "$power_cycle";
593     }
594 }
595
596 sub do_not_reboot {
597     my $i = $iteration;
598
599     return $test_type eq "build" ||
600         ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
601         ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
602 }
603
604 sub dodie {
605     doprint "CRITICAL FAILURE... ", @_, "\n";
606
607     my $i = $iteration;
608
609     if ($reboot_on_error && !do_not_reboot) {
610
611         doprint "REBOOTING\n";
612         reboot;
613
614     } elsif ($poweroff_on_error && defined($power_off)) {
615         doprint "POWERING OFF\n";
616         `$power_off`;
617     }
618
619     if (defined($opt{"LOG_FILE"})) {
620         print " See $opt{LOG_FILE} for more info.\n";
621     }
622
623     die @_, "\n";
624 }
625
626 sub open_console {
627     my ($fp) = @_;
628
629     my $flags;
630
631     my $pid = open($fp, "$console|") or
632         dodie "Can't open console $console";
633
634     $flags = fcntl($fp, F_GETFL, 0) or
635         dodie "Can't get flags for the socket: $!";
636     $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
637         dodie "Can't set flags for the socket: $!";
638
639     return $pid;
640 }
641
642 sub close_console {
643     my ($fp, $pid) = @_;
644
645     doprint "kill child process $pid\n";
646     kill 2, $pid;
647
648     print "closing!\n";
649     close($fp);
650 }
651
652 sub start_monitor {
653     if ($monitor_cnt++) {
654         return;
655     }
656     $monitor_fp = \*MONFD;
657     $monitor_pid = open_console $monitor_fp;
658
659     return;
660
661     open(MONFD, "Stop perl from warning about single use of MONFD");
662 }
663
664 sub end_monitor {
665     if (--$monitor_cnt) {
666         return;
667     }
668     close_console($monitor_fp, $monitor_pid);
669 }
670
671 sub wait_for_monitor {
672     my ($time) = @_;
673     my $line;
674
675     doprint "** Wait for monitor to settle down **\n";
676
677     # read the monitor and wait for the system to calm down
678     do {
679         $line = wait_for_input($monitor_fp, $time);
680         print "$line" if (defined($line));
681     } while (defined($line));
682     print "** Monitor flushed **\n";
683 }
684
685 sub fail {
686
687         if ($die_on_failure) {
688                 dodie @_;
689         }
690
691         doprint "FAILED\n";
692
693         my $i = $iteration;
694
695         # no need to reboot for just building.
696         if (!do_not_reboot) {
697             doprint "REBOOTING\n";
698             reboot;
699             start_monitor;
700             wait_for_monitor $sleep_time;
701             end_monitor;
702         }
703
704         my $name = "";
705
706         if (defined($test_name)) {
707             $name = " ($test_name)";
708         }
709
710         doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
711         doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
712         doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
713         doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
714         doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
715
716         return 1 if (!defined($store_failures));
717
718         my @t = localtime;
719         my $date = sprintf "%04d%02d%02d%02d%02d%02d",
720                 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
721
722         my $type = $build_type;
723         if ($type =~ /useconfig/) {
724             $type = "useconfig";
725         }
726
727         my $dir = "$machine-$test_type-$type-fail-$date";
728         my $faildir = "$store_failures/$dir";
729
730         if (!-d $faildir) {
731             mkpath($faildir) or
732                 die "can't create $faildir";
733         }
734         if (-f "$output_config") {
735             cp "$output_config", "$faildir/config" or
736                 die "failed to copy .config";
737         }
738         if (-f $buildlog) {
739             cp $buildlog, "$faildir/buildlog" or
740                 die "failed to move $buildlog";
741         }
742         if (-f $dmesg) {
743             cp $dmesg, "$faildir/dmesg" or
744                 die "failed to move $dmesg";
745         }
746
747         doprint "*** Saved info to $faildir ***\n";
748
749         return 1;
750 }
751
752 sub run_command {
753     my ($command) = @_;
754     my $dolog = 0;
755     my $dord = 0;
756     my $pid;
757
758     $command =~ s/\$SSH_USER/$ssh_user/g;
759     $command =~ s/\$MACHINE/$machine/g;
760
761     doprint("$command ... ");
762
763     $pid = open(CMD, "$command 2>&1 |") or
764         (fail "unable to exec $command" and return 0);
765
766     if (defined($opt{"LOG_FILE"})) {
767         open(LOG, ">>$opt{LOG_FILE}") or
768             dodie "failed to write to log";
769         $dolog = 1;
770     }
771
772     if (defined($redirect)) {
773         open (RD, ">$redirect") or
774             dodie "failed to write to redirect $redirect";
775         $dord = 1;
776     }
777
778     while (<CMD>) {
779         print LOG if ($dolog);
780         print RD  if ($dord);
781     }
782
783     waitpid($pid, 0);
784     my $failed = $?;
785
786     close(CMD);
787     close(LOG) if ($dolog);
788     close(RD)  if ($dord);
789
790     if ($failed) {
791         doprint "FAILED!\n";
792     } else {
793         doprint "SUCCESS\n";
794     }
795
796     return !$failed;
797 }
798
799 sub run_ssh {
800     my ($cmd) = @_;
801     my $cp_exec = $ssh_exec;
802
803     $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
804     return run_command "$cp_exec";
805 }
806
807 sub run_scp {
808     my ($src, $dst) = @_;
809     my $cp_scp = $scp_to_target;
810
811     $cp_scp =~ s/\$SRC_FILE/$src/g;
812     $cp_scp =~ s/\$DST_FILE/$dst/g;
813
814     return run_command "$cp_scp";
815 }
816
817 sub get_grub_index {
818
819     if ($reboot_type ne "grub") {
820         return;
821     }
822     return if (defined($grub_number));
823
824     doprint "Find grub menu ... ";
825     $grub_number = -1;
826
827     my $ssh_grub = $ssh_exec;
828     $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
829
830     open(IN, "$ssh_grub |")
831         or die "unable to get menu.lst";
832
833     while (<IN>) {
834         if (/^\s*title\s+$grub_menu\s*$/) {
835             $grub_number++;
836             last;
837         } elsif (/^\s*title\s/) {
838             $grub_number++;
839         }
840     }
841     close(IN);
842
843     die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
844         if ($grub_number < 0);
845     doprint "$grub_number\n";
846 }
847
848 sub wait_for_input
849 {
850     my ($fp, $time) = @_;
851     my $rin;
852     my $ready;
853     my $line;
854     my $ch;
855
856     if (!defined($time)) {
857         $time = $timeout;
858     }
859
860     $rin = '';
861     vec($rin, fileno($fp), 1) = 1;
862     $ready = select($rin, undef, undef, $time);
863
864     $line = "";
865
866     # try to read one char at a time
867     while (sysread $fp, $ch, 1) {
868         $line .= $ch;
869         last if ($ch eq "\n");
870     }
871
872     if (!length($line)) {
873         return undef;
874     }
875
876     return $line;
877 }
878
879 sub reboot_to {
880     if ($reboot_type eq "grub") {
881         run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'";
882         return;
883     }
884
885     run_command "$reboot_script";
886 }
887
888 sub get_sha1 {
889     my ($commit) = @_;
890
891     doprint "git rev-list --max-count=1 $commit ... ";
892     my $sha1 = `git rev-list --max-count=1 $commit`;
893     my $ret = $?;
894
895     logit $sha1;
896
897     if ($ret) {
898         doprint "FAILED\n";
899         dodie "Failed to get git $commit";
900     }
901
902     print "SUCCESS\n";
903
904     chomp $sha1;
905
906     return $sha1;
907 }
908
909 sub monitor {
910     my $booted = 0;
911     my $bug = 0;
912     my $skip_call_trace = 0;
913     my $loops;
914
915     wait_for_monitor 5;
916
917     my $line;
918     my $full_line = "";
919
920     open(DMESG, "> $dmesg") or
921         die "unable to write to $dmesg";
922
923     reboot_to;
924
925     my $success_start;
926     my $failure_start;
927     my $monitor_start = time;
928     my $done = 0;
929     my $version_found = 0;
930
931     while (!$done) {
932
933         if ($bug && defined($stop_after_failure) &&
934             $stop_after_failure >= 0) {
935             my $time = $stop_after_failure - (time - $failure_start);
936             $line = wait_for_input($monitor_fp, $time);
937             if (!defined($line)) {
938                 doprint "bug timed out after $booted_timeout seconds\n";
939                 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
940                 last;
941             }
942         } elsif ($booted) {
943             $line = wait_for_input($monitor_fp, $booted_timeout);
944             if (!defined($line)) {
945                 my $s = $booted_timeout == 1 ? "" : "s";
946                 doprint "Successful boot found: break after $booted_timeout second$s\n";
947                 last;
948             }
949         } else {
950             $line = wait_for_input($monitor_fp);
951             if (!defined($line)) {
952                 my $s = $timeout == 1 ? "" : "s";
953                 doprint "Timed out after $timeout second$s\n";
954                 last;
955             }
956         }
957
958         doprint $line;
959         print DMESG $line;
960
961         # we are not guaranteed to get a full line
962         $full_line .= $line;
963
964         if ($full_line =~ /$success_line/) {
965             $booted = 1;
966             $success_start = time;
967         }
968
969         if ($booted && defined($stop_after_success) &&
970             $stop_after_success >= 0) {
971             my $now = time;
972             if ($now - $success_start >= $stop_after_success) {
973                 doprint "Test forced to stop after $stop_after_success seconds after success\n";
974                 last;
975             }
976         }
977
978         if ($full_line =~ /\[ backtrace testing \]/) {
979             $skip_call_trace = 1;
980         }
981
982         if ($full_line =~ /call trace:/i) {
983             if (!$bug && !$skip_call_trace) {
984                 $bug = 1;
985                 $failure_start = time;
986             }
987         }
988
989         if ($bug && defined($stop_after_failure) &&
990             $stop_after_failure >= 0) {
991             my $now = time;
992             if ($now - $failure_start >= $stop_after_failure) {
993                 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
994                 last;
995             }
996         }
997
998         if ($full_line =~ /\[ end of backtrace testing \]/) {
999             $skip_call_trace = 0;
1000         }
1001
1002         if ($full_line =~ /Kernel panic -/) {
1003             $failure_start = time;
1004             $bug = 1;
1005         }
1006
1007         # Detect triple faults by testing the banner
1008         if ($full_line =~ /\bLinux version (\S+).*\n/) {
1009             if ($1 eq $version) {
1010                 $version_found = 1;
1011             } elsif ($version_found && $detect_triplefault) {
1012                 # We already booted into the kernel we are testing,
1013                 # but now we booted into another kernel?
1014                 # Consider this a triple fault.
1015                 doprint "Aleady booted in Linux kernel $version, but now\n";
1016                 doprint "we booted into Linux kernel $1.\n";
1017                 doprint "Assuming that this is a triple fault.\n";
1018                 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1019                 last;
1020             }
1021         }
1022
1023         if ($line =~ /\n/) {
1024             $full_line = "";
1025         }
1026
1027         if ($stop_test_after > 0 && !$booted && !$bug) {
1028             if (time - $monitor_start > $stop_test_after) {
1029                 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
1030                 $done = 1;
1031             }
1032         }
1033     }
1034
1035     close(DMESG);
1036
1037     if ($bug) {
1038         return 0 if ($in_bisect);
1039         fail "failed - got a bug report" and return 0;
1040     }
1041
1042     if (!$booted) {
1043         return 0 if ($in_bisect);
1044         fail "failed - never got a boot prompt." and return 0;
1045     }
1046
1047     return 1;
1048 }
1049
1050 sub do_post_install {
1051
1052     return if (!defined($post_install));
1053
1054     my $cp_post_install = $post_install;
1055     $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
1056     run_command "$cp_post_install" or
1057         dodie "Failed to run post install";
1058 }
1059
1060 sub install {
1061
1062     run_scp "$outputdir/$build_target", "$target_image" or
1063         dodie "failed to copy image";
1064
1065     my $install_mods = 0;
1066
1067     # should we process modules?
1068     $install_mods = 0;
1069     open(IN, "$output_config") or dodie("Can't read config file");
1070     while (<IN>) {
1071         if (/CONFIG_MODULES(=y)?/) {
1072             $install_mods = 1 if (defined($1));
1073             last;
1074         }
1075     }
1076     close(IN);
1077
1078     if (!$install_mods) {
1079         do_post_install;
1080         doprint "No modules needed\n";
1081         return;
1082     }
1083
1084     run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
1085         dodie "Failed to install modules";
1086
1087     my $modlib = "/lib/modules/$version";
1088     my $modtar = "ktest-mods.tar.bz2";
1089
1090     run_ssh "rm -rf $modlib" or
1091         dodie "failed to remove old mods: $modlib";
1092
1093     # would be nice if scp -r did not follow symbolic links
1094     run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
1095         dodie "making tarball";
1096
1097     run_scp "$tmpdir/$modtar", "/tmp" or
1098         dodie "failed to copy modules";
1099
1100     unlink "$tmpdir/$modtar";
1101
1102     run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
1103         dodie "failed to tar modules";
1104
1105     run_ssh "rm -f /tmp/$modtar";
1106
1107     do_post_install;
1108 }
1109
1110 sub get_version {
1111     # get the release name
1112     doprint "$make kernelrelease ... ";
1113     $version = `$make kernelrelease | tail -1`;
1114     chomp($version);
1115     doprint "$version\n";
1116 }
1117
1118 sub start_monitor_and_boot {
1119     get_grub_index;
1120     get_version;
1121     install;
1122
1123     start_monitor;
1124     return monitor;
1125 }
1126
1127 sub check_buildlog {
1128     my ($patch) = @_;
1129
1130     my @files = `git show $patch | diffstat -l`;
1131
1132     open(IN, "git show $patch |") or
1133         dodie "failed to show $patch";
1134     while (<IN>) {
1135         if (m,^--- a/(.*),) {
1136             chomp $1;
1137             $files[$#files] = $1;
1138         }
1139     }
1140     close(IN);
1141
1142     open(IN, $buildlog) or dodie "Can't open $buildlog";
1143     while (<IN>) {
1144         if (/^\s*(.*?):.*(warning|error)/) {
1145             my $err = $1;
1146             foreach my $file (@files) {
1147                 my $fullpath = "$builddir/$file";
1148                 if ($file eq $err || $fullpath eq $err) {
1149                     fail "$file built with warnings" and return 0;
1150                 }
1151             }
1152         }
1153     }
1154     close(IN);
1155
1156     return 1;
1157 }
1158
1159 sub apply_min_config {
1160     my $outconfig = "$output_config.new";
1161
1162     # Read the config file and remove anything that
1163     # is in the force_config hash (from minconfig and others)
1164     # then add the force config back.
1165
1166     doprint "Applying minimum configurations into $output_config.new\n";
1167
1168     open (OUT, ">$outconfig") or
1169         dodie "Can't create $outconfig";
1170
1171     if (-f $output_config) {
1172         open (IN, $output_config) or
1173             dodie "Failed to open $output_config";
1174         while (<IN>) {
1175             if (/^(# )?(CONFIG_[^\s=]*)/) {
1176                 next if (defined($force_config{$2}));
1177             }
1178             print OUT;
1179         }
1180         close IN;
1181     }
1182     foreach my $config (keys %force_config) {
1183         print OUT "$force_config{$config}\n";
1184     }
1185     close OUT;
1186
1187     run_command "mv $outconfig $output_config";
1188 }
1189
1190 sub make_oldconfig {
1191
1192     apply_min_config;
1193
1194     if (!run_command "$make oldnoconfig") {
1195         # Perhaps oldnoconfig doesn't exist in this version of the kernel
1196         # try a yes '' | oldconfig
1197         doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1198         run_command "yes '' | $make oldconfig" or
1199             dodie "failed make config oldconfig";
1200     }
1201 }
1202
1203 # read a config file and use this to force new configs.
1204 sub load_force_config {
1205     my ($config) = @_;
1206
1207     open(IN, $config) or
1208         dodie "failed to read $config";
1209     while (<IN>) {
1210         chomp;
1211         if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1212             $force_config{$1} = $_;
1213         } elsif (/^# (CONFIG_\S*) is not set/) {
1214             $force_config{$1} = $_;
1215         }
1216     }
1217     close IN;
1218 }
1219
1220 sub build {
1221     my ($type) = @_;
1222
1223     unlink $buildlog;
1224
1225     if (defined($pre_build)) {
1226         my $ret = run_command $pre_build;
1227         if (!$ret && defined($pre_build_die) &&
1228             $pre_build_die) {
1229             dodie "failed to pre_build\n";
1230         }
1231     }
1232
1233     if ($type =~ /^useconfig:(.*)/) {
1234         run_command "cp $1 $output_config" or
1235             dodie "could not copy $1 to .config";
1236
1237         $type = "oldconfig";
1238     }
1239
1240     # old config can ask questions
1241     if ($type eq "oldconfig") {
1242         $type = "oldnoconfig";
1243
1244         # allow for empty configs
1245         run_command "touch $output_config";
1246
1247         run_command "mv $output_config $outputdir/config_temp" or
1248             dodie "moving .config";
1249
1250         if (!$noclean && !run_command "$make mrproper") {
1251             dodie "make mrproper";
1252         }
1253
1254         run_command "mv $outputdir/config_temp $output_config" or
1255             dodie "moving config_temp";
1256
1257     } elsif (!$noclean) {
1258         unlink "$output_config";
1259         run_command "$make mrproper" or
1260             dodie "make mrproper";
1261     }
1262
1263     # add something to distinguish this build
1264     open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
1265     print OUT "$localversion\n";
1266     close(OUT);
1267
1268     if (defined($minconfig)) {
1269         load_force_config($minconfig);
1270     }
1271
1272     if ($type ne "oldnoconfig") {
1273         run_command "$make $type" or
1274             dodie "failed make config";
1275     }
1276     # Run old config regardless, to enforce min configurations
1277     make_oldconfig;
1278
1279     $redirect = "$buildlog";
1280     my $build_ret = run_command "$make $build_options";
1281     undef $redirect;
1282
1283     if (defined($post_build)) {
1284         my $ret = run_command $post_build;
1285         if (!$ret && defined($post_build_die) &&
1286             $post_build_die) {
1287             dodie "failed to post_build\n";
1288         }
1289     }
1290
1291     if (!$build_ret) {
1292         # bisect may need this to pass
1293         return 0 if ($in_bisect);
1294         fail "failed build" and return 0;
1295     }
1296
1297     return 1;
1298 }
1299
1300 sub halt {
1301     if (!run_ssh "halt" or defined($power_off)) {
1302         if (defined($poweroff_after_halt)) {
1303             sleep $poweroff_after_halt;
1304             run_command "$power_off";
1305         }
1306     } else {
1307         # nope? the zap it!
1308         run_command "$power_off";
1309     }
1310 }
1311
1312 sub success {
1313     my ($i) = @_;
1314
1315     $successes++;
1316
1317     my $name = "";
1318
1319     if (defined($test_name)) {
1320         $name = " ($test_name)";
1321     }
1322
1323     doprint "\n\n*******************************************\n";
1324     doprint     "*******************************************\n";
1325     doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
1326     doprint     "*******************************************\n";
1327     doprint     "*******************************************\n";
1328
1329     if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1330         doprint "Reboot and wait $sleep_time seconds\n";
1331         reboot;
1332         start_monitor;
1333         wait_for_monitor $sleep_time;
1334         end_monitor;
1335     }
1336 }
1337
1338 sub answer_bisect {
1339     for (;;) {
1340         doprint "Pass or fail? [p/f]";
1341         my $ans = <STDIN>;
1342         chomp $ans;
1343         if ($ans eq "p" || $ans eq "P") {
1344             return 1;
1345         } elsif ($ans eq "f" || $ans eq "F") {
1346             return 0;
1347         } else {
1348             print "Please answer 'P' or 'F'\n";
1349         }
1350     }
1351 }
1352
1353 sub child_run_test {
1354     my $failed = 0;
1355
1356     # child should have no power
1357     $reboot_on_error = 0;
1358     $poweroff_on_error = 0;
1359     $die_on_failure = 1;
1360
1361     run_command $run_test or $failed = 1;
1362     exit $failed;
1363 }
1364
1365 my $child_done;
1366
1367 sub child_finished {
1368     $child_done = 1;
1369 }
1370
1371 sub do_run_test {
1372     my $child_pid;
1373     my $child_exit;
1374     my $line;
1375     my $full_line;
1376     my $bug = 0;
1377
1378     wait_for_monitor 1;
1379
1380     doprint "run test $run_test\n";
1381
1382     $child_done = 0;
1383
1384     $SIG{CHLD} = qw(child_finished);
1385
1386     $child_pid = fork;
1387
1388     child_run_test if (!$child_pid);
1389
1390     $full_line = "";
1391
1392     do {
1393         $line = wait_for_input($monitor_fp, 1);
1394         if (defined($line)) {
1395
1396             # we are not guaranteed to get a full line
1397             $full_line .= $line;
1398             doprint $line;
1399
1400             if ($full_line =~ /call trace:/i) {
1401                 $bug = 1;
1402             }
1403
1404             if ($full_line =~ /Kernel panic -/) {
1405                 $bug = 1;
1406             }
1407
1408             if ($line =~ /\n/) {
1409                 $full_line = "";
1410             }
1411         }
1412     } while (!$child_done && !$bug);
1413
1414     if ($bug) {
1415         my $failure_start = time;
1416         my $now;
1417         do {
1418             $line = wait_for_input($monitor_fp, 1);
1419             if (defined($line)) {
1420                 doprint $line;
1421             }
1422             $now = time;
1423             if ($now - $failure_start >= $stop_after_failure) {
1424                 last;
1425             }
1426         } while (defined($line));
1427
1428         doprint "Detected kernel crash!\n";
1429         # kill the child with extreme prejudice
1430         kill 9, $child_pid;
1431     }
1432
1433     waitpid $child_pid, 0;
1434     $child_exit = $?;
1435
1436     if ($bug || $child_exit) {
1437         return 0 if $in_bisect;
1438         fail "test failed" and return 0;
1439     }
1440     return 1;
1441 }
1442
1443 sub run_git_bisect {
1444     my ($command) = @_;
1445
1446     doprint "$command ... ";
1447
1448     my $output = `$command 2>&1`;
1449     my $ret = $?;
1450
1451     logit $output;
1452
1453     if ($ret) {
1454         doprint "FAILED\n";
1455         dodie "Failed to git bisect";
1456     }
1457
1458     doprint "SUCCESS\n";
1459     if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1460         doprint "$1 [$2]\n";
1461     } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1462         $bisect_bad = $1;
1463         doprint "Found bad commit... $1\n";
1464         return 0;
1465     } else {
1466         # we already logged it, just print it now.
1467         print $output;
1468     }
1469
1470     return 1;
1471 }
1472
1473 sub bisect_reboot {
1474     doprint "Reboot and sleep $bisect_sleep_time seconds\n";
1475     reboot;
1476     start_monitor;
1477     wait_for_monitor $bisect_sleep_time;
1478     end_monitor;
1479 }
1480
1481 # returns 1 on success, 0 on failure, -1 on skip
1482 sub run_bisect_test {
1483     my ($type, $buildtype) = @_;
1484
1485     my $failed = 0;
1486     my $result;
1487     my $output;
1488     my $ret;
1489
1490     $in_bisect = 1;
1491
1492     build $buildtype or $failed = 1;
1493
1494     if ($type ne "build") {
1495         if ($failed && $bisect_skip) {
1496             $in_bisect = 0;
1497             return -1;
1498         }
1499         dodie "Failed on build" if $failed;
1500
1501         # Now boot the box
1502         start_monitor_and_boot or $failed = 1;
1503
1504         if ($type ne "boot") {
1505             if ($failed && $bisect_skip) {
1506                 end_monitor;
1507                 bisect_reboot;
1508                 $in_bisect = 0;
1509                 return -1;
1510             }
1511             dodie "Failed on boot" if $failed;
1512
1513             do_run_test or $failed = 1;
1514         }
1515         end_monitor;
1516     }
1517
1518     if ($failed) {
1519         $result = 0;
1520     } else {
1521         $result = 1;
1522     }
1523
1524     # reboot the box to a kernel we can ssh to
1525     if ($type ne "build") {
1526         bisect_reboot;
1527     }
1528     $in_bisect = 0;
1529
1530     return $result;
1531 }
1532
1533 sub run_bisect {
1534     my ($type) = @_;
1535     my $buildtype = "oldconfig";
1536
1537     # We should have a minconfig to use?
1538     if (defined($minconfig)) {
1539         $buildtype = "useconfig:$minconfig";
1540     }
1541
1542     my $ret = run_bisect_test $type, $buildtype;
1543
1544     if ($bisect_manual) {
1545         $ret = answer_bisect;
1546     }
1547
1548     # Are we looking for where it worked, not failed?
1549     if ($reverse_bisect) {
1550         $ret = !$ret;
1551     }
1552
1553     if ($ret > 0) {
1554         return "good";
1555     } elsif ($ret == 0) {
1556         return  "bad";
1557     } elsif ($bisect_skip) {
1558         doprint "HIT A BAD COMMIT ... SKIPPING\n";
1559         return "skip";
1560     }
1561 }
1562
1563 sub bisect {
1564     my ($i) = @_;
1565
1566     my $result;
1567
1568     die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
1569     die "BISECT_BAD[$i] not defined\n"  if (!defined($opt{"BISECT_BAD[$i]"}));
1570     die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
1571
1572     my $good = $opt{"BISECT_GOOD[$i]"};
1573     my $bad = $opt{"BISECT_BAD[$i]"};
1574     my $type = $opt{"BISECT_TYPE[$i]"};
1575     my $start = $opt{"BISECT_START[$i]"};
1576     my $replay = $opt{"BISECT_REPLAY[$i]"};
1577     my $start_files = $opt{"BISECT_FILES[$i]"};
1578
1579     if (defined($start_files)) {
1580         $start_files = " -- " . $start_files;
1581     } else {
1582         $start_files = "";
1583     }
1584
1585     # convert to true sha1's
1586     $good = get_sha1($good);
1587     $bad = get_sha1($bad);
1588
1589     if (defined($opt{"BISECT_REVERSE[$i]"}) &&
1590         $opt{"BISECT_REVERSE[$i]"} == 1) {
1591         doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1592         $reverse_bisect = 1;
1593     } else {
1594         $reverse_bisect = 0;
1595     }
1596
1597     # Can't have a test without having a test to run
1598     if ($type eq "test" && !defined($run_test)) {
1599         $type = "boot";
1600     }
1601
1602     my $check = $opt{"BISECT_CHECK[$i]"};
1603     if (defined($check) && $check ne "0") {
1604
1605         # get current HEAD
1606         my $head = get_sha1("HEAD");
1607
1608         if ($check ne "good") {
1609             doprint "TESTING BISECT BAD [$bad]\n";
1610             run_command "git checkout $bad" or
1611                 die "Failed to checkout $bad";
1612
1613             $result = run_bisect $type;
1614
1615             if ($result ne "bad") {
1616                 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
1617             }
1618         }
1619
1620         if ($check ne "bad") {
1621             doprint "TESTING BISECT GOOD [$good]\n";
1622             run_command "git checkout $good" or
1623                 die "Failed to checkout $good";
1624
1625             $result = run_bisect $type;
1626
1627             if ($result ne "good") {
1628                 fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
1629             }
1630         }
1631
1632         # checkout where we started
1633         run_command "git checkout $head" or
1634             die "Failed to checkout $head";
1635     }
1636
1637     run_command "git bisect start$start_files" or
1638         dodie "could not start bisect";
1639
1640     run_command "git bisect good $good" or
1641         dodie "could not set bisect good to $good";
1642
1643     run_git_bisect "git bisect bad $bad" or
1644         dodie "could not set bisect bad to $bad";
1645
1646     if (defined($replay)) {
1647         run_command "git bisect replay $replay" or
1648             dodie "failed to run replay";
1649     }
1650
1651     if (defined($start)) {
1652         run_command "git checkout $start" or
1653             dodie "failed to checkout $start";
1654     }
1655
1656     my $test;
1657     do {
1658         $result = run_bisect $type;
1659         $test = run_git_bisect "git bisect $result";
1660     } while ($test);
1661
1662     run_command "git bisect log" or
1663         dodie "could not capture git bisect log";
1664
1665     run_command "git bisect reset" or
1666         dodie "could not reset git bisect";
1667
1668     doprint "Bad commit was [$bisect_bad]\n";
1669
1670     success $i;
1671 }
1672
1673 my %config_ignore;
1674 my %config_set;
1675
1676 my %config_list;
1677 my %null_config;
1678
1679 my %dependency;
1680
1681 sub process_config_ignore {
1682     my ($config) = @_;
1683
1684     open (IN, $config)
1685         or dodie "Failed to read $config";
1686
1687     while (<IN>) {
1688         if (/^((CONFIG\S*)=.*)/) {
1689             $config_ignore{$2} = $1;
1690         }
1691     }
1692
1693     close(IN);
1694 }
1695
1696 sub read_current_config {
1697     my ($config_ref) = @_;
1698
1699     %{$config_ref} = ();
1700     undef %{$config_ref};
1701
1702     my @key = keys %{$config_ref};
1703     if ($#key >= 0) {
1704         print "did not delete!\n";
1705         exit;
1706     }
1707     open (IN, "$output_config");
1708
1709     while (<IN>) {
1710         if (/^(CONFIG\S+)=(.*)/) {
1711             ${$config_ref}{$1} = $2;
1712         }
1713     }
1714     close(IN);
1715 }
1716
1717 sub get_dependencies {
1718     my ($config) = @_;
1719
1720     my $arr = $dependency{$config};
1721     if (!defined($arr)) {
1722         return ();
1723     }
1724
1725     my @deps = @{$arr};
1726
1727     foreach my $dep (@{$arr}) {
1728         print "ADD DEP $dep\n";
1729         @deps = (@deps, get_dependencies $dep);
1730     }
1731
1732     return @deps;
1733 }
1734
1735 sub create_config {
1736     my @configs = @_;
1737
1738     open(OUT, ">$output_config") or dodie "Can not write to $output_config";
1739
1740     foreach my $config (@configs) {
1741         print OUT "$config_set{$config}\n";
1742         my @deps = get_dependencies $config;
1743         foreach my $dep (@deps) {
1744             print OUT "$config_set{$dep}\n";
1745         }
1746     }
1747
1748     foreach my $config (keys %config_ignore) {
1749         print OUT "$config_ignore{$config}\n";
1750     }
1751     close(OUT);
1752
1753 #    exit;
1754     make_oldconfig;
1755 }
1756
1757 sub compare_configs {
1758     my (%a, %b) = @_;
1759
1760     foreach my $item (keys %a) {
1761         if (!defined($b{$item})) {
1762             print "diff $item\n";
1763             return 1;
1764         }
1765         delete $b{$item};
1766     }
1767
1768     my @keys = keys %b;
1769     if ($#keys) {
1770         print "diff2 $keys[0]\n";
1771     }
1772     return -1 if ($#keys >= 0);
1773
1774     return 0;
1775 }
1776
1777 sub run_config_bisect_test {
1778     my ($type) = @_;
1779
1780     return run_bisect_test $type, "oldconfig";
1781 }
1782
1783 sub process_passed {
1784     my (%configs) = @_;
1785
1786     doprint "These configs had no failure: (Enabling them for further compiles)\n";
1787     # Passed! All these configs are part of a good compile.
1788     # Add them to the min options.
1789     foreach my $config (keys %configs) {
1790         if (defined($config_list{$config})) {
1791             doprint " removing $config\n";
1792             $config_ignore{$config} = $config_list{$config};
1793             delete $config_list{$config};
1794         }
1795     }
1796     doprint "config copied to $outputdir/config_good\n";
1797     run_command "cp -f $output_config $outputdir/config_good";
1798 }
1799
1800 sub process_failed {
1801     my ($config) = @_;
1802
1803     doprint "\n\n***************************************\n";
1804     doprint "Found bad config: $config\n";
1805     doprint "***************************************\n\n";
1806 }
1807
1808 sub run_config_bisect {
1809
1810     my @start_list = keys %config_list;
1811
1812     if ($#start_list < 0) {
1813         doprint "No more configs to test!!!\n";
1814         return -1;
1815     }
1816
1817     doprint "***** RUN TEST ***\n";
1818     my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
1819     my $ret;
1820     my %current_config;
1821
1822     my $count = $#start_list + 1;
1823     doprint "  $count configs to test\n";
1824
1825     my $half = int($#start_list / 2);
1826
1827     do {
1828         my @tophalf = @start_list[0 .. $half];
1829
1830         create_config @tophalf;
1831         read_current_config \%current_config;
1832
1833         $count = $#tophalf + 1;
1834         doprint "Testing $count configs\n";
1835         my $found = 0;
1836         # make sure we test something
1837         foreach my $config (@tophalf) {
1838             if (defined($current_config{$config})) {
1839                 logit " $config\n";
1840                 $found = 1;
1841             }
1842         }
1843         if (!$found) {
1844             # try the other half
1845             doprint "Top half produced no set configs, trying bottom half\n";
1846             @tophalf = @start_list[$half + 1 .. $#start_list];
1847             create_config @tophalf;
1848             read_current_config \%current_config;
1849             foreach my $config (@tophalf) {
1850                 if (defined($current_config{$config})) {
1851                     logit " $config\n";
1852                     $found = 1;
1853                 }
1854             }
1855             if (!$found) {
1856                 doprint "Failed: Can't make new config with current configs\n";
1857                 foreach my $config (@start_list) {
1858                     doprint "  CONFIG: $config\n";
1859                 }
1860                 return -1;
1861             }
1862             $count = $#tophalf + 1;
1863             doprint "Testing $count configs\n";
1864         }
1865
1866         $ret = run_config_bisect_test $type;
1867         if ($bisect_manual) {
1868             $ret = answer_bisect;
1869         }
1870         if ($ret) {
1871             process_passed %current_config;
1872             return 0;
1873         }
1874
1875         doprint "This config had a failure.\n";
1876         doprint "Removing these configs that were not set in this config:\n";
1877         doprint "config copied to $outputdir/config_bad\n";
1878         run_command "cp -f $output_config $outputdir/config_bad";
1879
1880         # A config exists in this group that was bad.
1881         foreach my $config (keys %config_list) {
1882             if (!defined($current_config{$config})) {
1883                 doprint " removing $config\n";
1884                 delete $config_list{$config};
1885             }
1886         }
1887
1888         @start_list = @tophalf;
1889
1890         if ($#start_list == 0) {
1891             process_failed $start_list[0];
1892             return 1;
1893         }
1894
1895         # remove half the configs we are looking at and see if
1896         # they are good.
1897         $half = int($#start_list / 2);
1898     } while ($#start_list > 0);
1899
1900     # we found a single config, try it again unless we are running manually
1901
1902     if ($bisect_manual) {
1903         process_failed $start_list[0];
1904         return 1;
1905     }
1906
1907     my @tophalf = @start_list[0 .. 0];
1908
1909     $ret = run_config_bisect_test $type;
1910     if ($ret) {
1911         process_passed %current_config;
1912         return 0;
1913     }
1914
1915     process_failed $start_list[0];
1916     return 1;
1917 }
1918
1919 sub config_bisect {
1920     my ($i) = @_;
1921
1922     my $start_config = $opt{"CONFIG_BISECT[$i]"};
1923
1924     my $tmpconfig = "$tmpdir/use_config";
1925
1926     if (defined($config_bisect_good)) {
1927         process_config_ignore $config_bisect_good;
1928     }
1929
1930     # Make the file with the bad config and the min config
1931     if (defined($minconfig)) {
1932         # read the min config for things to ignore
1933         run_command "cp $minconfig $tmpconfig" or
1934             dodie "failed to copy $minconfig to $tmpconfig";
1935     } else {
1936         unlink $tmpconfig;
1937     }
1938
1939     # Add other configs
1940     if (defined($addconfig)) {
1941         run_command "cat $addconfig >> $tmpconfig" or
1942             dodie "failed to append $addconfig";
1943     }
1944
1945     if (-f $tmpconfig) {
1946         load_force_config($tmpconfig);
1947         process_config_ignore $tmpconfig;
1948     }
1949
1950     # now process the start config
1951     run_command "cp $start_config $output_config" or
1952         dodie "failed to copy $start_config to $output_config";
1953
1954     # read directly what we want to check
1955     my %config_check;
1956     open (IN, $output_config)
1957         or dodie "faied to open $output_config";
1958
1959     while (<IN>) {
1960         if (/^((CONFIG\S*)=.*)/) {
1961             $config_check{$2} = $1;
1962         }
1963     }
1964     close(IN);
1965
1966     # Now run oldconfig with the minconfig (and addconfigs)
1967     make_oldconfig;
1968
1969     # check to see what we lost (or gained)
1970     open (IN, $output_config)
1971         or dodie "Failed to read $start_config";
1972
1973     my %removed_configs;
1974     my %added_configs;
1975
1976     while (<IN>) {
1977         if (/^((CONFIG\S*)=.*)/) {
1978             # save off all options
1979             $config_set{$2} = $1;
1980             if (defined($config_check{$2})) {
1981                 if (defined($config_ignore{$2})) {
1982                     $removed_configs{$2} = $1;
1983                 } else {
1984                     $config_list{$2} = $1;
1985                 }
1986             } elsif (!defined($config_ignore{$2})) {
1987                 $added_configs{$2} = $1;
1988                 $config_list{$2} = $1;
1989             }
1990         }
1991     }
1992     close(IN);
1993
1994     my @confs = keys %removed_configs;
1995     if ($#confs >= 0) {
1996         doprint "Configs overridden by default configs and removed from check:\n";
1997         foreach my $config (@confs) {
1998             doprint " $config\n";
1999         }
2000     }
2001     @confs = keys %added_configs;
2002     if ($#confs >= 0) {
2003         doprint "Configs appearing in make oldconfig and added:\n";
2004         foreach my $config (@confs) {
2005             doprint " $config\n";
2006         }
2007     }
2008
2009     my %config_test;
2010     my $once = 0;
2011
2012     # Sometimes kconfig does weird things. We must make sure
2013     # that the config we autocreate has everything we need
2014     # to test, otherwise we may miss testing configs, or
2015     # may not be able to create a new config.
2016     # Here we create a config with everything set.
2017     create_config (keys %config_list);
2018     read_current_config \%config_test;
2019     foreach my $config (keys %config_list) {
2020         if (!defined($config_test{$config})) {
2021             if (!$once) {
2022                 $once = 1;
2023                 doprint "Configs not produced by kconfig (will not be checked):\n";
2024             }
2025             doprint "  $config\n";
2026             delete $config_list{$config};
2027         }
2028     }
2029     my $ret;
2030     do {
2031         $ret = run_config_bisect;
2032     } while (!$ret);
2033
2034     return $ret if ($ret < 0);
2035
2036     success $i;
2037 }
2038
2039 sub patchcheck_reboot {
2040     doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
2041     reboot;
2042     start_monitor;
2043     wait_for_monitor $patchcheck_sleep_time;
2044     end_monitor;
2045 }
2046
2047 sub patchcheck {
2048     my ($i) = @_;
2049
2050     die "PATCHCHECK_START[$i] not defined\n"
2051         if (!defined($opt{"PATCHCHECK_START[$i]"}));
2052     die "PATCHCHECK_TYPE[$i] not defined\n"
2053         if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
2054
2055     my $start = $opt{"PATCHCHECK_START[$i]"};
2056
2057     my $end = "HEAD";
2058     if (defined($opt{"PATCHCHECK_END[$i]"})) {
2059         $end = $opt{"PATCHCHECK_END[$i]"};
2060     }
2061
2062     # Get the true sha1's since we can use things like HEAD~3
2063     $start = get_sha1($start);
2064     $end = get_sha1($end);
2065
2066     my $type = $opt{"PATCHCHECK_TYPE[$i]"};
2067
2068     # Can't have a test without having a test to run
2069     if ($type eq "test" && !defined($run_test)) {
2070         $type = "boot";
2071     }
2072
2073     open (IN, "git log --pretty=oneline $end|") or
2074         dodie "could not get git list";
2075
2076     my @list;
2077
2078     while (<IN>) {
2079         chomp;
2080         $list[$#list+1] = $_;
2081         last if (/^$start/);
2082     }
2083     close(IN);
2084
2085     if ($list[$#list] !~ /^$start/) {
2086         fail "SHA1 $start not found";
2087     }
2088
2089     # go backwards in the list
2090     @list = reverse @list;
2091
2092     my $save_clean = $noclean;
2093     my %ignored_warnings;
2094
2095     if (defined($ignore_warnings)) {
2096         foreach my $sha1 (split /\s+/, $ignore_warnings) {
2097             $ignored_warnings{$sha1} = 1;
2098         }
2099     }
2100
2101     $in_patchcheck = 1;
2102     foreach my $item (@list) {
2103         my $sha1 = $item;
2104         $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
2105
2106         doprint "\nProcessing commit $item\n\n";
2107
2108         run_command "git checkout $sha1" or
2109             die "Failed to checkout $sha1";
2110
2111         # only clean on the first and last patch
2112         if ($item eq $list[0] ||
2113             $item eq $list[$#list]) {
2114             $noclean = $save_clean;
2115         } else {
2116             $noclean = 1;
2117         }
2118
2119         if (defined($minconfig)) {
2120             build "useconfig:$minconfig" or return 0;
2121         } else {
2122             # ?? no config to use?
2123             build "oldconfig" or return 0;
2124         }
2125
2126
2127         if (!defined($ignored_warnings{$sha1})) {
2128             check_buildlog $sha1 or return 0;
2129         }
2130
2131         next if ($type eq "build");
2132
2133         my $failed = 0;
2134
2135         start_monitor_and_boot or $failed = 1;
2136
2137         if (!$failed && $type ne "boot"){
2138             do_run_test or $failed = 1;
2139         }
2140         end_monitor;
2141         return 0 if ($failed);
2142
2143         patchcheck_reboot;
2144
2145     }
2146     $in_patchcheck = 0;
2147     success $i;
2148
2149     return 1;
2150 }
2151
2152 $#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
2153
2154 if ($#ARGV == 0) {
2155     $ktest_config = $ARGV[0];
2156     if (! -f $ktest_config) {
2157         print "$ktest_config does not exist.\n";
2158         my $ans;
2159         for (;;) {
2160             print "Create it? [Y/n] ";
2161             $ans = <STDIN>;
2162             chomp $ans;
2163             if ($ans =~ /^\s*$/) {
2164                 $ans = "y";
2165             }
2166             last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
2167             print "Please answer either 'y' or 'n'.\n";
2168         }
2169         if ($ans !~ /^y$/i) {
2170             exit 0;
2171         }
2172     }
2173 } else {
2174     $ktest_config = "ktest.conf";
2175 }
2176
2177 if (! -f $ktest_config) {
2178     open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
2179     print OUT << "EOF"
2180 # Generated by ktest.pl
2181 #
2182 # Define each test with TEST_START
2183 # The config options below it will override the defaults
2184 TEST_START
2185
2186 DEFAULTS
2187 EOF
2188 ;
2189     close(OUT);
2190 }
2191 read_config $ktest_config;
2192
2193 if (defined($opt{"LOG_FILE"})) {
2194     $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
2195 }
2196
2197 # Append any configs entered in manually to the config file.
2198 my @new_configs = keys %entered_configs;
2199 if ($#new_configs >= 0) {
2200     print "\nAppending entered in configs to $ktest_config\n";
2201     open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
2202     foreach my $config (@new_configs) {
2203         print OUT "$config = $entered_configs{$config}\n";
2204         $opt{$config} = $entered_configs{$config};
2205     }
2206 }
2207
2208 if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
2209     unlink $opt{"LOG_FILE"};
2210 }
2211
2212 doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
2213
2214 for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
2215
2216     if (!$i) {
2217         doprint "DEFAULT OPTIONS:\n";
2218     } else {
2219         doprint "\nTEST $i OPTIONS";
2220         if (defined($repeat_tests{$i})) {
2221             $repeat = $repeat_tests{$i};
2222             doprint " ITERATE $repeat";
2223         }
2224         doprint "\n";
2225     }
2226
2227     foreach my $option (sort keys %opt) {
2228
2229         if ($option =~ /\[(\d+)\]$/) {
2230             next if ($i != $1);
2231         } else {
2232             next if ($i);
2233         }
2234
2235         doprint "$option = $opt{$option}\n";
2236     }
2237 }
2238
2239 sub __set_test_option {
2240     my ($name, $i) = @_;
2241
2242     my $option = "$name\[$i\]";
2243
2244     if (defined($opt{$option})) {
2245         return $opt{$option};
2246     }
2247
2248     foreach my $test (keys %repeat_tests) {
2249         if ($i >= $test &&
2250             $i < $test + $repeat_tests{$test}) {
2251             $option = "$name\[$test\]";
2252             if (defined($opt{$option})) {
2253                 return $opt{$option};
2254             }
2255         }
2256     }
2257
2258     if (defined($opt{$name})) {
2259         return $opt{$name};
2260     }
2261
2262     return undef;
2263 }
2264
2265 sub set_test_option {
2266     my ($name, $i) = @_;
2267
2268     my $option = __set_test_option($name, $i);
2269     return $option if (!defined($option));
2270
2271     return eval_option($option, $i);
2272 }
2273
2274 # First we need to do is the builds
2275 for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2276
2277     $iteration = $i;
2278
2279     my $makecmd = set_test_option("MAKE_CMD", $i);
2280
2281     $machine = set_test_option("MACHINE", $i);
2282     $ssh_user = set_test_option("SSH_USER", $i);
2283     $tmpdir = set_test_option("TMP_DIR", $i);
2284     $outputdir = set_test_option("OUTPUT_DIR", $i);
2285     $builddir = set_test_option("BUILD_DIR", $i);
2286     $test_type = set_test_option("TEST_TYPE", $i);
2287     $build_type = set_test_option("BUILD_TYPE", $i);
2288     $build_options = set_test_option("BUILD_OPTIONS", $i);
2289     $pre_build = set_test_option("PRE_BUILD", $i);
2290     $post_build = set_test_option("POST_BUILD", $i);
2291     $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
2292     $post_build_die = set_test_option("POST_BUILD_DIE", $i);
2293     $power_cycle = set_test_option("POWER_CYCLE", $i);
2294     $reboot = set_test_option("REBOOT", $i);
2295     $noclean = set_test_option("BUILD_NOCLEAN", $i);
2296     $minconfig = set_test_option("MIN_CONFIG", $i);
2297     $run_test = set_test_option("TEST", $i);
2298     $addconfig = set_test_option("ADD_CONFIG", $i);
2299     $reboot_type = set_test_option("REBOOT_TYPE", $i);
2300     $grub_menu = set_test_option("GRUB_MENU", $i);
2301     $post_install = set_test_option("POST_INSTALL", $i);
2302     $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
2303     $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
2304     $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
2305     $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
2306     $power_off = set_test_option("POWER_OFF", $i);
2307     $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
2308     $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
2309     $sleep_time = set_test_option("SLEEP_TIME", $i);
2310     $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
2311     $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
2312     $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
2313     $bisect_manual = set_test_option("BISECT_MANUAL", $i);
2314     $bisect_skip = set_test_option("BISECT_SKIP", $i);
2315     $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
2316     $store_failures = set_test_option("STORE_FAILURES", $i);
2317     $test_name = set_test_option("TEST_NAME", $i);
2318     $timeout = set_test_option("TIMEOUT", $i);
2319     $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
2320     $console = set_test_option("CONSOLE", $i);
2321     $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
2322     $success_line = set_test_option("SUCCESS_LINE", $i);
2323     $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
2324     $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
2325     $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
2326     $build_target = set_test_option("BUILD_TARGET", $i);
2327     $ssh_exec = set_test_option("SSH_EXEC", $i);
2328     $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
2329     $target_image = set_test_option("TARGET_IMAGE", $i);
2330     $localversion = set_test_option("LOCALVERSION", $i);
2331
2332     chdir $builddir || die "can't change directory to $builddir";
2333
2334     if (!-d $tmpdir) {
2335         mkpath($tmpdir) or
2336             die "can't create $tmpdir";
2337     }
2338
2339     $ENV{"SSH_USER"} = $ssh_user;
2340     $ENV{"MACHINE"} = $machine;
2341
2342     $target = "$ssh_user\@$machine";
2343
2344     $buildlog = "$tmpdir/buildlog-$machine";
2345     $dmesg = "$tmpdir/dmesg-$machine";
2346     $make = "$makecmd O=$outputdir";
2347     $output_config = "$outputdir/.config";
2348
2349     if ($reboot_type eq "grub") {
2350         dodie "GRUB_MENU not defined" if (!defined($grub_menu));
2351     } elsif (!defined($reboot_script)) {
2352         dodie "REBOOT_SCRIPT not defined"
2353     }
2354
2355     my $run_type = $build_type;
2356     if ($test_type eq "patchcheck") {
2357         $run_type = $opt{"PATCHCHECK_TYPE[$i]"};
2358     } elsif ($test_type eq "bisect") {
2359         $run_type = $opt{"BISECT_TYPE[$i]"};
2360     } elsif ($test_type eq "config_bisect") {
2361         $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
2362     }
2363
2364     # mistake in config file?
2365     if (!defined($run_type)) {
2366         $run_type = "ERROR";
2367     }
2368
2369     doprint "\n\n";
2370     doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
2371
2372     unlink $dmesg;
2373     unlink $buildlog;
2374
2375     if (!defined($minconfig)) {
2376         $minconfig = $addconfig;
2377
2378     } elsif (defined($addconfig)) {
2379         run_command "cat $addconfig $minconfig > $tmpdir/add_config" or
2380             dodie "Failed to create temp config";
2381         $minconfig = "$tmpdir/add_config";
2382     }
2383
2384     my $checkout = $opt{"CHECKOUT[$i]"};
2385     if (defined($checkout)) {
2386         run_command "git checkout $checkout" or
2387             die "failed to checkout $checkout";
2388     }
2389
2390     if ($test_type eq "bisect") {
2391         bisect $i;
2392         next;
2393     } elsif ($test_type eq "config_bisect") {
2394         config_bisect $i;
2395         next;
2396     } elsif ($test_type eq "patchcheck") {
2397         patchcheck $i;
2398         next;
2399     }
2400
2401     if ($build_type ne "nobuild") {
2402         build $build_type or next;
2403     }
2404
2405     if ($test_type ne "build") {
2406         my $failed = 0;
2407         start_monitor_and_boot or $failed = 1;
2408
2409         if (!$failed && $test_type ne "boot" && defined($run_test)) {
2410             do_run_test or $failed = 1;
2411         }
2412         end_monitor;
2413         next if ($failed);
2414     }
2415
2416     success $i;
2417 }
2418
2419 if ($opt{"POWEROFF_ON_SUCCESS"}) {
2420     halt;
2421 } elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
2422     reboot;
2423 }
2424
2425 doprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
2426
2427 exit 0;