-
-
Notifications
You must be signed in to change notification settings - Fork 64
/
Copy pathCompositeActionExperiments.java
112 lines (86 loc) · 2.31 KB
/
CompositeActionExperiments.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package experiments;
import org.assertj.core.api.*;
import net.jqwik.api.*;
import net.jqwik.api.stateful.*;
import static net.jqwik.api.Arbitraries.*;
class CompositeActionExperiments {
@Property
void neverLongerThan10(@ForAll("actions") ActionSequence<String> actions) {
String result = actions.run("");
// This will fail since strings of length 10 can be created
Assertions.assertThat(result).hasSizeLessThan(10);
}
@Provide
Arbitrary<ActionSequence<String>> actions() {
Arbitrary<String> toAdd = strings().alpha().ofMinLength(1).ofMaxLength(3);
Arbitrary<Integer> toRemove = integers().between(1, 2);
Arbitrary<Action<String>> addThenRemove =
Combinators.combine(toAdd, toRemove)
.as((add, remove) -> new CompositeAction<>(new AddAction(add), new RemoveAction(remove)));
return sequences(oneOf(
toAdd.map(AddAction::new),
toRemove.map(RemoveAction::new),
addThenRemove
));
}
}
class CompositeAction<T> implements Action<T> {
private final Action<T> first;
private final Action<T> second;
public CompositeAction(Action<T> first, Action<T> second) {this.first = first;
this.second = second;
}
@Override
public boolean precondition(T state) {
return first.precondition(state);
}
@Override
public T run(T state) {
T stateAfterFirst = first.run(state);
if (second.precondition(stateAfterFirst)) {
return second.run(stateAfterFirst);
} else {
return stateAfterFirst;
}
}
@Override
public String toString() {
return String.format("[%s then %s]", first, second);
}
}
class AddAction implements Action<String> {
private final String letter;
AddAction(String toAdd) {
this.letter = toAdd;
}
@Override
public boolean precondition(String state) {
return state.length() + letter.length() <= 10;
}
@Override
public String run(String state) {
return state + letter;
}
@Override
public String toString() {
return String.format("Add: %s", letter);
}
}
class RemoveAction implements Action<String> {
private final int count;
RemoveAction(int count) {
this.count = count;
}
@Override
public boolean precondition(String state) {
return state.length() >= count;
}
@Override
public String run(String state) {
return state.substring(0, state.length() - count);
}
@Override
public String toString() {
return String.format("Remove: %s", count);
}
}