/* __ __ __ __ __ ___
* \ \ / / \ \ / / __/
* \ \/ / /\ \ \/ / /
* \____/__/ \__\____/__/.ɪᴏ
* ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
*/
package io.vavr.test;
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\
G E N E R A T O R C R A F T E D
\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
import static org.assertj.core.api.Assertions.assertThat;
import io.vavr.CheckedFunction1;
import io.vavr.Tuple;
import io.vavr.collection.List;
import java.util.Random;
import org.junit.Test;
public class PropertyTest {
static <T> CheckedFunction1<T, Boolean> tautology() {
return any -> true;
}
static <T> CheckedFunction1<T, Boolean> falsum() {
return any -> false;
}
static final Arbitrary<Object> OBJECTS = Gen.of(null).arbitrary();
@Test(expected = NullPointerException.class)
public void shouldThrowWhenPropertyNameIsNull() {
Property.def(null);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowWhenPropertyNameIsEmpty() {
Property.def("");
}
// -- Property.check methods
@Test
public void shouldCheckUsingDefaultConfiguration() {
final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check();
assertThat(result.isSatisfied()).isTrue();
assertThat(result.isExhausted()).isFalse();
}
@Test
public void shouldCheckGivenSizeAndTries() {
final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(0, 0);
assertThat(result.isSatisfied()).isTrue();
assertThat(result.isExhausted()).isTrue();
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowOnCheckGivenNegativeTries() {
Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(0, -1);
}
@Test
public void shouldCheckGivenRandomAndSizeAndTries() {
final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(new Random(), 0, 0);
assertThat(result.isSatisfied()).isTrue();
assertThat(result.isExhausted()).isTrue();
}
// -- satisfaction
@Test
public void shouldCheckPythagoras() {
final Arbitrary<Double> real = n -> Gen.choose(0, (double) n).filter(d -> d > .0d);
// (∀a,b ∈ ℝ+ ∃c ∈ ℝ+ : a²+b²=c²) ≡ (∀a,b ∈ ℝ+ : √(a²+b²) ∈ ℝ+)
final Checkable property = Property.def("test").forAll(real, real).suchThat((a, b) -> Math.sqrt(a * a + b * b) > .0d);
final CheckResult result = property.check();
assertThat(result.isSatisfied()).isTrue();
assertThat(result.isExhausted()).isFalse();
}
@Test
public void shouldCheckZipAndThenUnzipIsIdempotentForListsOfSameLength() {
// ∀is,ss: length(is) = length(ss) → unzip(zip(is, ss)) = (is, ss)
final Arbitrary<List<Integer>> ints = Arbitrary.list(size -> Gen.choose(0, size));
final Arbitrary<List<String>> strings = Arbitrary.list(
Arbitrary.string(
Gen.frequency(
Tuple.of(1, Gen.choose('A', 'Z')),
Tuple.of(1, Gen.choose('a', 'z')),
Tuple.of(1, Gen.choose('0', '9'))
)));
final CheckResult result = Property.def("test")
.forAll(ints, strings)
.suchThat((is, ss) -> is.length() == ss.length())
.implies((is, ss) -> is.zip(ss).unzip(t -> t).equals(Tuple.of(is, ss)))
.check();
assertThat(result.isSatisfied()).isTrue();
assertThat(result.isExhausted()).isFalse();
}
// -- exhausting
@Test
public void shouldRecognizeExhaustedParameters() {
final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(falsum()).implies(tautology()).check();
assertThat(result.isSatisfied()).isTrue();
assertThat(result.isExhausted()).isTrue();
}
// -- falsification
@Test
public void shouldFalsifyFalseProperty() {
final Arbitrary<Integer> ones = n -> random -> 1;
final CheckResult result = Property.def("test").forAll(ones).suchThat(one -> one == 2).check();
assertThat(result.isFalsified()).isTrue();
assertThat(result.isExhausted()).isFalse();
assertThat(result.count()).isEqualTo(1);
}
// -- error detection
@Test
public void shouldRecognizeArbitraryError() {
final Arbitrary<?> arbitrary = n -> { throw new RuntimeException("yay! (this is a negative test)"); };
final CheckResult result = Property.def("test").forAll(arbitrary).suchThat(tautology()).check();
assertThat(result.isErroneous()).isTrue();
assertThat(result.isExhausted()).isFalse();
assertThat(result.count()).isEqualTo(0);
assertThat(result.sample().isEmpty()).isTrue();
}
@Test
public void shouldRecognizeGenError() {
final Arbitrary<?> arbitrary = Gen.fail("yay! (this is a negative test)").arbitrary();
final CheckResult result = Property.def("test").forAll(arbitrary).suchThat(tautology()).check();
assertThat(result.isErroneous()).isTrue();
assertThat(result.isExhausted()).isFalse();
assertThat(result.count()).isEqualTo(1);
assertThat(result.sample().isEmpty()).isTrue();
}
@Test
public void shouldRecognizePropertyError() {
final Arbitrary<Integer> a1 = n -> random -> 1;
final Arbitrary<Integer> a2 = n -> random -> 2;
final CheckResult result = Property.def("test").forAll(a1, a2).suchThat((a, b) -> {
throw new RuntimeException("yay! (this is a negative test)");
}).check();
assertThat(result.isErroneous()).isTrue();
assertThat(result.isExhausted()).isFalse();
assertThat(result.count()).isEqualTo(1);
assertThat(result.sample().isDefined()).isTrue();
assertThat(result.sample().get()).isEqualTo(Tuple.of(1, 2));
}
// -- Property.and tests
@Test
public void shouldCheckAndCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsTrue() {
final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology());
final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology());
final CheckResult result = p1.and(p2).check();
assertThat(result.isSatisfied()).isTrue();
}
@Test
public void shouldCheckAndCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsFalse() {
final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology());
final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum());
final CheckResult result = p1.and(p2).check();
assertThat(result.isSatisfied()).isFalse();
}
@Test
public void shouldCheckAndCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsTrue() {
final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum());
final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology());
final CheckResult result = p1.and(p2).check();
assertThat(result.isSatisfied()).isFalse();
}
@Test
public void shouldCheckAndCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsFalse() {
final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum());
final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum());
final CheckResult result = p1.and(p2).check();
assertThat(result.isSatisfied()).isFalse();
}
// -- Property.or tests
@Test
public void shouldCheckOrCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsTrue() {
final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology());
final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology());
final CheckResult result = p1.or(p2).check();
assertThat(result.isSatisfied()).isTrue();
}
@Test
public void shouldCheckOrCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsFalse() {
final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology());
final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum());
final CheckResult result = p1.or(p2).check();
assertThat(result.isSatisfied()).isTrue();
}
@Test
public void shouldCheckOrCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsTrue() {
final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum());
final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology());
final CheckResult result = p1.or(p2).check();
assertThat(result.isSatisfied()).isTrue();
}
@Test
public void shouldCheckOrCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsFalse() {
final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum());
final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum());
final CheckResult result = p1.or(p2).check();
assertThat(result.isSatisfied()).isFalse();
}
}