View Javadoc
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  }