diff options
author | Carlo Zancanaro <carlo@zancanaro.id.au> | 2015-06-06 16:40:04 +1000 |
---|---|---|
committer | Carlo Zancanaro <carlo@zancanaro.id.au> | 2015-06-06 16:40:04 +1000 |
commit | 84f0f216b4643601e4b8760d190b087bbce98bd4 (patch) | |
tree | 5f9ea5c1087b5da6611c9a9c51ba076e55e4e9e3 | |
parent | 05ec409ce96da92d430c4a8e58b08d46f42d667a (diff) |
Lots of work on the stateful checking stuff: it's a fair bit nicer now
19 files changed, 340 insertions, 196 deletions
diff --git a/src/main/java/au/id/zancanaro/javacheck/Generators.java b/src/main/java/au/id/zancanaro/javacheck/Generators.java index 619fe2d..f4ac025 100644 --- a/src/main/java/au/id/zancanaro/javacheck/Generators.java +++ b/src/main/java/au/id/zancanaro/javacheck/Generators.java @@ -40,7 +40,8 @@ public final class Generators { return integer(0, gens.length).flatMap(index -> gens[index].map(x -> (T) x)); } - public static <T> Generator<T> elements(T[] elements) { + @SafeVarargs + public static <T> Generator<T> elements(T... elements) { return elements(Arrays.asList(elements)); } diff --git a/src/main/java/au/id/zancanaro/javacheck/state/Command.java b/src/main/java/au/id/zancanaro/javacheck/state/Command.java index afa3957..78df8f1 100644 --- a/src/main/java/au/id/zancanaro/javacheck/state/Command.java +++ b/src/main/java/au/id/zancanaro/javacheck/state/Command.java @@ -2,22 +2,26 @@ package au.id.zancanaro.javacheck.state; import au.id.zancanaro.javacheck.Generator; -public abstract class Command<State,Args,Result> { - public Generator<Args> argsGenerator(State state) { +public abstract class Command<S, A, R> { + public Generator<A> argsGenerator(S state) { return Generator.pure(null); } - public boolean preCondition(State state, Args args) { + public boolean preCondition(S state, A args) { return true; } - public abstract Result runCommand(Args args); + public abstract R runCommand(S state, A args) throws Throwable; - public State nextState(State state, Args args, CommandValue<Result> result) { + public S nextState(S state, A args, CommandValue<R> result) { return state; } - public boolean postCondition(State oldState, State newState, Args args, Result result) { - return true; + public void postCondition(S oldState, S newState, A args, R result) throws Throwable { + } + + @Override + public String toString() { + return this.getClass().getSimpleName(); } } diff --git a/src/main/java/au/id/zancanaro/javacheck/state/CommandList.java b/src/main/java/au/id/zancanaro/javacheck/state/CommandList.java index 0426fd3..05000f2 100644 --- a/src/main/java/au/id/zancanaro/javacheck/state/CommandList.java +++ b/src/main/java/au/id/zancanaro/javacheck/state/CommandList.java @@ -2,17 +2,17 @@ package au.id.zancanaro.javacheck.state; import java.util.*; -public class CommandList<State> { - private final List<GeneratedCommand<State, ?, ?>> commands; +public class CommandList<S> { + private final List<GeneratedCommand<S, ?, ?>> commands; - public CommandList(List<GeneratedCommand<State, ?, ?>> commands) { + public CommandList(List<GeneratedCommand<S, ?, ?>> commands) { this.commands = new ArrayList<>(commands); } - public CommandResult<State> run(State initialState) { + public CommandResult<S> run(S initialState) { Map<Integer, Object> values = new HashMap<>(); - CommandResult<State> result = CommandResult.success(initialState); - for (GeneratedCommand<State, ?, ?> generated : commands) { + CommandResult<S> result = CommandResult.success(initialState); + for (GeneratedCommand<S, ?, ?> generated : commands) { result = runRealCommand(generated, result.getState(), values); if (result.isFailed()) { break; @@ -21,26 +21,27 @@ public class CommandList<State> { return result; } - private static <State, Args, Result> CommandResult<State> runRealCommand( - GeneratedCommand<State, Args, Result> generated, - State state, + private static <S, A, R> CommandResult<S> runRealCommand( + GeneratedCommand<S, A, R> generated, + S state, Map<Integer, Object> values) { int id = generated.getId(); - Command<State, Args, Result> command = generated.getCommand(); - Args args = generated.getArgs(); + Command<S, A, R> command = generated.getCommand(); + A args = generated.getArgs(); try { if (!command.preCondition(state, args)) { return CommandResult.fail(state, new Error("Precondition failed")); } - Result result = CommandValue.withValues(values, () -> - command.runCommand(args)); + final S oldState = state; + R result = CommandValue.withValues(values, () -> command.runCommand(oldState, args)); values.put(id, result); - final State oldState = state; - final State newState = CommandValue.withValues(values, () -> + final S newState = CommandValue.withValues(values, () -> command.nextState(oldState, args, new CommandValue<>(id))); state = newState; - if (!CommandValue.withValues(values, () -> command.postCondition(oldState, newState, args, result))) { - return CommandResult.fail(state, new Error("Postcondition failed")); + try { + CommandValue.withValues(values, () -> command.postCondition(oldState, newState, args, result)); + } catch (Throwable ex) { + return CommandResult.fail(state, ex); } return CommandResult.success(state); } catch (Throwable ex) { @@ -48,12 +49,12 @@ public class CommandList<State> { } } - private static <State, Args, Result> CommandResult<State> runAbstractCommand( - GeneratedCommand<State, Args, Result> generated, - State state) { + private static <S, A, R> CommandResult<S> runAbstractCommand( + GeneratedCommand<S, A, R> generated, + S state) { int id = generated.getId(); - Command<State, Args, Result> command = generated.getCommand(); - Args args = generated.getArgs(); + Command<S, A, R> command = generated.getCommand(); + A args = generated.getArgs(); try { if (!command.preCondition(state, args)) { return CommandResult.fail(state, new Error("Precondition failed")); @@ -66,8 +67,8 @@ public class CommandList<State> { } public boolean isValid() { - CommandResult<State> result = CommandResult.success(null); - for (GeneratedCommand<State, ?, ?> generated : commands) { + CommandResult<S> result = CommandResult.success(null); + for (GeneratedCommand<S, ?, ?> generated : commands) { result = runAbstractCommand(generated, result.getState()); if (result.isFailed()) { break; @@ -79,7 +80,7 @@ public class CommandList<State> { @Override public String toString() { StringBuilder builder = new StringBuilder(); - Iterator<GeneratedCommand<State, ?, ?>> iterator = commands.iterator(); + Iterator<GeneratedCommand<S, ?, ?>> iterator = commands.iterator(); while (iterator.hasNext()) { builder.append(iterator.next()); if (iterator.hasNext()) { diff --git a/src/main/java/au/id/zancanaro/javacheck/state/CommandListGenerator.java b/src/main/java/au/id/zancanaro/javacheck/state/CommandListGenerator.java index 4c2c47f..1600f07 100644 --- a/src/main/java/au/id/zancanaro/javacheck/state/CommandListGenerator.java +++ b/src/main/java/au/id/zancanaro/javacheck/state/CommandListGenerator.java @@ -9,38 +9,40 @@ import java.util.function.Function; import static au.id.zancanaro.javacheck.Generator.pure; import static au.id.zancanaro.javacheck.Generators.noShrink; -public class CommandListGenerator<State> implements Generator<CommandList<State>> { - private final Function<State, Generator<Command<State, ?, ?>>> generateCommand; +public class CommandListGenerator<S> implements Generator<CommandList<S>> { + private final S initialState; + private final Function<S, Generator<Command<S, ?, ?>>> generateCommand; - public CommandListGenerator(Function<State, Generator<Command<State, ?, ?>>> generateCommand) { + public CommandListGenerator(S initialState, Function<S, Generator<Command<S, ?, ?>>> generateCommand) { + this.initialState = initialState; this.generateCommand = generateCommand; } - public Generator<GeneratedCommand<State, ?, ?>> commandGenerator(int id, State state) { + public Generator<GeneratedCommand<S, ?, ?>> commandGenerator(int id, S state) { return noShrink(generateCommand.apply(state)) .flatMap(command -> generateSingleCommand(id, command, state)); } - public <Args, Result> Generator<GeneratedCommand<State, ?, ?>> generateSingleCommand(int id, Command<State, Args, Result> command, State 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 <Args, Result> State nextState(int id, GeneratedCommand<State, Args, Result> generatedCommand, State 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<State>> generate(Random random, int size) { + public ShrinkTree<CommandList<S>> generate(Random random, int size) { int count = random.nextInt(size); @SuppressWarnings("unchecked") - ShrinkTree<GeneratedCommand<State, ?, ?>>[] commandTrees = (ShrinkTree<GeneratedCommand<State, ?, ?>>[]) new ShrinkTree[count]; - State state = null; + 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<State, ?, ?> generatedCommand = commandTrees[i].getValue(); + GeneratedCommand<S, ?, ?> generatedCommand = commandTrees[i].getValue(); state = nextState(i, generatedCommand, state); } return ShrinkTree.combine(commandTrees, ShrinkTree::removeAndPromoteChildren) diff --git a/src/main/java/au/id/zancanaro/javacheck/state/CommandResult.java b/src/main/java/au/id/zancanaro/javacheck/state/CommandResult.java index 12f650d..cc2f5ba 100644 --- a/src/main/java/au/id/zancanaro/javacheck/state/CommandResult.java +++ b/src/main/java/au/id/zancanaro/javacheck/state/CommandResult.java @@ -1,15 +1,15 @@ package au.id.zancanaro.javacheck.state; -public class CommandResult<State> { - private final State state; +public class CommandResult<S> { + private final S state; private final Throwable thrown; - private CommandResult(State state, Throwable thrown) { + private CommandResult(S state, Throwable thrown) { this.state = state; this.thrown = thrown; } - public State getState() { + public S getState() { return state; } @@ -21,11 +21,11 @@ public class CommandResult<State> { return thrown; } - public static <State> CommandResult<State> success(State state) { + public static <S> CommandResult<S> success(S state) { return new CommandResult<>(state, null); } - public static <State> CommandResult<State> fail(State state, Throwable ex) { + public static <S> CommandResult<S> fail(S state, Throwable ex) { return new CommandResult<>(state, ex); } } diff --git a/src/main/java/au/id/zancanaro/javacheck/state/CommandValue.java b/src/main/java/au/id/zancanaro/javacheck/state/CommandValue.java index 8d3f272..8584fc7 100644 --- a/src/main/java/au/id/zancanaro/javacheck/state/CommandValue.java +++ b/src/main/java/au/id/zancanaro/javacheck/state/CommandValue.java @@ -5,13 +5,31 @@ import java.util.NoSuchElementException; import java.util.function.Supplier; public class CommandValue<T> { + public static interface Action<T> { + T doAction() throws Throwable; + } + + public static interface VoidAction { + void doAction() throws Throwable; + } + private static Map<Integer, Object> values = null; - public static <T> T withValues(Map<Integer, Object> newValues, Supplier<T> action) { + public static <T> T withValues(Map<Integer, Object> newValues, Action<T> action) throws Throwable { + Map<Integer,Object> oldValues = values; + try { + values = newValues; + return action.doAction(); + } finally { + values = oldValues; + } + } + + public static void withValues(Map<Integer, Object> newValues, VoidAction action) throws Throwable { Map<Integer,Object> oldValues = values; try { values = newValues; - return action.get(); + action.doAction(); } finally { values = oldValues; } diff --git a/src/main/java/au/id/zancanaro/javacheck/state/GeneratedCommand.java b/src/main/java/au/id/zancanaro/javacheck/state/GeneratedCommand.java index 90d9a47..23f306b 100644 --- a/src/main/java/au/id/zancanaro/javacheck/state/GeneratedCommand.java +++ b/src/main/java/au/id/zancanaro/javacheck/state/GeneratedCommand.java @@ -1,11 +1,11 @@ package au.id.zancanaro.javacheck.state; -public class GeneratedCommand<State, Args, Result> { +public class GeneratedCommand<S, A, R> { private final int id; - private final Command<State, Args, Result> command; - private final Args args; + private final Command<S, A, R> command; + private final A args; - public GeneratedCommand(int id, Command<State, Args, Result> command, Args args) { + public GeneratedCommand(int id, Command<S, A, R> command, A args) { this.id = id; this.command = command; this.args = args; @@ -15,11 +15,11 @@ public class GeneratedCommand<State, Args, Result> { return id; } - public Command<State, Args, Result> getCommand() { + public Command<S, A, R> getCommand() { return command; } - public Args getArgs() { + public A getArgs() { return args; } diff --git a/src/test/java/au/id/zancanaro/javacheck/state/queue/MyQueue.java b/src/test/java/au/id/zancanaro/javacheck/state/queue/MyQueue.java new file mode 100644 index 0000000..a820532 --- /dev/null +++ b/src/test/java/au/id/zancanaro/javacheck/state/queue/MyQueue.java @@ -0,0 +1,38 @@ +package au.id.zancanaro.javacheck.state.queue; + +import java.util.AbstractQueue; +import java.util.Iterator; +import java.util.LinkedList; + +public class MyQueue<T> extends AbstractQueue<T> { + public final LinkedList<T> list; + + public MyQueue() { + this.list = new LinkedList<>(); + } + + @Override + public Iterator<T> iterator() { + return list.iterator(); + } + + @Override + public int size() { + return list.size(); + } + + @Override + public boolean offer(T t) { + return list.offer(t); + } + + @Override + public T poll() { + return list.poll(); + } + + @Override + public T peek() { + return list.peek(); + } +} diff --git a/src/test/java/au/id/zancanaro/javacheck/state/queue/PopQueueCommand.java b/src/test/java/au/id/zancanaro/javacheck/state/queue/PopQueueCommand.java deleted file mode 100644 index f8a018c..0000000 --- a/src/test/java/au/id/zancanaro/javacheck/state/queue/PopQueueCommand.java +++ /dev/null @@ -1,58 +0,0 @@ -package au.id.zancanaro.javacheck.state.queue; - -import au.id.zancanaro.javacheck.Generator; -import au.id.zancanaro.javacheck.state.Command; -import au.id.zancanaro.javacheck.state.CommandValue; - -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; - -import static au.id.zancanaro.javacheck.Generator.pure; - -public class PopQueueCommand<T> extends Command<QueueState<T>, PopQueueCommand.ArgsType<T>, T> { - @Override - public Generator<ArgsType<T>> argsGenerator(QueueState<T> tQueueState) { - return pure(tQueueState.getConcreteQueue()).map(x -> new ArgsType<>(x)); - } - - @Override - public boolean preCondition(QueueState<T> state, ArgsType<T> args) { - return state != null && !state.getAbstractQueue().isEmpty(); - } - - @Override - public T runCommand(ArgsType<T> args) { - return args.queue.get().poll(); - } - - @Override - public QueueState<T> nextState(QueueState<T> state, ArgsType<T> args, CommandValue<T> result) { - List<T> newState = new ArrayList<>(state.getAbstractQueue()); - newState.remove(0); - return new QueueState<>(state.getConcreteQueue(), newState); - } - - @Override - public boolean postCondition(QueueState<T> oldState, QueueState<T> newState, ArgsType<T> args, T result) { - return oldState.getAbstractQueue().get(0) == result; - } - - @Override - public String toString() { - return "pop"; - } - - static class ArgsType<T> { - public final CommandValue<Queue<T>> queue; - - public ArgsType(CommandValue<Queue<T>> queue) { - this.queue = queue; - } - - @Override - public String toString() { - return "[" + queue + "]"; - } - } -} diff --git a/src/test/java/au/id/zancanaro/javacheck/state/queue/PushQueueCommand.java b/src/test/java/au/id/zancanaro/javacheck/state/queue/PushQueueCommand.java deleted file mode 100644 index b198eb5..0000000 --- a/src/test/java/au/id/zancanaro/javacheck/state/queue/PushQueueCommand.java +++ /dev/null @@ -1,60 +0,0 @@ -package au.id.zancanaro.javacheck.state.queue; - -import au.id.zancanaro.javacheck.Generator; -import au.id.zancanaro.javacheck.state.Command; -import au.id.zancanaro.javacheck.state.CommandValue; - -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; - -public class PushQueueCommand<T> extends Command<QueueState<T>, PushQueueCommand.ArgsType<T>, Void> { - public final Generator<T> generator; - - public PushQueueCommand(Generator<T> argGen) { - this.generator = argGen; - } - - @Override - public Generator<ArgsType<T>> argsGenerator(QueueState<T> state) { - return generator.map(i -> new ArgsType<>(state.getConcreteQueue(), i)); - } - - @Override - public Void runCommand(ArgsType<T> args) { - args.queue.get().offer(args.pushValue); - return null; - } - - @Override - public QueueState<T> nextState(QueueState<T> state, ArgsType<T> args, CommandValue<Void> result) { - List<T> newState = new ArrayList<>(state.getAbstractQueue()); - newState.add(args.pushValue); - return new QueueState<>(state.getConcreteQueue(), newState); - } - - @Override - public boolean preCondition(QueueState<T> state, ArgsType<T> args) { - return state != null; - } - - @Override - public String toString() { - return "push"; - } - - static class ArgsType<T> { - public final CommandValue<Queue<T>> queue; - public final T pushValue; - - public ArgsType(CommandValue<Queue<T>> queue, T pushValue) { - this.queue = queue; - this.pushValue = pushValue; - } - - @Override - public String toString() { - return "[" + queue + ", " + pushValue + "]"; - } - } -} diff --git a/src/test/java/au/id/zancanaro/javacheck/state/queue/QueueState.java b/src/test/java/au/id/zancanaro/javacheck/state/queue/QueueState.java index e4f65f8..6cd6cf8 100644 --- a/src/test/java/au/id/zancanaro/javacheck/state/queue/QueueState.java +++ b/src/test/java/au/id/zancanaro/javacheck/state/queue/QueueState.java @@ -14,8 +14,12 @@ public class QueueState<T> { this.abstractQueue = abstractQueue; } - public CommandValue<Queue<T>> getConcreteQueue() { - return concreteQueue; + public QueueState<T> withAbstractQueue(List<T> abstractQueue) { + return new QueueState<>(this.concreteQueue, abstractQueue); + } + + public Queue<T> getConcreteQueue() { + return concreteQueue.get(); } public List<T> getAbstractQueue() { diff --git a/src/test/java/au/id/zancanaro/javacheck/state/queue/QueueTest.java b/src/test/java/au/id/zancanaro/javacheck/state/queue/QueueTest.java index 083a8ad..9672fca 100644 --- a/src/test/java/au/id/zancanaro/javacheck/state/queue/QueueTest.java +++ b/src/test/java/au/id/zancanaro/javacheck/state/queue/QueueTest.java @@ -3,29 +3,33 @@ package au.id.zancanaro.javacheck.state.queue; import au.id.zancanaro.javacheck.Generator; import au.id.zancanaro.javacheck.annotations.DataSource; import au.id.zancanaro.javacheck.annotations.Property; -import au.id.zancanaro.javacheck.annotations.Seed; import au.id.zancanaro.javacheck.junit.Properties; import au.id.zancanaro.javacheck.state.*; +import au.id.zancanaro.javacheck.state.queue.commands.*; import org.junit.runner.RunWith; -import java.util.*; +import java.util.LinkedList; import static au.id.zancanaro.javacheck.Generator.pure; +import static au.id.zancanaro.javacheck.Generators.elements; import static au.id.zancanaro.javacheck.Generators.integer; -import static au.id.zancanaro.javacheck.Generators.oneOf; import static org.junit.Assert.assertFalse; @RunWith(Properties.class) public class QueueTest { @DataSource public static Generator<CommandList<QueueState<Integer>>> commandGenerator = - new CommandListGenerator<>(state -> + new CommandListGenerator<>(null, state -> state == null ? - pure(new NewQueueCommand<>()) : - oneOf( - pure(new PopQueueCommand<>()), - pure(new PushQueueCommand<>(integer())) - )); + pure(new New<>()) : + elements( + new New<>(), + new Poll<>(), + new Peek<>(), + new Offer<>(integer()), + new Size<>(), + new Clear<>(), + new Iterator<>())); @Property public void test(CommandList<QueueState<Integer>> commands) throws Throwable { diff --git a/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Clear.java b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Clear.java new file mode 100644 index 0000000..2e88796 --- /dev/null +++ b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Clear.java @@ -0,0 +1,29 @@ +package au.id.zancanaro.javacheck.state.queue.commands; + +import au.id.zancanaro.javacheck.Generator; +import au.id.zancanaro.javacheck.state.Command; +import au.id.zancanaro.javacheck.state.CommandValue; +import au.id.zancanaro.javacheck.state.queue.QueueState; + +import java.util.ArrayList; +import java.util.Queue; + +import static org.junit.Assert.assertEquals; + +public class Clear<T> extends Command<QueueState<T>, Void, Void> { + @Override + public boolean preCondition(QueueState<T> state, Void args) { + return state != null; + } + + @Override + public Void runCommand(QueueState<T> state, Void args) { + state.getConcreteQueue().clear(); + return null; + } + + @Override + public QueueState<T> nextState(QueueState<T> state, Void args, CommandValue<Void> result) { + return state.withAbstractQueue(new ArrayList<>()); + } +} diff --git a/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Iterator.java b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Iterator.java new file mode 100644 index 0000000..361abd6 --- /dev/null +++ b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Iterator.java @@ -0,0 +1,31 @@ +package au.id.zancanaro.javacheck.state.queue.commands; + +import au.id.zancanaro.javacheck.state.Command; +import au.id.zancanaro.javacheck.state.queue.QueueState; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +public class Iterator<T> extends Command<QueueState<T>, Void, java.util.Iterator<T>> { + @Override + public boolean preCondition(QueueState<T> state, Void args) { + return state != null; + } + + @Override + public java.util.Iterator<T> runCommand(QueueState<T> state, Void args) { + return state.getConcreteQueue().iterator(); + } + + @Override + public void postCondition(QueueState<T> oldState, QueueState<T> newState, Void args, java.util.Iterator<T> result) throws Throwable { + java.util.Iterator<T> abstractIterator = oldState.getAbstractQueue().iterator(); + while (abstractIterator.hasNext() && result.hasNext()) { + assertEquals(abstractIterator.next(), result.next()); + } + assertFalse("The abstract iterator is 'longer' than the concrete iterator", + abstractIterator.hasNext()); + assertFalse("The concrete iterator is 'longer' than the abstract iterator", + result.hasNext()); + } +} diff --git a/src/test/java/au/id/zancanaro/javacheck/state/queue/NewQueueCommand.java b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/New.java index d2815dc..114e7ba 100644 --- a/src/test/java/au/id/zancanaro/javacheck/state/queue/NewQueueCommand.java +++ b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/New.java @@ -1,30 +1,27 @@ -package au.id.zancanaro.javacheck.state.queue; +package au.id.zancanaro.javacheck.state.queue.commands; import au.id.zancanaro.javacheck.state.Command; import au.id.zancanaro.javacheck.state.CommandValue; +import au.id.zancanaro.javacheck.state.queue.MyQueue; +import au.id.zancanaro.javacheck.state.queue.QueueState; +import org.junit.Assume; import java.util.ArrayList; -import java.util.LinkedList; import java.util.Queue; -public class NewQueueCommand<T> extends Command<QueueState<T>, Void, Queue<T>> { +public class New<T> extends Command<QueueState<T>, Void, Queue<T>> { @Override public boolean preCondition(QueueState<T> state, Void args) { return state == null; } @Override - public Queue<T> runCommand(Void args) { - return new LinkedList<>(); + public Queue<T> runCommand(QueueState<T> state, Void args) { + return new MyQueue<>(); } @Override public QueueState<T> nextState(QueueState<T> state, Void args, CommandValue<Queue<T>> result) { return new QueueState<>(result, new ArrayList<>()); } - - @Override - public String toString() { - return "new"; - } } diff --git a/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Offer.java b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Offer.java new file mode 100644 index 0000000..301efeb --- /dev/null +++ b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Offer.java @@ -0,0 +1,41 @@ +package au.id.zancanaro.javacheck.state.queue.commands; + +import au.id.zancanaro.javacheck.Generator; +import au.id.zancanaro.javacheck.state.Command; +import au.id.zancanaro.javacheck.state.CommandValue; +import au.id.zancanaro.javacheck.state.queue.QueueState; + +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; + +public class Offer<T> extends Command<QueueState<T>, T, Void> { + public final Generator<T> generator; + + public Offer(Generator<T> argGen) { + this.generator = argGen; + } + + @Override + public Generator<T> argsGenerator(QueueState<T> state) { + return generator; + } + + @Override + public boolean preCondition(QueueState<T> state, T args) { + return state != null; + } + + @Override + public Void runCommand(QueueState<T> state, T args) { + state.getConcreteQueue().offer(args); + return null; + } + + @Override + public QueueState<T> nextState(QueueState<T> state, T args, CommandValue<Void> result) { + List<T> newState = new ArrayList<>(state.getAbstractQueue()); + newState.add(args); + return state.withAbstractQueue(newState); + } +} diff --git a/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Peek.java b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Peek.java new file mode 100644 index 0000000..5bb71a9 --- /dev/null +++ b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Peek.java @@ -0,0 +1,28 @@ +package au.id.zancanaro.javacheck.state.queue.commands; + +import au.id.zancanaro.javacheck.Generator; +import au.id.zancanaro.javacheck.state.Command; +import au.id.zancanaro.javacheck.state.CommandValue; +import au.id.zancanaro.javacheck.state.queue.QueueState; + +import java.util.Queue; + +import static au.id.zancanaro.javacheck.Generator.pure; +import static org.junit.Assert.assertEquals; + +public class Peek<T> extends Command<QueueState<T>, Void, T> { + @Override + public boolean preCondition(QueueState<T> state, Void args) { + return state != null && !state.getAbstractQueue().isEmpty(); + } + + @Override + public T runCommand(QueueState<T> state, Void args) { + return state.getConcreteQueue().peek(); + } + + @Override + public void postCondition(QueueState<T> oldState, QueueState<T> newState, Void args, T result) { + assertEquals(oldState.getAbstractQueue().get(0), result); + } +} diff --git a/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Poll.java b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Poll.java new file mode 100644 index 0000000..b5e0d98 --- /dev/null +++ b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Poll.java @@ -0,0 +1,37 @@ +package au.id.zancanaro.javacheck.state.queue.commands; + +import au.id.zancanaro.javacheck.Generator; +import au.id.zancanaro.javacheck.state.Command; +import au.id.zancanaro.javacheck.state.CommandValue; +import au.id.zancanaro.javacheck.state.queue.QueueState; + +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; + +import static au.id.zancanaro.javacheck.Generator.pure; +import static org.junit.Assert.assertEquals; + +public class Poll<T> extends Command<QueueState<T>, Void, T> { + @Override + public boolean preCondition(QueueState<T> state, Void args) { + return state != null && !state.getAbstractQueue().isEmpty(); + } + + @Override + public T runCommand(QueueState<T> state, Void args) { + return state.getConcreteQueue().poll(); + } + + @Override + public QueueState<T> nextState(QueueState<T> state, Void args, CommandValue<T> result) { + List<T> newState = new ArrayList<>(state.getAbstractQueue()); + newState.remove(0); + return state.withAbstractQueue(newState); + } + + @Override + public void postCondition(QueueState<T> oldState, QueueState<T> newState, Void args, T result) { + assertEquals(oldState.getAbstractQueue().get(0), result); + } +} diff --git a/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Size.java b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Size.java new file mode 100644 index 0000000..ba9d196 --- /dev/null +++ b/src/test/java/au/id/zancanaro/javacheck/state/queue/commands/Size.java @@ -0,0 +1,27 @@ +package au.id.zancanaro.javacheck.state.queue.commands; + +import au.id.zancanaro.javacheck.Generator; +import au.id.zancanaro.javacheck.state.Command; +import au.id.zancanaro.javacheck.state.CommandValue; +import au.id.zancanaro.javacheck.state.queue.QueueState; + +import java.util.Queue; + +import static org.junit.Assert.assertEquals; + +public class Size<T> extends Command<QueueState<T>, Void, Integer> { + @Override + public boolean preCondition(QueueState<T> state, Void args) { + return state != null; + } + + @Override + public Integer runCommand(QueueState<T> state, Void args) { + return state.getConcreteQueue().size(); + } + + @Override + public void postCondition(QueueState<T> oldState, QueueState<T> newState, Void args, Integer result) throws Throwable { + assertEquals((Object) oldState.getAbstractQueue().size(), result); + } +} |