| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 | // 210-Evt-EventListeners.cpp// Contents:// 1. Printing of listener data// 2. My listener and registration// 3. Test cases#include <catch2/catch_test_macros.hpp>#include <catch2/reporters/catch_reporter_event_listener.hpp>#include <catch2/reporters/catch_reporter_registrars.hpp>#include <catch2/catch_test_case_info.hpp>#include <iostream>// -----------------------------------------------------------------------// 1. Printing of listener data://namespace {std::string ws(int const level) {    return std::string( 2 * level, ' ' );}std::ostream& operator<<(std::ostream& out, Catch::Tag t) {    return out << "original: " << t.original;}template< typename T >std::ostream& operator<<( std::ostream& os, std::vector<T> const& v ) {    os << "{ ";    for ( const auto& x : v )        os << x << ", ";    return os << "}";}// struct SourceLineInfo {//     char const* file;//     std::size_t line;// };void print( std::ostream& os, int const level, std::string const& title, Catch::SourceLineInfo const& info ) {    os << ws(level  ) << title << ":\n"       << ws(level+1) << "- file: " << info.file << "\n"       << ws(level+1) << "- line: " << info.line << "\n";}//struct MessageInfo {//    std::string macroName;//    std::string message;//    SourceLineInfo lineInfo;//    ResultWas::OfType type;//    unsigned int sequence;//};void print( std::ostream& os, int const level, Catch::MessageInfo const& info ) {    os << ws(level+1) << "- macroName: '" << info.macroName << "'\n"       << ws(level+1) << "- message '"    << info.message   << "'\n";    print( os,level+1  , "- lineInfo", info.lineInfo );    os << ws(level+1) << "- sequence "    << info.sequence  << "\n";}void print( std::ostream& os, int const level, std::string const& title, std::vector<Catch::MessageInfo> const& v ) {    os << ws(level  ) << title << ":\n";    for ( const auto& x : v )    {        os << ws(level+1) << "{\n";        print( os, level+2, x );        os << ws(level+1) << "}\n";    }//    os << ws(level+1) << "\n";}// struct TestRunInfo {//     std::string name;// };void print( std::ostream& os, int const level, std::string const& title, Catch::TestRunInfo const& info ) {    os << ws(level  ) << title << ":\n"       << ws(level+1) << "- name: " << info.name << "\n";}// struct Counts {//     std::size_t total() const;//     bool allPassed() const;//     bool allOk() const;////     std::size_t passed = 0;//     std::size_t failed = 0;//     std::size_t failedButOk = 0;// };void print( std::ostream& os, int const level, std::string const& title, Catch::Counts const& info ) {    os << ws(level  ) << title << ":\n"       << ws(level+1) << "- total(): "     << info.total()     << "\n"       << ws(level+1) << "- allPassed(): " << info.allPassed() << "\n"       << ws(level+1) << "- allOk(): "     << info.allOk()     << "\n"       << ws(level+1) << "- passed: "      << info.passed      << "\n"       << ws(level+1) << "- failed: "      << info.failed      << "\n"       << ws(level+1) << "- failedButOk: " << info.failedButOk << "\n";}// struct Totals {//     Counts assertions;//     Counts testCases;// };void print( std::ostream& os, int const level, std::string const& title, Catch::Totals const& info ) {    os << ws(level) << title << ":\n";    print( os, level+1, "- assertions", info.assertions );    print( os, level+1, "- testCases" , info.testCases  );}// struct TestRunStats {//     TestRunInfo runInfo;//     Totals totals;//     bool aborting;// };void print( std::ostream& os, int const level, std::string const& title, Catch::TestRunStats const& info ) {    os << ws(level) << title << ":\n";    print( os, level+1 , "- runInfo", info.runInfo );    print( os, level+1 , "- totals" , info.totals  );    os << ws(level+1) << "- aborting: " << info.aborting << "\n";}//    struct Tag {//        StringRef original, lowerCased;//    };//////    enum class TestCaseProperties : uint8_t {//        None = 0,//        IsHidden = 1 << 1,//        ShouldFail = 1 << 2,//        MayFail = 1 << 3,//        Throws = 1 << 4,//        NonPortable = 1 << 5,//        Benchmark = 1 << 6//    };//////    struct TestCaseInfo : NonCopyable {////        bool isHidden() const;//        bool throws() const;//        bool okToFail() const;//        bool expectedToFail() const;//////        std::string name;//        std::string className;//        std::vector<Tag> tags;//        SourceLineInfo lineInfo;//        TestCaseProperties properties = TestCaseProperties::None;//    };void print( std::ostream& os, int const level, std::string const& title, Catch::TestCaseInfo const& info ) {    os << ws(level  ) << title << ":\n"       << ws(level+1) << "- isHidden(): "       << info.isHidden() << "\n"       << ws(level+1) << "- throws(): "         << info.throws() << "\n"       << ws(level+1) << "- okToFail(): "       << info.okToFail() << "\n"       << ws(level+1) << "- expectedToFail(): " << info.expectedToFail() << "\n"       << ws(level+1) << "- tagsAsString(): '"  << info.tagsAsString() << "'\n"       << ws(level+1) << "- name: '"            << info.name << "'\n"       << ws(level+1) << "- className: '"       << info.className << "'\n"       << ws(level+1) << "- tags: "             << info.tags << "\n";    print( os, level+1 , "- lineInfo", info.lineInfo );    os << ws(level+1) << "- properties (flags): 0x" << std::hex << static_cast<uint32_t>(info.properties) << std::dec << "\n";}// struct TestCaseStats {//     TestCaseInfo testInfo;//     Totals totals;//     std::string stdOut;//     std::string stdErr;//     bool aborting;// };void print( std::ostream& os, int const level, std::string const& title, Catch::TestCaseStats const& info ) {    os << ws(level  ) << title << ":\n";    print( os, level+1 , "- testInfo", *info.testInfo );    print( os, level+1 , "- totals"  , info.totals   );    os << ws(level+1) << "- stdOut: "   << info.stdOut << "\n"       << ws(level+1) << "- stdErr: "   << info.stdErr << "\n"       << ws(level+1) << "- aborting: " << info.aborting << "\n";}// struct SectionInfo {//     std::string name;//     std::string description;//     SourceLineInfo lineInfo;// };void print( std::ostream& os, int const level, std::string const& title, Catch::SectionInfo const& info ) {    os << ws(level  ) << title << ":\n"       << ws(level+1) << "- name: "         << info.name << "\n";    print( os, level+1 , "- lineInfo", info.lineInfo );}// struct SectionStats {//     SectionInfo sectionInfo;//     Counts assertions;//     double durationInSeconds;//     bool missingAssertions;// };void print( std::ostream& os, int const level, std::string const& title, Catch::SectionStats const& info ) {    os << ws(level  ) << title << ":\n";    print( os, level+1 , "- sectionInfo", info.sectionInfo );    print( os, level+1 , "- assertions" , info.assertions );    os << ws(level+1) << "- durationInSeconds: " << info.durationInSeconds << "\n"       << ws(level+1) << "- missingAssertions: " << info.missingAssertions << "\n";}// struct AssertionInfo// {//     StringRef macroName;//     SourceLineInfo lineInfo;//     StringRef capturedExpression;//     ResultDisposition::Flags resultDisposition;// };void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionInfo const& info ) {    os << ws(level  ) << title << ":\n"       << ws(level+1) << "- macroName: '"  << info.macroName << "'\n";    print( os, level+1 , "- lineInfo" , info.lineInfo );    os << ws(level+1) << "- capturedExpression: '" << info.capturedExpression << "'\n"       << ws(level+1) << "- resultDisposition (flags): 0x" << std::hex << info.resultDisposition  << std::dec << "\n";}//struct AssertionResultData//{//    std::string reconstructExpression() const;////    std::string message;//    mutable std::string reconstructedExpression;//    LazyExpression lazyExpression;//    ResultWas::OfType resultType;//};void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionResultData const& info ) {    os << ws(level  ) << title << ":\n"       << ws(level+1) << "- reconstructExpression(): '" <<   info.reconstructExpression() << "'\n"       << ws(level+1) << "- message: '"                 <<   info.message << "'\n"       << ws(level+1) << "- lazyExpression: '"          << "(info.lazyExpression)" << "'\n"       << ws(level+1) << "- resultType: '"              <<   info.resultType << "'\n";}//class AssertionResult {//    bool isOk() const;//    bool succeeded() const;//    ResultWas::OfType getResultType() const;//    bool hasExpression() const;//    bool hasMessage() const;//    std::string getExpression() const;//    std::string getExpressionInMacro() const;//    bool hasExpandedExpression() const;//    std::string getExpandedExpression() const;//    std::string getMessage() const;//    SourceLineInfo getSourceInfo() const;//    std::string getTestMacroName() const;////    AssertionInfo m_info;//    AssertionResultData m_resultData;//};void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionResult const& info ) {    os << ws(level  ) << title << ":\n"       << ws(level+1) << "- isOk(): "  << info.isOk() << "\n"       << ws(level+1) << "- succeeded(): "  << info.succeeded() << "\n"       << ws(level+1) << "- getResultType(): "  << info.getResultType() << "\n"       << ws(level+1) << "- hasExpression(): "  << info.hasExpression() << "\n"       << ws(level+1) << "- hasMessage(): "  << info.hasMessage() << "\n"       << ws(level+1) << "- getExpression(): '"  << info.getExpression() << "'\n"       << ws(level+1) << "- getExpressionInMacro(): '"  << info.getExpressionInMacro()  << "'\n"       << ws(level+1) << "- hasExpandedExpression(): "  << info.hasExpandedExpression() << "\n"       << ws(level+1) << "- getExpandedExpression(): "  << info.getExpandedExpression() << "'\n"       << ws(level+1) << "- getMessage(): '"  << info.getMessage() << "'\n";    print( os, level+1 , "- getSourceInfo(): ", info.getSourceInfo() );    os << ws(level+1) << "- getTestMacroName(): '"  << info.getTestMacroName() << "'\n";    print( os, level+1 , "- *** m_info (AssertionInfo)", info.m_info );    print( os, level+1 , "- *** m_resultData (AssertionResultData)", info.m_resultData );}// struct AssertionStats {//     AssertionResult assertionResult;//     std::vector<MessageInfo> infoMessages;//     Totals totals;// };void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionStats const& info ) {    os << ws(level  ) << title << ":\n";    print( os, level+1 , "- assertionResult", info.assertionResult );    print( os, level+1 , "- infoMessages", info.infoMessages );    print( os, level+1 , "- totals", info.totals );}// -----------------------------------------------------------------------// 2. My listener and registration://char const * dashed_line =    "--------------------------------------------------------------------------";struct MyListener : Catch::EventListenerBase {    using EventListenerBase::EventListenerBase; // inherit constructor    // Get rid of Wweak-tables    ~MyListener() override;    // The whole test run starting    void testRunStarting( Catch::TestRunInfo const& testRunInfo ) override {        std::cout            << std::boolalpha            << "\nEvent: testRunStarting:\n";        print( std::cout, 1, "- testRunInfo", testRunInfo );    }    // The whole test run ending    void testRunEnded( Catch::TestRunStats const& testRunStats ) override {        std::cout            << dashed_line            << "\nEvent: testRunEnded:\n";        print( std::cout, 1, "- testRunStats", testRunStats );    }    // A test is being skipped (because it is "hidden")    void skipTest( Catch::TestCaseInfo const& testInfo ) override {        std::cout            << dashed_line            << "\nEvent: skipTest:\n";        print( std::cout, 1, "- testInfo", testInfo );    }    // Test cases starting    void testCaseStarting( Catch::TestCaseInfo const& testInfo ) override {        std::cout            << dashed_line            << "\nEvent: testCaseStarting:\n";        print( std::cout, 1, "- testInfo", testInfo );    }    // Test cases ending    void testCaseEnded( Catch::TestCaseStats const& testCaseStats ) override {        std::cout << "\nEvent: testCaseEnded:\n";        print( std::cout, 1, "testCaseStats", testCaseStats );    }    // Sections starting    void sectionStarting( Catch::SectionInfo const& sectionInfo ) override {        std::cout << "\nEvent: sectionStarting:\n";        print( std::cout, 1, "- sectionInfo", sectionInfo );    }    // Sections ending    void sectionEnded( Catch::SectionStats const& sectionStats ) override {        std::cout << "\nEvent: sectionEnded:\n";        print( std::cout, 1, "- sectionStats", sectionStats );    }    // Assertions before/ after    void assertionStarting( Catch::AssertionInfo const& assertionInfo ) override {        std::cout << "\nEvent: assertionStarting:\n";        print( std::cout, 1, "- assertionInfo", assertionInfo );    }    void assertionEnded( Catch::AssertionStats const& assertionStats ) override {        std::cout << "\nEvent: assertionEnded:\n";        print( std::cout, 1, "- assertionStats", assertionStats );    }};} // end anonymous namespaceCATCH_REGISTER_LISTENER( MyListener )// Get rid of Wweak-tablesMyListener::~MyListener() {}// -----------------------------------------------------------------------// 3. Test cases://TEST_CASE( "1: Hidden testcase", "[.hidden]" ) {}TEST_CASE( "2: Testcase with sections", "[tag-A][tag-B]" ) {    int i = 42;    REQUIRE( i == 42 );    SECTION("Section 1") {        INFO("Section 1");        i = 7;        SECTION("Section 1.1") {            INFO("Section 1.1");            REQUIRE( i == 42 );        }    }    SECTION("Section 2") {        INFO("Section 2");        REQUIRE( i == 42 );    }    WARN("At end of test case");}struct Fixture {    int fortytwo() const {        return 42;    }};TEST_CASE_METHOD( Fixture, "3: Testcase with class-based fixture", "[tag-C][tag-D]" ) {    REQUIRE( fortytwo() == 42 );}// Compile & run:// - g++ -std=c++14 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 210-Evt-EventListeners 210-Evt-EventListeners.cpp && 210-Evt-EventListeners --success// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 210-Evt-EventListeners.cpp && 210-Evt-EventListeners --success// Expected compact output (all assertions)://// prompt> 210-Evt-EventListeners --reporter compact --success// result omitted for brevity.
 |