xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision 63dc02bd)
1#!/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;
3620