Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/docs
diff options
context:
space:
mode:
authorLeitwolf2026-10-02 15:53:33 +0300
committerGitHub2026-10-02 15:53:33 +0300
commit00bd15ded1dd732472156aece844e7696454bd3a (patch)
tree61e94c3bd1684b4caa256bc34e380c272b67cdb6 /docs
parentfebb5b1e244174da0985b9994f8d5ed1676950e8 (diff)
parent5d55a3226360fae1eaa5ef91908b0fa7d7d07234 (diff)
downloadcatch3-00bd15ded1dd732472156aece844e7696454bd3a.tar.gz
Merge pull request #1 from Progmasoft/feature/property-combinators
Add composite property generators, single-trial replay and stable counterexample printing
Diffstat (limited to 'docs')
-rw-r--r--docs/progmasoft-catch3.md66
-rw-r--r--docs/why-catch3.md2
2 files changed, 62 insertions, 6 deletions
diff --git a/docs/progmasoft-catch3.md b/docs/progmasoft-catch3.md
index 43a73f03..55114f32 100644
--- a/docs/progmasoft-catch3.md
+++ b/docs/progmasoft-catch3.md
@@ -33,7 +33,10 @@ The current property API is split into these headers:
bounded sampling, inclusive integer ranges, and per-trial seed derivation.
- `<Progmasoft/Catch3/Generator.hpp>`: user-defined generation/shrinking pair.
- `<Progmasoft/Catch3/Generators/Integer.hpp>` and `Boolean.hpp`: built-in
- strategies with deterministic shrink candidates.
+ scalar strategies with deterministic shrink candidates.
+- `<Progmasoft/Catch3/Generators/Vector.hpp>`, `Tuple.hpp`, `Element.hpp` and
+ `Text.hpp`: composite strategies described under
+ [Composite generators](#composite-generators).
- `<Progmasoft/Catch3/Property.hpp>`: trial execution and structured results.
- `<Progmasoft/Catch3/Assertions.hpp>`: `CATCH3_CHECK_PROPERTY`, which reports
the failing trial, replay seed, reason, and minimized counterexample through
@@ -53,10 +56,63 @@ minimal value. A false predicate or an exception from the predicate fails the
property. Exceptions from generation or shrinking are reported as execution
errors, distinct from an ordinary failing property.
-The API currently accepts one generated value per property. Tuple strategies,
-state-machine commands, parallel trials, and adaptive shrinking are deliberately
-not implied by this first module; they need their own deterministic contracts and
-tests before being added.
+A failing report ends with the line
+`replay: set PropertyOptions::ReplayTrialSeed to <seed>`. Setting that option
+runs exactly one trial with the given seed, including its shrinking, and
+ignores `Seed` and `Trials`; the reported trial number is then 1. This
+reproduces a failure from a CI log without rerunning the trials before it.
+
+```cpp
+Progmasoft::Catch3::PropertyOptions{ .ReplayTrialSeed = 1234567890123456789ULL }
+```
+
+### Composite generators
+
+A property still receives one generated value. Several arguments are passed
+as one tuple:
+
+```cpp
+using namespace Progmasoft::Catch3;
+
+CATCH3_CHECK_PROPERTY(
+ Tuple(Vector(Integer<int>(0, 100), 0, 20), Text("abc", 1, 8)),
+ [](const std::tuple<std::vector<int>, std::string> &input) {
+ return Accepts(std::get<0>(input), std::get<1>(input));
+ },
+ PropertyOptions{ .Trials = 500 });
+```
+
+- `Tuple(generators...)` draws its components strictly left to right from the
+ trial's random source and shrinks one component at a time: every candidate
+ of the first component, then every candidate of the second, and so on.
+- `Vector(element, minimumSize, maximumSize)` draws a length in the inclusive
+ range and then the elements in index order. `Text(alphabet, minimumLength,
+ maximumLength)` does the same for byte strings over the given alphabet;
+ `PrintableAscii()` is the default alphabet. Both shrink in a fixed order:
+ the shortest allowed prefix, the first and second half, the value with one
+ element removed, and finally the value with one element simplified. A
+ shrunk value is never shorter than its minimum, each step offers at most
+ 256 candidates, and a size limit above 1,048,576 elements is rejected.
+- `Element(values)` picks uniformly from a fixed non-empty list. The list
+ order is the simplicity order: a value shrinks to the values listed before
+ it. `Text` treats its alphabet the same way, so put the simplest value or
+ character first.
+
+Counterexamples of tuples, pairs and vectors are printed element by element,
+for example `{ 7, { true, false }, "text" }`. This does not depend on Catch2's
+optional tuple or range string makers, so the report is the same whatever
+configuration macros a client defines. Scalars still use `Catch::StringMaker`,
+including user specializations.
+
+Invalid factory arguments, such as an empty alphabet or a minimum above its
+maximum, throw `std::invalid_argument`; a client built without exceptions
+gets the message on standard error followed by `std::abort`.
+
+State-machine commands, parallel trials, mapped or filtered generators, and
+adaptive shrinking are deliberately not implied by this module; they need
+their own deterministic contracts and tests before being added. Shrinking a
+composite value is greedy and local like scalar shrinking: it finds a small
+counterexample, not a provably smallest one.
## Snapshots
diff --git a/docs/why-catch3.md b/docs/why-catch3.md
index 30dd5159..7fbeef44 100644
--- a/docs/why-catch3.md
+++ b/docs/why-catch3.md
@@ -25,7 +25,7 @@ Catch2 runner.
The current property runner handles one generated value per property. Shrinking
is deterministic and bounded, but greedy rather than globally minimal. There is
-not yet built-in support for state-machine properties, generated tuples,
+not yet built-in support for state-machine properties, mapped or filtered generators,
discard/classification policies, parallel execution, or a standalone Catch3
runner. Those features are not implied by the initial API.