mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-19 03:15:40 +02:00
Compare commits
44 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
60b05b2041 | ||
![]() |
232ea3c456 | ||
![]() |
a5c900d077 | ||
![]() |
8b01883854 | ||
![]() |
86da2846af | ||
![]() |
ef9150fe6f | ||
![]() |
84fa76e985 | ||
![]() |
fcd91c7d6b | ||
![]() |
efbf50fc7d | ||
![]() |
64fd5b8058 | ||
![]() |
ee73989f9b | ||
![]() |
646e1f608d | ||
![]() |
6f75acbfb5 | ||
![]() |
9c3cc4a076 | ||
![]() |
f3972f0695 | ||
![]() |
38e1731f69 | ||
![]() |
0947752a44 | ||
![]() |
0646e0283c | ||
![]() |
90663b2e75 | ||
![]() |
7667a7d89c | ||
![]() |
9773d89ab4 | ||
![]() |
2067c8d3bd | ||
![]() |
1742ab76a2 | ||
![]() |
898d111f72 | ||
![]() |
5202993555 | ||
![]() |
f061dabbad | ||
![]() |
1a501fcb48 | ||
![]() |
94121a5f6d | ||
![]() |
92e25049cf | ||
![]() |
fdcd46420e | ||
![]() |
7c25dae9ea | ||
![]() |
7f18282d17 | ||
![]() |
1cdaa48a0b | ||
![]() |
1a63fad8d6 | ||
![]() |
d6f2fd486c | ||
![]() |
5884ec1e28 | ||
![]() |
eb783fc20e | ||
![]() |
38248f3f2c | ||
![]() |
c9de7dd12d | ||
![]() |
52cbb507ab | ||
![]() |
83bfae1a50 | ||
![]() |
f7f592dfc9 | ||
![]() |
78804ea304 | ||
![]() |
b93284716e |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -17,6 +17,6 @@
|
|||||||
|
|
||||||
# Keep the single include header with LFs to make sure it is uploaded,
|
# Keep the single include header with LFs to make sure it is uploaded,
|
||||||
# hashed etc with LF
|
# hashed etc with LF
|
||||||
single_include/*.hpp eol=lf
|
single_include/**/*.hpp eol=lf
|
||||||
# Also keep the LICENCE file with LFs for the same reason
|
# Also keep the LICENCE file with LFs for the same reason
|
||||||
LICENCE.txt eol=lf
|
LICENCE.txt eol=lf
|
||||||
|
@@ -219,7 +219,7 @@ matrix:
|
|||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['lcov', 'g++-7']
|
packages: ['lcov', 'g++-7']
|
||||||
env: COMPILER='g++-7' CPP14=1 EXAMPLES=1 COVERAGE=1
|
env: COMPILER='g++-7' CPP14=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
@@ -229,7 +229,7 @@ matrix:
|
|||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
- llvm-toolchain-trusty
|
- llvm-toolchain-trusty
|
||||||
env: COMPILER='clang++-3.8' EXAMPLES=1 COVERAGE=1
|
env: COMPILER='clang++-3.8' EXAMPLES=1 COVERAGE=1 EXTRAS=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
@@ -242,7 +242,7 @@ matrix:
|
|||||||
- os: osx
|
- os: osx
|
||||||
osx_image: xcode9.1
|
osx_image: xcode9.1
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER='clang++' CPP14=1 EXAMPLES=1 COVERAGE=1
|
env: COMPILER='clang++' CPP14=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||||
@@ -263,7 +263,7 @@ before_script:
|
|||||||
- python scripts/generateSingleHeader.py
|
- python scripts/generateSingleHeader.py
|
||||||
|
|
||||||
# Use Debug builds for running Valgrind and building examples
|
# Use Debug builds for running Valgrind and building examples
|
||||||
- cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=${EXAMPLES} -DCATCH_ENABLE_COVERAGE=${COVERAGE}
|
- cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=${EXAMPLES} -DCATCH_ENABLE_COVERAGE=${COVERAGE} -DCATCH_BUILD_EXTRA_TESTS=${EXTRAS}
|
||||||
# Don't bother with release build for coverage build
|
# Don't bother with release build for coverage build
|
||||||
- cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
|
- cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@ if(NOT DEFINED PROJECT_NAME)
|
|||||||
set(NOT_SUBPROJECT ON)
|
set(NOT_SUBPROJECT ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(Catch2 LANGUAGES CXX VERSION 2.3.0)
|
project(Catch2 LANGUAGES CXX VERSION 2.4.0)
|
||||||
|
|
||||||
# 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")
|
||||||
@@ -18,6 +18,7 @@ include(CTest)
|
|||||||
option(CATCH_USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
|
option(CATCH_USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
|
||||||
option(CATCH_BUILD_TESTING "Build SelfTest project" ON)
|
option(CATCH_BUILD_TESTING "Build SelfTest project" ON)
|
||||||
option(CATCH_BUILD_EXAMPLES "Build documentation examples" OFF)
|
option(CATCH_BUILD_EXAMPLES "Build documentation examples" OFF)
|
||||||
|
option(CATCH_BUILD_EXTRA_TESTS "Build extra tests" OFF)
|
||||||
option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io" OFF)
|
option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io" OFF)
|
||||||
option(CATCH_ENABLE_WERROR "Enable all warnings as errors" ON)
|
option(CATCH_ENABLE_WERROR "Enable all warnings as errors" ON)
|
||||||
option(CATCH_INSTALL_DOCS "Install documentation alongside library" ON)
|
option(CATCH_INSTALL_DOCS "Install documentation alongside library" ON)
|
||||||
@@ -37,6 +38,10 @@ 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(PythonInterp)
|
||||||
|
if (NOT PYTHONINTERP_FOUND)
|
||||||
|
message(FATAL_ERROR "Python not found, but required for tests")
|
||||||
|
endif()
|
||||||
add_subdirectory(projects)
|
add_subdirectory(projects)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -44,6 +49,9 @@ if(CATCH_BUILD_EXAMPLES)
|
|||||||
add_subdirectory(examples)
|
add_subdirectory(examples)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CATCH_BUILD_EXTRA_TESTS)
|
||||||
|
add_subdirectory(projects/ExtraTests)
|
||||||
|
endif()
|
||||||
|
|
||||||
# add catch as a 'linkable' target
|
# add catch as a 'linkable' target
|
||||||
add_library(Catch2 INTERFACE)
|
add_library(Catch2 INTERFACE)
|
||||||
@@ -83,102 +91,118 @@ target_include_directories(Catch2
|
|||||||
# 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)
|
||||||
|
|
||||||
set(CATCH_CMAKE_CONFIG_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Catch2")
|
# Only perform the installation steps when Catch is not being used as
|
||||||
|
# a subproject via `add_subdirectory`, or the destinations will break,
|
||||||
|
# see https://github.com/catchorg/Catch2/issues/1373
|
||||||
|
if (NOT_SUBPROJECT)
|
||||||
|
set(CATCH_CMAKE_CONFIG_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Catch2")
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
configure_package_config_file(
|
||||||
configure_package_config_file(
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/CMake/Catch2Config.cmake.in
|
${CMAKE_CURRENT_LIST_DIR}/CMake/Catch2Config.cmake.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake
|
${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake
|
||||||
INSTALL_DESTINATION
|
INSTALL_DESTINATION
|
||||||
${CATCH_CMAKE_CONFIG_DESTINATION}
|
${CATCH_CMAKE_CONFIG_DESTINATION}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# create and install an export set for catch target as Catch2::Catch
|
# create and install an export set for catch target as Catch2::Catch
|
||||||
install(
|
install(
|
||||||
TARGETS
|
TARGETS
|
||||||
Catch2
|
Catch2
|
||||||
EXPORT
|
EXPORT
|
||||||
Catch2Targets
|
Catch2Targets
|
||||||
DESTINATION
|
DESTINATION
|
||||||
${CMAKE_INSTALL_LIBDIR}
|
${CMAKE_INSTALL_LIBDIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
install(
|
install(
|
||||||
EXPORT
|
EXPORT
|
||||||
Catch2Targets
|
Catch2Targets
|
||||||
NAMESPACE
|
NAMESPACE
|
||||||
Catch2::
|
Catch2::
|
||||||
DESTINATION
|
DESTINATION
|
||||||
${CATCH_CMAKE_CONFIG_DESTINATION}
|
${CATCH_CMAKE_CONFIG_DESTINATION}
|
||||||
)
|
)
|
||||||
|
|
||||||
write_basic_package_version_file(
|
# By default, FooConfigVersion is tied to architecture that it was
|
||||||
|
# generated on. Because Catch2 is header-only, it is arch-independent
|
||||||
|
# and thus Catch2ConfigVersion should not be tied to the architecture
|
||||||
|
# it was generated on.
|
||||||
|
#
|
||||||
|
# CMake does not provide a direct customization point for this in
|
||||||
|
# `write_basic_package_version_file`, but it can be accomplished
|
||||||
|
# indirectly by temporarily undefining `CMAKE_SIZEOF_VOID_P`.
|
||||||
|
set(CATCH2_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
|
||||||
|
unset(CMAKE_SIZEOF_VOID_P)
|
||||||
|
write_basic_package_version_file(
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
|
||||||
COMPATIBILITY
|
COMPATIBILITY
|
||||||
SameMajorVersion
|
SameMajorVersion
|
||||||
)
|
)
|
||||||
|
set(CMAKE_SIZEOF_VOID_P ${CATCH2_CMAKE_SIZEOF_VOID_P})
|
||||||
|
|
||||||
install(
|
install(
|
||||||
DIRECTORY
|
DIRECTORY
|
||||||
"single_include/"
|
"single_include/"
|
||||||
DESTINATION
|
DESTINATION
|
||||||
"${CMAKE_INSTALL_INCLUDEDIR}"
|
"${CMAKE_INSTALL_INCLUDEDIR}"
|
||||||
)
|
)
|
||||||
|
|
||||||
install(
|
install(
|
||||||
FILES
|
FILES
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake"
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
|
||||||
DESTINATION
|
DESTINATION
|
||||||
${CATCH_CMAKE_CONFIG_DESTINATION}
|
${CATCH_CMAKE_CONFIG_DESTINATION}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Install documentation
|
# Install documentation
|
||||||
if(CATCH_INSTALL_DOCS)
|
if(CATCH_INSTALL_DOCS)
|
||||||
install(
|
install(
|
||||||
DIRECTORY
|
DIRECTORY
|
||||||
docs/
|
docs/
|
||||||
DESTINATION
|
DESTINATION
|
||||||
"${CMAKE_INSTALL_DOCDIR}"
|
"${CMAKE_INSTALL_DOCDIR}"
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CATCH_INSTALL_HELPERS)
|
if(CATCH_INSTALL_HELPERS)
|
||||||
# Install CMake scripts
|
# Install CMake scripts
|
||||||
install(
|
install(
|
||||||
FILES
|
FILES
|
||||||
"contrib/ParseAndAddCatchTests.cmake"
|
"contrib/ParseAndAddCatchTests.cmake"
|
||||||
"contrib/Catch.cmake"
|
"contrib/Catch.cmake"
|
||||||
"contrib/CatchAddTests.cmake"
|
"contrib/CatchAddTests.cmake"
|
||||||
DESTINATION
|
DESTINATION
|
||||||
${CATCH_CMAKE_CONFIG_DESTINATION}
|
${CATCH_CMAKE_CONFIG_DESTINATION}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Install debugger helpers
|
# Install debugger helpers
|
||||||
install(
|
install(
|
||||||
FILES
|
FILES
|
||||||
"contrib/gdbinit"
|
"contrib/gdbinit"
|
||||||
"contrib/lldbinit"
|
"contrib/lldbinit"
|
||||||
DESTINATION
|
DESTINATION
|
||||||
${CMAKE_INSTALL_DATAROOTDIR}/Catch2
|
${CMAKE_INSTALL_DATAROOTDIR}/Catch2
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
## Provide some pkg-config integration
|
## Provide some pkg-config integration
|
||||||
set(PKGCONFIG_INSTALL_DIR
|
set(PKGCONFIG_INSTALL_DIR
|
||||||
"${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig"
|
"${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig"
|
||||||
CACHE PATH "Path where catch2.pc is installed"
|
CACHE PATH "Path where catch2.pc is installed"
|
||||||
)
|
)
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/CMake/catch2.pc.in
|
${CMAKE_CURRENT_SOURCE_DIR}/CMake/catch2.pc.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/catch2.pc
|
${CMAKE_CURRENT_BINARY_DIR}/catch2.pc
|
||||||
@ONLY
|
@ONLY
|
||||||
)
|
)
|
||||||
install(
|
install(
|
||||||
FILES
|
FILES
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/catch2.pc"
|
"${CMAKE_CURRENT_BINARY_DIR}/catch2.pc"
|
||||||
DESTINATION
|
DESTINATION
|
||||||
${PKGCONFIG_INSTALL_DIR}
|
${PKGCONFIG_INSTALL_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
endif(NOT_SUBPROJECT)
|
||||||
|
@@ -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/Gcuv2Xx3wmWIPNzy)
|
[](https://wandbox.org/permlink/4wRGoJ1WzLjRM7HZ)
|
||||||
[](https://discord.gg/4CWS9zD)
|
[](https://discord.gg/4CWS9zD)
|
||||||
|
|
||||||
|
|
||||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.3.0/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.4.0/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||||
|
|
||||||
## Catch2 is released!
|
## Catch2 is released!
|
||||||
|
|
||||||
|
@@ -33,8 +33,6 @@ environment:
|
|||||||
|
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
|
||||||
- os: Visual Studio 2017
|
|
||||||
exclude:
|
exclude:
|
||||||
- os: Visual Studio 2015
|
- os: Visual Studio 2015
|
||||||
additional_flags: "/permissive- /std:c++latest"
|
additional_flags: "/permissive- /std:c++latest"
|
||||||
|
@@ -4,7 +4,7 @@ from conans import ConanFile, CMake
|
|||||||
|
|
||||||
class CatchConan(ConanFile):
|
class CatchConan(ConanFile):
|
||||||
name = "Catch"
|
name = "Catch"
|
||||||
version = "2.3.0"
|
version = "2.4.0"
|
||||||
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
|
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
|
||||||
author = "philsquared"
|
author = "philsquared"
|
||||||
generators = "cmake"
|
generators = "cmake"
|
||||||
|
@@ -12,6 +12,7 @@ Writing tests:
|
|||||||
* [Test fixtures](test-fixtures.md#top)
|
* [Test fixtures](test-fixtures.md#top)
|
||||||
* [Reporters](reporters.md#top)
|
* [Reporters](reporters.md#top)
|
||||||
* [Event Listeners](event-listeners.md#top)
|
* [Event Listeners](event-listeners.md#top)
|
||||||
|
* [Data Generators](generators.md#top)
|
||||||
|
|
||||||
Fine tuning:
|
Fine tuning:
|
||||||
* [Supplying your own main()](own-main.md#top)
|
* [Supplying your own main()](own-main.md#top)
|
||||||
|
@@ -200,6 +200,40 @@ By default, Catch does not stringify some types from the standard library. This
|
|||||||
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS // Defines all of the above
|
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS // Defines all of the above
|
||||||
|
|
||||||
|
|
||||||
|
## Disabling exceptions
|
||||||
|
|
||||||
|
By default, Catch2 uses exceptions to signal errors and to abort tests
|
||||||
|
when an assertion from the `REQUIRE` family of assertions fails. We also
|
||||||
|
provide an experimental support for disabling exceptions. Catch2 should
|
||||||
|
automatically detect when it is compiled with exceptions disabled, but
|
||||||
|
it can be forced to compile without exceptions by defining
|
||||||
|
|
||||||
|
CATCH_CONFIG_DISABLE_EXCEPTIONS
|
||||||
|
|
||||||
|
Note that when using Catch2 without exceptions, there are 2 major
|
||||||
|
limitations:
|
||||||
|
|
||||||
|
1) If there is an error that would normally be signalled by an exception,
|
||||||
|
the exception's message will instead be written to `Catch::cerr` and
|
||||||
|
`std::terminate` will be called.
|
||||||
|
2) If an assertion from the `REQUIRE` family of macros fails,
|
||||||
|
`std::terminate` will be called after the active reporter returns.
|
||||||
|
|
||||||
|
|
||||||
|
There is also a customization point for the exact behaviour of what
|
||||||
|
happens instead of exception being thrown. To use it, define
|
||||||
|
|
||||||
|
CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER
|
||||||
|
|
||||||
|
and provide a definition for this function:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace Catch {
|
||||||
|
[[noreturn]]
|
||||||
|
void throw_exception(std::exception const&);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[Home](Readme.md#top)
|
[Home](Readme.md#top)
|
||||||
|
50
docs/generators.md
Normal file
50
docs/generators.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<a id="top"></a>
|
||||||
|
# Data Generators
|
||||||
|
|
||||||
|
_Generators are currently considered an experimental feature and their
|
||||||
|
API can change between versions freely._
|
||||||
|
|
||||||
|
Data generators (also known as _data driven/parametrized test cases_)
|
||||||
|
let you reuse the same set of assertions across different input values.
|
||||||
|
In Catch2, this means that they respect the ordering and nesting
|
||||||
|
of the `TEST_CASE` and `SECTION` macros.
|
||||||
|
|
||||||
|
How does combining generators and test cases work might be better
|
||||||
|
explained by an example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
TEST_CASE("Generators") {
|
||||||
|
auto i = GENERATE( range(1, 11) );
|
||||||
|
|
||||||
|
SECTION( "Some section" ) {
|
||||||
|
auto j = GENERATE( range( 11, 21 ) );
|
||||||
|
REQUIRE(i < j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
the assertion will be checked 100 times, because there are 10 possible
|
||||||
|
values for `i` (1, 2, ..., 10) and for each of them, there are 10 possible
|
||||||
|
values for `j` (11, 12, ..., 20).
|
||||||
|
|
||||||
|
You can also combine multiple generators by concatenation:
|
||||||
|
```cpp
|
||||||
|
static int square(int x) { return x * x; }
|
||||||
|
TEST_CASE("Generators 2") {
|
||||||
|
auto i = GENERATE(0, 1, -1, range(-20, -10), range(10, 20));
|
||||||
|
CAPTURE(i);
|
||||||
|
REQUIRE(square(i) >= 0);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This will call `square` with arguments `0`, `1`, `-1`, `-20`, ..., `-11`,
|
||||||
|
`10`, ..., `19`.
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
|
Because of the experimental nature of the current Generator implementation,
|
||||||
|
we won't list all of the first-party generators in Catch2. Instead you
|
||||||
|
should look at our current usage tests in
|
||||||
|
[projects/SelfTest/UsageTests/Generators.tests.cpp](/projects/SelfTest/UsageTests/Generators.tests.cpp).
|
||||||
|
For implementing your own generators, you can look at their implementation in
|
||||||
|
[include/internal/catch_generators.hpp](/include/internal/catch_generators.hpp).
|
@@ -36,7 +36,7 @@ The next-generation core storage and query engine for Couchbase Lite
|
|||||||
A High-performance Cluster Computing Engine
|
A High-performance Cluster Computing Engine
|
||||||
|
|
||||||
### [forest](https://github.com/xorz57/forest)
|
### [forest](https://github.com/xorz57/forest)
|
||||||
Forest is an open-source, template library of tree data structures written in C++11.
|
Template Library of Tree Data Structures
|
||||||
|
|
||||||
### [Fuxedo](https://github.com/fuxedo/fuxedo)
|
### [Fuxedo](https://github.com/fuxedo/fuxedo)
|
||||||
Open source Oracle Tuxedo-like XATMI middleware for C and C++.
|
Open source Oracle Tuxedo-like XATMI middleware for C and C++.
|
||||||
@@ -71,6 +71,9 @@ A C++ client library for Consul. Consul is a distributed tool for discovering an
|
|||||||
### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp)
|
### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp)
|
||||||
A library of algorithms for values-distributed-in-time
|
A library of algorithms for values-distributed-in-time
|
||||||
|
|
||||||
|
### [thor](https://github.com/xorz57/thor)
|
||||||
|
Wrapper Library for CUDA
|
||||||
|
|
||||||
### [TextFlowCpp](https://github.com/philsquared/textflowcpp)
|
### [TextFlowCpp](https://github.com/philsquared/textflowcpp)
|
||||||
A small, single-header-only, library for wrapping and composing columns of text
|
A small, single-header-only, library for wrapping and composing columns of text
|
||||||
|
|
||||||
|
@@ -1,5 +1,34 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
|
|
||||||
|
# 2.4.0
|
||||||
|
|
||||||
|
**This release brings two new experimental features, generator support
|
||||||
|
and a `-fno-exceptions` support. Being experimental means that they
|
||||||
|
will not be subject to the usual stability guarantees provided by semver.**
|
||||||
|
|
||||||
|
## Improvements
|
||||||
|
* Various small runtime performance improvements
|
||||||
|
* `CAPTURE` macro is now variadic
|
||||||
|
* Added `AND_GIVEN` macro (#1360)
|
||||||
|
* Added experimental support for data generators
|
||||||
|
* See [their documentation](generators.md) for details
|
||||||
|
* Added support for compiling and running Catch without exceptions
|
||||||
|
* Doing so limits the functionality somewhat
|
||||||
|
* Look [into the documentation](configuration.md#disablingexceptions) for details
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
* Suppressed `-Wnon-virtual-dtor` warnings in Matchers (#1357)
|
||||||
|
* Suppressed `-Wunreachable-code` warnings in floating point matchers (#1350)
|
||||||
|
|
||||||
|
## CMake
|
||||||
|
* It is now possible to override which Python is used to run Catch's tests (#1365)
|
||||||
|
* Catch now provides infrastructure for adding tests that check compile-time configuration
|
||||||
|
* Catch no longer tries to install itself when used as a subproject (#1373)
|
||||||
|
* Catch2ConfigVersion.cmake is now generated as arch-independent (#1368)
|
||||||
|
* This means that installing Catch from 32-bit machine and copying it to 64-bit one works
|
||||||
|
* This fixes conan installation of Catch
|
||||||
|
|
||||||
|
|
||||||
# 2.3.0
|
# 2.3.0
|
||||||
|
|
||||||
**This release changes the include paths provided by our CMake and
|
**This release changes the include paths provided by our CMake and
|
||||||
|
@@ -85,6 +85,7 @@ foreach( name ${TARGETS_ALL} )
|
|||||||
target_include_directories( ${name} PRIVATE ${HEADER_DIR} )
|
target_include_directories( ${name} PRIVATE ${HEADER_DIR} )
|
||||||
|
|
||||||
set_property(TARGET ${name} PROPERTY CXX_STANDARD 11)
|
set_property(TARGET ${name} PROPERTY CXX_STANDARD 11)
|
||||||
|
set_property(TARGET ${name} PROPERTY CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
# Add desired warnings
|
# Add desired warnings
|
||||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
|
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
|
||||||
|
@@ -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 3
|
#define CATCH_VERSION_MINOR 4
|
||||||
#define CATCH_VERSION_PATCH 0
|
#define CATCH_VERSION_PATCH 0
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
@@ -62,6 +62,7 @@
|
|||||||
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||||
#include "internal/catch_capture_matchers.h"
|
#include "internal/catch_capture_matchers.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "internal/catch_generators.hpp"
|
||||||
|
|
||||||
// These files are included here so the single_include script doesn't put them
|
// These files are included here so the single_include script doesn't put them
|
||||||
// in the conditionally compiled sections
|
// in the conditionally compiled sections
|
||||||
@@ -130,7 +131,7 @@
|
|||||||
|
|
||||||
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
|
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
|
||||||
#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
|
#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
|
||||||
#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
|
#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ )
|
||||||
|
|
||||||
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
|
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
|
||||||
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
||||||
@@ -148,8 +149,9 @@
|
|||||||
#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
|
#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
|
||||||
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
|
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
|
||||||
#define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
|
#define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
|
||||||
|
#define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
|
||||||
#define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
|
#define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
|
||||||
#define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And when: " << desc )
|
#define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
|
||||||
#define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
|
#define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
|
||||||
#define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
|
#define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
|
||||||
|
|
||||||
@@ -190,7 +192,7 @@
|
|||||||
|
|
||||||
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
|
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
|
||||||
#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
|
#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
|
||||||
#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
|
#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )
|
||||||
|
|
||||||
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
|
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
|
||||||
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
||||||
@@ -212,8 +214,9 @@
|
|||||||
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
|
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
|
||||||
|
|
||||||
#define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
|
#define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
|
||||||
|
#define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
|
||||||
#define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
|
#define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
|
||||||
#define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And when: " << desc )
|
#define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
|
||||||
#define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
|
#define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
|
||||||
#define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
|
#define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
|
||||||
|
|
||||||
@@ -276,6 +279,7 @@ using Catch::Detail::Approx;
|
|||||||
#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
|
#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
|
||||||
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
|
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
|
||||||
#define CATCH_GIVEN( desc )
|
#define CATCH_GIVEN( desc )
|
||||||
|
#define CATCH_AND_GIVEN( desc )
|
||||||
#define CATCH_WHEN( desc )
|
#define CATCH_WHEN( desc )
|
||||||
#define CATCH_AND_WHEN( desc )
|
#define CATCH_AND_WHEN( desc )
|
||||||
#define CATCH_THEN( desc )
|
#define CATCH_THEN( desc )
|
||||||
@@ -340,6 +344,7 @@ using Catch::Detail::Approx;
|
|||||||
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
|
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
|
||||||
|
|
||||||
#define GIVEN( desc )
|
#define GIVEN( desc )
|
||||||
|
#define AND_GIVEN( desc )
|
||||||
#define WHEN( desc )
|
#define WHEN( desc )
|
||||||
#define AND_WHEN( desc )
|
#define AND_WHEN( desc )
|
||||||
#define THEN( desc )
|
#define THEN( desc )
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_approx.h"
|
#include "catch_approx.h"
|
||||||
|
#include "catch_enforce.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -54,6 +55,20 @@ namespace Detail {
|
|||||||
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(m_value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Approx::setMargin(double margin) {
|
||||||
|
CATCH_ENFORCE(margin >= 0,
|
||||||
|
"Invalid Approx::margin: " << margin << '.'
|
||||||
|
<< " Approx::Margin has to be non-negative.");
|
||||||
|
m_margin = margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Approx::setEpsilon(double epsilon) {
|
||||||
|
CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0,
|
||||||
|
"Invalid Approx::epsilon: " << epsilon << '.'
|
||||||
|
<< " Approx::epsilon has to be in [0, 1]");
|
||||||
|
m_epsilon = epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace Detail
|
} // end namespace Detail
|
||||||
|
|
||||||
namespace literals {
|
namespace literals {
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
#include "catch_tostring.h"
|
#include "catch_tostring.h"
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Detail {
|
namespace Detail {
|
||||||
@@ -19,6 +18,12 @@ namespace Detail {
|
|||||||
class Approx {
|
class Approx {
|
||||||
private:
|
private:
|
||||||
bool equalityComparisonImpl(double other) const;
|
bool equalityComparisonImpl(double other) const;
|
||||||
|
// Validates the new margin (margin >= 0)
|
||||||
|
// out-of-line to avoid including stdexcept in the header
|
||||||
|
void setMargin(double margin);
|
||||||
|
// Validates the new epsilon (0 < epsilon < 1)
|
||||||
|
// out-of-line to avoid including stdexcept in the header
|
||||||
|
void setEpsilon(double epsilon);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Approx ( double value );
|
explicit Approx ( double value );
|
||||||
@@ -30,9 +35,9 @@ namespace Detail {
|
|||||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||||
Approx operator()( T const& value ) {
|
Approx operator()( T const& value ) {
|
||||||
Approx approx( static_cast<double>(value) );
|
Approx approx( static_cast<double>(value) );
|
||||||
approx.epsilon( m_epsilon );
|
approx.m_epsilon = m_epsilon;
|
||||||
approx.margin( m_margin );
|
approx.m_margin = m_margin;
|
||||||
approx.scale( m_scale );
|
approx.m_scale = m_scale;
|
||||||
return approx;
|
return approx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,27 +90,14 @@ namespace Detail {
|
|||||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||||
Approx& epsilon( T const& newEpsilon ) {
|
Approx& epsilon( T const& newEpsilon ) {
|
||||||
double epsilonAsDouble = static_cast<double>(newEpsilon);
|
double epsilonAsDouble = static_cast<double>(newEpsilon);
|
||||||
if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) {
|
setEpsilon(epsilonAsDouble);
|
||||||
throw std::domain_error
|
|
||||||
( "Invalid Approx::epsilon: " +
|
|
||||||
Catch::Detail::stringify( epsilonAsDouble ) +
|
|
||||||
", Approx::epsilon has to be between 0 and 1" );
|
|
||||||
}
|
|
||||||
m_epsilon = epsilonAsDouble;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||||
Approx& margin( T const& newMargin ) {
|
Approx& margin( T const& newMargin ) {
|
||||||
double marginAsDouble = static_cast<double>(newMargin);
|
double marginAsDouble = static_cast<double>(newMargin);
|
||||||
if( marginAsDouble < 0 ) {
|
setMargin(marginAsDouble);
|
||||||
throw std::domain_error
|
|
||||||
( "Invalid Approx::margin: " +
|
|
||||||
Catch::Detail::stringify( marginAsDouble ) +
|
|
||||||
", Approx::Margin has to be non-negative." );
|
|
||||||
|
|
||||||
}
|
|
||||||
m_margin = marginAsDouble;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,7 +52,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AssertionHandler::AssertionHandler
|
AssertionHandler::AssertionHandler
|
||||||
( StringRef macroName,
|
( StringRef const& macroName,
|
||||||
SourceLineInfo const& lineInfo,
|
SourceLineInfo const& lineInfo,
|
||||||
StringRef capturedExpression,
|
StringRef capturedExpression,
|
||||||
ResultDisposition::Flags resultDisposition )
|
ResultDisposition::Flags resultDisposition )
|
||||||
@@ -81,8 +81,13 @@ namespace Catch {
|
|||||||
// (To go back to the test and change execution, jump over the throw, next)
|
// (To go back to the test and change execution, jump over the throw, next)
|
||||||
CATCH_BREAK_INTO_DEBUGGER();
|
CATCH_BREAK_INTO_DEBUGGER();
|
||||||
}
|
}
|
||||||
if( m_reaction.shouldThrow )
|
if (m_reaction.shouldThrow) {
|
||||||
|
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||||
throw Catch::TestFailureException();
|
throw Catch::TestFailureException();
|
||||||
|
#else
|
||||||
|
CATCH_ERROR( "Test failure requires aborting test!" );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void AssertionHandler::setCompleted() {
|
void AssertionHandler::setCompleted() {
|
||||||
m_completed = true;
|
m_completed = true;
|
||||||
@@ -109,7 +114,7 @@ namespace Catch {
|
|||||||
|
|
||||||
// This is the overload that takes a string and infers the Equals matcher from it
|
// This is the overload that takes a string and infers the Equals matcher from it
|
||||||
// The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
|
// The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
|
||||||
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ) {
|
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ) {
|
||||||
handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );
|
handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -49,7 +49,7 @@ namespace Catch {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
AssertionHandler
|
AssertionHandler
|
||||||
( StringRef macroName,
|
( StringRef const& macroName,
|
||||||
SourceLineInfo const& lineInfo,
|
SourceLineInfo const& lineInfo,
|
||||||
StringRef capturedExpression,
|
StringRef capturedExpression,
|
||||||
ResultDisposition::Flags resultDisposition );
|
ResultDisposition::Flags resultDisposition );
|
||||||
@@ -81,7 +81,7 @@ namespace Catch {
|
|||||||
auto allowThrows() const -> bool;
|
auto allowThrows() const -> bool;
|
||||||
};
|
};
|
||||||
|
|
||||||
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString );
|
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString );
|
||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
|
@@ -9,8 +9,9 @@
|
|||||||
#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
|
||||||
|
|
||||||
#include "catch_assertionhandler.h"
|
#include "catch_assertionhandler.h"
|
||||||
#include "catch_message.h"
|
|
||||||
#include "catch_interfaces_capture.h"
|
#include "catch_interfaces_capture.h"
|
||||||
|
#include "catch_message.h"
|
||||||
|
#include "catch_stringref.h"
|
||||||
|
|
||||||
#if !defined(CATCH_CONFIG_DISABLE)
|
#if !defined(CATCH_CONFIG_DISABLE)
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@
|
|||||||
#define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
|
#define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_FAST_COMPILE)
|
#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
|
// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
|
||||||
@@ -40,7 +41,7 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
|
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
|
||||||
do { \
|
do { \
|
||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
|
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
|
||||||
INTERNAL_CATCH_TRY { \
|
INTERNAL_CATCH_TRY { \
|
||||||
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
||||||
catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
|
catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
|
||||||
@@ -63,7 +64,7 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
|
#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
|
||||||
do { \
|
do { \
|
||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
|
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
|
||||||
try { \
|
try { \
|
||||||
static_cast<void>(__VA_ARGS__); \
|
static_cast<void>(__VA_ARGS__); \
|
||||||
catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
|
catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
|
||||||
@@ -77,7 +78,7 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
|
#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
|
||||||
do { \
|
do { \
|
||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
|
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
|
||||||
if( catchAssertionHandler.allowThrows() ) \
|
if( catchAssertionHandler.allowThrows() ) \
|
||||||
try { \
|
try { \
|
||||||
static_cast<void>(__VA_ARGS__); \
|
static_cast<void>(__VA_ARGS__); \
|
||||||
@@ -94,7 +95,7 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
|
#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
|
||||||
do { \
|
do { \
|
||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
|
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
|
||||||
if( catchAssertionHandler.allowThrows() ) \
|
if( catchAssertionHandler.allowThrows() ) \
|
||||||
try { \
|
try { \
|
||||||
static_cast<void>(expr); \
|
static_cast<void>(expr); \
|
||||||
@@ -115,27 +116,32 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
|
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
|
||||||
do { \
|
do { \
|
||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
|
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
|
||||||
catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
|
catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( false )
|
} while( false )
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
|
||||||
|
auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \
|
||||||
|
varName.captureValues( 0, __VA_ARGS__ )
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_INFO( macroName, log ) \
|
#define INTERNAL_CATCH_INFO( macroName, log ) \
|
||||||
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
|
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Although this is matcher-based, it can be used with just a string
|
// Although this is matcher-based, it can be used with just a string
|
||||||
#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
|
#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
|
||||||
do { \
|
do { \
|
||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
|
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
|
||||||
if( catchAssertionHandler.allowThrows() ) \
|
if( catchAssertionHandler.allowThrows() ) \
|
||||||
try { \
|
try { \
|
||||||
static_cast<void>(__VA_ARGS__); \
|
static_cast<void>(__VA_ARGS__); \
|
||||||
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
|
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
|
||||||
} \
|
} \
|
||||||
catch( ... ) { \
|
catch( ... ) { \
|
||||||
Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \
|
Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
catchAssertionHandler.handleThrowingCallSkipped(); \
|
catchAssertionHandler.handleThrowingCallSkipped(); \
|
||||||
|
@@ -15,7 +15,7 @@ namespace Catch {
|
|||||||
// This is the general overload that takes a any string matcher
|
// This is the general overload that takes a any string matcher
|
||||||
// There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
|
// There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
|
||||||
// the Equals matcher (so the header does not mention matchers)
|
// the Equals matcher (so the header does not mention matchers)
|
||||||
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) {
|
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) {
|
||||||
std::string exceptionMessage = Catch::translateActiveException();
|
std::string exceptionMessage = Catch::translateActiveException();
|
||||||
MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
|
MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
|
||||||
handler.handleExpr( expr );
|
handler.handleExpr( expr );
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#include "catch_matchers_generic.hpp"
|
#include "catch_matchers_generic.hpp"
|
||||||
#include "catch_matchers_string.h"
|
#include "catch_matchers_string.h"
|
||||||
#include "catch_matchers_vector.h"
|
#include "catch_matchers_vector.h"
|
||||||
|
#include "catch_stringref.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ namespace Catch {
|
|||||||
MatcherT m_matcher;
|
MatcherT m_matcher;
|
||||||
StringRef m_matcherString;
|
StringRef m_matcherString;
|
||||||
public:
|
public:
|
||||||
MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString )
|
MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString )
|
||||||
: ITransientExpression{ true, matcher.match( arg ) },
|
: ITransientExpression{ true, matcher.match( arg ) },
|
||||||
m_arg( arg ),
|
m_arg( arg ),
|
||||||
m_matcher( matcher ),
|
m_matcher( matcher ),
|
||||||
@@ -42,10 +43,10 @@ namespace Catch {
|
|||||||
|
|
||||||
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
|
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
|
||||||
|
|
||||||
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString );
|
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString );
|
||||||
|
|
||||||
template<typename ArgT, typename MatcherT>
|
template<typename ArgT, typename MatcherT>
|
||||||
auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr<ArgT, MatcherT> {
|
auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> {
|
||||||
return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
|
return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,9 +56,9 @@ namespace Catch {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
|
#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
|
||||||
do { \
|
do { \
|
||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
|
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
|
||||||
INTERNAL_CATCH_TRY { \
|
INTERNAL_CATCH_TRY { \
|
||||||
catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \
|
catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \
|
||||||
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
|
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( false )
|
} while( false )
|
||||||
@@ -66,14 +67,14 @@ namespace Catch {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
|
#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
|
||||||
do { \
|
do { \
|
||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
|
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
|
||||||
if( catchAssertionHandler.allowThrows() ) \
|
if( catchAssertionHandler.allowThrows() ) \
|
||||||
try { \
|
try { \
|
||||||
static_cast<void>(__VA_ARGS__ ); \
|
static_cast<void>(__VA_ARGS__ ); \
|
||||||
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
|
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
|
||||||
} \
|
} \
|
||||||
catch( exceptionType const& ex ) { \
|
catch( exceptionType const& ex ) { \
|
||||||
catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \
|
catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \
|
||||||
} \
|
} \
|
||||||
catch( ... ) { \
|
catch( ... ) { \
|
||||||
catchAssertionHandler.handleUnexpectedInflightException(); \
|
catchAssertionHandler.handleUnexpectedInflightException(); \
|
||||||
|
@@ -22,7 +22,9 @@ namespace Catch {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
|
bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
|
||||||
return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
|
// We can assume that the same file will usually have the same pointer.
|
||||||
|
// Thus, if the pointers are the same, there is no point in calling the strcmp
|
||||||
|
return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
|
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
|
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
|
||||||
// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
|
// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
|
||||||
// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
|
// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
|
||||||
|
// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?
|
||||||
// ****************
|
// ****************
|
||||||
// Note to maintainers: if new toggles are added please document them
|
// Note to maintainers: if new toggles are added please document them
|
||||||
// in configuration.md, too
|
// in configuration.md, too
|
||||||
@@ -131,7 +132,12 @@
|
|||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Check if we are compiled with -fno-exceptions or equivalent
|
||||||
|
#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
|
||||||
|
# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// DJGPP
|
// DJGPP
|
||||||
#ifdef __DJGPP__
|
#ifdef __DJGPP__
|
||||||
# define CATCH_INTERNAL_CONFIG_NO_WCHAR
|
# define CATCH_INTERNAL_CONFIG_NO_WCHAR
|
||||||
@@ -179,6 +185,10 @@
|
|||||||
# define CATCH_CONFIG_NEW_CAPTURE
|
# define CATCH_CONFIG_NEW_CAPTURE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||||
|
# define CATCH_CONFIG_DISABLE_EXCEPTIONS
|
||||||
|
#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
|
||||||
@@ -192,6 +202,16 @@
|
|||||||
# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
|
# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||||
|
#define CATCH_TRY if ((true))
|
||||||
|
#define CATCH_CATCH_ALL if ((false))
|
||||||
|
#define CATCH_CATCH_ANON(type) if ((false))
|
||||||
|
#else
|
||||||
|
#define CATCH_TRY try
|
||||||
|
#define CATCH_CATCH_ALL catch (...)
|
||||||
|
#define CATCH_CATCH_ANON(type) catch (type)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
|
||||||
|
|
||||||
|
19
include/internal/catch_enforce.cpp
Normal file
19
include/internal/catch_enforce.cpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Created by Martin on 03/09/2018.
|
||||||
|
*
|
||||||
|
* 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_enforce.h"
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
|
||||||
|
[[noreturn]]
|
||||||
|
void throw_exception(std::exception const& e) {
|
||||||
|
Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n"
|
||||||
|
<< "The message was: " << e.what() << '\n';
|
||||||
|
std::terminate();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // namespace Catch;
|
@@ -8,17 +8,35 @@
|
|||||||
#define TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED
|
||||||
|
|
||||||
#include "catch_common.h"
|
#include "catch_common.h"
|
||||||
|
#include "catch_compiler_capabilities.h"
|
||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
|
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||||
|
template <typename Ex>
|
||||||
|
[[noreturn]]
|
||||||
|
void throw_exception(Ex const& e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
#else // ^^ Exceptions are enabled // Exceptions are disabled vv
|
||||||
|
[[noreturn]]
|
||||||
|
void throw_exception(std::exception const& e);
|
||||||
|
#endif
|
||||||
|
} // namespace Catch;
|
||||||
|
|
||||||
#define CATCH_PREPARE_EXCEPTION( type, msg ) \
|
#define CATCH_PREPARE_EXCEPTION( type, msg ) \
|
||||||
type( ( Catch::ReusableStringStream() << msg ).str() )
|
type( ( Catch::ReusableStringStream() << msg ).str() )
|
||||||
#define CATCH_INTERNAL_ERROR( msg ) \
|
#define CATCH_INTERNAL_ERROR( msg ) \
|
||||||
throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg);
|
Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg))
|
||||||
#define CATCH_ERROR( msg ) \
|
#define CATCH_ERROR( msg ) \
|
||||||
throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg )
|
Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg ))
|
||||||
|
#define CATCH_RUNTIME_ERROR( msg ) \
|
||||||
|
Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg ))
|
||||||
#define CATCH_ENFORCE( condition, msg ) \
|
#define CATCH_ENFORCE( condition, msg ) \
|
||||||
do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
|
do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
|
||||||
|
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED
|
||||||
|
@@ -6,8 +6,10 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_assertionhandler.h"
|
|
||||||
#include "catch_exception_translator_registry.h"
|
#include "catch_exception_translator_registry.h"
|
||||||
|
#include "catch_assertionhandler.h"
|
||||||
|
#include "catch_compiler_capabilities.h"
|
||||||
|
#include "catch_enforce.h"
|
||||||
|
|
||||||
#ifdef __OBJC__
|
#ifdef __OBJC__
|
||||||
#import "Foundation/Foundation.h"
|
#import "Foundation/Foundation.h"
|
||||||
@@ -22,6 +24,7 @@ namespace Catch {
|
|||||||
m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
|
m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||||
std::string ExceptionTranslatorRegistry::translateActiveException() const {
|
std::string ExceptionTranslatorRegistry::translateActiveException() const {
|
||||||
try {
|
try {
|
||||||
#ifdef __OBJC__
|
#ifdef __OBJC__
|
||||||
@@ -64,6 +67,13 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else // ^^ Exceptions are enabled // Exceptions are disabled vv
|
||||||
|
std::string ExceptionTranslatorRegistry::translateActiveException() const {
|
||||||
|
CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
std::string ExceptionTranslatorRegistry::tryTranslators() const {
|
std::string ExceptionTranslatorRegistry::tryTranslators() const {
|
||||||
if( m_translators.empty() )
|
if( m_translators.empty() )
|
||||||
std::rethrow_exception(std::current_exception());
|
std::rethrow_exception(std::current_exception());
|
||||||
|
50
include/internal/catch_generators.cpp
Normal file
50
include/internal/catch_generators.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Created by Phil Nash on 15/6/2018.
|
||||||
|
*
|
||||||
|
* 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_generators.hpp"
|
||||||
|
#include "catch_random_number_generator.h"
|
||||||
|
#include "catch_interfaces_capture.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
IGeneratorTracker::~IGeneratorTracker() {}
|
||||||
|
|
||||||
|
namespace Generators {
|
||||||
|
|
||||||
|
GeneratorBase::~GeneratorBase() {}
|
||||||
|
|
||||||
|
std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize ) {
|
||||||
|
|
||||||
|
assert( selectionSize <= sourceSize );
|
||||||
|
std::vector<size_t> indices;
|
||||||
|
indices.reserve( selectionSize );
|
||||||
|
std::uniform_int_distribution<size_t> uid( 0, sourceSize-1 );
|
||||||
|
|
||||||
|
std::set<size_t> seen;
|
||||||
|
// !TBD: improve this algorithm
|
||||||
|
while( indices.size() < selectionSize ) {
|
||||||
|
auto index = uid( rng() );
|
||||||
|
if( seen.insert( index ).second )
|
||||||
|
indices.push_back( index );
|
||||||
|
}
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
|
||||||
|
return getResultCapture().acquireGeneratorTracker( lineInfo );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
auto all<int>() -> Generator<int> {
|
||||||
|
return range( std::numeric_limits<int>::min(), std::numeric_limits<int>::max() );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Generators
|
||||||
|
} // namespace Catch
|
253
include/internal/catch_generators.hpp
Normal file
253
include/internal/catch_generators.hpp
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
* Created by Phil Nash on 15/6/2018.
|
||||||
|
*
|
||||||
|
* 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_GENERATORS_HPP_INCLUDED
|
||||||
|
#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "catch_interfaces_generatortracker.h"
|
||||||
|
#include "catch_common.h"
|
||||||
|
#include "catch_enforce.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
namespace Generators {
|
||||||
|
|
||||||
|
// !TBD move this into its own location?
|
||||||
|
namespace pf{
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
std::unique_ptr<T> make_unique( Args&&... args ) {
|
||||||
|
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct IGenerator {
|
||||||
|
virtual ~IGenerator() {}
|
||||||
|
virtual auto get( size_t index ) const -> T = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class SingleValueGenerator : public IGenerator<T> {
|
||||||
|
T m_value;
|
||||||
|
public:
|
||||||
|
SingleValueGenerator( T const& value ) : m_value( value ) {}
|
||||||
|
|
||||||
|
auto get( size_t ) const -> T override {
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class FixedValuesGenerator : public IGenerator<T> {
|
||||||
|
std::vector<T> m_values;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
|
||||||
|
|
||||||
|
auto get( size_t index ) const -> T override {
|
||||||
|
return m_values[index];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class RangeGenerator : public IGenerator<T> {
|
||||||
|
T const m_first;
|
||||||
|
T const m_last;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RangeGenerator( T const& first, T const& last ) : m_first( first ), m_last( last ) {
|
||||||
|
assert( m_last > m_first );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto get( size_t index ) const -> T override {
|
||||||
|
// ToDo:: introduce a safe cast to catch potential overflows
|
||||||
|
return static_cast<T>(m_first+index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct NullGenerator : IGenerator<T> {
|
||||||
|
auto get( size_t ) const -> T override {
|
||||||
|
CATCH_INTERNAL_ERROR("A Null Generator is always empty");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Generator {
|
||||||
|
std::unique_ptr<IGenerator<T>> m_generator;
|
||||||
|
size_t m_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Generator( size_t size, std::unique_ptr<IGenerator<T>> generator )
|
||||||
|
: m_generator( std::move( generator ) ),
|
||||||
|
m_size( size )
|
||||||
|
{}
|
||||||
|
|
||||||
|
auto size() const -> size_t { return m_size; }
|
||||||
|
auto operator[]( size_t index ) const -> T {
|
||||||
|
assert( index < m_size );
|
||||||
|
return m_generator->get( index );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize );
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class GeneratorRandomiser : public IGenerator<T> {
|
||||||
|
Generator<T> m_baseGenerator;
|
||||||
|
|
||||||
|
std::vector<size_t> m_indices;
|
||||||
|
public:
|
||||||
|
GeneratorRandomiser( Generator<T>&& baseGenerator, size_t numberOfItems )
|
||||||
|
: m_baseGenerator( std::move( baseGenerator ) ),
|
||||||
|
m_indices( randomiseIndices( numberOfItems, m_baseGenerator.size() ) )
|
||||||
|
{}
|
||||||
|
|
||||||
|
auto get( size_t index ) const -> T override {
|
||||||
|
return m_baseGenerator[m_indices[index]];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct RequiresASpecialisationFor;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto all() -> Generator<T> { return RequiresASpecialisationFor<T>(); }
|
||||||
|
|
||||||
|
template<>
|
||||||
|
auto all<int>() -> Generator<int>;
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto range( T const& first, T const& last ) -> Generator<T> {
|
||||||
|
return Generator<T>( (last-first), pf::make_unique<RangeGenerator<T>>( first, last ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto random( T const& first, T const& last ) -> Generator<T> {
|
||||||
|
auto gen = range( first, last );
|
||||||
|
auto size = gen.size();
|
||||||
|
|
||||||
|
return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( std::move( gen ), size ) );
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
auto random( size_t size ) -> Generator<T> {
|
||||||
|
return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( all<T>(), size ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto values( std::initializer_list<T> values ) -> Generator<T> {
|
||||||
|
return Generator<T>( values.size(), pf::make_unique<FixedValuesGenerator<T>>( values ) );
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
auto value( T const& val ) -> Generator<T> {
|
||||||
|
return Generator<T>( 1, pf::make_unique<SingleValueGenerator<T>>( val ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto as() -> Generator<T> {
|
||||||
|
return Generator<T>( 0, pf::make_unique<NullGenerator<T>>() );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
auto table( std::initializer_list<std::tuple<Ts...>>&& tuples ) -> Generator<std::tuple<Ts...>> {
|
||||||
|
return values<std::tuple<Ts...>>( std::forward<std::initializer_list<std::tuple<Ts...>>>( tuples ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Generators : GeneratorBase {
|
||||||
|
std::vector<Generator<T>> m_generators;
|
||||||
|
|
||||||
|
using type = T;
|
||||||
|
|
||||||
|
Generators() : GeneratorBase( 0 ) {}
|
||||||
|
|
||||||
|
void populate( T&& val ) {
|
||||||
|
m_size += 1;
|
||||||
|
m_generators.emplace_back( value( std::move( val ) ) );
|
||||||
|
}
|
||||||
|
template<typename U>
|
||||||
|
void populate( U&& val ) {
|
||||||
|
populate( T( std::move( val ) ) );
|
||||||
|
}
|
||||||
|
void populate( Generator<T>&& generator ) {
|
||||||
|
m_size += generator.size();
|
||||||
|
m_generators.emplace_back( std::move( generator ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U, typename... Gs>
|
||||||
|
void populate( U&& valueOrGenerator, Gs... moreGenerators ) {
|
||||||
|
populate( std::forward<U>( valueOrGenerator ) );
|
||||||
|
populate( std::forward<Gs>( moreGenerators )... );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto operator[]( size_t index ) const -> T {
|
||||||
|
size_t sizes = 0;
|
||||||
|
for( auto const& gen : m_generators ) {
|
||||||
|
auto localIndex = index-sizes;
|
||||||
|
sizes += gen.size();
|
||||||
|
if( index < sizes )
|
||||||
|
return gen[localIndex];
|
||||||
|
}
|
||||||
|
CATCH_INTERNAL_ERROR("Index '" << index << "' is out of range (" << sizes << ')');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename... Gs>
|
||||||
|
auto makeGenerators( Generator<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
|
||||||
|
Generators<T> generators;
|
||||||
|
generators.m_generators.reserve( 1+sizeof...(Gs) );
|
||||||
|
generators.populate( std::move( generator ), std::forward<Gs>( moreGenerators )... );
|
||||||
|
return generators;
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
auto makeGenerators( Generator<T>&& generator ) -> Generators<T> {
|
||||||
|
Generators<T> generators;
|
||||||
|
generators.populate( std::move( generator ) );
|
||||||
|
return generators;
|
||||||
|
}
|
||||||
|
template<typename T, typename... Gs>
|
||||||
|
auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
|
||||||
|
return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
|
||||||
|
}
|
||||||
|
template<typename T, typename U, typename... Gs>
|
||||||
|
auto makeGenerators( U&& val, Gs... moreGenerators ) -> Generators<T> {
|
||||||
|
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
|
||||||
|
|
||||||
|
template<typename L>
|
||||||
|
// Note: The type after -> is weird, because VS2015 cannot parse
|
||||||
|
// the expression used in the typedef inside, when it is in
|
||||||
|
// return type. Yeah, ¯\_(ツ)_/¯
|
||||||
|
auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>()[0]) {
|
||||||
|
using UnderlyingType = typename decltype(generatorExpression())::type;
|
||||||
|
|
||||||
|
IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
|
||||||
|
if( !tracker.hasGenerator() )
|
||||||
|
tracker.setGenerator( pf::make_unique<Generators<UnderlyingType>>( generatorExpression() ) );
|
||||||
|
|
||||||
|
auto const& generator = static_cast<Generators<UnderlyingType> const&>( *tracker.getGenerator() );
|
||||||
|
return generator[tracker.getIndex()];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Generators
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
#define GENERATE( ... ) \
|
||||||
|
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
|
@@ -24,8 +24,10 @@ namespace Catch {
|
|||||||
struct BenchmarkInfo;
|
struct BenchmarkInfo;
|
||||||
struct BenchmarkStats;
|
struct BenchmarkStats;
|
||||||
struct AssertionReaction;
|
struct AssertionReaction;
|
||||||
|
struct SourceLineInfo;
|
||||||
|
|
||||||
struct ITransientExpression;
|
struct ITransientExpression;
|
||||||
|
struct IGeneratorTracker;
|
||||||
|
|
||||||
struct IResultCapture {
|
struct IResultCapture {
|
||||||
|
|
||||||
@@ -36,6 +38,8 @@ namespace Catch {
|
|||||||
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
|
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
|
||||||
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
|
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
|
||||||
|
|
||||||
|
virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;
|
||||||
|
|
||||||
virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
|
virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
|
||||||
virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0;
|
virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0;
|
||||||
|
|
||||||
|
39
include/internal/catch_interfaces_generatortracker.h
Normal file
39
include/internal/catch_interfaces_generatortracker.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Created by Phil Nash on 26/6/2018.
|
||||||
|
*
|
||||||
|
* 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_INTERFACES_GENERATORTRACKER_INCLUDED
|
||||||
|
#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORTRACKER_INCLUDED
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
namespace Generators {
|
||||||
|
class GeneratorBase {
|
||||||
|
protected:
|
||||||
|
size_t m_size = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GeneratorBase( size_t size ) : m_size( size ) {}
|
||||||
|
virtual ~GeneratorBase();
|
||||||
|
auto size() const -> size_t { return m_size; }
|
||||||
|
};
|
||||||
|
using GeneratorBasePtr = std::unique_ptr<GeneratorBase>;
|
||||||
|
|
||||||
|
} // namespace Generators
|
||||||
|
|
||||||
|
struct IGeneratorTracker {
|
||||||
|
virtual ~IGeneratorTracker();
|
||||||
|
virtual auto hasGenerator() const -> bool = 0;
|
||||||
|
virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
|
||||||
|
virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
|
||||||
|
virtual auto getIndex() const -> std::size_t = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
#endif //TWOBLUECUBES_CATCH_INTERFACES_GENERATORTRACKER_INCLUDED
|
@@ -33,7 +33,7 @@ namespace Catch {
|
|||||||
virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
|
virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
|
||||||
virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
|
virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
|
||||||
|
|
||||||
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
|
virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
|
||||||
|
|
||||||
|
|
||||||
virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
|
virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
|
||||||
@@ -49,7 +49,7 @@ namespace Catch {
|
|||||||
virtual void registerStartupException() noexcept = 0;
|
virtual void registerStartupException() noexcept = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
IRegistryHub& getRegistryHub();
|
IRegistryHub const& getRegistryHub();
|
||||||
IMutableRegistryHub& getMutableRegistryHub();
|
IMutableRegistryHub& getMutableRegistryHub();
|
||||||
void cleanUp();
|
void cleanUp();
|
||||||
std::string translateActiveException();
|
std::string translateActiveException();
|
||||||
|
@@ -34,6 +34,11 @@ namespace Matchers {
|
|||||||
mutable std::string m_cachedToString;
|
mutable std::string m_cachedToString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
# pragma clang diagnostic push
|
||||||
|
# pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename ObjectT>
|
template<typename ObjectT>
|
||||||
struct MatcherMethod {
|
struct MatcherMethod {
|
||||||
virtual bool match( ObjectT const& arg ) const = 0;
|
virtual bool match( ObjectT const& arg ) const = 0;
|
||||||
@@ -43,6 +48,10 @@ namespace Matchers {
|
|||||||
virtual bool match( PtrT* arg ) const = 0;
|
virtual bool match( PtrT* arg ) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
# pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> {
|
struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> {
|
||||||
|
|
||||||
|
@@ -6,13 +6,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_matchers_floating.h"
|
#include "catch_matchers_floating.h"
|
||||||
|
#include "catch_enforce.h"
|
||||||
#include "catch_to_string.hpp"
|
#include "catch_to_string.hpp"
|
||||||
#include "catch_tostring.h"
|
#include "catch_tostring.h"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Matchers {
|
namespace Matchers {
|
||||||
@@ -81,9 +81,8 @@ namespace Matchers {
|
|||||||
namespace Floating {
|
namespace Floating {
|
||||||
WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
|
WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
|
||||||
:m_target{ target }, m_margin{ margin } {
|
:m_target{ target }, m_margin{ margin } {
|
||||||
if (m_margin < 0) {
|
CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.'
|
||||||
throw std::domain_error("Allowed margin difference has to be >= 0");
|
<< " Margin has to be non-negative.");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
|
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
|
||||||
@@ -99,11 +98,16 @@ namespace Floating {
|
|||||||
|
|
||||||
WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
|
WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
|
||||||
:m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
|
:m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
|
||||||
if (m_ulps < 0) {
|
CATCH_ENFORCE(ulps >= 0, "Invalid ULP setting: " << ulps << '.'
|
||||||
throw std::domain_error("Allowed ulp difference has to be >= 0");
|
<< " ULPs have to be non-negative.");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
// Clang <3.5 reports on the default branch in the switch below
|
||||||
|
#pragma clang diagnostic ignored "-Wunreachable-code"
|
||||||
|
#endif
|
||||||
|
|
||||||
bool WithinUlpsMatcher::match(double const& matchee) const {
|
bool WithinUlpsMatcher::match(double const& matchee) const {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case FloatingPointKind::Float:
|
case FloatingPointKind::Float:
|
||||||
@@ -111,10 +115,14 @@ namespace Floating {
|
|||||||
case FloatingPointKind::Double:
|
case FloatingPointKind::Double:
|
||||||
return almostEqualUlps<double>(matchee, m_target, m_ulps);
|
return almostEqualUlps<double>(matchee, m_target, m_ulps);
|
||||||
default:
|
default:
|
||||||
throw std::domain_error("Unknown FloatingPointKind value");
|
CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
std::string WithinUlpsMatcher::describe() const {
|
std::string WithinUlpsMatcher::describe() const {
|
||||||
return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
|
return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
|
||||||
}
|
}
|
||||||
|
@@ -10,9 +10,11 @@
|
|||||||
#include "catch_interfaces_capture.h"
|
#include "catch_interfaces_capture.h"
|
||||||
#include "catch_uncaught_exceptions.h"
|
#include "catch_uncaught_exceptions.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
MessageInfo::MessageInfo( std::string const& _macroName,
|
MessageInfo::MessageInfo( StringRef const& _macroName,
|
||||||
SourceLineInfo const& _lineInfo,
|
SourceLineInfo const& _lineInfo,
|
||||||
ResultWas::OfType _type )
|
ResultWas::OfType _type )
|
||||||
: macroName( _macroName ),
|
: macroName( _macroName ),
|
||||||
@@ -35,7 +37,7 @@ namespace Catch {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Catch::MessageBuilder::MessageBuilder( std::string const& macroName,
|
Catch::MessageBuilder::MessageBuilder( StringRef const& macroName,
|
||||||
SourceLineInfo const& lineInfo,
|
SourceLineInfo const& lineInfo,
|
||||||
ResultWas::OfType type )
|
ResultWas::OfType type )
|
||||||
:m_info(macroName, lineInfo, type) {}
|
:m_info(macroName, lineInfo, type) {}
|
||||||
@@ -55,4 +57,36 @@ namespace Catch {
|
|||||||
getResultCapture().popScopedMessage(m_info);
|
getResultCapture().popScopedMessage(m_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {
|
||||||
|
auto start = std::string::npos;
|
||||||
|
for( size_t pos = 0; pos <= names.size(); ++pos ) {
|
||||||
|
char c = names[pos];
|
||||||
|
if( pos == names.size() || c == ' ' || c == '\t' || c == ',' || c == ']' ) {
|
||||||
|
if( start != std::string::npos ) {
|
||||||
|
m_messages.push_back( MessageInfo( macroName, lineInfo, resultType ) );
|
||||||
|
m_messages.back().message = names.substr( start, pos-start) + " := ";
|
||||||
|
start = std::string::npos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( c != '[' && c != ']' && start == std::string::npos )
|
||||||
|
start = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Capturer::~Capturer() {
|
||||||
|
if ( !uncaught_exceptions() ){
|
||||||
|
assert( m_captured == m_messages.size() );
|
||||||
|
for( size_t i = 0; i < m_captured; ++i )
|
||||||
|
m_resultCapture.popScopedMessage( m_messages[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Capturer::captureValue( size_t index, StringRef value ) {
|
||||||
|
assert( index < m_messages.size() );
|
||||||
|
m_messages[index].message += value;
|
||||||
|
m_resultCapture.pushScopedMessage( m_messages[index] );
|
||||||
|
m_captured++;
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
@@ -8,19 +8,23 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "catch_result_type.h"
|
#include "catch_result_type.h"
|
||||||
#include "catch_common.h"
|
#include "catch_common.h"
|
||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
|
#include "catch_interfaces_capture.h"
|
||||||
|
#include "catch_tostring.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
struct MessageInfo {
|
struct MessageInfo {
|
||||||
MessageInfo( std::string const& _macroName,
|
MessageInfo( StringRef const& _macroName,
|
||||||
SourceLineInfo const& _lineInfo,
|
SourceLineInfo const& _lineInfo,
|
||||||
ResultWas::OfType _type );
|
ResultWas::OfType _type );
|
||||||
|
|
||||||
std::string macroName;
|
StringRef macroName;
|
||||||
std::string message;
|
std::string message;
|
||||||
SourceLineInfo lineInfo;
|
SourceLineInfo lineInfo;
|
||||||
ResultWas::OfType type;
|
ResultWas::OfType type;
|
||||||
@@ -44,7 +48,7 @@ namespace Catch {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct MessageBuilder : MessageStream {
|
struct MessageBuilder : MessageStream {
|
||||||
MessageBuilder( std::string const& macroName,
|
MessageBuilder( StringRef const& macroName,
|
||||||
SourceLineInfo const& lineInfo,
|
SourceLineInfo const& lineInfo,
|
||||||
ResultWas::OfType type );
|
ResultWas::OfType type );
|
||||||
|
|
||||||
@@ -65,6 +69,28 @@ namespace Catch {
|
|||||||
MessageInfo m_info;
|
MessageInfo m_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Capturer {
|
||||||
|
std::vector<MessageInfo> m_messages;
|
||||||
|
IResultCapture& m_resultCapture = getResultCapture();
|
||||||
|
size_t m_captured = 0;
|
||||||
|
public:
|
||||||
|
Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
|
||||||
|
~Capturer();
|
||||||
|
|
||||||
|
void captureValue( size_t index, StringRef value );
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void captureValues( size_t index, T&& value ) {
|
||||||
|
captureValue( index, Catch::Detail::stringify( value ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... Ts>
|
||||||
|
void captureValues( size_t index, T&& value, Ts&&... values ) {
|
||||||
|
captureValues( index, value );
|
||||||
|
captureValues( index+1, values... );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
|
||||||
|
@@ -6,8 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_output_redirect.h"
|
#include "catch_output_redirect.h"
|
||||||
|
#include "catch_enforce.h"
|
||||||
|
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -56,21 +55,21 @@ namespace Catch {
|
|||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
TempFile::TempFile() {
|
TempFile::TempFile() {
|
||||||
if (tmpnam_s(m_buffer)) {
|
if (tmpnam_s(m_buffer)) {
|
||||||
throw std::runtime_error("Could not get a temp filename");
|
CATCH_RUNTIME_ERROR("Could not get a temp filename");
|
||||||
}
|
}
|
||||||
if (fopen_s(&m_file, m_buffer, "w")) {
|
if (fopen_s(&m_file, m_buffer, "w")) {
|
||||||
char buffer[100];
|
char buffer[100];
|
||||||
if (strerror_s(buffer, errno)) {
|
if (strerror_s(buffer, errno)) {
|
||||||
throw std::runtime_error("Could not translate errno to string");
|
CATCH_RUNTIME_ERROR("Could not translate errno to a string");
|
||||||
}
|
}
|
||||||
throw std::runtime_error("Could not open the temp file: " + std::string(m_buffer) + buffer);
|
CATCH_RUNTIME_ERROR("Coul dnot open the temp file: '" << m_buffer << "' because: " << buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
TempFile::TempFile() {
|
TempFile::TempFile() {
|
||||||
m_file = std::tmpfile();
|
m_file = std::tmpfile();
|
||||||
if (!m_file) {
|
if (!m_file) {
|
||||||
throw std::runtime_error("Could not create a temp file.");
|
CATCH_RUNTIME_ERROR("Could not create a temp file.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#include "catch_exception_translator_registry.h"
|
#include "catch_exception_translator_registry.h"
|
||||||
#include "catch_tag_alias_registry.h"
|
#include "catch_tag_alias_registry.h"
|
||||||
#include "catch_startup_exception_registry.h"
|
#include "catch_startup_exception_registry.h"
|
||||||
|
#include "catch_singletons.hpp"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ namespace Catch {
|
|||||||
ITestCaseRegistry const& getTestCaseRegistry() const override {
|
ITestCaseRegistry const& getTestCaseRegistry() const override {
|
||||||
return m_testCaseRegistry;
|
return m_testCaseRegistry;
|
||||||
}
|
}
|
||||||
IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override {
|
IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override {
|
||||||
return m_exceptionTranslatorRegistry;
|
return m_exceptionTranslatorRegistry;
|
||||||
}
|
}
|
||||||
ITagAliasRegistry const& getTagAliasRegistry() const override {
|
ITagAliasRegistry const& getTagAliasRegistry() const override {
|
||||||
@@ -67,27 +68,19 @@ namespace Catch {
|
|||||||
TagAliasRegistry m_tagAliasRegistry;
|
TagAliasRegistry m_tagAliasRegistry;
|
||||||
StartupExceptionRegistry m_exceptionRegistry;
|
StartupExceptionRegistry m_exceptionRegistry;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Single, global, instance
|
|
||||||
RegistryHub*& getTheRegistryHub() {
|
|
||||||
static RegistryHub* theRegistryHub = nullptr;
|
|
||||||
if( !theRegistryHub )
|
|
||||||
theRegistryHub = new RegistryHub();
|
|
||||||
return theRegistryHub;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IRegistryHub& getRegistryHub() {
|
using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
|
||||||
return *getTheRegistryHub();
|
|
||||||
|
IRegistryHub const& getRegistryHub() {
|
||||||
|
return RegistryHubSingleton::get();
|
||||||
}
|
}
|
||||||
IMutableRegistryHub& getMutableRegistryHub() {
|
IMutableRegistryHub& getMutableRegistryHub() {
|
||||||
return *getTheRegistryHub();
|
return RegistryHubSingleton::getMutable();
|
||||||
}
|
}
|
||||||
void cleanUp() {
|
void cleanUp() {
|
||||||
delete getTheRegistryHub();
|
cleanupSingletons();
|
||||||
getTheRegistryHub() = nullptr;
|
|
||||||
cleanUpContext();
|
cleanUpContext();
|
||||||
ReusableStringStream::cleanup();
|
|
||||||
}
|
}
|
||||||
std::string translateActiveException() {
|
std::string translateActiveException() {
|
||||||
return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
|
return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#include "catch_run_context.h"
|
#include "catch_run_context.h"
|
||||||
|
#include "catch_compiler_capabilities.h"
|
||||||
#include "catch_context.h"
|
#include "catch_context.h"
|
||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
#include "catch_random_number_generator.h"
|
#include "catch_random_number_generator.h"
|
||||||
@@ -11,6 +12,70 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
namespace Generators {
|
||||||
|
struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
|
||||||
|
size_t m_index = static_cast<size_t>( -1 );
|
||||||
|
GeneratorBasePtr m_generator;
|
||||||
|
|
||||||
|
GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||||
|
: TrackerBase( nameAndLocation, ctx, parent )
|
||||||
|
{}
|
||||||
|
~GeneratorTracker();
|
||||||
|
|
||||||
|
static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
|
||||||
|
std::shared_ptr<GeneratorTracker> tracker;
|
||||||
|
|
||||||
|
ITracker& currentTracker = ctx.currentTracker();
|
||||||
|
if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
|
||||||
|
assert( childTracker );
|
||||||
|
assert( childTracker->isIndexTracker() );
|
||||||
|
tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, ¤tTracker );
|
||||||
|
currentTracker.addChild( tracker );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !ctx.completedCycle() && !tracker->isComplete() ) {
|
||||||
|
if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
|
||||||
|
tracker->moveNext();
|
||||||
|
tracker->open();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *tracker;
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveNext() {
|
||||||
|
m_index++;
|
||||||
|
m_children.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrackerBase interface
|
||||||
|
bool isIndexTracker() const override { return true; }
|
||||||
|
auto hasGenerator() const -> bool override {
|
||||||
|
return !!m_generator;
|
||||||
|
}
|
||||||
|
void close() override {
|
||||||
|
TrackerBase::close();
|
||||||
|
if( m_runState == CompletedSuccessfully && m_index < m_generator->size()-1 )
|
||||||
|
m_runState = Executing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IGeneratorTracker interface
|
||||||
|
auto getGenerator() const -> GeneratorBasePtr const& override {
|
||||||
|
return m_generator;
|
||||||
|
}
|
||||||
|
void setGenerator( GeneratorBasePtr&& generator ) override {
|
||||||
|
m_generator = std::move( generator );
|
||||||
|
}
|
||||||
|
auto getIndex() const -> size_t override {
|
||||||
|
return m_index;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
GeneratorTracker::~GeneratorTracker() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
|
RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
|
||||||
: m_runInfo(_config->name()),
|
: m_runInfo(_config->name()),
|
||||||
m_context(getCurrentMutableContext()),
|
m_context(getCurrentMutableContext()),
|
||||||
@@ -128,6 +193,13 @@ namespace Catch {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
|
||||||
|
using namespace Generators;
|
||||||
|
GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) );
|
||||||
|
assert( tracker.isOpen() );
|
||||||
|
m_lastAssertionInfo.lineInfo = lineInfo;
|
||||||
|
return tracker;
|
||||||
|
}
|
||||||
|
|
||||||
bool RunContext::testForMissingAssertions(Counts& assertions) {
|
bool RunContext::testForMissingAssertions(Counts& assertions) {
|
||||||
if (assertions.total() != 0)
|
if (assertions.total() != 0)
|
||||||
@@ -256,7 +328,7 @@ namespace Catch {
|
|||||||
seedRng(*m_config);
|
seedRng(*m_config);
|
||||||
|
|
||||||
Timer timer;
|
Timer timer;
|
||||||
try {
|
CATCH_TRY {
|
||||||
if (m_reporter->getPreferences().shouldRedirectStdOut) {
|
if (m_reporter->getPreferences().shouldRedirectStdOut) {
|
||||||
#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
|
#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
|
||||||
RedirectedStdOut redirectedStdOut;
|
RedirectedStdOut redirectedStdOut;
|
||||||
@@ -276,9 +348,9 @@ namespace Catch {
|
|||||||
invokeActiveTestCase();
|
invokeActiveTestCase();
|
||||||
}
|
}
|
||||||
duration = timer.getElapsedSeconds();
|
duration = timer.getElapsedSeconds();
|
||||||
} catch (TestFailureException&) {
|
} CATCH_CATCH_ANON (TestFailureException&) {
|
||||||
// This just means the test was aborted due to failure
|
// This just means the test was aborted due to failure
|
||||||
} catch (...) {
|
} CATCH_CATCH_ALL {
|
||||||
// Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
|
// Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
|
||||||
// are reported without translation at the point of origin.
|
// are reported without translation at the point of origin.
|
||||||
if( m_shouldReportUnexpected ) {
|
if( m_shouldReportUnexpected ) {
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "catch_interfaces_generatortracker.h"
|
||||||
#include "catch_interfaces_runner.h"
|
#include "catch_interfaces_runner.h"
|
||||||
#include "catch_interfaces_reporter.h"
|
#include "catch_interfaces_reporter.h"
|
||||||
#include "catch_interfaces_exception.h"
|
#include "catch_interfaces_exception.h"
|
||||||
@@ -79,6 +80,8 @@ namespace Catch {
|
|||||||
void sectionEnded( SectionEndInfo const& endInfo ) override;
|
void sectionEnded( SectionEndInfo const& endInfo ) override;
|
||||||
void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
|
void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
|
||||||
|
|
||||||
|
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override;
|
||||||
|
|
||||||
void benchmarkStarting( BenchmarkInfo const& info ) override;
|
void benchmarkStarting( BenchmarkInfo const& info ) override;
|
||||||
void benchmarkEnded( BenchmarkStats const& stats ) override;
|
void benchmarkEnded( BenchmarkStats const& stats ) override;
|
||||||
|
|
||||||
|
@@ -119,10 +119,12 @@ namespace Catch {
|
|||||||
Session::Session() {
|
Session::Session() {
|
||||||
static bool alreadyInstantiated = false;
|
static bool alreadyInstantiated = false;
|
||||||
if( alreadyInstantiated ) {
|
if( alreadyInstantiated ) {
|
||||||
try { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
|
CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
|
||||||
catch(...) { getMutableRegistryHub().registerStartupException(); }
|
CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There cannot be exceptions at startup in no-exception mode.
|
||||||
|
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||||
const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
|
const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
|
||||||
if ( !exceptions.empty() ) {
|
if ( !exceptions.empty() ) {
|
||||||
m_startupExceptions = true;
|
m_startupExceptions = true;
|
||||||
@@ -137,6 +139,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
alreadyInstantiated = true;
|
alreadyInstantiated = true;
|
||||||
m_cli = makeCommandLineParser( m_configData );
|
m_cli = makeCommandLineParser( m_configData );
|
||||||
@@ -251,11 +254,11 @@ namespace Catch {
|
|||||||
if( m_startupExceptions )
|
if( m_startupExceptions )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if( m_configData.showHelp || m_configData.libIdentify )
|
if (m_configData.showHelp || m_configData.libIdentify) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
CATCH_TRY {
|
||||||
{
|
|
||||||
config(); // Force config to be constructed
|
config(); // Force config to be constructed
|
||||||
|
|
||||||
seedRng( *m_config );
|
seedRng( *m_config );
|
||||||
@@ -273,10 +276,12 @@ namespace Catch {
|
|||||||
// of 256 tests has failed
|
// of 256 tests has failed
|
||||||
return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
|
return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
|
||||||
}
|
}
|
||||||
|
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
|
||||||
catch( std::exception& ex ) {
|
catch( std::exception& ex ) {
|
||||||
Catch::cerr() << ex.what() << std::endl;
|
Catch::cerr() << ex.what() << std::endl;
|
||||||
return MaxExitCode;
|
return MaxExitCode;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
36
include/internal/catch_singletons.cpp
Normal file
36
include/internal/catch_singletons.cpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Created by Phil Nash on 15/6/2018.
|
||||||
|
*
|
||||||
|
* 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_singletons.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static auto getSingletons() -> std::vector<ISingleton*>*& {
|
||||||
|
static std::vector<ISingleton*>* g_singletons = nullptr;
|
||||||
|
if( !g_singletons )
|
||||||
|
g_singletons = new std::vector<ISingleton*>();
|
||||||
|
return g_singletons;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ISingleton::~ISingleton() {}
|
||||||
|
|
||||||
|
void addSingleton(ISingleton* singleton ) {
|
||||||
|
getSingletons()->push_back( singleton );
|
||||||
|
}
|
||||||
|
void cleanupSingletons() {
|
||||||
|
auto& singletons = getSingletons();
|
||||||
|
for( auto singleton : *singletons )
|
||||||
|
delete singleton;
|
||||||
|
delete singletons;
|
||||||
|
singletons = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Catch
|
44
include/internal/catch_singletons.hpp
Normal file
44
include/internal/catch_singletons.hpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Created by Phil Nash on 15/6/2018.
|
||||||
|
*
|
||||||
|
* 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_SINGLETONS_HPP_INCLUDED
|
||||||
|
#define TWOBLUECUBES_CATCH_SINGLETONS_HPP_INCLUDED
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
struct ISingleton {
|
||||||
|
virtual ~ISingleton();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void addSingleton( ISingleton* singleton );
|
||||||
|
void cleanupSingletons();
|
||||||
|
|
||||||
|
|
||||||
|
template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
|
||||||
|
class Singleton : SingletonImplT, public ISingleton {
|
||||||
|
|
||||||
|
static auto getInternal() -> Singleton* {
|
||||||
|
static Singleton* s_instance = nullptr;
|
||||||
|
if( !s_instance ) {
|
||||||
|
s_instance = new Singleton;
|
||||||
|
addSingleton( s_instance );
|
||||||
|
}
|
||||||
|
return s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static auto get() -> InterfaceT const& {
|
||||||
|
return *getInternal();
|
||||||
|
}
|
||||||
|
static auto getMutable() -> MutableInterfaceT& {
|
||||||
|
return *getInternal();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
#endif // TWOBLUECUBES_CATCH_SINGLETONS_HPP_INCLUDED
|
@@ -7,13 +7,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_startup_exception_registry.h"
|
#include "catch_startup_exception_registry.h"
|
||||||
|
#include "catch_compiler_capabilities.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
|
void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
|
||||||
try {
|
CATCH_TRY {
|
||||||
m_exceptions.push_back(exception);
|
m_exceptions.push_back(exception);
|
||||||
}
|
} CATCH_CATCH_ALL {
|
||||||
catch(...) {
|
|
||||||
// If we run out of memory during start-up there's really not a lot more we can do about it
|
// If we run out of memory during start-up there's really not a lot more we can do about it
|
||||||
std::terminate();
|
std::terminate();
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
#include "catch_debug_console.h"
|
#include "catch_debug_console.h"
|
||||||
#include "catch_stringref.h"
|
#include "catch_stringref.h"
|
||||||
|
#include "catch_singletons.hpp"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -20,11 +21,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
# pragma clang diagnostic push
|
|
||||||
# pragma clang diagnostic ignored "-Wexit-time-destructors"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
Catch::IStream::~IStream() = default;
|
Catch::IStream::~IStream() = default;
|
||||||
@@ -145,7 +141,6 @@ namespace Catch {
|
|||||||
std::vector<std::unique_ptr<std::ostringstream>> m_streams;
|
std::vector<std::unique_ptr<std::ostringstream>> m_streams;
|
||||||
std::vector<std::size_t> m_unused;
|
std::vector<std::size_t> m_unused;
|
||||||
std::ostringstream m_referenceStream; // Used for copy state/ flags from
|
std::ostringstream m_referenceStream; // Used for copy state/ flags from
|
||||||
static StringStreams* s_instance;
|
|
||||||
|
|
||||||
auto add() -> std::size_t {
|
auto add() -> std::size_t {
|
||||||
if( m_unused.empty() ) {
|
if( m_unused.empty() ) {
|
||||||
@@ -163,34 +158,17 @@ namespace Catch {
|
|||||||
m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
|
m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
|
||||||
m_unused.push_back(index);
|
m_unused.push_back(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// !TBD: put in TLS
|
|
||||||
static auto instance() -> StringStreams& {
|
|
||||||
if( !s_instance )
|
|
||||||
s_instance = new StringStreams();
|
|
||||||
return *s_instance;
|
|
||||||
}
|
|
||||||
static void cleanup() {
|
|
||||||
delete s_instance;
|
|
||||||
s_instance = nullptr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
StringStreams* StringStreams::s_instance = nullptr;
|
|
||||||
|
|
||||||
void ReusableStringStream::cleanup() {
|
|
||||||
StringStreams::cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
ReusableStringStream::ReusableStringStream()
|
ReusableStringStream::ReusableStringStream()
|
||||||
: m_index( StringStreams::instance().add() ),
|
: m_index( Singleton<StringStreams>::getMutable().add() ),
|
||||||
m_oss( StringStreams::instance().m_streams[m_index].get() )
|
m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ReusableStringStream::~ReusableStringStream() {
|
ReusableStringStream::~ReusableStringStream() {
|
||||||
static_cast<std::ostringstream*>( m_oss )->str("");
|
static_cast<std::ostringstream*>( m_oss )->str("");
|
||||||
m_oss->clear();
|
m_oss->clear();
|
||||||
StringStreams::instance().release( m_index );
|
Singleton<StringStreams>::getMutable().release( m_index );
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ReusableStringStream::str() const -> std::string {
|
auto ReusableStringStream::str() const -> std::string {
|
||||||
@@ -207,7 +185,3 @@ namespace Catch {
|
|||||||
std::ostream& clog() { return std::clog; }
|
std::ostream& clog() { return std::clog; }
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
# pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
@@ -43,8 +43,6 @@ namespace Catch {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
auto get() -> std::ostream& { return *m_oss; }
|
auto get() -> std::ostream& { return *m_oss; }
|
||||||
|
|
||||||
static void cleanup();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -127,4 +127,8 @@ namespace Catch {
|
|||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
|
inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
|
||||||
|
return Catch::StringRef( rawChars, size );
|
||||||
|
}
|
||||||
|
|
||||||
#endif // CATCH_STRINGREF_H_INCLUDED
|
#endif // CATCH_STRINGREF_H_INCLUDED
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
#include "catch_tag_alias_autoregistrar.h"
|
#include "catch_tag_alias_autoregistrar.h"
|
||||||
|
#include "catch_compiler_capabilities.h"
|
||||||
#include "catch_interfaces_registry_hub.h"
|
#include "catch_interfaces_registry_hub.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
|
RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
|
||||||
try {
|
CATCH_TRY {
|
||||||
getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
|
getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
|
||||||
} catch (...) {
|
} CATCH_CATCH_ALL {
|
||||||
// Do not throw when constructing global objects, instead register the exception to be processed later
|
// Do not throw when constructing global objects, instead register the exception to be processed later
|
||||||
getMutableRegistryHub().registerStartupException();
|
getMutableRegistryHub().registerStartupException();
|
||||||
}
|
}
|
||||||
|
@@ -69,14 +69,6 @@ namespace TestCaseTracking {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
|
|
||||||
bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) const {
|
|
||||||
return
|
|
||||||
tracker->nameAndLocation().location == m_nameAndLocation.location &&
|
|
||||||
tracker->nameAndLocation().name == m_nameAndLocation.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||||
: m_nameAndLocation( nameAndLocation ),
|
: m_nameAndLocation( nameAndLocation ),
|
||||||
m_ctx( ctx ),
|
m_ctx( ctx ),
|
||||||
@@ -105,7 +97,12 @@ namespace TestCaseTracking {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) {
|
ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) {
|
||||||
auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
|
auto it = std::find_if( m_children.begin(), m_children.end(),
|
||||||
|
[&nameAndLocation]( ITrackerPtr const& tracker ){
|
||||||
|
return
|
||||||
|
tracker->nameAndLocation().location == nameAndLocation.location &&
|
||||||
|
tracker->nameAndLocation().name == nameAndLocation.name;
|
||||||
|
} );
|
||||||
return( it != m_children.end() )
|
return( it != m_children.end() )
|
||||||
? *it
|
? *it
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
@@ -95,13 +95,6 @@ namespace TestCaseTracking {
|
|||||||
Failed
|
Failed
|
||||||
};
|
};
|
||||||
|
|
||||||
class TrackerHasName {
|
|
||||||
NameAndLocation m_nameAndLocation;
|
|
||||||
public:
|
|
||||||
TrackerHasName( NameAndLocation const& nameAndLocation );
|
|
||||||
bool operator ()( ITrackerPtr const& tracker ) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
using Children = std::vector<ITrackerPtr>;
|
using Children = std::vector<ITrackerPtr>;
|
||||||
NameAndLocation m_nameAndLocation;
|
NameAndLocation m_nameAndLocation;
|
||||||
TrackerContext& m_ctx;
|
TrackerContext& m_ctx;
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_test_registry.h"
|
#include "catch_test_registry.h"
|
||||||
|
#include "catch_compiler_capabilities.h"
|
||||||
#include "catch_test_case_registry_impl.h"
|
#include "catch_test_case_registry_impl.h"
|
||||||
#include "catch_interfaces_registry_hub.h"
|
#include "catch_interfaces_registry_hub.h"
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ namespace Catch {
|
|||||||
NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
|
NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
|
||||||
|
|
||||||
AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {
|
AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {
|
||||||
try {
|
CATCH_TRY {
|
||||||
getMutableRegistryHub()
|
getMutableRegistryHub()
|
||||||
.registerTest(
|
.registerTest(
|
||||||
makeTestCase(
|
makeTestCase(
|
||||||
@@ -26,7 +27,7 @@ namespace Catch {
|
|||||||
extractClassName( classOrMethod ),
|
extractClassName( classOrMethod ),
|
||||||
nameAndTags,
|
nameAndTags,
|
||||||
lineInfo));
|
lineInfo));
|
||||||
} catch (...) {
|
} CATCH_CATCH_ALL {
|
||||||
// Do not throw when constructing global objects, instead register the exception to be processed later
|
// Do not throw when constructing global objects, instead register the exception to be processed later
|
||||||
getMutableRegistryHub().registerStartupException();
|
getMutableRegistryHub().registerStartupException();
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Version const& libraryVersion() {
|
Version const& libraryVersion() {
|
||||||
static Version version( 2, 3, 0, "", 0 );
|
static Version version( 2, 4, 0, "", 0 );
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "../internal/catch_enforce.h"
|
||||||
#include "../internal/catch_interfaces_reporter.h"
|
#include "../internal/catch_interfaces_reporter.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -33,7 +34,7 @@ namespace Catch {
|
|||||||
{
|
{
|
||||||
m_reporterPrefs.shouldRedirectStdOut = false;
|
m_reporterPrefs.shouldRedirectStdOut = false;
|
||||||
if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
|
if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
|
||||||
throw std::domain_error( "Verbosity level not supported by this reporter" );
|
CATCH_ERROR( "Verbosity level not supported by this reporter" );
|
||||||
}
|
}
|
||||||
|
|
||||||
ReporterPreferences getPreferences() const override {
|
ReporterPreferences getPreferences() const override {
|
||||||
@@ -148,7 +149,7 @@ namespace Catch {
|
|||||||
{
|
{
|
||||||
m_reporterPrefs.shouldRedirectStdOut = false;
|
m_reporterPrefs.shouldRedirectStdOut = false;
|
||||||
if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
|
if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
|
||||||
throw std::domain_error( "Verbosity level not supported by this reporter" );
|
CATCH_ERROR( "Verbosity level not supported by this reporter" );
|
||||||
}
|
}
|
||||||
~CumulativeReporterBase() override = default;
|
~CumulativeReporterBase() override = default;
|
||||||
|
|
||||||
|
@@ -97,12 +97,12 @@ namespace Catch {
|
|||||||
case ResultWas::Ok:
|
case ResultWas::Ok:
|
||||||
case ResultWas::Info:
|
case ResultWas::Info:
|
||||||
case ResultWas::Warning:
|
case ResultWas::Warning:
|
||||||
throw std::domain_error( "Internal error in TeamCity reporter" );
|
CATCH_ERROR( "Internal error in TeamCity reporter" );
|
||||||
// These cases are here to prevent compiler warnings
|
// These cases are here to prevent compiler warnings
|
||||||
case ResultWas::Unknown:
|
case ResultWas::Unknown:
|
||||||
case ResultWas::FailureBit:
|
case ResultWas::FailureBit:
|
||||||
case ResultWas::Exception:
|
case ResultWas::Exception:
|
||||||
throw std::domain_error( "Not implemented" );
|
CATCH_ERROR( "Not implemented" );
|
||||||
}
|
}
|
||||||
if( assertionStats.infoMessages.size() == 1 )
|
if( assertionStats.infoMessages.size() == 1 )
|
||||||
msg << " with message:";
|
msg << " with message:";
|
||||||
|
23
misc/SelfTest.vcxproj.user
Normal file
23
misc/SelfTest.vcxproj.user
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<UseFullPaths>false</UseFullPaths>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<UseFullPaths>false</UseFullPaths>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<UseFullPaths>false</UseFullPaths>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<UseFullPaths>false</UseFullPaths>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
</Project>
|
@@ -15,7 +15,7 @@ if "%CONFIGURATION%"=="Debug" (
|
|||||||
if "%examples%"=="1" (
|
if "%examples%"=="1" (
|
||||||
@REM # Examples live off the single header, so it needs to be regenerated
|
@REM # Examples live off the single header, so it needs to be regenerated
|
||||||
python scripts\generateSingleHeader.py
|
python scripts\generateSingleHeader.py
|
||||||
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DCATCH_BUILD_EXAMPLES=ON
|
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DCATCH_BUILD_EXAMPLES=ON -DCATCH_BUILD_EXTRA_TESTS=ON
|
||||||
) else (
|
) else (
|
||||||
@REM # This is just a plain debug build
|
@REM # This is just a plain debug build
|
||||||
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain%
|
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain%
|
||||||
|
@@ -1,10 +1,23 @@
|
|||||||
include(MiscFunctions)
|
include(MiscFunctions)
|
||||||
|
|
||||||
|
####
|
||||||
|
# Temporary workaround for VS toolset changes in 2017
|
||||||
|
# We need to disable <UseFullPaths> property, but CMake doesn't support it
|
||||||
|
# until 3.13 (not yet released)
|
||||||
|
####
|
||||||
|
if (MSVC)
|
||||||
|
configure_file(${CATCH_DIR}/misc/SelfTest.vcxproj.user
|
||||||
|
${CMAKE_BINARY_DIR}/projects
|
||||||
|
COPYONLY)
|
||||||
|
endif(MSVC) #Temporary workaround
|
||||||
|
|
||||||
|
|
||||||
# define the sources of the self test
|
# define the sources of the self test
|
||||||
# Please keep these ordered alphabetically
|
# Please keep these ordered alphabetically
|
||||||
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/GeneratorsImpl.tests.cpp
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp
|
${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/TagAlias.tests.cpp
|
${SELF_TEST_DIR}/IntrospectiveTests/TagAlias.tests.cpp
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp
|
${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp
|
||||||
@@ -18,6 +31,7 @@ set(TEST_SOURCES
|
|||||||
${SELF_TEST_DIR}/UsageTests/Decomposition.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/Decomposition.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/EnumToString.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/EnumToString.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/Exception.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/Exception.tests.cpp
|
||||||
|
${SELF_TEST_DIR}/UsageTests/Generators.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/Message.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/Message.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp
|
||||||
@@ -85,6 +99,7 @@ set(INTERNAL_HEADERS
|
|||||||
${HEADER_DIR}/internal/catch_exception_translator_registry.h
|
${HEADER_DIR}/internal/catch_exception_translator_registry.h
|
||||||
${HEADER_DIR}/internal/catch_external_interfaces.h
|
${HEADER_DIR}/internal/catch_external_interfaces.h
|
||||||
${HEADER_DIR}/internal/catch_fatal_condition.h
|
${HEADER_DIR}/internal/catch_fatal_condition.h
|
||||||
|
${HEADER_DIR}/internal/catch_generators.hpp
|
||||||
${HEADER_DIR}/internal/catch_impl.hpp
|
${HEADER_DIR}/internal/catch_impl.hpp
|
||||||
${HEADER_DIR}/internal/catch_interfaces_capture.h
|
${HEADER_DIR}/internal/catch_interfaces_capture.h
|
||||||
${HEADER_DIR}/internal/catch_interfaces_config.h
|
${HEADER_DIR}/internal/catch_interfaces_config.h
|
||||||
@@ -117,6 +132,7 @@ set(INTERNAL_HEADERS
|
|||||||
${HEADER_DIR}/internal/catch_section.h
|
${HEADER_DIR}/internal/catch_section.h
|
||||||
${HEADER_DIR}/internal/catch_section_info.h
|
${HEADER_DIR}/internal/catch_section_info.h
|
||||||
${HEADER_DIR}/internal/catch_session.h
|
${HEADER_DIR}/internal/catch_session.h
|
||||||
|
${HEADER_DIR}/internal/catch_singletons.hpp
|
||||||
${HEADER_DIR}/internal/catch_startup_exception_registry.h
|
${HEADER_DIR}/internal/catch_startup_exception_registry.h
|
||||||
${HEADER_DIR}/internal/catch_stream.h
|
${HEADER_DIR}/internal/catch_stream.h
|
||||||
${HEADER_DIR}/internal/catch_stringref.h
|
${HEADER_DIR}/internal/catch_stringref.h
|
||||||
@@ -157,12 +173,15 @@ set(IMPL_SOURCES
|
|||||||
${HEADER_DIR}/internal/catch_debug_console.cpp
|
${HEADER_DIR}/internal/catch_debug_console.cpp
|
||||||
${HEADER_DIR}/internal/catch_debugger.cpp
|
${HEADER_DIR}/internal/catch_debugger.cpp
|
||||||
${HEADER_DIR}/internal/catch_decomposer.cpp
|
${HEADER_DIR}/internal/catch_decomposer.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_enforce.cpp
|
||||||
${HEADER_DIR}/internal/catch_errno_guard.cpp
|
${HEADER_DIR}/internal/catch_errno_guard.cpp
|
||||||
${HEADER_DIR}/internal/catch_exception_translator_registry.cpp
|
${HEADER_DIR}/internal/catch_exception_translator_registry.cpp
|
||||||
${HEADER_DIR}/internal/catch_fatal_condition.cpp
|
${HEADER_DIR}/internal/catch_fatal_condition.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_generators.cpp
|
||||||
${HEADER_DIR}/internal/catch_interfaces_capture.cpp
|
${HEADER_DIR}/internal/catch_interfaces_capture.cpp
|
||||||
${HEADER_DIR}/internal/catch_interfaces_config.cpp
|
${HEADER_DIR}/internal/catch_interfaces_config.cpp
|
||||||
${HEADER_DIR}/internal/catch_interfaces_exception.cpp
|
${HEADER_DIR}/internal/catch_interfaces_exception.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_interfaces_generatortracker.h
|
||||||
${HEADER_DIR}/internal/catch_interfaces_registry_hub.cpp
|
${HEADER_DIR}/internal/catch_interfaces_registry_hub.cpp
|
||||||
${HEADER_DIR}/internal/catch_interfaces_runner.cpp
|
${HEADER_DIR}/internal/catch_interfaces_runner.cpp
|
||||||
${HEADER_DIR}/internal/catch_interfaces_testcase.cpp
|
${HEADER_DIR}/internal/catch_interfaces_testcase.cpp
|
||||||
@@ -183,6 +202,7 @@ set(IMPL_SOURCES
|
|||||||
${HEADER_DIR}/internal/catch_section.cpp
|
${HEADER_DIR}/internal/catch_section.cpp
|
||||||
${HEADER_DIR}/internal/catch_section_info.cpp
|
${HEADER_DIR}/internal/catch_section_info.cpp
|
||||||
${HEADER_DIR}/internal/catch_session.cpp
|
${HEADER_DIR}/internal/catch_session.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_singletons.cpp
|
||||||
${HEADER_DIR}/internal/catch_startup_exception_registry.cpp
|
${HEADER_DIR}/internal/catch_startup_exception_registry.cpp
|
||||||
${HEADER_DIR}/internal/catch_stream.cpp
|
${HEADER_DIR}/internal/catch_stream.cpp
|
||||||
${HEADER_DIR}/internal/catch_stringref.cpp
|
${HEADER_DIR}/internal/catch_stringref.cpp
|
||||||
@@ -317,7 +337,7 @@ add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> -w NoTests "___nonexistent_
|
|||||||
set_tests_properties(NoTest PROPERTIES PASS_REGULAR_EXPRESSION "No test cases matched")
|
set_tests_properties(NoTest PROPERTIES PASS_REGULAR_EXPRESSION "No test cases matched")
|
||||||
|
|
||||||
# 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 ${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")
|
||||||
|
|
||||||
if (CATCH_USE_VALGRIND)
|
if (CATCH_USE_VALGRIND)
|
||||||
|
135
projects/ExtraTests/CMakeLists.txt
Normal file
135
projects/ExtraTests/CMakeLists.txt
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
#
|
||||||
|
# Build extra tests.
|
||||||
|
#
|
||||||
|
# Requires CATCH_BUILD_EXTRA_TESTS to be defined 'true', see ../CMakeLists.txt.
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required( VERSION 3.5 )
|
||||||
|
|
||||||
|
project( Catch2ExtraTests LANGUAGES CXX )
|
||||||
|
|
||||||
|
message( STATUS "Extra tests included" )
|
||||||
|
|
||||||
|
# define folders used:
|
||||||
|
|
||||||
|
set( TESTS_DIR ${CATCH_DIR}/projects/ExtraTests )
|
||||||
|
set( SINGLE_INCLUDE_PATH ${CATCH_DIR}/single_include )
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(PrefixedMacros ${TESTS_DIR}/X01-PrefixedMacros.cpp)
|
||||||
|
target_compile_definitions( PrefixedMacros PRIVATE CATCH_CONFIG_PREFIX_ALL )
|
||||||
|
|
||||||
|
add_test(NAME CATCH_CONFIG_PREFIX_ALL COMMAND PrefixedMacros -s)
|
||||||
|
set_tests_properties(
|
||||||
|
CATCH_CONFIG_PREFIX_ALL
|
||||||
|
PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "CATCH_"
|
||||||
|
FAIL_REGULAR_EXPRESSION
|
||||||
|
# The spaces are important -> They disambiguate between CATCH_REQUIRE
|
||||||
|
# and REQUIRE without prefix.
|
||||||
|
" REQUIRE; REQUIRE_FALSE; REQUIRE_THROWS; REQUIRE_THROWS_AS; REQUIRE_THROWS_WITH; REQUIRE_THROWS_MATCHES; REQUIRE_NOTHROW; CHECK; CHECK_FALSE; CHECKED_IF; CHECKED_ELSE; CHECK_NOFAIL; CHECK_THROWS; CHECK_THROWS_AS; CHECK_THROWS_WITH; CHECK_THROWS_MATCHES; CHECK_NOTHROW; REQUIRE_THAT; CHECK_THAT"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(DisabledMacros ${TESTS_DIR}/X02-DisabledMacros.cpp)
|
||||||
|
target_compile_definitions( DisabledMacros PRIVATE CATCH_CONFIG_DISABLE )
|
||||||
|
|
||||||
|
add_test(NAME CATCH_CONFIG_DISABLE-1 COMMAND DisabledMacros -s)
|
||||||
|
set_tests_properties(
|
||||||
|
CATCH_CONFIG_DISABLE-1
|
||||||
|
PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "No tests ran"
|
||||||
|
FAIL_REGULAR_EXPRESSION "This should not happen"
|
||||||
|
)
|
||||||
|
add_test(NAME CATCH_CONFIG_DISABLE-2 COMMAND DisabledMacros --list-tests)
|
||||||
|
set_tests_properties(
|
||||||
|
CATCH_CONFIG_DISABLE-2
|
||||||
|
PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "0 test cases"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
add_executable( DisabledExceptions-DefaultHandler ${TESTS_DIR}/X03-DisabledExceptions-DefaultHandler.cpp )
|
||||||
|
add_executable( DisabledExceptions-CustomHandler ${TESTS_DIR}/X04-DisabledExceptions-CustomHandler.cpp )
|
||||||
|
|
||||||
|
foreach(target DisabledExceptions-DefaultHandler DisabledExceptions-CustomHandler)
|
||||||
|
target_compile_options( ${target}
|
||||||
|
PRIVATE
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:/EHs-c-;/D_HAS_EXCEPTIONS=0>
|
||||||
|
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:AppleClang>>:-fno-exceptions>
|
||||||
|
# $<$<CXX_COMPILER_ID:Clang>:-fno-exceptions>
|
||||||
|
# $<$<CXX_COMPILER_ID:GNU>:-fno-exceptions>
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
|
||||||
|
add_test(NAME CATCH_CONFIG_DISABLE_EXCEPTIONS-1 COMMAND DisabledExceptions-DefaultHandler "Tests that run")
|
||||||
|
set_tests_properties(
|
||||||
|
CATCH_CONFIG_DISABLE_EXCEPTIONS-1
|
||||||
|
PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "assertions: 4 \| 2 passed \| 2 failed"
|
||||||
|
FAIL_REGULAR_EXPRESSION "abort;terminate;fatal"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_test(NAME CATCH_CONFIG_DISABLE_EXCEPTIONS-2 COMMAND DisabledExceptions-DefaultHandler "Tests that abort")
|
||||||
|
set_tests_properties(
|
||||||
|
CATCH_CONFIG_DISABLE_EXCEPTIONS-2
|
||||||
|
PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "Catch will terminate"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_test(NAME CATCH_CONFIG_DISABLE_EXCEPTIONS-3 COMMAND DisabledExceptions-CustomHandler "Tests that run")
|
||||||
|
set_tests_properties(
|
||||||
|
CATCH_CONFIG_DISABLE_EXCEPTIONS-3
|
||||||
|
PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "assertions: 4 \| 2 passed \| 2 failed"
|
||||||
|
FAIL_REGULAR_EXPRESSION "====== CUSTOM HANDLER ======"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_test(NAME CATCH_CONFIG_DISABLE_EXCEPTIONS-4 COMMAND DisabledExceptions-CustomHandler "Tests that abort")
|
||||||
|
set_tests_properties(
|
||||||
|
CATCH_CONFIG_DISABLE_EXCEPTIONS-4
|
||||||
|
PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "====== CUSTOM HANDLER ======"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(FallbackStringifier ${TESTS_DIR}/X10-FallbackStringifier.cpp)
|
||||||
|
target_compile_definitions( FallbackStringifier PRIVATE CATCH_CONFIG_FALLBACK_STRINGIFIER=fallbackStringifier )
|
||||||
|
|
||||||
|
add_test(NAME FallbackStringifier COMMAND FallbackStringifier -r compact -s)
|
||||||
|
set_tests_properties(
|
||||||
|
FallbackStringifier
|
||||||
|
PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "foo{} for: { !!! }"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(DisableStringification ${TESTS_DIR}/X11-DisableStringification.cpp)
|
||||||
|
target_compile_definitions( DisableStringification PRIVATE CATCH_CONFIG_DISABLE_STRINGIFICATION )
|
||||||
|
add_test(NAME CATCH_CONFIG_DISABLE_STRINGIFICATION COMMAND DisableStringification -r compact -s)
|
||||||
|
set_tests_properties(
|
||||||
|
CATCH_CONFIG_DISABLE_STRINGIFICATION
|
||||||
|
PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
|
||||||
|
FAIL_REGULAR_EXPRESSION "Hidden{} == Hidden{}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
set( EXTRA_TEST_BINARIES
|
||||||
|
PrefixedMacros
|
||||||
|
DisabledMacros
|
||||||
|
DisabledExceptions-DefaultHandler
|
||||||
|
DisabledExceptions-CustomHandler
|
||||||
|
FallbackStringifier
|
||||||
|
DisableStringification
|
||||||
|
)
|
||||||
|
|
||||||
|
# Shared config
|
||||||
|
foreach( test ${EXTRA_TEST_BINARIES} )
|
||||||
|
set_property( TARGET ${test} PROPERTY CXX_STANDARD 11 )
|
||||||
|
set_property( TARGET ${test} PROPERTY CXX_STANDARD_REQUIRED ON )
|
||||||
|
set_property( TARGET ${test} PROPERTY CXX_EXTENSIONS OFF )
|
||||||
|
target_include_directories( ${test} PRIVATE ${SINGLE_INCLUDE_PATH} )
|
||||||
|
endforeach()
|
||||||
|
|
11
projects/ExtraTests/ToDo.txt
Normal file
11
projects/ExtraTests/ToDo.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Configuration options that are left default and thus are not properly tested
|
||||||
|
yet:
|
||||||
|
|
||||||
|
CATCH_CONFIG_COUNTER // Use __COUNTER__ to generate unique names for test cases
|
||||||
|
CATCH_CONFIG_WINDOWS_SEH // Enable SEH handling on Windows
|
||||||
|
CATCH_CONFIG_FAST_COMPILE // Sacrifices some (rather minor) features for compilation speed
|
||||||
|
CATCH_CONFIG_DISABLE_MATCHERS // Do not compile Matchers in this compilation unit
|
||||||
|
CATCH_CONFIG_POSIX_SIGNALS // Enable handling POSIX signals
|
||||||
|
CATCH_CONFIG_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap
|
||||||
|
CATCH_CONFIG_DEFAULT_REPORTER
|
||||||
|
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS
|
76
projects/ExtraTests/X01-PrefixedMacros.cpp
Normal file
76
projects/ExtraTests/X01-PrefixedMacros.cpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// X11-DisableStringification.cpp
|
||||||
|
// Test that Catch's prefixed macros compile and run properly.
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
[[noreturn]]
|
||||||
|
void this_throws() {
|
||||||
|
throw std::runtime_error("Some msg");
|
||||||
|
}
|
||||||
|
void this_doesnt_throw() {}
|
||||||
|
|
||||||
|
CATCH_TEST_CASE("PrefixedMacros") {
|
||||||
|
using namespace Catch::Matchers;
|
||||||
|
|
||||||
|
CATCH_REQUIRE( 1 == 1 );
|
||||||
|
CATCH_REQUIRE_FALSE( 1 != 1 );
|
||||||
|
|
||||||
|
CATCH_REQUIRE_THROWS(this_throws());
|
||||||
|
CATCH_REQUIRE_THROWS_AS(this_throws(), std::runtime_error);
|
||||||
|
CATCH_REQUIRE_THROWS_WITH(this_throws(), "Some msg");
|
||||||
|
CATCH_REQUIRE_THROWS_MATCHES(this_throws(), std::runtime_error, Predicate<std::runtime_error>([](std::runtime_error const&) { return true; }));
|
||||||
|
CATCH_REQUIRE_NOTHROW(this_doesnt_throw());
|
||||||
|
|
||||||
|
CATCH_CHECK( 1 == 1 );
|
||||||
|
CATCH_CHECK_FALSE( 1 != 1 );
|
||||||
|
CATCH_CHECKED_IF( 1 == 1 ) {
|
||||||
|
CATCH_SUCCEED("don't care");
|
||||||
|
} CATCH_CHECKED_ELSE ( 1 == 1 ) {
|
||||||
|
CATCH_SUCCEED("don't care");
|
||||||
|
}
|
||||||
|
|
||||||
|
CATCH_CHECK_NOFAIL(1 == 2);
|
||||||
|
|
||||||
|
CATCH_CHECK_THROWS(this_throws());
|
||||||
|
CATCH_CHECK_THROWS_AS(this_throws(), std::runtime_error);
|
||||||
|
CATCH_CHECK_THROWS_WITH(this_throws(), "Some msg");
|
||||||
|
CATCH_CHECK_THROWS_MATCHES(this_throws(), std::runtime_error, Predicate<std::runtime_error>([](std::runtime_error const&) { return true; }));
|
||||||
|
CATCH_CHECK_NOTHROW(this_doesnt_throw());
|
||||||
|
|
||||||
|
CATCH_REQUIRE_THAT("abcd", Equals("abcd"));
|
||||||
|
CATCH_CHECK_THAT("bdef", Equals("bdef"));
|
||||||
|
|
||||||
|
CATCH_INFO( "some info" );
|
||||||
|
CATCH_WARN( "some warn" );
|
||||||
|
CATCH_SECTION("some section") {
|
||||||
|
int i = 1;
|
||||||
|
CATCH_CAPTURE( i );
|
||||||
|
CATCH_DYNAMIC_SECTION("Dynamic section: " << i) {
|
||||||
|
CATCH_FAIL_CHECK( "failure" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CATCH_ANON_TEST_CASE() {
|
||||||
|
CATCH_FAIL("");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Missing:
|
||||||
|
|
||||||
|
//
|
||||||
|
// #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
||||||
|
// #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
|
||||||
|
// #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
|
||||||
|
//
|
||||||
|
// // "BDD-style" convenience wrappers
|
||||||
|
// #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
|
||||||
|
// #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
|
||||||
|
// #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
|
||||||
|
// #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
|
||||||
|
// #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And when: " << desc )
|
||||||
|
// #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
|
||||||
|
// #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
|
||||||
|
//
|
31
projects/ExtraTests/X02-DisabledMacros.cpp
Normal file
31
projects/ExtraTests/X02-DisabledMacros.cpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// X02-DisabledMacros.cpp
|
||||||
|
// Test that CATCH_CONFIG_DISABLE turns off TEST_CASE autoregistration
|
||||||
|
// and expressions in assertion macros are not run.
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
// CATCH_CONFIG_DISABLE also prevents reporter registration.
|
||||||
|
// We need to manually register at least one reporter for our tests
|
||||||
|
static Catch::ReporterRegistrar<Catch::ConsoleReporter> temporary( "console" );
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
struct foo {
|
||||||
|
foo(){
|
||||||
|
REQUIRE_NOTHROW( print() );
|
||||||
|
}
|
||||||
|
void print() const {
|
||||||
|
std::cout << "This should not happen\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Construct foo, but `foo::print` should not be run
|
||||||
|
foo f;
|
||||||
|
|
||||||
|
// This test should not be run, because it won't be registered
|
||||||
|
TEST_CASE( "Disabled Macros" ) {
|
||||||
|
std::cout << "This should not happen\n";
|
||||||
|
FAIL();
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
TEST_CASE("Tests that run") {
|
||||||
|
// All of these should be run and be reported
|
||||||
|
CHECK(1 == 2);
|
||||||
|
CHECK(1 == 1);
|
||||||
|
CHECK(1 != 3);
|
||||||
|
CHECK(1 == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("Tests that abort") {
|
||||||
|
// Avoid abort and other exceptional exits -- there is no way
|
||||||
|
// to tell CMake that abort is the desired outcome of a test.
|
||||||
|
std::set_terminate([](){exit(1);});
|
||||||
|
REQUIRE(1 == 1);
|
||||||
|
REQUIRE(1 != 2);
|
||||||
|
REQUIRE(1 == 3);
|
||||||
|
// We should not get here, because the test above aborts
|
||||||
|
REQUIRE(1 != 4);
|
||||||
|
}
|
33
projects/ExtraTests/X04-DisabledExceptions-CustomHandler.cpp
Normal file
33
projects/ExtraTests/X04-DisabledExceptions-CustomHandler.cpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#define CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
[[noreturn]]
|
||||||
|
void throw_exception(std::exception const& e) {
|
||||||
|
Catch::cerr() << "====== CUSTOM HANDLER ====== run terminates because an exception was thrown.\n"
|
||||||
|
<< "The message was: " << e.what() << '\n';
|
||||||
|
// Avoid abort and other exceptional exits -- there is no way
|
||||||
|
// to tell CMake that abort is the desired outcome of a test.
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Tests that run") {
|
||||||
|
// All of these should be run and be reported
|
||||||
|
CHECK(1 == 2);
|
||||||
|
CHECK(1 == 1);
|
||||||
|
CHECK(1 != 3);
|
||||||
|
CHECK(1 == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("Tests that abort") {
|
||||||
|
REQUIRE(1 == 1);
|
||||||
|
REQUIRE(1 != 2);
|
||||||
|
REQUIRE(1 == 3);
|
||||||
|
// We should not get here, because the test above aborts
|
||||||
|
REQUIRE(1 != 4);
|
||||||
|
}
|
23
projects/ExtraTests/X10-FallbackStringifier.cpp
Normal file
23
projects/ExtraTests/X10-FallbackStringifier.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// X10-FallbackStringifier.cpp
|
||||||
|
// Test that defining fallbackStringifier compiles
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// A catch-all stringifier
|
||||||
|
template <typename T>
|
||||||
|
std::string fallbackStringifier(T const&) {
|
||||||
|
return "{ !!! }";
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
struct foo {
|
||||||
|
explicit operator bool() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("aa") {
|
||||||
|
REQUIRE(foo{});
|
||||||
|
}
|
16
projects/ExtraTests/X11-DisableStringification.cpp
Normal file
16
projects/ExtraTests/X11-DisableStringification.cpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// X11-DisableStringification.cpp
|
||||||
|
// Test that stringification of original expression can be disabled
|
||||||
|
// this is a workaround for VS 2017 issue with Raw String literal
|
||||||
|
// and preprocessor token pasting. In other words, hopefully this test
|
||||||
|
// will be deleted soon :-)
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
struct Hidden {};
|
||||||
|
|
||||||
|
bool operator==(Hidden, Hidden) { return true; }
|
||||||
|
|
||||||
|
TEST_CASE("DisableStringification") {
|
||||||
|
REQUIRE( Hidden{} == Hidden{} );
|
||||||
|
}
|
@@ -56,6 +56,106 @@ Tricky.tests.cpp:<line number>: passed: !is_true<false>::value for: true
|
|||||||
Tricky.tests.cpp:<line number>: passed: !!is_true<true>::value for: true
|
Tricky.tests.cpp:<line number>: passed: !!is_true<true>::value for: true
|
||||||
Tricky.tests.cpp:<line number>: passed: is_true<true>::value for: true
|
Tricky.tests.cpp:<line number>: passed: is_true<true>::value for: true
|
||||||
Tricky.tests.cpp:<line number>: passed: !(is_true<false>::value) for: !false
|
Tricky.tests.cpp:<line number>: passed: !(is_true<false>::value) for: !false
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 101
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 102
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 103
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 104
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 105
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 106
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 107
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 108
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 109
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 1 < 110
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 101
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 102
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 103
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 104
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 105
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 106
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 107
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 108
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 109
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 2 < 110
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 101
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 102
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 103
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 104
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 105
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 106
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 107
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 108
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 109
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 3 < 110
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 101
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 102
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 103
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 104
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 105
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 106
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 107
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 108
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 109
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 4 < 110
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 101
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 102
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 103
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 104
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 105
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 106
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 107
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 108
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 109
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 5 < 110
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 101
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 102
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 103
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 104
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 105
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 106
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 107
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 108
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 109
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 6 < 110
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 101
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 102
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 103
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 104
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 105
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 106
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 107
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 108
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 109
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 7 < 110
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 101
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 102
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 103
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 104
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 105
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 106
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 107
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 108
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 109
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 8 < 110
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 101
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 102
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 103
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 104
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 105
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 106
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 107
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 108
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 109
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 9 < 110
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 101
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 102
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 103
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 104
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 105
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 106
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 107
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 108
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 109
|
||||||
|
Generators.tests.cpp:<line number>: passed: x < y for: 10 < 110
|
||||||
Class.tests.cpp:<line number>: failed: s == "world" for: "hello" == "world"
|
Class.tests.cpp:<line number>: failed: s == "world" for: "hello" == "world"
|
||||||
Class.tests.cpp:<line number>: passed: s == "hello" for: "hello" == "hello"
|
Class.tests.cpp:<line number>: passed: s == "hello" for: "hello" == "hello"
|
||||||
Class.tests.cpp:<line number>: failed: m_a == 2 for: 1 == 2
|
Class.tests.cpp:<line number>: failed: m_a == 2 for: 1 == 2
|
||||||
@@ -297,6 +397,48 @@ 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, -1), std::domain_error
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 8'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 9'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 10'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 2'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 3.141'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "a"' and 'j := 1.379'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 8'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 9'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 10'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 2'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 3.141'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "b"' and 'j := 1.379'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 8'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 9'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 10'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 2'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 3.141'
|
||||||
|
Generators.tests.cpp:<line number>: passed: with 2 messages: 'i := "c"' and 'j := 1.379'
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 4 for: 4 == 4
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 3 for: 3 == 3
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[2] == 4 for: 4 == 4
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[3] == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 4 for: 4 == 4
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[2] == 9 for: 9 == 9
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[3] == 7 for: 7 == 7
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 3 for: 3 == 3
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen.size() == 2 for: 2 == 2
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[0] == 3 for: 3 == 3
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: gen[1] == 1 for: 1 == 1
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: base->size() == 4 for: 4 == 4
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: typed for: 0x<hex digits>
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: typed->size() == 4 for: 4 == 4
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: (*typed)[0] == 7 for: 7 == 7
|
||||||
|
GeneratorsImpl.tests.cpp:<line number>: passed: (*typed)[3] == 11 for: 11 == 11
|
||||||
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 )
|
||||||
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.24 )) for: !(1.23 >= Approx( 1.24 ))
|
Approx.tests.cpp:<line number>: passed: !(d >= Approx( 1.24 )) for: !(1.23 >= Approx( 1.24 ))
|
||||||
@@ -1093,6 +1235,10 @@ ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( v ) =
|
|||||||
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" for: "{ operator<<( has_operator ) }"
|
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" for: "{ operator<<( has_operator ) }"
|
||||||
==
|
==
|
||||||
"{ operator<<( has_operator ) }"
|
"{ operator<<( has_operator ) }"
|
||||||
|
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 3 == 3
|
||||||
|
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 3 == 3
|
||||||
|
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 5 == 5
|
||||||
|
Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 4 == 4
|
||||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'Why would you throw a std::string?'
|
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'Why would you throw a std::string?'
|
||||||
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
|
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
|
||||||
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
|
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
|
||||||
|
@@ -1096,6 +1096,6 @@ due to unexpected exception with message:
|
|||||||
Why would you throw a std::string?
|
Why would you throw a std::string?
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 208 | 155 passed | 49 failed | 4 failed as expected
|
test cases: 212 | 159 passed | 49 failed | 4 failed as expected
|
||||||
assertions: 1081 | 952 passed | 108 failed | 21 failed as expected
|
assertions: 1227 | 1098 passed | 108 failed | 21 failed as expected
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<testsuitesloose text artifact
|
<testsuitesloose text artifact
|
||||||
>
|
>
|
||||||
<testsuite name="<exe-name>" errors="17" failures="106" tests="1096" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
<testsuite name="<exe-name>" errors="17" failures="106" tests="1242" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||||
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
|
||||||
@@ -69,6 +69,7 @@ Condition.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/negation" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/negation" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/double negation" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/double negation" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/direct" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/direct" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="10x10 ints" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.TestClass" name="A METHOD_AS_TEST_CASE based test run that fails" time="{duration}">
|
<testcase classname="<exe-name>.TestClass" name="A METHOD_AS_TEST_CASE based test run that fails" time="{duration}">
|
||||||
<failure message=""hello" == "world"" type="REQUIRE">
|
<failure message=""hello" == "world"" type="REQUIRE">
|
||||||
Class.tests.cpp:<line number>
|
Class.tests.cpp:<line number>
|
||||||
@@ -289,6 +290,14 @@ Message.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Constructor validation" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Constructor validation" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators/one" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators/two" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators impl/range" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators impl/fixed values" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators impl/combined" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators impl/values" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators impl/values2" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Generators impl/type erasure" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Greater-than inequalities with different epsilons" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Greater-than inequalities with different epsilons" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="INFO and WARN do not abort tests" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="INFO and WARN do not abort tests" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="INFO gets logged on failure" time="{duration}">
|
<testcase classname="<exe-name>.global" name="INFO gets logged on failure" time="{duration}">
|
||||||
@@ -513,8 +522,8 @@ Matchers.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="SUCCEED does not require an argument" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="SUCCEED does not require an argument" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me" time="{duration}"/>
|
<testcase classname="<exe-name>.Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me/When: We get the count/Then: Subsequently values are higher" time="{duration}"/>
|
<testcase classname="<exe-name>.Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me/When: We get the count/Then: Subsequently values are higher" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Scenario: Do that thing with the thing/Given: This stuff exists/When: I do this/Then: it should do this" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Scenario: Do that thing with the thing/Given: This stuff exists/And given: And some assumption/When: I do this/Then: it should do this" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Scenario: Do that thing with the thing/Given: This stuff exists/When: I do this/Then: it should do this/And: do that" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Scenario: Do that thing with the thing/Given: This stuff exists/And given: And some assumption/When: I do this/Then: it should do this/And: do that" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Scenario: This is a really long scenario name to see how the list command deals with wrapping/Given: A section name that is so long that it cannot fit in a single console width/When: The test headers are printed as part of the normal running of the scenario/Then: The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Scenario: This is a really long scenario name to see how the list command deals with wrapping/Given: A section name that is so long that it cannot fit in a single console width/When: The test headers are printed as part of the normal running of the scenario/Then: The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Scenario: Vector resizing affects size and capacity/Given: an empty vector" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Scenario: Vector resizing affects size and capacity/Given: an empty vector" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Scenario: Vector resizing affects size and capacity/Given: an empty vector/When: it is made larger/Then: the size and capacity go up" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Scenario: Vector resizing affects size and capacity/Given: an empty vector/When: it is made larger/Then: the size and capacity go up" time="{duration}"/>
|
||||||
@@ -855,6 +864,7 @@ Tricky.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="stringify( vectors<has_maker> )" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="stringify( vectors<has_maker> )" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="stringify( vectors<has_maker_and_operator> )" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="stringify( vectors<has_maker_and_operator> )" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="stringify( vectors<has_operator> )" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="stringify( vectors<has_operator> )" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="strlen3" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="thrown std::strings are translated" time="{duration}">
|
<testcase classname="<exe-name>.global" name="thrown std::strings are translated" time="{duration}">
|
||||||
<error type="TEST_CASE">
|
<error type="TEST_CASE">
|
||||||
Why would you throw a std::string?
|
Why would you throw a std::string?
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,93 @@
|
|||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
// Tests of generartor implementation details
|
||||||
|
|
||||||
|
TEST_CASE("Generators impl", "[impl]") {
|
||||||
|
using namespace Catch::Generators;
|
||||||
|
|
||||||
|
SECTION( "range" ) {
|
||||||
|
auto gen = range(1,3);
|
||||||
|
|
||||||
|
CHECK( gen.size() == 2 );
|
||||||
|
|
||||||
|
CHECK( gen[0] == 1 );
|
||||||
|
CHECK( gen[1] == 2 );
|
||||||
|
}
|
||||||
|
SECTION( "fixed values" ) {
|
||||||
|
auto gen = values( { 3, 1, 4, 1 } );
|
||||||
|
|
||||||
|
CHECK( gen.size() == 4 );
|
||||||
|
CHECK( gen[0] == 3 );
|
||||||
|
CHECK( gen[1] == 1 );
|
||||||
|
CHECK( gen[2] == 4 );
|
||||||
|
CHECK( gen[3] == 1 );
|
||||||
|
}
|
||||||
|
SECTION( "combined" ) {
|
||||||
|
auto gen = makeGenerators( range( 1, 3 ), values( { 9, 7 } ) );
|
||||||
|
|
||||||
|
CHECK( gen.size() == 4 );
|
||||||
|
CHECK( gen[0] == 1 );
|
||||||
|
CHECK( gen[1] == 2 );
|
||||||
|
CHECK( gen[2] == 9 );
|
||||||
|
CHECK( gen[3] == 7 );
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION( "values" ) {
|
||||||
|
auto gen = makeGenerators( 3, 1 );
|
||||||
|
|
||||||
|
CHECK( gen.size() == 2 );
|
||||||
|
CHECK( gen[0] == 3 );
|
||||||
|
CHECK( gen[1] == 1 );
|
||||||
|
}
|
||||||
|
SECTION( "values2" ) {
|
||||||
|
auto gen = makeGenerators( 3, 1 );
|
||||||
|
|
||||||
|
CHECK( gen.size() == 2 );
|
||||||
|
CHECK( gen[0] == 3 );
|
||||||
|
CHECK( gen[1] == 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SECTION( "type erasure" ) {
|
||||||
|
auto gen = makeGenerators( range( 7, 10 ), 11 );
|
||||||
|
|
||||||
|
// Make type erased version
|
||||||
|
auto dynCopy = pf::make_unique<Generators<int>>( std::move( gen ) );
|
||||||
|
std::unique_ptr<GeneratorBase const> base = std::move( dynCopy );
|
||||||
|
|
||||||
|
// Only thing we can do is ask for the size
|
||||||
|
CHECK( base->size() == 4 );
|
||||||
|
|
||||||
|
// Restore typed version
|
||||||
|
auto typed = dynamic_cast<Generators<int> const*>( base.get() );
|
||||||
|
REQUIRE( typed );
|
||||||
|
CHECK( typed->size() == 4 );
|
||||||
|
CHECK( (*typed)[0] == 7 );
|
||||||
|
CHECK( (*typed)[3] == 11 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Generators impl - random", "[approvals]") {
|
||||||
|
using namespace Catch::Generators;
|
||||||
|
|
||||||
|
SECTION( "random range" ) {
|
||||||
|
auto gen = random( 3, 9 );
|
||||||
|
|
||||||
|
CHECK( gen.size() == 6 );
|
||||||
|
for( size_t i = 0; i < 6; ++i ) {
|
||||||
|
CHECK( gen[i] >= 3 );
|
||||||
|
CHECK( gen[i] <= 8 );
|
||||||
|
if( i > 0 )
|
||||||
|
CHECK( gen[i] != gen[i-1] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SECTION( "random selection" ) {
|
||||||
|
auto gen = random<int>( 10 );
|
||||||
|
|
||||||
|
CHECK( gen.size() == 10 );
|
||||||
|
for( size_t i = 0; i < 10; ++i ) {
|
||||||
|
if( i > 0 )
|
||||||
|
CHECK( gen[i] != gen[i-1] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -38,6 +38,8 @@ namespace { namespace BDDTests {
|
|||||||
SCENARIO("Do that thing with the thing", "[Tags]") {
|
SCENARIO("Do that thing with the thing", "[Tags]") {
|
||||||
GIVEN("This stuff exists") {
|
GIVEN("This stuff exists") {
|
||||||
// make stuff exist
|
// make stuff exist
|
||||||
|
AND_GIVEN("And some assumption") {
|
||||||
|
// Validate assumption
|
||||||
WHEN("I do this") {
|
WHEN("I do this") {
|
||||||
// do this
|
// do this
|
||||||
THEN("it should do this") {
|
THEN("it should do this") {
|
||||||
@@ -47,6 +49,7 @@ namespace { namespace BDDTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SCENARIO("Vector resizing affects size and capacity", "[vector][bdd][size][capacity]") {
|
SCENARIO("Vector resizing affects size and capacity", "[vector][bdd][size][capacity]") {
|
||||||
GIVEN("an empty vector") {
|
GIVEN("an empty vector") {
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wweak-vtables"
|
#pragma clang diagnostic ignored "-Wweak-vtables"
|
||||||
#pragma clang diagnostic ignored "-Wmissing-noreturn"
|
#pragma clang diagnostic ignored "-Wmissing-noreturn"
|
||||||
|
#pragma clang diagnostic ignored "-Wunreachable-code"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace { namespace ExceptionTests {
|
namespace { namespace ExceptionTests {
|
||||||
|
134
projects/SelfTest/UsageTests/Generators.tests.cpp
Normal file
134
projects/SelfTest/UsageTests/Generators.tests.cpp
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
// Examples of usage of Generators
|
||||||
|
|
||||||
|
// This test doesn't do much - it just shows how you can have several generators, of different
|
||||||
|
// types (ie `i` and `j` are different types), can be sequenced using `,` and
|
||||||
|
// can be expressed as named generators (like range) or as individual values.
|
||||||
|
// Generators can be mixed with SECTIONs.
|
||||||
|
// At time of writing the generated values are not automatically reported as part of the test
|
||||||
|
// name or associated values - so we explicitly CAPTURE then (run this with `-s` to see them).
|
||||||
|
// We could also incorporate them into the section names using DYNAMIC_SECTION. See the BDD
|
||||||
|
// example later for more information.
|
||||||
|
TEST_CASE("Generators") {
|
||||||
|
|
||||||
|
auto i = GENERATE( as<std::string>(), "a", "b", "c" );
|
||||||
|
|
||||||
|
SECTION( "one" ) {
|
||||||
|
auto j = GENERATE( range( 8, 11 ), 2 );
|
||||||
|
|
||||||
|
CAPTURE( i, j );
|
||||||
|
SUCCEED();
|
||||||
|
}
|
||||||
|
SECTION( "two" ) {
|
||||||
|
auto j = GENERATE( 3.141, 1.379 );
|
||||||
|
CAPTURE( i, j );
|
||||||
|
SUCCEED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This one generates the cross-product of two ranges.
|
||||||
|
// It's mostly here to demonstrate the performance which, at time of writing,
|
||||||
|
// leaves a lot to be desired.
|
||||||
|
TEST_CASE( "100x100 ints", "[.][approvals]" ) {
|
||||||
|
auto x = GENERATE( range( 0,100 ) );
|
||||||
|
auto y = GENERATE( range( 200,300 ) );
|
||||||
|
|
||||||
|
CHECK( x < y );
|
||||||
|
}
|
||||||
|
|
||||||
|
// smaller version
|
||||||
|
TEST_CASE( "10x10 ints" ) {
|
||||||
|
auto x = GENERATE( range( 1,11 ) );
|
||||||
|
auto y = GENERATE( range( 101, 111 ) );
|
||||||
|
|
||||||
|
CHECK( x < y );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some of the following tests use structured bindings for convenience and so are
|
||||||
|
// conditionally compiled using the de-facto (and soon to be formally) standard
|
||||||
|
// feature macros
|
||||||
|
|
||||||
|
#ifdef __cpp_structured_bindings
|
||||||
|
|
||||||
|
// One way to do pairs of values (actual/ expected?)
|
||||||
|
// For a simple case like this I'd recommend writing out a series of REQUIREs
|
||||||
|
// but it demonstrates a possible usage.
|
||||||
|
// Spelling out the pair like this is a bit verbose, so read on for better examples
|
||||||
|
// - the use of structured bindings here is an optional convenience
|
||||||
|
TEST_CASE( "strlen", "[.][approvals]" ) {
|
||||||
|
auto [test_input, expected] = GENERATE( values<std::pair<std::string_view, size_t>>({
|
||||||
|
{"one", 3},
|
||||||
|
{"two", 3},
|
||||||
|
{"three", 5},
|
||||||
|
{"four", 4}
|
||||||
|
}));
|
||||||
|
|
||||||
|
REQUIRE( test_input.size() == expected );
|
||||||
|
}
|
||||||
|
|
||||||
|
// A nicer way to do pairs (or more) of values - using the table generator.
|
||||||
|
// Note, you must specify the types up-front.
|
||||||
|
TEST_CASE( "strlen2", "[.][approvals]" ) {
|
||||||
|
auto [test_input, expected] = GENERATE( table<std::string, size_t>({
|
||||||
|
{"one", 3},
|
||||||
|
{"two", 3},
|
||||||
|
{"three", 5},
|
||||||
|
{"four", 4}
|
||||||
|
}));
|
||||||
|
|
||||||
|
REQUIRE( test_input.size() == expected );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// An alternate way of doing data tables without structure bindings
|
||||||
|
// - I'd prefer to have the Data class within the test case but gcc 4.x doesn't seem to like it
|
||||||
|
struct Data { std::string str; size_t len; };
|
||||||
|
|
||||||
|
TEST_CASE( "strlen3" ) {
|
||||||
|
auto data = GENERATE( values<Data>({
|
||||||
|
{"one", 3},
|
||||||
|
{"two", 3},
|
||||||
|
{"three", 5},
|
||||||
|
{"four", 4}
|
||||||
|
}));
|
||||||
|
|
||||||
|
REQUIRE( data.str.size() == data.len );
|
||||||
|
}
|
||||||
|
|
||||||
|
// A nod towards property-based testing - generate a random selection of numbers
|
||||||
|
// in a range and assert on global properties those numbers.
|
||||||
|
static auto square( int i ) -> int { return i*i; }
|
||||||
|
|
||||||
|
TEST_CASE( "Random numbers in a range", "[.][approvals]" ) {
|
||||||
|
auto x = GENERATE( random( -10000, 10000 ) );
|
||||||
|
CAPTURE( x );
|
||||||
|
REQUIRE( square(x) >= 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cpp_structured_bindings
|
||||||
|
|
||||||
|
// Based on example from https://docs.cucumber.io/gherkin/reference/#scenario-outline
|
||||||
|
// (thanks to https://github.com/catchorg/Catch2/issues/850#issuecomment-399504851)
|
||||||
|
|
||||||
|
// Note that GIVEN, WHEN, and THEN now forward onto DYNAMIC_SECTION instead of SECTION.
|
||||||
|
// DYNAMIC_SECTION takes its name as a stringstream-style expression, so can be formatted using
|
||||||
|
// variables in scope - such as the generated variables here. This reads quite nicely in the
|
||||||
|
// test name output (the full scenario description).
|
||||||
|
|
||||||
|
static auto eatCucumbers( int start, int eat ) -> int { return start-eat; }
|
||||||
|
|
||||||
|
SCENARIO("Eating cucumbers", "[.][approvals]") {
|
||||||
|
|
||||||
|
auto [start, eat, left] = GENERATE( table<int,int,int> ({
|
||||||
|
{ 12, 5, 7 },
|
||||||
|
{ 20, 5, 15 }
|
||||||
|
}));
|
||||||
|
|
||||||
|
GIVEN( "there are " << start << " cucumbers" )
|
||||||
|
WHEN( "I eat " << eat << " cucumbers" )
|
||||||
|
THEN( "I should have " << left << " cucumbers" ) {
|
||||||
|
REQUIRE( eatCucumbers( start, eat ) == left );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@@ -98,7 +98,6 @@ def filterLine(line, isCompact):
|
|||||||
# go from \ in windows paths to /
|
# go from \ in windows paths to /
|
||||||
line = line.replace('\\', '/')
|
line = line.replace('\\', '/')
|
||||||
|
|
||||||
|
|
||||||
# strip source line numbers
|
# strip source line numbers
|
||||||
m = filelocParser.match(line)
|
m = filelocParser.match(line)
|
||||||
if m:
|
if m:
|
||||||
@@ -180,19 +179,19 @@ print("Running approvals against executable:")
|
|||||||
print(" " + cmdPath)
|
print(" " + cmdPath)
|
||||||
|
|
||||||
|
|
||||||
### Keep default reporters here
|
# ## Keep default reporters here ##
|
||||||
# Standard console reporter
|
# Standard console reporter
|
||||||
approve("console.std", ["~[!nonportable]~[!benchmark]~[approvals]", "--order", "lex"])
|
approve("console.std", ["~[!nonportable]~[!benchmark]~[approvals]", "--order", "lex", "--rng-seed", "0"])
|
||||||
# console reporter, include passes, warn about No Assertions
|
# console reporter, include passes, warn about No Assertions
|
||||||
approve("console.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "--order", "lex"])
|
approve("console.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "--order", "lex", "--rng-seed", "0"])
|
||||||
# console reporter, include passes, warn about No Assertions, limit failures to first 4
|
# console reporter, include passes, warn about No Assertions, limit failures to first 4
|
||||||
approve("console.swa4", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-x", "4", "--order", "lex"])
|
approve("console.swa4", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-x", "4", "--order", "lex", "--rng-seed", "0"])
|
||||||
# junit reporter, include passes, warn about No Assertions
|
# junit reporter, include passes, warn about No Assertions
|
||||||
approve("junit.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "junit", "--order", "lex"])
|
approve("junit.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "junit", "--order", "lex", "--rng-seed", "0"])
|
||||||
# xml reporter, include passes, warn about No Assertions
|
# xml reporter, include passes, warn about No Assertions
|
||||||
approve("xml.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "xml", "--order", "lex"])
|
approve("xml.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "xml", "--order", "lex", "--rng-seed", "0"])
|
||||||
# compact reporter, include passes, warn about No Assertions
|
# compact reporter, include passes, warn about No Assertions
|
||||||
approve('compact.sw', ['~[!nonportable]~[!benchmark]~[approvals]', '-s', '-w', 'NoAssertions', '-r', 'compact', '--order', 'lex'])
|
approve('compact.sw', ['~[!nonportable]~[!benchmark]~[approvals]', '-s', '-w', 'NoAssertions', '-r', 'compact', '--order', 'lex', "--rng-seed", "0"])
|
||||||
|
|
||||||
if overallResult != 0:
|
if overallResult != 0:
|
||||||
print("If these differences are expected, run approve.py to approve new baselines.")
|
print("If these differences are expected, run approve.py to approve new baselines.")
|
||||||
|
@@ -46,7 +46,7 @@ def generate(v):
|
|||||||
outDir = os.path.dirname(outputPath)
|
outDir = os.path.dirname(outputPath)
|
||||||
if not os.path.exists(outDir):
|
if not os.path.exists(outDir):
|
||||||
os.makedirs(outDir)
|
os.makedirs(outDir)
|
||||||
out = io.open( outputPath, 'w', newline='\n')
|
out = io.open( outputPath, 'w', newline='\n', encoding='utf-8')
|
||||||
|
|
||||||
def write( line ):
|
def write( line ):
|
||||||
if globals['includeImpl'] or globals['implIfDefs'] == -1:
|
if globals['includeImpl'] or globals['implIfDefs'] == -1:
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -97,12 +97,12 @@ namespace Catch {
|
|||||||
case ResultWas::Ok:
|
case ResultWas::Ok:
|
||||||
case ResultWas::Info:
|
case ResultWas::Info:
|
||||||
case ResultWas::Warning:
|
case ResultWas::Warning:
|
||||||
throw std::domain_error( "Internal error in TeamCity reporter" );
|
CATCH_ERROR( "Internal error in TeamCity reporter" );
|
||||||
// These cases are here to prevent compiler warnings
|
// These cases are here to prevent compiler warnings
|
||||||
case ResultWas::Unknown:
|
case ResultWas::Unknown:
|
||||||
case ResultWas::FailureBit:
|
case ResultWas::FailureBit:
|
||||||
case ResultWas::Exception:
|
case ResultWas::Exception:
|
||||||
throw std::domain_error( "Not implemented" );
|
CATCH_ERROR( "Not implemented" );
|
||||||
}
|
}
|
||||||
if( assertionStats.infoMessages.size() == 1 )
|
if( assertionStats.infoMessages.size() == 1 )
|
||||||
msg << " with message:";
|
msg << " with message:";
|
||||||
|
@@ -10,7 +10,7 @@ class CatchConanTest(ConanFile):
|
|||||||
settings = "os", "compiler", "arch", "build_type"
|
settings = "os", "compiler", "arch", "build_type"
|
||||||
username = getenv("CONAN_USERNAME", "philsquared")
|
username = getenv("CONAN_USERNAME", "philsquared")
|
||||||
channel = getenv("CONAN_CHANNEL", "testing")
|
channel = getenv("CONAN_CHANNEL", "testing")
|
||||||
requires = "Catch/2.3.0@%s/%s" % (username, channel)
|
requires = "Catch/2.4.0@%s/%s" % (username, channel)
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
cmake = CMake(self)
|
cmake = CMake(self)
|
||||||
|
Reference in New Issue
Block a user