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

net.jqwik.api.Arbitraries Maven / Gradle / Ivy

There is a newer version: 1.9.2
Show newest version
package net.jqwik.api;

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

import org.apiguardian.api.*;

import net.jqwik.api.Tuple.*;
import net.jqwik.api.arbitraries.*;
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  EdgeCases edgeCasesChoose(List values, int maxEdgeCases);

		public abstract  EdgeCases edgeCasesChoose(char[] validChars, int maxEdgeCases);

		public abstract  Optional> exhaustiveChoose(List values, long maxNumberOfSamples);

		public abstract  Optional> exhaustiveCreate(Supplier supplier, long maxNumberOfSamples);

		public abstract Optional> exhaustiveChoose(char[] values, long maxNumberOfSamples);

		public abstract  Optional>> exhaustiveShuffle(List values, long maxNumberOfSamples);

		public abstract  RandomGenerator randomChoose(List values);

		public abstract RandomGenerator randomChoose(char[] values);

		public abstract  Arbitrary oneOf(List> all);

		public abstract  RandomGenerator randomFrequency(List> frequencies);

		public abstract  RandomGenerator randomSamples(T[] samples);

		public abstract  RandomGenerator> randomShuffle(List values);

		public abstract  ActionSequenceArbitrary sequences(Arbitrary> actionArbitrary);

		public abstract  Arbitrary frequencyOf(List>> frequencies);

		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);

		public abstract  Arbitrary lazy(Supplier> 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> base, Function, Arbitrary> recur, int depth);

		public abstract  Arbitrary lazyOf(List>> suppliers);
	}

	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 new Arbitrary() {
			@Override
			public RandomGenerator generator(final int genSize) {
				return generator;
			}

			@Override
			public EdgeCases edgeCases(int maxEdgeCases) {
				return EdgeCases.none();
			}
		};
	}

	/**
	 * 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) {
		return fromGenerator(random -> Shrinkable.unshrinkable(generator.apply(random)));
	}

	/**
	 * 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 values, because changing the value will change * subsequent generated values as well. * For mutable values use {@linkplain #ofSuppliers(Supplier[])} instead. * * @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 values, because changing the value will change * subsequent generated values as well. * For mutable values use {@linkplain #ofSuppliers(Collection)} instead. * * @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 values) { List valueList = values instanceof List ? (List) values : new ArrayList<>(values); return fromGenerators( ArbitrariesFacade.implementation.randomChoose(valueList), max -> ArbitrariesFacade.implementation.exhaustiveChoose(valueList, max), maxEdgeCases -> ArbitrariesFacade.implementation.edgeCasesChoose(valueList, maxEdgeCases) ); } /** * 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 fromGenerators( ArbitrariesFacade.implementation.randomChoose(values), max -> ArbitrariesFacade.implementation.exhaustiveChoose(values, max), maxEdgeCases -> ArbitrariesFacade.implementation.edgeCasesChoose(values, maxEdgeCases) ); } /** * 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 first, Arbitrary... rest) { List> all = new ArrayList<>(); all.add((Arbitrary) first); for (Arbitrary arbitrary : rest) { all.add((Arbitrary) arbitrary); } return oneOf(all); } /** * Create an arbitrary that will randomly choose between all given arbitraries of the same type T. * * @param all A list of arbitraries to choose from * @param The type of values to generate * @return a new arbitrary instance */ public static Arbitrary oneOf(List> all) { if (all.size() == 1) { return all.get(0); } // Simple flatMapping is not enough because of configurations return ArbitrariesFacade.implementation.oneOf(all); } /** * 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> frequencies) { List values = frequencies.stream() .filter(f -> f.get1() > 0) .map(Tuple2::get2) .collect(Collectors.toList()); return fromGenerators( ArbitrariesFacade.implementation.randomFrequency(frequencies), max -> ArbitrariesFacade.implementation.exhaustiveChoose(values, max), maxEdgeCases -> ArbitrariesFacade.implementation.edgeCasesChoose(values, maxEdgeCases) ); } /** * 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>> 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 fromGenerators( random -> Shrinkable.unshrinkable(value), max -> ArbitrariesFacade.implementation.exhaustiveChoose(Arrays.asList(value), max), maxEdgeCases -> EdgeCases.fromSupplier(() -> Shrinkable.unshrinkable(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. *

* 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 fromGenerators( random -> Shrinkable.supplyUnshrinkable(supplier, true), max -> ArbitrariesFacade.implementation.exhaustiveCreate(supplier, max), maxEdgeCases -> EdgeCases.fromSupplier(() -> Shrinkable.supplyUnshrinkable(supplier, true)) ); } /** * 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 fromGenerators( ArbitrariesFacade.implementation.randomShuffle(values), max -> ArbitrariesFacade.implementation.exhaustiveShuffle(values, max), maxEdgeCases -> EdgeCases.fromSupplier(() -> Shrinkable.unshrinkable(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. * * @param typeUsage The type of the value to find an arbitrary for * @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 */ @API(status = MAINTAINED, since = "1.1") public static Arbitrary defaultFor(TypeUsage typeUsage) { return ArbitrariesFacade.implementation.defaultFor(typeUsage); } /** * 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); } private static Arbitrary fromGenerators( final RandomGenerator randomGenerator, final Function>> exhaustiveGeneratorFunction, final Function> edgeCasesSupplier ) { return new Arbitrary() { @Override public RandomGenerator generator(int tries) { return randomGenerator; } @Override public Optional> exhaustive(long maxNumberOfSamples) { return exhaustiveGeneratorFunction.apply(maxNumberOfSamples); } @Override public EdgeCases edgeCases(int maxEdgeCases) { return edgeCasesSupplier.apply(maxEdgeCases); } }; } /** * 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> 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> base, Function, Arbitrary> recur, int depth ) { return ArbitrariesFacade.implementation.recursive(base, recur, depth); } /** * 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 = EXPERIMENTAL, 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> 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); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy