1 /*
2  *  Created by Phil Nash on 23/7/2013
3  *  Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
4  *
5  *  Distributed under the Boost Software License, Version 1.0. (See accompanying
6  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  */
8 #ifndef TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
9 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
10 
11 #include "catch_compiler_capabilities.h"
12 #include "catch_common.h"
13 
14 #include <string>
15 #include <vector>
16 #include <memory>
17 
18 namespace Catch {
19 namespace TestCaseTracking {
20 
21     struct NameAndLocation {
22         std::string name;
23         SourceLineInfo location;
24 
25         NameAndLocation( std::string const& _name, SourceLineInfo const& _location );
26     };
27 
28     struct ITracker;
29 
30     using ITrackerPtr = std::shared_ptr<ITracker>;
31 
32     struct ITracker {
33         virtual ~ITracker();
34 
35         // static queries
36         virtual NameAndLocation const& nameAndLocation() const = 0;
37 
38         // dynamic queries
39         virtual bool isComplete() const = 0; // Successfully completed or failed
40         virtual bool isSuccessfullyCompleted() const = 0;
41         virtual bool isOpen() const = 0; // Started but not complete
42         virtual bool hasChildren() const = 0;
43 
44         virtual ITracker& parent() = 0;
45 
46         // actions
47         virtual void close() = 0; // Successfully complete
48         virtual void fail() = 0;
49         virtual void markAsNeedingAnotherRun() = 0;
50 
51         virtual void addChild( ITrackerPtr const& child ) = 0;
52         virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0;
53         virtual void openChild() = 0;
54 
55         // Debug/ checking
56         virtual bool isSectionTracker() const = 0;
57         virtual bool isGeneratorTracker() const = 0;
58     };
59 
60     class TrackerContext {
61 
62         enum RunState {
63             NotStarted,
64             Executing,
65             CompletedCycle
66         };
67 
68         ITrackerPtr m_rootTracker;
69         ITracker* m_currentTracker = nullptr;
70         RunState m_runState = NotStarted;
71 
72     public:
73 
74         ITracker& startRun();
75         void endRun();
76 
77         void startCycle();
78         void completeCycle();
79 
80         bool completedCycle() const;
81         ITracker& currentTracker();
82         void setCurrentTracker( ITracker* tracker );
83     };
84 
85     class TrackerBase : public ITracker {
86     protected:
87         enum CycleState {
88             NotStarted,
89             Executing,
90             ExecutingChildren,
91             NeedsAnotherRun,
92             CompletedSuccessfully,
93             Failed
94         };
95 
96         using Children = std::vector<ITrackerPtr>;
97         NameAndLocation m_nameAndLocation;
98         TrackerContext& m_ctx;
99         ITracker* m_parent;
100         Children m_children;
101         CycleState m_runState = NotStarted;
102 
103     public:
104         TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
105 
106         NameAndLocation const& nameAndLocation() const override;
107         bool isComplete() const override;
108         bool isSuccessfullyCompleted() const override;
109         bool isOpen() const override;
110         bool hasChildren() const override;
111 
112 
113         void addChild( ITrackerPtr const& child ) override;
114 
115         ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override;
116         ITracker& parent() override;
117 
118         void openChild() override;
119 
120         bool isSectionTracker() const override;
121         bool isGeneratorTracker() const override;
122 
123         void open();
124 
125         void close() override;
126         void fail() override;
127         void markAsNeedingAnotherRun() override;
128 
129     private:
130         void moveToParent();
131         void moveToThis();
132     };
133 
134     class SectionTracker : public TrackerBase {
135         std::vector<std::string> m_filters;
136         std::string m_trimmed_name;
137     public:
138         SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
139 
140         bool isSectionTracker() const override;
141 
142         bool isComplete() const override;
143 
144         static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
145 
146         void tryOpen();
147 
148         void addInitialFilters( std::vector<std::string> const& filters );
149         void addNextFilters( std::vector<std::string> const& filters );
150     };
151 
152 } // namespace TestCaseTracking
153 
154 using TestCaseTracking::ITracker;
155 using TestCaseTracking::TrackerContext;
156 using TestCaseTracking::SectionTracker;
157 
158 } // namespace Catch
159 
160 #endif // TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
161