net.jqwik.api.Arbitraries Maven / Gradle / Ivy
package net.jqwik.api;
import java.util.*;
import java.util.function.*;
import org.apiguardian.api.*;
import org.jspecify.annotations.*;
import net.jqwik.api.Tuple.*;
import net.jqwik.api.arbitraries.*;
import net.jqwik.api.arbitraries.TraverseArbitrary.*;
import net.jqwik.api.providers.*;
import net.jqwik.api.stateful.*;
import static org.apiguardian.api.API.Status.*;
@API(status = STABLE, since = "1.0")
public class Arbitraries {
@API(status = INTERNAL)
public static abstract class ArbitrariesFacade {
private static final ArbitrariesFacade implementation;
static {
implementation = FacadeLoader.load(ArbitrariesFacade.class);
}
public abstract Arbitrary oneOf(Collection extends Arbitrary extends T>> all);
public abstract ActionSequenceArbitrary sequences(Arbitrary extends Action> actionArbitrary);
public abstract Arbitrary frequencyOf(List extends Tuple2>> frequencies);
public abstract Arbitrary just(T value);
public abstract IntegerArbitrary integers();
public abstract LongArbitrary longs();
public abstract BigIntegerArbitrary bigIntegers();
public abstract FloatArbitrary floats();
public abstract BigDecimalArbitrary bigDecimals();
public abstract DoubleArbitrary doubles();
public abstract ByteArbitrary bytes();
public abstract ShortArbitrary shorts();
public abstract StringArbitrary strings();
public abstract CharacterArbitrary chars();
public abstract Arbitrary defaultFor(Class type, Class>[] typeParameters);
public abstract Arbitrary defaultFor(TypeUsage typeUsage, Function super TypeUsage, ? extends Arbitrary> noDefaultResolver);
public abstract Arbitrary lazy(Supplier extends Arbitrary> arbitrarySupplier);
public abstract TypeArbitrary forType(Class targetType);
public abstract MapArbitrary maps(Arbitrary keysArbitrary, Arbitrary valuesArbitrary);
public abstract Arbitrary> entries(Arbitrary keysArbitrary, Arbitrary valuesArbitrary);
public abstract Arbitrary recursive(
Supplier extends Arbitrary> base,
Function super Arbitrary, ? extends Arbitrary> recur,
int minDepth,
int maxDepth
);
public abstract Arbitrary lazyOf(List extends Supplier extends Arbitrary>> suppliers);
public abstract TraverseArbitrary traverse(Class targetType, Traverser traverser);
public abstract Arbitrary of(char[] chars);
public abstract Arbitrary of(Collection extends T> values);
public abstract Arbitrary create(Supplier supplier);
public abstract Arbitrary> shuffle(List values);
public abstract Arbitrary fromGenerator(IntFunction extends RandomGenerator> generatorSupplier);
public abstract Arbitrary frequency(List extends Tuple2> frequencies);
}
private Arbitraries() {
}
/**
* Create an arbitrary of type T from a corresponding generator of type T.
*
* @param generator The generator to be used for generating the values
* @param The type of values to generate
* @return a new arbitrary instance
*/
public static Arbitrary fromGenerator(RandomGenerator generator) {
return fromGeneratorWithSize(ignore -> generator);
}
/**
* Create an arbitrary of type T by supplying a corresponding generator of type T.
*
* @param generatorSupplier A function to supply a generator instance given the "size" of a generation attempt
* @param The type of values to generate
* @return a new arbitrary instance
*/
@API(status = EXPERIMENTAL, since = "1.8.0")
public static Arbitrary fromGeneratorWithSize(IntFunction> generatorSupplier) {
return ArbitrariesFacade.implementation.fromGenerator(generatorSupplier);
}
/**
* Create an arbitrary that will generate values of type T using a generator function.
* The generated values are unshrinkable.
*
* @param generator The generator function to be used for generating the values
* @param The type of values to generate
* @return a new arbitrary instance
*/
public static Arbitrary randomValue(Function generator) {
IntFunction> generatorSupplier = ignore -> random -> Shrinkable.unshrinkable(generator.apply(random));
return fromGeneratorWithSize(generatorSupplier);
}
/**
* Create an arbitrary for Random objects.
*
* @return a new arbitrary instance
*/
public static Arbitrary randoms() {
return randomValue(random -> new Random(random.nextLong()));
}
/**
* Create an arbitrary that will randomly choose from a given array of values.
* A generated value will be shrunk towards the start of the array.
*
*
* Use this method only for immutable arrays of immutable values.
* Changing a value will change subsequently generated values as well.
* For mutable values use {@linkplain #ofSuppliers(Supplier[])} instead.
* Modifying the array may cause erratic behavior, things may halt and
* catch fire.
*
* @param values The array of values to choose from
* @param The type of values to generate
* @return a new arbitrary instance
*/
@SafeVarargs
public static Arbitrary of(T... values) {
return of(Arrays.asList(values));
}
/**
* Create an arbitrary that will randomly choose from a given collection of values.
* A generated value will be shrunk towards the start of the collection.
*
*
* Use this method only for immutable collections of immutable values.
* Changing a value will change subsequently generated values as well.
* For mutable values use {@linkplain #ofSuppliers(Collection)} instead.
* Modifying the collection may cause erratic behavior, kittens may die.
*
* @param values The collection of values to choose from
* @param The type of values to generate
* @return a new arbitrary instance
*/
@API(status = MAINTAINED, since = "1.3.1")
public static Arbitrary of(Collection extends T> values) {
return ArbitrariesFacade.implementation.of(values);
}
/**
* Create an arbitrary that will randomly choose from a given array of value suppliers
* and then get the value from the supplier.
* A generated value will be shrunk towards the start of the array.
*
*
* Use this method instead of {@linkplain #of(Object[])} for mutable objects
* to make sure that changing a generated object will not influence other generated
* objects.
*
* @param valueSuppliers The array of values to choose from
* @param The type of values to generate
* @return a new arbitrary instance
*/
@API(status = MAINTAINED, since = "1.3.0")
@SafeVarargs
public static Arbitrary ofSuppliers(Supplier... valueSuppliers) {
return of(valueSuppliers).map(Supplier::get);
}
/**
* Create an arbitrary that will randomly choose from a given collection of value suppliers
* and then get the value from the supplier.
* A generated value will be shrunk towards the start of the collection.
*
*
* Use this method instead of {@linkplain #of(Collection)} for mutable objects
* to make sure that changing a generated object will not influence other generated
* objects.
*
* @param valueSuppliers The collection of values to choose from
* @param The type of values to generate
* @return a new arbitrary instance
*/
@API(status = MAINTAINED, since = "1.3.1")
public static Arbitrary ofSuppliers(Collection> valueSuppliers) {
return of(valueSuppliers).map(Supplier::get);
}
/**
* Create an arbitrary of character values.
*
* @param values The array of characters to choose from.
* @return a new arbitrary instance
*/
public static Arbitrary of(char[] values) {
return ArbitrariesFacade.implementation.of(values);
}
/**
* Create an arbitrary for enum values of type T.
*
* @param enumClass The enum class.
* @param The type of values to generate
* @return a new arbitrary instance
*/
public static > Arbitrary of(Class enumClass) {
List values = Arrays.asList(enumClass.getEnumConstants());
return of(values);
}
/**
* Create an arbitrary that will randomly choose between all given arbitraries of the same type T.
*
* @param first The first arbitrary to choose form
* @param rest An array of arbitraries to choose from
* @param The type of values to generate
* @return a new arbitrary instance
*/
@SuppressWarnings("unchecked")
@SafeVarargs
public static Arbitrary oneOf(Arbitrary extends T> first, Arbitrary extends T>... rest) {
List> all = new ArrayList<>();
all.add(first);
for (Arbitrary> arbitrary : rest) {
all.add((Arbitrary extends T>) arbitrary);
}
return oneOf(all);
}
/**
* Create an arbitrary that will randomly choose between all given arbitraries of the same type T.
*
* @param choices A collection of arbitraries to choose from
* @param The type of values to generate
* @return a new arbitrary instance
*/
@SuppressWarnings("unchecked")
public static Arbitrary oneOf(Collection extends Arbitrary extends T>> choices) {
if (choices.isEmpty()) {
String message = "oneOf() must not be called with no choices";
throw new JqwikException(message);
}
if (choices.size() == 1) {
return (Arbitrary) choices.iterator().next();
}
// Simple flatMapping is not enough because of configurations
return ArbitrariesFacade.implementation.oneOf(choices);
}
/**
* Create an arbitrary that will randomly choose between all given values of the same type T.
* The probability distribution is weighted with the first parameter of the tuple.
*
* @param frequencies An array of tuples of which the first parameter gives the weight and the second the value.
* @param The type of values to generate
* @return a new arbitrary instance
*/
@SafeVarargs
public static Arbitrary frequency(Tuple2... frequencies) {
return frequency(Arrays.asList(frequencies));
}
/**
* Create an arbitrary that will randomly choose between all given values of the same type T.
* The probability distribution is weighted with the first parameter of the tuple.
*
* @param frequencies A list of tuples of which the first parameter gives the weight and the second the value.
* @param The type of values to generate
* @return a new arbitrary instance
*/
public static Arbitrary frequency(List extends Tuple2> frequencies) {
return ArbitrariesFacade.implementation.frequency(frequencies);
}
/**
* Create an arbitrary that will randomly choose between all given arbitraries of the same type T.
* The probability distribution is weighted with the first parameter of the tuple.
*
* @param frequencies An array of tuples of which the first parameter gives the weight and the second the arbitrary.
* @param The type of values to generate
* @return a new arbitrary instance
*/
@SuppressWarnings("unchecked")
@SafeVarargs
public static Arbitrary frequencyOf(Tuple2>... frequencies) {
List>> all = new ArrayList<>();
for (Tuple2> frequency : frequencies) {
all.add(Tuple.of(frequency.get1(), (Arbitrary) frequency.get2()));
}
return frequencyOf(all);
}
/**
* Create an arbitrary that will randomly choose between all given arbitraries of the same type T.
* The probability distribution is weighted with the first parameter of the tuple.
*
* @param frequencies A list of tuples of which the first parameter gives the weight and the second the arbitrary.
* @param The type of values to generate
* @return a new arbitrary instance
*/
public static Arbitrary frequencyOf(List extends Tuple2>> frequencies) {
// Simple flatMapping is not enough because of configurations
return ArbitrariesFacade.implementation.frequencyOf(frequencies);
}
/**
* Create an arbitrary that generates values of type Integer.
*
* @return a new arbitrary instance
*/
public static IntegerArbitrary integers() {
return ArbitrariesFacade.implementation.integers();
}
/**
* Create an arbitrary that generates values of type Long.
*
* @return a new arbitrary instance
*/
public static LongArbitrary longs() {
return ArbitrariesFacade.implementation.longs();
}
/**
* Create an arbitrary that generates values of type BigInteger.
*
* @return a new arbitrary instance
*/
public static BigIntegerArbitrary bigIntegers() {
return ArbitrariesFacade.implementation.bigIntegers();
}
/**
* Create an arbitrary that generates values of type Float.
*
* @return a new arbitrary instance
*/
public static FloatArbitrary floats() {
return ArbitrariesFacade.implementation.floats();
}
/**
* Create an arbitrary that generates values of type BigDecimal.
*
* @return a new arbitrary instance
*/
public static BigDecimalArbitrary bigDecimals() {
return ArbitrariesFacade.implementation.bigDecimals();
}
/**
* Create an arbitrary that generates values of type Double.
*
* @return a new arbitrary instance
*/
public static DoubleArbitrary doubles() {
return ArbitrariesFacade.implementation.doubles();
}
/**
* Create an arbitrary that generates values of type Byte.
*
* @return a new arbitrary instance
*/
public static ByteArbitrary bytes() {
return ArbitrariesFacade.implementation.bytes();
}
/**
* Create an arbitrary that generates values of type Short.
*
* @return a new arbitrary instance
*/
public static ShortArbitrary shorts() {
return ArbitrariesFacade.implementation.shorts();
}
/**
* Create an arbitrary that generates values of type String.
*
* @return a new arbitrary instance
*/
public static StringArbitrary strings() {
return ArbitrariesFacade.implementation.strings();
}
/**
* Create an arbitrary that generates values of type Character.
*
* @return a new arbitrary instance
*/
public static CharacterArbitrary chars() {
return ArbitrariesFacade.implementation.chars();
}
/**
* Create an arbitrary that will always generate the same value.
*
* @param value The value to "generate".
* @param The type of the value
* @return a new arbitrary instance
*/
@API(status = MAINTAINED, since = "1.3.2")
public static Arbitrary just(T value) {
return ArbitrariesFacade.implementation.just(value);
}
/**
* Create an arbitrary that will use a supplier to generate a value.
* The difference to {@linkplain Arbitraries#just(Object)} is that the value
* is freshly generated for each try of a property.
*
*
* Mind that within a {@code supplier} you should never use other arbitraries
* or do anything non-deterministic.
*
*
*
* For exhaustive shrinking all generated values are supposed to have identical behaviour,
* i.e. that means that only one value is generated per combination.
*
*
* @param supplier The supplier use to generate a value
* @param The type of values to generate
* @return a new arbitrary instance
*/
@API(status = MAINTAINED, since = "1.1.1")
public static Arbitrary create(Supplier supplier) {
return ArbitrariesFacade.implementation.create(supplier);
}
/**
* Create an arbitrary that will always generate a list which is a
* permutation of the values handed to it. Permutations will
* not be shrunk.
*
* @param values The values to permute
* @param The type of values to generate
* @return a new arbitrary instance
*/
@SafeVarargs
public static Arbitrary> shuffle(T... values) {
return shuffle(Arrays.asList(values));
}
/**
* Create an arbitrary that will always generate a list which is a
* permutation of the values handed to it. Permutations will
* not be shrunk.
*
* @param values The values to permute
* @param The type of values to generate
* @return a new arbitrary instance
*/
public static Arbitrary> shuffle(List values) {
return ArbitrariesFacade.implementation.shuffle(values);
}
/**
* Find a registered arbitrary that will be used to generate values of type T.
* All default arbitrary providers and all registered arbitrary providers are considered.
* This is more or less the same mechanism that jqwik uses to find arbitraries for
* property method parameters.
*
* @param type The type of the value to find an arbitrary for
* @param typeParameters The type parameters if type is a generic type
* @param The type of values to generate
* @return a new arbitrary instance
* @throws CannotFindArbitraryException if there is no registered arbitrary provider to serve this type
*/
public static Arbitrary defaultFor(Class type, Class>... typeParameters) {
return ArbitrariesFacade.implementation.defaultFor(type, typeParameters);
}
/**
* Find a registered arbitrary that will be used to generate values of type T.
* All default arbitrary providers and all registered arbitrary providers are considered.
* This is more or less the same mechanism that jqwik uses to find arbitraries for
* property method parameters.
*
* The returned arbitrary is lazy, i.e. it be evaluated at generation time to allow
* domain contexts to be used.
*
* @param typeUsage The type of the value to find an arbitrary for
* @param The type of values to generate
* @return a new arbitrary instance
*/
@API(status = MAINTAINED, since = "1.1")
public static Arbitrary defaultFor(TypeUsage typeUsage) {
return defaultFor(typeUsage, ignore -> {throw new CannotFindArbitraryException(typeUsage);});
}
/**
* Find a registered arbitrary that will be used to generate values of type T.
* All default arbitrary providers and all registered arbitrary providers are considered.
* This is more or less the same mechanism that jqwik uses to find arbitraries for
* property method parameters.
*
* The returned arbitrary is lazy, i.e. it be evaluated at generation time to allow
* domain contexts to be used. Those
*
* @param typeUsage The type of the value to find an arbitrary for
* @param noDefaultResolver Alternative resolution when no default arbitrary can be found at generation time
* @param The type of values to generate
* @return a new arbitrary instance
*/
@API(status = EXPERIMENTAL, since = "1.6.1")
public static Arbitrary defaultFor(TypeUsage typeUsage, Function super TypeUsage, ? extends Arbitrary> noDefaultResolver) {
return ArbitrariesFacade.implementation.defaultFor(typeUsage, noDefaultResolver);
}
/**
* Create an arbitrary for type {@code T} that will by default use the type's
* public constructors and public factory methods.
*
* @param targetType The class of the type to create an arbitrary for
* @param The type of values to generate
* @return a new arbitrary instance
* @see TypeArbitrary
*/
@API(status = MAINTAINED, since = "1.2.0")
public static TypeArbitrary forType(Class targetType) {
return ArbitrariesFacade.implementation.forType(targetType);
}
/**
* Create an arbitrary for type {@code T} that will try to traverse a type
* - and all types it is based on - given a {@linkplain Traverser} strategy.
*
*
* By default recursion is disable, i.e. that parameters of creator functions
* can be resolved by the traverser, have a default arbitrary or generation fails at runtime.
* Use {@linkplain TraverseArbitrary#enableRecursion()} to switch on recursive traversal.
*
*
* One usage of this traversing mechanism is {@linkplain #forType(Class)}
* which uses {@code #traverse(Class, Traverser)} under the hood.
*
*
* @param targetType The class of the type to create an arbitrary for
* @param The type of values to generate
* @param traverser The traversing strategy specification
* @return a new arbitrary instance
* @see TraverseArbitrary
*/
@API(status = EXPERIMENTAL, since = "1.6.1")
public static TraverseArbitrary traverse(Class targetType, Traverser traverser) {
return ArbitrariesFacade.implementation.traverse(targetType, traverser);
}
/**
* Create an arbitrary that will evaluate arbitrarySupplier as soon as it is used for generating values.
*
* This is useful (and necessary) when arbitrary providing functions use other arbitrary providing functions
* in a recursive way. Without the use of lazy() this would result in a stack overflow.
* Most of the time, however, using {@linkplain #lazyOf(Supplier, Supplier[])} is the better choice
* because it has significantly better shrinking behaviour.
*
* @param arbitrarySupplier The supplier function being used to generate an arbitrary
* @param The type of values to generate
* @return a new arbitrary instance
* @see #recursive(Supplier, Function, int)
* @see #lazyOf(Supplier, Supplier[])
*/
public static Arbitrary lazy(Supplier extends Arbitrary> arbitrarySupplier) {
return ArbitrariesFacade.implementation.lazy(arbitrarySupplier);
}
/**
* Create an arbitrary by deterministic recursion.
*
* Mind that the arbitrary will be created by invoking recursion at arbitrary creation time.
* Using {@linkplain #lazyOf(Supplier, Supplier[])} or {@linkplain #lazy(Supplier)} instead
* will recur at value generation time.
*
* @param base The supplier returning the recursion's base case
* @param recur The function to extend the base case
* @param depth The number of times to invoke recursion
* @param The type of values to generate
* @return a new arbitrary instance
* @see #lazy(Supplier)
*/
public static Arbitrary recursive(
Supplier extends Arbitrary> base,
Function super Arbitrary, ? extends Arbitrary> recur,
int depth
) {
return ArbitrariesFacade.implementation.recursive(base, recur, depth, depth);
}
/**
* Create an arbitrary by deterministic recursion.
*
* Mind that the arbitrary will be created by invoking recursion at arbitrary creation time.
* Using {@linkplain #lazyOf(Supplier, Supplier[])} or {@linkplain #lazy(Supplier)} instead
* will recur at value generation time.
*
* @param base The supplier returning the recursion's base case
* @param recur The function to extend the base case
* @param minDepth The minimum number of times to invoke recursion
* @param maxDepth The maximum number of times to invoke recursion
* @param The type of values to generate
* @return a new arbitrary instance
* @see #lazy(Supplier)
*/
@API(status = MAINTAINED, since = "1.6.4")
public static Arbitrary recursive(
Supplier extends Arbitrary> base,
Function super Arbitrary, ? extends Arbitrary> recur,
int minDepth,
int maxDepth
) {
return ArbitrariesFacade.implementation.recursive(base, recur, minDepth, maxDepth);
}
/**
* Create an arbitrary by lazy supplying one of several arbitraries.
* The main use of this function is to allow recursive generation of structured
* values without overflowing the stack.
*
*
* One alternative is to use {@linkplain #lazy(Supplier)} combined with
* {@linkplain Arbitraries#oneOf(Arbitrary, Arbitrary[])}
* or {@linkplain Arbitraries#frequencyOf(Tuple.Tuple2[])}.
* But {@code lazyOf()} has considerably better shrinking behaviour with recursion.
*
*
*
* Caveat:
* Never use this construct if suppliers make use of variable state
* like method parameters or changing instance members.
* In those cases use {@linkplain #lazy(Supplier)} instead.
*
*
* @param first The first supplier to choose from
* @param rest The rest of suppliers to choose from
* @param The type of values to generate
* @return a (potentially cached) arbitrary instance
* @see #lazy(Supplier)
* @see #recursive(Supplier, Function, int)
*/
@SuppressWarnings("unchecked")
@SafeVarargs
@API(status = MAINTAINED, since = "1.3.4")
public static Arbitrary lazyOf(Supplier> first, Supplier>... rest) {
List>> all = new ArrayList<>();
all.add(() -> (Arbitrary) first.get());
for (Supplier> arbitrarySupplier : rest) {
all.add(() -> (Arbitrary) arbitrarySupplier.get());
}
return ArbitrariesFacade.implementation.lazyOf(all);
}
/**
* Create an arbitrary to create a sequence of actions. Useful for stateful testing.
*
* @param actionArbitrary The arbitrary to generate individual actions.
* @param The type of actions to generate
* @return a new arbitrary instance
*/
@API(status = MAINTAINED, since = "1.0")
public static ActionSequenceArbitrary sequences(Arbitrary extends Action> actionArbitrary) {
return ArbitrariesFacade.implementation.sequences(actionArbitrary);
}
/**
* Create an arbitrary to create instances of {@linkplain Map}.
* The generated maps are mutable.
*
* @param keysArbitrary The arbitrary to generate the keys
* @param valuesArbitrary The arbitrary to generate the values
* @param type of keys
* @param type of values
* @return a new arbitrary instance
*/
@API(status = MAINTAINED, since = "1.1.6")
public static MapArbitrary maps(Arbitrary keysArbitrary, Arbitrary valuesArbitrary) {
return ArbitrariesFacade.implementation.maps(keysArbitrary, valuesArbitrary);
}
/**
* Create an arbitrary to create instances of {@linkplain java.util.Map.Entry}.
* The generated entries are mutable.
*
* @param keysArbitrary The arbitrary to generate the keys
* @param valuesArbitrary The arbitrary to generate the values
* @param type of keys
* @param type of values
* @return a new arbitrary instance
*/
@API(status = MAINTAINED, since = "1.2.0")
public static Arbitrary> entries(Arbitrary keysArbitrary, Arbitrary valuesArbitrary) {
return ArbitrariesFacade.implementation.entries(keysArbitrary, valuesArbitrary);
}
/**
* Create an arbitrary that never creates anything. Sometimes useful
* when generating arbitraries of "functions" that have void as return type.
*
* @return arbitrary instance that will generate nothing
*/
@API(status = MAINTAINED, since = "1.3.0")
public static Arbitrary nothing() {
return just(null);
}
/**
* Create a new arbitrary of element type {@code Set} using the handed in values as elements of the set.
*
* @return a new arbitrary instance
*/
@API(status = MAINTAINED, since = "1.6.4")
public static SetArbitrary subsetOf(Collection extends T> values) {
return Arbitraries.of(values).set();
}
/**
* Create a new arbitrary of element type {@code Set} using the handed in values as elements of the set.
*
* @return a new arbitrary instance
*/
@SafeVarargs
@API(status = MAINTAINED, since = "1.6.4")
public static SetArbitrary subsetOf(T... values) {
return subsetOf(Arrays.asList(values));
}
}