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