blob: e0ded14b5477ff612c0e8e071aa671537d180497 [file] [log] [blame]
Steven Rostedt2545eb62010-11-02 15:01:32 -04001#!/usr/bin/perl -w
2
3use strict;
4use IPC::Open2;
5use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
6use FileHandle;
7
8$#ARGV >= 0 || die "usage: autotest.pl config-file\n";
9
10$| = 1;
11
12my %opt;
13
14#default opts
15$opt{"NUM_BUILDS"} = 5;
16$opt{"DEFAULT_BUILD_TYPE"} = "randconfig";
17$opt{"MAKE_CMD"} = "make";
18$opt{"TIMEOUT"} = 50;
19$opt{"TMP_DIR"} = "/tmp/autotest";
20$opt{"SLEEP_TIME"} = 60; # sleep time between tests
Steven Rostedt5c42fc52010-11-02 14:57:01 -040021$opt{"BUILD_NOCLEAN"} = 0;
Steven Rostedt75c3fda72010-11-02 14:57:21 -040022$opt{"REBOOT_ON_ERROR"} = 0;
Steven Rostedt5c42fc52010-11-02 14:57:01 -040023$opt{"POWEROFF_ON_ERROR"} = 0;
Steven Rostedt1a5cfce2010-11-02 14:57:51 -040024$opt{"REBOOT_ON_SUCCESS"} = 1;
Steven Rostedt5c42fc52010-11-02 14:57:01 -040025$opt{"POWEROFF_ON_SUCCESS"} = 0;
Steven Rostedt75c3fda72010-11-02 14:57:21 -040026$opt{"BUILD_OPTIONS"} = "";
Steven Rostedt5a391fb2010-11-02 14:57:43 -040027$opt{"BISECT_SLEEP_TIME"} = 10; # sleep time between bisects
Steven Rostedt2545eb62010-11-02 15:01:32 -040028
29my $version;
Steven Rostedt2545eb62010-11-02 15:01:32 -040030my $grub_number;
31my $target;
32my $make;
Steven Rostedt5c42fc52010-11-02 14:57:01 -040033my $noclean;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040034my $minconfig;
35my $in_bisect = 0;
36my $bisect_bad = "";
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -040037my $in_patchcheck = 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -040038my $run_test;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -040039my $redirect;
Steven Rostedt2545eb62010-11-02 15:01:32 -040040
41sub read_config {
42 my ($config) = @_;
43
44 open(IN, $config) || die "can't read file $config";
45
46 while (<IN>) {
47
48 # ignore blank lines and comments
49 next if (/^\s*$/ || /\s*\#/);
50
51 if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) {
52 my $lvalue = $1;
53 my $rvalue = $2;
54
55 $opt{$lvalue} = $rvalue;
56 }
57 }
58
59 close(IN);
60}
61
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040062sub logit {
Steven Rostedt2545eb62010-11-02 15:01:32 -040063 if (defined($opt{"LOG_FILE"})) {
64 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
65 print OUT @_;
66 close(OUT);
67 }
68}
69
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040070sub doprint {
71 print @_;
72 logit @_;
73}
74
Steven Rostedt5c42fc52010-11-02 14:57:01 -040075sub dodie {
Steven Rostedt5a391fb2010-11-02 14:57:43 -040076 doprint "CRITICAL FAILURE... ", @_, "\n";
Steven Rostedt5c42fc52010-11-02 14:57:01 -040077
Steven Rostedt75c3fda72010-11-02 14:57:21 -040078 if ($opt{"REBOOT_ON_ERROR"}) {
79 doprint "REBOOTING\n";
80 `$opt{"POWER_CYCLE"}`;
81
82 } elsif ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) {
Steven Rostedt5c42fc52010-11-02 14:57:01 -040083 doprint "POWERING OFF\n";
84 `$opt{"POWER_OFF"}`;
85 }
Steven Rostedt75c3fda72010-11-02 14:57:21 -040086
Steven Rostedt5c42fc52010-11-02 14:57:01 -040087 die @_;
88}
89
Steven Rostedt2545eb62010-11-02 15:01:32 -040090sub run_command {
91 my ($command) = @_;
Steven Rostedt5a391fb2010-11-02 14:57:43 -040092 my $redirect_log = "";
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -040093 my $redirect_tee = "";
Steven Rostedt2545eb62010-11-02 15:01:32 -040094
95 if (defined($opt{"LOG_FILE"})) {
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -040096 $redirect_log = "| tee -a $opt{LOG_FILE}";
97 }
98
99 if (defined($redirect)) {
100 $redirect_tee = "| tee $redirect"
Steven Rostedt2545eb62010-11-02 15:01:32 -0400101 }
102
103 doprint "$command ... ";
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400104 `$command 2>&1 $redirect_tee $redirect_log > /dev/null`;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400105
106 my $failed = $?;
107
108 if ($failed) {
109 doprint "FAILED!\n";
110 } else {
111 doprint "SUCCESS\n";
112 }
113
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400114 return !$failed;
115}
116
117sub get_grub_index {
118
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400119 return if (defined($grub_number));
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400120
121 doprint "Find grub menu ... ";
122 $grub_number = -1;
123 open(IN, "ssh $target cat /boot/grub/menu.lst |")
124 or die "unable to get menu.lst";
125 while (<IN>) {
126 if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) {
127 $grub_number++;
128 last;
129 } elsif (/^\s*title\s/) {
130 $grub_number++;
131 }
132 }
133 close(IN);
134
135 die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}"
136 if ($grub_number < 0);
137 doprint "$grub_number\n";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400138}
139
140my $timeout = $opt{"TIMEOUT"};
141
142sub wait_for_input
143{
144 my ($fp, $time) = @_;
145 my $rin;
146 my $ready;
147 my $line;
148 my $ch;
149
150 if (!defined($time)) {
151 $time = $timeout;
152 }
153
154 $rin = '';
155 vec($rin, fileno($fp), 1) = 1;
156 $ready = select($rin, undef, undef, $time);
157
158 $line = "";
159
160 # try to read one char at a time
161 while (sysread $fp, $ch, 1) {
162 $line .= $ch;
163 last if ($ch eq "\n");
164 }
165
166 if (!length($line)) {
167 return undef;
168 }
169
170 return $line;
171}
172
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400173sub reboot_to {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400174 run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
175}
176
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400177sub open_console {
178 my ($fp) = @_;
179
Steven Rostedt2545eb62010-11-02 15:01:32 -0400180 my $flags;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400181
182 my $pid = open($fp, "$opt{CONSOLE}|") or
183 dodie "Can't open console $opt{CONSOLE}";
184
185 $flags = fcntl($fp, F_GETFL, 0) or
186 dodie "Can't get flags for the socket: $!\n";
187 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
188 dodie "Can't set flags for the socket: $!\n";
189
190 return $pid;
191}
192
193sub close_console {
194 my ($fp, $pid) = @_;
195
196 doprint "kill child process $pid\n";
197 kill 2, $pid;
198
199 print "closing!\n";
200 close($fp);
201}
202
203sub monitor {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400204 my $booted = 0;
205 my $bug = 0;
206 my $pid;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400207 my $skip_call_trace = 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400208 my $fp = \*IN;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400209
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400210 $pid = open_console($fp);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400211
212 my $line;
213 my $full_line = "";
214
215 doprint "Wait for monitor to settle down.\n";
216 # read the monitor and wait for the system to calm down
217 do {
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400218 $line = wait_for_input($fp, 5);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400219 } while (defined($line));
220
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400221 reboot_to;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400222
223 for (;;) {
224
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400225 $line = wait_for_input($fp);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400226
227 last if (!defined($line));
228
229 doprint $line;
230
231 # we are not guaranteed to get a full line
232 $full_line .= $line;
233
234 if ($full_line =~ /login:/) {
235 $booted = 1;
236 }
237
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400238 if ($full_line =~ /\[ backtrace testing \]/) {
239 $skip_call_trace = 1;
240 }
241
Steven Rostedt2545eb62010-11-02 15:01:32 -0400242 if ($full_line =~ /call trace:/i) {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400243 $bug = 1 if (!$skip_call_trace);
244 }
245
246 if ($full_line =~ /\[ end of backtrace testing \]/) {
247 $skip_call_trace = 0;
248 }
249
250 if ($full_line =~ /Kernel panic -/) {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400251 $bug = 1;
252 }
253
254 if ($line =~ /\n/) {
255 $full_line = "";
256 }
257 }
258
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400259 close_console($fp, $pid);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400260
261 if (!$booted) {
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400262 return 1 if ($in_bisect);
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400263 dodie "failed - never got a boot prompt.\n";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400264 }
265
266 if ($bug) {
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400267 return 1 if ($in_bisect);
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400268 dodie "failed - got a bug report\n";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400269 }
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400270
271 return 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400272}
273
274sub install {
275
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400276 run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400277 dodie "failed to copy image";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400278
279 my $install_mods = 0;
280
281 # should we process modules?
282 $install_mods = 0;
283 open(IN, "$opt{OUTPUT_DIR}/.config") or dodie("Can't read config file");
284 while (<IN>) {
285 if (/CONFIG_MODULES(=y)?/) {
286 $install_mods = 1 if (defined($1));
287 last;
288 }
289 }
290 close(IN);
291
292 if (!$install_mods) {
293 doprint "No modules needed\n";
294 return;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400295 }
296
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400297 run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install" or
298 dodie "Failed to install modules";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400299
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400300 my $modlib = "/lib/modules/$version";
301 my $modtar = "autotest-mods.tar.bz2";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400302
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400303 run_command "ssh $target rm -rf $modlib" or
304 dodie "failed to remove old mods: $modlib";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400305
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400306 # would be nice if scp -r did not follow symbolic links
307 run_command "cd $opt{TMP_DIR} && tar -cjf $modtar lib/modules/$version" or
308 dodie "making tarball";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400309
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400310 run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp" or
311 dodie "failed to copy modules";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400312
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400313 unlink "$opt{TMP_DIR}/$modtar";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400314
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400315 run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or
316 dodie "failed to tar modules";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400317
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400318 run_command "ssh $target rm -f /tmp/$modtar";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400319}
320
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400321sub check_buildlog {
322 my ($patch) = @_;
323
324 my $buildlog = "$opt{TMP_DIR}/buildlog";
325 my @files = `git show $patch | diffstat -l`;
326
327 open(IN, "git show $patch |") or
328 dodie "failed to show $patch";
329 while (<IN>) {
330 if (m,^--- a/(.*),) {
331 chomp $1;
332 $files[$#files] = $1;
333 }
334 }
335 close(IN);
336
337 open(IN, $buildlog) or dodie "Can't open $buildlog";
338 while (<IN>) {
339 if (/^\s*(.*?):.*(warning|error)/) {
340 my $err = $1;
341 foreach my $file (@files) {
342 my $fullpath = "$opt{BUILD_DIR}/$file";
343 if ($file eq $err || $fullpath eq $err) {
344 dodie "$file built with warnings";
345 }
346 }
347 }
348 }
349 close(IN);
350}
351
Steven Rostedt2545eb62010-11-02 15:01:32 -0400352sub build {
353 my ($type) = @_;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400354 my $defconfig = "";
355 my $append = "";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400356
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400357 if ($type =~ /^useconfig:(.*)/) {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400358 run_command "cp $1 $opt{OUTPUT_DIR}/.config" or
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400359 dodie "could not copy $1 to .config";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400360
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400361 $type = "oldconfig";
362 }
363
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400364 # old config can ask questions
365 if ($type eq "oldconfig") {
366 $append = "yes ''|";
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400367
368 # allow for empty configs
369 run_command "touch $opt{OUTPUT_DIR}/.config";
370
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400371 run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400372 dodie "moving .config";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400373
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400374 if (!$noclean && !run_command "$make mrproper") {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400375 dodie "make mrproper";
376 }
377
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400378 run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400379 dodie "moving config_temp";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400380
381 } elsif (!$noclean) {
382 unlink "$opt{OUTPUT_DIR}/.config";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400383 run_command "$make mrproper" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400384 dodie "make mrproper";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400385 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400386
387 # add something to distinguish this build
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400388 open(OUT, "> $opt{OUTPUT_DIR}/localversion") or dodie("Can't make localversion file");
Steven Rostedt2545eb62010-11-02 15:01:32 -0400389 print OUT "$opt{LOCALVERSION}\n";
390 close(OUT);
391
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400392 if (defined($minconfig)) {
393 $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400394 }
395
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400396 run_command "$defconfig $append $make $type" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400397 dodie "failed make config";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400398
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400399 # patch check will examine the log
400 if ($in_patchcheck) {
401 $redirect = "$opt{TMP_DIR}/buildlog";
402 }
403
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400404 if (!run_command "$make $opt{BUILD_OPTIONS}") {
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400405 undef $redirect;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400406 # bisect may need this to pass
407 return 1 if ($in_bisect);
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400408 dodie "failed build";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400409 }
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400410 undef $redirect;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400411
412 return 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400413}
414
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400415sub reboot {
416 # try to reboot normally
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400417 if (!run_command "ssh $target reboot") {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400418 # nope? power cycle it.
419 run_command "$opt{POWER_CYCLE}";
420 }
421}
422
423sub halt {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400424 if (!run_command "ssh $target halt" or defined($opt{"POWER_OFF"})) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400425 # nope? the zap it!
426 run_command "$opt{POWER_OFF}";
427 }
428}
429
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400430sub success {
431 my ($i) = @_;
432
433 doprint "\n\n*******************************************\n";
434 doprint "*******************************************\n";
435 doprint "** SUCCESS!!!! **\n";
436 doprint "*******************************************\n";
437 doprint "*******************************************\n";
438
439 if ($i != $opt{"NUM_BUILDS"}) {
440 reboot;
441 doprint "Sleeping $opt{SLEEP_TIME} seconds\n";
442 sleep "$opt{SLEEP_TIME}";
443 }
444}
445
446sub get_version {
447 # get the release name
448 doprint "$make kernelrelease ... ";
449 $version = `$make kernelrelease | tail -1`;
450 chomp($version);
451 doprint "$version\n";
452}
453
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400454sub child_run_test {
455 my $failed;
456
457 $failed = !run_command $run_test;
458 exit $failed;
459}
460
461my $child_done;
462
463sub child_finished {
464 $child_done = 1;
465}
466
467sub do_run_test {
468 my $child_pid;
469 my $child_exit;
470 my $pid;
471 my $line;
472 my $full_line;
473 my $bug = 0;
474 my $fp = \*IN;
475
476 $pid = open_console($fp);
477
478 # read the monitor and wait for the system to calm down
479 do {
480 $line = wait_for_input($fp, 1);
481 } while (defined($line));
482
483 $child_done = 0;
484
485 $SIG{CHLD} = qw(child_finished);
486
487 $child_pid = fork;
488
489 child_run_test if (!$child_pid);
490
491 $full_line = "";
492
493 do {
494 $line = wait_for_input($fp, 1);
495 if (defined($line)) {
496
497 # we are not guaranteed to get a full line
498 $full_line .= $line;
499
500 if ($full_line =~ /call trace:/i) {
501 $bug = 1;
502 }
503
504 if ($full_line =~ /Kernel panic -/) {
505 $bug = 1;
506 }
507
508 if ($line =~ /\n/) {
509 $full_line = "";
510 }
511 }
512 } while (!$child_done && !$bug);
513
514 if ($bug) {
515 doprint "Detected kernel crash!\n";
516 # kill the child with extreme prejudice
517 kill 9, $child_pid;
518 }
519
520 waitpid $child_pid, 0;
521 $child_exit = $?;
522
523 close_console($fp, $pid);
524
525 if ($bug || $child_exit) {
526 return 1 if $in_bisect;
527 dodie "test failed";
528 }
529 return 0;
530}
531
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400532sub run_bisect {
533 my ($type) = @_;
534
535 my $failed;
536 my $result;
537 my $output;
538 my $ret;
539
540
541 if (defined($minconfig)) {
542 $failed = build "useconfig:$minconfig";
543 } else {
544 # ?? no config to use?
545 $failed = build "oldconfig";
546 }
547
548 if ($type ne "build") {
549 dodie "Failed on build" if $failed;
550
551 # Now boot the box
552 get_grub_index;
553 get_version;
554 install;
555 $failed = monitor;
556
557 if ($type ne "boot") {
558 dodie "Failed on boot" if $failed;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400559
560 $failed = do_run_test;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400561 }
562 }
563
564 if ($failed) {
565 $result = "bad";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400566
567 # reboot the box to a good kernel
568 if ($type eq "boot") {
569 reboot;
570 doprint "sleep a little for reboot\n";
571 sleep $opt{"BISECT_SLEEP_TIME"};
572 }
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400573 } else {
574 $result = "good";
575 }
576
577 doprint "git bisect $result ... ";
578 $output = `git bisect $result 2>&1`;
579 $ret = $?;
580
581 logit $output;
582
583 if ($ret) {
584 doprint "FAILED\n";
585 dodie "Failed to git bisect";
586 }
587
588 doprint "SUCCESS\n";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400589 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400590 doprint "$1 [$2]\n";
591 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
592 $bisect_bad = $1;
593 doprint "Found bad commit... $1\n";
594 return 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400595 } else {
596 # we already logged it, just print it now.
597 print $output;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400598 }
599
600
601 return 1;
602}
603
604sub bisect {
605 my ($i) = @_;
606
607 my $result;
608
609 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
610 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
611 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
612
613 my $good = $opt{"BISECT_GOOD[$i]"};
614 my $bad = $opt{"BISECT_BAD[$i]"};
615 my $type = $opt{"BISECT_TYPE[$i]"};
616
617 $in_bisect = 1;
618
619 run_command "git bisect start" or
620 dodie "could not start bisect";
621
622 run_command "git bisect good $good" or
623 dodie "could not set bisect good to $good";
624
625 run_command "git bisect bad $bad" or
626 dodie "could not set bisect good to $bad";
627
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400628 # Can't have a test without having a test to run
629 if ($type eq "test" && !defined($run_test)) {
630 $type = "boot";
631 }
632
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400633 do {
634 $result = run_bisect $type;
635 } while ($result);
636
637 run_command "git bisect log" or
638 dodie "could not capture git bisect log";
639
640 run_command "git bisect reset" or
641 dodie "could not reset git bisect";
642
643 doprint "Bad commit was [$bisect_bad]\n";
644
645 $in_bisect = 0;
646
647 success $i;
648}
649
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400650sub patchcheck {
651 my ($i) = @_;
652
653 die "PATCHCHECK_START[$i] not defined\n"
654 if (!defined($opt{"PATCHCHECK_START[$i]"}));
655 die "PATCHCHECK_TYPE[$i] not defined\n"
656 if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
657
658 my $start = $opt{"PATCHCHECK_START[$i]"};
659
660 my $end = "HEAD";
661 if (defined($opt{"PATCHCHECK_END[$i]"})) {
662 $end = $opt{"PATCHCHECK_END[$i]"};
663 }
664
665 my $type = $opt{"PATCHCHECK_TYPE[$i]"};
666
667 # Can't have a test without having a test to run
668 if ($type eq "test" && !defined($run_test)) {
669 $type = "boot";
670 }
671
672 open (IN, "git log --pretty=oneline $end|") or
673 dodie "could not get git list";
674
675 my @list;
676
677 while (<IN>) {
678 chomp;
679 $list[$#list+1] = $_;
680 last if (/^$start/);
681 }
682 close(IN);
683
684 if ($list[$#list] !~ /^$start/) {
685 dodie "SHA1 $start not found";
686 }
687
688 # go backwards in the list
689 @list = reverse @list;
690
691 my $save_clean = $noclean;
692
693 $in_patchcheck = 1;
694 foreach my $item (@list) {
695 my $sha1 = $item;
696 $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
697
698 doprint "\nProcessing commit $item\n\n";
699
700 run_command "git checkout $sha1" or
701 die "Failed to checkout $sha1";
702
703 # only clean on the first and last patch
704 if ($item eq $list[0] ||
705 $item eq $list[$#list]) {
706 $noclean = $save_clean;
707 } else {
708 $noclean = 1;
709 }
710
711 if (defined($minconfig)) {
712 build "useconfig:$minconfig";
713 } else {
714 # ?? no config to use?
715 build "oldconfig";
716 }
717
718 check_buildlog $sha1;
719
720 next if ($type eq "build");
721
722 get_grub_index;
723 get_version;
724 install;
725 monitor;
726
727 next if ($type eq "boot");
728 do_run_test;
729 }
730 $in_patchcheck = 0;
731 success $i;
732}
733
Steven Rostedt2545eb62010-11-02 15:01:32 -0400734read_config $ARGV[0];
735
736# mandatory configs
737die "MACHINE not defined\n" if (!defined($opt{"MACHINE"}));
738die "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"}));
739die "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"}));
740die "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"}));
741die "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"}));
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400742die "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"}));
Steven Rostedt2545eb62010-11-02 15:01:32 -0400743die "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"}));
744die "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"}));
745die "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"}));
746die "GRUB_MENU not defined\n" if (!defined($opt{"GRUB_MENU"}));
747
748chdir $opt{"BUILD_DIR"} || die "can't change directory to $opt{BUILD_DIR}";
749
750$target = "$opt{SSH_USER}\@$opt{MACHINE}";
751
752doprint "\n\nSTARTING AUTOMATED TESTS\n";
753
Steven Rostedt2545eb62010-11-02 15:01:32 -0400754
755$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}";
756
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400757sub set_build_option {
758 my ($name, $i) = @_;
759
760 my $option = "$name\[$i\]";
761
762 if (defined($opt{$option})) {
763 return $opt{$option};
764 }
765
766 if (defined($opt{$name})) {
767 return $opt{$name};
768 }
769
770 return undef;
771}
772
Steven Rostedt2545eb62010-11-02 15:01:32 -0400773# First we need to do is the builds
774for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
775 my $type = "BUILD_TYPE[$i]";
776
Steven Rostedt1a5cfce2010-11-02 14:57:51 -0400777 if (!defined($opt{$type})) {
778 $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"};
779 }
780
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400781 $noclean = set_build_option("BUILD_NOCLEAN", $i);
782 $minconfig = set_build_option("MIN_CONFIG", $i);
783 $run_test = set_build_option("TEST", $i);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400784
785 doprint "\n\n";
786 doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n";
787
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400788 my $checkout = $opt{"CHECKOUT[$i]"};
789 if (defined($checkout)) {
790 run_command "git checkout $checkout" or
791 die "failed to checkout $checkout";
792 }
793
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400794 if ($opt{$type} eq "bisect") {
795 bisect $i;
796 next;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400797 } elsif ($opt{$type} eq "patchcheck") {
798 patchcheck $i;
799 next;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400800 }
801
Steven Rostedt2545eb62010-11-02 15:01:32 -0400802 if ($opt{$type} ne "nobuild") {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400803 build $opt{$type};
Steven Rostedt2545eb62010-11-02 15:01:32 -0400804 }
805
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400806 get_grub_index;
807 get_version;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400808 install;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400809 monitor;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400810
811 if (defined($run_test)) {
812 do_run_test;
813 }
814
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400815 success $i;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400816}
817
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400818if ($opt{"POWEROFF_ON_SUCCESS"}) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400819 halt;
Steven Rostedt1a5cfce2010-11-02 14:57:51 -0400820} elsif ($opt{"REBOOT_ON_SUCCESS"}) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400821 reboot;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400822}
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400823
Steven Rostedt2545eb62010-11-02 15:01:32 -0400824exit 0;