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