mirror of
https://github.com/catchorg/Catch2.git
synced 2025-08-02 21:35:40 +02:00
Modify generator tracking to allow GENERATEs between SECTIONs
This means that code such as ```cpp TEST_CASE() { SECTION("first") { SUCCEED(); } auto _ = GENERATE(1, 2); SECTION("second") { SUCCEED(); } } ``` will run and report 3 assertions, 1 from section "first" and 2 from section "second". This also applies for greater and potentially more confusing nesting, but fundamentally it is up to the user to avoid overly complex and confusing nestings, just as with `SECTION`s. The old behaviour of `GENERATE` as first thing in a `TEST_CASE`, `GENERATE` not followed by a `SECTION`, etc etc should be unchanged. Closes #1938
This commit is contained in:
@@ -50,7 +50,7 @@ namespace Catch {
|
||||
currentTracker.addChild( tracker );
|
||||
}
|
||||
|
||||
if( !ctx.completedCycle() && !tracker->isComplete() ) {
|
||||
if( !tracker->isComplete() ) {
|
||||
tracker->open();
|
||||
}
|
||||
|
||||
@@ -64,8 +64,28 @@ namespace Catch {
|
||||
}
|
||||
void close() override {
|
||||
TrackerBase::close();
|
||||
// Generator interface only finds out if it has another item on atual move
|
||||
if (m_runState == CompletedSuccessfully && m_generator->next()) {
|
||||
// If a generator has a child (it is followed by a section)
|
||||
// and none of its children have started, then we must wait
|
||||
// until later to start consuming its values.
|
||||
// This catches cases where `GENERATE` is placed between two
|
||||
// `SECTION`s.
|
||||
// **The check for m_children.empty cannot be removed**.
|
||||
// doing so would break `GENERATE` _not_ followed by `SECTION`s.
|
||||
const bool should_wait_for_child =
|
||||
!m_children.empty() &&
|
||||
std::find_if( m_children.begin(),
|
||||
m_children.end(),
|
||||
[]( TestCaseTracking::ITrackerPtr tracker ) {
|
||||
return tracker->hasStarted();
|
||||
} ) == m_children.end();
|
||||
|
||||
// This check is a bit tricky, because m_generator->next()
|
||||
// has a side-effect, where it consumes generator's current
|
||||
// value, but we do not want to invoke the side-effect if
|
||||
// this generator is still waiting for any child to start.
|
||||
if ( should_wait_for_child ||
|
||||
( m_runState == CompletedSuccessfully &&
|
||||
m_generator->next() ) ) {
|
||||
m_children.clear();
|
||||
m_runState = Executing;
|
||||
}
|
||||
@@ -206,7 +226,6 @@ namespace Catch {
|
||||
using namespace Generators;
|
||||
GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext,
|
||||
TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) );
|
||||
assert( tracker.isOpen() );
|
||||
m_lastAssertionInfo.lineInfo = lineInfo;
|
||||
return tracker;
|
||||
}
|
||||
|
@@ -187,7 +187,8 @@ namespace TestCaseTracking {
|
||||
bool SectionTracker::isComplete() const {
|
||||
bool complete = true;
|
||||
|
||||
if ((m_filters.empty() || m_filters[0] == "")
|
||||
if (m_filters.empty()
|
||||
|| m_filters[0] == ""
|
||||
|| std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
|
||||
complete = TrackerBase::isComplete();
|
||||
}
|
||||
|
@@ -55,6 +55,7 @@ namespace TestCaseTracking {
|
||||
virtual bool isSuccessfullyCompleted() const = 0;
|
||||
virtual bool isOpen() const = 0; // Started but not complete
|
||||
virtual bool hasChildren() const = 0;
|
||||
virtual bool hasStarted() const = 0;
|
||||
|
||||
virtual ITracker& parent() = 0;
|
||||
|
||||
@@ -121,7 +122,9 @@ namespace TestCaseTracking {
|
||||
bool isSuccessfullyCompleted() const override;
|
||||
bool isOpen() const override;
|
||||
bool hasChildren() const override;
|
||||
|
||||
bool hasStarted() const override {
|
||||
return m_runState != NotStarted;
|
||||
}
|
||||
|
||||
void addChild( ITrackerPtr const& child ) override;
|
||||
|
||||
|
Reference in New Issue
Block a user