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