Compare commits

..

4 Commits

Author SHA1 Message Date
Chris Thrasher 8efee9b763 Use std::string_view 2025-09-22 11:50:44 -06:00
Chris Thrasher a5735af2f7 Use std::optional 2025-09-22 11:35:23 -06:00
Chris Thrasher db46dc4cb2 Upgrade to C++17 2025-09-22 11:35:22 -06:00
Chris Thrasher c6cefc6596 Disable reproducible build flags for dev builds 2025-09-21 21:43:51 -06:00
292 changed files with 4516 additions and 15189 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
---
Language: Cpp
Standard: c++14
Standard: c++17
# Note that we cannot use IncludeIsMainRegex functionality, because it
# does not support includes in angle brackets (<>)
+2 -6
View File
@@ -28,14 +28,12 @@ Checks: >-
-modernize-concat-nested-namespaces,
-modernize-use-nodiscard,
-modernize-use-default-member-init,
-modernize-type-traits,# we need to support C++14,
-modernize-deprecated-headers,
,# There's a lot of these and most of them are probably not useful,
-modernize-pass-by-value,
-modernize-use-string-view, # We support C++14,
performance-*,
performance-enum-size,
-performance-enum-size,
portability-*,
@@ -59,8 +57,6 @@ Checks: >-
-readability-uppercase-literal-suffix,
-readability-use-anyofallof,
-readability-avoid-return-with-void-value,
,# We prefer if defined(FOO) form because it is easier to extend later,
-readability-use-concise-preprocessor-directives,
,# time hogs,
-bugprone-throw-keyword-missing,
@@ -81,5 +77,5 @@ WarningsAsErrors: >-
readability-duplicate-include,
HeaderFilterRegex: '.*\.(c|cxx|cpp)$'
FormatStyle: none
CheckOptions: []
CheckOptions: {}
...
+2 -6
View File
@@ -2,10 +2,6 @@ name: Linux Builds (Bazel)
on: [push, pull_request]
env:
CTEST_OUTPUT_ON_FAILURE: 1
CTEST_NO_TESTS_ACTION: error
jobs:
build_and_test_ubuntu:
name: Linux Ubuntu 22.04 Bazel build <GCC 11.2.0>
@@ -16,10 +12,10 @@ jobs:
compilation_mode: [fastbuild, dbg, opt]
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- name: Mount Bazel cache
uses: actions/cache@v5
uses: actions/cache@v3
with:
path: "/home/runner/.cache/bazel"
key: bazel-ubuntu22-gcc11
+3 -8
View File
@@ -2,13 +2,9 @@ name: Linux Builds (Meson)
on: [push, pull_request]
env:
CTEST_OUTPUT_ON_FAILURE: 1
CTEST_NO_TESTS_ACTION: error
jobs:
build:
name: meson ${{matrix.cxx}}, C++${{matrix.std}}, ${{matrix.build_type}}
name: meson ${{matrix.cxx}}, ${{matrix.build_type}}
runs-on: ubuntu-22.04
strategy:
fail-fast: false
@@ -17,13 +13,12 @@ jobs:
- g++-11
- clang++-11
build_type: [debug, release]
std: [14, 17]
include:
- cxx: clang++-11
other_pkgs: clang-11
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- name: Prepare environment
run: |
@@ -33,7 +28,7 @@ jobs:
- name: Configure
env:
CXX: ${{matrix.cxx}}
CXXFLAGS: -std=c++${{matrix.std}} ${{matrix.cxxflags}}
CXXFLAGS: -std=c++17 ${{matrix.cxxflags}}
# Note: $GITHUB_WORKSPACE is distinct from ${{runner.workspace}}.
# This is important
run: |
+4 -24
View File
@@ -5,13 +5,9 @@ name: Linux Builds (Complex)
on: [push, pull_request]
env:
CTEST_OUTPUT_ON_FAILURE: 1
CTEST_NO_TESTS_ACTION: error
jobs:
build:
name: ${{matrix.build_description}}, ${{matrix.cxx}}, C++${{matrix.std}} ${{matrix.build_type}}
name: ${{matrix.build_description}}, ${{matrix.cxx}}, ${{matrix.build_type}}
runs-on: ubuntu-22.04
strategy:
fail-fast: false
@@ -24,7 +20,6 @@ jobs:
- cxx: clang++-14
build_description: Surrogates build
build_type: Debug
std: 14
other_pkgs: clang-14
cmake_configurations: -DCATCH_BUILD_SURROGATES=ON
@@ -32,13 +27,11 @@ jobs:
- cxx: g++-11
build_description: Extras + Examples
build_type: Debug
std: 14
other_pkgs: g++-11
cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_ENABLE_CMAKE_HELPER_TESTS=ON
- cxx: g++-11
build_description: Extras + Examples
build_type: Release
std: 14
other_pkgs: g++-11
cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_ENABLE_CMAKE_HELPER_TESTS=ON
@@ -46,36 +39,25 @@ jobs:
- cxx: clang++-14
build_description: Extras + Examples
build_type: Debug
std: 17
other_pkgs: clang-14
cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_ENABLE_CMAKE_HELPER_TESTS=ON
- cxx: clang++-14
build_description: Extras + Examples
build_type: Release
std: 17
other_pkgs: clang-14
cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_ENABLE_CMAKE_HELPER_TESTS=ON
# Configure tests with Clang-14
- cxx: clang++-14
build_description: CMake configuration tests
build_type: Debug
std: 14
other_pkgs: clang-14
cmake_configurations: -DCATCH_ENABLE_CONFIGURE_TESTS=ON
# Valgrind test Clang-14
# - cxx: clang++-14
# build_description: Valgrind tests
# build_type: Debug
# std: 14
# other_pkgs: clang-14 valgrind
# cmake_configurations: -DMEMORYCHECK_COMMAND=`which valgrind` -DMEMORYCHECK_COMMAND_OPTIONS="-q --track-origins=yes --leak-check=full --num-callers=50 --show-leak-kinds=definite --error-exitcode=1"
# other_ctest_args: -T memcheck -LE uses-python
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- name: Prepare environment
run: |
@@ -87,20 +69,19 @@ jobs:
cmake --preset basic-tests -GNinja \
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
-DCMAKE_CXX_COMPILER=${{matrix.cxx}} \
-DCMAKE_CXX_STANDARD=${{matrix.std}} \
${{matrix.cmake_configurations}}
- name: Build
run: cmake --build build
- name: Test
run: ctest --test-dir build -j
run: ctest --test-dir build -j --output-on-failure
clang-tidy:
name: clang-tidy
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- name: Prepare environment
run: |
@@ -120,7 +101,6 @@ jobs:
-DCMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/true \
-DCMAKE_CXX_COMPILER=clang++-15 \
-DCMAKE_CXX_LINK_EXECUTABLE=/usr/bin/true \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_RANLIB=/usr/bin/true \
-DCATCH_BUILD_EXAMPLES=ON \
-DCATCH_ENABLE_CMAKE_HELPER_TESTS=ON
+3 -19
View File
@@ -2,10 +2,6 @@ name: Linux Builds (Basic)
on: [push, pull_request]
env:
CTEST_OUTPUT_ON_FAILURE: 1
CTEST_NO_TESTS_ACTION: error
jobs:
build:
name: ${{matrix.cxx}}, C++${{matrix.std}}, ${{matrix.build_type}}
@@ -18,7 +14,6 @@ jobs:
- g++-10
- g++-11
- g++-12
- clang++-6.0
- clang++-7
- clang++-8
- clang++-9
@@ -28,7 +23,7 @@ jobs:
- clang++-13
- clang++-14
build_type: [Debug, Release]
std: [14]
std: [17]
include:
- cxx: g++-9
other_pkgs: g++-9
@@ -38,8 +33,6 @@ jobs:
other_pkgs: g++-11
- cxx: g++-12
other_pkgs: g++-12
- cxx: clang++-6.0
other_pkgs: clang-6.0
- cxx: clang++-7
other_pkgs: clang-7
- cxx: clang++-8
@@ -56,15 +49,6 @@ jobs:
other_pkgs: clang-13
- cxx: clang++-14
other_pkgs: clang-14
# Clang 14 + C++17
- cxx: clang++-14
build_type: Debug
std: 17
other_pkgs: clang-14
- cxx: clang++-14
build_type: Release
std: 17
other_pkgs: clang-14
- cxx: clang++-14
build_type: Debug
std: 20
@@ -83,7 +67,7 @@ jobs:
other_pkgs: g++-11
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- name: Add repositories for older compilers
run: |
@@ -106,4 +90,4 @@ jobs:
run: cmake --build build
- name: Test
run: ctest --test-dir build -j
run: ctest --test-dir build -j --output-on-failure
+5 -9
View File
@@ -2,28 +2,24 @@ name: Mac Builds
on: [push, pull_request]
env:
CTEST_OUTPUT_ON_FAILURE: 1
CTEST_NO_TESTS_ACTION: error
jobs:
build:
# From macos-14 forward, the baseline "macos-X" image is Arm based,
# and not Intel based.
runs-on: ${{matrix.image}}
strategy:
fail-fast: false
matrix:
image: [macos-14, macos-15, macos-15-intel]
image: [macos-13, macos-14, macos-15]
build_type: [Debug, Release]
std: [14, 17]
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- name: Configure
run: |
cmake --preset basic-tests -GNinja \
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
-DCMAKE_CXX_STANDARD=${{matrix.std}} \
-DCATCH_BUILD_EXAMPLES=ON \
-DCATCH_BUILD_EXTRA_TESTS=ON
@@ -31,4 +27,4 @@ jobs:
run: cmake --build build
- name: Test
run: ctest --test-dir build -j
run: ctest --test-dir build -j --output-on-failure
@@ -1,43 +0,0 @@
name: Mac Sanitizer Builds
on: [push, pull_request]
env:
CTEST_OUTPUT_ON_FAILURE: 1
CTEST_NO_TESTS_ACTION: error
jobs:
build:
runs-on: ${{matrix.image}}
strategy:
fail-fast: false
matrix:
image: [macos-15, macos-15-intel]
build_type: [Debug]
std: [17]
sanitizer: [thread, address]
include:
- sanitizer: thread
preset: basic-tests
filter: -R ThreadSafetyTests
- sanitizer: address
preset: most-tests
filter:
steps:
- uses: actions/checkout@v6
- name: Configure
run: |
CFXXFLAGS=-fsanitize=${{matrix.sanitizer}},undefined
cmake --preset ${{matrix.preset}} -GNinja \
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
-DCMAKE_CXX_STANDARD=${{matrix.std}} \
-DCATCH_BUILD_EXTRA_TESTS=ON
- name: Build
run: cmake --build build
- name: Test
run: ctest --test-dir build ${{matrix.filter}}
@@ -18,7 +18,7 @@ jobs:
profile_generate: 'false'
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- name: Install conan
run: pip install conan==${{matrix.conan_version}}
+2 -2
View File
@@ -9,10 +9,10 @@ jobs:
steps:
- name: Checkout source code
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Setup Dependencies
uses: actions/setup-python@v6
uses: actions/setup-python@v2
with:
python-version: '3.7'
- name: Install checkguard
+3 -9
View File
@@ -2,13 +2,9 @@ name: Windows Builds (Basic)
on: [push, pull_request]
env:
CTEST_OUTPUT_ON_FAILURE: 1
CTEST_NO_TESTS_ACTION: error
jobs:
build:
name: ${{matrix.os}}, ${{matrix.std}}, ${{matrix.build_type}}, ${{matrix.platform}}
name: ${{matrix.os}}, ${{matrix.build_type}}, ${{matrix.platform}}
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
@@ -16,20 +12,18 @@ jobs:
os: [windows-2022, windows-2025]
platform: [Win32, x64]
build_type: [Debug, Release]
std: [14, 17]
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- name: Configure build
run: |
cmake --preset all-tests `
-A ${{matrix.platform}} `
-DCMAKE_CXX_STANDARD=${{matrix.std}} `
- name: Build tests
run: cmake --build build --config ${{matrix.build_type}} --parallel %NUMBER_OF_PROCESSORS%
shell: cmd
- name: Run tests
run: ctest --test-dir build -C ${{matrix.build_type}} -j %NUMBER_OF_PROCESSORS%
run: ctest --test-dir build -C ${{matrix.build_type}} -j %NUMBER_OF_PROCESSORS% --output-on-failure
shell: cmd
+2 -12
View File
@@ -27,11 +27,6 @@ expand_template(
"#cmakedefine CATCH_CONFIG_COLOUR_WIN32": "",
"#cmakedefine CATCH_CONFIG_COUNTER": "",
"#cmakedefine CATCH_CONFIG_CPP11_TO_STRING": "",
"#cmakedefine CATCH_CONFIG_CPP17_BYTE": "",
"#cmakedefine CATCH_CONFIG_CPP17_OPTIONAL": "",
"#cmakedefine CATCH_CONFIG_CPP17_STRING_VIEW": "",
"#cmakedefine CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS": "",
"#cmakedefine CATCH_CONFIG_CPP17_VARIANT": "",
"#cmakedefine CATCH_CONFIG_DEPRECATION_ANNOTATIONS": "",
"#cmakedefine CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER": "",
"#cmakedefine CATCH_CONFIG_DISABLE_EXCEPTIONS": "",
@@ -51,11 +46,6 @@ expand_template(
"#cmakedefine CATCH_CONFIG_NO_COLOUR_WIN32": "",
"#cmakedefine CATCH_CONFIG_NO_COUNTER": "",
"#cmakedefine CATCH_CONFIG_NO_CPP11_TO_STRING": "",
"#cmakedefine CATCH_CONFIG_NO_CPP17_BYTE": "",
"#cmakedefine CATCH_CONFIG_NO_CPP17_OPTIONAL": "",
"#cmakedefine CATCH_CONFIG_NO_CPP17_STRING_VIEW": "",
"#cmakedefine CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS": "",
"#cmakedefine CATCH_CONFIG_NO_CPP17_VARIANT": "",
"#cmakedefine CATCH_CONFIG_NO_DEPRECATION_ANNOTATIONS": "",
"#cmakedefine CATCH_CONFIG_NO_GETENV": "",
"#cmakedefine CATCH_CONFIG_NO_GLOBAL_NEXTAFTER": "",
@@ -76,8 +66,8 @@ expand_template(
"#cmakedefine CATCH_CONFIG_WINDOWS_SEH": "",
"#cmakedefine CATCH_CONFIG_USE_BUILTIN_CONSTANT_P": "",
"#cmakedefine CATCH_CONFIG_NO_USE_BUILTIN_CONSTANT_P": "",
"#cmakedefine CATCH_CONFIG_THREAD_SAFE_ASSERTIONS": "",
"#cmakedefine CATCH_CONFIG_NO_THREAD_SAFE_ASSERTIONS": "",
"#cmakedefine CATCH_CONFIG_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS": "",
"#cmakedefine CATCH_CONFIG_NO_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS": "",
},
template = "src/catch2/catch_user_config.hpp.in",
)
+1 -6
View File
@@ -31,11 +31,6 @@ set(_OverridableOptions
"COLOUR_WIN32"
"COUNTER"
"CPP11_TO_STRING"
"CPP17_BYTE"
"CPP17_OPTIONAL"
"CPP17_STRING_VIEW"
"CPP17_UNCAUGHT_EXCEPTIONS"
"CPP17_VARIANT"
"GLOBAL_NEXTAFTER"
"POSIX_SIGNALS"
"USE_ASYNC"
@@ -45,7 +40,7 @@ set(_OverridableOptions
"EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT"
"USE_BUILTIN_CONSTANT_P"
"DEPRECATION_ANNOTATIONS"
"THREAD_SAFE_ASSERTIONS"
"EXPERIMENTAL_THREAD_SAFE_ASSERTIONS"
)
foreach(OptionName ${_OverridableOptions})
+1 -1
View File
@@ -3,7 +3,7 @@ libdir=${prefix}/@lib_dir@
pkg_version=@Catch2_VERSION@
Name: Catch2 with main function
Description: A modern, C++-native test framework for C++14 and above (links in default main)
Description: A modern, C++-native test framework for C++17 and above (links in default main)
URL: https://github.com/catchorg/Catch2
Version: ${pkg_version}
Requires: catch2 = ${pkg_version}
+1 -1
View File
@@ -4,7 +4,7 @@ includedir=${prefix}/@include_dir@
libdir=${prefix}/@lib_dir@
Name: Catch2
Description: A modern, C++-native, test framework for C++14 and above
Description: A modern, C++-native, test framework for C++17 and above
URL: https://github.com/catchorg/Catch2
Version: @Catch2_VERSION@
Cflags: -I${includedir}
+1 -7
View File
@@ -20,7 +20,6 @@ cmake_dependent_option(CATCH_BUILD_TESTING "Build the SelfTest project" ON "CATC
cmake_dependent_option(CATCH_BUILD_EXAMPLES "Build code examples" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_BUILD_EXTRA_TESTS "Build extra tests" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_BUILD_FUZZERS "Build fuzzers" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_BUILD_BENCHMARKS "Build the benchmarks" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_ENABLE_WERROR "Enables Werror during build" ON "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_BUILD_SURROGATES "Enable generating and building surrogate TUs for the main headers" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
@@ -35,7 +34,7 @@ if(CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif()
project(Catch2
VERSION 3.15.0 # CML version placeholder, don't delete
VERSION 3.10.0 # CML version placeholder, don't delete
LANGUAGES CXX
HOMEPAGE_URL "https://github.com/catchorg/Catch2"
DESCRIPTION "A modern, C++-native, unit test framework."
@@ -78,11 +77,6 @@ set(SELF_TEST_DIR ${CATCH_DIR}/tests/SelfTest)
# We need to bring-in the variables defined there to this scope
add_subdirectory(src)
if (CATCH_BUILD_BENCHMARKS)
set(CMAKE_FOLDER "benchmarks")
add_subdirectory(benchmarks)
endif()
# Build tests only if requested
if(BUILD_TESTING AND CATCH_BUILD_TESTING AND NOT_SUBPROJECT)
find_package(Python3 REQUIRED COMPONENTS Interpreter)
+6 -14
View File
@@ -11,27 +11,19 @@
"CMAKE_CXX_EXTENSIONS": "OFF",
"CMAKE_CXX_STANDARD_REQUIRED": "ON",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"CATCH_DEVELOPMENT_BUILD": "ON"
}
},
{
"name": "most-tests",
"inherits": "basic-tests",
"displayName": "Full development build",
"description": "Enables development build with extended set of tests (still relatively cheap to build)",
"cacheVariables": {
"CATCH_BUILD_EXAMPLES": "ON",
"CATCH_BUILD_EXTRA_TESTS": "ON",
"CATCH_BUILD_SURROGATES": "ON",
"CATCH_BUILD_BENCHMARKS": "ON"
"CATCH_DEVELOPMENT_BUILD": "ON",
"CATCH_ENABLE_REPRODUCIBLE_BUILD": "OFF"
}
},
{
"name": "all-tests",
"inherits": "most-tests",
"inherits": "basic-tests",
"displayName": "Full development build",
"description": "Enables development build with examples and ALL tests",
"cacheVariables": {
"CATCH_BUILD_EXAMPLES": "ON",
"CATCH_BUILD_EXTRA_TESTS": "ON",
"CATCH_BUILD_SURROGATES": "ON",
"CATCH_ENABLE_CONFIGURE_TESTS": "ON",
"CATCH_ENABLE_CMAKE_HELPER_TESTS": "ON"
}
+266 -432
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,5 +1,5 @@
module(name = "catch2")
bazel_dep(name = "bazel_skylib", version = "1.9.0")
bazel_dep(name = "rules_cc", version = "0.2.16")
bazel_dep(name = "bazel_skylib", version = "1.7.1")
bazel_dep(name = "rules_cc", version = "0.1.1")
bazel_dep(name = "rules_license", version = "1.0.0")
-21
View File
@@ -1,21 +0,0 @@
include(CatchMiscFunctions)
add_executable(AssertionsFastPath
runtime_assertion_benches.cpp
)
add_executable(AssertionsSlowPath
runtime_assertion_benches.cpp
assertion_listener.cpp
)
add_executable(EmptyExecutable
only_include.cpp
)
target_link_libraries(AssertionsFastPath PRIVATE Catch2::Catch2WithMain)
target_link_libraries(AssertionsSlowPath PRIVATE Catch2::Catch2WithMain)
target_link_libraries(EmptyExecutable PRIVATE Catch2::Catch2WithMain)
list(APPEND CATCH_TEST_TARGETS AssertionsFastPath AssertionsSlowPath EmptyExecutable)
set(CATCH_TEST_TARGETS ${CATCH_TEST_TARGETS} PARENT_SCOPE)
-30
View File
@@ -1,30 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/reporters/catch_reporter_event_listener.hpp>
#include <catch2/reporters/catch_reporter_registrars.hpp>
/**
* Event listener that listens to all assertions, forcing assertion slow path
*/
namespace {
class AssertionSlowPathListener : public Catch::EventListenerBase {
public:
static std::string getDescription() {
return "Validates ordering of Catch2's listener events";
}
AssertionSlowPathListener(Catch::IConfig const* config) :
EventListenerBase(config) {
m_preferences.shouldReportAllAssertions = true;
m_preferences.shouldReportAllAssertionStarts = true;
}
};
CATCH_REGISTER_LISTENER( AssertionSlowPathListener )
}
-16
View File
@@ -1,16 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
/**\file
* "empty" include of catch_test_macros.hpp
*
* This file does only one thing: include `catch2/catch_test_macros.hpp`,
* so that we can measure the compilation cost of the header.
*/
#include <catch2/catch_test_macros.hpp>
-81
View File
@@ -1,81 +0,0 @@
<a id="top"></a>
# Benchmarks of Catch2
This folder holds benchmarks for Catch2. It should not be built for the
small(er) test sets, as it is only relevant for running (mainly runtime)
benchmarks.
Below you will find some practical examples using
[hyperfine](https://github.com/sharkdp/hyperfine) to determine the
performance of various scenarios. They assume two parallel checkouts, one
named `Catch2-old` and the other `Catch2-new`. You will need to change
the paths to work on your own machine.
## Runtime benchmarks
The runtime benchmarks currently consist of few different `TEST_CASE`s,
each with a simple loop over different assertion type. They are compiled
into two binaries, one for assertion slow path and one for assertion fast
path.
### Assumptions and notes about real-world usage
The basic assertion macro, `REQUIRE` (and `CHECK`) is the most common one,
by far. Thus, it is the most important one to run quickly. It is probably
followed by the matcher macro, `REQUIRE_THAT`.
The most common result of an assertion is that it passes. Even if it is
stringified and reported, that is most likely due to some listener/reporter
that wants the string representation, not because it failed.
The performance of both Debug and Release builds are important; users
will run tests in both. LTO runtime performance is not too important,
but compile time perf is.
### Examples
**Compare performance of `REQUIRE` in slow path, debug build**
```text
hyperfine --warmup 2 --shell none --parameter-list version old,new '/home/xarn/benches/Catch2-{version}/build-debug/benchmarks/AssertionsSlowPath -o /dev/null "REQUIRE"'
```
**Compare performance of `REQUIRE_THAT` in fast path, release build**
```text
hyperfine --warmup 2 --shell none --parameter-list version old,new '/home/xarn/benches/Catch2-{version}/build-release/benchmarks/AssertionsFastPath -o /dev/null "REQUIRE_THAT"'
```
**Compare performance of `REQUIRE` with stringification enabled, release build**
```text
hyperfine --warmup 2 --shell none --parameter-list version old,new '/home/xarn/benches/Catch2-{version}/build-release/benchmarks/AssertionsFastPath -s -o /dev/null "REQUIRE"'
```
_Note that we redirect the output to `/dev/null` to reduce the overhead of the actual output printing, to see just the impact of stringification._
TODO:
* Start empty binary (set up cost base)
* Start binary with X (100/1k/10k) tests (test registration cost)
* Section tracking
## Compilation benchmarks
As tests are often iterated upon and relinked, the compilation cost of
Catch2 is also important.
### Examples
**Compare overhead of including `catch_test_macros.hpp`**
```text
hyperfine --warmup 2 --shell none --parameter-list version old,new '/usr/bin/c++ -I/home/xarn/benches/Catch2-{version}/src/catch2/.. -I/home/xarn/benches/Catch2-{version}/build-debug/generated-includes -g -o /dev/null -c /home/xarn/benches/Catch2-{version}/benchmarks/only_include.cpp'
```
**Compare build time of Catch2's `SelfTest` test suite, Debug build**
```text
hyperfine --warmup 2 --parameter-list version old,vas --prepare 'find ~/benches/Catch2-{version}/tests/SelfTest -type f -name "*.cpp" -exec touch {} +' 'ninja -j 1 -C ~/benches/Catch2-{version}/build-debug'
```
TODO:
* Link-only recipe
-54
View File
@@ -1,54 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_templated.hpp>
namespace {
class MatchAllMatcher final : public Catch::Matchers::MatcherGenericBase {
public:
template <typename Any>
bool match( Any&& ) const {
return true;
}
std::string describe() const override {
using namespace std::string_literals;
return "Long string that does not fit into SSO"s;
}
};
MatchAllMatcher MatchAll() { return MatchAllMatcher(); }
TEST_CASE( "REQUIRE", "[assertions]" ) {
for ( size_t i = 0; i < 10'000'000; ++i ) {
REQUIRE( true );
}
}
TEST_CASE( "REQUIRE_THAT", "[assertions][matchers]" ) {
for ( size_t i = 0; i < 10'000'000; ++i ) {
REQUIRE_THAT( 1, MatchAll() );
}
}
TEST_CASE( "REQUIRE_NOTHROW", "[assertions][exceptions]" ) {
for ( size_t i = 0; i < 10'000'000; ++i ) {
REQUIRE_NOTHROW( []() {}() );
}
}
TEST_CASE( "REQUIRE_THROWS", "[assertions][exceptions]" ) {
for ( size_t i = 0; i < 10'000'000; ++i ) {
REQUIRE_THROWS( []() { throw 1; }() );
}
}
} // namespace
+1 -2
View File
@@ -24,8 +24,7 @@ Once you're up and running consider the following reference material.
* [String Conversions](tostring.md#top)
**Running:**
* [Command line reference](command-line.md#top)
* [Running specific section/generator](filtering-execution-path.md#top)
* [Command line](command-line.md#top)
**Odds and ends:**
* [Frequently Asked Questions (FAQ)](faq.md#top)
-7
View File
@@ -66,24 +66,17 @@ test execution. Specifically it understands
* JUnit output path via `XML_OUTPUT_FILE`
* Test filtering via `TESTBRIDGE_TEST_ONLY`
* Test sharding via `TEST_SHARD_INDEX`, `TEST_TOTAL_SHARDS`, and `TEST_SHARD_STATUS_FILE`
* Creating a file to signal premature test exit via `TEST_PREMATURE_EXIT_FILE`
* Setting the RNG seed via `TEST_RANDOM_SEED`
> Support for `XML_OUTPUT_FILE` was [introduced](https://github.com/catchorg/Catch2/pull/2399) in Catch2 3.0.1
> Support for `TESTBRIDGE_TEST_ONLY` and sharding was introduced in Catch2 3.2.0
> Support for `TEST_PREMATURE_EXIT_FILE` and `TEST_RANDOM_SEED` was introduced in Catch2 3.11.0
This integration is enabled via either a [compile time configuration
option](configuration.md#bazel-support), or via `BAZEL_TEST` environment
variable set to "1".
> Support for `BAZEL_TEST` was [introduced](https://github.com/catchorg/Catch2/pull/2459) in Catch2 3.1.0
Note that if both the Bazel environment var and command line option for
something are used, the environment variable wins.
## Low-level tools
+37 -33
View File
@@ -32,7 +32,6 @@
[Test Sharding](#test-sharding)<br>
[Allow running the binary without tests](#allow-running-the-binary-without-tests)<br>
[Output verbosity](#output-verbosity)<br>
[Create file to guard against silent early termination](#create-file-to-guard-against-silent-early-termination)<br>
Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available.
Click one of the following links to take you straight to that option - or scroll on to browse the available options.
@@ -52,8 +51,6 @@ Click one of the following links to take you straight to that option - or scroll
<a href="#reporting-timings"> ` -d, --durations`</a><br />
<a href="#input-file"> ` -f, --input-file`</a><br />
<a href="#run-section"> ` -c, --section`</a><br />
<a href="#path-filtering"> ` -g, --generator-index`</a><br />
<a href="#path-filtering"> ` -p, --path-filter`</a><br />
<a href="#filenames-as-tags"> ` -#, --filenames-as-tags`</a><br />
@@ -289,10 +286,9 @@ as follows:
| Option | `normal` (default) | `quiet` | `high` |
|--------------------|---------------------------------|---------------------|-----------------------------------------|
| `--list-tests` | Test names and tags | Test names only | Same as `normal`, plus source code line |
| `--list-tags` | Tags and counts | Tags only | Same as `normal` |
| `--list-tags` | Tags and counts | Same as `normal` | Same as `normal` |
| `--list-reporters` | Reporter names and descriptions | Reporter names only | Same as `normal` |
| `--list-listeners` | Listener names and descriptions | Listener names only | Same as `normal` |
| `--list-listeners` | Listener names and descriptions | Same as `normal` | Same as `normal` |
<a id="sending-output-to-a-file"></a>
## Sending output to a file
@@ -361,13 +357,10 @@ There are currently two warnings implemented:
// (e.g. `REQUIRE`) is encountered.
UnmatchedTestSpec // Fail test run if any of the CLI test specs did
// not match any tests.
InfiniteGenerators // Fail if GENERATE would run infinitely
```
> `UnmatchedTestSpec` was introduced in Catch2 3.0.1.
> `InfiniteGenerators` was introduced in Catch2 3.13.0
<a id="reporting-timings"></a>
## Reporting timings
@@ -535,19 +528,45 @@ Prints the command line arguments to stdout
<a id="run-section"></a>
<a id="path-filtering"></a>
## Specify the section/generator element to run
## Specify the section to run
<pre>-c, --section &lt;section name&gt;</pre>
<pre>-g, --generator-index &lt;index in generator&gt;</pre>
<pre>-p, --path-filter &lt;path filter spec&gt;</pre>
> The generator and generic path filtering was added in Catch2 3.13.0
To limit execution to a specific section within a test case, use this option one or more times.
To narrow to sub-sections use multiple instances, where each subsequent instance specifies a deeper nesting level.
These arguments allow you to run specific section(s) in a test case, or
only get specific element from a generator. All the variants form a shared
stack of filters.
E.g. if you have:
[See the full documentation of path filtering for more details](filtering-execution-path.md#top)
<pre>
TEST_CASE( "Test" ) {
SECTION( "sa" ) {
SECTION( "sb" ) {
/*...*/
}
SECTION( "sc" ) {
/*...*/
}
}
SECTION( "sd" ) {
/*...*/
}
}
</pre>
Then you can run `sb` with:
<pre>./MyExe Test -c sa -c sb</pre>
Or run just `sd` with:
<pre>./MyExe Test -c sd</pre>
To run all of `sa`, including `sb` and `sc` use:
<pre>./MyExe Test -c sa</pre>
There are some limitations of this feature to be aware of:
- Code outside of sections being skipped will still be executed - e.g. any set-up code in the TEST_CASE before the
start of the first section.</br>
- At time of writing, wildcards are not supported in section names.
- If you specify a section without narrowing to a test case first then all test cases will be executed
(but only matching sections within them).
<a id="filenames-as-tags"></a>
@@ -630,21 +649,6 @@ ignored.
Verbosity defaults to _normal_.
## Create file to guard against silent early termination
<pre>--premature-exit-guard-file &lt;path&gt;</pre>
> Introduced in Catch2 3.11.0
Tells Catch2 to create an empty file at specified path before the tests
start, and delete it after the tests finish. If the file is present after
the process stops, it can be assumed that the testing binary exited
prematurely, e.g. due to the OOM killer.
All directories in the path must already exist. If this option is used
and Catch2 cannot create the file (e.g. the location is not writable),
the test run will fail.
---
[Home](Readme.md#top)
+7 -29
View File
@@ -10,14 +10,13 @@
[Default reporter](#default-reporter)<br>
[Bazel support](#bazel-support)<br>
[C++11 toggles](#c11-toggles)<br>
[C++17 toggles](#c17-toggles)<br>
[Other toggles](#other-toggles)<br>
[Enabling stringification](#enabling-stringification)<br>
[Disabling exceptions](#disabling-exceptions)<br>
[Disabling deprecation warnings](#disabling-deprecation-warnings)<br>
[Overriding Catch's debug break (`-b`)](#overriding-catchs-debug-break--b)<br>
[Static analysis support](#static-analysis-support)<br>
[Thread safety in assertions (and messages)](#thread-safety-in-assertions-and-messages)<br>
[Experimental thread safety](#experimental-thread-safety)<br>
Catch2 is designed to "just work" as much as possible, and most of the
configuration options below are changed automatically during compilation,
@@ -29,7 +28,7 @@ with the same name.
## Prefixing Catch macros
CATCH_CONFIG_PREFIX_ALL // Prefix all macros with CATCH_
CATCH_CONFIG_PREFIX_MESSAGES // Prefix only message macros ((UNSCOPED_)INFO, WARN, (UNSCOPED_)CAPTURE)
CATCH_CONFIG_PREFIX_MESSAGES // Prefix only INFO, UNSCOPED_INFO, WARN and CAPTURE
To keep test code clean and uncluttered Catch uses short macro names (e.g. ```TEST_CASE``` and ```REQUIRE```). Occasionally these may conflict with identifiers from platform headers or the system under test. In this case the above identifier can be defined. This will cause all the Catch user macros to be prefixed with ```CATCH_``` (e.g. ```CATCH_TEST_CASE``` and ```CATCH_REQUIRE```).
@@ -128,23 +127,6 @@ Catch's selection, by defining either `CATCH_CONFIG_CPP11_TO_STRING` or
`CATCH_CONFIG_NO_CPP11_TO_STRING`.
## C++17 toggles
CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS // Override std::uncaught_exceptions (instead of std::uncaught_exception) support detection
CATCH_CONFIG_CPP17_STRING_VIEW // Override std::string_view support detection (Catch provides a StringMaker specialization by default)
CATCH_CONFIG_CPP17_VARIANT // Override std::variant support detection (checked by CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER)
CATCH_CONFIG_CPP17_OPTIONAL // Override std::optional support detection (checked by CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER)
CATCH_CONFIG_CPP17_BYTE // Override std::byte support detection (Catch provides a StringMaker specialization by default)
> `CATCH_CONFIG_CPP17_STRING_VIEW` was [introduced](https://github.com/catchorg/Catch2/issues/1376) in Catch2 2.4.1.
Catch contains basic compiler/standard detection and attempts to use
some C++17 features whenever appropriate. This automatic detection
can be manually overridden in both directions, that is, a feature
can be enabled by defining the macro in the table above, and disabled
by using `_NO_` in the macro, e.g. `CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS`.
## Other toggles
CATCH_CONFIG_COUNTER // Use __COUNTER__ to generate unique names for test cases
@@ -221,8 +203,8 @@ By default, Catch does not stringify some types from the standard library. This
CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER // Provide StringMaker specialization for std::pair
CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER // Provide StringMaker specialization for std::tuple
CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER // Provide StringMaker specialization for std::variant, std::monostate (on C++17)
CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER // Provide StringMaker specialization for std::optional (on C++17)
CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER // Provide StringMaker specialization for std::variant, std::monostate
CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER // Provide StringMaker specialization for std::optional
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS // Defines all of the above
> `CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER` was [introduced](https://github.com/catchorg/Catch2/issues/1380) in Catch2 2.4.1.
@@ -316,21 +298,17 @@ no backwards compatibility guarantees._
are not meant to be runnable, only "scannable".
<a id="experimental-thread-safety"></a>
## Thread safety in assertions (and messages)
## Experimental thread safety
> Introduced in Catch2 3.9.0
> Made non-experimental in Catch2 3.12.0
Catch2 can optionally support thread-safe assertions, that means, multiple
user-spawned threads can use the assertion macros at the same time. Due
to the performance cost this imposes even on single-threaded usage, Catch2
defaults to non-thread-safe assertions.
CATCH_CONFIG_THREAD_SAFE_ASSERTIONS // enables thread safe assertions
CATCH_CONFIG_NO_THREAD_SAFE_ASSERTIONS // force-disables thread safe assertions
CATCH_CONFIG_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS // enables thread safe assertions
CATCH_CONFIG_NO_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS // force-disables thread safe assertions
See [the documentation on thread safety in Catch2](thread-safety.md#top)
for details on which macros are safe and other notes.
+1 -7
View File
@@ -211,16 +211,10 @@ and so on.
### C++ standard version
Catch2 currently targets C++14 as the minimum supported C++ version.
Catch2 currently targets C++17 as the minimum supported C++ version.
Features from higher language versions should be used only sparingly,
when the benefits from using them outweigh the maintenance overhead.
Example of good use of polyfilling features is our use of `conjunction`,
where if available we use `std::conjunction` and otherwise provide our
own implementation. The reason it is good is that the surface area for
maintenance is quite small, and `std::conjunction` can directly use
compiler built-ins, thus providing significant compilation benefits.
Example of bad use of polyfilling features would be to keep around two
sets of metaprogramming in the stringification implementation, once
using C++14 compliant TMP and once using C++17's `if constexpr`. While
-26
View File
@@ -48,32 +48,6 @@ If you are mutating the fixture instance from within the test case, and
want to keep doing so in the future, mark the mutated members as `mutable`.
### Section-only filtering with `-c/--section`
> Deprecated in Catch2 3.13.0
Currently, if you use only `-c/--section` parameters to decide which
sections to enter, the filtering ignores generators completely. In the
future, using only `-c/--section` will behave the same way as if you
specified the filters through the new `-p/--path-filter` parameter, which
means that generators are taken into account.
### Generator interfaces
#### Defaulted `UntypedGeneratorBase::isFinite()`
> Deprecated in Catch2 3.13.0
The `UntypedGeneratorBase` currently provides a default implementation
for `isFinite` that always returns `true`. This was done to keep backwards
compatibility with pre-existing generators, as infinite generators can
be diagnosed as errors in some cases.
In the future, all generators will be expected to override `isFinite`.
---
[Home](Readme.md#top)
+1 -1
View File
@@ -10,7 +10,7 @@ in-memory logs if they are not needed (the test case passed).
Unlike reporters, each registered event listener is always active. Event
listeners are always notified before reporter(s).
To write your own event listener, you should derive from `Catch::EventListenerBase`,
To write your own event listener, you should derive from `Catch::TestEventListenerBase`,
as it provides empty stubs for all reporter events, allowing you to
only override events you care for. Afterwards you have to register it
with Catch2 using `CATCH_REGISTER_LISTENER` macro, so that Catch2 knows
-222
View File
@@ -1,222 +0,0 @@
<a id="top"></a>
# How to run specific section/generator
> The generator and generic path filtering was added in Catch2 3.13.0
Catch2 supports picking specific path through a test case by filtering
sections and generator indices to run through. This is done by using one
of the three commandline parameters, one or more times.
```
-c, --section <section name>
-g, --generator-index <index in generator>
-p, --path-filter <path filter spec>
```
All the variants form a shared stack of filters, but if you use only
`-c`/`--section` form to specify section filters, you will get the old
behaviour, which does not affect generators at all. If you also use either
`-g`/`--generator-index`, or `-p`/`--path-filter`, you will get the new
behaviour, which can also filter generator elements.
Both the new and old filter behaviours include some potentially surprising
things:
* Code outside of sections being skipped will still be executed. E.g.
any setup code in the TEST_CASE that lives outside of sections.
* Path filters filter the prefix of the path. So if you specify single
filter, it affects only the top level sections/generator, with their
child sections/generators being unfiltered.
* Path filters are independent of test case selection, Catch2 will try
to follow the path filters in all selected test cases. This means
that if you specify path filters without a test case filter, Catch2
will try to apply the path filters inside every registered test case.
## Old behaviour
> The old behaviour was deprecated in Catch2 3.13.0
```
-c, --section <section name>
```
The argument to `-c`/`--section` can be any arbitrary string. When Catch2
is deciding whether to enter a section, it will check its trimmed name
against the appropriate trimmed section filter. If they are the same,
the section can be opened. If not, Catch2 will skip over that section.
### Examples
#### Simple section nesting
Given
```cpp
TEST_CASE( "foo" ) {
REQUIRE( true );
SECTION( "A" ) {
SECTION( "A1" ) { REQUIRE( true ); }
SECTION( "A2" ) { REQUIRE( true ); }
}
SECTION( "B" ) {
SECTION( "B1" ) { REQUIRE( true ); }
SECTION( "B2" ) { REQUIRE( true ); }
}
}
```
* `./tests foo -c A` runs section "A" and both of its subsections,
resulting in 4 assertions.
* `./tests foo -c A -c B` runs section "A", but none of its subsections,
resulting in 1 assertion (the one before "A").
* `./tests foo -c A -c A1` runs section "A" and only the "A1" subsection,
resulting in 2 assertions.
#### Sections with nested generators
Note that old behaviour completely _ignores_ generators. This means both
that they can't be filtered, but also that they aren't taken into account
for the filter depth. In other words, given
```cpp
TEST_CASE( "bar" ) {
REQUIRE( true );
SECTION( "A" ) { REQUIRE( true ); }
SECTION( "B" ) {
auto i = GENERATE( 1, 2, 3 );
DYNAMIC_SECTION( "i=" << i ) {
REQUIRE( true );
}
}
}
```
* `./tests bar -c A` results in 2 assertions.
* `./tests bar -c B -c i=2` results in 4 assertions, because the whole
generator in section "B" has to be used up, but the dynamic section is
only entered when the generator returns 2 as the value for `i`.
* `./tests bar -c B -c i=4` results in 3 assertions, because the assertion
outside of section is executed every time the test case is entered, and
the generator forces the test case to rerun 3 times before it is used up,
even though the dynamic section will never be entered.
#### Section with sibling generators
For cases where sections have sibling generators, the filtering can get
even more surprising.
```cpp
TEST_CASE( "qux" ) {
REQUIRE( true );
SECTION( "A" ) { REQUIRE( true ); }
auto i = GENERATE( 1, 2, 3 );
DYNAMIC_SECTION( "i=" << i ) {
REQUIRE( true );
}
}
```
* `./tests qux -c A` results in **4** assertions, because section "A" is
entered once, but the sibling generator has to be exhausted, and
the first assertion is executed once per generator element.
* `./tests qux -c i=2` also results in 4 assertions. Once again,
the generator has to be exhausted and the dynamic section is entered
once.
## New behaviour
> The new behaviour was introduced in Catch2 3.13.0
```
-g, --generator-index <index in generator>
-p, --path-filter <path filter spec>
```
The argument to `-g`/`--generator-index` must be either a non-negative
number, which is interpreted as the index of the desired element from
the generator, or "\*", which allows all elements from the generator.
Providing index outside of the generator is an error.
The argument to `-p`/`--path-filter` must start with either "c:" for
a section filter, or with "g:" for a generator filter. Everything past
the colon is then parsed as either a section filter, or a generator filter.
Note that using `p`/`--path-filter` enables new filtering behaviour, even
if it is only used to add section filters.
There is another important difference between filtering out sections and
generators. A section can be left un-entered, but a generator always has
to be active. For this reason, if generator fails a filter
(e.g. there is a section filter at given depth instead), it has to stop
the execution of the test case. Currently, this is done via `SKIP()`
equivalent, causing the section to be considered skipped.
### Examples
#### Nested generators
```cpp
TEST_CASE( "waldo" ) {
auto i = GENERATE( 1, 10, 100 );
auto j = GENERATE( 2, 20, 200 );
CAPTURE( i, j );
REQUIRE( true );
}
```
* `./tests waldo -g 1` results in 3 assertions, with `i := 10`, because
the second nested generator is unfiltered.
* `./tests waldo -g 1 -g 2` results in 1 assertion, with `i := 10, j := 200`.
* `./tests waldo -g * -g 2` results in 3 assertions, all with `j := 200`.
* `./tests waldo -g 1 -g *` results in 3 assertions, all with `i := 10`.
* `./tests waldo -g 3` results in 1 **failed** assertion, because the first
generator does not have 3rd element.
* `./tests waldo -g * -g 3` results in 3 **failed** assertions, as the
second generator does not have 3rd element, but we have to exhaust the
first generator.
#### Generator with a nested dynamic section
```cpp
TEST_CASE( "grault" ) {
REQUIRE( true );
auto i = GENERATE( 1, 2, 3 );
DYNAMIC_SECTION( "i=" << i ) {
REQUIRE( true );
}
}
```
* `./tests grault -p g:1` results in 2 assertions, as there is no filter
on the dynamic section.
* `./tests grault -p g:1 -p c:i=2` results in 2 assertions, as the filter
on the dynamic section matches the element given from the generator.
* `./tests grault -p g:1 -p c:i=3` results in 1 assertion, as the generator
is limited to only try `i := 2` and the dynamic section is filtered out.
#### Section with a sibling generator
Because generators have to stop test execution when they don't pass filter,
it is impossible to run only a section with sibling generator without
triggering a test case skip. Consider this test case from an earlier example:
```cpp
TEST_CASE( "qux" ) {
REQUIRE( true );
SECTION( "A" ) { REQUIRE( true ); }
auto i = GENERATE( 1, 2, 3 );
DYNAMIC_SECTION( "i=" << i ) {
REQUIRE( true );
}
}
```
* `./tests qux -p g:1` results in 2 assertions, as the dynamic section is
entered only once.
* `./tests qux -p g:1 -p c:i=1` results in 1 assertion, as the dynamic
section filter is incompatible with the generator filter.
* `./tests qux -p c:A` results in 2 assertions **and a skipped test case**.
This is because the generator is sibling to section "A", and thus reads
the same section filter. However, it is not a section and as thus cannot
proceed.
* `./tests qux -p c:i=2` results in 1 assertion **and a skipped test case**.
Once again, the first filter in the filter stack is a section filter,
and thus the generator cannot proceed.
Compare this with the old filter behaviour, where `./tests qux -c i=2`
would instead result in 4 assertions, because the generator would go
through all elements.
---
[Home](Readme.md#top)
+2 -65
View File
@@ -1,12 +1,6 @@
<a id="top"></a>
# Data Generators
**Contents**<br>
[Combining `GENERATE` and `SECTION`.](#combining-generate-and-section)<br>
[Provided generators](#provided-generators)<br>
[Generator interface](#generator-interface)<br>
[Other usage examples](#other-usage-examples)<br>
> Introduced in Catch2 2.6.0.
Data generators (also known as _data driven/parametrized test cases_)
@@ -112,7 +106,7 @@ a test case,
* 2 fundamental generators
* `SingleValueGenerator<T>` -- contains only single element
* `FixedValuesGenerator<T>` -- contains multiple elements
* 6 generic generators that modify other generators (defined in `catch2/generators/catch_generators_adapters.hpp`)
* 5 generic generators that modify other generators (defined in `catch2/generators/catch_generators_adapters.hpp`)
* `FilterGenerator<T, Predicate>` -- filters out elements from a generator
for which the predicate returns "false"
* `TakeGenerator<T>` -- takes first `n` elements from a generator
@@ -120,7 +114,6 @@ a test case,
* `MapGenerator<T, U, Func>` -- returns the result of applying `Func`
on elements from a different generator
* `ChunkGenerator<T>` -- returns chunks (inside `std::vector`) of n elements from a generator
* `ConcatGenerator<T>` -- returns elements from multiple generators as if they were one
* 2 random generators (defined in `catch2/generators/catch_generators_random.hpp`)
* `RandomIntegerGenerator<Integral>` -- generates random Integrals from range
* `RandomFloatGenerator<Float>` -- generates random Floats from range
@@ -132,8 +125,6 @@ a test case,
> `IteratorGenerator<T>` was introduced in Catch2 2.10.0.
> `ConcatGenerator<T>` was introduced in Catch2 3.13.0
The generators also have associated helper functions that infer their
type, making their usage much nicer. These are
@@ -151,7 +142,6 @@ type, making their usage much nicer. These are
* `range(Arithmetic start, Arithmetic end, Arithmetic step)` for `RangeGenerator<Arithmetic>` with a custom step size
* `from_range(InputIterator from, InputIterator to)` for `IteratorGenerator<T>`
* `from_range(Container const&)` for `IteratorGenerator<T>`
* `cat(GeneratorWrapper<T>&&...)` for `ConcatGenerator<T>`
> `chunk()`, `random()` and both `range()` functions were introduced in Catch2 2.7.0.
@@ -159,8 +149,6 @@ type, making their usage much nicer. These are
> `range()` for floating point numbers has been introduced in Catch2 2.11.0
> `cat` has been introduced in Catch2 3.13.0
And can be used as shown in the example below to create a generator
that returns 100 odd random number:
@@ -264,34 +252,9 @@ struct IGenerator : GeneratorUntypedBase {
// Returns user-friendly string showing the current generator element
// Does not have to be overridden, IGenerator provides default implementation
virtual std::string stringifyImpl() const;
/**
* Customization point for `skipToNthElement`
*
* Does not have to be overridden, there is a default implementation.
* Can be overridden for better performance.
*
* If there are not enough elements, shall throw an error.
*
* Going backwards is not supported.
*/
virtual void skipToNthElementImpl( std::size_t n );
/**
* Returns true if calls to `next` will eventually return false
*
* Note that for backwards compatibility this is currently defaulted
* to return `true`, but in the future all generators will have to
* provide their own implementation.
*/
virtual bool isFinite() const = 0;
};
```
> `skipToNthElementImpl` was added in Catch2 3.13.0
> `isFinite` was added in Catch2 3.13.0
However, to be able to use your custom generator inside `GENERATE`, it
will need to be wrapped inside a `GeneratorWrapper<T>`.
`GeneratorWrapper<T>` is a value wrapper around a
@@ -312,35 +275,9 @@ There are two ways to handle this, depending on whether you want this
to be an error or not.
* If empty generator **is** an error, throw an exception in constructor.
* If empty generator **is not** an error, use the [`SKIP` macro](skipping-passing-failing.md#skipping-test-cases-at-runtime) in constructor.
* If empty generator **is not** an error, use the [`SKIP`](skipping-passing-failing.md#skipping-test-cases-at-runtime) in constructor.
## Other usage examples
### Adding a reproducer to random tests
If you use generators to generate random inputs for testing, you might
want to combine them with specific inputs, e.g. reproducers for previously
found issues.
Because `GENERATE` accepts multiple values/generators, the basic case is simple:
```cpp
const int input = GENERATE(1, 2, take(10, random(10, 10'000'000)));
```
This will set `input` first to "1", then to "2", and then to 10 random
integers.
But if you process the random inputs further (e.g. via `map`), you can't
rely on `GENERATE`'s support for multiple generators. In that case, you
have to use the `cat` generator combinator.
```cpp
const auto input = GENERATE(
map( foo,
cat( value( 4 ), take( 10, random( 10, 10'000'000 ) ) ) ) );
```
This will set `input` first to `foo(4)`, before transforming the 10 random
integers through `foo`.
---
+11 -22
View File
@@ -26,22 +26,19 @@ started" and "Section B", while the third one will only report "Test case
started" as the extra info.
## Logging outside of current scope
## Logging without local scope
> `UNSCOPED_INFO` was [introduced](https://github.com/catchorg/Catch2/issues/1522) in Catch2 2.7.0.
> [Introduced](https://github.com/catchorg/Catch2/issues/1522) in Catch2 2.7.0.
> `UNSCOPED_CAPTURE` was introduced in Catch2 3.13.0.
`UNSCOPED_INFO` is similar to `INFO` with two key differences:
The `UNSCOPED_X` macros are similar to their plain `X` macro counterparts,
with two key differences:
- The lifetime of an unscoped message is not tied to its own scope.
- Lifetime of an unscoped message is not tied to its own scope.
- An unscoped message can be reported by the first following assertion only, regardless of the result of that assertion.
In other words, the `UNSCOPED_X` macros are useful to add extra information
to the next assertion, e.g. from helper functions or inner scopes.
In other words, lifetime of `UNSCOPED_INFO` is limited by the following assertion (or by the end of test case/section, whichever comes first) whereas lifetime of `INFO` is limited by its own scope.
These differences make this macro useful for reporting information from helper functions or inner scopes. An example:
An example:
```cpp
void print_some_info() {
UNSCOPED_INFO("Info from helper");
@@ -86,16 +83,9 @@ Second info
Second unscoped info
```
Note that unscoped messages are not passed between test cases, even if
there were no assertions between them.
## Streaming macros
Apart from `CAPTURE` (and its close sibling, `UNSCOPED_CAPTURE`), message
macros support gradual streaming of messages and values in the same way
that the standard streams do.
All these macros allow heterogeneous sequences of values to be streaming using the insertion operator (```<<```) in the same way that std::ostream, std::cout, etc support it.
E.g.:
```c++
@@ -109,6 +99,9 @@ These macros come in three forms:
The message is logged to a buffer, but only reported with next assertions that are logged. This allows you to log contextual information in case of failures which is not shown during a successful test run (for the console reporter, without -s). Messages are removed from the buffer at the end of their scope, so may be used, for example, in loops.
_Note that in Catch2 2.x.x `INFO` can be used without a trailing semicolon as there is a trailing semicolon inside macro.
This semicolon will be removed with next major version. It is highly advised to use a trailing semicolon after `INFO` macro._
**UNSCOPED_INFO(** _message expression_ **)**
> [Introduced](https://github.com/catchorg/Catch2/issues/1522) in Catch2 2.7.0.
@@ -135,10 +128,6 @@ AS `FAIL`, but does not abort the test
**CAPTURE(** _expression1_, _expression2_, ... **)**
**UNSCOPED_CAPTURE(** _expression1_, _expression2_, ... **)**
> `UNSCOPED_CAPTURE` was introduced in Catch2 3.13.0.
Sometimes you just want to log a value of variable, or expression. For
convenience, we provide the `CAPTURE` macro, that can take a variable,
or an expression, and prints out that variable/expression and its value
-37
View File
@@ -6,7 +6,6 @@
[Built-in matchers](#built-in-matchers)<br>
[Writing custom matchers (old style)](#writing-custom-matchers-old-style)<br>
[Writing custom matchers (new style)](#writing-custom-matchers-new-style)<br>
[Constexpr matchers](#constexpr-matchers)<br>
Matchers, as popularized by the [Hamcrest](https://en.wikipedia.org/wiki/Hamcrest)
framework are an alternative way to write assertions, useful for tests
@@ -472,42 +471,6 @@ and new style matchers arbitrarily.
> `MatcherGenericBase` lives in `catch2/matchers/catch_matchers_templated.hpp`
## Constexpr matchers
> Support for constexpr matchers was introduced in Catch2 3.15.0
When compiled for C++20, the new-style matchers (can) support `constexpr`
matching, albeit not `constexpr` stringification. The matcher combinators
require C++26 (or at least P2738) to be `constexpr` compatible.
This can be used together with the `STATIC_REQUIRE_THAT` macro to write
matcher-based static assertions like this:
```cpp
TEST_CASE("Constexpr support for matchers", "[constexpr][matchers]") {
STATIC_REQUIRE_THAT( 1, MatchAll() );
STATIC_REQUIRE_THAT( 1, MatchAll() || MatchAll() );
STATIC_REQUIRE_THAT( 1, !!MatchAll() );
}
```
### First party constexpr matchers
Some (but not all) of Catch2's generic matchers support `constexpr`
matching. Currently, this includes:
* `IsEmpty()`
* `SizeIs(size_t target_size)`, `SizeIs(Matcher size_matcher)`
* `AllMatch(Matcher element_matcher)`
* `AnyMatch(Matcher element_matcher)`
* `NoneMatch(Matcher element_matcher)`
* `AllTrue()`, `AnyTrue()`, `NoneTrue()`
* `Contains(T&& target_element, Comparator = std::equal_to<>{})`
* `Contains(Matcher element_matcher)`
* `RangeEquals(TargetRangeLike&&, Comparator = std::equal_to<>{})`
* `UnorderedRangeEquals(TargetRangeLike&&, Comparator = std::equal_to<>{})`
---
[Home](Readme.md#top)
+4 -28
View File
@@ -72,8 +72,8 @@ including the Catch2 header.
Example:
```cpp
TEST_CASE("STATIC_REQUIRE showcase", "[traits]") {
STATIC_REQUIRE( std::is_void<void>::value );
STATIC_REQUIRE_FALSE( std::is_void<int>::value );
STATIC_REQUIRE( std::is_void_v<void> );
STATIC_REQUIRE_FALSE( std::is_void_v<int> );
}
```
@@ -86,35 +86,11 @@ becomes equivalent to `CHECK` instead of `REQUIRE`.
Example:
```cpp
TEST_CASE("STATIC_CHECK showcase", "[traits]") {
STATIC_CHECK( std::is_void<void>::value );
STATIC_CHECK_FALSE( std::is_void<int>::value );
STATIC_CHECK( std::is_void_v<void> );
STATIC_CHECK_FALSE( std::is_void_v<int> );
}
```
* `STATIC_REQUIRE_THAT` and `STATIC_CHECK_THAT`
> `STATIC_REQUIRE_THAT` and `STATIC_CHECK_THAT` was introduced in Catch2 3.15.0
`STATIC_{REQUIRE,CHECK}_THAT` are analogous to `STATIC_{REQUIRE,CHECK}`,
but for matchers. They are always defined, even if the current compiler
does not support `constexpr` matchers, but in that case the compilation
will always fail.
Just like `STATIC_{REQUIRE,CHECK}`, `STATIC_{REQUIRE,CHECK}_THAT` can be
delayed into runtime through the `CATCH_CONFIG_RUNTIME_STATIC_REQUIRE`
configuration option.
Example:
```cpp
TEST_CASE("Constexpr support for matchers", "[constexpr][matchers]") {
STATIC_REQUIRE_THAT( 1, MatchAll() );
STATIC_REQUIRE_THAT( 1, MatchAll() && MatchAll() );
STATIC_REQUIRE_THAT( 1, MatchAll() || MatchAll() );
STATIC_REQUIRE_THAT( 1, !!MatchAll() );
}
```
## Test case related macros
* `REGISTER_TEST_CASE`
+1 -1
View File
@@ -65,7 +65,7 @@ int main( int argc, char* argv[] ) {
returnCode = session.run();
// returnCode encodes the type of error that occurred. See the
// returnCode encodes the type of error that occured. See the
// integer constants in catch_session.hpp for more information
// on what each return code means.
-109
View File
@@ -2,11 +2,6 @@
# Release notes
**Contents**<br>
[3.15.0](#3150)<br>
[3.14.0](#3140)<br>
[3.13.0](#3130)<br>
[3.12.0](#3120)<br>
[3.11.0](#3110)<br>
[3.10.0](#3100)<br>
[3.9.1](#391)<br>
[3.9.0](#390)<br>
@@ -75,110 +70,6 @@
[Even Older versions](#even-older-versions)<br>
## 3.15.0
### Fixes
* Fixed ambiguous overload issue with `std::optional<T>` in C++26. (#3095)
* Since `std::optional` was turned into a range, the partial specialization of `StringMaker` for range-like types and for `std::optional<T>` were in conflict.
### Improvements
* Simplified `CATCH_REGISTER_ENUM` internals for faster compilation and retrieval.
* Successful assertion are slightly (1-2%) faster.
* Generic (new-style) matchers support constexpr matching in C++20.
* Combining matchers requires C++26.
* Catch2-provided generic matchers are all constexpr enabled.
* Added `STATIC_REQUIRE_THAT` for compile-time matcher assertions.
* This requires the compiler to support enough `constexpr` for matchers, see above.
## 3.14.0
### Fixes
* Added missing `<cstdint>` includes. (#3078)
* Fixed suppression of empty variadic macro arguments warning on Clang <19. (#3085)
* Fixed `catch_discover_tests` failing during `PRE_TEST` discovery if a target does not have discoverable tests. (#3075)
* Fixed build of the main library failing with `CATCH_CONFIG_PREFIX_ALL` defined. (#3087)
* JUnit reporter outputs single failed (errored/skipped) assertion per test case. (#1919)
### Improvements
* The default implementation of `--list-tags` and `--list-listeners` has a quiet variant.
* Suppressed the new Clang warning about `__COUNTER__` usage. (#3076)
* Line-wrapping counts utf-8 codepoints instead of bytes. (#1022, #3086)
* Combining character sequences are still miscounted, but Catch2 does not aim to fully support Unicode.
## 3.13.0
### Fixes
* `--benchmark-samples 0` no longer hard crashes (#3056)
* The CLI validation fails instead.
* Fixed warning suppression macros being doubly defined when using Clang on Windows (#3060)
### Improvements
* Suppressed static analysis 26426 diagnostic for MSVC (#3057)
* Renamed the internal deprecation macro from `DEPRECATED` to `CATCH_DEPRECATED` to avoid conflicts (#3058)
* Added `UNSCOPED_CAPTURE` macro (#2954)
* Added `ConcatGenerator` to combine multiple separate generator into one
* The short form is `cat`
* Generators can now jump forward to nth element efficiently
* Custom generators that can jump forward efficiently should override `skipToNthElementImpl`
* Generators can declare themselves infinite
* The generator base defaults to declaring itself finite for backwards compatibility
* Custom generators should override `isFinite()` to return the proper value
* Added `--warn InfiniteGenerators` to error out on `GENERATE` being given an infinite generator
* Extended options for section filtering from CLI to include generators
* The user can specify which element from the generator to use in the test case
* See documentation for how the new filters work and how they can be specified
* `MapGenerator` only calls the mapping function if the output will be used
## 3.12.0
### Fixes
* Fixed unscoped messages after a passing fast-pathed assertion being lost.
* Fixed the help string for `--order` to mention random order as the default. (#3045)
* Fixed small documentation typos. (#3039)
* Fixed compilation with `CATCH_CONFIG_THREAD_SAFE_ASSERTIONS` for older C++ standards.
* Fixed a thread-safety issue with message macros being used too early after the process starts.
* Fixed automatic configuration to properly handle PlayStation platform. (#3054)
* **Fixed the _weird_ behaviour of section filtering when specifying multiple filters.** (#3038)
* See #3038 for more details.
### Improvements
* Added `lifetimebound` attribute to various places.
* As an example, compiler that supports lifetime analysis will now diagnose invalid use of Matcher combinators.
* Minor compile-time improvements to stringification. (#3028)
* `std::tuple` printer does not recurse.
* Some implementation details were outlined into the cpp file.
* Global variables will only be marked with `thread_local` in thread-safe builds. (#3044)
### Miscellaneous
* The thread safety support is no longer experimental.
* The new CMake option and C++ define is now `CATCH_CONFIG_THREAD_SAFE_ASSERTIONS`.
## 3.11.0
### Fixes
* Fixed building on non-desktop GDK platforms (#3029)
* Fixed message macros being susceptible to race in specific scenario (#3031)
* Catch2's SEH filter will call the previously installed filter after reporting the error (#3033)
### Improvements
* Handling of scoped messages (e.g. `CAPTURE`) is a bit faster.
* Better out-of-the-box support for QNX (#2953)
* Improved performance of assertions by up-to 10%
* Release mode assertion fast-path sees the biggest improvement.
* Faster processing of non-escaped strings in `--invisibles` mode.
* Added support for Bazel's `TEST_RANDOM_SEED` env var (#3021)
* Added support for Bazel's `TEST_PREMATURE_EXIT_FILE` env var (#3020)
* This creates a file that is deleted if the tests exit normally, but stays around if the process dies unexpectedly.
* This functionality is also exposed through CLI as `--premature-exit-guard-file`
### Miscellaneous
* **[Tuple.app](https://tuple.app/catch2) has sponsored Catch2**
## 3.10.0
### Fixes
+5 -5
View File
@@ -109,10 +109,10 @@ and then `assertionEnded` event is emitted.
> [Introduced](https://github.com/catchorg/Catch2/issues/1616) in Catch2 2.9.0.
```cpp
void benchmarkPreparing( StringRef name ) override;
void benchmarkPreparing( std::string_view name ) override;
void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
void benchmarkFailed( StringRef error ) override;
void benchmarkFailed( std::string_view error ) override;
```
Due to the benchmark lifecycle being bit more complicated, the benchmarking
@@ -153,9 +153,9 @@ void listTags( std::vector<TagInfo> const& tagInfos );
## Miscellaneous events
```cpp
void reportInvalidTestSpec( StringRef unmatchedSpec );
void fatalErrorEncountered( StringRef error );
void noMatchingTestCases( StringRef unmatchedSpec );
void reportInvalidTestSpec( std::string_view unmatchedSpec );
void fatalErrorEncountered( std::string_view error );
void noMatchingTestCases( std::string_view unmatchedSpec );
```
These are one-off events that do not neatly fit into other categories.
+1 -1
View File
@@ -87,7 +87,7 @@ TEST_CASE("complex test case") {
```
This test case will report 5 passing assertions; one for each of the three
values in section `a1`, and then two in section `a2`, from values 2 and 6.
values in section `a1`, and then two in section `a2`, from values 2 and 4.
Note that as soon as one section is skipped, the entire test case will
be reported as _skipped_ (unless there is a failing assertion, in which
+1 -1
View File
@@ -264,7 +264,7 @@ You can also have different arities in the _template-arg_ packs:
```cpp
TEMPLATE_PRODUCT_TEST_CASE("Product with differing arities", "[template][product]", std::tuple, (int, (int, double), (int, double, float))) {
TestType x;
REQUIRE(std::tuple_size<TestType>::value >= 1);
REQUIRE(std::tuple_size_v<TestType> >= 1);
}
```
+1 -1
View File
@@ -20,7 +20,7 @@ test case macros is not thread-safe. The way sections define paths through
the test is incompatible with user spawning threads arbitrarily, so this
limitation is here to stay.
**Important: thread safety in Catch2 is [opt-in](configuration.md#thread-safety)**
**Important: thread safety in Catch2 is [opt-in](configuration.md#experimental-thread-safety)**
## Using assertion macros from spawned threads
+1 -1
View File
@@ -15,7 +15,7 @@ So what does Catch2 bring to the party that differentiates it from these? Apart
## Key Features
* Quick and easy to get started. Just download two files, add them into your project and you're away.
* No external dependencies. As long as you can compile C++14 and have the C++ standard library available.
* No external dependencies. As long as you can compile C++17 and have the C++ standard library available.
* Write test cases as, self-registering, functions (or methods, if you prefer).
* Divide test cases into sections, each of which is run in isolation (eliminates the need for fixtures).
* Use BDD-style Given-When-Then sections as well as traditional unit test cases.
+1 -1
View File
@@ -27,7 +27,7 @@ TEST_CASE( "Factorials of 1 and higher are computed (pass)", "[single-file]" ) {
}
// Compile & run:
// - g++ -std=c++14 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 010-TestCase 010-TestCase.cpp && 010-TestCase --success
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 010-TestCase 010-TestCase.cpp && 010-TestCase --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 010-TestCase.cpp && 010-TestCase --success
// Expected compact output (all assertions):
+2 -2
View File
@@ -18,8 +18,8 @@ TEST_CASE( "1: All test cases reside in other .cpp files (empty)", "[multi-file:
// Here just to show there are two source files via option --list-tests.
// Compile & run:
// - g++ -std=c++14 -Wall -I$(CATCH_SINGLE_INCLUDE) -c 020-TestCase-1.cpp
// - g++ -std=c++14 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 020-TestCase TestCase-1.o 020-TestCase-2.cpp && 020-TestCase --success
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -c 020-TestCase-1.cpp
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 020-TestCase TestCase-1.o 020-TestCase-2.cpp && 020-TestCase --success
//
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% -c 020-TestCase-1.cpp
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% -Fe020-TestCase.exe 020-TestCase-1.obj 020-TestCase-2.cpp && 020-TestCase --success
+1 -1
View File
@@ -61,7 +61,7 @@ TEST_CASE( "Assert that something is false (continue after failure)", "[check-fa
}
// Compile & run:
// - g++ -std=c++14 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 030-Asn-Require-Check 030-Asn-Require-Check.cpp && 030-Asn-Require-Check --success
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 030-Asn-Require-Check 030-Asn-Require-Check.cpp && 030-Asn-Require-Check --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 030-Asn-Require-Check.cpp && 030-Asn-Require-Check --success
// Expected compact output (all assertions):
+1 -1
View File
@@ -53,7 +53,7 @@ TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
}
// Compile & run:
// - g++ -std=c++14 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 100-Fix-Section 100-Fix-Section.cpp && 100-Fix-Section --success
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 100-Fix-Section 100-Fix-Section.cpp && 100-Fix-Section --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 100-Fix-Section.cpp && 100-Fix-Section --success
// Expected compact output (all assertions):
+2 -2
View File
@@ -60,11 +60,11 @@ TEST_CASE_METHOD( UniqueTestsFixture, "Create Employee/Normal", "[create]" ) {
}
// Compile & run:
// - g++ -std=c++14 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 110-Fix-ClassFixture 110-Fix-ClassFixture.cpp && 110-Fix-ClassFixture --success
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 110-Fix-ClassFixture 110-Fix-ClassFixture.cpp && 110-Fix-ClassFixture --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 110-Fix-ClassFixture.cpp && 110-Fix-ClassFixture --success
//
// Compile with pkg-config:
// - g++ -std=c++14 -Wall $(pkg-config catch2-with-main --cflags) -o 110-Fix-ClassFixture 110-Fix-ClassFixture.cpp $(pkg-config catch2-with-main --libs)
// - g++ -std=c++17 -Wall $(pkg-config catch2-with-main --cflags) -o 110-Fix-ClassFixture 110-Fix-ClassFixture.cpp $(pkg-config catch2-with-main --libs)
// Expected compact output (all assertions):
//
+1 -1
View File
@@ -56,7 +56,7 @@ SCENARIO( "vectors can be sized and resized", "[vector]" ) {
}
// Compile & run:
// - g++ -std=c++14 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 120-Bdd-ScenarioGivenWhenThen 120-Bdd-ScenarioGivenWhenThen.cpp && 120-Bdd-ScenarioGivenWhenThen --success
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 120-Bdd-ScenarioGivenWhenThen 120-Bdd-ScenarioGivenWhenThen.cpp && 120-Bdd-ScenarioGivenWhenThen --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 120-Bdd-ScenarioGivenWhenThen.cpp && 120-Bdd-ScenarioGivenWhenThen --success
// Expected compact output (all assertions):
+4 -4
View File
@@ -131,7 +131,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
}
// struct Tag {
// StringRef original, lowerCased;
// std::string_view original, lowerCased;
// };
//
//
@@ -221,9 +221,9 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// struct AssertionInfo
// {
// StringRef macroName;
// std::string_view macroName;
// SourceLineInfo lineInfo;
// StringRef capturedExpression;
// std::string_view capturedExpression;
// ResultDisposition::Flags resultDisposition;
// };
@@ -427,7 +427,7 @@ TEST_CASE_METHOD( Fixture, "3: Testcase with class-based fixture", "[tag-C][tag-
}
// Compile & run:
// - g++ -std=c++14 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 210-Evt-EventListeners 210-Evt-EventListeners.cpp && 210-Evt-EventListeners --success
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 210-Evt-EventListeners 210-Evt-EventListeners.cpp && 210-Evt-EventListeners --success
// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 210-Evt-EventListeners.cpp && 210-Evt-EventListeners --success
// Expected compact output (all assertions):
-18
View File
@@ -39,24 +39,6 @@ public:
current_number = m_dist(m_rand);
return true;
}
bool isFinite() const override { return false; }
// Note: this improves the performance only a bit, but it is here
// to show how you can override the skip functionality.
void skipToNthElementImpl( std::size_t n ) override {
auto current_index = currentElementIndex();
assert(current_index <= n);
// We cannot jump forward the underlying generator directly,
// because we do not know how many bits each distributed number
// would consume to be generated.
for (; current_index < n; ++current_index) {
(void)m_dist(m_rand);
}
// We do not have to touch the current element index; it is handled
// by the base class.
}
};
// Avoids -Wweak-vtables
-2
View File
@@ -40,8 +40,6 @@ public:
bool next() override {
return !!std::getline(m_stream, m_line);
}
bool isFinite() const override { return true; }
};
std::string const& LineGenerator::get() const {
+5 -18
View File
@@ -22,24 +22,21 @@ struct TestSubject {
TEST_CASE("Table allows pre-computed test inputs and outputs", "[example][generator]") {
using std::make_tuple;
// do setup here as normal
TestSubject subj;
SECTION("This section is run for each row in the table") {
std::string test_input;
size_t expected_output;
std::tie( test_input, expected_output ) =
const auto [test_input, expected_output] =
GENERATE( table<std::string, size_t>(
{ /* In this case one of the parameters to our test case is the
* expected output, but this is not required. There could be
* multiple expected values in the table, which can have any
* (fixed) number of columns.
*/
make_tuple( "one", 3 ),
make_tuple( "two", 3 ),
make_tuple( "three", 5 ),
make_tuple( "four", 4 ) } ) );
{ "one", 3 },
{ "two", 3 },
{ "three", 5 },
{ "four", 4 } } ) );
// run the test
auto result = subj.GetLength(test_input);
@@ -50,14 +47,4 @@ TEST_CASE("Table allows pre-computed test inputs and outputs", "[example][genera
} // end section
}
/* Possible simplifications where less legacy toolchain support is needed:
*
* - With libstdc++6 or newer, the make_tuple() calls can be omitted
* (technically C++17 but does not require -std in GCC/Clang). See
* https://stackoverflow.com/questions/12436586/tuple-vector-and-initializer-list
*
* - In C++17 mode std::tie() and the preceding variable declarations can be
* replaced by structured bindings: auto [test_input, expected] = GENERATE(
* table<std::string, size_t>({ ...
*/
// Compiling and running this file will result in 4 successful assertions
-1
View File
@@ -146,7 +146,6 @@ function(catch_discover_tests_impl)
# Exit early if no tests are detected
if(num_tests STREQUAL "0")
file(WRITE "${_CTEST_FILE}" "")
return()
endif()
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-1
View File
@@ -9,7 +9,6 @@
#include <catch2/internal/catch_test_spec_parser.hpp>
#include <catch2/internal/catch_tag_alias_registry.hpp>
#include <cstdint>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
-1
View File
@@ -13,7 +13,6 @@
#include <string>
#include <string_view>
#include <cstdint>
template<class Callback>
+1 -1
View File
@@ -8,7 +8,7 @@
project(
'catch2',
'cpp',
version: '3.15.0', # CML version placeholder, don't delete
version: '3.10.0', # CML version placeholder, don't delete
license: 'BSL-1.0',
meson_version: '>=0.54.1',
)
+6 -16
View File
@@ -76,18 +76,16 @@ set(IMPL_HEADERS
${SOURCES_DIR}/internal/catch_config_counter.hpp
${SOURCES_DIR}/internal/catch_config_prefix_messages.hpp
${SOURCES_DIR}/internal/catch_config_static_analysis_support.hpp
${SOURCES_DIR}/internal/catch_config_uncaught_exceptions.hpp
${SOURCES_DIR}/internal/catch_config_wchar.hpp
${SOURCES_DIR}/internal/catch_console_colour.hpp
${SOURCES_DIR}/internal/catch_console_width.hpp
${SOURCES_DIR}/internal/catch_container_nonmembers.hpp
${SOURCES_DIR}/internal/catch_context.hpp
${SOURCES_DIR}/internal/catch_debug_console.hpp
${SOURCES_DIR}/internal/catch_debugger.hpp
${SOURCES_DIR}/internal/catch_decomposer.hpp
${SOURCES_DIR}/internal/catch_deprecation_macro.hpp
${SOURCES_DIR}/internal/catch_enforce.hpp
${SOURCES_DIR}/internal/catch_enum_info.hpp
${SOURCES_DIR}/internal/catch_enum_values_registry.hpp
${SOURCES_DIR}/internal/catch_errno_guard.hpp
${SOURCES_DIR}/internal/catch_exception_translator_registry.hpp
${SOURCES_DIR}/internal/catch_fatal_condition_handler.hpp
@@ -98,17 +96,13 @@ set(IMPL_HEADERS
${SOURCES_DIR}/internal/catch_jsonwriter.hpp
${SOURCES_DIR}/internal/catch_lazy_expr.hpp
${SOURCES_DIR}/internal/catch_leak_detector.hpp
${SOURCES_DIR}/internal/catch_lifetimebound.hpp
${SOURCES_DIR}/internal/catch_list.hpp
${SOURCES_DIR}/internal/catch_logical_traits.hpp
${SOURCES_DIR}/internal/catch_message_info.hpp
${SOURCES_DIR}/internal/catch_meta.hpp
${SOURCES_DIR}/internal/catch_move_and_forward.hpp
${SOURCES_DIR}/internal/catch_noncopyable.hpp
${SOURCES_DIR}/internal/catch_optional.hpp
${SOURCES_DIR}/internal/catch_output_redirect.hpp
${SOURCES_DIR}/internal/catch_parse_numbers.hpp
${SOURCES_DIR}/internal/catch_path_filter.hpp
${SOURCES_DIR}/internal/catch_platform.hpp
${SOURCES_DIR}/internal/catch_polyfills.hpp
${SOURCES_DIR}/internal/catch_preprocessor.hpp
@@ -130,7 +124,6 @@ set(IMPL_HEADERS
${SOURCES_DIR}/internal/catch_stdstreams.hpp
${SOURCES_DIR}/internal/catch_stream_end_stop.hpp
${SOURCES_DIR}/internal/catch_string_manip.hpp
${SOURCES_DIR}/internal/catch_stringref.hpp
${SOURCES_DIR}/internal/catch_tag_alias_registry.hpp
${SOURCES_DIR}/internal/catch_template_test_registry.hpp
${SOURCES_DIR}/internal/catch_test_case_info_hasher.hpp
@@ -141,7 +134,6 @@ set(IMPL_HEADERS
${SOURCES_DIR}/internal/catch_test_registry.hpp
${SOURCES_DIR}/internal/catch_test_spec_parser.hpp
${SOURCES_DIR}/internal/catch_textflow.hpp
${SOURCES_DIR}/internal/catch_thread_local.hpp
${SOURCES_DIR}/internal/catch_thread_support.hpp
${SOURCES_DIR}/internal/catch_to_string.hpp
${SOURCES_DIR}/internal/catch_uncaught_exceptions.hpp
@@ -181,7 +173,7 @@ set(IMPL_SOURCES
${SOURCES_DIR}/internal/catch_debugger.cpp
${SOURCES_DIR}/internal/catch_decomposer.cpp
${SOURCES_DIR}/internal/catch_enforce.cpp
${SOURCES_DIR}/internal/catch_enum_info.cpp
${SOURCES_DIR}/internal/catch_enum_values_registry.cpp
${SOURCES_DIR}/internal/catch_errno_guard.cpp
${SOURCES_DIR}/internal/catch_exception_translator_registry.cpp
${SOURCES_DIR}/internal/catch_fatal_condition_handler.cpp
@@ -208,7 +200,6 @@ set(IMPL_SOURCES
${SOURCES_DIR}/internal/catch_startup_exception_registry.cpp
${SOURCES_DIR}/internal/catch_stdstreams.cpp
${SOURCES_DIR}/internal/catch_string_manip.cpp
${SOURCES_DIR}/internal/catch_stringref.cpp
${SOURCES_DIR}/internal/catch_tag_alias_registry.cpp
${SOURCES_DIR}/internal/catch_test_case_info_hasher.cpp
${SOURCES_DIR}/internal/catch_test_case_registry_impl.cpp
@@ -227,6 +218,7 @@ set(INTERFACE_HEADERS
${SOURCES_DIR}/interfaces/catch_interfaces_all.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_capture.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_config.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_enum_values_registry.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_exception.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_generatortracker.hpp
${SOURCES_DIR}/interfaces/catch_interfaces_registry_hub.hpp
@@ -255,13 +247,11 @@ set(GENERATOR_HEADERS
${SOURCES_DIR}/generators/catch_generators_all.hpp
${SOURCES_DIR}/generators/catch_generators_random.hpp
${SOURCES_DIR}/generators/catch_generators_range.hpp
${SOURCES_DIR}/generators/catch_generators_throw.hpp
)
set(GENERATOR_SOURCES
${SOURCES_DIR}/generators/catch_generator_exception.cpp
${SOURCES_DIR}/generators/catch_generators.cpp
${SOURCES_DIR}/generators/catch_generators_random.cpp
${SOURCES_DIR}/generators/catch_generators_throw.cpp
)
set(GENERATOR_FILES ${GENERATOR_HEADERS} ${GENERATOR_SOURCES})
@@ -369,8 +359,8 @@ set_target_properties(Catch2 PROPERTIES
SOVERSION ${PROJECT_VERSION}
)
# require C++14
target_compile_features(Catch2 PUBLIC cxx_std_14)
# require C++17
target_compile_features(Catch2 PUBLIC cxx_std_17)
configure_file(
"${SOURCES_DIR}/catch_user_config.hpp.in"
@@ -454,7 +444,7 @@ if(CATCH_BUILD_EXAMPLES OR CATCH_BUILD_EXTRA_TESTS)
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_compile_definitions(Catch2_buildall_interface INTERFACE CATCH_CONFIG_STATIC)
target_compile_features(Catch2_buildall_interface INTERFACE cxx_std_14)
target_compile_features(Catch2_buildall_interface INTERFACE cxx_std_17)
endif()
list(APPEND CATCH_IMPL_TARGETS Catch2 Catch2WithMain)
+2 -2
View File
@@ -64,12 +64,12 @@ namespace Catch {
}
template <typename Fn, typename... Args>
inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<!std::is_same<void, decltype(fn(args...))>::value> {
inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<!std::is_same_v<void, decltype(fn(args...))>> {
deoptimize_value(CATCH_FORWARD(fn) (CATCH_FORWARD(args)...));
}
template <typename Fn, typename... Args>
inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<std::is_same<void, decltype(fn(args...))>::value> {
inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<std::is_same_v<void, decltype(fn(args...))>> {
CATCH_FORWARD((fn)) (CATCH_FORWARD(args)...);
}
} // namespace Benchmark
@@ -36,17 +36,17 @@ namespace Catch {
samples.data(), samples.data() + samples.size() );
auto wrap_estimate = [](Estimate<double> e) {
return Estimate<FDuration>{
FDuration( e.point ),
FDuration( e.lower_bound ),
FDuration( e.upper_bound ),
e.confidence_interval,
return Estimate<FDuration> {
FDuration(e.point),
FDuration(e.lower_bound),
FDuration(e.upper_bound),
e.confidence_interval,
};
};
std::vector<FDuration> samples2;
samples2.reserve(samples.size());
for (auto s : samples) {
samples2.push_back( FDuration( s ) );
samples2.emplace_back( s );
}
return {
@@ -21,7 +21,7 @@ namespace Catch {
namespace Benchmark {
namespace Detail {
template <typename T, typename U>
static constexpr bool is_related_v = std::is_same<std::decay_t<T>, std::decay_t<U>>::value;
static constexpr bool is_related_v = std::is_same_v<std::decay_t<T>, std::decay_t<U>>;
/// We need to reinvent std::function because every piece of code that might add overhead
/// in a measurement context needs to have consistent performance characteristics so that we
@@ -41,7 +41,7 @@ namespace Catch {
callable& operator=(callable&&) = default;
};
template <typename Fun>
struct model final : public callable {
struct model : public callable {
model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {}
model(Fun const& fun_) : fun(fun_) {}
@@ -8,7 +8,6 @@
#ifndef CATCH_BENCHMARK_STATS_HPP_INCLUDED
#define CATCH_BENCHMARK_STATS_HPP_INCLUDED
#include <catch2/benchmark/catch_clock.hpp>
#include <catch2/benchmark/catch_estimate.hpp>
#include <catch2/benchmark/catch_outlier_classification.hpp>
// The fwd decl & default specialization needs to be seen by VS2017 before
@@ -8,16 +8,14 @@
#ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
#define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
namespace Catch {
#include <catch2/benchmark/catch_clock.hpp>
namespace Detail {
struct DummyTemplateArgPlaceholder;
}
namespace Catch {
// We cannot forward declare the type with default template argument
// multiple times, so it is split out into a separate header so that
// we can prevent multiple declarations in dependencies
template <typename Duration = Detail::DummyTemplateArgPlaceholder>
// we can prevent multiple declarations in dependees
template <typename Duration = Benchmark::FDuration>
struct BenchmarkStats;
} // end namespace Catch
@@ -14,7 +14,7 @@
namespace Catch {
namespace Benchmark {
namespace Detail {
struct optimized_away_error final : std::exception {
struct optimized_away_error : std::exception {
const char* what() const noexcept override;
};
+1 -9
View File
@@ -57,18 +57,16 @@
#include <catch2/internal/catch_config_counter.hpp>
#include <catch2/internal/catch_config_prefix_messages.hpp>
#include <catch2/internal/catch_config_static_analysis_support.hpp>
#include <catch2/internal/catch_config_uncaught_exceptions.hpp>
#include <catch2/internal/catch_config_wchar.hpp>
#include <catch2/internal/catch_console_colour.hpp>
#include <catch2/internal/catch_console_width.hpp>
#include <catch2/internal/catch_container_nonmembers.hpp>
#include <catch2/internal/catch_context.hpp>
#include <catch2/internal/catch_debug_console.hpp>
#include <catch2/internal/catch_debugger.hpp>
#include <catch2/internal/catch_decomposer.hpp>
#include <catch2/internal/catch_deprecation_macro.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_enum_info.hpp>
#include <catch2/internal/catch_enum_values_registry.hpp>
#include <catch2/internal/catch_errno_guard.hpp>
#include <catch2/internal/catch_exception_translator_registry.hpp>
#include <catch2/internal/catch_fatal_condition_handler.hpp>
@@ -79,17 +77,13 @@
#include <catch2/internal/catch_jsonwriter.hpp>
#include <catch2/internal/catch_lazy_expr.hpp>
#include <catch2/internal/catch_leak_detector.hpp>
#include <catch2/internal/catch_lifetimebound.hpp>
#include <catch2/internal/catch_list.hpp>
#include <catch2/internal/catch_logical_traits.hpp>
#include <catch2/internal/catch_message_info.hpp>
#include <catch2/internal/catch_meta.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_noncopyable.hpp>
#include <catch2/internal/catch_optional.hpp>
#include <catch2/internal/catch_output_redirect.hpp>
#include <catch2/internal/catch_parse_numbers.hpp>
#include <catch2/internal/catch_path_filter.hpp>
#include <catch2/internal/catch_platform.hpp>
#include <catch2/internal/catch_polyfills.hpp>
#include <catch2/internal/catch_preprocessor.hpp>
@@ -112,7 +106,6 @@
#include <catch2/internal/catch_stdstreams.hpp>
#include <catch2/internal/catch_stream_end_stop.hpp>
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_tag_alias_registry.hpp>
#include <catch2/internal/catch_template_test_registry.hpp>
#include <catch2/internal/catch_test_case_info_hasher.hpp>
@@ -123,7 +116,6 @@
#include <catch2/internal/catch_test_registry.hpp>
#include <catch2/internal/catch_test_spec_parser.hpp>
#include <catch2/internal/catch_textflow.hpp>
#include <catch2/internal/catch_thread_local.hpp>
#include <catch2/internal/catch_thread_support.hpp>
#include <catch2/internal/catch_to_string.hpp>
#include <catch2/internal/catch_uncaught_exceptions.hpp>
+13 -13
View File
@@ -29,7 +29,7 @@ namespace Catch {
Approx operator-() const;
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
Approx operator()( T const& value ) const {
Approx approx( static_cast<double>(value) );
approx.m_epsilon = m_epsilon;
@@ -38,67 +38,67 @@ namespace Catch {
return approx;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
explicit Approx( T const& value ): Approx(static_cast<double>(value))
{}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
friend bool operator == ( const T& lhs, Approx const& rhs ) {
auto lhs_v = static_cast<double>(lhs);
return rhs.equalityComparisonImpl(lhs_v);
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
friend bool operator == ( Approx const& lhs, const T& rhs ) {
return operator==( rhs, lhs );
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
friend bool operator != ( T const& lhs, Approx const& rhs ) {
return !operator==( lhs, rhs );
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
friend bool operator != ( Approx const& lhs, T const& rhs ) {
return !operator==( rhs, lhs );
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
friend bool operator <= ( T const& lhs, Approx const& rhs ) {
return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
friend bool operator <= ( Approx const& lhs, T const& rhs ) {
return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
friend bool operator >= ( T const& lhs, Approx const& rhs ) {
return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
friend bool operator >= ( Approx const& lhs, T const& rhs ) {
return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
Approx& epsilon( T const& newEpsilon ) {
const auto epsilonAsDouble = static_cast<double>(newEpsilon);
setEpsilon(epsilonAsDouble);
return *this;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
Approx& margin( T const& newMargin ) {
const auto marginAsDouble = static_cast<double>(newMargin);
setMargin(marginAsDouble);
return *this;
}
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
Approx& scale( T const& newScale ) {
m_scale = static_cast<double>(newScale);
return *this;
+4 -3
View File
@@ -10,16 +10,17 @@
#include <catch2/internal/catch_result_type.hpp>
#include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <string_view>
namespace Catch {
struct AssertionInfo {
// AssertionInfo() = delete;
StringRef macroName;
std::string_view macroName;
SourceLineInfo lineInfo;
StringRef capturedExpression;
std::string_view capturedExpression;
ResultDisposition::Flags resultDisposition;
};
+2 -2
View File
@@ -91,14 +91,14 @@ namespace Catch {
: expr;
}
StringRef AssertionResult::getMessage() const {
std::string_view AssertionResult::getMessage() const {
return m_resultData.message;
}
SourceLineInfo AssertionResult::getSourceInfo() const {
return m_info.lineInfo;
}
StringRef AssertionResult::getTestMacroName() const {
std::string_view AssertionResult::getTestMacroName() const {
return m_info.macroName;
}
+2 -3
View File
@@ -11,7 +11,6 @@
#include <catch2/catch_assertion_info.hpp>
#include <catch2/internal/catch_result_type.hpp>
#include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_lazy_expr.hpp>
#include <string>
@@ -46,9 +45,9 @@ namespace Catch {
std::string getExpressionInMacro() const;
bool hasExpandedExpression() const;
std::string getExpandedExpression() const;
StringRef getMessage() const;
std::string_view getMessage() const;
SourceLineInfo getSourceInfo() const;
StringRef getTestMacroName() const;
std::string_view getTestMacroName() const;
//protected:
AssertionInfo m_info;
+9 -38
View File
@@ -10,13 +10,13 @@
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_parse_numbers.hpp>
#include <catch2/internal/catch_stdstreams.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_test_spec_parser.hpp>
#include <catch2/interfaces/catch_interfaces_tag_alias_registry.hpp>
#include <catch2/internal/catch_getenv.hpp>
#include <fstream>
#include <optional>
namespace Catch {
@@ -34,7 +34,7 @@ namespace Catch {
std::string shardFilePath;
};
static Optional<bazelShardingOptions> readBazelShardingOptions() {
static std::optional<bazelShardingOptions> readBazelShardingOptions() {
const auto bazelShardIndex = Detail::getEnv( "TEST_SHARD_INDEX" );
const auto bazelShardTotal = Detail::getEnv( "TEST_TOTAL_SHARDS" );
const auto bazelShardInfoFile = Detail::getEnv( "TEST_SHARD_STATUS_FILE" );
@@ -92,10 +92,6 @@ namespace Catch {
lhs.customOptions == rhs.customOptions;
}
bool operator==( PathFilter const& lhs, PathFilter const& rhs ) {
return lhs.type == rhs.type && lhs.filter == rhs.filter;
}
Config::Config( ConfigData const& data ):
m_data( data ) {
// We need to trim filter specs to avoid trouble with superfluous
@@ -105,6 +101,9 @@ namespace Catch {
for (auto& elem : m_data.testsOrTags) {
elem = trim(elem);
}
for (auto& elem : m_data.sectionsToRun) {
elem = trim(elem);
}
// Insert the default reporter if user hasn't asked for a specific one
if ( m_data.reporterSpecifications.empty() ) {
@@ -120,8 +119,6 @@ namespace Catch {
m_data.reporterSpecifications.push_back( std::move( *parsed ) );
}
// Reading bazel env vars can change some parts of the config data,
// so we have to process the bazel env before acting on the config.
if ( enableBazelEnvSupport() ) {
readBazelEnvVars();
}
@@ -145,7 +142,7 @@ namespace Catch {
// We do the default-output check separately, while always
// using the default output below to make the code simpler
// and avoid superfluous copies.
if ( reporterSpec.outputFile().none() ) {
if ( !reporterSpec.outputFile() ) {
CATCH_ENFORCE( !defaultOutputUsed,
"Internal error: cannot use default output for "
"multiple reporters" );
@@ -156,7 +153,7 @@ namespace Catch {
reporterSpec.name(),
reporterSpec.outputFile() ? *reporterSpec.outputFile()
: data.defaultOutputFilename,
reporterSpec.colourMode().valueOr( data.defaultColourMode ),
reporterSpec.colourMode().value_or( data.defaultColourMode ),
reporterSpec.customOptions() } );
}
}
@@ -170,8 +167,7 @@ namespace Catch {
bool Config::listListeners() const { return m_data.listListeners; }
std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
std::vector<PathFilter> const& Config::getPathFilters() const { return m_data.pathFilters; }
bool Config::useNewFilterBehaviour() const { return m_data.useNewPathFilteringBehaviour; }
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
std::vector<ReporterSpec> const& Config::getReporterSpecs() const {
return m_data.reporterSpecifications;
@@ -187,11 +183,9 @@ namespace Catch {
bool Config::showHelp() const { return m_data.showHelp; }
std::string const& Config::getExitGuardFilePath() const { return m_data.prematureExitGuardFilePath; }
// IConfig interface
bool Config::allowThrows() const { return !m_data.noThrow; }
StringRef Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
std::string_view Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
bool Config::warnAboutMissingAssertions() const {
return !!( m_data.warnings & WarnAbout::NoAssertions );
@@ -199,9 +193,6 @@ namespace Catch {
bool Config::warnAboutUnmatchedTestSpecs() const {
return !!( m_data.warnings & WarnAbout::UnmatchedTestSpec );
}
bool Config::warnAboutInfiniteGenerators() const {
return !!( m_data.warnings & WarnAbout::InfiniteGenerator );
}
bool Config::zeroTestsCountAsSuccess() const { return m_data.allowZeroTests; }
ShowDurations Config::showDurations() const { return m_data.showDurations; }
double Config::minDuration() const { return m_data.minDuration; }
@@ -253,26 +244,6 @@ namespace Catch {
m_data.shardCount = bazelShardOptions->shardCount;
}
}
const auto bazelExitGuardFile = Detail::getEnv( "TEST_PREMATURE_EXIT_FILE" );
if (bazelExitGuardFile) {
m_data.prematureExitGuardFilePath = bazelExitGuardFile;
}
const auto bazelRandomSeed = Detail::getEnv( "TEST_RANDOM_SEED" );
if ( bazelRandomSeed ) {
auto parsedSeed = parseUInt( bazelRandomSeed, 0 );
if ( !parsedSeed ) {
// Currently we handle issues with parsing other Bazel Env
// options by warning and ignoring the issue. So we do the
// same for random seed option.
Catch::cerr()
<< "Warning: could not parse 'TEST_RANDOM_SEED' ('"
<< bazelRandomSeed << "') as proper seed.\n";
} else {
m_data.rngSeed = *parsedSeed;
}
}
}
} // end namespace Catch
+3 -13
View File
@@ -11,9 +11,6 @@
#include <catch2/catch_test_spec.hpp>
#include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_optional.hpp>
#include <catch2/internal/catch_path_filter.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_random_seed_generation.hpp>
#include <catch2/internal/catch_reporter_spec_parser.hpp>
@@ -87,10 +84,7 @@ namespace Catch {
std::vector<ReporterSpec> reporterSpecifications;
std::vector<std::string> testsOrTags;
std::vector<PathFilter> pathFilters;
bool useNewPathFilteringBehaviour = false;
std::string prematureExitGuardFilePath;
std::vector<std::string> sectionsToRun;
};
@@ -111,23 +105,19 @@ namespace Catch {
getProcessedReporterSpecs() const;
std::vector<std::string> const& getTestsOrTags() const override;
std::vector<PathFilter> const& getPathFilters() const override;
bool useNewFilterBehaviour() const override;
std::vector<std::string> const& getSectionsToRun() const override;
TestSpec const& testSpec() const override;
bool hasTestFilters() const override;
bool showHelp() const;
std::string const& getExitGuardFilePath() const;
// IConfig interface
bool allowThrows() const override;
StringRef name() const override;
std::string_view name() const override;
bool includeSuccessfulResults() const override;
bool warnAboutMissingAssertions() const override;
bool warnAboutUnmatchedTestSpecs() const override;
bool warnAboutInfiniteGenerators() const override;
bool zeroTestsCountAsSuccess() const override;
ShowDurations showDurations() const override;
double minDuration() const override;
+11 -18
View File
@@ -5,8 +5,8 @@
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_message.hpp>
#include <catch2/interfaces/catch_interfaces_capture.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
@@ -22,7 +22,7 @@ namespace Catch {
m_messageId( builder.m_info.sequence ) {
MessageInfo info( CATCH_MOVE( builder.m_info ) );
info.message = builder.m_stream.str();
Detail::pushScopedMessage( CATCH_MOVE( info ) );
getResultCapture().pushScopedMessage( CATCH_MOVE(info) );
}
ScopedMessage::ScopedMessage( ScopedMessage&& old ) noexcept:
@@ -31,16 +31,15 @@ namespace Catch {
}
ScopedMessage::~ScopedMessage() {
if ( !m_moved ) { Detail::popScopedMessage( m_messageId ); }
if ( !m_moved ) { getResultCapture().popScopedMessage( m_messageId ); }
}
Capturer::Capturer( StringRef macroName,
Capturer::Capturer( std::string_view macroName,
SourceLineInfo const& lineInfo,
ResultWas::OfType resultType,
StringRef names,
bool isScoped):
m_isScoped(isScoped) {
std::string_view names ):
m_resultCapture( getResultCapture() ) {
auto trimmed = [&] (size_t start, size_t end) {
while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {
++start;
@@ -87,7 +86,7 @@ namespace Catch {
if (start != pos && openings.empty()) {
m_messages.emplace_back(macroName, lineInfo, resultType);
m_messages.back().message += trimmed(start, pos);
m_messages.back().message += " := "_sr;
m_messages.back().message += " := ";
start = pos;
}
break;
@@ -97,25 +96,19 @@ namespace Catch {
assert(openings.empty() && "Mismatched openings");
m_messages.emplace_back(macroName, lineInfo, resultType);
m_messages.back().message += trimmed(start, names.size() - 1);
m_messages.back().message += " := "_sr;
m_messages.back().message += " := ";
}
Capturer::~Capturer() {
assert( m_captured == m_messages.size() );
if ( m_isScoped ) {
for ( auto const& message : m_messages ) {
Detail::popScopedMessage( message.sequence );
}
for (auto const& message : m_messages) {
m_resultCapture.popScopedMessage( message.sequence );
}
}
void Capturer::captureValue( size_t index, std::string const& value ) {
assert( index < m_messages.size() );
m_messages[index].message += value;
if ( m_isScoped ) {
Detail::pushScopedMessage( CATCH_MOVE( m_messages[index] ) );
} else {
Detail::addUnscopedMessage( CATCH_MOVE( m_messages[index] ) );
}
m_resultCapture.pushScopedMessage( CATCH_MOVE(m_messages[index]) );
m_captured++;
}
+23 -40
View File
@@ -13,28 +13,16 @@
#include <catch2/internal/catch_reusable_string_stream.hpp>
#include <catch2/internal/catch_stream_end_stop.hpp>
#include <catch2/internal/catch_message_info.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/catch_tostring.hpp>
#include <catch2/interfaces/catch_interfaces_capture.hpp>
#include <string>
#include <vector>
namespace Catch {
struct MessageInfo;
struct MessageBuilder;
namespace Detail {
// The message state affecting functions have to be defined in
// the TU where the thread-local message holders are defined.
// Currently this is catch_run_context.cpp
void pushScopedMessage( MessageInfo&& message );
void popScopedMessage( unsigned int messageId );
void addUnscopedMessage( MessageInfo&& message );
void emplaceUnscopedMessage( MessageBuilder&& builder );
} // namespace Detail
struct SourceLineInfo;
class IResultCapture;
struct MessageStream {
@@ -48,7 +36,7 @@ namespace Catch {
};
struct MessageBuilder : MessageStream {
MessageBuilder( StringRef macroName,
MessageBuilder( std::string_view macroName,
SourceLineInfo const& lineInfo,
ResultWas::OfType type ):
m_info(macroName, lineInfo, type) {}
@@ -75,10 +63,10 @@ namespace Catch {
class Capturer {
std::vector<MessageInfo> m_messages;
IResultCapture& m_resultCapture;
size_t m_captured = 0;
bool m_isScoped = false;
public:
Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names, bool isScoped );
Capturer( std::string_view macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, std::string_view names );
Capturer(Capturer const&) = delete;
Capturer& operator=(Capturer const&) = delete;
@@ -104,27 +92,26 @@ namespace Catch {
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, std::string_view(), resultDisposition ); \
catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
catchAssertionHandler.complete(); \
} while( false )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_CAPTURE( varName, macroName, scopedCapture, ... ) \
Catch::Capturer varName( macroName##_catch_sr, \
CATCH_INTERNAL_LINEINFO, \
Catch::ResultWas::Info, \
#__VA_ARGS__##_catch_sr, \
scopedCapture ); \
#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
Catch::Capturer varName( macroName, \
CATCH_INTERNAL_LINEINFO, \
Catch::ResultWas::Info, \
#__VA_ARGS__ ); \
varName.captureValues( 0, __VA_ARGS__ )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_INFO( macroName, log ) \
const Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
const Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
Catch::Detail::emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
#if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
@@ -132,32 +119,28 @@ namespace Catch {
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
#define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg )
#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", true, __VA_ARGS__ )
#define CATCH_UNSCOPED_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_UNSCOPED_CAPTURE", false, __VA_ARGS__ )
#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__ )
#elif defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE)
#define CATCH_INFO( msg ) (void)(0)
#define CATCH_UNSCOPED_INFO( msg ) (void)(0)
#define CATCH_WARN( msg ) (void)(0)
#define CATCH_CAPTURE( ... ) (void)(0)
#define CATCH_UNSCOPED_CAPTURE( ... ) (void)(0)
#define CATCH_INFO( msg ) (void)(0)
#define CATCH_UNSCOPED_INFO( msg ) (void)(0)
#define CATCH_WARN( msg ) (void)(0)
#define CATCH_CAPTURE( ... ) (void)(0)
#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", true, __VA_ARGS__ )
#define UNSCOPED_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "UNSCOPED_CAPTURE", false, __VA_ARGS__ )
#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__ )
#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE)
#define INFO( msg ) (void)(0)
#define UNSCOPED_INFO( msg ) (void)(0)
#define WARN( msg ) (void)(0)
#define CAPTURE( ... ) (void)(0)
#define UNSCOPED_CAPTURE( ... ) (void)(0)
#define INFO( msg ) (void)(0)
#define UNSCOPED_INFO( msg ) (void)(0)
#define WARN( msg ) (void)(0)
#define CAPTURE( ... ) (void)(0)
#endif // end of user facing macro declarations
+6
View File
@@ -15,6 +15,7 @@
#include <catch2/internal/catch_tag_alias_registry.hpp>
#include <catch2/internal/catch_startup_exception_registry.hpp>
#include <catch2/internal/catch_singletons.hpp>
#include <catch2/internal/catch_enum_values_registry.hpp>
#include <catch2/catch_test_case_info.hpp>
#include <catch2/internal/catch_noncopyable.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_factory.hpp>
@@ -71,6 +72,9 @@ namespace Catch {
CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
#endif
}
IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {
return m_enumValuesRegistry;
}
private:
TestRegistry m_testCaseRegistry;
@@ -78,6 +82,7 @@ namespace Catch {
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
TagAliasRegistry m_tagAliasRegistry;
StartupExceptionRegistry m_exceptionRegistry;
Detail::EnumValuesRegistry m_enumValuesRegistry;
};
}
@@ -91,6 +96,7 @@ namespace Catch {
}
void cleanUp() {
cleanupSingletons();
cleanUpContext();
}
std::string translateActiveException() {
return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
-1
View File
@@ -10,7 +10,6 @@
#include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/catch_totals.hpp>
#include <string>
+1 -56
View File
@@ -21,14 +21,11 @@
#include <catch2/reporters/catch_reporter_multi.hpp>
#include <catch2/internal/catch_reporter_registry.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_factory.hpp>
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_stdstreams.hpp>
#include <catch2/internal/catch_istream.hpp>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <exception>
#include <iomanip>
#include <set>
@@ -143,50 +140,6 @@ namespace Catch {
}
}
// Creates empty file at path. The path must be writable, we do not
// try to create directories in path because that's hard in C++14.
void setUpGuardFile( std::string const& guardFilePath ) {
if ( !guardFilePath.empty() ) {
#if defined( _MSC_VER )
std::FILE* file = nullptr;
if ( fopen_s( &file, guardFilePath.c_str(), "w" ) ) {
char msgBuffer[100];
const auto err = errno;
std::string errMsg;
if ( !strerror_s( msgBuffer, err ) ) {
errMsg = msgBuffer;
} else {
errMsg = "Could not translate errno to a string";
}
#else
std::FILE* file = std::fopen( guardFilePath.c_str(), "w" );
if ( !file ) {
const auto err = errno;
const char* errMsg = std::strerror( err );
#endif
CATCH_RUNTIME_ERROR( "Could not open the exit guard file '"
<< guardFilePath << "' because '"
<< errMsg << "' (" << err << ')' );
}
const int ret = std::fclose( file );
CATCH_ENFORCE(
ret == 0,
"Error when closing the exit guard file: " << ret );
}
}
// Removes file at path. Assuming we created it in setUpGuardFile.
void tearDownGuardFile( std::string const& guardFilePath ) {
if ( !guardFilePath.empty() ) {
const int ret = std::remove( guardFilePath.c_str() );
CATCH_ENFORCE(
ret == 0,
"Error when removing the exit guard file: " << ret );
}
}
} // anon namespace
Session::Session() {
@@ -305,7 +258,6 @@ namespace Catch {
static_cast<void>(std::getchar());
}
int exitCode = runInternal();
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << '\n' << std::flush;
static_cast<void>(std::getchar());
@@ -346,10 +298,6 @@ namespace Catch {
CATCH_TRY {
config(); // Force config to be constructed
// We need to retrieve potential Bazel config with the full Config
// constructor, so we have to create the guard file after it is created.
setUpGuardFile( m_config->getExitGuardFilePath() );
seedRng( *m_config );
if (m_configData.filenamesAsTags) {
@@ -379,12 +327,9 @@ namespace Catch {
TestGroup tests { CATCH_MOVE(reporter), m_config.get() };
auto const totals = tests.execute();
// If we got here, running the tests finished normally-enough.
// They might've failed, but that would've been reported elsewhere.
tearDownGuardFile( m_config->getExitGuardFilePath() );
if ( tests.hadUnmatchedTestSpecs()
&& m_config->warnAboutUnmatchedTestSpecs() ) {
// UnmatchedTestSpecExitCode
return UnmatchedTestSpecExitCode;
}
-1
View File
@@ -16,7 +16,6 @@
namespace Catch {
// TODO: Use C++17 `inline` variables
constexpr int UnspecifiedErrorExitCode = 1;
constexpr int NoTestsRunExitCode = 2;
constexpr int UnmatchedTestSpecExitCode = 3;
+19 -18
View File
@@ -14,6 +14,7 @@
#include <cassert>
#include <cctype>
#include <algorithm>
#include <string_view>
namespace Catch {
@@ -47,28 +48,28 @@ namespace Catch {
return tcp != TestCaseProperties::None;
}
TestCaseProperties parseSpecialTag( StringRef tag ) {
TestCaseProperties parseSpecialTag( std::string_view tag ) {
if( !tag.empty() && tag[0] == '.' )
return TestCaseProperties::IsHidden;
else if( tag == "!throws"_sr )
else if( tag == "!throws" )
return TestCaseProperties::Throws;
else if( tag == "!shouldfail"_sr )
else if( tag == "!shouldfail" )
return TestCaseProperties::ShouldFail;
else if( tag == "!mayfail"_sr )
else if( tag == "!mayfail" )
return TestCaseProperties::MayFail;
else if( tag == "!nonportable"_sr )
else if( tag == "!nonportable" )
return TestCaseProperties::NonPortable;
else if( tag == "!benchmark"_sr )
else if( tag == "!benchmark" )
return TestCaseProperties::Benchmark | TestCaseProperties::IsHidden;
else
return TestCaseProperties::None;
}
bool isReservedTag( StringRef tag ) {
bool isReservedTag( std::string_view tag ) {
return parseSpecialTag( tag ) == TestCaseProperties::None
&& tag.size() > 0
&& !std::isalnum( static_cast<unsigned char>(tag[0]) );
}
void enforceNotReservedTag( StringRef tag, SourceLineInfo const& _lineInfo ) {
void enforceNotReservedTag( std::string_view tag, SourceLineInfo const& _lineInfo ) {
CATCH_ENFORCE( !isReservedTag(tag),
"Tag name: [" << tag << "] is not allowed.\n"
<< "Tag names starting with non alphanumeric characters are reserved\n"
@@ -80,13 +81,13 @@ namespace Catch {
return "Anonymous test case " + std::to_string(++counter);
}
constexpr StringRef extractFilenamePart(StringRef filename) {
constexpr std::string_view extractFilenamePart(std::string_view filename) {
size_t lastDot = filename.size();
while (lastDot > 0 && filename[lastDot - 1] != '.') {
--lastDot;
}
// In theory we could have filename without any extension in it
if ( lastDot == 0 ) { return StringRef(); }
if ( lastDot == 0 ) { return std::string_view(); }
--lastDot;
size_t nameStart = lastDot;
@@ -98,7 +99,7 @@ namespace Catch {
}
// Returns the upper bound on size of extra tags ([#file]+[.])
constexpr size_t sizeOfExtraTags(StringRef filepath) {
constexpr size_t sizeOfExtraTags(std::string_view filepath) {
// [.] is 3, [#] is another 3
const size_t extras = 3 + 3;
return extractFilenamePart(filepath).size() + extras;
@@ -115,20 +116,20 @@ namespace Catch {
}
Detail::unique_ptr<TestCaseInfo>
makeTestCaseInfo(StringRef _className,
makeTestCaseInfo(std::string_view _className,
NameAndTags const& nameAndTags,
SourceLineInfo const& _lineInfo ) {
return Detail::make_unique<TestCaseInfo>(_className, nameAndTags, _lineInfo);
}
TestCaseInfo::TestCaseInfo(StringRef _className,
TestCaseInfo::TestCaseInfo(std::string_view _className,
NameAndTags const& _nameAndTags,
SourceLineInfo const& _lineInfo):
name( _nameAndTags.name.empty() ? makeDefaultName() : _nameAndTags.name ),
className( _className ),
lineInfo( _lineInfo )
{
StringRef originalTags = _nameAndTags.tags;
std::string_view originalTags = _nameAndTags.tags;
// We need to reserve enough space to store all of the tags
// (including optional hidden tag and filename tag)
auto requiredSize = originalTags.size() + sizeOfExtraTags(_lineInfo.file);
@@ -163,7 +164,7 @@ namespace Catch {
// We need to check the tag for special meanings, copy
// it over to backing storage and actually reference the
// backing storage in the saved tags
StringRef tagStr = originalTags.substr(tagStart+1, tagEnd - tagStart - 1);
std::string_view tagStr = originalTags.substr(tagStart+1, tagEnd - tagStart - 1);
CATCH_ENFORCE( !tagStr.empty(),
"Found an empty tag while registering test case '"
<< _nameAndTags.name << "' at "
@@ -190,7 +191,7 @@ namespace Catch {
// Add [.] if relevant
if (isHidden()) {
internalAppendTag("."_sr);
internalAppendTag(".");
}
// Sort and prepare tags
@@ -235,13 +236,13 @@ namespace Catch {
return ret;
}
void TestCaseInfo::internalAppendTag(StringRef tagStr) {
void TestCaseInfo::internalAppendTag(std::string_view tagStr) {
backingTags += '[';
const auto backingStart = backingTags.size();
backingTags += tagStr;
const auto backingEnd = backingTags.size();
backingTags += ']';
tags.emplace_back(StringRef(backingTags.c_str() + backingStart, backingEnd - backingStart));
tags.emplace_back(std::string_view(backingTags.c_str() + backingStart, backingEnd - backingStart));
}
bool operator<( TestCaseInfo const& lhs, TestCaseInfo const& rhs ) {
+7 -7
View File
@@ -11,12 +11,12 @@
#include <catch2/interfaces/catch_interfaces_test_invoker.hpp>
#include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_noncopyable.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
#ifdef __clang__
@@ -34,10 +34,10 @@ namespace Catch {
* as "cool-tag" internally.
*/
struct Tag {
constexpr Tag(StringRef original_):
constexpr Tag(std::string_view original_):
original(original_)
{}
StringRef original;
std::string_view original;
friend bool operator< ( Tag const& lhs, Tag const& rhs );
friend bool operator==( Tag const& lhs, Tag const& rhs );
@@ -67,7 +67,7 @@ namespace Catch {
*/
struct TestCaseInfo : Detail::NonCopyable {
TestCaseInfo(StringRef _className,
TestCaseInfo(std::string_view _className,
NameAndTags const& _nameAndTags,
SourceLineInfo const& _lineInfo);
@@ -87,12 +87,12 @@ namespace Catch {
std::string tagsAsString() const;
std::string name;
StringRef className;
std::string_view className;
private:
std::string backingTags;
// Internally we copy tags to the backing storage and then add
// refs to this storage to the tags vector.
void internalAppendTag(StringRef tagString);
void internalAppendTag(std::string_view tagString);
public:
std::vector<Tag> tags;
SourceLineInfo lineInfo;
@@ -130,7 +130,7 @@ namespace Catch {
};
Detail::unique_ptr<TestCaseInfo>
makeTestCaseInfo( StringRef className,
makeTestCaseInfo( std::string_view className,
NameAndTags const& nameAndTags,
SourceLineInfo const& lineInfo );
}
+3 -3
View File
@@ -8,13 +8,13 @@
#ifndef CATCH_TEST_RUN_INFO_HPP_INCLUDED
#define CATCH_TEST_RUN_INFO_HPP_INCLUDED
#include <catch2/internal/catch_stringref.hpp>
#include <string_view>
namespace Catch {
struct TestRunInfo {
constexpr TestRunInfo(StringRef _name) : name(_name) {}
StringRef name;
constexpr TestRunInfo(std::string_view _name) : name(_name) {}
std::string_view name;
};
} // end namespace Catch
+23 -59
View File
@@ -13,6 +13,7 @@
#include <catch2/internal/catch_polyfills.hpp>
#include <iomanip>
#include <cstddef>
namespace Catch {
@@ -57,75 +58,45 @@ namespace Detail {
}
} // end unnamed namespace
std::size_t catch_strnlen( const char* str, std::size_t n ) {
auto ret = std::char_traits<char>::find( str, n, '\0' );
if ( ret != nullptr ) { return static_cast<std::size_t>( ret - str ); }
return n;
}
std::string formatTimeT(std::time_t time) {
#ifdef _MSC_VER
std::tm timeInfo = {};
const auto err = gmtime_s( &timeInfo, &time );
if ( err ) {
return "gmtime from provided timepoint has failed. This "
"happens e.g. with pre-1970 dates using Microsoft libc";
}
#else
std::tm* timeInfo = std::gmtime( &time );
#endif
auto const timeStampSize = sizeof( "2017-01-16T17:06:45Z" );
char timeStamp[timeStampSize];
const char* const fmt = "%Y-%m-%dT%H:%M:%SZ";
#ifdef _MSC_VER
std::strftime( timeStamp, timeStampSize, fmt, &timeInfo );
#else
std::strftime( timeStamp, timeStampSize, fmt, timeInfo );
#endif
return std::string( timeStamp, timeStampSize - 1 );
}
std::string convertIntoString(StringRef string, bool escapeInvisibles) {
std::string convertIntoString(std::string_view string, bool escapeInvisibles) {
std::string ret;
// This is enough for the "don't escape invisibles" case, and a good
// lower bound on the "escape invisibles" case.
ret.reserve( string.size() + 2 );
ret.reserve(string.size() + 2);
if ( !escapeInvisibles ) {
if (!escapeInvisibles) {
ret += '"';
ret += string;
ret += '"';
return ret;
}
size_t last_start = 0;
auto write_to = [&]( size_t idx ) {
if ( last_start < idx ) {
ret += string.substr( last_start, idx - last_start );
}
last_start = idx + 1;
};
ret += '"';
for ( size_t i = 0; i < string.size(); ++i ) {
const char c = string[i];
if ( c == '\r' || c == '\n' || c == '\t' || c == '\f' ) {
write_to( i );
if ( c == '\r' ) { ret.append( "\\r" ); }
if ( c == '\n' ) { ret.append( "\\n" ); }
if ( c == '\t' ) { ret.append( "\\t" ); }
if ( c == '\f' ) { ret.append( "\\f" ); }
for (char c : string) {
switch (c) {
case '\r':
ret.append("\\r");
break;
case '\n':
ret.append("\\n");
break;
case '\t':
ret.append("\\t");
break;
case '\f':
ret.append("\\f");
break;
default:
ret.push_back(c);
break;
}
}
write_to( string.size() );
ret += '"';
return ret;
}
std::string convertIntoString(StringRef string) {
std::string convertIntoString(std::string_view string) {
return convertIntoString(string, getCurrentContext().getConfig()->showInvisibles());
}
@@ -165,11 +136,9 @@ std::string StringMaker<std::string>::convert(const std::string& str) {
return Detail::convertIntoString( str );
}
#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
std::string StringMaker<std::string_view>::convert(std::string_view str) {
return Detail::convertIntoString( StringRef( str.data(), str.size() ) );
return Detail::convertIntoString( std::string_view( str.data(), str.size() ) );
}
#endif
std::string StringMaker<char const*>::convert(char const* str) {
if (str) {
@@ -196,11 +165,9 @@ std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
return ::Catch::Detail::stringify(s);
}
# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) {
return StringMaker<std::wstring>::convert(std::wstring(str));
}
# endif
std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {
if (str) {
@@ -218,12 +185,9 @@ std::string StringMaker<wchar_t *>::convert(wchar_t * str) {
}
#endif
#if defined(CATCH_CONFIG_CPP17_BYTE)
#include <cstddef>
std::string StringMaker<std::byte>::convert(std::byte value) {
return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value));
}
#endif // defined(CATCH_CONFIG_CPP17_BYTE)
std::string StringMaker<int>::convert(int value) {
return ::Catch::Detail::stringify(static_cast<long long>(value));
+80 -65
View File
@@ -8,7 +8,7 @@
#ifndef CATCH_TOSTRING_HPP_INCLUDED
#define CATCH_TOSTRING_HPP_INCLUDED
#include <ctime>
#include <vector>
#include <cstddef>
#include <type_traits>
@@ -18,12 +18,9 @@
#include <catch2/internal/catch_config_wchar.hpp>
#include <catch2/internal/catch_reusable_string_stream.hpp>
#include <catch2/internal/catch_void_type.hpp>
#include <catch2/internal/catch_enum_info.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/interfaces/catch_interfaces_enum_values_registry.hpp>
#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
#include <string_view>
#endif
#ifdef _MSC_VER
#pragma warning(push)
@@ -41,18 +38,22 @@ namespace Catch {
namespace Detail {
std::size_t catch_strnlen(const char *str, std::size_t n);
inline std::size_t catch_strnlen(const char *str, std::size_t n) {
auto ret = std::char_traits<char>::find(str, n, '\0');
if (ret != nullptr) {
return static_cast<std::size_t>(ret - str);
}
return n;
}
std::string formatTimeT( std::time_t time );
constexpr StringRef unprintableString = "{?}"_sr;
constexpr std::string_view unprintableString = "{?}";
//! Encases `string in quotes, and optionally escapes invisibles
std::string convertIntoString( StringRef string, bool escapeInvisibles );
std::string convertIntoString( std::string_view string, bool escapeInvisibles );
//! Encases `string` in quotes, and escapes invisibles if user requested
//! it via CLI
std::string convertIntoString( StringRef string );
std::string convertIntoString( std::string_view string );
std::string rawMemoryToString( const void *object, std::size_t size );
@@ -75,13 +76,13 @@ namespace Catch {
template<typename T>
std::enable_if_t<
!std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,
!std::is_enum_v<T> && !std::is_base_of_v<std::exception, T>,
std::string> convertUnstreamable( T const& ) {
return std::string(Detail::unprintableString);
}
template<typename T>
std::enable_if_t<
!std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
!std::is_enum_v<T> && std::is_base_of_v<std::exception, T>,
std::string> convertUnstreamable(T const& ex) {
return ex.what();
}
@@ -89,7 +90,7 @@ namespace Catch {
template<typename T>
std::enable_if_t<
std::is_enum<T>::value,
std::is_enum_v<T>,
std::string> convertUnstreamable( T const& value ) {
return convertUnknownEnumToString( value );
}
@@ -170,12 +171,10 @@ namespace Catch {
static std::string convert(const std::string& str);
};
#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
template<>
struct StringMaker<std::string_view> {
static std::string convert(std::string_view str);
};
#endif
template<>
struct StringMaker<char const *> {
@@ -192,12 +191,10 @@ namespace Catch {
static std::string convert(const std::wstring& wstr);
};
# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
template<>
struct StringMaker<std::wstring_view> {
static std::string convert(std::wstring_view str);
};
# endif
template<>
struct StringMaker<wchar_t const *> {
@@ -213,7 +210,7 @@ namespace Catch {
struct StringMaker<char[SZ]> {
static std::string convert(char const* str) {
return Detail::convertIntoString(
StringRef( str, Detail::catch_strnlen( str, SZ ) ) );
std::string_view( str, Detail::catch_strnlen( str, SZ ) ) );
}
};
template<size_t SZ>
@@ -221,7 +218,7 @@ namespace Catch {
static std::string convert(signed char const* str) {
auto reinterpreted = reinterpret_cast<char const*>(str);
return Detail::convertIntoString(
StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
std::string_view(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
}
};
template<size_t SZ>
@@ -229,16 +226,14 @@ namespace Catch {
static std::string convert(unsigned char const* str) {
auto reinterpreted = reinterpret_cast<char const*>(str);
return Detail::convertIntoString(
StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
std::string_view(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
}
};
#if defined(CATCH_CONFIG_CPP17_BYTE)
template<>
struct StringMaker<std::byte> {
static std::string convert(std::byte value);
};
#endif // defined(CATCH_CONFIG_CPP17_BYTE)
template<>
struct StringMaker<int> {
static std::string convert(int value);
@@ -384,10 +379,7 @@ namespace Catch {
}
#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
#if defined( CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER ) && \
defined( CATCH_CONFIG_CPP17_OPTIONAL ) && \
/* P3168 turned optional into a range, making this ambigous with the range support */ \
!defined( __cpp_lib_optional_range_support )
#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER)
#include <optional>
namespace Catch {
template<typename T>
@@ -411,41 +403,47 @@ namespace Catch {
// Separate std::tuple specialization
#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
# include <tuple>
# include <utility>
#include <tuple>
namespace Catch {
namespace Detail {
template <typename Tuple, std::size_t... Is>
void PrintTuple( const Tuple& tuple,
std::ostream& os,
std::index_sequence<Is...> ) {
// 1 + Account for when the tuple is empty
char a[1 + sizeof...( Is )] = {
( ( os << ( Is ? ", " : " " )
<< ::Catch::Detail::stringify( std::get<Is>( tuple ) ) ),
'\0' )... };
(void)a;
}
template<
typename Tuple,
std::size_t N = 0,
bool = (N < std::tuple_size_v<Tuple>)
>
struct TupleElementPrinter {
static void print(const Tuple& tuple, std::ostream& os) {
os << (N ? ", " : " ")
<< ::Catch::Detail::stringify(std::get<N>(tuple));
TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
}
};
} // namespace Detail
template<
typename Tuple,
std::size_t N
>
struct TupleElementPrinter<Tuple, N, false> {
static void print(const Tuple&, std::ostream&) {}
};
template <typename... Types>
}
template<typename ...Types>
struct StringMaker<std::tuple<Types...>> {
static std::string convert( const std::tuple<Types...>& tuple ) {
static std::string convert(const std::tuple<Types...>& tuple) {
ReusableStringStream rss;
rss << '{';
Detail::PrintTuple(
tuple,
rss.get(),
std::make_index_sequence<sizeof...( Types )>{} );
Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
rss << " }";
return rss.str();
}
};
} // namespace Catch
}
#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER)
#include <variant>
namespace Catch {
template<>
@@ -629,26 +627,43 @@ struct ratio_string<std::milli> {
const auto systemish = std::chrono::time_point_cast<
std::chrono::system_clock::duration>( time_point );
const auto as_time_t = std::chrono::system_clock::to_time_t( systemish );
return ::Catch::Detail::formatTimeT( as_time_t );
#ifdef _MSC_VER
std::tm timeInfo = {};
const auto err = gmtime_s( &timeInfo, &as_time_t );
if ( err ) {
return "gmtime from provided timepoint has failed. This "
"happens e.g. with pre-1970 dates using Microsoft libc";
}
#else
std::tm* timeInfo = std::gmtime( &as_time_t );
#endif
auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
char timeStamp[timeStampSize];
const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
#ifdef _MSC_VER
std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
#else
std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
#endif
return std::string(timeStamp, timeStampSize - 1);
}
};
}
#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
namespace Catch { \
template <> \
struct StringMaker<enumName> { \
static std::string convert( enumName value ) { \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
static const auto enumInfo = ::Catch::Detail::makeEnumInfo( \
#enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
return static_cast<std::string>( \
enumInfo.lookup( static_cast<int64_t>( value ) ) ); \
} \
}; \
}
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
namespace Catch { \
template<> struct StringMaker<enumName> { \
static std::string convert( enumName value ) { \
static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \
} \
}; \
}
#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
+1 -1
View File
@@ -22,7 +22,7 @@ namespace Catch {
class ExceptionTranslatorRegistrar {
template<typename T>
class ExceptionTranslator final : public IExceptionTranslator {
class ExceptionTranslator : public IExceptionTranslator {
public:
constexpr ExceptionTranslator( std::string(*translateFunction)( T const& ) )
+5 -55
View File
@@ -60,56 +60,6 @@
#cmakedefine CATCH_CONFIG_CPP17_BYTE
#cmakedefine CATCH_CONFIG_NO_CPP17_BYTE
#if defined( CATCH_CONFIG_CPP17_BYTE ) && \
defined( CATCH_CONFIG_NO_CPP17_BYTE )
# error Cannot force CPP17_BYTE to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_CPP17_OPTIONAL
#cmakedefine CATCH_CONFIG_NO_CPP17_OPTIONAL
#if defined( CATCH_CONFIG_CPP17_OPTIONAL ) && \
defined( CATCH_CONFIG_NO_CPP17_OPTIONAL )
# error Cannot force CPP17_OPTIONAL to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_CPP17_STRING_VIEW
#cmakedefine CATCH_CONFIG_NO_CPP17_STRING_VIEW
#if defined( CATCH_CONFIG_CPP17_STRING_VIEW ) && \
defined( CATCH_CONFIG_NO_CPP17_STRING_VIEW )
# error Cannot force CPP17_STRING_VIEW to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#cmakedefine CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS
#if defined( CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS ) && \
defined( CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS )
# error Cannot force CPP17_UNCAUGHT_EXCEPTIONS to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_CPP17_VARIANT
#cmakedefine CATCH_CONFIG_NO_CPP17_VARIANT
#if defined( CATCH_CONFIG_CPP17_VARIANT ) && \
defined( CATCH_CONFIG_NO_CPP17_VARIANT )
# error Cannot force CPP17_VARIANT to both ON and OFF
#endif
#cmakedefine CATCH_CONFIG_GLOBAL_NEXTAFTER
#cmakedefine CATCH_CONFIG_NO_GLOBAL_NEXTAFTER
@@ -196,12 +146,12 @@
#endif
#cmakedefine CATCH_CONFIG_THREAD_SAFE_ASSERTIONS
#cmakedefine CATCH_CONFIG_NO_THREAD_SAFE_ASSERTIONS
#cmakedefine CATCH_CONFIG_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS
#cmakedefine CATCH_CONFIG_NO_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS
#if defined( CATCH_CONFIG_THREAD_SAFE_ASSERTIONS ) && \
defined( CATCH_CONFIG_NO_THREAD_SAFE_ASSERTIONS )
# error Cannot force THREAD_SAFE_ASSERTIONS to both ON and OFF
#if defined( CATCH_CONFIG_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS ) && \
defined( CATCH_CONFIG_NO_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS )
# error Cannot force EXPERIMENTAL_THREAD_SAFE_ASSERTIONS to both ON and OFF
#endif
+1 -1
View File
@@ -36,7 +36,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 3, 15, 0, "", 0 );
static Version version( 3, 10, 0, "", 0 );
return version;
}
+1 -1
View File
@@ -9,7 +9,7 @@
#define CATCH_VERSION_MACROS_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 3
#define CATCH_VERSION_MINOR 15
#define CATCH_VERSION_MINOR 10
#define CATCH_VERSION_PATCH 0
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
+12 -2
View File
@@ -7,6 +7,8 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/generators/catch_generators.hpp>
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/generators/catch_generator_exception.hpp>
#include <catch2/interfaces/catch_interfaces_capture.hpp>
namespace Catch {
@@ -15,13 +17,21 @@ namespace Catch {
namespace Generators {
namespace Detail {
[[noreturn]]
void throw_generator_exception(char const* msg) {
Catch::throw_exception(GeneratorException{ msg });
}
} // end namespace Detail
GeneratorUntypedBase::~GeneratorUntypedBase() = default;
IGeneratorTracker* acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo ) {
IGeneratorTracker* acquireGeneratorTracker(std::string_view generatorName, SourceLineInfo const& lineInfo ) {
return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo );
}
IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
IGeneratorTracker* createGeneratorTracker( std::string_view generatorName,
SourceLineInfo lineInfo,
GeneratorBasePtr&& generator ) {
return getResultCapture().createGeneratorTracker(
+14 -32
View File
@@ -9,10 +9,8 @@
#define CATCH_GENERATORS_HPP_INCLUDED
#include <catch2/catch_tostring.hpp>
#include <catch2/generators/catch_generators_throw.hpp>
#include <catch2/interfaces/catch_interfaces_generatortracker.hpp>
#include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_unique_name.hpp>
@@ -23,6 +21,14 @@ namespace Catch {
namespace Generators {
namespace Detail {
//! Throws GeneratorException with the provided message
[[noreturn]]
void throw_generator_exception(char const * msg);
} // end namespace detail
template<typename T>
class IGenerator : public GeneratorUntypedBase {
std::string stringifyImpl() const override {
@@ -57,9 +63,6 @@ namespace Generators {
bool next() {
return m_generator->countedNext();
}
bool isFinite() const { return m_generator->isFinite(); }
void skipToNthElement( size_t n ) { m_generator->skipToNthElement(n); }
};
@@ -80,26 +83,15 @@ namespace Generators {
bool next() override {
return false;
}
bool isFinite() const override { return true; }
};
template<typename T>
class FixedValuesGenerator final : public IGenerator<T> {
static_assert(!std::is_same<T, bool>::value,
static_assert(!std::is_same_v<T, bool>,
"FixedValuesGenerator does not support bools because of std::vector<bool>"
"specialization, use SingleValue Generator instead.");
std::vector<T> m_values;
size_t m_idx = 0;
void skipToNthElementImpl( std::size_t n ) override {
if ( n >= m_values.size() ) {
Detail::throw_generator_exception(
"Coud not jump to Nth element: not enough elements" );
}
m_idx = n;
}
public:
FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
@@ -110,8 +102,6 @@ namespace Generators {
++m_idx;
return m_idx < m_values.size();
}
bool isFinite() const override { return true; }
};
template <typename T, typename DecayedT = std::decay_t<T>>
@@ -140,7 +130,7 @@ namespace Generators {
m_generators.emplace_back( value( CATCH_MOVE( val ) ) );
}
template <typename U>
std::enable_if_t<!std::is_same<std::decay_t<U>, T>::value>
std::enable_if_t<!std::is_same_v<std::decay_t<U>, T>>
add_generator( U&& val ) {
add_generator( T( CATCH_FORWARD( val ) ) );
}
@@ -176,14 +166,6 @@ namespace Generators {
}
return m_current < m_generators.size();
}
bool isFinite() const override {
for (auto const& gen : m_generators) {
if (!gen.isFinite()) { return false;
}
}
return true;
}
};
@@ -214,14 +196,14 @@ namespace Generators {
return makeGenerators( value( T( CATCH_FORWARD( val ) ) ), CATCH_FORWARD( moreGenerators )... );
}
IGeneratorTracker* acquireGeneratorTracker( StringRef generatorName,
IGeneratorTracker* acquireGeneratorTracker( std::string_view generatorName,
SourceLineInfo const& lineInfo );
IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
IGeneratorTracker* createGeneratorTracker( std::string_view generatorName,
SourceLineInfo lineInfo,
GeneratorBasePtr&& generator );
template<typename L>
auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> typename decltype(generatorExpression())::type {
auto generate( std::string_view generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> typename decltype(generatorExpression())::type {
using UnderlyingType = typename decltype(generatorExpression())::type;
IGeneratorTracker* tracker = acquireGeneratorTracker( generatorName, lineInfo );
@@ -242,7 +224,7 @@ namespace Generators {
} // namespace Generators
} // namespace Catch
#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__##_catch_sr
#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__
#define CATCH_INTERNAL_GENERATOR_STRINGIZE(...) CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL(__VA_ARGS__)
#define GENERATE( ... ) \
@@ -11,7 +11,6 @@
#include <catch2/generators/catch_generators.hpp>
#include <catch2/internal/catch_meta.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_optional.hpp>
#include <cassert>
@@ -23,17 +22,6 @@ namespace Generators {
GeneratorWrapper<T> m_generator;
size_t m_returned = 0;
size_t m_target;
void skipToNthElementImpl( std::size_t n ) override {
if ( n >= m_target ) {
Detail::throw_generator_exception(
"Coud not jump to Nth element: not enough elements" );
}
m_generator.skipToNthElement( n );
m_returned = n;
}
public:
TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
m_generator(CATCH_MOVE(generator)),
@@ -58,8 +46,6 @@ namespace Generators {
}
return success;
}
bool isFinite() const override { return true; }
};
template <typename T>
@@ -72,7 +58,7 @@ namespace Generators {
class FilterGenerator final : public IGenerator<T> {
GeneratorWrapper<T> m_generator;
Predicate m_predicate;
static_assert(!std::is_reference<Predicate>::value, "This would most likely result in a dangling reference");
static_assert(!std::is_reference_v<Predicate>, "This would most likely result in a dangling reference");
public:
template <typename P>
FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
@@ -101,8 +87,6 @@ namespace Generators {
while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
return success;
}
bool isFinite() const override { return m_generator.isFinite(); }
};
@@ -113,7 +97,7 @@ namespace Generators {
template <typename T>
class RepeatGenerator final : public IGenerator<T> {
static_assert(!std::is_same<T, bool>::value,
static_assert(!std::is_same_v<T, bool>,
"RepeatGenerator currently does not support bools"
"because of std::vector<bool> specialization");
GeneratorWrapper<T> m_generator;
@@ -127,9 +111,6 @@ namespace Generators {
m_target_repeats(repeats)
{
assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
if (!m_generator.isFinite()) {
Detail::throw_generator_exception( "Cannot repeat infinite generator" );
}
}
T const& get() const override {
@@ -163,8 +144,6 @@ namespace Generators {
}
return m_current_repeat < m_target_repeats;
}
bool isFinite() const override { return m_generator.isFinite(); }
};
template <typename T>
@@ -178,30 +157,25 @@ namespace Generators {
GeneratorWrapper<U> m_generator;
Func m_function;
// To avoid returning dangling reference, we have to save the values
mutable Optional<T> m_cache;
void skipToNthElementImpl( std::size_t n ) override {
m_generator.skipToNthElement( n );
m_cache.reset();
}
T m_cache;
public:
template <typename F2 = Func>
MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
m_generator(CATCH_MOVE(generator)),
m_function(CATCH_FORWARD(function))
m_function(CATCH_FORWARD(function)),
m_cache(m_function(m_generator.get()))
{}
T const& get() const override {
if ( !m_cache ) { m_cache = m_function( m_generator.get() ); }
return *m_cache;
return m_cache;
}
bool next() override {
m_cache.reset();
return m_generator.next();
const auto success = m_generator.next();
if (success) {
m_cache = m_function(m_generator.get());
}
return success;
}
bool isFinite() const override { return m_generator.isFinite(); }
};
template <typename Func, typename U, typename T = FunctionReturnType<Func, U>>
@@ -223,6 +197,7 @@ namespace Generators {
std::vector<T> m_chunk;
size_t m_chunk_size;
GeneratorWrapper<T> m_generator;
bool m_used_up = false;
public:
ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :
m_chunk_size(size), m_generator(CATCH_MOVE(generator))
@@ -251,8 +226,6 @@ namespace Generators {
}
return true;
}
bool isFinite() const override { return m_generator.isFinite(); }
};
template <typename T>
@@ -262,56 +235,6 @@ namespace Generators {
);
}
template <typename T>
class ConcatGenerator final : public IGenerator<T> {
std::vector<GeneratorWrapper<T>> m_generators;
size_t m_current_generator = 0;
void InsertGenerators( GeneratorWrapper<T>&& gen ) {
m_generators.push_back( CATCH_MOVE( gen ) );
}
template <typename... Generators>
void InsertGenerators( GeneratorWrapper<T>&& gen, Generators&&... gens ) {
m_generators.push_back( CATCH_MOVE( gen ) );
InsertGenerators( CATCH_MOVE( gens )... );
}
public:
template <typename... Generators>
ConcatGenerator( Generators&&... generators ) {
InsertGenerators( CATCH_MOVE( generators )... );
}
T const& get() const override {
return m_generators[m_current_generator].get();
}
bool next() override {
const bool success = m_generators[m_current_generator].next();
if ( success ) { return true; }
// If current generator is used up, we have to move to the next one
++m_current_generator;
return m_current_generator < m_generators.size();
}
bool isFinite() const override {
for ( auto const& gen : m_generators ) {
if ( !gen.isFinite() ) { return false; }
}
return true;
}
};
template <typename T, typename... Generators>
GeneratorWrapper<T> cat( GeneratorWrapper<T>&& generator,
Generators&&... generators ) {
return GeneratorWrapper<T>(
Catch::Detail::make_unique<ConcatGenerator<T>>(
CATCH_MOVE( generator ), CATCH_MOVE( generators )... ) );
}
} // namespace Generators
} // namespace Catch
@@ -26,6 +26,5 @@
#include <catch2/generators/catch_generators_adapters.hpp>
#include <catch2/generators/catch_generators_random.hpp>
#include <catch2/generators/catch_generators_range.hpp>
#include <catch2/generators/catch_generators_throw.hpp>
#endif // CATCH_GENERATORS_ALL_HPP_INCLUDED
@@ -37,10 +37,5 @@ namespace Catch {
m_current_number = m_pimpl->dist( m_pimpl->rng );
return true;
}
bool RandomFloatingGenerator<long double>::isFinite() const {
return false;
}
} // namespace Generators
} // namespace Catch
@@ -42,7 +42,6 @@ public:
m_current_number = m_dist(m_rng);
return true;
}
bool isFinite() const override { return false; }
};
template <>
@@ -60,7 +59,6 @@ public:
bool next() override;
~RandomFloatingGenerator() override; // = default
bool isFinite() const override;
};
template <typename Integer>
@@ -82,11 +80,10 @@ public:
m_current_number = m_dist(m_rng);
return true;
}
bool isFinite() const override { return false; }
};
template <typename T>
std::enable_if_t<std::is_integral<T>::value, GeneratorWrapper<T>>
std::enable_if_t<std::is_integral_v<T>, GeneratorWrapper<T>>
random(T a, T b) {
return GeneratorWrapper<T>(
Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b, Detail::getSeed())
@@ -94,7 +91,7 @@ random(T a, T b) {
}
template <typename T>
std::enable_if_t<std::is_floating_point<T>::value,
std::enable_if_t<std::is_floating_point_v<T>,
GeneratorWrapper<T>>
random(T a, T b) {
return GeneratorWrapper<T>(
@@ -48,26 +48,24 @@ public:
m_current += m_step;
return (m_positive) ? (m_current < m_end) : (m_current > m_end);
}
bool isFinite() const override { return true; }
};
template <typename T>
GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric");
static_assert(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>, "Type must be numeric");
return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end, step));
}
template <typename T>
GeneratorWrapper<T> range(T const& start, T const& end) {
static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
static_assert(std::is_integral_v<T> && !std::is_same_v<T, bool>, "Type must be an integer");
return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end));
}
template <typename T>
class IteratorGenerator final : public IGenerator<T> {
static_assert(!std::is_same<T, bool>::value,
static_assert(!std::is_same_v<T, bool>,
"IteratorGenerator currently does not support bools"
"because of std::vector<bool> specialization");
@@ -89,8 +87,6 @@ public:
++m_current;
return m_current != m_elems.size();
}
bool isFinite() const override { return true; }
};
template <typename InputIterator,
@@ -1,24 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/generators/catch_generator_exception.hpp>
#include <catch2/generators/catch_generators_throw.hpp>
#include <catch2/internal/catch_enforce.hpp>
namespace Catch {
namespace Generators {
namespace Detail {
[[noreturn]]
void throw_generator_exception( char const* msg ) {
Catch::throw_exception( GeneratorException{ msg } );
}
} // namespace Detail
} // namespace Generators
} // namespace Catch
@@ -1,23 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_GENERATORS_THROW_HPP_INCLUDED
#define CATCH_GENERATORS_THROW_HPP_INCLUDED
namespace Catch {
namespace Generators {
namespace Detail {
//! Throws GeneratorException with the provided message
[[noreturn]]
void throw_generator_exception( char const* msg );
} // namespace Detail
} // namespace Generators
} // namespace Catch
#endif // CATCH_GENERATORS_THROW_HPP_INCLUDED
@@ -24,6 +24,7 @@
#include <catch2/interfaces/catch_interfaces_capture.hpp>
#include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/interfaces/catch_interfaces_enum_values_registry.hpp>
#include <catch2/interfaces/catch_interfaces_exception.hpp>
#include <catch2/interfaces/catch_interfaces_generatortracker.hpp>
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
@@ -7,14 +7,7 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/interfaces/catch_interfaces_capture.hpp>
#include <catch2/internal/catch_enforce.hpp>
namespace Catch {
namespace Detail {
void missingCaptureInstance() {
CATCH_INTERNAL_ERROR( "No result capture instance" );
}
} // namespace Detail
IResultCapture::~IResultCapture() = default;
} // namespace Catch
}
@@ -10,8 +10,6 @@
#include <string>
#include <catch2/internal/catch_context.hpp>
#include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_result_type.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/benchmark/detail/catch_benchmark_stats_fwd.hpp>
@@ -22,6 +20,8 @@ namespace Catch {
struct AssertionInfo;
struct SectionInfo;
struct SectionEndInfo;
struct MessageInfo;
struct MessageBuilder;
struct Counts;
struct AssertionReaction;
struct SourceLineInfo;
@@ -42,26 +42,31 @@ namespace Catch {
virtual ~IResultCapture();
virtual void notifyAssertionStarted( AssertionInfo const& info ) = 0;
virtual bool sectionStarted( StringRef sectionName,
virtual bool sectionStarted( std::string_view sectionName,
SourceLineInfo const& sectionLineInfo,
Counts& assertions ) = 0;
virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0;
virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0;
virtual IGeneratorTracker*
acquireGeneratorTracker( StringRef generatorName,
acquireGeneratorTracker( std::string_view generatorName,
SourceLineInfo const& lineInfo ) = 0;
virtual IGeneratorTracker*
createGeneratorTracker( StringRef generatorName,
createGeneratorTracker( std::string_view generatorName,
SourceLineInfo lineInfo,
Generators::GeneratorBasePtr&& generator ) = 0;
virtual void benchmarkPreparing( StringRef name ) = 0;
virtual void benchmarkPreparing( std::string_view name ) = 0;
virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;
virtual void benchmarkFailed( StringRef error ) = 0;
virtual void benchmarkFailed( std::string_view error ) = 0;
virtual void handleFatalErrorCondition( StringRef message ) = 0;
virtual void pushScopedMessage( MessageInfo&& message ) = 0;
virtual void popScopedMessage( unsigned int messageId ) = 0;
virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0;
virtual void handleFatalErrorCondition( std::string_view message ) = 0;
virtual void handleExpr
( AssertionInfo const& info,
@@ -86,24 +91,16 @@ namespace Catch {
ResultWas::OfType resultType,
AssertionReaction &reaction ) = 0;
virtual bool lastAssertionPassed() = 0;
// Deprecated, do not use:
virtual std::string getCurrentTestName() const = 0;
virtual const AssertionResult* getLastResult() const = 0;
virtual void exceptionEarlyReported() = 0;
};
namespace Detail {
[[noreturn]]
void missingCaptureInstance();
}
inline IResultCapture& getResultCapture() {
if (auto* capture = getCurrentContext().getResultCapture()) {
return *capture;
} else {
Detail::missingCaptureInstance();
}
}
IResultCapture& getResultCapture();
}
#endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED

Some files were not shown because too many files have changed in this diff Show More