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