javaslang.test.CheckResult Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javaslang-test Show documentation
Show all versions of javaslang-test Show documentation
A property check framework for Javaslang.
/* / \____ _ _ ____ ______ / \ ____ __ _______
* / / \/ \ / \/ \ / /\__\/ // \/ \ // /\__\ JΛVΛSLΛNG
* _/ / /\ \ \/ / /\ \\__\\ \ // /\ \ /\\/ \ /__\ \ Copyright 2014-2017 Javaslang, http://javaslang.io
* /___/\_/ \_/\____/\_/ \_/\__\/__/\__\_/ \_// \__/\_____/ Licensed under the Apache License, Version 2.0
*/
package javaslang.test;
import javaslang.Tuple;
import javaslang.control.Option;
import java.io.Serializable;
import java.util.Objects;
/**
* Represents the result of a property check which is
*
*
* - {@code Satisfied}, if all tests satisfied the given property
* - {@code Falsified}, if a counter-example could be discovered that falsified the given property
* - {@code Erroneous}, if an exception occurred executing the property check
*
*
* Please note that a {@code Satisfied} property check may be {@code Exhausted}, if the property is an implication
* and no sample could be found that satisfied the pre-condition. In this case the post-condition is satisfied by
* definition (see ex falso quodlibet).
*
* @author Daniel Dietrich
* @since 1.2.0
*/
public interface CheckResult {
/**
* If this check result is satisfied as specified above.
*
* @return true, if this check result is satisfied, false otherwise
*/
boolean isSatisfied();
/**
* If this check result is falsified as specified above.
*
* @return true, if this check result is falsified, false otherwise
*/
boolean isFalsified();
/**
* If this check result is erroneous as specified above.
*
* @return true, if this check result is erroneous, false otherwise
*/
boolean isErroneous();
/**
* If this check result is exhausted as specified above.
*
* @return true, if this check result is exhausted, false otherwise
*/
boolean isExhausted();
/**
* The name of the checked property this result refers to.
*
* @return a property name
*/
String propertyName();
/**
* The number of checks performed using random generated input data.
*
* @return the number of checks performed
*/
int count();
/**
* An optional sample which falsified the property or which lead to an error.
*
* @return an optional sample
*/
Option sample();
/**
* An optional error.
*
* @return an optional error
* @since 1.2.0
*/
Option error();
/**
* Asserts that this CheckResult is satisfied.
*
* @throws AssertionError if this CheckResult is not satisfied.
*/
default void assertIsSatisfied() {
if (!isSatisfied()) {
throw new AssertionError("Expected satisfied check result but was " + this);
}
}
/**
* Asserts that this CheckResult is satisfied with a given exhausted state.
*
* @param exhausted The exhausted state to be checked in the case of a satisfied CheckResult.
* @throws AssertionError if this CheckResult is not satisfied or the exhausted state does not match.
*/
default void assertIsSatisfiedWithExhaustion(boolean exhausted) {
if (!isSatisfied()) {
throw new AssertionError("Expected satisfied check result but was " + this);
} else if (isExhausted() != exhausted) {
throw new AssertionError("Expected satisfied check result to be " + (exhausted ? "" : "not ") + "exhausted but was: " + this);
}
}
/**
* Asserts that this CheckResult is falsified.
*
* @throws AssertionError if this CheckResult is not falsified.
*/
default void assertIsFalsified() {
if (!isFalsified()) {
throw new AssertionError("Expected falsified check result but was " + this);
}
}
/**
* Asserts that this CheckResult is erroneous.
*
* @throws AssertionError if this CheckResult is not erroneous.
*/
default void assertIsErroneous() {
if (!isErroneous()) {
throw new AssertionError("Expected erroneous check result but was " + this);
}
}
/**
* Represents a satisfied property check.
*/
class Satisfied implements CheckResult, Serializable {
private static final long serialVersionUID = 1L;
private final String propertyName;
private final int count;
private final boolean exhausted;
Satisfied(String propertyName, int count, boolean exhausted) {
this.propertyName = propertyName;
this.count = count;
this.exhausted = exhausted;
}
@Override
public boolean isSatisfied() {
return true;
}
@Override
public boolean isFalsified() {
return false;
}
@Override
public boolean isErroneous() {
return false;
}
@Override
public boolean isExhausted() {
return exhausted;
}
@Override
public String propertyName() {
return propertyName;
}
@Override
public int count() {
return count;
}
@Override
public Option sample() {
return Option.none();
}
@Override
public Option error() {
return Option.none();
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (o instanceof Satisfied) {
final Satisfied that = (Satisfied) o;
return Objects.equals(this.propertyName, that.propertyName)
&& this.count == that.count
&& this.exhausted == that.exhausted;
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hash(propertyName, count, exhausted);
}
@Override
public String toString() {
return String.format("%s(propertyName = %s, count = %s, exhausted = %s)", getClass().getSimpleName(), propertyName, count, exhausted);
}
}
/**
* Represents a falsified property check.
*
* @since 1.2.0
*/
class Falsified implements CheckResult, Serializable {
private static final long serialVersionUID = 1L;
private final String propertyName;
private final int count;
private final Tuple sample;
Falsified(String propertyName, int count, Tuple sample) {
this.propertyName = propertyName;
this.count = count;
this.sample = sample;
}
@Override
public boolean isSatisfied() {
return false;
}
@Override
public boolean isFalsified() {
return true;
}
@Override
public boolean isErroneous() {
return false;
}
@Override
public boolean isExhausted() {
return false;
}
@Override
public String propertyName() {
return propertyName;
}
@Override
public int count() {
return count;
}
@Override
public Option sample() {
return Option.some(sample);
}
@Override
public Option error() {
return Option.none();
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (o instanceof Falsified) {
final Falsified that = (Falsified) o;
return Objects.equals(this.propertyName, that.propertyName)
&& this.count == that.count
&& Objects.equals(this.sample, that.sample);
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hash(propertyName, count, sample);
}
@Override
public String toString() {
return String.format("%s(propertyName = %s, count = %s, sample = %s)", getClass().getSimpleName(), propertyName, count, sample);
}
}
/**
* Represents an erroneous property check.
*
* @since 1.2.0
*/
class Erroneous implements CheckResult, Serializable {
private static final long serialVersionUID = 1L;
private final String propertyName;
private final int count;
private final Error error;
private final Option sample;
Erroneous(String propertyName, int count, Error error, Option sample) {
this.propertyName = propertyName;
this.count = count;
this.error = error;
this.sample = sample;
}
@Override
public boolean isSatisfied() {
return false;
}
@Override
public boolean isFalsified() {
return false;
}
@Override
public boolean isErroneous() {
return true;
}
@Override
public boolean isExhausted() {
return false;
}
@Override
public String propertyName() {
return propertyName;
}
@Override
public int count() {
return count;
}
@Override
public Option sample() {
return sample;
}
@Override
public Option error() {
return Option.some(error);
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (o instanceof Erroneous) {
final Erroneous that = (Erroneous) o;
return Objects.equals(this.propertyName, that.propertyName)
&& this.count == that.count
&& deepEquals(this.error, that.error)
&& Objects.equals(this.sample, that.sample);
} else {
return false;
}
}
boolean deepEquals(Throwable t1, Throwable t2) {
return (t1 == null && t2 == null) || (
t1 != null && t2 != null
&& Objects.equals(t1.getMessage(), t2.getMessage())
&& deepEquals(t1.getCause(), t2.getCause())
);
}
@Override
public int hashCode() {
return Objects.hash(propertyName, count, deepHashCode(error), sample);
}
int deepHashCode(Throwable t) {
if (t == null) {
return 0;
} else {
return Objects.hash(t.getMessage(), deepHashCode(t.getCause()));
}
}
@Override
public String toString() {
return String.format("%s(propertyName = %s, count = %s, error = %s, sample = %s)", getClass().getSimpleName(), propertyName, count, error.getMessage(), sample);
}
}
}