114b11b2bSmrg#!/usr/bin/env perl
214b11b2bSmrg
314b11b2bSmrg$usage = "Usage:
414b11b2bSmrg  fuzzer-find-diff.pl reference_binary new_binary [number_of_tests_to_run]
514b11b2bSmrg
614b11b2bSmrgThe first two input arguments are the commands to run the test programs
714b11b2bSmrgbased on fuzzer_test_main() function from 'util.c' (preferably they should
814b11b2bSmrgbe statically compiled, this can be achieved via '--disable-shared' pixman
914b11b2bSmrgconfigure option). The third optional argument is the number of test rounds
1014b11b2bSmrgto run (if not specified, then testing runs infinitely or until some problem
1114b11b2bSmrgis detected).
1214b11b2bSmrg
1314b11b2bSmrgUsage examples:
1414b11b2bSmrg  fuzzer-find-diff.pl ./blitters-test-with-sse-disabled ./blitters-test 9000000
1514b11b2bSmrg  fuzzer-find-diff.pl ./blitters-test \"ssh ppc64_host /path/to/blitters-test\"
1614b11b2bSmrg";
1714b11b2bSmrg
1814b11b2bSmrg$#ARGV >= 1 or die $usage;
1914b11b2bSmrg
2014b11b2bSmrg$batch_size = 10000;
2114b11b2bSmrg
2214b11b2bSmrgif ($#ARGV >= 2) {
2314b11b2bSmrg    $number_of_tests = int($ARGV[2]);
2414b11b2bSmrg} else {
2514b11b2bSmrg    $number_of_tests = -1
2614b11b2bSmrg}
2714b11b2bSmrg
2814b11b2bSmrgsub test_range {
2914b11b2bSmrg    my $min = shift;
3014b11b2bSmrg    my $max = shift;
3114b11b2bSmrg
3214b11b2bSmrg    # check that [$min, $max] range is "bad", otherwise return
3314b11b2bSmrg    if (`$ARGV[0] $min $max 2>/dev/null` eq `$ARGV[1] $min $max 2>/dev/null`) {
3414b11b2bSmrg        return;
3514b11b2bSmrg    }
3614b11b2bSmrg
3714b11b2bSmrg    # check that $min itself is "good", otherwise return
3814b11b2bSmrg    if (`$ARGV[0] $min 2>/dev/null` ne `$ARGV[1] $min 2>/dev/null`) {
3914b11b2bSmrg        return $min;
4014b11b2bSmrg    }
4114b11b2bSmrg
4214b11b2bSmrg    # start bisecting
4314b11b2bSmrg    while ($max != $min + 1) {
4414b11b2bSmrg        my $avg = int(($min + $max) / 2);
4514b11b2bSmrg        my $res1 = `$ARGV[0] $min $avg 2>/dev/null`;
4614b11b2bSmrg        my $res2 = `$ARGV[1] $min $avg 2>/dev/null`;
4714b11b2bSmrg        if ($res1 ne $res2) {
4814b11b2bSmrg            $max = $avg;
4914b11b2bSmrg        } else {
5014b11b2bSmrg            $min = $avg;
5114b11b2bSmrg        }
5214b11b2bSmrg    }
5314b11b2bSmrg    return $max;
5414b11b2bSmrg}
5514b11b2bSmrg
5614b11b2bSmrg$base = 1;
5714b11b2bSmrgwhile ($number_of_tests <= 0 || $base <= $number_of_tests) {
5814b11b2bSmrg    printf("testing %-12d\r", $base + $batch_size - 1);
5914b11b2bSmrg    my $res = test_range($base, $base + $batch_size - 1);
6014b11b2bSmrg    if ($res) {
6114b11b2bSmrg        printf("Failure: results are different for test %d:\n", $res);
6214b11b2bSmrg
6314b11b2bSmrg        printf("\n-- ref --\n");
6414b11b2bSmrg        print `$ARGV[0] $res`;
6514b11b2bSmrg        printf("-- new --\n");
6614b11b2bSmrg        print `$ARGV[1] $res`;
6714b11b2bSmrg
6814b11b2bSmrg        printf("The problematic conditions can be reproduced by running:\n");
6914b11b2bSmrg        printf("$ARGV[1] %d\n", $res);
7014b11b2bSmrg
7114b11b2bSmrg        exit(1);
7214b11b2bSmrg    }
7314b11b2bSmrg    $base += $batch_size;
7414b11b2bSmrg}
7514b11b2bSmrgprintf("Success: %d tests finished\n", $base - 1);
76