Merge branch 'catchorg:v2.x' into v2.x

This commit is contained in:
Scott Hutchinson 2022-11-23 15:56:56 -08:00 committed by GitHub
commit 428a30ebd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 1040 additions and 493 deletions

View File

@ -258,6 +258,15 @@ matrix:
addons: *gcc7 addons: *gcc7
env: COMPILER='g++-7' EXAMPLES=1 COVERAGE=1 EXTRAS=1 CPP17=1 env: COMPILER='g++-7' EXAMPLES=1 COVERAGE=1 EXTRAS=1 CPP17=1
- os: linux
dist: xenial
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-5.0']
env: COMPILER='clang++-5.0' CPP17=1
- os: linux - os: linux
dist: xenial dist: xenial
compiler: clang compiler: clang
@ -276,19 +285,6 @@ matrix:
packages: ['clang-6.0', 'libstdc++-8-dev'] packages: ['clang-6.0', 'libstdc++-8-dev']
env: COMPILER='clang++-6.0' CPP17=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1 env: COMPILER='clang++-6.0' CPP17=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1
# 8/ Conan
- language: python
python:
- "3.7"
dist: xenial
install:
- pip install conan-package-tools
env:
- CONAN_GCC_VERSIONS=8
- CONAN_DOCKER_IMAGE=conanio/gcc8
script:
- python .conan/build.py
install: install:
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR} - mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}

View File

@ -1,4 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
Name: Catch2 Name: Catch2
Description: A modern, C++-native, header-only, test framework for C++11 Description: A modern, C++-native, header-only, test framework for C++11

View File

@ -4,6 +4,8 @@ cmake_minimum_required(VERSION 3.5)
# disable testsuite in that case # disable testsuite in that case
if(NOT DEFINED PROJECT_NAME) if(NOT DEFINED PROJECT_NAME)
set(NOT_SUBPROJECT ON) set(NOT_SUBPROJECT ON)
else()
set(NOT_SUBPROJECT OFF)
endif() endif()
# Catch2's build breaks if done in-tree. You probably should not build # Catch2's build breaks if done in-tree. You probably should not build
@ -14,7 +16,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif() endif()
project(Catch2 LANGUAGES CXX VERSION 2.13.4) project(Catch2 LANGUAGES CXX VERSION 2.13.10)
# 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")
@ -25,12 +27,12 @@ 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_BUILD_EXTRA_TESTS "Build extra tests" OFF)
option(CATCH_BUILD_STATIC_LIBRARY "Builds static library from the main implementation. EXPERIMENTAL" 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)
option(CATCH_INSTALL_HELPERS "Install contrib alongside library" ON) option(CATCH_INSTALL_HELPERS "Install contrib alongside library" ON)
# define some folders # define some folders
set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest) set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
@ -104,6 +106,7 @@ endif()
add_library(Catch2::Catch2 ALIAS Catch2) add_library(Catch2::Catch2 ALIAS Catch2)
# Hacky support for compiling the impl into a static lib # Hacky support for compiling the impl into a static lib
if (CATCH_BUILD_STATIC_LIBRARY)
add_library(Catch2WithMain ${CMAKE_CURRENT_LIST_DIR}/src/catch_with_main.cpp) add_library(Catch2WithMain ${CMAKE_CURRENT_LIST_DIR}/src/catch_with_main.cpp)
target_link_libraries(Catch2WithMain PUBLIC Catch2) target_link_libraries(Catch2WithMain PUBLIC Catch2)
add_library(Catch2::Catch2WithMain ALIAS Catch2WithMain) add_library(Catch2::Catch2WithMain ALIAS Catch2WithMain)
@ -114,6 +117,11 @@ if(("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND NOT ${CMAKE_CXX_COMPILER_VERSI
target_compile_options(Catch2WithMain PRIVATE "-ffile-prefix-map=${CMAKE_SOURCE_DIR}=.") target_compile_options(Catch2WithMain PRIVATE "-ffile-prefix-map=${CMAKE_SOURCE_DIR}=.")
endif() endif()
if (CATCH_CONFIG_DEFAULT_REPORTER)
target_compile_definitions(Catch2WithMain PRIVATE CATCH_CONFIG_DEFAULT_REPORTER=${CATCH_CONFIG_DEFAULT_REPORTER})
endif()
endif(CATCH_BUILD_STATIC_LIBRARY)
# Only perform the installation steps when Catch is not being used as # Only perform the installation steps when Catch is not being used as
# a subproject via `add_subdirectory`, or the destinations will break, # a subproject via `add_subdirectory`, or the destinations will break,
# see https://github.com/catchorg/Catch2/issues/1373 # see https://github.com/catchorg/Catch2/issues/1373
@ -128,11 +136,17 @@ if (NOT_SUBPROJECT)
${CATCH_CMAKE_CONFIG_DESTINATION} ${CATCH_CMAKE_CONFIG_DESTINATION}
) )
# Workaround lack of generator expressions in install(TARGETS
set(InstallationTargets Catch2)
if (TARGET Catch2WithMain)
list(APPEND InstallationTargets Catch2WithMain)
endif()
# 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 Catch2WithMain ${InstallationTargets}
EXPORT EXPORT
Catch2Targets Catch2Targets
DESTINATION DESTINATION

View File

@ -9,7 +9,7 @@
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD) [![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.13.4/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.13.10/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released! ## Catch2 is released!

View File

@ -16,7 +16,10 @@ set(tests)
function(add_command NAME) function(add_command NAME)
set(_args "") set(_args "")
foreach(_arg ${ARGN}) # use ARGV* instead of ARGN, because ARGN splits arrays into multiple arguments
math(EXPR _last_arg ${ARGC}-1)
foreach(_n RANGE 1 ${_last_arg})
set(_arg "${ARGV${_n}}")
if(_arg MATCHES "[^-./:a-zA-Z0-9_]") if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument
else() else()

View File

@ -200,7 +200,7 @@ function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
# Escape commas in the test spec # Escape commas in the test spec
string(REPLACE "," "\\," Name ${Name}) string(REPLACE "," "\\," Name ${Name})
# Work around CMake 3.18.0 change in `add_test()`, before the escaped quotes were neccessary, # Work around CMake 3.18.0 change in `add_test()`, before the escaped quotes were necessary,
# only with CMake 3.18.0 the escaped double quotes confuse the call. This change is reverted in 3.18.1 # only with CMake 3.18.0 the escaped double quotes confuse the call. This change is reverted in 3.18.1
# And properly introduced in 3.19 with the CMP0110 policy # And properly introduced in 3.19 with the CMP0110 policy
if(_cmp0110_value STREQUAL "NEW" OR ${CMAKE_VERSION} VERSION_EQUAL "3.18") if(_cmp0110_value STREQUAL "NEW" OR ${CMAKE_VERSION} VERSION_EQUAL "3.18")

View File

@ -43,7 +43,8 @@ Include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
Catch2 Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v2.13.1) GIT_TAG v2.13.9 # or a later release
)
FetchContent_MakeAvailable(Catch2) FetchContent_MakeAvailable(Catch2)

View File

@ -26,7 +26,7 @@ Ongoing development happens in the `v2.x` branch for Catch2 v2, and in
Commits should be small and atomic. A commit is atomic when, after it is Commits should be small and atomic. A commit is atomic when, after it is
applied, the codebase, tests and all, still works as expected. Small applied, the codebase, tests and all, still works as expected. Small
commits are also prefered, as they make later operations with git history, commits are also preferred, as they make later operations with git history,
whether it is bisecting, reverting, or something else, easier. whether it is bisecting, reverting, or something else, easier.
_When submitting a pull request please do not include changes to the _When submitting a pull request please do not include changes to the

View File

@ -104,6 +104,20 @@ Both of these solutions have their problems, but should let you wring parallelis
## 3rd party bugs ## 3rd party bugs
This section outlines known bugs in 3rd party components (this means compilers, standard libraries, standard runtimes). This section outlines known bugs in 3rd party components (this means compilers, standard libraries, standard runtimes).
### Visual Studio 2015 -- `GENERATE` does not compile if it would deduce char array
VS 2015 refuses to compile `GENERATE` statements that would deduce to a
char array with known size, e.g. this:
```cpp
TEST_CASE("Deducing string lit") {
auto param = GENERATE("start", "stop");
}
```
A workaround for this is to use the `as` helper and force deduction of
either a `char const*` or a `std::string`.
### Visual Studio 2017 -- raw string literal in assert fails to compile ### Visual Studio 2017 -- raw string literal in assert fails to compile
There is a known bug in Visual Studio 2017 (VC 15), that causes compilation error when preprocessor attempts to stringize a raw string literal (`#` preprocessor is applied to it). This snippet is sufficient to trigger the compilation error: There is a known bug in Visual Studio 2017 (VC 15), that causes compilation error when preprocessor attempts to stringize a raw string literal (`#` preprocessor is applied to it). This snippet is sufficient to trigger the compilation error:
```cpp ```cpp

