diff --git a/src/catch2/generators/catch_generators.hpp b/src/catch2/generators/catch_generators.hpp index acfdb7dc..24af63d6 100644 --- a/src/catch2/generators/catch_generators.hpp +++ b/src/catch2/generators/catch_generators.hpp @@ -64,7 +64,7 @@ namespace Detail { return m_generator->get(); } bool next() { - return m_generator->next(); + return m_generator->countedNext(); } }; diff --git a/src/catch2/interfaces/catch_interfaces_generatortracker.hpp b/src/catch2/interfaces/catch_interfaces_generatortracker.hpp index fa475e28..2efc4a58 100644 --- a/src/catch2/interfaces/catch_interfaces_generatortracker.hpp +++ b/src/catch2/interfaces/catch_interfaces_generatortracker.hpp @@ -14,6 +14,17 @@ namespace Catch { namespace Generators { class GeneratorUntypedBase { + // Counts based on `next` returning true + std::size_t m_currentElementIndex = 0; + + /** + * Attempts to move the generator to the next element + * + * Returns true iff the move succeeded (and a valid element + * can be retrieved). + */ + virtual bool next() = 0; + public: GeneratorUntypedBase() = default; // Generation of copy ops is deprecated (and Clang will complain) @@ -23,11 +34,25 @@ namespace Catch { virtual ~GeneratorUntypedBase(); // = default; - // Attempts to move the generator to the next element - // - // Returns true iff the move succeeded (and a valid element - // can be retrieved). - virtual bool next() = 0; + /** + * Attempts to move the generator to the next element + * + * Serves as a non-virtual interface to `next`, so that the + * top level interface can provide sanity checking and shared + * features. + * + * As with `next`, returns true iff the move succeeded and + * the generator has new valid element to provide. + */ + bool countedNext() { + auto ret = next(); + if ( ret ) { + ++m_currentElementIndex; + } + return ret; + } + + std::size_t currentElementIndex() const { return m_currentElementIndex; } }; using GeneratorBasePtr = Catch::Detail::unique_ptr; diff --git a/src/catch2/internal/catch_run_context.cpp b/src/catch2/internal/catch_run_context.cpp index 872783c6..7da8f714 100644 --- a/src/catch2/internal/catch_run_context.cpp +++ b/src/catch2/internal/catch_run_context.cpp @@ -143,7 +143,7 @@ namespace Catch { // this generator is still waiting for any child to start. if ( should_wait_for_child || ( m_runState == CompletedSuccessfully && - m_generator->next() ) ) { + m_generator->countedNext() ) ) { m_children.clear(); m_runState = Executing; } diff --git a/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp b/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp index 2aad184d..42d80741 100644 --- a/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp @@ -413,3 +413,14 @@ TEST_CASE("GENERATE decays arrays", "[generators][compilation][approvals]") { auto str = GENERATE("abc", "def", "gh"); STATIC_REQUIRE(std::is_same::value); } + +TEST_CASE("Generators count returned elements", "[generators][approvals]") { + auto generator = Catch::Generators::FixedValuesGenerator( { 1, 2, 3 } ); + REQUIRE( generator.currentElementIndex() == 0 ); + REQUIRE( generator.countedNext() ); + REQUIRE( generator.currentElementIndex() == 1 ); + REQUIRE( generator.countedNext() ); + REQUIRE( generator.currentElementIndex() == 2 ); + REQUIRE_FALSE( generator.countedNext() ); + REQUIRE( generator.currentElementIndex() == 2 ); +}