blob: 962c0f773e20112f54d0ad63513db7a29d0d05e2 [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
Steven Rostedta57419b2010-11-02 15:13:54 -040014$#ARGV >= 0 || die "usage: ktest.pl config-file\n";
Steven Rostedt2545eb62010-11-02 15:01:32 -040015
16$| = 1;
17
18my %opt;
Steven Rostedta57419b2010-11-02 15:13:54 -040019my %repeat_tests;
20my %repeats;
Steven Rostedta75fece2010-11-02 14:58:27 -040021my %default;
Steven Rostedt2545eb62010-11-02 15:01:32 -040022
23#default opts
Steven Rostedta57419b2010-11-02 15:13:54 -040024$default{"NUM_TESTS"} = 1;
Steven Rostedta75fece2010-11-02 14:58:27 -040025$default{"REBOOT_TYPE"} = "grub";
26$default{"TEST_TYPE"} = "test";
27$default{"BUILD_TYPE"} = "randconfig";
28$default{"MAKE_CMD"} = "make";
29$default{"TIMEOUT"} = 120;
Steven Rostedta57419b2010-11-02 15:13:54 -040030$default{"TMP_DIR"} = "/tmp/ktest";
Steven Rostedta75fece2010-11-02 14:58:27 -040031$default{"SLEEP_TIME"} = 60; # sleep time between tests
32$default{"BUILD_NOCLEAN"} = 0;
33$default{"REBOOT_ON_ERROR"} = 0;
34$default{"POWEROFF_ON_ERROR"} = 0;
35$default{"REBOOT_ON_SUCCESS"} = 1;
36$default{"POWEROFF_ON_SUCCESS"} = 0;
37$default{"BUILD_OPTIONS"} = "";
38$default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects
39$default{"CLEAR_LOG"} = 0;
40$default{"SUCCESS_LINE"} = "login:";
41$default{"BOOTED_TIMEOUT"} = 1;
42$default{"DIE_ON_FAILURE"} = 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -040043
44my $version;
Steven Rostedta75fece2010-11-02 14:58:27 -040045my $machine;
46my $tmpdir;
47my $builddir;
48my $outputdir;
Steven Rostedt51ad1dd2010-11-08 16:43:21 -050049my $output_config;
Steven Rostedta75fece2010-11-02 14:58:27 -040050my $test_type;
Steven Rostedt7faafbd2010-11-02 14:58:22 -040051my $build_type;
Steven Rostedta75fece2010-11-02 14:58:27 -040052my $build_options;
53my $reboot_type;
54my $reboot_script;
55my $power_cycle;
56my $reboot_on_error;
57my $poweroff_on_error;
58my $die_on_failure;
Steven Rostedt576f6272010-11-02 14:58:38 -040059my $powercycle_after_reboot;
60my $poweroff_after_halt;
Steven Rostedta75fece2010-11-02 14:58:27 -040061my $power_off;
62my $grub_menu;
Steven Rostedt2545eb62010-11-02 15:01:32 -040063my $grub_number;
64my $target;
65my $make;
Steven Rostedt8b37ca82010-11-02 14:58:33 -040066my $post_install;
Steven Rostedt5c42fc52010-11-02 14:57:01 -040067my $noclean;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040068my $minconfig;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -040069my $addconfig;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -040070my $in_bisect = 0;
71my $bisect_bad = "";
Steven Rostedtd6ce2a02010-11-02 14:58:05 -040072my $reverse_bisect;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -040073my $in_patchcheck = 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -040074my $run_test;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -040075my $redirect;
Steven Rostedt7faafbd2010-11-02 14:58:22 -040076my $buildlog;
77my $dmesg;
78my $monitor_fp;
79my $monitor_pid;
80my $monitor_cnt = 0;
Steven Rostedta75fece2010-11-02 14:58:27 -040081my $sleep_time;
82my $bisect_sleep_time;
83my $store_failures;
84my $timeout;
85my $booted_timeout;
86my $console;
87my $success_line;
88my $build_target;
89my $target_image;
90my $localversion;
Steven Rostedt576f6272010-11-02 14:58:38 -040091my $iteration = 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -040092
Steven Rostedta57419b2010-11-02 15:13:54 -040093sub set_value {
94 my ($lvalue, $rvalue) = @_;
95
96 if (defined($opt{$lvalue})) {
97 die "Error: Option $lvalue defined more than once!\n";
98 }
99 $opt{$lvalue} = $rvalue;
Steven Rostedt21a96792010-11-08 16:45:50 -0500100 if ($rvalue =~ /^\s*$/) {
101 delete $opt{$lvalue};
102 } else {
103 $opt{$lvalue} = $rvalue;
104 }
Steven Rostedta57419b2010-11-02 15:13:54 -0400105}
106
Steven Rostedt2545eb62010-11-02 15:01:32 -0400107sub read_config {
108 my ($config) = @_;
109
110 open(IN, $config) || die "can't read file $config";
111
Steven Rostedta57419b2010-11-02 15:13:54 -0400112 my $name = $config;
113 $name =~ s,.*/(.*),$1,;
114
115 my $test_num = 0;
116 my $default = 1;
117 my $repeat = 1;
118 my $num_tests_set = 0;
119 my $skip = 0;
120 my $rest;
121
Steven Rostedt2545eb62010-11-02 15:01:32 -0400122 while (<IN>) {
123
124 # ignore blank lines and comments
125 next if (/^\s*$/ || /\s*\#/);
126
Steven Rostedta57419b2010-11-02 15:13:54 -0400127 if (/^\s*TEST_START(.*)/) {
128
129 $rest = $1;
130
131 if ($num_tests_set) {
132 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
133 }
134
135 my $old_test_num = $test_num;
136
137 $test_num += $repeat;
138 $default = 0;
139 $repeat = 1;
140
141 if ($rest =~ /\s+SKIP(.*)/) {
142 $rest = $1;
143 $skip = 1;
144 } else {
145 $skip = 0;
146 }
147
148 if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
149 $repeat = $1;
150 $rest = $2;
151 $repeat_tests{"$test_num"} = $repeat;
152 }
153
154 if ($rest =~ /\s+SKIP(.*)/) {
155 $rest = $1;
156 $skip = 1;
157 }
158
159 if ($rest !~ /^\s*$/) {
160 die "$name: $.: Gargbage found after TEST_START\n$_";
161 }
162
163 if ($skip) {
164 $test_num = $old_test_num;
165 $repeat = 1;
166 }
167
168 } elsif (/^\s*DEFAULTS(.*)$/) {
169 $default = 1;
170
171 $rest = $1;
172
173 if ($rest =~ /\s+SKIP(.*)/) {
174 $rest = $1;
175 $skip = 1;
176 } else {
177 $skip = 0;
178 }
179
180 if ($rest !~ /^\s*$/) {
181 die "$name: $.: Gargbage found after DEFAULTS\n$_";
182 }
183
184 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
185
186 next if ($skip);
187
Steven Rostedt2545eb62010-11-02 15:01:32 -0400188 my $lvalue = $1;
189 my $rvalue = $2;
190
Steven Rostedta57419b2010-11-02 15:13:54 -0400191 if (!$default &&
192 ($lvalue eq "NUM_TESTS" ||
193 $lvalue eq "LOG_FILE" ||
194 $lvalue eq "CLEAR_LOG")) {
195 die "$name: $.: $lvalue must be set in DEFAULTS section\n";
Steven Rostedta75fece2010-11-02 14:58:27 -0400196 }
Steven Rostedta57419b2010-11-02 15:13:54 -0400197
198 if ($lvalue eq "NUM_TESTS") {
199 if ($test_num) {
200 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
201 }
202 if (!$default) {
203 die "$name: $.: NUM_TESTS must be set in default section\n";
204 }
205 $num_tests_set = 1;
206 }
207
208 if ($default || $lvalue =~ /\[\d+\]$/) {
209 set_value($lvalue, $rvalue);
210 } else {
211 my $val = "$lvalue\[$test_num\]";
212 set_value($val, $rvalue);
213
214 if ($repeat > 1) {
215 $repeats{$val} = $repeat;
216 }
217 }
218 } else {
219 die "$name: $.: Garbage found in config\n$_";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400220 }
221 }
222
223 close(IN);
Steven Rostedta75fece2010-11-02 14:58:27 -0400224
Steven Rostedta57419b2010-11-02 15:13:54 -0400225 if ($test_num) {
226 $test_num += $repeat - 1;
227 $opt{"NUM_TESTS"} = $test_num;
228 }
229
Steven Rostedta75fece2010-11-02 14:58:27 -0400230 # set any defaults
231
232 foreach my $default (keys %default) {
233 if (!defined($opt{$default})) {
234 $opt{$default} = $default{$default};
235 }
236 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400237}
238
Steven Rostedtd1e2f222010-11-08 16:39:57 -0500239sub _logit {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400240 if (defined($opt{"LOG_FILE"})) {
241 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
242 print OUT @_;
243 close(OUT);
244 }
245}
246
Steven Rostedtd1e2f222010-11-08 16:39:57 -0500247sub logit {
248 if (defined($opt{"LOG_FILE"})) {
249 _logit @_;
250 } else {
251 print @_;
252 }
253}
254
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400255sub doprint {
256 print @_;
Steven Rostedtd1e2f222010-11-08 16:39:57 -0500257 _logit @_;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400258}
259
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400260sub run_command;
261
262sub reboot {
263 # try to reboot normally
Steven Rostedt576f6272010-11-02 14:58:38 -0400264 if (run_command "ssh $target reboot") {
265 if (defined($powercycle_after_reboot)) {
266 sleep $powercycle_after_reboot;
267 run_command "$power_cycle";
268 }
269 } else {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400270 # nope? power cycle it.
Steven Rostedta75fece2010-11-02 14:58:27 -0400271 run_command "$power_cycle";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400272 }
273}
274
Steven Rostedt576f6272010-11-02 14:58:38 -0400275sub do_not_reboot {
276 my $i = $iteration;
277
278 return $test_type eq "build" ||
279 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
280 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
281}
282
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400283sub dodie {
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400284 doprint "CRITICAL FAILURE... ", @_, "\n";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400285
Steven Rostedt576f6272010-11-02 14:58:38 -0400286 my $i = $iteration;
287
288 if ($reboot_on_error && !do_not_reboot) {
289
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400290 doprint "REBOOTING\n";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400291 reboot;
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400292
Steven Rostedta75fece2010-11-02 14:58:27 -0400293 } elsif ($poweroff_on_error && defined($power_off)) {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400294 doprint "POWERING OFF\n";
Steven Rostedta75fece2010-11-02 14:58:27 -0400295 `$power_off`;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400296 }
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400297
Steven Rostedt576f6272010-11-02 14:58:38 -0400298 die @_, "\n";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400299}
300
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400301sub open_console {
302 my ($fp) = @_;
303
304 my $flags;
305
Steven Rostedta75fece2010-11-02 14:58:27 -0400306 my $pid = open($fp, "$console|") or
307 dodie "Can't open console $console";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400308
309 $flags = fcntl($fp, F_GETFL, 0) or
Steven Rostedt576f6272010-11-02 14:58:38 -0400310 dodie "Can't get flags for the socket: $!";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400311 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
Steven Rostedt576f6272010-11-02 14:58:38 -0400312 dodie "Can't set flags for the socket: $!";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400313
314 return $pid;
315}
316
317sub close_console {
318 my ($fp, $pid) = @_;
319
320 doprint "kill child process $pid\n";
321 kill 2, $pid;
322
323 print "closing!\n";
324 close($fp);
325}
326
327sub start_monitor {
328 if ($monitor_cnt++) {
329 return;
330 }
331 $monitor_fp = \*MONFD;
332 $monitor_pid = open_console $monitor_fp;
Steven Rostedta75fece2010-11-02 14:58:27 -0400333
334 return;
335
336 open(MONFD, "Stop perl from warning about single use of MONFD");
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400337}
338
339sub end_monitor {
340 if (--$monitor_cnt) {
341 return;
342 }
343 close_console($monitor_fp, $monitor_pid);
344}
345
346sub wait_for_monitor {
347 my ($time) = @_;
348 my $line;
349
Steven Rostedta75fece2010-11-02 14:58:27 -0400350 doprint "** Wait for monitor to settle down **\n";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400351
352 # read the monitor and wait for the system to calm down
353 do {
354 $line = wait_for_input($monitor_fp, $time);
Steven Rostedta75fece2010-11-02 14:58:27 -0400355 print "$line" if (defined($line));
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400356 } while (defined($line));
Steven Rostedta75fece2010-11-02 14:58:27 -0400357 print "** Monitor flushed **\n";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400358}
359
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400360sub fail {
361
Steven Rostedta75fece2010-11-02 14:58:27 -0400362 if ($die_on_failure) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400363 dodie @_;
364 }
365
Steven Rostedta75fece2010-11-02 14:58:27 -0400366 doprint "FAILED\n";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400367
Steven Rostedt576f6272010-11-02 14:58:38 -0400368 my $i = $iteration;
369
Steven Rostedta75fece2010-11-02 14:58:27 -0400370 # no need to reboot for just building.
Steven Rostedt576f6272010-11-02 14:58:38 -0400371 if (!do_not_reboot) {
Steven Rostedta75fece2010-11-02 14:58:27 -0400372 doprint "REBOOTING\n";
373 reboot;
374 start_monitor;
375 wait_for_monitor $sleep_time;
376 end_monitor;
377 }
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400378
Steven Rostedt576f6272010-11-02 14:58:38 -0400379 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
380 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
Steven Rostedta75fece2010-11-02 14:58:27 -0400381 doprint "**** Failed: ", @_, " ****\n";
Steven Rostedt576f6272010-11-02 14:58:38 -0400382 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
383 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
Steven Rostedta75fece2010-11-02 14:58:27 -0400384
385 return 1 if (!defined($store_failures));
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400386
387 my @t = localtime;
388 my $date = sprintf "%04d%02d%02d%02d%02d%02d",
389 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
390
Steven Rostedta75fece2010-11-02 14:58:27 -0400391 my $dir = "$machine-$test_type-$build_type-fail-$date";
392 my $faildir = "$store_failures/$dir";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400393
394 if (!-d $faildir) {
395 mkpath($faildir) or
Steven Rostedta75fece2010-11-02 14:58:27 -0400396 die "can't create $faildir";
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400397 }
Steven Rostedt51ad1dd2010-11-08 16:43:21 -0500398 if (-f "$output_config") {
399 cp "$output_config", "$faildir/config" or
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400400 die "failed to copy .config";
401 }
402 if (-f $buildlog) {
403 cp $buildlog, "$faildir/buildlog" or
404 die "failed to move $buildlog";
405 }
406 if (-f $dmesg) {
407 cp $dmesg, "$faildir/dmesg" or
408 die "failed to move $dmesg";
409 }
410
411 doprint "*** Saved info to $faildir ***\n";
412
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400413 return 1;
414}
415
Steven Rostedt2545eb62010-11-02 15:01:32 -0400416sub run_command {
417 my ($command) = @_;
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400418 my $dolog = 0;
419 my $dord = 0;
420 my $pid;
421
422 doprint("$command ... ");
423
424 $pid = open(CMD, "$command 2>&1 |") or
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400425 (fail "unable to exec $command" and return 0);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400426
427 if (defined($opt{"LOG_FILE"})) {
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400428 open(LOG, ">>$opt{LOG_FILE}") or
429 dodie "failed to write to log";
430 $dolog = 1;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400431 }
432
433 if (defined($redirect)) {
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400434 open (RD, ">$redirect") or
435 dodie "failed to write to redirect $redirect";
436 $dord = 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400437 }
438
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400439 while (<CMD>) {
440 print LOG if ($dolog);
441 print RD if ($dord);
442 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400443
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400444 waitpid($pid, 0);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400445 my $failed = $?;
446
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400447 close(CMD);
448 close(LOG) if ($dolog);
449 close(RD) if ($dord);
450
Steven Rostedt2545eb62010-11-02 15:01:32 -0400451 if ($failed) {
452 doprint "FAILED!\n";
453 } else {
454 doprint "SUCCESS\n";
455 }
456
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400457 return !$failed;
458}
459
460sub get_grub_index {
461
Steven Rostedta75fece2010-11-02 14:58:27 -0400462 if ($reboot_type ne "grub") {
463 return;
464 }
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400465 return if (defined($grub_number));
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400466
467 doprint "Find grub menu ... ";
468 $grub_number = -1;
469 open(IN, "ssh $target cat /boot/grub/menu.lst |")
470 or die "unable to get menu.lst";
471 while (<IN>) {
Steven Rostedta75fece2010-11-02 14:58:27 -0400472 if (/^\s*title\s+$grub_menu\s*$/) {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400473 $grub_number++;
474 last;
475 } elsif (/^\s*title\s/) {
476 $grub_number++;
477 }
478 }
479 close(IN);
480
Steven Rostedta75fece2010-11-02 14:58:27 -0400481 die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400482 if ($grub_number < 0);
483 doprint "$grub_number\n";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400484}
485
Steven Rostedt2545eb62010-11-02 15:01:32 -0400486sub wait_for_input
487{
488 my ($fp, $time) = @_;
489 my $rin;
490 my $ready;
491 my $line;
492 my $ch;
493
494 if (!defined($time)) {
495 $time = $timeout;
496 }
497
498 $rin = '';
499 vec($rin, fileno($fp), 1) = 1;
500 $ready = select($rin, undef, undef, $time);
501
502 $line = "";
503
504 # try to read one char at a time
505 while (sysread $fp, $ch, 1) {
506 $line .= $ch;
507 last if ($ch eq "\n");
508 }
509
510 if (!length($line)) {
511 return undef;
512 }
513
514 return $line;
515}
516
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400517sub reboot_to {
Steven Rostedta75fece2010-11-02 14:58:27 -0400518 if ($reboot_type eq "grub") {
519 run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
520 return;
521 }
522
523 run_command "$reboot_script";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400524}
525
Steven Rostedta57419b2010-11-02 15:13:54 -0400526sub get_sha1 {
527 my ($commit) = @_;
528
529 doprint "git rev-list --max-count=1 $commit ... ";
530 my $sha1 = `git rev-list --max-count=1 $commit`;
531 my $ret = $?;
532
533 logit $sha1;
534
535 if ($ret) {
536 doprint "FAILED\n";
537 dodie "Failed to get git $commit";
538 }
539
540 print "SUCCESS\n";
541
542 chomp $sha1;
543
544 return $sha1;
545}
546
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400547sub monitor {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400548 my $booted = 0;
549 my $bug = 0;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400550 my $skip_call_trace = 0;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400551 my $loops;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400552
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400553 wait_for_monitor 5;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400554
555 my $line;
556 my $full_line = "";
557
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400558 open(DMESG, "> $dmesg") or
559 die "unable to write to $dmesg";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400560
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400561 reboot_to;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400562
563 for (;;) {
564
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400565 if ($booted) {
Steven Rostedta75fece2010-11-02 14:58:27 -0400566 $line = wait_for_input($monitor_fp, $booted_timeout);
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400567 } else {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400568 $line = wait_for_input($monitor_fp);
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400569 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400570
571 last if (!defined($line));
572
573 doprint $line;
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400574 print DMESG $line;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400575
576 # we are not guaranteed to get a full line
577 $full_line .= $line;
578
Steven Rostedta75fece2010-11-02 14:58:27 -0400579 if ($full_line =~ /$success_line/) {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400580 $booted = 1;
581 }
582
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400583 if ($full_line =~ /\[ backtrace testing \]/) {
584 $skip_call_trace = 1;
585 }
586
Steven Rostedt2545eb62010-11-02 15:01:32 -0400587 if ($full_line =~ /call trace:/i) {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400588 $bug = 1 if (!$skip_call_trace);
589 }
590
591 if ($full_line =~ /\[ end of backtrace testing \]/) {
592 $skip_call_trace = 0;
593 }
594
595 if ($full_line =~ /Kernel panic -/) {
Steven Rostedt2545eb62010-11-02 15:01:32 -0400596 $bug = 1;
597 }
598
599 if ($line =~ /\n/) {
600 $full_line = "";
601 }
602 }
603
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400604 close(DMESG);
Steven Rostedt2545eb62010-11-02 15:01:32 -0400605
Steven Rostedt2545eb62010-11-02 15:01:32 -0400606 if ($bug) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400607 return 0 if ($in_bisect);
Steven Rostedt576f6272010-11-02 14:58:38 -0400608 fail "failed - got a bug report" and return 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400609 }
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400610
Steven Rostedta75fece2010-11-02 14:58:27 -0400611 if (!$booted) {
612 return 0 if ($in_bisect);
Steven Rostedt576f6272010-11-02 14:58:38 -0400613 fail "failed - never got a boot prompt." and return 0;
Steven Rostedta75fece2010-11-02 14:58:27 -0400614 }
615
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400616 return 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400617}
618
619sub install {
620
Steven Rostedta75fece2010-11-02 14:58:27 -0400621 run_command "scp $outputdir/$build_target $target:$target_image" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400622 dodie "failed to copy image";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400623
624 my $install_mods = 0;
625
626 # should we process modules?
627 $install_mods = 0;
Steven Rostedt51ad1dd2010-11-08 16:43:21 -0500628 open(IN, "$output_config") or dodie("Can't read config file");
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400629 while (<IN>) {
630 if (/CONFIG_MODULES(=y)?/) {
631 $install_mods = 1 if (defined($1));
632 last;
633 }
634 }
635 close(IN);
636
637 if (!$install_mods) {
638 doprint "No modules needed\n";
639 return;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400640 }
641
Steven Rostedta75fece2010-11-02 14:58:27 -0400642 run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400643 dodie "Failed to install modules";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400644
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400645 my $modlib = "/lib/modules/$version";
Steven Rostedta57419b2010-11-02 15:13:54 -0400646 my $modtar = "ktest-mods.tar.bz2";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400647
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400648 run_command "ssh $target rm -rf $modlib" or
649 dodie "failed to remove old mods: $modlib";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400650
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400651 # would be nice if scp -r did not follow symbolic links
Steven Rostedta75fece2010-11-02 14:58:27 -0400652 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400653 dodie "making tarball";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400654
Steven Rostedta75fece2010-11-02 14:58:27 -0400655 run_command "scp $tmpdir/$modtar $target:/tmp" or
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400656 dodie "failed to copy modules";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400657
Steven Rostedta75fece2010-11-02 14:58:27 -0400658 unlink "$tmpdir/$modtar";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400659
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400660 run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or
661 dodie "failed to tar modules";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400662
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400663 run_command "ssh $target rm -f /tmp/$modtar";
Steven Rostedt8b37ca82010-11-02 14:58:33 -0400664
665 return if (!defined($post_install));
666
667 my $save_env = $ENV{KERNEL_VERSION};
668
669 $ENV{KERNEL_VERSION} = $version;
Steven Rostedt576f6272010-11-02 14:58:38 -0400670 run_command "$post_install" or
671 dodie "Failed to run post install";
Steven Rostedt8b37ca82010-11-02 14:58:33 -0400672
673 $ENV{KERNEL_VERSION} = $save_env;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400674}
675
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400676sub check_buildlog {
677 my ($patch) = @_;
678
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400679 my @files = `git show $patch | diffstat -l`;
680
681 open(IN, "git show $patch |") or
682 dodie "failed to show $patch";
683 while (<IN>) {
684 if (m,^--- a/(.*),) {
685 chomp $1;
686 $files[$#files] = $1;
687 }
688 }
689 close(IN);
690
691 open(IN, $buildlog) or dodie "Can't open $buildlog";
692 while (<IN>) {
693 if (/^\s*(.*?):.*(warning|error)/) {
694 my $err = $1;
695 foreach my $file (@files) {
Steven Rostedta75fece2010-11-02 14:58:27 -0400696 my $fullpath = "$builddir/$file";
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400697 if ($file eq $err || $fullpath eq $err) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400698 fail "$file built with warnings" and return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400699 }
700 }
701 }
702 }
703 close(IN);
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400704
705 return 1;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400706}
707
Steven Rostedt2545eb62010-11-02 15:01:32 -0400708sub build {
709 my ($type) = @_;
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400710 my $defconfig = "";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400711
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400712 unlink $buildlog;
713
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400714 if ($type =~ /^useconfig:(.*)/) {
Steven Rostedt51ad1dd2010-11-08 16:43:21 -0500715 run_command "cp $1 $output_config" or
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400716 dodie "could not copy $1 to .config";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400717
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400718 $type = "oldconfig";
719 }
720
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400721 # old config can ask questions
722 if ($type eq "oldconfig") {
Steven Rostedt9386c6a2010-11-08 16:35:48 -0500723 $type = "oldnoconfig";
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400724
725 # allow for empty configs
Steven Rostedt51ad1dd2010-11-08 16:43:21 -0500726 run_command "touch $output_config";
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400727
Steven Rostedt51ad1dd2010-11-08 16:43:21 -0500728 run_command "mv $output_config $outputdir/config_temp" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400729 dodie "moving .config";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400730
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400731 if (!$noclean && !run_command "$make mrproper") {
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400732 dodie "make mrproper";
733 }
734
Steven Rostedt51ad1dd2010-11-08 16:43:21 -0500735 run_command "mv $outputdir/config_temp $output_config" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400736 dodie "moving config_temp";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400737
738 } elsif (!$noclean) {
Steven Rostedt51ad1dd2010-11-08 16:43:21 -0500739 unlink "$output_config";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400740 run_command "$make mrproper" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400741 dodie "make mrproper";
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400742 }
Steven Rostedt2545eb62010-11-02 15:01:32 -0400743
744 # add something to distinguish this build
Steven Rostedta75fece2010-11-02 14:58:27 -0400745 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
746 print OUT "$localversion\n";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400747 close(OUT);
748
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400749 if (defined($minconfig)) {
750 $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400751 }
752
Steven Rostedt9386c6a2010-11-08 16:35:48 -0500753 run_command "$defconfig $make $type" or
Steven Rostedt5c42fc52010-11-02 14:57:01 -0400754 dodie "failed make config";
Steven Rostedt2545eb62010-11-02 15:01:32 -0400755
Steven Rostedta75fece2010-11-02 14:58:27 -0400756 $redirect = "$buildlog";
757 if (!run_command "$make $build_options") {
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400758 undef $redirect;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400759 # bisect may need this to pass
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400760 return 0 if ($in_bisect);
761 fail "failed build" and return 0;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400762 }
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -0400763 undef $redirect;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400764
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400765 return 1;
Steven Rostedt2545eb62010-11-02 15:01:32 -0400766}
767
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400768sub halt {
Steven Rostedta75fece2010-11-02 14:58:27 -0400769 if (!run_command "ssh $target halt" or defined($power_off)) {
Steven Rostedt576f6272010-11-02 14:58:38 -0400770 if (defined($poweroff_after_halt)) {
771 sleep $poweroff_after_halt;
772 run_command "$power_off";
773 }
774 } else {
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400775 # nope? the zap it!
Steven Rostedta75fece2010-11-02 14:58:27 -0400776 run_command "$power_off";
Steven Rostedt75c3fda72010-11-02 14:57:21 -0400777 }
778}
779
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400780sub success {
781 my ($i) = @_;
782
783 doprint "\n\n*******************************************\n";
784 doprint "*******************************************\n";
Steven Rostedta75fece2010-11-02 14:58:27 -0400785 doprint "** TEST $i SUCCESS!!!! **\n";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400786 doprint "*******************************************\n";
787 doprint "*******************************************\n";
788
Steven Rostedt576f6272010-11-02 14:58:38 -0400789 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
Steven Rostedta75fece2010-11-02 14:58:27 -0400790 doprint "Reboot and wait $sleep_time seconds\n";
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400791 reboot;
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400792 start_monitor;
Steven Rostedta75fece2010-11-02 14:58:27 -0400793 wait_for_monitor $sleep_time;
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400794 end_monitor;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400795 }
796}
797
798sub get_version {
799 # get the release name
800 doprint "$make kernelrelease ... ";
801 $version = `$make kernelrelease | tail -1`;
802 chomp($version);
803 doprint "$version\n";
804}
805
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400806sub child_run_test {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400807 my $failed = 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400808
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400809 # child should have no power
Steven Rostedta75fece2010-11-02 14:58:27 -0400810 $reboot_on_error = 0;
811 $poweroff_on_error = 0;
812 $die_on_failure = 1;
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400813
814 run_command $run_test or $failed = 1;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400815 exit $failed;
816}
817
818my $child_done;
819
820sub child_finished {
821 $child_done = 1;
822}
823
824sub do_run_test {
825 my $child_pid;
826 my $child_exit;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400827 my $line;
828 my $full_line;
829 my $bug = 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400830
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400831 wait_for_monitor 1;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400832
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400833 doprint "run test $run_test\n";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400834
835 $child_done = 0;
836
837 $SIG{CHLD} = qw(child_finished);
838
839 $child_pid = fork;
840
841 child_run_test if (!$child_pid);
842
843 $full_line = "";
844
845 do {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400846 $line = wait_for_input($monitor_fp, 1);
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400847 if (defined($line)) {
848
849 # we are not guaranteed to get a full line
850 $full_line .= $line;
851
852 if ($full_line =~ /call trace:/i) {
853 $bug = 1;
854 }
855
856 if ($full_line =~ /Kernel panic -/) {
857 $bug = 1;
858 }
859
860 if ($line =~ /\n/) {
861 $full_line = "";
862 }
863 }
864 } while (!$child_done && !$bug);
865
866 if ($bug) {
867 doprint "Detected kernel crash!\n";
868 # kill the child with extreme prejudice
869 kill 9, $child_pid;
870 }
871
872 waitpid $child_pid, 0;
873 $child_exit = $?;
874
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400875 if ($bug || $child_exit) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400876 return 0 if $in_bisect;
877 fail "test failed" and return 0;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400878 }
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400879 return 1;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400880}
881
Steven Rostedta75fece2010-11-02 14:58:27 -0400882sub run_git_bisect {
883 my ($command) = @_;
884
885 doprint "$command ... ";
886
887 my $output = `$command 2>&1`;
888 my $ret = $?;
889
890 logit $output;
891
892 if ($ret) {
893 doprint "FAILED\n";
894 dodie "Failed to git bisect";
895 }
896
897 doprint "SUCCESS\n";
898 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
899 doprint "$1 [$2]\n";
900 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
901 $bisect_bad = $1;
902 doprint "Found bad commit... $1\n";
903 return 0;
904 } else {
905 # we already logged it, just print it now.
906 print $output;
907 }
908
909 return 1;
910}
911
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400912sub run_bisect {
913 my ($type) = @_;
914
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400915 my $failed = 0;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400916 my $result;
917 my $output;
918 my $ret;
919
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400920 if (defined($minconfig)) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400921 build "useconfig:$minconfig" or $failed = 1;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400922 } else {
923 # ?? no config to use?
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400924 build "oldconfig" or $failed = 1;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400925 }
926
927 if ($type ne "build") {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400928 dodie "Failed on build" if $failed;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400929
930 # Now boot the box
931 get_grub_index;
932 get_version;
933 install;
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400934
935 start_monitor;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400936 monitor or $failed = 1;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400937
938 if ($type ne "boot") {
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400939 dodie "Failed on boot" if $failed;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400940
Steven Rostedt2b7d9b22010-11-02 14:58:15 -0400941 do_run_test or $failed = 1;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400942 }
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400943 end_monitor;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400944 }
945
946 if ($failed) {
947 $result = "bad";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400948
949 # reboot the box to a good kernel
Steven Rostedta75fece2010-11-02 14:58:27 -0400950 if ($type ne "build") {
951 doprint "Reboot and sleep $bisect_sleep_time seconds\n";
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400952 reboot;
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400953 start_monitor;
Steven Rostedta75fece2010-11-02 14:58:27 -0400954 wait_for_monitor $bisect_sleep_time;
Steven Rostedt7faafbd2010-11-02 14:58:22 -0400955 end_monitor;
Steven Rostedt5a391fb2010-11-02 14:57:43 -0400956 }
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400957 } else {
958 $result = "good";
959 }
960
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400961 # Are we looking for where it worked, not failed?
962 if ($reverse_bisect) {
963 if ($failed) {
964 $result = "good";
965 } else {
966 $result = "bad";
967 }
968 }
969
Steven Rostedta75fece2010-11-02 14:58:27 -0400970 return $result;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400971}
972
973sub bisect {
974 my ($i) = @_;
975
976 my $result;
977
978 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
979 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
980 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
981
982 my $good = $opt{"BISECT_GOOD[$i]"};
983 my $bad = $opt{"BISECT_BAD[$i]"};
984 my $type = $opt{"BISECT_TYPE[$i]"};
Steven Rostedta75fece2010-11-02 14:58:27 -0400985 my $start = $opt{"BISECT_START[$i]"};
986 my $replay = $opt{"BISECT_REPLAY[$i]"};
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -0400987
Steven Rostedta57419b2010-11-02 15:13:54 -0400988 # convert to true sha1's
989 $good = get_sha1($good);
990 $bad = get_sha1($bad);
991
Steven Rostedtd6ce2a02010-11-02 14:58:05 -0400992 if (defined($opt{"BISECT_REVERSE[$i]"}) &&
993 $opt{"BISECT_REVERSE[$i]"} == 1) {
994 doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
995 $reverse_bisect = 1;
996 } else {
997 $reverse_bisect = 0;
998 }
999
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -04001000 $in_bisect = 1;
1001
Steven Rostedt5a391fb2010-11-02 14:57:43 -04001002 # Can't have a test without having a test to run
1003 if ($type eq "test" && !defined($run_test)) {
1004 $type = "boot";
1005 }
1006
Steven Rostedta75fece2010-11-02 14:58:27 -04001007 my $check = $opt{"BISECT_CHECK[$i]"};
1008 if (defined($check) && $check ne "0") {
1009
1010 # get current HEAD
Steven Rostedta57419b2010-11-02 15:13:54 -04001011 my $head = get_sha1("HEAD");
Steven Rostedta75fece2010-11-02 14:58:27 -04001012
1013 if ($check ne "good") {
1014 doprint "TESTING BISECT BAD [$bad]\n";
1015 run_command "git checkout $bad" or
1016 die "Failed to checkout $bad";
1017
1018 $result = run_bisect $type;
1019
1020 if ($result ne "bad") {
1021 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
1022 }
1023 }
1024
1025 if ($check ne "bad") {
1026 doprint "TESTING BISECT GOOD [$good]\n";
1027 run_command "git checkout $good" or
1028 die "Failed to checkout $good";
1029
1030 $result = run_bisect $type;
1031
1032 if ($result ne "good") {
1033 fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
1034 }
1035 }
1036
1037 # checkout where we started
1038 run_command "git checkout $head" or
1039 die "Failed to checkout $head";
1040 }
1041
1042 run_command "git bisect start" or
1043 dodie "could not start bisect";
1044
1045 run_command "git bisect good $good" or
1046 dodie "could not set bisect good to $good";
1047
1048 run_git_bisect "git bisect bad $bad" or
1049 dodie "could not set bisect bad to $bad";
1050
1051 if (defined($replay)) {
1052 run_command "git bisect replay $replay" or
1053 dodie "failed to run replay";
1054 }
1055
1056 if (defined($start)) {
1057 run_command "git checkout $start" or
1058 dodie "failed to checkout $start";
1059 }
1060
1061 my $test;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -04001062 do {
1063 $result = run_bisect $type;
Steven Rostedta75fece2010-11-02 14:58:27 -04001064 $test = run_git_bisect "git bisect $result";
1065 } while ($test);
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -04001066
1067 run_command "git bisect log" or
1068 dodie "could not capture git bisect log";
1069
1070 run_command "git bisect reset" or
1071 dodie "could not reset git bisect";
1072
1073 doprint "Bad commit was [$bisect_bad]\n";
1074
1075 $in_bisect = 0;
1076
1077 success $i;
1078}
1079
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -04001080sub patchcheck {
1081 my ($i) = @_;
1082
1083 die "PATCHCHECK_START[$i] not defined\n"
1084 if (!defined($opt{"PATCHCHECK_START[$i]"}));
1085 die "PATCHCHECK_TYPE[$i] not defined\n"
1086 if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
1087
1088 my $start = $opt{"PATCHCHECK_START[$i]"};
1089
1090 my $end = "HEAD";
1091 if (defined($opt{"PATCHCHECK_END[$i]"})) {
1092 $end = $opt{"PATCHCHECK_END[$i]"};
1093 }
1094
Steven Rostedta57419b2010-11-02 15:13:54 -04001095 # Get the true sha1's since we can use things like HEAD~3
1096 $start = get_sha1($start);
1097 $end = get_sha1($end);
1098
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -04001099 my $type = $opt{"PATCHCHECK_TYPE[$i]"};
1100
1101 # Can't have a test without having a test to run
1102 if ($type eq "test" && !defined($run_test)) {
1103 $type = "boot";
1104 }
1105
1106 open (IN, "git log --pretty=oneline $end|") or
1107 dodie "could not get git list";
1108
1109 my @list;
1110
1111 while (<IN>) {
1112 chomp;
1113 $list[$#list+1] = $_;
1114 last if (/^$start/);
1115 }
1116 close(IN);
1117
1118 if ($list[$#list] !~ /^$start/) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -04001119 fail "SHA1 $start not found";
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -04001120 }
1121
1122 # go backwards in the list
1123 @list = reverse @list;
1124
1125 my $save_clean = $noclean;
1126
1127 $in_patchcheck = 1;
1128 foreach my $item (@list) {
1129 my $sha1 = $item;
1130 $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
1131
1132 doprint "\nProcessing commit $item\n\n";
1133
1134 run_command "git checkout $sha1" or
1135 die "Failed to checkout $sha1";
1136
1137 # only clean on the first and last patch
1138 if ($item eq $list[0] ||
1139 $item eq $list[$#list]) {
1140 $noclean = $save_clean;
1141 } else {
1142 $noclean = 1;
1143 }
1144
1145 if (defined($minconfig)) {
Steven Rostedt2b7d9b22010-11-02 14:58:15 -04001146 build "useconfig:$minconfig" or return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -04001147 } else {
1148 # ?? no config to use?
Steven Rostedt2b7d9b22010-11-02 14:58:15 -04001149 build "oldconfig" or return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -04001150 }
1151
Steven Rostedt2b7d9b22010-11-02 14:58:15 -04001152 check_buildlog $sha1 or return 0;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -04001153
1154 next if ($type eq "build");
1155
1156 get_grub_index;
1157 get_version;
1158 install;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -04001159
Steven Rostedt7faafbd2010-11-02 14:58:22 -04001160 my $failed = 0;
1161
1162 start_monitor;
1163 monitor or $failed = 1;
1164
1165 if (!$failed && $type ne "boot"){
1166 do_run_test or $failed = 1;
1167 }
1168 end_monitor;
1169 return 0 if ($failed);
1170
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -04001171 }
1172 $in_patchcheck = 0;
1173 success $i;
Steven Rostedt2b7d9b22010-11-02 14:58:15 -04001174
1175 return 1;
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -04001176}
1177
Steven Rostedt2545eb62010-11-02 15:01:32 -04001178read_config $ARGV[0];
1179
1180# mandatory configs
1181die "MACHINE not defined\n" if (!defined($opt{"MACHINE"}));
1182die "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"}));
1183die "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"}));
1184die "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"}));
1185die "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"}));
Steven Rostedt75c3fda72010-11-02 14:57:21 -04001186die "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"}));
Steven Rostedt2545eb62010-11-02 15:01:32 -04001187die "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"}));
1188die "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"}));
1189die "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"}));
Steven Rostedt2545eb62010-11-02 15:01:32 -04001190
Steven Rostedt2b7d9b22010-11-02 14:58:15 -04001191if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
1192 unlink $opt{"LOG_FILE"};
1193}
Steven Rostedt2545eb62010-11-02 15:01:32 -04001194
Steven Rostedt2b7d9b22010-11-02 14:58:15 -04001195doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
1196
Steven Rostedta57419b2010-11-02 15:13:54 -04001197for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
1198
1199 if (!$i) {
1200 doprint "DEFAULT OPTIONS:\n";
1201 } else {
1202 doprint "\nTEST $i OPTIONS";
1203 if (defined($repeat_tests{$i})) {
1204 $repeat = $repeat_tests{$i};
1205 doprint " ITERATE $repeat";
1206 }
1207 doprint "\n";
1208 }
1209
1210 foreach my $option (sort keys %opt) {
1211
1212 if ($option =~ /\[(\d+)\]$/) {
1213 next if ($i != $1);
1214 } else {
1215 next if ($i);
1216 }
1217
1218 doprint "$option = $opt{$option}\n";
1219 }
Steven Rostedt2b7d9b22010-11-02 14:58:15 -04001220}
Steven Rostedt2545eb62010-11-02 15:01:32 -04001221
Steven Rostedta75fece2010-11-02 14:58:27 -04001222sub set_test_option {
Steven Rostedt5a391fb2010-11-02 14:57:43 -04001223 my ($name, $i) = @_;
1224
1225 my $option = "$name\[$i\]";
1226
1227 if (defined($opt{$option})) {
1228 return $opt{$option};
1229 }
1230
Steven Rostedta57419b2010-11-02 15:13:54 -04001231 foreach my $test (keys %repeat_tests) {
1232 if ($i >= $test &&
1233 $i < $test + $repeat_tests{$test}) {
1234 $option = "$name\[$test\]";
1235 if (defined($opt{$option})) {
1236 return $opt{$option};
1237 }
1238 }
1239 }
1240
Steven Rostedt5a391fb2010-11-02 14:57:43 -04001241 if (defined($opt{$name})) {
1242 return $opt{$name};
1243 }
1244
1245 return undef;
1246}
1247
Steven Rostedt2545eb62010-11-02 15:01:32 -04001248# First we need to do is the builds
Steven Rostedta75fece2010-11-02 14:58:27 -04001249for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
Steven Rostedt2545eb62010-11-02 15:01:32 -04001250
Steven Rostedt576f6272010-11-02 14:58:38 -04001251 $iteration = $i;
1252
Steven Rostedta75fece2010-11-02 14:58:27 -04001253 my $ssh_user = set_test_option("SSH_USER", $i);
1254 my $makecmd = set_test_option("MAKE_CMD", $i);
1255
1256 $machine = set_test_option("MACHINE", $i);
1257 $tmpdir = set_test_option("TMP_DIR", $i);
1258 $outputdir = set_test_option("OUTPUT_DIR", $i);
1259 $builddir = set_test_option("BUILD_DIR", $i);
1260 $test_type = set_test_option("TEST_TYPE", $i);
1261 $build_type = set_test_option("BUILD_TYPE", $i);
1262 $build_options = set_test_option("BUILD_OPTIONS", $i);
1263 $power_cycle = set_test_option("POWER_CYCLE", $i);
1264 $noclean = set_test_option("BUILD_NOCLEAN", $i);
1265 $minconfig = set_test_option("MIN_CONFIG", $i);
1266 $run_test = set_test_option("TEST", $i);
1267 $addconfig = set_test_option("ADD_CONFIG", $i);
1268 $reboot_type = set_test_option("REBOOT_TYPE", $i);
1269 $grub_menu = set_test_option("GRUB_MENU", $i);
Steven Rostedt8b37ca82010-11-02 14:58:33 -04001270 $post_install = set_test_option("POST_INSTALL", $i);
Steven Rostedta75fece2010-11-02 14:58:27 -04001271 $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
1272 $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
1273 $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
1274 $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
1275 $power_off = set_test_option("POWER_OFF", $i);
Steven Rostedt576f6272010-11-02 14:58:38 -04001276 $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
1277 $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
Steven Rostedta75fece2010-11-02 14:58:27 -04001278 $sleep_time = set_test_option("SLEEP_TIME", $i);
1279 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
1280 $store_failures = set_test_option("STORE_FAILURES", $i);
1281 $timeout = set_test_option("TIMEOUT", $i);
1282 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
1283 $console = set_test_option("CONSOLE", $i);
1284 $success_line = set_test_option("SUCCESS_LINE", $i);
1285 $build_target = set_test_option("BUILD_TARGET", $i);
1286 $target_image = set_test_option("TARGET_IMAGE", $i);
1287 $localversion = set_test_option("LOCALVERSION", $i);
1288
1289 chdir $builddir || die "can't change directory to $builddir";
1290
1291 if (!-d $tmpdir) {
1292 mkpath($tmpdir) or
1293 die "can't create $tmpdir";
1294 }
1295
1296 $target = "$ssh_user\@$machine";
1297
1298 $buildlog = "$tmpdir/buildlog-$machine";
1299 $dmesg = "$tmpdir/dmesg-$machine";
1300 $make = "$makecmd O=$outputdir";
Steven Rostedt51ad1dd2010-11-08 16:43:21 -05001301 $output_config = "$outputdir/.config";
Steven Rostedta75fece2010-11-02 14:58:27 -04001302
1303 if ($reboot_type eq "grub") {
Steven Rostedt576f6272010-11-02 14:58:38 -04001304 dodie "GRUB_MENU not defined" if (!defined($grub_menu));
Steven Rostedta75fece2010-11-02 14:58:27 -04001305 } elsif (!defined($reboot_script)) {
Steven Rostedt576f6272010-11-02 14:58:38 -04001306 dodie "REBOOT_SCRIPT not defined"
Steven Rostedta75fece2010-11-02 14:58:27 -04001307 }
1308
1309 my $run_type = $build_type;
1310 if ($test_type eq "patchcheck") {
1311 $run_type = $opt{"PATCHCHECK_TYPE[$i]"};
1312 } elsif ($test_type eq "bisect") {
1313 $run_type = $opt{"BISECT_TYPE[$i]"};
1314 }
1315
1316 # mistake in config file?
1317 if (!defined($run_type)) {
1318 $run_type = "ERROR";
1319 }
Steven Rostedt2545eb62010-11-02 15:01:32 -04001320
1321 doprint "\n\n";
Steven Rostedta75fece2010-11-02 14:58:27 -04001322 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
Steven Rostedt7faafbd2010-11-02 14:58:22 -04001323
1324 unlink $dmesg;
1325 unlink $buildlog;
Steven Rostedt2545eb62010-11-02 15:01:32 -04001326
Steven Rostedt2b7d9b22010-11-02 14:58:15 -04001327 if (!defined($minconfig)) {
1328 $minconfig = $addconfig;
1329
1330 } elsif (defined($addconfig)) {
Steven Rostedta75fece2010-11-02 14:58:27 -04001331 run_command "cat $addconfig $minconfig > $tmpdir/use_config" or
Steven Rostedt2b7d9b22010-11-02 14:58:15 -04001332 dodie "Failed to create temp config";
Steven Rostedta75fece2010-11-02 14:58:27 -04001333 $minconfig = "$tmpdir/use_config";
Steven Rostedt2b7d9b22010-11-02 14:58:15 -04001334 }
1335
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -04001336 my $checkout = $opt{"CHECKOUT[$i]"};
1337 if (defined($checkout)) {
1338 run_command "git checkout $checkout" or
1339 die "failed to checkout $checkout";
1340 }
1341
Steven Rostedta75fece2010-11-02 14:58:27 -04001342 if ($test_type eq "bisect") {
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -04001343 bisect $i;
1344 next;
Steven Rostedta75fece2010-11-02 14:58:27 -04001345 } elsif ($test_type eq "patchcheck") {
Steven Rostedt6c5ee0b2010-11-02 14:57:58 -04001346 patchcheck $i;
1347 next;
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -04001348 }
1349
Steven Rostedt7faafbd2010-11-02 14:58:22 -04001350 if ($build_type ne "nobuild") {
1351 build $build_type or next;
Steven Rostedt2545eb62010-11-02 15:01:32 -04001352 }
1353
Steven Rostedta75fece2010-11-02 14:58:27 -04001354 if ($test_type ne "build") {
1355 get_grub_index;
1356 get_version;
1357 install;
Steven Rostedt5a391fb2010-11-02 14:57:43 -04001358
Steven Rostedta75fece2010-11-02 14:58:27 -04001359 my $failed = 0;
1360 start_monitor;
1361 monitor or $failed = 1;;
1362
1363 if (!$failed && $test_type ne "boot" && defined($run_test)) {
1364 do_run_test or $failed = 1;
1365 }
1366 end_monitor;
1367 next if ($failed);
Steven Rostedt5a391fb2010-11-02 14:57:43 -04001368 }
1369
Steven Rostedt5f9b6ce2010-11-02 14:57:33 -04001370 success $i;
Steven Rostedt2545eb62010-11-02 15:01:32 -04001371}
1372
Steven Rostedt5c42fc52010-11-02 14:57:01 -04001373if ($opt{"POWEROFF_ON_SUCCESS"}) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -04001374 halt;
Steven Rostedt576f6272010-11-02 14:58:38 -04001375} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
Steven Rostedt75c3fda72010-11-02 14:57:21 -04001376 reboot;
Steven Rostedt5c42fc52010-11-02 14:57:01 -04001377}
Steven Rostedt75c3fda72010-11-02 14:57:21 -04001378
Steven Rostedt2545eb62010-11-02 15:01:32 -04001379exit 0;