mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-15 01:45:39 +02:00
Compare commits
127 Commits
dev-stupid
...
v2.10.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
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 | ||
![]() |
2c869e17e4 | ||
![]() |
0ab11aa9b4 | ||
![]() |
7a6af7ba76 | ||
![]() |
fa096b26d1 | ||
![]() |
820b1f12bf | ||
![]() |
6070745cab | ||
![]() |
3d9e7db2e0 | ||
![]() |
cf55cfd76f | ||
![]() |
3701c2e2e6 | ||
![]() |
7dc7d77af2 | ||
![]() |
06bc20cf37 | ||
![]() |
7a4beed6a6 | ||
![]() |
67b4ada6b0 | ||
![]() |
119569a67e | ||
![]() |
ab713894cc | ||
![]() |
69fc94d6f8 | ||
![]() |
49cd7c96b4 | ||
![]() |
e998d152cc | ||
![]() |
42a5903188 | ||
![]() |
c071f07e1a | ||
![]() |
53776a90cf | ||
![]() |
4511dc0c16 | ||
![]() |
e7c3bdb351 | ||
![]() |
9aab958667 | ||
![]() |
8cd58f75ec | ||
![]() |
d5a69cd400 | ||
![]() |
1d13d88833 | ||
![]() |
de0674c116 | ||
![]() |
3d7282c2bd | ||
![]() |
e5c0e3322d | ||
![]() |
dc8c8e957f | ||
![]() |
ba9193370b | ||
![]() |
7b70b11c23 | ||
![]() |
ab80277a86 | ||
![]() |
7e7ab0e28b | ||
![]() |
425957dc63 | ||
![]() |
d017f6d18f | ||
![]() |
91244d30a7 | ||
![]() |
62b3f6c3c2 | ||
![]() |
e7c26f09d1 | ||
![]() |
a22b7df46c | ||
![]() |
032068b889 | ||
![]() |
2aed6233cf | ||
![]() |
fb74bb133c | ||
![]() |
0b42ada60d | ||
![]() |
c424ca47f9 |
12
.travis.yml
12
.travis.yml
@@ -9,8 +9,8 @@ common_sources: &all_sources
|
|||||||
- llvm-toolchain-trusty
|
- llvm-toolchain-trusty
|
||||||
- llvm-toolchain-trusty-3.9
|
- llvm-toolchain-trusty-3.9
|
||||||
- llvm-toolchain-trusty-4.0
|
- llvm-toolchain-trusty-4.0
|
||||||
- llvm-toolchain-trusty-5.0
|
- llvm-toolchain-xenial-5.0
|
||||||
- llvm-toolchain-trusty-6.0
|
- llvm-toolchain-xenial-6.0
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
@@ -60,6 +60,7 @@ matrix:
|
|||||||
env: COMPILER='clang++-4.0'
|
env: COMPILER='clang++-4.0'
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
|
dist: xenial
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
@@ -68,6 +69,7 @@ matrix:
|
|||||||
env: COMPILER='clang++-5.0'
|
env: COMPILER='clang++-5.0'
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
|
dist: xenial
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
@@ -153,6 +155,7 @@ matrix:
|
|||||||
env: COMPILER='clang++-4.0' CPP14=1
|
env: COMPILER='clang++-4.0' CPP14=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
|
dist: xenial
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
@@ -161,6 +164,7 @@ matrix:
|
|||||||
env: COMPILER='clang++-5.0' CPP14=1
|
env: COMPILER='clang++-5.0' CPP14=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
|
dist: xenial
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
@@ -255,6 +259,7 @@ matrix:
|
|||||||
env: COMPILER='g++-7' EXAMPLES=1 COVERAGE=1 EXTRAS=1 CPP17=1
|
env: COMPILER='g++-7' EXAMPLES=1 COVERAGE=1 EXTRAS=1 CPP17=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
|
dist: xenial
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
@@ -263,6 +268,7 @@ matrix:
|
|||||||
env: COMPILER='clang++-6.0' CPP17=1
|
env: COMPILER='clang++-6.0' CPP17=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
|
dist: xenial
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
@@ -276,7 +282,7 @@ matrix:
|
|||||||
- "3.7"
|
- "3.7"
|
||||||
dist: xenial
|
dist: xenial
|
||||||
install:
|
install:
|
||||||
- pip install conan==1.10.2 conan-package-tools
|
- pip install conan-package-tools
|
||||||
env:
|
env:
|
||||||
- CONAN_GCC_VERSIONS=8
|
- CONAN_GCC_VERSIONS=8
|
||||||
- CONAN_DOCKER_IMAGE=conanio/gcc8
|
- CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||||
|
@@ -6,12 +6,16 @@ if(NOT DEFINED PROJECT_NAME)
|
|||||||
set(NOT_SUBPROJECT ON)
|
set(NOT_SUBPROJECT ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(Catch2 LANGUAGES CXX VERSION 2.9.1)
|
# 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
|
||||||
if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
|
# 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")
|
message(FATAL_ERROR "Building in-source is not supported! Create a build dir and remove ${CMAKE_SOURCE_DIR}/CMakeCache.txt")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
project(Catch2 LANGUAGES CXX VERSION 2.10.1)
|
||||||
|
|
||||||
# Provide path for scripts
|
# Provide path for scripts
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
||||||
|
|
||||||
@@ -42,8 +46,8 @@ if(USE_WMAIN)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_TESTING AND CATCH_BUILD_TESTING AND NOT_SUBPROJECT)
|
if (BUILD_TESTING AND CATCH_BUILD_TESTING AND NOT_SUBPROJECT)
|
||||||
find_package(Python COMPONENTS Interpreter)
|
find_package(PythonInterp)
|
||||||
if (NOT Python_Interpreter_FOUND)
|
if (NOT PYTHONINTERP_FOUND)
|
||||||
message(FATAL_ERROR "Python not found, but required for tests")
|
message(FATAL_ERROR "Python not found, but required for tests")
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(projects)
|
add_subdirectory(projects)
|
||||||
@@ -92,6 +96,10 @@ target_include_directories(Catch2
|
|||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
$<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
|
# provide a namespaced alias for clients to 'link' against if catch is included as a sub-project
|
||||||
add_library(Catch2::Catch2 ALIAS Catch2)
|
add_library(Catch2::Catch2 ALIAS Catch2)
|
||||||
|
|
||||||
|
@@ -5,11 +5,11 @@
|
|||||||
[](https://travis-ci.org/catchorg/Catch2)
|
[](https://travis-ci.org/catchorg/Catch2)
|
||||||
[](https://ci.appveyor.com/project/catchorg/catch2)
|
[](https://ci.appveyor.com/project/catchorg/catch2)
|
||||||
[](https://codecov.io/gh/catchorg/Catch2)
|
[](https://codecov.io/gh/catchorg/Catch2)
|
||||||
[](https://wandbox.org/permlink/5icuqPwk9miJLAL1)
|
[](https://wandbox.org/permlink/oT2uthEb4CcTd0hb)
|
||||||
[](https://discord.gg/4CWS9zD)
|
[](https://discord.gg/4CWS9zD)
|
||||||
|
|
||||||
|
|
||||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.9.1/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.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||||
|
|
||||||
## Catch2 is released!
|
## 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 |
@@ -51,8 +51,11 @@ string(REPLACE "\n" ";" output "${output}")
|
|||||||
# Parse output
|
# Parse output
|
||||||
foreach(line ${output})
|
foreach(line ${output})
|
||||||
set(test ${line})
|
set(test ${line})
|
||||||
# use escape commas to handle properly test cases with commans inside the name
|
# Escape characters in test case names that would be parsed by Catch2
|
||||||
string(REPLACE "," "\\," test_name ${test})
|
set(test_name ${test})
|
||||||
|
foreach(char , [ ])
|
||||||
|
string(REPLACE ${char} "\\${char}" test_name ${test_name})
|
||||||
|
endforeach(char)
|
||||||
# ...and add to script
|
# ...and add to script
|
||||||
add_command(add_test
|
add_command(add_test
|
||||||
"${prefix}${test}${suffix}"
|
"${prefix}${test}${suffix}"
|
||||||
|
@@ -136,7 +136,7 @@ REQUIRE_THROWS_WITH( dismantleHal(), "My mind is going" );
|
|||||||
* **REQUIRE_THROWS_MATCHES(** _expression_, _exception type_, _matcher for given exception type_ **)** and
|
* **REQUIRE_THROWS_MATCHES(** _expression_, _exception type_, _matcher for given exception type_ **)** and
|
||||||
* **CHECK_THROWS_MATCHES(** _expression_, _exception type_, _matcher for given exception type_ **)**
|
* **CHECK_THROWS_MATCHES(** _expression_, _exception type_, _matcher for given exception type_ **)**
|
||||||
|
|
||||||
Expects that exception of _exception type_ is thrown and it matches provided matcher (see next section for Matchers).
|
Expects that exception of _exception type_ is thrown and it matches provided matcher (see the [documentation for Matchers](matchers.md#top)).
|
||||||
|
|
||||||
|
|
||||||
_Please note that the `THROW` family of assertions expects to be passed a single expression, not a statement or series of statements. If you want to check a more complicated sequence of operations, you can use a C++11 lambda function._
|
_Please note that the `THROW` family of assertions expects to be passed a single expression, not a statement or series of statements. If you want to check a more complicated sequence of operations, you can use a C++11 lambda function._
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Authoring benchmarks
|
# Authoring benchmarks
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1616) in Catch 2.9.0.
|
||||||
|
|
||||||
_Note that benchmarking support is disabled by default and to enable it,
|
_Note that benchmarking support is disabled by default and to enable it,
|
||||||
you need to define `CATCH_CONFIG_ENABLE_BENCHMARKING`. For more details,
|
you need to define `CATCH_CONFIG_ENABLE_BENCHMARKING`. For more details,
|
||||||
see the [compile-time configuration documentation](configuration.md#top)._
|
see the [compile-time configuration documentation](configuration.md#top)._
|
||||||
|
@@ -277,6 +277,8 @@ either before running any tests, after running all tests - or both, depending on
|
|||||||
## Specify the number of benchmark samples to collect
|
## Specify the number of benchmark samples to collect
|
||||||
<pre>--benchmark-samples <# of samples></pre>
|
<pre>--benchmark-samples <# of samples></pre>
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1616) in Catch 2.9.0.
|
||||||
|
|
||||||
When running benchmarks a number of "samples" is collected. This is the base data for later statistical analysis.
|
When running benchmarks a number of "samples" is collected. This is the base data for later statistical analysis.
|
||||||
Per sample a clock resolution dependent number of iterations of the user code is run, which is independent of the number of samples. Defaults to 100.
|
Per sample a clock resolution dependent number of iterations of the user code is run, which is independent of the number of samples. Defaults to 100.
|
||||||
|
|
||||||
@@ -284,6 +286,8 @@ Per sample a clock resolution dependent number of iterations of the user code is
|
|||||||
## Specify the number of resamples for bootstrapping
|
## Specify the number of resamples for bootstrapping
|
||||||
<pre>--benchmark-resamples <# of resamples></pre>
|
<pre>--benchmark-resamples <# of resamples></pre>
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1616) in Catch 2.9.0.
|
||||||
|
|
||||||
After the measurements are performed, statistical [bootstrapping] is performed
|
After the measurements are performed, statistical [bootstrapping] is performed
|
||||||
on the samples. The number of resamples for that bootstrapping is configurable
|
on the samples. The number of resamples for that bootstrapping is configurable
|
||||||
but defaults to 100000. Due to the bootstrapping it is possible to give
|
but defaults to 100000. Due to the bootstrapping it is possible to give
|
||||||
@@ -297,6 +301,8 @@ defaults to 95%).
|
|||||||
## Specify the confidence-interval for bootstrapping
|
## Specify the confidence-interval for bootstrapping
|
||||||
<pre>--benchmark-confidence-interval <confidence-interval></pre>
|
<pre>--benchmark-confidence-interval <confidence-interval></pre>
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1616) in Catch 2.9.0.
|
||||||
|
|
||||||
The confidence-interval is used for statistical bootstrapping on the samples to
|
The confidence-interval is used for statistical bootstrapping on the samples to
|
||||||
calculate the upper and lower bounds of mean and standard deviation.
|
calculate the upper and lower bounds of mean and standard deviation.
|
||||||
Must be between 0 and 1 and defaults to 0.95.
|
Must be between 0 and 1 and defaults to 0.95.
|
||||||
@@ -305,6 +311,8 @@ Must be between 0 and 1 and defaults to 0.95.
|
|||||||
## Disable statistical analysis of collected benchmark samples
|
## Disable statistical analysis of collected benchmark samples
|
||||||
<pre>--benchmark-no-analysis</pre>
|
<pre>--benchmark-no-analysis</pre>
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1616) in Catch 2.9.0.
|
||||||
|
|
||||||
When this flag is specified no bootstrapping or any other statistical analysis is performed.
|
When this flag is specified no bootstrapping or any other statistical analysis is performed.
|
||||||
Instead the user code is only measured and the plain mean from the samples is reported.
|
Instead the user code is only measured and the plain mean from the samples is reported.
|
||||||
|
|
||||||
|
@@ -17,3 +17,4 @@ fact then please let us know - either directly, via a PR or
|
|||||||
- NASA
|
- NASA
|
||||||
- [Inscopix Inc.](https://www.inscopix.com/)
|
- [Inscopix Inc.](https://www.inscopix.com/)
|
||||||
- [Makimo](https://makimo.pl/)
|
- [Makimo](https://makimo.pl/)
|
||||||
|
- [UX3D] (https://ux3d.io)
|
||||||
|
@@ -127,8 +127,12 @@ Catch's selection, by defining either `CATCH_CONFIG_CPP11_TO_STRING` or
|
|||||||
## C++17 toggles
|
## C++17 toggles
|
||||||
|
|
||||||
CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS // Use std::uncaught_exceptions instead of std::uncaught_exception
|
CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS // Use std::uncaught_exceptions instead of std::uncaught_exception
|
||||||
CATCH_CONFIG_CPP17_STRING_VIEW // Provide StringMaker specialization for std::string_view
|
CATCH_CONFIG_CPP17_STRING_VIEW // Override std::string_view support detection(Catch provides a StringMaker specialization by default)
|
||||||
CATCH_CONFIG_CPP17_VARIANT // Override C++17 detection for CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
|
CATCH_CONFIG_CPP17_VARIANT // Override std::variant support detection (checked by CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER)
|
||||||
|
CATCH_CONFIG_CPP17_OPTIONAL // Override std::optional support detection (checked by CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER)
|
||||||
|
CATCH_CONFIG_CPP17_BYTE // Override std::byte support detection (Catch provides a StringMaker specialization by default)
|
||||||
|
|
||||||
|
> `CATCH_CONFIG_CPP17_STRING_VIEW` was [introduced](https://github.com/catchorg/Catch2/issues/1376) in Catch 2.4.1.
|
||||||
|
|
||||||
Catch contains basic compiler/standard detection and attempts to use
|
Catch contains basic compiler/standard detection and attempts to use
|
||||||
some C++17 features whenever appropriate. This automatic detection
|
some C++17 features whenever appropriate. This automatic detection
|
||||||
@@ -151,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_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_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_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.
|
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.
|
||||||
|
|
||||||
@@ -209,9 +217,14 @@ By default, Catch does not stringify some types from the standard library. This
|
|||||||
CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER // Provide StringMaker specialization for std::optional (on C++17)
|
CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER // Provide StringMaker specialization for std::optional (on C++17)
|
||||||
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS // Defines all of the above
|
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS // Defines all of the above
|
||||||
|
|
||||||
|
> `CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER` was [introduced](https://github.com/catchorg/Catch2/issues/1380) in Catch 2.4.1.
|
||||||
|
|
||||||
|
> `CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER` was [introduced](https://github.com/catchorg/Catch2/issues/1510) in Catch 2.6.0.
|
||||||
|
|
||||||
## Disabling exceptions
|
## Disabling exceptions
|
||||||
|
|
||||||
|
> Introduced in Catch 2.4.0.
|
||||||
|
|
||||||
By default, Catch2 uses exceptions to signal errors and to abort tests
|
By default, Catch2 uses exceptions to signal errors and to abort tests
|
||||||
when an assertion from the `REQUIRE` family of assertions fails. We also
|
when an assertion from the `REQUIRE` family of assertions fails. We also
|
||||||
provide an experimental support for disabling exceptions. Catch2 should
|
provide an experimental support for disabling exceptions. Catch2 should
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
[Branches](#branches)<br>
|
[Branches](#branches)<br>
|
||||||
[Directory structure](#directory-structure)<br>
|
[Directory structure](#directory-structure)<br>
|
||||||
[Testing your changes](#testing-your-changes)<br>
|
[Testing your changes](#testing-your-changes)<br>
|
||||||
|
[Documenting your code](#documenting-your-code)<br>
|
||||||
[Code constructs to watch out for](#code-constructs-to-watch-out-for)<br>
|
[Code constructs to watch out for](#code-constructs-to-watch-out-for)<br>
|
||||||
|
|
||||||
So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for
|
So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for
|
||||||
@@ -69,6 +70,10 @@ locally takes just a few minutes.
|
|||||||
$ cd debug-build
|
$ cd debug-build
|
||||||
$ ctest -j 2 --output-on-failure
|
$ 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
|
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
|
do not, it means that your changes weren't run as part of them. This
|
||||||
_might_ be intentional, but usually is not.
|
_might_ be intentional, but usually is not.
|
||||||
@@ -81,6 +86,59 @@ before you do so, you need to check that the introduced changes are indeed
|
|||||||
intentional.
|
intentional.
|
||||||
|
|
||||||
|
|
||||||
|
## Documenting your code
|
||||||
|
|
||||||
|
If you have added new feature to Catch2, it needs documentation, so that
|
||||||
|
other people can use it as well. This section collects some technical
|
||||||
|
information that you will need for updating Catch2's documentation, and
|
||||||
|
possibly some generic advise as well.
|
||||||
|
|
||||||
|
First, the technicalities:
|
||||||
|
|
||||||
|
* We introduced version tags to the documentation, which show users in
|
||||||
|
which version a specific feature was introduced. This means that newly
|
||||||
|
written documentation should be tagged with a placeholder, that will
|
||||||
|
be replaced with the actual version upon release. There are 2 styles
|
||||||
|
of placeholders used through the documentation, you should pick one that
|
||||||
|
fits your text better (if in doubt, take a look at the existing version
|
||||||
|
tags for other features).
|
||||||
|
* `> [Introduced](link-to-issue-or-PR) in Catch X.Y.Z` - this
|
||||||
|
placeholder is usually used after a section heading
|
||||||
|
* `> X (Y and Z) was [introduced](link-to-issue-or-PR) in Catch X.Y.Z`
|
||||||
|
- this placeholder is used when you need to tag a subpart of something,
|
||||||
|
e.g. list
|
||||||
|
* Crosslinks to different pages should target the `top` anchor, like this
|
||||||
|
`[link to contributing](contributing.md#top)`.
|
||||||
|
* If you have introduced a new document, there is a simple template you
|
||||||
|
should use. It provides you with the top anchor mentioned above, and also
|
||||||
|
with a backlink to the top of the documentation:
|
||||||
|
```markdown
|
||||||
|
<a id="top"></a>
|
||||||
|
# Cool feature
|
||||||
|
|
||||||
|
Text that explains how to use the cool feature.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[Home](Readme.md#top)
|
||||||
|
```
|
||||||
|
* For pages with more than 4 subheadings, we provide a table of contents
|
||||||
|
(ToC) at the top of the page. Because GitHub markdown does not support
|
||||||
|
automatic generation of ToC, it has to be handled semi-manually. Thus,
|
||||||
|
if you've added a new subheading to some page, you should add it to the
|
||||||
|
ToC. This can be done either manually, or by running the
|
||||||
|
`updateDocumentToC.py` script in the `scripts/` folder.
|
||||||
|
|
||||||
|
|
||||||
|
Now, for the generic tips:
|
||||||
|
* Usage examples are good
|
||||||
|
* Don't be afraid to introduce new pages
|
||||||
|
* Try to be reasonably consistent with the surrounding documentation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Code constructs to watch out for
|
## Code constructs to watch out for
|
||||||
|
|
||||||
This section is a (sadly incomplete) listing of various constructs that
|
This section is a (sadly incomplete) listing of various constructs that
|
||||||
|
@@ -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
|
Because it isn't actually used nor documented, and brings complications
|
||||||
to Catch2's internals, description support will be removed.
|
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
|
## Planned changes
|
||||||
|
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Data Generators
|
# Data Generators
|
||||||
|
|
||||||
|
> Introduced in Catch 2.6.0.
|
||||||
|
|
||||||
Data generators (also known as _data driven/parametrized test cases_)
|
Data generators (also known as _data driven/parametrized test cases_)
|
||||||
let you reuse the same set of assertions across different input values.
|
let you reuse the same set of assertions across different input values.
|
||||||
In Catch2, this means that they respect the ordering and nesting
|
In Catch2, this means that they respect the ordering and nesting
|
||||||
@@ -34,8 +36,8 @@ Catch2's provided generator functionality consists of three parts,
|
|||||||
* `GENERATE` macro, that serves to integrate generator expression with
|
* `GENERATE` macro, that serves to integrate generator expression with
|
||||||
a test case,
|
a test case,
|
||||||
* 2 fundamental generators
|
* 2 fundamental generators
|
||||||
* `ValueGenerator<T>` -- contains only single element
|
* `SingleValueGenerator<T>` -- contains only single element
|
||||||
* `ValuesGenerator<T>` -- contains multiple elements
|
* `FixedValuesGenerator<T>` -- contains multiple elements
|
||||||
* 5 generic generators that modify other generators
|
* 5 generic generators that modify other generators
|
||||||
* `FilterGenerator<T, Predicate>` -- filters out elements from a generator
|
* `FilterGenerator<T, Predicate>` -- filters out elements from a generator
|
||||||
for which the predicate returns "false"
|
for which the predicate returns "false"
|
||||||
@@ -44,16 +46,22 @@ a test case,
|
|||||||
* `MapGenerator<T, U, Func>` -- returns the result of applying `Func`
|
* `MapGenerator<T, U, Func>` -- returns the result of applying `Func`
|
||||||
on elements from a different generator
|
on elements from a different generator
|
||||||
* `ChunkGenerator<T>` -- returns chunks (inside `std::vector`) of n elements from a 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
|
* `RandomIntegerGenerator<Integral>` -- generates random Integrals from range
|
||||||
* `RandomFloatGenerator<Float>` -- generates random Floats from range
|
* `RandomFloatGenerator<Float>` -- generates random Floats from range
|
||||||
* `RangeGenerator<T>` -- generates all values inside a specific 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
|
The generators also have associated helper functions that infer their
|
||||||
type, making their usage much nicer. These are
|
type, making their usage much nicer. These are
|
||||||
|
|
||||||
* `value(T&&)` for `ValueGenerator<T>`
|
* `value(T&&)` for `SingleValueGenerator<T>`
|
||||||
* `values(std::initializer_list<T>)` for `ValuesGenerator<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>`
|
* `filter(predicate, GeneratorWrapper<T>&&)` for `FilterGenerator<T, Predicate>`
|
||||||
* `take(count, GeneratorWrapper<T>&&)` for `TakeGenerator<T>`
|
* `take(count, GeneratorWrapper<T>&&)` for `TakeGenerator<T>`
|
||||||
* `repeat(repeats, GeneratorWrapper<T>&&)` for `RepeatGenerator<T>`
|
* `repeat(repeats, GeneratorWrapper<T>&&)` for `RepeatGenerator<T>`
|
||||||
@@ -63,7 +71,12 @@ type, making their usage much nicer. These are
|
|||||||
* `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator`
|
* `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator`
|
||||||
* `range(start, end)` for `RangeGenerator<T>` with a step size of `1`
|
* `range(start, end)` for `RangeGenerator<T>` with a step size of `1`
|
||||||
* `range(start, end, step)` for `RangeGenerator<T>` with a custom step size
|
* `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
|
And can be used as shown in the example below to create a generator
|
||||||
that returns 100 odd random number:
|
that returns 100 odd random number:
|
||||||
@@ -84,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
|
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
|
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
|
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
|
a special generator that concatenates other generators. It can also be
|
||||||
used with other generators as arguments, such as `auto i = GENERATE(0, 2,
|
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
|
take(100, random(300, 3000)));`. This is useful e.g. if you know that
|
||||||
@@ -96,6 +109,8 @@ scope and thus capturing references is dangerous. If you need to use
|
|||||||
variables inside the generator expression, make sure you thought through
|
variables inside the generator expression, make sure you thought through
|
||||||
the lifetime implications and use `GENERATE_COPY` or `GENERATE_REF`.**
|
the lifetime implications and use `GENERATE_COPY` or `GENERATE_REF`.**
|
||||||
|
|
||||||
|
> `GENERATE_COPY` and `GENERATE_REF` were introduced in Catch 2.7.1.
|
||||||
|
|
||||||
You can also override the inferred type by using `as<type>` as the first
|
You can also override the inferred type by using `as<type>` as the first
|
||||||
argument to the macro. This can be useful when dealing with string literals,
|
argument to the macro. This can be useful when dealing with string literals,
|
||||||
if you want them to come out as `std::string`:
|
if you want them to come out as `std::string`:
|
||||||
|
@@ -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.
|
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
|
## Features
|
||||||
This section outlines some missing features, what is their status and their possible workarounds.
|
This section outlines some missing features, what is their status and their possible workarounds.
|
||||||
|
|
||||||
|
@@ -30,6 +30,8 @@ When the last `CHECK` fails in the "Bar" test case, then only one message will b
|
|||||||
|
|
||||||
## Logging without local scope
|
## Logging without local scope
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1522) in Catch 2.7.0.
|
||||||
|
|
||||||
`UNSCOPED_INFO` is similar to `INFO` with two key differences:
|
`UNSCOPED_INFO` is similar to `INFO` with two key differences:
|
||||||
|
|
||||||
- Lifetime of an unscoped message is not tied to its own scope.
|
- Lifetime of an unscoped message is not tied to its own scope.
|
||||||
@@ -104,6 +106,8 @@ This semicolon will be removed with next major version. It is highly advised to
|
|||||||
|
|
||||||
**UNSCOPED_INFO(** _message expression_ **)**
|
**UNSCOPED_INFO(** _message expression_ **)**
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1522) in Catch 2.7.0.
|
||||||
|
|
||||||
Similar to `INFO`, but messages are not limited to their own scope: They are removed from the buffer after each assertion, section or test case, whichever comes first.
|
Similar to `INFO`, but messages are not limited to their own scope: They are removed from the buffer after each assertion, section or test case, whichever comes first.
|
||||||
|
|
||||||
**WARN(** _message expression_ **)**
|
**WARN(** _message expression_ **)**
|
||||||
|
@@ -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.
|
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:
|
For example, to assert that a string ends with a certain substring:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
using Catch::Matchers::EndsWith; // or Catch::EndsWith
|
using Catch::Matchers::EndsWith; // or Catch::EndsWith
|
||||||
std::string str = getStringFromSomewhere();
|
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.
|
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:
|
case sensitive or not:
|
||||||
|
|
||||||
```c++
|
```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:
|
And matchers can be combined:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
REQUIRE_THAT( str,
|
REQUIRE_THAT( str,
|
||||||
EndsWith( "as a service" ) ||
|
EndsWith( "as a service" ) ||
|
||||||
(StartsWith( "Big data" ) && !Contains( "web scale" ) ) );
|
(StartsWith( "Big data" ) && !Contains( "web scale" ) ) );
|
||||||
```
|
```
|
||||||
|
|
||||||
## Built in matchers
|
## 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
|
### 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.
|
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.
|
||||||
@@ -45,13 +55,42 @@ Each of the provided `std::string` matchers also takes an optional second argume
|
|||||||
|
|
||||||
|
|
||||||
### Vector matchers
|
### Vector matchers
|
||||||
The vector matchers are `Contains`, `VectorContains` and `Equals`. `VectorContains` looks for a single element in the matched vector, `Contains` looks for a set (vector) of elements inside the matched vector.
|
Catch2 currently provides 5 built-in matchers that work on `std::vector`.
|
||||||
|
These are
|
||||||
|
|
||||||
|
* `Contains` which checks whether a specified vector is present in the result
|
||||||
|
* `VectorContains` which checks whether a specified element is present in the result
|
||||||
|
* `Equals` which checks whether the result is exactly equal (order matters) to a specific vector
|
||||||
|
* `UnorderedEquals` which checks whether the result is equal to a specific vector under a permutation
|
||||||
|
* `Approx` which checks whether the result is "approx-equal" (order matters, but comparison is done via `Approx`) to a specific vector
|
||||||
|
> Approx matcher was [introduced](https://github.com/catchorg/Catch2/issues/1499) in Catch 2.7.2.
|
||||||
|
|
||||||
|
|
||||||
### Floating point matchers
|
### 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
|
### Generic matchers
|
||||||
Catch also aims to provide a set of generic matchers. Currently this set
|
Catch also aims to provide a set of generic matchers. Currently this set
|
||||||
@@ -72,13 +111,29 @@ The second argument is an optional description of the predicate, and is
|
|||||||
used only during reporting of the result.
|
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
|
## Custom matchers
|
||||||
It's easy to provide your own matchers to extend Catch or just to work with your own types.
|
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.
|
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
|
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.
|
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
|
Here's an example for asserting that an integer falls within a given range
|
||||||
@@ -123,7 +178,7 @@ TEST_CASE("Integers are within a range")
|
|||||||
```
|
```
|
||||||
|
|
||||||
Running this test gives the following in the console:
|
Running this test gives the following in the console:
|
||||||
|
|
||||||
```
|
```
|
||||||
/**/TestFile.cpp:123: FAILED:
|
/**/TestFile.cpp:123: FAILED:
|
||||||
CHECK_THAT( 100, IsBetween( 1, 10 ) )
|
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)
|
### [Azmq](https://github.com/zeromq/azmq)
|
||||||
Boost Asio style bindings for ZeroMQ.
|
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)
|
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
|
||||||
The core part of the Chakra JavaScript engine that powers Microsoft Edge.
|
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)
|
### [Inja](https://github.com/pantor/inja)
|
||||||
A header-only template engine for modern C++.
|
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)
|
### [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.
|
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.
|
||||||
|
|
||||||
@@ -112,6 +112,9 @@ SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gr
|
|||||||
### [Standardese](https://github.com/foonathan/standardese)
|
### [Standardese](https://github.com/foonathan/standardese)
|
||||||
Standardese aims to be a nextgen Doxygen.
|
Standardese aims to be a nextgen Doxygen.
|
||||||
|
|
||||||
|
### [PopHead](https://github.com/SPC-Some-Polish-Coders/PopHead)
|
||||||
|
A 2D, Zombie, RPG game which is being made on our own engine.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[Home](Readme.md#top)
|
[Home](Readme.md#top)
|
||||||
|
@@ -59,6 +59,8 @@ TEST_CASE( "SUCCEED showcase" ) {
|
|||||||
|
|
||||||
* `STATIC_REQUIRE`
|
* `STATIC_REQUIRE`
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1362) in Catch 2.4.2.
|
||||||
|
|
||||||
`STATIC_REQUIRE( expr )` is a macro that can be used the same way as a
|
`STATIC_REQUIRE( expr )` is a macro that can be used the same way as a
|
||||||
`static_assert`, but also registers the success with Catch2, so it is
|
`static_assert`, but also registers the success with Catch2, so it is
|
||||||
reported as a success at runtime. The whole check can also be deferred
|
reported as a success at runtime. The whole check can also be deferred
|
||||||
@@ -132,6 +134,8 @@ ANON_TEST_CASE() {
|
|||||||
|
|
||||||
* `DYNAMIC_SECTION`
|
* `DYNAMIC_SECTION`
|
||||||
|
|
||||||
|
> Introduced in Catch 2.3.0.
|
||||||
|
|
||||||
`DYNAMIC_SECTION` is a `SECTION` where the user can use `operator<<` to
|
`DYNAMIC_SECTION` is a `SECTION` where the user can use `operator<<` to
|
||||||
create the final name for that section. This can be useful with e.g.
|
create the final name for that section. This can be useful with e.g.
|
||||||
generators, or when creating a `SECTION` dynamically, within a loop.
|
generators, or when creating a `SECTION` dynamically, within a loop.
|
||||||
|
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
# Release notes
|
# Release notes
|
||||||
**Contents**<br>
|
**Contents**<br>
|
||||||
|
[2.10.1](#2101)<br>
|
||||||
|
[2.10.0](#2100)<br>
|
||||||
|
[2.9.2](#292)<br>
|
||||||
[2.9.1](#291)<br>
|
[2.9.1](#291)<br>
|
||||||
[2.9.0](#290)<br>
|
[2.9.0](#290)<br>
|
||||||
[2.8.0](#280)<br>
|
[2.8.0](#280)<br>
|
||||||
@@ -26,6 +29,107 @@
|
|||||||
[Older versions](#older-versions)<br>
|
[Older versions](#older-versions)<br>
|
||||||
[Even Older versions](#even-older-versions)<br>
|
[Even Older versions](#even-older-versions)<br>
|
||||||
|
|
||||||
|
|
||||||
|
## 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
|
||||||
|
* `ChunkGenerator` can now be used with chunks of size 0 (#1671)
|
||||||
|
* Nested subsections are now run properly when specific section is run via the `-c` argument (#1670, #1673)
|
||||||
|
* Catch2 now consistently uses `_WIN32` to detect Windows platform (#1676)
|
||||||
|
* `TEMPLATE_LIST_TEST_CASE` now support non-default constructible type lists (#1697)
|
||||||
|
* Fixed a crash in the XMLReporter when a benchmark throws exception during warmup (#1706)
|
||||||
|
* Fixed a possible infinite loop in CompactReporter (#1715)
|
||||||
|
* Fixed `-w NoTests` returning 0 even when no tests were matched (#1449, #1683, #1684)
|
||||||
|
* Fixed matcher compilation under Obj-C++ (#1661)
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* `RepeatGenerator` and `FixedValuesGenerator` now fail to compile when used with `bool` (#1692)
|
||||||
|
* Previously they would fail at runtime.
|
||||||
|
* Catch2 now supports Android's debug logging for its debug output (#1710)
|
||||||
|
* Catch2 now detects and configures itself for the RTX platform (#1693)
|
||||||
|
* You still need to pass `--benchmark-no-analysis` if you are using benchmarking under RTX
|
||||||
|
* Removed a "storage class is not first" warning when compiling Catch2 with PGI compiler (#1717)
|
||||||
|
|
||||||
|
### Miscellaneous
|
||||||
|
* Documentation now contains indication when a specific feature was introduced (#1695)
|
||||||
|
* These start with Catch2 v2.3.0, (a bit over a year ago).
|
||||||
|
* `docs/contributing.md` has been updated to provide contributors guidance on how to add these to newly written documentation
|
||||||
|
* Various other documentation improvements
|
||||||
|
* ToC fixes
|
||||||
|
* Documented `--order` and `--rng-seed` command line options
|
||||||
|
* Benchmarking documentation now clearly states that it requires opt-in
|
||||||
|
* Documented `CATCH_CONFIG_CPP17_OPTIONAL` and `CATCH_CONFIG_CPP17_BYTE` macros
|
||||||
|
* Properly documented built-in vector matchers
|
||||||
|
* 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
|
## 2.9.1
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
@@ -88,7 +192,7 @@
|
|||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
* Reporters now print out the filters applied to test cases (#1550, #1585)
|
* Reporters now print out the filters applied to test cases (#1550, #1585)
|
||||||
* Added `GENERATE_COPY` and `GENERATE_VAR` macros that can use variables inside the generator expression
|
* Added `GENERATE_COPY` and `GENERATE_REF` macros that can use variables inside the generator expression
|
||||||
* Because of the significant danger of lifetime issues, the default `GENERATE` macro still does not allow variables
|
* Because of the significant danger of lifetime issues, the default `GENERATE` macro still does not allow variables
|
||||||
* The `map` generator helper now deduces the mapped return type (#1576)
|
* The `map` generator helper now deduces the mapped return type (#1576)
|
||||||
|
|
||||||
|
@@ -84,10 +84,13 @@ This macro maps onto ```TEST_CASE``` and works in the same way, except that the
|
|||||||
|
|
||||||
These macros map onto ```SECTION```s except that the section names are the _something_s prefixed by "given: ", "when: " or "then: " respectively.
|
These macros map onto ```SECTION```s except that the section names are the _something_s prefixed by "given: ", "when: " or "then: " respectively.
|
||||||
|
|
||||||
|
* **AND_GIVEN(** _something_ **)**
|
||||||
* **AND_WHEN(** _something_ **)**
|
* **AND_WHEN(** _something_ **)**
|
||||||
* **AND_THEN(** _something_ **)**
|
* **AND_THEN(** _something_ **)**
|
||||||
|
|
||||||
Similar to ```WHEN``` and ```THEN``` except that the prefixes start with "and ". These are used to chain ```WHEN```s and ```THEN```s together.
|
Similar to ```GIVEN```, ```WHEN``` and ```THEN``` except that the prefixes start with "and ". These are used to chain ```GIVEN```s, ```WHEN```s and ```THEN```s together.
|
||||||
|
|
||||||
|
> `AND_GIVEN` was [introduced](https://github.com/catchorg/Catch2/issues/1360) in Catch 2.4.0.
|
||||||
|
|
||||||
When any of these macros are used the console reporter recognises them and formats the test case header such that the Givens, Whens and Thens are aligned to aid readability.
|
When any of these macros are used the console reporter recognises them and formats the test case header such that the Givens, Whens and Thens are aligned to aid readability.
|
||||||
|
|
||||||
@@ -101,6 +104,8 @@ by types, in the form of `TEMPLATE_TEST_CASE`,
|
|||||||
|
|
||||||
* **TEMPLATE_TEST_CASE(** _test name_ , _tags_, _type1_, _type2_, ..., _typen_ **)**
|
* **TEMPLATE_TEST_CASE(** _test name_ , _tags_, _type1_, _type2_, ..., _typen_ **)**
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1437) in Catch 2.5.0.
|
||||||
|
|
||||||
_test name_ and _tag_ are exactly the same as they are in `TEST_CASE`,
|
_test name_ and _tag_ are exactly the same as they are in `TEST_CASE`,
|
||||||
with the difference that the tag string must be provided (however, it
|
with the difference that the tag string must be provided (however, it
|
||||||
can be empty). _type1_ through _typen_ is the list of types for which
|
can be empty). _type1_ through _typen_ is the list of types for which
|
||||||
@@ -151,6 +156,8 @@ TEMPLATE_TEST_CASE( "vectors can be sized and resized", "[vector][template]", in
|
|||||||
|
|
||||||
* **TEMPLATE_PRODUCT_TEST_CASE(** _test name_ , _tags_, (_template-type1_, _template-type2_, ..., _template-typen_), (_template-arg1_, _template-arg2_, ..., _template-argm_) **)**
|
* **TEMPLATE_PRODUCT_TEST_CASE(** _test name_ , _tags_, (_template-type1_, _template-type2_, ..., _template-typen_), (_template-arg1_, _template-arg2_, ..., _template-argm_) **)**
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1468) in Catch 2.6.0.
|
||||||
|
|
||||||
_template-type1_ through _template-typen_ is list of template template
|
_template-type1_ through _template-typen_ is list of template template
|
||||||
types which should be combined with each of _template-arg1_ through
|
types which should be combined with each of _template-arg1_ through
|
||||||
_template-argm_, resulting in _n * m_ test cases. Inside the test case,
|
_template-argm_, resulting in _n * m_ test cases. Inside the test case,
|
||||||
@@ -194,6 +201,8 @@ is very high and should not be encountered in practice._
|
|||||||
|
|
||||||
* **TEMPLATE_LIST_TEST_CASE(** _test name_, _tags_, _type list_ **)**
|
* **TEMPLATE_LIST_TEST_CASE(** _test name_, _tags_, _type list_ **)**
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1627) in Catch 2.9.0.
|
||||||
|
|
||||||
_type list_ is a generic list of types on which test case should be instantiated.
|
_type list_ is a generic list of types on which test case should be instantiated.
|
||||||
List can be `std::tuple`, `boost::mpl::list`, `boost::mp11::mp_list` or anything with
|
List can be `std::tuple`, `boost::mpl::list`, `boost::mp11::mp_list` or anything with
|
||||||
`template <typename...>` signature.
|
`template <typename...>` signature.
|
||||||
@@ -212,6 +221,8 @@ TEMPLATE_LIST_TEST_CASE("Template test case with test types specified inside std
|
|||||||
|
|
||||||
## Signature based parametrised test cases
|
## Signature based parametrised test cases
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1609) in Catch 2.8.0.
|
||||||
|
|
||||||
In addition to [type parametrised test cases](#type-parametrised-test-cases) Catch2 also supports
|
In addition to [type parametrised test cases](#type-parametrised-test-cases) Catch2 also supports
|
||||||
signature base parametrised test cases, in form of `TEMPLATE_TEST_CASE_SIG` and `TEMPLATE_PRODUCT_TEST_CASE_SIG`.
|
signature base parametrised test cases, in form of `TEMPLATE_TEST_CASE_SIG` and `TEMPLATE_PRODUCT_TEST_CASE_SIG`.
|
||||||
These test cases have similar syntax like [type parametrised test cases](#type-parametrised-test-cases), with one
|
These test cases have similar syntax like [type parametrised test cases](#type-parametrised-test-cases), with one
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Test fixtures
|
# Test fixtures
|
||||||
|
|
||||||
|
## Defining test fixtures
|
||||||
|
|
||||||
Although Catch allows you to group tests together as sections within a test case, it can still be convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure:
|
Although Catch allows you to group tests together as sections within a test case, it can still be convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
@@ -84,6 +86,9 @@ _While there is an upper limit on the number of types you can specify
|
|||||||
in single `TEMPLATE_TEST_CASE_METHOD` or `TEMPLATE_PRODUCT_TEST_CASE_METHOD`,
|
in single `TEMPLATE_TEST_CASE_METHOD` or `TEMPLATE_PRODUCT_TEST_CASE_METHOD`,
|
||||||
the limit is very high and should not be encountered in practice._
|
the limit is very high and should not be encountered in practice._
|
||||||
|
|
||||||
|
## Signature-based parametrised test fixtures
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1609) in Catch 2.8.0.
|
||||||
|
|
||||||
Catch2 also provides `TEMPLATE_TEST_CASE_METHOD_SIG` and `TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG` to support
|
Catch2 also provides `TEMPLATE_TEST_CASE_METHOD_SIG` and `TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG` to support
|
||||||
fixtures using non-type template parameters. These test cases work similar to `TEMPLATE_TEST_CASE_METHOD` and `TEMPLATE_PRODUCT_TEST_CASE_METHOD`,
|
fixtures using non-type template parameters. These test cases work similar to `TEMPLATE_TEST_CASE_METHOD` and `TEMPLATE_PRODUCT_TEST_CASE_METHOD`,
|
||||||
@@ -100,6 +105,13 @@ TEMPLATE_TEST_CASE_METHOD_SIG(Nttp_Fixture, "A TEMPLATE_TEST_CASE_METHOD_SIG bas
|
|||||||
REQUIRE(Nttp_Fixture<V>::value > 0);
|
REQUIRE(Nttp_Fixture<V>::value > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Template_Fixture_2 {
|
||||||
|
Template_Fixture_2() {}
|
||||||
|
|
||||||
|
T m_a;
|
||||||
|
};
|
||||||
|
|
||||||
template< typename T, size_t V>
|
template< typename T, size_t V>
|
||||||
struct Template_Foo_2 {
|
struct Template_Foo_2 {
|
||||||
size_t size() { return V; }
|
size_t size() { return V; }
|
||||||
@@ -111,6 +123,8 @@ TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(Template_Fixture_2, "A TEMPLATE_PRODUCT_TE
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Template fixtures with types specified in template type lists
|
||||||
|
|
||||||
Catch2 also provides `TEMPLATE_LIST_TEST_CASE_METHOD` to support template fixtures with types specified in
|
Catch2 also provides `TEMPLATE_LIST_TEST_CASE_METHOD` to support template fixtures with types specified in
|
||||||
template type lists like `std::tuple`, `boost::mpl::list` or `boost::mp11::mp_list`. This test case works the same as `TEMPLATE_TEST_CASE_METHOD`,
|
template type lists like `std::tuple`, `boost::mpl::list` or `boost::mp11::mp_list`. This test case works the same as `TEMPLATE_TEST_CASE_METHOD`,
|
||||||
only difference is the source of types. This allows you to reuse the template type list in multiple test cases.
|
only difference is the source of types. This allows you to reuse the template type list in multiple test cases.
|
||||||
|
@@ -71,6 +71,8 @@ CATCH_TRANSLATE_EXCEPTION( MyType& ex ) {
|
|||||||
|
|
||||||
## Enums
|
## Enums
|
||||||
|
|
||||||
|
> Introduced in Catch 2.8.0.
|
||||||
|
|
||||||
Enums that already have a `<<` overload for `std::ostream` will convert to strings as expected.
|
Enums that already have a `<<` overload for `std::ostream` will convert to strings as expected.
|
||||||
If you only need to convert enums to strings for test reporting purposes you can provide a `StringMaker` specialisations as any other type.
|
If you only need to convert enums to strings for test reporting purposes you can provide a `StringMaker` specialisations as any other type.
|
||||||
However, as a convenience, Catch provides the `REGISTER_ENUM` helper macro that will generate the `StringMaker` specialiation for you with minimal code.
|
However, as a convenience, Catch provides the `REGISTER_ENUM` helper macro that will generate the `StringMaker` specialiation for you with minimal code.
|
||||||
@@ -108,6 +110,8 @@ TEST_CASE() {
|
|||||||
|
|
||||||
## Floating point precision
|
## Floating point precision
|
||||||
|
|
||||||
|
> [Introduced](https://github.com/catchorg/Catch2/issues/1614) in Catch 2.8.0.
|
||||||
|
|
||||||
Catch provides a built-in `StringMaker` specialization for both `float`
|
Catch provides a built-in `StringMaker` specialization for both `float`
|
||||||
and `double`. By default, it uses what we think is a reasonable precision,
|
and `double`. By default, it uses what we think is a reasonable precision,
|
||||||
but you can customize it by modifying the `precision` static variable
|
but you can customize it by modifying the `precision` static variable
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
||||||
|
|
||||||
#define CATCH_VERSION_MAJOR 2
|
#define CATCH_VERSION_MAJOR 2
|
||||||
#define CATCH_VERSION_MINOR 9
|
#define CATCH_VERSION_MINOR 10
|
||||||
#define CATCH_VERSION_PATCH 1
|
#define CATCH_VERSION_PATCH 1
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
|
@@ -52,7 +52,8 @@ namespace Detail {
|
|||||||
bool Approx::equalityComparisonImpl(const double other) const {
|
bool Approx::equalityComparisonImpl(const double other) const {
|
||||||
// First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
|
// 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
|
// 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) {
|
void Approx::setMargin(double newMargin) {
|
||||||
|
@@ -45,7 +45,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AssertionResult::hasExpression() const {
|
bool AssertionResult::hasExpression() const {
|
||||||
return m_info.capturedExpression[0] != 0;
|
return !m_info.capturedExpression.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssertionResult::hasMessage() const {
|
bool AssertionResult::hasMessage() const {
|
||||||
@@ -53,16 +53,22 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string AssertionResult::getExpression() const {
|
std::string AssertionResult::getExpression() const {
|
||||||
if( isFalseTest( m_info.resultDisposition ) )
|
// Possibly overallocating by 3 characters should be basically free
|
||||||
return "!(" + m_info.capturedExpression + ")";
|
std::string expr; expr.reserve(m_info.capturedExpression.size() + 3);
|
||||||
else
|
if (isFalseTest(m_info.resultDisposition)) {
|
||||||
return m_info.capturedExpression;
|
expr += "!(";
|
||||||
|
}
|
||||||
|
expr += m_info.capturedExpression;
|
||||||
|
if (isFalseTest(m_info.resultDisposition)) {
|
||||||
|
expr += ')';
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AssertionResult::getExpressionInMacro() const {
|
std::string AssertionResult::getExpressionInMacro() const {
|
||||||
std::string expr;
|
std::string expr;
|
||||||
if( m_info.macroName[0] == 0 )
|
if( m_info.macroName.empty() )
|
||||||
expr = m_info.capturedExpression;
|
expr = static_cast<std::string>(m_info.capturedExpression);
|
||||||
else {
|
else {
|
||||||
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
|
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
|
||||||
expr += m_info.macroName;
|
expr += m_info.macroName;
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "catch_capture.hpp"
|
#include "catch_capture.hpp"
|
||||||
#include "catch_matchers.h"
|
#include "catch_matchers.h"
|
||||||
|
#include "catch_matchers_exception.hpp"
|
||||||
#include "catch_matchers_floating.h"
|
#include "catch_matchers_floating.h"
|
||||||
#include "catch_matchers_generic.hpp"
|
#include "catch_matchers_generic.hpp"
|
||||||
#include "catch_matchers_string.h"
|
#include "catch_matchers_string.h"
|
||||||
|
@@ -49,9 +49,15 @@ namespace Catch {
|
|||||||
if( !line.empty() && !startsWith( line, '#' ) ) {
|
if( !line.empty() && !startsWith( line, '#' ) ) {
|
||||||
if( !startsWith( line, '"' ) )
|
if( !startsWith( line, '"' ) )
|
||||||
line = '"' + 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 );
|
return ParserResult::ok( ParseResultType::Matched );
|
||||||
};
|
};
|
||||||
auto const setTestOrder = [&]( std::string const& order ) {
|
auto const setTestOrder = [&]( std::string const& order ) {
|
||||||
|
@@ -15,9 +15,6 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
bool SourceLineInfo::empty() const noexcept {
|
|
||||||
return file[0] == '\0';
|
|
||||||
}
|
|
||||||
bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {
|
bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {
|
||||||
return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
|
return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
|
||||||
}
|
}
|
||||||
|
@@ -57,7 +57,7 @@ namespace Catch {
|
|||||||
SourceLineInfo( SourceLineInfo&& ) noexcept = default;
|
SourceLineInfo( SourceLineInfo&& ) noexcept = default;
|
||||||
SourceLineInfo& operator = ( 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;
|
||||||
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 \
|
# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
_Pragma( "clang diagnostic pop" )
|
_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__
|
#endif // __clang__
|
||||||
|
|
||||||
|
|
||||||
@@ -94,6 +99,7 @@
|
|||||||
// Android somehow still does not support std::to_string
|
// Android somehow still does not support std::to_string
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
|
# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
|
||||||
|
# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -115,7 +121,7 @@
|
|||||||
// Required for some versions of Cygwin to declare gettimeofday
|
// Required for some versions of Cygwin to declare gettimeofday
|
||||||
// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
|
// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
|
||||||
# define _BSD_SOURCE
|
# 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
|
// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
|
||||||
# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
|
# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
|
||||||
&& !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
|
&& !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
|
||||||
@@ -184,49 +190,55 @@
|
|||||||
#define CATCH_INTERNAL_CONFIG_COUNTER
|
#define CATCH_INTERNAL_CONFIG_COUNTER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Check if string_view is available and usable
|
|
||||||
// The check is split apart to work around v140 (VS2015) preprocessor issue...
|
// RTX is a special version of Windows that is real time.
|
||||||
#if defined(__has_include)
|
// This means that it is detected as Windows, but does not provide
|
||||||
#if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
|
// the same set of capabilities as real Windows does.
|
||||||
# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
|
#if defined(UNDER_RTSS) || defined(RTX64_BUILD)
|
||||||
#endif
|
#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
|
||||||
|
#define CATCH_INTERNAL_CONFIG_NO_ASYNC
|
||||||
|
#define CATCH_CONFIG_COLOUR_NONE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
#if defined(__UCLIBC__)
|
||||||
// Check if optional is available and usable
|
#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
|
||||||
#if defined(__has_include)
|
#endif
|
||||||
# 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
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
// Various stdlib support checks that require __has_include
|
||||||
// Check if byte is available and usable
|
|
||||||
#if defined(__has_include)
|
#if defined(__has_include)
|
||||||
# if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
// Check if string_view is available and usable
|
||||||
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE
|
#if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
|
||||||
# endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
|
||||||
#endif // __has_include
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
// Check if optional is available and usable
|
||||||
// Check if variant is available and usable
|
# if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
|
||||||
#if defined(__has_include)
|
# define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
|
||||||
# if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
|
# endif // __has_include(<optional>) && 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
|
// Check if byte is available and usable
|
||||||
// fix should be in clang 8, workaround in libstdc++ 8.2
|
# if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
||||||
# include <ciso646>
|
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE
|
||||||
# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
|
# endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
||||||
# define CATCH_CONFIG_NO_CPP17_VARIANT
|
|
||||||
# else
|
// Check if variant is available and usable
|
||||||
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
|
# if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
|
||||||
# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
|
# if defined(__clang__) && (__clang_major__ < 8)
|
||||||
# else
|
// work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
|
||||||
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
|
// fix should be in clang 8, workaround in libstdc++ 8.2
|
||||||
# endif // defined(__clang__) && (__clang_major__ < 8)
|
# include <ciso646>
|
||||||
# endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
|
# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
|
||||||
#endif // __has_include
|
# 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)
|
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
|
||||||
@@ -285,10 +297,18 @@
|
|||||||
# define CATCH_CONFIG_POLYFILL_ISNAN
|
# define CATCH_CONFIG_POLYFILL_ISNAN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
|
#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
|
||||||
# define CATCH_CONFIG_USE_ASYNC
|
# define CATCH_CONFIG_USE_ASYNC
|
||||||
#endif
|
#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)
|
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
|
||||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
|
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
|
||||||
@@ -306,6 +326,19 @@
|
|||||||
# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS
|
# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS
|
||||||
#endif
|
#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)
|
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||||
#define CATCH_TRY if ((true))
|
#define CATCH_TRY if ((true))
|
||||||
#define CATCH_CATCH_ALL if ((false))
|
#define CATCH_CATCH_ALL if ((false))
|
||||||
|
@@ -15,11 +15,23 @@ namespace Catch {
|
|||||||
: m_data( data ),
|
: m_data( data ),
|
||||||
m_stream( openStream() )
|
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());
|
TestSpecParser parser(ITagAliasRegistry::get());
|
||||||
if (!data.testsOrTags.empty()) {
|
if (!m_data.testsOrTags.empty()) {
|
||||||
m_hasTestFilters = true;
|
m_hasTestFilters = true;
|
||||||
for( auto const& testOrTags : data.testsOrTags )
|
for (auto const& testOrTags : m_data.testsOrTags) {
|
||||||
parser.parse( testOrTags );
|
parser.parse(testOrTags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_testSpec = parser.testSpec();
|
m_testSpec = parser.testSpec();
|
||||||
}
|
}
|
||||||
@@ -32,7 +44,7 @@ namespace Catch {
|
|||||||
bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; }
|
bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; }
|
||||||
bool Config::listTags() const { return m_data.listTags; }
|
bool Config::listTags() const { return m_data.listTags; }
|
||||||
bool Config::listReporters() const { return m_data.listReporters; }
|
bool Config::listReporters() const { return m_data.listReporters; }
|
||||||
|
|
||||||
std::string Config::getProcessName() const { return m_data.processName; }
|
std::string Config::getProcessName() const { return m_data.processName; }
|
||||||
std::string const& Config::getReporterName() const { return m_data.reporterName; }
|
std::string const& Config::getReporterName() const { return m_data.reporterName; }
|
||||||
|
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "catch_context.h"
|
#include "catch_context.h"
|
||||||
#include "catch_common.h"
|
#include "catch_common.h"
|
||||||
|
#include "catch_random_number_generator.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -59,4 +60,11 @@ namespace Catch {
|
|||||||
IContext::~IContext() = default;
|
IContext::~IContext() = default;
|
||||||
IMutableContext::~IMutableContext() = default;
|
IMutableContext::~IMutableContext() = default;
|
||||||
Context::~Context() = default;
|
Context::~Context() = default;
|
||||||
|
|
||||||
|
|
||||||
|
SimplePcg32& rng() {
|
||||||
|
static SimplePcg32 s_rng;
|
||||||
|
return s_rng;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -46,6 +46,7 @@ namespace Catch {
|
|||||||
{
|
{
|
||||||
if( !IMutableContext::currentContext )
|
if( !IMutableContext::currentContext )
|
||||||
IMutableContext::createContext();
|
IMutableContext::createContext();
|
||||||
|
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
|
||||||
return *IMutableContext::currentContext;
|
return *IMutableContext::currentContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +56,9 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cleanUpContext();
|
void cleanUpContext();
|
||||||
|
|
||||||
|
class SimplePcg32;
|
||||||
|
SimplePcg32& rng();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
|
||||||
|
@@ -7,11 +7,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_debug_console.h"
|
#include "catch_debug_console.h"
|
||||||
|
#include "catch_compiler_capabilities.h"
|
||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
#include "catch_platform.h"
|
#include "catch_platform.h"
|
||||||
#include "catch_windows_h_proxy.h"
|
#include "catch_windows_h_proxy.h"
|
||||||
|
|
||||||
#ifdef CATCH_PLATFORM_WINDOWS
|
#if defined(CATCH_CONFIG_ANDROID_LOGWRITE)
|
||||||
|
#include <android/log.h>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
void writeToDebugConsole( std::string const& text ) {
|
||||||
|
__android_log_write( ANDROID_LOG_DEBUG, "Catch", text.c_str() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(CATCH_PLATFORM_WINDOWS)
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
void writeToDebugConsole( std::string const& text ) {
|
void writeToDebugConsole( std::string const& text ) {
|
||||||
|
@@ -38,13 +38,13 @@ namespace Catch {
|
|||||||
(Catch::ReusableStringStream() << __VA_ARGS__).str()
|
(Catch::ReusableStringStream() << __VA_ARGS__).str()
|
||||||
|
|
||||||
#define CATCH_INTERNAL_ERROR(...) \
|
#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(...) \
|
#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(...) \
|
#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, ... ) \
|
#define CATCH_ENFORCE( condition, ... ) \
|
||||||
do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)
|
do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)
|
||||||
|
@@ -18,13 +18,25 @@ namespace Catch {
|
|||||||
|
|
||||||
namespace Detail {
|
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, ',' );
|
auto enumValues = splitStringRef( enums, ',' );
|
||||||
std::vector<std::string> parsed;
|
std::vector<StringRef> parsed;
|
||||||
parsed.reserve( enumValues.size() );
|
parsed.reserve( enumValues.size() );
|
||||||
for( auto const& enumValue : enumValues ) {
|
for( auto const& enumValue : enumValues ) {
|
||||||
auto identifiers = splitStringRef( enumValue, ':' );
|
parsed.push_back(trim(extractInstanceName(enumValue)));
|
||||||
parsed.push_back( Catch::trim( identifiers.back() ) );
|
|
||||||
}
|
}
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
@@ -36,7 +48,7 @@ namespace Catch {
|
|||||||
if( valueToName.first == value )
|
if( valueToName.first == value )
|
||||||
return valueToName.second;
|
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 ) {
|
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 ) {
|
EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
|
||||||
auto enumInfo = makeEnumInfo( enumName, allValueNames, values );
|
m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));
|
||||||
EnumInfo* raw = enumInfo.get();
|
return *m_enumInfos.back();
|
||||||
m_enumInfos.push_back( std::move( enumInfo ) );
|
|
||||||
return *raw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Detail
|
} // Detail
|
||||||
|
@@ -26,7 +26,7 @@ namespace Catch {
|
|||||||
EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values) override;
|
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
|
} // Detail
|
||||||
|
|
||||||
|
@@ -97,7 +97,7 @@ namespace Catch {
|
|||||||
|
|
||||||
// 32kb for the alternate stack seems to be sufficient. However, this value
|
// 32kb for the alternate stack seems to be sufficient. However, this value
|
||||||
// is experimentally determined, so that's not guaranteed.
|
// is experimentally determined, so that's not guaranteed.
|
||||||
constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
|
static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
|
||||||
|
|
||||||
static SignalDefs signalDefs[] = {
|
static SignalDefs signalDefs[] = {
|
||||||
{ SIGINT, "SIGINT - Terminal interrupt signal" },
|
{ SIGINT, "SIGINT - Terminal interrupt signal" },
|
||||||
|
@@ -71,7 +71,7 @@ namespace Generators {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
class FixedValuesGenerator final : public IGenerator<T> {
|
class FixedValuesGenerator final : public IGenerator<T> {
|
||||||
static_assert(!std::is_same<T, bool>::value,
|
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.");
|
"specialization, use SingleValue Generator instead.");
|
||||||
std::vector<T> m_values;
|
std::vector<T> m_values;
|
||||||
size_t m_idx = 0;
|
size_t m_idx = 0;
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include "catch_context.h"
|
#include "catch_context.h"
|
||||||
#include "catch_generators.hpp"
|
#include "catch_generators.hpp"
|
||||||
#include "catch_interfaces_config.h"
|
#include "catch_interfaces_config.h"
|
||||||
|
#include "catch_random_number_generator.h"
|
||||||
|
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
@@ -18,14 +19,13 @@ namespace Generators {
|
|||||||
|
|
||||||
template <typename Float>
|
template <typename Float>
|
||||||
class RandomFloatingGenerator final : public IGenerator<Float> {
|
class RandomFloatingGenerator final : public IGenerator<Float> {
|
||||||
// FIXME: What is the right seed?
|
Catch::SimplePcg32& m_rng;
|
||||||
std::minstd_rand m_rand;
|
|
||||||
std::uniform_real_distribution<Float> m_dist;
|
std::uniform_real_distribution<Float> m_dist;
|
||||||
Float m_current_number;
|
Float m_current_number;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
RandomFloatingGenerator(Float a, Float b):
|
RandomFloatingGenerator(Float a, Float b):
|
||||||
m_rand(getCurrentContext().getConfig()->rngSeed()),
|
m_rng(rng()),
|
||||||
m_dist(a, b) {
|
m_dist(a, b) {
|
||||||
static_cast<void>(next());
|
static_cast<void>(next());
|
||||||
}
|
}
|
||||||
@@ -34,20 +34,20 @@ public:
|
|||||||
return m_current_number;
|
return m_current_number;
|
||||||
}
|
}
|
||||||
bool next() override {
|
bool next() override {
|
||||||
m_current_number = m_dist(m_rand);
|
m_current_number = m_dist(m_rng);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Integer>
|
template <typename Integer>
|
||||||
class RandomIntegerGenerator final : public IGenerator<Integer> {
|
class RandomIntegerGenerator final : public IGenerator<Integer> {
|
||||||
std::minstd_rand m_rand;
|
Catch::SimplePcg32& m_rng;
|
||||||
std::uniform_int_distribution<Integer> m_dist;
|
std::uniform_int_distribution<Integer> m_dist;
|
||||||
Integer m_current_number;
|
Integer m_current_number;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
RandomIntegerGenerator(Integer a, Integer b):
|
RandomIntegerGenerator(Integer a, Integer b):
|
||||||
m_rand(getCurrentContext().getConfig()->rngSeed()),
|
m_rng(rng()),
|
||||||
m_dist(a, b) {
|
m_dist(a, b) {
|
||||||
static_cast<void>(next());
|
static_cast<void>(next());
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ public:
|
|||||||
return m_current_number;
|
return m_current_number;
|
||||||
}
|
}
|
||||||
bool next() override {
|
bool next() override {
|
||||||
m_current_number = m_dist(m_rand);
|
m_current_number = m_dist(m_rng);
|
||||||
return true;
|
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 Generators
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#include "internal/catch_interfaces_config.h"
|
#include "catch_interfaces_config.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
IConfig::~IConfig() = default;
|
IConfig::~IConfig() = default;
|
||||||
|
@@ -17,7 +17,7 @@ namespace Catch {
|
|||||||
namespace Detail {
|
namespace Detail {
|
||||||
struct EnumInfo {
|
struct EnumInfo {
|
||||||
StringRef m_name;
|
StringRef m_name;
|
||||||
std::vector<std::pair<int, std::string>> m_values;
|
std::vector<std::pair<int, StringRef>> m_values;
|
||||||
|
|
||||||
~EnumInfo();
|
~EnumInfo();
|
||||||
|
|
||||||
@@ -32,6 +32,7 @@ namespace Catch {
|
|||||||
|
|
||||||
template<typename E>
|
template<typename E>
|
||||||
Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
|
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;
|
std::vector<int> intValues;
|
||||||
intValues.reserve( values.size() );
|
intValues.reserve( values.size() );
|
||||||
for( auto enumValue : values )
|
for( auto enumValue : values )
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#include "internal/catch_interfaces_exception.h"
|
#include "catch_interfaces_exception.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
IExceptionTranslator::~IExceptionTranslator() = default;
|
IExceptionTranslator::~IExceptionTranslator() = default;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#include "internal/catch_interfaces_registry_hub.h"
|
#include "catch_interfaces_registry_hub.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
IRegistryHub::~IRegistryHub() = default;
|
IRegistryHub::~IRegistryHub() = default;
|
||||||
|
@@ -214,6 +214,8 @@ namespace Catch {
|
|||||||
|
|
||||||
virtual void noMatchingTestCases( std::string const& spec ) = 0;
|
virtual void noMatchingTestCases( std::string const& spec ) = 0;
|
||||||
|
|
||||||
|
virtual void reportInvalidArguments(std::string const&) {}
|
||||||
|
|
||||||
virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
|
virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
|
||||||
virtual void testGroupStarting( GroupInfo const& groupInfo ) = 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 {
|
namespace Catch {
|
||||||
IRunner::~IRunner() = default;
|
IRunner::~IRunner() = default;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#include "internal/catch_interfaces_testcase.h"
|
#include "catch_interfaces_testcase.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
ITestInvoker::~ITestInvoker() = default;
|
ITestInvoker::~ITestInvoker() = default;
|
||||||
|
@@ -28,6 +28,7 @@ namespace Catch {
|
|||||||
virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
|
virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool isThrowSafe( TestCase const& testCase, IConfig const& config );
|
||||||
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
|
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
|
||||||
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
|
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
|
||||||
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
|
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
|
||||||
|
@@ -84,9 +84,18 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string TagInfo::all() const {
|
std::string TagInfo::all() const {
|
||||||
std::string out;
|
size_t size = 0;
|
||||||
for( auto const& spelling : spellings )
|
for (auto const& spelling : spellings) {
|
||||||
out += "[" + spelling + "]";
|
// Add 2 for the brackes
|
||||||
|
size += spelling.size() + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string out; out.reserve(size);
|
||||||
|
for (auto const& spelling : spellings) {
|
||||||
|
out += '[';
|
||||||
|
out += spelling;
|
||||||
|
out += ']';
|
||||||
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -44,6 +44,15 @@ namespace Matchers {
|
|||||||
virtual bool match( ObjectT const& arg ) const = 0;
|
virtual bool match( ObjectT const& arg ) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(__OBJC__)
|
||||||
|
// Hack to fix Catch GH issue #1661. Could use id for generic Object support.
|
||||||
|
// use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation
|
||||||
|
template<>
|
||||||
|
struct MatcherMethod<NSString*> {
|
||||||
|
virtual bool match( NSString* arg ) const = 0;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
# pragma clang diagnostic pop
|
# pragma clang diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
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_to_string.hpp"
|
||||||
#include "catch_tostring.h"
|
#include "catch_tostring.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <type_traits>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Matchers {
|
namespace {
|
||||||
namespace Floating {
|
|
||||||
enum class FloatingPointKind : uint8_t {
|
int32_t convert(float f) {
|
||||||
Float,
|
static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated");
|
||||||
Double
|
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 {
|
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>
|
template <typename FP>
|
||||||
bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) {
|
FP step(FP start, FP direction, uint64_t steps) {
|
||||||
// Comparison with NaN should always be false.
|
for (uint64_t i = 0; i < steps; ++i) {
|
||||||
// This way we can rule it out before getting into the ugly details
|
#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
|
||||||
if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
|
start = Catch::nextafter(start, direction);
|
||||||
return false;
|
#else
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
start = std::nextafter(start, direction);
|
start = std::nextafter(start, direction);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return start;
|
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
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
namespace Catch {
|
|
||||||
namespace Matchers {
|
namespace Matchers {
|
||||||
namespace Floating {
|
namespace Floating {
|
||||||
|
|
||||||
|
enum class FloatingPointKind : uint8_t {
|
||||||
|
Float,
|
||||||
|
Double
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
|
WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
|
||||||
:m_target{ target }, m_margin{ margin } {
|
:m_target{ target }, m_margin{ margin } {
|
||||||
CATCH_ENFORCE(margin >= 0, "Invalid 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 } {
|
:m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
|
||||||
CATCH_ENFORCE(ulps >= 0, "Invalid ULP setting: " << ulps << '.'
|
CATCH_ENFORCE(m_type == FloatingPointKind::Double
|
||||||
<< " ULPs have to be non-negative.");
|
|| m_ulps < (std::numeric_limits<uint32_t>::max)(),
|
||||||
|
"Provided ULP is impossibly large for a float comparison.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
@@ -138,38 +173,58 @@ namespace Floating {
|
|||||||
std::string WithinUlpsMatcher::describe() const {
|
std::string WithinUlpsMatcher::describe() const {
|
||||||
std::stringstream ret;
|
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) {
|
if (m_type == FloatingPointKind::Float) {
|
||||||
|
write(ret, static_cast<float>(m_target));
|
||||||
ret << 'f';
|
ret << 'f';
|
||||||
|
} else {
|
||||||
|
write(ret, m_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret << " ([";
|
ret << " ([";
|
||||||
ret << std::fixed << std::setprecision(std::numeric_limits<double>::max_digits10);
|
|
||||||
if (m_type == FloatingPointKind::Double) {
|
if (m_type == FloatingPointKind::Double) {
|
||||||
ret << step(m_target, static_cast<double>(-INFINITY), m_ulps)
|
write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps));
|
||||||
<< ", "
|
ret << ", ";
|
||||||
<< step(m_target, static_cast<double>(INFINITY), m_ulps);
|
write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps));
|
||||||
} else {
|
} else {
|
||||||
ret << step<float>(static_cast<float>(m_target), -INFINITY, m_ulps)
|
write(ret, step(static_cast<float>(m_target), -INFINITY, m_ulps));
|
||||||
<< ", "
|
ret << ", ";
|
||||||
<< step<float>(static_cast<float>(m_target), INFINITY, m_ulps);
|
write(ret, step(static_cast<float>(m_target), INFINITY, m_ulps));
|
||||||
}
|
}
|
||||||
ret << "])";
|
ret << "])";
|
||||||
|
|
||||||
return ret.str();
|
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
|
}// 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);
|
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);
|
return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,6 +232,23 @@ Floating::WithinAbsMatcher WithinAbs(double target, double margin) {
|
|||||||
return Floating::WithinAbsMatcher(target, 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 Matchers
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
|
@@ -9,9 +9,6 @@
|
|||||||
|
|
||||||
#include "catch_matchers.h"
|
#include "catch_matchers.h"
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Matchers {
|
namespace Matchers {
|
||||||
|
|
||||||
@@ -29,23 +26,43 @@ namespace Matchers {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct WithinUlpsMatcher : MatcherBase<double> {
|
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;
|
bool match(double const& matchee) const override;
|
||||||
std::string describe() const override;
|
std::string describe() const override;
|
||||||
private:
|
private:
|
||||||
double m_target;
|
double m_target;
|
||||||
int m_ulps;
|
uint64_t m_ulps;
|
||||||
FloatingPointKind m_type;
|
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
|
} // namespace Floating
|
||||||
|
|
||||||
// The following functions create the actual matcher objects.
|
// The following functions create the actual matcher objects.
|
||||||
// This allows the types to be inferred
|
// This allows the types to be inferred
|
||||||
Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff);
|
Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
|
||||||
Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff);
|
Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
|
||||||
Floating::WithinAbsMatcher WithinAbs(double target, double margin);
|
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 Matchers
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
@@ -113,7 +113,7 @@ namespace Catch {
|
|||||||
case ',':
|
case ',':
|
||||||
if (start != pos && openings.size() == 0) {
|
if (start != pos && openings.size() == 0) {
|
||||||
m_messages.emplace_back(macroName, lineInfo, resultType);
|
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 += " := ";
|
m_messages.back().message += " := ";
|
||||||
start = pos;
|
start = pos;
|
||||||
}
|
}
|
||||||
@@ -121,7 +121,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
assert(openings.size() == 0 && "Mismatched openings");
|
assert(openings.size() == 0 && "Mismatched openings");
|
||||||
m_messages.emplace_back(macroName, lineInfo, resultType);
|
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 += " := ";
|
m_messages.back().message += " := ";
|
||||||
}
|
}
|
||||||
Capturer::~Capturer() {
|
Capturer::~Capturer() {
|
||||||
|
@@ -116,7 +116,7 @@ namespace Catch {
|
|||||||
arcSafeRelease( m_substr );
|
arcSafeRelease( m_substr );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool match( NSString* const& str ) const override {
|
bool match( NSString* str ) const override {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ namespace Catch {
|
|||||||
struct Equals : StringHolder {
|
struct Equals : StringHolder {
|
||||||
Equals( NSString* substr ) : StringHolder( substr ){}
|
Equals( NSString* substr ) : StringHolder( substr ){}
|
||||||
|
|
||||||
bool match( NSString* const& str ) const override {
|
bool match( NSString* str ) const override {
|
||||||
return (str != nil || m_substr == nil ) &&
|
return (str != nil || m_substr == nil ) &&
|
||||||
[str isEqualToString:m_substr];
|
[str isEqualToString:m_substr];
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ namespace Catch {
|
|||||||
struct Contains : StringHolder {
|
struct Contains : StringHolder {
|
||||||
Contains( NSString* substr ) : StringHolder( substr ){}
|
Contains( NSString* substr ) : StringHolder( substr ){}
|
||||||
|
|
||||||
bool match( NSString* const& str ) const override {
|
bool match( NSString* str ) const override {
|
||||||
return (str != nil || m_substr == nil ) &&
|
return (str != nil || m_substr == nil ) &&
|
||||||
[str rangeOfString:m_substr].location != NSNotFound;
|
[str rangeOfString:m_substr].location != NSNotFound;
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ namespace Catch {
|
|||||||
struct StartsWith : StringHolder {
|
struct StartsWith : StringHolder {
|
||||||
StartsWith( NSString* substr ) : StringHolder( substr ){}
|
StartsWith( NSString* substr ) : StringHolder( substr ){}
|
||||||
|
|
||||||
bool match( NSString* const& str ) const override {
|
bool match( NSString* str ) const override {
|
||||||
return (str != nil || m_substr == nil ) &&
|
return (str != nil || m_substr == nil ) &&
|
||||||
[str rangeOfString:m_substr].location == 0;
|
[str rangeOfString:m_substr].location == 0;
|
||||||
}
|
}
|
||||||
@@ -164,7 +164,7 @@ namespace Catch {
|
|||||||
struct EndsWith : StringHolder {
|
struct EndsWith : StringHolder {
|
||||||
EndsWith( NSString* substr ) : StringHolder( substr ){}
|
EndsWith( NSString* substr ) : StringHolder( substr ){}
|
||||||
|
|
||||||
bool match( NSString* const& str ) const override {
|
bool match( NSString* str ) const override {
|
||||||
return (str != nil || m_substr == nil ) &&
|
return (str != nil || m_substr == nil ) &&
|
||||||
[str rangeOfString:m_substr].location == [str length] - [m_substr length];
|
[str rangeOfString:m_substr].location == [str length] - [m_substr length];
|
||||||
}
|
}
|
||||||
|
@@ -102,35 +102,49 @@
|
|||||||
template<typename...> struct TypeList {};\
|
template<typename...> struct TypeList {};\
|
||||||
template<typename...Ts>\
|
template<typename...Ts>\
|
||||||
constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\
|
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> \
|
template<typename T> \
|
||||||
constexpr auto append(L1<E1...>, L2<E2...>) noexcept -> L1<E1...,E2...> { return {}; }\
|
struct append<T> { using type = T; };\
|
||||||
template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
|
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>\
|
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>\
|
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>\
|
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>\
|
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>\
|
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, ...)\
|
#define INTERNAL_CATCH_NTTP_1(signature, ...)\
|
||||||
template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
|
template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
|
||||||
template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
|
template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
|
||||||
constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
|
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)>\
|
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>\
|
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>\
|
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_TEST0(TestName)
|
||||||
#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
|
#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
|
||||||
|
@@ -7,23 +7,67 @@
|
|||||||
|
|
||||||
#include "catch_random_number_generator.h"
|
#include "catch_random_number_generator.h"
|
||||||
#include "catch_context.h"
|
#include "catch_context.h"
|
||||||
|
#include "catch_run_context.h"
|
||||||
#include "catch_interfaces_config.h"
|
#include "catch_interfaces_config.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
std::mt19937& rng() {
|
namespace {
|
||||||
static std::mt19937 s_rng;
|
|
||||||
return s_rng;
|
#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 ) {
|
void SimplePcg32::seed(result_type seed_) {
|
||||||
std::srand( config.rngSeed() );
|
m_state = 0;
|
||||||
rng().seed( config.rngSeed() );
|
(*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() {
|
SimplePcg32::result_type SimplePcg32::operator()() {
|
||||||
return getCurrentContext().getConfig()->rngSeed();
|
// 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
|
#ifndef TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
||||||
|
|
||||||
#include <algorithm>
|
#include <cstdint>
|
||||||
#include <random>
|
|
||||||
|
|
||||||
namespace Catch {
|
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();
|
// Provide some default initial state for the default constructor
|
||||||
void seedRng( IConfig const& config );
|
SimplePcg32():SimplePcg32(0xed743cc4U) {}
|
||||||
unsigned int rngSeed();
|
|
||||||
|
|
||||||
}
|
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
|
#endif // TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
||||||
|
@@ -230,7 +230,7 @@ namespace Catch {
|
|||||||
|
|
||||||
m_unfinishedSections.push_back(endInfo);
|
m_unfinishedSections.push_back(endInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||||
void RunContext::benchmarkPreparing(std::string const& name) {
|
void RunContext::benchmarkPreparing(std::string const& name) {
|
||||||
m_reporter->benchmarkPreparing(name);
|
m_reporter->benchmarkPreparing(name);
|
||||||
@@ -279,7 +279,7 @@ namespace Catch {
|
|||||||
// Don't rebuild the result -- the stringification itself can cause more fatal errors
|
// Don't rebuild the result -- the stringification itself can cause more fatal errors
|
||||||
// Instead, fake a result data.
|
// Instead, fake a result data.
|
||||||
AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
|
AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
|
||||||
tempResult.message = message;
|
tempResult.message = static_cast<std::string>(message);
|
||||||
AssertionResult result(m_lastAssertionInfo, tempResult);
|
AssertionResult result(m_lastAssertionInfo, tempResult);
|
||||||
|
|
||||||
assertionEnded(result);
|
assertionEnded(result);
|
||||||
@@ -442,7 +442,7 @@ namespace Catch {
|
|||||||
m_lastAssertionInfo = info;
|
m_lastAssertionInfo = info;
|
||||||
|
|
||||||
AssertionResultData data( resultType, LazyExpression( false ) );
|
AssertionResultData data( resultType, LazyExpression( false ) );
|
||||||
data.message = message;
|
data.message = static_cast<std::string>(message);
|
||||||
AssertionResult assertionResult{ m_lastAssertionInfo, data };
|
AssertionResult assertionResult{ m_lastAssertionInfo, data };
|
||||||
assertionEnded( assertionResult );
|
assertionEnded( assertionResult );
|
||||||
if( !assertionResult.isOk() )
|
if( !assertionResult.isOk() )
|
||||||
@@ -506,4 +506,16 @@ namespace Catch {
|
|||||||
else
|
else
|
||||||
CATCH_INTERNAL_ERROR("No result capture instance");
|
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;
|
bool m_includeSuccessfulResults;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void seedRng(IConfig const& config);
|
||||||
|
unsigned int rngSeed();
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
|
||||||
|
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <set>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -58,46 +60,61 @@ namespace Catch {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TestGroup {
|
||||||
Catch::Totals runTests(std::shared_ptr<Config> const& config) {
|
public:
|
||||||
auto reporter = makeReporter(config);
|
explicit TestGroup(std::shared_ptr<Config> const& config)
|
||||||
|
: m_config{config}
|
||||||
RunContext context(config, std::move(reporter));
|
, m_context{config, makeReporter(config)}
|
||||||
|
{
|
||||||
Totals totals;
|
auto const& allTestCases = getAllTestCasesSorted(*m_config);
|
||||||
|
m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
|
||||||
context.testGroupStarting(config->name(), 1, 1);
|
auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
|
||||||
|
|
||||||
TestSpec testSpec = config->testSpec();
|
if (m_matches.empty() && invalidArgs.empty()) {
|
||||||
|
for (auto const& test : allTestCases)
|
||||||
auto const& allTestCases = getAllTestCasesSorted(*config);
|
if (!test.isHidden())
|
||||||
for (auto const& testCase : allTestCases) {
|
m_tests.emplace(&test);
|
||||||
bool matching = (!testSpec.hasFilters() && !testCase.isHidden()) ||
|
} else {
|
||||||
(testSpec.hasFilters() && matchTest(testCase, testSpec, *config));
|
for (auto const& match : m_matches)
|
||||||
|
m_tests.insert(match.tests.begin(), match.tests.end());
|
||||||
if (!context.aborting() && matching)
|
}
|
||||||
totals += context.runTest(testCase);
|
|
||||||
else
|
|
||||||
context.reporter().skipTest(testCase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
|
Totals execute() {
|
||||||
ReusableStringStream testConfig;
|
auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
|
||||||
|
Totals totals;
|
||||||
bool first = true;
|
m_context.testGroupStarting(m_config->name(), 1, 1);
|
||||||
for (const auto& input : config->getTestsOrTags()) {
|
for (auto const& testCase : m_tests) {
|
||||||
if (!first) { testConfig << ' '; }
|
if (!m_context.aborting())
|
||||||
first = false;
|
totals += m_context.runTest(*testCase);
|
||||||
testConfig << input;
|
else
|
||||||
|
m_context.reporter().skipTest(*testCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.reporter().noMatchingTestCases(testConfig.str());
|
for (auto const& match : m_matches) {
|
||||||
totals.error = -1;
|
if (match.tests.empty()) {
|
||||||
|
m_context.reporter().noMatchingTestCases(match.name);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.testGroupEnded(config->name(), totals, 1, 1);
|
private:
|
||||||
return totals;
|
using Tests = std::set<TestCase const*>;
|
||||||
}
|
|
||||||
|
std::shared_ptr<Config> m_config;
|
||||||
|
RunContext m_context;
|
||||||
|
Tests m_tests;
|
||||||
|
TestSpec::Matches m_matches;
|
||||||
|
};
|
||||||
|
|
||||||
void applyFilenamesAsTags(Catch::IConfig const& config) {
|
void applyFilenamesAsTags(Catch::IConfig const& config) {
|
||||||
auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
|
auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
|
||||||
@@ -166,7 +183,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
void Session::libIdentify() {
|
void Session::libIdentify() {
|
||||||
Catch::cout()
|
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) << "category: " << "testframework\n"
|
||||||
<< std::left << std::setw(16) << "framework: " << "Catch Test\n"
|
<< std::left << std::setw(16) << "framework: " << "Catch Test\n"
|
||||||
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
|
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
|
||||||
@@ -274,7 +291,12 @@ namespace Catch {
|
|||||||
if( Option<std::size_t> listed = list( m_config ) )
|
if( Option<std::size_t> listed = list( m_config ) )
|
||||||
return static_cast<int>( *listed );
|
return static_cast<int>( *listed );
|
||||||
|
|
||||||
auto totals = runTests( m_config );
|
TestGroup tests { m_config };
|
||||||
|
auto const totals = tests.execute();
|
||||||
|
|
||||||
|
if( m_config->warnAboutNoTests() && totals.error == -1 )
|
||||||
|
return 2;
|
||||||
|
|
||||||
// Note that on unices only the lower 8 bits are usually used, clamping
|
// Note that on unices only the lower 8 bits are usually used, clamping
|
||||||
// the return value to 255 prevents false negative when some multiple
|
// the return value to 255 prevents false negative when some multiple
|
||||||
// of 256 tests has failed
|
// of 256 tests has failed
|
||||||
|
@@ -53,6 +53,18 @@ namespace Catch {
|
|||||||
return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
|
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 replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
|
||||||
bool replaced = false;
|
bool replaced = false;
|
||||||
std::size_t i = str.find( replaceThis );
|
std::size_t i = str.find( replaceThis );
|
||||||
|
@@ -22,7 +22,10 @@ namespace Catch {
|
|||||||
bool contains( std::string const& s, std::string const& infix );
|
bool contains( std::string const& s, std::string const& infix );
|
||||||
void toLowerInPlace( std::string& s );
|
void toLowerInPlace( std::string& s );
|
||||||
std::string toLower( std::string const& 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 );
|
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
|
// !!! Be aware, returns refs into original string - make sure original string outlives them
|
||||||
std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
|
std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
|
||||||
|
@@ -17,21 +17,11 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdint>
|
#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 {
|
namespace Catch {
|
||||||
StringRef::StringRef( char const* rawChars ) noexcept
|
StringRef::StringRef( char const* rawChars ) noexcept
|
||||||
: StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )
|
: 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 {
|
void StringRef::swap( StringRef& other ) noexcept {
|
||||||
std::swap( m_start, other.m_start );
|
std::swap( m_start, other.m_start );
|
||||||
std::swap( m_size, other.m_size );
|
std::swap( m_size, other.m_size );
|
||||||
@@ -78,40 +68,6 @@ namespace Catch {
|
|||||||
return !operator==( other );
|
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& {
|
auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
|
||||||
return os.write(str.currentData(), str.size());
|
return os.write(str.currentData(), str.size());
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -23,6 +24,7 @@ namespace Catch {
|
|||||||
class StringRef {
|
class StringRef {
|
||||||
public:
|
public:
|
||||||
using size_type = std::size_t;
|
using size_type = std::size_t;
|
||||||
|
using const_iterator = const char*;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct StringRefTestAccess;
|
friend struct StringRefTestAccess;
|
||||||
@@ -78,7 +80,9 @@ namespace Catch {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator std::string() const;
|
explicit operator std::string() const {
|
||||||
|
return std::string(m_start, m_size);
|
||||||
|
}
|
||||||
|
|
||||||
void swap( StringRef& other ) noexcept;
|
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 != ( 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
|
public: // named queries
|
||||||
auto empty() const noexcept -> bool {
|
auto empty() const noexcept -> bool {
|
||||||
@@ -96,7 +103,6 @@ namespace Catch {
|
|||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto numberOfCharacters() const noexcept -> size_type;
|
|
||||||
auto c_str() const -> char const*;
|
auto c_str() const -> char const*;
|
||||||
|
|
||||||
public: // substrings and searches
|
public: // substrings and searches
|
||||||
@@ -106,15 +112,15 @@ namespace Catch {
|
|||||||
// Note that the pointer can change when if the StringRef is a substring
|
// Note that the pointer can change when if the StringRef is a substring
|
||||||
auto currentData() const noexcept -> char const*;
|
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
|
private: // ownership queries - may not be consistent between calls
|
||||||
auto isOwned() const noexcept -> bool;
|
auto isOwned() const noexcept -> bool;
|
||||||
auto isSubstring() 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::string& lhs, StringRef const& sr ) -> std::string&;
|
||||||
auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
|
auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
|
||||||
|
|
||||||
|
@@ -59,8 +59,7 @@ namespace Catch {
|
|||||||
std::vector<std::string> tags;
|
std::vector<std::string> tags;
|
||||||
std::string desc, tag;
|
std::string desc, tag;
|
||||||
bool inTag = false;
|
bool inTag = false;
|
||||||
std::string _descOrTags = nameAndTags.tags;
|
for (char c : nameAndTags.tags) {
|
||||||
for (char c : _descOrTags) {
|
|
||||||
if( !inTag ) {
|
if( !inTag ) {
|
||||||
if( c == '[' )
|
if( c == '[' )
|
||||||
inTag = true;
|
inTag = true;
|
||||||
@@ -93,7 +92,7 @@ namespace Catch {
|
|||||||
tags.push_back( "." );
|
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) );
|
return TestCase( _testCase, std::move(info) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
#include "catch_interfaces_registry_hub.h"
|
#include "catch_interfaces_registry_hub.h"
|
||||||
#include "catch_random_number_generator.h"
|
#include "catch_random_number_generator.h"
|
||||||
|
#include "catch_run_context.h"
|
||||||
#include "catch_string_manip.h"
|
#include "catch_string_manip.h"
|
||||||
#include "catch_test_case_info.h"
|
#include "catch_test_case_info.h"
|
||||||
|
|
||||||
@@ -36,8 +37,13 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
return sorted;
|
return sorted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isThrowSafe( TestCase const& testCase, IConfig const& config ) {
|
||||||
|
return !testCase.throws() || config.allowThrows();
|
||||||
|
}
|
||||||
|
|
||||||
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
|
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
|
||||||
return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
|
return testSpec.matches( testCase ) && isThrowSafe( testCase, config );
|
||||||
}
|
}
|
||||||
|
|
||||||
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
|
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
|
||||||
@@ -100,7 +106,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
|
std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
|
||||||
std::string className = classOrQualifiedMethodName;
|
std::string className(classOrQualifiedMethodName);
|
||||||
if( startsWith( className, '&' ) )
|
if( startsWith( className, '&' ) )
|
||||||
{
|
{
|
||||||
std::size_t lastColons = className.rfind( "::" );
|
std::size_t lastColons = className.rfind( "::" );
|
||||||
|
@@ -23,6 +23,8 @@ namespace Catch {
|
|||||||
struct IConfig;
|
struct IConfig;
|
||||||
|
|
||||||
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
|
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
|
||||||
|
|
||||||
|
bool isThrowSafe( TestCase const& testCase, IConfig const& config );
|
||||||
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
|
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
|
||||||
|
|
||||||
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
|
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#include "catch_test_case_tracker.h"
|
#include "catch_test_case_tracker.h"
|
||||||
|
|
||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
|
#include "catch_string_manip.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -174,7 +175,8 @@ namespace TestCaseTracking {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
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 ) {
|
if( parent ) {
|
||||||
while( !parent->isSectionTracker() )
|
while( !parent->isSectionTracker() )
|
||||||
@@ -188,12 +190,11 @@ namespace TestCaseTracking {
|
|||||||
bool SectionTracker::isComplete() const {
|
bool SectionTracker::isComplete() const {
|
||||||
bool complete = true;
|
bool complete = true;
|
||||||
|
|
||||||
if ((m_filters.empty() || m_filters[0] == "") ||
|
if ((m_filters.empty() || m_filters[0] == "")
|
||||||
std::find(m_filters.begin(), m_filters.end(),
|
|| std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
|
||||||
m_nameAndLocation.name) != m_filters.end())
|
|
||||||
complete = TrackerBase::isComplete();
|
complete = TrackerBase::isComplete();
|
||||||
|
}
|
||||||
return complete;
|
return complete;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SectionTracker::isSectionTracker() const { return true; }
|
bool SectionTracker::isSectionTracker() const { return true; }
|
||||||
@@ -217,12 +218,13 @@ namespace TestCaseTracking {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SectionTracker::tryOpen() {
|
void SectionTracker::tryOpen() {
|
||||||
if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
|
if( !isComplete() )
|
||||||
open();
|
open();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
|
void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
|
||||||
if( !filters.empty() ) {
|
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(""); // Root - should never be consulted
|
||||||
m_filters.push_back(""); // Test Case - not a section filter
|
m_filters.push_back(""); // Test Case - not a section filter
|
||||||
m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
|
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 ) {
|
void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) {
|
||||||
if( filters.size() > 1 )
|
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
|
} // namespace TestCaseTracking
|
||||||
|
@@ -133,6 +133,7 @@ namespace TestCaseTracking {
|
|||||||
|
|
||||||
class SectionTracker : public TrackerBase {
|
class SectionTracker : public TrackerBase {
|
||||||
std::vector<std::string> m_filters;
|
std::vector<std::string> m_filters;
|
||||||
|
std::string m_trimmed_name;
|
||||||
public:
|
public:
|
||||||
SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
|
SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
|
||||||
|
|
||||||
|
@@ -12,7 +12,6 @@
|
|||||||
#include "catch_interfaces_testcase.h"
|
#include "catch_interfaces_testcase.h"
|
||||||
#include "catch_compiler_capabilities.h"
|
#include "catch_compiler_capabilities.h"
|
||||||
#include "catch_stringref.h"
|
#include "catch_stringref.h"
|
||||||
#include "catch_type_traits.hpp"
|
|
||||||
#include "catch_preprocessor.hpp"
|
#include "catch_preprocessor.hpp"
|
||||||
#include "catch_meta.hpp"
|
#include "catch_meta.hpp"
|
||||||
|
|
||||||
@@ -143,6 +142,7 @@ struct AutoReg : NonCopyable {
|
|||||||
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
|
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
|
INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
|
||||||
namespace {\
|
namespace {\
|
||||||
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
|
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
|
||||||
@@ -166,6 +166,7 @@ struct AutoReg : NonCopyable {
|
|||||||
}\
|
}\
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
|
INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
|
||||||
|
|
||||||
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
#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) \
|
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
template<typename TestType> static void TestFuncName(); \
|
template<typename TestType> static void TestFuncName(); \
|
||||||
namespace {\
|
namespace {\
|
||||||
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
|
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
|
||||||
@@ -204,7 +206,7 @@ struct AutoReg : NonCopyable {
|
|||||||
} \
|
} \
|
||||||
}; \
|
}; \
|
||||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
|
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; \
|
TestInit t; \
|
||||||
t.reg_tests(); \
|
t.reg_tests(); \
|
||||||
return 0; \
|
return 0; \
|
||||||
@@ -213,6 +215,7 @@ struct AutoReg : NonCopyable {
|
|||||||
} \
|
} \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
template<typename TestType> \
|
template<typename TestType> \
|
||||||
static void TestFuncName()
|
static void TestFuncName()
|
||||||
|
|
||||||
@@ -234,6 +237,7 @@ struct AutoReg : NonCopyable {
|
|||||||
|
|
||||||
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
|
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
template<typename TestType> static void TestFunc(); \
|
template<typename TestType> static void TestFunc(); \
|
||||||
namespace {\
|
namespace {\
|
||||||
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
|
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
|
||||||
@@ -247,13 +251,14 @@ struct AutoReg : NonCopyable {
|
|||||||
} \
|
} \
|
||||||
};\
|
};\
|
||||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
|
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
|
||||||
using TestInit = decltype(convert<TestName>(TmplList {})); \
|
using TestInit = typename convert<TestName, TmplList>::type; \
|
||||||
TestInit t; \
|
TestInit t; \
|
||||||
t.reg_tests(); \
|
t.reg_tests(); \
|
||||||
return 0; \
|
return 0; \
|
||||||
}(); \
|
}(); \
|
||||||
}}\
|
}}\
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
template<typename TestType> \
|
template<typename TestType> \
|
||||||
static void TestFunc()
|
static void TestFunc()
|
||||||
|
|
||||||
@@ -264,6 +269,7 @@ struct AutoReg : NonCopyable {
|
|||||||
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
|
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
namespace {\
|
namespace {\
|
||||||
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
|
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
|
||||||
INTERNAL_CATCH_TYPE_GEN\
|
INTERNAL_CATCH_TYPE_GEN\
|
||||||
@@ -287,6 +293,7 @@ struct AutoReg : NonCopyable {
|
|||||||
}\
|
}\
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_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))
|
INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
|
||||||
|
|
||||||
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
|
#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)\
|
#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_GLOBALS_WARNINGS \
|
||||||
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
template<typename TestType> \
|
template<typename TestType> \
|
||||||
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
|
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
|
||||||
void test();\
|
void test();\
|
||||||
@@ -328,7 +336,7 @@ struct AutoReg : NonCopyable {
|
|||||||
}\
|
}\
|
||||||
};\
|
};\
|
||||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
|
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;\
|
TestInit t;\
|
||||||
t.reg_tests();\
|
t.reg_tests();\
|
||||||
return 0;\
|
return 0;\
|
||||||
@@ -337,6 +345,7 @@ struct AutoReg : NonCopyable {
|
|||||||
}\
|
}\
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
template<typename TestType> \
|
template<typename TestType> \
|
||||||
void TestName<TestType>::test()
|
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) \
|
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
template<typename TestType> \
|
template<typename TestType> \
|
||||||
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
|
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
|
||||||
void test();\
|
void test();\
|
||||||
@@ -374,13 +384,14 @@ struct AutoReg : NonCopyable {
|
|||||||
}\
|
}\
|
||||||
};\
|
};\
|
||||||
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
|
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
|
||||||
using TestInit = decltype(convert<TestNameClass>(TmplList {}));\
|
using TestInit = typename convert<TestNameClass, TmplList>::type;\
|
||||||
TestInit t;\
|
TestInit t;\
|
||||||
t.reg_tests();\
|
t.reg_tests();\
|
||||||
return 0;\
|
return 0;\
|
||||||
}(); \
|
}(); \
|
||||||
}}\
|
}}\
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
|
||||||
template<typename TestType> \
|
template<typename TestType> \
|
||||||
void TestName<TestType>::test()
|
void TestName<TestType>::test()
|
||||||
|
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "catch_test_spec.h"
|
#include "catch_test_spec.h"
|
||||||
#include "catch_string_manip.h"
|
#include "catch_string_manip.h"
|
||||||
|
#include "catch_interfaces_config.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -15,45 +16,84 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
TestSpec::Pattern::~Pattern() = default;
|
TestSpec::Pattern::Pattern( std::string const& name )
|
||||||
TestSpec::NamePattern::~NamePattern() = default;
|
: m_name( name )
|
||||||
TestSpec::TagPattern::~TagPattern() = default;
|
|
||||||
TestSpec::ExcludedPattern::~ExcludedPattern() = default;
|
|
||||||
|
|
||||||
TestSpec::NamePattern::NamePattern( std::string const& name )
|
|
||||||
: m_wildcardPattern( toLower( name ), CaseSensitive::No )
|
|
||||||
{}
|
{}
|
||||||
bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
|
|
||||||
return m_wildcardPattern.matches( toLower( testCase.name ) );
|
TestSpec::Pattern::~Pattern() = default;
|
||||||
|
|
||||||
|
std::string const& TestSpec::Pattern::name() const {
|
||||||
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
|
|
||||||
|
TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString )
|
||||||
|
: Pattern( filterString )
|
||||||
|
, m_wildcardPattern( toLower( name ), CaseSensitive::No )
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
|
||||||
|
return m_wildcardPattern.matches( testCase.name );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString )
|
||||||
|
: Pattern( filterString )
|
||||||
|
, m_tag( toLower( tag ) )
|
||||||
|
{}
|
||||||
|
|
||||||
bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
|
bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
|
||||||
return std::find(begin(testCase.lcaseTags),
|
return std::find(begin(testCase.lcaseTags),
|
||||||
end(testCase.lcaseTags),
|
end(testCase.lcaseTags),
|
||||||
m_tag) != end(testCase.lcaseTags);
|
m_tag) != end(testCase.lcaseTags);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
|
|
||||||
bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
|
TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern )
|
||||||
|
: Pattern( underlyingPattern->name() )
|
||||||
|
, m_underlyingPattern( underlyingPattern )
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const {
|
||||||
|
return !m_underlyingPattern->matches( testCase );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
|
bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
|
||||||
// All patterns in a filter must match for the filter to be a match
|
return std::all_of( m_patterns.begin(), m_patterns.end(), [&]( PatternPtr const& p ){ return p->matches( testCase ); } );
|
||||||
for( auto const& pattern : m_patterns ) {
|
|
||||||
if( !pattern->matches( testCase ) )
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string TestSpec::Filter::name() const {
|
||||||
|
std::string name;
|
||||||
|
for( auto const& p : m_patterns )
|
||||||
|
name += p->name();
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TestSpec::hasFilters() const {
|
bool TestSpec::hasFilters() const {
|
||||||
return !m_filters.empty();
|
return !m_filters.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestSpec::matches( TestCaseInfo const& testCase ) const {
|
bool TestSpec::matches( TestCaseInfo const& testCase ) const {
|
||||||
// A TestSpec matches if any filter matches
|
return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } );
|
||||||
for( auto const& filter : m_filters )
|
|
||||||
if( filter.matches( testCase ) )
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const
|
||||||
|
{
|
||||||
|
Matches matches( m_filters.size() );
|
||||||
|
std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){
|
||||||
|
std::vector<TestCase const*> currentMatches;
|
||||||
|
for( auto const& test : testCases )
|
||||||
|
if( isThrowSafe( test, config ) && filter.matches( test ) )
|
||||||
|
currentMatches.emplace_back( &test );
|
||||||
|
return FilterMatch{ filter.name(), currentMatches };
|
||||||
|
} );
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{
|
||||||
|
return (m_invalidArgs);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -22,17 +22,23 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
struct IConfig;
|
||||||
|
|
||||||
class TestSpec {
|
class TestSpec {
|
||||||
struct Pattern {
|
class Pattern {
|
||||||
|
public:
|
||||||
|
explicit Pattern( std::string const& name );
|
||||||
virtual ~Pattern();
|
virtual ~Pattern();
|
||||||
virtual bool matches( TestCaseInfo const& testCase ) const = 0;
|
virtual bool matches( TestCaseInfo const& testCase ) const = 0;
|
||||||
|
std::string const& name() const;
|
||||||
|
private:
|
||||||
|
std::string const m_name;
|
||||||
};
|
};
|
||||||
using PatternPtr = std::shared_ptr<Pattern>;
|
using PatternPtr = std::shared_ptr<Pattern>;
|
||||||
|
|
||||||
class NamePattern : public Pattern {
|
class NamePattern : public Pattern {
|
||||||
public:
|
public:
|
||||||
NamePattern( std::string const& name );
|
explicit NamePattern( std::string const& name, std::string const& filterString );
|
||||||
virtual ~NamePattern();
|
|
||||||
bool matches( TestCaseInfo const& testCase ) const override;
|
bool matches( TestCaseInfo const& testCase ) const override;
|
||||||
private:
|
private:
|
||||||
WildcardPattern m_wildcardPattern;
|
WildcardPattern m_wildcardPattern;
|
||||||
@@ -40,8 +46,7 @@ namespace Catch {
|
|||||||
|
|
||||||
class TagPattern : public Pattern {
|
class TagPattern : public Pattern {
|
||||||
public:
|
public:
|
||||||
TagPattern( std::string const& tag );
|
explicit TagPattern( std::string const& tag, std::string const& filterString );
|
||||||
virtual ~TagPattern();
|
|
||||||
bool matches( TestCaseInfo const& testCase ) const override;
|
bool matches( TestCaseInfo const& testCase ) const override;
|
||||||
private:
|
private:
|
||||||
std::string m_tag;
|
std::string m_tag;
|
||||||
@@ -49,8 +54,7 @@ namespace Catch {
|
|||||||
|
|
||||||
class ExcludedPattern : public Pattern {
|
class ExcludedPattern : public Pattern {
|
||||||
public:
|
public:
|
||||||
ExcludedPattern( PatternPtr const& underlyingPattern );
|
explicit ExcludedPattern( PatternPtr const& underlyingPattern );
|
||||||
virtual ~ExcludedPattern();
|
|
||||||
bool matches( TestCaseInfo const& testCase ) const override;
|
bool matches( TestCaseInfo const& testCase ) const override;
|
||||||
private:
|
private:
|
||||||
PatternPtr m_underlyingPattern;
|
PatternPtr m_underlyingPattern;
|
||||||
@@ -60,15 +64,25 @@ namespace Catch {
|
|||||||
std::vector<PatternPtr> m_patterns;
|
std::vector<PatternPtr> m_patterns;
|
||||||
|
|
||||||
bool matches( TestCaseInfo const& testCase ) const;
|
bool matches( TestCaseInfo const& testCase ) const;
|
||||||
|
std::string name() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct FilterMatch {
|
||||||
|
std::string name;
|
||||||
|
std::vector<TestCase const*> tests;
|
||||||
|
};
|
||||||
|
using Matches = std::vector<FilterMatch>;
|
||||||
|
using vectorStrings = std::vector<std::string>;
|
||||||
|
|
||||||
bool hasFilters() const;
|
bool hasFilters() const;
|
||||||
bool matches( TestCaseInfo const& testCase ) const;
|
bool matches( TestCaseInfo const& testCase ) const;
|
||||||
|
Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const;
|
||||||
|
const vectorStrings & getInvalidArgs() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Filter> m_filters;
|
std::vector<Filter> m_filters;
|
||||||
|
std::vector<std::string> m_invalidArgs;
|
||||||
friend class TestSpecParser;
|
friend class TestSpecParser;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "catch_test_spec_parser.h"
|
#include "catch_test_spec_parser.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
|
TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
|
||||||
@@ -14,64 +15,136 @@ namespace Catch {
|
|||||||
TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
|
TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
|
||||||
m_mode = None;
|
m_mode = None;
|
||||||
m_exclusion = false;
|
m_exclusion = false;
|
||||||
m_start = std::string::npos;
|
|
||||||
m_arg = m_tagAliases->expandAliases( arg );
|
m_arg = m_tagAliases->expandAliases( arg );
|
||||||
m_escapeChars.clear();
|
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 )
|
for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
|
||||||
visitChar( m_arg[m_pos] );
|
//if visitChar fails
|
||||||
if( m_mode == Name )
|
if( !visitChar( m_arg[m_pos] ) ){
|
||||||
addPattern<TestSpec::NamePattern>();
|
m_testSpec.m_invalidArgs.push_back(arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
endMode();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
TestSpec TestSpecParser::testSpec() {
|
TestSpec TestSpecParser::testSpec() {
|
||||||
addFilter();
|
addFilter();
|
||||||
return m_testSpec;
|
return m_testSpec;
|
||||||
}
|
}
|
||||||
|
bool TestSpecParser::visitChar( char c ) {
|
||||||
|
if( (m_mode != EscapedName) && (c == '\\') ) {
|
||||||
|
escape();
|
||||||
|
addCharToPattern(c);
|
||||||
|
return true;
|
||||||
|
}else if((m_mode != EscapedName) && (c == ',') ) {
|
||||||
|
return separate();
|
||||||
|
}
|
||||||
|
|
||||||
void TestSpecParser::visitChar( char c ) {
|
switch( m_mode ) {
|
||||||
if( m_mode == None ) {
|
case None:
|
||||||
switch( c ) {
|
if( processNoneChar( c ) )
|
||||||
case ' ': return;
|
return true;
|
||||||
case '~': m_exclusion = true; return;
|
break;
|
||||||
case '[': return startNewMode( Tag, ++m_pos );
|
case Name:
|
||||||
case '"': return startNewMode( QuotedName, ++m_pos );
|
processNameChar( c );
|
||||||
case '\\': return escape();
|
break;
|
||||||
default: startNewMode( Name, m_pos ); break;
|
case EscapedName:
|
||||||
}
|
endMode();
|
||||||
|
addCharToPattern(c);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
case Tag:
|
||||||
|
case QuotedName:
|
||||||
|
if( processOtherChar( c ) )
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if( m_mode == Name ) {
|
|
||||||
if( c == ',' ) {
|
m_substring += c;
|
||||||
addPattern<TestSpec::NamePattern>();
|
if( !isControlChar( c ) ) {
|
||||||
addFilter();
|
m_patternName += c;
|
||||||
}
|
m_realPatternPos++;
|
||||||
else if( c == '[' ) {
|
|
||||||
if( subString() == "exclude:" )
|
|
||||||
m_exclusion = true;
|
|
||||||
else
|
|
||||||
addPattern<TestSpec::NamePattern>();
|
|
||||||
startNewMode( Tag, ++m_pos );
|
|
||||||
}
|
|
||||||
else if( c == '\\' )
|
|
||||||
escape();
|
|
||||||
}
|
}
|
||||||
else if( m_mode == EscapedName )
|
return true;
|
||||||
m_mode = Name;
|
|
||||||
else if( m_mode == QuotedName && c == '"' )
|
|
||||||
addPattern<TestSpec::NamePattern>();
|
|
||||||
else if( m_mode == Tag && c == ']' )
|
|
||||||
addPattern<TestSpec::TagPattern>();
|
|
||||||
}
|
}
|
||||||
void TestSpecParser::startNewMode( Mode mode, std::size_t start ) {
|
// Two of the processing methods return true to signal the caller to return
|
||||||
|
// without adding the given character to the current pattern strings
|
||||||
|
bool TestSpecParser::processNoneChar( char c ) {
|
||||||
|
switch( c ) {
|
||||||
|
case ' ':
|
||||||
|
return true;
|
||||||
|
case '~':
|
||||||
|
m_exclusion = true;
|
||||||
|
return false;
|
||||||
|
case '[':
|
||||||
|
startNewMode( Tag );
|
||||||
|
return false;
|
||||||
|
case '"':
|
||||||
|
startNewMode( QuotedName );
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
startNewMode( Name );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void TestSpecParser::processNameChar( char c ) {
|
||||||
|
if( c == '[' ) {
|
||||||
|
if( m_substring == "exclude:" )
|
||||||
|
m_exclusion = true;
|
||||||
|
else
|
||||||
|
endMode();
|
||||||
|
startNewMode( Tag );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool TestSpecParser::processOtherChar( char c ) {
|
||||||
|
if( !isControlChar( c ) )
|
||||||
|
return false;
|
||||||
|
m_substring += c;
|
||||||
|
endMode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void TestSpecParser::startNewMode( Mode mode ) {
|
||||||
m_mode = mode;
|
m_mode = mode;
|
||||||
m_start = start;
|
}
|
||||||
|
void TestSpecParser::endMode() {
|
||||||
|
switch( m_mode ) {
|
||||||
|
case Name:
|
||||||
|
case QuotedName:
|
||||||
|
return addPattern<TestSpec::NamePattern>();
|
||||||
|
case Tag:
|
||||||
|
return addPattern<TestSpec::TagPattern>();
|
||||||
|
case EscapedName:
|
||||||
|
revertBackToLastMode();
|
||||||
|
return;
|
||||||
|
case None:
|
||||||
|
default:
|
||||||
|
return startNewMode( None );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void TestSpecParser::escape() {
|
void TestSpecParser::escape() {
|
||||||
if( m_mode == None )
|
saveLastMode();
|
||||||
m_start = m_pos;
|
|
||||||
m_mode = EscapedName;
|
m_mode = EscapedName;
|
||||||
m_escapeChars.push_back( m_pos );
|
m_escapeChars.push_back(m_realPatternPos);
|
||||||
|
}
|
||||||
|
bool TestSpecParser::isControlChar( char c ) const {
|
||||||
|
switch( m_mode ) {
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
case None:
|
||||||
|
return c == '~';
|
||||||
|
case Name:
|
||||||
|
return c == '[';
|
||||||
|
case EscapedName:
|
||||||
|
return true;
|
||||||
|
case QuotedName:
|
||||||
|
return c == '"';
|
||||||
|
case Tag:
|
||||||
|
return c == '[' || c == ']';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
|
|
||||||
|
|
||||||
void TestSpecParser::addFilter() {
|
void TestSpecParser::addFilter() {
|
||||||
if( !m_currentFilter.m_patterns.empty() ) {
|
if( !m_currentFilter.m_patterns.empty() ) {
|
||||||
@@ -80,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 ) {
|
TestSpec parseTestSpec( std::string const& arg ) {
|
||||||
return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
|
return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
|
||||||
}
|
}
|
||||||
|
@@ -22,9 +22,13 @@ namespace Catch {
|
|||||||
class TestSpecParser {
|
class TestSpecParser {
|
||||||
enum Mode{ None, Name, QuotedName, Tag, EscapedName };
|
enum Mode{ None, Name, QuotedName, Tag, EscapedName };
|
||||||
Mode m_mode = None;
|
Mode m_mode = None;
|
||||||
|
Mode lastMode = None;
|
||||||
bool m_exclusion = false;
|
bool m_exclusion = false;
|
||||||
std::size_t m_start = std::string::npos, m_pos = 0;
|
std::size_t m_pos = 0;
|
||||||
|
std::size_t m_realPatternPos = 0;
|
||||||
std::string m_arg;
|
std::string m_arg;
|
||||||
|
std::string m_substring;
|
||||||
|
std::string m_patternName;
|
||||||
std::vector<std::size_t> m_escapeChars;
|
std::vector<std::size_t> m_escapeChars;
|
||||||
TestSpec::Filter m_currentFilter;
|
TestSpec::Filter m_currentFilter;
|
||||||
TestSpec m_testSpec;
|
TestSpec m_testSpec;
|
||||||
@@ -37,32 +41,47 @@ namespace Catch {
|
|||||||
TestSpec testSpec();
|
TestSpec testSpec();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void visitChar( char c );
|
bool visitChar( char c );
|
||||||
void startNewMode( Mode mode, std::size_t start );
|
void startNewMode( Mode mode );
|
||||||
|
bool processNoneChar( char c );
|
||||||
|
void processNameChar( char c );
|
||||||
|
bool processOtherChar( char c );
|
||||||
|
void endMode();
|
||||||
void escape();
|
void escape();
|
||||||
std::string subString() const;
|
bool isControlChar( char c ) const;
|
||||||
|
void saveLastMode();
|
||||||
|
void revertBackToLastMode();
|
||||||
|
void addFilter();
|
||||||
|
bool separate();
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void addPattern() {
|
void addPattern() {
|
||||||
std::string token = subString();
|
std::string token = m_patternName;
|
||||||
for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
|
for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
|
||||||
token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
|
token = token.substr( 0, m_escapeChars[i] - i ) + token.substr( m_escapeChars[i] -i +1 );
|
||||||
m_escapeChars.clear();
|
m_escapeChars.clear();
|
||||||
if( startsWith( token, "exclude:" ) ) {
|
if( startsWith( token, "exclude:" ) ) {
|
||||||
m_exclusion = true;
|
m_exclusion = true;
|
||||||
token = token.substr( 8 );
|
token = token.substr( 8 );
|
||||||
}
|
}
|
||||||
if( !token.empty() ) {
|
if( !token.empty() ) {
|
||||||
TestSpec::PatternPtr pattern = std::make_shared<T>( token );
|
TestSpec::PatternPtr pattern = std::make_shared<T>( token, m_substring );
|
||||||
if( m_exclusion )
|
if( m_exclusion )
|
||||||
pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
|
pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
|
||||||
m_currentFilter.m_patterns.push_back( pattern );
|
m_currentFilter.m_patterns.push_back( pattern );
|
||||||
}
|
}
|
||||||
|
m_substring.clear();
|
||||||
|
m_patternName.clear();
|
||||||
m_exclusion = false;
|
m_exclusion = false;
|
||||||
m_mode = None;
|
m_mode = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addFilter();
|
inline void addCharToPattern(char c) {
|
||||||
|
m_substring += c;
|
||||||
|
m_patternName += c;
|
||||||
|
m_realPatternPos++;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
TestSpec parseTestSpec( std::string const& arg );
|
TestSpec parseTestSpec( std::string const& arg );
|
||||||
|
|
||||||
@@ -72,4 +91,4 @@ namespace Catch {
|
|||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
#endif
|
#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>
|
template<typename T>
|
||||||
class IsStreamInsertable {
|
class IsStreamInsertable {
|
||||||
template<typename SS, typename TT>
|
template<typename Stream, typename U>
|
||||||
static auto test(int)
|
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>
|
template<typename, typename>
|
||||||
static auto test(...)->std::false_type;
|
static auto test(...)->std::false_type;
|
||||||
@@ -654,7 +654,7 @@ namespace Catch { \
|
|||||||
template<> struct StringMaker<enumName> { \
|
template<> struct StringMaker<enumName> { \
|
||||||
static std::string convert( enumName value ) { \
|
static std::string convert( enumName value ) { \
|
||||||
static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
|
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() {
|
Version const& libraryVersion() {
|
||||||
static Version version( 2, 9, 1, "", 0 );
|
static Version version( 2, 10, 1, "", 0 );
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,14 +9,12 @@
|
|||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
#include "catch_string_manip.h"
|
#include "catch_string_manip.h"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
WildcardPattern::WildcardPattern( std::string const& pattern,
|
WildcardPattern::WildcardPattern( std::string const& pattern,
|
||||||
CaseSensitive::Choice caseSensitivity )
|
CaseSensitive::Choice caseSensitivity )
|
||||||
: m_caseSensitivity( caseSensitivity ),
|
: m_caseSensitivity( caseSensitivity ),
|
||||||
m_pattern( adjustCase( pattern ) )
|
m_pattern( normaliseString( pattern ) )
|
||||||
{
|
{
|
||||||
if( startsWith( m_pattern, '*' ) ) {
|
if( startsWith( m_pattern, '*' ) ) {
|
||||||
m_pattern = m_pattern.substr( 1 );
|
m_pattern = m_pattern.substr( 1 );
|
||||||
@@ -31,19 +29,19 @@ namespace Catch {
|
|||||||
bool WildcardPattern::matches( std::string const& str ) const {
|
bool WildcardPattern::matches( std::string const& str ) const {
|
||||||
switch( m_wildcard ) {
|
switch( m_wildcard ) {
|
||||||
case NoWildcard:
|
case NoWildcard:
|
||||||
return m_pattern == adjustCase( str );
|
return m_pattern == normaliseString( str );
|
||||||
case WildcardAtStart:
|
case WildcardAtStart:
|
||||||
return endsWith( adjustCase( str ), m_pattern );
|
return endsWith( normaliseString( str ), m_pattern );
|
||||||
case WildcardAtEnd:
|
case WildcardAtEnd:
|
||||||
return startsWith( adjustCase( str ), m_pattern );
|
return startsWith( normaliseString( str ), m_pattern );
|
||||||
case WildcardAtBothEnds:
|
case WildcardAtBothEnds:
|
||||||
return contains( adjustCase( str ), m_pattern );
|
return contains( normaliseString( str ), m_pattern );
|
||||||
default:
|
default:
|
||||||
CATCH_INTERNAL_ERROR( "Unknown enum" );
|
CATCH_INTERNAL_ERROR( "Unknown enum" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string WildcardPattern::adjustCase( std::string const& str ) const {
|
std::string WildcardPattern::normaliseString( std::string const& str ) const {
|
||||||
return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
|
return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,7 @@ namespace Catch
|
|||||||
virtual bool matches( std::string const& str ) const;
|
virtual bool matches( std::string const& str ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string adjustCase( std::string const& str ) const;
|
std::string normaliseString( std::string const& str ) const;
|
||||||
CaseSensitive::Choice m_caseSensitivity;
|
CaseSensitive::Choice m_caseSensitivity;
|
||||||
WildcardPosition m_wildcard = NoWildcard;
|
WildcardPosition m_wildcard = NoWildcard;
|
||||||
std::string m_pattern;
|
std::string m_pattern;
|
||||||
|
@@ -51,6 +51,8 @@ namespace Catch {
|
|||||||
|
|
||||||
void noMatchingTestCases(std::string const&) override {}
|
void noMatchingTestCases(std::string const&) override {}
|
||||||
|
|
||||||
|
void reportInvalidArguments(std::string const&) override {}
|
||||||
|
|
||||||
void testRunStarting(TestRunInfo const& _testRunInfo) override {
|
void testRunStarting(TestRunInfo const& _testRunInfo) override {
|
||||||
currentTestRunInfo = _testRunInfo;
|
currentTestRunInfo = _testRunInfo;
|
||||||
}
|
}
|
||||||
@@ -277,4 +279,4 @@ namespace Catch {
|
|||||||
|
|
||||||
} // end 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 "catch_reporter_compact.h"
|
||||||
|
|
||||||
#include "../internal/catch_reporter_registrars.hpp"
|
#include "../internal/catch_reporter_registrars.hpp"
|
||||||
#include "internal/catch_console_colour.h"
|
#include "../internal/catch_console_colour.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -209,24 +209,25 @@ private:
|
|||||||
if (itMessage == messages.end())
|
if (itMessage == messages.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// using messages.end() directly yields (or auto) compilation error:
|
const auto itEnd = messages.cend();
|
||||||
std::vector<MessageInfo>::const_iterator itEnd = messages.end();
|
const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
|
||||||
const std::size_t N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Colour colourGuard(colour);
|
Colour colourGuard(colour);
|
||||||
stream << " with " << pluralise(N, "message") << ':';
|
stream << " with " << pluralise(N, "message") << ':';
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; itMessage != itEnd; ) {
|
while (itMessage != itEnd) {
|
||||||
// If this assertion is a warning ignore any INFO messages
|
// If this assertion is a warning ignore any INFO messages
|
||||||
if (printInfoMessages || itMessage->type != ResultWas::Info) {
|
if (printInfoMessages || itMessage->type != ResultWas::Info) {
|
||||||
stream << " '" << itMessage->message << '\'';
|
printMessage();
|
||||||
if (++itMessage != itEnd) {
|
if (itMessage != itEnd) {
|
||||||
Colour colourGuard(dimColour());
|
Colour colourGuard(dimColour());
|
||||||
stream << " and";
|
stream << " and";
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
++itMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#include "catch_reporter_console.h"
|
#include "catch_reporter_console.h"
|
||||||
|
|
||||||
#include "../internal/catch_reporter_registrars.hpp"
|
#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_version.h"
|
||||||
#include "../internal/catch_text.h"
|
#include "../internal/catch_text.h"
|
||||||
#include "../internal/catch_stringref.h"
|
#include "../internal/catch_stringref.h"
|
||||||
@@ -268,7 +268,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& {
|
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
|
} // end anon namespace
|
||||||
@@ -300,9 +300,9 @@ public:
|
|||||||
headerCols += Column(info.name).width(static_cast<std::size_t>(info.width - 2));
|
headerCols += Column(info.name).width(static_cast<std::size_t>(info.width - 2));
|
||||||
headerCols += spacer;
|
headerCols += spacer;
|
||||||
}
|
}
|
||||||
m_os << headerCols << "\n";
|
m_os << headerCols << '\n';
|
||||||
|
|
||||||
m_os << Catch::getLineOfChars<'-'>() << "\n";
|
m_os << Catch::getLineOfChars<'-'>() << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void close() {
|
void close() {
|
||||||
@@ -321,30 +321,29 @@ public:
|
|||||||
|
|
||||||
friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) {
|
friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) {
|
||||||
auto colStr = tp.m_oss.str();
|
auto colStr = tp.m_oss.str();
|
||||||
// This takes account of utf8 encodings
|
const auto strSize = colStr.size();
|
||||||
auto strSize = Catch::StringRef(colStr).numberOfCharacters();
|
|
||||||
tp.m_oss.str("");
|
tp.m_oss.str("");
|
||||||
tp.open();
|
tp.open();
|
||||||
if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
|
if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
|
||||||
tp.m_currentColumn = -1;
|
tp.m_currentColumn = -1;
|
||||||
tp.m_os << "\n";
|
tp.m_os << '\n';
|
||||||
}
|
}
|
||||||
tp.m_currentColumn++;
|
tp.m_currentColumn++;
|
||||||
|
|
||||||
auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
|
auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
|
||||||
auto padding = (strSize + 2 < static_cast<std::size_t>(colInfo.width))
|
auto padding = (strSize + 1 < static_cast<std::size_t>(colInfo.width))
|
||||||
? std::string(colInfo.width - (strSize + 2), ' ')
|
? std::string(colInfo.width - (strSize + 1), ' ')
|
||||||
: std::string();
|
: std::string();
|
||||||
if (colInfo.justification == ColumnInfo::Left)
|
if (colInfo.justification == ColumnInfo::Left)
|
||||||
tp.m_os << colStr << padding << " ";
|
tp.m_os << colStr << padding << ' ';
|
||||||
else
|
else
|
||||||
tp.m_os << padding << colStr << " ";
|
tp.m_os << padding << colStr << ' ';
|
||||||
return tp;
|
return tp;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend TablePrinter& operator << (TablePrinter& tp, RowBreak) {
|
friend TablePrinter& operator << (TablePrinter& tp, RowBreak) {
|
||||||
if (tp.m_currentColumn > 0) {
|
if (tp.m_currentColumn > 0) {
|
||||||
tp.m_os << "\n";
|
tp.m_os << '\n';
|
||||||
tp.m_currentColumn = -1;
|
tp.m_currentColumn = -1;
|
||||||
}
|
}
|
||||||
return tp;
|
return tp;
|
||||||
@@ -354,12 +353,26 @@ public:
|
|||||||
ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
|
ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
|
||||||
: StreamingReporterBase(config),
|
: StreamingReporterBase(config),
|
||||||
m_tablePrinter(new TablePrinter(config.stream(),
|
m_tablePrinter(new TablePrinter(config.stream(),
|
||||||
{
|
[&config]() -> std::vector<ColumnInfo> {
|
||||||
{ "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
|
if (config.fullConfig()->benchmarkNoAnalysis())
|
||||||
{ "samples mean std dev", 14, ColumnInfo::Right },
|
{
|
||||||
{ "iterations low mean low std dev", 14, ColumnInfo::Right },
|
return{
|
||||||
{ "estimated high mean high std dev", 14, ColumnInfo::Right }
|
{ "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;
|
ConsoleReporter::~ConsoleReporter() = default;
|
||||||
|
|
||||||
std::string ConsoleReporter::getDescription() {
|
std::string ConsoleReporter::getDescription() {
|
||||||
@@ -370,6 +383,10 @@ void ConsoleReporter::noMatchingTestCases(std::string const& spec) {
|
|||||||
stream << "No test cases matched '" << spec << '\'' << std::endl;
|
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&) {}
|
void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
|
||||||
|
|
||||||
bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
|
bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
|
||||||
@@ -432,24 +449,32 @@ void ConsoleReporter::benchmarkPreparing(std::string const& name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
|
void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
|
||||||
(*m_tablePrinter) << info.samples << ColumnBreak()
|
(*m_tablePrinter) << info.samples << ColumnBreak()
|
||||||
<< info.iterations << ColumnBreak()
|
<< info.iterations << ColumnBreak();
|
||||||
<< Duration(info.estimatedDuration) << ColumnBreak();
|
if (!m_config->benchmarkNoAnalysis())
|
||||||
|
(*m_tablePrinter) << Duration(info.estimatedDuration) << ColumnBreak();
|
||||||
}
|
}
|
||||||
void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) {
|
void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) {
|
||||||
(*m_tablePrinter) << ColumnBreak()
|
if (m_config->benchmarkNoAnalysis())
|
||||||
<< Duration(stats.mean.point.count()) << ColumnBreak()
|
{
|
||||||
<< Duration(stats.mean.lower_bound.count()) << ColumnBreak()
|
(*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak();
|
||||||
<< Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak()
|
}
|
||||||
<< Duration(stats.standardDeviation.point.count()) << ColumnBreak()
|
else
|
||||||
<< Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak()
|
{
|
||||||
<< Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak();
|
(*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) {
|
void ConsoleReporter::benchmarkFailed(std::string const& error) {
|
||||||
Colour colour(Colour::Red);
|
Colour colour(Colour::Red);
|
||||||
(*m_tablePrinter)
|
(*m_tablePrinter)
|
||||||
<< "Benchmark failed (" << error << ")"
|
<< "Benchmark failed (" << error << ')'
|
||||||
<< ColumnBreak() << RowBreak();
|
<< ColumnBreak() << RowBreak();
|
||||||
}
|
}
|
||||||
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
|
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
|
||||||
@@ -531,11 +556,10 @@ void ConsoleReporter::printTestCaseAndSectionHeader() {
|
|||||||
|
|
||||||
SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
|
SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
|
||||||
|
|
||||||
if (!lineInfo.empty()) {
|
|
||||||
stream << getLineOfChars<'-'>() << '\n';
|
stream << getLineOfChars<'-'>() << '\n';
|
||||||
Colour colourGuard(Colour::FileName);
|
Colour colourGuard(Colour::FileName);
|
||||||
stream << lineInfo << '\n';
|
stream << lineInfo << '\n';
|
||||||
}
|
|
||||||
stream << getLineOfChars<'.'>() << '\n' << std::endl;
|
stream << getLineOfChars<'.'>() << '\n' << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -674,4 +698,4 @@ CATCH_REGISTER_REPORTER("console", ConsoleReporter)
|
|||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
# pragma clang diagnostic pop
|
# pragma clang diagnostic pop
|
||||||
#endif
|
#endif
|
@@ -32,6 +32,8 @@ namespace Catch {
|
|||||||
|
|
||||||
void noMatchingTestCases(std::string const& spec) override;
|
void noMatchingTestCases(std::string const& spec) override;
|
||||||
|
|
||||||
|
void reportInvalidArguments(std::string const&arg) override;
|
||||||
|
|
||||||
void assertionStarting(AssertionInfo const&) override;
|
void assertionStarting(AssertionInfo const&) override;
|
||||||
|
|
||||||
bool assertionEnded(AssertionStats const& _assertionStats) override;
|
bool assertionEnded(AssertionStats const& _assertionStats) override;
|
||||||
@@ -84,4 +86,4 @@ namespace Catch {
|
|||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#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 );
|
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)
|
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||||
void ListeningReporter::benchmarkPreparing( std::string const& name ) {
|
void ListeningReporter::benchmarkPreparing( std::string const& name ) {
|
||||||
@@ -154,4 +161,4 @@ namespace Catch {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
@@ -28,7 +28,9 @@ namespace Catch {
|
|||||||
ReporterPreferences getPreferences() const override;
|
ReporterPreferences getPreferences() const override;
|
||||||
|
|
||||||
void noMatchingTestCases( std::string const& spec ) override;
|
void noMatchingTestCases( std::string const& spec ) override;
|
||||||
|
|
||||||
|
void reportInvalidArguments(std::string const&arg) override;
|
||||||
|
|
||||||
static std::set<Verbosity> getSupportedVerbosities();
|
static std::set<Verbosity> getSupportedVerbosities();
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||||
@@ -58,4 +60,4 @@ namespace Catch {
|
|||||||
|
|
||||||
} // end 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;
|
SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
|
||||||
|
|
||||||
if( !lineInfo.empty() )
|
os << lineInfo << "\n";
|
||||||
os << lineInfo << "\n";
|
|
||||||
os << getLineOfChars<'.'>() << "\n\n";
|
os << getLineOfChars<'.'>() << "\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -220,10 +220,13 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||||
void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) {
|
void XmlReporter::benchmarkPreparing(std::string const& name) {
|
||||||
m_xml.startElement("BenchmarkResults")
|
m_xml.startElement("BenchmarkResults")
|
||||||
.writeAttribute("name", info.name)
|
.writeAttribute("name", name);
|
||||||
.writeAttribute("samples", info.samples)
|
}
|
||||||
|
|
||||||
|
void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) {
|
||||||
|
m_xml.writeAttribute("samples", info.samples)
|
||||||
.writeAttribute("resamples", info.resamples)
|
.writeAttribute("resamples", info.resamples)
|
||||||
.writeAttribute("iterations", info.iterations)
|
.writeAttribute("iterations", info.iterations)
|
||||||
.writeAttribute("clockResolution", static_cast<uint64_t>(info.clockResolution))
|
.writeAttribute("clockResolution", static_cast<uint64_t>(info.clockResolution))
|
||||||
|
@@ -51,6 +51,7 @@ namespace Catch {
|
|||||||
void testRunEnded(TestRunStats const& testRunStats) override;
|
void testRunEnded(TestRunStats const& testRunStats) override;
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||||
|
void benchmarkPreparing(std::string const& name) override;
|
||||||
void benchmarkStarting(BenchmarkInfo const&) override;
|
void benchmarkStarting(BenchmarkInfo const&) override;
|
||||||
void benchmarkEnded(BenchmarkStats<> const&) override;
|
void benchmarkEnded(BenchmarkStats<> const&) override;
|
||||||
void benchmarkFailed(std::string const&) override;
|
void benchmarkFailed(std::string const&) override;
|
||||||
|
@@ -4,6 +4,6 @@ import glob
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
cov_files = list(glob.glob('cov-report*.bin'))
|
cov_files = list(glob.glob('projects/cov-report*.bin'))
|
||||||
base_cmd = ['OpenCppCoverage', '--quiet', '--export_type=cobertura:cobertura.xml'] + ['--input_coverage={}'.format(f) for f in cov_files]
|
base_cmd = ['OpenCppCoverage', '--quiet', '--export_type=cobertura:cobertura.xml'] + ['--input_coverage={}'.format(f) for f in cov_files]
|
||||||
subprocess.call(base_cmd)
|
subprocess.check_call(base_cmd)
|
||||||
|
@@ -29,7 +29,8 @@ std::string escape_arg(const std::string& arg) {
|
|||||||
escaped.append(num_backslashes * 2, '\\');
|
escaped.append(num_backslashes * 2, '\\');
|
||||||
break;
|
break;
|
||||||
} else if (*it == '"') {
|
} else if (*it == '"') {
|
||||||
escaped.append(num_backslashes * 2 + 1, '\\');
|
escaped.append((num_backslashes + 1) * 2, '\\');
|
||||||
|
escaped.push_back('"');
|
||||||
escaped.push_back(*it);
|
escaped.push_back(*it);
|
||||||
} else {
|
} else {
|
||||||
escaped.append(num_backslashes, '\\');
|
escaped.append(num_backslashes, '\\');
|
||||||
@@ -89,27 +90,30 @@ std::string windowsify_path(std::string path) {
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void exec_cmd(std::string const& cmd, int log_num, std::string const& path) {
|
int exec_cmd(std::string const& cmd, int log_num, std::string const& path) {
|
||||||
std::array<char, 128> buffer;
|
std::array<char, 128> buffer;
|
||||||
#if defined(_WIN32)
|
|
||||||
// cmd has already been escaped outside this function.
|
// cmd has already been escaped outside this function.
|
||||||
auto real_cmd = "OpenCppCoverage --export_type binary:cov-report" + std::to_string(log_num)
|
auto real_cmd = "OpenCppCoverage --export_type binary:cov-report" + std::to_string(log_num)
|
||||||
+ ".bin --quiet " + "--sources " + escape_arg(path) + " --cover_children -- " + cmd;
|
+ ".bin --quiet " + "--sources " + escape_arg(path) + " --cover_children -- " + cmd;
|
||||||
std::cout << "=== Marker ===: Cmd: " << real_cmd << '\n';
|
std::cout << "=== Marker ===: Cmd: " << real_cmd << '\n';
|
||||||
std::shared_ptr<FILE> pipe(_popen(real_cmd.c_str(), "r"), _pclose);
|
auto pipe = _popen(real_cmd.c_str(), "r");
|
||||||
#else // Just for testing, in the real world we will always work under WIN32
|
|
||||||
(void)log_num; (void)path;
|
|
||||||
std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!pipe) {
|
if (!pipe) {
|
||||||
throw std::runtime_error("popen() failed!");
|
throw std::runtime_error("popen() failed!");
|
||||||
}
|
}
|
||||||
while (!feof(pipe.get())) {
|
while (!feof(pipe)) {
|
||||||
if (fgets(buffer.data(), 128, pipe.get()) != nullptr) {
|
if (fgets(buffer.data(), 128, pipe) != nullptr) {
|
||||||
std::cout << buffer.data();
|
std::cout << buffer.data();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto ret = _pclose(pipe);
|
||||||
|
if (ret == -1) {
|
||||||
|
throw std::runtime_error("underlying error in pclose()");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// argv should be:
|
// argv should be:
|
||||||
@@ -124,7 +128,7 @@ int main(int argc, char** argv) {
|
|||||||
assert(sep - begin(args) == 2 && "Structure differs from expected!");
|
assert(sep - begin(args) == 2 && "Structure differs from expected!");
|
||||||
|
|
||||||
auto num = parse_log_file_arg(args[1]);
|
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) {
|
auto cmdline = std::accumulate(++sep, end(args), std::string{}, [] (const std::string& lhs, const std::string& rhs) {
|
||||||
return lhs + ' ' + escape_arg(rhs);
|
return lhs + ' ' + escape_arg(rhs);
|
||||||
});
|
});
|
||||||
|
@@ -17,11 +17,14 @@ endif(MSVC) #Temporary workaround
|
|||||||
set(TEST_SOURCES
|
set(TEST_SOURCES
|
||||||
${SELF_TEST_DIR}/TestMain.cpp
|
${SELF_TEST_DIR}/TestMain.cpp
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.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/GeneratorsImpl.tests.cpp
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/InternalBenchmark.tests.cpp
|
${SELF_TEST_DIR}/IntrospectiveTests/InternalBenchmark.tests.cpp
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.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/Tag.tests.cpp
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/String.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/Xml.tests.cpp
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/ToString.tests.cpp
|
${SELF_TEST_DIR}/IntrospectiveTests/ToString.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/Approx.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_leak_detector.h
|
||||||
${HEADER_DIR}/internal/catch_list.h
|
${HEADER_DIR}/internal/catch_list.h
|
||||||
${HEADER_DIR}/internal/catch_matchers.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_floating.h
|
||||||
${HEADER_DIR}/internal/catch_matchers_generic.hpp
|
${HEADER_DIR}/internal/catch_matchers_generic.hpp
|
||||||
${HEADER_DIR}/internal/catch_matchers_string.h
|
${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_to_string.hpp
|
||||||
${HEADER_DIR}/internal/catch_tostring.h
|
${HEADER_DIR}/internal/catch_tostring.h
|
||||||
${HEADER_DIR}/internal/catch_totals.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_uncaught_exceptions.h
|
||||||
${HEADER_DIR}/internal/catch_user_interfaces.h
|
${HEADER_DIR}/internal/catch_user_interfaces.h
|
||||||
${HEADER_DIR}/internal/catch_version.h
|
${HEADER_DIR}/internal/catch_version.h
|
||||||
@@ -227,6 +230,7 @@ set(IMPL_SOURCES
|
|||||||
${HEADER_DIR}/internal/catch_list.cpp
|
${HEADER_DIR}/internal/catch_list.cpp
|
||||||
${HEADER_DIR}/internal/catch_leak_detector.cpp
|
${HEADER_DIR}/internal/catch_leak_detector.cpp
|
||||||
${HEADER_DIR}/internal/catch_matchers.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_floating.cpp
|
||||||
${HEADER_DIR}/internal/catch_matchers_generic.cpp
|
${HEADER_DIR}/internal/catch_matchers_generic.cpp
|
||||||
${HEADER_DIR}/internal/catch_matchers_string.cpp
|
${HEADER_DIR}/internal/catch_matchers_string.cpp
|
||||||
@@ -393,8 +397,19 @@ set_tests_properties(ListTestNamesOnly PROPERTIES
|
|||||||
add_test(NAME NoAssertions COMMAND $<TARGET_FILE:SelfTest> -w NoAssertions)
|
add_test(NAME NoAssertions COMMAND $<TARGET_FILE:SelfTest> -w NoAssertions)
|
||||||
set_tests_properties(NoAssertions PROPERTIES PASS_REGULAR_EXPRESSION "No assertions in test case")
|
set_tests_properties(NoAssertions PROPERTIES PASS_REGULAR_EXPRESSION "No assertions in test case")
|
||||||
|
|
||||||
add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> -w NoTests "___nonexistent_test___")
|
add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> Tracker, "___nonexistent_test___")
|
||||||
set_tests_properties(NoTest PROPERTIES PASS_REGULAR_EXPRESSION "No test cases matched")
|
set_tests_properties(NoTest PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "No test cases matched '___nonexistent_test___'"
|
||||||
|
FAIL_REGULAR_EXPRESSION "No tests ran"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_test(NAME WarnAboutNoTests COMMAND ${CMAKE_COMMAND} -P ${CATCH_DIR}/projects/SelfTest/WarnAboutNoTests.cmake $<TARGET_FILE:SelfTest>)
|
||||||
|
|
||||||
|
add_test(NAME UnmatchedOutputFilter COMMAND $<TARGET_FILE:SelfTest> [this-tag-does-not-exist] -w NoTests)
|
||||||
|
set_tests_properties(UnmatchedOutputFilter
|
||||||
|
PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "No test cases matched '\\[this-tag-does-not-exist\\]'"
|
||||||
|
)
|
||||||
|
|
||||||
add_test(NAME FilteredSection-1 COMMAND $<TARGET_FILE:SelfTest> \#1394 -c RunSection)
|
add_test(NAME FilteredSection-1 COMMAND $<TARGET_FILE:SelfTest> \#1394 -c RunSection)
|
||||||
set_tests_properties(FilteredSection-1 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
|
set_tests_properties(FilteredSection-1 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
|
||||||
@@ -402,12 +417,40 @@ add_test(NAME FilteredSection-2 COMMAND $<TARGET_FILE:SelfTest> \#1394\ nested -
|
|||||||
set_tests_properties(FilteredSection-2 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
|
set_tests_properties(FilteredSection-2 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
|
||||||
|
|
||||||
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
|
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
|
||||||
add_test(NAME ApprovalTests COMMAND ${Python_EXECUTABLE} ${CATCH_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
|
add_test(NAME ApprovalTests COMMAND ${PYTHON_EXECUTABLE} ${CATCH_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
|
||||||
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
|
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
|
||||||
|
|
||||||
add_test(NAME RegressionCheck-1670 COMMAND $<TARGET_FILE:SelfTest> "#1670 regression check" -c A -r compact)
|
add_test(NAME RegressionCheck-1670 COMMAND $<TARGET_FILE:SelfTest> "#1670 regression check" -c A -r compact)
|
||||||
set_tests_properties(RegressionCheck-1670 PROPERTIES PASS_REGULAR_EXPRESSION "Passed 1 test case with 2 assertions.")
|
set_tests_properties(RegressionCheck-1670 PROPERTIES PASS_REGULAR_EXPRESSION "Passed 1 test case with 2 assertions.")
|
||||||
|
|
||||||
|
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)
|
if (CATCH_USE_VALGRIND)
|
||||||
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
|
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
|
||||||
add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
|
add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
|
||||||
|
@@ -126,6 +126,16 @@ set_tests_properties(
|
|||||||
PASS_REGULAR_EXPRESSION "benchmark name samples iterations estimated"
|
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
|
set( EXTRA_TEST_BINARIES
|
||||||
PrefixedMacros
|
PrefixedMacros
|
||||||
@@ -145,3 +155,4 @@ foreach( test ${EXTRA_TEST_BINARIES} )
|
|||||||
target_include_directories( ${test} PRIVATE ${SINGLE_INCLUDE_PATH} )
|
target_include_directories( ${test} PRIVATE ${SINGLE_INCLUDE_PATH} )
|
||||||
endforeach()
|
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();
|
||||||
|
}
|
@@ -3,6 +3,8 @@ Decomposition.tests.cpp:<line number>: passed: fptr == 0 for: 0 == 0
|
|||||||
Decomposition.tests.cpp:<line number>: passed: fptr == 0l for: 0 == 0
|
Decomposition.tests.cpp:<line number>: passed: fptr == 0l for: 0 == 0
|
||||||
Compilation.tests.cpp:<line number>: passed: y.v == 0 for: 0 == 0
|
Compilation.tests.cpp:<line number>: passed: y.v == 0 for: 0 == 0
|
||||||
Compilation.tests.cpp:<line number>: passed: 0 == y.v for: 0 == 0
|
Compilation.tests.cpp:<line number>: passed: 0 == y.v for: 0 == 0
|
||||||
|
Compilation.tests.cpp:<line number>: passed: y.v == 0 for: 0 == 0
|
||||||
|
Compilation.tests.cpp:<line number>: passed: 0 == y.v for: 0 == 0
|
||||||
Compilation.tests.cpp:<line number>: passed: t1 == t2 for: {?} == {?}
|
Compilation.tests.cpp:<line number>: passed: t1 == t2 for: {?} == {?}
|
||||||
Compilation.tests.cpp:<line number>: passed: t1 != t2 for: {?} != {?}
|
Compilation.tests.cpp:<line number>: passed: t1 != t2 for: {?} != {?}
|
||||||
Compilation.tests.cpp:<line number>: passed: t1 < t2 for: {?} < {?}
|
Compilation.tests.cpp:<line number>: passed: t1 < t2 for: {?} < {?}
|
||||||
@@ -241,11 +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
|
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 ))
|
|
||||||
Tricky.tests.cpp:<line number>: passed: y.v == 0 for: 0 == 0
|
|
||||||
Tricky.tests.cpp:<line number>: passed: 0 == y.v for: 0 == 0
|
|
||||||
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: '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 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 ''{' := '{''
|
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: 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 for: 0x<hex digits>
|
||||||
Tricky.tests.cpp:<line number>: passed: a == &foo for: 0x<hex digits> == 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: 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: 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 )
|
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
|
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("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"
|
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()
|
||||||
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 exception - not std'; expression was: throwCustom(), std::exception
|
||||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'custom 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: 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: 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: throwsSpecialException(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>: failed: throwsSpecialException(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: throwsSpecialException(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>: 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(), "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(), 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(), 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(), 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" ) for: "expected exception" contains: "except"
|
||||||
Exception.tests.cpp:<line number>: passed: thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) for: "expected exception" contains: "except" (case insensitive)
|
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: 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: 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()
|
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(2) == 2 for: 2 == 2
|
||||||
Misc.tests.cpp:<line number>: passed: Factorial(3) == 6 for: 6 == 6
|
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>)
|
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: 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., 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
|
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(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(-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: -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: 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.0 ([0.99999999999999989, 1.00000000000000022])
|
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: 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: 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: 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(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(1., 0) for: 1.0 is within 0 ULPs of 1.0 ([1.00000000000000000, 1.00000000000000000])
|
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: -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., 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: 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: -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(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., 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., 0.)
|
||||||
Matchers.tests.cpp:<line number>: passed: WithinAbs(1., -1.), std::domain_error
|
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., 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: 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, 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
|
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(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(-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: -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: 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.0f ([0.99999994039535522, 1.00000011920928955])
|
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: 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: 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: 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(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(1.f, 0) for: 1.0f is within 0 ULPs of 1.0f ([1.00000000000000000, 1.00000000000000000])
|
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: -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, 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: 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: -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(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, 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, 0.f)
|
||||||
Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, -1.f), std::domain_error
|
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, 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
|
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 < "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 > "hellm" for: "hello" > "hellm"
|
||||||
Condition.tests.cpp:<line number>: passed: data.str_hello > "a" for: "hello" > "a"
|
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 one'
|
||||||
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Message from section two'
|
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
|
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( 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( 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( 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 == 0 for: 0 == 0
|
||||||
Condition.tests.cpp:<line number>: passed: p == pNULL 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
|
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.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.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: 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 one
|
||||||
Message from section two
|
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"
|
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: 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() == 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.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("hello") for: hello == hello
|
||||||
String.tests.cpp:<line number>: passed: StringRef("hello") != StringRef("cello") for: hello != cello
|
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"
|
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.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 == "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.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: 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: hour != seconds for: 1 h != 60 s
|
||||||
ToStringChrono.tests.cpp:<line number>: passed: micro != milli for: 1 us != 1 ms
|
ToStringChrono.tests.cpp:<line number>: passed: micro != milli for: 1 us != 1 ms
|
||||||
@@ -1084,6 +1172,10 @@ Tag.tests.cpp:<line number>: passed: registry.add( "[@no square bracket at end",
|
|||||||
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 == 1
|
||||||
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 == 1
|
||||||
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1.0 == 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
|
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: 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
|
||||||
@@ -1225,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
|
Misc.tests.cpp:<line number>: passed: v.capacity() >= V for: 15 >= 15
|
||||||
VariadicMacros.tests.cpp:<line number>: passed: with 1 message: 'no assertions'
|
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
|
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
|
Message.tests.cpp:<line number>: failed - but was ok: 1 == 2
|
||||||
Misc.tests.cpp:<line number>: passed: with 1 message: 'oops!'
|
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!'
|
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'For some reason someone is throwing a string literal!'
|
||||||
@@ -1295,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: s1.isComplete() for: true
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
|
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
|
||||||
PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() for: true
|
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'
|
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.23 ) for: 1.23 == Approx( 1.23 )
|
||||||
Approx.tests.cpp:<line number>: passed: d == approx( 1.22 ) for: 1.23 == Approx( 1.22 )
|
Approx.tests.cpp:<line number>: passed: d == approx( 1.22 ) for: 1.23 == Approx( 1.22 )
|
||||||
@@ -1480,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 } }"
|
ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" for: "{ { 42, "Arthur" }, { "Ford", 24 } }"
|
||||||
==
|
==
|
||||||
"{ { 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( "" ), Equals( std::vector<Catch::StringRef>{} ) 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( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"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( "Value1" ), Equals( std::vector<Catch::StringRef>{"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( "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<std::string>{"Value1", "Value2"} ) for: { "Value1", "Value2" } Equals: { "Value1", "Value2" }
|
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<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<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<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<Catch::StringRef>{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 }
|
||||||
Tricky.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
|
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>: 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'
|
Message.tests.cpp:<line number>: failed: false with 2 messages: 'this SHOULD be seen' and 'this SHOULD also be seen'
|
||||||
@@ -1497,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: a != b for: 1 != 2
|
||||||
Misc.tests.cpp:<line number>: passed: b != a for: 2 != 1
|
Misc.tests.cpp:<line number>: passed: b != a for: 2 != 1
|
||||||
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
|
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
|
||||||
String.tests.cpp:<line number>: passed: Catch::replaceInPlace( letters, "b", "z" ) for: true
|
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, "b", "z") for: true
|
||||||
String.tests.cpp:<line number>: passed: letters == "azcdefcg" for: "azcdefcg" == "azcdefcg"
|
StringManip.tests.cpp:<line number>: passed: letters == "azcdefcg" for: "azcdefcg" == "azcdefcg"
|
||||||
String.tests.cpp:<line number>: passed: Catch::replaceInPlace( letters, "c", "z" ) for: true
|
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, "c", "z") for: true
|
||||||
String.tests.cpp:<line number>: passed: letters == "abzdefzg" for: "abzdefzg" == "abzdefzg"
|
StringManip.tests.cpp:<line number>: passed: letters == "abzdefzg" for: "abzdefzg" == "abzdefzg"
|
||||||
String.tests.cpp:<line number>: passed: Catch::replaceInPlace( letters, "a", "z" ) for: true
|
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, "a", "z") for: true
|
||||||
String.tests.cpp:<line number>: passed: letters == "zbcdefcg" for: "zbcdefcg" == "zbcdefcg"
|
StringManip.tests.cpp:<line number>: passed: letters == "zbcdefcg" for: "zbcdefcg" == "zbcdefcg"
|
||||||
String.tests.cpp:<line number>: passed: Catch::replaceInPlace( letters, "g", "z" ) for: true
|
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, "g", "z") for: true
|
||||||
String.tests.cpp:<line number>: passed: letters == "abcdefcz" for: "abcdefcz" == "abcdefcz"
|
StringManip.tests.cpp:<line number>: passed: letters == "abcdefcz" for: "abcdefcz" == "abcdefcz"
|
||||||
String.tests.cpp:<line number>: passed: Catch::replaceInPlace( letters, letters, "replaced" ) for: true
|
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, letters, "replaced") for: true
|
||||||
String.tests.cpp:<line number>: passed: letters == "replaced" for: "replaced" == "replaced"
|
StringManip.tests.cpp:<line number>: passed: letters == "replaced" for: "replaced" == "replaced"
|
||||||
String.tests.cpp:<line number>: passed: !(Catch::replaceInPlace( letters, "x", "z" )) for: !false
|
StringManip.tests.cpp:<line number>: passed: !(Catch::replaceInPlace(letters, "x", "z")) for: !false
|
||||||
String.tests.cpp:<line number>: passed: letters == letters for: "abcdefcg" == "abcdefcg"
|
StringManip.tests.cpp:<line number>: passed: letters == letters for: "abcdefcg" == "abcdefcg"
|
||||||
String.tests.cpp:<line number>: passed: Catch::replaceInPlace( s, "'", "|'" ) for: true
|
StringManip.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: s == "didn|'t" for: "didn|'t" == "didn|'t"
|
||||||
Misc.tests.cpp:<line number>: failed: false with 1 message: '3'
|
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'
|
Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7'
|
||||||
Tag.tests.cpp:<line number>: passed: testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")) for: { ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
|
Tag.tests.cpp:<line number>: passed: testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")) for: { ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
|
||||||
String.tests.cpp:<line number>: passed: splitStringRef("", ',' ), Equals(std::vector<StringRef>() ) for: { } Equals: { }
|
StringManip.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 }
|
StringManip.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("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 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'
|
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: "{ }" == "{ }"
|
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:
|
Matchers.tests.cpp:<line number>: FAILED:
|
||||||
CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{1} )
|
CHECK_THROWS_MATCHES( throwsSpecialException(3), SpecialException, ExceptionMatcher{1} )
|
||||||
with expansion:
|
with expansion:
|
||||||
SpecialException::what special exception has value of 1
|
SpecialException::what special exception has value of 1
|
||||||
|
|
||||||
Matchers.tests.cpp:<line number>: FAILED:
|
Matchers.tests.cpp:<line number>: FAILED:
|
||||||
REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{1} )
|
REQUIRE_THROWS_MATCHES( throwsSpecialException(4), SpecialException, ExceptionMatcher{1} )
|
||||||
with expansion:
|
with expansion:
|
||||||
SpecialException::what special exception has value of 1
|
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?
|
Why would you throw a std::string?
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 295 | 221 passed | 70 failed | 4 failed as expected
|
test cases: 304 | 230 passed | 70 failed | 4 failed as expected
|
||||||
assertions: 1550 | 1398 passed | 131 failed | 21 failed as expected
|
assertions: 1621 | 1469 passed | 131 failed | 21 failed as expected
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user