mirror of
https://github.com/catchorg/Catch2.git
synced 2024-12-23 11:43:29 +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_result_builder.h"
|
||||||
#include "catch_fatal_condition.hpp"
|
#include "catch_fatal_condition.hpp"
|
||||||
|
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -50,6 +51,29 @@ namespace Catch {
|
|||||||
std::string& m_targetString;
|
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 {
|
class RunContext : public IResultCapture, public IRunner {
|
||||||
@ -305,7 +329,7 @@ namespace Catch {
|
|||||||
timer.start();
|
timer.start();
|
||||||
if( m_reporter->getPreferences().shouldRedirectStdOut ) {
|
if( m_reporter->getPreferences().shouldRedirectStdOut ) {
|
||||||
StreamRedirect coutRedir( Catch::cout(), redirectedCout );
|
StreamRedirect coutRedir( Catch::cout(), redirectedCout );
|
||||||
StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
|
StdErrRedirect errRedir( redirectedCerr );
|
||||||
invokeActiveTestCase();
|
invokeActiveTestCase();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -21,6 +21,7 @@ namespace Catch {
|
|||||||
|
|
||||||
std::ostream& cout();
|
std::ostream& cout();
|
||||||
std::ostream& cerr();
|
std::ostream& cerr();
|
||||||
|
std::ostream& clog();
|
||||||
|
|
||||||
|
|
||||||
struct IStream {
|
struct IStream {
|
||||||
|
@ -103,6 +103,9 @@ namespace Catch {
|
|||||||
std::ostream& cerr() {
|
std::ostream& cerr() {
|
||||||
return std::cerr;
|
return std::cerr;
|
||||||
}
|
}
|
||||||
|
std::ostream& clog() {
|
||||||
|
return std::clog;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,6 +622,9 @@ with messages:
|
|||||||
|
|
||||||
A string sent directly to stdout
|
A string sent directly to stdout
|
||||||
A string sent directly to stderr
|
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 one
|
||||||
Message from section two
|
Message from section two
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -953,6 +956,6 @@ with expansion:
|
|||||||
"first" == "second"
|
"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
|
assertions: 968 | 859 passed | 88 failed | 21 failed as expected
|
||||||
|
|
||||||
|
@ -6786,6 +6786,39 @@ PASSED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
Approx( 1.23 ) != 1.24
|
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
|
Message from section one
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Standard output from all sections is reported
|
Standard output from all sections is reported
|
||||||
@ -9483,6 +9516,6 @@ MiscTests.cpp:<line number>:
|
|||||||
PASSED:
|
PASSED:
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 168 | 118 passed | 46 failed | 4 failed as expected
|
test cases: 169 | 118 passed | 47 failed | 4 failed as expected
|
||||||
assertions: 970 | 859 passed | 90 failed | 21 failed as expected
|
assertions: 973 | 859 passed | 93 failed | 21 failed as expected
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<testsuitesspanner>
|
<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="global" name="# A test name that starts with a #" time="{duration}"/>
|
||||||
<testcase classname="#748 - captures with unexpected exceptions" name="outside assertions" time="{duration}">
|
<testcase classname="#748 - captures with unexpected exceptions" name="outside assertions" time="{duration}">
|
||||||
<error type="TEST_CASE">
|
<error type="TEST_CASE">
|
||||||
@ -475,6 +475,13 @@ A string sent directly to stderr
|
|||||||
</system-err>
|
</system-err>
|
||||||
</testcase>
|
</testcase>
|
||||||
<testcase classname="global" name="Some simple comparisons between doubles" time="{duration}"/>
|
<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}">
|
<testcase classname="Standard output from all sections is reported" name="two" time="{duration}">
|
||||||
<system-out>
|
<system-out>
|
||||||
Message from section one
|
Message from section one
|
||||||
@ -750,6 +757,9 @@ hello
|
|||||||
</system-out>
|
</system-out>
|
||||||
<system-err>
|
<system-err>
|
||||||
A string sent directly to stderr
|
A string sent directly to stderr
|
||||||
|
Write to std::cerr
|
||||||
|
Write to std::clog
|
||||||
|
Interleaved writes to error streams
|
||||||
</system-err>
|
</system-err>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
|
@ -7309,6 +7309,24 @@ A string sent directly to stderr
|
|||||||
</Expression>
|
</Expression>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</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" >
|
<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" >
|
<Section name="one" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||||
<OverallResults successes="0" failures="1" expectedFailures="0"/>
|
<OverallResults successes="0" failures="1" expectedFailures="0"/>
|
||||||
@ -10143,7 +10161,7 @@ spanner <OverallResult success="true"/>
|
|||||||
</Section>
|
</Section>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<OverallResults successes="859" failures="91" expectedFailures="21"/>
|
<OverallResults successes="859" failures="94" expectedFailures="21"/>
|
||||||
</Group>
|
</Group>
|
||||||
<OverallResults successes="859" failures="90" expectedFailures="21"/>
|
<OverallResults successes="859" failures="93" expectedFailures="21"/>
|
||||||
</Catch>
|
</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][.]" )
|
TEST_CASE( "SCOPED_INFO is reset for each loop", "[messages][failing][.]" )
|
||||||
{
|
{
|
||||||
for( int i=0; i<100; i++ )
|
for( int i=0; i<100; i++ )
|
||||||
|
Loading…
Reference in New Issue
Block a user