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