1 package io.atlassian.fugue.quickcheck;
2
3 import com.pholser.junit.quickcheck.Property;
4 import com.pholser.junit.quickcheck.runner.JUnitQuickcheck;
5 import io.atlassian.fugue.Either;
6 import org.junit.runner.RunWith;
7
8 import java.util.function.Function;
9
10 import static org.hamcrest.Matchers.equalTo;
11 import static org.hamcrest.Matchers.notNullValue;
12 import static org.junit.Assert.assertThat;
13 import static org.junit.Assume.assumeThat;
14
15 @RunWith(JUnitQuickcheck.class) public class EitherPropertiesTest {
16
17 @Property public <E, A> void satisfiesFunctorIdentityLaw(Either<E, A> fa) {
18 assertThat(fa.map(Function.identity()), equalTo(fa));
19 }
20
21 @Property public <E, A, B, C> void satisfiesFunctorCompositeLaw(Either<E, A> fa, Function<A, B> f, Function<B, C> g) {
22 Function<A, B> f1 = assumeResultNotNull(f);
23 Function<B, C> g1 = assumeResultNotNull(g);
24 assertThat(fa.map(f1).map(g1), equalTo(fa.map(g1.compose(f1))));
25 }
26
27 @Property public <E, A> void satisfiesMonadRightIdentityLaw(Either<E, A> fa) {
28 assertThat(fa.flatMap(Either::right), equalTo(fa));
29 }
30
31 @Property public <E, A, B> void satisfiesMonadLeftIdentityLaw(A a, Function<A, Either<E, B>> f) {
32 assumeThat("Either does not support leftIdentity for null values", a, notNullValue());
33 assertThat(Either.right(a).flatMap(f), equalTo(f.apply(a)));
34 }
35
36 @Property public <E, A, B, C> void satisfiesApplicativeCompositionLaw(Either<E, Function<B, C>> fbc, Either<E, Function<A, B>> fab, Either<E, A> fa) {
37 Either<E, Function<B, C>> fbc1 = fbc.map(EitherPropertiesTest::assumeResultNotNull);
38 Either<E, Function<A, B>> fab1 = fab.map(EitherPropertiesTest::assumeResultNotNull);
39 Either<E, Function<A, C>> fac = fab1.ap(fbc1.map(bc -> bc::compose));
40 assertThat(fa.ap(fab1).ap(fbc1), equalTo(fa.ap(fac)));
41 }
42
43 private static <A, B> Function<A, B> assumeResultNotNull(Function<A, B> f) {
44 return a -> {
45 B b = f.apply(a);
46 assumeThat(b, notNullValue());
47 return b;
48 };
49 }
50
51 }