blob: ff6283a44847a0a8c4580e7effce6031ca20b8a8 [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);
Steven Rostedt7faafbd2010-11-02 14:58:22 -040010use File::Path qw(mkpath);
11use File::Copy qw(cp);
Steven Rostedt2545eb62010-11-02 15:01:32 -040012use FileHandle;
13
14$#ARGV >= 0 || die "usage: autotest.pl config-file\n";
15
16$| = 1;
17
18my %opt;
19
20#default opts
21$opt{"NUM_BUILDS"} = 5;
Steven Rostedt7faafbd2010-11-02 14:58:22 -040022$opt{"BUILD_TYPE"} = "randconfig";
Steven Rostedt2545eb62010-11-02 15:01:32 -040023$opt{"MAKE_CMD"} = "make";
Steven Rostedt2b7d9b22010-11-02 14:58:15 -040024$opt{"TIMEOUT"} = 120;
Steven Rostedt2545eb62010-11-02 15:01:32 -040025$opt{"TMP_DIR"} = "/tmp/autotest";
26$opt{"SLEEP_TIME"} = 60; # sleep time between tests
Steven Rostedt5c42fc52010-11-02 14:57:01 -040027$opt{"BUILD_NOCLEAN"} = 0;
Steven Rostedt75c3fda72010-11-02 14:57:21 -040028$opt{"REBOOT_ON_ERROR"} = 0;
Steven Rostedt5c42fc52010-11-02 14:57:01 -040029$opt{"POWEROFF_ON_ERROR"} = 0;
Steven Rostedt1a5cfce2010-11-02 14:57:51 -040030$opt{"REBOOT_ON_SUCCESS"} = 1;
Steven Rostedt5c42fc52010-11-02 14:57:01 -040031$opt{"POWEROFF_ON_SUCCESS"} = 0;
Steven Rostedt75c3fda72010-11-02 14:57:21 -040032$opt{"BUILD_OPTIONS"} = "";
Steven Rostedt5a391fb2010-11-02 14:57:43 -040033$opt{"BISECT_SLEEP_TIME"} = 10; # sleep time between bisects
Steven Rostedt2b7d9b22010-11-02 14:58:15 -040034$opt{"CLEAR_LOG"} = 0;
35$opt{"SUCCESS_LINE"} = "login:";
36$opt{"BOOTED_TIMEOUT"} = 1;
37$opt{"DIE_ON_FAILURE"} = 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -040038
39my $version;
Steven Rostedt7faafbd2010-11-02 14:58:22 -040040my $build_type;
Steven Rostedt2545eb62010-11-02 15:01:32 -040041my $grub_number;
42my $target;
43my $make;
Steven Rostedt5c42fc52010-11-02 14:57:01 -040044my $noclean;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040045my $minconfig;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -040046my $addconfig;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040047my $in_bisect = 0;
48my $bisect_bad = "";
Steven Rostedtd6ce2a02010-11-02 14:58:05 -040049my $reverse_bisect;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -040050my $in_patchcheck = 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -040051my $run_test;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -040052my $redirect;
Steven Rostedt7faafbd2010-11-02 14:58:22 -040053my $buildlog;
54my $dmesg;
55my $monitor_fp;
56my $monitor_pid;
57my $monitor_cnt = 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -040058
59sub 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
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040080sub logit {
Steven Rostedt2545eb62010-11-02 15:01:32 -040081 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
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040088sub doprint {
89 print @_;
90 logit @_;
91}
92
Steven Rostedt7faafbd2010-11-02 14:58:22 -040093sub run_command;
94
95sub 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
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400103sub dodie {
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400104 doprint "CRITICAL FAILURE... ", @_, "\n";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400105
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400106 if ($opt{"REBOOT_ON_ERROR"}) {
107 doprint "REBOOTING\n";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400108 reboot;
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400109
110 } elsif ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400111 doprint "POWERING OFF\n";
112 `$opt{"POWER_OFF"}`;
113 }
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400114
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400115 die @_;
116}
117
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400118sub 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
134sub 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
144sub start_monitor {
145 if ($monitor_cnt++) {
146 return;
147 }
148 $monitor_fp = \*MONFD;
149 $monitor_pid = open_console $monitor_fp;
150}
151
152sub end_monitor {
153 if (--$monitor_cnt) {
154 return;
155 }
156 close_console($monitor_fp, $monitor_pid);
157}
158
159sub 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
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400171sub fail {
172
173 if ($opt{"DIE_ON_FAILURE"}) {
174 dodie @_;
175 }
176
177 doprint "Failed: ", @_, "\n";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400178
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
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400213 return 1;
214}
215
Steven Rostedt2545eb62010-11-02 15:01:32 -0400216sub run_command {
217 my ($command) = @_;
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400218 my $dolog = 0;
219 my $dord = 0;
220 my $pid;
221
222 doprint("$command ... ");
223
224 $pid = open(CMD, "$command 2>&1 |") or
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400225 (fail "unable to exec $command" and return 0);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400226
227 if (defined($opt{"LOG_FILE"})) {
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400228 open(LOG, ">>$opt{LOG_FILE}") or
229 dodie "failed to write to log";
230 $dolog = 1;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400231 }
232
233 if (defined($redirect)) {
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400234 open (RD, ">$redirect") or
235 dodie "failed to write to redirect $redirect";
236 $dord = 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400237 }
238
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400239 while (<CMD>) {
240 print LOG if ($dolog);
241 print RD if ($dord);
242 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400243
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400244 waitpid($pid, 0);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400245 my $failed = $?;
246
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400247 close(CMD);
248 close(LOG) if ($dolog);
249 close(RD) if ($dord);
250
Steven Rostedt2545eb62010-11-02 15:01:32 -0400251 if ($failed) {
252 doprint "FAILED!\n";
253 } else {
254 doprint "SUCCESS\n";
255 }
256
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400257 return !$failed;
258}
259
260sub get_grub_index {
261
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400262 return if (defined($grub_number));
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400263
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";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400281}
282
283my $timeout = $opt{"TIMEOUT"};
284
285sub 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
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400316sub reboot_to {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400317 run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
318}
319
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400320sub monitor {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400321 my $booted = 0;
322 my $bug = 0;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400323 my $skip_call_trace = 0;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400324 my $loops;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400325
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400326 wait_for_monitor 5;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400327
328 my $line;
329 my $full_line = "";
330
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400331 open(DMESG, "> $dmesg") or
332 die "unable to write to $dmesg";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400333
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400334 reboot_to;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400335
336 for (;;) {
337
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400338 if ($booted) {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400339 $line = wait_for_input($monitor_fp, $opt{"BOOTED_TIMEOUT"});
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400340 } else {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400341 $line = wait_for_input($monitor_fp);
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400342 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400343
344 last if (!defined($line));
345
346 doprint $line;
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400347 print DMESG $line;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400348
349 # we are not guaranteed to get a full line
350 $full_line .= $line;
351
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400352 if ($full_line =~ /$opt{"SUCCESS_LINE"}/) {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400353 $booted = 1;
354 }
355
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400356 if ($full_line =~ /\[ backtrace testing \]/) {
357 $skip_call_trace = 1;
358 }
359
Steven Rostedt2545eb62010-11-02 15:01:32 -0400360 if ($full_line =~ /call trace:/i) {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400361 $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 -/) {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400369 $bug = 1;
370 }
371
372 if ($line =~ /\n/) {
373 $full_line = "";
374 }
375 }
376
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400377 close(DMESG);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400378
379 if (!$booted) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400380 return 0 if ($in_bisect);
381 fail "failed - never got a boot prompt.\n" and return 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400382 }
383
384 if ($bug) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400385 return 0 if ($in_bisect);
386 fail "failed - got a bug report\n" and return 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400387 }
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400388
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400389 return 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400390}
391
392sub install {
393
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400394 run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400395 dodie "failed to copy image";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400396
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;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400413 }
414
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400415 run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install" or
416 dodie "Failed to install modules";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400417
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400418 my $modlib = "/lib/modules/$version";
419 my $modtar = "autotest-mods.tar.bz2";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400420
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400421 run_command "ssh $target rm -rf $modlib" or
422 dodie "failed to remove old mods: $modlib";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400423
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400424 # 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";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400427
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400428 run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp" or
429 dodie "failed to copy modules";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400430
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400431 unlink "$opt{TMP_DIR}/$modtar";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400432
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400433 run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or
434 dodie "failed to tar modules";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400435
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400436 run_command "ssh $target rm -f /tmp/$modtar";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400437}
438
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400439sub check_buildlog {
440 my ($patch) = @_;
441
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400442 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) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400461 fail "$file built with warnings" and return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400462 }
463 }
464 }
465 }
466 close(IN);
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400467
468 return 1;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400469}
470
Steven Rostedt2545eb62010-11-02 15:01:32 -0400471sub build {
472 my ($type) = @_;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400473 my $defconfig = "";
474 my $append = "";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400475
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400476 unlink $buildlog;
477
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400478 if ($type =~ /^useconfig:(.*)/) {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400479 run_command "cp $1 $opt{OUTPUT_DIR}/.config" or
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400480 dodie "could not copy $1 to .config";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400481
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400482 $type = "oldconfig";
483 }
484
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400485 # old config can ask questions
486 if ($type eq "oldconfig") {
487 $append = "yes ''|";
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400488
489 # allow for empty configs
490 run_command "touch $opt{OUTPUT_DIR}/.config";
491
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400492 run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400493 dodie "moving .config";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400494
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400495 if (!$noclean && !run_command "$make mrproper") {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400496 dodie "make mrproper";
497 }
498
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400499 run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400500 dodie "moving config_temp";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400501
502 } elsif (!$noclean) {
503 unlink "$opt{OUTPUT_DIR}/.config";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400504 run_command "$make mrproper" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400505 dodie "make mrproper";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400506 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400507
508 # add something to distinguish this build
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400509 open(OUT, "> $opt{OUTPUT_DIR}/localversion") or dodie("Can't make localversion file");
Steven Rostedt2545eb62010-11-02 15:01:32 -0400510 print OUT "$opt{LOCALVERSION}\n";
511 close(OUT);
512
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400513 if (defined($minconfig)) {
514 $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400515 }
516
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400517 run_command "$defconfig $append $make $type" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400518 dodie "failed make config";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400519
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400520 $redirect = "$opt{TMP_DIR}/buildlog";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400521 if (!run_command "$make $opt{BUILD_OPTIONS}") {
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400522 undef $redirect;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400523 # bisect may need this to pass
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400524 return 0 if ($in_bisect);
525 fail "failed build" and return 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400526 }
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400527 undef $redirect;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400528
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400529 return 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400530}
531
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400532sub halt {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400533 if (!run_command "ssh $target halt" or defined($opt{"POWER_OFF"})) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400534 # nope? the zap it!
535 run_command "$opt{POWER_OFF}";
536 }
537}
538
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400539sub 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"}) {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400549 doprint "Reboot and wait $opt{SLEEP_TIME} seconds\n";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400550 reboot;
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400551 start_monitor;
552 wait_for_monitor $opt{"SLEEP_TIME"};
553 end_monitor;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400554 }
555}
556
557sub 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
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400565sub child_run_test {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400566 my $failed = 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400567
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400568 # 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;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400574 exit $failed;
575}
576
577my $child_done;
578
579sub child_finished {
580 $child_done = 1;
581}
582
583sub do_run_test {
584 my $child_pid;
585 my $child_exit;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400586 my $line;
587 my $full_line;
588 my $bug = 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400589
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400590 wait_for_monitor 1;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400591
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400592 doprint "run test $run_test\n";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400593
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 {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400605 $line = wait_for_input($monitor_fp, 1);
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400606 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
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400634 if ($bug || $child_exit) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400635 return 0 if $in_bisect;
636 fail "test failed" and return 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400637 }
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400638 return 1;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400639}
640
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400641sub run_bisect {
642 my ($type) = @_;
643
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400644 my $failed = 0;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400645 my $result;
646 my $output;
647 my $ret;
648
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400649 if (defined($minconfig)) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400650 build "useconfig:$minconfig" or $failed = 1;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400651 } else {
652 # ?? no config to use?
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400653 build "oldconfig" or $failed = 1;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400654 }
655
656 if ($type ne "build") {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400657 dodie "Failed on build" if $failed;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400658
659 # Now boot the box
660 get_grub_index;
661 get_version;
662 install;
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400663
664 start_monitor;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400665 monitor or $failed = 1;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400666
667 if ($type ne "boot") {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400668 dodie "Failed on boot" if $failed;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400669
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400670 do_run_test or $failed = 1;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400671 }
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400672 end_monitor;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400673 }
674
675 if ($failed) {
676 $result = "bad";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400677
678 # reboot the box to a good kernel
679 if ($type eq "boot") {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400680 doprint "Reboot and sleep $opt{BISECT_SLEEP_TIME} seconds\n";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400681 reboot;
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400682 start_monitor;
683 wait_for_monitor $opt{"BISECT_SLEEP_TIME"};
684 end_monitor;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400685 }
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400686 } else {
687 $result = "good";
688 }
689
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400690 # 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
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400699 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";
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400707 fail "Failed to git bisect";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400708 }
709
710 doprint "SUCCESS\n";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400711 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400712 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;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400717 } else {
718 # we already logged it, just print it now.
719 print $output;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400720 }
721
722
723 return 1;
724}
725
726sub 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
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400739 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
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400747 $in_bisect = 1;
748
749 run_command "git bisect start" or
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400750 fail "could not start bisect";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400751
752 run_command "git bisect good $good" or
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400753 fail "could not set bisect good to $good";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400754
755 run_command "git bisect bad $bad" or
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400756 fail "could not set bisect good to $bad";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400757
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400758 # Can't have a test without having a test to run
759 if ($type eq "test" && !defined($run_test)) {
760 $type = "boot";
761 }
762
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400763 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
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400780sub 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/) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400815 fail "SHA1 $start not found";
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400816 }
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)) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400842 build "useconfig:$minconfig" or return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400843 } else {
844 # ?? no config to use?
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400845 build "oldconfig" or return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400846 }
847
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400848 check_buildlog $sha1 or return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400849
850 next if ($type eq "build");
851
852 get_grub_index;
853 get_version;
854 install;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400855
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400856 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
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400867 }
868 $in_patchcheck = 0;
869 success $i;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400870
871 return 1;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400872}
873
Steven Rostedt2545eb62010-11-02 15:01:32 -0400874read_config $ARGV[0];
875
876# mandatory configs
877die "MACHINE not defined\n" if (!defined($opt{"MACHINE"}));
878die "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"}));
879die "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"}));
880die "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"}));
881die "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"}));
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400882die "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"}));
Steven Rostedt2545eb62010-11-02 15:01:32 -0400883die "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"}));
884die "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"}));
885die "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"}));
886die "GRUB_MENU not defined\n" if (!defined($opt{"GRUB_MENU"}));
887
888chdir $opt{"BUILD_DIR"} || die "can't change directory to $opt{BUILD_DIR}";
889
890$target = "$opt{SSH_USER}\@$opt{MACHINE}";
891
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400892if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
893 unlink $opt{"LOG_FILE"};
894}
Steven Rostedt2545eb62010-11-02 15:01:32 -0400895
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400896doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
897
898foreach my $option (sort keys %opt) {
899 doprint "$option = $opt{$option}\n";
900}
Steven Rostedt2545eb62010-11-02 15:01:32 -0400901
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400902$buildlog = "$opt{TMP_DIR}/buildlog";
903$dmesg = "$opt{TMP_DIR}/dmesg";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400904$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}";
905
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400906sub 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
Steven Rostedt2545eb62010-11-02 15:01:32 -0400922# First we need to do is the builds
923for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400924
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400925 $build_type = set_build_option("BUILD_TYPE", $i);
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400926 $noclean = set_build_option("BUILD_NOCLEAN", $i);
927 $minconfig = set_build_option("MIN_CONFIG", $i);
928 $run_test = set_build_option("TEST", $i);
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400929 $addconfig = set_build_option("ADD_CONFIG", $i);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400930
931 doprint "\n\n";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400932 doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $build_type\n\n";
933
934 unlink $dmesg;
935 unlink $buildlog;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400936
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400937 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
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400946 my $checkout = $opt{"CHECKOUT[$i]"};
947 if (defined($checkout)) {
948 run_command "git checkout $checkout" or
949 die "failed to checkout $checkout";
950 }
951
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400952 if ($build_type eq "bisect") {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400953 bisect $i;
954 next;
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400955 } elsif ($build_type eq "patchcheck") {
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400956 patchcheck $i;
957 next;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400958 }
959
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400960 if ($build_type ne "nobuild") {
961 build $build_type or next;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400962 }
963
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400964 get_grub_index;
965 get_version;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400966 install;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400967
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400968 my $failed = 0;
969 start_monitor;
970 monitor or $failed = 1;;
971 if (!$failed && defined($run_test)) {
972 do_run_test or $failed = 1;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400973 }
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400974 end_monitor;
975 next if ($failed);
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400976
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400977 success $i;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400978}
979
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400980if ($opt{"POWEROFF_ON_SUCCESS"}) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400981 halt;
Steven Rostedt1a5cfce2010-11-02 14:57:51 -0400982} elsif ($opt{"REBOOT_ON_SUCCESS"}) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400983 reboot;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400984}
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400985
Steven Rostedt2545eb62010-11-02 15:01:32 -0400986exit 0;