Compare commits

..

46 Commits

Author SHA1 Message Date
Martin Hořeňovský
0c015aa887 v1.8.2 release 2017-03-13 21:29:30 +01:00
Phil Nash
f69f821853 Updatecd [!shouldFail] docs with extra explanatory note, 2017-03-13 19:35:17 +00:00
Phil Nash
485dbdc0e7 Added link to event listeners docs 2017-03-13 19:27:18 +00:00
Phil Nash
0afd52b98d Fix Objective-C Matchers
Fixes #854
2017-03-13 15:40:21 +00:00
Phil Nash
38b05f1400 Don’t assume first CL arg (exe name) is present
Fixes #729
2017-03-13 11:00:58 +00:00
Phil Nash
db9866677e Don’t ref past end of string
fixes #830
2017-03-13 10:22:02 +00:00
Phil Nash
4101ff314a #include <ctype> for std::to lower 2017-03-10 19:25:00 +00:00
Phil Nash
68da5a6d19 Docs for Listeners 2017-03-10 19:17:25 +00:00
Phil Nash
e4a25ad5ff Added CATCH_REGISTER_LISTENER without the INTERNAL_ prefix 2017-03-10 19:15:03 +00:00
Phil Nash
5d6c744d38 Qualified std::tolower in Clara.
Fixes #543
2017-03-10 18:38:52 +00:00
Phil Nash
5dd0639520 Added FAIL_CHECK
Works like FAIL, but does not abort test.
As proposed in #765
2017-03-08 15:42:11 +00:00
Phil Nash
a2515755c3 Merge pull request #846 from m0ppers/patch-1
Add ArangoDB
2017-03-07 11:34:07 +00:00
m0ppers
807941eb31 Add ArangoDB 2017-03-07 12:29:13 +01:00
Martin Hořeňovský
a2e20b07f8 "Fix" build by annotating the new test as !shouldfail
The quick test under ctest checks only for no tests failing, not for the
expected output.
2017-03-07 10:17:59 +01:00
Martin Hořeňovský
ace70407a2 Add tests for #835
Also add ErrnoGuard before `isatty` call, because apparently it can set
errno to 25 (ENOTTY).
2017-03-06 22:07:33 +01:00
Martin Hořeňovský
613e1466f9 Save errno before using sprintf, ifstream.
std::ifstream in libstdc++ contains a bug, where it sets errno to zero.
To work around it, we manually save the errno before using std::ifstream
in debugger check, and reset it after we are done.

We also preventively save errno before using sprintf.

Fixes #835
2017-03-06 21:51:22 +01:00
Martin Hořeňovský
e95bf48445 Take std::string by const-ref where possible
Most places already do, this brings over some forgotten places.

Also close #842
2017-03-06 13:16:43 +01:00
Martin Hořeňovský
932a405e18 /Wx -> /WX (stupid typo) 2017-03-06 11:29:57 +01:00
Martin Hořeňovský
9a037204fa Enable /Wx (Warnings as error) for SelfTest builds 2017-03-06 11:21:35 +01:00
Martin Hořeňovský
374c050a42 benchmarkCompile.py fixup 2017-03-06 10:59:17 +01:00
Martin Hořeňovský
8b8e3ee117 Disable C4702 in Exception tests self tests
VS 2015 in Release mode sees through our indirection and complains.
There is no reason to make the indirectoin harder to reason about,
instead of just disabling the warning.
2017-03-06 10:52:21 +01:00
Martin Hořeňovský
af1ed708e4 Copied release note fixes to documentation 2017-03-06 10:46:21 +01:00
Phil Nash
041498b221 Fixed unintentional tabs 2017-03-06 09:23:31 +00:00
philsquared
d5a5883a10 Fixed mssing virtual destructor warnings
In Visual Studio with warning 4265 enabled
Closes #844
2017-03-06 08:59:52 +00:00
philsquared
6fea473414 Fixed CMake generation of MSVC warning levels 2017-03-06 08:35:14 +00:00
Phil Nash
68e7fdce20 Added 4265 to specific warnings in VS 2017-03-06 08:21:52 +00:00
Phil Nash
b4c9bf5802 Removed version # from readme
- and script that updates it (as it’s now automatically in a badge)
2017-03-03 15:40:32 +00:00
Phil Nash
e952fa8946 Added release badge 2017-03-03 15:25:58 +00:00
Phil Nash
84a178f0b0 Add AppVeyor status 2017-03-03 14:38:20 +00:00
Phil Nash
f9db24a824 Refactored console reporter include logic to match Xml Reporter’s 2017-03-03 14:19:41 +00:00
Phil Nash
9bee606dd6 Tweaked Xml Reporter to follow same success/ info behaviour as Console reporter 2017-03-03 14:12:47 +00:00
Martin Hořeňovský
be4f6ab8e1 Change reporting of CAPTURE'd variables
Info is not changed, intentionally.

Closes #639
2017-03-03 14:34:50 +01:00
Martin Hořeňovský
fd6c7aee6d Fixed compile benchmark script
Now it no longer attempts to enter a directory before creating it...
2017-03-02 18:27:31 +01:00
Martin Hořeňovský
cd6de9cd34 Don't reconstruct expression on encountering fatal error
In some cases, like when given

```cpp
std::vector<char>* str =
reinterpret_cast<std::vector<char>*>(0x1234458);
CHECK(*str == std::vector<char>());
```

reconstructing the expression to report it would cause another fatal
error. Instead we just put together an AssertionResult without
reconstructing the expression fully.

This should fully fix #810
2017-03-02 18:18:28 +01:00
Martin Hořeňovský
40f6a5b8a4 Added duration reporting to compact reporter
Also made the duration formatting code available to all reporters.

Closes #780
2017-03-02 16:16:17 +01:00
Martin Hořeňovský
95b0eb2b6c TAP reporter now behaves as if -s was always set
This should fulfill the TAP specification better.
2017-03-02 15:54:08 +01:00
Martin Hořeňovský
0b28d3daf2 Merge branch 'tap-count-success' of https://github.com/gahr/Catch 2017-03-02 15:23:46 +01:00
Phil Nash
8435dcbb61 Resized main logo again 2017-03-01 17:00:33 +00:00
Phil Nash
99347df70e Updated artwork 2017-03-01 16:47:04 +00:00
Phil Nash
658b5f63ef Updated release notes 2017-03-01 16:06:48 +00:00
Phil Nash
c6535a080e v1.8.1 release 2017-03-01 16:04:44 +00:00
Phil Nash
673ec550f5 Moved definition of _BSD_SOURCE earlier 2017-03-01 15:59:10 +00:00
Phil Nash
ff78e7c45a Fixed typo in test name 2017-03-01 15:59:10 +00:00
Pietro Cerutti
da023b2f9a TAP Reporter: count success tests even if not printed
This fixes a bug whereas running the TAP reporter without the -s switch
causes the reporter to print 1..0.
2017-03-01 09:24:58 +00:00
Phil Nash
470561cbbd Update release-notes.md
Removed speed up time placeholder
2017-03-01 08:24:16 +00:00
Phil Nash
417202b743 Update release-notes.md
Fixed docs/ paths
2017-03-01 08:22:38 +00:00
47 changed files with 838 additions and 270 deletions

View File

@@ -135,6 +135,7 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_debugger.h ${HEADER_DIR}/internal/catch_debugger.h
${HEADER_DIR}/internal/catch_debugger.hpp ${HEADER_DIR}/internal/catch_debugger.hpp
${HEADER_DIR}/internal/catch_default_main.hpp ${HEADER_DIR}/internal/catch_default_main.hpp
${HEADER_DIR}/internal/catch_errno_guard.hpp
${HEADER_DIR}/internal/catch_evaluate.hpp ${HEADER_DIR}/internal/catch_evaluate.hpp
${HEADER_DIR}/internal/catch_exception_translator_registry.hpp ${HEADER_DIR}/internal/catch_exception_translator_registry.hpp
${HEADER_DIR}/internal/catch_expression_lhs.hpp ${HEADER_DIR}/internal/catch_expression_lhs.hpp
@@ -253,7 +254,7 @@ if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
target_compile_options( Benchmark PRIVATE -Wall -Wextra ) target_compile_options( Benchmark PRIVATE -Wall -Wextra )
endif() endif()
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" ) if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
target_compile_options( SelfTest PRIVATE /W4 ) target_compile_options( SelfTest PRIVATE /W4 /w44265 /WX )
target_compile_options( Benchmark PRIVATE /W4 ) target_compile_options( Benchmark PRIVATE /W4 )
endif() endif()

View File

