fj.test.Shrink Maven / Gradle / Ivy
package fj.test;
import fj.*;
import static fj.P.p;
import static fj.P.p2;
import static fj.P.p3;
import static fj.P.p4;
import static fj.P.p5;
import static fj.P.p6;
import static fj.P.p7;
import static fj.P.p8;
import static fj.Primitive.Byte_Long;
import static fj.Primitive.Character_Long;
import static fj.Primitive.Double_Long;
import static fj.Primitive.Float_Long;
import static fj.Primitive.Integer_Long;
import static fj.Primitive.Long_Byte;
import static fj.Primitive.Long_Character;
import static fj.Primitive.Long_Double;
import static fj.Primitive.Long_Float;
import static fj.Primitive.Long_Integer;
import static fj.Primitive.Long_Short;
import static fj.Primitive.Short_Long;
import static fj.data.Array.array;
import fj.data.Conversions;
import static fj.data.List.isNotEmpty_;
import fj.data.Array;
import fj.data.Either;
import fj.data.Java;
import fj.data.List;
import fj.data.Option;
import fj.data.Stream;
import static fj.data.Stream.cons;
import static fj.data.Stream.iterate;
import static fj.data.Stream.nil;
import static java.lang.System.arraycopy;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Properties;
import java.util.Stack;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
import java.util.WeakHashMap;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.SynchronousQueue;
/**
* Represents a shrinking strategy over the given type parameter if that type can be represented as
* a tree structure. This is used in falsification to produce the smallest counter-example, rather
* than the first counter-example.
*
* @version %build.number%
*/
public final class Shrink {
private final F> f;
private Shrink(final F> f) {
this.f = f;
}
/**
* Returns a shrink of the given argument.
*
* @param a The argument to shrink.
* @return A shrink of the given argument.
*/
public Stream shrink(final A a) {
return f.f(a);
}
/**
* Creates a shrink from this shrink and the given symmetric transformations.
*
* @param f A transformation from this shrink type to the new shrink type.
* @param g A transformation from the new shrink type to this shrink type.
* @return A shrink from this shrink and the given symmetric transformations.
*/
public Shrink map(final F f, final F g) {
return shrink(b -> Shrink.this.f.f(g.f(b)).map(f));
}
/**
* Constructs a shrink strategy from the given function that produces a tree of values given a
* value.
*
* @param f A function that produces a tree of values given a value.
* @return A shrink strategy from the given function that produces a tree of values given a
* value.
*/
public static Shrink shrink(final F> f) {
return new Shrink(f);
}
/**
* Returns a shrink strategy that cannot be reduced further.
*
* @return A shrink strategy that cannot be reduced further.
*/
public static Shrink empty() {
return shrink(a -> nil());
}
/**
* A shrink strategy for longs using 0 as the bottom of the shrink.
*/
public static final Shrink shrinkLong = shrink(i -> {
if (i == 0L)
return nil();
else {
final Stream is = cons(0L, () -> iterate(x -> x / 2L, i).takeWhile(x2 -> x2 != 0L).map(x1 -> i - x1));
return i < 0L ? cons(-i, () -> is) : is;
}
});
/**
* A shrink strategy for booleans using false as the bottom of the shrink.
*/
public static final Shrink shrinkBoolean =
shrink(Function.>constant(Stream.single(false)));
/**
* A shrink strategy for integers using 0 as the bottom of the shrink.
*/
public static final Shrink shrinkInteger = shrinkLong.map(Long_Integer, Integer_Long);
/**
* A shrink strategy for bytes using 0 as the bottom of the shrink.
*/
public static final Shrink shrinkByte = shrinkLong.map(Long_Byte, Byte_Long);
/**
* A shrink strategy for characters using 0 as the bottom of the shrink.
*/
public static final Shrink shrinkCharacter = shrinkLong.map(Long_Character, Character_Long);
/**
* A shrink strategy for shorts using 0 as the bottom of the shrink.
*/
public static final Shrink shrinkShort = shrinkLong.map(Long_Short, Short_Long);
/**
* A shrink strategy for floats using 0 as the bottom of the shrink.
*/
public static final Shrink shrinkFloat = shrinkLong.map(Long_Float, Float_Long);
/**
* A shrink strategy for doubles using 0 as the bottom of the shrink.
*/
public static final Shrink shrinkDouble = shrinkLong.map(Long_Double, Double_Long);
/**
* Returns a shrink strategy for optional values. A 'no value' is already fully
* shrunk, otherwise, the shrinking occurs on the value with the given shrink strategy.
*
* @param sa The shrink strategy for the potential value.
* @return A shrink strategy for optional values.
*/
public static Shrink