aboutsummaryrefslogtreecommitdiffstats
path: root/tests/SelfTest/TestRegistrations.cpp
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 /tests/SelfTest/TestRegistrations.cpp
downloadnihil-548ea226e1944e077d3ff305df43ef6b366b03f4.tar.gz
nihil-548ea226e1944e077d3ff305df43ef6b366b03f4.tar.bz2
Diffstat (limited to 'tests/SelfTest/TestRegistrations.cpp')
-rw-r--r--tests/SelfTest/TestRegistrations.cpp180
1 files changed, 180 insertions, 0 deletions
diff --git a/tests/SelfTest/TestRegistrations.cpp b/tests/SelfTest/TestRegistrations.cpp
new file mode 100644
index 0000000..d7a6966
--- /dev/null
+++ b/tests/SelfTest/TestRegistrations.cpp
@@ -0,0 +1,180 @@
+
+// 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
+
+#include <catch2/catch_tag_alias_autoregistrar.hpp>
+#include <catch2/reporters/catch_reporter_event_listener.hpp>
+#include <catch2/internal/catch_enforce.hpp>
+#include <catch2/catch_test_case_info.hpp>
+#include <catch2/reporters/catch_reporter_registrars.hpp>
+
+
+// Some example tag aliases
+CATCH_REGISTER_TAG_ALIAS("[@nhf]", "[failing]~[.]")
+CATCH_REGISTER_TAG_ALIAS("[@tricky]", "[tricky]~[.]")
+
+#ifdef __clang__
+# pragma clang diagnostic ignored "-Wpadded"
+# pragma clang diagnostic ignored "-Wweak-vtables"
+#endif
+
+/**
+ * Event listener that internally counts and validates received events.
+ *
+ * Currently only performs validation by counting received events, rather
+ * than performing full matching. This means that it won't fail if the *Ended
+ * events are provided in wrong order, as long as they come in the right amount
+ * and with the right nesting.
+ */
+class ValidatingTestListener : public Catch::EventListenerBase {
+ struct EventCounter {
+ int starting = 0;
+ int ended = 0;
+
+ bool hasActiveEvent() const {
+ return starting > ended;
+ }
+ bool hasSingleActiveEvent() const {
+ return starting - 1 == ended;
+ }
+ bool allEventsEnded() const {
+ return starting == ended;
+ }
+ };
+
+public:
+ static std::string getDescription() {
+ return "Validates ordering of Catch2's listener events";
+ }
+
+ ValidatingTestListener(Catch::IConfig const* config) :
+ EventListenerBase(config) {
+ m_preferences.shouldReportAllAssertions = true;
+ }
+
+ void testRunStarting( Catch::TestRunInfo const& ) override {
+ CATCH_ENFORCE( m_testRunCounter.starting == 0,
+ "Test run can only start once" );
+ ++m_testRunCounter.starting;
+ }
+ void testCaseStarting(Catch::TestCaseInfo const&) override {
+ CATCH_ENFORCE( m_testRunCounter.hasActiveEvent(),
+ "Test case can only be started if the test run has already started" );
+ CATCH_ENFORCE( m_testCaseCounter.allEventsEnded(),
+ "Test case cannot start if there is an unfinished one" );
+
+ ++m_testCaseCounter.starting;
+
+ // Reset the part tracking for partial test case events
+ m_lastSeenPartNumber = uint64_t(-1);
+ }
+
+ void testCasePartialStarting(Catch::TestCaseInfo const&,
+ uint64_t partNumber) override {
+ CATCH_ENFORCE( m_testCaseCounter.hasSingleActiveEvent(),
+ "Test case can only be partially started if the test case has fully started already" );
+ CATCH_ENFORCE( m_lastSeenPartNumber + 1 == partNumber,
+ "Partial test case started out of order" );
+
+ ++m_testCasePartialCounter.starting;
+ m_lastSeenPartNumber = partNumber;
+ }
+
+ void sectionStarting(Catch::SectionInfo const&) override {
+ CATCH_ENFORCE( m_testCaseCounter.hasSingleActiveEvent(),
+ "Section can only start in a test case" );
+ CATCH_ENFORCE( m_testCasePartialCounter.hasSingleActiveEvent(),
+ "Section can only start in a test case" );
+
+ ++m_sectionCounter.starting;
+ }
+
+ void assertionStarting(Catch::AssertionInfo const&) override {
+ CATCH_ENFORCE( m_testCaseCounter.hasSingleActiveEvent(),
+ "Assertion can only start if test case is started" );
+
+ ++m_assertionCounter.starting;
+ }
+ void assertionEnded(Catch::AssertionStats const&) override {
+ // todo:
+ // * Check that assertions are balanced
+ // * Check that assertions has started
+ ++m_assertionCounter.ended;
+ }
+
+ void sectionEnded(Catch::SectionStats const&) override {
+ CATCH_ENFORCE( m_sectionCounter.hasActiveEvent(),
+ "Section ended without corresponding start" );
+ // TODO: Check that all assertions ended
+
+ ++m_sectionCounter.ended;
+ }
+
+
+ void testCasePartialEnded(Catch::TestCaseStats const&,
+ uint64_t partNumber) override {
+ CATCH_ENFORCE( m_lastSeenPartNumber == partNumber,
+ "Partial test case ended out of order" );
+ CATCH_ENFORCE( m_testCasePartialCounter.hasSingleActiveEvent(),
+ "Partial test case ended without corresponding start" );
+ CATCH_ENFORCE( m_sectionCounter.allEventsEnded(),
+ "Partial test case ended with unbalanced sections" );
+ // TODO: Check that all assertions ended
+
+ ++m_testCasePartialCounter.ended;
+ }
+
+
+ void testCaseEnded(Catch::TestCaseStats const&) override {
+ CATCH_ENFORCE( m_testCaseCounter.hasSingleActiveEvent(),
+ "Test case end is not matched with test case start" );
+ CATCH_ENFORCE( m_testCasePartialCounter.allEventsEnded(),
+ "A partial test case has not ended" );
+ CATCH_ENFORCE( m_sectionCounter.allEventsEnded(),
+ "Test case ended with unbalanced sections" );
+
+ // TODO: Check that all assertions ended
+
+ ++m_testCaseCounter.ended;
+ }
+ void testRunEnded( Catch::TestRunStats const& ) override {
+ CATCH_ENFORCE( m_testRunCounter.hasSingleActiveEvent(),
+ "Test run end is not matched with test run start" );
+ CATCH_ENFORCE( m_testRunCounter.ended == 0,
+ "Test run can only end once" );
+
+ ++m_testRunCounter.ended;
+ }
+
+ ~ValidatingTestListener() override;
+
+private:
+ EventCounter m_testRunCounter;
+ EventCounter m_testCaseCounter;
+ EventCounter m_testCasePartialCounter;
+ uint64_t m_lastSeenPartNumber = 0;
+ EventCounter m_sectionCounter;
+ EventCounter m_assertionCounter;
+};
+
+
+ValidatingTestListener::~ValidatingTestListener() {
+ // Throwing from noexcept destructor terminates, but we don't mind
+ // because this is test-only check and we don't need to try and recover
+ // from assumption violation here.
+
+ CATCH_ENFORCE( m_testRunCounter.ended < 2,
+ "Test run should be started at most once" );
+ CATCH_ENFORCE( m_testRunCounter.allEventsEnded(),
+ "The test run has not finished" );
+ CATCH_ENFORCE( m_testCaseCounter.allEventsEnded(),
+ "A test case did not finish" );
+
+ // TODO: other counters being balanced?
+}
+
+CATCH_REGISTER_LISTENER( ValidatingTestListener )