blob: 0dc403e7170cec98c0e995ffc7fb9f5c9dfaadd6 [file] [log] [blame]
Steven Rostedt2545eb62010-11-02 15:01:32 -04001#!/usr/bin/perl -w
Steven Rostedtd6ce2a02010-11-02 14:58:05 -04002#
3# Copywrite 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
4# Licensed under the terms of the GNU GPL License version 2
5#
Steven Rostedt2545eb62010-11-02 15:01:32 -04006
7use strict;
8use IPC::Open2;
9use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
10use FileHandle;
11
12$#ARGV >= 0 || die "usage: autotest.pl config-file\n";
13
14$| = 1;
15
16my %opt;
17
18#default opts
19$opt{"NUM_BUILDS"} = 5;
20$opt{"DEFAULT_BUILD_TYPE"} = "randconfig";
21$opt{"MAKE_CMD"} = "make";
22$opt{"TIMEOUT"} = 50;
23$opt{"TMP_DIR"} = "/tmp/autotest";
24$opt{"SLEEP_TIME"} = 60; # sleep time between tests
Steven Rostedt5c42fc52010-11-02 14:57:01 -040025$opt{"BUILD_NOCLEAN"} = 0;
Steven Rostedt75c3fda72010-11-02 14:57:21 -040026$opt{"REBOOT_ON_ERROR"} = 0;
Steven Rostedt5c42fc52010-11-02 14:57:01 -040027$opt{"POWEROFF_ON_ERROR"} = 0;
Steven Rostedt1a5cfce2010-11-02 14:57:51 -040028$opt{"REBOOT_ON_SUCCESS"} = 1;
Steven Rostedt5c42fc52010-11-02 14:57:01 -040029$opt{"POWEROFF_ON_SUCCESS"} = 0;
Steven Rostedt75c3fda72010-11-02 14:57:21 -040030$opt{"BUILD_OPTIONS"} = "";
Steven Rostedt5a391fb2010-11-02 14:57:43 -040031$opt{"BISECT_SLEEP_TIME"} = 10; # sleep time between bisects
Steven Rostedt2545eb62010-11-02 15:01:32 -040032
33my $version;
Steven Rostedt2545eb62010-11-02 15:01:32 -040034my $grub_number;
35my $target;
36my $make;
Steven Rostedt5c42fc52010-11-02 14:57:01 -040037my $noclean;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040038my $minconfig;
39my $in_bisect = 0;
40my $bisect_bad = "";
Steven Rostedtd6ce2a02010-11-02 14:58:05 -040041my $reverse_bisect;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -040042my $in_patchcheck = 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -040043my $run_test;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -040044my $redirect;
Steven Rostedt2545eb62010-11-02 15:01:32 -040045
46sub read_config {
47 my ($config) = @_;
48
49 open(IN, $config) || die "can't read file $config";
50
51 while (<IN>) {
52
53 # ignore blank lines and comments
54 next if (/^\s*$/ || /\s*\#/);
55
56 if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) {
57 my $lvalue = $1;
58 my $rvalue = $2;
59
60 $opt{$lvalue} = $rvalue;
61 }
62 }
63
64 close(IN);
65}
66
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040067sub logit {
Steven Rostedt2545eb62010-11-02 15:01:32 -040068 if (defined($opt{"LOG_FILE"})) {
69 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
70 print OUT @_;
71 close(OUT);
72 }
73}
74
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040075sub doprint {
76 print @_;
77 logit @_;
78}
79
Steven Rostedt5c42fc52010-11-02 14:57:01 -040080sub dodie {
Steven Rostedt5a391fb2010-11-02 14:57:43 -040081 doprint "CRITICAL FAILURE... ", @_, "\n";
Steven Rostedt5c42fc52010-11-02 14:57:01 -040082
Steven Rostedt75c3fda72010-11-02 14:57:21 -040083 if ($opt{"REBOOT_ON_ERROR"}) {
84 doprint "REBOOTING\n";
85 `$opt{"POWER_CYCLE"}`;
86
87 } elsif ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) {
Steven Rostedt5c42fc52010-11-02 14:57:01 -040088 doprint "POWERING OFF\n";
89 `$opt{"POWER_OFF"}`;
90 }
Steven Rostedt75c3fda72010-11-02 14:57:21 -040091
Steven Rostedt5c42fc52010-11-02 14:57:01 -040092 die @_;
93}
94
Steven Rostedt2545eb62010-11-02 15:01:32 -040095sub run_command {
96 my ($command) = @_;
Steven Rostedtd6ce2a02010-11-02 14:58:05 -040097 my $dolog = 0;
98 my $dord = 0;
99 my $pid;
100
101 doprint("$command ... ");
102
103 $pid = open(CMD, "$command 2>&1 |") or
104 dodie "unable to exec $command";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400105
106 if (defined($opt{"LOG_FILE"})) {
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400107 open(LOG, ">>$opt{LOG_FILE}") or
108 dodie "failed to write to log";
109 $dolog = 1;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400110 }
111
112 if (defined($redirect)) {
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400113 open (RD, ">$redirect") or
114 dodie "failed to write to redirect $redirect";
115 $dord = 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400116 }
117
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400118 while (<CMD>) {
119 print LOG if ($dolog);
120 print RD if ($dord);
121 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400122
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400123 waitpid($pid, 0);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400124 my $failed = $?;
125
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400126 close(CMD);
127 close(LOG) if ($dolog);
128 close(RD) if ($dord);
129
Steven Rostedt2545eb62010-11-02 15:01:32 -0400130 if ($failed) {
131 doprint "FAILED!\n";
132 } else {
133 doprint "SUCCESS\n";
134 }
135
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400136 return !$failed;
137}
138
139sub get_grub_index {
140
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400141 return if (defined($grub_number));
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400142
143 doprint "Find grub menu ... ";
144 $grub_number = -1;
145 open(IN, "ssh $target cat /boot/grub/menu.lst |")
146 or die "unable to get menu.lst";
147 while (<IN>) {
148 if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) {
149 $grub_number++;
150 last;
151 } elsif (/^\s*title\s/) {
152 $grub_number++;
153 }
154 }
155 close(IN);
156
157 die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}"
158 if ($grub_number < 0);
159 doprint "$grub_number\n";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400160}
161
162my $timeout = $opt{"TIMEOUT"};
163
164sub wait_for_input
165{
166 my ($fp, $time) = @_;
167 my $rin;
168 my $ready;
169 my $line;
170 my $ch;
171
172 if (!defined($time)) {
173 $time = $timeout;
174 }
175
176 $rin = '';
177 vec($rin, fileno($fp), 1) = 1;
178 $ready = select($rin, undef, undef, $time);
179
180 $line = "";
181
182 # try to read one char at a time
183 while (sysread $fp, $ch, 1) {
184 $line .= $ch;
185 last if ($ch eq "\n");
186 }
187
188 if (!length($line)) {
189 return undef;
190 }
191
192 return $line;
193}
194
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400195sub reboot_to {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400196 run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
197}
198
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400199sub open_console {
200 my ($fp) = @_;
201
Steven Rostedt2545eb62010-11-02 15:01:32 -0400202 my $flags;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400203
204 my $pid = open($fp, "$opt{CONSOLE}|") or
205 dodie "Can't open console $opt{CONSOLE}";
206
207 $flags = fcntl($fp, F_GETFL, 0) or
208 dodie "Can't get flags for the socket: $!\n";
209 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
210 dodie "Can't set flags for the socket: $!\n";
211
212 return $pid;
213}
214
215sub close_console {
216 my ($fp, $pid) = @_;
217
218 doprint "kill child process $pid\n";
219 kill 2, $pid;
220
221 print "closing!\n";
222 close($fp);
223}
224
225sub monitor {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400226 my $booted = 0;
227 my $bug = 0;
228 my $pid;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400229 my $skip_call_trace = 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400230 my $fp = \*IN;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400231
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400232 $pid = open_console($fp);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400233
234 my $line;
235 my $full_line = "";
236
237 doprint "Wait for monitor to settle down.\n";
238 # read the monitor and wait for the system to calm down
239 do {
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400240 $line = wait_for_input($fp, 5);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400241 } while (defined($line));
242
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400243 reboot_to;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400244
245 for (;;) {
246
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400247 $line = wait_for_input($fp);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400248
249 last if (!defined($line));
250
251 doprint $line;
252
253 # we are not guaranteed to get a full line
254 $full_line .= $line;
255
256 if ($full_line =~ /login:/) {
257 $booted = 1;
258 }
259
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400260 if ($full_line =~ /\[ backtrace testing \]/) {
261 $skip_call_trace = 1;
262 }
263
Steven Rostedt2545eb62010-11-02 15:01:32 -0400264 if ($full_line =~ /call trace:/i) {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400265 $bug = 1 if (!$skip_call_trace);
266 }
267
268 if ($full_line =~ /\[ end of backtrace testing \]/) {
269 $skip_call_trace = 0;
270 }
271
272 if ($full_line =~ /Kernel panic -/) {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400273 $bug = 1;
274 }
275
276 if ($line =~ /\n/) {
277 $full_line = "";
278 }
279 }
280
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400281 close_console($fp, $pid);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400282
283 if (!$booted) {
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400284 return 1 if ($in_bisect);
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400285 dodie "failed - never got a boot prompt.\n";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400286 }
287
288 if ($bug) {
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400289 return 1 if ($in_bisect);
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400290 dodie "failed - got a bug report\n";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400291 }
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400292
293 return 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400294}
295
296sub install {
297
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400298 run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400299 dodie "failed to copy image";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400300
301 my $install_mods = 0;
302
303 # should we process modules?
304 $install_mods = 0;
305 open(IN, "$opt{OUTPUT_DIR}/.config") or dodie("Can't read config file");
306 while (<IN>) {
307 if (/CONFIG_MODULES(=y)?/) {
308 $install_mods = 1 if (defined($1));
309 last;
310 }
311 }
312 close(IN);
313
314 if (!$install_mods) {
315 doprint "No modules needed\n";
316 return;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400317 }
318
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400319 run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install" or
320 dodie "Failed to install modules";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400321
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400322 my $modlib = "/lib/modules/$version";
323 my $modtar = "autotest-mods.tar.bz2";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400324
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400325 run_command "ssh $target rm -rf $modlib" or
326 dodie "failed to remove old mods: $modlib";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400327
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400328 # would be nice if scp -r did not follow symbolic links
329 run_command "cd $opt{TMP_DIR} && tar -cjf $modtar lib/modules/$version" or
330 dodie "making tarball";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400331
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400332 run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp" or
333 dodie "failed to copy modules";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400334
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400335 unlink "$opt{TMP_DIR}/$modtar";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400336
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400337 run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or
338 dodie "failed to tar modules";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400339
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400340 run_command "ssh $target rm -f /tmp/$modtar";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400341}
342
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400343sub check_buildlog {
344 my ($patch) = @_;
345
346 my $buildlog = "$opt{TMP_DIR}/buildlog";
347 my @files = `git show $patch | diffstat -l`;
348
349 open(IN, "git show $patch |") or
350 dodie "failed to show $patch";
351 while (<IN>) {
352 if (m,^--- a/(.*),) {
353 chomp $1;
354 $files[$#files] = $1;
355 }
356 }
357 close(IN);
358
359 open(IN, $buildlog) or dodie "Can't open $buildlog";
360 while (<IN>) {
361 if (/^\s*(.*?):.*(warning|error)/) {
362 my $err = $1;
363 foreach my $file (@files) {
364 my $fullpath = "$opt{BUILD_DIR}/$file";
365 if ($file eq $err || $fullpath eq $err) {
366 dodie "$file built with warnings";
367 }
368 }
369 }
370 }
371 close(IN);
372}
373
Steven Rostedt2545eb62010-11-02 15:01:32 -0400374sub build {
375 my ($type) = @_;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400376 my $defconfig = "";
377 my $append = "";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400378
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400379 if ($type =~ /^useconfig:(.*)/) {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400380 run_command "cp $1 $opt{OUTPUT_DIR}/.config" or
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400381 dodie "could not copy $1 to .config";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400382
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400383 $type = "oldconfig";
384 }
385
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400386 # old config can ask questions
387 if ($type eq "oldconfig") {
388 $append = "yes ''|";
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400389
390 # allow for empty configs
391 run_command "touch $opt{OUTPUT_DIR}/.config";
392
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400393 run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400394 dodie "moving .config";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400395
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400396 if (!$noclean && !run_command "$make mrproper") {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400397 dodie "make mrproper";
398 }
399
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400400 run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400401 dodie "moving config_temp";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400402
403 } elsif (!$noclean) {
404 unlink "$opt{OUTPUT_DIR}/.config";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400405 run_command "$make mrproper" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400406 dodie "make mrproper";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400407 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400408
409 # add something to distinguish this build
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400410 open(OUT, "> $opt{OUTPUT_DIR}/localversion") or dodie("Can't make localversion file");
Steven Rostedt2545eb62010-11-02 15:01:32 -0400411 print OUT "$opt{LOCALVERSION}\n";
412 close(OUT);
413
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400414 if (defined($minconfig)) {
415 $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400416 }
417
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400418 run_command "$defconfig $append $make $type" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400419 dodie "failed make config";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400420
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400421 # patch check will examine the log
422 if ($in_patchcheck) {
423 $redirect = "$opt{TMP_DIR}/buildlog";
424 }
425
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400426 if (!run_command "$make $opt{BUILD_OPTIONS}") {
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400427 undef $redirect;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400428 # bisect may need this to pass
429 return 1 if ($in_bisect);
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400430 dodie "failed build";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400431 }
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400432 undef $redirect;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400433
434 return 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400435}
436
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400437sub reboot {
438 # try to reboot normally
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400439 if (!run_command "ssh $target reboot") {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400440 # nope? power cycle it.
441 run_command "$opt{POWER_CYCLE}";
442 }
443}
444
445sub halt {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400446 if (!run_command "ssh $target halt" or defined($opt{"POWER_OFF"})) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400447 # nope? the zap it!
448 run_command "$opt{POWER_OFF}";
449 }
450}
451
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400452sub success {
453 my ($i) = @_;
454
455 doprint "\n\n*******************************************\n";
456 doprint "*******************************************\n";
457 doprint "** SUCCESS!!!! **\n";
458 doprint "*******************************************\n";
459 doprint "*******************************************\n";
460
461 if ($i != $opt{"NUM_BUILDS"}) {
462 reboot;
463 doprint "Sleeping $opt{SLEEP_TIME} seconds\n";
464 sleep "$opt{SLEEP_TIME}";
465 }
466}
467
468sub get_version {
469 # get the release name
470 doprint "$make kernelrelease ... ";
471 $version = `$make kernelrelease | tail -1`;
472 chomp($version);
473 doprint "$version\n";
474}
475
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400476sub child_run_test {
477 my $failed;
478
479 $failed = !run_command $run_test;
480 exit $failed;
481}
482
483my $child_done;
484
485sub child_finished {
486 $child_done = 1;
487}
488
489sub do_run_test {
490 my $child_pid;
491 my $child_exit;
492 my $pid;
493 my $line;
494 my $full_line;
495 my $bug = 0;
496 my $fp = \*IN;
497
498 $pid = open_console($fp);
499
500 # read the monitor and wait for the system to calm down
501 do {
502 $line = wait_for_input($fp, 1);
503 } while (defined($line));
504
505 $child_done = 0;
506
507 $SIG{CHLD} = qw(child_finished);
508
509 $child_pid = fork;
510
511 child_run_test if (!$child_pid);
512
513 $full_line = "";
514
515 do {
516 $line = wait_for_input($fp, 1);
517 if (defined($line)) {
518
519 # we are not guaranteed to get a full line
520 $full_line .= $line;
521
522 if ($full_line =~ /call trace:/i) {
523 $bug = 1;
524 }
525
526 if ($full_line =~ /Kernel panic -/) {
527 $bug = 1;
528 }
529
530 if ($line =~ /\n/) {
531 $full_line = "";
532 }
533 }
534 } while (!$child_done && !$bug);
535
536 if ($bug) {
537 doprint "Detected kernel crash!\n";
538 # kill the child with extreme prejudice
539 kill 9, $child_pid;
540 }
541
542 waitpid $child_pid, 0;
543 $child_exit = $?;
544
545 close_console($fp, $pid);
546
547 if ($bug || $child_exit) {
548 return 1 if $in_bisect;
549 dodie "test failed";
550 }
551 return 0;
552}
553
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400554sub run_bisect {
555 my ($type) = @_;
556
557 my $failed;
558 my $result;
559 my $output;
560 my $ret;
561
562
563 if (defined($minconfig)) {
564 $failed = build "useconfig:$minconfig";
565 } else {
566 # ?? no config to use?
567 $failed = build "oldconfig";
568 }
569
570 if ($type ne "build") {
571 dodie "Failed on build" if $failed;
572
573 # Now boot the box
574 get_grub_index;
575 get_version;
576 install;
577 $failed = monitor;
578
579 if ($type ne "boot") {
580 dodie "Failed on boot" if $failed;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400581
582 $failed = do_run_test;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400583 }
584 }
585
586 if ($failed) {
587 $result = "bad";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400588
589 # reboot the box to a good kernel
590 if ($type eq "boot") {
591 reboot;
592 doprint "sleep a little for reboot\n";
593 sleep $opt{"BISECT_SLEEP_TIME"};
594 }
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400595 } else {
596 $result = "good";
597 }
598
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400599 # Are we looking for where it worked, not failed?
600 if ($reverse_bisect) {
601 if ($failed) {
602 $result = "good";
603 } else {
604 $result = "bad";
605 }
606 }
607
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400608 doprint "git bisect $result ... ";
609 $output = `git bisect $result 2>&1`;
610 $ret = $?;
611
612 logit $output;
613
614 if ($ret) {
615 doprint "FAILED\n";
616 dodie "Failed to git bisect";
617 }
618
619 doprint "SUCCESS\n";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400620 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400621 doprint "$1 [$2]\n";
622 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
623 $bisect_bad = $1;
624 doprint "Found bad commit... $1\n";
625 return 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400626 } else {
627 # we already logged it, just print it now.
628 print $output;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400629 }
630
631
632 return 1;
633}
634
635sub bisect {
636 my ($i) = @_;
637
638 my $result;
639
640 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
641 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
642 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
643
644 my $good = $opt{"BISECT_GOOD[$i]"};
645 my $bad = $opt{"BISECT_BAD[$i]"};
646 my $type = $opt{"BISECT_TYPE[$i]"};
647
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400648 if (defined($opt{"BISECT_REVERSE[$i]"}) &&
649 $opt{"BISECT_REVERSE[$i]"} == 1) {
650 doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
651 $reverse_bisect = 1;
652 } else {
653 $reverse_bisect = 0;
654 }
655
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400656 $in_bisect = 1;
657
658 run_command "git bisect start" or
659 dodie "could not start bisect";
660
661 run_command "git bisect good $good" or
662 dodie "could not set bisect good to $good";
663
664 run_command "git bisect bad $bad" or
665 dodie "could not set bisect good to $bad";
666
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400667 # Can't have a test without having a test to run
668 if ($type eq "test" && !defined($run_test)) {
669 $type = "boot";
670 }
671
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400672 do {
673 $result = run_bisect $type;
674 } while ($result);
675
676 run_command "git bisect log" or
677 dodie "could not capture git bisect log";
678
679 run_command "git bisect reset" or
680 dodie "could not reset git bisect";
681
682 doprint "Bad commit was [$bisect_bad]\n";
683
684 $in_bisect = 0;
685
686 success $i;
687}
688
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400689sub patchcheck {
690 my ($i) = @_;
691
692 die "PATCHCHECK_START[$i] not defined\n"
693 if (!defined($opt{"PATCHCHECK_START[$i]"}));
694 die "PATCHCHECK_TYPE[$i] not defined\n"
695 if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
696
697 my $start = $opt{"PATCHCHECK_START[$i]"};
698
699 my $end = "HEAD";
700 if (defined($opt{"PATCHCHECK_END[$i]"})) {
701 $end = $opt{"PATCHCHECK_END[$i]"};
702 }
703
704 my $type = $opt{"PATCHCHECK_TYPE[$i]"};
705
706 # Can't have a test without having a test to run
707 if ($type eq "test" && !defined($run_test)) {
708 $type = "boot";
709 }
710
711 open (IN, "git log --pretty=oneline $end|") or
712 dodie "could not get git list";
713
714 my @list;
715
716 while (<IN>) {
717 chomp;
718 $list[$#list+1] = $_;
719 last if (/^$start/);
720 }
721 close(IN);
722
723 if ($list[$#list] !~ /^$start/) {
724 dodie "SHA1 $start not found";
725 }
726
727 # go backwards in the list
728 @list = reverse @list;
729
730 my $save_clean = $noclean;
731
732 $in_patchcheck = 1;
733 foreach my $item (@list) {
734 my $sha1 = $item;
735 $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
736
737 doprint "\nProcessing commit $item\n\n";
738
739 run_command "git checkout $sha1" or
740 die "Failed to checkout $sha1";
741
742 # only clean on the first and last patch
743 if ($item eq $list[0] ||
744 $item eq $list[$#list]) {
745 $noclean = $save_clean;
746 } else {
747 $noclean = 1;
748 }
749
750 if (defined($minconfig)) {
751 build "useconfig:$minconfig";
752 } else {
753 # ?? no config to use?
754 build "oldconfig";
755 }
756
757 check_buildlog $sha1;
758
759 next if ($type eq "build");
760
761 get_grub_index;
762 get_version;
763 install;
764 monitor;
765
766 next if ($type eq "boot");
767 do_run_test;
768 }
769 $in_patchcheck = 0;
770 success $i;
771}
772
Steven Rostedt2545eb62010-11-02 15:01:32 -0400773read_config $ARGV[0];
774
775# mandatory configs
776die "MACHINE not defined\n" if (!defined($opt{"MACHINE"}));
777die "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"}));
778die "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"}));
779die "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"}));
780die "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"}));
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400781die "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"}));
Steven Rostedt2545eb62010-11-02 15:01:32 -0400782die "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"}));
783die "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"}));
784die "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"}));
785die "GRUB_MENU not defined\n" if (!defined($opt{"GRUB_MENU"}));
786
787chdir $opt{"BUILD_DIR"} || die "can't change directory to $opt{BUILD_DIR}";
788
789$target = "$opt{SSH_USER}\@$opt{MACHINE}";
790
791doprint "\n\nSTARTING AUTOMATED TESTS\n";
792
Steven Rostedt2545eb62010-11-02 15:01:32 -0400793
794$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}";
795
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400796sub set_build_option {
797 my ($name, $i) = @_;
798
799 my $option = "$name\[$i\]";
800
801 if (defined($opt{$option})) {
802 return $opt{$option};
803 }
804
805 if (defined($opt{$name})) {
806 return $opt{$name};
807 }
808
809 return undef;
810}
811
Steven Rostedt2545eb62010-11-02 15:01:32 -0400812# First we need to do is the builds
813for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
814 my $type = "BUILD_TYPE[$i]";
815
Steven Rostedt1a5cfce2010-11-02 14:57:51 -0400816 if (!defined($opt{$type})) {
817 $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"};
818 }
819
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400820 $noclean = set_build_option("BUILD_NOCLEAN", $i);
821 $minconfig = set_build_option("MIN_CONFIG", $i);
822 $run_test = set_build_option("TEST", $i);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400823
824 doprint "\n\n";
825 doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n";
826
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400827 my $checkout = $opt{"CHECKOUT[$i]"};
828 if (defined($checkout)) {
829 run_command "git checkout $checkout" or
830 die "failed to checkout $checkout";
831 }
832
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400833 if ($opt{$type} eq "bisect") {
834 bisect $i;
835 next;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400836 } elsif ($opt{$type} eq "patchcheck") {
837 patchcheck $i;
838 next;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400839 }
840
Steven Rostedt2545eb62010-11-02 15:01:32 -0400841 if ($opt{$type} ne "nobuild") {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400842 build $opt{$type};
Steven Rostedt2545eb62010-11-02 15:01:32 -0400843 }
844
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400845 get_grub_index;
846 get_version;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400847 install;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400848 monitor;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400849
850 if (defined($run_test)) {
851 do_run_test;
852 }
853
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400854 success $i;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400855}
856
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400857if ($opt{"POWEROFF_ON_SUCCESS"}) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400858 halt;
Steven Rostedt1a5cfce2010-11-02 14:57:51 -0400859} elsif ($opt{"REBOOT_ON_SUCCESS"}) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400860 reboot;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400861}
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400862
Steven Rostedt2545eb62010-11-02 15:01:32 -0400863exit 0;