From e8b31108d695f996998d2abe143e63ef394f9a79 Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Tue, 14 Mar 2017 11:54:14 -0700 Subject: [PATCH 01/12] Fix Catch::toString() linker error when main() is compiled as C++ Fixes #278 --- include/internal/catch_tostring.h | 2 +- include/internal/catch_tostring.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index e6f7ec9d..1e89af79 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -63,7 +63,7 @@ std::string toString( std::nullptr_t ); #ifdef __OBJC__ std::string toString( NSString const * const& nsstring ); - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG & nsstring ); std::string toString( NSObject* const& nsObject ); #endif diff --git a/include/internal/catch_tostring.hpp b/include/internal/catch_tostring.hpp index e61191b9..602e639d 100644 --- a/include/internal/catch_tostring.hpp +++ b/include/internal/catch_tostring.hpp @@ -198,7 +198,7 @@ std::string toString( std::nullptr_t ) { return "nil"; return "@" + toString([nsstring UTF8String]); } - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + std::string toString( NSString * CATCH_ARC_STRONG & nsstring ) { if( !nsstring ) return "nil"; return "@" + toString([nsstring UTF8String]); From a09bef23ed0ddf7674f20b1077b1a51a447a3fd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 6 Jun 2017 16:43:14 +0200 Subject: [PATCH 02/12] Refer to #923 in reporter documentation --- docs/reporters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reporters.md b/docs/reporters.md index 1b89b64f..8db5eab9 100644 --- a/docs/reporters.md +++ b/docs/reporters.md @@ -17,7 +17,7 @@ There are four reporters built in to the single include: * `console` writes as lines of text, formatted to a typical terminal width, with colours if a capable terminal is detected. * `compact` similar to `console` but optimised for minimal output - each entry on one line -* `junit` writes xml that corresponds to Ant's [junitreport](http://help.catchsoftware.com/display/ET/JUnit+Format) target. Useful for build systems that understand Junit. +* `junit` writes xml that corresponds to Ant's [junitreport](http://help.catchsoftware.com/display/ET/JUnit+Format) target. Useful for build systems that understand Junit. If you are using Jenkins with Catch 1.x, you can improve quality of output by applying changes in #923. Because of the way the junit format is structured the run must complete before anything is written. * `xml` writes an xml format tailored to Catch. Unlike `junit` this is a streaming format so results are delivered progressively. From e0aaba6cf84c2e932c9a87dd26263875628c4c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 6 Jun 2017 16:46:46 +0200 Subject: [PATCH 03/12] Actually link #923 from the documentation --- docs/reporters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reporters.md b/docs/reporters.md index 8db5eab9..703234b1 100644 --- a/docs/reporters.md +++ b/docs/reporters.md @@ -17,7 +17,7 @@ There are four reporters built in to the single include: * `console` writes as lines of text, formatted to a typical terminal width, with colours if a capable terminal is detected. * `compact` similar to `console` but optimised for minimal output - each entry on one line -* `junit` writes xml that corresponds to Ant's [junitreport](http://help.catchsoftware.com/display/ET/JUnit+Format) target. Useful for build systems that understand Junit. If you are using Jenkins with Catch 1.x, you can improve quality of output by applying changes in #923. +* `junit` writes xml that corresponds to Ant's [junitreport](http://help.catchsoftware.com/display/ET/JUnit+Format) target. Useful for build systems that understand Junit. If you are using Jenkins with Catch 1.x, you can improve quality of output by applying changes in [#923](https://github.com/philsquared/Catch/pull/923). Because of the way the junit format is structured the run must complete before anything is written. * `xml` writes an xml format tailored to Catch. Unlike `junit` this is a streaming format so results are delivered progressively. From efba988ccc3f8d9410ddf73b028854ce0cba685a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 13 Jun 2017 18:20:59 +0200 Subject: [PATCH 04/12] Fix how GCC version is detected when checking for __COUNTER__ Fixes #928 --- include/internal/catch_compiler_capabilities.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index ac6f259d..01964499 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -170,7 +170,7 @@ // Use __COUNTER__ if the compiler supports it #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ - ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ + ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ ( defined __clang__ && __clang_major__ >= 3 ) #define CATCH_INTERNAL_CONFIG_COUNTER From b90d0b72679a0e69a059eb87c531a7e30c95cd6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 15 Jun 2017 11:43:31 +0200 Subject: [PATCH 05/12] Disable deprecation warning of std::uncaught_exception We might prefer to use `std::uncaught_exceptions` in the future, but I would prefer not to bring in more configuration into Catch Classic Closes #927 --- include/internal/catch_section.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/internal/catch_section.hpp b/include/internal/catch_section.hpp index a5d1b6d5..aab721f6 100644 --- a/include/internal/catch_section.hpp +++ b/include/internal/catch_section.hpp @@ -30,6 +30,10 @@ namespace Catch { m_timer.start(); } +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17 +#endif Section::~Section() { if( m_sectionIncluded ) { SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); @@ -39,6 +43,9 @@ namespace Catch { getResultCapture().sectionEnded( endInfo ); } } +#if defined(_MSC_VER) +#pragma warning(pop) +#endif // This indicates whether the section should be executed or not Section::operator bool() const { From 017a63da62ba7ffce1e1b005e6adc846412c575b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 15 Jun 2017 13:08:26 +0200 Subject: [PATCH 06/12] v1.9.5 --- README.md | 2 +- docs/release-notes.md | 16 +++++++ include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 75 ++++++++++++++++-------------- 4 files changed, 59 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 0ef573b3..76035f34 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=master)](https://travis-ci.org/philsquared/Catch) [![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght/branch/master?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/master) -The latest, single header, version can be downloaded directly using this link +The latest, single header, version can be downloaded directly using this link ## What's the Catch? diff --git a/docs/release-notes.md b/docs/release-notes.md index f98d8475..e5fa9531 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,3 +1,19 @@ +# 1.9.5 + +### Fixes +* Truthy expressions are now reconstructed properly, not as booleans (#914) +* Various warnings are no longer erroneously suppressed in test files (files that include `catch.hpp`, but do not define `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`) (#871) +* Catch no longer fails to link when main is compiled as C++, but linked against Objective-C (#855) +* Fixed incorrect gcc version detection when deciding to use `__COUNTER__` (#928) + * Previously any GCC with minor version less than 3 would be incorrectly classified as not supporting `__COUNTER__`. +* Suppressed C4996 warning caused by upcoming updated to MSVC 2017, marking `std::uncaught_exception` as deprecated. (#927) + +### Improvements +* CMake integration script now incorporates debug messages and registers tests in an improved way (#911) +* Various documentation improvements + + + # 1.9.4 ### Fixes diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 62ba34f3..f7d1618f 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -38,7 +38,7 @@ namespace Catch { } inline Version libraryVersion() { - static Version version( 1, 9, 4, "", 0 ); + static Version version( 1, 9, 5, "", 0 ); return version; } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 33d037e5..2c93e370 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.9.4 - * Generated: 2017-05-16 13:51:55.506519 + * Catch v1.9.5 + * Generated: 2017-06-15 12:03:23.301505 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -220,7 +220,7 @@ // Use __COUNTER__ if the compiler supports it #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ - ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ + ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ ( defined __clang__ && __clang_major__ >= 3 ) #define CATCH_INTERNAL_CONFIG_COUNTER @@ -927,8 +927,8 @@ namespace Catch { template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& ); - private: - DecomposedExpression& operator = (DecomposedExpression const&); + private: + DecomposedExpression& operator = (DecomposedExpression const&); }; struct AssertionInfo @@ -1571,7 +1571,7 @@ std::string toString( std::nullptr_t ); #ifdef __OBJC__ std::string toString( NSString const * const& nsstring ); - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG & nsstring ); std::string toString( NSObject* const& nsObject ); #endif @@ -1855,7 +1855,7 @@ public: } virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { - dest = Catch::toString( m_truthy ); + dest = Catch::toString( m_lhs ); } private: @@ -3490,16 +3490,16 @@ return @ desc; \ #include class LeakDetector { public: - LeakDetector() { - int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - flag |= _CRTDBG_LEAK_CHECK_DF; - flag |= _CRTDBG_ALLOC_MEM_DF; - _CrtSetDbgFlag(flag); - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); - // Change this to leaking allocation's number to break there - _CrtSetBreakAlloc(-1); - } + LeakDetector() { + int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + flag |= _CRTDBG_LEAK_CHECK_DF; + flag |= _CRTDBG_ALLOC_MEM_DF; + _CrtSetDbgFlag(flag); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + // Change this to leaking allocation's number to break there + _CrtSetBreakAlloc(-1); + } }; #else class LeakDetector {}; @@ -8309,7 +8309,7 @@ namespace Catch { } inline Version libraryVersion() { - static Version version( 1, 9, 4, "", 0 ); + static Version version( 1, 9, 5, "", 0 ); return version; } @@ -8661,6 +8661,10 @@ namespace Catch { m_timer.start(); } +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17 +#endif Section::~Section() { if( m_sectionIncluded ) { SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); @@ -8670,6 +8674,9 @@ namespace Catch { getResultCapture().sectionEnded( endInfo ); } } +#if defined(_MSC_VER) +#pragma warning(pop) +#endif // This indicates whether the section should be executed or not Section::operator bool() const { @@ -8985,7 +8992,7 @@ std::string toString( std::nullptr_t ) { return "nil"; return "@" + toString([nsstring UTF8String]); } - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + std::string toString( NSString * CATCH_ARC_STRONG & nsstring ) { if( !nsstring ) return "nil"; return "@" + toString([nsstring UTF8String]); @@ -10028,20 +10035,6 @@ namespace Catch { }; } -// #included from: catch_reenable_warnings.h - -#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(pop) -# else -# pragma clang diagnostic pop -# endif -#elif defined __GNUC__ -# pragma GCC diagnostic pop -#endif - namespace Catch { class XmlReporter : public StreamingReporterBase { @@ -11303,7 +11296,7 @@ extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { int main (int argc, char * argv[]) { #endif - int result = Catch::Session().run( argc, argv ); + int result = Catch::Session().run( argc, argv ); return ( result < 0xff ? result : 0xff ); } @@ -11504,5 +11497,19 @@ int main (int argc, char * const argv[]) { using Catch::Detail::Approx; +// #included from: internal/catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED From dcab8a59716d785ad2ed8512a35f27b671ae1b20 Mon Sep 17 00:00:00 2001 From: Neal Coombes Date: Wed, 21 Jun 2017 13:34:58 -0500 Subject: [PATCH 07/12] Performance improvement in AssertionInfo. By using char const * instead of std::string we avoid significant copying per assertion. In a simple loop with 10000000 CHECKS on my system, this reduces the run time from 9.8s to 6s. --- include/internal/catch_assertionresult.h | 12 ++++++---- include/internal/catch_assertionresult.hpp | 28 ++++++++++++++-------- include/internal/catch_result_builder.hpp | 11 +++------ include/internal/catch_run_context.hpp | 8 +++---- 4 files changed, 32 insertions(+), 27 deletions(-) diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index 22d1355e..5d6c86d1 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -40,15 +40,17 @@ namespace Catch { struct AssertionInfo { AssertionInfo() {} - AssertionInfo( std::string const& _macroName, + AssertionInfo( char const * _macroName, SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ); + char const * _capturedExpression, + ResultDisposition::Flags _resultDisposition, + char const * _secondArg = ""); - std::string macroName; + char const * macroName; SourceLineInfo lineInfo; - std::string capturedExpression; + char const * capturedExpression; ResultDisposition::Flags resultDisposition; + char const * secondArg; }; struct AssertionResultData diff --git a/include/internal/catch_assertionresult.hpp b/include/internal/catch_assertionresult.hpp index 9b637028..2fa3373d 100644 --- a/include/internal/catch_assertionresult.hpp +++ b/include/internal/catch_assertionresult.hpp @@ -13,14 +13,16 @@ namespace Catch { - AssertionInfo::AssertionInfo( std::string const& _macroName, + AssertionInfo::AssertionInfo( char const * _macroName, SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ) + char const * _capturedExpression, + ResultDisposition::Flags _resultDisposition, + char const * _secondArg) : macroName( _macroName ), lineInfo( _lineInfo ), capturedExpression( _capturedExpression ), - resultDisposition( _resultDisposition ) + resultDisposition( _resultDisposition ), + secondArg( _secondArg ) {} AssertionResult::AssertionResult() {} @@ -47,24 +49,30 @@ namespace Catch { } bool AssertionResult::hasExpression() const { - return !m_info.capturedExpression.empty(); + return m_info.capturedExpression[0] != 0; } bool AssertionResult::hasMessage() const { return !m_resultData.message.empty(); } + std::string capturedExpressionWithSecondArgument( char const * capturedExpression, char const * secondArg ) { + return (secondArg[0] == 0 || secondArg[0] == '"' && secondArg[1] == '"') + ? capturedExpression + : std::string(capturedExpression) + ", " + secondArg; + } + std::string AssertionResult::getExpression() const { if( isFalseTest( m_info.resultDisposition ) ) - return '!' + m_info.capturedExpression; + return '!' + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); else - return m_info.capturedExpression; + return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); } std::string AssertionResult::getExpressionInMacro() const { - if( m_info.macroName.empty() ) - return m_info.capturedExpression; + if( m_info.macroName[0] == 0 ) + return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); else - return m_info.macroName + "( " + m_info.capturedExpression + " )"; + return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )"; } bool AssertionResult::hasExpandedExpression() const { diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.hpp index 2874c568..510fbc3b 100644 --- a/include/internal/catch_result_builder.hpp +++ b/include/internal/catch_result_builder.hpp @@ -18,17 +18,12 @@ namespace Catch { - std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { - return secondArg.empty() || secondArg == "\"\"" - ? capturedExpression - : capturedExpression + ", " + secondArg; - } ResultBuilder::ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, ResultDisposition::Flags resultDisposition, char const* secondArg ) - : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), + : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition, secondArg ), m_shouldDebugBreak( false ), m_shouldThrow( false ), m_guardException( false ) @@ -82,7 +77,7 @@ namespace Catch { assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); AssertionResultData data = m_data; data.resultType = ResultWas::Ok; - data.reconstructedExpression = m_assertionInfo.capturedExpression; + data.reconstructedExpression = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); std::string actualMessage = Catch::translateActiveException(); if( !matcher.match( actualMessage ) ) { @@ -154,7 +149,7 @@ namespace Catch { } void ResultBuilder::reconstructExpression( std::string& dest ) const { - dest = m_assertionInfo.capturedExpression; + dest = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); } void ResultBuilder::setExceptionGuard() { diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 572b54d1..b3dee17f 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -150,7 +150,7 @@ namespace Catch { static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); // Reset working state - m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); m_lastResult = result; } @@ -280,7 +280,7 @@ namespace Catch { double duration = 0; m_shouldReportUnexpected = true; try { - m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal ); + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); seedRng( *m_config ); @@ -332,9 +332,9 @@ namespace Catch { private: ResultBuilder makeUnexpectedResultBuilder() const { - return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), + return ResultBuilder( m_lastAssertionInfo.macroName, m_lastAssertionInfo.lineInfo, - m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.capturedExpression, m_lastAssertionInfo.resultDisposition ); } From a6cdcd43aa24adf1e36edd5517a96feaeac18c25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 22 Jun 2017 18:55:17 +0200 Subject: [PATCH 08/12] Added "How to test changes in PR" section to documentation Also linked it from PR template. Closes #936 --- .github/pull_request_template.md | 3 +++ docs/contributing.md | 23 +++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 95e3ccd2..368f41fb 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,6 +2,9 @@ Please do not submit pull requests changing the `version.hpp` or the single-include `catch.hpp` file, these are changed only when a new release is made. + +Before submitting a PR you should probably read the contributor documentation +at docs/contributing.md. It will tell you how to properly test your changes. --> diff --git a/docs/contributing.md b/docs/contributing.md index 28d0643d..1bcef99b 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -18,8 +18,8 @@ Ongoing development is currently on _master_. At some point an integration branc _Users_ of Catch primarily use the single header version. _Maintainers_ should work with the full source (which is still, primarily, in headers). This can be found in the `include` folder. There are a set of test files, currently under `projects/SelfTest`. The test app can be built via CMake from the `CMakeLists.txt` file in the root, or you can generate -project files for Visual Studio, XCode, and others (instructions in the `projects` folder). If you have access to CLion -that can work with the CMake file directly. +project files for Visual Studio, XCode, and others (instructions in the `projects` folder). If you have access to CLion, +it can work with the CMake file directly. As well as the runtime test files you'll also see a `SurrogateCpps` directory under `projects/SelfTest`. This contains a set of .cpp files that each `#include` a single header. @@ -34,6 +34,25 @@ __When submitting a pull request please do not include changes to the single inc as these are managed by the scripts!__ +## Testing your changes + +Obviously all changes to Catch's code should be tested. If you added new functionality, you should add tests covering and +showcasing it. Even if you have only made changes to Catch internals (ie you implemented some performance improvements), +you should still test your changes. + +This means 3 things + +* Compiling Catch's SelfTest project -- code that does not compile is evidently incorrect. Obviously, you are not expected to +have access to all compilers and platforms Catch supports, Catch's CI pipeline will compile your code using supported compilers +once you open a PR. +* Running the SelfTest binary. There should be no unexpected failures on simple run. +* Running Catch's approval tests. Approval tests compare current output of the SelfTest binary in various configurations against +known good output. Catch's repository provides utility scripts `approvalTests.py` to help you with this. It needs to be passed +the SelfTest binary compiled with your changes, like so: `$ ./scripts/approvalTests.py clang-build/SelfTest`. The output should +be fairly self-explanatory. + + + *this document is still in-progress...* --- From 396ecf6021b9c0e2b6799d091adf49b0182b180f Mon Sep 17 00:00:00 2001 From: Neal Coombes Date: Fri, 23 Jun 2017 11:31:17 -0500 Subject: [PATCH 09/12] Cache std::ostringstream between assertions. This is not thread safe, but I think that was already true of Catch. The construction/destruction of the std::ostringstream is where the vast majority of time is spent per assertion. A simple test of 100000000 CHECK()s is reduced from around 60s to 7.4s --- include/internal/catch_result_builder.h | 9 +++++++-- include/internal/catch_result_builder.hpp | 10 ++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index 82494566..b1808cc0 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -47,7 +47,7 @@ namespace Catch { template ResultBuilder& operator << ( T const& value ) { - m_stream.oss << value; + m_stream().oss << value; return *this; } @@ -80,7 +80,12 @@ namespace Catch { private: AssertionInfo m_assertionInfo; AssertionResultData m_data; - CopyableStream m_stream; + + static CopyableStream &m_stream() + { + static CopyableStream s; + return s; + } bool m_shouldDebugBreak; bool m_shouldThrow; diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.hpp index 510fbc3b..2abb9a91 100644 --- a/include/internal/catch_result_builder.hpp +++ b/include/internal/catch_result_builder.hpp @@ -27,12 +27,14 @@ namespace Catch { m_shouldDebugBreak( false ), m_shouldThrow( false ), m_guardException( false ) - {} + { + m_stream().oss.str(""); + } ResultBuilder::~ResultBuilder() { #if defined(CATCH_CONFIG_FAST_COMPILE) if ( m_guardException ) { - m_stream.oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; + m_stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; captureResult( ResultWas::ThrewException ); getCurrentContext().getResultCapture()->exceptionEarlyReported(); } @@ -55,7 +57,7 @@ namespace Catch { void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { m_assertionInfo.resultDisposition = resultDisposition; - m_stream.oss << Catch::translateActiveException(); + m_stream().oss << Catch::translateActiveException(); captureResult( ResultWas::ThrewException ); } @@ -143,7 +145,7 @@ namespace Catch { data.negate( expr.isBinaryExpression() ); } - data.message = m_stream.oss.str(); + data.message = m_stream().oss.str(); data.decomposedExpression = &expr; // for lazy reconstruction return AssertionResult( m_assertionInfo, data ); } From 616f7235efc875ee239c1dc6ddb48025e05e57ff Mon Sep 17 00:00:00 2001 From: Baruch Burstein Date: Tue, 20 Jun 2017 22:14:38 +0300 Subject: [PATCH 10/12] add --extra-info flag this will add line info to test lists, and test descriptions to the long form of the test list --- include/internal/catch_commandline.hpp | 4 ++++ include/internal/catch_config.hpp | 3 +++ include/internal/catch_list.hpp | 17 ++++++++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index 742f01a4..07115db4 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -187,6 +187,10 @@ namespace Catch { .describe( "list all/matching test cases names only" ) .bind( &ConfigData::listTestNamesOnly ); + cli["--extra-info"] + .describe( "list more info" ) + .bind( &ConfigData::extraInfo ); + cli["--list-reporters"] .describe( "list all reporters" ) .bind( &ConfigData::listReporters ); diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 174850bf..304fe32b 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -31,6 +31,7 @@ namespace Catch { listTags( false ), listReporters( false ), listTestNamesOnly( false ), + extraInfo( false ), showSuccessfulTests( false ), shouldDebugBreak( false ), noThrow( false ), @@ -50,6 +51,7 @@ namespace Catch { bool listTags; bool listReporters; bool listTestNamesOnly; + bool extraInfo; bool showSuccessfulTests; bool shouldDebugBreak; @@ -109,6 +111,7 @@ namespace Catch { bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } bool listTags() const { return m_data.listTags; } bool listReporters() const { return m_data.listReporters; } + bool extraInfo() const { return m_data.extraInfo; } std::string getProcessName() const { return m_data.processName; } diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp index e09898e9..b692f4e3 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.hpp @@ -30,8 +30,9 @@ namespace Catch { } std::size_t matchedTests = 0; - TextAttributes nameAttr, tagsAttr; + TextAttributes nameAttr, descAttr, tagsAttr; nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + descAttr.setIndent( 4 ); tagsAttr.setIndent( 6 ); std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); @@ -46,6 +47,13 @@ namespace Catch { Colour colourGuard( colour ); Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( config.extraInfo() ) { + Catch::cout() << " " << testCaseInfo.lineInfo << std::endl; + std::string description = testCaseInfo.description; + if( description == "" ) + description = "(NO DESCRIPTION)"; + Catch::cout() << Text( description, descAttr ) << std::endl; + } if( !testCaseInfo.tags.empty() ) Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; } @@ -69,9 +77,12 @@ namespace Catch { matchedTests++; TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); if( startsWith( testCaseInfo.name, '#' ) ) - Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl; + Catch::cout() << '"' << testCaseInfo.name << '"'; else - Catch::cout() << testCaseInfo.name << std::endl; + Catch::cout() << testCaseInfo.name; + if ( config.extraInfo() ) + Catch::cout() << "\t@" << testCaseInfo.lineInfo; + Catch::cout() << std::endl; } return matchedTests; } From 07c6bfc3b9aa473d41cd4abcd1962c093ca0f531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 22 Jun 2017 19:27:17 +0200 Subject: [PATCH 11/12] --extra-info -> --list-extra-info, behaves like other --list-* flags --- include/internal/catch_commandline.hpp | 6 +++--- include/internal/catch_config.hpp | 6 +++--- include/internal/catch_list.hpp | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index 07115db4..3ece92f8 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -187,9 +187,9 @@ namespace Catch { .describe( "list all/matching test cases names only" ) .bind( &ConfigData::listTestNamesOnly ); - cli["--extra-info"] - .describe( "list more info" ) - .bind( &ConfigData::extraInfo ); + cli["--list-extra-info"] + .describe( "list all/matching test cases with more info" ) + .bind( &ConfigData::listExtraInfo ); cli["--list-reporters"] .describe( "list all reporters" ) diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 304fe32b..b006d512 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -31,7 +31,7 @@ namespace Catch { listTags( false ), listReporters( false ), listTestNamesOnly( false ), - extraInfo( false ), + listExtraInfo( false ), showSuccessfulTests( false ), shouldDebugBreak( false ), noThrow( false ), @@ -51,7 +51,7 @@ namespace Catch { bool listTags; bool listReporters; bool listTestNamesOnly; - bool extraInfo; + bool listExtraInfo; bool showSuccessfulTests; bool shouldDebugBreak; @@ -111,7 +111,7 @@ namespace Catch { bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } bool listTags() const { return m_data.listTags; } bool listReporters() const { return m_data.listReporters; } - bool extraInfo() const { return m_data.extraInfo; } + bool listExtraInfo() const { return m_data.listExtraInfo; } std::string getProcessName() const { return m_data.processName; } diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp index b692f4e3..747b17c8 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.hpp @@ -47,10 +47,10 @@ namespace Catch { Colour colourGuard( colour ); Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; - if( config.extraInfo() ) { + if( config.listExtraInfo() ) { Catch::cout() << " " << testCaseInfo.lineInfo << std::endl; std::string description = testCaseInfo.description; - if( description == "" ) + if( description.empty() ) description = "(NO DESCRIPTION)"; Catch::cout() << Text( description, descAttr ) << std::endl; } @@ -80,7 +80,7 @@ namespace Catch { Catch::cout() << '"' << testCaseInfo.name << '"'; else Catch::cout() << testCaseInfo.name; - if ( config.extraInfo() ) + if ( config.listExtraInfo() ) Catch::cout() << "\t@" << testCaseInfo.lineInfo; Catch::cout() << std::endl; } @@ -174,7 +174,7 @@ namespace Catch { inline Option list( Config const& config ) { Option listedCount; - if( config.listTests() ) + if( config.listTests() || config.listExtraInfo() ) listedCount = listedCount.valueOr(0) + listTests( config ); if( config.listTestNamesOnly() ) listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); From 8a14af701e020311f9e7b13a0adba2692b12d5ec Mon Sep 17 00:00:00 2001 From: Baruch Burstein Date: Thu, 22 Jun 2017 23:00:18 +0300 Subject: [PATCH 12/12] If --list-extra-info is specified with --list-test-names-only, only output one list --- include/internal/catch_list.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp index 747b17c8..8a02611a 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.hpp @@ -174,7 +174,7 @@ namespace Catch { inline Option list( Config const& config ) { Option listedCount; - if( config.listTests() || config.listExtraInfo() ) + if( config.listTests() || ( config.listExtraInfo() && !config.listTestNamesOnly() ) ) listedCount = listedCount.valueOr(0) + listTests( config ); if( config.listTestNamesOnly() ) listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );