blob: e1d67fbf7d99ed721a3ccfeabcde8cdb130244ab [file] [log] [blame]
#!/usr/bin/env perl
$usage = "Usage:
fuzzer-find-diff.pl reference_binary new_binary [number_of_tests_to_run]
The first two input arguments are the commands to run the test programs
based on fuzzer_test_main() function from 'util.c' (preferably they should
be statically compiled, this can be achieved via '--disable-shared' pixman
configure option). The third optional argument is the number of test rounds
to run (if not specified, then testing runs infinitely or until some problem
is detected).
Usage examples:
fuzzer-find-diff.pl ./blitters-test-with-sse-disabled ./blitters-test 9000000
fuzzer-find-diff.pl ./blitters-test \"ssh ppc64_host /path/to/blitters-test\"
";
$#ARGV >= 1 or die $usage;
$batch_size = 10000;
if ($#ARGV >= 2) {
$number_of_tests = int($ARGV[2]);
} else {
$number_of_tests = -1
}
sub test_range {
my $min = shift;
my $max = shift;
# check that [$min, $max] range is "bad", otherwise return
if (`$ARGV[0] $min $max 2>/dev/null` eq `$ARGV[1] $min $max 2>/dev/null`) {
return;
}
# check that $min itself is "good", otherwise return
if (`$ARGV[0] $min 2>/dev/null` ne `$ARGV[1] $min 2>/dev/null`) {
return $min;
}
# start bisecting
while ($max != $min + 1) {
my $avg = int(($min + $max) / 2);
my $res1 = `$ARGV[0] $min $avg 2>/dev/null`;
my $res2 = `$ARGV[1] $min $avg 2>/dev/null`;
if ($res1 ne $res2) {
$max = $avg;
} else {
$min = $avg;
}
}
return $max;
}
$base = 1;
while ($number_of_tests <= 0 || $base <= $number_of_tests) {
printf("testing %-12d\r", $base + $batch_size - 1);
my $res = test_range($base, $base + $batch_size - 1);
if ($res) {
printf("Failure: results are different for test %d:\n", $res);
printf("\n-- ref --\n");
print `$ARGV[0] $res`;
printf("-- new --\n");
print `$ARGV[1] $res`;
printf("The problematic conditions can be reproduced by running:\n");
printf("$ARGV[1] %d\n", $res);
exit(1);
}
$base += $batch_size;
}
printf("Success: %d tests finished\n", $base - 1);