mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-23 21:15:39 +02:00
Compare commits
4 Commits
devel-c++1
...
devel-add-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b626e4c7ae | ||
![]() |
434bf55d47 | ||
![]() |
9048c24fa7 | ||
![]() |
8ed8c431c6 |
@@ -1,6 +1,6 @@
|
||||
---
|
||||
Language: Cpp
|
||||
Standard: c++17
|
||||
Standard: c++14
|
||||
|
||||
# Note that we cannot use IncludeIsMainRegex functionality, because it
|
||||
# does not support includes in angle brackets (<>)
|
||||
|
@@ -28,12 +28,13 @@ 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,
|
||||
|
||||
performance-*,
|
||||
-performance-enum-size,
|
||||
performance-enum-size,
|
||||
|
||||
portability-*,
|
||||
|
||||
|
5
.github/workflows/linux-meson-builds.yml
vendored
5
.github/workflows/linux-meson-builds.yml
vendored
@@ -4,7 +4,7 @@ on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: meson ${{matrix.cxx}}, ${{matrix.build_type}}
|
||||
name: meson ${{matrix.cxx}}, C++${{matrix.std}}, ${{matrix.build_type}}
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -13,6 +13,7 @@ jobs:
|
||||
- g++-11
|
||||
- clang++-11
|
||||
build_type: [debug, release]
|
||||
std: [14, 17]
|
||||
include:
|
||||
- cxx: clang++-11
|
||||
other_pkgs: clang-11
|
||||
@@ -28,7 +29,7 @@ jobs:
|
||||
- name: Configure
|
||||
env:
|
||||
CXX: ${{matrix.cxx}}
|
||||
CXXFLAGS: -std=c++17 ${{matrix.cxxflags}}
|
||||
CXXFLAGS: -std=c++${{matrix.std}} ${{matrix.cxxflags}}
|
||||
# Note: $GITHUB_WORKSPACE is distinct from ${{runner.workspace}}.
|
||||
# This is important
|
||||
run: |
|
||||
|
18
.github/workflows/linux-other-builds.yml
vendored
18
.github/workflows/linux-other-builds.yml
vendored
@@ -7,7 +7,7 @@ on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{matrix.build_description}}, ${{matrix.cxx}}, ${{matrix.build_type}}
|
||||
name: ${{matrix.build_description}}, ${{matrix.cxx}}, C++${{matrix.std}} ${{matrix.build_type}}
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -20,6 +20,7 @@ jobs:
|
||||
- cxx: clang++-14
|
||||
build_description: Surrogates build
|
||||
build_type: Debug
|
||||
std: 14
|
||||
other_pkgs: clang-14
|
||||
cmake_configurations: -DCATCH_BUILD_SURROGATES=ON
|
||||
|
||||
@@ -27,11 +28,13 @@ 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
|
||||
|
||||
@@ -39,18 +42,29 @@ 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
|
||||
@@ -69,6 +83,7 @@ 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
|
||||
@@ -101,6 +116,7 @@ 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
|
||||
|
14
.github/workflows/linux-simple-builds.yml
vendored
14
.github/workflows/linux-simple-builds.yml
vendored
@@ -14,6 +14,7 @@ jobs:
|
||||
- g++-10
|
||||
- g++-11
|
||||
- g++-12
|
||||
- clang++-6.0
|
||||
- clang++-7
|
||||
- clang++-8
|
||||
- clang++-9
|
||||
@@ -23,7 +24,7 @@ jobs:
|
||||
- clang++-13
|
||||
- clang++-14
|
||||
build_type: [Debug, Release]
|
||||
std: [17]
|
||||
std: [14]
|
||||
include:
|
||||
- cxx: g++-9
|
||||
other_pkgs: g++-9
|
||||
@@ -33,6 +34,8 @@ 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
|
||||
@@ -49,6 +52,15 @@ 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
|
||||
|
2
.github/workflows/mac-builds.yml
vendored
2
.github/workflows/mac-builds.yml
vendored
@@ -12,6 +12,7 @@ jobs:
|
||||
matrix:
|
||||
image: [macos-13, macos-14, macos-15]
|
||||
build_type: [Debug, Release]
|
||||
std: [14, 17]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -20,6 +21,7 @@ jobs:
|
||||
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
|
||||
|
||||
|
4
.github/workflows/windows-simple-builds.yml
vendored
4
.github/workflows/windows-simple-builds.yml
vendored
@@ -4,7 +4,7 @@ on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{matrix.os}}, ${{matrix.build_type}}, ${{matrix.platform}}
|
||||
name: ${{matrix.os}}, ${{matrix.std}}, ${{matrix.build_type}}, ${{matrix.platform}}
|
||||
runs-on: ${{matrix.os}}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -12,6 +12,7 @@ jobs:
|
||||
os: [windows-2022, windows-2025]
|
||||
platform: [Win32, x64]
|
||||
build_type: [Debug, Release]
|
||||
std: [14, 17]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -19,6 +20,7 @@ jobs:
|
||||
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%
|
||||
|
10
BUILD.bazel
10
BUILD.bazel
@@ -27,6 +27,11 @@ 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": "",
|
||||
@@ -46,6 +51,11 @@ 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": "",
|
||||
|
@@ -31,6 +31,11 @@ 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"
|
||||
|
@@ -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++17 and above (links in default main)
|
||||
Description: A modern, C++-native test framework for C++14 and above (links in default main)
|
||||
URL: https://github.com/catchorg/Catch2
|
||||
Version: ${pkg_version}
|
||||
Requires: catch2 = ${pkg_version}
|
||||
|
@@ -4,7 +4,7 @@ includedir=${prefix}/@include_dir@
|
||||
libdir=${prefix}/@lib_dir@
|
||||
|
||||
Name: Catch2
|
||||
Description: A modern, C++-native, test framework for C++17 and above
|
||||
Description: A modern, C++-native, test framework for C++14 and above
|
||||
URL: https://github.com/catchorg/Catch2
|
||||
Version: @Catch2_VERSION@
|
||||
Cflags: -I${includedir}
|
||||
|
@@ -20,6 +20,7 @@ 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)
|
||||
@@ -77,6 +78,11 @@ 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)
|
||||
|
@@ -11,19 +11,27 @@
|
||||
"CMAKE_CXX_EXTENSIONS": "OFF",
|
||||
"CMAKE_CXX_STANDARD_REQUIRED": "ON",
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
|
||||
"CATCH_DEVELOPMENT_BUILD": "ON",
|
||||
"CATCH_ENABLE_REPRODUCIBLE_BUILD": "OFF"
|
||||
"CATCH_DEVELOPMENT_BUILD": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "all-tests",
|
||||
"name": "most-tests",
|
||||
"inherits": "basic-tests",
|
||||
"displayName": "Full development build",
|
||||
"description": "Enables development build with examples and ALL tests",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "all-tests",
|
||||
"inherits": "most-tests",
|
||||
"displayName": "Full development build",
|
||||
"description": "Enables development build with examples and ALL tests",
|
||||
"cacheVariables": {
|
||||
"CATCH_ENABLE_CONFIGURE_TESTS": "ON",
|
||||
"CATCH_ENABLE_CMAKE_HELPER_TESTS": "ON"
|
||||
}
|
||||
|
16
benchmarks/CMakeLists.txt
Normal file
16
benchmarks/CMakeLists.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
include(CatchMiscFunctions)
|
||||
|
||||
add_executable(AssertionsFastPath
|
||||
runtime_assertion_benches.cpp
|
||||
)
|
||||
|
||||
add_executable(AssertionsSlowPath
|
||||
runtime_assertion_benches.cpp
|
||||
assertion_listener.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(AssertionsFastPath PRIVATE Catch2::Catch2WithMain)
|
||||
target_link_libraries(AssertionsSlowPath PRIVATE Catch2::Catch2WithMain)
|
||||
|
||||
list(APPEND CATCH_TEST_TARGETS AssertionsFastPath AssertionsSlowPath)
|
||||
set(CATCH_TEST_TARGETS ${CATCH_TEST_TARGETS} PARENT_SCOPE)
|
28
benchmarks/assertion_listener.cpp
Normal file
28
benchmarks/assertion_listener.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
// 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
|
||||
*/
|
||||
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 )
|
27
benchmarks/runtime_assertion_benches.cpp
Normal file
27
benchmarks/runtime_assertion_benches.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
// 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>
|
||||
|
||||
TEST_CASE("Simple REQUIRE - 10M") {
|
||||
for (size_t i = 0; i < 10'000'000; ++i) {
|
||||
REQUIRE(true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Simple NOTHROW - 10M") {
|
||||
for (size_t i = 0; i < 10'000'000; ++i) {
|
||||
REQUIRE_NOTHROW([](){}());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Simple THROWS - 10M") {
|
||||
for (size_t i = 0; i < 10'000'000; ++i) {
|
||||
REQUIRE_THROWS([]() { throw 1; }());
|
||||
}
|
||||
}
|
@@ -66,11 +66,14 @@ 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`
|
||||
|
||||
> 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` was introduced in Catch2 X.Y.Z
|
||||
|
||||
This integration is enabled via either a [compile time configuration
|
||||
option](configuration.md#bazel-support), or via `BAZEL_TEST` environment
|
||||
variable set to "1".
|
||||
|
@@ -32,6 +32,7 @@
|
||||
[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.
|
||||
@@ -649,6 +650,21 @@ ignored.
|
||||
Verbosity defaults to _normal_.
|
||||
|
||||
|
||||
## Create file to guard against silent early termination
|
||||
<pre>--premature-exit-guard-file <path></pre>
|
||||
|
||||
> Introduced in Catch2 X.Y.Z
|
||||
|
||||
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)
|
||||
|
@@ -10,6 +10,7 @@
|
||||
[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>
|
||||
@@ -127,6 +128,23 @@ 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
|
||||
@@ -203,8 +221,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
|
||||
CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER // Provide StringMaker specialization for std::optional
|
||||
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_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.
|
||||
|
@@ -211,10 +211,16 @@ and so on.
|
||||
|
||||
### C++ standard version
|
||||
|
||||
Catch2 currently targets C++17 as the minimum supported C++ version.
|
||||
Catch2 currently targets C++14 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
|
||||
|
@@ -72,8 +72,8 @@ including the Catch2 header.
|
||||
Example:
|
||||
```cpp
|
||||
TEST_CASE("STATIC_REQUIRE showcase", "[traits]") {
|
||||
STATIC_REQUIRE( std::is_void_v<void> );
|
||||
STATIC_REQUIRE_FALSE( std::is_void_v<int> );
|
||||
STATIC_REQUIRE( std::is_void<void>::value );
|
||||
STATIC_REQUIRE_FALSE( std::is_void<int>::value );
|
||||
}
|
||||
```
|
||||
|
||||
@@ -86,8 +86,8 @@ becomes equivalent to `CHECK` instead of `REQUIRE`.
|
||||
Example:
|
||||
```cpp
|
||||
TEST_CASE("STATIC_CHECK showcase", "[traits]") {
|
||||
STATIC_CHECK( std::is_void_v<void> );
|
||||
STATIC_CHECK_FALSE( std::is_void_v<int> );
|
||||
STATIC_CHECK( std::is_void<void>::value );
|
||||
STATIC_CHECK_FALSE( std::is_void<int>::value );
|
||||
}
|
||||
```
|
||||
|
||||
|
@@ -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( std::string_view name ) override;
|
||||
void benchmarkPreparing( StringRef name ) override;
|
||||
void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
|
||||
void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
|
||||
void benchmarkFailed( std::string_view error ) override;
|
||||
void benchmarkFailed( StringRef 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( std::string_view unmatchedSpec );
|
||||
void fatalErrorEncountered( std::string_view error );
|
||||
void noMatchingTestCases( std::string_view unmatchedSpec );
|
||||
void reportInvalidTestSpec( StringRef unmatchedSpec );
|
||||
void fatalErrorEncountered( StringRef error );
|
||||
void noMatchingTestCases( StringRef unmatchedSpec );
|
||||
```
|
||||
|
||||
These are one-off events that do not neatly fit into other categories.
|
||||
|
@@ -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_v<TestType> >= 1);
|
||||
REQUIRE(std::tuple_size<TestType>::value >= 1);
|
||||
}
|
||||
```
|
||||
|
||||
|
@@ -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++17 and have the C++ standard library available.
|
||||
* No external dependencies. As long as you can compile C++14 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.
|
||||
|
@@ -27,7 +27,7 @@ TEST_CASE( "Factorials of 1 and higher are computed (pass)", "[single-file]" ) {
|
||||
}
|
||||
|
||||
// Compile & run:
|
||||
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 010-TestCase 010-TestCase.cpp && 010-TestCase --success
|
||||
// - g++ -std=c++14 -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):
|
||||
|
@@ -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++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
|
||||
// - 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
|
||||
//
|
||||
// - 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
|
||||
|
@@ -61,7 +61,7 @@ TEST_CASE( "Assert that something is false (continue after failure)", "[check-fa
|
||||
}
|
||||
|
||||
// Compile & run:
|
||||
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 030-Asn-Require-Check 030-Asn-Require-Check.cpp && 030-Asn-Require-Check --success
|
||||
// - g++ -std=c++14 -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):
|
||||
|
@@ -53,7 +53,7 @@ TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
|
||||
}
|
||||
|
||||
// Compile & run:
|
||||
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 100-Fix-Section 100-Fix-Section.cpp && 100-Fix-Section --success
|
||||
// - g++ -std=c++14 -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):
|
||||
|
@@ -60,11 +60,11 @@ TEST_CASE_METHOD( UniqueTestsFixture, "Create Employee/Normal", "[create]" ) {
|
||||
}
|
||||
|
||||
// Compile & run:
|
||||
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 110-Fix-ClassFixture 110-Fix-ClassFixture.cpp && 110-Fix-ClassFixture --success
|
||||
// - g++ -std=c++14 -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++17 -Wall $(pkg-config catch2-with-main --cflags) -o 110-Fix-ClassFixture 110-Fix-ClassFixture.cpp $(pkg-config catch2-with-main --libs)
|
||||
// - 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)
|
||||
|
||||
// Expected compact output (all assertions):
|
||||
//
|
||||
|
@@ -56,7 +56,7 @@ SCENARIO( "vectors can be sized and resized", "[vector]" ) {
|
||||
}
|
||||
|
||||
// Compile & run:
|
||||
// - g++ -std=c++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 120-Bdd-ScenarioGivenWhenThen 120-Bdd-ScenarioGivenWhenThen.cpp && 120-Bdd-ScenarioGivenWhenThen --success
|
||||
// - g++ -std=c++14 -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):
|
||||
|
@@ -131,7 +131,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
|
||||
}
|
||||
|
||||
// struct Tag {
|
||||
// std::string_view original, lowerCased;
|
||||
// StringRef original, lowerCased;
|
||||
// };
|
||||
//
|
||||
//
|
||||
@@ -221,9 +221,9 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
|
||||
|
||||
// struct AssertionInfo
|
||||
// {
|
||||
// std::string_view macroName;
|
||||
// StringRef macroName;
|
||||
// SourceLineInfo lineInfo;
|
||||
// std::string_view capturedExpression;
|
||||
// StringRef 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++17 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 210-Evt-EventListeners 210-Evt-EventListeners.cpp && 210-Evt-EventListeners --success
|
||||
// - g++ -std=c++14 -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):
|
||||
|
@@ -22,21 +22,24 @@ 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") {
|
||||
const auto [test_input, expected_output] =
|
||||
std::string test_input;
|
||||
size_t expected_output;
|
||||
std::tie( 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.
|
||||
*/
|
||||
{ "one", 3 },
|
||||
{ "two", 3 },
|
||||
{ "three", 5 },
|
||||
{ "four", 4 } } ) );
|
||||
make_tuple( "one", 3 ),
|
||||
make_tuple( "two", 3 ),
|
||||
make_tuple( "three", 5 ),
|
||||
make_tuple( "four", 4 ) } ) );
|
||||
|
||||
// run the test
|
||||
auto result = subj.GetLength(test_input);
|
||||
@@ -47,4 +50,14 @@ 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
|
||||
|
@@ -76,9 +76,11 @@ 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
|
||||
@@ -97,10 +99,12 @@ set(IMPL_HEADERS
|
||||
${SOURCES_DIR}/internal/catch_lazy_expr.hpp
|
||||
${SOURCES_DIR}/internal/catch_leak_detector.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_platform.hpp
|
||||
@@ -124,6 +128,7 @@ 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
|
||||
@@ -200,6 +205,7 @@ 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
|
||||
@@ -359,8 +365,8 @@ set_target_properties(Catch2 PROPERTIES
|
||||
SOVERSION ${PROJECT_VERSION}
|
||||
)
|
||||
|
||||
# require C++17
|
||||
target_compile_features(Catch2 PUBLIC cxx_std_17)
|
||||
# require C++14
|
||||
target_compile_features(Catch2 PUBLIC cxx_std_14)
|
||||
|
||||
configure_file(
|
||||
"${SOURCES_DIR}/catch_user_config.hpp.in"
|
||||
@@ -444,7 +450,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_17)
|
||||
target_compile_features(Catch2_buildall_interface INTERFACE cxx_std_14)
|
||||
endif()
|
||||
|
||||
list(APPEND CATCH_IMPL_TARGETS Catch2 Catch2WithMain)
|
||||
|
@@ -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_v<void, decltype(fn(args...))>> {
|
||||
inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<!std::is_same<void, decltype(fn(args...))>::value> {
|
||||
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_v<void, decltype(fn(args...))>> {
|
||||
inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<std::is_same<void, decltype(fn(args...))>::value> {
|
||||
CATCH_FORWARD((fn)) (CATCH_FORWARD(args)...);
|
||||
}
|
||||
} // namespace Benchmark
|
||||
|
@@ -46,7 +46,7 @@ namespace Catch {
|
||||
std::vector<FDuration> samples2;
|
||||
samples2.reserve(samples.size());
|
||||
for (auto s : samples) {
|
||||
samples2.emplace_back( s );
|
||||
samples2.push_back( FDuration( 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_v<std::decay_t<T>, std::decay_t<U>>;
|
||||
static constexpr bool is_related_v = std::is_same<std::decay_t<T>, std::decay_t<U>>::value;
|
||||
|
||||
/// 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
|
||||
|
@@ -57,9 +57,11 @@
|
||||
#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>
|
||||
@@ -78,10 +80,12 @@
|
||||
#include <catch2/internal/catch_lazy_expr.hpp>
|
||||
#include <catch2/internal/catch_leak_detector.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_platform.hpp>
|
||||
@@ -106,6 +110,7 @@
|
||||
#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>
|
||||
|
@@ -29,7 +29,7 @@ namespace Catch {
|
||||
|
||||
Approx operator-() const;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
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_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
explicit Approx( T const& value ): Approx(static_cast<double>(value))
|
||||
{}
|
||||
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
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_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
friend bool operator == ( Approx const& lhs, const T& rhs ) {
|
||||
return operator==( rhs, lhs );
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
friend bool operator != ( T const& lhs, Approx const& rhs ) {
|
||||
return !operator==( lhs, rhs );
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
friend bool operator != ( Approx const& lhs, T const& rhs ) {
|
||||
return !operator==( rhs, lhs );
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
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_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
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_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
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_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
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_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
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_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
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_v<double, T>>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
|
||||
Approx& scale( T const& newScale ) {
|
||||
m_scale = static_cast<double>(newScale);
|
||||
return *this;
|
||||
|
@@ -10,17 +10,16 @@
|
||||
|
||||
#include <catch2/internal/catch_result_type.hpp>
|
||||
#include <catch2/internal/catch_source_line_info.hpp>
|
||||
|
||||
#include <string_view>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct AssertionInfo {
|
||||
// AssertionInfo() = delete;
|
||||
|
||||
std::string_view macroName;
|
||||
StringRef macroName;
|
||||
SourceLineInfo lineInfo;
|
||||
std::string_view capturedExpression;
|
||||
StringRef capturedExpression;
|
||||
ResultDisposition::Flags resultDisposition;
|
||||
};
|
||||
|
||||
|
@@ -91,14 +91,14 @@ namespace Catch {
|
||||
: expr;
|
||||
}
|
||||
|
||||
std::string_view AssertionResult::getMessage() const {
|
||||
StringRef AssertionResult::getMessage() const {
|
||||
return m_resultData.message;
|
||||
}
|
||||
SourceLineInfo AssertionResult::getSourceInfo() const {
|
||||
return m_info.lineInfo;
|
||||
}
|
||||
|
||||
std::string_view AssertionResult::getTestMacroName() const {
|
||||
StringRef AssertionResult::getTestMacroName() const {
|
||||
return m_info.macroName;
|
||||
}
|
||||
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#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>
|
||||
@@ -45,9 +46,9 @@ namespace Catch {
|
||||
std::string getExpressionInMacro() const;
|
||||
bool hasExpandedExpression() const;
|
||||
std::string getExpandedExpression() const;
|
||||
std::string_view getMessage() const;
|
||||
StringRef getMessage() const;
|
||||
SourceLineInfo getSourceInfo() const;
|
||||
std::string_view getTestMacroName() const;
|
||||
StringRef getTestMacroName() const;
|
||||
|
||||
//protected:
|
||||
AssertionInfo m_info;
|
||||
|
@@ -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 std::optional<bazelShardingOptions> readBazelShardingOptions() {
|
||||
static 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" );
|
||||
@@ -119,6 +119,8 @@ 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();
|
||||
}
|
||||
@@ -142,7 +144,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() ) {
|
||||
if ( reporterSpec.outputFile().none() ) {
|
||||
CATCH_ENFORCE( !defaultOutputUsed,
|
||||
"Internal error: cannot use default output for "
|
||||
"multiple reporters" );
|
||||
@@ -153,7 +155,7 @@ namespace Catch {
|
||||
reporterSpec.name(),
|
||||
reporterSpec.outputFile() ? *reporterSpec.outputFile()
|
||||
: data.defaultOutputFilename,
|
||||
reporterSpec.colourMode().value_or( data.defaultColourMode ),
|
||||
reporterSpec.colourMode().valueOr( data.defaultColourMode ),
|
||||
reporterSpec.customOptions() } );
|
||||
}
|
||||
}
|
||||
@@ -183,9 +185,11 @@ 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; }
|
||||
std::string_view Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
|
||||
StringRef 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 );
|
||||
@@ -244,6 +248,11 @@ namespace Catch {
|
||||
m_data.shardCount = bazelShardOptions->shardCount;
|
||||
}
|
||||
}
|
||||
|
||||
const auto bazelExitGuardFile = Detail::getEnv( "TEST_PREMATURE_EXIT_FILE" );
|
||||
if (bazelExitGuardFile) {
|
||||
m_data.prematureExitGuardFilePath = bazelExitGuardFile;
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
||||
|
@@ -11,6 +11,8 @@
|
||||
#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_stringref.hpp>
|
||||
#include <catch2/internal/catch_random_seed_generation.hpp>
|
||||
#include <catch2/internal/catch_reporter_spec_parser.hpp>
|
||||
|
||||
@@ -85,6 +87,8 @@ namespace Catch {
|
||||
|
||||
std::vector<std::string> testsOrTags;
|
||||
std::vector<std::string> sectionsToRun;
|
||||
|
||||
std::string prematureExitGuardFilePath;
|
||||
};
|
||||
|
||||
|
||||
@@ -112,9 +116,11 @@ namespace Catch {
|
||||
|
||||
bool showHelp() const;
|
||||
|
||||
std::string const& getExitGuardFilePath() const;
|
||||
|
||||
// IConfig interface
|
||||
bool allowThrows() const override;
|
||||
std::string_view name() const override;
|
||||
StringRef name() const override;
|
||||
bool includeSuccessfulResults() const override;
|
||||
bool warnAboutMissingAssertions() const override;
|
||||
bool warnAboutUnmatchedTestSpecs() const override;
|
||||
|
@@ -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();
|
||||
getResultCapture().pushScopedMessage( CATCH_MOVE(info) );
|
||||
IResultCapture::pushScopedMessage( CATCH_MOVE( info ) );
|
||||
}
|
||||
|
||||
ScopedMessage::ScopedMessage( ScopedMessage&& old ) noexcept:
|
||||
@@ -31,15 +31,14 @@ namespace Catch {
|
||||
}
|
||||
|
||||
ScopedMessage::~ScopedMessage() {
|
||||
if ( !m_moved ) { getResultCapture().popScopedMessage( m_messageId ); }
|
||||
if ( !m_moved ) { IResultCapture::popScopedMessage( m_messageId ); }
|
||||
}
|
||||
|
||||
|
||||
Capturer::Capturer( std::string_view macroName,
|
||||
Capturer::Capturer( StringRef macroName,
|
||||
SourceLineInfo const& lineInfo,
|
||||
ResultWas::OfType resultType,
|
||||
std::string_view names ):
|
||||
m_resultCapture( getResultCapture() ) {
|
||||
StringRef names ) {
|
||||
auto trimmed = [&] (size_t start, size_t end) {
|
||||
while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {
|
||||
++start;
|
||||
@@ -86,7 +85,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 += " := ";
|
||||
m_messages.back().message += " := "_sr;
|
||||
start = pos;
|
||||
}
|
||||
break;
|
||||
@@ -96,19 +95,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 += " := ";
|
||||
m_messages.back().message += " := "_sr;
|
||||
}
|
||||
Capturer::~Capturer() {
|
||||
assert( m_captured == m_messages.size() );
|
||||
for (auto const& message : m_messages) {
|
||||
m_resultCapture.popScopedMessage( message.sequence );
|
||||
IResultCapture::popScopedMessage( message.sequence );
|
||||
}
|
||||
}
|
||||
|
||||
void Capturer::captureValue( size_t index, std::string const& value ) {
|
||||
assert( index < m_messages.size() );
|
||||
m_messages[index].message += value;
|
||||
m_resultCapture.pushScopedMessage( CATCH_MOVE(m_messages[index]) );
|
||||
IResultCapture::pushScopedMessage( CATCH_MOVE( m_messages[index] ) );
|
||||
m_captured++;
|
||||
}
|
||||
|
||||
|
@@ -36,7 +36,7 @@ namespace Catch {
|
||||
};
|
||||
|
||||
struct MessageBuilder : MessageStream {
|
||||
MessageBuilder( std::string_view macroName,
|
||||
MessageBuilder( StringRef macroName,
|
||||
SourceLineInfo const& lineInfo,
|
||||
ResultWas::OfType type ):
|
||||
m_info(macroName, lineInfo, type) {}
|
||||
@@ -63,10 +63,9 @@ namespace Catch {
|
||||
|
||||
class Capturer {
|
||||
std::vector<MessageInfo> m_messages;
|
||||
IResultCapture& m_resultCapture;
|
||||
size_t m_captured = 0;
|
||||
public:
|
||||
Capturer( std::string_view macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, std::string_view names );
|
||||
Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
|
||||
|
||||
Capturer(Capturer const&) = delete;
|
||||
Capturer& operator=(Capturer const&) = delete;
|
||||
@@ -92,26 +91,26 @@ namespace Catch {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
|
||||
do { \
|
||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, std::string_view(), resultDisposition ); \
|
||||
Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
|
||||
catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
|
||||
catchAssertionHandler.complete(); \
|
||||
} while( false )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
|
||||
Catch::Capturer varName( macroName, \
|
||||
Catch::Capturer varName( macroName##_catch_sr, \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
Catch::ResultWas::Info, \
|
||||
#__VA_ARGS__ ); \
|
||||
#__VA_ARGS__##_catch_sr ); \
|
||||
varName.captureValues( 0, __VA_ARGS__ )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_INFO( macroName, log ) \
|
||||
const Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
|
||||
const Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
|
||||
Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
|
||||
Catch::IResultCapture::emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
|
||||
|
||||
|
||||
#if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
#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>
|
||||
|
@@ -26,6 +26,8 @@
|
||||
#include <catch2/internal/catch_istream.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <iomanip>
|
||||
#include <set>
|
||||
@@ -140,6 +142,50 @@ 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() {
|
||||
@@ -258,6 +304,7 @@ 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());
|
||||
@@ -298,6 +345,10 @@ 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) {
|
||||
@@ -327,9 +378,12 @@ 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;
|
||||
}
|
||||
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
// TODO: Use C++17 `inline` variables
|
||||
constexpr int UnspecifiedErrorExitCode = 1;
|
||||
constexpr int NoTestsRunExitCode = 2;
|
||||
constexpr int UnmatchedTestSpecExitCode = 3;
|
||||
|
@@ -14,7 +14,6 @@
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -48,28 +47,28 @@ namespace Catch {
|
||||
return tcp != TestCaseProperties::None;
|
||||
}
|
||||
|
||||
TestCaseProperties parseSpecialTag( std::string_view tag ) {
|
||||
TestCaseProperties parseSpecialTag( StringRef tag ) {
|
||||
if( !tag.empty() && tag[0] == '.' )
|
||||
return TestCaseProperties::IsHidden;
|
||||
else if( tag == "!throws" )
|
||||
else if( tag == "!throws"_sr )
|
||||
return TestCaseProperties::Throws;
|
||||
else if( tag == "!shouldfail" )
|
||||
else if( tag == "!shouldfail"_sr )
|
||||
return TestCaseProperties::ShouldFail;
|
||||
else if( tag == "!mayfail" )
|
||||
else if( tag == "!mayfail"_sr )
|
||||
return TestCaseProperties::MayFail;
|
||||
else if( tag == "!nonportable" )
|
||||
else if( tag == "!nonportable"_sr )
|
||||
return TestCaseProperties::NonPortable;
|
||||
else if( tag == "!benchmark" )
|
||||
else if( tag == "!benchmark"_sr )
|
||||
return TestCaseProperties::Benchmark | TestCaseProperties::IsHidden;
|
||||
else
|
||||
return TestCaseProperties::None;
|
||||
}
|
||||
bool isReservedTag( std::string_view tag ) {
|
||||
bool isReservedTag( StringRef tag ) {
|
||||
return parseSpecialTag( tag ) == TestCaseProperties::None
|
||||
&& tag.size() > 0
|
||||
&& !std::isalnum( static_cast<unsigned char>(tag[0]) );
|
||||
}
|
||||
void enforceNotReservedTag( std::string_view tag, SourceLineInfo const& _lineInfo ) {
|
||||
void enforceNotReservedTag( StringRef 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"
|
||||
@@ -81,13 +80,13 @@ namespace Catch {
|
||||
return "Anonymous test case " + std::to_string(++counter);
|
||||
}
|
||||
|
||||
constexpr std::string_view extractFilenamePart(std::string_view filename) {
|
||||
constexpr StringRef extractFilenamePart(StringRef 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 std::string_view(); }
|
||||
if ( lastDot == 0 ) { return StringRef(); }
|
||||
|
||||
--lastDot;
|
||||
size_t nameStart = lastDot;
|
||||
@@ -99,7 +98,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
// Returns the upper bound on size of extra tags ([#file]+[.])
|
||||
constexpr size_t sizeOfExtraTags(std::string_view filepath) {
|
||||
constexpr size_t sizeOfExtraTags(StringRef filepath) {
|
||||
// [.] is 3, [#] is another 3
|
||||
const size_t extras = 3 + 3;
|
||||
return extractFilenamePart(filepath).size() + extras;
|
||||
@@ -116,20 +115,20 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Detail::unique_ptr<TestCaseInfo>
|
||||
makeTestCaseInfo(std::string_view _className,
|
||||
makeTestCaseInfo(StringRef _className,
|
||||
NameAndTags const& nameAndTags,
|
||||
SourceLineInfo const& _lineInfo ) {
|
||||
return Detail::make_unique<TestCaseInfo>(_className, nameAndTags, _lineInfo);
|
||||
}
|
||||
|
||||
TestCaseInfo::TestCaseInfo(std::string_view _className,
|
||||
TestCaseInfo::TestCaseInfo(StringRef _className,
|
||||
NameAndTags const& _nameAndTags,
|
||||
SourceLineInfo const& _lineInfo):
|
||||
name( _nameAndTags.name.empty() ? makeDefaultName() : _nameAndTags.name ),
|
||||
className( _className ),
|
||||
lineInfo( _lineInfo )
|
||||
{
|
||||
std::string_view originalTags = _nameAndTags.tags;
|
||||
StringRef 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);
|
||||
@@ -164,7 +163,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
|
||||
std::string_view tagStr = originalTags.substr(tagStart+1, tagEnd - tagStart - 1);
|
||||
StringRef tagStr = originalTags.substr(tagStart+1, tagEnd - tagStart - 1);
|
||||
CATCH_ENFORCE( !tagStr.empty(),
|
||||
"Found an empty tag while registering test case '"
|
||||
<< _nameAndTags.name << "' at "
|
||||
@@ -191,7 +190,7 @@ namespace Catch {
|
||||
|
||||
// Add [.] if relevant
|
||||
if (isHidden()) {
|
||||
internalAppendTag(".");
|
||||
internalAppendTag("."_sr);
|
||||
}
|
||||
|
||||
// Sort and prepare tags
|
||||
@@ -236,13 +235,13 @@ namespace Catch {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void TestCaseInfo::internalAppendTag(std::string_view tagStr) {
|
||||
void TestCaseInfo::internalAppendTag(StringRef tagStr) {
|
||||
backingTags += '[';
|
||||
const auto backingStart = backingTags.size();
|
||||
backingTags += tagStr;
|
||||
const auto backingEnd = backingTags.size();
|
||||
backingTags += ']';
|
||||
tags.emplace_back(std::string_view(backingTags.c_str() + backingStart, backingEnd - backingStart));
|
||||
tags.emplace_back(StringRef(backingTags.c_str() + backingStart, backingEnd - backingStart));
|
||||
}
|
||||
|
||||
bool operator<( TestCaseInfo const& lhs, TestCaseInfo const& rhs ) {
|
||||
|
@@ -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(std::string_view original_):
|
||||
constexpr Tag(StringRef original_):
|
||||
original(original_)
|
||||
{}
|
||||
std::string_view original;
|
||||
StringRef 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(std::string_view _className,
|
||||
TestCaseInfo(StringRef _className,
|
||||
NameAndTags const& _nameAndTags,
|
||||
SourceLineInfo const& _lineInfo);
|
||||
|
||||
@@ -87,12 +87,12 @@ namespace Catch {
|
||||
std::string tagsAsString() const;
|
||||
|
||||
std::string name;
|
||||
std::string_view className;
|
||||
StringRef 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(std::string_view tagString);
|
||||
void internalAppendTag(StringRef tagString);
|
||||
public:
|
||||
std::vector<Tag> tags;
|
||||
SourceLineInfo lineInfo;
|
||||
@@ -130,7 +130,7 @@ namespace Catch {
|
||||
};
|
||||
|
||||
Detail::unique_ptr<TestCaseInfo>
|
||||
makeTestCaseInfo( std::string_view className,
|
||||
makeTestCaseInfo( StringRef className,
|
||||
NameAndTags const& nameAndTags,
|
||||
SourceLineInfo const& lineInfo );
|
||||
}
|
||||
|
@@ -8,13 +8,13 @@
|
||||
#ifndef CATCH_TEST_RUN_INFO_HPP_INCLUDED
|
||||
#define CATCH_TEST_RUN_INFO_HPP_INCLUDED
|
||||
|
||||
#include <string_view>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct TestRunInfo {
|
||||
constexpr TestRunInfo(std::string_view _name) : name(_name) {}
|
||||
std::string_view name;
|
||||
constexpr TestRunInfo(StringRef _name) : name(_name) {}
|
||||
StringRef name;
|
||||
};
|
||||
|
||||
} // end namespace Catch
|
||||
|
@@ -13,7 +13,6 @@
|
||||
#include <catch2/internal/catch_polyfills.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <cstddef>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -58,7 +57,7 @@ namespace Detail {
|
||||
}
|
||||
} // end unnamed namespace
|
||||
|
||||
std::string convertIntoString(std::string_view string, bool escapeInvisibles) {
|
||||
std::string convertIntoString(StringRef 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.
|
||||
@@ -96,7 +95,7 @@ namespace Detail {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string convertIntoString(std::string_view string) {
|
||||
std::string convertIntoString(StringRef string) {
|
||||
return convertIntoString(string, getCurrentContext().getConfig()->showInvisibles());
|
||||
}
|
||||
|
||||
@@ -136,9 +135,11 @@ 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( std::string_view( str.data(), str.size() ) );
|
||||
return Detail::convertIntoString( StringRef( str.data(), str.size() ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string StringMaker<char const*>::convert(char const* str) {
|
||||
if (str) {
|
||||
@@ -165,9 +166,11 @@ 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) {
|
||||
@@ -185,9 +188,12 @@ 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));
|
||||
|
@@ -20,7 +20,9 @@
|
||||
#include <catch2/internal/catch_void_type.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)
|
||||
@@ -46,14 +48,14 @@ namespace Catch {
|
||||
return n;
|
||||
}
|
||||
|
||||
constexpr std::string_view unprintableString = "{?}";
|
||||
constexpr StringRef unprintableString = "{?}"_sr;
|
||||
|
||||
//! Encases `string in quotes, and optionally escapes invisibles
|
||||
std::string convertIntoString( std::string_view string, bool escapeInvisibles );
|
||||
std::string convertIntoString( StringRef string, bool escapeInvisibles );
|
||||
|
||||
//! Encases `string` in quotes, and escapes invisibles if user requested
|
||||
//! it via CLI
|
||||
std::string convertIntoString( std::string_view string );
|
||||
std::string convertIntoString( StringRef string );
|
||||
|
||||
std::string rawMemoryToString( const void *object, std::size_t size );
|
||||
|
||||
@@ -76,13 +78,13 @@ namespace Catch {
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<
|
||||
!std::is_enum_v<T> && !std::is_base_of_v<std::exception, T>,
|
||||
!std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,
|
||||
std::string> convertUnstreamable( T const& ) {
|
||||
return std::string(Detail::unprintableString);
|
||||
}
|
||||
template<typename T>
|
||||
std::enable_if_t<
|
||||
!std::is_enum_v<T> && std::is_base_of_v<std::exception, T>,
|
||||
!std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
|
||||
std::string> convertUnstreamable(T const& ex) {
|
||||
return ex.what();
|
||||
}
|
||||
@@ -90,7 +92,7 @@ namespace Catch {
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<
|
||||
std::is_enum_v<T>,
|
||||
std::is_enum<T>::value,
|
||||
std::string> convertUnstreamable( T const& value ) {
|
||||
return convertUnknownEnumToString( value );
|
||||
}
|
||||
@@ -171,10 +173,12 @@ 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 *> {
|
||||
@@ -191,10 +195,12 @@ 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 *> {
|
||||
@@ -210,7 +216,7 @@ namespace Catch {
|
||||
struct StringMaker<char[SZ]> {
|
||||
static std::string convert(char const* str) {
|
||||
return Detail::convertIntoString(
|
||||
std::string_view( str, Detail::catch_strnlen( str, SZ ) ) );
|
||||
StringRef( str, Detail::catch_strnlen( str, SZ ) ) );
|
||||
}
|
||||
};
|
||||
template<size_t SZ>
|
||||
@@ -218,7 +224,7 @@ namespace Catch {
|
||||
static std::string convert(signed char const* str) {
|
||||
auto reinterpreted = reinterpret_cast<char const*>(str);
|
||||
return Detail::convertIntoString(
|
||||
std::string_view(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
|
||||
StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
|
||||
}
|
||||
};
|
||||
template<size_t SZ>
|
||||
@@ -226,14 +232,16 @@ namespace Catch {
|
||||
static std::string convert(unsigned char const* str) {
|
||||
auto reinterpreted = reinterpret_cast<char const*>(str);
|
||||
return Detail::convertIntoString(
|
||||
std::string_view(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
|
||||
StringRef(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);
|
||||
@@ -379,7 +387,7 @@ namespace Catch {
|
||||
}
|
||||
#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
|
||||
|
||||
#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER)
|
||||
#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
|
||||
#include <optional>
|
||||
namespace Catch {
|
||||
template<typename T>
|
||||
@@ -409,7 +417,7 @@ namespace Catch {
|
||||
template<
|
||||
typename Tuple,
|
||||
std::size_t N = 0,
|
||||
bool = (N < std::tuple_size_v<Tuple>)
|
||||
bool = (N < std::tuple_size<Tuple>::value)
|
||||
>
|
||||
struct TupleElementPrinter {
|
||||
static void print(const Tuple& tuple, std::ostream& os) {
|
||||
@@ -443,7 +451,7 @@ namespace Catch {
|
||||
}
|
||||
#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
|
||||
|
||||
#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER)
|
||||
#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
|
||||
#include <variant>
|
||||
namespace Catch {
|
||||
template<>
|
||||
|
@@ -60,6 +60,56 @@
|
||||
|
||||
|
||||
|
||||
#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
|
||||
|
||||
|
@@ -27,11 +27,11 @@ namespace Detail {
|
||||
|
||||
GeneratorUntypedBase::~GeneratorUntypedBase() = default;
|
||||
|
||||
IGeneratorTracker* acquireGeneratorTracker(std::string_view generatorName, SourceLineInfo const& lineInfo ) {
|
||||
IGeneratorTracker* acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo ) {
|
||||
return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo );
|
||||
}
|
||||
|
||||
IGeneratorTracker* createGeneratorTracker( std::string_view generatorName,
|
||||
IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
|
||||
SourceLineInfo lineInfo,
|
||||
GeneratorBasePtr&& generator ) {
|
||||
return getResultCapture().createGeneratorTracker(
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include <catch2/catch_tostring.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>
|
||||
|
||||
@@ -87,7 +88,7 @@ namespace Detail {
|
||||
|
||||
template<typename T>
|
||||
class FixedValuesGenerator final : public IGenerator<T> {
|
||||
static_assert(!std::is_same_v<T, bool>,
|
||||
static_assert(!std::is_same<T, bool>::value,
|
||||
"FixedValuesGenerator does not support bools because of std::vector<bool>"
|
||||
"specialization, use SingleValue Generator instead.");
|
||||
std::vector<T> m_values;
|
||||
@@ -130,7 +131,7 @@ namespace Detail {
|
||||
m_generators.emplace_back( value( CATCH_MOVE( val ) ) );
|
||||
}
|
||||
template <typename U>
|
||||
std::enable_if_t<!std::is_same_v<std::decay_t<U>, T>>
|
||||
std::enable_if_t<!std::is_same<std::decay_t<U>, T>::value>
|
||||
add_generator( U&& val ) {
|
||||
add_generator( T( CATCH_FORWARD( val ) ) );
|
||||
}
|
||||
@@ -196,14 +197,14 @@ namespace Detail {
|
||||
return makeGenerators( value( T( CATCH_FORWARD( val ) ) ), CATCH_FORWARD( moreGenerators )... );
|
||||
}
|
||||
|
||||
IGeneratorTracker* acquireGeneratorTracker( std::string_view generatorName,
|
||||
IGeneratorTracker* acquireGeneratorTracker( StringRef generatorName,
|
||||
SourceLineInfo const& lineInfo );
|
||||
IGeneratorTracker* createGeneratorTracker( std::string_view generatorName,
|
||||
IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
|
||||
SourceLineInfo lineInfo,
|
||||
GeneratorBasePtr&& generator );
|
||||
|
||||
template<typename L>
|
||||
auto generate( std::string_view generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> typename decltype(generatorExpression())::type {
|
||||
auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> typename decltype(generatorExpression())::type {
|
||||
using UnderlyingType = typename decltype(generatorExpression())::type;
|
||||
|
||||
IGeneratorTracker* tracker = acquireGeneratorTracker( generatorName, lineInfo );
|
||||
@@ -224,7 +225,7 @@ namespace Detail {
|
||||
} // namespace Generators
|
||||
} // namespace Catch
|
||||
|
||||
#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__
|
||||
#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__##_catch_sr
|
||||
#define CATCH_INTERNAL_GENERATOR_STRINGIZE(...) CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL(__VA_ARGS__)
|
||||
|
||||
#define GENERATE( ... ) \
|
||||
|
@@ -58,7 +58,7 @@ namespace Generators {
|
||||
class FilterGenerator final : public IGenerator<T> {
|
||||
GeneratorWrapper<T> m_generator;
|
||||
Predicate m_predicate;
|
||||
static_assert(!std::is_reference_v<Predicate>, "This would most likely result in a dangling reference");
|
||||
static_assert(!std::is_reference<Predicate>::value, "This would most likely result in a dangling reference");
|
||||
public:
|
||||
template <typename P>
|
||||
FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
|
||||
@@ -97,7 +97,7 @@ namespace Generators {
|
||||
|
||||
template <typename T>
|
||||
class RepeatGenerator final : public IGenerator<T> {
|
||||
static_assert(!std::is_same_v<T, bool>,
|
||||
static_assert(!std::is_same<T, bool>::value,
|
||||
"RepeatGenerator currently does not support bools"
|
||||
"because of std::vector<bool> specialization");
|
||||
GeneratorWrapper<T> m_generator;
|
||||
|
@@ -83,7 +83,7 @@ public:
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_integral_v<T>, GeneratorWrapper<T>>
|
||||
std::enable_if_t<std::is_integral<T>::value, GeneratorWrapper<T>>
|
||||
random(T a, T b) {
|
||||
return GeneratorWrapper<T>(
|
||||
Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b, Detail::getSeed())
|
||||
@@ -91,7 +91,7 @@ random(T a, T b) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_floating_point_v<T>,
|
||||
std::enable_if_t<std::is_floating_point<T>::value,
|
||||
GeneratorWrapper<T>>
|
||||
random(T a, T b) {
|
||||
return GeneratorWrapper<T>(
|
||||
|
@@ -52,20 +52,20 @@ public:
|
||||
|
||||
template <typename T>
|
||||
GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
|
||||
static_assert(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>, "Type must be numeric");
|
||||
static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "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_v<T> && !std::is_same_v<T, bool>, "Type must be an integer");
|
||||
static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "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_v<T, bool>,
|
||||
static_assert(!std::is_same<T, bool>::value,
|
||||
"IteratorGenerator currently does not support bools"
|
||||
"because of std::vector<bool> specialization");
|
||||
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#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>
|
||||
@@ -42,31 +43,30 @@ namespace Catch {
|
||||
virtual ~IResultCapture();
|
||||
|
||||
virtual void notifyAssertionStarted( AssertionInfo const& info ) = 0;
|
||||
virtual bool sectionStarted( std::string_view sectionName,
|
||||
virtual bool sectionStarted( StringRef sectionName,
|
||||
SourceLineInfo const& sectionLineInfo,
|
||||
Counts& assertions ) = 0;
|
||||
virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0;
|
||||
virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0;
|
||||
|
||||
virtual IGeneratorTracker*
|
||||
acquireGeneratorTracker( std::string_view generatorName,
|
||||
acquireGeneratorTracker( StringRef generatorName,
|
||||
SourceLineInfo const& lineInfo ) = 0;
|
||||
virtual IGeneratorTracker*
|
||||
createGeneratorTracker( std::string_view generatorName,
|
||||
createGeneratorTracker( StringRef generatorName,
|
||||
SourceLineInfo lineInfo,
|
||||
Generators::GeneratorBasePtr&& generator ) = 0;
|
||||
|
||||
virtual void benchmarkPreparing( std::string_view name ) = 0;
|
||||
virtual void benchmarkPreparing( StringRef name ) = 0;
|
||||
virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
|
||||
virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;
|
||||
virtual void benchmarkFailed( std::string_view error ) = 0;
|
||||
virtual void benchmarkFailed( StringRef error ) = 0;
|
||||
|
||||
virtual void pushScopedMessage( MessageInfo&& message ) = 0;
|
||||
virtual void popScopedMessage( unsigned int messageId ) = 0;
|
||||
static void pushScopedMessage( MessageInfo&& message );
|
||||
static void popScopedMessage( unsigned int messageId );
|
||||
static void emplaceUnscopedMessage( MessageBuilder&& builder );
|
||||
|
||||
virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0;
|
||||
|
||||
virtual void handleFatalErrorCondition( std::string_view message ) = 0;
|
||||
virtual void handleFatalErrorCondition( StringRef message ) = 0;
|
||||
|
||||
virtual void handleExpr
|
||||
( AssertionInfo const& info,
|
||||
@@ -101,6 +101,7 @@ namespace Catch {
|
||||
};
|
||||
|
||||
IResultCapture& getResultCapture();
|
||||
|
||||
}
|
||||
|
||||
#endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#define CATCH_INTERFACES_CONFIG_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_noncopyable.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
@@ -65,7 +66,7 @@ namespace Catch {
|
||||
virtual ~IConfig();
|
||||
|
||||
virtual bool allowThrows() const = 0;
|
||||
virtual std::string_view name() const = 0;
|
||||
virtual StringRef name() const = 0;
|
||||
virtual bool includeSuccessfulResults() const = 0;
|
||||
virtual bool shouldDebugBreak() const = 0;
|
||||
virtual bool warnAboutMissingAssertions() const = 0;
|
||||
|
@@ -8,19 +8,20 @@
|
||||
#ifndef CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
#define CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
|
||||
|
||||
#include <string_view>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace Detail {
|
||||
struct EnumInfo {
|
||||
std::string_view m_name;
|
||||
std::vector<std::pair<int, std::string_view>> m_values;
|
||||
StringRef m_name;
|
||||
std::vector<std::pair<int, StringRef>> m_values;
|
||||
|
||||
~EnumInfo();
|
||||
|
||||
std::string_view lookup( int value ) const;
|
||||
StringRef lookup( int value ) const;
|
||||
};
|
||||
} // namespace Detail
|
||||
|
||||
@@ -28,10 +29,10 @@ namespace Catch {
|
||||
public:
|
||||
virtual ~IMutableEnumValuesRegistry(); // = default;
|
||||
|
||||
virtual Detail::EnumInfo const& registerEnum( std::string_view enumName, std::string_view allEnums, std::vector<int> const& values ) = 0;
|
||||
virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
|
||||
|
||||
template<typename E>
|
||||
Detail::EnumInfo const& registerEnum( std::string_view enumName, std::string_view allEnums, std::initializer_list<E> values ) {
|
||||
Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
|
||||
static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
|
||||
std::vector<int> intValues;
|
||||
intValues.reserve( values.size() );
|
||||
|
@@ -21,7 +21,7 @@ namespace Catch {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string_view GeneratorUntypedBase::currentElementAsString() const {
|
||||
StringRef GeneratorUntypedBase::currentElementAsString() const {
|
||||
if ( m_stringReprCache.empty() ) {
|
||||
m_stringReprCache = stringifyImpl();
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#define CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_unique_ptr.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -70,7 +71,7 @@ namespace Catch {
|
||||
* is destructed, or it moves onto the next element, whichever
|
||||
* comes first.
|
||||
*/
|
||||
std::string_view currentElementAsString() const;
|
||||
StringRef currentElementAsString() const;
|
||||
};
|
||||
using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;
|
||||
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include <catch2/catch_totals.hpp>
|
||||
#include <catch2/catch_assertion_result.hpp>
|
||||
#include <catch2/internal/catch_message_info.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
#include <catch2/internal/catch_unique_ptr.hpp>
|
||||
#include <catch2/benchmark/detail/catch_benchmark_stats.hpp>
|
||||
|
||||
@@ -153,9 +154,9 @@ namespace Catch {
|
||||
}
|
||||
|
||||
//! Called when no test cases match provided test spec
|
||||
virtual void noMatchingTestCases( std::string_view unmatchedSpec ) = 0;
|
||||
virtual void noMatchingTestCases( StringRef unmatchedSpec ) = 0;
|
||||
//! Called for all invalid test specs from the cli
|
||||
virtual void reportInvalidTestSpec( std::string_view invalidArgument ) = 0;
|
||||
virtual void reportInvalidTestSpec( StringRef invalidArgument ) = 0;
|
||||
|
||||
/**
|
||||
* Called once in a testing run before tests are started
|
||||
@@ -172,13 +173,13 @@ namespace Catch {
|
||||
virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
|
||||
|
||||
//! Called when user-code is being probed before the actual benchmark runs
|
||||
virtual void benchmarkPreparing( std::string_view benchmarkName ) = 0;
|
||||
virtual void benchmarkPreparing( StringRef benchmarkName ) = 0;
|
||||
//! Called after probe but before the user-code is being benchmarked
|
||||
virtual void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) = 0;
|
||||
//! Called with the benchmark results if benchmark successfully finishes
|
||||
virtual void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) = 0;
|
||||
//! Called if running the benchmarks fails for any reason
|
||||
virtual void benchmarkFailed( std::string_view benchmarkName ) = 0;
|
||||
virtual void benchmarkFailed( StringRef benchmarkName ) = 0;
|
||||
|
||||
//! Called before assertion success/failure is evaluated
|
||||
virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
|
||||
@@ -208,7 +209,7 @@ namespace Catch {
|
||||
virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
|
||||
|
||||
//! Called if a fatal error (signal/structured exception) occurred
|
||||
virtual void fatalErrorEncountered( std::string_view error ) = 0;
|
||||
virtual void fatalErrorEncountered( StringRef error ) = 0;
|
||||
|
||||
//! Writes out information about provided reporters using reporter-specific format
|
||||
virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0;
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_unique_ptr.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -35,7 +36,7 @@ namespace Catch {
|
||||
virtual ~EventListenerFactory(); // = default
|
||||
virtual IEventListenerPtr create( IConfig const* config ) const = 0;
|
||||
//! Return a meaningful name for the listener, e.g. its type name
|
||||
virtual std::string_view getName() const = 0;
|
||||
virtual StringRef getName() const = 0;
|
||||
//! Return listener's description if available
|
||||
virtual std::string getDescription() const = 0;
|
||||
};
|
||||
|
@@ -15,9 +15,9 @@
|
||||
namespace Catch {
|
||||
|
||||
AssertionHandler::AssertionHandler
|
||||
( std::string_view macroName,
|
||||
( StringRef macroName,
|
||||
SourceLineInfo const& lineInfo,
|
||||
std::string_view capturedExpression,
|
||||
StringRef capturedExpression,
|
||||
ResultDisposition::Flags resultDisposition )
|
||||
: m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
|
||||
m_resultCapture( getResultCapture() )
|
||||
|
@@ -30,9 +30,9 @@ namespace Catch {
|
||||
|
||||
public:
|
||||
AssertionHandler
|
||||
( std::string_view macroName,
|
||||
( StringRef macroName,
|
||||
SourceLineInfo const& lineInfo,
|
||||
std::string_view capturedExpression,
|
||||
StringRef capturedExpression,
|
||||
ResultDisposition::Flags resultDisposition );
|
||||
~AssertionHandler() {
|
||||
if ( !m_completed ) {
|
||||
|
@@ -14,8 +14,8 @@
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
|
||||
bool CaseInsensitiveLess::operator()( std::string_view lhs,
|
||||
std::string_view rhs ) const {
|
||||
bool CaseInsensitiveLess::operator()( StringRef lhs,
|
||||
StringRef rhs ) const {
|
||||
return std::lexicographical_compare(
|
||||
lhs.begin(), lhs.end(),
|
||||
rhs.begin(), rhs.end(),
|
||||
@@ -23,8 +23,8 @@ namespace Catch {
|
||||
}
|
||||
|
||||
bool
|
||||
CaseInsensitiveEqualTo::operator()( std::string_view lhs,
|
||||
std::string_view rhs ) const {
|
||||
CaseInsensitiveEqualTo::operator()( StringRef lhs,
|
||||
StringRef rhs ) const {
|
||||
return std::equal(
|
||||
lhs.begin(), lhs.end(),
|
||||
rhs.begin(), rhs.end(),
|
||||
|
@@ -8,20 +8,20 @@
|
||||
#ifndef CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
|
||||
#define CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
|
||||
|
||||
#include <string_view>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
//! Provides case-insensitive `op<` semantics when called
|
||||
struct CaseInsensitiveLess {
|
||||
bool operator()( std::string_view lhs,
|
||||
std::string_view rhs ) const;
|
||||
bool operator()( StringRef lhs,
|
||||
StringRef rhs ) const;
|
||||
};
|
||||
|
||||
//! Provides case-insensitive `op==` semantics when called
|
||||
struct CaseInsensitiveEqualTo {
|
||||
bool operator()( std::string_view lhs,
|
||||
std::string_view rhs ) const;
|
||||
bool operator()( StringRef lhs,
|
||||
StringRef rhs ) const;
|
||||
};
|
||||
|
||||
} // namespace Detail
|
||||
|
@@ -25,7 +25,7 @@ namespace {
|
||||
;
|
||||
}
|
||||
|
||||
std::string_view normaliseOpt( std::string_view optName ) {
|
||||
Catch::StringRef normaliseOpt( Catch::StringRef optName ) {
|
||||
if ( optName[0] == '-'
|
||||
#if defined(CATCH_PLATFORM_WINDOWS)
|
||||
|| optName[0] == '/'
|
||||
@@ -37,7 +37,7 @@ namespace {
|
||||
return optName;
|
||||
}
|
||||
|
||||
static size_t find_first_separator(std::string_view sr) {
|
||||
static size_t find_first_separator(Catch::StringRef sr) {
|
||||
auto is_separator = []( char c ) {
|
||||
return c == ' ' || c == ':' || c == '=';
|
||||
};
|
||||
@@ -47,7 +47,7 @@ namespace {
|
||||
++pos;
|
||||
}
|
||||
|
||||
return std::string_view::npos;
|
||||
return Catch::StringRef::npos;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -65,10 +65,10 @@ namespace Catch {
|
||||
}
|
||||
|
||||
if ( it != itEnd ) {
|
||||
std::string_view next = *it;
|
||||
StringRef next = *it;
|
||||
if ( isOptPrefix( next[0] ) ) {
|
||||
auto delimiterPos = find_first_separator(next);
|
||||
if ( delimiterPos != std::string_view::npos ) {
|
||||
if ( delimiterPos != StringRef::npos ) {
|
||||
m_tokenBuffer.push_back(
|
||||
{ TokenType::Option,
|
||||
next.substr( 0, delimiterPos ) } );
|
||||
@@ -205,7 +205,7 @@ namespace Catch {
|
||||
return { oss.str(), m_description };
|
||||
}
|
||||
|
||||
bool Opt::isMatch(std::string_view optToken) const {
|
||||
bool Opt::isMatch(StringRef optToken) const {
|
||||
auto normalisedToken = normaliseOpt(optToken);
|
||||
for (auto const& name : m_optNames) {
|
||||
if (normaliseOpt(name) == normalisedToken)
|
||||
@@ -243,12 +243,12 @@ namespace Catch {
|
||||
if (!tokens)
|
||||
return Detail::InternalParseResult::runtimeError(
|
||||
"Expected argument following " +
|
||||
std::string(token.token));
|
||||
token.token);
|
||||
auto const& argToken = *tokens;
|
||||
if (argToken.type != Detail::TokenType::Argument)
|
||||
return Detail::InternalParseResult::runtimeError(
|
||||
"Expected argument following " +
|
||||
std::string(token.token));
|
||||
token.token);
|
||||
const auto result = valueRef->setValue(static_cast<std::string>(argToken.token));
|
||||
if (!result)
|
||||
return Detail::InternalParseResult(result);
|
||||
@@ -436,7 +436,7 @@ namespace Catch {
|
||||
if ( !tokenParsed )
|
||||
return Detail::InternalParseResult::runtimeError(
|
||||
"Unrecognised token: " +
|
||||
std::string(result.value().remainingTokens()->token) );
|
||||
result.value().remainingTokens()->token );
|
||||
}
|
||||
// !TBD Check missing required options
|
||||
return result;
|
||||
@@ -445,7 +445,7 @@ namespace Catch {
|
||||
Args::Args(int argc, char const* const* argv) :
|
||||
m_exeName(argv[0]), m_args(argv + 1, argv + argc) {}
|
||||
|
||||
Args::Args(std::initializer_list<std::string_view> args) :
|
||||
Args::Args(std::initializer_list<StringRef> args) :
|
||||
m_exeName(*args.begin()),
|
||||
m_args(args.begin() + 1, args.end()) {}
|
||||
|
||||
|
@@ -20,8 +20,16 @@
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#include <optional>
|
||||
#ifndef CLARA_CONFIG_OPTIONAL_TYPE
|
||||
# ifdef __has_include
|
||||
# if __has_include( <optional>) && __cplusplus >= 201703L
|
||||
# include <optional>
|
||||
# define CLARA_CONFIG_OPTIONAL_TYPE std::optional
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
#include <catch2/internal/catch_noncopyable.hpp>
|
||||
#include <catch2/internal/catch_void_type.hpp>
|
||||
@@ -92,13 +100,13 @@ namespace Catch {
|
||||
enum class TokenType { Option, Argument };
|
||||
struct Token {
|
||||
TokenType type;
|
||||
std::string_view token;
|
||||
StringRef token;
|
||||
};
|
||||
|
||||
// Abstracts iterators into args as a stream of tokens, with option
|
||||
// arguments uniformly handled
|
||||
class TokenStream {
|
||||
using Iterator = std::vector<std::string_view>::const_iterator;
|
||||
using Iterator = std::vector<StringRef>::const_iterator;
|
||||
Iterator it;
|
||||
Iterator itEnd;
|
||||
std::vector<Token> m_tokenBuffer;
|
||||
@@ -301,7 +309,7 @@ namespace Catch {
|
||||
|
||||
struct HelpColumns {
|
||||
std::string left;
|
||||
std::string_view descriptions;
|
||||
StringRef descriptions;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -320,9 +328,10 @@ namespace Catch {
|
||||
std::string& target );
|
||||
ParserResult convertInto( std::string const& source, bool& target );
|
||||
|
||||
#ifdef CLARA_CONFIG_OPTIONAL_TYPE
|
||||
template <typename T>
|
||||
auto convertInto( std::string const& source,
|
||||
std::optional<T>& target )
|
||||
CLARA_CONFIG_OPTIONAL_TYPE<T>& target )
|
||||
-> ParserResult {
|
||||
T temp;
|
||||
auto result = convertInto( source, temp );
|
||||
@@ -330,6 +339,7 @@ namespace Catch {
|
||||
target = CATCH_MOVE( temp );
|
||||
return result;
|
||||
}
|
||||
#endif // CLARA_CONFIG_OPTIONAL_TYPE
|
||||
|
||||
struct BoundRef : Catch::Detail::NonCopyable {
|
||||
virtual ~BoundRef() = default;
|
||||
@@ -383,7 +393,7 @@ namespace Catch {
|
||||
|
||||
template <typename ReturnType> struct LambdaInvoker {
|
||||
static_assert(
|
||||
std::is_same_v<ReturnType, ParserResult>,
|
||||
std::is_same<ReturnType, ParserResult>::value,
|
||||
"Lambda must return void or clara::ParserResult" );
|
||||
|
||||
template <typename L, typename ArgType>
|
||||
@@ -439,8 +449,8 @@ namespace Catch {
|
||||
UnaryLambdaTraits<L>::isValid,
|
||||
"Supplied lambda must take exactly one argument" );
|
||||
static_assert(
|
||||
std::is_same_v<typename UnaryLambdaTraits<L>::ArgType,
|
||||
bool>,
|
||||
std::is_same<typename UnaryLambdaTraits<L>::ArgType,
|
||||
bool>::value,
|
||||
"flags must be boolean" );
|
||||
|
||||
explicit BoundFlagLambda( L const& lambda ):
|
||||
@@ -479,8 +489,8 @@ namespace Catch {
|
||||
protected:
|
||||
Optionality m_optionality = Optionality::Optional;
|
||||
std::shared_ptr<BoundRef> m_ref;
|
||||
std::string_view m_hint;
|
||||
std::string_view m_description;
|
||||
StringRef m_hint;
|
||||
StringRef m_description;
|
||||
|
||||
explicit ParserRefImpl( std::shared_ptr<BoundRef> const& ref ):
|
||||
m_ref( ref ) {}
|
||||
@@ -489,29 +499,29 @@ namespace Catch {
|
||||
template <typename LambdaT>
|
||||
ParserRefImpl( accept_many_t,
|
||||
LambdaT const& ref,
|
||||
std::string_view hint ):
|
||||
StringRef hint ):
|
||||
m_ref( std::make_shared<BoundManyLambda<LambdaT>>( ref ) ),
|
||||
m_hint( hint ) {}
|
||||
|
||||
template <typename T,
|
||||
typename = typename std::enable_if_t<
|
||||
!Detail::is_unary_function_v<T>>>
|
||||
ParserRefImpl( T& ref, std::string_view hint ):
|
||||
ParserRefImpl( T& ref, StringRef hint ):
|
||||
m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
|
||||
m_hint( hint ) {}
|
||||
|
||||
template <typename LambdaT,
|
||||
typename = typename std::enable_if_t<
|
||||
Detail::is_unary_function_v<LambdaT>>>
|
||||
ParserRefImpl( LambdaT const& ref, std::string_view hint ):
|
||||
ParserRefImpl( LambdaT const& ref, StringRef hint ):
|
||||
m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
|
||||
m_hint( hint ) {}
|
||||
|
||||
DerivedT& operator()( std::string_view description ) & {
|
||||
DerivedT& operator()( StringRef description ) & {
|
||||
m_description = description;
|
||||
return static_cast<DerivedT&>( *this );
|
||||
}
|
||||
DerivedT&& operator()( std::string_view description ) && {
|
||||
DerivedT&& operator()( StringRef description ) && {
|
||||
m_description = description;
|
||||
return static_cast<DerivedT&&>( *this );
|
||||
}
|
||||
@@ -537,7 +547,7 @@ namespace Catch {
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string_view hint() const { return m_hint; }
|
||||
StringRef hint() const { return m_hint; }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
@@ -557,7 +567,7 @@ namespace Catch {
|
||||
// A parser for options
|
||||
class Opt : public Detail::ParserRefImpl<Opt> {
|
||||
protected:
|
||||
std::vector<std::string_view> m_optNames;
|
||||
std::vector<StringRef> m_optNames;
|
||||
|
||||
public:
|
||||
template <typename LambdaT>
|
||||
@@ -570,31 +580,31 @@ namespace Catch {
|
||||
template <typename LambdaT,
|
||||
typename = typename std::enable_if_t<
|
||||
Detail::is_unary_function_v<LambdaT>>>
|
||||
Opt( LambdaT const& ref, std::string_view hint ):
|
||||
Opt( LambdaT const& ref, StringRef hint ):
|
||||
ParserRefImpl( ref, hint ) {}
|
||||
|
||||
template <typename LambdaT>
|
||||
Opt( accept_many_t, LambdaT const& ref, std::string_view hint ):
|
||||
Opt( accept_many_t, LambdaT const& ref, StringRef hint ):
|
||||
ParserRefImpl( accept_many, ref, hint ) {}
|
||||
|
||||
template <typename T,
|
||||
typename = typename std::enable_if_t<
|
||||
!Detail::is_unary_function_v<T>>>
|
||||
Opt( T& ref, std::string_view hint ):
|
||||
Opt( T& ref, StringRef hint ):
|
||||
ParserRefImpl( ref, hint ) {}
|
||||
|
||||
Opt& operator[]( std::string_view optName ) & {
|
||||
Opt& operator[]( StringRef optName ) & {
|
||||
m_optNames.push_back(optName);
|
||||
return *this;
|
||||
}
|
||||
Opt&& operator[]( std::string_view optName ) && {
|
||||
Opt&& operator[]( StringRef optName ) && {
|
||||
m_optNames.push_back( optName );
|
||||
return CATCH_MOVE(*this);
|
||||
}
|
||||
|
||||
Detail::HelpColumns getHelpColumns() const;
|
||||
|
||||
bool isMatch(std::string_view optToken) const;
|
||||
bool isMatch(StringRef optToken) const;
|
||||
|
||||
using ParserBase::parse;
|
||||
|
||||
@@ -695,15 +705,15 @@ namespace Catch {
|
||||
*/
|
||||
class Args {
|
||||
friend Detail::TokenStream;
|
||||
std::string_view m_exeName;
|
||||
std::vector<std::string_view> m_args;
|
||||
StringRef m_exeName;
|
||||
std::vector<StringRef> m_args;
|
||||
|
||||
public:
|
||||
Args(int argc, char const* const* argv);
|
||||
// Helper constructor for testing
|
||||
Args(std::initializer_list<std::string_view> args);
|
||||
Args(std::initializer_list<StringRef> args);
|
||||
|
||||
std::string_view exeName() const { return m_exeName; }
|
||||
StringRef exeName() const { return m_exeName; }
|
||||
};
|
||||
|
||||
|
||||
|
@@ -88,7 +88,7 @@ namespace Catch {
|
||||
return ParserResult::ok( ParseResultType::Matched );
|
||||
};
|
||||
auto const setDefaultColourMode = [&]( std::string const& colourMode ) {
|
||||
std::optional<ColourMode> maybeMode = Catch::Detail::stringToColourMode(toLower( colourMode ));
|
||||
Optional<ColourMode> maybeMode = Catch::Detail::stringToColourMode(toLower( colourMode ));
|
||||
if ( !maybeMode ) {
|
||||
return ParserResult::runtimeError(
|
||||
"colour mode must be one of: default, ansi, win32, "
|
||||
@@ -135,7 +135,7 @@ namespace Catch {
|
||||
return ParserResult::runtimeError( "Received empty reporter spec." );
|
||||
}
|
||||
|
||||
std::optional<ReporterSpec> parsed =
|
||||
Optional<ReporterSpec> parsed =
|
||||
parseReporterSpec( userReporterSpec );
|
||||
if ( !parsed ) {
|
||||
return ParserResult::runtimeError(
|
||||
@@ -156,7 +156,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
|
||||
const bool hadOutputFile = reporterSpec.outputFile().has_value();
|
||||
const bool hadOutputFile = reporterSpec.outputFile().some();
|
||||
config.reporterSpecifications.push_back( CATCH_MOVE( *parsed ) );
|
||||
// It would be enough to check this only once at the very end, but
|
||||
// there is not a place where we could call this check, so do it
|
||||
@@ -165,7 +165,7 @@ namespace Catch {
|
||||
if (!hadOutputFile) {
|
||||
int n_reporters_without_file = 0;
|
||||
for (auto const& spec : config.reporterSpecifications) {
|
||||
if (!spec.outputFile()) {
|
||||
if (spec.outputFile().none()) {
|
||||
n_reporters_without_file++;
|
||||
}
|
||||
}
|
||||
@@ -305,6 +305,9 @@ namespace Catch {
|
||||
| Opt( config.allowZeroTests )
|
||||
["--allow-running-no-tests"]
|
||||
( "Treat 'No tests run' as a success" )
|
||||
| Opt( config.prematureExitGuardFilePath, "path" )
|
||||
["--premature-exit-guard-file"]
|
||||
( "create a file before running tests and delete it during clean exit" )
|
||||
| Arg( config.testsOrTags, "test name|pattern|tags" )
|
||||
( "which test or tests to use" );
|
||||
|
||||
|
@@ -29,6 +29,10 @@
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
||||
# define CATCH_CPP17_OR_GREATER
|
||||
# endif
|
||||
|
||||
# if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||
# define CATCH_CPP20_OR_GREATER
|
||||
# endif
|
||||
@@ -194,7 +198,8 @@
|
||||
# define _BSD_SOURCE
|
||||
// some versions of cygwin (most) do not support std::to_string. Use the libstd check.
|
||||
// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
|
||||
# if !(defined(_GLIBCXX_USE_C99) && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
|
||||
# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
|
||||
&& !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
|
||||
|
||||
# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
|
||||
|
||||
@@ -270,6 +275,43 @@
|
||||
#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
|
||||
#endif
|
||||
|
||||
// Various stdlib support checks that require __has_include
|
||||
#if defined(__has_include)
|
||||
// Check if string_view is available and usable
|
||||
#if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
|
||||
#endif
|
||||
|
||||
// Check if optional is available and usable
|
||||
# if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
|
||||
# endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
|
||||
// Check if byte is available and usable
|
||||
# if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
# include <cstddef>
|
||||
# if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE
|
||||
# endif
|
||||
# endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
|
||||
// Check if variant is available and usable
|
||||
# if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
# if defined(__clang__) && (__clang_major__ < 8)
|
||||
// work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
|
||||
// fix should be in clang 8, workaround in libstdc++ 8.2
|
||||
# include <ciso646>
|
||||
# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
|
||||
# define CATCH_CONFIG_NO_CPP17_VARIANT
|
||||
# else
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
|
||||
# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
|
||||
# else
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
|
||||
# endif // defined(__clang__) && (__clang_major__ < 8)
|
||||
# endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
|
||||
#endif // defined(__has_include)
|
||||
|
||||
|
||||
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
|
||||
# define CATCH_CONFIG_WINDOWS_SEH
|
||||
@@ -287,6 +329,22 @@
|
||||
# define CATCH_CONFIG_CPP11_TO_STRING
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
|
||||
# define CATCH_CONFIG_CPP17_OPTIONAL
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
|
||||
# define CATCH_CONFIG_CPP17_STRING_VIEW
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
|
||||
# define CATCH_CONFIG_CPP17_VARIANT
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE)
|
||||
# define CATCH_CONFIG_CPP17_BYTE
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
|
||||
# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
|
||||
|
46
src/catch2/internal/catch_config_uncaught_exceptions.hpp
Normal file
46
src/catch2/internal/catch_config_uncaught_exceptions.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
// 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
|
||||
* Wrapper for UNCAUGHT_EXCEPTIONS configuration option
|
||||
*
|
||||
* For some functionality, Catch2 requires to know whether there is
|
||||
* an active exception. Because `std::uncaught_exception` is deprecated
|
||||
* in C++17, we want to use `std::uncaught_exceptions` if possible.
|
||||
*/
|
||||
|
||||
#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
|
||||
#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
|
||||
|
||||
#include <catch2/catch_user_config.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#include <exception>
|
||||
|
||||
#if defined(__cpp_lib_uncaught_exceptions) \
|
||||
&& !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
|
||||
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||
#endif // __cpp_lib_uncaught_exceptions
|
||||
|
||||
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \
|
||||
&& !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \
|
||||
&& !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
|
||||
|
||||
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
|
||||
#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
|
@@ -161,7 +161,11 @@ namespace {
|
||||
#endif // Windows/ ANSI/ None
|
||||
|
||||
|
||||
#if defined( CATCH_PLATFORM_LINUX ) || defined( CATCH_PLATFORM_MAC ) || defined( __GLIBC__ ) || defined(__FreeBSD__)
|
||||
#if defined( CATCH_PLATFORM_LINUX ) \
|
||||
|| defined( CATCH_PLATFORM_MAC ) \
|
||||
|| defined( __GLIBC__ ) \
|
||||
|| defined( __FreeBSD__ ) \
|
||||
|| defined( CATCH_PLATFORM_QNX )
|
||||
# define CATCH_INTERNAL_HAS_ISATTY
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
73
src/catch2/internal/catch_container_nonmembers.hpp
Normal file
73
src/catch2/internal/catch_container_nonmembers.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
|
||||
// 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_CONTAINER_NONMEMBERS_HPP_INCLUDED
|
||||
#define CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_compiler_capabilities.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
|
||||
// We want a simple polyfill over `std::empty`, `std::size` and so on
|
||||
// for C++14 or C++ libraries with incomplete support.
|
||||
// We also have to handle that MSVC std lib will happily provide these
|
||||
// under older standards.
|
||||
#if defined(CATCH_CPP17_OR_GREATER) || defined(_MSC_VER)
|
||||
|
||||
// We are already using this header either way, so there shouldn't
|
||||
// be much additional overhead in including it to get the feature
|
||||
// test macros
|
||||
#include <string>
|
||||
|
||||
# if !defined(__cpp_lib_nonmember_container_access)
|
||||
# define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
|
||||
# endif
|
||||
|
||||
#else
|
||||
#define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
|
||||
#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
|
||||
template <typename Container>
|
||||
constexpr auto empty(Container const& cont) -> decltype(cont.empty()) {
|
||||
return cont.empty();
|
||||
}
|
||||
template <typename T, std::size_t N>
|
||||
constexpr bool empty(const T (&)[N]) noexcept {
|
||||
// GCC < 7 does not support the const T(&)[] parameter syntax
|
||||
// so we have to ignore the length explicitly
|
||||
(void)N;
|
||||
return false;
|
||||
}
|
||||
template <typename T>
|
||||
constexpr bool empty(std::initializer_list<T> list) noexcept {
|
||||
return list.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
constexpr auto size(Container const& cont) -> decltype(cont.size()) {
|
||||
return cont.size();
|
||||
}
|
||||
template <typename T, std::size_t N>
|
||||
constexpr std::size_t size(const T(&)[N]) noexcept {
|
||||
return N;
|
||||
}
|
||||
#endif // CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
|
||||
|
||||
} // end namespace Detail
|
||||
} // end namespace Catch
|
||||
|
||||
|
||||
|
||||
#endif // CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
|
@@ -69,7 +69,7 @@
|
||||
#endif
|
||||
} // namespace Catch
|
||||
|
||||
#elif defined(CATCH_PLATFORM_LINUX)
|
||||
#elif defined(CATCH_PLATFORM_LINUX) || defined(CATCH_PLATFORM_QNX)
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
|
@@ -49,7 +49,7 @@ namespace Catch {
|
||||
#define CATCH_TRAP() __asm__(".inst 0xde01")
|
||||
#endif
|
||||
|
||||
#elif defined(CATCH_PLATFORM_LINUX)
|
||||
#elif defined(CATCH_PLATFORM_LINUX) || defined(CATCH_PLATFORM_QNX)
|
||||
// If we can use inline assembler, do it because this allows us to break
|
||||
// directly at the location of the failing check instead of breaking inside
|
||||
// raise() called from it, i.e. one stack frame below.
|
||||
|
@@ -17,7 +17,7 @@ namespace Catch {
|
||||
os << "Some class derived from ITransientExpression without overriding streamReconstructedExpression";
|
||||
}
|
||||
|
||||
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string_view op, std::string const& rhs ) {
|
||||
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
|
||||
if( lhs.size() + rhs.size() < 40 &&
|
||||
lhs.find('\n') == std::string::npos &&
|
||||
rhs.find('\n') == std::string::npos )
|
||||
|
@@ -9,8 +9,10 @@
|
||||
#define CATCH_DECOMPOSER_HPP_INCLUDED
|
||||
|
||||
#include <catch2/catch_tostring.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
#include <catch2/internal/catch_compare_traits.hpp>
|
||||
#include <catch2/internal/catch_test_failure_exception.hpp>
|
||||
#include <catch2/internal/catch_logical_traits.hpp>
|
||||
#include <catch2/internal/catch_compiler_capabilities.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
@@ -127,7 +129,7 @@
|
||||
namespace Catch {
|
||||
|
||||
namespace Detail {
|
||||
// This was added in C++20, but we require only C++17 for now.
|
||||
// This was added in C++20, but we require only C++14 for now.
|
||||
template <typename T>
|
||||
using RemoveCVRef_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
}
|
||||
@@ -146,8 +148,8 @@ namespace Catch {
|
||||
template <typename T>
|
||||
struct capture_by_value
|
||||
: std::integral_constant<bool,
|
||||
std::is_arithmetic_v<T> ||
|
||||
std::is_enum_v<T>> {};
|
||||
std::is_arithmetic<T>::value ||
|
||||
std::is_enum<T>::value> {};
|
||||
|
||||
#if defined( CATCH_CONFIG_CPP20_COMPARE_OVERLOADS )
|
||||
template <>
|
||||
@@ -188,12 +190,12 @@ namespace Catch {
|
||||
}
|
||||
};
|
||||
|
||||
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string_view op, std::string const& rhs );
|
||||
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
|
||||
|
||||
template<typename LhsT, typename RhsT>
|
||||
class BinaryExpr : public ITransientExpression {
|
||||
LhsT m_lhs;
|
||||
std::string_view m_op;
|
||||
StringRef m_op;
|
||||
RhsT m_rhs;
|
||||
|
||||
void streamReconstructedExpression( std::ostream &os ) const override {
|
||||
@@ -202,7 +204,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr BinaryExpr( bool comparisonResult, LhsT lhs, std::string_view op, RhsT rhs )
|
||||
constexpr BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
|
||||
: ITransientExpression{ true, comparisonResult },
|
||||
m_lhs( lhs ),
|
||||
m_op( op ),
|
||||
@@ -292,48 +294,48 @@ namespace Catch {
|
||||
template <typename RhsT> \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
|
||||
-> std::enable_if_t< \
|
||||
std::conjunction_v<Detail::is_##id##_comparable<LhsT, RhsT>, \
|
||||
std::negation<capture_by_value< \
|
||||
Detail::RemoveCVRef_t<RhsT>>>>, \
|
||||
Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
|
||||
Detail::negation<capture_by_value< \
|
||||
Detail::RemoveCVRef_t<RhsT>>>>::value, \
|
||||
BinaryExpr<LhsT, RhsT const&>> { \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op, rhs }; \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
-> std::enable_if_t< \
|
||||
std::conjunction_v<Detail::is_##id##_comparable<LhsT, RhsT>, \
|
||||
capture_by_value<RhsT>>, \
|
||||
Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
|
||||
capture_by_value<RhsT>>::value, \
|
||||
BinaryExpr<LhsT, RhsT>> { \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op, rhs }; \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
-> std::enable_if_t< \
|
||||
std::conjunction_v< \
|
||||
std::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
|
||||
Detail::conjunction< \
|
||||
Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
|
||||
Detail::is_eq_0_comparable<LhsT>, \
|
||||
/* We allow long because we want `ptr op NULL` to be accepted */ \
|
||||
std::disjunction<std::is_same<RhsT, int>, \
|
||||
std::is_same<RhsT, long>>>, \
|
||||
Detail::disjunction<std::is_same<RhsT, int>, \
|
||||
std::is_same<RhsT, long>>>::value, \
|
||||
BinaryExpr<LhsT, RhsT>> { \
|
||||
if ( rhs != 0 ) { throw_test_failure_exception(); } \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op, rhs }; \
|
||||
static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
-> std::enable_if_t< \
|
||||
std::conjunction_v< \
|
||||
std::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
|
||||
Detail::conjunction< \
|
||||
Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
|
||||
Detail::is_eq_0_comparable<RhsT>, \
|
||||
/* We allow long because we want `ptr op NULL` to be accepted */ \
|
||||
std::disjunction<std::is_same<LhsT, int>, \
|
||||
std::is_same<LhsT, long>>>, \
|
||||
Detail::disjunction<std::is_same<LhsT, int>, \
|
||||
std::is_same<LhsT, long>>>::value, \
|
||||
BinaryExpr<LhsT, RhsT>> { \
|
||||
if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \
|
||||
return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op, rhs }; \
|
||||
return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
}
|
||||
|
||||
CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( eq, == )
|
||||
@@ -346,44 +348,44 @@ namespace Catch {
|
||||
template <typename RhsT> \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
|
||||
-> std::enable_if_t< \
|
||||
std::conjunction_v<Detail::is_##id##_comparable<LhsT, RhsT>, \
|
||||
std::negation<capture_by_value< \
|
||||
Detail::RemoveCVRef_t<RhsT>>>>, \
|
||||
Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
|
||||
Detail::negation<capture_by_value< \
|
||||
Detail::RemoveCVRef_t<RhsT>>>>::value, \
|
||||
BinaryExpr<LhsT, RhsT const&>> { \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op, rhs }; \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
-> std::enable_if_t< \
|
||||
std::conjunction_v<Detail::is_##id##_comparable<LhsT, RhsT>, \
|
||||
capture_by_value<RhsT>> , \
|
||||
Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
|
||||
capture_by_value<RhsT>>::value, \
|
||||
BinaryExpr<LhsT, RhsT>> { \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op, rhs }; \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
-> std::enable_if_t< \
|
||||
std::conjunction_v< \
|
||||
std::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
|
||||
Detail::conjunction< \
|
||||
Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
|
||||
Detail::is_##id##_0_comparable<LhsT>, \
|
||||
std::is_same<RhsT, int>>, \
|
||||
std::is_same<RhsT, int>>::value, \
|
||||
BinaryExpr<LhsT, RhsT>> { \
|
||||
if ( rhs != 0 ) { throw_test_failure_exception(); } \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op, rhs }; \
|
||||
static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
-> std::enable_if_t< \
|
||||
std::conjunction_v< \
|
||||
std::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
|
||||
Detail::conjunction< \
|
||||
Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
|
||||
Detail::is_##id##_0_comparable<RhsT>, \
|
||||
std::is_same<LhsT, int>>, \
|
||||
std::is_same<LhsT, int>>::value, \
|
||||
BinaryExpr<LhsT, RhsT>> { \
|
||||
if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \
|
||||
return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op, rhs }; \
|
||||
return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
}
|
||||
|
||||
CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( lt, < )
|
||||
@@ -401,14 +403,14 @@ namespace Catch {
|
||||
!capture_by_value<Detail::RemoveCVRef_t<RhsT>>::value, \
|
||||
BinaryExpr<LhsT, RhsT const&>> { \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op, rhs }; \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
-> std::enable_if_t<capture_by_value<RhsT>::value, \
|
||||
BinaryExpr<LhsT, RhsT>> { \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op, rhs }; \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
}
|
||||
|
||||
CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(|)
|
||||
|
@@ -19,7 +19,7 @@ namespace Catch {
|
||||
namespace {
|
||||
// Extracts the actual name part of an enum instance
|
||||
// In other words, it returns the Blue part of Bikeshed::Colour::Blue
|
||||
std::string_view extractInstanceName(std::string_view enumInstance) {
|
||||
StringRef extractInstanceName(StringRef enumInstance) {
|
||||
// Find last occurrence of ":"
|
||||
size_t name_start = enumInstance.size();
|
||||
while (name_start > 0 && enumInstance[name_start - 1] != ':') {
|
||||
@@ -29,9 +29,9 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string_view> parseEnums( std::string_view enums ) {
|
||||
std::vector<StringRef> parseEnums( StringRef enums ) {
|
||||
auto enumValues = splitStringRef( enums, ',' );
|
||||
std::vector<std::string_view> parsed;
|
||||
std::vector<StringRef> parsed;
|
||||
parsed.reserve( enumValues.size() );
|
||||
for( auto const& enumValue : enumValues ) {
|
||||
parsed.push_back(trim(extractInstanceName(enumValue)));
|
||||
@@ -41,15 +41,15 @@ namespace Catch {
|
||||
|
||||
EnumInfo::~EnumInfo() = default;
|
||||
|
||||
std::string_view EnumInfo::lookup( int value ) const {
|
||||
StringRef EnumInfo::lookup( int value ) const {
|
||||
for( auto const& valueToName : m_values ) {
|
||||
if( valueToName.first == value )
|
||||
return valueToName.second;
|
||||
}
|
||||
return "{** unexpected enum value **}";
|
||||
return "{** unexpected enum value **}"_sr;
|
||||
}
|
||||
|
||||
Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( std::string_view enumName, std::string_view allValueNames, std::vector<int> const& values ) {
|
||||
Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
|
||||
auto enumInfo = Catch::Detail::make_unique<EnumInfo>();
|
||||
enumInfo->m_name = enumName;
|
||||
enumInfo->m_values.reserve( values.size() );
|
||||
@@ -63,10 +63,11 @@ namespace Catch {
|
||||
return enumInfo;
|
||||
}
|
||||
|
||||
EnumInfo const& EnumValuesRegistry::registerEnum( std::string_view enumName, std::string_view allValueNames, std::vector<int> const& values ) {
|
||||
EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
|
||||
m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));
|
||||
return *m_enumInfos.back();
|
||||
}
|
||||
|
||||
} // Detail
|
||||
} // Catch
|
||||
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <catch2/interfaces/catch_interfaces_enum_values_registry.hpp>
|
||||
#include <catch2/internal/catch_unique_ptr.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -17,16 +18,16 @@ namespace Catch {
|
||||
|
||||
namespace Detail {
|
||||
|
||||
Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( std::string_view enumName, std::string_view allValueNames, std::vector<int> const& values );
|
||||
Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values );
|
||||
|
||||
class EnumValuesRegistry : public IMutableEnumValuesRegistry {
|
||||
|
||||
std::vector<Catch::Detail::unique_ptr<EnumInfo>> m_enumInfos;
|
||||
|
||||
EnumInfo const& registerEnum( std::string_view enumName, std::string_view allValueNames, std::vector<int> const& values) override;
|
||||
EnumInfo const& registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values) override;
|
||||
};
|
||||
|
||||
std::vector<std::string_view> parseEnums( std::string_view enums );
|
||||
std::vector<StringRef> parseEnums( StringRef enums );
|
||||
|
||||
} // Detail
|
||||
|
||||
|
@@ -49,7 +49,7 @@ namespace Catch {
|
||||
|
||||
template <typename ForwardIter, typename Sentinel>
|
||||
constexpr
|
||||
std::enable_if_t<!std::is_same_v<ForwardIter, Sentinel>,
|
||||
std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value,
|
||||
std::ptrdiff_t>
|
||||
sentinel_distance( ForwardIter iter, const Sentinel sentinel ) {
|
||||
std::ptrdiff_t dist = 0;
|
||||
|
@@ -17,21 +17,21 @@ namespace Catch {
|
||||
c == '\n' || c == '\r' || c == '\t';
|
||||
}
|
||||
|
||||
static std::string_view makeEscapeStringRef( char c ) {
|
||||
static Catch::StringRef makeEscapeStringRef( char c ) {
|
||||
if ( c == '"' ) {
|
||||
return "\\\"";
|
||||
return "\\\""_sr;
|
||||
} else if ( c == '\\' ) {
|
||||
return "\\\\";
|
||||
return "\\\\"_sr;
|
||||
} else if ( c == '\b' ) {
|
||||
return "\\b";
|
||||
return "\\b"_sr;
|
||||
} else if ( c == '\f' ) {
|
||||
return "\\f";
|
||||
return "\\f"_sr;
|
||||
} else if ( c == '\n' ) {
|
||||
return "\\n";
|
||||
return "\\n"_sr;
|
||||
} else if ( c == '\r' ) {
|
||||
return "\\r";
|
||||
return "\\r"_sr;
|
||||
} else if ( c == '\t' ) {
|
||||
return "\\t";
|
||||
return "\\t"_sr;
|
||||
}
|
||||
Catch::Detail::Unreachable();
|
||||
}
|
||||
@@ -75,7 +75,7 @@ namespace Catch {
|
||||
m_os << '}';
|
||||
}
|
||||
|
||||
JsonValueWriter JsonObjectWriter::write( std::string_view key ) {
|
||||
JsonValueWriter JsonObjectWriter::write( StringRef key ) {
|
||||
JsonUtils::appendCommaNewline(
|
||||
m_os, m_should_comma, m_indent_level + 1 );
|
||||
|
||||
@@ -136,15 +136,15 @@ namespace Catch {
|
||||
return JsonArrayWriter{ m_os, m_indent_level };
|
||||
}
|
||||
|
||||
void JsonValueWriter::write( std::string_view value ) && {
|
||||
void JsonValueWriter::write( Catch::StringRef value ) && {
|
||||
writeImpl( value, true );
|
||||
}
|
||||
|
||||
void JsonValueWriter::write( bool value ) && {
|
||||
writeImpl( value ? "true" : "false", false );
|
||||
writeImpl( value ? "true"_sr : "false"_sr, false );
|
||||
}
|
||||
|
||||
void JsonValueWriter::writeImpl( std::string_view value, bool quote ) {
|
||||
void JsonValueWriter::writeImpl( Catch::StringRef value, bool quote ) {
|
||||
if ( quote ) { m_os << '"'; }
|
||||
size_t current_start = 0;
|
||||
for ( size_t i = 0; i < value.size(); ++i ) {
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#define CATCH_JSONWRITER_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_reusable_string_stream.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
@@ -34,13 +35,13 @@ namespace Catch {
|
||||
|
||||
template <typename T>
|
||||
void write( T const& value ) && {
|
||||
writeImpl( value, !std::is_arithmetic_v<T> );
|
||||
writeImpl( value, !std::is_arithmetic<T>::value );
|
||||
}
|
||||
void write( std::string_view value ) &&;
|
||||
void write( StringRef value ) &&;
|
||||
void write( bool value ) &&;
|
||||
|
||||
private:
|
||||
void writeImpl( std::string_view value, bool quote );
|
||||
void writeImpl( StringRef value, bool quote );
|
||||
|
||||
// Without this SFINAE, this overload is a better match
|
||||
// for `std::string`, `char const*`, `char const[N]` args.
|
||||
@@ -48,7 +49,7 @@ namespace Catch {
|
||||
// and multiple iteration over the strings
|
||||
template <typename T,
|
||||
typename = typename std::enable_if_t<
|
||||
!std::is_convertible_v<T, std::string_view>>>
|
||||
!std::is_convertible<T, StringRef>::value>>
|
||||
void writeImpl( T const& value, bool quote_value ) {
|
||||
m_sstream << value;
|
||||
writeImpl( m_sstream.str(), quote_value );
|
||||
@@ -69,7 +70,7 @@ namespace Catch {
|
||||
|
||||
~JsonObjectWriter();
|
||||
|
||||
JsonValueWriter write( std::string_view key );
|
||||
JsonValueWriter write( StringRef key );
|
||||
|
||||
private:
|
||||
std::ostream& m_os;
|
||||
|
@@ -30,7 +30,7 @@ namespace Catch {
|
||||
auto const& testSpec = config.testSpec();
|
||||
std::vector<TestCaseHandle> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
|
||||
|
||||
std::map<std::string_view, TagInfo, Detail::CaseInsensitiveLess> tagCounts;
|
||||
std::map<StringRef, TagInfo, Detail::CaseInsensitiveLess> tagCounts;
|
||||
for (auto const& testCase : matchedTestCases) {
|
||||
for (auto const& tagName : testCase.getTestCaseInfo().tags) {
|
||||
auto it = tagCounts.find(tagName.original);
|
||||
@@ -75,7 +75,7 @@ namespace Catch {
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
void TagInfo::add( std::string_view spelling ) {
|
||||
void TagInfo::add( StringRef spelling ) {
|
||||
++count;
|
||||
spellings.insert( spelling );
|
||||
}
|
||||
|
@@ -8,9 +8,10 @@
|
||||
#ifndef CATCH_LIST_HPP_INCLUDED
|
||||
#define CATCH_LIST_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
|
||||
namespace Catch {
|
||||
@@ -23,15 +24,15 @@ namespace Catch {
|
||||
std::string name, description;
|
||||
};
|
||||
struct ListenerDescription {
|
||||
std::string_view name;
|
||||
StringRef name;
|
||||
std::string description;
|
||||
};
|
||||
|
||||
struct TagInfo {
|
||||
void add(std::string_view spelling);
|
||||
void add(StringRef spelling);
|
||||
std::string all() const;
|
||||
|
||||
std::set<std::string_view> spellings;
|
||||
std::set<StringRef> spellings;
|
||||
std::size_t count = 0;
|
||||
};
|
||||
|
||||
|
44
src/catch2/internal/catch_logical_traits.hpp
Normal file
44
src/catch2/internal/catch_logical_traits.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
// 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_LOGICAL_TRAITS_HPP_INCLUDED
|
||||
#define CATCH_LOGICAL_TRAITS_HPP_INCLUDED
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
|
||||
#if defined( __cpp_lib_logical_traits ) && __cpp_lib_logical_traits >= 201510
|
||||
|
||||
using std::conjunction;
|
||||
using std::disjunction;
|
||||
using std::negation;
|
||||
|
||||
#else
|
||||
|
||||
template <class...> struct conjunction : std::true_type {};
|
||||
template <class B1> struct conjunction<B1> : B1 {};
|
||||
template <class B1, class... Bn>
|
||||
struct conjunction<B1, Bn...>
|
||||
: std::conditional_t<bool( B1::value ), conjunction<Bn...>, B1> {};
|
||||
|
||||
template <class...> struct disjunction : std::false_type {};
|
||||
template <class B1> struct disjunction<B1> : B1 {};
|
||||
template <class B1, class... Bn>
|
||||
struct disjunction<B1, Bn...>
|
||||
: std::conditional_t<bool( B1::value ), B1, disjunction<Bn...>> {};
|
||||
|
||||
template <class B>
|
||||
struct negation : std::integral_constant<bool, !bool(B::value)> {};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace Detail
|
||||
} // namespace Catch
|
||||
|
||||
#endif // CATCH_LOGICAL_TRAITS_HPP_INCLUDED
|
@@ -10,7 +10,7 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
MessageInfo::MessageInfo( std::string_view _macroName,
|
||||
MessageInfo::MessageInfo( StringRef _macroName,
|
||||
SourceLineInfo const& _lineInfo,
|
||||
ResultWas::OfType _type )
|
||||
: macroName( _macroName ),
|
||||
|
@@ -11,17 +11,18 @@
|
||||
#include <catch2/internal/catch_deprecation_macro.hpp>
|
||||
#include <catch2/internal/catch_result_type.hpp>
|
||||
#include <catch2/internal/catch_source_line_info.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct MessageInfo {
|
||||
MessageInfo( std::string_view _macroName,
|
||||
MessageInfo( StringRef _macroName,
|
||||
SourceLineInfo const& _lineInfo,
|
||||
ResultWas::OfType _type );
|
||||
|
||||
std::string_view macroName;
|
||||
StringRef macroName;
|
||||
std::string message;
|
||||
SourceLineInfo lineInfo;
|
||||
ResultWas::OfType type;
|
||||
|
@@ -27,8 +27,16 @@ namespace Catch {
|
||||
template <typename Fun, typename... Args>
|
||||
struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {};
|
||||
|
||||
|
||||
#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
|
||||
// std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
|
||||
// replaced with std::invoke_result here.
|
||||
template <typename Func, typename... U>
|
||||
using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>;
|
||||
#else
|
||||
template <typename Func, typename... U>
|
||||
using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::result_of_t<Func(U...)>>>;
|
||||
#endif
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
|
117
src/catch2/internal/catch_optional.hpp
Normal file
117
src/catch2/internal/catch_optional.hpp
Normal file
@@ -0,0 +1,117 @@
|
||||
|
||||
// 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_OPTIONAL_HPP_INCLUDED
|
||||
#define CATCH_OPTIONAL_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
// An optional type
|
||||
template<typename T>
|
||||
class Optional {
|
||||
public:
|
||||
Optional(): nullableValue( nullptr ) {}
|
||||
~Optional() { reset(); }
|
||||
|
||||
Optional( T const& _value ):
|
||||
nullableValue( new ( storage ) T( _value ) ) {}
|
||||
Optional( T&& _value ):
|
||||
nullableValue( new ( storage ) T( CATCH_MOVE( _value ) ) ) {}
|
||||
|
||||
Optional& operator=( T const& _value ) {
|
||||
reset();
|
||||
nullableValue = new ( storage ) T( _value );
|
||||
return *this;
|
||||
}
|
||||
Optional& operator=( T&& _value ) {
|
||||
reset();
|
||||
nullableValue = new ( storage ) T( CATCH_MOVE( _value ) );
|
||||
return *this;
|
||||
}
|
||||
|
||||
Optional( Optional const& _other ):
|
||||
nullableValue( _other ? new ( storage ) T( *_other ) : nullptr ) {}
|
||||
Optional( Optional&& _other ):
|
||||
nullableValue( _other ? new ( storage ) T( CATCH_MOVE( *_other ) )
|
||||
: nullptr ) {}
|
||||
|
||||
Optional& operator=( Optional const& _other ) {
|
||||
if ( &_other != this ) {
|
||||
reset();
|
||||
if ( _other ) { nullableValue = new ( storage ) T( *_other ); }
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Optional& operator=( Optional&& _other ) {
|
||||
if ( &_other != this ) {
|
||||
reset();
|
||||
if ( _other ) {
|
||||
nullableValue = new ( storage ) T( CATCH_MOVE( *_other ) );
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if ( nullableValue ) { nullableValue->~T(); }
|
||||
nullableValue = nullptr;
|
||||
}
|
||||
|
||||
T& operator*() {
|
||||
assert(nullableValue);
|
||||
return *nullableValue;
|
||||
}
|
||||
T const& operator*() const {
|
||||
assert(nullableValue);
|
||||
return *nullableValue;
|
||||
}
|
||||
T* operator->() {
|
||||
assert(nullableValue);
|
||||
return nullableValue;
|
||||
}
|
||||
const T* operator->() const {
|
||||
assert(nullableValue);
|
||||
return nullableValue;
|
||||
}
|
||||
|
||||
T valueOr( T const& defaultValue ) const {
|
||||
return nullableValue ? *nullableValue : defaultValue;
|
||||
}
|
||||
|
||||
bool some() const { return nullableValue != nullptr; }
|
||||
bool none() const { return nullableValue == nullptr; }
|
||||
|
||||
bool operator !() const { return nullableValue == nullptr; }
|
||||
explicit operator bool() const {
|
||||
return some();
|
||||
}
|
||||
|
||||
friend bool operator==(Optional const& a, Optional const& b) {
|
||||
if (a.none() && b.none()) {
|
||||
return true;
|
||||
} else if (a.some() && b.some()) {
|
||||
return *a == *b;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
friend bool operator!=(Optional const& a, Optional const& b) {
|
||||
return !( a == b );
|
||||
}
|
||||
|
||||
private:
|
||||
T* nullableValue;
|
||||
alignas(alignof(T)) char storage[sizeof(T)];
|
||||
};
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // CATCH_OPTIONAL_HPP_INCLUDED
|
@@ -311,6 +311,23 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
RedirectGuard::RedirectGuard( RedirectGuard&& rhs ) noexcept:
|
||||
m_redirect( rhs.m_redirect ),
|
||||
m_activate( rhs.m_activate ),
|
||||
m_previouslyActive( rhs.m_previouslyActive ),
|
||||
m_moved( false ) {
|
||||
rhs.m_moved = true;
|
||||
}
|
||||
|
||||
RedirectGuard& RedirectGuard::operator=( RedirectGuard&& rhs ) noexcept {
|
||||
m_redirect = rhs.m_redirect;
|
||||
m_activate = rhs.m_activate;
|
||||
m_previouslyActive = rhs.m_previouslyActive;
|
||||
m_moved = false;
|
||||
rhs.m_moved = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
#if defined( CATCH_CONFIG_NEW_CAPTURE )
|
||||
|
@@ -63,6 +63,10 @@ namespace Catch {
|
||||
|
||||
RedirectGuard( RedirectGuard const& ) = delete;
|
||||
RedirectGuard& operator=( RedirectGuard const& ) = delete;
|
||||
|
||||
// C++14 needs move-able guards to return them from functions
|
||||
RedirectGuard( RedirectGuard&& rhs ) noexcept;
|
||||
RedirectGuard& operator=( RedirectGuard&& rhs ) noexcept;
|
||||
};
|
||||
|
||||
RedirectGuard scopedActivate( OutputRedirect& redirectImpl );
|
||||
|
@@ -12,11 +12,10 @@
|
||||
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <optional>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
std::optional<unsigned int> parseUInt(std::string const& input, int base) {
|
||||
Optional<unsigned int> parseUInt(std::string const& input, int base) {
|
||||
auto trimmed = trim( input );
|
||||
// std::stoull is annoying and accepts numbers starting with '-',
|
||||
// it just negates them into unsigned int
|
||||
|
@@ -8,7 +8,8 @@
|
||||
#ifndef CATCH_PARSE_NUMBERS_HPP_INCLUDED
|
||||
#define CATCH_PARSE_NUMBERS_HPP_INCLUDED
|
||||
|
||||
#include <optional>
|
||||
#include <catch2/internal/catch_optional.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Catch {
|
||||
@@ -19,7 +20,7 @@ namespace Catch {
|
||||
* Effectively a wrapper around std::stoul but with better error checking
|
||||
* e.g. "-1" is rejected, instead of being parsed as UINT_MAX.
|
||||
*/
|
||||
std::optional<unsigned int> parseUInt(std::string const& input, int base = 10);
|
||||
Optional<unsigned int> parseUInt(std::string const& input, int base = 10);
|
||||
}
|
||||
|
||||
#endif // CATCH_PARSE_NUMBERS_HPP_INCLUDED
|
||||
|
@@ -25,6 +25,9 @@
|
||||
#elif defined(linux) || defined(__linux) || defined(__linux__)
|
||||
# define CATCH_PLATFORM_LINUX
|
||||
|
||||
#elif defined(__QNX__)
|
||||
# define CATCH_PLATFORM_QNX
|
||||
|
||||
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
|
||||
# define CATCH_PLATFORM_WINDOWS
|
||||
|
||||
|
@@ -176,7 +176,7 @@ namespace Catch {
|
||||
template<typename... Ts>\
|
||||
void reg_test(TypeList<Ts...>, Catch::NameAndTags nameAndTags)\
|
||||
{\
|
||||
Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Ts...>), CATCH_INTERNAL_LINEINFO, std::string_view(), nameAndTags);\
|
||||
Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Ts...>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
|
||||
}
|
||||
|
||||
#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature, ...)
|
||||
@@ -184,19 +184,19 @@ namespace Catch {
|
||||
template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
|
||||
void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\
|
||||
{\
|
||||
Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, std::string_view(), nameAndTags);\
|
||||
Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
|
||||
}
|
||||
|
||||
#define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\
|
||||
template<typename Type>\
|
||||
void reg_test(TypeList<Type>, std::string_view className, Catch::NameAndTags nameAndTags)\
|
||||
void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
|
||||
{\
|
||||
Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
|
||||
}
|
||||
|
||||
#define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\
|
||||
template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
|
||||
void reg_test(Nttp<__VA_ARGS__>, std::string_view className, Catch::NameAndTags nameAndTags)\
|
||||
void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
|
||||
{\
|
||||
Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
|
||||
}
|
||||
|
@@ -11,9 +11,9 @@
|
||||
#include <catch2/catch_user_config.hpp>
|
||||
|
||||
#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
|
||||
#define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
|
||||
#define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr
|
||||
#else
|
||||
#define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
|
||||
#define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr
|
||||
#endif
|
||||
|
||||
#endif // CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user