mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 12:17:11 +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:
		| @@ -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,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
	 Phil Nash
					Phil Nash