File indexing completed on 2025-01-18 09:54:06
0001
0002
0003
0004
0005
0006
0007
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
0028
0029
0030
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
0042
0043
0044
0045
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
0058
0059
0060
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
0102 NameAndLocation const& nameAndLocation() const {
0103 return m_nameAndLocation;
0104 }
0105 ITracker* parent() const {
0106 return m_parent;
0107 }
0108
0109 virtual ~ITracker();
0110
0111
0112
0113
0114
0115 virtual bool isComplete() const = 0;
0116
0117 bool isSuccessfullyCompleted() const {
0118 return m_runState == CompletedSuccessfully;
0119 }
0120
0121 bool isOpen() const;
0122
0123 bool hasStarted() const;
0124
0125
0126 virtual void close() = 0;
0127 virtual void fail() = 0;
0128 void markAsNeedingAnotherRun();
0129
0130
0131 void addChild( ITrackerPtr&& child );
0132
0133
0134
0135
0136
0137 ITracker* findChild( NameAndLocationRef const& nameAndLocation );
0138
0139 bool hasChildren() const {
0140 return !m_children.empty();
0141 }
0142
0143
0144
0145 void openChild();
0146
0147
0148
0149
0150
0151
0152
0153 virtual bool isSectionTracker() const;
0154
0155
0156
0157
0158
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
0213
0214
0215
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
0231 std::vector<StringRef> const& getFilters() const { return m_filters; }
0232
0233 StringRef trimmedName() const;
0234 };
0235
0236 }
0237
0238 using TestCaseTracking::ITracker;
0239 using TestCaseTracking::TrackerContext;
0240 using TestCaseTracking::SectionTracker;
0241
0242 }
0243
0244 #endif