Devirtualize handling of ReporterPreferences

The new scheme is that there is one protected member instance of
`ReporterPreferences` in the `IStreamingReporter` base class,
and derived classes can modify it to express their own preferences.

Retrieving the preferences is now a non-virtual operation, which
makes it much cheaper to read them frequently. Previously, we
avoided doing so by caching the preferences in another variable,
but we still read them at least once per test case run.
This commit is contained in:
Martin Hořeňovský 2020-07-28 09:24:57 +02:00
parent d218d6f9e2
commit d090074da7
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
9 changed files with 32 additions and 41 deletions

View File

@ -46,11 +46,6 @@ namespace Catch {
IConfig const* m_fullConfig;
};
struct ReporterPreferences {
bool shouldRedirectStdOut = false;
bool shouldReportAllAssertions = false;
};
template<typename T>
struct LazyStat : Option<T> {
LazyStat& operator=( T const& _value ) {
@ -178,13 +173,32 @@ namespace Catch {
}
};
//! By setting up its preferences, a reporter can modify Catch2's behaviour
//! in some regards, e.g. it can request Catch2 to capture writes to
//! stdout/stderr during test execution, and pass them to the reporter.
struct ReporterPreferences {
//! Catch2 should redirect writes to stdout and pass them to the
//! reporter
bool shouldRedirectStdOut = false;
//! Catch2 should call `Reporter::assertionEnded` even for passing
//! assertions
bool shouldReportAllAssertions = false;
};
struct IStreamingReporter {
protected:
//! Derived classes can set up their preferences here
ReporterPreferences m_preferences;
public:
virtual ~IStreamingReporter() = default;
// Implementing class must also provide the following static methods:
// static std::string getDescription();
virtual ReporterPreferences getPreferences() const = 0;
ReporterPreferences const& getPreferences() const {
return m_preferences;
}
virtual void noMatchingTestCases( std::string const& spec ) = 0;

View File

@ -29,16 +29,10 @@ namespace Catch {
struct StreamingReporterBase : IStreamingReporter {
StreamingReporterBase( ReporterConfig const& _config )
: m_config( _config.fullConfig() ),
stream( _config.stream() )
{
m_reporterPrefs.shouldRedirectStdOut = false;
StreamingReporterBase( ReporterConfig const& _config ):
m_config( _config.fullConfig() ), stream( _config.stream() ) {
}
ReporterPreferences getPreferences() const override {
return m_reporterPrefs;
}
~StreamingReporterBase() override;
@ -83,7 +77,6 @@ namespace Catch {
TestCaseInfo const* currentTestCaseInfo;
std::vector<SectionInfo> m_sectionStack;
ReporterPreferences m_reporterPrefs;
};
struct CumulativeReporterBase : IStreamingReporter {
@ -117,18 +110,10 @@ namespace Catch {
using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
using TestRunNode = Node<TestRunStats, TestGroupNode>;
CumulativeReporterBase( ReporterConfig const& _config )
: m_config( _config.fullConfig() ),
stream( _config.stream() )
{
m_reporterPrefs.shouldRedirectStdOut = false;
}
CumulativeReporterBase( ReporterConfig const& _config ):
m_config( _config.fullConfig() ), stream( _config.stream() ) {}
~CumulativeReporterBase() override;
ReporterPreferences getPreferences() const override {
return m_reporterPrefs;
}
void testRunStarting( TestRunInfo const& ) override {}
void testGroupStarting( GroupInfo const& ) override {}
@ -159,7 +144,6 @@ namespace Catch {
std::shared_ptr<SectionNode> m_rootSection;
std::shared_ptr<SectionNode> m_deepestSection;
std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
ReporterPreferences m_reporterPrefs;
};
struct lineOfChars {

View File

@ -67,8 +67,8 @@ namespace Catch {
: CumulativeReporterBase( _config ),
xml( _config.stream() )
{
m_reporterPrefs.shouldRedirectStdOut = true;
m_reporterPrefs.shouldReportAllAssertions = true;
m_preferences.shouldRedirectStdOut = true;
m_preferences.shouldReportAllAssertions = true;
}
JunitReporter::~JunitReporter() {}

View File

@ -26,10 +26,6 @@ namespace Catch {
m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut;
}
ReporterPreferences ListeningReporter::getPreferences() const {
return m_preferences;
}
void ListeningReporter::noMatchingTestCases( std::string const& spec ) {
for ( auto const& listener : m_listeners ) {
listener->noMatchingTestCases( spec );

View File

@ -15,7 +15,6 @@ namespace Catch {
using Reporters = std::vector<IStreamingReporterPtr>;
Reporters m_listeners;
IStreamingReporterPtr m_reporter = nullptr;
ReporterPreferences m_preferences;
public:
ListeningReporter();
@ -25,8 +24,6 @@ namespace Catch {
public: // IStreamingReporter
ReporterPreferences getPreferences() const override;
void noMatchingTestCases( std::string const& spec ) override;
void reportInvalidArguments(std::string const&arg) override;

View File

@ -16,8 +16,8 @@ namespace Catch {
SonarQubeReporter(ReporterConfig const& config)
: CumulativeReporterBase(config)
, xml(config.stream()) {
m_reporterPrefs.shouldRedirectStdOut = true;
m_reporterPrefs.shouldReportAllAssertions = true;
m_preferences.shouldRedirectStdOut = true;
m_preferences.shouldReportAllAssertions = true;
}
~SonarQubeReporter() override;

View File

@ -13,7 +13,7 @@ namespace Catch {
TAPReporter( ReporterConfig const& config ):
StreamingReporterBase( config ) {
m_reporterPrefs.shouldReportAllAssertions = true;
m_preferences.shouldReportAllAssertions = true;
}
~TAPReporter() override;

View File

@ -21,7 +21,7 @@ namespace Catch {
TeamCityReporter( ReporterConfig const& _config )
: StreamingReporterBase( _config )
{
m_reporterPrefs.shouldRedirectStdOut = true;
m_preferences.shouldRedirectStdOut = true;
}
~TeamCityReporter() override;

View File

@ -23,8 +23,8 @@ namespace Catch {
: StreamingReporterBase( _config ),
m_xml(_config.stream())
{
m_reporterPrefs.shouldRedirectStdOut = true;
m_reporterPrefs.shouldReportAllAssertions = true;
m_preferences.shouldRedirectStdOut = true;
m_preferences.shouldReportAllAssertions = true;
}
XmlReporter::~XmlReporter() = default;