mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-19 03:15:40 +02:00
Compare commits
85 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
87b745da66 | ||
![]() |
7d0b205564 | ||
![]() |
8fb1219013 | ||
![]() |
23c80bcc92 | ||
![]() |
a2c8dce85c | ||
![]() |
1e379de9d7 | ||
![]() |
4eea438b73 | ||
![]() |
407ee0af2f | ||
![]() |
060a41ec7b | ||
![]() |
90825a4f7a | ||
![]() |
9e8ae7d470 | ||
![]() |
84856844e1 | ||
![]() |
01ef7076f5 | ||
![]() |
ae14a47360 | ||
![]() |
f2b23db6d1 | ||
![]() |
1aa98c76ac | ||
![]() |
3195c242c2 | ||
![]() |
31906d83ec | ||
![]() |
91fa55303b | ||
![]() |
7c9f92bc1c | ||
![]() |
a92a7d0229 | ||
![]() |
e4d61e4cd8 | ||
![]() |
9ba48e2c9b | ||
![]() |
2cc0c71856 | ||
![]() |
28663fb959 | ||
![]() |
d2d418a9cb | ||
![]() |
c8db4e77c4 | ||
![]() |
1c5749669e | ||
![]() |
3109add95c | ||
![]() |
adb4789136 | ||
![]() |
75200e199e | ||
![]() |
a5a22cdadb | ||
![]() |
535da5c513 | ||
![]() |
2331249a8d | ||
![]() |
319cb9e1da | ||
![]() |
b8b765d55e | ||
![]() |
a0ebd63806 | ||
![]() |
4bd2c3ad6a | ||
![]() |
c38a5caa2e | ||
![]() |
ebc5609484 | ||
![]() |
fcda35f645 | ||
![]() |
02ee130bd0 | ||
![]() |
815f99541d | ||
![]() |
da0062f7c1 | ||
![]() |
de42f8a93e | ||
![]() |
af84f1350e | ||
![]() |
fc2066bf18 | ||
![]() |
2bcff9dd35 | ||
![]() |
3beccfb429 | ||
![]() |
af8b2538a6 | ||
![]() |
a156440b19 | ||
![]() |
dab0296b64 | ||
![]() |
9f4c4777a5 | ||
![]() |
293012a002 | ||
![]() |
e2b3443fe7 | ||
![]() |
7b865daccc | ||
![]() |
14362533bb | ||
![]() |
a5bb3e3d91 | ||
![]() |
923db16322 | ||
![]() |
fbbaadb704 | ||
![]() |
dd1f0f1c72 | ||
![]() |
d27d580d0b | ||
![]() |
6da00c1b64 | ||
![]() |
fe967b1f41 | ||
![]() |
f2c2711bdc | ||
![]() |
b77ab74b72 | ||
![]() |
4038ee6bc6 | ||
![]() |
789f3591ef | ||
![]() |
6e8d769775 | ||
![]() |
1189a73be2 | ||
![]() |
071bacad5e | ||
![]() |
addf799040 | ||
![]() |
155274f0df | ||
![]() |
18d597cf10 | ||
![]() |
6629c11ef8 | ||
![]() |
c6bf56b3d5 | ||
![]() |
623e348d9e | ||
![]() |
46f767e602 | ||
![]() |
ce42deb72f | ||
![]() |
46a70071a7 | ||
![]() |
378cc1a670 | ||
![]() |
e2d863b090 | ||
![]() |
ebe6a07c23 | ||
![]() |
edcfd7fc62 | ||
![]() |
738818ae1d |
12
.travis.yml
12
.travis.yml
@@ -9,8 +9,8 @@ common_sources: &all_sources
|
||||
- llvm-toolchain-trusty
|
||||
- llvm-toolchain-trusty-3.9
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- llvm-toolchain-trusty-5.0
|
||||
- llvm-toolchain-trusty-6.0
|
||||
- llvm-toolchain-xenial-5.0
|
||||
- llvm-toolchain-xenial-6.0
|
||||
|
||||
matrix:
|
||||
include:
|
||||
@@ -60,6 +60,7 @@ matrix:
|
||||
env: COMPILER='clang++-4.0'
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
@@ -68,6 +69,7 @@ matrix:
|
||||
env: COMPILER='clang++-5.0'
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
@@ -153,6 +155,7 @@ matrix:
|
||||
env: COMPILER='clang++-4.0' CPP14=1
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
@@ -161,6 +164,7 @@ matrix:
|
||||
env: COMPILER='clang++-5.0' CPP14=1
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
@@ -255,6 +259,7 @@ matrix:
|
||||
env: COMPILER='g++-7' EXAMPLES=1 COVERAGE=1 EXTRAS=1 CPP17=1
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
@@ -263,6 +268,7 @@ matrix:
|
||||
env: COMPILER='clang++-6.0' CPP17=1
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
@@ -276,7 +282,7 @@ matrix:
|
||||
- "3.7"
|
||||
dist: xenial
|
||||
install:
|
||||
- pip install conan conan-package-tools
|
||||
- pip install conan-package-tools
|
||||
env:
|
||||
- CONAN_GCC_VERSIONS=8
|
||||
- CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||
|
@@ -6,12 +6,16 @@ if(NOT DEFINED PROJECT_NAME)
|
||||
set(NOT_SUBPROJECT ON)
|
||||
endif()
|
||||
|
||||
project(Catch2 LANGUAGES CXX VERSION 2.9.2)
|
||||
|
||||
if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
# Catch2's build breaks if done in-tree. You probably should not build
|
||||
# things in tree anyway, but we can allow projects that include Catch2
|
||||
# as a subproject to build in-tree as long as it is not in our tree.
|
||||
if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
message(FATAL_ERROR "Building in-source is not supported! Create a build dir and remove ${CMAKE_SOURCE_DIR}/CMakeCache.txt")
|
||||
endif()
|
||||
|
||||
|
||||
project(Catch2 LANGUAGES CXX VERSION 2.10.2)
|
||||
|
||||
# Provide path for scripts
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
||||
|
||||
@@ -92,6 +96,10 @@ target_include_directories(Catch2
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
if (ANDROID)
|
||||
target_link_libraries(Catch2 INTERFACE log)
|
||||
endif()
|
||||
|
||||
# provide a namespaced alias for clients to 'link' against if catch is included as a sub-project
|
||||
add_library(Catch2::Catch2 ALIAS Catch2)
|
||||
|
||||
|
@@ -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/8YrGVqYqqSC4Sc5R)
|
||||
[](https://wandbox.org/permlink/LzYWgcPrcy9yQmed)
|
||||
[](https://discord.gg/4CWS9zD)
|
||||
|
||||
|
||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.9.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.10.2/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||
|
||||
## Catch2 is released!
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 10 KiB |
Binary file not shown.
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 33 KiB |
Binary file not shown.
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 20 KiB |
@@ -99,6 +99,7 @@ exclude:notThis Matches all tests except, 'notThis'
|
||||
~*private* Matches all tests except those that contain 'private'
|
||||
a* ~ab* abc Matches all tests that start with 'a', except those that
|
||||
start with 'ab', except 'abc', which is included
|
||||
-# [#somefile] Matches all tests from the file 'somefile.cpp'
|
||||
</pre>
|
||||
|
||||
Names within square brackets are interpreted as tags.
|
||||
|
@@ -17,3 +17,4 @@ 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)
|
||||
|
@@ -155,6 +155,10 @@ by using `_NO_` in the macro, e.g. `CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS`.
|
||||
CATCH_CONFIG_EXPERIMENTAL_REDIRECT // Enables the new (experimental) way of capturing stdout/stderr
|
||||
CATCH_CONFIG_ENABLE_BENCHMARKING // Enables the integrated benchmarking features (has a significant effect on compilation speed)
|
||||
CATCH_CONFIG_USE_ASYNC // Force parallel statistical processing of samples during benchmarking
|
||||
CATCH_CONFIG_ANDROID_LOGWRITE // Use android's logging system for debug output
|
||||
CATCH_CONFIG_GLOBAL_NEXTAFTER // Use nextafter{,f,l} instead of std::nextafter
|
||||
|
||||
> [`CATCH_CONFIG_ANDROID_LOGWRITE`](https://github.com/catchorg/Catch2/issues/1743) and [`CATCH_CONFIG_GLOBAL_NEXTAFTER`](https://github.com/catchorg/Catch2/pull/1739) were introduced in Catch 2.10.0
|
||||
|
||||
Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support.
|
||||
|
||||
|
@@ -70,6 +70,10 @@ locally takes just a few minutes.
|
||||
$ cd debug-build
|
||||
$ ctest -j 2 --output-on-failure
|
||||
```
|
||||
__Note:__ When running your tests with multi-configuration generators like
|
||||
Visual Studio, you might get errors "Test not available without configuration."
|
||||
You then have to pick one configuration (e.g. ` -C Debug`) in the `ctest` call.
|
||||
|
||||
If you added new tests, approval tests are very likely to fail. If they
|
||||
do not, it means that your changes weren't run as part of them. This
|
||||
_might_ be intentional, but usually is not.
|
||||
|
@@ -39,6 +39,11 @@ apart from writing it out for `--list-tests -v high`.
|
||||
Because it isn't actually used nor documented, and brings complications
|
||||
to Catch2's internals, description support will be removed.
|
||||
|
||||
### SourceLineInfo::empty()
|
||||
|
||||
There should be no reason to ever have an empty `SourceLineInfo`, so the
|
||||
method will be removed.
|
||||
|
||||
|
||||
## Planned changes
|
||||
|
||||
|
@@ -36,8 +36,8 @@ Catch2's provided generator functionality consists of three parts,
|
||||
* `GENERATE` macro, that serves to integrate generator expression with
|
||||
a test case,
|
||||
* 2 fundamental generators
|
||||
* `ValueGenerator<T>` -- contains only single element
|
||||
* `ValuesGenerator<T>` -- contains multiple elements
|
||||
* `SingleValueGenerator<T>` -- contains only single element
|
||||
* `FixedValuesGenerator<T>` -- contains multiple elements
|
||||
* 5 generic generators that modify other generators
|
||||
* `FilterGenerator<T, Predicate>` -- filters out elements from a generator
|
||||
for which the predicate returns "false"
|
||||
@@ -46,18 +46,22 @@ a test case,
|
||||
* `MapGenerator<T, U, Func>` -- returns the result of applying `Func`
|
||||
on elements from a different generator
|
||||
* `ChunkGenerator<T>` -- returns chunks (inside `std::vector`) of n elements from a generator
|
||||
* 3 specific purpose generators
|
||||
* 4 specific purpose generators
|
||||
* `RandomIntegerGenerator<Integral>` -- generates random Integrals from range
|
||||
* `RandomFloatGenerator<Float>` -- generates random Floats from range
|
||||
* `RangeGenerator<T>` -- generates all values inside a specific range
|
||||
* `IteratorGenerator<T>` -- copies and returns values from an iterator range
|
||||
|
||||
> `ChunkGenerator<T>`, `RandomIntegerGenerator<Integral>`, `RandomFloatGenerator<Float>` and `RangeGenerator<T>` were introduced in Catch 2.7.0.
|
||||
|
||||
> `IteratorGenerator<T>` was introduced in Catch 2.10.0.
|
||||
|
||||
The generators also have associated helper functions that infer their
|
||||
type, making their usage much nicer. These are
|
||||
|
||||
* `value(T&&)` for `ValueGenerator<T>`
|
||||
* `values(std::initializer_list<T>)` for `ValuesGenerator<T>`
|
||||
* `value(T&&)` for `SingleValueGenerator<T>`
|
||||
* `values(std::initializer_list<T>)` for `FixedValuesGenerator<T>`
|
||||
* `table<Ts...>(std::initializer_list<std::tuple<Ts...>>)` for `FixedValuesGenerator<std::tuple<Ts...>>`
|
||||
* `filter(predicate, GeneratorWrapper<T>&&)` for `FilterGenerator<T, Predicate>`
|
||||
* `take(count, GeneratorWrapper<T>&&)` for `TakeGenerator<T>`
|
||||
* `repeat(repeats, GeneratorWrapper<T>&&)` for `RepeatGenerator<T>`
|
||||
@@ -67,9 +71,13 @@ type, making their usage much nicer. These are
|
||||
* `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator`
|
||||
* `range(start, end)` for `RangeGenerator<T>` with a step size of `1`
|
||||
* `range(start, end, step)` for `RangeGenerator<T>` with a custom step size
|
||||
* `from_range(InputIterator from, InputIterator to)` for `IteratorGenerator<T>`
|
||||
* `from_range(Container const&)` for `IteratorGenerator<T>`
|
||||
|
||||
> `chunk()`, `random()` and both `range()` functions were introduced in Catch 2.7.0.
|
||||
|
||||
> `from_range` has been introduced in Catch 2.10.0
|
||||
|
||||
And can be used as shown in the example below to create a generator
|
||||
that returns 100 odd random number:
|
||||
|
||||
@@ -89,7 +97,7 @@ Apart from registering generators with Catch2, the `GENERATE` macro has
|
||||
one more purpose, and that is to provide simple way of generating trivial
|
||||
generators, as seen in the first example on this page, where we used it
|
||||
as `auto i = GENERATE(1, 2, 3);`. This usage converted each of the three
|
||||
literals into a single `ValueGenerator<int>` and then placed them all in
|
||||
literals into a single `SingleValueGenerator<int>` and then placed them all in
|
||||
a special generator that concatenates other generators. It can also be
|
||||
used with other generators as arguments, such as `auto i = GENERATE(0, 2,
|
||||
take(100, random(300, 3000)));`. This is useful e.g. if you know that
|
||||
|
@@ -45,6 +45,15 @@ the `REQUIRE` family of macros), Catch2 does not know that there are no
|
||||
more sections in that test case and must run the test case again.
|
||||
|
||||
|
||||
### MinGW/CygWin compilation (linking) is extremely slow
|
||||
|
||||
Compiling Catch2 with MinGW can be exceedingly slow, especially during
|
||||
the linking step. As far as we can tell, this is caused by deficiencies
|
||||
in its default linker. If you can tell MinGW to instead use lld, via
|
||||
`-fuse-ld=lld`, the link time should drop down to reasonable length
|
||||
again.
|
||||
|
||||
|
||||
## Features
|
||||
This section outlines some missing features, what is their status and their possible workarounds.
|
||||
|
||||
|
@@ -12,11 +12,11 @@ The first argument is the thing (object or value) under test. The second part is
|
||||
which consists of either a single matcher or one or more matchers combined using `&&`, `||` or `!` operators.
|
||||
|
||||
For example, to assert that a string ends with a certain substring:
|
||||
|
||||
|
||||
```c++
|
||||
using Catch::Matchers::EndsWith; // or Catch::EndsWith
|
||||
std::string str = getStringFromSomewhere();
|
||||
REQUIRE_THAT( str, EndsWith( "as a service" ) );
|
||||
REQUIRE_THAT( str, EndsWith( "as a service" ) );
|
||||
```
|
||||
|
||||
The matcher objects can take multiple arguments, allowing more fine tuning.
|
||||
@@ -24,19 +24,29 @@ The built-in string matchers, for example, take a second argument specifying whe
|
||||
case sensitive or not:
|
||||
|
||||
```c++
|
||||
REQUIRE_THAT( str, EndsWith( "as a service", Catch::CaseSensitive::No ) );
|
||||
REQUIRE_THAT( str, EndsWith( "as a service", Catch::CaseSensitive::No ) );
|
||||
```
|
||||
|
||||
And matchers can be combined:
|
||||
|
||||
```c++
|
||||
REQUIRE_THAT( str,
|
||||
EndsWith( "as a service" ) ||
|
||||
(StartsWith( "Big data" ) && !Contains( "web scale" ) ) );
|
||||
REQUIRE_THAT( str,
|
||||
EndsWith( "as a service" ) ||
|
||||
(StartsWith( "Big data" ) && !Contains( "web scale" ) ) );
|
||||
```
|
||||
|
||||
## Built in matchers
|
||||
Catch currently provides some matchers, they are in the `Catch::Matchers` and `Catch` namespaces.
|
||||
Catch2 provides some matchers by default. They can be found in the
|
||||
`Catch::Matchers::foo` namespace and are imported into the `Catch`
|
||||
namespace as well.
|
||||
|
||||
There are two parts to each of the built-in matchers, the matcher
|
||||
type itself and a helper function that provides template argument
|
||||
deduction when creating templated matchers. As an example, the matcher
|
||||
for checking that two instances of `std::vector` are identical is
|
||||
`EqualsMatcher<T>`, but the user is expected to use the `Equals`
|
||||
helper function instead.
|
||||
|
||||
|
||||
### String matchers
|
||||
The string matchers are `StartsWith`, `EndsWith`, `Contains`, `Equals` and `Matches`. The first four match a literal (sub)string against a result, while `Matches` takes and matches an ECMAScript regex. Do note that `Matches` matches the string as a whole, meaning that "abc" will not match against "abcd", but "abc.*" will.
|
||||
@@ -57,10 +67,30 @@ These are
|
||||
|
||||
|
||||
### Floating point matchers
|
||||
The floating point matchers are `WithinULP` and `WithinAbs`. `WithinAbs` accepts floating point numbers that are within a certain margin of target. `WithinULP` performs an [ULP](https://en.wikipedia.org/wiki/Unit_in_the_last_place)-based comparison of two floating point numbers and accepts them if they are less than certain number of ULPs apart.
|
||||
Catch2 provides 3 matchers for working with floating point numbers. These
|
||||
are `WithinAbsMatcher`, `WithinUlpsMatcher` and `WithinRelMatcher`.
|
||||
|
||||
Do note that ULP-based checks only make sense when both compared numbers are of the same type and `WithinULP` will use type of its argument as the target type. This means that `WithinULP(1.f, 1)` will expect to compare `float`s, but `WithinULP(1., 1)` will expect to compare `double`s.
|
||||
The `WithinAbsMatcher` matcher accepts floating point numbers that are
|
||||
within a certain distance of target. It should be constructed with the
|
||||
`WithinAbs(double target, double margin)` helper.
|
||||
|
||||
The `WithinUlpsMatcher` matcher accepts floating point numbers that are
|
||||
within a certain number of [ULPs](https://en.wikipedia.org/wiki/Unit_in_the_last_place)
|
||||
of the target. Because ULP comparisons need to be done differently for
|
||||
`float`s and for `double`s, there are two overloads of the helpers for
|
||||
this matcher, `WithinULP(float target, int64_t ULPs)`, and
|
||||
`WithinULP(double target, int64_t ULPs)`.
|
||||
|
||||
The `WithinRelMatcher` matcher accepts floating point numbers that are
|
||||
_approximately equal_ with the target number with some specific tolerance.
|
||||
In other words, it checks that `|lhs - rhs| <= epsilon * max(|lhs|, |rhs|)`,
|
||||
with special casing for `INFINITY` and `NaN`. There are _4_ overloads of
|
||||
the helpers for this matcher, `WithinRel(double target, double margin)`,
|
||||
`WithinRel(float target, float margin)`, `WithinRel(double target)`, and
|
||||
`WithinRel(float target)`. The latter two provide a default epsilon of
|
||||
machine epsilon * 100.
|
||||
|
||||
> `WithinRel` matcher was introduced in Catch 2.10.0
|
||||
|
||||
### Generic matchers
|
||||
Catch also aims to provide a set of generic matchers. Currently this set
|
||||
@@ -81,13 +111,29 @@ The second argument is an optional description of the predicate, and is
|
||||
used only during reporting of the result.
|
||||
|
||||
|
||||
### Exception matchers
|
||||
Catch2 also provides an exception matcher that can be used to verify
|
||||
that an exception's message exactly matches desired string. The matcher
|
||||
is `ExceptionMessageMatcher`, and we also provide a helper function
|
||||
`Message`.
|
||||
|
||||
The matched exception must publicly derive from `std::exception` and
|
||||
the message matching is done _exactly_, including case.
|
||||
|
||||
> `ExceptionMessageMatcher` was introduced in Catch 2.10.0
|
||||
|
||||
Example use:
|
||||
```cpp
|
||||
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, Message("DerivedException::what"));
|
||||
```
|
||||
|
||||
## Custom matchers
|
||||
It's easy to provide your own matchers to extend Catch or just to work with your own types.
|
||||
|
||||
You need to provide two things:
|
||||
You need to provide two things:
|
||||
1. A matcher class, derived from `Catch::MatcherBase<T>` - where `T` is the type being tested.
|
||||
The constructor takes and stores any arguments needed (e.g. something to compare against) and you must
|
||||
override two methods: `match()` and `describe()`.
|
||||
override two methods: `match()` and `describe()`.
|
||||
2. A simple builder function. This is what is actually called from the test code and allows overloading.
|
||||
|
||||
Here's an example for asserting that an integer falls within a given range
|
||||
@@ -132,7 +178,7 @@ TEST_CASE("Integers are within a range")
|
||||
```
|
||||
|
||||
Running this test gives the following in the console:
|
||||
|
||||
|
||||
```
|
||||
/**/TestFile.cpp:123: FAILED:
|
||||
CHECK_THAT( 100, IsBetween( 1, 10 ) )
|
||||
|
@@ -23,6 +23,9 @@ C++11 implementation of Approval Tests, for quick, convenient testing of legacy
|
||||
### [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.
|
||||
|
||||
@@ -50,9 +53,6 @@ Open source Oracle Tuxedo-like XATMI middleware for C and C++.
|
||||
### [Inja](https://github.com/pantor/inja)
|
||||
A header-only template engine for modern C++.
|
||||
|
||||
### [JSON for Modern C++](https://github.com/nlohmann/json)
|
||||
A, single-header, JSON parsing library that takes advantage of what C++ has to offer.
|
||||
|
||||
### [libcluon](https://github.com/chrberger/libcluon)
|
||||
A single-header-only library written in C++14 to glue distributed software components (UDP, TCP, shared memory) supporting natively Protobuf, LCM/ZCM, MsgPack, and JSON for dynamic message transformations in-between.
|
||||
|
||||
|
@@ -2,6 +2,9 @@
|
||||
|
||||
# Release notes
|
||||
**Contents**<br>
|
||||
[2.10.2](#2102)<br>
|
||||
[2.10.1](#2101)<br>
|
||||
[2.10.0](#2100)<br>
|
||||
[2.9.2](#292)<br>
|
||||
[2.9.1](#291)<br>
|
||||
[2.9.0](#290)<br>
|
||||
@@ -28,6 +31,78 @@
|
||||
[Even Older versions](#even-older-versions)<br>
|
||||
|
||||
|
||||
## 2.10.2
|
||||
|
||||
### Improvements
|
||||
* Catch2 will now compile on platform where `INFINITY` is double (#1782)
|
||||
|
||||
|
||||
### Fixes
|
||||
* Warning suppressed during listener registration will no longer leak
|
||||
|
||||
|
||||
|
||||
## 2.10.1
|
||||
|
||||
### Improvements
|
||||
* Catch2 now guards itself against `min` and `max` macros from `windows.h` (#1772)
|
||||
* Templated tests will now compile with ICC (#1748)
|
||||
* `WithinULP` matcher now uses scientific notation for stringification (#1760)
|
||||
|
||||
|
||||
### Fixes
|
||||
* Templated tests no longer trigger `-Wunused-templates` (#1762)
|
||||
* Suppressed clang-analyzer false positive in context getter (#1230, #1735)
|
||||
|
||||
|
||||
### Miscellaneous
|
||||
* CMake no longer prohibits in-tree build when Catch2 is used as a subproject (#1773, #1774)
|
||||
|
||||
|
||||
|
||||
## 2.10.0
|
||||
|
||||
### Fixes
|
||||
* `TEMPLATE_LIST_TEST_CASE` now properly handles non-copyable and non-movable types (#1729)
|
||||
* Fixed compilation error on Solaris caused by a system header defining macro `TT` (#1722, #1723)
|
||||
* `REGISTER_ENUM` will now fail at compilation time if the registered enum is too large
|
||||
* Removed use of `std::is_same_v` in C++17 mode (#1757)
|
||||
* Fixed parsing of escaped special characters when reading test specs from a file (#1767, #1769)
|
||||
|
||||
|
||||
### Improvements
|
||||
* Trailing and leading whitespace in test/section specs are now ignored.
|
||||
* Writing to Android debug log now uses `__android_log_write` instead of `__android_log_print`
|
||||
* Android logging support can now be turned on/off at compile time (#1743)
|
||||
* The toggle is `CATCH_CONFIG_ANDROID_LOGWRITE`
|
||||
* Added a generator that returns elements of a range
|
||||
* Use via `from_range(from, to)` or `from_range(container)`
|
||||
* Added support for CRTs that do not provide `std::nextafter` (#1739)
|
||||
* They must still provide global `nextafter{f,l,}`
|
||||
* Enabled via `CATCH_CONFIG_GLOBAL_NEXTAFTER`
|
||||
* Special cased `Approx(inf)` not to match non-infinite values
|
||||
* Very strictly speaking this might be a breaking change, but it should match user expectations better
|
||||
* The output of benchmarking through the Console reporter when `--benchmark-no-analysis` is set is now much simpler (#1768)
|
||||
* Added a matcher that can be used for checking an exceptions message (#1649, #1728)
|
||||
* The matcher helper function is called `Message`
|
||||
* The exception must publicly derive from `std::exception`
|
||||
* The matching is done exactly, including case and whitespace
|
||||
* Added a matcher that can be used for checking relative equality of floating point numbers (#1746)
|
||||
* Unlike `Approx`, it considers both sides when determining the allowed margin
|
||||
* Special cases `NaN` and `INFINITY` to match user expectations
|
||||
* The matcher helper function is called `WithinRel`
|
||||
* The ULP matcher now allows for any possible distance between the two numbers
|
||||
* The random number generators now use Catch-global instance of RNG (#1734, #1736)
|
||||
* This means that nested random number generators actually generate different numbers
|
||||
|
||||
|
||||
### Miscellaneous
|
||||
* In-repo PNGs have been optimized to lower overhead of using Catch2 via git clone
|
||||
* Catch2 now uses its own implementation of the URBG concept
|
||||
* In the future we also plan to use our own implementation of the distributions from `<random>` to provide cross-platform repeatability of random results
|
||||
|
||||
|
||||
|
||||
## 2.9.2
|
||||
|
||||
### Fixes
|
||||
@@ -61,6 +136,10 @@
|
||||
* Improved `*_THROWS_MATCHES` documentation a bit
|
||||
* CMake config file is now arch-independent even if `CMAKE_SIZEOF_VOID_P` is in CMake cache (#1660)
|
||||
* `CatchAddTests` now properly escapes `[` and `]` in test names (#1634, #1698)
|
||||
* Reverted `CatchAddTests` adding tags as CTest labels (#1658)
|
||||
* The script broke when test names were too long
|
||||
* Overwriting `LABELS` caused trouble for users who set them manually
|
||||
* CMake does not let users append to `LABELS` if the test name has spaces
|
||||
|
||||
|
||||
## 2.9.1
|
||||
|
@@ -10,7 +10,7 @@
|
||||
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
||||
|
||||
#define CATCH_VERSION_MAJOR 2
|
||||
#define CATCH_VERSION_MINOR 9
|
||||
#define CATCH_VERSION_MINOR 10
|
||||
#define CATCH_VERSION_PATCH 2
|
||||
|
||||
#ifdef __clang__
|
||||
|
@@ -52,7 +52,8 @@ namespace Detail {
|
||||
bool Approx::equalityComparisonImpl(const double other) const {
|
||||
// First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
|
||||
// Thanks to Richard Harris for his help refining the scaled margin value
|
||||
return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
|
||||
return marginComparison(m_value, other, m_margin)
|
||||
|| marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value)));
|
||||
}
|
||||
|
||||
void Approx::setMargin(double newMargin) {
|
||||
|
@@ -45,7 +45,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
bool AssertionResult::hasExpression() const {
|
||||
return m_info.capturedExpression[0] != 0;
|
||||
return !m_info.capturedExpression.empty();
|
||||
}
|
||||
|
||||
bool AssertionResult::hasMessage() const {
|
||||
@@ -53,16 +53,22 @@ namespace Catch {
|
||||
}
|
||||
|
||||
std::string AssertionResult::getExpression() const {
|
||||
if( isFalseTest( m_info.resultDisposition ) )
|
||||
return "!(" + m_info.capturedExpression + ")";
|
||||
else
|
||||
return m_info.capturedExpression;
|
||||
// Possibly overallocating by 3 characters should be basically free
|
||||
std::string expr; expr.reserve(m_info.capturedExpression.size() + 3);
|
||||
if (isFalseTest(m_info.resultDisposition)) {
|
||||
expr += "!(";
|
||||
}
|
||||
expr += m_info.capturedExpression;
|
||||
if (isFalseTest(m_info.resultDisposition)) {
|
||||
expr += ')';
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
std::string AssertionResult::getExpressionInMacro() const {
|
||||
std::string expr;
|
||||
if( m_info.macroName[0] == 0 )
|
||||
expr = m_info.capturedExpression;
|
||||
if( m_info.macroName.empty() )
|
||||
expr = static_cast<std::string>(m_info.capturedExpression);
|
||||
else {
|
||||
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
|
||||
expr += m_info.macroName;
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "catch_capture.hpp"
|
||||
#include "catch_matchers.h"
|
||||
#include "catch_matchers_exception.hpp"
|
||||
#include "catch_matchers_floating.h"
|
||||
#include "catch_matchers_generic.hpp"
|
||||
#include "catch_matchers_string.h"
|
||||
|
@@ -49,9 +49,15 @@ namespace Catch {
|
||||
if( !line.empty() && !startsWith( line, '#' ) ) {
|
||||
if( !startsWith( line, '"' ) )
|
||||
line = '"' + line + '"';
|
||||
config.testsOrTags.push_back( line + ',' );
|
||||
config.testsOrTags.push_back( line );
|
||||
config.testsOrTags.push_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 ) {
|
||||
|
@@ -15,9 +15,6 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
bool SourceLineInfo::empty() const noexcept {
|
||||
return file[0] == '\0';
|
||||
}
|
||||
bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {
|
||||
return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
|
||||
}
|
||||
|
@@ -57,7 +57,7 @@ namespace Catch {
|
||||
SourceLineInfo( SourceLineInfo&& ) noexcept = default;
|
||||
SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;
|
||||
|
||||
bool empty() const noexcept;
|
||||
bool empty() const noexcept { return file[0] == '\0'; }
|
||||
bool operator == ( SourceLineInfo const& other ) const noexcept;
|
||||
bool operator < ( SourceLineInfo const& other ) const noexcept;
|
||||
|
||||
|
@@ -70,6 +70,11 @@
|
||||
# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||
_Pragma( "clang diagnostic pop" )
|
||||
|
||||
# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
_Pragma( "clang diagnostic push" ) \
|
||||
_Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
|
||||
# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
_Pragma( "clang diagnostic pop" )
|
||||
#endif // __clang__
|
||||
|
||||
|
||||
@@ -94,6 +99,7 @@
|
||||
// Android somehow still does not support std::to_string
|
||||
#if defined(__ANDROID__)
|
||||
# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
|
||||
# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -115,7 +121,7 @@
|
||||
// Required for some versions of Cygwin to declare gettimeofday
|
||||
// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
|
||||
# define _BSD_SOURCE
|
||||
// some versions of cygwin (most) do not support std::to_string. Use the libstd check.
|
||||
// some versions of cygwin (most) do not support std::to_string. Use the libstd check.
|
||||
// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
|
||||
# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
|
||||
&& !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
|
||||
@@ -196,49 +202,43 @@
|
||||
#define CATCH_CONFIG_COLOUR_NONE
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Check if string_view is available and usable
|
||||
// The check is split apart to work around v140 (VS2015) preprocessor issue...
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
|
||||
#endif
|
||||
#if defined(__UCLIBC__)
|
||||
#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Check if optional is available and usable
|
||||
// Various stdlib support checks that require __has_include
|
||||
#if defined(__has_include)
|
||||
# if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
|
||||
# endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
#endif // __has_include
|
||||
// Check if string_view is available and usable
|
||||
#if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Check if byte is available and usable
|
||||
#if defined(__has_include)
|
||||
# if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE
|
||||
# endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
#endif // __has_include
|
||||
// Check if optional is available and usable
|
||||
# if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
|
||||
# endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Check if variant is available and usable
|
||||
#if defined(__has_include)
|
||||
# if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
# if defined(__clang__) && (__clang_major__ < 8)
|
||||
// work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
|
||||
// fix should be in clang 8, workaround in libstdc++ 8.2
|
||||
# include <ciso646>
|
||||
# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
|
||||
# define CATCH_CONFIG_NO_CPP17_VARIANT
|
||||
# else
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
|
||||
# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
|
||||
# else
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
|
||||
# endif // defined(__clang__) && (__clang_major__ < 8)
|
||||
# endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
#endif // __has_include
|
||||
// Check if byte is available and usable
|
||||
# if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE
|
||||
# endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
|
||||
// Check if variant is available and usable
|
||||
# if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
# if defined(__clang__) && (__clang_major__ < 8)
|
||||
// work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
|
||||
// fix should be in clang 8, workaround in libstdc++ 8.2
|
||||
# include <ciso646>
|
||||
# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
|
||||
# define CATCH_CONFIG_NO_CPP17_VARIANT
|
||||
# else
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
|
||||
# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
|
||||
# else
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
|
||||
# endif // defined(__clang__) && (__clang_major__ < 8)
|
||||
# endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
#endif // defined(__has_include)
|
||||
|
||||
|
||||
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
|
||||
@@ -301,6 +301,14 @@
|
||||
# define CATCH_CONFIG_USE_ASYNC
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE)
|
||||
# define CATCH_CONFIG_ANDROID_LOGWRITE
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
|
||||
# define CATCH_CONFIG_GLOBAL_NEXTAFTER
|
||||
#endif
|
||||
|
||||
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
|
||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
||||
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
|
||||
@@ -318,6 +326,19 @@
|
||||
# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
|
||||
# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
|
||||
# undef CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS
|
||||
#elif defined(__clang__) && (__clang_major__ < 5)
|
||||
# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
|
||||
# undef CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS
|
||||
#endif
|
||||
|
||||
#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS)
|
||||
# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
|
||||
# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||
#define CATCH_TRY if ((true))
|
||||
#define CATCH_CATCH_ALL if ((false))
|
||||
|
@@ -15,11 +15,23 @@ namespace Catch {
|
||||
: m_data( data ),
|
||||
m_stream( openStream() )
|
||||
{
|
||||
// We need to trim filter specs to avoid trouble with superfluous
|
||||
// whitespace (esp. important for bdd macros, as those are manually
|
||||
// aligned with whitespace).
|
||||
|
||||
for (auto& elem : m_data.testsOrTags) {
|
||||
elem = trim(elem);
|
||||
}
|
||||
for (auto& elem : m_data.sectionsToRun) {
|
||||
elem = trim(elem);
|
||||
}
|
||||
|
||||
TestSpecParser parser(ITagAliasRegistry::get());
|
||||
if (!data.testsOrTags.empty()) {
|
||||
if (!m_data.testsOrTags.empty()) {
|
||||
m_hasTestFilters = true;
|
||||
for( auto const& testOrTags : data.testsOrTags )
|
||||
parser.parse( testOrTags );
|
||||
for (auto const& testOrTags : m_data.testsOrTags) {
|
||||
parser.parse(testOrTags);
|
||||
}
|
||||
}
|
||||
m_testSpec = parser.testSpec();
|
||||
}
|
||||
@@ -32,7 +44,7 @@ namespace Catch {
|
||||
bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; }
|
||||
bool Config::listTags() const { return m_data.listTags; }
|
||||
bool Config::listReporters() const { return m_data.listReporters; }
|
||||
|
||||
|
||||
std::string Config::getProcessName() const { return m_data.processName; }
|
||||
std::string const& Config::getReporterName() const { return m_data.reporterName; }
|
||||
|
||||
|
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
#include "catch_context.h"
|
||||
#include "catch_common.h"
|
||||
#include "catch_random_number_generator.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -59,4 +60,11 @@ namespace Catch {
|
||||
IContext::~IContext() = default;
|
||||
IMutableContext::~IMutableContext() = default;
|
||||
Context::~Context() = default;
|
||||
|
||||
|
||||
SimplePcg32& rng() {
|
||||
static SimplePcg32 s_rng;
|
||||
return s_rng;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -46,6 +46,7 @@ namespace Catch {
|
||||
{
|
||||
if( !IMutableContext::currentContext )
|
||||
IMutableContext::createContext();
|
||||
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
|
||||
return *IMutableContext::currentContext;
|
||||
}
|
||||
|
||||
@@ -55,6 +56,9 @@ namespace Catch {
|
||||
}
|
||||
|
||||
void cleanUpContext();
|
||||
|
||||
class SimplePcg32;
|
||||
SimplePcg32& rng();
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
|
||||
|
@@ -7,16 +7,17 @@
|
||||
*/
|
||||
|
||||
#include "catch_debug_console.h"
|
||||
#include "catch_compiler_capabilities.h"
|
||||
#include "catch_stream.h"
|
||||
#include "catch_platform.h"
|
||||
#include "catch_windows_h_proxy.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#if defined(CATCH_CONFIG_ANDROID_LOGWRITE)
|
||||
#include <android/log.h>
|
||||
|
||||
namespace Catch {
|
||||
void writeToDebugConsole( std::string const& text ) {
|
||||
__android_log_print( ANDROID_LOG_DEBUG, "Catch", text.c_str() );
|
||||
__android_log_write( ANDROID_LOG_DEBUG, "Catch", text.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -38,13 +38,13 @@ namespace Catch {
|
||||
(Catch::ReusableStringStream() << __VA_ARGS__).str()
|
||||
|
||||
#define CATCH_INTERNAL_ERROR(...) \
|
||||
Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__));
|
||||
Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__))
|
||||
|
||||
#define CATCH_ERROR(...) \
|
||||
Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ ));
|
||||
Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
|
||||
|
||||
#define CATCH_RUNTIME_ERROR(...) \
|
||||
Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ ));
|
||||
Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
|
||||
|
||||
#define CATCH_ENFORCE( condition, ... ) \
|
||||
do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)
|
||||
|
@@ -18,13 +18,25 @@ namespace Catch {
|
||||
|
||||
namespace Detail {
|
||||
|
||||
std::vector<std::string> parseEnums( StringRef enums ) {
|
||||
namespace {
|
||||
// Extracts the actual name part of an enum instance
|
||||
// In other words, it returns the Blue part of Bikeshed::Colour::Blue
|
||||
StringRef extractInstanceName(StringRef enumInstance) {
|
||||
// Find last occurence of ":"
|
||||
size_t name_start = enumInstance.size();
|
||||
while (name_start > 0 && enumInstance[name_start - 1] != ':') {
|
||||
--name_start;
|
||||
}
|
||||
return enumInstance.substr(name_start, enumInstance.size() - name_start);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<StringRef> parseEnums( StringRef enums ) {
|
||||
auto enumValues = splitStringRef( enums, ',' );
|
||||
std::vector<std::string> parsed;
|
||||
std::vector<StringRef> parsed;
|
||||
parsed.reserve( enumValues.size() );
|
||||
for( auto const& enumValue : enumValues ) {
|
||||
auto identifiers = splitStringRef( enumValue, ':' );
|
||||
parsed.push_back( Catch::trim( identifiers.back() ) );
|
||||
parsed.push_back(trim(extractInstanceName(enumValue)));
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
@@ -36,7 +48,7 @@ namespace Catch {
|
||||
if( valueToName.first == value )
|
||||
return valueToName.second;
|
||||
}
|
||||
return "{** unexpected enum value **}";
|
||||
return "{** unexpected enum value **}"_sr;
|
||||
}
|
||||
|
||||
std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
|
||||
@@ -54,10 +66,8 @@ namespace Catch {
|
||||
}
|
||||
|
||||
EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
|
||||
auto enumInfo = makeEnumInfo( enumName, allValueNames, values );
|
||||
EnumInfo* raw = enumInfo.get();
|
||||
m_enumInfos.push_back( std::move( enumInfo ) );
|
||||
return *raw;
|
||||
m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));
|
||||
return *m_enumInfos.back();
|
||||
}
|
||||
|
||||
} // Detail
|
||||
|
@@ -26,7 +26,7 @@ namespace Catch {
|
||||
EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values) override;
|
||||
};
|
||||
|
||||
std::vector<std::string> parseEnums( StringRef enums );
|
||||
std::vector<StringRef> parseEnums( StringRef enums );
|
||||
|
||||
} // Detail
|
||||
|
||||
|
@@ -71,7 +71,7 @@ namespace Generators {
|
||||
template<typename T>
|
||||
class FixedValuesGenerator final : public IGenerator<T> {
|
||||
static_assert(!std::is_same<T, bool>::value,
|
||||
"ValuesGenerator does not support bools because of std::vector<bool>"
|
||||
"FixedValuesGenerator does not support bools because of std::vector<bool>"
|
||||
"specialization, use SingleValue Generator instead.");
|
||||
std::vector<T> m_values;
|
||||
size_t m_idx = 0;
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include "catch_context.h"
|
||||
#include "catch_generators.hpp"
|
||||
#include "catch_interfaces_config.h"
|
||||
#include "catch_random_number_generator.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
@@ -18,14 +19,13 @@ namespace Generators {
|
||||
|
||||
template <typename Float>
|
||||
class RandomFloatingGenerator final : public IGenerator<Float> {
|
||||
// FIXME: What is the right seed?
|
||||
std::minstd_rand m_rand;
|
||||
Catch::SimplePcg32& m_rng;
|
||||
std::uniform_real_distribution<Float> m_dist;
|
||||
Float m_current_number;
|
||||
public:
|
||||
|
||||
RandomFloatingGenerator(Float a, Float b):
|
||||
m_rand(getCurrentContext().getConfig()->rngSeed()),
|
||||
m_rng(rng()),
|
||||
m_dist(a, b) {
|
||||
static_cast<void>(next());
|
||||
}
|
||||
@@ -34,20 +34,20 @@ public:
|
||||
return m_current_number;
|
||||
}
|
||||
bool next() override {
|
||||
m_current_number = m_dist(m_rand);
|
||||
m_current_number = m_dist(m_rng);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Integer>
|
||||
class RandomIntegerGenerator final : public IGenerator<Integer> {
|
||||
std::minstd_rand m_rand;
|
||||
Catch::SimplePcg32& m_rng;
|
||||
std::uniform_int_distribution<Integer> m_dist;
|
||||
Integer m_current_number;
|
||||
public:
|
||||
|
||||
RandomIntegerGenerator(Integer a, Integer b):
|
||||
m_rand(getCurrentContext().getConfig()->rngSeed()),
|
||||
m_rng(rng()),
|
||||
m_dist(a, b) {
|
||||
static_cast<void>(next());
|
||||
}
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
return m_current_number;
|
||||
}
|
||||
bool next() override {
|
||||
m_current_number = m_dist(m_rand);
|
||||
m_current_number = m_dist(m_rng);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -128,6 +128,46 @@ GeneratorWrapper<T> range(T const& start, T const& end) {
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
class IteratorGenerator final : public IGenerator<T> {
|
||||
static_assert(!std::is_same<T, bool>::value,
|
||||
"IteratorGenerator currently does not support bools"
|
||||
"because of std::vector<bool> specialization");
|
||||
|
||||
std::vector<T> m_elems;
|
||||
size_t m_current = 0;
|
||||
public:
|
||||
template <typename InputIterator, typename InputSentinel>
|
||||
IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) {
|
||||
if (m_elems.empty()) {
|
||||
Catch::throw_exception(GeneratorException("IteratorGenerator received no valid values"));
|
||||
}
|
||||
}
|
||||
|
||||
T const& get() const override {
|
||||
return m_elems[m_current];
|
||||
}
|
||||
|
||||
bool next() override {
|
||||
++m_current;
|
||||
return m_current != m_elems.size();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename InputIterator,
|
||||
typename InputSentinel,
|
||||
typename ResultType = typename std::iterator_traits<InputIterator>::value_type>
|
||||
GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) {
|
||||
return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(from, to));
|
||||
}
|
||||
|
||||
template <typename Container,
|
||||
typename ResultType = typename Container::value_type>
|
||||
GeneratorWrapper<ResultType> from_range(Container const& cnt) {
|
||||
return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(cnt.begin(), cnt.end()));
|
||||
}
|
||||
|
||||
|
||||
} // namespace Generators
|
||||
} // namespace Catch
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#include "internal/catch_interfaces_config.h"
|
||||
#include "catch_interfaces_config.h"
|
||||
|
||||
namespace Catch {
|
||||
IConfig::~IConfig() = default;
|
||||
|
@@ -17,7 +17,7 @@ namespace Catch {
|
||||
namespace Detail {
|
||||
struct EnumInfo {
|
||||
StringRef m_name;
|
||||
std::vector<std::pair<int, std::string>> m_values;
|
||||
std::vector<std::pair<int, StringRef>> m_values;
|
||||
|
||||
~EnumInfo();
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Catch {
|
||||
|
||||
template<typename E>
|
||||
Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
|
||||
static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
|
||||
std::vector<int> intValues;
|
||||
intValues.reserve( values.size() );
|
||||
for( auto enumValue : values )
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#include "internal/catch_interfaces_exception.h"
|
||||
#include "catch_interfaces_exception.h"
|
||||
|
||||
namespace Catch {
|
||||
IExceptionTranslator::~IExceptionTranslator() = default;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#include "internal/catch_interfaces_registry_hub.h"
|
||||
#include "catch_interfaces_registry_hub.h"
|
||||
|
||||
namespace Catch {
|
||||
IRegistryHub::~IRegistryHub() = default;
|
||||
|
@@ -214,6 +214,8 @@ namespace Catch {
|
||||
|
||||
virtual void noMatchingTestCases( std::string const& spec ) = 0;
|
||||
|
||||
virtual void reportInvalidArguments(std::string const&) {}
|
||||
|
||||
virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
|
||||
virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#include "internal/catch_interfaces_runner.h"
|
||||
#include "catch_interfaces_runner.h"
|
||||
|
||||
namespace Catch {
|
||||
IRunner::~IRunner() = default;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#include "internal/catch_interfaces_testcase.h"
|
||||
#include "catch_interfaces_testcase.h"
|
||||
|
||||
namespace Catch {
|
||||
ITestInvoker::~ITestInvoker() = default;
|
||||
|
30
include/internal/catch_matchers_exception.cpp
Normal file
30
include/internal/catch_matchers_exception.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Created by Martin Hořeňovský on 13/10/2019.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include "catch_matchers_exception.hpp"
|
||||
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
namespace Exception {
|
||||
|
||||
bool ExceptionMessageMatcher::match(std::exception const& ex) const {
|
||||
return ex.what() == m_message;
|
||||
}
|
||||
|
||||
std::string ExceptionMessageMatcher::describe() const {
|
||||
return "exception message matches \"" + m_message + "\"";
|
||||
}
|
||||
|
||||
}
|
||||
Exception::ExceptionMessageMatcher Message(std::string const& message) {
|
||||
return Exception::ExceptionMessageMatcher(message);
|
||||
}
|
||||
|
||||
// namespace Exception
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
36
include/internal/catch_matchers_exception.hpp
Normal file
36
include/internal/catch_matchers_exception.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Created by Martin Hořeňovský on 13/10/2019.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
|
||||
|
||||
#include "catch_matchers.h"
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
namespace Exception {
|
||||
|
||||
class ExceptionMessageMatcher : public MatcherBase<std::exception> {
|
||||
std::string m_message;
|
||||
public:
|
||||
|
||||
ExceptionMessageMatcher(std::string const& message):
|
||||
m_message(message)
|
||||
{}
|
||||
|
||||
bool match(std::exception const& ex) const override;
|
||||
|
||||
std::string describe() const override;
|
||||
};
|
||||
|
||||
} // namespace Exception
|
||||
|
||||
Exception::ExceptionMessageMatcher Message(std::string const& message);
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
|
@@ -11,86 +11,120 @@
|
||||
#include "catch_to_string.hpp"
|
||||
#include "catch_tostring.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
namespace Floating {
|
||||
enum class FloatingPointKind : uint8_t {
|
||||
Float,
|
||||
Double
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace {
|
||||
|
||||
int32_t convert(float f) {
|
||||
static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated");
|
||||
int32_t i;
|
||||
std::memcpy(&i, &f, sizeof(f));
|
||||
return i;
|
||||
}
|
||||
|
||||
int64_t convert(double d) {
|
||||
static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated");
|
||||
int64_t i;
|
||||
std::memcpy(&i, &d, sizeof(d));
|
||||
return i;
|
||||
}
|
||||
|
||||
template <typename FP>
|
||||
bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) {
|
||||
// Comparison with NaN should always be false.
|
||||
// This way we can rule it out before getting into the ugly details
|
||||
if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto lc = convert(lhs);
|
||||
auto rc = convert(rhs);
|
||||
|
||||
if ((lc < 0) != (rc < 0)) {
|
||||
// Potentially we can have +0 and -0
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
auto ulpDiff = std::abs(lc - rc);
|
||||
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);
|
||||
}
|
||||
|
||||
double nextafter(double x, double y) {
|
||||
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 T>
|
||||
struct Converter;
|
||||
|
||||
template <>
|
||||
struct Converter<float> {
|
||||
static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated");
|
||||
Converter(float f) {
|
||||
std::memcpy(&i, &f, sizeof(f));
|
||||
}
|
||||
int32_t i;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<double> {
|
||||
static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated");
|
||||
Converter(double d) {
|
||||
std::memcpy(&i, &d, sizeof(d));
|
||||
}
|
||||
int64_t i;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
auto convert(T t) -> Converter<T> {
|
||||
return Converter<T>(t);
|
||||
}
|
||||
|
||||
template <typename FP>
|
||||
bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) {
|
||||
// Comparison with NaN should always be false.
|
||||
// This way we can rule it out before getting into the ugly details
|
||||
if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto lc = convert(lhs);
|
||||
auto rc = convert(rhs);
|
||||
|
||||
if ((lc.i < 0) != (rc.i < 0)) {
|
||||
// Potentially we can have +0 and -0
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
auto ulpDiff = std::abs(lc.i - rc.i);
|
||||
return ulpDiff <= maxUlpDiff;
|
||||
}
|
||||
|
||||
template <typename FP>
|
||||
FP step(FP start, FP direction, int steps) {
|
||||
for (int i = 0; i < steps; ++i) {
|
||||
FP step(FP start, FP direction, uint64_t steps) {
|
||||
for (uint64_t i = 0; i < steps; ++i) {
|
||||
#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
|
||||
start = Catch::nextafter(start, direction);
|
||||
#else
|
||||
start = std::nextafter(start, direction);
|
||||
#endif
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
|
||||
// But without the subtraction to allow for INFINITY in comparison
|
||||
bool marginComparison(double lhs, double rhs, double margin) {
|
||||
return (lhs + margin >= rhs) && (rhs + margin >= lhs);
|
||||
}
|
||||
|
||||
template <typename FloatingPoint>
|
||||
void write(std::ostream& out, FloatingPoint num) {
|
||||
out << std::scientific
|
||||
<< std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1)
|
||||
<< num;
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
namespace Floating {
|
||||
|
||||
enum class FloatingPointKind : uint8_t {
|
||||
Float,
|
||||
Double
|
||||
};
|
||||
|
||||
|
||||
WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
|
||||
:m_target{ target }, m_margin{ margin } {
|
||||
CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.'
|
||||
@@ -108,10 +142,11 @@ namespace Floating {
|
||||
}
|
||||
|
||||
|
||||
WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
|
||||
WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType)
|
||||
:m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
|
||||
CATCH_ENFORCE(ulps >= 0, "Invalid ULP setting: " << ulps << '.'
|
||||
<< " ULPs have to be non-negative.");
|
||||
CATCH_ENFORCE(m_type == FloatingPointKind::Double
|
||||
|| m_ulps < (std::numeric_limits<uint32_t>::max)(),
|
||||
"Provided ULP is impossibly large for a float comparison.");
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
@@ -138,38 +173,59 @@ namespace Floating {
|
||||
std::string WithinUlpsMatcher::describe() const {
|
||||
std::stringstream ret;
|
||||
|
||||
ret << "is within " << m_ulps << " ULPs of " << ::Catch::Detail::stringify(m_target);
|
||||
ret << "is within " << m_ulps << " ULPs of ";
|
||||
|
||||
if (m_type == FloatingPointKind::Float) {
|
||||
write(ret, static_cast<float>(m_target));
|
||||
ret << 'f';
|
||||
} else {
|
||||
write(ret, m_target);
|
||||
}
|
||||
|
||||
ret << " ([";
|
||||
ret << std::fixed << std::setprecision(std::numeric_limits<double>::max_digits10);
|
||||
if (m_type == FloatingPointKind::Double) {
|
||||
ret << step(m_target, static_cast<double>(-INFINITY), m_ulps)
|
||||
<< ", "
|
||||
<< step(m_target, static_cast<double>(INFINITY), m_ulps);
|
||||
write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps));
|
||||
ret << ", ";
|
||||
write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps));
|
||||
} else {
|
||||
ret << step<float>(static_cast<float>(m_target), -INFINITY, m_ulps)
|
||||
<< ", "
|
||||
<< step<float>(static_cast<float>(m_target), INFINITY, m_ulps);
|
||||
// We have to cast INFINITY to float because of MinGW, see #1782
|
||||
write(ret, step(static_cast<float>(m_target), static_cast<float>(-INFINITY), m_ulps));
|
||||
ret << ", ";
|
||||
write(ret, step(static_cast<float>(m_target), static_cast<float>( INFINITY), m_ulps));
|
||||
}
|
||||
ret << "])";
|
||||
|
||||
return ret.str();
|
||||
//return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
|
||||
}
|
||||
|
||||
WithinRelMatcher::WithinRelMatcher(double target, double epsilon):
|
||||
m_target(target),
|
||||
m_epsilon(epsilon){
|
||||
CATCH_ENFORCE(m_epsilon >= 0., "Relative comparison with epsilon < 0 does not make sense.");
|
||||
CATCH_ENFORCE(m_epsilon < 1., "Relative comparison with epsilon >= 1 does not make sense.");
|
||||
}
|
||||
|
||||
bool WithinRelMatcher::match(double const& matchee) const {
|
||||
const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target));
|
||||
return marginComparison(matchee, m_target,
|
||||
std::isinf(relMargin)? 0 : relMargin);
|
||||
}
|
||||
|
||||
std::string WithinRelMatcher::describe() const {
|
||||
Catch::ReusableStringStream sstr;
|
||||
sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other";
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
}// namespace Floating
|
||||
|
||||
|
||||
|
||||
Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff) {
|
||||
Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) {
|
||||
return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
|
||||
}
|
||||
|
||||
Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff) {
|
||||
Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) {
|
||||
return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
|
||||
}
|
||||
|
||||
@@ -177,6 +233,23 @@ Floating::WithinAbsMatcher WithinAbs(double target, double margin) {
|
||||
return Floating::WithinAbsMatcher(target, margin);
|
||||
}
|
||||
|
||||
Floating::WithinRelMatcher WithinRel(double target, double eps) {
|
||||
return Floating::WithinRelMatcher(target, eps);
|
||||
}
|
||||
|
||||
Floating::WithinRelMatcher WithinRel(double target) {
|
||||
return Floating::WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);
|
||||
}
|
||||
|
||||
Floating::WithinRelMatcher WithinRel(float target, float eps) {
|
||||
return Floating::WithinRelMatcher(target, eps);
|
||||
}
|
||||
|
||||
Floating::WithinRelMatcher WithinRel(float target) {
|
||||
return Floating::WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
||||
|
@@ -9,9 +9,6 @@
|
||||
|
||||
#include "catch_matchers.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
|
||||
@@ -29,23 +26,43 @@ namespace Matchers {
|
||||
};
|
||||
|
||||
struct WithinUlpsMatcher : MatcherBase<double> {
|
||||
WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType);
|
||||
WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType);
|
||||
bool match(double const& matchee) const override;
|
||||
std::string describe() const override;
|
||||
private:
|
||||
double m_target;
|
||||
int m_ulps;
|
||||
uint64_t m_ulps;
|
||||
FloatingPointKind m_type;
|
||||
};
|
||||
|
||||
// Given IEEE-754 format for floats and doubles, we can assume
|
||||
// that float -> double promotion is lossless. Given this, we can
|
||||
// assume that if we do the standard relative comparison of
|
||||
// |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
|
||||
// the same result if we do this for floats, as if we do this for
|
||||
// doubles that were promoted from floats.
|
||||
struct WithinRelMatcher : MatcherBase<double> {
|
||||
WithinRelMatcher(double target, double epsilon);
|
||||
bool match(double const& matchee) const override;
|
||||
std::string describe() const override;
|
||||
private:
|
||||
double m_target;
|
||||
double m_epsilon;
|
||||
};
|
||||
|
||||
} // namespace Floating
|
||||
|
||||
// The following functions create the actual matcher objects.
|
||||
// This allows the types to be inferred
|
||||
Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff);
|
||||
Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff);
|
||||
Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
|
||||
Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
|
||||
Floating::WithinAbsMatcher WithinAbs(double target, double margin);
|
||||
Floating::WithinRelMatcher WithinRel(double target, double eps);
|
||||
// defaults epsilon to 100*numeric_limits<double>::epsilon()
|
||||
Floating::WithinRelMatcher WithinRel(double target);
|
||||
Floating::WithinRelMatcher WithinRel(float target, float eps);
|
||||
// defaults epsilon to 100*numeric_limits<float>::epsilon()
|
||||
Floating::WithinRelMatcher WithinRel(float target);
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
@@ -113,7 +113,7 @@ namespace Catch {
|
||||
case ',':
|
||||
if (start != pos && openings.size() == 0) {
|
||||
m_messages.emplace_back(macroName, lineInfo, resultType);
|
||||
m_messages.back().message = trimmed(start, pos);
|
||||
m_messages.back().message = static_cast<std::string>(trimmed(start, pos));
|
||||
m_messages.back().message += " := ";
|
||||
start = pos;
|
||||
}
|
||||
@@ -121,7 +121,7 @@ namespace Catch {
|
||||
}
|
||||
assert(openings.size() == 0 && "Mismatched openings");
|
||||
m_messages.emplace_back(macroName, lineInfo, resultType);
|
||||
m_messages.back().message = trimmed(start, names.size() - 1);
|
||||
m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));
|
||||
m_messages.back().message += " := ";
|
||||
}
|
||||
Capturer::~Capturer() {
|
||||
|
@@ -102,35 +102,49 @@
|
||||
template<typename...> struct TypeList {};\
|
||||
template<typename...Ts>\
|
||||
constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\
|
||||
template<template<typename...> class...> struct TemplateTypeList{};\
|
||||
template<template<typename...> class...Cs>\
|
||||
constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\
|
||||
template<typename...>\
|
||||
struct append;\
|
||||
template<typename...>\
|
||||
struct rewrap;\
|
||||
template<template<typename...> class, typename...>\
|
||||
struct create;\
|
||||
template<template<typename...> class, typename>\
|
||||
struct convert;\
|
||||
\
|
||||
template<template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2> \
|
||||
constexpr auto append(L1<E1...>, L2<E2...>) noexcept -> L1<E1...,E2...> { return {}; }\
|
||||
template<typename T> \
|
||||
struct append<T> { using type = T; };\
|
||||
template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
|
||||
constexpr auto append(L1<E1...>, L2<E2...>, Rest...) noexcept -> decltype(append(L1<E1...,E2...>{}, Rest{}...)) { return {}; }\
|
||||
struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\
|
||||
template< template<typename...> class L1, typename...E1, typename...Rest>\
|
||||
constexpr auto append(L1<E1...>, TypeList<mpl_::na>, Rest...) noexcept -> L1<E1...> { return {}; }\
|
||||
struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\
|
||||
\
|
||||
template< template<typename...> class Container, template<typename...> class List, typename...elems>\
|
||||
constexpr auto rewrap(List<elems...>) noexcept -> TypeList<Container<elems...>> { return {}; }\
|
||||
struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\
|
||||
template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\
|
||||
constexpr auto rewrap(List<Elems...>,Elements...) noexcept -> decltype(append(TypeList<Container<Elems...>>{}, rewrap<Container>(Elements{}...))) { return {}; }\
|
||||
struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\
|
||||
\
|
||||
template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\
|
||||
constexpr auto create(TypeList<Types...>) noexcept -> decltype(append(Final<>{}, rewrap<Containers>(Types{}...)...)) { return {}; }\
|
||||
struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\
|
||||
template<template <typename...> class Final, template <typename...> class List, typename...Ts>\
|
||||
constexpr auto convert(List<Ts...>) noexcept -> decltype(append(Final<>{},TypeList<Ts>{}...)) { return {}; }
|
||||
struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; };
|
||||
|
||||
#define INTERNAL_CATCH_NTTP_1(signature, ...)\
|
||||
template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
|
||||
template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
|
||||
constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
|
||||
template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\
|
||||
template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\
|
||||
constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \
|
||||
\
|
||||
template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
|
||||
constexpr auto rewrap(List<__VA_ARGS__>) noexcept -> TypeList<Container<__VA_ARGS__>> { return {}; }\
|
||||
struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\
|
||||
template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
|
||||
constexpr auto rewrap(List<__VA_ARGS__>,Elements...elems) noexcept -> decltype(append(TypeList<Container<__VA_ARGS__>>{}, rewrap<Container>(elems...))) { return {}; }\
|
||||
struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\
|
||||
template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\
|
||||
constexpr auto create(TypeList<Types...>) noexcept -> decltype(append(Final<>{}, rewrap<Containers>(Types{}...)...)) { return {}; }
|
||||
struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; };
|
||||
|
||||
#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
|
||||
#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
|
||||
|
@@ -7,23 +7,67 @@
|
||||
|
||||
#include "catch_random_number_generator.h"
|
||||
#include "catch_context.h"
|
||||
#include "catch_run_context.h"
|
||||
#include "catch_interfaces_config.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
std::mt19937& rng() {
|
||||
static std::mt19937 s_rng;
|
||||
return s_rng;
|
||||
namespace {
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4146) // we negate uint32 during the rotate
|
||||
#endif
|
||||
// Safe rotr implementation thanks to John Regehr
|
||||
uint32_t rotate_right(uint32_t val, uint32_t count) {
|
||||
const uint32_t mask = 31;
|
||||
count &= mask;
|
||||
return (val >> count) | (val << (-count & mask));
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
SimplePcg32::SimplePcg32(result_type seed_) {
|
||||
seed(seed_);
|
||||
}
|
||||
|
||||
void seedRng( IConfig const& config ) {
|
||||
if( config.rngSeed() != 0 ) {
|
||||
std::srand( config.rngSeed() );
|
||||
rng().seed( config.rngSeed() );
|
||||
|
||||
void SimplePcg32::seed(result_type seed_) {
|
||||
m_state = 0;
|
||||
(*this)();
|
||||
m_state += seed_;
|
||||
(*this)();
|
||||
}
|
||||
|
||||
void SimplePcg32::discard(uint64_t skip) {
|
||||
// We could implement this to run in O(log n) steps, but this
|
||||
// should suffice for our use case.
|
||||
for (uint64_t s = 0; s < skip; ++s) {
|
||||
static_cast<void>((*this)());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int rngSeed() {
|
||||
return getCurrentContext().getConfig()->rngSeed();
|
||||
SimplePcg32::result_type SimplePcg32::operator()() {
|
||||
// prepare the output value
|
||||
const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);
|
||||
const auto output = rotate_right(xorshifted, m_state >> 59u);
|
||||
|
||||
// advance state
|
||||
m_state = m_state * 6364136223846793005ULL + s_inc;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
|
||||
return lhs.m_state == rhs.m_state;
|
||||
}
|
||||
|
||||
bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
|
||||
return lhs.m_state != rhs.m_state;
|
||||
}
|
||||
}
|
||||
|
@@ -7,17 +7,52 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct IConfig;
|
||||
// This is a simple implementation of C++11 Uniform Random Number
|
||||
// Generator. It does not provide all operators, because Catch2
|
||||
// does not use it, but it should behave as expected inside stdlib's
|
||||
// distributions.
|
||||
// The implementation is based on the PCG family (http://pcg-random.org)
|
||||
class SimplePcg32 {
|
||||
using state_type = std::uint64_t;
|
||||
public:
|
||||
using result_type = std::uint32_t;
|
||||
static constexpr result_type (min)() {
|
||||
return 0;
|
||||
}
|
||||
static constexpr result_type (max)() {
|
||||
return static_cast<result_type>(-1);
|
||||
}
|
||||
|
||||
std::mt19937& rng();
|
||||
void seedRng( IConfig const& config );
|
||||
unsigned int rngSeed();
|
||||
// Provide some default initial state for the default constructor
|
||||
SimplePcg32():SimplePcg32(0xed743cc4U) {}
|
||||
|
||||
}
|
||||
explicit SimplePcg32(result_type seed_);
|
||||
|
||||
void seed(result_type seed_);
|
||||
void discard(uint64_t skip);
|
||||
|
||||
result_type operator()();
|
||||
|
||||
private:
|
||||
friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
|
||||
friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
|
||||
|
||||
// In theory we also need operator<< and operator>>
|
||||
// In practice we do not use them, so we will skip them for now
|
||||
|
||||
|
||||
std::uint64_t m_state;
|
||||
// This part of the state determines which "stream" of the numbers
|
||||
// is chosen -- we take it as a constant for Catch2, so we only
|
||||
// need to deal with seeding the main state.
|
||||
// Picked by reading 8 bytes from `/dev/random` :-)
|
||||
static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL;
|
||||
};
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
||||
|
@@ -63,9 +63,9 @@ namespace Catch {
|
||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
||||
|
||||
#define CATCH_REGISTER_LISTENER( listenerType ) \
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
|
||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
||||
#else // CATCH_CONFIG_DISABLE
|
||||
|
||||
#define CATCH_REGISTER_REPORTER(name, reporterType)
|
||||
|
@@ -230,7 +230,7 @@ namespace Catch {
|
||||
|
||||
m_unfinishedSections.push_back(endInfo);
|
||||
}
|
||||
|
||||
|
||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||
void RunContext::benchmarkPreparing(std::string const& name) {
|
||||
m_reporter->benchmarkPreparing(name);
|
||||
@@ -279,7 +279,7 @@ namespace Catch {
|
||||
// Don't rebuild the result -- the stringification itself can cause more fatal errors
|
||||
// Instead, fake a result data.
|
||||
AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
|
||||
tempResult.message = message;
|
||||
tempResult.message = static_cast<std::string>(message);
|
||||
AssertionResult result(m_lastAssertionInfo, tempResult);
|
||||
|
||||
assertionEnded(result);
|
||||
@@ -442,7 +442,7 @@ namespace Catch {
|
||||
m_lastAssertionInfo = info;
|
||||
|
||||
AssertionResultData data( resultType, LazyExpression( false ) );
|
||||
data.message = message;
|
||||
data.message = static_cast<std::string>(message);
|
||||
AssertionResult assertionResult{ m_lastAssertionInfo, data };
|
||||
assertionEnded( assertionResult );
|
||||
if( !assertionResult.isOk() )
|
||||
@@ -506,4 +506,16 @@ namespace Catch {
|
||||
else
|
||||
CATCH_INTERNAL_ERROR("No result capture instance");
|
||||
}
|
||||
|
||||
void seedRng(IConfig const& config) {
|
||||
if (config.rngSeed() != 0) {
|
||||
std::srand(config.rngSeed());
|
||||
rng().seed(config.rngSeed());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int rngSeed() {
|
||||
return getCurrentContext().getConfig()->rngSeed();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -151,6 +151,8 @@ namespace Catch {
|
||||
bool m_includeSuccessfulResults;
|
||||
};
|
||||
|
||||
void seedRng(IConfig const& config);
|
||||
unsigned int rngSeed();
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
|
||||
|
@@ -68,8 +68,9 @@ namespace Catch {
|
||||
{
|
||||
auto const& allTestCases = getAllTestCasesSorted(*m_config);
|
||||
m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
|
||||
|
||||
if (m_matches.empty()) {
|
||||
auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
|
||||
|
||||
if (m_matches.empty() && invalidArgs.empty()) {
|
||||
for (auto const& test : allTestCases)
|
||||
if (!test.isHidden())
|
||||
m_tests.emplace(&test);
|
||||
@@ -80,6 +81,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Totals execute() {
|
||||
auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
|
||||
Totals totals;
|
||||
m_context.testGroupStarting(m_config->name(), 1, 1);
|
||||
for (auto const& testCase : m_tests) {
|
||||
@@ -95,6 +97,12 @@ namespace Catch {
|
||||
totals.error = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!invalidArgs.empty()) {
|
||||
for (auto const& invalidArg: invalidArgs)
|
||||
m_context.reporter().reportInvalidArguments(invalidArg);
|
||||
}
|
||||
|
||||
m_context.testGroupEnded(m_config->name(), totals, 1, 1);
|
||||
return totals;
|
||||
}
|
||||
@@ -175,7 +183,7 @@ namespace Catch {
|
||||
}
|
||||
void Session::libIdentify() {
|
||||
Catch::cout()
|
||||
<< std::left << std::setw(16) << "description: " << "A Catch test executable\n"
|
||||
<< std::left << std::setw(16) << "description: " << "A Catch2 test executable\n"
|
||||
<< std::left << std::setw(16) << "category: " << "testframework\n"
|
||||
<< std::left << std::setw(16) << "framework: " << "Catch Test\n"
|
||||
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
|
||||
|
@@ -53,6 +53,18 @@ namespace Catch {
|
||||
return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
|
||||
}
|
||||
|
||||
StringRef trim(StringRef ref) {
|
||||
const auto is_ws = [](char c) {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
|
||||
};
|
||||
size_t real_begin = 0;
|
||||
while (real_begin < ref.size() && is_ws(ref[real_begin])) { ++real_begin; }
|
||||
size_t real_end = ref.size();
|
||||
while (real_end > real_begin && is_ws(ref[real_end - 1])) { --real_end; }
|
||||
|
||||
return ref.substr(real_begin, real_end - real_begin);
|
||||
}
|
||||
|
||||
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
|
||||
bool replaced = false;
|
||||
std::size_t i = str.find( replaceThis );
|
||||
|
@@ -22,7 +22,10 @@ namespace Catch {
|
||||
bool contains( std::string const& s, std::string const& infix );
|
||||
void toLowerInPlace( std::string& s );
|
||||
std::string toLower( std::string const& s );
|
||||
//! Returns a new string without whitespace at the start/end
|
||||
std::string trim( std::string const& str );
|
||||
//! Returns a substring of the original ref without whitespace. Beware lifetimes!
|
||||
StringRef trim(StringRef ref);
|
||||
|
||||
// !!! Be aware, returns refs into original string - make sure original string outlives them
|
||||
std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
|
||||
|
@@ -17,21 +17,11 @@
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
namespace {
|
||||
const uint32_t byte_2_lead = 0xC0;
|
||||
const uint32_t byte_3_lead = 0xE0;
|
||||
const uint32_t byte_4_lead = 0xF0;
|
||||
}
|
||||
|
||||
namespace Catch {
|
||||
StringRef::StringRef( char const* rawChars ) noexcept
|
||||
: StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )
|
||||
{}
|
||||
|
||||
StringRef::operator std::string() const {
|
||||
return std::string( m_start, m_size );
|
||||
}
|
||||
|
||||
void StringRef::swap( StringRef& other ) noexcept {
|
||||
std::swap( m_start, other.m_start );
|
||||
std::swap( m_size, other.m_size );
|
||||
@@ -78,40 +68,6 @@ namespace Catch {
|
||||
return !operator==( other );
|
||||
}
|
||||
|
||||
auto StringRef::operator[](size_type index) const noexcept -> char {
|
||||
return m_start[index];
|
||||
}
|
||||
|
||||
auto StringRef::numberOfCharacters() const noexcept -> size_type {
|
||||
size_type noChars = m_size;
|
||||
// Make adjustments for uft encodings
|
||||
for( size_type i=0; i < m_size; ++i ) {
|
||||
char c = m_start[i];
|
||||
if( ( c & byte_2_lead ) == byte_2_lead ) {
|
||||
noChars--;
|
||||
if (( c & byte_3_lead ) == byte_3_lead )
|
||||
noChars--;
|
||||
if( ( c & byte_4_lead ) == byte_4_lead )
|
||||
noChars--;
|
||||
}
|
||||
}
|
||||
return noChars;
|
||||
}
|
||||
|
||||
auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string {
|
||||
std::string str;
|
||||
str.reserve( lhs.size() + rhs.size() );
|
||||
str += lhs;
|
||||
str += rhs;
|
||||
return str;
|
||||
}
|
||||
auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string {
|
||||
return std::string( lhs ) + std::string( rhs );
|
||||
}
|
||||
auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string {
|
||||
return std::string( lhs ) + std::string( rhs );
|
||||
}
|
||||
|
||||
auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
|
||||
return os.write(str.currentData(), str.size());
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
#include <cassert>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -23,6 +24,7 @@ namespace Catch {
|
||||
class StringRef {
|
||||
public:
|
||||
using size_type = std::size_t;
|
||||
using const_iterator = const char*;
|
||||
|
||||
private:
|
||||
friend struct StringRefTestAccess;
|
||||
@@ -78,7 +80,9 @@ namespace Catch {
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator std::string() const;
|
||||
explicit operator std::string() const {
|
||||
return std::string(m_start, m_size);
|
||||
}
|
||||
|
||||
void swap( StringRef& other ) noexcept;
|
||||
|
||||
@@ -86,7 +90,10 @@ namespace Catch {
|
||||
auto operator == ( StringRef const& other ) const noexcept -> bool;
|
||||
auto operator != ( StringRef const& other ) const noexcept -> bool;
|
||||
|
||||
auto operator[] ( size_type index ) const noexcept -> char;
|
||||
auto operator[] ( size_type index ) const noexcept -> char {
|
||||
assert(index < m_size);
|
||||
return m_start[index];
|
||||
}
|
||||
|
||||
public: // named queries
|
||||
auto empty() const noexcept -> bool {
|
||||
@@ -96,7 +103,6 @@ namespace Catch {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
auto numberOfCharacters() const noexcept -> size_type;
|
||||
auto c_str() const -> char const*;
|
||||
|
||||
public: // substrings and searches
|
||||
@@ -106,15 +112,15 @@ namespace Catch {
|
||||
// Note that the pointer can change when if the StringRef is a substring
|
||||
auto currentData() const noexcept -> char const*;
|
||||
|
||||
public: // iterators
|
||||
const_iterator begin() const { return m_start; }
|
||||
const_iterator end() const { return m_start + m_size; }
|
||||
|
||||
private: // ownership queries - may not be consistent between calls
|
||||
auto isOwned() const noexcept -> bool;
|
||||
auto isSubstring() const noexcept -> bool;
|
||||
};
|
||||
|
||||
auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string;
|
||||
auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string;
|
||||
auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string;
|
||||
|
||||
auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
|
||||
auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
|
||||
|
||||
|
@@ -59,8 +59,7 @@ namespace Catch {
|
||||
std::vector<std::string> tags;
|
||||
std::string desc, tag;
|
||||
bool inTag = false;
|
||||
std::string _descOrTags = nameAndTags.tags;
|
||||
for (char c : _descOrTags) {
|
||||
for (char c : nameAndTags.tags) {
|
||||
if( !inTag ) {
|
||||
if( c == '[' )
|
||||
inTag = true;
|
||||
@@ -93,7 +92,7 @@ namespace Catch {
|
||||
tags.push_back( "." );
|
||||
}
|
||||
|
||||
TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );
|
||||
TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo );
|
||||
return TestCase( _testCase, std::move(info) );
|
||||
}
|
||||
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "catch_enforce.h"
|
||||
#include "catch_interfaces_registry_hub.h"
|
||||
#include "catch_random_number_generator.h"
|
||||
#include "catch_run_context.h"
|
||||
#include "catch_string_manip.h"
|
||||
#include "catch_test_case_info.h"
|
||||
|
||||
@@ -105,7 +106,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
|
||||
std::string className = classOrQualifiedMethodName;
|
||||
std::string className(classOrQualifiedMethodName);
|
||||
if( startsWith( className, '&' ) )
|
||||
{
|
||||
std::size_t lastColons = className.rfind( "::" );
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include "catch_test_case_tracker.h"
|
||||
|
||||
#include "catch_enforce.h"
|
||||
#include "catch_string_manip.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@@ -174,7 +175,8 @@ namespace TestCaseTracking {
|
||||
}
|
||||
|
||||
SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||
: TrackerBase( nameAndLocation, ctx, parent )
|
||||
: TrackerBase( nameAndLocation, ctx, parent ),
|
||||
m_trimmed_name(trim(nameAndLocation.name))
|
||||
{
|
||||
if( parent ) {
|
||||
while( !parent->isSectionTracker() )
|
||||
@@ -188,12 +190,11 @@ namespace TestCaseTracking {
|
||||
bool SectionTracker::isComplete() const {
|
||||
bool complete = true;
|
||||
|
||||
if ((m_filters.empty() || m_filters[0] == "") ||
|
||||
std::find(m_filters.begin(), m_filters.end(),
|
||||
m_nameAndLocation.name) != m_filters.end())
|
||||
if ((m_filters.empty() || m_filters[0] == "")
|
||||
|| std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
|
||||
complete = TrackerBase::isComplete();
|
||||
}
|
||||
return complete;
|
||||
|
||||
}
|
||||
|
||||
bool SectionTracker::isSectionTracker() const { return true; }
|
||||
@@ -217,12 +218,13 @@ namespace TestCaseTracking {
|
||||
}
|
||||
|
||||
void SectionTracker::tryOpen() {
|
||||
if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
|
||||
if( !isComplete() )
|
||||
open();
|
||||
}
|
||||
|
||||
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.insert( m_filters.end(), filters.begin(), filters.end() );
|
||||
@@ -230,7 +232,7 @@ namespace TestCaseTracking {
|
||||
}
|
||||
void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) {
|
||||
if( filters.size() > 1 )
|
||||
m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
|
||||
m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() );
|
||||
}
|
||||
|
||||
} // namespace TestCaseTracking
|
||||
|
@@ -133,6 +133,7 @@ namespace TestCaseTracking {
|
||||
|
||||
class SectionTracker : public TrackerBase {
|
||||
std::vector<std::string> m_filters;
|
||||
std::string m_trimmed_name;
|
||||
public:
|
||||
SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
|
||||
|
||||
|
@@ -12,7 +12,6 @@
|
||||
#include "catch_interfaces_testcase.h"
|
||||
#include "catch_compiler_capabilities.h"
|
||||
#include "catch_stringref.h"
|
||||
#include "catch_type_traits.hpp"
|
||||
#include "catch_preprocessor.hpp"
|
||||
#include "catch_meta.hpp"
|
||||
|
||||
@@ -143,6 +142,7 @@ struct AutoReg : NonCopyable {
|
||||
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
|
||||
namespace {\
|
||||
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
|
||||
@@ -166,6 +166,7 @@ struct AutoReg : NonCopyable {
|
||||
}\
|
||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||
CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
|
||||
|
||||
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||
@@ -187,6 +188,7 @@ struct AutoReg : NonCopyable {
|
||||
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
template<typename TestType> static void TestFuncName(); \
|
||||
namespace {\
|
||||
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
|
||||
@@ -204,7 +206,7 @@ struct AutoReg : NonCopyable {
|
||||
} \
|
||||
}; \
|
||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
|
||||
using TestInit = decltype(create<TestName, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>(TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>{})); \
|
||||
using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
|
||||
TestInit t; \
|
||||
t.reg_tests(); \
|
||||
return 0; \
|
||||
@@ -213,6 +215,7 @@ struct AutoReg : NonCopyable {
|
||||
} \
|
||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||
CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
template<typename TestType> \
|
||||
static void TestFuncName()
|
||||
|
||||
@@ -234,6 +237,7 @@ struct AutoReg : NonCopyable {
|
||||
|
||||
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
template<typename TestType> static void TestFunc(); \
|
||||
namespace {\
|
||||
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
|
||||
@@ -247,13 +251,14 @@ struct AutoReg : NonCopyable {
|
||||
} \
|
||||
};\
|
||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
|
||||
using TestInit = decltype(convert<TestName>(std::declval<TmplList>())); \
|
||||
using TestInit = typename convert<TestName, TmplList>::type; \
|
||||
TestInit t; \
|
||||
t.reg_tests(); \
|
||||
return 0; \
|
||||
}(); \
|
||||
}}\
|
||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
template<typename TestType> \
|
||||
static void TestFunc()
|
||||
|
||||
@@ -264,6 +269,7 @@ struct AutoReg : NonCopyable {
|
||||
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
namespace {\
|
||||
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
|
||||
INTERNAL_CATCH_TYPE_GEN\
|
||||
@@ -287,6 +293,7 @@ struct AutoReg : NonCopyable {
|
||||
}\
|
||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\
|
||||
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS\
|
||||
CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS\
|
||||
INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
|
||||
|
||||
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
||||
@@ -308,6 +315,7 @@ struct AutoReg : NonCopyable {
|
||||
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
template<typename TestType> \
|
||||
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
|
||||
void test();\
|
||||
@@ -328,7 +336,7 @@ struct AutoReg : NonCopyable {
|
||||
}\
|
||||
};\
|
||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
|
||||
using TestInit = decltype(create<TestNameClass, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>(TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>{}));\
|
||||
using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\
|
||||
TestInit t;\
|
||||
t.reg_tests();\
|
||||
return 0;\
|
||||
@@ -337,6 +345,7 @@ struct AutoReg : NonCopyable {
|
||||
}\
|
||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||
CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
template<typename TestType> \
|
||||
void TestName<TestType>::test()
|
||||
|
||||
@@ -358,6 +367,7 @@ struct AutoReg : NonCopyable {
|
||||
|
||||
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
template<typename TestType> \
|
||||
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
|
||||
void test();\
|
||||
@@ -374,13 +384,14 @@ struct AutoReg : NonCopyable {
|
||||
}\
|
||||
};\
|
||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
|
||||
using TestInit = decltype(convert<TestNameClass>(std::declval<TmplList>()));\
|
||||
using TestInit = typename convert<TestNameClass, TmplList>::type;\
|
||||
TestInit t;\
|
||||
t.reg_tests();\
|
||||
return 0;\
|
||||
}(); \
|
||||
}}\
|
||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||
template<typename TestType> \
|
||||
void TestName<TestType>::test()
|
||||
|
||||
|
@@ -33,7 +33,7 @@ namespace Catch {
|
||||
{}
|
||||
|
||||
bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
|
||||
return m_wildcardPattern.matches( toLower( testCase.name ) );
|
||||
return m_wildcardPattern.matches( testCase.name );
|
||||
}
|
||||
|
||||
|
||||
@@ -91,5 +91,9 @@ namespace Catch {
|
||||
} );
|
||||
return matches;
|
||||
}
|
||||
|
||||
const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{
|
||||
return (m_invalidArgs);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -73,14 +73,16 @@ namespace Catch {
|
||||
std::vector<TestCase const*> tests;
|
||||
};
|
||||
using Matches = std::vector<FilterMatch>;
|
||||
using vectorStrings = std::vector<std::string>;
|
||||
|
||||
bool hasFilters() const;
|
||||
bool matches( TestCaseInfo const& testCase ) const;
|
||||
Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const;
|
||||
const vectorStrings & getInvalidArgs() const;
|
||||
|
||||
private:
|
||||
std::vector<Filter> m_filters;
|
||||
|
||||
std::vector<std::string> m_invalidArgs;
|
||||
friend class TestSpecParser;
|
||||
};
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "catch_test_spec_parser.h"
|
||||
|
||||
|
||||
namespace Catch {
|
||||
|
||||
TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
|
||||
@@ -18,8 +19,14 @@ namespace Catch {
|
||||
m_escapeChars.clear();
|
||||
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 )
|
||||
visitChar( m_arg[m_pos] );
|
||||
//if visitChar fails
|
||||
if( !visitChar( m_arg[m_pos] ) ){
|
||||
m_testSpec.m_invalidArgs.push_back(arg);
|
||||
break;
|
||||
}
|
||||
endMode();
|
||||
return *this;
|
||||
}
|
||||
@@ -27,35 +34,41 @@ namespace Catch {
|
||||
addFilter();
|
||||
return m_testSpec;
|
||||
}
|
||||
void TestSpecParser::visitChar( char c ) {
|
||||
if( c == ',' ) {
|
||||
endMode();
|
||||
addFilter();
|
||||
return;
|
||||
bool TestSpecParser::visitChar( char c ) {
|
||||
if( (m_mode != EscapedName) && (c == '\\') ) {
|
||||
escape();
|
||||
addCharToPattern(c);
|
||||
return true;
|
||||
}else if((m_mode != EscapedName) && (c == ',') ) {
|
||||
return separate();
|
||||
}
|
||||
|
||||
switch( m_mode ) {
|
||||
case None:
|
||||
if( processNoneChar( c ) )
|
||||
return;
|
||||
return true;
|
||||
break;
|
||||
case Name:
|
||||
processNameChar( c );
|
||||
break;
|
||||
case EscapedName:
|
||||
endMode();
|
||||
break;
|
||||
addCharToPattern(c);
|
||||
return true;
|
||||
default:
|
||||
case Tag:
|
||||
case QuotedName:
|
||||
if( processOtherChar( c ) )
|
||||
return;
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
m_substring += c;
|
||||
if( !isControlChar( c ) )
|
||||
if( !isControlChar( c ) ) {
|
||||
m_patternName += c;
|
||||
m_realPatternPos++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Two of the processing methods return true to signal the caller to return
|
||||
// without adding the given character to the current pattern strings
|
||||
@@ -72,9 +85,6 @@ namespace Catch {
|
||||
case '"':
|
||||
startNewMode( QuotedName );
|
||||
return false;
|
||||
case '\\':
|
||||
escape();
|
||||
return true;
|
||||
default:
|
||||
startNewMode( Name );
|
||||
return false;
|
||||
@@ -107,15 +117,17 @@ namespace Catch {
|
||||
case Tag:
|
||||
return addPattern<TestSpec::TagPattern>();
|
||||
case EscapedName:
|
||||
return startNewMode( Name );
|
||||
revertBackToLastMode();
|
||||
return;
|
||||
case None:
|
||||
default:
|
||||
return startNewMode( None );
|
||||
}
|
||||
}
|
||||
void TestSpecParser::escape() {
|
||||
saveLastMode();
|
||||
m_mode = EscapedName;
|
||||
m_escapeChars.push_back( m_pos );
|
||||
m_escapeChars.push_back(m_realPatternPos);
|
||||
}
|
||||
bool TestSpecParser::isControlChar( char c ) const {
|
||||
switch( m_mode ) {
|
||||
@@ -141,6 +153,28 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
void TestSpecParser::saveLastMode() {
|
||||
lastMode = m_mode;
|
||||
}
|
||||
|
||||
void TestSpecParser::revertBackToLastMode() {
|
||||
m_mode = lastMode;
|
||||
}
|
||||
|
||||
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();
|
||||
return false;
|
||||
}
|
||||
endMode();
|
||||
addFilter();
|
||||
return true; //success
|
||||
}
|
||||
|
||||
TestSpec parseTestSpec( std::string const& arg ) {
|
||||
return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
|
||||
}
|
||||
|
@@ -22,8 +22,10 @@ namespace Catch {
|
||||
class TestSpecParser {
|
||||
enum Mode{ None, Name, QuotedName, Tag, EscapedName };
|
||||
Mode m_mode = None;
|
||||
Mode lastMode = None;
|
||||
bool m_exclusion = false;
|
||||
std::size_t m_pos = 0;
|
||||
std::size_t m_realPatternPos = 0;
|
||||
std::string m_arg;
|
||||
std::string m_substring;
|
||||
std::string m_patternName;
|
||||
@@ -39,7 +41,7 @@ namespace Catch {
|
||||
TestSpec testSpec();
|
||||
|
||||
private:
|
||||
void visitChar( char c );
|
||||
bool visitChar( char c );
|
||||
void startNewMode( Mode mode );
|
||||
bool processNoneChar( char c );
|
||||
void processNameChar( char c );
|
||||
@@ -47,7 +49,11 @@ namespace Catch {
|
||||
void endMode();
|
||||
void escape();
|
||||
bool isControlChar( char c ) const;
|
||||
|
||||
void saveLastMode();
|
||||
void revertBackToLastMode();
|
||||
void addFilter();
|
||||
bool separate();
|
||||
|
||||
template<typename T>
|
||||
void addPattern() {
|
||||
std::string token = m_patternName;
|
||||
@@ -69,8 +75,13 @@ namespace Catch {
|
||||
m_exclusion = false;
|
||||
m_mode = None;
|
||||
}
|
||||
|
||||
void addFilter();
|
||||
|
||||
inline void addCharToPattern(char c) {
|
||||
m_substring += c;
|
||||
m_patternName += c;
|
||||
m_realPatternPos++;
|
||||
}
|
||||
|
||||
};
|
||||
TestSpec parseTestSpec( std::string const& arg );
|
||||
|
||||
@@ -80,4 +91,4 @@ namespace Catch {
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
|
||||
#endif // TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
|
@@ -44,9 +44,9 @@ namespace Catch {
|
||||
|
||||
template<typename T>
|
||||
class IsStreamInsertable {
|
||||
template<typename SS, typename TT>
|
||||
template<typename Stream, typename U>
|
||||
static auto test(int)
|
||||
-> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
|
||||
-> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type());
|
||||
|
||||
template<typename, typename>
|
||||
static auto test(...)->std::false_type;
|
||||
@@ -654,7 +654,7 @@ namespace Catch { \
|
||||
template<> struct StringMaker<enumName> { \
|
||||
static std::string convert( enumName value ) { \
|
||||
static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
|
||||
return enumInfo.lookup( static_cast<int>( value ) ); \
|
||||
return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
|
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Created by Jozef on 12/11/2018.
|
||||
* Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace Catch{
|
||||
|
||||
#ifdef CATCH_CPP17_OR_GREATER
|
||||
template <typename...>
|
||||
inline constexpr auto is_unique = std::true_type{};
|
||||
|
||||
template <typename T, typename... Rest>
|
||||
inline constexpr auto is_unique<T, Rest...> = std::bool_constant<
|
||||
(!std::is_same_v<T, Rest> && ...) && is_unique<Rest...>
|
||||
>{};
|
||||
#else
|
||||
|
||||
template <typename...>
|
||||
struct is_unique : std::true_type{};
|
||||
|
||||
template <typename T0, typename T1, typename... Rest>
|
||||
struct is_unique<T0, T1, Rest...> : std::integral_constant
|
||||
<bool,
|
||||
!std::is_same<T0, T1>::value
|
||||
&& is_unique<T0, Rest...>::value
|
||||
&& is_unique<T1, Rest...>::value
|
||||
>{};
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
|
@@ -37,7 +37,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Version const& libraryVersion() {
|
||||
static Version version( 2, 9, 2, "", 0 );
|
||||
static Version version( 2, 10, 2, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
|
@@ -9,14 +9,12 @@
|
||||
#include "catch_enforce.h"
|
||||
#include "catch_string_manip.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
WildcardPattern::WildcardPattern( std::string const& pattern,
|
||||
CaseSensitive::Choice caseSensitivity )
|
||||
: m_caseSensitivity( caseSensitivity ),
|
||||
m_pattern( adjustCase( pattern ) )
|
||||
m_pattern( normaliseString( pattern ) )
|
||||
{
|
||||
if( startsWith( m_pattern, '*' ) ) {
|
||||
m_pattern = m_pattern.substr( 1 );
|
||||
@@ -31,19 +29,19 @@ namespace Catch {
|
||||
bool WildcardPattern::matches( std::string const& str ) const {
|
||||
switch( m_wildcard ) {
|
||||
case NoWildcard:
|
||||
return m_pattern == adjustCase( str );
|
||||
return m_pattern == normaliseString( str );
|
||||
case WildcardAtStart:
|
||||
return endsWith( adjustCase( str ), m_pattern );
|
||||
return endsWith( normaliseString( str ), m_pattern );
|
||||
case WildcardAtEnd:
|
||||
return startsWith( adjustCase( str ), m_pattern );
|
||||
return startsWith( normaliseString( str ), m_pattern );
|
||||
case WildcardAtBothEnds:
|
||||
return contains( adjustCase( str ), m_pattern );
|
||||
return contains( normaliseString( str ), m_pattern );
|
||||
default:
|
||||
CATCH_INTERNAL_ERROR( "Unknown enum" );
|
||||
}
|
||||
}
|
||||
|
||||
std::string WildcardPattern::adjustCase( std::string const& str ) const {
|
||||
return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
|
||||
std::string WildcardPattern::normaliseString( std::string const& str ) const {
|
||||
return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str );
|
||||
}
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ namespace Catch
|
||||
virtual bool matches( std::string const& str ) const;
|
||||
|
||||
private:
|
||||
std::string adjustCase( std::string const& str ) const;
|
||||
std::string normaliseString( std::string const& str ) const;
|
||||
CaseSensitive::Choice m_caseSensitivity;
|
||||
WildcardPosition m_wildcard = NoWildcard;
|
||||
std::string m_pattern;
|
||||
|
@@ -51,6 +51,8 @@ namespace Catch {
|
||||
|
||||
void noMatchingTestCases(std::string const&) override {}
|
||||
|
||||
void reportInvalidArguments(std::string const&) override {}
|
||||
|
||||
void testRunStarting(TestRunInfo const& _testRunInfo) override {
|
||||
currentTestRunInfo = _testRunInfo;
|
||||
}
|
||||
@@ -277,4 +279,4 @@ namespace Catch {
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
||||
#endif // TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
@@ -8,7 +8,7 @@
|
||||
#include "catch_reporter_compact.h"
|
||||
|
||||
#include "../internal/catch_reporter_registrars.hpp"
|
||||
#include "internal/catch_console_colour.h"
|
||||
#include "../internal/catch_console_colour.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
#include "catch_reporter_console.h"
|
||||
|
||||
#include "../internal/catch_reporter_registrars.hpp"
|
||||
#include "internal/catch_console_colour.h"
|
||||
#include "../internal/catch_console_colour.h"
|
||||
#include "../internal/catch_version.h"
|
||||
#include "../internal/catch_text.h"
|
||||
#include "../internal/catch_stringref.h"
|
||||
@@ -268,7 +268,7 @@ public:
|
||||
|
||||
}
|
||||
friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& {
|
||||
return os << duration.value() << " " << duration.unitsAsString();
|
||||
return os << duration.value() << ' ' << duration.unitsAsString();
|
||||
}
|
||||
};
|
||||
} // end anon namespace
|
||||
@@ -300,9 +300,9 @@ public:
|
||||
headerCols += Column(info.name).width(static_cast<std::size_t>(info.width - 2));
|
||||
headerCols += spacer;
|
||||
}
|
||||
m_os << headerCols << "\n";
|
||||
m_os << headerCols << '\n';
|
||||
|
||||
m_os << Catch::getLineOfChars<'-'>() << "\n";
|
||||
m_os << Catch::getLineOfChars<'-'>() << '\n';
|
||||
}
|
||||
}
|
||||
void close() {
|
||||
@@ -321,30 +321,29 @@ public:
|
||||
|
||||
friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) {
|
||||
auto colStr = tp.m_oss.str();
|
||||
// This takes account of utf8 encodings
|
||||
auto strSize = Catch::StringRef(colStr).numberOfCharacters();
|
||||
const auto strSize = colStr.size();
|
||||
tp.m_oss.str("");
|
||||
tp.open();
|
||||
if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
|
||||
tp.m_currentColumn = -1;
|
||||
tp.m_os << "\n";
|
||||
tp.m_os << '\n';
|
||||
}
|
||||
tp.m_currentColumn++;
|
||||
|
||||
auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
|
||||
auto padding = (strSize + 2 < static_cast<std::size_t>(colInfo.width))
|
||||
? std::string(colInfo.width - (strSize + 2), ' ')
|
||||
auto padding = (strSize + 1 < static_cast<std::size_t>(colInfo.width))
|
||||
? std::string(colInfo.width - (strSize + 1), ' ')
|
||||
: std::string();
|
||||
if (colInfo.justification == ColumnInfo::Left)
|
||||
tp.m_os << colStr << padding << " ";
|
||||
tp.m_os << colStr << padding << ' ';
|
||||
else
|
||||
tp.m_os << padding << colStr << " ";
|
||||
tp.m_os << padding << colStr << ' ';
|
||||
return tp;
|
||||
}
|
||||
|
||||
friend TablePrinter& operator << (TablePrinter& tp, RowBreak) {
|
||||
if (tp.m_currentColumn > 0) {
|
||||
tp.m_os << "\n";
|
||||
tp.m_os << '\n';
|
||||
tp.m_currentColumn = -1;
|
||||
}
|
||||
return tp;
|
||||
@@ -354,12 +353,26 @@ public:
|
||||
ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
|
||||
: StreamingReporterBase(config),
|
||||
m_tablePrinter(new TablePrinter(config.stream(),
|
||||
{
|
||||
{ "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, 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 }
|
||||
})) {}
|
||||
[&config]() -> std::vector<ColumnInfo> {
|
||||
if (config.fullConfig()->benchmarkNoAnalysis())
|
||||
{
|
||||
return{
|
||||
{ "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left },
|
||||
{ " samples", 14, ColumnInfo::Right },
|
||||
{ " iterations", 14, ColumnInfo::Right },
|
||||
{ " mean", 14, ColumnInfo::Right }
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return{
|
||||
{ "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, 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 }
|
||||
};
|
||||
}
|
||||
}())) {}
|
||||
ConsoleReporter::~ConsoleReporter() = default;
|
||||
|
||||
std::string ConsoleReporter::getDescription() {
|
||||
@@ -370,6 +383,10 @@ void ConsoleReporter::noMatchingTestCases(std::string const& spec) {
|
||||
stream << "No test cases matched '" << spec << '\'' << std::endl;
|
||||
}
|
||||
|
||||
void ConsoleReporter::reportInvalidArguments(std::string const&arg){
|
||||
stream << "Invalid Filter: " << arg << std::endl;
|
||||
}
|
||||
|
||||
void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
|
||||
|
||||
bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
|
||||
@@ -432,24 +449,32 @@ void ConsoleReporter::benchmarkPreparing(std::string const& name) {
|
||||
}
|
||||
|
||||
void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
|
||||
(*m_tablePrinter) << info.samples << ColumnBreak()
|
||||
<< info.iterations << ColumnBreak()
|
||||
<< Duration(info.estimatedDuration) << ColumnBreak();
|
||||
(*m_tablePrinter) << info.samples << ColumnBreak()
|
||||
<< info.iterations << ColumnBreak();
|
||||
if (!m_config->benchmarkNoAnalysis())
|
||||
(*m_tablePrinter) << Duration(info.estimatedDuration) << ColumnBreak();
|
||||
}
|
||||
void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) {
|
||||
(*m_tablePrinter) << ColumnBreak()
|
||||
<< Duration(stats.mean.point.count()) << ColumnBreak()
|
||||
<< Duration(stats.mean.lower_bound.count()) << ColumnBreak()
|
||||
<< Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak()
|
||||
<< Duration(stats.standardDeviation.point.count()) << ColumnBreak()
|
||||
<< Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak()
|
||||
<< Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak();
|
||||
if (m_config->benchmarkNoAnalysis())
|
||||
{
|
||||
(*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak();
|
||||
}
|
||||
else
|
||||
{
|
||||
(*m_tablePrinter) << ColumnBreak()
|
||||
<< Duration(stats.mean.point.count()) << ColumnBreak()
|
||||
<< Duration(stats.mean.lower_bound.count()) << ColumnBreak()
|
||||
<< Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak()
|
||||
<< Duration(stats.standardDeviation.point.count()) << ColumnBreak()
|
||||
<< Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak()
|
||||
<< Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleReporter::benchmarkFailed(std::string const& error) {
|
||||
Colour colour(Colour::Red);
|
||||
(*m_tablePrinter)
|
||||
<< "Benchmark failed (" << error << ")"
|
||||
<< "Benchmark failed (" << error << ')'
|
||||
<< ColumnBreak() << RowBreak();
|
||||
}
|
||||
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
|
||||
@@ -531,11 +556,10 @@ void ConsoleReporter::printTestCaseAndSectionHeader() {
|
||||
|
||||
SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
|
||||
|
||||
if (!lineInfo.empty()) {
|
||||
stream << getLineOfChars<'-'>() << '\n';
|
||||
Colour colourGuard(Colour::FileName);
|
||||
stream << lineInfo << '\n';
|
||||
}
|
||||
|
||||
stream << getLineOfChars<'-'>() << '\n';
|
||||
Colour colourGuard(Colour::FileName);
|
||||
stream << lineInfo << '\n';
|
||||
stream << getLineOfChars<'.'>() << '\n' << std::endl;
|
||||
}
|
||||
|
||||
@@ -674,4 +698,4 @@ CATCH_REGISTER_REPORTER("console", ConsoleReporter)
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
#endif
|
@@ -32,6 +32,8 @@ namespace Catch {
|
||||
|
||||
void noMatchingTestCases(std::string const& spec) override;
|
||||
|
||||
void reportInvalidArguments(std::string const&arg) override;
|
||||
|
||||
void assertionStarting(AssertionInfo const&) override;
|
||||
|
||||
bool assertionEnded(AssertionStats const& _assertionStats) override;
|
||||
@@ -84,4 +86,4 @@ namespace Catch {
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_REPORTER_CONSOLE_H_INCLUDED
|
||||
#endif // TWOBLUECUBES_CATCH_REPORTER_CONSOLE_H_INCLUDED
|
@@ -41,6 +41,13 @@ namespace Catch {
|
||||
}
|
||||
m_reporter->noMatchingTestCases( spec );
|
||||
}
|
||||
|
||||
void ListeningReporter::reportInvalidArguments(std::string const&arg){
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->reportInvalidArguments( arg );
|
||||
}
|
||||
m_reporter->reportInvalidArguments( arg );
|
||||
}
|
||||
|
||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||
void ListeningReporter::benchmarkPreparing( std::string const& name ) {
|
||||
@@ -154,4 +161,4 @@ namespace Catch {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
||||
} // end namespace Catch
|
@@ -28,7 +28,9 @@ namespace Catch {
|
||||
ReporterPreferences getPreferences() const override;
|
||||
|
||||
void noMatchingTestCases( std::string const& spec ) override;
|
||||
|
||||
|
||||
void reportInvalidArguments(std::string const&arg) override;
|
||||
|
||||
static std::set<Verbosity> getSupportedVerbosities();
|
||||
|
||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||
@@ -58,4 +60,4 @@ namespace Catch {
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_MULTI_REPORTER_H_INCLUDED
|
||||
#endif // TWOBLUECUBES_CATCH_MULTI_REPORTER_H_INCLUDED
|
@@ -183,8 +183,7 @@ namespace Catch {
|
||||
|
||||
SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
|
||||
|
||||
if( !lineInfo.empty() )
|
||||
os << lineInfo << "\n";
|
||||
os << lineInfo << "\n";
|
||||
os << getLineOfChars<'.'>() << "\n\n";
|
||||
}
|
||||
|
||||
|
@@ -29,7 +29,8 @@ std::string escape_arg(const std::string& arg) {
|
||||
escaped.append(num_backslashes * 2, '\\');
|
||||
break;
|
||||
} else if (*it == '"') {
|
||||
escaped.append(num_backslashes * 2 + 1, '\\');
|
||||
escaped.append((num_backslashes + 1) * 2, '\\');
|
||||
escaped.push_back('"');
|
||||
escaped.push_back(*it);
|
||||
} else {
|
||||
escaped.append(num_backslashes, '\\');
|
||||
@@ -97,7 +98,7 @@ int exec_cmd(std::string const& cmd, int log_num, std::string const& path) {
|
||||
+ ".bin --quiet " + "--sources " + escape_arg(path) + " --cover_children -- " + cmd;
|
||||
std::cout << "=== Marker ===: Cmd: " << real_cmd << '\n';
|
||||
auto pipe = _popen(real_cmd.c_str(), "r");
|
||||
|
||||
|
||||
if (!pipe) {
|
||||
throw std::runtime_error("popen() failed!");
|
||||
}
|
||||
@@ -106,12 +107,12 @@ int exec_cmd(std::string const& cmd, int log_num, std::string const& path) {
|
||||
std::cout << buffer.data();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto ret = _pclose(pipe);
|
||||
if (ret == -1) {
|
||||
throw std::runtime_error("underlying error in pclose()");
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -127,7 +128,7 @@ int main(int argc, char** argv) {
|
||||
assert(sep - begin(args) == 2 && "Structure differs from expected!");
|
||||
|
||||
auto num = parse_log_file_arg(args[1]);
|
||||
|
||||
|
||||
auto cmdline = std::accumulate(++sep, end(args), std::string{}, [] (const std::string& lhs, const std::string& rhs) {
|
||||
return lhs + ' ' + escape_arg(rhs);
|
||||
});
|
||||
|
@@ -17,11 +17,14 @@ endif(MSVC) #Temporary workaround
|
||||
set(TEST_SOURCES
|
||||
${SELF_TEST_DIR}/TestMain.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/Details.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/GeneratorsImpl.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/InternalBenchmark.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/RandomNumberGeneration.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/Tag.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/StringManip.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/Xml.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/ToString.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Approx.tests.cpp
|
||||
@@ -148,6 +151,7 @@ set(INTERNAL_HEADERS
|
||||
${HEADER_DIR}/internal/catch_leak_detector.h
|
||||
${HEADER_DIR}/internal/catch_list.h
|
||||
${HEADER_DIR}/internal/catch_matchers.h
|
||||
${HEADER_DIR}/internal/catch_matchers_exception.hpp
|
||||
${HEADER_DIR}/internal/catch_matchers_floating.h
|
||||
${HEADER_DIR}/internal/catch_matchers_generic.hpp
|
||||
${HEADER_DIR}/internal/catch_matchers_string.h
|
||||
@@ -190,7 +194,6 @@ set(INTERNAL_HEADERS
|
||||
${HEADER_DIR}/internal/catch_to_string.hpp
|
||||
${HEADER_DIR}/internal/catch_tostring.h
|
||||
${HEADER_DIR}/internal/catch_totals.h
|
||||
${HEADER_DIR}/internal/catch_type_traits.hpp
|
||||
${HEADER_DIR}/internal/catch_uncaught_exceptions.h
|
||||
${HEADER_DIR}/internal/catch_user_interfaces.h
|
||||
${HEADER_DIR}/internal/catch_version.h
|
||||
@@ -227,6 +230,7 @@ set(IMPL_SOURCES
|
||||
${HEADER_DIR}/internal/catch_list.cpp
|
||||
${HEADER_DIR}/internal/catch_leak_detector.cpp
|
||||
${HEADER_DIR}/internal/catch_matchers.cpp
|
||||
${HEADER_DIR}/internal/catch_matchers_exception.cpp
|
||||
${HEADER_DIR}/internal/catch_matchers_floating.cpp
|
||||
${HEADER_DIR}/internal/catch_matchers_generic.cpp
|
||||
${HEADER_DIR}/internal/catch_matchers_string.cpp
|
||||
@@ -422,6 +426,30 @@ set_tests_properties(RegressionCheck-1670 PROPERTIES PASS_REGULAR_EXPRESSION "Pa
|
||||
add_test(NAME VersionCheck COMMAND $<TARGET_FILE:SelfTest> -h)
|
||||
set_tests_properties(VersionCheck PROPERTIES PASS_REGULAR_EXPRESSION "Catch v${PROJECT_VERSION}")
|
||||
|
||||
add_test(NAME LibIdentityTest COMMAND $<TARGET_FILE:SelfTest> --libidentify)
|
||||
set_tests_properties(LibIdentityTest PROPERTIES PASS_REGULAR_EXPRESSION "description: A Catch2 test executable")
|
||||
|
||||
add_test(NAME FilenameAsTagsTest COMMAND $<TARGET_FILE:SelfTest> -\# --list-tags)
|
||||
set_tests_properties(FilenameAsTagsTest PROPERTIES PASS_REGULAR_EXPRESSION "\\[#Approx.tests\\]")
|
||||
|
||||
add_test(NAME EscapeSpecialCharactersInTestNames COMMAND $<TARGET_FILE:SelfTest> "Test with special\\, characters \"in name")
|
||||
set_tests_properties(EscapeSpecialCharactersInTestNames PROPERTIES PASS_REGULAR_EXPRESSION "1 assertion in 1 test case")
|
||||
|
||||
add_test(NAME TestsInFile::SimpleSpecs COMMAND $<TARGET_FILE:SelfTest> "-f ${CATCH_DIR}/projects/SelfTest/Misc/plain-old-tests.input")
|
||||
set_tests_properties(TestsInFile::SimpleSpecs PROPERTIES PASS_REGULAR_EXPRESSION "6 assertions in 2 test cases")
|
||||
|
||||
add_test(NAME TestsInFile::EscapeSpecialCharacters COMMAND $<TARGET_FILE:SelfTest> "-f ${CATCH_DIR}/projects/SelfTest/Misc/special-characters-in-file.input")
|
||||
set_tests_properties(TestsInFile::EscapeSpecialCharacters PROPERTIES PASS_REGULAR_EXPRESSION "1 assertion in 1 test case")
|
||||
|
||||
# CTest does not allow us to create an AND of required regular expressions,
|
||||
# so we have to split the test into 2 parts and look for parts of the expected
|
||||
# output separately.
|
||||
add_test(NAME TestsInFile::InvalidTestNames-1 COMMAND $<TARGET_FILE:SelfTest> "-f ${CATCH_DIR}/projects/SelfTest/Misc/invalid-test-names.input")
|
||||
set_tests_properties(TestsInFile::InvalidTestNames-1 PROPERTIES PASS_REGULAR_EXPRESSION "Invalid Filter: \"Test with special, characters in \\\\\" name\"")
|
||||
|
||||
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")
|
||||
|
||||
|
||||
if (CATCH_USE_VALGRIND)
|
||||
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
|
||||
|
@@ -126,6 +126,16 @@ set_tests_properties(
|
||||
PASS_REGULAR_EXPRESSION "benchmark name samples iterations estimated"
|
||||
)
|
||||
|
||||
# This test touches windows.h, so it should only be compiled under msvc
|
||||
if (MSVC)
|
||||
# This test fails if it does not compile and succeeds otherwise
|
||||
add_executable(WindowsHeader ${TESTS_DIR}/X90-WindowsHeaderInclusion.cpp)
|
||||
set_property( TARGET WindowsHeader PROPERTY CXX_STANDARD 11 )
|
||||
set_property( TARGET WindowsHeader PROPERTY CXX_STANDARD_REQUIRED ON )
|
||||
set_property( TARGET WindowsHeader PROPERTY CXX_EXTENSIONS OFF )
|
||||
target_include_directories( WindowsHeader PRIVATE ${SINGLE_INCLUDE_PATH} )
|
||||
add_test(NAME WindowsHeader COMMAND WindowsHeader -r compact)
|
||||
endif()
|
||||
|
||||
set( EXTRA_TEST_BINARIES
|
||||
PrefixedMacros
|
||||
@@ -145,3 +155,4 @@ foreach( test ${EXTRA_TEST_BINARIES} )
|
||||
target_include_directories( ${test} PRIVATE ${SINGLE_INCLUDE_PATH} )
|
||||
endforeach()
|
||||
|
||||
|
||||
|
12
projects/ExtraTests/X90-WindowsHeaderInclusion.cpp
Normal file
12
projects/ExtraTests/X90-WindowsHeaderInclusion.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
// X90-WindowsHeaderInclusion.cpp
|
||||
// Test that the Catch2 header compiles even after including windows.h
|
||||
// without defining NOMINMAX first. As an FYI, if you do that, you are
|
||||
// wrong.
|
||||
|
||||
#include <windows.h>
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
TEST_CASE("Catch2 did survive compilation with windows.h", "[compile-test]") {
|
||||
SUCCEED();
|
||||
}
|
@@ -243,9 +243,6 @@ Tricky.tests.cpp:<line number>: passed: true
|
||||
Tricky.tests.cpp:<line number>: passed: true
|
||||
Tricky.tests.cpp:<line number>: passed: true
|
||||
Tricky.tests.cpp:<line number>: passed: true
|
||||
Approx.tests.cpp:<line number>: passed: INFINITY == Approx(INFINITY) for: inff == Approx( inf )
|
||||
Approx.tests.cpp:<line number>: passed: NAN != Approx(NAN) for: nanf != Approx( nan )
|
||||
Approx.tests.cpp:<line number>: passed: !(NAN == Approx(NAN)) for: !(nanf == Approx( nan ))
|
||||
Message.tests.cpp:<line number>: passed: with 7 messages: 'a := 1' and 'b := 2' and 'c := 3' and 'a + b := 3' and 'a+b := 3' and 'c > b := true' and 'a == 1 := true'
|
||||
Message.tests.cpp:<line number>: passed: with 7 messages: 'std::vector<int>{1, 2, 3}[0, 1, 2] := 3' and 'std::vector<int>{1, 2, 3}[(0, 1)] := 2' and 'std::vector<int>{1, 2, 3}[0] := 1' and '(helper_1436<int, int>{12, -12}) := { 12, -12 }' and '(helper_1436<int, int>(-12, 12)) := { -12, 12 }' and '(1, 2) := 2' and '(2, 3) := 3'
|
||||
Message.tests.cpp:<line number>: passed: with 11 messages: '("comma, in string", "escaped, \", ") := "escaped, ", "' and '"single quote in string,'," := "single quote in string,',"' and '"some escapes, \\,\\\\" := "some escapes, \,\\"' and '"some, ), unmatched, } prenheses {[<" := "some, ), unmatched, } prenheses {[<"' and ''"' := '"'' and ''\'' := '''' and '',' := ','' and ''}' := '}'' and '')' := ')'' and ''(' := '('' and ''{' := '{''
|
||||
@@ -279,6 +276,10 @@ Tricky.tests.cpp:<line number>: passed: true
|
||||
Tricky.tests.cpp:<line number>: passed: std::vector<int>{1, 2} == std::vector<int>{1, 2} for: { 1, 2 } == { 1, 2 }
|
||||
Tricky.tests.cpp:<line number>: passed: a for: 0x<hex digits>
|
||||
Tricky.tests.cpp:<line number>: passed: a == &foo for: 0x<hex digits> == 0x<hex digits>
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: SimplePcg32{} == SimplePcg32{} for: {?} == {?}
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: SimplePcg32{ 0 } != SimplePcg32{} for: {?} != {?}
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: !(SimplePcg32{ 1 } == SimplePcg32{ 2 }) for: !({?} == {?})
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: !(SimplePcg32{ 1 } != SimplePcg32{ 1 }) for: !({?} != {?})
|
||||
Approx.tests.cpp:<line number>: passed: td == Approx(10.0) for: StrongDoubleTypedef(10) == Approx( 10.0 )
|
||||
Approx.tests.cpp:<line number>: passed: Approx(10.0) == td for: Approx( 10.0 ) == StrongDoubleTypedef(10)
|
||||
Approx.tests.cpp:<line number>: passed: td != Approx(11.0) for: StrongDoubleTypedef(10) != Approx( 11.0 )
|
||||
@@ -313,6 +314,20 @@ 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>: 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
|
||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||
Generators.tests.cpp:<line number>: passed: call_count == 1 for: 1 == 1
|
||||
Generators.tests.cpp:<line number>: passed: make_data().size() == test_count for: 6 == 6
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'custom exception - not std'; expression was: throwCustom()
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'custom exception - not std'; expression was: throwCustom(), std::exception
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'custom std exception'
|
||||
@@ -370,16 +385,20 @@ Matchers.tests.cpp:<line number>: failed: expected exception, got none; expressi
|
||||
Matchers.tests.cpp:<line number>: failed: expected exception, got none; expression was: doesNotThrow(), SpecialException, ExceptionMatcher{1}
|
||||
Matchers.tests.cpp:<line number>: failed: unexpected exception with message: 'Unknown exception'; expression was: throwsAsInt(1), SpecialException, ExceptionMatcher{1}
|
||||
Matchers.tests.cpp:<line number>: failed: unexpected exception with message: 'Unknown exception'; expression was: throwsAsInt(1), SpecialException, ExceptionMatcher{1}
|
||||
Matchers.tests.cpp:<line number>: failed: throws(3), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
|
||||
Matchers.tests.cpp:<line number>: failed: throws(4), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
|
||||
Matchers.tests.cpp:<line number>: passed: throws(1), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
|
||||
Matchers.tests.cpp:<line number>: passed: throws(2), SpecialException, ExceptionMatcher{2} for: SpecialException::what special exception has value of 2
|
||||
Matchers.tests.cpp:<line number>: failed: throwsSpecialException(3), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
|
||||
Matchers.tests.cpp:<line number>: failed: throwsSpecialException(4), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
|
||||
Matchers.tests.cpp:<line number>: passed: throwsSpecialException(1), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
|
||||
Matchers.tests.cpp:<line number>: passed: throwsSpecialException(2), SpecialException, ExceptionMatcher{2} for: SpecialException::what special exception has value of 2
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows(), "expected exception" for: "expected exception" equals: "expected exception"
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) for: "expected exception" equals: "expected exception" (case insensitive)
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows(), StartsWith( "expected" ) for: "expected exception" starts with: "expected"
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows(), EndsWith( "exception" ) for: "expected exception" ends with: "exception"
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows(), Contains( "except" ) for: "expected exception" contains: "except"
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) for: "expected exception" contains: "except" (case insensitive)
|
||||
Matchers.tests.cpp:<line number>: passed: throwsDerivedException(), DerivedException, Message("DerivedException::what") for: DerivedException::what exception message matches "DerivedException::what"
|
||||
Matchers.tests.cpp:<line number>: passed: throwsDerivedException(), DerivedException, !Message("derivedexception::what") for: DerivedException::what not exception message matches "derivedexception::what"
|
||||
Matchers.tests.cpp:<line number>: passed: throwsSpecialException(2), SpecialException, !Message("DerivedException::what") for: SpecialException::what not exception message matches "DerivedException::what"
|
||||
Matchers.tests.cpp:<line number>: passed: throwsSpecialException(2), SpecialException, Message("SpecialException::what") for: SpecialException::what exception message matches "SpecialException::what"
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'expected exception'; expression was: thisThrows(), std::string
|
||||
Exception.tests.cpp:<line number>: failed: expected exception, got none; expression was: thisDoesntThrow(), std::domain_error
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'expected exception'; expression was: thisThrows()
|
||||
@@ -392,6 +411,11 @@ Misc.tests.cpp:<line number>: passed: Factorial(1) == 1 for: 1 == 1
|
||||
Misc.tests.cpp:<line number>: passed: Factorial(2) == 2 for: 2 == 2
|
||||
Misc.tests.cpp:<line number>: passed: Factorial(3) == 6 for: 6 == 6
|
||||
Misc.tests.cpp:<line number>: passed: Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
|
||||
Matchers.tests.cpp:<line number>: passed: 10., WithinRel(11.1, 0.1) for: 10.0 and 11.1 are within 10% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 10., !WithinRel(11.2, 0.1) for: 10.0 not and 11.2 are within 10% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 1., !WithinRel(0., 0.99) for: 1.0 not and 0 are within 99% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: -0., WithinRel(0.) for: -0.0 and 0 are within 2.22045e-12% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: v1, WithinRel(v2) for: 0.0 and 2.22507e-308 are within 2.22045e-12% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 1., WithinAbs(1., 0) for: 1.0 is within 0.0 of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: 0., WithinAbs(1., 1) for: 0.0 is within 1.0 of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: 0., !WithinAbs(1., 0.99) for: 0.0 not is within 0.99 of 1.0
|
||||
@@ -400,18 +424,27 @@ Matchers.tests.cpp:<line number>: passed: 11., !WithinAbs(10., 0.5) for: 11.0 no
|
||||
Matchers.tests.cpp:<line number>: passed: 10., !WithinAbs(11., 0.5) for: 10.0 not is within 0.5 of 11.0
|
||||
Matchers.tests.cpp:<line number>: passed: -10., WithinAbs(-10., 0.5) for: -10.0 is within 0.5 of -10.0
|
||||
Matchers.tests.cpp:<line number>: passed: -10., WithinAbs(-9.6, 0.5) for: -10.0 is within 0.5 of -9.6
|
||||
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0 ([1.00000000000000000, 1.00000000000000000])
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1., 2.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0 ([0.99999999999999989, 1.00000000000000022])
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1., 0.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0 ([0.99999999999999989, 1.00000000000000022])
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1., 2.), !WithinULP(1., 0) for: 1.0 not is within 0 ULPs of 1.0 ([1.00000000000000000, 1.00000000000000000])
|
||||
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0 ([1.00000000000000000, 1.00000000000000000])
|
||||
Matchers.tests.cpp:<line number>: passed: -0., WithinULP(0., 0) for: -0.0 is within 0 ULPs of 0.0 ([0.00000000000000000, 0.00000000000000000])
|
||||
Matchers.tests.cpp:<line number>: passed: 1., WithinAbs(1., 0.5) || WithinULP(2., 1) for: 1.0 ( is within 0.5 of 1.0 or is within 1 ULPs of 2.0 ([1.99999999999999978, 2.00000000000000044]) )
|
||||
Matchers.tests.cpp:<line number>: passed: 1., WithinAbs(2., 0.5) || WithinULP(1., 0) for: 1.0 ( is within 0.5 of 2.0 or is within 0 ULPs of 1.0 ([1.00000000000000000, 1.00000000000000000]) )
|
||||
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0000000000000000e+00 ([1.0000000000000000e+00, 1.0000000000000000e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1., 2.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0000000000000000e+00 ([9.9999999999999989e-01, 1.0000000000000002e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: 0., WithinULP(nextafter(0., 1.), 1) for: 0.0 is within 1 ULPs of 4.9406564584124654e-324 ([0.0000000000000000e+00, 9.8813129168249309e-324])
|
||||
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(nextafter(1., 0.), 1) for: 1.0 is within 1 ULPs of 9.9999999999999989e-01 ([9.9999999999999978e-01, 1.0000000000000000e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: 1., !WithinULP(nextafter(1., 2.), 0) for: 1.0 not is within 0 ULPs of 1.0000000000000002e+00 ([1.0000000000000002e+00, 1.0000000000000002e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0000000000000000e+00 ([1.0000000000000000e+00, 1.0000000000000000e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: -0., WithinULP(0., 0) for: -0.0 is within 0 ULPs of 0.0000000000000000e+00 ([0.0000000000000000e+00, 0.0000000000000000e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: 1., WithinAbs(1., 0.5) || WithinULP(2., 1) for: 1.0 ( is within 0.5 of 1.0 or is within 1 ULPs of 2.0000000000000000e+00 ([1.9999999999999998e+00, 2.0000000000000004e+00]) )
|
||||
Matchers.tests.cpp:<line number>: passed: 1., WithinAbs(2., 0.5) || WithinULP(1., 0) for: 1.0 ( is within 0.5 of 2.0 or is within 0 ULPs of 1.0000000000000000e+00 ([1.0000000000000000e+00, 1.0000000000000000e+00]) )
|
||||
Matchers.tests.cpp:<line number>: passed: 0.0001, WithinAbs(0., 0.001) || WithinRel(0., 0.1) for: 0.0001 ( is within 0.001 of 0.0 or and 0 are within 10% of each other )
|
||||
Matchers.tests.cpp:<line number>: passed: WithinAbs(1., 0.)
|
||||
Matchers.tests.cpp:<line number>: passed: WithinAbs(1., -1.), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: WithinULP(1., 0)
|
||||
Matchers.tests.cpp:<line number>: passed: WithinULP(1., -1), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel(1., 0.)
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel(1., -0.2), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel(1., 1.), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: 10.f, WithinRel(11.1f, 0.1f) for: 10.0f and 11.1 are within 10% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 10.f, !WithinRel(11.2f, 0.1f) for: 10.0f not and 11.2 are within 10% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, !WithinRel(0.f, 0.99f) for: 1.0f not and 0 are within 99% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: -0.f, WithinRel(0.f) for: -0.0f and 0 are within 0.00119209% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: v1, WithinRel(v2) for: 0.0f and 1.17549e-38 are within 0.00119209% of each other
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinAbs(1.f, 0) for: 1.0f is within 0.0 of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: 0.f, WithinAbs(1.f, 1) for: 0.0f is within 1.0 of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: 0.f, !WithinAbs(1.f, 0.99f) for: 0.0f not is within 0.9900000095 of 1.0
|
||||
@@ -421,18 +454,23 @@ Matchers.tests.cpp:<line number>: passed: 11.f, !WithinAbs(10.f, 0.5f) for: 11.0
|
||||
Matchers.tests.cpp:<line number>: passed: 10.f, !WithinAbs(11.f, 0.5f) for: 10.0f not is within 0.5 of 11.0
|
||||
Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs(-10.f, 0.5f) for: -10.0f is within 0.5 of -10.0
|
||||
Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs(-9.6f, 0.5f) for: -10.0f is within 0.5 of -9.6000003815
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.0f ([1.00000000000000000, 1.00000000000000000])
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 2.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f ([0.99999994039535522, 1.00000011920928955])
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 0.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f ([0.99999994039535522, 1.00000011920928955])
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 2.f), !WithinULP(1.f, 0) for: 1.0f not is within 0 ULPs of 1.0f ([1.00000000000000000, 1.00000000000000000])
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.0f ([1.00000000000000000, 1.00000000000000000])
|
||||
Matchers.tests.cpp:<line number>: passed: -0.f, WithinULP(0.f, 0) for: -0.0f is within 0 ULPs of 0.0f ([0.00000000000000000, 0.00000000000000000])
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinAbs(1.f, 0.5) || WithinULP(1.f, 1) for: 1.0f ( is within 0.5 of 1.0 or is within 1 ULPs of 1.0f ([0.99999994039535522, 1.00000011920928955]) )
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinAbs(2.f, 0.5) || WithinULP(1.f, 0) for: 1.0f ( is within 0.5 of 2.0 or is within 0 ULPs of 1.0f ([1.00000000000000000, 1.00000000000000000]) )
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 2.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.00000000e+00f ([9.99999940e-01, 1.00000012e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: 0.f, WithinULP(nextafter(0.f, 1.f), 1) for: 0.0f is within 1 ULPs of 1.40129846e-45f ([0.00000000e+00, 2.80259693e-45])
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(nextafter(1.f, 0.f), 1) for: 1.0f is within 1 ULPs of 9.99999940e-01f ([9.99999881e-01, 1.00000000e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, !WithinULP(nextafter(1.f, 2.f), 0) for: 1.0f not is within 0 ULPs of 1.00000012e+00f ([1.00000012e+00, 1.00000012e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: -0.f, WithinULP(0.f, 0) for: -0.0f is within 0 ULPs of 0.00000000e+00f ([0.00000000e+00, 0.00000000e+00])
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinAbs(1.f, 0.5) || WithinULP(1.f, 1) for: 1.0f ( is within 0.5 of 1.0 or is within 1 ULPs of 1.00000000e+00f ([9.99999940e-01, 1.00000012e+00]) )
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinAbs(2.f, 0.5) || WithinULP(1.f, 0) for: 1.0f ( is within 0.5 of 2.0 or is within 0 ULPs of 1.00000000e+00f ([1.00000000e+00, 1.00000000e+00]) )
|
||||
Matchers.tests.cpp:<line number>: passed: 0.0001f, WithinAbs(0.f, 0.001f) || WithinRel(0.f, 0.1f) for: 0.0001f ( is within 0.001 of 0.0 or and 0 are within 10% of each other )
|
||||
Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, 0.f)
|
||||
Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, -1.f), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, 0)
|
||||
Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, -1), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, static_cast<uint64_t>(-1)), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel(1.f, 0.f)
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel(1.f, -0.2f), std::domain_error
|
||||
Matchers.tests.cpp:<line number>: passed: WithinRel(1.f, 1.f), std::domain_error
|
||||
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
|
||||
@@ -729,6 +767,51 @@ Condition.tests.cpp:<line number>: passed: data.str_hello < "hellp" for: "hello"
|
||||
Condition.tests.cpp:<line number>: passed: data.str_hello < "zebra" for: "hello" < "zebra"
|
||||
Condition.tests.cpp:<line number>: passed: data.str_hello > "hellm" for: "hello" > "hellm"
|
||||
Condition.tests.cpp:<line number>: passed: data.str_hello > "a" for: "hello" > "a"
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 4242248763 (0x<hex digits>)
|
||||
==
|
||||
4242248763 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 1867888929 (0x<hex digits>)
|
||||
==
|
||||
1867888929 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 1276619030 (0x<hex digits>)
|
||||
==
|
||||
1276619030 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 1911218783 (0x<hex digits>)
|
||||
==
|
||||
1911218783 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 1827115164 (0x<hex digits>)
|
||||
==
|
||||
1827115164 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 1472234645 (0x<hex digits>)
|
||||
==
|
||||
1472234645 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 868832940 (0x<hex digits>)
|
||||
==
|
||||
868832940 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 570883446 (0x<hex digits>)
|
||||
==
|
||||
570883446 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 889299803 (0x<hex digits>)
|
||||
==
|
||||
889299803 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 4261393167 (0x<hex digits>)
|
||||
==
|
||||
4261393167 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 1472234645 (0x<hex digits>)
|
||||
==
|
||||
1472234645 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 868832940 (0x<hex digits>)
|
||||
==
|
||||
868832940 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 570883446 (0x<hex digits>)
|
||||
==
|
||||
570883446 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 889299803 (0x<hex digits>)
|
||||
==
|
||||
889299803 (0x<hex digits>)
|
||||
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 4261393167 (0x<hex digits>)
|
||||
==
|
||||
4261393167 (0x<hex digits>)
|
||||
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Message from section one'
|
||||
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Message from section two'
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.hasFilters() == false for: false == false
|
||||
@@ -866,6 +949,16 @@ CmdLine.tests.cpp:<line number>: passed: spec.matches( tcA ) == false for: false
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches( tcB ) == false for: false == false
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches( tcC ) == false for: false == false
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches( tcD ) == true for: true == 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( " 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( " 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( "aardvark " ) ) for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: spec.matches( fakeTestCase( "aardvark" ) ) 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
|
||||
@@ -983,7 +1076,6 @@ Approx.tests.cpp:<line number>: passed: d != 1.22_a for: 1.23 != Approx( 1.22 )
|
||||
Approx.tests.cpp:<line number>: passed: Approx( d ) == 1.23 for: Approx( 1.23 ) == 1.23
|
||||
Approx.tests.cpp:<line number>: passed: Approx( d ) != 1.22 for: Approx( 1.23 ) != 1.22
|
||||
Approx.tests.cpp:<line number>: passed: Approx( d ) != 1.24 for: Approx( 1.23 ) != 1.24
|
||||
Approx.tests.cpp:<line number>: passed: INFINITY == Approx(INFINITY) for: inff == Approx( inf )
|
||||
Message from section one
|
||||
Message from section two
|
||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), StartsWith("This String") for: "this string contains 'abc' as a substring" starts with: "This String"
|
||||
@@ -1031,6 +1123,7 @@ String.tests.cpp:<line number>: passed: ss.size() == 6 for: 6 == 6
|
||||
String.tests.cpp:<line number>: passed: std::strcmp( ss.c_str(), "world!" ) == 0 for: 0 == 0
|
||||
String.tests.cpp:<line number>: passed: s.c_str() == s2.c_str() for: "hello world!" == "hello world!"
|
||||
String.tests.cpp:<line number>: passed: s.c_str() != ss.c_str() for: "hello world!" != "hello"
|
||||
String.tests.cpp:<line number>: passed: s.substr(s.size() + 1, 123).empty() for: true
|
||||
String.tests.cpp:<line number>: passed: StringRef("hello") == StringRef("hello") for: hello == hello
|
||||
String.tests.cpp:<line number>: passed: StringRef("hello") != StringRef("cello") for: hello != cello
|
||||
String.tests.cpp:<line number>: passed: sr == "a standard string" for: a standard string == "a standard string"
|
||||
@@ -1043,11 +1136,6 @@ String.tests.cpp:<line number>: passed: stdStr == "a stringref" for: "a stringre
|
||||
String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
|
||||
String.tests.cpp:<line number>: passed: stdStr == "a stringref" for: "a stringref" == "a stringref"
|
||||
String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
|
||||
String.tests.cpp:<line number>: passed: stdStr == "a stringref" for: "a stringref" == "a stringref"
|
||||
String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
|
||||
String.tests.cpp:<line number>: passed: ascii.numberOfCharacters() == ascii.size() for: 39 == 39
|
||||
String.tests.cpp:<line number>: passed: simpleu8.numberOfCharacters() == 30 for: 30 == 30
|
||||
String.tests.cpp:<line number>: passed: emojis.numberOfCharacters() == 9 for: 9 == 9
|
||||
ToStringChrono.tests.cpp:<line number>: passed: minute == seconds for: 1 m == 60 s
|
||||
ToStringChrono.tests.cpp:<line number>: passed: hour != seconds for: 1 h != 60 s
|
||||
ToStringChrono.tests.cpp:<line number>: passed: micro != milli for: 1 us != 1 ms
|
||||
@@ -1085,6 +1173,7 @@ Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for:
|
||||
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1 == 1
|
||||
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1.0 == 1
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 1 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 1 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
|
||||
@@ -1228,6 +1317,7 @@ Misc.tests.cpp:<line number>: passed: v.size() == V for: 15 == 15
|
||||
Misc.tests.cpp:<line number>: passed: v.capacity() >= V for: 15 >= 15
|
||||
VariadicMacros.tests.cpp:<line number>: passed: with 1 message: 'no assertions'
|
||||
Tricky.tests.cpp:<line number>: passed: 0x<hex digits> == bit30and31 for: 3221225472 (0x<hex digits>) == 3221225472
|
||||
CmdLine.tests.cpp:<line number>: passed:
|
||||
Message.tests.cpp:<line number>: failed - but was ok: 1 == 2
|
||||
Misc.tests.cpp:<line number>: passed: with 1 message: 'oops!'
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'For some reason someone is throwing a string literal!'
|
||||
@@ -1298,6 +1388,30 @@ PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false
|
||||
PartTracker.tests.cpp:<line number>: passed: s1.isComplete() for: true
|
||||
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
|
||||
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() for: true
|
||||
StringManip.tests.cpp:<line number>: passed: trim(std::string(no_whitespace)) == no_whitespace for: "There is no extra whitespace here"
|
||||
==
|
||||
"There is no extra whitespace here"
|
||||
StringManip.tests.cpp:<line number>: passed: trim(std::string(leading_whitespace)) == no_whitespace for: "There is no extra whitespace here"
|
||||
==
|
||||
"There is no extra whitespace here"
|
||||
StringManip.tests.cpp:<line number>: passed: trim(std::string(trailing_whitespace)) == no_whitespace for: "There is no extra whitespace here"
|
||||
==
|
||||
"There is no extra whitespace here"
|
||||
StringManip.tests.cpp:<line number>: passed: trim(std::string(whitespace_at_both_ends)) == no_whitespace for: "There is no extra whitespace here"
|
||||
==
|
||||
"There is no extra whitespace here"
|
||||
StringManip.tests.cpp:<line number>: passed: trim(StringRef(no_whitespace)) == StringRef(no_whitespace) for: There is no extra whitespace here
|
||||
==
|
||||
There is no extra whitespace here
|
||||
StringManip.tests.cpp:<line number>: passed: trim(StringRef(leading_whitespace)) == StringRef(no_whitespace) for: There is no extra whitespace here
|
||||
==
|
||||
There is no extra whitespace here
|
||||
StringManip.tests.cpp:<line number>: passed: trim(StringRef(trailing_whitespace)) == StringRef(no_whitespace) for: There is no extra whitespace here
|
||||
==
|
||||
There is no extra whitespace here
|
||||
StringManip.tests.cpp:<line number>: passed: trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace) for: There is no extra whitespace here
|
||||
==
|
||||
There is no extra whitespace here
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: '3.14'
|
||||
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 )
|
||||
@@ -1483,13 +1597,13 @@ Tricky.tests.cpp:<line number>: passed: ptr.get() == 0 for: 0 == 0
|
||||
ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" for: "{ { 42, "Arthur" }, { "Ford", 24 } }"
|
||||
==
|
||||
"{ { 42, "Arthur" }, { "Ford", 24 } }"
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "" ), Equals( std::vector<std::string>{} ) for: { } Equals: { }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<std::string>{"Value1"} ) for: { "Value1" } Equals: { "Value1" }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "Value1" ), Equals( std::vector<std::string>{"Value1"} ) for: { "Value1" } Equals: { "Value1" }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "EnumName::Value1" ), Equals(std::vector<std::string>{"Value1"} ) for: { "Value1" } Equals: { "Value1" }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<std::string>{"Value1", "Value2"} ) for: { "Value1", "Value2" } Equals: { "Value1", "Value2" }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<std::string>{"Value1", "Value2", "Value3"} ) for: { "Value1", "Value2", "Value3" } Equals: { "Value1", "Value2", "Value3" }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<std::string>{"Value1", "Value2", "Value3"} ) for: { "Value1", "Value2", "Value3" } Equals: { "Value1", "Value2", "Value3" }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) for: { } Equals: { }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "Value1" ), Equals( std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) for: { Value1 } Equals: { Value1 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) for: { Value1, Value2 } Equals: { Value1, Value2 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
ToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||
Tricky.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
|
||||
Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY be seen IF info is printed for passing assertions'
|
||||
Message.tests.cpp:<line number>: failed: false with 2 messages: 'this SHOULD be seen' and 'this SHOULD also be seen'
|
||||
@@ -1500,26 +1614,26 @@ Message.tests.cpp:<line number>: passed: true
|
||||
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
|
||||
Misc.tests.cpp:<line number>: passed: b != a for: 2 != 1
|
||||
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
|
||||
String.tests.cpp:<line number>: passed: Catch::replaceInPlace( letters, "b", "z" ) for: true
|
||||
String.tests.cpp:<line number>: passed: letters == "azcdefcg" for: "azcdefcg" == "azcdefcg"
|
||||
String.tests.cpp:<line number>: passed: Catch::replaceInPlace( letters, "c", "z" ) for: true
|
||||
String.tests.cpp:<line number>: passed: letters == "abzdefzg" for: "abzdefzg" == "abzdefzg"
|
||||
String.tests.cpp:<line number>: passed: Catch::replaceInPlace( letters, "a", "z" ) for: true
|
||||
String.tests.cpp:<line number>: passed: letters == "zbcdefcg" for: "zbcdefcg" == "zbcdefcg"
|
||||
String.tests.cpp:<line number>: passed: Catch::replaceInPlace( letters, "g", "z" ) for: true
|
||||
String.tests.cpp:<line number>: passed: letters == "abcdefcz" for: "abcdefcz" == "abcdefcz"
|
||||
String.tests.cpp:<line number>: passed: Catch::replaceInPlace( letters, letters, "replaced" ) for: true
|
||||
String.tests.cpp:<line number>: passed: letters == "replaced" for: "replaced" == "replaced"
|
||||
String.tests.cpp:<line number>: passed: !(Catch::replaceInPlace( letters, "x", "z" )) for: !false
|
||||
String.tests.cpp:<line number>: passed: letters == letters for: "abcdefcg" == "abcdefcg"
|
||||
String.tests.cpp:<line number>: passed: Catch::replaceInPlace( s, "'", "|'" ) for: true
|
||||
String.tests.cpp:<line number>: passed: s == "didn|'t" for: "didn|'t" == "didn|'t"
|
||||
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, "b", "z") for: true
|
||||
StringManip.tests.cpp:<line number>: passed: letters == "azcdefcg" for: "azcdefcg" == "azcdefcg"
|
||||
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, "c", "z") for: true
|
||||
StringManip.tests.cpp:<line number>: passed: letters == "abzdefzg" for: "abzdefzg" == "abzdefzg"
|
||||
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, "a", "z") for: true
|
||||
StringManip.tests.cpp:<line number>: passed: letters == "zbcdefcg" for: "zbcdefcg" == "zbcdefcg"
|
||||
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, "g", "z") for: true
|
||||
StringManip.tests.cpp:<line number>: passed: letters == "abcdefcz" for: "abcdefcz" == "abcdefcz"
|
||||
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, letters, "replaced") for: true
|
||||
StringManip.tests.cpp:<line number>: passed: letters == "replaced" for: "replaced" == "replaced"
|
||||
StringManip.tests.cpp:<line number>: passed: !(Catch::replaceInPlace(letters, "x", "z")) for: !false
|
||||
StringManip.tests.cpp:<line number>: passed: letters == letters for: "abcdefcg" == "abcdefcg"
|
||||
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(s, "'", "|'") for: true
|
||||
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: "." )
|
||||
String.tests.cpp:<line number>: passed: splitStringRef("", ',' ), Equals(std::vector<StringRef>() ) for: { } Equals: { }
|
||||
String.tests.cpp:<line number>: passed: splitStringRef("abc", ',' ), Equals(std::vector<StringRef>{"abc"} ) for: { abc } Equals: { abc }
|
||||
String.tests.cpp:<line number>: passed: splitStringRef("abc,def", ',' ), Equals(std::vector<StringRef>{"abc", "def"} ) for: { abc, def } Equals: { abc, def }
|
||||
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 }
|
||||
Message.tests.cpp:<line number>: failed: false with 4 messages: 'Count 1 to 3...' and '1' and '2' and '3'
|
||||
Message.tests.cpp:<line number>: failed: false with 4 messages: 'Count 4 to 6...' and '4' and '5' and '6'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( emptyMap ) == "{ }" for: "{ }" == "{ }"
|
||||
|
@@ -520,12 +520,12 @@ Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>: FAILED:
|
||||
CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{1} )
|
||||
CHECK_THROWS_MATCHES( throwsSpecialException(3), SpecialException, ExceptionMatcher{1} )
|
||||
with expansion:
|
||||
SpecialException::what special exception has value of 1
|
||||
|
||||
Matchers.tests.cpp:<line number>: FAILED:
|
||||
REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{1} )
|
||||
REQUIRE_THROWS_MATCHES( throwsSpecialException(4), SpecialException, ExceptionMatcher{1} )
|
||||
with expansion:
|
||||
SpecialException::what special exception has value of 1
|
||||
|
||||
@@ -1380,6 +1380,6 @@ due to unexpected exception with message:
|
||||
Why would you throw a std::string?
|
||||
|
||||
===============================================================================
|
||||
test cases: 298 | 224 passed | 70 failed | 4 failed as expected
|
||||
assertions: 1553 | 1401 passed | 131 failed | 21 failed as expected
|
||||
test cases: 304 | 230 passed | 70 failed | 4 failed as expected
|
||||
assertions: 1621 | 1469 passed | 131 failed | 21 failed as expected
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuitesloose text artifact
|
||||
>
|
||||
<testsuite name="<exe-name>" errors="17" failures="132" tests="1571" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="17" failures="132" tests="1639" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<properties>
|
||||
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/>
|
||||
<property name="random-seed" value="1"/>
|
||||
@@ -232,7 +232,6 @@ Exception.tests.cpp:<line number>
|
||||
<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}"/>
|
||||
<testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another other section" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Assorted miscellaneous tests" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="CAPTURE can deal with complex expressions" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="CAPTURE can deal with complex expressions involving commas" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="CAPTURE parses string and character constants" time="{duration}"/>
|
||||
@@ -243,6 +242,7 @@ Exception.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Character pretty printing/Low ASCII" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Commas in various macros are allowed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Comparing function pointers" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Comparison ops" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Comparison with explicitly convertible types" time="{duration}"/>
|
||||
<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}"/>
|
||||
@@ -255,6 +255,9 @@ Matchers.tests.cpp:<line number>
|
||||
Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Copy and then generate a range/from var and iterators" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Copy and then generate a range/From a temporary container" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Copy and then generate a range/Final validation" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Custom exceptions can be translated when testing for nothrow" time="{duration}">
|
||||
<error message="throwCustom()" type="REQUIRE_NOTHROW">
|
||||
custom exception - not std
|
||||
@@ -368,6 +371,7 @@ Matchers.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Exception messages can be tested for/exact match" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Exception messages can be tested for/different case" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Exception messages can be tested for/wildcarded" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Exceptions matchers" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Expected exceptions that don't throw or unexpected exceptions fail the test" time="{duration}">
|
||||
<error message="thisThrows(), std::string" type="CHECK_THROWS_AS">
|
||||
expected exception
|
||||
@@ -399,10 +403,14 @@ Message.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Factorials are computed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Relative" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Relative/Some subnormal values" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Margin" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/ULPs" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Composed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Constructor validation" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Relative" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Relative/Some subnormal values" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Margin" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}"/>
|
||||
@@ -577,6 +585,8 @@ Condition.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Ordering comparison checks that should succeed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Our PCG implementation provides expected results for known seeds/Default seeded" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Our PCG implementation provides expected results for known seeds/Specific seed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Output from all sections is reported/one" time="{duration}">
|
||||
<failure type="FAIL">
|
||||
Message from section one
|
||||
@@ -620,6 +630,8 @@ Message.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Parse test names and tags/empty tag" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Parse test names and tags/empty quoted name" time="{duration}"/>
|
||||
<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="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}"/>
|
||||
@@ -722,14 +734,13 @@ Matchers.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/Substrings/non-zero-based substring" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/Substrings/Pointer values of full refs should match" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/Substrings/Pointer values of substring refs should not match" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/Substrings/Past the end substring" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/Comparisons" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/from std::string/implicitly constructed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/from std::string/explicitly constructed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/from std::string/assigned" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/to std::string/implicitly constructed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/to std::string/explicitly constructed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/to std::string/assigned" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/Counting utf-8 codepoints" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Stringifying std::chrono::duration helpers" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Stringifying std::chrono::duration with weird ratios" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Stringifying std::chrono::time_point<system_clock>" time="{duration}"/>
|
||||
@@ -750,9 +761,10 @@ Misc.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.Template_Fixture" name="Template test case method with test types specified inside std::tuple - MyTypes - 0" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.Template_Fixture" name="Template test case method with test types specified inside std::tuple - MyTypes - 1" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.Template_Fixture" name="Template test case method with test types specified inside std::tuple - MyTypes - 2" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside non-copyable and non-movable std::tuple - NonCopyableAndNonMovableTypes - 0" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside non-copyable and non-movable std::tuple - NonCopyableAndNonMovableTypes - 1" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside non-default-constructible std::tuple - MyNonDefaultConstructibleTypes - 0" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside non-default-constructible std::tuple - MyNonDefaultConstructibleTypes - 1" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside non-default-constructible std::tuple - MyNonDefaultConstructibleTypes - 2" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside std::tuple - MyTypes - 0" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside std::tuple - MyTypes - 1" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Template test case with test types specified inside std::tuple - MyTypes - 2" time="{duration}"/>
|
||||
@@ -806,6 +818,7 @@ Misc.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="TemplateTestSig: vectors can be sized and resized - std::string,15/reserving smaller does not change size or capacity" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Test case with one argument" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Test enum bit values" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Test with special, characters "in name" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="The NO_FAIL macro reports a failure but does not fail the test" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="This test 'should' fail but doesn't" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Thrown string literals are translated" time="{duration}">
|
||||
@@ -824,6 +837,7 @@ Exception.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Tracker/successfully close one section, then find another/Re-enter - skips S1 and enters S2/Successfully close S2" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Tracker/successfully close one section, then find another/Re-enter - skips S1 and enters S2/fail S2" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Tracker/open a nested section" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Trim strings" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Unexpected exceptions can be translated" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
3.14
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -262,7 +262,24 @@ TEST_CASE( "Parse test names and tags" ) {
|
||||
CHECK( spec.matches( tcC ) == false );
|
||||
CHECK( spec.matches( tcD ) == true );
|
||||
}
|
||||
SECTION( "Leading and trailing spaces in test spec" ) {
|
||||
TestSpec spec = parseTestSpec( "\" aardvark \"" );
|
||||
CHECK( spec.matches( fakeTestCase( " aardvark " ) ) );
|
||||
CHECK( spec.matches( fakeTestCase( " aardvark" ) ) );
|
||||
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" );
|
||||
CHECK( spec.matches( fakeTestCase( " aardvark " ) ) );
|
||||
CHECK( spec.matches( fakeTestCase( " aardvark" ) ) );
|
||||
CHECK( spec.matches( fakeTestCase( " aardvark " ) ) );
|
||||
CHECK( spec.matches( fakeTestCase( "aardvark " ) ) );
|
||||
CHECK( spec.matches( fakeTestCase( "aardvark" ) ) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) {
|
||||
@@ -489,3 +506,8 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test with special, characters \"in name", "[cli][regression]") {
|
||||
// This test case succeeds if we can invoke it from the CLI
|
||||
SUCCEED();
|
||||
}
|
||||
|
23
projects/SelfTest/IntrospectiveTests/Details.tests.cpp
Normal file
23
projects/SelfTest/IntrospectiveTests/Details.tests.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // unreachable code in the macro expansions
|
||||
#endif
|
||||
|
||||
TEST_CASE("Check that our error handling macros throw the right exceptions", "[!throws][internals][approvals]") {
|
||||
REQUIRE_THROWS_AS(CATCH_INTERNAL_ERROR(""), std::logic_error);
|
||||
REQUIRE_THROWS_AS(CATCH_ERROR(""), std::domain_error);
|
||||
REQUIRE_THROWS_AS(CATCH_RUNTIME_ERROR(""), std::runtime_error);
|
||||
REQUIRE_THROWS_AS([](){CATCH_ENFORCE(false, "");}(), std::domain_error);
|
||||
REQUIRE_NOTHROW([](){CATCH_ENFORCE(true, "");}());
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop) // unreachable code in the macro expansions
|
||||
#endif
|
@@ -250,7 +250,7 @@ int const& TestGen::get() const {
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("GENERATE capture macros", "[generators][internals][.approvals]") {
|
||||
TEST_CASE("GENERATE capture macros", "[generators][internals][approvals]") {
|
||||
auto value = GENERATE(take(10, random(0, 10)));
|
||||
|
||||
non_copyable nc; nc.value = value;
|
||||
@@ -258,3 +258,28 @@ TEST_CASE("GENERATE capture macros", "[generators][internals][.approvals]") {
|
||||
auto value2 = GENERATE_REF(Catch::Generators::GeneratorWrapper<int>(std::unique_ptr<Catch::Generators::IGenerator<int>>(new TestGen(nc))));
|
||||
REQUIRE(value == value2);
|
||||
}
|
||||
|
||||
TEST_CASE("Multiple random generators in one test case output different values", "[generators][internals][approvals]") {
|
||||
SECTION("Integer") {
|
||||
auto random1 = Catch::Generators::random(0, 1000);
|
||||
auto random2 = Catch::Generators::random(0, 1000);
|
||||
size_t same = 0;
|
||||
for (size_t i = 0; i < 1000; ++i) {
|
||||
same += random1.get() == random2.get();
|
||||
random1.next(); random2.next();
|
||||
}
|
||||
// 0.5% seems like a sane bound for random identical elements within 1000 runs
|
||||
REQUIRE(same < 5);
|
||||
}
|
||||
SECTION("Float") {
|
||||
auto random1 = Catch::Generators::random(0., 1000.);
|
||||
auto random2 = Catch::Generators::random(0., 1000.);
|
||||
size_t same = 0;
|
||||
for (size_t i = 0; i < 1000; ++i) {
|
||||
same += random1.get() == random2.get();
|
||||
random1.next(); random2.next();
|
||||
}
|
||||
// 0.5% seems like a sane bound for random identical elements within 1000 runs
|
||||
REQUIRE(same < 5);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Created by Martin on 06/10/2019.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "internal/catch_random_number_generator.h"
|
||||
|
||||
TEST_CASE("Our PCG implementation provides expected results for known seeds", "[rng]") {
|
||||
Catch::SimplePcg32 rng;
|
||||
SECTION("Default seeded") {
|
||||
REQUIRE(rng() == 0xfcdb943b);
|
||||
REQUIRE(rng() == 0x6f55b921);
|
||||
REQUIRE(rng() == 0x4c17a916);
|
||||
REQUIRE(rng() == 0x71eae25f);
|
||||
REQUIRE(rng() == 0x6ce7909c);
|
||||
}
|
||||
SECTION("Specific seed") {
|
||||
rng.seed(0xabcd1234);
|
||||
REQUIRE(rng() == 0x57c08495);
|
||||
REQUIRE(rng() == 0x33c956ac);
|
||||
REQUIRE(rng() == 0x2206fd76);
|
||||
REQUIRE(rng() == 0x3501a35b);
|
||||
REQUIRE(rng() == 0xfdffb30f);
|
||||
|
||||
// Also check repeated output after reseeding
|
||||
rng.seed(0xabcd1234);
|
||||
REQUIRE(rng() == 0x57c08495);
|
||||
REQUIRE(rng() == 0x33c956ac);
|
||||
REQUIRE(rng() == 0x2206fd76);
|
||||
REQUIRE(rng() == 0x3501a35b);
|
||||
REQUIRE(rng() == 0xfdffb30f);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Comparison ops", "[rng]") {
|
||||
using Catch::SimplePcg32;
|
||||
REQUIRE(SimplePcg32{} == SimplePcg32{});
|
||||
REQUIRE(SimplePcg32{ 0 } != SimplePcg32{});
|
||||
REQUIRE_FALSE(SimplePcg32{ 1 } == SimplePcg32{ 2 });
|
||||
REQUIRE_FALSE(SimplePcg32{ 1 } != SimplePcg32{ 1 });
|
||||
}
|
@@ -111,6 +111,10 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
||||
SECTION( "Pointer values of substring refs should not match" ) {
|
||||
REQUIRE( s.c_str() != ss.c_str() );
|
||||
}
|
||||
|
||||
SECTION("Past the end substring") {
|
||||
REQUIRE(s.substr(s.size() + 1, 123).empty());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "Comparisons" ) {
|
||||
@@ -142,11 +146,6 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
||||
SECTION( "to std::string" ) {
|
||||
StringRef sr = "a stringref";
|
||||
|
||||
SECTION( "implicitly constructed" ) {
|
||||
std::string stdStr = sr;
|
||||
REQUIRE( stdStr == "a stringref" );
|
||||
REQUIRE( stdStr.size() == sr.size() );
|
||||
}
|
||||
SECTION( "explicitly constructed" ) {
|
||||
std::string stdStr( sr );
|
||||
REQUIRE( stdStr == "a stringref" );
|
||||
@@ -154,66 +153,9 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
||||
}
|
||||
SECTION( "assigned" ) {
|
||||
std::string stdStr;
|
||||
stdStr = sr;
|
||||
stdStr = static_cast<std::string>(sr);
|
||||
REQUIRE( stdStr == "a stringref" );
|
||||
REQUIRE( stdStr.size() == sr.size() );
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "Counting utf-8 codepoints" ) {
|
||||
StringRef ascii = "just a plain old boring ascii string...";
|
||||
REQUIRE(ascii.numberOfCharacters() == ascii.size());
|
||||
|
||||
StringRef simpleu8 = u8"Trocha češtiny nikoho nezabila";
|
||||
REQUIRE(simpleu8.numberOfCharacters() == 30);
|
||||
|
||||
StringRef emojis = u8"Here be 👾";
|
||||
REQUIRE(emojis.numberOfCharacters() == 9);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE( "replaceInPlace", "[Strings][StringManip]" ) {
|
||||
std::string letters = "abcdefcg";
|
||||
SECTION( "replace single char" ) {
|
||||
CHECK( Catch::replaceInPlace( letters, "b", "z" ) );
|
||||
CHECK( letters == "azcdefcg" );
|
||||
}
|
||||
SECTION( "replace two chars" ) {
|
||||
CHECK( Catch::replaceInPlace( letters, "c", "z" ) );
|
||||
CHECK( letters == "abzdefzg" );
|
||||
}
|
||||
SECTION( "replace first char" ) {
|
||||
CHECK( Catch::replaceInPlace( letters, "a", "z" ) );
|
||||
CHECK( letters == "zbcdefcg" );
|
||||
}
|
||||
SECTION( "replace last char" ) {
|
||||
CHECK( Catch::replaceInPlace( letters, "g", "z" ) );
|
||||
CHECK( letters == "abcdefcz" );
|
||||
}
|
||||
SECTION( "replace all chars" ) {
|
||||
CHECK( Catch::replaceInPlace( letters, letters, "replaced" ) );
|
||||
CHECK( letters == "replaced" );
|
||||
}
|
||||
SECTION( "replace no chars" ) {
|
||||
CHECK_FALSE( Catch::replaceInPlace( letters, "x", "z" ) );
|
||||
CHECK( letters == letters );
|
||||
}
|
||||
SECTION( "escape '" ) {
|
||||
std::string s = "didn't";
|
||||
CHECK( Catch::replaceInPlace( s, "'", "|'" ) );
|
||||
CHECK( s == "didn|'t" );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "splitString", "[Strings]" ) {
|
||||
using namespace Catch::Matchers;
|
||||
using Catch::splitStringRef;
|
||||
using Catch::StringRef;
|
||||
|
||||
CHECK_THAT( splitStringRef("", ',' ), Equals(std::vector<StringRef>() ) );
|
||||
CHECK_THAT( splitStringRef("abc", ',' ), Equals(std::vector<StringRef>{"abc"} ) );
|
||||
CHECK_THAT( splitStringRef("abc,def", ',' ), Equals(std::vector<StringRef>{"abc", "def"} ) );
|
||||
}
|
||||
|
||||
|
||||
|
67
projects/SelfTest/IntrospectiveTests/StringManip.tests.cpp
Normal file
67
projects/SelfTest/IntrospectiveTests/StringManip.tests.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "internal/catch_string_manip.h"
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
static const char * const no_whitespace = "There is no extra whitespace here";
|
||||
static const char * const leading_whitespace = " \r \t\n There is no extra whitespace here";
|
||||
static const char * const trailing_whitespace = "There is no extra whitespace here \t \n \r ";
|
||||
static const char * const whitespace_at_both_ends = " \r\n \t There is no extra whitespace here \t\t\t \n";
|
||||
|
||||
TEST_CASE("Trim strings", "[string-manip]") {
|
||||
using Catch::trim; using Catch::StringRef;
|
||||
static_assert(std::is_same<std::string, decltype(trim(std::string{}))>::value, "Trimming std::string should return std::string");
|
||||
static_assert(std::is_same<StringRef, decltype(trim(StringRef{}))>::value, "Trimming StringRef should return StringRef");
|
||||
|
||||
REQUIRE(trim(std::string(no_whitespace)) == no_whitespace);
|
||||
REQUIRE(trim(std::string(leading_whitespace)) == no_whitespace);
|
||||
REQUIRE(trim(std::string(trailing_whitespace)) == no_whitespace);
|
||||
REQUIRE(trim(std::string(whitespace_at_both_ends)) == no_whitespace);
|
||||
|
||||
REQUIRE(trim(StringRef(no_whitespace)) == StringRef(no_whitespace));
|
||||
REQUIRE(trim(StringRef(leading_whitespace)) == StringRef(no_whitespace));
|
||||
REQUIRE(trim(StringRef(trailing_whitespace)) == StringRef(no_whitespace));
|
||||
REQUIRE(trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace));
|
||||
}
|
||||
|
||||
TEST_CASE("replaceInPlace", "[string-manip]") {
|
||||
std::string letters = "abcdefcg";
|
||||
SECTION("replace single char") {
|
||||
CHECK(Catch::replaceInPlace(letters, "b", "z"));
|
||||
CHECK(letters == "azcdefcg");
|
||||
}
|
||||
SECTION("replace two chars") {
|
||||
CHECK(Catch::replaceInPlace(letters, "c", "z"));
|
||||
CHECK(letters == "abzdefzg");
|
||||
}
|
||||
SECTION("replace first char") {
|
||||
CHECK(Catch::replaceInPlace(letters, "a", "z"));
|
||||
CHECK(letters == "zbcdefcg");
|
||||
}
|
||||
SECTION("replace last char") {
|
||||
CHECK(Catch::replaceInPlace(letters, "g", "z"));
|
||||
CHECK(letters == "abcdefcz");
|
||||
}
|
||||
SECTION("replace all chars") {
|
||||
CHECK(Catch::replaceInPlace(letters, letters, "replaced"));
|
||||
CHECK(letters == "replaced");
|
||||
}
|
||||
SECTION("replace no chars") {
|
||||
CHECK_FALSE(Catch::replaceInPlace(letters, "x", "z"));
|
||||
CHECK(letters == letters);
|
||||
}
|
||||
SECTION("escape '") {
|
||||
std::string s = "didn't";
|
||||
CHECK(Catch::replaceInPlace(s, "'", "|'"));
|
||||
CHECK(s == "didn|'t");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("splitString", "[string-manip]") {
|
||||
using namespace Catch::Matchers;
|
||||
using Catch::splitStringRef;
|
||||
using Catch::StringRef;
|
||||
|
||||
CHECK_THAT(splitStringRef("", ','), Equals(std::vector<StringRef>()));
|
||||
CHECK_THAT(splitStringRef("abc", ','), Equals(std::vector<StringRef>{"abc"}));
|
||||
CHECK_THAT(splitStringRef("abc,def", ','), Equals(std::vector<StringRef>{"abc", "def"}));
|
||||
}
|
@@ -10,24 +10,24 @@ TEST_CASE( "parseEnums", "[Strings][enums]" ) {
|
||||
using Catch::Detail::parseEnums;
|
||||
|
||||
SECTION( "No enums" )
|
||||
CHECK_THAT( parseEnums( "" ), Equals( std::vector<std::string>{} ) );
|
||||
CHECK_THAT( parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) );
|
||||
|
||||
SECTION( "One enum value" ) {
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1" ),
|
||||
Equals(std::vector<std::string>{"Value1"} ) );
|
||||
Equals(std::vector<Catch::StringRef>{"Value1"} ) );
|
||||
CHECK_THAT( parseEnums( "Value1" ),
|
||||
Equals( std::vector<std::string>{"Value1"} ) );
|
||||
Equals( std::vector<Catch::StringRef>{"Value1"} ) );
|
||||
CHECK_THAT( parseEnums( "EnumName::Value1" ),
|
||||
Equals(std::vector<std::string>{"Value1"} ) );
|
||||
Equals(std::vector<Catch::StringRef>{"Value1"} ) );
|
||||
}
|
||||
|
||||
SECTION( "Multiple enum values" ) {
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ),
|
||||
Equals( std::vector<std::string>{"Value1", "Value2"} ) );
|
||||
Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) );
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ),
|
||||
Equals( std::vector<std::string>{"Value1", "Value2", "Value3"} ) );
|
||||
Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) );
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ),
|
||||
Equals( std::vector<std::string>{"Value1", "Value2", "Value3"} ) );
|
||||
Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
1
projects/SelfTest/Misc/invalid-test-names.input
Normal file
1
projects/SelfTest/Misc/invalid-test-names.input
Normal file
@@ -0,0 +1 @@
|
||||
Test with special, characters in \" name
|
2
projects/SelfTest/Misc/plain-old-tests.input
Normal file
2
projects/SelfTest/Misc/plain-old-tests.input
Normal file
@@ -0,0 +1,2 @@
|
||||
random SECTION tests
|
||||
nested SECTION tests
|
1
projects/SelfTest/Misc/special-characters-in-file.input
Normal file
1
projects/SelfTest/Misc/special-characters-in-file.input
Normal file
@@ -0,0 +1 @@
|
||||
Test with special\, characters \"in name
|
@@ -61,8 +61,6 @@ TEST_CASE( "Some simple comparisons between doubles", "[Approx]" ) {
|
||||
REQUIRE( Approx( d ) == 1.23 );
|
||||
REQUIRE( Approx( d ) != 1.22 );
|
||||
REQUIRE( Approx( d ) != 1.24 );
|
||||
|
||||
REQUIRE(INFINITY == Approx(INFINITY));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -183,8 +181,11 @@ TEST_CASE("Epsilon only applies to Approx's value", "[Approx]") {
|
||||
REQUIRE(101.01 != Approx(100).epsilon(0.01));
|
||||
}
|
||||
|
||||
TEST_CASE("Assorted miscellaneous tests", "[Approx]") {
|
||||
TEST_CASE("Assorted miscellaneous tests", "[Approx][approvals]") {
|
||||
REQUIRE(INFINITY == Approx(INFINITY));
|
||||
REQUIRE(-INFINITY != Approx(INFINITY));
|
||||
REQUIRE(1 != Approx(INFINITY));
|
||||
REQUIRE(INFINITY != Approx(1));
|
||||
REQUIRE(NAN != Approx(NAN));
|
||||
REQUIRE_FALSE(NAN == Approx(NAN));
|
||||
}
|
||||
|
@@ -180,16 +180,18 @@ TEST_CASE("Generators -- adapters", "[generators][generic]") {
|
||||
|
||||
// Note that because of the non-reproducibility of distributions,
|
||||
// anything involving the random generators cannot be part of approvals
|
||||
TEST_CASE("Random generator", "[generators][.][approvals]") {
|
||||
TEST_CASE("Random generator", "[generators][approvals]") {
|
||||
SECTION("Infer int from integral arguments") {
|
||||
auto val = GENERATE(take(4, random(0, 1)));
|
||||
STATIC_REQUIRE(std::is_same<decltype(val), int>::value);
|
||||
static_cast<void>(val); // Silence VS 2015 unused variable warning
|
||||
REQUIRE(0 <= val);
|
||||
REQUIRE(val <= 1);
|
||||
}
|
||||
SECTION("Infer double from double arguments") {
|
||||
auto val = GENERATE(take(4, random(0., 1.)));
|
||||
STATIC_REQUIRE(std::is_same<decltype(val), double>::value);
|
||||
static_cast<void>(val); // Silence VS 2015 unused variable warning
|
||||
REQUIRE(0. <= val);
|
||||
REQUIRE(val < 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,3 +212,45 @@ TEST_CASE("Nested generators and captured variables", "[generators]") {
|
||||
auto values = GENERATE_COPY(range(from, to));
|
||||
REQUIRE(values > -6);
|
||||
}
|
||||
|
||||
namespace {
|
||||
size_t call_count = 0;
|
||||
size_t test_count = 0;
|
||||
std::vector<int> make_data() {
|
||||
return { 1, 3, 5, 7, 9, 11 };
|
||||
}
|
||||
std::vector<int> make_data_counted() {
|
||||
++call_count;
|
||||
return make_data();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||
#endif
|
||||
|
||||
TEST_CASE("Copy and then generate a range", "[generators]") {
|
||||
SECTION("from var and iterators") {
|
||||
static auto data = make_data();
|
||||
|
||||
// It is important to notice that a generator is only initialized
|
||||
// **once** per run. What this means is that modifying data will not
|
||||
// modify the underlying generator.
|
||||
auto elem = GENERATE_REF(from_range(data.begin(), data.end()));
|
||||
REQUIRE(elem % 2 == 1);
|
||||
}
|
||||
SECTION("From a temporary container") {
|
||||
auto elem = GENERATE(from_range(make_data_counted()));
|
||||
++test_count;
|
||||
REQUIRE(elem % 2 == 1);
|
||||
}
|
||||
SECTION("Final validation") {
|
||||
REQUIRE(call_count == 1);
|
||||
REQUIRE(make_data().size() == test_count);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
@@ -52,10 +52,16 @@ namespace { namespace MatchersTests {
|
||||
int i;
|
||||
};
|
||||
|
||||
struct DerivedException : std::exception {
|
||||
char const* what() const noexcept override {
|
||||
return "DerivedException::what";
|
||||
}
|
||||
};
|
||||
|
||||
void doesNotThrow() {}
|
||||
|
||||
[[noreturn]]
|
||||
void throws(int i) {
|
||||
void throwsSpecialException(int i) {
|
||||
throw SpecialException{i};
|
||||
}
|
||||
|
||||
@@ -64,6 +70,11 @@ namespace { namespace MatchersTests {
|
||||
throw i;
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void throwsDerivedException() {
|
||||
throw DerivedException{};
|
||||
}
|
||||
|
||||
class ExceptionMatcher : public Catch::MatcherBase<SpecialException> {
|
||||
int m_expected;
|
||||
public:
|
||||
@@ -319,8 +330,8 @@ namespace { namespace MatchersTests {
|
||||
}
|
||||
|
||||
TEST_CASE("Exception matchers that succeed", "[matchers][exceptions][!throws]") {
|
||||
CHECK_THROWS_MATCHES(throws(1), SpecialException, ExceptionMatcher{1});
|
||||
REQUIRE_THROWS_MATCHES(throws(2), SpecialException, ExceptionMatcher{2});
|
||||
CHECK_THROWS_MATCHES(throwsSpecialException(1), SpecialException, ExceptionMatcher{1});
|
||||
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, ExceptionMatcher{2});
|
||||
}
|
||||
|
||||
TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.failing]") {
|
||||
@@ -333,12 +344,26 @@ namespace { namespace MatchersTests {
|
||||
REQUIRE_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{1});
|
||||
}
|
||||
SECTION("Contents are wrong") {
|
||||
CHECK_THROWS_MATCHES(throws(3), SpecialException, ExceptionMatcher{1});
|
||||
REQUIRE_THROWS_MATCHES(throws(4), SpecialException, ExceptionMatcher{1});
|
||||
CHECK_THROWS_MATCHES(throwsSpecialException(3), SpecialException, ExceptionMatcher{1});
|
||||
REQUIRE_THROWS_MATCHES(throwsSpecialException(4), SpecialException, ExceptionMatcher{1});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Floating point matchers: float", "[matchers][floating-point]") {
|
||||
SECTION("Relative") {
|
||||
REQUIRE_THAT(10.f, WithinRel(11.1f, 0.1f));
|
||||
REQUIRE_THAT(10.f, !WithinRel(11.2f, 0.1f));
|
||||
REQUIRE_THAT( 1.f, !WithinRel(0.f, 0.99f));
|
||||
REQUIRE_THAT(-0.f, WithinRel(0.f));
|
||||
SECTION("Some subnormal values") {
|
||||
auto v1 = std::numeric_limits<float>::min();
|
||||
auto v2 = v1;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
v2 = std::nextafter(v1, 0.f);
|
||||
}
|
||||
REQUIRE_THAT(v1, WithinRel(v2));
|
||||
}
|
||||
}
|
||||
SECTION("Margin") {
|
||||
REQUIRE_THAT(1.f, WithinAbs(1.f, 0));
|
||||
REQUIRE_THAT(0.f, WithinAbs(1.f, 1));
|
||||
@@ -357,8 +382,9 @@ namespace { namespace MatchersTests {
|
||||
REQUIRE_THAT(1.f, WithinULP(1.f, 0));
|
||||
|
||||
REQUIRE_THAT(nextafter(1.f, 2.f), WithinULP(1.f, 1));
|
||||
REQUIRE_THAT(nextafter(1.f, 0.f), WithinULP(1.f, 1));
|
||||
REQUIRE_THAT(nextafter(1.f, 2.f), !WithinULP(1.f, 0));
|
||||
REQUIRE_THAT(0.f, WithinULP(nextafter(0.f, 1.f), 1));
|
||||
REQUIRE_THAT(1.f, WithinULP(nextafter(1.f, 0.f), 1));
|
||||
REQUIRE_THAT(1.f, !WithinULP(nextafter(1.f, 2.f), 0));
|
||||
|
||||
REQUIRE_THAT(1.f, WithinULP(1.f, 0));
|
||||
REQUIRE_THAT(-0.f, WithinULP(0.f, 0));
|
||||
@@ -366,17 +392,36 @@ namespace { namespace MatchersTests {
|
||||
SECTION("Composed") {
|
||||
REQUIRE_THAT(1.f, WithinAbs(1.f, 0.5) || WithinULP(1.f, 1));
|
||||
REQUIRE_THAT(1.f, WithinAbs(2.f, 0.5) || WithinULP(1.f, 0));
|
||||
REQUIRE_THAT(0.0001f, WithinAbs(0.f, 0.001f) || WithinRel(0.f, 0.1f));
|
||||
}
|
||||
SECTION("Constructor validation") {
|
||||
REQUIRE_NOTHROW(WithinAbs(1.f, 0.f));
|
||||
REQUIRE_THROWS_AS(WithinAbs(1.f, -1.f), std::domain_error);
|
||||
|
||||
REQUIRE_NOTHROW(WithinULP(1.f, 0));
|
||||
REQUIRE_THROWS_AS(WithinULP(1.f, -1), std::domain_error);
|
||||
REQUIRE_THROWS_AS(WithinULP(1.f, static_cast<uint64_t>(-1)), std::domain_error);
|
||||
|
||||
REQUIRE_NOTHROW(WithinRel(1.f, 0.f));
|
||||
REQUIRE_THROWS_AS(WithinRel(1.f, -0.2f), std::domain_error);
|
||||
REQUIRE_THROWS_AS(WithinRel(1.f, 1.f), std::domain_error);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Floating point matchers: double", "[matchers][floating-point]") {
|
||||
SECTION("Relative") {
|
||||
REQUIRE_THAT(10., WithinRel(11.1, 0.1));
|
||||
REQUIRE_THAT(10., !WithinRel(11.2, 0.1));
|
||||
REQUIRE_THAT(1., !WithinRel(0., 0.99));
|
||||
REQUIRE_THAT(-0., WithinRel(0.));
|
||||
SECTION("Some subnormal values") {
|
||||
auto v1 = std::numeric_limits<double>::min();
|
||||
auto v2 = v1;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
v2 = std::nextafter(v1, 0);
|
||||
}
|
||||
REQUIRE_THAT(v1, WithinRel(v2));
|
||||
}
|
||||
}
|
||||
SECTION("Margin") {
|
||||
REQUIRE_THAT(1., WithinAbs(1., 0));
|
||||
REQUIRE_THAT(0., WithinAbs(1., 1));
|
||||
@@ -393,8 +438,9 @@ namespace { namespace MatchersTests {
|
||||
REQUIRE_THAT(1., WithinULP(1., 0));
|
||||
|
||||
REQUIRE_THAT(nextafter(1., 2.), WithinULP(1., 1));
|
||||
REQUIRE_THAT(nextafter(1., 0.), WithinULP(1., 1));
|
||||
REQUIRE_THAT(nextafter(1., 2.), !WithinULP(1., 0));
|
||||
REQUIRE_THAT(0., WithinULP(nextafter(0., 1.), 1));
|
||||
REQUIRE_THAT(1., WithinULP(nextafter(1., 0.), 1));
|
||||
REQUIRE_THAT(1., !WithinULP(nextafter(1., 2.), 0));
|
||||
|
||||
REQUIRE_THAT(1., WithinULP(1., 0));
|
||||
REQUIRE_THAT(-0., WithinULP(0., 0));
|
||||
@@ -402,13 +448,17 @@ namespace { namespace MatchersTests {
|
||||
SECTION("Composed") {
|
||||
REQUIRE_THAT(1., WithinAbs(1., 0.5) || WithinULP(2., 1));
|
||||
REQUIRE_THAT(1., WithinAbs(2., 0.5) || WithinULP(1., 0));
|
||||
REQUIRE_THAT(0.0001, WithinAbs(0., 0.001) || WithinRel(0., 0.1));
|
||||
}
|
||||
SECTION("Constructor validation") {
|
||||
REQUIRE_NOTHROW(WithinAbs(1., 0.));
|
||||
REQUIRE_THROWS_AS(WithinAbs(1., -1.), std::domain_error);
|
||||
|
||||
REQUIRE_NOTHROW(WithinULP(1., 0));
|
||||
REQUIRE_THROWS_AS(WithinULP(1., -1), std::domain_error);
|
||||
|
||||
REQUIRE_NOTHROW(WithinRel(1., 0.));
|
||||
REQUIRE_THROWS_AS(WithinRel(1., -0.2), std::domain_error);
|
||||
REQUIRE_THROWS_AS(WithinRel(1., 1.), std::domain_error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,6 +466,13 @@ namespace { namespace MatchersTests {
|
||||
REQUIRE_THAT(NAN, !WithinAbs(NAN, 0));
|
||||
REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)));
|
||||
REQUIRE_THAT(NAN, !WithinULP(NAN, 123));
|
||||
REQUIRE_THAT(INFINITY, WithinRel(INFINITY));
|
||||
REQUIRE_THAT(-INFINITY, !WithinRel(INFINITY));
|
||||
REQUIRE_THAT(1., !WithinRel(INFINITY));
|
||||
REQUIRE_THAT(INFINITY, !WithinRel(1.));
|
||||
REQUIRE_THAT(NAN, !WithinRel(NAN));
|
||||
REQUIRE_THAT(1., !WithinRel(NAN));
|
||||
REQUIRE_THAT(NAN, !WithinRel(1.));
|
||||
}
|
||||
|
||||
TEST_CASE("Arbitrary predicate matcher", "[matchers][generic]") {
|
||||
@@ -489,6 +546,13 @@ namespace { namespace MatchersTests {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Exceptions matchers", "[matchers][exceptions][!throws]") {
|
||||
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, Message("DerivedException::what"));
|
||||
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, !Message("derivedexception::what"));
|
||||
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, !Message("DerivedException::what"));
|
||||
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, Message("SpecialException::what"));
|
||||
}
|
||||
|
||||
} } // namespace MatchersTests
|
||||
|
||||
#endif // CATCH_CONFIG_DISABLE_MATCHERS
|
||||
|
@@ -375,12 +375,27 @@ struct NonDefaultConstructibleType {
|
||||
NonDefaultConstructibleType() = delete;
|
||||
};
|
||||
|
||||
using MyNonDefaultConstructibleTypes = std::tuple<NonDefaultConstructibleType, char, float>;
|
||||
using MyNonDefaultConstructibleTypes = std::tuple<NonDefaultConstructibleType, float>;
|
||||
TEMPLATE_LIST_TEST_CASE("Template test case with test types specified inside non-default-constructible std::tuple", "[template][list]", MyNonDefaultConstructibleTypes)
|
||||
{
|
||||
REQUIRE(sizeof(TestType) > 0);
|
||||
}
|
||||
|
||||
struct NonCopyableAndNonMovableType {
|
||||
NonCopyableAndNonMovableType() = default;
|
||||
|
||||
NonCopyableAndNonMovableType(NonCopyableAndNonMovableType const &) = delete;
|
||||
NonCopyableAndNonMovableType(NonCopyableAndNonMovableType &&) = delete;
|
||||
auto operator=(NonCopyableAndNonMovableType const &) -> NonCopyableAndNonMovableType & = delete;
|
||||
auto operator=(NonCopyableAndNonMovableType &&) -> NonCopyableAndNonMovableType & = delete;
|
||||
};
|
||||
|
||||
using NonCopyableAndNonMovableTypes = std::tuple<NonCopyableAndNonMovableType, float>;
|
||||
TEMPLATE_LIST_TEST_CASE("Template test case with test types specified inside non-copyable and non-movable std::tuple", "[template][list]", NonCopyableAndNonMovableTypes)
|
||||
{
|
||||
REQUIRE(sizeof(TestType) > 0);
|
||||
}
|
||||
|
||||
// https://github.com/philsquared/Catch/issues/166
|
||||
TEST_CASE("A couple of nested sections followed by a failure", "[failing][.]") {
|
||||
SECTION("Outer")
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user