mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-08 23:29:53 +01:00
ed7eaf2df3
Each of the two reporter bases now has its own header file, and cpp file. Even though this adds another TU to the compilation, the total CPU time taken by compilation is reduced by about 1% for debug build and ~0.5% for optimized build of the main library. (The improvement would be roughly doubles without splitting the TUs, but the maintainability hit is not worth it.) The code size of the static library build has also somewhat decreased. Follow up: Introduce combined TU for reporters, and further split apart the catch_reporter_streaming_base.hpp header into its constituent parts, as it still contains a whole bunch of other stuff.
431 lines
15 KiB
C++
431 lines
15 KiB
C++
// 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_streaming_base.hpp>
|
|
#include <catch2/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 << "lower cased: " << t.lowerCased;
|
|
}
|
|
|
|
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::TestEventListenerBase {
|
|
|
|
using TestEventListenerBase::TestEventListenerBase; // inherit constructor
|
|
|
|
// Get rid of Wweak-tables
|
|
~MyListener();
|
|
|
|
// 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 );
|
|
}
|
|
|
|
bool assertionEnded( Catch::AssertionStats const& assertionStats ) override {
|
|
std::cout << "\nEvent: assertionEnded:\n";
|
|
print( std::cout, 1, "- assertionStats", assertionStats );
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
CATCH_REGISTER_LISTENER( MyListener )
|
|
|
|
// Get rid of Wweak-tables
|
|
MyListener::~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++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 210-Evt-EventListeners 210-Evt-EventListeners.cpp 000-CatchMain.o && 210-Evt-EventListeners --success
|
|
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 210-Evt-EventListeners.cpp 000-CatchMain.obj && 210-Evt-EventListeners --success
|
|
|
|
// Expected compact output (all assertions):
|
|
//
|
|
// prompt> 210-Evt-EventListeners --reporter compact --success
|
|
// result omitted for brevity.
|