Generators now keep track of the index of current element

This might become potentially useful in the future, when we want
to provide the ability to forward jump generators, to be able to
simply reproduce specific input to a test.

I am not yet sure how it would work, but the basic idea is that
it could be similar to the `-c` switch for selecting specific
`SECTION` in a test case.
This commit is contained in:
Martin Hořeňovský 2022-05-16 11:56:11 +02:00
parent 07bec74096
commit af8b54ecd5
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
4 changed files with 43 additions and 7 deletions

View File

@ -64,7 +64,7 @@ namespace Detail {
return m_generator->get(); return m_generator->get();
} }
bool next() { bool next() {
return m_generator->next(); return m_generator->countedNext();
} }
}; };

View File

@ -14,6 +14,17 @@ namespace Catch {
namespace Generators { namespace Generators {
class GeneratorUntypedBase { 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: public:
GeneratorUntypedBase() = default; GeneratorUntypedBase() = default;
// Generation of copy ops is deprecated (and Clang will complain) // Generation of copy ops is deprecated (and Clang will complain)
@ -23,11 +34,25 @@ namespace Catch {
virtual ~GeneratorUntypedBase(); // = default; virtual ~GeneratorUntypedBase(); // = default;
// Attempts to move the generator to the next element /**
// * Attempts to move the generator to the next element
// Returns true iff the move succeeded (and a valid element *
// can be retrieved). * Serves as a non-virtual interface to `next`, so that the
virtual bool next() = 0; * 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<GeneratorUntypedBase>; using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;

View File

@ -143,7 +143,7 @@ namespace Catch {
// this generator is still waiting for any child to start. // this generator is still waiting for any child to start.
if ( should_wait_for_child || if ( should_wait_for_child ||
( m_runState == CompletedSuccessfully && ( m_runState == CompletedSuccessfully &&
m_generator->next() ) ) { m_generator->countedNext() ) ) {
m_children.clear(); m_children.clear();
m_runState = Executing; m_runState = Executing;
} }

View File

@ -413,3 +413,14 @@ TEST_CASE("GENERATE decays arrays", "[generators][compilation][approvals]") {
auto str = GENERATE("abc", "def", "gh"); auto str = GENERATE("abc", "def", "gh");
STATIC_REQUIRE(std::is_same<decltype(str), const char*>::value); STATIC_REQUIRE(std::is_same<decltype(str), const char*>::value);
} }
TEST_CASE("Generators count returned elements", "[generators][approvals]") {
auto generator = Catch::Generators::FixedValuesGenerator<int>( { 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 );
}