net.jqwik.engine.properties.arbitraries.EdgeCasesSupport Maven / Gradle / Ivy
The newest version!
package net.jqwik.engine.properties.arbitraries;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
import net.jqwik.api.*;
import net.jqwik.engine.*;
import net.jqwik.engine.properties.shrinking.*;
import net.jqwik.engine.support.*;
import org.jspecify.annotations.*;
import static net.jqwik.engine.support.JqwikExceptionSupport.*;
public class EdgeCasesSupport {
public static EdgeCases fromSuppliers(final List>> suppliers) {
return new EdgeCases() {
@Override
public List>> suppliers() {
return suppliers;
}
@Override
public String toString() {
String edgeCases =
suppliers
.stream()
.map(Supplier::get)
.map(Shrinkable::value)
.map(JqwikStringSupport::displayString)
.collect(Collectors.joining(", "));
return String.format("EdgeCases[%s]", edgeCases);
}
};
}
public static EdgeCases choose(final List values, int maxEdgeCases) {
List> shrinkables = new ArrayList<>();
if (values.size() > 0) {
shrinkables.add(new ChooseValueShrinkable<>(values.get(0), values));
}
if (values.size() > 1 && (shrinkables.size() < maxEdgeCases)) {
int lastIndex = values.size() - 1;
shrinkables.add(new ChooseValueShrinkable<>(values.get(lastIndex), values));
}
//noinspection CatchMayIgnoreException
try {
if (values.contains(null) && (shrinkables.size() < maxEdgeCases)) {
shrinkables.add(Shrinkable.unshrinkable(null));
}
} catch (NullPointerException someListsDoNotAllowNullValues) { }
return EdgeCasesSupport.fromShrinkables(shrinkables);
}
public static EdgeCases concatFrom(final List extends Arbitrary> arbitraries, int maxEdgeCases) {
List>> shrinkables = new ArrayList<>();
for (Arbitrary arbitrary : arbitraries) {
shrinkables.add(new ChooseValueShrinkable<>(arbitrary, arbitraries));
}
return flatMapArbitrary(fromShrinkables(shrinkables), Function.identity(), maxEdgeCases);
}
public static EdgeCases concat(List> edgeCases, int maxEdgeCases) {
if (edgeCases.isEmpty() || maxEdgeCases <= 0) {
return EdgeCases.none();
}
if (edgeCases.size() == 1) {
return edgeCases.get(0);
}
List>> concatenatedSuppliers = new ArrayList<>();
int remainingMaxEdgeCases = maxEdgeCases;
for (EdgeCases edgeCase : edgeCases) {
if (edgeCase.isEmpty()) {
continue;
}
List>> suppliers =
edgeCase.suppliers()
.stream()
.limit(Math.max(0, remainingMaxEdgeCases))
.collect(Collectors.toList());
concatenatedSuppliers.addAll(suppliers);
remainingMaxEdgeCases = remainingMaxEdgeCases - suppliers.size();
}
return EdgeCasesSupport.fromSuppliers(concatenatedSuppliers);
}
public static EdgeCases fromShrinkables(List> shrinkables) {
return () -> shrinkables
.stream()
.map(shrinkable -> (Supplier>) () -> shrinkable)
.collect(Collectors.toList());
}
public static EdgeCases map(EdgeCases self, Function super T, ? extends U> mapper) {
return mapShrinkable(self, tShrinkable -> tShrinkable.map(mapper));
}
public static EdgeCases mapShrinkable(EdgeCases self, Function super Shrinkable, ? extends Shrinkable> mapper) {
List>> mappedSuppliers =
self.suppliers().stream()
.map(tSupplier -> mapper.apply(tSupplier.get()))
.filter(Objects::nonNull)
.map(uShrinkable -> (Supplier>) () -> uShrinkable)
.collect(Collectors.toList());
return EdgeCases.fromSuppliers(mappedSuppliers);
}
public static EdgeCases filter(EdgeCases self, Predicate super T> filterPredicate) {
List>> filteredSuppliers =
self.suppliers().stream()
.filter(supplier -> filterPredicate.test(supplier.get().value()))
.map(supplier -> (Supplier>) () -> new FilteredShrinkable<>(supplier.get(), filterPredicate))
.collect(Collectors.toList());
return EdgeCases.fromSuppliers(filteredSuppliers);
}
public static EdgeCases ignoreExceptions(final EdgeCases self, final Class extends Throwable>[] exceptionTypes) {
List>> filteredSuppliers =
self.suppliers().stream()
.filter(supplier -> {
try {
supplier.get().value();
return true;
} catch (Throwable throwable) {
if (isInstanceOfAny(throwable, exceptionTypes)) {
return false;
}
throw throwable;
}
})
.map(shrinkableSupplier -> (Supplier>) () -> {
Shrinkable tShrinkable = shrinkableSupplier.get();
return new IgnoreExceptionShrinkable(tShrinkable, exceptionTypes);
})
.collect(Collectors.toList());
return EdgeCases.fromSuppliers(filteredSuppliers);
}
public static EdgeCases dontShrink(EdgeCases self) {
return () -> self.suppliers()
.stream()
.map(supplier -> (Supplier>) () -> supplier.get().makeUnshrinkable())
.collect(Collectors.toList());
}
public static EdgeCases flatMapArbitrary(
EdgeCases self,
Function super T, ? extends Arbitrary> mapper,
int maxEdgeCases
) {
List>> flatMappedSuppliers =
self.suppliers().stream()
.flatMap(tSupplier -> {
T t = tSupplier.get().value();
return mapper.apply(t).edgeCases(maxEdgeCases).suppliers()
.stream()
.map(uSupplier -> {
Function> shrinkableMapper =
newT -> mapper.apply(newT).generator(1000)
.next(SourceOfRandomness.newRandom(42L));
return (Supplier>) () -> new FixedValueFlatMappedShrinkable<>(
tSupplier.get(),
shrinkableMapper,
uSupplier
);
});
})
.limit(Math.max(0, maxEdgeCases))
.collect(Collectors.toList());
return EdgeCases.fromSuppliers(flatMappedSuppliers);
}
public static EdgeCases combine(
final List> arbitraries,
final Function super List>, ? extends T> combineFunction,
int maxEdgeCases
) {
if (arbitraries.isEmpty() || maxEdgeCases <= 0) {
return EdgeCases.none();
}
List>>> listOfSuppliers = new ArrayList<>();
int remainingEdgeCases = maxEdgeCases;
for (Arbitrary