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