mirror of
https://github.com/catchorg/Catch2.git
synced 2024-12-23 03:43:28 +01:00
Capture std::clog writes and combine them with std::cerr writes (#989)
This also introduces Catch::clog() method to allow embedded targets to override std::clog usage with their own stream (presumably null-sink), similarly to how Catch::cout() and Catch::cerr() are used. Fixes #989
This commit is contained in:
parent
92d714ee12
commit
7e4038d848
@ -22,6 +22,7 @@
|
||||
#include "catch_result_builder.h"
|
||||
#include "catch_fatal_condition.hpp"
|
||||
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
@ -50,6 +51,29 @@ namespace Catch {
|
||||
std::string& m_targetString;
|
||||
};
|
||||
|
||||
// StdErr has two constituent streams in C++, std::cerr and std::clog
|
||||
// This means that we need to redirect 2 streams into 1 to keep proper
|
||||
// order of writes and cannot use StreamRedirect on its own
|
||||
class StdErrRedirect {
|
||||
public:
|
||||
StdErrRedirect(std::string& targetString)
|
||||
:m_cerrBuf( cerr().rdbuf() ), m_clogBuf(clog().rdbuf()),
|
||||
m_targetString(targetString){
|
||||
cerr().rdbuf(m_oss.rdbuf());
|
||||
clog().rdbuf(m_oss.rdbuf());
|
||||
}
|
||||
~StdErrRedirect() {
|
||||
m_targetString += m_oss.str();
|
||||
cerr().rdbuf(m_cerrBuf);
|
||||
clog().rdbuf(m_clogBuf);
|
||||
}
|
||||
private:
|
||||
std::streambuf* m_cerrBuf;
|
||||
std::streambuf* m_clogBuf;
|
||||
std::ostringstream m_oss;
|
||||
std::string& m_targetString;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class RunContext : public IResultCapture, public IRunner {
|
||||
@ -305,7 +329,7 @@ namespace Catch {
|
||||
timer.start();
|
||||
if( m_reporter->getPreferences().shouldRedirectStdOut ) {
|
||||
StreamRedirect coutRedir( Catch::cout(), redirectedCout );
|
||||
StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
|
||||
StdErrRedirect errRedir( redirectedCerr );
|
||||
invokeActiveTestCase();
|
||||
}
|
||||
else {
|
||||
|
@ -21,6 +21,7 @@ namespace Catch {
|
||||
|
||||
std::ostream& cout();
|
||||
std::ostream& cerr();
|
||||
std::ostream& clog();
|
||||
|
||||
|
||||
struct IStream {
|
||||
|
@ -103,6 +103,9 @@ namespace Catch {
|
||||
std::ostream& cerr() {
|
||||
return std::cerr;
|
||||
}
|
||||
std::ostream& clog() {
|
||||
return std::clog;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -622,6 +622,9 @@ with messages:
|
||||
|
||||
A string sent directly to stdout
|
||||
A string sent directly to stderr
|
||||
Write to std::cerr
|
||||
Write to std::clog
|
||||
Interleaved writes to error streams
|
||||
Message from section one
|
||||
Message from section two
|
||||
-------------------------------------------------------------------------------
|
||||
@ -953,6 +956,6 @@ with expansion:
|
||||
"first" == "second"
|
||||
|
||||
===============================================================================
|
||||
test cases: 168 | 119 passed | 45 failed | 4 failed as expected
|
||||
test cases: 169 | 120 passed | 45 failed | 4 failed as expected
|
||||
assertions: 968 | 859 passed | 88 failed | 21 failed as expected
|
||||
|
||||
|
@ -6786,6 +6786,39 @@ PASSED:
|
||||
with expansion:
|
||||
Approx( 1.23 ) != 1.24
|
||||
|
||||
Write to std::cerr
|
||||
-------------------------------------------------------------------------------
|
||||
Standard error is reported and redirected
|
||||
std::cerr
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in section 'std::cerr'
|
||||
|
||||
Write to std::clog
|
||||
-------------------------------------------------------------------------------
|
||||
Standard error is reported and redirected
|
||||
std::clog
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in section 'std::clog'
|
||||
|
||||
Interleaved writes to error streams
|
||||
-------------------------------------------------------------------------------
|
||||
Standard error is reported and redirected
|
||||
Interleaved writes to cerr and clog
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in section 'Interleaved writes to cerr and clog'
|
||||
|
||||
Message from section one
|
||||
-------------------------------------------------------------------------------
|
||||
Standard output from all sections is reported
|
||||
@ -9483,6 +9516,6 @@ MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
|
||||
===============================================================================
|
||||
test cases: 168 | 118 passed | 46 failed | 4 failed as expected
|
||||
assertions: 970 | 859 passed | 90 failed | 21 failed as expected
|
||||
test cases: 169 | 118 passed | 47 failed | 4 failed as expected
|
||||
assertions: 973 | 859 passed | 93 failed | 21 failed as expected
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuitesspanner>
|
||||
<testsuite name="<exe-name>" errors="13" failures="78" tests="971" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="13" failures="81" tests="974" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testcase classname="global" name="# A test name that starts with a #" time="{duration}"/>
|
||||
<testcase classname="#748 - captures with unexpected exceptions" name="outside assertions" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
@ -475,6 +475,13 @@ A string sent directly to stderr
|
||||
</system-err>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Some simple comparisons between doubles" time="{duration}"/>
|
||||
<testcase classname="Standard error is reported and redirected" name="Interleaved writes to cerr and clog" time="{duration}">
|
||||
<system-err>
|
||||
Write to std::cerr
|
||||
Write to std::clog
|
||||
Interleaved writes to error streams
|
||||
</system-err>
|
||||
</testcase>
|
||||
<testcase classname="Standard output from all sections is reported" name="two" time="{duration}">
|
||||
<system-out>
|
||||
Message from section one
|
||||
@ -750,6 +757,9 @@ hello
|
||||
</system-out>
|
||||
<system-err>
|
||||
A string sent directly to stderr
|
||||
Write to std::cerr
|
||||
Write to std::clog
|
||||
Interleaved writes to error streams
|
||||
</system-err>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
@ -7309,6 +7309,24 @@ A string sent directly to stderr
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="Standard error is reported and redirected" tags="[.][hide][messages]" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<Section name="std::cerr" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<OverallResults successes="0" failures="1" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="std::clog" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<OverallResults successes="0" failures="1" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="Interleaved writes to cerr and clog" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<OverallResults successes="0" failures="1" expectedFailures="0"/>
|
||||
</Section>
|
||||
<OverallResult success="false">
|
||||
<StdErr>
|
||||
Write to std::cerr
|
||||
Write to std::clog
|
||||
Interleaved writes to error streams
|
||||
</StdErr>
|
||||
</OverallResult>
|
||||
</TestCase>
|
||||
<TestCase name="Standard output from all sections is reported" tags="[.][hide][messages]" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<Section name="one" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<OverallResults successes="0" failures="1" expectedFailures="0"/>
|
||||
@ -10143,7 +10161,7 @@ spanner <OverallResult success="true"/>
|
||||
</Section>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<OverallResults successes="859" failures="91" expectedFailures="21"/>
|
||||
<OverallResults successes="859" failures="94" expectedFailures="21"/>
|
||||
</Group>
|
||||
<OverallResults successes="859" failures="90" expectedFailures="21"/>
|
||||
<OverallResults successes="859" failures="93" expectedFailures="21"/>
|
||||
</Catch>
|
||||
|
@ -99,6 +99,23 @@ TEST_CASE( "Standard output from all sections is reported", "[messages][.]" )
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Standard error is reported and redirected", "[messages][.]" ) {
|
||||
SECTION( "std::cerr" ) {
|
||||
std::cerr << "Write to std::cerr" << std::endl;
|
||||
}
|
||||
SECTION( "std::clog" ) {
|
||||
std::clog << "Write to std::clog" << std::endl;
|
||||
}
|
||||
SECTION( "Interleaved writes to cerr and clog" ) {
|
||||
std::cerr << "Inter";
|
||||
std::clog << "leaved";
|
||||
std::cerr << ' ';
|
||||
std::clog << "writes";
|
||||
std::cerr << " to error";
|
||||
std::clog << " streams\n";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "SCOPED_INFO is reset for each loop", "[messages][failing][.]" )
|
||||
{
|
||||
for( int i=0; i<100; i++ )
|
||||
|
Loading…
Reference in New Issue
Block a user