Skip to content

Commit 26c674c

Browse files
committed
Added property based tests for State
1 parent 158276f commit 26c674c

6 files changed

Lines changed: 149 additions & 22 deletions

File tree

core/src/main/java/fj/LcgRng.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88
public class LcgRng extends Rng {
99

10-
private Long seed;
10+
private final Long seed;
1111

1212
public LcgRng() {
1313
this(System.currentTimeMillis());
@@ -17,6 +17,10 @@ public LcgRng(long s) {
1717
seed = s;
1818
}
1919

20+
public long getSeed() {
21+
return seed;
22+
}
23+
2024
public P2<Rng, Integer> nextInt() {
2125
P2<Rng, Long> p = nextLong();
2226
int i = (int) p._2().longValue();

core/src/main/java/fj/Rng.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ public abstract class Rng {
99

1010
public abstract P2<Rng, Long> nextLong();
1111

12+
// [low, high] inclusive
1213
public P2<Rng, Integer> range(int low, int high) {
1314
return nextNatural().map2(x -> (x % (high - low + 1)) + low);
1415
}

core/src/main/java/fj/test/Arbitrary.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import fj.P7;
2121
import fj.P8;
2222
import fj.data.*;
23+
import fj.LcgRng;
2324

2425
import static fj.data.Either.left;
2526
import static fj.data.Either.right;
@@ -127,6 +128,20 @@ public static <A, B> Arbitrary<Reader<A, B>> arbReader(Coarbitrary<A> aa, Arbitr
127128
return arbitrary(Arbitrary.arbF(aa, ab).gen.map(f -> Reader.unit(f)));
128129
}
129130

131+
/**
132+
* An arbitrary for state.
133+
*/
134+
public static <S, A> Arbitrary<State<S, A>> arbState(Arbitrary<S> as, Coarbitrary<S> cs, Arbitrary<A> aa) {
135+
return arbitrary(arbF(cs, arbP2(as, aa)).gen.map(f -> State.unit(f)));
136+
}
137+
138+
/**
139+
* An arbitrary for the LcgRng.
140+
*/
141+
public static <A> Arbitrary<LcgRng> arbLcgRng() {
142+
return arbitrary(Arbitrary.arbLong.gen.map(l -> new LcgRng(l)));
143+
}
144+
130145
/**
131146
* An arbitrary for functions.
132147
*

core/src/main/java/fj/test/Coarbitrary.java

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,15 @@
11
package fj.test;
22

3-
import fj.F;
4-
import fj.F2;
5-
import fj.F3;
6-
import fj.F4;
7-
import fj.F5;
8-
import fj.F6;
9-
import fj.F7;
10-
import fj.F8;
3+
import fj.*;
4+
115
import static fj.Function.curry;
126
import static fj.P.p;
13-
import fj.P1;
14-
import fj.P2;
15-
import fj.P3;
16-
import fj.P4;
17-
import fj.P5;
18-
import fj.P6;
19-
import fj.P7;
20-
import fj.P8;
21-
import fj.data.Array;
7+
8+
import fj.data.*;
9+
2210
import static fj.data.Array.array;
23-
import fj.data.Either;
24-
import fj.data.List;
2511
import static fj.data.List.fromString;
2612
import static fj.data.List.nil;
27-
import fj.data.Option;
28-
import fj.data.Stream;
2913

3014
import static fj.test.Variant.variant;
3115

@@ -84,6 +68,7 @@ public abstract class Coarbitrary<A> {
8468
*/
8569
public abstract <B> Gen<B> coarbitrary(A a, Gen<B> g);
8670

71+
8772
/**
8873
* A curried version of {@link #coarbitrary(Object, Gen)}.
8974
*
@@ -472,6 +457,35 @@ public <B> Gen<B> coarbitrary(final Stream<A> as, final Gen<B> g) {
472457
};
473458
}
474459

460+
/**
461+
* A coarbitrary for the provided LcgRng
462+
* @return A coarbitrary for the provided LcgRng.
463+
*/
464+
public static Coarbitrary<LcgRng> coarbLcgRng() {
465+
return new Coarbitrary<LcgRng>() {
466+
@Override
467+
public <B> Gen<B> coarbitrary(LcgRng rng, Gen<B> g) {
468+
long i = rng.getSeed();
469+
return variant(i >= 0 ? 2 * i : -2 * i + 1, g);
470+
}
471+
};
472+
}
473+
474+
/**
475+
* A coarbitrary for state.
476+
*/
477+
public static <S, A> Coarbitrary<State<S, A>> coarbState(Arbitrary<S> as, F2<S, A, Long> f) {
478+
return new Coarbitrary<State<S, A>>() {
479+
@Override
480+
public <B> Gen<B> coarbitrary(State<S, A> s1, Gen<B> g) {
481+
return as.gen.bind(r -> {
482+
P2<S, A> p = s1.run(r);
483+
return variant(f.f(p._1(), p._2()), g);
484+
});
485+
}
486+
};
487+
}
488+
475489
/**
476490
* A coarbitrary for arrays.
477491
*
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package fj.data;
2+
3+
import org.junit.Test;
4+
5+
/**
6+
* Created by MarkPerry on 18/12/2014.
7+
*/
8+
public class StateTest {
9+
10+
@Test
11+
public void map() {
12+
13+
}
14+
15+
}

core/src/test/java/fj/data/TestRngState.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
package fj.data;
22

33
import fj.*;
4+
import fj.test.Arbitrary;
5+
import fj.test.Coarbitrary;
6+
import fj.test.Gen;
7+
import fj.test.Property;
48
import org.junit.Assert;
59
import org.junit.Test;
610

711
import static fj.data.Option.some;
812
import static fj.data.Stream.unfold;
13+
import static fj.data.test.PropertyAssert.assertResult;
14+
import static fj.test.Arbitrary.*;
15+
import static fj.test.Coarbitrary.coarbInteger;
16+
import static fj.test.Property.prop;
17+
import static fj.test.Property.property;
18+
import static fj.test.Variant.variant;
919

1020
/**
1121
* Created by mperry on 4/08/2014.
@@ -68,4 +78,72 @@ public void testTraverse() {
6878
Assert.assertTrue(list.toString().equals(expected));
6979
}
7080

81+
public static Arbitrary<State<LcgRng, Integer>> arbState() {
82+
return Arbitrary.arbState(Arbitrary.arbLcgRng(), Coarbitrary.coarbLcgRng(), arbInteger);
83+
}
84+
85+
public static Arbitrary<F<LcgRng, P2<LcgRng, Integer>>> arbStateF() {
86+
return arbF(Coarbitrary.coarbLcgRng(), arbP2(arbLcgRng(), arbInteger));
87+
}
88+
89+
public static Coarbitrary<State<LcgRng, Integer>> coarbState() {
90+
return Coarbitrary.coarbState(Arbitrary.arbLcgRng(), (LcgRng s, Integer j) -> (long) (j >= 0 ? 2 * j : -2 * j + 1));
91+
}
92+
93+
public static Arbitrary<F<Integer, State<LcgRng, Integer>>> arbBindable() {
94+
return arbF(coarbInteger, arbState());
95+
}
96+
97+
// Left identity: return i >>= f == f i
98+
@Test
99+
public void testLeftIdentity() {
100+
Property p = property(
101+
arbBindable(),
102+
arbInteger,
103+
arbLcgRng(),
104+
(f, i, r) -> {
105+
int a = State.<LcgRng, Integer>constant(i).flatMap(f).eval(r);
106+
int b = f.f(i).eval(r);
107+
// System.out.println(String.format("a=%d, b=%d", a, b));
108+
return prop(a == b);
109+
}
110+
);
111+
assertResult(p);
112+
}
113+
114+
115+
// Right identity: m >>= return == m
116+
@Test
117+
public void testRightIdentity() {
118+
Property p = Property.property(
119+
arbState(),
120+
arbLcgRng(),
121+
(s, r) -> {
122+
int x = s.flatMap(a -> State.constant(a)).eval(r);
123+
int y = s.eval(r);
124+
// System.out.println(String.format("x=%d, y=%d", x, y));
125+
return prop(x == y);
126+
}
127+
);
128+
assertResult(p);
129+
}
130+
131+
// Associativity: (m >>= f) >>= g == m >>= (\x -> f x >>= g)
132+
@Test
133+
public void testAssociativity() {
134+
Property p = Property.property(
135+
arbState(),
136+
arbBindable(),
137+
arbBindable(),
138+
arbLcgRng(),
139+
(s, f, g, r) -> {
140+
int t = s.flatMap(f).flatMap(g).eval(r);
141+
int u = s.flatMap(x -> f.f(x).flatMap(g)).eval(r);
142+
// System.out.println(String.format("x=%d, y=%d", t, u));
143+
return prop(t == u);
144+
});
145+
assertResult(p);
146+
}
147+
148+
71149
}

0 commit comments

Comments
 (0)