| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 | 
							- /*
 
-  *  Created by Martin on 19/07/2017
 
-  *
 
-  *  Distributed under the Boost Software License, Version 1.0. (See accompanying
 
-  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 
-  */
 
- #include "catch_test_case_tracker.h"
 
- #include "catch_enforce.h"
 
- #include "catch_string_manip.h"
 
- #include <algorithm>
 
- #include <cassert>
 
- #include <stdexcept>
 
- #include <memory>
 
- #include <sstream>
 
- #if defined(__clang__)
 
- #    pragma clang diagnostic push
 
- #    pragma clang diagnostic ignored "-Wexit-time-destructors"
 
- #endif
 
- namespace Catch {
 
- namespace TestCaseTracking {
 
-     NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
 
-     :   name( _name ),
 
-         location( _location )
 
-     {}
 
-     ITracker::~ITracker() = default;
 
-     ITracker& TrackerContext::startRun() {
 
-         m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr );
 
-         m_currentTracker = nullptr;
 
-         m_runState = Executing;
 
-         return *m_rootTracker;
 
-     }
 
-     void TrackerContext::endRun() {
 
-         m_rootTracker.reset();
 
-         m_currentTracker = nullptr;
 
-         m_runState = NotStarted;
 
-     }
 
-     void TrackerContext::startCycle() {
 
-         m_currentTracker = m_rootTracker.get();
 
-         m_runState = Executing;
 
-     }
 
-     void TrackerContext::completeCycle() {
 
-         m_runState = CompletedCycle;
 
-     }
 
-     bool TrackerContext::completedCycle() const {
 
-         return m_runState == CompletedCycle;
 
-     }
 
-     ITracker& TrackerContext::currentTracker() {
 
-         return *m_currentTracker;
 
-     }
 
-     void TrackerContext::setCurrentTracker( ITracker* tracker ) {
 
-         m_currentTracker = tracker;
 
-     }
 
-     TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
 
-         ITracker(nameAndLocation),
 
-         m_ctx( ctx ),
 
-         m_parent( parent )
 
-     {}
 
-     bool TrackerBase::isComplete() const {
 
-         return m_runState == CompletedSuccessfully || m_runState == Failed;
 
-     }
 
-     bool TrackerBase::isSuccessfullyCompleted() const {
 
-         return m_runState == CompletedSuccessfully;
 
-     }
 
-     bool TrackerBase::isOpen() const {
 
-         return m_runState != NotStarted && !isComplete();
 
-     }
 
-     bool TrackerBase::hasChildren() const {
 
-         return !m_children.empty();
 
-     }
 
-     void TrackerBase::addChild( ITrackerPtr const& child ) {
 
-         m_children.push_back( child );
 
-     }
 
-     ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) {
 
-         auto it = std::find_if( m_children.begin(), m_children.end(),
 
-             [&nameAndLocation]( ITrackerPtr const& tracker ){
 
-                 return
 
-                     tracker->nameAndLocation().location == nameAndLocation.location &&
 
-                     tracker->nameAndLocation().name == nameAndLocation.name;
 
-             } );
 
-         return( it != m_children.end() )
 
-             ? *it
 
-             : nullptr;
 
-     }
 
-     ITracker& TrackerBase::parent() {
 
-         assert( m_parent ); // Should always be non-null except for root
 
-         return *m_parent;
 
-     }
 
-     void TrackerBase::openChild() {
 
-         if( m_runState != ExecutingChildren ) {
 
-             m_runState = ExecutingChildren;
 
-             if( m_parent )
 
-                 m_parent->openChild();
 
-         }
 
-     }
 
-     bool TrackerBase::isSectionTracker() const { return false; }
 
-     bool TrackerBase::isGeneratorTracker() const { return false; }
 
-     void TrackerBase::open() {
 
-         m_runState = Executing;
 
-         moveToThis();
 
-         if( m_parent )
 
-             m_parent->openChild();
 
-     }
 
