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

summaryrefslogtreecommitdiffhomepage
path: root/src/Progmasoft/Catch3/Generators
diff options
context:
space:
mode:
authorLeitwolf112026-09-24 22:07:03 +0300
committerLeitwolf112026-09-24 22:07:03 +0300
commit9ad804cedf4cc4a85ef89fe097f97a3b44654360 (patch)
treef088e919776b22d19387377bdbec727daa2429c0 /src/Progmasoft/Catch3/Generators
parent02f8b5593a15cdec8558256e6f40a0c7fb5862d6 (diff)
downloadcatch3-0.1.0.tar.gz
Add Progmasoft Catch3 property testing and build support0.1.0
Introduce deterministic property execution, built-in generators, shrinking, replayable seeds, and a separate Progmasoft-owned header API while preserving Catch2 compatibility targets and the C++14 engine baseline. Add Bazel, Meson, Xmake, and Premake integration and tests alongside the existing CMake build. Replace Linux-only workflow coverage with Windows and macOS jobs and document the Catch2/Catch3 distinction.
Diffstat (limited to 'src/Progmasoft/Catch3/Generators')
-rw-r--r--src/Progmasoft/Catch3/Generators/Boolean.hpp18
-rw-r--r--src/Progmasoft/Catch3/Generators/Integer.hpp82
2 files changed, 100 insertions, 0 deletions
diff --git a/src/Progmasoft/Catch3/Generators/Boolean.hpp b/src/Progmasoft/Catch3/Generators/Boolean.hpp
new file mode 100644
index 00000000..3f881927
--- /dev/null
+++ b/src/Progmasoft/Catch3/Generators/Boolean.hpp
@@ -0,0 +1,18 @@
+// Copyright (c) 2026 Progmasoft.
+// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-1.1
+#pragma once
+
+#include <Progmasoft/Catch3/Generator.hpp>
+
+namespace Progmasoft::Catch3 {
+
+ /// Generates booleans and shrinks true to the simplest value, false.
+ [[nodiscard]] inline Generator<bool> Boolean() {
+ return MakeGenerator<bool>(
+ []( Random& random ) { return ( random.Next() & 1U ) != 0; },
+ []( const bool& value ) {
+ return value ? std::vector<bool>{ false } : std::vector<bool>{};
+ } );
+ }
+
+} // namespace Progmasoft::Catch3
diff --git a/src/Progmasoft/Catch3/Generators/Integer.hpp b/src/Progmasoft/Catch3/Generators/Integer.hpp
new file mode 100644
index 00000000..2a50525e
--- /dev/null
+++ b/src/Progmasoft/Catch3/Generators/Integer.hpp
@@ -0,0 +1,82 @@
+// 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 <limits>
+#include <type_traits>
+
+namespace Progmasoft::Catch3 {
+ namespace Detail {
+
+ template <std::integral IntegerType>
+ requires( !std::same_as<IntegerType, bool> )
+ [[nodiscard]] std::vector<IntegerType> ShrinkInteger(
+ IntegerType value, IntegerType minimum, IntegerType maximum ) {
+ std::vector<IntegerType> candidates;
+ const auto addCandidate = [&]( IntegerType candidate ) {
+ if ( candidate < minimum || candidate > maximum ||
+ candidate == value ||
+ std::ranges::find( candidates, candidate ) !=
+ candidates.end() ) {
+ return;
+ }
+ candidates.push_back( candidate );
+ };
+
+ if ( value == 0 ) { return candidates; }
+
+ // First try the conventional simplest value, then halve toward it.
+ // The adjacent value at the end lets the runner find boundary
+ // counterexamples (for example, the first failing integer in a
+ // threshold property).
+ if ( minimum <= 0 && maximum >= 0 ) { addCandidate( 0 ); }
+
+ IntegerType smaller = value;
+ while ( smaller != 0 ) {
+ smaller = static_cast<IntegerType>( smaller / 2 );
+ if ( smaller == 0 ) { break; }
+ addCandidate( smaller );
+ }
+
+ if ( value > 0 ) {
+ if ( value > minimum ) {
+ addCandidate( static_cast<IntegerType>( value - 1 ) );
+ }
+ if ( minimum > 0 ) { addCandidate( minimum ); }
+ } else {
+ if ( value < maximum ) {
+ addCandidate( static_cast<IntegerType>( value + 1 ) );
+ }
+ if ( maximum < 0 ) { addCandidate( maximum ); }
+ }
+ return candidates;
+ }
+
+ } // namespace Detail
+
+ /// Generates integers over the inclusive range and shrinks toward simple
+ /// values.
+ template <std::integral IntegerType>
+ requires( !std::same_as<IntegerType, bool> )
+ [[nodiscard]] Generator<IntegerType> Integer(
+ IntegerType minimum = std::numeric_limits<IntegerType>::lowest(),
+ IntegerType maximum = std::numeric_limits<IntegerType>::max() ) {
+ if ( minimum > maximum ) {
+ throw std::invalid_argument(
+ "Integer requires minimum <= maximum" );
+ }
+
+ return MakeGenerator<IntegerType>(
+ [minimum, maximum]( Random& random ) {
+ return random.Between( minimum, maximum );
+ },
+ [minimum, maximum]( const IntegerType& value ) {
+ return Detail::ShrinkInteger( value, minimum, maximum );
+ } );
+ }
+
+} // namespace Progmasoft::Catch3