Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.redfin.fuzzy.Cases Maven / Gradle / Ivy
package com.redfin.fuzzy;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class Cases {
/**
* Creates and returns a new case that is "composed" of the values returned by a collection of base cases, according
* to a composition function . This can be useful for quickly writing cases of complex objects that rely on
* various generators for their properties.
*
*
* Use this overload only when you have more base cases than can be covered by one of the type-safe overloads.
*
*
* This function works by collecting all of the subcases defined by each of the base cases and combining them in
* order to produce a single "composed" subcase. The composition function is responsible for returning the result of
* a single such subcase, where the values generated by each of the base cases are provided as input.
*
*
* For example, consider the following composition:
*
* {@code
* Case composedCase = Cases.compose(
* CaseCompositionMode.PAIRWISE_PERMUTATIONS_OF_SUBCASES,
* new Case[] { Any.of(2, 3), Any.of(10, 100, 1000) },
* (random, values) -> (int)values[0] * (int)values[1]
* );
*
* composedCase.generateAllOnce().stream().forEach(System.out::println);
* }
*
* This will return a Case of Integers that is the result of multiplying one of the values from the first base case
* ({@code 2} or {@code 3}) with one of the values from the second base case ({@code 10}, {@code 100}, or
* {@code 1000}). The output might look like the following:
*
*
* 20
* 200
* 2000
* 30
* 300
* 3000
*
*
* @param caseCompositionMode - the algorithm to use for deciding both how many composed subcases will be created,
* as well as which specific values of the base cases to use for each composed subcase. See the descriptions
* for the individual algorithms for more information. In general, you should use
* {@link CaseCompositionMode#PAIRWISE_PERMUTATIONS_OF_SUBCASES} unless you experience performance issues.
* Use {@link CaseCompositionMode#EACH_SUBCASE_AT_LEAST_ONCE} to limit the total number of composed subcases.
* @param baseCases - the cases that the overall case is comprised of.
* @param composition - a function that produces an {@code OUTPUT} value based on the specific values chosen for
* each of the subcases. This function is supplied with the random number generator to use for the test as
* well as an array of the values generated for each of the base cases in the {@code baseCases} array. This
* array will have the same length as the {@code baseCases} array, and the value at each index {@code i} will
* have been produced by a subcase of the base case at the same index.
*
* @param - the return type of the composed case and of the composition function.
*
* @return a case that can be used to generate values based on the composition function.
*/
public static Case compose(
CaseCompositionMode caseCompositionMode,
Case[] baseCases,
BiFunction composition
) {
FuzzyPreconditions.checkNotNull("caseCompositionMode is required.", caseCompositionMode);
FuzzyPreconditions.checkNotNullAndContainsNoNulls(baseCases);
FuzzyPreconditions.checkNotNull("composition function is required.", composition);
Subcase[][] composedSubcases = caseCompositionMode.algorithm.apply(baseCases);
Set> subcases = new HashSet<>();
for(final Subcase[] subcase : composedSubcases) {
subcases.add(r -> {
Object[] values = new Object[subcase.length];
for (int j = 0; j < subcase.length; j++) {
@SuppressWarnings("unchecked")
Subcase> supplier = (Subcase>) subcase[j];
values[j] = supplier.generate(r);
}
return composition.apply(r, values);
});
}
return () -> subcases;
}
/**
* Creates and returns a new case that is "composed" of the subcases of the given base case. This can be useful for
* quickly writing cases of complex objects that rely on various generators for their properties.
*
* @param baseCase - the case that provides the basis for the returned case.
* @param compositionFunction - a function that is called once for each subcase defined by the base case. It is
* provided with the random number generator to use for the test as well as a value generated by one of the
* base case's subcases.
*
* @param the type of values generated by the base case.
* @param the type of values generated by the returned case.
*
* @return a case defining one subcase for each subcase of the base case, whose values are defined by the
* composition function.
*/
@SuppressWarnings("unchecked")
public static Case compose(
Case baseCase,
BiFunction compositionFunction
) {
return compose(
CaseCompositionMode.EACH_SUBCASE_AT_LEAST_ONCE,
new Case[] { baseCase },
(random, cases) -> compositionFunction.apply(random, (INPUT)cases[0])
);
}
/**
* Creates and returns a new case that is "composed" of the values returned by a collection of base cases, according
* to a composition function . This can be useful for quickly writing cases of complex objects that rely on
* various generators for their properties.
*
* @see #compose(CaseCompositionMode, Case[], BiFunction)
*/
@SuppressWarnings("unchecked")
public static Case compose(
CaseCompositionMode caseCompositionMode,
Case baseCase1,
Case baseCase2,
TwoCaseCompositionFunction compositionFunction
) {
return compose(
caseCompositionMode,
new Case[] { baseCase1, baseCase2 },
(random, values) -> compositionFunction.apply(random, (INPUT1)values[0], (INPUT2)values[1])
);
}
public interface TwoCaseCompositionFunction {
OUTPUT apply(Random random, INPUT1 input1, INPUT2 input2);
}
/**
* Creates and returns a new case that is "composed" of the values returned by a collection of base cases, according
* to a composition function . This can be useful for quickly writing cases of complex objects that rely on
* various generators for their properties.
*
* @see #compose(CaseCompositionMode, Case[], BiFunction)
*/
@SuppressWarnings("unchecked")
public static Case compose(
CaseCompositionMode caseCompositionMode,
Case baseCase1,
Case baseCase2,
Case baseCase3,
ThreeCaseCompositionFunction compositionFunction
) {
return compose(
caseCompositionMode,
new Case[] { baseCase1, baseCase2, baseCase3 },
(random, values) -> compositionFunction.apply(random, (INPUT1)values[0], (INPUT2)values[1], (INPUT3)values[2])
);
}
public interface ThreeCaseCompositionFunction {
OUTPUT apply(Random random, INPUT1 input1, INPUT2 input2, INPUT3 input3);
}
/**
* Creates and returns a new case that is "composed" of the values returned by a collection of base cases, according
* to a composition function . This can be useful for quickly writing cases of complex objects that rely on
* various generators for their properties.
*
* @see #compose(CaseCompositionMode, Case[], BiFunction)
*/
@SuppressWarnings("unchecked")
public static Case compose(
CaseCompositionMode caseCompositionMode,
Case baseCase1,
Case baseCase2,
Case baseCase3,
Case baseCase4,
FourCaseCompositionFunction compositionFunction
) {
return compose(
caseCompositionMode,
new Case[] { baseCase1, baseCase2, baseCase3, baseCase4 },
(random, values) -> compositionFunction.apply(random, (INPUT1)values[0], (INPUT2)values[1], (INPUT3)values[2], (INPUT4)values[3])
);
}
public interface FourCaseCompositionFunction {
OUTPUT apply(Random random, INPUT1 input1, INPUT2 input2, INPUT3 input3, INPUT4 input4);
}
/**
* Creates and returns a new case that is "composed" of the values returned by a collection of base cases, according
* to a composition function . This can be useful for quickly writing cases of complex objects that rely on
* various generators for their properties.
*
* @see #compose(CaseCompositionMode, Case[], BiFunction)
*/
@SuppressWarnings("unchecked")
public static Case compose(
CaseCompositionMode caseCompositionMode,
Case baseCase1,
Case baseCase2,
Case baseCase3,
Case baseCase4,
Case baseCase5,
FiveCaseCompositionFunction compositionFunction
) {
return compose(
caseCompositionMode,
new Case[] { baseCase1, baseCase2, baseCase3, baseCase4, baseCase5 },
(random, values) -> compositionFunction.apply(random, (INPUT1)values[0], (INPUT2)values[1], (INPUT3)values[2], (INPUT4)values[3], (INPUT5)values[4])
);
}
public interface FiveCaseCompositionFunction {
OUTPUT apply(Random random, INPUT1 input1, INPUT2 input2, INPUT3 input3, INPUT4 input4, INPUT5 input5);
}
/**
* Creates and returns a new case that is "composed" of the values returned by a collection of base cases, according
* to a composition function . This can be useful for quickly writing cases of complex objects that rely on
* various generators for their properties.
*
* @see #compose(CaseCompositionMode, Case[], BiFunction)
*/
@SuppressWarnings("unchecked")
public static Case compose(
CaseCompositionMode caseCompositionMode,
Case baseCase1,
Case baseCase2,
Case baseCase3,
Case baseCase4,
Case baseCase5,
Case baseCase6,
SixCaseCompositionFunction compositionFunction
) {
return compose(
caseCompositionMode,
new Case[] { baseCase1, baseCase2, baseCase3, baseCase4, baseCase5, baseCase6 },
(random, values) -> compositionFunction.apply(random, (INPUT1)values[0], (INPUT2)values[1], (INPUT3)values[2], (INPUT4)values[3], (INPUT5)values[4], (INPUT6)values[5])
);
}
public interface SixCaseCompositionFunction {
OUTPUT apply(Random random, INPUT1 input1, INPUT2 input2, INPUT3 input3, INPUT4 input4, INPUT5 input5, INPUT6 input6);
}
/**
* Creates and returns a new case that is "composed" of the values returned by a collection of base cases, according
* to a composition function . This can be useful for quickly writing cases of complex objects that rely on
* various generators for their properties.
*
* @see #compose(CaseCompositionMode, Case[], BiFunction)
*/
@SuppressWarnings("unchecked")
public static Case compose(
CaseCompositionMode caseCompositionMode,
Case baseCase1,
Case baseCase2,
Case baseCase3,
Case baseCase4,
Case baseCase5,
Case baseCase6,
Case baseCase7,
SevenCaseCompositionFunction compositionFunction
) {
return compose(
caseCompositionMode,
new Case[] { baseCase1, baseCase2, baseCase3, baseCase4, baseCase5, baseCase6, baseCase7 },
(random, values) -> compositionFunction.apply(random, (INPUT1)values[0], (INPUT2)values[1], (INPUT3)values[2], (INPUT4)values[3], (INPUT5)values[4], (INPUT6)values[5], (INPUT7)values[6])
);
}
public interface SevenCaseCompositionFunction {
OUTPUT apply(Random random, INPUT1 input1, INPUT2 input2, INPUT3 input3, INPUT4 input4, INPUT5 input5, INPUT6 input6, INPUT7 input7);
}
/**
* Creates and returns a new case that is "composed" of the values returned by a collection of base cases, according
* to a composition function . This can be useful for quickly writing cases of complex objects that rely on
* various generators for their properties.
*
* @see #compose(CaseCompositionMode, Case[], BiFunction)
*/
@SuppressWarnings("unchecked")
public static Case compose(
CaseCompositionMode caseCompositionMode,
Case baseCase1,
Case baseCase2,
Case baseCase3,
Case baseCase4,
Case baseCase5,
Case baseCase6,
Case baseCase7,
Case baseCase8,
EightCaseCompositionFunction compositionFunction
) {
return compose(
caseCompositionMode,
new Case[] { baseCase1, baseCase2, baseCase3, baseCase4, baseCase5, baseCase6, baseCase7, baseCase8 },
(random, values) -> compositionFunction.apply(random, (INPUT1)values[0], (INPUT2)values[1], (INPUT3)values[2], (INPUT4)values[3], (INPUT5)values[4], (INPUT6)values[5], (INPUT7)values[6], (INPUT8)values[7])
);
}
public interface EightCaseCompositionFunction {
OUTPUT apply(Random random, INPUT1 input1, INPUT2 input2, INPUT3 input3, INPUT4 input4, INPUT5 input5, INPUT6 input6, INPUT7 input7, INPUT8 input8);
}
/**
* Creates and returns a new case that is "composed" of the values returned by a collection of base cases, according
* to a composition function . This can be useful for quickly writing cases of complex objects that rely on
* various generators for their properties.
*
* @see #compose(CaseCompositionMode, Case[], BiFunction)
*/
@SuppressWarnings("unchecked")
public static Case compose(
CaseCompositionMode caseCompositionMode,
Case baseCase1,
Case baseCase2,
Case baseCase3,
Case baseCase4,
Case baseCase5,
Case baseCase6,
Case baseCase7,
Case baseCase8,
Case baseCase9,
NineCaseCompositionFunction compositionFunction
) {
return compose(
caseCompositionMode,
new Case[] { baseCase1, baseCase2, baseCase3, baseCase4, baseCase5, baseCase6, baseCase7, baseCase8, baseCase9 },
(random, values) -> compositionFunction.apply(random, (INPUT1)values[0], (INPUT2)values[1], (INPUT3)values[2], (INPUT4)values[3], (INPUT5)values[4], (INPUT6)values[5], (INPUT7)values[6], (INPUT8)values[7], (INPUT9)values[8])
);
}
public interface NineCaseCompositionFunction {
OUTPUT apply(Random random, INPUT1 input1, INPUT2 input2, INPUT3 input3, INPUT4 input4, INPUT5 input5, INPUT6 input6, INPUT7 input7, INPUT8 input8, INPUT9 input9);
}
@SafeVarargs
public static Case of(Subcase... subcases) {
FuzzyPreconditions.checkNotNullAndContainsNoNulls(subcases);
Set> subcasesSet = FuzzyUtil.setOf(subcases);
return () -> subcasesSet;
}
@SafeVarargs
public static Case of(Supplier... subcases) {
FuzzyPreconditions.checkNotNullAndContainsNoNulls(subcases);
Set> subcasesSet = new HashSet<>(subcases.length);
for(Supplier supplier : subcases) {
subcasesSet.add(r -> supplier.get());
}
return () -> subcasesSet;
}
@SafeVarargs
public static Case of(T... literalCases) {
FuzzyPreconditions.checkNotNull(literalCases);
Set> subcases = new HashSet<>(literalCases.length);
for(T t : literalCases) {
subcases.add(r -> t);
}
return () -> subcases;
}
@SafeVarargs
public static Case ofDelegates(Supplier>... delegateCases) {
FuzzyPreconditions.checkNotNullAndContainsNoNulls(delegateCases);
Set> subcases = new HashSet<>();
for(Supplier> delegate : delegateCases) {
subcases.addAll(delegate.get().getSubcases());
}
return () -> subcases;
}
public static Case map(Case original, Function mapping) {
FuzzyPreconditions.checkNotNull(original);
FuzzyPreconditions.checkNotNull(mapping);
return map(original, (r, t) -> mapping.apply(t));
}
public static Case map(Case original, BiFunction mapping) {
FuzzyPreconditions.checkNotNull(original);
FuzzyPreconditions.checkNotNull(mapping);
return () -> {
Set> sourceSubcases = original.getSubcases();
Set> mappedSubcases = new HashSet<>(sourceSubcases.size());
for(Subcase source : sourceSubcases) {
mappedSubcases.add(r -> mapping.apply(r, source.generate(r)));
}
return mappedSubcases;
};
}
}