$opt{"BUILD_OPTIONS"} = "";
my $version;
-my $install_mods;
my $grub_number;
my $target;
my $make;
my $noclean;
+my $minconfig;
+my $in_bisect = 0;
+my $bisect_bad = "";
sub read_config {
my ($config) = @_;
close(IN);
}
-sub doprint {
- print @_;
-
+sub logit {
if (defined($opt{"LOG_FILE"})) {
open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
print OUT @_;
}
}
+sub doprint {
+ print @_;
+ logit @_;
+}
+
sub dodie {
doprint "CRITICAL FAILURE... ", @_;
doprint "SUCCESS\n";
}
- return $failed;
+ return !$failed;
+}
+
+sub get_grub_index {
+
+ return if ($grub_number >= 0);
+
+ doprint "Find grub menu ... ";
+ $grub_number = -1;
+ open(IN, "ssh $target cat /boot/grub/menu.lst |")
+ or die "unable to get menu.lst";
+ while (<IN>) {
+ if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) {
+ $grub_number++;
+ last;
+ } elsif (/^\s*title\s/) {
+ $grub_number++;
+ }
+ }
+ close(IN);
+
+ die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}"
+ if ($grub_number < 0);
+ doprint "$grub_number\n";
}
my $timeout = $opt{"TIMEOUT"};
close(IN);
if (!$booted) {
+ return 1 if (!$in_bisect);
dodie "failed - never got a boot prompt.\n";
}
if ($bug) {
+ return 1 if (!$in_bisect);
dodie "failed - got a bug report\n";
}
+
+ return 0;
}
sub install {
- if (run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}") {
+ run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}" or
dodie "failed to copy image";
- }
- if ($install_mods) {
- my $modlib = "/lib/modules/$version";
- my $modtar = "autotest-mods.tar.bz2";
+ my $install_mods = 0;
- if (run_command "ssh $target rm -rf $modlib") {
- dodie "failed to remove old mods: $modlib";
+ # should we process modules?
+ $install_mods = 0;
+ open(IN, "$opt{OUTPUT_DIR}/.config") or dodie("Can't read config file");
+ while (<IN>) {
+ if (/CONFIG_MODULES(=y)?/) {
+ $install_mods = 1 if (defined($1));
+ last;
}
+ }
+ close(IN);
- # would be nice if scp -r did not follow symbolic links
- if (run_command "cd $opt{TMP_DIR} && tar -cjf $modtar lib/modules/$version") {
- dodie "making tarball";
- }
+ if (!$install_mods) {
+ doprint "No modules needed\n";
+ return;
+ }
- if (run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp") {
- dodie "failed to copy modules";
- }
+ run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install" or
+ dodie "Failed to install modules";
- unlink "$opt{TMP_DIR}/$modtar";
+ my $modlib = "/lib/modules/$version";
+ my $modtar = "autotest-mods.tar.bz2";
- if (run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'") {
- dodie "failed to tar modules";
- }
+ run_command "ssh $target rm -rf $modlib" or
+ dodie "failed to remove old mods: $modlib";
- run_command "ssh $target rm -f /tmp/$modtar";
- }
+ # would be nice if scp -r did not follow symbolic links
+ run_command "cd $opt{TMP_DIR} && tar -cjf $modtar lib/modules/$version" or
+ dodie "making tarball";
+
+ run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp" or
+ dodie "failed to copy modules";
+
+ unlink "$opt{TMP_DIR}/$modtar";
+
+ run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or
+ dodie "failed to tar modules";
+ run_command "ssh $target rm -f /tmp/$modtar";
}
sub build {
my $append = "";
if ($type =~ /^useconfig:(.*)/) {
- if (run_command "cp $1 $opt{OUTPUT_DIR}/.config") {
+ run_command "cp $1 $opt{OUTPUT_DIR}/.config" or
dodie "could not copy $1 to .config";
- }
+
$type = "oldconfig";
}
# allow for empty configs
run_command "touch $opt{OUTPUT_DIR}/.config";
- if (run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp") {
+ run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp" or
dodie "moving .config";
- }
- if (!$noclean && run_command "$make mrproper") {
+ if (!$noclean && !run_command "$make mrproper") {
dodie "make mrproper";
}
- if (run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config") {
+ run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config" or
dodie "moving config_temp";
- }
} elsif (!$noclean) {
unlink "$opt{OUTPUT_DIR}/.config";
- if (run_command "$make mrproper") {
+ run_command "$make mrproper" or
dodie "make mrproper";
- }
}
# add something to distinguish this build
print OUT "$opt{LOCALVERSION}\n";
close(OUT);
- if (defined($opt{"MIN_CONFIG"})) {
- $defconfig = "KCONFIG_ALLCONFIG=$opt{MIN_CONFIG}";
+ if (defined($minconfig)) {
+ $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
}
- if (run_command "$defconfig $append $make $type") {
+ run_command "$defconfig $append $make $type" or
dodie "failed make config";
- }
- if (run_command "$make $opt{BUILD_OPTIONS}") {
+ if (!run_command "$make $opt{BUILD_OPTIONS}") {
+ # bisect may need this to pass
+ return 1 if ($in_bisect);
dodie "failed build";
}
+
+ return 0;
}
sub reboot {
# try to reboot normally
- if (run_command "ssh $target reboot") {
+ if (!run_command "ssh $target reboot") {
# nope? power cycle it.
run_command "$opt{POWER_CYCLE}";
}
}
sub halt {
- if ((run_command "ssh $target halt") or defined($opt{"POWER_OFF"})) {
+ if (!run_command "ssh $target halt" or defined($opt{"POWER_OFF"})) {
# nope? the zap it!
run_command "$opt{POWER_OFF}";
}
}
+sub success {
+ my ($i) = @_;
+
+ doprint "\n\n*******************************************\n";
+ doprint "*******************************************\n";
+ doprint "** SUCCESS!!!! **\n";
+ doprint "*******************************************\n";
+ doprint "*******************************************\n";
+
+ if ($i != $opt{"NUM_BUILDS"}) {
+ reboot;
+ doprint "Sleeping $opt{SLEEP_TIME} seconds\n";
+ sleep "$opt{SLEEP_TIME}";
+ }
+}
+
+sub get_version {
+ # get the release name
+ doprint "$make kernelrelease ... ";
+ $version = `$make kernelrelease | tail -1`;
+ chomp($version);
+ doprint "$version\n";
+}
+
+sub run_bisect {
+ my ($type) = @_;
+
+ my $failed;
+ my $result;
+ my $output;
+ my $ret;
+
+
+ if (defined($minconfig)) {
+ $failed = build "useconfig:$minconfig";
+ } else {
+ # ?? no config to use?
+ $failed = build "oldconfig";
+ }
+
+ if ($type ne "build") {
+ dodie "Failed on build" if $failed;
+
+ # Now boot the box
+ get_grub_index;
+ get_version;
+ install;
+ $failed = monitor;
+
+ if ($type ne "boot") {
+ dodie "Failed on boot" if $failed;
+ }
+ }
+
+ if ($failed) {
+ $result = "bad";
+ } else {
+ $result = "good";
+ }
+
+ doprint "git bisect $result ... ";
+ $output = `git bisect $result 2>&1`;
+ $ret = $?;
+
+ logit $output;
+
+ if ($ret) {
+ doprint "FAILED\n";
+ dodie "Failed to git bisect";
+ }
+
+ doprint "SUCCESS\n";
+ if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\)) \[([[:xdigit:]]+)\]/) {
+ doprint "$1 [$2]\n";
+ } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
+ $bisect_bad = $1;
+ doprint "Found bad commit... $1\n";
+ return 0;
+ }
+
+
+ return 1;
+}
+
+sub bisect {
+ my ($i) = @_;
+
+ my $result;
+
+ die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
+ die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
+ die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
+
+ my $good = $opt{"BISECT_GOOD[$i]"};
+ my $bad = $opt{"BISECT_BAD[$i]"};
+ my $type = $opt{"BISECT_TYPE[$i]"};
+
+ $in_bisect = 1;
+
+ run_command "git bisect start" or
+ dodie "could not start bisect";
+
+ run_command "git bisect good $good" or
+ dodie "could not set bisect good to $good";
+
+ run_command "git bisect bad $bad" or
+ dodie "could not set bisect good to $bad";
+
+ do {
+ $result = run_bisect $type;
+ } while ($result);
+
+ run_command "git bisect log" or
+ dodie "could not capture git bisect log";
+
+ run_command "git bisect reset" or
+ dodie "could not reset git bisect";
+
+ doprint "Bad commit was [$bisect_bad]\n";
+
+ $in_bisect = 0;
+
+ success $i;
+}
+
read_config $ARGV[0];
# mandatory configs
doprint "\n\nSTARTING AUTOMATED TESTS\n";
-doprint "Find grub menu ... ";
-$grub_number = -1;
-open(IN, "ssh $target cat /boot/grub/menu.lst |")
- or die "unable to get menu.lst";
-while (<IN>) {
- if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) {
- $grub_number++;
- last;
- } elsif (/^\s*title\s/) {
- $grub_number++;
- }
-}
-close(IN);
-die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}"
- if ($grub_number < 0);
-doprint "$grub_number\n";
$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}";
$noclean = $opt{"BUILD_NOCLEAN"};
}
+ if (defined($opt{"MIN_CONFIG[$i]"})) {
+ $minconfig = $opt{"MIN_CONFIG[$i]"};
+ } elsif (defined($opt{"MIN_CONFIG"})) {
+ $minconfig = $opt{"MIN_CONFIG"};
+ } else {
+ undef $minconfig;
+ }
+
if (!defined($opt{$type})) {
$opt{$type} = $opt{"DEFAULT_BUILD_TYPE"};
}
doprint "\n\n";
doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n";
- if ($opt{$type} ne "nobuild") {
- build $opt{$type};
- }
-
- # get the release name
- doprint "$make kernelrelease ... ";
- $version = `$make kernelrelease | tail -1`;
- chomp($version);
- doprint "$version\n";
-
- # should we process modules?
- $install_mods = 0;
- open(IN, "$opt{OUTPUT_DIR}/.config") or dodie("Can't read config file");
- while (<IN>) {
- if (/CONFIG_MODULES(=y)?/) {
- $install_mods = 1 if (defined($1));
- last;
- }
+ if ($opt{$type} eq "bisect") {
+ bisect $i;
+ next;
}
- close(IN);
- if ($install_mods) {
- if (run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install") {
- dodie "Failed to install modules";
- }
- } else {
- doprint "No modules needed\n";
+ if ($opt{$type} ne "nobuild") {
+ build $opt{$type};
}
+ get_grub_index;
+ get_version;
install;
-
monitor;
-
- doprint "\n\n*******************************************\n";
- doprint "*******************************************\n";
- doprint "** SUCCESS!!!! **\n";
- doprint "*******************************************\n";
- doprint "*******************************************\n";
-
- if ($i != $opt{"NUM_BUILDS"}) {
- reboot;
- sleep "$opt{SLEEP_TIME}";
- }
+ success $i;
}
if ($opt{"POWEROFF_ON_SUCCESS"}) {