Refactored StreamRedirect classes

This commit is contained in:
Phil Nash 2017-12-05 23:19:28 +00:00
parent 7c5a21fb7d
commit aa9d635014
2 changed files with 43 additions and 50 deletions

View File

@ -10,30 +10,47 @@
namespace Catch { namespace Catch {
StreamRedirect::StreamRedirect(std::ostream& stream, std::string& targetString) class RedirectedStream {
: m_stream(stream), std::ostream& m_originalStream;
m_prevBuf(stream.rdbuf()), std::ostream& m_redirectionStream;
m_targetString(targetString) { std::streambuf* m_prevBuf;
stream.rdbuf(m_oss.get().rdbuf());
}
StreamRedirect::~StreamRedirect() { public:
m_targetString += m_oss.str(); RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
m_stream.rdbuf(m_prevBuf); : m_originalStream( originalStream ),
} m_redirectionStream( redirectionStream ),
m_prevBuf( m_originalStream.rdbuf() )
{
m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
}
~RedirectedStream() {
m_originalStream.rdbuf( m_prevBuf );
}
};
StdErrRedirect::StdErrRedirect(std::string & targetString) class RedirectedStdOut {
:m_cerrBuf(cerr().rdbuf()), m_clogBuf(clog().rdbuf()), ReusableStringStream m_rss;
m_targetString(targetString) { RedirectedStream m_cout;
cerr().rdbuf(m_oss.get().rdbuf()); public:
clog().rdbuf(m_oss.get().rdbuf()); RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
} auto str() const -> std::string { return m_rss.str(); }
};
// 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
class RedirectedStdErr {
ReusableStringStream m_rss;
RedirectedStream m_cerr;
RedirectedStream m_clog;
public:
RedirectedStdErr()
: m_cerr( Catch::cerr(), m_rss.get() ),
m_clog( Catch::clog(), m_rss.get() )
{}
auto str() const -> std::string { return m_rss.str(); }
};
StdErrRedirect::~StdErrRedirect() {
m_targetString += m_oss.str();
cerr().rdbuf(m_cerrBuf);
clog().rdbuf(m_clogBuf);
}
RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
: m_runInfo(_config->name()), : m_runInfo(_config->name()),
@ -282,10 +299,13 @@ namespace Catch {
Timer timer; Timer timer;
try { try {
if (m_reporter->getPreferences().shouldRedirectStdOut) { if (m_reporter->getPreferences().shouldRedirectStdOut) {
StreamRedirect coutRedir(cout(), redirectedCout); RedirectedStdOut redirectedStdOut;
StdErrRedirect errRedir(redirectedCerr); RedirectedStdErr redirectedStdErr;
timer.start(); timer.start();
invokeActiveTestCase(); invokeActiveTestCase();
redirectedCout += redirectedStdOut.str();
redirectedCerr += redirectedStdErr.str();
} else { } else {
timer.start(); timer.start();
invokeActiveTestCase(); invokeActiveTestCase();

View File

@ -28,33 +28,6 @@ namespace Catch {
struct IMutableContext; struct IMutableContext;
class StreamRedirect {
public:
StreamRedirect(std::ostream& stream, std::string& targetString);
~StreamRedirect();
private:
std::ostream& m_stream;
std::streambuf* m_prevBuf;
ReusableStringStream m_oss;
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:
explicit StdErrRedirect( std::string& targetString );
~StdErrRedirect();
private:
std::streambuf* m_cerrBuf;
std::streambuf* m_clogBuf;
ReusableStringStream m_oss;
std::string& m_targetString;
};
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
class RunContext : public IResultCapture, public IRunner { class RunContext : public IResultCapture, public IRunner {