Struct GeneratorTracker

Synopsis

#include <include/internal/catch_run_context.cpp>

struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker

Description

No description yet.

Inheritance

Ancestors: TrackerBase, IGeneratorTracker

Methods

GeneratorTracker
~GeneratorTracker
acquire
close
getGenerator
hasGenerator
isGeneratorTracker
setGenerator

Source

Lines 16-101 in include/internal/catch_run_context.cpp.

struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
    GeneratorBasePtr m_generator;
    GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
    :   TrackerBase( nameAndLocation, ctx, parent )
    {}
    ~GeneratorTracker();
    static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
        std::shared_ptr<GeneratorTracker> tracker;
        ITracker& currentTracker = ctx.currentTracker();
        // Under specific circumstances, the generator we want
        // to acquire is also the current tracker. If this is
        // the case, we have to avoid looking through current
        // tracker's children, and instead return the current
        // tracker.
        // A case where this check is important is e.g.
        //     for (int i = 0; i < 5; ++i) {
        //         int n = GENERATE(1, 2);
        //     }
        //
        // without it, the code above creates 5 nested generators.
        if (currentTracker.nameAndLocation() == nameAndLocation) {
            auto thisTracker = currentTracker.parent().findChild(nameAndLocation);
            assert(thisTracker);
            assert(thisTracker->isGeneratorTracker());
            tracker = std::static_pointer_cast<GeneratorTracker>(thisTracker);
        } else if ( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
            assert( childTracker );
            assert( childTracker->isGeneratorTracker() );
            tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
        } else {
            tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, &currentTracker );
            currentTracker.addChild( tracker );
        }
        if( !tracker->isComplete() ) {
            tracker->open();
        }
        return *tracker;
    }
    // TrackerBase interface
    bool isGeneratorTracker() const override { return true; }
    auto hasGenerator() const -> bool override {
        return !!m_generator;
    }
    void close() override {
        TrackerBase::close();
        // 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;
        }
    }
    // IGeneratorTracker interface
    auto getGenerator() const -> GeneratorBasePtr const& override {
        return m_generator;
    }
    void setGenerator( GeneratorBasePtr&& generator ) override {
        m_generator = std::move( generator );
    }
};





Add Discussion as Guest

Log in