View File

@ -121,7 +121,7 @@ constructor, or before Catch2's session is created in user's own main._
`ANON_TEST_CASE` is a `TEST_CASE` replacement that will autogenerate `ANON_TEST_CASE` is a `TEST_CASE` replacement that will autogenerate
unique name. The advantage of this is that you do not have to think unique name. The advantage of this is that you do not have to think
of a name for the test case,`the disadvantage is that the name doesn't of a name for the test case, the disadvantage is that the name doesn't
necessarily remain stable across different links, and thus it might be necessarily remain stable across different links, and thus it might be
hard to run directly. hard to run directly.

View File

@ -2,6 +2,12 @@
# Release notes # Release notes
**Contents**<br> **Contents**<br>
[2.13.10](#21310)<br>
[2.13.9](#2139)<br>
[2.13.8](#2138)<br>
[2.13.7](#2137)<br>
[2.13.6](#2136)<br>
[2.13.5](#2135)<br>
[2.13.4](#2134)<br> [2.13.4](#2134)<br>
[2.13.3](#2133)<br> [2.13.3](#2133)<br>
[2.13.2](#2132)<br> [2.13.2](#2132)<br>
@ -45,6 +51,74 @@
[Even Older versions](#even-older-versions)<br> [Even Older versions](#even-older-versions)<br>
## 2.13.10
### Fixes
* Fixed issue with `catch_discover_tests` when there is multiple of 256 tests (#2401, #2503)
* Catch2-provided `main` and `wmain` are explicitly marked as `__cdecl` when compiled with MSVC (#2486, #2487)
* Improved break-into-debugger behaviour for ARM Macs. It should now be possible to step execution after the break (#2422)
* Replaced deprecated `std::aligned_storage` (#2419, #2420)
## 2.13.9
### Fixes
* Fixed issue with `-#` (filename-as-tag) flag when `__FILE__` expands into filename without directories (#2328, #2393)
* Fixed `CAPTURE` macro not being variadic when disabled through `CATCH_CONFIG_DISABLE` (#2316, #2378)
## 2.13.8
### Fixes
* Made `Approx::operator()` const (#2288)
* Improved pkg-config files (#2284)
* Fixed warning suppression leaking out of Catch2 when compiled with clang.exe (#2280)
* The macro-generated names for things like `TEST_CASE` no longer create reserved identifiers (#2336)
### Improvements
* Clang-tidy should no longer warn about missing virtual dispatch in `FilterGenerator`'s constructor (#2314)
## 2.13.7
### Fixes
* Added missing `<iterator>` include in benchmarking. (#2231)
* Fixed noexcept build with benchmarking enabled (#2235)
* Fixed build for compilers with C++17 support but without C++17 library support (#2195)
* JUnit only uses 3 decimal places when reporting durations (#2221)
* `!mayfail` tagged tests are now marked as `skipped` in JUnit reporter output (#2116)
## 2.13.6
### Fixes
* Disabling all signal handlers no longer breaks compilation (#2212, #2213)
### Miscellaneous
* `catch_discover_tests` should handle escaped semicolon (`;`) better (#2214, #2215)
## 2.13.5
### Improvements
* Detection of MAC and IPHONE platforms has been improved (#2140, #2157)
* Added workaround for bug in XLC 16.1.0.1 (#2155)
* Add detection for LCC when it is masquerading as GCC (#2199)
* Modified posix signal handling so it supports newer libcs (#2178)
* `MINSIGSTKSZ` was no longer usable in constexpr context.
### Fixes
* Fixed compilation of benchmarking when `min` and `max` macros are defined (#2159)
* Including `windows.h` without `NOMINMAX` remains a really bad idea, don't do it
### Miscellaneous
* `Catch2WithMain` target (static library) is no longer built by default (#2142)
* Building it by default was at best unnecessary overhead for people not using it, and at worst it caused trouble with install paths
* To have it built, set CMake option `CATCH_BUILD_STATIC_LIBRARY` to `ON`
* The check whether Catch2 is being built as a subproject is now more reliable (#2202, #2204)
* The problem was that if the variable name used internally was defined the project including Catch2 as subproject, it would not be properly overwritten for Catch2's CMake.
## 2.13.4 ## 2.13.4
### Improvements ### Improvements

View File

@ -43,7 +43,7 @@ TEST_CASE("Table allows pre-computed test inputs and outputs", "[example][genera
/* Possible simplifications where less legacy toolchain support is needed: /* Possible simplifications where less legacy toolchain support is needed:
* *
* - With libstdc++6 or newer, the make_tuple() calls can be ommitted * - With libstdc++6 or newer, the make_tuple() calls can be omitted
* (technically C++17 but does not require -std in GCC/Clang). See * (technically C++17 but does not require -std in GCC/Clang). See
* https://stackoverflow.com/questions/12436586/tuple-vector-and-initializer-list * https://stackoverflow.com/questions/12436586/tuple-vector-and-initializer-list
* *

View File

@ -11,7 +11,7 @@
#define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 13 #define CATCH_VERSION_MINOR 13
#define CATCH_VERSION_PATCH 4 #define CATCH_VERSION_PATCH 10
#ifdef __clang__ #ifdef __clang__
# pragma clang system_header # pragma clang system_header
@ -195,9 +195,9 @@
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
#define CATCH_BENCHMARK(...) \ #define CATCH_BENCHMARK(...) \
INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
#define CATCH_BENCHMARK_ADVANCED(name) \ #define CATCH_BENCHMARK_ADVANCED(name) \
INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name)
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
@ -301,9 +301,9 @@
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
#define BENCHMARK(...) \ #define BENCHMARK(...) \
INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
#define BENCHMARK_ADVANCED(name) \ #define BENCHMARK_ADVANCED(name) \
INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name)
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
using Catch::Detail::Approx; using Catch::Detail::Approx;
@ -350,8 +350,8 @@ using Catch::Detail::Approx;
#define CATCH_WARN( msg ) (void)(0) #define CATCH_WARN( msg ) (void)(0)
#define CATCH_CAPTURE( msg ) (void)(0) #define CATCH_CAPTURE( msg ) (void)(0)
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) #define CATCH_METHOD_AS_TEST_CASE( method, ... )
#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
#define CATCH_SECTION( ... ) #define CATCH_SECTION( ... )
@ -360,7 +360,7 @@ using Catch::Detail::Approx;
#define CATCH_FAIL_CHECK( ... ) (void)(0) #define CATCH_FAIL_CHECK( ... ) (void)(0)
#define CATCH_SUCCEED( ... ) (void)(0) #define CATCH_SUCCEED( ... ) (void)(0)
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
@ -383,8 +383,8 @@ using Catch::Detail::Approx;
#endif #endif
// "BDD-style" convenience wrappers // "BDD-style" convenience wrappers
#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_AND_GIVEN( desc )
#define CATCH_WHEN( desc ) #define CATCH_WHEN( desc )
@ -433,10 +433,10 @@ using Catch::Detail::Approx;
#define INFO( msg ) (void)(0) #define INFO( msg ) (void)(0)
#define UNSCOPED_INFO( msg ) (void)(0) #define UNSCOPED_INFO( msg ) (void)(0)
#define WARN( msg ) (void)(0) #define WARN( msg ) (void)(0)
#define CAPTURE( msg ) (void)(0) #define CAPTURE( ... ) (void)(0)
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#define METHOD_AS_TEST_CASE( method, ... ) #define METHOD_AS_TEST_CASE( method, ... )
#define REGISTER_TEST_CASE( Function, ... ) (void)(0) #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
#define SECTION( ... ) #define SECTION( ... )
@ -444,7 +444,7 @@ using Catch::Detail::Approx;
#define FAIL( ... ) (void)(0) #define FAIL( ... ) (void)(0)
#define FAIL_CHECK( ... ) (void)(0) #define FAIL_CHECK( ... ) (void)(0)
#define SUCCEED( ... ) (void)(0) #define SUCCEED( ... ) (void)(0)
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
@ -474,8 +474,8 @@ using Catch::Detail::Approx;
#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
// "BDD-style" convenience wrappers // "BDD-style" convenience wrappers
#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ) )
#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 AND_GIVEN( desc )

View File

@ -19,8 +19,6 @@ namespace Catch {
template <typename T, bool Destruct> template <typename T, bool Destruct>
struct ObjectStorage struct ObjectStorage
{ {
using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
ObjectStorage() : data() {} ObjectStorage() : data() {}
ObjectStorage(const ObjectStorage& other) ObjectStorage(const ObjectStorage& other)
@ -64,7 +62,7 @@ namespace Catch {
} }
TStorage data; struct { alignas(T) unsigned char data[sizeof(T)]; } data;
}; };
} }

View File

@ -19,6 +19,7 @@
#include "detail/catch_run_for_at_least.hpp" #include "detail/catch_run_for_at_least.hpp"
#include <algorithm> #include <algorithm>
#include <iterator>
namespace Catch { namespace Catch {
namespace Benchmark { namespace Benchmark {

View File

@ -56,7 +56,7 @@ namespace Catch {
} }
iters *= 2; iters *= 2;
} }
throw optimized_away_error{}; Catch::throw_exception(optimized_away_error{});
} }
} // namespace Detail } // namespace Detail
} // namespace Benchmark } // namespace Benchmark

View File

@ -33,7 +33,7 @@ namespace Detail {
Approx operator-() const; Approx operator-() const;
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 ) const {
Approx approx( static_cast<double>(value) ); Approx approx( static_cast<double>(value) );
approx.m_epsilon = m_epsilon; approx.m_epsilon = m_epsilon;
approx.m_margin = m_margin; approx.m_margin = m_margin;

View File

@ -39,9 +39,9 @@
#endif #endif
// We have to avoid both ICC and Clang, because they try to mask themselves // Only GCC compiler should be used in this block, so other compilers trying to
// as gcc, and we want only GCC in this block // mask themselves as GCC should be ignored.
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) #if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__)
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
@ -146,10 +146,6 @@
// Visual C++ // Visual C++
#if defined(_MSC_VER) #if defined(_MSC_VER)
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) )
// Universal Windows platform does not support SEH // Universal Windows platform does not support SEH
// Or console colours (or console at all...) // Or console colours (or console at all...)
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
@ -158,13 +154,18 @@
# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
# endif # endif
# if !defined(__clang__) // Handle Clang masquerading for msvc
// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ // MSVC traditional preprocessor needs some workaround for __VA_ARGS__
// _MSVC_TRADITIONAL == 0 means new conformant preprocessor // _MSVC_TRADITIONAL == 0 means new conformant preprocessor
// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
# if !defined(__clang__) // Handle Clang masquerading for msvc
# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) # if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR # define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
# endif // MSVC_TRADITIONAL # endif // MSVC_TRADITIONAL
// Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop`
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) )
# endif // __clang__ # endif // __clang__
#endif // _MSC_VER #endif // _MSC_VER
@ -234,7 +235,7 @@
// Check if byte is available and usable // Check if byte is available and usable
# if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
# include <cstddef> # include <cstddef>
# if __cpp_lib_byte > 0 # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE # define CATCH_INTERNAL_CONFIG_CPP17_BYTE
# endif # endif
# endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) # endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)

View File

@ -121,7 +121,10 @@ namespace {
#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// #elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
#if defined( CATCH_PLATFORM_LINUX ) || defined( CATCH_PLATFORM_MAC )
# define CATCH_INTERNAL_HAS_ISATTY
# include <unistd.h> # include <unistd.h>
#endif
namespace Catch { namespace Catch {
namespace { namespace {
@ -170,7 +173,8 @@ namespace {
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE) #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
!isDebuggerActive() && !isDebuggerActive() &&
#endif #endif
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) #if defined( CATCH_INTERNAL_HAS_ISATTY ) && \
!( defined( __DJGPP__ ) && defined( __STRICT_ANSI__ ) )
isatty(STDOUT_FILENO) isatty(STDOUT_FILENO)
#else #else
false false

View File

@ -20,7 +20,7 @@ namespace Catch {
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
#elif defined(__aarch64__) #elif defined(__aarch64__)
#define CATCH_TRAP() __asm__(".inst 0xd4200000") #define CATCH_TRAP() __asm__(".inst 0xd43e0000")
#endif #endif
#elif defined(CATCH_PLATFORM_IPHONE) #elif defined(CATCH_PLATFORM_IPHONE)

View File

@ -13,12 +13,20 @@
#ifndef __OBJC__ #ifndef __OBJC__
#ifndef CATCH_INTERNAL_CDECL
#ifdef _MSC_VER
#define CATCH_INTERNAL_CDECL __cdecl
#else
#define CATCH_INTERNAL_CDECL
#endif
#endif
#if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) #if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
// Standard C/C++ Win32 Unicode wmain entry point // Standard C/C++ Win32 Unicode wmain entry point
extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { extern "C" int CATCH_INTERNAL_CDECL wmain (int argc, wchar_t * argv[], wchar_t * []) {
#else #else
// Standard C/C++ main entry point // Standard C/C++ main entry point
int main (int argc, char * argv[]) { int CATCH_INTERNAL_CDECL main (int argc, char * argv[]) {
#endif #endif
return Catch::Session().run( argc, argv ); return Catch::Session().run( argc, argv );

View File

@ -22,7 +22,7 @@ namespace Catch {
// Extracts the actual name part of an enum instance // Extracts the actual name part of an enum instance
// In other words, it returns the Blue part of Bikeshed::Colour::Blue // In other words, it returns the Blue part of Bikeshed::Colour::Blue
StringRef extractInstanceName(StringRef enumInstance) { StringRef extractInstanceName(StringRef enumInstance) {
// Find last occurence of ":" // Find last occurrence of ":"
size_t name_start = enumInstance.size(); size_t name_start = enumInstance.size();
while (name_start > 0 && enumInstance[name_start - 1] != ':') { while (name_start > 0 && enumInstance[name_start - 1] != ':') {
--name_start; --name_start;

View File

@ -7,30 +7,72 @@
* *
*/ */
/** \file
* This file provides platform specific implementations of FatalConditionHandler
*
* This means that there is a lot of conditional compilation, and platform
* specific code. Currently, Catch2 supports a dummy handler (if no
* handler is desired), and 2 platform specific handlers:
* * Windows' SEH
* * POSIX signals
*
* Consequently, various pieces of code below are compiled if either of
* the platform specific handlers is enabled, or if none of them are
* enabled. It is assumed that both cannot be enabled at the same time,
* and doing so should cause a compilation error.
*
* If another platform specific handler is added, the compile guards
* below will need to be updated taking these assumptions into account.
*/
#include "catch_fatal_condition.h" #include "catch_fatal_condition.h"
#include "catch_context.h" #include "catch_context.h"
#include "catch_interfaces_capture.h" #include "catch_enforce.h"
#include "catch_run_context.h"
#include "catch_windows_h_proxy.h"
#if defined(__GNUC__) #include <algorithm>
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wmissing-field-initializers" #if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS )
#endif
namespace Catch {
// If neither SEH nor signal handling is required, the handler impls
// do not have to do anything, and can be empty.
void FatalConditionHandler::engage_platform() {}
void FatalConditionHandler::disengage_platform() {}
FatalConditionHandler::FatalConditionHandler() = default;
FatalConditionHandler::~FatalConditionHandler() = default;
} // end namespace Catch
#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS
#if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS )
#error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time"
#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS
#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
namespace { namespace {
// Report the error condition //! Signals fatal error message to the run context
void reportFatal( char const * const message ) { void reportFatal( char const * const message ) {
Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
} }
}
#endif // signals/SEH handling //! Minimal size Catch2 needs for its own fatal error handling.
//! Picked anecdotally, so it might not be sufficient on all
//! platforms, and for all configurations.
constexpr std::size_t minStackSizeForErrors = 32 * 1024;
} // end unnamed namespace
#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS
#if defined( CATCH_CONFIG_WINDOWS_SEH ) #if defined( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch { namespace Catch {
struct SignalDefs { DWORD id; const char* name; }; struct SignalDefs { DWORD id; const char* name; };
// There is no 1-1 mapping between signals and windows exceptions. // There is no 1-1 mapping between signals and windows exceptions.
@ -43,7 +85,7 @@ namespace Catch {
{ static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" }, { static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },
}; };
LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
for (auto const& def : signalDefs) { for (auto const& def : signalDefs) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
reportFatal(def.name); reportFatal(def.name);
@ -54,39 +96,52 @@ namespace Catch {
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;
} }
// Since we do not support multiple instantiations, we put these
// into global variables and rely on cleaning them up in outlined
// constructors/destructors
static PVOID exceptionHandlerHandle = nullptr;
// For MSVC, we reserve part of the stack memory for handling
// memory overflow structured exception.
FatalConditionHandler::FatalConditionHandler() { FatalConditionHandler::FatalConditionHandler() {
isSet = true; ULONG guaranteeSize = static_cast<ULONG>(minStackSizeForErrors);
// 32k seems enough for Catch to handle stack overflow, if (!SetThreadStackGuarantee(&guaranteeSize)) {
// but the value was found experimentally, so there is no strong guarantee // We do not want to fully error out, because needing
guaranteeSize = 32 * 1024; // the stack reserve should be rare enough anyway.
exceptionHandlerHandle = nullptr; Catch::cerr()
<< "Failed to reserve piece of stack."
<< " Stack overflows will not be reported successfully.";
}
}
// We do not attempt to unset the stack guarantee, because
// Windows does not support lowering the stack size guarantee.
FatalConditionHandler::~FatalConditionHandler() = default;
void FatalConditionHandler::engage_platform() {
// Register as first handler in current chain // Register as first handler in current chain
exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
// Pass in guarantee size to be filled if (!exceptionHandlerHandle) {
SetThreadStackGuarantee(&guaranteeSize); CATCH_RUNTIME_ERROR("Could not register vectored exception handler");
}
} }
void FatalConditionHandler::reset() { void FatalConditionHandler::disengage_platform() {
if (isSet) { if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) {
RemoveVectoredExceptionHandler(exceptionHandlerHandle); CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler");
SetThreadStackGuarantee(&guaranteeSize); }
exceptionHandlerHandle = nullptr; exceptionHandlerHandle = nullptr;
isSet = false;
}
} }
FatalConditionHandler::~FatalConditionHandler() { } // end namespace Catch
reset();
}
bool FatalConditionHandler::isSet = false; #endif // CATCH_CONFIG_WINDOWS_SEH
ULONG FatalConditionHandler::guaranteeSize = 0;
PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
#if defined( CATCH_CONFIG_POSIX_SIGNALS )
} // namespace Catch #include <signal.h>
#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
namespace Catch { namespace Catch {
@ -95,10 +150,6 @@ namespace Catch {
const char* name; const char* name;
}; };
// 32kb for the alternate stack seems to be sufficient. However, this value
// is experimentally determined, so that's not guaranteed.
static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
static SignalDefs signalDefs[] = { static SignalDefs signalDefs[] = {
{ SIGINT, "SIGINT - Terminal interrupt signal" }, { SIGINT, "SIGINT - Terminal interrupt signal" },
{ SIGILL, "SIGILL - Illegal instruction signal" }, { SIGILL, "SIGILL - Illegal instruction signal" },
@ -108,8 +159,32 @@ namespace Catch {
{ SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
}; };
// Older GCCs trigger -Wmissing-field-initializers for T foo = {}
// which is zero initialization, but not explicit. We want to avoid
// that.
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
void FatalConditionHandler::handleSignal( int sig ) { static char* altStackMem = nullptr;
static std::size_t altStackSize = 0;
static stack_t oldSigStack{};
static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
static void restorePreviousSignalHandlers() {
// We set signal handlers back to the previous ones. Hopefully
// nobody overwrote them in the meantime, and doesn't expect
// their signal handlers to live past ours given that they
// installed them after ours..
for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
}
// Return the old stack
sigaltstack(&oldSigStack, nullptr);
}
static void handleSignal( int sig ) {
char const * name = "<unknown signal>"; char const * name = "<unknown signal>";
for (auto const& def : signalDefs) { for (auto const& def : signalDefs) {
if (sig == def.id) { if (sig == def.id) {
@ -117,16 +192,33 @@ namespace Catch {
break; break;
} }
} }
reset(); // We need to restore previous signal handlers and let them do
// their thing, so that the users can have the debugger break
// when a signal is raised, and so on.
restorePreviousSignalHandlers();
reportFatal( name ); reportFatal( name );
raise( sig ); raise( sig );
} }
FatalConditionHandler::FatalConditionHandler() { FatalConditionHandler::FatalConditionHandler() {
isSet = true; assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists");
if (altStackSize == 0) {
altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors);
}
altStackMem = new char[altStackSize]();
}
FatalConditionHandler::~FatalConditionHandler() {
delete[] altStackMem;
// We signal that another instance can be constructed by zeroing
// out the pointer.
altStackMem = nullptr;
}
void FatalConditionHandler::engage_platform() {
stack_t sigStack; stack_t sigStack;
sigStack.ss_sp = altStackMem; sigStack.ss_sp = altStackMem;
sigStack.ss_size = sigStackSize; sigStack.ss_size = altStackSize;
sigStack.ss_flags = 0; sigStack.ss_flags = 0;
sigaltstack(&sigStack, &oldSigStack); sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = { }; struct sigaction sa = { };
@ -138,39 +230,15 @@ namespace Catch {
} }
} }
FatalConditionHandler::~FatalConditionHandler() {
reset();
}
void FatalConditionHandler::reset() {
if( isSet ) {
// Set signals back to previous values -- hopefully nobody overwrote them in the meantime
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
}
// Return the old stack
sigaltstack(&oldSigStack, nullptr);
isSet = false;
}
}
bool FatalConditionHandler::isSet = false;
struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
stack_t FatalConditionHandler::oldSigStack = {};
char FatalConditionHandler::altStackMem[sigStackSize] = {};
} // namespace Catch
#else
namespace Catch {
void FatalConditionHandler::reset() {}
}
#endif // signals/SEH handling
#if defined(__GNUC__) #if defined(__GNUC__)
# pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif #endif
void FatalConditionHandler::disengage_platform() {
restorePreviousSignalHandlers();
}
} // end namespace Catch
#endif // CATCH_CONFIG_POSIX_SIGNALS

View File

@ -11,59 +11,58 @@
#include "catch_platform.h" #include "catch_platform.h"
#include "catch_compiler_capabilities.h" #include "catch_compiler_capabilities.h"
#include "catch_windows_h_proxy.h"
#include <cassert>
#if defined( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch { namespace Catch {
struct FatalConditionHandler { // Wrapper for platform-specific fatal error (signals/SEH) handlers
//
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); // Tries to be cooperative with other handlers, and not step over
FatalConditionHandler(); // other handlers. This means that unknown structured exceptions
static void reset(); // are passed on, previous signal handlers are called, and so on.
~FatalConditionHandler(); //
// Can only be instantiated once, and assumes that once a signal
private: // is caught, the binary will end up terminating. Thus, there
static bool isSet; class FatalConditionHandler {
static ULONG guaranteeSize; bool m_started = false;
static PVOID exceptionHandlerHandle;
};
} // namespace Catch
#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
#include <signal.h>
namespace Catch {
struct FatalConditionHandler {
static bool isSet;
static struct sigaction oldSigActions[];
static stack_t oldSigStack;
static char altStackMem[];
static void handleSignal( int sig );
// Install/disengage implementation for specific platform.
// Should be if-defed to work on current platform, can assume
// engage-disengage 1:1 pairing.
void engage_platform();
void disengage_platform();
public:
// Should also have platform-specific implementations as needed
FatalConditionHandler(); FatalConditionHandler();
~FatalConditionHandler(); ~FatalConditionHandler();
static void reset();
};
} // namespace Catch void engage() {
assert(!m_started && "Handler cannot be installed twice.");
m_started = true;
#else engage_platform();
namespace Catch {
struct FatalConditionHandler {
void reset();
};
} }
#endif void disengage() {
assert(m_started && "Handler cannot be uninstalled without being installed first");
m_started = false;
disengage_platform();
}
};
//! Simple RAII guard for (dis)engaging the FatalConditionHandler
class FatalConditionHandlerGuard {
FatalConditionHandler* m_handler;
public:
FatalConditionHandlerGuard(FatalConditionHandler* handler):
m_handler(handler) {
m_handler->engage();
}
~FatalConditionHandlerGuard() {
m_handler->disengage();
}
};
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED #endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED

View File

@ -63,7 +63,7 @@ namespace Generators {
if (!m_predicate(m_generator.get())) { if (!m_predicate(m_generator.get())) {
// It might happen that there are no values that pass the // It might happen that there are no values that pass the
// filter. In that case we throw an exception. // filter. In that case we throw an exception.
auto has_initial_value = next(); auto has_initial_value = nextImpl();
if (!has_initial_value) { if (!has_initial_value) {
Catch::throw_exception(GeneratorException("No valid value found in filtered generator")); Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));
} }
@ -75,6 +75,11 @@ namespace Generators {
} }
bool next() override { bool next() override {
return nextImpl();
}
private:
bool nextImpl() {
bool success = m_generator.next(); bool success = m_generator.next();
if (!success) { if (!success) {
return false; return false;

View File

@ -21,6 +21,8 @@
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
#include "benchmark/catch_estimate.hpp" #include "benchmark/catch_estimate.hpp"
#include "benchmark/catch_outlier_classification.hpp" #include "benchmark/catch_outlier_classification.hpp"
#include <iterator>
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING #endif // CATCH_CONFIG_ENABLE_BENCHMARKING

View File

@ -452,9 +452,8 @@ namespace Catch {
} }
void RunContext::invokeActiveTestCase() { void RunContext::invokeActiveTestCase() {
FatalConditionHandler fatalConditionHandler; // Handle signals FatalConditionHandlerGuard _(&m_fatalConditionhandler);
m_activeTestCase->invoke(); m_activeTestCase->invoke();
fatalConditionHandler.reset();
} }
void RunContext::handleUnfinishedSections() { void RunContext::handleUnfinishedSections() {

View File

@ -146,6 +146,7 @@ namespace Catch {
std::vector<SectionEndInfo> m_unfinishedSections; std::vector<SectionEndInfo> m_unfinishedSections;
std::vector<ITracker*> m_activeSections; std::vector<ITracker*> m_activeSections;
TrackerContext m_trackerContext; TrackerContext m_trackerContext;
FatalConditionHandler m_fatalConditionhandler;
bool m_lastAssertionPassed = false; bool m_lastAssertionPassed = false;
bool m_shouldReportUnexpected = true; bool m_shouldReportUnexpected = true;
bool m_includeSuccessfulResults; bool m_includeSuccessfulResults;

View File

@ -127,6 +127,10 @@ namespace Catch {
filename.erase(0, lastSlash); filename.erase(0, lastSlash);
filename[0] = '#'; filename[0] = '#';
} }
else
{
filename.insert(0, "#");
}
auto lastDot = filename.find_last_of('.'); auto lastDot = filename.find_last_of('.');
if (lastDot != std::string::npos) { if (lastDot != std::string::npos) {
@ -289,7 +293,7 @@ namespace Catch {
// Handle list request // Handle list request
if( Option<std::size_t> listed = list( m_config ) ) if( Option<std::size_t> listed = list( m_config ) )
return static_cast<int>( *listed ); return (std::min) (MaxExitCode, static_cast<int>(*listed));
TestGroup tests { m_config }; TestGroup tests { m_config };
auto const totals = tests.execute(); auto const totals = tests.execute();

View File

@ -71,34 +71,34 @@ struct AutoReg : NonCopyable {
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
#endif #endif
#endif #endif
@ -111,7 +111,7 @@ struct AutoReg : NonCopyable {
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
static void TestName() static void TestName()
#define INTERNAL_CATCH_TESTCASE( ... ) \ #define INTERNAL_CATCH_TESTCASE( ... ) \
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), __VA_ARGS__ )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
@ -133,7 +133,7 @@ struct AutoReg : NonCopyable {
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
void TestName::test() void TestName::test()
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), ClassName, __VA_ARGS__ )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
@ -174,18 +174,18 @@ struct AutoReg : NonCopyable {
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) )
#endif #endif
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
@ -223,18 +223,18 @@ struct AutoReg : NonCopyable {
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T,__VA_ARGS__) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T,__VA_ARGS__)
#else #else
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T, __VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__)
#else #else
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) )
#endif #endif
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\ #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
@ -265,7 +265,7 @@ struct AutoReg : NonCopyable {
static void TestFunc() static void TestFunc()
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \ #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, TmplList ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, TmplList )
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
@ -299,18 +299,18 @@ struct AutoReg : NonCopyable {
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
#endif #endif
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
@ -351,18 +351,18 @@ struct AutoReg : NonCopyable {
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) )
#endif #endif
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \ #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
@ -396,7 +396,7 @@ struct AutoReg : NonCopyable {
void TestName<TestType>::test() void TestName<TestType>::test()
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \ #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, TmplList ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, TmplList )
#endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED

View File

@ -37,7 +37,7 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 2, 13, 4, "", 0 ); static Version version( 2, 13, 10, "", 0 );
return version; return version;
} }

View File

@ -18,6 +18,7 @@
#include <sstream> #include <sstream>
#include <ctime> #include <ctime>
#include <algorithm> #include <algorithm>
#include <iomanip>
namespace Catch { namespace Catch {
@ -45,7 +46,7 @@ namespace Catch {
#else #else
std::strftime(timeStamp, timeStampSize, fmt, timeInfo); std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
#endif #endif
return std::string(timeStamp); return std::string(timeStamp, timeStampSize-1);
} }
std::string fileNameTag(const std::vector<std::string> &tags) { std::string fileNameTag(const std::vector<std::string> &tags) {
@ -56,6 +57,17 @@ namespace Catch {
return it->substr(1); return it->substr(1);
return std::string(); return std::string();
} }
// Formats the duration in seconds to 3 decimal places.
// This is done because some genius defined Maven Surefire schema
// in a way that only accepts 3 decimal places, and tools like
// Jenkins use that schema for validation JUnit reporter output.
std::string formatDuration( double seconds ) {
ReusableStringStream rss;
rss << std::fixed << std::setprecision( 3 ) << seconds;
return rss.str();
}
} // anonymous namespace } // anonymous namespace
JunitReporter::JunitReporter( ReporterConfig const& _config ) JunitReporter::JunitReporter( ReporterConfig const& _config )
@ -125,7 +137,7 @@ namespace Catch {
if( m_config->showDurations() == ShowDurations::Never ) if( m_config->showDurations() == ShowDurations::Never )
xml.writeAttribute( "time", "" ); xml.writeAttribute( "time", "" );
else else
xml.writeAttribute( "time", suiteTime ); xml.writeAttribute( "time", formatDuration( suiteTime ) );
xml.writeAttribute( "timestamp", getCurrentTimestamp() ); xml.writeAttribute( "timestamp", getCurrentTimestamp() );
// Write properties if there are any // Write properties if there are any
@ -170,12 +182,13 @@ namespace Catch {
if ( !m_config->name().empty() ) if ( !m_config->name().empty() )
className = m_config->name() + "." + className; className = m_config->name() + "." + className;
writeSection( className, "", rootSection ); writeSection( className, "", rootSection, stats.testInfo.okToFail() );
} }
void JunitReporter::writeSection( std::string const& className, void JunitReporter::writeSection( std::string const& className,
std::string const& rootName, std::string const& rootName,
SectionNode const& sectionNode ) { SectionNode const& sectionNode,
bool testOkToFail) {
std::string name = trim( sectionNode.stats.sectionInfo.name ); std::string name = trim( sectionNode.stats.sectionInfo.name );
if( !rootName.empty() ) if( !rootName.empty() )
name = rootName + '/' + name; name = rootName + '/' + name;
@ -192,15 +205,21 @@ namespace Catch {
xml.writeAttribute( "classname", className ); xml.writeAttribute( "classname", className );
xml.writeAttribute( "name", name ); xml.writeAttribute( "name", name );
} }
xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) ); xml.writeAttribute( "time", formatDuration( sectionNode.stats.durationInSeconds ) );
// This is not ideal, but it should be enough to mimic gtest's // This is not ideal, but it should be enough to mimic gtest's
// junit output. // junit output.
// Ideally the JUnit reporter would also handle `skipTest` // Ideally the JUnit reporter would also handle `skipTest`
// events and write those out appropriately. // events and write those out appropriately.
xml.writeAttribute( "status", "run" ); xml.writeAttribute( "status", "run" );
if (sectionNode.stats.assertions.failedButOk) {
xml.scopedElement("skipped")
.writeAttribute("message", "TEST_CASE tagged with !mayfail");
}
writeAssertions( sectionNode ); writeAssertions( sectionNode );
if( !sectionNode.stdOut.empty() ) if( !sectionNode.stdOut.empty() )
xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline ); xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline );
if( !sectionNode.stdErr.empty() ) if( !sectionNode.stdErr.empty() )
@ -208,9 +227,9 @@ namespace Catch {
} }
for( auto const& childNode : sectionNode.childSections ) for( auto const& childNode : sectionNode.childSections )
if( className.empty() ) if( className.empty() )
writeSection( name, "", *childNode ); writeSection( name, "", *childNode, testOkToFail );
else else
writeSection( className, name, *childNode ); writeSection( className, name, *childNode, testOkToFail );
} }
void JunitReporter::writeAssertions( SectionNode const& sectionNode ) { void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {

View File

@ -43,7 +43,8 @@ namespace Catch {
void writeSection( std::string const& className, void writeSection( std::string const& className,
std::string const& rootName, std::string const& rootName,
SectionNode const& sectionNode); SectionNode const& sectionNode,
bool testOkToFail );
void writeAssertions(SectionNode const& sectionNode); void writeAssertions(SectionNode const& sectionNode);
void writeAssertion(AssertionStats const& stats); void writeAssertion(AssertionStats const& stats);

View File

@ -354,7 +354,7 @@ endif()
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" ) if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code -Wpedantic -Wmissing-declarations ) target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code -Wpedantic -Wmissing-declarations )
if (CATCH_ENABLE_WERROR) if (CATCH_ENABLE_WERROR)
target_compile_options( SelfTest PRIVATE -Werror ) target_compile_options( SelfTest PRIVATE -Werror -Wno-error=pragmas )
endif() endif()
endif() endif()
# Clang specific options go here # Clang specific options go here

View File

@ -53,6 +53,7 @@ CATCH_TEST_CASE("PrefixedMacros") {
CATCH_SECTION("some section") { CATCH_SECTION("some section") {
int i = 1; int i = 1;
CATCH_CAPTURE( i ); CATCH_CAPTURE( i );
CATCH_CAPTURE( i, i + 1 );
CATCH_DYNAMIC_SECTION("Dynamic section: " << i) { CATCH_DYNAMIC_SECTION("Dynamic section: " << i) {
CATCH_FAIL_CHECK( "failure" ); CATCH_FAIL_CHECK( "failure" );
} }

View File

@ -26,6 +26,10 @@ foo f;
// This test should not be run, because it won't be registered // This test should not be run, because it won't be registered
TEST_CASE( "Disabled Macros" ) { TEST_CASE( "Disabled Macros" ) {
CAPTURE( 1 );
CAPTURE( 1, "captured" );
std::cout << "This should not happen\n"; std::cout << "This should not happen\n";
FAIL(); FAIL();
} }

View File

@ -628,6 +628,7 @@ GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3 GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: filter([] (int) { return false; }, value(1)), Catch::GeneratorException GeneratorsImpl.tests.cpp:<line number>: passed: filter([] (int) { return false; }, value(1)), Catch::GeneratorException
GeneratorsImpl.tests.cpp:<line number>: passed: filter( []( int ) { return false; }, values( { 1, 2, 3 } ) ), Catch::GeneratorException
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1 GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2 GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
@ -846,6 +847,10 @@ Matchers.tests.cpp:<line number>: passed: testStringForMatching(), (Contains("st
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), (Contains("string") || Contains("different")) && Contains("random") for: "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" ) Matchers.tests.cpp:<line number>: failed: testStringForMatching(), (Contains("string") || Contains("different")) && Contains("random") for: "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" )
Matchers.tests.cpp:<line number>: passed: testStringForMatching(), !Contains("different") for: "this string contains 'abc' as a substring" not contains: "different" Matchers.tests.cpp:<line number>: passed: testStringForMatching(), !Contains("different") for: "this string contains 'abc' as a substring" not contains: "different"
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), !Contains("substring") for: "this string contains 'abc' as a substring" not contains: "substring" Matchers.tests.cpp:<line number>: failed: testStringForMatching(), !Contains("substring") for: "this string contains 'abc' as a substring" not contains: "substring"
Condition.tests.cpp:<line number>: failed: explicitly
Condition.tests.cpp:<line number>: failed: explicitly
Condition.tests.cpp:<line number>: failed: explicitly
Condition.tests.cpp:<line number>: failed: explicitly
Exception.tests.cpp:<line number>: passed: thisThrows(), "expected exception" for: "expected exception" equals: "expected exception" Exception.tests.cpp:<line number>: passed: thisThrows(), "expected exception" for: "expected exception" equals: "expected exception"
Exception.tests.cpp:<line number>: failed: thisThrows(), "should fail" for: "expected exception" equals: "should fail" Exception.tests.cpp:<line number>: failed: thisThrows(), "should fail" for: "expected exception" equals: "should fail"
Generators.tests.cpp:<line number>: passed: values > -6 for: 3 > -6 Generators.tests.cpp:<line number>: passed: values > -6 for: 3 > -6

View File

@ -694,6 +694,46 @@ Matchers.tests.cpp:<line number>: FAILED:
with expansion: with expansion:
"this string contains 'abc' as a substring" not contains: "substring" "this string contains 'abc' as a substring" not contains: "substring"
-------------------------------------------------------------------------------
Mayfail test case with nested sections
A
1
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Mayfail test case with nested sections
A
2
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Mayfail test case with nested sections
B
1
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Mayfail test case with nested sections
B
2
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Mismatching exception messages failing the test Mismatching exception messages failing the test
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -1380,6 +1420,6 @@ due to unexpected exception with message:
Why would you throw a std::string? Why would you throw a std::string?
=============================================================================== ===============================================================================
test cases: 322 | 248 passed | 70 failed | 4 failed as expected test cases: 323 | 248 passed | 70 failed | 5 failed as expected
assertions: 1759 | 1607 passed | 131 failed | 21 failed as expected assertions: 1764 | 1608 passed | 131 failed | 25 failed as expected

View File

@ -4968,6 +4968,9 @@ with expansion:
GeneratorsImpl.tests.cpp:<line number>: PASSED: GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_AS( filter([] (int) { return false; }, value(1)), Catch::GeneratorException ) REQUIRE_THROWS_AS( filter([] (int) { return false; }, value(1)), Catch::GeneratorException )
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_AS( filter( []( int ) { return false; }, values( { 1, 2, 3 } ) ), Catch::GeneratorException )
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Generators internals Generators internals
Take generator Take generator
@ -6492,6 +6495,46 @@ Matchers.tests.cpp:<line number>: FAILED:
with expansion: with expansion:
"this string contains 'abc' as a substring" not contains: "substring" "this string contains 'abc' as a substring" not contains: "substring"
-------------------------------------------------------------------------------
Mayfail test case with nested sections
A
1
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Mayfail test case with nested sections
A
2
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Mayfail test case with nested sections
B
1
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Mayfail test case with nested sections
B
2
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Mismatching exception messages failing the test Mismatching exception messages failing the test
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -14138,6 +14181,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 322 | 232 passed | 86 failed | 4 failed as expected test cases: 323 | 232 passed | 86 failed | 5 failed as expected
assertions: 1776 | 1607 passed | 148 failed | 21 failed as expected assertions: 1781 | 1608 passed | 148 failed | 25 failed as expected

View File

@ -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="132" tests="1777" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="132" tests="1782" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties> <properties>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/> <property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/>
<property name="random-seed" value="1"/> <property name="random-seed" value="1"/>
@ -48,6 +48,7 @@ Nor would this
<testcase classname="<exe-name>.global" name="#1954 - 7 arg template test case sig compiles - 5, 1, 1, 1, 1, 0, 0" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="#1954 - 7 arg template test case sig compiles - 5, 1, 1, 1, 1, 0, 0" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="#1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="#1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}" status="run"> <testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}" status="run">
<skipped message="TEST_CASE tagged with !mayfail"/>
<error type="TEST_CASE"> <error type="TEST_CASE">
FAILED: FAILED:
expected exception expected exception
@ -56,6 +57,7 @@ Exception.tests.cpp:<line number>
</error> </error>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/inside REQUIRE_NOTHROW" time="{duration}" status="run"> <testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/inside REQUIRE_NOTHROW" time="{duration}" status="run">
<skipped message="TEST_CASE tagged with !mayfail"/>
<error message="thisThrows()" type="REQUIRE_NOTHROW"> <error message="thisThrows()" type="REQUIRE_NOTHROW">
FAILED: FAILED:
REQUIRE_NOTHROW( thisThrows() ) REQUIRE_NOTHROW( thisThrows() )
@ -68,6 +70,7 @@ Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="#809" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="#809" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="#833" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="#833" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="#835 -- errno should not be touched by Catch" time="{duration}" status="run"> <testcase classname="<exe-name>.global" name="#835 -- errno should not be touched by Catch" time="{duration}" status="run">
<skipped message="TEST_CASE tagged with !mayfail"/>
<failure message="f() == 0" type="CHECK"> <failure message="f() == 0" type="CHECK">
FAILED: FAILED:
CHECK( f() == 0 ) CHECK( f() == 0 )
@ -443,6 +446,7 @@ Matchers.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Enums in namespaces can quickly have stringification enabled using REGISTER_ENUM" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Enums in namespaces can quickly have stringification enabled using REGISTER_ENUM" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Epsilon only applies to Approx's value" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Epsilon only applies to Approx's value" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Equality checks that should fail" time="{duration}" status="run"> <testcase classname="<exe-name>.global" name="Equality checks that should fail" time="{duration}" status="run">
<skipped message="TEST_CASE tagged with !mayfail"/>
<failure message="data.int_seven == 6" type="CHECK"> <failure message="data.int_seven == 6" type="CHECK">
FAILED: FAILED:
CHECK( data.int_seven == 6 ) CHECK( data.int_seven == 6 )
@ -736,6 +740,7 @@ Message.tests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="Inequality checks that should fail" time="{duration}" status="run"> <testcase classname="<exe-name>.global" name="Inequality checks that should fail" time="{duration}" status="run">
<skipped message="TEST_CASE tagged with !mayfail"/>
<failure message="data.int_seven != 7" type="CHECK"> <failure message="data.int_seven != 7" type="CHECK">
FAILED: FAILED:
CHECK( data.int_seven != 7 ) CHECK( data.int_seven != 7 )
@ -799,6 +804,34 @@ with expansion:
Matchers.tests.cpp:<line number> Matchers.tests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="Mayfail test case with nested sections/1/A" time="{duration}" status="run">
<skipped message="TEST_CASE tagged with !mayfail"/>
<failure type="FAIL">
FAILED:
Condition.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.global" name="Mayfail test case with nested sections/2/A" time="{duration}" status="run">
<skipped message="TEST_CASE tagged with !mayfail"/>
<failure type="FAIL">
FAILED:
Condition.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.global" name="Mayfail test case with nested sections/1/B" time="{duration}" status="run">
<skipped message="TEST_CASE tagged with !mayfail"/>
<failure type="FAIL">
FAILED:
Condition.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.global" name="Mayfail test case with nested sections/2/B" time="{duration}" status="run">
<skipped message="TEST_CASE tagged with !mayfail"/>
<failure type="FAIL">
FAILED:
Condition.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.global" name="Mismatching exception messages failing the test" time="{duration}" status="run"> <testcase classname="<exe-name>.global" name="Mismatching exception messages failing the test" time="{duration}" status="run">
<failure message="thisThrows(), &quot;should fail&quot;" type="REQUIRE_THROWS_WITH"> <failure message="thisThrows(), &quot;should fail&quot;" type="REQUIRE_THROWS_WITH">
FAILED: FAILED:

View File

@ -575,6 +575,30 @@ Condition.tests.cpp:<line number>
</skipped> </skipped>
</testCase> </testCase>
<testCase name="Inequality checks that should succeed" duration="{duration}"/> <testCase name="Inequality checks that should succeed" duration="{duration}"/>
<testCase name="Mayfail test case with nested sections/1/A" duration="{duration}">
<skipped message="FAIL()">
FAILED:
Condition.tests.cpp:<line number>
</skipped>
</testCase>
<testCase name="Mayfail test case with nested sections/2/A" duration="{duration}">
<skipped message="FAIL()">
FAILED:
Condition.tests.cpp:<line number>
</skipped>
</testCase>
<testCase name="Mayfail test case with nested sections/1/B" duration="{duration}">
<skipped message="FAIL()">
FAILED:
Condition.tests.cpp:<line number>
</skipped>
</testCase>
<testCase name="Mayfail test case with nested sections/2/B" duration="{duration}">
<skipped message="FAIL()">
FAILED:
Condition.tests.cpp:<line number>
</skipped>
</testCase>
<testCase name="Ordering comparison checks that should fail" duration="{duration}"> <testCase name="Ordering comparison checks that should fail" duration="{duration}">
<failure message="CHECK(data.int_seven > 7)"> <failure message="CHECK(data.int_seven > 7)">
FAILED: FAILED:

View File

@ -5720,7 +5720,15 @@ Nor would this
filter([] (int) { return false; }, value(1)), Catch::GeneratorException filter([] (int) { return false; }, value(1)), Catch::GeneratorException
</Expanded> </Expanded>
</Expression> </Expression>
<OverallResults successes="5" failures="0" expectedFailures="0"/> <Expression success="true" type="REQUIRE_THROWS_AS" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
filter( []( int ) { return false; }, values( { 1, 2, 3 } ) ), Catch::GeneratorException
</Original>
<Expanded>
filter( []( int ) { return false; }, values( { 1, 2, 3 } ) ), Catch::GeneratorException
</Expanded>
</Expression>
<OverallResults successes="6" failures="0" expectedFailures="0"/>
</Section> </Section>
<Section name="Take generator" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" > <Section name="Take generator" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Section name="Take less" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" > <Section name="Take less" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
@ -7956,6 +7964,43 @@ Nor would this
</Expression> </Expression>
<OverallResult success="false"/> <OverallResult success="false"/>
</TestCase> </TestCase>
<TestCase name="Mayfail test case with nested sections" tags="[!mayfail]" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
<Section name="A" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
<Section name="1" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
<Failure filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" />
<OverallResults successes="0" failures="0" expectedFailures="1"/>
</Section>
<OverallResults successes="0" failures="0" expectedFailures="1"/>
</Section>
<Section name="A" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
<Section name="2" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
<Failure filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" />
<OverallResults successes="0" failures="0" expectedFailures="1"/>
</Section>
<OverallResults successes="0" failures="0" expectedFailures="1"/>
</Section>
<Section name="A" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
<OverallResults successes="0" failures="0" expectedFailures="0"/>
</Section>
<Section name="B" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
<Section name="1" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
<Failure filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" />
<OverallResults successes="0" failures="0" expectedFailures="1"/>
</Section>
<OverallResults successes="0" failures="0" expectedFailures="1"/>
</Section>
<Section name="B" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
<Section name="2" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
<Failure filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" />
<OverallResults successes="0" failures="0" expectedFailures="1"/>
</Section>
<OverallResults successes="0" failures="0" expectedFailures="1"/>
</Section>
<Section name="B" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
<OverallResults successes="0" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Mismatching exception messages failing the test" tags="[!hide][!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" > <TestCase name="Mismatching exception messages failing the test" tags="[!hide][!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
<Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" > <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
<Original> <Original>
@ -16722,9 +16767,9 @@ loose text artifact
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="1607" failures="149" expectedFailures="21"/> <OverallResults successes="1608" failures="149" expectedFailures="25"/>
<OverallResultsCases successes="232" failures="86" expectedFailures="4"/> <OverallResultsCases successes="232" failures="86" expectedFailures="5"/>
</Group> </Group>
<OverallResults successes="1607" failures="148" expectedFailures="21"/> <OverallResults successes="1608" failures="148" expectedFailures="25"/>
<OverallResultsCases successes="232" failures="86" expectedFailures="4"/> <OverallResultsCases successes="232" failures="86" expectedFailures="5"/>
</Catch> </Catch>

View File

@ -53,6 +53,9 @@ TEST_CASE("Generators internals", "[generators][internals]") {
// Completely filtered-out generator should throw on construction // Completely filtered-out generator should throw on construction
REQUIRE_THROWS_AS(filter([] (int) { return false; }, value(1)), Catch::GeneratorException); REQUIRE_THROWS_AS(filter([] (int) { return false; }, value(1)), Catch::GeneratorException);
REQUIRE_THROWS_AS(
filter( []( int ) { return false; }, values( { 1, 2, 3 } ) ),
Catch::GeneratorException );
} }
SECTION("Take generator") { SECTION("Take generator") {
SECTION("Take less") { SECTION("Take less") {

View File

@ -212,4 +212,11 @@ TEST_CASE( "Comparison with explicitly convertible types", "[Approx]" )
} }
TEST_CASE("Approx::operator() is const correct", "[Approx][.approvals]") {
const Approx ap = Approx(0.0).margin(0.01);
// As long as this compiles, the test should be considered passing
REQUIRE(1.0 == ap(1.0));
}
}} // namespace ApproxTests }} // namespace ApproxTests

View File

@ -89,6 +89,19 @@ TEST_CASE( "Equality checks that should fail", "[.][failing][!mayfail]" )
CHECK( x == Approx( 1.301 ) ); CHECK( x == Approx( 1.301 ) );
} }
// Needed to test junit reporter's handling of mayfail test cases and sections
TEST_CASE("Mayfail test case with nested sections", "[!mayfail]") {
SECTION("A") {
SECTION("1") { FAIL(); }
SECTION("2") { FAIL(); }
}
SECTION("B") {
SECTION("1") { FAIL(); }
SECTION("2") { FAIL(); }
}
}
TEST_CASE( "Inequality checks that should succeed" ) TEST_CASE( "Inequality checks that should succeed" )
{ {
TestData data; TestData data;

View File

@ -58,12 +58,12 @@ TEST_CASE("tables", "[generators]") {
// Structured bindings make the table utility much nicer to use // Structured bindings make the table utility much nicer to use
TEST_CASE( "strlen2", "[approvals][generators]" ) { TEST_CASE( "strlen2", "[approvals][generators]" ) {
auto [test_input, expected] = GENERATE( table<std::string, size_t>({ using tuple_type = std::tuple<std::string, int>; // see above workaround
{"one", 3}, auto [test_input, expected] =
{"two", 3}, GENERATE( table<std::string, size_t>( { tuple_type{ "one", 3 },
{"three", 5}, tuple_type{ "two", 3 },
{"four", 4} tuple_type{ "three", 5 },
})); tuple_type{ "four", 4 } } ) );
REQUIRE( test_input.size() == expected ); REQUIRE( test_input.size() == expected );
} }
@ -99,11 +99,9 @@ TEST_CASE( "strlen3", "[generators]" ) {
static auto eatCucumbers( int start, int eat ) -> int { return start-eat; } static auto eatCucumbers( int start, int eat ) -> int { return start-eat; }
SCENARIO("Eating cucumbers", "[generators][approvals]") { SCENARIO("Eating cucumbers", "[generators][approvals]") {
using tuple_type = std::tuple<int, int, int>;
auto [start, eat, left] = GENERATE( table<int,int,int> ({ auto [start, eat, left] = GENERATE( table<int, int, int>(
{ 12, 5, 7 }, { tuple_type{ 12, 5, 7 }, tuple_type{ 20, 5, 15 } } ) );
{ 20, 5, 15 }
}));
GIVEN( "there are " << start << " cucumbers" ) GIVEN( "there are " << start << " cucumbers" )
WHEN( "I eat " << eat << " cucumbers" ) WHEN( "I eat " << eat << " cucumbers" )

View File

@ -242,12 +242,14 @@ namespace { namespace MatchersTests {
~CustomAllocator() = default; ~CustomAllocator() = default;
#if defined(_MSC_VER) && _MSVC_LANG < 201703L
using std::allocator<T>::address; using std::allocator<T>::address;
using std::allocator<T>::allocate;
using std::allocator<T>::construct; using std::allocator<T>::construct;
using std::allocator<T>::deallocate;
using std::allocator<T>::max_size; using std::allocator<T>::max_size;
using std::allocator<T>::destroy; using std::allocator<T>::destroy;
#endif
using std::allocator<T>::allocate;
using std::allocator<T>::deallocate;
}; };
TEST_CASE("Vector matchers", "[matchers][vector]") { TEST_CASE("Vector matchers", "[matchers][vector]") {

View File

@ -241,6 +241,19 @@ std::ostream& operator<<(std::ostream& out, helper_1436<T1, T2> const& helper) {
return out; return out;
} }
// clang can handle GCC's diagnostic pragma
#if defined( __GNUG__ ) || defined(__clang__)
# pragma GCC diagnostic push
#endif
// Clang and gcc have different names for this warning, and clang also
// warns about an unused value
#if defined( __GNUG__ ) && !defined( __clang__ ) && \
( __GNUG__ > 10 || ( __GNUG__ == 10 && __GNUC_MINOR__ >= 1 ) )
#pragma GCC diagnostic ignored "-Wcomma-subscript"
#elif defined(__clang__)
#pragma clang diagnostic ignored "-Wdeprecated-comma-subscript"
#pragma clang diagnostic ignored "-Wunused-value"
#endif
TEST_CASE("CAPTURE can deal with complex expressions involving commas", "[messages][capture]") { TEST_CASE("CAPTURE can deal with complex expressions involving commas", "[messages][capture]") {
CAPTURE(std::vector<int>{1, 2, 3}[0, 1, 2], CAPTURE(std::vector<int>{1, 2, 3}[0, 1, 2],
std::vector<int>{1, 2, 3}[(0, 1)], std::vector<int>{1, 2, 3}[(0, 1)],
@ -250,6 +263,9 @@ TEST_CASE("CAPTURE can deal with complex expressions involving commas", "[messag
CAPTURE( (1, 2), (2, 3) ); CAPTURE( (1, 2), (2, 3) );
SUCCEED(); SUCCEED();
} }
#if defined( __GNUG__ ) || defined(__clang__)
# pragma GCC diagnostic pop
#endif
TEST_CASE("CAPTURE parses string and character constants", "[messages][capture]") { TEST_CASE("CAPTURE parses string and character constants", "[messages][capture]") {
CAPTURE(("comma, in string", "escaped, \", "), "single quote in string,',", "some escapes, \\,\\\\"); CAPTURE(("comma, in string", "escaped, \", "), "single quote in string,',", "some escapes, \\,\\\\");

View File

@ -28,7 +28,10 @@ filelocParser = re.compile(r'''
''', re.VERBOSE) ''', re.VERBOSE)
lineNumberParser = re.compile(r' line="[0-9]*"') lineNumberParser = re.compile(r' line="[0-9]*"')
hexParser = re.compile(r'\b(0[xX][0-9a-fA-F]+)\b') hexParser = re.compile(r'\b(0[xX][0-9a-fA-F]+)\b')
durationsParser = re.compile(r' time="[0-9]*\.[0-9]*"') # Note: junit must serialize time with 3 (or or less) decimal places
# before generalizing this parser, make sure that this is checked
# in other places too.
junitDurationsParser = re.compile(r' time="[0-9]*\.[0-9]{3}"')
sonarqubeDurationParser = re.compile(r' duration="[0-9]+"') sonarqubeDurationParser = re.compile(r' duration="[0-9]+"')
timestampsParser = re.compile(r'\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}Z') timestampsParser = re.compile(r'\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}Z')
versionParser = re.compile(r'Catch v[0-9]+\.[0-9]+\.[0-9]+(-develop\.[0-9]+)?') versionParser = re.compile(r'Catch v[0-9]+\.[0-9]+\.[0-9]+(-develop\.[0-9]+)?')
@ -138,7 +141,7 @@ def filterLine(line, isCompact):
line = hexParser.sub("0x<hex digits>", line) line = hexParser.sub("0x<hex digits>", line)
# strip durations and timestamps # strip durations and timestamps
line = durationsParser.sub(' time="{duration}"', line) line = junitDurationsParser.sub(' time="{duration}"', line)
line = sonarqubeDurationParser.sub(' duration="{duration}"', line) line = sonarqubeDurationParser.sub(' duration="{duration}"', line)
line = timestampsParser.sub('{iso8601-timestamp}', line) line = timestampsParser.sub('{iso8601-timestamp}', line)
line = specialCaseParser.sub('file:\g<1>', line) line = specialCaseParser.sub('file:\g<1>', line)

File diff suppressed because it is too large Load Diff