Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:06

0001 
0002 //              Copyright Catch2 Authors
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //   (See accompanying file LICENSE.txt or copy at
0005 //        https://www.boost.org/LICENSE_1_0.txt)
0006 
0007 // SPDX-License-Identifier: BSL-1.0
0008 #ifndef CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
0009 #define CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
0010 
0011 #include <catch2/internal/catch_source_line_info.hpp>
0012 #include <catch2/internal/catch_unique_ptr.hpp>
0013 #include <catch2/internal/catch_stringref.hpp>
0014 
0015 #include <string>
0016 #include <vector>
0017 
0018 namespace Catch {
0019 namespace TestCaseTracking {
0020 
0021     struct NameAndLocation {
0022         std::string name;
0023         SourceLineInfo location;
0024 
0025         NameAndLocation( std::string&& _name, SourceLineInfo const& _location );
0026         friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
0027             // This is a very cheap check that should have a very high hit rate.
0028             // If we get to SourceLineInfo::operator==, we will redo it, but the
0029             // cost of repeating is trivial at that point (we will be paying
0030             // multiple strcmp/memcmps at that point).
0031             if ( lhs.location.line != rhs.location.line ) { return false; }
0032             return lhs.name == rhs.name && lhs.location == rhs.location;
0033         }
0034         friend bool operator!=(NameAndLocation const& lhs,
0035                                NameAndLocation const& rhs) {
0036             return !( lhs == rhs );
0037         }
0038     };
0039 
0040     /**
0041      * This is a variant of `NameAndLocation` that does not own the name string
0042      *
0043      * This avoids extra allocations when trying to locate a tracker by its
0044      * name and location, as long as we make sure that trackers only keep
0045      * around the owning variant.
0046      */
0047     struct NameAndLocationRef {
0048         StringRef name;
0049         SourceLineInfo location;
0050 
0051         constexpr NameAndLocationRef( StringRef name_,
0052                                       SourceLineInfo location_ ):
0053             name( name_ ), location( location_ ) {}
0054 
0055         friend bool operator==( NameAndLocation const& lhs,
0056                                 NameAndLocationRef const& rhs ) {
0057             // This is a very cheap check that should have a very high hit rate.
0058             // If we get to SourceLineInfo::operator==, we will redo it, but the
0059             // cost of repeating is trivial at that point (we will be paying
0060             // multiple strcmp/memcmps at that point).
0061             if ( lhs.location.line != rhs.location.line ) { return false; }
0062             return StringRef( lhs.name ) == rhs.name &&
0063                    lhs.location == rhs.location;
0064         }
0065         friend bool operator==( NameAndLocationRef const& lhs,
0066                                 NameAndLocation const& rhs ) {
0067             return rhs == lhs;
0068         }
0069     };
0070 
0071     class ITracker;
0072 
0073     using ITrackerPtr = Catch::Detail::unique_ptr<ITracker>;
0074 
0075     class ITracker {
0076         NameAndLocation m_nameAndLocation;
0077 
0078         using Children = std::vector<ITrackerPtr>;
0079 
0080     protected:
0081         enum CycleState {
0082             NotStarted,
0083             Executing,
0084             ExecutingChildren,
0085             NeedsAnotherRun,
0086             CompletedSuccessfully,
0087             Failed
0088         };
0089 
0090         ITracker* m_parent = nullptr;
0091         Children m_children;
0092         CycleState m_runState = NotStarted;
0093 
0094     public:
0095         ITracker( NameAndLocation&& nameAndLoc, ITracker* parent ):
0096             m_nameAndLocation( CATCH_MOVE(nameAndLoc) ),
0097             m_parent( parent )
0098         {}
0099 
0100 
0101         // static queries
0102         NameAndLocation const& nameAndLocation() const {
0103             return m_nameAndLocation;
0104         }
0105         ITracker* parent() const {
0106             return m_parent;
0107         }
0108 
0109         virtual ~ITracker(); // = default
0110 
0111 
0112         // dynamic queries
0113 
0114         //! Returns true if tracker run to completion (successfully or not)
0115         virtual bool isComplete() const = 0;
0116         //! Returns true if tracker run to completion successfully
0117         bool isSuccessfullyCompleted() const {
0118             return m_runState == CompletedSuccessfully;
0119         }
0120         //! Returns true if tracker has started but hasn't been completed
0121         bool isOpen() const;
0122         //! Returns true iff tracker has started
0123         bool hasStarted() const;
0124 
0125         // actions
0126         virtual void close() = 0; // Successfully complete
0127         virtual void fail() = 0;
0128         void markAsNeedingAnotherRun();
0129 
0130         //! Register a nested ITracker
0131         void addChild( ITrackerPtr&& child );
0132         /**
0133          * Returns ptr to specific child if register with this tracker.
0134          *
0135          * Returns nullptr if not found.
0136          */
0137         ITracker* findChild( NameAndLocationRef const& nameAndLocation );
0138         //! Have any children been added?
0139         bool hasChildren() const {
0140             return !m_children.empty();
0141         }
0142 
0143 
0144         //! Marks tracker as executing a child, doing se recursively up the tree
0145         void openChild();
0146 
0147         /**
0148          * Returns true if the instance is a section tracker
0149          *
0150          * Subclasses should override to true if they are, replaces RTTI
0151          * for internal debug checks.
0152          */
0153         virtual bool isSectionTracker() const;
0154         /**
0155          * Returns true if the instance is a generator tracker
0156          *
0157          * Subclasses should override to true if they are, replaces RTTI
0158          * for internal debug checks.
0159          */
0160         virtual bool isGeneratorTracker() const;
0161     };
0162 
0163     class TrackerContext {
0164 
0165         enum RunState {
0166             NotStarted,
0167             Executing,
0168             CompletedCycle
0169         };
0170 
0171         ITrackerPtr m_rootTracker;
0172         ITracker* m_currentTracker = nullptr;
0173         RunState m_runState = NotStarted;
0174 
0175     public:
0176 
0177         ITracker& startRun();
0178 
0179         void startCycle() {
0180             m_currentTracker = m_rootTracker.get();
0181             m_runState = Executing;
0182         }
0183         void completeCycle();
0184 
0185         bool completedCycle() const;
0186         ITracker& currentTracker() { return *m_currentTracker; }
0187         void setCurrentTracker( ITracker* tracker );
0188     };
0189 
0190     class TrackerBase : public ITracker {
0191     protected:
0192 
0193         TrackerContext& m_ctx;
0194 
0195     public:
0196         TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
0197 
0198         bool isComplete() const override;
0199 
0200         void open();
0201 
0202         void close() override;
0203         void fail() override;
0204 
0205     private:
0206         void moveToParent();
0207         void moveToThis();
0208     };
0209 
0210     class SectionTracker : public TrackerBase {
0211         std::vector<StringRef> m_filters;
0212         // Note that lifetime-wise we piggy back off the name stored in the `ITracker` parent`.
0213         // Currently it allocates owns the name, so this is safe. If it is later refactored
0214         // to not own the name, the name still has to outlive the `ITracker` parent, so
0215         // this should still be safe.
0216         StringRef m_trimmed_name;
0217     public:
0218         SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
0219 
0220         bool isSectionTracker() const override;
0221 
0222         bool isComplete() const override;
0223 
0224         static SectionTracker& acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation );
0225 
0226         void tryOpen();
0227 
0228         void addInitialFilters( std::vector<std::string> const& filters );
0229         void addNextFilters( std::vector<StringRef> const& filters );
0230         //! Returns filters active in this tracker
0231         std::vector<StringRef> const& getFilters() const { return m_filters; }
0232         //! Returns whitespace-trimmed name of the tracked section
0233         StringRef trimmedName() const;
0234     };
0235 
0236 } // namespace TestCaseTracking
0237 
0238 using TestCaseTracking::ITracker;
0239 using TestCaseTracking::TrackerContext;
0240 using TestCaseTracking::SectionTracker;
0241 
0242 } // namespace Catch
0243 
0244 #endif // CATCH_TEST_CASE_TRACKER_HPP_INCLUDED