diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fdf30a87..fb859db9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -76,6 +76,7 @@ set(INTERNAL_HEADERS ${SOURCES_DIR}/internal/catch_exception_translator_registry.hpp ${SOURCES_DIR}/internal/catch_fatal_condition_handler.hpp ${SOURCES_DIR}/internal/catch_floating_point_helpers.hpp + ${SOURCES_DIR}/internal/catch_istream.hpp ${SOURCES_DIR}/internal/catch_unique_name.hpp ${SOURCES_DIR}/internal/catch_sharding.hpp ${SOURCES_DIR}/generators/catch_generator_exception.hpp @@ -181,6 +182,7 @@ set(IMPL_SOURCES ${SOURCES_DIR}/internal/catch_exception_translator_registry.cpp ${SOURCES_DIR}/internal/catch_fatal_condition_handler.cpp ${SOURCES_DIR}/internal/catch_floating_point_helpers.cpp + ${SOURCES_DIR}/internal/catch_istream.cpp ${SOURCES_DIR}/generators/internal/catch_generators_combined_tu.cpp ${SOURCES_DIR}/interfaces/catch_interfaces_combined_tu.cpp ${SOURCES_DIR}/interfaces/catch_interfaces_reporter.cpp diff --git a/src/catch2/catch_all.hpp b/src/catch2/catch_all.hpp index ce3f49d3..101eb834 100644 --- a/src/catch2/catch_all.hpp +++ b/src/catch2/catch_all.hpp @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include diff --git a/src/catch2/catch_session.cpp b/src/catch2/catch_session.cpp index c2047aa2..df92559b 100644 --- a/src/catch2/catch_session.cpp +++ b/src/catch2/catch_session.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include diff --git a/src/catch2/interfaces/catch_interfaces_reporter.cpp b/src/catch2/interfaces/catch_interfaces_reporter.cpp index 9a6cbdc2..b1ad584c 100644 --- a/src/catch2/interfaces/catch_interfaces_reporter.cpp +++ b/src/catch2/interfaces/catch_interfaces_reporter.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,8 @@ namespace Catch { return m_customOptions; } + ReporterConfig::~ReporterConfig() = default; + AssertionStats::AssertionStats( AssertionResult const& _assertionResult, std::vector const& _infoMessages, Totals const& _totals ) diff --git a/src/catch2/interfaces/catch_interfaces_reporter.hpp b/src/catch2/interfaces/catch_interfaces_reporter.hpp index 1e6c2590..1a2736f7 100644 --- a/src/catch2/interfaces/catch_interfaces_reporter.hpp +++ b/src/catch2/interfaces/catch_interfaces_reporter.hpp @@ -40,6 +40,10 @@ namespace Catch { ColourMode colourMode, std::map customOptions ); + ReporterConfig( ReporterConfig&& ) = default; + ReporterConfig& operator=( ReporterConfig&& ) = default; + ~ReporterConfig(); // = default + Detail::unique_ptr takeStream() &&; IConfig const* fullConfig() const; ColourMode colourMode() const; diff --git a/src/catch2/internal/catch_console_colour.cpp b/src/catch2/internal/catch_console_colour.cpp index 7f202490..f519fb86 100644 --- a/src/catch2/internal/catch_console_colour.cpp +++ b/src/catch2/internal/catch_console_colour.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/catch2/internal/catch_istream.cpp b/src/catch2/internal/catch_istream.cpp new file mode 100644 index 00000000..656813b3 --- /dev/null +++ b/src/catch2/internal/catch_istream.cpp @@ -0,0 +1,158 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace Catch { + + Catch::IStream::~IStream() = default; + +namespace Detail { + namespace { + template + class StreamBufImpl : public std::streambuf { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() noexcept { + StreamBufImpl::sync(); + } + + private: + int overflow( int c ) override { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() override { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + struct OutputDebugWriter { + + void operator()( std::string const& str ) { + if ( !str.empty() ) { + writeToDebugConsole( str ); + } + } + }; + + /////////////////////////////////////////////////////////////////////////// + + class FileStream : public IStream { + std::ofstream m_ofs; + public: + FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << '\'' ); + } + ~FileStream() override = default; + public: // IStream + std::ostream& stream() override { + return m_ofs; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + class CoutStream : public IStream { + std::ostream m_os; + public: + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream() : m_os( Catch::cout().rdbuf() ) {} + ~CoutStream() override = default; + + public: // IStream + std::ostream& stream() override { return m_os; } + bool isConsole() const override { return true; } + }; + + class CerrStream : public IStream { + std::ostream m_os; + + public: + // Store the streambuf from cerr up-front because + // cout may get redirected when running tests + CerrStream(): m_os( Catch::cerr().rdbuf() ) {} + ~CerrStream() override = default; + + public: // IStream + std::ostream& stream() override { return m_os; } + bool isConsole() const override { return true; } + }; + + /////////////////////////////////////////////////////////////////////////// + + class DebugOutStream : public IStream { + Detail::unique_ptr> m_streamBuf; + std::ostream m_os; + public: + DebugOutStream() + : m_streamBuf( Detail::make_unique>() ), + m_os( m_streamBuf.get() ) + {} + + ~DebugOutStream() override = default; + + public: // IStream + std::ostream& stream() override { return m_os; } + }; + + } // unnamed namespace +} // namespace Detail + + /////////////////////////////////////////////////////////////////////////// + + auto makeStream( std::string const& filename ) -> Detail::unique_ptr { + if ( filename.empty() || filename == "-" ) { + return Detail::make_unique(); + } + if( filename[0] == '%' ) { + if ( filename == "%debug" ) { + return Detail::make_unique(); + } else if ( filename == "%stderr" ) { + return Detail::make_unique(); + } else if ( filename == "%stdout" ) { + return Detail::make_unique(); + } else { + CATCH_ERROR( "Unrecognised stream: '" << filename << '\'' ); + } + } + return Detail::make_unique( filename ); + } + +} diff --git a/src/catch2/internal/catch_istream.hpp b/src/catch2/internal/catch_istream.hpp new file mode 100644 index 00000000..629816c8 --- /dev/null +++ b/src/catch2/internal/catch_istream.hpp @@ -0,0 +1,54 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 +#ifndef CATCH_ISTREAM_HPP_INCLUDED +#define CATCH_ISTREAM_HPP_INCLUDED + +#include +#include + +#include +#include +#include +#include + +namespace Catch { + + class IStream { + public: + virtual ~IStream(); // = default + virtual std::ostream& stream() = 0; + /** + * Best guess on whether the instance is writing to a console (e.g. via stdout/stderr) + * + * This is useful for e.g. Win32 colour support, because the Win32 + * API manipulates console directly, unlike POSIX escape codes, + * that can be written anywhere. + * + * Due to variety of ways to change where the stdout/stderr is + * _actually_ being written, users should always assume that + * the answer might be wrong. + */ + virtual bool isConsole() const { return false; } + }; + + /** + * Creates a stream wrapper that writes to specific file. + * + * Also recognizes 4 special filenames + * * `-` for stdout + * * `%stdout` for stdout + * * `%stderr` for stderr + * * `%debug` for platform specific debugging output + * + * \throws if passed an unrecognized %-prefixed stream + */ + auto makeStream( std::string const& filename ) -> Detail::unique_ptr; + +} + +#endif // CATCH_STREAM_HPP_INCLUDED diff --git a/src/catch2/internal/catch_stream.cpp b/src/catch2/internal/catch_stream.cpp index 64cfde0a..10eb4a9e 100644 --- a/src/catch2/internal/catch_stream.cpp +++ b/src/catch2/internal/catch_stream.cpp @@ -5,158 +5,16 @@ // https://www.boost.org/LICENSE_1_0.txt) // SPDX-License-Identifier: BSL-1.0 -#include #include -#include -#include #include #include -#include #include -#include #include #include namespace Catch { - Catch::IStream::~IStream() = default; - -namespace Detail { - namespace { - template - class StreamBufImpl : public std::streambuf { - char data[bufferSize]; - WriterF m_writer; - - public: - StreamBufImpl() { - setp( data, data + sizeof(data) ); - } - - ~StreamBufImpl() noexcept { - StreamBufImpl::sync(); - } - - private: - int overflow( int c ) override { - sync(); - - if( c != EOF ) { - if( pbase() == epptr() ) - m_writer( std::string( 1, static_cast( c ) ) ); - else - sputc( static_cast( c ) ); - } - return 0; - } - - int sync() override { - if( pbase() != pptr() ) { - m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); - setp( pbase(), epptr() ); - } - return 0; - } - }; - - /////////////////////////////////////////////////////////////////////////// - - struct OutputDebugWriter { - - void operator()( std::string const& str ) { - if ( !str.empty() ) { - writeToDebugConsole( str ); - } - } - }; - - /////////////////////////////////////////////////////////////////////////// - - class FileStream : public IStream { - std::ofstream m_ofs; - public: - FileStream( std::string const& filename ) { - m_ofs.open( filename.c_str() ); - CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << '\'' ); - } - ~FileStream() override = default; - public: // IStream - std::ostream& stream() override { - return m_ofs; - } - }; - - /////////////////////////////////////////////////////////////////////////// - - class CoutStream : public IStream { - std::ostream m_os; - public: - // Store the streambuf from cout up-front because - // cout may get redirected when running tests - CoutStream() : m_os( Catch::cout().rdbuf() ) {} - ~CoutStream() override = default; - - public: // IStream - std::ostream& stream() override { return m_os; } - bool isConsole() const override { return true; } - }; - - class CerrStream : public IStream { - std::ostream m_os; - - public: - // Store the streambuf from cerr up-front because - // cout may get redirected when running tests - CerrStream(): m_os( Catch::cerr().rdbuf() ) {} - ~CerrStream() override = default; - - public: // IStream - std::ostream& stream() override { return m_os; } - bool isConsole() const override { return true; } - }; - - /////////////////////////////////////////////////////////////////////////// - - class DebugOutStream : public IStream { - Detail::unique_ptr> m_streamBuf; - std::ostream m_os; - public: - DebugOutStream() - : m_streamBuf( Detail::make_unique>() ), - m_os( m_streamBuf.get() ) - {} - - ~DebugOutStream() override = default; - - public: // IStream - std::ostream& stream() override { return m_os; } - }; - - } // unnamed namespace -} // namespace Detail - - /////////////////////////////////////////////////////////////////////////// - - auto makeStream( std::string const& filename ) -> Detail::unique_ptr { - if ( filename.empty() || filename == "-" ) { - return Detail::make_unique(); - } - if( filename[0] == '%' ) { - if ( filename == "%debug" ) { - return Detail::make_unique(); - } else if ( filename == "%stderr" ) { - return Detail::make_unique(); - } else if ( filename == "%stdout" ) { - return Detail::make_unique(); - } else { - CATCH_ERROR( "Unrecognised stream: '" << filename << '\'' ); - } - } - return Detail::make_unique( filename ); - } - - // This class encapsulates the idea of a pool of ostringstreams that can be reused. struct StringStreams { std::vector> m_streams; diff --git a/src/catch2/internal/catch_stream.hpp b/src/catch2/internal/catch_stream.hpp index d02dc4b1..104a2412 100644 --- a/src/catch2/internal/catch_stream.hpp +++ b/src/catch2/internal/catch_stream.hpp @@ -9,7 +9,6 @@ #define CATCH_STREAM_HPP_INCLUDED #include -#include #include #include @@ -18,37 +17,6 @@ namespace Catch { - class IStream { - public: - virtual ~IStream(); // = default - virtual std::ostream& stream() = 0; - /** - * Best guess on whether the instance is writing to a console (e.g. via stdout/stderr) - * - * This is useful for e.g. Win32 colour support, because the Win32 - * API manipulates console directly, unlike POSIX escape codes, - * that can be written anywhere. - * - * Due to variety of ways to change where the stdout/stderr is - * _actually_ being written, users should always assume that - * the answer might be wrong. - */ - virtual bool isConsole() const { return false; } - }; - - /** - * Creates a stream wrapper that writes to specific file. - * - * Also recognizes 4 special filenames - * * `-` for stdout - * * `%stdout` for stdout - * * `%stderr` for stderr - * * `%debug` for platform specific debugging output - * - * \throws if passed an unrecognized %-prefixed stream - */ - auto makeStream( std::string const& filename ) -> Detail::unique_ptr; - class ReusableStringStream : Detail::NonCopyable { std::size_t m_index; std::ostream* m_oss; diff --git a/src/catch2/reporters/catch_reporter_common_base.cpp b/src/catch2/reporters/catch_reporter_common_base.cpp index 68a24eef..f4736ab2 100644 --- a/src/catch2/reporters/catch_reporter_common_base.cpp +++ b/src/catch2/reporters/catch_reporter_common_base.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace Catch { diff --git a/tests/SelfTest/IntrospectiveTests/ColourImpl.tests.cpp b/tests/SelfTest/IntrospectiveTests/ColourImpl.tests.cpp index 716d6033..83501cae 100644 --- a/tests/SelfTest/IntrospectiveTests/ColourImpl.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/ColourImpl.tests.cpp @@ -8,6 +8,7 @@ #include #include +#include #include diff --git a/tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp b/tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp index e4554fca..5288709d 100644 --- a/tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/tests/SelfTest/IntrospectiveTests/Stream.tests.cpp b/tests/SelfTest/IntrospectiveTests/Stream.tests.cpp index 9d647b0d..5ad92e8c 100644 --- a/tests/SelfTest/IntrospectiveTests/Stream.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/Stream.tests.cpp @@ -8,7 +8,7 @@ #include -#include +#include TEST_CASE( "Cout stream properly declares it writes to stdout", "[streams]" ) { REQUIRE( Catch::makeStream( "-" )->isConsole() );