mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-22 20:45:39 +02:00
Compare commits
48 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7cbd0b587a | ||
![]() |
2f15ccd4d3 | ||
![]() |
8f3fc15b73 | ||
![]() |
e13d9cab02 | ||
![]() |
414e2fa946 | ||
![]() |
b5ef68b044 | ||
![]() |
681f5daa13 | ||
![]() |
3b6fda3c1b | ||
![]() |
1b2fa601c6 | ||
![]() |
39bfc6e82b | ||
![]() |
ba6d33fb8c | ||
![]() |
4be81d3588 | ||
![]() |
5201e92564 | ||
![]() |
5e484862f2 | ||
![]() |
5713381d06 | ||
![]() |
1ab6be30a2 | ||
![]() |
126850e76b | ||
![]() |
5e8df1c384 | ||
![]() |
44dbda9f01 | ||
![]() |
ca2455e6e6 | ||
![]() |
42213d4c31 | ||
![]() |
62dae592c3 | ||
![]() |
9a5705411a | ||
![]() |
a1aefce6e4 | ||
![]() |
d5959907f5 | ||
![]() |
31e6499e64 | ||
![]() |
b0f4f16ee0 | ||
![]() |
1e3ddbb496 | ||
![]() |
15ad95c8db | ||
![]() |
00a10d5a5e | ||
![]() |
0d687a15d3 | ||
![]() |
bdf431c400 | ||
![]() |
a0359980f0 | ||
![]() |
8d4074aad9 | ||
![]() |
f0f40a0dbf | ||
![]() |
fa4fd7f296 | ||
![]() |
07c84adfba | ||
![]() |
8d854c689b | ||
![]() |
f0909dfe02 | ||
![]() |
de36b2ada6 | ||
![]() |
9700ee4fc0 | ||
![]() |
bbda8cd77c | ||
![]() |
4575594bbf | ||
![]() |
c053dca26e | ||
![]() |
3d7104c124 | ||
![]() |
6441c20a2c | ||
![]() |
5774c4f9c2 | ||
![]() |
2bc33dd04d |
13
.gitattributes
vendored
13
.gitattributes
vendored
@@ -8,4 +8,15 @@
|
||||
*.hpp text
|
||||
|
||||
# Windows specific files should retain windows line-endings
|
||||
*.sln text eol=crlf
|
||||
*.sln text eol=crlf
|
||||
|
||||
# Keep executable scripts with LFs so they can be run after being
|
||||
# checked out on Windows
|
||||
*.py text eol=lf
|
||||
|
||||
|
||||
# Keep the single include header with LFs to make sure it is uploaded,
|
||||
# hashed etc with LF
|
||||
single_include/*.hpp eol=lf
|
||||
# Also keep the LICENCE file with LFs for the same reason
|
||||
LICENCE.txt eol=lf
|
||||
|
@@ -204,7 +204,7 @@ before_script:
|
||||
|
||||
- |
|
||||
# Use Debug builds for running Valgrind and building examples
|
||||
cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DUSE_VALGRIND=${VALGRIND} -DBUILD_EXAMPLES=ON -DENABLE_COVERAGE=ON
|
||||
cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=ON -DCATCH_ENABLE_COVERAGE=ON
|
||||
# Don't bother with release build for coverage build
|
||||
cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
|
||||
|
||||
|
100
CMakeLists.txt
100
CMakeLists.txt
@@ -1,10 +1,19 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(CatchSelfTest)
|
||||
# detect if Catch is being bundled,
|
||||
# disable testsuite in that case
|
||||
if(NOT DEFINED PROJECT_NAME)
|
||||
set(NOT_SUBPROJECT ON)
|
||||
endif()
|
||||
|
||||
option(USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
|
||||
option(BUILD_EXAMPLES "Build documentation examples" OFF)
|
||||
option(ENABLE_COVERAGE "Generate coverage for codecov.io" OFF)
|
||||
project(Catch2 LANGUAGES CXX VERSION 2.1.2)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
option(CATCH_USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
|
||||
option(CATCH_BUILD_EXAMPLES "Build documentation examples" OFF)
|
||||
option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io" OFF)
|
||||
option(CATCH_ENABLE_WERROR "Enable all warnings as errors" ON)
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
@@ -13,7 +22,6 @@ set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
|
||||
set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark)
|
||||
set(HEADER_DIR ${CATCH_DIR}/include)
|
||||
set(CATCH_VERSION_NUMBER 2.1.0)
|
||||
|
||||
if(USE_WMAIN)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wmainCRTStartup")
|
||||
@@ -179,6 +187,7 @@ set(INTERNAL_HEADERS
|
||||
${HEADER_DIR}/internal/catch_timer.h
|
||||
${HEADER_DIR}/internal/catch_tostring.h
|
||||
${HEADER_DIR}/internal/catch_totals.h
|
||||
${HEADER_DIR}/internal/catch_uncaught_exceptions.h
|
||||
${HEADER_DIR}/internal/catch_user_interfaces.h
|
||||
${HEADER_DIR}/internal/catch_version.h
|
||||
${HEADER_DIR}/internal/catch_wildcard_pattern.h
|
||||
@@ -239,6 +248,7 @@ set(IMPL_SOURCES
|
||||
${HEADER_DIR}/internal/catch_timer.cpp
|
||||
${HEADER_DIR}/internal/catch_tostring.cpp
|
||||
${HEADER_DIR}/internal/catch_totals.cpp
|
||||
${HEADER_DIR}/internal/catch_uncaught_exceptions.cpp
|
||||
${HEADER_DIR}/internal/catch_version.cpp
|
||||
${HEADER_DIR}/internal/catch_wildcard_pattern.cpp
|
||||
${HEADER_DIR}/internal/catch_xmlwriter.cpp
|
||||
@@ -284,7 +294,19 @@ SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
|
||||
|
||||
# Projects consuming Catch via ExternalProject_Add might want to use install step
|
||||
# without building all of our selftests.
|
||||
if (NOT NO_SELFTEST)
|
||||
|
||||
if(DEFINED NO_SELFTEST)
|
||||
message(DEPRECATION "*** CMake option NO_SELFTEST is deprecated; use BUILD_TESTING instead")
|
||||
if (NO_SELFTEST)
|
||||
set(BUILD_TESTING OFF CACHE BOOL "Disable Catch2 internal testsuite" FORCE)
|
||||
else()
|
||||
set(BUILD_TESTING ON CACHE BOOL "Disable Catch2 internal testsuite" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CTest)
|
||||
|
||||
if (BUILD_TESTING AND NOT_SUBPROJECT)
|
||||
add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS})
|
||||
target_include_directories(SelfTest PRIVATE ${HEADER_DIR})
|
||||
|
||||
@@ -299,7 +321,8 @@ if (NOT NO_SELFTEST)
|
||||
set_property(TARGET SelfTest PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
set_property(TARGET SelfTest PROPERTY CXX_EXTENSIONS OFF)
|
||||
|
||||
if (ENABLE_COVERAGE)
|
||||
if (CATCH_ENABLE_COVERAGE)
|
||||
set(ENABLE_COVERAGE ON CACHE BOOL "Enable coverage build." FORCE)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
||||
find_package(codecov)
|
||||
add_coverage(SelfTest)
|
||||
@@ -307,18 +330,25 @@ if (NOT NO_SELFTEST)
|
||||
coverage_evaluate()
|
||||
endif()
|
||||
|
||||
# Add desired warnings
|
||||
# Add per compiler options
|
||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
|
||||
target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code -Werror )
|
||||
target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code -Wpedantic)
|
||||
if (CATCH_ENABLE_WERROR)
|
||||
target_compile_options( SelfTest PRIVATE -Werror)
|
||||
endif()
|
||||
endif()
|
||||
# Clang specific warning go here
|
||||
# Clang specific options go here
|
||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
||||
# Actually keep these
|
||||
target_compile_options( SelfTest PRIVATE -Wweak-vtables -Wexit-time-destructors -Wglobal-constructors -Wmissing-noreturn )
|
||||
endif()
|
||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
|
||||
STRING(REGEX REPLACE "/W[0-9]" "/W4" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) # override default warning level
|
||||
target_compile_options( SelfTest PRIVATE /w44265 /WX /w44061 /w44062 )
|
||||
target_compile_options( SelfTest PRIVATE /w44265 /w44061 /w44062 )
|
||||
if (CATCH_ENABLE_WERROR)
|
||||
target_compile_options( SelfTest PRIVATE /WX)
|
||||
endif()
|
||||
# Force MSVC to consider everything as encoded in utf-8
|
||||
target_compile_options( SelfTest PRIVATE /utf-8 )
|
||||
endif()
|
||||
|
||||
|
||||
@@ -344,7 +374,7 @@ if (NOT NO_SELFTEST)
|
||||
add_test(NAME ApprovalTests COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
|
||||
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
|
||||
|
||||
if (USE_VALGRIND)
|
||||
if (CATCH_USE_VALGRIND)
|
||||
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
|
||||
add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
|
||||
set_tests_properties(ValgrindListTests PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
|
||||
@@ -355,18 +385,20 @@ if (NOT NO_SELFTEST)
|
||||
endif() # !NO_SELFTEST
|
||||
|
||||
|
||||
if(BUILD_EXAMPLES)
|
||||
if(CATCH_BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
install(DIRECTORY "single_include/" DESTINATION "include/catch")
|
||||
install(DIRECTORY "single_include/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/catch")
|
||||
|
||||
install(DIRECTORY docs/ DESTINATION "${CMAKE_INSTALL_DOCDIR}")
|
||||
|
||||
## Provide some pkg-config integration
|
||||
# Don't bother on Windows
|
||||
if(NOT WIN32 OR NOT CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
|
||||
|
||||
set(PKGCONFIG_INSTALL_DIR
|
||||
"${CMAKE_INSTALL_PREFIX}/share/pkgconfig"
|
||||
"${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig"
|
||||
CACHE PATH "Path where catch.pc is installed"
|
||||
)
|
||||
|
||||
@@ -374,3 +406,37 @@ if(NOT WIN32 OR NOT CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/catch.pc DESTINATION ${PKGCONFIG_INSTALL_DIR})
|
||||
|
||||
endif()
|
||||
|
||||
# add catch as a 'linkable' target
|
||||
add_library(Catch INTERFACE)
|
||||
|
||||
# depend on some obvious c++11 features so the dependency is transitively added dependants
|
||||
target_compile_features(Catch INTERFACE cxx_auto_type cxx_constexpr cxx_noexcept)
|
||||
|
||||
target_include_directories(Catch
|
||||
INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/single_include>
|
||||
$<INSTALL_INTERFACE:include/catch>
|
||||
$<INSTALL_INTERFACE:include>)
|
||||
|
||||
# provide a namespaced alias for clients to 'link' against if catch is included as a sub-project
|
||||
add_library(Catch2::Catch ALIAS Catch)
|
||||
|
||||
set(CATCH_CMAKE_CONFIG_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Catch2")
|
||||
|
||||
# create and install an export set for catch target as Catch2::Catch
|
||||
install(TARGETS Catch EXPORT Catch2Config DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
install(EXPORT Catch2Config
|
||||
NAMESPACE Catch2::
|
||||
DESTINATION ${CATCH_CMAKE_CONFIG_DESTINATION})
|
||||
|
||||
# install Catch2ConfigVersion.cmake file to handle versions in find_package
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
write_basic_package_version_file(Catch2ConfigVersion.cmake
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
|
||||
install(FILES
|
||||
"${CMAKE_BINARY_DIR}/Catch2ConfigVersion.cmake"
|
||||
DESTINATION ${CATCH_CMAKE_CONFIG_DESTINATION})
|
||||
|
@@ -5,9 +5,9 @@
|
||||
[](https://travis-ci.org/catchorg/Catch2)
|
||||
[](https://ci.appveyor.com/project/catchorg/catch2)
|
||||
[](https://codecov.io/gh/catchorg/Catch2)
|
||||
[](https://wandbox.org/permlink/nerce2MiN6sVmfCi)
|
||||
[](https://wandbox.org/permlink/6O2wo5BOvVeUeKQe)
|
||||
|
||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.0.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.1.2/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||
|
||||
## Catch2 is released!
|
||||
|
||||
|
@@ -54,7 +54,7 @@ before_build:
|
||||
|
||||
# build with MSBuild
|
||||
build:
|
||||
project: Build\CatchSelfTest.sln # path to Visual Studio solution or project
|
||||
project: Build\Catch2.sln # path to Visual Studio solution or project
|
||||
parallel: true # enable MSBuild parallel builds
|
||||
verbosity: normal # MSBuild verbosity level {quiet|minimal|normal|detailed}
|
||||
|
||||
|
@@ -1,9 +1,6 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||
|
||||
Name: Catch
|
||||
Description: Testing library for C++
|
||||
Requires:
|
||||
Version: @CATCH_VERSION_NUMBER@
|
||||
Libs:
|
||||
Cflags: -I${prefix}/@INCLUDE_INSTALL_DIR@/include
|
||||
Version: @Catch2_VERSION@
|
||||
Cflags: -I${includedir}
|
||||
|
12
codecov.yml
12
codecov.yml
@@ -1,6 +1,18 @@
|
||||
coverage:
|
||||
precision: 2
|
||||
round: nearest
|
||||
range: "60...90"
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
threshold: 2%
|
||||
|
||||
codecov:
|
||||
branch: master
|
||||
|
||||
comment:
|
||||
layout: "diff"
|
||||
|
||||
coverage:
|
||||
ignore:
|
||||
- "projects/SelfTest"
|
||||
|
@@ -4,7 +4,7 @@ from conans import ConanFile
|
||||
|
||||
class CatchConan(ConanFile):
|
||||
name = "Catch"
|
||||
version = "2.1.0"
|
||||
version = "2.1.2"
|
||||
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
|
||||
author = "philsquared"
|
||||
generators = "cmake"
|
||||
|
175
contrib/Catch.cmake
Normal file
175
contrib/Catch.cmake
Normal file
@@ -0,0 +1,175 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
Catch
|
||||
-----
|
||||
|
||||
This module defines a function to help use the Catch test framework.
|
||||
|
||||
The :command:`catch_discover_tests` discovers tests by asking the compiled test
|
||||
executable to enumerate its tests. This does not require CMake to be re-run
|
||||
when tests change. However, it may not work in a cross-compiling environment,
|
||||
and setting test properties is less convenient.
|
||||
|
||||
This command is intended to replace use of :command:`add_test` to register
|
||||
tests, and will create a separate CTest test for each Catch test case. Note
|
||||
that this is in some cases less efficient, as common set-up and tear-down logic
|
||||
cannot be shared by multiple test cases executing in the same instance.
|
||||
However, it provides more fine-grained pass/fail information to CTest, which is
|
||||
usually considered as more beneficial. By default, the CTest test name is the
|
||||
same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
|
||||
|
||||
.. command:: catch_discover_tests
|
||||
|
||||
Automatically add tests with CTest by querying the compiled test executable
|
||||
for available tests::
|
||||
|
||||
catch_discover_tests(target
|
||||
[TEST_SPEC arg1...]
|
||||
[EXTRA_ARGS arg1...]
|
||||
[WORKING_DIRECTORY dir]
|
||||
[TEST_PREFIX prefix]
|
||||
[TEST_SUFFIX suffix]
|
||||
[PROPERTIES name1 value1...]
|
||||
[TEST_LIST var]
|
||||
)
|
||||
|
||||
``catch_discover_tests`` sets up a post-build command on the test executable
|
||||
that generates the list of tests by parsing the output from running the test
|
||||
with the ``--list-test-names-only`` argument. This ensures that the full
|
||||
list of tests is obtained. Since test discovery occurs at build time, it is
|
||||
not necessary to re-run CMake when the list of tests changes.
|
||||
However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set
|
||||
in order to function in a cross-compiling environment.
|
||||
|
||||
Additionally, setting properties on tests is somewhat less convenient, since
|
||||
the tests are not available at CMake time. Additional test properties may be
|
||||
assigned to the set of tests as a whole using the ``PROPERTIES`` option. If
|
||||
more fine-grained test control is needed, custom content may be provided
|
||||
through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES`
|
||||
directory property. The set of discovered tests is made accessible to such a
|
||||
script via the ``<target>_TESTS`` variable.
|
||||
|
||||
The options are:
|
||||
|
||||
``target``
|
||||
Specifies the Catch executable, which must be a known CMake executable
|
||||
target. CMake will substitute the location of the built executable when
|
||||
running the test.
|
||||
|
||||
``TEST_SPEC arg1...``
|
||||
Specifies test cases, wildcarded test cases, tags and tag expressions to
|
||||
pass to the Catch executable with the ``--list-test-names-only`` argument.
|
||||
|
||||
``EXTRA_ARGS arg1...``
|
||||
Any extra arguments to pass on the command line to each test case.
|
||||
|
||||
``WORKING_DIRECTORY dir``
|
||||
Specifies the directory in which to run the discovered test cases. If this
|
||||
option is not provided, the current binary directory is used.
|
||||
|
||||
``TEST_PREFIX prefix``
|
||||
Specifies a ``prefix`` to be prepended to the name of each discovered test
|
||||
case. This can be useful when the same test executable is being used in
|
||||
multiple calls to ``catch_discover_tests()`` but with different
|
||||
``TEST_SPEC`` or ``EXTRA_ARGS``.
|
||||
|
||||
``TEST_SUFFIX suffix``
|
||||
Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of
|
||||
every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may
|
||||
be specified.
|
||||
|
||||
``PROPERTIES name1 value1...``
|
||||
Specifies additional properties to be set on all tests discovered by this
|
||||
invocation of ``catch_discover_tests``.
|
||||
|
||||
``TEST_LIST var``
|
||||
Make the list of tests available in the variable ``var``, rather than the
|
||||
default ``<target>_TESTS``. This can be useful when the same test
|
||||
executable is being used in multiple calls to ``catch_discover_tests()``.
|
||||
Note that this variable is only available in CTest.
|
||||
|
||||
#]=======================================================================]
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
function(catch_discover_tests TARGET)
|
||||
cmake_parse_arguments(
|
||||
""
|
||||
""
|
||||
"TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST"
|
||||
"TEST_SPEC;EXTRA_ARGS;PROPERTIES"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
if(NOT _WORKING_DIRECTORY)
|
||||
set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
if(NOT _TEST_LIST)
|
||||
set(_TEST_LIST ${TARGET}_TESTS)
|
||||
endif()
|
||||
|
||||
## Generate a unique name based on the extra arguments
|
||||
string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS}")
|
||||
string(SUBSTRING ${args_hash} 0 7 args_hash)
|
||||
|
||||
# Define rule to generate test list for aforementioned test executable
|
||||
set(ctest_include_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_include-${args_hash}.cmake")
|
||||
set(ctest_tests_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_tests-${args_hash}.cmake")
|
||||
get_property(crosscompiling_emulator
|
||||
TARGET ${TARGET}
|
||||
PROPERTY CROSSCOMPILING_EMULATOR
|
||||
)
|
||||
add_custom_command(
|
||||
TARGET ${TARGET} POST_BUILD
|
||||
BYPRODUCTS "${ctest_tests_file}"
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-D "TEST_TARGET=${TARGET}"
|
||||
-D "TEST_EXECUTABLE=$<TARGET_FILE:${TARGET}>"
|
||||
-D "TEST_EXECUTOR=${crosscompiling_emulator}"
|
||||
-D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}"
|
||||
-D "TEST_SPEC=${_TEST_SPEC}"
|
||||
-D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}"
|
||||
-D "TEST_PROPERTIES=${_PROPERTIES}"
|
||||
-D "TEST_PREFIX=${_TEST_PREFIX}"
|
||||
-D "TEST_SUFFIX=${_TEST_SUFFIX}"
|
||||
-D "TEST_LIST=${_TEST_LIST}"
|
||||
-D "CTEST_FILE=${ctest_tests_file}"
|
||||
-P "${_CATCH_DISCOVER_TESTS_SCRIPT}"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
file(WRITE "${ctest_include_file}"
|
||||
"if(EXISTS \"${ctest_tests_file}\")\n"
|
||||
" include(\"${ctest_tests_file}\")\n"
|
||||
"else()\n"
|
||||
" add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n"
|
||||
"endif()\n"
|
||||
)
|
||||
|
||||
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0")
|
||||
# Add discovered tests to directory TEST_INCLUDE_FILES
|
||||
set_property(DIRECTORY
|
||||
APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}"
|
||||
)
|
||||
else()
|
||||
# Add discovered tests as directory TEST_INCLUDE_FILE if possible
|
||||
get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET)
|
||||
if (NOT ${test_include_file_set})
|
||||
set_property(DIRECTORY
|
||||
PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}"
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR
|
||||
"Cannot set more than one TEST_INCLUDE_FILE"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endfunction()
|
||||
|
||||
###############################################################################
|
||||
|
||||
set(_CATCH_DISCOVER_TESTS_SCRIPT
|
||||
${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake
|
||||
)
|
77
contrib/CatchAddTests.cmake
Normal file
77
contrib/CatchAddTests.cmake
Normal file
@@ -0,0 +1,77 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
set(prefix "${TEST_PREFIX}")
|
||||
set(suffix "${TEST_SUFFIX}")
|
||||
set(spec ${TEST_SPEC})
|
||||
set(extra_args ${TEST_EXTRA_ARGS})
|
||||
set(properties ${TEST_PROPERTIES})
|
||||
set(script)
|
||||
set(suite)
|
||||
set(tests)
|
||||
|
||||
function(add_command NAME)
|
||||
set(_args "")
|
||||
foreach(_arg ${ARGN})
|
||||
if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
|
||||
set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument
|
||||
else()
|
||||
set(_args "${_args} ${_arg}")
|
||||
endif()
|
||||
endforeach()
|
||||
set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Run test executable to get list of available tests
|
||||
if(NOT EXISTS "${TEST_EXECUTABLE}")
|
||||
message(FATAL_ERROR
|
||||
"Specified test executable '${TEST_EXECUTABLE}' does not exist"
|
||||
)
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-names-only
|
||||
OUTPUT_VARIABLE output
|
||||
RESULT_VARIABLE result
|
||||
)
|
||||
# Catch --list-test-names-only reports the number of tests, so 0 is... surprising
|
||||
if(${result} EQUAL 0)
|
||||
message(WARNING
|
||||
"Test executable '${TEST_EXECUTABLE}' contains no tests!\n"
|
||||
)
|
||||
elseif(${result} LESS 0)
|
||||
message(FATAL_ERROR
|
||||
"Error running test executable '${TEST_EXECUTABLE}':\n"
|
||||
" Result: ${result}\n"
|
||||
" Output: ${output}\n"
|
||||
)
|
||||
endif()
|
||||
|
||||
string(REPLACE "\n" ";" output "${output}")
|
||||
|
||||
# Parse output
|
||||
foreach(line ${output})
|
||||
# Test name; strip spaces to get just the name...
|
||||
string(REGEX REPLACE " +" "" test "${line}")
|
||||
# ...and add to script
|
||||
add_command(add_test
|
||||
"${prefix}${test}${suffix}"
|
||||
${TEST_EXECUTOR}
|
||||
"${TEST_EXECUTABLE}"
|
||||
"${test}"
|
||||
${extra_args}
|
||||
)
|
||||
add_command(set_tests_properties
|
||||
"${prefix}${test}${suffix}"
|
||||
PROPERTIES
|
||||
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
|
||||
${properties}
|
||||
)
|
||||
list(APPEND tests "${prefix}${test}${suffix}")
|
||||
endforeach()
|
||||
|
||||
# Create a list of all discovered tests, which users may use to e.g. set
|
||||
# properties on the tests
|
||||
add_command(set ${TEST_LIST} ${tests})
|
||||
|
||||
# Write CTest script
|
||||
file(WRITE "${CTEST_FILE}" "${script}")
|
@@ -28,9 +28,14 @@ The advantage of this format is that the JUnit Ant schema is widely understood b
|
||||
The disadvantage is that this schema was designed to correspond to how JUnit works - and there is a significant mismatch with how Catch works. Additionally the format is not streamable (because opening elements hold counts of failed and passing tests as attributes) - so the whole test run must complete before it can be written.
|
||||
|
||||
## Other reporters
|
||||
Other reporters are not part of the single-header distribution and need to be downloaded and included separately. All reporters are stored in `include/reporters` directory in the git repository, and are named `catch_reporter_*.hpp`. For example, to use the TeamCity reporter you need to download `include/reporters/catch_reporter_teamcity.hpp` and include it after Catch itself.
|
||||
Other reporters are not part of the single-header distribution and need
|
||||
to be downloaded and included separately. All reporters are stored in
|
||||
`single_include` directory in the git repository, and are named
|
||||
`catch_reporter_*.hpp`. For example, to use the TeamCity reporter you
|
||||
need to download `single_include/catch_reporter_teamcity.hpp` and include
|
||||
it after Catch itself.
|
||||
|
||||
```
|
||||
```cpp
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
#include "catch_reporter_teamcity.hpp"
|
||||
@@ -124,7 +129,15 @@ The advantage of this approach is that you can always automatically update Catch
|
||||
|
||||
|
||||
### Automatic test registration
|
||||
If you are also using ctest, `contrib/ParseAndAddCatchTests.cmake` is a CMake script that attempts to parse your test files and automatically register all test cases, using tags as labels. This means that these
|
||||
We provide 2 CMake scripts that can automatically register Catch-based
|
||||
tests with CTest,
|
||||
* `contrib/ParseAndAddCatchTests.cmake`
|
||||
* `contrib/CatchAddTests.cmake`
|
||||
|
||||
The first is based on parsing the test implementation files, and attempts
|
||||
to register all `TEST_CASE`s using their tags as labels. This means that
|
||||
these:
|
||||
|
||||
```cpp
|
||||
TEST_CASE("Test1", "[unit]") {
|
||||
int a = 1;
|
||||
@@ -144,7 +157,14 @@ TEST_CASE("Test3", "[a][b][c]") {
|
||||
REQUIRE(a == b);
|
||||
}
|
||||
```
|
||||
would be registered as 3 tests, `Test1`, `Test2` and `Test3`, and 4 ctest labels would be created, `a`, `b`, `c` and `unit`.
|
||||
would be registered as 3 tests, `Test1`, `Test2` and `Test3`,
|
||||
and 4 CTest labels would be created, `a`, `b`, `c` and `unit`.
|
||||
|
||||
|
||||
The second is based on parsing the output of a Catch binary given
|
||||
`--list-test-names-only`. This means that it deals with inactive
|
||||
(e.g. commented-out) tests better, but requires CMake 3.10 for full
|
||||
functionality.
|
||||
|
||||
### CodeCoverage module (GCOV, LCOV...)
|
||||
|
||||
|
@@ -35,6 +35,9 @@ The next-generation core storage and query engine for Couchbase Lite
|
||||
### [DtCraft](https://github.com/twhuang-uiuc/DtCraft)
|
||||
A High-performance Cluster Computing Engine
|
||||
|
||||
### [forest](https://github.com/xorz57/forest)
|
||||
Forest is an open-source, template library of tree data structures written in C++11.
|
||||
|
||||
### [Fuxedo](https://github.com/fuxedo/fuxedo)
|
||||
Open source Oracle Tuxedo-like XATMI middleware for C and C++.
|
||||
|
||||
|
@@ -81,6 +81,7 @@ int main( int argc, char* argv[] )
|
||||
int height = 0; // Some user variable you want to be able to set
|
||||
|
||||
// Build a new parser on top of Catch's
|
||||
using namespace Catch::clara;
|
||||
auto cli
|
||||
= session.cli() // Get Catch's composite command line parser
|
||||
| Opt( height, "height" ) // bind variable to a new option, with a hint string
|
||||
@@ -105,6 +106,20 @@ int main( int argc, char* argv[] )
|
||||
|
||||
See the [Clara documentation](https://github.com/philsquared/Clara/blob/master/README.md) for more details.
|
||||
|
||||
|
||||
## Version detection
|
||||
|
||||
Catch provides a triplet of macros providing the header's version,
|
||||
|
||||
* `CATCH_VERSION_MAJOR`
|
||||
* `CATCH_VERSION_MINOR`
|
||||
* `CATCH_VERSION_PATCH`
|
||||
|
||||
these macros expand into a single number, that corresponds to the appropriate
|
||||
part of the version. As an example, given single header version v2.3.4,
|
||||
the macros would expand into `2`, `3`, and `4` respectively.
|
||||
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md#top)
|
||||
|
@@ -1,5 +1,44 @@
|
||||
<a id="top"></a>
|
||||
|
||||
# 2.1.2
|
||||
|
||||
## Fixes
|
||||
* Fixed compilation error with `-fno-rtti` (#1165)
|
||||
* Fixed NoAssertion warnings
|
||||
* `operator<<` is used before range-based stringification (#1172)
|
||||
* Fixed `-Wpedantic` warnings (extra semicolons and binary literals) (#1173)
|
||||
|
||||
|
||||
## Improvements
|
||||
* Added `CATCH_VERSION_{MAJOR,MINOR,PATCH}` macros (#1131)
|
||||
* Added `BrightYellow` colour for use in reporters (#979)
|
||||
* It is also used by ConsoleReporter for reconstructed expressions
|
||||
|
||||
## Other changes
|
||||
* Catch is now exported as a CMake package and linkable target (#1170)
|
||||
|
||||
# 2.1.1
|
||||
|
||||
## Improvements
|
||||
* Static arrays are now properly stringified like ranges across MSVC/GCC/Clang
|
||||
* Embedded newer version of Clara -- v1.1.1
|
||||
* This should fix some warnings dragged in from Clara
|
||||
* MSVC's CLR exceptions are supported
|
||||
|
||||
|
||||
## Fixes
|
||||
* Fixed compilation when comparison operators do not return bool (#1147)
|
||||
* Fixed CLR exceptions blowing up the executable during translation (#1138)
|
||||
|
||||
|
||||
## Other changes
|
||||
* Many CMake changes
|
||||
* `NO_SELFTEST` option is deprecated, use `BUILD_TESTING` instead.
|
||||
* Catch specific CMake options were prefixed with `CATCH_` for namespacing purposes
|
||||
* Other changes to simplify Catch2's packaging
|
||||
|
||||
|
||||
|
||||
# 2.1.0
|
||||
|
||||
## Improvements
|
||||
|
@@ -21,10 +21,8 @@ Catch uses a variant of [semantic versioning](http://semver.org/), with breaking
|
||||
|
||||
After deciding which part of version number should be incremented, you can use one of the `*Release.py` scripts to perform the required changes to Catch.
|
||||
|
||||
|
||||
### Generate updated single-include header
|
||||
|
||||
After updating version number, regenerate single-include header using `generateSingleHeader.py`.
|
||||
This will take care of generating the single include header, updating
|
||||
version numbers everywhere and pushing the new version to Wandbox.
|
||||
|
||||
|
||||
### Release notes
|
||||
@@ -39,11 +37,19 @@ After version number is incremented, single-include header is regenerated and re
|
||||
|
||||
### Release on GitHub
|
||||
|
||||
After pushing changes to GitHub, GitHub release *needs* to be created. Tag version and release title should be same as the new version, description should contain the release notes for the current release. Single header version of `catch.hpp` *needs* to be attached as a binary, as that is where the official download link links to. Preferably it should use linux line endings.
|
||||
After pushing changes to GitHub, GitHub release *needs* to be created.
|
||||
Tag version and release title should be same as the new version,
|
||||
description should contain the release notes for the current release.
|
||||
Single header version of `catch.hpp` *needs* to be attached as a binary,
|
||||
as that is where the official download link links to. Preferably
|
||||
it should use linux line endings. All non-bundled reporters (Automake,
|
||||
TAP, TeamCity) should also be attached as binaries, as they are dependent
|
||||
on a specific version of the single-include header.
|
||||
|
||||
|
||||
## Optional steps
|
||||
|
||||
The following steps are optional, and do not have to be performed when releasing new version of Catch. However, they are *should* happen, but they can happen the next day without losing anything significant.
|
||||
The following steps are optional, and do not have to be performed when releasing new version of Catch. However, they *should* happen, but they can happen the next day without losing anything significant.
|
||||
|
||||
|
||||
### vcpkg update
|
||||
@@ -57,8 +63,3 @@ GitHub
|
||||
vcpkg
|
||||
```
|
||||
|
||||
|
||||
### Wandbox update
|
||||
|
||||
Recently we also included a link to wandbox with preloaded Catch on the main page. Strictly speaking it is unneccessary to update this after every release, Catch usually does not change that much between versions, but it should be kept up to date anyway.
|
||||
|
||||
|
@@ -33,6 +33,23 @@ namespace Catch {
|
||||
}
|
||||
```
|
||||
|
||||
## Catch::is_range<T> specialisation
|
||||
As a fallback, Catch attempts to detect if the type can be iterated
|
||||
(`begin(T)` and `end(T)` are valid) and if it can be, it is stringified
|
||||
as a range. For certain types this can lead to infinite recursion, so
|
||||
it can be disabled by specializing `Catch::is_range` like so:
|
||||
|
||||
```cpp
|
||||
namespace Catch {
|
||||
template<>
|
||||
struct is_range<T> {
|
||||
static const bool value = false;
|
||||
};
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Exceptions
|
||||
|
||||
By default all exceptions deriving from `std::exception` will be translated to strings by calling the `what()` method. For exception types that do not derive from `std::exception` - or if `what()` does not return a suitable string - use `CATCH_TRANSLATE_EXCEPTION`. This defines a function that takes your exception type, by reference, and returns a string. It can appear anywhere in the code - it doesn't have to be in the same translation unit. For example:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Build examples.
|
||||
#
|
||||
# Requires BUILD_EXAMPLES to be defined 'true', see ../CMakeLists.txt.
|
||||
# Requires CATCH_BUILD_EXAMPLES to be defined 'true', see ../CMakeLists.txt.
|
||||
#
|
||||
|
||||
cmake_minimum_required( VERSION 3.0 )
|
||||
|
@@ -9,6 +9,9 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
||||
|
||||
#define CATCH_VERSION_MAJOR 2
|
||||
#define CATCH_VERSION_MINOR 1
|
||||
#define CATCH_VERSION_PATCH 2
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang system_header
|
||||
|
106
include/external/clara.hpp
vendored
106
include/external/clara.hpp
vendored
@@ -1,5 +1,11 @@
|
||||
// v1.0-develop.2
|
||||
// See https://github.com/philsquared/Clara
|
||||
// Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See https://github.com/philsquared/Clara for more details
|
||||
|
||||
// Clara v1.1.2
|
||||
|
||||
#ifndef CATCH_CLARA_HPP_INCLUDED
|
||||
#define CATCH_CLARA_HPP_INCLUDED
|
||||
@@ -370,7 +376,7 @@ namespace detail {
|
||||
template<typename ClassT, typename ReturnT, typename ArgT>
|
||||
struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
|
||||
static const bool isValid = true;
|
||||
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;;
|
||||
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
|
||||
using ReturnType = ReturnT;
|
||||
};
|
||||
|
||||
@@ -535,7 +541,7 @@ namespace detail {
|
||||
return *this;
|
||||
}
|
||||
|
||||
~ResultValueBase() {
|
||||
~ResultValueBase() override {
|
||||
if( m_type == Ok )
|
||||
m_value.~T();
|
||||
}
|
||||
@@ -573,7 +579,7 @@ namespace detail {
|
||||
auto errorMessage() const -> std::string { return m_errorMessage; }
|
||||
|
||||
protected:
|
||||
virtual void enforceOk() const {
|
||||
void enforceOk() const override {
|
||||
// !TBD: If no exceptions, std::terminate here or something
|
||||
switch( m_type ) {
|
||||
case ResultBase::LogicError:
|
||||
@@ -653,46 +659,32 @@ namespace detail {
|
||||
return ParserResult::ok( ParseResultType::Matched );
|
||||
}
|
||||
|
||||
struct BoundRefBase {
|
||||
BoundRefBase() = default;
|
||||
BoundRefBase( BoundRefBase const & ) = delete;
|
||||
BoundRefBase( BoundRefBase && ) = delete;
|
||||
BoundRefBase &operator=( BoundRefBase const & ) = delete;
|
||||
BoundRefBase &operator=( BoundRefBase && ) = delete;
|
||||
struct NonCopyable {
|
||||
NonCopyable() = default;
|
||||
NonCopyable( NonCopyable const & ) = delete;
|
||||
NonCopyable( NonCopyable && ) = delete;
|
||||
NonCopyable &operator=( NonCopyable const & ) = delete;
|
||||
NonCopyable &operator=( NonCopyable && ) = delete;
|
||||
};
|
||||
|
||||
virtual ~BoundRefBase() = default;
|
||||
|
||||
virtual auto isFlag() const -> bool = 0;
|
||||
struct BoundRef : NonCopyable {
|
||||
virtual ~BoundRef() = default;
|
||||
virtual auto isContainer() const -> bool { return false; }
|
||||
virtual auto isFlag() const -> bool { return false; }
|
||||
};
|
||||
struct BoundValueRefBase : BoundRef {
|
||||
virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
|
||||
};
|
||||
struct BoundFlagRefBase : BoundRef {
|
||||
virtual auto setFlag( bool flag ) -> ParserResult = 0;
|
||||
};
|
||||
|
||||
struct BoundValueRefBase : BoundRefBase {
|
||||
auto isFlag() const -> bool override { return false; }
|
||||
|
||||
auto setFlag( bool ) -> ParserResult override {
|
||||
return ParserResult::logicError( "Flags can only be set on boolean fields" );
|
||||
}
|
||||
};
|
||||
|
||||
struct BoundFlagRefBase : BoundRefBase {
|
||||
auto isFlag() const -> bool override { return true; }
|
||||
|
||||
auto setValue( std::string const &arg ) -> ParserResult override {
|
||||
bool flag;
|
||||
auto result = convertInto( arg, flag );
|
||||
if( result )
|
||||
setFlag( flag );
|
||||
return result;
|
||||
}
|
||||
virtual auto isFlag() const -> bool { return true; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct BoundRef : BoundValueRefBase {
|
||||
struct BoundValueRef : BoundValueRefBase {
|
||||
T &m_ref;
|
||||
|
||||
explicit BoundRef( T &ref ) : m_ref( ref ) {}
|
||||
explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
|
||||
|
||||
auto setValue( std::string const &arg ) -> ParserResult override {
|
||||
return convertInto( arg, m_ref );
|
||||
@@ -700,10 +692,10 @@ namespace detail {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct BoundRef<std::vector<T>> : BoundValueRefBase {
|
||||
struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
|
||||
std::vector<T> &m_ref;
|
||||
|
||||
explicit BoundRef( std::vector<T> &ref ) : m_ref( ref ) {}
|
||||
explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
|
||||
|
||||
auto isContainer() const -> bool override { return true; }
|
||||
|
||||
@@ -748,12 +740,12 @@ namespace detail {
|
||||
|
||||
template<typename ArgType, typename L>
|
||||
inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
|
||||
ArgType temp;
|
||||
ArgType temp{};
|
||||
auto result = convertInto( arg, temp );
|
||||
return !result
|
||||
? result
|
||||
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template<typename L>
|
||||
@@ -803,6 +795,9 @@ namespace detail {
|
||||
public:
|
||||
template<typename T>
|
||||
auto operator|( T const &other ) const -> Parser;
|
||||
|
||||
template<typename T>
|
||||
auto operator+( T const &other ) const -> Parser;
|
||||
};
|
||||
|
||||
// Common code and state for Args and Opts
|
||||
@@ -810,16 +805,16 @@ namespace detail {
|
||||
class ParserRefImpl : public ComposableParserImpl<DerivedT> {
|
||||
protected:
|
||||
Optionality m_optionality = Optionality::Optional;
|
||||
std::shared_ptr<BoundRefBase> m_ref;
|
||||
std::shared_ptr<BoundRef> m_ref;
|
||||
std::string m_hint;
|
||||
std::string m_description;
|
||||
|
||||
explicit ParserRefImpl( std::shared_ptr<BoundRefBase> const &ref ) : m_ref( ref ) {}
|
||||
explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
ParserRefImpl( T &ref, std::string const &hint )
|
||||
: m_ref( std::make_shared<BoundRef<T>>( ref ) ),
|
||||
: m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
|
||||
m_hint( hint )
|
||||
{}
|
||||
|
||||
@@ -860,10 +855,10 @@ namespace detail {
|
||||
|
||||
class ExeName : public ComposableParserImpl<ExeName> {
|
||||
std::shared_ptr<std::string> m_name;
|
||||
std::shared_ptr<BoundRefBase> m_ref;
|
||||
std::shared_ptr<BoundValueRefBase> m_ref;
|
||||
|
||||
template<typename LambdaT>
|
||||
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundRefBase> {
|
||||
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {
|
||||
return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
|
||||
}
|
||||
|
||||
@@ -871,7 +866,7 @@ namespace detail {
|
||||
ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
|
||||
|
||||
explicit ExeName( std::string &ref ) : ExeName() {
|
||||
m_ref = std::make_shared<BoundRef<std::string>>( ref );
|
||||
m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
|
||||
}
|
||||
|
||||
template<typename LambdaT>
|
||||
@@ -914,7 +909,10 @@ namespace detail {
|
||||
if( token.type != TokenType::Argument )
|
||||
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
|
||||
|
||||
auto result = m_ref->setValue( remainingTokens->token );
|
||||
assert( !m_ref->isFlag() );
|
||||
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
|
||||
|
||||
auto result = valueRef->setValue( remainingTokens->token );
|
||||
if( !result )
|
||||
return InternalParseResult( result );
|
||||
else
|
||||
@@ -988,19 +986,21 @@ namespace detail {
|
||||
auto const &token = *remainingTokens;
|
||||
if( isMatch(token.token ) ) {
|
||||
if( m_ref->isFlag() ) {
|
||||
auto result = m_ref->setFlag( true );
|
||||
auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
|
||||
auto result = flagRef->setFlag( true );
|
||||
if( !result )
|
||||
return InternalParseResult( result );
|
||||
if( result.value() == ParseResultType::ShortCircuitAll )
|
||||
return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
|
||||
} else {
|
||||
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
|
||||
++remainingTokens;
|
||||
if( !remainingTokens )
|
||||
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
|
||||
auto const &argToken = *remainingTokens;
|
||||
if( argToken.type != TokenType::Argument )
|
||||
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
|
||||
auto result = m_ref->setValue( argToken.token );
|
||||
auto result = valueRef->setValue( argToken.token );
|
||||
if( !result )
|
||||
return InternalParseResult( result );
|
||||
if( result.value() == ParseResultType::ShortCircuitAll )
|
||||
@@ -1077,6 +1077,12 @@ namespace detail {
|
||||
return Parser( *this ) |= other;
|
||||
}
|
||||
|
||||
// Forward deprecated interface with '+' instead of '|'
|
||||
template<typename T>
|
||||
auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
|
||||
template<typename T>
|
||||
auto operator+( T const &other ) const -> Parser { return operator|( other ); }
|
||||
|
||||
auto getHelpColumns() const -> std::vector<HelpColumns> {
|
||||
std::vector<HelpColumns> cols;
|
||||
for (auto const &o : m_options) {
|
||||
@@ -1116,6 +1122,8 @@ namespace detail {
|
||||
for( auto const &cols : rows )
|
||||
optWidth = (std::max)(optWidth, cols.left.size() + 2);
|
||||
|
||||
optWidth = (std::min)(optWidth, consoleWidth/2);
|
||||
|
||||
for( auto const &cols : rows ) {
|
||||
auto row =
|
||||
TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
|
||||
|
@@ -31,6 +31,14 @@
|
||||
# define CATCH_CPP14_OR_GREATER
|
||||
# endif
|
||||
|
||||
# if __cplusplus >= 201703L
|
||||
# define CATCH_CPP17_OR_GREATER
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_CPP17_OR_GREATER)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
@@ -80,6 +88,11 @@
|
||||
// Visual C++
|
||||
#ifdef _MSC_VER
|
||||
|
||||
|
||||
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||
# endif
|
||||
|
||||
// Universal Windows platform does not support SEH
|
||||
// Or console colours (or console at all...)
|
||||
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
|
||||
@@ -112,6 +125,11 @@
|
||||
# define CATCH_CONFIG_POSIX_SIGNALS
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_INTERNAL_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
|
||||
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
|
||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
||||
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
|
||||
|
@@ -11,8 +11,8 @@
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#include "catch_console_colour.h"
|
||||
#include "catch_enforce.h"
|
||||
#include "catch_errno_guard.h"
|
||||
@@ -84,8 +84,12 @@ namespace {
|
||||
case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
|
||||
case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
|
||||
case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
|
||||
case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
|
||||
|
||||
case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
|
||||
|
||||
default:
|
||||
CATCH_ERROR( "Unknown colour requested" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,8 +147,10 @@ namespace {
|
||||
case Colour::BrightRed: return setColour( "[1;31m" );
|
||||
case Colour::BrightGreen: return setColour( "[1;32m" );
|
||||
case Colour::BrightWhite: return setColour( "[1;37m" );
|
||||
case Colour::BrightYellow: return setColour( "[1;33m" );
|
||||
|
||||
case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
|
||||
default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
|
||||
}
|
||||
}
|
||||
static IColourImpl* instance() {
|
||||
@@ -196,7 +202,7 @@ namespace Catch {
|
||||
namespace Catch {
|
||||
|
||||
Colour::Colour( Code _colourCode ) { use( _colourCode ); }
|
||||
Colour::Colour( Colour&& rhs ) noexcept {
|
||||
Colour::Colour( Colour&& rhs ) noexcept {
|
||||
m_moved = rhs.m_moved;
|
||||
rhs.m_moved = true;
|
||||
}
|
||||
@@ -205,7 +211,7 @@ namespace Catch {
|
||||
rhs.m_moved = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Colour::~Colour(){ if( !m_moved ) use( None ); }
|
||||
|
||||
void Colour::use( Code _colourCode ) {
|
||||
|
@@ -30,10 +30,11 @@ namespace Catch {
|
||||
BrightGreen = Bright | Green,
|
||||
LightGrey = Bright | Grey,
|
||||
BrightWhite = Bright | White,
|
||||
BrightYellow = Bright | Yellow,
|
||||
|
||||
// By intention
|
||||
FileName = LightGrey,
|
||||
Warning = Yellow,
|
||||
Warning = BrightYellow,
|
||||
ResultError = BrightRed,
|
||||
ResultSuccess = BrightGreen,
|
||||
ResultExpectedFailure = Warning,
|
||||
@@ -42,7 +43,7 @@ namespace Catch {
|
||||
Success = Green,
|
||||
|
||||
OriginalExpression = Cyan,
|
||||
ReconstructedExpression = Yellow,
|
||||
ReconstructedExpression = BrightYellow,
|
||||
|
||||
SecondaryText = LightGrey,
|
||||
Headers = White
|
||||
|
@@ -40,7 +40,10 @@ namespace Catch {
|
||||
#ifdef CATCH_TRAP
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
|
||||
#else
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() (void)0, 0
|
||||
namespace Catch {
|
||||
inline void doNothing() {}
|
||||
}
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing()
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
||||
|
@@ -82,7 +82,7 @@ namespace Catch {
|
||||
|
||||
// Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
|
||||
template<typename LhsT, typename RhsT>
|
||||
auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return lhs == rhs; };
|
||||
auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); }
|
||||
template<typename T>
|
||||
auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
|
||||
template<typename T>
|
||||
@@ -93,7 +93,7 @@ namespace Catch {
|
||||
auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
|
||||
|
||||
template<typename LhsT, typename RhsT>
|
||||
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs != rhs; };
|
||||
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }
|
||||
template<typename T>
|
||||
auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
|
||||
template<typename T>
|
||||
@@ -128,19 +128,19 @@ namespace Catch {
|
||||
|
||||
template<typename RhsT>
|
||||
auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
return { m_lhs > rhs, m_lhs, ">", rhs };
|
||||
return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs };
|
||||
}
|
||||
template<typename RhsT>
|
||||
auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
return { m_lhs < rhs, m_lhs, "<", rhs };
|
||||
return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs };
|
||||
}
|
||||
template<typename RhsT>
|
||||
auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
return { m_lhs >= rhs, m_lhs, ">=", rhs };
|
||||
return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs };
|
||||
}
|
||||
template<typename RhsT>
|
||||
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
return { m_lhs <= rhs, m_lhs, "<=", rhs };
|
||||
return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
|
||||
}
|
||||
|
||||
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
||||
|
@@ -33,6 +33,17 @@ namespace Catch {
|
||||
return Catch::Detail::stringify( [exception description] );
|
||||
}
|
||||
#else
|
||||
// Compiling a mixed mode project with MSVC means that CLR
|
||||
// exceptions will be caught in (...) as well. However, these
|
||||
// do not fill-in std::current_exception and thus lead to crash
|
||||
// when attempting rethrow.
|
||||
// /EHa switch also causes structured exceptions to be caught
|
||||
// here, but they fill-in current_exception properly, so
|
||||
// at worst the output should be a little weird, instead of
|
||||
// causing a crash.
|
||||
if (std::current_exception() == nullptr) {
|
||||
return "Non C++ exception. Possibly a CLR exception.";
|
||||
}
|
||||
return tryTranslators();
|
||||
#endif
|
||||
}
|
||||
|
@@ -17,12 +17,14 @@
|
||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#endif
|
||||
|
||||
#if (defined(CATCH_PLATFORM_WINDOWS) && defined(CATCH_CONFIG_WINDOWS_SEH)) || defined(CATCH_CONFIG_POSIX_SIGNALS)
|
||||
namespace {
|
||||
// Report the error condition
|
||||
void reportFatal( char const * const message ) {
|
||||
Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
||||
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "catch_message.h"
|
||||
#include "catch_interfaces_capture.h"
|
||||
#include "catch_uncaught_exceptions.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -49,18 +50,9 @@ namespace Catch {
|
||||
getResultCapture().pushScopedMessage( m_info );
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17
|
||||
#endif
|
||||
ScopedMessage::~ScopedMessage() {
|
||||
if ( !std::uncaught_exception() ){
|
||||
if ( !uncaught_exceptions() ){
|
||||
getResultCapture().popScopedMessage(m_info);
|
||||
}
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
} // end namespace Catch
|
||||
|
@@ -321,12 +321,13 @@ namespace Catch {
|
||||
handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
|
||||
}
|
||||
}
|
||||
Counts assertions = m_totals.assertions - prevAssertions;
|
||||
bool missingAssertions = testForMissingAssertions(assertions);
|
||||
|
||||
m_testCaseTracker->close();
|
||||
handleUnfinishedSections();
|
||||
m_messages.clear();
|
||||
|
||||
Counts assertions = m_totals.assertions - prevAssertions;
|
||||
bool missingAssertions = testForMissingAssertions(assertions);
|
||||
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
|
||||
m_reporter->sectionEnded(testCaseSectionStats);
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "catch_section.h"
|
||||
#include "catch_capture.hpp"
|
||||
#include "catch_uncaught_exceptions.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -18,22 +19,15 @@ namespace Catch {
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17
|
||||
#endif
|
||||
Section::~Section() {
|
||||
if( m_sectionIncluded ) {
|
||||
SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
|
||||
if( std::uncaught_exception() )
|
||||
if( uncaught_exceptions() )
|
||||
getResultCapture().sectionEndedEarly( endInfo );
|
||||
else
|
||||
getResultCapture().sectionEnded( endInfo );
|
||||
}
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// This indicates whether the section should be executed or not
|
||||
Section::operator bool() const {
|
||||
|
@@ -259,6 +259,9 @@ namespace Catch {
|
||||
if( Option<std::size_t> listed = list( config() ) )
|
||||
return static_cast<int>( *listed );
|
||||
|
||||
// Note that on unices only the lower 8 bits are usually used, clamping
|
||||
// the return value to 255 prevents false negative when some multiple
|
||||
// of 256 tests has failed
|
||||
return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) );
|
||||
}
|
||||
catch( std::exception& ex ) {
|
||||
|
@@ -15,6 +15,13 @@
|
||||
|
||||
#include <ostream>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
namespace {
|
||||
const uint32_t byte_2_lead = 0xC0;
|
||||
const uint32_t byte_3_lead = 0xE0;
|
||||
const uint32_t byte_4_lead = 0xF0;
|
||||
}
|
||||
|
||||
namespace Catch {
|
||||
StringRef::StringRef( char const* rawChars ) noexcept
|
||||
@@ -79,13 +86,12 @@ namespace Catch {
|
||||
// Make adjustments for uft encodings
|
||||
for( size_type i=0; i < m_size; ++i ) {
|
||||
char c = m_start[i];
|
||||
if( ( c & 0b11000000 ) == 0b11000000 ) {
|
||||
if( ( c & 0b11100000 ) == 0b11000000 )
|
||||
if( ( c & byte_2_lead ) == byte_2_lead ) {
|
||||
noChars--;
|
||||
if (( c & byte_3_lead ) == byte_3_lead )
|
||||
noChars--;
|
||||
if( ( c & byte_4_lead ) == byte_4_lead )
|
||||
noChars--;
|
||||
else if( ( c & 0b11110000 ) == 0b11100000 )
|
||||
noChars-=2;
|
||||
else if( ( c & 0b11111000 ) == 0b11110000 )
|
||||
noChars-=3;
|
||||
}
|
||||
}
|
||||
return noChars;
|
||||
|
@@ -63,11 +63,11 @@ namespace Catch {
|
||||
template<typename T>
|
||||
typename std::enable_if<!std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& ) {
|
||||
return Detail::unprintableString;
|
||||
};
|
||||
}
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& value ) {
|
||||
return convertUnknownEnumToString( value );
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
@@ -136,18 +136,6 @@ namespace Catch {
|
||||
static std::string convert(wchar_t * str);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_string_array : std::false_type {};
|
||||
|
||||
template<std::size_t N>
|
||||
struct is_string_array<char[N]> : std::true_type {};
|
||||
|
||||
template<std::size_t N>
|
||||
struct is_string_array<signed char[N]> : std::true_type {};
|
||||
|
||||
template<std::size_t N>
|
||||
struct is_string_array<unsigned char[N]> : std::true_type {};
|
||||
|
||||
template<int SZ>
|
||||
struct StringMaker<char[SZ]> {
|
||||
static std::string convert(const char* str) {
|
||||
@@ -399,12 +387,20 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
struct StringMaker<R, typename std::enable_if<is_range<R>::value && !is_string_array<R>::value>::type> {
|
||||
struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {
|
||||
static std::string convert( R const& range ) {
|
||||
return rangeToString( range );
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, int SZ>
|
||||
struct StringMaker<T[SZ]> {
|
||||
static std::string convert(T const(&arr)[SZ]) {
|
||||
return rangeToString(arr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
// Separate std::chrono::duration specialization
|
||||
|
21
include/internal/catch_uncaught_exceptions.cpp
Normal file
21
include/internal/catch_uncaught_exceptions.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Created by Josh on 1/2/2018.
|
||||
* Copyright 2018 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include "catch_compiler_capabilities.h"
|
||||
#include "catch_uncaught_exceptions.h"
|
||||
#include <exception>
|
||||
|
||||
namespace Catch {
|
||||
bool uncaught_exceptions() {
|
||||
#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
|
||||
return std::uncaught_exceptions() > 0;
|
||||
#else
|
||||
return std::uncaught_exception();
|
||||
#endif
|
||||
}
|
||||
} // end namespace Catch
|
15
include/internal/catch_uncaught_exceptions.h
Normal file
15
include/internal/catch_uncaught_exceptions.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Created by Josh on 1/2/2018.
|
||||
* Copyright 2018 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_UNCAUGHT_EXCEPTIONS_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_UNCAUGHT_EXCEPTIONS_H_INCLUDED
|
||||
|
||||
namespace Catch {
|
||||
bool uncaught_exceptions();
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_UNCAUGHT_EXCEPTIONS_H_INCLUDED
|
@@ -37,7 +37,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Version const& libraryVersion() {
|
||||
static Version version( 2, 1, 0, "", 0 );
|
||||
static Version version( 2, 1, 2, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
|
@@ -64,7 +64,7 @@ namespace Catch {
|
||||
m_reporterPrefs.shouldRedirectStdOut = true;
|
||||
}
|
||||
|
||||
JunitReporter::~JunitReporter() {};
|
||||
JunitReporter::~JunitReporter() {}
|
||||
|
||||
std::string JunitReporter::getDescription() {
|
||||
return "Reports test results in an XML format that looks like Ant's junitreport target";
|
||||
|
@@ -6,7 +6,7 @@ if "%CONFIGURATION%"=="Debug" (
|
||||
python scripts\generateSingleHeader.py
|
||||
cmake -Hmisc -Bbuild-misc -A%PLATFORM%
|
||||
cmake --build build-misc
|
||||
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DBUILD_EXAMPLES=ON -DMEMORYCHECK_COMMAND=build-misc\Debug\CoverageHelper.exe -DMEMORYCHECK_COMMAND_OPTIONS=--sep-- -DMEMORYCHECK_TYPE=Valgrind
|
||||
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DCATCH_BUILD_EXAMPLES=ON -DMEMORYCHECK_COMMAND=build-misc\Debug\CoverageHelper.exe -DMEMORYCHECK_COMMAND_OPTIONS=--sep-- -DMEMORYCHECK_TYPE=Valgrind
|
||||
)
|
||||
if "%CONFIGURATION%"=="Release" (
|
||||
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain%
|
||||
|
@@ -96,5 +96,10 @@ int main(int argc, char** argv) {
|
||||
return lhs + ' ' + rhs;
|
||||
});
|
||||
|
||||
exec_cmd(cmdline, num, windowsify_path(catch_path(args[0])));
|
||||
try {
|
||||
return exec_cmd(cmdline, num, windowsify_path(catch_path(args[0])));
|
||||
} catch (std::exception const& ex) {
|
||||
std::cerr << "Helper failed with: '" << ex.what() << "'\n";
|
||||
return 12;
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,12 @@ Decomposition.tests.cpp:<line number>: passed: fptr == 0 for: 0 == 0
|
||||
Decomposition.tests.cpp:<line number>: passed: fptr == 0l for: 0 == 0
|
||||
Compilation.tests.cpp:<line number>: passed: y.v == 0 for: 0 == 0
|
||||
Compilation.tests.cpp:<line number>: passed: 0 == y.v for: 0 == 0
|
||||
Compilation.tests.cpp:<line number>: passed: t1 == t2 for: {?} == {?}
|
||||
Compilation.tests.cpp:<line number>: passed: t1 != t2 for: {?} != {?}
|
||||
Compilation.tests.cpp:<line number>: passed: t1 < t2 for: {?} < {?}
|
||||
Compilation.tests.cpp:<line number>: passed: t1 > t2 for: {?} > {?}
|
||||
Compilation.tests.cpp:<line number>: passed: t1 <= t2 for: {?} <= {?}
|
||||
Compilation.tests.cpp:<line number>: passed: t1 >= t2 for: {?} >= {?}
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception'
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42'
|
||||
@@ -592,6 +598,11 @@ Message from section one
|
||||
Message from section two
|
||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), StartsWith("This String") for: "this string contains 'abc' as a substring" starts with: "This String"
|
||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), StartsWith("string", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" starts with: "string" (case insensitive)
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify(singular) == "{ 1 }" for: "{ 1 }" == "{ 1 }"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify(arr) == "{ 3, 2, 1 }" for: "{ 3, 2, 1 }" == "{ 3, 2, 1 }"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify(arr) == R"({ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } })" for: "{ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } }"
|
||||
==
|
||||
"{ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } }"
|
||||
Matchers.tests.cpp:<line number>: passed: testStringForMatching(), Contains("string") for: "this string contains 'abc' as a substring" contains: "string"
|
||||
Matchers.tests.cpp:<line number>: passed: testStringForMatching(), Contains("string", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" contains: "string" (case insensitive)
|
||||
Matchers.tests.cpp:<line number>: passed: testStringForMatching(), Contains("abc") for: "this string contains 'abc' as a substring" contains: "abc"
|
||||
@@ -641,6 +652,9 @@ String.tests.cpp:<line number>: passed: stdStr == "a stringref" for: "a stringre
|
||||
String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
|
||||
String.tests.cpp:<line number>: passed: stdStr == "a stringref" for: "a stringref" == "a stringref"
|
||||
String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
|
||||
String.tests.cpp:<line number>: passed: ascii.numberOfCharacters() == ascii.size() for: 39 == 39
|
||||
String.tests.cpp:<line number>: passed: simpleu8.numberOfCharacters() == 30 for: 30 == 30
|
||||
String.tests.cpp:<line number>: passed: emojis.numberOfCharacters() == 9 for: 9 == 9
|
||||
ToStringChrono.tests.cpp:<line number>: passed: minute == seconds for: 1 m == 60 s
|
||||
ToStringChrono.tests.cpp:<line number>: passed: hour != seconds for: 1 h != 60 s
|
||||
ToStringChrono.tests.cpp:<line number>: passed: micro != milli for: 1 us != 1 ms
|
||||
@@ -976,6 +990,14 @@ Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load
|
||||
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
|
||||
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
|
||||
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
|
||||
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)" for: "op<<(streamable_range)"
|
||||
==
|
||||
"op<<(streamable_range)"
|
||||
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)" for: "stringmaker(streamable_range)"
|
||||
==
|
||||
"stringmaker(streamable_range)"
|
||||
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }" for: "{ 1, 2, 3, 4 }" == "{ 1, 2, 3, 4 }"
|
||||
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(disabled_range{}) == "{?}" for: "{?}" == "{?}"
|
||||
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" for: "{ StringMaker<has_maker> }"
|
||||
==
|
||||
"{ StringMaker<has_maker> }"
|
||||
@@ -1047,5 +1069,5 @@ Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
|
||||
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
|
||||
Misc.tests.cpp:<line number>: passed:
|
||||
Misc.tests.cpp:<line number>: passed:
|
||||
Failed 49 test cases, failed 108 assertions.
|
||||
Failed 61 test cases, failed 120 assertions.
|
||||
|
||||
|
@@ -1064,6 +1064,6 @@ with expansion:
|
||||
"first" == "second"
|
||||
|
||||
===============================================================================
|
||||
test cases: 195 | 144 passed | 47 failed | 4 failed as expected
|
||||
assertions: 983 | 857 passed | 105 failed | 21 failed as expected
|
||||
test cases: 198 | 147 passed | 47 failed | 4 failed as expected
|
||||
assertions: 999 | 873 passed | 105 failed | 21 failed as expected
|
||||
|
||||
|
@@ -51,6 +51,48 @@ PASSED:
|
||||
with expansion:
|
||||
0 == 0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1147
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( t1 == t2 )
|
||||
with expansion:
|
||||
{?} == {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( t1 != t2 )
|
||||
with expansion:
|
||||
{?} != {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( t1 < t2 )
|
||||
with expansion:
|
||||
{?} < {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( t1 > t2 )
|
||||
with expansion:
|
||||
{?} > {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( t1 <= t2 )
|
||||
with expansion:
|
||||
{?} <= {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( t1 >= t2 )
|
||||
with expansion:
|
||||
{?} >= {?}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#748 - captures with unexpected exceptions
|
||||
outside assertions
|
||||
@@ -532,6 +574,15 @@ PASSED:
|
||||
with expansion:
|
||||
100.3 == Approx( 100.0 )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
An empty test with no assertions
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in test case 'An empty test with no assertions'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
An expression with side-effects should only be evaluated once
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -2076,6 +2127,9 @@ warning:
|
||||
this is a message
|
||||
this is a warning
|
||||
|
||||
|
||||
No assertions in test case 'INFO and WARN do not abort tests'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
INFO gets logged on failure
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -2488,6 +2542,9 @@ Misc.tests.cpp:<line number>:
|
||||
warning:
|
||||
This one ran
|
||||
|
||||
|
||||
No assertions in test case 'Nice descriptive name'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Non-std exceptions can be translated
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -4620,6 +4677,15 @@ with expansion:
|
||||
A string sent directly to stdout
|
||||
A string sent directly to stderr
|
||||
A string sent to stderr via clog
|
||||
-------------------------------------------------------------------------------
|
||||
Sends stuff to stdout and stderr
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in test case 'Sends stuff to stdout and stderr'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Some simple comparisons between doubles
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -4707,6 +4773,47 @@ with expansion:
|
||||
"this string contains 'abc' as a substring" starts with: "string" (case
|
||||
insensitive)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Static arrays are convertible to string
|
||||
Single item
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringGeneral.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringGeneral.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::Detail::stringify(singular) == "{ 1 }" )
|
||||
with expansion:
|
||||
"{ 1 }" == "{ 1 }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Static arrays are convertible to string
|
||||
Multiple
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringGeneral.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringGeneral.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::Detail::stringify(arr) == "{ 3, 2, 1 }" )
|
||||
with expansion:
|
||||
"{ 3, 2, 1 }" == "{ 3, 2, 1 }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Static arrays are convertible to string
|
||||
Non-trivial inner items
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringGeneral.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringGeneral.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Catch::Detail::stringify(arr) == R"({ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } })" )
|
||||
with expansion:
|
||||
"{ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } }"
|
||||
==
|
||||
"{ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } }"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
String matchers
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -5132,6 +5239,31 @@ PASSED:
|
||||
with expansion:
|
||||
11 == 11
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
StringRef
|
||||
Counting utf-8 codepoints
|
||||
-------------------------------------------------------------------------------
|
||||
String.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
String.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( ascii.numberOfCharacters() == ascii.size() )
|
||||
with expansion:
|
||||
39 == 39
|
||||
|
||||
String.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( simpleu8.numberOfCharacters() == 30 )
|
||||
with expansion:
|
||||
30 == 30
|
||||
|
||||
String.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( emojis.numberOfCharacters() == 9 )
|
||||
with expansion:
|
||||
9 == 9
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Stringifying std::chrono::duration helpers
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -5307,6 +5439,9 @@ Message.tests.cpp:<line number>:
|
||||
FAILED - but was ok:
|
||||
CHECK_NOFAIL( 1 == 2 )
|
||||
|
||||
|
||||
No assertions in test case 'The NO_FAIL macro reports a failure but does not fail the test'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
This test 'should' fail but doesn't
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -6672,6 +6807,15 @@ Exception.tests.cpp:<line number>: FAILED:
|
||||
due to unexpected exception with message:
|
||||
unexpected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
When unchecked exceptions are thrown, but caught, they do not affect the test
|
||||
-------------------------------------------------------------------------------
|
||||
Exception.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in test case 'When unchecked exceptions are thrown, but caught, they do not affect the test'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Where the LHS is not a simple value
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -6683,6 +6827,9 @@ warning:
|
||||
Uncomment the code in this test to check that it gives a sensible compiler
|
||||
error
|
||||
|
||||
|
||||
No assertions in test case 'Where the LHS is not a simple value'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Where there is more to the expression after the RHS
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -6694,6 +6841,9 @@ warning:
|
||||
Uncomment the code in this test to check that it gives a sensible compiler
|
||||
error
|
||||
|
||||
|
||||
No assertions in test case 'Where there is more to the expression after the RHS'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
X/level/0/a
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -7060,7 +7210,25 @@ Misc.tests.cpp:<line number>
|
||||
Misc.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
first tag
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in test case 'first tag'
|
||||
|
||||
loose text artifact
|
||||
-------------------------------------------------------------------------------
|
||||
has printf
|
||||
-------------------------------------------------------------------------------
|
||||
Tricky.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in test case 'has printf'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
just failure
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -7071,6 +7239,15 @@ Message.tests.cpp:<line number>: FAILED:
|
||||
explicitly with message:
|
||||
Previous info should not be seen
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
just info
|
||||
-------------------------------------------------------------------------------
|
||||
Message.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in test case 'just info'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
long long
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -7489,6 +7666,15 @@ PASSED:
|
||||
with expansion:
|
||||
"didn|'t" == "didn|'t"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
second tag
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in test case 'second tag'
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
send a single char to INFO
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -7733,6 +7919,40 @@ PASSED:
|
||||
with expansion:
|
||||
""wide load"" == ""wide load""
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString streamable range
|
||||
-------------------------------------------------------------------------------
|
||||
ToStringWhich.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ToStringWhich.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( ::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)" )
|
||||
with expansion:
|
||||
"op<<(streamable_range)"
|
||||
==
|
||||
"op<<(streamable_range)"
|
||||
|
||||
ToStringWhich.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( ::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)" )
|
||||
with expansion:
|
||||
"stringmaker(streamable_range)"
|
||||
==
|
||||
"stringmaker(streamable_range)"
|
||||
|
||||
ToStringWhich.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( ::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }" )
|
||||
with expansion:
|
||||
"{ 1, 2, 3, 4 }" == "{ 1, 2, 3, 4 }"
|
||||
|
||||
ToStringWhich.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( ::Catch::Detail::stringify(disabled_range{}) == "{?}" )
|
||||
with expansion:
|
||||
"{?}" == "{?}"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString( vectors<has_maker> )
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -8246,6 +8466,6 @@ Misc.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
|
||||
===============================================================================
|
||||
test cases: 195 | 142 passed | 49 failed | 4 failed as expected
|
||||
assertions: 982 | 853 passed | 108 failed | 21 failed as expected
|
||||
test cases: 198 | 133 passed | 61 failed | 4 failed as expected
|
||||
assertions: 1010 | 869 passed | 120 failed | 21 failed as expected
|
||||
|
||||
|
@@ -51,6 +51,48 @@ PASSED:
|
||||
with expansion:
|
||||
0 == 0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1147
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( t1 == t2 )
|
||||
with expansion:
|
||||
{?} == {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( t1 != t2 )
|
||||
with expansion:
|
||||
{?} != {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( t1 < t2 )
|
||||
with expansion:
|
||||
{?} < {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( t1 > t2 )
|
||||
with expansion:
|
||||
{?} > {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( t1 <= t2 )
|
||||
with expansion:
|
||||
{?} <= {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( t1 >= t2 )
|
||||
with expansion:
|
||||
{?} >= {?}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#748 - captures with unexpected exceptions
|
||||
outside assertions
|
||||
@@ -257,6 +299,6 @@ with expansion:
|
||||
!true
|
||||
|
||||
===============================================================================
|
||||
test cases: 10 | 7 passed | 1 failed | 2 failed as expected
|
||||
assertions: 28 | 21 passed | 4 failed | 3 failed as expected
|
||||
test cases: 11 | 8 passed | 1 failed | 2 failed as expected
|
||||
assertions: 34 | 27 passed | 4 failed | 3 failed as expected
|
||||
|
||||
|
@@ -1,10 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuitesloose text artifact
|
||||
>
|
||||
<testsuite name="<exe-name>" errors="15" failures="94" tests="983" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="15" failures="106" tests="1011" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="#1147" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
expected exception
|
||||
@@ -537,6 +538,9 @@ Matchers.tests.cpp:<line number>
|
||||
Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Static arrays are convertible to string/Single item" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Static arrays are convertible to string/Multiple" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Static arrays are convertible to string/Non-trivial inner items" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="String matchers" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/Empty string" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/From string literal" time="{duration}"/>
|
||||
@@ -558,6 +562,7 @@ String.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/to std::string/implicitly constructed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/to std::string/explicitly constructed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/to std::string/assigned" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/Counting utf-8 codepoints" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Stringifying std::chrono::duration helpers" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Stringifying std::chrono::duration with weird ratios" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Stringifying std::chrono::time_point<system_clock>" time="{duration}"/>
|
||||
@@ -821,6 +826,7 @@ Tricky.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="toString on const wchar_t pointer returns the string contents" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="toString on wchar_t const pointer returns the string contents" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="toString on wchar_t returns the string contents" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="toString streamable range" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="toString( vectors<has_maker> )" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="toString( vectors<has_maker_and_operator> )" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="toString( vectors<has_operator> )" time="{duration}"/>
|
||||
|
@@ -42,6 +42,57 @@
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="#1147" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
|
||||
<Original>
|
||||
t1 == t2
|
||||
</Original>
|
||||
<Expanded>
|
||||
{?} == {?}
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
|
||||
<Original>
|
||||
t1 != t2
|
||||
</Original>
|
||||
<Expanded>
|
||||
{?} != {?}
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
|
||||
<Original>
|
||||
t1 < t2
|
||||
</Original>
|
||||
<Expanded>
|
||||
{?} < {?}
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
|
||||
<Original>
|
||||
t1 > t2
|
||||
</Original>
|
||||
<Expanded>
|
||||
{?} > {?}
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
|
||||
<Original>
|
||||
t1 <= t2
|
||||
</Original>
|
||||
<Expanded>
|
||||
{?} <= {?}
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
|
||||
<Original>
|
||||
t1 >= t2
|
||||
</Original>
|
||||
<Expanded>
|
||||
{?} >= {?}
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="#748 - captures with unexpected exceptions" tags="[!shouldfail][!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
|
||||
<Section name="outside assertions" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
|
||||
<Info>
|
||||
@@ -549,7 +600,7 @@
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="An empty test with no assertions" tags="[empty]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
|
||||
<OverallResult success="true"/>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="An expression with side-effects should only be evaluated once" tags="[Tricky]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||
@@ -2396,7 +2447,7 @@
|
||||
<Warning>
|
||||
this is a warning
|
||||
</Warning>
|
||||
<OverallResult success="true"/>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="INFO gets logged on failure" tags="[.][failing][messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
|
||||
<Info>
|
||||
@@ -2906,7 +2957,7 @@
|
||||
<Warning>
|
||||
This one ran
|
||||
</Warning>
|
||||
<OverallResult success="true"/>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="Non-std exceptions can be translated" tags="[!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
|
||||
<Exception filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
|
||||
@@ -5324,7 +5375,7 @@
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="Sends stuff to stdout and stderr" tags="[.]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
|
||||
<OverallResult success="true">
|
||||
<OverallResult success="false">
|
||||
<StdOut>
|
||||
A string sent directly to stdout
|
||||
</StdOut>
|
||||
@@ -5426,6 +5477,44 @@ Message from section two
|
||||
</Expression>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="Static arrays are convertible to string" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
|
||||
<Section name="Single item" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
|
||||
<Original>
|
||||
Catch::Detail::stringify(singular) == "{ 1 }"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"{ 1 }" == "{ 1 }"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="Multiple" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
|
||||
<Original>
|
||||
Catch::Detail::stringify(arr) == "{ 3, 2, 1 }"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"{ 3, 2, 1 }" == "{ 3, 2, 1 }"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="Non-trivial inner items" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
|
||||
<Original>
|
||||
Catch::Detail::stringify(arr) == R"({ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } })"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"{ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } }"
|
||||
==
|
||||
"{ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } }"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="String matchers" tags="[matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
@@ -5493,7 +5582,7 @@ Message from section two
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="StringRef" tags="[Strings]" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
|
||||
<TestCase name="StringRef" tags="[StringRef][Strings]" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
|
||||
<Section name="Empty string" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
|
||||
<Original>
|
||||
@@ -5903,6 +5992,33 @@ Message from section two
|
||||
</Section>
|
||||
<OverallResults successes="2" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="Counting utf-8 codepoints" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
|
||||
<Original>
|
||||
ascii.numberOfCharacters() == ascii.size()
|
||||
</Original>
|
||||
<Expanded>
|
||||
39 == 39
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
|
||||
<Original>
|
||||
simpleu8.numberOfCharacters() == 30
|
||||
</Original>
|
||||
<Expanded>
|
||||
30 == 30
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
|
||||
<Original>
|
||||
emojis.numberOfCharacters() == 9
|
||||
</Original>
|
||||
<Expanded>
|
||||
9 == 9
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="3" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="Stringifying std::chrono::duration helpers" tags="[chrono][toString]" filename="projects/<exe-name>/UsageTests/ToStringChrono.tests.cpp" >
|
||||
@@ -6094,7 +6210,7 @@ Message from section two
|
||||
1 == 2
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="This test 'should' fail but doesn't" tags="[!shouldfail][.][failing]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
|
||||
<OverallResult success="false"/>
|
||||
@@ -7610,19 +7726,19 @@ Message from section two
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="When unchecked exceptions are thrown, but caught, they do not affect the test" tags="[!throws]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
|
||||
<OverallResult success="true"/>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="Where the LHS is not a simple value" tags="[.][Tricky][failing]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||
<Warning>
|
||||
Uncomment the code in this test to check that it gives a sensible compiler error
|
||||
</Warning>
|
||||
<OverallResult success="true"/>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="Where there is more to the expression after the RHS" tags="[.][Tricky][failing]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||
<Warning>
|
||||
Uncomment the code in this test to check that it gives a sensible compiler error
|
||||
</Warning>
|
||||
<OverallResult success="true"/>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="X/level/0/a" tags="[Tricky]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||
<OverallResult success="true"/>
|
||||
@@ -7963,11 +8079,11 @@ Message from section two
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="first tag" tags="[tag1]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
|
||||
<OverallResult success="true"/>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="has printf" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||
loose text artifact
|
||||
<OverallResult success="true"/>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="just failure" tags="[.][fail][isolated info][messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
|
||||
<Failure filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
|
||||
@@ -7976,7 +8092,7 @@ loose text artifact
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="just info" tags="[info][isolated info][messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
|
||||
<OverallResult success="true"/>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="long long" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
|
||||
@@ -8286,7 +8402,7 @@ loose text artifact
|
||||
</Section>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="replaceInPlace" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
|
||||
<TestCase name="replaceInPlace" tags="[StringManip][Strings]" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
|
||||
<Section name="replace single char" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
|
||||
<Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
|
||||
<Original>
|
||||
@@ -8423,7 +8539,7 @@ loose text artifact
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="second tag" tags="[tag2]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
|
||||
<OverallResult success="true"/>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="send a single char to INFO" tags="[.][failing]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
|
||||
<Info>
|
||||
@@ -8661,6 +8777,45 @@ loose text artifact
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="toString streamable range" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||
<Original>
|
||||
::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"op<<(streamable_range)"
|
||||
==
|
||||
"op<<(streamable_range)"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||
<Original>
|
||||
::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"stringmaker(streamable_range)"
|
||||
==
|
||||
"stringmaker(streamable_range)"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||
<Original>
|
||||
::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"{ 1, 2, 3, 4 }" == "{ 1, 2, 3, 4 }"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||
<Original>
|
||||
::Catch::Detail::stringify(disabled_range{}) == "{?}"
|
||||
</Original>
|
||||
<Expanded>
|
||||
"{?}" == "{?}"
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="toString( vectors<has_maker> )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||
<Original>
|
||||
@@ -9168,7 +9323,7 @@ loose text artifact
|
||||
</Section>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<OverallResults successes="853" failures="109" expectedFailures="21"/>
|
||||
<OverallResults successes="869" failures="121" expectedFailures="21"/>
|
||||
</Group>
|
||||
<OverallResults successes="853" failures="108" expectedFailures="21"/>
|
||||
<OverallResults successes="869" failures="120" expectedFailures="21"/>
|
||||
</Catch>
|
||||
|
@@ -36,8 +36,8 @@ namespace Catch {
|
||||
}
|
||||
} // namespace Catch
|
||||
|
||||
TEST_CASE( "StringRef", "[Strings]" ) {
|
||||
|
||||
TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
||||
|
||||
using Catch::StringRef;
|
||||
|
||||
SECTION( "Empty string" ) {
|
||||
@@ -46,21 +46,21 @@ TEST_CASE( "StringRef", "[Strings]" ) {
|
||||
REQUIRE( empty.size() == 0 );
|
||||
REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 );
|
||||
}
|
||||
|
||||
|
||||
SECTION( "From string literal" ) {
|
||||
StringRef s = "hello";
|
||||
REQUIRE( s.empty() == false );
|
||||
REQUIRE( s.size() == 5 );
|
||||
REQUIRE( isSubstring( s ) == false );
|
||||
|
||||
|
||||
auto rawChars = data( s );
|
||||
REQUIRE( std::strcmp( rawChars, "hello" ) == 0 );
|
||||
|
||||
|
||||
SECTION( "c_str() does not cause copy" ) {
|
||||
REQUIRE( isOwned( s ) == false );
|
||||
|
||||
|
||||
REQUIRE( s.c_str() == rawChars );
|
||||
|
||||
|
||||
REQUIRE( isOwned( s ) == false );
|
||||
}
|
||||
}
|
||||
@@ -69,19 +69,19 @@ TEST_CASE( "StringRef", "[Strings]" ) {
|
||||
REQUIRE( original == "original" );
|
||||
REQUIRE( isSubstring( original ) );
|
||||
REQUIRE( isOwned( original ) == false );
|
||||
|
||||
|
||||
original.c_str(); // Forces it to take ownership
|
||||
|
||||
|
||||
REQUIRE( isSubstring( original ) == false );
|
||||
REQUIRE( isOwned( original ) );
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SECTION( "Substrings" ) {
|
||||
StringRef s = "hello world!";
|
||||
StringRef ss = s.substr(0, 5);
|
||||
|
||||
|
||||
SECTION( "zero-based substring" ) {
|
||||
REQUIRE( ss.empty() == false );
|
||||
REQUIRE( ss.size() == 5 );
|
||||
@@ -91,33 +91,33 @@ TEST_CASE( "StringRef", "[Strings]" ) {
|
||||
SECTION( "c_str() causes copy" ) {
|
||||
REQUIRE( isSubstring( ss ) );
|
||||
REQUIRE( isOwned( ss ) == false );
|
||||
|
||||
|
||||
auto rawChars = data( ss );
|
||||
REQUIRE( rawChars == data( s ) ); // same pointer value
|
||||
REQUIRE( ss.c_str() != rawChars );
|
||||
|
||||
|
||||
REQUIRE( isSubstring( ss ) == false );
|
||||
REQUIRE( isOwned( ss ) );
|
||||
|
||||
|
||||
REQUIRE( data( ss ) != data( s ) ); // different pointer value
|
||||
}
|
||||
|
||||
|
||||
SECTION( "non-zero-based substring") {
|
||||
ss = s.substr( 6, 6 );
|
||||
REQUIRE( ss.size() == 6 );
|
||||
REQUIRE( std::strcmp( ss.c_str(), "world!" ) == 0 );
|
||||
}
|
||||
|
||||
|
||||
SECTION( "Pointer values of full refs should match" ) {
|
||||
StringRef s2 = s;
|
||||
REQUIRE( s.c_str() == s2.c_str() );
|
||||
}
|
||||
|
||||
|
||||
SECTION( "Pointer values of substring refs should not match" ) {
|
||||
REQUIRE( s.c_str() != ss.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SECTION( "Comparisons" ) {
|
||||
REQUIRE( StringRef("hello") == StringRef("hello") );
|
||||
REQUIRE( StringRef("hello") != StringRef("cello") );
|
||||
@@ -164,9 +164,21 @@ TEST_CASE( "StringRef", "[Strings]" ) {
|
||||
REQUIRE( stdStr.size() == sr.size() );
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "Counting utf-8 codepoints" ) {
|
||||
StringRef ascii = "just a plain old boring ascii string...";
|
||||
REQUIRE(ascii.numberOfCharacters() == ascii.size());
|
||||
|
||||
StringRef simpleu8 = u8"Trocha češtiny nikoho nezabila";
|
||||
REQUIRE(simpleu8.numberOfCharacters() == 30);
|
||||
|
||||
StringRef emojis = u8"Here be 👾";
|
||||
REQUIRE(emojis.numberOfCharacters() == 9);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE( "replaceInPlace" ) {
|
||||
TEST_CASE( "replaceInPlace", "[Strings][StringManip]" ) {
|
||||
std::string letters = "abcdefcg";
|
||||
SECTION( "replace single char" ) {
|
||||
CHECK( Catch::replaceInPlace( letters, "b", "z" ) );
|
||||
|
@@ -29,5 +29,5 @@ CATCH_REGISTER_TAG_ALIAS( "[@tricky]", "[tricky]~[.]" )
|
||||
struct TestListener : Catch::TestEventListenerBase {
|
||||
using TestEventListenerBase::TestEventListenerBase; // inherit constructor
|
||||
};
|
||||
CATCH_REGISTER_LISTENER( TestListener );
|
||||
CATCH_REGISTER_LISTENER( TestListener )
|
||||
|
||||
|
@@ -12,6 +12,19 @@ namespace { namespace CompilationTests {
|
||||
#ifndef COMPILATION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
|
||||
#define COMPILATION_TEST_HELPERS_INCLUDED
|
||||
|
||||
// Comparison operators can return non-booleans.
|
||||
// This is unusual, but should be supported.
|
||||
struct logic_t {
|
||||
logic_t operator< (logic_t) const { return {}; }
|
||||
logic_t operator<=(logic_t) const { return {}; }
|
||||
logic_t operator> (logic_t) const { return {}; }
|
||||
logic_t operator>=(logic_t) const { return {}; }
|
||||
logic_t operator==(logic_t) const { return {}; }
|
||||
logic_t operator!=(logic_t) const { return {}; }
|
||||
explicit operator bool() const { return true; }
|
||||
};
|
||||
|
||||
|
||||
// This is a minimal example for an issue we have found in 1.7.0
|
||||
struct foo {
|
||||
int i;
|
||||
@@ -109,4 +122,16 @@ namespace { namespace CompilationTests {
|
||||
REQUIRE(0 == y.v);
|
||||
}
|
||||
|
||||
// Comparison operators can return non-booleans.
|
||||
// This is unusual, but should be supported.
|
||||
TEST_CASE("#1147") {
|
||||
logic_t t1, t2;
|
||||
REQUIRE(t1 == t2);
|
||||
REQUIRE(t1 != t2);
|
||||
REQUIRE(t1 < t2);
|
||||
REQUIRE(t1 > t2);
|
||||
REQUIRE(t1 <= t2);
|
||||
REQUIRE(t1 >= t2);
|
||||
}
|
||||
|
||||
}} // namespace CompilationTests
|
||||
|
@@ -100,3 +100,18 @@ TEST_CASE( "std::set is convertible string", "[toString]" ) {
|
||||
REQUIRE( Catch::Detail::stringify( set ) == "{ \"abc\", \"def\", \"ghi\" }" );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Static arrays are convertible to string", "[toString]") {
|
||||
SECTION("Single item") {
|
||||
int singular[1] = { 1 };
|
||||
REQUIRE(Catch::Detail::stringify(singular) == "{ 1 }");
|
||||
}
|
||||
SECTION("Multiple") {
|
||||
int arr[3] = { 3, 2, 1 };
|
||||
REQUIRE(Catch::Detail::stringify(arr) == "{ 3, 2, 1 }");
|
||||
}
|
||||
SECTION("Non-trivial inner items") {
|
||||
std::vector<std::string> arr[2] = { {"1:1", "1:2", "1:3"}, {"2:1", "2:2"} };
|
||||
REQUIRE(Catch::Detail::stringify(arr) == R"({ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } })");
|
||||
}
|
||||
}
|
||||
|
@@ -71,3 +71,76 @@ TEST_CASE( "toString( vectors<has_maker_and_operator> )", "[toString]" ) {
|
||||
std::vector<has_maker_and_operator> v(1);
|
||||
REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker_and_operator> }" );
|
||||
}
|
||||
|
||||
// Conversion should go
|
||||
// StringMaker specialization, operator<<, range/enum detection, unprintable
|
||||
struct int_iterator {
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = int;
|
||||
using reference = int&;
|
||||
using pointer = int*;
|
||||
|
||||
int_iterator() = default;
|
||||
int_iterator(int i) :val(i) {}
|
||||
|
||||
value_type operator*() const { return val; }
|
||||
bool operator==(int_iterator rhs) const { return val == rhs.val; }
|
||||
bool operator!=(int_iterator rhs) const { return val != rhs.val; }
|
||||
int_iterator operator++() { ++val; return *this; }
|
||||
int_iterator operator++(int) {
|
||||
auto temp(*this);
|
||||
++val;
|
||||
return temp;
|
||||
}
|
||||
private:
|
||||
int val = 5;
|
||||
};
|
||||
|
||||
struct streamable_range {
|
||||
int_iterator begin() const { return int_iterator{ 1 }; }
|
||||
int_iterator end() const { return {}; }
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const streamable_range&) {
|
||||
os << "op<<(streamable_range)";
|
||||
return os;
|
||||
}
|
||||
|
||||
struct stringmaker_range {
|
||||
int_iterator begin() const { return int_iterator{ 1 }; }
|
||||
int_iterator end() const { return {}; }
|
||||
};
|
||||
|
||||
namespace Catch {
|
||||
template <>
|
||||
struct StringMaker<stringmaker_range> {
|
||||
static std::string convert(stringmaker_range const&) {
|
||||
return "stringmaker(streamable_range)";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct just_range {
|
||||
int_iterator begin() const { return int_iterator{ 1 }; }
|
||||
int_iterator end() const { return {}; }
|
||||
};
|
||||
|
||||
struct disabled_range {
|
||||
int_iterator begin() const { return int_iterator{ 1 }; }
|
||||
int_iterator end() const { return {}; }
|
||||
};
|
||||
|
||||
namespace Catch {
|
||||
template <>
|
||||
struct is_range<disabled_range> {
|
||||
static const bool value = false;
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("toString streamable range", "[toString]") {
|
||||
REQUIRE(::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)");
|
||||
REQUIRE(::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)");
|
||||
REQUIRE(::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }");
|
||||
REQUIRE(::Catch::Detail::stringify(disabled_range{}) == "{?}");
|
||||
}
|
||||
|
@@ -50,6 +50,8 @@ infParser = re.compile(r'''
|
||||
|
|
||||
\(__builtin_inff\(\)\) # Linux (ubuntu) INFINITY macro
|
||||
|
|
||||
\(__builtin_inff\ \(\)\) # Fedora INFINITY macro
|
||||
|
|
||||
__builtin_huge_valf\(\) # OSX macro
|
||||
''', re.VERBOSE)
|
||||
nanParser = re.compile(r'''
|
||||
|
2
scripts/embedClara.py
Normal file → Executable file
2
scripts/embedClara.py
Normal file → Executable file
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Execute this script any time you import a new copy of Clara into the third_party area
|
||||
import os
|
||||
import sys
|
||||
|
@@ -3,6 +3,7 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import io
|
||||
import sys
|
||||
import re
|
||||
import datetime
|
||||
@@ -46,11 +47,11 @@ def generate(v):
|
||||
outDir = os.path.dirname(outputPath)
|
||||
if not os.path.exists(outDir):
|
||||
os.makedirs(outDir)
|
||||
out = open( outputPath, 'w' )
|
||||
out = io.open( outputPath, 'w', newline='\n')
|
||||
|
||||
def write( line ):
|
||||
if globals['includeImpl'] or globals['implIfDefs'] == -1:
|
||||
out.write( line )
|
||||
out.write( line.decode('utf-8') )
|
||||
|
||||
def insertCpps():
|
||||
dirs = [os.path.join( rootPath, s) for s in ['', 'internal', 'reporters']]
|
||||
@@ -104,22 +105,22 @@ def generate(v):
|
||||
write( '// end {}\n'.format(filename) )
|
||||
|
||||
|
||||
out.write( "/*\n" )
|
||||
out.write( " * Catch v{0}\n".format( v.getVersionString() ) )
|
||||
out.write( " * Generated: {0}\n".format( datetime.datetime.now() ) )
|
||||
out.write( " * ----------------------------------------------------------\n" )
|
||||
out.write( " * This file has been merged from multiple headers. Please don't edit it directly\n" )
|
||||
out.write( " * Copyright (c) {} Two Blue Cubes Ltd. All rights reserved.\n".format( datetime.date.today().year ) )
|
||||
out.write( " *\n" )
|
||||
out.write( " * Distributed under the Boost Software License, Version 1.0. (See accompanying\n" )
|
||||
out.write( " * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" )
|
||||
out.write( " */\n" )
|
||||
out.write( "#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
|
||||
out.write( "#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
|
||||
write( "/*\n" )
|
||||
write( " * Catch v{0}\n".format( v.getVersionString() ) )
|
||||
write( " * Generated: {0}\n".format( datetime.datetime.now() ) )
|
||||
write( " * ----------------------------------------------------------\n" )
|
||||
write( " * This file has been merged from multiple headers. Please don't edit it directly\n" )
|
||||
write( " * Copyright (c) {} Two Blue Cubes Ltd. All rights reserved.\n".format( datetime.date.today().year ) )
|
||||
write( " *\n" )
|
||||
write( " * Distributed under the Boost Software License, Version 1.0. (See accompanying\n" )
|
||||
write( " * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" )
|
||||
write( " */\n" )
|
||||
write( "#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
|
||||
write( "#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
|
||||
|
||||
parseFile( rootPath, 'catch.hpp' )
|
||||
|
||||
out.write( "#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" )
|
||||
write( "#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" )
|
||||
out.close()
|
||||
print ("Generated single include for Catch v{0}\n".format( v.getVersionString() ) )
|
||||
|
||||
|
@@ -10,6 +10,7 @@ from scriptCommon import catchPath
|
||||
versionParser = re.compile( r'(\s*static\sVersion\sversion)\s*\(\s*(.*)\s*,\s*(.*)\s*,\s*(.*)\s*,\s*\"(.*)\"\s*,\s*(.*)\s*\).*' )
|
||||
rootPath = os.path.join( catchPath, 'include/' )
|
||||
versionPath = os.path.join( rootPath, "internal/catch_version.cpp" )
|
||||
definePath = os.path.join(rootPath, 'catch.hpp')
|
||||
readmePath = os.path.join( catchPath, "README.md" )
|
||||
conanPath = os.path.join(catchPath, 'conanfile.py')
|
||||
conanTestPath = os.path.join(catchPath, 'test_package', 'conanfile.py')
|
||||
@@ -80,7 +81,7 @@ class Version:
|
||||
def updateReadmeFile(version):
|
||||
import updateWandbox
|
||||
|
||||
downloadParser = re.compile( r'<a href=\"https://github.com/philsquared/Catch/releases/download/v\d+\.\d+\.\d+/catch.hpp\">' )
|
||||
downloadParser = re.compile( r'<a href=\"https://github.com/catchorg/Catch2/releases/download/v\d+\.\d+\.\d+/catch.hpp\">' )
|
||||
success, wandboxLink = updateWandbox.uploadFiles()
|
||||
if not success:
|
||||
print('Error when uploading to wandbox: {}'.format(wandboxLink))
|
||||
@@ -92,7 +93,7 @@ def updateReadmeFile(version):
|
||||
f.close()
|
||||
f = open( readmePath, 'w' )
|
||||
for line in lines:
|
||||
line = downloadParser.sub( r'<a href="https://github.com/philsquared/Catch/releases/download/v{0}/catch.hpp">'.format(version.getVersionString()) , line)
|
||||
line = downloadParser.sub( r'<a href="https://github.com/catchorg/Catch2/releases/download/v{0}/catch.hpp">'.format(version.getVersionString()) , line)
|
||||
if '[]' in line:
|
||||
line = '[]({0})'.format(wandboxLink)
|
||||
f.write( line + "\n" )
|
||||
@@ -128,20 +129,36 @@ def updateConanTestFile(version):
|
||||
f.write( line + "\n" )
|
||||
|
||||
def updateCmakeFile(version):
|
||||
cmakeParser = re.compile(r'set(CATCH_VERSION_NUMBER \d+\.\d+\.\d+)')
|
||||
with open(cmakePath, 'r') as file:
|
||||
lines = file.readlines()
|
||||
with open(cmakePath, 'w') as file:
|
||||
for line in lines:
|
||||
if 'set(CATCH_VERSION_NUMBER ' in line:
|
||||
file.write('set(CATCH_VERSION_NUMBER {0})\n'.format(version.getVersionString()))
|
||||
if 'project(Catch2 LANGUAGES CXX VERSION ' in line:
|
||||
file.write('project(Catch2 LANGUAGES CXX VERSION {0})\n'.format(version.getVersionString()))
|
||||
else:
|
||||
file.write(line)
|
||||
|
||||
|
||||
def updateVersionDefine(version):
|
||||
with open(definePath, 'r') as file:
|
||||
lines = file.readlines()
|
||||
with open(definePath, 'w') as file:
|
||||
for line in lines:
|
||||
if '#define CATCH_VERSION_MAJOR' in line:
|
||||
file.write('#define CATCH_VERSION_MAJOR {}\n'.format(version.majorVersion))
|
||||
elif '#define CATCH_VERSION_MINOR' in line:
|
||||
file.write('#define CATCH_VERSION_MINOR {}\n'.format(version.minorVersion))
|
||||
elif '#define CATCH_VERSION_PATCH' in line:
|
||||
file.write('#define CATCH_VERSION_PATCH {}\n'.format(version.patchNumber))
|
||||
else:
|
||||
file.write(line)
|
||||
|
||||
|
||||
def performUpdates(version):
|
||||
# First update version file, so we can regenerate single header and
|
||||
# have it ready for upload to wandbox, when updating readme
|
||||
version.updateVersionFile()
|
||||
updateVersionDefine(version)
|
||||
|
||||
import generateSingleHeader
|
||||
generateSingleHeader.generate(version)
|
||||
|
@@ -8,7 +8,7 @@ from releaseCommon import Version
|
||||
|
||||
print(catchPath)
|
||||
|
||||
default_path = '../vcpkg/ports/catch/'
|
||||
default_path = '../vcpkg/ports/catch2/'
|
||||
|
||||
def adjusted_path(path):
|
||||
return os.path.join(catchPath, path)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Catch v2.1.0
|
||||
* Generated: 2018-01-10 13:51:15.378034
|
||||
* Catch v2.1.2
|
||||
* Generated: 2018-02-09 17:05:21.506253
|
||||
* ----------------------------------------------------------
|
||||
* This file has been merged from multiple headers. Please don't edit it directly
|
||||
* Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved.
|
||||
@@ -13,6 +13,10 @@
|
||||
// start catch.hpp
|
||||
|
||||
|
||||
#define CATCH_VERSION_MAJOR 2
|
||||
#define CATCH_VERSION_MINOR 1
|
||||
#define CATCH_VERSION_PATCH 2
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang system_header
|
||||
#elif defined __GNUC__
|
||||
@@ -116,6 +120,14 @@ namespace Catch {
|
||||
# define CATCH_CPP14_OR_GREATER
|
||||
# endif
|
||||
|
||||
# if __cplusplus >= 201703L
|
||||
# define CATCH_CPP17_OR_GREATER
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_CPP17_OR_GREATER)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
@@ -164,6 +176,10 @@ namespace Catch {
|
||||
// Visual C++
|
||||
#ifdef _MSC_VER
|
||||
|
||||
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
|
||||
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||
# endif
|
||||
|
||||
// Universal Windows platform does not support SEH
|
||||
// Or console colours (or console at all...)
|
||||
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
|
||||
@@ -196,6 +212,10 @@ namespace Catch {
|
||||
# define CATCH_CONFIG_POSIX_SIGNALS
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_INTERNAL_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
|
||||
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
|
||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
||||
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
|
||||
@@ -735,11 +755,11 @@ namespace Catch {
|
||||
template<typename T>
|
||||
typename std::enable_if<!std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& ) {
|
||||
return Detail::unprintableString;
|
||||
};
|
||||
}
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& value ) {
|
||||
return convertUnknownEnumToString( value );
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
@@ -807,18 +827,6 @@ namespace Catch {
|
||||
static std::string convert(wchar_t * str);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_string_array : std::false_type {};
|
||||
|
||||
template<std::size_t N>
|
||||
struct is_string_array<char[N]> : std::true_type {};
|
||||
|
||||
template<std::size_t N>
|
||||
struct is_string_array<signed char[N]> : std::true_type {};
|
||||
|
||||
template<std::size_t N>
|
||||
struct is_string_array<unsigned char[N]> : std::true_type {};
|
||||
|
||||
template<int SZ>
|
||||
struct StringMaker<char[SZ]> {
|
||||
static std::string convert(const char* str) {
|
||||
@@ -1069,12 +1077,19 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
struct StringMaker<R, typename std::enable_if<is_range<R>::value && !is_string_array<R>::value>::type> {
|
||||
struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {
|
||||
static std::string convert( R const& range ) {
|
||||
return rangeToString( range );
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, int SZ>
|
||||
struct StringMaker<T[SZ]> {
|
||||
static std::string convert(T const(&arr)[SZ]) {
|
||||
return rangeToString(arr);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
// Separate std::chrono::duration specialization
|
||||
@@ -1269,7 +1284,7 @@ namespace Catch {
|
||||
|
||||
// Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
|
||||
template<typename LhsT, typename RhsT>
|
||||
auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return lhs == rhs; };
|
||||
auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); }
|
||||
template<typename T>
|
||||
auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
|
||||
template<typename T>
|
||||
@@ -1280,7 +1295,7 @@ namespace Catch {
|
||||
auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
|
||||
|
||||
template<typename LhsT, typename RhsT>
|
||||
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs != rhs; };
|
||||
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }
|
||||
template<typename T>
|
||||
auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
|
||||
template<typename T>
|
||||
@@ -1314,19 +1329,19 @@ namespace Catch {
|
||||
|
||||
template<typename RhsT>
|
||||
auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
return { m_lhs > rhs, m_lhs, ">", rhs };
|
||||
return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs };
|
||||
}
|
||||
template<typename RhsT>
|
||||
auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
return { m_lhs < rhs, m_lhs, "<", rhs };
|
||||
return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs };
|
||||
}
|
||||
template<typename RhsT>
|
||||
auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
return { m_lhs >= rhs, m_lhs, ">=", rhs };
|
||||
return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs };
|
||||
}
|
||||
template<typename RhsT>
|
||||
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||
return { m_lhs <= rhs, m_lhs, "<=", rhs };
|
||||
return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
|
||||
}
|
||||
|
||||
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
||||
@@ -3886,10 +3901,11 @@ namespace Catch {
|
||||
BrightGreen = Bright | Green,
|
||||
LightGrey = Bright | Grey,
|
||||
BrightWhite = Bright | White,
|
||||
BrightYellow = Bright | Yellow,
|
||||
|
||||
// By intention
|
||||
FileName = LightGrey,
|
||||
Warning = Yellow,
|
||||
Warning = BrightYellow,
|
||||
ResultError = BrightRed,
|
||||
ResultSuccess = BrightGreen,
|
||||
ResultExpectedFailure = Warning,
|
||||
@@ -3898,7 +3914,7 @@ namespace Catch {
|
||||
Success = Green,
|
||||
|
||||
OriginalExpression = Cyan,
|
||||
ReconstructedExpression = Yellow,
|
||||
ReconstructedExpression = BrightYellow,
|
||||
|
||||
SecondaryText = LightGrey,
|
||||
Headers = White
|
||||
@@ -4611,7 +4627,10 @@ namespace Catch {
|
||||
#ifdef CATCH_TRAP
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
|
||||
#else
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() (void)0, 0
|
||||
namespace Catch {
|
||||
inline void doNothing() {}
|
||||
}
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing()
|
||||
#endif
|
||||
|
||||
// end catch_debugger.h
|
||||
@@ -5093,8 +5112,14 @@ namespace Catch {
|
||||
#endif
|
||||
|
||||
// start clara.hpp
|
||||
// v1.0-develop.2
|
||||
// See https://github.com/philsquared/Clara
|
||||
// Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See https://github.com/philsquared/Clara for more details
|
||||
|
||||
// Clara v1.1.2
|
||||
|
||||
|
||||
#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
|
||||
@@ -5457,7 +5482,7 @@ namespace detail {
|
||||
template<typename ClassT, typename ReturnT, typename ArgT>
|
||||
struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
|
||||
static const bool isValid = true;
|
||||
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;;
|
||||
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
|
||||
using ReturnType = ReturnT;
|
||||
};
|
||||
|
||||
@@ -5621,7 +5646,7 @@ namespace detail {
|
||||
return *this;
|
||||
}
|
||||
|
||||
~ResultValueBase() {
|
||||
~ResultValueBase() override {
|
||||
if( m_type == Ok )
|
||||
m_value.~T();
|
||||
}
|
||||
@@ -5659,7 +5684,7 @@ namespace detail {
|
||||
auto errorMessage() const -> std::string { return m_errorMessage; }
|
||||
|
||||
protected:
|
||||
virtual void enforceOk() const {
|
||||
void enforceOk() const override {
|
||||
// !TBD: If no exceptions, std::terminate here or something
|
||||
switch( m_type ) {
|
||||
case ResultBase::LogicError:
|
||||
@@ -5739,46 +5764,32 @@ namespace detail {
|
||||
return ParserResult::ok( ParseResultType::Matched );
|
||||
}
|
||||
|
||||
struct BoundRefBase {
|
||||
BoundRefBase() = default;
|
||||
BoundRefBase( BoundRefBase const & ) = delete;
|
||||
BoundRefBase( BoundRefBase && ) = delete;
|
||||
BoundRefBase &operator=( BoundRefBase const & ) = delete;
|
||||
BoundRefBase &operator=( BoundRefBase && ) = delete;
|
||||
struct NonCopyable {
|
||||
NonCopyable() = default;
|
||||
NonCopyable( NonCopyable const & ) = delete;
|
||||
NonCopyable( NonCopyable && ) = delete;
|
||||
NonCopyable &operator=( NonCopyable const & ) = delete;
|
||||
NonCopyable &operator=( NonCopyable && ) = delete;
|
||||
};
|
||||
|
||||
virtual ~BoundRefBase() = default;
|
||||
|
||||
virtual auto isFlag() const -> bool = 0;
|
||||
struct BoundRef : NonCopyable {
|
||||
virtual ~BoundRef() = default;
|
||||
virtual auto isContainer() const -> bool { return false; }
|
||||
virtual auto isFlag() const -> bool { return false; }
|
||||
};
|
||||
struct BoundValueRefBase : BoundRef {
|
||||
virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
|
||||
};
|
||||
struct BoundFlagRefBase : BoundRef {
|
||||
virtual auto setFlag( bool flag ) -> ParserResult = 0;
|
||||
};
|
||||
|
||||
struct BoundValueRefBase : BoundRefBase {
|
||||
auto isFlag() const -> bool override { return false; }
|
||||
|
||||
auto setFlag( bool ) -> ParserResult override {
|
||||
return ParserResult::logicError( "Flags can only be set on boolean fields" );
|
||||
}
|
||||
};
|
||||
|
||||
struct BoundFlagRefBase : BoundRefBase {
|
||||
auto isFlag() const -> bool override { return true; }
|
||||
|
||||
auto setValue( std::string const &arg ) -> ParserResult override {
|
||||
bool flag;
|
||||
auto result = convertInto( arg, flag );
|
||||
if( result )
|
||||
setFlag( flag );
|
||||
return result;
|
||||
}
|
||||
virtual auto isFlag() const -> bool { return true; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct BoundRef : BoundValueRefBase {
|
||||
struct BoundValueRef : BoundValueRefBase {
|
||||
T &m_ref;
|
||||
|
||||
explicit BoundRef( T &ref ) : m_ref( ref ) {}
|
||||
explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
|
||||
|
||||
auto setValue( std::string const &arg ) -> ParserResult override {
|
||||
return convertInto( arg, m_ref );
|
||||
@@ -5786,10 +5797,10 @@ namespace detail {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct BoundRef<std::vector<T>> : BoundValueRefBase {
|
||||
struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
|
||||
std::vector<T> &m_ref;
|
||||
|
||||
explicit BoundRef( std::vector<T> &ref ) : m_ref( ref ) {}
|
||||
explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
|
||||
|
||||
auto isContainer() const -> bool override { return true; }
|
||||
|
||||
@@ -5834,12 +5845,12 @@ namespace detail {
|
||||
|
||||
template<typename ArgType, typename L>
|
||||
inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
|
||||
ArgType temp;
|
||||
ArgType temp{};
|
||||
auto result = convertInto( arg, temp );
|
||||
return !result
|
||||
? result
|
||||
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
|
||||
};
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
struct BoundLambda : BoundValueRefBase {
|
||||
@@ -5888,6 +5899,9 @@ namespace detail {
|
||||
public:
|
||||
template<typename T>
|
||||
auto operator|( T const &other ) const -> Parser;
|
||||
|
||||
template<typename T>
|
||||
auto operator+( T const &other ) const -> Parser;
|
||||
};
|
||||
|
||||
// Common code and state for Args and Opts
|
||||
@@ -5895,16 +5909,16 @@ namespace detail {
|
||||
class ParserRefImpl : public ComposableParserImpl<DerivedT> {
|
||||
protected:
|
||||
Optionality m_optionality = Optionality::Optional;
|
||||
std::shared_ptr<BoundRefBase> m_ref;
|
||||
std::shared_ptr<BoundRef> m_ref;
|
||||
std::string m_hint;
|
||||
std::string m_description;
|
||||
|
||||
explicit ParserRefImpl( std::shared_ptr<BoundRefBase> const &ref ) : m_ref( ref ) {}
|
||||
explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
ParserRefImpl( T &ref, std::string const &hint )
|
||||
: m_ref( std::make_shared<BoundRef<T>>( ref ) ),
|
||||
: m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
|
||||
m_hint( hint )
|
||||
{}
|
||||
|
||||
@@ -5945,10 +5959,10 @@ namespace detail {
|
||||
|
||||
class ExeName : public ComposableParserImpl<ExeName> {
|
||||
std::shared_ptr<std::string> m_name;
|
||||
std::shared_ptr<BoundRefBase> m_ref;
|
||||
std::shared_ptr<BoundValueRefBase> m_ref;
|
||||
|
||||
template<typename LambdaT>
|
||||
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundRefBase> {
|
||||
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {
|
||||
return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
|
||||
}
|
||||
|
||||
@@ -5956,7 +5970,7 @@ namespace detail {
|
||||
ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
|
||||
|
||||
explicit ExeName( std::string &ref ) : ExeName() {
|
||||
m_ref = std::make_shared<BoundRef<std::string>>( ref );
|
||||
m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
|
||||
}
|
||||
|
||||
template<typename LambdaT>
|
||||
@@ -5999,7 +6013,10 @@ namespace detail {
|
||||
if( token.type != TokenType::Argument )
|
||||
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
|
||||
|
||||
auto result = m_ref->setValue( remainingTokens->token );
|
||||
assert( !m_ref->isFlag() );
|
||||
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
|
||||
|
||||
auto result = valueRef->setValue( remainingTokens->token );
|
||||
if( !result )
|
||||
return InternalParseResult( result );
|
||||
else
|
||||
@@ -6073,19 +6090,21 @@ namespace detail {
|
||||
auto const &token = *remainingTokens;
|
||||
if( isMatch(token.token ) ) {
|
||||
if( m_ref->isFlag() ) {
|
||||
auto result = m_ref->setFlag( true );
|
||||
auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
|
||||
auto result = flagRef->setFlag( true );
|
||||
if( !result )
|
||||
return InternalParseResult( result );
|
||||
if( result.value() == ParseResultType::ShortCircuitAll )
|
||||
return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
|
||||
} else {
|
||||
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
|
||||
++remainingTokens;
|
||||
if( !remainingTokens )
|
||||
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
|
||||
auto const &argToken = *remainingTokens;
|
||||
if( argToken.type != TokenType::Argument )
|
||||
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
|
||||
auto result = m_ref->setValue( argToken.token );
|
||||
auto result = valueRef->setValue( argToken.token );
|
||||
if( !result )
|
||||
return InternalParseResult( result );
|
||||
if( result.value() == ParseResultType::ShortCircuitAll )
|
||||
@@ -6161,6 +6180,12 @@ namespace detail {
|
||||
return Parser( *this ) |= other;
|
||||
}
|
||||
|
||||
// Forward deprecated interface with '+' instead of '|'
|
||||
template<typename T>
|
||||
auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
|
||||
template<typename T>
|
||||
auto operator+( T const &other ) const -> Parser { return operator|( other ); }
|
||||
|
||||
auto getHelpColumns() const -> std::vector<HelpColumns> {
|
||||
std::vector<HelpColumns> cols;
|
||||
for (auto const &o : m_options) {
|
||||
@@ -6200,6 +6225,8 @@ namespace detail {
|
||||
for( auto const &cols : rows )
|
||||
optWidth = (std::max)(optWidth, cols.left.size() + 2);
|
||||
|
||||
optWidth = (std::min)(optWidth, consoleWidth/2);
|
||||
|
||||
for( auto const &cols : rows ) {
|
||||
auto row =
|
||||
TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
|
||||
@@ -6690,8 +6717,12 @@ namespace {
|
||||
case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
|
||||
case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
|
||||
case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
|
||||
case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
|
||||
|
||||
case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
|
||||
|
||||
default:
|
||||
CATCH_ERROR( "Unknown colour requested" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6749,8 +6780,10 @@ namespace {
|
||||
case Colour::BrightRed: return setColour( "[1;31m" );
|
||||
case Colour::BrightGreen: return setColour( "[1;32m" );
|
||||
case Colour::BrightWhite: return setColour( "[1;37m" );
|
||||
case Colour::BrightYellow: return setColour( "[1;33m" );
|
||||
|
||||
case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
|
||||
default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
|
||||
}
|
||||
}
|
||||
static IColourImpl* instance() {
|
||||
@@ -7086,6 +7119,17 @@ namespace Catch {
|
||||
return Catch::Detail::stringify( [exception description] );
|
||||
}
|
||||
#else
|
||||
// Compiling a mixed mode project with MSVC means that CLR
|
||||
// exceptions will be caught in (...) as well. However, these
|
||||
// do not fill-in std::current_exception and thus lead to crash
|
||||
// when attempting rethrow.
|
||||
// /EHa switch also causes structured exceptions to be caught
|
||||
// here, but they fill-in current_exception properly, so
|
||||
// at worst the output should be a little weird, instead of
|
||||
// causing a crash.
|
||||
if (std::current_exception() == nullptr) {
|
||||
return "Non C++ exception. Possibly a CLR exception.";
|
||||
}
|
||||
return tryTranslators();
|
||||
#endif
|
||||
}
|
||||
@@ -7121,12 +7165,14 @@ namespace Catch {
|
||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#endif
|
||||
|
||||
#if (defined(CATCH_PLATFORM_WINDOWS) && defined(CATCH_CONFIG_WINDOWS_SEH)) || defined(CATCH_CONFIG_POSIX_SIGNALS)
|
||||
namespace {
|
||||
// Report the error condition
|
||||
void reportFatal( char const * const message ) {
|
||||
Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
||||
|
||||
@@ -7950,6 +7996,13 @@ namespace Matchers {
|
||||
// end catch_matchers_string.cpp
|
||||
// start catch_message.cpp
|
||||
|
||||
// start catch_uncaught_exceptions.h
|
||||
|
||||
namespace Catch {
|
||||
bool uncaught_exceptions();
|
||||
} // end namespace Catch
|
||||
|
||||
// end catch_uncaught_exceptions.h
|
||||
namespace Catch {
|
||||
|
||||
MessageInfo::MessageInfo( std::string const& _macroName,
|
||||
@@ -7988,19 +8041,11 @@ namespace Catch {
|
||||
getResultCapture().pushScopedMessage( m_info );
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17
|
||||
#endif
|
||||
ScopedMessage::~ScopedMessage() {
|
||||
if ( !std::uncaught_exception() ){
|
||||
if ( !uncaught_exceptions() ){
|
||||
getResultCapture().popScopedMessage(m_info);
|
||||
}
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // end namespace Catch
|
||||
// end catch_message.cpp
|
||||
// start catch_random_number_generator.cpp
|
||||
@@ -8640,12 +8685,13 @@ namespace Catch {
|
||||
handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
|
||||
}
|
||||
}
|
||||
Counts assertions = m_totals.assertions - prevAssertions;
|
||||
bool missingAssertions = testForMissingAssertions(assertions);
|
||||
|
||||
m_testCaseTracker->close();
|
||||
handleUnfinishedSections();
|
||||
m_messages.clear();
|
||||
|
||||
Counts assertions = m_totals.assertions - prevAssertions;
|
||||
bool missingAssertions = testForMissingAssertions(assertions);
|
||||
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
|
||||
m_reporter->sectionEnded(testCaseSectionStats);
|
||||
}
|
||||
@@ -8792,22 +8838,15 @@ namespace Catch {
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17
|
||||
#endif
|
||||
Section::~Section() {
|
||||
if( m_sectionIncluded ) {
|
||||
SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
|
||||
if( std::uncaught_exception() )
|
||||
if( uncaught_exceptions() )
|
||||
getResultCapture().sectionEndedEarly( endInfo );
|
||||
else
|
||||
getResultCapture().sectionEnded( endInfo );
|
||||
}
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// This indicates whether the section should be executed or not
|
||||
Section::operator bool() const {
|
||||
@@ -9148,6 +9187,9 @@ namespace Catch {
|
||||
if( Option<std::size_t> listed = list( config() ) )
|
||||
return static_cast<int>( *listed );
|
||||
|
||||
// Note that on unices only the lower 8 bits are usually used, clamping
|
||||
// the return value to 255 prevents false negative when some multiple
|
||||
// of 256 tests has failed
|
||||
return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) );
|
||||
}
|
||||
catch( std::exception& ex ) {
|
||||
@@ -9455,6 +9497,13 @@ namespace Catch {
|
||||
|
||||
#include <ostream>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
namespace {
|
||||
const uint32_t byte_2_lead = 0xC0;
|
||||
const uint32_t byte_3_lead = 0xE0;
|
||||
const uint32_t byte_4_lead = 0xF0;
|
||||
}
|
||||
|
||||
namespace Catch {
|
||||
StringRef::StringRef( char const* rawChars ) noexcept
|
||||
@@ -9519,13 +9568,12 @@ namespace Catch {
|
||||
// Make adjustments for uft encodings
|
||||
for( size_type i=0; i < m_size; ++i ) {
|
||||
char c = m_start[i];
|
||||
if( ( c & 0b11000000 ) == 0b11000000 ) {
|
||||
if( ( c & 0b11100000 ) == 0b11000000 )
|
||||
if( ( c & byte_2_lead ) == byte_2_lead ) {
|
||||
noChars--;
|
||||
if (( c & byte_3_lead ) == byte_3_lead )
|
||||
noChars--;
|
||||
if( ( c & byte_4_lead ) == byte_4_lead )
|
||||
noChars--;
|
||||
else if( ( c & 0b11110000 ) == 0b11100000 )
|
||||
noChars-=2;
|
||||
else if( ( c & 0b11111000 ) == 0b11110000 )
|
||||
noChars-=3;
|
||||
}
|
||||
}
|
||||
return noChars;
|
||||
@@ -10657,6 +10705,20 @@ namespace Catch {
|
||||
|
||||
}
|
||||
// end catch_totals.cpp
|
||||
// start catch_uncaught_exceptions.cpp
|
||||
|
||||
#include <exception>
|
||||
|
||||
namespace Catch {
|
||||
bool uncaught_exceptions() {
|
||||
#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
|
||||
return std::uncaught_exceptions() > 0;
|
||||
#else
|
||||
return std::uncaught_exception();
|
||||
#endif
|
||||
}
|
||||
} // end namespace Catch
|
||||
// end catch_uncaught_exceptions.cpp
|
||||
// start catch_version.cpp
|
||||
|
||||
#include <ostream>
|
||||
@@ -10689,7 +10751,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
Version const& libraryVersion() {
|
||||
static Version version( 2, 1, 0, "", 0 );
|
||||
static Version version( 2, 1, 2, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
@@ -11918,7 +11980,7 @@ namespace Catch {
|
||||
m_reporterPrefs.shouldRedirectStdOut = true;
|
||||
}
|
||||
|
||||
JunitReporter::~JunitReporter() {};
|
||||
JunitReporter::~JunitReporter() {}
|
||||
|
||||
std::string JunitReporter::getDescription() {
|
||||
return "Reports test results in an XML format that looks like Ant's junitreport target";
|
||||
|
@@ -10,7 +10,7 @@ class CatchConanTest(ConanFile):
|
||||
settings = "os", "compiler", "arch", "build_type"
|
||||
username = getenv("CONAN_USERNAME", "philsquared")
|
||||
channel = getenv("CONAN_CHANNEL", "testing")
|
||||
requires = "Catch/2.1.0@%s/%s" % (username, channel)
|
||||
requires = "Catch/2.1.2@%s/%s" % (username, channel)
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
|
106
third_party/clara.hpp
vendored
106
third_party/clara.hpp
vendored
@@ -1,5 +1,11 @@
|
||||
// v1.0-develop.2
|
||||
// See https://github.com/philsquared/Clara
|
||||
// Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See https://github.com/philsquared/Clara for more details
|
||||
|
||||
// Clara v1.1.2
|
||||
|
||||
#ifndef CLARA_HPP_INCLUDED
|
||||
#define CLARA_HPP_INCLUDED
|
||||
@@ -370,7 +376,7 @@ namespace detail {
|
||||
template<typename ClassT, typename ReturnT, typename ArgT>
|
||||
struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
|
||||
static const bool isValid = true;
|
||||
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;;
|
||||
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
|
||||
using ReturnType = ReturnT;
|
||||
};
|
||||
|
||||
@@ -535,7 +541,7 @@ namespace detail {
|
||||
return *this;
|
||||
}
|
||||
|
||||
~ResultValueBase() {
|
||||
~ResultValueBase() override {
|
||||
if( m_type == Ok )
|
||||
m_value.~T();
|
||||
}
|
||||
@@ -573,7 +579,7 @@ namespace detail {
|
||||
auto errorMessage() const -> std::string { return m_errorMessage; }
|
||||
|
||||
protected:
|
||||
virtual void enforceOk() const {
|
||||
void enforceOk() const override {
|
||||
// !TBD: If no exceptions, std::terminate here or something
|
||||
switch( m_type ) {
|
||||
case ResultBase::LogicError:
|
||||
@@ -653,46 +659,32 @@ namespace detail {
|
||||
return ParserResult::ok( ParseResultType::Matched );
|
||||
}
|
||||
|
||||
struct BoundRefBase {
|
||||
BoundRefBase() = default;
|
||||
BoundRefBase( BoundRefBase const & ) = delete;
|
||||
BoundRefBase( BoundRefBase && ) = delete;
|
||||
BoundRefBase &operator=( BoundRefBase const & ) = delete;
|
||||
BoundRefBase &operator=( BoundRefBase && ) = delete;
|
||||
struct NonCopyable {
|
||||
NonCopyable() = default;
|
||||
NonCopyable( NonCopyable const & ) = delete;
|
||||
NonCopyable( NonCopyable && ) = delete;
|
||||
NonCopyable &operator=( NonCopyable const & ) = delete;
|
||||
NonCopyable &operator=( NonCopyable && ) = delete;
|
||||
};
|
||||
|
||||
virtual ~BoundRefBase() = default;
|
||||
|
||||
virtual auto isFlag() const -> bool = 0;
|
||||
struct BoundRef : NonCopyable {
|
||||
virtual ~BoundRef() = default;
|
||||
virtual auto isContainer() const -> bool { return false; }
|
||||
virtual auto isFlag() const -> bool { return false; }
|
||||
};
|
||||
struct BoundValueRefBase : BoundRef {
|
||||
virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
|
||||
};
|
||||
struct BoundFlagRefBase : BoundRef {
|
||||
virtual auto setFlag( bool flag ) -> ParserResult = 0;
|
||||
};
|
||||
|
||||
struct BoundValueRefBase : BoundRefBase {
|
||||
auto isFlag() const -> bool override { return false; }
|
||||
|
||||
auto setFlag( bool ) -> ParserResult override {
|
||||
return ParserResult::logicError( "Flags can only be set on boolean fields" );
|
||||
}
|
||||
};
|
||||
|
||||
struct BoundFlagRefBase : BoundRefBase {
|
||||
auto isFlag() const -> bool override { return true; }
|
||||
|
||||
auto setValue( std::string const &arg ) -> ParserResult override {
|
||||
bool flag;
|
||||
auto result = convertInto( arg, flag );
|
||||
if( result )
|
||||
setFlag( flag );
|
||||
return result;
|
||||
}
|
||||
virtual auto isFlag() const -> bool { return true; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct BoundRef : BoundValueRefBase {
|
||||
struct BoundValueRef : BoundValueRefBase {
|
||||
T &m_ref;
|
||||
|
||||
explicit BoundRef( T &ref ) : m_ref( ref ) {}
|
||||
explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
|
||||
|
||||
auto setValue( std::string const &arg ) -> ParserResult override {
|
||||
return convertInto( arg, m_ref );
|
||||
@@ -700,10 +692,10 @@ namespace detail {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct BoundRef<std::vector<T>> : BoundValueRefBase {
|
||||
struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
|
||||
std::vector<T> &m_ref;
|
||||
|
||||
explicit BoundRef( std::vector<T> &ref ) : m_ref( ref ) {}
|
||||
explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
|
||||
|
||||
auto isContainer() const -> bool override { return true; }
|
||||
|
||||
@@ -748,12 +740,12 @@ namespace detail {
|
||||
|
||||
template<typename ArgType, typename L>
|
||||
inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
|
||||
ArgType temp;
|
||||
ArgType temp{};
|
||||
auto result = convertInto( arg, temp );
|
||||
return !result
|
||||
? result
|
||||
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template<typename L>
|
||||
@@ -803,6 +795,9 @@ namespace detail {
|
||||
public:
|
||||
template<typename T>
|
||||
auto operator|( T const &other ) const -> Parser;
|
||||
|
||||
template<typename T>
|
||||
auto operator+( T const &other ) const -> Parser;
|
||||
};
|
||||
|
||||
// Common code and state for Args and Opts
|
||||
@@ -810,16 +805,16 @@ namespace detail {
|
||||
class ParserRefImpl : public ComposableParserImpl<DerivedT> {
|
||||
protected:
|
||||
Optionality m_optionality = Optionality::Optional;
|
||||
std::shared_ptr<BoundRefBase> m_ref;
|
||||
std::shared_ptr<BoundRef> m_ref;
|
||||
std::string m_hint;
|
||||
std::string m_description;
|
||||
|
||||
explicit ParserRefImpl( std::shared_ptr<BoundRefBase> const &ref ) : m_ref( ref ) {}
|
||||
explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
ParserRefImpl( T &ref, std::string const &hint )
|
||||
: m_ref( std::make_shared<BoundRef<T>>( ref ) ),
|
||||
: m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
|
||||
m_hint( hint )
|
||||
{}
|
||||
|
||||
@@ -860,10 +855,10 @@ namespace detail {
|
||||
|
||||
class ExeName : public ComposableParserImpl<ExeName> {
|
||||
std::shared_ptr<std::string> m_name;
|
||||
std::shared_ptr<BoundRefBase> m_ref;
|
||||
std::shared_ptr<BoundValueRefBase> m_ref;
|
||||
|
||||
template<typename LambdaT>
|
||||
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundRefBase> {
|
||||
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {
|
||||
return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
|
||||
}
|
||||
|
||||
@@ -871,7 +866,7 @@ namespace detail {
|
||||
ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
|
||||
|
||||
explicit ExeName( std::string &ref ) : ExeName() {
|
||||
m_ref = std::make_shared<BoundRef<std::string>>( ref );
|
||||
m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
|
||||
}
|
||||
|
||||
template<typename LambdaT>
|
||||
@@ -914,7 +909,10 @@ namespace detail {
|
||||
if( token.type != TokenType::Argument )
|
||||
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
|
||||
|
||||
auto result = m_ref->setValue( remainingTokens->token );
|
||||
assert( !m_ref->isFlag() );
|
||||
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
|
||||
|
||||
auto result = valueRef->setValue( remainingTokens->token );
|
||||
if( !result )
|
||||
return InternalParseResult( result );
|
||||
else
|
||||
@@ -988,19 +986,21 @@ namespace detail {
|
||||
auto const &token = *remainingTokens;
|
||||
if( isMatch(token.token ) ) {
|
||||
if( m_ref->isFlag() ) {
|
||||
auto result = m_ref->setFlag( true );
|
||||
auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
|
||||
auto result = flagRef->setFlag( true );
|
||||
if( !result )
|
||||
return InternalParseResult( result );
|
||||
if( result.value() == ParseResultType::ShortCircuitAll )
|
||||
return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
|
||||
} else {
|
||||
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
|
||||
++remainingTokens;
|
||||
if( !remainingTokens )
|
||||
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
|
||||
auto const &argToken = *remainingTokens;
|
||||
if( argToken.type != TokenType::Argument )
|
||||
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
|
||||
auto result = m_ref->setValue( argToken.token );
|
||||
auto result = valueRef->setValue( argToken.token );
|
||||
if( !result )
|
||||
return InternalParseResult( result );
|
||||
if( result.value() == ParseResultType::ShortCircuitAll )
|
||||
@@ -1077,6 +1077,12 @@ namespace detail {
|
||||
return Parser( *this ) |= other;
|
||||
}
|
||||
|
||||
// Forward deprecated interface with '+' instead of '|'
|
||||
template<typename T>
|
||||
auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
|
||||
template<typename T>
|
||||
auto operator+( T const &other ) const -> Parser { return operator|( other ); }
|
||||
|
||||
auto getHelpColumns() const -> std::vector<HelpColumns> {
|
||||
std::vector<HelpColumns> cols;
|
||||
for (auto const &o : m_options) {
|
||||
@@ -1116,6 +1122,8 @@ namespace detail {
|
||||
for( auto const &cols : rows )
|
||||
optWidth = (std::max)(optWidth, cols.left.size() + 2);
|
||||
|
||||
optWidth = (std::min)(optWidth, consoleWidth/2);
|
||||
|
||||
for( auto const &cols : rows ) {
|
||||
auto row =
|
||||
TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
|
||||
|
Reference in New Issue
Block a user