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

com.sageserpent.americium.java.TrialsApi Maven / Gradle / Ivy

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 firstAlternative, Trials secondAlternative, Trials... 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); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy