blob: 4915408f6a98c0c6d970a7ef341da7733fa8e6bc [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001#!/usr/bin/perl -w
2#
3# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
4# Licensed under the terms of the GNU GPL License version 2
5#
6
7use strict;
8use IPC::Open2;
9use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
10use File::Path qw(mkpath);
11use File::Copy qw(cp);
12use FileHandle;
13
14my $VERSION = "0.2";
15
16$| = 1;
17
18my %opt;
19my %repeat_tests;
20my %repeats;
21
22#default opts
23my %default = (
24 "NUM_TESTS" => 1,
25 "TEST_TYPE" => "build",
26 "BUILD_TYPE" => "randconfig",
27 "MAKE_CMD" => "make",
28 "TIMEOUT" => 120,
29 "TMP_DIR" => "/tmp/ktest/\${MACHINE}",
30 "SLEEP_TIME" => 60, # sleep time between tests
31 "BUILD_NOCLEAN" => 0,
32 "REBOOT_ON_ERROR" => 0,
33 "POWEROFF_ON_ERROR" => 0,
34 "REBOOT_ON_SUCCESS" => 1,
35 "POWEROFF_ON_SUCCESS" => 0,
36 "BUILD_OPTIONS" => "",
37 "BISECT_SLEEP_TIME" => 60, # sleep time between bisects
38 "PATCHCHECK_SLEEP_TIME" => 60, # sleep time between patch checks
39 "CLEAR_LOG" => 0,
40 "BISECT_MANUAL" => 0,
41 "BISECT_SKIP" => 1,
42 "SUCCESS_LINE" => "login:",
43 "DETECT_TRIPLE_FAULT" => 1,
44 "NO_INSTALL" => 0,
45 "BOOTED_TIMEOUT" => 1,
46 "DIE_ON_FAILURE" => 1,
47 "SSH_EXEC" => "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND",
48 "SCP_TO_TARGET" => "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE",
49 "SCP_TO_TARGET_INSTALL" => "\${SCP_TO_TARGET}",
50 "REBOOT" => "ssh \$SSH_USER\@\$MACHINE reboot",
51 "STOP_AFTER_SUCCESS" => 10,
52 "STOP_AFTER_FAILURE" => 60,
53 "STOP_TEST_AFTER" => 600,
54
55# required, and we will ask users if they don't have them but we keep the default
56# value something that is common.
57 "REBOOT_TYPE" => "grub",
58 "LOCALVERSION" => "-test",
59 "SSH_USER" => "root",
60 "BUILD_TARGET" => "arch/x86/boot/bzImage",
61 "TARGET_IMAGE" => "/boot/vmlinuz-test",
62
63 "LOG_FILE" => undef,
64 "IGNORE_UNUSED" => 0,
65);
66
67my $ktest_config;
68my $version;
69my $machine;
70my $ssh_user;
71my $tmpdir;
72my $builddir;
73my $outputdir;
74my $output_config;
75my $test_type;
76my $build_type;
77my $build_options;
78my $pre_build;
79my $post_build;
80my $pre_build_die;
81my $post_build_die;
82my $reboot_type;
83my $reboot_script;
84my $power_cycle;
85my $reboot;
86my $reboot_on_error;
87my $switch_to_good;
88my $switch_to_test;
89my $poweroff_on_error;
90my $reboot_on_success;
91my $die_on_failure;
92my $powercycle_after_reboot;
93my $poweroff_after_halt;
94my $ssh_exec;
95my $scp_to_target;
96my $scp_to_target_install;
97my $power_off;
98my $grub_menu;
99my $grub_number;
100my $target;
101my $make;
102my $post_install;
103my $no_install;
104my $noclean;
105my $minconfig;
106my $start_minconfig;
107my $start_minconfig_defined;
108my $output_minconfig;
109my $ignore_config;
110my $ignore_errors;
111my $addconfig;
112my $in_bisect = 0;
113my $bisect_bad_commit = "";
114my $reverse_bisect;
115my $bisect_manual;
116my $bisect_skip;
117my $config_bisect_good;
118my $bisect_ret_good;
119my $bisect_ret_bad;
120my $bisect_ret_skip;
121my $bisect_ret_abort;
122my $bisect_ret_default;
123my $in_patchcheck = 0;
124my $run_test;
125my $redirect;
126my $buildlog;
127my $testlog;
128my $dmesg;
129my $monitor_fp;
130my $monitor_pid;
131my $monitor_cnt = 0;
132my $sleep_time;
133my $bisect_sleep_time;
134my $patchcheck_sleep_time;
135my $ignore_warnings;
136my $store_failures;
137my $store_successes;
138my $test_name;
139my $timeout;
140my $booted_timeout;
141my $detect_triplefault;
142my $console;
143my $reboot_success_line;
144my $success_line;
145my $stop_after_success;
146my $stop_after_failure;
147my $stop_test_after;
148my $build_target;
149my $target_image;
150my $checkout;
151my $localversion;
152my $iteration = 0;
153my $successes = 0;
154
155my $bisect_good;
156my $bisect_bad;
157my $bisect_type;
158my $bisect_start;
159my $bisect_replay;
160my $bisect_files;
161my $bisect_reverse;
162my $bisect_check;
163
164my $config_bisect;
165my $config_bisect_type;
166
167my $patchcheck_type;
168my $patchcheck_start;
169my $patchcheck_end;
170
171# set when a test is something other that just building or install
172# which would require more options.
173my $buildonly = 1;
174
175# set when creating a new config
176my $newconfig = 0;
177
178my %entered_configs;
179my %config_help;
180my %variable;
181my %force_config;
182
183# do not force reboots on config problems
184my $no_reboot = 1;
185
186# reboot on success
187my $reboot_success = 0;
188
189my %option_map = (
190 "MACHINE" => \$machine,
191 "SSH_USER" => \$ssh_user,
192 "TMP_DIR" => \$tmpdir,
193 "OUTPUT_DIR" => \$outputdir,
194 "BUILD_DIR" => \$builddir,
195 "TEST_TYPE" => \$test_type,
196 "BUILD_TYPE" => \$build_type,
197 "BUILD_OPTIONS" => \$build_options,
198 "PRE_BUILD" => \$pre_build,
199 "POST_BUILD" => \$post_build,
200 "PRE_BUILD_DIE" => \$pre_build_die,
201 "POST_BUILD_DIE" => \$post_build_die,
202 "POWER_CYCLE" => \$power_cycle,
203 "REBOOT" => \$reboot,
204 "BUILD_NOCLEAN" => \$noclean,
205 "MIN_CONFIG" => \$minconfig,
206 "OUTPUT_MIN_CONFIG" => \$output_minconfig,
207 "START_MIN_CONFIG" => \$start_minconfig,
208 "IGNORE_CONFIG" => \$ignore_config,
209 "TEST" => \$run_test,
210 "ADD_CONFIG" => \$addconfig,
211 "REBOOT_TYPE" => \$reboot_type,
212 "GRUB_MENU" => \$grub_menu,
213 "POST_INSTALL" => \$post_install,
214 "NO_INSTALL" => \$no_install,
215 "REBOOT_SCRIPT" => \$reboot_script,
216 "REBOOT_ON_ERROR" => \$reboot_on_error,
217 "SWITCH_TO_GOOD" => \$switch_to_good,
218 "SWITCH_TO_TEST" => \$switch_to_test,
219 "POWEROFF_ON_ERROR" => \$poweroff_on_error,
220 "REBOOT_ON_SUCCESS" => \$reboot_on_success,
221 "DIE_ON_FAILURE" => \$die_on_failure,
222 "POWER_OFF" => \$power_off,
223 "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot,
224 "POWEROFF_AFTER_HALT" => \$poweroff_after_halt,
225 "SLEEP_TIME" => \$sleep_time,
226 "BISECT_SLEEP_TIME" => \$bisect_sleep_time,
227 "PATCHCHECK_SLEEP_TIME" => \$patchcheck_sleep_time,
228 "IGNORE_WARNINGS" => \$ignore_warnings,
229 "IGNORE_ERRORS" => \$ignore_errors,
230 "BISECT_MANUAL" => \$bisect_manual,
231 "BISECT_SKIP" => \$bisect_skip,
232 "CONFIG_BISECT_GOOD" => \$config_bisect_good,
233 "BISECT_RET_GOOD" => \$bisect_ret_good,
234 "BISECT_RET_BAD" => \$bisect_ret_bad,
235 "BISECT_RET_SKIP" => \$bisect_ret_skip,
236 "BISECT_RET_ABORT" => \$bisect_ret_abort,
237 "BISECT_RET_DEFAULT" => \$bisect_ret_default,
238 "STORE_FAILURES" => \$store_failures,
239 "STORE_SUCCESSES" => \$store_successes,
240 "TEST_NAME" => \$test_name,
241 "TIMEOUT" => \$timeout,
242 "BOOTED_TIMEOUT" => \$booted_timeout,
243 "CONSOLE" => \$console,
244 "DETECT_TRIPLE_FAULT" => \$detect_triplefault,
245 "SUCCESS_LINE" => \$success_line,
246 "REBOOT_SUCCESS_LINE" => \$reboot_success_line,
247 "STOP_AFTER_SUCCESS" => \$stop_after_success,
248 "STOP_AFTER_FAILURE" => \$stop_after_failure,
249 "STOP_TEST_AFTER" => \$stop_test_after,
250 "BUILD_TARGET" => \$build_target,
251 "SSH_EXEC" => \$ssh_exec,
252 "SCP_TO_TARGET" => \$scp_to_target,
253 "SCP_TO_TARGET_INSTALL" => \$scp_to_target_install,
254 "CHECKOUT" => \$checkout,
255 "TARGET_IMAGE" => \$target_image,
256 "LOCALVERSION" => \$localversion,
257
258 "BISECT_GOOD" => \$bisect_good,
259 "BISECT_BAD" => \$bisect_bad,
260 "BISECT_TYPE" => \$bisect_type,
261 "BISECT_START" => \$bisect_start,
262 "BISECT_REPLAY" => \$bisect_replay,
263 "BISECT_FILES" => \$bisect_files,
264 "BISECT_REVERSE" => \$bisect_reverse,
265 "BISECT_CHECK" => \$bisect_check,
266
267 "CONFIG_BISECT" => \$config_bisect,
268 "CONFIG_BISECT_TYPE" => \$config_bisect_type,
269
270 "PATCHCHECK_TYPE" => \$patchcheck_type,
271 "PATCHCHECK_START" => \$patchcheck_start,
272 "PATCHCHECK_END" => \$patchcheck_end,
273);
274
275# Options may be used by other options, record them.
276my %used_options;
277
278# default variables that can be used
279chomp ($variable{"PWD"} = `pwd`);
280
281$config_help{"MACHINE"} = << "EOF"
282 The machine hostname that you will test.
283 For build only tests, it is still needed to differentiate log files.
284EOF
285 ;
286$config_help{"SSH_USER"} = << "EOF"
287 The box is expected to have ssh on normal bootup, provide the user
288 (most likely root, since you need privileged operations)
289EOF
290 ;
291$config_help{"BUILD_DIR"} = << "EOF"
292 The directory that contains the Linux source code (full path).
293 You can use \${PWD} that will be the path where ktest.pl is run, or use
294 \${THIS_DIR} which is assigned \${PWD} but may be changed later.
295EOF
296 ;
297$config_help{"OUTPUT_DIR"} = << "EOF"
298 The directory that the objects will be built (full path).
299 (can not be same as BUILD_DIR)
300 You can use \${PWD} that will be the path where ktest.pl is run, or use
301 \${THIS_DIR} which is assigned \${PWD} but may be changed later.
302EOF
303 ;
304$config_help{"BUILD_TARGET"} = << "EOF"
305 The location of the compiled file to copy to the target.
306 (relative to OUTPUT_DIR)
307EOF
308 ;
309$config_help{"BUILD_OPTIONS"} = << "EOF"
310 Options to add to \"make\" when building.
311 i.e. -j20
312EOF
313 ;
314$config_help{"TARGET_IMAGE"} = << "EOF"
315 The place to put your image on the test machine.
316EOF
317 ;
318$config_help{"POWER_CYCLE"} = << "EOF"
319 A script or command to reboot the box.
320
321 Here is a digital loggers power switch example
322 POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
323
324 Here is an example to reboot a virtual box on the current host
325 with the name "Guest".
326 POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
327EOF
328 ;
329$config_help{"CONSOLE"} = << "EOF"
330 The script or command that reads the console
331
332 If you use ttywatch server, something like the following would work.
333CONSOLE = nc -d localhost 3001
334
335 For a virtual machine with guest name "Guest".
336CONSOLE = virsh console Guest
337EOF
338 ;
339$config_help{"LOCALVERSION"} = << "EOF"
340 Required version ending to differentiate the test
341 from other linux builds on the system.
342EOF
343 ;
344$config_help{"REBOOT_TYPE"} = << "EOF"
345 Way to reboot the box to the test kernel.
346 Only valid options so far are "grub" and "script".
347
348 If you specify grub, it will assume grub version 1
349 and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
350 and select that target to reboot to the kernel. If this is not
351 your setup, then specify "script" and have a command or script
352 specified in REBOOT_SCRIPT to boot to the target.
353
354 The entry in /boot/grub/menu.lst must be entered in manually.
355 The test will not modify that file.
356EOF
357 ;
358$config_help{"GRUB_MENU"} = << "EOF"
359 The grub title name for the test kernel to boot
360 (Only mandatory if REBOOT_TYPE = grub)
361
362 Note, ktest.pl will not update the grub menu.lst, you need to
363 manually add an option for the test. ktest.pl will search
364 the grub menu.lst for this option to find what kernel to
365 reboot into.
366
367 For example, if in the /boot/grub/menu.lst the test kernel title has:
368 title Test Kernel
369 kernel vmlinuz-test
370 GRUB_MENU = Test Kernel
371EOF
372 ;
373$config_help{"REBOOT_SCRIPT"} = << "EOF"
374 A script to reboot the target into the test kernel
375 (Only mandatory if REBOOT_TYPE = script)
376EOF
377 ;
378
379sub read_prompt {
380 my ($cancel, $prompt) = @_;
381
382 my $ans;
383
384 for (;;) {
385 if ($cancel) {
386 print "$prompt [y/n/C] ";
387 } else {
388 print "$prompt [Y/n] ";
389 }
390 $ans = <STDIN>;
391 chomp $ans;
392 if ($ans =~ /^\s*$/) {
393 if ($cancel) {
394 $ans = "c";
395 } else {
396 $ans = "y";
397 }
398 }
399 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
400 if ($cancel) {
401 last if ($ans =~ /^c$/i);
402 print "Please answer either 'y', 'n' or 'c'.\n";
403 } else {
404 print "Please answer either 'y' or 'n'.\n";
405 }
406 }
407 if ($ans =~ /^c/i) {
408 exit;
409 }
410 if ($ans !~ /^y$/i) {
411 return 0;
412 }
413 return 1;
414}
415
416sub read_yn {
417 my ($prompt) = @_;
418
419 return read_prompt 0, $prompt;
420}
421
422sub read_ync {
423 my ($prompt) = @_;
424
425 return read_prompt 1, $prompt;
426}
427
428sub get_ktest_config {
429 my ($config) = @_;
430 my $ans;
431
432 return if (defined($opt{$config}));
433
434 if (defined($config_help{$config})) {
435 print "\n";
436 print $config_help{$config};
437 }
438
439 for (;;) {
440 print "$config = ";
441 if (defined($default{$config}) && length($default{$config})) {
442 print "\[$default{$config}\] ";
443 }
444 $ans = <STDIN>;
445 $ans =~ s/^\s*(.*\S)\s*$/$1/;
446 if ($ans =~ /^\s*$/) {
447 if ($default{$config}) {
448 $ans = $default{$config};
449 } else {
450 print "Your answer can not be blank\n";
451 next;
452 }
453 }
454 $entered_configs{$config} = ${ans};
455 last;
456 }
457}
458
459sub get_ktest_configs {
460 get_ktest_config("MACHINE");
461 get_ktest_config("BUILD_DIR");
462 get_ktest_config("OUTPUT_DIR");
463
464 if ($newconfig) {
465 get_ktest_config("BUILD_OPTIONS");
466 }
467
468 # options required for other than just building a kernel
469 if (!$buildonly) {
470 get_ktest_config("POWER_CYCLE");
471 get_ktest_config("CONSOLE");
472 }
473
474 # options required for install and more
475 if ($buildonly != 1) {
476 get_ktest_config("SSH_USER");
477 get_ktest_config("BUILD_TARGET");
478 get_ktest_config("TARGET_IMAGE");
479 }
480
481 get_ktest_config("LOCALVERSION");
482
483 return if ($buildonly);
484
485 my $rtype = $opt{"REBOOT_TYPE"};
486
487 if (!defined($rtype)) {
488 if (!defined($opt{"GRUB_MENU"})) {
489 get_ktest_config("REBOOT_TYPE");
490 $rtype = $entered_configs{"REBOOT_TYPE"};
491 } else {
492 $rtype = "grub";
493 }
494 }
495
496 if ($rtype eq "grub") {
497 get_ktest_config("GRUB_MENU");
498 }
499}
500
501sub process_variables {
502 my ($value, $remove_undef) = @_;
503 my $retval = "";
504
505 # We want to check for '\', and it is just easier
506 # to check the previous characet of '$' and not need
507 # to worry if '$' is the first character. By adding
508 # a space to $value, we can just check [^\\]\$ and
509 # it will still work.
510 $value = " $value";
511
512 while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
513 my $begin = $1;
514 my $var = $2;
515 my $end = $3;
516 # append beginning of value to retval
517 $retval = "$retval$begin";
518 if (defined($variable{$var})) {
519 $retval = "$retval$variable{$var}";
520 } elsif (defined($remove_undef) && $remove_undef) {
521 # for if statements, any variable that is not defined,
522 # we simple convert to 0
523 $retval = "${retval}0";
524 } else {
525 # put back the origin piece.
526 $retval = "$retval\$\{$var\}";
527 # This could be an option that is used later, save
528 # it so we don't warn if this option is not one of
529 # ktests options.
530 $used_options{$var} = 1;
531 }
532 $value = $end;
533 }
534 $retval = "$retval$value";
535
536 # remove the space added in the beginning
537 $retval =~ s/ //;
538
539 return "$retval"
540}
541
542sub set_value {
543 my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
544
545 my $prvalue = process_variables($rvalue);
546
547 if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") {
548 # Note if a test is something other than build, then we
549 # will need other manditory options.
550 if ($prvalue ne "install") {
551 $buildonly = 0;
552 } else {
553 # install still limits some manditory options.
554 $buildonly = 2;
555 }
556 }
557
558 if (defined($opt{$lvalue})) {
559 if (!$override || defined(${$overrides}{$lvalue})) {
560 my $extra = "";
561 if ($override) {
562 $extra = "In the same override section!\n";
563 }
564 die "$name: $.: Option $lvalue defined more than once!\n$extra";
565 }
566 ${$overrides}{$lvalue} = $prvalue;
567 }
568 if ($rvalue =~ /^\s*$/) {
569 delete $opt{$lvalue};
570 } else {
571 $opt{$lvalue} = $prvalue;
572 }
573}
574
575sub set_variable {
576 my ($lvalue, $rvalue) = @_;
577
578 if ($rvalue =~ /^\s*$/) {
579 delete $variable{$lvalue};
580 } else {
581 $rvalue = process_variables($rvalue);
582 $variable{$lvalue} = $rvalue;
583 }
584}
585
586sub process_compare {
587 my ($lval, $cmp, $rval) = @_;
588
589 # remove whitespace
590
591 $lval =~ s/^\s*//;
592 $lval =~ s/\s*$//;
593
594 $rval =~ s/^\s*//;
595 $rval =~ s/\s*$//;
596
597 if ($cmp eq "==") {
598 return $lval eq $rval;
599 } elsif ($cmp eq "!=") {
600 return $lval ne $rval;
601 }
602
603 my $statement = "$lval $cmp $rval";
604 my $ret = eval $statement;
605
606 # $@ stores error of eval
607 if ($@) {
608 return -1;
609 }
610
611 return $ret;
612}
613
614sub value_defined {
615 my ($val) = @_;
616
617 return defined($variable{$2}) ||
618 defined($opt{$2});
619}
620
621my $d = 0;
622sub process_expression {
623 my ($name, $val) = @_;
624
625 my $c = $d++;
626
627 while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
628 my $express = $1;
629
630 if (process_expression($name, $express)) {
631 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
632 } else {
633 $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
634 }
635 }
636
637 $d--;
638 my $OR = "\\|\\|";
639 my $AND = "\\&\\&";
640
641 while ($val =~ s/^(.*?)($OR|$AND)//) {
642 my $express = $1;
643 my $op = $2;
644
645 if (process_expression($name, $express)) {
646 if ($op eq "||") {
647 return 1;
648 }
649 } else {
650 if ($op eq "&&") {
651 return 0;
652 }
653 }
654 }
655
656 if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) {
657 my $ret = process_compare($1, $2, $3);
658 if ($ret < 0) {
659 die "$name: $.: Unable to process comparison\n";
660 }
661 return $ret;
662 }
663
664 if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
665 if (defined $1) {
666 return !value_defined($2);
667 } else {
668 return value_defined($2);
669 }
670 }
671
672 if ($val =~ /^\s*0\s*$/) {
673 return 0;
674 } elsif ($val =~ /^\s*\d+\s*$/) {
675 return 1;
676 }
677
678 die ("$name: $.: Undefined content $val in if statement\n");
679}
680
681sub process_if {
682 my ($name, $value) = @_;
683
684 # Convert variables and replace undefined ones with 0
685 my $val = process_variables($value, 1);
686 my $ret = process_expression $name, $val;
687
688 return $ret;
689}
690
691sub __read_config {
692 my ($config, $current_test_num) = @_;
693
694 my $in;
695 open($in, $config) || die "can't read file $config";
696
697 my $name = $config;
698 $name =~ s,.*/(.*),$1,;
699
700 my $test_num = $$current_test_num;
701 my $default = 1;
702 my $repeat = 1;
703 my $num_tests_set = 0;
704 my $skip = 0;
705 my $rest;
706 my $line;
707 my $test_case = 0;
708 my $if = 0;
709 my $if_set = 0;
710 my $override = 0;
711
712 my %overrides;
713
714 while (<$in>) {
715
716 # ignore blank lines and comments
717 next if (/^\s*$/ || /\s*\#/);
718
719 if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
720
721 my $type = $1;
722 $rest = $2;
723 $line = $2;
724
725 my $old_test_num;
726 my $old_repeat;
727 $override = 0;
728
729 if ($type eq "TEST_START") {
730
731 if ($num_tests_set) {
732 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
733 }
734
735 $old_test_num = $test_num;
736 $old_repeat = $repeat;
737
738 $test_num += $repeat;
739 $default = 0;
740 $repeat = 1;
741 } else {
742 $default = 1;
743 }
744
745 # If SKIP is anywhere in the line, the command will be skipped
746 if ($rest =~ s/\s+SKIP\b//) {
747 $skip = 1;
748 } else {
749 $test_case = 1;
750 $skip = 0;
751 }
752
753 if ($rest =~ s/\sELSE\b//) {
754 if (!$if) {
755 die "$name: $.: ELSE found with out matching IF section\n$_";
756 }
757 $if = 0;
758
759 if ($if_set) {
760 $skip = 1;
761 } else {
762 $skip = 0;
763 }
764 }
765
766 if ($rest =~ s/\sIF\s+(.*)//) {
767 if (process_if($name, $1)) {
768 $if_set = 1;
769 } else {
770 $skip = 1;
771 }
772 $if = 1;
773 } else {
774 $if = 0;
775 $if_set = 0;
776 }
777
778 if (!$skip) {
779 if ($type eq "TEST_START") {
780 if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
781 $repeat = $1;
782 $repeat_tests{"$test_num"} = $repeat;
783 }
784 } elsif ($rest =~ s/\sOVERRIDE\b//) {
785 # DEFAULT only
786 $override = 1;
787 # Clear previous overrides
788 %overrides = ();
789 }
790 }
791
792 if (!$skip && $rest !~ /^\s*$/) {
793 die "$name: $.: Gargbage found after $type\n$_";
794 }
795
796 if ($skip && $type eq "TEST_START") {
797 $test_num = $old_test_num;
798 $repeat = $old_repeat;
799 }
800
801 } elsif (/^\s*ELSE\b(.*)$/) {
802 if (!$if) {
803 die "$name: $.: ELSE found with out matching IF section\n$_";
804 }
805 $rest = $1;
806 if ($if_set) {
807 $skip = 1;
808 $rest = "";
809 } else {
810 $skip = 0;
811
812 if ($rest =~ /\sIF\s+(.*)/) {
813 # May be a ELSE IF section.
814 if (!process_if($name, $1)) {
815 $skip = 1;
816 }
817 $rest = "";
818 } else {
819 $if = 0;
820 }
821 }
822
823 if ($rest !~ /^\s*$/) {
824 die "$name: $.: Gargbage found after DEFAULTS\n$_";
825 }
826
827 } elsif (/^\s*INCLUDE\s+(\S+)/) {
828
829 next if ($skip);
830
831 if (!$default) {
832 die "$name: $.: INCLUDE can only be done in default sections\n$_";
833 }
834
835 my $file = process_variables($1);
836
837 if ($file !~ m,^/,) {
838 # check the path of the config file first
839 if ($config =~ m,(.*)/,) {
840 if (-f "$1/$file") {
841 $file = "$1/$file";
842 }
843 }
844 }
845
846 if ( ! -r $file ) {
847 die "$name: $.: Can't read file $file\n$_";
848 }
849
850 if (__read_config($file, \$test_num)) {
851 $test_case = 1;
852 }
853
854 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
855
856 next if ($skip);
857
858 my $lvalue = $1;
859 my $rvalue = $2;
860
861 if (!$default &&
862 ($lvalue eq "NUM_TESTS" ||
863 $lvalue eq "LOG_FILE" ||
864 $lvalue eq "CLEAR_LOG")) {
865 die "$name: $.: $lvalue must be set in DEFAULTS section\n";
866 }
867
868 if ($lvalue eq "NUM_TESTS") {
869 if ($test_num) {
870 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
871 }
872 if (!$default) {
873 die "$name: $.: NUM_TESTS must be set in default section\n";
874 }
875 $num_tests_set = 1;
876 }
877
878 if ($default || $lvalue =~ /\[\d+\]$/) {
879 set_value($lvalue, $rvalue, $override, \%overrides, $name);
880 } else {
881 my $val = "$lvalue\[$test_num\]";
882 set_value($val, $rvalue, $override, \%overrides, $name);
883
884 if ($repeat > 1) {
885 $repeats{$val} = $repeat;
886 }
887 }
888 } elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
889 next if ($skip);
890
891 my $lvalue = $1;
892 my $rvalue = $2;
893
894 # process config variables.
895 # Config variables are only active while reading the
896 # config and can be defined anywhere. They also ignore
897 # TEST_START and DEFAULTS, but are skipped if they are in
898 # on of these sections that have SKIP defined.
899 # The save variable can be
900 # defined multiple times and the new one simply overrides
901 # the prevous one.
902 set_variable($lvalue, $rvalue);
903
904 } else {
905 die "$name: $.: Garbage found in config\n$_";
906 }
907 }
908
909 if ($test_num) {
910 $test_num += $repeat - 1;
911 $opt{"NUM_TESTS"} = $test_num;
912 }
913
914 close($in);
915
916 $$current_test_num = $test_num;
917
918 return $test_case;
919}
920
921sub get_test_case {
922 print "What test case would you like to run?\n";
923 print " (build, install or boot)\n";
924 print " Other tests are available but require editing the config file\n";
925 my $ans = <STDIN>;
926 chomp $ans;
927 $default{"TEST_TYPE"} = $ans;
928}
929
930sub read_config {
931 my ($config) = @_;
932
933 my $test_case;
934 my $test_num = 0;
935
936 $test_case = __read_config $config, \$test_num;
937
938 # make sure we have all mandatory configs
939 get_ktest_configs;
940
941 # was a test specified?
942 if (!$test_case) {
943 print "No test case specified.\n";
944 get_test_case;
945 }
946
947 # set any defaults
948
949 foreach my $default (keys %default) {
950 if (!defined($opt{$default})) {
951 $opt{$default} = $default{$default};
952 }
953 }
954
955 if ($opt{"IGNORE_UNUSED"} == 1) {
956 return;
957 }
958
959 my %not_used;
960
961 # check if there are any stragglers (typos?)
962 foreach my $option (keys %opt) {
963 my $op = $option;
964 # remove per test labels.
965 $op =~ s/\[.*\]//;
966 if (!exists($option_map{$op}) &&
967 !exists($default{$op}) &&
968 !exists($used_options{$op})) {
969 $not_used{$op} = 1;
970 }
971 }
972
973 if (%not_used) {
974 my $s = "s are";
975 $s = " is" if (keys %not_used == 1);
976 print "The following option$s not used; could be a typo:\n";
977 foreach my $option (keys %not_used) {
978 print "$option\n";
979 }
980 print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n";
981 if (!read_yn "Do you want to continue?") {
982 exit -1;
983 }
984 }
985}
986
987sub __eval_option {
988 my ($option, $i) = @_;
989
990 # Add space to evaluate the character before $
991 $option = " $option";
992 my $retval = "";
993 my $repeated = 0;
994 my $parent = 0;
995
996 foreach my $test (keys %repeat_tests) {
997 if ($i >= $test &&
998 $i < $test + $repeat_tests{$test}) {
999
1000 $repeated = 1;
1001 $parent = $test;
1002 last;
1003 }
1004 }
1005
1006 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
1007 my $start = $1;
1008 my $var = $2;
1009 my $end = $3;
1010
1011 # Append beginning of line
1012 $retval = "$retval$start";
1013
1014 # If the iteration option OPT[$i] exists, then use that.
1015 # otherwise see if the default OPT (without [$i]) exists.
1016
1017 my $o = "$var\[$i\]";
1018 my $parento = "$var\[$parent\]";
1019
1020 if (defined($opt{$o})) {
1021 $o = $opt{$o};
1022 $retval = "$retval$o";
1023 } elsif ($repeated && defined($opt{$parento})) {
1024 $o = $opt{$parento};
1025 $retval = "$retval$o";
1026 } elsif (defined($opt{$var})) {
1027 $o = $opt{$var};
1028 $retval = "$retval$o";
1029 } else {
1030 $retval = "$retval\$\{$var\}";
1031 }
1032
1033 $option = $end;
1034 }
1035
1036 $retval = "$retval$option";
1037
1038 $retval =~ s/^ //;
1039
1040 return $retval;
1041}
1042
1043sub eval_option {
1044 my ($option, $i) = @_;
1045
1046 my $prev = "";
1047
1048 # Since an option can evaluate to another option,
1049 # keep iterating until we do not evaluate any more
1050 # options.
1051 my $r = 0;
1052 while ($prev ne $option) {
1053 # Check for recursive evaluations.
1054 # 100 deep should be more than enough.
1055 if ($r++ > 100) {
1056 die "Over 100 evaluations accurred with $option\n" .
1057 "Check for recursive variables\n";
1058 }
1059 $prev = $option;
1060 $option = __eval_option($option, $i);
1061 }
1062
1063 return $option;
1064}
1065
1066sub _logit {
1067 if (defined($opt{"LOG_FILE"})) {
1068 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
1069 print OUT @_;
1070 close(OUT);
1071 }
1072}
1073
1074sub logit {
1075 if (defined($opt{"LOG_FILE"})) {
1076 _logit @_;
1077 } else {
1078 print @_;
1079 }
1080}
1081
1082sub doprint {
1083 print @_;
1084 _logit @_;
1085}
1086
1087sub run_command;
1088sub start_monitor;
1089sub end_monitor;
1090sub wait_for_monitor;
1091
1092sub reboot {
1093 my ($time) = @_;
1094
1095 if (defined($time)) {
1096 start_monitor;
1097 # flush out current monitor
1098 # May contain the reboot success line
1099 wait_for_monitor 1;
1100 }
1101
1102 # try to reboot normally
1103 if (run_command $reboot) {
1104 if (defined($powercycle_after_reboot)) {
1105 sleep $powercycle_after_reboot;
1106 run_command "$power_cycle";
1107 }
1108 } else {
1109 # nope? power cycle it.
1110 run_command "$power_cycle";
1111 }
1112
1113 if (defined($time)) {
1114 wait_for_monitor($time, $reboot_success_line);
1115 end_monitor;
1116 }
1117}
1118
1119sub reboot_to_good {
1120 my ($time) = @_;
1121
1122 if (defined($switch_to_good)) {
1123 run_command $switch_to_good;
1124 }
1125
1126 reboot $time;
1127}
1128
1129sub do_not_reboot {
1130 my $i = $iteration;
1131
1132 return $test_type eq "build" || $no_reboot ||
1133 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
1134 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
1135}
1136
1137sub dodie {
1138 doprint "CRITICAL FAILURE... ", @_, "\n";
1139
1140 my $i = $iteration;
1141
1142 if ($reboot_on_error && !do_not_reboot) {
1143
1144 doprint "REBOOTING\n";
1145 reboot_to_good;
1146
1147 } elsif ($poweroff_on_error && defined($power_off)) {
1148 doprint "POWERING OFF\n";
1149 `$power_off`;
1150 }
1151
1152 if (defined($opt{"LOG_FILE"})) {
1153 print " See $opt{LOG_FILE} for more info.\n";
1154 }
1155
1156 die @_, "\n";
1157}
1158
1159sub open_console {
1160 my ($fp) = @_;
1161
1162 my $flags;
1163
1164 my $pid = open($fp, "$console|") or
1165 dodie "Can't open console $console";
1166
1167 $flags = fcntl($fp, F_GETFL, 0) or
1168 dodie "Can't get flags for the socket: $!";
1169 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
1170 dodie "Can't set flags for the socket: $!";
1171
1172 return $pid;
1173}
1174
1175sub close_console {
1176 my ($fp, $pid) = @_;
1177
1178 doprint "kill child process $pid\n";
1179 kill 2, $pid;
1180
1181 print "closing!\n";
1182 close($fp);
1183}
1184
1185sub start_monitor {
1186 if ($monitor_cnt++) {
1187 return;
1188 }
1189 $monitor_fp = \*MONFD;
1190 $monitor_pid = open_console $monitor_fp;
1191
1192 return;
1193
1194 open(MONFD, "Stop perl from warning about single use of MONFD");
1195}
1196
1197sub end_monitor {
1198 if (--$monitor_cnt) {
1199 return;
1200 }
1201 close_console($monitor_fp, $monitor_pid);
1202}
1203
1204sub wait_for_monitor {
1205 my ($time, $stop) = @_;
1206 my $full_line = "";
1207 my $line;
1208 my $booted = 0;
1209
1210 doprint "** Wait for monitor to settle down **\n";
1211
1212 # read the monitor and wait for the system to calm down
1213 while (!$booted) {
1214 $line = wait_for_input($monitor_fp, $time);
1215 last if (!defined($line));
1216 print "$line";
1217 $full_line .= $line;
1218
1219 if (defined($stop) && $full_line =~ /$stop/) {
1220 doprint "wait for monitor detected $stop\n";
1221 $booted = 1;
1222 }
1223
1224 if ($line =~ /\n/) {
1225 $full_line = "";
1226 }
1227 }
1228 print "** Monitor flushed **\n";
1229}
1230
1231sub save_logs {
1232 my ($result, $basedir) = @_;
1233 my @t = localtime;
1234 my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1235 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1236
1237 my $type = $build_type;
1238 if ($type =~ /useconfig/) {
1239 $type = "useconfig";
1240 }
1241
1242 my $dir = "$machine-$test_type-$type-$result-$date";
1243
1244 $dir = "$basedir/$dir";
1245
1246 if (!-d $dir) {
1247 mkpath($dir) or
1248 die "can't create $dir";
1249 }
1250
1251 my %files = (
1252 "config" => $output_config,
1253 "buildlog" => $buildlog,
1254 "dmesg" => $dmesg,
1255 "testlog" => $testlog,
1256 );
1257
1258 while (my ($name, $source) = each(%files)) {
1259 if (-f "$source") {
1260 cp "$source", "$dir/$name" or
1261 die "failed to copy $source";
1262 }
1263 }
1264
1265 doprint "*** Saved info to $dir ***\n";
1266}
1267
1268sub fail {
1269
1270 if ($die_on_failure) {
1271 dodie @_;
1272 }
1273
1274 doprint "FAILED\n";
1275
1276 my $i = $iteration;
1277
1278 # no need to reboot for just building.
1279 if (!do_not_reboot) {
1280 doprint "REBOOTING\n";
1281 reboot_to_good $sleep_time;
1282 }
1283
1284 my $name = "";
1285
1286 if (defined($test_name)) {
1287 $name = " ($test_name)";
1288 }
1289
1290 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1291 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1292 doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1293 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1294 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1295
1296 if (defined($store_failures)) {
1297 save_logs "fail", $store_failures;
1298 }
1299
1300 return 1;
1301}
1302
1303sub run_command {
1304 my ($command) = @_;
1305 my $dolog = 0;
1306 my $dord = 0;
1307 my $pid;
1308
1309 $command =~ s/\$SSH_USER/$ssh_user/g;
1310 $command =~ s/\$MACHINE/$machine/g;
1311
1312 doprint("$command ... ");
1313
1314 $pid = open(CMD, "$command 2>&1 |") or
1315 (fail "unable to exec $command" and return 0);
1316
1317 if (defined($opt{"LOG_FILE"})) {
1318 open(LOG, ">>$opt{LOG_FILE}") or
1319 dodie "failed to write to log";
1320 $dolog = 1;
1321 }
1322
1323 if (defined($redirect)) {
1324 open (RD, ">$redirect") or
1325 dodie "failed to write to redirect $redirect";
1326 $dord = 1;
1327 }
1328
1329 while (<CMD>) {
1330 print LOG if ($dolog);
1331 print RD if ($dord);
1332 }
1333
1334 waitpid($pid, 0);
1335 my $failed = $?;
1336
1337 close(CMD);
1338 close(LOG) if ($dolog);
1339 close(RD) if ($dord);
1340
1341 if ($failed) {
1342 doprint "FAILED!\n";
1343 } else {
1344 doprint "SUCCESS\n";
1345 }
1346
1347 return !$failed;
1348}
1349
1350sub run_ssh {
1351 my ($cmd) = @_;
1352 my $cp_exec = $ssh_exec;
1353
1354 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1355 return run_command "$cp_exec";
1356}
1357
1358sub run_scp {
1359 my ($src, $dst, $cp_scp) = @_;
1360
1361 $cp_scp =~ s/\$SRC_FILE/$src/g;
1362 $cp_scp =~ s/\$DST_FILE/$dst/g;
1363
1364 return run_command "$cp_scp";
1365}
1366
1367sub run_scp_install {
1368 my ($src, $dst) = @_;
1369
1370 my $cp_scp = $scp_to_target_install;
1371
1372 return run_scp($src, $dst, $cp_scp);
1373}
1374
1375sub run_scp_mod {
1376 my ($src, $dst) = @_;
1377
1378 my $cp_scp = $scp_to_target;
1379
1380 return run_scp($src, $dst, $cp_scp);
1381}
1382
1383sub get_grub_index {
1384
1385 if ($reboot_type ne "grub") {
1386 return;
1387 }
1388 return if (defined($grub_number));
1389
1390 doprint "Find grub menu ... ";
1391 $grub_number = -1;
1392
1393 my $ssh_grub = $ssh_exec;
1394 $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
1395
1396 open(IN, "$ssh_grub |")
1397 or die "unable to get menu.lst";
1398
1399 my $found = 0;
1400
1401 while (<IN>) {
1402 if (/^\s*title\s+$grub_menu\s*$/) {
1403 $grub_number++;
1404 $found = 1;
1405 last;
1406 } elsif (/^\s*title\s/) {
1407 $grub_number++;
1408 }
1409 }
1410 close(IN);
1411
1412 die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
1413 if (!$found);
1414 doprint "$grub_number\n";
1415}
1416
1417sub wait_for_input
1418{
1419 my ($fp, $time) = @_;
1420 my $rin;
1421 my $ready;
1422 my $line;
1423 my $ch;
1424
1425 if (!defined($time)) {
1426 $time = $timeout;
1427 }
1428
1429 $rin = '';
1430 vec($rin, fileno($fp), 1) = 1;
1431 $ready = select($rin, undef, undef, $time);
1432
1433 $line = "";
1434
1435 # try to read one char at a time
1436 while (sysread $fp, $ch, 1) {
1437 $line .= $ch;
1438 last if ($ch eq "\n");
1439 }
1440
1441 if (!length($line)) {
1442 return undef;
1443 }
1444
1445 return $line;
1446}
1447
1448sub reboot_to {
1449 if (defined($switch_to_test)) {
1450 run_command $switch_to_test;
1451 }
1452
1453 if ($reboot_type eq "grub") {
1454 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
1455 } elsif (defined $reboot_script) {
1456 run_command "$reboot_script";
1457 }
1458 reboot;
1459}
1460
1461sub get_sha1 {
1462 my ($commit) = @_;
1463
1464 doprint "git rev-list --max-count=1 $commit ... ";
1465 my $sha1 = `git rev-list --max-count=1 $commit`;
1466 my $ret = $?;
1467
1468 logit $sha1;
1469
1470 if ($ret) {
1471 doprint "FAILED\n";
1472 dodie "Failed to get git $commit";
1473 }
1474
1475 print "SUCCESS\n";
1476
1477 chomp $sha1;
1478
1479 return $sha1;
1480}
1481
1482sub monitor {
1483 my $booted = 0;
1484 my $bug = 0;
1485 my $bug_ignored = 0;
1486 my $skip_call_trace = 0;
1487 my $loops;
1488
1489 wait_for_monitor 5;
1490
1491 my $line;
1492 my $full_line = "";
1493
1494 open(DMESG, "> $dmesg") or
1495 die "unable to write to $dmesg";
1496
1497 reboot_to;
1498
1499 my $success_start;
1500 my $failure_start;
1501 my $monitor_start = time;
1502 my $done = 0;
1503 my $version_found = 0;
1504
1505 while (!$done) {
1506
1507 if ($bug && defined($stop_after_failure) &&
1508 $stop_after_failure >= 0) {
1509 my $time = $stop_after_failure - (time - $failure_start);
1510 $line = wait_for_input($monitor_fp, $time);
1511 if (!defined($line)) {
1512 doprint "bug timed out after $booted_timeout seconds\n";
1513 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1514 last;
1515 }
1516 } elsif ($booted) {
1517 $line = wait_for_input($monitor_fp, $booted_timeout);
1518 if (!defined($line)) {
1519 my $s = $booted_timeout == 1 ? "" : "s";
1520 doprint "Successful boot found: break after $booted_timeout second$s\n";
1521 last;
1522 }
1523 } else {
1524 $line = wait_for_input($monitor_fp);
1525 if (!defined($line)) {
1526 my $s = $timeout == 1 ? "" : "s";
1527 doprint "Timed out after $timeout second$s\n";
1528 last;
1529 }
1530 }
1531
1532 doprint $line;
1533 print DMESG $line;
1534
1535 # we are not guaranteed to get a full line
1536 $full_line .= $line;
1537
1538 if ($full_line =~ /$success_line/) {
1539 $booted = 1;
1540 $success_start = time;
1541 }
1542
1543 if ($booted && defined($stop_after_success) &&
1544 $stop_after_success >= 0) {
1545 my $now = time;
1546 if ($now - $success_start >= $stop_after_success) {
1547 doprint "Test forced to stop after $stop_after_success seconds after success\n";
1548 last;
1549 }
1550 }
1551
1552 if ($full_line =~ /\[ backtrace testing \]/) {
1553 $skip_call_trace = 1;
1554 }
1555
1556 if ($full_line =~ /call trace:/i) {
1557 if (!$bug && !$skip_call_trace) {
1558 if ($ignore_errors) {
1559 $bug_ignored = 1;
1560 } else {
1561 $bug = 1;
1562 $failure_start = time;
1563 }
1564 }
1565 }
1566
1567 if ($bug && defined($stop_after_failure) &&
1568 $stop_after_failure >= 0) {
1569 my $now = time;
1570 if ($now - $failure_start >= $stop_after_failure) {
1571 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1572 last;
1573 }
1574 }
1575
1576 if ($full_line =~ /\[ end of backtrace testing \]/) {
1577 $skip_call_trace = 0;
1578 }
1579
1580 if ($full_line =~ /Kernel panic -/) {
1581 $failure_start = time;
1582 $bug = 1;
1583 }
1584
1585 # Detect triple faults by testing the banner
1586 if ($full_line =~ /\bLinux version (\S+).*\n/) {
1587 if ($1 eq $version) {
1588 $version_found = 1;
1589 } elsif ($version_found && $detect_triplefault) {
1590 # We already booted into the kernel we are testing,
1591 # but now we booted into another kernel?
1592 # Consider this a triple fault.
1593 doprint "Aleady booted in Linux kernel $version, but now\n";
1594 doprint "we booted into Linux kernel $1.\n";
1595 doprint "Assuming that this is a triple fault.\n";
1596 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1597 last;
1598 }
1599 }
1600
1601 if ($line =~ /\n/) {
1602 $full_line = "";
1603 }
1604
1605 if ($stop_test_after > 0 && !$booted && !$bug) {
1606 if (time - $monitor_start > $stop_test_after) {
1607 doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
1608 $done = 1;
1609 }
1610 }
1611 }
1612
1613 close(DMESG);
1614
1615 if ($bug) {
1616 return 0 if ($in_bisect);
1617 fail "failed - got a bug report" and return 0;
1618 }
1619
1620 if (!$booted) {
1621 return 0 if ($in_bisect);
1622 fail "failed - never got a boot prompt." and return 0;
1623 }
1624
1625 if ($bug_ignored) {
1626 doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
1627 }
1628
1629 return 1;
1630}
1631
1632sub eval_kernel_version {
1633 my ($option) = @_;
1634
1635 $option =~ s/\$KERNEL_VERSION/$version/g;
1636
1637 return $option;
1638}
1639
1640sub do_post_install {
1641
1642 return if (!defined($post_install));
1643
1644 my $cp_post_install = eval_kernel_version $post_install;
1645 run_command "$cp_post_install" or
1646 dodie "Failed to run post install";
1647}
1648
1649sub install {
1650
1651 return if ($no_install);
1652
1653 my $cp_target = eval_kernel_version $target_image;
1654
1655 run_scp_install "$outputdir/$build_target", "$cp_target" or
1656 dodie "failed to copy image";
1657
1658 my $install_mods = 0;
1659
1660 # should we process modules?
1661 $install_mods = 0;
1662 open(IN, "$output_config") or dodie("Can't read config file");
1663 while (<IN>) {
1664 if (/CONFIG_MODULES(=y)?/) {
1665 $install_mods = 1 if (defined($1));
1666 last;
1667 }
1668 }
1669 close(IN);
1670
1671 if (!$install_mods) {
1672 do_post_install;
1673 doprint "No modules needed\n";
1674 return;
1675 }
1676
1677 run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or
1678 dodie "Failed to install modules";
1679
1680 my $modlib = "/lib/modules/$version";
1681 my $modtar = "ktest-mods.tar.bz2";
1682
1683 run_ssh "rm -rf $modlib" or
1684 dodie "failed to remove old mods: $modlib";
1685
1686 # would be nice if scp -r did not follow symbolic links
1687 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
1688 dodie "making tarball";
1689
1690 run_scp_mod "$tmpdir/$modtar", "/tmp" or
1691 dodie "failed to copy modules";
1692
1693 unlink "$tmpdir/$modtar";
1694
1695 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
1696 dodie "failed to tar modules";
1697
1698 run_ssh "rm -f /tmp/$modtar";
1699
1700 do_post_install;
1701}
1702
1703sub get_version {
1704 # get the release name
1705 doprint "$make kernelrelease ... ";
1706 $version = `$make kernelrelease | tail -1`;
1707 chomp($version);
1708 doprint "$version\n";
1709}
1710
1711sub start_monitor_and_boot {
1712 # Make sure the stable kernel has finished booting
1713 start_monitor;
1714 wait_for_monitor 5;
1715 end_monitor;
1716
1717 get_grub_index;
1718 get_version;
1719 install;
1720
1721 start_monitor;
1722 return monitor;
1723}
1724
1725sub check_buildlog {
1726 my ($patch) = @_;
1727
1728 my @files = `git show $patch | diffstat -l`;
1729
1730 open(IN, "git show $patch |") or
1731 dodie "failed to show $patch";
1732 while (<IN>) {
1733 if (m,^--- a/(.*),) {
1734 chomp $1;
1735 $files[$#files] = $1;
1736 }
1737 }
1738 close(IN);
1739
1740 open(IN, $buildlog) or dodie "Can't open $buildlog";
1741 while (<IN>) {
1742 if (/^\s*(.*?):.*(warning|error)/) {
1743 my $err = $1;
1744 foreach my $file (@files) {
1745 my $fullpath = "$builddir/$file";
1746 if ($file eq $err || $fullpath eq $err) {
1747 fail "$file built with warnings" and return 0;
1748 }
1749 }
1750 }
1751 }
1752 close(IN);
1753
1754 return 1;
1755}
1756
1757sub apply_min_config {
1758 my $outconfig = "$output_config.new";
1759
1760 # Read the config file and remove anything that
1761 # is in the force_config hash (from minconfig and others)
1762 # then add the force config back.
1763
1764 doprint "Applying minimum configurations into $output_config.new\n";
1765
1766 open (OUT, ">$outconfig") or
1767 dodie "Can't create $outconfig";
1768
1769 if (-f $output_config) {
1770 open (IN, $output_config) or
1771 dodie "Failed to open $output_config";
1772 while (<IN>) {
1773 if (/^(# )?(CONFIG_[^\s=]*)/) {
1774 next if (defined($force_config{$2}));
1775 }
1776 print OUT;
1777 }
1778 close IN;
1779 }
1780 foreach my $config (keys %force_config) {
1781 print OUT "$force_config{$config}\n";
1782 }
1783 close OUT;
1784
1785 run_command "mv $outconfig $output_config";
1786}
1787
1788sub make_oldconfig {
1789
1790 my @force_list = keys %force_config;
1791
1792 if ($#force_list >= 0) {
1793 apply_min_config;
1794 }
1795
1796 if (!run_command "$make oldnoconfig") {
1797 # Perhaps oldnoconfig doesn't exist in this version of the kernel
1798 # try a yes '' | oldconfig
1799 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1800 run_command "yes '' | $make oldconfig" or
1801 dodie "failed make config oldconfig";
1802 }
1803}
1804
1805# read a config file and use this to force new configs.
1806sub load_force_config {
1807 my ($config) = @_;
1808
1809 open(IN, $config) or
1810 dodie "failed to read $config";
1811 while (<IN>) {
1812 chomp;
1813 if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1814 $force_config{$1} = $_;
1815 } elsif (/^# (CONFIG_\S*) is not set/) {
1816 $force_config{$1} = $_;
1817 }
1818 }
1819 close IN;
1820}
1821
1822sub build {
1823 my ($type) = @_;
1824
1825 unlink $buildlog;
1826
1827 # Failed builds should not reboot the target
1828 my $save_no_reboot = $no_reboot;
1829 $no_reboot = 1;
1830
1831 if (defined($pre_build)) {
1832 my $ret = run_command $pre_build;
1833 if (!$ret && defined($pre_build_die) &&
1834 $pre_build_die) {
1835 dodie "failed to pre_build\n";
1836 }
1837 }
1838
1839 if ($type =~ /^useconfig:(.*)/) {
1840 run_command "cp $1 $output_config" or
1841 dodie "could not copy $1 to .config";
1842
1843 $type = "oldconfig";
1844 }
1845
1846 # old config can ask questions
1847 if ($type eq "oldconfig") {
1848 $type = "oldnoconfig";
1849
1850 # allow for empty configs
1851 run_command "touch $output_config";
1852
1853 if (!$noclean) {
1854 run_command "mv $output_config $outputdir/config_temp" or
1855 dodie "moving .config";
1856
1857 run_command "$make mrproper" or dodie "make mrproper";
1858
1859 run_command "mv $outputdir/config_temp $output_config" or
1860 dodie "moving config_temp";
1861 }
1862
1863 } elsif (!$noclean) {
1864 unlink "$output_config";
1865 run_command "$make mrproper" or
1866 dodie "make mrproper";
1867 }
1868
1869 # add something to distinguish this build
1870 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
1871 print OUT "$localversion\n";
1872 close(OUT);
1873
1874 if (defined($minconfig)) {
1875 load_force_config($minconfig);
1876 }
1877
1878 if ($type ne "oldnoconfig") {
1879 run_command "$make $type" or
1880 dodie "failed make config";
1881 }
1882 # Run old config regardless, to enforce min configurations
1883 make_oldconfig;
1884
1885 $redirect = "$buildlog";
1886 my $build_ret = run_command "$make $build_options";
1887 undef $redirect;
1888
1889 if (defined($post_build)) {
1890 my $ret = run_command $post_build;
1891 if (!$ret && defined($post_build_die) &&
1892 $post_build_die) {
1893 dodie "failed to post_build\n";
1894 }
1895 }
1896
1897 if (!$build_ret) {
1898 # bisect may need this to pass
1899 if ($in_bisect) {
1900 $no_reboot = $save_no_reboot;
1901 return 0;
1902 }
1903 fail "failed build" and return 0;
1904 }
1905
1906 $no_reboot = $save_no_reboot;
1907
1908 return 1;
1909}
1910
1911sub halt {
1912 if (!run_ssh "halt" or defined($power_off)) {
1913 if (defined($poweroff_after_halt)) {
1914 sleep $poweroff_after_halt;
1915 run_command "$power_off";
1916 }
1917 } else {
1918 # nope? the zap it!
1919 run_command "$power_off";
1920 }
1921}
1922
1923sub success {
1924 my ($i) = @_;
1925
1926 $successes++;
1927
1928 my $name = "";
1929
1930 if (defined($test_name)) {
1931 $name = " ($test_name)";
1932 }
1933
1934 doprint "\n\n*******************************************\n";
1935 doprint "*******************************************\n";
1936 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n";
1937 doprint "*******************************************\n";
1938 doprint "*******************************************\n";
1939
1940 if (defined($store_successes)) {
1941 save_logs "success", $store_successes;
1942 }
1943
1944 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1945 doprint "Reboot and wait $sleep_time seconds\n";
1946 reboot_to_good $sleep_time;
1947 }
1948}
1949
1950sub answer_bisect {
1951 for (;;) {
1952 doprint "Pass or fail? [p/f]";
1953 my $ans = <STDIN>;
1954 chomp $ans;
1955 if ($ans eq "p" || $ans eq "P") {
1956 return 1;
1957 } elsif ($ans eq "f" || $ans eq "F") {
1958 return 0;
1959 } else {
1960 print "Please answer 'P' or 'F'\n";
1961 }
1962 }
1963}
1964
1965sub child_run_test {
1966 my $failed = 0;
1967
1968 # child should have no power
1969 $reboot_on_error = 0;
1970 $poweroff_on_error = 0;
1971 $die_on_failure = 1;
1972
1973 $redirect = "$testlog";
1974 run_command $run_test or $failed = 1;
1975 undef $redirect;
1976
1977 exit $failed;
1978}
1979
1980my $child_done;
1981
1982sub child_finished {
1983 $child_done = 1;
1984}
1985
1986sub do_run_test {
1987 my $child_pid;
1988 my $child_exit;
1989 my $line;
1990 my $full_line;
1991 my $bug = 0;
1992
1993 wait_for_monitor 1;
1994
1995 doprint "run test $run_test\n";
1996
1997 $child_done = 0;
1998
1999 $SIG{CHLD} = qw(child_finished);
2000
2001 $child_pid = fork;
2002
2003 child_run_test if (!$child_pid);
2004
2005 $full_line = "";
2006
2007 do {
2008 $line = wait_for_input($monitor_fp, 1);
2009 if (defined($line)) {
2010
2011 # we are not guaranteed to get a full line
2012 $full_line .= $line;
2013 doprint $line;
2014
2015 if ($full_line =~ /call trace:/i) {
2016 $bug = 1;
2017 }
2018
2019 if ($full_line =~ /Kernel panic -/) {
2020 $bug = 1;
2021 }
2022
2023 if ($line =~ /\n/) {
2024 $full_line = "";
2025 }
2026 }
2027 } while (!$child_done && !$bug);
2028
2029 if ($bug) {
2030 my $failure_start = time;
2031 my $now;
2032 do {
2033 $line = wait_for_input($monitor_fp, 1);
2034 if (defined($line)) {
2035 doprint $line;
2036 }
2037 $now = time;
2038 if ($now - $failure_start >= $stop_after_failure) {
2039 last;
2040 }
2041 } while (defined($line));
2042
2043 doprint "Detected kernel crash!\n";
2044 # kill the child with extreme prejudice
2045 kill 9, $child_pid;
2046 }
2047
2048 waitpid $child_pid, 0;
2049 $child_exit = $?;
2050
2051 if (!$bug && $in_bisect) {
2052 if (defined($bisect_ret_good)) {
2053 if ($child_exit == $bisect_ret_good) {
2054 return 1;
2055 }
2056 }
2057 if (defined($bisect_ret_skip)) {
2058 if ($child_exit == $bisect_ret_skip) {
2059 return -1;
2060 }
2061 }
2062 if (defined($bisect_ret_abort)) {
2063 if ($child_exit == $bisect_ret_abort) {
2064 fail "test abort" and return -2;
2065 }
2066 }
2067 if (defined($bisect_ret_bad)) {
2068 if ($child_exit == $bisect_ret_skip) {
2069 return 0;
2070 }
2071 }
2072 if (defined($bisect_ret_default)) {
2073 if ($bisect_ret_default eq "good") {
2074 return 1;
2075 } elsif ($bisect_ret_default eq "bad") {
2076 return 0;
2077 } elsif ($bisect_ret_default eq "skip") {
2078 return -1;
2079 } elsif ($bisect_ret_default eq "abort") {
2080 return -2;
2081 } else {
2082 fail "unknown default action: $bisect_ret_default"
2083 and return -2;
2084 }
2085 }
2086 }
2087
2088 if ($bug || $child_exit) {
2089 return 0 if $in_bisect;
2090 fail "test failed" and return 0;
2091 }
2092 return 1;
2093}
2094
2095sub run_git_bisect {
2096 my ($command) = @_;
2097
2098 doprint "$command ... ";
2099
2100 my $output = `$command 2>&1`;
2101 my $ret = $?;
2102
2103 logit $output;
2104
2105 if ($ret) {
2106 doprint "FAILED\n";
2107 dodie "Failed to git bisect";
2108 }
2109
2110 doprint "SUCCESS\n";
2111 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
2112 doprint "$1 [$2]\n";
2113 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
2114 $bisect_bad_commit = $1;
2115 doprint "Found bad commit... $1\n";
2116 return 0;
2117 } else {
2118 # we already logged it, just print it now.
2119 print $output;
2120 }
2121
2122 return 1;
2123}
2124
2125sub bisect_reboot {
2126 doprint "Reboot and sleep $bisect_sleep_time seconds\n";
2127 reboot_to_good $bisect_sleep_time;
2128}
2129
2130# returns 1 on success, 0 on failure, -1 on skip
2131sub run_bisect_test {
2132 my ($type, $buildtype) = @_;
2133
2134 my $failed = 0;
2135 my $result;
2136 my $output;
2137 my $ret;
2138
2139 $in_bisect = 1;
2140
2141 build $buildtype or $failed = 1;
2142
2143 if ($type ne "build") {
2144 if ($failed && $bisect_skip) {
2145 $in_bisect = 0;
2146 return -1;
2147 }
2148 dodie "Failed on build" if $failed;
2149
2150 # Now boot the box
2151 start_monitor_and_boot or $failed = 1;
2152
2153 if ($type ne "boot") {
2154 if ($failed && $bisect_skip) {
2155 end_monitor;
2156 bisect_reboot;
2157 $in_bisect = 0;
2158 return -1;
2159 }
2160 dodie "Failed on boot" if $failed;
2161
2162 do_run_test or $failed = 1;
2163 }
2164 end_monitor;
2165 }
2166
2167 if ($failed) {
2168 $result = 0;
2169 } else {
2170 $result = 1;
2171 }
2172
2173 # reboot the box to a kernel we can ssh to
2174 if ($type ne "build") {
2175 bisect_reboot;
2176 }
2177 $in_bisect = 0;
2178
2179 return $result;
2180}
2181
2182sub run_bisect {
2183 my ($type) = @_;
2184 my $buildtype = "oldconfig";
2185
2186 # We should have a minconfig to use?
2187 if (defined($minconfig)) {
2188 $buildtype = "useconfig:$minconfig";
2189 }
2190
2191 my $ret = run_bisect_test $type, $buildtype;
2192
2193 if ($bisect_manual) {
2194 $ret = answer_bisect;
2195 }
2196
2197 # Are we looking for where it worked, not failed?
2198 if ($reverse_bisect && $ret >= 0) {
2199 $ret = !$ret;
2200 }
2201
2202 if ($ret > 0) {
2203 return "good";
2204 } elsif ($ret == 0) {
2205 return "bad";
2206 } elsif ($bisect_skip) {
2207 doprint "HIT A BAD COMMIT ... SKIPPING\n";
2208 return "skip";
2209 }
2210}
2211
2212sub update_bisect_replay {
2213 my $tmp_log = "$tmpdir/ktest_bisect_log";
2214 run_command "git bisect log > $tmp_log" or
2215 die "can't create bisect log";
2216 return $tmp_log;
2217}
2218
2219sub bisect {
2220 my ($i) = @_;
2221
2222 my $result;
2223
2224 die "BISECT_GOOD[$i] not defined\n" if (!defined($bisect_good));
2225 die "BISECT_BAD[$i] not defined\n" if (!defined($bisect_bad));
2226 die "BISECT_TYPE[$i] not defined\n" if (!defined($bisect_type));
2227
2228 my $good = $bisect_good;
2229 my $bad = $bisect_bad;
2230 my $type = $bisect_type;
2231 my $start = $bisect_start;
2232 my $replay = $bisect_replay;
2233 my $start_files = $bisect_files;
2234
2235 if (defined($start_files)) {
2236 $start_files = " -- " . $start_files;
2237 } else {
2238 $start_files = "";
2239 }
2240
2241 # convert to true sha1's
2242 $good = get_sha1($good);
2243 $bad = get_sha1($bad);
2244
2245 if (defined($bisect_reverse) && $bisect_reverse == 1) {
2246 doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
2247 $reverse_bisect = 1;
2248 } else {
2249 $reverse_bisect = 0;
2250 }
2251
2252 # Can't have a test without having a test to run
2253 if ($type eq "test" && !defined($run_test)) {
2254 $type = "boot";
2255 }
2256
2257 # Check if a bisect was running
2258 my $bisect_start_file = "$builddir/.git/BISECT_START";
2259
2260 my $check = $bisect_check;
2261 my $do_check = defined($check) && $check ne "0";
2262
2263 if ( -f $bisect_start_file ) {
2264 print "Bisect in progress found\n";
2265 if ($do_check) {
2266 print " If you say yes, then no checks of good or bad will be done\n";
2267 }
2268 if (defined($replay)) {
2269 print "** BISECT_REPLAY is defined in config file **";
2270 print " Ignore config option and perform new git bisect log?\n";
2271 if (read_ync " (yes, no, or cancel) ") {
2272 $replay = update_bisect_replay;
2273 $do_check = 0;
2274 }
2275 } elsif (read_yn "read git log and continue?") {
2276 $replay = update_bisect_replay;
2277 $do_check = 0;
2278 }
2279 }
2280
2281 if ($do_check) {
2282
2283 # get current HEAD
2284 my $head = get_sha1("HEAD");
2285
2286 if ($check ne "good") {
2287 doprint "TESTING BISECT BAD [$bad]\n";
2288 run_command "git checkout $bad" or
2289 die "Failed to checkout $bad";
2290
2291 $result = run_bisect $type;
2292
2293 if ($result ne "bad") {
2294 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
2295 }
2296 }
2297
2298 if ($check ne "bad") {
2299 doprint "TESTING BISECT GOOD [$good]\n";
2300 run_command "git checkout $good" or
2301 die "Failed to checkout $good";
2302
2303 $result = run_bisect $type;
2304
2305 if ($result ne "good") {
2306 fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
2307 }
2308 }
2309
2310 # checkout where we started
2311 run_command "git checkout $head" or
2312 die "Failed to checkout $head";
2313 }
2314
2315 run_command "git bisect start$start_files" or
2316 dodie "could not start bisect";
2317
2318 run_command "git bisect good $good" or
2319 dodie "could not set bisect good to $good";
2320
2321 run_git_bisect "git bisect bad $bad" or
2322 dodie "could not set bisect bad to $bad";
2323
2324 if (defined($replay)) {
2325 run_command "git bisect replay $replay" or
2326 dodie "failed to run replay";
2327 }
2328
2329 if (defined($start)) {
2330 run_command "git checkout $start" or
2331 dodie "failed to checkout $start";
2332 }
2333
2334 my $test;
2335 do {
2336 $result = run_bisect $type;
2337 $test = run_git_bisect "git bisect $result";
2338 } while ($test);
2339
2340 run_command "git bisect log" or
2341 dodie "could not capture git bisect log";
2342
2343 run_command "git bisect reset" or
2344 dodie "could not reset git bisect";
2345
2346 doprint "Bad commit was [$bisect_bad_commit]\n";
2347
2348 success $i;
2349}
2350
2351my %config_ignore;
2352my %config_set;
2353
2354my %config_list;
2355my %null_config;
2356
2357my %dependency;
2358
2359sub assign_configs {
2360 my ($hash, $config) = @_;
2361
2362 open (IN, $config)
2363 or dodie "Failed to read $config";
2364
2365 while (<IN>) {
2366 if (/^((CONFIG\S*)=.*)/) {
2367 ${$hash}{$2} = $1;
2368 }
2369 }
2370
2371 close(IN);
2372}
2373
2374sub process_config_ignore {
2375 my ($config) = @_;
2376
2377 assign_configs \%config_ignore, $config;
2378}
2379
2380sub read_current_config {
2381 my ($config_ref) = @_;
2382
2383 %{$config_ref} = ();
2384 undef %{$config_ref};
2385
2386 my @key = keys %{$config_ref};
2387 if ($#key >= 0) {
2388 print "did not delete!\n";
2389 exit;
2390 }
2391 open (IN, "$output_config");
2392
2393 while (<IN>) {
2394 if (/^(CONFIG\S+)=(.*)/) {
2395 ${$config_ref}{$1} = $2;
2396 }
2397 }
2398 close(IN);
2399}
2400
2401sub get_dependencies {
2402 my ($config) = @_;
2403
2404 my $arr = $dependency{$config};
2405 if (!defined($arr)) {
2406 return ();
2407 }
2408
2409 my @deps = @{$arr};
2410
2411 foreach my $dep (@{$arr}) {
2412 print "ADD DEP $dep\n";
2413 @deps = (@deps, get_dependencies $dep);
2414 }
2415
2416 return @deps;
2417}
2418
2419sub create_config {
2420 my @configs = @_;
2421
2422 open(OUT, ">$output_config") or dodie "Can not write to $output_config";
2423
2424 foreach my $config (@configs) {
2425 print OUT "$config_set{$config}\n";
2426 my @deps = get_dependencies $config;
2427 foreach my $dep (@deps) {
2428 print OUT "$config_set{$dep}\n";
2429 }
2430 }
2431
2432 foreach my $config (keys %config_ignore) {
2433 print OUT "$config_ignore{$config}\n";
2434 }
2435 close(OUT);
2436
2437# exit;
2438 make_oldconfig;
2439}
2440
2441sub compare_configs {
2442 my (%a, %b) = @_;
2443
2444 foreach my $item (keys %a) {
2445 if (!defined($b{$item})) {
2446 print "diff $item\n";
2447 return 1;
2448 }
2449 delete $b{$item};
2450 }
2451
2452 my @keys = keys %b;
2453 if ($#keys) {
2454 print "diff2 $keys[0]\n";
2455 }
2456 return -1 if ($#keys >= 0);
2457
2458 return 0;
2459}
2460
2461sub run_config_bisect_test {
2462 my ($type) = @_;
2463
2464 return run_bisect_test $type, "oldconfig";
2465}
2466
2467sub process_passed {
2468 my (%configs) = @_;
2469
2470 doprint "These configs had no failure: (Enabling them for further compiles)\n";
2471 # Passed! All these configs are part of a good compile.
2472 # Add them to the min options.
2473 foreach my $config (keys %configs) {
2474 if (defined($config_list{$config})) {
2475 doprint " removing $config\n";
2476 $config_ignore{$config} = $config_list{$config};
2477 delete $config_list{$config};
2478 }
2479 }
2480 doprint "config copied to $outputdir/config_good\n";
2481 run_command "cp -f $output_config $outputdir/config_good";
2482}
2483
2484sub process_failed {
2485 my ($config) = @_;
2486
2487 doprint "\n\n***************************************\n";
2488 doprint "Found bad config: $config\n";
2489 doprint "***************************************\n\n";
2490}
2491
2492sub run_config_bisect {
2493
2494 my @start_list = keys %config_list;
2495
2496 if ($#start_list < 0) {
2497 doprint "No more configs to test!!!\n";
2498 return -1;
2499 }
2500
2501 doprint "***** RUN TEST ***\n";
2502 my $type = $config_bisect_type;
2503 my $ret;
2504 my %current_config;
2505
2506 my $count = $#start_list + 1;
2507 doprint " $count configs to test\n";
2508
2509 my $half = int($#start_list / 2);
2510
2511 do {
2512 my @tophalf = @start_list[0 .. $half];
2513
2514 create_config @tophalf;
2515 read_current_config \%current_config;
2516
2517 $count = $#tophalf + 1;
2518 doprint "Testing $count configs\n";
2519 my $found = 0;
2520 # make sure we test something
2521 foreach my $config (@tophalf) {
2522 if (defined($current_config{$config})) {
2523 logit " $config\n";
2524 $found = 1;
2525 }
2526 }
2527 if (!$found) {
2528 # try the other half
2529 doprint "Top half produced no set configs, trying bottom half\n";
2530 @tophalf = @start_list[$half + 1 .. $#start_list];
2531 create_config @tophalf;
2532 read_current_config \%current_config;
2533 foreach my $config (@tophalf) {
2534 if (defined($current_config{$config})) {
2535 logit " $config\n";
2536 $found = 1;
2537 }
2538 }
2539 if (!$found) {
2540 doprint "Failed: Can't make new config with current configs\n";
2541 foreach my $config (@start_list) {
2542 doprint " CONFIG: $config\n";
2543 }
2544 return -1;
2545 }
2546 $count = $#tophalf + 1;
2547 doprint "Testing $count configs\n";
2548 }
2549
2550 $ret = run_config_bisect_test $type;
2551 if ($bisect_manual) {
2552 $ret = answer_bisect;
2553 }
2554 if ($ret) {
2555 process_passed %current_config;
2556 return 0;
2557 }
2558
2559 doprint "This config had a failure.\n";
2560 doprint "Removing these configs that were not set in this config:\n";
2561 doprint "config copied to $outputdir/config_bad\n";
2562 run_command "cp -f $output_config $outputdir/config_bad";
2563
2564 # A config exists in this group that was bad.
2565 foreach my $config (keys %config_list) {
2566 if (!defined($current_config{$config})) {
2567 doprint " removing $config\n";
2568 delete $config_list{$config};
2569 }
2570 }
2571
2572 @start_list = @tophalf;
2573
2574 if ($#start_list == 0) {
2575 process_failed $start_list[0];
2576 return 1;
2577 }
2578
2579 # remove half the configs we are looking at and see if
2580 # they are good.
2581 $half = int($#start_list / 2);
2582 } while ($#start_list > 0);
2583
2584 # we found a single config, try it again unless we are running manually
2585
2586 if ($bisect_manual) {
2587 process_failed $start_list[0];
2588 return 1;
2589 }
2590
2591 my @tophalf = @start_list[0 .. 0];
2592
2593 $ret = run_config_bisect_test $type;
2594 if ($ret) {
2595 process_passed %current_config;
2596 return 0;
2597 }
2598
2599 process_failed $start_list[0];
2600 return 1;
2601}
2602
2603sub config_bisect {
2604 my ($i) = @_;
2605
2606 my $start_config = $config_bisect;
2607
2608 my $tmpconfig = "$tmpdir/use_config";
2609
2610 if (defined($config_bisect_good)) {
2611 process_config_ignore $config_bisect_good;
2612 }
2613
2614 # Make the file with the bad config and the min config
2615 if (defined($minconfig)) {
2616 # read the min config for things to ignore
2617 run_command "cp $minconfig $tmpconfig" or
2618 dodie "failed to copy $minconfig to $tmpconfig";
2619 } else {
2620 unlink $tmpconfig;
2621 }
2622
2623 if (-f $tmpconfig) {
2624 load_force_config($tmpconfig);
2625 process_config_ignore $tmpconfig;
2626 }
2627
2628 # now process the start config
2629 run_command "cp $start_config $output_config" or
2630 dodie "failed to copy $start_config to $output_config";
2631
2632 # read directly what we want to check
2633 my %config_check;
2634 open (IN, $output_config)
2635 or dodie "failed to open $output_config";
2636
2637 while (<IN>) {
2638 if (/^((CONFIG\S*)=.*)/) {
2639 $config_check{$2} = $1;
2640 }
2641 }
2642 close(IN);
2643
2644 # Now run oldconfig with the minconfig
2645 make_oldconfig;
2646
2647 # check to see what we lost (or gained)
2648 open (IN, $output_config)
2649 or dodie "Failed to read $start_config";
2650
2651 my %removed_configs;
2652 my %added_configs;
2653
2654 while (<IN>) {
2655 if (/^((CONFIG\S*)=.*)/) {
2656 # save off all options
2657 $config_set{$2} = $1;
2658 if (defined($config_check{$2})) {
2659 if (defined($config_ignore{$2})) {
2660 $removed_configs{$2} = $1;
2661 } else {
2662 $config_list{$2} = $1;
2663 }
2664 } elsif (!defined($config_ignore{$2})) {
2665 $added_configs{$2} = $1;
2666 $config_list{$2} = $1;
2667 }
2668 }
2669 }
2670 close(IN);
2671
2672 my @confs = keys %removed_configs;
2673 if ($#confs >= 0) {
2674 doprint "Configs overridden by default configs and removed from check:\n";
2675 foreach my $config (@confs) {
2676 doprint " $config\n";
2677 }
2678 }
2679 @confs = keys %added_configs;
2680 if ($#confs >= 0) {
2681 doprint "Configs appearing in make oldconfig and added:\n";
2682 foreach my $config (@confs) {
2683 doprint " $config\n";
2684 }
2685 }
2686
2687 my %config_test;
2688 my $once = 0;
2689
2690 # Sometimes kconfig does weird things. We must make sure
2691 # that the config we autocreate has everything we need
2692 # to test, otherwise we may miss testing configs, or
2693 # may not be able to create a new config.
2694 # Here we create a config with everything set.
2695 create_config (keys %config_list);
2696 read_current_config \%config_test;
2697 foreach my $config (keys %config_list) {
2698 if (!defined($config_test{$config})) {
2699 if (!$once) {
2700 $once = 1;
2701 doprint "Configs not produced by kconfig (will not be checked):\n";
2702 }
2703 doprint " $config\n";
2704 delete $config_list{$config};
2705 }
2706 }
2707 my $ret;
2708 do {
2709 $ret = run_config_bisect;
2710 } while (!$ret);
2711
2712 return $ret if ($ret < 0);
2713
2714 success $i;
2715}
2716
2717sub patchcheck_reboot {
2718 doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
2719 reboot_to_good $patchcheck_sleep_time;
2720}
2721
2722sub patchcheck {
2723 my ($i) = @_;
2724
2725 die "PATCHCHECK_START[$i] not defined\n"
2726 if (!defined($patchcheck_start));
2727 die "PATCHCHECK_TYPE[$i] not defined\n"
2728 if (!defined($patchcheck_type));
2729
2730 my $start = $patchcheck_start;
2731
2732 my $end = "HEAD";
2733 if (defined($patchcheck_end)) {
2734 $end = $patchcheck_end;
2735 }
2736
2737 # Get the true sha1's since we can use things like HEAD~3
2738 $start = get_sha1($start);
2739 $end = get_sha1($end);
2740
2741 my $type = $patchcheck_type;
2742
2743 # Can't have a test without having a test to run
2744 if ($type eq "test" && !defined($run_test)) {
2745 $type = "boot";
2746 }
2747
2748 open (IN, "git log --pretty=oneline $end|") or
2749 dodie "could not get git list";
2750
2751 my @list;
2752
2753 while (<IN>) {
2754 chomp;
2755 $list[$#list+1] = $_;
2756 last if (/^$start/);
2757 }
2758 close(IN);
2759
2760 if ($list[$#list] !~ /^$start/) {
2761 fail "SHA1 $start not found";
2762 }
2763
2764 # go backwards in the list
2765 @list = reverse @list;
2766
2767 my $save_clean = $noclean;
2768 my %ignored_warnings;
2769
2770 if (defined($ignore_warnings)) {
2771 foreach my $sha1 (split /\s+/, $ignore_warnings) {
2772 $ignored_warnings{$sha1} = 1;
2773 }
2774 }
2775
2776 $in_patchcheck = 1;
2777 foreach my $item (@list) {
2778 my $sha1 = $item;
2779 $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
2780
2781 doprint "\nProcessing commit $item\n\n";
2782
2783 run_command "git checkout $sha1" or
2784 die "Failed to checkout $sha1";
2785
2786 # only clean on the first and last patch
2787 if ($item eq $list[0] ||
2788 $item eq $list[$#list]) {
2789 $noclean = $save_clean;
2790 } else {
2791 $noclean = 1;
2792 }
2793
2794 if (defined($minconfig)) {
2795 build "useconfig:$minconfig" or return 0;
2796 } else {
2797 # ?? no config to use?
2798 build "oldconfig" or return 0;
2799 }
2800
2801
2802 if (!defined($ignored_warnings{$sha1})) {
2803 check_buildlog $sha1 or return 0;
2804 }
2805
2806 next if ($type eq "build");
2807
2808 my $failed = 0;
2809
2810 start_monitor_and_boot or $failed = 1;
2811
2812 if (!$failed && $type ne "boot"){
2813 do_run_test or $failed = 1;
2814 }
2815 end_monitor;
2816 return 0 if ($failed);
2817
2818 patchcheck_reboot;
2819
2820 }
2821 $in_patchcheck = 0;
2822 success $i;
2823
2824 return 1;
2825}
2826
2827my %depends;
2828my %depcount;
2829my $iflevel = 0;
2830my @ifdeps;
2831
2832# prevent recursion
2833my %read_kconfigs;
2834
2835sub add_dep {
2836 # $config depends on $dep
2837 my ($config, $dep) = @_;
2838
2839 if (defined($depends{$config})) {
2840 $depends{$config} .= " " . $dep;
2841 } else {
2842 $depends{$config} = $dep;
2843 }
2844
2845 # record the number of configs depending on $dep
2846 if (defined $depcount{$dep}) {
2847 $depcount{$dep}++;
2848 } else {
2849 $depcount{$dep} = 1;
2850 }
2851}
2852
2853# taken from streamline_config.pl
2854sub read_kconfig {
2855 my ($kconfig) = @_;
2856
2857 my $state = "NONE";
2858 my $config;
2859 my @kconfigs;
2860
2861 my $cont = 0;
2862 my $line;
2863
2864
2865 if (! -f $kconfig) {
2866 doprint "file $kconfig does not exist, skipping\n";
2867 return;
2868 }
2869
2870 open(KIN, "$kconfig")
2871 or die "Can't open $kconfig";
2872 while (<KIN>) {
2873 chomp;
2874
2875 # Make sure that lines ending with \ continue
2876 if ($cont) {
2877 $_ = $line . " " . $_;
2878 }
2879
2880 if (s/\\$//) {
2881 $cont = 1;
2882 $line = $_;
2883 next;
2884 }
2885
2886 $cont = 0;
2887
2888 # collect any Kconfig sources
2889 if (/^source\s*"(.*)"/) {
2890 $kconfigs[$#kconfigs+1] = $1;
2891 }
2892
2893 # configs found
2894 if (/^\s*(menu)?config\s+(\S+)\s*$/) {
2895 $state = "NEW";
2896 $config = $2;
2897
2898 for (my $i = 0; $i < $iflevel; $i++) {
2899 add_dep $config, $ifdeps[$i];
2900 }
2901
2902 # collect the depends for the config
2903 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
2904
2905 add_dep $config, $1;
2906
2907 # Get the configs that select this config
2908 } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
2909
2910 # selected by depends on config
2911 add_dep $1, $config;
2912
2913 # Check for if statements
2914 } elsif (/^if\s+(.*\S)\s*$/) {
2915 my $deps = $1;
2916 # remove beginning and ending non text
2917 $deps =~ s/^[^a-zA-Z0-9_]*//;
2918 $deps =~ s/[^a-zA-Z0-9_]*$//;
2919
2920 my @deps = split /[^a-zA-Z0-9_]+/, $deps;
2921
2922 $ifdeps[$iflevel++] = join ':', @deps;
2923
2924 } elsif (/^endif/) {
2925
2926 $iflevel-- if ($iflevel);
2927
2928 # stop on "help"
2929 } elsif (/^\s*help\s*$/) {
2930 $state = "NONE";
2931 }
2932 }
2933 close(KIN);
2934
2935 # read in any configs that were found.
2936 foreach $kconfig (@kconfigs) {
2937 if (!defined($read_kconfigs{$kconfig})) {
2938 $read_kconfigs{$kconfig} = 1;
2939 read_kconfig("$builddir/$kconfig");
2940 }
2941 }
2942}
2943
2944sub read_depends {
2945 # find out which arch this is by the kconfig file
2946 open (IN, $output_config)
2947 or dodie "Failed to read $output_config";
2948 my $arch;
2949 while (<IN>) {
2950 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
2951 $arch = $1;
2952 last;
2953 }
2954 }
2955 close IN;
2956
2957 if (!defined($arch)) {
2958 doprint "Could not find arch from config file\n";
2959 doprint "no dependencies used\n";
2960 return;
2961 }
2962
2963 # arch is really the subarch, we need to know
2964 # what directory to look at.
2965 if ($arch eq "i386" || $arch eq "x86_64") {
2966 $arch = "x86";
2967 } elsif ($arch =~ /^tile/) {
2968 $arch = "tile";
2969 }
2970
2971 my $kconfig = "$builddir/arch/$arch/Kconfig";
2972
2973 if (! -f $kconfig && $arch =~ /\d$/) {
2974 my $orig = $arch;
2975 # some subarchs have numbers, truncate them
2976 $arch =~ s/\d*$//;
2977 $kconfig = "$builddir/arch/$arch/Kconfig";
2978 if (! -f $kconfig) {
2979 doprint "No idea what arch dir $orig is for\n";
2980 doprint "no dependencies used\n";
2981 return;
2982 }
2983 }
2984
2985 read_kconfig($kconfig);
2986}
2987
2988sub read_config_list {
2989 my ($config) = @_;
2990
2991 open (IN, $config)
2992 or dodie "Failed to read $config";
2993
2994 while (<IN>) {
2995 if (/^((CONFIG\S*)=.*)/) {
2996 if (!defined($config_ignore{$2})) {
2997 $config_list{$2} = $1;
2998 }
2999 }
3000 }
3001
3002 close(IN);
3003}
3004
3005sub read_output_config {
3006 my ($config) = @_;
3007
3008 assign_configs \%config_ignore, $config;
3009}
3010
3011sub make_new_config {
3012 my @configs = @_;
3013
3014 open (OUT, ">$output_config")
3015 or dodie "Failed to write $output_config";
3016
3017 foreach my $config (@configs) {
3018 print OUT "$config\n";
3019 }
3020 close OUT;
3021}
3022
3023sub chomp_config {
3024 my ($config) = @_;
3025
3026 $config =~ s/CONFIG_//;
3027
3028 return $config;
3029}
3030
3031sub get_depends {
3032 my ($dep) = @_;
3033
3034 my $kconfig = chomp_config $dep;
3035
3036 $dep = $depends{"$kconfig"};
3037
3038 # the dep string we have saves the dependencies as they
3039 # were found, including expressions like ! && ||. We
3040 # want to split this out into just an array of configs.
3041
3042 my $valid = "A-Za-z_0-9";
3043
3044 my @configs;
3045
3046 while ($dep =~ /[$valid]/) {
3047
3048 if ($dep =~ /^[^$valid]*([$valid]+)/) {
3049 my $conf = "CONFIG_" . $1;
3050
3051 $configs[$#configs + 1] = $conf;
3052
3053 $dep =~ s/^[^$valid]*[$valid]+//;
3054 } else {
3055 die "this should never happen";
3056 }
3057 }
3058
3059 return @configs;
3060}
3061
3062my %min_configs;
3063my %keep_configs;
3064my %save_configs;
3065my %processed_configs;
3066my %nochange_config;
3067
3068sub test_this_config {
3069 my ($config) = @_;
3070
3071 my $found;
3072
3073 # if we already processed this config, skip it
3074 if (defined($processed_configs{$config})) {
3075 return undef;
3076 }
3077 $processed_configs{$config} = 1;
3078
3079 # if this config failed during this round, skip it
3080 if (defined($nochange_config{$config})) {
3081 return undef;
3082 }
3083
3084 my $kconfig = chomp_config $config;
3085
3086 # Test dependencies first
3087 if (defined($depends{"$kconfig"})) {
3088 my @parents = get_depends $config;
3089 foreach my $parent (@parents) {
3090 # if the parent is in the min config, check it first
3091 next if (!defined($min_configs{$parent}));
3092 $found = test_this_config($parent);
3093 if (defined($found)) {
3094 return $found;
3095 }
3096 }
3097 }
3098
3099 # Remove this config from the list of configs
3100 # do a make oldnoconfig and then read the resulting
3101 # .config to make sure it is missing the config that
3102 # we had before
3103 my %configs = %min_configs;
3104 delete $configs{$config};
3105 make_new_config ((values %configs), (values %keep_configs));
3106 make_oldconfig;
3107 undef %configs;
3108 assign_configs \%configs, $output_config;
3109
3110 return $config if (!defined($configs{$config}));
3111
3112 doprint "disabling config $config did not change .config\n";
3113
3114 $nochange_config{$config} = 1;
3115
3116 return undef;
3117}
3118
3119sub make_min_config {
3120 my ($i) = @_;
3121
3122 if (!defined($output_minconfig)) {
3123 fail "OUTPUT_MIN_CONFIG not defined" and return;
3124 }
3125
3126 # If output_minconfig exists, and the start_minconfig
3127 # came from min_config, than ask if we should use
3128 # that instead.
3129 if (-f $output_minconfig && !$start_minconfig_defined) {
3130 print "$output_minconfig exists\n";
3131 if (read_yn " Use it as minconfig?") {
3132 $start_minconfig = $output_minconfig;
3133 }
3134 }
3135
3136 if (!defined($start_minconfig)) {
3137 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
3138 }
3139
3140 my $temp_config = "$tmpdir/temp_config";
3141
3142 # First things first. We build an allnoconfig to find
3143 # out what the defaults are that we can't touch.
3144 # Some are selections, but we really can't handle selections.
3145
3146 my $save_minconfig = $minconfig;
3147 undef $minconfig;
3148
3149 run_command "$make allnoconfig" or return 0;
3150
3151 read_depends;
3152
3153 process_config_ignore $output_config;
3154
3155 undef %save_configs;
3156 undef %min_configs;
3157
3158 if (defined($ignore_config)) {
3159 # make sure the file exists
3160 `touch $ignore_config`;
3161 assign_configs \%save_configs, $ignore_config;
3162 }
3163
3164 %keep_configs = %save_configs;
3165
3166 doprint "Load initial configs from $start_minconfig\n";
3167
3168 # Look at the current min configs, and save off all the
3169 # ones that were set via the allnoconfig
3170 assign_configs \%min_configs, $start_minconfig;
3171
3172 my @config_keys = keys %min_configs;
3173
3174 # All configs need a depcount
3175 foreach my $config (@config_keys) {
3176 my $kconfig = chomp_config $config;
3177 if (!defined $depcount{$kconfig}) {
3178 $depcount{$kconfig} = 0;
3179 }
3180 }
3181
3182 # Remove anything that was set by the make allnoconfig
3183 # we shouldn't need them as they get set for us anyway.
3184 foreach my $config (@config_keys) {
3185 # Remove anything in the ignore_config
3186 if (defined($keep_configs{$config})) {
3187 my $file = $ignore_config;
3188 $file =~ s,.*/(.*?)$,$1,;
3189 doprint "$config set by $file ... ignored\n";
3190 delete $min_configs{$config};
3191 next;
3192 }
3193 # But make sure the settings are the same. If a min config
3194 # sets a selection, we do not want to get rid of it if
3195 # it is not the same as what we have. Just move it into
3196 # the keep configs.
3197 if (defined($config_ignore{$config})) {
3198 if ($config_ignore{$config} ne $min_configs{$config}) {
3199 doprint "$config is in allnoconfig as '$config_ignore{$config}'";
3200 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
3201 $keep_configs{$config} = $min_configs{$config};
3202 } else {
3203 doprint "$config set by allnoconfig ... ignored\n";
3204 }
3205 delete $min_configs{$config};
3206 }
3207 }
3208
3209 my $done = 0;
3210 my $take_two = 0;
3211
3212 while (!$done) {
3213
3214 my $config;
3215 my $found;
3216
3217 # Now disable each config one by one and do a make oldconfig
3218 # till we find a config that changes our list.
3219
3220 my @test_configs = keys %min_configs;
3221
3222 # Sort keys by who is most dependent on
3223 @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
3224 @test_configs ;
3225
3226 # Put configs that did not modify the config at the end.
3227 my $reset = 1;
3228 for (my $i = 0; $i < $#test_configs; $i++) {
3229 if (!defined($nochange_config{$test_configs[0]})) {
3230 $reset = 0;
3231 last;
3232 }
3233 # This config didn't change the .config last time.
3234 # Place it at the end
3235 my $config = shift @test_configs;
3236 push @test_configs, $config;
3237 }
3238
3239 # if every test config has failed to modify the .config file
3240 # in the past, then reset and start over.
3241 if ($reset) {
3242 undef %nochange_config;
3243 }
3244
3245 undef %processed_configs;
3246
3247 foreach my $config (@test_configs) {
3248
3249 $found = test_this_config $config;
3250
3251 last if (defined($found));
3252
3253 # oh well, try another config
3254 }
3255
3256 if (!defined($found)) {
3257 # we could have failed due to the nochange_config hash
3258 # reset and try again
3259 if (!$take_two) {
3260 undef %nochange_config;
3261 $take_two = 1;
3262 next;
3263 }
3264 doprint "No more configs found that we can disable\n";
3265 $done = 1;
3266 last;
3267 }
3268 $take_two = 0;
3269
3270 $config = $found;
3271
3272 doprint "Test with $config disabled\n";
3273
3274 # set in_bisect to keep build and monitor from dieing
3275 $in_bisect = 1;
3276
3277 my $failed = 0;
3278 build "oldconfig" or $failed = 1;
3279 if (!$failed) {
3280 start_monitor_and_boot or $failed = 1;
3281 end_monitor;
3282 }
3283
3284 $in_bisect = 0;
3285
3286 if ($failed) {
3287 doprint "$min_configs{$config} is needed to boot the box... keeping\n";
3288 # this config is needed, add it to the ignore list.
3289 $keep_configs{$config} = $min_configs{$config};
3290 $save_configs{$config} = $min_configs{$config};
3291 delete $min_configs{$config};
3292
3293 # update new ignore configs
3294 if (defined($ignore_config)) {
3295 open (OUT, ">$temp_config")
3296 or die "Can't write to $temp_config";
3297 foreach my $config (keys %save_configs) {
3298 print OUT "$save_configs{$config}\n";
3299 }
3300 close OUT;
3301 run_command "mv $temp_config $ignore_config" or
3302 dodie "failed to copy update to $ignore_config";
3303 }
3304
3305 } else {
3306 # We booted without this config, remove it from the minconfigs.
3307 doprint "$config is not needed, disabling\n";
3308
3309 delete $min_configs{$config};
3310
3311 # Also disable anything that is not enabled in this config
3312 my %configs;
3313 assign_configs \%configs, $output_config;
3314 my @config_keys = keys %min_configs;
3315 foreach my $config (@config_keys) {
3316 if (!defined($configs{$config})) {
3317 doprint "$config is not set, disabling\n";
3318 delete $min_configs{$config};
3319 }
3320 }
3321
3322 # Save off all the current mandidory configs
3323 open (OUT, ">$temp_config")
3324 or die "Can't write to $temp_config";
3325 foreach my $config (keys %keep_configs) {
3326 print OUT "$keep_configs{$config}\n";
3327 }
3328 foreach my $config (keys %min_configs) {
3329 print OUT "$min_configs{$config}\n";
3330 }
3331 close OUT;
3332
3333 run_command "mv $temp_config $output_minconfig" or
3334 dodie "failed to copy update to $output_minconfig";
3335 }
3336
3337 doprint "Reboot and wait $sleep_time seconds\n";
3338 reboot_to_good $sleep_time;
3339 }
3340
3341 success $i;
3342 return 1;
3343}
3344
3345$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n";
3346
3347if ($#ARGV == 0) {
3348 $ktest_config = $ARGV[0];
3349 if (! -f $ktest_config) {
3350 print "$ktest_config does not exist.\n";
3351 if (!read_yn "Create it?") {
3352 exit 0;
3353 }
3354 }
3355} else {
3356 $ktest_config = "ktest.conf";
3357}
3358
3359if (! -f $ktest_config) {
3360 $newconfig = 1;
3361 get_test_case;
3362 open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
3363 print OUT << "EOF"
3364# Generated by ktest.pl
3365#
3366
3367# PWD is a ktest.pl variable that will result in the process working
3368# directory that ktest.pl is executed in.
3369
3370# THIS_DIR is automatically assigned the PWD of the path that generated
3371# the config file. It is best to use this variable when assigning other
3372# directory paths within this directory. This allows you to easily
3373# move the test cases to other locations or to other machines.
3374#
3375THIS_DIR := $variable{"PWD"}
3376
3377# Define each test with TEST_START
3378# The config options below it will override the defaults
3379TEST_START
3380TEST_TYPE = $default{"TEST_TYPE"}
3381
3382DEFAULTS
3383EOF
3384;
3385 close(OUT);
3386}
3387read_config $ktest_config;
3388
3389if (defined($opt{"LOG_FILE"})) {
3390 $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
3391}
3392
3393# Append any configs entered in manually to the config file.
3394my @new_configs = keys %entered_configs;
3395if ($#new_configs >= 0) {
3396 print "\nAppending entered in configs to $ktest_config\n";
3397 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
3398 foreach my $config (@new_configs) {
3399 print OUT "$config = $entered_configs{$config}\n";
3400 $opt{$config} = process_variables($entered_configs{$config});
3401 }
3402}
3403
3404if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
3405 unlink $opt{"LOG_FILE"};
3406}
3407
3408doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
3409
3410for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
3411
3412 if (!$i) {
3413 doprint "DEFAULT OPTIONS:\n";
3414 } else {
3415 doprint "\nTEST $i OPTIONS";
3416 if (defined($repeat_tests{$i})) {
3417 $repeat = $repeat_tests{$i};
3418 doprint " ITERATE $repeat";
3419 }
3420 doprint "\n";
3421 }
3422
3423 foreach my $option (sort keys %opt) {
3424
3425 if ($option =~ /\[(\d+)\]$/) {
3426 next if ($i != $1);
3427 } else {
3428 next if ($i);
3429 }
3430
3431 doprint "$option = $opt{$option}\n";
3432 }
3433}
3434
3435sub __set_test_option {
3436 my ($name, $i) = @_;
3437
3438 my $option = "$name\[$i\]";
3439
3440 if (defined($opt{$option})) {
3441 return $opt{$option};
3442 }
3443
3444 foreach my $test (keys %repeat_tests) {
3445 if ($i >= $test &&
3446 $i < $test + $repeat_tests{$test}) {
3447 $option = "$name\[$test\]";
3448 if (defined($opt{$option})) {
3449 return $opt{$option};
3450 }
3451 }
3452 }
3453
3454 if (defined($opt{$name})) {
3455 return $opt{$name};
3456 }
3457
3458 return undef;
3459}
3460
3461sub set_test_option {
3462 my ($name, $i) = @_;
3463
3464 my $option = __set_test_option($name, $i);
3465 return $option if (!defined($option));
3466
3467 return eval_option($option, $i);
3468}
3469
3470# First we need to do is the builds
3471for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
3472
3473 # Do not reboot on failing test options
3474 $no_reboot = 1;
3475 $reboot_success = 0;
3476
3477 $iteration = $i;
3478
3479 my $makecmd = set_test_option("MAKE_CMD", $i);
3480
3481 # Load all the options into their mapped variable names
3482 foreach my $opt (keys %option_map) {
3483 ${$option_map{$opt}} = set_test_option($opt, $i);
3484 }
3485
3486 $start_minconfig_defined = 1;
3487
3488 if (!defined($start_minconfig)) {
3489 $start_minconfig_defined = 0;
3490 $start_minconfig = $minconfig;
3491 }
3492
3493 chdir $builddir || die "can't change directory to $builddir";
3494
3495 foreach my $dir ($tmpdir, $outputdir) {
3496 if (!-d $dir) {
3497 mkpath($dir) or
3498 die "can't create $dir";
3499 }
3500 }
3501
3502 $ENV{"SSH_USER"} = $ssh_user;
3503 $ENV{"MACHINE"} = $machine;
3504
3505 $buildlog = "$tmpdir/buildlog-$machine";
3506 $testlog = "$tmpdir/testlog-$machine";
3507 $dmesg = "$tmpdir/dmesg-$machine";
3508 $make = "$makecmd O=$outputdir";
3509 $output_config = "$outputdir/.config";
3510
3511 if (!$buildonly) {
3512 $target = "$ssh_user\@$machine";
3513 if ($reboot_type eq "grub") {
3514 dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3515 }
3516 }
3517
3518 my $run_type = $build_type;
3519 if ($test_type eq "patchcheck") {
3520 $run_type = $patchcheck_type;
3521 } elsif ($test_type eq "bisect") {
3522 $run_type = $bisect_type;
3523 } elsif ($test_type eq "config_bisect") {
3524 $run_type = $config_bisect_type;
3525 }
3526
3527 if ($test_type eq "make_min_config") {
3528 $run_type = "";
3529 }
3530
3531 # mistake in config file?
3532 if (!defined($run_type)) {
3533 $run_type = "ERROR";
3534 }
3535
3536 my $installme = "";
3537 $installme = " no_install" if ($no_install);
3538
3539 doprint "\n\n";
3540 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
3541
3542 unlink $dmesg;
3543 unlink $buildlog;
3544 unlink $testlog;
3545
3546 if (defined($addconfig)) {
3547 my $min = $minconfig;
3548 if (!defined($minconfig)) {
3549 $min = "";
3550 }
3551 run_command "cat $addconfig $min > $tmpdir/add_config" or
3552 dodie "Failed to create temp config";
3553 $minconfig = "$tmpdir/add_config";
3554 }
3555
3556 if (defined($checkout)) {
3557 run_command "git checkout $checkout" or
3558 die "failed to checkout $checkout";
3559 }
3560
3561 $no_reboot = 0;
3562
3563 # A test may opt to not reboot the box
3564 if ($reboot_on_success) {
3565 $reboot_success = 1;
3566 }
3567
3568 if ($test_type eq "bisect") {
3569 bisect $i;
3570 next;
3571 } elsif ($test_type eq "config_bisect") {
3572 config_bisect $i;
3573 next;
3574 } elsif ($test_type eq "patchcheck") {
3575 patchcheck $i;
3576 next;
3577 } elsif ($test_type eq "make_min_config") {
3578 make_min_config $i;
3579 next;
3580 }
3581
3582 if ($build_type ne "nobuild") {
3583 build $build_type or next;
3584 }
3585
3586 if ($test_type eq "install") {
3587 get_version;
3588 install;
3589 success $i;
3590 next;
3591 }
3592
3593 if ($test_type ne "build") {
3594 my $failed = 0;
3595 start_monitor_and_boot or $failed = 1;
3596
3597 if (!$failed && $test_type ne "boot" && defined($run_test)) {
3598 do_run_test or $failed = 1;
3599 }
3600 end_monitor;
3601 next if ($failed);
3602 }
3603
3604 success $i;
3605}
3606
3607if ($opt{"POWEROFF_ON_SUCCESS"}) {
3608 halt;
3609} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) {
3610 reboot_to_good;
3611} elsif (defined($switch_to_good)) {
3612 # still need to get to the good kernel
3613 run_command $switch_to_good;
3614}
3615
3616
3617doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n";
3618
3619exit 0;