diff --git a/include/internal/catch_common.hpp b/include/internal/catch_common.hpp index fe6f2c10..41ff38a9 100644 --- a/include/internal/catch_common.hpp +++ b/include/internal/catch_common.hpp @@ -87,8 +87,8 @@ namespace Catch { std::srand( config.rngSeed() ); } unsigned int rngSeed() { - return getCurrentConfig() - ? getCurrentConfig()->rngSeed() + return getGlobalConfig() + ? getGlobalConfig()->rngSeed() : 0; } diff --git a/include/internal/catch_console_colour_impl.hpp b/include/internal/catch_console_colour_impl.hpp index c9891b17..83c53cad 100644 --- a/include/internal/catch_console_colour_impl.hpp +++ b/include/internal/catch_console_colour_impl.hpp @@ -145,7 +145,7 @@ namespace { }; IColourImpl* platformColourInstance() { - IConfig const* config = getCurrentConfig(); + IConfig const* config = getGlobalConfig(); return (config && config->forceColour()) || isatty(STDOUT_FILENO) ? PosixColourImpl::instance() : NoColourImpl::instance(); diff --git a/include/internal/catch_fatal_condition.hpp b/include/internal/catch_fatal_condition.hpp index 128f4ed5..d8e95809 100644 --- a/include/internal/catch_fatal_condition.hpp +++ b/include/internal/catch_fatal_condition.hpp @@ -14,7 +14,7 @@ namespace Catch { // Report the error condition then exit the process inline void fatal( std::string const& message, int exitCode ) { - IRunContext& runContext = getCurrentRunContext(); + IRunContext& runContext = getGlobalRunContext(); runContext.handleFatalErrorCondition( message ); if( Catch::alwaysTrue() ) // avoids "no return" warnings diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 5bc90f60..5c6a1a2a 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -33,6 +33,7 @@ #include "catch_result_builder.hpp" #include "catch_tag_alias_registry.hpp" #include "catch_test_case_tracker.hpp" +#include "catch_thread_context.hpp" #include "catch_stream.hpp" #include "../reporters/catch_reporter_multi.hpp" @@ -68,6 +69,7 @@ namespace Catch { TestRunStats::~TestRunStats() {} CumulativeReporterBase::SectionNode::~SectionNode() {} CumulativeReporterBase::~CumulativeReporterBase() {} + ThreadContext::~ThreadContext() {} StreamingReporterBase::~StreamingReporterBase() {} ConsoleReporter::~ConsoleReporter() {} diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h index 4ed9bf2d..c1c26d5d 100644 --- a/include/internal/catch_interfaces_capture.h +++ b/include/internal/catch_interfaces_capture.h @@ -47,21 +47,21 @@ namespace Catch { virtual IConfig const& config() const = 0; }; - IRunContext& getCurrentRunContext(); - - IConfig const* getCurrentConfig(); + IRunContext& getGlobalRunContext(); + + IConfig const* getGlobalConfig(); class LocalContext { public: IRunContext& operator()() const { - return getCurrentRunContext(); // !TBD + return getGlobalRunContext(); // !TBD } }; } inline Catch::IRunContext& C_A_T_C_H_Context() { - return Catch::getCurrentRunContext(); + return Catch::getGlobalRunContext(); } #endif // TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 643c6840..ec3c28ad 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -8,6 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED +#include "catch_thread_context.hpp" + #include "catch_interfaces_capture.h" #include "catch_interfaces_reporter.h" #include "catch_interfaces_exception.h" @@ -53,24 +55,25 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////// namespace { - IRunContext* s_currentRunContext = CATCH_NULL; + IRunContext* g_globalRunContext = CATCH_NULL; - void setCurrentRunContext( IRunContext* context ) { - s_currentRunContext = context; + void setGlobalRunContext( IRunContext* context ) { + assert( g_globalRunContext == CATCH_NULL || context == CATCH_NULL ); + g_globalRunContext = context; } } - IRunContext* tryGetCurrentRunContext() { - return s_currentRunContext; + IRunContext* tryGetGlobalRunContext() { + return g_globalRunContext; } - IRunContext& getCurrentRunContext() { - if( IRunContext* capture = tryGetCurrentRunContext() ) + IRunContext& getGlobalRunContext() { + if( IRunContext* capture = tryGetGlobalRunContext() ) return *capture; else throw std::logic_error( "No current test runner" ); } - IConfig const* getCurrentConfig() { - if( IRunContext* capture = tryGetCurrentRunContext() ) + IConfig const* getGlobalConfig() { + if( IRunContext* capture = tryGetGlobalRunContext() ) return &capture->config(); else return CATCH_NULL; @@ -89,13 +92,13 @@ namespace Catch { m_reporter( reporter ), m_activeTestCaseInfo( CATCH_NULL ) { - setCurrentRunContext( this ); + setGlobalRunContext( this ); m_reporter->testRunStarting( m_runInfo ); } virtual ~RunContext() { m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, isAborting() ) ); - setCurrentRunContext( CATCH_NULL ); + setGlobalRunContext( CATCH_NULL ); } void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { diff --git a/include/internal/catch_thread_context.hpp b/include/internal/catch_thread_context.hpp new file mode 100644 index 00000000..deb16914 --- /dev/null +++ b/include/internal/catch_thread_context.hpp @@ -0,0 +1,85 @@ +// +/* + * Created by Phil on 24/11/2015. + * Copyright 2015 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_THREAD_CONTEXT_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_THREAD_CONTEXT_HPP_INCLUDED + +#include "catch_interfaces_capture.h" +#include "catch_notimplemented_exception.h" + +namespace Catch { + + class ThreadContext : public IRunContext { + + IRunContext& m_parentContext; + std::vector m_messages; + std::vector m_assertions; + + ThreadContext( ThreadContext const& ); + void operator =( ThreadContext const& ); + + public: + ThreadContext( IRunContext& parentContext ) + : m_parentContext( parentContext ) + {} + virtual ~ThreadContext(); + + private: // IRunContext + + virtual void assertionEnded( AssertionResult const& result ) CATCH_OVERRIDE { + m_assertions.push_back( result ); + } + + virtual bool sectionStarted( SectionInfo const&, Counts& ) CATCH_OVERRIDE + { + throw std::logic_error( "Sections nested within threaded sections are not currently supported" ); + } + + virtual void sectionEnded( SectionEndInfo const& ) CATCH_OVERRIDE { + throw std::logic_error( "Sections nested within threaded sections are not currently supported" ); + } + + virtual void sectionEndedEarly( SectionEndInfo const& ) CATCH_OVERRIDE { + throw std::logic_error( "Sections nested within threaded sections are not currently supported" ); + } + + virtual void pushScopedMessage( MessageInfo const& message ) CATCH_OVERRIDE { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) CATCH_OVERRIDE { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const CATCH_OVERRIDE { + return m_parentContext.getCurrentTestName(); + } + + virtual AssertionResult const* getLastResult() const CATCH_OVERRIDE { + return m_assertions.empty() + ? CATCH_NULL + : &m_assertions.back(); + } + virtual IConfig const& config() const CATCH_OVERRIDE { + return m_parentContext.config(); + } + + virtual void handleFatalErrorCondition( std::string const& message ) CATCH_OVERRIDE { + m_parentContext.handleFatalErrorCondition( message ); + } + + public: + virtual bool isAborting() const CATCH_OVERRIDE { + // Probably can't do this + CATCH_NOT_IMPLEMENTED; + } + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_THREAD_CONTEXT_HPP_INCLUDED diff --git a/include/internal/catch_tostring.hpp b/include/internal/catch_tostring.hpp index 52f12350..c6b78026 100644 --- a/include/internal/catch_tostring.hpp +++ b/include/internal/catch_tostring.hpp @@ -55,7 +55,7 @@ namespace Detail { std::string toString( std::string const& value ) { std::string s = value; - IConfig const* config = getCurrentConfig(); + IConfig const* config = getGlobalConfig(); if( config && config->showInvisibles() ) { for(size_t i = 0; i < s.size(); ++i ) { std::string subs; diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index dfcaa4b8..73672f2f 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -8,6 +8,8 @@ #include "catch.hpp" +#include "../include/internal/catch_suppress_warnings.h" + #include #include @@ -112,7 +114,7 @@ public: CustomStdException( const std::string& msg ) : m_msg( msg ) {} - ~CustomStdException() CATCH_NOEXCEPT {} + ~CustomStdException() CATCH_NOEXCEPT; std::string getMessage() const { @@ -122,6 +124,7 @@ public: private: std::string m_msg; }; +CustomStdException::~CustomStdException() CATCH_NOEXCEPT {} CATCH_TRANSLATE_EXCEPTION( CustomException& ex ) diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 1713b51a..97d96c15 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -21,6 +21,7 @@ CATCH_REGISTER_TAG_ALIAS( "[@tricky]", "[tricky]~[.]" ) # pragma clang diagnostic ignored "-Wc++98-compat" #endif +namespace { template void parseIntoConfig( const char * (&argv)[size], Catch::ConfigData& config ) { @@ -458,4 +459,7 @@ struct AutoTestReg { REGISTER_TEST_CASE( manuallyRegisteredTestFunction, "ManuallyRegistered", "" ); } }; + AutoTestReg autoTestReg; + +} // anon namespace diff --git a/projects/SelfTest/ThreadedTests.cpp b/projects/SelfTest/ThreadedTests.cpp new file mode 100644 index 00000000..4c9a3e70 --- /dev/null +++ b/projects/SelfTest/ThreadedTests.cpp @@ -0,0 +1,23 @@ +/* + * Created by Phil on 24/11/2015. + * Copyright 2015 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +#include "../include/internal/catch_suppress_warnings.h" +#include "../include/internal/catch_thread_context.hpp" + +#define THREADED_SECTION SECTION + +TEST_CASE( "multithreaded sections" ) { + + + THREADED_SECTION( "test" ) { + Catch::ThreadContext tctx( Catch::getGlobalRunContext() ); + + } +} diff --git a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index 9dbaa0ec..3eeaac1c 100644 --- a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj +++ b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 26847E5F16BBADB40043B9C1 /* catch_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26847E5D16BBADB40043B9C1 /* catch_message.cpp */; }; 2691574C1A532A280054F1ED /* ToStringTuple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2691574B1A532A280054F1ED /* ToStringTuple.cpp */; }; 2694A1FD16A0000E004816E3 /* catch_text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2694A1FB16A0000E004816E3 /* catch_text.cpp */; }; + 269E42321C04E21300133E05 /* ThreadedTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 269E42311C04E21300133E05 /* ThreadedTests.cpp */; }; 26E1B7D319213BC900812682 /* CmdLineTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E1B7D119213BC900812682 /* CmdLineTests.cpp */; }; 4A45DA2416161EF9004F8D6B /* catch_console_colour.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2316161EF9004F8D6B /* catch_console_colour.cpp */; }; 4A45DA2716161F1F004F8D6B /* catch_ptr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2616161F1F004F8D6B /* catch_ptr.cpp */; }; @@ -103,6 +104,8 @@ 269831E519078C1600BB0CE0 /* catch_tostring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_tostring.h; sourceTree = ""; }; 269831E619078CA200BB0CE0 /* catch_tostring.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_tostring.hpp; sourceTree = ""; }; 269831E719121CA500BB0CE0 /* catch_reporter_compact.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_compact.hpp; sourceTree = ""; }; + 269E42311C04E21300133E05 /* ThreadedTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadedTests.cpp; path = ../../../SelfTest/ThreadedTests.cpp; sourceTree = ""; }; + 269E42331C04E33D00133E05 /* catch_thread_context.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_thread_context.hpp; sourceTree = ""; }; 26AEAF1617BEA18E009E32C9 /* catch_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_platform.h; sourceTree = ""; }; 26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = ""; }; 26DFD3B11B53F84700FD6F16 /* catch_wildcard_pattern.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_wildcard_pattern.hpp; sourceTree = ""; }; @@ -264,6 +267,7 @@ 4A6D0C33149B3D9E00DB3EAA /* MessageTests.cpp */, 4A6D0C34149B3D9E00DB3EAA /* MiscTests.cpp */, 266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */, + 269E42311C04E21300133E05 /* ThreadedTests.cpp */, ); name = Tests; sourceTree = ""; @@ -356,6 +360,7 @@ 26847E5C16BBACB60043B9C1 /* catch_message.hpp */, 2627F7061935B55F009BCE2D /* catch_result_builder.hpp */, 26711C92195D48F60033EDA2 /* catch_tag_alias_registry.hpp */, + 269E42331C04E33D00133E05 /* catch_thread_context.hpp */, ); name = impl; sourceTree = ""; @@ -534,6 +539,7 @@ 4AEE032016142F910071E950 /* catch_common.cpp in Sources */, 263F7A4C19B6FE1E009474C2 /* ToStringVector.cpp in Sources */, 4AEE032316142FC70071E950 /* catch_debugger.cpp in Sources */, + 269E42321C04E21300133E05 /* ThreadedTests.cpp in Sources */, 4AEE032516142FF10071E950 /* catch_stream.cpp in Sources */, 4AEE0328161434FD0071E950 /* catch_xmlwriter.cpp in Sources */, 4A45DA2416161EF9004F8D6B /* catch_console_colour.cpp in Sources */,