| #!/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); |