Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh...
[deliverable/linux.git] / tools / testing / ktest / ktest.pl
CommitLineData
2545eb61 1#!/usr/bin/perl -w
d6ce2a0b 2#
cce1dac8 3# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
d6ce2a0b
SR
4# Licensed under the terms of the GNU GPL License version 2
5#
2545eb61
SR
6
7use strict;
8use IPC::Open2;
9use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
7faafbd6
SR
10use File::Path qw(mkpath);
11use File::Copy qw(cp);
2545eb61
SR
12use FileHandle;
13
e48c5293
SR
14my $VERSION = "0.2";
15
2545eb61
SR
16$| = 1;
17
18my %opt;
a57419b3
SR
19my %repeat_tests;
20my %repeats;
a75fecec 21my %default;
2545eb61
SR
22
23#default opts
a57419b3 24$default{"NUM_TESTS"} = 1;
a75fecec
SR
25$default{"REBOOT_TYPE"} = "grub";
26$default{"TEST_TYPE"} = "test";
27$default{"BUILD_TYPE"} = "randconfig";
28$default{"MAKE_CMD"} = "make";
29$default{"TIMEOUT"} = 120;
a57419b3 30$default{"TMP_DIR"} = "/tmp/ktest";
a75fecec
SR
31$default{"SLEEP_TIME"} = 60; # sleep time between tests
32$default{"BUILD_NOCLEAN"} = 0;
33$default{"REBOOT_ON_ERROR"} = 0;
34$default{"POWEROFF_ON_ERROR"} = 0;
35$default{"REBOOT_ON_SUCCESS"} = 1;
36$default{"POWEROFF_ON_SUCCESS"} = 0;
37$default{"BUILD_OPTIONS"} = "";
38$default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects
39$default{"CLEAR_LOG"} = 0;
40$default{"SUCCESS_LINE"} = "login:";
41$default{"BOOTED_TIMEOUT"} = 1;
42$default{"DIE_ON_FAILURE"} = 1;
e48c5293
SR
43$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
44$default{"SCP_TO_TARGET"} = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE";
45$default{"REBOOT"} = "ssh \$SSH_USER\@\$MACHINE reboot";
1c8a617a
SR
46$default{"STOP_AFTER_SUCCESS"} = 10;
47$default{"STOP_AFTER_FAILURE"} = 60;
8d1491ba 48$default{"LOCALVERSION"} = "-test";
2545eb61 49
8d1491ba 50my $ktest_config;
2545eb61 51my $version;
a75fecec 52my $machine;
e48c5293 53my $ssh_user;
a75fecec
SR
54my $tmpdir;
55my $builddir;
56my $outputdir;
51ad1dd1 57my $output_config;
a75fecec 58my $test_type;
7faafbd6 59my $build_type;
a75fecec
SR
60my $build_options;
61my $reboot_type;
62my $reboot_script;
63my $power_cycle;
e48c5293 64my $reboot;
a75fecec
SR
65my $reboot_on_error;
66my $poweroff_on_error;
67my $die_on_failure;
576f627c
SR
68my $powercycle_after_reboot;
69my $poweroff_after_halt;
e48c5293
SR
70my $ssh_exec;
71my $scp_to_target;
a75fecec
SR
72my $power_off;
73my $grub_menu;
2545eb61
SR
74my $grub_number;
75my $target;
76my $make;
8b37ca8c 77my $post_install;
5c42fc5b 78my $noclean;
5f9b6ced 79my $minconfig;
2b7d9b21 80my $addconfig;
5f9b6ced
SR
81my $in_bisect = 0;
82my $bisect_bad = "";
d6ce2a0b 83my $reverse_bisect;
6c5ee0be 84my $in_patchcheck = 0;
5a391fbf 85my $run_test;
6c5ee0be 86my $redirect;
7faafbd6
SR
87my $buildlog;
88my $dmesg;
89my $monitor_fp;
90my $monitor_pid;
91my $monitor_cnt = 0;
a75fecec
SR
92my $sleep_time;
93my $bisect_sleep_time;
94my $store_failures;
95my $timeout;
96my $booted_timeout;
97my $console;
98my $success_line;
1c8a617a
SR
99my $stop_after_success;
100my $stop_after_failure;
a75fecec
SR
101my $build_target;
102my $target_image;
103my $localversion;
576f627c 104my $iteration = 0;
e48c5293 105my $successes = 0;
2545eb61 106
8d1491ba
SR
107my %entered_configs;
108my %config_help;
109
110$config_help{"MACHINE"} = << "EOF"
111 The machine hostname that you will test.
112EOF
113 ;
114$config_help{"SSH_USER"} = << "EOF"
115 The box is expected to have ssh on normal bootup, provide the user
116 (most likely root, since you need privileged operations)
117EOF
118 ;
119$config_help{"BUILD_DIR"} = << "EOF"
120 The directory that contains the Linux source code (full path).
121EOF
122 ;
123$config_help{"OUTPUT_DIR"} = << "EOF"
124 The directory that the objects will be built (full path).
125 (can not be same as BUILD_DIR)
126EOF
127 ;
128$config_help{"BUILD_TARGET"} = << "EOF"
129 The location of the compiled file to copy to the target.
130 (relative to OUTPUT_DIR)
131EOF
132 ;
133$config_help{"TARGET_IMAGE"} = << "EOF"
134 The place to put your image on the test machine.
135EOF
136 ;
137$config_help{"POWER_CYCLE"} = << "EOF"
138 A script or command to reboot the box.
139
140 Here is a digital loggers power switch example
141 POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
142
143 Here is an example to reboot a virtual box on the current host
144 with the name "Guest".
145 POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
146EOF
147 ;
148$config_help{"CONSOLE"} = << "EOF"
149 The script or command that reads the console
150
151 If you use ttywatch server, something like the following would work.
152CONSOLE = nc -d localhost 3001
153
154 For a virtual machine with guest name "Guest".
155CONSOLE = virsh console Guest
156EOF
157 ;
158$config_help{"LOCALVERSION"} = << "EOF"
159 Required version ending to differentiate the test
160 from other linux builds on the system.
161EOF
162 ;
163$config_help{"REBOOT_TYPE"} = << "EOF"
164 Way to reboot the box to the test kernel.
165 Only valid options so far are "grub" and "script".
166
167 If you specify grub, it will assume grub version 1
168 and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
169 and select that target to reboot to the kernel. If this is not
170 your setup, then specify "script" and have a command or script
171 specified in REBOOT_SCRIPT to boot to the target.
172
173 The entry in /boot/grub/menu.lst must be entered in manually.
174 The test will not modify that file.
175EOF
176 ;
177$config_help{"GRUB_MENU"} = << "EOF"
178 The grub title name for the test kernel to boot
179 (Only mandatory if REBOOT_TYPE = grub)
180
181 Note, ktest.pl will not update the grub menu.lst, you need to
182 manually add an option for the test. ktest.pl will search
183 the grub menu.lst for this option to find what kernel to
184 reboot into.
185
186 For example, if in the /boot/grub/menu.lst the test kernel title has:
187 title Test Kernel
188 kernel vmlinuz-test
189 GRUB_MENU = Test Kernel
190EOF
191 ;
192$config_help{"REBOOT_SCRIPT"} = << "EOF"
193 A script to reboot the target into the test kernel
194 (Only mandatory if REBOOT_TYPE = script)
195EOF
196 ;
197
198
199sub get_ktest_config {
200 my ($config) = @_;
201
202 return if (defined($opt{$config}));
203
204 if (defined($config_help{$config})) {
205 print "\n";
206 print $config_help{$config};
207 }
208
209 for (;;) {
210 print "$config = ";
211 if (defined($default{$config})) {
212 print "\[$default{$config}\] ";
213 }
214 $entered_configs{$config} = <STDIN>;
215 $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/;
216 if ($entered_configs{$config} =~ /^\s*$/) {
217 if ($default{$config}) {
218 $entered_configs{$config} = $default{$config};
219 } else {
220 print "Your answer can not be blank\n";
221 next;
222 }
223 }
224 last;
225 }
226}
227
228sub get_ktest_configs {
229 get_ktest_config("MACHINE");
230 get_ktest_config("SSH_USER");
231 get_ktest_config("BUILD_DIR");
232 get_ktest_config("OUTPUT_DIR");
233 get_ktest_config("BUILD_TARGET");
234 get_ktest_config("TARGET_IMAGE");
235 get_ktest_config("POWER_CYCLE");
236 get_ktest_config("CONSOLE");
237 get_ktest_config("LOCALVERSION");
238
239 my $rtype = $opt{"REBOOT_TYPE"};
240
241 if (!defined($rtype)) {
242 if (!defined($opt{"GRUB_MENU"})) {
243 get_ktest_config("REBOOT_TYPE");
244 $rtype = $entered_configs{"REBOOT_TYPE"};
245 } else {
246 $rtype = "grub";
247 }
248 }
249
250 if ($rtype eq "grub") {
251 get_ktest_config("GRUB_MENU");
252 } else {
253 get_ktest_config("REBOOT_SCRIPT");
254 }
255}
256
a57419b3
SR
257sub set_value {
258 my ($lvalue, $rvalue) = @_;
259
260 if (defined($opt{$lvalue})) {
261 die "Error: Option $lvalue defined more than once!\n";
262 }
21a9679f
SR
263 if ($rvalue =~ /^\s*$/) {
264 delete $opt{$lvalue};
265 } else {
266 $opt{$lvalue} = $rvalue;
267 }
a57419b3
SR
268}
269
2545eb61
SR
270sub read_config {
271 my ($config) = @_;
272
273 open(IN, $config) || die "can't read file $config";
274
a57419b3
SR
275 my $name = $config;
276 $name =~ s,.*/(.*),$1,;
277
278 my $test_num = 0;
279 my $default = 1;
280 my $repeat = 1;
281 my $num_tests_set = 0;
282 my $skip = 0;
283 my $rest;
284
2545eb61
SR
285 while (<IN>) {
286
287 # ignore blank lines and comments
288 next if (/^\s*$/ || /\s*\#/);
289
a57419b3
SR
290 if (/^\s*TEST_START(.*)/) {
291
292 $rest = $1;
293
294 if ($num_tests_set) {
295 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
296 }
297
298 my $old_test_num = $test_num;
e48c5293 299 my $old_repeat = $repeat;
a57419b3
SR
300
301 $test_num += $repeat;
302 $default = 0;
303 $repeat = 1;
304
305 if ($rest =~ /\s+SKIP(.*)/) {
306 $rest = $1;
307 $skip = 1;
308 } else {
309 $skip = 0;
310 }
311
312 if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
313 $repeat = $1;
314 $rest = $2;
315 $repeat_tests{"$test_num"} = $repeat;
316 }
317
318 if ($rest =~ /\s+SKIP(.*)/) {
319 $rest = $1;
320 $skip = 1;
321 }
322
323 if ($rest !~ /^\s*$/) {
324 die "$name: $.: Gargbage found after TEST_START\n$_";
325 }
326
327 if ($skip) {
328 $test_num = $old_test_num;
e48c5293 329 $repeat = $old_repeat;
a57419b3
SR
330 }
331
332 } elsif (/^\s*DEFAULTS(.*)$/) {
333 $default = 1;
334
335 $rest = $1;
336
337 if ($rest =~ /\s+SKIP(.*)/) {
338 $rest = $1;
339 $skip = 1;
340 } else {
341 $skip = 0;
342 }
343
344 if ($rest !~ /^\s*$/) {
345 die "$name: $.: Gargbage found after DEFAULTS\n$_";
346 }
347
348 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
349
350 next if ($skip);
351
2545eb61
SR
352 my $lvalue = $1;
353 my $rvalue = $2;
354
a57419b3
SR
355 if (!$default &&
356 ($lvalue eq "NUM_TESTS" ||
357 $lvalue eq "LOG_FILE" ||
358 $lvalue eq "CLEAR_LOG")) {
359 die "$name: $.: $lvalue must be set in DEFAULTS section\n";
360 }
361
362 if ($lvalue eq "NUM_TESTS") {
363 if ($test_num) {
364 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
365 }
366 if (!$default) {
367 die "$name: $.: NUM_TESTS must be set in default section\n";
368 }
369 $num_tests_set = 1;
370 }
371
372 if ($default || $lvalue =~ /\[\d+\]$/) {
373 set_value($lvalue, $rvalue);
374 } else {
375 my $val = "$lvalue\[$test_num\]";
376 set_value($val, $rvalue);
377
378 if ($repeat > 1) {
379 $repeats{$val} = $repeat;
380 }
a75fecec 381 }
a57419b3
SR
382 } else {
383 die "$name: $.: Garbage found in config\n$_";
2545eb61
SR
384 }
385 }
386
387 close(IN);
a75fecec 388
a57419b3
SR
389 if ($test_num) {
390 $test_num += $repeat - 1;
391 $opt{"NUM_TESTS"} = $test_num;
392 }
393
8d1491ba
SR
394 # make sure we have all mandatory configs
395 get_ktest_configs;
396
a75fecec
SR
397 # set any defaults
398
399 foreach my $default (keys %default) {
400 if (!defined($opt{$default})) {
401 $opt{$default} = $default{$default};
402 }
403 }
2545eb61
SR
404}
405
d1e2f22a 406sub _logit {
2545eb61
SR
407 if (defined($opt{"LOG_FILE"})) {
408 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
409 print OUT @_;
410 close(OUT);
411 }
412}
413
d1e2f22a
SR
414sub logit {
415 if (defined($opt{"LOG_FILE"})) {
416 _logit @_;
417 } else {
418 print @_;
419 }
420}
421
5f9b6ced
SR
422sub doprint {
423 print @_;
d1e2f22a 424 _logit @_;
5f9b6ced
SR
425}
426
7faafbd6
SR
427sub run_command;
428
429sub reboot {
430 # try to reboot normally
e48c5293 431 if (run_command $reboot) {
576f627c
SR
432 if (defined($powercycle_after_reboot)) {
433 sleep $powercycle_after_reboot;
434 run_command "$power_cycle";
435 }
436 } else {
7faafbd6 437 # nope? power cycle it.
a75fecec 438 run_command "$power_cycle";
7faafbd6
SR
439 }
440}
441
576f627c
SR
442sub do_not_reboot {
443 my $i = $iteration;
444
445 return $test_type eq "build" ||
446 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
447 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
448}
449
5c42fc5b 450sub dodie {
5a391fbf 451 doprint "CRITICAL FAILURE... ", @_, "\n";
5c42fc5b 452
576f627c
SR
453 my $i = $iteration;
454
455 if ($reboot_on_error && !do_not_reboot) {
456
75c3fda7 457 doprint "REBOOTING\n";
7faafbd6 458 reboot;
75c3fda7 459
a75fecec 460 } elsif ($poweroff_on_error && defined($power_off)) {
5c42fc5b 461 doprint "POWERING OFF\n";
a75fecec 462 `$power_off`;
5c42fc5b 463 }
75c3fda7 464
576f627c 465 die @_, "\n";
5c42fc5b
SR
466}
467
7faafbd6
SR
468sub open_console {
469 my ($fp) = @_;
470
471 my $flags;
472
a75fecec
SR
473 my $pid = open($fp, "$console|") or
474 dodie "Can't open console $console";
7faafbd6
SR
475
476 $flags = fcntl($fp, F_GETFL, 0) or
576f627c 477 dodie "Can't get flags for the socket: $!";
7faafbd6 478 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
576f627c 479 dodie "Can't set flags for the socket: $!";
7faafbd6
SR
480
481 return $pid;
482}
483
484sub close_console {
485 my ($fp, $pid) = @_;
486
487 doprint "kill child process $pid\n";
488 kill 2, $pid;
489
490 print "closing!\n";
491 close($fp);
492}
493
494sub start_monitor {
495 if ($monitor_cnt++) {
496 return;
497 }
498 $monitor_fp = \*MONFD;
499 $monitor_pid = open_console $monitor_fp;
a75fecec
SR
500
501 return;
502
503 open(MONFD, "Stop perl from warning about single use of MONFD");
7faafbd6
SR
504}
505
506sub end_monitor {
507 if (--$monitor_cnt) {
508 return;
509 }
510 close_console($monitor_fp, $monitor_pid);
511}
512
513sub wait_for_monitor {
514 my ($time) = @_;
515 my $line;
516
a75fecec 517 doprint "** Wait for monitor to settle down **\n";
7faafbd6
SR
518
519 # read the monitor and wait for the system to calm down
520 do {
521 $line = wait_for_input($monitor_fp, $time);
a75fecec 522 print "$line" if (defined($line));
7faafbd6 523 } while (defined($line));
a75fecec 524 print "** Monitor flushed **\n";
7faafbd6
SR
525}
526
2b7d9b21
SR
527sub fail {
528
a75fecec 529 if ($die_on_failure) {
2b7d9b21
SR
530 dodie @_;
531 }
532
a75fecec 533 doprint "FAILED\n";
7faafbd6 534
576f627c
SR
535 my $i = $iteration;
536
a75fecec 537 # no need to reboot for just building.
576f627c 538 if (!do_not_reboot) {
a75fecec
SR
539 doprint "REBOOTING\n";
540 reboot;
541 start_monitor;
542 wait_for_monitor $sleep_time;
543 end_monitor;
544 }
7faafbd6 545
576f627c
SR
546 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
547 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
7a849cd9 548 doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n";
576f627c
SR
549 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
550 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
a75fecec
SR
551
552 return 1 if (!defined($store_failures));
7faafbd6
SR
553
554 my @t = localtime;
555 my $date = sprintf "%04d%02d%02d%02d%02d%02d",
556 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
557
cccae1a6
SR
558 my $type = $build_type;
559 if ($type =~ /useconfig/) {
560 $type = "useconfig";
561 }
562
563 my $dir = "$machine-$test_type-$type-fail-$date";
a75fecec 564 my $faildir = "$store_failures/$dir";
7faafbd6
SR
565
566 if (!-d $faildir) {
567 mkpath($faildir) or
a75fecec 568 die "can't create $faildir";
7faafbd6 569 }
51ad1dd1
SR
570 if (-f "$output_config") {
571 cp "$output_config", "$faildir/config" or
7faafbd6
SR
572 die "failed to copy .config";
573 }
574 if (-f $buildlog) {
575 cp $buildlog, "$faildir/buildlog" or
576 die "failed to move $buildlog";
577 }
578 if (-f $dmesg) {
579 cp $dmesg, "$faildir/dmesg" or
580 die "failed to move $dmesg";
581 }
582
583 doprint "*** Saved info to $faildir ***\n";
584
2b7d9b21
SR
585 return 1;
586}
587
2545eb61
SR
588sub run_command {
589 my ($command) = @_;
d6ce2a0b
SR
590 my $dolog = 0;
591 my $dord = 0;
592 my $pid;
593
e48c5293
SR
594 $command =~ s/\$SSH_USER/$ssh_user/g;
595 $command =~ s/\$MACHINE/$machine/g;
596
d6ce2a0b
SR
597 doprint("$command ... ");
598
599 $pid = open(CMD, "$command 2>&1 |") or
2b7d9b21 600 (fail "unable to exec $command" and return 0);
2545eb61
SR
601
602 if (defined($opt{"LOG_FILE"})) {
d6ce2a0b
SR
603 open(LOG, ">>$opt{LOG_FILE}") or
604 dodie "failed to write to log";
605 $dolog = 1;
6c5ee0be
SR
606 }
607
608 if (defined($redirect)) {
d6ce2a0b
SR
609 open (RD, ">$redirect") or
610 dodie "failed to write to redirect $redirect";
611 $dord = 1;
2545eb61
SR
612 }
613
d6ce2a0b
SR
614 while (<CMD>) {
615 print LOG if ($dolog);
616 print RD if ($dord);
617 }
2545eb61 618
d6ce2a0b 619 waitpid($pid, 0);
2545eb61
SR
620 my $failed = $?;
621
d6ce2a0b
SR
622 close(CMD);
623 close(LOG) if ($dolog);
624 close(RD) if ($dord);
625
2545eb61
SR
626 if ($failed) {
627 doprint "FAILED!\n";
628 } else {
629 doprint "SUCCESS\n";
630 }
631
5f9b6ced
SR
632 return !$failed;
633}
634
e48c5293
SR
635sub run_ssh {
636 my ($cmd) = @_;
637 my $cp_exec = $ssh_exec;
638
639 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
640 return run_command "$cp_exec";
641}
642
643sub run_scp {
644 my ($src, $dst) = @_;
645 my $cp_scp = $scp_to_target;
646
647 $cp_scp =~ s/\$SRC_FILE/$src/g;
648 $cp_scp =~ s/\$DST_FILE/$dst/g;
649
650 return run_command "$cp_scp";
651}
652
5f9b6ced
SR
653sub get_grub_index {
654
a75fecec
SR
655 if ($reboot_type ne "grub") {
656 return;
657 }
5a391fbf 658 return if (defined($grub_number));
5f9b6ced
SR
659
660 doprint "Find grub menu ... ";
661 $grub_number = -1;
e48c5293
SR
662
663 my $ssh_grub = $ssh_exec;
664 $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
665
666 open(IN, "$ssh_grub |")
5f9b6ced 667 or die "unable to get menu.lst";
e48c5293 668
5f9b6ced 669 while (<IN>) {
a75fecec 670 if (/^\s*title\s+$grub_menu\s*$/) {
5f9b6ced
SR
671 $grub_number++;
672 last;
673 } elsif (/^\s*title\s/) {
674 $grub_number++;
675 }
676 }
677 close(IN);
678
a75fecec 679 die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
5f9b6ced
SR
680 if ($grub_number < 0);
681 doprint "$grub_number\n";
2545eb61
SR
682}
683
2545eb61
SR
684sub wait_for_input
685{
686 my ($fp, $time) = @_;
687 my $rin;
688 my $ready;
689 my $line;
690 my $ch;
691
692 if (!defined($time)) {
693 $time = $timeout;
694 }
695
696 $rin = '';
697 vec($rin, fileno($fp), 1) = 1;
698 $ready = select($rin, undef, undef, $time);
699
700 $line = "";
701
702 # try to read one char at a time
703 while (sysread $fp, $ch, 1) {
704 $line .= $ch;
705 last if ($ch eq "\n");
706 }
707
708 if (!length($line)) {
709 return undef;
710 }
711
712 return $line;
713}
714
75c3fda7 715sub reboot_to {
a75fecec 716 if ($reboot_type eq "grub") {
eec56460 717 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
a75fecec
SR
718 return;
719 }
720
721 run_command "$reboot_script";
2545eb61
SR
722}
723
a57419b3
SR
724sub get_sha1 {
725 my ($commit) = @_;
726
727 doprint "git rev-list --max-count=1 $commit ... ";
728 my $sha1 = `git rev-list --max-count=1 $commit`;
729 my $ret = $?;
730
731 logit $sha1;
732
733 if ($ret) {
734 doprint "FAILED\n";
735 dodie "Failed to get git $commit";
736 }
737
738 print "SUCCESS\n";
739
740 chomp $sha1;
741
742 return $sha1;
743}
744
5a391fbf 745sub monitor {
2545eb61
SR
746 my $booted = 0;
747 my $bug = 0;
5c42fc5b 748 my $skip_call_trace = 0;
2b7d9b21 749 my $loops;
2545eb61 750
7faafbd6 751 wait_for_monitor 5;
2545eb61
SR
752
753 my $line;
754 my $full_line = "";
755
7faafbd6
SR
756 open(DMESG, "> $dmesg") or
757 die "unable to write to $dmesg";
2545eb61 758
75c3fda7 759 reboot_to;
2545eb61 760
1c8a617a
SR
761 my $success_start;
762 my $failure_start;
763
2545eb61
SR
764 for (;;) {
765
2b7d9b21 766 if ($booted) {
a75fecec 767 $line = wait_for_input($monitor_fp, $booted_timeout);
2b7d9b21 768 } else {
7faafbd6 769 $line = wait_for_input($monitor_fp);
2b7d9b21 770 }
2545eb61
SR
771
772 last if (!defined($line));
773
774 doprint $line;
7faafbd6 775 print DMESG $line;
2545eb61
SR
776
777 # we are not guaranteed to get a full line
778 $full_line .= $line;
779
a75fecec 780 if ($full_line =~ /$success_line/) {
2545eb61 781 $booted = 1;
1c8a617a
SR
782 $success_start = time;
783 }
784
785 if ($booted && defined($stop_after_success) &&
786 $stop_after_success >= 0) {
787 my $now = time;
788 if ($now - $success_start >= $stop_after_success) {
789 doprint "Test forced to stop after $stop_after_success seconds after success\n";
790 last;
791 }
2545eb61
SR
792 }
793
5c42fc5b
SR
794 if ($full_line =~ /\[ backtrace testing \]/) {
795 $skip_call_trace = 1;
796 }
797
2545eb61 798 if ($full_line =~ /call trace:/i) {
1c8a617a
SR
799 if (!$skip_call_trace) {
800 $bug = 1;
801 $failure_start = time;
802 }
803 }
804
805 if ($bug && defined($stop_after_failure) &&
806 $stop_after_failure >= 0) {
807 my $now = time;
808 if ($now - $failure_start >= $stop_after_failure) {
809 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
810 last;
811 }
5c42fc5b
SR
812 }
813
814 if ($full_line =~ /\[ end of backtrace testing \]/) {
815 $skip_call_trace = 0;
816 }
817
818 if ($full_line =~ /Kernel panic -/) {
2545eb61
SR
819 $bug = 1;
820 }
821
822 if ($line =~ /\n/) {
823 $full_line = "";
824 }
825 }
826
7faafbd6 827 close(DMESG);
2545eb61 828
a75fecec 829 if ($bug) {
2b7d9b21 830 return 0 if ($in_bisect);
576f627c 831 fail "failed - got a bug report" and return 0;
2545eb61
SR
832 }
833
a75fecec 834 if (!$booted) {
2b7d9b21 835 return 0 if ($in_bisect);
576f627c 836 fail "failed - never got a boot prompt." and return 0;
2545eb61 837 }
5f9b6ced 838
2b7d9b21 839 return 1;
2545eb61
SR
840}
841
842sub install {
843
e48c5293 844 run_scp "$outputdir/$build_target", "$target_image" or
5c42fc5b 845 dodie "failed to copy image";
2545eb61 846
5f9b6ced 847 my $install_mods = 0;
2545eb61 848
5f9b6ced
SR
849 # should we process modules?
850 $install_mods = 0;
51ad1dd1 851 open(IN, "$output_config") or dodie("Can't read config file");
5f9b6ced
SR
852 while (<IN>) {
853 if (/CONFIG_MODULES(=y)?/) {
854 $install_mods = 1 if (defined($1));
855 last;
5c42fc5b 856 }
5f9b6ced
SR
857 }
858 close(IN);
5c42fc5b 859
5f9b6ced
SR
860 if (!$install_mods) {
861 doprint "No modules needed\n";
862 return;
863 }
2545eb61 864
a75fecec 865 run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
5f9b6ced 866 dodie "Failed to install modules";
5c42fc5b 867
5f9b6ced 868 my $modlib = "/lib/modules/$version";
a57419b3 869 my $modtar = "ktest-mods.tar.bz2";
5c42fc5b 870
e48c5293 871 run_ssh "rm -rf $modlib" or
5f9b6ced 872 dodie "failed to remove old mods: $modlib";
5c42fc5b 873
5f9b6ced 874 # would be nice if scp -r did not follow symbolic links
a75fecec 875 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
5f9b6ced
SR
876 dodie "making tarball";
877
e48c5293 878 run_scp "$tmpdir/$modtar", "/tmp" or
5f9b6ced
SR
879 dodie "failed to copy modules";
880
a75fecec 881 unlink "$tmpdir/$modtar";
5f9b6ced 882
e48c5293 883 run_ssh "'(cd / && tar xf /tmp/$modtar)'" or
5f9b6ced 884 dodie "failed to tar modules";
2545eb61 885
e48c5293 886 run_ssh "rm -f /tmp/$modtar";
8b37ca8c
SR
887
888 return if (!defined($post_install));
889
e48c5293
SR
890 my $cp_post_install = $post_install;
891 $cp_post_install = s/\$KERNEL_VERSION/$version/g;
892 run_command "$cp_post_install" or
576f627c 893 dodie "Failed to run post install";
2545eb61
SR
894}
895
6c5ee0be
SR
896sub check_buildlog {
897 my ($patch) = @_;
898
6c5ee0be
SR
899 my @files = `git show $patch | diffstat -l`;
900
901 open(IN, "git show $patch |") or
902 dodie "failed to show $patch";
903 while (<IN>) {
904 if (m,^--- a/(.*),) {
905 chomp $1;
906 $files[$#files] = $1;
907 }
908 }
909 close(IN);
910
911 open(IN, $buildlog) or dodie "Can't open $buildlog";
912 while (<IN>) {
913 if (/^\s*(.*?):.*(warning|error)/) {
914 my $err = $1;
915 foreach my $file (@files) {
a75fecec 916 my $fullpath = "$builddir/$file";
6c5ee0be 917 if ($file eq $err || $fullpath eq $err) {
2b7d9b21 918 fail "$file built with warnings" and return 0;
6c5ee0be
SR
919 }
920 }
921 }
922 }
923 close(IN);
2b7d9b21
SR
924
925 return 1;
6c5ee0be
SR
926}
927
2545eb61
SR
928sub build {
929 my ($type) = @_;
5c42fc5b 930 my $defconfig = "";
5c42fc5b 931
7faafbd6
SR
932 unlink $buildlog;
933
75c3fda7 934 if ($type =~ /^useconfig:(.*)/) {
51ad1dd1 935 run_command "cp $1 $output_config" or
75c3fda7 936 dodie "could not copy $1 to .config";
5f9b6ced 937
75c3fda7
SR
938 $type = "oldconfig";
939 }
940
5c42fc5b
SR
941 # old config can ask questions
942 if ($type eq "oldconfig") {
9386c6ab 943 $type = "oldnoconfig";
75c3fda7
SR
944
945 # allow for empty configs
51ad1dd1 946 run_command "touch $output_config";
75c3fda7 947
51ad1dd1 948 run_command "mv $output_config $outputdir/config_temp" or
5c42fc5b 949 dodie "moving .config";
2545eb61 950
5f9b6ced 951 if (!$noclean && !run_command "$make mrproper") {
5c42fc5b
SR
952 dodie "make mrproper";
953 }
2545eb61 954
51ad1dd1 955 run_command "mv $outputdir/config_temp $output_config" or
5c42fc5b 956 dodie "moving config_temp";
5c42fc5b
SR
957
958 } elsif (!$noclean) {
51ad1dd1 959 unlink "$output_config";
5f9b6ced 960 run_command "$make mrproper" or
5c42fc5b 961 dodie "make mrproper";
5c42fc5b 962 }
2545eb61
SR
963
964 # add something to distinguish this build
a75fecec
SR
965 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
966 print OUT "$localversion\n";
2545eb61
SR
967 close(OUT);
968
5f9b6ced
SR
969 if (defined($minconfig)) {
970 $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
2545eb61
SR
971 }
972
9386c6ab 973 run_command "$defconfig $make $type" or
5c42fc5b 974 dodie "failed make config";
2545eb61 975
a75fecec
SR
976 $redirect = "$buildlog";
977 if (!run_command "$make $build_options") {
6c5ee0be 978 undef $redirect;
5f9b6ced 979 # bisect may need this to pass
2b7d9b21
SR
980 return 0 if ($in_bisect);
981 fail "failed build" and return 0;
2545eb61 982 }
6c5ee0be 983 undef $redirect;
5f9b6ced 984
2b7d9b21 985 return 1;
2545eb61
SR
986}
987
75c3fda7 988sub halt {
e48c5293 989 if (!run_ssh "halt" or defined($power_off)) {
576f627c
SR
990 if (defined($poweroff_after_halt)) {
991 sleep $poweroff_after_halt;
992 run_command "$power_off";
993 }
994 } else {
75c3fda7 995 # nope? the zap it!
a75fecec 996 run_command "$power_off";
75c3fda7
SR
997 }
998}
999
5f9b6ced
SR
1000sub success {
1001 my ($i) = @_;
1002
e48c5293
SR
1003 $successes++;
1004
5f9b6ced
SR
1005 doprint "\n\n*******************************************\n";
1006 doprint "*******************************************\n";
7a849cd9 1007 doprint "KTEST RESULT: TEST $i SUCCESS!!!! **\n";
5f9b6ced
SR
1008 doprint "*******************************************\n";
1009 doprint "*******************************************\n";
1010
576f627c 1011 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
a75fecec 1012 doprint "Reboot and wait $sleep_time seconds\n";
5f9b6ced 1013 reboot;
7faafbd6 1014 start_monitor;
a75fecec 1015 wait_for_monitor $sleep_time;
7faafbd6 1016 end_monitor;
5f9b6ced
SR
1017 }
1018}
1019
1020sub get_version {
1021 # get the release name
1022 doprint "$make kernelrelease ... ";
1023 $version = `$make kernelrelease | tail -1`;
1024 chomp($version);
1025 doprint "$version\n";
1026}
1027
5a391fbf 1028sub child_run_test {
7faafbd6 1029 my $failed = 0;
5a391fbf 1030
7faafbd6 1031 # child should have no power
a75fecec
SR
1032 $reboot_on_error = 0;
1033 $poweroff_on_error = 0;
1034 $die_on_failure = 1;
7faafbd6
SR
1035
1036 run_command $run_test or $failed = 1;
5a391fbf
SR
1037 exit $failed;
1038}
1039
1040my $child_done;
1041
1042sub child_finished {
1043 $child_done = 1;
1044}
1045
1046sub do_run_test {
1047 my $child_pid;
1048 my $child_exit;
5a391fbf
SR
1049 my $line;
1050 my $full_line;
1051 my $bug = 0;
5a391fbf 1052
7faafbd6 1053 wait_for_monitor 1;
5a391fbf 1054
7faafbd6 1055 doprint "run test $run_test\n";
5a391fbf
SR
1056
1057 $child_done = 0;
1058
1059 $SIG{CHLD} = qw(child_finished);
1060
1061 $child_pid = fork;
1062
1063 child_run_test if (!$child_pid);
1064
1065 $full_line = "";
1066
1067 do {
7faafbd6 1068 $line = wait_for_input($monitor_fp, 1);
5a391fbf
SR
1069 if (defined($line)) {
1070
1071 # we are not guaranteed to get a full line
1072 $full_line .= $line;
1073
1074 if ($full_line =~ /call trace:/i) {
1075 $bug = 1;
1076 }
1077
1078 if ($full_line =~ /Kernel panic -/) {
1079 $bug = 1;
1080 }
1081
1082 if ($line =~ /\n/) {
1083 $full_line = "";
1084 }
1085 }
1086 } while (!$child_done && !$bug);
1087
1088 if ($bug) {
1089 doprint "Detected kernel crash!\n";
1090 # kill the child with extreme prejudice
1091 kill 9, $child_pid;
1092 }
1093
1094 waitpid $child_pid, 0;
1095 $child_exit = $?;
1096
5a391fbf 1097 if ($bug || $child_exit) {
2b7d9b21
SR
1098 return 0 if $in_bisect;
1099 fail "test failed" and return 0;
5a391fbf 1100 }
2b7d9b21 1101 return 1;
5a391fbf
SR
1102}
1103
a75fecec
SR
1104sub run_git_bisect {
1105 my ($command) = @_;
1106
1107 doprint "$command ... ";
1108
1109 my $output = `$command 2>&1`;
1110 my $ret = $?;
1111
1112 logit $output;
1113
1114 if ($ret) {
1115 doprint "FAILED\n";
1116 dodie "Failed to git bisect";
1117 }
1118
1119 doprint "SUCCESS\n";
1120 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1121 doprint "$1 [$2]\n";
1122 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1123 $bisect_bad = $1;
1124 doprint "Found bad commit... $1\n";
1125 return 0;
1126 } else {
1127 # we already logged it, just print it now.
1128 print $output;
1129 }
1130
1131 return 1;
1132}
1133
0a05c769
SR
1134# returns 1 on success, 0 on failure
1135sub run_bisect_test {
1136 my ($type, $buildtype) = @_;
5f9b6ced 1137
2b7d9b21 1138 my $failed = 0;
5f9b6ced
SR
1139 my $result;
1140 my $output;
1141 my $ret;
1142
0a05c769
SR
1143 $in_bisect = 1;
1144
1145 build $buildtype or $failed = 1;
5f9b6ced
SR
1146
1147 if ($type ne "build") {
7faafbd6 1148 dodie "Failed on build" if $failed;
5f9b6ced
SR
1149
1150 # Now boot the box
1151 get_grub_index;
1152 get_version;
1153 install;
7faafbd6
SR
1154
1155 start_monitor;
2b7d9b21 1156 monitor or $failed = 1;
5f9b6ced
SR
1157
1158 if ($type ne "boot") {
7faafbd6 1159 dodie "Failed on boot" if $failed;
5a391fbf 1160
2b7d9b21 1161 do_run_test or $failed = 1;
5f9b6ced 1162 }
7faafbd6 1163 end_monitor;
5f9b6ced
SR
1164 }
1165
1166 if ($failed) {
0a05c769 1167 $result = 0;
5a391fbf
SR
1168
1169 # reboot the box to a good kernel
a75fecec
SR
1170 if ($type ne "build") {
1171 doprint "Reboot and sleep $bisect_sleep_time seconds\n";
5a391fbf 1172 reboot;
7faafbd6 1173 start_monitor;
a75fecec 1174 wait_for_monitor $bisect_sleep_time;
7faafbd6 1175 end_monitor;
5a391fbf 1176 }
5f9b6ced 1177 } else {
0a05c769
SR
1178 $result = 1;
1179 }
1180 $in_bisect = 0;
1181
1182 return $result;
1183}
1184
1185sub run_bisect {
1186 my ($type) = @_;
1187 my $buildtype = "oldconfig";
1188
1189 # We should have a minconfig to use?
1190 if (defined($minconfig)) {
1191 $buildtype = "useconfig:$minconfig";
5f9b6ced
SR
1192 }
1193
0a05c769
SR
1194 my $ret = run_bisect_test $type, $buildtype;
1195
1196
d6ce2a0b
SR
1197 # Are we looking for where it worked, not failed?
1198 if ($reverse_bisect) {
0a05c769 1199 $ret = !$ret;
d6ce2a0b
SR
1200 }
1201
0a05c769
SR
1202 if ($ret) {
1203 return "good";
1204 } else {
1205 return "bad";
1206 }
5f9b6ced
SR
1207}
1208
1209sub bisect {
1210 my ($i) = @_;
1211
1212 my $result;
1213
1214 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
1215 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
1216 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
1217
1218 my $good = $opt{"BISECT_GOOD[$i]"};
1219 my $bad = $opt{"BISECT_BAD[$i]"};
1220 my $type = $opt{"BISECT_TYPE[$i]"};
a75fecec
SR
1221 my $start = $opt{"BISECT_START[$i]"};
1222 my $replay = $opt{"BISECT_REPLAY[$i]"};
5f9b6ced 1223
a57419b3
SR
1224 # convert to true sha1's
1225 $good = get_sha1($good);
1226 $bad = get_sha1($bad);
1227
d6ce2a0b
SR
1228 if (defined($opt{"BISECT_REVERSE[$i]"}) &&
1229 $opt{"BISECT_REVERSE[$i]"} == 1) {
1230 doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1231 $reverse_bisect = 1;
1232 } else {
1233 $reverse_bisect = 0;
1234 }
1235
a75fecec
SR
1236 # Can't have a test without having a test to run
1237 if ($type eq "test" && !defined($run_test)) {
1238 $type = "boot";
1239 }
1240
1241 my $check = $opt{"BISECT_CHECK[$i]"};
1242 if (defined($check) && $check ne "0") {
1243
1244 # get current HEAD
a57419b3 1245 my $head = get_sha1("HEAD");
a75fecec
SR
1246
1247 if ($check ne "good") {
1248 doprint "TESTING BISECT BAD [$bad]\n";
1249 run_command "git checkout $bad" or
1250 die "Failed to checkout $bad";
1251
1252 $result = run_bisect $type;
1253
1254 if ($result ne "bad") {
1255 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
1256 }
1257 }
1258
1259 if ($check ne "bad") {
1260 doprint "TESTING BISECT GOOD [$good]\n";
1261 run_command "git checkout $good" or
1262 die "Failed to checkout $good";
1263
1264 $result = run_bisect $type;
1265
1266 if ($result ne "good") {
1267 fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
1268 }
1269 }
1270
1271 # checkout where we started
1272 run_command "git checkout $head" or
1273 die "Failed to checkout $head";
1274 }
1275
5f9b6ced 1276 run_command "git bisect start" or
a75fecec 1277 dodie "could not start bisect";
5f9b6ced
SR
1278
1279 run_command "git bisect good $good" or
a75fecec 1280 dodie "could not set bisect good to $good";
5f9b6ced 1281
a75fecec
SR
1282 run_git_bisect "git bisect bad $bad" or
1283 dodie "could not set bisect bad to $bad";
5f9b6ced 1284
a75fecec
SR
1285 if (defined($replay)) {
1286 run_command "git bisect replay $replay" or
1287 dodie "failed to run replay";
5a391fbf
SR
1288 }
1289
a75fecec
SR
1290 if (defined($start)) {
1291 run_command "git checkout $start" or
1292 dodie "failed to checkout $start";
1293 }
1294
1295 my $test;
5f9b6ced
SR
1296 do {
1297 $result = run_bisect $type;
a75fecec
SR
1298 $test = run_git_bisect "git bisect $result";
1299 } while ($test);
5f9b6ced
SR
1300
1301 run_command "git bisect log" or
1302 dodie "could not capture git bisect log";
1303
1304 run_command "git bisect reset" or
1305 dodie "could not reset git bisect";
1306
1307 doprint "Bad commit was [$bisect_bad]\n";
1308
0a05c769
SR
1309 success $i;
1310}
1311
1312my %config_ignore;
1313my %config_set;
1314
1315my %config_list;
1316my %null_config;
1317
1318my %dependency;
1319
1320sub process_config_ignore {
1321 my ($config) = @_;
1322
1323 open (IN, $config)
1324 or dodie "Failed to read $config";
1325
1326 while (<IN>) {
1327 if (/^(.*?(CONFIG\S*)(=.*| is not set))/) {
1328 $config_ignore{$2} = $1;
1329 }
1330 }
1331
1332 close(IN);
1333}
1334
1335sub read_current_config {
1336 my ($config_ref) = @_;
1337
1338 %{$config_ref} = ();
1339 undef %{$config_ref};
1340
1341 my @key = keys %{$config_ref};
1342 if ($#key >= 0) {
1343 print "did not delete!\n";
1344 exit;
1345 }
1346 open (IN, "$output_config");
1347
1348 while (<IN>) {
1349 if (/^(CONFIG\S+)=(.*)/) {
1350 ${$config_ref}{$1} = $2;
1351 }
1352 }
1353 close(IN);
1354}
1355
1356sub get_dependencies {
1357 my ($config) = @_;
1358
1359 my $arr = $dependency{$config};
1360 if (!defined($arr)) {
1361 return ();
1362 }
1363
1364 my @deps = @{$arr};
1365
1366 foreach my $dep (@{$arr}) {
1367 print "ADD DEP $dep\n";
1368 @deps = (@deps, get_dependencies $dep);
1369 }
1370
1371 return @deps;
1372}
1373
1374sub create_config {
1375 my @configs = @_;
1376
1377 open(OUT, ">$output_config") or dodie "Can not write to $output_config";
1378
1379 foreach my $config (@configs) {
1380 print OUT "$config_set{$config}\n";
1381 my @deps = get_dependencies $config;
1382 foreach my $dep (@deps) {
1383 print OUT "$config_set{$dep}\n";
1384 }
1385 }
1386
1387 foreach my $config (keys %config_ignore) {
1388 print OUT "$config_ignore{$config}\n";
1389 }
1390 close(OUT);
1391
1392# exit;
1393 run_command "$make oldnoconfig" or
1394 dodie "failed make config oldconfig";
1395
1396}
1397
1398sub compare_configs {
1399 my (%a, %b) = @_;
1400
1401 foreach my $item (keys %a) {
1402 if (!defined($b{$item})) {
1403 print "diff $item\n";
1404 return 1;
1405 }
1406 delete $b{$item};
1407 }
1408
1409 my @keys = keys %b;
1410 if ($#keys) {
1411 print "diff2 $keys[0]\n";
1412 }
1413 return -1 if ($#keys >= 0);
1414
1415 return 0;
1416}
1417
1418sub run_config_bisect_test {
1419 my ($type) = @_;
1420
1421 return run_bisect_test $type, "oldconfig";
1422}
1423
1424sub process_passed {
1425 my (%configs) = @_;
1426
1427 doprint "These configs had no failure: (Enabling them for further compiles)\n";
1428 # Passed! All these configs are part of a good compile.
1429 # Add them to the min options.
1430 foreach my $config (keys %configs) {
1431 if (defined($config_list{$config})) {
1432 doprint " removing $config\n";
1433 $config_ignore{$config} = $config_list{$config};
1434 delete $config_list{$config};
1435 }
1436 }
f1a27850
SR
1437 doprint "config copied to $outputdir/config_good\n";
1438 run_command "cp -f $output_config $outputdir/config_good";
0a05c769
SR
1439}
1440
1441sub process_failed {
1442 my ($config) = @_;
1443
1444 doprint "\n\n***************************************\n";
1445 doprint "Found bad config: $config\n";
1446 doprint "***************************************\n\n";
1447}
1448
1449sub run_config_bisect {
1450
1451 my @start_list = keys %config_list;
1452
1453 if ($#start_list < 0) {
1454 doprint "No more configs to test!!!\n";
1455 return -1;
1456 }
1457
1458 doprint "***** RUN TEST ***\n";
1459 my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
1460 my $ret;
1461 my %current_config;
1462
1463 my $count = $#start_list + 1;
1464 doprint " $count configs to test\n";
1465
1466 my $half = int($#start_list / 2);
1467
1468 do {
1469 my @tophalf = @start_list[0 .. $half];
1470
1471 create_config @tophalf;
1472 read_current_config \%current_config;
1473
1474 $count = $#tophalf + 1;
1475 doprint "Testing $count configs\n";
1476 my $found = 0;
1477 # make sure we test something
1478 foreach my $config (@tophalf) {
1479 if (defined($current_config{$config})) {
1480 logit " $config\n";
1481 $found = 1;
1482 }
1483 }
1484 if (!$found) {
1485 # try the other half
1486 doprint "Top half produced no set configs, trying bottom half\n";
1487 @tophalf = @start_list[$half .. $#start_list];
1488 create_config @tophalf;
1489 read_current_config \%current_config;
1490 foreach my $config (@tophalf) {
1491 if (defined($current_config{$config})) {
1492 logit " $config\n";
1493 $found = 1;
1494 }
1495 }
1496 if (!$found) {
1497 doprint "Failed: Can't make new config with current configs\n";
1498 foreach my $config (@start_list) {
1499 doprint " CONFIG: $config\n";
1500 }
1501 return -1;
1502 }
1503 $count = $#tophalf + 1;
1504 doprint "Testing $count configs\n";
1505 }
1506
1507 $ret = run_config_bisect_test $type;
1508
1509 if ($ret) {
1510 process_passed %current_config;
1511 return 0;
1512 }
1513
1514 doprint "This config had a failure.\n";
1515 doprint "Removing these configs that were not set in this config:\n";
f1a27850
SR
1516 doprint "config copied to $outputdir/config_bad\n";
1517 run_command "cp -f $output_config $outputdir/config_bad";
0a05c769
SR
1518
1519 # A config exists in this group that was bad.
1520 foreach my $config (keys %config_list) {
1521 if (!defined($current_config{$config})) {
1522 doprint " removing $config\n";
1523 delete $config_list{$config};
1524 }
1525 }
1526
1527 @start_list = @tophalf;
1528
1529 if ($#start_list == 0) {
1530 process_failed $start_list[0];
1531 return 1;
1532 }
1533
1534 # remove half the configs we are looking at and see if
1535 # they are good.
1536 $half = int($#start_list / 2);
1537 } while ($half > 0);
1538
1539 # we found a single config, try it again
1540 my @tophalf = @start_list[0 .. 0];
1541
1542 $ret = run_config_bisect_test $type;
1543 if ($ret) {
1544 process_passed %current_config;
1545 return 0;
1546 }
1547
1548 process_failed $start_list[0];
1549 return 1;
1550}
1551
1552sub config_bisect {
1553 my ($i) = @_;
1554
1555 my $start_config = $opt{"CONFIG_BISECT[$i]"};
1556
1557 my $tmpconfig = "$tmpdir/use_config";
1558
1559 # Make the file with the bad config and the min config
1560 if (defined($minconfig)) {
1561 # read the min config for things to ignore
1562 run_command "cp $minconfig $tmpconfig" or
1563 dodie "failed to copy $minconfig to $tmpconfig";
1564 } else {
1565 unlink $tmpconfig;
1566 }
1567
1568 # Add other configs
1569 if (defined($addconfig)) {
1570 run_command "cat $addconfig >> $tmpconfig" or
1571 dodie "failed to append $addconfig";
1572 }
1573
1574 my $defconfig = "";
1575 if (-f $tmpconfig) {
1576 $defconfig = "KCONFIG_ALLCONFIG=$tmpconfig";
1577 process_config_ignore $tmpconfig;
1578 }
1579
1580 # now process the start config
1581 run_command "cp $start_config $output_config" or
1582 dodie "failed to copy $start_config to $output_config";
1583
1584 # read directly what we want to check
1585 my %config_check;
1586 open (IN, $output_config)
1587 or dodie "faied to open $output_config";
1588
1589 while (<IN>) {
1590 if (/^((CONFIG\S*)=.*)/) {
1591 $config_check{$2} = $1;
1592 }
1593 }
1594 close(IN);
1595
1596 # Now run oldconfig with the minconfig (and addconfigs)
1597 run_command "$defconfig $make oldnoconfig" or
1598 dodie "failed make config oldconfig";
1599
1600 # check to see what we lost (or gained)
1601 open (IN, $output_config)
1602 or dodie "Failed to read $start_config";
1603
1604 my %removed_configs;
1605 my %added_configs;
1606
1607 while (<IN>) {
1608 if (/^((CONFIG\S*)=.*)/) {
1609 # save off all options
1610 $config_set{$2} = $1;
1611 if (defined($config_check{$2})) {
1612 if (defined($config_ignore{$2})) {
1613 $removed_configs{$2} = $1;
1614 } else {
1615 $config_list{$2} = $1;
1616 }
1617 } elsif (!defined($config_ignore{$2})) {
1618 $added_configs{$2} = $1;
1619 $config_list{$2} = $1;
1620 }
1621 }
1622 }
1623 close(IN);
1624
1625 my @confs = keys %removed_configs;
1626 if ($#confs >= 0) {
1627 doprint "Configs overridden by default configs and removed from check:\n";
1628 foreach my $config (@confs) {
1629 doprint " $config\n";
1630 }
1631 }
1632 @confs = keys %added_configs;
1633 if ($#confs >= 0) {
1634 doprint "Configs appearing in make oldconfig and added:\n";
1635 foreach my $config (@confs) {
1636 doprint " $config\n";
1637 }
1638 }
1639
1640 my %config_test;
1641 my $once = 0;
1642
1643 # Sometimes kconfig does weird things. We must make sure
1644 # that the config we autocreate has everything we need
1645 # to test, otherwise we may miss testing configs, or
1646 # may not be able to create a new config.
1647 # Here we create a config with everything set.
1648 create_config (keys %config_list);
1649 read_current_config \%config_test;
1650 foreach my $config (keys %config_list) {
1651 if (!defined($config_test{$config})) {
1652 if (!$once) {
1653 $once = 1;
1654 doprint "Configs not produced by kconfig (will not be checked):\n";
1655 }
1656 doprint " $config\n";
1657 delete $config_list{$config};
1658 }
1659 }
1660 my $ret;
1661 do {
1662 $ret = run_config_bisect;
1663 } while (!$ret);
1664
1665 return $ret if ($ret < 0);
5f9b6ced
SR
1666
1667 success $i;
1668}
1669
6c5ee0be
SR
1670sub patchcheck {
1671 my ($i) = @_;
1672
1673 die "PATCHCHECK_START[$i] not defined\n"
1674 if (!defined($opt{"PATCHCHECK_START[$i]"}));
1675 die "PATCHCHECK_TYPE[$i] not defined\n"
1676 if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
1677
1678 my $start = $opt{"PATCHCHECK_START[$i]"};
1679
1680 my $end = "HEAD";
1681 if (defined($opt{"PATCHCHECK_END[$i]"})) {
1682 $end = $opt{"PATCHCHECK_END[$i]"};
1683 }
1684
a57419b3
SR
1685 # Get the true sha1's since we can use things like HEAD~3
1686 $start = get_sha1($start);
1687 $end = get_sha1($end);
1688
6c5ee0be
SR
1689 my $type = $opt{"PATCHCHECK_TYPE[$i]"};
1690
1691 # Can't have a test without having a test to run
1692 if ($type eq "test" && !defined($run_test)) {
1693 $type = "boot";
1694 }
1695
1696 open (IN, "git log --pretty=oneline $end|") or
1697 dodie "could not get git list";
1698
1699 my @list;
1700
1701 while (<IN>) {
1702 chomp;
1703 $list[$#list+1] = $_;
1704 last if (/^$start/);
1705 }
1706 close(IN);
1707
1708 if ($list[$#list] !~ /^$start/) {
2b7d9b21 1709 fail "SHA1 $start not found";
6c5ee0be
SR
1710 }
1711
1712 # go backwards in the list
1713 @list = reverse @list;
1714
1715 my $save_clean = $noclean;
1716
1717 $in_patchcheck = 1;
1718 foreach my $item (@list) {
1719 my $sha1 = $item;
1720 $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
1721
1722 doprint "\nProcessing commit $item\n\n";
1723
1724 run_command "git checkout $sha1" or
1725 die "Failed to checkout $sha1";
1726
1727 # only clean on the first and last patch
1728 if ($item eq $list[0] ||
1729 $item eq $list[$#list]) {
1730 $noclean = $save_clean;
1731 } else {
1732 $noclean = 1;
1733 }
1734
1735 if (defined($minconfig)) {
2b7d9b21 1736 build "useconfig:$minconfig" or return 0;
6c5ee0be
SR
1737 } else {
1738 # ?? no config to use?
2b7d9b21 1739 build "oldconfig" or return 0;
6c5ee0be
SR
1740 }
1741
2b7d9b21 1742 check_buildlog $sha1 or return 0;
6c5ee0be
SR
1743
1744 next if ($type eq "build");
1745
1746 get_grub_index;
1747 get_version;
1748 install;
6c5ee0be 1749
7faafbd6
SR
1750 my $failed = 0;
1751
1752 start_monitor;
1753 monitor or $failed = 1;
1754
1755 if (!$failed && $type ne "boot"){
1756 do_run_test or $failed = 1;
1757 }
1758 end_monitor;
1759 return 0 if ($failed);
1760
6c5ee0be
SR
1761 }
1762 $in_patchcheck = 0;
1763 success $i;
2b7d9b21
SR
1764
1765 return 1;
6c5ee0be
SR
1766}
1767
8d1491ba
SR
1768$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n";
1769
1770if ($#ARGV == 0) {
1771 $ktest_config = $ARGV[0];
1772 if (! -f $ktest_config) {
1773 print "$ktest_config does not exist.\n";
1774 my $ans;
1775 for (;;) {
1776 print "Create it? [Y/n] ";
1777 $ans = <STDIN>;
1778 chomp $ans;
1779 if ($ans =~ /^\s*$/) {
1780 $ans = "y";
1781 }
1782 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
1783 print "Please answer either 'y' or 'n'.\n";
1784 }
1785 if ($ans !~ /^y$/i) {
1786 exit 0;
1787 }
1788 }
1789} else {
1790 $ktest_config = "ktest.conf";
1791}
1792
1793if (! -f $ktest_config) {
1794 open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
1795 print OUT << "EOF"
1796# Generated by ktest.pl
1797#
1798# Define each test with TEST_START
1799# The config options below it will override the defaults
1800TEST_START
1801
1802DEFAULTS
1803EOF
1804;
1805 close(OUT);
1806}
1807read_config $ktest_config;
1808
1809# Append any configs entered in manually to the config file.
1810my @new_configs = keys %entered_configs;
1811if ($#new_configs >= 0) {
1812 print "\nAppending entered in configs to $ktest_config\n";
1813 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
1814 foreach my $config (@new_configs) {
1815 print OUT "$config = $entered_configs{$config}\n";
1816 $opt{$config} = $entered_configs{$config};
1817 }
1818}
2545eb61 1819
2b7d9b21
SR
1820if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
1821 unlink $opt{"LOG_FILE"};
1822}
2545eb61 1823
2b7d9b21
SR
1824doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
1825
a57419b3
SR
1826for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
1827
1828 if (!$i) {
1829 doprint "DEFAULT OPTIONS:\n";
1830 } else {
1831 doprint "\nTEST $i OPTIONS";
1832 if (defined($repeat_tests{$i})) {
1833 $repeat = $repeat_tests{$i};
1834 doprint " ITERATE $repeat";
1835 }
1836 doprint "\n";
1837 }
1838
1839 foreach my $option (sort keys %opt) {
1840
1841 if ($option =~ /\[(\d+)\]$/) {
1842 next if ($i != $1);
1843 } else {
1844 next if ($i);
1845 }
1846
1847 doprint "$option = $opt{$option}\n";
1848 }
2b7d9b21 1849}
2545eb61 1850
a75fecec 1851sub set_test_option {
5a391fbf 1852 my ($name, $i) = @_;
2545eb61 1853
5a391fbf 1854 my $option = "$name\[$i\]";
5c42fc5b 1855
5a391fbf
SR
1856 if (defined($opt{$option})) {
1857 return $opt{$option};
5f9b6ced
SR
1858 }
1859
a57419b3
SR
1860 foreach my $test (keys %repeat_tests) {
1861 if ($i >= $test &&
1862 $i < $test + $repeat_tests{$test}) {
1863 $option = "$name\[$test\]";
1864 if (defined($opt{$option})) {
1865 return $opt{$option};
1866 }
1867 }
1868 }
1869
5a391fbf
SR
1870 if (defined($opt{$name})) {
1871 return $opt{$name};
2545eb61
SR
1872 }
1873
5a391fbf
SR
1874 return undef;
1875}
1876
1877# First we need to do is the builds
a75fecec
SR
1878for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
1879
576f627c
SR
1880 $iteration = $i;
1881
a75fecec
SR
1882 my $makecmd = set_test_option("MAKE_CMD", $i);
1883
1884 $machine = set_test_option("MACHINE", $i);
e48c5293 1885 $ssh_user = set_test_option("SSH_USER", $i);
a75fecec
SR
1886 $tmpdir = set_test_option("TMP_DIR", $i);
1887 $outputdir = set_test_option("OUTPUT_DIR", $i);
1888 $builddir = set_test_option("BUILD_DIR", $i);
1889 $test_type = set_test_option("TEST_TYPE", $i);
1890 $build_type = set_test_option("BUILD_TYPE", $i);
1891 $build_options = set_test_option("BUILD_OPTIONS", $i);
1892 $power_cycle = set_test_option("POWER_CYCLE", $i);
e48c5293 1893 $reboot = set_test_option("REBOOT", $i);
a75fecec
SR
1894 $noclean = set_test_option("BUILD_NOCLEAN", $i);
1895 $minconfig = set_test_option("MIN_CONFIG", $i);
1896 $run_test = set_test_option("TEST", $i);
1897 $addconfig = set_test_option("ADD_CONFIG", $i);
1898 $reboot_type = set_test_option("REBOOT_TYPE", $i);
1899 $grub_menu = set_test_option("GRUB_MENU", $i);
8b37ca8c 1900 $post_install = set_test_option("POST_INSTALL", $i);
a75fecec
SR
1901 $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
1902 $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
1903 $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
1904 $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
1905 $power_off = set_test_option("POWER_OFF", $i);
576f627c
SR
1906 $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
1907 $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
a75fecec
SR
1908 $sleep_time = set_test_option("SLEEP_TIME", $i);
1909 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
1910 $store_failures = set_test_option("STORE_FAILURES", $i);
1911 $timeout = set_test_option("TIMEOUT", $i);
1912 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
1913 $console = set_test_option("CONSOLE", $i);
1914 $success_line = set_test_option("SUCCESS_LINE", $i);
1c8a617a
SR
1915 $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
1916 $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
a75fecec 1917 $build_target = set_test_option("BUILD_TARGET", $i);
e48c5293
SR
1918 $ssh_exec = set_test_option("SSH_EXEC", $i);
1919 $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
a75fecec
SR
1920 $target_image = set_test_option("TARGET_IMAGE", $i);
1921 $localversion = set_test_option("LOCALVERSION", $i);
1922
1923 chdir $builddir || die "can't change directory to $builddir";
1924
1925 if (!-d $tmpdir) {
1926 mkpath($tmpdir) or
1927 die "can't create $tmpdir";
1928 }
1a5cfce3 1929
e48c5293
SR
1930 $ENV{"SSH_USER"} = $ssh_user;
1931 $ENV{"MACHINE"} = $machine;
1932
a75fecec
SR
1933 $target = "$ssh_user\@$machine";
1934
1935 $buildlog = "$tmpdir/buildlog-$machine";
1936 $dmesg = "$tmpdir/dmesg-$machine";
1937 $make = "$makecmd O=$outputdir";
51ad1dd1 1938 $output_config = "$outputdir/.config";
a75fecec
SR
1939
1940 if ($reboot_type eq "grub") {
576f627c 1941 dodie "GRUB_MENU not defined" if (!defined($grub_menu));
a75fecec 1942 } elsif (!defined($reboot_script)) {
576f627c 1943 dodie "REBOOT_SCRIPT not defined"
a75fecec
SR
1944 }
1945
1946 my $run_type = $build_type;
1947 if ($test_type eq "patchcheck") {
1948 $run_type = $opt{"PATCHCHECK_TYPE[$i]"};
1949 } elsif ($test_type eq "bisect") {
1950 $run_type = $opt{"BISECT_TYPE[$i]"};
0a05c769
SR
1951 } elsif ($test_type eq "config_bisect") {
1952 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
a75fecec
SR
1953 }
1954
1955 # mistake in config file?
1956 if (!defined($run_type)) {
1957 $run_type = "ERROR";
1958 }
5a391fbf 1959
2545eb61 1960 doprint "\n\n";
a75fecec 1961 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
7faafbd6
SR
1962
1963 unlink $dmesg;
1964 unlink $buildlog;
2545eb61 1965
2b7d9b21
SR
1966 if (!defined($minconfig)) {
1967 $minconfig = $addconfig;
1968
1969 } elsif (defined($addconfig)) {
9be2e6b5 1970 run_command "cat $addconfig $minconfig > $tmpdir/add_config" or
2b7d9b21 1971 dodie "Failed to create temp config";
9be2e6b5 1972 $minconfig = "$tmpdir/add_config";
2b7d9b21
SR
1973 }
1974
6c5ee0be
SR
1975 my $checkout = $opt{"CHECKOUT[$i]"};
1976 if (defined($checkout)) {
1977 run_command "git checkout $checkout" or
1978 die "failed to checkout $checkout";
1979 }
1980
a75fecec 1981 if ($test_type eq "bisect") {
5f9b6ced
SR
1982 bisect $i;
1983 next;
0a05c769
SR
1984 } elsif ($test_type eq "config_bisect") {
1985 config_bisect $i;
1986 next;
a75fecec 1987 } elsif ($test_type eq "patchcheck") {
6c5ee0be
SR
1988 patchcheck $i;
1989 next;
2545eb61 1990 }
2545eb61 1991
7faafbd6
SR
1992 if ($build_type ne "nobuild") {
1993 build $build_type or next;
2545eb61
SR
1994 }
1995
a75fecec
SR
1996 if ($test_type ne "build") {
1997 get_grub_index;
1998 get_version;
1999 install;
5a391fbf 2000
a75fecec
SR
2001 my $failed = 0;
2002 start_monitor;
2003 monitor or $failed = 1;;
2004
2005 if (!$failed && $test_type ne "boot" && defined($run_test)) {
2006 do_run_test or $failed = 1;
2007 }
2008 end_monitor;
2009 next if ($failed);
5a391fbf
SR
2010 }
2011
5f9b6ced 2012 success $i;
2545eb61
SR
2013}
2014
5c42fc5b 2015if ($opt{"POWEROFF_ON_SUCCESS"}) {
75c3fda7 2016 halt;
576f627c 2017} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
75c3fda7 2018 reboot;
5c42fc5b 2019}
75c3fda7 2020
e48c5293
SR
2021doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n";
2022
2545eb61 2023exit 0;
This page took 0.127706 seconds and 5 git commands to generate.