mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 14:09:33 +01:00 
			
		
		
		
	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:
		@@ -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,29 +56,47 @@ namespace Catch {
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
    struct OutputDebugWriter {
 | 
			
		||||
 | 
			
		||||
    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 ) {
 | 
			
		||||
            writeToDebugConsole( str );
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user