Hegel 0.11.4
Property-based testing for C++
Loading...
Searching...
No Matches
hegel::stateful Namespace Reference

Stateful (model-based) property testing. More...

Classes

class  VariablesGenerator
class  Pool
 A pool of previously generated values. A pool lets data flow from one rule to another, so a rule can act on a handle or identifier that an earlier rule produced rather than on a freshly drawn value. More...
class  Rule
 A rule is one possible action in a stateful test. More...
class  Invariant
 An invariant is a predicate that must hold at any point in the stateful test. They are evaluated on the initial state and after every valid step. The invariant function should throw when the invariant is violated. More...
struct  StateMachineParams
 Arguments for the StateMachine constructor. More...
class  StateMachine
 Base class for a state machine. Holds the state and declares the rules and the invariants that act on it. More...
struct  RunParams
 Options for run. More...
class  Generator
 The base class of all generators. More...
struct  IGenerator
 Base interface for generators. More...

Functions

Variable pools
template<typename T>
Generator< T > values_consumed (Pool< T > &p)
 Returns a value from the pool and removes it.
template<typename T>
Generator< T > values_reusable (Pool< T > &p)
 Returns a value from the pool without removing it.
template<typename M>
void run (M &machine, TestCase &tc, const RunParams &params={})
 Executes a stateful test by repeatedly applying randomly chosen rules from machine to it and checking machine's invariants before the first step and after every valid step. Rules mutate machine in place. Raises std::invalid_argument if the machine declares no rules.

Detailed Description

Stateful (model-based) property testing.

A stateful test exercises a system through a sequence of randomly chosen actions ("rules") applied to a state machine. Derive a machine from StateMachine and define its rules(). Each Rule is a name and a step function that performs one application of the rule, drawing any arguments it needs from the test case and mutating the machine. Invariants are predicates on the machine evaluated before any step is run and after every successful step. An invariant must throw when violated.

To run a state machine, pass an instance to run inside a hegel::test. Examples in this documentation assume the alias namespace gs = hegel::generators;.

Example: an integer stack.

struct IntegerStack
: hegel::stateful::StateMachine<IntegerStack, std::vector<int>> {
IntegerStack() : StateMachine({.initial_state = {}}) {}
std::vector<hegel::stateful::Rule<IntegerStack>> rules() {
return {
hegel::stateful::Rule<IntegerStack>(
"push", [](hegel::TestCase& tc, IntegerStack& m) {
m.state.push_back(tc.draw(gs::integers<int>(
{.min_value = 0, .max_value = 100})));
}),
hegel::stateful::Rule<IntegerStack>(
"pop", [](hegel::TestCase& tc, IntegerStack& m) {
tc.assume(!m.state.empty());
m.state.pop_back();
}),
};
}
};
HEGEL_TEST(stack_operations)(hegel::TestCase& tc) {
IntegerStack machine;
hegel::stateful::run(machine, tc);
}
void assume(bool condition) const
Reject the current test case if condition is false.
T draw(const generators::Generator< T > &gen) const
Draw a random value from a generator.
Definition core.h:264
Base class for a state machine. Holds the state and declares the rules and the invariants that act on...
Definition stateful.h:406
#define HEGEL_TEST(name,...)
Define a Hegel property test.
Definition hegel.h:575
void run(M &machine, TestCase &tc, const RunParams &params={})
Executes a stateful test by repeatedly applying randomly chosen rules from machine to it and checking...
Definition stateful.h:508

Function Documentation

◆ run()

template<typename M>
void hegel::stateful::run ( M & machine,
TestCase & tc,
const RunParams & params = {} )

Executes a stateful test by repeatedly applying randomly chosen rules from machine to it and checking machine's invariants before the first step and after every valid step. Rules mutate machine in place. Raises std::invalid_argument if the machine declares no rules.

On a failing replay, each applied rule prints as "Step N: <name>". A violated invariant prints "Invariant <name> violated after step M" or "Invariant <name> violated in the initial state".

Step 1: add
Step 2: add
Invariant nonneg violated after step 2
An invariant is a predicate that must hold at any point in the stateful test. They are evaluated on t...
Definition stateful.h:329
Template Parameters
MThe state-machine type, deriving from StateMachine
Parameters
machineThe state machine, initialized by the caller and mutated by its rules
tcThe test case object
paramsOptions for the run. See RunParams.

◆ values_consumed()

template<typename T>
Generator< T > hegel::stateful::values_consumed ( Pool< T > & p)

Returns a value from the pool and removes it.

HEGEL_TEST(pool_round_trip)(hegel::TestCase& tc) {
auto original_set = tc.draw(
"original_set", gs::sets(gs::integers<int>(), {.max_size =
10}));
for (int num : original_set) {
pool.add(num);
}
std::set<int> returned_set;
for (int i = 0; i < original_set.size(); i++) {
returned_set.insert(
}
assert(original_set == returned_set);
}
Handle to the currently-executing test case.
Definition test_case.h:40
A pool of previously generated values. A pool lets data flow from one rule to another,...
Definition stateful.h:122
Generator< T > values_consumed(Pool< T > &p)
Returns a value from the pool and removes it.
Definition stateful.h:242
Template Parameters
TElement type
Parameters
pThe pool to draw from
Returns
An element of the pool

◆ values_reusable()

template<typename T>
Generator< T > hegel::stateful::values_reusable ( Pool< T > & p)

Returns a value from the pool without removing it.

HEGEL_TEST(pool_reuse)(hegel::TestCase& tc) {
auto sz = tc.draw("sz", gs::integers<uint8_t>());
auto original_set = tc.draw(
"original_set", gs::sets(gs::integers<int>(), {.max_size =
sz}));
for (int num : original_set) {
pool.add(num);
}
for (int i = 0; i < original_set.size(); i++) {
}
assert(pool.size() == original_set.size());
}
Generator< T > values_reusable(Pool< T > &p)
Returns a value from the pool without removing it.
Definition stateful.h:273
Template Parameters
TElement type
Parameters
pThe pool to draw from
Returns
An element of the pool