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