-     void TrackerBase::close() {
 
-         // Close any still open children (e.g. generators)
 
-         while( &m_ctx.currentTracker() != this )
 
-             m_ctx.currentTracker().close();
 
-         switch( m_runState ) {
 
-             case NeedsAnotherRun:
 
-                 break;
 
-             case Executing:
 
-                 m_runState = CompletedSuccessfully;
 
-                 break;
 
-             case ExecutingChildren:
 
-                 if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) )
 
-                     m_runState = CompletedSuccessfully;
 
-                 break;
 
-             case NotStarted:
 
-             case CompletedSuccessfully:
 
-             case Failed:
 
-                 CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState );
 
-             default:
 
-                 CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState );
 
-         }
 
-         moveToParent();
 
-         m_ctx.completeCycle();
 
-     }
 
-     void TrackerBase::fail() {
 
-         m_runState = Failed;
 
-         if( m_parent )
 
-             m_parent->markAsNeedingAnotherRun();
 
-         moveToParent();
 
-         m_ctx.completeCycle();
 
-     }
 
-     void TrackerBase::markAsNeedingAnotherRun() {
 
-         m_runState = NeedsAnotherRun;
 
-     }
 
-     void TrackerBase::moveToParent() {
 
-         assert( m_parent );
 
-         m_ctx.setCurrentTracker( m_parent );
 
-     }
 
-     void TrackerBase::moveToThis() {
 
-         m_ctx.setCurrentTracker( this );
 
-     }
 
-     SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
 
-     :   TrackerBase( nameAndLocation, ctx, parent ),
 
-         m_trimmed_name(trim(nameAndLocation.name))
 
-     {
 
-         if( parent ) {
 
-             while( !parent->isSectionTracker() )
 
-                 parent = &parent->parent();
 
-             SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
 
-             addNextFilters( parentSection.m_filters );
 
-         }
 
-     }
 
-     bool SectionTracker::isComplete() const {
 
-         bool complete = true;
 
-         if (m_filters.empty()
 
-             || m_filters[0] == ""
 
-             || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
 
-             complete = TrackerBase::isComplete();
 
-         }
 
-         return complete;
 
-     }
 
-     bool SectionTracker::isSectionTracker() const { return true; }
 
-     SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
 
-         std::shared_ptr<SectionTracker> section;
 
-         ITracker& currentTracker = ctx.currentTracker();
 
-         if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
 
-             assert( childTracker );
 
-             assert( childTracker->isSectionTracker() );
 
-             section = std::static_pointer_cast<SectionTracker>( childTracker );
 
-         }
 
-         else {
 
-             section = std::make_shared<SectionTracker>( nameAndLocation, ctx, ¤tTracker );
 
-             currentTracker.addChild( section );
 
-         }
 
-         if( !ctx.completedCycle() )
 
-             section->tryOpen();
 
-         return *section;
 
-     }
 
-     void SectionTracker::tryOpen() {
 
-         if( !isComplete() )
 
-             open();
 
-     }
 
-     void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
 
-         if( !filters.empty() ) {
 
-             m_filters.reserve( m_filters.size() + filters.size() + 2 );
 
-             m_filters.emplace_back(""); // Root - should never be consulted
 
-             m_filters.emplace_back(""); // Test Case - not a section filter
 
-             m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
 
-         }
 
-     }
 
-     void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) {
 
-         if( filters.size() > 1 )
 
-             m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() );
 
-     }
 
-     std::vector<std::string> const& SectionTracker::getFilters() const {
 
-         return m_filters;
 
-     }
 
-     std::string const& SectionTracker::trimmedName() const {
 
-         return m_trimmed_name;
 
-     }
 
- } // namespace TestCaseTracking
 
- using TestCaseTracking::ITracker;
 
- using TestCaseTracking::TrackerContext;
 
- using TestCaseTracking::SectionTracker;
 
- } // namespace Catch
 
- #if defined(__clang__)
 
- #    pragma clang diagnostic pop
 
- #endif
 
 
  |