| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Catch v2.2.2 | |||
| * Generated: 2018-04-06 12:05:03.186665 | |||
| * Catch v2.2.3 | |||
| * Generated: 2018-06-06 23:11:57.601416 | |||
| * ---------------------------------------------------------- | |||
| * This file has been merged from multiple headers. Please don't edit it directly | |||
| * Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved. | |||
| @@ -15,7 +15,7 @@ | |||
| #define CATCH_VERSION_MAJOR 2 | |||
| #define CATCH_VERSION_MINOR 2 | |||
| #define CATCH_VERSION_PATCH 2 | |||
| #define CATCH_VERSION_PATCH 3 | |||
| #ifdef __clang__ | |||
| # pragma clang system_header | |||
| @@ -72,7 +72,7 @@ | |||
| #elif defined(linux) || defined(__linux) || defined(__linux__) | |||
| # define CATCH_PLATFORM_LINUX | |||
| #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) | |||
| #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) | |||
| # define CATCH_PLATFORM_WINDOWS | |||
| #endif | |||
| @@ -164,6 +164,18 @@ namespace Catch { | |||
| # define CATCH_CONFIG_COLOUR_NONE | |||
| #endif | |||
| //////////////////////////////////////////////////////////////////////////////// | |||
| // Android somehow still does not support std::to_string | |||
| #if defined(__ANDROID__) | |||
| # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING | |||
| #endif | |||
| //////////////////////////////////////////////////////////////////////////////// | |||
| // Not all Windows environments support SEH properly | |||
| #if defined(__MINGW32__) | |||
| # define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH | |||
| #endif | |||
| //////////////////////////////////////////////////////////////////////////////// | |||
| // Cygwin | |||
| #ifdef __CYGWIN__ | |||
| @@ -213,7 +225,7 @@ namespace Catch { | |||
| #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) | |||
| # define CATCH_CONFIG_COUNTER | |||
| #endif | |||
| #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) | |||
| #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) | |||
| # define CATCH_CONFIG_WINDOWS_SEH | |||
| #endif | |||
| // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. | |||
| @@ -225,6 +237,10 @@ namespace Catch { | |||
| # define CATCH_CONFIG_WCHAR | |||
| #endif | |||
| #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) | |||
| # define CATCH_CONFIG_CPP11_TO_STRING | |||
| #endif | |||
| #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) | |||
| # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS | |||
| #endif | |||
| @@ -513,12 +529,17 @@ struct AutoReg : NonCopyable { | |||
| } // end namespace Catch | |||
| #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) | |||
| #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ | |||
| #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ | |||
| #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF | |||
| #if defined(CATCH_CONFIG_DISABLE) | |||
| #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ | |||
| static void TestName() | |||
| #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ | |||
| namespace{ \ | |||
| struct TestName : ClassName { \ | |||
| struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \ | |||
| void test(); \ | |||
| }; \ | |||
| } \ | |||
| @@ -546,7 +567,7 @@ struct AutoReg : NonCopyable { | |||
| #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ | |||
| CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ | |||
| namespace{ \ | |||
| struct TestName : ClassName{ \ | |||
| struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \ | |||
| void test(); \ | |||
| }; \ | |||
| Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ | |||
| @@ -770,16 +791,22 @@ namespace Catch { | |||
| std::string convertUnknownEnumToString( E e ); | |||
| template<typename T> | |||
| typename std::enable_if<!std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& value ) { | |||
| #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) | |||
| (void)value; | |||
| typename std::enable_if< | |||
| !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value, | |||
| std::string>::type convertUnstreamable( T const& ) { | |||
| return Detail::unprintableString; | |||
| #else | |||
| return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); | |||
| #endif | |||
| } | |||
| template<typename T> | |||
| typename std::enable_if<std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& value ) { | |||
| typename std::enable_if< | |||
| !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value, | |||
| std::string>::type convertUnstreamable(T const& ex) { | |||
| return ex.what(); | |||
| } | |||
| template<typename T> | |||
| typename std::enable_if< | |||
| std::is_enum<T>::value | |||
| , std::string>::type convertUnstreamable( T const& value ) { | |||
| return convertUnknownEnumToString( value ); | |||
| } | |||
| @@ -805,7 +832,9 @@ namespace Catch { | |||
| typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type | |||
| convert(const Fake& value) { | |||
| ReusableStringStream rss; | |||
| rss << value; | |||
| // NB: call using the function-like syntax to avoid ambiguity with | |||
| // user-defined templated operator<< under clang. | |||
| rss.operator<<(value); | |||
| return rss.str(); | |||
| } | |||
| @@ -813,7 +842,11 @@ namespace Catch { | |||
| static | |||
| typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type | |||
| convert( const Fake& value ) { | |||
| return Detail::convertUnstreamable( value ); | |||
| #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) | |||
| return Detail::convertUnstreamable(value); | |||
| #else | |||
| return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); | |||
| #endif | |||
| } | |||
| }; | |||
| @@ -3354,8 +3387,12 @@ namespace Catch { | |||
| std::string outputFilename; | |||
| std::string name; | |||
| std::string processName; | |||
| #ifndef CATCH_CONFIG_DEFAULT_REPORTER | |||
| #define CATCH_CONFIG_DEFAULT_REPORTER "console" | |||
| #endif | |||
| std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; | |||
| #undef CATCH_CONFIG_DEFAULT_REPORTER | |||
| std::vector<std::string> reporterNames; | |||
| std::vector<std::string> testsOrTags; | |||
| std::vector<std::string> sectionsToRun; | |||
| }; | |||
| @@ -3375,8 +3412,8 @@ namespace Catch { | |||
| bool listReporters() const; | |||
| std::string getProcessName() const; | |||
| std::string const& getReporterName() const; | |||
| std::vector<std::string> const& getReporterNames() const; | |||
| std::vector<std::string> const& getTestsOrTags() const; | |||
| std::vector<std::string> const& getSectionsToRun() const override; | |||
| @@ -3733,8 +3770,6 @@ namespace Catch { | |||
| virtual Listeners const& getListeners() const = 0; | |||
| }; | |||
| void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ); | |||
| } // end namespace Catch | |||
| // end catch_interfaces_reporter.h | |||
| @@ -3742,7 +3777,7 @@ namespace Catch { | |||
| #include <cstring> | |||
| #include <cfloat> | |||
| #include <cstdio> | |||
| #include <assert.h> | |||
| #include <cassert> | |||
| #include <memory> | |||
| #include <ostream> | |||
| @@ -6592,7 +6627,7 @@ namespace Catch { | |||
| | Opt( config.outputFilename, "filename" ) | |||
| ["-o"]["--out"] | |||
| ( "output filename" ) | |||
| | Opt( config.reporterNames, "name" ) | |||
| | Opt( config.reporterName, "name" ) | |||
| ["-r"]["--reporter"] | |||
| ( "reporter to use (defaults to console)" ) | |||
| | Opt( config.name, "name" ) | |||
| @@ -6734,8 +6769,8 @@ namespace Catch { | |||
| bool Config::listReporters() const { return m_data.listReporters; } | |||
| std::string Config::getProcessName() const { return m_data.processName; } | |||
| std::string const& Config::getReporterName() const { return m_data.reporterName; } | |||
| std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; } | |||
| std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; } | |||
| std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } | |||
| @@ -7381,6 +7416,11 @@ namespace Catch { | |||
| int id; | |||
| const char* name; | |||
| }; | |||
| // 32kb for the alternate stack seems to be sufficient. However, this value | |||
| // is experimentally determined, so that's not guaranteed. | |||
| constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; | |||
| static SignalDefs signalDefs[] = { | |||
| { SIGINT, "SIGINT - Terminal interrupt signal" }, | |||
| { SIGILL, "SIGILL - Illegal instruction signal" }, | |||
| @@ -7407,7 +7447,7 @@ namespace Catch { | |||
| isSet = true; | |||
| stack_t sigStack; | |||
| sigStack.ss_sp = altStackMem; | |||
| sigStack.ss_size = SIGSTKSZ; | |||
| sigStack.ss_size = sigStackSize; | |||
| sigStack.ss_flags = 0; | |||
| sigaltstack(&sigStack, &oldSigStack); | |||
| struct sigaction sa = { }; | |||
| @@ -7438,7 +7478,7 @@ namespace Catch { | |||
| bool FatalConditionHandler::isSet = false; | |||
| struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; | |||
| stack_t FatalConditionHandler::oldSigStack = {}; | |||
| char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; | |||
| char FatalConditionHandler::altStackMem[sigStackSize] = {}; | |||
| } // namespace Catch | |||
| @@ -7482,16 +7522,18 @@ namespace Catch { | |||
| // end catch_interfaces_registry_hub.cpp | |||
| // start catch_interfaces_reporter.cpp | |||
| // start catch_reporter_multi.h | |||
| // start catch_reporter_listening.h | |||
| namespace Catch { | |||
| class MultipleReporters : public IStreamingReporter { | |||
| class ListeningReporter : public IStreamingReporter { | |||
| using Reporters = std::vector<IStreamingReporterPtr>; | |||
| Reporters m_reporters; | |||
| Reporters m_listeners; | |||
| IStreamingReporterPtr m_reporter = nullptr; | |||
| public: | |||
| void add( IStreamingReporterPtr&& reporter ); | |||
| void addListener( IStreamingReporterPtr&& listener ); | |||
| void addReporter( IStreamingReporterPtr&& reporter ); | |||
| public: // IStreamingReporter | |||
| @@ -7524,7 +7566,7 @@ namespace Catch { | |||
| } // end namespace Catch | |||
| // end catch_reporter_multi.h | |||
| // end catch_reporter_listening.h | |||
| namespace Catch { | |||
| ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) | |||
| @@ -7625,27 +7667,6 @@ namespace Catch { | |||
| IReporterFactory::~IReporterFactory() = default; | |||
| IReporterRegistry::~IReporterRegistry() = default; | |||
| void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) { | |||
| if( !existingReporter ) { | |||
| existingReporter = std::move( additionalReporter ); | |||
| return; | |||
| } | |||
| MultipleReporters* multi = nullptr; | |||
| if( existingReporter->isMulti() ) { | |||
| multi = static_cast<MultipleReporters*>( existingReporter.get() ); | |||
| } | |||
| else { | |||
| auto newMulti = std::unique_ptr<MultipleReporters>( new MultipleReporters ); | |||
| newMulti->add( std::move( existingReporter ) ); | |||
| multi = newMulti.get(); | |||
| existingReporter = std::move( newMulti ); | |||
| } | |||
| multi->add( std::move( additionalReporter ) ); | |||
| } | |||
| } // end namespace Catch | |||
| // end catch_interfaces_reporter.cpp | |||
| // start catch_interfaces_runner.cpp | |||
| @@ -7887,6 +7908,24 @@ using Matchers::Impl::MatcherBase; | |||
| // end catch_matchers.cpp | |||
| // start catch_matchers_floating.cpp | |||
| // start catch_to_string.hpp | |||
| #include <string> | |||
| namespace Catch { | |||
| template <typename T> | |||
| std::string to_string(T const& t) { | |||
| #if defined(CATCH_CONFIG_CPP11_TO_STRING) | |||
| return std::to_string(t); | |||
| #else | |||
| ReusableStringStream rss; | |||
| rss << t; | |||
| return rss.str(); | |||
| #endif | |||
| } | |||
| } // end namespace Catch | |||
| // end catch_to_string.hpp | |||
| #include <cstdlib> | |||
| #include <cstdint> | |||
| #include <cstring> | |||
| @@ -7992,7 +8031,7 @@ namespace Floating { | |||
| } | |||
| std::string WithinUlpsMatcher::describe() const { | |||
| return "is within " + std::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : ""); | |||
| return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : ""); | |||
| } | |||
| }// namespace Floating | |||
| @@ -8179,6 +8218,213 @@ namespace Catch { | |||
| } | |||
| } // end namespace Catch | |||
| // end catch_message.cpp | |||
| // start catch_output_redirect.cpp | |||
| // start catch_output_redirect.h | |||
| #ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H | |||
| #define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H | |||
| #include <cstdio> | |||
| #include <iosfwd> | |||
| #include <string> | |||
| namespace Catch { | |||
| class RedirectedStream { | |||
| std::ostream& m_originalStream; | |||
| std::ostream& m_redirectionStream; | |||
| std::streambuf* m_prevBuf; | |||
| public: | |||
| RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ); | |||
| ~RedirectedStream(); | |||
| }; | |||
| class RedirectedStdOut { | |||
| ReusableStringStream m_rss; | |||
| RedirectedStream m_cout; | |||
| public: | |||
| RedirectedStdOut(); | |||
| auto str() const -> std::string; | |||
| }; | |||
| // 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(); | |||
| auto str() const -> std::string; | |||
| }; | |||
| // Windows's implementation of std::tmpfile is terrible (it tries | |||
| // to create a file inside system folder, thus requiring elevated | |||
| // privileges for the binary), so we have to use tmpnam(_s) and | |||
| // create the file ourselves there. | |||
| class TempFile { | |||
| public: | |||
| TempFile(TempFile const&) = delete; | |||
| TempFile& operator=(TempFile const&) = delete; | |||
| TempFile(TempFile&&) = delete; | |||
| TempFile& operator=(TempFile&&) = delete; | |||
| TempFile(); | |||
| ~TempFile(); | |||
| std::FILE* getFile(); | |||
| std::string getContents(); | |||
| private: | |||
| std::FILE* m_file = nullptr; | |||
| #if defined(_MSC_VER) | |||
| char m_buffer[L_tmpnam] = { 0 }; | |||
| #endif | |||
| }; | |||
| class OutputRedirect { | |||
| public: | |||
| OutputRedirect(OutputRedirect const&) = delete; | |||
| OutputRedirect& operator=(OutputRedirect const&) = delete; | |||
| OutputRedirect(OutputRedirect&&) = delete; | |||
| OutputRedirect& operator=(OutputRedirect&&) = delete; | |||
| OutputRedirect(std::string& stdout_dest, std::string& stderr_dest); | |||
| ~OutputRedirect(); | |||
| private: | |||
| int m_originalStdout = -1; | |||
| int m_originalStderr = -1; | |||
| TempFile m_stdoutFile; | |||
| TempFile m_stderrFile; | |||
| std::string& m_stdoutDest; | |||
| std::string& m_stderrDest; | |||
| }; | |||
| } // end namespace Catch | |||
| #endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H | |||
| // end catch_output_redirect.h | |||
| #include <cstdio> | |||
| #include <cstring> | |||
| #include <fstream> | |||
| #include <sstream> | |||
| #include <stdexcept> | |||
| #if defined(_MSC_VER) | |||
| #include <io.h> //_dup and _dup2 | |||
| #define dup _dup | |||
| #define dup2 _dup2 | |||
| #define fileno _fileno | |||
| #else | |||
| #include <unistd.h> // dup and dup2 | |||
| #endif | |||
| namespace Catch { | |||
| RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ) | |||
| : m_originalStream( originalStream ), | |||
| m_redirectionStream( redirectionStream ), | |||
| m_prevBuf( m_originalStream.rdbuf() ) | |||
| { | |||
| m_originalStream.rdbuf( m_redirectionStream.rdbuf() ); | |||
| } | |||
| RedirectedStream::~RedirectedStream() { | |||
| m_originalStream.rdbuf( m_prevBuf ); | |||
| } | |||
| RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {} | |||
| auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); } | |||
| RedirectedStdErr::RedirectedStdErr() | |||
| : m_cerr( Catch::cerr(), m_rss.get() ), | |||
| m_clog( Catch::clog(), m_rss.get() ) | |||
| {} | |||
| auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); } | |||
| #if defined(_MSC_VER) | |||
| TempFile::TempFile() { | |||
| if (tmpnam_s(m_buffer)) { | |||
| throw std::runtime_error("Could not get a temp filename"); | |||
| } | |||
| if (fopen_s(&m_file, m_buffer, "w")) { | |||
| char buffer[100]; | |||
| if (strerror_s(buffer, errno)) { | |||
| throw std::runtime_error("Could not translate errno to string"); | |||
| } | |||
| throw std::runtime_error("Could not open the temp file: " + std::string(m_buffer) + buffer); | |||
| } | |||
| } | |||
| #else | |||
| TempFile::TempFile() { | |||
| m_file = std::tmpfile(); | |||
| if (!m_file) { | |||
| throw std::runtime_error("Could not create a temp file."); | |||
| } | |||
| } | |||
| #endif | |||
| TempFile::~TempFile() { | |||
| // TBD: What to do about errors here? | |||
| std::fclose(m_file); | |||
| // We manually create the file on Windows only, on Linux | |||
| // it will be autodeleted | |||
| #if defined(_MSC_VER) | |||
| std::remove(m_buffer); | |||
| #endif | |||
| } | |||
| FILE* TempFile::getFile() { | |||
| return m_file; | |||
| } | |||
| std::string TempFile::getContents() { | |||
| std::stringstream sstr; | |||
| char buffer[100] = {}; | |||
| std::rewind(m_file); | |||
| while (std::fgets(buffer, sizeof(buffer), m_file)) { | |||
| sstr << buffer; | |||
| } | |||
| return sstr.str(); | |||
| } | |||
| OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) : | |||
| m_originalStdout(dup(1)), | |||
| m_originalStderr(dup(2)), | |||
| m_stdoutDest(stdout_dest), | |||
| m_stderrDest(stderr_dest) { | |||
| dup2(fileno(m_stdoutFile.getFile()), 1); | |||
| dup2(fileno(m_stderrFile.getFile()), 2); | |||
| } | |||
| OutputRedirect::~OutputRedirect() { | |||
| Catch::cout() << std::flush; | |||
| fflush(stdout); | |||
| // Since we support overriding these streams, we flush cerr | |||
| // even though std::cerr is unbuffered | |||
| Catch::cerr() << std::flush; | |||
| Catch::clog() << std::flush; | |||
| fflush(stderr); | |||
| dup2(m_originalStdout, 1); | |||
| dup2(m_originalStderr, 2); | |||
| m_stdoutDest += m_stdoutFile.getContents(); | |||
| m_stderrDest += m_stderrFile.getContents(); | |||
| } | |||
| } // namespace Catch | |||
| #if defined(_MSC_VER) | |||
| #undef dup | |||
| #undef dup2 | |||
| #undef fileno | |||
| #endif | |||
| // end catch_output_redirect.cpp | |||
| // start catch_random_number_generator.cpp | |||
| // start catch_random_number_generator.h | |||
| @@ -8507,47 +8753,6 @@ namespace Catch { | |||
| namespace Catch { | |||
| class RedirectedStream { | |||
| std::ostream& m_originalStream; | |||
| std::ostream& m_redirectionStream; | |||
| std::streambuf* m_prevBuf; | |||
| public: | |||
| RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ) | |||
| : m_originalStream( originalStream ), | |||
| m_redirectionStream( redirectionStream ), | |||
| m_prevBuf( m_originalStream.rdbuf() ) | |||
| { | |||
| m_originalStream.rdbuf( m_redirectionStream.rdbuf() ); | |||
| } | |||
| ~RedirectedStream() { | |||
| m_originalStream.rdbuf( m_prevBuf ); | |||
| } | |||
| }; | |||
| class RedirectedStdOut { | |||
| ReusableStringStream m_rss; | |||
| RedirectedStream m_cout; | |||
| public: | |||
| 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(); } | |||
| }; | |||
| RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) | |||
| : m_runInfo(_config->name()), | |||
| m_context(getCurrentMutableContext()), | |||
| @@ -8794,13 +8999,19 @@ namespace Catch { | |||
| Timer timer; | |||
| try { | |||
| if (m_reporter->getPreferences().shouldRedirectStdOut) { | |||
| #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) | |||
| RedirectedStdOut redirectedStdOut; | |||
| RedirectedStdErr redirectedStdErr; | |||
| timer.start(); | |||
| invokeActiveTestCase(); | |||
| redirectedCout += redirectedStdOut.str(); | |||
| redirectedCerr += redirectedStdErr.str(); | |||
| #else | |||
| OutputRedirect r(redirectedCout, redirectedCerr); | |||
| timer.start(); | |||
| invokeActiveTestCase(); | |||
| #endif | |||
| } else { | |||
| timer.start(); | |||
| invokeActiveTestCase(); | |||
| @@ -9094,32 +9305,25 @@ namespace Catch { | |||
| return reporter; | |||
| } | |||
| #ifndef CATCH_CONFIG_DEFAULT_REPORTER | |||
| #define CATCH_CONFIG_DEFAULT_REPORTER "console" | |||
| #endif | |||
| IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) { | |||
| auto const& reporterNames = config->getReporterNames(); | |||
| if (reporterNames.empty()) | |||
| return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config); | |||
| IStreamingReporterPtr reporter; | |||
| for (auto const& name : reporterNames) | |||
| addReporter(reporter, createReporter(name, config)); | |||
| return reporter; | |||
| } | |||
| if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) { | |||
| return createReporter(config->getReporterName(), config); | |||
| } | |||
| #undef CATCH_CONFIG_DEFAULT_REPORTER | |||
| auto multi = std::unique_ptr<ListeningReporter>(new ListeningReporter); | |||
| void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) { | |||
| auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); | |||
| for (auto const& listener : listeners) | |||
| addReporter(reporters, listener->create(Catch::ReporterConfig(config))); | |||
| for (auto const& listener : listeners) { | |||
| multi->addListener(listener->create(Catch::ReporterConfig(config))); | |||
| } | |||
| multi->addReporter(createReporter(config->getReporterName(), config)); | |||
| return std::move(multi); | |||
| } | |||
| Catch::Totals runTests(std::shared_ptr<Config> const& config) { | |||
| IStreamingReporterPtr reporter = makeReporter(config); | |||
| addListeners(reporter, config); | |||
| // FixMe: Add listeners in order first, then add reporters. | |||
| auto reporter = makeReporter(config); | |||
| RunContext context(config, std::move(reporter)); | |||
| @@ -9847,7 +10051,7 @@ namespace Catch { | |||
| return TestCaseInfo::None; | |||
| } | |||
| bool isReservedTag( std::string const& tag ) { | |||
| return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); | |||
| return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) ); | |||
| } | |||
| void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { | |||
| CATCH_ENFORCE( !isReservedTag(tag), | |||
| @@ -10085,7 +10289,7 @@ namespace Catch { | |||
| // start catch_test_case_tracker.cpp | |||
| #include <algorithm> | |||
| #include <assert.h> | |||
| #include <cassert> | |||
| #include <stdexcept> | |||
| #include <memory> | |||
| #include <sstream> | |||
| @@ -10913,7 +11117,7 @@ namespace Catch { | |||
| } | |||
| Version const& libraryVersion() { | |||
| static Version version( 2, 2, 2, "", 0 ); | |||
| static Version version( 2, 2, 3, "", 0 ); | |||
| return version; | |||
| } | |||
| @@ -11240,7 +11444,7 @@ namespace { | |||
| #include <cstring> | |||
| #include <cfloat> | |||
| #include <cstdio> | |||
| #include <assert.h> | |||
| #include <cassert> | |||
| #include <memory> | |||
| namespace Catch { | |||
| @@ -12183,7 +12387,7 @@ CATCH_REGISTER_REPORTER("console", ConsoleReporter) | |||
| // end catch_reporter_console.cpp | |||
| // start catch_reporter_junit.cpp | |||
| #include <assert.h> | |||
| #include <cassert> | |||
| #include <sstream> | |||
| #include <ctime> | |||
| #include <algorithm> | |||
| @@ -12416,100 +12620,133 @@ namespace Catch { | |||
| } // end namespace Catch | |||
| // end catch_reporter_junit.cpp | |||
| // start catch_reporter_multi.cpp | |||
| // start catch_reporter_listening.cpp | |||
| #include <cassert> | |||
| namespace Catch { | |||
| void MultipleReporters::add( IStreamingReporterPtr&& reporter ) { | |||
| m_reporters.push_back( std::move( reporter ) ); | |||
| void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) { | |||
| m_listeners.push_back( std::move( listener ) ); | |||
| } | |||
| ReporterPreferences MultipleReporters::getPreferences() const { | |||
| return m_reporters[0]->getPreferences(); | |||
| void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) { | |||
| assert(!m_reporter && "Listening reporter can wrap only 1 real reporter"); | |||
| m_reporter = std::move( reporter ); | |||
| } | |||
| std::set<Verbosity> MultipleReporters::getSupportedVerbosities() { | |||
| ReporterPreferences ListeningReporter::getPreferences() const { | |||
| return m_reporter->getPreferences(); | |||
| } | |||
| std::set<Verbosity> ListeningReporter::getSupportedVerbosities() { | |||
| return std::set<Verbosity>{ }; | |||
| } | |||
| void MultipleReporters::noMatchingTestCases( std::string const& spec ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->noMatchingTestCases( spec ); | |||
| void ListeningReporter::noMatchingTestCases( std::string const& spec ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->noMatchingTestCases( spec ); | |||
| } | |||
| m_reporter->noMatchingTestCases( spec ); | |||
| } | |||
| void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->benchmarkStarting( benchmarkInfo ); | |||
| void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->benchmarkStarting( benchmarkInfo ); | |||
| } | |||
| m_reporter->benchmarkStarting( benchmarkInfo ); | |||
| } | |||
| void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->benchmarkEnded( benchmarkStats ); | |||
| void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->benchmarkEnded( benchmarkStats ); | |||
| } | |||
| m_reporter->benchmarkEnded( benchmarkStats ); | |||
| } | |||
| void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->testRunStarting( testRunInfo ); | |||
| void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->testRunStarting( testRunInfo ); | |||
| } | |||
| m_reporter->testRunStarting( testRunInfo ); | |||
| } | |||
| void MultipleReporters::testGroupStarting( GroupInfo const& groupInfo ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->testGroupStarting( groupInfo ); | |||
| void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->testGroupStarting( groupInfo ); | |||
| } | |||
| m_reporter->testGroupStarting( groupInfo ); | |||
| } | |||
| void MultipleReporters::testCaseStarting( TestCaseInfo const& testInfo ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->testCaseStarting( testInfo ); | |||
| void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->testCaseStarting( testInfo ); | |||
| } | |||
| m_reporter->testCaseStarting( testInfo ); | |||
| } | |||
| void MultipleReporters::sectionStarting( SectionInfo const& sectionInfo ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->sectionStarting( sectionInfo ); | |||
| void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->sectionStarting( sectionInfo ); | |||
| } | |||
| m_reporter->sectionStarting( sectionInfo ); | |||
| } | |||
| void MultipleReporters::assertionStarting( AssertionInfo const& assertionInfo ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->assertionStarting( assertionInfo ); | |||
| void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->assertionStarting( assertionInfo ); | |||
| } | |||
| m_reporter->assertionStarting( assertionInfo ); | |||
| } | |||
| // The return value indicates if the messages buffer should be cleared: | |||
| bool MultipleReporters::assertionEnded( AssertionStats const& assertionStats ) { | |||
| bool clearBuffer = false; | |||
| for( auto const& reporter : m_reporters ) | |||
| clearBuffer |= reporter->assertionEnded( assertionStats ); | |||
| return clearBuffer; | |||
| bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) { | |||
| for( auto const& listener : m_listeners ) { | |||
| static_cast<void>( listener->assertionEnded( assertionStats ) ); | |||
| } | |||
| return m_reporter->assertionEnded( assertionStats ); | |||
| } | |||
| void MultipleReporters::sectionEnded( SectionStats const& sectionStats ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->sectionEnded( sectionStats ); | |||
| void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->sectionEnded( sectionStats ); | |||
| } | |||
| m_reporter->sectionEnded( sectionStats ); | |||
| } | |||
| void MultipleReporters::testCaseEnded( TestCaseStats const& testCaseStats ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->testCaseEnded( testCaseStats ); | |||
| void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->testCaseEnded( testCaseStats ); | |||
| } | |||
| m_reporter->testCaseEnded( testCaseStats ); | |||
| } | |||
| void MultipleReporters::testGroupEnded( TestGroupStats const& testGroupStats ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->testGroupEnded( testGroupStats ); | |||
| void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->testGroupEnded( testGroupStats ); | |||
| } | |||
| m_reporter->testGroupEnded( testGroupStats ); | |||
| } | |||
| void MultipleReporters::testRunEnded( TestRunStats const& testRunStats ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->testRunEnded( testRunStats ); | |||
| void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->testRunEnded( testRunStats ); | |||
| } | |||
| m_reporter->testRunEnded( testRunStats ); | |||
| } | |||
| void MultipleReporters::skipTest( TestCaseInfo const& testInfo ) { | |||
| for( auto const& reporter : m_reporters ) | |||
| reporter->skipTest( testInfo ); | |||
| void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) { | |||
| for ( auto const& listener : m_listeners ) { | |||
| listener->skipTest( testInfo ); | |||
| } | |||
| m_reporter->skipTest( testInfo ); | |||
| } | |||
| bool MultipleReporters::isMulti() const { | |||
| bool ListeningReporter::isMulti() const { | |||
| return true; | |||
| } | |||
| } // end namespace Catch | |||
| // end catch_reporter_multi.cpp | |||
| // end catch_reporter_listening.cpp | |||
| // start catch_reporter_xml.cpp | |||
| #if defined(_MSC_VER) | |||