@@ -1,10 +1,10 @@
![catch logo](catch-logo-small.png) ![catch logo](catch-logo-small.png)
*v1.8.0* [![Github Releases](https://img.shields.io/github/release/philsquared/catch.svg)](https://github.com/philsquared/catch/releases)
[![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)
Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=master)](https://travis-ci.org/philsquared/Catch) <a href="https://github.com/philsquared/Catch/releases/download/v1.8.2/catch.hpp">The latest, single header, version can be downloaded directly using this link</a>
<a href="https://github.com/philsquared/Catch/releases/download/v1.8.0/catch.hpp">The latest, single header, version can be downloaded directly using this link</a>
## What's the Catch? ## What's the Catch?

BIN
catch-hand-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
catch-icon-tiny.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -7,11 +7,12 @@ Before looking at this material be sure to read the [tutorial](tutorial.md)
* [Logging macros](logging.md) * [Logging macros](logging.md)
* [Test cases and sections](test-cases-and-sections.md) * [Test cases and sections](test-cases-and-sections.md)
* [Test fixtures](test-fixtures.md) * [Test fixtures](test-fixtures.md)
* [Command line](command-line.md)
* [Build systems](build-systems.md)
* [Supplying your own main()](own-main.md) * [Supplying your own main()](own-main.md)
* [Event Listeners](event-listeners.md)
* [Configuration](configuration.md) * [Configuration](configuration.md)
* [String Conversions](tostring.md) * [String Conversions](tostring.md)
* [Command line](command-line.md)
* [Build systems](build-systems.md)
* [Why are my tests slow to compile?](slow-compiles.md) * [Why are my tests slow to compile?](slow-compiles.md)
* [Known limitations](limitations.md) * [Known limitations](limitations.md)

73
docs/event-listeners.md Normal file
View File

@@ -0,0 +1,73 @@
# Event Listeners
A `Listener` is a class you can register with Catch that will then be passed events,
such as a test case starting or ending, as they happen during a test run.
`Listeners` are actually types of `Reporters`, with a few small differences:
1. Once registered in code they are automatically used - you don't need to specify them on the command line
2. They are called in addition to (just before) any reporters, and you can register multiple listeners.
3. They derive from `Catch::TestEventListenerBase`, which has default stubs for all the events,
so you are not forced to implement events you're not interested in.
4. You register a listener with `CATCH_REGISTER_LISTENER`
## Implementing a Listener
In your main source file (i.e. the one that has the `#define` for `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`),
simply derive a class from `Catch::TestEventListenerBase` and implement the methods you are interested in.
Then register it using `INTERNAL_CATCH_REGISTER_LISTENER`.
For example:
```c++
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
struct MyListener : Catch::TestEventListenerBase {
using TestEventListenerBase::TestEventListenerBase; // inherit constructor
virtual void testCaseStarting( Catch::TestCaseInfo const& testInfo ) override {
// Perform some setup before a test case is run
}
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override {
// Tear-down after a test case is run
}
};
CATCH_REGISTER_LISTENER( MyListener )
```
_Note that you should not use any assertion macros within a Listener!_
## Events that can be hooked
The following are the methods that can be overriden in the Listener:
```c++
// The whole test run, starting and ending
virtual void testRunStarting( TestRunInfo const& testRunInfo );
virtual void testRunEnded( TestRunStats const& testRunStats );
// Test cases starting and ending
virtual void testCaseStarting( TestCaseInfo const& testInfo );
virtual void testCaseEnded( TestCaseStats const& testCaseStats );
// Sections starting and ending
virtual void sectionStarting( SectionInfo const& sectionInfo );
virtual void sectionEnded( SectionStats const& sectionStats );
// Assertions before/ after
virtual void assertionStarting( AssertionInfo const& assertionInfo );
virtual bool assertionEnded( AssertionStats const& assertionStats );
// A test is being skipped (because it is "hidden")
virtual void skipTest( TestCaseInfo const& testInfo );
```
More information about the events (e.g. name of the test case) is contained in the structs passed as arguments -
just look in the source code to see what fields are available.
---
[Home](Readme.md)

View File

@@ -26,6 +26,10 @@ The message is always reported but does not fail the test.
The message is reported and the test case fails. The message is reported and the test case fails.
**FAIL_CHECK(** _message expression_ **)**
AS `FAIL`, but does not abort the test
## Quickly capture a variable value ## Quickly capture a variable value
**CAPTURE(** _expression_ **)** **CAPTURE(** _expression_ **)**

View File

@@ -48,6 +48,9 @@ A thread safe header only mocking framework for C++14
## Applications & Tools ## Applications & Tools
### [ArangoDB](https://github.com/arangodb/arangodb)
ArangoDB is a native multi-model database with flexible data models for documents, graphs, and key-values.
### [MAME](https://github.com/mamedev/mame) ### [MAME](https://github.com/mamedev/mame)
MAME originally stood for Multiple Arcade Machine Emulator MAME originally stood for Multiple Arcade Machine Emulator

View File

@@ -1,3 +1,48 @@
# 1.8.2
### Improvements and minor changes
* TAP reporter now behaves as if `-s` was always set
* This should be more consistent with the protocol desired behaviour.
* Compact reporter now obeys `-d yes` argument (#780)
* The format is "XXX.123 s: <section-name>" (3 decimal places are always present).
* Before it did not report the durations at all.
* XML reporter now behaves the same way as Console reporter in regards to `INFO`
* This means it reports `INFO` messages on success, if output on success (`-s`) is enabled.
* Previously it only reported `INFO` messages on failure.
* `CAPTURE(expr)` now stringifies `expr` in the same way assertion macros do (#639)
* Listeners are now finally [documented](event-listeners.md).
* Listeners provide a way to hook into events generated by running your tests, including start and end of run, every test case, every section and every assertion.
### Fixes:
* Catch no longer attempts to reconstruct expression that led to a fatal error (#810)
* This fixes possible signal/SEH loop when processing expressions, where the signal was triggered by expression decomposition.
* Fixed (C4265) missing virtual destructor warning in Matchers (#844)
* `std::string`s are now taken by `const&` everywhere (#842).
* Previously some places were taking them by-value.
* Catch should no longer change errno (#835).
* This was caused by libstdc++ bug that we now work around.
* Catch now provides `FAIL_CHECK( ... )` macro (#765).
* Same as `FAIL( ... )`, but does not abort the test.
* Functions like `fabs`, `tolower`, `memset`, `isalnum` are now used with `std::` qualification (#543).
* Clara no longer assumes first argument (binary name) is always present (#729)
* If it is missing, empty string is used as default.
* Clara no longer reads 1 character past argument string (#830)
### Other notes:
* We have added VS 2013 and 2015 to our CI
* Catch Classic (1.x.x) now contains its own, forked, version of Clara (the argument parser).
# 1.8.1
### Fixes
Cygwin issue with `gettimeofday` - `#define` was not early enough
# 1.8.0 # 1.8.0
### New features/ minor changes ### New features/ minor changes
@@ -11,14 +56,14 @@
* Added opt-in leak detection under MSVC + Windows (#439) * Added opt-in leak detection under MSVC + Windows (#439)
* Enable it by compiling Catch's main with `CATCH_CONFIG_WINDOWS_CRTDBG` * Enable it by compiling Catch's main with `CATCH_CONFIG_WINDOWS_CRTDBG`
* Introduced new compile-time flag, `CATCH_CONFIG_FAST_COMPILE`, trading features for compilation speed. * Introduced new compile-time flag, `CATCH_CONFIG_FAST_COMPILE`, trading features for compilation speed.
* Moves debug breaks out of tests and into implementation, speeding up compilation time by ~XX% * Moves debug breaks out of tests and into implementation, speeding up test compilation time (~10% on linux).
* _More changes are coming_ * _More changes are coming_
* Added [TAP (Test Anything Protocol)](https://testanything.org/) and [Automake](https://www.gnu.org/software/automake/manual/html_node/Log-files-generation-and-test-results-recording.html#Log-files-generation-and-test-results-recording) reporters. * Added [TAP (Test Anything Protocol)](https://testanything.org/) and [Automake](https://www.gnu.org/software/automake/manual/html_node/Log-files-generation-and-test-results-recording.html#Log-files-generation-and-test-results-recording) reporters.
* These are not present in the default single-include header and need to be downloaded from GitHub separately. * These are not present in the default single-include header and need to be downloaded from GitHub separately.
* For details see [documentation about integrating with build systems](docs/build-systems.md). * For details see [documentation about integrating with build systems](build-systems.md).
* XML reporter now reports filename as part of the `Section` and `TestCase` tags. * XML reporter now reports filename as part of the `Section` and `TestCase` tags.
* `Approx` now supports an optional margin of absolute error * `Approx` now supports an optional margin of absolute error
* It has also received [new documentation](). * It has also received [new documentation](docs/assertions.md).
### Fixes ### Fixes
* Silenced C4312 ("conversion from int to 'ClassName *") warnings in the evaluate layer. * Silenced C4312 ("conversion from int to 'ClassName *") warnings in the evaluate layer.

View File

@@ -38,10 +38,10 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch.
* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`. * `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`.
* `[!shouldfail]` - reverse the failing logic of the test: if the test is successful if it fails, and vice-versa.
* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in the your tests. * `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in the your tests.
* `[!shouldfail]` - like `[!mayfail]` but *fails* the test if it *passes*. This can be useful if you want to be notified of accidental, or third-party, fixes.
* `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers. * `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers.
* `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped) as a tag. e.g. tests in testfile.cpp would all be tagged `[#testfile]`. * `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped) as a tag. e.g. tests in testfile.cpp would all be tagged `[#testfile]`.

View File

@@ -116,8 +116,8 @@ LeakDetector leakDetector;
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << Catch::toString(msg), "CATCH_CAPTURE" )
#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << Catch::toString(msg), "CATCH_CAPTURE" )
#ifdef CATCH_CONFIG_VARIADIC_MACROS #ifdef CATCH_CONFIG_VARIADIC_MACROS
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
@@ -126,6 +126,7 @@ LeakDetector leakDetector;
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, "CATCH_FAIL_CHECK", __VA_ARGS__ )
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
#else #else
#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
@@ -134,6 +135,7 @@ LeakDetector leakDetector;
#define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
#define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, "CATCH_FAIL_CHECK", msg )
#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
#endif #endif
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
@@ -185,24 +187,26 @@ LeakDetector leakDetector;
#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) #define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) #define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << Catch::toString(msg), "CAPTURE" )
#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << Catch::toString(msg), "CAPTURE" )
#ifdef CATCH_CONFIG_VARIADIC_MACROS #ifdef CATCH_CONFIG_VARIADIC_MACROS
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, "FAIL_CHECK", __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
#else #else
#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
#define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
#define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
#define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
#define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, "FAIL_CHECK", msg )
#define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
#endif #endif
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )

View File

@@ -41,6 +41,7 @@
#include <vector> #include <vector>
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
#include <cctype>
// Use optional outer namespace // Use optional outer namespace
#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
@@ -397,7 +398,7 @@ namespace Clara {
_dest = _source; _dest = _source;
} }
char toLowerCh(char c) { char toLowerCh(char c) {
return static_cast<char>( ::tolower( c ) ); return static_cast<char>( std::tolower( c ) );
} }
inline void convertInto( std::string const& _source, bool& _dest ) { inline void convertInto( std::string const& _source, bool& _dest ) {
std::string sourceLC = _source; std::string sourceLC = _source;
@@ -553,12 +554,13 @@ namespace Clara {
} }
void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) { void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
for( std::size_t i = 0; i <= arg.size(); ++i ) { for( std::size_t i = 0; i < arg.size(); ++i ) {
char c = arg[i]; char c = arg[i];
if( c == '"' ) if( c == '"' )
inQuotes = !inQuotes; inQuotes = !inQuotes;
mode = handleMode( i, c, arg, tokens ); mode = handleMode( i, c, arg, tokens );
} }
mode = handleMode( arg.size(), '\0', arg, tokens );
} }
Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) { Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
switch( mode ) { switch( mode ) {
@@ -591,6 +593,7 @@ namespace Clara {
default: from = i; return ShortOpt; default: from = i; return ShortOpt;
} }
} }
Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) { Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
return mode; return mode;
@@ -924,7 +927,7 @@ namespace Clara {
} }
std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const { std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
std::string processName = args[0]; std::string processName = args.empty() ? std::string() : args[0];
std::size_t lastSlash = processName.find_last_of( "/\\" ); std::size_t lastSlash = processName.find_last_of( "/\\" );
if( lastSlash != std::string::npos ) if( lastSlash != std::string::npos )
processName = processName.substr( lastSlash+1 ); processName = processName.substr( lastSlash+1 );

View File

@@ -81,6 +81,10 @@
# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
# endif # endif
// Required for some versions of Cygwin to declare gettimeofday
// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
# define _BSD_SOURCE
#endif // __CYGWIN__ #endif // __CYGWIN__
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@@ -9,6 +9,7 @@
#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
#include "catch_console_colour.hpp" #include "catch_console_colour.hpp"
#include "catch_errno_guard.hpp"
namespace Catch { namespace Catch {
namespace { namespace {
@@ -148,6 +149,7 @@ namespace {
}; };
IColourImpl* platformColourInstance() { IColourImpl* platformColourInstance() {
ErrnoGuard guard;
Ptr<IConfig const> config = getCurrentContext().getConfig(); Ptr<IConfig const> config = getCurrentContext().getConfig();
UseColour::YesOrNo colourMode = config UseColour::YesOrNo colourMode = config
? config->useColour() ? config->useColour()

View File

@@ -10,6 +10,7 @@
#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
#include "catch_debugger.h" #include "catch_debugger.h"
#include "catch_errno_guard.hpp"
#ifdef CATCH_PLATFORM_MAC #ifdef CATCH_PLATFORM_MAC
@@ -72,6 +73,9 @@
// be strace, for example) in /proc/$PID/status, so just get it from // be strace, for example) in /proc/$PID/status, so just get it from
// there instead. // there instead.
bool isDebuggerActive(){ bool isDebuggerActive(){
// Libstdc++ has a bug, where std::ifstream sets errno to 0
// This way our users can properly assert over errno values
ErrnoGuard guard;
std::ifstream in("/proc/self/status"); std::ifstream in("/proc/self/status");
for( std::string line; std::getline(in, line); ) { for( std::string line; std::getline(in, line); ) {
static const int PREFIX_LEN = 11; static const int PREFIX_LEN = 11;

View File

@@ -0,0 +1,25 @@
/*
* Created by Martin on 06/03/2017.
*
* 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_ERRNO_GUARD_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED
#include <cerrno>
namespace Catch {
class ErrnoGuard {
public:
ErrnoGuard():m_oldErrno(errno){}
~ErrnoGuard() { errno = m_oldErrno; }
private:
int m_oldErrno;
};
}
#endif // TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED

View File

@@ -53,7 +53,6 @@ namespace Catch {
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
reset();
reportFatal(signalDefs[i].name); reportFatal(signalDefs[i].name);
} }
} }

View File

@@ -91,6 +91,7 @@ namespace Catch {
TestSpec::NamePattern::~NamePattern() {} TestSpec::NamePattern::~NamePattern() {}
TestSpec::TagPattern::~TagPattern() {} TestSpec::TagPattern::~TagPattern() {}
TestSpec::ExcludedPattern::~ExcludedPattern() {} TestSpec::ExcludedPattern::~ExcludedPattern() {}
Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {}
void Config::dummy() {} void Config::dummy() {}

View File

@@ -27,16 +27,25 @@ namespace Matchers {
} }
protected: protected:
virtual ~MatcherUntypedBase();
virtual std::string describe() const = 0; virtual std::string describe() const = 0;
mutable std::string m_cachedToString; mutable std::string m_cachedToString;
private: private:
MatcherUntypedBase& operator = ( MatcherUntypedBase const& ); MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
}; };
template<typename ObjectT, typename ComparatorT = ObjectT> template<typename ObjectT>
struct MatcherBase : MatcherUntypedBase { struct MatcherMethod {
virtual bool match( ObjectT const& arg ) const = 0; virtual bool match( ObjectT const& arg ) const = 0;
};
template<typename PtrT>
struct MatcherMethod<PtrT*> {
virtual bool match( PtrT* arg ) const = 0;
};
template<typename ObjectT, typename ComparatorT = ObjectT>
struct MatcherBase : MatcherUntypedBase, MatcherMethod<ObjectT> {
MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const; MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const;
MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const; MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;

View File

@@ -26,7 +26,7 @@ namespace Matchers {
}; };
struct StringMatcherBase : MatcherBase<std::string> { struct StringMatcherBase : MatcherBase<std::string> {
StringMatcherBase( std::string operation, CasedString const& comparator ); StringMatcherBase( std::string const& operation, CasedString const& comparator );
virtual std::string describe() const CATCH_OVERRIDE; virtual std::string describe() const CATCH_OVERRIDE;
CasedString m_comparator; CasedString m_comparator;

View File

@@ -29,7 +29,7 @@ namespace Matchers {
} }
StringMatcherBase::StringMatcherBase( std::string operation, CasedString const& comparator ) StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
: m_comparator( comparator ), : m_comparator( comparator ),
m_operation( operation ) { m_operation( operation ) {
} }

View File

@@ -104,65 +104,68 @@ namespace Catch {
namespace Matchers { namespace Matchers {
namespace Impl { namespace Impl {
namespace NSStringMatchers { namespace NSStringMatchers {
template<typename MatcherT> struct StringHolder : MatcherBase<NSString*>{
struct StringHolder : MatcherImpl<MatcherT, NSString*>{
StringHolder( NSString* substr ) : m_substr( [substr copy] ){} StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
StringHolder() { StringHolder() {
arcSafeRelease( m_substr ); arcSafeRelease( m_substr );
} }
virtual bool match( NSString* arg ) const CATCH_OVERRIDE {
return false;
}
NSString* m_substr; NSString* m_substr;
}; };
struct Equals : StringHolder<Equals> { struct Equals : StringHolder {
Equals( NSString* substr ) : StringHolder( substr ){} Equals( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const { virtual bool match( NSString* str ) const CATCH_OVERRIDE {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str isEqualToString:m_substr]; [str isEqualToString:m_substr];
} }
virtual std::string toString() const { virtual std::string describe() const CATCH_OVERRIDE {
return "equals string: " + Catch::toString( m_substr ); return "equals string: " + Catch::toString( m_substr );
} }
}; };
struct Contains : StringHolder<Contains> { struct Contains : StringHolder {
Contains( NSString* substr ) : StringHolder( substr ){} Contains( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const { virtual bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location != NSNotFound; [str rangeOfString:m_substr].location != NSNotFound;
} }
virtual std::string toString() const { virtual std::string describe() const CATCH_OVERRIDE {
return "contains string: " + Catch::toString( m_substr ); return "contains string: " + Catch::toString( m_substr );
} }
}; };
struct StartsWith : StringHolder<StartsWith> { struct StartsWith : StringHolder {
StartsWith( NSString* substr ) : StringHolder( substr ){} StartsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const { virtual bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == 0; [str rangeOfString:m_substr].location == 0;
} }
virtual std::string toString() const { virtual std::string describe() const CATCH_OVERRIDE {
return "starts with: " + Catch::toString( m_substr ); return "starts with: " + Catch::toString( m_substr );
} }
}; };
struct EndsWith : StringHolder<EndsWith> { struct EndsWith : StringHolder {
EndsWith( NSString* substr ) : StringHolder( substr ){} EndsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const { virtual bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == [str length] - [m_substr length]; [str rangeOfString:m_substr].location == [str length] - [m_substr length];
} }
virtual std::string toString() const { virtual std::string describe() const CATCH_OVERRIDE {
return "ends with: " + Catch::toString( m_substr ); return "ends with: " + Catch::toString( m_substr );
} }
}; };

View File

@@ -92,7 +92,11 @@ namespace Catch {
#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
// Deprecated - use the form without INTERNAL_
#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ #define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
#define CATCH_REGISTER_LISTENER( listenerType ) \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
#endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED

View File

@@ -224,10 +224,14 @@ namespace Catch {
} }
virtual void handleFatalErrorCondition( std::string const& message ) { virtual void handleFatalErrorCondition( std::string const& message ) {
ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); // Don't rebuild the result -- the stringification itself can cause more fatal errors
resultBuilder.setResultType( ResultWas::FatalErrorCondition ); // Instead, fake a result data.
resultBuilder << message; AssertionResultData tempResult;
resultBuilder.captureExpression(); tempResult.resultType = ResultWas::FatalErrorCondition;
tempResult.message = message;
AssertionResult result(m_lastAssertionInfo, tempResult);
getResultCapture().assertionEnded(result);
handleUnfinishedSections(); handleUnfinishedSections();

View File

@@ -15,7 +15,7 @@
namespace Catch { namespace Catch {
struct TagAlias { struct TagAlias {
TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
std::string tag; std::string tag;
SourceLineInfo lineInfo; SourceLineInfo lineInfo;

View File

@@ -20,13 +20,8 @@
#else #else
// Required for some versions of Cygwin to declare gettimeofday
// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
# ifdef __CYGWIN__
# define _BSD_SOURCE
# endif
#include <sys/time.h> #include <sys/time.h>
#endif #endif
namespace Catch { namespace Catch {

View File

@@ -37,7 +37,7 @@ namespace Catch {
return os; return os;
} }
Version libraryVersion( 1, 8, 0, "", 0 ); Version libraryVersion( 1, 8, 2, "", 0 );
} }

View File

@@ -9,12 +9,38 @@
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
#include "../internal/catch_interfaces_reporter.h" #include "../internal/catch_interfaces_reporter.h"
#include "../internal/catch_errno_guard.hpp"
#include <cstring> #include <cstring>
#include <cfloat>
#include <cstdio>
#include <assert.h> #include <assert.h>
namespace Catch { namespace Catch {
namespace {
// Because formatting using c++ streams is stateful, drop down to C is required
// Alternatively we could use stringstream, but its performance is... not good.
std::string getFormattedDuration( double duration ) {
// Max exponent + 1 is required to represent the whole part
// + 1 for decimal point
// + 3 for the 3 decimal places
// + 1 for null terminator
const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
char buffer[maxDoubleSize];
// Save previous errno, to prevent sprintf from overwriting it
ErrnoGuard guard;
#ifdef _MSC_VER
sprintf_s(buffer, "%.3f", duration);
#else
sprintf(buffer, "%.3f", duration);
#endif
return std::string(buffer);
}
}
struct StreamingReporterBase : SharedImpl<IStreamingReporter> { struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
StreamingReporterBase( ReporterConfig const& _config ) StreamingReporterBase( ReporterConfig const& _config )

View File

@@ -37,8 +37,7 @@ namespace Catch {
stream << "No test cases matched '" << spec << '\'' << std::endl; stream << "No test cases matched '" << spec << '\'' << std::endl;
} }
virtual void assertionStarting( AssertionInfo const& ) { virtual void assertionStarting( AssertionInfo const& ) {}
}
virtual bool assertionEnded( AssertionStats const& _assertionStats ) { virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
AssertionResult const& result = _assertionStats.assertionResult; AssertionResult const& result = _assertionStats.assertionResult;
@@ -59,6 +58,12 @@ namespace Catch {
return true; return true;
} }
virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE {
if (m_config->showDurations() == ShowDurations::Always) {
stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
}
}
virtual void testRunEnded( TestRunStats const& _testRunStats ) { virtual void testRunEnded( TestRunStats const& _testRunStats ) {
printTotals( _testRunStats.totals ); printTotals( _testRunStats.totals );
stream << '\n' << std::endl; stream << '\n' << std::endl;
@@ -164,7 +169,7 @@ namespace Catch {
stream << result.getSourceInfo() << ':'; stream << result.getSourceInfo() << ':';
} }
void printResultType( Colour::Code colour, std::string passOrFail ) const { void printResultType( Colour::Code colour, std::string const& passOrFail ) const {
if( !passOrFail.empty() ) { if( !passOrFail.empty() ) {
{ {
Colour colourGuard( colour ); Colour colourGuard( colour );
@@ -174,7 +179,7 @@ namespace Catch {
} }
} }
void printIssue( std::string issue ) const { void printIssue( std::string const& issue ) const {
stream << ' ' << issue; stream << ' ' << issue;
} }

View File

@@ -18,25 +18,6 @@
namespace Catch { namespace Catch {
namespace {
// Because formatting using c++ streams is stateful, drop down to C is required
// Alternatively we could use stringstream, but its performance is... not good.
std::string getFormattedDuration( double duration ) {
// Max exponent + 1 is required to represent the whole part
// + 1 for decimal point
// + 3 for the 3 decimal places
// + 1 for null terminator
const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
char buffer[maxDoubleSize];
#ifdef _MSC_VER
sprintf_s(buffer, "%.3f", duration);
#else
sprintf(buffer, "%.3f", duration);
#endif
return std::string(buffer);
}
}
struct ConsoleReporter : StreamingReporterBase { struct ConsoleReporter : StreamingReporterBase {
ConsoleReporter( ReporterConfig const& _config ) ConsoleReporter( ReporterConfig const& _config )
@@ -59,18 +40,15 @@ namespace Catch {
virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
AssertionResult const& result = _assertionStats.assertionResult; AssertionResult const& result = _assertionStats.assertionResult;
bool printInfoMessages = true; bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
// Drop out if result was successful and we're not printing those // Drop out if result was successful but we're not printing them.
if( !m_config->includeSuccessfulResults() && result.isOk() ) { if( !includeResults && result.getResultType() != ResultWas::Warning )
if( result.getResultType() != ResultWas::Warning ) return false;
return false;
printInfoMessages = false;
}
lazyPrint(); lazyPrint();
AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); AssertionPrinter printer( stream, _assertionStats, includeResults );
printer.print(); printer.print();
stream << std::endl; stream << std::endl;
return true; return true;

View File

@@ -45,18 +45,9 @@ namespace Catch {
virtual void assertionStarting( AssertionInfo const& ) {} virtual void assertionStarting( AssertionInfo const& ) {}
virtual bool assertionEnded( AssertionStats const& _assertionStats ) { virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
AssertionResult const& result = _assertionStats.assertionResult; ++counter;
bool printInfoMessages = true; AssertionPrinter printer( stream, _assertionStats, counter );
// Drop out if result was successful and we're not printing those
if ( !m_config->includeSuccessfulResults() && result.isOk() ) {
if ( result.getResultType() != ResultWas::Warning )
return false;
printInfoMessages = false;
}
AssertionPrinter printer( stream, _assertionStats, printInfoMessages, ++counter );
printer.print(); printer.print();
stream << " # " << currentTestCaseInfo->name ; stream << " # " << currentTestCaseInfo->name ;
@@ -75,13 +66,13 @@ namespace Catch {
class AssertionPrinter { class AssertionPrinter {
void operator= ( AssertionPrinter const& ); void operator= ( AssertionPrinter const& );
public: public:
AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages, size_t counter = 0 ) AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, size_t counter )
: stream( _stream ) : stream( _stream )
, stats( _stats ) , stats( _stats )
, result( _stats.assertionResult ) , result( _stats.assertionResult )
, messages( _stats.infoMessages ) , messages( _stats.infoMessages )
, itMessage( _stats.infoMessages.begin() ) , itMessage( _stats.infoMessages.begin() )
, printInfoMessages( _printInfoMessages ) , printInfoMessages( true )
, counter(counter) , counter(counter)
{} {}
@@ -156,28 +147,23 @@ namespace Catch {
} }
private: private:
static Colour::Code dimColour() { return Colour::FileName; } static Colour::Code dimColour() { return Colour::FileName; }
static const char* failedString() { return "not ok"; } static const char* failedString() { return "not ok"; }
static const char* passedString() { return "ok"; } static const char* passedString() { return "ok"; }
void printSourceInfo() const { void printSourceInfo() const {
Colour colourGuard( Colour::FileName ); Colour colourGuard( dimColour() );
stream << result.getSourceInfo() << ":"; stream << result.getSourceInfo() << ":";
} }
void printResultType( std::string passOrFail ) const { void printResultType( std::string const& passOrFail ) const {
if( !passOrFail.empty() ) { if( !passOrFail.empty() ) {
{ stream << passOrFail << ' ' << counter << " -";
//Colour colourGuard( colour );
stream << passOrFail << " " << counter;
}
stream << " -";
} }
} }
void printIssue( std::string issue ) const { void printIssue( std::string const& issue ) const {
stream << " " << issue; stream << " " << issue;
} }
@@ -218,8 +204,9 @@ namespace Catch {
} }
void printRemainingMessages( Colour::Code colour = dimColour() ) { void printRemainingMessages( Colour::Code colour = dimColour() ) {
if ( itMessage == messages.end() ) if (itMessage == messages.end()) {
return; return;
}
// using messages.end() directly yields compilation error: // using messages.end() directly yields compilation error:
std::vector<MessageInfo>::const_iterator itEnd = messages.end(); std::vector<MessageInfo>::const_iterator itEnd = messages.end();
@@ -252,17 +239,6 @@ namespace Catch {
size_t counter; size_t counter;
}; };
// Colour, message variants:
// - white: No tests ran.
// - red: Failed [both/all] N test cases, failed [both/all] M assertions.
// - white: Passed [both/all] N test cases (no assertions).
// - red: Failed N tests cases, failed M assertions.
// - green: Passed [both/all] N tests cases with M assertions.
std::string bothOrAll( std::size_t count ) const {
return count == 1 ? "" : count == 2 ? "both " : "all " ;
}
void printTotals( const Totals& totals ) const { void printTotals( const Totals& totals ) const {
if( totals.testCases.total() == 0 ) { if( totals.testCases.total() == 0 ) {
stream << "1..0 # Skipped: No tests ran."; stream << "1..0 # Skipped: No tests ran.";

View File

@@ -92,73 +92,77 @@ namespace Catch {
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
const AssertionResult& assertionResult = assertionStats.assertionResult;
// Print any info messages in <Info> tags. AssertionResult const& result = assertionStats.assertionResult;
if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
if( includeResults ) {
// Print any info messages in <Info> tags.
for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
it != itEnd; it != itEnd;
++it ) { ++it ) {
if( it->type == ResultWas::Info ) { if( it->type == ResultWas::Info ) {
m_xml.scopedElement( "Info" ) m_xml.scopedElement( "Info" )
.writeText( it->message ); .writeText( it->message );
} else if ( it->type == ResultWas::Warning ) { } else if ( it->type == ResultWas::Warning ) {
m_xml.scopedElement( "Warning" ) m_xml.scopedElement( "Warning" )
.writeText( it->message ); .writeText( it->message );
} }
} }
} }
// Drop out if result was successful but we're not printing them. // Drop out if result was successful but we're not printing them.
if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) if( !includeResults && result.getResultType() != ResultWas::Warning )
return true; return true;
// Print the expression if there is one.
if( assertionResult.hasExpression() ) {
m_xml.startElement( "Expression" )
.writeAttribute( "success", assertionResult.succeeded() )
.writeAttribute( "type", assertionResult.getTestMacroName() );
writeSourceInfo( assertionResult.getSourceInfo() ); // Print the expression if there is one.
if( result.hasExpression() ) {
m_xml.startElement( "Expression" )
.writeAttribute( "success", result.succeeded() )
.writeAttribute( "type", result.getTestMacroName() );
writeSourceInfo( result.getSourceInfo() );
m_xml.scopedElement( "Original" ) m_xml.scopedElement( "Original" )
.writeText( assertionResult.getExpression() ); .writeText( result.getExpression() );
m_xml.scopedElement( "Expanded" ) m_xml.scopedElement( "Expanded" )
.writeText( assertionResult.getExpandedExpression() ); .writeText( result.getExpandedExpression() );
} }
// And... Print a result applicable to each result type. // And... Print a result applicable to each result type.
switch( assertionResult.getResultType() ) { switch( result.getResultType() ) {
case ResultWas::ThrewException: case ResultWas::ThrewException:
m_xml.startElement( "Exception" ); m_xml.startElement( "Exception" );
writeSourceInfo( assertionResult.getSourceInfo() ); writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() ); m_xml.writeText( result.getMessage() );
m_xml.endElement(); m_xml.endElement();
break; break;
case ResultWas::FatalErrorCondition: case ResultWas::FatalErrorCondition:
m_xml.startElement( "FatalErrorCondition" ); m_xml.startElement( "FatalErrorCondition" );
writeSourceInfo( assertionResult.getSourceInfo() ); writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() ); m_xml.writeText( result.getMessage() );
m_xml.endElement(); m_xml.endElement();
break; break;
case ResultWas::Info: case ResultWas::Info:
m_xml.scopedElement( "Info" ) m_xml.scopedElement( "Info" )
.writeText( assertionResult.getMessage() ); .writeText( result.getMessage() );
break; break;
case ResultWas::Warning: case ResultWas::Warning:
// Warning will already have been written // Warning will already have been written
break; break;
case ResultWas::ExplicitFailure: case ResultWas::ExplicitFailure:
m_xml.startElement( "Failure" ); m_xml.startElement( "Failure" );
writeSourceInfo( assertionResult.getSourceInfo() ); writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() ); m_xml.writeText( result.getMessage() );
m_xml.endElement(); m_xml.endElement();
break; break;
default: default:
break; break;
} }
if( assertionResult.hasExpression() ) if( result.hasExpression() )
m_xml.endElement(); m_xml.endElement();
return true; return true;

View File

@@ -3,6 +3,17 @@
<exe-name> is a <version> host application. <exe-name> is a <version> host application.
Run with -? for options Run with -? for options
-------------------------------------------------------------------------------
#835 -- errno should not be touched by Catch
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK( f() == 0 )
with expansion:
1 == 0
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
'Not' checks that should fail 'Not' checks that should fail
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -276,6 +287,20 @@ MessageTests.cpp:<line number>
MessageTests.cpp:<line number>: FAILED: MessageTests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
FAIL_CHECK does not abort the test
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
explicitly with message:
This is a failure
MessageTests.cpp:<line number>:
warning:
This message appears in the output
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
INFO and WARN do not abort tests INFO and WARN do not abort tests
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -890,6 +915,6 @@ with expansion:
"first" == "second" "first" == "second"
=============================================================================== ===============================================================================
test cases: 163 | 118 passed | 43 failed | 2 failed as expected test cases: 166 | 119 passed | 44 failed | 3 failed as expected
assertions: 953 | 849 passed | 86 failed | 18 failed as expected assertions: 961 | 855 passed | 87 failed | 19 failed as expected

View File

@@ -48,6 +48,23 @@ PASSED:
with expansion: with expansion:
42 == {?} 42 == {?}
-------------------------------------------------------------------------------
#835 -- errno should not be touched by Catch
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK( f() == 0 )
with expansion:
1 == 0
MiscTests.cpp:<line number>:
PASSED:
REQUIRE( (*__error()) == 1 )
with expansion:
1 == 1
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
'Not' checks that should fail 'Not' checks that should fail
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -603,6 +620,32 @@ PASSED:
with expansion: with expansion:
true true
-------------------------------------------------------------------------------
Capture and info messages
Capture should stringify like assertions
-------------------------------------------------------------------------------
ToStringGeneralTests.cpp:<line number>
...............................................................................
ToStringGeneralTests.cpp:<line number>:
PASSED:
REQUIRE( true )
with message:
i := 2
-------------------------------------------------------------------------------
Capture and info messages
Info should NOT stringify the way assertions do
-------------------------------------------------------------------------------
ToStringGeneralTests.cpp:<line number>
...............................................................................
ToStringGeneralTests.cpp:<line number>:
PASSED:
REQUIRE( true )
with message:
3
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Character pretty printing Character pretty printing
Specifically escaped Specifically escaped
@@ -1173,6 +1216,20 @@ MessageTests.cpp:<line number>
MessageTests.cpp:<line number>: FAILED: MessageTests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
FAIL_CHECK does not abort the test
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
...............................................................................
MessageTests.cpp:<line number>: FAILED:
explicitly with message:
This is a failure
MessageTests.cpp:<line number>:
warning:
This message appears in the output
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Factorials are computed Factorials are computed
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -3292,7 +3349,7 @@ with expansion:
re>" re>"
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Long text is truncted Long text is truncated
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
TestMain.cpp:<line number> TestMain.cpp:<line number>
............................................................................... ...............................................................................
@@ -5814,6 +5871,23 @@ MessageTests.cpp:<line number>:
warning: warning:
toString(p): 0x<hex digits> toString(p): 0x<hex digits>
-------------------------------------------------------------------------------
Process can be configured on command line
empty args don't cause a crash
-------------------------------------------------------------------------------
TestMain.cpp:<line number>
...............................................................................
TestMain.cpp:<line number>:
PASSED:
CHECK_NOTHROW( parser.parseInto( std::vector<std::string>(), config ) )
TestMain.cpp:<line number>:
PASSED:
CHECK( config.processName == "" )
with expansion:
"" == ""
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Process can be configured on command line Process can be configured on command line
default - no arguments default - no arguments
@@ -5825,6 +5899,12 @@ TestMain.cpp:<line number>:
PASSED: PASSED:
CHECK_NOTHROW( parseIntoConfig( argv, config ) ) CHECK_NOTHROW( parseIntoConfig( argv, config ) )
TestMain.cpp:<line number>:
PASSED:
CHECK( config.processName == "test" )
with expansion:
"test" == "test"
TestMain.cpp:<line number>: TestMain.cpp:<line number>:
PASSED: PASSED:
CHECK( config.shouldDebugBreak == false ) CHECK( config.shouldDebugBreak == false )
@@ -9324,6 +9404,6 @@ MiscTests.cpp:<line number>:
PASSED: PASSED:
=============================================================================== ===============================================================================
test cases: 163 | 117 passed | 44 failed | 2 failed as expected test cases: 166 | 118 passed | 45 failed | 3 failed as expected
assertions: 955 | 849 passed | 88 failed | 18 failed as expected assertions: 963 | 855 passed | 89 failed | 19 failed as expected

View File

@@ -48,6 +48,23 @@ PASSED:
with expansion: with expansion:
42 == {?} 42 == {?}
-------------------------------------------------------------------------------
#835 -- errno should not be touched by Catch
-------------------------------------------------------------------------------
MiscTests.cpp:<line number>
...............................................................................
MiscTests.cpp:<line number>: FAILED:
CHECK( f() == 0 )
with expansion:
1 == 0
MiscTests.cpp:<line number>:
PASSED:
REQUIRE( (*__error()) == 1 )
with expansion:
1 == 1
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
'Not' checks that should fail 'Not' checks that should fail
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -69,6 +86,6 @@ ConditionTests.cpp:<line number>: FAILED:
CHECK_FALSE( true ) CHECK_FALSE( true )
=============================================================================== ===============================================================================
test cases: 4 | 3 passed | 1 failed test cases: 5 | 3 passed | 1 failed | 1 failed as expected
assertions: 10 | 6 passed | 4 failed assertions: 12 | 7 passed | 4 failed | 1 failed as expected

View File

@@ -1,9 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuitesspanner> <testsuitesspanner>
<testsuite name="<exe-name>" errors="13" failures="76" tests="956" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="13" failures="77" tests="964" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testcase classname="global" name="# A test name that starts with a #" time="{duration}"/> <testcase classname="global" name="# A test name that starts with a #" time="{duration}"/>
<testcase classname="global" name="#542" time="{duration}"/> <testcase classname="global" name="#542" time="{duration}"/>
<testcase classname="global" name="#809" time="{duration}"/> <testcase classname="global" name="#809" time="{duration}"/>
<testcase classname="global" name="#835 -- errno should not be touched by Catch" time="{duration}">
<failure message="1 == 0" type="CHECK">
MiscTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="'Not' checks that should fail" time="{duration}"> <testcase classname="global" name="'Not' checks that should fail" time="{duration}">
<failure message="false != false" type="CHECK"> <failure message="false != false" type="CHECK">
ConditionTests.cpp:<line number> ConditionTests.cpp:<line number>
@@ -83,6 +88,8 @@ ExceptionTests.cpp:<line number>
<testcase classname="Assertions then sections" name="A section" time="{duration}"/> <testcase classname="Assertions then sections" name="A section" time="{duration}"/>
<testcase classname="Assertions then sections" name="A section/Another section" time="{duration}"/> <testcase classname="Assertions then sections" name="A section/Another section" time="{duration}"/>
<testcase classname="Assertions then sections" name="A section/Another other section" time="{duration}"/> <testcase classname="Assertions then sections" name="A section/Another other section" time="{duration}"/>
<testcase classname="Capture and info messages" name="Capture should stringify like assertions" time="{duration}"/>
<testcase classname="Capture and info messages" name="Info should NOT stringify the way assertions do" time="{duration}"/>
<testcase classname="Character pretty printing" name="Specifically escaped" time="{duration}"/> <testcase classname="Character pretty printing" name="Specifically escaped" time="{duration}"/>
<testcase classname="Character pretty printing" name="General chars" time="{duration}"/> <testcase classname="Character pretty printing" name="General chars" time="{duration}"/>
<testcase classname="Character pretty printing" name="Low ASCII" time="{duration}"/> <testcase classname="Character pretty printing" name="Low ASCII" time="{duration}"/>
@@ -192,6 +199,12 @@ MessageTests.cpp:<line number>
</testcase> </testcase>
<testcase classname="global" name="FAIL does not require an argument" time="{duration}"> <testcase classname="global" name="FAIL does not require an argument" time="{duration}">
<failure type="FAIL"> <failure type="FAIL">
MessageTests.cpp:<line number>
</failure>
</testcase>
<testcase classname="global" name="FAIL_CHECK does not abort the test" time="{duration}">
<failure type="FAIL_CHECK">
This is a failure
MessageTests.cpp:<line number> MessageTests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>
@@ -250,7 +263,7 @@ ConditionTests.cpp:<line number>
<testcase classname="Long strings can be wrapped" name="With wrap-before/ after characters/No wrapping" time="{duration}"/> <testcase classname="Long strings can be wrapped" name="With wrap-before/ after characters/No wrapping" time="{duration}"/>
<testcase classname="Long strings can be wrapped" name="With wrap-before/ after characters/Wrap before" time="{duration}"/> <testcase classname="Long strings can be wrapped" name="With wrap-before/ after characters/Wrap before" time="{duration}"/>
<testcase classname="Long strings can be wrapped" name="With wrap-before/ after characters/Wrap after" time="{duration}"/> <testcase classname="Long strings can be wrapped" name="With wrap-before/ after characters/Wrap after" time="{duration}"/>
<testcase classname="global" name="Long text is truncted" time="{duration}"/> <testcase classname="global" name="Long text is truncated" time="{duration}"/>
<testcase classname="global" name="ManuallyRegistered" time="{duration}"/> <testcase classname="global" name="ManuallyRegistered" time="{duration}"/>
<testcase classname="global" name="Matchers can be (AllOf) composed with the &amp;&amp; operator" time="{duration}"/> <testcase classname="global" name="Matchers can be (AllOf) composed with the &amp;&amp; operator" time="{duration}"/>
<testcase classname="global" name="Matchers can be (AnyOf) composed with the || operator" time="{duration}"/> <testcase classname="global" name="Matchers can be (AnyOf) composed with the || operator" time="{duration}"/>
@@ -387,6 +400,7 @@ MessageTests.cpp:<line number>
<testcase classname="global" name="Parsing a std::pair" time="{duration}"/> <testcase classname="global" name="Parsing a std::pair" time="{duration}"/>
<testcase classname="global" name="Pointers can be compared to null" time="{duration}"/> <testcase classname="global" name="Pointers can be compared to null" time="{duration}"/>
<testcase classname="global" name="Pointers can be converted to strings" time="{duration}"/> <testcase classname="global" name="Pointers can be converted to strings" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="empty args don't cause a crash" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="default - no arguments" time="{duration}"/> <testcase classname="Process can be configured on command line" name="default - no arguments" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="test lists/1 test" time="{duration}"/> <testcase classname="Process can be configured on command line" name="test lists/1 test" time="{duration}"/>
<testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using exclude:" time="{duration}"/> <testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using exclude:" time="{duration}"/>

View File

@@ -50,6 +50,25 @@
</Expression> </Expression>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="#835 -- errno should not be touched by Catch" tags="[!shouldfail]" filename="projects/<exe-name>/MiscTests.cpp" >
<Expression success="false" type="CHECK" filename="projects/<exe-name>/MiscTests.cpp" >
<Original>
f() == 0
</Original>
<Expanded>
1 == 0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MiscTests.cpp" >
<Original>
(*__error()) == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="'Not' checks that should fail" tags="[.][failing][hide]" filename="projects/<exe-name>/ConditionTests.cpp" > <TestCase name="'Not' checks that should fail" tags="[.][failing][hide]" filename="projects/<exe-name>/ConditionTests.cpp" >
<Expression success="false" type="CHECK" filename="projects/<exe-name>/ConditionTests.cpp" > <Expression success="false" type="CHECK" filename="projects/<exe-name>/ConditionTests.cpp" >
<Original> <Original>
@@ -643,6 +662,37 @@
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="Capture and info messages" filename="projects/<exe-name>/ToStringGeneralTests.cpp" >
<Section name="Capture should stringify like assertions" filename="projects/<exe-name>/ToStringGeneralTests.cpp" >
<Info>
i := 2
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringGeneralTests.cpp" >
<Original>
true
</Original>
<Expanded>
true
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Info should NOT stringify the way assertions do" filename="projects/<exe-name>/ToStringGeneralTests.cpp" >
<Info>
3
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringGeneralTests.cpp" >
<Original>
true
</Original>
<Expanded>
true
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Character pretty printing" filename="projects/<exe-name>/ToStringGeneralTests.cpp" > <TestCase name="Character pretty printing" filename="projects/<exe-name>/ToStringGeneralTests.cpp" >
<Section name="Specifically escaped" filename="projects/<exe-name>/ToStringGeneralTests.cpp" > <Section name="Specifically escaped" filename="projects/<exe-name>/ToStringGeneralTests.cpp" >
<Expression success="true" type="CHECK" filename="projects/<exe-name>/ToStringGeneralTests.cpp" > <Expression success="true" type="CHECK" filename="projects/<exe-name>/ToStringGeneralTests.cpp" >
@@ -1328,6 +1378,15 @@
<Failure filename="projects/<exe-name>/MessageTests.cpp" /> <Failure filename="projects/<exe-name>/MessageTests.cpp" />
<OverallResult success="false"/> <OverallResult success="false"/>
</TestCase> </TestCase>
<TestCase name="FAIL_CHECK does not abort the test" tags="[.][failing][hide][messages]" filename="projects/<exe-name>/MessageTests.cpp" >
<Failure filename="projects/<exe-name>/MessageTests.cpp" >
This is a failure
</Failure>
<Warning>
This message appears in the output
</Warning>
<OverallResult success="false"/>
</TestCase>
<TestCase name="Factorials are computed" tags="[factorial]" filename="projects/<exe-name>/MiscTests.cpp" > <TestCase name="Factorials are computed" tags="[factorial]" filename="projects/<exe-name>/MiscTests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MiscTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MiscTests.cpp" >
<Original> <Original>
@@ -2607,6 +2666,9 @@
<OverallResult success="false"/> <OverallResult success="false"/>
</TestCase> </TestCase>
<TestCase name="INFO gets logged on failure, even if captured before successful assertions" tags="[.][failing][hide][messages]" filename="projects/<exe-name>/MessageTests.cpp" > <TestCase name="INFO gets logged on failure, even if captured before successful assertions" tags="[.][failing][hide][messages]" filename="projects/<exe-name>/MessageTests.cpp" >
<Info>
this message may be logged later
</Info>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/MessageTests.cpp" > <Expression success="true" type="CHECK" filename="projects/<exe-name>/MessageTests.cpp" >
<Original> <Original>
a == 2 a == 2
@@ -2637,6 +2699,9 @@
2 == 0 2 == 0
</Expanded> </Expanded>
</Expression> </Expression>
<Info>
but not this
</Info>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/MessageTests.cpp" > <Expression success="true" type="CHECK" filename="projects/<exe-name>/MessageTests.cpp" >
<Original> <Original>
a == 2 a == 2
@@ -3409,7 +3474,7 @@ re>"
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="Long text is truncted" tags="[Text][Truncated]" filename="projects/<exe-name>/TestMain.cpp" > <TestCase name="Long text is truncated" tags="[Text][Truncated]" filename="projects/<exe-name>/TestMain.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/TestMain.cpp" > <Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/TestMain.cpp" >
<Original> <Original>
t.toString(), EndsWith( "... message truncated due to excessive size" ) t.toString(), EndsWith( "... message truncated due to excessive size" )
@@ -6150,6 +6215,25 @@ re>"
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="Process can be configured on command line" tags="[command-line][config]" filename="projects/<exe-name>/TestMain.cpp" > <TestCase name="Process can be configured on command line" tags="[command-line][config]" filename="projects/<exe-name>/TestMain.cpp" >
<Section name="empty args don't cause a crash" filename="projects/<exe-name>/TestMain.cpp" >
<Expression success="true" type="CHECK_NOTHROW" filename="projects/<exe-name>/TestMain.cpp" >
<Original>
parser.parseInto( std::vector&lt;std::string>(), config )
</Original>
<Expanded>
parser.parseInto( std::vector&lt;std::string>(), config )
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/TestMain.cpp" >
<Original>
config.processName == ""
</Original>
<Expanded>
"" == ""
</Expanded>
</Expression>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<Section name="default - no arguments" filename="projects/<exe-name>/TestMain.cpp" > <Section name="default - no arguments" filename="projects/<exe-name>/TestMain.cpp" >
<Expression success="true" type="CHECK_NOTHROW" filename="projects/<exe-name>/TestMain.cpp" > <Expression success="true" type="CHECK_NOTHROW" filename="projects/<exe-name>/TestMain.cpp" >
<Original> <Original>
@@ -6159,6 +6243,14 @@ re>"
parseIntoConfig( argv, config ) parseIntoConfig( argv, config )
</Expanded> </Expanded>
</Expression> </Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/TestMain.cpp" >
<Original>
config.processName == "test"
</Original>
<Expanded>
"test" == "test"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/TestMain.cpp" > <Expression success="true" type="CHECK" filename="projects/<exe-name>/TestMain.cpp" >
<Original> <Original>
config.shouldDebugBreak == false config.shouldDebugBreak == false
@@ -6191,7 +6283,7 @@ re>"
true true
</Expanded> </Expanded>
</Expression> </Expression>
<OverallResults successes="5" failures="0" expectedFailures="0"/> <OverallResults successes="6" failures="0" expectedFailures="0"/>
</Section> </Section>
<Section name="test lists" filename="projects/<exe-name>/TestMain.cpp" > <Section name="test lists" filename="projects/<exe-name>/TestMain.cpp" >
<Section name="1 test" description="Specify one test case using" filename="projects/<exe-name>/TestMain.cpp" > <Section name="1 test" description="Specify one test case using" filename="projects/<exe-name>/TestMain.cpp" >
@@ -6736,6 +6828,12 @@ re>"
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="SCOPED_INFO is reset for each loop" tags="[.][failing][hide][messages]" filename="projects/<exe-name>/MessageTests.cpp" > <TestCase name="SCOPED_INFO is reset for each loop" tags="[.][failing][hide][messages]" filename="projects/<exe-name>/MessageTests.cpp" >
<Info>
current counter 0
</Info>
<Info>
i := 0
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original> <Original>
i &lt; 10 i &lt; 10
@@ -6744,6 +6842,12 @@ re>"
0 &lt; 10 0 &lt; 10
</Expanded> </Expanded>
</Expression> </Expression>
<Info>
current counter 1
</Info>
<Info>
i := 1
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original> <Original>
i &lt; 10 i &lt; 10
@@ -6752,6 +6856,12 @@ re>"
1 &lt; 10 1 &lt; 10
</Expanded> </Expanded>
</Expression> </Expression>
<Info>
current counter 2
</Info>
<Info>
i := 2
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original> <Original>
i &lt; 10 i &lt; 10
@@ -6760,6 +6870,12 @@ re>"
2 &lt; 10 2 &lt; 10
</Expanded> </Expanded>
</Expression> </Expression>
<Info>
current counter 3
</Info>
<Info>
i := 3
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original> <Original>
i &lt; 10 i &lt; 10
@@ -6768,6 +6884,12 @@ re>"
3 &lt; 10 3 &lt; 10
</Expanded> </Expanded>
</Expression> </Expression>
<Info>
current counter 4
</Info>
<Info>
i := 4
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original> <Original>
i &lt; 10 i &lt; 10
@@ -6776,6 +6898,12 @@ re>"
4 &lt; 10 4 &lt; 10
</Expanded> </Expanded>
</Expression> </Expression>
<Info>
current counter 5
</Info>
<Info>
i := 5
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original> <Original>
i &lt; 10 i &lt; 10
@@ -6784,6 +6912,12 @@ re>"
5 &lt; 10 5 &lt; 10
</Expanded> </Expanded>
</Expression> </Expression>
<Info>
current counter 6
</Info>
<Info>
i := 6
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original> <Original>
i &lt; 10 i &lt; 10
@@ -6792,6 +6926,12 @@ re>"
6 &lt; 10 6 &lt; 10
</Expanded> </Expanded>
</Expression> </Expression>
<Info>
current counter 7
</Info>
<Info>
i := 7
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original> <Original>
i &lt; 10 i &lt; 10
@@ -6800,6 +6940,12 @@ re>"
7 &lt; 10 7 &lt; 10
</Expanded> </Expanded>
</Expression> </Expression>
<Info>
current counter 8
</Info>
<Info>
i := 8
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original> <Original>
i &lt; 10 i &lt; 10
@@ -6808,6 +6954,12 @@ re>"
8 &lt; 10 8 &lt; 10
</Expanded> </Expanded>
</Expression> </Expression>
<Info>
current counter 9
</Info>
<Info>
i := 9
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original> <Original>
i &lt; 10 i &lt; 10
@@ -9086,6 +9238,9 @@ spanner <OverallResult success="true"/>
1 == 0 1 == 0
</Expanded> </Expanded>
</Expression> </Expression>
<Info>
Testing if fib[2] (2) is even
</Info>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/MiscTests.cpp" > <Expression success="true" type="CHECK" filename="projects/<exe-name>/MiscTests.cpp" >
<Original> <Original>
( fib[i] % 2 ) == 0 ( fib[i] % 2 ) == 0
@@ -9116,6 +9271,9 @@ spanner <OverallResult success="true"/>
1 == 0 1 == 0
</Expanded> </Expanded>
</Expression> </Expression>
<Info>
Testing if fib[5] (8) is even
</Info>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/MiscTests.cpp" > <Expression success="true" type="CHECK" filename="projects/<exe-name>/MiscTests.cpp" >
<Original> <Original>
( fib[i] % 2 ) == 0 ( fib[i] % 2 ) == 0
@@ -9885,7 +10043,7 @@ spanner <OverallResult success="true"/>
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="849" failures="89" expectedFailures="18"/> <OverallResults successes="855" failures="90" expectedFailures="19"/>
</Group> </Group>
<OverallResults successes="849" failures="88" expectedFailures="18"/> <OverallResults successes="855" failures="89" expectedFailures="19"/>
</Catch> </Catch>

View File

@@ -11,6 +11,10 @@
#include <string> #include <string>
#include <stdexcept> #include <stdexcept>
#ifdef _MSC_VER
#pragma warning(disable:4702) // Unreachable code -- MSVC 19 (VS 2015) sees right through the indirection
#endif
namespace namespace
{ {
inline int thisThrows() inline int thisThrows()

View File

@@ -53,6 +53,13 @@ TEST_CASE( "INFO gets logged on failure, even if captured before successful asse
TEST_CASE( "FAIL aborts the test", "[failing][messages][.]" ) TEST_CASE( "FAIL aborts the test", "[failing][messages][.]" )
{ {
FAIL( "This is a " << "failure" ); // This should output the message and abort FAIL( "This is a " << "failure" ); // This should output the message and abort
WARN( "We should never see this");
}
TEST_CASE( "FAIL_CHECK does not abort the test", "[failing][messages][.]" )
{
FAIL_CHECK( "This is a " << "failure" ); // This should output the message then continue
WARN( "This message appears in the output");
} }
#ifdef CATCH_CONFIG_VARIADIC_MACROS #ifdef CATCH_CONFIG_VARIADIC_MACROS

View File

@@ -16,6 +16,7 @@
#include "../include/internal/catch_xmlwriter.hpp" #include "../include/internal/catch_xmlwriter.hpp"
#include <iostream> #include <iostream>
#include <cerrno>
TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) TEST_CASE( "random SECTION tests", "[.][sections][failing]" )
{ {
@@ -393,3 +394,14 @@ TEST_CASE( "This test 'should' fail but doesn't", "[.][failing][!shouldfail]" )
TEST_CASE( "# A test name that starts with a #" ) { TEST_CASE( "# A test name that starts with a #" ) {
SUCCEED( "yay" ); SUCCEED( "yay" );
} }
static int f() {
return 1;
}
TEST_CASE( "#835 -- errno should not be touched by Catch", "[!shouldfail]" ) {
errno = 1;
CHECK(f() == 0);
REQUIRE(errno == 1); // Check that f() doesn't touch errno.
}

View File

@@ -51,10 +51,18 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
Catch::ConfigData config; Catch::ConfigData config;
SECTION( "empty args don't cause a crash" ) {
Catch::Clara::CommandLine<Catch::ConfigData> parser = Catch::makeCommandLineParser();
CHECK_NOTHROW( parser.parseInto( std::vector<std::string>(), config ) );
CHECK( config.processName == "" );
}
SECTION( "default - no arguments", "" ) { SECTION( "default - no arguments", "" ) {
const char* argv[] = { "test" }; const char* argv[] = { "test" };
CHECK_NOTHROW( parseIntoConfig( argv, config ) ); CHECK_NOTHROW( parseIntoConfig( argv, config ) );
CHECK( config.processName == "test" );
CHECK( config.shouldDebugBreak == false ); CHECK( config.shouldDebugBreak == false );
CHECK( config.abortAfter == -1 ); CHECK( config.abortAfter == -1 );
CHECK( config.noThrow == false ); CHECK( config.noThrow == false );
@@ -471,7 +479,7 @@ TEST_CASE( "Text can be formatted using the Text class", "" ) {
CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" ); CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" );
} }
TEST_CASE( "Long text is truncted", "[Text][Truncated]" ) { TEST_CASE( "Long text is truncated", "[Text][Truncated]" ) {
std::string longLine( 90, '*' ); std::string longLine( 90, '*' );

View File

@@ -38,3 +38,17 @@ TEST_CASE( "Character pretty printing" ){
} }
} }
} }
TEST_CASE( "Capture and info messages" ) {
SECTION("Capture should stringify like assertions") {
int i = 2;
CAPTURE(i);
REQUIRE(true);
}
SECTION("Info should NOT stringify the way assertions do") {
int i = 3;
INFO(i);
REQUIRE(true);
}
}

View File

@@ -124,16 +124,18 @@ args = parser.parse_args()
compiler_path = args.compiler compiler_path = args.compiler
catch_path = args.catch_header catch_path = args.catch_header
os.chdir(dir_name)
if args.generate_files: if args.generate_files:
create_temp_dir() create_temp_dir()
copy_catch(catch_path) copy_catch(catch_path)
os.chdir(dir_name)
# now create the fake test files # now create the fake test files
generate_files() generate_files()
# Early exit # Early exit
print('Finished generating files') print('Finished generating files')
exit(1) exit(1)
os.chdir(dir_name)
if args.flags: if args.flags:
flags = args.flags flags = args.flags

View File

@@ -75,7 +75,6 @@ class Version:
f.write( line + "\n" ) f.write( line + "\n" )
def updateReadmeFile(self): def updateReadmeFile(self):
versionParser = re.compile( r'\*v\d+\.\d+\.\d+\*' )
downloadParser = re.compile( r'<a href=\"https://github.com/philsquared/Catch/releases/download/v\d+\.\d+\.\d+/catch.hpp\">' ) downloadParser = re.compile( r'<a href=\"https://github.com/philsquared/Catch/releases/download/v\d+\.\d+\.\d+/catch.hpp\">' )
f = open( readmePath, 'r' ) f = open( readmePath, 'r' )
lines = [] lines = []
@@ -84,7 +83,6 @@ class Version:
f.close() f.close()
f = open( readmePath, 'w' ) f = open( readmePath, 'w' )
for line in lines: for line in lines:
line = versionParser.sub( '*v{0}*'.format(self.getVersionString()), line)
line = downloadParser.sub( r'<a href="https://github.com/philsquared/Catch/releases/download/v{0}/catch.hpp">'.format(self.getVersionString()) , line) line = downloadParser.sub( r'<a href="https://github.com/philsquared/Catch/releases/download/v{0}/catch.hpp">'.format(self.getVersionString()) , line)
f.write( line + "\n" ) f.write( line + "\n" )

View File

@@ -1,6 +1,6 @@
/* /*
* Catch v1.8.0 * Catch v1.8.2
* Generated: 2017-02-28 14:16:45.289179 * Generated: 2017-03-13 21:18:33.619572
* ---------------------------------------------------------- * ----------------------------------------------------------
* 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) 2012 Two Blue Cubes Ltd. All rights reserved. * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@@ -141,6 +141,10 @@
# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
# endif # endif
// Required for some versions of Cygwin to declare gettimeofday
// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
# define _BSD_SOURCE
#endif // __CYGWIN__ #endif // __CYGWIN__
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1017,16 +1021,24 @@ namespace Matchers {
} }
protected: protected:
virtual ~MatcherUntypedBase();
virtual std::string describe() const = 0; virtual std::string describe() const = 0;
mutable std::string m_cachedToString; mutable std::string m_cachedToString;
private: private:
MatcherUntypedBase& operator = ( MatcherUntypedBase const& ); MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
}; };
template<typename ObjectT, typename ComparatorT = ObjectT> template<typename ObjectT>
struct MatcherBase : MatcherUntypedBase { struct MatcherMethod {
virtual bool match( ObjectT const& arg ) const = 0; virtual bool match( ObjectT const& arg ) const = 0;
};
template<typename PtrT>
struct MatcherMethod<PtrT*> {
virtual bool match( PtrT* arg ) const = 0;
};
template<typename ObjectT, typename ComparatorT = ObjectT>
struct MatcherBase : MatcherUntypedBase, MatcherMethod<ObjectT> {
MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const; MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const;
MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const; MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
@@ -2889,7 +2901,7 @@ namespace Matchers {
}; };
struct StringMatcherBase : MatcherBase<std::string> { struct StringMatcherBase : MatcherBase<std::string> {
StringMatcherBase( std::string operation, CasedString const& comparator ); StringMatcherBase( std::string const& operation, CasedString const& comparator );
virtual std::string describe() const CATCH_OVERRIDE; virtual std::string describe() const CATCH_OVERRIDE;
CasedString m_comparator; CasedString m_comparator;
@@ -3028,7 +3040,7 @@ namespace Matchers {
namespace Catch { namespace Catch {
struct TagAlias { struct TagAlias {
TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
std::string tag; std::string tag;
SourceLineInfo lineInfo; SourceLineInfo lineInfo;
@@ -3300,64 +3312,67 @@ namespace Catch {
namespace Impl { namespace Impl {
namespace NSStringMatchers { namespace NSStringMatchers {
template<typename MatcherT> struct StringHolder : MatcherBase<NSString*>{
struct StringHolder : MatcherImpl<MatcherT, NSString*>{
StringHolder( NSString* substr ) : m_substr( [substr copy] ){} StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
StringHolder() { StringHolder() {
arcSafeRelease( m_substr ); arcSafeRelease( m_substr );
} }
virtual bool match( NSString* arg ) const CATCH_OVERRIDE {
return false;
}
NSString* m_substr; NSString* m_substr;
}; };
struct Equals : StringHolder<Equals> { struct Equals : StringHolder {
Equals( NSString* substr ) : StringHolder( substr ){} Equals( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const { virtual bool match( NSString* str ) const CATCH_OVERRIDE {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str isEqualToString:m_substr]; [str isEqualToString:m_substr];
} }
virtual std::string toString() const { virtual std::string describe() const CATCH_OVERRIDE {
return "equals string: " + Catch::toString( m_substr ); return "equals string: " + Catch::toString( m_substr );
} }
}; };
struct Contains : StringHolder<Contains> { struct Contains : StringHolder {
Contains( NSString* substr ) : StringHolder( substr ){} Contains( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const { virtual bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location != NSNotFound; [str rangeOfString:m_substr].location != NSNotFound;
} }
virtual std::string toString() const { virtual std::string describe() const CATCH_OVERRIDE {
return "contains string: " + Catch::toString( m_substr ); return "contains string: " + Catch::toString( m_substr );
} }
}; };
struct StartsWith : StringHolder<StartsWith> { struct StartsWith : StringHolder {
StartsWith( NSString* substr ) : StringHolder( substr ){} StartsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const { virtual bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == 0; [str rangeOfString:m_substr].location == 0;
} }
virtual std::string toString() const { virtual std::string describe() const CATCH_OVERRIDE {
return "starts with: " + Catch::toString( m_substr ); return "starts with: " + Catch::toString( m_substr );
} }
}; };
struct EndsWith : StringHolder<EndsWith> { struct EndsWith : StringHolder {
EndsWith( NSString* substr ) : StringHolder( substr ){} EndsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const { virtual bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == [str length] - [m_substr length]; [str rangeOfString:m_substr].location == [str length] - [m_substr length];
} }
virtual std::string toString() const { virtual std::string describe() const CATCH_OVERRIDE {
return "ends with: " + Catch::toString( m_substr ); return "ends with: " + Catch::toString( m_substr );
} }
}; };
@@ -4016,6 +4031,7 @@ namespace Catch {
#include <vector> #include <vector>
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
#include <cctype>
// Use optional outer namespace // Use optional outer namespace
#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
@@ -4358,7 +4374,7 @@ namespace Clara {
_dest = _source; _dest = _source;
} }
char toLowerCh(char c) { char toLowerCh(char c) {
return static_cast<char>( ::tolower( c ) ); return static_cast<char>( std::tolower( c ) );
} }
inline void convertInto( std::string const& _source, bool& _dest ) { inline void convertInto( std::string const& _source, bool& _dest ) {
std::string sourceLC = _source; std::string sourceLC = _source;
@@ -4512,12 +4528,13 @@ namespace Clara {
} }
void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) { void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
for( std::size_t i = 0; i <= arg.size(); ++i ) { for( std::size_t i = 0; i < arg.size(); ++i ) {
char c = arg[i]; char c = arg[i];
if( c == '"' ) if( c == '"' )
inQuotes = !inQuotes; inQuotes = !inQuotes;
mode = handleMode( i, c, arg, tokens ); mode = handleMode( i, c, arg, tokens );
} }
mode = handleMode( arg.size(), '\0', arg, tokens );
} }
Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) { Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
switch( mode ) { switch( mode ) {
@@ -4550,6 +4567,7 @@ namespace Clara {
default: from = i; return ShortOpt; default: from = i; return ShortOpt;
} }
} }
Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) { Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
return mode; return mode;
@@ -4881,7 +4899,7 @@ namespace Clara {
} }
std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const { std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
std::string processName = args[0]; std::string processName = args.empty() ? std::string() : args[0];
std::size_t lastSlash = processName.find_last_of( "/\\" ); std::size_t lastSlash = processName.find_last_of( "/\\" );
if( lastSlash != std::string::npos ) if( lastSlash != std::string::npos )
processName = processName.substr( lastSlash+1 ); processName = processName.substr( lastSlash+1 );
@@ -6288,7 +6306,6 @@ namespace Catch {
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
reset();
reportFatal(signalDefs[i].name); reportFatal(signalDefs[i].name);
} }
} }
@@ -6630,10 +6647,14 @@ namespace Catch {
} }
virtual void handleFatalErrorCondition( std::string const& message ) { virtual void handleFatalErrorCondition( std::string const& message ) {
ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); // Don't rebuild the result -- the stringification itself can cause more fatal errors
resultBuilder.setResultType( ResultWas::FatalErrorCondition ); // Instead, fake a result data.
resultBuilder << message; AssertionResultData tempResult;
resultBuilder.captureExpression(); tempResult.resultType = ResultWas::FatalErrorCondition;
tempResult.message = message;
AssertionResult result(m_lastAssertionInfo, tempResult);
getResultCapture().assertionEnded(result);
handleUnfinishedSections(); handleUnfinishedSections();
@@ -7577,6 +7598,23 @@ namespace Catch {
// #included from: catch_console_colour_impl.hpp // #included from: catch_console_colour_impl.hpp
#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
// #included from: catch_errno_guard.hpp
#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED
#include <cerrno>
namespace Catch {
class ErrnoGuard {
public:
ErrnoGuard():m_oldErrno(errno){}
~ErrnoGuard() { errno = m_oldErrno; }
private:
int m_oldErrno;
};
}
namespace Catch { namespace Catch {
namespace { namespace {
@@ -7712,6 +7750,7 @@ namespace {
}; };
IColourImpl* platformColourInstance() { IColourImpl* platformColourInstance() {
ErrnoGuard guard;
Ptr<IConfig const> config = getCurrentContext().getConfig(); Ptr<IConfig const> config = getCurrentContext().getConfig();
UseColour::YesOrNo colourMode = config UseColour::YesOrNo colourMode = config
? config->useColour() ? config->useColour()
@@ -8134,7 +8173,7 @@ namespace Catch {
return os; return os;
} }
Version libraryVersion( 1, 8, 0, "", 0 ); Version libraryVersion( 1, 8, 2, "", 0 );
} }
@@ -8308,13 +8347,8 @@ namespace Catch
#else #else
// Required for some versions of Cygwin to declare gettimeofday
// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
# ifdef __CYGWIN__
# define _BSD_SOURCE
# endif
#include <sys/time.h> #include <sys/time.h>
#endif #endif
namespace Catch { namespace Catch {
@@ -8568,6 +8602,9 @@ namespace Catch {
// be strace, for example) in /proc/$PID/status, so just get it from // be strace, for example) in /proc/$PID/status, so just get it from
// there instead. // there instead.
bool isDebuggerActive(){ bool isDebuggerActive(){
// Libstdc++ has a bug, where std::ifstream sets errno to 0
// This way our users can properly assert over errno values
ErrnoGuard guard;
std::ifstream in("/proc/self/status"); std::ifstream in("/proc/self/status");
for( std::string line; std::getline(in, line); ) { for( std::string line; std::getline(in, line); ) {
static const int PREFIX_LEN = 11; static const int PREFIX_LEN = 11;
@@ -9065,7 +9102,7 @@ namespace Matchers {
: std::string(); : std::string();
} }
StringMatcherBase::StringMatcherBase( std::string operation, CasedString const& comparator ) StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
: m_comparator( comparator ), : m_comparator( comparator ),
m_operation( operation ) { m_operation( operation ) {
} }
@@ -9266,10 +9303,34 @@ Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingRepo
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
#include <cstring> #include <cstring>
#include <cfloat>
#include <cstdio>
#include <assert.h> #include <assert.h>
namespace Catch { namespace Catch {
namespace {
// Because formatting using c++ streams is stateful, drop down to C is required
// Alternatively we could use stringstream, but its performance is... not good.
std::string getFormattedDuration( double duration ) {
// Max exponent + 1 is required to represent the whole part
// + 1 for decimal point
// + 3 for the 3 decimal places
// + 1 for null terminator
const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
char buffer[maxDoubleSize];
// Save previous errno, to prevent sprintf from overwriting it
ErrnoGuard guard;
#ifdef _MSC_VER
sprintf_s(buffer, "%.3f", duration);
#else
sprintf(buffer, "%.3f", duration);
#endif
return std::string(buffer);
}
}
struct StreamingReporterBase : SharedImpl<IStreamingReporter> { struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
StreamingReporterBase( ReporterConfig const& _config ) StreamingReporterBase( ReporterConfig const& _config )
@@ -9595,9 +9656,13 @@ namespace Catch {
#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
// Deprecated - use the form without INTERNAL_
#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ #define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
#define CATCH_REGISTER_LISTENER( listenerType ) \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
// #included from: ../internal/catch_xmlwriter.hpp // #included from: ../internal/catch_xmlwriter.hpp
#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
@@ -9922,73 +9987,76 @@ namespace Catch {
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
const AssertionResult& assertionResult = assertionStats.assertionResult;
// Print any info messages in <Info> tags. AssertionResult const& result = assertionStats.assertionResult;
if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
if( includeResults ) {
// Print any info messages in <Info> tags.
for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
it != itEnd; it != itEnd;
++it ) { ++it ) {
if( it->type == ResultWas::Info ) { if( it->type == ResultWas::Info ) {
m_xml.scopedElement( "Info" ) m_xml.scopedElement( "Info" )
.writeText( it->message ); .writeText( it->message );
} else if ( it->type == ResultWas::Warning ) { } else if ( it->type == ResultWas::Warning ) {
m_xml.scopedElement( "Warning" ) m_xml.scopedElement( "Warning" )
.writeText( it->message ); .writeText( it->message );
} }
} }
} }
// Drop out if result was successful but we're not printing them. // Drop out if result was successful but we're not printing them.
if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) if( !includeResults && result.getResultType() != ResultWas::Warning )
return true; return true;
// Print the expression if there is one. // Print the expression if there is one.
if( assertionResult.hasExpression() ) { if( result.hasExpression() ) {
m_xml.startElement( "Expression" ) m_xml.startElement( "Expression" )
.writeAttribute( "success", assertionResult.succeeded() ) .writeAttribute( "success", result.succeeded() )
.writeAttribute( "type", assertionResult.getTestMacroName() ); .writeAttribute( "type", result.getTestMacroName() );
writeSourceInfo( assertionResult.getSourceInfo() ); writeSourceInfo( result.getSourceInfo() );
m_xml.scopedElement( "Original" ) m_xml.scopedElement( "Original" )
.writeText( assertionResult.getExpression() ); .writeText( result.getExpression() );
m_xml.scopedElement( "Expanded" ) m_xml.scopedElement( "Expanded" )
.writeText( assertionResult.getExpandedExpression() ); .writeText( result.getExpandedExpression() );
} }
// And... Print a result applicable to each result type. // And... Print a result applicable to each result type.
switch( assertionResult.getResultType() ) { switch( result.getResultType() ) {
case ResultWas::ThrewException: case ResultWas::ThrewException:
m_xml.startElement( "Exception" ); m_xml.startElement( "Exception" );
writeSourceInfo( assertionResult.getSourceInfo() ); writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() ); m_xml.writeText( result.getMessage() );
m_xml.endElement(); m_xml.endElement();
break; break;
case ResultWas::FatalErrorCondition: case ResultWas::FatalErrorCondition:
m_xml.startElement( "FatalErrorCondition" ); m_xml.startElement( "FatalErrorCondition" );
writeSourceInfo( assertionResult.getSourceInfo() ); writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() ); m_xml.writeText( result.getMessage() );
m_xml.endElement(); m_xml.endElement();
break; break;
case ResultWas::Info: case ResultWas::Info:
m_xml.scopedElement( "Info" ) m_xml.scopedElement( "Info" )
.writeText( assertionResult.getMessage() ); .writeText( result.getMessage() );
break; break;
case ResultWas::Warning: case ResultWas::Warning:
// Warning will already have been written // Warning will already have been written
break; break;
case ResultWas::ExplicitFailure: case ResultWas::ExplicitFailure:
m_xml.startElement( "Failure" ); m_xml.startElement( "Failure" );
writeSourceInfo( assertionResult.getSourceInfo() ); writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() ); m_xml.writeText( result.getMessage() );
m_xml.endElement(); m_xml.endElement();
break; break;
default: default:
break; break;
} }
if( assertionResult.hasExpression() ) if( result.hasExpression() )
m_xml.endElement(); m_xml.endElement();
return true; return true;
@@ -10300,25 +10368,6 @@ namespace Catch {
namespace Catch { namespace Catch {
namespace {
// Because formatting using c++ streams is stateful, drop down to C is required
// Alternatively we could use stringstream, but its performance is... not good.
std::string getFormattedDuration( double duration ) {
// Max exponent + 1 is required to represent the whole part
// + 1 for decimal point
// + 3 for the 3 decimal places
// + 1 for null terminator
const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
char buffer[maxDoubleSize];
#ifdef _MSC_VER
sprintf_s(buffer, "%.3f", duration);
#else
sprintf(buffer, "%.3f", duration);
#endif
return std::string(buffer);
}
}
struct ConsoleReporter : StreamingReporterBase { struct ConsoleReporter : StreamingReporterBase {
ConsoleReporter( ReporterConfig const& _config ) ConsoleReporter( ReporterConfig const& _config )
: StreamingReporterBase( _config ), : StreamingReporterBase( _config ),
@@ -10340,18 +10389,15 @@ namespace Catch {
virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
AssertionResult const& result = _assertionStats.assertionResult; AssertionResult const& result = _assertionStats.assertionResult;
bool printInfoMessages = true; bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
// Drop out if result was successful and we're not printing those // Drop out if result was successful but we're not printing them.
if( !m_config->includeSuccessfulResults() && result.isOk() ) { if( !includeResults && result.getResultType() != ResultWas::Warning )
if( result.getResultType() != ResultWas::Warning ) return false;
return false;
printInfoMessages = false;
}
lazyPrint(); lazyPrint();
AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); AssertionPrinter printer( stream, _assertionStats, includeResults );
printer.print(); printer.print();
stream << std::endl; stream << std::endl;
return true; return true;
@@ -10770,8 +10816,7 @@ namespace Catch {
stream << "No test cases matched '" << spec << '\'' << std::endl; stream << "No test cases matched '" << spec << '\'' << std::endl;
} }
virtual void assertionStarting( AssertionInfo const& ) { virtual void assertionStarting( AssertionInfo const& ) {}
}
virtual bool assertionEnded( AssertionStats const& _assertionStats ) { virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
AssertionResult const& result = _assertionStats.assertionResult; AssertionResult const& result = _assertionStats.assertionResult;
@@ -10792,6 +10837,12 @@ namespace Catch {
return true; return true;
} }
virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE {
if (m_config->showDurations() == ShowDurations::Always) {
stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
}
}
virtual void testRunEnded( TestRunStats const& _testRunStats ) { virtual void testRunEnded( TestRunStats const& _testRunStats ) {
printTotals( _testRunStats.totals ); printTotals( _testRunStats.totals );
stream << '\n' << std::endl; stream << '\n' << std::endl;
@@ -10897,7 +10948,7 @@ namespace Catch {
stream << result.getSourceInfo() << ':'; stream << result.getSourceInfo() << ':';
} }
void printResultType( Colour::Code colour, std::string passOrFail ) const { void printResultType( Colour::Code colour, std::string const& passOrFail ) const {
if( !passOrFail.empty() ) { if( !passOrFail.empty() ) {
{ {
Colour colourGuard( colour ); Colour colourGuard( colour );
@@ -10907,7 +10958,7 @@ namespace Catch {
} }
} }
void printIssue( std::string issue ) const { void printIssue( std::string const& issue ) const {
stream << ' ' << issue; stream << ' ' << issue;
} }
@@ -11078,6 +11129,7 @@ namespace Catch {
TestSpec::NamePattern::~NamePattern() {} TestSpec::NamePattern::~NamePattern() {}
TestSpec::TagPattern::~TagPattern() {} TestSpec::TagPattern::~TagPattern() {}
TestSpec::ExcludedPattern::~ExcludedPattern() {} TestSpec::ExcludedPattern::~ExcludedPattern() {}
Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {}
void Config::dummy() {} void Config::dummy() {}
@@ -11163,8 +11215,8 @@ int main (int argc, char * const argv[]) {
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << Catch::toString(msg), "CATCH_CAPTURE" )
#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << Catch::toString(msg), "CATCH_CAPTURE" )
#ifdef CATCH_CONFIG_VARIADIC_MACROS #ifdef CATCH_CONFIG_VARIADIC_MACROS
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
@@ -11173,6 +11225,7 @@ int main (int argc, char * const argv[]) {
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, "CATCH_FAIL_CHECK", __VA_ARGS__ )
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
#else #else
#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
@@ -11181,6 +11234,7 @@ int main (int argc, char * const argv[]) {
#define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
#define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, "CATCH_FAIL_CHECK", msg )
#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
#endif #endif
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
@@ -11232,24 +11286,26 @@ int main (int argc, char * const argv[]) {
#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) #define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) #define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << Catch::toString(msg), "CAPTURE" )
#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << Catch::toString(msg), "CAPTURE" )
#ifdef CATCH_CONFIG_VARIADIC_MACROS #ifdef CATCH_CONFIG_VARIADIC_MACROS
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, "FAIL_CHECK", __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
#else #else
#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
#define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
#define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
#define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
#define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, "FAIL_CHECK", msg )
#define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
#endif #endif
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )