net.jqwik.engine.properties.arbitraries.randomized.RandomGenerators Maven / Gradle / Ivy
The 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 extends U> 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 extends U> 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 extends RandomGenerator> 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 super List extends Shrinkable>, ? extends Shrinkable> createShrinkable,
int minSize, int maxSize, long maxUniqueElements,
int genSize, RandomDistribution sizeDistribution,
Set extends FeatureExtractor> 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 extends FeatureExtractor> 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 extends FeatureExtractor> 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 extends Shrinkable> 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 extends Tuple2> frequencies) {
return new FrequencyGenerator<>(frequencies);
}
public static RandomGenerator frequencyOf(
List extends Tuple2>> 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);
};
}
}