All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.jqwik.engine.properties.arbitraries.IntegralGeneratingArbitrary Maven / Gradle / Ivy

package net.jqwik.engine.properties.arbitraries;

import java.math.*;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

import net.jqwik.api.*;
import net.jqwik.engine.properties.arbitraries.exhaustive.*;
import net.jqwik.engine.properties.arbitraries.randomized.*;
import net.jqwik.engine.properties.shrinking.*;

import static java.math.BigInteger.*;

class IntegralGeneratingArbitrary implements Arbitrary {

	BigInteger min;
	BigInteger max;
	BigInteger shrinkingTarget;

	IntegralGeneratingArbitrary(BigInteger defaultMin, BigInteger defaultMax) {
		this.min = defaultMin;
		this.max = defaultMax;
		this.shrinkingTarget = null;
	}

	@Override
	public RandomGenerator generator(int genSize) {
		BigInteger[] partitionPoints = RandomGenerators.calculateDefaultPartitionPoints(genSize, this.min, this.max);
		return createGenerator(partitionPoints, genSize);
	}

	@Override
	public Optional> exhaustive() {
		BigInteger maxCount = max.subtract(min).add(BigInteger.ONE);

		if (maxCount.compareTo(valueOf(ExhaustiveGenerators.MAXIMUM_ACCEPTED_MAX_COUNT)) > 0) {
			return Optional.empty();
		} else {
			return ExhaustiveGenerators.fromIterable(RangeIterator::new, maxCount.longValueExact());
		}
	}

	private RandomGenerator createGenerator(BigInteger[] partitionPoints, int genSize) {
		List> edgeCases =
			streamEdgeCases()
				.filter(aBigInt -> aBigInt.compareTo(min) >= 0 && aBigInt.compareTo(max) <= 0) //
				.map(anInt -> new ShrinkableBigInteger(anInt, Range.of(min, max), shrinkingTarget(anInt))) //
				.collect(Collectors.toList());
		return RandomGenerators.bigIntegers(min, max, shrinkingTargetCalculator(), partitionPoints)
							   .withEdgeCases(genSize, edgeCases);
	}

	private Stream streamEdgeCases() {
		BigInteger[] literalEdgeCases = new BigInteger[]{
			valueOf(-10), valueOf(-5), valueOf(-4), valueOf(-3), valueOf(-2), valueOf(-1),
			BigInteger.ZERO, BigInteger.ZERO, BigInteger.ZERO, // more weight for 0
			valueOf(10), valueOf(5), valueOf(4), valueOf(3), valueOf(2), valueOf(1),
			min, max
		};
		return shrinkingTarget == null
				   ? Arrays.stream(literalEdgeCases)
				   : Stream.concat(Stream.of(shrinkingTarget), Arrays.stream(literalEdgeCases));
	}

	private Function shrinkingTargetCalculator() {
		if (shrinkingTarget == null) {
			return RandomGenerators.defaultShrinkingTargetCalculator(min, max);
		} else {
			return ignore -> shrinkingTarget;
		}
	}

	private BigInteger shrinkingTarget(BigInteger anInt) {
		return shrinkingTargetCalculator().apply(anInt);
	}

	class RangeIterator implements Iterator {

		BigInteger current = min;

		@Override
		public boolean hasNext() {
			return current.compareTo(max) <= 0;
		}

		@Override
		public BigInteger next() {
			if (!hasNext()) {
				throw new NoSuchElementException();
			}
			BigInteger next = current;
			current = current.add(BigInteger.ONE);
			return next;
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy