diff options
| author | Leitwolf11 | 2026-10-02 03:27:05 +0300 |
|---|---|---|
| committer | Leitwolf11 | 2026-10-02 03:27:05 +0300 |
| commit | 5d55a3226360fae1eaa5ef91908b0fa7d7d07234 (patch) | |
| tree | 61e94c3bd1684b4caa256bc34e380c272b67cdb6 /src/Progmasoft/Catch3/Generators/Element.hpp | |
| parent | febb5b1e244174da0985b9994f8d5ed1676950e8 (diff) | |
| download | catch3-feature/property-combinators.tar.gz | |
Add composite property generators, single-trial replay and stable counterexample printingfeature/property-combinators
Property tests could only generate one integer or Boolean. This adds the
composite strategies the documentation listed as missing, without changing
any Catch2 file or the existing Progmasoft API.
Generators:
- Tuple(generators...) draws components left to right and shrinks one
component at a time, which is how a property receives several arguments.
- Vector(element, minimumSize, maximumSize) and Text(alphabet,
minimumLength, maximumLength) share one ordered shrink: shortest allowed
prefix, the two halves, single removals, then single element
simplifications. A shrunk value never falls below its minimum, each step
offers at most 256 candidates, and a size limit above 1,048,576 is
rejected.
- Element(values) picks from a fixed list and shrinks toward earlier
entries.
Runner:
- PropertyOptions::ReplayTrialSeed runs exactly one trial with a reported
replay seed, including its shrinking, so a failure from a log can be
reproduced without rerunning earlier trials. The report now ends with the
line that names this option and the seed.
- Counterexamples of tuples, pairs and vectors are printed element by
element instead of relying on Catch2's optional string makers, so the
report does not depend on configuration macros or include order.
The headers still compile for clients built without language exceptions.
Thirteen new test cases cover bounds, determinism, shrink order, candidate
limits, minimized counterexamples, replay and invalid configurations, and
every build description (Bazel, CMake, Meson, Xmake, Premake) lists the new
headers and test file.
Diffstat (limited to 'src/Progmasoft/Catch3/Generators/Element.hpp')
| -rw-r--r-- | src/Progmasoft/Catch3/Generators/Element.hpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/Progmasoft/Catch3/Generators/Element.hpp b/src/Progmasoft/Catch3/Generators/Element.hpp new file mode 100644 index 00000000..087b6355 --- /dev/null +++ b/src/Progmasoft/Catch3/Generators/Element.hpp @@ -0,0 +1,63 @@ +// Copyright (c) 2026 Progmasoft. +// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-1.1 +#pragma once + +#include <Progmasoft/Catch3/Generator.hpp> +#include <algorithm> +#include <concepts> +#include <cstddef> +#include <initializer_list> +#include <iterator> +#include <memory> +#include <utility> +#include <vector> + +namespace Progmasoft::Catch3 +{ + + /// Picks uniformly from a fixed, non-empty list of values. + /// + /// The list order is the simplicity order: a value shrinks to the values + /// listed before it, earliest first, so place the simplest case first. + /// A value that is not in the list has no candidates. + template<typename ValueType> + requires std::equality_comparable<ValueType> + [[nodiscard]] Generator<ValueType> + Element(std::vector<ValueType> values) + { + if (values.empty()) + { + Detail::RejectInvalidArgument( + "Element requires at least one value"); + } + + // Both callbacks share one immutable copy of the list. + const auto shared + = std::make_shared<const std::vector<ValueType>>(std::move(values)); + return MakeGenerator<ValueType>( + [shared](Random &random) { + const std::size_t index + = random.Between(std::size_t{ 0 }, shared->size() - 1); + return static_cast<ValueType>((*shared)[index]); + }, + [shared](const ValueType &value) { + const auto found + = std::find(shared->begin(), shared->end(), value); + if (found == shared->end()) + { + return std::vector<ValueType>{}; + } + return std::vector<ValueType>(shared->begin(), found); + }); + } + + /// Convenience overload for a literal list of values. + template<typename ValueType> + requires std::equality_comparable<ValueType> + [[nodiscard]] Generator<ValueType> + Element(std::initializer_list<ValueType> values) + { + return Element(std::vector<ValueType>(values)); + } + +} // namespace Progmasoft::Catch3 |