| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 | 
//              Copyright Catch2 Authors// Distributed under the Boost Software License, Version 1.0.//   (See accompanying file LICENSE_1_0.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 aliasesCATCH_REGISTER_TAG_ALIAS("[@nhf]", "[failing]~[.]")CATCH_REGISTER_TAG_ALIAS("[@tricky]", "[tricky]~[.]")#ifdef __clang__#   pragma clang diagnostic ignored "-Wpadded"#   pragma clang diagnostic ignored "-Wweak-vtables"#   pragma clang diagnostic ignored "-Wc++98-compat"#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 )
 |