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

net.jqwik.engine.properties.arbitraries.randomized.RandomGenerators Maven / Gradle / Ivy

There is a newer version: 1.9.1
Show newest version
package net.jqwik.engine.properties.arbitraries.randomized;

import java.math.*;
import java.util.*;
import java.util.concurrent.atomic.*;
import java.util.function.*;

import net.jqwik.api.*;
import net.jqwik.api.Tuple.*;
import net.jqwik.engine.properties.*;
import net.jqwik.engine.properties.shrinking.*;

import org.jspecify.annotations.*;

import static java.lang.Math.*;

public class RandomGenerators {

	public static final int DEFAULT_COLLECTION_SIZE = 255;

	public static int collectionMaxSize(int minSize, Integer maxSize) {
		if (maxSize != null) {
			return maxSize;
		}
		int doubleMinSize = toIntExact(min(Integer.MAX_VALUE, (long) minSize * 2));
		return max(RandomGenerators.DEFAULT_COLLECTION_SIZE, doubleMinSize);
	}

	public static  RandomGenerator choose(List values) {
		if (values.isEmpty()) {
			return fail("empty set of values");
		}
		return random -> {
			U value = chooseValue(values, random);
			return new ChooseValueShrinkable<>(value, values);
		};
	}

	public static  U chooseValue(List values, Random random) {
		int index = random.nextInt(values.size());
		return values.get(index);
	}

	public static  RandomGenerator choose(U[] values) {
		return choose(Arrays.asList(values));
	}

	public static RandomGenerator choose(char[] characters) {
		List validCharacters = new ArrayList<>(characters.length);
		for (char character : characters) {
			validCharacters.add(character);
		}
		return choose(validCharacters);
	}

	public static RandomGenerator chars(char min, char max) {
		return integers(min, max).map(anInt -> ((char) (int) anInt));
	}

	public static RandomGenerator integers(int min, int max) {
		BigInteger minBig = BigInteger.valueOf(min);
		BigInteger maxBig = BigInteger.valueOf(max);
		return bigIntegers(
				minBig,
				maxBig,
				RandomIntegralGenerators.defaultShrinkingTarget(Range.of(minBig, maxBig)),
				RandomDistribution.uniform()
		).map(BigInteger::intValueExact);
	}

	public static RandomGenerator bigIntegers(
			BigInteger min,
			BigInteger max,
			BigInteger shrinkingTarget,
			RandomDistribution distribution
	) {
		return RandomIntegralGenerators.bigIntegers(1000, min, max, shrinkingTarget, distribution);
	}

	public static RandomGenerator bigDecimals(
			Range range,
			int scale,
			BigDecimal shrinkingTarget,
			RandomDistribution distribution
	) {
		return RandomDecimalGenerators.bigDecimals(1000, range, scale, distribution, shrinkingTarget);
	}

	public static  RandomGenerator oneOf(List> all) {
		return choose(all).flatMap(Function.identity());
	}

	public static  RandomGenerator> shuffle(List values) {
		return random -> {
			List clone = new ArrayList<>(values);
			Collections.shuffle(clone, random);
			return Shrinkable.unshrinkable(clone);
		};
	}

	public static RandomGenerator strings(
		RandomGenerator elementGenerator,
		int minLength, int maxLength, long maxUniqueChars,
		int genSize, RandomDistribution lengthDistribution,
		Arbitrary characterArbitrary,
		boolean uniqueChars
	) {
		Function>, Shrinkable> createShrinkable = elements -> new ShrinkableString(elements, minLength, maxLength, characterArbitrary, uniqueChars);
		Set> featureExtractors = uniqueChars ? ShrinkableString.UNIQUE_CHARS_EXTRACTOR : Collections.emptySet();
		return container(elementGenerator, createShrinkable, minLength, maxLength, maxUniqueChars, genSize, lengthDistribution, featureExtractors);
	}

	private static  RandomGenerator container(
		RandomGenerator elementGenerator,
		Function>, ? extends Shrinkable> createShrinkable,
		int minSize, int maxSize, long maxUniqueElements,
		int genSize, RandomDistribution sizeDistribution,
		Set> uniquenessExtractors
	) {
		if (minSize > maxSize) {
			String message = String.format("minSize <%s> must not be larger than maxSize <%s>.", minSize, maxSize);
			throw new JqwikException(message);
		}
		return new ContainerGenerator<>(
			elementGenerator, createShrinkable,
			minSize, maxSize, maxUniqueElements,
			genSize, sizeDistribution,
			uniquenessExtractors
		);
	}

	public static  RandomGenerator> list(
		RandomGenerator elementGenerator,
		int minSize, int maxSize, long maxUniqueElements,
		int genSize, RandomDistribution sizeDistribution,
		Set> uniquenessExtractors,
		Arbitrary elementArbitrary
	) {
		Function>, Shrinkable>> createShrinkable =
			elements -> new ShrinkableList<>(elements, minSize, maxSize, uniquenessExtractors, elementArbitrary);
		return container(elementGenerator, createShrinkable, minSize, maxSize, maxUniqueElements, genSize, sizeDistribution, uniquenessExtractors);
	}

	public static  RandomGenerator> set(
		RandomGenerator elementGenerator,
		int minSize, int maxSize, int genSize,
		Arbitrary elementArbitrary
	) {
		return set(elementGenerator, minSize, maxSize, genSize, null, Collections.emptySet(), elementArbitrary);
	}

	public static  RandomGenerator> set(
			RandomGenerator elementGenerator,
			int minSize, int maxSize, int genSize, RandomDistribution sizeDistribution,
			Set> uniquenessExtractors,
			Arbitrary elementArbitrary
	) {
		Set> extractors = new LinkedHashSet<>(uniquenessExtractors);
		extractors.add(FeatureExtractor.identity());
		Function>, ? extends Shrinkable>> createShrinkable =
			elements -> new ShrinkableSet(elements, minSize, maxSize, uniquenessExtractors, elementArbitrary);
		return container(elementGenerator, createShrinkable, minSize, maxSize, maxSize, genSize, sizeDistribution, extractors);
	}

	public static  RandomGenerator samplesFromShrinkables(List> samples) {
		AtomicInteger tryCount = new AtomicInteger(0);
		return ignored -> {
			if (tryCount.get() >= samples.size())
				tryCount.set(0);
			return samples.get(tryCount.getAndIncrement());
		};
	}

	public static  RandomGenerator samples(T[] samples) {
		List> shrinkables = SampleShrinkable.listOf(samples);
		return samplesFromShrinkables(shrinkables);
	}

	public static  RandomGenerator frequency(List> frequencies) {
		return new FrequencyGenerator<>(frequencies);
	}

	public static  RandomGenerator frequencyOf(
			List>> frequencies,
			int genSize,
			boolean withEmbeddedEdgeCases
	) {
		return frequency(frequencies).flatMap(Function.identity(), genSize, withEmbeddedEdgeCases);
	}

	public static  RandomGenerator withEdgeCases(RandomGenerator self, int genSize, EdgeCases edgeCases) {
		if (edgeCases.isEmpty()) {
			return self;
		}
		return new WithEdgeCasesGenerator<>(self, edgeCases, genSize);
	}

	public static  RandomGenerator fail(String message) {
		return ignored -> {
			throw new JqwikException(message);
		};
	}

}