com.sageserpent.americium.java.TrialsApi Maven / Gradle / Ivy
Show all versions of americium_3 Show documentation
package com.sageserpent.americium.java;
import com.google.common.collect.ImmutableList;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
public interface TrialsApi {
/**
* Helper to break direct recursion when implementing a recursively
* defined trials. You need this when your definition either doesn't have
* a flatmap, or the first argument (the 'left hand side') of a flatmap is
* where the recursion takes place. You won't need this very often, if at
* all.
*
* @param delayed Some definition of a trials instance that is typically
* a recursive step - so you don't want it to execute
* there and then to avoid infinite recursion.
* @param
* @return A safe form of the {@code delayed} {@link Trials} instance
* that won't
* immediately execute, but will yield the same {@code Case} instances.
*/
Trials delay(Supplier> delayed);
/**
* Make a {@link Trials} instance that only ever yields a single instance
* of {@code Case}. Typically used with alternation to mix in some
* important special case with say, a bunch of streamed cases, and also
* used as a base case for recursively-defined trials.
*
* @param onlyCase
* @param
* @return A {@link Trials} instance that only ever yields {@code onlyCase}.
*/
Trials only(Case onlyCase);
/**
* Denote a situation where no cases are possible. This is obviously an
* obscure requirement - it is intended for sophisticated composition of
* several {@link Trials} instances via nested flat-mapping where a
* combination of the parameters from the prior levels of flat-mapping
* cannot yield a test-case, possibly because of a precondition violation
* or simply because the combination is undesirable for testing. In
* this situation one can detect such bad combinations and substitute an
* impossible {@link Trials} instance.
*
* @param
* @return A {@link Trials} instance that never yields any cases.
*/
Trials impossible();
/**
* Produce a {@link Trials} instance that chooses between several cases.
*
* @param firstChoice Mandatory first choice, so there is at least one
* {@link Case}.
* @param secondChoice Mandatory second choice, so there is always some
* element of choice.
* @param otherChoices Optional further choices.
* @return A {@link Trials} instance.
* @apiNote The peculiar signature is to avoid ambiguity with the
* overloads for an iterable / array of cases.
*/
Trials choose(Case firstChoice,
Case secondChoice,
Case... otherChoices);
Trials choose(Iterable choices);
Trials choose(Case[] choices);
Trials chooseWithWeights(Map.Entry firstChoice,
Map.Entry secondChoice,
Map.Entry... otherChoices);
Trials chooseWithWeights(
Iterable> choices);
Trials chooseWithWeights(Map.Entry[] choices);
/**
* Produce a {@link Trials} instance that alternates between the cases of
* the
* given alternatives.
*
*
* @param firstAlternative Mandatory first alternative, so there is at
* least one {@link Trials}.
* @param secondAlternative Mandatory second alternative, so there is
* always some element of alternation.
* @param otherAlternatives Optional further alternatives.
* @return A {@link Trials} instance.
* @apiNote The peculiar signature is to avoid ambiguity with the
* overloads for an iterable / array of cases.
*/
Trials alternate(Trials extends Case> firstAlternative,
Trials extends Case> secondAlternative,
Trials extends Case>... otherAlternatives);
Trials alternate(Iterable> alternatives);
Trials alternate(Trials[] alternatives);
Trials alternateWithWeights(
Map.Entry> firstAlternative,
Map.Entry> secondAlternative,
Map.Entry>... otherAlternatives);
Trials alternateWithWeights(
Iterable>> alternatives);
Trials alternateWithWeights(
Map.Entry>[] alternatives);
/**
* Combine a list of trials instances into a single trials instance that
* yields lists, where those lists all have the size given by the number
* of trials, and the element in each position in the list is provided by
* the trials instance at the corresponding position within {@code
* listOfTrials}.
*
* @param listOfTrials Several trials that act as sources for the
* elements of lists yielded by the resulting
* {@link Trials} instance.
* @param The type of the list elements yielded by the
* resulting {@link Trials} instance.
* @return A {@link Trials} instance that yields lists of the same size.
*/
Trials> immutableLists(
List> listOfTrials);
/**
* Combine an iterable of trials instances into a single trials instance
* that yields collections, where each collection is built from elements
* taken in sequence from the corresponding trials instances in {@code
* iterableOfTrials}. {@link Collection} is some kind of collection that
* can be built from elements of type {@link Element} by a {@link Builder}.
*
* @param iterableOfTrials Several trials that act as sources for the
* elements of collections yielded by the
* resulting {link @Trials} instance. The assumption
* is made that this can be traversed multiple
* times and yield the same elements.
* @param builderFactory A {@link Supplier} that should construct a
* *fresh* instance of a {@link Builder}.
* @param The type of the collection elements yielded by
* the resulting {@link Trials} instance.
* @param Any kind of collection that can take an
* arbitrary number of elements of type
* {@code Case}.
* @return A {@link Trials} instance that yields collections.
*/
Trials collections(
Iterable> iterableOfTrials,
Supplier> builderFactory);
/**
* This is for advanced usage, where there is a need to control how
* trials instances are formulated to avoid hitting the complexity limit,
* or alternatively to control the amount of potentially unbounded
* recursion when trials are recursively flat-mapped. If you don't know
* what this means, you probably don't need this.
*
* The notion of a complexity limit is described in
* {@link TrialsScaffolding.SupplyToSyntax#withComplexityLimit(int)}
*
* @return A {@link Trials} instance yielding the complexity associated
* with the definition's context, taking into account any flat-mapping
* this call is embedded in.
*/
Trials complexities();
/**
* This yields integer ids that are guaranteed to be unique *within* a
* complex test case. This uniqueness holds when multiple ids are
* combined by flat-mapping, possibly in a recursively-formulated trials
* instance.
*
* @return A non-negative integer.
* @apiNote The notion of uniqueness applies *within* the formulation of
* a test case, not between test cases. It is to be expected that
* successive test cases may re-use id values seen in earlier ones.
*/
Trials uniqueIds();
/**
* Produce a trials instance that stream cases from a factory.
*
* This is used where we want to generate a supposedly potentially
* unbounded number of cases, although there is an implied upper limit
* based on the number of distinct long values in the factory's input
* domain.
*
* @param caseFactory Pure (in other words, stateless) function that
* produces a {@link Case} from a long value. Each
* call taking the same long value is expected to
* yield the same case.
Rather than {@link Function
* }, the type {@link CaseFactory} is used here - this
* allows the factory to declare its domain of valid
* inputs, as well as the input value in that domain
* that denotes a 'maximally shrunk' case.
The
* factory is expected to be an injection, so it can
* be fed with any potential long value from that
* domain. It is not expected to be a surjection, so
* distinct long values may result in equivalent cases.
*
* It is expected that long values closer to the case
* factory's maximally shrunk input yield 'smaller'
* cases, in whatever sense is appropriate to either
* the actual type of the cases or their specific use
* as implemented by the factory.
* @return A {@link Trials} instance.
*/
Trials stream(CaseFactory caseFactory);
/**
* Produce a trials instance that stream cases from a factory.
*
* This is used where we want to generate a supposedly potentially
* unbounded number of cases, although there is an implied upper limit
* based on the number of distinct long values in practice.
*
* @param factory Pure (in other words, stateless) function that produces
* a {@code Case} from a long value. Each call taking the
* same long value is expected to yield the same case. The
* factory is expected to be an injection, so it can be
* fed with any potential long value, negative, zero or
* positive. It is not expected to be a surjection, even
* if there are at most as many possible values of {@code
* Case} as there are long values, so distinct long values
* may result in equivalent cases.
*
* It is expected that long values closer to zero yield
* 'smaller' cases, in whatever sense is appropriate to
* either the actual type of the cases or their specific
* use as encoded by the factory.
* @return A {@link Trials} instance.
*/
Trials streamLegacy(Function factory);
Trials bytes();
Trials integers();
Trials integers(int lowerBound, int upperBound);
Trials integers(int lowerBound, int upperBound,
int shrinkageTarget);
Trials nonNegativeIntegers();
Trials longs();
Trials longs(long lowerBound, long upperBound);
Trials longs(long lowerBound, long upperBound, long shrinkageTarget);
Trials nonNegativeLongs();
Trials bigIntegers(BigInteger lowerBound,
BigInteger upperBound);
Trials bigIntegers(BigInteger lowerBound, BigInteger upperBound,
BigInteger shrinkageTarget);
Trials doubles();
Trials doubles(double lowerBound, double upperBound);
Trials doubles(double lowerBound, double upperBound,
double shrinkageTarget);
Trials bigDecimals(BigDecimal lowerBound,
BigDecimal upperBound);
Trials bigDecimals(BigDecimal lowerBound, BigDecimal upperBound,
BigDecimal shrinkageTarget);
Trials booleans();
Trials characters();
Trials characters(char lowerBound, char upperBound);
Trials characters(char lowerBound, char upperBound,
char shrinkageTarget);
Trials instants();
Trials instants(Instant lowerBound, Instant upperBound);
Trials instants(Instant lowerBound, Instant upperBound,
Instant shrinkageTarget);
Trials strings();
/**
* Produce a trials instance whose cases can be used to permute elements
* of indexed collections, or as permutations of integers in their own
* right.
*
* @param numberOfIndices The size of the set of indices [0;
* numberOfIndices)
that permutations are
* generated from: also the size of the
* permutations themselves.
* @return A {@link Trials} instance whose cases are permutations of the
* integer range
* [0; numberOfIndices)
.
*/
Trials> indexPermutations(int numberOfIndices);
/**
* Produce a trials instance whose cases can be used to permute elements
* of indexed collections, or as permutations of integers in their own
* right.
*
* @param numberOfIndices The size of the set of indices [0;
* numberOfIndices)
that permutations are
* generated from.
* @param permutationSize The size of the generated permutations; must be
* in the range [0; numberOfIndices)
* @return A {@link Trials} instance whose cases are permutations of the
* integer range
* [0; numberOfIndices)
.
*/
Trials> indexPermutations(int numberOfIndices,
int permutationSize);
/**
* Produce a trials instance whose cases can be used to select
* combinations of elements of indexed collections, or as permutations of
* integers in their own right.
*
* @param numberOfIndices The size of the set of indices [0;
* numberOfIndices)
that combinations are
* generated from.
* @param combinationSize The size of the generated combinations; must be
* in the range [0; numberOfIndices)
* @return A {@link Trials} instance whose cases are combinations of the
* integer range [0; numberOfIndices)
.
* @apiNote The indices in the combinations are sorted in ascending order.
*/
Trials> indexCombinations(int numberOfIndices,
int combinationSize);
/**
* Produce a trials instance whose cases are lists containing elements
* picked alternately from {@code iterables}. The order of elements
* contributed by any given iterable is preserved in the yielded lists,
* but there can be arbitrary alternation across the iterables.
*
* @param shrinkToRoundRobin If true, then shrinkage will try to proceed
* to a systematic alternation across the
* iterables, draining them in round-robin
* fashion. Otherwise, shrinkage will try to
* proceed towards concatenating the iterables,
* draining each one completely in sequence.
* @param iterable Sources of elements.
* @param The type of the list elements yielded by the
* resulting {@link Trials} instance.
* @return A {@link Trials} instance whose cases are lists of {@code
* Element}.
*/
Trials> pickAlternatelyFrom(
boolean shrinkToRoundRobin,
Iterable... iterable);
}