From 9eca713a1f4555b3095564781d77654958ee3dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 6 Oct 2025 11:47:38 +0200 Subject: [PATCH] Add option to skip forward to the generator interface --- docs/generators.md | 14 ++++ examples/300-Gen-OwnGenerator.cpp | 16 ++++ .../catch_interfaces_generatortracker.cpp | 27 +++++++ .../catch_interfaces_generatortracker.hpp | 16 ++++ .../Baselines/automake.sw.approved.txt | 1 + .../Baselines/automake.sw.multi.approved.txt | 1 + .../Baselines/compact.sw.approved.txt | 13 ++- .../Baselines/compact.sw.multi.approved.txt | 13 ++- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 51 +++++++++++- .../Baselines/console.sw.multi.approved.txt | 51 +++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 3 +- .../Baselines/junit.sw.multi.approved.txt | 3 +- .../Baselines/sonarqube.sw.approved.txt | 1 + .../Baselines/sonarqube.sw.multi.approved.txt | 1 + tests/SelfTest/Baselines/tap.sw.approved.txt | 20 ++++- .../Baselines/tap.sw.multi.approved.txt | 20 ++++- .../Baselines/teamcity.sw.approved.txt | 2 + .../Baselines/teamcity.sw.multi.approved.txt | 2 + tests/SelfTest/Baselines/xml.sw.approved.txt | 79 ++++++++++++++++++- .../Baselines/xml.sw.multi.approved.txt | 79 ++++++++++++++++++- .../GeneratorsImpl.tests.cpp | 39 +++++++++ 22 files changed, 438 insertions(+), 18 deletions(-) diff --git a/docs/generators.md b/docs/generators.md index b01ec906..f45eac06 100644 --- a/docs/generators.md +++ b/docs/generators.md @@ -264,9 +264,23 @@ struct IGenerator : GeneratorUntypedBase { // Returns user-friendly string showing the current generator element // Does not have to be overridden, IGenerator provides default implementation virtual std::string stringifyImpl() const; + + /** + * Customization point for `skipToNthElement` + * + * Does not have to be overridden, there is a default implementation. + * Can be overridden for better performance. + * + * If there are not enough elements, shall throw an error. + * + * Going backwards is not supported. + */ + virtual void skipToNthElementImpl( std::size_t n ); }; ``` +> `skipToNthElementImpl` was added in Catch2 vX.Y.Z + However, to be able to use your custom generator inside `GENERATE`, it will need to be wrapped inside a `GeneratorWrapper`. `GeneratorWrapper` is a value wrapper around a diff --git a/examples/300-Gen-OwnGenerator.cpp b/examples/300-Gen-OwnGenerator.cpp index 9cb02e39..b7f9d5da 100644 --- a/examples/300-Gen-OwnGenerator.cpp +++ b/examples/300-Gen-OwnGenerator.cpp @@ -39,6 +39,22 @@ public: current_number = m_dist(m_rand); return true; } + + // Note: this improves the performance only a bit, but it is here + // to show how you can override the skip functionality. + void skipToNthElementImpl( std::size_t n ) override { + auto current_index = currentElementIndex(); + assert(current_index <= n); + // We cannot jump forward the underlying generator directly, + // because we do not know how many bits each distributed number + // would consume to be generated. + for (; current_index < n; ++current_index) { + (void)m_dist(m_rand); + } + + // We do not have to touch the current element index; it is handled + // by the base class. + } }; // Avoids -Wweak-vtables diff --git a/src/catch2/interfaces/catch_interfaces_generatortracker.cpp b/src/catch2/interfaces/catch_interfaces_generatortracker.cpp index e9fa5dda..4ac23ddb 100644 --- a/src/catch2/interfaces/catch_interfaces_generatortracker.cpp +++ b/src/catch2/interfaces/catch_interfaces_generatortracker.cpp @@ -7,6 +7,8 @@ // SPDX-License-Identifier: BSL-1.0 #include +#include + #include namespace Catch { @@ -21,6 +23,31 @@ namespace Catch { return ret; } + void GeneratorUntypedBase::skipToNthElementImpl( std::size_t n ) { + for ( size_t i = m_currentElementIndex; i < n; ++i ) { + bool isValid = next(); + if ( !isValid ) { + Detail::throw_generator_exception( + "Coud not jump to Nth element: not enough elements" ); + } + } + } + + void GeneratorUntypedBase::skipToNthElement( std::size_t n ) { + if ( n < m_currentElementIndex ) { + Detail::throw_generator_exception( + "Tried to jump generator backwards" ); + } + if ( n == m_currentElementIndex ) { return; } + + skipToNthElementImpl(n); + // Fixup tracking after moving the generator forward + // * Ensure that the correct element index is set after skipping + // * Invalidate cache + m_currentElementIndex = n; + m_stringReprCache.clear(); + } + StringRef GeneratorUntypedBase::currentElementAsString() const { if ( m_stringReprCache.empty() ) { m_stringReprCache = stringifyImpl(); diff --git a/src/catch2/interfaces/catch_interfaces_generatortracker.hpp b/src/catch2/interfaces/catch_interfaces_generatortracker.hpp index d70cb593..eb3871bc 100644 --- a/src/catch2/interfaces/catch_interfaces_generatortracker.hpp +++ b/src/catch2/interfaces/catch_interfaces_generatortracker.hpp @@ -35,6 +35,15 @@ namespace Catch { //! Customization point for `currentElementAsString` virtual std::string stringifyImpl() const = 0; + /** + * Customization point for skipping to the n-th element + * + * Defaults to successively calling `countedNext`. If there + * are not enough elements to reach the nth one, will throw + * an error. + */ + virtual void skipToNthElementImpl( std::size_t n ); + public: GeneratorUntypedBase() = default; // Generation of copy ops is deprecated (and Clang will complain) @@ -58,6 +67,13 @@ namespace Catch { std::size_t currentElementIndex() const { return m_currentElementIndex; } + /** + * Moves the generator forward **to** the n-th element + * + * Cannot move backwards. Can stay in place. + */ + void skipToNthElement( std::size_t n ); + /** * Returns generator's current element as user-friendly string. * diff --git a/tests/SelfTest/Baselines/automake.sw.approved.txt b/tests/SelfTest/Baselines/automake.sw.approved.txt index 606d7ac3..cf504a78 100644 --- a/tests/SelfTest/Baselines/automake.sw.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.approved.txt @@ -170,6 +170,7 @@ Nor would this :test-result: PASS GENERATE can combine literals and generators :test-result: PASS Generators -- adapters :test-result: PASS Generators -- simple +:test-result: PASS Generators can be skipped forward :test-result: PASS Generators internals :test-result: PASS Greater-than inequalities with different epsilons :test-result: PASS Hashers with different seed produce different hash with same test case diff --git a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt index fd146fe7..2b4b1ba7 100644 --- a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt @@ -168,6 +168,7 @@ :test-result: PASS GENERATE can combine literals and generators :test-result: PASS Generators -- adapters :test-result: PASS Generators -- simple +:test-result: PASS Generators can be skipped forward :test-result: PASS Generators internals :test-result: PASS Greater-than inequalities with different epsilons :test-result: PASS Hashers with different seed produce different hash with same test case diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index a366d006..8f7f2bf9 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -801,6 +801,15 @@ Generators.tests.cpp:: passed: j < i for: -1 < 3 Generators.tests.cpp:: passed: 4u * i > str.size() for: 12 > 1 Generators.tests.cpp:: passed: 4u * i > str.size() for: 12 > 2 Generators.tests.cpp:: passed: 4u * i > str.size() for: 12 > 3 +GeneratorsImpl.tests.cpp:: passed: generator.currentElementIndex() == 0 for: 0 == 0 +GeneratorsImpl.tests.cpp:: passed: generator.currentElementIndex() == 3 for: 3 == 3 +GeneratorsImpl.tests.cpp:: passed: generator.get() == 3 for: 3 == 3 +GeneratorsImpl.tests.cpp:: passed: generator.currentElementIndex() == 3 for: 3 == 3 +GeneratorsImpl.tests.cpp:: passed: generator.get() == 3 for: 3 == 3 +GeneratorsImpl.tests.cpp:: passed: generator.currentElementIndex() == 5 for: 5 == 5 +GeneratorsImpl.tests.cpp:: passed: generator.get() == 5 for: 5 == 5 +GeneratorsImpl.tests.cpp:: passed: generator.skipToNthElement( 3 ) +GeneratorsImpl.tests.cpp:: passed: generator.skipToNthElement( 6 ) GeneratorsImpl.tests.cpp:: passed: gen.get() == 123 for: 123 == 123 GeneratorsImpl.tests.cpp:: passed: !(gen.next()) for: !false GeneratorsImpl.tests.cpp:: passed: gen.get() == 1 for: 1 == 1 @@ -2915,7 +2924,7 @@ InternalBenchmark.tests.cpp:: passed: med == 18. for: 18.0 == 18.0 InternalBenchmark.tests.cpp:: passed: q3 == 23. for: 23.0 == 23.0 Misc.tests.cpp:: passed: Misc.tests.cpp:: passed: -test cases: 439 | 319 passed | 96 failed | 6 skipped | 18 failed as expected -assertions: 2331 | 2130 passed | 158 failed | 43 failed as expected +test cases: 440 | 320 passed | 96 failed | 6 skipped | 18 failed as expected +assertions: 2340 | 2139 passed | 158 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt index dab12a55..17cf066a 100644 --- a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt @@ -799,6 +799,15 @@ Generators.tests.cpp:: passed: j < i for: -1 < 3 Generators.tests.cpp:: passed: 4u * i > str.size() for: 12 > 1 Generators.tests.cpp:: passed: 4u * i > str.size() for: 12 > 2 Generators.tests.cpp:: passed: 4u * i > str.size() for: 12 > 3 +GeneratorsImpl.tests.cpp:: passed: generator.currentElementIndex() == 0 for: 0 == 0 +GeneratorsImpl.tests.cpp:: passed: generator.currentElementIndex() == 3 for: 3 == 3 +GeneratorsImpl.tests.cpp:: passed: generator.get() == 3 for: 3 == 3 +GeneratorsImpl.tests.cpp:: passed: generator.currentElementIndex() == 3 for: 3 == 3 +GeneratorsImpl.tests.cpp:: passed: generator.get() == 3 for: 3 == 3 +GeneratorsImpl.tests.cpp:: passed: generator.currentElementIndex() == 5 for: 5 == 5 +GeneratorsImpl.tests.cpp:: passed: generator.get() == 5 for: 5 == 5 +GeneratorsImpl.tests.cpp:: passed: generator.skipToNthElement( 3 ) +GeneratorsImpl.tests.cpp:: passed: generator.skipToNthElement( 6 ) GeneratorsImpl.tests.cpp:: passed: gen.get() == 123 for: 123 == 123 GeneratorsImpl.tests.cpp:: passed: !(gen.next()) for: !false GeneratorsImpl.tests.cpp:: passed: gen.get() == 1 for: 1 == 1 @@ -2904,7 +2913,7 @@ InternalBenchmark.tests.cpp:: passed: med == 18. for: 18.0 == 18.0 InternalBenchmark.tests.cpp:: passed: q3 == 23. for: 23.0 == 23.0 Misc.tests.cpp:: passed: Misc.tests.cpp:: passed: -test cases: 439 | 319 passed | 96 failed | 6 skipped | 18 failed as expected -assertions: 2331 | 2130 passed | 158 failed | 43 failed as expected +test cases: 440 | 320 passed | 96 failed | 6 skipped | 18 failed as expected +assertions: 2340 | 2139 passed | 158 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt index 48bcec18..02d7a3cb 100644 --- a/tests/SelfTest/Baselines/console.std.approved.txt +++ b/tests/SelfTest/Baselines/console.std.approved.txt @@ -1743,6 +1743,6 @@ due to unexpected exception with message: Why would you throw a std::string? =============================================================================== -test cases: 439 | 337 passed | 76 failed | 7 skipped | 19 failed as expected -assertions: 2309 | 2130 passed | 136 failed | 43 failed as expected +test cases: 440 | 338 passed | 76 failed | 7 skipped | 19 failed as expected +assertions: 2318 | 2139 passed | 136 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index eb9f7367..38578deb 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -5921,6 +5921,53 @@ Generators.tests.cpp:: PASSED: with expansion: 12 > 3 +------------------------------------------------------------------------------- +Generators can be skipped forward +------------------------------------------------------------------------------- +GeneratorsImpl.tests.cpp: +............................................................................... + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.currentElementIndex() == 0 ) +with expansion: + 0 == 0 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.currentElementIndex() == 3 ) +with expansion: + 3 == 3 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.get() == 3 ) +with expansion: + 3 == 3 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.currentElementIndex() == 3 ) +with expansion: + 3 == 3 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.get() == 3 ) +with expansion: + 3 == 3 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.currentElementIndex() == 5 ) +with expansion: + 5 == 5 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.get() == 5 ) +with expansion: + 5 == 5 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE_THROWS( generator.skipToNthElement( 3 ) ) + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE_THROWS( generator.skipToNthElement( 6 ) ) + ------------------------------------------------------------------------------- Generators internals Single value @@ -19542,6 +19589,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 439 | 319 passed | 96 failed | 6 skipped | 18 failed as expected -assertions: 2331 | 2130 passed | 158 failed | 43 failed as expected +test cases: 440 | 320 passed | 96 failed | 6 skipped | 18 failed as expected +assertions: 2340 | 2139 passed | 158 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.multi.approved.txt b/tests/SelfTest/Baselines/console.sw.multi.approved.txt index 4d0bd8f4..207697cf 100644 --- a/tests/SelfTest/Baselines/console.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.multi.approved.txt @@ -5919,6 +5919,53 @@ Generators.tests.cpp:: PASSED: with expansion: 12 > 3 +------------------------------------------------------------------------------- +Generators can be skipped forward +------------------------------------------------------------------------------- +GeneratorsImpl.tests.cpp: +............................................................................... + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.currentElementIndex() == 0 ) +with expansion: + 0 == 0 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.currentElementIndex() == 3 ) +with expansion: + 3 == 3 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.get() == 3 ) +with expansion: + 3 == 3 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.currentElementIndex() == 3 ) +with expansion: + 3 == 3 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.get() == 3 ) +with expansion: + 3 == 3 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.currentElementIndex() == 5 ) +with expansion: + 5 == 5 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( generator.get() == 5 ) +with expansion: + 5 == 5 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE_THROWS( generator.skipToNthElement( 3 ) ) + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE_THROWS( generator.skipToNthElement( 6 ) ) + ------------------------------------------------------------------------------- Generators internals Single value @@ -19531,6 +19578,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 439 | 319 passed | 96 failed | 6 skipped | 18 failed as expected -assertions: 2331 | 2130 passed | 158 failed | 43 failed as expected +test cases: 440 | 320 passed | 96 failed | 6 skipped | 18 failed as expected +assertions: 2340 | 2139 passed | 158 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index d08e4f81..beaf9cf8 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -849,6 +849,7 @@ at Message.tests.cpp: + diff --git a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt index 5d7dce1d..a69a4979 100644 --- a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt @@ -1,6 +1,6 @@ - + @@ -848,6 +848,7 @@ at Message.tests.cpp: + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index 2c5d4a90..60ce76cd 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -149,6 +149,7 @@ at AssertionHandler.tests.cpp: + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt index 9baa1c15..6811d003 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt @@ -148,6 +148,7 @@ at AssertionHandler.tests.cpp: + diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index 5804c06a..6d45b413 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -1458,6 +1458,24 @@ ok {test-number} - 4u * i > str.size() for: 12 > 1 ok {test-number} - 4u * i > str.size() for: 12 > 2 # Generators -- simple ok {test-number} - 4u * i > str.size() for: 12 > 3 +# Generators can be skipped forward +ok {test-number} - generator.currentElementIndex() == 0 for: 0 == 0 +# Generators can be skipped forward +ok {test-number} - generator.currentElementIndex() == 3 for: 3 == 3 +# Generators can be skipped forward +ok {test-number} - generator.get() == 3 for: 3 == 3 +# Generators can be skipped forward +ok {test-number} - generator.currentElementIndex() == 3 for: 3 == 3 +# Generators can be skipped forward +ok {test-number} - generator.get() == 3 for: 3 == 3 +# Generators can be skipped forward +ok {test-number} - generator.currentElementIndex() == 5 for: 5 == 5 +# Generators can be skipped forward +ok {test-number} - generator.get() == 5 for: 5 == 5 +# Generators can be skipped forward +ok {test-number} - generator.skipToNthElement( 3 ) +# Generators can be skipped forward +ok {test-number} - generator.skipToNthElement( 6 ) # Generators internals ok {test-number} - gen.get() == 123 for: 123 == 123 # Generators internals @@ -4681,5 +4699,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2343 +1..2352 diff --git a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt index 85e5a226..215243ac 100644 --- a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt @@ -1456,6 +1456,24 @@ ok {test-number} - 4u * i > str.size() for: 12 > 1 ok {test-number} - 4u * i > str.size() for: 12 > 2 # Generators -- simple ok {test-number} - 4u * i > str.size() for: 12 > 3 +# Generators can be skipped forward +ok {test-number} - generator.currentElementIndex() == 0 for: 0 == 0 +# Generators can be skipped forward +ok {test-number} - generator.currentElementIndex() == 3 for: 3 == 3 +# Generators can be skipped forward +ok {test-number} - generator.get() == 3 for: 3 == 3 +# Generators can be skipped forward +ok {test-number} - generator.currentElementIndex() == 3 for: 3 == 3 +# Generators can be skipped forward +ok {test-number} - generator.get() == 3 for: 3 == 3 +# Generators can be skipped forward +ok {test-number} - generator.currentElementIndex() == 5 for: 5 == 5 +# Generators can be skipped forward +ok {test-number} - generator.get() == 5 for: 5 == 5 +# Generators can be skipped forward +ok {test-number} - generator.skipToNthElement( 3 ) +# Generators can be skipped forward +ok {test-number} - generator.skipToNthElement( 6 ) # Generators internals ok {test-number} - gen.get() == 123 for: 123 == 123 # Generators internals @@ -4670,5 +4688,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2343 +1..2352 diff --git a/tests/SelfTest/Baselines/teamcity.sw.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.approved.txt index 6705806c..d460f1ff 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.approved.txt @@ -419,6 +419,8 @@ ##teamcity[testFinished name='Generators -- adapters' duration="{duration}"] ##teamcity[testStarted name='Generators -- simple'] ##teamcity[testFinished name='Generators -- simple' duration="{duration}"] +##teamcity[testStarted name='Generators can be skipped forward'] +##teamcity[testFinished name='Generators can be skipped forward' duration="{duration}"] ##teamcity[testStarted name='Generators internals'] ##teamcity[testFinished name='Generators internals' duration="{duration}"] ##teamcity[testStarted name='Greater-than inequalities with different epsilons'] diff --git a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt index 80d53df2..5eee54e5 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt @@ -419,6 +419,8 @@ ##teamcity[testFinished name='Generators -- adapters' duration="{duration}"] ##teamcity[testStarted name='Generators -- simple'] ##teamcity[testFinished name='Generators -- simple' duration="{duration}"] +##teamcity[testStarted name='Generators can be skipped forward'] +##teamcity[testFinished name='Generators can be skipped forward' duration="{duration}"] ##teamcity[testStarted name='Generators internals'] ##teamcity[testFinished name='Generators internals' duration="{duration}"] ##teamcity[testStarted name='Greater-than inequalities with different epsilons'] diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index b719f1a0..08900bfa 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -6735,6 +6735,81 @@ Approx( 1.30000000000000004 ) + + + + generator.currentElementIndex() == 0 + + + 0 == 0 + + + + + generator.currentElementIndex() == 3 + + + 3 == 3 + + + + + generator.get() == 3 + + + 3 == 3 + + + + + generator.currentElementIndex() == 3 + + + 3 == 3 + + + + + generator.get() == 3 + + + 3 == 3 + + + + + generator.currentElementIndex() == 5 + + + 5 == 5 + + + + + generator.get() == 5 + + + 5 == 5 + + + + + generator.skipToNthElement( 3 ) + + + generator.skipToNthElement( 3 ) + + + + + generator.skipToNthElement( 6 ) + + + generator.skipToNthElement( 6 ) + + + +
@@ -22612,6 +22687,6 @@ Approx( -1.95996398454005449 )
- - + + diff --git a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt index 051f9a82..c51ae00a 100644 --- a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt @@ -6735,6 +6735,81 @@ Approx( 1.30000000000000004 )
+ + + + generator.currentElementIndex() == 0 + + + 0 == 0 + + + + + generator.currentElementIndex() == 3 + + + 3 == 3 + + + + + generator.get() == 3 + + + 3 == 3 + + + + + generator.currentElementIndex() == 3 + + + 3 == 3 + + + + + generator.get() == 3 + + + 3 == 3 + + + + + generator.currentElementIndex() == 5 + + + 5 == 5 + + + + + generator.get() == 5 + + + 5 == 5 + + + + + generator.skipToNthElement( 3 ) + + + generator.skipToNthElement( 3 ) + + + + + generator.skipToNthElement( 6 ) + + + generator.skipToNthElement( 6 ) + + + +
@@ -22611,6 +22686,6 @@ Approx( -1.95996398454005449 )
- - + + diff --git a/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp b/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp index 0ba4ab43..0a2b17ea 100644 --- a/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp @@ -604,3 +604,42 @@ TEST_CASE( "ConcatGenerator", "[generators][concat]" ) { REQUIRE_FALSE( c.next() ); } } + +namespace { + // Test the default behaviour of skipping generators forward. We do + // not want to use pre-existing generator, because they will get + // specialized forward skip implementation. + class SkipTestGenerator : public Catch::Generators::IGenerator { + std::vector m_elements{ 0, 1, 2, 3, 4, 5 }; + size_t m_idx = 0; + public: + int const& get() const override { return m_elements[m_idx]; } + bool next() override { + ++m_idx; + return m_idx < m_elements.size(); + } + }; +} + +TEST_CASE( "Generators can be skipped forward", "[generators]" ) { + SkipTestGenerator generator; + REQUIRE( generator.currentElementIndex() == 0 ); + + generator.skipToNthElement( 3 ); + REQUIRE( generator.currentElementIndex() == 3 ); + REQUIRE( generator.get() == 3 ); + + // Try "skipping" to the same element. + generator.skipToNthElement( 3 ); + REQUIRE( generator.currentElementIndex() == 3 ); + REQUIRE( generator.get() == 3 ); + + generator.skipToNthElement( 5 ); + REQUIRE( generator.currentElementIndex() == 5 ); + REQUIRE( generator.get() == 5 ); + + // Backwards + REQUIRE_THROWS( generator.skipToNthElement( 3 ) ); + // Past the end + REQUIRE_THROWS( generator.skipToNthElement( 6 ) ); +}