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         friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
27             return lhs.name == rhs.name
28                 && lhs.location == rhs.location;
29         }
30     };
31 
32     class ITracker;
33 
34     using ITrackerPtr = std::shared_ptr<ITracker>;
35 
36     class  ITracker {
37         NameAndLocation m_nameAndLocation;
38 
39     public:
ITracker(NameAndLocation const & nameAndLoc)40         ITracker(NameAndLocation const& nameAndLoc) :
41             m_nameAndLocation(nameAndLoc)
42         {}
43 
44 
45         // static queries
nameAndLocation()46         NameAndLocation const& nameAndLocation() const {
47             return m_nameAndLocation;
48         }
49 
50         virtual ~ITracker();
51 
52 
53         // dynamic queries
54         virtual bool isComplete() const = 0; // Successfully completed or failed
55         virtual bool isSuccessfullyCompleted() const = 0;
56         virtual bool isOpen() const = 0; // Started but not complete
57         virtual bool hasChildren() const = 0;
58         virtual bool hasStarted() const = 0;
59 
60         virtual ITracker& parent() = 0;
61 
62         // actions
63         virtual void close() = 0; // Successfully complete
64         virtual void fail() = 0;
65         virtual void markAsNeedingAnotherRun() = 0;
66 
67         virtual void addChild( ITrackerPtr const& child ) = 0;
68         virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0;
69         virtual void openChild() = 0;
70 
71         // Debug/ checking
72         virtual bool isSectionTracker() const = 0;
73         virtual bool isGeneratorTracker() const = 0;
74     };
75 
76     class TrackerContext {
77 
78         enum RunState {
79             NotStarted,
80             Executing,
81             CompletedCycle
82         };
83 
84         ITrackerPtr m_rootTracker;
85         ITracker* m_currentTracker = nullptr;
86         RunState m_runState = NotStarted;
87 
88     public:
89 
90         ITracker& startRun();
91         void endRun();
92 
93         void startCycle();
94         void completeCycle();
95 
96         bool completedCycle() const;
97         ITracker& currentTracker();
98         void setCurrentTracker( ITracker* tracker );
99     };
100 
101     class TrackerBase : public ITracker {
102     protected:
103         enum CycleState {
104             NotStarted,
105             Executing,
106             ExecutingChildren,
107             NeedsAnotherRun,
108             CompletedSuccessfully,
109             Failed
110         };
111 
112         using Children = std::vector<ITrackerPtr>;
113         TrackerContext& m_ctx;
114         ITracker* m_parent;
115         Children m_children;
116         CycleState m_runState = NotStarted;
117 
118     public:
119         TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
120 
121         bool isComplete() const override;
122         bool isSuccessfullyCompleted() const override;
123         bool isOpen() const override;
124         bool hasChildren() const override;
hasStarted()125         bool hasStarted() const override {
126             return m_runState != NotStarted;
127         }
128 
129         void addChild( ITrackerPtr const& child ) override;
130 
131         ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override;
132         ITracker& parent() override;
133 
134         void openChild() override;
135 
136         bool isSectionTracker() const override;
137         bool isGeneratorTracker() const override;
138 
139         void open();
140 
141         void close() override;
142         void fail() override;
143         void markAsNeedingAnotherRun() override;
144 
145     private:
146         void moveToParent();
147         void moveToThis();
148     };
149 
150     class SectionTracker : public TrackerBase {
151         std::vector<std::string> m_filters;
152         std::string m_trimmed_name;
153     public:
154         SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
155 
156         bool isSectionTracker() const override;
157 
158         bool isComplete() const override;
159 
160         static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
161 
162         void tryOpen();
163 
164         void addInitialFilters( std::vector<std::string> const& filters );
165         void addNextFilters( std::vector<std::string> const& filters );
166         //! Returns filters active in this tracker
167         std::vector<std::string> const& getFilters() const;
168         //! Returns whitespace-trimmed name of the tracked section
169         std::string const& trimmedName() const;
170     };
171 
172 } // namespace TestCaseTracking
173 
174 using TestCaseTracking::ITracker;
175 using TestCaseTracking::TrackerContext;
176 using TestCaseTracking::SectionTracker;
177 
178 } // namespace Catch
179 
180 #endif // TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
181