Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/src/Progmasoft/Catch3/Internal/RunContext.hpp
blob: 295e4ca3609c32667fa6a9615faaafb00d73c726 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

//              Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
//   (See accompanying file LICENSE.txt or copy at
//        https://www.boost.org/LICENSE_1_0.txt)

// SPDX-License-Identifier: BSL-1.0
#pragma once

#include <Progmasoft/Catch3/Interfaces/IResultCapture.hpp>
#include <Progmasoft/Catch3/Internal/TestRegistry.hpp>
#include <Progmasoft/Catch3/TestRunInfo.hpp>
#include <Progmasoft/Catch3/Internal/FatalConditionHandler.hpp>
#include <Progmasoft/Catch3/TestCaseInfo.hpp>
#include <Progmasoft/Catch3/Message.hpp>
#include <Progmasoft/Catch3/Totals.hpp>
#include <Progmasoft/Catch3/Internal/TestCaseTracker.hpp>
#include <Progmasoft/Catch3/AssertionInfo.hpp>
#include <Progmasoft/Catch3/AssertionResult.hpp>
#include <Progmasoft/Catch3/Internal/Optional.hpp>
#include <Progmasoft/Catch3/Internal/MoveAndForward.hpp>
#include <Progmasoft/Catch3/Internal/ThreadSupport.hpp>

#include <string>

namespace Catch {

    class IGeneratorTracker;
    class IConfig;
    class IEventListener;
    using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
    class OutputRedirect;

    ///////////////////////////////////////////////////////////////////////////

    class RunContext final : public IResultCapture {

    public:
        RunContext( RunContext const& ) = delete;
        RunContext& operator =( RunContext const& ) = delete;

        explicit RunContext( IConfig const* _config, IEventListenerPtr&& reporter );

        ~RunContext() override;

        Totals runTest(TestCaseHandle const& testCase);

    public: // IResultCapture

        // Assertion handlers
        void handleExpr
                (   AssertionInfo const& info,
                    ITransientExpression const& expr,
                    AssertionReaction& reaction ) override;
        void handleMessage
                (   AssertionInfo const& info,
                    ResultWas::OfType resultType,
                    std::string&& message,
                    AssertionReaction& reaction ) override;
        void handleUnexpectedExceptionNotThrown
                (   AssertionInfo const& info,
                    AssertionReaction& reaction ) override;
        void handleUnexpectedInflightException
                (   AssertionInfo const& info,
                    std::string&& message,
                    AssertionReaction& reaction ) override;
        void handleIncomplete
                (   AssertionInfo const& info ) override;
        void handleNonExpr
                (   AssertionInfo const &info,
                    ResultWas::OfType resultType,
                    AssertionReaction &reaction ) override;

        void notifyAssertionStarted( AssertionInfo const& info ) override;
        bool sectionStarted( StringRef sectionName,
                             SourceLineInfo const& sectionLineInfo,
                             Counts& assertions ) override;

        void sectionEnded( SectionEndInfo&& endInfo ) override;
        void sectionEndedEarly( SectionEndInfo&& endInfo ) override;

        IGeneratorTracker*
        acquireGeneratorTracker( StringRef generatorName,
                                 SourceLineInfo const& lineInfo ) override;
        IGeneratorTracker* createGeneratorTracker(
            StringRef generatorName,
            SourceLineInfo lineInfo,
            Generators::GeneratorBasePtr&& generator ) override;


        void benchmarkPreparing( StringRef name ) override;
        void benchmarkStarting( BenchmarkInfo const& info ) override;
        void benchmarkEnded( BenchmarkStats<> const& stats ) override;
        void benchmarkFailed( StringRef error ) override;

        std::string getCurrentTestName() const override;

        const AssertionResult* getLastResult() const override;

        void exceptionEarlyReported() override;

        void handleFatalErrorCondition( StringRef message ) override;

    public:
        // !TBD We need to do this another way!
        bool aborting() const;

        //! Ends the capture of the running test's output and returns what
        //! it captured; for a process that ends inside a test, whose end is
        //! never reported. The standard streams are their own again, so
        //! flushing them at exit no longer reaches the capture buffers,
        //! which may be gone by then.
        std::string endCapture();

    private:
        void assertionPassedFastPath( SourceLineInfo lineInfo );
        // Update the non-thread-safe m_totals from the atomic assertion counts.
        void updateTotalsFromAtomics();

        void runCurrentTest();
        void invokeActiveTestCase();

        bool testForMissingAssertions( Counts& assertions );

        void assertionEnded( AssertionResult&& result );
        void reportExpr
                (   AssertionInfo const &info,
                    ResultWas::OfType resultType,
                    ITransientExpression const *expr,
                    bool negated );

        void populateReaction( AssertionReaction& reaction, bool has_normal_disposition ) const;

        // Creates dummy info for unexpected exceptions/fatal errors,
        // where we do not have the access to one, but we still need
        // to send one to the reporters.
        AssertionInfo makeDummyAssertionInfo();

    private:

        void handleUnfinishedSections();
        mutable Detail::Mutex m_assertionMutex;
        TestRunInfo m_runInfo;
        TestCaseHandle const* m_activeTestCase = nullptr;
        ITracker* m_testCaseTracker = nullptr;
        Optional<AssertionResult> m_lastResult;
        IConfig const* m_config;
        Totals m_totals;
        Detail::AtomicCounts m_atomicAssertionCount;
        IEventListenerPtr m_reporter;
        std::vector<SectionEndInfo> m_unfinishedSections;
        std::vector<ITracker*> m_activeSections;
        TrackerContext m_trackerContext;
        Detail::unique_ptr<OutputRedirect> m_outputRedirect;
        FatalConditionHandler m_fatalConditionhandler;
        // Caches m_config->abortAfter() to avoid vptr calls/allow inlining
        size_t m_abortAfterXFailedAssertions;
        bool m_shouldReportUnexpected = true;
        // Caches whether `assertionStarting` events should be sent to the reporter.
        bool m_reportAssertionStarting;
        // Caches whether `assertionEnded` events for successful assertions should be sent to the reporter
        bool m_includeSuccessfulResults;
        // Caches m_config->shouldDebugBreak() to avoid vptr calls/allow inlining
        bool m_shouldDebugBreak;
    };

    void seedRng(IConfig const& config);
    unsigned int rngSeed();
} // end namespace Catch