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 142545eb61SSteven Rostedt$#ARGV >= 0 || die "usage: autotest.pl config-file\n"; 152545eb61SSteven Rostedt 162545eb61SSteven Rostedt$| = 1; 172545eb61SSteven Rostedt 182545eb61SSteven Rostedtmy %opt; 19a75fececSSteven Rostedtmy %default; 202545eb61SSteven Rostedt 212545eb61SSteven Rostedt#default opts 22a75fececSSteven Rostedt$default{"NUM_TESTS"} = 5; 23a75fececSSteven Rostedt$default{"REBOOT_TYPE"} = "grub"; 24a75fececSSteven Rostedt$default{"TEST_TYPE"} = "test"; 25a75fececSSteven Rostedt$default{"BUILD_TYPE"} = "randconfig"; 26a75fececSSteven Rostedt$default{"MAKE_CMD"} = "make"; 27a75fececSSteven Rostedt$default{"TIMEOUT"} = 120; 28a75fececSSteven Rostedt$default{"TMP_DIR"} = "/tmp/autotest"; 29a75fececSSteven Rostedt$default{"SLEEP_TIME"} = 60; # sleep time between tests 30a75fececSSteven Rostedt$default{"BUILD_NOCLEAN"} = 0; 31a75fececSSteven Rostedt$default{"REBOOT_ON_ERROR"} = 0; 32a75fececSSteven Rostedt$default{"POWEROFF_ON_ERROR"} = 0; 33a75fececSSteven Rostedt$default{"REBOOT_ON_SUCCESS"} = 1; 34a75fececSSteven Rostedt$default{"POWEROFF_ON_SUCCESS"} = 0; 35a75fececSSteven Rostedt$default{"BUILD_OPTIONS"} = ""; 36a75fececSSteven Rostedt$default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects 37a75fececSSteven Rostedt$default{"CLEAR_LOG"} = 0; 38a75fececSSteven Rostedt$default{"SUCCESS_LINE"} = "login:"; 39a75fececSSteven Rostedt$default{"BOOTED_TIMEOUT"} = 1; 40a75fececSSteven Rostedt$default{"DIE_ON_FAILURE"} = 1; 412545eb61SSteven Rostedt 422545eb61SSteven Rostedtmy $version; 43a75fececSSteven Rostedtmy $machine; 44a75fececSSteven Rostedtmy $tmpdir; 45a75fececSSteven Rostedtmy $builddir; 46a75fececSSteven Rostedtmy $outputdir; 47a75fececSSteven Rostedtmy $test_type; 487faafbd6SSteven Rostedtmy $build_type; 49a75fececSSteven Rostedtmy $build_options; 50a75fececSSteven Rostedtmy $reboot_type; 51a75fececSSteven Rostedtmy $reboot_script; 52a75fececSSteven Rostedtmy $power_cycle; 53a75fececSSteven Rostedtmy $reboot_on_error; 54a75fececSSteven Rostedtmy $poweroff_on_error; 55a75fececSSteven Rostedtmy $die_on_failure; 56a75fececSSteven Rostedtmy $power_off; 57a75fececSSteven Rostedtmy $grub_menu; 582545eb61SSteven Rostedtmy $grub_number; 592545eb61SSteven Rostedtmy $target; 602545eb61SSteven Rostedtmy $make; 61*8b37ca8cSSteven Rostedtmy $post_install; 625c42fc5bSSteven Rostedtmy $noclean; 635f9b6cedSSteven Rostedtmy $minconfig; 642b7d9b21SSteven Rostedtmy $addconfig; 655f9b6cedSSteven Rostedtmy $in_bisect = 0; 665f9b6cedSSteven Rostedtmy $bisect_bad = ""; 67d6ce2a0bSSteven Rostedtmy $reverse_bisect; 686c5ee0beSSteven Rostedtmy $in_patchcheck = 0; 695a391fbfSSteven Rostedtmy $run_test; 706c5ee0beSSteven Rostedtmy $redirect; 717faafbd6SSteven Rostedtmy $buildlog; 727faafbd6SSteven Rostedtmy $dmesg; 737faafbd6SSteven Rostedtmy $monitor_fp; 747faafbd6SSteven Rostedtmy $monitor_pid; 757faafbd6SSteven Rostedtmy $monitor_cnt = 0; 76a75fececSSteven Rostedtmy $sleep_time; 77a75fececSSteven Rostedtmy $bisect_sleep_time; 78a75fececSSteven Rostedtmy $store_failures; 79a75fececSSteven Rostedtmy $timeout; 80a75fececSSteven Rostedtmy $booted_timeout; 81a75fececSSteven Rostedtmy $console; 82a75fececSSteven Rostedtmy $success_line; 83a75fececSSteven Rostedtmy $build_target; 84a75fececSSteven Rostedtmy $target_image; 85a75fececSSteven Rostedtmy $localversion; 862545eb61SSteven Rostedt 872545eb61SSteven Rostedtsub read_config { 882545eb61SSteven Rostedt my ($config) = @_; 892545eb61SSteven Rostedt 902545eb61SSteven Rostedt open(IN, $config) || die "can't read file $config"; 912545eb61SSteven Rostedt 922545eb61SSteven Rostedt while (<IN>) { 932545eb61SSteven Rostedt 942545eb61SSteven Rostedt # ignore blank lines and comments 952545eb61SSteven Rostedt next if (/^\s*$/ || /\s*\#/); 962545eb61SSteven Rostedt 972545eb61SSteven Rostedt if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) { 982545eb61SSteven Rostedt my $lvalue = $1; 992545eb61SSteven Rostedt my $rvalue = $2; 1002545eb61SSteven Rostedt 101a75fececSSteven Rostedt if (defined($opt{$lvalue})) { 102a75fececSSteven Rostedt die "Error: Option $lvalue defined more than once!\n"; 103a75fececSSteven Rostedt } 1042545eb61SSteven Rostedt $opt{$lvalue} = $rvalue; 1052545eb61SSteven Rostedt } 1062545eb61SSteven Rostedt } 1072545eb61SSteven Rostedt 1082545eb61SSteven Rostedt close(IN); 109a75fececSSteven Rostedt 110a75fececSSteven Rostedt # set any defaults 111a75fececSSteven Rostedt 112a75fececSSteven Rostedt foreach my $default (keys %default) { 113a75fececSSteven Rostedt if (!defined($opt{$default})) { 114a75fececSSteven Rostedt $opt{$default} = $default{$default}; 115a75fececSSteven Rostedt } 116a75fececSSteven Rostedt } 1172545eb61SSteven Rostedt} 1182545eb61SSteven Rostedt 1195f9b6cedSSteven Rostedtsub logit { 1202545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 1212545eb61SSteven Rostedt open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 1222545eb61SSteven Rostedt print OUT @_; 1232545eb61SSteven Rostedt close(OUT); 1242545eb61SSteven Rostedt } 1252545eb61SSteven Rostedt} 1262545eb61SSteven Rostedt 1275f9b6cedSSteven Rostedtsub doprint { 1285f9b6cedSSteven Rostedt print @_; 1295f9b6cedSSteven Rostedt logit @_; 1305f9b6cedSSteven Rostedt} 1315f9b6cedSSteven Rostedt 1327faafbd6SSteven Rostedtsub run_command; 1337faafbd6SSteven Rostedt 1347faafbd6SSteven Rostedtsub reboot { 1357faafbd6SSteven Rostedt # try to reboot normally 1367faafbd6SSteven Rostedt if (!run_command "ssh $target reboot") { 1377faafbd6SSteven Rostedt # nope? power cycle it. 138a75fececSSteven Rostedt run_command "$power_cycle"; 1397faafbd6SSteven Rostedt } 1407faafbd6SSteven Rostedt} 1417faafbd6SSteven Rostedt 1425c42fc5bSSteven Rostedtsub dodie { 1435a391fbfSSteven Rostedt doprint "CRITICAL FAILURE... ", @_, "\n"; 1445c42fc5bSSteven Rostedt 145a75fececSSteven Rostedt if ($reboot_on_error && $test_type ne "build") { 14675c3fda7SSteven Rostedt doprint "REBOOTING\n"; 1477faafbd6SSteven Rostedt reboot; 14875c3fda7SSteven Rostedt 149a75fececSSteven Rostedt } elsif ($poweroff_on_error && defined($power_off)) { 1505c42fc5bSSteven Rostedt doprint "POWERING OFF\n"; 151a75fececSSteven Rostedt `$power_off`; 1525c42fc5bSSteven Rostedt } 15375c3fda7SSteven Rostedt 1545c42fc5bSSteven Rostedt die @_; 1555c42fc5bSSteven Rostedt} 1565c42fc5bSSteven Rostedt 1577faafbd6SSteven Rostedtsub open_console { 1587faafbd6SSteven Rostedt my ($fp) = @_; 1597faafbd6SSteven Rostedt 1607faafbd6SSteven Rostedt my $flags; 1617faafbd6SSteven Rostedt 162a75fececSSteven Rostedt my $pid = open($fp, "$console|") or 163a75fececSSteven Rostedt dodie "Can't open console $console"; 1647faafbd6SSteven Rostedt 1657faafbd6SSteven Rostedt $flags = fcntl($fp, F_GETFL, 0) or 1667faafbd6SSteven Rostedt dodie "Can't get flags for the socket: $!\n"; 1677faafbd6SSteven Rostedt $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or 1687faafbd6SSteven Rostedt dodie "Can't set flags for the socket: $!\n"; 1697faafbd6SSteven Rostedt 1707faafbd6SSteven Rostedt return $pid; 1717faafbd6SSteven Rostedt} 1727faafbd6SSteven Rostedt 1737faafbd6SSteven Rostedtsub close_console { 1747faafbd6SSteven Rostedt my ($fp, $pid) = @_; 1757faafbd6SSteven Rostedt 1767faafbd6SSteven Rostedt doprint "kill child process $pid\n"; 1777faafbd6SSteven Rostedt kill 2, $pid; 1787faafbd6SSteven Rostedt 1797faafbd6SSteven Rostedt print "closing!\n"; 1807faafbd6SSteven Rostedt close($fp); 1817faafbd6SSteven Rostedt} 1827faafbd6SSteven Rostedt 1837faafbd6SSteven Rostedtsub start_monitor { 1847faafbd6SSteven Rostedt if ($monitor_cnt++) { 1857faafbd6SSteven Rostedt return; 1867faafbd6SSteven Rostedt } 1877faafbd6SSteven Rostedt $monitor_fp = \*MONFD; 1887faafbd6SSteven Rostedt $monitor_pid = open_console $monitor_fp; 189a75fececSSteven Rostedt 190a75fececSSteven Rostedt return; 191a75fececSSteven Rostedt 192a75fececSSteven Rostedt open(MONFD, "Stop perl from warning about single use of MONFD"); 1937faafbd6SSteven Rostedt} 1947faafbd6SSteven Rostedt 1957faafbd6SSteven Rostedtsub end_monitor { 1967faafbd6SSteven Rostedt if (--$monitor_cnt) { 1977faafbd6SSteven Rostedt return; 1987faafbd6SSteven Rostedt } 1997faafbd6SSteven Rostedt close_console($monitor_fp, $monitor_pid); 2007faafbd6SSteven Rostedt} 2017faafbd6SSteven Rostedt 2027faafbd6SSteven Rostedtsub wait_for_monitor { 2037faafbd6SSteven Rostedt my ($time) = @_; 2047faafbd6SSteven Rostedt my $line; 2057faafbd6SSteven Rostedt 206a75fececSSteven Rostedt doprint "** Wait for monitor to settle down **\n"; 2077faafbd6SSteven Rostedt 2087faafbd6SSteven Rostedt # read the monitor and wait for the system to calm down 2097faafbd6SSteven Rostedt do { 2107faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, $time); 211a75fececSSteven Rostedt print "$line" if (defined($line)); 2127faafbd6SSteven Rostedt } while (defined($line)); 213a75fececSSteven Rostedt print "** Monitor flushed **\n"; 2147faafbd6SSteven Rostedt} 2157faafbd6SSteven Rostedt 2162b7d9b21SSteven Rostedtsub fail { 2172b7d9b21SSteven Rostedt 218a75fececSSteven Rostedt if ($die_on_failure) { 2192b7d9b21SSteven Rostedt dodie @_; 2202b7d9b21SSteven Rostedt } 2212b7d9b21SSteven Rostedt 222a75fececSSteven Rostedt doprint "FAILED\n"; 2237faafbd6SSteven Rostedt 224a75fececSSteven Rostedt # no need to reboot for just building. 225a75fececSSteven Rostedt if ($test_type ne "build") { 2267faafbd6SSteven Rostedt doprint "REBOOTING\n"; 2277faafbd6SSteven Rostedt reboot; 2287faafbd6SSteven Rostedt start_monitor; 229a75fececSSteven Rostedt wait_for_monitor $sleep_time; 2307faafbd6SSteven Rostedt end_monitor; 231a75fececSSteven Rostedt } 2327faafbd6SSteven Rostedt 233a75fececSSteven Rostedt doprint "**** Failed: ", @_, " ****\n"; 234a75fececSSteven Rostedt 235a75fececSSteven Rostedt return 1 if (!defined($store_failures)); 2367faafbd6SSteven Rostedt 2377faafbd6SSteven Rostedt my @t = localtime; 2387faafbd6SSteven Rostedt my $date = sprintf "%04d%02d%02d%02d%02d%02d", 2397faafbd6SSteven Rostedt 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; 2407faafbd6SSteven Rostedt 241a75fececSSteven Rostedt my $dir = "$machine-$test_type-$build_type-fail-$date"; 242a75fececSSteven Rostedt my $faildir = "$store_failures/$dir"; 2437faafbd6SSteven Rostedt 2447faafbd6SSteven Rostedt if (!-d $faildir) { 2457faafbd6SSteven Rostedt mkpath($faildir) or 246a75fececSSteven Rostedt die "can't create $faildir"; 2477faafbd6SSteven Rostedt } 248a75fececSSteven Rostedt if (-f "$outputdir/.config") { 249a75fececSSteven Rostedt cp "$outputdir/.config", "$faildir/config" or 2507faafbd6SSteven Rostedt die "failed to copy .config"; 2517faafbd6SSteven Rostedt } 2527faafbd6SSteven Rostedt if (-f $buildlog) { 2537faafbd6SSteven Rostedt cp $buildlog, "$faildir/buildlog" or 2547faafbd6SSteven Rostedt die "failed to move $buildlog"; 2557faafbd6SSteven Rostedt } 2567faafbd6SSteven Rostedt if (-f $dmesg) { 2577faafbd6SSteven Rostedt cp $dmesg, "$faildir/dmesg" or 2587faafbd6SSteven Rostedt die "failed to move $dmesg"; 2597faafbd6SSteven Rostedt } 2607faafbd6SSteven Rostedt 2617faafbd6SSteven Rostedt doprint "*** Saved info to $faildir ***\n"; 2627faafbd6SSteven Rostedt 2632b7d9b21SSteven Rostedt return 1; 2642b7d9b21SSteven Rostedt} 2652b7d9b21SSteven Rostedt 2662545eb61SSteven Rostedtsub run_command { 2672545eb61SSteven Rostedt my ($command) = @_; 268d6ce2a0bSSteven Rostedt my $dolog = 0; 269d6ce2a0bSSteven Rostedt my $dord = 0; 270d6ce2a0bSSteven Rostedt my $pid; 271d6ce2a0bSSteven Rostedt 272d6ce2a0bSSteven Rostedt doprint("$command ... "); 273d6ce2a0bSSteven Rostedt 274d6ce2a0bSSteven Rostedt $pid = open(CMD, "$command 2>&1 |") or 2752b7d9b21SSteven Rostedt (fail "unable to exec $command" and return 0); 2762545eb61SSteven Rostedt 2772545eb61SSteven Rostedt if (defined($opt{"LOG_FILE"})) { 278d6ce2a0bSSteven Rostedt open(LOG, ">>$opt{LOG_FILE}") or 279d6ce2a0bSSteven Rostedt dodie "failed to write to log"; 280d6ce2a0bSSteven Rostedt $dolog = 1; 2816c5ee0beSSteven Rostedt } 2826c5ee0beSSteven Rostedt 2836c5ee0beSSteven Rostedt if (defined($redirect)) { 284d6ce2a0bSSteven Rostedt open (RD, ">$redirect") or 285d6ce2a0bSSteven Rostedt dodie "failed to write to redirect $redirect"; 286d6ce2a0bSSteven Rostedt $dord = 1; 2872545eb61SSteven Rostedt } 2882545eb61SSteven Rostedt 289d6ce2a0bSSteven Rostedt while (<CMD>) { 290d6ce2a0bSSteven Rostedt print LOG if ($dolog); 291d6ce2a0bSSteven Rostedt print RD if ($dord); 292d6ce2a0bSSteven Rostedt } 2932545eb61SSteven Rostedt 294d6ce2a0bSSteven Rostedt waitpid($pid, 0); 2952545eb61SSteven Rostedt my $failed = $?; 2962545eb61SSteven Rostedt 297d6ce2a0bSSteven Rostedt close(CMD); 298d6ce2a0bSSteven Rostedt close(LOG) if ($dolog); 299d6ce2a0bSSteven Rostedt close(RD) if ($dord); 300d6ce2a0bSSteven Rostedt 3012545eb61SSteven Rostedt if ($failed) { 3022545eb61SSteven Rostedt doprint "FAILED!\n"; 3032545eb61SSteven Rostedt } else { 3042545eb61SSteven Rostedt doprint "SUCCESS\n"; 3052545eb61SSteven Rostedt } 3062545eb61SSteven Rostedt 3075f9b6cedSSteven Rostedt return !$failed; 3085f9b6cedSSteven Rostedt} 3095f9b6cedSSteven Rostedt 3105f9b6cedSSteven Rostedtsub get_grub_index { 3115f9b6cedSSteven Rostedt 312a75fececSSteven Rostedt if ($reboot_type ne "grub") { 313a75fececSSteven Rostedt return; 314a75fececSSteven Rostedt } 3155a391fbfSSteven Rostedt return if (defined($grub_number)); 3165f9b6cedSSteven Rostedt 3175f9b6cedSSteven Rostedt doprint "Find grub menu ... "; 3185f9b6cedSSteven Rostedt $grub_number = -1; 3195f9b6cedSSteven Rostedt open(IN, "ssh $target cat /boot/grub/menu.lst |") 3205f9b6cedSSteven Rostedt or die "unable to get menu.lst"; 3215f9b6cedSSteven Rostedt while (<IN>) { 322a75fececSSteven Rostedt if (/^\s*title\s+$grub_menu\s*$/) { 3235f9b6cedSSteven Rostedt $grub_number++; 3245f9b6cedSSteven Rostedt last; 3255f9b6cedSSteven Rostedt } elsif (/^\s*title\s/) { 3265f9b6cedSSteven Rostedt $grub_number++; 3275f9b6cedSSteven Rostedt } 3285f9b6cedSSteven Rostedt } 3295f9b6cedSSteven Rostedt close(IN); 3305f9b6cedSSteven Rostedt 331a75fececSSteven Rostedt die "Could not find '$grub_menu' in /boot/grub/menu on $machine" 3325f9b6cedSSteven Rostedt if ($grub_number < 0); 3335f9b6cedSSteven Rostedt doprint "$grub_number\n"; 3342545eb61SSteven Rostedt} 3352545eb61SSteven Rostedt 3362545eb61SSteven Rostedtsub wait_for_input 3372545eb61SSteven Rostedt{ 3382545eb61SSteven Rostedt my ($fp, $time) = @_; 3392545eb61SSteven Rostedt my $rin; 3402545eb61SSteven Rostedt my $ready; 3412545eb61SSteven Rostedt my $line; 3422545eb61SSteven Rostedt my $ch; 3432545eb61SSteven Rostedt 3442545eb61SSteven Rostedt if (!defined($time)) { 3452545eb61SSteven Rostedt $time = $timeout; 3462545eb61SSteven Rostedt } 3472545eb61SSteven Rostedt 3482545eb61SSteven Rostedt $rin = ''; 3492545eb61SSteven Rostedt vec($rin, fileno($fp), 1) = 1; 3502545eb61SSteven Rostedt $ready = select($rin, undef, undef, $time); 3512545eb61SSteven Rostedt 3522545eb61SSteven Rostedt $line = ""; 3532545eb61SSteven Rostedt 3542545eb61SSteven Rostedt # try to read one char at a time 3552545eb61SSteven Rostedt while (sysread $fp, $ch, 1) { 3562545eb61SSteven Rostedt $line .= $ch; 3572545eb61SSteven Rostedt last if ($ch eq "\n"); 3582545eb61SSteven Rostedt } 3592545eb61SSteven Rostedt 3602545eb61SSteven Rostedt if (!length($line)) { 3612545eb61SSteven Rostedt return undef; 3622545eb61SSteven Rostedt } 3632545eb61SSteven Rostedt 3642545eb61SSteven Rostedt return $line; 3652545eb61SSteven Rostedt} 3662545eb61SSteven Rostedt 36775c3fda7SSteven Rostedtsub reboot_to { 368a75fececSSteven Rostedt if ($reboot_type eq "grub") { 3692545eb61SSteven Rostedt run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; 370a75fececSSteven Rostedt return; 371a75fececSSteven Rostedt } 372a75fececSSteven Rostedt 373a75fececSSteven Rostedt run_command "$reboot_script"; 3742545eb61SSteven Rostedt} 3752545eb61SSteven Rostedt 3765a391fbfSSteven Rostedtsub monitor { 3772545eb61SSteven Rostedt my $booted = 0; 3782545eb61SSteven Rostedt my $bug = 0; 3795c42fc5bSSteven Rostedt my $skip_call_trace = 0; 3802b7d9b21SSteven Rostedt my $loops; 3812545eb61SSteven Rostedt 3827faafbd6SSteven Rostedt wait_for_monitor 5; 3832545eb61SSteven Rostedt 3842545eb61SSteven Rostedt my $line; 3852545eb61SSteven Rostedt my $full_line = ""; 3862545eb61SSteven Rostedt 3877faafbd6SSteven Rostedt open(DMESG, "> $dmesg") or 3887faafbd6SSteven Rostedt die "unable to write to $dmesg"; 3892545eb61SSteven Rostedt 39075c3fda7SSteven Rostedt reboot_to; 3912545eb61SSteven Rostedt 3922545eb61SSteven Rostedt for (;;) { 3932545eb61SSteven Rostedt 3942b7d9b21SSteven Rostedt if ($booted) { 395a75fececSSteven Rostedt $line = wait_for_input($monitor_fp, $booted_timeout); 3962b7d9b21SSteven Rostedt } else { 3977faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp); 3982b7d9b21SSteven Rostedt } 3992545eb61SSteven Rostedt 4002545eb61SSteven Rostedt last if (!defined($line)); 4012545eb61SSteven Rostedt 4022545eb61SSteven Rostedt doprint $line; 4037faafbd6SSteven Rostedt print DMESG $line; 4042545eb61SSteven Rostedt 4052545eb61SSteven Rostedt # we are not guaranteed to get a full line 4062545eb61SSteven Rostedt $full_line .= $line; 4072545eb61SSteven Rostedt 408a75fececSSteven Rostedt if ($full_line =~ /$success_line/) { 4092545eb61SSteven Rostedt $booted = 1; 4102545eb61SSteven Rostedt } 4112545eb61SSteven Rostedt 4125c42fc5bSSteven Rostedt if ($full_line =~ /\[ backtrace testing \]/) { 4135c42fc5bSSteven Rostedt $skip_call_trace = 1; 4145c42fc5bSSteven Rostedt } 4155c42fc5bSSteven Rostedt 4162545eb61SSteven Rostedt if ($full_line =~ /call trace:/i) { 4175c42fc5bSSteven Rostedt $bug = 1 if (!$skip_call_trace); 4185c42fc5bSSteven Rostedt } 4195c42fc5bSSteven Rostedt 4205c42fc5bSSteven Rostedt if ($full_line =~ /\[ end of backtrace testing \]/) { 4215c42fc5bSSteven Rostedt $skip_call_trace = 0; 4225c42fc5bSSteven Rostedt } 4235c42fc5bSSteven Rostedt 4245c42fc5bSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 4252545eb61SSteven Rostedt $bug = 1; 4262545eb61SSteven Rostedt } 4272545eb61SSteven Rostedt 4282545eb61SSteven Rostedt if ($line =~ /\n/) { 4292545eb61SSteven Rostedt $full_line = ""; 4302545eb61SSteven Rostedt } 4312545eb61SSteven Rostedt } 4322545eb61SSteven Rostedt 4337faafbd6SSteven Rostedt close(DMESG); 4342545eb61SSteven Rostedt 4352545eb61SSteven Rostedt if ($bug) { 4362b7d9b21SSteven Rostedt return 0 if ($in_bisect); 4372b7d9b21SSteven Rostedt fail "failed - got a bug report\n" and return 0; 4382545eb61SSteven Rostedt } 4395f9b6cedSSteven Rostedt 440a75fececSSteven Rostedt if (!$booted) { 441a75fececSSteven Rostedt return 0 if ($in_bisect); 442a75fececSSteven Rostedt fail "failed - never got a boot prompt.\n" and return 0; 443a75fececSSteven Rostedt } 444a75fececSSteven Rostedt 4452b7d9b21SSteven Rostedt return 1; 4462545eb61SSteven Rostedt} 4472545eb61SSteven Rostedt 4482545eb61SSteven Rostedtsub install { 4492545eb61SSteven Rostedt 450a75fececSSteven Rostedt run_command "scp $outputdir/$build_target $target:$target_image" or 4515c42fc5bSSteven Rostedt dodie "failed to copy image"; 4525f9b6cedSSteven Rostedt 4535f9b6cedSSteven Rostedt my $install_mods = 0; 4545f9b6cedSSteven Rostedt 4555f9b6cedSSteven Rostedt # should we process modules? 4565f9b6cedSSteven Rostedt $install_mods = 0; 457a75fececSSteven Rostedt open(IN, "$outputdir/.config") or dodie("Can't read config file"); 4585f9b6cedSSteven Rostedt while (<IN>) { 4595f9b6cedSSteven Rostedt if (/CONFIG_MODULES(=y)?/) { 4605f9b6cedSSteven Rostedt $install_mods = 1 if (defined($1)); 4615f9b6cedSSteven Rostedt last; 4625f9b6cedSSteven Rostedt } 4635f9b6cedSSteven Rostedt } 4645f9b6cedSSteven Rostedt close(IN); 4655f9b6cedSSteven Rostedt 4665f9b6cedSSteven Rostedt if (!$install_mods) { 4675f9b6cedSSteven Rostedt doprint "No modules needed\n"; 4685f9b6cedSSteven Rostedt return; 4692545eb61SSteven Rostedt } 4702545eb61SSteven Rostedt 471a75fececSSteven Rostedt run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or 4725f9b6cedSSteven Rostedt dodie "Failed to install modules"; 4735f9b6cedSSteven Rostedt 4742545eb61SSteven Rostedt my $modlib = "/lib/modules/$version"; 4755c42fc5bSSteven Rostedt my $modtar = "autotest-mods.tar.bz2"; 4762545eb61SSteven Rostedt 4775f9b6cedSSteven Rostedt run_command "ssh $target rm -rf $modlib" or 4785c42fc5bSSteven Rostedt dodie "failed to remove old mods: $modlib"; 4792545eb61SSteven Rostedt 4805c42fc5bSSteven Rostedt # would be nice if scp -r did not follow symbolic links 481a75fececSSteven Rostedt run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or 4825c42fc5bSSteven Rostedt dodie "making tarball"; 4835c42fc5bSSteven Rostedt 484a75fececSSteven Rostedt run_command "scp $tmpdir/$modtar $target:/tmp" or 4855c42fc5bSSteven Rostedt dodie "failed to copy modules"; 4865c42fc5bSSteven Rostedt 487a75fececSSteven Rostedt unlink "$tmpdir/$modtar"; 4885c42fc5bSSteven Rostedt 4895f9b6cedSSteven Rostedt run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or 4905c42fc5bSSteven Rostedt dodie "failed to tar modules"; 4915c42fc5bSSteven Rostedt 4925c42fc5bSSteven Rostedt run_command "ssh $target rm -f /tmp/$modtar"; 493*8b37ca8cSSteven Rostedt 494*8b37ca8cSSteven Rostedt return if (!defined($post_install)); 495*8b37ca8cSSteven Rostedt 496*8b37ca8cSSteven Rostedt my $save_env = $ENV{KERNEL_VERSION}; 497*8b37ca8cSSteven Rostedt 498*8b37ca8cSSteven Rostedt $ENV{KERNEL_VERSION} = $version; 499*8b37ca8cSSteven Rostedt run_command "$post_install"; 500*8b37ca8cSSteven Rostedt 501*8b37ca8cSSteven Rostedt $ENV{KERNEL_VERSION} = $save_env; 5022545eb61SSteven Rostedt} 5032545eb61SSteven Rostedt 5046c5ee0beSSteven Rostedtsub check_buildlog { 5056c5ee0beSSteven Rostedt my ($patch) = @_; 5066c5ee0beSSteven Rostedt 5076c5ee0beSSteven Rostedt my @files = `git show $patch | diffstat -l`; 5086c5ee0beSSteven Rostedt 5096c5ee0beSSteven Rostedt open(IN, "git show $patch |") or 5106c5ee0beSSteven Rostedt dodie "failed to show $patch"; 5116c5ee0beSSteven Rostedt while (<IN>) { 5126c5ee0beSSteven Rostedt if (m,^--- a/(.*),) { 5136c5ee0beSSteven Rostedt chomp $1; 5146c5ee0beSSteven Rostedt $files[$#files] = $1; 5156c5ee0beSSteven Rostedt } 5166c5ee0beSSteven Rostedt } 5176c5ee0beSSteven Rostedt close(IN); 5186c5ee0beSSteven Rostedt 5196c5ee0beSSteven Rostedt open(IN, $buildlog) or dodie "Can't open $buildlog"; 5206c5ee0beSSteven Rostedt while (<IN>) { 5216c5ee0beSSteven Rostedt if (/^\s*(.*?):.*(warning|error)/) { 5226c5ee0beSSteven Rostedt my $err = $1; 5236c5ee0beSSteven Rostedt foreach my $file (@files) { 524a75fececSSteven Rostedt my $fullpath = "$builddir/$file"; 5256c5ee0beSSteven Rostedt if ($file eq $err || $fullpath eq $err) { 5262b7d9b21SSteven Rostedt fail "$file built with warnings" and return 0; 5276c5ee0beSSteven Rostedt } 5286c5ee0beSSteven Rostedt } 5296c5ee0beSSteven Rostedt } 5306c5ee0beSSteven Rostedt } 5316c5ee0beSSteven Rostedt close(IN); 5322b7d9b21SSteven Rostedt 5332b7d9b21SSteven Rostedt return 1; 5346c5ee0beSSteven Rostedt} 5356c5ee0beSSteven Rostedt 5362545eb61SSteven Rostedtsub build { 5372545eb61SSteven Rostedt my ($type) = @_; 5385c42fc5bSSteven Rostedt my $defconfig = ""; 5395c42fc5bSSteven Rostedt my $append = ""; 5402545eb61SSteven Rostedt 5417faafbd6SSteven Rostedt unlink $buildlog; 5427faafbd6SSteven Rostedt 54375c3fda7SSteven Rostedt if ($type =~ /^useconfig:(.*)/) { 544a75fececSSteven Rostedt run_command "cp $1 $outputdir/.config" or 54575c3fda7SSteven Rostedt dodie "could not copy $1 to .config"; 5465f9b6cedSSteven Rostedt 54775c3fda7SSteven Rostedt $type = "oldconfig"; 54875c3fda7SSteven Rostedt } 54975c3fda7SSteven Rostedt 5505c42fc5bSSteven Rostedt # old config can ask questions 5515c42fc5bSSteven Rostedt if ($type eq "oldconfig") { 5525c42fc5bSSteven Rostedt $append = "yes ''|"; 55375c3fda7SSteven Rostedt 55475c3fda7SSteven Rostedt # allow for empty configs 555a75fececSSteven Rostedt run_command "touch $outputdir/.config"; 55675c3fda7SSteven Rostedt 557a75fececSSteven Rostedt run_command "mv $outputdir/.config $outputdir/config_temp" or 5585c42fc5bSSteven Rostedt dodie "moving .config"; 5595c42fc5bSSteven Rostedt 5605f9b6cedSSteven Rostedt if (!$noclean && !run_command "$make mrproper") { 5615c42fc5bSSteven Rostedt dodie "make mrproper"; 5625c42fc5bSSteven Rostedt } 5635c42fc5bSSteven Rostedt 564a75fececSSteven Rostedt run_command "mv $outputdir/config_temp $outputdir/.config" or 5655c42fc5bSSteven Rostedt dodie "moving config_temp"; 5665c42fc5bSSteven Rostedt 5675c42fc5bSSteven Rostedt } elsif (!$noclean) { 568a75fececSSteven Rostedt unlink "$outputdir/.config"; 5695f9b6cedSSteven Rostedt run_command "$make mrproper" or 5705c42fc5bSSteven Rostedt dodie "make mrproper"; 5715c42fc5bSSteven Rostedt } 5722545eb61SSteven Rostedt 5732545eb61SSteven Rostedt # add something to distinguish this build 574a75fececSSteven Rostedt open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file"); 575a75fececSSteven Rostedt print OUT "$localversion\n"; 5762545eb61SSteven Rostedt close(OUT); 5772545eb61SSteven Rostedt 5785f9b6cedSSteven Rostedt if (defined($minconfig)) { 5795f9b6cedSSteven Rostedt $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; 5802545eb61SSteven Rostedt } 5812545eb61SSteven Rostedt 582a75fececSSteven Rostedt run_command "$append $defconfig $make $type" or 5835c42fc5bSSteven Rostedt dodie "failed make config"; 5842545eb61SSteven Rostedt 585a75fececSSteven Rostedt $redirect = "$buildlog"; 586a75fececSSteven Rostedt if (!run_command "$make $build_options") { 5876c5ee0beSSteven Rostedt undef $redirect; 5885f9b6cedSSteven Rostedt # bisect may need this to pass 5892b7d9b21SSteven Rostedt return 0 if ($in_bisect); 5902b7d9b21SSteven Rostedt fail "failed build" and return 0; 5912545eb61SSteven Rostedt } 5926c5ee0beSSteven Rostedt undef $redirect; 5935f9b6cedSSteven Rostedt 5942b7d9b21SSteven Rostedt return 1; 5952545eb61SSteven Rostedt} 5962545eb61SSteven Rostedt 59775c3fda7SSteven Rostedtsub halt { 598a75fececSSteven Rostedt if (!run_command "ssh $target halt" or defined($power_off)) { 59975c3fda7SSteven Rostedt # nope? the zap it! 600a75fececSSteven Rostedt run_command "$power_off"; 60175c3fda7SSteven Rostedt } 60275c3fda7SSteven Rostedt} 60375c3fda7SSteven Rostedt 6045f9b6cedSSteven Rostedtsub success { 6055f9b6cedSSteven Rostedt my ($i) = @_; 6065f9b6cedSSteven Rostedt 6075f9b6cedSSteven Rostedt doprint "\n\n*******************************************\n"; 6085f9b6cedSSteven Rostedt doprint "*******************************************\n"; 609a75fececSSteven Rostedt doprint "** TEST $i SUCCESS!!!! **\n"; 6105f9b6cedSSteven Rostedt doprint "*******************************************\n"; 6115f9b6cedSSteven Rostedt doprint "*******************************************\n"; 6125f9b6cedSSteven Rostedt 613a75fececSSteven Rostedt if ($i != $opt{"NUM_TESTS"} && $test_type ne "build" && 614a75fececSSteven Rostedt !($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") && 615a75fececSSteven Rostedt !($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build")) { 616a75fececSSteven Rostedt doprint "Reboot and wait $sleep_time seconds\n"; 6175f9b6cedSSteven Rostedt reboot; 6187faafbd6SSteven Rostedt start_monitor; 619a75fececSSteven Rostedt wait_for_monitor $sleep_time; 6207faafbd6SSteven Rostedt end_monitor; 6215f9b6cedSSteven Rostedt } 6225f9b6cedSSteven Rostedt} 6235f9b6cedSSteven Rostedt 6245f9b6cedSSteven Rostedtsub get_version { 6255f9b6cedSSteven Rostedt # get the release name 6265f9b6cedSSteven Rostedt doprint "$make kernelrelease ... "; 6275f9b6cedSSteven Rostedt $version = `$make kernelrelease | tail -1`; 6285f9b6cedSSteven Rostedt chomp($version); 6295f9b6cedSSteven Rostedt doprint "$version\n"; 6305f9b6cedSSteven Rostedt} 6315f9b6cedSSteven Rostedt 6325a391fbfSSteven Rostedtsub child_run_test { 6337faafbd6SSteven Rostedt my $failed = 0; 6345a391fbfSSteven Rostedt 6357faafbd6SSteven Rostedt # child should have no power 636a75fececSSteven Rostedt $reboot_on_error = 0; 637a75fececSSteven Rostedt $poweroff_on_error = 0; 638a75fececSSteven Rostedt $die_on_failure = 1; 6397faafbd6SSteven Rostedt 6407faafbd6SSteven Rostedt run_command $run_test or $failed = 1; 6415a391fbfSSteven Rostedt exit $failed; 6425a391fbfSSteven Rostedt} 6435a391fbfSSteven Rostedt 6445a391fbfSSteven Rostedtmy $child_done; 6455a391fbfSSteven Rostedt 6465a391fbfSSteven Rostedtsub child_finished { 6475a391fbfSSteven Rostedt $child_done = 1; 6485a391fbfSSteven Rostedt} 6495a391fbfSSteven Rostedt 6505a391fbfSSteven Rostedtsub do_run_test { 6515a391fbfSSteven Rostedt my $child_pid; 6525a391fbfSSteven Rostedt my $child_exit; 6535a391fbfSSteven Rostedt my $line; 6545a391fbfSSteven Rostedt my $full_line; 6555a391fbfSSteven Rostedt my $bug = 0; 6565a391fbfSSteven Rostedt 6577faafbd6SSteven Rostedt wait_for_monitor 1; 6585a391fbfSSteven Rostedt 6597faafbd6SSteven Rostedt doprint "run test $run_test\n"; 6605a391fbfSSteven Rostedt 6615a391fbfSSteven Rostedt $child_done = 0; 6625a391fbfSSteven Rostedt 6635a391fbfSSteven Rostedt $SIG{CHLD} = qw(child_finished); 6645a391fbfSSteven Rostedt 6655a391fbfSSteven Rostedt $child_pid = fork; 6665a391fbfSSteven Rostedt 6675a391fbfSSteven Rostedt child_run_test if (!$child_pid); 6685a391fbfSSteven Rostedt 6695a391fbfSSteven Rostedt $full_line = ""; 6705a391fbfSSteven Rostedt 6715a391fbfSSteven Rostedt do { 6727faafbd6SSteven Rostedt $line = wait_for_input($monitor_fp, 1); 6735a391fbfSSteven Rostedt if (defined($line)) { 6745a391fbfSSteven Rostedt 6755a391fbfSSteven Rostedt # we are not guaranteed to get a full line 6765a391fbfSSteven Rostedt $full_line .= $line; 6775a391fbfSSteven Rostedt 6785a391fbfSSteven Rostedt if ($full_line =~ /call trace:/i) { 6795a391fbfSSteven Rostedt $bug = 1; 6805a391fbfSSteven Rostedt } 6815a391fbfSSteven Rostedt 6825a391fbfSSteven Rostedt if ($full_line =~ /Kernel panic -/) { 6835a391fbfSSteven Rostedt $bug = 1; 6845a391fbfSSteven Rostedt } 6855a391fbfSSteven Rostedt 6865a391fbfSSteven Rostedt if ($line =~ /\n/) { 6875a391fbfSSteven Rostedt $full_line = ""; 6885a391fbfSSteven Rostedt } 6895a391fbfSSteven Rostedt } 6905a391fbfSSteven Rostedt } while (!$child_done && !$bug); 6915a391fbfSSteven Rostedt 6925a391fbfSSteven Rostedt if ($bug) { 6935a391fbfSSteven Rostedt doprint "Detected kernel crash!\n"; 6945a391fbfSSteven Rostedt # kill the child with extreme prejudice 6955a391fbfSSteven Rostedt kill 9, $child_pid; 6965a391fbfSSteven Rostedt } 6975a391fbfSSteven Rostedt 6985a391fbfSSteven Rostedt waitpid $child_pid, 0; 6995a391fbfSSteven Rostedt $child_exit = $?; 7005a391fbfSSteven Rostedt 7015a391fbfSSteven Rostedt if ($bug || $child_exit) { 7022b7d9b21SSteven Rostedt return 0 if $in_bisect; 7032b7d9b21SSteven Rostedt fail "test failed" and return 0; 7045a391fbfSSteven Rostedt } 7052b7d9b21SSteven Rostedt return 1; 7065a391fbfSSteven Rostedt} 7075a391fbfSSteven Rostedt 708a75fececSSteven Rostedtsub run_git_bisect { 709a75fececSSteven Rostedt my ($command) = @_; 710a75fececSSteven Rostedt 711a75fececSSteven Rostedt doprint "$command ... "; 712a75fececSSteven Rostedt 713a75fececSSteven Rostedt my $output = `$command 2>&1`; 714a75fececSSteven Rostedt my $ret = $?; 715a75fececSSteven Rostedt 716a75fececSSteven Rostedt logit $output; 717a75fececSSteven Rostedt 718a75fececSSteven Rostedt if ($ret) { 719a75fececSSteven Rostedt doprint "FAILED\n"; 720a75fececSSteven Rostedt dodie "Failed to git bisect"; 721a75fececSSteven Rostedt } 722a75fececSSteven Rostedt 723a75fececSSteven Rostedt doprint "SUCCESS\n"; 724a75fececSSteven Rostedt if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) { 725a75fececSSteven Rostedt doprint "$1 [$2]\n"; 726a75fececSSteven Rostedt } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) { 727a75fececSSteven Rostedt $bisect_bad = $1; 728a75fececSSteven Rostedt doprint "Found bad commit... $1\n"; 729a75fececSSteven Rostedt return 0; 730a75fececSSteven Rostedt } else { 731a75fececSSteven Rostedt # we already logged it, just print it now. 732a75fececSSteven Rostedt print $output; 733a75fececSSteven Rostedt } 734a75fececSSteven Rostedt 735a75fececSSteven Rostedt return 1; 736a75fececSSteven Rostedt} 737a75fececSSteven Rostedt 7385f9b6cedSSteven Rostedtsub run_bisect { 7395f9b6cedSSteven Rostedt my ($type) = @_; 7405f9b6cedSSteven Rostedt 7412b7d9b21SSteven Rostedt my $failed = 0; 7425f9b6cedSSteven Rostedt my $result; 7435f9b6cedSSteven Rostedt my $output; 7445f9b6cedSSteven Rostedt my $ret; 7455f9b6cedSSteven Rostedt 7465f9b6cedSSteven Rostedt if (defined($minconfig)) { 7472b7d9b21SSteven Rostedt build "useconfig:$minconfig" or $failed = 1; 7485f9b6cedSSteven Rostedt } else { 7495f9b6cedSSteven Rostedt # ?? no config to use? 7502b7d9b21SSteven Rostedt build "oldconfig" or $failed = 1; 7515f9b6cedSSteven Rostedt } 7525f9b6cedSSteven Rostedt 7535f9b6cedSSteven Rostedt if ($type ne "build") { 7547faafbd6SSteven Rostedt dodie "Failed on build" if $failed; 7555f9b6cedSSteven Rostedt 7565f9b6cedSSteven Rostedt # Now boot the box 7575f9b6cedSSteven Rostedt get_grub_index; 7585f9b6cedSSteven Rostedt get_version; 7595f9b6cedSSteven Rostedt install; 7607faafbd6SSteven Rostedt 7617faafbd6SSteven Rostedt start_monitor; 7622b7d9b21SSteven Rostedt monitor or $failed = 1; 7635f9b6cedSSteven Rostedt 7645f9b6cedSSteven Rostedt if ($type ne "boot") { 7657faafbd6SSteven Rostedt dodie "Failed on boot" if $failed; 7665a391fbfSSteven Rostedt 7672b7d9b21SSteven Rostedt do_run_test or $failed = 1; 7685f9b6cedSSteven Rostedt } 7697faafbd6SSteven Rostedt end_monitor; 7705f9b6cedSSteven Rostedt } 7715f9b6cedSSteven Rostedt 7725f9b6cedSSteven Rostedt if ($failed) { 7735f9b6cedSSteven Rostedt $result = "bad"; 7745a391fbfSSteven Rostedt 7755a391fbfSSteven Rostedt # reboot the box to a good kernel 776a75fececSSteven Rostedt if ($type ne "build") { 777a75fececSSteven Rostedt doprint "Reboot and sleep $bisect_sleep_time seconds\n"; 7785a391fbfSSteven Rostedt reboot; 7797faafbd6SSteven Rostedt start_monitor; 780a75fececSSteven Rostedt wait_for_monitor $bisect_sleep_time; 7817faafbd6SSteven Rostedt end_monitor; 7825a391fbfSSteven Rostedt } 7835f9b6cedSSteven Rostedt } else { 7845f9b6cedSSteven Rostedt $result = "good"; 7855f9b6cedSSteven Rostedt } 7865f9b6cedSSteven Rostedt 787d6ce2a0bSSteven Rostedt # Are we looking for where it worked, not failed? 788d6ce2a0bSSteven Rostedt if ($reverse_bisect) { 789d6ce2a0bSSteven Rostedt if ($failed) { 790d6ce2a0bSSteven Rostedt $result = "good"; 791d6ce2a0bSSteven Rostedt } else { 792d6ce2a0bSSteven Rostedt $result = "bad"; 793d6ce2a0bSSteven Rostedt } 794d6ce2a0bSSteven Rostedt } 795d6ce2a0bSSteven Rostedt 796a75fececSSteven Rostedt return $result; 7975f9b6cedSSteven Rostedt} 7985f9b6cedSSteven Rostedt 7995f9b6cedSSteven Rostedtsub bisect { 8005f9b6cedSSteven Rostedt my ($i) = @_; 8015f9b6cedSSteven Rostedt 8025f9b6cedSSteven Rostedt my $result; 8035f9b6cedSSteven Rostedt 8045f9b6cedSSteven Rostedt die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"})); 8055f9b6cedSSteven Rostedt die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"})); 8065f9b6cedSSteven Rostedt die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"})); 8075f9b6cedSSteven Rostedt 8085f9b6cedSSteven Rostedt my $good = $opt{"BISECT_GOOD[$i]"}; 8095f9b6cedSSteven Rostedt my $bad = $opt{"BISECT_BAD[$i]"}; 8105f9b6cedSSteven Rostedt my $type = $opt{"BISECT_TYPE[$i]"}; 811a75fececSSteven Rostedt my $start = $opt{"BISECT_START[$i]"}; 812a75fececSSteven Rostedt my $replay = $opt{"BISECT_REPLAY[$i]"}; 8135f9b6cedSSteven Rostedt 814d6ce2a0bSSteven Rostedt if (defined($opt{"BISECT_REVERSE[$i]"}) && 815d6ce2a0bSSteven Rostedt $opt{"BISECT_REVERSE[$i]"} == 1) { 816d6ce2a0bSSteven Rostedt doprint "Performing a reverse bisect (bad is good, good is bad!)\n"; 817d6ce2a0bSSteven Rostedt $reverse_bisect = 1; 818d6ce2a0bSSteven Rostedt } else { 819d6ce2a0bSSteven Rostedt $reverse_bisect = 0; 820d6ce2a0bSSteven Rostedt } 821d6ce2a0bSSteven Rostedt 8225f9b6cedSSteven Rostedt $in_bisect = 1; 8235f9b6cedSSteven Rostedt 8245a391fbfSSteven Rostedt # Can't have a test without having a test to run 8255a391fbfSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 8265a391fbfSSteven Rostedt $type = "boot"; 8275a391fbfSSteven Rostedt } 8285a391fbfSSteven Rostedt 829a75fececSSteven Rostedt my $check = $opt{"BISECT_CHECK[$i]"}; 830a75fececSSteven Rostedt if (defined($check) && $check ne "0") { 831a75fececSSteven Rostedt 832a75fececSSteven Rostedt # get current HEAD 833a75fececSSteven Rostedt doprint "git rev-list HEAD --max-count=1 ... "; 834a75fececSSteven Rostedt my $head = `git rev-list HEAD --max-count=1`; 835a75fececSSteven Rostedt my $ret = $?; 836a75fececSSteven Rostedt 837a75fececSSteven Rostedt logit $head; 838a75fececSSteven Rostedt 839a75fececSSteven Rostedt if ($ret) { 840a75fececSSteven Rostedt doprint "FAILED\n"; 841a75fececSSteven Rostedt dodie "Failed to get git HEAD"; 842a75fececSSteven Rostedt } 843a75fececSSteven Rostedt 844a75fececSSteven Rostedt print "SUCCESS\n"; 845a75fececSSteven Rostedt 846a75fececSSteven Rostedt chomp $head; 847a75fececSSteven Rostedt 848a75fececSSteven Rostedt if ($check ne "good") { 849a75fececSSteven Rostedt doprint "TESTING BISECT BAD [$bad]\n"; 850a75fececSSteven Rostedt run_command "git checkout $bad" or 851a75fececSSteven Rostedt die "Failed to checkout $bad"; 852a75fececSSteven Rostedt 853a75fececSSteven Rostedt $result = run_bisect $type; 854a75fececSSteven Rostedt 855a75fececSSteven Rostedt if ($result ne "bad") { 856a75fececSSteven Rostedt fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0; 857a75fececSSteven Rostedt } 858a75fececSSteven Rostedt } 859a75fececSSteven Rostedt 860a75fececSSteven Rostedt if ($check ne "bad") { 861a75fececSSteven Rostedt doprint "TESTING BISECT GOOD [$good]\n"; 862a75fececSSteven Rostedt run_command "git checkout $good" or 863a75fececSSteven Rostedt die "Failed to checkout $good"; 864a75fececSSteven Rostedt 865a75fececSSteven Rostedt $result = run_bisect $type; 866a75fececSSteven Rostedt 867a75fececSSteven Rostedt if ($result ne "good") { 868a75fececSSteven Rostedt fail "Tested BISECT_GOOD [$good] and it failed" and return 0; 869a75fececSSteven Rostedt } 870a75fececSSteven Rostedt } 871a75fececSSteven Rostedt 872a75fececSSteven Rostedt # checkout where we started 873a75fececSSteven Rostedt run_command "git checkout $head" or 874a75fececSSteven Rostedt die "Failed to checkout $head"; 875a75fececSSteven Rostedt } 876a75fececSSteven Rostedt 877a75fececSSteven Rostedt run_command "git bisect start" or 878a75fececSSteven Rostedt dodie "could not start bisect"; 879a75fececSSteven Rostedt 880a75fececSSteven Rostedt run_command "git bisect good $good" or 881a75fececSSteven Rostedt dodie "could not set bisect good to $good"; 882a75fececSSteven Rostedt 883a75fececSSteven Rostedt run_git_bisect "git bisect bad $bad" or 884a75fececSSteven Rostedt dodie "could not set bisect bad to $bad"; 885a75fececSSteven Rostedt 886a75fececSSteven Rostedt if (defined($replay)) { 887a75fececSSteven Rostedt run_command "git bisect replay $replay" or 888a75fececSSteven Rostedt dodie "failed to run replay"; 889a75fececSSteven Rostedt } 890a75fececSSteven Rostedt 891a75fececSSteven Rostedt if (defined($start)) { 892a75fececSSteven Rostedt run_command "git checkout $start" or 893a75fececSSteven Rostedt dodie "failed to checkout $start"; 894a75fececSSteven Rostedt } 895a75fececSSteven Rostedt 896a75fececSSteven Rostedt my $test; 8975f9b6cedSSteven Rostedt do { 8985f9b6cedSSteven Rostedt $result = run_bisect $type; 899a75fececSSteven Rostedt $test = run_git_bisect "git bisect $result"; 900a75fececSSteven Rostedt } while ($test); 9015f9b6cedSSteven Rostedt 9025f9b6cedSSteven Rostedt run_command "git bisect log" or 9035f9b6cedSSteven Rostedt dodie "could not capture git bisect log"; 9045f9b6cedSSteven Rostedt 9055f9b6cedSSteven Rostedt run_command "git bisect reset" or 9065f9b6cedSSteven Rostedt dodie "could not reset git bisect"; 9075f9b6cedSSteven Rostedt 9085f9b6cedSSteven Rostedt doprint "Bad commit was [$bisect_bad]\n"; 9095f9b6cedSSteven Rostedt 9105f9b6cedSSteven Rostedt $in_bisect = 0; 9115f9b6cedSSteven Rostedt 9125f9b6cedSSteven Rostedt success $i; 9135f9b6cedSSteven Rostedt} 9145f9b6cedSSteven Rostedt 9156c5ee0beSSteven Rostedtsub patchcheck { 9166c5ee0beSSteven Rostedt my ($i) = @_; 9176c5ee0beSSteven Rostedt 9186c5ee0beSSteven Rostedt die "PATCHCHECK_START[$i] not defined\n" 9196c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_START[$i]"})); 9206c5ee0beSSteven Rostedt die "PATCHCHECK_TYPE[$i] not defined\n" 9216c5ee0beSSteven Rostedt if (!defined($opt{"PATCHCHECK_TYPE[$i]"})); 9226c5ee0beSSteven Rostedt 9236c5ee0beSSteven Rostedt my $start = $opt{"PATCHCHECK_START[$i]"}; 9246c5ee0beSSteven Rostedt 9256c5ee0beSSteven Rostedt my $end = "HEAD"; 9266c5ee0beSSteven Rostedt if (defined($opt{"PATCHCHECK_END[$i]"})) { 9276c5ee0beSSteven Rostedt $end = $opt{"PATCHCHECK_END[$i]"}; 9286c5ee0beSSteven Rostedt } 9296c5ee0beSSteven Rostedt 9306c5ee0beSSteven Rostedt my $type = $opt{"PATCHCHECK_TYPE[$i]"}; 9316c5ee0beSSteven Rostedt 9326c5ee0beSSteven Rostedt # Can't have a test without having a test to run 9336c5ee0beSSteven Rostedt if ($type eq "test" && !defined($run_test)) { 9346c5ee0beSSteven Rostedt $type = "boot"; 9356c5ee0beSSteven Rostedt } 9366c5ee0beSSteven Rostedt 9376c5ee0beSSteven Rostedt open (IN, "git log --pretty=oneline $end|") or 9386c5ee0beSSteven Rostedt dodie "could not get git list"; 9396c5ee0beSSteven Rostedt 9406c5ee0beSSteven Rostedt my @list; 9416c5ee0beSSteven Rostedt 9426c5ee0beSSteven Rostedt while (<IN>) { 9436c5ee0beSSteven Rostedt chomp; 9446c5ee0beSSteven Rostedt $list[$#list+1] = $_; 9456c5ee0beSSteven Rostedt last if (/^$start/); 9466c5ee0beSSteven Rostedt } 9476c5ee0beSSteven Rostedt close(IN); 9486c5ee0beSSteven Rostedt 9496c5ee0beSSteven Rostedt if ($list[$#list] !~ /^$start/) { 9502b7d9b21SSteven Rostedt fail "SHA1 $start not found"; 9516c5ee0beSSteven Rostedt } 9526c5ee0beSSteven Rostedt 9536c5ee0beSSteven Rostedt # go backwards in the list 9546c5ee0beSSteven Rostedt @list = reverse @list; 9556c5ee0beSSteven Rostedt 9566c5ee0beSSteven Rostedt my $save_clean = $noclean; 9576c5ee0beSSteven Rostedt 9586c5ee0beSSteven Rostedt $in_patchcheck = 1; 9596c5ee0beSSteven Rostedt foreach my $item (@list) { 9606c5ee0beSSteven Rostedt my $sha1 = $item; 9616c5ee0beSSteven Rostedt $sha1 =~ s/^([[:xdigit:]]+).*/$1/; 9626c5ee0beSSteven Rostedt 9636c5ee0beSSteven Rostedt doprint "\nProcessing commit $item\n\n"; 9646c5ee0beSSteven Rostedt 9656c5ee0beSSteven Rostedt run_command "git checkout $sha1" or 9666c5ee0beSSteven Rostedt die "Failed to checkout $sha1"; 9676c5ee0beSSteven Rostedt 9686c5ee0beSSteven Rostedt # only clean on the first and last patch 9696c5ee0beSSteven Rostedt if ($item eq $list[0] || 9706c5ee0beSSteven Rostedt $item eq $list[$#list]) { 9716c5ee0beSSteven Rostedt $noclean = $save_clean; 9726c5ee0beSSteven Rostedt } else { 9736c5ee0beSSteven Rostedt $noclean = 1; 9746c5ee0beSSteven Rostedt } 9756c5ee0beSSteven Rostedt 9766c5ee0beSSteven Rostedt if (defined($minconfig)) { 9772b7d9b21SSteven Rostedt build "useconfig:$minconfig" or return 0; 9786c5ee0beSSteven Rostedt } else { 9796c5ee0beSSteven Rostedt # ?? no config to use? 9802b7d9b21SSteven Rostedt build "oldconfig" or return 0; 9816c5ee0beSSteven Rostedt } 9826c5ee0beSSteven Rostedt 9832b7d9b21SSteven Rostedt check_buildlog $sha1 or return 0; 9846c5ee0beSSteven Rostedt 9856c5ee0beSSteven Rostedt next if ($type eq "build"); 9866c5ee0beSSteven Rostedt 9876c5ee0beSSteven Rostedt get_grub_index; 9886c5ee0beSSteven Rostedt get_version; 9896c5ee0beSSteven Rostedt install; 9906c5ee0beSSteven Rostedt 9917faafbd6SSteven Rostedt my $failed = 0; 9927faafbd6SSteven Rostedt 9937faafbd6SSteven Rostedt start_monitor; 9947faafbd6SSteven Rostedt monitor or $failed = 1; 9957faafbd6SSteven Rostedt 9967faafbd6SSteven Rostedt if (!$failed && $type ne "boot"){ 9977faafbd6SSteven Rostedt do_run_test or $failed = 1; 9987faafbd6SSteven Rostedt } 9997faafbd6SSteven Rostedt end_monitor; 10007faafbd6SSteven Rostedt return 0 if ($failed); 10017faafbd6SSteven Rostedt 10026c5ee0beSSteven Rostedt } 10036c5ee0beSSteven Rostedt $in_patchcheck = 0; 10046c5ee0beSSteven Rostedt success $i; 10052b7d9b21SSteven Rostedt 10062b7d9b21SSteven Rostedt return 1; 10076c5ee0beSSteven Rostedt} 10086c5ee0beSSteven Rostedt 10092545eb61SSteven Rostedtread_config $ARGV[0]; 10102545eb61SSteven Rostedt 10112545eb61SSteven Rostedt# mandatory configs 10122545eb61SSteven Rostedtdie "MACHINE not defined\n" if (!defined($opt{"MACHINE"})); 10132545eb61SSteven Rostedtdie "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"})); 10142545eb61SSteven Rostedtdie "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"})); 10152545eb61SSteven Rostedtdie "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"})); 10162545eb61SSteven Rostedtdie "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"})); 101775c3fda7SSteven Rostedtdie "TARGET_IMAGE not defined\n" if (!defined($opt{"TARGET_IMAGE"})); 10182545eb61SSteven Rostedtdie "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"})); 10192545eb61SSteven Rostedtdie "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"})); 10202545eb61SSteven Rostedtdie "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"})); 10212545eb61SSteven Rostedt 10222b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { 10232b7d9b21SSteven Rostedt unlink $opt{"LOG_FILE"}; 10242b7d9b21SSteven Rostedt} 10252545eb61SSteven Rostedt 10262b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n"; 10272b7d9b21SSteven Rostedt 10282b7d9b21SSteven Rostedtforeach my $option (sort keys %opt) { 10292b7d9b21SSteven Rostedt doprint "$option = $opt{$option}\n"; 10302b7d9b21SSteven Rostedt} 10312545eb61SSteven Rostedt 1032a75fececSSteven Rostedtsub set_test_option { 10335a391fbfSSteven Rostedt my ($name, $i) = @_; 10345a391fbfSSteven Rostedt 10355a391fbfSSteven Rostedt my $option = "$name\[$i\]"; 10365a391fbfSSteven Rostedt 10375a391fbfSSteven Rostedt if (defined($opt{$option})) { 10385a391fbfSSteven Rostedt return $opt{$option}; 10395a391fbfSSteven Rostedt } 10405a391fbfSSteven Rostedt 10415a391fbfSSteven Rostedt if (defined($opt{$name})) { 10425a391fbfSSteven Rostedt return $opt{$name}; 10435a391fbfSSteven Rostedt } 10445a391fbfSSteven Rostedt 10455a391fbfSSteven Rostedt return undef; 10465a391fbfSSteven Rostedt} 10475a391fbfSSteven Rostedt 10482545eb61SSteven Rostedt# First we need to do is the builds 1049a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { 10502545eb61SSteven Rostedt 1051a75fececSSteven Rostedt my $ssh_user = set_test_option("SSH_USER", $i); 1052a75fececSSteven Rostedt my $makecmd = set_test_option("MAKE_CMD", $i); 1053a75fececSSteven Rostedt 1054a75fececSSteven Rostedt $machine = set_test_option("MACHINE", $i); 1055a75fececSSteven Rostedt $tmpdir = set_test_option("TMP_DIR", $i); 1056a75fececSSteven Rostedt $outputdir = set_test_option("OUTPUT_DIR", $i); 1057a75fececSSteven Rostedt $builddir = set_test_option("BUILD_DIR", $i); 1058a75fececSSteven Rostedt $test_type = set_test_option("TEST_TYPE", $i); 1059a75fececSSteven Rostedt $build_type = set_test_option("BUILD_TYPE", $i); 1060a75fececSSteven Rostedt $build_options = set_test_option("BUILD_OPTIONS", $i); 1061a75fececSSteven Rostedt $power_cycle = set_test_option("POWER_CYCLE", $i); 1062a75fececSSteven Rostedt $noclean = set_test_option("BUILD_NOCLEAN", $i); 1063a75fececSSteven Rostedt $minconfig = set_test_option("MIN_CONFIG", $i); 1064a75fececSSteven Rostedt $run_test = set_test_option("TEST", $i); 1065a75fececSSteven Rostedt $addconfig = set_test_option("ADD_CONFIG", $i); 1066a75fececSSteven Rostedt $reboot_type = set_test_option("REBOOT_TYPE", $i); 1067a75fececSSteven Rostedt $grub_menu = set_test_option("GRUB_MENU", $i); 1068*8b37ca8cSSteven Rostedt $post_install = set_test_option("POST_INSTALL", $i); 1069a75fececSSteven Rostedt $reboot_script = set_test_option("REBOOT_SCRIPT", $i); 1070a75fececSSteven Rostedt $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); 1071a75fececSSteven Rostedt $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); 1072a75fececSSteven Rostedt $die_on_failure = set_test_option("DIE_ON_FAILURE", $i); 1073a75fececSSteven Rostedt $power_off = set_test_option("POWER_OFF", $i); 1074a75fececSSteven Rostedt $sleep_time = set_test_option("SLEEP_TIME", $i); 1075a75fececSSteven Rostedt $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 1076a75fececSSteven Rostedt $store_failures = set_test_option("STORE_FAILURES", $i); 1077a75fececSSteven Rostedt $timeout = set_test_option("TIMEOUT", $i); 1078a75fececSSteven Rostedt $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 1079a75fececSSteven Rostedt $console = set_test_option("CONSOLE", $i); 1080a75fececSSteven Rostedt $success_line = set_test_option("SUCCESS_LINE", $i); 1081a75fececSSteven Rostedt $build_target = set_test_option("BUILD_TARGET", $i); 1082a75fececSSteven Rostedt $target_image = set_test_option("TARGET_IMAGE", $i); 1083a75fececSSteven Rostedt $localversion = set_test_option("LOCALVERSION", $i); 1084a75fececSSteven Rostedt 1085a75fececSSteven Rostedt chdir $builddir || die "can't change directory to $builddir"; 1086a75fececSSteven Rostedt 1087a75fececSSteven Rostedt if (!-d $tmpdir) { 1088a75fececSSteven Rostedt mkpath($tmpdir) or 1089a75fececSSteven Rostedt die "can't create $tmpdir"; 1090a75fececSSteven Rostedt } 1091a75fececSSteven Rostedt 1092a75fececSSteven Rostedt $target = "$ssh_user\@$machine"; 1093a75fececSSteven Rostedt 1094a75fececSSteven Rostedt $buildlog = "$tmpdir/buildlog-$machine"; 1095a75fececSSteven Rostedt $dmesg = "$tmpdir/dmesg-$machine"; 1096a75fececSSteven Rostedt $make = "$makecmd O=$outputdir"; 1097a75fececSSteven Rostedt 1098a75fececSSteven Rostedt if ($reboot_type eq "grub") { 1099a75fececSSteven Rostedt dodie "GRUB_MENU not defined\n" if (!defined($grub_menu)); 1100a75fececSSteven Rostedt } elsif (!defined($reboot_script)) { 1101a75fececSSteven Rostedt dodie "REBOOT_SCRIPT not defined\n" 1102a75fececSSteven Rostedt } 1103a75fececSSteven Rostedt 1104a75fececSSteven Rostedt my $run_type = $build_type; 1105a75fececSSteven Rostedt if ($test_type eq "patchcheck") { 1106a75fececSSteven Rostedt $run_type = $opt{"PATCHCHECK_TYPE[$i]"}; 1107a75fececSSteven Rostedt } elsif ($test_type eq "bisect") { 1108a75fececSSteven Rostedt $run_type = $opt{"BISECT_TYPE[$i]"}; 1109a75fececSSteven Rostedt } 1110a75fececSSteven Rostedt 1111a75fececSSteven Rostedt # mistake in config file? 1112a75fececSSteven Rostedt if (!defined($run_type)) { 1113a75fececSSteven Rostedt $run_type = "ERROR"; 1114a75fececSSteven Rostedt } 11152545eb61SSteven Rostedt 11162545eb61SSteven Rostedt doprint "\n\n"; 1117a75fececSSteven Rostedt doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n"; 11187faafbd6SSteven Rostedt 11197faafbd6SSteven Rostedt unlink $dmesg; 11207faafbd6SSteven Rostedt unlink $buildlog; 11212545eb61SSteven Rostedt 11222b7d9b21SSteven Rostedt if (!defined($minconfig)) { 11232b7d9b21SSteven Rostedt $minconfig = $addconfig; 11242b7d9b21SSteven Rostedt 11252b7d9b21SSteven Rostedt } elsif (defined($addconfig)) { 1126a75fececSSteven Rostedt run_command "cat $addconfig $minconfig > $tmpdir/use_config" or 11272b7d9b21SSteven Rostedt dodie "Failed to create temp config"; 1128a75fececSSteven Rostedt $minconfig = "$tmpdir/use_config"; 11292b7d9b21SSteven Rostedt } 11302b7d9b21SSteven Rostedt 11316c5ee0beSSteven Rostedt my $checkout = $opt{"CHECKOUT[$i]"}; 11326c5ee0beSSteven Rostedt if (defined($checkout)) { 11336c5ee0beSSteven Rostedt run_command "git checkout $checkout" or 11346c5ee0beSSteven Rostedt die "failed to checkout $checkout"; 11356c5ee0beSSteven Rostedt } 11366c5ee0beSSteven Rostedt 1137a75fececSSteven Rostedt if ($test_type eq "bisect") { 11385f9b6cedSSteven Rostedt bisect $i; 11395f9b6cedSSteven Rostedt next; 1140a75fececSSteven Rostedt } elsif ($test_type eq "patchcheck") { 11416c5ee0beSSteven Rostedt patchcheck $i; 11426c5ee0beSSteven Rostedt next; 11435f9b6cedSSteven Rostedt } 11445f9b6cedSSteven Rostedt 11457faafbd6SSteven Rostedt if ($build_type ne "nobuild") { 11467faafbd6SSteven Rostedt build $build_type or next; 11472545eb61SSteven Rostedt } 11482545eb61SSteven Rostedt 1149a75fececSSteven Rostedt if ($test_type ne "build") { 11505f9b6cedSSteven Rostedt get_grub_index; 11515f9b6cedSSteven Rostedt get_version; 11522545eb61SSteven Rostedt install; 11535a391fbfSSteven Rostedt 11547faafbd6SSteven Rostedt my $failed = 0; 11557faafbd6SSteven Rostedt start_monitor; 11567faafbd6SSteven Rostedt monitor or $failed = 1;; 1157a75fececSSteven Rostedt 1158a75fececSSteven Rostedt if (!$failed && $test_type ne "boot" && defined($run_test)) { 11597faafbd6SSteven Rostedt do_run_test or $failed = 1; 11605a391fbfSSteven Rostedt } 11617faafbd6SSteven Rostedt end_monitor; 11627faafbd6SSteven Rostedt next if ($failed); 1163a75fececSSteven Rostedt } 11645a391fbfSSteven Rostedt 11655f9b6cedSSteven Rostedt success $i; 116675c3fda7SSteven Rostedt} 11672545eb61SSteven Rostedt 11685c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) { 116975c3fda7SSteven Rostedt halt; 1170a75fececSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && $test_type ne "build") { 117175c3fda7SSteven Rostedt reboot; 11725c42fc5bSSteven Rostedt} 117375c3fda7SSteven Rostedt 11742545eb61SSteven Rostedtexit 0; 1175