ktest: Add poweroff after halt and powercycle after reboot
[deliverable/linux.git] / tools / testing / ktest / ktest.pl
CommitLineData
2545eb61 1#!/usr/bin/perl -w
d6ce2a0b
SR
2#
3# Copywrite 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
4# Licensed under the terms of the GNU GPL License version 2
5#
2545eb61
SR
6
7use strict;
8use IPC::Open2;
9use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
7faafbd6
SR
10use File::Path qw(mkpath);
11use File::Copy qw(cp);
2545eb61
SR
12use FileHandle;
13
14$#ARGV >= 0 || die "usage: autotest.pl config-file\n";
15
16$| = 1;
17
18my %opt;
a75fecec 19my %default;
2545eb61
SR
20
21#default opts
a75fecec
SR
22$default{"NUM_TESTS"} = 5;
23$default{"REBOOT_TYPE"} = "grub";
24$default{"TEST_TYPE"} = "test";
25$default{"BUILD_TYPE"} = "randconfig";
26$default{"MAKE_CMD"} = "make";
27$default{"TIMEOUT"} = 120;
28$default{"TMP_DIR"} = "/tmp/autotest";
29$default{"SLEEP_TIME"} = 60; # sleep time between tests
30$default{"BUILD_NOCLEAN"} = 0;
31$default{"REBOOT_ON_ERROR"} = 0;
32$default{"POWEROFF_ON_ERROR"} = 0;
33$default{"REBOOT_ON_SUCCESS"} = 1;
34$default{"POWEROFF_ON_SUCCESS"} = 0;
35$default{"BUILD_OPTIONS"} = "";
36$default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects
37$default{"CLEAR_LOG"} = 0;
38$default{"SUCCESS_LINE"} = "login:";
39$default{"BOOTED_TIMEOUT"} = 1;
40$default{"DIE_ON_FAILURE"} = 1;
2545eb61
SR
41
42my $version;
a75fecec
SR
43my $machine;
44my $tmpdir;
45my $builddir;
46my $outputdir;
47my $test_type;
7faafbd6 48my $build_type;
a75fecec
SR
49my $build_options;
50my $reboot_type;
51my $reboot_script;
52my $power_cycle;
53my $reboot_on_error;
54my $poweroff_on_error;
55my $die_on_failure;
576f627c
SR
56my $powercycle_after_reboot;
57my $poweroff_after_halt;
a75fecec
SR
58my $power_off;
59my $grub_menu;
2545eb61
SR
60my $grub_number;
61my $target;
62my $make;
8b37ca8c 63my $post_install;
5c42fc5b 64my $noclean;
5f9b6ced 65my $minconfig;
2b7d9b21 66my $addconfig;
5f9b6ced
SR
67my $in_bisect = 0;
68my $bisect_bad = "";
d6ce2a0b 69my $reverse_bisect;
6c5ee0be 70my $in_patchcheck = 0;
5a391fbf 71my $run_test;
6c5ee0be 72my $redirect;
7faafbd6
SR
73my $buildlog;
74my $dmesg;
75my $monitor_fp;
76my $monitor_pid;
77my $monitor_cnt = 0;
a75fecec
SR
78my $sleep_time;
79my $bisect_sleep_time;
80my $store_failures;
81my $timeout;
82my $booted_timeout;
83my $console;
84my $success_line;
85my $build_target;
86my $target_image;
87my $localversion;
576f627c 88my $iteration = 0;
2545eb61
SR
89
90sub read_config {
91 my ($config) = @_;
92
93 open(IN, $config) || die "can't read file $config";
94
95 while (<IN>) {
96
97 # ignore blank lines and comments
98 next if (/^\s*$/ || /\s*\#/);
99
100 if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) {
101 my $lvalue = $1;
102 my $rvalue = $2;
103
a75fecec
SR
104 if (defined($opt{$lvalue})) {
105 die "Error: Option $lvalue defined more than once!\n";
106 }
2545eb61
SR
107 $opt{$lvalue} = $rvalue;
108 }
109 }
110
111 close(IN);
a75fecec
SR
112
113 # set any defaults
114
115 foreach my $default (keys %default) {
116 if (!defined($opt{$default})) {
117 $opt{$default} = $default{$default};
118 }
119 }
2545eb61
SR
120}
121
5f9b6ced 122sub logit {
2545eb61
SR
123 if (defined($opt{"LOG_FILE"})) {
124 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
125 print OUT @_;
126 close(OUT);
127 }
128}
129
5f9b6ced
SR
130sub doprint {
131 print @_;
132 logit @_;
133}
134
7faafbd6
SR
135sub run_command;
136
137sub reboot {
138 # try to reboot normally
576f627c
SR
139 if (run_command "ssh $target reboot") {
140 if (defined($powercycle_after_reboot)) {
141 sleep $powercycle_after_reboot;
142 run_command "$power_cycle";
143 }
144 } else {
7faafbd6 145 # nope? power cycle it.
a75fecec 146 run_command "$power_cycle";
7faafbd6
SR
147 }
148}
149
576f627c
SR
150sub do_not_reboot {
151 my $i = $iteration;
152
153 return $test_type eq "build" ||
154 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
155 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
156}
157
5c42fc5b 158sub dodie {
5a391fbf 159 doprint "CRITICAL FAILURE... ", @_, "\n";
5c42fc5b 160
576f627c
SR
161 my $i = $iteration;
162
163 if ($reboot_on_error && !do_not_reboot) {
164
75c3fda7 165 doprint "REBOOTING\n";
7faafbd6 166 reboot;
75c3fda7 167
a75fecec 168 } elsif ($poweroff_on_error && defined($power_off)) {
5c42fc5b 169 doprint "POWERING OFF\n";
a75fecec 170 `$power_off`;
5c42fc5b 171 }
75c3fda7 172
576f627c 173 die @_, "\n";
5c42fc5b
SR
174}
175
7faafbd6
SR
176sub open_console {
177 my ($fp) = @_;
178
179 my $flags;
180
a75fecec
SR
181 my $pid = open($fp, "$console|") or
182 dodie "Can't open console $console";
7faafbd6
SR
183
184 $flags = fcntl($fp, F_GETFL, 0) or
576f627c 185 dodie "Can't get flags for the socket: $!";
7faafbd6 186 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
576f627c 187 dodie "Can't set flags for the socket: $!";
7faafbd6
SR
188
189 return $pid;
190}
191
192sub close_console {
193 my ($fp, $pid) = @_;
194
195 doprint "kill child process $pid\n";
196 kill 2, $pid;
197
198 print "closing!\n";
199 close($fp);
200}
201
202sub start_monitor {
203 if ($monitor_cnt++) {
204 return;
205 }
206 $monitor_fp = \*MONFD;
207 $monitor_pid = open_console $monitor_fp;
a75fecec
SR
208
209 return;
210
211 open(MONFD, "Stop perl from warning about single use of MONFD");
7faafbd6
SR
212}
213
214sub end_monitor {
215 if (--$monitor_cnt) {
216 return;
217 }
218 close_console($monitor_fp, $monitor_pid);
219}
220
221sub wait_for_monitor {
222 my ($time) = @_;
223 my $line;
224
a75fecec 225 doprint "** Wait for monitor to settle down **\n";
7faafbd6
SR
226
227 # read the monitor and wait for the system to calm down
228 do {
229 $line = wait_for_input($monitor_fp, $time);
a75fecec 230 print "$line" if (defined($line));
7faafbd6 231 } while (defined($line));
a75fecec 232 print "** Monitor flushed **\n";
7faafbd6
SR
233}
234
2b7d9b21
SR
235sub fail {
236
a75fecec 237 if ($die_on_failure) {
2b7d9b21
SR
238 dodie @_;
239 }
240
a75fecec 241 doprint "FAILED\n";
7faafbd6 242
576f627c
SR
243 my $i = $iteration;
244
a75fecec 245 # no need to reboot for just building.
576f627c 246 if (!do_not_reboot) {
a75fecec
SR
247 doprint "REBOOTING\n";
248 reboot;
249 start_monitor;
250 wait_for_monitor $sleep_time;
251 end_monitor;
252 }
7faafbd6 253
576f627c
SR
254 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
255 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
a75fecec 256 doprint "**** Failed: ", @_, " ****\n";
576f627c
SR
257 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
258 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
a75fecec
SR
259
260 return 1 if (!defined($store_failures));
7faafbd6
SR
261
262 my @t = localtime;
263 my $date = sprintf "%04d%02d%02d%02d%02d%02d",
264 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
265
a75fecec
SR
266 my $dir = "$machine-$test_type-$build_type-fail-$date";
267 my $faildir = "$store_failures/$dir";
7faafbd6
SR
268
269 if (!-d $faildir) {
270 mkpath($faildir) or
a75fecec 271 die "can't create $faildir";
7faafbd6 272 }
a75fecec
SR
273 if (-f "$outputdir/.config") {
274 cp "$outputdir/.config", "$faildir/config" or
7faafbd6
SR
275 die "failed to copy .config";
276 }
277 if (-f $buildlog) {
278 cp $buildlog, "$faildir/buildlog" or
279 die "failed to move $buildlog";
280 }
281 if (-f $dmesg) {
282 cp $dmesg, "$faildir/dmesg" or
283 die "failed to move $dmesg";
284 }
285
286 doprint "*** Saved info to $faildir ***\n";
287
2b7d9b21
SR
288 return 1;
289}
290
2545eb61
SR
291sub run_command {
292 my ($command) = @_;
d6ce2a0b
SR
293 my $dolog = 0;
294 my $dord = 0;
295 my $pid;
296
297 doprint("$command ... ");
298
299 $pid = open(CMD, "$command 2>&1 |") or
2b7d9b21 300 (fail "unable to exec $command" and return 0);
2545eb61
SR
301
302 if (defined($opt{"LOG_FILE"})) {
d6ce2a0b
SR
303 open(LOG, ">>$opt{LOG_FILE}") or
304 dodie "failed to write to log";
305 $dolog = 1;
6c5ee0be
SR
306 }
307
308 if (defined($redirect)) {
d6ce2a0b
SR
309 open (RD, ">$redirect") or
310 dodie "failed to write to redirect $redirect";
311 $dord = 1;
2545eb61
SR
312 }
313
d6ce2a0b
SR
314 while (<CMD>) {
315 print LOG if ($dolog);
316 print RD if ($dord);
317 }
2545eb61 318
d6ce2a0b 319 waitpid($pid, 0);
2545eb61
SR
320 my $failed = $?;
321
d6ce2a0b
SR
322 close(CMD);
323 close(LOG) if ($dolog);
324 close(RD) if ($dord);
325
2545eb61
SR
326 if ($failed) {
327 doprint "FAILED!\n";
328 } else {
329 doprint "SUCCESS\n";
330 }
331
5f9b6ced
SR
332 return !$failed;
333}
334
335sub get_grub_index {
336
a75fecec
SR
337 if ($reboot_type ne "grub") {
338 return;
339 }
5a391fbf 340 return if (defined($grub_number));
5f9b6ced
SR
341
342 doprint "Find grub menu ... ";
343 $grub_number = -1;
344 open(IN, "ssh $target cat /boot/grub/menu.lst |")
345 or die "unable to get menu.lst";
346 while (<IN>) {
a75fecec 347 if (/^\s*title\s+$grub_menu\s*$/) {
5f9b6ced
SR
348 $grub_number++;
349 last;
350 } elsif (/^\s*title\s/) {
351 $grub_number++;
352 }
353 }
354 close(IN);
355
a75fecec 356 die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
5f9b6ced
SR
357 if ($grub_number < 0);
358 doprint "$grub_number\n";
2545eb61
SR
359}
360
2545eb61
SR
361sub wait_for_input
362{
363 my ($fp, $time) = @_;
364 my $rin;
365 my $ready;
366 my $line;
367 my $ch;
368
369 if (!defined($time)) {
370 $time = $timeout;
371 }
372
373 $rin = '';
374 vec($rin, fileno($fp), 1) = 1;
375 $ready = select($rin, undef, undef, $time);
376
377 $line = "";
378
379 # try to read one char at a time
380 while (sysread $fp, $ch, 1) {
381 $line .= $ch;
382 last if ($ch eq "\n");
383 }
384
385 if (!length($line)) {
386 return undef;
387 }
388
389 return $line;
390}
391
75c3fda7 392sub reboot_to {
a75fecec
SR
393 if ($reboot_type eq "grub") {
394 run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
395 return;
396 }
397
398 run_command "$reboot_script";
2545eb61
SR
399}
400
5a391fbf 401sub monitor {
2545eb61
SR
402 my $booted = 0;
403 my $bug = 0;
5c42fc5b 404 my $skip_call_trace = 0;
2b7d9b21 405 my $loops;
2545eb61 406
7faafbd6 407 wait_for_monitor 5;
2545eb61
SR
408
409 my $line;
410 my $full_line = "";
411
7faafbd6
SR
412 open(DMESG, "> $dmesg") or
413 die "unable to write to $dmesg";
2545eb61 414
75c3fda7 415 reboot_to;
2545eb61
SR
416
417 for (;;) {
418
2b7d9b21 419 if ($booted) {
a75fecec 420 $line = wait_for_input($monitor_fp, $booted_timeout);
2b7d9b21 421 } else {
7faafbd6 422 $line = wait_for_input($monitor_fp);
2b7d9b21 423 }
2545eb61
SR
424
425 last if (!defined($line));
426
427 doprint $line;
7faafbd6 428 print DMESG $line;
2545eb61
SR
429
430 # we are not guaranteed to get a full line
431 $full_line .= $line;
432
a75fecec 433 if ($full_line =~ /$success_line/) {
2545eb61
SR
434 $booted = 1;
435 }
436
5c42fc5b
SR
437 if ($full_line =~ /\[ backtrace testing \]/) {
438 $skip_call_trace = 1;
439 }
440
2545eb61 441 if ($full_line =~ /call trace:/i) {
5c42fc5b
SR
442 $bug = 1 if (!$skip_call_trace);
443 }
444
445 if ($full_line =~ /\[ end of backtrace testing \]/) {
446 $skip_call_trace = 0;
447 }
448
449 if ($full_line =~ /Kernel panic -/) {
2545eb61
SR
450 $bug = 1;
451 }
452
453 if ($line =~ /\n/) {
454 $full_line = "";
455 }
456 }
457
7faafbd6 458 close(DMESG);
2545eb61 459
a75fecec 460 if ($bug) {
2b7d9b21 461 return 0 if ($in_bisect);
576f627c 462 fail "failed - got a bug report" and return 0;
2545eb61
SR
463 }
464
a75fecec 465 if (!$booted) {
2b7d9b21 466 return 0 if ($in_bisect);
576f627c 467 fail "failed - never got a boot prompt." and return 0;
2545eb61 468 }
5f9b6ced 469
2b7d9b21 470 return 1;
2545eb61
SR
471}
472
473sub install {
474
a75fecec 475 run_command "scp $outputdir/$build_target $target:$target_image" or
5c42fc5b 476 dodie "failed to copy image";
2545eb61 477
5f9b6ced 478 my $install_mods = 0;
2545eb61 479
5f9b6ced
SR
480 # should we process modules?
481 $install_mods = 0;
a75fecec 482 open(IN, "$outputdir/.config") or dodie("Can't read config file");
5f9b6ced
SR
483 while (<IN>) {
484 if (/CONFIG_MODULES(=y)?/) {
485 $install_mods = 1 if (defined($1));
486 last;
5c42fc5b 487 }
5f9b6ced
SR
488 }
489 close(IN);
5c42fc5b 490
5f9b6ced
SR
491 if (!$install_mods) {
492 doprint "No modules needed\n";
493 return;
494 }
2545eb61 495
a75fecec 496 run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
5f9b6ced 497 dodie "Failed to install modules";
5c42fc5b 498
5f9b6ced
SR
499 my $modlib = "/lib/modules/$version";
500 my $modtar = "autotest-mods.tar.bz2";
5c42fc5b 501
5f9b6ced
SR
502 run_command "ssh $target rm -rf $modlib" or
503 dodie "failed to remove old mods: $modlib";
5c42fc5b 504
5f9b6ced 505 # would be nice if scp -r did not follow symbolic links
a75fecec 506 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
5f9b6ced
SR
507 dodie "making tarball";
508
a75fecec 509 run_command "scp $tmpdir/$modtar $target:/tmp" or
5f9b6ced
SR
510 dodie "failed to copy modules";
511
a75fecec 512 unlink "$tmpdir/$modtar";
5f9b6ced
SR
513
514 run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or
515 dodie "failed to tar modules";
2545eb61 516
5f9b6ced 517 run_command "ssh $target rm -f /tmp/$modtar";
8b37ca8c
SR
518
519 return if (!defined($post_install));
520
521 my $save_env = $ENV{KERNEL_VERSION};
522
523 $ENV{KERNEL_VERSION} = $version;
576f627c
SR
524 run_command "$post_install" or
525 dodie "Failed to run post install";
8b37ca8c
SR
526
527 $ENV{KERNEL_VERSION} = $save_env;
2545eb61
SR
528}
529
6c5ee0be
SR
530sub check_buildlog {
531 my ($patch) = @_;
532
6c5ee0be
SR
533 my @files = `git show $patch | diffstat -l`;
534
535 open(IN, "git show $patch |") or
536 dodie "failed to show $patch";
537 while (<IN>) {
538 if (m,^--- a/(.*),) {
539 chomp $1;
540 $files[$#files] = $1;
541 }
542 }
543 close(IN);
544
545 open(IN, $buildlog) or dodie "Can't open $buildlog";
546 while (<IN>) {
547 if (/^\s*(.*?):.*(warning|error)/) {
548 my $err = $1;
549 foreach my $file (@files) {
a75fecec 550 my $fullpath = "$builddir/$file";
6c5ee0be 551 if ($file eq $err || $fullpath eq $err) {
2b7d9b21 552 fail "$file built with warnings" and return 0;
6c5ee0be
SR
553 }
554 }
555 }
556 }
557 close(IN);
2b7d9b21
SR
558
559 return 1;
6c5ee0be
SR
560}
561
2545eb61
SR
562sub build {
563 my ($type) = @_;
5c42fc5b
SR
564 my $defconfig = "";
565 my $append = "";
566
7faafbd6
SR
567 unlink $buildlog;
568
75c3fda7 569 if ($type =~ /^useconfig:(.*)/) {
a75fecec 570 run_command "cp $1 $outputdir/.config" or
75c3fda7 571 dodie "could not copy $1 to .config";
5f9b6ced 572
75c3fda7
SR
573 $type = "oldconfig";
574 }
575
5c42fc5b
SR
576 # old config can ask questions
577 if ($type eq "oldconfig") {
578 $append = "yes ''|";
75c3fda7
SR
579
580 # allow for empty configs
a75fecec 581 run_command "touch $outputdir/.config";
75c3fda7 582
a75fecec 583 run_command "mv $outputdir/.config $outputdir/config_temp" or
5c42fc5b 584 dodie "moving .config";
2545eb61 585
5f9b6ced 586 if (!$noclean && !run_command "$make mrproper") {
5c42fc5b
SR
587 dodie "make mrproper";
588 }
2545eb61 589
a75fecec 590 run_command "mv $outputdir/config_temp $outputdir/.config" or
5c42fc5b 591 dodie "moving config_temp";
5c42fc5b
SR
592
593 } elsif (!$noclean) {
a75fecec 594 unlink "$outputdir/.config";
5f9b6ced 595 run_command "$make mrproper" or
5c42fc5b 596 dodie "make mrproper";
5c42fc5b 597 }
2545eb61
SR
598
599 # add something to distinguish this build
a75fecec
SR
600 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
601 print OUT "$localversion\n";
2545eb61
SR
602 close(OUT);
603
5f9b6ced
SR
604 if (defined($minconfig)) {
605 $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
2545eb61
SR
606 }
607
a75fecec 608 run_command "$append $defconfig $make $type" or
5c42fc5b 609 dodie "failed make config";
2545eb61 610
a75fecec
SR
611 $redirect = "$buildlog";
612 if (!run_command "$make $build_options") {
6c5ee0be 613 undef $redirect;
5f9b6ced 614 # bisect may need this to pass
2b7d9b21
SR
615 return 0 if ($in_bisect);
616 fail "failed build" and return 0;
2545eb61 617 }
6c5ee0be 618 undef $redirect;
5f9b6ced 619
2b7d9b21 620 return 1;
2545eb61
SR
621}
622
75c3fda7 623sub halt {
a75fecec 624 if (!run_command "ssh $target halt" or defined($power_off)) {
576f627c
SR
625 if (defined($poweroff_after_halt)) {
626 sleep $poweroff_after_halt;
627 run_command "$power_off";
628 }
629 } else {
75c3fda7 630 # nope? the zap it!
a75fecec 631 run_command "$power_off";
75c3fda7
SR
632 }
633}
634
5f9b6ced
SR
635sub success {
636 my ($i) = @_;
637
638 doprint "\n\n*******************************************\n";
639 doprint "*******************************************\n";
a75fecec 640 doprint "** TEST $i SUCCESS!!!! **\n";
5f9b6ced
SR
641 doprint "*******************************************\n";
642 doprint "*******************************************\n";
643
576f627c 644 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
a75fecec 645 doprint "Reboot and wait $sleep_time seconds\n";
5f9b6ced 646 reboot;
7faafbd6 647 start_monitor;
a75fecec 648 wait_for_monitor $sleep_time;
7faafbd6 649 end_monitor;
5f9b6ced
SR
650 }
651}
652
653sub get_version {
654 # get the release name
655 doprint "$make kernelrelease ... ";
656 $version = `$make kernelrelease | tail -1`;
657 chomp($version);
658 doprint "$version\n";
659}
660
5a391fbf 661sub child_run_test {
7faafbd6 662 my $failed = 0;
5a391fbf 663
7faafbd6 664 # child should have no power
a75fecec
SR
665 $reboot_on_error = 0;
666 $poweroff_on_error = 0;
667 $die_on_failure = 1;
7faafbd6
SR
668
669 run_command $run_test or $failed = 1;
5a391fbf
SR
670 exit $failed;
671}
672
673my $child_done;
674
675sub child_finished {
676 $child_done = 1;
677}
678
679sub do_run_test {
680 my $child_pid;
681 my $child_exit;
5a391fbf
SR
682 my $line;
683 my $full_line;
684 my $bug = 0;
5a391fbf 685
7faafbd6 686 wait_for_monitor 1;
5a391fbf 687
7faafbd6 688 doprint "run test $run_test\n";
5a391fbf
SR
689
690 $child_done = 0;
691
692 $SIG{CHLD} = qw(child_finished);
693
694 $child_pid = fork;
695
696 child_run_test if (!$child_pid);
697
698 $full_line = "";
699
700 do {
7faafbd6 701 $line = wait_for_input($monitor_fp, 1);
5a391fbf
SR
702 if (defined($line)) {
703
704 # we are not guaranteed to get a full line
705 $full_line .= $line;
706
707 if ($full_line =~ /call trace:/i) {
708 $bug = 1;
709 }
710
711 if ($full_line =~ /Kernel panic -/) {
712 $bug = 1;
713 }
714
715 if ($line =~ /\n/) {
716 $full_line = "";
717 }
718 }
719 } while (!$child_done && !$bug);
720
721 if ($bug) {
722 doprint "Detected kernel crash!\n";
723 # kill the child with extreme prejudice
724 kill 9, $child_pid;
725 }
726
727 waitpid $child_pid, 0;
728 $child_exit = $?;
729
5a391fbf 730 if ($bug || $child_exit) {
2b7d9b21
SR
731 return 0 if $in_bisect;
732 fail "test failed" and return 0;
5a391fbf 733 }
2b7d9b21 734 return 1;
5a391fbf
SR
735}
736
a75fecec
SR
737sub run_git_bisect {
738 my ($command) = @_;
739
740 doprint "$command ... ";
741
742 my $output = `$command 2>&1`;
743 my $ret = $?;
744
745 logit $output;
746
747 if ($ret) {
748 doprint "FAILED\n";
749 dodie "Failed to git bisect";
750 }
751
752 doprint "SUCCESS\n";
753 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
754 doprint "$1 [$2]\n";
755 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
756 $bisect_bad = $1;
757 doprint "Found bad commit... $1\n";
758 return 0;
759 } else {
760 # we already logged it, just print it now.
761 print $output;
762 }
763
764 return 1;
765}
766
5f9b6ced
SR
767sub run_bisect {
768 my ($type) = @_;
769
2b7d9b21 770 my $failed = 0;
5f9b6ced
SR
771 my $result;
772 my $output;
773 my $ret;
774
5f9b6ced 775 if (defined($minconfig)) {
2b7d9b21 776 build "useconfig:$minconfig" or $failed = 1;
5f9b6ced
SR
777 } else {
778 # ?? no config to use?
2b7d9b21 779 build "oldconfig" or $failed = 1;
5f9b6ced
SR
780 }
781
782 if ($type ne "build") {
7faafbd6 783 dodie "Failed on build" if $failed;
5f9b6ced
SR
784
785 # Now boot the box
786 get_grub_index;
787 get_version;
788 install;
7faafbd6
SR
789
790 start_monitor;
2b7d9b21 791 monitor or $failed = 1;
5f9b6ced
SR
792
793 if ($type ne "boot") {
7faafbd6 794 dodie "Failed on boot" if $failed;
5a391fbf 795
2b7d9b21 796 do_run_test or $failed = 1;
5f9b6ced 797 }
7faafbd6 798 end_monitor;
5f9b6ced
SR
799 }
800
801 if ($failed) {
802 $result = "bad";
5a391fbf
SR
803
804 # reboot the box to a good kernel
a75fecec
SR
805 if ($type ne "build") {
806 doprint "Reboot and sleep $bisect_sleep_time seconds\n";
5a391fbf 807 reboot;
7faafbd6 808 start_monitor;
a75fecec 809 wait_for_monitor $bisect_sleep_time;
7faafbd6 810 end_monitor;
5a391fbf 811 }
5f9b6ced
SR
812 } else {
813 $result = "good";
814 }
815
d6ce2a0b
SR
816 # Are we looking for where it worked, not failed?
817 if ($reverse_bisect) {
818 if ($failed) {
819 $result = "good";
820 } else {
821 $result = "bad";
822 }
823 }
824
a75fecec 825 return $result;
5f9b6ced
SR
826}
827
828sub bisect {
829 my ($i) = @_;
830
831 my $result;
832
833 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
834 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
835 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
836
837 my $good = $opt{"BISECT_GOOD[$i]"};
838 my $bad = $opt{"BISECT_BAD[$i]"};
839 my $type = $opt{"BISECT_TYPE[$i]"};
a75fecec
SR
840 my $start = $opt{"BISECT_START[$i]"};
841 my $replay = $opt{"BISECT_REPLAY[$i]"};
5f9b6ced 842
d6ce2a0b
SR
843 if (defined($opt{"BISECT_REVERSE[$i]"}) &&
844 $opt{"BISECT_REVERSE[$i]"} == 1) {
845 doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
846 $reverse_bisect = 1;
847 } else {
848 $reverse_bisect = 0;
849 }
850
5f9b6ced
SR
851 $in_bisect = 1;
852
a75fecec
SR
853 # Can't have a test without having a test to run
854 if ($type eq "test" && !defined($run_test)) {
855 $type = "boot";
856 }
857
858 my $check = $opt{"BISECT_CHECK[$i]"};
859 if (defined($check) && $check ne "0") {
860
861 # get current HEAD
862 doprint "git rev-list HEAD --max-count=1 ... ";
863 my $head = `git rev-list HEAD --max-count=1`;
864 my $ret = $?;
865
866 logit $head;
867
868 if ($ret) {
869 doprint "FAILED\n";
870 dodie "Failed to get git HEAD";
871 }
872
873 print "SUCCESS\n";
874
875 chomp $head;
876
877 if ($check ne "good") {
878 doprint "TESTING BISECT BAD [$bad]\n";
879 run_command "git checkout $bad" or
880 die "Failed to checkout $bad";
881
882 $result = run_bisect $type;
883
884 if ($result ne "bad") {
885 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
886 }
887 }
888
889 if ($check ne "bad") {
890 doprint "TESTING BISECT GOOD [$good]\n";
891 run_command "git checkout $good" or
892 die "Failed to checkout $good";
893
894 $result = run_bisect $type;
895
896 if ($result ne "good") {
897 fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
898 }
899 }
900
901 # checkout where we started
902 run_command "git checkout $head" or
903 die "Failed to checkout $head";
904 }
905
5f9b6ced 906 run_command "git bisect start" or
a75fecec 907 dodie "could not start bisect";
5f9b6ced
SR
908
909 run_command "git bisect good $good" or
a75fecec 910 dodie "could not set bisect good to $good";
5f9b6ced 911
a75fecec
SR
912 run_git_bisect "git bisect bad $bad" or
913 dodie "could not set bisect bad to $bad";
5f9b6ced 914
a75fecec
SR
915 if (defined($replay)) {
916 run_command "git bisect replay $replay" or
917 dodie "failed to run replay";
5a391fbf
SR
918 }
919
a75fecec
SR
920 if (defined($start)) {
921 run_command "git checkout $start" or
922 dodie "failed to checkout $start";
923 }
924
925 my $test;
5f9b6ced
SR
926 do {
927 $result = run_bisect $type;
a75fecec
SR
928 $test = run_git_bisect "git bisect $result";
929 } while ($test);
5f9b6ced
SR
930
931 run_command "git bisect log" or
932 dodie "could not capture git bisect log";
933
934 run_command "git bisect reset" or
935 dodie "could not reset git bisect";
936
937 doprint "Bad commit was [$bisect_bad]\n";
938
939 $in_bisect = 0;
940
941 success $i;
942}
943
6c5ee0be
SR
944sub patchcheck {
945 my ($i) = @_;
946
947 die "PATCHCHECK_START[$i] not defined\n"
948 if (!defined($opt{"PATCHCHECK_START[$i]"}));
949 die "PATCHCHECK_TYPE[$i] not defined\n"
950 if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
951
952 my $start = $opt{"PATCHCHECK_START[$i]"};
953
954 my $end = "HEAD";
955 if (defined($opt{"PATCHCHECK_END[$i]"})) {
956 $end = $opt{"PATCHCHECK_END[$i]"};
957 }
958
959 my $type = $opt{"PATCHCHECK_TYPE[$i]"};
960
961 # Can't have a test without having a test to run
962 if ($type eq "test" && !defined($run_test)) {
963 $type = "boot";
964 }
965
966 open (IN, "git log --pretty=oneline $end|") or
967 dodie "could not get git list";
968
969 my @list;
970
971 while (<IN>) {
972 chomp;
973 $list[$#list+1] = $_;
974 last if (/^$start/);
975 }
976 close(IN);
977
978 if ($list[$#list] !~ /^$start/) {
2b7d9b21 979 fail "SHA1 $start not found";
6c5ee0be
SR
980 }
981
982 # go backwards in the list
983 @list = reverse @list;
984
985 my $save_clean = $noclean;
986
987 $in_patchcheck = 1;
988 foreach my $item (@list) {
989 my $sha1 = $item;
990 $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
991
992 doprint "\nProcessing commit $item\n\n";
993
994 run_command "git checkout $sha1" or
995 die "Failed to checkout $sha1";
996
997 # only clean on the first and last patch
998 if ($item eq $list[0] ||
999 $item eq $list[$#list]) {
1000 $noclean = $save_clean;
1001 } else {
1002 $noclean = 1;
1003 }
1004
1005 if (defined($minconfig)) {
2b7d9b21 1006 build "useconfig:$minconfig" or return 0;
6c5ee0be
SR
1007 } else {
1008 # ?? no config to use?
2b7d9b21 1009 build "oldconfig" or return 0;
6c5ee0be
SR
1010 }
1011
2b7d9b21 1012 check_buildlog $sha1 or return 0;
6c5ee0be
SR
1013
1014 next if ($type eq "build");
1015
1016 get_grub_index;
1017 get_version;
1018 install;
6c5ee0be 1019
7faafbd6
SR
1020 my $failed = 0;
1021
1022 start_monitor;
1023 monitor or $failed = 1;
1024
1025 if (!$failed && $type ne "boot"){
1026 do_run_test or $failed = 1;
1027 }
1028 end_monitor;
1029 return 0 if ($failed);
1030
6c5ee0be
SR
1031 }
1032 $in_patchcheck = 0;
1033 success $i;
2b7d9b21
SR
1034
1035 return 1;
6c5ee0be
SR
1036}
1037
2545eb61
SR
1038read_config $ARGV[0];
1039
1040# mandatory configs
1041die "MACHINE not defined\n" if (!defined($opt{"MACHINE"}));
1042die "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"}));
1043die "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"}));
1044die "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"}));
1045die "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"}));
75c3fda7 1046die "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"}));
2545eb61
SR
1047die "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"}));
1048die "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"}));
1049die "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"}));
2545eb61 1050
2b7d9b21
SR
1051if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
1052 unlink $opt{"LOG_FILE"};
1053}
2545eb61 1054
2b7d9b21
SR
1055doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
1056
1057foreach my $option (sort keys %opt) {
1058 doprint "$option = $opt{$option}\n";
1059}
2545eb61 1060
a75fecec 1061sub set_test_option {
5a391fbf 1062 my ($name, $i) = @_;
2545eb61 1063
5a391fbf 1064 my $option = "$name\[$i\]";
5c42fc5b 1065
5a391fbf
SR
1066 if (defined($opt{$option})) {
1067 return $opt{$option};
5f9b6ced
SR
1068 }
1069
5a391fbf
SR
1070 if (defined($opt{$name})) {
1071 return $opt{$name};
2545eb61
SR
1072 }
1073
5a391fbf
SR
1074 return undef;
1075}
1076
1077# First we need to do is the builds
a75fecec
SR
1078for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
1079
576f627c
SR
1080 $iteration = $i;
1081
a75fecec
SR
1082 my $ssh_user = set_test_option("SSH_USER", $i);
1083 my $makecmd = set_test_option("MAKE_CMD", $i);
1084
1085 $machine = set_test_option("MACHINE", $i);
1086 $tmpdir = set_test_option("TMP_DIR", $i);
1087 $outputdir = set_test_option("OUTPUT_DIR", $i);
1088 $builddir = set_test_option("BUILD_DIR", $i);
1089 $test_type = set_test_option("TEST_TYPE", $i);
1090 $build_type = set_test_option("BUILD_TYPE", $i);
1091 $build_options = set_test_option("BUILD_OPTIONS", $i);
1092 $power_cycle = set_test_option("POWER_CYCLE", $i);
1093 $noclean = set_test_option("BUILD_NOCLEAN", $i);
1094 $minconfig = set_test_option("MIN_CONFIG", $i);
1095 $run_test = set_test_option("TEST", $i);
1096 $addconfig = set_test_option("ADD_CONFIG", $i);
1097 $reboot_type = set_test_option("REBOOT_TYPE", $i);
1098 $grub_menu = set_test_option("GRUB_MENU", $i);
8b37ca8c 1099 $post_install = set_test_option("POST_INSTALL", $i);
a75fecec
SR
1100 $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
1101 $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
1102 $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
1103 $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
1104 $power_off = set_test_option("POWER_OFF", $i);
576f627c
SR
1105 $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
1106 $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
a75fecec
SR
1107 $sleep_time = set_test_option("SLEEP_TIME", $i);
1108 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
1109 $store_failures = set_test_option("STORE_FAILURES", $i);
1110 $timeout = set_test_option("TIMEOUT", $i);
1111 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
1112 $console = set_test_option("CONSOLE", $i);
1113 $success_line = set_test_option("SUCCESS_LINE", $i);
1114 $build_target = set_test_option("BUILD_TARGET", $i);
1115 $target_image = set_test_option("TARGET_IMAGE", $i);
1116 $localversion = set_test_option("LOCALVERSION", $i);
1117
1118 chdir $builddir || die "can't change directory to $builddir";
1119
1120 if (!-d $tmpdir) {
1121 mkpath($tmpdir) or
1122 die "can't create $tmpdir";
1123 }
1a5cfce3 1124
a75fecec
SR
1125 $target = "$ssh_user\@$machine";
1126
1127 $buildlog = "$tmpdir/buildlog-$machine";
1128 $dmesg = "$tmpdir/dmesg-$machine";
1129 $make = "$makecmd O=$outputdir";
1130
1131 if ($reboot_type eq "grub") {
576f627c 1132 dodie "GRUB_MENU not defined" if (!defined($grub_menu));
a75fecec 1133 } elsif (!defined($reboot_script)) {
576f627c 1134 dodie "REBOOT_SCRIPT not defined"
a75fecec
SR
1135 }
1136
1137 my $run_type = $build_type;
1138 if ($test_type eq "patchcheck") {
1139 $run_type = $opt{"PATCHCHECK_TYPE[$i]"};
1140 } elsif ($test_type eq "bisect") {
1141 $run_type = $opt{"BISECT_TYPE[$i]"};
1142 }
1143
1144 # mistake in config file?
1145 if (!defined($run_type)) {
1146 $run_type = "ERROR";
1147 }
5a391fbf 1148
2545eb61 1149 doprint "\n\n";
a75fecec 1150 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
7faafbd6
SR
1151
1152 unlink $dmesg;
1153 unlink $buildlog;
2545eb61 1154
2b7d9b21
SR
1155 if (!defined($minconfig)) {
1156 $minconfig = $addconfig;
1157
1158 } elsif (defined($addconfig)) {
a75fecec 1159 run_command "cat $addconfig $minconfig > $tmpdir/use_config" or
2b7d9b21 1160 dodie "Failed to create temp config";
a75fecec 1161 $minconfig = "$tmpdir/use_config";
2b7d9b21
SR
1162 }
1163
6c5ee0be
SR
1164 my $checkout = $opt{"CHECKOUT[$i]"};
1165 if (defined($checkout)) {
1166 run_command "git checkout $checkout" or
1167 die "failed to checkout $checkout";
1168 }
1169
a75fecec 1170 if ($test_type eq "bisect") {
5f9b6ced
SR
1171 bisect $i;
1172 next;
a75fecec 1173 } elsif ($test_type eq "patchcheck") {
6c5ee0be
SR
1174 patchcheck $i;
1175 next;
2545eb61 1176 }
2545eb61 1177
7faafbd6
SR
1178 if ($build_type ne "nobuild") {
1179 build $build_type or next;
2545eb61
SR
1180 }
1181
a75fecec
SR
1182 if ($test_type ne "build") {
1183 get_grub_index;
1184 get_version;
1185 install;
5a391fbf 1186
a75fecec
SR
1187 my $failed = 0;
1188 start_monitor;
1189 monitor or $failed = 1;;
1190
1191 if (!$failed && $test_type ne "boot" && defined($run_test)) {
1192 do_run_test or $failed = 1;
1193 }
1194 end_monitor;
1195 next if ($failed);
5a391fbf
SR
1196 }
1197
5f9b6ced 1198 success $i;
2545eb61
SR
1199}
1200
5c42fc5b 1201if ($opt{"POWEROFF_ON_SUCCESS"}) {
75c3fda7 1202 halt;
576f627c 1203} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
75c3fda7 1204 reboot;
5c42fc5b 1205}
75c3fda7 1206
2545eb61 1207exit 0;
This page took 0.082562 seconds and 5 git commands to generate.