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
|
package au.id.zancanaro.javacheck.state;
import au.id.zancanaro.javacheck.Generator;
import au.id.zancanaro.javacheck.ShrinkTree;
import java.util.Arrays;
import java.util.Random;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Function;
import java.util.function.IntConsumer;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static au.id.zancanaro.javacheck.Generator.pure;
import static au.id.zancanaro.javacheck.Generators.noShrink;
public class CommandListGenerator<S> implements Generator<CommandList<S>> {
private final S initialState;
private final Function<S, Generator<Command<S, ?, ?>>> generateCommand;
public CommandListGenerator(S initialState, Function<S, Generator<Command<S, ?, ?>>> generateCommand) {
this.initialState = initialState;
this.generateCommand = generateCommand;
}
public Generator<GeneratedCommand<S, ?, ?>> commandGenerator(int id, S state) {
return noShrink(generateCommand.apply(state))
.flatMap(command -> generateSingleCommand(id, command, state));
}
public <A, R> Generator<GeneratedCommand<S, ?, ?>> generateSingleCommand(int id, Command<S, A, R> command, S state) {
return command.argsGenerator(state).flatMap(generatedArgs ->
command.preCondition(state, generatedArgs) ?
pure(new GeneratedCommand<>(id, command, generatedArgs)) :
commandGenerator(id, state));
}
public <A, R> S nextState(int id, GeneratedCommand<S, A, R> generatedCommand, S state) {
return generatedCommand.getCommand().nextState(state, generatedCommand.getArgs(), new CommandValue<>(id));
}
@Override
public ShrinkTree<CommandList<S>> generate(Random random, int size) {
int count = random.nextInt(size);
@SuppressWarnings("unchecked")
ShrinkTree<GeneratedCommand<S, ?, ?>>[] commandTrees = (ShrinkTree<GeneratedCommand<S, ?, ?>>[]) new ShrinkTree[count];
S state = initialState;
for (int i = 0; i < count; ++i) {
commandTrees[i] = commandGenerator(i, state).generate(random, size);
GeneratedCommand<S, ?, ?> generatedCommand = commandTrees[i].getValue();
state = nextState(i, generatedCommand, state);
}
return ShrinkTree.combine(commandTrees, ShrinkTree::removeAndPromoteChildren)
.map(list -> new CommandList<>(initialState, list))
.filter(CommandList::isValid);
}
}
|