aboutsummaryrefslogtreecommitdiffstats
path: root/src/catch2/reporters/catch_reporter_cumulative_base.hpp
diff options
context:
space:
mode:
authorLexi Winter <lexi@le-fay.org>2025-06-29 19:25:29 +0100
committerLexi Winter <lexi@le-fay.org>2025-06-29 19:25:29 +0100
commitbc524d70253a4ab2fe40c3ca3e5666e267c0a4d1 (patch)
tree1e629e7b46b1d9972a973bc93fd100bcebd395be /src/catch2/reporters/catch_reporter_cumulative_base.hpp
downloadnihil-vendor/catch2.tar.gz
nihil-vendor/catch2.tar.bz2
Diffstat (limited to 'src/catch2/reporters/catch_reporter_cumulative_base.hpp')
-rw-r--r--src/catch2/reporters/catch_reporter_cumulative_base.hpp151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/catch2/reporters/catch_reporter_cumulative_base.hpp b/src/catch2/reporters/catch_reporter_cumulative_base.hpp
new file mode 100644
index 0000000..267b39f
--- /dev/null
+++ b/src/catch2/reporters/catch_reporter_cumulative_base.hpp
@@ -0,0 +1,151 @@
+
+// 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
+#ifndef CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
+#define CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
+
+#include <catch2/reporters/catch_reporter_common_base.hpp>
+#include <catch2/internal/catch_move_and_forward.hpp>
+#include <catch2/internal/catch_unique_ptr.hpp>
+#include <catch2/internal/catch_optional.hpp>
+
+#include <string>
+#include <vector>
+
+namespace Catch {
+
+ namespace Detail {
+
+ //! Represents either an assertion or a benchmark result to be handled by cumulative reporter later
+ class AssertionOrBenchmarkResult {
+ // This should really be a variant, but this is much faster
+ // to write and the data layout here is already terrible
+ // enough that we do not have to care about the object size.
+ Optional<AssertionStats> m_assertion;
+ Optional<BenchmarkStats<>> m_benchmark;
+ public:
+ AssertionOrBenchmarkResult(AssertionStats const& assertion);
+ AssertionOrBenchmarkResult(BenchmarkStats<> const& benchmark);
+
+ bool isAssertion() const;
+ bool isBenchmark() const;
+
+ AssertionStats const& asAssertion() const;
+ BenchmarkStats<> const& asBenchmark() const;
+ };
+ }
+
+ /**
+ * Utility base for reporters that need to handle all results at once
+ *
+ * It stores tree of all test cases, sections and assertions, and after the
+ * test run is finished, calls into `testRunEndedCumulative` to pass the
+ * control to the deriving class.
+ *
+ * If you are deriving from this class and override any testing related
+ * member functions, you should first call into the base's implementation to
+ * avoid breaking the tree construction.
+ *
+ * Due to the way this base functions, it has to expand assertions up-front,
+ * even if they are later unused (e.g. because the deriving reporter does
+ * not report successful assertions, or because the deriving reporter does
+ * not use assertion expansion at all). Derived classes can use two
+ * customization points, `m_shouldStoreSuccesfulAssertions` and
+ * `m_shouldStoreFailedAssertions`, to disable the expansion and gain extra
+ * performance. **Accessing the assertion expansions if it wasn't stored is
+ * UB.**
+ */
+ class CumulativeReporterBase : public ReporterBase {
+ public:
+ template<typename T, typename ChildNodeT>
+ struct Node {
+ explicit Node( T const& _value ) : value( _value ) {}
+
+ using ChildNodes = std::vector<Detail::unique_ptr<ChildNodeT>>;
+ T value;
+ ChildNodes children;
+ };
+ struct SectionNode {
+ explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}
+
+ bool operator == (SectionNode const& other) const {
+ return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
+ }
+
+ bool hasAnyAssertions() const;
+
+ SectionStats stats;
+ std::vector<Detail::unique_ptr<SectionNode>> childSections;
+ std::vector<Detail::AssertionOrBenchmarkResult> assertionsAndBenchmarks;
+ std::string stdOut;
+ std::string stdErr;
+ };
+
+
+ using TestCaseNode = Node<TestCaseStats, SectionNode>;
+ using TestRunNode = Node<TestRunStats, TestCaseNode>;
+
+ // GCC5 compat: we cannot use inherited constructor, because it
+ // doesn't implement backport of P0136
+ CumulativeReporterBase(ReporterConfig&& _config):
+ ReporterBase(CATCH_MOVE(_config))
+ {}
+ ~CumulativeReporterBase() override;
+
+ void benchmarkPreparing( StringRef ) override {}
+ void benchmarkStarting( BenchmarkInfo const& ) override {}
+ void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
+ void benchmarkFailed( StringRef ) override {}
+
+ void noMatchingTestCases( StringRef ) override {}
+ void reportInvalidTestSpec( StringRef ) override {}
+ void fatalErrorEncountered( StringRef /*error*/ ) override {}
+
+ void testRunStarting( TestRunInfo const& ) override {}
+
+ void testCaseStarting( TestCaseInfo const& ) override {}
+ void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {}
+ void sectionStarting( SectionInfo const& sectionInfo ) override;
+
+ void assertionStarting( AssertionInfo const& ) override {}
+
+ void assertionEnded( AssertionStats const& assertionStats ) override;
+ void sectionEnded( SectionStats const& sectionStats ) override;
+ void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {}
+ void testCaseEnded( TestCaseStats const& testCaseStats ) override;
+ void testRunEnded( TestRunStats const& testRunStats ) override;
+ //! Customization point: called after last test finishes (testRunEnded has been handled)
+ virtual void testRunEndedCumulative() = 0;
+
+ void skipTest(TestCaseInfo const&) override {}
+
+ protected:
+ //! Should the cumulative base store the assertion expansion for successful assertions?
+ bool m_shouldStoreSuccesfulAssertions = true;
+ //! Should the cumulative base store the assertion expansion for failed assertions?
+ bool m_shouldStoreFailedAssertions = true;
+
+ // We need lazy construction here. We should probably refactor it
+ // later, after the events are redone.
+ //! The root node of the test run tree.
+ Detail::unique_ptr<TestRunNode> m_testRun;
+
+ private:
+ // Note: We rely on pointer identity being stable, which is why
+ // we store pointers to the nodes rather than the values.
+ std::vector<Detail::unique_ptr<TestCaseNode>> m_testCases;
+ // Root section of the _current_ test case
+ Detail::unique_ptr<SectionNode> m_rootSection;
+ // Deepest section of the _current_ test case
+ SectionNode* m_deepestSection = nullptr;
+ // Stack of _active_ sections in the _current_ test case
+ std::vector<SectionNode*> m_sectionStack;
+ };
+
+} // end namespace Catch
+
+#endif // CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED