ktest: Consolidate TEST_TYPE and DEFAULT code
[linux-2.6.git] / tools / testing / ktest / ktest.pl
blobb4f32e73474539b4f99c6467ca2c80fa008e270e
1 #!/usr/bin/perl -w
3 # Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
4 # Licensed under the terms of the GNU GPL License version 2
7 use strict;
8 use IPC::Open2;
9 use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
10 use File::Path qw(mkpath);
11 use File::Copy qw(cp);
12 use FileHandle;
14 my $VERSION = "0.2";
16 $| = 1;
18 my %opt;
19 my %repeat_tests;
20 my %repeats;
21 my %default;
23 #default opts
24 $default{"NUM_TESTS"} = 1;
25 $default{"REBOOT_TYPE"} = "grub";
26 $default{"TEST_TYPE"} = "test";
27 $default{"BUILD_TYPE"} = "randconfig";
28 $default{"MAKE_CMD"} = "make";
29 $default{"TIMEOUT"} = 120;
30 $default{"TMP_DIR"} = "/tmp/ktest/\${MACHINE}";
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{"PATCHCHECK_SLEEP_TIME"} = 60; # sleep time between patch checks
40 $default{"CLEAR_LOG"} = 0;
41 $default{"BISECT_MANUAL"} = 0;
42 $default{"BISECT_SKIP"} = 1;
43 $default{"SUCCESS_LINE"} = "login:";
44 $default{"DETECT_TRIPLE_FAULT"} = 1;
45 $default{"NO_INSTALL"} = 0;
46 $default{"BOOTED_TIMEOUT"} = 1;
47 $default{"DIE_ON_FAILURE"} = 1;
48 $default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
49 $default{"SCP_TO_TARGET"} = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE";
50 $default{"REBOOT"} = "ssh \$SSH_USER\@\$MACHINE reboot";
51 $default{"STOP_AFTER_SUCCESS"} = 10;
52 $default{"STOP_AFTER_FAILURE"} = 60;
53 $default{"STOP_TEST_AFTER"} = 600;
54 $default{"LOCALVERSION"} = "-test";
56 my $ktest_config;
57 my $version;
58 my $machine;
59 my $ssh_user;
60 my $tmpdir;
61 my $builddir;
62 my $outputdir;
63 my $output_config;
64 my $test_type;
65 my $build_type;
66 my $build_options;
67 my $pre_build;
68 my $post_build;
69 my $pre_build_die;
70 my $post_build_die;
71 my $reboot_type;
72 my $reboot_script;
73 my $power_cycle;
74 my $reboot;
75 my $reboot_on_error;
76 my $poweroff_on_error;
77 my $die_on_failure;
78 my $powercycle_after_reboot;
79 my $poweroff_after_halt;
80 my $ssh_exec;
81 my $scp_to_target;
82 my $power_off;
83 my $grub_menu;
84 my $grub_number;
85 my $target;
86 my $make;
87 my $post_install;
88 my $no_install;
89 my $noclean;
90 my $minconfig;
91 my $start_minconfig;
92 my $start_minconfig_defined;
93 my $output_minconfig;
94 my $ignore_config;
95 my $addconfig;
96 my $in_bisect = 0;
97 my $bisect_bad = "";
98 my $reverse_bisect;
99 my $bisect_manual;
100 my $bisect_skip;
101 my $config_bisect_good;
102 my $in_patchcheck = 0;
103 my $run_test;
104 my $redirect;
105 my $buildlog;
106 my $dmesg;
107 my $monitor_fp;
108 my $monitor_pid;
109 my $monitor_cnt = 0;
110 my $sleep_time;
111 my $bisect_sleep_time;
112 my $patchcheck_sleep_time;
113 my $ignore_warnings;
114 my $store_failures;
115 my $test_name;
116 my $timeout;
117 my $booted_timeout;
118 my $detect_triplefault;
119 my $console;
120 my $reboot_success_line;
121 my $success_line;
122 my $stop_after_success;
123 my $stop_after_failure;
124 my $stop_test_after;
125 my $build_target;
126 my $target_image;
127 my $localversion;
128 my $iteration = 0;
129 my $successes = 0;
131 my %entered_configs;
132 my %config_help;
133 my %variable;
134 my %force_config;
136 # do not force reboots on config problems
137 my $no_reboot = 1;
139 $config_help{"MACHINE"} = << "EOF"
140 The machine hostname that you will test.
143 $config_help{"SSH_USER"} = << "EOF"
144 The box is expected to have ssh on normal bootup, provide the user
145 (most likely root, since you need privileged operations)
148 $config_help{"BUILD_DIR"} = << "EOF"
149 The directory that contains the Linux source code (full path).
152 $config_help{"OUTPUT_DIR"} = << "EOF"
153 The directory that the objects will be built (full path).
154 (can not be same as BUILD_DIR)
157 $config_help{"BUILD_TARGET"} = << "EOF"
158 The location of the compiled file to copy to the target.
159 (relative to OUTPUT_DIR)
162 $config_help{"TARGET_IMAGE"} = << "EOF"
163 The place to put your image on the test machine.
166 $config_help{"POWER_CYCLE"} = << "EOF"
167 A script or command to reboot the box.
169 Here is a digital loggers power switch example
170 POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
172 Here is an example to reboot a virtual box on the current host
173 with the name "Guest".
174 POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
177 $config_help{"CONSOLE"} = << "EOF"
178 The script or command that reads the console
180 If you use ttywatch server, something like the following would work.
181 CONSOLE = nc -d localhost 3001
183 For a virtual machine with guest name "Guest".
184 CONSOLE = virsh console Guest
187 $config_help{"LOCALVERSION"} = << "EOF"
188 Required version ending to differentiate the test
189 from other linux builds on the system.
192 $config_help{"REBOOT_TYPE"} = << "EOF"
193 Way to reboot the box to the test kernel.
194 Only valid options so far are "grub" and "script".
196 If you specify grub, it will assume grub version 1
197 and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
198 and select that target to reboot to the kernel. If this is not
199 your setup, then specify "script" and have a command or script
200 specified in REBOOT_SCRIPT to boot to the target.
202 The entry in /boot/grub/menu.lst must be entered in manually.
203 The test will not modify that file.
206 $config_help{"GRUB_MENU"} = << "EOF"
207 The grub title name for the test kernel to boot
208 (Only mandatory if REBOOT_TYPE = grub)
210 Note, ktest.pl will not update the grub menu.lst, you need to
211 manually add an option for the test. ktest.pl will search
212 the grub menu.lst for this option to find what kernel to
213 reboot into.
215 For example, if in the /boot/grub/menu.lst the test kernel title has:
216 title Test Kernel
217 kernel vmlinuz-test
218 GRUB_MENU = Test Kernel
221 $config_help{"REBOOT_SCRIPT"} = << "EOF"
222 A script to reboot the target into the test kernel
223 (Only mandatory if REBOOT_TYPE = script)
227 sub read_yn {
228 my ($prompt) = @_;
230 my $ans;
232 for (;;) {
233 print "$prompt [Y/n] ";
234 $ans = <STDIN>;
235 chomp $ans;
236 if ($ans =~ /^\s*$/) {
237 $ans = "y";
239 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
240 print "Please answer either 'y' or 'n'.\n";
242 if ($ans !~ /^y$/i) {
243 return 0;
245 return 1;
248 sub get_ktest_config {
249 my ($config) = @_;
251 return if (defined($opt{$config}));
253 if (defined($config_help{$config})) {
254 print "\n";
255 print $config_help{$config};
258 for (;;) {
259 print "$config = ";
260 if (defined($default{$config})) {
261 print "\[$default{$config}\] ";
263 $entered_configs{$config} = <STDIN>;
264 $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/;
265 if ($entered_configs{$config} =~ /^\s*$/) {
266 if ($default{$config}) {
267 $entered_configs{$config} = $default{$config};
268 } else {
269 print "Your answer can not be blank\n";
270 next;
273 last;
277 sub get_ktest_configs {
278 get_ktest_config("MACHINE");
279 get_ktest_config("SSH_USER");
280 get_ktest_config("BUILD_DIR");
281 get_ktest_config("OUTPUT_DIR");
282 get_ktest_config("BUILD_TARGET");
283 get_ktest_config("TARGET_IMAGE");
284 get_ktest_config("POWER_CYCLE");
285 get_ktest_config("CONSOLE");
286 get_ktest_config("LOCALVERSION");
288 my $rtype = $opt{"REBOOT_TYPE"};
290 if (!defined($rtype)) {
291 if (!defined($opt{"GRUB_MENU"})) {
292 get_ktest_config("REBOOT_TYPE");
293 $rtype = $entered_configs{"REBOOT_TYPE"};
294 } else {
295 $rtype = "grub";
299 if ($rtype eq "grub") {
300 get_ktest_config("GRUB_MENU");
301 } else {
302 get_ktest_config("REBOOT_SCRIPT");
306 sub process_variables {
307 my ($value) = @_;
308 my $retval = "";
310 # We want to check for '\', and it is just easier
311 # to check the previous characet of '$' and not need
312 # to worry if '$' is the first character. By adding
313 # a space to $value, we can just check [^\\]\$ and
314 # it will still work.
315 $value = " $value";
317 while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
318 my $begin = $1;
319 my $var = $2;
320 my $end = $3;
321 # append beginning of value to retval
322 $retval = "$retval$begin";
323 if (defined($variable{$var})) {
324 $retval = "$retval$variable{$var}";
325 } else {
326 # put back the origin piece.
327 $retval = "$retval\$\{$var\}";
329 $value = $end;
331 $retval = "$retval$value";
333 # remove the space added in the beginning
334 $retval =~ s/ //;
336 return "$retval"
339 sub set_value {
340 my ($lvalue, $rvalue) = @_;
342 if (defined($opt{$lvalue})) {
343 die "Error: Option $lvalue defined more than once!\n";
345 if ($rvalue =~ /^\s*$/) {
346 delete $opt{$lvalue};
347 } else {
348 $rvalue = process_variables($rvalue);
349 $opt{$lvalue} = $rvalue;
353 sub set_variable {
354 my ($lvalue, $rvalue) = @_;
356 if ($rvalue =~ /^\s*$/) {
357 delete $variable{$lvalue};
358 } else {
359 $rvalue = process_variables($rvalue);
360 $variable{$lvalue} = $rvalue;
364 sub process_compare {
365 my ($lval, $cmp, $rval) = @_;
367 # remove whitespace
369 $lval =~ s/^\s*//;
370 $lval =~ s/\s*$//;
372 $rval =~ s/^\s*//;
373 $rval =~ s/\s*$//;
375 if ($cmp eq "==") {
376 return $lval eq $rval;
377 } elsif ($cmp eq "!=") {
378 return $lval ne $rval;
381 my $statement = "$lval $cmp $rval";
382 my $ret = eval $statement;
384 # $@ stores error of eval
385 if ($@) {
386 return -1;
389 return $ret;
392 sub process_if {
393 my ($name, $value) = @_;
395 my $val = process_variables($value);
397 if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) {
398 my $ret = process_compare($1, $2, $3);
399 if ($ret < 0) {
400 die "$name: $.: Unable to process comparison\n";
402 return $ret;
405 if ($val =~ /^\s*0\s*$/) {
406 return 0;
407 } elsif ($val =~ /^\s*\d+\s*$/) {
408 return 1;
411 die ("$name: $.: Undefined variable $val in if statement\n");
412 return 1;
415 sub __read_config {
416 my ($config, $current_test_num) = @_;
418 my $in;
419 open($in, $config) || die "can't read file $config";
421 my $name = $config;
422 $name =~ s,.*/(.*),$1,;
424 my $test_num = $$current_test_num;
425 my $default = 1;
426 my $repeat = 1;
427 my $num_tests_set = 0;
428 my $skip = 0;
429 my $rest;
430 my $test_case = 0;
431 my $if = 0;
432 my $if_set = 0;
434 while (<$in>) {
436 # ignore blank lines and comments
437 next if (/^\s*$/ || /\s*\#/);
439 if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
441 my $type = $1;
442 $rest = $2;
444 my $old_test_num;
445 my $old_repeat;
447 if ($type eq "TEST_START") {
449 if ($num_tests_set) {
450 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
453 $old_test_num = $test_num;
454 $old_repeat = $repeat;
456 $test_num += $repeat;
457 $default = 0;
458 $repeat = 1;
459 } else {
460 $default = 1;
463 if ($rest =~ /\s+SKIP\b(.*)/) {
464 $rest = $1;
465 $skip = 1;
466 } else {
467 $test_case = 1;
468 $skip = 0;
471 if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
472 $repeat = $1;
473 $rest = $2;
474 $repeat_tests{"$test_num"} = $repeat;
477 if ($rest =~ /\sIF\s+(.*)/) {
478 $rest = "";
479 if (process_if($name, $1)) {
480 $if_set = 1;
481 } else {
482 $skip = 1;
484 $if = 1;
485 } else {
486 $if = 0;
489 if ($rest !~ /^\s*$/) {
490 die "$name: $.: Gargbage found after $type\n$_";
493 if ($skip && $type eq "TEST_START") {
494 $test_num = $old_test_num;
495 $repeat = $old_repeat;
498 } elsif (/^\s*ELSE\b(.*)$/) {
499 if (!$if) {
500 die "$name: $.: ELSE found with out matching IF section\n$_";
502 $rest = $1;
503 if ($if_set) {
504 $skip = 1;
505 $rest = "";
506 } else {
507 $skip = 0;
509 if ($rest =~ /\sIF\s+(.*)/) {
510 # May be a ELSE IF section.
511 if (!process_if($name, $1)) {
512 $skip = 1;
514 $rest = "";
515 } else {
516 $if = 0;
520 if ($rest !~ /^\s*$/) {
521 die "$name: $.: Gargbage found after DEFAULTS\n$_";
524 } elsif (/^\s*INCLUDE\s+(\S+)/) {
526 next if ($skip);
528 if (!$default) {
529 die "$name: $.: INCLUDE can only be done in default sections\n$_";
532 my $file = process_variables($1);
534 if ($file !~ m,^/,) {
535 # check the path of the config file first
536 if ($config =~ m,(.*)/,) {
537 if (-f "$1/$file") {
538 $file = "$1/$file";
543 if ( ! -r $file ) {
544 die "$name: $.: Can't read file $file\n$_";
547 if (__read_config($file, \$test_num)) {
548 $test_case = 1;
551 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
553 next if ($skip);
555 my $lvalue = $1;
556 my $rvalue = $2;
558 if (!$default &&
559 ($lvalue eq "NUM_TESTS" ||
560 $lvalue eq "LOG_FILE" ||
561 $lvalue eq "CLEAR_LOG")) {
562 die "$name: $.: $lvalue must be set in DEFAULTS section\n";
565 if ($lvalue eq "NUM_TESTS") {
566 if ($test_num) {
567 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
569 if (!$default) {
570 die "$name: $.: NUM_TESTS must be set in default section\n";
572 $num_tests_set = 1;
575 if ($default || $lvalue =~ /\[\d+\]$/) {
576 set_value($lvalue, $rvalue);
577 } else {
578 my $val = "$lvalue\[$test_num\]";
579 set_value($val, $rvalue);
581 if ($repeat > 1) {
582 $repeats{$val} = $repeat;
585 } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
586 next if ($skip);
588 my $lvalue = $1;
589 my $rvalue = $2;
591 # process config variables.
592 # Config variables are only active while reading the
593 # config and can be defined anywhere. They also ignore
594 # TEST_START and DEFAULTS, but are skipped if they are in
595 # on of these sections that have SKIP defined.
596 # The save variable can be
597 # defined multiple times and the new one simply overrides
598 # the prevous one.
599 set_variable($lvalue, $rvalue);
601 } else {
602 die "$name: $.: Garbage found in config\n$_";
606 if ($test_num) {
607 $test_num += $repeat - 1;
608 $opt{"NUM_TESTS"} = $test_num;
611 close($in);
613 $$current_test_num = $test_num;
615 return $test_case;
618 sub read_config {
619 my ($config) = @_;
621 my $test_case;
622 my $test_num = 0;
624 $test_case = __read_config $config, \$test_num;
626 # make sure we have all mandatory configs
627 get_ktest_configs;
629 # was a test specified?
630 if (!$test_case) {
631 print "No test case specified.\n";
632 print "What test case would you like to run?\n";
633 my $ans = <STDIN>;
634 chomp $ans;
635 $default{"TEST_TYPE"} = $ans;
638 # set any defaults
640 foreach my $default (keys %default) {
641 if (!defined($opt{$default})) {
642 $opt{$default} = $default{$default};
647 sub __eval_option {
648 my ($option, $i) = @_;
650 # Add space to evaluate the character before $
651 $option = " $option";
652 my $retval = "";
654 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
655 my $start = $1;
656 my $var = $2;
657 my $end = $3;
659 # Append beginning of line
660 $retval = "$retval$start";
662 # If the iteration option OPT[$i] exists, then use that.
663 # otherwise see if the default OPT (without [$i]) exists.
665 my $o = "$var\[$i\]";
667 if (defined($opt{$o})) {
668 $o = $opt{$o};
669 $retval = "$retval$o";
670 } elsif (defined($opt{$var})) {
671 $o = $opt{$var};
672 $retval = "$retval$o";
673 } else {
674 $retval = "$retval\$\{$var\}";
677 $option = $end;
680 $retval = "$retval$option";
682 $retval =~ s/^ //;
684 return $retval;
687 sub eval_option {
688 my ($option, $i) = @_;
690 my $prev = "";
692 # Since an option can evaluate to another option,
693 # keep iterating until we do not evaluate any more
694 # options.
695 my $r = 0;
696 while ($prev ne $option) {
697 # Check for recursive evaluations.
698 # 100 deep should be more than enough.
699 if ($r++ > 100) {
700 die "Over 100 evaluations accurred with $option\n" .
701 "Check for recursive variables\n";
703 $prev = $option;
704 $option = __eval_option($option, $i);
707 return $option;
710 sub _logit {
711 if (defined($opt{"LOG_FILE"})) {
712 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
713 print OUT @_;
714 close(OUT);
718 sub logit {
719 if (defined($opt{"LOG_FILE"})) {
720 _logit @_;
721 } else {
722 print @_;
726 sub doprint {
727 print @_;
728 _logit @_;
731 sub run_command;
732 sub start_monitor;
733 sub end_monitor;
734 sub wait_for_monitor;
736 sub reboot {
737 my ($time) = @_;
739 if (defined($time)) {
740 start_monitor;
741 # flush out current monitor
742 # May contain the reboot success line
743 wait_for_monitor 1;
746 # try to reboot normally
747 if (run_command $reboot) {
748 if (defined($powercycle_after_reboot)) {
749 sleep $powercycle_after_reboot;
750 run_command "$power_cycle";
752 } else {
753 # nope? power cycle it.
754 run_command "$power_cycle";
757 if (defined($time)) {
758 wait_for_monitor($time, $reboot_success_line);
759 end_monitor;
763 sub do_not_reboot {
764 my $i = $iteration;
766 return $test_type eq "build" || $no_reboot ||
767 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
768 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
771 sub dodie {
772 doprint "CRITICAL FAILURE... ", @_, "\n";
774 my $i = $iteration;
776 if ($reboot_on_error && !do_not_reboot) {
778 doprint "REBOOTING\n";
779 reboot;
781 } elsif ($poweroff_on_error && defined($power_off)) {
782 doprint "POWERING OFF\n";
783 `$power_off`;
786 if (defined($opt{"LOG_FILE"})) {
787 print " See $opt{LOG_FILE} for more info.\n";
790 die @_, "\n";
793 sub open_console {
794 my ($fp) = @_;
796 my $flags;
798 my $pid = open($fp, "$console|") or
799 dodie "Can't open console $console";
801 $flags = fcntl($fp, F_GETFL, 0) or
802 dodie "Can't get flags for the socket: $!";
803 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
804 dodie "Can't set flags for the socket: $!";
806 return $pid;
809 sub close_console {
810 my ($fp, $pid) = @_;
812 doprint "kill child process $pid\n";
813 kill 2, $pid;
815 print "closing!\n";
816 close($fp);
819 sub start_monitor {
820 if ($monitor_cnt++) {
821 return;
823 $monitor_fp = \*MONFD;
824 $monitor_pid = open_console $monitor_fp;
826 return;
828 open(MONFD, "Stop perl from warning about single use of MONFD");
831 sub end_monitor {
832 if (--$monitor_cnt) {
833 return;
835 close_console($monitor_fp, $monitor_pid);
838 sub wait_for_monitor {
839 my ($time, $stop) = @_;
840 my $full_line = "";
841 my $line;
842 my $booted = 0;
844 doprint "** Wait for monitor to settle down **\n";
846 # read the monitor and wait for the system to calm down
847 while (!$booted) {
848 $line = wait_for_input($monitor_fp, $time);
849 last if (!defined($line));
850 print "$line";
851 $full_line .= $line;
853 if (defined($stop) && $full_line =~ /$stop/) {
854 doprint "wait for monitor detected $stop\n";
855 $booted = 1;
858 if ($line =~ /\n/) {
859 $full_line = "";
862 print "** Monitor flushed **\n";
865 sub fail {
867 if ($die_on_failure) {
868 dodie @_;
871 doprint "FAILED\n";
873 my $i = $iteration;
875 # no need to reboot for just building.
876 if (!do_not_reboot) {
877 doprint "REBOOTING\n";
878 reboot $sleep_time;
881 my $name = "";
883 if (defined($test_name)) {
884 $name = " ($test_name)";
887 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
888 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
889 doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
890 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
891 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
893 return 1 if (!defined($store_failures));
895 my @t = localtime;
896 my $date = sprintf "%04d%02d%02d%02d%02d%02d",
897 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
899 my $type = $build_type;
900 if ($type =~ /useconfig/) {
901 $type = "useconfig";
904 my $dir = "$machine-$test_type-$type-fail-$date";
905 my $faildir = "$store_failures/$dir";
907 if (!-d $faildir) {
908 mkpath($faildir) or
909 die "can't create $faildir";
911 if (-f "$output_config") {
912 cp "$output_config", "$faildir/config" or
913 die "failed to copy .config";
915 if (-f $buildlog) {
916 cp $buildlog, "$faildir/buildlog" or
917 die "failed to move $buildlog";
919 if (-f $dmesg) {
920 cp $dmesg, "$faildir/dmesg" or
921 die "failed to move $dmesg";
924 doprint "*** Saved info to $faildir ***\n";
926 return 1;
929 sub run_command {
930 my ($command) = @_;
931 my $dolog = 0;
932 my $dord = 0;
933 my $pid;
935 $command =~ s/\$SSH_USER/$ssh_user/g;
936 $command =~ s/\$MACHINE/$machine/g;
938 doprint("$command ... ");
940 $pid = open(CMD, "$command 2>&1 |") or
941 (fail "unable to exec $command" and return 0);
943 if (defined($opt{"LOG_FILE"})) {
944 open(LOG, ">>$opt{LOG_FILE}") or
945 dodie "failed to write to log";
946 $dolog = 1;
949 if (defined($redirect)) {
950 open (RD, ">$redirect") or
951 dodie "failed to write to redirect $redirect";
952 $dord = 1;
955 while (<CMD>) {
956 print LOG if ($dolog);
957 print RD if ($dord);
960 waitpid($pid, 0);
961 my $failed = $?;
963 close(CMD);
964 close(LOG) if ($dolog);
965 close(RD) if ($dord);
967 if ($failed) {
968 doprint "FAILED!\n";
969 } else {
970 doprint "SUCCESS\n";
973 return !$failed;
976 sub run_ssh {
977 my ($cmd) = @_;
978 my $cp_exec = $ssh_exec;
980 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
981 return run_command "$cp_exec";
984 sub run_scp {
985 my ($src, $dst) = @_;
986 my $cp_scp = $scp_to_target;
988 $cp_scp =~ s/\$SRC_FILE/$src/g;
989 $cp_scp =~ s/\$DST_FILE/$dst/g;
991 return run_command "$cp_scp";
994 sub get_grub_index {
996 if ($reboot_type ne "grub") {
997 return;
999 return if (defined($grub_number));
1001 doprint "Find grub menu ... ";
1002 $grub_number = -1;
1004 my $ssh_grub = $ssh_exec;
1005 $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
1007 open(IN, "$ssh_grub |")
1008 or die "unable to get menu.lst";
1010 my $found = 0;
1012 while (<IN>) {
1013 if (/^\s*title\s+$grub_menu\s*$/) {
1014 $grub_number++;
1015 $found = 1;
1016 last;
1017 } elsif (/^\s*title\s/) {
1018 $grub_number++;
1021 close(IN);
1023 die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
1024 if (!$found);
1025 doprint "$grub_number\n";
1028 sub wait_for_input
1030 my ($fp, $time) = @_;
1031 my $rin;
1032 my $ready;
1033 my $line;
1034 my $ch;
1036 if (!defined($time)) {
1037 $time = $timeout;
1040 $rin = '';
1041 vec($rin, fileno($fp), 1) = 1;
1042 $ready = select($rin, undef, undef, $time);
1044 $line = "";
1046 # try to read one char at a time
1047 while (sysread $fp, $ch, 1) {
1048 $line .= $ch;
1049 last if ($ch eq "\n");
1052 if (!length($line)) {
1053 return undef;
1056 return $line;
1059 sub reboot_to {
1060 if ($reboot_type eq "grub") {
1061 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'";
1062 return;
1065 run_command "$reboot_script";
1068 sub get_sha1 {
1069 my ($commit) = @_;
1071 doprint "git rev-list --max-count=1 $commit ... ";
1072 my $sha1 = `git rev-list --max-count=1 $commit`;
1073 my $ret = $?;
1075 logit $sha1;
1077 if ($ret) {
1078 doprint "FAILED\n";
1079 dodie "Failed to get git $commit";
1082 print "SUCCESS\n";
1084 chomp $sha1;
1086 return $sha1;
1089 sub monitor {
1090 my $booted = 0;
1091 my $bug = 0;
1092 my $skip_call_trace = 0;
1093 my $loops;
1095 wait_for_monitor 5;
1097 my $line;
1098 my $full_line = "";
1100 open(DMESG, "> $dmesg") or
1101 die "unable to write to $dmesg";
1103 reboot_to;
1105 my $success_start;
1106 my $failure_start;
1107 my $monitor_start = time;
1108 my $done = 0;
1109 my $version_found = 0;
1111 while (!$done) {
1113 if ($bug && defined($stop_after_failure) &&
1114 $stop_after_failure >= 0) {
1115 my $time = $stop_after_failure - (time - $failure_start);
1116 $line = wait_for_input($monitor_fp, $time);
1117 if (!defined($line)) {
1118 doprint "bug timed out after $booted_timeout seconds\n";
1119 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1120 last;
1122 } elsif ($booted) {
1123 $line = wait_for_input($monitor_fp, $booted_timeout);
1124 if (!defined($line)) {
1125 my $s = $booted_timeout == 1 ? "" : "s";
1126 doprint "Successful boot found: break after $booted_timeout second$s\n";
1127 last;
1129 } else {
1130 $line = wait_for_input($monitor_fp);
1131 if (!defined($line)) {
1132 my $s = $timeout == 1 ? "" : "s";
1133 doprint "Timed out after $timeout second$s\n";
1134 last;
1138 doprint $line;
1139 print DMESG $line;
1141 # we are not guaranteed to get a full line
1142 $full_line .= $line;
1144 if ($full_line =~ /$success_line/) {
1145 $booted = 1;
1146 $success_start = time;
1149 if ($booted && defined($stop_after_success) &&
1150 $stop_after_success >= 0) {
1151 my $now = time;
1152 if ($now - $success_start >= $stop_after_success) {
1153 doprint "Test forced to stop after $stop_after_success seconds after success\n";
1154 last;
1158 if ($full_line =~ /\[ backtrace testing \]/) {
1159 $skip_call_trace = 1;
1162 if ($full_line =~ /call trace:/i) {
1163 if (!$bug && !$skip_call_trace) {
1164 $bug = 1;
1165 $failure_start = time;
1169 if ($bug && defined($stop_after_failure) &&
1170 $stop_after_failure >= 0) {
1171 my $now = time;
1172 if ($now - $failure_start >= $stop_after_failure) {
1173 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1174 last;
1178 if ($full_line =~ /\[ end of backtrace testing \]/) {
1179 $skip_call_trace = 0;
1182 if ($full_line =~ /Kernel panic -/) {
1183 $failure_start = time;
1184 $bug = 1;
1187 # Detect triple faults by testing the banner
1188 if ($full_line =~ /\bLinux version (\S+).*\n/) {
1189 if ($1 eq $version) {
1190 $version_found = 1;
1191 } elsif ($version_found && $detect_triplefault) {
1192 # We already booted into the kernel we are testing,
1193 # but now we booted into another kernel?
1194 # Consider this a triple fault.
1195 doprint "Aleady booted in Linux kernel $version, but now\n";
1196 doprint "we booted into Linux kernel $1.\n";
1197 doprint "Assuming that this is a triple fault.\n";
1198 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1199 last;
1203 if ($line =~ /\n/) {
1204 $full_line = "";
1207 if ($stop_test_after > 0 && !$booted && !$bug) {
1208 if (time - $monitor_start > $stop_test_after) {
1209 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
1210 $done = 1;
1215 close(DMESG);
1217 if ($bug) {
1218 return 0 if ($in_bisect);
1219 fail "failed - got a bug report" and return 0;
1222 if (!$booted) {
1223 return 0 if ($in_bisect);
1224 fail "failed - never got a boot prompt." and return 0;
1227 return 1;
1230 sub do_post_install {
1232 return if (!defined($post_install));
1234 my $cp_post_install = $post_install;
1235 $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
1236 run_command "$cp_post_install" or
1237 dodie "Failed to run post install";
1240 sub install {
1242 return if ($no_install);
1244 run_scp "$outputdir/$build_target", "$target_image" or
1245 dodie "failed to copy image";
1247 my $install_mods = 0;
1249 # should we process modules?
1250 $install_mods = 0;
1251 open(IN, "$output_config") or dodie("Can't read config file");
1252 while (<IN>) {
1253 if (/CONFIG_MODULES(=y)?/) {
1254 $install_mods = 1 if (defined($1));
1255 last;
1258 close(IN);
1260 if (!$install_mods) {
1261 do_post_install;
1262 doprint "No modules needed\n";
1263 return;
1266 run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
1267 dodie "Failed to install modules";
1269 my $modlib = "/lib/modules/$version";
1270 my $modtar = "ktest-mods.tar.bz2";
1272 run_ssh "rm -rf $modlib" or
1273 dodie "failed to remove old mods: $modlib";
1275 # would be nice if scp -r did not follow symbolic links
1276 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
1277 dodie "making tarball";
1279 run_scp "$tmpdir/$modtar", "/tmp" or
1280 dodie "failed to copy modules";
1282 unlink "$tmpdir/$modtar";
1284 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
1285 dodie "failed to tar modules";
1287 run_ssh "rm -f /tmp/$modtar";
1289 do_post_install;
1292 sub get_version {
1293 # get the release name
1294 doprint "$make kernelrelease ... ";
1295 $version = `$make kernelrelease | tail -1`;
1296 chomp($version);
1297 doprint "$version\n";
1300 sub start_monitor_and_boot {
1301 get_grub_index;
1302 get_version;
1303 install;
1305 start_monitor;
1306 return monitor;
1309 sub check_buildlog {
1310 my ($patch) = @_;
1312 my @files = `git show $patch | diffstat -l`;
1314 open(IN, "git show $patch |") or
1315 dodie "failed to show $patch";
1316 while (<IN>) {
1317 if (m,^--- a/(.*),) {
1318 chomp $1;
1319 $files[$#files] = $1;
1322 close(IN);
1324 open(IN, $buildlog) or dodie "Can't open $buildlog";
1325 while (<IN>) {
1326 if (/^\s*(.*?):.*(warning|error)/) {
1327 my $err = $1;
1328 foreach my $file (@files) {
1329 my $fullpath = "$builddir/$file";
1330 if ($file eq $err || $fullpath eq $err) {
1331 fail "$file built with warnings" and return 0;
1336 close(IN);
1338 return 1;
1341 sub apply_min_config {
1342 my $outconfig = "$output_config.new";
1344 # Read the config file and remove anything that
1345 # is in the force_config hash (from minconfig and others)
1346 # then add the force config back.
1348 doprint "Applying minimum configurations into $output_config.new\n";
1350 open (OUT, ">$outconfig") or
1351 dodie "Can't create $outconfig";
1353 if (-f $output_config) {
1354 open (IN, $output_config) or
1355 dodie "Failed to open $output_config";
1356 while (<IN>) {
1357 if (/^(# )?(CONFIG_[^\s=]*)/) {
1358 next if (defined($force_config{$2}));
1360 print OUT;
1362 close IN;
1364 foreach my $config (keys %force_config) {
1365 print OUT "$force_config{$config}\n";
1367 close OUT;
1369 run_command "mv $outconfig $output_config";
1372 sub make_oldconfig {
1374 my @force_list = keys %force_config;
1376 if ($#force_list >= 0) {
1377 apply_min_config;
1380 if (!run_command "$make oldnoconfig") {
1381 # Perhaps oldnoconfig doesn't exist in this version of the kernel
1382 # try a yes '' | oldconfig
1383 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1384 run_command "yes '' | $make oldconfig" or
1385 dodie "failed make config oldconfig";
1389 # read a config file and use this to force new configs.
1390 sub load_force_config {
1391 my ($config) = @_;
1393 open(IN, $config) or
1394 dodie "failed to read $config";
1395 while (<IN>) {
1396 chomp;
1397 if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1398 $force_config{$1} = $_;
1399 } elsif (/^# (CONFIG_\S*) is not set/) {
1400 $force_config{$1} = $_;
1403 close IN;
1406 sub build {
1407 my ($type) = @_;
1409 unlink $buildlog;
1411 # Failed builds should not reboot the target
1412 my $save_no_reboot = $no_reboot;
1413 $no_reboot = 1;
1415 if (defined($pre_build)) {
1416 my $ret = run_command $pre_build;
1417 if (!$ret && defined($pre_build_die) &&
1418 $pre_build_die) {
1419 dodie "failed to pre_build\n";
1423 if ($type =~ /^useconfig:(.*)/) {
1424 run_command "cp $1 $output_config" or
1425 dodie "could not copy $1 to .config";
1427 $type = "oldconfig";
1430 # old config can ask questions
1431 if ($type eq "oldconfig") {
1432 $type = "oldnoconfig";
1434 # allow for empty configs
1435 run_command "touch $output_config";
1437 if (!$noclean) {
1438 run_command "mv $output_config $outputdir/config_temp" or
1439 dodie "moving .config";
1441 run_command "$make mrproper" or dodie "make mrproper";
1443 run_command "mv $outputdir/config_temp $output_config" or
1444 dodie "moving config_temp";
1447 } elsif (!$noclean) {
1448 unlink "$output_config";
1449 run_command "$make mrproper" or
1450 dodie "make mrproper";
1453 # add something to distinguish this build
1454 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
1455 print OUT "$localversion\n";
1456 close(OUT);
1458 if (defined($minconfig)) {
1459 load_force_config($minconfig);
1462 if ($type ne "oldnoconfig") {
1463 run_command "$make $type" or
1464 dodie "failed make config";
1466 # Run old config regardless, to enforce min configurations
1467 make_oldconfig;
1469 $redirect = "$buildlog";
1470 my $build_ret = run_command "$make $build_options";
1471 undef $redirect;
1473 if (defined($post_build)) {
1474 my $ret = run_command $post_build;
1475 if (!$ret && defined($post_build_die) &&
1476 $post_build_die) {
1477 dodie "failed to post_build\n";
1481 if (!$build_ret) {
1482 # bisect may need this to pass
1483 if ($in_bisect) {
1484 $no_reboot = $save_no_reboot;
1485 return 0;
1487 fail "failed build" and return 0;
1490 $no_reboot = $save_no_reboot;
1492 return 1;
1495 sub halt {
1496 if (!run_ssh "halt" or defined($power_off)) {
1497 if (defined($poweroff_after_halt)) {
1498 sleep $poweroff_after_halt;
1499 run_command "$power_off";
1501 } else {
1502 # nope? the zap it!
1503 run_command "$power_off";
1507 sub success {
1508 my ($i) = @_;
1510 $successes++;
1512 my $name = "";
1514 if (defined($test_name)) {
1515 $name = " ($test_name)";
1518 doprint "\n\n*******************************************\n";
1519 doprint "*******************************************\n";
1520 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n";
1521 doprint "*******************************************\n";
1522 doprint "*******************************************\n";
1524 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1525 doprint "Reboot and wait $sleep_time seconds\n";
1526 reboot $sleep_time;
1530 sub answer_bisect {
1531 for (;;) {
1532 doprint "Pass or fail? [p/f]";
1533 my $ans = <STDIN>;
1534 chomp $ans;
1535 if ($ans eq "p" || $ans eq "P") {
1536 return 1;
1537 } elsif ($ans eq "f" || $ans eq "F") {
1538 return 0;
1539 } else {
1540 print "Please answer 'P' or 'F'\n";
1545 sub child_run_test {
1546 my $failed = 0;
1548 # child should have no power
1549 $reboot_on_error = 0;
1550 $poweroff_on_error = 0;
1551 $die_on_failure = 1;
1553 run_command $run_test or $failed = 1;
1554 exit $failed;
1557 my $child_done;
1559 sub child_finished {
1560 $child_done = 1;
1563 sub do_run_test {
1564 my $child_pid;
1565 my $child_exit;
1566 my $line;
1567 my $full_line;
1568 my $bug = 0;
1570 wait_for_monitor 1;
1572 doprint "run test $run_test\n";
1574 $child_done = 0;
1576 $SIG{CHLD} = qw(child_finished);
1578 $child_pid = fork;
1580 child_run_test if (!$child_pid);
1582 $full_line = "";
1584 do {
1585 $line = wait_for_input($monitor_fp, 1);
1586 if (defined($line)) {
1588 # we are not guaranteed to get a full line
1589 $full_line .= $line;
1590 doprint $line;
1592 if ($full_line =~ /call trace:/i) {
1593 $bug = 1;
1596 if ($full_line =~ /Kernel panic -/) {
1597 $bug = 1;
1600 if ($line =~ /\n/) {
1601 $full_line = "";
1604 } while (!$child_done && !$bug);
1606 if ($bug) {
1607 my $failure_start = time;
1608 my $now;
1609 do {
1610 $line = wait_for_input($monitor_fp, 1);
1611 if (defined($line)) {
1612 doprint $line;
1614 $now = time;
1615 if ($now - $failure_start >= $stop_after_failure) {
1616 last;
1618 } while (defined($line));
1620 doprint "Detected kernel crash!\n";
1621 # kill the child with extreme prejudice
1622 kill 9, $child_pid;
1625 waitpid $child_pid, 0;
1626 $child_exit = $?;
1628 if ($bug || $child_exit) {
1629 return 0 if $in_bisect;
1630 fail "test failed" and return 0;
1632 return 1;
1635 sub run_git_bisect {
1636 my ($command) = @_;
1638 doprint "$command ... ";
1640 my $output = `$command 2>&1`;
1641 my $ret = $?;
1643 logit $output;
1645 if ($ret) {
1646 doprint "FAILED\n";
1647 dodie "Failed to git bisect";
1650 doprint "SUCCESS\n";
1651 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1652 doprint "$1 [$2]\n";
1653 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1654 $bisect_bad = $1;
1655 doprint "Found bad commit... $1\n";
1656 return 0;
1657 } else {
1658 # we already logged it, just print it now.
1659 print $output;
1662 return 1;
1665 sub bisect_reboot {
1666 doprint "Reboot and sleep $bisect_sleep_time seconds\n";
1667 reboot $bisect_sleep_time;
1670 # returns 1 on success, 0 on failure, -1 on skip
1671 sub run_bisect_test {
1672 my ($type, $buildtype) = @_;
1674 my $failed = 0;
1675 my $result;
1676 my $output;
1677 my $ret;
1679 $in_bisect = 1;
1681 build $buildtype or $failed = 1;
1683 if ($type ne "build") {
1684 if ($failed && $bisect_skip) {
1685 $in_bisect = 0;
1686 return -1;
1688 dodie "Failed on build" if $failed;
1690 # Now boot the box
1691 start_monitor_and_boot or $failed = 1;
1693 if ($type ne "boot") {
1694 if ($failed && $bisect_skip) {
1695 end_monitor;
1696 bisect_reboot;
1697 $in_bisect = 0;
1698 return -1;
1700 dodie "Failed on boot" if $failed;
1702 do_run_test or $failed = 1;
1704 end_monitor;
1707 if ($failed) {
1708 $result = 0;
1709 } else {
1710 $result = 1;
1713 # reboot the box to a kernel we can ssh to
1714 if ($type ne "build") {
1715 bisect_reboot;
1717 $in_bisect = 0;
1719 return $result;
1722 sub run_bisect {
1723 my ($type) = @_;
1724 my $buildtype = "oldconfig";
1726 # We should have a minconfig to use?
1727 if (defined($minconfig)) {
1728 $buildtype = "useconfig:$minconfig";
1731 my $ret = run_bisect_test $type, $buildtype;
1733 if ($bisect_manual) {
1734 $ret = answer_bisect;
1737 # Are we looking for where it worked, not failed?
1738 if ($reverse_bisect) {
1739 $ret = !$ret;
1742 if ($ret > 0) {
1743 return "good";
1744 } elsif ($ret == 0) {
1745 return "bad";
1746 } elsif ($bisect_skip) {
1747 doprint "HIT A BAD COMMIT ... SKIPPING\n";
1748 return "skip";
1752 sub bisect {
1753 my ($i) = @_;
1755 my $result;
1757 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
1758 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
1759 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
1761 my $good = $opt{"BISECT_GOOD[$i]"};
1762 my $bad = $opt{"BISECT_BAD[$i]"};
1763 my $type = $opt{"BISECT_TYPE[$i]"};
1764 my $start = $opt{"BISECT_START[$i]"};
1765 my $replay = $opt{"BISECT_REPLAY[$i]"};
1766 my $start_files = $opt{"BISECT_FILES[$i]"};
1768 if (defined($start_files)) {
1769 $start_files = " -- " . $start_files;
1770 } else {
1771 $start_files = "";
1774 # convert to true sha1's
1775 $good = get_sha1($good);
1776 $bad = get_sha1($bad);
1778 if (defined($opt{"BISECT_REVERSE[$i]"}) &&
1779 $opt{"BISECT_REVERSE[$i]"} == 1) {
1780 doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1781 $reverse_bisect = 1;
1782 } else {
1783 $reverse_bisect = 0;
1786 # Can't have a test without having a test to run
1787 if ($type eq "test" && !defined($run_test)) {
1788 $type = "boot";
1791 my $check = $opt{"BISECT_CHECK[$i]"};
1792 if (defined($check) && $check ne "0") {
1794 # get current HEAD
1795 my $head = get_sha1("HEAD");
1797 if ($check ne "good") {
1798 doprint "TESTING BISECT BAD [$bad]\n";
1799 run_command "git checkout $bad" or
1800 die "Failed to checkout $bad";
1802 $result = run_bisect $type;
1804 if ($result ne "bad") {
1805 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
1809 if ($check ne "bad") {
1810 doprint "TESTING BISECT GOOD [$good]\n";
1811 run_command "git checkout $good" or
1812 die "Failed to checkout $good";
1814 $result = run_bisect $type;
1816 if ($result ne "good") {
1817 fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
1821 # checkout where we started
1822 run_command "git checkout $head" or
1823 die "Failed to checkout $head";
1826 run_command "git bisect start$start_files" or
1827 dodie "could not start bisect";
1829 run_command "git bisect good $good" or
1830 dodie "could not set bisect good to $good";
1832 run_git_bisect "git bisect bad $bad" or
1833 dodie "could not set bisect bad to $bad";
1835 if (defined($replay)) {
1836 run_command "git bisect replay $replay" or
1837 dodie "failed to run replay";
1840 if (defined($start)) {
1841 run_command "git checkout $start" or
1842 dodie "failed to checkout $start";
1845 my $test;
1846 do {
1847 $result = run_bisect $type;
1848 $test = run_git_bisect "git bisect $result";
1849 } while ($test);
1851 run_command "git bisect log" or
1852 dodie "could not capture git bisect log";
1854 run_command "git bisect reset" or
1855 dodie "could not reset git bisect";
1857 doprint "Bad commit was [$bisect_bad]\n";
1859 success $i;
1862 my %config_ignore;
1863 my %config_set;
1865 my %config_list;
1866 my %null_config;
1868 my %dependency;
1870 sub assign_configs {
1871 my ($hash, $config) = @_;
1873 open (IN, $config)
1874 or dodie "Failed to read $config";
1876 while (<IN>) {
1877 if (/^((CONFIG\S*)=.*)/) {
1878 ${$hash}{$2} = $1;
1882 close(IN);
1885 sub process_config_ignore {
1886 my ($config) = @_;
1888 assign_configs \%config_ignore, $config;
1891 sub read_current_config {
1892 my ($config_ref) = @_;
1894 %{$config_ref} = ();
1895 undef %{$config_ref};
1897 my @key = keys %{$config_ref};
1898 if ($#key >= 0) {
1899 print "did not delete!\n";
1900 exit;
1902 open (IN, "$output_config");
1904 while (<IN>) {
1905 if (/^(CONFIG\S+)=(.*)/) {
1906 ${$config_ref}{$1} = $2;
1909 close(IN);
1912 sub get_dependencies {
1913 my ($config) = @_;
1915 my $arr = $dependency{$config};
1916 if (!defined($arr)) {
1917 return ();
1920 my @deps = @{$arr};
1922 foreach my $dep (@{$arr}) {
1923 print "ADD DEP $dep\n";
1924 @deps = (@deps, get_dependencies $dep);
1927 return @deps;
1930 sub create_config {
1931 my @configs = @_;
1933 open(OUT, ">$output_config") or dodie "Can not write to $output_config";
1935 foreach my $config (@configs) {
1936 print OUT "$config_set{$config}\n";
1937 my @deps = get_dependencies $config;
1938 foreach my $dep (@deps) {
1939 print OUT "$config_set{$dep}\n";
1943 foreach my $config (keys %config_ignore) {
1944 print OUT "$config_ignore{$config}\n";
1946 close(OUT);
1948 # exit;
1949 make_oldconfig;
1952 sub compare_configs {
1953 my (%a, %b) = @_;
1955 foreach my $item (keys %a) {
1956 if (!defined($b{$item})) {
1957 print "diff $item\n";
1958 return 1;
1960 delete $b{$item};
1963 my @keys = keys %b;
1964 if ($#keys) {
1965 print "diff2 $keys[0]\n";
1967 return -1 if ($#keys >= 0);
1969 return 0;
1972 sub run_config_bisect_test {
1973 my ($type) = @_;
1975 return run_bisect_test $type, "oldconfig";
1978 sub process_passed {
1979 my (%configs) = @_;
1981 doprint "These configs had no failure: (Enabling them for further compiles)\n";
1982 # Passed! All these configs are part of a good compile.
1983 # Add them to the min options.
1984 foreach my $config (keys %configs) {
1985 if (defined($config_list{$config})) {
1986 doprint " removing $config\n";
1987 $config_ignore{$config} = $config_list{$config};
1988 delete $config_list{$config};
1991 doprint "config copied to $outputdir/config_good\n";
1992 run_command "cp -f $output_config $outputdir/config_good";
1995 sub process_failed {
1996 my ($config) = @_;
1998 doprint "\n\n***************************************\n";
1999 doprint "Found bad config: $config\n";
2000 doprint "***************************************\n\n";
2003 sub run_config_bisect {
2005 my @start_list = keys %config_list;
2007 if ($#start_list < 0) {
2008 doprint "No more configs to test!!!\n";
2009 return -1;
2012 doprint "***** RUN TEST ***\n";
2013 my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
2014 my $ret;
2015 my %current_config;
2017 my $count = $#start_list + 1;
2018 doprint " $count configs to test\n";
2020 my $half = int($#start_list / 2);
2022 do {
2023 my @tophalf = @start_list[0 .. $half];
2025 create_config @tophalf;
2026 read_current_config \%current_config;
2028 $count = $#tophalf + 1;
2029 doprint "Testing $count configs\n";
2030 my $found = 0;
2031 # make sure we test something
2032 foreach my $config (@tophalf) {
2033 if (defined($current_config{$config})) {
2034 logit " $config\n";
2035 $found = 1;
2038 if (!$found) {
2039 # try the other half
2040 doprint "Top half produced no set configs, trying bottom half\n";
2041 @tophalf = @start_list[$half + 1 .. $#start_list];
2042 create_config @tophalf;
2043 read_current_config \%current_config;
2044 foreach my $config (@tophalf) {
2045 if (defined($current_config{$config})) {
2046 logit " $config\n";
2047 $found = 1;
2050 if (!$found) {
2051 doprint "Failed: Can't make new config with current configs\n";
2052 foreach my $config (@start_list) {
2053 doprint " CONFIG: $config\n";
2055 return -1;
2057 $count = $#tophalf + 1;
2058 doprint "Testing $count configs\n";
2061 $ret = run_config_bisect_test $type;
2062 if ($bisect_manual) {
2063 $ret = answer_bisect;
2065 if ($ret) {
2066 process_passed %current_config;
2067 return 0;
2070 doprint "This config had a failure.\n";
2071 doprint "Removing these configs that were not set in this config:\n";
2072 doprint "config copied to $outputdir/config_bad\n";
2073 run_command "cp -f $output_config $outputdir/config_bad";
2075 # A config exists in this group that was bad.
2076 foreach my $config (keys %config_list) {
2077 if (!defined($current_config{$config})) {
2078 doprint " removing $config\n";
2079 delete $config_list{$config};
2083 @start_list = @tophalf;
2085 if ($#start_list == 0) {
2086 process_failed $start_list[0];
2087 return 1;
2090 # remove half the configs we are looking at and see if
2091 # they are good.
2092 $half = int($#start_list / 2);
2093 } while ($#start_list > 0);
2095 # we found a single config, try it again unless we are running manually
2097 if ($bisect_manual) {
2098 process_failed $start_list[0];
2099 return 1;
2102 my @tophalf = @start_list[0 .. 0];
2104 $ret = run_config_bisect_test $type;
2105 if ($ret) {
2106 process_passed %current_config;
2107 return 0;
2110 process_failed $start_list[0];
2111 return 1;
2114 sub config_bisect {
2115 my ($i) = @_;
2117 my $start_config = $opt{"CONFIG_BISECT[$i]"};
2119 my $tmpconfig = "$tmpdir/use_config";
2121 if (defined($config_bisect_good)) {
2122 process_config_ignore $config_bisect_good;
2125 # Make the file with the bad config and the min config
2126 if (defined($minconfig)) {
2127 # read the min config for things to ignore
2128 run_command "cp $minconfig $tmpconfig" or
2129 dodie "failed to copy $minconfig to $tmpconfig";
2130 } else {
2131 unlink $tmpconfig;
2134 if (-f $tmpconfig) {
2135 load_force_config($tmpconfig);
2136 process_config_ignore $tmpconfig;
2139 # now process the start config
2140 run_command "cp $start_config $output_config" or
2141 dodie "failed to copy $start_config to $output_config";
2143 # read directly what we want to check
2144 my %config_check;
2145 open (IN, $output_config)
2146 or dodie "faied to open $output_config";
2148 while (<IN>) {
2149 if (/^((CONFIG\S*)=.*)/) {
2150 $config_check{$2} = $1;
2153 close(IN);
2155 # Now run oldconfig with the minconfig
2156 make_oldconfig;
2158 # check to see what we lost (or gained)
2159 open (IN, $output_config)
2160 or dodie "Failed to read $start_config";
2162 my %removed_configs;
2163 my %added_configs;
2165 while (<IN>) {
2166 if (/^((CONFIG\S*)=.*)/) {
2167 # save off all options
2168 $config_set{$2} = $1;
2169 if (defined($config_check{$2})) {
2170 if (defined($config_ignore{$2})) {
2171 $removed_configs{$2} = $1;
2172 } else {
2173 $config_list{$2} = $1;
2175 } elsif (!defined($config_ignore{$2})) {
2176 $added_configs{$2} = $1;
2177 $config_list{$2} = $1;
2181 close(IN);
2183 my @confs = keys %removed_configs;
2184 if ($#confs >= 0) {
2185 doprint "Configs overridden by default configs and removed from check:\n";
2186 foreach my $config (@confs) {
2187 doprint " $config\n";
2190 @confs = keys %added_configs;
2191 if ($#confs >= 0) {
2192 doprint "Configs appearing in make oldconfig and added:\n";
2193 foreach my $config (@confs) {
2194 doprint " $config\n";
2198 my %config_test;
2199 my $once = 0;
2201 # Sometimes kconfig does weird things. We must make sure
2202 # that the config we autocreate has everything we need
2203 # to test, otherwise we may miss testing configs, or
2204 # may not be able to create a new config.
2205 # Here we create a config with everything set.
2206 create_config (keys %config_list);
2207 read_current_config \%config_test;
2208 foreach my $config (keys %config_list) {
2209 if (!defined($config_test{$config})) {
2210 if (!$once) {
2211 $once = 1;
2212 doprint "Configs not produced by kconfig (will not be checked):\n";
2214 doprint " $config\n";
2215 delete $config_list{$config};
2218 my $ret;
2219 do {
2220 $ret = run_config_bisect;
2221 } while (!$ret);
2223 return $ret if ($ret < 0);
2225 success $i;
2228 sub patchcheck_reboot {
2229 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
2230 reboot $patchcheck_sleep_time;
2233 sub patchcheck {
2234 my ($i) = @_;
2236 die "PATCHCHECK_START[$i] not defined\n"
2237 if (!defined($opt{"PATCHCHECK_START[$i]"}));
2238 die "PATCHCHECK_TYPE[$i] not defined\n"
2239 if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
2241 my $start = $opt{"PATCHCHECK_START[$i]"};
2243 my $end = "HEAD";
2244 if (defined($opt{"PATCHCHECK_END[$i]"})) {
2245 $end = $opt{"PATCHCHECK_END[$i]"};
2248 # Get the true sha1's since we can use things like HEAD~3
2249 $start = get_sha1($start);
2250 $end = get_sha1($end);
2252 my $type = $opt{"PATCHCHECK_TYPE[$i]"};
2254 # Can't have a test without having a test to run
2255 if ($type eq "test" && !defined($run_test)) {
2256 $type = "boot";
2259 open (IN, "git log --pretty=oneline $end|") or
2260 dodie "could not get git list";
2262 my @list;
2264 while (<IN>) {
2265 chomp;
2266 $list[$#list+1] = $_;
2267 last if (/^$start/);
2269 close(IN);
2271 if ($list[$#list] !~ /^$start/) {
2272 fail "SHA1 $start not found";
2275 # go backwards in the list
2276 @list = reverse @list;
2278 my $save_clean = $noclean;
2279 my %ignored_warnings;
2281 if (defined($ignore_warnings)) {
2282 foreach my $sha1 (split /\s+/, $ignore_warnings) {
2283 $ignored_warnings{$sha1} = 1;
2287 $in_patchcheck = 1;
2288 foreach my $item (@list) {
2289 my $sha1 = $item;
2290 $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
2292 doprint "\nProcessing commit $item\n\n";
2294 run_command "git checkout $sha1" or
2295 die "Failed to checkout $sha1";
2297 # only clean on the first and last patch
2298 if ($item eq $list[0] ||
2299 $item eq $list[$#list]) {
2300 $noclean = $save_clean;
2301 } else {
2302 $noclean = 1;
2305 if (defined($minconfig)) {
2306 build "useconfig:$minconfig" or return 0;
2307 } else {
2308 # ?? no config to use?
2309 build "oldconfig" or return 0;
2313 if (!defined($ignored_warnings{$sha1})) {
2314 check_buildlog $sha1 or return 0;
2317 next if ($type eq "build");
2319 my $failed = 0;
2321 start_monitor_and_boot or $failed = 1;
2323 if (!$failed && $type ne "boot"){
2324 do_run_test or $failed = 1;
2326 end_monitor;
2327 return 0 if ($failed);
2329 patchcheck_reboot;
2332 $in_patchcheck = 0;
2333 success $i;
2335 return 1;
2338 my %depends;
2339 my $iflevel = 0;
2340 my @ifdeps;
2342 # prevent recursion
2343 my %read_kconfigs;
2345 # taken from streamline_config.pl
2346 sub read_kconfig {
2347 my ($kconfig) = @_;
2349 my $state = "NONE";
2350 my $config;
2351 my @kconfigs;
2353 my $cont = 0;
2354 my $line;
2357 if (! -f $kconfig) {
2358 doprint "file $kconfig does not exist, skipping\n";
2359 return;
2362 open(KIN, "$kconfig")
2363 or die "Can't open $kconfig";
2364 while (<KIN>) {
2365 chomp;
2367 # Make sure that lines ending with \ continue
2368 if ($cont) {
2369 $_ = $line . " " . $_;
2372 if (s/\\$//) {
2373 $cont = 1;
2374 $line = $_;
2375 next;
2378 $cont = 0;
2380 # collect any Kconfig sources
2381 if (/^source\s*"(.*)"/) {
2382 $kconfigs[$#kconfigs+1] = $1;
2385 # configs found
2386 if (/^\s*(menu)?config\s+(\S+)\s*$/) {
2387 $state = "NEW";
2388 $config = $2;
2390 for (my $i = 0; $i < $iflevel; $i++) {
2391 if ($i) {
2392 $depends{$config} .= " " . $ifdeps[$i];
2393 } else {
2394 $depends{$config} = $ifdeps[$i];
2396 $state = "DEP";
2399 # collect the depends for the config
2400 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
2402 if (defined($depends{$1})) {
2403 $depends{$config} .= " " . $1;
2404 } else {
2405 $depends{$config} = $1;
2408 # Get the configs that select this config
2409 } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
2410 if (defined($depends{$1})) {
2411 $depends{$1} .= " " . $config;
2412 } else {
2413 $depends{$1} = $config;
2416 # Check for if statements
2417 } elsif (/^if\s+(.*\S)\s*$/) {
2418 my $deps = $1;
2419 # remove beginning and ending non text
2420 $deps =~ s/^[^a-zA-Z0-9_]*//;
2421 $deps =~ s/[^a-zA-Z0-9_]*$//;
2423 my @deps = split /[^a-zA-Z0-9_]+/, $deps;
2425 $ifdeps[$iflevel++] = join ':', @deps;
2427 } elsif (/^endif/) {
2429 $iflevel-- if ($iflevel);
2431 # stop on "help"
2432 } elsif (/^\s*help\s*$/) {
2433 $state = "NONE";
2436 close(KIN);
2438 # read in any configs that were found.
2439 foreach $kconfig (@kconfigs) {
2440 if (!defined($read_kconfigs{$kconfig})) {
2441 $read_kconfigs{$kconfig} = 1;
2442 read_kconfig("$builddir/$kconfig");
2447 sub read_depends {
2448 # find out which arch this is by the kconfig file
2449 open (IN, $output_config)
2450 or dodie "Failed to read $output_config";
2451 my $arch;
2452 while (<IN>) {
2453 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
2454 $arch = $1;
2455 last;
2458 close IN;
2460 if (!defined($arch)) {
2461 doprint "Could not find arch from config file\n";
2462 doprint "no dependencies used\n";
2463 return;
2466 # arch is really the subarch, we need to know
2467 # what directory to look at.
2468 if ($arch eq "i386" || $arch eq "x86_64") {
2469 $arch = "x86";
2470 } elsif ($arch =~ /^tile/) {
2471 $arch = "tile";
2474 my $kconfig = "$builddir/arch/$arch/Kconfig";
2476 if (! -f $kconfig && $arch =~ /\d$/) {
2477 my $orig = $arch;
2478 # some subarchs have numbers, truncate them
2479 $arch =~ s/\d*$//;
2480 $kconfig = "$builddir/arch/$arch/Kconfig";
2481 if (! -f $kconfig) {
2482 doprint "No idea what arch dir $orig is for\n";
2483 doprint "no dependencies used\n";
2484 return;
2488 read_kconfig($kconfig);
2491 sub read_config_list {
2492 my ($config) = @_;
2494 open (IN, $config)
2495 or dodie "Failed to read $config";
2497 while (<IN>) {
2498 if (/^((CONFIG\S*)=.*)/) {
2499 if (!defined($config_ignore{$2})) {
2500 $config_list{$2} = $1;
2505 close(IN);
2508 sub read_output_config {
2509 my ($config) = @_;
2511 assign_configs \%config_ignore, $config;
2514 sub make_new_config {
2515 my @configs = @_;
2517 open (OUT, ">$output_config")
2518 or dodie "Failed to write $output_config";
2520 foreach my $config (@configs) {
2521 print OUT "$config\n";
2523 close OUT;
2526 sub get_depends {
2527 my ($dep) = @_;
2529 my $kconfig = $dep;
2530 $kconfig =~ s/CONFIG_//;
2532 $dep = $depends{"$kconfig"};
2534 # the dep string we have saves the dependencies as they
2535 # were found, including expressions like ! && ||. We
2536 # want to split this out into just an array of configs.
2538 my $valid = "A-Za-z_0-9";
2540 my @configs;
2542 while ($dep =~ /[$valid]/) {
2544 if ($dep =~ /^[^$valid]*([$valid]+)/) {
2545 my $conf = "CONFIG_" . $1;
2547 $configs[$#configs + 1] = $conf;
2549 $dep =~ s/^[^$valid]*[$valid]+//;
2550 } else {
2551 die "this should never happen";
2555 return @configs;
2558 my %min_configs;
2559 my %keep_configs;
2560 my %save_configs;
2561 my %processed_configs;
2562 my %nochange_config;
2564 sub test_this_config {
2565 my ($config) = @_;
2567 my $found;
2569 # if we already processed this config, skip it
2570 if (defined($processed_configs{$config})) {
2571 return undef;
2573 $processed_configs{$config} = 1;
2575 # if this config failed during this round, skip it
2576 if (defined($nochange_config{$config})) {
2577 return undef;
2580 my $kconfig = $config;
2581 $kconfig =~ s/CONFIG_//;
2583 # Test dependencies first
2584 if (defined($depends{"$kconfig"})) {
2585 my @parents = get_depends $config;
2586 foreach my $parent (@parents) {
2587 # if the parent is in the min config, check it first
2588 next if (!defined($min_configs{$parent}));
2589 $found = test_this_config($parent);
2590 if (defined($found)) {
2591 return $found;
2596 # Remove this config from the list of configs
2597 # do a make oldnoconfig and then read the resulting
2598 # .config to make sure it is missing the config that
2599 # we had before
2600 my %configs = %min_configs;
2601 delete $configs{$config};
2602 make_new_config ((values %configs), (values %keep_configs));
2603 make_oldconfig;
2604 undef %configs;
2605 assign_configs \%configs, $output_config;
2607 return $config if (!defined($configs{$config}));
2609 doprint "disabling config $config did not change .config\n";
2611 $nochange_config{$config} = 1;
2613 return undef;
2616 sub make_min_config {
2617 my ($i) = @_;
2619 if (!defined($output_minconfig)) {
2620 fail "OUTPUT_MIN_CONFIG not defined" and return;
2623 # If output_minconfig exists, and the start_minconfig
2624 # came from min_config, than ask if we should use
2625 # that instead.
2626 if (-f $output_minconfig && !$start_minconfig_defined) {
2627 print "$output_minconfig exists\n";
2628 if (read_yn " Use it as minconfig?") {
2629 $start_minconfig = $output_minconfig;
2633 if (!defined($start_minconfig)) {
2634 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
2637 my $temp_config = "$tmpdir/temp_config";
2639 # First things first. We build an allnoconfig to find
2640 # out what the defaults are that we can't touch.
2641 # Some are selections, but we really can't handle selections.
2643 my $save_minconfig = $minconfig;
2644 undef $minconfig;
2646 run_command "$make allnoconfig" or return 0;
2648 read_depends;
2650 process_config_ignore $output_config;
2652 undef %save_configs;
2653 undef %min_configs;
2655 if (defined($ignore_config)) {
2656 # make sure the file exists
2657 `touch $ignore_config`;
2658 assign_configs \%save_configs, $ignore_config;
2661 %keep_configs = %save_configs;
2663 doprint "Load initial configs from $start_minconfig\n";
2665 # Look at the current min configs, and save off all the
2666 # ones that were set via the allnoconfig
2667 assign_configs \%min_configs, $start_minconfig;
2669 my @config_keys = keys %min_configs;
2671 # Remove anything that was set by the make allnoconfig
2672 # we shouldn't need them as they get set for us anyway.
2673 foreach my $config (@config_keys) {
2674 # Remove anything in the ignore_config
2675 if (defined($keep_configs{$config})) {
2676 my $file = $ignore_config;
2677 $file =~ s,.*/(.*?)$,$1,;
2678 doprint "$config set by $file ... ignored\n";
2679 delete $min_configs{$config};
2680 next;
2682 # But make sure the settings are the same. If a min config
2683 # sets a selection, we do not want to get rid of it if
2684 # it is not the same as what we have. Just move it into
2685 # the keep configs.
2686 if (defined($config_ignore{$config})) {
2687 if ($config_ignore{$config} ne $min_configs{$config}) {
2688 doprint "$config is in allnoconfig as '$config_ignore{$config}'";
2689 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
2690 $keep_configs{$config} = $min_configs{$config};
2691 } else {
2692 doprint "$config set by allnoconfig ... ignored\n";
2694 delete $min_configs{$config};
2698 my $done = 0;
2699 my $take_two = 0;
2701 while (!$done) {
2703 my $config;
2704 my $found;
2706 # Now disable each config one by one and do a make oldconfig
2707 # till we find a config that changes our list.
2709 # Put configs that did not modify the config at the end.
2710 my @test_configs = keys %min_configs;
2711 my $reset = 1;
2712 for (my $i = 0; $i < $#test_configs; $i++) {
2713 if (!defined($nochange_config{$test_configs[0]})) {
2714 $reset = 0;
2715 last;
2717 # This config didn't change the .config last time.
2718 # Place it at the end
2719 my $config = shift @test_configs;
2720 push @test_configs, $config;
2723 # if every test config has failed to modify the .config file
2724 # in the past, then reset and start over.
2725 if ($reset) {
2726 undef %nochange_config;
2729 undef %processed_configs;
2731 foreach my $config (@test_configs) {
2733 $found = test_this_config $config;
2735 last if (defined($found));
2737 # oh well, try another config
2740 if (!defined($found)) {
2741 # we could have failed due to the nochange_config hash
2742 # reset and try again
2743 if (!$take_two) {
2744 undef %nochange_config;
2745 $take_two = 1;
2746 next;
2748 doprint "No more configs found that we can disable\n";
2749 $done = 1;
2750 last;
2752 $take_two = 0;
2754 $config = $found;
2756 doprint "Test with $config disabled\n";
2758 # set in_bisect to keep build and monitor from dieing
2759 $in_bisect = 1;
2761 my $failed = 0;
2762 build "oldconfig";
2763 start_monitor_and_boot or $failed = 1;
2764 end_monitor;
2766 $in_bisect = 0;
2768 if ($failed) {
2769 doprint "$min_configs{$config} is needed to boot the box... keeping\n";
2770 # this config is needed, add it to the ignore list.
2771 $keep_configs{$config} = $min_configs{$config};
2772 $save_configs{$config} = $min_configs{$config};
2773 delete $min_configs{$config};
2775 # update new ignore configs
2776 if (defined($ignore_config)) {
2777 open (OUT, ">$temp_config")
2778 or die "Can't write to $temp_config";
2779 foreach my $config (keys %save_configs) {
2780 print OUT "$save_configs{$config}\n";
2782 close OUT;
2783 run_command "mv $temp_config $ignore_config" or
2784 dodie "failed to copy update to $ignore_config";
2787 } else {
2788 # We booted without this config, remove it from the minconfigs.
2789 doprint "$config is not needed, disabling\n";
2791 delete $min_configs{$config};
2793 # Also disable anything that is not enabled in this config
2794 my %configs;
2795 assign_configs \%configs, $output_config;
2796 my @config_keys = keys %min_configs;
2797 foreach my $config (@config_keys) {
2798 if (!defined($configs{$config})) {
2799 doprint "$config is not set, disabling\n";
2800 delete $min_configs{$config};
2804 # Save off all the current mandidory configs
2805 open (OUT, ">$temp_config")
2806 or die "Can't write to $temp_config";
2807 foreach my $config (keys %keep_configs) {
2808 print OUT "$keep_configs{$config}\n";
2810 foreach my $config (keys %min_configs) {
2811 print OUT "$min_configs{$config}\n";
2813 close OUT;
2815 run_command "mv $temp_config $output_minconfig" or
2816 dodie "failed to copy update to $output_minconfig";
2819 doprint "Reboot and wait $sleep_time seconds\n";
2820 reboot $sleep_time;
2823 success $i;
2824 return 1;
2827 $#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n";
2829 if ($#ARGV == 0) {
2830 $ktest_config = $ARGV[0];
2831 if (! -f $ktest_config) {
2832 print "$ktest_config does not exist.\n";
2833 if (!read_yn "Create it?") {
2834 exit 0;
2837 } else {
2838 $ktest_config = "ktest.conf";
2841 if (! -f $ktest_config) {
2842 open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
2843 print OUT << "EOF"
2844 # Generated by ktest.pl
2846 # Define each test with TEST_START
2847 # The config options below it will override the defaults
2848 TEST_START
2850 DEFAULTS
2853 close(OUT);
2855 read_config $ktest_config;
2857 if (defined($opt{"LOG_FILE"})) {
2858 $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
2861 # Append any configs entered in manually to the config file.
2862 my @new_configs = keys %entered_configs;
2863 if ($#new_configs >= 0) {
2864 print "\nAppending entered in configs to $ktest_config\n";
2865 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
2866 foreach my $config (@new_configs) {
2867 print OUT "$config = $entered_configs{$config}\n";
2868 $opt{$config} = $entered_configs{$config};
2872 if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
2873 unlink $opt{"LOG_FILE"};
2876 doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
2878 for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
2880 if (!$i) {
2881 doprint "DEFAULT OPTIONS:\n";
2882 } else {
2883 doprint "\nTEST $i OPTIONS";
2884 if (defined($repeat_tests{$i})) {
2885 $repeat = $repeat_tests{$i};
2886 doprint " ITERATE $repeat";
2888 doprint "\n";
2891 foreach my $option (sort keys %opt) {
2893 if ($option =~ /\[(\d+)\]$/) {
2894 next if ($i != $1);
2895 } else {
2896 next if ($i);
2899 doprint "$option = $opt{$option}\n";
2903 sub __set_test_option {
2904 my ($name, $i) = @_;
2906 my $option = "$name\[$i\]";
2908 if (defined($opt{$option})) {
2909 return $opt{$option};
2912 foreach my $test (keys %repeat_tests) {
2913 if ($i >= $test &&
2914 $i < $test + $repeat_tests{$test}) {
2915 $option = "$name\[$test\]";
2916 if (defined($opt{$option})) {
2917 return $opt{$option};
2922 if (defined($opt{$name})) {
2923 return $opt{$name};
2926 return undef;
2929 sub set_test_option {
2930 my ($name, $i) = @_;
2932 my $option = __set_test_option($name, $i);
2933 return $option if (!defined($option));
2935 return eval_option($option, $i);
2938 # First we need to do is the builds
2939 for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2941 # Do not reboot on failing test options
2942 $no_reboot = 1;
2944 $iteration = $i;
2946 my $makecmd = set_test_option("MAKE_CMD", $i);
2948 $machine = set_test_option("MACHINE", $i);
2949 $ssh_user = set_test_option("SSH_USER", $i);
2950 $tmpdir = set_test_option("TMP_DIR", $i);
2951 $outputdir = set_test_option("OUTPUT_DIR", $i);
2952 $builddir = set_test_option("BUILD_DIR", $i);
2953 $test_type = set_test_option("TEST_TYPE", $i);
2954 $build_type = set_test_option("BUILD_TYPE", $i);
2955 $build_options = set_test_option("BUILD_OPTIONS", $i);
2956 $pre_build = set_test_option("PRE_BUILD", $i);
2957 $post_build = set_test_option("POST_BUILD", $i);
2958 $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
2959 $post_build_die = set_test_option("POST_BUILD_DIE", $i);
2960 $power_cycle = set_test_option("POWER_CYCLE", $i);
2961 $reboot = set_test_option("REBOOT", $i);
2962 $noclean = set_test_option("BUILD_NOCLEAN", $i);
2963 $minconfig = set_test_option("MIN_CONFIG", $i);
2964 $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i);
2965 $start_minconfig = set_test_option("START_MIN_CONFIG", $i);
2966 $ignore_config = set_test_option("IGNORE_CONFIG", $i);
2967 $run_test = set_test_option("TEST", $i);
2968 $addconfig = set_test_option("ADD_CONFIG", $i);
2969 $reboot_type = set_test_option("REBOOT_TYPE", $i);
2970 $grub_menu = set_test_option("GRUB_MENU", $i);
2971 $post_install = set_test_option("POST_INSTALL", $i);
2972 $no_install = set_test_option("NO_INSTALL", $i);
2973 $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
2974 $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
2975 $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
2976 $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
2977 $power_off = set_test_option("POWER_OFF", $i);
2978 $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
2979 $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
2980 $sleep_time = set_test_option("SLEEP_TIME", $i);
2981 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
2982 $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
2983 $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
2984 $bisect_manual = set_test_option("BISECT_MANUAL", $i);
2985 $bisect_skip = set_test_option("BISECT_SKIP", $i);
2986 $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
2987 $store_failures = set_test_option("STORE_FAILURES", $i);
2988 $test_name = set_test_option("TEST_NAME", $i);
2989 $timeout = set_test_option("TIMEOUT", $i);
2990 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
2991 $console = set_test_option("CONSOLE", $i);
2992 $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
2993 $success_line = set_test_option("SUCCESS_LINE", $i);
2994 $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i);
2995 $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
2996 $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
2997 $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
2998 $build_target = set_test_option("BUILD_TARGET", $i);
2999 $ssh_exec = set_test_option("SSH_EXEC", $i);
3000 $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
3001 $target_image = set_test_option("TARGET_IMAGE", $i);
3002 $localversion = set_test_option("LOCALVERSION", $i);
3004 $start_minconfig_defined = 1;
3006 if (!defined($start_minconfig)) {
3007 $start_minconfig_defined = 0;
3008 $start_minconfig = $minconfig;
3011 chdir $builddir || die "can't change directory to $builddir";
3013 foreach my $dir ($tmpdir, $outputdir) {
3014 if (!-d $dir) {
3015 mkpath($dir) or
3016 die "can't create $dir";
3020 $ENV{"SSH_USER"} = $ssh_user;
3021 $ENV{"MACHINE"} = $machine;
3023 $target = "$ssh_user\@$machine";
3025 $buildlog = "$tmpdir/buildlog-$machine";
3026 $dmesg = "$tmpdir/dmesg-$machine";
3027 $make = "$makecmd O=$outputdir";
3028 $output_config = "$outputdir/.config";
3030 if ($reboot_type eq "grub") {
3031 dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3032 } elsif (!defined($reboot_script)) {
3033 dodie "REBOOT_SCRIPT not defined"
3036 my $run_type = $build_type;
3037 if ($test_type eq "patchcheck") {
3038 $run_type = $opt{"PATCHCHECK_TYPE[$i]"};
3039 } elsif ($test_type eq "bisect") {
3040 $run_type = $opt{"BISECT_TYPE[$i]"};
3041 } elsif ($test_type eq "config_bisect") {
3042 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
3045 if ($test_type eq "make_min_config") {
3046 $run_type = "";
3049 # mistake in config file?
3050 if (!defined($run_type)) {
3051 $run_type = "ERROR";
3054 my $installme = "";
3055 $installme = " no_install" if ($no_install);
3057 doprint "\n\n";
3058 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
3060 unlink $dmesg;
3061 unlink $buildlog;
3063 if (defined($addconfig)) {
3064 my $min = $minconfig;
3065 if (!defined($minconfig)) {
3066 $min = "";
3068 run_command "cat $addconfig $min > $tmpdir/add_config" or
3069 dodie "Failed to create temp config";
3070 $minconfig = "$tmpdir/add_config";
3073 my $checkout = $opt{"CHECKOUT[$i]"};
3074 if (defined($checkout)) {
3075 run_command "git checkout $checkout" or
3076 die "failed to checkout $checkout";
3079 $no_reboot = 0;
3082 if ($test_type eq "bisect") {
3083 bisect $i;
3084 next;
3085 } elsif ($test_type eq "config_bisect") {
3086 config_bisect $i;
3087 next;
3088 } elsif ($test_type eq "patchcheck") {
3089 patchcheck $i;
3090 next;
3091 } elsif ($test_type eq "make_min_config") {
3092 make_min_config $i;
3093 next;
3096 if ($build_type ne "nobuild") {
3097 build $build_type or next;
3100 if ($test_type eq "install") {
3101 get_version;
3102 install;
3103 success $i;
3104 next;
3107 if ($test_type ne "build") {
3108 my $failed = 0;
3109 start_monitor_and_boot or $failed = 1;
3111 if (!$failed && $test_type ne "boot" && defined($run_test)) {
3112 do_run_test or $failed = 1;
3114 end_monitor;
3115 next if ($failed);
3118 success $i;
3121 if ($opt{"POWEROFF_ON_SUCCESS"}) {
3122 halt;
3123 } elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
3124 reboot;
3127 doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n";
3129 exit 0;