| /* | /* | ||||
| * 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 | * This file has been merged from multiple headers. Please don't edit it directly | ||||
| * Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved. | * Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved. | ||||
| #define CATCH_VERSION_MAJOR 2 | #define CATCH_VERSION_MAJOR 2 | ||||
| #define CATCH_VERSION_MINOR 2 | #define CATCH_VERSION_MINOR 2 | ||||
| #define CATCH_VERSION_PATCH 2 | |||||
| #define CATCH_VERSION_PATCH 3 | |||||
| #ifdef __clang__ | #ifdef __clang__ | ||||
| # pragma clang system_header | # pragma clang system_header | ||||
| #elif defined(linux) || defined(__linux) || defined(__linux__) | #elif defined(linux) || defined(__linux) || defined(__linux__) | ||||
| # define CATCH_PLATFORM_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 | # define CATCH_PLATFORM_WINDOWS | ||||
| #endif | #endif | ||||
| # define CATCH_CONFIG_COLOUR_NONE | # define CATCH_CONFIG_COLOUR_NONE | ||||
| #endif | #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 | // Cygwin | ||||
| #ifdef __CYGWIN__ | #ifdef __CYGWIN__ | ||||
| #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) | #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) | ||||
| # define CATCH_CONFIG_COUNTER | # define CATCH_CONFIG_COUNTER | ||||
| #endif | #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 | # define CATCH_CONFIG_WINDOWS_SEH | ||||
| #endif | #endif | ||||
| // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. | // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. | ||||
| # define CATCH_CONFIG_WCHAR | # define CATCH_CONFIG_WCHAR | ||||
| #endif | #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) | #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 | # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS | ||||
| #endif | #endif | ||||
| } // end namespace Catch | } // 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) | #if defined(CATCH_CONFIG_DISABLE) | ||||
| #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ | #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ | ||||
| static void TestName() | static void TestName() | ||||
| #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ | #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ | ||||
| namespace{ \ | namespace{ \ | ||||
| struct TestName : ClassName { \ | |||||
| struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \ | |||||
| void test(); \ | void test(); \ | ||||
| }; \ | }; \ | ||||
| } \ | } \ | ||||
| #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ | #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ | ||||
| CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ | CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ | ||||
| namespace{ \ | namespace{ \ | ||||
| struct TestName : ClassName{ \ | |||||
| struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \ | |||||
| void test(); \ | void test(); \ | ||||
| }; \ | }; \ | ||||
| Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ | Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ | ||||
| std::string convertUnknownEnumToString( E e ); | std::string convertUnknownEnumToString( E e ); | ||||
| template<typename T> | 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; | return Detail::unprintableString; | ||||
| #else | |||||
| return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); | |||||
| #endif | |||||
| } | } | ||||
| template<typename T> | 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 ); | return convertUnknownEnumToString( value ); | ||||
| } | } | ||||
| typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type | typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type | ||||
| convert(const Fake& value) { | convert(const Fake& value) { | ||||
| ReusableStringStream rss; | 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(); | return rss.str(); | ||||
| } | } | ||||
| static | static | ||||
| typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type | typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type | ||||
| convert( const Fake& value ) { | 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 | |||||
| } | } | ||||
| }; | }; | ||||
| std::string outputFilename; | std::string outputFilename; | ||||
| std::string name; | std::string name; | ||||
| std::string processName; | 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> testsOrTags; | ||||
| std::vector<std::string> sectionsToRun; | std::vector<std::string> sectionsToRun; | ||||
| }; | }; | ||||
| bool listReporters() const; | bool listReporters() const; | ||||
| std::string getProcessName() 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& getTestsOrTags() const; | ||||
| std::vector<std::string> const& getSectionsToRun() const override; | std::vector<std::string> const& getSectionsToRun() const override; | ||||
| virtual Listeners const& getListeners() const = 0; | virtual Listeners const& getListeners() const = 0; | ||||
| }; | }; | ||||
| void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ); | |||||
| } // end namespace Catch | } // end namespace Catch | ||||
| // end catch_interfaces_reporter.h | // end catch_interfaces_reporter.h | ||||
| #include <cstring> | #include <cstring> | ||||
| #include <cfloat> | #include <cfloat> | ||||
| #include <cstdio> | #include <cstdio> | ||||
| #include <assert.h> | |||||
| #include <cassert> | |||||
| #include <memory> | #include <memory> | ||||
| #include <ostream> | #include <ostream> | ||||
| | Opt( config.outputFilename, "filename" ) | | Opt( config.outputFilename, "filename" ) | ||||
| ["-o"]["--out"] | ["-o"]["--out"] | ||||
| ( "output filename" ) | ( "output filename" ) | ||||
| | Opt( config.reporterNames, "name" ) | |||||
| | Opt( config.reporterName, "name" ) | |||||
| ["-r"]["--reporter"] | ["-r"]["--reporter"] | ||||
| ( "reporter to use (defaults to console)" ) | ( "reporter to use (defaults to console)" ) | ||||
| | Opt( config.name, "name" ) | | Opt( config.name, "name" ) | ||||
| bool Config::listReporters() const { return m_data.listReporters; } | bool Config::listReporters() const { return m_data.listReporters; } | ||||
| std::string Config::getProcessName() const { return m_data.processName; } | 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::getTestsOrTags() const { return m_data.testsOrTags; } | ||||
| std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } | std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } | ||||
| int id; | int id; | ||||
| const char* name; | 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[] = { | static SignalDefs signalDefs[] = { | ||||
| { SIGINT, "SIGINT - Terminal interrupt signal" }, | { SIGINT, "SIGINT - Terminal interrupt signal" }, | ||||
| { SIGILL, "SIGILL - Illegal instruction signal" }, | { SIGILL, "SIGILL - Illegal instruction signal" }, | ||||
| isSet = true; | isSet = true; | ||||
| stack_t sigStack; | stack_t sigStack; | ||||
| sigStack.ss_sp = altStackMem; | sigStack.ss_sp = altStackMem; | ||||
| sigStack.ss_size = SIGSTKSZ; | |||||
| sigStack.ss_size = sigStackSize; | |||||
| sigStack.ss_flags = 0; | sigStack.ss_flags = 0; | ||||
| sigaltstack(&sigStack, &oldSigStack); | sigaltstack(&sigStack, &oldSigStack); | ||||
| struct sigaction sa = { }; | struct sigaction sa = { }; | ||||
| bool FatalConditionHandler::isSet = false; | bool FatalConditionHandler::isSet = false; | ||||
| struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; | struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; | ||||
| stack_t FatalConditionHandler::oldSigStack = {}; | stack_t FatalConditionHandler::oldSigStack = {}; | ||||
| char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; | |||||
| char FatalConditionHandler::altStackMem[sigStackSize] = {}; | |||||
| } // namespace Catch | } // namespace Catch | ||||
| // end catch_interfaces_registry_hub.cpp | // end catch_interfaces_registry_hub.cpp | ||||
| // start catch_interfaces_reporter.cpp | // start catch_interfaces_reporter.cpp | ||||
| // start catch_reporter_multi.h | |||||
| // start catch_reporter_listening.h | |||||
| namespace Catch { | namespace Catch { | ||||
| class MultipleReporters : public IStreamingReporter { | |||||
| class ListeningReporter : public IStreamingReporter { | |||||
| using Reporters = std::vector<IStreamingReporterPtr>; | using Reporters = std::vector<IStreamingReporterPtr>; | ||||
| Reporters m_reporters; | |||||
| Reporters m_listeners; | |||||
| IStreamingReporterPtr m_reporter = nullptr; | |||||
| public: | public: | ||||
| void add( IStreamingReporterPtr&& reporter ); | |||||
| void addListener( IStreamingReporterPtr&& listener ); | |||||
| void addReporter( IStreamingReporterPtr&& reporter ); | |||||
| public: // IStreamingReporter | public: // IStreamingReporter | ||||
| } // end namespace Catch | } // end namespace Catch | ||||
| // end catch_reporter_multi.h | |||||
| // end catch_reporter_listening.h | |||||
| namespace Catch { | namespace Catch { | ||||
| ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) | ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) | ||||
| IReporterFactory::~IReporterFactory() = default; | IReporterFactory::~IReporterFactory() = default; | ||||
| IReporterRegistry::~IReporterRegistry() = 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 namespace Catch | ||||
| // end catch_interfaces_reporter.cpp | // end catch_interfaces_reporter.cpp | ||||
| // start catch_interfaces_runner.cpp | // start catch_interfaces_runner.cpp | ||||
| // end catch_matchers.cpp | // end catch_matchers.cpp | ||||
| // start catch_matchers_floating.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 <cstdlib> | ||||
| #include <cstdint> | #include <cstdint> | ||||
| #include <cstring> | #include <cstring> | ||||
| } | } | ||||
| std::string WithinUlpsMatcher::describe() const { | 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 | }// namespace Floating | ||||
| } | } | ||||
| } // end namespace Catch | } // end namespace Catch | ||||
| // end catch_message.cpp | // 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.cpp | ||||
| // start catch_random_number_generator.h | // start catch_random_number_generator.h | ||||
| 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) | RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) | ||||
| : m_runInfo(_config->name()), | : m_runInfo(_config->name()), | ||||
| m_context(getCurrentMutableContext()), | m_context(getCurrentMutableContext()), | ||||
| Timer timer; | Timer timer; | ||||
| try { | try { | ||||
| if (m_reporter->getPreferences().shouldRedirectStdOut) { | if (m_reporter->getPreferences().shouldRedirectStdOut) { | ||||
| #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) | |||||
| RedirectedStdOut redirectedStdOut; | RedirectedStdOut redirectedStdOut; | ||||
| RedirectedStdErr redirectedStdErr; | RedirectedStdErr redirectedStdErr; | ||||
| timer.start(); | timer.start(); | ||||
| invokeActiveTestCase(); | invokeActiveTestCase(); | ||||
| redirectedCout += redirectedStdOut.str(); | redirectedCout += redirectedStdOut.str(); | ||||
| redirectedCerr += redirectedStdErr.str(); | redirectedCerr += redirectedStdErr.str(); | ||||
| #else | |||||
| OutputRedirect r(redirectedCout, redirectedCerr); | |||||
| timer.start(); | |||||
| invokeActiveTestCase(); | |||||
| #endif | |||||
| } else { | } else { | ||||
| timer.start(); | timer.start(); | ||||
| invokeActiveTestCase(); | invokeActiveTestCase(); | ||||
| return reporter; | return reporter; | ||||
| } | } | ||||
| #ifndef CATCH_CONFIG_DEFAULT_REPORTER | |||||
| #define CATCH_CONFIG_DEFAULT_REPORTER "console" | |||||
| #endif | |||||
| IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) { | 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(); | 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) { | 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)); | RunContext context(config, std::move(reporter)); | ||||
| return TestCaseInfo::None; | return TestCaseInfo::None; | ||||
| } | } | ||||
| bool isReservedTag( std::string const& tag ) { | 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 ) { | void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { | ||||
| CATCH_ENFORCE( !isReservedTag(tag), | CATCH_ENFORCE( !isReservedTag(tag), | ||||
| // start catch_test_case_tracker.cpp | // start catch_test_case_tracker.cpp | ||||
| #include <algorithm> | #include <algorithm> | ||||
| #include <assert.h> | |||||
| #include <cassert> | |||||
| #include <stdexcept> | #include <stdexcept> | ||||
| #include <memory> | #include <memory> | ||||
| #include <sstream> | #include <sstream> | ||||
| } | } | ||||
| Version const& libraryVersion() { | Version const& libraryVersion() { | ||||
| static Version version( 2, 2, 2, "", 0 ); | |||||
| static Version version( 2, 2, 3, "", 0 ); | |||||
| return version; | return version; | ||||
| } | } | ||||
| #include <cstring> | #include <cstring> | ||||
| #include <cfloat> | #include <cfloat> | ||||
| #include <cstdio> | #include <cstdio> | ||||
| #include <assert.h> | |||||
| #include <cassert> | |||||
| #include <memory> | #include <memory> | ||||
| namespace Catch { | namespace Catch { | ||||
| // end catch_reporter_console.cpp | // end catch_reporter_console.cpp | ||||
| // start catch_reporter_junit.cpp | // start catch_reporter_junit.cpp | ||||
| #include <assert.h> | |||||
| #include <cassert> | |||||
| #include <sstream> | #include <sstream> | ||||
| #include <ctime> | #include <ctime> | ||||
| #include <algorithm> | #include <algorithm> | ||||
| } // end namespace Catch | } // end namespace Catch | ||||
| // end catch_reporter_junit.cpp | // end catch_reporter_junit.cpp | ||||
| // start catch_reporter_multi.cpp | |||||
| // start catch_reporter_listening.cpp | |||||
| #include <cassert> | |||||
| namespace Catch { | 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>{ }; | 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: | // 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; | return true; | ||||
| } | } | ||||
| } // end namespace Catch | } // end namespace Catch | ||||
| // end catch_reporter_multi.cpp | |||||
| // end catch_reporter_listening.cpp | |||||
| // start catch_reporter_xml.cpp | // start catch_reporter_xml.cpp | ||||
| #if defined(_MSC_VER) | #if defined(_MSC_VER) |