jqwik-team / jqwik

Property-Based Testing on the JUnit Platform

Home Page:http://jqwik.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bug: Uniform Distribution of Integers does not work if range is >= Integer.MAX_VALUE

jlink opened this issue · comments

Testing Problem

Consider the following test:

@Example
void integers() {
    IntegerArbitrary integers = Arbitraries.integers().withDistribution(RandomDistribution.uniform());
    integers.sampleStream().limit(50).forEach(System.out::println);
}

Which will only create three different values:

-2147483647
-2147483648
1

Discussion

The problem is the implementation of SmallUniformGenerator:

class SmallUniformNumericGenerator implements RandomDistribution.RandomNumericGenerator {

	private final int min;
	private final int max;

	SmallUniformNumericGenerator(BigInteger min, BigInteger max) {
		this.min = min.intValueExact();
		this.max = max.intValueExact();
	}

	@Override
	public BigInteger next(Random random) {
		int bound = Math.abs(max - min) + 1;
		int value = random.nextInt(bound >= 0 ? bound : Integer.MAX_VALUE) + min;
		return BigInteger.valueOf(value);
	}
}

which should only be used if max-min < Integer.MAX_VALUE. See:

public class UniformRandomDistribution implements RandomDistribution {

	@Override
	public RandomNumericGenerator createGenerator(
		int genSize,
		BigInteger min,
		BigInteger max,
		BigInteger center
	) {
		// Small number generation can be faster
		if (isWithinIntegerRange(min, max)) {
			return new SmallUniformNumericGenerator(min, max);
		} else {
			return new BigUniformNumericGenerator(min, max);
		}

	}

	private static boolean isWithinIntegerRange(BigInteger min, BigInteger max) {
		return min.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) >= 0
			&& max.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) <= 0;
	}
}

Released in 1.8.3-SNAPSHOT