forked from catchorg/Catch2
Compare commits
78 Commits
add_cstdin
...
v2.12.1
Author | SHA1 | Date | |
---|---|---|---|
2e61d38c7c | |||
5c9f09e94a | |||
f4fc2dab2c | |||
cfb6956698 | |||
e59fc2c3b3 | |||
4e4171420d | |||
37cbf4a4fe | |||
38f897c887 | |||
fa4a93e051 | |||
6fbe5efc71 | |||
bad0fb51f8 | |||
a2fc7cf8c0 | |||
da9e3eec65 | |||
f696ab836b | |||
5d32ce26f4 | |||
035a062596 | |||
d399a308d0 | |||
b8ce814ee6 | |||
6260962108 | |||
b4c8967ac5 | |||
7900fb3abb | |||
01bdfe3312 | |||
e5c9a58d66 | |||
255aa5f2af | |||
3a33315ff8 | |||
5f94c8dafb | |||
695a356f93 | |||
020b655635 | |||
5561d0342d | |||
3a15315a37 | |||
b7b346c3e5 | |||
9e09d79946 | |||
7048c2c269 | |||
6f77d59b16 | |||
022b61ff92 | |||
87b5bf77bc | |||
81d52c4a5f | |||
200b8b6fc0 | |||
e70fd2a4b9 | |||
36170d60ca | |||
917e92c162 | |||
f54950744f | |||
b3b07215d1 | |||
2652bb86e3 | |||
1715b6b923 | |||
f20a9dbc6e | |||
273c3f85eb | |||
6a3d0dc176 | |||
ccb1f70629 | |||
4a5bc0f39a | |||
f96e89e016 | |||
481f54b357 | |||
2d172dc688 | |||
587a20b312 | |||
bff44f8b01 | |||
4ea74ff966 | |||
d10b9bd02e | |||
55794e9b27 | |||
fa6211bfc2 | |||
4e90f910dc | |||
0c59cc83cf | |||
e4004e0adb | |||
6c9a255dc2 | |||
9a8963133f | |||
cfba9dce97 | |||
a537ccae22 | |||
e1c9d5569d | |||
d512decaac | |||
f23f96883a | |||
d7b8c3ace3 | |||
32733e08c0 | |||
930f49a641 | |||
c409dccee5 | |||
95bfb33167 | |||
59d2d08c0f | |||
fa6d52e2a3 | |||
5ac348cd6e | |||
776a4686c7 |
@ -14,7 +14,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
endif()
|
||||
|
||||
|
||||
project(Catch2 LANGUAGES CXX VERSION 2.10.2)
|
||||
project(Catch2 LANGUAGES CXX VERSION 2.12.1)
|
||||
|
||||
# Provide path for scripts
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
||||
|
@ -5,11 +5,11 @@
|
||||
[](https://travis-ci.org/catchorg/Catch2)
|
||||
[](https://ci.appveyor.com/project/catchorg/catch2)
|
||||
[](https://codecov.io/gh/catchorg/Catch2)
|
||||
[](https://wandbox.org/permlink/LzYWgcPrcy9yQmed)
|
||||
[](https://wandbox.org/permlink/DQL97fLLJLZXwB8d)
|
||||
[](https://discord.gg/4CWS9zD)
|
||||
|
||||
|
||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.10.2/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.12.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||
|
||||
## Catch2 is released!
|
||||
|
||||
|
@ -1,6 +1,11 @@
|
||||
# version string format -- This will be overwritten later anyway
|
||||
version: "{build}"
|
||||
|
||||
# We need a more up to date pip because Python 2.7 is EOL soon
|
||||
init:
|
||||
- set PATH=C:\Python35\Scripts;%PATH%
|
||||
|
||||
|
||||
branches:
|
||||
except:
|
||||
- /dev-travis.+/
|
||||
@ -62,7 +67,7 @@ matrix:
|
||||
|
||||
|
||||
install:
|
||||
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { python -m pip --disable-pip-version-check install codecov }
|
||||
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { pip --disable-pip-version-check install codecov }
|
||||
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { .\misc\installOpenCppCoverage.ps1 }
|
||||
|
||||
# Win32 and x64 are CMake-compatible solution platform names.
|
||||
|
@ -144,7 +144,7 @@ function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
|
||||
if("${TestType}" STREQUAL "SCENARIO")
|
||||
set(Name "Scenario: ${Name}")
|
||||
endif()
|
||||
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND TestFixture)
|
||||
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND "${TestType}" MATCHES "(CATCH_)?TEST_CASE_METHOD" AND TestFixture )
|
||||
set(CTestName "${TestFixture}:${Name}")
|
||||
else()
|
||||
set(CTestName "${Name}")
|
||||
|
@ -35,6 +35,7 @@ FAQ:
|
||||
Other:
|
||||
* [Why Catch?](why-catch.md#top)
|
||||
* [Open Source Projects using Catch](opensource-users.md#top)
|
||||
* [Commercial Projects using Catch](commercial-users.md#top)
|
||||
* [Contributing](contributing.md#top)
|
||||
* [Release Notes](release-notes.md#top)
|
||||
* [Deprecations and incoming changes](deprecations.md#top)
|
||||
|
@ -168,7 +168,7 @@ Note that it is not possible to simply use the same instance for different runs
|
||||
and resetting it between each run since that would pollute the measurements with
|
||||
the resetting code.
|
||||
|
||||
It is also possible to just provide an argument name to the simple `BENCHMARK` macro to get
|
||||
It is also possible to just provide an argument name to the simple `BENCHMARK` macro to get
|
||||
the same semantics as providing a callable to `meter.measure` with `int` argument:
|
||||
|
||||
```c++
|
||||
@ -189,19 +189,17 @@ construct and destroy objects without dynamic allocation and in a way that lets
|
||||
you measure construction and destruction separately.
|
||||
|
||||
```c++
|
||||
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter)
|
||||
{
|
||||
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) {
|
||||
std::vector<Catch::Benchmark::storage_for<std::string>> storage(meter.runs());
|
||||
meter.measure([&](int i) { storage[i].construct("thing"); });
|
||||
})
|
||||
};
|
||||
|
||||
BENCHMARK_ADVANCED("destroy", [](Catch::Benchmark::Chronometer meter)
|
||||
{
|
||||
BENCHMARK_ADVANCED("destroy")(Catch::Benchmark::Chronometer meter) {
|
||||
std::vector<Catch::Benchmark::destructable_object<std::string>> storage(meter.runs());
|
||||
for(auto&& o : storage)
|
||||
o.construct("thing");
|
||||
meter.measure([&](int i) { storage[i].destruct(); });
|
||||
})
|
||||
};
|
||||
```
|
||||
|
||||
`Catch::Benchmark::storage_for<T>` objects are just pieces of raw storage suitable for `T`
|
||||
|
@ -6,6 +6,7 @@
|
||||
[Automatic test registration](#automatic-test-registration)<br>
|
||||
[CMake project options](#cmake-project-options)<br>
|
||||
[Installing Catch2 from git repository](#installing-catch2-from-git-repository)<br>
|
||||
[Installing Catch2 from vcpkg](#installing-catch2-from-vcpkg)<br>
|
||||
|
||||
Because we use CMake to build Catch2, we also provide a couple of
|
||||
integration points for our users.
|
||||
@ -220,6 +221,19 @@ when configuring the build, and then modify your calls to
|
||||
[find_package](https://cmake.org/cmake/help/latest/command/find_package.html)
|
||||
accordingly.
|
||||
|
||||
## Installing Catch2 from vcpkg
|
||||
|
||||
Alternatively, you can build and install Catch2 using [vcpkg](https://github.com/microsoft/vcpkg/) dependency manager:
|
||||
```
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
./vcpkg install catch2
|
||||
```
|
||||
|
||||
The catch2 port in vcpkg is kept up to date by microsoft team members and community contributors.
|
||||
If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
---
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
[Specify the number of resamples for bootstrapping](#specify-the-number-of-resamples-for-bootstrapping)<br>
|
||||
[Specify the confidence-interval for bootstrapping](#specify-the-confidence-interval-for-bootstrapping)<br>
|
||||
[Disable statistical analysis of collected benchmark samples](#disable-statistical-analysis-of-collected-benchmark-samples)<br>
|
||||
[Specify the amount of time in milliseconds spent on warming up each test](#specify-the-amount-of-time-in-milliseconds-spent-on-warming-up-each-test)<br>
|
||||
[Usage](#usage)<br>
|
||||
[Specify the section to run](#specify-the-section-to-run)<br>
|
||||
[Filenames as tags](#filenames-as-tags)<br>
|
||||
@ -64,6 +65,7 @@ Click one of the following links to take you straight to that option - or scroll
|
||||
<a href="#benchmark-resamples"> ` --benchmark-resamples`</a><br />
|
||||
<a href="#benchmark-confidence-interval"> ` --benchmark-confidence-interval`</a><br />
|
||||
<a href="#benchmark-no-analysis"> ` --benchmark-no-analysis`</a><br />
|
||||
<a href="#benchmark-warmup-time"> ` --benchmark-warmup-time`</a><br />
|
||||
<a href="#use-colour"> ` --use-colour`</a><br />
|
||||
|
||||
</br>
|
||||
@ -241,15 +243,25 @@ This option lists all available tests in a non-indented form, one on each line.
|
||||
|
||||
Test cases are ordered one of three ways:
|
||||
|
||||
|
||||
### decl
|
||||
Declaration order (this is the default order if no --order argument is provided). The order the tests were originally declared in. Note that ordering between files is not guaranteed and is implementation dependent.
|
||||
Declaration order (this is the default order if no --order argument is provided).
|
||||
Tests in the same TU are sorted using their declaration orders, different
|
||||
TUs are in an implementation (linking) dependent order.
|
||||
|
||||
|
||||
### lex
|
||||
Lexicographically sorted. Tests are sorted, alpha-numerically, by name.
|
||||
Lexicographic order. Tests are sorted by their name, their tags are ignored.
|
||||
|
||||
|
||||
### rand
|
||||
Randomly sorted. Test names are sorted using ```std::random_shuffle()```. By default the random number generator is seeded with 0 - and so the order is repeatable. To control the random seed see <a href="#rng-seed">rng-seed</a>.
|
||||
|
||||
Randomly sorted. The order is dependent on Catch2's random seed (see
|
||||
[`--rng-seed`](#rng-seed)), and is subset invariant. What this means
|
||||
is that as long as the random seed is fixed, running only some tests
|
||||
(e.g. via tag) does not change their relative order.
|
||||
|
||||
> The subset stability was introduced in Catch2 v2.12.0
|
||||
|
||||
|
||||
<a id="rng-seed"></a>
|
||||
## Specify a seed for the Random Number Generator
|
||||
@ -269,7 +281,7 @@ See [The LibIdentify repo for more information and examples](https://github.com/
|
||||
|
||||
<a id="wait-for-keypress"></a>
|
||||
## Wait for key before continuing
|
||||
<pre>--wait-for-keypress <start|exit|both></pre>
|
||||
<pre>--wait-for-keypress <never|start|exit|both></pre>
|
||||
|
||||
Will cause the executable to print a message and wait until the return/ enter key is pressed before continuing -
|
||||
either before running any tests, after running all tests - or both, depending on the argument.
|
||||
@ -317,6 +329,14 @@ Must be between 0 and 1 and defaults to 0.95.
|
||||
When this flag is specified no bootstrapping or any other statistical analysis is performed.
|
||||
Instead the user code is only measured and the plain mean from the samples is reported.
|
||||
|
||||
<a id="benchmark-warmup-time"></a>
|
||||
## Specify the amount of time in milliseconds spent on warming up each test
|
||||
<pre>--benchmark-warmup-time</pre>
|
||||
|
||||
> [Introduced](https://github.com/catchorg/Catch2/pull/1844) in Catch 2.11.2.
|
||||
|
||||
Configure the amount of time spent warming up each test.
|
||||
|
||||
<a id="usage"></a>
|
||||
## Usage
|
||||
<pre>-h, -?, --help</pre>
|
||||
|
@ -17,4 +17,6 @@ fact then please let us know - either directly, via a PR or
|
||||
- NASA
|
||||
- [Inscopix Inc.](https://www.inscopix.com/)
|
||||
- [Makimo](https://makimo.pl/)
|
||||
- [UX3D] (https://ux3d.io)
|
||||
- [UX3D](https://ux3d.io)
|
||||
- [King](https://king.com)
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
[Windows header clutter](#windows-header-clutter)<br>
|
||||
[Enabling stringification](#enabling-stringification)<br>
|
||||
[Disabling exceptions](#disabling-exceptions)<br>
|
||||
[Overriding Catch's debug break (`-b`)](#overriding-catchs-debug-break--b)<br>
|
||||
|
||||
Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```).
|
||||
|
||||
@ -257,6 +258,18 @@ namespace Catch {
|
||||
}
|
||||
```
|
||||
|
||||
## Overriding Catch's debug break (`-b`)
|
||||
|
||||
> [Introduced](https://github.com/catchorg/Catch2/pull/1846) in Catch 2.11.2.
|
||||
|
||||
You can override Catch2's break-into-debugger code by defining the
|
||||
`CATCH_BREAK_INTO_DEBUGGER()` macro. This can be used if e.g. Catch2 does
|
||||
not know your platform, or your platform is misdetected.
|
||||
|
||||
The macro will be used as is, that is, `CATCH_BREAK_INTO_DEBUGGER();`
|
||||
must compile and must break into debugger.
|
||||
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md#top)
|
||||
|
@ -45,6 +45,34 @@ There should be no reason to ever have an empty `SourceLineInfo`, so the
|
||||
method will be removed.
|
||||
|
||||
|
||||
### Composing lvalues of already composed matchers
|
||||
|
||||
Because a significant bug in this use case has persisted for 2+ years
|
||||
without a bug report, and to simplify the implementation, code that
|
||||
composes lvalues of composed matchers will not compile. That is,
|
||||
this code will no longer work:
|
||||
|
||||
```cpp
|
||||
auto m1 = Contains("string");
|
||||
auto m2 = Contains("random");
|
||||
auto composed1 = m1 || m2;
|
||||
auto m3 = Contains("different");
|
||||
auto composed2 = composed1 || m3;
|
||||
REQUIRE_THAT(foo(), !composed1);
|
||||
REQUIRE_THAT(foo(), composed2);
|
||||
```
|
||||
|
||||
Instead you will have to write this:
|
||||
|
||||
```cpp
|
||||
auto m1 = Contains("string");
|
||||
auto m2 = Contains("random");
|
||||
auto m3 = Contains("different");
|
||||
REQUIRE_THAT(foo(), !(m1 || m2));
|
||||
REQUIRE_THAT(foo(), m1 || m2 || m3);
|
||||
```
|
||||
|
||||
|
||||
## Planned changes
|
||||
|
||||
|
||||
|
@ -78,7 +78,7 @@ type, making their usage much nicer. These are
|
||||
|
||||
> `from_range` has been introduced in Catch 2.10.0
|
||||
|
||||
> `range()` for floating point numbers has been introduced in Catch X.Y.Z
|
||||
> `range()` for floating point numbers has been introduced in Catch 2.11.0
|
||||
|
||||
And can be used as shown in the example below to create a generator
|
||||
that returns 100 odd random number:
|
||||
|
@ -20,18 +20,21 @@ Listing a project here does not imply endorsement and the plan is to keep these
|
||||
### [ApprovalTests.cpp](https://github.com/approvals/ApprovalTests.cpp)
|
||||
C++11 implementation of Approval Tests, for quick, convenient testing of legacy code.
|
||||
|
||||
### [args](https://github.com/Taywee/args)
|
||||
A simple header-only C++ argument parser library.
|
||||
|
||||
### [Azmq](https://github.com/zeromq/azmq)
|
||||
Boost Asio style bindings for ZeroMQ.
|
||||
|
||||
### [Cataclysm: Dark Days Ahead](https://github.com/CleverRaven/Cataclysm-DDA)
|
||||
Post-apocalyptic survival RPG.
|
||||
|
||||
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
|
||||
The core part of the Chakra JavaScript engine that powers Microsoft Edge.
|
||||
|
||||
### [ChaiScript](https://github.com/ChaiScript/ChaiScript)
|
||||
A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques.
|
||||
|
||||
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
|
||||
The core part of the Chakra JavaScript engine that powers Microsoft Edge.
|
||||
|
||||
### [Clara](https://github.com/philsquared/Clara)
|
||||
A, single-header-only, type-safe, command line parser - which also prints formatted usage strings.
|
||||
|
||||
@ -65,9 +68,6 @@ A small C++ library wrapper for the native C ODBC API.
|
||||
### [Nonius](https://github.com/libnonius/nonius)
|
||||
A header-only framework for benchmarking small snippets of C++ code.
|
||||
|
||||
### [SOCI](https://github.com/SOCI/soci)
|
||||
The C++ Database Access Library.
|
||||
|
||||
### [polymorphic_value](https://github.com/jbcoe/polymorphic_value)
|
||||
A polymorphic value-type for C++.
|
||||
|
||||
@ -77,18 +77,21 @@ A C++ client library for Consul. Consul is a distributed tool for discovering an
|
||||
### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp)
|
||||
A library of algorithms for values-distributed-in-time.
|
||||
|
||||
### [thor](https://github.com/xorz57/thor)
|
||||
Wrapper Library for CUDA.
|
||||
### [SOCI](https://github.com/SOCI/soci)
|
||||
The C++ Database Access Library.
|
||||
|
||||
### [TextFlowCpp](https://github.com/philsquared/textflowcpp)
|
||||
A small, single-header-only, library for wrapping and composing columns of text.
|
||||
|
||||
### [thor](https://github.com/xorz57/thor)
|
||||
Wrapper Library for CUDA.
|
||||
|
||||
### [toml++](https://github.com/marzer/tomlplusplus)
|
||||
A header-only TOML parser and serializer for modern C++.
|
||||
|
||||
### [Trompeloeil](https://github.com/rollbear/trompeloeil)
|
||||
A thread-safe header-only mocking framework for C++14.
|
||||
|
||||
### [args](https://github.com/Taywee/args)
|
||||
A simple header-only C++ argument parser library.
|
||||
|
||||
## Applications & Tools
|
||||
|
||||
### [ArangoDB](https://github.com/arangodb/arangodb)
|
||||
@ -103,6 +106,9 @@ MAME originally stood for Multiple Arcade Machine Emulator.
|
||||
### [Newsbeuter](https://github.com/akrennmair/newsbeuter)
|
||||
Newsbeuter is an open-source RSS/Atom feed reader for text terminals.
|
||||
|
||||
### [PopHead](https://github.com/SPC-Some-Polish-Coders/PopHead)
|
||||
A 2D, Zombie, RPG game which is being made on our own engine.
|
||||
|
||||
### [raspigcd](https://github.com/pantadeusz/raspigcd)
|
||||
Low level CLI app and library for execution of GCODE on Raspberry Pi without any additional microcontrolers (just RPi + Stepsticks).
|
||||
|
||||
@ -112,9 +118,6 @@ SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gr
|
||||
### [Standardese](https://github.com/foonathan/standardese)
|
||||
Standardese aims to be a nextgen Doxygen.
|
||||
|
||||
### [PopHead](https://github.com/SPC-Some-Polish-Coders/PopHead)
|
||||
A 2D, Zombie, RPG game which is being made on our own engine.
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md#top)
|
||||
|
@ -2,6 +2,12 @@
|
||||
|
||||
# Release notes
|
||||
**Contents**<br>
|
||||
[2.12.1](#2121)<br>
|
||||
[2.12.0](#2120)<br>
|
||||
[2.11.3](#2113)<br>
|
||||
[2.11.2](#2112)<br>
|
||||
[2.11.1](#2111)<br>
|
||||
[2.11.0](#2110)<br>
|
||||
[2.10.2](#2102)<br>
|
||||
[2.10.1](#2101)<br>
|
||||
[2.10.0](#2100)<br>
|
||||
@ -30,6 +36,97 @@
|
||||
[Older versions](#older-versions)<br>
|
||||
[Even Older versions](#even-older-versions)<br>
|
||||
|
||||
## 2.12.1
|
||||
|
||||
### Fixes
|
||||
* Vector matchers now support initializer list literals better
|
||||
|
||||
### Improvements
|
||||
* Added support for `^` (bitwise xor) to `CHECK` and `REQUIRE`
|
||||
|
||||
|
||||
## 2.12.0
|
||||
|
||||
### Improvements
|
||||
* Running tests in random order (`--order rand`) has been reworked significantly (#1908)
|
||||
* Given same seed, all platforms now produce the same order
|
||||
* Given same seed, the relative order of tests does not change if you select only a subset of them
|
||||
* Vector matchers support custom allocators (#1909)
|
||||
* `|` and `&` (bitwise or and bitwise and) are now supported in `CHECK` and `REQUIRE`
|
||||
* The resulting type must be convertible to `bool`
|
||||
|
||||
### Fixes
|
||||
* Fixed computation of benchmarking column widths in ConsoleReporter (#1885, #1886)
|
||||
* Suppressed clang-tidy's `cppcoreguidelines-pro-type-vararg` in assertions (#1901)
|
||||
* It was a false positive trigered by the new warning support workaround
|
||||
* Fixed bug in test specification parser handling of OR'd patterns using escaping (#1905)
|
||||
|
||||
### Miscellaneous
|
||||
* Worked around IBM XL's codegen bug (#1907)
|
||||
* It would emit code for _destructors_ of temporaries in an unevaluated context
|
||||
* Improved detection of stdlib's support for `std::uncaught_exceptions` (#1911)
|
||||
|
||||
|
||||
## 2.11.3
|
||||
|
||||
### Fixes
|
||||
* Fixed compilation error caused by lambdas in assertions under MSVC
|
||||
|
||||
|
||||
## 2.11.2
|
||||
|
||||
### Improvements
|
||||
* GCC and Clang now issue warnings for suspicious code in assertions (#1880)
|
||||
* E.g. `REQUIRE( int != unsigned int )` will now issue mixed signedness comparison warning
|
||||
* This has always worked on MSVC, but it now also works for GCC and current Clang versions
|
||||
* Colorization of "Test filters" output should be more robust now
|
||||
* `--wait-for-keypress` now also accepts `never` as an option (#1866)
|
||||
* Reporters no longer round-off nanoseconds when reporting benchmarking results (#1876)
|
||||
* Catch2's debug break now supports iOS while using Thumb instruction set (#1862)
|
||||
* It is now possible to customize benchmark's warm-up time when running the test binary (#1844)
|
||||
* `--benchmark-warmup-time {ms}`
|
||||
* User can now specify how Catch2 should break into debugger (#1846)
|
||||
|
||||
### Fixes
|
||||
* Fixes missing `<random>` include in benchmarking (#1831)
|
||||
* Fixed missing `<iterator>` include in benchmarking (#1874)
|
||||
* Hidden test cases are now also tagged with `[!hide]` as per documentation (#1847)
|
||||
* Detection of whether libc provides `std::nextafter` has been improved (#1854)
|
||||
* Detection of `wmain` no longer incorrectly looks for `WIN32` macro (#1849)
|
||||
* Now it just detects Windows platform
|
||||
* Composing already-composed matchers no longer modifies the partially-composed matcher expression
|
||||
* This bug has been present for the last ~2 years and nobody reported it
|
||||
|
||||
|
||||
## 2.11.1
|
||||
|
||||
### Improvements
|
||||
* Breaking into debugger is supported on iOS (#1817)
|
||||
* `google-build-using-namespace` clang-tidy warning is suppressed (#1799)
|
||||
|
||||
### Fixes
|
||||
* Clang on Windows is no longer assumed to implement MSVC's traditional preprocessor (#1806)
|
||||
* `ObjectStorage` now behaves properly in `const` contexts (#1820)
|
||||
* `GENERATE_COPY(a, b)` now compiles properly (#1809, #1815)
|
||||
* Some more cleanups in the benchmarking support
|
||||
|
||||
|
||||
## 2.11.0
|
||||
|
||||
### Improvements
|
||||
* JUnit reporter output now contains more details in case of failure (#1347, #1719)
|
||||
* Added SonarQube Test Data reporter (#1738)
|
||||
* It is in a separate header, just like the TAP, Automake, and TeamCity reporters
|
||||
* `range` generator now allows floating point numbers (#1776)
|
||||
* Reworked part of internals to increase throughput
|
||||
|
||||
|
||||
### Fixes
|
||||
* The single header version should contain full benchmarking support (#1800)
|
||||
* `[.foo]` is now properly parsed as `[.][foo]` when used on the command line (#1798)
|
||||
* Fixed compilation of benchmarking on platforms where `steady_clock::period` is not `std::nano` (#1794)
|
||||
|
||||
|
||||
|
||||
## 2.10.2
|
||||
|
||||
|
@ -67,6 +67,7 @@ $ gpg2 --armor --output catch.hpp.asc --detach-sig catch.hpp
|
||||
$ gpg2 --armor --output catch_reporter_automake.hpp.asc --detach-sig catch_reporter_automake.hpp
|
||||
$ gpg2 --armor --output catch_reporter_teamcity.hpp.asc --detach-sig catch_reporter_teamcity.hpp
|
||||
$ gpg2 --armor --output catch_reporter_tap.hpp.asc --detach-sig catch_reporter_tap.hpp
|
||||
$ gpg2 --armor --output catch_reporter_sonarqube.hpp.asc --detach-sig catch_reporter_sonarqube.hpp
|
||||
```
|
||||
|
||||
_GPG does not support signing multiple files in single invocation._
|
||||
|
@ -22,7 +22,7 @@ But functions and methods can also be written inline in header files. The downsi
|
||||
|
||||
Because Catch is implemented *entirely* in headers you might think that the whole of Catch must be compiled into every translation unit that uses it! Actually it's not quite as bad as that. Catch mitigates this situation by effectively maintaining the traditional separation between the implementation code and declarations. Internally the implementation code is protected by ```#ifdef```s and is conditionally compiled into only one translation unit. This translation unit is that one that ```#define```s ```CATCH_CONFIG_MAIN``` or ```CATCH_CONFIG_RUNNER```. Let's call this the main source file.
|
||||
|
||||
As a result the main source file *does* compile the whole of Catch every time! So it makes sense to dedicate this file to *only* ```#define```-ing the identifier and ```#include```-ing Catch (and implementing the runner code, if you're doing that). Keep all your test cases in other files. This way you won't pay the recompilation cost for the whole of Catch
|
||||
As a result the main source file *does* compile the whole of Catch every time! So it makes sense to dedicate this file to *only* ```#define```-ing the identifier and ```#include```-ing Catch (and implementing the runner code, if you're doing that). Keep all your test cases in other files. This way you won't pay the recompilation cost for the whole of Catch.
|
||||
|
||||
## Practical example
|
||||
Assume you have the `Factorial` function from the [tutorial](tutorial.md#top) in `factorial.cpp` (with forward declaration in `factorial.h`) and want to test it and keep the compile times down when adding new tests. Then you should have 2 files, `tests-main.cpp` and `tests-factorial.cpp`:
|
||||
|
@ -106,7 +106,7 @@ Of course there are still more issues to deal with. For example we'll hit proble
|
||||
Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take a moment to consider those before we move on.
|
||||
|
||||
1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will [respond to command line arguments](command-line.md#top). You can only use that ```#define``` in one implementation file, for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "catch.hpp"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define CATCH_CONFIG_MAIN``` and ```#include "catch.hpp"```. You can also provide your own implementation of main and drive Catch yourself (see [Supplying-your-own-main()](own-main.md#top)).
|
||||
2. We introduce test cases with the ```TEST_CASE``` macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see <a href="#test-cases-and-sections">Test cases and Sections</a>, ). The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md#top) for more information on running tests.
|
||||
2. We introduce test cases with the ```TEST_CASE``` macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see <a href="#test-cases-and-sections">Test cases and Sections</a>). The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md#top) for more information on running tests.
|
||||
3. The name and tags arguments are just strings. We haven't had to declare a function or method - or explicitly register the test case anywhere. Behind the scenes a function with a generated name is defined for you, and automatically registered using static registry classes. By abstracting the function name away we can name our tests without the constraints of identifier names.
|
||||
4. We write our individual test assertions using the ```REQUIRE``` macro. Rather than a separate macro for each type of condition we express the condition naturally using C/C++ syntax. Behind the scenes a simple set of expression templates captures the left-hand-side and right-hand-side of the expression so we can display the values in our test report. As we'll see later there _are_ other assertion macros - but because of this technique the number of them is drastically reduced.
|
||||
|
||||
|
@ -24,7 +24,7 @@ std::string ws(int const level) {
|
||||
template< typename T >
|
||||
std::ostream& operator<<( std::ostream& os, std::vector<T> const& v ) {
|
||||
os << "{ ";
|
||||
for ( auto x : v )
|
||||
for ( const auto& x : v )
|
||||
os << x << ", ";
|
||||
return os << "}";
|
||||
}
|
||||
@ -57,7 +57,7 @@ void print( std::ostream& os, int const level, Catch::MessageInfo const& info )
|
||||
|
||||
void print( std::ostream& os, int const level, std::string const& title, std::vector<Catch::MessageInfo> const& v ) {
|
||||
os << ws(level ) << title << ":\n";
|
||||
for ( auto x : v )
|
||||
for ( const auto& x : v )
|
||||
{
|
||||
os << ws(level+1) << "{\n";
|
||||
print( os, level+2, x );
|
||||
@ -300,7 +300,7 @@ char const * dashed_line =
|
||||
struct MyListener : Catch::TestEventListenerBase {
|
||||
|
||||
using TestEventListenerBase::TestEventListenerBase; // inherit constructor
|
||||
|
||||
|
||||
// Get rid of Wweak-tables
|
||||
~MyListener();
|
||||
|
||||
|
@ -10,12 +10,13 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
|
||||
class out_buff : public std::stringbuf {
|
||||
std::FILE* m_stream;
|
||||
public:
|
||||
out_buff(std::FILE* stream) :m_stream(stream) {}
|
||||
~out_buff() { pubsync(); }
|
||||
int sync() {
|
||||
out_buff(std::FILE* stream):m_stream(stream) {}
|
||||
~out_buff();
|
||||
int sync() override {
|
||||
int ret = 0;
|
||||
for (unsigned char c : str()) {
|
||||
if (putc(c, m_stream) == EOF) {
|
||||
@ -29,6 +30,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
out_buff::~out_buff() { pubsync(); }
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wexit-time-destructors" // static variables in cout/cerr/clog
|
||||
#endif
|
||||
|
||||
namespace Catch {
|
||||
std::ostream& cout() {
|
||||
static std::ostream ret(new out_buff(stdout));
|
||||
|
@ -22,15 +22,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::string const& get() const override {
|
||||
return m_line;
|
||||
}
|
||||
std::string const& get() const override;
|
||||
|
||||
bool next() override {
|
||||
return !!std::getline(m_stream, m_line);
|
||||
}
|
||||
};
|
||||
|
||||
std::string const& LineGenerator::get() const {
|
||||
return m_line;
|
||||
}
|
||||
|
||||
// This helper function provides a nicer UX when instantiating the generator
|
||||
// Notice that it returns an instance of GeneratorWrapper<std::string>, which
|
||||
// is a value-wrapper around std::unique_ptr<IGenerator<std::string>>.
|
||||
|
@ -10,8 +10,8 @@
|
||||
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
||||
|
||||
#define CATCH_VERSION_MAJOR 2
|
||||
#define CATCH_VERSION_MINOR 10
|
||||
#define CATCH_VERSION_PATCH 2
|
||||
#define CATCH_VERSION_MINOR 12
|
||||
#define CATCH_VERSION_PATCH 1
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang system_header
|
||||
@ -80,7 +80,7 @@
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||
#include "internal/benchmark/catch_benchmark.hpp"
|
||||
#include "internal/benchmark/catch_benchmarking_all.hpp"
|
||||
#endif
|
||||
|
||||
#endif // ! CATCH_CONFIG_IMPL_ONLY
|
||||
|
@ -44,10 +44,10 @@ namespace Catch {
|
||||
template <typename Clock>
|
||||
ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {
|
||||
auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
|
||||
auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(Detail::warmup_time));
|
||||
auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
|
||||
auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun);
|
||||
int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
|
||||
return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(Detail::warmup_time), Detail::warmup_iterations };
|
||||
return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
|
||||
}
|
||||
|
||||
template <typename Clock = default_clock>
|
||||
@ -79,7 +79,7 @@ namespace Catch {
|
||||
});
|
||||
|
||||
auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
|
||||
BenchmarkStats<std::chrono::duration<double, std::nano>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
|
||||
BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
|
||||
getResultCapture().benchmarkEnded(stats);
|
||||
|
||||
} CATCH_CATCH_ALL{
|
||||
|
29
include/internal/benchmark/catch_benchmarking_all.hpp
Normal file
29
include/internal/benchmark/catch_benchmarking_all.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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)
|
||||
*/
|
||||
|
||||
|
||||
// A proxy header that includes all of the benchmarking headers to allow
|
||||
// concise include of the benchmarking features. You should prefer the
|
||||
// individual includes in standard use.
|
||||
|
||||
#include "catch_benchmark.hpp"
|
||||
#include "catch_chronometer.hpp"
|
||||
#include "catch_clock.hpp"
|
||||
#include "catch_constructor.hpp"
|
||||
#include "catch_environment.hpp"
|
||||
#include "catch_estimate.hpp"
|
||||
#include "catch_execution_plan.hpp"
|
||||
#include "catch_optimizer.hpp"
|
||||
#include "catch_outlier_classification.hpp"
|
||||
#include "catch_sample_analysis.hpp"
|
||||
#include "detail/catch_analyse.hpp"
|
||||
#include "detail/catch_benchmark_function.hpp"
|
||||
#include "detail/catch_complete_invoke.hpp"
|
||||
#include "detail/catch_estimate_clock.hpp"
|
||||
#include "detail/catch_measure.hpp"
|
||||
#include "detail/catch_repeat.hpp"
|
||||
#include "detail/catch_run_for_at_least.hpp"
|
||||
#include "detail/catch_stats.hpp"
|
||||
#include "detail/catch_timing.hpp"
|
@ -14,60 +14,66 @@
|
||||
#include <type_traits>
|
||||
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
template <typename T, bool Destruct>
|
||||
struct ObjectStorage
|
||||
{
|
||||
using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
|
||||
|
||||
ObjectStorage() : data() {}
|
||||
|
||||
ObjectStorage(const ObjectStorage& other)
|
||||
namespace Benchmark {
|
||||
namespace Detail {
|
||||
template <typename T, bool Destruct>
|
||||
struct ObjectStorage
|
||||
{
|
||||
new(&data) T(other.stored_object());
|
||||
}
|
||||
using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
|
||||
|
||||
ObjectStorage(ObjectStorage&& other)
|
||||
{
|
||||
new(&data) T(std::move(other.stored_object()));
|
||||
}
|
||||
ObjectStorage() : data() {}
|
||||
|
||||
~ObjectStorage() { destruct_on_exit<T>(); }
|
||||
ObjectStorage(const ObjectStorage& other)
|
||||
{
|
||||
new(&data) T(other.stored_object());
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void construct(Args&&... args)
|
||||
{
|
||||
new (&data) T(std::forward<Args>(args)...);
|
||||
}
|
||||
ObjectStorage(ObjectStorage&& other)
|
||||
{
|
||||
new(&data) T(std::move(other.stored_object()));
|
||||
}
|
||||
|
||||
template <bool AllowManualDestruction = !Destruct>
|
||||
typename std::enable_if<AllowManualDestruction>::type destruct()
|
||||
{
|
||||
stored_object().~T();
|
||||
}
|
||||
~ObjectStorage() { destruct_on_exit<T>(); }
|
||||
|
||||
private:
|
||||
// If this is a constructor benchmark, destruct the underlying object
|
||||
template <typename U>
|
||||
void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }
|
||||
// Otherwise, don't
|
||||
template <typename U>
|
||||
void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
|
||||
template <typename... Args>
|
||||
void construct(Args&&... args)
|
||||
{
|
||||
new (&data) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
T& stored_object()
|
||||
{
|
||||
return *static_cast<T*>(static_cast<void*>(&data));
|
||||
}
|
||||
template <bool AllowManualDestruction = !Destruct>
|
||||
typename std::enable_if<AllowManualDestruction>::type destruct()
|
||||
{
|
||||
stored_object().~T();
|
||||
}
|
||||
|
||||
TStorage data;
|
||||
};
|
||||
private:
|
||||
// If this is a constructor benchmark, destruct the underlying object
|
||||
template <typename U>
|
||||
void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }
|
||||
// Otherwise, don't
|
||||
template <typename U>
|
||||
void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
|
||||
|
||||
T& stored_object() {
|
||||
return *static_cast<T*>(static_cast<void*>(&data));
|
||||
}
|
||||
|
||||
T const& stored_object() const {
|
||||
return *static_cast<T*>(static_cast<void*>(&data));
|
||||
}
|
||||
|
||||
|
||||
TStorage data;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using storage_for = Detail::ObjectStorage<T, true>;
|
||||
|
||||
template <typename T>
|
||||
using destructable_object = Detail::ObjectStorage<T, false>;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using storage_for = Detail::ObjectStorage<T, true>;
|
||||
|
||||
template <typename T>
|
||||
using destructable_object = Detail::ObjectStorage<T, false>;
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED
|
||||
|
@ -18,11 +18,13 @@
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <cmath>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#include <random>
|
||||
|
||||
namespace Catch {
|
||||
namespace Benchmark {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "catch_interfaces_registry_hub.h"
|
||||
#include "catch_capture_matchers.h"
|
||||
#include "catch_run_context.h"
|
||||
#include "catch_enforce.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
|
@ -41,6 +41,8 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
|
||||
do { \
|
||||
/* The expression should not be evaluated, but warnings should hopefully be checked */ \
|
||||
CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \
|
||||
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
|
||||
INTERNAL_CATCH_TRY { \
|
||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||
@ -49,8 +51,7 @@
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
|
||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||
} while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
|
||||
// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
|
||||
} while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
|
||||
|
@ -50,14 +50,13 @@ namespace Catch {
|
||||
if( !startsWith( line, '"' ) )
|
||||
line = '"' + line + '"';
|
||||
config.testsOrTags.push_back( line );
|
||||
config.testsOrTags.push_back( "," );
|
||||
|
||||
config.testsOrTags.emplace_back( "," );
|
||||
}
|
||||
}
|
||||
//Remove comma in the end
|
||||
if(!config.testsOrTags.empty())
|
||||
config.testsOrTags.erase( config.testsOrTags.end()-1 );
|
||||
|
||||
|
||||
return ParserResult::ok( ParseResultType::Matched );
|
||||
};
|
||||
auto const setTestOrder = [&]( std::string const& order ) {
|
||||
@ -92,14 +91,16 @@ namespace Catch {
|
||||
};
|
||||
auto const setWaitForKeypress = [&]( std::string const& keypress ) {
|
||||
auto keypressLc = toLower( keypress );
|
||||
if( keypressLc == "start" )
|
||||
if (keypressLc == "never")
|
||||
config.waitForKeypress = WaitForKeypress::Never;
|
||||
else if( keypressLc == "start" )
|
||||
config.waitForKeypress = WaitForKeypress::BeforeStart;
|
||||
else if( keypressLc == "exit" )
|
||||
config.waitForKeypress = WaitForKeypress::BeforeExit;
|
||||
else if( keypressLc == "both" )
|
||||
config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
|
||||
else
|
||||
return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" );
|
||||
return ParserResult::runtimeError( "keypress argument must be one of: never, start, exit or both. '" + keypress + "' not recognised" );
|
||||
return ParserResult::ok( ParseResultType::Matched );
|
||||
};
|
||||
auto const setVerbosity = [&]( std::string const& verbosity ) {
|
||||
@ -199,7 +200,7 @@ namespace Catch {
|
||||
| Opt( config.libIdentify )
|
||||
["--libidentify"]
|
||||
( "report name and version according to libidentify standard" )
|
||||
| Opt( setWaitForKeypress, "start|exit|both" )
|
||||
| Opt( setWaitForKeypress, "never|start|exit|both" )
|
||||
["--wait-for-keypress"]
|
||||
( "waits for a keypress before exiting" )
|
||||
| Opt( config.benchmarkSamples, "samples" )
|
||||
@ -214,7 +215,10 @@ namespace Catch {
|
||||
| Opt( config.benchmarkNoAnalysis )
|
||||
["--benchmark-no-analysis"]
|
||||
( "perform only measurements; do not perform any analysis" )
|
||||
| Arg( config.testsOrTags, "test name|pattern|tags" )
|
||||
| Opt( config.benchmarkWarmupTime, "benchmarkWarmupTime" )
|
||||
["--benchmark-warmup-time"]
|
||||
( "amount of time in milliseconds spent on warming up each test (default: 100)" )
|
||||
| Arg( config.testsOrTags, "test name|pattern|tags" )
|
||||
( "which test or tests to use" );
|
||||
|
||||
return cli;
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_CPP17_OR_GREATER)
|
||||
#if defined(__cpp_lib_uncaught_exceptions)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
@ -48,6 +48,9 @@
|
||||
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC)
|
||||
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
|
||||
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
|
||||
|
||||
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
@ -55,6 +58,22 @@
|
||||
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
|
||||
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" )
|
||||
|
||||
// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug
|
||||
// which results in calls to destructors being emitted for each temporary,
|
||||
// without a matching initialization. In practice, this can result in something
|
||||
// like `std::string::~string` being called on an uninitialized value.
|
||||
//
|
||||
// For example, this code will likely segfault under IBM XL:
|
||||
// ```
|
||||
// REQUIRE(std::string("12") + "34" == "1234")
|
||||
// ```
|
||||
//
|
||||
// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
|
||||
# if !defined(__ibmxl__)
|
||||
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg) */
|
||||
# endif
|
||||
|
||||
|
||||
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
_Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
|
||||
_Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
|
||||
@ -149,9 +168,12 @@
|
||||
// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
|
||||
// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
|
||||
// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
|
||||
# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
|
||||
# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||
# endif
|
||||
# if !defined(__clang__) // Handle Clang masquerading for msvc
|
||||
# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
|
||||
# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||
# endif // MSVC_TRADITIONAL
|
||||
# endif // __clang__
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#if defined(_REENTRANT) || defined(_MSC_VER)
|
||||
@ -200,7 +222,7 @@
|
||||
#define CATCH_CONFIG_COLOUR_NONE
|
||||
#endif
|
||||
|
||||
#if defined(__UCLIBC__)
|
||||
#if !defined(_GLIBCXX_USE_C99_MATH_TR1)
|
||||
#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
|
||||
#endif
|
||||
|
||||
@ -329,6 +351,11 @@
|
||||
# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
|
||||
#endif
|
||||
|
||||
// The goal of this macro is to avoid evaluation of the arguments, but
|
||||
// still have the compiler warn on problems inside...
|
||||
#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN)
|
||||
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...)
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
|
||||
# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
|
||||
|
@ -72,10 +72,11 @@ namespace Catch {
|
||||
bool Config::showInvisibles() const { return m_data.showInvisibles; }
|
||||
Verbosity Config::verbosity() const { return m_data.verbosity; }
|
||||
|
||||
bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; }
|
||||
int Config::benchmarkSamples() const { return m_data.benchmarkSamples; }
|
||||
double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; }
|
||||
unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; }
|
||||
bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; }
|
||||
int Config::benchmarkSamples() const { return m_data.benchmarkSamples; }
|
||||
double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; }
|
||||
unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; }
|
||||
std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); }
|
||||
|
||||
IStream const* Config::openStream() {
|
||||
return Catch::makeStream(m_data.outputFilename);
|
||||
|
@ -47,6 +47,7 @@ namespace Catch {
|
||||
unsigned int benchmarkSamples = 100;
|
||||
double benchmarkConfidenceInterval = 0.95;
|
||||
unsigned int benchmarkResamples = 100000;
|
||||
std::chrono::milliseconds::rep benchmarkWarmupTime = 100;
|
||||
|
||||
Verbosity verbosity = Verbosity::Normal;
|
||||
WarnAbout::What warnings = WarnAbout::Nothing;
|
||||
@ -113,6 +114,7 @@ namespace Catch {
|
||||
int benchmarkSamples() const override;
|
||||
double benchmarkConfidenceInterval() const override;
|
||||
unsigned int benchmarkResamples() const override;
|
||||
std::chrono::milliseconds benchmarkWarmupTime() const override;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -34,7 +34,7 @@ namespace Catch {
|
||||
};
|
||||
|
||||
struct NoColourImpl : IColourImpl {
|
||||
void use( Colour::Code ) {}
|
||||
void use( Colour::Code ) override {}
|
||||
|
||||
static IColourImpl* instance() {
|
||||
static NoColourImpl s_instance;
|
||||
@ -167,7 +167,7 @@ namespace {
|
||||
|
||||
bool useColourOnPlatform() {
|
||||
return
|
||||
#ifdef CATCH_PLATFORM_MAC
|
||||
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
|
||||
!isDebuggerActive() &&
|
||||
#endif
|
||||
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
|
||||
@ -208,13 +208,13 @@ namespace Catch {
|
||||
namespace Catch {
|
||||
|
||||
Colour::Colour( Code _colourCode ) { use( _colourCode ); }
|
||||
Colour::Colour( Colour&& rhs ) noexcept {
|
||||
m_moved = rhs.m_moved;
|
||||
rhs.m_moved = true;
|
||||
Colour::Colour( Colour&& other ) noexcept {
|
||||
m_moved = other.m_moved;
|
||||
other.m_moved = true;
|
||||
}
|
||||
Colour& Colour::operator=( Colour&& rhs ) noexcept {
|
||||
m_moved = rhs.m_moved;
|
||||
rhs.m_moved = true;
|
||||
Colour& Colour::operator=( Colour&& other ) noexcept {
|
||||
m_moved = other.m_moved;
|
||||
other.m_moved = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -226,7 +226,7 @@ namespace Catch {
|
||||
// However, under some conditions it does happen (see #1626),
|
||||
// and this change is small enough that we can let practicality
|
||||
// triumph over purity in this case.
|
||||
if (impl != NULL) {
|
||||
if (impl != nullptr) {
|
||||
impl->use( _colourCode );
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,9 @@
|
||||
#include "catch_stream.h"
|
||||
#include "catch_platform.h"
|
||||
|
||||
#ifdef CATCH_PLATFORM_MAC
|
||||
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
|
||||
|
||||
# include <assert.h>
|
||||
# include <stdbool.h>
|
||||
# include <cassert>
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
# include <cstddef>
|
||||
|
@ -19,6 +19,19 @@ namespace Catch {
|
||||
|
||||
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
|
||||
|
||||
#elif defined(CATCH_PLATFORM_IPHONE)
|
||||
|
||||
// use inline assembler
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#define CATCH_TRAP() __asm__("int $3")
|
||||
#elif defined(__aarch64__)
|
||||
#define CATCH_TRAP() __asm__(".inst 0xd4200000")
|
||||
#elif defined(__arm__) && !defined(__thumb__)
|
||||
#define CATCH_TRAP() __asm__(".inst 0xe7f001f0")
|
||||
#elif defined(__arm__) && defined(__thumb__)
|
||||
#define CATCH_TRAP() __asm__(".inst 0xde01")
|
||||
#endif
|
||||
|
||||
#elif defined(CATCH_PLATFORM_LINUX)
|
||||
// If we can use inline assembler, do it because this allows us to break
|
||||
// directly at the location of the failing check instead of breaking inside
|
||||
@ -37,10 +50,12 @@ namespace Catch {
|
||||
#define CATCH_TRAP() DebugBreak()
|
||||
#endif
|
||||
|
||||
#ifdef CATCH_TRAP
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
|
||||
#else
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() []{}()
|
||||
#ifndef CATCH_BREAK_INTO_DEBUGGER
|
||||
#ifdef CATCH_TRAP
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
|
||||
#else
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() []{}()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
||||
|
@ -200,6 +200,18 @@ namespace Catch {
|
||||
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
|
||||
}
|
||||
template <typename RhsT>
|
||||
auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs };
|
||||
}
|
||||
template <typename RhsT>
|
||||
auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs };
|
||||
}
|
||||
template <typename RhsT>
|
||||
auto operator ^ (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
return { static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs };
|
||||
}
|
||||
|
||||
template<typename RhsT>
|
||||
auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
|
@ -9,10 +9,11 @@
|
||||
#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
|
||||
|
||||
#include "catch_session.h"
|
||||
#include "catch_platform.h"
|
||||
|
||||
#ifndef __OBJC__
|
||||
|
||||
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
|
||||
#if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
|
||||
// Standard C/C++ Win32 Unicode wmain entry point
|
||||
extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
|
||||
#else
|
||||
|
@ -60,7 +60,7 @@ namespace Catch {
|
||||
assert( valueNames.size() == values.size() );
|
||||
std::size_t i = 0;
|
||||
for( auto value : values )
|
||||
enumInfo->m_values.push_back({ value, valueNames[i++] });
|
||||
enumInfo->m_values.emplace_back(value, valueNames[i++]);
|
||||
|
||||
return enumInfo;
|
||||
}
|
||||
|
@ -57,7 +57,6 @@ namespace Generators {
|
||||
class SingleValueGenerator final : public IGenerator<T> {
|
||||
T m_value;
|
||||
public:
|
||||
SingleValueGenerator(T const& value) : m_value( value ) {}
|
||||
SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
|
||||
|
||||
T const& get() const override {
|
||||
@ -120,21 +119,21 @@ namespace Generators {
|
||||
m_generators.emplace_back(std::move(generator));
|
||||
}
|
||||
void populate(T&& val) {
|
||||
m_generators.emplace_back(value(std::move(val)));
|
||||
m_generators.emplace_back(value(std::forward<T>(val)));
|
||||
}
|
||||
template<typename U>
|
||||
void populate(U&& val) {
|
||||
populate(T(std::move(val)));
|
||||
populate(T(std::forward<U>(val)));
|
||||
}
|
||||
template<typename U, typename... Gs>
|
||||
void populate(U&& valueOrGenerator, Gs... moreGenerators) {
|
||||
void populate(U&& valueOrGenerator, Gs &&... moreGenerators) {
|
||||
populate(std::forward<U>(valueOrGenerator));
|
||||
populate(std::forward<Gs>(moreGenerators)...);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename... Gs>
|
||||
Generators(Gs... moreGenerators) {
|
||||
Generators(Gs &&... moreGenerators) {
|
||||
m_generators.reserve(sizeof...(Gs));
|
||||
populate(std::forward<Gs>(moreGenerators)...);
|
||||
}
|
||||
@ -166,7 +165,7 @@ namespace Generators {
|
||||
struct as {};
|
||||
|
||||
template<typename T, typename... Gs>
|
||||
auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
|
||||
auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {
|
||||
return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
|
||||
}
|
||||
template<typename T>
|
||||
@ -174,11 +173,11 @@ namespace Generators {
|
||||
return Generators<T>(std::move(generator));
|
||||
}
|
||||
template<typename T, typename... Gs>
|
||||
auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
|
||||
auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> {
|
||||
return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
|
||||
}
|
||||
template<typename T, typename U, typename... Gs>
|
||||
auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> {
|
||||
auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {
|
||||
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
|
||||
}
|
||||
|
||||
@ -204,10 +203,10 @@ namespace Generators {
|
||||
} // namespace Catch
|
||||
|
||||
#define GENERATE( ... ) \
|
||||
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
|
||||
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
|
||||
#define GENERATE_COPY( ... ) \
|
||||
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
|
||||
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
|
||||
#define GENERATE_REF( ... ) \
|
||||
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
|
||||
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "catch_common.h"
|
||||
#include "catch_option.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -81,6 +82,7 @@ namespace Catch {
|
||||
virtual int benchmarkSamples() const = 0;
|
||||
virtual double benchmarkConfidenceInterval() const = 0;
|
||||
virtual unsigned int benchmarkResamples() const = 0;
|
||||
virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0;
|
||||
};
|
||||
|
||||
using IConfigPtr = std::shared_ptr<IConfig const>;
|
||||
|
@ -46,6 +46,9 @@ namespace Catch {
|
||||
{}
|
||||
|
||||
std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
|
||||
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||
return "";
|
||||
#else
|
||||
try {
|
||||
if( it == itEnd )
|
||||
std::rethrow_exception(std::current_exception());
|
||||
@ -55,6 +58,7 @@ namespace Catch {
|
||||
catch( T& ex ) {
|
||||
return m_translateFunction( ex );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -28,7 +28,7 @@
|
||||
namespace Catch {
|
||||
|
||||
std::size_t listTests( Config const& config ) {
|
||||
TestSpec testSpec = config.testSpec();
|
||||
TestSpec const& testSpec = config.testSpec();
|
||||
if( config.hasTestFilters() )
|
||||
Catch::cout() << "Matching test cases:\n";
|
||||
else {
|
||||
@ -62,7 +62,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
std::size_t listTestsNamesOnly( Config const& config ) {
|
||||
TestSpec testSpec = config.testSpec();
|
||||
TestSpec const& testSpec = config.testSpec();
|
||||
std::size_t matchedTests = 0;
|
||||
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
|
||||
for( auto const& testCaseInfo : matchedTestCases ) {
|
||||
@ -100,7 +100,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
std::size_t listTags( Config const& config ) {
|
||||
TestSpec testSpec = config.testSpec();
|
||||
TestSpec const& testSpec = config.testSpec();
|
||||
if( config.hasTestFilters() )
|
||||
Catch::cout() << "Tags for matching test cases:\n";
|
||||
else {
|
||||
|
@ -91,9 +91,10 @@ namespace Matchers {
|
||||
return description;
|
||||
}
|
||||
|
||||
MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
|
||||
m_matchers.push_back( &other );
|
||||
return *this;
|
||||
MatchAllOf<ArgT> operator && ( MatcherBase<ArgT> const& other ) {
|
||||
auto copy(*this);
|
||||
copy.m_matchers.push_back( &other );
|
||||
return copy;
|
||||
}
|
||||
|
||||
std::vector<MatcherBase<ArgT> const*> m_matchers;
|
||||
@ -124,9 +125,10 @@ namespace Matchers {
|
||||
return description;
|
||||
}
|
||||
|
||||
MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
|
||||
m_matchers.push_back( &other );
|
||||
return *this;
|
||||
MatchAnyOf<ArgT> operator || ( MatcherBase<ArgT> const& other ) {
|
||||
auto copy(*this);
|
||||
copy.m_matchers.push_back( &other );
|
||||
return copy;
|
||||
}
|
||||
|
||||
std::vector<MatcherBase<ArgT> const*> m_matchers;
|
||||
|
@ -59,16 +59,8 @@ namespace {
|
||||
return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;
|
||||
}
|
||||
|
||||
} //end anonymous namespace
|
||||
|
||||
#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
// The long double overload is currently unused
|
||||
#pragma clang diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
float nextafter(float x, float y) {
|
||||
return ::nextafterf(x, y);
|
||||
}
|
||||
@ -77,18 +69,8 @@ namespace {
|
||||
return ::nextafter(x, y);
|
||||
}
|
||||
|
||||
long double nextafter(long double x, long double y) {
|
||||
return ::nextafterl(x, y);
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename FP>
|
||||
FP step(FP start, FP direction, uint64_t steps) {
|
||||
for (uint64_t i = 0; i < steps; ++i) {
|
||||
|
@ -17,12 +17,12 @@ namespace Catch {
|
||||
namespace Matchers {
|
||||
|
||||
namespace Vector {
|
||||
template<typename T>
|
||||
struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
|
||||
template<typename T, typename Alloc>
|
||||
struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> {
|
||||
|
||||
ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
|
||||
|
||||
bool match(std::vector<T> const &v) const override {
|
||||
bool match(std::vector<T, Alloc> const &v) const override {
|
||||
for (auto const& el : v) {
|
||||
if (el == m_comparator) {
|
||||
return true;
|
||||
@ -38,12 +38,12 @@ namespace Matchers {
|
||||
T const& m_comparator;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ContainsMatcher : MatcherBase<std::vector<T>> {
|
||||
template<typename T, typename AllocComp, typename AllocMatch>
|
||||
struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
|
||||
|
||||
ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
|
||||
ContainsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
|
||||
|
||||
bool match(std::vector<T> const &v) const override {
|
||||
bool match(std::vector<T, AllocMatch> const &v) const override {
|
||||
// !TBD: see note in EqualsMatcher
|
||||
if (m_comparator.size() > v.size())
|
||||
return false;
|
||||
@ -65,18 +65,18 @@ namespace Matchers {
|
||||
return "Contains: " + ::Catch::Detail::stringify( m_comparator );
|
||||
}
|
||||
|
||||
std::vector<T> const& m_comparator;
|
||||
std::vector<T, AllocComp> const& m_comparator;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct EqualsMatcher : MatcherBase<std::vector<T>> {
|
||||
template<typename T, typename AllocComp, typename AllocMatch>
|
||||
struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
|
||||
|
||||
EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
|
||||
EqualsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
|
||||
|
||||
bool match(std::vector<T> const &v) const override {
|
||||
bool match(std::vector<T, AllocMatch> const &v) const override {
|
||||
// !TBD: This currently works if all elements can be compared using !=
|
||||
// - a more general approach would be via a compare template that defaults
|
||||
// to using !=. but could be specialised for, e.g. std::vector<T> etc
|
||||
// to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc
|
||||
// - then just call that directly
|
||||
if (m_comparator.size() != v.size())
|
||||
return false;
|
||||
@ -88,15 +88,15 @@ namespace Matchers {
|
||||
std::string describe() const override {
|
||||
return "Equals: " + ::Catch::Detail::stringify( m_comparator );
|
||||
}
|
||||
std::vector<T> const& m_comparator;
|
||||
std::vector<T, AllocComp> const& m_comparator;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ApproxMatcher : MatcherBase<std::vector<T>> {
|
||||
template<typename T, typename AllocComp, typename AllocMatch>
|
||||
struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> {
|
||||
|
||||
ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {}
|
||||
ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator( comparator ) {}
|
||||
|
||||
bool match(std::vector<T> const &v) const override {
|
||||
bool match(std::vector<T, AllocMatch> const &v) const override {
|
||||
if (m_comparator.size() != v.size())
|
||||
return false;
|
||||
for (std::size_t i = 0; i < v.size(); ++i)
|
||||
@ -123,14 +123,14 @@ namespace Matchers {
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<T> const& m_comparator;
|
||||
std::vector<T, AllocComp> const& m_comparator;
|
||||
mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
|
||||
UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
|
||||
bool match(std::vector<T> const& vec) const override {
|
||||
template<typename T, typename AllocComp, typename AllocMatch>
|
||||
struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
|
||||
UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {}
|
||||
bool match(std::vector<T, AllocMatch> const& vec) const override {
|
||||
// Note: This is a reimplementation of std::is_permutation,
|
||||
// because I don't want to include <algorithm> inside the common path
|
||||
if (m_target.size() != vec.size()) {
|
||||
@ -143,7 +143,7 @@ namespace Matchers {
|
||||
return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
|
||||
}
|
||||
private:
|
||||
std::vector<T> const& m_target;
|
||||
std::vector<T, AllocComp> const& m_target;
|
||||
};
|
||||
|
||||
} // namespace Vector
|
||||
@ -151,29 +151,29 @@ namespace Matchers {
|
||||
// The following functions create the actual matcher objects.
|
||||
// This allows the types to be inferred
|
||||
|
||||
template<typename T>
|
||||
Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
|
||||
return Vector::ContainsMatcher<T>( comparator );
|
||||
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
|
||||
Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {
|
||||
return Vector::ContainsMatcher<T, AllocComp, AllocMatch>( comparator );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
|
||||
return Vector::ContainsElementMatcher<T>( comparator );
|
||||
template<typename T, typename Alloc = std::allocator<T>>
|
||||
Vector::ContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) {
|
||||
return Vector::ContainsElementMatcher<T, Alloc>( comparator );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
|
||||
return Vector::EqualsMatcher<T>( comparator );
|
||||
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
|
||||
Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) {
|
||||
return Vector::EqualsMatcher<T, AllocComp, AllocMatch>( comparator );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) {
|
||||
return Vector::ApproxMatcher<T>( comparator );
|
||||
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
|
||||
Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) {
|
||||
return Vector::ApproxMatcher<T, AllocComp, AllocMatch>( comparator );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
|
||||
return Vector::UnorderedEqualsMatcher<T>(target);
|
||||
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
|
||||
Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) {
|
||||
return Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch>( target );
|
||||
}
|
||||
|
||||
} // namespace Matchers
|
||||
|
@ -111,7 +111,7 @@ namespace Catch {
|
||||
pos = skipq(pos, c);
|
||||
break;
|
||||
case ',':
|
||||
if (start != pos && openings.size() == 0) {
|
||||
if (start != pos && openings.empty()) {
|
||||
m_messages.emplace_back(macroName, lineInfo, resultType);
|
||||
m_messages.back().message = static_cast<std::string>(trimmed(start, pos));
|
||||
m_messages.back().message += " := ";
|
||||
@ -119,7 +119,7 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(openings.size() == 0 && "Mismatched openings");
|
||||
assert(openings.empty() && "Mismatched openings");
|
||||
m_messages.emplace_back(macroName, lineInfo, resultType);
|
||||
m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));
|
||||
m_messages.back().message += " := ";
|
||||
|
@ -69,7 +69,7 @@ namespace Catch {
|
||||
auto const& allTestCases = getAllTestCasesSorted(*m_config);
|
||||
m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
|
||||
auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
|
||||
|
||||
|
||||
if (m_matches.empty() && invalidArgs.empty()) {
|
||||
for (auto const& test : allTestCases)
|
||||
if (!test.isHidden())
|
||||
@ -97,12 +97,12 @@ namespace Catch {
|
||||
totals.error = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!invalidArgs.empty()) {
|
||||
for (auto const& invalidArg: invalidArgs)
|
||||
for (auto const& invalidArg: invalidArgs)
|
||||
m_context.reporter().reportInvalidArguments(invalidArg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_context.testGroupEnded(m_config->name(), totals, 1, 1);
|
||||
return totals;
|
||||
}
|
||||
@ -220,11 +220,11 @@ namespace Catch {
|
||||
char **utf8Argv = new char *[ argc ];
|
||||
|
||||
for ( int i = 0; i < argc; ++i ) {
|
||||
int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
|
||||
int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr );
|
||||
|
||||
utf8Argv[ i ] = new char[ bufSize ];
|
||||
|
||||
WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
|
||||
WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr );
|
||||
}
|
||||
|
||||
int returnCode = applyCommandLine( argc, utf8Argv );
|
||||
|
@ -9,6 +9,8 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||
|
||||
#include "catch_common.h"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <cstddef>
|
||||
#include <ostream>
|
||||
@ -28,7 +30,7 @@ namespace Catch {
|
||||
|
||||
auto makeStream( StringRef const &filename ) -> IStream const*;
|
||||
|
||||
class ReusableStringStream {
|
||||
class ReusableStringStream : NonCopyable {
|
||||
std::size_t m_index;
|
||||
std::ostream* m_oss;
|
||||
public:
|
||||
|
@ -89,7 +89,8 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
if( isHidden ) {
|
||||
tags.push_back( "." );
|
||||
// Add all "hidden" tags to make them behave identically
|
||||
tags.insert( tags.end(), { ".", "!hide" } );
|
||||
}
|
||||
|
||||
TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo );
|
||||
|
@ -15,27 +15,78 @@
|
||||
#include "catch_string_manip.h"
|
||||
#include "catch_test_case_info.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace {
|
||||
struct TestHasher {
|
||||
explicit TestHasher(Catch::SimplePcg32& rng) {
|
||||
basis = rng();
|
||||
basis <<= 32;
|
||||
basis |= rng();
|
||||
}
|
||||
|
||||
uint64_t basis;
|
||||
|
||||
uint64_t operator()(TestCase const& t) const {
|
||||
// Modified FNV-1a hash
|
||||
static constexpr uint64_t prime = 1099511628211;
|
||||
uint64_t hash = basis;
|
||||
for (const char c : t.name) {
|
||||
hash ^= c;
|
||||
hash *= prime;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
} // end unnamed namespace
|
||||
|
||||
|
||||
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
|
||||
|
||||
std::vector<TestCase> sorted = unsortedTestCases;
|
||||
|
||||
switch( config.runOrder() ) {
|
||||
case RunTests::InLexicographicalOrder:
|
||||
std::sort( sorted.begin(), sorted.end() );
|
||||
break;
|
||||
case RunTests::InRandomOrder:
|
||||
seedRng( config );
|
||||
std::shuffle( sorted.begin(), sorted.end(), rng() );
|
||||
break;
|
||||
case RunTests::InDeclarationOrder:
|
||||
// already in declaration order
|
||||
break;
|
||||
|
||||
case RunTests::InLexicographicalOrder: {
|
||||
std::vector<TestCase> sorted = unsortedTestCases;
|
||||
std::sort( sorted.begin(), sorted.end() );
|
||||
return sorted;
|
||||
}
|
||||
|
||||
case RunTests::InRandomOrder: {
|
||||
seedRng( config );
|
||||
TestHasher h( rng() );
|
||||
|
||||
using hashedTest = std::pair<uint64_t, TestCase const*>;
|
||||
std::vector<hashedTest> indexed_tests;
|
||||
indexed_tests.reserve( unsortedTestCases.size() );
|
||||
|
||||
for (auto const& testCase : unsortedTestCases) {
|
||||
indexed_tests.emplace_back(h(testCase), &testCase);
|
||||
}
|
||||
|
||||
std::sort(indexed_tests.begin(), indexed_tests.end(),
|
||||
[](hashedTest const& lhs, hashedTest const& rhs) {
|
||||
if (lhs.first == rhs.first) {
|
||||
return lhs.second->name < rhs.second->name;
|
||||
}
|
||||
return lhs.first < rhs.first;
|
||||
});
|
||||
|
||||
std::vector<TestCase> sorted;
|
||||
sorted.reserve( indexed_tests.size() );
|
||||
|
||||
for (auto const& hashed : indexed_tests) {
|
||||
sorted.emplace_back(*hashed.second);
|
||||
}
|
||||
|
||||
return sorted;
|
||||
}
|
||||
}
|
||||
return sorted;
|
||||
return unsortedTestCases;
|
||||
}
|
||||
|
||||
bool isThrowSafe( TestCase const& testCase, IConfig const& config ) {
|
||||
|
@ -225,8 +225,8 @@ namespace TestCaseTracking {
|
||||
void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
|
||||
if( !filters.empty() ) {
|
||||
m_filters.reserve( m_filters.size() + filters.size() + 2 );
|
||||
m_filters.push_back(""); // Root - should never be consulted
|
||||
m_filters.push_back(""); // Test Case - not a section filter
|
||||
m_filters.emplace_back(""); // Root - should never be consulted
|
||||
m_filters.emplace_back(""); // Test Case - not a section filter
|
||||
m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
|
||||
}
|
||||
}
|
||||
|
@ -20,10 +20,10 @@ namespace Catch {
|
||||
m_substring.reserve(m_arg.size());
|
||||
m_patternName.reserve(m_arg.size());
|
||||
m_realPatternPos = 0;
|
||||
|
||||
|
||||
for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
|
||||
//if visitChar fails
|
||||
if( !visitChar( m_arg[m_pos] ) ){
|
||||
if( !visitChar( m_arg[m_pos] ) ){
|
||||
m_testSpec.m_invalidArgs.push_back(arg);
|
||||
break;
|
||||
}
|
||||
@ -113,9 +113,9 @@ namespace Catch {
|
||||
switch( m_mode ) {
|
||||
case Name:
|
||||
case QuotedName:
|
||||
return addPattern<TestSpec::NamePattern>();
|
||||
return addNamePattern();
|
||||
case Tag:
|
||||
return addPattern<TestSpec::TagPattern>();
|
||||
return addTagPattern();
|
||||
case EscapedName:
|
||||
revertBackToLastMode();
|
||||
return;
|
||||
@ -156,25 +156,83 @@ namespace Catch {
|
||||
void TestSpecParser::saveLastMode() {
|
||||
lastMode = m_mode;
|
||||
}
|
||||
|
||||
|
||||
void TestSpecParser::revertBackToLastMode() {
|
||||
m_mode = lastMode;
|
||||
}
|
||||
|
||||
bool TestSpecParser::separate() {
|
||||
|
||||
bool TestSpecParser::separate() {
|
||||
if( (m_mode==QuotedName) || (m_mode==Tag) ){
|
||||
//invalid argument, signal failure to previous scope.
|
||||
m_mode = None;
|
||||
m_pos = m_arg.size();
|
||||
m_substring.clear();
|
||||
m_patternName.clear();
|
||||
m_realPatternPos = 0;
|
||||
return false;
|
||||
}
|
||||
endMode();
|
||||
addFilter();
|
||||
return true; //success
|
||||
}
|
||||
|
||||
|
||||
std::string TestSpecParser::preprocessPattern() {
|
||||
std::string token = m_patternName;
|
||||
for (std::size_t i = 0; i < m_escapeChars.size(); ++i)
|
||||
token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1);
|
||||
m_escapeChars.clear();
|
||||
if (startsWith(token, "exclude:")) {
|
||||
m_exclusion = true;
|
||||
token = token.substr(8);
|
||||
}
|
||||
|
||||
m_patternName.clear();
|
||||
m_realPatternPos = 0;
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
void TestSpecParser::addNamePattern() {
|
||||
auto token = preprocessPattern();
|
||||
|
||||
if (!token.empty()) {
|
||||
TestSpec::PatternPtr pattern = std::make_shared<TestSpec::NamePattern>(token, m_substring);
|
||||
if (m_exclusion)
|
||||
pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
|
||||
m_currentFilter.m_patterns.push_back(pattern);
|
||||
}
|
||||
m_substring.clear();
|
||||
m_exclusion = false;
|
||||
m_mode = None;
|
||||
}
|
||||
|
||||
void TestSpecParser::addTagPattern() {
|
||||
auto token = preprocessPattern();
|
||||
|
||||
if (!token.empty()) {
|
||||
// If the tag pattern is the "hide and tag" shorthand (e.g. [.foo])
|
||||
// we have to create a separate hide tag and shorten the real one
|
||||
if (token.size() > 1 && token[0] == '.') {
|
||||
token.erase(token.begin());
|
||||
TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(".", m_substring);
|
||||
if (m_exclusion) {
|
||||
pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
|
||||
}
|
||||
m_currentFilter.m_patterns.push_back(pattern);
|
||||
}
|
||||
|
||||
TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(token, m_substring);
|
||||
|
||||
if (m_exclusion) {
|
||||
pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
|
||||
}
|
||||
m_currentFilter.m_patterns.push_back(pattern);
|
||||
}
|
||||
m_substring.clear();
|
||||
m_exclusion = false;
|
||||
m_mode = None;
|
||||
}
|
||||
|
||||
TestSpec parseTestSpec( std::string const& arg ) {
|
||||
return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
|
||||
}
|
||||
|
@ -53,35 +53,20 @@ namespace Catch {
|
||||
void revertBackToLastMode();
|
||||
void addFilter();
|
||||
bool separate();
|
||||
|
||||
template<typename T>
|
||||
void addPattern() {
|
||||
std::string token = m_patternName;
|
||||
for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
|
||||
token = token.substr( 0, m_escapeChars[i] - i ) + token.substr( m_escapeChars[i] -i +1 );
|
||||
m_escapeChars.clear();
|
||||
if( startsWith( token, "exclude:" ) ) {
|
||||
m_exclusion = true;
|
||||
token = token.substr( 8 );
|
||||
}
|
||||
if( !token.empty() ) {
|
||||
TestSpec::PatternPtr pattern = std::make_shared<T>( token, m_substring );
|
||||
if( m_exclusion )
|
||||
pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
|
||||
m_currentFilter.m_patterns.push_back( pattern );
|
||||
}
|
||||
m_substring.clear();
|
||||
m_patternName.clear();
|
||||
m_exclusion = false;
|
||||
m_mode = None;
|
||||
}
|
||||
|
||||
|
||||
// Handles common preprocessing of the pattern for name/tag patterns
|
||||
std::string preprocessPattern();
|
||||
// Adds the current pattern as a test name
|
||||
void addNamePattern();
|
||||
// Adds the current pattern as a tag
|
||||
void addTagPattern();
|
||||
|
||||
inline void addCharToPattern(char c) {
|
||||
m_substring += c;
|
||||
m_patternName += c;
|
||||
m_realPatternPos++;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
TestSpec parseTestSpec( std::string const& arg );
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Version const& libraryVersion() {
|
||||
static Version version( 2, 10, 2, "", 0 );
|
||||
static Version version( 2, 12, 1, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,6 @@
|
||||
#include <iomanip>
|
||||
#include <type_traits>
|
||||
|
||||
using uchar = unsigned char;
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace {
|
||||
@ -87,7 +85,7 @@ namespace {
|
||||
// (see: http://www.w3.org/TR/xml/#syntax)
|
||||
|
||||
for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
|
||||
uchar c = m_str[idx];
|
||||
unsigned char c = m_str[idx];
|
||||
switch (c) {
|
||||
case '<': os << "<"; break;
|
||||
case '&': os << "&"; break;
|
||||
@ -147,7 +145,7 @@ namespace {
|
||||
bool valid = true;
|
||||
uint32_t value = headerValue(c);
|
||||
for (std::size_t n = 1; n < encBytes; ++n) {
|
||||
uchar nc = m_str[idx + n];
|
||||
unsigned char nc = m_str[idx + n];
|
||||
valid &= ((nc & 0xC0) == 0x80);
|
||||
value = (value << 6) | (nc & 0x3F);
|
||||
}
|
||||
|
@ -210,15 +210,11 @@ class Duration {
|
||||
static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
|
||||
static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
|
||||
|
||||
uint64_t m_inNanoseconds;
|
||||
double m_inNanoseconds;
|
||||
Unit m_units;
|
||||
|
||||
public:
|
||||
explicit Duration(double inNanoseconds, Unit units = Unit::Auto)
|
||||
: Duration(static_cast<uint64_t>(inNanoseconds), units) {
|
||||
}
|
||||
|
||||
explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
|
||||
explicit Duration(double inNanoseconds, Unit units = Unit::Auto)
|
||||
: m_inNanoseconds(inNanoseconds),
|
||||
m_units(units) {
|
||||
if (m_units == Unit::Auto) {
|
||||
@ -247,7 +243,7 @@ public:
|
||||
case Unit::Minutes:
|
||||
return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);
|
||||
default:
|
||||
return static_cast<double>(m_inNanoseconds);
|
||||
return m_inNanoseconds;
|
||||
}
|
||||
}
|
||||
auto unitsAsString() const -> std::string {
|
||||
@ -366,7 +362,7 @@ ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
|
||||
else
|
||||
{
|
||||
return{
|
||||
{ "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
|
||||
{ "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left },
|
||||
{ "samples mean std dev", 14, ColumnInfo::Right },
|
||||
{ "iterations low mean low std dev", 14, ColumnInfo::Right },
|
||||
{ "estimated high mean high std dev", 14, ColumnInfo::Right }
|
||||
@ -684,8 +680,10 @@ void ConsoleReporter::printSummaryDivider() {
|
||||
}
|
||||
|
||||
void ConsoleReporter::printTestFilters() {
|
||||
if (m_config->testSpec().hasFilters())
|
||||
stream << Colour(Colour::BrightYellow) << "Filters: " << serializeFilters( m_config->getTestsOrTags() ) << '\n';
|
||||
if (m_config->testSpec().hasFilters()) {
|
||||
Colour guard(Colour::BrightYellow);
|
||||
stream << "Filters: " << serializeFilters(m_config->getTestsOrTags()) << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
CATCH_REGISTER_REPORTER("console", ConsoleReporter)
|
||||
@ -698,4 +696,4 @@ CATCH_REGISTER_REPORTER("console", ConsoleReporter)
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
@ -223,11 +223,7 @@ namespace Catch {
|
||||
elementName = "error";
|
||||
break;
|
||||
case ResultWas::ExplicitFailure:
|
||||
elementName = "failure";
|
||||
break;
|
||||
case ResultWas::ExpressionFailed:
|
||||
elementName = "failure";
|
||||
break;
|
||||
case ResultWas::DidntThrowException:
|
||||
elementName = "failure";
|
||||
break;
|
||||
|
@ -229,16 +229,16 @@ namespace Catch {
|
||||
m_xml.writeAttribute("samples", info.samples)
|
||||
.writeAttribute("resamples", info.resamples)
|
||||
.writeAttribute("iterations", info.iterations)
|
||||
.writeAttribute("clockResolution", static_cast<uint64_t>(info.clockResolution))
|
||||
.writeAttribute("estimatedDuration", static_cast<uint64_t>(info.estimatedDuration))
|
||||
.writeAttribute("clockResolution", info.clockResolution)
|
||||
.writeAttribute("estimatedDuration", info.estimatedDuration)
|
||||
.writeComment("All values in nano seconds");
|
||||
}
|
||||
|
||||
void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
|
||||
m_xml.startElement("mean")
|
||||
.writeAttribute("value", static_cast<uint64_t>(benchmarkStats.mean.point.count()))
|
||||
.writeAttribute("lowerBound", static_cast<uint64_t>(benchmarkStats.mean.lower_bound.count()))
|
||||
.writeAttribute("upperBound", static_cast<uint64_t>(benchmarkStats.mean.upper_bound.count()))
|
||||
.writeAttribute("value", benchmarkStats.mean.point.count())
|
||||
.writeAttribute("lowerBound", benchmarkStats.mean.lower_bound.count())
|
||||
.writeAttribute("upperBound", benchmarkStats.mean.upper_bound.count())
|
||||
.writeAttribute("ci", benchmarkStats.mean.confidence_interval);
|
||||
m_xml.endElement();
|
||||
m_xml.startElement("standardDeviation")
|
||||
|
@ -451,6 +451,8 @@ set_tests_properties(TestsInFile::InvalidTestNames-1 PROPERTIES PASS_REGULAR_EXP
|
||||
add_test(NAME TestsInFile::InvalidTestNames-2 COMMAND $<TARGET_FILE:SelfTest> "-f ${CATCH_DIR}/projects/SelfTest/Misc/invalid-test-names.input")
|
||||
set_tests_properties(TestsInFile::InvalidTestNames-2 PROPERTIES PASS_REGULAR_EXPRESSION "No tests ran")
|
||||
|
||||
add_test(NAME RandomTestOrdering COMMAND ${PYTHON_EXECUTABLE}
|
||||
${CATCH_DIR}/projects/TestScripts/testRandomOrder.py $<TARGET_FILE:SelfTest>)
|
||||
|
||||
if (CATCH_USE_VALGRIND)
|
||||
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
|
||||
|
@ -123,7 +123,7 @@ add_test(NAME BenchmarkingMacros COMMAND BenchmarkingMacros -r console -s)
|
||||
set_tests_properties(
|
||||
BenchmarkingMacros
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "benchmark name samples iterations estimated"
|
||||
PASS_REGULAR_EXPRESSION "benchmark name[\\r\\n\\t ]+samples[\\r\\n\\t ]+iterations[\\r\\n\\t ]+estimated"
|
||||
)
|
||||
|
||||
# This test touches windows.h, so it should only be compiled under msvc
|
||||
@ -137,6 +137,14 @@ if (MSVC)
|
||||
add_test(NAME WindowsHeader COMMAND WindowsHeader -r compact)
|
||||
endif()
|
||||
|
||||
add_executable(DebugBreakMacros ${TESTS_DIR}/X12-CustomDebugBreakMacro.cpp)
|
||||
add_test(NAME DebugBreakMacros COMMAND DebugBreakMacros --break)
|
||||
set_tests_properties(
|
||||
DebugBreakMacros
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "Pretty please, break into debugger"
|
||||
)
|
||||
|
||||
set( EXTRA_TEST_BINARIES
|
||||
PrefixedMacros
|
||||
DisabledMacros
|
||||
@ -145,6 +153,7 @@ set( EXTRA_TEST_BINARIES
|
||||
FallbackStringifier
|
||||
DisableStringification
|
||||
BenchmarkingMacros
|
||||
DebugBreakMacros
|
||||
)
|
||||
|
||||
# Shared config
|
||||
|
17
projects/ExtraTests/X12-CustomDebugBreakMacro.cpp
Normal file
17
projects/ExtraTests/X12-CustomDebugBreakMacro.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
// X12-CustomDebugBreakMacro.cpp
|
||||
// Test that user-defined `CATCH_BREAK_INTO_DEBUGGER` is respected and used.
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void custom_debug_break() {
|
||||
std::cerr << "Pretty please, break into debugger\n";
|
||||
}
|
||||
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() custom_debug_break()
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
TEST_CASE("Failing test that breaks into debugger", "[macros]") {
|
||||
REQUIRE(1 == 2);
|
||||
}
|
@ -26,14 +26,6 @@ TEST_CASE("Benchmark factorial", "[benchmark]") {
|
||||
BENCHMARK("factorial 14") {
|
||||
return factorial(14);
|
||||
};
|
||||
//
|
||||
// BENCHMARK("factorial 20") {
|
||||
// return factorial(20);
|
||||
// };
|
||||
//
|
||||
// BENCHMARK("factorial 35") {
|
||||
// return factorial(35);
|
||||
// };
|
||||
}
|
||||
|
||||
TEST_CASE("Benchmark containers", "[.][benchmark]") {
|
||||
|
@ -23,6 +23,13 @@ This would not be caught previously
|
||||
Nor would this
|
||||
Tricky.tests.cpp:<line number>: failed: explicitly with 1 message: '1514'
|
||||
Compilation.tests.cpp:<line number>: passed: std::is_same<TypeList<int>, TypeList<int>>::value for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase("spec . char")) for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase("spec , char")) for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase(R"(spec \, char)"))) for: !false
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase(R"(spec {a} char)")) for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase(R"(spec [a] char)")) for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase("differs but has similar tag", "[a]"))) for: !false
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase(R"(spec \ char)")) for: true
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception'
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42'
|
||||
@ -237,6 +244,11 @@ Matchers.tests.cpp:<line number>: passed: 1, Predicate<int>(alwaysTrue, "always
|
||||
Matchers.tests.cpp:<line number>: passed: 1, !Predicate<int>(alwaysFalse, "always false") for: 1 not matches predicate: "always false"
|
||||
Matchers.tests.cpp:<line number>: passed: "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal"
|
||||
Matchers.tests.cpp:<line number>: passed: "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate
|
||||
Compilation.tests.cpp:<line number>: passed: lhs | rhs for: Val: 1 | Val: 2
|
||||
Compilation.tests.cpp:<line number>: passed: !(lhs & rhs) for: !(Val: 1 & Val: 2)
|
||||
Compilation.tests.cpp:<line number>: passed: HasBitOperators{ 1 } & HasBitOperators{ 1 } for: Val: 1 & Val: 1
|
||||
Compilation.tests.cpp:<line number>: passed: lhs ^ rhs for: Val: 1 ^ Val: 2
|
||||
Compilation.tests.cpp:<line number>: passed: !(lhs ^ lhs) for: !(Val: 1 ^ Val: 1)
|
||||
Tricky.tests.cpp:<line number>: passed: true
|
||||
Tricky.tests.cpp:<line number>: passed: true
|
||||
Tricky.tests.cpp:<line number>: passed: true
|
||||
@ -312,6 +324,8 @@ Condition.tests.cpp:<line number>: passed: 4 == ul for: 4 == 4
|
||||
Condition.tests.cpp:<line number>: passed: 5 == c for: 5 == 5
|
||||
Condition.tests.cpp:<line number>: passed: 6 == uc for: 6 == 6
|
||||
Condition.tests.cpp:<line number>: passed: (std::numeric_limits<uint32_t>::max)() > ul for: 4294967295 (0x<hex digits>) > 4
|
||||
Matchers.tests.cpp:<line number>: passed: testStringForMatching2(), !composed1 for: "some completely different text that contains one common word" not ( contains: "string" or contains: "random" )
|
||||
Matchers.tests.cpp:<line number>: passed: testStringForMatching2(), composed2 for: "some completely different text that contains one common word" ( contains: "string" or contains: "random" or contains: "different" )
|
||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" contains: "not there" (case insensitive)
|
||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("STRING") for: "this string contains 'abc' as a substring" contains: "STRING"
|
||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||
@ -762,6 +776,7 @@ Condition.tests.cpp:<line number>: passed: data.str_hello != "goodbye" for: "hel
|
||||
Condition.tests.cpp:<line number>: passed: data.str_hello != "hell" for: "hello" != "hell"
|
||||
Condition.tests.cpp:<line number>: passed: data.str_hello != "hello1" for: "hello" != "hello1"
|
||||
Condition.tests.cpp:<line number>: passed: data.str_hello.size() != 6 for: 5 != 6
|
||||
Compilation.tests.cpp:<line number>: passed: []() { return true; }() for: true
|
||||
Approx.tests.cpp:<line number>: passed: d <= Approx( 1.24 ) for: 1.23 <= Approx( 1.24 )
|
||||
Approx.tests.cpp:<line number>: passed: d <= Approx( 1.23 ) for: 1.23 <= Approx( 1.23 )
|
||||
Approx.tests.cpp:<line number>: passed: !(d <= Approx( 1.22 )) for: !(1.23 <= Approx( 1.22 ))
|
||||
@ -1027,6 +1042,12 @@ CmdLine.tests.cpp:<line number>: passed: spec.matches( fakeTestCase( " aardvark
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches( fakeTestCase( " aardvark " ) ) for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches( fakeTestCase( "aardvark " ) ) for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches( fakeTestCase( "aardvark" ) ) for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase("hidden and foo", "[.][foo]")) for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase("only foo", "[foo]"))) for: !false
|
||||
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase("hidden and foo", "[.][foo]"))) for: !false
|
||||
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase("only foo", "[foo]"))) for: !false
|
||||
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase("only hidden", "[.]"))) for: !false
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase("neither foo nor hidden", "[bar]")) for: true
|
||||
Condition.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
|
||||
Condition.tests.cpp:<line number>: passed: p == pNULL for: 0 == 0
|
||||
Condition.tests.cpp:<line number>: passed: p != 0 for: 0x<hex digits> != 0
|
||||
@ -1080,6 +1101,16 @@ CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-x", "2"}) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.abortAfter == 2 for: 2 == 2
|
||||
CmdLine.tests.cpp:<line number>: passed: !result for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: result.errorMessage(), Contains("convert") && Contains("oops") for: "Unable to convert 'oops' to destination type" ( contains: "convert" and contains: "oops" )
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.waitForKeypress == std::get<1>(input) for: 0 == 0
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.waitForKeypress == std::get<1>(input) for: 1 == 1
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.waitForKeypress == std::get<1>(input) for: 2 == 2
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.waitForKeypress == std::get<1>(input) for: 3 == 3
|
||||
CmdLine.tests.cpp:<line number>: passed: !result for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: result.errorMessage(), Contains("never") && Contains("both") for: "keypress argument must be one of: never, start, exit or both. 'sometimes' not recognised" ( contains: "never" and contains: "both" )
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-e"}) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.noThrow for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--nothrow"}) for: {?}
|
||||
@ -1110,6 +1141,8 @@ CmdLine.tests.cpp:<line number>: passed: cli.parse({ "test", "--benchmark-confid
|
||||
CmdLine.tests.cpp:<line number>: passed: config.benchmarkConfidenceInterval == Catch::Detail::Approx(0.99) for: 0.99 == Approx( 0.99 )
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({ "test", "--benchmark-no-analysis" }) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.benchmarkNoAnalysis for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({ "test", "--benchmark-warmup-time=10" }) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.benchmarkWarmupTime == 10 for: 10 == 10
|
||||
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 3 >= 1
|
||||
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 2 >= 1
|
||||
Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 1 >= 1
|
||||
@ -1186,7 +1219,7 @@ String.tests.cpp:<line number>: passed: s.data() == s2.data() for: "hello world!
|
||||
String.tests.cpp:<line number>: passed: s.data() == ss.data() for: "hello world!" == "hello world!"
|
||||
String.tests.cpp:<line number>: passed: s.substr(s.size() + 1, 123).empty() for: true
|
||||
String.tests.cpp:<line number>: passed: std::strcmp(ss.c_str(), "world!") == 0 for: 0 == 0
|
||||
String.tests.cpp:<line number>: passed: buffer1 != buffer2 for: "Hello" != "Hello"
|
||||
String.tests.cpp:<line number>: passed: (char*)buffer1 != (char*)buffer2 for: "Hello" != "Hello"
|
||||
String.tests.cpp:<line number>: passed: left == right for: Hello == Hello
|
||||
String.tests.cpp:<line number>: passed: left != left.substr(0, 3) for: Hello != Hel
|
||||
String.tests.cpp:<line number>: passed: sr == "a standard string" for: a standard string == "a standard string"
|
||||
@ -1498,6 +1531,7 @@ Approx.tests.cpp:<line number>: passed: approx( d ) != 1.25 for: Approx( 1.23 )
|
||||
VariadicMacros.tests.cpp:<line number>: passed: with 1 message: 'no assertions'
|
||||
Matchers.tests.cpp:<line number>: passed: empty, Approx(empty) for: { } is approx: { }
|
||||
Matchers.tests.cpp:<line number>: passed: v1, Approx(v1) for: { 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
|
||||
Matchers.tests.cpp:<line number>: passed: v1, Approx<double>({ 1., 2., 3. }) for: { 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
|
||||
Matchers.tests.cpp:<line number>: passed: v1, !Approx(temp) for: { 1.0, 2.0, 3.0 } not is approx: { 1.0, 2.0, 3.0, 4.0 }
|
||||
Matchers.tests.cpp:<line number>: passed: v1, !Approx(v2) for: { 1.0, 2.0, 3.0 } not is approx: { 1.5, 2.5, 3.5 }
|
||||
Matchers.tests.cpp:<line number>: passed: v1, Approx(v2).margin(0.5) for: { 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
|
||||
@ -1507,18 +1541,29 @@ Matchers.tests.cpp:<line number>: failed: empty, Approx(t1) for: { } is approx:
|
||||
Matchers.tests.cpp:<line number>: failed: v1, Approx(v2) for: { 2.0, 4.0, 6.0 } is approx: { 1.0, 3.0, 5.0 }
|
||||
Matchers.tests.cpp:<line number>: passed: v, VectorContains(1) for: { 1, 2, 3 } Contains: 1
|
||||
Matchers.tests.cpp:<line number>: passed: v, VectorContains(2) for: { 1, 2, 3 } Contains: 2
|
||||
Matchers.tests.cpp:<line number>: passed: v5, (VectorContains<int, CustomAllocator<int>>(2)) for: { 1, 2, 3 } Contains: 2
|
||||
Matchers.tests.cpp:<line number>: passed: v, Contains(v2) for: { 1, 2, 3 } Contains: { 1, 2 }
|
||||
Matchers.tests.cpp:<line number>: passed: v, Contains<int>({ 1, 2 }) for: { 1, 2, 3 } Contains: { 1, 2 }
|
||||
Matchers.tests.cpp:<line number>: passed: v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)) for: { 1, 2, 3 } Contains: { 1, 2 }
|
||||
Matchers.tests.cpp:<line number>: passed: v, Contains(v2) for: { 1, 2, 3 } Contains: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: v, Contains(empty) for: { 1, 2, 3 } Contains: { }
|
||||
Matchers.tests.cpp:<line number>: passed: empty, Contains(empty) for: { } Contains: { }
|
||||
Matchers.tests.cpp:<line number>: passed: v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)) for: { 1, 2, 3 } Contains: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: v5, Contains(v6) for: { 1, 2, 3 } Contains: { 1, 2 }
|
||||
Matchers.tests.cpp:<line number>: passed: v, VectorContains(1) && VectorContains(2) for: { 1, 2, 3 } ( Contains: 1 and Contains: 2 )
|
||||
Matchers.tests.cpp:<line number>: passed: v, Equals(v) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: empty, Equals(empty) for: { } Equals: { }
|
||||
Matchers.tests.cpp:<line number>: passed: v, Equals<int>({ 1, 2, 3 }) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: v, Equals(v2) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: v5, (Equals<int, std::allocator<int>, CustomAllocator<int>>(v2)) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: v5, Equals(v6) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: v, UnorderedEquals(v) for: { 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: v, UnorderedEquals<int>({ 3, 2, 1 }) for: { 1, 2, 3 } UnorderedEquals: { 3, 2, 1 }
|
||||
Matchers.tests.cpp:<line number>: passed: empty, UnorderedEquals(empty) for: { } UnorderedEquals: { }
|
||||
Matchers.tests.cpp:<line number>: passed: permuted, UnorderedEquals(v) for: { 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: permuted, UnorderedEquals(v) for: { 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: v5, (UnorderedEquals<int, std::allocator<int>, CustomAllocator<int>>(permuted)) for: { 1, 2, 3 } UnorderedEquals: { 2, 3, 1 }
|
||||
Matchers.tests.cpp:<line number>: passed: v5_permuted, UnorderedEquals(v5) for: { 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: failed: v, VectorContains(-1) for: { 1, 2, 3 } Contains: -1
|
||||
Matchers.tests.cpp:<line number>: failed: empty, VectorContains(1) for: { } Contains: 1
|
||||
Matchers.tests.cpp:<line number>: failed: empty, Contains(v) for: { } Contains: { 1, 2, 3 }
|
||||
@ -1561,48 +1606,9 @@ Xml.tests.cpp:<line number>: passed: encode( stringWithQuotes, Catch::XmlEncode:
|
||||
"don't "quote" me on that"
|
||||
Xml.tests.cpp:<line number>: passed: encode( "[\x01]" ) == "[\\x01]" for: "[\x01]" == "[\x01]"
|
||||
Xml.tests.cpp:<line number>: passed: encode( "[\x7F]" ) == "[\\x7F]" for: "[\x7F]" == "[\x7F]"
|
||||
Xml.tests.cpp:<line number>: passed: encode(u8"Here be 👾") == u8"Here be 👾" for: "Here be 👾" == "Here be 👾"
|
||||
Xml.tests.cpp:<line number>: passed: encode(u8"šš") == u8"šš" for: "šš" == "šš"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xDF\xBF") == "\xDF\xBF" for: "߿" == "߿"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xE0\xA0\x80") == "\xE0\xA0\x80" for: "ࠀ" == "ࠀ"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xED\x9F\xBF") == "\xED\x9F\xBF" for: "" == ""
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xEE\x80\x80") == "\xEE\x80\x80" for: "" == ""
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xEF\xBF\xBF") == "\xEF\xBF\xBF" for: "" == ""
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80" for: "𐀀" == "𐀀"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF" for: "" == ""
|
||||
Xml.tests.cpp:<line number>: passed: encode("Here \xFF be 👾") == u8"Here \\xFF be 👾" for: "Here \xFF be 👾" == "Here \xFF be 👾"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xFF") == "\\xFF" for: "\xFF" == "\xFF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xC5\xC5\xA0") == u8"\\xC5Š" for: "\xC5Š" == "\xC5Š"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80" for: "\xF4\x90\x80\x80" == "\xF4\x90\x80\x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xC0\x80") == u8"\\xC0\\x80" for: "\xC0\x80" == "\xC0\x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80" for: "\xF0\x80\x80\x80" == "\xF0\x80\x80\x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xC1\xBF") == u8"\\xC1\\xBF" for: "\xC1\xBF" == "\xC1\xBF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF" for: "\xE0\x9F\xBF" == "\xE0\x9F\xBF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF" for: "\xF0\x8F\xBF\xBF" == "\xF0\x8F\xBF\xBF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xED\xA0\x80") == "\xED\xA0\x80" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xED\xAF\xBF") == "\xED\xAF\xBF" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xED\xB0\x80") == "\xED\xB0\x80" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xED\xBF\xBF") == "\xED\xBF\xBF" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\x80") == u8"\\x80" for: "\x80" == "\x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\x81") == u8"\\x81" for: "\x81" == "\x81"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xBC") == u8"\\xBC" for: "\xBC" == "\xBC"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xBF") == u8"\\xBF" for: "\xBF" == "\xBF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80" for: "\xF5\x80\x80\x80" == "\xF5\x80\x80\x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80" for: "\xF6\x80\x80\x80" == "\xF6\x80\x80\x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80" for: "\xF7\x80\x80\x80" == "\xF7\x80\x80\x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xDE") == u8"\\xDE" for: "\xDE" == "\xDE"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xDF") == u8"\\xDF" for: "\xDF" == "\xDF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xE0") == u8"\\xE0" for: "\xE0" == "\xE0"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xEF") == u8"\\xEF" for: "\xEF" == "\xEF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF0") == u8"\\xF0" for: "\xF0" == "\xF0"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF4") == u8"\\xF4" for: "\xF4" == "\xF4"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xE0\x80") == u8"\\xE0\\x80" for: "\xE0\x80" == "\xE0\x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xE0\xBF") == u8"\\xE0\\xBF" for: "\xE0\xBF" == "\xE0\xBF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xE1\x80") == u8"\\xE1\\x80" for: "\xE1\x80" == "\xE1\x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF0\x80") == u8"\\xF0\\x80" for: "\xF0\x80" == "\xF0\x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF4\x80") == u8"\\xF4\\x80" for: "\xF4\x80" == "\xF4\x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80" for: "\xF0\x80\x80" == "\xF0\x80\x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80" for: "\xF4\x80\x80" == "\xF4\x80\x80"
|
||||
Tag.tests.cpp:<line number>: passed: testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide")) for: { "!hide", "." } ( Contains: "." and Contains: "!hide" )
|
||||
Tag.tests.cpp:<line number>: passed: testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide")) for: { "!hide", "." } ( Contains: "." and Contains: "!hide" )
|
||||
Tag.tests.cpp:<line number>: passed: testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide")) for: { "!hide", ".", "foo" } ( Contains: "." and Contains: "!hide" )
|
||||
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( empty ) == "{ }" for: "{ }" == "{ }"
|
||||
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( oneValue ) == "{ 42 }" for: "{ 42 }" == "{ 42 }"
|
||||
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( twoValues ) == "{ 42, 250 }" for: "{ 42, 250 }" == "{ 42, 250 }"
|
||||
@ -1704,7 +1710,7 @@ StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(s, "'", "|'")
|
||||
StringManip.tests.cpp:<line number>: passed: s == "didn|'t" for: "didn|'t" == "didn|'t"
|
||||
Misc.tests.cpp:<line number>: failed: false with 1 message: '3'
|
||||
Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7'
|
||||
Tag.tests.cpp:<line number>: passed: testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")) for: { ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
|
||||
Tag.tests.cpp:<line number>: passed: testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")) for: { "!hide", ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
|
||||
StringManip.tests.cpp:<line number>: passed: splitStringRef("", ','), Equals(std::vector<StringRef>()) for: { } Equals: { }
|
||||
StringManip.tests.cpp:<line number>: passed: splitStringRef("abc", ','), Equals(std::vector<StringRef>{"abc"}) for: { abc } Equals: { abc }
|
||||
StringManip.tests.cpp:<line number>: passed: splitStringRef("abc,def", ','), Equals(std::vector<StringRef>{"abc", "def"}) for: { abc, def } Equals: { abc, def }
|
||||
|
@ -1380,6 +1380,6 @@ due to unexpected exception with message:
|
||||
Why would you throw a std::string?
|
||||
|
||||
===============================================================================
|
||||
test cases: 305 | 231 passed | 70 failed | 4 failed as expected
|
||||
assertions: 1695 | 1543 passed | 131 failed | 21 failed as expected
|
||||
test cases: 310 | 236 passed | 70 failed | 4 failed as expected
|
||||
assertions: 1701 | 1549 passed | 131 failed | 21 failed as expected
|
||||
|
||||
|
@ -188,6 +188,61 @@ Compilation.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1905 -- test spec parser properly clears internal state between compound tests
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( spec.matches(fakeTestCase("spec . char")) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( spec.matches(fakeTestCase("spec , char")) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_FALSE( spec.matches(fakeTestCase(R"(spec \, char)")) )
|
||||
with expansion:
|
||||
!false
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1912 -- test spec parser handles escaping
|
||||
Various parentheses
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( spec.matches(fakeTestCase(R"(spec {a} char)")) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( spec.matches(fakeTestCase(R"(spec [a] char)")) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_FALSE( spec.matches(fakeTestCase("differs but has similar tag", "[a]")) )
|
||||
with expansion:
|
||||
!false
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1912 -- test spec parser handles escaping
|
||||
backslash in test name
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( spec.matches(fakeTestCase(R"(spec \ char)")) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#748 - captures with unexpected exceptions
|
||||
outside assertions
|
||||
@ -1879,6 +1934,37 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
"This wouldn't pass" not matches undescribed predicate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Assertion macros support bit operators and bool conversions
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( lhs | rhs )
|
||||
with expansion:
|
||||
Val: 1 | Val: 2
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_FALSE( lhs & rhs )
|
||||
with expansion:
|
||||
!(Val: 1 & Val: 2)
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( HasBitOperators{ 1 } & HasBitOperators{ 1 } )
|
||||
with expansion:
|
||||
Val: 1 & Val: 1
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( lhs ^ rhs )
|
||||
with expansion:
|
||||
Val: 1 ^ Val: 2
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_FALSE( lhs ^ lhs )
|
||||
with expansion:
|
||||
!(Val: 1 ^ Val: 1)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Assertions then sections
|
||||
-------------------------------------------------------------------------------
|
||||
@ -2390,6 +2476,24 @@ Condition.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
4294967295 (0x<hex digits>) > 4
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Composed matchers are distinct
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( testStringForMatching2(), !composed1 )
|
||||
with expansion:
|
||||
"some completely different text that contains one common word" not (
|
||||
contains: "string" or contains: "random" )
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( testStringForMatching2(), composed2 )
|
||||
with expansion:
|
||||
"some completely different text that contains one common word" ( contains:
|
||||
"string" or contains: "random" or contains: "different" )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Contains string matcher
|
||||
-------------------------------------------------------------------------------
|
||||
@ -5711,6 +5815,17 @@ Condition.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
5 != 6
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Lambdas in assertions
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( []() { return true; }() )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Less-than inequalities with different epsilons
|
||||
-------------------------------------------------------------------------------
|
||||
@ -7361,6 +7476,50 @@ CmdLine.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Parse test names and tags
|
||||
Shortened hide tags are split apart when parsing
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
CHECK( spec.matches(fakeTestCase("hidden and foo", "[.][foo]")) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
CHECK_FALSE( spec.matches(fakeTestCase("only foo", "[foo]")) )
|
||||
with expansion:
|
||||
!false
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Parse test names and tags
|
||||
Shortened hide tags also properly handle exclusion
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
CHECK_FALSE( spec.matches(fakeTestCase("hidden and foo", "[.][foo]")) )
|
||||
with expansion:
|
||||
!false
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
CHECK_FALSE( spec.matches(fakeTestCase("only foo", "[foo]")) )
|
||||
with expansion:
|
||||
!false
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
CHECK_FALSE( spec.matches(fakeTestCase("only hidden", "[.]")) )
|
||||
with expansion:
|
||||
!false
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
CHECK( spec.matches(fakeTestCase("neither foo nor hidden", "[bar]")) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Pointers can be compared to null
|
||||
-------------------------------------------------------------------------------
|
||||
@ -7772,6 +7931,102 @@ with expansion:
|
||||
"Unable to convert 'oops' to destination type" ( contains: "convert" and
|
||||
contains: "oops" )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Process can be configured on command line
|
||||
abort
|
||||
wait-for-keypress
|
||||
Accepted options
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
CHECK( cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}) )
|
||||
with expansion:
|
||||
{?}
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( config.waitForKeypress == std::get<1>(input) )
|
||||
with expansion:
|
||||
0 == 0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Process can be configured on command line
|
||||
abort
|
||||
wait-for-keypress
|
||||
Accepted options
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
CHECK( cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}) )
|
||||
with expansion:
|
||||
{?}
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( config.waitForKeypress == std::get<1>(input) )
|
||||
with expansion:
|
||||
1 == 1
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Process can be configured on command line
|
||||
abort
|
||||
wait-for-keypress
|
||||
Accepted options
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
CHECK( cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}) )
|
||||
with expansion:
|
||||
{?}
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( config.waitForKeypress == std::get<1>(input) )
|
||||
with expansion:
|
||||
2 == 2
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Process can be configured on command line
|
||||
abort
|
||||
wait-for-keypress
|
||||
Accepted options
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
CHECK( cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}) )
|
||||
with expansion:
|
||||
{?}
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( config.waitForKeypress == std::get<1>(input) )
|
||||
with expansion:
|
||||
3 == 3
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Process can be configured on command line
|
||||
abort
|
||||
wait-for-keypress
|
||||
invalid options are reported
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
CHECK( !result )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( result.errorMessage(), Contains("never") && Contains("both") )
|
||||
with expansion:
|
||||
"keypress argument must be one of: never, start, exit or both. 'sometimes'
|
||||
not recognised" ( contains: "never" and contains: "both" )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Process can be configured on command line
|
||||
nothrow
|
||||
@ -8002,7 +8257,7 @@ with expansion:
|
||||
-------------------------------------------------------------------------------
|
||||
Process can be configured on command line
|
||||
Benchmark options
|
||||
resamples
|
||||
confidence-interval
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
@ -8020,7 +8275,7 @@ with expansion:
|
||||
-------------------------------------------------------------------------------
|
||||
Process can be configured on command line
|
||||
Benchmark options
|
||||
resamples
|
||||
no-analysis
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
@ -8035,6 +8290,24 @@ CmdLine.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Process can be configured on command line
|
||||
Benchmark options
|
||||
warmup-time
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
CHECK( cli.parse({ "test", "--benchmark-warmup-time=10" }) )
|
||||
with expansion:
|
||||
{?}
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( config.benchmarkWarmupTime == 10 )
|
||||
with expansion:
|
||||
10 == 10
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Product with differing arities - std::tuple<int, double, float>
|
||||
-------------------------------------------------------------------------------
|
||||
@ -8670,7 +8943,7 @@ String.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
String.tests.cpp:<line number>: PASSED:
|
||||
CHECK( buffer1 != buffer2 )
|
||||
CHECK( (char*)buffer1 != (char*)buffer2 )
|
||||
with expansion:
|
||||
"Hello" != "Hello"
|
||||
|
||||
@ -10914,6 +11187,11 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
{ 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( v1, Approx<double>({ 1., 2., 3. }) )
|
||||
with expansion:
|
||||
{ 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Vector Approx matcher
|
||||
Vectors with elements
|
||||
@ -10996,6 +11274,11 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Contains: 2
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v5, (VectorContains<int, CustomAllocator<int>>(2)) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Contains: 2
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Vector matchers
|
||||
Contains (vector)
|
||||
@ -11008,6 +11291,16 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Contains: { 1, 2 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v, Contains<int>({ 1, 2 }) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Contains: { 1, 2 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Contains: { 1, 2 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v, Contains(v2) )
|
||||
with expansion:
|
||||
@ -11023,6 +11316,16 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
{ } Contains: { }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Contains: { 1, 2, 3 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v5, Contains(v6) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Contains: { 1, 2 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Vector matchers
|
||||
Contains (element), composed
|
||||
@ -11052,11 +11355,26 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
{ } Equals: { }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v, Equals<int>({ 1, 2, 3 }) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v, Equals(v2) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v5, (Equals<int, std::allocator<int>, CustomAllocator<int>>(v2)) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v5, Equals(v6) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Vector matchers
|
||||
UnorderedEquals
|
||||
@ -11069,6 +11387,11 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
{ 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v, UnorderedEquals<int>({ 3, 2, 1 }) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } UnorderedEquals: { 3, 2, 1 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( empty, UnorderedEquals(empty) )
|
||||
with expansion:
|
||||
@ -11084,6 +11407,16 @@ Matchers.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
{ 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v5, (UnorderedEquals<int, std::allocator<int>, CustomAllocator<int>>(permuted)) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } UnorderedEquals: { 2, 3, 1 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THAT( v5_permuted, UnorderedEquals(v5) )
|
||||
with expansion:
|
||||
{ 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Vector matchers that fail
|
||||
Contains (element)
|
||||
@ -11422,261 +11755,37 @@ with expansion:
|
||||
"[\x7F]" == "[\x7F]"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode: UTF-8
|
||||
Valid utf-8 strings
|
||||
adding a hide tag implicitly enables all others
|
||||
-------------------------------------------------------------------------------
|
||||
Xml.tests.cpp:<line number>
|
||||
Tag.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode(u8"Here be 👾") == u8"Here be 👾" )
|
||||
Tag.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide")) )
|
||||
with expansion:
|
||||
"Here be 👾" == "Here be 👾"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode(u8"šš") == u8"šš" )
|
||||
with expansion:
|
||||
"šš" == "šš"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xDF\xBF") == "\xDF\xBF" )
|
||||
with expansion:
|
||||
"߿" == "߿"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xE0\xA0\x80") == "\xE0\xA0\x80" )
|
||||
with expansion:
|
||||
"ࠀ" == "ࠀ"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xED\x9F\xBF") == "\xED\x9F\xBF" )
|
||||
with expansion:
|
||||
"" == ""
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xEE\x80\x80") == "\xEE\x80\x80" )
|
||||
with expansion:
|
||||
"" == ""
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xEF\xBF\xBF") == "\xEF\xBF\xBF" )
|
||||
with expansion:
|
||||
"" == ""
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80" )
|
||||
with expansion:
|
||||
"𐀀" == "𐀀"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF" )
|
||||
with expansion:
|
||||
"" == ""
|
||||
{ "!hide", "." } ( Contains: "." and Contains: "!hide" )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode: UTF-8
|
||||
Invalid utf-8 strings
|
||||
Various broken strings
|
||||
adding a hide tag implicitly enables all others
|
||||
-------------------------------------------------------------------------------
|
||||
Xml.tests.cpp:<line number>
|
||||
Tag.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("Here \xFF be 👾") == u8"Here \\xFF be 👾" )
|
||||
Tag.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide")) )
|
||||
with expansion:
|
||||
"Here \xFF be 👾" == "Here \xFF be 👾"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xFF") == "\\xFF" )
|
||||
with expansion:
|
||||
"\xFF" == "\xFF"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xC5\xC5\xA0") == u8"\\xC5Š" )
|
||||
with expansion:
|
||||
"\xC5Š" == "\xC5Š"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80" )
|
||||
with expansion:
|
||||
"\xF4\x90\x80\x80" == "\xF4\x90\x80\x80"
|
||||
{ "!hide", "." } ( Contains: "." and Contains: "!hide" )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode: UTF-8
|
||||
Invalid utf-8 strings
|
||||
Overlong encodings
|
||||
adding a hide tag implicitly enables all others
|
||||
-------------------------------------------------------------------------------
|
||||
Xml.tests.cpp:<line number>
|
||||
Tag.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xC0\x80") == u8"\\xC0\\x80" )
|
||||
Tag.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide")) )
|
||||
with expansion:
|
||||
"\xC0\x80" == "\xC0\x80"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80" )
|
||||
with expansion:
|
||||
"\xF0\x80\x80\x80" == "\xF0\x80\x80\x80"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xC1\xBF") == u8"\\xC1\\xBF" )
|
||||
with expansion:
|
||||
"\xC1\xBF" == "\xC1\xBF"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF" )
|
||||
with expansion:
|
||||
"\xE0\x9F\xBF" == "\xE0\x9F\xBF"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF" )
|
||||
with expansion:
|
||||
"\xF0\x8F\xBF\xBF" == "\xF0\x8F\xBF\xBF"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode: UTF-8
|
||||
Invalid utf-8 strings
|
||||
Surrogate pairs
|
||||
-------------------------------------------------------------------------------
|
||||
Xml.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xED\xA0\x80") == "\xED\xA0\x80" )
|
||||
with expansion:
|
||||
"<22><><EFBFBD>" == "<22><><EFBFBD>"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xED\xAF\xBF") == "\xED\xAF\xBF" )
|
||||
with expansion:
|
||||
"<22><><EFBFBD>" == "<22><><EFBFBD>"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xED\xB0\x80") == "\xED\xB0\x80" )
|
||||
with expansion:
|
||||
"<22><><EFBFBD>" == "<22><><EFBFBD>"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xED\xBF\xBF") == "\xED\xBF\xBF" )
|
||||
with expansion:
|
||||
"<22><><EFBFBD>" == "<22><><EFBFBD>"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode: UTF-8
|
||||
Invalid utf-8 strings
|
||||
Invalid start byte
|
||||
-------------------------------------------------------------------------------
|
||||
Xml.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\x80") == u8"\\x80" )
|
||||
with expansion:
|
||||
"\x80" == "\x80"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\x81") == u8"\\x81" )
|
||||
with expansion:
|
||||
"\x81" == "\x81"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xBC") == u8"\\xBC" )
|
||||
with expansion:
|
||||
"\xBC" == "\xBC"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xBF") == u8"\\xBF" )
|
||||
with expansion:
|
||||
"\xBF" == "\xBF"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80" )
|
||||
with expansion:
|
||||
"\xF5\x80\x80\x80" == "\xF5\x80\x80\x80"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80" )
|
||||
with expansion:
|
||||
"\xF6\x80\x80\x80" == "\xF6\x80\x80\x80"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80" )
|
||||
with expansion:
|
||||
"\xF7\x80\x80\x80" == "\xF7\x80\x80\x80"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
XmlEncode: UTF-8
|
||||
Invalid utf-8 strings
|
||||
Missing continuation byte(s)
|
||||
-------------------------------------------------------------------------------
|
||||
Xml.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xDE") == u8"\\xDE" )
|
||||
with expansion:
|
||||
"\xDE" == "\xDE"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xDF") == u8"\\xDF" )
|
||||
with expansion:
|
||||
"\xDF" == "\xDF"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xE0") == u8"\\xE0" )
|
||||
with expansion:
|
||||
"\xE0" == "\xE0"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xEF") == u8"\\xEF" )
|
||||
with expansion:
|
||||
"\xEF" == "\xEF"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF0") == u8"\\xF0" )
|
||||
with expansion:
|
||||
"\xF0" == "\xF0"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF4") == u8"\\xF4" )
|
||||
with expansion:
|
||||
"\xF4" == "\xF4"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xE0\x80") == u8"\\xE0\\x80" )
|
||||
with expansion:
|
||||
"\xE0\x80" == "\xE0\x80"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xE0\xBF") == u8"\\xE0\\xBF" )
|
||||
with expansion:
|
||||
"\xE0\xBF" == "\xE0\xBF"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xE1\x80") == u8"\\xE1\\x80" )
|
||||
with expansion:
|
||||
"\xE1\x80" == "\xE1\x80"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF0\x80") == u8"\\xF0\\x80" )
|
||||
with expansion:
|
||||
"\xF0\x80" == "\xF0\x80"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF4\x80") == u8"\\xF4\\x80" )
|
||||
with expansion:
|
||||
"\xF4\x80" == "\xF4\x80"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80" )
|
||||
with expansion:
|
||||
"\xF0\x80\x80" == "\xF0\x80\x80"
|
||||
|
||||
Xml.tests.cpp:<line number>: PASSED:
|
||||
CHECK( encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80" )
|
||||
with expansion:
|
||||
"\xF4\x80\x80" == "\xF4\x80\x80"
|
||||
{ "!hide", ".", "foo" } ( Contains: "." and Contains: "!hide" )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
array<int, N> -> toString
|
||||
@ -12600,7 +12709,7 @@ Tag.tests.cpp:<line number>
|
||||
Tag.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")) )
|
||||
with expansion:
|
||||
{ ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
|
||||
{ "!hide", ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
splitString
|
||||
@ -13464,6 +13573,6 @@ Misc.tests.cpp:<line number>
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
|
||||
===============================================================================
|
||||
test cases: 305 | 215 passed | 86 failed | 4 failed as expected
|
||||
assertions: 1712 | 1543 passed | 148 failed | 21 failed as expected
|
||||
test cases: 310 | 220 passed | 86 failed | 4 failed as expected
|
||||
assertions: 1718 | 1549 passed | 148 failed | 21 failed as expected
|
||||
|
||||
|
@ -188,6 +188,61 @@ Compilation.tests.cpp:<line number>: PASSED:
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1905 -- test spec parser properly clears internal state between compound tests
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( spec.matches(fakeTestCase("spec . char")) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( spec.matches(fakeTestCase("spec , char")) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_FALSE( spec.matches(fakeTestCase(R"(spec \, char)")) )
|
||||
with expansion:
|
||||
!false
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1912 -- test spec parser handles escaping
|
||||
Various parentheses
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( spec.matches(fakeTestCase(R"(spec {a} char)")) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( spec.matches(fakeTestCase(R"(spec [a] char)")) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_FALSE( spec.matches(fakeTestCase("differs but has similar tag", "[a]")) )
|
||||
with expansion:
|
||||
!false
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1912 -- test spec parser handles escaping
|
||||
backslash in test name
|
||||
-------------------------------------------------------------------------------
|
||||
CmdLine.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
CmdLine.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( spec.matches(fakeTestCase(R"(spec \ char)")) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#748 - captures with unexpected exceptions
|
||||
outside assertions
|
||||
@ -368,6 +423,6 @@ Condition.tests.cpp:<line number>: FAILED:
|
||||
CHECK( true != true )
|
||||
|
||||
===============================================================================
|
||||
test cases: 19 | 14 passed | 3 failed | 2 failed as expected
|
||||
assertions: 42 | 35 passed | 4 failed | 3 failed as expected
|
||||
test cases: 21 | 16 passed | 3 failed | 2 failed as expected
|
||||
assertions: 49 | 42 passed | 4 failed | 3 failed as expected
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuitesloose text artifact
|
||||
>
|
||||
<testsuite name="<exe-name>" errors="17" failures="132" tests="1713" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="17" failures="132" tests="1719" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<properties>
|
||||
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/>
|
||||
<property name="random-seed" value="1"/>
|
||||
@ -30,6 +30,9 @@ Nor would this
|
||||
</system-err>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="#1548" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="#1905 -- test spec parser properly clears internal state between compound tests" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="#1912 -- test spec parser handles escaping/Various parentheses" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="#1912 -- test spec parser handles escaping/backslash in test name" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
FAILED:
|
||||
@ -337,6 +340,7 @@ Exception.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Approximate comparisons with mixed numeric types" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Function pointer" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Lambdas + different type" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Assertion macros support bit operators and bool conversions" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Assertions then sections" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Assertions then sections/A section" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another section" time="{duration}"/>
|
||||
@ -356,6 +360,7 @@ Exception.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Comparisons between ints where one side is computed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Comparisons with int literals don't warn when mixing signed/ unsigned" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Composed matchers are distinct" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Contains string matcher" time="{duration}">
|
||||
<failure message="testStringForMatching(), Contains("not there", Catch::CaseSensitive::No)" type="CHECK_THAT">
|
||||
FAILED:
|
||||
@ -752,6 +757,7 @@ Condition.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Inequality checks that should succeed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Lambdas in assertions" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Less-than inequalities with different epsilons" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="ManuallyRegistered" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Matchers can be (AllOf) composed with the && operator" time="{duration}"/>
|
||||
@ -982,6 +988,8 @@ Message.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Parse test names and tags/quoted string followed by tag exclusion" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Parse test names and tags/Leading and trailing spaces in test spec" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Parse test names and tags/Leading and trailing spaces in test name" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Parse test names and tags/Shortened hide tags are split apart when parsing" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Parse test names and tags/Shortened hide tags also properly handle exclusion" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Pointers can be compared to null" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Precision of floating point stringification can be set/Floats" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Precision of floating point stringification can be set/Double" time="{duration}"/>
|
||||
@ -1001,6 +1009,8 @@ Message.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/abort/-a aborts after first failure" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/abort/-x 2 aborts after two failures" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/abort/-x must be numeric" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/abort/wait-for-keypress/Accepted options" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/abort/wait-for-keypress/invalid options are reported" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/nothrow/-e" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/nothrow/--nothrow" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/output filename/-o filename" time="{duration}"/>
|
||||
@ -1013,8 +1023,9 @@ Message.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/error" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/Benchmark options/samples" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/Benchmark options/resamples" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/Benchmark options/resamples" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/Benchmark options/resamples" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/Benchmark options/confidence-interval" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/Benchmark options/no-analysis" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/Benchmark options/warmup-time" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Product with differing arities - std::tuple<int, double, float>" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Product with differing arities - std::tuple<int, double>" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Product with differing arities - std::tuple<int>" time="{duration}"/>
|
||||
@ -1402,12 +1413,7 @@ Exception.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode/string with quotes" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode/string with control char (1)" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode/string with control char (x7F)" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Valid utf-8 strings" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Various broken strings" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Overlong encodings" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Surrogate pairs" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Invalid start byte" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Missing continuation byte(s)" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="adding a hide tag implicitly enables all others" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="array<int, N> -> toString" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="atomic if" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="boolean member" time="{duration}"/>
|
||||
|
@ -2,6 +2,9 @@
|
||||
<testExecutions version="1"loose text artifact
|
||||
>
|
||||
<file path="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp">
|
||||
<testCase name="#1905 -- test spec parser properly clears internal state between compound tests" duration="{duration}"/>
|
||||
<testCase name="#1912 -- test spec parser handles escaping/Various parentheses" duration="{duration}"/>
|
||||
<testCase name="#1912 -- test spec parser handles escaping/backslash in test name" duration="{duration}"/>
|
||||
<testCase name="Parse test names and tags/Empty test spec should have no filters" duration="{duration}"/>
|
||||
<testCase name="Parse test names and tags/Test spec from empty string should have no filters" duration="{duration}"/>
|
||||
<testCase name="Parse test names and tags/Test spec from just a comma should have no filters" duration="{duration}"/>
|
||||
@ -35,6 +38,8 @@
|
||||
<testCase name="Parse test names and tags/quoted string followed by tag exclusion" duration="{duration}"/>
|
||||
<testCase name="Parse test names and tags/Leading and trailing spaces in test spec" duration="{duration}"/>
|
||||
<testCase name="Parse test names and tags/Leading and trailing spaces in test name" duration="{duration}"/>
|
||||
<testCase name="Parse test names and tags/Shortened hide tags are split apart when parsing" duration="{duration}"/>
|
||||
<testCase name="Parse test names and tags/Shortened hide tags also properly handle exclusion" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/empty args don't cause a crash" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/default - no arguments" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/test lists/Specify one test case using" duration="{duration}"/>
|
||||
@ -50,6 +55,8 @@
|
||||
<testCase name="Process can be configured on command line/abort/-a aborts after first failure" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/abort/-x 2 aborts after two failures" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/abort/-x must be numeric" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/abort/wait-for-keypress/Accepted options" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/abort/wait-for-keypress/invalid options are reported" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/nothrow/-e" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/nothrow/--nothrow" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/output filename/-o filename" duration="{duration}"/>
|
||||
@ -62,8 +69,9 @@
|
||||
<testCase name="Process can be configured on command line/use-colour/error" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/Benchmark options/samples" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/Benchmark options/resamples" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/Benchmark options/resamples" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/Benchmark options/resamples" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/Benchmark options/confidence-interval" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/Benchmark options/no-analysis" duration="{duration}"/>
|
||||
<testCase name="Process can be configured on command line/Benchmark options/warmup-time" duration="{duration}"/>
|
||||
<testCase name="Test with special, characters "in name" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp">
|
||||
@ -140,6 +148,7 @@
|
||||
<file path="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp">
|
||||
<testCase name="Tag alias can be registered against tag patterns/The same tag alias can only be registered once" duration="{duration}"/>
|
||||
<testCase name="Tag alias can be registered against tag patterns/Tag aliases must be of the form [@name]" duration="{duration}"/>
|
||||
<testCase name="adding a hide tag implicitly enables all others" duration="{duration}"/>
|
||||
<testCase name="shortened hide tags are split apart" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="projects/<exe-name>/IntrospectiveTests/ToString.tests.cpp">
|
||||
@ -157,12 +166,6 @@
|
||||
<testCase name="XmlEncode/string with quotes" duration="{duration}"/>
|
||||
<testCase name="XmlEncode/string with control char (1)" duration="{duration}"/>
|
||||
<testCase name="XmlEncode/string with control char (x7F)" duration="{duration}"/>
|
||||
<testCase name="XmlEncode: UTF-8/Valid utf-8 strings" duration="{duration}"/>
|
||||
<testCase name="XmlEncode: UTF-8/Invalid utf-8 strings/Various broken strings" duration="{duration}"/>
|
||||
<testCase name="XmlEncode: UTF-8/Invalid utf-8 strings/Overlong encodings" duration="{duration}"/>
|
||||
<testCase name="XmlEncode: UTF-8/Invalid utf-8 strings/Surrogate pairs" duration="{duration}"/>
|
||||
<testCase name="XmlEncode: UTF-8/Invalid utf-8 strings/Invalid start byte" duration="{duration}"/>
|
||||
<testCase name="XmlEncode: UTF-8/Invalid utf-8 strings/Missing continuation byte(s)" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="projects/<exe-name>/UsageTests/Approx.tests.cpp">
|
||||
<testCase name="A comparison that uses literals instead of the normal constructor" duration="{duration}"/>
|
||||
@ -369,6 +372,8 @@ Class.tests.cpp:<line number>
|
||||
<testCase name="#809" duration="{duration}"/>
|
||||
<testCase name="#833" duration="{duration}"/>
|
||||
<testCase name="#872" duration="{duration}"/>
|
||||
<testCase name="Assertion macros support bit operators and bool conversions" duration="{duration}"/>
|
||||
<testCase name="Lambdas in assertions" duration="{duration}"/>
|
||||
<testCase name="Optionally static assertions" duration="{duration}"/>
|
||||
</file>
|
||||
<file path="projects/<exe-name>/UsageTests/Condition.tests.cpp">
|
||||
@ -894,6 +899,7 @@ Exception.tests.cpp:<line number>
|
||||
<file path="projects/<exe-name>/UsageTests/Matchers.tests.cpp">
|
||||
<testCase name="Arbitrary predicate matcher/Function pointer" duration="{duration}"/>
|
||||
<testCase name="Arbitrary predicate matcher/Lambdas + different type" duration="{duration}"/>
|
||||
<testCase name="Composed matchers are distinct" duration="{duration}"/>
|
||||
<testCase name="Contains string matcher" duration="{duration}">
|
||||
<failure message="CHECK_THAT(testStringForMatching(), Contains("not there", Catch::CaseSensitive::No))">
|
||||
FAILED:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,7 +17,7 @@
|
||||
|
||||
inline Catch::TestCase fakeTestCase(const char* name, const char* desc = "") { return Catch::makeTestCase(nullptr, "", { name, desc }, CATCH_INTERNAL_LINEINFO); }
|
||||
|
||||
TEST_CASE( "Parse test names and tags" ) {
|
||||
TEST_CASE( "Parse test names and tags", "[command-line][test-spec]" ) {
|
||||
|
||||
using Catch::parseTestSpec;
|
||||
using Catch::TestSpec;
|
||||
@ -269,7 +269,6 @@ TEST_CASE( "Parse test names and tags" ) {
|
||||
CHECK( spec.matches( fakeTestCase( " aardvark " ) ) );
|
||||
CHECK( spec.matches( fakeTestCase( "aardvark " ) ) );
|
||||
CHECK( spec.matches( fakeTestCase( "aardvark" ) ) );
|
||||
|
||||
}
|
||||
SECTION( "Leading and trailing spaces in test name" ) {
|
||||
TestSpec spec = parseTestSpec( "aardvark" );
|
||||
@ -278,7 +277,47 @@ TEST_CASE( "Parse test names and tags" ) {
|
||||
CHECK( spec.matches( fakeTestCase( " aardvark " ) ) );
|
||||
CHECK( spec.matches( fakeTestCase( "aardvark " ) ) );
|
||||
CHECK( spec.matches( fakeTestCase( "aardvark" ) ) );
|
||||
}
|
||||
SECTION("Shortened hide tags are split apart when parsing") {
|
||||
TestSpec spec = parseTestSpec("[.foo]");
|
||||
CHECK(spec.matches(fakeTestCase("hidden and foo", "[.][foo]")));
|
||||
CHECK_FALSE(spec.matches(fakeTestCase("only foo", "[foo]")));
|
||||
}
|
||||
SECTION("Shortened hide tags also properly handle exclusion") {
|
||||
TestSpec spec = parseTestSpec("~[.foo]");
|
||||
CHECK_FALSE(spec.matches(fakeTestCase("hidden and foo", "[.][foo]")));
|
||||
CHECK_FALSE(spec.matches(fakeTestCase("only foo", "[foo]")));
|
||||
CHECK_FALSE(spec.matches(fakeTestCase("only hidden", "[.]")));
|
||||
CHECK(spec.matches(fakeTestCase("neither foo nor hidden", "[bar]")));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("#1905 -- test spec parser properly clears internal state between compound tests", "[command-line][test-spec]") {
|
||||
using Catch::parseTestSpec;
|
||||
using Catch::TestSpec;
|
||||
// We ask for one of 2 different tests and the latter one of them has a , in name that needs escaping
|
||||
TestSpec spec = parseTestSpec(R"("spec . char","spec \, char")");
|
||||
|
||||
REQUIRE(spec.matches(fakeTestCase("spec . char")));
|
||||
REQUIRE(spec.matches(fakeTestCase("spec , char")));
|
||||
REQUIRE_FALSE(spec.matches(fakeTestCase(R"(spec \, char)")));
|
||||
}
|
||||
|
||||
TEST_CASE("#1912 -- test spec parser handles escaping", "[command-line][test-spec]") {
|
||||
using Catch::parseTestSpec;
|
||||
using Catch::TestSpec;
|
||||
|
||||
SECTION("Various parentheses") {
|
||||
TestSpec spec = parseTestSpec(R"(spec {a} char,spec \[a] char)");
|
||||
|
||||
REQUIRE(spec.matches(fakeTestCase(R"(spec {a} char)")));
|
||||
REQUIRE(spec.matches(fakeTestCase(R"(spec [a] char)")));
|
||||
REQUIRE_FALSE(spec.matches(fakeTestCase("differs but has similar tag", "[a]")));
|
||||
}
|
||||
SECTION("backslash in test name") {
|
||||
TestSpec spec = parseTestSpec(R"(spec \\ char)");
|
||||
|
||||
REQUIRE(spec.matches(fakeTestCase(R"(spec \ char)")));
|
||||
}
|
||||
}
|
||||
|
||||
@ -402,9 +441,33 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
|
||||
|
||||
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||
REQUIRE_THAT(result.errorMessage(), Contains("convert") && Contains("oops"));
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("wait-for-keypress") {
|
||||
SECTION("Accepted options") {
|
||||
using tuple_type = std::tuple<char const*, Catch::WaitForKeypress::When>;
|
||||
auto input = GENERATE(table<char const*, Catch::WaitForKeypress::When>({
|
||||
tuple_type{"never", Catch::WaitForKeypress::Never},
|
||||
tuple_type{"start", Catch::WaitForKeypress::BeforeStart},
|
||||
tuple_type{"exit", Catch::WaitForKeypress::BeforeExit},
|
||||
tuple_type{"both", Catch::WaitForKeypress::BeforeStartAndExit},
|
||||
}));
|
||||
CHECK(cli.parse({"test", "--wait-for-keypress", std::get<0>(input)}));
|
||||
|
||||
REQUIRE(config.waitForKeypress == std::get<1>(input));
|
||||
}
|
||||
|
||||
SECTION("invalid options are reported") {
|
||||
auto result = cli.parse({"test", "--wait-for-keypress", "sometimes"});
|
||||
CHECK(!result);
|
||||
|
||||
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||
REQUIRE_THAT(result.errorMessage(), Contains("never") && Contains("both"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("nothrow") {
|
||||
SECTION("-e") {
|
||||
@ -486,24 +549,30 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
|
||||
|
||||
REQUIRE(config.benchmarkSamples == 200);
|
||||
}
|
||||
|
||||
|
||||
SECTION("resamples") {
|
||||
CHECK(cli.parse({ "test", "--benchmark-resamples=20000" }));
|
||||
|
||||
REQUIRE(config.benchmarkResamples == 20000);
|
||||
}
|
||||
|
||||
SECTION("resamples") {
|
||||
SECTION("confidence-interval") {
|
||||
CHECK(cli.parse({ "test", "--benchmark-confidence-interval=0.99" }));
|
||||
|
||||
REQUIRE(config.benchmarkConfidenceInterval == Catch::Detail::Approx(0.99));
|
||||
}
|
||||
|
||||
SECTION("resamples") {
|
||||
SECTION("no-analysis") {
|
||||
CHECK(cli.parse({ "test", "--benchmark-no-analysis" }));
|
||||
|
||||
REQUIRE(config.benchmarkNoAnalysis);
|
||||
}
|
||||
|
||||
SECTION("warmup-time") {
|
||||
CHECK(cli.parse({ "test", "--benchmark-warmup-time=10" }));
|
||||
|
||||
REQUIRE(config.benchmarkWarmupTime == 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,7 @@ TEST_CASE("Generators internals", "[generators][internals]") {
|
||||
const auto step = .1;
|
||||
|
||||
auto gen = range(rangeStart, rangeEnd, step);
|
||||
auto expected = rangeStart;
|
||||
auto expected = rangeStart;
|
||||
while( (rangeEnd - expected) > step ) {
|
||||
INFO( "Current expected value is " << expected )
|
||||
REQUIRE(gen.get() == Approx(expected));
|
||||
@ -198,7 +198,7 @@ TEST_CASE("Generators internals", "[generators][internals]") {
|
||||
const auto step = .3;
|
||||
|
||||
auto gen = range(rangeStart, rangeEnd, step);
|
||||
auto expected = rangeStart;
|
||||
auto expected = rangeStart;
|
||||
while( (rangeEnd - expected) > step ) {
|
||||
INFO( "Current expected value is " << expected )
|
||||
REQUIRE(gen.get() == Approx(expected));
|
||||
@ -214,7 +214,7 @@ TEST_CASE("Generators internals", "[generators][internals]") {
|
||||
const auto step = .3;
|
||||
|
||||
auto gen = range(rangeStart, rangeEnd, step);
|
||||
auto expected = rangeStart;
|
||||
auto expected = rangeStart;
|
||||
while( (rangeEnd - expected) > step ) {
|
||||
INFO( "Current expected value is " << expected )
|
||||
REQUIRE(gen.get() == Approx(expected));
|
||||
@ -223,7 +223,7 @@ TEST_CASE("Generators internals", "[generators][internals]") {
|
||||
expected += step;
|
||||
}
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SECTION("Negative manual step") {
|
||||
@ -311,6 +311,21 @@ TEST_CASE("GENERATE capture macros", "[generators][internals][approvals]") {
|
||||
REQUIRE(value == value2);
|
||||
}
|
||||
|
||||
TEST_CASE("#1809 - GENERATE_COPY and SingleValueGenerator does not compile", "[generators][compilation][approvals]") {
|
||||
// Verify Issue #1809 fix, only needs to compile.
|
||||
auto a = GENERATE_COPY(1, 2);
|
||||
(void)a;
|
||||
auto b = GENERATE_COPY(as<long>{}, 1, 2);
|
||||
(void)b;
|
||||
int i = 1;
|
||||
int j = 2;
|
||||
auto c = GENERATE_COPY(i, j);
|
||||
(void)c;
|
||||
auto d = GENERATE_COPY(as<long>{}, i, j);
|
||||
(void)d;
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
TEST_CASE("Multiple random generators in one test case output different values", "[generators][internals][approvals]") {
|
||||
SECTION("Integer") {
|
||||
auto random1 = Catch::Generators::random(0, 1000);
|
||||
|
@ -79,7 +79,7 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
||||
SECTION( "Comparisons are deep" ) {
|
||||
char buffer1[] = "Hello";
|
||||
char buffer2[] = "Hello";
|
||||
CHECK(buffer1 != buffer2);
|
||||
CHECK((char*)buffer1 != (char*)buffer2);
|
||||
|
||||
StringRef left(buffer1), right(buffer2);
|
||||
REQUIRE( left == right );
|
||||
|
@ -45,3 +45,10 @@ TEST_CASE("shortened hide tags are split apart") {
|
||||
auto testcase = Catch::makeTestCase(nullptr, "", {"fake test name", "[.magic-tag]"}, CATCH_INTERNAL_LINEINFO);
|
||||
REQUIRE_THAT(testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")));
|
||||
}
|
||||
|
||||
TEST_CASE("adding a hide tag implicitly enables all others", "[tags]") {
|
||||
using Catch::VectorContains;
|
||||
auto tag = GENERATE(as<char const*>{}, "[!hide]", "[.]", "[.foo]");
|
||||
auto testcase = Catch::makeTestCase(nullptr, "", {"fake test name", tag}, CATCH_INTERNAL_LINEINFO);
|
||||
REQUIRE_THAT(testcase.tags, VectorContains(std::string(".")) && VectorContains(std::string("!hide")));
|
||||
}
|
||||
|
@ -40,10 +40,11 @@ TEST_CASE( "XmlEncode", "[XML]" ) {
|
||||
}
|
||||
|
||||
// Thanks to Peter Bindels (dascandy) for some of the tests
|
||||
TEST_CASE("XmlEncode: UTF-8", "[XML][UTF-8]") {
|
||||
TEST_CASE("XmlEncode: UTF-8", "[XML][UTF-8][approvals]") {
|
||||
#define ESC(lit) (char*)(lit)
|
||||
SECTION("Valid utf-8 strings") {
|
||||
CHECK(encode(u8"Here be 👾") == u8"Here be 👾");
|
||||
CHECK(encode(u8"šš") == u8"šš");
|
||||
CHECK(encode(ESC(u8"Here be 👾")) == ESC(u8"Here be 👾"));
|
||||
CHECK(encode(ESC(u8"šš")) == ESC(u8"šš"));
|
||||
|
||||
CHECK(encode("\xDF\xBF") == "\xDF\xBF"); // 0x7FF
|
||||
CHECK(encode("\xE0\xA0\x80") == "\xE0\xA0\x80"); // 0x800
|
||||
@ -55,18 +56,18 @@ TEST_CASE("XmlEncode: UTF-8", "[XML][UTF-8]") {
|
||||
}
|
||||
SECTION("Invalid utf-8 strings") {
|
||||
SECTION("Various broken strings") {
|
||||
CHECK(encode("Here \xFF be 👾") == u8"Here \\xFF be 👾");
|
||||
CHECK(encode(ESC("Here \xFF be \xF0\x9F\x91\xBE")) == ESC(u8"Here \\xFF be 👾"));
|
||||
CHECK(encode("\xFF") == "\\xFF");
|
||||
CHECK(encode("\xC5\xC5\xA0") == u8"\\xC5Š");
|
||||
CHECK(encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80"); // 0x110000 -- out of unicode range
|
||||
CHECK(encode("\xC5\xC5\xA0") == ESC(u8"\\xC5Š"));
|
||||
CHECK(encode("\xF4\x90\x80\x80") == ESC(u8"\\xF4\\x90\\x80\\x80")); // 0x110000 -- out of unicode range
|
||||
}
|
||||
|
||||
SECTION("Overlong encodings") {
|
||||
CHECK(encode("\xC0\x80") == u8"\\xC0\\x80"); // \0
|
||||
CHECK(encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80"); // Super-over-long \0
|
||||
CHECK(encode("\xC1\xBF") == u8"\\xC1\\xBF"); // ASCII char as UTF-8 (0x7F)
|
||||
CHECK(encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF"); // 0x7FF
|
||||
CHECK(encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF"); // 0xFFFF
|
||||
CHECK(encode("\xC0\x80") == "\\xC0\\x80"); // \0
|
||||
CHECK(encode("\xF0\x80\x80\x80") == "\\xF0\\x80\\x80\\x80"); // Super-over-long \0
|
||||
CHECK(encode("\xC1\xBF") == "\\xC1\\xBF"); // ASCII char as UTF-8 (0x7F)
|
||||
CHECK(encode("\xE0\x9F\xBF") == "\\xE0\\x9F\\xBF"); // 0x7FF
|
||||
CHECK(encode("\xF0\x8F\xBF\xBF") == "\\xF0\\x8F\\xBF\\xBF"); // 0xFFFF
|
||||
}
|
||||
|
||||
// Note that we actually don't modify surrogate pairs, as we do not do strict checking
|
||||
@ -78,35 +79,36 @@ TEST_CASE("XmlEncode: UTF-8", "[XML][UTF-8]") {
|
||||
}
|
||||
|
||||
SECTION("Invalid start byte") {
|
||||
CHECK(encode("\x80") == u8"\\x80");
|
||||
CHECK(encode("\x81") == u8"\\x81");
|
||||
CHECK(encode("\xBC") == u8"\\xBC");
|
||||
CHECK(encode("\xBF") == u8"\\xBF");
|
||||
CHECK(encode("\x80") == "\\x80");
|
||||
CHECK(encode("\x81") == "\\x81");
|
||||
CHECK(encode("\xBC") == "\\xBC");
|
||||
CHECK(encode("\xBF") == "\\xBF");
|
||||
// Out of range
|
||||
CHECK(encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80");
|
||||
CHECK(encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80");
|
||||
CHECK(encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80");
|
||||
CHECK(encode("\xF5\x80\x80\x80") == "\\xF5\\x80\\x80\\x80");
|
||||
CHECK(encode("\xF6\x80\x80\x80") == "\\xF6\\x80\\x80\\x80");
|
||||
CHECK(encode("\xF7\x80\x80\x80") == "\\xF7\\x80\\x80\\x80");
|
||||
}
|
||||
|
||||
SECTION("Missing continuation byte(s)") {
|
||||
// Missing first continuation byte
|
||||
CHECK(encode("\xDE") == u8"\\xDE");
|
||||
CHECK(encode("\xDF") == u8"\\xDF");
|
||||
CHECK(encode("\xE0") == u8"\\xE0");
|
||||
CHECK(encode("\xEF") == u8"\\xEF");
|
||||
CHECK(encode("\xF0") == u8"\\xF0");
|
||||
CHECK(encode("\xF4") == u8"\\xF4");
|
||||
CHECK(encode("\xDE") == "\\xDE");
|
||||
CHECK(encode("\xDF") == "\\xDF");
|
||||
CHECK(encode("\xE0") == "\\xE0");
|
||||
CHECK(encode("\xEF") == "\\xEF");
|
||||
CHECK(encode("\xF0") == "\\xF0");
|
||||
CHECK(encode("\xF4") == "\\xF4");
|
||||
|
||||
// Missing second continuation byte
|
||||
CHECK(encode("\xE0\x80") == u8"\\xE0\\x80");
|
||||
CHECK(encode("\xE0\xBF") == u8"\\xE0\\xBF");
|
||||
CHECK(encode("\xE1\x80") == u8"\\xE1\\x80");
|
||||
CHECK(encode("\xF0\x80") == u8"\\xF0\\x80");
|
||||
CHECK(encode("\xF4\x80") == u8"\\xF4\\x80");
|
||||
CHECK(encode("\xE0\x80") == "\\xE0\\x80");
|
||||
CHECK(encode("\xE0\xBF") == "\\xE0\\xBF");
|
||||
CHECK(encode("\xE1\x80") == "\\xE1\\x80");
|
||||
CHECK(encode("\xF0\x80") == "\\xF0\\x80");
|
||||
CHECK(encode("\xF4\x80") == "\\xF4\\x80");
|
||||
|
||||
// Missing third continuation byte
|
||||
CHECK(encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80");
|
||||
CHECK(encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80");
|
||||
CHECK(encode("\xF0\x80\x80") == "\\xF0\\x80\\x80");
|
||||
CHECK(encode("\xF4\x80\x80") == "\\xF4\\x80\\x80");
|
||||
}
|
||||
}
|
||||
#undef ESC
|
||||
}
|
||||
|
@ -126,5 +126,19 @@ TEST_CASE("Benchmark containers", "[!benchmark]") {
|
||||
REQUIRE(v[i] == generated);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("construct and destroy example") {
|
||||
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) {
|
||||
std::vector<Catch::Benchmark::storage_for<std::string>> storage(meter.runs());
|
||||
meter.measure([&](int i) { storage[i].construct("thing"); });
|
||||
};
|
||||
|
||||
BENCHMARK_ADVANCED("destroy")(Catch::Benchmark::Chronometer meter) {
|
||||
std::vector<Catch::Benchmark::destructable_object<std::string>> storage(meter.runs());
|
||||
for(auto&& o : storage)
|
||||
o.construct("thing");
|
||||
meter.measure([&](int i) { storage[i].destruct(); });
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
|
||||
|
@ -205,10 +205,19 @@ namespace { namespace CompilationTests {
|
||||
inline static void synchronizing_callback( void * ) { }
|
||||
}
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
#pragma warning(push)
|
||||
// The function pointer comparison below triggers warning because of
|
||||
// calling conventions
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
TEST_CASE("#925: comparing function pointer to function address failed to compile", "[!nonportable]" ) {
|
||||
TestClass test;
|
||||
REQUIRE(utility::synchronizing_callback != test.testMethod_uponComplete_arg);
|
||||
}
|
||||
#if defined (_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
TEST_CASE( "#1027: Bitfields can be captured" ) {
|
||||
struct Y {
|
||||
@ -219,6 +228,42 @@ namespace { namespace CompilationTests {
|
||||
REQUIRE( 0 == y.v );
|
||||
}
|
||||
|
||||
TEST_CASE("Lambdas in assertions") {
|
||||
REQUIRE([]() { return true; }());
|
||||
}
|
||||
|
||||
}} // namespace CompilationTests
|
||||
|
||||
namespace {
|
||||
struct HasBitOperators {
|
||||
int value;
|
||||
|
||||
friend HasBitOperators operator| (HasBitOperators lhs, HasBitOperators rhs) {
|
||||
return { lhs.value | rhs.value };
|
||||
}
|
||||
friend HasBitOperators operator& (HasBitOperators lhs, HasBitOperators rhs) {
|
||||
return { lhs.value & rhs.value };
|
||||
}
|
||||
friend HasBitOperators operator^ (HasBitOperators lhs, HasBitOperators rhs) {
|
||||
return { lhs.value ^ rhs.value };
|
||||
}
|
||||
explicit operator bool() const {
|
||||
return !!value;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, HasBitOperators val) {
|
||||
out << "Val: " << val.value;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("Assertion macros support bit operators and bool conversions", "[compilation][bitops]") {
|
||||
HasBitOperators lhs{ 1 }, rhs{ 2 };
|
||||
REQUIRE(lhs | rhs);
|
||||
REQUIRE_FALSE(lhs & rhs);
|
||||
REQUIRE(HasBitOperators{ 1 } & HasBitOperators{ 1 });
|
||||
REQUIRE(lhs ^ rhs);
|
||||
REQUIRE_FALSE(lhs ^ lhs);
|
||||
}
|
||||
|
||||
|
@ -214,6 +214,42 @@ namespace { namespace MatchersTests {
|
||||
CHECK_THAT(testStringForMatching(), !Contains("substring"));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct CustomAllocator : private std::allocator<T>
|
||||
{
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = T*;
|
||||
using const_pointer = const T*;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
using value_type = T;
|
||||
|
||||
template<typename U>
|
||||
struct rebind
|
||||
{ using other = CustomAllocator<U>; };
|
||||
|
||||
using propagate_on_container_move_assignment = std::true_type;
|
||||
using is_always_equal = std::true_type;
|
||||
|
||||
CustomAllocator() = default;
|
||||
|
||||
CustomAllocator(const CustomAllocator& other)
|
||||
: std::allocator<T>(other) { }
|
||||
|
||||
template<typename U>
|
||||
CustomAllocator(const CustomAllocator<U>&) { }
|
||||
|
||||
~CustomAllocator() = default;
|
||||
|
||||
using std::allocator<T>::address;
|
||||
using std::allocator<T>::allocate;
|
||||
using std::allocator<T>::construct;
|
||||
using std::allocator<T>::deallocate;
|
||||
using std::allocator<T>::max_size;
|
||||
using std::allocator<T>::destroy;
|
||||
};
|
||||
|
||||
TEST_CASE("Vector matchers", "[matchers][vector]") {
|
||||
std::vector<int> v;
|
||||
v.push_back(1);
|
||||
@ -234,19 +270,35 @@ namespace { namespace MatchersTests {
|
||||
v4.push_back(2 + 1e-8);
|
||||
v4.push_back(3 + 1e-8);
|
||||
|
||||
std::vector<int, CustomAllocator<int>> v5;
|
||||
v5.push_back(1);
|
||||
v5.push_back(2);
|
||||
v5.push_back(3);
|
||||
|
||||
std::vector<int, CustomAllocator<int>> v6;
|
||||
v6.push_back(1);
|
||||
v6.push_back(2);
|
||||
|
||||
std::vector<int> empty;
|
||||
|
||||
SECTION("Contains (element)") {
|
||||
CHECK_THAT(v, VectorContains(1));
|
||||
CHECK_THAT(v, VectorContains(2));
|
||||
CHECK_THAT(v5, (VectorContains<int, CustomAllocator<int>>(2)));
|
||||
}
|
||||
SECTION("Contains (vector)") {
|
||||
CHECK_THAT(v, Contains(v2));
|
||||
CHECK_THAT(v, Contains<int>({ 1, 2 }));
|
||||
CHECK_THAT(v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)));
|
||||
|
||||
v2.push_back(3); // now exactly matches
|
||||
CHECK_THAT(v, Contains(v2));
|
||||
|
||||
CHECK_THAT(v, Contains(empty));
|
||||
CHECK_THAT(empty, Contains(empty));
|
||||
|
||||
CHECK_THAT(v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)));
|
||||
CHECK_THAT(v5, Contains(v6));
|
||||
}
|
||||
SECTION("Contains (element), composed") {
|
||||
CHECK_THAT(v, VectorContains(1) && VectorContains(2));
|
||||
@ -256,15 +308,21 @@ namespace { namespace MatchersTests {
|
||||
|
||||
// Same vector
|
||||
CHECK_THAT(v, Equals(v));
|
||||
|
||||
CHECK_THAT(empty, Equals(empty));
|
||||
|
||||
// Different vector with same elements
|
||||
CHECK_THAT(v, Equals<int>({ 1, 2, 3 }));
|
||||
v2.push_back(3);
|
||||
CHECK_THAT(v, Equals(v2));
|
||||
|
||||
CHECK_THAT(v5, (Equals<int, std::allocator<int>, CustomAllocator<int>>(v2)));
|
||||
|
||||
v6.push_back(3);
|
||||
CHECK_THAT(v5, Equals(v6));
|
||||
}
|
||||
SECTION("UnorderedEquals") {
|
||||
CHECK_THAT(v, UnorderedEquals(v));
|
||||
CHECK_THAT(v, UnorderedEquals<int>({ 3, 2, 1 }));
|
||||
CHECK_THAT(empty, UnorderedEquals(empty));
|
||||
|
||||
auto permuted = v;
|
||||
@ -273,6 +331,12 @@ namespace { namespace MatchersTests {
|
||||
|
||||
std::reverse(begin(permuted), end(permuted));
|
||||
REQUIRE_THAT(permuted, UnorderedEquals(v));
|
||||
|
||||
CHECK_THAT(v5, (UnorderedEquals<int, std::allocator<int>, CustomAllocator<int>>(permuted)));
|
||||
|
||||
auto v5_permuted = v5;
|
||||
std::next_permutation(begin(v5_permuted), end(v5_permuted));
|
||||
CHECK_THAT(v5_permuted, UnorderedEquals(v5));
|
||||
}
|
||||
}
|
||||
|
||||
@ -518,6 +582,7 @@ namespace { namespace MatchersTests {
|
||||
std::vector<double> v1({1., 2., 3.});
|
||||
SECTION("A vector is approx equal to itself") {
|
||||
REQUIRE_THAT(v1, Approx(v1));
|
||||
REQUIRE_THAT(v1, Approx<double>({ 1., 2., 3. }));
|
||||
}
|
||||
std::vector<double> v2({1.5, 2.5, 3.5});
|
||||
SECTION("Different length") {
|
||||
@ -553,6 +618,16 @@ namespace { namespace MatchersTests {
|
||||
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, Message("SpecialException::what"));
|
||||
}
|
||||
|
||||
TEST_CASE("Composed matchers are distinct", "[matchers][composed]") {
|
||||
auto m1 = Contains("string");
|
||||
auto m2 = Contains("random");
|
||||
auto composed1 = m1 || m2;
|
||||
auto m3 = Contains("different");
|
||||
auto composed2 = composed1 || m3;
|
||||
REQUIRE_THAT(testStringForMatching2(), !composed1);
|
||||
REQUIRE_THAT(testStringForMatching2(), composed2);
|
||||
}
|
||||
|
||||
} } // namespace MatchersTests
|
||||
|
||||
#endif // CATCH_CONFIG_DISABLE_MATCHERS
|
||||
|
@ -9,12 +9,12 @@
|
||||
// We need 2 types with non-trivial copies/moves
|
||||
struct MyType1 {
|
||||
MyType1() = default;
|
||||
MyType1(MyType1 const&) { throw 1; }
|
||||
[[noreturn]] MyType1(MyType1 const&) { throw 1; }
|
||||
MyType1& operator=(MyType1 const&) { throw 3; }
|
||||
};
|
||||
struct MyType2 {
|
||||
MyType2() = default;
|
||||
MyType2(MyType2 const&) { throw 2; }
|
||||
[[noreturn]] MyType2(MyType2 const&) { throw 2; }
|
||||
MyType2& operator=(MyType2 const&) { throw 4; }
|
||||
};
|
||||
|
||||
|
@ -17,9 +17,9 @@ TEST_CASE( "vector<string> -> toString", "[toString][vector]" )
|
||||
{
|
||||
std::vector<std::string> vv;
|
||||
REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" );
|
||||
vv.push_back( "hello" );
|
||||
vv.emplace_back( "hello" );
|
||||
REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\" }" );
|
||||
vv.push_back( "world" );
|
||||
vv.emplace_back( "world" );
|
||||
REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" );
|
||||
}
|
||||
|
||||
@ -83,4 +83,4 @@ TEST_CASE( "array<int, N> -> toString", "[toString][containers][array]" ) {
|
||||
REQUIRE( Catch::Detail::stringify( oneValue ) == "{ 42 }" );
|
||||
std::array<int, 2> twoValues = {{ 42, 250 }};
|
||||
REQUIRE( Catch::Detail::stringify( twoValues ) == "{ 42, 250 }" );
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
|
59
projects/TestScripts/testRandomOrder.py
Executable file
59
projects/TestScripts/testRandomOrder.py
Executable file
@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
This test script verifies that the random ordering of tests inside
|
||||
Catch2 is invariant in regards to subsetting. This is done by running
|
||||
the binary 3 times, once with all tests selected, and twice with smaller
|
||||
subsets of tests selected, and verifying that the selected tests are in
|
||||
the same relative order.
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import random
|
||||
|
||||
def list_tests(self_test_exe, tags, rng_seed):
|
||||
cmd = [self_test_exe, '--list-test-names-only', '--order', 'rand',
|
||||
'--rng-seed', str(rng_seed)]
|
||||
tags_arg = ','.join('[{}]'.format(t) for t in tags)
|
||||
if tags_arg:
|
||||
cmd.append(tags_arg + '~[.]')
|
||||
process = subprocess.Popen(
|
||||
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = process.communicate()
|
||||
if stderr:
|
||||
raise RuntimeError("Unexpected error output:\n" + process.stderr)
|
||||
result = stdout.split(b'\n')
|
||||
result = [s for s in result if s]
|
||||
if len(result) < 2:
|
||||
raise RuntimeError("Unexpectedly few tests listed (got {})".format(
|
||||
len(result)))
|
||||
return result
|
||||
|
||||
def check_is_sublist_of(shorter, longer):
|
||||
assert len(shorter) < len(longer)
|
||||
assert len(set(longer)) == len(longer)
|
||||
|
||||
indexes_in_longer = {s: i for i, s in enumerate(longer)}
|
||||
for s1, s2 in zip(shorter, shorter[1:]):
|
||||
assert indexes_in_longer[s1] < indexes_in_longer[s2], (
|
||||
'{} comes before {} in longer list.\n'
|
||||
'Longer: {}\nShorter: {}'.format(s2, s1, longer, shorter))
|
||||
|
||||
def main():
|
||||
self_test_exe, = sys.argv[1:]
|
||||
|
||||
# We want a random seed for the test, but want to avoid 0,
|
||||
# because it has special meaning
|
||||
seed = random.randint(1, 2 ** 32 - 1)
|
||||
|
||||
list_one_tag = list_tests(self_test_exe, ['generators'], seed)
|
||||
list_two_tags = list_tests(self_test_exe, ['generators', 'matchers'], seed)
|
||||
list_all = list_tests(self_test_exe, [], seed)
|
||||
|
||||
# First, verify that restricting to a subset yields the same order
|
||||
check_is_sublist_of(list_two_tags, list_all)
|
||||
check_is_sublist_of(list_one_tag, list_two_tags)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
import releaseCommon
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Execute this script any time you import a new copy of Clara into the third_party area
|
||||
import os
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# extractFeaturesFromReleaseNotes.py
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
import os
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
@ -23,6 +23,7 @@ def generate(v):
|
||||
blankParser = re.compile( r'^\s*$')
|
||||
|
||||
seenHeaders = set([])
|
||||
possibleHeaders = set([])
|
||||
rootPath = os.path.join( catchPath, 'include/' )
|
||||
outputPath = os.path.join( catchPath, 'single_include/catch2/catch.hpp' )
|
||||
|
||||
@ -52,8 +53,20 @@ def generate(v):
|
||||
if globals['includeImpl'] or globals['implIfDefs'] == -1:
|
||||
out.write( line )
|
||||
|
||||
def getDirsToSearch( ):
|
||||
return [os.path.join( rootPath, s) for s in ['', 'internal', 'reporters', 'internal/benchmark', 'internal/benchmark/detail']]
|
||||
|
||||
def collectPossibleHeaders():
|
||||
dirs = getDirsToSearch()
|
||||
for dir in dirs:
|
||||
hpps = glob(os.path.join(dir, '*.hpp'))
|
||||
hs = glob(os.path.join(dir, '*.h'))
|
||||
possibleHeaders.update( hpp.rpartition( os.sep )[2] for hpp in hpps )
|
||||
possibleHeaders.update( h.rpartition( os.sep )[2] for h in hs )
|
||||
|
||||
|
||||
def insertCpps():
|
||||
dirs = [os.path.join( rootPath, s) for s in ['', 'internal', 'reporters', 'internal/benchmark', 'internal/benchmark/detail']]
|
||||
dirs = getDirsToSearch()
|
||||
cppFiles = []
|
||||
for dir in dirs:
|
||||
cppFiles += glob(os.path.join(dir, '*.cpp'))
|
||||
@ -103,6 +116,13 @@ def generate(v):
|
||||
write( line.rstrip() + "\n" )
|
||||
write( u'// end {}\n'.format(filename) )
|
||||
|
||||
def warnUnparsedHeaders():
|
||||
unparsedHeaders = possibleHeaders.difference( seenHeaders )
|
||||
# These headers aren't packaged into the unified header, exclude them from any warning
|
||||
whitelist = ['catch.hpp', 'catch_reporter_teamcity.hpp', 'catch_with_main.hpp', 'catch_reporter_automake.hpp', 'catch_reporter_tap.hpp', 'catch_reporter_sonarqube.hpp']
|
||||
unparsedHeaders = unparsedHeaders.difference( whitelist )
|
||||
if unparsedHeaders:
|
||||
print( "WARNING: unparsed headers detected\n{0}\n".format( unparsedHeaders ) )
|
||||
|
||||
write( u"/*\n" )
|
||||
write( u" * Catch v{0}\n".format( v.getVersionString() ) )
|
||||
@ -117,11 +137,13 @@ def generate(v):
|
||||
write( u"#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
|
||||
write( u"#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
|
||||
|
||||
collectPossibleHeaders()
|
||||
parseFile( rootPath, 'catch.hpp' )
|
||||
warnUnparsedHeaders()
|
||||
|
||||
write( u"#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" )
|
||||
out.close()
|
||||
print ("Generated single include for Catch v{0}\n".format( v.getVersionString() ) )
|
||||
print( "Generated single include for Catch v{0}\n".format( v.getVersionString() ) )
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
import releaseCommon
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
import releaseCommon
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
import releaseCommon
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# updateDocumentToC.py
|
||||
|
@ -1,16 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
import os
|
||||
import urllib2
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
|
||||
|
||||
from scriptCommon import catchPath
|
||||
|
||||
def upload(options):
|
||||
request = urllib2.Request('http://melpon.org/wandbox/api/compile.json')
|
||||
request.add_header('Content-Type', 'application/json')
|
||||
response = urllib2.urlopen(request, json.dumps(options))
|
||||
return json.loads(response.read())
|
||||
# request_blah = urllib.request.Request('https://
|
||||
|
||||
request = urllib.request.Request('https://melpon.org/wandbox/api/compile.json', method='POST')
|
||||
json_bytes = json.dumps(options).encode('utf-8')
|
||||
request.add_header('Content-Type', 'application/json; charset=utf-8')
|
||||
request.add_header('Content-Length', len(json_bytes))
|
||||
response = urllib.request.urlopen(request, json_bytes)
|
||||
return json.loads(response.read().decode('utf-8'))
|
||||
|
||||
main_file = '''
|
||||
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
|
||||
|
File diff suppressed because it is too large
Load Diff
181
single_include/catch2/catch_reporter_sonarqube.hpp
Normal file
181
single_include/catch2/catch_reporter_sonarqube.hpp
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Created by Daniel Garcia on 2018-12-04.
|
||||
* Copyright Social Point SL. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
|
||||
#define CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
|
||||
|
||||
|
||||
// Don't #include any Catch headers here - we can assume they are already
|
||||
// included before this header.
|
||||
// This is not good practice in general but is necessary in this case so this
|
||||
// file can be distributed as a single header that works with the main
|
||||
// Catch single header.
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct SonarQubeReporter : CumulativeReporterBase<SonarQubeReporter> {
|
||||
|
||||
SonarQubeReporter(ReporterConfig const& config)
|
||||
: CumulativeReporterBase(config)
|
||||
, xml(config.stream()) {
|
||||
m_reporterPrefs.shouldRedirectStdOut = true;
|
||||
m_reporterPrefs.shouldReportAllAssertions = true;
|
||||
}
|
||||
|
||||
~SonarQubeReporter() override;
|
||||
|
||||
static std::string getDescription() {
|
||||
return "Reports test results in the Generic Test Data SonarQube XML format";
|
||||
}
|
||||
|
||||
static std::set<Verbosity> getSupportedVerbosities() {
|
||||
return { Verbosity::Normal };
|
||||
}
|
||||
|
||||
void noMatchingTestCases(std::string const& /*spec*/) override {}
|
||||
|
||||
void testRunStarting(TestRunInfo const& testRunInfo) override {
|
||||
CumulativeReporterBase::testRunStarting(testRunInfo);
|
||||
xml.startElement("testExecutions");
|
||||
xml.writeAttribute("version", "1");
|
||||
}
|
||||
|
||||
void testGroupEnded(TestGroupStats const& testGroupStats) override {
|
||||
CumulativeReporterBase::testGroupEnded(testGroupStats);
|
||||
writeGroup(*m_testGroups.back());
|
||||
}
|
||||
|
||||
void testRunEndedCumulative() override {
|
||||
xml.endElement();
|
||||
}
|
||||
|
||||
void writeGroup(TestGroupNode const& groupNode) {
|
||||
std::map<std::string, TestGroupNode::ChildNodes> testsPerFile;
|
||||
for(auto const& child : groupNode.children)
|
||||
testsPerFile[child->value.testInfo.lineInfo.file].push_back(child);
|
||||
|
||||
for(auto const& kv : testsPerFile)
|
||||
writeTestFile(kv.first.c_str(), kv.second);
|
||||
}
|
||||
|
||||
void writeTestFile(const char* filename, TestGroupNode::ChildNodes const& testCaseNodes) {
|
||||
XmlWriter::ScopedElement e = xml.scopedElement("file");
|
||||
xml.writeAttribute("path", filename);
|
||||
|
||||
for(auto const& child : testCaseNodes)
|
||||
writeTestCase(*child);
|
||||
}
|
||||
|
||||
void writeTestCase(TestCaseNode const& testCaseNode) {
|
||||
// All test cases have exactly one section - which represents the
|
||||
// test case itself. That section may have 0-n nested sections
|
||||
assert(testCaseNode.children.size() == 1);
|
||||
SectionNode const& rootSection = *testCaseNode.children.front();
|
||||
writeSection("", rootSection, testCaseNode.value.testInfo.okToFail());
|
||||
}
|
||||
|
||||
void writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail) {
|
||||
std::string name = trim(sectionNode.stats.sectionInfo.name);
|
||||
if(!rootName.empty())
|
||||
name = rootName + '/' + name;
|
||||
|
||||
if(!sectionNode.assertions.empty() || !sectionNode.stdOut.empty() || !sectionNode.stdErr.empty()) {
|
||||
XmlWriter::ScopedElement e = xml.scopedElement("testCase");
|
||||
xml.writeAttribute("name", name);
|
||||
xml.writeAttribute("duration", static_cast<long>(sectionNode.stats.durationInSeconds * 1000));
|
||||
|
||||
writeAssertions(sectionNode, okToFail);
|
||||
}
|
||||
|
||||
for(auto const& childNode : sectionNode.childSections)
|
||||
writeSection(name, *childNode, okToFail);
|
||||
}
|
||||
|
||||
void writeAssertions(SectionNode const& sectionNode, bool okToFail) {
|
||||
for(auto const& assertion : sectionNode.assertions)
|
||||
writeAssertion( assertion, okToFail);
|
||||
}
|
||||
|
||||
void writeAssertion(AssertionStats const& stats, bool okToFail) {
|
||||
AssertionResult const& result = stats.assertionResult;
|
||||
if(!result.isOk()) {
|
||||
std::string elementName;
|
||||
if(okToFail) {
|
||||
elementName = "skipped";
|
||||
}
|
||||
else {
|
||||
switch(result.getResultType()) {
|
||||
case ResultWas::ThrewException:
|
||||
case ResultWas::FatalErrorCondition:
|
||||
elementName = "error";
|
||||
break;
|
||||
case ResultWas::ExplicitFailure:
|
||||
elementName = "failure";
|
||||
break;
|
||||
case ResultWas::ExpressionFailed:
|
||||
elementName = "failure";
|
||||
break;
|
||||
case ResultWas::DidntThrowException:
|
||||
elementName = "failure";
|
||||
break;
|
||||
|
||||
// We should never see these here:
|
||||
case ResultWas::Info:
|
||||
case ResultWas::Warning:
|
||||
case ResultWas::Ok:
|
||||
case ResultWas::Unknown:
|
||||
case ResultWas::FailureBit:
|
||||
case ResultWas::Exception:
|
||||
elementName = "internalError";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XmlWriter::ScopedElement e = xml.scopedElement(elementName);
|
||||
|
||||
ReusableStringStream messageRss;
|
||||
messageRss << result.getTestMacroName() << "(" << result.getExpression() << ")";
|
||||
xml.writeAttribute("message", messageRss.str());
|
||||
|
||||
ReusableStringStream textRss;
|
||||
if (stats.totals.assertions.total() > 0) {
|
||||
textRss << "FAILED:\n";
|
||||
if (result.hasExpression()) {
|
||||
textRss << "\t" << result.getExpressionInMacro() << "\n";
|
||||
}
|
||||
if (result.hasExpandedExpression()) {
|
||||
textRss << "with expansion:\n\t" << result.getExpandedExpression() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if(!result.getMessage().empty())
|
||||
textRss << result.getMessage() << "\n";
|
||||
|
||||
for(auto const& msg : stats.infoMessages)
|
||||
if(msg.type == ResultWas::Info)
|
||||
textRss << msg.message << "\n";
|
||||
|
||||
textRss << "at " << result.getSourceInfo();
|
||||
xml.writeText(textRss.str(), XmlFormatting::Newline);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
XmlWriter xml;
|
||||
};
|
||||
|
||||
#ifdef CATCH_IMPL
|
||||
SonarQubeReporter::~SonarQubeReporter() {}
|
||||
#endif
|
||||
|
||||
CATCH_REGISTER_REPORTER( "sonarqube", SonarQubeReporter )
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
|
Reference in New Issue
Block a user