Compare commits

...

41 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
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
45 changed files with 827 additions and 257 deletions

View File

@@ -135,6 +135,7 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_debugger.h
${HEADER_DIR}/internal/catch_debugger.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_exception_translator_registry.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 )
endif()
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 )
endif()

View File

@@ -1,10 +1,10 @@
![catch logo](catch-logo-small.png)
*v1.8.1*
[![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.1/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.2/catch.hpp">The latest, single header, version can be downloaded directly using this link</a>
## 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)
* [Test cases and sections](test-cases-and-sections.md)
* [Test fixtures](test-fixtures.md)
* [Command line](command-line.md)
* [Build systems](build-systems.md)
* [Supplying your own main()](own-main.md)
* [Event Listeners](event-listeners.md)
* [Configuration](configuration.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)
* [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.
**FAIL_CHECK(** _message expression_ **)**
AS `FAIL`, but does not abort the test
## Quickly capture a variable value
**CAPTURE(** _expression_ **)**

View File

@@ -48,6 +48,9 @@ A thread safe header only mocking framework for C++14
## 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 originally stood for Multiple Arcade Machine Emulator

View File

@@ -1,24 +1,69 @@
# 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
### New features/ minor changes
* Matchers have new, simpler (and documented) interface.
* Catch provides string and vector matchers.
* For details see [Matchers documentation](matchers.md).
* For details see [Matchers documentation](docs/matchers.md).
* Changed console reporter test duration reporting format (#322)
* Old format: `Some simple comparisons between doubles completed in 0.000123s`
* New format: `xxx.123s: Some simple comparisons between doubles` _(There will always be exactly 3 decimal places)_
* Added opt-in leak detection under MSVC + Windows (#439)
* 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.
* Moves debug breaks out of tests and into implementation, speeding up compilation time
* Moves debug breaks out of tests and into implementation, speeding up test compilation time (~10% on linux).
* _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.
* 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](build-systems.md).
* XML reporter now reports filename as part of the `Section` and `TestCase` tags.
* `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
* 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`.
* `[!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.
* `[!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.
* `[#<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_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_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
#define CATCH_SCOPED_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 " := " << Catch::toString(msg), "CATCH_CAPTURE" )
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#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_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_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__ )
#else
#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_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_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 )
#endif
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
@@ -185,24 +187,26 @@ LeakDetector leakDetector;
#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
#define SCOPED_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 " := " << Catch::toString(msg), "CAPTURE" )
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __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 REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __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 TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __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 REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __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_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
#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 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 SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
#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 )
#endif
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )

View File

@@ -41,6 +41,7 @@
#include <vector>
#include <sstream>
#include <algorithm>
#include <cctype>
// Use optional outer namespace
#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
@@ -397,7 +398,7 @@ namespace Clara {
_dest = _source;
}
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 ) {
std::string sourceLC = _source;
@@ -553,12 +554,13 @@ namespace Clara {
}
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];
if( c == '"' )
inQuotes = !inQuotes;
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 ) {
switch( mode ) {
@@ -591,6 +593,7 @@ namespace Clara {
default: from = i; return ShortOpt;
}
}
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 )
return mode;
@@ -924,7 +927,7 @@ namespace Clara {
}
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( "/\\" );
if( lastSlash != std::string::npos )
processName = processName.substr( lastSlash+1 );

View File

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

View File

@@ -10,6 +10,7 @@
#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
#include "catch_debugger.h"
#include "catch_errno_guard.hpp"
#ifdef CATCH_PLATFORM_MAC
@@ -72,6 +73,9 @@
// be strace, for example) in /proc/$PID/status, so just get it from
// there instead.
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");
for( std::string line; std::getline(in, line); ) {
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) {
for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
reset();
reportFatal(signalDefs[i].name);
}
}

View File

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

View File

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

View File

@@ -26,7 +26,7 @@ namespace Matchers {
};
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;
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_operation( operation ) {
}

View File

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

View File

@@ -92,7 +92,11 @@ namespace Catch {
#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
// Deprecated - use the form without INTERNAL_
#define INTERNAL_CATCH_REGISTER_LISTENER( 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

View File

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

View File

@@ -15,7 +15,7 @@
namespace Catch {
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;
SourceLineInfo lineInfo;

View File

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

View File

@@ -9,12 +9,38 @@
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
#include "../internal/catch_interfaces_reporter.h"
#include "../internal/catch_errno_guard.hpp"
#include <cstring>
#include <cfloat>
#include <cstdio>
#include <assert.h>
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> {
StreamingReporterBase( ReporterConfig const& _config )

View File

@@ -37,8 +37,7 @@ namespace Catch {
stream << "No test cases matched '" << spec << '\'' << std::endl;
}
virtual void assertionStarting( AssertionInfo const& ) {
}
virtual void assertionStarting( AssertionInfo const& ) {}
virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
AssertionResult const& result = _assertionStats.assertionResult;
@@ -59,6 +58,12 @@ namespace Catch {
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 ) {
printTotals( _testRunStats.totals );
stream << '\n' << std::endl;
@@ -164,7 +169,7 @@ namespace Catch {
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() ) {
{
Colour colourGuard( colour );
@@ -174,7 +179,7 @@ namespace Catch {
}
}
void printIssue( std::string issue ) const {
void printIssue( std::string const& issue ) const {
stream << ' ' << issue;
}

View File

@@ -18,25 +18,6 @@
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 {
ConsoleReporter( ReporterConfig const& _config )
@@ -59,18 +40,15 @@ namespace Catch {
virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
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
if( !m_config->includeSuccessfulResults() && result.isOk() ) {
if( result.getResultType() != ResultWas::Warning )
return false;
printInfoMessages = false;
}
// Drop out if result was successful but we're not printing them.
if( !includeResults && result.getResultType() != ResultWas::Warning )
return false;
lazyPrint();
AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
AssertionPrinter printer( stream, _assertionStats, includeResults );
printer.print();
stream << std::endl;
return true;

View File

@@ -45,18 +45,9 @@ namespace Catch {
virtual void assertionStarting( AssertionInfo const& ) {}
virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
AssertionResult const& result = _assertionStats.assertionResult;
++counter;
bool printInfoMessages = true;
// 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 );
AssertionPrinter printer( stream, _assertionStats, counter );
printer.print();
stream << " # " << currentTestCaseInfo->name ;
@@ -75,13 +66,13 @@ namespace Catch {
class AssertionPrinter {
void operator= ( AssertionPrinter const& );
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 )
, stats( _stats )
, result( _stats.assertionResult )
, messages( _stats.infoMessages )
, itMessage( _stats.infoMessages.begin() )
, printInfoMessages( _printInfoMessages )
, printInfoMessages( true )
, counter(counter)
{}
@@ -156,28 +147,23 @@ namespace Catch {
}
private:
static Colour::Code dimColour() { return Colour::FileName; }
static const char* failedString() { return "not ok"; }
static const char* passedString() { return "ok"; }
void printSourceInfo() const {
Colour colourGuard( Colour::FileName );
Colour colourGuard( dimColour() );
stream << result.getSourceInfo() << ":";
}
void printResultType( std::string passOrFail ) const {
void printResultType( std::string const& passOrFail ) const {
if( !passOrFail.empty() ) {
{
//Colour colourGuard( colour );
stream << passOrFail << " " << counter;
}
stream << " -";
stream << passOrFail << ' ' << counter << " -";
}
}
void printIssue( std::string issue ) const {
void printIssue( std::string const& issue ) const {
stream << " " << issue;
}
@@ -218,8 +204,9 @@ namespace Catch {
}
void printRemainingMessages( Colour::Code colour = dimColour() ) {
if ( itMessage == messages.end() )
if (itMessage == messages.end()) {
return;
}
// using messages.end() directly yields compilation error:
std::vector<MessageInfo>::const_iterator itEnd = messages.end();
@@ -252,17 +239,6 @@ namespace Catch {
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 {
if( totals.testCases.total() == 0 ) {
stream << "1..0 # Skipped: No tests ran.";

View File

@@ -92,73 +92,77 @@ namespace Catch {
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
const AssertionResult& assertionResult = assertionStats.assertionResult;
// Print any info messages in <Info> tags.
if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
AssertionResult const& result = assertionStats.assertionResult;
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();
it != itEnd;
++it ) {
it != itEnd;
++it ) {
if( it->type == ResultWas::Info ) {
m_xml.scopedElement( "Info" )
.writeText( it->message );
.writeText( it->message );
} else if ( it->type == ResultWas::Warning ) {
m_xml.scopedElement( "Warning" )
.writeText( it->message );
.writeText( it->message );
}
}
}
// 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;
// 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" )
.writeText( assertionResult.getExpression() );
.writeText( result.getExpression() );
m_xml.scopedElement( "Expanded" )
.writeText( assertionResult.getExpandedExpression() );
.writeText( result.getExpandedExpression() );
}
// And... Print a result applicable to each result type.
switch( assertionResult.getResultType() ) {
switch( result.getResultType() ) {
case ResultWas::ThrewException:
m_xml.startElement( "Exception" );
writeSourceInfo( assertionResult.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() );
writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( result.getMessage() );
m_xml.endElement();
break;
case ResultWas::FatalErrorCondition:
m_xml.startElement( "FatalErrorCondition" );
writeSourceInfo( assertionResult.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() );
writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( result.getMessage() );
m_xml.endElement();
break;
case ResultWas::Info:
m_xml.scopedElement( "Info" )
.writeText( assertionResult.getMessage() );
.writeText( result.getMessage() );
break;
case ResultWas::Warning:
// Warning will already have been written
break;
case ResultWas::ExplicitFailure:
m_xml.startElement( "Failure" );
writeSourceInfo( assertionResult.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() );
writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( result.getMessage() );
m_xml.endElement();
break;
default:
break;
}
if( assertionResult.hasExpression() )
if( result.hasExpression() )
m_xml.endElement();
return true;

View File

@@ -3,6 +3,17 @@
<exe-name> is a <version> host application.
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
-------------------------------------------------------------------------------
@@ -276,6 +287,20 @@ MessageTests.cpp:<line number>
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
-------------------------------------------------------------------------------
@@ -890,6 +915,6 @@ with expansion:
"first" == "second"
===============================================================================
test cases: 163 | 118 passed | 43 failed | 2 failed as expected
assertions: 953 | 849 passed | 86 failed | 18 failed as expected
test cases: 166 | 119 passed | 44 failed | 3 failed as expected
assertions: 961 | 855 passed | 87 failed | 19 failed as expected

View File

@@ -48,6 +48,23 @@ PASSED:
with expansion:
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
-------------------------------------------------------------------------------
@@ -603,6 +620,32 @@ PASSED:
with expansion:
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
Specifically escaped
@@ -1173,6 +1216,20 @@ MessageTests.cpp:<line number>
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
-------------------------------------------------------------------------------
@@ -3292,7 +3349,7 @@ with expansion:
re>"
-------------------------------------------------------------------------------
Long text is truncted
Long text is truncated
-------------------------------------------------------------------------------
TestMain.cpp:<line number>
...............................................................................
@@ -5814,6 +5871,23 @@ MessageTests.cpp:<line number>:
warning:
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
default - no arguments
@@ -5825,6 +5899,12 @@ TestMain.cpp:<line number>:
PASSED:
CHECK_NOTHROW( parseIntoConfig( argv, config ) )
TestMain.cpp:<line number>:
PASSED:
CHECK( config.processName == "test" )
with expansion:
"test" == "test"
TestMain.cpp:<line number>:
PASSED:
CHECK( config.shouldDebugBreak == false )
@@ -9324,6 +9404,6 @@ MiscTests.cpp:<line number>:
PASSED:
===============================================================================
test cases: 163 | 117 passed | 44 failed | 2 failed as expected
assertions: 955 | 849 passed | 88 failed | 18 failed as expected
test cases: 166 | 118 passed | 45 failed | 3 failed as expected
assertions: 963 | 855 passed | 89 failed | 19 failed as expected

View File

@@ -48,6 +48,23 @@ PASSED:
with expansion:
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
-------------------------------------------------------------------------------
@@ -69,6 +86,6 @@ ConditionTests.cpp:<line number>: FAILED:
CHECK_FALSE( true )
===============================================================================
test cases: 4 | 3 passed | 1 failed
assertions: 10 | 6 passed | 4 failed
test cases: 5 | 3 passed | 1 failed | 1 failed as expected
assertions: 12 | 7 passed | 4 failed | 1 failed as expected

View File

@@ -1,9 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<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="#542" 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}">
<failure message="false != false" type="CHECK">
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/Another 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="General chars" time="{duration}"/>
<testcase classname="Character pretty printing" name="Low ASCII" time="{duration}"/>
@@ -192,6 +199,12 @@ MessageTests.cpp:<line number>
</testcase>
<testcase classname="global" name="FAIL does not require an argument" time="{duration}">
<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>
</failure>
</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/Wrap before" 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="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}"/>
@@ -387,6 +400,7 @@ MessageTests.cpp:<line number>
<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 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="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}"/>

View File

@@ -50,6 +50,25 @@
</Expression>
<OverallResult success="true"/>
</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" >
<Expression success="false" type="CHECK" filename="projects/<exe-name>/ConditionTests.cpp" >
<Original>
@@ -643,6 +662,37 @@
</Section>
<OverallResult success="true"/>
</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" >
<Section name="Specifically escaped" 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" />
<OverallResult success="false"/>
</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" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MiscTests.cpp" >
<Original>
@@ -2607,6 +2666,9 @@
<OverallResult success="false"/>
</TestCase>
<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" >
<Original>
a == 2
@@ -2637,6 +2699,9 @@
2 == 0
</Expanded>
</Expression>
<Info>
but not this
</Info>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/MessageTests.cpp" >
<Original>
a == 2
@@ -3409,7 +3474,7 @@ re>"
</Section>
<OverallResult success="true"/>
</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" >
<Original>
t.toString(), EndsWith( "... message truncated due to excessive size" )
@@ -6150,6 +6215,25 @@ re>"
<OverallResult success="true"/>
</TestCase>
<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" >
<Expression success="true" type="CHECK_NOTHROW" filename="projects/<exe-name>/TestMain.cpp" >
<Original>
@@ -6159,6 +6243,14 @@ re>"
parseIntoConfig( argv, config )
</Expanded>
</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" >
<Original>
config.shouldDebugBreak == false
@@ -6191,7 +6283,7 @@ re>"
true
</Expanded>
</Expression>
<OverallResults successes="5" failures="0" expectedFailures="0"/>
<OverallResults successes="6" failures="0" expectedFailures="0"/>
</Section>
<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" >
@@ -6736,6 +6828,12 @@ re>"
<OverallResult success="true"/>
</TestCase>
<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" >
<Original>
i &lt; 10
@@ -6744,6 +6842,12 @@ re>"
0 &lt; 10
</Expanded>
</Expression>
<Info>
current counter 1
</Info>
<Info>
i := 1
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original>
i &lt; 10
@@ -6752,6 +6856,12 @@ re>"
1 &lt; 10
</Expanded>
</Expression>
<Info>
current counter 2
</Info>
<Info>
i := 2
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original>
i &lt; 10
@@ -6760,6 +6870,12 @@ re>"
2 &lt; 10
</Expanded>
</Expression>
<Info>
current counter 3
</Info>
<Info>
i := 3
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original>
i &lt; 10
@@ -6768,6 +6884,12 @@ re>"
3 &lt; 10
</Expanded>
</Expression>
<Info>
current counter 4
</Info>
<Info>
i := 4
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original>
i &lt; 10
@@ -6776,6 +6898,12 @@ re>"
4 &lt; 10
</Expanded>
</Expression>
<Info>
current counter 5
</Info>
<Info>
i := 5
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original>
i &lt; 10
@@ -6784,6 +6912,12 @@ re>"
5 &lt; 10
</Expanded>
</Expression>
<Info>
current counter 6
</Info>
<Info>
i := 6
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original>
i &lt; 10
@@ -6792,6 +6926,12 @@ re>"
6 &lt; 10
</Expanded>
</Expression>
<Info>
current counter 7
</Info>
<Info>
i := 7
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original>
i &lt; 10
@@ -6800,6 +6940,12 @@ re>"
7 &lt; 10
</Expanded>
</Expression>
<Info>
current counter 8
</Info>
<Info>
i := 8
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original>
i &lt; 10
@@ -6808,6 +6954,12 @@ re>"
8 &lt; 10
</Expanded>
</Expression>
<Info>
current counter 9
</Info>
<Info>
i := 9
</Info>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MessageTests.cpp" >
<Original>
i &lt; 10
@@ -9086,6 +9238,9 @@ spanner <OverallResult success="true"/>
1 == 0
</Expanded>
</Expression>
<Info>
Testing if fib[2] (2) is even
</Info>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/MiscTests.cpp" >
<Original>
( fib[i] % 2 ) == 0
@@ -9116,6 +9271,9 @@ spanner <OverallResult success="true"/>
1 == 0
</Expanded>
</Expression>
<Info>
Testing if fib[5] (8) is even
</Info>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/MiscTests.cpp" >
<Original>
( fib[i] % 2 ) == 0
@@ -9885,7 +10043,7 @@ spanner <OverallResult success="true"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="849" failures="89" expectedFailures="18"/>
<OverallResults successes="855" failures="90" expectedFailures="19"/>
</Group>
<OverallResults successes="849" failures="88" expectedFailures="18"/>
<OverallResults successes="855" failures="89" expectedFailures="19"/>
</Catch>

View File

@@ -11,6 +11,10 @@
#include <string>
#include <stdexcept>
#ifdef _MSC_VER
#pragma warning(disable:4702) // Unreachable code -- MSVC 19 (VS 2015) sees right through the indirection
#endif
namespace
{
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][.]" )
{
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

View File

@@ -16,6 +16,7 @@
#include "../include/internal/catch_xmlwriter.hpp"
#include <iostream>
#include <cerrno>
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 #" ) {
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;
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", "" ) {
const char* argv[] = { "test" };
CHECK_NOTHROW( parseIntoConfig( argv, config ) );
CHECK( config.processName == "test" );
CHECK( config.shouldDebugBreak == false );
CHECK( config.abortAfter == -1 );
CHECK( config.noThrow == false );

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
catch_path = args.catch_header
os.chdir(dir_name)
if args.generate_files:
create_temp_dir()
copy_catch(catch_path)
os.chdir(dir_name)
# now create the fake test files
generate_files()
# Early exit
print('Finished generating files')
exit(1)
os.chdir(dir_name)
if args.flags:
flags = args.flags

View File

@@ -75,7 +75,6 @@ class Version:
f.write( line + "\n" )
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\">' )
f = open( readmePath, 'r' )
lines = []
@@ -84,7 +83,6 @@ class Version:
f.close()
f = open( readmePath, 'w' )
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)
f.write( line + "\n" )

View File

@@ -1,6 +1,6 @@
/*
* Catch v1.8.1
* Generated: 2017-03-01 16:04:19.016511
* Catch v1.8.2
* Generated: 2017-03-13 21:18:33.619572
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@@ -1021,16 +1021,24 @@ namespace Matchers {
}
protected:
virtual ~MatcherUntypedBase();
virtual std::string describe() const = 0;
mutable std::string m_cachedToString;
private:
MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
};
template<typename ObjectT, typename ComparatorT = ObjectT>
struct MatcherBase : MatcherUntypedBase {
template<typename ObjectT>
struct MatcherMethod {
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;
MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
@@ -2893,7 +2901,7 @@ namespace Matchers {
};
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;
CasedString m_comparator;
@@ -3032,7 +3040,7 @@ namespace Matchers {
namespace Catch {
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;
SourceLineInfo lineInfo;
@@ -3304,64 +3312,67 @@ namespace Catch {
namespace Impl {
namespace NSStringMatchers {
template<typename MatcherT>
struct StringHolder : MatcherImpl<MatcherT, NSString*>{
struct StringHolder : MatcherBase<NSString*>{
StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
StringHolder() {
arcSafeRelease( m_substr );
}
virtual bool match( NSString* arg ) const CATCH_OVERRIDE {
return false;
}
NSString* m_substr;
};
struct Equals : StringHolder<Equals> {
struct Equals : StringHolder {
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 ) &&
[str isEqualToString:m_substr];
}
virtual std::string toString() const {
virtual std::string describe() const CATCH_OVERRIDE {
return "equals string: " + Catch::toString( m_substr );
}
};
struct Contains : StringHolder<Contains> {
struct Contains : StringHolder {
Contains( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const {
virtual bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) &&
[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 );
}
};
struct StartsWith : StringHolder<StartsWith> {
struct StartsWith : StringHolder {
StartsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const {
virtual bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) &&
[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 );
}
};
struct EndsWith : StringHolder<EndsWith> {
struct EndsWith : StringHolder {
EndsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const {
virtual bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) &&
[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 );
}
};
@@ -4020,6 +4031,7 @@ namespace Catch {
#include <vector>
#include <sstream>
#include <algorithm>
#include <cctype>
// Use optional outer namespace
#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
@@ -4362,7 +4374,7 @@ namespace Clara {
_dest = _source;
}
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 ) {
std::string sourceLC = _source;
@@ -4516,12 +4528,13 @@ namespace Clara {
}
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];
if( c == '"' )
inQuotes = !inQuotes;
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 ) {
switch( mode ) {
@@ -4554,6 +4567,7 @@ namespace Clara {
default: from = i; return ShortOpt;
}
}
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 )
return mode;
@@ -4885,7 +4899,7 @@ namespace Clara {
}
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( "/\\" );
if( lastSlash != std::string::npos )
processName = processName.substr( lastSlash+1 );
@@ -6292,7 +6306,6 @@ namespace Catch {
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
reset();
reportFatal(signalDefs[i].name);
}
}
@@ -6634,10 +6647,14 @@ namespace Catch {
}
virtual void handleFatalErrorCondition( std::string const& message ) {
ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
resultBuilder.setResultType( ResultWas::FatalErrorCondition );
resultBuilder << message;
resultBuilder.captureExpression();
// Don't rebuild the result -- the stringification itself can cause more fatal errors
// Instead, fake a result data.
AssertionResultData tempResult;
tempResult.resultType = ResultWas::FatalErrorCondition;
tempResult.message = message;
AssertionResult result(m_lastAssertionInfo, tempResult);
getResultCapture().assertionEnded(result);
handleUnfinishedSections();
@@ -7581,6 +7598,23 @@ namespace Catch {
// #included from: catch_console_colour_impl.hpp
#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 {
@@ -7716,6 +7750,7 @@ namespace {
};
IColourImpl* platformColourInstance() {
ErrnoGuard guard;
Ptr<IConfig const> config = getCurrentContext().getConfig();
UseColour::YesOrNo colourMode = config
? config->useColour()
@@ -8138,7 +8173,7 @@ namespace Catch {
return os;
}
Version libraryVersion( 1, 8, 1, "", 0 );
Version libraryVersion( 1, 8, 2, "", 0 );
}
@@ -8567,6 +8602,9 @@ namespace Catch {
// be strace, for example) in /proc/$PID/status, so just get it from
// there instead.
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");
for( std::string line; std::getline(in, line); ) {
static const int PREFIX_LEN = 11;
@@ -9064,7 +9102,7 @@ namespace Matchers {
: std::string();
}
StringMatcherBase::StringMatcherBase( std::string operation, CasedString const& comparator )
StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
: m_comparator( comparator ),
m_operation( operation ) {
}
@@ -9265,10 +9303,34 @@ Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingRepo
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
#include <cstring>
#include <cfloat>
#include <cstdio>
#include <assert.h>
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> {
StreamingReporterBase( ReporterConfig const& _config )
@@ -9594,9 +9656,13 @@ namespace Catch {
#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
// Deprecated - use the form without INTERNAL_
#define INTERNAL_CATCH_REGISTER_LISTENER( 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
#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
@@ -9921,73 +9987,76 @@ namespace Catch {
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
const AssertionResult& assertionResult = assertionStats.assertionResult;
// Print any info messages in <Info> tags.
if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
AssertionResult const& result = assertionStats.assertionResult;
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();
it != itEnd;
++it ) {
it != itEnd;
++it ) {
if( it->type == ResultWas::Info ) {
m_xml.scopedElement( "Info" )
.writeText( it->message );
.writeText( it->message );
} else if ( it->type == ResultWas::Warning ) {
m_xml.scopedElement( "Warning" )
.writeText( it->message );
.writeText( it->message );
}
}
}
// 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;
// Print the expression if there is one.
if( assertionResult.hasExpression() ) {
if( result.hasExpression() ) {
m_xml.startElement( "Expression" )
.writeAttribute( "success", assertionResult.succeeded() )
.writeAttribute( "type", assertionResult.getTestMacroName() );
.writeAttribute( "success", result.succeeded() )
.writeAttribute( "type", result.getTestMacroName() );
writeSourceInfo( assertionResult.getSourceInfo() );
writeSourceInfo( result.getSourceInfo() );
m_xml.scopedElement( "Original" )
.writeText( assertionResult.getExpression() );
.writeText( result.getExpression() );
m_xml.scopedElement( "Expanded" )
.writeText( assertionResult.getExpandedExpression() );
.writeText( result.getExpandedExpression() );
}
// And... Print a result applicable to each result type.
switch( assertionResult.getResultType() ) {
switch( result.getResultType() ) {
case ResultWas::ThrewException:
m_xml.startElement( "Exception" );
writeSourceInfo( assertionResult.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() );
writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( result.getMessage() );
m_xml.endElement();
break;
case ResultWas::FatalErrorCondition:
m_xml.startElement( "FatalErrorCondition" );
writeSourceInfo( assertionResult.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() );
writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( result.getMessage() );
m_xml.endElement();
break;
case ResultWas::Info:
m_xml.scopedElement( "Info" )
.writeText( assertionResult.getMessage() );
.writeText( result.getMessage() );
break;
case ResultWas::Warning:
// Warning will already have been written
break;
case ResultWas::ExplicitFailure:
m_xml.startElement( "Failure" );
writeSourceInfo( assertionResult.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() );
writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( result.getMessage() );
m_xml.endElement();
break;
default:
break;
}
if( assertionResult.hasExpression() )
if( result.hasExpression() )
m_xml.endElement();
return true;
@@ -10299,25 +10368,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 {
ConsoleReporter( ReporterConfig const& _config )
: StreamingReporterBase( _config ),
@@ -10339,18 +10389,15 @@ namespace Catch {
virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
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
if( !m_config->includeSuccessfulResults() && result.isOk() ) {
if( result.getResultType() != ResultWas::Warning )
return false;
printInfoMessages = false;
}
// Drop out if result was successful but we're not printing them.
if( !includeResults && result.getResultType() != ResultWas::Warning )
return false;
lazyPrint();
AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
AssertionPrinter printer( stream, _assertionStats, includeResults );
printer.print();
stream << std::endl;
return true;
@@ -10769,8 +10816,7 @@ namespace Catch {
stream << "No test cases matched '" << spec << '\'' << std::endl;
}
virtual void assertionStarting( AssertionInfo const& ) {
}
virtual void assertionStarting( AssertionInfo const& ) {}
virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
AssertionResult const& result = _assertionStats.assertionResult;
@@ -10791,6 +10837,12 @@ namespace Catch {
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 ) {
printTotals( _testRunStats.totals );
stream << '\n' << std::endl;
@@ -10896,7 +10948,7 @@ namespace Catch {
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() ) {
{
Colour colourGuard( colour );
@@ -10906,7 +10958,7 @@ namespace Catch {
}
}
void printIssue( std::string issue ) const {
void printIssue( std::string const& issue ) const {
stream << ' ' << issue;
}
@@ -11077,6 +11129,7 @@ namespace Catch {
TestSpec::NamePattern::~NamePattern() {}
TestSpec::TagPattern::~TagPattern() {}
TestSpec::ExcludedPattern::~ExcludedPattern() {}
Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {}
void Config::dummy() {}
@@ -11162,8 +11215,8 @@ int main (int argc, char * const argv[]) {
#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_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
#define CATCH_SCOPED_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 " := " << Catch::toString(msg), "CATCH_CAPTURE" )
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
@@ -11172,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_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_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__ )
#else
#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
@@ -11180,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_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_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 )
#endif
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
@@ -11231,24 +11286,26 @@ int main (int argc, char * const argv[]) {
#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
#define SCOPED_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 " := " << Catch::toString(msg), "CAPTURE" )
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __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 REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __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 TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __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 REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __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_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
#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 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 SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
#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 )
#endif
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )