12545eb61SSteven Rostedt#!/usr/bin/perl -w 2d6ce2a0bSSteven Rostedt# 3d6ce2a0bSSteven Rostedt# Copywrite 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. 4d6ce2a0bSSteven Rostedt# Licensed under the terms of the GNU GPL License version 2 5d6ce2a0bSSteven Rostedt# 62545eb61SSteven Rostedt 72545eb61SSteven Rostedtuse strict; 82545eb61SSteven Rostedtuse IPC::Open2; 92545eb61SSteven Rostedtuse Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); 107faafbd6SSteven Rostedtuse File::Path qw(mkpath); 117faafbd6SSteven Rostedtuse File::Copy qw(cp); 122545eb61SSteven Rostedtuse FileHandle; 132545eb61SSteven Rostedt 14e48c5293SSteven Rostedtmy $VERSION = "0.2"; 15e48c5293SSteven Rostedt 16e48c5293SSteven Rostedt$#ARGV >= 0 || die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 172545eb61SSteven Rostedt 182545eb61SSteven Rostedt$| = 1; 192545eb61SSteven Rostedt 202545eb61SSteven Rostedtmy %opt; 21a57419b3SSteven Rostedtmy %repeat_tests; 22a57419b3SSteven Rostedtmy %repeats; 23a75fececSSteven Rostedtmy %default; 242545eb61SSteven Rostedt 252545eb61SSteven Rostedt#default opts 26a57419b3SSteven Rostedt$default{"NUM_TESTS"} = 1; 27a75fececSSteven Rostedt$default{"REBOOT_TYPE"} = "grub"; 28a75fececSSteven Rostedt$default{"TEST_TYPE"} = "test"; 29a75fececSSteven Rostedt$default{"BUILD_TYPE"} = "randconfig"; 30a75fececSSteven Rostedt$default{"MAKE_CMD"} = "make"; 31a75fececSSteven Rostedt$default{"TIMEOUT"} = 120; 32a57419b3SSteven Rostedt$default{"TMP_DIR"} = "/tmp/ktest"; 33a75fececSSteven Rostedt$default{"SLEEP_TIME"} = 60; # sleep time between tests 34a75fececSSteven Rostedt$default{"BUILD_NOCLEAN"} = 0; 35a75fececSSteven Rostedt$default{"REBOOT_ON_ERROR"} = 0; 36a75fececSSteven Rostedt$default{"POWEROFF_ON_ERROR"} = 0; 37a75fececSSteven Rostedt$default{"REBOOT_ON_SUCCESS"} = 1; 38a75fececSSteven Rostedt$default{"POWEROFF_ON_SUCCESS"} = 0; 39a75fececSSteven Rostedt$default{"BUILD_OPTIONS"} = ""; 40a75fececSSteven Rostedt$default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects 41a75fececSSteven Rostedt$default{"CLEAR_LOG"} = 0; 42a75fececSSteven Rostedt$default{"SUCCESS_LINE"} = "login:"; 43a75fececSSteven Rostedt$default{"BOOTED_TIMEOUT"} = 1; 44a75fececSSteven Rostedt$default{"DIE_ON_FAILURE"} = 1; 45e48c5293SSteven Rostedt$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND"; 46e48c5293SSteven Rostedt$default{"SCP_TO_TARGET"} = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE"; 47e48c5293SSteven Rostedt$default{"REBOOT"} = "ssh \$SSH_USER\@\$MACHINE reboot"; 481c8a617aSSteven Rostedt$default{"STOP_AFTER_SUCCESS"} = 10; 491c8a617aSSteven Rostedt$default{"STOP_AFTER_FAILURE"} = 60; 502545eb61SSteven Rostedt 512545eb61SSteven Rostedtmy $version; 52a75fececSSteven Rostedtmy $machine; 53e48c5293SSteven Rostedtmy $ssh_user; 54a75fececSSteven Rostedtmy $tmpdir; 55a75fececSSteven Rostedtmy $builddir; 56a75fececSSteven Rostedtmy $outputdir; 5751ad1dd1SSteven Rostedtmy $output_config; 58a75fececSSteven Rostedtmy $test_type; 597faafbd6SSteven Rostedtmy $build_type; 60a75fececSSteven Rostedtmy $build_options; 61a75fececSSteven Rostedtmy $reboot_type; 62a75fececSSteven Rostedtmy $reboot_script; 63a75fececSSteven Rostedtmy $power_cycle; 64e48c5293SSteven Rostedtmy $reboot; 65a75fececSSteven Rostedtmy $reboot_on_error; 66a75fececSSteven Rostedtmy $poweroff_on_error; 67a75fececSSteven Rostedtmy $die_on_failure; 68576f627cSSteven Rostedtmy $powercycle_after_reboot; 69576f627cSSteven Rostedtmy $poweroff_after_halt; 70e48c5293SSteven Rostedtmy $ssh_exec; 71e48c5293SSteven Rostedtmy $scp_to_target; 72a75fececSSteven Rostedtmy $power_off; 73a75fececSSteven Rostedtmy $grub_menu; 742545eb61SSteven Rostedtmy $grub_number; 752545eb61SSteven Rostedtmy $target; 762545eb61SSteven Rostedtmy $make; 778b37ca8cSSteven Rostedtmy $post_install; 785c42fc5bSSteven Rostedtmy $noclean; 795f9b6cedSSteven Rostedtmy $minconfig; 802b7d9b21SSteven Rostedtmy $addconfig; 815f9b6cedSSteven Rostedtmy $in_bisect = 0; 825f9b6cedSSteven Rostedtmy $bisect_bad = ""; 83d6ce2a0bSSteven Rostedtmy $reverse_bisect; 846c5ee0beSSteven Rostedtmy $in_patchcheck = 0; 855a391fbfSSteven Rostedtmy $run_test; 866c5ee0beSSteven Rostedtmy $redirect; 877faafbd6SSteven Rostedtmy $buildlog; 887faafbd6SSteven Rostedtmy $dmesg; 897faafbd6SSteven Rostedtmy $monitor_fp; 907faafbd6SSteven Rostedtmy $monitor_pid; 917faafbd6SSteven Rostedtmy $monitor_cnt = 0; 92a75fececSSteven Rostedtmy $sleep_time; 93a75fececSSteven Rostedtmy $bisect_sleep_time; 94a75fececSSteven Rostedtmy $store_failures; 95a75fececSSteven Rostedtmy $timeout; 96a75fececSSteven Rostedtmy $booted_timeout; 97a75fececSSteven Rostedtmy $console; 98a75fececSSteven Rostedtmy $success_line; 991c8a617aSSteven Rostedtmy $stop_after_success; 1001c8a617aSSteven Rostedtmy $stop_after_failure; 101a75fececSSteven Rostedtmy $build_target; 102a75fececSSteven Rostedtmy $target_image; 103a75fececSSteven Rostedtmy $localversion; 104576f627cSSteven Rostedtmy $iteration = 0; 105e48c5293SSteven Rostedtmy $successes = 0; 1062545eb61SSteven Rostedt 107a57419b3SSteven Rostedtsub set_value { 108a57419b3SSteven Rostedt my ($lvalue, $rvalue) = @_; 1092545eb61SSteven Rostedt 110a75fececSSteven Rostedt if (defined($opt{$lvalue})) { 111a75fececSSteven Rostedt die "Error: Option $lvalue defined more than once!\n"; 112a75fececSSteven Rostedt } 11321a9679fSSteven Rostedt if ($rvalue =~ /^\s*$/) { 11421a9679fSSteven Rostedt delete $opt{$lvalue}; 11521a9679fSSteven Rostedt } else { 11621a9679fSSteven Rostedt $opt{$lvalue} = $rvalue; 11721a9679fSSteven Rostedt } 1182545eb61SSteven Rostedt} 119a57419b3SSteven Rostedt 120a57419b3SSteven Rostedtsub read_config { 121a57419b3SSteven Rostedt my ($config) = @_; 122a57419b3SSteven Rostedt 123a57419b3SSteven Rostedt open(IN, $config) || die "can't read file $config"; 124a57419b3SSteven Rostedt 125a57419b3SSteven Rostedt my $name = $config; 126a57419b3SSteven Rostedt $name =~ s,.*/(.*),$1,; 127a57419b3SSteven Rostedt 128a57419b3SSteven Rostedt my $test_num = 0; 129a57419b3SSteven Rostedt my $default = 1; 130a57419b3SSteven Rostedt my $repeat = 1; 131a57419b3SSteven Rostedt my $num_tests_set = 0; 132a57419b3SSteven Rostedt my $skip = 0; 133a57419b3SSteven Rostedt my $rest; 134a57419b3SSteven Rostedt 135a57419b3SSteven Rostedt while (<IN>) { 136a57419b3SSteven Rostedt 137a57419b3SSteven Rostedt # ignore blank lines and comments 138a57419b3SSteven Rostedt next if (/^\s*$/ || /\s*\#/); 139a57419b3SSteven Rostedt 140a57419b3SSteven Rostedt if (/^\s*TEST_START(.*)/) { 141a57419b3SSteven Rostedt 142a57419b3SSteven Rostedt $rest = $1; 143a57419b3SSteven Rostedt 144a57419b3SSteven Rostedt if ($num_tests_set) { 145a57419b3SSteven Rostedt die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 146a57419b3SSteven Rostedt } 147a57419b3SSteven Rostedt 148a57419b3SSteven Rostedt my $old_test_num = $test_num; 149e48c5293SSteven Rostedt my $old_repeat = $repeat; 150a57419b3SSteven Rostedt 151a57419b3SSteven Rostedt $test_num += $repeat; 152a57419b3SSteven Rostedt $default = 0; 153a57419b3SSteven Rostedt $repeat = 1; 154a57419b3SSteven Rostedt 155a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 156a57419b3SSteven Rostedt $rest = $1; 157a57419b3SSteven Rostedt $skip = 1; 158a57419b3SSteven Rostedt } else { 159a57419b3SSteven Rostedt $skip = 0; 160a57419b3SSteven Rostedt } 161a57419b3SSteven Rostedt 162a57419b3SSteven Rostedt if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) { 163a57419b3SSteven Rostedt $repeat = $1; 164a57419b3SSteven Rostedt $rest = $2; 165a57419b3SSteven Rostedt $repeat_tests{"$test_num"} = $repeat; 166a57419b3SSteven Rostedt } 167a57419b3SSteven Rostedt 168a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 169a57419b3SSteven Rostedt $rest = $1; 170a57419b3SSteven Rostedt $skip = 1; 171a57419b3SSteven Rostedt } 172a57419b3SSteven Rostedt 173a57419b3SSteven Rostedt if ($rest !~ /^\s*$/) { 174a57419b3SSteven Rostedt die "$name: $.: Gargbage found after TEST_START\n$_"; 175a57419b3SSteven Rostedt } 176a57419b3SSteven Rostedt 177a57419b3SSteven Rostedt if ($skip) { 178a57419b3SSteven Rostedt $test_num = $old_test_num; 179e48c5293SSteven Rostedt $repeat = $old_repeat; 180a57419b3SSteven Rostedt } 181a57419b3SSteven Rostedt 182a57419b3SSteven Rostedt } elsif (/^\s*DEFAULTS(.*)$/) { 183a57419b3SSteven Rostedt $default = 1; 184a57419b3SSteven Rostedt 185a57419b3SSteven Rostedt $rest = $1; 186a57419b3SSteven Rostedt 187a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 188a57419b3SSteven Rostedt $rest = $1; 189a57419b3SSteven Rostedt $skip = 1; 190a57419b3SSteven Rostedt } else { 191a57419b3SSteven Rostedt $skip = 0; 192a57419b3SSteven Rostedt } 193a57419b3SSteven Rostedt 194a57419b3SSteven Rostedt if ($rest !~ /^\s*$/) { 195a57419b3SSteven Rostedt die "$name: $.: Gargbage found after DEFAULTS\n$_"; 196a57419b3SSteven Rostedt } 197a57419b3SSteven Rostedt 198a57419b3SSteven Rostedt } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 199a57419b3SSteven Rostedt 200a57419b3SSteven Rostedt next if ($skip); 201a57419b3SSteven Rostedt 202a57419b3SSteven Rostedt my $lvalue = $1; 203a57419b3SSteven Rostedt my $rvalue = $2; 204a57419b3SSteven Rostedt 205a57419b3SSteven Rostedt if (!$default && 206a57419b3SSteven Rostedt ($lvalue eq "NUM_TESTS" || 207a57419b3SSteven Rostedt $lvalue eq "LOG_FILE" || 208a57419b3SSteven Rostedt $lvalue eq "CLEAR_LOG")) { 209a57419b3SSteven Rostedt die "$name: $.: $lvalue must be set in DEFAULTS section\n"; 210a57419b3SSteven Rostedt } 211a57419b3SSteven Rostedt 212a57419b3SSteven Rostedt if ($lvalue eq "NUM_TESTS") { 213a57419b3SSteven Rostedt if ($test_num) { 214a57419b3SSteven Rostedt die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 215a57419b3SSteven Rostedt } 216a57419b3SSteven Rostedt if (!$default) { 217a57419b3SSteven Rostedt die "$name: $.: NUM_TESTS must be set in default section\n"; 218a57419b3SSteven Rostedt } 219a57419b3SSteven Rostedt $num_tests_set = 1; 220a57419b3SSteven Rostedt } 221a57419b3SSteven Rostedt 222a57419b3SSteven Rostedt if ($default || $lvalue =~ /\[\d+\]$/) { 223a57419b3SSteven Rostedt set_value($lvalue, $rvalue); 224a57419b3SSteven Rostedt } else { 225a57419b3SSteven Rostedt my $val = "$lvalue\[$test_num\]"; 226a57419b3SSteven Rostedt set_value($val, $rvalue); 227a57419b3SSteven Rostedt 228a57419b3SSteven Rostedt if ($repeat > 1) { 229a57419b3SSteven Rostedt $repeats{$val} = $repeat; 230a57419b3SSteven Rostedt } 231a57419b3SSteven Rostedt } 232a57419b3SSteven Rostedt } else { 233a57419b3SSteven Rostedt die "$name: $.: Garbage found in config\n$_"; 234a57419b3SSteven Rostedt } 2352545eb61SSteven Rostedt } 2362545eb61SSteven Rostedt 2372545eb61SSteven Rostedt close(IN); 238a75fececSSteven Rostedt 239a57419b3SSteven Rostedt if ($test_num) { 240a57419b3SSteven Rostedt $test_num += $repeat - 1; 241a57419b3SSteven Rostedt $opt{"NUM_TESTS"} = $test_num; 242a57419b3SSteven Rostedt } 243a57419b3SSteven Rostedt 244a75fececSSteven Rostedt # set any defaults 245a75fececSSteven Rostedt 246a75fececSSteven Rostedt foreach my $default (keys %default) { 247a75fececSSteven Rostedt if (!defined($opt{$default})) { 248a75fececSSteven Rostedt $opt{$default} = $default{$default}; 249a75fececSSteven Rostedt } 250a75fececSSteven Rostedt } 2512545eb61SSteven Rostedt} 2522545eb61SSteven Rostedt 253d1e2f22aSSteven Rostedtsub _logit { 2542545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 2552545eb61SSteven Rostedt open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 2562545eb61SSteven Rostedt print OUT @_; 2572545eb61SSteven Rostedt close(OUT); 2582545eb61SSteven Rostedt } 2592545eb61SSteven Rostedt} 2602545eb61SSteven Rostedt 261d1e2f22aSSteven Rostedtsub logit { 262d1e2f22aSSteven Rostedt if (defined($opt{"LOG_FILE"})) { 263d1e2f22aSSteven Rostedt _logit @_; 264d1e2f22aSSteven Rostedt } else { 265d1e2f22aSSteven Rostedt print @_; 266d1e2f22aSSteven Rostedt } 267d1e2f22aSSteven Rostedt} 268d1e2f22aSSteven Rostedt 2695f9b6cedSSteven Rostedtsub doprint { 2705f9b6cedSSteven Rostedt print @_; 271d1e2f22aSSteven Rostedt _logit @_; 2725f9b6cedSSteven Rostedt} 2735f9b6cedSSteven Rostedt 2747faafbd6SSteven Rostedtsub run_command; 2757faafbd6SSteven Rostedt 2767faafbd6SSteven Rostedtsub reboot { 2777faafbd6SSteven Rostedt # try to reboot normally 278e48c5293SSteven Rostedt if (run_command $reboot) { 279576f627cSSteven Rostedt if (defined($powercycle_after_reboot)) { 280576f627cSSteven Rostedt sleep $powercycle_after_reboot; 281576f627cSSteven Rostedt run_command "$power_cycle"; 282576f627cSSteven Rostedt } 283576f627cSSteven Rostedt } else { 2847faafbd6SSteven Rostedt # nope? power cycle it. 285a75fececSSteven Rostedt run_command "$power_cycle"; 2867faafbd6SSteven Rostedt } 2877faafbd6SSteven Rostedt} 2887faafbd6SSteven Rostedt 289576f627cSSteven Rostedtsub do_not_reboot { 290576f627cSSteven Rostedt my $i = $iteration; 291576f627cSSteven Rostedt 292576f627cSSteven Rostedt return $test_type eq "build" || 293576f627cSSteven Rostedt ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 294576f627cSSteven Rostedt ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 295576f627cSSteven Rostedt} 296576f627cSSteven Rostedt 2975c42fc5bSSteven Rostedtsub dodie { 2985a391fbfSSteven Rostedt doprint "CRITICAL FAILURE... ", @_, "\n"; 2995c42fc5bSSteven Rostedt 300576f627cSSteven Rostedt my $i = $iteration; 301576f627cSSteven Rostedt 302576f627cSSteven Rostedt if ($reboot_on_error && !do_not_reboot) { 303576f627cSSteven Rostedt 30475c3fda7SSteven Rostedt doprint "REBOOTING\n"; 3057faafbd6SSteven Rostedt reboot; 30675c3fda7SSteven Rostedt 307a75fececSSteven Rostedt } elsif ($poweroff_on_error && defined($power_off)) { 3085c42fc5bSSteven Rostedt doprint "POWERING OFF\n"; 309a75fececSSteven Rostedt `$power_off`; 3105c42fc5bSSteven Rostedt } 31175c3fda7SSteven Rostedt 312576f627cSSteven Rostedt die @_, "\n"; 3135c42fc5bSSteven Rostedt} 3145c42fc5bSSteven Rostedt 3157faafbd6SSteven Rostedtsub open_console { 3167faafbd6SSteven Rostedt my ($fp) = @_; 3177faafbd6SSteven Rostedt 3187faafbd6SSteven Rostedt my $flags; 3197faafbd6SSteven Rostedt 320a75fececSSteven Rostedt my $pid = open($fp, "$console|") or 321a75fececSSteven Rostedt dodie "Can't open console $console"; 3227faafbd6SSteven Rostedt 3237faafbd6SSteven Rostedt $flags = fcntl($fp, F_GETFL, 0) or 324576f627cSSteven Rostedt dodie "Can't get flags for the socket: $!"; 3257faafbd6SSteven Rostedt $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 326576f627cSSteven Rostedt dodie "Can't set flags for the socket: $!"; 3277faafbd6SSteven Rostedt 3287faafbd6SSteven Rostedt return $pid; 3297faafbd6SSteven Rostedt} 3307faafbd6SSteven Rostedt 3317faafbd6SSteven Rostedtsub close_console { 3327faafbd6SSteven Rostedt my ($fp, $pid) = @_; 3337faafbd6SSteven Rostedt 3347faafbd6SSteven Rostedt doprint "kill child process $pid\n"; 3357faafbd6SSteven Rostedt kill 2, $pid; 3367faafbd6SSteven Rostedt 3377faafbd6SSteven Rostedt print "closing!\n"; 3387faafbd6SSteven Rostedt close($fp); 3397faafbd6SSteven Rostedt} 3407faafbd6SSteven Rostedt 3417faafbd6SSteven Rostedtsub start_monitor { 3427faafbd6SSteven Rostedt if ($monitor_cnt++) { 3437faafbd6SSteven Rostedt return; 3447faafbd6SSteven Rostedt } 3457faafbd6SSteven Rostedt $monitor_fp = \*MONFD; 3467faafbd6SSteven Rostedt $monitor_pid = open_console $monitor_fp; 347a75fececSSteven Rostedt 348a75fececSSteven Rostedt return; 349a75fececSSteven Rostedt 350a75fececSSteven Rostedt open(MONFD, "Stop perl from warning about single use of MONFD"); 3517faafbd6SSteven Rostedt} 3527faafbd6SSteven Rostedt 3537faafbd6SSteven Rostedtsub end_monitor { 3547faafbd6SSteven Rostedt if (--$monitor_cnt) { 3557faafbd6SSteven Rostedt return; 3567faafbd6SSteven Rostedt } 3577faafbd6SSteven Rostedt close_console($monitor_fp, $monitor_pid); 3587faafbd6SSteven Rostedt} 3597faafbd6SSteven Rostedt 3607faafbd6SSteven Rostedtsub wait_for_monitor { 3617faafbd6SSteven Rostedt my ($time) = @_; 3627faafbd6SSteven Rostedt my $line; 3637faafbd6SSteven Rostedt 364a75fececSSteven Rostedt doprint "** Wait for monitor to settle down **\n"; 3657faafbd6SSteven Rostedt 3667faafbd6SSteven Rostedt # read the monitor and wait for the system to calm down 3677faafbd6SSteven Rostedt do { 3687faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 369a75fececSSteven Rostedt print "$line" if (defined($line)); 3707faafbd6SSteven Rostedt } while (defined($line)); 371a75fececSSteven Rostedt print "** Monitor flushed **\n"; 3727faafbd6SSteven Rostedt} 3737faafbd6SSteven Rostedt 3742b7d9b21SSteven Rostedtsub fail { 3752b7d9b21SSteven Rostedt 376a75fececSSteven Rostedt if ($die_on_failure) { 3772b7d9b21SSteven Rostedt dodie @_; 3782b7d9b21SSteven Rostedt } 3792b7d9b21SSteven Rostedt 380a75fececSSteven Rostedt doprint "FAILED\n"; 3817faafbd6SSteven Rostedt 382576f627cSSteven Rostedt my $i = $iteration; 383576f627cSSteven Rostedt 384a75fececSSteven Rostedt # no need to reboot for just building. 385576f627cSSteven Rostedt if (!do_not_reboot) { 3867faafbd6SSteven Rostedt doprint "REBOOTING\n"; 3877faafbd6SSteven Rostedt reboot; 3887faafbd6SSteven Rostedt start_monitor; 389a75fececSSteven Rostedt wait_for_monitor $sleep_time; 3907faafbd6SSteven Rostedt end_monitor; 391a75fececSSteven Rostedt } 3927faafbd6SSteven Rostedt 393576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 394576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 3957a849cd9SSteven Rostedt doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n"; 396576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 397576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 398a75fececSSteven Rostedt 399a75fececSSteven Rostedt return 1 if (!defined($store_failures)); 4007faafbd6SSteven Rostedt 4017faafbd6SSteven Rostedt my @t = localtime; 4027faafbd6SSteven Rostedt my $date = sprintf "%04d%02d%02d%02d%02d%02d", 4037faafbd6SSteven Rostedt 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 4047faafbd6SSteven Rostedt 405cccae1a6SSteven Rostedt my $type = $build_type; 406cccae1a6SSteven Rostedt if ($type =~ /useconfig/) { 407cccae1a6SSteven Rostedt $type = "useconfig"; 408cccae1a6SSteven Rostedt } 409cccae1a6SSteven Rostedt 410cccae1a6SSteven Rostedt my $dir = "$machine-$test_type-$type-fail-$date"; 411a75fececSSteven Rostedt my $faildir = "$store_failures/$dir"; 4127faafbd6SSteven Rostedt 4137faafbd6SSteven Rostedt if (!-d $faildir) { 4147faafbd6SSteven Rostedt mkpath($faildir) or 415a75fececSSteven Rostedt die "can't create $faildir"; 4167faafbd6SSteven Rostedt } 41751ad1dd1SSteven Rostedt if (-f "$output_config") { 41851ad1dd1SSteven Rostedt cp "$output_config", "$faildir/config" or 4197faafbd6SSteven Rostedt die "failed to copy .config"; 4207faafbd6SSteven Rostedt } 4217faafbd6SSteven Rostedt if (-f $buildlog) { 4227faafbd6SSteven Rostedt cp $buildlog, "$faildir/buildlog" or 4237faafbd6SSteven Rostedt die "failed to move $buildlog"; 4247faafbd6SSteven Rostedt } 4257faafbd6SSteven Rostedt if (-f $dmesg) { 4267faafbd6SSteven Rostedt cp $dmesg, "$faildir/dmesg" or 4277faafbd6SSteven Rostedt die "failed to move $dmesg"; 4287faafbd6SSteven Rostedt } 4297faafbd6SSteven Rostedt 4307faafbd6SSteven Rostedt doprint "*** Saved info to $faildir ***\n"; 4317faafbd6SSteven Rostedt 4322b7d9b21SSteven Rostedt return 1; 4332b7d9b21SSteven Rostedt} 4342b7d9b21SSteven Rostedt 4352545eb61SSteven Rostedtsub run_command { 4362545eb61SSteven Rostedt my ($command) = @_; 437d6ce2a0bSSteven Rostedt my $dolog = 0; 438d6ce2a0bSSteven Rostedt my $dord = 0; 439d6ce2a0bSSteven Rostedt my $pid; 440d6ce2a0bSSteven Rostedt 441e48c5293SSteven Rostedt $command =~ s/\$SSH_USER/$ssh_user/g; 442e48c5293SSteven Rostedt $command =~ s/\$MACHINE/$machine/g; 443e48c5293SSteven Rostedt 444d6ce2a0bSSteven Rostedt doprint("$command ... "); 445d6ce2a0bSSteven Rostedt 446d6ce2a0bSSteven Rostedt $pid = open(CMD, "$command 2>&1 |") or 4472b7d9b21SSteven Rostedt (fail "unable to exec $command" and return 0); 4482545eb61SSteven Rostedt 4492545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 450d6ce2a0bSSteven Rostedt open(LOG, ">>$opt{LOG_FILE}") or 451d6ce2a0bSSteven Rostedt dodie "failed to write to log"; 452d6ce2a0bSSteven Rostedt $dolog = 1; 4536c5ee0beSSteven Rostedt } 4546c5ee0beSSteven Rostedt 4556c5ee0beSSteven Rostedt if (defined($redirect)) { 456d6ce2a0bSSteven Rostedt open (RD, ">$redirect") or 457d6ce2a0bSSteven Rostedt dodie "failed to write to redirect $redirect"; 458d6ce2a0bSSteven Rostedt $dord = 1; 4592545eb61SSteven Rostedt } 4602545eb61SSteven Rostedt 461d6ce2a0bSSteven Rostedt while (<CMD>) { 462d6ce2a0bSSteven Rostedt print LOG if ($dolog); 463d6ce2a0bSSteven Rostedt print RD if ($dord); 464d6ce2a0bSSteven Rostedt } 4652545eb61SSteven Rostedt 466d6ce2a0bSSteven Rostedt waitpid($pid, 0); 4672545eb61SSteven Rostedt my $failed = $?; 4682545eb61SSteven Rostedt 469d6ce2a0bSSteven Rostedt close(CMD); 470d6ce2a0bSSteven Rostedt close(LOG) if ($dolog); 471d6ce2a0bSSteven Rostedt close(RD) if ($dord); 472d6ce2a0bSSteven Rostedt 4732545eb61SSteven Rostedt if ($failed) { 4742545eb61SSteven Rostedt doprint "FAILED!\n"; 4752545eb61SSteven Rostedt } else { 4762545eb61SSteven Rostedt doprint "SUCCESS\n"; 4772545eb61SSteven Rostedt } 4782545eb61SSteven Rostedt 4795f9b6cedSSteven Rostedt return !$failed; 4805f9b6cedSSteven Rostedt} 4815f9b6cedSSteven Rostedt 482e48c5293SSteven Rostedtsub run_ssh { 483e48c5293SSteven Rostedt my ($cmd) = @_; 484e48c5293SSteven Rostedt my $cp_exec = $ssh_exec; 485e48c5293SSteven Rostedt 486e48c5293SSteven Rostedt $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 487e48c5293SSteven Rostedt return run_command "$cp_exec"; 488e48c5293SSteven Rostedt} 489e48c5293SSteven Rostedt 490e48c5293SSteven Rostedtsub run_scp { 491e48c5293SSteven Rostedt my ($src, $dst) = @_; 492e48c5293SSteven Rostedt my $cp_scp = $scp_to_target; 493e48c5293SSteven Rostedt 494e48c5293SSteven Rostedt $cp_scp =~ s/\$SRC_FILE/$src/g; 495e48c5293SSteven Rostedt $cp_scp =~ s/\$DST_FILE/$dst/g; 496e48c5293SSteven Rostedt 497e48c5293SSteven Rostedt return run_command "$cp_scp"; 498e48c5293SSteven Rostedt} 499e48c5293SSteven Rostedt 5005f9b6cedSSteven Rostedtsub get_grub_index { 5015f9b6cedSSteven Rostedt 502a75fececSSteven Rostedt if ($reboot_type ne "grub") { 503a75fececSSteven Rostedt return; 504a75fececSSteven Rostedt } 5055a391fbfSSteven Rostedt return if (defined($grub_number)); 5065f9b6cedSSteven Rostedt 5075f9b6cedSSteven Rostedt doprint "Find grub menu ... "; 5085f9b6cedSSteven Rostedt $grub_number = -1; 509e48c5293SSteven Rostedt 510e48c5293SSteven Rostedt my $ssh_grub = $ssh_exec; 511e48c5293SSteven Rostedt $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 512e48c5293SSteven Rostedt 513e48c5293SSteven Rostedt open(IN, "$ssh_grub |") 5145f9b6cedSSteven Rostedt or die "unable to get menu.lst"; 515e48c5293SSteven Rostedt 5165f9b6cedSSteven Rostedt while (<IN>) { 517a75fececSSteven Rostedt if (/^\s*title\s+$grub_menu\s*$/) { 5185f9b6cedSSteven Rostedt $grub_number++; 5195f9b6cedSSteven Rostedt last; 5205f9b6cedSSteven Rostedt } elsif (/^\s*title\s/) { 5215f9b6cedSSteven Rostedt $grub_number++; 5225f9b6cedSSteven Rostedt } 5235f9b6cedSSteven Rostedt } 5245f9b6cedSSteven Rostedt close(IN); 5255f9b6cedSSteven Rostedt 526a75fececSSteven Rostedt die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 5275f9b6cedSSteven Rostedt if ($grub_number < 0); 5285f9b6cedSSteven Rostedt doprint "$grub_number\n"; 5292545eb61SSteven Rostedt} 5302545eb61SSteven Rostedt 5312545eb61SSteven Rostedtsub wait_for_input 5322545eb61SSteven Rostedt{ 5332545eb61SSteven Rostedt my ($fp, $time) = @_; 5342545eb61SSteven Rostedt my $rin; 5352545eb61SSteven Rostedt my $ready; 5362545eb61SSteven Rostedt my $line; 5372545eb61SSteven Rostedt my $ch; 5382545eb61SSteven Rostedt 5392545eb61SSteven Rostedt if (!defined($time)) { 5402545eb61SSteven Rostedt $time = $timeout; 5412545eb61SSteven Rostedt } 5422545eb61SSteven Rostedt 5432545eb61SSteven Rostedt $rin = ''; 5442545eb61SSteven Rostedt vec($rin, fileno($fp), 1) = 1; 5452545eb61SSteven Rostedt $ready = select($rin, undef, undef, $time); 5462545eb61SSteven Rostedt 5472545eb61SSteven Rostedt $line = ""; 5482545eb61SSteven Rostedt 5492545eb61SSteven Rostedt # try to read one char at a time 5502545eb61SSteven Rostedt while (sysread $fp, $ch, 1) { 5512545eb61SSteven Rostedt $line .= $ch; 5522545eb61SSteven Rostedt last if ($ch eq "\n"); 5532545eb61SSteven Rostedt } 5542545eb61SSteven Rostedt 5552545eb61SSteven Rostedt if (!length($line)) { 5562545eb61SSteven Rostedt return undef; 5572545eb61SSteven Rostedt } 5582545eb61SSteven Rostedt 5592545eb61SSteven Rostedt return $line; 5602545eb61SSteven Rostedt} 5612545eb61SSteven Rostedt 56275c3fda7SSteven Rostedtsub reboot_to { 563a75fececSSteven Rostedt if ($reboot_type eq "grub") { 564eec56460SSteven Rostedt run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; 565a75fececSSteven Rostedt return; 566a75fececSSteven Rostedt } 567a75fececSSteven Rostedt 568a75fececSSteven Rostedt run_command "$reboot_script"; 5692545eb61SSteven Rostedt} 5702545eb61SSteven Rostedt 571a57419b3SSteven Rostedtsub get_sha1 { 572a57419b3SSteven Rostedt my ($commit) = @_; 573a57419b3SSteven Rostedt 574a57419b3SSteven Rostedt doprint "git rev-list --max-count=1 $commit ... "; 575a57419b3SSteven Rostedt my $sha1 = `git rev-list --max-count=1 $commit`; 576a57419b3SSteven Rostedt my $ret = $?; 577a57419b3SSteven Rostedt 578a57419b3SSteven Rostedt logit $sha1; 579a57419b3SSteven Rostedt 580a57419b3SSteven Rostedt if ($ret) { 581a57419b3SSteven Rostedt doprint "FAILED\n"; 582a57419b3SSteven Rostedt dodie "Failed to get git $commit"; 583a57419b3SSteven Rostedt } 584a57419b3SSteven Rostedt 585a57419b3SSteven Rostedt print "SUCCESS\n"; 586a57419b3SSteven Rostedt 587a57419b3SSteven Rostedt chomp $sha1; 588a57419b3SSteven Rostedt 589a57419b3SSteven Rostedt return $sha1; 590a57419b3SSteven Rostedt} 591a57419b3SSteven Rostedt 5925a391fbfSSteven Rostedtsub monitor { 5932545eb61SSteven Rostedt my $booted = 0; 5942545eb61SSteven Rostedt my $bug = 0; 5955c42fc5bSSteven Rostedt my $skip_call_trace = 0; 5962b7d9b21SSteven Rostedt my $loops; 5972545eb61SSteven Rostedt 5987faafbd6SSteven Rostedt wait_for_monitor 5; 5992545eb61SSteven Rostedt 6002545eb61SSteven Rostedt my $line; 6012545eb61SSteven Rostedt my $full_line = ""; 6022545eb61SSteven Rostedt 6037faafbd6SSteven Rostedt open(DMESG, "> $dmesg") or 6047faafbd6SSteven Rostedt die "unable to write to $dmesg"; 6052545eb61SSteven Rostedt 60675c3fda7SSteven Rostedt reboot_to; 6072545eb61SSteven Rostedt 6081c8a617aSSteven Rostedt my $success_start; 6091c8a617aSSteven Rostedt my $failure_start; 6101c8a617aSSteven Rostedt 6112545eb61SSteven Rostedt for (;;) { 6122545eb61SSteven Rostedt 6132b7d9b21SSteven Rostedt if ($booted) { 614a75fececSSteven Rostedt $line = wait_for_input($monitor_fp, $booted_timeout); 6152b7d9b21SSteven Rostedt } else { 6167faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp); 6172b7d9b21SSteven Rostedt } 6182545eb61SSteven Rostedt 6192545eb61SSteven Rostedt last if (!defined($line)); 6202545eb61SSteven Rostedt 6212545eb61SSteven Rostedt doprint $line; 6227faafbd6SSteven Rostedt print DMESG $line; 6232545eb61SSteven Rostedt 6242545eb61SSteven Rostedt # we are not guaranteed to get a full line 6252545eb61SSteven Rostedt $full_line .= $line; 6262545eb61SSteven Rostedt 627a75fececSSteven Rostedt if ($full_line =~ /$success_line/) { 6282545eb61SSteven Rostedt $booted = 1; 6291c8a617aSSteven Rostedt $success_start = time; 6301c8a617aSSteven Rostedt } 6311c8a617aSSteven Rostedt 6321c8a617aSSteven Rostedt if ($booted && defined($stop_after_success) && 6331c8a617aSSteven Rostedt $stop_after_success >= 0) { 6341c8a617aSSteven Rostedt my $now = time; 6351c8a617aSSteven Rostedt if ($now - $success_start >= $stop_after_success) { 6361c8a617aSSteven Rostedt doprint "Test forced to stop after $stop_after_success seconds after success\n"; 6371c8a617aSSteven Rostedt last; 6381c8a617aSSteven Rostedt } 6392545eb61SSteven Rostedt } 6402545eb61SSteven Rostedt 6415c42fc5bSSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 6425c42fc5bSSteven Rostedt $skip_call_trace = 1; 6435c42fc5bSSteven Rostedt } 6445c42fc5bSSteven Rostedt 6452545eb61SSteven Rostedt if ($full_line =~ /call trace:/i) { 6461c8a617aSSteven Rostedt if (!$skip_call_trace) { 6471c8a617aSSteven Rostedt $bug = 1; 6481c8a617aSSteven Rostedt $failure_start = time; 6491c8a617aSSteven Rostedt } 6501c8a617aSSteven Rostedt } 6511c8a617aSSteven Rostedt 6521c8a617aSSteven Rostedt if ($bug && defined($stop_after_failure) && 6531c8a617aSSteven Rostedt $stop_after_failure >= 0) { 6541c8a617aSSteven Rostedt my $now = time; 6551c8a617aSSteven Rostedt if ($now - $failure_start >= $stop_after_failure) { 6561c8a617aSSteven Rostedt doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; 6571c8a617aSSteven Rostedt last; 6581c8a617aSSteven Rostedt } 6595c42fc5bSSteven Rostedt } 6605c42fc5bSSteven Rostedt 6615c42fc5bSSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 6625c42fc5bSSteven Rostedt $skip_call_trace = 0; 6635c42fc5bSSteven Rostedt } 6645c42fc5bSSteven Rostedt 6655c42fc5bSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 6662545eb61SSteven Rostedt $bug = 1; 6672545eb61SSteven Rostedt } 6682545eb61SSteven Rostedt 6692545eb61SSteven Rostedt if ($line =~ /\n/) { 6702545eb61SSteven Rostedt $full_line = ""; 6712545eb61SSteven Rostedt } 6722545eb61SSteven Rostedt } 6732545eb61SSteven Rostedt 6747faafbd6SSteven Rostedt close(DMESG); 6752545eb61SSteven Rostedt 6762545eb61SSteven Rostedt if ($bug) { 6772b7d9b21SSteven Rostedt return 0 if ($in_bisect); 678576f627cSSteven Rostedt fail "failed - got a bug report" and return 0; 6792545eb61SSteven Rostedt } 6805f9b6cedSSteven Rostedt 681a75fececSSteven Rostedt if (!$booted) { 682a75fececSSteven Rostedt return 0 if ($in_bisect); 683576f627cSSteven Rostedt fail "failed - never got a boot prompt." and return 0; 684a75fececSSteven Rostedt } 685a75fececSSteven Rostedt 6862b7d9b21SSteven Rostedt return 1; 6872545eb61SSteven Rostedt} 6882545eb61SSteven Rostedt 6892545eb61SSteven Rostedtsub install { 6902545eb61SSteven Rostedt 691e48c5293SSteven Rostedt run_scp "$outputdir/$build_target", "$target_image" or 6925c42fc5bSSteven Rostedt dodie "failed to copy image"; 6935f9b6cedSSteven Rostedt 6945f9b6cedSSteven Rostedt my $install_mods = 0; 6955f9b6cedSSteven Rostedt 6965f9b6cedSSteven Rostedt # should we process modules? 6975f9b6cedSSteven Rostedt $install_mods = 0; 69851ad1dd1SSteven Rostedt open(IN, "$output_config") or dodie("Can't read config file"); 6995f9b6cedSSteven Rostedt while (<IN>) { 7005f9b6cedSSteven Rostedt if (/CONFIG_MODULES(=y)?/) { 7015f9b6cedSSteven Rostedt $install_mods = 1 if (defined($1)); 7025f9b6cedSSteven Rostedt last; 7035f9b6cedSSteven Rostedt } 7045f9b6cedSSteven Rostedt } 7055f9b6cedSSteven Rostedt close(IN); 7065f9b6cedSSteven Rostedt 7075f9b6cedSSteven Rostedt if (!$install_mods) { 7085f9b6cedSSteven Rostedt doprint "No modules needed\n"; 7095f9b6cedSSteven Rostedt return; 7102545eb61SSteven Rostedt } 7112545eb61SSteven Rostedt 712a75fececSSteven Rostedt run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or 7135f9b6cedSSteven Rostedt dodie "Failed to install modules"; 7145f9b6cedSSteven Rostedt 7152545eb61SSteven Rostedt my $modlib = "/lib/modules/$version"; 716a57419b3SSteven Rostedt my $modtar = "ktest-mods.tar.bz2"; 7172545eb61SSteven Rostedt 718e48c5293SSteven Rostedt run_ssh "rm -rf $modlib" or 7195c42fc5bSSteven Rostedt dodie "failed to remove old mods: $modlib"; 7202545eb61SSteven Rostedt 7215c42fc5bSSteven Rostedt # would be nice if scp -r did not follow symbolic links 722a75fececSSteven Rostedt run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 7235c42fc5bSSteven Rostedt dodie "making tarball"; 7245c42fc5bSSteven Rostedt 725e48c5293SSteven Rostedt run_scp "$tmpdir/$modtar", "/tmp" or 7265c42fc5bSSteven Rostedt dodie "failed to copy modules"; 7275c42fc5bSSteven Rostedt 728a75fececSSteven Rostedt unlink "$tmpdir/$modtar"; 7295c42fc5bSSteven Rostedt 730e48c5293SSteven Rostedt run_ssh "'(cd / && tar xf /tmp/$modtar)'" or 7315c42fc5bSSteven Rostedt dodie "failed to tar modules"; 7325c42fc5bSSteven Rostedt 733e48c5293SSteven Rostedt run_ssh "rm -f /tmp/$modtar"; 7348b37ca8cSSteven Rostedt 7358b37ca8cSSteven Rostedt return if (!defined($post_install)); 7368b37ca8cSSteven Rostedt 737e48c5293SSteven Rostedt my $cp_post_install = $post_install; 738e48c5293SSteven Rostedt $cp_post_install = s/\$KERNEL_VERSION/$version/g; 739e48c5293SSteven Rostedt run_command "$cp_post_install" or 740576f627cSSteven Rostedt dodie "Failed to run post install"; 7412545eb61SSteven Rostedt} 7422545eb61SSteven Rostedt 7436c5ee0beSSteven Rostedtsub check_buildlog { 7446c5ee0beSSteven Rostedt my ($patch) = @_; 7456c5ee0beSSteven Rostedt 7466c5ee0beSSteven Rostedt my @files = `git show $patch | diffstat -l`; 7476c5ee0beSSteven Rostedt 7486c5ee0beSSteven Rostedt open(IN, "git show $patch |") or 7496c5ee0beSSteven Rostedt dodie "failed to show $patch"; 7506c5ee0beSSteven Rostedt while (<IN>) { 7516c5ee0beSSteven Rostedt if (m,^--- a/(.*),) { 7526c5ee0beSSteven Rostedt chomp $1; 7536c5ee0beSSteven Rostedt $files[$#files] = $1; 7546c5ee0beSSteven Rostedt } 7556c5ee0beSSteven Rostedt } 7566c5ee0beSSteven Rostedt close(IN); 7576c5ee0beSSteven Rostedt 7586c5ee0beSSteven Rostedt open(IN, $buildlog) or dodie "Can't open $buildlog"; 7596c5ee0beSSteven Rostedt while (<IN>) { 7606c5ee0beSSteven Rostedt if (/^\s*(.*?):.*(warning|error)/) { 7616c5ee0beSSteven Rostedt my $err = $1; 7626c5ee0beSSteven Rostedt foreach my $file (@files) { 763a75fececSSteven Rostedt my $fullpath = "$builddir/$file"; 7646c5ee0beSSteven Rostedt if ($file eq $err || $fullpath eq $err) { 7652b7d9b21SSteven Rostedt fail "$file built with warnings" and return 0; 7666c5ee0beSSteven Rostedt } 7676c5ee0beSSteven Rostedt } 7686c5ee0beSSteven Rostedt } 7696c5ee0beSSteven Rostedt } 7706c5ee0beSSteven Rostedt close(IN); 7712b7d9b21SSteven Rostedt 7722b7d9b21SSteven Rostedt return 1; 7736c5ee0beSSteven Rostedt} 7746c5ee0beSSteven Rostedt 7752545eb61SSteven Rostedtsub build { 7762545eb61SSteven Rostedt my ($type) = @_; 7775c42fc5bSSteven Rostedt my $defconfig = ""; 7782545eb61SSteven Rostedt 7797faafbd6SSteven Rostedt unlink $buildlog; 7807faafbd6SSteven Rostedt 78175c3fda7SSteven Rostedt if ($type =~ /^useconfig:(.*)/) { 78251ad1dd1SSteven Rostedt run_command "cp $1 $output_config" or 78375c3fda7SSteven Rostedt dodie "could not copy $1 to .config"; 7845f9b6cedSSteven Rostedt 78575c3fda7SSteven Rostedt $type = "oldconfig"; 78675c3fda7SSteven Rostedt } 78775c3fda7SSteven Rostedt 7885c42fc5bSSteven Rostedt # old config can ask questions 7895c42fc5bSSteven Rostedt if ($type eq "oldconfig") { 7909386c6abSSteven Rostedt $type = "oldnoconfig"; 79175c3fda7SSteven Rostedt 79275c3fda7SSteven Rostedt # allow for empty configs 79351ad1dd1SSteven Rostedt run_command "touch $output_config"; 79475c3fda7SSteven Rostedt 79551ad1dd1SSteven Rostedt run_command "mv $output_config $outputdir/config_temp" or 7965c42fc5bSSteven Rostedt dodie "moving .config"; 7975c42fc5bSSteven Rostedt 7985f9b6cedSSteven Rostedt if (!$noclean && !run_command "$make mrproper") { 7995c42fc5bSSteven Rostedt dodie "make mrproper"; 8005c42fc5bSSteven Rostedt } 8015c42fc5bSSteven Rostedt 80251ad1dd1SSteven Rostedt run_command "mv $outputdir/config_temp $output_config" or 8035c42fc5bSSteven Rostedt dodie "moving config_temp"; 8045c42fc5bSSteven Rostedt 8055c42fc5bSSteven Rostedt } elsif (!$noclean) { 80651ad1dd1SSteven Rostedt unlink "$output_config"; 8075f9b6cedSSteven Rostedt run_command "$make mrproper" or 8085c42fc5bSSteven Rostedt dodie "make mrproper"; 8095c42fc5bSSteven Rostedt } 8102545eb61SSteven Rostedt 8112545eb61SSteven Rostedt # add something to distinguish this build 812a75fececSSteven Rostedt open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 813a75fececSSteven Rostedt print OUT "$localversion\n"; 8142545eb61SSteven Rostedt close(OUT); 8152545eb61SSteven Rostedt 8165f9b6cedSSteven Rostedt if (defined($minconfig)) { 8175f9b6cedSSteven Rostedt $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; 8182545eb61SSteven Rostedt } 8192545eb61SSteven Rostedt 8209386c6abSSteven Rostedt run_command "$defconfig $make $type" or 8215c42fc5bSSteven Rostedt dodie "failed make config"; 8222545eb61SSteven Rostedt 823a75fececSSteven Rostedt $redirect = "$buildlog"; 824a75fececSSteven Rostedt if (!run_command "$make $build_options") { 8256c5ee0beSSteven Rostedt undef $redirect; 8265f9b6cedSSteven Rostedt # bisect may need this to pass 8272b7d9b21SSteven Rostedt return 0 if ($in_bisect); 8282b7d9b21SSteven Rostedt fail "failed build" and return 0; 8292545eb61SSteven Rostedt } 8306c5ee0beSSteven Rostedt undef $redirect; 8315f9b6cedSSteven Rostedt 8322b7d9b21SSteven Rostedt return 1; 8332545eb61SSteven Rostedt} 8342545eb61SSteven Rostedt 83575c3fda7SSteven Rostedtsub halt { 836e48c5293SSteven Rostedt if (!run_ssh "halt" or defined($power_off)) { 837576f627cSSteven Rostedt if (defined($poweroff_after_halt)) { 838576f627cSSteven Rostedt sleep $poweroff_after_halt; 839576f627cSSteven Rostedt run_command "$power_off"; 840576f627cSSteven Rostedt } 841576f627cSSteven Rostedt } else { 84275c3fda7SSteven Rostedt # nope? the zap it! 843a75fececSSteven Rostedt run_command "$power_off"; 84475c3fda7SSteven Rostedt } 84575c3fda7SSteven Rostedt} 84675c3fda7SSteven Rostedt 8475f9b6cedSSteven Rostedtsub success { 8485f9b6cedSSteven Rostedt my ($i) = @_; 8495f9b6cedSSteven Rostedt 850e48c5293SSteven Rostedt $successes++; 851e48c5293SSteven Rostedt 8525f9b6cedSSteven Rostedt doprint "\n\n*******************************************\n"; 8535f9b6cedSSteven Rostedt doprint "*******************************************\n"; 8547a849cd9SSteven Rostedt doprint "KTEST RESULT: TEST $i SUCCESS!!!! **\n"; 8555f9b6cedSSteven Rostedt doprint "*******************************************\n"; 8565f9b6cedSSteven Rostedt doprint "*******************************************\n"; 8575f9b6cedSSteven Rostedt 858576f627cSSteven Rostedt if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 859a75fececSSteven Rostedt doprint "Reboot and wait $sleep_time seconds\n"; 8605f9b6cedSSteven Rostedt reboot; 8617faafbd6SSteven Rostedt start_monitor; 862a75fececSSteven Rostedt wait_for_monitor $sleep_time; 8637faafbd6SSteven Rostedt end_monitor; 8645f9b6cedSSteven Rostedt } 8655f9b6cedSSteven Rostedt} 8665f9b6cedSSteven Rostedt 8675f9b6cedSSteven Rostedtsub get_version { 8685f9b6cedSSteven Rostedt # get the release name 8695f9b6cedSSteven Rostedt doprint "$make kernelrelease ... "; 8705f9b6cedSSteven Rostedt $version = `$make kernelrelease | tail -1`; 8715f9b6cedSSteven Rostedt chomp($version); 8725f9b6cedSSteven Rostedt doprint "$version\n"; 8735f9b6cedSSteven Rostedt} 8745f9b6cedSSteven Rostedt 8755a391fbfSSteven Rostedtsub child_run_test { 8767faafbd6SSteven Rostedt my $failed = 0; 8775a391fbfSSteven Rostedt 8787faafbd6SSteven Rostedt # child should have no power 879a75fececSSteven Rostedt $reboot_on_error = 0; 880a75fececSSteven Rostedt $poweroff_on_error = 0; 881a75fececSSteven Rostedt $die_on_failure = 1; 8827faafbd6SSteven Rostedt 8837faafbd6SSteven Rostedt run_command $run_test or $failed = 1; 8845a391fbfSSteven Rostedt exit $failed; 8855a391fbfSSteven Rostedt} 8865a391fbfSSteven Rostedt 8875a391fbfSSteven Rostedtmy $child_done; 8885a391fbfSSteven Rostedt 8895a391fbfSSteven Rostedtsub child_finished { 8905a391fbfSSteven Rostedt $child_done = 1; 8915a391fbfSSteven Rostedt} 8925a391fbfSSteven Rostedt 8935a391fbfSSteven Rostedtsub do_run_test { 8945a391fbfSSteven Rostedt my $child_pid; 8955a391fbfSSteven Rostedt my $child_exit; 8965a391fbfSSteven Rostedt my $line; 8975a391fbfSSteven Rostedt my $full_line; 8985a391fbfSSteven Rostedt my $bug = 0; 8995a391fbfSSteven Rostedt 9007faafbd6SSteven Rostedt wait_for_monitor 1; 9015a391fbfSSteven Rostedt 9027faafbd6SSteven Rostedt doprint "run test $run_test\n"; 9035a391fbfSSteven Rostedt 9045a391fbfSSteven Rostedt $child_done = 0; 9055a391fbfSSteven Rostedt 9065a391fbfSSteven Rostedt $SIG{CHLD} = qw(child_finished); 9075a391fbfSSteven Rostedt 9085a391fbfSSteven Rostedt $child_pid = fork; 9095a391fbfSSteven Rostedt 9105a391fbfSSteven Rostedt child_run_test if (!$child_pid); 9115a391fbfSSteven Rostedt 9125a391fbfSSteven Rostedt $full_line = ""; 9135a391fbfSSteven Rostedt 9145a391fbfSSteven Rostedt do { 9157faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 9165a391fbfSSteven Rostedt if (defined($line)) { 9175a391fbfSSteven Rostedt 9185a391fbfSSteven Rostedt # we are not guaranteed to get a full line 9195a391fbfSSteven Rostedt $full_line .= $line; 9205a391fbfSSteven Rostedt 9215a391fbfSSteven Rostedt if ($full_line =~ /call trace:/i) { 9225a391fbfSSteven Rostedt $bug = 1; 9235a391fbfSSteven Rostedt } 9245a391fbfSSteven Rostedt 9255a391fbfSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 9265a391fbfSSteven Rostedt $bug = 1; 9275a391fbfSSteven Rostedt } 9285a391fbfSSteven Rostedt 9295a391fbfSSteven Rostedt if ($line =~ /\n/) { 9305a391fbfSSteven Rostedt $full_line = ""; 9315a391fbfSSteven Rostedt } 9325a391fbfSSteven Rostedt } 9335a391fbfSSteven Rostedt } while (!$child_done && !$bug); 9345a391fbfSSteven Rostedt 9355a391fbfSSteven Rostedt if ($bug) { 9365a391fbfSSteven Rostedt doprint "Detected kernel crash!\n"; 9375a391fbfSSteven Rostedt # kill the child with extreme prejudice 9385a391fbfSSteven Rostedt kill 9, $child_pid; 9395a391fbfSSteven Rostedt } 9405a391fbfSSteven Rostedt 9415a391fbfSSteven Rostedt waitpid $child_pid, 0; 9425a391fbfSSteven Rostedt $child_exit = $?; 9435a391fbfSSteven Rostedt 9445a391fbfSSteven Rostedt if ($bug || $child_exit) { 9452b7d9b21SSteven Rostedt return 0 if $in_bisect; 9462b7d9b21SSteven Rostedt fail "test failed" and return 0; 9475a391fbfSSteven Rostedt } 9482b7d9b21SSteven Rostedt return 1; 9495a391fbfSSteven Rostedt} 9505a391fbfSSteven Rostedt 951a75fececSSteven Rostedtsub run_git_bisect { 952a75fececSSteven Rostedt my ($command) = @_; 953a75fececSSteven Rostedt 954a75fececSSteven Rostedt doprint "$command ... "; 955a75fececSSteven Rostedt 956a75fececSSteven Rostedt my $output = `$command 2>&1`; 957a75fececSSteven Rostedt my $ret = $?; 958a75fececSSteven Rostedt 959a75fececSSteven Rostedt logit $output; 960a75fececSSteven Rostedt 961a75fececSSteven Rostedt if ($ret) { 962a75fececSSteven Rostedt doprint "FAILED\n"; 963a75fececSSteven Rostedt dodie "Failed to git bisect"; 964a75fececSSteven Rostedt } 965a75fececSSteven Rostedt 966a75fececSSteven Rostedt doprint "SUCCESS\n"; 967a75fececSSteven Rostedt if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 968a75fececSSteven Rostedt doprint "$1 [$2]\n"; 969a75fececSSteven Rostedt } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 970a75fececSSteven Rostedt $bisect_bad = $1; 971a75fececSSteven Rostedt doprint "Found bad commit... $1\n"; 972a75fececSSteven Rostedt return 0; 973a75fececSSteven Rostedt } else { 974a75fececSSteven Rostedt # we already logged it, just print it now. 975a75fececSSteven Rostedt print $output; 976a75fececSSteven Rostedt } 977a75fececSSteven Rostedt 978a75fececSSteven Rostedt return 1; 979a75fececSSteven Rostedt} 980a75fececSSteven Rostedt 9810a05c769SSteven Rostedt# returns 1 on success, 0 on failure 9820a05c769SSteven Rostedtsub run_bisect_test { 9830a05c769SSteven Rostedt my ($type, $buildtype) = @_; 9845f9b6cedSSteven Rostedt 9852b7d9b21SSteven Rostedt my $failed = 0; 9865f9b6cedSSteven Rostedt my $result; 9875f9b6cedSSteven Rostedt my $output; 9885f9b6cedSSteven Rostedt my $ret; 9895f9b6cedSSteven Rostedt 9900a05c769SSteven Rostedt $in_bisect = 1; 9910a05c769SSteven Rostedt 9920a05c769SSteven Rostedt build $buildtype or $failed = 1; 9935f9b6cedSSteven Rostedt 9945f9b6cedSSteven Rostedt if ($type ne "build") { 9957faafbd6SSteven Rostedt dodie "Failed on build" if $failed; 9965f9b6cedSSteven Rostedt 9975f9b6cedSSteven Rostedt # Now boot the box 9985f9b6cedSSteven Rostedt get_grub_index; 9995f9b6cedSSteven Rostedt get_version; 10005f9b6cedSSteven Rostedt install; 10017faafbd6SSteven Rostedt 10027faafbd6SSteven Rostedt start_monitor; 10032b7d9b21SSteven Rostedt monitor or $failed = 1; 10045f9b6cedSSteven Rostedt 10055f9b6cedSSteven Rostedt if ($type ne "boot") { 10067faafbd6SSteven Rostedt dodie "Failed on boot" if $failed; 10075a391fbfSSteven Rostedt 10082b7d9b21SSteven Rostedt do_run_test or $failed = 1; 10095f9b6cedSSteven Rostedt } 10107faafbd6SSteven Rostedt end_monitor; 10115f9b6cedSSteven Rostedt } 10125f9b6cedSSteven Rostedt 10135f9b6cedSSteven Rostedt if ($failed) { 10140a05c769SSteven Rostedt $result = 0; 10155a391fbfSSteven Rostedt 10165a391fbfSSteven Rostedt # reboot the box to a good kernel 1017a75fececSSteven Rostedt if ($type ne "build") { 1018a75fececSSteven Rostedt doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 10195a391fbfSSteven Rostedt reboot; 10207faafbd6SSteven Rostedt start_monitor; 1021a75fececSSteven Rostedt wait_for_monitor $bisect_sleep_time; 10227faafbd6SSteven Rostedt end_monitor; 10235a391fbfSSteven Rostedt } 10245f9b6cedSSteven Rostedt } else { 10250a05c769SSteven Rostedt $result = 1; 10265f9b6cedSSteven Rostedt } 10270a05c769SSteven Rostedt $in_bisect = 0; 10280a05c769SSteven Rostedt 10290a05c769SSteven Rostedt return $result; 10300a05c769SSteven Rostedt} 10310a05c769SSteven Rostedt 10320a05c769SSteven Rostedtsub run_bisect { 10330a05c769SSteven Rostedt my ($type) = @_; 10340a05c769SSteven Rostedt my $buildtype = "oldconfig"; 10350a05c769SSteven Rostedt 10360a05c769SSteven Rostedt # We should have a minconfig to use? 10370a05c769SSteven Rostedt if (defined($minconfig)) { 10380a05c769SSteven Rostedt $buildtype = "useconfig:$minconfig"; 10390a05c769SSteven Rostedt } 10400a05c769SSteven Rostedt 10410a05c769SSteven Rostedt my $ret = run_bisect_test $type, $buildtype; 10420a05c769SSteven Rostedt 10435f9b6cedSSteven Rostedt 1044d6ce2a0bSSteven Rostedt # Are we looking for where it worked, not failed? 1045d6ce2a0bSSteven Rostedt if ($reverse_bisect) { 10460a05c769SSteven Rostedt $ret = !$ret; 1047d6ce2a0bSSteven Rostedt } 1048d6ce2a0bSSteven Rostedt 10490a05c769SSteven Rostedt if ($ret) { 10500a05c769SSteven Rostedt return "good"; 10510a05c769SSteven Rostedt } else { 10520a05c769SSteven Rostedt return "bad"; 10530a05c769SSteven Rostedt } 10545f9b6cedSSteven Rostedt} 10555f9b6cedSSteven Rostedt 10565f9b6cedSSteven Rostedtsub bisect { 10575f9b6cedSSteven Rostedt my ($i) = @_; 10585f9b6cedSSteven Rostedt 10595f9b6cedSSteven Rostedt my $result; 10605f9b6cedSSteven Rostedt 10615f9b6cedSSteven Rostedt die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 10625f9b6cedSSteven Rostedt die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 10635f9b6cedSSteven Rostedt die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 10645f9b6cedSSteven Rostedt 10655f9b6cedSSteven Rostedt my $good = $opt{"BISECT_GOOD[$i]"}; 10665f9b6cedSSteven Rostedt my $bad = $opt{"BISECT_BAD[$i]"}; 10675f9b6cedSSteven Rostedt my $type = $opt{"BISECT_TYPE[$i]"}; 1068a75fececSSteven Rostedt my $start = $opt{"BISECT_START[$i]"}; 1069a75fececSSteven Rostedt my $replay = $opt{"BISECT_REPLAY[$i]"}; 10705f9b6cedSSteven Rostedt 1071a57419b3SSteven Rostedt # convert to true sha1's 1072a57419b3SSteven Rostedt $good = get_sha1($good); 1073a57419b3SSteven Rostedt $bad = get_sha1($bad); 1074a57419b3SSteven Rostedt 1075d6ce2a0bSSteven Rostedt if (defined($opt{"BISECT_REVERSE[$i]"}) && 1076d6ce2a0bSSteven Rostedt $opt{"BISECT_REVERSE[$i]"} == 1) { 1077d6ce2a0bSSteven Rostedt doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 1078d6ce2a0bSSteven Rostedt $reverse_bisect = 1; 1079d6ce2a0bSSteven Rostedt } else { 1080d6ce2a0bSSteven Rostedt $reverse_bisect = 0; 1081d6ce2a0bSSteven Rostedt } 1082d6ce2a0bSSteven Rostedt 10835a391fbfSSteven Rostedt # Can't have a test without having a test to run 10845a391fbfSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 10855a391fbfSSteven Rostedt $type = "boot"; 10865a391fbfSSteven Rostedt } 10875a391fbfSSteven Rostedt 1088a75fececSSteven Rostedt my $check = $opt{"BISECT_CHECK[$i]"}; 1089a75fececSSteven Rostedt if (defined($check) && $check ne "0") { 1090a75fececSSteven Rostedt 1091a75fececSSteven Rostedt # get current HEAD 1092a57419b3SSteven Rostedt my $head = get_sha1("HEAD"); 1093a75fececSSteven Rostedt 1094a75fececSSteven Rostedt if ($check ne "good") { 1095a75fececSSteven Rostedt doprint "TESTING BISECT BAD [$bad]\n"; 1096a75fececSSteven Rostedt run_command "git checkout $bad" or 1097a75fececSSteven Rostedt die "Failed to checkout $bad"; 1098a75fececSSteven Rostedt 1099a75fececSSteven Rostedt $result = run_bisect $type; 1100a75fececSSteven Rostedt 1101a75fececSSteven Rostedt if ($result ne "bad") { 1102a75fececSSteven Rostedt fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 1103a75fececSSteven Rostedt } 1104a75fececSSteven Rostedt } 1105a75fececSSteven Rostedt 1106a75fececSSteven Rostedt if ($check ne "bad") { 1107a75fececSSteven Rostedt doprint "TESTING BISECT GOOD [$good]\n"; 1108a75fececSSteven Rostedt run_command "git checkout $good" or 1109a75fececSSteven Rostedt die "Failed to checkout $good"; 1110a75fececSSteven Rostedt 1111a75fececSSteven Rostedt $result = run_bisect $type; 1112a75fececSSteven Rostedt 1113a75fececSSteven Rostedt if ($result ne "good") { 1114a75fececSSteven Rostedt fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 1115a75fececSSteven Rostedt } 1116a75fececSSteven Rostedt } 1117a75fececSSteven Rostedt 1118a75fececSSteven Rostedt # checkout where we started 1119a75fececSSteven Rostedt run_command "git checkout $head" or 1120a75fececSSteven Rostedt die "Failed to checkout $head"; 1121a75fececSSteven Rostedt } 1122a75fececSSteven Rostedt 1123a75fececSSteven Rostedt run_command "git bisect start" or 1124a75fececSSteven Rostedt dodie "could not start bisect"; 1125a75fececSSteven Rostedt 1126a75fececSSteven Rostedt run_command "git bisect good $good" or 1127a75fececSSteven Rostedt dodie "could not set bisect good to $good"; 1128a75fececSSteven Rostedt 1129a75fececSSteven Rostedt run_git_bisect "git bisect bad $bad" or 1130a75fececSSteven Rostedt dodie "could not set bisect bad to $bad"; 1131a75fececSSteven Rostedt 1132a75fececSSteven Rostedt if (defined($replay)) { 1133a75fececSSteven Rostedt run_command "git bisect replay $replay" or 1134a75fececSSteven Rostedt dodie "failed to run replay"; 1135a75fececSSteven Rostedt } 1136a75fececSSteven Rostedt 1137a75fececSSteven Rostedt if (defined($start)) { 1138a75fececSSteven Rostedt run_command "git checkout $start" or 1139a75fececSSteven Rostedt dodie "failed to checkout $start"; 1140a75fececSSteven Rostedt } 1141a75fececSSteven Rostedt 1142a75fececSSteven Rostedt my $test; 11435f9b6cedSSteven Rostedt do { 11445f9b6cedSSteven Rostedt $result = run_bisect $type; 1145a75fececSSteven Rostedt $test = run_git_bisect "git bisect $result"; 1146a75fececSSteven Rostedt } while ($test); 11475f9b6cedSSteven Rostedt 11485f9b6cedSSteven Rostedt run_command "git bisect log" or 11495f9b6cedSSteven Rostedt dodie "could not capture git bisect log"; 11505f9b6cedSSteven Rostedt 11515f9b6cedSSteven Rostedt run_command "git bisect reset" or 11525f9b6cedSSteven Rostedt dodie "could not reset git bisect"; 11535f9b6cedSSteven Rostedt 11545f9b6cedSSteven Rostedt doprint "Bad commit was [$bisect_bad]\n"; 11555f9b6cedSSteven Rostedt 11560a05c769SSteven Rostedt success $i; 11570a05c769SSteven Rostedt} 11580a05c769SSteven Rostedt 11590a05c769SSteven Rostedtmy %config_ignore; 11600a05c769SSteven Rostedtmy %config_set; 11610a05c769SSteven Rostedt 11620a05c769SSteven Rostedtmy %config_list; 11630a05c769SSteven Rostedtmy %null_config; 11640a05c769SSteven Rostedt 11650a05c769SSteven Rostedtmy %dependency; 11660a05c769SSteven Rostedt 11670a05c769SSteven Rostedtsub process_config_ignore { 11680a05c769SSteven Rostedt my ($config) = @_; 11690a05c769SSteven Rostedt 11700a05c769SSteven Rostedt open (IN, $config) 11710a05c769SSteven Rostedt or dodie "Failed to read $config"; 11720a05c769SSteven Rostedt 11730a05c769SSteven Rostedt while (<IN>) { 11740a05c769SSteven Rostedt if (/^(.*?(CONFIG\S*)(=.*| is not set))/) { 11750a05c769SSteven Rostedt $config_ignore{$2} = $1; 11760a05c769SSteven Rostedt } 11770a05c769SSteven Rostedt } 11780a05c769SSteven Rostedt 11790a05c769SSteven Rostedt close(IN); 11800a05c769SSteven Rostedt} 11810a05c769SSteven Rostedt 11820a05c769SSteven Rostedtsub read_current_config { 11830a05c769SSteven Rostedt my ($config_ref) = @_; 11840a05c769SSteven Rostedt 11850a05c769SSteven Rostedt %{$config_ref} = (); 11860a05c769SSteven Rostedt undef %{$config_ref}; 11870a05c769SSteven Rostedt 11880a05c769SSteven Rostedt my @key = keys %{$config_ref}; 11890a05c769SSteven Rostedt if ($#key >= 0) { 11900a05c769SSteven Rostedt print "did not delete!\n"; 11910a05c769SSteven Rostedt exit; 11920a05c769SSteven Rostedt } 11930a05c769SSteven Rostedt open (IN, "$output_config"); 11940a05c769SSteven Rostedt 11950a05c769SSteven Rostedt while (<IN>) { 11960a05c769SSteven Rostedt if (/^(CONFIG\S+)=(.*)/) { 11970a05c769SSteven Rostedt ${$config_ref}{$1} = $2; 11980a05c769SSteven Rostedt } 11990a05c769SSteven Rostedt } 12000a05c769SSteven Rostedt close(IN); 12010a05c769SSteven Rostedt} 12020a05c769SSteven Rostedt 12030a05c769SSteven Rostedtsub get_dependencies { 12040a05c769SSteven Rostedt my ($config) = @_; 12050a05c769SSteven Rostedt 12060a05c769SSteven Rostedt my $arr = $dependency{$config}; 12070a05c769SSteven Rostedt if (!defined($arr)) { 12080a05c769SSteven Rostedt return (); 12090a05c769SSteven Rostedt } 12100a05c769SSteven Rostedt 12110a05c769SSteven Rostedt my @deps = @{$arr}; 12120a05c769SSteven Rostedt 12130a05c769SSteven Rostedt foreach my $dep (@{$arr}) { 12140a05c769SSteven Rostedt print "ADD DEP $dep\n"; 12150a05c769SSteven Rostedt @deps = (@deps, get_dependencies $dep); 12160a05c769SSteven Rostedt } 12170a05c769SSteven Rostedt 12180a05c769SSteven Rostedt return @deps; 12190a05c769SSteven Rostedt} 12200a05c769SSteven Rostedt 12210a05c769SSteven Rostedtsub create_config { 12220a05c769SSteven Rostedt my @configs = @_; 12230a05c769SSteven Rostedt 12240a05c769SSteven Rostedt open(OUT, ">$output_config") or dodie "Can not write to $output_config"; 12250a05c769SSteven Rostedt 12260a05c769SSteven Rostedt foreach my $config (@configs) { 12270a05c769SSteven Rostedt print OUT "$config_set{$config}\n"; 12280a05c769SSteven Rostedt my @deps = get_dependencies $config; 12290a05c769SSteven Rostedt foreach my $dep (@deps) { 12300a05c769SSteven Rostedt print OUT "$config_set{$dep}\n"; 12310a05c769SSteven Rostedt } 12320a05c769SSteven Rostedt } 12330a05c769SSteven Rostedt 12340a05c769SSteven Rostedt foreach my $config (keys %config_ignore) { 12350a05c769SSteven Rostedt print OUT "$config_ignore{$config}\n"; 12360a05c769SSteven Rostedt } 12370a05c769SSteven Rostedt close(OUT); 12380a05c769SSteven Rostedt 12390a05c769SSteven Rostedt# exit; 12400a05c769SSteven Rostedt run_command "$make oldnoconfig" or 12410a05c769SSteven Rostedt dodie "failed make config oldconfig"; 12420a05c769SSteven Rostedt 12430a05c769SSteven Rostedt} 12440a05c769SSteven Rostedt 12450a05c769SSteven Rostedtsub compare_configs { 12460a05c769SSteven Rostedt my (%a, %b) = @_; 12470a05c769SSteven Rostedt 12480a05c769SSteven Rostedt foreach my $item (keys %a) { 12490a05c769SSteven Rostedt if (!defined($b{$item})) { 12500a05c769SSteven Rostedt print "diff $item\n"; 12510a05c769SSteven Rostedt return 1; 12520a05c769SSteven Rostedt } 12530a05c769SSteven Rostedt delete $b{$item}; 12540a05c769SSteven Rostedt } 12550a05c769SSteven Rostedt 12560a05c769SSteven Rostedt my @keys = keys %b; 12570a05c769SSteven Rostedt if ($#keys) { 12580a05c769SSteven Rostedt print "diff2 $keys[0]\n"; 12590a05c769SSteven Rostedt } 12600a05c769SSteven Rostedt return -1 if ($#keys >= 0); 12610a05c769SSteven Rostedt 12620a05c769SSteven Rostedt return 0; 12630a05c769SSteven Rostedt} 12640a05c769SSteven Rostedt 12650a05c769SSteven Rostedtsub run_config_bisect_test { 12660a05c769SSteven Rostedt my ($type) = @_; 12670a05c769SSteven Rostedt 12680a05c769SSteven Rostedt return run_bisect_test $type, "oldconfig"; 12690a05c769SSteven Rostedt} 12700a05c769SSteven Rostedt 12710a05c769SSteven Rostedtsub process_passed { 12720a05c769SSteven Rostedt my (%configs) = @_; 12730a05c769SSteven Rostedt 12740a05c769SSteven Rostedt doprint "These configs had no failure: (Enabling them for further compiles)\n"; 12750a05c769SSteven Rostedt # Passed! All these configs are part of a good compile. 12760a05c769SSteven Rostedt # Add them to the min options. 12770a05c769SSteven Rostedt foreach my $config (keys %configs) { 12780a05c769SSteven Rostedt if (defined($config_list{$config})) { 12790a05c769SSteven Rostedt doprint " removing $config\n"; 12800a05c769SSteven Rostedt $config_ignore{$config} = $config_list{$config}; 12810a05c769SSteven Rostedt delete $config_list{$config}; 12820a05c769SSteven Rostedt } 12830a05c769SSteven Rostedt } 1284*f1a27850SSteven Rostedt doprint "config copied to $outputdir/config_good\n"; 1285*f1a27850SSteven Rostedt run_command "cp -f $output_config $outputdir/config_good"; 12860a05c769SSteven Rostedt} 12870a05c769SSteven Rostedt 12880a05c769SSteven Rostedtsub process_failed { 12890a05c769SSteven Rostedt my ($config) = @_; 12900a05c769SSteven Rostedt 12910a05c769SSteven Rostedt doprint "\n\n***************************************\n"; 12920a05c769SSteven Rostedt doprint "Found bad config: $config\n"; 12930a05c769SSteven Rostedt doprint "***************************************\n\n"; 12940a05c769SSteven Rostedt} 12950a05c769SSteven Rostedt 12960a05c769SSteven Rostedtsub run_config_bisect { 12970a05c769SSteven Rostedt 12980a05c769SSteven Rostedt my @start_list = keys %config_list; 12990a05c769SSteven Rostedt 13000a05c769SSteven Rostedt if ($#start_list < 0) { 13010a05c769SSteven Rostedt doprint "No more configs to test!!!\n"; 13020a05c769SSteven Rostedt return -1; 13030a05c769SSteven Rostedt } 13040a05c769SSteven Rostedt 13050a05c769SSteven Rostedt doprint "***** RUN TEST ***\n"; 13060a05c769SSteven Rostedt my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"}; 13070a05c769SSteven Rostedt my $ret; 13080a05c769SSteven Rostedt my %current_config; 13090a05c769SSteven Rostedt 13100a05c769SSteven Rostedt my $count = $#start_list + 1; 13110a05c769SSteven Rostedt doprint " $count configs to test\n"; 13120a05c769SSteven Rostedt 13130a05c769SSteven Rostedt my $half = int($#start_list / 2); 13140a05c769SSteven Rostedt 13150a05c769SSteven Rostedt do { 13160a05c769SSteven Rostedt my @tophalf = @start_list[0 .. $half]; 13170a05c769SSteven Rostedt 13180a05c769SSteven Rostedt create_config @tophalf; 13190a05c769SSteven Rostedt read_current_config \%current_config; 13200a05c769SSteven Rostedt 13210a05c769SSteven Rostedt $count = $#tophalf + 1; 13220a05c769SSteven Rostedt doprint "Testing $count configs\n"; 13230a05c769SSteven Rostedt my $found = 0; 13240a05c769SSteven Rostedt # make sure we test something 13250a05c769SSteven Rostedt foreach my $config (@tophalf) { 13260a05c769SSteven Rostedt if (defined($current_config{$config})) { 13270a05c769SSteven Rostedt logit " $config\n"; 13280a05c769SSteven Rostedt $found = 1; 13290a05c769SSteven Rostedt } 13300a05c769SSteven Rostedt } 13310a05c769SSteven Rostedt if (!$found) { 13320a05c769SSteven Rostedt # try the other half 13330a05c769SSteven Rostedt doprint "Top half produced no set configs, trying bottom half\n"; 13340a05c769SSteven Rostedt @tophalf = @start_list[$half .. $#start_list]; 13350a05c769SSteven Rostedt create_config @tophalf; 13360a05c769SSteven Rostedt read_current_config \%current_config; 13370a05c769SSteven Rostedt foreach my $config (@tophalf) { 13380a05c769SSteven Rostedt if (defined($current_config{$config})) { 13390a05c769SSteven Rostedt logit " $config\n"; 13400a05c769SSteven Rostedt $found = 1; 13410a05c769SSteven Rostedt } 13420a05c769SSteven Rostedt } 13430a05c769SSteven Rostedt if (!$found) { 13440a05c769SSteven Rostedt doprint "Failed: Can't make new config with current configs\n"; 13450a05c769SSteven Rostedt foreach my $config (@start_list) { 13460a05c769SSteven Rostedt doprint " CONFIG: $config\n"; 13470a05c769SSteven Rostedt } 13480a05c769SSteven Rostedt return -1; 13490a05c769SSteven Rostedt } 13500a05c769SSteven Rostedt $count = $#tophalf + 1; 13510a05c769SSteven Rostedt doprint "Testing $count configs\n"; 13520a05c769SSteven Rostedt } 13530a05c769SSteven Rostedt 13540a05c769SSteven Rostedt $ret = run_config_bisect_test $type; 13550a05c769SSteven Rostedt 13560a05c769SSteven Rostedt if ($ret) { 13570a05c769SSteven Rostedt process_passed %current_config; 13580a05c769SSteven Rostedt return 0; 13590a05c769SSteven Rostedt } 13600a05c769SSteven Rostedt 13610a05c769SSteven Rostedt doprint "This config had a failure.\n"; 13620a05c769SSteven Rostedt doprint "Removing these configs that were not set in this config:\n"; 1363*f1a27850SSteven Rostedt doprint "config copied to $outputdir/config_bad\n"; 1364*f1a27850SSteven Rostedt run_command "cp -f $output_config $outputdir/config_bad"; 13650a05c769SSteven Rostedt 13660a05c769SSteven Rostedt # A config exists in this group that was bad. 13670a05c769SSteven Rostedt foreach my $config (keys %config_list) { 13680a05c769SSteven Rostedt if (!defined($current_config{$config})) { 13690a05c769SSteven Rostedt doprint " removing $config\n"; 13700a05c769SSteven Rostedt delete $config_list{$config}; 13710a05c769SSteven Rostedt } 13720a05c769SSteven Rostedt } 13730a05c769SSteven Rostedt 13740a05c769SSteven Rostedt @start_list = @tophalf; 13750a05c769SSteven Rostedt 13760a05c769SSteven Rostedt if ($#start_list == 0) { 13770a05c769SSteven Rostedt process_failed $start_list[0]; 13780a05c769SSteven Rostedt return 1; 13790a05c769SSteven Rostedt } 13800a05c769SSteven Rostedt 13810a05c769SSteven Rostedt # remove half the configs we are looking at and see if 13820a05c769SSteven Rostedt # they are good. 13830a05c769SSteven Rostedt $half = int($#start_list / 2); 13840a05c769SSteven Rostedt } while ($half > 0); 13850a05c769SSteven Rostedt 13860a05c769SSteven Rostedt # we found a single config, try it again 13870a05c769SSteven Rostedt my @tophalf = @start_list[0 .. 0]; 13880a05c769SSteven Rostedt 13890a05c769SSteven Rostedt $ret = run_config_bisect_test $type; 13900a05c769SSteven Rostedt if ($ret) { 13910a05c769SSteven Rostedt process_passed %current_config; 13920a05c769SSteven Rostedt return 0; 13930a05c769SSteven Rostedt } 13940a05c769SSteven Rostedt 13950a05c769SSteven Rostedt process_failed $start_list[0]; 13960a05c769SSteven Rostedt return 1; 13970a05c769SSteven Rostedt} 13980a05c769SSteven Rostedt 13990a05c769SSteven Rostedtsub config_bisect { 14000a05c769SSteven Rostedt my ($i) = @_; 14010a05c769SSteven Rostedt 14020a05c769SSteven Rostedt my $start_config = $opt{"CONFIG_BISECT[$i]"}; 14030a05c769SSteven Rostedt 14040a05c769SSteven Rostedt my $tmpconfig = "$tmpdir/use_config"; 14050a05c769SSteven Rostedt 14060a05c769SSteven Rostedt # Make the file with the bad config and the min config 14070a05c769SSteven Rostedt if (defined($minconfig)) { 14080a05c769SSteven Rostedt # read the min config for things to ignore 14090a05c769SSteven Rostedt run_command "cp $minconfig $tmpconfig" or 14100a05c769SSteven Rostedt dodie "failed to copy $minconfig to $tmpconfig"; 14110a05c769SSteven Rostedt } else { 14120a05c769SSteven Rostedt unlink $tmpconfig; 14130a05c769SSteven Rostedt } 14140a05c769SSteven Rostedt 14150a05c769SSteven Rostedt # Add other configs 14160a05c769SSteven Rostedt if (defined($addconfig)) { 14170a05c769SSteven Rostedt run_command "cat $addconfig >> $tmpconfig" or 14180a05c769SSteven Rostedt dodie "failed to append $addconfig"; 14190a05c769SSteven Rostedt } 14200a05c769SSteven Rostedt 14210a05c769SSteven Rostedt my $defconfig = ""; 14220a05c769SSteven Rostedt if (-f $tmpconfig) { 14230a05c769SSteven Rostedt $defconfig = "KCONFIG_ALLCONFIG=$tmpconfig"; 14240a05c769SSteven Rostedt process_config_ignore $tmpconfig; 14250a05c769SSteven Rostedt } 14260a05c769SSteven Rostedt 14270a05c769SSteven Rostedt # now process the start config 14280a05c769SSteven Rostedt run_command "cp $start_config $output_config" or 14290a05c769SSteven Rostedt dodie "failed to copy $start_config to $output_config"; 14300a05c769SSteven Rostedt 14310a05c769SSteven Rostedt # read directly what we want to check 14320a05c769SSteven Rostedt my %config_check; 14330a05c769SSteven Rostedt open (IN, $output_config) 14340a05c769SSteven Rostedt or dodie "faied to open $output_config"; 14350a05c769SSteven Rostedt 14360a05c769SSteven Rostedt while (<IN>) { 14370a05c769SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 14380a05c769SSteven Rostedt $config_check{$2} = $1; 14390a05c769SSteven Rostedt } 14400a05c769SSteven Rostedt } 14410a05c769SSteven Rostedt close(IN); 14420a05c769SSteven Rostedt 14430a05c769SSteven Rostedt # Now run oldconfig with the minconfig (and addconfigs) 14440a05c769SSteven Rostedt run_command "$defconfig $make oldnoconfig" or 14450a05c769SSteven Rostedt dodie "failed make config oldconfig"; 14460a05c769SSteven Rostedt 14470a05c769SSteven Rostedt # check to see what we lost (or gained) 14480a05c769SSteven Rostedt open (IN, $output_config) 14490a05c769SSteven Rostedt or dodie "Failed to read $start_config"; 14500a05c769SSteven Rostedt 14510a05c769SSteven Rostedt my %removed_configs; 14520a05c769SSteven Rostedt my %added_configs; 14530a05c769SSteven Rostedt 14540a05c769SSteven Rostedt while (<IN>) { 14550a05c769SSteven Rostedt if (/^((CONFIG\S*)=.*)/) { 14560a05c769SSteven Rostedt # save off all options 14570a05c769SSteven Rostedt $config_set{$2} = $1; 14580a05c769SSteven Rostedt if (defined($config_check{$2})) { 14590a05c769SSteven Rostedt if (defined($config_ignore{$2})) { 14600a05c769SSteven Rostedt $removed_configs{$2} = $1; 14610a05c769SSteven Rostedt } else { 14620a05c769SSteven Rostedt $config_list{$2} = $1; 14630a05c769SSteven Rostedt } 14640a05c769SSteven Rostedt } elsif (!defined($config_ignore{$2})) { 14650a05c769SSteven Rostedt $added_configs{$2} = $1; 14660a05c769SSteven Rostedt $config_list{$2} = $1; 14670a05c769SSteven Rostedt } 14680a05c769SSteven Rostedt } 14690a05c769SSteven Rostedt } 14700a05c769SSteven Rostedt close(IN); 14710a05c769SSteven Rostedt 14720a05c769SSteven Rostedt my @confs = keys %removed_configs; 14730a05c769SSteven Rostedt if ($#confs >= 0) { 14740a05c769SSteven Rostedt doprint "Configs overridden by default configs and removed from check:\n"; 14750a05c769SSteven Rostedt foreach my $config (@confs) { 14760a05c769SSteven Rostedt doprint " $config\n"; 14770a05c769SSteven Rostedt } 14780a05c769SSteven Rostedt } 14790a05c769SSteven Rostedt @confs = keys %added_configs; 14800a05c769SSteven Rostedt if ($#confs >= 0) { 14810a05c769SSteven Rostedt doprint "Configs appearing in make oldconfig and added:\n"; 14820a05c769SSteven Rostedt foreach my $config (@confs) { 14830a05c769SSteven Rostedt doprint " $config\n"; 14840a05c769SSteven Rostedt } 14850a05c769SSteven Rostedt } 14860a05c769SSteven Rostedt 14870a05c769SSteven Rostedt my %config_test; 14880a05c769SSteven Rostedt my $once = 0; 14890a05c769SSteven Rostedt 14900a05c769SSteven Rostedt # Sometimes kconfig does weird things. We must make sure 14910a05c769SSteven Rostedt # that the config we autocreate has everything we need 14920a05c769SSteven Rostedt # to test, otherwise we may miss testing configs, or 14930a05c769SSteven Rostedt # may not be able to create a new config. 14940a05c769SSteven Rostedt # Here we create a config with everything set. 14950a05c769SSteven Rostedt create_config (keys %config_list); 14960a05c769SSteven Rostedt read_current_config \%config_test; 14970a05c769SSteven Rostedt foreach my $config (keys %config_list) { 14980a05c769SSteven Rostedt if (!defined($config_test{$config})) { 14990a05c769SSteven Rostedt if (!$once) { 15000a05c769SSteven Rostedt $once = 1; 15010a05c769SSteven Rostedt doprint "Configs not produced by kconfig (will not be checked):\n"; 15020a05c769SSteven Rostedt } 15030a05c769SSteven Rostedt doprint " $config\n"; 15040a05c769SSteven Rostedt delete $config_list{$config}; 15050a05c769SSteven Rostedt } 15060a05c769SSteven Rostedt } 15070a05c769SSteven Rostedt my $ret; 15080a05c769SSteven Rostedt do { 15090a05c769SSteven Rostedt $ret = run_config_bisect; 15100a05c769SSteven Rostedt } while (!$ret); 15110a05c769SSteven Rostedt 15120a05c769SSteven Rostedt return $ret if ($ret < 0); 15135f9b6cedSSteven Rostedt 15145f9b6cedSSteven Rostedt success $i; 15155f9b6cedSSteven Rostedt} 15165f9b6cedSSteven Rostedt 15176c5ee0beSSteven Rostedtsub patchcheck { 15186c5ee0beSSteven Rostedt my ($i) = @_; 15196c5ee0beSSteven Rostedt 15206c5ee0beSSteven Rostedt die "PATCHCHECK_START[$i] not defined\n" 15216c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_START[$i]"})); 15226c5ee0beSSteven Rostedt die "PATCHCHECK_TYPE[$i] not defined\n" 15236c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 15246c5ee0beSSteven Rostedt 15256c5ee0beSSteven Rostedt my $start = $opt{"PATCHCHECK_START[$i]"}; 15266c5ee0beSSteven Rostedt 15276c5ee0beSSteven Rostedt my $end = "HEAD"; 15286c5ee0beSSteven Rostedt if (defined($opt{"PATCHCHECK_END[$i]"})) { 15296c5ee0beSSteven Rostedt $end = $opt{"PATCHCHECK_END[$i]"}; 15306c5ee0beSSteven Rostedt } 15316c5ee0beSSteven Rostedt 1532a57419b3SSteven Rostedt # Get the true sha1's since we can use things like HEAD~3 1533a57419b3SSteven Rostedt $start = get_sha1($start); 1534a57419b3SSteven Rostedt $end = get_sha1($end); 1535a57419b3SSteven Rostedt 15366c5ee0beSSteven Rostedt my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 15376c5ee0beSSteven Rostedt 15386c5ee0beSSteven Rostedt # Can't have a test without having a test to run 15396c5ee0beSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 15406c5ee0beSSteven Rostedt $type = "boot"; 15416c5ee0beSSteven Rostedt } 15426c5ee0beSSteven Rostedt 15436c5ee0beSSteven Rostedt open (IN, "git log --pretty=oneline $end|") or 15446c5ee0beSSteven Rostedt dodie "could not get git list"; 15456c5ee0beSSteven Rostedt 15466c5ee0beSSteven Rostedt my @list; 15476c5ee0beSSteven Rostedt 15486c5ee0beSSteven Rostedt while (<IN>) { 15496c5ee0beSSteven Rostedt chomp; 15506c5ee0beSSteven Rostedt $list[$#list+1] = $_; 15516c5ee0beSSteven Rostedt last if (/^$start/); 15526c5ee0beSSteven Rostedt } 15536c5ee0beSSteven Rostedt close(IN); 15546c5ee0beSSteven Rostedt 15556c5ee0beSSteven Rostedt if ($list[$#list] !~ /^$start/) { 15562b7d9b21SSteven Rostedt fail "SHA1 $start not found"; 15576c5ee0beSSteven Rostedt } 15586c5ee0beSSteven Rostedt 15596c5ee0beSSteven Rostedt # go backwards in the list 15606c5ee0beSSteven Rostedt @list = reverse @list; 15616c5ee0beSSteven Rostedt 15626c5ee0beSSteven Rostedt my $save_clean = $noclean; 15636c5ee0beSSteven Rostedt 15646c5ee0beSSteven Rostedt $in_patchcheck = 1; 15656c5ee0beSSteven Rostedt foreach my $item (@list) { 15666c5ee0beSSteven Rostedt my $sha1 = $item; 15676c5ee0beSSteven Rostedt $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 15686c5ee0beSSteven Rostedt 15696c5ee0beSSteven Rostedt doprint "\nProcessing commit $item\n\n"; 15706c5ee0beSSteven Rostedt 15716c5ee0beSSteven Rostedt run_command "git checkout $sha1" or 15726c5ee0beSSteven Rostedt die "Failed to checkout $sha1"; 15736c5ee0beSSteven Rostedt 15746c5ee0beSSteven Rostedt # only clean on the first and last patch 15756c5ee0beSSteven Rostedt if ($item eq $list[0] || 15766c5ee0beSSteven Rostedt $item eq $list[$#list]) { 15776c5ee0beSSteven Rostedt $noclean = $save_clean; 15786c5ee0beSSteven Rostedt } else { 15796c5ee0beSSteven Rostedt $noclean = 1; 15806c5ee0beSSteven Rostedt } 15816c5ee0beSSteven Rostedt 15826c5ee0beSSteven Rostedt if (defined($minconfig)) { 15832b7d9b21SSteven Rostedt build "useconfig:$minconfig" or return 0; 15846c5ee0beSSteven Rostedt } else { 15856c5ee0beSSteven Rostedt # ?? no config to use? 15862b7d9b21SSteven Rostedt build "oldconfig" or return 0; 15876c5ee0beSSteven Rostedt } 15886c5ee0beSSteven Rostedt 15892b7d9b21SSteven Rostedt check_buildlog $sha1 or return 0; 15906c5ee0beSSteven Rostedt 15916c5ee0beSSteven Rostedt next if ($type eq "build"); 15926c5ee0beSSteven Rostedt 15936c5ee0beSSteven Rostedt get_grub_index; 15946c5ee0beSSteven Rostedt get_version; 15956c5ee0beSSteven Rostedt install; 15966c5ee0beSSteven Rostedt 15977faafbd6SSteven Rostedt my $failed = 0; 15987faafbd6SSteven Rostedt 15997faafbd6SSteven Rostedt start_monitor; 16007faafbd6SSteven Rostedt monitor or $failed = 1; 16017faafbd6SSteven Rostedt 16027faafbd6SSteven Rostedt if (!$failed && $type ne "boot"){ 16037faafbd6SSteven Rostedt do_run_test or $failed = 1; 16047faafbd6SSteven Rostedt } 16057faafbd6SSteven Rostedt end_monitor; 16067faafbd6SSteven Rostedt return 0 if ($failed); 16077faafbd6SSteven Rostedt 16086c5ee0beSSteven Rostedt } 16096c5ee0beSSteven Rostedt $in_patchcheck = 0; 16106c5ee0beSSteven Rostedt success $i; 16112b7d9b21SSteven Rostedt 16122b7d9b21SSteven Rostedt return 1; 16136c5ee0beSSteven Rostedt} 16146c5ee0beSSteven Rostedt 16152545eb61SSteven Rostedtread_config $ARGV[0]; 16162545eb61SSteven Rostedt 16172545eb61SSteven Rostedt# mandatory configs 16182545eb61SSteven Rostedtdie "MACHINE not defined\n" if (!defined($opt{"MACHINE"})); 16192545eb61SSteven Rostedtdie "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"})); 16202545eb61SSteven Rostedtdie "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"})); 16212545eb61SSteven Rostedtdie "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"})); 16222545eb61SSteven Rostedtdie "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"})); 162375c3fda7SSteven Rostedtdie "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"})); 16242545eb61SSteven Rostedtdie "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"})); 16252545eb61SSteven Rostedtdie "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"})); 16262545eb61SSteven Rostedtdie "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"})); 16272545eb61SSteven Rostedt 16282b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 16292b7d9b21SSteven Rostedt unlink $opt{"LOG_FILE"}; 16302b7d9b21SSteven Rostedt} 16312545eb61SSteven Rostedt 16322b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 16332b7d9b21SSteven Rostedt 1634a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 1635a57419b3SSteven Rostedt 1636a57419b3SSteven Rostedt if (!$i) { 1637a57419b3SSteven Rostedt doprint "DEFAULT OPTIONS:\n"; 1638a57419b3SSteven Rostedt } else { 1639a57419b3SSteven Rostedt doprint "\nTEST $i OPTIONS"; 1640a57419b3SSteven Rostedt if (defined($repeat_tests{$i})) { 1641a57419b3SSteven Rostedt $repeat = $repeat_tests{$i}; 1642a57419b3SSteven Rostedt doprint " ITERATE $repeat"; 1643a57419b3SSteven Rostedt } 1644a57419b3SSteven Rostedt doprint "\n"; 1645a57419b3SSteven Rostedt } 1646a57419b3SSteven Rostedt 16472b7d9b21SSteven Rostedt foreach my $option (sort keys %opt) { 1648a57419b3SSteven Rostedt 1649a57419b3SSteven Rostedt if ($option =~ /\[(\d+)\]$/) { 1650a57419b3SSteven Rostedt next if ($i != $1); 1651a57419b3SSteven Rostedt } else { 1652a57419b3SSteven Rostedt next if ($i); 1653a57419b3SSteven Rostedt } 1654a57419b3SSteven Rostedt 16552b7d9b21SSteven Rostedt doprint "$option = $opt{$option}\n"; 16562b7d9b21SSteven Rostedt } 1657a57419b3SSteven Rostedt} 16582545eb61SSteven Rostedt 1659a75fececSSteven Rostedtsub set_test_option { 16605a391fbfSSteven Rostedt my ($name, $i) = @_; 16615a391fbfSSteven Rostedt 16625a391fbfSSteven Rostedt my $option = "$name\[$i\]"; 16635a391fbfSSteven Rostedt 16645a391fbfSSteven Rostedt if (defined($opt{$option})) { 16655a391fbfSSteven Rostedt return $opt{$option}; 16665a391fbfSSteven Rostedt } 16675a391fbfSSteven Rostedt 1668a57419b3SSteven Rostedt foreach my $test (keys %repeat_tests) { 1669a57419b3SSteven Rostedt if ($i >= $test && 1670a57419b3SSteven Rostedt $i < $test + $repeat_tests{$test}) { 1671a57419b3SSteven Rostedt $option = "$name\[$test\]"; 1672a57419b3SSteven Rostedt if (defined($opt{$option})) { 1673a57419b3SSteven Rostedt return $opt{$option}; 1674a57419b3SSteven Rostedt } 1675a57419b3SSteven Rostedt } 1676a57419b3SSteven Rostedt } 1677a57419b3SSteven Rostedt 16785a391fbfSSteven Rostedt if (defined($opt{$name})) { 16795a391fbfSSteven Rostedt return $opt{$name}; 16805a391fbfSSteven Rostedt } 16815a391fbfSSteven Rostedt 16825a391fbfSSteven Rostedt return undef; 16835a391fbfSSteven Rostedt} 16845a391fbfSSteven Rostedt 16852545eb61SSteven Rostedt# First we need to do is the builds 1686a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 16872545eb61SSteven Rostedt 1688576f627cSSteven Rostedt $iteration = $i; 1689576f627cSSteven Rostedt 1690a75fececSSteven Rostedt my $makecmd = set_test_option("MAKE_CMD", $i); 1691a75fececSSteven Rostedt 1692a75fececSSteven Rostedt $machine = set_test_option("MACHINE", $i); 1693e48c5293SSteven Rostedt $ssh_user = set_test_option("SSH_USER", $i); 1694a75fececSSteven Rostedt $tmpdir = set_test_option("TMP_DIR", $i); 1695a75fececSSteven Rostedt $outputdir = set_test_option("OUTPUT_DIR", $i); 1696a75fececSSteven Rostedt $builddir = set_test_option("BUILD_DIR", $i); 1697a75fececSSteven Rostedt $test_type = set_test_option("TEST_TYPE", $i); 1698a75fececSSteven Rostedt $build_type = set_test_option("BUILD_TYPE", $i); 1699a75fececSSteven Rostedt $build_options = set_test_option("BUILD_OPTIONS", $i); 1700a75fececSSteven Rostedt $power_cycle = set_test_option("POWER_CYCLE", $i); 1701e48c5293SSteven Rostedt $reboot = set_test_option("REBOOT", $i); 1702a75fececSSteven Rostedt $noclean = set_test_option("BUILD_NOCLEAN", $i); 1703a75fececSSteven Rostedt $minconfig = set_test_option("MIN_CONFIG", $i); 1704a75fececSSteven Rostedt $run_test = set_test_option("TEST", $i); 1705a75fececSSteven Rostedt $addconfig = set_test_option("ADD_CONFIG", $i); 1706a75fececSSteven Rostedt $reboot_type = set_test_option("REBOOT_TYPE", $i); 1707a75fececSSteven Rostedt $grub_menu = set_test_option("GRUB_MENU", $i); 17088b37ca8cSSteven Rostedt $post_install = set_test_option("POST_INSTALL", $i); 1709a75fececSSteven Rostedt $reboot_script = set_test_option("REBOOT_SCRIPT", $i); 1710a75fececSSteven Rostedt $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); 1711a75fececSSteven Rostedt $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); 1712a75fececSSteven Rostedt $die_on_failure = set_test_option("DIE_ON_FAILURE", $i); 1713a75fececSSteven Rostedt $power_off = set_test_option("POWER_OFF", $i); 1714576f627cSSteven Rostedt $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i); 1715576f627cSSteven Rostedt $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i); 1716a75fececSSteven Rostedt $sleep_time = set_test_option("SLEEP_TIME", $i); 1717a75fececSSteven Rostedt $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 1718a75fececSSteven Rostedt $store_failures = set_test_option("STORE_FAILURES", $i); 1719a75fececSSteven Rostedt $timeout = set_test_option("TIMEOUT", $i); 1720a75fececSSteven Rostedt $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 1721a75fececSSteven Rostedt $console = set_test_option("CONSOLE", $i); 1722a75fececSSteven Rostedt $success_line = set_test_option("SUCCESS_LINE", $i); 17231c8a617aSSteven Rostedt $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); 17241c8a617aSSteven Rostedt $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); 1725a75fececSSteven Rostedt $build_target = set_test_option("BUILD_TARGET", $i); 1726e48c5293SSteven Rostedt $ssh_exec = set_test_option("SSH_EXEC", $i); 1727e48c5293SSteven Rostedt $scp_to_target = set_test_option("SCP_TO_TARGET", $i); 1728a75fececSSteven Rostedt $target_image = set_test_option("TARGET_IMAGE", $i); 1729a75fececSSteven Rostedt $localversion = set_test_option("LOCALVERSION", $i); 1730a75fececSSteven Rostedt 1731a75fececSSteven Rostedt chdir $builddir || die "can't change directory to $builddir"; 1732a75fececSSteven Rostedt 1733a75fececSSteven Rostedt if (!-d $tmpdir) { 1734a75fececSSteven Rostedt mkpath($tmpdir) or 1735a75fececSSteven Rostedt die "can't create $tmpdir"; 1736a75fececSSteven Rostedt } 1737a75fececSSteven Rostedt 1738e48c5293SSteven Rostedt $ENV{"SSH_USER"} = $ssh_user; 1739e48c5293SSteven Rostedt $ENV{"MACHINE"} = $machine; 1740e48c5293SSteven Rostedt 1741a75fececSSteven Rostedt $target = "$ssh_user\@$machine"; 1742a75fececSSteven Rostedt 1743a75fececSSteven Rostedt $buildlog = "$tmpdir/buildlog-$machine"; 1744a75fececSSteven Rostedt $dmesg = "$tmpdir/dmesg-$machine"; 1745a75fececSSteven Rostedt $make = "$makecmd O=$outputdir"; 174651ad1dd1SSteven Rostedt $output_config = "$outputdir/.config"; 1747a75fececSSteven Rostedt 1748a75fececSSteven Rostedt if ($reboot_type eq "grub") { 1749576f627cSSteven Rostedt dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 1750a75fececSSteven Rostedt } elsif (!defined($reboot_script)) { 1751576f627cSSteven Rostedt dodie "REBOOT_SCRIPT not defined" 1752a75fececSSteven Rostedt } 1753a75fececSSteven Rostedt 1754a75fececSSteven Rostedt my $run_type = $build_type; 1755a75fececSSteven Rostedt if ($test_type eq "patchcheck") { 1756a75fececSSteven Rostedt $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 1757a75fececSSteven Rostedt } elsif ($test_type eq "bisect") { 1758a75fececSSteven Rostedt $run_type = $opt{"BISECT_TYPE[$i]"}; 17590a05c769SSteven Rostedt } elsif ($test_type eq "config_bisect") { 17600a05c769SSteven Rostedt $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; 1761a75fececSSteven Rostedt } 1762a75fececSSteven Rostedt 1763a75fececSSteven Rostedt # mistake in config file? 1764a75fececSSteven Rostedt if (!defined($run_type)) { 1765a75fececSSteven Rostedt $run_type = "ERROR"; 1766a75fececSSteven Rostedt } 17672545eb61SSteven Rostedt 17682545eb61SSteven Rostedt doprint "\n\n"; 1769a75fececSSteven Rostedt doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n"; 17707faafbd6SSteven Rostedt 17717faafbd6SSteven Rostedt unlink $dmesg; 17727faafbd6SSteven Rostedt unlink $buildlog; 17732545eb61SSteven Rostedt 17742b7d9b21SSteven Rostedt if (!defined($minconfig)) { 17752b7d9b21SSteven Rostedt $minconfig = $addconfig; 17762b7d9b21SSteven Rostedt 17772b7d9b21SSteven Rostedt } elsif (defined($addconfig)) { 17789be2e6b5SSteven Rostedt run_command "cat $addconfig $minconfig > $tmpdir/add_config" or 17792b7d9b21SSteven Rostedt dodie "Failed to create temp config"; 17809be2e6b5SSteven Rostedt $minconfig = "$tmpdir/add_config"; 17812b7d9b21SSteven Rostedt } 17822b7d9b21SSteven Rostedt 17836c5ee0beSSteven Rostedt my $checkout = $opt{"CHECKOUT[$i]"}; 17846c5ee0beSSteven Rostedt if (defined($checkout)) { 17856c5ee0beSSteven Rostedt run_command "git checkout $checkout" or 17866c5ee0beSSteven Rostedt die "failed to checkout $checkout"; 17876c5ee0beSSteven Rostedt } 17886c5ee0beSSteven Rostedt 1789a75fececSSteven Rostedt if ($test_type eq "bisect") { 17905f9b6cedSSteven Rostedt bisect $i; 17915f9b6cedSSteven Rostedt next; 17920a05c769SSteven Rostedt } elsif ($test_type eq "config_bisect") { 17930a05c769SSteven Rostedt config_bisect $i; 17940a05c769SSteven Rostedt next; 1795a75fececSSteven Rostedt } elsif ($test_type eq "patchcheck") { 17966c5ee0beSSteven Rostedt patchcheck $i; 17976c5ee0beSSteven Rostedt next; 17985f9b6cedSSteven Rostedt } 17995f9b6cedSSteven Rostedt 18007faafbd6SSteven Rostedt if ($build_type ne "nobuild") { 18017faafbd6SSteven Rostedt build $build_type or next; 18022545eb61SSteven Rostedt } 18032545eb61SSteven Rostedt 1804a75fececSSteven Rostedt if ($test_type ne "build") { 18055f9b6cedSSteven Rostedt get_grub_index; 18065f9b6cedSSteven Rostedt get_version; 18072545eb61SSteven Rostedt install; 18085a391fbfSSteven Rostedt 18097faafbd6SSteven Rostedt my $failed = 0; 18107faafbd6SSteven Rostedt start_monitor; 18117faafbd6SSteven Rostedt monitor or $failed = 1;; 1812a75fececSSteven Rostedt 1813a75fececSSteven Rostedt if (!$failed && $test_type ne "boot" && defined($run_test)) { 18147faafbd6SSteven Rostedt do_run_test or $failed = 1; 18155a391fbfSSteven Rostedt } 18167faafbd6SSteven Rostedt end_monitor; 18177faafbd6SSteven Rostedt next if ($failed); 1818a75fececSSteven Rostedt } 18195a391fbfSSteven Rostedt 18205f9b6cedSSteven Rostedt success $i; 182175c3fda7SSteven Rostedt} 18222545eb61SSteven Rostedt 18235c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) { 182475c3fda7SSteven Rostedt halt; 1825576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { 182675c3fda7SSteven Rostedt reboot; 18275c42fc5bSSteven Rostedt} 182875c3fda7SSteven Rostedt 1829e48c5293SSteven Rostedtdoprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 1830e48c5293SSteven Rostedt 18312545eb61SSteven Rostedtexit 0; 1832