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 14*e48c5293SSteven Rostedtmy $VERSION = "0.2"; 15*e48c5293SSteven Rostedt 16*e48c5293SSteven 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; 45*e48c5293SSteven Rostedt$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND"; 46*e48c5293SSteven Rostedt$default{"SCP_TO_TARGET"} = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE"; 47*e48c5293SSteven Rostedt$default{"REBOOT"} = "ssh \$SSH_USER\@\$MACHINE reboot"; 482545eb61SSteven Rostedt 492545eb61SSteven Rostedtmy $version; 50a75fececSSteven Rostedtmy $machine; 51*e48c5293SSteven Rostedtmy $ssh_user; 52a75fececSSteven Rostedtmy $tmpdir; 53a75fececSSteven Rostedtmy $builddir; 54a75fececSSteven Rostedtmy $outputdir; 5551ad1dd1SSteven Rostedtmy $output_config; 56a75fececSSteven Rostedtmy $test_type; 577faafbd6SSteven Rostedtmy $build_type; 58a75fececSSteven Rostedtmy $build_options; 59a75fececSSteven Rostedtmy $reboot_type; 60a75fececSSteven Rostedtmy $reboot_script; 61a75fececSSteven Rostedtmy $power_cycle; 62*e48c5293SSteven Rostedtmy $reboot; 63a75fececSSteven Rostedtmy $reboot_on_error; 64a75fececSSteven Rostedtmy $poweroff_on_error; 65a75fececSSteven Rostedtmy $die_on_failure; 66576f627cSSteven Rostedtmy $powercycle_after_reboot; 67576f627cSSteven Rostedtmy $poweroff_after_halt; 68*e48c5293SSteven Rostedtmy $ssh_exec; 69*e48c5293SSteven Rostedtmy $scp_to_target; 70a75fececSSteven Rostedtmy $power_off; 71a75fececSSteven Rostedtmy $grub_menu; 722545eb61SSteven Rostedtmy $grub_number; 732545eb61SSteven Rostedtmy $target; 742545eb61SSteven Rostedtmy $make; 758b37ca8cSSteven Rostedtmy $post_install; 765c42fc5bSSteven Rostedtmy $noclean; 775f9b6cedSSteven Rostedtmy $minconfig; 782b7d9b21SSteven Rostedtmy $addconfig; 795f9b6cedSSteven Rostedtmy $in_bisect = 0; 805f9b6cedSSteven Rostedtmy $bisect_bad = ""; 81d6ce2a0bSSteven Rostedtmy $reverse_bisect; 826c5ee0beSSteven Rostedtmy $in_patchcheck = 0; 835a391fbfSSteven Rostedtmy $run_test; 846c5ee0beSSteven Rostedtmy $redirect; 857faafbd6SSteven Rostedtmy $buildlog; 867faafbd6SSteven Rostedtmy $dmesg; 877faafbd6SSteven Rostedtmy $monitor_fp; 887faafbd6SSteven Rostedtmy $monitor_pid; 897faafbd6SSteven Rostedtmy $monitor_cnt = 0; 90a75fececSSteven Rostedtmy $sleep_time; 91a75fececSSteven Rostedtmy $bisect_sleep_time; 92a75fececSSteven Rostedtmy $store_failures; 93a75fececSSteven Rostedtmy $timeout; 94a75fececSSteven Rostedtmy $booted_timeout; 95a75fececSSteven Rostedtmy $console; 96a75fececSSteven Rostedtmy $success_line; 97a75fececSSteven Rostedtmy $build_target; 98a75fececSSteven Rostedtmy $target_image; 99a75fececSSteven Rostedtmy $localversion; 100576f627cSSteven Rostedtmy $iteration = 0; 101*e48c5293SSteven Rostedtmy $successes = 0; 1022545eb61SSteven Rostedt 103a57419b3SSteven Rostedtsub set_value { 104a57419b3SSteven Rostedt my ($lvalue, $rvalue) = @_; 1052545eb61SSteven Rostedt 106a75fececSSteven Rostedt if (defined($opt{$lvalue})) { 107a75fececSSteven Rostedt die "Error: Option $lvalue defined more than once!\n"; 108a75fececSSteven Rostedt } 1092545eb61SSteven Rostedt $opt{$lvalue} = $rvalue; 11021a9679fSSteven Rostedt if ($rvalue =~ /^\s*$/) { 11121a9679fSSteven Rostedt delete $opt{$lvalue}; 11221a9679fSSteven Rostedt } else { 11321a9679fSSteven Rostedt $opt{$lvalue} = $rvalue; 11421a9679fSSteven Rostedt } 1152545eb61SSteven Rostedt} 116a57419b3SSteven Rostedt 117a57419b3SSteven Rostedtsub read_config { 118a57419b3SSteven Rostedt my ($config) = @_; 119a57419b3SSteven Rostedt 120a57419b3SSteven Rostedt open(IN, $config) || die "can't read file $config"; 121a57419b3SSteven Rostedt 122a57419b3SSteven Rostedt my $name = $config; 123a57419b3SSteven Rostedt $name =~ s,.*/(.*),$1,; 124a57419b3SSteven Rostedt 125a57419b3SSteven Rostedt my $test_num = 0; 126a57419b3SSteven Rostedt my $default = 1; 127a57419b3SSteven Rostedt my $repeat = 1; 128a57419b3SSteven Rostedt my $num_tests_set = 0; 129a57419b3SSteven Rostedt my $skip = 0; 130a57419b3SSteven Rostedt my $rest; 131a57419b3SSteven Rostedt 132a57419b3SSteven Rostedt while (<IN>) { 133a57419b3SSteven Rostedt 134a57419b3SSteven Rostedt # ignore blank lines and comments 135a57419b3SSteven Rostedt next if (/^\s*$/ || /\s*\#/); 136a57419b3SSteven Rostedt 137a57419b3SSteven Rostedt if (/^\s*TEST_START(.*)/) { 138a57419b3SSteven Rostedt 139a57419b3SSteven Rostedt $rest = $1; 140a57419b3SSteven Rostedt 141a57419b3SSteven Rostedt if ($num_tests_set) { 142a57419b3SSteven Rostedt die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 143a57419b3SSteven Rostedt } 144a57419b3SSteven Rostedt 145a57419b3SSteven Rostedt my $old_test_num = $test_num; 146*e48c5293SSteven Rostedt my $old_repeat = $repeat; 147a57419b3SSteven Rostedt 148a57419b3SSteven Rostedt $test_num += $repeat; 149a57419b3SSteven Rostedt $default = 0; 150a57419b3SSteven Rostedt $repeat = 1; 151a57419b3SSteven Rostedt 152a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 153a57419b3SSteven Rostedt $rest = $1; 154a57419b3SSteven Rostedt $skip = 1; 155a57419b3SSteven Rostedt } else { 156a57419b3SSteven Rostedt $skip = 0; 157a57419b3SSteven Rostedt } 158a57419b3SSteven Rostedt 159a57419b3SSteven Rostedt if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) { 160a57419b3SSteven Rostedt $repeat = $1; 161a57419b3SSteven Rostedt $rest = $2; 162a57419b3SSteven Rostedt $repeat_tests{"$test_num"} = $repeat; 163a57419b3SSteven Rostedt } 164a57419b3SSteven Rostedt 165a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 166a57419b3SSteven Rostedt $rest = $1; 167a57419b3SSteven Rostedt $skip = 1; 168a57419b3SSteven Rostedt } 169a57419b3SSteven Rostedt 170a57419b3SSteven Rostedt if ($rest !~ /^\s*$/) { 171a57419b3SSteven Rostedt die "$name: $.: Gargbage found after TEST_START\n$_"; 172a57419b3SSteven Rostedt } 173a57419b3SSteven Rostedt 174a57419b3SSteven Rostedt if ($skip) { 175a57419b3SSteven Rostedt $test_num = $old_test_num; 176*e48c5293SSteven Rostedt $repeat = $old_repeat; 177a57419b3SSteven Rostedt } 178a57419b3SSteven Rostedt 179a57419b3SSteven Rostedt } elsif (/^\s*DEFAULTS(.*)$/) { 180a57419b3SSteven Rostedt $default = 1; 181a57419b3SSteven Rostedt 182a57419b3SSteven Rostedt $rest = $1; 183a57419b3SSteven Rostedt 184a57419b3SSteven Rostedt if ($rest =~ /\s+SKIP(.*)/) { 185a57419b3SSteven Rostedt $rest = $1; 186a57419b3SSteven Rostedt $skip = 1; 187a57419b3SSteven Rostedt } else { 188a57419b3SSteven Rostedt $skip = 0; 189a57419b3SSteven Rostedt } 190a57419b3SSteven Rostedt 191a57419b3SSteven Rostedt if ($rest !~ /^\s*$/) { 192a57419b3SSteven Rostedt die "$name: $.: Gargbage found after DEFAULTS\n$_"; 193a57419b3SSteven Rostedt } 194a57419b3SSteven Rostedt 195a57419b3SSteven Rostedt } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { 196a57419b3SSteven Rostedt 197a57419b3SSteven Rostedt next if ($skip); 198a57419b3SSteven Rostedt 199a57419b3SSteven Rostedt my $lvalue = $1; 200a57419b3SSteven Rostedt my $rvalue = $2; 201a57419b3SSteven Rostedt 202a57419b3SSteven Rostedt if (!$default && 203a57419b3SSteven Rostedt ($lvalue eq "NUM_TESTS" || 204a57419b3SSteven Rostedt $lvalue eq "LOG_FILE" || 205a57419b3SSteven Rostedt $lvalue eq "CLEAR_LOG")) { 206a57419b3SSteven Rostedt die "$name: $.: $lvalue must be set in DEFAULTS section\n"; 207a57419b3SSteven Rostedt } 208a57419b3SSteven Rostedt 209a57419b3SSteven Rostedt if ($lvalue eq "NUM_TESTS") { 210a57419b3SSteven Rostedt if ($test_num) { 211a57419b3SSteven Rostedt die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; 212a57419b3SSteven Rostedt } 213a57419b3SSteven Rostedt if (!$default) { 214a57419b3SSteven Rostedt die "$name: $.: NUM_TESTS must be set in default section\n"; 215a57419b3SSteven Rostedt } 216a57419b3SSteven Rostedt $num_tests_set = 1; 217a57419b3SSteven Rostedt } 218a57419b3SSteven Rostedt 219a57419b3SSteven Rostedt if ($default || $lvalue =~ /\[\d+\]$/) { 220a57419b3SSteven Rostedt set_value($lvalue, $rvalue); 221a57419b3SSteven Rostedt } else { 222a57419b3SSteven Rostedt my $val = "$lvalue\[$test_num\]"; 223a57419b3SSteven Rostedt set_value($val, $rvalue); 224a57419b3SSteven Rostedt 225a57419b3SSteven Rostedt if ($repeat > 1) { 226a57419b3SSteven Rostedt $repeats{$val} = $repeat; 227a57419b3SSteven Rostedt } 228a57419b3SSteven Rostedt } 229a57419b3SSteven Rostedt } else { 230a57419b3SSteven Rostedt die "$name: $.: Garbage found in config\n$_"; 231a57419b3SSteven Rostedt } 2322545eb61SSteven Rostedt } 2332545eb61SSteven Rostedt 2342545eb61SSteven Rostedt close(IN); 235a75fececSSteven Rostedt 236a57419b3SSteven Rostedt if ($test_num) { 237a57419b3SSteven Rostedt $test_num += $repeat - 1; 238a57419b3SSteven Rostedt $opt{"NUM_TESTS"} = $test_num; 239a57419b3SSteven Rostedt } 240a57419b3SSteven Rostedt 241a75fececSSteven Rostedt # set any defaults 242a75fececSSteven Rostedt 243a75fececSSteven Rostedt foreach my $default (keys %default) { 244a75fececSSteven Rostedt if (!defined($opt{$default})) { 245a75fececSSteven Rostedt $opt{$default} = $default{$default}; 246a75fececSSteven Rostedt } 247a75fececSSteven Rostedt } 2482545eb61SSteven Rostedt} 2492545eb61SSteven Rostedt 250d1e2f22aSSteven Rostedtsub _logit { 2512545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 2522545eb61SSteven Rostedt open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 2532545eb61SSteven Rostedt print OUT @_; 2542545eb61SSteven Rostedt close(OUT); 2552545eb61SSteven Rostedt } 2562545eb61SSteven Rostedt} 2572545eb61SSteven Rostedt 258d1e2f22aSSteven Rostedtsub logit { 259d1e2f22aSSteven Rostedt if (defined($opt{"LOG_FILE"})) { 260d1e2f22aSSteven Rostedt _logit @_; 261d1e2f22aSSteven Rostedt } else { 262d1e2f22aSSteven Rostedt print @_; 263d1e2f22aSSteven Rostedt } 264d1e2f22aSSteven Rostedt} 265d1e2f22aSSteven Rostedt 2665f9b6cedSSteven Rostedtsub doprint { 2675f9b6cedSSteven Rostedt print @_; 268d1e2f22aSSteven Rostedt _logit @_; 2695f9b6cedSSteven Rostedt} 2705f9b6cedSSteven Rostedt 2717faafbd6SSteven Rostedtsub run_command; 2727faafbd6SSteven Rostedt 2737faafbd6SSteven Rostedtsub reboot { 2747faafbd6SSteven Rostedt # try to reboot normally 275*e48c5293SSteven Rostedt if (run_command $reboot) { 276576f627cSSteven Rostedt if (defined($powercycle_after_reboot)) { 277576f627cSSteven Rostedt sleep $powercycle_after_reboot; 278576f627cSSteven Rostedt run_command "$power_cycle"; 279576f627cSSteven Rostedt } 280576f627cSSteven Rostedt } else { 2817faafbd6SSteven Rostedt # nope? power cycle it. 282a75fececSSteven Rostedt run_command "$power_cycle"; 2837faafbd6SSteven Rostedt } 2847faafbd6SSteven Rostedt} 2857faafbd6SSteven Rostedt 286576f627cSSteven Rostedtsub do_not_reboot { 287576f627cSSteven Rostedt my $i = $iteration; 288576f627cSSteven Rostedt 289576f627cSSteven Rostedt return $test_type eq "build" || 290576f627cSSteven Rostedt ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || 291576f627cSSteven Rostedt ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); 292576f627cSSteven Rostedt} 293576f627cSSteven Rostedt 2945c42fc5bSSteven Rostedtsub dodie { 2955a391fbfSSteven Rostedt doprint "CRITICAL FAILURE... ", @_, "\n"; 2965c42fc5bSSteven Rostedt 297576f627cSSteven Rostedt my $i = $iteration; 298576f627cSSteven Rostedt 299576f627cSSteven Rostedt if ($reboot_on_error && !do_not_reboot) { 300576f627cSSteven Rostedt 30175c3fda7SSteven Rostedt doprint "REBOOTING\n"; 3027faafbd6SSteven Rostedt reboot; 30375c3fda7SSteven Rostedt 304a75fececSSteven Rostedt } elsif ($poweroff_on_error && defined($power_off)) { 3055c42fc5bSSteven Rostedt doprint "POWERING OFF\n"; 306a75fececSSteven Rostedt `$power_off`; 3075c42fc5bSSteven Rostedt } 30875c3fda7SSteven Rostedt 309576f627cSSteven Rostedt die @_, "\n"; 3105c42fc5bSSteven Rostedt} 3115c42fc5bSSteven Rostedt 3127faafbd6SSteven Rostedtsub open_console { 3137faafbd6SSteven Rostedt my ($fp) = @_; 3147faafbd6SSteven Rostedt 3157faafbd6SSteven Rostedt my $flags; 3167faafbd6SSteven Rostedt 317a75fececSSteven Rostedt my $pid = open($fp, "$console|") or 318a75fececSSteven Rostedt dodie "Can't open console $console"; 3197faafbd6SSteven Rostedt 3207faafbd6SSteven Rostedt $flags = fcntl($fp, F_GETFL, 0) or 321576f627cSSteven Rostedt dodie "Can't get flags for the socket: $!"; 3227faafbd6SSteven Rostedt $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 323576f627cSSteven Rostedt dodie "Can't set flags for the socket: $!"; 3247faafbd6SSteven Rostedt 3257faafbd6SSteven Rostedt return $pid; 3267faafbd6SSteven Rostedt} 3277faafbd6SSteven Rostedt 3287faafbd6SSteven Rostedtsub close_console { 3297faafbd6SSteven Rostedt my ($fp, $pid) = @_; 3307faafbd6SSteven Rostedt 3317faafbd6SSteven Rostedt doprint "kill child process $pid\n"; 3327faafbd6SSteven Rostedt kill 2, $pid; 3337faafbd6SSteven Rostedt 3347faafbd6SSteven Rostedt print "closing!\n"; 3357faafbd6SSteven Rostedt close($fp); 3367faafbd6SSteven Rostedt} 3377faafbd6SSteven Rostedt 3387faafbd6SSteven Rostedtsub start_monitor { 3397faafbd6SSteven Rostedt if ($monitor_cnt++) { 3407faafbd6SSteven Rostedt return; 3417faafbd6SSteven Rostedt } 3427faafbd6SSteven Rostedt $monitor_fp = \*MONFD; 3437faafbd6SSteven Rostedt $monitor_pid = open_console $monitor_fp; 344a75fececSSteven Rostedt 345a75fececSSteven Rostedt return; 346a75fececSSteven Rostedt 347a75fececSSteven Rostedt open(MONFD, "Stop perl from warning about single use of MONFD"); 3487faafbd6SSteven Rostedt} 3497faafbd6SSteven Rostedt 3507faafbd6SSteven Rostedtsub end_monitor { 3517faafbd6SSteven Rostedt if (--$monitor_cnt) { 3527faafbd6SSteven Rostedt return; 3537faafbd6SSteven Rostedt } 3547faafbd6SSteven Rostedt close_console($monitor_fp, $monitor_pid); 3557faafbd6SSteven Rostedt} 3567faafbd6SSteven Rostedt 3577faafbd6SSteven Rostedtsub wait_for_monitor { 3587faafbd6SSteven Rostedt my ($time) = @_; 3597faafbd6SSteven Rostedt my $line; 3607faafbd6SSteven Rostedt 361a75fececSSteven Rostedt doprint "** Wait for monitor to settle down **\n"; 3627faafbd6SSteven Rostedt 3637faafbd6SSteven Rostedt # read the monitor and wait for the system to calm down 3647faafbd6SSteven Rostedt do { 3657faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 366a75fececSSteven Rostedt print "$line" if (defined($line)); 3677faafbd6SSteven Rostedt } while (defined($line)); 368a75fececSSteven Rostedt print "** Monitor flushed **\n"; 3697faafbd6SSteven Rostedt} 3707faafbd6SSteven Rostedt 3712b7d9b21SSteven Rostedtsub fail { 3722b7d9b21SSteven Rostedt 373a75fececSSteven Rostedt if ($die_on_failure) { 3742b7d9b21SSteven Rostedt dodie @_; 3752b7d9b21SSteven Rostedt } 3762b7d9b21SSteven Rostedt 377a75fececSSteven Rostedt doprint "FAILED\n"; 3787faafbd6SSteven Rostedt 379576f627cSSteven Rostedt my $i = $iteration; 380576f627cSSteven Rostedt 381a75fececSSteven Rostedt # no need to reboot for just building. 382576f627cSSteven Rostedt if (!do_not_reboot) { 3837faafbd6SSteven Rostedt doprint "REBOOTING\n"; 3847faafbd6SSteven Rostedt reboot; 3857faafbd6SSteven Rostedt start_monitor; 386a75fececSSteven Rostedt wait_for_monitor $sleep_time; 3877faafbd6SSteven Rostedt end_monitor; 388a75fececSSteven Rostedt } 3897faafbd6SSteven Rostedt 390576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 391576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 3927a849cd9SSteven Rostedt doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n"; 393576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 394576f627cSSteven Rostedt doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 395a75fececSSteven Rostedt 396a75fececSSteven Rostedt return 1 if (!defined($store_failures)); 3977faafbd6SSteven Rostedt 3987faafbd6SSteven Rostedt my @t = localtime; 3997faafbd6SSteven Rostedt my $date = sprintf "%04d%02d%02d%02d%02d%02d", 4007faafbd6SSteven Rostedt 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 4017faafbd6SSteven Rostedt 402a75fececSSteven Rostedt my $dir = "$machine-$test_type-$build_type-fail-$date"; 403a75fececSSteven Rostedt my $faildir = "$store_failures/$dir"; 4047faafbd6SSteven Rostedt 4057faafbd6SSteven Rostedt if (!-d $faildir) { 4067faafbd6SSteven Rostedt mkpath($faildir) or 407a75fececSSteven Rostedt die "can't create $faildir"; 4087faafbd6SSteven Rostedt } 40951ad1dd1SSteven Rostedt if (-f "$output_config") { 41051ad1dd1SSteven Rostedt cp "$output_config", "$faildir/config" or 4117faafbd6SSteven Rostedt die "failed to copy .config"; 4127faafbd6SSteven Rostedt } 4137faafbd6SSteven Rostedt if (-f $buildlog) { 4147faafbd6SSteven Rostedt cp $buildlog, "$faildir/buildlog" or 4157faafbd6SSteven Rostedt die "failed to move $buildlog"; 4167faafbd6SSteven Rostedt } 4177faafbd6SSteven Rostedt if (-f $dmesg) { 4187faafbd6SSteven Rostedt cp $dmesg, "$faildir/dmesg" or 4197faafbd6SSteven Rostedt die "failed to move $dmesg"; 4207faafbd6SSteven Rostedt } 4217faafbd6SSteven Rostedt 4227faafbd6SSteven Rostedt doprint "*** Saved info to $faildir ***\n"; 4237faafbd6SSteven Rostedt 4242b7d9b21SSteven Rostedt return 1; 4252b7d9b21SSteven Rostedt} 4262b7d9b21SSteven Rostedt 4272545eb61SSteven Rostedtsub run_command { 4282545eb61SSteven Rostedt my ($command) = @_; 429d6ce2a0bSSteven Rostedt my $dolog = 0; 430d6ce2a0bSSteven Rostedt my $dord = 0; 431d6ce2a0bSSteven Rostedt my $pid; 432d6ce2a0bSSteven Rostedt 433*e48c5293SSteven Rostedt $command =~ s/\$SSH_USER/$ssh_user/g; 434*e48c5293SSteven Rostedt $command =~ s/\$MACHINE/$machine/g; 435*e48c5293SSteven Rostedt 436d6ce2a0bSSteven Rostedt doprint("$command ... "); 437d6ce2a0bSSteven Rostedt 438d6ce2a0bSSteven Rostedt $pid = open(CMD, "$command 2>&1 |") or 4392b7d9b21SSteven Rostedt (fail "unable to exec $command" and return 0); 4402545eb61SSteven Rostedt 4412545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 442d6ce2a0bSSteven Rostedt open(LOG, ">>$opt{LOG_FILE}") or 443d6ce2a0bSSteven Rostedt dodie "failed to write to log"; 444d6ce2a0bSSteven Rostedt $dolog = 1; 4456c5ee0beSSteven Rostedt } 4466c5ee0beSSteven Rostedt 4476c5ee0beSSteven Rostedt if (defined($redirect)) { 448d6ce2a0bSSteven Rostedt open (RD, ">$redirect") or 449d6ce2a0bSSteven Rostedt dodie "failed to write to redirect $redirect"; 450d6ce2a0bSSteven Rostedt $dord = 1; 4512545eb61SSteven Rostedt } 4522545eb61SSteven Rostedt 453d6ce2a0bSSteven Rostedt while (<CMD>) { 454d6ce2a0bSSteven Rostedt print LOG if ($dolog); 455d6ce2a0bSSteven Rostedt print RD if ($dord); 456d6ce2a0bSSteven Rostedt } 4572545eb61SSteven Rostedt 458d6ce2a0bSSteven Rostedt waitpid($pid, 0); 4592545eb61SSteven Rostedt my $failed = $?; 4602545eb61SSteven Rostedt 461d6ce2a0bSSteven Rostedt close(CMD); 462d6ce2a0bSSteven Rostedt close(LOG) if ($dolog); 463d6ce2a0bSSteven Rostedt close(RD) if ($dord); 464d6ce2a0bSSteven Rostedt 4652545eb61SSteven Rostedt if ($failed) { 4662545eb61SSteven Rostedt doprint "FAILED!\n"; 4672545eb61SSteven Rostedt } else { 4682545eb61SSteven Rostedt doprint "SUCCESS\n"; 4692545eb61SSteven Rostedt } 4702545eb61SSteven Rostedt 4715f9b6cedSSteven Rostedt return !$failed; 4725f9b6cedSSteven Rostedt} 4735f9b6cedSSteven Rostedt 474*e48c5293SSteven Rostedtsub run_ssh { 475*e48c5293SSteven Rostedt my ($cmd) = @_; 476*e48c5293SSteven Rostedt my $cp_exec = $ssh_exec; 477*e48c5293SSteven Rostedt 478*e48c5293SSteven Rostedt $cp_exec =~ s/\$SSH_COMMAND/$cmd/g; 479*e48c5293SSteven Rostedt return run_command "$cp_exec"; 480*e48c5293SSteven Rostedt} 481*e48c5293SSteven Rostedt 482*e48c5293SSteven Rostedtsub run_scp { 483*e48c5293SSteven Rostedt my ($src, $dst) = @_; 484*e48c5293SSteven Rostedt my $cp_scp = $scp_to_target; 485*e48c5293SSteven Rostedt 486*e48c5293SSteven Rostedt $cp_scp =~ s/\$SRC_FILE/$src/g; 487*e48c5293SSteven Rostedt $cp_scp =~ s/\$DST_FILE/$dst/g; 488*e48c5293SSteven Rostedt 489*e48c5293SSteven Rostedt return run_command "$cp_scp"; 490*e48c5293SSteven Rostedt} 491*e48c5293SSteven Rostedt 4925f9b6cedSSteven Rostedtsub get_grub_index { 4935f9b6cedSSteven Rostedt 494a75fececSSteven Rostedt if ($reboot_type ne "grub") { 495a75fececSSteven Rostedt return; 496a75fececSSteven Rostedt } 4975a391fbfSSteven Rostedt return if (defined($grub_number)); 4985f9b6cedSSteven Rostedt 4995f9b6cedSSteven Rostedt doprint "Find grub menu ... "; 5005f9b6cedSSteven Rostedt $grub_number = -1; 501*e48c5293SSteven Rostedt 502*e48c5293SSteven Rostedt my $ssh_grub = $ssh_exec; 503*e48c5293SSteven Rostedt $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; 504*e48c5293SSteven Rostedt 505*e48c5293SSteven Rostedt open(IN, "$ssh_grub |") 5065f9b6cedSSteven Rostedt or die "unable to get menu.lst"; 507*e48c5293SSteven Rostedt 5085f9b6cedSSteven Rostedt while (<IN>) { 509a75fececSSteven Rostedt if (/^\s*title\s+$grub_menu\s*$/) { 5105f9b6cedSSteven Rostedt $grub_number++; 5115f9b6cedSSteven Rostedt last; 5125f9b6cedSSteven Rostedt } elsif (/^\s*title\s/) { 5135f9b6cedSSteven Rostedt $grub_number++; 5145f9b6cedSSteven Rostedt } 5155f9b6cedSSteven Rostedt } 5165f9b6cedSSteven Rostedt close(IN); 5175f9b6cedSSteven Rostedt 518a75fececSSteven Rostedt die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 5195f9b6cedSSteven Rostedt if ($grub_number < 0); 5205f9b6cedSSteven Rostedt doprint "$grub_number\n"; 5212545eb61SSteven Rostedt} 5222545eb61SSteven Rostedt 5232545eb61SSteven Rostedtsub wait_for_input 5242545eb61SSteven Rostedt{ 5252545eb61SSteven Rostedt my ($fp, $time) = @_; 5262545eb61SSteven Rostedt my $rin; 5272545eb61SSteven Rostedt my $ready; 5282545eb61SSteven Rostedt my $line; 5292545eb61SSteven Rostedt my $ch; 5302545eb61SSteven Rostedt 5312545eb61SSteven Rostedt if (!defined($time)) { 5322545eb61SSteven Rostedt $time = $timeout; 5332545eb61SSteven Rostedt } 5342545eb61SSteven Rostedt 5352545eb61SSteven Rostedt $rin = ''; 5362545eb61SSteven Rostedt vec($rin, fileno($fp), 1) = 1; 5372545eb61SSteven Rostedt $ready = select($rin, undef, undef, $time); 5382545eb61SSteven Rostedt 5392545eb61SSteven Rostedt $line = ""; 5402545eb61SSteven Rostedt 5412545eb61SSteven Rostedt # try to read one char at a time 5422545eb61SSteven Rostedt while (sysread $fp, $ch, 1) { 5432545eb61SSteven Rostedt $line .= $ch; 5442545eb61SSteven Rostedt last if ($ch eq "\n"); 5452545eb61SSteven Rostedt } 5462545eb61SSteven Rostedt 5472545eb61SSteven Rostedt if (!length($line)) { 5482545eb61SSteven Rostedt return undef; 5492545eb61SSteven Rostedt } 5502545eb61SSteven Rostedt 5512545eb61SSteven Rostedt return $line; 5522545eb61SSteven Rostedt} 5532545eb61SSteven Rostedt 55475c3fda7SSteven Rostedtsub reboot_to { 555a75fececSSteven Rostedt if ($reboot_type eq "grub") { 556*e48c5293SSteven Rostedt run_command "$ssh_exec '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; 557a75fececSSteven Rostedt return; 558a75fececSSteven Rostedt } 559a75fececSSteven Rostedt 560a75fececSSteven Rostedt run_command "$reboot_script"; 5612545eb61SSteven Rostedt} 5622545eb61SSteven Rostedt 563a57419b3SSteven Rostedtsub get_sha1 { 564a57419b3SSteven Rostedt my ($commit) = @_; 565a57419b3SSteven Rostedt 566a57419b3SSteven Rostedt doprint "git rev-list --max-count=1 $commit ... "; 567a57419b3SSteven Rostedt my $sha1 = `git rev-list --max-count=1 $commit`; 568a57419b3SSteven Rostedt my $ret = $?; 569a57419b3SSteven Rostedt 570a57419b3SSteven Rostedt logit $sha1; 571a57419b3SSteven Rostedt 572a57419b3SSteven Rostedt if ($ret) { 573a57419b3SSteven Rostedt doprint "FAILED\n"; 574a57419b3SSteven Rostedt dodie "Failed to get git $commit"; 575a57419b3SSteven Rostedt } 576a57419b3SSteven Rostedt 577a57419b3SSteven Rostedt print "SUCCESS\n"; 578a57419b3SSteven Rostedt 579a57419b3SSteven Rostedt chomp $sha1; 580a57419b3SSteven Rostedt 581a57419b3SSteven Rostedt return $sha1; 582a57419b3SSteven Rostedt} 583a57419b3SSteven Rostedt 5845a391fbfSSteven Rostedtsub monitor { 5852545eb61SSteven Rostedt my $booted = 0; 5862545eb61SSteven Rostedt my $bug = 0; 5875c42fc5bSSteven Rostedt my $skip_call_trace = 0; 5882b7d9b21SSteven Rostedt my $loops; 5892545eb61SSteven Rostedt 5907faafbd6SSteven Rostedt wait_for_monitor 5; 5912545eb61SSteven Rostedt 5922545eb61SSteven Rostedt my $line; 5932545eb61SSteven Rostedt my $full_line = ""; 5942545eb61SSteven Rostedt 5957faafbd6SSteven Rostedt open(DMESG, "> $dmesg") or 5967faafbd6SSteven Rostedt die "unable to write to $dmesg"; 5972545eb61SSteven Rostedt 59875c3fda7SSteven Rostedt reboot_to; 5992545eb61SSteven Rostedt 6002545eb61SSteven Rostedt for (;;) { 6012545eb61SSteven Rostedt 6022b7d9b21SSteven Rostedt if ($booted) { 603a75fececSSteven Rostedt $line = wait_for_input($monitor_fp, $booted_timeout); 6042b7d9b21SSteven Rostedt } else { 6057faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp); 6062b7d9b21SSteven Rostedt } 6072545eb61SSteven Rostedt 6082545eb61SSteven Rostedt last if (!defined($line)); 6092545eb61SSteven Rostedt 6102545eb61SSteven Rostedt doprint $line; 6117faafbd6SSteven Rostedt print DMESG $line; 6122545eb61SSteven Rostedt 6132545eb61SSteven Rostedt # we are not guaranteed to get a full line 6142545eb61SSteven Rostedt $full_line .= $line; 6152545eb61SSteven Rostedt 616a75fececSSteven Rostedt if ($full_line =~ /$success_line/) { 6172545eb61SSteven Rostedt $booted = 1; 6182545eb61SSteven Rostedt } 6192545eb61SSteven Rostedt 6205c42fc5bSSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 6215c42fc5bSSteven Rostedt $skip_call_trace = 1; 6225c42fc5bSSteven Rostedt } 6235c42fc5bSSteven Rostedt 6242545eb61SSteven Rostedt if ($full_line =~ /call trace:/i) { 6255c42fc5bSSteven Rostedt $bug = 1 if (!$skip_call_trace); 6265c42fc5bSSteven Rostedt } 6275c42fc5bSSteven Rostedt 6285c42fc5bSSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 6295c42fc5bSSteven Rostedt $skip_call_trace = 0; 6305c42fc5bSSteven Rostedt } 6315c42fc5bSSteven Rostedt 6325c42fc5bSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 6332545eb61SSteven Rostedt $bug = 1; 6342545eb61SSteven Rostedt } 6352545eb61SSteven Rostedt 6362545eb61SSteven Rostedt if ($line =~ /\n/) { 6372545eb61SSteven Rostedt $full_line = ""; 6382545eb61SSteven Rostedt } 6392545eb61SSteven Rostedt } 6402545eb61SSteven Rostedt 6417faafbd6SSteven Rostedt close(DMESG); 6422545eb61SSteven Rostedt 6432545eb61SSteven Rostedt if ($bug) { 6442b7d9b21SSteven Rostedt return 0 if ($in_bisect); 645576f627cSSteven Rostedt fail "failed - got a bug report" and return 0; 6462545eb61SSteven Rostedt } 6475f9b6cedSSteven Rostedt 648a75fececSSteven Rostedt if (!$booted) { 649a75fececSSteven Rostedt return 0 if ($in_bisect); 650576f627cSSteven Rostedt fail "failed - never got a boot prompt." and return 0; 651a75fececSSteven Rostedt } 652a75fececSSteven Rostedt 6532b7d9b21SSteven Rostedt return 1; 6542545eb61SSteven Rostedt} 6552545eb61SSteven Rostedt 6562545eb61SSteven Rostedtsub install { 6572545eb61SSteven Rostedt 658*e48c5293SSteven Rostedt run_scp "$outputdir/$build_target", "$target_image" or 6595c42fc5bSSteven Rostedt dodie "failed to copy image"; 6605f9b6cedSSteven Rostedt 6615f9b6cedSSteven Rostedt my $install_mods = 0; 6625f9b6cedSSteven Rostedt 6635f9b6cedSSteven Rostedt # should we process modules? 6645f9b6cedSSteven Rostedt $install_mods = 0; 66551ad1dd1SSteven Rostedt open(IN, "$output_config") or dodie("Can't read config file"); 6665f9b6cedSSteven Rostedt while (<IN>) { 6675f9b6cedSSteven Rostedt if (/CONFIG_MODULES(=y)?/) { 6685f9b6cedSSteven Rostedt $install_mods = 1 if (defined($1)); 6695f9b6cedSSteven Rostedt last; 6705f9b6cedSSteven Rostedt } 6715f9b6cedSSteven Rostedt } 6725f9b6cedSSteven Rostedt close(IN); 6735f9b6cedSSteven Rostedt 6745f9b6cedSSteven Rostedt if (!$install_mods) { 6755f9b6cedSSteven Rostedt doprint "No modules needed\n"; 6765f9b6cedSSteven Rostedt return; 6772545eb61SSteven Rostedt } 6782545eb61SSteven Rostedt 679a75fececSSteven Rostedt run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or 6805f9b6cedSSteven Rostedt dodie "Failed to install modules"; 6815f9b6cedSSteven Rostedt 6822545eb61SSteven Rostedt my $modlib = "/lib/modules/$version"; 683a57419b3SSteven Rostedt my $modtar = "ktest-mods.tar.bz2"; 6842545eb61SSteven Rostedt 685*e48c5293SSteven Rostedt run_ssh "rm -rf $modlib" or 6865c42fc5bSSteven Rostedt dodie "failed to remove old mods: $modlib"; 6872545eb61SSteven Rostedt 6885c42fc5bSSteven Rostedt # would be nice if scp -r did not follow symbolic links 689a75fececSSteven Rostedt run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 6905c42fc5bSSteven Rostedt dodie "making tarball"; 6915c42fc5bSSteven Rostedt 692*e48c5293SSteven Rostedt run_scp "$tmpdir/$modtar", "/tmp" or 6935c42fc5bSSteven Rostedt dodie "failed to copy modules"; 6945c42fc5bSSteven Rostedt 695a75fececSSteven Rostedt unlink "$tmpdir/$modtar"; 6965c42fc5bSSteven Rostedt 697*e48c5293SSteven Rostedt run_ssh "'(cd / && tar xf /tmp/$modtar)'" or 6985c42fc5bSSteven Rostedt dodie "failed to tar modules"; 6995c42fc5bSSteven Rostedt 700*e48c5293SSteven Rostedt run_ssh "rm -f /tmp/$modtar"; 7018b37ca8cSSteven Rostedt 7028b37ca8cSSteven Rostedt return if (!defined($post_install)); 7038b37ca8cSSteven Rostedt 704*e48c5293SSteven Rostedt my $cp_post_install = $post_install; 705*e48c5293SSteven Rostedt $cp_post_install = s/\$KERNEL_VERSION/$version/g; 706*e48c5293SSteven Rostedt run_command "$cp_post_install" or 707576f627cSSteven Rostedt dodie "Failed to run post install"; 7082545eb61SSteven Rostedt} 7092545eb61SSteven Rostedt 7106c5ee0beSSteven Rostedtsub check_buildlog { 7116c5ee0beSSteven Rostedt my ($patch) = @_; 7126c5ee0beSSteven Rostedt 7136c5ee0beSSteven Rostedt my @files = `git show $patch | diffstat -l`; 7146c5ee0beSSteven Rostedt 7156c5ee0beSSteven Rostedt open(IN, "git show $patch |") or 7166c5ee0beSSteven Rostedt dodie "failed to show $patch"; 7176c5ee0beSSteven Rostedt while (<IN>) { 7186c5ee0beSSteven Rostedt if (m,^--- a/(.*),) { 7196c5ee0beSSteven Rostedt chomp $1; 7206c5ee0beSSteven Rostedt $files[$#files] = $1; 7216c5ee0beSSteven Rostedt } 7226c5ee0beSSteven Rostedt } 7236c5ee0beSSteven Rostedt close(IN); 7246c5ee0beSSteven Rostedt 7256c5ee0beSSteven Rostedt open(IN, $buildlog) or dodie "Can't open $buildlog"; 7266c5ee0beSSteven Rostedt while (<IN>) { 7276c5ee0beSSteven Rostedt if (/^\s*(.*?):.*(warning|error)/) { 7286c5ee0beSSteven Rostedt my $err = $1; 7296c5ee0beSSteven Rostedt foreach my $file (@files) { 730a75fececSSteven Rostedt my $fullpath = "$builddir/$file"; 7316c5ee0beSSteven Rostedt if ($file eq $err || $fullpath eq $err) { 7322b7d9b21SSteven Rostedt fail "$file built with warnings" and return 0; 7336c5ee0beSSteven Rostedt } 7346c5ee0beSSteven Rostedt } 7356c5ee0beSSteven Rostedt } 7366c5ee0beSSteven Rostedt } 7376c5ee0beSSteven Rostedt close(IN); 7382b7d9b21SSteven Rostedt 7392b7d9b21SSteven Rostedt return 1; 7406c5ee0beSSteven Rostedt} 7416c5ee0beSSteven Rostedt 7422545eb61SSteven Rostedtsub build { 7432545eb61SSteven Rostedt my ($type) = @_; 7445c42fc5bSSteven Rostedt my $defconfig = ""; 7452545eb61SSteven Rostedt 7467faafbd6SSteven Rostedt unlink $buildlog; 7477faafbd6SSteven Rostedt 74875c3fda7SSteven Rostedt if ($type =~ /^useconfig:(.*)/) { 74951ad1dd1SSteven Rostedt run_command "cp $1 $output_config" or 75075c3fda7SSteven Rostedt dodie "could not copy $1 to .config"; 7515f9b6cedSSteven Rostedt 75275c3fda7SSteven Rostedt $type = "oldconfig"; 75375c3fda7SSteven Rostedt } 75475c3fda7SSteven Rostedt 7555c42fc5bSSteven Rostedt # old config can ask questions 7565c42fc5bSSteven Rostedt if ($type eq "oldconfig") { 7579386c6abSSteven Rostedt $type = "oldnoconfig"; 75875c3fda7SSteven Rostedt 75975c3fda7SSteven Rostedt # allow for empty configs 76051ad1dd1SSteven Rostedt run_command "touch $output_config"; 76175c3fda7SSteven Rostedt 76251ad1dd1SSteven Rostedt run_command "mv $output_config $outputdir/config_temp" or 7635c42fc5bSSteven Rostedt dodie "moving .config"; 7645c42fc5bSSteven Rostedt 7655f9b6cedSSteven Rostedt if (!$noclean && !run_command "$make mrproper") { 7665c42fc5bSSteven Rostedt dodie "make mrproper"; 7675c42fc5bSSteven Rostedt } 7685c42fc5bSSteven Rostedt 76951ad1dd1SSteven Rostedt run_command "mv $outputdir/config_temp $output_config" or 7705c42fc5bSSteven Rostedt dodie "moving config_temp"; 7715c42fc5bSSteven Rostedt 7725c42fc5bSSteven Rostedt } elsif (!$noclean) { 77351ad1dd1SSteven Rostedt unlink "$output_config"; 7745f9b6cedSSteven Rostedt run_command "$make mrproper" or 7755c42fc5bSSteven Rostedt dodie "make mrproper"; 7765c42fc5bSSteven Rostedt } 7772545eb61SSteven Rostedt 7782545eb61SSteven Rostedt # add something to distinguish this build 779a75fececSSteven Rostedt open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 780a75fececSSteven Rostedt print OUT "$localversion\n"; 7812545eb61SSteven Rostedt close(OUT); 7822545eb61SSteven Rostedt 7835f9b6cedSSteven Rostedt if (defined($minconfig)) { 7845f9b6cedSSteven Rostedt $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; 7852545eb61SSteven Rostedt } 7862545eb61SSteven Rostedt 7879386c6abSSteven Rostedt run_command "$defconfig $make $type" or 7885c42fc5bSSteven Rostedt dodie "failed make config"; 7892545eb61SSteven Rostedt 790a75fececSSteven Rostedt $redirect = "$buildlog"; 791a75fececSSteven Rostedt if (!run_command "$make $build_options") { 7926c5ee0beSSteven Rostedt undef $redirect; 7935f9b6cedSSteven Rostedt # bisect may need this to pass 7942b7d9b21SSteven Rostedt return 0 if ($in_bisect); 7952b7d9b21SSteven Rostedt fail "failed build" and return 0; 7962545eb61SSteven Rostedt } 7976c5ee0beSSteven Rostedt undef $redirect; 7985f9b6cedSSteven Rostedt 7992b7d9b21SSteven Rostedt return 1; 8002545eb61SSteven Rostedt} 8012545eb61SSteven Rostedt 80275c3fda7SSteven Rostedtsub halt { 803*e48c5293SSteven Rostedt if (!run_ssh "halt" or defined($power_off)) { 804576f627cSSteven Rostedt if (defined($poweroff_after_halt)) { 805576f627cSSteven Rostedt sleep $poweroff_after_halt; 806576f627cSSteven Rostedt run_command "$power_off"; 807576f627cSSteven Rostedt } 808576f627cSSteven Rostedt } else { 80975c3fda7SSteven Rostedt # nope? the zap it! 810a75fececSSteven Rostedt run_command "$power_off"; 81175c3fda7SSteven Rostedt } 81275c3fda7SSteven Rostedt} 81375c3fda7SSteven Rostedt 8145f9b6cedSSteven Rostedtsub success { 8155f9b6cedSSteven Rostedt my ($i) = @_; 8165f9b6cedSSteven Rostedt 817*e48c5293SSteven Rostedt $successes++; 818*e48c5293SSteven Rostedt 8195f9b6cedSSteven Rostedt doprint "\n\n*******************************************\n"; 8205f9b6cedSSteven Rostedt doprint "*******************************************\n"; 8217a849cd9SSteven Rostedt doprint "KTEST RESULT: TEST $i SUCCESS!!!! **\n"; 8225f9b6cedSSteven Rostedt doprint "*******************************************\n"; 8235f9b6cedSSteven Rostedt doprint "*******************************************\n"; 8245f9b6cedSSteven Rostedt 825576f627cSSteven Rostedt if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { 826a75fececSSteven Rostedt doprint "Reboot and wait $sleep_time seconds\n"; 8275f9b6cedSSteven Rostedt reboot; 8287faafbd6SSteven Rostedt start_monitor; 829a75fececSSteven Rostedt wait_for_monitor $sleep_time; 8307faafbd6SSteven Rostedt end_monitor; 8315f9b6cedSSteven Rostedt } 8325f9b6cedSSteven Rostedt} 8335f9b6cedSSteven Rostedt 8345f9b6cedSSteven Rostedtsub get_version { 8355f9b6cedSSteven Rostedt # get the release name 8365f9b6cedSSteven Rostedt doprint "$make kernelrelease ... "; 8375f9b6cedSSteven Rostedt $version = `$make kernelrelease | tail -1`; 8385f9b6cedSSteven Rostedt chomp($version); 8395f9b6cedSSteven Rostedt doprint "$version\n"; 8405f9b6cedSSteven Rostedt} 8415f9b6cedSSteven Rostedt 8425a391fbfSSteven Rostedtsub child_run_test { 8437faafbd6SSteven Rostedt my $failed = 0; 8445a391fbfSSteven Rostedt 8457faafbd6SSteven Rostedt # child should have no power 846a75fececSSteven Rostedt $reboot_on_error = 0; 847a75fececSSteven Rostedt $poweroff_on_error = 0; 848a75fececSSteven Rostedt $die_on_failure = 1; 8497faafbd6SSteven Rostedt 8507faafbd6SSteven Rostedt run_command $run_test or $failed = 1; 8515a391fbfSSteven Rostedt exit $failed; 8525a391fbfSSteven Rostedt} 8535a391fbfSSteven Rostedt 8545a391fbfSSteven Rostedtmy $child_done; 8555a391fbfSSteven Rostedt 8565a391fbfSSteven Rostedtsub child_finished { 8575a391fbfSSteven Rostedt $child_done = 1; 8585a391fbfSSteven Rostedt} 8595a391fbfSSteven Rostedt 8605a391fbfSSteven Rostedtsub do_run_test { 8615a391fbfSSteven Rostedt my $child_pid; 8625a391fbfSSteven Rostedt my $child_exit; 8635a391fbfSSteven Rostedt my $line; 8645a391fbfSSteven Rostedt my $full_line; 8655a391fbfSSteven Rostedt my $bug = 0; 8665a391fbfSSteven Rostedt 8677faafbd6SSteven Rostedt wait_for_monitor 1; 8685a391fbfSSteven Rostedt 8697faafbd6SSteven Rostedt doprint "run test $run_test\n"; 8705a391fbfSSteven Rostedt 8715a391fbfSSteven Rostedt $child_done = 0; 8725a391fbfSSteven Rostedt 8735a391fbfSSteven Rostedt $SIG{CHLD} = qw(child_finished); 8745a391fbfSSteven Rostedt 8755a391fbfSSteven Rostedt $child_pid = fork; 8765a391fbfSSteven Rostedt 8775a391fbfSSteven Rostedt child_run_test if (!$child_pid); 8785a391fbfSSteven Rostedt 8795a391fbfSSteven Rostedt $full_line = ""; 8805a391fbfSSteven Rostedt 8815a391fbfSSteven Rostedt do { 8827faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 8835a391fbfSSteven Rostedt if (defined($line)) { 8845a391fbfSSteven Rostedt 8855a391fbfSSteven Rostedt # we are not guaranteed to get a full line 8865a391fbfSSteven Rostedt $full_line .= $line; 8875a391fbfSSteven Rostedt 8885a391fbfSSteven Rostedt if ($full_line =~ /call trace:/i) { 8895a391fbfSSteven Rostedt $bug = 1; 8905a391fbfSSteven Rostedt } 8915a391fbfSSteven Rostedt 8925a391fbfSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 8935a391fbfSSteven Rostedt $bug = 1; 8945a391fbfSSteven Rostedt } 8955a391fbfSSteven Rostedt 8965a391fbfSSteven Rostedt if ($line =~ /\n/) { 8975a391fbfSSteven Rostedt $full_line = ""; 8985a391fbfSSteven Rostedt } 8995a391fbfSSteven Rostedt } 9005a391fbfSSteven Rostedt } while (!$child_done && !$bug); 9015a391fbfSSteven Rostedt 9025a391fbfSSteven Rostedt if ($bug) { 9035a391fbfSSteven Rostedt doprint "Detected kernel crash!\n"; 9045a391fbfSSteven Rostedt # kill the child with extreme prejudice 9055a391fbfSSteven Rostedt kill 9, $child_pid; 9065a391fbfSSteven Rostedt } 9075a391fbfSSteven Rostedt 9085a391fbfSSteven Rostedt waitpid $child_pid, 0; 9095a391fbfSSteven Rostedt $child_exit = $?; 9105a391fbfSSteven Rostedt 9115a391fbfSSteven Rostedt if ($bug || $child_exit) { 9122b7d9b21SSteven Rostedt return 0 if $in_bisect; 9132b7d9b21SSteven Rostedt fail "test failed" and return 0; 9145a391fbfSSteven Rostedt } 9152b7d9b21SSteven Rostedt return 1; 9165a391fbfSSteven Rostedt} 9175a391fbfSSteven Rostedt 918a75fececSSteven Rostedtsub run_git_bisect { 919a75fececSSteven Rostedt my ($command) = @_; 920a75fececSSteven Rostedt 921a75fececSSteven Rostedt doprint "$command ... "; 922a75fececSSteven Rostedt 923a75fececSSteven Rostedt my $output = `$command 2>&1`; 924a75fececSSteven Rostedt my $ret = $?; 925a75fececSSteven Rostedt 926a75fececSSteven Rostedt logit $output; 927a75fececSSteven Rostedt 928a75fececSSteven Rostedt if ($ret) { 929a75fececSSteven Rostedt doprint "FAILED\n"; 930a75fececSSteven Rostedt dodie "Failed to git bisect"; 931a75fececSSteven Rostedt } 932a75fececSSteven Rostedt 933a75fececSSteven Rostedt doprint "SUCCESS\n"; 934a75fececSSteven Rostedt if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 935a75fececSSteven Rostedt doprint "$1 [$2]\n"; 936a75fececSSteven Rostedt } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 937a75fececSSteven Rostedt $bisect_bad = $1; 938a75fececSSteven Rostedt doprint "Found bad commit... $1\n"; 939a75fececSSteven Rostedt return 0; 940a75fececSSteven Rostedt } else { 941a75fececSSteven Rostedt # we already logged it, just print it now. 942a75fececSSteven Rostedt print $output; 943a75fececSSteven Rostedt } 944a75fececSSteven Rostedt 945a75fececSSteven Rostedt return 1; 946a75fececSSteven Rostedt} 947a75fececSSteven Rostedt 9485f9b6cedSSteven Rostedtsub run_bisect { 9495f9b6cedSSteven Rostedt my ($type) = @_; 9505f9b6cedSSteven Rostedt 9512b7d9b21SSteven Rostedt my $failed = 0; 9525f9b6cedSSteven Rostedt my $result; 9535f9b6cedSSteven Rostedt my $output; 9545f9b6cedSSteven Rostedt my $ret; 9555f9b6cedSSteven Rostedt 9565f9b6cedSSteven Rostedt if (defined($minconfig)) { 9572b7d9b21SSteven Rostedt build "useconfig:$minconfig" or $failed = 1; 9585f9b6cedSSteven Rostedt } else { 9595f9b6cedSSteven Rostedt # ?? no config to use? 9602b7d9b21SSteven Rostedt build "oldconfig" or $failed = 1; 9615f9b6cedSSteven Rostedt } 9625f9b6cedSSteven Rostedt 9635f9b6cedSSteven Rostedt if ($type ne "build") { 9647faafbd6SSteven Rostedt dodie "Failed on build" if $failed; 9655f9b6cedSSteven Rostedt 9665f9b6cedSSteven Rostedt # Now boot the box 9675f9b6cedSSteven Rostedt get_grub_index; 9685f9b6cedSSteven Rostedt get_version; 9695f9b6cedSSteven Rostedt install; 9707faafbd6SSteven Rostedt 9717faafbd6SSteven Rostedt start_monitor; 9722b7d9b21SSteven Rostedt monitor or $failed = 1; 9735f9b6cedSSteven Rostedt 9745f9b6cedSSteven Rostedt if ($type ne "boot") { 9757faafbd6SSteven Rostedt dodie "Failed on boot" if $failed; 9765a391fbfSSteven Rostedt 9772b7d9b21SSteven Rostedt do_run_test or $failed = 1; 9785f9b6cedSSteven Rostedt } 9797faafbd6SSteven Rostedt end_monitor; 9805f9b6cedSSteven Rostedt } 9815f9b6cedSSteven Rostedt 9825f9b6cedSSteven Rostedt if ($failed) { 9835f9b6cedSSteven Rostedt $result = "bad"; 9845a391fbfSSteven Rostedt 9855a391fbfSSteven Rostedt # reboot the box to a good kernel 986a75fececSSteven Rostedt if ($type ne "build") { 987a75fececSSteven Rostedt doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 9885a391fbfSSteven Rostedt reboot; 9897faafbd6SSteven Rostedt start_monitor; 990a75fececSSteven Rostedt wait_for_monitor $bisect_sleep_time; 9917faafbd6SSteven Rostedt end_monitor; 9925a391fbfSSteven Rostedt } 9935f9b6cedSSteven Rostedt } else { 9945f9b6cedSSteven Rostedt $result = "good"; 9955f9b6cedSSteven Rostedt } 9965f9b6cedSSteven Rostedt 997d6ce2a0bSSteven Rostedt # Are we looking for where it worked, not failed? 998d6ce2a0bSSteven Rostedt if ($reverse_bisect) { 999d6ce2a0bSSteven Rostedt if ($failed) { 1000d6ce2a0bSSteven Rostedt $result = "good"; 1001d6ce2a0bSSteven Rostedt } else { 1002d6ce2a0bSSteven Rostedt $result = "bad"; 1003d6ce2a0bSSteven Rostedt } 1004d6ce2a0bSSteven Rostedt } 1005d6ce2a0bSSteven Rostedt 1006a75fececSSteven Rostedt return $result; 10075f9b6cedSSteven Rostedt} 10085f9b6cedSSteven Rostedt 10095f9b6cedSSteven Rostedtsub bisect { 10105f9b6cedSSteven Rostedt my ($i) = @_; 10115f9b6cedSSteven Rostedt 10125f9b6cedSSteven Rostedt my $result; 10135f9b6cedSSteven Rostedt 10145f9b6cedSSteven Rostedt die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 10155f9b6cedSSteven Rostedt die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 10165f9b6cedSSteven Rostedt die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 10175f9b6cedSSteven Rostedt 10185f9b6cedSSteven Rostedt my $good = $opt{"BISECT_GOOD[$i]"}; 10195f9b6cedSSteven Rostedt my $bad = $opt{"BISECT_BAD[$i]"}; 10205f9b6cedSSteven Rostedt my $type = $opt{"BISECT_TYPE[$i]"}; 1021a75fececSSteven Rostedt my $start = $opt{"BISECT_START[$i]"}; 1022a75fececSSteven Rostedt my $replay = $opt{"BISECT_REPLAY[$i]"}; 10235f9b6cedSSteven Rostedt 1024a57419b3SSteven Rostedt # convert to true sha1's 1025a57419b3SSteven Rostedt $good = get_sha1($good); 1026a57419b3SSteven Rostedt $bad = get_sha1($bad); 1027a57419b3SSteven Rostedt 1028d6ce2a0bSSteven Rostedt if (defined($opt{"BISECT_REVERSE[$i]"}) && 1029d6ce2a0bSSteven Rostedt $opt{"BISECT_REVERSE[$i]"} == 1) { 1030d6ce2a0bSSteven Rostedt doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 1031d6ce2a0bSSteven Rostedt $reverse_bisect = 1; 1032d6ce2a0bSSteven Rostedt } else { 1033d6ce2a0bSSteven Rostedt $reverse_bisect = 0; 1034d6ce2a0bSSteven Rostedt } 1035d6ce2a0bSSteven Rostedt 10365f9b6cedSSteven Rostedt $in_bisect = 1; 10375f9b6cedSSteven Rostedt 10385a391fbfSSteven Rostedt # Can't have a test without having a test to run 10395a391fbfSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 10405a391fbfSSteven Rostedt $type = "boot"; 10415a391fbfSSteven Rostedt } 10425a391fbfSSteven Rostedt 1043a75fececSSteven Rostedt my $check = $opt{"BISECT_CHECK[$i]"}; 1044a75fececSSteven Rostedt if (defined($check) && $check ne "0") { 1045a75fececSSteven Rostedt 1046a75fececSSteven Rostedt # get current HEAD 1047a57419b3SSteven Rostedt my $head = get_sha1("HEAD"); 1048a75fececSSteven Rostedt 1049a75fececSSteven Rostedt if ($check ne "good") { 1050a75fececSSteven Rostedt doprint "TESTING BISECT BAD [$bad]\n"; 1051a75fececSSteven Rostedt run_command "git checkout $bad" or 1052a75fececSSteven Rostedt die "Failed to checkout $bad"; 1053a75fececSSteven Rostedt 1054a75fececSSteven Rostedt $result = run_bisect $type; 1055a75fececSSteven Rostedt 1056a75fececSSteven Rostedt if ($result ne "bad") { 1057a75fececSSteven Rostedt fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 1058a75fececSSteven Rostedt } 1059a75fececSSteven Rostedt } 1060a75fececSSteven Rostedt 1061a75fececSSteven Rostedt if ($check ne "bad") { 1062a75fececSSteven Rostedt doprint "TESTING BISECT GOOD [$good]\n"; 1063a75fececSSteven Rostedt run_command "git checkout $good" or 1064a75fececSSteven Rostedt die "Failed to checkout $good"; 1065a75fececSSteven Rostedt 1066a75fececSSteven Rostedt $result = run_bisect $type; 1067a75fececSSteven Rostedt 1068a75fececSSteven Rostedt if ($result ne "good") { 1069a75fececSSteven Rostedt fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 1070a75fececSSteven Rostedt } 1071a75fececSSteven Rostedt } 1072a75fececSSteven Rostedt 1073a75fececSSteven Rostedt # checkout where we started 1074a75fececSSteven Rostedt run_command "git checkout $head" or 1075a75fececSSteven Rostedt die "Failed to checkout $head"; 1076a75fececSSteven Rostedt } 1077a75fececSSteven Rostedt 1078a75fececSSteven Rostedt run_command "git bisect start" or 1079a75fececSSteven Rostedt dodie "could not start bisect"; 1080a75fececSSteven Rostedt 1081a75fececSSteven Rostedt run_command "git bisect good $good" or 1082a75fececSSteven Rostedt dodie "could not set bisect good to $good"; 1083a75fececSSteven Rostedt 1084a75fececSSteven Rostedt run_git_bisect "git bisect bad $bad" or 1085a75fececSSteven Rostedt dodie "could not set bisect bad to $bad"; 1086a75fececSSteven Rostedt 1087a75fececSSteven Rostedt if (defined($replay)) { 1088a75fececSSteven Rostedt run_command "git bisect replay $replay" or 1089a75fececSSteven Rostedt dodie "failed to run replay"; 1090a75fececSSteven Rostedt } 1091a75fececSSteven Rostedt 1092a75fececSSteven Rostedt if (defined($start)) { 1093a75fececSSteven Rostedt run_command "git checkout $start" or 1094a75fececSSteven Rostedt dodie "failed to checkout $start"; 1095a75fececSSteven Rostedt } 1096a75fececSSteven Rostedt 1097a75fececSSteven Rostedt my $test; 10985f9b6cedSSteven Rostedt do { 10995f9b6cedSSteven Rostedt $result = run_bisect $type; 1100a75fececSSteven Rostedt $test = run_git_bisect "git bisect $result"; 1101a75fececSSteven Rostedt } while ($test); 11025f9b6cedSSteven Rostedt 11035f9b6cedSSteven Rostedt run_command "git bisect log" or 11045f9b6cedSSteven Rostedt dodie "could not capture git bisect log"; 11055f9b6cedSSteven Rostedt 11065f9b6cedSSteven Rostedt run_command "git bisect reset" or 11075f9b6cedSSteven Rostedt dodie "could not reset git bisect"; 11085f9b6cedSSteven Rostedt 11095f9b6cedSSteven Rostedt doprint "Bad commit was [$bisect_bad]\n"; 11105f9b6cedSSteven Rostedt 11115f9b6cedSSteven Rostedt $in_bisect = 0; 11125f9b6cedSSteven Rostedt 11135f9b6cedSSteven Rostedt success $i; 11145f9b6cedSSteven Rostedt} 11155f9b6cedSSteven Rostedt 11166c5ee0beSSteven Rostedtsub patchcheck { 11176c5ee0beSSteven Rostedt my ($i) = @_; 11186c5ee0beSSteven Rostedt 11196c5ee0beSSteven Rostedt die "PATCHCHECK_START[$i] not defined\n" 11206c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_START[$i]"})); 11216c5ee0beSSteven Rostedt die "PATCHCHECK_TYPE[$i] not defined\n" 11226c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 11236c5ee0beSSteven Rostedt 11246c5ee0beSSteven Rostedt my $start = $opt{"PATCHCHECK_START[$i]"}; 11256c5ee0beSSteven Rostedt 11266c5ee0beSSteven Rostedt my $end = "HEAD"; 11276c5ee0beSSteven Rostedt if (defined($opt{"PATCHCHECK_END[$i]"})) { 11286c5ee0beSSteven Rostedt $end = $opt{"PATCHCHECK_END[$i]"}; 11296c5ee0beSSteven Rostedt } 11306c5ee0beSSteven Rostedt 1131a57419b3SSteven Rostedt # Get the true sha1's since we can use things like HEAD~3 1132a57419b3SSteven Rostedt $start = get_sha1($start); 1133a57419b3SSteven Rostedt $end = get_sha1($end); 1134a57419b3SSteven Rostedt 11356c5ee0beSSteven Rostedt my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 11366c5ee0beSSteven Rostedt 11376c5ee0beSSteven Rostedt # Can't have a test without having a test to run 11386c5ee0beSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 11396c5ee0beSSteven Rostedt $type = "boot"; 11406c5ee0beSSteven Rostedt } 11416c5ee0beSSteven Rostedt 11426c5ee0beSSteven Rostedt open (IN, "git log --pretty=oneline $end|") or 11436c5ee0beSSteven Rostedt dodie "could not get git list"; 11446c5ee0beSSteven Rostedt 11456c5ee0beSSteven Rostedt my @list; 11466c5ee0beSSteven Rostedt 11476c5ee0beSSteven Rostedt while (<IN>) { 11486c5ee0beSSteven Rostedt chomp; 11496c5ee0beSSteven Rostedt $list[$#list+1] = $_; 11506c5ee0beSSteven Rostedt last if (/^$start/); 11516c5ee0beSSteven Rostedt } 11526c5ee0beSSteven Rostedt close(IN); 11536c5ee0beSSteven Rostedt 11546c5ee0beSSteven Rostedt if ($list[$#list] !~ /^$start/) { 11552b7d9b21SSteven Rostedt fail "SHA1 $start not found"; 11566c5ee0beSSteven Rostedt } 11576c5ee0beSSteven Rostedt 11586c5ee0beSSteven Rostedt # go backwards in the list 11596c5ee0beSSteven Rostedt @list = reverse @list; 11606c5ee0beSSteven Rostedt 11616c5ee0beSSteven Rostedt my $save_clean = $noclean; 11626c5ee0beSSteven Rostedt 11636c5ee0beSSteven Rostedt $in_patchcheck = 1; 11646c5ee0beSSteven Rostedt foreach my $item (@list) { 11656c5ee0beSSteven Rostedt my $sha1 = $item; 11666c5ee0beSSteven Rostedt $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 11676c5ee0beSSteven Rostedt 11686c5ee0beSSteven Rostedt doprint "\nProcessing commit $item\n\n"; 11696c5ee0beSSteven Rostedt 11706c5ee0beSSteven Rostedt run_command "git checkout $sha1" or 11716c5ee0beSSteven Rostedt die "Failed to checkout $sha1"; 11726c5ee0beSSteven Rostedt 11736c5ee0beSSteven Rostedt # only clean on the first and last patch 11746c5ee0beSSteven Rostedt if ($item eq $list[0] || 11756c5ee0beSSteven Rostedt $item eq $list[$#list]) { 11766c5ee0beSSteven Rostedt $noclean = $save_clean; 11776c5ee0beSSteven Rostedt } else { 11786c5ee0beSSteven Rostedt $noclean = 1; 11796c5ee0beSSteven Rostedt } 11806c5ee0beSSteven Rostedt 11816c5ee0beSSteven Rostedt if (defined($minconfig)) { 11822b7d9b21SSteven Rostedt build "useconfig:$minconfig" or return 0; 11836c5ee0beSSteven Rostedt } else { 11846c5ee0beSSteven Rostedt # ?? no config to use? 11852b7d9b21SSteven Rostedt build "oldconfig" or return 0; 11866c5ee0beSSteven Rostedt } 11876c5ee0beSSteven Rostedt 11882b7d9b21SSteven Rostedt check_buildlog $sha1 or return 0; 11896c5ee0beSSteven Rostedt 11906c5ee0beSSteven Rostedt next if ($type eq "build"); 11916c5ee0beSSteven Rostedt 11926c5ee0beSSteven Rostedt get_grub_index; 11936c5ee0beSSteven Rostedt get_version; 11946c5ee0beSSteven Rostedt install; 11956c5ee0beSSteven Rostedt 11967faafbd6SSteven Rostedt my $failed = 0; 11977faafbd6SSteven Rostedt 11987faafbd6SSteven Rostedt start_monitor; 11997faafbd6SSteven Rostedt monitor or $failed = 1; 12007faafbd6SSteven Rostedt 12017faafbd6SSteven Rostedt if (!$failed && $type ne "boot"){ 12027faafbd6SSteven Rostedt do_run_test or $failed = 1; 12037faafbd6SSteven Rostedt } 12047faafbd6SSteven Rostedt end_monitor; 12057faafbd6SSteven Rostedt return 0 if ($failed); 12067faafbd6SSteven Rostedt 12076c5ee0beSSteven Rostedt } 12086c5ee0beSSteven Rostedt $in_patchcheck = 0; 12096c5ee0beSSteven Rostedt success $i; 12102b7d9b21SSteven Rostedt 12112b7d9b21SSteven Rostedt return 1; 12126c5ee0beSSteven Rostedt} 12136c5ee0beSSteven Rostedt 12142545eb61SSteven Rostedtread_config $ARGV[0]; 12152545eb61SSteven Rostedt 12162545eb61SSteven Rostedt# mandatory configs 12172545eb61SSteven Rostedtdie "MACHINE not defined\n" if (!defined($opt{"MACHINE"})); 12182545eb61SSteven Rostedtdie "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"})); 12192545eb61SSteven Rostedtdie "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"})); 12202545eb61SSteven Rostedtdie "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"})); 12212545eb61SSteven Rostedtdie "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"})); 122275c3fda7SSteven Rostedtdie "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"})); 12232545eb61SSteven Rostedtdie "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"})); 12242545eb61SSteven Rostedtdie "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"})); 12252545eb61SSteven Rostedtdie "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"})); 12262545eb61SSteven Rostedt 12272b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 12282b7d9b21SSteven Rostedt unlink $opt{"LOG_FILE"}; 12292b7d9b21SSteven Rostedt} 12302545eb61SSteven Rostedt 12312b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 12322b7d9b21SSteven Rostedt 1233a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) { 1234a57419b3SSteven Rostedt 1235a57419b3SSteven Rostedt if (!$i) { 1236a57419b3SSteven Rostedt doprint "DEFAULT OPTIONS:\n"; 1237a57419b3SSteven Rostedt } else { 1238a57419b3SSteven Rostedt doprint "\nTEST $i OPTIONS"; 1239a57419b3SSteven Rostedt if (defined($repeat_tests{$i})) { 1240a57419b3SSteven Rostedt $repeat = $repeat_tests{$i}; 1241a57419b3SSteven Rostedt doprint " ITERATE $repeat"; 1242a57419b3SSteven Rostedt } 1243a57419b3SSteven Rostedt doprint "\n"; 1244a57419b3SSteven Rostedt } 1245a57419b3SSteven Rostedt 12462b7d9b21SSteven Rostedt foreach my $option (sort keys %opt) { 1247a57419b3SSteven Rostedt 1248a57419b3SSteven Rostedt if ($option =~ /\[(\d+)\]$/) { 1249a57419b3SSteven Rostedt next if ($i != $1); 1250a57419b3SSteven Rostedt } else { 1251a57419b3SSteven Rostedt next if ($i); 1252a57419b3SSteven Rostedt } 1253a57419b3SSteven Rostedt 12542b7d9b21SSteven Rostedt doprint "$option = $opt{$option}\n"; 12552b7d9b21SSteven Rostedt } 1256a57419b3SSteven Rostedt} 12572545eb61SSteven Rostedt 1258a75fececSSteven Rostedtsub set_test_option { 12595a391fbfSSteven Rostedt my ($name, $i) = @_; 12605a391fbfSSteven Rostedt 12615a391fbfSSteven Rostedt my $option = "$name\[$i\]"; 12625a391fbfSSteven Rostedt 12635a391fbfSSteven Rostedt if (defined($opt{$option})) { 12645a391fbfSSteven Rostedt return $opt{$option}; 12655a391fbfSSteven Rostedt } 12665a391fbfSSteven Rostedt 1267a57419b3SSteven Rostedt foreach my $test (keys %repeat_tests) { 1268a57419b3SSteven Rostedt if ($i >= $test && 1269a57419b3SSteven Rostedt $i < $test + $repeat_tests{$test}) { 1270a57419b3SSteven Rostedt $option = "$name\[$test\]"; 1271a57419b3SSteven Rostedt if (defined($opt{$option})) { 1272a57419b3SSteven Rostedt return $opt{$option}; 1273a57419b3SSteven Rostedt } 1274a57419b3SSteven Rostedt } 1275a57419b3SSteven Rostedt } 1276a57419b3SSteven Rostedt 12775a391fbfSSteven Rostedt if (defined($opt{$name})) { 12785a391fbfSSteven Rostedt return $opt{$name}; 12795a391fbfSSteven Rostedt } 12805a391fbfSSteven Rostedt 12815a391fbfSSteven Rostedt return undef; 12825a391fbfSSteven Rostedt} 12835a391fbfSSteven Rostedt 12842545eb61SSteven Rostedt# First we need to do is the builds 1285a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 12862545eb61SSteven Rostedt 1287576f627cSSteven Rostedt $iteration = $i; 1288576f627cSSteven Rostedt 1289a75fececSSteven Rostedt my $makecmd = set_test_option("MAKE_CMD", $i); 1290a75fececSSteven Rostedt 1291a75fececSSteven Rostedt $machine = set_test_option("MACHINE", $i); 1292*e48c5293SSteven Rostedt $ssh_user = set_test_option("SSH_USER", $i); 1293a75fececSSteven Rostedt $tmpdir = set_test_option("TMP_DIR", $i); 1294a75fececSSteven Rostedt $outputdir = set_test_option("OUTPUT_DIR", $i); 1295a75fececSSteven Rostedt $builddir = set_test_option("BUILD_DIR", $i); 1296a75fececSSteven Rostedt $test_type = set_test_option("TEST_TYPE", $i); 1297a75fececSSteven Rostedt $build_type = set_test_option("BUILD_TYPE", $i); 1298a75fececSSteven Rostedt $build_options = set_test_option("BUILD_OPTIONS", $i); 1299a75fececSSteven Rostedt $power_cycle = set_test_option("POWER_CYCLE", $i); 1300*e48c5293SSteven Rostedt $reboot = set_test_option("REBOOT", $i); 1301a75fececSSteven Rostedt $noclean = set_test_option("BUILD_NOCLEAN", $i); 1302a75fececSSteven Rostedt $minconfig = set_test_option("MIN_CONFIG", $i); 1303a75fececSSteven Rostedt $run_test = set_test_option("TEST", $i); 1304a75fececSSteven Rostedt $addconfig = set_test_option("ADD_CONFIG", $i); 1305a75fececSSteven Rostedt $reboot_type = set_test_option("REBOOT_TYPE", $i); 1306a75fececSSteven Rostedt $grub_menu = set_test_option("GRUB_MENU", $i); 13078b37ca8cSSteven Rostedt $post_install = set_test_option("POST_INSTALL", $i); 1308a75fececSSteven Rostedt $reboot_script = set_test_option("REBOOT_SCRIPT", $i); 1309a75fececSSteven Rostedt $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); 1310a75fececSSteven Rostedt $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); 1311a75fececSSteven Rostedt $die_on_failure = set_test_option("DIE_ON_FAILURE", $i); 1312a75fececSSteven Rostedt $power_off = set_test_option("POWER_OFF", $i); 1313576f627cSSteven Rostedt $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i); 1314576f627cSSteven Rostedt $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i); 1315a75fececSSteven Rostedt $sleep_time = set_test_option("SLEEP_TIME", $i); 1316a75fececSSteven Rostedt $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 1317a75fececSSteven Rostedt $store_failures = set_test_option("STORE_FAILURES", $i); 1318a75fececSSteven Rostedt $timeout = set_test_option("TIMEOUT", $i); 1319a75fececSSteven Rostedt $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 1320a75fececSSteven Rostedt $console = set_test_option("CONSOLE", $i); 1321a75fececSSteven Rostedt $success_line = set_test_option("SUCCESS_LINE", $i); 1322a75fececSSteven Rostedt $build_target = set_test_option("BUILD_TARGET", $i); 1323*e48c5293SSteven Rostedt $ssh_exec = set_test_option("SSH_EXEC", $i); 1324*e48c5293SSteven Rostedt $scp_to_target = set_test_option("SCP_TO_TARGET", $i); 1325a75fececSSteven Rostedt $target_image = set_test_option("TARGET_IMAGE", $i); 1326a75fececSSteven Rostedt $localversion = set_test_option("LOCALVERSION", $i); 1327a75fececSSteven Rostedt 1328a75fececSSteven Rostedt chdir $builddir || die "can't change directory to $builddir"; 1329a75fececSSteven Rostedt 1330a75fececSSteven Rostedt if (!-d $tmpdir) { 1331a75fececSSteven Rostedt mkpath($tmpdir) or 1332a75fececSSteven Rostedt die "can't create $tmpdir"; 1333a75fececSSteven Rostedt } 1334a75fececSSteven Rostedt 1335*e48c5293SSteven Rostedt $ENV{"SSH_USER"} = $ssh_user; 1336*e48c5293SSteven Rostedt $ENV{"MACHINE"} = $machine; 1337*e48c5293SSteven Rostedt 1338a75fececSSteven Rostedt $target = "$ssh_user\@$machine"; 1339a75fececSSteven Rostedt 1340a75fececSSteven Rostedt $buildlog = "$tmpdir/buildlog-$machine"; 1341a75fececSSteven Rostedt $dmesg = "$tmpdir/dmesg-$machine"; 1342a75fececSSteven Rostedt $make = "$makecmd O=$outputdir"; 134351ad1dd1SSteven Rostedt $output_config = "$outputdir/.config"; 1344*e48c5293SSteven Rostedt $output_config = "$outputdir/.config"; 1345a75fececSSteven Rostedt 1346a75fececSSteven Rostedt if ($reboot_type eq "grub") { 1347576f627cSSteven Rostedt dodie "GRUB_MENU not defined" if (!defined($grub_menu)); 1348a75fececSSteven Rostedt } elsif (!defined($reboot_script)) { 1349576f627cSSteven Rostedt dodie "REBOOT_SCRIPT not defined" 1350a75fececSSteven Rostedt } 1351a75fececSSteven Rostedt 1352a75fececSSteven Rostedt my $run_type = $build_type; 1353a75fececSSteven Rostedt if ($test_type eq "patchcheck") { 1354a75fececSSteven Rostedt $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 1355a75fececSSteven Rostedt } elsif ($test_type eq "bisect") { 1356a75fececSSteven Rostedt $run_type = $opt{"BISECT_TYPE[$i]"}; 1357a75fececSSteven Rostedt } 1358a75fececSSteven Rostedt 1359a75fececSSteven Rostedt # mistake in config file? 1360a75fececSSteven Rostedt if (!defined($run_type)) { 1361a75fececSSteven Rostedt $run_type = "ERROR"; 1362a75fececSSteven Rostedt } 13632545eb61SSteven Rostedt 13642545eb61SSteven Rostedt doprint "\n\n"; 1365a75fececSSteven Rostedt doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n"; 13667faafbd6SSteven Rostedt 13677faafbd6SSteven Rostedt unlink $dmesg; 13687faafbd6SSteven Rostedt unlink $buildlog; 13692545eb61SSteven Rostedt 13702b7d9b21SSteven Rostedt if (!defined($minconfig)) { 13712b7d9b21SSteven Rostedt $minconfig = $addconfig; 13722b7d9b21SSteven Rostedt 13732b7d9b21SSteven Rostedt } elsif (defined($addconfig)) { 1374a75fececSSteven Rostedt run_command "cat $addconfig $minconfig > $tmpdir/use_config" or 13752b7d9b21SSteven Rostedt dodie "Failed to create temp config"; 1376a75fececSSteven Rostedt $minconfig = "$tmpdir/use_config"; 13772b7d9b21SSteven Rostedt } 13782b7d9b21SSteven Rostedt 13796c5ee0beSSteven Rostedt my $checkout = $opt{"CHECKOUT[$i]"}; 13806c5ee0beSSteven Rostedt if (defined($checkout)) { 13816c5ee0beSSteven Rostedt run_command "git checkout $checkout" or 13826c5ee0beSSteven Rostedt die "failed to checkout $checkout"; 13836c5ee0beSSteven Rostedt } 13846c5ee0beSSteven Rostedt 1385a75fececSSteven Rostedt if ($test_type eq "bisect") { 13865f9b6cedSSteven Rostedt bisect $i; 13875f9b6cedSSteven Rostedt next; 1388a75fececSSteven Rostedt } elsif ($test_type eq "patchcheck") { 13896c5ee0beSSteven Rostedt patchcheck $i; 13906c5ee0beSSteven Rostedt next; 13915f9b6cedSSteven Rostedt } 13925f9b6cedSSteven Rostedt 13937faafbd6SSteven Rostedt if ($build_type ne "nobuild") { 13947faafbd6SSteven Rostedt build $build_type or next; 13952545eb61SSteven Rostedt } 13962545eb61SSteven Rostedt 1397a75fececSSteven Rostedt if ($test_type ne "build") { 13985f9b6cedSSteven Rostedt get_grub_index; 13995f9b6cedSSteven Rostedt get_version; 14002545eb61SSteven Rostedt install; 14015a391fbfSSteven Rostedt 14027faafbd6SSteven Rostedt my $failed = 0; 14037faafbd6SSteven Rostedt start_monitor; 14047faafbd6SSteven Rostedt monitor or $failed = 1;; 1405a75fececSSteven Rostedt 1406a75fececSSteven Rostedt if (!$failed && $test_type ne "boot" && defined($run_test)) { 14077faafbd6SSteven Rostedt do_run_test or $failed = 1; 14085a391fbfSSteven Rostedt } 14097faafbd6SSteven Rostedt end_monitor; 14107faafbd6SSteven Rostedt next if ($failed); 1411a75fececSSteven Rostedt } 14125a391fbfSSteven Rostedt 14135f9b6cedSSteven Rostedt success $i; 141475c3fda7SSteven Rostedt} 14152545eb61SSteven Rostedt 14165c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) { 141775c3fda7SSteven Rostedt halt; 1418576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { 141975c3fda7SSteven Rostedt reboot; 14205c42fc5bSSteven Rostedt} 142175c3fda7SSteven Rostedt 1422*e48c5293SSteven Rostedtdoprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; 1423*e48c5293SSteven Rostedt 14242545eb61SSteven Rostedtexit 0; 1425