mirror of https://github.com/catchorg/Catch2.git
Refactored stream related stuff
- simpler, polymorphic hierarchy-based, approach - less bitty conditionals spread across the code - all resolved up-front so now config class is immutable (it had evolved the way it was and in need of a clean-up sweep for a long time)
This commit is contained in:
parent
a0de07d45b
commit
d43a47efca
|
@ -52,25 +52,11 @@ namespace Catch {
|
|||
return reporters;
|
||||
}
|
||||
|
||||
void openStreamInto( Ptr<Config> const& config, std::ofstream& ofs ) {
|
||||
// Open output file, if specified
|
||||
if( !config->getFilename().empty() ) {
|
||||
ofs.open( config->getFilename().c_str() );
|
||||
if( ofs.fail() ) {
|
||||
std::ostringstream oss;
|
||||
oss << "Unable to open file: '" << config->getFilename() << "'";
|
||||
throw std::domain_error( oss.str() );
|
||||
}
|
||||
config->setStreamBuf( ofs.rdbuf() );
|
||||
}
|
||||
}
|
||||
|
||||
Totals runTests( Ptr<Config> const& config ) {
|
||||
|
||||
Ptr<IConfig const> iconfig = config.get();
|
||||
|
||||
std::ofstream ofs;
|
||||
openStreamInto( config, ofs );
|
||||
Ptr<IStreamingReporter> reporter = makeReporter( config );
|
||||
reporter = addListeners( iconfig, reporter );
|
||||
|
||||
|
|
|
@ -85,12 +85,11 @@ namespace Catch {
|
|||
public:
|
||||
|
||||
Config()
|
||||
: m_os( Catch::cout().rdbuf() )
|
||||
{}
|
||||
|
||||
Config( ConfigData const& data )
|
||||
: m_data( data ),
|
||||
m_os( Catch::cout().rdbuf() )
|
||||
m_stream( openStream() )
|
||||
{
|
||||
if( !data.testsOrTags.empty() ) {
|
||||
TestSpecParser parser( ITagAliasRegistry::get() );
|
||||
|
@ -101,12 +100,6 @@ namespace Catch {
|
|||
}
|
||||
|
||||
virtual ~Config() {
|
||||
m_os.rdbuf( Catch::cout().rdbuf() );
|
||||
m_stream.release();
|
||||
}
|
||||
|
||||
void setFilename( std::string const& filename ) {
|
||||
m_data.outputFilename = filename;
|
||||
}
|
||||
|
||||
std::string const& getFilename() const {
|
||||
|
@ -122,17 +115,6 @@ namespace Catch {
|
|||
|
||||
bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
|
||||
|
||||
void setStreamBuf( std::streambuf* buf ) {
|
||||
m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() );
|
||||
}
|
||||
|
||||
void useStream( std::string const& streamName ) {
|
||||
Stream stream = createStream( streamName );
|
||||
setStreamBuf( stream.streamBuf );
|
||||
m_stream.release();
|
||||
m_stream = stream;
|
||||
}
|
||||
|
||||
std::vector<std::string> getReporterNames() const { return m_data.reporterNames; }
|
||||
|
||||
int abortAfter() const { return m_data.abortAfter; }
|
||||
|
@ -144,7 +126,7 @@ namespace Catch {
|
|||
|
||||
// IConfig interface
|
||||
virtual bool allowThrows() const { return !m_data.noThrow; }
|
||||
virtual std::ostream& stream() const { return m_os; }
|
||||
virtual std::ostream& stream() const { return m_stream->stream(); }
|
||||
virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
|
||||
virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
|
||||
virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
|
||||
|
@ -154,10 +136,22 @@ namespace Catch {
|
|||
virtual bool forceColour() const { return m_data.forceColour; }
|
||||
|
||||
private:
|
||||
|
||||
IStream const* openStream() {
|
||||
if( m_data.outputFilename.empty() )
|
||||
return new CoutStream();
|
||||
else if( m_data.outputFilename[0] == '%' ) {
|
||||
if( m_data.outputFilename == "%debug" )
|
||||
return new DebugOutStream();
|
||||
else
|
||||
throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
|
||||
}
|
||||
else
|
||||
return new FileStream( m_data.outputFilename );
|
||||
}
|
||||
ConfigData m_data;
|
||||
|
||||
Stream m_stream;
|
||||
mutable std::ostream m_os;
|
||||
std::auto_ptr<IStream const> m_stream;
|
||||
TestSpec m_testSpec;
|
||||
};
|
||||
|
||||
|
|
|
@ -95,14 +95,6 @@ namespace Catch {
|
|||
return getCurrentMutableContext();
|
||||
}
|
||||
|
||||
Stream createStream( std::string const& streamName ) {
|
||||
if( streamName == "stdout" ) return Stream( Catch::cout().rdbuf(), false );
|
||||
if( streamName == "stderr" ) return Stream( Catch::cerr().rdbuf(), false );
|
||||
if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
|
||||
|
||||
throw std::domain_error( "Unknown stream: " + streamName );
|
||||
}
|
||||
|
||||
void cleanUpContext() {
|
||||
delete currentContext;
|
||||
currentContext = CATCH_NULL;
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
namespace Catch {
|
||||
NonCopyable::~NonCopyable() {}
|
||||
IShared::~IShared() {}
|
||||
IStream::~IStream() CATCH_NOEXCEPT {}
|
||||
StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
|
||||
IContext::~IContext() {}
|
||||
IResultCapture::~IResultCapture() {}
|
||||
|
|
|
@ -9,28 +9,52 @@
|
|||
#ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||
|
||||
#include <streambuf>
|
||||
#include "catch_compiler_capabilities.h"
|
||||
#include "catch_streambuf.h"
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wpadded"
|
||||
#endif
|
||||
#include <streambuf>
|
||||
#include <ostream>
|
||||
#include <fstream>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class Stream {
|
||||
public:
|
||||
Stream();
|
||||
Stream( std::streambuf* _streamBuf, bool _isOwned );
|
||||
void release();
|
||||
|
||||
std::streambuf* streamBuf;
|
||||
|
||||
private:
|
||||
bool isOwned;
|
||||
};
|
||||
|
||||
std::ostream& cout();
|
||||
std::ostream& cerr();
|
||||
|
||||
|
||||
struct IStream {
|
||||
virtual ~IStream() CATCH_NOEXCEPT;
|
||||
virtual std::ostream& stream() const = 0;
|
||||
};
|
||||
|
||||
class FileStream : public IStream {
|
||||
mutable std::ofstream m_ofs;
|
||||
public:
|
||||
FileStream( std::string const& filename );
|
||||
public: // IStream
|
||||
virtual std::ostream& stream() const CATCH_OVERRIDE;
|
||||
};
|
||||
|
||||
|
||||
class CoutStream : public IStream {
|
||||
mutable std::ostream m_os;
|
||||
public:
|
||||
CoutStream();
|
||||
|
||||
public: // IStream
|
||||
virtual std::ostream& stream() const CATCH_OVERRIDE;
|
||||
};
|
||||
|
||||
|
||||
class DebugOutStream : public IStream {
|
||||
std::auto_ptr<StreamBufBase> m_streamBuf;
|
||||
mutable std::ostream m_os;
|
||||
public:
|
||||
DebugOutStream();
|
||||
|
||||
public: // IStream
|
||||
virtual std::ostream& stream() const CATCH_OVERRIDE;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
|
||||
|
||||
#include "catch_stream.h"
|
||||
#include "catch_streambuf.h"
|
||||
#include "catch_debugger.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
@ -57,6 +56,20 @@ namespace Catch {
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
FileStream::FileStream( std::string const& filename ) {
|
||||
m_ofs.open( filename.c_str() );
|
||||
if( m_ofs.fail() ) {
|
||||
std::ostringstream oss;
|
||||
oss << "Unable to open file: '" << filename << "'";
|
||||
throw std::domain_error( oss.str() );
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& FileStream::stream() const {
|
||||
return m_ofs;
|
||||
}
|
||||
|
||||
struct OutputDebugWriter {
|
||||
|
||||
void operator()( std::string const&str ) {
|
||||
|
@ -64,22 +77,26 @@ namespace Catch {
|
|||
}
|
||||
};
|
||||
|
||||
Stream::Stream()
|
||||
: streamBuf( CATCH_NULL ), isOwned( false )
|
||||
DebugOutStream::DebugOutStream()
|
||||
: m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
|
||||
m_os( m_streamBuf.get() )
|
||||
{}
|
||||
|
||||
Stream::Stream( std::streambuf* _streamBuf, bool _isOwned )
|
||||
: streamBuf( _streamBuf ), isOwned( _isOwned )
|
||||
{}
|
||||
|
||||
void Stream::release() {
|
||||
if( isOwned ) {
|
||||
delete streamBuf;
|
||||
streamBuf = CATCH_NULL;
|
||||
isOwned = false;
|
||||
}
|
||||
std::ostream& DebugOutStream::stream() const {
|
||||
return m_os;
|
||||
}
|
||||
|
||||
// Store the streambuf from cout up-front because
|
||||
// cout may get redirected when running tests
|
||||
CoutStream::CoutStream()
|
||||
: m_os( Catch::cout().rdbuf() )
|
||||
{}
|
||||
|
||||
std::ostream& CoutStream::stream() const {
|
||||
return m_os;
|
||||
}
|
||||
|
||||
|
||||
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions
|
||||
std::ostream& cout() {
|
||||
return std::cout;
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
// This file is only here to verify (to the extent possible) the self sufficiency of the header
|
||||
#include "catch_suppress_warnings.h"
|
||||
#include "catch_stream.h"
|
||||
|
|
Loading…
Reference in New Issue