package fj.test;
import fj.F;
import fj.data.List;
import fj.data.Option;
import static fj.data.Option.none;
import static fj.data.Option.some;
/**
* The result of evaluating a property.
*
* @version %build.number%
*/
public final class Result {
private final Option<List<Arg<?>>> args;
private final R r;
private final Option<Throwable> t;
private enum R {
Unfalsified, Falsified, Proven, Exception, NoResult
}
private Result(final Option<List<Arg<?>>> args, final R r, final Option<Throwable> t) {
this.args = args;
this.r = r;
this.t = t;
}
/**
* Returns the potential arguments associated with this result. This will only have a value, if
* and only if {@link #noResult(Option) !noResult()} holds.
*
* @return The potential arguments associated with this result.
*/
public Option<List<Arg<?>>> args() {
return args;
}
/**
* Returns the potential exception associated with this result. This will only have a value if and
* only if this result is an exception result.
*
* @return The potential exception associated with this result.
*/
public Option<Throwable> exception() {
return t;
}
/**
* Returns <code>true</code> if this result is unfalsified; otherwise, <code>false</code>.
*
* @return <code>true</code> if this result is unfalsified; otherwise, <code>false</code>.
*/
public boolean isUnfalsified() {
return r == R.Unfalsified;
}
/**
* Returns <code>true</code> if this result is falsified; otherwise, <code>false</code>.
*
* @return <code>true</code> if this result is falsified; otherwise, <code>false</code>.
*/
public boolean isFalsified() {
return r == R.Falsified;
}
/**
* Returns <code>true</code> if this result is proven; otherwise, <code>false</code>.
*
* @return <code>true</code> if this result is proven; otherwise, <code>false</code>.
*/
public boolean isProven() {
return r == R.Proven;
}
/**
* Returns <code>true</code> if this result is an exception; otherwise, <code>false</code>.
*
* @return <code>true</code> if this result is an exception; otherwise, <code>false</code>.
*/
public boolean isException() {
return r == R.Exception;
}
/**
* Returns <code>true</code> if this result is no result; otherwise, <code>false</code>.
*
* @return <code>true</code> if this result is no result; otherwise, <code>false</code>.
*/
public boolean isNoResult() {
return r == R.NoResult;
}
/**
* Returns <code>true</code> if this result is falsified or an exception; otherwise,
* <code>false</code>.
*
* @return <code>true</code> if this result is falsified or an exception; otherwise,
* <code>false</code>.
*/
public boolean failed() {
return isFalsified() || isException();
}
/**
* Returns <code>true</code> if this result is unfalsified or proven; otherwise,
* <code>false</code>.
*
* @return <code>true</code> if this result is unfalsified or proven; otherwise,
* <code>false</code>.
*/
public boolean passed() {
return isUnfalsified() || isProven();
}
/**
* If this result is proven, alter it to be unfalsified with the same arguments; otherwise, return
* <code>this</code>.
*
* @return If this result is proven, alter it to be unfalsified with the same arguments;
* otherwise, return <code>this</code>.
*/
public Result provenAsUnfalsified() {
return isProven() ? unfalsified(args.some()) : this;
}
/**
* Adds an argument to this result.
*
* @param a The argument to add.
* @return A result with the new argument.
*/
public Result addArg(final Arg<?> a) {
final F<Arg<?>, F<List<Arg<?>>, List<Arg<?>>>> cons = List.cons();
return new Result(args.map(cons.f(a)), r, t);
}
/**
* Returns a potential result for this result. This will have a value if this result is
* {@link #noResult(Option) !noResult()}.
*
* @return A potential result for this result.
*/
@SuppressWarnings("IfMayBeConditional")
public Option<Result> toOption() {
if(isNoResult())
return none();
else
return some(this);
}
/**
* Returns a result from the given potential result.
*
* @param r The potential result.
* @return The result that may be {@link #noResult() noResult()}.
*/
public static Result noResult(final Option<Result> r) {
return r.orSome(Result::noResult);
}
/**
* Returns a result representing no result.
*
* @return A result representing no result.
*/
public static Result noResult() {
return new Result(Option.none(), R.NoResult, Option.none());
}
/**
* Returns an unfalsified result.
*
* @param args The arguments used during the failure of falsification.
* @return An unfalsified result.
*/
public static Result unfalsified(final List<Arg<?>> args) {
return new Result(some(args), R.Unfalsified, Option.none());
}
/**
* Returns a falsified result.
*
* @param args The arguments used during falsification.
* @return A falsified result.
*/
public static Result falsified(final List<Arg<?>> args) {
return new Result(some(args), R.Falsified, Option.none());
}
/**
* Returns a proven result.
*
* @param args The arguments used during proof.
* @return A proven result.
*/
public static Result proven(final List<Arg<?>> args) {
return new Result(some(args), R.Proven, Option.none());
}
/**
* Returns an exception result.
*
* @param args The arguments used when the exception occurred.
* @param t The exception that occurred.
* @return A exception result.
*/
public static Result exception(final List<Arg<?>> args, final Throwable t) {
return new Result(some(args), R.Exception, some(t));
}
}