mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-13 00:45:39 +02:00
Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
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
|
||||
|
@@ -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.2 # 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",
|
||||
],
|
||||
)
|
||||
|
||||
|
@@ -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,8 @@
|
||||
|
||||
# Release notes
|
||||
**Contents**<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 +60,24 @@
|
||||
[Even Older versions](#even-older-versions)<br>
|
||||
|
||||
|
||||
## 3.5.1
|
||||
|
||||
### 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 +95,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.
|
||||
|
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 << std::endl;
|
||||
|
||||
return session.run();
|
||||
}
|
@@ -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.2
|
||||
// Generated: 2024-01-15 14:06:36.675713
|
||||
// ----------------------------------------------------------
|
||||
// This file is an amalgamation of multiple different files.
|
||||
// You probably shouldn't edit it directly.
|
||||
@@ -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() );
|
||||
@@ -2273,7 +2268,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Version const& libraryVersion() {
|
||||
static Version version( 3, 5, 0, "", 0 );
|
||||
static Version version( 3, 5, 2, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
@@ -2415,9 +2410,7 @@ namespace Catch {
|
||||
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -2627,13 +2620,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 +2660,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 +2736,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 +2759,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 +2797,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 +2810,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 +2829,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 +2889,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 +2921,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 +2961,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 +2988,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 +3006,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 +3014,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 +3040,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()) {}
|
||||
|
||||
@@ -3338,8 +3346,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" )
|
||||
@@ -4367,7 +4375,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 +4389,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 +4402,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 +4419,6 @@ namespace Detail {
|
||||
m_os( m_streamBuf.get() )
|
||||
{}
|
||||
|
||||
~DebugOutStream() override = default;
|
||||
|
||||
public: // IStream
|
||||
std::ostream& stream() override { return m_os; }
|
||||
};
|
||||
@@ -4641,7 +4644,6 @@ Catch::LeakDetector::~LeakDetector() {
|
||||
|
||||
|
||||
|
||||
|
||||
namespace Catch {
|
||||
namespace {
|
||||
|
||||
@@ -5429,7 +5431,6 @@ namespace Catch {
|
||||
TrackerContext& ctx,
|
||||
ITracker* parent ):
|
||||
TrackerBase( CATCH_MOVE( nameAndLocation ), ctx, parent ) {}
|
||||
~GeneratorTracker() override = default;
|
||||
|
||||
static GeneratorTracker*
|
||||
acquire( TrackerContext& ctx,
|
||||
@@ -6527,7 +6528,6 @@ namespace Catch {
|
||||
return sorted;
|
||||
}
|
||||
case TestRunOrder::Randomized: {
|
||||
seedRng(config);
|
||||
using TestWithHash = std::pair<TestCaseInfoHasher::hash_t, TestCaseHandle>;
|
||||
|
||||
TestCaseInfoHasher h{ config.rngSeed() };
|
||||
@@ -7390,23 +7390,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 +8788,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 +8865,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 +8895,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';
|
||||
|
||||
|
@@ -6,8 +6,8 @@
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
// Catch v3.5.0
|
||||
// Generated: 2023-12-11 00:51:06.770598
|
||||
// Catch v3.5.2
|
||||
// Generated: 2024-01-15 14:06:34.036475
|
||||
// ----------------------------------------------------------
|
||||
// This file is an amalgamation of multiple different files.
|
||||
// You probably shouldn't edit it directly.
|
||||
@@ -690,6 +690,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 = "";
|
||||
|
||||
@@ -740,7 +742,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) {
|
||||
@@ -1969,12 +1971,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())),
|
||||
@@ -1996,7 +1998,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));
|
||||
@@ -3639,141 +3641,6 @@ namespace Catch {
|
||||
#define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
|
||||
|
||||
|
||||
|
||||
#ifndef CATCH_CONSOLE_COLOUR_HPP_INCLUDED
|
||||
#define CATCH_CONSOLE_COLOUR_HPP_INCLUDED
|
||||
|
||||
|
||||
#include <iosfwd>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
enum class ColourMode : std::uint8_t;
|
||||
class IStream;
|
||||
|
||||
struct Colour {
|
||||
enum Code {
|
||||
None = 0,
|
||||
|
||||
White,
|
||||
Red,
|
||||
Green,
|
||||
Blue,
|
||||
Cyan,
|
||||
Yellow,
|
||||
Grey,
|
||||
|
||||
Bright = 0x10,
|
||||
|
||||
BrightRed = Bright | Red,
|
||||
BrightGreen = Bright | Green,
|
||||
LightGrey = Bright | Grey,
|
||||
BrightWhite = Bright | White,
|
||||
BrightYellow = Bright | Yellow,
|
||||
|
||||
// By intention
|
||||
FileName = LightGrey,
|
||||
Warning = BrightYellow,
|
||||
ResultError = BrightRed,
|
||||
ResultSuccess = BrightGreen,
|
||||
ResultExpectedFailure = Warning,
|
||||
|
||||
Error = BrightRed,
|
||||
Success = Green,
|
||||
Skip = LightGrey,
|
||||
|
||||
OriginalExpression = Cyan,
|
||||
ReconstructedExpression = BrightYellow,
|
||||
|
||||
SecondaryText = LightGrey,
|
||||
Headers = White
|
||||
};
|
||||
};
|
||||
|
||||
class ColourImpl {
|
||||
protected:
|
||||
//! The associated stream of this ColourImpl instance
|
||||
IStream* m_stream;
|
||||
public:
|
||||
ColourImpl( IStream* stream ): m_stream( stream ) {}
|
||||
|
||||
//! RAII wrapper around writing specific colour of text using specific
|
||||
//! colour impl into a stream.
|
||||
class ColourGuard {
|
||||
ColourImpl const* m_colourImpl;
|
||||
Colour::Code m_code;
|
||||
bool m_engaged = false;
|
||||
|
||||
public:
|
||||
//! Does **not** engage the guard/start the colour
|
||||
ColourGuard( Colour::Code code,
|
||||
ColourImpl const* colour );
|
||||
|
||||
ColourGuard( ColourGuard const& rhs ) = delete;
|
||||
ColourGuard& operator=( ColourGuard const& rhs ) = delete;
|
||||
|
||||
ColourGuard( ColourGuard&& rhs ) noexcept;
|
||||
ColourGuard& operator=( ColourGuard&& rhs ) noexcept;
|
||||
|
||||
//! Removes colour _if_ the guard was engaged
|
||||
~ColourGuard();
|
||||
|
||||
/**
|
||||
* Explicitly engages colour for given stream.
|
||||
*
|
||||
* The API based on operator<< should be preferred.
|
||||
*/
|
||||
ColourGuard& engage( std::ostream& stream ) &;
|
||||
/**
|
||||
* Explicitly engages colour for given stream.
|
||||
*
|
||||
* The API based on operator<< should be preferred.
|
||||
*/
|
||||
ColourGuard&& engage( std::ostream& stream ) &&;
|
||||
|
||||
private:
|
||||
//! Engages the guard and starts using colour
|
||||
friend std::ostream& operator<<( std::ostream& lhs,
|
||||
ColourGuard& guard ) {
|
||||
guard.engageImpl( lhs );
|
||||
return lhs;
|
||||
}
|
||||
//! Engages the guard and starts using colour
|
||||
friend std::ostream& operator<<( std::ostream& lhs,
|
||||
ColourGuard&& guard) {
|
||||
guard.engageImpl( lhs );
|
||||
return lhs;
|
||||
}
|
||||
|
||||
void engageImpl( std::ostream& stream );
|
||||
|
||||
};
|
||||
|
||||
virtual ~ColourImpl(); // = default
|
||||
/**
|
||||
* Creates a guard object for given colour and this colour impl
|
||||
*
|
||||
* **Important:**
|
||||
* the guard starts disengaged, and has to be engaged explicitly.
|
||||
*/
|
||||
ColourGuard guardColour( Colour::Code colourCode );
|
||||
|
||||
private:
|
||||
virtual void use( Colour::Code colourCode ) const = 0;
|
||||
};
|
||||
|
||||
//! Provides ColourImpl based on global config and target compilation platform
|
||||
Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
|
||||
IStream* stream );
|
||||
|
||||
//! Checks if specific colour impl has been compiled into the binary
|
||||
bool isColourImplAvailable( ColourMode colourSelection );
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // CATCH_CONSOLE_COLOUR_HPP_INCLUDED
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -3899,7 +3766,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;
|
||||
@@ -4387,17 +4254,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:
|
||||
@@ -4449,12 +4315,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 ) {}
|
||||
@@ -4464,13 +4335,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 );
|
||||
@@ -4478,6 +4359,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 )
|
||||
@@ -4505,8 +4394,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 )
|
||||
@@ -4553,12 +4442,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;
|
||||
@@ -4571,7 +4463,7 @@ namespace Catch {
|
||||
|
||||
struct HelpColumns {
|
||||
std::string left;
|
||||
std::string right;
|
||||
StringRef descriptions;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -4731,7 +4623,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;
|
||||
|
||||
@@ -4751,8 +4643,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 ) {}
|
||||
@@ -4761,28 +4653,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;
|
||||
@@ -4805,7 +4701,7 @@ namespace Catch {
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string const& hint() const { return m_hint; }
|
||||
StringRef hint() const { return m_hint; }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
@@ -4819,13 +4715,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>
|
||||
@@ -4838,33 +4734,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;
|
||||
};
|
||||
@@ -4887,7 +4787,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);
|
||||
@@ -4912,16 +4812,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;
|
||||
@@ -4939,21 +4851,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; }
|
||||
};
|
||||
|
||||
|
||||
@@ -6997,6 +6911,7 @@ namespace Catch {
|
||||
};
|
||||
|
||||
class ITestInvoker;
|
||||
struct NameAndTags;
|
||||
|
||||
enum class TestCaseProperties : uint8_t {
|
||||
None = 0,
|
||||
@@ -7233,7 +7148,7 @@ namespace Catch {
|
||||
|
||||
#define CATCH_VERSION_MAJOR 3
|
||||
#define CATCH_VERSION_MINOR 5
|
||||
#define CATCH_VERSION_PATCH 0
|
||||
#define CATCH_VERSION_PATCH 2
|
||||
|
||||
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
|
||||
|
||||
@@ -7391,12 +7306,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,
|
||||
@@ -8133,12 +8042,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;
|
||||
@@ -8151,11 +8060,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) {
|
||||
@@ -8179,8 +8087,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 );
|
||||
}
|
||||
@@ -8205,7 +8112,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
|
||||
@@ -9065,6 +8972,141 @@ namespace Catch {
|
||||
#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
|
||||
|
||||
|
||||
#ifndef CATCH_CONSOLE_COLOUR_HPP_INCLUDED
|
||||
#define CATCH_CONSOLE_COLOUR_HPP_INCLUDED
|
||||
|
||||
|
||||
#include <iosfwd>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
enum class ColourMode : std::uint8_t;
|
||||
class IStream;
|
||||
|
||||
struct Colour {
|
||||
enum Code {
|
||||
None = 0,
|
||||
|
||||
White,
|
||||
Red,
|
||||
Green,
|
||||
Blue,
|
||||
Cyan,
|
||||
Yellow,
|
||||
Grey,
|
||||
|
||||
Bright = 0x10,
|
||||
|
||||
BrightRed = Bright | Red,
|
||||
BrightGreen = Bright | Green,
|
||||
LightGrey = Bright | Grey,
|
||||
BrightWhite = Bright | White,
|
||||
BrightYellow = Bright | Yellow,
|
||||
|
||||
// By intention
|
||||
FileName = LightGrey,
|
||||
Warning = BrightYellow,
|
||||
ResultError = BrightRed,
|
||||
ResultSuccess = BrightGreen,
|
||||
ResultExpectedFailure = Warning,
|
||||
|
||||
Error = BrightRed,
|
||||
Success = Green,
|
||||
Skip = LightGrey,
|
||||
|
||||
OriginalExpression = Cyan,
|
||||
ReconstructedExpression = BrightYellow,
|
||||
|
||||
SecondaryText = LightGrey,
|
||||
Headers = White
|
||||
};
|
||||
};
|
||||
|
||||
class ColourImpl {
|
||||
protected:
|
||||
//! The associated stream of this ColourImpl instance
|
||||
IStream* m_stream;
|
||||
public:
|
||||
ColourImpl( IStream* stream ): m_stream( stream ) {}
|
||||
|
||||
//! RAII wrapper around writing specific colour of text using specific
|
||||
//! colour impl into a stream.
|
||||
class ColourGuard {
|
||||
ColourImpl const* m_colourImpl;
|
||||
Colour::Code m_code;
|
||||
bool m_engaged = false;
|
||||
|
||||
public:
|
||||
//! Does **not** engage the guard/start the colour
|
||||
ColourGuard( Colour::Code code,
|
||||
ColourImpl const* colour );
|
||||
|
||||
ColourGuard( ColourGuard const& rhs ) = delete;
|
||||
ColourGuard& operator=( ColourGuard const& rhs ) = delete;
|
||||
|
||||
ColourGuard( ColourGuard&& rhs ) noexcept;
|
||||
ColourGuard& operator=( ColourGuard&& rhs ) noexcept;
|
||||
|
||||
//! Removes colour _if_ the guard was engaged
|
||||
~ColourGuard();
|
||||
|
||||
/**
|
||||
* Explicitly engages colour for given stream.
|
||||
*
|
||||
* The API based on operator<< should be preferred.
|
||||
*/
|
||||
ColourGuard& engage( std::ostream& stream ) &;
|
||||
/**
|
||||
* Explicitly engages colour for given stream.
|
||||
*
|
||||
* The API based on operator<< should be preferred.
|
||||
*/
|
||||
ColourGuard&& engage( std::ostream& stream ) &&;
|
||||
|
||||
private:
|
||||
//! Engages the guard and starts using colour
|
||||
friend std::ostream& operator<<( std::ostream& lhs,
|
||||
ColourGuard& guard ) {
|
||||
guard.engageImpl( lhs );
|
||||
return lhs;
|
||||
}
|
||||
//! Engages the guard and starts using colour
|
||||
friend std::ostream& operator<<( std::ostream& lhs,
|
||||
ColourGuard&& guard) {
|
||||
guard.engageImpl( lhs );
|
||||
return lhs;
|
||||
}
|
||||
|
||||
void engageImpl( std::ostream& stream );
|
||||
|
||||
};
|
||||
|
||||
virtual ~ColourImpl(); // = default
|
||||
/**
|
||||
* Creates a guard object for given colour and this colour impl
|
||||
*
|
||||
* **Important:**
|
||||
* the guard starts disengaged, and has to be engaged explicitly.
|
||||
*/
|
||||
ColourGuard guardColour( Colour::Code colourCode );
|
||||
|
||||
private:
|
||||
virtual void use( Colour::Code colourCode ) const = 0;
|
||||
};
|
||||
|
||||
//! Provides ColourImpl based on global config and target compilation platform
|
||||
Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
|
||||
IStream* stream );
|
||||
|
||||
//! Checks if specific colour impl has been compiled into the binary
|
||||
bool isColourImplAvailable( ColourMode colourSelection );
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // CATCH_CONSOLE_COLOUR_HPP_INCLUDED
|
||||
|
||||
|
||||
#ifndef CATCH_CONSOLE_WIDTH_HPP_INCLUDED
|
||||
#define CATCH_CONSOLE_WIDTH_HPP_INCLUDED
|
||||
|
||||
@@ -9340,7 +9382,6 @@ namespace Catch {
|
||||
#ifndef CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
|
||||
#define CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
|
||||
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace Catch {
|
||||
@@ -10421,7 +10462,7 @@ namespace Catch {
|
||||
#ifndef CATCH_SHARDING_HPP_INCLUDED
|
||||
#define CATCH_SHARDING_HPP_INCLUDED
|
||||
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -10662,8 +10703,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;
|
||||
@@ -10769,6 +10808,7 @@ namespace Catch {
|
||||
#ifndef CATCH_TEXTFLOW_HPP_INCLUDED
|
||||
#define CATCH_TEXTFLOW_HPP_INCLUDED
|
||||
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -10797,7 +10837,7 @@ namespace Catch {
|
||||
|
||||
public:
|
||||
/**
|
||||
* Iterates "lines" in `Column` and return sthem
|
||||
* Iterates "lines" in `Column` and returns them
|
||||
*/
|
||||
class const_iterator {
|
||||
friend Column;
|
||||
@@ -10851,20 +10891,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 ); }
|
||||
@@ -10873,7 +10928,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
|
||||
@@ -10917,8 +10973,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 );
|
||||
@@ -13312,8 +13370,6 @@ namespace Catch {
|
||||
public:
|
||||
JunitReporter(ReporterConfig&& _config);
|
||||
|
||||
~JunitReporter() override = default;
|
||||
|
||||
static std::string getDescription();
|
||||
|
||||
void testRunStarting(TestRunInfo const& runInfo) override;
|
||||
@@ -13554,8 +13610,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;
|
||||
@@ -13602,7 +13656,6 @@ namespace Catch {
|
||||
StreamingReporterBase( CATCH_MOVE(config) ) {
|
||||
m_preferences.shouldReportAllAssertions = true;
|
||||
}
|
||||
~TAPReporter() override = default;
|
||||
|
||||
static std::string getDescription() {
|
||||
using namespace std::string_literals;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
project(
|
||||
'catch2',
|
||||
'cpp',
|
||||
version: '3.5.0', # CML version placeholder, don't delete
|
||||
version: '3.5.2', # CML version placeholder, don't delete
|
||||
license: 'BSL-1.0',
|
||||
meson_version: '>=0.54.1',
|
||||
)
|
||||
|
@@ -348,7 +348,9 @@ 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)
|
||||
@@ -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
|
||||
|
@@ -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() );
|
||||
|
@@ -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;
|
||||
|
@@ -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>
|
||||
|
@@ -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,
|
||||
|
@@ -36,7 +36,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Version const& libraryVersion() {
|
||||
static Version version( 3, 5, 0, "", 0 );
|
||||
static Version version( 3, 5, 2, "", 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 2
|
||||
|
||||
#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>
|
||||
@@ -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" )
|
||||
|
@@ -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; }
|
||||
};
|
||||
|
@@ -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 {
|
||||
|
@@ -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>
|
||||
|
||||
|
@@ -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>
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
|
@@ -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';
|
||||
|
||||
|
@@ -19,8 +19,6 @@ namespace Catch {
|
||||
public:
|
||||
JunitReporter(ReporterConfig&& _config);
|
||||
|
||||
~JunitReporter() override = default;
|
||||
|
||||
static std::string getDescription();
|
||||
|
||||
void testRunStarting(TestRunInfo const& runInfo) 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;
|
||||
|
@@ -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;
|
||||
|
@@ -123,6 +123,12 @@ TEST_CASE( "count_equidistant_floats",
|
||||
CHECK( count_floats_with_scaled_ulp( 1., 1.5 ) == 1ull << 51 );
|
||||
CHECK( count_floats_with_scaled_ulp( 1.25, 1.5 ) == 1ull << 50 );
|
||||
CHECK( count_floats_with_scaled_ulp( 1.f, 1.5f ) == 1 << 22 );
|
||||
CHECK( count_floats_with_scaled_ulp( -std::numeric_limits<float>::max(),
|
||||
std::numeric_limits<float>::max() ) ==
|
||||
33554430 ); // (1 << 25) - 2 due to not including infinities
|
||||
CHECK( count_floats_with_scaled_ulp( -std::numeric_limits<double>::max(),
|
||||
std::numeric_limits<double>::max() ) ==
|
||||
18014398509481982 ); // (1 << 54) - 2 due to not including infinities
|
||||
|
||||
STATIC_REQUIRE( std::is_same<std::uint64_t,
|
||||
decltype( count_floats_with_scaled_ulp(
|
||||
|
Reference in New Issue
Block a user