blob: 0a0b1b16fccd3718e40dc3444ffca5f0737a15fb [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";
Steven Rostedt2b7d9b22010-11-02 14:58:15 -040022$opt{"TIMEOUT"} = 120;
Steven Rostedt2545eb62010-11-02 15:01:32 -040023$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 Rostedt2b7d9b22010-11-02 14:58:15 -040032$opt{"CLEAR_LOG"} = 0;
33$opt{"SUCCESS_LINE"} = "login:";
34$opt{"BOOTED_TIMEOUT"} = 1;
35$opt{"DIE_ON_FAILURE"} = 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -040036
37my $version;
Steven Rostedt2545eb62010-11-02 15:01:32 -040038my $grub_number;
39my $target;
40my $make;
Steven Rostedt5c42fc52010-11-02 14:57:01 -040041my $noclean;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040042my $minconfig;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -040043my $addconfig;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040044my $in_bisect = 0;
45my $bisect_bad = "";
Steven Rostedtd6ce2a02010-11-02 14:58:05 -040046my $reverse_bisect;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -040047my $in_patchcheck = 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -040048my $run_test;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -040049my $redirect;
Steven Rostedt2545eb62010-11-02 15:01:32 -040050
51sub read_config {
52 my ($config) = @_;
53
54 open(IN, $config) || die "can't read file $config";
55
56 while (<IN>) {
57
58 # ignore blank lines and comments
59 next if (/^\s*$/ || /\s*\#/);
60
61 if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) {
62 my $lvalue = $1;
63 my $rvalue = $2;
64
65 $opt{$lvalue} = $rvalue;
66 }
67 }
68
69 close(IN);
70}
71
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040072sub logit {
Steven Rostedt2545eb62010-11-02 15:01:32 -040073 if (defined($opt{"LOG_FILE"})) {
74 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
75 print OUT @_;
76 close(OUT);
77 }
78}
79
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040080sub doprint {
81 print @_;
82 logit @_;
83}
84
Steven Rostedt5c42fc52010-11-02 14:57:01 -040085sub dodie {
Steven Rostedt5a391fb2010-11-02 14:57:43 -040086 doprint "CRITICAL FAILURE... ", @_, "\n";
Steven Rostedt5c42fc52010-11-02 14:57:01 -040087
Steven Rostedt75c3fda72010-11-02 14:57:21 -040088 if ($opt{"REBOOT_ON_ERROR"}) {
89 doprint "REBOOTING\n";
90 `$opt{"POWER_CYCLE"}`;
91
92 } elsif ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) {
Steven Rostedt5c42fc52010-11-02 14:57:01 -040093 doprint "POWERING OFF\n";
94 `$opt{"POWER_OFF"}`;
95 }
Steven Rostedt75c3fda72010-11-02 14:57:21 -040096
Steven Rostedt5c42fc52010-11-02 14:57:01 -040097 die @_;
98}
99
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400100sub fail {
101
102 if ($opt{"DIE_ON_FAILURE"}) {
103 dodie @_;
104 }
105
106 doprint "Failed: ", @_, "\n";
107 return 1;
108}
109
Steven Rostedt2545eb62010-11-02 15:01:32 -0400110sub run_command {
111 my ($command) = @_;
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400112 my $dolog = 0;
113 my $dord = 0;
114 my $pid;
115
116 doprint("$command ... ");
117
118 $pid = open(CMD, "$command 2>&1 |") or
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400119 (fail "unable to exec $command" and return 0);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400120
121 if (defined($opt{"LOG_FILE"})) {
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400122 open(LOG, ">>$opt{LOG_FILE}") or
123 dodie "failed to write to log";
124 $dolog = 1;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400125 }
126
127 if (defined($redirect)) {
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400128 open (RD, ">$redirect") or
129 dodie "failed to write to redirect $redirect";
130 $dord = 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400131 }
132
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400133 while (<CMD>) {
134 print LOG if ($dolog);
135 print RD if ($dord);
136 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400137
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400138 waitpid($pid, 0);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400139 my $failed = $?;
140
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400141 close(CMD);
142 close(LOG) if ($dolog);
143 close(RD) if ($dord);
144
Steven Rostedt2545eb62010-11-02 15:01:32 -0400145 if ($failed) {
146 doprint "FAILED!\n";
147 } else {
148 doprint "SUCCESS\n";
149 }
150
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400151 return !$failed;
152}
153
154sub get_grub_index {
155
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400156 return if (defined($grub_number));
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400157
158 doprint "Find grub menu ... ";
159 $grub_number = -1;
160 open(IN, "ssh $target cat /boot/grub/menu.lst |")
161 or die "unable to get menu.lst";
162 while (<IN>) {
163 if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) {
164 $grub_number++;
165 last;
166 } elsif (/^\s*title\s/) {
167 $grub_number++;
168 }
169 }
170 close(IN);
171
172 die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}"
173 if ($grub_number < 0);
174 doprint "$grub_number\n";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400175}
176
177my $timeout = $opt{"TIMEOUT"};
178
179sub wait_for_input
180{
181 my ($fp, $time) = @_;
182 my $rin;
183 my $ready;
184 my $line;
185 my $ch;
186
187 if (!defined($time)) {
188 $time = $timeout;
189 }
190
191 $rin = '';
192 vec($rin, fileno($fp), 1) = 1;
193 $ready = select($rin, undef, undef, $time);
194
195 $line = "";
196
197 # try to read one char at a time
198 while (sysread $fp, $ch, 1) {
199 $line .= $ch;
200 last if ($ch eq "\n");
201 }
202
203 if (!length($line)) {
204 return undef;
205 }
206
207 return $line;
208}
209
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400210sub reboot_to {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400211 run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
212}
213
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400214sub open_console {
215 my ($fp) = @_;
216
Steven Rostedt2545eb62010-11-02 15:01:32 -0400217 my $flags;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400218
219 my $pid = open($fp, "$opt{CONSOLE}|") or
220 dodie "Can't open console $opt{CONSOLE}";
221
222 $flags = fcntl($fp, F_GETFL, 0) or
223 dodie "Can't get flags for the socket: $!\n";
224 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
225 dodie "Can't set flags for the socket: $!\n";
226
227 return $pid;
228}
229
230sub close_console {
231 my ($fp, $pid) = @_;
232
233 doprint "kill child process $pid\n";
234 kill 2, $pid;
235
236 print "closing!\n";
237 close($fp);
238}
239
240sub monitor {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400241 my $booted = 0;
242 my $bug = 0;
243 my $pid;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400244 my $skip_call_trace = 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400245 my $fp = \*IN;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400246 my $loops;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400247
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400248 $pid = open_console($fp);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400249
250 my $line;
251 my $full_line = "";
252
253 doprint "Wait for monitor to settle down.\n";
254 # read the monitor and wait for the system to calm down
255 do {
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400256 $line = wait_for_input($fp, 5);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400257 } while (defined($line));
258
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400259 reboot_to;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400260
261 for (;;) {
262
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400263 if ($booted) {
264 $line = wait_for_input($fp, $opt{"BOOTED_TIMEOUT"});
265 } else {
266 $line = wait_for_input($fp);
267 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400268
269 last if (!defined($line));
270
271 doprint $line;
272
273 # we are not guaranteed to get a full line
274 $full_line .= $line;
275
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400276 if ($full_line =~ /$opt{"SUCCESS_LINE"}/) {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400277 $booted = 1;
278 }
279
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400280 if ($full_line =~ /\[ backtrace testing \]/) {
281 $skip_call_trace = 1;
282 }
283
Steven Rostedt2545eb62010-11-02 15:01:32 -0400284 if ($full_line =~ /call trace:/i) {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400285 $bug = 1 if (!$skip_call_trace);
286 }
287
288 if ($full_line =~ /\[ end of backtrace testing \]/) {
289 $skip_call_trace = 0;
290 }
291
292 if ($full_line =~ /Kernel panic -/) {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400293 $bug = 1;
294 }
295
296 if ($line =~ /\n/) {
297 $full_line = "";
298 }
299 }
300
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400301 close_console($fp, $pid);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400302
303 if (!$booted) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400304 return 0 if ($in_bisect);
305 fail "failed - never got a boot prompt.\n" and return 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400306 }
307
308 if ($bug) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400309 return 0 if ($in_bisect);
310 fail "failed - got a bug report\n" and return 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400311 }
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400312
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400313 return 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400314}
315
316sub install {
317
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400318 run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400319 dodie "failed to copy image";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400320
321 my $install_mods = 0;
322
323 # should we process modules?
324 $install_mods = 0;
325 open(IN, "$opt{OUTPUT_DIR}/.config") or dodie("Can't read config file");
326 while (<IN>) {
327 if (/CONFIG_MODULES(=y)?/) {
328 $install_mods = 1 if (defined($1));
329 last;
330 }
331 }
332 close(IN);
333
334 if (!$install_mods) {
335 doprint "No modules needed\n";
336 return;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400337 }
338
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400339 run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install" or
340 dodie "Failed to install modules";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400341
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400342 my $modlib = "/lib/modules/$version";
343 my $modtar = "autotest-mods.tar.bz2";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400344
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400345 run_command "ssh $target rm -rf $modlib" or
346 dodie "failed to remove old mods: $modlib";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400347
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400348 # would be nice if scp -r did not follow symbolic links
349 run_command "cd $opt{TMP_DIR} && tar -cjf $modtar lib/modules/$version" or
350 dodie "making tarball";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400351
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400352 run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp" or
353 dodie "failed to copy modules";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400354
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400355 unlink "$opt{TMP_DIR}/$modtar";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400356
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400357 run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or
358 dodie "failed to tar modules";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400359
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400360 run_command "ssh $target rm -f /tmp/$modtar";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400361}
362
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400363sub check_buildlog {
364 my ($patch) = @_;
365
366 my $buildlog = "$opt{TMP_DIR}/buildlog";
367 my @files = `git show $patch | diffstat -l`;
368
369 open(IN, "git show $patch |") or
370 dodie "failed to show $patch";
371 while (<IN>) {
372 if (m,^--- a/(.*),) {
373 chomp $1;
374 $files[$#files] = $1;
375 }
376 }
377 close(IN);
378
379 open(IN, $buildlog) or dodie "Can't open $buildlog";
380 while (<IN>) {
381 if (/^\s*(.*?):.*(warning|error)/) {
382 my $err = $1;
383 foreach my $file (@files) {
384 my $fullpath = "$opt{BUILD_DIR}/$file";
385 if ($file eq $err || $fullpath eq $err) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400386 fail "$file built with warnings" and return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400387 }
388 }
389 }
390 }
391 close(IN);
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400392
393 return 1;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400394}
395
Steven Rostedt2545eb62010-11-02 15:01:32 -0400396sub build {
397 my ($type) = @_;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400398 my $defconfig = "";
399 my $append = "";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400400
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400401 if ($type =~ /^useconfig:(.*)/) {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400402 run_command "cp $1 $opt{OUTPUT_DIR}/.config" or
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400403 dodie "could not copy $1 to .config";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400404
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400405 $type = "oldconfig";
406 }
407
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400408 # old config can ask questions
409 if ($type eq "oldconfig") {
410 $append = "yes ''|";
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400411
412 # allow for empty configs
413 run_command "touch $opt{OUTPUT_DIR}/.config";
414
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400415 run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400416 dodie "moving .config";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400417
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400418 if (!$noclean && !run_command "$make mrproper") {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400419 dodie "make mrproper";
420 }
421
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400422 run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400423 dodie "moving config_temp";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400424
425 } elsif (!$noclean) {
426 unlink "$opt{OUTPUT_DIR}/.config";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400427 run_command "$make mrproper" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400428 dodie "make mrproper";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400429 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400430
431 # add something to distinguish this build
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400432 open(OUT, "> $opt{OUTPUT_DIR}/localversion") or dodie("Can't make localversion file");
Steven Rostedt2545eb62010-11-02 15:01:32 -0400433 print OUT "$opt{LOCALVERSION}\n";
434 close(OUT);
435
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400436 if (defined($minconfig)) {
437 $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400438 }
439
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400440 run_command "$defconfig $append $make $type" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400441 dodie "failed make config";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400442
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400443 # patch check will examine the log
444 if ($in_patchcheck) {
445 $redirect = "$opt{TMP_DIR}/buildlog";
446 }
447
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400448 if (!run_command "$make $opt{BUILD_OPTIONS}") {
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400449 undef $redirect;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400450 # bisect may need this to pass
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400451 return 0 if ($in_bisect);
452 fail "failed build" and return 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400453 }
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400454 undef $redirect;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400455
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400456 return 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400457}
458
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400459sub reboot {
460 # try to reboot normally
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400461 if (!run_command "ssh $target reboot") {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400462 # nope? power cycle it.
463 run_command "$opt{POWER_CYCLE}";
464 }
465}
466
467sub halt {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400468 if (!run_command "ssh $target halt" or defined($opt{"POWER_OFF"})) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400469 # nope? the zap it!
470 run_command "$opt{POWER_OFF}";
471 }
472}
473
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400474sub success {
475 my ($i) = @_;
476
477 doprint "\n\n*******************************************\n";
478 doprint "*******************************************\n";
479 doprint "** SUCCESS!!!! **\n";
480 doprint "*******************************************\n";
481 doprint "*******************************************\n";
482
483 if ($i != $opt{"NUM_BUILDS"}) {
484 reboot;
485 doprint "Sleeping $opt{SLEEP_TIME} seconds\n";
486 sleep "$opt{SLEEP_TIME}";
487 }
488}
489
490sub get_version {
491 # get the release name
492 doprint "$make kernelrelease ... ";
493 $version = `$make kernelrelease | tail -1`;
494 chomp($version);
495 doprint "$version\n";
496}
497
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400498sub child_run_test {
499 my $failed;
500
501 $failed = !run_command $run_test;
502 exit $failed;
503}
504
505my $child_done;
506
507sub child_finished {
508 $child_done = 1;
509}
510
511sub do_run_test {
512 my $child_pid;
513 my $child_exit;
514 my $pid;
515 my $line;
516 my $full_line;
517 my $bug = 0;
518 my $fp = \*IN;
519
520 $pid = open_console($fp);
521
522 # read the monitor and wait for the system to calm down
523 do {
524 $line = wait_for_input($fp, 1);
525 } while (defined($line));
526
527 $child_done = 0;
528
529 $SIG{CHLD} = qw(child_finished);
530
531 $child_pid = fork;
532
533 child_run_test if (!$child_pid);
534
535 $full_line = "";
536
537 do {
538 $line = wait_for_input($fp, 1);
539 if (defined($line)) {
540
541 # we are not guaranteed to get a full line
542 $full_line .= $line;
543
544 if ($full_line =~ /call trace:/i) {
545 $bug = 1;
546 }
547
548 if ($full_line =~ /Kernel panic -/) {
549 $bug = 1;
550 }
551
552 if ($line =~ /\n/) {
553 $full_line = "";
554 }
555 }
556 } while (!$child_done && !$bug);
557
558 if ($bug) {
559 doprint "Detected kernel crash!\n";
560 # kill the child with extreme prejudice
561 kill 9, $child_pid;
562 }
563
564 waitpid $child_pid, 0;
565 $child_exit = $?;
566
567 close_console($fp, $pid);
568
569 if ($bug || $child_exit) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400570 return 0 if $in_bisect;
571 fail "test failed" and return 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400572 }
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400573 return 1;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400574}
575
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400576sub run_bisect {
577 my ($type) = @_;
578
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400579 my $failed = 0;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400580 my $result;
581 my $output;
582 my $ret;
583
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400584 if (defined($minconfig)) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400585 build "useconfig:$minconfig" or $failed = 1;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400586 } else {
587 # ?? no config to use?
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400588 build "oldconfig" or $failed = 1;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400589 }
590
591 if ($type ne "build") {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400592 fail "Failed on build" if $failed;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400593
594 # Now boot the box
595 get_grub_index;
596 get_version;
597 install;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400598 monitor or $failed = 1;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400599
600 if ($type ne "boot") {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400601 fail "Failed on boot" if $failed;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400602
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400603 do_run_test or $failed = 1;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400604 }
605 }
606
607 if ($failed) {
608 $result = "bad";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400609
610 # reboot the box to a good kernel
611 if ($type eq "boot") {
612 reboot;
613 doprint "sleep a little for reboot\n";
614 sleep $opt{"BISECT_SLEEP_TIME"};
615 }
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400616 } else {
617 $result = "good";
618 }
619
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400620 # Are we looking for where it worked, not failed?
621 if ($reverse_bisect) {
622 if ($failed) {
623 $result = "good";
624 } else {
625 $result = "bad";
626 }
627 }
628
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400629 doprint "git bisect $result ... ";
630 $output = `git bisect $result 2>&1`;
631 $ret = $?;
632
633 logit $output;
634
635 if ($ret) {
636 doprint "FAILED\n";
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400637 fail "Failed to git bisect";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400638 }
639
640 doprint "SUCCESS\n";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400641 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400642 doprint "$1 [$2]\n";
643 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
644 $bisect_bad = $1;
645 doprint "Found bad commit... $1\n";
646 return 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400647 } else {
648 # we already logged it, just print it now.
649 print $output;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400650 }
651
652
653 return 1;
654}
655
656sub bisect {
657 my ($i) = @_;
658
659 my $result;
660
661 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
662 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
663 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
664
665 my $good = $opt{"BISECT_GOOD[$i]"};
666 my $bad = $opt{"BISECT_BAD[$i]"};
667 my $type = $opt{"BISECT_TYPE[$i]"};
668
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400669 if (defined($opt{"BISECT_REVERSE[$i]"}) &&
670 $opt{"BISECT_REVERSE[$i]"} == 1) {
671 doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
672 $reverse_bisect = 1;
673 } else {
674 $reverse_bisect = 0;
675 }
676
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400677 $in_bisect = 1;
678
679 run_command "git bisect start" or
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400680 fail "could not start bisect";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400681
682 run_command "git bisect good $good" or
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400683 fail "could not set bisect good to $good";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400684
685 run_command "git bisect bad $bad" or
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400686 fail "could not set bisect good to $bad";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400687
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400688 # Can't have a test without having a test to run
689 if ($type eq "test" && !defined($run_test)) {
690 $type = "boot";
691 }
692
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400693 do {
694 $result = run_bisect $type;
695 } while ($result);
696
697 run_command "git bisect log" or
698 dodie "could not capture git bisect log";
699
700 run_command "git bisect reset" or
701 dodie "could not reset git bisect";
702
703 doprint "Bad commit was [$bisect_bad]\n";
704
705 $in_bisect = 0;
706
707 success $i;
708}
709
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400710sub patchcheck {
711 my ($i) = @_;
712
713 die "PATCHCHECK_START[$i] not defined\n"
714 if (!defined($opt{"PATCHCHECK_START[$i]"}));
715 die "PATCHCHECK_TYPE[$i] not defined\n"
716 if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
717
718 my $start = $opt{"PATCHCHECK_START[$i]"};
719
720 my $end = "HEAD";
721 if (defined($opt{"PATCHCHECK_END[$i]"})) {
722 $end = $opt{"PATCHCHECK_END[$i]"};
723 }
724
725 my $type = $opt{"PATCHCHECK_TYPE[$i]"};
726
727 # Can't have a test without having a test to run
728 if ($type eq "test" && !defined($run_test)) {
729 $type = "boot";
730 }
731
732 open (IN, "git log --pretty=oneline $end|") or
733 dodie "could not get git list";
734
735 my @list;
736
737 while (<IN>) {
738 chomp;
739 $list[$#list+1] = $_;
740 last if (/^$start/);
741 }
742 close(IN);
743
744 if ($list[$#list] !~ /^$start/) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400745 fail "SHA1 $start not found";
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400746 }
747
748 # go backwards in the list
749 @list = reverse @list;
750
751 my $save_clean = $noclean;
752
753 $in_patchcheck = 1;
754 foreach my $item (@list) {
755 my $sha1 = $item;
756 $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
757
758 doprint "\nProcessing commit $item\n\n";
759
760 run_command "git checkout $sha1" or
761 die "Failed to checkout $sha1";
762
763 # only clean on the first and last patch
764 if ($item eq $list[0] ||
765 $item eq $list[$#list]) {
766 $noclean = $save_clean;
767 } else {
768 $noclean = 1;
769 }
770
771 if (defined($minconfig)) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400772 build "useconfig:$minconfig" or return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400773 } else {
774 # ?? no config to use?
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400775 build "oldconfig" or return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400776 }
777
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400778 check_buildlog $sha1 or return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400779
780 next if ($type eq "build");
781
782 get_grub_index;
783 get_version;
784 install;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400785 monitor or return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400786
787 next if ($type eq "boot");
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400788 do_run_test or next;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400789 }
790 $in_patchcheck = 0;
791 success $i;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400792
793 return 1;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400794}
795
Steven Rostedt2545eb62010-11-02 15:01:32 -0400796read_config $ARGV[0];
797
798# mandatory configs
799die "MACHINE not defined\n" if (!defined($opt{"MACHINE"}));
800die "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"}));
801die "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"}));
802die "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"}));
803die "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"}));
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400804die "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"}));
Steven Rostedt2545eb62010-11-02 15:01:32 -0400805die "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"}));
806die "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"}));
807die "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"}));
808die "GRUB_MENU not defined\n" if (!defined($opt{"GRUB_MENU"}));
809
810chdir $opt{"BUILD_DIR"} || die "can't change directory to $opt{BUILD_DIR}";
811
812$target = "$opt{SSH_USER}\@$opt{MACHINE}";
813
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400814if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
815 unlink $opt{"LOG_FILE"};
816}
Steven Rostedt2545eb62010-11-02 15:01:32 -0400817
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400818doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
819
820foreach my $option (sort keys %opt) {
821 doprint "$option = $opt{$option}\n";
822}
Steven Rostedt2545eb62010-11-02 15:01:32 -0400823
824$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}";
825
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400826sub set_build_option {
827 my ($name, $i) = @_;
828
829 my $option = "$name\[$i\]";
830
831 if (defined($opt{$option})) {
832 return $opt{$option};
833 }
834
835 if (defined($opt{$name})) {
836 return $opt{$name};
837 }
838
839 return undef;
840}
841
Steven Rostedt2545eb62010-11-02 15:01:32 -0400842# First we need to do is the builds
843for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
844 my $type = "BUILD_TYPE[$i]";
845
Steven Rostedt1a5cfce2010-11-02 14:57:51 -0400846 if (!defined($opt{$type})) {
847 $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"};
848 }
849
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400850 $noclean = set_build_option("BUILD_NOCLEAN", $i);
851 $minconfig = set_build_option("MIN_CONFIG", $i);
852 $run_test = set_build_option("TEST", $i);
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400853 $addconfig = set_build_option("ADD_CONFIG", $i);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400854
855 doprint "\n\n";
856 doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n";
857
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400858 if (!defined($minconfig)) {
859 $minconfig = $addconfig;
860
861 } elsif (defined($addconfig)) {
862 run_command "cat $addconfig $minconfig > $opt{TMP_DIR}/use_config" or
863 dodie "Failed to create temp config";
864 $minconfig = "$opt{TMP_DIR}/use_config";
865 }
866
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400867 my $checkout = $opt{"CHECKOUT[$i]"};
868 if (defined($checkout)) {
869 run_command "git checkout $checkout" or
870 die "failed to checkout $checkout";
871 }
872
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400873 if ($opt{$type} eq "bisect") {
874 bisect $i;
875 next;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400876 } elsif ($opt{$type} eq "patchcheck") {
877 patchcheck $i;
878 next;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400879 }
880
Steven Rostedt2545eb62010-11-02 15:01:32 -0400881 if ($opt{$type} ne "nobuild") {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400882 build $opt{$type} or next;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400883 }
884
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400885 get_grub_index;
886 get_version;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400887 install;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400888 monitor or next;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400889
890 if (defined($run_test)) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400891 do_run_test or next;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400892 }
893
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400894 success $i;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400895}
896
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400897if ($opt{"POWEROFF_ON_SUCCESS"}) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400898 halt;
Steven Rostedt1a5cfce2010-11-02 14:57:51 -0400899} elsif ($opt{"REBOOT_ON_SUCCESS"}) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400900 reboot;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400901}
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400902
Steven Rostedt2545eb62010-11-02 15:01:32 -0400903exit 0;