mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-19 03:15:40 +02:00
Compare commits
67 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7ee2173aca | ||
![]() |
20d3f1939d | ||
![]() |
459ac8562b | ||
![]() |
8ac8190e49 | ||
![]() |
b20b365fd2 | ||
![]() |
4d8affc989 | ||
![]() |
cde3509664 | ||
![]() |
7677c1658e | ||
![]() |
92d3b23913 | ||
![]() |
dca87563bb | ||
![]() |
da303cc668 | ||
![]() |
c3fd4eb17e | ||
![]() |
fb51116d5b | ||
![]() |
ed6ac8a629 | ||
![]() |
e7913f1363 | ||
![]() |
4f3871d53f | ||
![]() |
f476bcb633 | ||
![]() |
024cfb3542 | ||
![]() |
28c2f0b0c2 | ||
![]() |
2e1b02a0e2 | ||
![]() |
82e9b9b5f2 | ||
![]() |
031a163a2c | ||
![]() |
562f31029a | ||
![]() |
62d4aecb8c | ||
![]() |
b817497528 | ||
![]() |
4f1b24df77 | ||
![]() |
3157d6bbf1 | ||
![]() |
4570fca24b | ||
![]() |
0787132fc8 | ||
![]() |
dc51386b9f | ||
![]() |
bbba3d8a06 | ||
![]() |
d937427f1f | ||
![]() |
2a5de4e447 | ||
![]() |
1078e7e95b | ||
![]() |
79205da6a6 | ||
![]() |
658acee86e | ||
![]() |
05e10dfccc | ||
![]() |
597ce12b65 | ||
![]() |
05786fa7ec | ||
![]() |
d79bfa05c7 | ||
![]() |
6ebdd8fac2 | ||
![]() |
7f931d6df4 | ||
![]() |
a0ef2115f8 | ||
![]() |
863c662c0e | ||
![]() |
f981c9cbca | ||
![]() |
b7b71ffd3a | ||
![]() |
048d7f7796 | ||
![]() |
a9a94bec13 | ||
![]() |
c8262e1f40 | ||
![]() |
08bdd43fcd | ||
![]() |
1512dac7e4 | ||
![]() |
b52d97855d | ||
![]() |
eaafd07674 | ||
![]() |
5d637d4c6b | ||
![]() |
cd3c7ebe87 | ||
![]() |
5d5f42f99b | ||
![]() |
c57e349d1d | ||
![]() |
822c44a203 | ||
![]() |
2295d2c8cc | ||
![]() |
2b69a3e216 | ||
![]() |
c809cb4d1c | ||
![]() |
9aadc3a53d | ||
![]() |
64ade68ca2 | ||
![]() |
680064d391 | ||
![]() |
3acb8b30f1 | ||
![]() |
3f23192e55 | ||
![]() |
d40a3289e5 |
1
.bazelrc
1
.bazelrc
@@ -8,3 +8,4 @@ build:vs2022 --cxxopt=/std:c++17
|
||||
|
||||
build:windows --config=vs2022
|
||||
build:linux --config=gcc11
|
||||
build:macos --cxxopt=-std=c++2b
|
||||
|
81
.clang-tidy
Normal file
81
.clang-tidy
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
# Note: Alas, `Checks` is a string, not an array.
|
||||
# Comments in the block string are not parsed and are passed in the value.
|
||||
# They must thus be delimited by ',' from either side - then they are
|
||||
# harmless. It's terrible, but it works.
|
||||
Checks: >-
|
||||
clang-diagnostic-*,
|
||||
clang-analyzer-*,
|
||||
-clang-analyzer-optin.core.EnumCastOutOfRange,
|
||||
|
||||
bugprone-*,
|
||||
-bugprone-unchecked-optional-access,
|
||||
,# This is ridiculous, as it triggers on constants,
|
||||
-bugprone-implicit-widening-of-multiplication-result,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
,# Is not really useful, has false positives, triggers for no-noexcept move constructors ...,
|
||||
-bugprone-exception-escape,
|
||||
-bugprone-narrowing-conversions,
|
||||
-bugprone-chained-comparison,# RIP decomposers,
|
||||
|
||||
modernize-*,
|
||||
-modernize-avoid-c-arrays,
|
||||
-modernize-use-auto,
|
||||
-modernize-use-emplace,
|
||||
-modernize-use-nullptr,# it went crazy with three-way comparison operators,
|
||||
-modernize-use-trailing-return-type,
|
||||
-modernize-return-braced-init-list,
|
||||
-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,
|
||||
|
||||
portability-*,
|
||||
|
||||
readability-*,
|
||||
-readability-braces-around-statements,
|
||||
-readability-container-size-empty,
|
||||
-readability-convert-member-functions-to-static,
|
||||
-readability-else-after-return,
|
||||
-readability-function-cognitive-complexity,
|
||||
-readability-function-size,
|
||||
-readability-identifier-length,
|
||||
-readability-implicit-bool-conversion,
|
||||
-readability-isolate-declaration,
|
||||
-readability-magic-numbers,
|
||||
-readability-named-parameter,
|
||||
-readability-qualified-auto,
|
||||
-readability-redundant-access-specifiers,
|
||||
-readability-simplify-boolean-expr,
|
||||
-readability-static-definition-in-anonymous-namespace,
|
||||
-readability-uppercase-literal-suffix,
|
||||
-readability-use-anyofallof,
|
||||
-readability-avoid-return-with-void-value,
|
||||
|
||||
,# time hogs,
|
||||
-bugprone-throw-keyword-missing,
|
||||
-modernize-replace-auto-ptr,
|
||||
-readability-identifier-naming,
|
||||
|
||||
,# We cannot use this until clang-tidy supports custom unique_ptr,
|
||||
-bugprone-use-after-move,
|
||||
,# Doesn't recognize unevaluated context in CATCH_MOVE and CATCH_FORWARD,
|
||||
-bugprone-macro-repeated-side-effects,
|
||||
WarningsAsErrors: >-
|
||||
clang-analyzer-core.*,
|
||||
clang-analyzer-cplusplus.*,
|
||||
clang-analyzer-security.*,
|
||||
clang-analyzer-unix.*,
|
||||
performance-move-const-arg,
|
||||
performance-unnecessary-value-param,
|
||||
readability-duplicate-include,
|
||||
HeaderFilterRegex: '.*\.(c|cxx|cpp)$'
|
||||
FormatStyle: none
|
||||
CheckOptions: {}
|
||||
...
|
@@ -1,12 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.2.0)
|
||||
project(test_package CXX)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(PackageTest CXX)
|
||||
|
||||
include("${CMAKE_BINARY_DIR}/conanbuildinfo.cmake")
|
||||
conan_basic_setup()
|
||||
find_package(Catch2 CONFIG REQUIRED)
|
||||
|
||||
find_package(Catch2 REQUIRED CONFIG)
|
||||
|
||||
add_executable(${PROJECT_NAME} test_package.cpp)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} Catch2::Catch2WithMain)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 14)
|
||||
add_executable(test_package test_package.cpp)
|
||||
target_link_libraries(test_package Catch2::Catch2WithMain)
|
@@ -1,12 +1,20 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from conans import ConanFile, CMake
|
||||
from conan import ConanFile
|
||||
from conan.tools.cmake import CMake, cmake_layout
|
||||
from conan.tools.build import can_run
|
||||
import os
|
||||
|
||||
|
||||
class TestPackageConan(ConanFile):
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
generators = "cmake_find_package_multi", "cmake"
|
||||
generators = "CMakeToolchain", "CMakeDeps"
|
||||
|
||||
def requirements(self):
|
||||
self.requires(self.tested_reference_str)
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
@@ -14,7 +22,12 @@ class TestPackageConan(ConanFile):
|
||||
cmake.build()
|
||||
|
||||
def test(self):
|
||||
assert os.path.isfile(os.path.join(
|
||||
self.deps_cpp_info["catch2"].rootpath, "licenses", "LICENSE.txt"))
|
||||
bin_path = os.path.join("bin", "test_package")
|
||||
self.run("%s -s" % bin_path, run_environment=True)
|
||||
if can_run(self):
|
||||
cmd = os.path.join(self.cpp.build.bindir, "test_package")
|
||||
self.run(cmd, env="conanrun")
|
||||
|
||||
# If we are on conan 2 we can check the license info is populated
|
||||
if hasattr(self, 'dependencies'):
|
||||
catch2 = self.dependencies["catch2"]
|
||||
assert os.path.exists(f'{catch2.package_folder}/licenses/LICENSE.txt')
|
||||
assert catch2.license == 'BSL-1.0'
|
||||
|
1
.github/workflows/linux-meson-builds.yml
vendored
1
.github/workflows/linux-meson-builds.yml
vendored
@@ -40,6 +40,5 @@ jobs:
|
||||
|
||||
- name: Run tests
|
||||
working-directory: ${{runner.workspace}}/meson-build
|
||||
# Hardcode 2 cores we know are there
|
||||
run: |
|
||||
meson test --verbose
|
||||
|
52
.github/workflows/linux-other-builds.yml
vendored
52
.github/workflows/linux-other-builds.yml
vendored
@@ -102,5 +102,53 @@ jobs:
|
||||
env:
|
||||
CTEST_OUTPUT_ON_FAILURE: 1
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
# Hardcode 2 cores we know are there
|
||||
run: ctest -C ${{matrix.build_type}} -j 2 ${{matrix.other_ctest_args}}
|
||||
run: ctest -C ${{matrix.build_type}} -j `nproc` ${{matrix.other_ctest_args}}
|
||||
clang-tidy:
|
||||
name: clang-tidy ${{matrix.version}}, ${{matrix.build_description}}, C++${{matrix.std}} ${{matrix.build_type}}
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- version: "15"
|
||||
build_description: all
|
||||
build_type: Debug
|
||||
std: 17
|
||||
other_pkgs: ''
|
||||
cmake_configurations: -DCATCH_BUILD_EXAMPLES=ON -DCATCH_ENABLE_CMAKE_HELPER_TESTS=ON
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare environment
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ninja-build clang-${{matrix.version}} clang-tidy-${{matrix.version}} ${{matrix.other_pkgs}}
|
||||
|
||||
- name: Configure build
|
||||
working-directory: ${{runner.workspace}}
|
||||
env:
|
||||
CXX: clang++-${{matrix.version}}
|
||||
CXXFLAGS: ${{matrix.cxxflags}}
|
||||
# Note: $GITHUB_WORKSPACE is distinct from ${{runner.workspace}}.
|
||||
# This is important
|
||||
run: |
|
||||
clangtidy="clang-tidy-${{matrix.version}};-use-color"
|
||||
# Use a dummy compiler/linker/ar/ranlib to effectively disable the
|
||||
# compilation and only run clang-tidy.
|
||||
cmake -Bbuild -H$GITHUB_WORKSPACE \
|
||||
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
|
||||
-DCMAKE_CXX_STANDARD=${{matrix.std}} \
|
||||
-DCMAKE_CXX_STANDARD_REQUIRED=ON \
|
||||
-DCMAKE_CXX_EXTENSIONS=OFF \
|
||||
-DCATCH_DEVELOPMENT_BUILD=ON \
|
||||
-DCMAKE_CXX_CLANG_TIDY="$clangtidy" \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/true \
|
||||
-DCMAKE_AR=/usr/bin/true \
|
||||
-DCMAKE_CXX_COMPILER_AR=/usr/bin/true \
|
||||
-DCMAKE_RANLIB=/usr/bin/true \
|
||||
-DCMAKE_CXX_LINK_EXECUTABLE=/usr/bin/true \
|
||||
${{matrix.cmake_configurations}} \
|
||||
-G Ninja
|
||||
|
||||
- name: Run clang-tidy
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: ninja
|
||||
|
9
.github/workflows/linux-simple-builds.yml
vendored
9
.github/workflows/linux-simple-builds.yml
vendored
@@ -9,8 +9,6 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
cxx:
|
||||
- g++-5
|
||||
- g++-6
|
||||
- g++-7
|
||||
- g++-8
|
||||
- g++-9
|
||||
@@ -23,10 +21,6 @@ jobs:
|
||||
build_type: [Debug, Release]
|
||||
std: [14]
|
||||
include:
|
||||
- cxx: g++-5
|
||||
other_pkgs: g++-5
|
||||
- cxx: g++-6
|
||||
other_pkgs: g++-6
|
||||
- cxx: g++-7
|
||||
other_pkgs: g++-7
|
||||
- cxx: g++-8
|
||||
@@ -120,5 +114,4 @@ jobs:
|
||||
env:
|
||||
CTEST_OUTPUT_ON_FAILURE: 1
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
# Hardcode 2 cores we know are there
|
||||
run: ctest -C ${{matrix.build_type}} -j 2
|
||||
run: ctest -C ${{matrix.build_type}} -j `nproc`
|
||||
|
6
.github/workflows/mac-builds.yml
vendored
6
.github/workflows/mac-builds.yml
vendored
@@ -4,11 +4,7 @@ on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# macos-12 updated to a toolchain that crashes when linking the
|
||||
# test binary. This seems to be a known bug in that version,
|
||||
# and will eventually get fixed in an update. After that, we can go
|
||||
# back to newer macos images.
|
||||
runs-on: macos-11
|
||||
runs-on: macos-14
|
||||
strategy:
|
||||
matrix:
|
||||
cxx:
|
||||
|
31
.github/workflows/package-manager-builds.yaml
vendored
Normal file
31
.github/workflows/package-manager-builds.yaml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
name: Package Manager Builds
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
conan_builds:
|
||||
name: Conan ${{matrix.conan_version}}
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
conan_version:
|
||||
- '1.62'
|
||||
- '2.0'
|
||||
|
||||
include:
|
||||
# Conan 1 has default profiles installed
|
||||
- conan_version: '1.62'
|
||||
profile_generate: 'false'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install conan
|
||||
run: pip install conan==${{matrix.conan_version}}
|
||||
|
||||
- name: Setup conan profiles
|
||||
if: matrix.profile_generate != 'false'
|
||||
run: conan profile detect
|
||||
|
||||
- name: Run conan package create
|
||||
run: conan create . -tf .conan/test_package
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -25,6 +25,7 @@ Build
|
||||
cmake-build-*
|
||||
benchmark-dir
|
||||
.conan/test_package/build
|
||||
.conan/test_package/CMakeUserPresets.json
|
||||
bazel-*
|
||||
build-fuzzers
|
||||
debug-build
|
||||
|
@@ -78,6 +78,7 @@ function(add_warnings_to_targets targets)
|
||||
"-Wreturn-std-move"
|
||||
"-Wshadow"
|
||||
"-Wstrict-aliasing"
|
||||
"-Wsubobject-linkage"
|
||||
"-Wsuggest-destructor-override"
|
||||
"-Wsuggest-override"
|
||||
"-Wundef"
|
||||
|
@@ -11,6 +11,7 @@ endif()
|
||||
option(CATCH_INSTALL_DOCS "Install documentation alongside library" ON)
|
||||
option(CATCH_INSTALL_EXTRAS "Install extras (CMake scripts, debugger helpers) alongside library" ON)
|
||||
option(CATCH_DEVELOPMENT_BUILD "Build tests, enable warnings, enable Werror, etc" OFF)
|
||||
option(CATCH_ENABLE_REPRODUCIBLE_BUILD "Add compiler flags for improving build reproducibility" ON)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
cmake_dependent_option(CATCH_BUILD_TESTING "Build the SelfTest project" ON "CATCH_DEVELOPMENT_BUILD" OFF)
|
||||
@@ -32,7 +33,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
endif()
|
||||
|
||||
project(Catch2
|
||||
VERSION 3.5.0 # CML version placeholder, don't delete
|
||||
VERSION 3.5.3 # CML version placeholder, don't delete
|
||||
LANGUAGES CXX
|
||||
# HOMEPAGE_URL is not supported until CMake version 3.12, which
|
||||
# we do not target yet.
|
||||
|
306
Doxyfile
306
Doxyfile
@@ -1,4 +1,4 @@
|
||||
# Doxyfile 1.8.16
|
||||
# Doxyfile 1.9.1
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
@@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8
|
||||
# title of most generated pages and in a few other places.
|
||||
# The default value is: My Project.
|
||||
|
||||
PROJECT_NAME = "Catch2"
|
||||
PROJECT_NAME = Catch2
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
@@ -51,6 +51,7 @@ PROJECT_BRIEF = "Popular C++ unit testing framework"
|
||||
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
|
||||
# the logo to the output directory.
|
||||
|
||||
PROJECT_LOGO =
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
|
||||
# into which the generated documentation will be written. If a relative path is
|
||||
@@ -216,6 +217,14 @@ QT_AUTOBRIEF = YES
|
||||
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
|
||||
# By default Python docstrings are displayed as preformatted text and doxygen's
|
||||
# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
|
||||
# doxygen's special commands can be used and the contents of the docstring
|
||||
# documentation blocks is shown as doxygen documentation.
|
||||
# The default value is: YES.
|
||||
|
||||
PYTHON_DOCSTRING = YES
|
||||
|
||||
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
||||
# documentation from any documented member that it re-implements.
|
||||
# The default value is: YES.
|
||||
@@ -251,13 +260,7 @@ TAB_SIZE = 4
|
||||
# a double escape (\\{ and \\})
|
||||
|
||||
ALIASES = "complexity=@par Complexity:" \
|
||||
"noexcept=**Noexcept**"
|
||||
|
||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
||||
# will allow you to use the command class in the itcl::class meaning.
|
||||
|
||||
TCL_SUBST =
|
||||
noexcept=**Noexcept**
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||
# only. Doxygen will then generate output that is more tailored for C. For
|
||||
@@ -299,19 +302,22 @@ OPTIMIZE_OUTPUT_SLICE = NO
|
||||
# parses. With this tag you can assign which parser to use for a given
|
||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
|
||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
|
||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||
# tries to guess whether the code is fixed or free formatted code, this is the
|
||||
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
|
||||
# .inc files as Fortran files (default is PHP), and .f files as C (default is
|
||||
# Fortran), use: inc=Fortran f=C.
|
||||
# default for Fortran type files). For instance to make doxygen treat .inc files
|
||||
# as Fortran files (default is PHP), and .f files as C (default is Fortran),
|
||||
# use: inc=Fortran f=C.
|
||||
#
|
||||
# Note: For files without extension you can use no_extension as a placeholder.
|
||||
#
|
||||
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
||||
# the files are not read by doxygen.
|
||||
# the files are not read by doxygen. When specifying no_extension you should add
|
||||
# * to the FILE_PATTERNS.
|
||||
#
|
||||
# Note see also the list of default file extension mappings.
|
||||
|
||||
EXTENSION_MAPPING =
|
||||
|
||||
@@ -445,6 +451,19 @@ TYPEDEF_HIDES_STRUCT = NO
|
||||
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
|
||||
# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
|
||||
# during processing. When set to 0 doxygen will based this on the number of
|
||||
# cores available in the system. You can set it explicitly to a value larger
|
||||
# than 0 to get more control over the balance between CPU load and processing
|
||||
# speed. At this moment only the input processing can be done using multiple
|
||||
# threads. Since this is still an experimental feature the default is set to 1,
|
||||
# which efficively disables parallel processing. Please report any issues you
|
||||
# encounter. Generating dot graphs in parallel is controlled by the
|
||||
# DOT_NUM_THREADS setting.
|
||||
# Minimum value: 0, maximum value: 32, default value: 1.
|
||||
|
||||
NUM_PROC_THREADS = 1
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -508,6 +527,13 @@ EXTRACT_LOCAL_METHODS = NO
|
||||
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
|
||||
# If this flag is set to YES, the name of an unnamed parameter in a declaration
|
||||
# will be determined by the corresponding definition. By default unnamed
|
||||
# parameters remain unnamed in the output.
|
||||
# The default value is: YES.
|
||||
|
||||
RESOLVE_UNNAMED_PARAMS = YES
|
||||
|
||||
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
|
||||
# undocumented members inside documented classes or files. If set to NO these
|
||||
# members will be included in the various overviews, but no documentation
|
||||
@@ -525,8 +551,8 @@ HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
|
||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
||||
# (class|struct|union) declarations. If set to NO, these declarations will be
|
||||
# included in the documentation.
|
||||
# declarations. If set to NO, these declarations will be included in the
|
||||
# documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
@@ -545,11 +571,18 @@ HIDE_IN_BODY_DOCS = NO
|
||||
|
||||
INTERNAL_DOCS = NO
|
||||
|
||||
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
|
||||
# names in lower-case letters. If set to YES, upper-case letters are also
|
||||
# allowed. This is useful if you have classes or files whose names only differ
|
||||
# in case and if your file system supports case sensitive file names. Windows
|
||||
# (including Cygwin) ands Mac users are advised to set this option to NO.
|
||||
# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
|
||||
# able to match the capabilities of the underlying filesystem. In case the
|
||||
# filesystem is case sensitive (i.e. it supports files in the same directory
|
||||
# whose names only differ in casing), the option must be set to YES to properly
|
||||
# deal with such files in case they appear in the input. For filesystems that
|
||||
# are not case sensitive the option should be be set to NO to properly deal with
|
||||
# output files written for symbols that only differ in casing, such as for two
|
||||
# classes, one named CLASS and the other named Class, and to also support
|
||||
# references to files without having to specify the exact matching casing. On
|
||||
# Windows (including Cygwin) and MacOS, users should typically set this option
|
||||
# to NO, whereas on Linux or other Unix flavors it should typically be set to
|
||||
# YES.
|
||||
# The default value is: system dependent.
|
||||
|
||||
CASE_SENSE_NAMES = NO
|
||||
@@ -788,7 +821,10 @@ WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = YES
|
||||
|
||||
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
||||
# a warning is encountered.
|
||||
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
|
||||
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
|
||||
# at the end of the doxygen process doxygen will return with a non-zero status.
|
||||
# Possible values are: NO, YES and FAIL_ON_WARNINGS.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_AS_ERROR = NO
|
||||
@@ -819,13 +855,13 @@ WARN_LOGFILE = doxygen.errors
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = "src/catch2"
|
||||
INPUT = src/catch2
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
|
||||
# possible encodings.
|
||||
# documentation (see:
|
||||
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
|
||||
# The default value is: UTF-8.
|
||||
|
||||
INPUT_ENCODING = UTF-8
|
||||
@@ -838,13 +874,61 @@ INPUT_ENCODING = UTF-8
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# read by doxygen.
|
||||
#
|
||||
# Note the list of default checked file patterns might differ from the list of
|
||||
# default file extension mappings.
|
||||
#
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
||||
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
|
||||
# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
|
||||
# *.ucf, *.qsf and *.ice.
|
||||
|
||||
# FILE_PATTERNS =
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.java \
|
||||
*.ii \
|
||||
*.ixx \
|
||||
*.ipp \
|
||||
*.i++ \
|
||||
*.inl \
|
||||
*.idl \
|
||||
*.ddl \
|
||||
*.odl \
|
||||
*.h \
|
||||
*.hh \
|
||||
*.hxx \
|
||||
*.hpp \
|
||||
*.h++ \
|
||||
*.cs \
|
||||
*.d \
|
||||
*.php \
|
||||
*.php4 \
|
||||
*.php5 \
|
||||
*.phtml \
|
||||
*.inc \
|
||||
*.m \
|
||||
*.markdown \
|
||||
*.md \
|
||||
*.mm \
|
||||
*.dox \
|
||||
*.py \
|
||||
*.pyw \
|
||||
*.f90 \
|
||||
*.f95 \
|
||||
*.f03 \
|
||||
*.f08 \
|
||||
*.f18 \
|
||||
*.f \
|
||||
*.for \
|
||||
*.vhd \
|
||||
*.vhdl \
|
||||
*.ucf \
|
||||
*.qsf \
|
||||
*.ice
|
||||
|
||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||
# be searched for input files as well.
|
||||
@@ -968,6 +1052,7 @@ FILTER_SOURCE_PATTERNS =
|
||||
# (index.html). This can be useful if you have a project on for instance GitHub
|
||||
# and want to reuse the introduction page also for the doxygen output.
|
||||
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
@@ -1055,6 +1140,44 @@ USE_HTAGS = NO
|
||||
|
||||
VERBATIM_HEADERS = YES
|
||||
|
||||
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
|
||||
# clang parser (see:
|
||||
# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
|
||||
# performance. This can be particularly helpful with template rich C++ code for
|
||||
# which doxygen's built-in parser lacks the necessary type information.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
# The default value is: NO.
|
||||
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
|
||||
# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to
|
||||
# YES then doxygen will add the directory of each input to the include path.
|
||||
# The default value is: YES.
|
||||
|
||||
CLANG_ADD_INC_PATHS = YES
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the compiler with command
|
||||
# line options that you would normally use when invoking the compiler. Note that
|
||||
# the include paths will already be set by doxygen for the files and directories
|
||||
# specified with INPUT and INCLUDE_PATH.
|
||||
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||
|
||||
CLANG_OPTIONS =
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the clang parser with the
|
||||
# path to the directory containing a file called compile_commands.json. This
|
||||
# file is the compilation database (see:
|
||||
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
|
||||
# options used when the source files were built. This is equivalent to
|
||||
# specifying the -p option to a clang tool, such as clang-check. These options
|
||||
# will then be passed to the parser. Any options specified with CLANG_OPTIONS
|
||||
# will be added as well.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
|
||||
CLANG_DATABASE_PATH =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -1066,13 +1189,6 @@ VERBATIM_HEADERS = YES
|
||||
|
||||
ALPHABETICAL_INDEX = YES
|
||||
|
||||
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
|
||||
# which the alphabetical index list will be split.
|
||||
# Minimum value: 1, maximum value: 20, default value: 5.
|
||||
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
|
||||
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
|
||||
# In case all classes in a project start with a common prefix, all classes will
|
||||
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
|
||||
# can be used to specify a prefix (or a list of prefixes) that should be ignored
|
||||
@@ -1211,9 +1327,9 @@ HTML_TIMESTAMP = NO
|
||||
|
||||
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
|
||||
# documentation will contain a main index with vertical navigation menus that
|
||||
# are dynamically created via Javascript. If disabled, the navigation index will
|
||||
# are dynamically created via JavaScript. If disabled, the navigation index will
|
||||
# consists of multiple levels of tabs that are statically embedded in every HTML
|
||||
# page. Disable this option to support browsers that do not have Javascript,
|
||||
# page. Disable this option to support browsers that do not have JavaScript,
|
||||
# like the Qt help browser.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
@@ -1243,10 +1359,11 @@ HTML_INDEX_NUM_ENTRIES = 100
|
||||
|
||||
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
|
||||
# generated that can be used as input for Apple's Xcode 3 integrated development
|
||||
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
|
||||
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
|
||||
# Makefile in the HTML output directory. Running make will produce the docset in
|
||||
# that directory and running make install will install the docset in
|
||||
# environment (see:
|
||||
# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
|
||||
# create a documentation set, doxygen will generate a Makefile in the HTML
|
||||
# output directory. Running make will produce the docset in that directory and
|
||||
# running make install will install the docset in
|
||||
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
||||
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
||||
# genXcode/_index.html for more information.
|
||||
@@ -1288,8 +1405,8 @@ DOCSET_PUBLISHER_NAME = Publisher
|
||||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
||||
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
||||
# Windows.
|
||||
# (see:
|
||||
# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows.
|
||||
#
|
||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
||||
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
||||
@@ -1364,7 +1481,8 @@ QCH_FILE =
|
||||
|
||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
||||
# Project output. For more information please see Qt Help Project / Namespace
|
||||
# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||
# (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
@@ -1372,8 +1490,8 @@ QHP_NAMESPACE = org.doxygen.Project
|
||||
|
||||
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
||||
# Help Project output. For more information please see Qt Help Project / Virtual
|
||||
# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
|
||||
# folders).
|
||||
# Folders (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
|
||||
# The default value is: doc.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
@@ -1381,16 +1499,16 @@ QHP_VIRTUAL_FOLDER = doc
|
||||
|
||||
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
||||
# filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# Filters (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_CUST_FILTER_NAME =
|
||||
|
||||
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
||||
# custom filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# Filters (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
@@ -1402,9 +1520,9 @@ QHP_CUST_FILTER_ATTRS =
|
||||
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
|
||||
# The QHG_LOCATION tag can be used to specify the location of Qt's
|
||||
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
|
||||
# generated .qhp file.
|
||||
# The QHG_LOCATION tag can be used to specify the location (absolute path
|
||||
# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
|
||||
# run qhelpgenerator on the generated .qhp file.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHG_LOCATION =
|
||||
@@ -1481,6 +1599,17 @@ TREEVIEW_WIDTH = 250
|
||||
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
|
||||
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
|
||||
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
|
||||
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
|
||||
# the HTML output. These images will generally look nicer at scaled resolutions.
|
||||
# Possible values are: png (the default) and svg (looks nicer but requires the
|
||||
# pdf2svg or inkscape tool).
|
||||
# The default value is: png.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_FORMULA_FORMAT = png
|
||||
|
||||
# Use this tag to change the font size of LaTeX formulas included as images in
|
||||
# the HTML documentation. When you change the font size after a successful
|
||||
# doxygen run you need to manually remove any form_*.png images from the HTML
|
||||
@@ -1501,8 +1630,14 @@ FORMULA_FONTSIZE = 10
|
||||
|
||||
FORMULA_TRANSPARENT = YES
|
||||
|
||||
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
|
||||
# to create new LaTeX commands to be used in formulas as building blocks. See
|
||||
# the section "Including formulas" for details.
|
||||
|
||||
FORMULA_MACROFILE =
|
||||
|
||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
||||
# https://www.mathjax.org) which uses client side Javascript for the rendering
|
||||
# https://www.mathjax.org) which uses client side JavaScript for the rendering
|
||||
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
||||
# installed or if you want to formulas look prettier in the HTML output. When
|
||||
# enabled you may also need to install MathJax separately and configure the path
|
||||
@@ -1514,7 +1649,7 @@ USE_MATHJAX = YES
|
||||
|
||||
# When MathJax is enabled you can set the default output format to be used for
|
||||
# the MathJax output. See the MathJax site (see:
|
||||
# http://docs.mathjax.org/en/latest/output.html) for more details.
|
||||
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details.
|
||||
# Possible values are: HTML-CSS (which is slower, but has the best
|
||||
# compatibility), NativeMML (i.e. MathML) and SVG.
|
||||
# The default value is: HTML-CSS.
|
||||
@@ -1530,7 +1665,7 @@ MATHJAX_FORMAT = HTML-CSS
|
||||
# Content Delivery Network so you can quickly see the result without installing
|
||||
# MathJax. However, it is strongly recommended to install a local copy of
|
||||
# MathJax from https://www.mathjax.org before deployment.
|
||||
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
|
||||
# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
@@ -1545,7 +1680,8 @@ MATHJAX_EXTENSIONS = TeX/AMSmath \
|
||||
|
||||
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
|
||||
# of code that will be used on startup of the MathJax code. See the MathJax site
|
||||
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
|
||||
# (see:
|
||||
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
|
||||
# example see the documentation.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
@@ -1573,7 +1709,7 @@ MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = YES
|
||||
|
||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||
# implemented using a web server instead of a web client using Javascript. There
|
||||
# implemented using a web server instead of a web client using JavaScript. There
|
||||
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
||||
# setting. When disabled, doxygen will generate a PHP script for searching and
|
||||
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
||||
@@ -1592,7 +1728,8 @@ SERVER_BASED_SEARCH = NO
|
||||
#
|
||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see: https://xapian.org/).
|
||||
# Xapian (see:
|
||||
# https://xapian.org/).
|
||||
#
|
||||
# See the section "External Indexing and Searching" for details.
|
||||
# The default value is: NO.
|
||||
@@ -1605,8 +1742,9 @@ EXTERNAL_SEARCH = NO
|
||||
#
|
||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see: https://xapian.org/). See the section "External Indexing and
|
||||
# Searching" for details.
|
||||
# Xapian (see:
|
||||
# https://xapian.org/). See the section "External Indexing and Searching" for
|
||||
# details.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
|
||||
SEARCHENGINE_URL =
|
||||
@@ -1770,9 +1908,11 @@ LATEX_EXTRA_FILES =
|
||||
|
||||
PDF_HYPERLINKS = YES
|
||||
|
||||
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
||||
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
|
||||
# higher quality PDF documentation.
|
||||
# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
|
||||
# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
|
||||
# files. Set this option to YES, to get a higher quality PDF documentation.
|
||||
#
|
||||
# See also section LATEX_CMD_NAME for selecting the engine.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
@@ -2204,7 +2344,7 @@ HIDE_UNDOC_RELATIONS = YES
|
||||
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
|
||||
# Bell Labs. The other options in this section have no effect if this option is
|
||||
# set to NO
|
||||
# The default value is: NO.
|
||||
# The default value is: YES.
|
||||
|
||||
HAVE_DOT = YES
|
||||
|
||||
@@ -2283,10 +2423,32 @@ UML_LOOK = NO
|
||||
# but if the number exceeds 15, the total amount of fields shown is limited to
|
||||
# 10.
|
||||
# Minimum value: 0, maximum value: 100, default value: 10.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# This tag requires that the tag UML_LOOK is set to YES.
|
||||
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
|
||||
# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
|
||||
# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
|
||||
# tag is set to YES, doxygen will add type and arguments for attributes and
|
||||
# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
|
||||
# will not generate fields with class member information in the UML graphs. The
|
||||
# class diagrams will look similar to the default class diagrams but using UML
|
||||
# notation for the relationships.
|
||||
# Possible values are: NO, YES and NONE.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag UML_LOOK is set to YES.
|
||||
|
||||
DOT_UML_DETAILS = NO
|
||||
|
||||
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
|
||||
# to display on a single line. If the actual line length exceeds this threshold
|
||||
# significantly it will wrapped across multiple lines. Some heuristics are apply
|
||||
# to avoid ugly line breaks.
|
||||
# Minimum value: 0, maximum value: 1000, default value: 17.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_WRAP_THRESHOLD = 17
|
||||
|
||||
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
|
||||
# collaboration graphs will show the relations between templates and their
|
||||
# instances.
|
||||
@@ -2360,7 +2522,9 @@ DIRECTORY_GRAPH = NO
|
||||
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
|
||||
# to make the SVG files visible in IE 9+ (other browsers do not have this
|
||||
# requirement).
|
||||
# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
|
||||
# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
|
||||
# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
|
||||
# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
|
||||
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
|
||||
# png:gdiplus:gdiplus.
|
||||
# The default value is: png.
|
||||
@@ -2476,9 +2640,11 @@ DOT_MULTI_TARGETS = YES
|
||||
|
||||
GENERATE_LEGEND = YES
|
||||
|
||||
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
|
||||
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
|
||||
# files that are used to generate the various graphs.
|
||||
#
|
||||
# Note: This setting is not only used for dot files but also for msc and
|
||||
# plantuml temporary files.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_CLEANUP = YES
|
||||
|
3
MODULE.bazel
Normal file
3
MODULE.bazel
Normal file
@@ -0,0 +1,3 @@
|
||||
module(name = "catch2")
|
||||
|
||||
bazel_dep(name = "bazel_skylib", version = "1.5.0")
|
@@ -4,10 +4,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "bazel_skylib",
|
||||
sha256 = "66ffd9315665bfaafc96b52278f57c7e2dd09f5ede279ea6d39b2be471e7e3aa",
|
||||
sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.4.2/bazel-skylib-1.4.2.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.2/bazel-skylib-1.4.2.tar.gz",
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
|
15
appveyor.yml
15
appveyor.yml
@@ -5,10 +5,10 @@ version: "{build}-{branch}"
|
||||
clone_depth: 20
|
||||
|
||||
# We want to build everything, except for branches that are explicitly
|
||||
# for messing around with travis.
|
||||
# for messing around with Github Actions.
|
||||
branches:
|
||||
except:
|
||||
- /dev-travis.+/
|
||||
- /devel-gha.+/
|
||||
|
||||
|
||||
# We need a more up to date pip because Python 2.7 is EOL soon
|
||||
@@ -70,3 +70,14 @@ environment:
|
||||
additional_flags: "/permissive- /std:c++latest"
|
||||
platform: x64
|
||||
configuration: Debug
|
||||
|
||||
- FLAVOR: VS 2017 x64 Debug
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
platform: x64
|
||||
configuration: Debug
|
||||
|
||||
- FLAVOR: VS 2017 x64 Release Coverage
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
coverage: 1
|
||||
platform: x64
|
||||
configuration: Debug
|
||||
|
75
conanfile.py
Normal file → Executable file
75
conanfile.py
Normal file → Executable file
@@ -1,5 +1,12 @@
|
||||
#!/usr/bin/env python
|
||||
from conans import ConanFile, CMake, tools
|
||||
from conan import ConanFile, tools, __version__ as conan_version
|
||||
from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout
|
||||
from conan.tools import files, scm
|
||||
import os
|
||||
import shutil
|
||||
import re
|
||||
|
||||
required_conan_version = ">=1.53.0"
|
||||
|
||||
class CatchConan(ConanFile):
|
||||
name = "catch2"
|
||||
@@ -8,53 +15,73 @@ class CatchConan(ConanFile):
|
||||
url = "https://github.com/catchorg/Catch2"
|
||||
homepage = url
|
||||
license = "BSL-1.0"
|
||||
version = "latest"
|
||||
|
||||
exports = "LICENSE.txt"
|
||||
exports_sources = ("src/*", "CMakeLists.txt", "CMake/*", "extras/*")
|
||||
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
|
||||
generators = "cmake"
|
||||
def set_version(self):
|
||||
pattern = re.compile(r"\w*VERSION (\d+\.\d+\.\d+) # CML version placeholder, don't delete")
|
||||
with open("CMakeLists.txt") as file:
|
||||
for line in file:
|
||||
result = pattern.search(line)
|
||||
if result:
|
||||
self.version = result.group(1)
|
||||
|
||||
self.output.info(f'Using version: {self.version}')
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
|
||||
def generate(self):
|
||||
tc = CMakeToolchain(self)
|
||||
tc.generate()
|
||||
|
||||
deps = CMakeDeps(self)
|
||||
deps.generate()
|
||||
|
||||
def _configure_cmake(self):
|
||||
cmake = CMake(self)
|
||||
cmake.definitions["BUILD_TESTING"] = "OFF"
|
||||
cmake.definitions["CATCH_INSTALL_DOCS"] = "OFF"
|
||||
cmake.definitions["CATCH_INSTALL_EXTRAS"] = "ON"
|
||||
cmake.configure(build_folder="build")
|
||||
|
||||
# These are option variables. The toolchain in conan 2 doesn't appear to
|
||||
# set these correctly so you have to do it in the configure variables.
|
||||
cmake.configure(variables= {
|
||||
"BUILD_TESTING": "OFF",
|
||||
"CATCH_INSTALL_DOCS": "OFF",
|
||||
"CATCH_INSTALL_EXTRAS": "ON",
|
||||
}
|
||||
)
|
||||
return cmake
|
||||
|
||||
def build(self):
|
||||
# We need this workaround until the toolchains feature
|
||||
# to inject stuff like MD/MT
|
||||
line_to_replace = 'list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")'
|
||||
tools.replace_in_file("CMakeLists.txt", line_to_replace,
|
||||
'''{}
|
||||
include("{}/conanbuildinfo.cmake")
|
||||
conan_basic_setup()'''.format(line_to_replace, self.install_folder.replace("\\", "/")))
|
||||
|
||||
cmake = self._configure_cmake()
|
||||
cmake.build()
|
||||
|
||||
def package(self):
|
||||
self.copy(pattern="LICENSE.txt", dst="licenses")
|
||||
cmake = self._configure_cmake()
|
||||
cmake.install()
|
||||
|
||||
os.mkdir(f'{self.package_folder}/licenses/')
|
||||
shutil.copy2(f'{self.recipe_folder}/LICENSE.txt', f'{self.package_folder}/licenses/')
|
||||
|
||||
def package_info(self):
|
||||
lib_suffix = "d" if self.settings.build_type == "Debug" else ""
|
||||
|
||||
self.cpp_info.names["cmake_find_package"] = "Catch2"
|
||||
self.cpp_info.names["cmake_find_package_multi"] = "Catch2"
|
||||
self.cpp_info.set_property("cmake_file_name", "Catch2")
|
||||
self.cpp_info.set_property("cmake_target_name", "Catch2::Catch2WithMain")
|
||||
self.cpp_info.set_property("pkg_config_name", "catch2-with-main")
|
||||
|
||||
# Catch2
|
||||
self.cpp_info.components["catch2base"].names["cmake_find_package"] = "Catch2"
|
||||
self.cpp_info.components["catch2base"].names["cmake_find_package_multi"] = "Catch2"
|
||||
self.cpp_info.components["catch2base"].names["pkg_config"] = "Catch2"
|
||||
self.cpp_info.components["catch2base"].set_property("cmake_file_name", "Catch2::Catch2")
|
||||
self.cpp_info.components["catch2base"].set_property("pkg_config_name", "catch2")
|
||||
self.cpp_info.components["catch2base"].libs = ["Catch2" + lib_suffix]
|
||||
self.cpp_info.components["catch2base"].builddirs.append("lib/cmake/Catch2")
|
||||
|
||||
# Catch2WithMain
|
||||
self.cpp_info.components["catch2main"].names["cmake_find_package"] = "Catch2WithMain"
|
||||
self.cpp_info.components["catch2main"].names["cmake_find_package_multi"] = "Catch2WithMain"
|
||||
self.cpp_info.components["catch2main"].names["pkg_config"] = "Catch2WithMain"
|
||||
self.cpp_info.components["catch2main"].set_property("cmake_file_name", "Catch2::Catch2WithMain")
|
||||
self.cpp_info.components["catch2main"].set_property("cmake_target_name", "Catch2::Catch2WithMain")
|
||||
self.cpp_info.components["catch2main"].set_property("pkg_config_name", "catch2-with-main")
|
||||
self.cpp_info.components["catch2main"].libs = ["Catch2Main" + lib_suffix]
|
||||
self.cpp_info.components["catch2main"].requires = ["catch2base"]
|
||||
self.cpp_info.components["catch2main"].requires = ["catch2base"]
|
@@ -384,7 +384,7 @@ install it to the default location, like so:
|
||||
```
|
||||
$ git clone https://github.com/catchorg/Catch2.git
|
||||
$ cd Catch2
|
||||
$ cmake -Bbuild -H. -DBUILD_TESTING=OFF
|
||||
$ cmake -B build -S . -DBUILD_TESTING=OFF
|
||||
$ sudo cmake --build build/ --target install
|
||||
```
|
||||
|
||||
@@ -408,6 +408,24 @@ cd vcpkg
|
||||
The catch2 port in vcpkg is kept up to date by microsoft team members and community contributors.
|
||||
If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
## Installing Catch2 from Bazel
|
||||
|
||||
Catch2 is now a supported module in the Bazel Central Registry. You only need to add one line to your MODULE.bazel file;
|
||||
please see https://registry.bazel.build/modules/catch2 for the latest supported version.
|
||||
|
||||
You can then add `catch2_main` to each of your C++ test build rules as follows:
|
||||
|
||||
```
|
||||
cc_test(
|
||||
name = "example_test",
|
||||
srcs = ["example_test.cpp"],
|
||||
deps = [
|
||||
":example",
|
||||
"@catch2//:catch2_main",
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md#top)
|
||||
|
@@ -365,14 +365,14 @@ There are currently two warnings implemented:
|
||||
## Reporting timings
|
||||
<pre>-d, --durations <yes/no></pre>
|
||||
|
||||
When set to ```yes``` Catch will report the duration of each test case, in milliseconds. Note that it does this regardless of whether a test case passes or fails. Note, also, the certain reporters (e.g. Junit) always report test case durations regardless of this option being set or not.
|
||||
When set to ```yes``` Catch will report the duration of each test case, in seconds with millisecond precision. Note that it does this regardless of whether a test case passes or fails. Note, also, the certain reporters (e.g. Junit) always report test case durations regardless of this option being set or not.
|
||||
|
||||
<pre>-D, --min-duration <value></pre>
|
||||
|
||||
> `--min-duration` was [introduced](https://github.com/catchorg/Catch2/pull/1910) in Catch2 2.13.0
|
||||
|
||||
When set, Catch will report the duration of each test case that took more
|
||||
than <value> seconds, in milliseconds. This option is overridden by both
|
||||
than <value> seconds, in seconds with millisecond precision. This option is overridden by both
|
||||
`-d yes` and `-d no`, so that either all durations are reported, or none
|
||||
are.
|
||||
|
||||
|
@@ -206,12 +206,26 @@ or OO ranges.
|
||||
Unlike `std::uniform_int_distribution`, Catch2's generators also support
|
||||
various single-byte integral types, such as `char` or `bool`.
|
||||
|
||||
Given the same seed, the output from the integral generators is
|
||||
reproducible across different platforms. For floating point generators,
|
||||
we only promise reproducibility on platforms that obey the IEEE 754
|
||||
standard, and where `float` is 4 bytes and `double` is 8 bytes. We provide
|
||||
no guarantees for `long double`, as the internals of `long double` can
|
||||
vary wildly across different platforms.
|
||||
|
||||
#### Reproducibility
|
||||
|
||||
Given the same seed, the output from the integral generators is fully
|
||||
reproducible across different platforms.
|
||||
|
||||
For floating point generators, the situation is much more complex.
|
||||
Generally Catch2 only promises reproducibility (or even just correctness!)
|
||||
on platforms that obey the IEEE-754 standard. Furthermore, reproducibility
|
||||
only applies between binaries that perform floating point math in the
|
||||
same way, e.g. if you compile a binary targetting the x87 FPU and another
|
||||
one targetting SSE2 for floating point math, their results will vary.
|
||||
Similarly, binaries compiled with compiler flags that relax the IEEE-754
|
||||
adherence, e.g. `-ffast-math`, might provide different results than those
|
||||
compiled for strict IEEE-754 adherence.
|
||||
|
||||
Finally, we provide zero guarantees on the reproducibility of generating
|
||||
`long double`s, as the internals of `long double` varies across different
|
||||
platforms.
|
||||
|
||||
|
||||
|
||||
## Generator interface
|
||||
|
@@ -173,3 +173,19 @@ TEST_CASE("b") {
|
||||
|
||||
If you are seeing a problem like this, i.e. weird test paths that trigger only under Clang with `libc++`, or only under very specific version of `libstdc++`, it is very likely you are seeing this. The only known workaround is to use a fixed version of your standard library.
|
||||
|
||||
|
||||
### Visual Studio 2022 -- can't compile assertion with the spaceship operator
|
||||
|
||||
[The C++ standard requires that `std::foo_ordering` is only comparable with
|
||||
a literal 0](https://eel.is/c++draft/cmp#categories.pre-3). There are
|
||||
multiple strategies a stdlib implementation can take to achieve this, and
|
||||
MSVC's STL has changed the strategy they use between two releases of VS 2022.
|
||||
|
||||
With the new strategy, `REQUIRE((a <=> b) == 0)` no longer compiles under
|
||||
MSVC. Note that Catch2 can compile code using MSVC STL's new strategy,
|
||||
but only when compiled with a C++20 conforming compiler. MSVC is currently
|
||||
not conformant enough, but `clang-cl` will compile the assertion above
|
||||
using MSVC STL without problem.
|
||||
|
||||
This change got in with MSVC v19.37](https://godbolt.org/z/KG9obzdvE).
|
||||
|
||||
|
@@ -50,25 +50,43 @@ Both of the string matchers used in the examples above live in the
|
||||
`catch_matchers_string.hpp` header, so to compile the code above also
|
||||
requires `#include <catch2/matchers/catch_matchers_string.hpp>`.
|
||||
|
||||
### Combining operators and lifetimes
|
||||
|
||||
**IMPORTANT**: The combining operators do not take ownership of the
|
||||
matcher objects being combined. This means that if you store combined
|
||||
matcher object, you have to ensure that the matchers being combined
|
||||
outlive its last use. What this means is that the following code leads
|
||||
to a use-after-free (UAF):
|
||||
matcher objects being combined.
|
||||
|
||||
This means that if you store combined matcher object, you have to ensure
|
||||
that the individual matchers being combined outlive the combined matcher.
|
||||
Note that the negation matcher from `!` also counts as combining matcher
|
||||
for this.
|
||||
|
||||
Explained on an example, this is fine
|
||||
```cpp
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_string.hpp>
|
||||
|
||||
TEST_CASE("Bugs, bugs, bugs", "[Bug]"){
|
||||
std::string str = "Bugs as a service";
|
||||
|
||||
auto match_expression = Catch::Matchers::EndsWith( "as a service" ) ||
|
||||
(Catch::Matchers::StartsWith( "Big data" ) && !Catch::Matchers::ContainsSubstring( "web scale" ) );
|
||||
REQUIRE_THAT(str, match_expression);
|
||||
}
|
||||
CHECK_THAT(value, WithinAbs(0, 2e-2) && !WithinULP(0., 1));
|
||||
```
|
||||
|
||||
and so is this
|
||||
```cpp
|
||||
auto is_close_to_zero = WithinAbs(0, 2e-2);
|
||||
auto is_zero = WithinULP(0., 1);
|
||||
|
||||
CHECK_THAT(value, is_close_to_zero && !is_zero);
|
||||
```
|
||||
|
||||
but this is not
|
||||
```cpp
|
||||
auto is_close_to_zero = WithinAbs(0, 2e-2);
|
||||
auto is_zero = WithinULP(0., 1);
|
||||
auto is_close_to_but_not_zero = is_close_to_zero && !is_zero;
|
||||
|
||||
CHECK_THAT(a_value, is_close_to_but_not_zero); // UAF
|
||||
```
|
||||
|
||||
because `!is_zero` creates a temporary instance of Negation matcher,
|
||||
which the `is_close_to_but_not_zero` refers to. After the line ends,
|
||||
the temporary is destroyed and the combined `is_close_to_but_not_zero`
|
||||
matcher now refers to non-existent object, so using it causes use-after-free.
|
||||
|
||||
|
||||
## Built-in matchers
|
||||
|
||||
|
@@ -2,6 +2,9 @@
|
||||
|
||||
# Release notes
|
||||
**Contents**<br>
|
||||
[3.5.3](#353)<br>
|
||||
[3.5.2](#352)<br>
|
||||
[3.5.1](#351)<br>
|
||||
[3.5.0](#350)<br>
|
||||
[3.4.0](#340)<br>
|
||||
[3.3.2](#332)<br>
|
||||
@@ -58,6 +61,49 @@
|
||||
[Even Older versions](#even-older-versions)<br>
|
||||
|
||||
|
||||
## 3.5.3
|
||||
|
||||
### Fixes
|
||||
* Fixed OOB access when computing filename tag (from the `-#` flag) for file without extension (#2798)
|
||||
* Fixed the linking against `log` on Android to be `PRIVATE` (#2815)
|
||||
* Fixed `Wuseless-cast` in benchmarking internals (#2823)
|
||||
|
||||
### Improvements
|
||||
* Restored compatibility with VS2017 (#2792, #2822)
|
||||
* The baseline for Catch2 is still C++14 with some reasonable workarounds for specific compilers, so if VS2017 starts acting up again, the support will be dropped again.
|
||||
* Suppressed clang-tidy's `bugprone-chained-comparison` in assertions (#2801)
|
||||
* Improved the static analysis mode to evaluate arguments to `TEST_CASE` and `SECTION` (#2817)
|
||||
* Clang-tidy should no longer warn about runtime arguments to these macros being unused in static analysis mode.
|
||||
* Clang-tidy can warn on issues involved arguments to these macros.
|
||||
* Added support for literal-zero detectors based on `consteval` constructors
|
||||
* This is required for compiling `REQUIRE((a <=> b) == 0)` against MSVC's stdlib.
|
||||
* Sadly, MSVC still cannot compile this assertion as it does not implement C++20 correctly.
|
||||
* You can use `clang-cl` with MSVC's stdlib instead.
|
||||
* If for some godforsaken reasons you want to understand this better, read the two relevant commits: [`dc51386b9fd61f99ea9c660d01867e6ad489b403`](https://github.com/catchorg/Catch2/commit/dc51386b9fd61f99ea9c660d01867e6ad489b403), and [`0787132fc82a75e3fb255aa9484ca1dc1eff2a30`](https://github.com/catchorg/Catch2/commit/0787132fc82a75e3fb255aa9484ca1dc1eff2a30).
|
||||
|
||||
### Miscellaneous
|
||||
* Disabled tests for FP random generator reproducibility on non-SSE2 x86 targets (#2796)
|
||||
* Modified the in-tree Conan recipe to support Conan 2 (#2805)
|
||||
|
||||
|
||||
## 3.5.2
|
||||
|
||||
### Fixes
|
||||
* Fixed `-Wsubobject-linkage` in the Console reporter (#2794)
|
||||
* Fixed adding new CLI Options to lvalue parser using `|` (#2787)
|
||||
|
||||
|
||||
## 3.5.1
|
||||
|
||||
### Improvements
|
||||
* Significantly improved performance of the CLI parsing.
|
||||
* This includes the cost of preparing the CLI parser, so Catch2's binaries start much faster.
|
||||
|
||||
### Miscellaneous
|
||||
* Added support for Bazel modules (#2781)
|
||||
* Added CMake option to disable the build reproducibility settings (#2785)
|
||||
* Added `log` library linking to the Meson build (#2784)
|
||||
|
||||
|
||||
## 3.5.0
|
||||
|
||||
@@ -75,7 +121,7 @@
|
||||
* Catch2 should automatically disable getenv when compiled for XBox.
|
||||
* Compiling Catch2 with exceptions disabled no longer triggers `Wunused-function` (#2726)
|
||||
* **`random` Generators for integral types are now reproducible across different platforms**
|
||||
* Unlike `<rando>`, Catch2's generators also support 1 byte integral types (`char`, `bool`, ...)
|
||||
* Unlike `<random>`, Catch2's generators also support 1 byte integral types (`char`, `bool`, ...)
|
||||
* **`random` Generators for `float` and `double` are now reproducible across different platforms**
|
||||
* `long double` varies across different platforms too much to be reproducible
|
||||
* This guarantee applies only to platforms with IEEE 754 floats.
|
||||
|
@@ -5,7 +5,7 @@ Reporters are a customization point for most of Catch2's output, e.g.
|
||||
formatting and writing out [assertions (whether passing or failing),
|
||||
sections, test cases, benchmarks, and so on](reporter-events.md#top).
|
||||
|
||||
Catch2 comes with a bunch of reporters by default (currently 8), and
|
||||
Catch2 comes with a bunch of reporters by default (currently 9), and
|
||||
you can also write your own reporter. Because multiple reporters can
|
||||
be active at the same time, your own reporters do not even have to handle
|
||||
all reporter event, just the ones you are interested in, e.g. benchmarks.
|
||||
|
@@ -16,7 +16,7 @@ Ideally you should be using Catch2 through its [CMake integration](cmake-integra
|
||||
Catch2 also provides pkg-config files and two file (header + cpp)
|
||||
distribution, but this documentation will assume you are using CMake. If
|
||||
you are using the two file distribution instead, remember to replace
|
||||
the included header with `catch_amalgamated.hpp`.
|
||||
the included header with `catch_amalgamated.hpp` ([step by step instructions](migrate-v2-to-v3.md#how-to-migrate-projects-from-v2-to-v3)).
|
||||
|
||||
|
||||
## Writing tests
|
||||
|
@@ -385,8 +385,7 @@ struct MyListener : Catch::EventListenerBase {
|
||||
CATCH_REGISTER_LISTENER( MyListener )
|
||||
|
||||
// Get rid of Wweak-tables
|
||||
MyListener::~MyListener() {}
|
||||
|
||||
MyListener::~MyListener() = default;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// 3. Test cases:
|
||||
|
@@ -22,7 +22,7 @@ class out_buff : public std::stringbuf {
|
||||
std::FILE* m_stream;
|
||||
public:
|
||||
out_buff(std::FILE* stream):m_stream(stream) {}
|
||||
~out_buff();
|
||||
~out_buff() override;
|
||||
int sync() override {
|
||||
int ret = 0;
|
||||
for (unsigned char c : str()) {
|
||||
|
41
examples/232-Cfg-CustomMain.cpp
Normal file
41
examples/232-Cfg-CustomMain.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
// 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
|
||||
|
||||
// 232-Cfg-CustomMain.cpp
|
||||
// Show how to use custom main and add a custom option to the CLI parser
|
||||
|
||||
#include <catch2/catch_session.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Catch::Session session; // There must be exactly one instance
|
||||
|
||||
int height = 0; // Some user variable you want to be able to set
|
||||
|
||||
// Build a new parser on top of Catch2's
|
||||
using namespace Catch::Clara;
|
||||
auto cli
|
||||
= session.cli() // Get Catch2's command line parser
|
||||
| Opt( height, "height" ) // bind variable to a new option, with a hint string
|
||||
["--height"] // the option names it will respond to
|
||||
("how high?"); // description string for the help output
|
||||
|
||||
// Now pass the new composite back to Catch2 so it uses that
|
||||
session.cli( cli );
|
||||
|
||||
// Let Catch2 (using Clara) parse the command line
|
||||
int returnCode = session.applyCommandLine( argc, argv );
|
||||
if( returnCode != 0 ) // Indicates a command line error
|
||||
return returnCode;
|
||||
|
||||
// if set on the command line then 'height' is now set at this point
|
||||
std::cout << "height: " << height << '\n';
|
||||
|
||||
return session.run();
|
||||
}
|
@@ -21,7 +21,7 @@
|
||||
namespace {
|
||||
|
||||
// This class shows how to implement a simple generator for Catch tests
|
||||
class RandomIntGenerator : public Catch::Generators::IGenerator<int> {
|
||||
class RandomIntGenerator final : public Catch::Generators::IGenerator<int> {
|
||||
std::minstd_rand m_rand;
|
||||
std::uniform_int_distribution<> m_dist;
|
||||
int current_number;
|
||||
|
@@ -24,12 +24,12 @@ namespace {
|
||||
// Returns a line from a stream. You could have it e.g. read lines from
|
||||
// a file, but to avoid problems with paths in examples, we will use
|
||||
// a fixed stringstream.
|
||||
class LineGenerator : public Catch::Generators::IGenerator<std::string> {
|
||||
class LineGenerator final : public Catch::Generators::IGenerator<std::string> {
|
||||
std::string m_line;
|
||||
std::stringstream m_stream;
|
||||
public:
|
||||
LineGenerator() {
|
||||
m_stream.str("1\n2\n3\n4\n");
|
||||
explicit LineGenerator( std::string const& lines ) {
|
||||
m_stream.str( lines );
|
||||
if (!next()) {
|
||||
Catch::Generators::Detail::throw_generator_exception("Couldn't read a single line");
|
||||
}
|
||||
@@ -49,18 +49,19 @@ std::string const& LineGenerator::get() const {
|
||||
// This helper function provides a nicer UX when instantiating the generator
|
||||
// Notice that it returns an instance of GeneratorWrapper<std::string>, which
|
||||
// is a value-wrapper around std::unique_ptr<IGenerator<std::string>>.
|
||||
Catch::Generators::GeneratorWrapper<std::string> lines(std::string /* ignored for example */) {
|
||||
Catch::Generators::GeneratorWrapper<std::string>
|
||||
lines( std::string const& lines ) {
|
||||
return Catch::Generators::GeneratorWrapper<std::string>(
|
||||
new LineGenerator()
|
||||
);
|
||||
new LineGenerator( lines ) );
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
TEST_CASE("filter can convert types inside the generator expression", "[example][generator]") {
|
||||
auto num = GENERATE(map<int>([](std::string const& line) { return std::stoi(line); },
|
||||
lines("fake-file")));
|
||||
auto num = GENERATE(
|
||||
map<int>( []( std::string const& line ) { return std::stoi( line ); },
|
||||
lines( "1\n2\n3\n4\n" ) ) );
|
||||
|
||||
REQUIRE(num > 0);
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ set( SOURCES_IDIOMATIC_EXAMPLES
|
||||
110-Fix-ClassFixture.cpp
|
||||
120-Bdd-ScenarioGivenWhenThen.cpp
|
||||
210-Evt-EventListeners.cpp
|
||||
232-Cfg-CustomMain.cpp
|
||||
300-Gen-OwnGenerator.cpp
|
||||
301-Gen-MapTypeConversion.cpp
|
||||
302-Gen-Table.cpp
|
||||
@@ -53,7 +54,7 @@ set(ALL_EXAMPLE_TARGETS
|
||||
)
|
||||
|
||||
foreach( name ${ALL_EXAMPLE_TARGETS} )
|
||||
target_link_libraries( ${name} Catch2 Catch2WithMain )
|
||||
target_link_libraries( ${name} Catch2WithMain )
|
||||
endforeach()
|
||||
|
||||
|
||||
|
@@ -6,8 +6,8 @@
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
// Catch v3.5.0
|
||||
// Generated: 2023-12-11 00:51:07.662625
|
||||
// Catch v3.5.3
|
||||
// Generated: 2024-03-01 22:05:56.038084
|
||||
// ----------------------------------------------------------
|
||||
// This file is an amalgamation of multiple different files.
|
||||
// You probably shouldn't edit it directly.
|
||||
@@ -101,8 +101,8 @@ namespace Catch {
|
||||
FDuration mean = FDuration(0);
|
||||
int i = 0;
|
||||
for (auto it = first; it < last; ++it, ++i) {
|
||||
samples.push_back(FDuration(*it));
|
||||
mean += FDuration(*it);
|
||||
samples.push_back(*it);
|
||||
mean += *it;
|
||||
}
|
||||
mean /= i;
|
||||
|
||||
@@ -187,21 +187,16 @@ namespace Catch {
|
||||
double const* last,
|
||||
Estimator& estimator ) {
|
||||
auto n = static_cast<size_t>( last - first );
|
||||
std::uniform_int_distribution<decltype( n )> dist( 0,
|
||||
n - 1 );
|
||||
std::uniform_int_distribution<size_t> dist( 0, n - 1 );
|
||||
|
||||
sample out;
|
||||
out.reserve( resamples );
|
||||
// We allocate the vector outside the loop to avoid realloc
|
||||
// per resample
|
||||
std::vector<double> resampled;
|
||||
resampled.reserve( n );
|
||||
for ( size_t i = 0; i < resamples; ++i ) {
|
||||
resampled.clear();
|
||||
for ( size_t s = 0; s < n; ++s ) {
|
||||
resampled.push_back(
|
||||
first[static_cast<std::ptrdiff_t>(
|
||||
dist( rng ) )] );
|
||||
resampled.push_back( first[dist( rng )] );
|
||||
}
|
||||
const auto estimate =
|
||||
estimator( resampled.data(), resampled.data() + resampled.size() );
|
||||
@@ -563,7 +558,7 @@ bool marginComparison(double lhs, double rhs, double margin) {
|
||||
namespace Catch {
|
||||
|
||||
Approx::Approx ( double value )
|
||||
: m_epsilon( std::numeric_limits<float>::epsilon()*100. ),
|
||||
: m_epsilon( static_cast<double>(std::numeric_limits<float>::epsilon())*100. ),
|
||||
m_margin( 0.0 ),
|
||||
m_scale( 0.0 ),
|
||||
m_value( value )
|
||||
@@ -1043,6 +1038,7 @@ namespace Catch {
|
||||
m_messages.back().message += " := ";
|
||||
start = pos;
|
||||
}
|
||||
default:; // noop
|
||||
}
|
||||
}
|
||||
assert(openings.empty() && "Mismatched openings");
|
||||
@@ -1586,8 +1582,10 @@ namespace Catch {
|
||||
while (lastDot > 0 && filename[lastDot - 1] != '.') {
|
||||
--lastDot;
|
||||
}
|
||||
--lastDot;
|
||||
// In theory we could have filename without any extension in it
|
||||
if ( lastDot == 0 ) { return StringRef(); }
|
||||
|
||||
--lastDot;
|
||||
size_t nameStart = lastDot;
|
||||
while (nameStart > 0 && filename[nameStart - 1] != '/' && filename[nameStart - 1] != '\\') {
|
||||
--nameStart;
|
||||
@@ -1971,13 +1969,13 @@ namespace Detail {
|
||||
}
|
||||
} // end unnamed namespace
|
||||
|
||||
std::string convertIntoString(StringRef string, bool escape_invisibles) {
|
||||
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.
|
||||
ret.reserve(string.size() + 2);
|
||||
|
||||
if (!escape_invisibles) {
|
||||
if (!escapeInvisibles) {
|
||||
ret += '"';
|
||||
ret += string;
|
||||
ret += '"';
|
||||
@@ -2055,7 +2053,7 @@ std::string StringMaker<char const*>::convert(char const* str) {
|
||||
return{ "{null string}" };
|
||||
}
|
||||
}
|
||||
std::string StringMaker<char*>::convert(char* str) {
|
||||
std::string StringMaker<char*>::convert(char* str) { // NOLINT(readability-non-const-parameter)
|
||||
if (str) {
|
||||
return Detail::convertIntoString( str );
|
||||
} else {
|
||||
@@ -2152,8 +2150,8 @@ std::string StringMaker<signed char>::convert(signed char value) {
|
||||
std::string StringMaker<char>::convert(char c) {
|
||||
return ::Catch::Detail::stringify(static_cast<signed char>(c));
|
||||
}
|
||||
std::string StringMaker<unsigned char>::convert(unsigned char c) {
|
||||
return ::Catch::Detail::stringify(static_cast<char>(c));
|
||||
std::string StringMaker<unsigned char>::convert(unsigned char value) {
|
||||
return ::Catch::Detail::stringify(static_cast<char>(value));
|
||||
}
|
||||
|
||||
int StringMaker<float>::precision = 5;
|
||||
@@ -2273,7 +2271,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Version const& libraryVersion() {
|
||||
static Version version( 3, 5, 0, "", 0 );
|
||||
static Version version( 3, 5, 3, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
@@ -2415,9 +2413,7 @@ namespace Catch {
|
||||
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -2627,13 +2623,29 @@ namespace {
|
||||
;
|
||||
}
|
||||
|
||||
std::string normaliseOpt( std::string const& optName ) {
|
||||
#ifdef CATCH_PLATFORM_WINDOWS
|
||||
if ( optName[0] == '/' )
|
||||
return "-" + optName.substr( 1 );
|
||||
else
|
||||
Catch::StringRef normaliseOpt( Catch::StringRef optName ) {
|
||||
if ( optName[0] == '-'
|
||||
#if defined(CATCH_PLATFORM_WINDOWS)
|
||||
|| optName[0] == '/'
|
||||
#endif
|
||||
return optName;
|
||||
) {
|
||||
return optName.substr( 1, optName.size() );
|
||||
}
|
||||
|
||||
return optName;
|
||||
}
|
||||
|
||||
static size_t find_first_separator(Catch::StringRef sr) {
|
||||
auto is_separator = []( char c ) {
|
||||
return c == ' ' || c == ':' || c == '=';
|
||||
};
|
||||
size_t pos = 0;
|
||||
while (pos < sr.size()) {
|
||||
if (is_separator(sr[pos])) { return pos; }
|
||||
++pos;
|
||||
}
|
||||
|
||||
return Catch::StringRef::npos;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -2651,23 +2663,23 @@ namespace Catch {
|
||||
}
|
||||
|
||||
if ( it != itEnd ) {
|
||||
auto const& next = *it;
|
||||
StringRef next = *it;
|
||||
if ( isOptPrefix( next[0] ) ) {
|
||||
auto delimiterPos = next.find_first_of( " :=" );
|
||||
if ( delimiterPos != std::string::npos ) {
|
||||
auto delimiterPos = find_first_separator(next);
|
||||
if ( delimiterPos != StringRef::npos ) {
|
||||
m_tokenBuffer.push_back(
|
||||
{ TokenType::Option,
|
||||
next.substr( 0, delimiterPos ) } );
|
||||
m_tokenBuffer.push_back(
|
||||
{ TokenType::Argument,
|
||||
next.substr( delimiterPos + 1 ) } );
|
||||
next.substr( delimiterPos + 1, next.size() ) } );
|
||||
} else {
|
||||
if ( next[1] != '-' && next.size() > 2 ) {
|
||||
std::string opt = "- ";
|
||||
// Combined short args, e.g. "-ab" for "-a -b"
|
||||
for ( size_t i = 1; i < next.size(); ++i ) {
|
||||
opt[1] = next[i];
|
||||
m_tokenBuffer.push_back(
|
||||
{ TokenType::Option, opt } );
|
||||
{ TokenType::Option,
|
||||
next.substr( i, 1 ) } );
|
||||
}
|
||||
} else {
|
||||
m_tokenBuffer.push_back(
|
||||
@@ -2727,12 +2739,12 @@ namespace Catch {
|
||||
size_t ParserBase::cardinality() const { return 1; }
|
||||
|
||||
InternalParseResult ParserBase::parse( Args const& args ) const {
|
||||
return parse( args.exeName(), TokenStream( args ) );
|
||||
return parse( static_cast<std::string>(args.exeName()), TokenStream( args ) );
|
||||
}
|
||||
|
||||
ParseState::ParseState( ParseResultType type,
|
||||
TokenStream const& remainingTokens ):
|
||||
m_type( type ), m_remainingTokens( remainingTokens ) {}
|
||||
TokenStream remainingTokens ):
|
||||
m_type( type ), m_remainingTokens( CATCH_MOVE(remainingTokens) ) {}
|
||||
|
||||
ParserResult BoundFlagRef::setFlag( bool flag ) {
|
||||
m_ref = flag;
|
||||
@@ -2750,34 +2762,34 @@ namespace Catch {
|
||||
} // namespace Detail
|
||||
|
||||
Detail::InternalParseResult Arg::parse(std::string const&,
|
||||
Detail::TokenStream const& tokens) const {
|
||||
Detail::TokenStream tokens) const {
|
||||
auto validationResult = validate();
|
||||
if (!validationResult)
|
||||
return Detail::InternalParseResult(validationResult);
|
||||
|
||||
auto remainingTokens = tokens;
|
||||
auto const& token = *remainingTokens;
|
||||
auto token = *tokens;
|
||||
if (token.type != Detail::TokenType::Argument)
|
||||
return Detail::InternalParseResult::ok(Detail::ParseState(
|
||||
ParseResultType::NoMatch, remainingTokens));
|
||||
ParseResultType::NoMatch, CATCH_MOVE(tokens)));
|
||||
|
||||
assert(!m_ref->isFlag());
|
||||
auto valueRef =
|
||||
static_cast<Detail::BoundValueRefBase*>(m_ref.get());
|
||||
|
||||
auto result = valueRef->setValue(remainingTokens->token);
|
||||
if (!result)
|
||||
return Detail::InternalParseResult(result);
|
||||
auto result = valueRef->setValue(static_cast<std::string>(token.token));
|
||||
if ( !result )
|
||||
return Detail::InternalParseResult( result );
|
||||
else
|
||||
return Detail::InternalParseResult::ok(Detail::ParseState(
|
||||
ParseResultType::Matched, ++remainingTokens));
|
||||
return Detail::InternalParseResult::ok(
|
||||
Detail::ParseState( ParseResultType::Matched,
|
||||
CATCH_MOVE( ++tokens ) ) );
|
||||
}
|
||||
|
||||
Opt::Opt(bool& ref) :
|
||||
ParserRefImpl(std::make_shared<Detail::BoundFlagRef>(ref)) {}
|
||||
|
||||
std::vector<Detail::HelpColumns> Opt::getHelpColumns() const {
|
||||
std::ostringstream oss;
|
||||
Detail::HelpColumns Opt::getHelpColumns() const {
|
||||
ReusableStringStream oss;
|
||||
bool first = true;
|
||||
for (auto const& opt : m_optNames) {
|
||||
if (first)
|
||||
@@ -2788,10 +2800,10 @@ namespace Catch {
|
||||
}
|
||||
if (!m_hint.empty())
|
||||
oss << " <" << m_hint << '>';
|
||||
return { { oss.str(), m_description } };
|
||||
return { oss.str(), m_description };
|
||||
}
|
||||
|
||||
bool Opt::isMatch(std::string const& optToken) const {
|
||||
bool Opt::isMatch(StringRef optToken) const {
|
||||
auto normalisedToken = normaliseOpt(optToken);
|
||||
for (auto const& name : m_optNames) {
|
||||
if (normaliseOpt(name) == normalisedToken)
|
||||
@@ -2801,15 +2813,14 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Detail::InternalParseResult Opt::parse(std::string const&,
|
||||
Detail::TokenStream const& tokens) const {
|
||||
Detail::TokenStream tokens) const {
|
||||
auto validationResult = validate();
|
||||
if (!validationResult)
|
||||
return Detail::InternalParseResult(validationResult);
|
||||
|
||||
auto remainingTokens = tokens;
|
||||
if (remainingTokens &&
|
||||
remainingTokens->type == Detail::TokenType::Option) {
|
||||
auto const& token = *remainingTokens;
|
||||
if (tokens &&
|
||||
tokens->type == Detail::TokenType::Option) {
|
||||
auto const& token = *tokens;
|
||||
if (isMatch(token.token)) {
|
||||
if (m_ref->isFlag()) {
|
||||
auto flagRef =
|
||||
@@ -2821,35 +2832,35 @@ namespace Catch {
|
||||
if (result.value() ==
|
||||
ParseResultType::ShortCircuitAll)
|
||||
return Detail::InternalParseResult::ok(Detail::ParseState(
|
||||
result.value(), remainingTokens));
|
||||
result.value(), CATCH_MOVE(tokens)));
|
||||
} else {
|
||||
auto valueRef =
|
||||
static_cast<Detail::BoundValueRefBase*>(
|
||||
m_ref.get());
|
||||
++remainingTokens;
|
||||
if (!remainingTokens)
|
||||
++tokens;
|
||||
if (!tokens)
|
||||
return Detail::InternalParseResult::runtimeError(
|
||||
"Expected argument following " +
|
||||
token.token);
|
||||
auto const& argToken = *remainingTokens;
|
||||
auto const& argToken = *tokens;
|
||||
if (argToken.type != Detail::TokenType::Argument)
|
||||
return Detail::InternalParseResult::runtimeError(
|
||||
"Expected argument following " +
|
||||
token.token);
|
||||
const auto result = valueRef->setValue(argToken.token);
|
||||
const auto result = valueRef->setValue(static_cast<std::string>(argToken.token));
|
||||
if (!result)
|
||||
return Detail::InternalParseResult(result);
|
||||
if (result.value() ==
|
||||
ParseResultType::ShortCircuitAll)
|
||||
return Detail::InternalParseResult::ok(Detail::ParseState(
|
||||
result.value(), remainingTokens));
|
||||
result.value(), CATCH_MOVE(tokens)));
|
||||
}
|
||||
return Detail::InternalParseResult::ok(Detail::ParseState(
|
||||
ParseResultType::Matched, ++remainingTokens));
|
||||
ParseResultType::Matched, CATCH_MOVE(++tokens)));
|
||||
}
|
||||
}
|
||||
return Detail::InternalParseResult::ok(
|
||||
Detail::ParseState(ParseResultType::NoMatch, remainingTokens));
|
||||
Detail::ParseState(ParseResultType::NoMatch, CATCH_MOVE(tokens)));
|
||||
}
|
||||
|
||||
Detail::Result Opt::validate() const {
|
||||
@@ -2881,9 +2892,9 @@ namespace Catch {
|
||||
|
||||
Detail::InternalParseResult
|
||||
ExeName::parse(std::string const&,
|
||||
Detail::TokenStream const& tokens) const {
|
||||
Detail::TokenStream tokens) const {
|
||||
return Detail::InternalParseResult::ok(
|
||||
Detail::ParseState(ParseResultType::NoMatch, tokens));
|
||||
Detail::ParseState(ParseResultType::NoMatch, CATCH_MOVE(tokens)));
|
||||
}
|
||||
|
||||
ParserResult ExeName::set(std::string const& newName) {
|
||||
@@ -2913,9 +2924,9 @@ namespace Catch {
|
||||
|
||||
std::vector<Detail::HelpColumns> Parser::getHelpColumns() const {
|
||||
std::vector<Detail::HelpColumns> cols;
|
||||
cols.reserve( m_options.size() );
|
||||
for ( auto const& o : m_options ) {
|
||||
auto childCols = o.getHelpColumns();
|
||||
cols.insert( cols.end(), childCols.begin(), childCols.end() );
|
||||
cols.push_back(o.getHelpColumns());
|
||||
}
|
||||
return cols;
|
||||
}
|
||||
@@ -2953,12 +2964,12 @@ namespace Catch {
|
||||
|
||||
optWidth = ( std::min )( optWidth, consoleWidth / 2 );
|
||||
|
||||
for ( auto const& cols : rows ) {
|
||||
auto row = TextFlow::Column( cols.left )
|
||||
for ( auto& cols : rows ) {
|
||||
auto row = TextFlow::Column( CATCH_MOVE(cols.left) )
|
||||
.width( optWidth )
|
||||
.indent( 2 ) +
|
||||
TextFlow::Spacer( 4 ) +
|
||||
TextFlow::Column( cols.right )
|
||||
TextFlow::Column( static_cast<std::string>(cols.descriptions) )
|
||||
.width( consoleWidth - 7 - optWidth );
|
||||
os << row << '\n';
|
||||
}
|
||||
@@ -2980,7 +2991,7 @@ namespace Catch {
|
||||
|
||||
Detail::InternalParseResult
|
||||
Parser::parse( std::string const& exeName,
|
||||
Detail::TokenStream const& tokens ) const {
|
||||
Detail::TokenStream tokens ) const {
|
||||
|
||||
struct ParserInfo {
|
||||
ParserBase const* parser = nullptr;
|
||||
@@ -2998,7 +3009,7 @@ namespace Catch {
|
||||
m_exeName.set( exeName );
|
||||
|
||||
auto result = Detail::InternalParseResult::ok(
|
||||
Detail::ParseState( ParseResultType::NoMatch, tokens ) );
|
||||
Detail::ParseState( ParseResultType::NoMatch, CATCH_MOVE(tokens) ) );
|
||||
while ( result.value().remainingTokens() ) {
|
||||
bool tokenParsed = false;
|
||||
|
||||
@@ -3006,7 +3017,7 @@ namespace Catch {
|
||||
if ( parseInfo.parser->cardinality() == 0 ||
|
||||
parseInfo.count < parseInfo.parser->cardinality() ) {
|
||||
result = parseInfo.parser->parse(
|
||||
exeName, result.value().remainingTokens() );
|
||||
exeName, CATCH_MOVE(result).value().remainingTokens() );
|
||||
if ( !result )
|
||||
return result;
|
||||
if ( result.value().type() !=
|
||||
@@ -3032,7 +3043,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> args) :
|
||||
Args::Args(std::initializer_list<StringRef> args) :
|
||||
m_exeName(*args.begin()),
|
||||
m_args(args.begin() + 1, args.end()) {}
|
||||
|
||||
@@ -3084,7 +3095,7 @@ namespace Catch {
|
||||
line = trim(line);
|
||||
if( !line.empty() && !startsWith( line, '#' ) ) {
|
||||
if( !startsWith( line, '"' ) )
|
||||
line = '"' + line + '"';
|
||||
line = '"' + CATCH_MOVE(line) + '"';
|
||||
config.testsOrTags.push_back( line );
|
||||
config.testsOrTags.emplace_back( "," );
|
||||
}
|
||||
@@ -3338,8 +3349,8 @@ namespace Catch {
|
||||
( "split the tests to execute into this many groups" )
|
||||
| Opt( setShardIndex, "shard index" )
|
||||
["--shard-index"]
|
||||
( "index of the group of tests to execute (see --shard-count)" ) |
|
||||
Opt( config.allowZeroTests )
|
||||
( "index of the group of tests to execute (see --shard-count)" )
|
||||
| Opt( config.allowZeroTests )
|
||||
["--allow-running-no-tests"]
|
||||
( "Treat 'No tests run' as a success" )
|
||||
| Arg( config.testsOrTags, "test name|pattern|tags" )
|
||||
@@ -3565,21 +3576,21 @@ namespace {
|
||||
|
||||
namespace Catch {
|
||||
|
||||
Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode implSelection,
|
||||
Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
|
||||
IStream* stream ) {
|
||||
#if defined( CATCH_CONFIG_COLOUR_WIN32 )
|
||||
if ( implSelection == ColourMode::Win32 ) {
|
||||
if ( colourSelection == ColourMode::Win32 ) {
|
||||
return Detail::make_unique<Win32ColourImpl>( stream );
|
||||
}
|
||||
#endif
|
||||
if ( implSelection == ColourMode::ANSI ) {
|
||||
if ( colourSelection == ColourMode::ANSI ) {
|
||||
return Detail::make_unique<ANSIColourImpl>( stream );
|
||||
}
|
||||
if ( implSelection == ColourMode::None ) {
|
||||
if ( colourSelection == ColourMode::None ) {
|
||||
return Detail::make_unique<NoColourImpl>( stream );
|
||||
}
|
||||
|
||||
if ( implSelection == ColourMode::PlatformDefault) {
|
||||
if ( colourSelection == ColourMode::PlatformDefault) {
|
||||
#if defined( CATCH_CONFIG_COLOUR_WIN32 )
|
||||
if ( Win32ColourImpl::useImplementationForStream( *stream ) ) {
|
||||
return Detail::make_unique<Win32ColourImpl>( stream );
|
||||
@@ -3591,7 +3602,7 @@ namespace Catch {
|
||||
return Detail::make_unique<NoColourImpl>( stream );
|
||||
}
|
||||
|
||||
CATCH_ERROR( "Could not create colour impl for selection " << static_cast<int>(implSelection) );
|
||||
CATCH_ERROR( "Could not create colour impl for selection " << static_cast<int>(colourSelection) );
|
||||
}
|
||||
|
||||
bool isColourImplAvailable( ColourMode colourSelection ) {
|
||||
@@ -3799,7 +3810,12 @@ namespace Catch {
|
||||
|
||||
namespace Catch {
|
||||
|
||||
ITransientExpression::~ITransientExpression() = default;
|
||||
void ITransientExpression::streamReconstructedExpression(
|
||||
std::ostream& os ) const {
|
||||
// We can't make this function pure virtual to keep ITransientExpression
|
||||
// constexpr, so we write error message instead
|
||||
os << "Some class derived from ITransientExpression without overriding streamReconstructedExpression";
|
||||
}
|
||||
|
||||
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
|
||||
if( lhs.size() + rhs.size() < 40 &&
|
||||
@@ -4367,7 +4383,6 @@ namespace Detail {
|
||||
CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << '\'' );
|
||||
m_ofs << std::unitbuf;
|
||||
}
|
||||
~FileStream() override = default;
|
||||
public: // IStream
|
||||
std::ostream& stream() override {
|
||||
return m_ofs;
|
||||
@@ -4382,7 +4397,6 @@ namespace Detail {
|
||||
// Store the streambuf from cout up-front because
|
||||
// cout may get redirected when running tests
|
||||
CoutStream() : m_os( Catch::cout().rdbuf() ) {}
|
||||
~CoutStream() override = default;
|
||||
|
||||
public: // IStream
|
||||
std::ostream& stream() override { return m_os; }
|
||||
@@ -4396,7 +4410,6 @@ namespace Detail {
|
||||
// Store the streambuf from cerr up-front because
|
||||
// cout may get redirected when running tests
|
||||
CerrStream(): m_os( Catch::cerr().rdbuf() ) {}
|
||||
~CerrStream() override = default;
|
||||
|
||||
public: // IStream
|
||||
std::ostream& stream() override { return m_os; }
|
||||
@@ -4414,8 +4427,6 @@ namespace Detail {
|
||||
m_os( m_streamBuf.get() )
|
||||
{}
|
||||
|
||||
~DebugOutStream() override = default;
|
||||
|
||||
public: // IStream
|
||||
std::ostream& stream() override { return m_os; }
|
||||
};
|
||||
@@ -4470,7 +4481,7 @@ namespace Catch {
|
||||
m_os{ os }, m_indent_level{ indent_level } {
|
||||
m_os << '{';
|
||||
}
|
||||
JsonObjectWriter::JsonObjectWriter( JsonObjectWriter&& source ):
|
||||
JsonObjectWriter::JsonObjectWriter( JsonObjectWriter&& source ) noexcept:
|
||||
m_os{ source.m_os },
|
||||
m_indent_level{ source.m_indent_level },
|
||||
m_should_comma{ source.m_should_comma },
|
||||
@@ -4501,7 +4512,7 @@ namespace Catch {
|
||||
m_os{ os }, m_indent_level{ indent_level } {
|
||||
m_os << '[';
|
||||
}
|
||||
JsonArrayWriter::JsonArrayWriter( JsonArrayWriter&& source ):
|
||||
JsonArrayWriter::JsonArrayWriter( JsonArrayWriter&& source ) noexcept:
|
||||
m_os{ source.m_os },
|
||||
m_indent_level{ source.m_indent_level },
|
||||
m_should_comma{ source.m_should_comma },
|
||||
@@ -4641,7 +4652,6 @@ Catch::LeakDetector::~LeakDetector() {
|
||||
|
||||
|
||||
|
||||
|
||||
namespace Catch {
|
||||
namespace {
|
||||
|
||||
@@ -5281,7 +5291,7 @@ namespace Catch {
|
||||
auto kv = splitKVPair( parts[i] );
|
||||
auto key = kv.key, value = kv.value;
|
||||
|
||||
if ( key.empty() || value.empty() ) {
|
||||
if ( key.empty() || value.empty() ) { // NOLINT(bugprone-branch-clone)
|
||||
return {};
|
||||
} else if ( key[0] == 'X' ) {
|
||||
// This is a reporter-specific option, we don't check these
|
||||
@@ -5429,7 +5439,6 @@ namespace Catch {
|
||||
TrackerContext& ctx,
|
||||
ITracker* parent ):
|
||||
TrackerBase( CATCH_MOVE( nameAndLocation ), ctx, parent ) {}
|
||||
~GeneratorTracker() override = default;
|
||||
|
||||
static GeneratorTracker*
|
||||
acquire( TrackerContext& ctx,
|
||||
@@ -6296,17 +6305,29 @@ namespace Catch {
|
||||
}
|
||||
|
||||
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
|
||||
bool replaced = false;
|
||||
std::size_t i = str.find( replaceThis );
|
||||
while( i != std::string::npos ) {
|
||||
replaced = true;
|
||||
str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
|
||||
if( i < str.size()-withThis.size() )
|
||||
i = str.find( replaceThis, i+withThis.size() );
|
||||
if (i == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
std::size_t copyBegin = 0;
|
||||
std::string origStr = CATCH_MOVE(str);
|
||||
str.clear();
|
||||
// There is at least one replacement, so reserve with the best guess
|
||||
// we can make without actually counting the number of occurences.
|
||||
str.reserve(origStr.size() - replaceThis.size() + withThis.size());
|
||||
do {
|
||||
str.append(origStr, copyBegin, i-copyBegin );
|
||||
str += withThis;
|
||||
copyBegin = i + replaceThis.size();
|
||||
if( copyBegin < origStr.size() )
|
||||
i = origStr.find( replaceThis, copyBegin );
|
||||
else
|
||||
i = std::string::npos;
|
||||
} while( i != std::string::npos );
|
||||
if ( copyBegin < origStr.size() ) {
|
||||
str.append(origStr, copyBegin, origStr.size() );
|
||||
}
|
||||
return replaced;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) {
|
||||
@@ -6527,7 +6548,6 @@ namespace Catch {
|
||||
return sorted;
|
||||
}
|
||||
case TestRunOrder::Randomized: {
|
||||
seedRng(config);
|
||||
using TestWithHash = std::pair<TestCaseInfoHasher::hash_t, TestCaseHandle>;
|
||||
|
||||
TestCaseInfoHasher h{ config.rngSeed() };
|
||||
@@ -7390,23 +7410,36 @@ namespace Catch {
|
||||
return os;
|
||||
}
|
||||
|
||||
Columns Column::operator+( Column const& other ) {
|
||||
Columns operator+(Column const& lhs, Column const& rhs) {
|
||||
Columns cols;
|
||||
cols += *this;
|
||||
cols += other;
|
||||
cols += lhs;
|
||||
cols += rhs;
|
||||
return cols;
|
||||
}
|
||||
Columns operator+(Column&& lhs, Column&& rhs) {
|
||||
Columns cols;
|
||||
cols += CATCH_MOVE( lhs );
|
||||
cols += CATCH_MOVE( rhs );
|
||||
return cols;
|
||||
}
|
||||
|
||||
Columns& Columns::operator+=( Column const& col ) {
|
||||
m_columns.push_back( col );
|
||||
return *this;
|
||||
Columns& operator+=(Columns& lhs, Column const& rhs) {
|
||||
lhs.m_columns.push_back( rhs );
|
||||
return lhs;
|
||||
}
|
||||
|
||||
Columns Columns::operator+( Column const& col ) {
|
||||
Columns combined = *this;
|
||||
combined += col;
|
||||
Columns& operator+=(Columns& lhs, Column&& rhs) {
|
||||
lhs.m_columns.push_back( CATCH_MOVE(rhs) );
|
||||
return lhs;
|
||||
}
|
||||
Columns operator+( Columns const& lhs, Column const& rhs ) {
|
||||
auto combined( lhs );
|
||||
combined += rhs;
|
||||
return combined;
|
||||
}
|
||||
Columns operator+( Columns&& lhs, Column&& rhs ) {
|
||||
lhs += CATCH_MOVE( rhs );
|
||||
return CATCH_MOVE( lhs );
|
||||
}
|
||||
|
||||
} // namespace TextFlow
|
||||
} // namespace Catch
|
||||
@@ -8775,13 +8808,6 @@ findMax( std::size_t& i, std::size_t& j, std::size_t& k, std::size_t& l ) {
|
||||
return l;
|
||||
}
|
||||
|
||||
enum class Justification { Left, Right };
|
||||
|
||||
struct ColumnInfo {
|
||||
std::string name;
|
||||
std::size_t width;
|
||||
Justification justification;
|
||||
};
|
||||
struct ColumnBreak {};
|
||||
struct RowBreak {};
|
||||
struct OutputFlush {};
|
||||
@@ -8859,6 +8885,14 @@ public:
|
||||
};
|
||||
} // end anon namespace
|
||||
|
||||
enum class Justification { Left, Right };
|
||||
|
||||
struct ColumnInfo {
|
||||
std::string name;
|
||||
std::size_t width;
|
||||
Justification justification;
|
||||
};
|
||||
|
||||
class TablePrinter {
|
||||
std::ostream& m_os;
|
||||
std::vector<ColumnInfo> m_columnInfos;
|
||||
@@ -8881,11 +8915,10 @@ public:
|
||||
*this << RowBreak();
|
||||
|
||||
TextFlow::Columns headerCols;
|
||||
auto spacer = TextFlow::Spacer(2);
|
||||
for (auto const& info : m_columnInfos) {
|
||||
assert(info.width > 2);
|
||||
headerCols += TextFlow::Column(info.name).width(info.width - 2);
|
||||
headerCols += spacer;
|
||||
headerCols += TextFlow::Spacer( 2 );
|
||||
}
|
||||
m_os << headerCols << '\n';
|
||||
|
||||
@@ -9086,8 +9119,8 @@ void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {
|
||||
m_stream << '\n' << std::flush;
|
||||
StreamingReporterBase::testRunEnded(_testRunStats);
|
||||
}
|
||||
void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) {
|
||||
StreamingReporterBase::testRunStarting(_testInfo);
|
||||
void ConsoleReporter::testRunStarting(TestRunInfo const& _testRunInfo) {
|
||||
StreamingReporterBase::testRunStarting(_testRunInfo);
|
||||
if ( m_config->testSpec().hasFilters() ) {
|
||||
m_stream << m_colour->guardColour( Colour::BrightYellow ) << "Filters: "
|
||||
<< m_config->testSpec() << '\n';
|
||||
@@ -9240,8 +9273,7 @@ namespace Catch {
|
||||
namespace {
|
||||
struct BySectionInfo {
|
||||
BySectionInfo( SectionInfo const& other ): m_other( other ) {}
|
||||
BySectionInfo( BySectionInfo const& other ):
|
||||
m_other( other.m_other ) {}
|
||||
BySectionInfo( BySectionInfo const& other ) = default;
|
||||
bool operator()(
|
||||
Detail::unique_ptr<CumulativeReporterBase::SectionNode> const&
|
||||
node ) const {
|
||||
@@ -9866,8 +9898,8 @@ namespace Catch {
|
||||
return "Outputs listings as JSON. Test listing is Work-in-Progress!";
|
||||
}
|
||||
|
||||
void JsonReporter::testRunStarting( TestRunInfo const& testInfo ) {
|
||||
StreamingReporterBase::testRunStarting( testInfo );
|
||||
void JsonReporter::testRunStarting( TestRunInfo const& runInfo ) {
|
||||
StreamingReporterBase::testRunStarting( runInfo );
|
||||
endListing();
|
||||
|
||||
assert( isInside( Writer::Object ) );
|
||||
@@ -10165,7 +10197,7 @@ namespace Catch {
|
||||
|
||||
static void normalizeNamespaceMarkers(std::string& str) {
|
||||
std::size_t pos = str.find( "::" );
|
||||
while ( pos != str.npos ) {
|
||||
while ( pos != std::string::npos ) {
|
||||
str.replace( pos, 2, "." );
|
||||
pos += 1;
|
||||
pos = str.find( "::", pos );
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
project(
|
||||
'catch2',
|
||||
'cpp',
|
||||
version: '3.5.0', # CML version placeholder, don't delete
|
||||
version: '3.5.3', # CML version placeholder, don't delete
|
||||
license: 'BSL-1.0',
|
||||
meson_version: '>=0.54.1',
|
||||
)
|
||||
|
@@ -348,11 +348,13 @@ source_group("generated headers"
|
||||
)
|
||||
|
||||
add_library(Catch2 ${ALL_FILES})
|
||||
add_build_reproducibility_settings(Catch2)
|
||||
if (CATCH_ENABLE_REPRODUCIBLE_BUILD)
|
||||
add_build_reproducibility_settings(Catch2)
|
||||
endif()
|
||||
add_library(Catch2::Catch2 ALIAS Catch2)
|
||||
|
||||
if (ANDROID)
|
||||
target_link_libraries(Catch2 INTERFACE log)
|
||||
target_link_libraries(Catch2 PRIVATE log)
|
||||
endif()
|
||||
|
||||
set_target_properties(Catch2 PROPERTIES
|
||||
@@ -401,7 +403,9 @@ target_include_directories(Catch2
|
||||
add_library(Catch2WithMain
|
||||
${SOURCES_DIR}/internal/catch_main.cpp
|
||||
)
|
||||
add_build_reproducibility_settings(Catch2WithMain)
|
||||
if (CATCH_ENABLE_REPRODUCIBLE_BUILD)
|
||||
add_build_reproducibility_settings(Catch2WithMain)
|
||||
endif()
|
||||
add_library(Catch2::Catch2WithMain ALIAS Catch2WithMain)
|
||||
target_link_libraries(Catch2WithMain PUBLIC Catch2)
|
||||
set_target_properties(Catch2WithMain
|
||||
|
@@ -63,8 +63,8 @@ namespace Catch {
|
||||
FDuration mean = FDuration(0);
|
||||
int i = 0;
|
||||
for (auto it = first; it < last; ++it, ++i) {
|
||||
samples.push_back(FDuration(*it));
|
||||
mean += FDuration(*it);
|
||||
samples.push_back(*it);
|
||||
mean += *it;
|
||||
}
|
||||
mean /= i;
|
||||
|
||||
|
@@ -55,12 +55,12 @@ namespace Catch {
|
||||
|
||||
template <typename Clock>
|
||||
int warmup() {
|
||||
return run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(warmup_time), warmup_seed, &resolution<Clock>)
|
||||
return run_for_at_least<Clock>(warmup_time, warmup_seed, &resolution<Clock>)
|
||||
.iterations;
|
||||
}
|
||||
template <typename Clock>
|
||||
EnvironmentEstimate estimate_clock_resolution(int iterations) {
|
||||
auto r = run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(clock_resolution_estimation_time), iterations, &resolution<Clock>)
|
||||
auto r = run_for_at_least<Clock>(clock_resolution_estimation_time, iterations, &resolution<Clock>)
|
||||
.result;
|
||||
return {
|
||||
FDuration(mean(r.data(), r.data() + r.size())),
|
||||
@@ -82,7 +82,7 @@ namespace Catch {
|
||||
};
|
||||
time_clock(1);
|
||||
int iters = clock_cost_estimation_iterations;
|
||||
auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(clock_cost_estimation_time), iters, time_clock);
|
||||
auto&& r = run_for_at_least<Clock>(clock_cost_estimation_time, iters, time_clock);
|
||||
std::vector<double> times;
|
||||
int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
|
||||
times.reserve(static_cast<size_t>(nsamples));
|
||||
|
@@ -38,21 +38,16 @@ namespace Catch {
|
||||
double const* last,
|
||||
Estimator& estimator ) {
|
||||
auto n = static_cast<size_t>( last - first );
|
||||
std::uniform_int_distribution<decltype( n )> dist( 0,
|
||||
n - 1 );
|
||||
std::uniform_int_distribution<size_t> dist( 0, n - 1 );
|
||||
|
||||
sample out;
|
||||
out.reserve( resamples );
|
||||
// We allocate the vector outside the loop to avoid realloc
|
||||
// per resample
|
||||
std::vector<double> resampled;
|
||||
resampled.reserve( n );
|
||||
for ( size_t i = 0; i < resamples; ++i ) {
|
||||
resampled.clear();
|
||||
for ( size_t s = 0; s < n; ++s ) {
|
||||
resampled.push_back(
|
||||
first[static_cast<std::ptrdiff_t>(
|
||||
dist( rng ) )] );
|
||||
resampled.push_back( first[dist( rng )] );
|
||||
}
|
||||
const auto estimate =
|
||||
estimator( resampled.data(), resampled.data() + resampled.size() );
|
||||
|
@@ -25,7 +25,7 @@ bool marginComparison(double lhs, double rhs, double margin) {
|
||||
namespace Catch {
|
||||
|
||||
Approx::Approx ( double value )
|
||||
: m_epsilon( std::numeric_limits<float>::epsilon()*100. ),
|
||||
: m_epsilon( static_cast<double>(std::numeric_limits<float>::epsilon())*100. ),
|
||||
m_margin( 0.0 ),
|
||||
m_scale( 0.0 ),
|
||||
m_value( value )
|
||||
|
@@ -69,7 +69,7 @@ namespace Catch {
|
||||
bool benchmarkNoAnalysis = false;
|
||||
unsigned int benchmarkSamples = 100;
|
||||
double benchmarkConfidenceInterval = 0.95;
|
||||
unsigned int benchmarkResamples = 100000;
|
||||
unsigned int benchmarkResamples = 100'000;
|
||||
std::chrono::milliseconds::rep benchmarkWarmupTime = 100;
|
||||
|
||||
Verbosity verbosity = Verbosity::Normal;
|
||||
|
@@ -91,6 +91,7 @@ namespace Catch {
|
||||
m_messages.back().message += " := ";
|
||||
start = pos;
|
||||
}
|
||||
default:; // noop
|
||||
}
|
||||
}
|
||||
assert(openings.empty() && "Mismatched openings");
|
||||
|
@@ -20,7 +20,6 @@
|
||||
#include <catch2/internal/catch_noncopyable.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_reporter_factory.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
#include <catch2/internal/catch_reporter_registry.hpp>
|
||||
|
||||
#include <exception>
|
||||
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#include <catch2/internal/catch_enforce.hpp>
|
||||
#include <catch2/internal/catch_string_manip.hpp>
|
||||
#include <catch2/internal/catch_case_insensitive_comparisons.hpp>
|
||||
#include <catch2/internal/catch_test_registry.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
@@ -84,8 +85,10 @@ namespace Catch {
|
||||
while (lastDot > 0 && filename[lastDot - 1] != '.') {
|
||||
--lastDot;
|
||||
}
|
||||
--lastDot;
|
||||
// In theory we could have filename without any extension in it
|
||||
if ( lastDot == 0 ) { return StringRef(); }
|
||||
|
||||
--lastDot;
|
||||
size_t nameStart = lastDot;
|
||||
while (nameStart > 0 && filename[nameStart - 1] != '/' && filename[nameStart - 1] != '\\') {
|
||||
--nameStart;
|
||||
|
@@ -8,10 +8,10 @@
|
||||
#ifndef CATCH_TEST_CASE_INFO_HPP_INCLUDED
|
||||
#define CATCH_TEST_CASE_INFO_HPP_INCLUDED
|
||||
|
||||
#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_test_registry.hpp>
|
||||
#include <catch2/internal/catch_unique_ptr.hpp>
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace Catch {
|
||||
};
|
||||
|
||||
class ITestInvoker;
|
||||
struct NameAndTags;
|
||||
|
||||
enum class TestCaseProperties : uint8_t {
|
||||
None = 0,
|
||||
@@ -67,7 +68,7 @@ namespace Catch {
|
||||
struct TestCaseInfo : Detail::NonCopyable {
|
||||
|
||||
TestCaseInfo(StringRef _className,
|
||||
NameAndTags const& _tags,
|
||||
NameAndTags const& _nameAndTags,
|
||||
SourceLineInfo const& _lineInfo);
|
||||
|
||||
bool isHidden() const;
|
||||
|
@@ -54,13 +54,13 @@ namespace Detail {
|
||||
}
|
||||
} // end unnamed namespace
|
||||
|
||||
std::string convertIntoString(StringRef string, bool escape_invisibles) {
|
||||
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.
|
||||
ret.reserve(string.size() + 2);
|
||||
|
||||
if (!escape_invisibles) {
|
||||
if (!escapeInvisibles) {
|
||||
ret += '"';
|
||||
ret += string;
|
||||
ret += '"';
|
||||
@@ -138,7 +138,7 @@ std::string StringMaker<char const*>::convert(char const* str) {
|
||||
return{ "{null string}" };
|
||||
}
|
||||
}
|
||||
std::string StringMaker<char*>::convert(char* str) {
|
||||
std::string StringMaker<char*>::convert(char* str) { // NOLINT(readability-non-const-parameter)
|
||||
if (str) {
|
||||
return Detail::convertIntoString( str );
|
||||
} else {
|
||||
@@ -235,8 +235,8 @@ std::string StringMaker<signed char>::convert(signed char value) {
|
||||
std::string StringMaker<char>::convert(char c) {
|
||||
return ::Catch::Detail::stringify(static_cast<signed char>(c));
|
||||
}
|
||||
std::string StringMaker<unsigned char>::convert(unsigned char c) {
|
||||
return ::Catch::Detail::stringify(static_cast<char>(c));
|
||||
std::string StringMaker<unsigned char>::convert(unsigned char value) {
|
||||
return ::Catch::Detail::stringify(static_cast<char>(value));
|
||||
}
|
||||
|
||||
int StringMaker<float>::precision = 5;
|
||||
|
@@ -279,11 +279,11 @@ namespace Catch {
|
||||
};
|
||||
template<>
|
||||
struct StringMaker<signed char> {
|
||||
static std::string convert(signed char c);
|
||||
static std::string convert(signed char value);
|
||||
};
|
||||
template<>
|
||||
struct StringMaker<unsigned char> {
|
||||
static std::string convert(unsigned char c);
|
||||
static std::string convert(unsigned char value);
|
||||
};
|
||||
|
||||
template<>
|
||||
|
@@ -36,7 +36,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Version const& libraryVersion() {
|
||||
static Version version( 3, 5, 0, "", 0 );
|
||||
static Version version( 3, 5, 3, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
|
@@ -10,6 +10,6 @@
|
||||
|
||||
#define CATCH_VERSION_MAJOR 3
|
||||
#define CATCH_VERSION_MINOR 5
|
||||
#define CATCH_VERSION_PATCH 0
|
||||
#define CATCH_VERSION_PATCH 3
|
||||
|
||||
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
|
||||
|
@@ -37,12 +37,6 @@ namespace Detail {
|
||||
}
|
||||
|
||||
public:
|
||||
~IGenerator() override = default;
|
||||
IGenerator() = default;
|
||||
IGenerator(IGenerator const&) = default;
|
||||
IGenerator& operator=(IGenerator const&) = default;
|
||||
|
||||
|
||||
// Returns the current element of the generator
|
||||
//
|
||||
// \Precondition The generator is either freshly constructed,
|
||||
|
@@ -8,7 +8,6 @@
|
||||
#ifndef CATCH_GENERATORS_RANDOM_HPP_INCLUDED
|
||||
#define CATCH_GENERATORS_RANDOM_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_context.hpp>
|
||||
#include <catch2/generators/catch_generators.hpp>
|
||||
#include <catch2/internal/catch_random_number_generator.hpp>
|
||||
#include <catch2/internal/catch_uniform_integer_distribution.hpp>
|
||||
|
@@ -7,19 +7,11 @@
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_config.hpp>
|
||||
#include <catch2/internal/catch_console_colour.hpp>
|
||||
#include <catch2/internal/catch_console_width.hpp>
|
||||
#include <catch2/catch_message.hpp>
|
||||
#include <catch2/internal/catch_list.hpp>
|
||||
#include <catch2/internal/catch_string_manip.hpp>
|
||||
#include <catch2/catch_test_case_info.hpp>
|
||||
#include <catch2/reporters/catch_reporter_helpers.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
#include <catch2/internal/catch_istream.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
|
@@ -15,7 +15,6 @@
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
#include <catch2/internal/catch_test_run_info.hpp>
|
||||
#include <catch2/internal/catch_unique_ptr.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
#include <catch2/benchmark/detail/catch_benchmark_stats.hpp>
|
||||
|
||||
#include <map>
|
||||
|
@@ -8,10 +8,8 @@
|
||||
#include <catch2/internal/catch_assertion_handler.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_config.hpp>
|
||||
#include <catch2/internal/catch_context.hpp>
|
||||
#include <catch2/internal/catch_enforce.hpp>
|
||||
#include <catch2/internal/catch_debugger.hpp>
|
||||
#include <catch2/internal/catch_test_failure_exception.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
|
||||
#include <catch2/matchers/catch_matchers_string.hpp>
|
||||
|
||||
namespace Catch {
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include <catch2/internal/catch_platform.hpp>
|
||||
#include <catch2/internal/catch_string_manip.hpp>
|
||||
#include <catch2/internal/catch_textflow.hpp>
|
||||
#include <catch2/internal/catch_reusable_string_stream.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
@@ -24,13 +25,29 @@ namespace {
|
||||
;
|
||||
}
|
||||
|
||||
std::string normaliseOpt( std::string const& optName ) {
|
||||
#ifdef CATCH_PLATFORM_WINDOWS
|
||||
if ( optName[0] == '/' )
|
||||
return "-" + optName.substr( 1 );
|
||||
else
|
||||
Catch::StringRef normaliseOpt( Catch::StringRef optName ) {
|
||||
if ( optName[0] == '-'
|
||||
#if defined(CATCH_PLATFORM_WINDOWS)
|
||||
|| optName[0] == '/'
|
||||
#endif
|
||||
return optName;
|
||||
) {
|
||||
return optName.substr( 1, optName.size() );
|
||||
}
|
||||
|
||||
return optName;
|
||||
}
|
||||
|
||||
static size_t find_first_separator(Catch::StringRef sr) {
|
||||
auto is_separator = []( char c ) {
|
||||
return c == ' ' || c == ':' || c == '=';
|
||||
};
|
||||
size_t pos = 0;
|
||||
while (pos < sr.size()) {
|
||||
if (is_separator(sr[pos])) { return pos; }
|
||||
++pos;
|
||||
}
|
||||
|
||||
return Catch::StringRef::npos;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -48,23 +65,23 @@ namespace Catch {
|
||||
}
|
||||
|
||||
if ( it != itEnd ) {
|
||||
auto const& next = *it;
|
||||
StringRef next = *it;
|
||||
if ( isOptPrefix( next[0] ) ) {
|
||||
auto delimiterPos = next.find_first_of( " :=" );
|
||||
if ( delimiterPos != std::string::npos ) {
|
||||
auto delimiterPos = find_first_separator(next);
|
||||
if ( delimiterPos != StringRef::npos ) {
|
||||
m_tokenBuffer.push_back(
|
||||
{ TokenType::Option,
|
||||
next.substr( 0, delimiterPos ) } );
|
||||
m_tokenBuffer.push_back(
|
||||
{ TokenType::Argument,
|
||||
next.substr( delimiterPos + 1 ) } );
|
||||
next.substr( delimiterPos + 1, next.size() ) } );
|
||||
} else {
|
||||
if ( next[1] != '-' && next.size() > 2 ) {
|
||||
std::string opt = "- ";
|
||||
// Combined short args, e.g. "-ab" for "-a -b"
|
||||
for ( size_t i = 1; i < next.size(); ++i ) {
|
||||
opt[1] = next[i];
|
||||
m_tokenBuffer.push_back(
|
||||
{ TokenType::Option, opt } );
|
||||
{ TokenType::Option,
|
||||
next.substr( i, 1 ) } );
|
||||
}
|
||||
} else {
|
||||
m_tokenBuffer.push_back(
|
||||
@@ -124,12 +141,12 @@ namespace Catch {
|
||||
size_t ParserBase::cardinality() const { return 1; }
|
||||
|
||||
InternalParseResult ParserBase::parse( Args const& args ) const {
|
||||
return parse( args.exeName(), TokenStream( args ) );
|
||||
return parse( static_cast<std::string>(args.exeName()), TokenStream( args ) );
|
||||
}
|
||||
|
||||
ParseState::ParseState( ParseResultType type,
|
||||
TokenStream const& remainingTokens ):
|
||||
m_type( type ), m_remainingTokens( remainingTokens ) {}
|
||||
TokenStream remainingTokens ):
|
||||
m_type( type ), m_remainingTokens( CATCH_MOVE(remainingTokens) ) {}
|
||||
|
||||
ParserResult BoundFlagRef::setFlag( bool flag ) {
|
||||
m_ref = flag;
|
||||
@@ -147,34 +164,34 @@ namespace Catch {
|
||||
} // namespace Detail
|
||||
|
||||
Detail::InternalParseResult Arg::parse(std::string const&,
|
||||
Detail::TokenStream const& tokens) const {
|
||||
Detail::TokenStream tokens) const {
|
||||
auto validationResult = validate();
|
||||
if (!validationResult)
|
||||
return Detail::InternalParseResult(validationResult);
|
||||
|
||||
auto remainingTokens = tokens;
|
||||
auto const& token = *remainingTokens;
|
||||
auto token = *tokens;
|
||||
if (token.type != Detail::TokenType::Argument)
|
||||
return Detail::InternalParseResult::ok(Detail::ParseState(
|
||||
ParseResultType::NoMatch, remainingTokens));
|
||||
ParseResultType::NoMatch, CATCH_MOVE(tokens)));
|
||||
|
||||
assert(!m_ref->isFlag());
|
||||
auto valueRef =
|
||||
static_cast<Detail::BoundValueRefBase*>(m_ref.get());
|
||||
|
||||
auto result = valueRef->setValue(remainingTokens->token);
|
||||
if (!result)
|
||||
return Detail::InternalParseResult(result);
|
||||
auto result = valueRef->setValue(static_cast<std::string>(token.token));
|
||||
if ( !result )
|
||||
return Detail::InternalParseResult( result );
|
||||
else
|
||||
return Detail::InternalParseResult::ok(Detail::ParseState(
|
||||
ParseResultType::Matched, ++remainingTokens));
|
||||
return Detail::InternalParseResult::ok(
|
||||
Detail::ParseState( ParseResultType::Matched,
|
||||
CATCH_MOVE( ++tokens ) ) );
|
||||
}
|
||||
|
||||
Opt::Opt(bool& ref) :
|
||||
ParserRefImpl(std::make_shared<Detail::BoundFlagRef>(ref)) {}
|
||||
|
||||
std::vector<Detail::HelpColumns> Opt::getHelpColumns() const {
|
||||
std::ostringstream oss;
|
||||
Detail::HelpColumns Opt::getHelpColumns() const {
|
||||
ReusableStringStream oss;
|
||||
bool first = true;
|
||||
for (auto const& opt : m_optNames) {
|
||||
if (first)
|
||||
@@ -185,10 +202,10 @@ namespace Catch {
|
||||
}
|
||||
if (!m_hint.empty())
|
||||
oss << " <" << m_hint << '>';
|
||||
return { { oss.str(), m_description } };
|
||||
return { oss.str(), m_description };
|
||||
}
|
||||
|
||||
bool Opt::isMatch(std::string const& optToken) const {
|
||||
bool Opt::isMatch(StringRef optToken) const {
|
||||
auto normalisedToken = normaliseOpt(optToken);
|
||||
for (auto const& name : m_optNames) {
|
||||
if (normaliseOpt(name) == normalisedToken)
|
||||
@@ -198,15 +215,14 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Detail::InternalParseResult Opt::parse(std::string const&,
|
||||
Detail::TokenStream const& tokens) const {
|
||||
Detail::TokenStream tokens) const {
|
||||
auto validationResult = validate();
|
||||
if (!validationResult)
|
||||
return Detail::InternalParseResult(validationResult);
|
||||
|
||||
auto remainingTokens = tokens;
|
||||
if (remainingTokens &&
|
||||
remainingTokens->type == Detail::TokenType::Option) {
|
||||
auto const& token = *remainingTokens;
|
||||
if (tokens &&
|
||||
tokens->type == Detail::TokenType::Option) {
|
||||
auto const& token = *tokens;
|
||||
if (isMatch(token.token)) {
|
||||
if (m_ref->isFlag()) {
|
||||
auto flagRef =
|
||||
@@ -218,35 +234,35 @@ namespace Catch {
|
||||
if (result.value() ==
|
||||
ParseResultType::ShortCircuitAll)
|
||||
return Detail::InternalParseResult::ok(Detail::ParseState(
|
||||
result.value(), remainingTokens));
|
||||
result.value(), CATCH_MOVE(tokens)));
|
||||
} else {
|
||||
auto valueRef =
|
||||
static_cast<Detail::BoundValueRefBase*>(
|
||||
m_ref.get());
|
||||
++remainingTokens;
|
||||
if (!remainingTokens)
|
||||
++tokens;
|
||||
if (!tokens)
|
||||
return Detail::InternalParseResult::runtimeError(
|
||||
"Expected argument following " +
|
||||
token.token);
|
||||
auto const& argToken = *remainingTokens;
|
||||
auto const& argToken = *tokens;
|
||||
if (argToken.type != Detail::TokenType::Argument)
|
||||
return Detail::InternalParseResult::runtimeError(
|
||||
"Expected argument following " +
|
||||
token.token);
|
||||
const auto result = valueRef->setValue(argToken.token);
|
||||
const auto result = valueRef->setValue(static_cast<std::string>(argToken.token));
|
||||
if (!result)
|
||||
return Detail::InternalParseResult(result);
|
||||
if (result.value() ==
|
||||
ParseResultType::ShortCircuitAll)
|
||||
return Detail::InternalParseResult::ok(Detail::ParseState(
|
||||
result.value(), remainingTokens));
|
||||
result.value(), CATCH_MOVE(tokens)));
|
||||
}
|
||||
return Detail::InternalParseResult::ok(Detail::ParseState(
|
||||
ParseResultType::Matched, ++remainingTokens));
|
||||
ParseResultType::Matched, CATCH_MOVE(++tokens)));
|
||||
}
|
||||
}
|
||||
return Detail::InternalParseResult::ok(
|
||||
Detail::ParseState(ParseResultType::NoMatch, remainingTokens));
|
||||
Detail::ParseState(ParseResultType::NoMatch, CATCH_MOVE(tokens)));
|
||||
}
|
||||
|
||||
Detail::Result Opt::validate() const {
|
||||
@@ -278,9 +294,9 @@ namespace Catch {
|
||||
|
||||
Detail::InternalParseResult
|
||||
ExeName::parse(std::string const&,
|
||||
Detail::TokenStream const& tokens) const {
|
||||
Detail::TokenStream tokens) const {
|
||||
return Detail::InternalParseResult::ok(
|
||||
Detail::ParseState(ParseResultType::NoMatch, tokens));
|
||||
Detail::ParseState(ParseResultType::NoMatch, CATCH_MOVE(tokens)));
|
||||
}
|
||||
|
||||
ParserResult ExeName::set(std::string const& newName) {
|
||||
@@ -310,9 +326,9 @@ namespace Catch {
|
||||
|
||||
std::vector<Detail::HelpColumns> Parser::getHelpColumns() const {
|
||||
std::vector<Detail::HelpColumns> cols;
|
||||
cols.reserve( m_options.size() );
|
||||
for ( auto const& o : m_options ) {
|
||||
auto childCols = o.getHelpColumns();
|
||||
cols.insert( cols.end(), childCols.begin(), childCols.end() );
|
||||
cols.push_back(o.getHelpColumns());
|
||||
}
|
||||
return cols;
|
||||
}
|
||||
@@ -350,12 +366,12 @@ namespace Catch {
|
||||
|
||||
optWidth = ( std::min )( optWidth, consoleWidth / 2 );
|
||||
|
||||
for ( auto const& cols : rows ) {
|
||||
auto row = TextFlow::Column( cols.left )
|
||||
for ( auto& cols : rows ) {
|
||||
auto row = TextFlow::Column( CATCH_MOVE(cols.left) )
|
||||
.width( optWidth )
|
||||
.indent( 2 ) +
|
||||
TextFlow::Spacer( 4 ) +
|
||||
TextFlow::Column( cols.right )
|
||||
TextFlow::Column( static_cast<std::string>(cols.descriptions) )
|
||||
.width( consoleWidth - 7 - optWidth );
|
||||
os << row << '\n';
|
||||
}
|
||||
@@ -377,7 +393,7 @@ namespace Catch {
|
||||
|
||||
Detail::InternalParseResult
|
||||
Parser::parse( std::string const& exeName,
|
||||
Detail::TokenStream const& tokens ) const {
|
||||
Detail::TokenStream tokens ) const {
|
||||
|
||||
struct ParserInfo {
|
||||
ParserBase const* parser = nullptr;
|
||||
@@ -395,7 +411,7 @@ namespace Catch {
|
||||
m_exeName.set( exeName );
|
||||
|
||||
auto result = Detail::InternalParseResult::ok(
|
||||
Detail::ParseState( ParseResultType::NoMatch, tokens ) );
|
||||
Detail::ParseState( ParseResultType::NoMatch, CATCH_MOVE(tokens) ) );
|
||||
while ( result.value().remainingTokens() ) {
|
||||
bool tokenParsed = false;
|
||||
|
||||
@@ -403,7 +419,7 @@ namespace Catch {
|
||||
if ( parseInfo.parser->cardinality() == 0 ||
|
||||
parseInfo.count < parseInfo.parser->cardinality() ) {
|
||||
result = parseInfo.parser->parse(
|
||||
exeName, result.value().remainingTokens() );
|
||||
exeName, CATCH_MOVE(result).value().remainingTokens() );
|
||||
if ( !result )
|
||||
return result;
|
||||
if ( result.value().type() !=
|
||||
@@ -429,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> args) :
|
||||
Args::Args(std::initializer_list<StringRef> args) :
|
||||
m_exeName(*args.begin()),
|
||||
m_args(args.begin() + 1, args.end()) {}
|
||||
|
||||
|
@@ -29,6 +29,7 @@
|
||||
# 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>
|
||||
@@ -101,17 +102,16 @@ namespace Catch {
|
||||
enum class TokenType { Option, Argument };
|
||||
struct Token {
|
||||
TokenType type;
|
||||
std::string 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>::const_iterator;
|
||||
using Iterator = std::vector<StringRef>::const_iterator;
|
||||
Iterator it;
|
||||
Iterator itEnd;
|
||||
std::vector<Token> m_tokenBuffer;
|
||||
|
||||
void loadBuffer();
|
||||
|
||||
public:
|
||||
@@ -163,12 +163,17 @@ namespace Catch {
|
||||
ResultType m_type;
|
||||
};
|
||||
|
||||
template <typename T> class ResultValueBase : public ResultBase {
|
||||
template <typename T>
|
||||
class ResultValueBase : public ResultBase {
|
||||
public:
|
||||
auto value() const -> T const& {
|
||||
T const& value() const& {
|
||||
enforceOk();
|
||||
return m_value;
|
||||
}
|
||||
T&& value() && {
|
||||
enforceOk();
|
||||
return CATCH_MOVE( m_value );
|
||||
}
|
||||
|
||||
protected:
|
||||
ResultValueBase( ResultType type ): ResultBase( type ) {}
|
||||
@@ -178,13 +183,23 @@ namespace Catch {
|
||||
if ( m_type == ResultType::Ok )
|
||||
new ( &m_value ) T( other.m_value );
|
||||
}
|
||||
|
||||
ResultValueBase( ResultType, T const& value ): ResultBase( ResultType::Ok ) {
|
||||
new ( &m_value ) T( value );
|
||||
ResultValueBase( ResultValueBase&& other ):
|
||||
ResultBase( other ) {
|
||||
if ( m_type == ResultType::Ok )
|
||||
new ( &m_value ) T( CATCH_MOVE(other.m_value) );
|
||||
}
|
||||
|
||||
auto operator=( ResultValueBase const& other )
|
||||
-> ResultValueBase& {
|
||||
|
||||
ResultValueBase( ResultType, T const& value ):
|
||||
ResultBase( ResultType::Ok ) {
|
||||
new ( &m_value ) T( value );
|
||||
}
|
||||
ResultValueBase( ResultType, T&& value ):
|
||||
ResultBase( ResultType::Ok ) {
|
||||
new ( &m_value ) T( CATCH_MOVE(value) );
|
||||
}
|
||||
|
||||
ResultValueBase& operator=( ResultValueBase const& other ) {
|
||||
if ( m_type == ResultType::Ok )
|
||||
m_value.~T();
|
||||
ResultBase::operator=( other );
|
||||
@@ -192,6 +207,14 @@ namespace Catch {
|
||||
new ( &m_value ) T( other.m_value );
|
||||
return *this;
|
||||
}
|
||||
ResultValueBase& operator=( ResultValueBase&& other ) {
|
||||
if ( m_type == ResultType::Ok ) m_value.~T();
|
||||
ResultBase::operator=( other );
|
||||
if ( m_type == ResultType::Ok )
|
||||
new ( &m_value ) T( CATCH_MOVE(other.m_value) );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
~ResultValueBase() override {
|
||||
if ( m_type == ResultType::Ok )
|
||||
@@ -219,8 +242,8 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static auto ok( U const& value ) -> BasicResult {
|
||||
return { ResultType::Ok, value };
|
||||
static auto ok( U&& value ) -> BasicResult {
|
||||
return { ResultType::Ok, CATCH_FORWARD(value) };
|
||||
}
|
||||
static auto ok() -> BasicResult { return { ResultType::Ok }; }
|
||||
static auto logicError( std::string&& message )
|
||||
@@ -267,12 +290,15 @@ namespace Catch {
|
||||
class ParseState {
|
||||
public:
|
||||
ParseState( ParseResultType type,
|
||||
TokenStream const& remainingTokens );
|
||||
TokenStream remainingTokens );
|
||||
|
||||
ParseResultType type() const { return m_type; }
|
||||
TokenStream const& remainingTokens() const {
|
||||
TokenStream const& remainingTokens() const& {
|
||||
return m_remainingTokens;
|
||||
}
|
||||
TokenStream&& remainingTokens() && {
|
||||
return CATCH_MOVE( m_remainingTokens );
|
||||
}
|
||||
|
||||
private:
|
||||
ParseResultType m_type;
|
||||
@@ -285,7 +311,7 @@ namespace Catch {
|
||||
|
||||
struct HelpColumns {
|
||||
std::string left;
|
||||
std::string right;
|
||||
StringRef descriptions;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -445,7 +471,7 @@ namespace Catch {
|
||||
virtual ~ParserBase() = default;
|
||||
virtual auto validate() const -> Result { return Result::ok(); }
|
||||
virtual auto parse( std::string const& exeName,
|
||||
TokenStream const& tokens ) const
|
||||
TokenStream tokens ) const
|
||||
-> InternalParseResult = 0;
|
||||
virtual size_t cardinality() const;
|
||||
|
||||
@@ -465,8 +491,8 @@ namespace Catch {
|
||||
protected:
|
||||
Optionality m_optionality = Optionality::Optional;
|
||||
std::shared_ptr<BoundRef> m_ref;
|
||||
std::string m_hint;
|
||||
std::string m_description;
|
||||
StringRef m_hint;
|
||||
StringRef m_description;
|
||||
|
||||
explicit ParserRefImpl( std::shared_ptr<BoundRef> const& ref ):
|
||||
m_ref( ref ) {}
|
||||
@@ -475,28 +501,32 @@ namespace Catch {
|
||||
template <typename LambdaT>
|
||||
ParserRefImpl( accept_many_t,
|
||||
LambdaT const& ref,
|
||||
std::string const& 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<T>::value>>
|
||||
ParserRefImpl( T& ref, std::string const& 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<LambdaT>::value>>
|
||||
ParserRefImpl( LambdaT const& ref, std::string const& hint ):
|
||||
ParserRefImpl( LambdaT const& ref, StringRef hint ):
|
||||
m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
|
||||
m_hint( hint ) {}
|
||||
|
||||
auto operator()( std::string const& description ) -> DerivedT& {
|
||||
DerivedT& operator()( StringRef description ) & {
|
||||
m_description = description;
|
||||
return static_cast<DerivedT&>( *this );
|
||||
}
|
||||
DerivedT&& operator()( StringRef description ) && {
|
||||
m_description = description;
|
||||
return static_cast<DerivedT&&>( *this );
|
||||
}
|
||||
|
||||
auto optional() -> DerivedT& {
|
||||
m_optionality = Optionality::Optional;
|
||||
@@ -519,7 +549,7 @@ namespace Catch {
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string const& hint() const { return m_hint; }
|
||||
StringRef hint() const { return m_hint; }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
@@ -533,13 +563,13 @@ namespace Catch {
|
||||
|
||||
Detail::InternalParseResult
|
||||
parse(std::string const&,
|
||||
Detail::TokenStream const& tokens) const override;
|
||||
Detail::TokenStream tokens) const override;
|
||||
};
|
||||
|
||||
// A parser for options
|
||||
class Opt : public Detail::ParserRefImpl<Opt> {
|
||||
protected:
|
||||
std::vector<std::string> m_optNames;
|
||||
std::vector<StringRef> m_optNames;
|
||||
|
||||
public:
|
||||
template <typename LambdaT>
|
||||
@@ -552,33 +582,37 @@ namespace Catch {
|
||||
template <typename LambdaT,
|
||||
typename = typename std::enable_if_t<
|
||||
Detail::is_unary_function<LambdaT>::value>>
|
||||
Opt( LambdaT const& ref, std::string const& hint ):
|
||||
Opt( LambdaT const& ref, StringRef hint ):
|
||||
ParserRefImpl( ref, hint ) {}
|
||||
|
||||
template <typename LambdaT>
|
||||
Opt( accept_many_t, LambdaT const& ref, std::string const& 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<T>::value>>
|
||||
Opt( T& ref, std::string const& hint ):
|
||||
Opt( T& ref, StringRef hint ):
|
||||
ParserRefImpl( ref, hint ) {}
|
||||
|
||||
auto operator[](std::string const& optName) -> Opt& {
|
||||
Opt& operator[]( StringRef optName ) & {
|
||||
m_optNames.push_back(optName);
|
||||
return *this;
|
||||
}
|
||||
Opt&& operator[]( StringRef optName ) && {
|
||||
m_optNames.push_back( optName );
|
||||
return CATCH_MOVE(*this);
|
||||
}
|
||||
|
||||
std::vector<Detail::HelpColumns> getHelpColumns() const;
|
||||
Detail::HelpColumns getHelpColumns() const;
|
||||
|
||||
bool isMatch(std::string const& optToken) const;
|
||||
bool isMatch(StringRef optToken) const;
|
||||
|
||||
using ParserBase::parse;
|
||||
|
||||
Detail::InternalParseResult
|
||||
parse(std::string const&,
|
||||
Detail::TokenStream const& tokens) const override;
|
||||
Detail::TokenStream tokens) const override;
|
||||
|
||||
Detail::Result validate() const override;
|
||||
};
|
||||
@@ -601,7 +635,7 @@ namespace Catch {
|
||||
// handled specially
|
||||
Detail::InternalParseResult
|
||||
parse(std::string const&,
|
||||
Detail::TokenStream const& tokens) const override;
|
||||
Detail::TokenStream tokens) const override;
|
||||
|
||||
std::string const& name() const { return *m_name; }
|
||||
Detail::ParserResult set(std::string const& newName);
|
||||
@@ -626,16 +660,28 @@ namespace Catch {
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto operator|=(Opt const& opt) -> Parser& {
|
||||
m_options.push_back(opt);
|
||||
return *this;
|
||||
friend Parser& operator|=( Parser& p, Opt const& opt ) {
|
||||
p.m_options.push_back( opt );
|
||||
return p;
|
||||
}
|
||||
friend Parser& operator|=( Parser& p, Opt&& opt ) {
|
||||
p.m_options.push_back( CATCH_MOVE(opt) );
|
||||
return p;
|
||||
}
|
||||
|
||||
Parser& operator|=(Parser const& other);
|
||||
|
||||
template <typename T>
|
||||
auto operator|(T const& other) const -> Parser {
|
||||
return Parser(*this) |= other;
|
||||
friend Parser operator|( Parser const& p, T&& rhs ) {
|
||||
Parser temp( p );
|
||||
temp |= rhs;
|
||||
return temp;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
friend Parser operator|( Parser&& p, T&& rhs ) {
|
||||
p |= CATCH_FORWARD(rhs);
|
||||
return CATCH_MOVE(p);
|
||||
}
|
||||
|
||||
std::vector<Detail::HelpColumns> getHelpColumns() const;
|
||||
@@ -653,21 +699,23 @@ namespace Catch {
|
||||
using ParserBase::parse;
|
||||
Detail::InternalParseResult
|
||||
parse(std::string const& exeName,
|
||||
Detail::TokenStream const& tokens) const override;
|
||||
Detail::TokenStream tokens) const override;
|
||||
};
|
||||
|
||||
// Transport for raw args (copied from main args, or supplied via
|
||||
// init list for testing)
|
||||
/**
|
||||
* Wrapper over argc + argv, assumes that the inputs outlive it
|
||||
*/
|
||||
class Args {
|
||||
friend Detail::TokenStream;
|
||||
std::string m_exeName;
|
||||
std::vector<std::string> m_args;
|
||||
StringRef m_exeName;
|
||||
std::vector<StringRef> m_args;
|
||||
|
||||
public:
|
||||
Args(int argc, char const* const* argv);
|
||||
Args(std::initializer_list<std::string> args);
|
||||
// Helper constructor for testing
|
||||
Args(std::initializer_list<StringRef> args);
|
||||
|
||||
std::string const& exeName() const { return m_exeName; }
|
||||
StringRef exeName() const { return m_exeName; }
|
||||
};
|
||||
|
||||
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <catch2/catch_config.hpp>
|
||||
#include <catch2/internal/catch_string_manip.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_config.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
|
||||
#include <catch2/internal/catch_reporter_registry.hpp>
|
||||
#include <catch2/internal/catch_console_colour.hpp>
|
||||
@@ -46,7 +47,7 @@ namespace Catch {
|
||||
line = trim(line);
|
||||
if( !line.empty() && !startsWith( line, '#' ) ) {
|
||||
if( !startsWith( line, '"' ) )
|
||||
line = '"' + line + '"';
|
||||
line = '"' + CATCH_MOVE(line) + '"';
|
||||
config.testsOrTags.push_back( line );
|
||||
config.testsOrTags.emplace_back( "," );
|
||||
}
|
||||
@@ -300,8 +301,8 @@ namespace Catch {
|
||||
( "split the tests to execute into this many groups" )
|
||||
| Opt( setShardIndex, "shard index" )
|
||||
["--shard-index"]
|
||||
( "index of the group of tests to execute (see --shard-count)" ) |
|
||||
Opt( config.allowZeroTests )
|
||||
( "index of the group of tests to execute (see --shard-count)" )
|
||||
| Opt( config.allowZeroTests )
|
||||
["--allow-running-no-tests"]
|
||||
( "Treat 'No tests run' as a success" )
|
||||
| Arg( config.testsOrTags, "test name|pattern|tags" )
|
||||
|
@@ -29,14 +29,14 @@
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
|
||||
# define CATCH_CPP14_OR_GREATER
|
||||
# endif
|
||||
|
||||
# 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
|
||||
|
||||
#endif
|
||||
|
||||
// Only GCC compiler should be used in this block, so other compilers trying to
|
||||
|
@@ -230,21 +230,21 @@ namespace {
|
||||
|
||||
namespace Catch {
|
||||
|
||||
Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode implSelection,
|
||||
Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
|
||||
IStream* stream ) {
|
||||
#if defined( CATCH_CONFIG_COLOUR_WIN32 )
|
||||
if ( implSelection == ColourMode::Win32 ) {
|
||||
if ( colourSelection == ColourMode::Win32 ) {
|
||||
return Detail::make_unique<Win32ColourImpl>( stream );
|
||||
}
|
||||
#endif
|
||||
if ( implSelection == ColourMode::ANSI ) {
|
||||
if ( colourSelection == ColourMode::ANSI ) {
|
||||
return Detail::make_unique<ANSIColourImpl>( stream );
|
||||
}
|
||||
if ( implSelection == ColourMode::None ) {
|
||||
if ( colourSelection == ColourMode::None ) {
|
||||
return Detail::make_unique<NoColourImpl>( stream );
|
||||
}
|
||||
|
||||
if ( implSelection == ColourMode::PlatformDefault) {
|
||||
if ( colourSelection == ColourMode::PlatformDefault) {
|
||||
#if defined( CATCH_CONFIG_COLOUR_WIN32 )
|
||||
if ( Win32ColourImpl::useImplementationForStream( *stream ) ) {
|
||||
return Detail::make_unique<Win32ColourImpl>( stream );
|
||||
@@ -256,7 +256,7 @@ namespace Catch {
|
||||
return Detail::make_unique<NoColourImpl>( stream );
|
||||
}
|
||||
|
||||
CATCH_ERROR( "Could not create colour impl for selection " << static_cast<int>(implSelection) );
|
||||
CATCH_ERROR( "Could not create colour impl for selection " << static_cast<int>(colourSelection) );
|
||||
}
|
||||
|
||||
bool isColourImplAvailable( ColourMode colourSelection ) {
|
||||
|
@@ -10,7 +10,12 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
ITransientExpression::~ITransientExpression() = default;
|
||||
void ITransientExpression::streamReconstructedExpression(
|
||||
std::ostream& os ) const {
|
||||
// We can't make this function pure virtual to keep ITransientExpression
|
||||
// constexpr, so we write error message instead
|
||||
os << "Some class derived from ITransientExpression without overriding streamReconstructedExpression";
|
||||
}
|
||||
|
||||
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
|
||||
if( lhs.size() + rhs.size() < 40 &&
|
||||
|
@@ -13,10 +13,91 @@
|
||||
#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>
|
||||
#include <iosfwd>
|
||||
|
||||
/** \file
|
||||
* Why does decomposing look the way it does:
|
||||
*
|
||||
* Conceptually, decomposing is simple. We change `REQUIRE( a == b )` into
|
||||
* `Decomposer{} <= a == b`, so that `Decomposer{} <= a` is evaluated first,
|
||||
* and our custom operator is used for `a == b`, because `a` is transformed
|
||||
* into `ExprLhs<T&>` and then into `BinaryExpr<T&, U&>`.
|
||||
*
|
||||
* In practice, decomposing ends up a mess, because we have to support
|
||||
* various fun things.
|
||||
*
|
||||
* 1) Types that are only comparable with literal 0, and they do this by
|
||||
* comparing against a magic type with pointer constructor and deleted
|
||||
* other constructors. Example: `REQUIRE((a <=> b) == 0)` in libstdc++
|
||||
*
|
||||
* 2) Types that are only comparable with literal 0, and they do this by
|
||||
* comparing against a magic type with consteval integer constructor.
|
||||
* Example: `REQUIRE((a <=> b) == 0)` in current MSVC STL.
|
||||
*
|
||||
* 3) Types that have no linkage, and so we cannot form a reference to
|
||||
* them. Example: some implementations of traits.
|
||||
*
|
||||
* 4) Starting with C++20, when the compiler sees `a == b`, it also uses
|
||||
* `b == a` when constructing the overload set. For us this means that
|
||||
* when the compiler handles `ExprLhs<T> == b`, it also tries to resolve
|
||||
* the overload set for `b == ExprLhs<T>`.
|
||||
*
|
||||
* To accomodate these use cases, decomposer ended up rather complex.
|
||||
*
|
||||
* 1) These types are handled by adding SFINAE overloads to our comparison
|
||||
* operators, checking whether `T == U` are comparable with the given
|
||||
* operator, and if not, whether T (or U) are comparable with literal 0.
|
||||
* If yes, the overload compares T (or U) with 0 literal inline in the
|
||||
* definition.
|
||||
*
|
||||
* Note that for extra correctness, we check that the other type is
|
||||
* either an `int` (literal 0 is captured as `int` by templates), or
|
||||
* a `long` (some platforms use 0L for `NULL` and we want to support
|
||||
* that for pointer comparisons).
|
||||
*
|
||||
* 2) For these types, `is_foo_comparable<T, int>` is true, but letting
|
||||
* them fall into the overload that actually does `T == int` causes
|
||||
* compilation error. Handling them requires that the decomposition
|
||||
* is `constexpr`, so that P2564R3 applies and the `consteval` from
|
||||
* their accompanying magic type is propagated through the `constexpr`
|
||||
* call stack.
|
||||
*
|
||||
* However this is not enough to handle these types automatically,
|
||||
* because our default is to capture types by reference, to avoid
|
||||
* runtime copies. While these references cannot become dangling,
|
||||
* they outlive the constexpr context and thus the default capture
|
||||
* path cannot be actually constexpr.
|
||||
*
|
||||
* The solution is to capture these types by value, by explicitly
|
||||
* specializing `Catch::capture_by_value` for them. Catch2 provides
|
||||
* specialization for `std::foo_ordering`s, but users can specialize
|
||||
* the trait for their own types as well.
|
||||
*
|
||||
* 3) If a type has no linkage, we also cannot capture it by reference.
|
||||
* The solution is once again to capture them by value. We handle
|
||||
* the common cases by using `std::is_arithmetic` as the default
|
||||
* for `Catch::capture_by_value`, but that is only a some-effort
|
||||
* heuristic. But as with 2), users can specialize `capture_by_value`
|
||||
* for their own types as needed.
|
||||
*
|
||||
* 4) To support C++20 and make the SFINAE on our decomposing operators
|
||||
* work, the SFINAE has to happen in return type, rather than in
|
||||
* a template type. This is due to our use of logical type traits
|
||||
* (`conjunction`/`disjunction`/`negation`), that we use to workaround
|
||||
* an issue in older (9-) versions of GCC. I still blame C++20 for
|
||||
* this, because without the comparison order switching, the logical
|
||||
* traits could still be used in template type.
|
||||
*
|
||||
* There are also other side concerns, e.g. supporting both `REQUIRE(a)`
|
||||
* and `REQUIRE(a == b)`, or making `REQUIRE_THAT(a, IsEqual(b))` slot
|
||||
* nicely into the same expression handling logic, but these are rather
|
||||
* straightforward and add only a bit of complexity (e.g. common base
|
||||
* class for decomposed expressions).
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
|
||||
@@ -34,8 +115,33 @@
|
||||
# pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_CPP20_OR_GREATER) && __has_include(<compare>)
|
||||
# include <compare>
|
||||
# if defined( __cpp_lib_three_way_comparison ) && \
|
||||
__cpp_lib_three_way_comparison >= 201907L
|
||||
# define CATCH_CONFIG_CPP20_COMPARE_OVERLOADS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace Catch {
|
||||
|
||||
// Note: There is nothing that stops us from extending this,
|
||||
// e.g. to `std::is_scalar`, but the more encompassing
|
||||
// traits are usually also more expensive. For now we
|
||||
// keep this as it used to be and it can be changed later.
|
||||
template <typename T>
|
||||
struct capture_by_value
|
||||
: std::integral_constant<bool, std::is_arithmetic<T>{}> {};
|
||||
|
||||
#if defined( CATCH_CONFIG_CPP20_COMPARE_OVERLOADS )
|
||||
template <>
|
||||
struct capture_by_value<std::strong_ordering> : std::true_type {};
|
||||
template <>
|
||||
struct capture_by_value<std::weak_ordering> : std::true_type {};
|
||||
template <>
|
||||
struct capture_by_value<std::partial_ordering> : std::true_type {};
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct always_false : std::false_type {};
|
||||
|
||||
@@ -44,11 +150,12 @@ namespace Catch {
|
||||
bool m_result;
|
||||
|
||||
public:
|
||||
auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
|
||||
auto getResult() const -> bool { return m_result; }
|
||||
virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
|
||||
constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
|
||||
constexpr auto getResult() const -> bool { return m_result; }
|
||||
//! This function **has** to be overriden by the derived class.
|
||||
virtual void streamReconstructedExpression( std::ostream& os ) const;
|
||||
|
||||
ITransientExpression( bool isBinaryExpression, bool result )
|
||||
constexpr ITransientExpression( bool isBinaryExpression, bool result )
|
||||
: m_isBinaryExpression( isBinaryExpression ),
|
||||
m_result( result )
|
||||
{}
|
||||
@@ -57,14 +164,13 @@ namespace Catch {
|
||||
ITransientExpression(ITransientExpression const&) = default;
|
||||
ITransientExpression& operator=(ITransientExpression const&) = default;
|
||||
|
||||
// We don't actually need a virtual destructor, but many static analysers
|
||||
// complain if it's not here :-(
|
||||
virtual ~ITransientExpression(); // = default;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) {
|
||||
expr.streamReconstructedExpression(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
protected:
|
||||
~ITransientExpression() = default;
|
||||
};
|
||||
|
||||
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
|
||||
@@ -81,7 +187,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
public:
|
||||
BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
|
||||
constexpr BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
|
||||
: ITransientExpression{ true, comparisonResult },
|
||||
m_lhs( lhs ),
|
||||
m_op( op ),
|
||||
@@ -154,7 +260,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
public:
|
||||
explicit UnaryExpr( LhsT lhs )
|
||||
explicit constexpr UnaryExpr( LhsT lhs )
|
||||
: ITransientExpression{ false, static_cast<bool>(lhs) },
|
||||
m_lhs( lhs )
|
||||
{}
|
||||
@@ -165,30 +271,30 @@ namespace Catch {
|
||||
class ExprLhs {
|
||||
LhsT m_lhs;
|
||||
public:
|
||||
explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
|
||||
explicit constexpr ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
|
||||
|
||||
#define CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( id, op ) \
|
||||
template <typename RhsT> \
|
||||
friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
|
||||
->std::enable_if_t< \
|
||||
Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
|
||||
Detail::negation<std::is_arithmetic< \
|
||||
Detail::negation<capture_by_value< \
|
||||
std::remove_reference_t<RhsT>>>>::value, \
|
||||
BinaryExpr<LhsT, RhsT const&>> { \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
->std::enable_if_t< \
|
||||
Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
|
||||
std::is_arithmetic<RhsT>>::value, \
|
||||
capture_by_value<RhsT>>::value, \
|
||||
BinaryExpr<LhsT, RhsT>> { \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
->std::enable_if_t< \
|
||||
Detail::conjunction< \
|
||||
Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
|
||||
@@ -202,7 +308,7 @@ namespace Catch {
|
||||
static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
->std::enable_if_t< \
|
||||
Detail::conjunction< \
|
||||
Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
|
||||
@@ -220,28 +326,29 @@ namespace Catch {
|
||||
|
||||
#undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR
|
||||
|
||||
|
||||
#define CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( id, op ) \
|
||||
template <typename RhsT> \
|
||||
friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
|
||||
->std::enable_if_t< \
|
||||
Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
|
||||
Detail::negation<std::is_arithmetic< \
|
||||
Detail::negation<capture_by_value< \
|
||||
std::remove_reference_t<RhsT>>>>::value, \
|
||||
BinaryExpr<LhsT, RhsT const&>> { \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
->std::enable_if_t< \
|
||||
Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
|
||||
std::is_arithmetic<RhsT>>::value, \
|
||||
capture_by_value<RhsT>>::value, \
|
||||
BinaryExpr<LhsT, RhsT>> { \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
->std::enable_if_t< \
|
||||
Detail::conjunction< \
|
||||
Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
|
||||
@@ -253,7 +360,7 @@ namespace Catch {
|
||||
static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
->std::enable_if_t< \
|
||||
Detail::conjunction< \
|
||||
Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
|
||||
@@ -274,16 +381,16 @@ namespace Catch {
|
||||
|
||||
#define CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR( op ) \
|
||||
template <typename RhsT> \
|
||||
friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
|
||||
constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
|
||||
->std::enable_if_t< \
|
||||
!std::is_arithmetic<std::remove_reference_t<RhsT>>::value, \
|
||||
!capture_by_value<std::remove_reference_t<RhsT>>::value, \
|
||||
BinaryExpr<LhsT, RhsT const&>> { \
|
||||
return { \
|
||||
static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
|
||||
} \
|
||||
template <typename RhsT> \
|
||||
friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
|
||||
->std::enable_if_t<std::is_arithmetic<RhsT>::value, \
|
||||
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##_sr, rhs }; \
|
||||
@@ -309,19 +416,23 @@ namespace Catch {
|
||||
"wrap the expression inside parentheses, or decompose it");
|
||||
}
|
||||
|
||||
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
||||
constexpr auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
||||
return UnaryExpr<LhsT>{ m_lhs };
|
||||
}
|
||||
};
|
||||
|
||||
struct Decomposer {
|
||||
template<typename T, std::enable_if_t<!std::is_arithmetic<std::remove_reference_t<T>>::value, int> = 0>
|
||||
friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs<T const&> {
|
||||
template <typename T,
|
||||
std::enable_if_t<
|
||||
!capture_by_value<std::remove_reference_t<T>>::value,
|
||||
int> = 0>
|
||||
constexpr friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs<T const&> {
|
||||
return ExprLhs<const T&>{ lhs };
|
||||
}
|
||||
|
||||
template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
|
||||
friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs<T> {
|
||||
template <typename T,
|
||||
std::enable_if_t<capture_by_value<T>::value, int> = 0>
|
||||
constexpr friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs<T> {
|
||||
return ExprLhs<T>{ value };
|
||||
}
|
||||
};
|
||||
|
@@ -24,7 +24,7 @@ namespace Catch {
|
||||
|
||||
std::vector<Catch::Detail::unique_ptr<EnumInfo>> m_enumInfos;
|
||||
|
||||
EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values) override;
|
||||
EnumInfo const& registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values) override;
|
||||
};
|
||||
|
||||
std::vector<StringRef> parseEnums( StringRef enums );
|
||||
|
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <catch2/internal/catch_fatal_condition_handler.hpp>
|
||||
|
||||
#include <catch2/internal/catch_compiler_capabilities.hpp>
|
||||
#include <catch2/internal/catch_context.hpp>
|
||||
#include <catch2/internal/catch_enforce.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_capture.hpp>
|
||||
|
@@ -8,9 +8,6 @@
|
||||
#ifndef CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
|
||||
#define CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_platform.hpp>
|
||||
#include <catch2/internal/catch_compiler_capabilities.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace Catch {
|
||||
|
@@ -80,7 +80,6 @@ namespace Detail {
|
||||
CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << '\'' );
|
||||
m_ofs << std::unitbuf;
|
||||
}
|
||||
~FileStream() override = default;
|
||||
public: // IStream
|
||||
std::ostream& stream() override {
|
||||
return m_ofs;
|
||||
@@ -95,7 +94,6 @@ namespace Detail {
|
||||
// Store the streambuf from cout up-front because
|
||||
// cout may get redirected when running tests
|
||||
CoutStream() : m_os( Catch::cout().rdbuf() ) {}
|
||||
~CoutStream() override = default;
|
||||
|
||||
public: // IStream
|
||||
std::ostream& stream() override { return m_os; }
|
||||
@@ -109,7 +107,6 @@ namespace Detail {
|
||||
// Store the streambuf from cerr up-front because
|
||||
// cout may get redirected when running tests
|
||||
CerrStream(): m_os( Catch::cerr().rdbuf() ) {}
|
||||
~CerrStream() override = default;
|
||||
|
||||
public: // IStream
|
||||
std::ostream& stream() override { return m_os; }
|
||||
@@ -127,8 +124,6 @@ namespace Detail {
|
||||
m_os( m_streamBuf.get() )
|
||||
{}
|
||||
|
||||
~DebugOutStream() override = default;
|
||||
|
||||
public: // IStream
|
||||
std::ostream& stream() override { return m_os; }
|
||||
};
|
||||
|
@@ -31,7 +31,7 @@ namespace Catch {
|
||||
m_os{ os }, m_indent_level{ indent_level } {
|
||||
m_os << '{';
|
||||
}
|
||||
JsonObjectWriter::JsonObjectWriter( JsonObjectWriter&& source ):
|
||||
JsonObjectWriter::JsonObjectWriter( JsonObjectWriter&& source ) noexcept:
|
||||
m_os{ source.m_os },
|
||||
m_indent_level{ source.m_indent_level },
|
||||
m_should_comma{ source.m_should_comma },
|
||||
@@ -62,7 +62,7 @@ namespace Catch {
|
||||
m_os{ os }, m_indent_level{ indent_level } {
|
||||
m_os << '[';
|
||||
}
|
||||
JsonArrayWriter::JsonArrayWriter( JsonArrayWriter&& source ):
|
||||
JsonArrayWriter::JsonArrayWriter( JsonArrayWriter&& source ) noexcept:
|
||||
m_os{ source.m_os },
|
||||
m_indent_level{ source.m_indent_level },
|
||||
m_should_comma{ source.m_should_comma },
|
||||
|
@@ -65,7 +65,7 @@ namespace Catch {
|
||||
JsonObjectWriter( std::ostream& os );
|
||||
JsonObjectWriter( std::ostream& os, std::uint64_t indent_level );
|
||||
|
||||
JsonObjectWriter( JsonObjectWriter&& source );
|
||||
JsonObjectWriter( JsonObjectWriter&& source ) noexcept;
|
||||
JsonObjectWriter& operator=( JsonObjectWriter&& source ) = delete;
|
||||
|
||||
~JsonObjectWriter();
|
||||
@@ -84,7 +84,7 @@ namespace Catch {
|
||||
JsonArrayWriter( std::ostream& os );
|
||||
JsonArrayWriter( std::ostream& os, std::uint64_t indent_level );
|
||||
|
||||
JsonArrayWriter( JsonArrayWriter&& source );
|
||||
JsonArrayWriter( JsonArrayWriter&& source ) noexcept;
|
||||
JsonArrayWriter& operator=( JsonArrayWriter&& source ) = delete;
|
||||
|
||||
~JsonArrayWriter();
|
||||
|
@@ -14,10 +14,7 @@
|
||||
#include <catch2/internal/catch_reporter_registry.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
#include <catch2/internal/catch_case_insensitive_comparisons.hpp>
|
||||
|
||||
#include <catch2/internal/catch_context.hpp>
|
||||
#include <catch2/catch_config.hpp>
|
||||
#include <catch2/catch_test_spec.hpp>
|
||||
#include <catch2/catch_test_case_info.hpp>
|
||||
|
||||
namespace Catch {
|
||||
|
@@ -41,9 +41,8 @@ namespace Catch {
|
||||
struct ExtendedMultResult {
|
||||
T upper;
|
||||
T lower;
|
||||
friend bool operator==( ExtendedMultResult const& lhs,
|
||||
ExtendedMultResult const& rhs ) {
|
||||
return lhs.upper == rhs.upper && lhs.lower == rhs.lower;
|
||||
bool operator==( ExtendedMultResult const& rhs ) const {
|
||||
return upper == rhs.upper && lower == rhs.lower;
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -117,7 +117,7 @@ namespace Catch {
|
||||
auto kv = splitKVPair( parts[i] );
|
||||
auto key = kv.key, value = kv.value;
|
||||
|
||||
if ( key.empty() || value.empty() ) {
|
||||
if ( key.empty() || value.empty() ) { // NOLINT(bugprone-branch-clone)
|
||||
return {};
|
||||
} else if ( key[0] == 'X' ) {
|
||||
// This is a reporter-specific option, we don't check these
|
||||
|
@@ -8,7 +8,7 @@
|
||||
#ifndef CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
|
||||
#define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_console_colour.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_config.hpp>
|
||||
#include <catch2/internal/catch_optional.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
|
@@ -38,7 +38,6 @@ namespace Catch {
|
||||
TrackerContext& ctx,
|
||||
ITracker* parent ):
|
||||
TrackerBase( CATCH_MOVE( nameAndLocation ), ctx, parent ) {}
|
||||
~GeneratorTracker() override = default;
|
||||
|
||||
static GeneratorTracker*
|
||||
acquire( TrackerContext& ctx,
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
#include <catch2/internal/catch_section.hpp>
|
||||
#include <catch2/internal/catch_run_context.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_capture.hpp>
|
||||
#include <catch2/internal/catch_uncaught_exceptions.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
|
||||
|
@@ -69,7 +69,9 @@ namespace Catch {
|
||||
namespace Detail {
|
||||
// Intentionally without linkage, as it should only be used as a dummy
|
||||
// symbol for static analysis.
|
||||
int GetNewSectionHint();
|
||||
// The arguments are used as a dummy for checking warnings in the passed
|
||||
// expressions.
|
||||
int GetNewSectionHint( StringRef, const char* const = nullptr );
|
||||
} // namespace Detail
|
||||
} // namespace Catch
|
||||
|
||||
@@ -80,7 +82,8 @@ namespace Catch {
|
||||
CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
|
||||
if ( [[maybe_unused]] const int catchInternalPreviousSectionHint = \
|
||||
catchInternalSectionHint, \
|
||||
catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \
|
||||
catchInternalSectionHint = \
|
||||
Catch::Detail::GetNewSectionHint(__VA_ARGS__); \
|
||||
catchInternalPreviousSectionHint == __LINE__ ) \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
|
||||
@@ -90,7 +93,8 @@ namespace Catch {
|
||||
CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
|
||||
if ( [[maybe_unused]] const int catchInternalPreviousSectionHint = \
|
||||
catchInternalSectionHint, \
|
||||
catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \
|
||||
catchInternalSectionHint = Catch::Detail::GetNewSectionHint( \
|
||||
( Catch::ReusableStringStream() << __VA_ARGS__ ).str()); \
|
||||
catchInternalPreviousSectionHint == __LINE__ ) \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
|
||||
|
@@ -8,8 +8,7 @@
|
||||
#ifndef CATCH_SHARDING_HPP_INCLUDED
|
||||
#define CATCH_SHARDING_HPP_INCLUDED
|
||||
|
||||
#include <catch2/catch_session.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
|
@@ -5,6 +5,7 @@
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
#include <catch2/internal/catch_string_manip.hpp>
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
|
||||
@@ -65,17 +66,29 @@ namespace Catch {
|
||||
}
|
||||
|
||||
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
|
||||
bool replaced = false;
|
||||
std::size_t i = str.find( replaceThis );
|
||||
while( i != std::string::npos ) {
|
||||
replaced = true;
|
||||
str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
|
||||
if( i < str.size()-withThis.size() )
|
||||
i = str.find( replaceThis, i+withThis.size() );
|
||||
if (i == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
std::size_t copyBegin = 0;
|
||||
std::string origStr = CATCH_MOVE(str);
|
||||
str.clear();
|
||||
// There is at least one replacement, so reserve with the best guess
|
||||
// we can make without actually counting the number of occurences.
|
||||
str.reserve(origStr.size() - replaceThis.size() + withThis.size());
|
||||
do {
|
||||
str.append(origStr, copyBegin, i-copyBegin );
|
||||
str += withThis;
|
||||
copyBegin = i + replaceThis.size();
|
||||
if( copyBegin < origStr.size() )
|
||||
i = origStr.find( replaceThis, copyBegin );
|
||||
else
|
||||
i = std::string::npos;
|
||||
} while( i != std::string::npos );
|
||||
if ( copyBegin < origStr.size() ) {
|
||||
str.append(origStr, copyBegin, origStr.size() );
|
||||
}
|
||||
return replaced;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) {
|
||||
|
@@ -25,6 +25,8 @@ namespace Catch {
|
||||
using size_type = std::size_t;
|
||||
using const_iterator = const char*;
|
||||
|
||||
static constexpr size_type npos{ static_cast<size_type>( -1 ) };
|
||||
|
||||
private:
|
||||
static constexpr char const* const s_empty = "";
|
||||
|
||||
@@ -75,7 +77,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
// Returns a substring of [start, start + length).
|
||||
// If start + length > size(), then the substring is [start, start + size()).
|
||||
// If start + length > size(), then the substring is [start, size()).
|
||||
// If start > size(), then the substring is empty.
|
||||
constexpr StringRef substr(size_type start, size_type length) const noexcept {
|
||||
if (start < m_size) {
|
||||
@@ -95,8 +97,8 @@ namespace Catch {
|
||||
constexpr const_iterator end() const { return m_start + m_size; }
|
||||
|
||||
|
||||
friend std::string& operator += (std::string& lhs, StringRef sr);
|
||||
friend std::ostream& operator << (std::ostream& os, StringRef sr);
|
||||
friend std::string& operator += (std::string& lhs, StringRef rhs);
|
||||
friend std::ostream& operator << (std::ostream& os, StringRef str);
|
||||
friend std::string operator+(StringRef lhs, StringRef rhs);
|
||||
|
||||
/**
|
||||
|
@@ -6,7 +6,6 @@
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
#include <catch2/internal/catch_tag_alias_registry.hpp>
|
||||
#include <catch2/internal/catch_console_colour.hpp>
|
||||
#include <catch2/internal/catch_enforce.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
|
||||
#include <catch2/internal/catch_string_manip.hpp>
|
||||
|
@@ -7,12 +7,9 @@
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
#include <catch2/internal/catch_test_case_registry_impl.hpp>
|
||||
|
||||
#include <catch2/internal/catch_context.hpp>
|
||||
#include <catch2/internal/catch_enforce.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_config.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_registry_hub.hpp>
|
||||
#include <catch2/internal/catch_random_number_generator.hpp>
|
||||
#include <catch2/internal/catch_run_context.hpp>
|
||||
#include <catch2/internal/catch_sharding.hpp>
|
||||
#include <catch2/catch_test_case_info.hpp>
|
||||
#include <catch2/catch_test_spec.hpp>
|
||||
@@ -73,7 +70,6 @@ namespace Catch {
|
||||
return sorted;
|
||||
}
|
||||
case TestRunOrder::Randomized: {
|
||||
seedRng(config);
|
||||
using TestWithHash = std::pair<TestCaseInfoHasher::hash_t, TestCaseHandle>;
|
||||
|
||||
TestCaseInfoHasher h{ config.rngSeed() };
|
||||
|
@@ -30,8 +30,6 @@ namespace Catch {
|
||||
|
||||
class TestRegistry : public ITestCaseRegistry {
|
||||
public:
|
||||
~TestRegistry() override = default;
|
||||
|
||||
void registerTest( Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker );
|
||||
|
||||
std::vector<TestCaseInfo*> const& getAllInfos() const override;
|
||||
|
@@ -49,7 +49,7 @@
|
||||
INTERNAL_CATCH_TRY { \
|
||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
||||
catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
|
||||
catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); /* NOLINT(bugprone-chained-comparison) */ \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
|
||||
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
|
||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||
|
@@ -95,7 +95,7 @@ struct AutoReg : Detail::NonCopyable {
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
struct DummyUse {
|
||||
DummyUse( void ( * )( int ) );
|
||||
DummyUse( void ( * )( int ), Catch::NameAndTags const& );
|
||||
};
|
||||
} // namespace Detail
|
||||
} // namespace Catch
|
||||
@@ -107,18 +107,18 @@ namespace Catch {
|
||||
// tests can compile. The redefined `TEST_CASE` shadows this with param.
|
||||
static int catchInternalSectionHint = 0;
|
||||
|
||||
# define INTERNAL_CATCH_TESTCASE2( fname ) \
|
||||
# define INTERNAL_CATCH_TESTCASE2( fname, ... ) \
|
||||
static void fname( int ); \
|
||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
|
||||
static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME( \
|
||||
dummyUser )( &(fname) ); \
|
||||
dummyUser )( &(fname), Catch::NameAndTags{ __VA_ARGS__ } ); \
|
||||
CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
|
||||
static void fname( [[maybe_unused]] int catchInternalSectionHint ) \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
# define INTERNAL_CATCH_TESTCASE( ... ) \
|
||||
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ) )
|
||||
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ), __VA_ARGS__ )
|
||||
|
||||
|
||||
#endif // CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
|
||||
|
@@ -233,23 +233,36 @@ namespace Catch {
|
||||
return os;
|
||||
}
|
||||
|
||||
Columns Column::operator+( Column const& other ) {
|
||||
Columns operator+(Column const& lhs, Column const& rhs) {
|
||||
Columns cols;
|
||||
cols += *this;
|
||||
cols += other;
|
||||
cols += lhs;
|
||||
cols += rhs;
|
||||
return cols;
|
||||
}
|
||||
Columns operator+(Column&& lhs, Column&& rhs) {
|
||||
Columns cols;
|
||||
cols += CATCH_MOVE( lhs );
|
||||
cols += CATCH_MOVE( rhs );
|
||||
return cols;
|
||||
}
|
||||
|
||||
Columns& Columns::operator+=( Column const& col ) {
|
||||
m_columns.push_back( col );
|
||||
return *this;
|
||||
Columns& operator+=(Columns& lhs, Column const& rhs) {
|
||||
lhs.m_columns.push_back( rhs );
|
||||
return lhs;
|
||||
}
|
||||
|
||||
Columns Columns::operator+( Column const& col ) {
|
||||
Columns combined = *this;
|
||||
combined += col;
|
||||
Columns& operator+=(Columns& lhs, Column&& rhs) {
|
||||
lhs.m_columns.push_back( CATCH_MOVE(rhs) );
|
||||
return lhs;
|
||||
}
|
||||
Columns operator+( Columns const& lhs, Column const& rhs ) {
|
||||
auto combined( lhs );
|
||||
combined += rhs;
|
||||
return combined;
|
||||
}
|
||||
Columns operator+( Columns&& lhs, Column&& rhs ) {
|
||||
lhs += CATCH_MOVE( rhs );
|
||||
return CATCH_MOVE( lhs );
|
||||
}
|
||||
|
||||
} // namespace TextFlow
|
||||
} // namespace Catch
|
||||
|
@@ -8,8 +8,10 @@
|
||||
#ifndef CATCH_TEXTFLOW_HPP_INCLUDED
|
||||
#define CATCH_TEXTFLOW_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
#include <catch2/internal/catch_console_width.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -37,7 +39,7 @@ namespace Catch {
|
||||
|
||||
public:
|
||||
/**
|
||||
* Iterates "lines" in `Column` and return sthem
|
||||
* Iterates "lines" in `Column` and returns them
|
||||
*/
|
||||
class const_iterator {
|
||||
friend Column;
|
||||
@@ -91,20 +93,35 @@ namespace Catch {
|
||||
using iterator = const_iterator;
|
||||
|
||||
explicit Column( std::string const& text ): m_string( text ) {}
|
||||
explicit Column( std::string&& text ):
|
||||
m_string( CATCH_MOVE(text)) {}
|
||||
|
||||
Column& width( size_t newWidth ) {
|
||||
Column& width( size_t newWidth ) & {
|
||||
assert( newWidth > 0 );
|
||||
m_width = newWidth;
|
||||
return *this;
|
||||
}
|
||||
Column& indent( size_t newIndent ) {
|
||||
Column&& width( size_t newWidth ) && {
|
||||
assert( newWidth > 0 );
|
||||
m_width = newWidth;
|
||||
return CATCH_MOVE( *this );
|
||||
}
|
||||
Column& indent( size_t newIndent ) & {
|
||||
m_indent = newIndent;
|
||||
return *this;
|
||||
}
|
||||
Column& initialIndent( size_t newIndent ) {
|
||||
Column&& indent( size_t newIndent ) && {
|
||||
m_indent = newIndent;
|
||||
return CATCH_MOVE( *this );
|
||||
}
|
||||
Column& initialIndent( size_t newIndent ) & {
|
||||
m_initialIndent = newIndent;
|
||||
return *this;
|
||||
}
|
||||
Column&& initialIndent( size_t newIndent ) && {
|
||||
m_initialIndent = newIndent;
|
||||
return CATCH_MOVE( *this );
|
||||
}
|
||||
|
||||
size_t width() const { return m_width; }
|
||||
const_iterator begin() const { return const_iterator( *this ); }
|
||||
@@ -113,7 +130,8 @@ namespace Catch {
|
||||
friend std::ostream& operator<<( std::ostream& os,
|
||||
Column const& col );
|
||||
|
||||
Columns operator+( Column const& other );
|
||||
friend Columns operator+( Column const& lhs, Column const& rhs );
|
||||
friend Columns operator+( Column&& lhs, Column&& rhs );
|
||||
};
|
||||
|
||||
//! Creates a column that serves as an empty space of specific width
|
||||
@@ -157,8 +175,10 @@ namespace Catch {
|
||||
iterator begin() const { return iterator( *this ); }
|
||||
iterator end() const { return { *this, iterator::EndTag() }; }
|
||||
|
||||
Columns& operator+=( Column const& col );
|
||||
Columns operator+( Column const& col );
|
||||
friend Columns& operator+=( Columns& lhs, Column const& rhs );
|
||||
friend Columns& operator+=( Columns& lhs, Column&& rhs );
|
||||
friend Columns operator+( Columns const& lhs, Column const& rhs );
|
||||
friend Columns operator+( Columns&& lhs, Column&& rhs );
|
||||
|
||||
friend std::ostream& operator<<( std::ostream& os,
|
||||
Columns const& cols );
|
||||
|
@@ -7,7 +7,6 @@
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
#include <catch2/internal/catch_uncaught_exceptions.hpp>
|
||||
#include <catch2/internal/catch_compiler_capabilities.hpp>
|
||||
#include <catch2/internal/catch_config_uncaught_exceptions.hpp>
|
||||
#include <catch2/catch_user_config.hpp>
|
||||
|
||||
|
@@ -46,12 +46,12 @@ class uniform_integer_distribution {
|
||||
|
||||
using UnsignedIntegerType = Detail::make_unsigned_t<IntegerType>;
|
||||
|
||||
// We store the left range bound converted to internal representation,
|
||||
// because it will be used in computation in the () operator.
|
||||
// Only the left bound is stored, and we store it converted to its
|
||||
// unsigned image. This avoids having to do the conversions inside
|
||||
// the operator(), at the cost of having to do the conversion in
|
||||
// the a() getter. The right bound is only needed in the b() getter,
|
||||
// so we recompute it there from other stored data.
|
||||
UnsignedIntegerType m_a;
|
||||
// After initialization, right bound is only used for the b() getter,
|
||||
// so we keep it in the original type.
|
||||
IntegerType m_b;
|
||||
|
||||
// How many different values are there in [a, b]. a == b => 1, can be 0 for distribution over all values in the type.
|
||||
UnsignedIntegerType m_ab_distance;
|
||||
@@ -64,11 +64,10 @@ class uniform_integer_distribution {
|
||||
// distribution will be reused many times and this is an optimization.
|
||||
UnsignedIntegerType m_rejection_threshold = 0;
|
||||
|
||||
// Assumes m_b and m_a are already filled
|
||||
UnsignedIntegerType computeDistance() const {
|
||||
// This overflows and returns 0 if ua == 0 and ub == TYPE_MAX.
|
||||
UnsignedIntegerType computeDistance(IntegerType a, IntegerType b) const {
|
||||
// This overflows and returns 0 if a == 0 and b == TYPE_MAX.
|
||||
// We handle that later when generating the number.
|
||||
return transposeTo(m_b) - m_a + 1;
|
||||
return transposeTo(b) - transposeTo(a) + 1;
|
||||
}
|
||||
|
||||
static UnsignedIntegerType computeRejectionThreshold(UnsignedIntegerType ab_distance) {
|
||||
@@ -92,8 +91,7 @@ public:
|
||||
|
||||
uniform_integer_distribution( IntegerType a, IntegerType b ):
|
||||
m_a( transposeTo(a) ),
|
||||
m_b( b ),
|
||||
m_ab_distance( computeDistance() ),
|
||||
m_ab_distance( computeDistance(a, b) ),
|
||||
m_rejection_threshold( computeRejectionThreshold(m_ab_distance) ) {
|
||||
assert( a <= b );
|
||||
}
|
||||
@@ -118,7 +116,7 @@ public:
|
||||
}
|
||||
|
||||
result_type a() const { return transposeBack(m_a); }
|
||||
result_type b() const { return m_b; }
|
||||
result_type b() const { return transposeBack(m_ab_distance + m_a - 1); }
|
||||
};
|
||||
|
||||
} // end namespace Catch
|
||||
|
@@ -18,6 +18,8 @@ configure_file(
|
||||
configuration: conf_data,
|
||||
)
|
||||
|
||||
fs = import('fs')
|
||||
|
||||
benchmark_headers = [
|
||||
'benchmark/catch_benchmark.hpp',
|
||||
'benchmark/catch_benchmark_all.hpp',
|
||||
@@ -340,9 +342,19 @@ foreach file : headers
|
||||
install_headers(file, subdir: join_paths(include_subdir, folder))
|
||||
endforeach
|
||||
|
||||
catch2_dependencies = []
|
||||
# Check if this is an Android NDK build.
|
||||
if ((host_machine.system() == 'android') or
|
||||
# Check if this is an Android Termux build.
|
||||
(host_machine.system() == 'linux' and fs.is_dir('/data/data/com.termux')))
|
||||
log_dep = meson.get_compiler('cpp').find_library('log')
|
||||
catch2_dependencies += log_dep
|
||||
endif
|
||||
|
||||
catch2 = static_library(
|
||||
'Catch2',
|
||||
sources,
|
||||
dependencies: catch2_dependencies,
|
||||
include_directories: '..',
|
||||
install: true,
|
||||
)
|
||||
|
@@ -209,13 +209,6 @@ findMax( std::size_t& i, std::size_t& j, std::size_t& k, std::size_t& l ) {
|
||||
return l;
|
||||
}
|
||||
|
||||
enum class Justification { Left, Right };
|
||||
|
||||
struct ColumnInfo {
|
||||
std::string name;
|
||||
std::size_t width;
|
||||
Justification justification;
|
||||
};
|
||||
struct ColumnBreak {};
|
||||
struct RowBreak {};
|
||||
struct OutputFlush {};
|
||||
@@ -293,6 +286,14 @@ public:
|
||||
};
|
||||
} // end anon namespace
|
||||
|
||||
enum class Justification { Left, Right };
|
||||
|
||||
struct ColumnInfo {
|
||||
std::string name;
|
||||
std::size_t width;
|
||||
Justification justification;
|
||||
};
|
||||
|
||||
class TablePrinter {
|
||||
std::ostream& m_os;
|
||||
std::vector<ColumnInfo> m_columnInfos;
|
||||
@@ -315,11 +316,10 @@ public:
|
||||
*this << RowBreak();
|
||||
|
||||
TextFlow::Columns headerCols;
|
||||
auto spacer = TextFlow::Spacer(2);
|
||||
for (auto const& info : m_columnInfos) {
|
||||
assert(info.width > 2);
|
||||
headerCols += TextFlow::Column(info.name).width(info.width - 2);
|
||||
headerCols += spacer;
|
||||
headerCols += TextFlow::Spacer( 2 );
|
||||
}
|
||||
m_os << headerCols << '\n';
|
||||
|
||||
@@ -520,8 +520,8 @@ void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {
|
||||
m_stream << '\n' << std::flush;
|
||||
StreamingReporterBase::testRunEnded(_testRunStats);
|
||||
}
|
||||
void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) {
|
||||
StreamingReporterBase::testRunStarting(_testInfo);
|
||||
void ConsoleReporter::testRunStarting(TestRunInfo const& _testRunInfo) {
|
||||
StreamingReporterBase::testRunStarting(_testRunInfo);
|
||||
if ( m_config->testSpec().hasFilters() ) {
|
||||
m_stream << m_colour->guardColour( Colour::BrightYellow ) << "Filters: "
|
||||
<< m_config->testSpec() << '\n';
|
||||
|
@@ -16,8 +16,7 @@ namespace Catch {
|
||||
namespace {
|
||||
struct BySectionInfo {
|
||||
BySectionInfo( SectionInfo const& other ): m_other( other ) {}
|
||||
BySectionInfo( BySectionInfo const& other ):
|
||||
m_other( other.m_other ) {}
|
||||
BySectionInfo( BySectionInfo const& other ) = default;
|
||||
bool operator()(
|
||||
Detail::unique_ptr<CumulativeReporterBase::SectionNode> const&
|
||||
node ) const {
|
||||
|
@@ -133,8 +133,8 @@ namespace Catch {
|
||||
return "Outputs listings as JSON. Test listing is Work-in-Progress!";
|
||||
}
|
||||
|
||||
void JsonReporter::testRunStarting( TestRunInfo const& testInfo ) {
|
||||
StreamingReporterBase::testRunStarting( testInfo );
|
||||
void JsonReporter::testRunStarting( TestRunInfo const& runInfo ) {
|
||||
StreamingReporterBase::testRunStarting( runInfo );
|
||||
endListing();
|
||||
|
||||
assert( isInside( Writer::Object ) );
|
||||
|
@@ -74,7 +74,7 @@ namespace Catch {
|
||||
|
||||
static void normalizeNamespaceMarkers(std::string& str) {
|
||||
std::size_t pos = str.find( "::" );
|
||||
while ( pos != str.npos ) {
|
||||
while ( pos != std::string::npos ) {
|
||||
str.replace( pos, 2, "." );
|
||||
pos += 1;
|
||||
pos = str.find( "::", pos );
|
||||
|
@@ -19,8 +19,6 @@ namespace Catch {
|
||||
public:
|
||||
JunitReporter(ReporterConfig&& _config);
|
||||
|
||||
~JunitReporter() override = default;
|
||||
|
||||
static std::string getDescription();
|
||||
|
||||
void testRunStarting(TestRunInfo const& runInfo) override;
|
||||
|
@@ -53,7 +53,7 @@ namespace Catch {
|
||||
|
||||
void assertionEnded( AssertionStats const& assertionStats ) override;
|
||||
void sectionEnded( SectionStats const& sectionStats ) override;
|
||||
void testCasePartialEnded(TestCaseStats const& testInfo, uint64_t partNumber) override;
|
||||
void testCasePartialEnded(TestCaseStats const& testStats, uint64_t partNumber) override;
|
||||
void testCaseEnded( TestCaseStats const& testCaseStats ) override;
|
||||
void testRunEnded( TestRunStats const& testRunStats ) override;
|
||||
|
||||
|
@@ -25,8 +25,6 @@ namespace Catch {
|
||||
m_shouldStoreSuccesfulAssertions = false;
|
||||
}
|
||||
|
||||
~SonarQubeReporter() override = default;
|
||||
|
||||
static std::string getDescription() {
|
||||
using namespace std::string_literals;
|
||||
return "Reports test results in the Generic Test Data SonarQube XML format"s;
|
||||
@@ -39,7 +37,7 @@ namespace Catch {
|
||||
xml.endElement();
|
||||
}
|
||||
|
||||
void writeRun( TestRunNode const& groupNode );
|
||||
void writeRun( TestRunNode const& runNode );
|
||||
|
||||
void writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes);
|
||||
|
||||
|
@@ -19,7 +19,6 @@ namespace Catch {
|
||||
StreamingReporterBase( CATCH_MOVE(config) ) {
|
||||
m_preferences.shouldReportAllAssertions = true;
|
||||
}
|
||||
~TAPReporter() override = default;
|
||||
|
||||
static std::string getDescription() {
|
||||
using namespace std::string_literals;
|
||||
|
@@ -35,8 +35,8 @@ namespace Catch {
|
||||
return "Reports test results as TeamCity service messages"s;
|
||||
}
|
||||
|
||||
void testRunStarting( TestRunInfo const& groupInfo ) override;
|
||||
void testRunEnded( TestRunStats const& testGroupStats ) override;
|
||||
void testRunStarting( TestRunInfo const& runInfo ) override;
|
||||
void testRunEnded( TestRunStats const& runStats ) override;
|
||||
|
||||
|
||||
void assertionEnded(AssertionStats const& assertionStats) override;
|
||||
|
@@ -34,7 +34,7 @@ public:
|
||||
return "Custom reporter for testing cumulative reporter base";
|
||||
}
|
||||
|
||||
virtual void testRunEndedCumulative() override;
|
||||
void testRunEndedCumulative() override;
|
||||
};
|
||||
|
||||
CATCH_REGISTER_REPORTER("testReporter", CumulativeBenchmarkReporter)
|
||||
|
@@ -36,6 +36,7 @@ public:
|
||||
|
||||
void testRunStarting( Catch::TestRunInfo const& ) override {
|
||||
std::vector<std::pair<std::string, std::string>> options;
|
||||
options.reserve( m_customOptions.size() );
|
||||
for ( auto const& kv : m_customOptions ) {
|
||||
options.push_back( kv );
|
||||
}
|
||||
|
@@ -16,10 +16,10 @@
|
||||
TEST_CASE("Just a dummy test") {
|
||||
auto i = GENERATE(1, 2, 3);
|
||||
SECTION("a") {
|
||||
REQUIRE(1 != 4);
|
||||
REQUIRE(i != 4);
|
||||
}
|
||||
SECTION("b") {
|
||||
CHECK(1 != 5);
|
||||
CHECK(i != 5);
|
||||
}
|
||||
REQUIRE_THAT(1,
|
||||
Catch::Matchers::Predicate<int>([](int i) {
|
||||
|
@@ -350,20 +350,16 @@ Details.tests.cpp:<line number>: passed: lt( "a", "b" ) for: true
|
||||
Details.tests.cpp:<line number>: passed: lt( "a", "B" ) for: true
|
||||
Details.tests.cpp:<line number>: passed: lt( "A", "b" ) for: true
|
||||
Details.tests.cpp:<line number>: passed: lt( "A", "B" ) for: true
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: tab == '\t' for: '\t' == '\t'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: newline == '\n' for: '\n' == '\n'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: carr_return == '\r' for: '\r' == '\r'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: form_feed == '\f' for: '\f' == '\f'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: space == ' ' for: ' ' == ' '
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'a' == 'a'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'z' == 'z'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'A' == 'A'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'Z' == 'Z'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: null_terminator == '\0' for: 0 == 0
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 2 == 2
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 3 == 3
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 4 == 4
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 5 == 5
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify('\t') == "'\\t'" for: "'\t'" == "'\t'"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify('\n') == "'\\n'" for: "'\n'" == "'\n'"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify('\r') == "'\\r'" for: "'\r'" == "'\r'"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify('\f') == "'\\f'" for: "'\f'" == "'\f'"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( ' ' ) == "' '" for: "' '" == "' '"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( 'A' ) == "'A'" for: "'A'" == "'A'"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( 'z' ) == "'z'" for: "'z'" == "'z'"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( '\0' ) == "0" for: "0" == "0"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( static_cast<char>(2) ) == "2" for: "2" == "2"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( static_cast<char>(5) ) == "5" for: "5" == "5"
|
||||
Clara.tests.cpp:<line number>: passed: name.empty() for: true
|
||||
Clara.tests.cpp:<line number>: passed: name == "foo" for: "foo" == "foo"
|
||||
Clara.tests.cpp:<line number>: passed: !(parse_result) for: !{?}
|
||||
@@ -1737,13 +1733,13 @@ Tag.tests.cpp:<line number>: passed: testCase.tags, VectorContains( Tag( "tag wi
|
||||
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1 == 1
|
||||
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1 == 1
|
||||
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1.0 == 1
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 1 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 1 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 1 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
|
||||
Misc.tests.cpp:<line number>: passed: std::is_default_constructible<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: std::is_default_constructible<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: std::is_trivially_copyable<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: std::is_trivially_copyable<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: std::is_arithmetic<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: std::is_arithmetic<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: std::is_arithmetic<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
|
||||
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
|
||||
Misc.tests.cpp:<line number>: passed: v.size() == 10 for: 10 == 10
|
||||
@@ -2483,6 +2479,10 @@ StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, lett
|
||||
StringManip.tests.cpp:<line number>: passed: letters == "replaced" for: "replaced" == "replaced"
|
||||
StringManip.tests.cpp:<line number>: passed: !(Catch::replaceInPlace(letters, "x", "z")) for: !false
|
||||
StringManip.tests.cpp:<line number>: passed: letters == letters for: "abcdefcg" == "abcdefcg"
|
||||
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, "c", "cc") for: true
|
||||
StringManip.tests.cpp:<line number>: passed: letters == "abccdefccg" for: "abccdefccg" == "abccdefccg"
|
||||
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(s, "--", "-") for: true
|
||||
StringManip.tests.cpp:<line number>: passed: s == "--" for: "--" == "--"
|
||||
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(s, "'", "|'") for: true
|
||||
StringManip.tests.cpp:<line number>: passed: s == "didn|'t" for: "didn|'t" == "didn|'t"
|
||||
Stream.tests.cpp:<line number>: passed: Catch::makeStream( "%somestream" )
|
||||
|
@@ -348,20 +348,16 @@ Details.tests.cpp:<line number>: passed: lt( "a", "b" ) for: true
|
||||
Details.tests.cpp:<line number>: passed: lt( "a", "B" ) for: true
|
||||
Details.tests.cpp:<line number>: passed: lt( "A", "b" ) for: true
|
||||
Details.tests.cpp:<line number>: passed: lt( "A", "B" ) for: true
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: tab == '\t' for: '\t' == '\t'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: newline == '\n' for: '\n' == '\n'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: carr_return == '\r' for: '\r' == '\r'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: form_feed == '\f' for: '\f' == '\f'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: space == ' ' for: ' ' == ' '
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'a' == 'a'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'z' == 'z'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'A' == 'A'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'Z' == 'Z'
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: null_terminator == '\0' for: 0 == 0
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 2 == 2
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 3 == 3
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 4 == 4
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 5 == 5
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify('\t') == "'\\t'" for: "'\t'" == "'\t'"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify('\n') == "'\\n'" for: "'\n'" == "'\n'"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify('\r') == "'\\r'" for: "'\r'" == "'\r'"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify('\f') == "'\\f'" for: "'\f'" == "'\f'"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( ' ' ) == "' '" for: "' '" == "' '"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( 'A' ) == "'A'" for: "'A'" == "'A'"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( 'z' ) == "'z'" for: "'z'" == "'z'"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( '\0' ) == "0" for: "0" == "0"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( static_cast<char>(2) ) == "2" for: "2" == "2"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( static_cast<char>(5) ) == "5" for: "5" == "5"
|
||||
Clara.tests.cpp:<line number>: passed: name.empty() for: true
|
||||
Clara.tests.cpp:<line number>: passed: name == "foo" for: "foo" == "foo"
|
||||
Clara.tests.cpp:<line number>: passed: !(parse_result) for: !{?}
|
||||
@@ -1730,13 +1726,13 @@ Tag.tests.cpp:<line number>: passed: testCase.tags, VectorContains( Tag( "tag wi
|
||||
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1 == 1
|
||||
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1 == 1
|
||||
Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1.0 == 1
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 1 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 1 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 1 > 0
|
||||
Misc.tests.cpp:<line number>: passed: sizeof(TestType) > 0 for: 4 > 0
|
||||
Misc.tests.cpp:<line number>: passed: std::is_default_constructible<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: std::is_default_constructible<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: std::is_trivially_copyable<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: std::is_trivially_copyable<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: std::is_arithmetic<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: std::is_arithmetic<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: std::is_arithmetic<TestType>::value for: true
|
||||
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
|
||||
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
|
||||
Misc.tests.cpp:<line number>: passed: v.size() == 10 for: 10 == 10
|
||||
@@ -2472,6 +2468,10 @@ StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, lett
|
||||
StringManip.tests.cpp:<line number>: passed: letters == "replaced" for: "replaced" == "replaced"
|
||||
StringManip.tests.cpp:<line number>: passed: !(Catch::replaceInPlace(letters, "x", "z")) for: !false
|
||||
StringManip.tests.cpp:<line number>: passed: letters == letters for: "abcdefcg" == "abcdefcg"
|
||||
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(letters, "c", "cc") for: true
|
||||
StringManip.tests.cpp:<line number>: passed: letters == "abccdefccg" for: "abccdefccg" == "abccdefccg"
|
||||
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(s, "--", "-") for: true
|
||||
StringManip.tests.cpp:<line number>: passed: s == "--" for: "--" == "--"
|
||||
StringManip.tests.cpp:<line number>: passed: Catch::replaceInPlace(s, "'", "|'") for: true
|
||||
StringManip.tests.cpp:<line number>: passed: s == "didn|'t" for: "didn|'t" == "didn|'t"
|
||||
Stream.tests.cpp:<line number>: passed: Catch::makeStream( "%somestream" )
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user