0a0b1b16fccd3718e40dc3444ffca5f0737a15fb
[linux-2.6.git] / tools / testing / ktest / ktest.pl
1 #!/usr/bin/perl -w
2 #
3 # Copywrite 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 FileHandle;
11
12 $#ARGV >= 0 || die "usage: autotest.pl config-file\n";
13
14 $| = 1;
15
16 my %opt;
17
18 #default opts
19 $opt{"NUM_BUILDS"}              = 5;
20 $opt{"DEFAULT_BUILD_TYPE"}      = "randconfig";
21 $opt{"MAKE_CMD"}                = "make";
22 $opt{"TIMEOUT"}                 = 120;
23 $opt{"TMP_DIR"}                 = "/tmp/autotest";
24 $opt{"SLEEP_TIME"}              = 60;   # sleep time between tests
25 $opt{"BUILD_NOCLEAN"}           = 0;
26 $opt{"REBOOT_ON_ERROR"}         = 0;
27 $opt{"POWEROFF_ON_ERROR"}       = 0;
28 $opt{"REBOOT_ON_SUCCESS"}       = 1;
29 $opt{"POWEROFF_ON_SUCCESS"}     = 0;
30 $opt{"BUILD_OPTIONS"}           = "";
31 $opt{"BISECT_SLEEP_TIME"}       = 10;   # sleep time between bisects
32 $opt{"CLEAR_LOG"}               = 0;
33 $opt{"SUCCESS_LINE"}            = "login:";
34 $opt{"BOOTED_TIMEOUT"}          = 1;
35 $opt{"DIE_ON_FAILURE"}          = 1;
36
37 my $version;
38 my $grub_number;
39 my $target;
40 my $make;
41 my $noclean;
42 my $minconfig;
43 my $addconfig;
44 my $in_bisect = 0;
45 my $bisect_bad = "";
46 my $reverse_bisect;
47 my $in_patchcheck = 0;
48 my $run_test;
49 my $redirect;
50
51 sub read_config {
52     my ($config) = @_;
53
54     open(IN, $config) || die "can't read file $config";
55
56     while (<IN>) {
57
58         # ignore blank lines and comments
59         next if (/^\s*$/ || /\s*\#/);
60
61         if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) {
62             my $lvalue = $1;
63             my $rvalue = $2;
64
65             $opt{$lvalue} = $rvalue;
66         }
67     }
68
69     close(IN);
70 }
71
72 sub logit {
73     if (defined($opt{"LOG_FILE"})) {
74         open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
75         print OUT @_;
76         close(OUT);
77     }
78 }
79
80 sub doprint {
81     print @_;
82     logit @_;
83 }
84
85 sub dodie {
86     doprint "CRITICAL FAILURE... ", @_, "\n";
87
88     if ($opt{"REBOOT_ON_ERROR"}) {
89         doprint "REBOOTING\n";
90         `$opt{"POWER_CYCLE"}`;
91
92     } elsif ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) {
93         doprint "POWERING OFF\n";
94         `$opt{"POWER_OFF"}`;
95     }
96
97     die @_;
98 }
99
100 sub fail {
101
102         if ($opt{"DIE_ON_FAILURE"}) {
103                 dodie @_;
104         }
105
106         doprint "Failed: ", @_, "\n";
107         return 1;
108 }
109
110 sub run_command {
111     my ($command) = @_;
112     my $dolog = 0;
113     my $dord = 0;
114     my $pid;
115
116     doprint("$command ... ");
117
118     $pid = open(CMD, "$command 2>&1 |") or
119         (fail "unable to exec $command" and return 0);
120
121     if (defined($opt{"LOG_FILE"})) {
122         open(LOG, ">>$opt{LOG_FILE}") or
123             dodie "failed to write to log";
124         $dolog = 1;
125     }
126
127     if (defined($redirect)) {
128         open (RD, ">$redirect") or
129             dodie "failed to write to redirect $redirect";
130         $dord = 1;
131     }
132
133     while (<CMD>) {
134         print LOG if ($dolog);
135         print RD  if ($dord);
136     }
137
138     waitpid($pid, 0);
139     my $failed = $?;
140
141     close(CMD);
142     close(LOG) if ($dolog);
143     close(RD)  if ($dord);
144
145     if ($failed) {
146         doprint "FAILED!\n";
147     } else {
148         doprint "SUCCESS\n";
149     }
150
151     return !$failed;
152 }
153
154 sub get_grub_index {
155
156     return if (defined($grub_number));
157
158     doprint "Find grub menu ... ";
159     $grub_number = -1;
160     open(IN, "ssh $target cat /boot/grub/menu.lst |")
161         or die "unable to get menu.lst";
162     while (<IN>) {
163         if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) {
164             $grub_number++;
165             last;
166         } elsif (/^\s*title\s/) {
167             $grub_number++;
168         }
169     }
170     close(IN);
171
172     die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}"
173         if ($grub_number < 0);
174     doprint "$grub_number\n";
175 }
176
177 my $timeout = $opt{"TIMEOUT"};
178
179 sub wait_for_input
180 {
181     my ($fp, $time) = @_;
182     my $rin;
183     my $ready;
184     my $line;
185     my $ch;
186
187     if (!defined($time)) {
188         $time = $timeout;
189     }
190
191     $rin = '';
192     vec($rin, fileno($fp), 1) = 1;
193     $ready = select($rin, undef, undef, $time);
194
195     $line = "";
196
197     # try to read one char at a time
198     while (sysread $fp, $ch, 1) {
199         $line .= $ch;
200         last if ($ch eq "\n");
201     }
202
203     if (!length($line)) {
204         return undef;
205     }
206
207     return $line;
208 }
209
210 sub reboot_to {
211     run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
212 }
213
214 sub open_console {
215     my ($fp) = @_;
216
217     my $flags;
218
219     my $pid = open($fp, "$opt{CONSOLE}|") or
220         dodie "Can't open console $opt{CONSOLE}";
221
222     $flags = fcntl($fp, F_GETFL, 0) or
223         dodie "Can't get flags for the socket: $!\n";
224     $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
225         dodie "Can't set flags for the socket: $!\n";
226
227     return $pid;
228 }
229
230 sub close_console {
231     my ($fp, $pid) = @_;
232
233     doprint "kill child process $pid\n";
234     kill 2, $pid;
235
236     print "closing!\n";
237     close($fp);
238 }
239
240 sub monitor {
241     my $booted = 0;
242     my $bug = 0;
243     my $pid;
244     my $skip_call_trace = 0;
245     my $fp = \*IN;
246     my $loops;
247
248     $pid = open_console($fp);
249
250     my $line;
251     my $full_line = "";
252
253     doprint "Wait for monitor to settle down.\n";
254     # read the monitor and wait for the system to calm down
255     do {
256         $line = wait_for_input($fp, 5);
257     } while (defined($line));
258
259     reboot_to;
260
261     for (;;) {
262
263         if ($booted) {
264             $line = wait_for_input($fp, $opt{"BOOTED_TIMEOUT"});
265         } else {
266             $line = wait_for_input($fp);
267         }
268
269         last if (!defined($line));
270
271         doprint $line;
272
273         # we are not guaranteed to get a full line
274         $full_line .= $line;
275
276         if ($full_line =~ /$opt{"SUCCESS_LINE"}/) {
277             $booted = 1;
278         }
279
280         if ($full_line =~ /\[ backtrace testing \]/) {
281             $skip_call_trace = 1;
282         }
283
284         if ($full_line =~ /call trace:/i) {
285             $bug = 1 if (!$skip_call_trace);
286         }
287
288         if ($full_line =~ /\[ end of backtrace testing \]/) {
289             $skip_call_trace = 0;
290         }
291
292         if ($full_line =~ /Kernel panic -/) {
293             $bug = 1;
294         }
295
296         if ($line =~ /\n/) {
297             $full_line = "";
298         }
299     }
300
301     close_console($fp, $pid);
302
303     if (!$booted) {
304         return 0 if ($in_bisect);
305         fail "failed - never got a boot prompt.\n" and return 0;
306     }
307
308     if ($bug) {
309         return 0 if ($in_bisect);
310         fail "failed - got a bug report\n" and return 0;
311     }
312
313     return 1;
314 }
315
316 sub install {
317
318     run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}" or
319         dodie "failed to copy image";
320
321     my $install_mods = 0;
322
323     # should we process modules?
324     $install_mods = 0;
325     open(IN, "$opt{OUTPUT_DIR}/.config") or dodie("Can't read config file");
326     while (<IN>) {
327         if (/CONFIG_MODULES(=y)?/) {
328             $install_mods = 1 if (defined($1));
329             last;
330         }
331     }
332     close(IN);
333
334     if (!$install_mods) {
335         doprint "No modules needed\n";
336         return;
337     }
338
339     run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install" or
340         dodie "Failed to install modules";
341
342     my $modlib = "/lib/modules/$version";
343     my $modtar = "autotest-mods.tar.bz2";
344
345     run_command "ssh $target rm -rf $modlib" or
346         dodie "failed to remove old mods: $modlib";
347
348     # would be nice if scp -r did not follow symbolic links
349     run_command "cd $opt{TMP_DIR} && tar -cjf $modtar lib/modules/$version" or
350         dodie "making tarball";
351
352     run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp" or
353         dodie "failed to copy modules";
354
355     unlink "$opt{TMP_DIR}/$modtar";
356
357     run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or
358         dodie "failed to tar modules";
359
360     run_command "ssh $target rm -f /tmp/$modtar";
361 }
362
363 sub check_buildlog {
364     my ($patch) = @_;
365
366     my $buildlog = "$opt{TMP_DIR}/buildlog";
367     my @files = `git show $patch | diffstat -l`;
368
369     open(IN, "git show $patch |") or
370         dodie "failed to show $patch";
371     while (<IN>) {
372         if (m,^--- a/(.*),) {
373             chomp $1;
374             $files[$#files] = $1;
375         }
376     }
377     close(IN);
378
379     open(IN, $buildlog) or dodie "Can't open $buildlog";
380     while (<IN>) {
381         if (/^\s*(.*?):.*(warning|error)/) {
382             my $err = $1;
383             foreach my $file (@files) {
384                 my $fullpath = "$opt{BUILD_DIR}/$file";
385                 if ($file eq $err || $fullpath eq $err) {
386                     fail "$file built with warnings" and return 0;
387                 }
388             }
389         }
390     }
391     close(IN);
392
393     return 1;
394 }
395
396 sub build {
397     my ($type) = @_;
398     my $defconfig = "";
399     my $append = "";
400
401     if ($type =~ /^useconfig:(.*)/) {
402         run_command "cp $1 $opt{OUTPUT_DIR}/.config" or
403             dodie "could not copy $1 to .config";
404
405         $type = "oldconfig";
406     }
407
408     # old config can ask questions
409     if ($type eq "oldconfig") {
410         $append = "yes ''|";
411
412         # allow for empty configs
413         run_command "touch $opt{OUTPUT_DIR}/.config";
414
415         run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp" or
416             dodie "moving .config";
417
418         if (!$noclean && !run_command "$make mrproper") {
419             dodie "make mrproper";
420         }
421
422         run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config" or
423             dodie "moving config_temp";
424
425     } elsif (!$noclean) {
426         unlink "$opt{OUTPUT_DIR}/.config";
427         run_command "$make mrproper" or
428             dodie "make mrproper";
429     }
430
431     # add something to distinguish this build
432     open(OUT, "> $opt{OUTPUT_DIR}/localversion") or dodie("Can't make localversion file");
433     print OUT "$opt{LOCALVERSION}\n";
434     close(OUT);
435
436     if (defined($minconfig)) {
437         $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
438     }
439
440     run_command "$defconfig $append $make $type" or
441         dodie "failed make config";
442
443     # patch check will examine the log
444     if ($in_patchcheck) {
445         $redirect = "$opt{TMP_DIR}/buildlog";
446     }
447
448     if (!run_command "$make $opt{BUILD_OPTIONS}") {
449         undef $redirect;
450         # bisect may need this to pass
451         return 0 if ($in_bisect);
452         fail "failed build" and return 0;
453     }
454     undef $redirect;
455
456     return 1;
457 }
458
459 sub reboot {
460     # try to reboot normally
461     if (!run_command "ssh $target reboot") {
462         # nope? power cycle it.
463         run_command "$opt{POWER_CYCLE}";
464     }
465 }
466
467 sub halt {
468     if (!run_command "ssh $target halt" or defined($opt{"POWER_OFF"})) {
469         # nope? the zap it!
470         run_command "$opt{POWER_OFF}";
471     }
472 }
473
474 sub success {
475     my ($i) = @_;
476
477     doprint "\n\n*******************************************\n";
478     doprint     "*******************************************\n";
479     doprint     "**            SUCCESS!!!!                **\n";
480     doprint     "*******************************************\n";
481     doprint     "*******************************************\n";
482
483     if ($i != $opt{"NUM_BUILDS"}) {
484         reboot;
485         doprint "Sleeping $opt{SLEEP_TIME} seconds\n";
486         sleep "$opt{SLEEP_TIME}";
487     }
488 }
489
490 sub get_version {
491     # get the release name
492     doprint "$make kernelrelease ... ";
493     $version = `$make kernelrelease | tail -1`;
494     chomp($version);
495     doprint "$version\n";
496 }
497
498 sub child_run_test {
499     my $failed;
500
501     $failed = !run_command $run_test;
502     exit $failed;
503 }
504
505 my $child_done;
506
507 sub child_finished {
508     $child_done = 1;
509 }
510
511 sub do_run_test {
512     my $child_pid;
513     my $child_exit;
514     my $pid;
515     my $line;
516     my $full_line;
517     my $bug = 0;
518     my $fp = \*IN;
519
520     $pid = open_console($fp);
521
522     # read the monitor and wait for the system to calm down
523     do {
524         $line = wait_for_input($fp, 1);
525     } while (defined($line));
526
527     $child_done = 0;
528
529     $SIG{CHLD} = qw(child_finished);
530
531     $child_pid = fork;
532
533     child_run_test if (!$child_pid);
534
535     $full_line = "";
536
537     do {
538         $line = wait_for_input($fp, 1);
539         if (defined($line)) {
540
541             # we are not guaranteed to get a full line
542             $full_line .= $line;
543
544             if ($full_line =~ /call trace:/i) {
545                 $bug = 1;
546             }
547
548             if ($full_line =~ /Kernel panic -/) {
549                 $bug = 1;
550             }
551
552             if ($line =~ /\n/) {
553                 $full_line = "";
554             }
555         }
556     } while (!$child_done && !$bug);
557
558     if ($bug) {
559         doprint "Detected kernel crash!\n";
560         # kill the child with extreme prejudice
561         kill 9, $child_pid;
562     }
563
564     waitpid $child_pid, 0;
565     $child_exit = $?;
566
567     close_console($fp, $pid);
568
569     if ($bug || $child_exit) {
570         return 0 if $in_bisect;
571         fail "test failed" and return 0;
572     }
573     return 1;
574 }
575
576 sub run_bisect {
577     my ($type) = @_;
578
579     my $failed = 0;
580     my $result;
581     my $output;
582     my $ret;
583
584     if (defined($minconfig)) {
585         build "useconfig:$minconfig" or $failed = 1;
586     } else {
587         # ?? no config to use?
588         build "oldconfig" or $failed = 1;
589     }
590
591     if ($type ne "build") {
592         fail "Failed on build" if $failed;
593
594         # Now boot the box
595         get_grub_index;
596         get_version;
597         install;
598         monitor or $failed = 1;
599
600         if ($type ne "boot") {
601             fail "Failed on boot" if $failed;
602
603             do_run_test or $failed = 1;
604         }
605     }
606
607     if ($failed) {
608         $result = "bad";
609
610         # reboot the box to a good kernel
611         if ($type eq "boot") {
612             reboot;
613             doprint "sleep a little for reboot\n";
614             sleep $opt{"BISECT_SLEEP_TIME"};
615         }
616     } else {
617         $result = "good";
618     }
619
620     # Are we looking for where it worked, not failed?
621     if ($reverse_bisect) {
622         if ($failed) {
623             $result = "good";
624         } else {
625             $result = "bad";
626         }
627     }
628
629     doprint "git bisect $result ... ";
630     $output = `git bisect $result 2>&1`;
631     $ret = $?;
632
633     logit $output;
634
635     if ($ret) {
636         doprint "FAILED\n";
637         fail "Failed to git bisect";
638     }
639
640     doprint "SUCCESS\n";
641     if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
642         doprint "$1 [$2]\n";
643     } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
644         $bisect_bad = $1;
645         doprint "Found bad commit... $1\n";
646         return 0;
647     } else {
648         # we already logged it, just print it now.
649         print $output;
650     }
651
652
653     return 1;
654 }
655
656 sub bisect {
657     my ($i) = @_;
658
659     my $result;
660
661     die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
662     die "BISECT_BAD[$i] not defined\n"  if (!defined($opt{"BISECT_BAD[$i]"}));
663     die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
664
665     my $good = $opt{"BISECT_GOOD[$i]"};
666     my $bad = $opt{"BISECT_BAD[$i]"};
667     my $type = $opt{"BISECT_TYPE[$i]"};
668
669     if (defined($opt{"BISECT_REVERSE[$i]"}) &&
670         $opt{"BISECT_REVERSE[$i]"} == 1) {
671         doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
672         $reverse_bisect = 1;
673     } else {
674         $reverse_bisect = 0;
675     }
676
677     $in_bisect = 1;
678
679     run_command "git bisect start" or
680         fail "could not start bisect";
681
682     run_command "git bisect good $good" or
683         fail "could not set bisect good to $good";
684
685     run_command "git bisect bad $bad" or
686         fail "could not set bisect good to $bad";
687
688     # Can't have a test without having a test to run
689     if ($type eq "test" && !defined($run_test)) {
690         $type = "boot";
691     }
692
693     do {
694         $result = run_bisect $type;
695     } while ($result);
696
697     run_command "git bisect log" or
698         dodie "could not capture git bisect log";
699
700     run_command "git bisect reset" or
701         dodie "could not reset git bisect";
702
703     doprint "Bad commit was [$bisect_bad]\n";
704
705     $in_bisect = 0;
706
707     success $i;
708 }
709
710 sub patchcheck {
711     my ($i) = @_;
712
713     die "PATCHCHECK_START[$i] not defined\n"
714         if (!defined($opt{"PATCHCHECK_START[$i]"}));
715     die "PATCHCHECK_TYPE[$i] not defined\n"
716         if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
717
718     my $start = $opt{"PATCHCHECK_START[$i]"};
719
720     my $end = "HEAD";
721     if (defined($opt{"PATCHCHECK_END[$i]"})) {
722         $end = $opt{"PATCHCHECK_END[$i]"};
723     }
724
725     my $type = $opt{"PATCHCHECK_TYPE[$i]"};
726
727     # Can't have a test without having a test to run
728     if ($type eq "test" && !defined($run_test)) {
729         $type = "boot";
730     }
731
732     open (IN, "git log --pretty=oneline $end|") or
733         dodie "could not get git list";
734
735     my @list;
736
737     while (<IN>) {
738         chomp;
739         $list[$#list+1] = $_;
740         last if (/^$start/);
741     }
742     close(IN);
743
744     if ($list[$#list] !~ /^$start/) {
745         fail "SHA1 $start not found";
746     }
747
748     # go backwards in the list
749     @list = reverse @list;
750
751     my $save_clean = $noclean;
752
753     $in_patchcheck = 1;
754     foreach my $item (@list) {
755         my $sha1 = $item;
756         $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
757
758         doprint "\nProcessing commit $item\n\n";
759
760         run_command "git checkout $sha1" or
761             die "Failed to checkout $sha1";
762
763         # only clean on the first and last patch
764         if ($item eq $list[0] ||
765             $item eq $list[$#list]) {
766             $noclean = $save_clean;
767         } else {
768             $noclean = 1;
769         }
770
771         if (defined($minconfig)) {
772             build "useconfig:$minconfig" or return 0;
773         } else {
774             # ?? no config to use?
775             build "oldconfig" or return 0;
776         }
777
778         check_buildlog $sha1 or return 0;
779
780         next if ($type eq "build");
781
782         get_grub_index;
783         get_version;
784         install;
785         monitor or return 0;
786
787         next if ($type eq "boot");
788         do_run_test or next;
789     }
790     $in_patchcheck = 0;
791     success $i;
792
793     return 1;
794 }
795
796 read_config $ARGV[0];
797
798 # mandatory configs
799 die "MACHINE not defined\n"             if (!defined($opt{"MACHINE"}));
800 die "SSH_USER not defined\n"            if (!defined($opt{"SSH_USER"}));
801 die "BUILD_DIR not defined\n"           if (!defined($opt{"BUILD_DIR"}));
802 die "OUTPUT_DIR not defined\n"          if (!defined($opt{"OUTPUT_DIR"}));
803 die "BUILD_TARGET not defined\n"        if (!defined($opt{"BUILD_TARGET"}));
804 die "TARGET_IMAGE not defined\n"        if (!defined($opt{"TARGET_IMAGE"}));
805 die "POWER_CYCLE not defined\n"         if (!defined($opt{"POWER_CYCLE"}));
806 die "CONSOLE not defined\n"             if (!defined($opt{"CONSOLE"}));
807 die "LOCALVERSION not defined\n"        if (!defined($opt{"LOCALVERSION"}));
808 die "GRUB_MENU not defined\n"           if (!defined($opt{"GRUB_MENU"}));
809
810 chdir $opt{"BUILD_DIR"} || die "can't change directory to $opt{BUILD_DIR}";
811
812 $target = "$opt{SSH_USER}\@$opt{MACHINE}";
813
814 if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
815     unlink $opt{"LOG_FILE"};
816 }
817
818 doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
819
820 foreach my $option (sort keys %opt) {
821     doprint "$option = $opt{$option}\n";
822 }
823
824 $make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}";
825
826 sub set_build_option {
827     my ($name, $i) = @_;
828
829     my $option = "$name\[$i\]";
830
831     if (defined($opt{$option})) {
832         return $opt{$option};
833     }
834
835     if (defined($opt{$name})) {
836         return $opt{$name};
837     }
838
839     return undef;
840 }
841
842 # First we need to do is the builds
843 for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
844     my $type = "BUILD_TYPE[$i]";
845
846     if (!defined($opt{$type})) {
847         $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"};
848     }
849
850     $noclean = set_build_option("BUILD_NOCLEAN", $i);
851     $minconfig = set_build_option("MIN_CONFIG", $i);
852     $run_test = set_build_option("TEST", $i);
853     $addconfig = set_build_option("ADD_CONFIG", $i);
854
855     doprint "\n\n";
856     doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n";
857
858     if (!defined($minconfig)) {
859         $minconfig = $addconfig;
860
861     } elsif (defined($addconfig)) {
862         run_command "cat $addconfig $minconfig > $opt{TMP_DIR}/use_config" or
863             dodie "Failed to create temp config";
864         $minconfig = "$opt{TMP_DIR}/use_config";
865     }
866
867     my $checkout = $opt{"CHECKOUT[$i]"};
868     if (defined($checkout)) {
869         run_command "git checkout $checkout" or
870             die "failed to checkout $checkout";
871     }
872
873     if ($opt{$type} eq "bisect") {
874         bisect $i;
875         next;
876     } elsif ($opt{$type} eq "patchcheck") {
877         patchcheck $i;
878         next;
879     }
880
881     if ($opt{$type} ne "nobuild") {
882         build $opt{$type} or next;
883     }
884
885     get_grub_index;
886     get_version;
887     install;
888     monitor or next;
889
890     if (defined($run_test)) {
891         do_run_test or next;
892     }
893
894     success $i;
895 }
896
897 if ($opt{"POWEROFF_ON_SUCCESS"}) {
898     halt;
899 } elsif ($opt{"REBOOT_ON_SUCCESS"}) {
900     reboot;
901 }
902
903 exit 0;