1# Stateful testing - reference
2
3All commands that are part of the state testing framework reside under the `rc::state` namespace. To use them, you must include the `rapidcheck/state.h` header. Type signatures are not to be taken literally.
4
5## Testing
6
7### `void check(Model initialState, Sut sut, GenFunc f)`
8
9### `void check(MakeModel makeInitialState, Sut sut, GenFunc f)`
10
11Generates a valid command sequence for an initial state and then runs that sequence on `sut`. Any assertions triggered when running the command sequence will cause the property to fail. For more information about the generation function parameter, see `rc::state::gen::commands`.
12
13There are two overloads, one that takes the initial state as an immediate value and and another that takes a callable that returns the initial state.
14
15This function must be used inside a property, it cannot be used standalone.
16
17## `Command<Model, Sut>`
18
19Represents an operation in the state testing framework. The `Model` type parameter is the type of the model that models `Sut` which is the actual System Under Test. These can also be accessed through the `Model` and `Sut` member type aliases.
20
21### `virtual void checkPreconditions(const Model &s0) const`
22
23If your command is not valid for all states, you must implement this method to assert preconditions. Preconditions can be asserted using any of the discarding macros such as `RC_PRE` or `RC_DISCARD`. If the command is discarded, RapidCheck will simply try to generate a new one. This method is intended to be overridden but has a default implementation that does nothing which is what you want if your command has no preconditions.
24
25While the model state is passed as `const`, this doesn't prevent modification of the model if it, for example, is a `shared_ptr` or similar. Regardless, modifying the model state in this method leads to undefined behavior.
26
27### `virtual void apply(Model &s0) const`
28
29Applies this command to the given state. The effect of this command on the model should be equivalent to this commands effect on the System Under Test. This method is intended to be overridden but has a default implementation that does nothing, something that can be useful for commands that do not modify state.
30
31### `virtual void run(const Model &s0, Sut &sut) const`
32
33Applies this command to the given System Under Test. The state before this command has been applied is also passed in. If you need the post state, you can get this using the `nextState` convenience method. This is the method in which to place your assertions (`RC_ASSERT` et al.). This method is intended to be overridden but has a default implementation that does nothing.
34
35While the model state is passed as `const`, this doesn't prevent modification of the model if it, for example, is a `shared_ptr` or similar. Regardless, modifying the model state in this method leads to undefined behavior.
36
37### `virtual void show(std::ostream &os) const`
38
39Outputs a string representation of the command to the given output stream. The default implementation outputs the type name (via RTTI) but if your command has any sort of parameters, you will likely want to override this with a custom implementation to include those.
40
41### `Model nextState(const Model &s0) const`
42
43Convenience method that calls `apply` on a copy of the given state and returns it. Saves some keystrokes occasionally since you don't have to allocate a model on the stack. Cannot be overridden, override `apply` instead.
44
45This method does not work for non-copyable models.
46
47## Command sequences
48
49### `Commands<CommandType>`
50
51Type alias for a `std::vector<std::shared_ptr<const CommandType>>`. Useful since command sequences are generally stored in vectors and individual commands are usually passed by `shared_ptr`-to-const.
52
53### `void applyAll(Commands commands, Model &state)`
54
55Applies the given commands in sequence to the given model state.
56
57### `void runAll(Commands commands, Model state, Sut &sut)`
58
59### `void runAll(Commands commands, MakeModel makeState, Sut &sut)`
60
61Runs the given commands in sequence on the given System Under Test assuming it is equivalent to the given model state.
62
63There are two overloads, one that takes the state as an immediate value and and another that takes a callable that returns the state.
64
65### `bool isValidSequence(Commands commands, Model state)`
66
67### `bool isValidSequence(Commands commands, MakeModel makeState)`
68
69Returns `true` if the given command sequence is valid for the given model state, otherwise `false`.
70
71There are two overloads, one that takes the state as an immediate value and and another that takes a callable that returns the state.
72
73## Generators
74
75### `MakeCommandGenerator gen::execOneOfWithArgs<Ts...>()`
76
77Returns a callable that when called returns a generator that randomly constructs one of the commands in `Ts`. If the command has a constructor that matches the (zero or more) arguments given to the callable, that constructor will be used. Otherwise, the command is assumed to have a default constructor. The constructor can make use of the `*`-operator just like in a property or in `gen::exec`.
78
79A common thing to do is to pass the model state as the constructor argument. Here is an example of a command designed for such use:
80
81```C++
82struct Take : rc::state::Command<MyModel, MySut> {
83  std::string item;
84
85  explicit Take(const MyModel &s0)
86      : item(*rc::gen::elementOf(s0.items)) {}
87
88  // ...
89};
90```
91
92Typical usage of `execOneOfWithArgs` is to create the generation function argument for `rc::state::gen::commands` or `rc::state::check`:
93
94```C++
95MyModel initialState;
96MySut sut;
97rc::state::check(initialState,
98                 sut,
99                 rc::state::gen::execOneOfWithArgs<Put, Take, Frobnicate>());
100```
101
102If the model is non-copyable, we can still use this to pass some copyable values of the model state:
103
104```C++
105MySut sut;
106rc::state::check(
107    [] { return MyNonCopyableModel(); },
108    sut,
109    [](const MyNonCopyableModel &state) {
110      return rc::state::gen::execOneOfWithArgs<Put, Take, Frobnicate>()(
111          state.status(), state.remaining());
112    });
113```
114
115With the construction shown above, the commands would take the return types of `state.status()` and `state.remaining()` as parameters to their constructors.
116
117Some notes:
118
119- In the first example, we also have to assert that `item` exists in the model in our `apply` implementation since a generated command might be used for a different state, in particular during shrinking where the state may change because the commands prior in the sequence may be shrunk or removed. For more about this, see the [Stateful testing](state.md) section.
120- Discarding macros such as `RC_PRE` and `RC_DISCARD` can be used in the constructor of a command to immediately discard the command if it is not valid for the given state.
121
122### `Gen<std::shared_ptr<const Command>> gen::execOneOf<Ts...>(Model state)`
123
124_**Note**: This function is deprecated, use `rc::gen::execOneOfWithArgs` instead._
125
126Returns a generator that randomly constructs one of the commands in `Ts`. The constructor can make use of the `*`-operator just like in a property or in `gen::exec`. If the command has a constructor taking a model state, `state` will be passed to it on construction. Otherwise, the command is assumed to have a default constructor.
127
128### `Gen<Commands<Cmd>> gen::commands(Model initialState, GenFunc f)`
129
130### `Gen<Commands<Cmd>> gen::commands(MakeModel makeInitialState, GenFunc f)`
131
132Generates a valid sequence of commands for the given model state.
133
134`f` should be a function that takes a `Model` as an argument and returns a `Gen<std::shared_ptr<const Command<Model, Sut>>>`. This type looks complicated but it is essentially a generator of `shared_ptr`s to appropriate commands. The generator does not have to yield only valid commands since `RapidCheck` will simply try again if a command is not valid. However, performance will be better if fewer commands have to be discarded, of course. The easiest way to create such a function is to use the `gen::execOneOfWithArgs` function.
135
136There are two overloads of this function, one that takes the state as an immediate value and and another that takes a callable that returns the state.
137
138Since the System Under Test is not specified, the type of the generated commands must be explicitly specified. It cannot be deduced.
139
140## Utilities
141
142### `bool isValidCommand(Command command, const Model &state)`
143
144Returns `true` if the given command is valid for the given model state, `false` otherwise.
145