diff options
| author | Leitwolf11 | 2026-09-24 22:07:03 +0300 |
|---|---|---|
| committer | Leitwolf11 | 2026-09-24 22:07:03 +0300 |
| commit | 9ad804cedf4cc4a85ef89fe097f97a3b44654360 (patch) | |
| tree | f088e919776b22d19387377bdbec727daa2429c0 /src/Progmasoft/Catch3/Generators/Integer.hpp | |
| parent | 02f8b5593a15cdec8558256e6f40a0c7fb5862d6 (diff) | |
| download | catch3-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/Integer.hpp')
| -rw-r--r-- | src/Progmasoft/Catch3/Generators/Integer.hpp | 82 |
1 files changed, 82 insertions, 0 deletions
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 |