mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-13 00:45:39 +02:00
Compare commits
109 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d2a130f243 | ||
![]() |
7be8a41adf | ||
![]() |
021fcee636 | ||
![]() |
3a47b8b072 | ||
![]() |
2771a8ee9a | ||
![]() |
7abd7db2c8 | ||
![]() |
88d7b8da25 | ||
![]() |
df0b0e64e1 | ||
![]() |
4c7b7d04fe | ||
![]() |
90988f578c | ||
![]() |
e5fe3e877a | ||
![]() |
6c5c4c43a0 | ||
![]() |
c323658483 | ||
![]() |
db570b7e24 | ||
![]() |
0074926e5c | ||
![]() |
6496c51c95 | ||
![]() |
3dd523bdf5 | ||
![]() |
8d5d49299b | ||
![]() |
d0287e3b56 | ||
![]() |
dd99a66cf4 | ||
![]() |
ae590fe216 | ||
![]() |
7f791fa08f | ||
![]() |
0510d4755f | ||
![]() |
e92b9c07c3 | ||
![]() |
88a6ff0b65 | ||
![]() |
9e7c281e6e | ||
![]() |
64be2ad96c | ||
![]() |
c651f239f0 | ||
![]() |
43769a19f7 | ||
![]() |
200d3ad824 | ||
![]() |
aa7b0c9104 | ||
![]() |
375f2052bd | ||
![]() |
dc6b83bec9 | ||
![]() |
f00257e374 | ||
![]() |
414dcae34a | ||
![]() |
d2d8455b57 | ||
![]() |
ab30621138 | ||
![]() |
1ca8f43b01 | ||
![]() |
dfb83f20e9 | ||
![]() |
319bddd5b8 | ||
![]() |
931441251e | ||
![]() |
ea1f326261 | ||
![]() |
3641706923 | ||
![]() |
3b801c4fda | ||
![]() |
e11508b48a | ||
![]() |
886d799b79 | ||
![]() |
8b78087412 | ||
![]() |
6c99b04c87 | ||
![]() |
0a34cc201e | ||
![]() |
11c89a5f7d | ||
![]() |
dc3e7f9cf7 | ||
![]() |
d14b7563c2 | ||
![]() |
a3d3a633b2 | ||
![]() |
8d4796309f | ||
![]() |
552589f25b | ||
![]() |
95c849f613 | ||
![]() |
352853ed7e | ||
![]() |
b11175548a | ||
![]() |
d38f782995 | ||
![]() |
dc8a8e6371 | ||
![]() |
9d1858b195 | ||
![]() |
1d1f8dc992 | ||
![]() |
1466686ade | ||
![]() |
93db01c647 | ||
![]() |
2e285b9579 | ||
![]() |
d2ddb997a7 | ||
![]() |
865d5f59b4 | ||
![]() |
05cd05743a | ||
![]() |
950ccf4749 | ||
![]() |
cf4b7eead9 | ||
![]() |
7b6e49d795 | ||
![]() |
0c5df42c28 | ||
![]() |
4e57661919 | ||
![]() |
5a8f9c84dd | ||
![]() |
f988b4eb35 | ||
![]() |
c8d765a575 | ||
![]() |
da783abee9 | ||
![]() |
c0267e5c20 | ||
![]() |
bb84f0788a | ||
![]() |
e84768fff1 | ||
![]() |
31673ee0ca | ||
![]() |
34d7a33574 | ||
![]() |
082c3b84bc | ||
![]() |
ef2e112561 | ||
![]() |
a90305f857 | ||
![]() |
543c9d3a67 | ||
![]() |
ca8470fbad | ||
![]() |
355b3f9952 | ||
![]() |
7cbd0b587a | ||
![]() |
2f15ccd4d3 | ||
![]() |
8f3fc15b73 | ||
![]() |
e13d9cab02 | ||
![]() |
414e2fa946 | ||
![]() |
b5ef68b044 | ||
![]() |
681f5daa13 | ||
![]() |
3b6fda3c1b | ||
![]() |
1b2fa601c6 | ||
![]() |
39bfc6e82b | ||
![]() |
ba6d33fb8c | ||
![]() |
4be81d3588 | ||
![]() |
5201e92564 | ||
![]() |
5e484862f2 | ||
![]() |
5713381d06 | ||
![]() |
1ab6be30a2 | ||
![]() |
126850e76b | ||
![]() |
5e8df1c384 | ||
![]() |
44dbda9f01 | ||
![]() |
ca2455e6e6 | ||
![]() |
42213d4c31 |
7
.gitattributes
vendored
7
.gitattributes
vendored
@@ -10,6 +10,13 @@
|
||||
# Windows specific files should retain windows line-endings
|
||||
*.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
|
||||
|
167
.travis.yml
167
.travis.yml
@@ -1,12 +1,17 @@
|
||||
language: cpp
|
||||
sudo: false
|
||||
|
||||
branches:
|
||||
except:
|
||||
- /dev-appveyor.*/
|
||||
|
||||
common_sources: &all_sources
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty
|
||||
- llvm-toolchain-trusty-3.9
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- llvm-toolchain-trusty-5.0
|
||||
- llvm-toolchain-trusty-6.0
|
||||
|
||||
matrix:
|
||||
include:
|
||||
@@ -17,145 +22,169 @@ matrix:
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['valgrind', 'lcov', 'clang-3.5']
|
||||
env: COMPILER='clang++-3.5' VALGRIND=1
|
||||
packages: ['clang-3.5']
|
||||
env: COMPILER='clang++-3.5'
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['valgrind', 'lcov', 'clang-3.6']
|
||||
env: COMPILER='clang++-3.6' VALGRIND=1
|
||||
packages: ['clang-3.6']
|
||||
env: COMPILER='clang++-3.6'
|
||||
|
||||
# Travis's containers do not seem to have Clang 3.7 in apt, no matter what sources I add.
|
||||
# - os: linux
|
||||
# compiler: clang
|
||||
# addons:
|
||||
# apt:
|
||||
# sources: *all_sources
|
||||
# packages: ['valgrind', 'clang-3.7']
|
||||
# env: COMPILER='clang++-3.7' VALGRIND=1
|
||||
# Clang 3.7 is intentionally skipped as we cannot get it easily on
|
||||
# TravisCI container
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['valgrind', 'lcov', 'clang-3.8']
|
||||
env: COMPILER='clang++-3.8' VALGRIND=1
|
||||
packages: ['lcov', 'clang-3.8']
|
||||
env: COMPILER='clang++-3.8'
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['clang-3.9', 'valgrind', 'lcov']
|
||||
env: COMPILER='clang++-3.9' VALGRIND=1
|
||||
packages: ['clang-3.9']
|
||||
env: COMPILER='clang++-3.9'
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['clang-4.0', 'valgrind', 'lcov']
|
||||
env: COMPILER='clang++-4.0' VALGRIND=1
|
||||
packages: ['clang-4.0']
|
||||
env: COMPILER='clang++-4.0'
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['clang-5.0', 'valgrind', 'lcov']
|
||||
env: COMPILER='clang++-5.0' VALGRIND=1
|
||||
packages: ['clang-5.0']
|
||||
env: COMPILER='clang++-5.0'
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['clang-6.0']
|
||||
env: COMPILER='clang++-6.0'
|
||||
|
||||
# 2/ Linux GCC Builds
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['valgrind', 'lcov', 'g++-4.8']
|
||||
env: COMPILER='g++-4.8' VALGRIND=1
|
||||
sources: *all_sources
|
||||
packages: ['g++-4.8']
|
||||
env: COMPILER='g++-4.8'
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['valgrind', 'lcov', 'g++-4.9']
|
||||
env: COMPILER='g++-4.9' VALGRIND=1
|
||||
packages: ['g++-4.9']
|
||||
env: COMPILER='g++-4.9'
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['valgrind', 'lcov', 'g++-5']
|
||||
env: COMPILER='g++-5' VALGRIND=1
|
||||
packages: ['g++-5']
|
||||
env: COMPILER='g++-5'
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: &gcc6
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['valgrind', 'lcov', 'g++-6']
|
||||
env: COMPILER='g++-6' VALGRIND=1
|
||||
packages: ['g++-6']
|
||||
env: COMPILER='g++-6'
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: &gcc7
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['valgrind', 'lcov', 'g++-7']
|
||||
env: COMPILER='g++-7' VALGRIND=1
|
||||
packages: ['g++-7']
|
||||
env: COMPILER='g++-7'
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: &gcc8
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['g++-8']
|
||||
env: COMPILER='g++-8'
|
||||
|
||||
# 3b/ Linux C++14 Clang builds
|
||||
# Note that we need newer libstdc++ for C++14 support
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages: ['clang-3.8', 'valgrind', 'lcov', 'libstdc++-6-dev']
|
||||
packages: ['clang-3.8', 'libstdc++-6-dev']
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty
|
||||
env: COMPILER='clang++-3.8' CPP14=1 VALGRIND=1
|
||||
env: COMPILER='clang++-3.8' CPP14=1
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['clang-3.9', 'valgrind', 'lcov', 'libstdc++-6-dev']
|
||||
env: COMPILER='clang++-3.9' CPP14=1 VALGRIND=1
|
||||
packages: ['clang-3.9', 'libstdc++-6-dev']
|
||||
env: COMPILER='clang++-3.9' CPP14=1
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['clang-4.0', 'valgrind', 'lcov', 'libstdc++-6-dev']
|
||||
env: COMPILER='clang++-4.0' CPP14=1 VALGRIND=1
|
||||
packages: ['clang-4.0', 'libstdc++-6-dev']
|
||||
env: COMPILER='clang++-4.0' CPP14=1
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['clang-5.0', 'valgrind', 'lcov', 'libstdc++-6-dev']
|
||||
env: COMPILER='clang++-5.0' CPP14=1 VALGRIND=1
|
||||
packages: ['clang-5.0', 'libstdc++-6-dev']
|
||||
env: COMPILER='clang++-5.0' CPP14=1
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['clang-6.0', 'libstdc++-6-dev']
|
||||
env: COMPILER='clang++-6.0' CPP14=1
|
||||
|
||||
|
||||
# 4a/ Linux C++14 GCC builds
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: *gcc6
|
||||
env: COMPILER='g++-6' CPP14=1 VALGRIND=1
|
||||
env: COMPILER='g++-6' CPP14=1
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: *gcc7
|
||||
env: COMPILER='g++-7' CPP14=1 VALGRIND=1
|
||||
env: COMPILER='g++-7' CPP14=1
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: *gcc8
|
||||
env: COMPILER='g++-8' CPP14=1
|
||||
|
||||
# 5/ OSX Clang Builds
|
||||
- os: osx
|
||||
@@ -181,8 +210,39 @@ matrix:
|
||||
- os: osx
|
||||
osx_image: xcode9.1
|
||||
compiler: clang
|
||||
env: COMPILER='clang++' USE_CPP14=1
|
||||
env: COMPILER='clang++' CPP14=1
|
||||
|
||||
# 6/ Special builds -- examples, coverage, valgrind, etc.
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['lcov', 'g++-7']
|
||||
env: COMPILER='g++-7' CPP14=1 EXAMPLES=1 COVERAGE=1
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages: ['clang-3.8', 'lcov']
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty
|
||||
env: COMPILER='clang++-3.8' EXAMPLES=1 COVERAGE=1
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: *all_sources
|
||||
packages: ['valgrind', 'lcov', 'g++-7']
|
||||
env: COMPILER='g++-7' CPP14=1 VALGRIND=1
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.1
|
||||
compiler: clang
|
||||
env: COMPILER='clang++' CPP14=1 EXAMPLES=1 COVERAGE=1
|
||||
|
||||
install:
|
||||
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||
@@ -202,25 +262,24 @@ before_script:
|
||||
# Regenerate single header file, so it is tested in the examples...
|
||||
- python scripts/generateSingleHeader.py
|
||||
|
||||
- |
|
||||
# Use Debug builds for running Valgrind and building examples
|
||||
cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=ON -DCATCH_ENABLE_COVERAGE=ON
|
||||
- cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=${EXAMPLES} -DCATCH_ENABLE_COVERAGE=${COVERAGE}
|
||||
# Don't bother with release build for coverage build
|
||||
cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
|
||||
- cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
|
||||
|
||||
|
||||
script:
|
||||
- |
|
||||
cd Build-Debug
|
||||
make -j 2
|
||||
CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
|
||||
- cd Build-Debug
|
||||
- make -j 2
|
||||
- CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
|
||||
# Coverage collection does not work for OS X atm
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]] && [[ "${COVERAGE}" == "1" ]]; then
|
||||
make gcov
|
||||
make lcov
|
||||
bash <(curl -s https://codecov.io/bash) -X gcov || echo "Codecov did not collect coverage reports"
|
||||
fi
|
||||
# Go to release build
|
||||
cd ../Build-Release
|
||||
make -j 2
|
||||
CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
|
||||
- # Go to release build
|
||||
- cd ../Build-Release
|
||||
- make -j 2
|
||||
- CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
|
||||
|
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
# detect if Catch is being bundled,
|
||||
# disable testsuite in that case
|
||||
@@ -6,7 +6,7 @@ if(NOT DEFINED PROJECT_NAME)
|
||||
set(NOT_SUBPROJECT ON)
|
||||
endif()
|
||||
|
||||
project(Catch2 LANGUAGES CXX VERSION 2.1.1)
|
||||
project(Catch2 LANGUAGES CXX VERSION 2.2.3)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
@@ -152,12 +152,14 @@ set(INTERNAL_HEADERS
|
||||
${HEADER_DIR}/internal/catch_list.h
|
||||
${HEADER_DIR}/internal/catch_matchers.h
|
||||
${HEADER_DIR}/internal/catch_matchers_floating.h
|
||||
${HEADER_DIR}/internal/catch_matchers_generic.hpp
|
||||
${HEADER_DIR}/internal/catch_matchers_string.h
|
||||
${HEADER_DIR}/internal/catch_matchers_vector.h
|
||||
${HEADER_DIR}/internal/catch_message.h
|
||||
${HEADER_DIR}/internal/catch_objc.hpp
|
||||
${HEADER_DIR}/internal/catch_objc_arc.hpp
|
||||
${HEADER_DIR}/internal/catch_option.hpp
|
||||
${HEADER_DIR}/internal/catch_output_redirect.h
|
||||
${HEADER_DIR}/internal/catch_platform.h
|
||||
${HEADER_DIR}/internal/catch_random_number_generator.h
|
||||
${HEADER_DIR}/internal/catch_reenable_warnings.h
|
||||
@@ -185,8 +187,10 @@ set(INTERNAL_HEADERS
|
||||
${HEADER_DIR}/internal/catch_test_spec_parser.h
|
||||
${HEADER_DIR}/internal/catch_text.h
|
||||
${HEADER_DIR}/internal/catch_timer.h
|
||||
${HEADER_DIR}/internal/catch_to_string.hpp
|
||||
${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
|
||||
@@ -220,8 +224,10 @@ set(IMPL_SOURCES
|
||||
${HEADER_DIR}/internal/catch_leak_detector.cpp
|
||||
${HEADER_DIR}/internal/catch_matchers.cpp
|
||||
${HEADER_DIR}/internal/catch_matchers_floating.cpp
|
||||
${HEADER_DIR}/internal/catch_matchers_generic.cpp
|
||||
${HEADER_DIR}/internal/catch_matchers_string.cpp
|
||||
${HEADER_DIR}/internal/catch_message.cpp
|
||||
${HEADER_DIR}/internal/catch_output_redirect.cpp
|
||||
${HEADER_DIR}/internal/catch_registry_hub.cpp
|
||||
${HEADER_DIR}/internal/catch_interfaces_reporter.cpp
|
||||
${HEADER_DIR}/internal/catch_random_number_generator.cpp
|
||||
@@ -247,6 +253,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
|
||||
@@ -261,7 +268,7 @@ set(REPORTER_HEADERS
|
||||
${HEADER_DIR}/reporters/catch_reporter_compact.h
|
||||
${HEADER_DIR}/reporters/catch_reporter_console.h
|
||||
${HEADER_DIR}/reporters/catch_reporter_junit.h
|
||||
${HEADER_DIR}/reporters/catch_reporter_multi.h
|
||||
${HEADER_DIR}/reporters/catch_reporter_listening.h
|
||||
${HEADER_DIR}/reporters/catch_reporter_tap.hpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_xml.h
|
||||
@@ -271,7 +278,7 @@ set(REPORTER_SOURCES
|
||||
${HEADER_DIR}/reporters/catch_reporter_compact.cpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_console.cpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_junit.cpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_multi.cpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_listening.cpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_xml.cpp
|
||||
)
|
||||
set(REPORTER_FILES ${REPORTER_HEADERS} ${REPORTER_SOURCES})
|
||||
@@ -328,16 +335,15 @@ if (BUILD_TESTING AND NOT_SUBPROJECT)
|
||||
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 )
|
||||
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" )
|
||||
@@ -346,6 +352,8 @@ if (BUILD_TESTING AND NOT_SUBPROJECT)
|
||||
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()
|
||||
|
||||
|
||||
@@ -354,18 +362,29 @@ if (BUILD_TESTING AND NOT_SUBPROJECT)
|
||||
add_test(NAME RunTests COMMAND $<TARGET_FILE:SelfTest>)
|
||||
|
||||
add_test(NAME ListTests COMMAND $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
|
||||
set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases")
|
||||
set_tests_properties(ListTests PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "[0-9]+ test cases"
|
||||
FAIL_REGULAR_EXPRESSION "Hidden Test"
|
||||
)
|
||||
|
||||
add_test(NAME ListTags COMMAND $<TARGET_FILE:SelfTest> --list-tags)
|
||||
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
|
||||
set_tests_properties(ListTags PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "[0-9]+ tags"
|
||||
FAIL_REGULAR_EXPRESSION "[.]")
|
||||
|
||||
add_test(NAME ListReporters COMMAND $<TARGET_FILE:SelfTest> --list-reporters)
|
||||
set_tests_properties(ListReporters PROPERTIES PASS_REGULAR_EXPRESSION "Available reporters:")
|
||||
|
||||
add_test(NAME ListTestNamesOnly COMMAND $<TARGET_FILE:SelfTest> --list-test-names-only)
|
||||
set_tests_properties(ListTestNamesOnly PROPERTIES PASS_REGULAR_EXPRESSION "Regex string matcher")
|
||||
set_tests_properties(ListTestNamesOnly PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "Regex string matcher"
|
||||
FAIL_REGULAR_EXPRESSION "Hidden Test")
|
||||
|
||||
add_test(NAME NoAssertions COMMAND $<TARGET_FILE:SelfTest> -w NoAssertions)
|
||||
set_tests_properties(NoAssertions PROPERTIES PASS_REGULAR_EXPRESSION "No assertions in test case")
|
||||
|
||||
add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> -w NoTests "___nonexistent_test___")
|
||||
set_tests_properties(NoTest PROPERTIES PASS_REGULAR_EXPRESSION "No test cases matched")
|
||||
|
||||
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
|
||||
add_test(NAME ApprovalTests COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
|
||||
@@ -403,3 +422,38 @@ 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(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_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/TpIcJaLaH4WrKlhS)
|
||||
[](https://wandbox.org/permlink/u7qF77qgv9YqOr55)
|
||||
|
||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.1.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.2.3/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||
|
||||
## Catch2 is released!
|
||||
|
||||
|
43
appveyor.yml
43
appveyor.yml
@@ -19,18 +19,53 @@ environment:
|
||||
|
||||
- additional_flags: "/D_UNICODE /DUNICODE"
|
||||
wmain: 1
|
||||
coverage: 0
|
||||
|
||||
# Have a coverage dimension
|
||||
- additional_flags: ""
|
||||
wmain: 0
|
||||
coverage: 1
|
||||
|
||||
# Have an examples dimension
|
||||
- additional_flags: ""
|
||||
wmain: 0
|
||||
examples: 1
|
||||
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- os: Visual Studio 2017
|
||||
exclude:
|
||||
- os: Visual Studio 2015
|
||||
additional_flags: "/permissive- /std:c++latest"
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
- os: Visual Studio 2015
|
||||
additional_flags: "/D_UNICODE /DUNICODE"
|
||||
|
||||
# Exclude unwanted coverage configurations
|
||||
- coverage: 1
|
||||
platform: Win32
|
||||
|
||||
- coverage: 1
|
||||
os: Visual Studio 2015
|
||||
|
||||
- coverage: 1
|
||||
configuration: Release
|
||||
|
||||
# Exclude unwanted examples configurations
|
||||
- examples: 1
|
||||
platform: Win32
|
||||
|
||||
- examples: 1
|
||||
os: Visual Studio 2015
|
||||
|
||||
- examples: 1
|
||||
configuration: Release
|
||||
|
||||
|
||||
install:
|
||||
- ps: if (($env:CONFIGURATION) -eq "Debug" ) { python -m pip install codecov }
|
||||
- ps: if (($env:CONFIGURATION) -eq "Debug" ) { .\misc\installOpenCppCoverage.ps1 }
|
||||
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { python -m pip --disable-pip-version-check install codecov }
|
||||
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { .\misc\installOpenCppCoverage.ps1 }
|
||||
|
||||
# Win32 and x64 are CMake-compatible solution platform names.
|
||||
# This allows us to pass %PLATFORM% to CMake -A.
|
||||
|
@@ -3,4 +3,4 @@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||
Name: Catch
|
||||
Description: Testing library for C++
|
||||
Version: @Catch2_VERSION@
|
||||
Cflags: -I${includedir}
|
||||
Cflags: -I${includedir} -I${includedir}/catch
|
||||
|
18
codecov.yml
18
codecov.yml
@@ -6,17 +6,19 @@ coverage:
|
||||
project:
|
||||
default:
|
||||
threshold: 2%
|
||||
|
||||
codecov:
|
||||
branch: master
|
||||
|
||||
comment:
|
||||
layout: "diff"
|
||||
|
||||
coverage:
|
||||
patch:
|
||||
default:
|
||||
target: 80%
|
||||
ignore:
|
||||
- "projects/SelfTest"
|
||||
- "**/catch_reporter_tap.hpp"
|
||||
- "**/catch_reporter_automake.hpp"
|
||||
- "**/catch_reporter_teamcity.hpp"
|
||||
- "**/external/clara.hpp"
|
||||
|
||||
|
||||
codecov:
|
||||
branch: master
|
||||
|
||||
comment:
|
||||
layout: "diff"
|
||||
|
@@ -4,7 +4,7 @@ from conans import ConanFile
|
||||
|
||||
class CatchConan(ConanFile):
|
||||
name = "Catch"
|
||||
version = "2.1.1"
|
||||
version = "2.2.3"
|
||||
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
|
||||
author = "philsquared"
|
||||
generators = "cmake"
|
||||
|
@@ -50,8 +50,7 @@ string(REPLACE "\n" ";" output "${output}")
|
||||
|
||||
# Parse output
|
||||
foreach(line ${output})
|
||||
# Test name; strip spaces to get just the name...
|
||||
string(REGEX REPLACE " +" "" test "${line}")
|
||||
set(test ${line})
|
||||
# ...and add to script
|
||||
add_command(add_test
|
||||
"${prefix}${test}${suffix}"
|
||||
|
16
contrib/gdbinit
Normal file
16
contrib/gdbinit
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# This file provides a way to skip stepping into Catch code when debugging with gdb.
|
||||
#
|
||||
# With the gdb "skip" command you can tell gdb to skip files or functions during debugging.
|
||||
# see https://xaizek.github.io/2016-05-26/skipping-standard-library-in-gdb/ for an example
|
||||
#
|
||||
# Basically the following line tells gdb to skip all functions containing the
|
||||
# regexp "Catch", which matches the complete Catch namespace.
|
||||
# If you want to skip just some parts of the Catch code you can modify the
|
||||
# regexp accordingly.
|
||||
#
|
||||
# If you want to permanently skip stepping into Catch code copy the following
|
||||
# line into your ~/.gdbinit file
|
||||
#
|
||||
|
||||
skip -rfu Catch
|
16
contrib/lldbinit
Normal file
16
contrib/lldbinit
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# This file provides a way to skip stepping into Catch code when debugging with lldb.
|
||||
#
|
||||
# With the setting "target.process.thread.step-avoid-regexp" you can tell lldb
|
||||
# to skip functions matching the regexp
|
||||
#
|
||||
# Basically the following line tells lldb to skip all functions containing the
|
||||
# regexp "Catch", which matches the complete Catch namespace.
|
||||
# If you want to skip just some parts of the Catch code you can modify the
|
||||
# regexp accordingly.
|
||||
#
|
||||
# If you want to permanently skip stepping into Catch code copy the following
|
||||
# line into your ~/.lldbinit file
|
||||
#
|
||||
|
||||
settings set target.process.thread.step-avoid-regexp Catch
|
@@ -6,10 +6,11 @@
|
||||
[Exceptions](#exceptions)<br>
|
||||
[Matcher expressions](#matcher-expressions)<br>
|
||||
[Thread Safety](#thread-safety)<br>
|
||||
[Expressions with commas](#expressions-with-commas)<br>
|
||||
|
||||
Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc).
|
||||
|
||||
Catch is different. Because it decomposes natural C-style conditional expressions most of these forms are reduced to one or two that you will use all the time. That said there are a rich set of auxilliary macros as well. We'll describe all of these here.
|
||||
Catch is different. Because it decomposes natural C-style conditional expressions most of these forms are reduced to one or two that you will use all the time. That said there are a rich set of auxiliary macros as well. We'll describe all of these here.
|
||||
|
||||
Most of these macros come in two forms:
|
||||
|
||||
@@ -155,6 +156,34 @@ Matchers can be composed using `&&`, `||` and `!` operators.
|
||||
Currently assertions in Catch are not thread safe.
|
||||
For more details, along with workarounds, see the section on [the limitations page](limitations.md#thread-safe-assertions).
|
||||
|
||||
## Expressions with commas
|
||||
|
||||
Because the preprocessor parses code using different rules than the
|
||||
compiler, multiple-argument assertions (e.g. `REQUIRE_THROWS_AS`) have
|
||||
problems with commas inside the provided expressions. As an example
|
||||
`REQUIRE_THROWS_AS(std::pair<int, int>(1, 2), std::invalid_argument);`
|
||||
will fail to compile, because the preprocessor sees 3 arguments provided,
|
||||
but the macro accepts only 2. There are two possible workarounds.
|
||||
|
||||
1) Use typedef:
|
||||
```cpp
|
||||
using int_pair = std::pair<int, int>;
|
||||
REQUIRE_THROWS_AS(int_pair(1, 2), std::invalid_argument);
|
||||
```
|
||||
|
||||
This solution is always applicable, but makes the meaning of the code
|
||||
less clear.
|
||||
|
||||
2) Parenthesize the expression:
|
||||
```cpp
|
||||
TEST_CASE_METHOD((Fixture<int, int>), "foo", "[bar]") {
|
||||
SUCCEED();
|
||||
}
|
||||
```
|
||||
|
||||
This solution is not always applicable, because it might require extra
|
||||
changes on the Catch's side to work.
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md#top)
|
||||
|
@@ -24,6 +24,7 @@
|
||||
[Usage](#usage)<br>
|
||||
[Specify the section to run](#specify-the-section-to-run)<br>
|
||||
[Filenames as tags](#filenames-as-tags)<br>
|
||||
[Override output colouring](#use-colour)<br>
|
||||
|
||||
Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available.
|
||||
Click one of the followings links to take you straight to that option - or scroll on to browse the available options.
|
||||
@@ -57,6 +58,7 @@ Click one of the followings links to take you straight to that option - or scrol
|
||||
<a href="#libidentify"> ` --libidentify`</a><br />
|
||||
<a href="#wait-for-keypress"> ` --wait-for-keypress`</a><br />
|
||||
<a href="#benchmark-resolution-multiple"> ` --benchmark-resolution-multiple`</a><br />
|
||||
<a href="#use-colour"> ` --use-colour`</a><br />
|
||||
|
||||
</br>
|
||||
|
||||
@@ -78,7 +80,7 @@ Wildcards consist of the `*` character at the beginning and/or end of test case
|
||||
|
||||
Test specs are case insensitive.
|
||||
|
||||
If a spec is prefixed with `exclude:` or the `~` character then the pattern matches an exclusion. This means that tests matching the pattern are excluded from the set - even if a prior inclusion spec included them. Subsequent inclusion specs will take precendence, however.
|
||||
If a spec is prefixed with `exclude:` or the `~` character then the pattern matches an exclusion. This means that tests matching the pattern are excluded from the set - even if a prior inclusion spec included them. Subsequent inclusion specs will take precedence, however.
|
||||
Inclusions and exclusions are evaluated in left-to-right order.
|
||||
|
||||
Test case examples:
|
||||
@@ -94,7 +96,7 @@ a* ~ab* abc Matches all tests that start with 'a', except those that
|
||||
</pre>
|
||||
|
||||
Names within square brackets are interpreted as tags.
|
||||
A series of tags form an AND expression wheras a comma-separated sequence forms an OR expression. e.g.:
|
||||
A series of tags form an AND expression whereas a comma-separated sequence forms an OR expression. e.g.:
|
||||
|
||||
<pre>[one][two],[three]</pre>
|
||||
This matches all tests tagged `[one]` and `[two]`, as well as all tests tagged `[three]`
|
||||
@@ -192,9 +194,16 @@ This option transforms tabs and newline characters into ```\t``` and ```\n``` re
|
||||
## Warnings
|
||||
<pre>-w, --warn <warning name></pre>
|
||||
|
||||
Enables reporting of warnings (only one, at time of this writing). If a warning is issued it fails the test.
|
||||
Enables reporting of suspicious test states. There are currently two
|
||||
available warnings
|
||||
|
||||
```
|
||||
NoAssertions // Fail test case / leaf section if no assertions
|
||||
// (e.g. `REQUIRE`) is encountered.
|
||||
NoTests // Return non-zero exit code when no test cases were run
|
||||
// Also calls reporter's noMatchingTestCases method
|
||||
```
|
||||
|
||||
The ony available warning, presently, is ```NoAssertions```. This warning fails a test case, or (leaf) section if no assertions (```REQUIRE```/ ```CHECK``` etc) are encountered.
|
||||
|
||||
<a id="reporting-timings"></a>
|
||||
## Reporting timings
|
||||
@@ -262,7 +271,7 @@ either before running any tests, after running all tests - or both, depending on
|
||||
|
||||
When running benchmarks the clock resolution is estimated. Benchmarks are then run for exponentially increasing
|
||||
numbers of iterations until some multiple of the estimated resolution is exceed. By default that multiple is 100, but
|
||||
it can be overriden here.
|
||||
it can be overridden here.
|
||||
|
||||
<a id="usage"></a>
|
||||
## Usage
|
||||
@@ -322,6 +331,16 @@ filename it is found in, with any extension stripped, prefixed with the `#` char
|
||||
|
||||
So, for example, tests within the file `~\Dev\MyProject\Ferrets.cpp` would be tagged `[#Ferrets]`.
|
||||
|
||||
<a id="use-colour"></a>
|
||||
## Override output colouring
|
||||
<pre>--use-colour <yes|no|auto></pre>
|
||||
|
||||
Catch colours output for terminals, but omits colouring when it detects that
|
||||
output is being sent to a pipe. This is done to avoid interfering with automated
|
||||
processing of output.
|
||||
|
||||
`--use-colour yes` forces coloured output, `--use-colour no` disables coloured
|
||||
output. The default behaviour is `--use-colour auto`.
|
||||
|
||||
---
|
||||
|
||||
|
@@ -7,6 +7,8 @@
|
||||
[Terminal colour](#terminal-colour)<br>
|
||||
[Console width](#console-width)<br>
|
||||
[stdout](#stdout)<br>
|
||||
[Fallback stringifier](#fallback-stringifier)<br>
|
||||
[Default reporter](#default-reporter)<br>
|
||||
[Other toggles](#other-toggles)<br>
|
||||
[Windows header clutter](#windows-header-clutter)<br>
|
||||
[Enabling stringification](#enabling-stringification)<br>
|
||||
@@ -24,7 +26,7 @@ Although Catch is header only it still, internally, maintains a distinction betw
|
||||
|
||||
# Reporter / Listener interfaces
|
||||
|
||||
CATCH_CONFIG_EXTERNAL_INTERFACES // Brings in neccessary headers for Reporter/Listener implementation
|
||||
CATCH_CONFIG_EXTERNAL_INTERFACES // Brings in necessary headers for Reporter/Listener implementation
|
||||
|
||||
Brings in various parts of Catch that are required for user defined Reporters and Listeners. This means that new Reporters and Listeners can be defined in this file as well as in the main file.
|
||||
|
||||
@@ -73,6 +75,56 @@ Catch does not use ```std::cout```, ```std::cerr``` and ```std::clog``` directly
|
||||
This can be useful on certain platforms that do not provide the standard iostreams, such as certain embedded systems.
|
||||
|
||||
|
||||
## Fallback stringifier
|
||||
|
||||
By default, when Catch's stringification machinery has to stringify
|
||||
a type that does not specialize `StringMaker`, does not overload `operator<<`,
|
||||
is not an enumeration and is not a range, it uses `"{?}"`. This can be
|
||||
overriden by defining `CATCH_CONFIG_FALLBACK_STRINGIFIER` to name of a
|
||||
function that should perform the stringification instead.
|
||||
|
||||
All types that do not provide `StringMaker` specialization or `operator<<`
|
||||
overload will be sent to this function (this includes enums and ranges).
|
||||
The provided function must return `std::string` and must accept any type,
|
||||
e.g. via overloading.
|
||||
|
||||
_Note that if the provided function does not handle a type and this type
|
||||
requires to be stringified, the compilation will fail._
|
||||
|
||||
|
||||
## Default reporter
|
||||
|
||||
Catch's default reporter can be changed by defining macro
|
||||
`CATCH_CONFIG_DEFAULT_REPORTER` to string literal naming the desired
|
||||
default reporter.
|
||||
|
||||
This means that defining `CATCH_CONFIG_DEFAULT_REPORTER` to `"console"`
|
||||
is equivalent with the out-of-the-box experience.
|
||||
|
||||
|
||||
## C++11 toggles
|
||||
|
||||
CATCH_CONFIG_CPP11_TO_STRING // Use `std::to_string`
|
||||
|
||||
Because we support platforms whose standard library does not contain
|
||||
`std::to_string`, it is possible to force Catch to use a workaround
|
||||
based on `std::stringstream`. On platforms other than Android,
|
||||
the default is to use `std::to_string`. On Android, the default is to
|
||||
use the `stringstream` workaround. As always, it is possible to override
|
||||
Catch's selection, by defining either `CATCH_CONFIG_CPP11_TO_STRING` or
|
||||
`CATCH_CONFIG_NO_CPP11_TO_STRING`.
|
||||
|
||||
|
||||
## C++17 toggles
|
||||
|
||||
CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS // Use std::uncaught_exceptions instead of std::uncaught_exception
|
||||
|
||||
Catch contains basic compiler/standard detection and attempts to use
|
||||
some C++17 features whenever appropriate. This automatic detection
|
||||
can be manually overridden in both directions, that is, a feature
|
||||
can be enabled by defining the macro in the table above, and disabled
|
||||
by using `_NO_` in the macro, e.g. `CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS`.
|
||||
|
||||
|
||||
## Other toggles
|
||||
|
||||
@@ -84,6 +136,8 @@ This can be useful on certain platforms that do not provide the standard iostrea
|
||||
CATCH_CONFIG_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap
|
||||
CATCH_CONFIG_DISABLE_STRINGIFICATION // Disable stringifying the original expression
|
||||
CATCH_CONFIG_DISABLE // Disables assertions and test case registration
|
||||
CATCH_CONFIG_WCHAR // Enables use of wchart_t
|
||||
CATCH_CONFIG_EXPERIMENTAL_REDIRECT // Enables the new (experimental) way of capturing stdout/stderr
|
||||
|
||||
Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support.
|
||||
|
||||
@@ -91,12 +145,17 @@ Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC,
|
||||
|
||||
`CATCH_CONFIG_WINDOWS_CRTDBG` is off by default. If enabled, Windows's CRT is used to check for memory leaks, and displays them after the tests finish running.
|
||||
|
||||
These toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`.
|
||||
`CATCH_CONFIG_WCHAR` is on by default, but can be disabled. Currently
|
||||
it is only used in support for DJGPP cross-compiler.
|
||||
|
||||
With the exception of `CATCH_CONFIG_EXPERIMENTAL_REDIRECT`,
|
||||
these toggles can be disabled by using `_NO_` form of the toggle,
|
||||
e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`.
|
||||
|
||||
### `CATCH_CONFIG_FAST_COMPILE`
|
||||
Defining this flag speeds up compilation of test files by ~20%, by making 2 changes:
|
||||
* The `-b` (`--break`) flag no longer makes Catch break into debugger in the same stack frame as the failed test, but rather in a stack frame *below*.
|
||||
* Non-exception family of macros ({`REQUIRE`,`CHECK`}{`_`,`_FALSE`, `_FALSE`}, no longer use local try-cache block. This disables exception translation, but should not lead to false negatives.
|
||||
* Non-exception family of macros ({`REQUIRE`,`CHECK`}{`_`,`_FALSE`, `_THAT`}, no longer use local try-catch block. This disables exception translation, but should not lead to false negatives.
|
||||
|
||||
`CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined, in all translation units that are linked into single test binary, or the behaviour of setting `-b` flag and throwing unexpected exceptions will be unpredictable.
|
||||
|
||||
|
@@ -44,7 +44,7 @@ _Note that you should not use any assertion macros within a Listener!_
|
||||
|
||||
## Events that can be hooked
|
||||
|
||||
The following are the methods that can be overriden in the Listener:
|
||||
The following are the methods that can be overridden in the Listener:
|
||||
|
||||
```c++
|
||||
// The whole test run, starting and ending
|
||||
|
@@ -96,6 +96,14 @@ with expansion:
|
||||
""\" == ""\"
|
||||
```
|
||||
|
||||
### Visual Studio 2015 -- Alignment compilation error (C2718)
|
||||
|
||||
VS 2015 has a known bug, where `declval<T>` can cause compilation error
|
||||
if `T` has alignment requirements that it cannot meet.
|
||||
|
||||
|
||||
A workaround is to explicitly specialize `Catch::is_range` for given
|
||||
type (this avoids code path that uses `declval<T>` in a SFINAE context).
|
||||
|
||||
|
||||
### Visual Studio 2015 -- Wrong line number reported in debug mode
|
||||
|
@@ -1,18 +1,25 @@
|
||||
<a id="top"></a>
|
||||
# List of examples
|
||||
|
||||
## Already available
|
||||
|
||||
- Test Case: [Single-file](../examples/010-TestCase.cpp)
|
||||
- Test Case: [Multiple-file 1](../examples/020-TestCase-1.cpp), [2](../examples/020-TestCase-1.cpp)
|
||||
- Assertion: [REQUIRE, CHECK](../examples/030-Asn-Require-Check.cpp)
|
||||
- Fixture: [Sections](../examples/100-Fix-Section.cpp)
|
||||
- Fixture: [Class-based fixtures](../examples/110-Fix-ClassFixture.cpp)
|
||||
- BDD: [SCENARIO, GIVEN, WHEN, THEN](../examples/120-Bdd-ScenarioGivenWhenThen.cpp)
|
||||
- Listener: [Listeners](../examples/210-Evt-EventListeners.cpp)
|
||||
|
||||
|
||||
## Planned
|
||||
|
||||
- Assertion: [REQUIRE_THAT and Matchers](../examples/040-Asn-RequireThat.cpp)
|
||||
- Assertion: [REQUIRE_NO_THROW](../examples/050-Asn-RequireNoThrow.cpp)
|
||||
- Assertion: [REQUIRE_THROWS](../examples/050-Asn-RequireThrows.cpp)
|
||||
- Assertion: [REQUIRE_THROWS_AS](../examples/070-Asn-RequireThrowsAs.cpp)
|
||||
- Assertion: [REQUIRE_THROWS_WITH](../examples/080-Asn-RequireThrowsWith.cpp)
|
||||
- Assertion: [REQUIRE_THROWS_MATCHES](../examples/090-Asn-RequireThrowsMatches.cpp)
|
||||
- Fixture: [Sections](../examples/100-Fix-Section.cpp)
|
||||
- Fixture: [Class-based fixtures](../examples/110-Fix-ClassFixture.cpp)
|
||||
- BDD: [SCENARIO, GIVEN, WHEN, THEN](../examples/120-Bdd-ScenarioGivenWhenThen.cpp)
|
||||
- Floating point: [Approx - Comparisons](../examples/130-Fpt-Approx.cpp)
|
||||
- Logging: [CAPTURE - Capture expression](../examples/140-Log-Capture.cpp)
|
||||
- Logging: [INFO - Provide information with failure](../examples/150-Log-Info.cpp)
|
||||
@@ -21,7 +28,6 @@
|
||||
- Logging: [SUCCEED - Issue message and continue](../examples/180-Log-Succeed.cpp)
|
||||
- Report: [User-defined type](../examples/190-Rpt-ReportUserDefinedType.cpp)
|
||||
- Report: [Reporter](../examples/200-Rpt-UserDefinedReporter.cpp)
|
||||
- Listener: [Listeners](../examples/210-Evt-EventListeners.cpp)
|
||||
- Configuration: [Provide your own main()](../examples/220-Cfg-OwnMain.cpp)
|
||||
- Configuration: [Compile-time configuration](../examples/230-Cfg-CompileTimeConfiguration.cpp)
|
||||
- Configuration: [Run-time configuration](../examples/240-Cfg-RunTimeConfiguration.cpp)
|
||||
|
@@ -53,6 +53,25 @@ The floating point matchers are `WithinULP` and `WithinAbs`. `WithinAbs` accepts
|
||||
Do note that ULP-based checks only make sense when both compared numbers are of the same type and `WithinULP` will use type of its argument as the target type. This means that `WithinULP(1.f, 1)` will expect to compare `float`s, but `WithinULP(1., 1)` will expect to compare `double`s.
|
||||
|
||||
|
||||
### Generic matchers
|
||||
Catch also aims to provide a set of generic matchers. Currently this set
|
||||
contains only a matcher that takes arbitrary callable predicate and applies
|
||||
it onto the provided object.
|
||||
|
||||
Because of type inference limitations, the argument type of the predicate
|
||||
has to be provided explicitly. Example:
|
||||
```cpp
|
||||
REQUIRE_THAT("Hello olleH",
|
||||
Predicate<std::string>(
|
||||
[] (std::string const& str) -> bool { return str.front() == str.back(); },
|
||||
"First and last character should be equal")
|
||||
);
|
||||
```
|
||||
|
||||
The second argument is an optional description of the predicate, and is
|
||||
used only during reporting of the result.
|
||||
|
||||
|
||||
## Custom matchers
|
||||
It's easy to provide your own matchers to extend Catch or just to work with your own types.
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
<a id="top"></a>
|
||||
# Open Source projects using Catch
|
||||
|
||||
Catch is great for open source. With its [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution
|
||||
Catch is great for open source. With its [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution
|
||||
it's easy to just drop the header into your project and start writing tests - what's not to like?
|
||||
|
||||
As a result Catch is now being used in many Open Source projects, including some quite well known ones.
|
||||
This page is an attempt to track those projects. Obviously it can never be complete.
|
||||
This effort largely relies on the maintainers of the projects themselves updating this page and submitting a PR
|
||||
(or, if you prefer contact one of the maintainers of Catch directly, use the
|
||||
(or, if you prefer contact one of the maintainers of Catch directly, use the
|
||||
[forums](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)), or raise an [issue](https://github.com/philsquared/Catch/issues) to let us know).
|
||||
Of course users of those projects might want to update this page too. That's fine - as long you're confident the project maintainers won't mind.
|
||||
If you're an Open Source project maintainer and see your project listed here but would rather it wasn't -
|
||||
If you're an Open Source project maintainer and see your project listed here but would rather it wasn't -
|
||||
just let us know via any of the previously mentioned means - although I'm sure there won't be many who feel that way.
|
||||
|
||||
|
||||
Listing a project here does not imply endorsement and the plan is to keep these ordered alphabetically to avoid an implication of relative importance.
|
||||
|
||||
## Libraries & Frameworks
|
||||
@@ -21,7 +21,7 @@ Listing a project here does not imply endorsement and the plan is to keep these
|
||||
Boost Asio style bindings for ZeroMQ
|
||||
|
||||
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
|
||||
The core part of the Chakra Javascript engine that powers Microsoft Edge
|
||||
The core part of the Chakra JavaScript engine that powers Microsoft Edge
|
||||
|
||||
### [ChaiScript](https://github.com/ChaiScript/ChaiScript)
|
||||
A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques
|
||||
@@ -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++.
|
||||
|
||||
@@ -44,6 +47,9 @@ A header-only template engine for modern C++.
|
||||
### [JSON for Modern C++](https://github.com/nlohmann/json)
|
||||
A, single-header, JSON parsing library that takes advantage of what C++ has to offer.
|
||||
|
||||
### [libcluon](https://github.com/chrberger/libcluon)
|
||||
A single-header-only library written in C++14 to glue distributed software components (UDP, TCP, shared memory) supporting natively Protobuf, LCM/ZCM, MsgPack, and JSON for dynamic message transformations in-between.
|
||||
|
||||
### [MNMLSTC Core](https://github.com/mnmlstc/core)
|
||||
A small and easy to use C++11 library that adds a functionality set that will be available in C++14 and later, as well as some useful additions.
|
||||
|
||||
@@ -88,6 +94,9 @@ MAME originally stood for Multiple Arcade Machine Emulator
|
||||
### [Newsbeuter](https://github.com/akrennmair/newsbeuter)
|
||||
Newsbeuter is an open-source RSS/Atom feed reader for text terminals.
|
||||
|
||||
### [SpECTRE](https://github.com/sxs-collaboration/spectre)
|
||||
SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gravitational physics.
|
||||
|
||||
### [Standardese](https://github.com/foonathan/standardese)
|
||||
Standardese aims to be a nextgen Doxygen
|
||||
|
||||
|
@@ -30,7 +30,7 @@ int main( int argc, char* argv[] ) {
|
||||
|
||||
## Amending the config
|
||||
|
||||
If you still want Catch to process the command line, but you want to programatically tweak the config, you can do so in one of two ways:
|
||||
If you still want Catch to process the command line, but you want to programmatically tweak the config, you can do so in one of two ways:
|
||||
|
||||
```c++
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
@@ -106,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,114 @@
|
||||
<a id="top"></a>
|
||||
|
||||
# 2.2.3
|
||||
|
||||
**To fix some of the bugs, some behavior had to change in potentially breaking manner.**
|
||||
**This means that even though this is a patch release, it might not be a drop-in replacement.**
|
||||
|
||||
## Fixes
|
||||
* Listeners are now called before reporter
|
||||
* This was always documented to be the case, now it actually works that way
|
||||
* Catch's commandline will no longer accept multiple reporters
|
||||
* This was done because multiple reporters never worked properly and broke things in non-obvious ways
|
||||
* **This has potential to be a breaking change**
|
||||
* MinGW is now detected as Windows platform w/o SEH support (#1257)
|
||||
* This means that Catch2 no longer tries to use POSIX signal handling when compiled with MinGW
|
||||
* Fixed potential UB in parsing tags using non-ASCII characters (#1266)
|
||||
* Note that Catch2 still supports only ASCII test names/tags/etc
|
||||
* `TEST_CASE_METHOD` can now be used on classnames containing commas (#1245)
|
||||
* You have to enclose the classname in extra set of parentheses
|
||||
* Fixed insufficient alt stack size for POSIX signal handling (#1225)
|
||||
* Fixed compilation error on Android due to missing `std::to_string` in C++11 mode (#1280)
|
||||
* Fixed the order of user-provided `FALLBACK_STRINGIFIER` in stringification machinery (#1024)
|
||||
* It was intended to be replacement for built-in fallbacks, but it was used _after_ them.
|
||||
* **This has potential to be a breaking change**
|
||||
* Fixed compilation error when a type has an `operator<<` with templated lhs (#1285, #1306)
|
||||
|
||||
## Improvements
|
||||
* Added a new, experimental, output capture (#1243)
|
||||
* This capture can also redirect output written via C apis, e.g. `printf`
|
||||
* To opt-in, define `CATCH_CONFIG_EXPERIMENTAL_REDIRECT` in the implementation file
|
||||
* Added a new fallback stringifier for classes derived from `std::exception`
|
||||
* Both `StringMaker` specialization and `operator<<` overload are given priority
|
||||
|
||||
## Miscellaneous
|
||||
* `contrib/` now contains dbg scripts that skip over Catch's internals (#904, #1283)
|
||||
* `gdbinit` for gdb `lldbinit` for lldb
|
||||
* `CatchAddTests.cmake` no longer strips whitespace from tests (#1265, #1281)
|
||||
* Online documentation now describes `--use-colour` option (#1263)
|
||||
|
||||
|
||||
# 2.2.2
|
||||
|
||||
## Fixes
|
||||
* Fixed bug in `WithinAbs::match()` failing spuriously (#1228)
|
||||
* Fixed clang-tidy diagnostic about virtual call in destructor (#1226)
|
||||
* Reduced the number of GCC warnings suppression leaking out of the header (#1090, #1091)
|
||||
* Only `-Wparentheses` should be leaking now
|
||||
* Added upper bound on the time benchmark timer calibration is allowed to take (#1237)
|
||||
* On platforms where `std::chrono::high_resolution_clock`'s resolution is low, the calibration would appear stuck
|
||||
* Fixed compilation error when stringifying static arrays of `unsigned char`s (#1238)
|
||||
|
||||
## Improvements
|
||||
* XML encoder now hex-encodes invalid UTF-8 sequences (#1207)
|
||||
* This affects xml and junit reporters
|
||||
* Some invalid UTF-8 parts are left as is, e.g. surrogate pairs. This is because certain extensions of UTF-8 allow them, such as WTF-8.
|
||||
* CLR objects (`T^`) can now be stringified (#1216)
|
||||
* This affects code compiled as C++/CLI
|
||||
* Added `PredicateMatcher`, a matcher that takes an arbitrary predicate function (#1236)
|
||||
* See [documentation for details](https://github.com/catchorg/Catch2/blob/master/docs/matchers.md)
|
||||
|
||||
## Others
|
||||
* Modified CMake-installed pkg-config to allow `#include <catch.hpp>`(#1239)
|
||||
* The plans to standardize on `#include <catch2/catch.hpp>` are still in effect
|
||||
|
||||
|
||||
# 2.2.1
|
||||
|
||||
## Fixes
|
||||
* Fixed compilation error when compiling Catch2 with `std=c++17` against libc++ (#1214)
|
||||
* Clara (Catch2's CLI parsing library) used `std::optional` without including it explicitly
|
||||
* Fixed Catch2 return code always being 0 (#1215)
|
||||
* In the words of STL, "We feel superbad about letting this in"
|
||||
|
||||
|
||||
# 2.2.0
|
||||
|
||||
## Fixes
|
||||
* Hidden tests are not listed by default when listing tests (#1175)
|
||||
* This makes `catch_discover_tests` CMake script work better
|
||||
* Fixed regression that meant `<windows.h>` could potentially not be included properly (#1197)
|
||||
* Fixed installing `Catch2ConfigVersion.cmake` when Catch2 is a subproject.
|
||||
|
||||
## Improvements
|
||||
* Added an option to warn (+ exit with error) when no tests were ran (#1158)
|
||||
* Use as `-w NoTests`
|
||||
* Added provisional support for Emscripten (#1114)
|
||||
* [Added a way to override the fallback stringifier](https://github.com/catchorg/Catch2/blob/master/docs/configuration.md#fallback-stringifier) (#1024)
|
||||
* This allows project's own stringification machinery to be easily reused for Catch
|
||||
* `Catch::Session::run()` now accepts `char const * const *`, allowing it to accept array of string literals (#1031, #1178)
|
||||
* The embedded version of Clara was bumped to v1.1.3
|
||||
* Various minor performance improvements
|
||||
* Added support for DJGPP DOS crosscompiler (#1206)
|
||||
|
||||
|
||||
# 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
|
||||
@@ -362,8 +471,8 @@ Cygwin issue with `gettimeofday` - `#define` was not early enough
|
||||
* Cygwin compatibility fixes
|
||||
* Signal handling is no longer compiled by default.
|
||||
* Usage of `gettimeofday` inside Catch should no longer cause compilation errors.
|
||||
* Improved `-Wparentheses` supression for gcc (#674)
|
||||
* When compiled with gcc 4.8 or newer, the supression is localized to assertions only
|
||||
* Improved `-Wparentheses` suppression for gcc (#674)
|
||||
* When compiled with gcc 4.8 or newer, the suppression is localized to assertions only
|
||||
* Otherwise it is supressed for the whole TU
|
||||
* Fixed test spec parser issue (with escapes in multiple names)
|
||||
|
||||
@@ -382,7 +491,7 @@ Xml:
|
||||
* C-escape control characters instead of XML encoding them (which requires XML 1.1)
|
||||
* Revert XML output to XML 1.0
|
||||
* Can provide stylesheet references by extending the XML reporter
|
||||
* Added description and tags attribites to XML Reporter
|
||||
* Added description and tags attributes to XML Reporter
|
||||
* Tags are closed and the stream flushed more eagerly to avoid stdout interpolation
|
||||
|
||||
|
||||
|
@@ -1,11 +1,11 @@
|
||||
<a id="top"></a>
|
||||
# How to release
|
||||
|
||||
When enough changes have accumulated, it is time to release new version of Catch. This document describes the proces in doing so, that no steps are forgotten. Note that all referenced scripts can be found in the `scripts/` directory.
|
||||
When enough changes have accumulated, it is time to release new version of Catch. This document describes the process in doing so, that no steps are forgotten. Note that all referenced scripts can be found in the `scripts/` directory.
|
||||
|
||||
## Neccessary steps
|
||||
## Necessary steps
|
||||
|
||||
These steps are neccessary and have to be performed before each new release. They serve to make sure that the new release is correct and linked-to from the standard places.
|
||||
These steps are necessary and have to be performed before each new release. They serve to make sure that the new release is correct and linked-to from the standard places.
|
||||
|
||||
|
||||
### Approval testing
|
||||
@@ -54,7 +54,7 @@ The following steps are optional, and do not have to be performed when releasing
|
||||
|
||||
### vcpkg update
|
||||
|
||||
Catch is maintaining its own port in Microsoft's package manager [vcpkg](https://github.com/Microsoft/vcpkg). This means that when new version of Catch is released, it should be posted there as well. `updateVcpkgPackage.py` can do a lot of neccessary work for you, it creates a branch and commits neccessary changes. You should review these changes, push and open a PR against vcpkg's upstream.
|
||||
Catch is maintaining its own port in Microsoft's package manager [vcpkg](https://github.com/Microsoft/vcpkg). This means that when new version of Catch is released, it should be posted there as well. `updateVcpkgPackage.py` can do a lot of necessary work for you, it creates a branch and commits necessary changes. You should review these changes, push and open a PR against vcpkg's upstream.
|
||||
|
||||
Note that the script assumes you have your fork of vcpkg checked out in a directory next to the directory where you have checked out Catch, like so:
|
||||
```
|
||||
|
@@ -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:
|
||||
|
@@ -9,6 +9,9 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
||||
|
||||
#define CATCH_VERSION_MAJOR 2
|
||||
#define CATCH_VERSION_MINOR 2
|
||||
#define CATCH_VERSION_PATCH 3
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang system_header
|
||||
|
54
include/external/clara.hpp
vendored
54
include/external/clara.hpp
vendored
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// See https://github.com/philsquared/Clara for more details
|
||||
|
||||
// Clara v1.1.1
|
||||
// Clara v1.1.4
|
||||
|
||||
#ifndef CATCH_CLARA_HPP_INCLUDED
|
||||
#define CATCH_CLARA_HPP_INCLUDED
|
||||
@@ -18,6 +18,16 @@
|
||||
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
|
||||
#endif
|
||||
|
||||
#ifndef CLARA_CONFIG_OPTIONAL_TYPE
|
||||
#ifdef __has_include
|
||||
#if __has_include(<optional>) && __cplusplus >= 201703L
|
||||
#include <optional>
|
||||
#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// ----------- #included from clara_textflow.hpp -----------
|
||||
|
||||
// TextFlowCpp
|
||||
@@ -389,11 +399,9 @@ namespace detail {
|
||||
std::vector<std::string> m_args;
|
||||
|
||||
public:
|
||||
Args( int argc, char *argv[] ) {
|
||||
m_exeName = argv[0];
|
||||
for( int i = 1; i < argc; ++i )
|
||||
m_args.push_back( argv[i] );
|
||||
}
|
||||
Args( int argc, char const* const* argv )
|
||||
: m_exeName(argv[0]),
|
||||
m_args(argv + 1, argv + argc) {}
|
||||
|
||||
Args( std::initializer_list<std::string> args )
|
||||
: m_exeName( *args.begin() ),
|
||||
@@ -580,15 +588,13 @@ namespace detail {
|
||||
|
||||
protected:
|
||||
void enforceOk() const override {
|
||||
// !TBD: If no exceptions, std::terminate here or something
|
||||
switch( m_type ) {
|
||||
case ResultBase::LogicError:
|
||||
throw std::logic_error( m_errorMessage );
|
||||
case ResultBase::RuntimeError:
|
||||
throw std::runtime_error( m_errorMessage );
|
||||
case ResultBase::Ok:
|
||||
break;
|
||||
}
|
||||
|
||||
// Errors shouldn't reach this point, but if they do
|
||||
// the actual error message will be in m_errorMessage
|
||||
assert( m_type != ResultBase::LogicError );
|
||||
assert( m_type != ResultBase::RuntimeError );
|
||||
if( m_type != ResultBase::Ok )
|
||||
std::abort();
|
||||
}
|
||||
|
||||
std::string m_errorMessage; // Only populated if resultType is an error
|
||||
@@ -658,6 +664,16 @@ namespace detail {
|
||||
return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
|
||||
return ParserResult::ok( ParseResultType::Matched );
|
||||
}
|
||||
#ifdef CLARA_CONFIG_OPTIONAL_TYPE
|
||||
template<typename T>
|
||||
inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
|
||||
T temp;
|
||||
auto result = convertInto( source, temp );
|
||||
if( result )
|
||||
target = std::move(temp);
|
||||
return result;
|
||||
}
|
||||
#endif // CLARA_CONFIG_OPTIONAL_TYPE
|
||||
|
||||
struct NonCopyable {
|
||||
NonCopyable() = default;
|
||||
@@ -670,12 +686,14 @@ namespace detail {
|
||||
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;
|
||||
virtual auto isFlag() const -> bool { return true; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@@ -907,7 +925,7 @@ namespace detail {
|
||||
if( token.type != TokenType::Argument )
|
||||
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
|
||||
|
||||
assert( dynamic_cast<detail::BoundValueRefBase*>( m_ref.get() ) );
|
||||
assert( !m_ref->isFlag() );
|
||||
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
|
||||
|
||||
auto result = valueRef->setValue( remainingTokens->token );
|
||||
@@ -983,14 +1001,14 @@ namespace detail {
|
||||
if( remainingTokens && remainingTokens->type == TokenType::Option ) {
|
||||
auto const &token = *remainingTokens;
|
||||
if( isMatch(token.token ) ) {
|
||||
if( auto flagRef = dynamic_cast<detail::BoundFlagRefBase*>( m_ref.get() ) ) {
|
||||
if( m_ref->isFlag() ) {
|
||||
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 {
|
||||
assert( dynamic_cast<detail::BoundValueRefBase*>( m_ref.get() ) );
|
||||
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
|
||||
++remainingTokens;
|
||||
if( !remainingTokens )
|
||||
|
@@ -65,9 +65,9 @@ namespace Catch {
|
||||
expr = m_info.capturedExpression;
|
||||
else {
|
||||
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
|
||||
expr += m_info.macroName.c_str();
|
||||
expr += m_info.macroName;
|
||||
expr += "( ";
|
||||
expr += m_info.capturedExpression.c_str();
|
||||
expr += m_info.capturedExpression;
|
||||
expr += " )";
|
||||
}
|
||||
return expr;
|
||||
|
@@ -13,7 +13,7 @@ namespace Catch {
|
||||
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
|
||||
|
||||
// This is the general overload that takes a any string matcher
|
||||
// There is another overload, in catch_assertinhandler.h/.cpp, that only takes a string and infers
|
||||
// There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
|
||||
// the Equals matcher (so the header does not mention matchers)
|
||||
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) {
|
||||
std::string exceptionMessage = Catch::translateActiveException();
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "catch_capture.hpp"
|
||||
#include "catch_matchers.h"
|
||||
#include "catch_matchers_floating.h"
|
||||
#include "catch_matchers_generic.hpp"
|
||||
#include "catch_matchers_string.h"
|
||||
#include "catch_matchers_vector.h"
|
||||
|
||||
|
@@ -20,9 +20,19 @@ namespace Catch {
|
||||
using namespace clara;
|
||||
|
||||
auto const setWarning = [&]( std::string const& warning ) {
|
||||
if( warning != "NoAssertions" )
|
||||
auto warningSet = [&]() {
|
||||
if( warning == "NoAssertions" )
|
||||
return WarnAbout::NoAssertions;
|
||||
|
||||
if ( warning == "NoTests" )
|
||||
return WarnAbout::NoTests;
|
||||
|
||||
return WarnAbout::Nothing;
|
||||
}();
|
||||
|
||||
if (warningSet == WarnAbout::Nothing)
|
||||
return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" );
|
||||
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
|
||||
config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet );
|
||||
return ParserResult::ok( ParseResultType::Matched );
|
||||
};
|
||||
auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
|
||||
@@ -120,7 +130,7 @@ namespace Catch {
|
||||
| Opt( config.outputFilename, "filename" )
|
||||
["-o"]["--out"]
|
||||
( "output filename" )
|
||||
| Opt( config.reporterNames, "name" )
|
||||
| Opt( config.reporterName, "name" )
|
||||
["-r"]["--reporter"]
|
||||
( "reporter to use (defaults to console)" )
|
||||
| Opt( config.name, "name" )
|
||||
|
@@ -24,6 +24,7 @@
|
||||
// Many features, at point of detection, define an _INTERNAL_ macro, so they
|
||||
// can be combined, en-mass, with the _NO_ forms later.
|
||||
|
||||
#include "catch_platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -31,6 +32,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__
|
||||
@@ -51,14 +60,16 @@
|
||||
#endif // __clang__
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Assume that non-Windows platforms support posix signals by default
|
||||
#if !defined(CATCH_PLATFORM_WINDOWS)
|
||||
#define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// We know some environments not to support full POSIX signals
|
||||
#if defined(__CYGWIN__) || defined(__QNX__)
|
||||
|
||||
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
|
||||
# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
|
||||
# endif
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
|
||||
#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
|
||||
#endif
|
||||
|
||||
#ifdef __OS400__
|
||||
@@ -66,6 +77,18 @@
|
||||
# define CATCH_CONFIG_COLOUR_NONE
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Android somehow still does not support std::to_string
|
||||
#if defined(__ANDROID__)
|
||||
# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Not all Windows environments support SEH properly
|
||||
#if defined(__MINGW32__)
|
||||
# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Cygwin
|
||||
#ifdef __CYGWIN__
|
||||
@@ -80,6 +103,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)
|
||||
@@ -92,6 +120,13 @@
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// DJGPP
|
||||
#ifdef __DJGPP__
|
||||
# define CATCH_INTERNAL_CONFIG_NO_WCHAR
|
||||
#endif // __DJGPP__
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Use of __COUNTER__ is suppressed during code analysis in
|
||||
// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
|
||||
// handled by it.
|
||||
@@ -104,13 +139,26 @@
|
||||
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
|
||||
# define CATCH_CONFIG_COUNTER
|
||||
#endif
|
||||
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
|
||||
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
|
||||
# define CATCH_CONFIG_WINDOWS_SEH
|
||||
#endif
|
||||
// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
|
||||
#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
|
||||
#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
|
||||
# define CATCH_CONFIG_POSIX_SIGNALS
|
||||
#endif
|
||||
// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
|
||||
#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
|
||||
# define CATCH_CONFIG_WCHAR
|
||||
#endif
|
||||
|
||||
#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
|
||||
# define CATCH_CONFIG_CPP11_TO_STRING
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
|
||||
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
|
||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
||||
|
@@ -15,12 +15,16 @@ namespace Catch {
|
||||
: m_data( data ),
|
||||
m_stream( openStream() )
|
||||
{
|
||||
if( !data.testsOrTags.empty() ) {
|
||||
TestSpecParser parser( ITagAliasRegistry::get() );
|
||||
TestSpecParser parser(ITagAliasRegistry::get());
|
||||
if (data.testsOrTags.empty()) {
|
||||
parser.parse("~[.]"); // All not hidden tests
|
||||
}
|
||||
else {
|
||||
m_hasTestFilters = true;
|
||||
for( auto const& testOrTags : data.testsOrTags )
|
||||
parser.parse( testOrTags );
|
||||
m_testSpec = parser.testSpec();
|
||||
}
|
||||
m_testSpec = parser.testSpec();
|
||||
}
|
||||
|
||||
std::string const& Config::getFilename() const {
|
||||
@@ -33,11 +37,13 @@ namespace Catch {
|
||||
bool Config::listReporters() const { return m_data.listReporters; }
|
||||
|
||||
std::string Config::getProcessName() const { return m_data.processName; }
|
||||
std::string const& Config::getReporterName() const { return m_data.reporterName; }
|
||||
|
||||
std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; }
|
||||
std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
|
||||
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
|
||||
|
||||
TestSpec const& Config::testSpec() const { return m_testSpec; }
|
||||
bool Config::hasTestFilters() const { return m_hasTestFilters; }
|
||||
|
||||
bool Config::showHelp() const { return m_data.showHelp; }
|
||||
|
||||
@@ -46,7 +52,8 @@ namespace Catch {
|
||||
std::ostream& Config::stream() const { return m_stream->stream(); }
|
||||
std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
|
||||
bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
|
||||
bool Config::warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
|
||||
bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); }
|
||||
bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); }
|
||||
ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
|
||||
RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; }
|
||||
unsigned int Config::rngSeed() const { return m_data.rngSeed; }
|
||||
|
@@ -54,8 +54,12 @@ namespace Catch {
|
||||
std::string outputFilename;
|
||||
std::string name;
|
||||
std::string processName;
|
||||
#ifndef CATCH_CONFIG_DEFAULT_REPORTER
|
||||
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
|
||||
#endif
|
||||
std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
|
||||
#undef CATCH_CONFIG_DEFAULT_REPORTER
|
||||
|
||||
std::vector<std::string> reporterNames;
|
||||
std::vector<std::string> testsOrTags;
|
||||
std::vector<std::string> sectionsToRun;
|
||||
};
|
||||
@@ -76,11 +80,13 @@ namespace Catch {
|
||||
bool listReporters() const;
|
||||
|
||||
std::string getProcessName() const;
|
||||
std::string const& getReporterName() const;
|
||||
|
||||
std::vector<std::string> const& getReporterNames() const;
|
||||
std::vector<std::string> const& getTestsOrTags() const;
|
||||
std::vector<std::string> const& getSectionsToRun() const override;
|
||||
|
||||
virtual TestSpec const& testSpec() const override;
|
||||
bool hasTestFilters() const override;
|
||||
|
||||
bool showHelp() const;
|
||||
|
||||
@@ -90,6 +96,7 @@ namespace Catch {
|
||||
std::string name() const override;
|
||||
bool includeSuccessfulResults() const override;
|
||||
bool warnAboutMissingAssertions() const override;
|
||||
bool warnAboutNoTests() const override;
|
||||
ShowDurations::OrNot showDurations() const override;
|
||||
RunTests::InWhatOrder runOrder() const override;
|
||||
unsigned int rngSeed() const override;
|
||||
@@ -107,6 +114,7 @@ namespace Catch {
|
||||
|
||||
std::unique_ptr<IStream const> m_stream;
|
||||
TestSpec m_testSpec;
|
||||
bool m_hasTestFilters = false;
|
||||
};
|
||||
|
||||
} // end namespace Catch
|
||||
|
@@ -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() {
|
||||
@@ -163,7 +169,12 @@ namespace {
|
||||
#ifdef CATCH_PLATFORM_MAC
|
||||
!isDebuggerActive() &&
|
||||
#endif
|
||||
isatty(STDOUT_FILENO);
|
||||
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
|
||||
isatty(STDOUT_FILENO)
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
;
|
||||
}
|
||||
IColourImpl* platformColourInstance() {
|
||||
ErrnoGuard guard;
|
||||
@@ -196,7 +207,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 +216,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
|
||||
|
@@ -9,21 +9,23 @@
|
||||
#include "catch_debug_console.h"
|
||||
#include "catch_stream.h"
|
||||
#include "catch_platform.h"
|
||||
#include "catch_windows_h_proxy.h"
|
||||
|
||||
#ifdef CATCH_PLATFORM_WINDOWS
|
||||
|
||||
#include "catch_windows_h_proxy.h"
|
||||
|
||||
namespace Catch {
|
||||
void writeToDebugConsole( std::string const& text ) {
|
||||
::OutputDebugStringA( text.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
namespace Catch {
|
||||
void writeToDebugConsole( std::string const& text ) {
|
||||
// !TBD: Need a version for Mac/ XCode and other IDEs
|
||||
Catch::cout() << text;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // Platform
|
||||
|
@@ -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 static_cast<bool>(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 static_cast<bool>(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>
|
||||
|
@@ -12,7 +12,7 @@
|
||||
|
||||
#ifndef __OBJC__
|
||||
|
||||
#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
|
||||
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
|
||||
// Standard C/C++ Win32 Unicode wmain entry point
|
||||
extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
|
||||
#else
|
||||
|
@@ -11,10 +11,9 @@
|
||||
#include "catch_stream.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iosfwd>
|
||||
|
||||
#define CATCH_PREPARE_EXCEPTION( type, msg ) \
|
||||
type( static_cast<std::ostringstream&&>( Catch::ReusableStringStream().get() << msg ).str() )
|
||||
type( ( Catch::ReusableStringStream() << msg ).str() )
|
||||
#define CATCH_INTERNAL_ERROR( msg ) \
|
||||
throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg);
|
||||
#define CATCH_ERROR( msg ) \
|
||||
|
@@ -17,6 +17,8 @@
|
||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#endif
|
||||
|
||||
#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
|
||||
|
||||
namespace {
|
||||
// Report the error condition
|
||||
void reportFatal( char const * const message ) {
|
||||
@@ -24,15 +26,9 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
||||
#endif // signals/SEH handling
|
||||
|
||||
# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
|
||||
|
||||
namespace Catch {
|
||||
void FatalConditionHandler::reset() {}
|
||||
}
|
||||
|
||||
# else // CATCH_CONFIG_WINDOWS_SEH is defined
|
||||
#if defined( CATCH_CONFIG_WINDOWS_SEH )
|
||||
|
||||
namespace Catch {
|
||||
struct SignalDefs { DWORD id; const char* name; };
|
||||
@@ -72,7 +68,6 @@ namespace Catch {
|
||||
|
||||
void FatalConditionHandler::reset() {
|
||||
if (isSet) {
|
||||
// Unregister handler and restore the old guarantee
|
||||
RemoveVectoredExceptionHandler(exceptionHandlerHandle);
|
||||
SetThreadStackGuarantee(&guaranteeSize);
|
||||
exceptionHandlerHandle = nullptr;
|
||||
@@ -91,20 +86,7 @@ PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
# endif // CATCH_CONFIG_WINDOWS_SEH
|
||||
|
||||
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
|
||||
|
||||
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
|
||||
|
||||
namespace Catch {
|
||||
void FatalConditionHandler::reset() {}
|
||||
}
|
||||
|
||||
|
||||
# else // CATCH_CONFIG_POSIX_SIGNALS is defined
|
||||
|
||||
#include <signal.h>
|
||||
#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -112,6 +94,11 @@ namespace Catch {
|
||||
int id;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
// 32kb for the alternate stack seems to be sufficient. However, this value
|
||||
// is experimentally determined, so that's not guaranteed.
|
||||
constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
|
||||
|
||||
static SignalDefs signalDefs[] = {
|
||||
{ SIGINT, "SIGINT - Terminal interrupt signal" },
|
||||
{ SIGILL, "SIGILL - Illegal instruction signal" },
|
||||
@@ -139,7 +126,7 @@ namespace Catch {
|
||||
isSet = true;
|
||||
stack_t sigStack;
|
||||
sigStack.ss_sp = altStackMem;
|
||||
sigStack.ss_size = SIGSTKSZ;
|
||||
sigStack.ss_size = sigStackSize;
|
||||
sigStack.ss_flags = 0;
|
||||
sigaltstack(&sigStack, &oldSigStack);
|
||||
struct sigaction sa = { };
|
||||
@@ -171,14 +158,18 @@ namespace Catch {
|
||||
bool FatalConditionHandler::isSet = false;
|
||||
struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
|
||||
stack_t FatalConditionHandler::oldSigStack = {};
|
||||
char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
|
||||
char FatalConditionHandler::altStackMem[sigStackSize] = {};
|
||||
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
# endif // CATCH_CONFIG_POSIX_SIGNALS
|
||||
#else
|
||||
|
||||
#endif // not Windows
|
||||
namespace Catch {
|
||||
void FatalConditionHandler::reset() {}
|
||||
}
|
||||
|
||||
#endif // signals/SEH handling
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# pragma GCC diagnostic pop
|
||||
|
@@ -9,23 +9,12 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include "catch_platform.h"
|
||||
#include "catch_compiler_capabilities.h"
|
||||
|
||||
|
||||
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
||||
#include "catch_windows_h_proxy.h"
|
||||
|
||||
# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
|
||||
|
||||
namespace Catch {
|
||||
struct FatalConditionHandler {
|
||||
void reset();
|
||||
};
|
||||
}
|
||||
|
||||
# else // CATCH_CONFIG_WINDOWS_SEH is defined
|
||||
#if defined( CATCH_CONFIG_WINDOWS_SEH )
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -44,20 +33,7 @@ namespace Catch {
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
# endif // CATCH_CONFIG_WINDOWS_SEH
|
||||
|
||||
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
|
||||
|
||||
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
|
||||
|
||||
namespace Catch {
|
||||
struct FatalConditionHandler {
|
||||
void reset();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
# else // CATCH_CONFIG_POSIX_SIGNALS is defined
|
||||
#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
@@ -66,7 +42,7 @@ namespace Catch {
|
||||
struct FatalConditionHandler {
|
||||
|
||||
static bool isSet;
|
||||
static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)];
|
||||
static struct sigaction oldSigActions[];
|
||||
static stack_t oldSigStack;
|
||||
static char altStackMem[];
|
||||
|
||||
@@ -79,8 +55,15 @@ namespace Catch {
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
# endif // CATCH_CONFIG_POSIX_SIGNALS
|
||||
|
||||
#endif // not Windows
|
||||
#else
|
||||
|
||||
namespace Catch {
|
||||
struct FatalConditionHandler {
|
||||
void reset();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
||||
|
@@ -25,7 +25,8 @@ namespace Catch {
|
||||
|
||||
struct WarnAbout { enum What {
|
||||
Nothing = 0x00,
|
||||
NoAssertions = 0x01
|
||||
NoAssertions = 0x01,
|
||||
NoTests = 0x02
|
||||
}; };
|
||||
|
||||
struct ShowDurations { enum OrNot {
|
||||
@@ -62,10 +63,12 @@ namespace Catch {
|
||||
virtual bool includeSuccessfulResults() const = 0;
|
||||
virtual bool shouldDebugBreak() const = 0;
|
||||
virtual bool warnAboutMissingAssertions() const = 0;
|
||||
virtual bool warnAboutNoTests() const = 0;
|
||||
virtual int abortAfter() const = 0;
|
||||
virtual bool showInvisibles() const = 0;
|
||||
virtual ShowDurations::OrNot showDurations() const = 0;
|
||||
virtual TestSpec const& testSpec() const = 0;
|
||||
virtual bool hasTestFilters() const = 0;
|
||||
virtual RunTests::InWhatOrder runOrder() const = 0;
|
||||
virtual unsigned int rngSeed() const = 0;
|
||||
virtual int benchmarkResolutionMultiple() const = 0;
|
||||
|
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "catch_interfaces_reporter.h"
|
||||
#include "../reporters/catch_reporter_multi.h"
|
||||
#include "../reporters/catch_reporter_listening.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -111,25 +111,4 @@ namespace Catch {
|
||||
IReporterFactory::~IReporterFactory() = default;
|
||||
IReporterRegistry::~IReporterRegistry() = default;
|
||||
|
||||
void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) {
|
||||
|
||||
if( !existingReporter ) {
|
||||
existingReporter = std::move( additionalReporter );
|
||||
return;
|
||||
}
|
||||
|
||||
MultipleReporters* multi = nullptr;
|
||||
|
||||
if( existingReporter->isMulti() ) {
|
||||
multi = static_cast<MultipleReporters*>( existingReporter.get() );
|
||||
}
|
||||
else {
|
||||
auto newMulti = std::unique_ptr<MultipleReporters>( new MultipleReporters );
|
||||
newMulti->add( std::move( existingReporter ) );
|
||||
multi = newMulti.get();
|
||||
existingReporter = std::move( newMulti );
|
||||
}
|
||||
multi->add( std::move( additionalReporter ) );
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
||||
|
@@ -226,8 +226,6 @@ namespace Catch {
|
||||
virtual Listeners const& getListeners() const = 0;
|
||||
};
|
||||
|
||||
void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter );
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
|
||||
|
@@ -28,11 +28,10 @@ namespace Catch {
|
||||
|
||||
std::size_t listTests( Config const& config ) {
|
||||
TestSpec testSpec = config.testSpec();
|
||||
if( config.testSpec().hasFilters() )
|
||||
if( config.hasTestFilters() )
|
||||
Catch::cout() << "Matching test cases:\n";
|
||||
else {
|
||||
Catch::cout() << "All available test cases:\n";
|
||||
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
|
||||
}
|
||||
|
||||
auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
|
||||
@@ -54,7 +53,7 @@ namespace Catch {
|
||||
Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n";
|
||||
}
|
||||
|
||||
if( !config.testSpec().hasFilters() )
|
||||
if( !config.hasTestFilters() )
|
||||
Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl;
|
||||
else
|
||||
Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl;
|
||||
@@ -63,8 +62,6 @@ namespace Catch {
|
||||
|
||||
std::size_t listTestsNamesOnly( Config const& config ) {
|
||||
TestSpec testSpec = config.testSpec();
|
||||
if( !config.testSpec().hasFilters() )
|
||||
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
|
||||
std::size_t matchedTests = 0;
|
||||
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
|
||||
for( auto const& testCaseInfo : matchedTestCases ) {
|
||||
@@ -94,11 +91,10 @@ namespace Catch {
|
||||
|
||||
std::size_t listTags( Config const& config ) {
|
||||
TestSpec testSpec = config.testSpec();
|
||||
if( config.testSpec().hasFilters() )
|
||||
if( config.hasTestFilters() )
|
||||
Catch::cout() << "Tags for matching test cases:\n";
|
||||
else {
|
||||
Catch::cout() << "All available tags:\n";
|
||||
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
|
||||
}
|
||||
|
||||
std::map<std::string, TagInfo> tagCounts;
|
||||
|
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "catch_matchers_floating.h"
|
||||
#include "catch_to_string.hpp"
|
||||
#include "catch_tostring.h"
|
||||
|
||||
#include <cstdlib>
|
||||
@@ -88,7 +89,7 @@ namespace Floating {
|
||||
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
|
||||
// But without the subtraction to allow for INFINITY in comparison
|
||||
bool WithinAbsMatcher::match(double const& matchee) const {
|
||||
return (matchee + m_margin >= m_target) && (m_target + m_margin >= m_margin);
|
||||
return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
|
||||
}
|
||||
|
||||
std::string WithinAbsMatcher::describe() const {
|
||||
@@ -115,7 +116,7 @@ namespace Floating {
|
||||
}
|
||||
|
||||
std::string WithinUlpsMatcher::describe() const {
|
||||
return "is within " + std::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
|
||||
return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
|
||||
}
|
||||
|
||||
}// namespace Floating
|
||||
|
9
include/internal/catch_matchers_generic.cpp
Normal file
9
include/internal/catch_matchers_generic.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "catch_matchers_generic.hpp"
|
||||
|
||||
std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) {
|
||||
if (desc.empty()) {
|
||||
return "matches undescribed predicate";
|
||||
} else {
|
||||
return "matches predicate: \"" + desc + '"';
|
||||
}
|
||||
}
|
58
include/internal/catch_matchers_generic.hpp
Normal file
58
include/internal/catch_matchers_generic.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Created by Martin Hořeňovský on 03/04/2017.
|
||||
*
|
||||
* 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_MATCHERS_GENERIC_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_MATCHERS_GENERIC_HPP_INCLUDED
|
||||
|
||||
#include "catch_common.h"
|
||||
#include "catch_matchers.h"
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
namespace Generic {
|
||||
|
||||
namespace Detail {
|
||||
std::string finalizeDescription(const std::string& desc);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class PredicateMatcher : public MatcherBase<T> {
|
||||
std::function<bool(T const&)> m_predicate;
|
||||
std::string m_description;
|
||||
public:
|
||||
|
||||
PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)
|
||||
:m_predicate(std::move(elem)),
|
||||
m_description(Detail::finalizeDescription(descr))
|
||||
{}
|
||||
|
||||
bool match( T const& item ) const override {
|
||||
return m_predicate(item);
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
return m_description;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Generic
|
||||
|
||||
// The following functions create the actual matcher objects.
|
||||
// The user has to explicitly specify type to the function, because
|
||||
// infering std::function<bool(T const&)> is hard (but possible) and
|
||||
// requires a lot of TMP.
|
||||
template<typename T>
|
||||
Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {
|
||||
return Generic::PredicateMatcher<T>(predicate, description);
|
||||
}
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_MATCHERS_GENERIC_HPP_INCLUDED
|
@@ -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
|
||||
|
132
include/internal/catch_output_redirect.cpp
Normal file
132
include/internal/catch_output_redirect.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Created by Martin on 28/04/2018.
|
||||
*
|
||||
* 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_output_redirect.h"
|
||||
|
||||
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <io.h> //_dup and _dup2
|
||||
#define dup _dup
|
||||
#define dup2 _dup2
|
||||
#define fileno _fileno
|
||||
#else
|
||||
#include <unistd.h> // dup and dup2
|
||||
#endif
|
||||
|
||||
namespace Catch {
|
||||
|
||||
RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
|
||||
: m_originalStream( originalStream ),
|
||||
m_redirectionStream( redirectionStream ),
|
||||
m_prevBuf( m_originalStream.rdbuf() )
|
||||
{
|
||||
m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
|
||||
}
|
||||
|
||||
RedirectedStream::~RedirectedStream() {
|
||||
m_originalStream.rdbuf( m_prevBuf );
|
||||
}
|
||||
|
||||
RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
|
||||
auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); }
|
||||
|
||||
RedirectedStdErr::RedirectedStdErr()
|
||||
: m_cerr( Catch::cerr(), m_rss.get() ),
|
||||
m_clog( Catch::clog(), m_rss.get() )
|
||||
{}
|
||||
auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
|
||||
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
TempFile::TempFile() {
|
||||
if (tmpnam_s(m_buffer)) {
|
||||
throw std::runtime_error("Could not get a temp filename");
|
||||
}
|
||||
if (fopen_s(&m_file, m_buffer, "w")) {
|
||||
char buffer[100];
|
||||
if (strerror_s(buffer, errno)) {
|
||||
throw std::runtime_error("Could not translate errno to string");
|
||||
}
|
||||
throw std::runtime_error("Could not open the temp file: " + std::string(m_buffer) + buffer);
|
||||
}
|
||||
}
|
||||
#else
|
||||
TempFile::TempFile() {
|
||||
m_file = std::tmpfile();
|
||||
if (!m_file) {
|
||||
throw std::runtime_error("Could not create a temp file.");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TempFile::~TempFile() {
|
||||
// TBD: What to do about errors here?
|
||||
std::fclose(m_file);
|
||||
// We manually create the file on Windows only, on Linux
|
||||
// it will be autodeleted
|
||||
#if defined(_MSC_VER)
|
||||
std::remove(m_buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
FILE* TempFile::getFile() {
|
||||
return m_file;
|
||||
}
|
||||
|
||||
std::string TempFile::getContents() {
|
||||
std::stringstream sstr;
|
||||
char buffer[100] = {};
|
||||
std::rewind(m_file);
|
||||
while (std::fgets(buffer, sizeof(buffer), m_file)) {
|
||||
sstr << buffer;
|
||||
}
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
|
||||
m_originalStdout(dup(1)),
|
||||
m_originalStderr(dup(2)),
|
||||
m_stdoutDest(stdout_dest),
|
||||
m_stderrDest(stderr_dest) {
|
||||
dup2(fileno(m_stdoutFile.getFile()), 1);
|
||||
dup2(fileno(m_stderrFile.getFile()), 2);
|
||||
}
|
||||
|
||||
OutputRedirect::~OutputRedirect() {
|
||||
Catch::cout() << std::flush;
|
||||
fflush(stdout);
|
||||
// Since we support overriding these streams, we flush cerr
|
||||
// even though std::cerr is unbuffered
|
||||
Catch::cerr() << std::flush;
|
||||
Catch::clog() << std::flush;
|
||||
fflush(stderr);
|
||||
|
||||
dup2(m_originalStdout, 1);
|
||||
dup2(m_originalStderr, 2);
|
||||
|
||||
m_stdoutDest += m_stdoutFile.getContents();
|
||||
m_stderrDest += m_stderrFile.getContents();
|
||||
}
|
||||
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#undef dup
|
||||
#undef dup2
|
||||
#undef fileno
|
||||
#endif
|
98
include/internal/catch_output_redirect.h
Normal file
98
include/internal/catch_output_redirect.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Created by Martin on 28/04/2018.
|
||||
*
|
||||
* 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_OUTPUT_REDIRECT_H
|
||||
#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
|
||||
|
||||
#include "catch_platform.h"
|
||||
#include "catch_stream.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class RedirectedStream {
|
||||
std::ostream& m_originalStream;
|
||||
std::ostream& m_redirectionStream;
|
||||
std::streambuf* m_prevBuf;
|
||||
|
||||
public:
|
||||
RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
|
||||
~RedirectedStream();
|
||||
};
|
||||
|
||||
class RedirectedStdOut {
|
||||
ReusableStringStream m_rss;
|
||||
RedirectedStream m_cout;
|
||||
public:
|
||||
RedirectedStdOut();
|
||||
auto str() const -> std::string;
|
||||
};
|
||||
|
||||
// StdErr has two constituent streams in C++, std::cerr and std::clog
|
||||
// This means that we need to redirect 2 streams into 1 to keep proper
|
||||
// order of writes
|
||||
class RedirectedStdErr {
|
||||
ReusableStringStream m_rss;
|
||||
RedirectedStream m_cerr;
|
||||
RedirectedStream m_clog;
|
||||
public:
|
||||
RedirectedStdErr();
|
||||
auto str() const -> std::string;
|
||||
};
|
||||
|
||||
|
||||
// Windows's implementation of std::tmpfile is terrible (it tries
|
||||
// to create a file inside system folder, thus requiring elevated
|
||||
// privileges for the binary), so we have to use tmpnam(_s) and
|
||||
// create the file ourselves there.
|
||||
class TempFile {
|
||||
public:
|
||||
TempFile(TempFile const&) = delete;
|
||||
TempFile& operator=(TempFile const&) = delete;
|
||||
TempFile(TempFile&&) = delete;
|
||||
TempFile& operator=(TempFile&&) = delete;
|
||||
|
||||
TempFile();
|
||||
~TempFile();
|
||||
|
||||
std::FILE* getFile();
|
||||
std::string getContents();
|
||||
|
||||
private:
|
||||
std::FILE* m_file = nullptr;
|
||||
#if defined(_MSC_VER)
|
||||
char m_buffer[L_tmpnam] = { 0 };
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class OutputRedirect {
|
||||
public:
|
||||
OutputRedirect(OutputRedirect const&) = delete;
|
||||
OutputRedirect& operator=(OutputRedirect const&) = delete;
|
||||
OutputRedirect(OutputRedirect&&) = delete;
|
||||
OutputRedirect& operator=(OutputRedirect&&) = delete;
|
||||
|
||||
|
||||
OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
|
||||
~OutputRedirect();
|
||||
|
||||
private:
|
||||
int m_originalStdout = -1;
|
||||
int m_originalStderr = -1;
|
||||
TempFile m_stdoutFile;
|
||||
TempFile m_stderrFile;
|
||||
std::string& m_stdoutDest;
|
||||
std::string& m_stderrDest;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
|
@@ -20,7 +20,7 @@
|
||||
#elif defined(linux) || defined(__linux) || defined(__linux__)
|
||||
# define CATCH_PLATFORM_LINUX
|
||||
|
||||
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
|
||||
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
|
||||
# define CATCH_PLATFORM_WINDOWS
|
||||
#endif
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include "catch_enforce.h"
|
||||
#include "catch_random_number_generator.h"
|
||||
#include "catch_stream.h"
|
||||
#include "catch_output_redirect.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
@@ -10,54 +11,12 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class RedirectedStream {
|
||||
std::ostream& m_originalStream;
|
||||
std::ostream& m_redirectionStream;
|
||||
std::streambuf* m_prevBuf;
|
||||
|
||||
public:
|
||||
RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
|
||||
: m_originalStream( originalStream ),
|
||||
m_redirectionStream( redirectionStream ),
|
||||
m_prevBuf( m_originalStream.rdbuf() )
|
||||
{
|
||||
m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
|
||||
}
|
||||
~RedirectedStream() {
|
||||
m_originalStream.rdbuf( m_prevBuf );
|
||||
}
|
||||
};
|
||||
|
||||
class RedirectedStdOut {
|
||||
ReusableStringStream m_rss;
|
||||
RedirectedStream m_cout;
|
||||
public:
|
||||
RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
|
||||
auto str() const -> std::string { return m_rss.str(); }
|
||||
};
|
||||
|
||||
// StdErr has two constituent streams in C++, std::cerr and std::clog
|
||||
// This means that we need to redirect 2 streams into 1 to keep proper
|
||||
// order of writes
|
||||
class RedirectedStdErr {
|
||||
ReusableStringStream m_rss;
|
||||
RedirectedStream m_cerr;
|
||||
RedirectedStream m_clog;
|
||||
public:
|
||||
RedirectedStdErr()
|
||||
: m_cerr( Catch::cerr(), m_rss.get() ),
|
||||
m_clog( Catch::clog(), m_rss.get() )
|
||||
{}
|
||||
auto str() const -> std::string { return m_rss.str(); }
|
||||
};
|
||||
|
||||
|
||||
RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
|
||||
: m_runInfo(_config->name()),
|
||||
m_context(getCurrentMutableContext()),
|
||||
m_config(_config),
|
||||
m_reporter(std::move(reporter)),
|
||||
m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal },
|
||||
m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
|
||||
m_includeSuccessfulResults( m_config->includeSuccessfulResults() )
|
||||
{
|
||||
m_context.setRunner(this);
|
||||
@@ -84,7 +43,7 @@ namespace Catch {
|
||||
std::string redirectedCout;
|
||||
std::string redirectedCerr;
|
||||
|
||||
TestCaseInfo testInfo = testCase.getTestCaseInfo();
|
||||
auto const& testInfo = testCase.getTestCaseInfo();
|
||||
|
||||
m_reporter->testCaseStarting(testInfo);
|
||||
|
||||
@@ -292,20 +251,26 @@ namespace Catch {
|
||||
Counts prevAssertions = m_totals.assertions;
|
||||
double duration = 0;
|
||||
m_shouldReportUnexpected = true;
|
||||
m_lastAssertionInfo = { "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal };
|
||||
m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
|
||||
|
||||
seedRng(*m_config);
|
||||
|
||||
Timer timer;
|
||||
try {
|
||||
if (m_reporter->getPreferences().shouldRedirectStdOut) {
|
||||
#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
|
||||
RedirectedStdOut redirectedStdOut;
|
||||
RedirectedStdErr redirectedStdErr;
|
||||
|
||||
timer.start();
|
||||
invokeActiveTestCase();
|
||||
redirectedCout += redirectedStdOut.str();
|
||||
redirectedCerr += redirectedStdErr.str();
|
||||
|
||||
#else
|
||||
OutputRedirect r(redirectedCout, redirectedCerr);
|
||||
timer.start();
|
||||
invokeActiveTestCase();
|
||||
#endif
|
||||
} else {
|
||||
timer.start();
|
||||
invokeActiveTestCase();
|
||||
@@ -321,12 +286,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);
|
||||
}
|
||||
|
@@ -99,7 +99,7 @@ namespace Catch {
|
||||
|
||||
public:
|
||||
// !TBD We need to do this another way!
|
||||
bool aborting() const override;
|
||||
bool aborting() const final;
|
||||
|
||||
private:
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -18,6 +18,9 @@
|
||||
#include "catch_random_number_generator.h"
|
||||
#include "catch_startup_exception_registry.h"
|
||||
#include "catch_text.h"
|
||||
#include "catch_stream.h"
|
||||
#include "catch_windows_h_proxy.h"
|
||||
#include "../reporters/catch_reporter_listening.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iomanip>
|
||||
@@ -34,33 +37,26 @@ namespace Catch {
|
||||
return reporter;
|
||||
}
|
||||
|
||||
#ifndef CATCH_CONFIG_DEFAULT_REPORTER
|
||||
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
|
||||
#endif
|
||||
|
||||
IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {
|
||||
auto const& reporterNames = config->getReporterNames();
|
||||
if (reporterNames.empty())
|
||||
return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config);
|
||||
if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {
|
||||
return createReporter(config->getReporterName(), config);
|
||||
}
|
||||
|
||||
IStreamingReporterPtr reporter;
|
||||
for (auto const& name : reporterNames)
|
||||
addReporter(reporter, createReporter(name, config));
|
||||
return reporter;
|
||||
}
|
||||
auto multi = std::unique_ptr<ListeningReporter>(new ListeningReporter);
|
||||
|
||||
#undef CATCH_CONFIG_DEFAULT_REPORTER
|
||||
|
||||
void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) {
|
||||
auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
|
||||
for (auto const& listener : listeners)
|
||||
addReporter(reporters, listener->create(Catch::ReporterConfig(config)));
|
||||
for (auto const& listener : listeners) {
|
||||
multi->addListener(listener->create(Catch::ReporterConfig(config)));
|
||||
}
|
||||
multi->addReporter(createReporter(config->getReporterName(), config));
|
||||
return std::move(multi);
|
||||
}
|
||||
|
||||
|
||||
Catch::Totals runTests(std::shared_ptr<Config> const& config) {
|
||||
IStreamingReporterPtr reporter = makeReporter(config);
|
||||
addListeners(reporter, config);
|
||||
// FixMe: Add listeners in order first, then add reporters.
|
||||
|
||||
auto reporter = makeReporter(config);
|
||||
|
||||
RunContext context(config, std::move(reporter));
|
||||
|
||||
@@ -69,8 +65,6 @@ namespace Catch {
|
||||
context.testGroupStarting(config->name(), 1, 1);
|
||||
|
||||
TestSpec testSpec = config->testSpec();
|
||||
if (!testSpec.hasFilters())
|
||||
testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests
|
||||
|
||||
auto const& allTestCases = getAllTestCasesSorted(*config);
|
||||
for (auto const& testCase : allTestCases) {
|
||||
@@ -80,6 +74,20 @@ namespace Catch {
|
||||
context.reporter().skipTest(testCase);
|
||||
}
|
||||
|
||||
if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
|
||||
ReusableStringStream testConfig;
|
||||
|
||||
bool first = true;
|
||||
for (const auto& input : config->getTestsOrTags()) {
|
||||
if (!first) { testConfig << ' '; }
|
||||
first = false;
|
||||
testConfig << input;
|
||||
}
|
||||
|
||||
context.reporter().noMatchingTestCases(testConfig.str());
|
||||
totals.error = -1;
|
||||
}
|
||||
|
||||
context.testGroupEnded(config->name(), totals, 1, 1);
|
||||
return totals;
|
||||
}
|
||||
@@ -119,7 +127,7 @@ namespace Catch {
|
||||
if ( !exceptions.empty() ) {
|
||||
m_startupExceptions = true;
|
||||
Colour colourGuard( Colour::Red );
|
||||
Catch::cerr() << "Errors occured during startup!" << '\n';
|
||||
Catch::cerr() << "Errors occurred during startup!" << '\n';
|
||||
// iterate over all exceptions and notify user
|
||||
for ( const auto& ex_ptr : exceptions ) {
|
||||
try {
|
||||
@@ -151,7 +159,7 @@ namespace Catch {
|
||||
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
|
||||
}
|
||||
|
||||
int Session::applyCommandLine( int argc, char* argv[] ) {
|
||||
int Session::applyCommandLine( int argc, char const * const * argv ) {
|
||||
if( m_startupExceptions )
|
||||
return 1;
|
||||
|
||||
@@ -188,7 +196,7 @@ namespace Catch {
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
#if defined(WIN32) && defined(UNICODE)
|
||||
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
|
||||
int Session::run( int argc, wchar_t* const argv[] ) {
|
||||
|
||||
char **utf8Argv = new char *[ argc ];
|
||||
@@ -259,10 +267,11 @@ namespace Catch {
|
||||
if( Option<std::size_t> listed = list( config() ) )
|
||||
return static_cast<int>( *listed );
|
||||
|
||||
auto totals = runTests( m_config );
|
||||
// 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 ) );
|
||||
return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
|
||||
}
|
||||
catch( std::exception& ex ) {
|
||||
Catch::cerr() << ex.what() << std::endl;
|
||||
|
@@ -25,12 +25,12 @@ namespace Catch {
|
||||
void showHelp() const;
|
||||
void libIdentify();
|
||||
|
||||
int applyCommandLine( int argc, char* argv[] );
|
||||
int applyCommandLine( int argc, char const * const * argv );
|
||||
|
||||
void useConfigData( ConfigData const& configData );
|
||||
|
||||
int run( int argc, char* argv[] );
|
||||
#if defined(WIN32) && defined(UNICODE)
|
||||
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
|
||||
int run( int argc, wchar_t* const argv[] );
|
||||
#endif
|
||||
int run();
|
||||
|
@@ -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
|
||||
@@ -36,7 +43,7 @@ namespace Catch {
|
||||
const_cast<StringRef*>( this )->takeOwnership();
|
||||
return m_start;
|
||||
}
|
||||
auto StringRef::data() const noexcept -> char const* {
|
||||
auto StringRef::currentData() const noexcept -> char const* {
|
||||
return m_start;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -106,7 +112,12 @@ namespace Catch {
|
||||
}
|
||||
|
||||
auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
|
||||
return os << str.c_str();
|
||||
return os.write(str.currentData(), str.size());
|
||||
}
|
||||
|
||||
auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {
|
||||
lhs.append(rhs.currentData(), rhs.size());
|
||||
return lhs;
|
||||
}
|
||||
|
||||
} // namespace Catch
|
||||
|
@@ -12,7 +12,7 @@
|
||||
#include <iosfwd>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
|
||||
class StringData;
|
||||
|
||||
/// A non-owning string class (similar to the forthcoming std::string_view)
|
||||
@@ -31,13 +31,13 @@ namespace Catch {
|
||||
|
||||
char const* m_start;
|
||||
size_type m_size;
|
||||
|
||||
|
||||
char* m_data = nullptr;
|
||||
|
||||
|
||||
void takeOwnership();
|
||||
|
||||
static constexpr char const* const s_empty = "";
|
||||
|
||||
|
||||
public: // construction/ assignment
|
||||
StringRef() noexcept
|
||||
: StringRef( s_empty, 0 )
|
||||
@@ -83,13 +83,13 @@ namespace Catch {
|
||||
operator std::string() const;
|
||||
|
||||
void swap( StringRef& other ) noexcept;
|
||||
|
||||
|
||||
public: // operators
|
||||
auto operator == ( StringRef const& other ) const noexcept -> bool;
|
||||
auto operator != ( StringRef const& other ) const noexcept -> bool;
|
||||
|
||||
|
||||
auto operator[] ( size_type index ) const noexcept -> char;
|
||||
|
||||
|
||||
public: // named queries
|
||||
auto empty() const noexcept -> bool {
|
||||
return m_size == 0;
|
||||
@@ -100,22 +100,27 @@ namespace Catch {
|
||||
|
||||
auto numberOfCharacters() const noexcept -> size_type;
|
||||
auto c_str() const -> char const*;
|
||||
|
||||
|
||||
public: // substrings and searches
|
||||
auto substr( size_type start, size_type size ) const noexcept -> StringRef;
|
||||
|
||||
// Returns the current start pointer.
|
||||
// Note that the pointer can change when if the StringRef is a substring
|
||||
auto currentData() const noexcept -> char const*;
|
||||
|
||||
private: // ownership queries - may not be consistent between calls
|
||||
auto isOwned() const noexcept -> bool;
|
||||
auto isSubstring() const noexcept -> bool;
|
||||
auto data() const noexcept -> char const*;
|
||||
};
|
||||
|
||||
auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string;
|
||||
auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string;
|
||||
auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string;
|
||||
|
||||
auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
|
||||
auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
|
||||
|
||||
|
||||
inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
|
||||
return StringRef( rawChars, size );
|
||||
}
|
||||
|
@@ -17,8 +17,8 @@
|
||||
# pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||
# endif
|
||||
#elif defined __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
# pragma GCC diagnostic ignored "-Wparentheses"
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
# pragma GCC diagnostic ignored "-Wpadded"
|
||||
#endif
|
||||
|
@@ -37,7 +37,7 @@ namespace Catch {
|
||||
return TestCaseInfo::None;
|
||||
}
|
||||
bool isReservedTag( std::string const& tag ) {
|
||||
return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
|
||||
return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );
|
||||
}
|
||||
void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
|
||||
CATCH_ENFORCE( !isReservedTag(tag),
|
||||
@@ -48,8 +48,7 @@ namespace Catch {
|
||||
|
||||
TestCase makeTestCase( ITestInvoker* _testCase,
|
||||
std::string const& _className,
|
||||
std::string const& _name,
|
||||
std::string const& _descOrTags,
|
||||
NameAndTags const& nameAndTags,
|
||||
SourceLineInfo const& _lineInfo )
|
||||
{
|
||||
bool isHidden = false;
|
||||
@@ -58,6 +57,7 @@ namespace Catch {
|
||||
std::vector<std::string> tags;
|
||||
std::string desc, tag;
|
||||
bool inTag = false;
|
||||
std::string _descOrTags = nameAndTags.tags;
|
||||
for (char c : _descOrTags) {
|
||||
if( !inTag ) {
|
||||
if( c == '[' )
|
||||
@@ -85,8 +85,8 @@ namespace Catch {
|
||||
tags.push_back( "." );
|
||||
}
|
||||
|
||||
TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
|
||||
return TestCase( _testCase, info );
|
||||
TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );
|
||||
return TestCase( _testCase, std::move(info) );
|
||||
}
|
||||
|
||||
void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
|
||||
@@ -147,7 +147,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
|
||||
TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
|
||||
TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {}
|
||||
|
||||
|
||||
TestCase TestCase::withName( std::string const& _newName ) const {
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
|
||||
|
||||
#include "catch_common.h"
|
||||
#include "catch_test_registry.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -61,7 +62,7 @@ namespace Catch {
|
||||
class TestCase : public TestCaseInfo {
|
||||
public:
|
||||
|
||||
TestCase( ITestInvoker* testCase, TestCaseInfo const& info );
|
||||
TestCase( ITestInvoker* testCase, TestCaseInfo&& info );
|
||||
|
||||
TestCase withName( std::string const& _newName ) const;
|
||||
|
||||
@@ -78,8 +79,7 @@ namespace Catch {
|
||||
|
||||
TestCase makeTestCase( ITestInvoker* testCase,
|
||||
std::string const& className,
|
||||
std::string const& name,
|
||||
std::string const& description,
|
||||
NameAndTags const& nameAndTags,
|
||||
SourceLineInfo const& lineInfo );
|
||||
}
|
||||
|
||||
|
@@ -96,7 +96,7 @@ namespace Catch {
|
||||
m_testAsFunction();
|
||||
}
|
||||
|
||||
std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
|
||||
std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
|
||||
std::string className = classOrQualifiedMethodName;
|
||||
if( startsWith( className, '&' ) )
|
||||
{
|
||||
|
@@ -22,7 +22,7 @@ namespace Catch {
|
||||
class TestCase;
|
||||
struct IConfig;
|
||||
|
||||
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
|
||||
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
|
||||
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
|
||||
|
||||
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
|
||||
@@ -58,7 +58,7 @@ namespace Catch {
|
||||
};
|
||||
|
||||
|
||||
std::string extractClassName( std::string const& classOrQualifiedMethodName );
|
||||
std::string extractClassName( StringRef const& classOrQualifiedMethodName );
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@@ -10,7 +10,7 @@
|
||||
#include "catch_enforce.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
@@ -15,23 +15,22 @@ namespace Catch {
|
||||
return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
|
||||
}
|
||||
|
||||
NameAndTags::NameAndTags( StringRef name_ , StringRef tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
|
||||
NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
|
||||
|
||||
AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept {
|
||||
AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {
|
||||
try {
|
||||
getMutableRegistryHub()
|
||||
.registerTest(
|
||||
makeTestCase(
|
||||
invoker,
|
||||
extractClassName( classOrMethod ),
|
||||
nameAndTags.name,
|
||||
nameAndTags.tags,
|
||||
nameAndTags,
|
||||
lineInfo));
|
||||
} catch (...) {
|
||||
// Do not throw when constructing global objects, instead register the exception to be processed later
|
||||
getMutableRegistryHub().registerStartupException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AutoReg::~AutoReg() = default;
|
||||
}
|
||||
|
@@ -35,24 +35,29 @@ auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
|
||||
}
|
||||
|
||||
struct NameAndTags {
|
||||
NameAndTags( StringRef name_ = StringRef(), StringRef tags_ = StringRef() ) noexcept;
|
||||
NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
|
||||
StringRef name;
|
||||
StringRef tags;
|
||||
};
|
||||
|
||||
struct AutoReg : NonCopyable {
|
||||
AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept;
|
||||
AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
|
||||
~AutoReg();
|
||||
};
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
|
||||
#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
|
||||
#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
|
||||
#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
|
||||
|
||||
#if defined(CATCH_CONFIG_DISABLE)
|
||||
#define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
|
||||
static void TestName()
|
||||
#define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
|
||||
namespace{ \
|
||||
struct TestName : ClassName { \
|
||||
struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
|
||||
void test(); \
|
||||
}; \
|
||||
} \
|
||||
@@ -80,7 +85,7 @@ struct AutoReg : NonCopyable {
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||
namespace{ \
|
||||
struct TestName : ClassName{ \
|
||||
struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
|
||||
void test(); \
|
||||
}; \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
||||
|
@@ -10,6 +10,8 @@
|
||||
|
||||
#include <chrono>
|
||||
|
||||
static const uint64_t nanosecondsInSecond = 1000000000;
|
||||
|
||||
namespace Catch {
|
||||
|
||||
auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
|
||||
@@ -20,17 +22,25 @@ namespace Catch {
|
||||
uint64_t sum = 0;
|
||||
static const uint64_t iterations = 1000000;
|
||||
|
||||
auto startTime = getCurrentNanosecondsSinceEpoch();
|
||||
|
||||
for( std::size_t i = 0; i < iterations; ++i ) {
|
||||
|
||||
uint64_t ticks;
|
||||
uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
|
||||
do {
|
||||
ticks = getCurrentNanosecondsSinceEpoch();
|
||||
}
|
||||
while( ticks == baseTicks );
|
||||
} while( ticks == baseTicks );
|
||||
|
||||
auto delta = ticks - baseTicks;
|
||||
sum += delta;
|
||||
|
||||
// If we have been calibrating for over 3 seconds -- the clock
|
||||
// is terrible and we should move on.
|
||||
// TBD: How to signal that the measured resolution is probably wrong?
|
||||
if (ticks > startTime + 3 * nanosecondsInSecond) {
|
||||
return sum / i;
|
||||
}
|
||||
}
|
||||
|
||||
// We're just taking the mean, here. To do better we could take the std. dev and exclude outliers
|
||||
|
28
include/internal/catch_to_string.hpp
Normal file
28
include/internal/catch_to_string.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Created by Martin on 9/5/2018.
|
||||
*
|
||||
* 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_TO_STRING_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_TO_STRING_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "catch_compiler_capabilities.h"
|
||||
#include "catch_stream.h"
|
||||
|
||||
namespace Catch {
|
||||
template <typename T>
|
||||
std::string to_string(T const& t) {
|
||||
#if defined(CATCH_CONFIG_CPP11_TO_STRING)
|
||||
return std::to_string(t);
|
||||
#else
|
||||
ReusableStringStream rss;
|
||||
rss << t;
|
||||
return rss.str();
|
||||
#endif
|
||||
}
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_TO_STRING_H_INCLUDED
|
@@ -116,6 +116,7 @@ std::string StringMaker<std::string>::convert(const std::string& str) {
|
||||
return s;
|
||||
}
|
||||
|
||||
#ifdef CATCH_CONFIG_WCHAR
|
||||
std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
|
||||
std::string s;
|
||||
s.reserve(wstr.size());
|
||||
@@ -124,6 +125,7 @@ std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
|
||||
}
|
||||
return ::Catch::Detail::stringify(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string StringMaker<char const*>::convert(char const* str) {
|
||||
if (str) {
|
||||
@@ -139,6 +141,7 @@ std::string StringMaker<char*>::convert(char* str) {
|
||||
return{ "{null string}" };
|
||||
}
|
||||
}
|
||||
#ifdef CATCH_CONFIG_WCHAR
|
||||
std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {
|
||||
if (str) {
|
||||
return ::Catch::Detail::stringify(std::wstring{ str });
|
||||
@@ -153,6 +156,7 @@ std::string StringMaker<wchar_t *>::convert(wchar_t * str) {
|
||||
return{ "{null string}" };
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
std::string StringMaker<int>::convert(int value) {
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
#include "catch_compiler_capabilities.h"
|
||||
#include "catch_stream.h"
|
||||
|
||||
#ifdef __OBJC__
|
||||
@@ -61,13 +62,37 @@ namespace Catch {
|
||||
std::string convertUnknownEnumToString( E e );
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<!std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& ) {
|
||||
typename std::enable_if<
|
||||
!std::is_enum<T>::value && !std::is_base_of<std::exception, 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 ) {
|
||||
typename std::enable_if<
|
||||
!std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
|
||||
std::string>::type convertUnstreamable(T const& ex) {
|
||||
return ex.what();
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<
|
||||
std::is_enum<T>::value
|
||||
, std::string>::type convertUnstreamable( T const& value ) {
|
||||
return convertUnknownEnumToString( value );
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(_MANAGED)
|
||||
//! Convert a CLR string to a utf8 std::string
|
||||
template<typename T>
|
||||
std::string clrReferenceToString( T^ ref ) {
|
||||
if (ref == nullptr)
|
||||
return std::string("null");
|
||||
auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
|
||||
cli::pin_ptr<System::Byte> p = &bytes[0];
|
||||
return std::string(reinterpret_cast<char const *>(p), bytes->Length);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
@@ -80,7 +105,9 @@ namespace Catch {
|
||||
typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
|
||||
convert(const Fake& value) {
|
||||
ReusableStringStream rss;
|
||||
rss << value;
|
||||
// NB: call using the function-like syntax to avoid ambiguity with
|
||||
// user-defined templated operator<< under clang.
|
||||
rss.operator<<(value);
|
||||
return rss.str();
|
||||
}
|
||||
|
||||
@@ -88,7 +115,11 @@ namespace Catch {
|
||||
static
|
||||
typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
|
||||
convert( const Fake& value ) {
|
||||
return Detail::convertUnstreamable( value );
|
||||
#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
|
||||
return Detail::convertUnstreamable(value);
|
||||
#else
|
||||
return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -106,6 +137,13 @@ namespace Catch {
|
||||
return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e));
|
||||
}
|
||||
|
||||
#if defined(_MANAGED)
|
||||
template <typename T>
|
||||
std::string stringify( T^ e ) {
|
||||
return ::Catch::StringMaker<T^>::convert(e);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
// Some predefined specializations
|
||||
@@ -114,10 +152,12 @@ namespace Catch {
|
||||
struct StringMaker<std::string> {
|
||||
static std::string convert(const std::string& str);
|
||||
};
|
||||
#ifdef CATCH_CONFIG_WCHAR
|
||||
template<>
|
||||
struct StringMaker<std::wstring> {
|
||||
static std::string convert(const std::wstring& wstr);
|
||||
};
|
||||
#endif
|
||||
|
||||
template<>
|
||||
struct StringMaker<char const *> {
|
||||
@@ -127,6 +167,8 @@ namespace Catch {
|
||||
struct StringMaker<char *> {
|
||||
static std::string convert(char * str);
|
||||
};
|
||||
|
||||
#ifdef CATCH_CONFIG_WCHAR
|
||||
template<>
|
||||
struct StringMaker<wchar_t const *> {
|
||||
static std::string convert(wchar_t const * str);
|
||||
@@ -135,23 +177,26 @@ namespace Catch {
|
||||
struct StringMaker<wchar_t *> {
|
||||
static std::string convert(wchar_t * str);
|
||||
};
|
||||
#endif
|
||||
|
||||
// TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,
|
||||
// while keeping string semantics?
|
||||
template<int SZ>
|
||||
struct StringMaker<char[SZ]> {
|
||||
static std::string convert(const char* str) {
|
||||
static std::string convert(char const* str) {
|
||||
return ::Catch::Detail::stringify(std::string{ str });
|
||||
}
|
||||
};
|
||||
template<int SZ>
|
||||
struct StringMaker<signed char[SZ]> {
|
||||
static std::string convert(const char* str) {
|
||||
return ::Catch::Detail::stringify(std::string{ str });
|
||||
static std::string convert(signed char const* str) {
|
||||
return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
|
||||
}
|
||||
};
|
||||
template<int SZ>
|
||||
struct StringMaker<unsigned char[SZ]> {
|
||||
static std::string convert(const char* str) {
|
||||
return ::Catch::Detail::stringify(std::string{ str });
|
||||
static std::string convert(unsigned char const* str) {
|
||||
return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -235,6 +280,15 @@ namespace Catch {
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(_MANAGED)
|
||||
template <typename T>
|
||||
struct StringMaker<T^> {
|
||||
static std::string convert( T^ ref ) {
|
||||
return ::Catch::Detail::clrReferenceToString(ref);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace Detail {
|
||||
template<typename InputIterator>
|
||||
std::string rangeToString(InputIterator first, InputIterator last) {
|
||||
@@ -364,6 +418,13 @@ namespace Catch {
|
||||
!std::is_same<decltype(end(std::declval<T>())), not_this_one>::value;
|
||||
};
|
||||
|
||||
#if defined(_MANAGED) // Managed types are never ranges
|
||||
template <typename T>
|
||||
struct is_range<T^> {
|
||||
static const bool value = false;
|
||||
};
|
||||
#endif
|
||||
|
||||
template<typename Range>
|
||||
std::string rangeToString( Range const& range ) {
|
||||
return ::Catch::Detail::rangeToString( begin( range ), end( range ) );
|
||||
@@ -387,7 +448,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
struct StringMaker<R, typename std::enable_if<is_range<R>::value && !std::is_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 );
|
||||
}
|
||||
|
@@ -32,7 +32,7 @@ namespace Catch {
|
||||
|
||||
Totals delta( Totals const& prevTotals ) const;
|
||||
|
||||
|
||||
int error = 0;
|
||||
Counts assertions;
|
||||
Counts testCases;
|
||||
};
|
||||
|
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, 1, "", 0 );
|
||||
static Version version( 2, 2, 3, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
|
@@ -7,51 +7,145 @@
|
||||
|
||||
#include "catch_xmlwriter.h"
|
||||
|
||||
#include "catch_enforce.h"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
using uchar = unsigned char;
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace {
|
||||
|
||||
size_t trailingBytes(unsigned char c) {
|
||||
if ((c & 0xE0) == 0xC0) {
|
||||
return 2;
|
||||
}
|
||||
if ((c & 0xF0) == 0xE0) {
|
||||
return 3;
|
||||
}
|
||||
if ((c & 0xF8) == 0xF0) {
|
||||
return 4;
|
||||
}
|
||||
CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
|
||||
}
|
||||
|
||||
uint32_t headerValue(unsigned char c) {
|
||||
if ((c & 0xE0) == 0xC0) {
|
||||
return c & 0x1F;
|
||||
}
|
||||
if ((c & 0xF0) == 0xE0) {
|
||||
return c & 0x0F;
|
||||
}
|
||||
if ((c & 0xF8) == 0xF0) {
|
||||
return c & 0x07;
|
||||
}
|
||||
CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
|
||||
}
|
||||
|
||||
void hexEscapeChar(std::ostream& os, unsigned char c) {
|
||||
os << "\\x"
|
||||
<< std::uppercase << std::hex << std::setfill('0') << std::setw(2)
|
||||
<< static_cast<int>(c);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
|
||||
: m_str( str ),
|
||||
m_forWhat( forWhat )
|
||||
{}
|
||||
|
||||
void XmlEncode::encodeTo( std::ostream& os ) const {
|
||||
|
||||
// Apostrophe escaping not necessary if we always use " to write attributes
|
||||
// (see: http://www.w3.org/TR/xml/#syntax)
|
||||
|
||||
for( std::size_t i = 0; i < m_str.size(); ++ i ) {
|
||||
char c = m_str[i];
|
||||
switch( c ) {
|
||||
case '<': os << "<"; break;
|
||||
case '&': os << "&"; break;
|
||||
for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
|
||||
uchar c = m_str[idx];
|
||||
switch (c) {
|
||||
case '<': os << "<"; break;
|
||||
case '&': os << "&"; break;
|
||||
|
||||
case '>':
|
||||
// See: http://www.w3.org/TR/xml/#syntax
|
||||
if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
|
||||
os << ">";
|
||||
else
|
||||
os << c;
|
||||
case '>':
|
||||
// See: http://www.w3.org/TR/xml/#syntax
|
||||
if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
|
||||
os << ">";
|
||||
else
|
||||
os << c;
|
||||
break;
|
||||
|
||||
case '\"':
|
||||
if (m_forWhat == ForAttributes)
|
||||
os << """;
|
||||
else
|
||||
os << c;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Check for control characters and invalid utf-8
|
||||
|
||||
// Escape control characters in standard ascii
|
||||
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
|
||||
if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
|
||||
hexEscapeChar(os, c);
|
||||
break;
|
||||
}
|
||||
|
||||
case '\"':
|
||||
if( m_forWhat == ForAttributes )
|
||||
os << """;
|
||||
else
|
||||
os << c;
|
||||
// Plain ASCII: Write it to stream
|
||||
if (c < 0x7F) {
|
||||
os << c;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Escape control chars - based on contribution by @espenalb in PR #465 and
|
||||
// by @mrpi PR #588
|
||||
if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) {
|
||||
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
|
||||
os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
|
||||
<< static_cast<int>( c );
|
||||
}
|
||||
else
|
||||
os << c;
|
||||
// UTF-8 territory
|
||||
// Check if the encoding is valid and if it is not, hex escape bytes.
|
||||
// Important: We do not check the exact decoded values for validity, only the encoding format
|
||||
// First check that this bytes is a valid lead byte:
|
||||
// This means that it is not encoded as 1111 1XXX
|
||||
// Or as 10XX XXXX
|
||||
if (c < 0xC0 ||
|
||||
c >= 0xF8) {
|
||||
hexEscapeChar(os, c);
|
||||
break;
|
||||
}
|
||||
|
||||
auto encBytes = trailingBytes(c);
|
||||
// Are there enough bytes left to avoid accessing out-of-bounds memory?
|
||||
if (idx + encBytes - 1 >= m_str.size()) {
|
||||
hexEscapeChar(os, c);
|
||||
break;
|
||||
}
|
||||
// The header is valid, check data
|
||||
// The next encBytes bytes must together be a valid utf-8
|
||||
// This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
|
||||
bool valid = true;
|
||||
uint32_t value = headerValue(c);
|
||||
for (std::size_t n = 1; n < encBytes; ++n) {
|
||||
uchar nc = m_str[idx + n];
|
||||
valid &= ((nc & 0xC0) == 0x80);
|
||||
value = (value << 6) | (nc & 0x3F);
|
||||
}
|
||||
|
||||
if (
|
||||
// Wrong bit pattern of following bytes
|
||||
(!valid) ||
|
||||
// Overlong encodings
|
||||
(value < 0x80) ||
|
||||
(0x80 <= value && value < 0x800 && encBytes > 2) ||
|
||||
(0x800 < value && value < 0x10000 && encBytes > 3) ||
|
||||
// Encoded value out of range
|
||||
(value >= 0x110000)
|
||||
) {
|
||||
hexEscapeChar(os, c);
|
||||
break;
|
||||
}
|
||||
|
||||
// If we got here, this is in fact a valid(ish) utf-8 sequence
|
||||
for (std::size_t n = 0; n < encBytes; ++n) {
|
||||
os << m_str[idx + n];
|
||||
}
|
||||
idx += encBytes - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -56,7 +56,7 @@ namespace Catch {
|
||||
|
||||
XmlWriter( std::ostream& os = Catch::cout() );
|
||||
~XmlWriter();
|
||||
|
||||
|
||||
XmlWriter( XmlWriter const& ) = delete;
|
||||
XmlWriter& operator=( XmlWriter const& ) = delete;
|
||||
|
||||
|
@@ -13,7 +13,7 @@
|
||||
#include <cstring>
|
||||
#include <cfloat>
|
||||
#include <cstdio>
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
namespace Catch {
|
||||
|
@@ -14,7 +14,7 @@
|
||||
#include <cstring>
|
||||
#include <cfloat>
|
||||
#include <cstdio>
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
|
||||
|
@@ -13,7 +13,7 @@
|
||||
#include "../internal/catch_tostring.h"
|
||||
#include "../internal/catch_reporter_registrars.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <ctime>
|
||||
#include <algorithm>
|
||||
@@ -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";
|
||||
|
136
include/reporters/catch_reporter_listening.cpp
Normal file
136
include/reporters/catch_reporter_listening.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Created by Phil on 5/08/2015.
|
||||
* Copyright 2015 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_reporter_listening.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {
|
||||
m_listeners.push_back( std::move( listener ) );
|
||||
}
|
||||
|
||||
void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {
|
||||
assert(!m_reporter && "Listening reporter can wrap only 1 real reporter");
|
||||
m_reporter = std::move( reporter );
|
||||
}
|
||||
|
||||
ReporterPreferences ListeningReporter::getPreferences() const {
|
||||
return m_reporter->getPreferences();
|
||||
}
|
||||
|
||||
std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {
|
||||
return std::set<Verbosity>{ };
|
||||
}
|
||||
|
||||
|
||||
void ListeningReporter::noMatchingTestCases( std::string const& spec ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->noMatchingTestCases( spec );
|
||||
}
|
||||
m_reporter->noMatchingTestCases( spec );
|
||||
}
|
||||
|
||||
void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->benchmarkStarting( benchmarkInfo );
|
||||
}
|
||||
m_reporter->benchmarkStarting( benchmarkInfo );
|
||||
}
|
||||
void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->benchmarkEnded( benchmarkStats );
|
||||
}
|
||||
m_reporter->benchmarkEnded( benchmarkStats );
|
||||
}
|
||||
|
||||
void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->testRunStarting( testRunInfo );
|
||||
}
|
||||
m_reporter->testRunStarting( testRunInfo );
|
||||
}
|
||||
|
||||
void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->testGroupStarting( groupInfo );
|
||||
}
|
||||
m_reporter->testGroupStarting( groupInfo );
|
||||
}
|
||||
|
||||
|
||||
void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->testCaseStarting( testInfo );
|
||||
}
|
||||
m_reporter->testCaseStarting( testInfo );
|
||||
}
|
||||
|
||||
void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->sectionStarting( sectionInfo );
|
||||
}
|
||||
m_reporter->sectionStarting( sectionInfo );
|
||||
}
|
||||
|
||||
void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->assertionStarting( assertionInfo );
|
||||
}
|
||||
m_reporter->assertionStarting( assertionInfo );
|
||||
}
|
||||
|
||||
// The return value indicates if the messages buffer should be cleared:
|
||||
bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) {
|
||||
for( auto const& listener : m_listeners ) {
|
||||
static_cast<void>( listener->assertionEnded( assertionStats ) );
|
||||
}
|
||||
return m_reporter->assertionEnded( assertionStats );
|
||||
}
|
||||
|
||||
void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->sectionEnded( sectionStats );
|
||||
}
|
||||
m_reporter->sectionEnded( sectionStats );
|
||||
}
|
||||
|
||||
void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->testCaseEnded( testCaseStats );
|
||||
}
|
||||
m_reporter->testCaseEnded( testCaseStats );
|
||||
}
|
||||
|
||||
void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->testGroupEnded( testGroupStats );
|
||||
}
|
||||
m_reporter->testGroupEnded( testGroupStats );
|
||||
}
|
||||
|
||||
void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->testRunEnded( testRunStats );
|
||||
}
|
||||
m_reporter->testRunEnded( testRunStats );
|
||||
}
|
||||
|
||||
|
||||
void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) {
|
||||
for ( auto const& listener : m_listeners ) {
|
||||
listener->skipTest( testInfo );
|
||||
}
|
||||
m_reporter->skipTest( testInfo );
|
||||
}
|
||||
|
||||
bool ListeningReporter::isMulti() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
@@ -11,12 +11,14 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class MultipleReporters : public IStreamingReporter {
|
||||
class ListeningReporter : public IStreamingReporter {
|
||||
using Reporters = std::vector<IStreamingReporterPtr>;
|
||||
Reporters m_reporters;
|
||||
Reporters m_listeners;
|
||||
IStreamingReporterPtr m_reporter = nullptr;
|
||||
|
||||
public:
|
||||
void add( IStreamingReporterPtr&& reporter );
|
||||
void addListener( IStreamingReporterPtr&& listener );
|
||||
void addReporter( IStreamingReporterPtr&& reporter );
|
||||
|
||||
public: // IStreamingReporter
|
||||
|
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Created by Phil on 5/08/2015.
|
||||
* Copyright 2015 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_reporter_multi.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
void MultipleReporters::add( IStreamingReporterPtr&& reporter ) {
|
||||
m_reporters.push_back( std::move( reporter ) );
|
||||
}
|
||||
|
||||
ReporterPreferences MultipleReporters::getPreferences() const {
|
||||
return m_reporters[0]->getPreferences();
|
||||
}
|
||||
|
||||
std::set<Verbosity> MultipleReporters::getSupportedVerbosities() {
|
||||
return std::set<Verbosity>{ };
|
||||
}
|
||||
|
||||
|
||||
void MultipleReporters::noMatchingTestCases( std::string const& spec ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->noMatchingTestCases( spec );
|
||||
}
|
||||
|
||||
void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->benchmarkStarting( benchmarkInfo );
|
||||
}
|
||||
void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->benchmarkEnded( benchmarkStats );
|
||||
}
|
||||
|
||||
void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->testRunStarting( testRunInfo );
|
||||
}
|
||||
|
||||
void MultipleReporters::testGroupStarting( GroupInfo const& groupInfo ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->testGroupStarting( groupInfo );
|
||||
}
|
||||
|
||||
|
||||
void MultipleReporters::testCaseStarting( TestCaseInfo const& testInfo ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->testCaseStarting( testInfo );
|
||||
}
|
||||
|
||||
void MultipleReporters::sectionStarting( SectionInfo const& sectionInfo ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->sectionStarting( sectionInfo );
|
||||
}
|
||||
|
||||
void MultipleReporters::assertionStarting( AssertionInfo const& assertionInfo ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->assertionStarting( assertionInfo );
|
||||
}
|
||||
|
||||
// The return value indicates if the messages buffer should be cleared:
|
||||
bool MultipleReporters::assertionEnded( AssertionStats const& assertionStats ) {
|
||||
bool clearBuffer = false;
|
||||
for( auto const& reporter : m_reporters )
|
||||
clearBuffer |= reporter->assertionEnded( assertionStats );
|
||||
return clearBuffer;
|
||||
}
|
||||
|
||||
void MultipleReporters::sectionEnded( SectionStats const& sectionStats ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->sectionEnded( sectionStats );
|
||||
}
|
||||
|
||||
void MultipleReporters::testCaseEnded( TestCaseStats const& testCaseStats ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->testCaseEnded( testCaseStats );
|
||||
}
|
||||
|
||||
void MultipleReporters::testGroupEnded( TestGroupStats const& testGroupStats ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->testGroupEnded( testGroupStats );
|
||||
}
|
||||
|
||||
void MultipleReporters::testRunEnded( TestRunStats const& testRunStats ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->testRunEnded( testRunStats );
|
||||
}
|
||||
|
||||
|
||||
void MultipleReporters::skipTest( TestCaseInfo const& testInfo ) {
|
||||
for( auto const& reporter : m_reporters )
|
||||
reporter->skipTest( testInfo );
|
||||
}
|
||||
|
||||
bool MultipleReporters::isMulti() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
@@ -26,7 +26,7 @@ namespace Catch {
|
||||
~TAPReporter() override;
|
||||
|
||||
static std::string getDescription() {
|
||||
return "Reports test results in TAP format, suitable for test harneses";
|
||||
return "Reports test results in TAP format, suitable for test harnesses";
|
||||
}
|
||||
|
||||
ReporterPreferences getPreferences() const override {
|
||||
|
@@ -1,12 +1,26 @@
|
||||
@REM # In debug build, we want to
|
||||
@REM # 1) Prebuild memcheck redirecter
|
||||
@REM # 2) Regenerate single header include for examples
|
||||
@REM # 3) Enable building examples
|
||||
|
||||
@REM # Possibilities:
|
||||
@REM # Debug build + coverage
|
||||
@REM # Debug build + examples
|
||||
@REM # Debug build + ---
|
||||
@REM # Release build
|
||||
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% -DCATCH_BUILD_EXAMPLES=ON -DMEMORYCHECK_COMMAND=build-misc\Debug\CoverageHelper.exe -DMEMORYCHECK_COMMAND_OPTIONS=--sep-- -DMEMORYCHECK_TYPE=Valgrind
|
||||
if "%coverage%"=="1" (
|
||||
@REM # coverage needs to build the special helper as well as the main
|
||||
cmake -Hmisc -Bbuild-misc -A%PLATFORM%
|
||||
cmake --build build-misc
|
||||
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DMEMORYCHECK_COMMAND=build-misc\Debug\CoverageHelper.exe -DMEMORYCHECK_COMMAND_OPTIONS=--sep-- -DMEMORYCHECK_TYPE=Valgrind
|
||||
) else (
|
||||
@REM # We know that coverage is 0
|
||||
if "%examples%"=="1" (
|
||||
@REM # Examples live off the single header, so it needs to be regenerated
|
||||
python scripts\generateSingleHeader.py
|
||||
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DCATCH_BUILD_EXAMPLES=ON
|
||||
) else (
|
||||
@REM # This is just a plain debug build
|
||||
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain%
|
||||
)
|
||||
)
|
||||
)
|
||||
if "%CONFIGURATION%"=="Release" (
|
||||
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain%
|
||||
|
@@ -1,8 +1,12 @@
|
||||
cd Build
|
||||
if "%CONFIGURATION%"=="Debug" (
|
||||
ctest -j 2 -C %CONFIGURATION% -D ExperimentalMemCheck
|
||||
python ..\misc\appveyorMergeCoverageScript.py
|
||||
codecov --root .. --no-color --disable gcov -f cobertura.xml -t %CODECOV_TOKEN%
|
||||
if "%coverage%"=="1" (
|
||||
ctest -j 2 -C %CONFIGURATION% -D ExperimentalMemCheck
|
||||
python ..\misc\appveyorMergeCoverageScript.py
|
||||
codecov --root .. --no-color --disable gcov -f cobertura.xml -t %CODECOV_TOKEN%
|
||||
) else (
|
||||
ctest -j 2 -C %CONFIGURATION%
|
||||
)
|
||||
)
|
||||
if "%CONFIGURATION%"=="Release" (
|
||||
ctest -j 2 -C %CONFIGURATION%
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# Downloads are done from the oficial github release page links
|
||||
$downloadUrl = "https://github.com/OpenCppCoverage/OpenCppCoverage/releases/download/release-0.9.6.1/OpenCppCoverageSetup-x64-0.9.6.1.exe"
|
||||
# Downloads are done from the official github release page links
|
||||
$downloadUrl = "https://github.com/OpenCppCoverage/OpenCppCoverage/releases/download/release-0.9.7.0/OpenCppCoverageSetup-x64-0.9.7.0.exe"
|
||||
$installerPath = [System.IO.Path]::Combine($Env:USERPROFILE, "Downloads", "OpenCppCoverageSetup.exe")
|
||||
|
||||
if(-Not (Test-Path $installerPath)) {
|
||||
|
@@ -53,7 +53,7 @@
|
||||
:test-result: PASS Inequality checks that should succeed
|
||||
:test-result: PASS Less-than inequalities with different epsilons
|
||||
:test-result: PASS Long strings can be wrapped
|
||||
:test-result: PASS Long text is truncted
|
||||
:test-result: PASS Long text is truncated
|
||||
:test-result: PASS ManuallyRegistered
|
||||
:test-result: PASS Matchers can be (AllOf) composed with the && operator
|
||||
:test-result: PASS Matchers can be (AnyOf) composed with the || operator
|
||||
|
@@ -9,6 +9,10 @@ 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: {?} >= {?}
|
||||
Misc.tests.cpp:<line number>: passed:
|
||||
Compilation.tests.cpp:<line number>: passed: std::memcmp(uarr, "123", sizeof(uarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"'
|
||||
Compilation.tests.cpp:<line number>: passed: std::memcmp(sarr, "456", sizeof(sarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"'
|
||||
Compilation.tests.cpp:<line number>: passed:
|
||||
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'
|
||||
@@ -96,6 +100,10 @@ Approx.tests.cpp:<line number>: passed: 0 == Approx( dZero) for: 0 == Approx( 0.
|
||||
Approx.tests.cpp:<line number>: passed: 0 == Approx( dSmall ).margin( 0.001 ) for: 0 == Approx( 0.00001 )
|
||||
Approx.tests.cpp:<line number>: passed: 1.234f == Approx( dMedium ) for: 1.234f == Approx( 1.234 )
|
||||
Approx.tests.cpp:<line number>: passed: dMedium == Approx( 1.234f ) for: 1.234 == Approx( 1.2339999676 )
|
||||
Matchers.tests.cpp:<line number>: passed: 1, Predicate<int>(alwaysTrue, "always true") for: 1 matches predicate: "always true"
|
||||
Matchers.tests.cpp:<line number>: passed: 1, !Predicate<int>(alwaysFalse, "always false") for: 1 not matches predicate: "always false"
|
||||
Matchers.tests.cpp:<line number>: passed: "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal"
|
||||
Matchers.tests.cpp:<line number>: passed: "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate
|
||||
Tricky.tests.cpp:<line number>: passed: true
|
||||
Tricky.tests.cpp:<line number>: passed: true
|
||||
Tricky.tests.cpp:<line number>: passed: true
|
||||
@@ -203,14 +211,21 @@ Matchers.tests.cpp:<line number>: passed: testStringForMatching(), Equals("this
|
||||
Matchers.tests.cpp:<line number>: passed: testStringForMatching(), Equals("this string contains 'ABC' as a substring", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" (case insensitive)
|
||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Equals("this string contains 'ABC' as a substring") for: "this string contains 'abc' as a substring" equals: "this string contains 'ABC' as a substring"
|
||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Equals("something else", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" equals: "something else" (case insensitive)
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method" for: "This exception has overriden what() method"
|
||||
==
|
||||
"This exception has overriden what() method"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(OperatorException{}) == "OperatorException" for: "OperatorException" == "OperatorException"
|
||||
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException" for: "StringMakerException"
|
||||
==
|
||||
"StringMakerException"
|
||||
Matchers.tests.cpp:<line number>: failed: expected exception, got none; expression was: doesNotThrow(), SpecialException, ExceptionMatcher{1}
|
||||
Matchers.tests.cpp:<line number>: failed: expected exception, got none; expression was: doesNotThrow(), SpecialException, ExceptionMatcher{1}
|
||||
Matchers.tests.cpp:<line number>: failed: unexpected exception with message: 'Unknown exception'; expression was: throwsAsInt(1), SpecialException, ExceptionMatcher{1}
|
||||
Matchers.tests.cpp:<line number>: failed: unexpected exception with message: 'Unknown exception'; expression was: throwsAsInt(1), SpecialException, ExceptionMatcher{1}
|
||||
Matchers.tests.cpp:<line number>: failed: throws(3), SpecialException, ExceptionMatcher{1} for: {?} special exception has value of 1
|
||||
Matchers.tests.cpp:<line number>: failed: throws(4), SpecialException, ExceptionMatcher{1} for: {?} special exception has value of 1
|
||||
Matchers.tests.cpp:<line number>: passed: throws(1), SpecialException, ExceptionMatcher{1} for: {?} special exception has value of 1
|
||||
Matchers.tests.cpp:<line number>: passed: throws(2), SpecialException, ExceptionMatcher{2} for: {?} special exception has value of 2
|
||||
Matchers.tests.cpp:<line number>: failed: throws(3), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
|
||||
Matchers.tests.cpp:<line number>: failed: throws(4), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
|
||||
Matchers.tests.cpp:<line number>: passed: throws(1), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
|
||||
Matchers.tests.cpp:<line number>: passed: throws(2), SpecialException, ExceptionMatcher{2} for: SpecialException::what special exception has value of 2
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows(), "expected exception" for: "expected exception" equals: "expected exception"
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) for: "expected exception" equals: "expected exception" (case insensitive)
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows(), StartsWith( "expected" ) for: "expected exception" starts with: "expected"
|
||||
@@ -234,10 +249,14 @@ Matchers.tests.cpp:<line number>: passed: 0., WithinAbs(1., 1) for: 0.0 is withi
|
||||
Matchers.tests.cpp:<line number>: passed: 0., !WithinAbs(1., 0.99) for: 0.0 not is within 0.99 of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: 0., !WithinAbs(1., 0.99) for: 0.0 not is within 0.99 of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: NAN, !WithinAbs(NAN, 0) for: nanf not is within 0.0 of nan
|
||||
Matchers.tests.cpp:<line number>: passed: 11., !WithinAbs(10., 0.5) for: 11.0 not is within 0.5 of 10.0
|
||||
Matchers.tests.cpp:<line number>: passed: 10., !WithinAbs(11., 0.5) for: 10.0 not is within 0.5 of 11.0
|
||||
Matchers.tests.cpp:<line number>: passed: -10., WithinAbs(-10., 0.5) for: -10.0 is within 0.5 of -10.0
|
||||
Matchers.tests.cpp:<line number>: passed: -10., WithinAbs(-9.6, 0.5) for: -10.0 is within 0.5 of -9.6
|
||||
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: std::nextafter(1., 2.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: std::nextafter(1., 0.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: std::nextafter(1., 2.), !WithinULP(1., 0) for: 1.0 not is within 0 ULPs of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1., 2.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1., 0.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1., 2.), !WithinULP(1., 0) for: 1.0 not is within 0 ULPs of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: -0., WithinULP(0., 0) for: -0.0 is within 0 ULPs of 0.0
|
||||
Matchers.tests.cpp:<line number>: passed: NAN, !WithinULP(NAN, 123) for: nanf not is within 123 ULPs of nanf
|
||||
@@ -254,10 +273,14 @@ Matchers.tests.cpp:<line number>: passed: 0.f, !WithinAbs(1.f, 0.99f) for: 0.0f
|
||||
Matchers.tests.cpp:<line number>: passed: 0.f, !WithinAbs(1.f, 0.99f) for: 0.0f not is within 0.9900000095 of 1.0
|
||||
Matchers.tests.cpp:<line number>: passed: 0.f, WithinAbs(-0.f, 0) for: 0.0f is within 0.0 of -0.0
|
||||
Matchers.tests.cpp:<line number>: passed: NAN, !WithinAbs(NAN, 0) for: nanf not is within 0.0 of nan
|
||||
Matchers.tests.cpp:<line number>: passed: 11.f, !WithinAbs(10.f, 0.5f) for: 11.0f not is within 0.5 of 10.0
|
||||
Matchers.tests.cpp:<line number>: passed: 10.f, !WithinAbs(11.f, 0.5f) for: 10.0f not is within 0.5 of 11.0
|
||||
Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs(-10.f, 0.5f) for: -10.0f is within 0.5 of -10.0
|
||||
Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs(-9.6f, 0.5f) for: -10.0f is within 0.5 of -9.6000003815
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.0f
|
||||
Matchers.tests.cpp:<line number>: passed: std::nextafter(1.f, 2.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f
|
||||
Matchers.tests.cpp:<line number>: passed: std::nextafter(1.f, 0.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f
|
||||
Matchers.tests.cpp:<line number>: passed: std::nextafter(1.f, 2.f), !WithinULP(1.f, 0) for: 1.0f not is within 0 ULPs of 1.0f
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 2.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 0.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f
|
||||
Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 2.f), !WithinULP(1.f, 0) for: 1.0f not is within 0 ULPs of 1.0f
|
||||
Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.0f
|
||||
Matchers.tests.cpp:<line number>: passed: -0.f, WithinULP(0.f, 0) for: -0.0f is within 0 ULPs of 0.0f
|
||||
Matchers.tests.cpp:<line number>: passed: NAN, !WithinULP(NAN, 123) for: nanf not is within 123 ULPs of nanf
|
||||
@@ -513,26 +536,27 @@ CmdLine.tests.cpp:<line number>: passed: config.processName == "test" for: "test
|
||||
CmdLine.tests.cpp:<line number>: passed: config.shouldDebugBreak == false for: false == false
|
||||
CmdLine.tests.cpp:<line number>: passed: config.abortAfter == -1 for: -1 == -1
|
||||
CmdLine.tests.cpp:<line number>: passed: config.noThrow == false for: false == false
|
||||
CmdLine.tests.cpp:<line number>: passed: config.reporterNames.empty() for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: config.reporterName == "console" for: "console" == "console"
|
||||
CmdLine.tests.cpp:<line number>: passed: !(cfg.hasTestFilters()) for: !false
|
||||
CmdLine.tests.cpp:<line number>: passed: result for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: cfg.hasTestFilters() for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("notIncluded")) == false for: false == false
|
||||
CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("test1")) for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: result for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: cfg.hasTestFilters() for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("test1")) == false for: false == false
|
||||
CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: result for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: cfg.hasTestFilters() for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("test1")) == false for: false == false
|
||||
CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) for: true
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-r", "console"}) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.reporterNames[0] == "console" for: "console" == "console"
|
||||
CmdLine.tests.cpp:<line number>: passed: config.reporterName == "console" for: "console" == "console"
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-r", "xml"}) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.reporterNames[0] == "xml" for: "xml" == "xml"
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-r", "xml", "-r", "junit"}) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.reporterNames.size() == 2 for: 2 == 2
|
||||
CmdLine.tests.cpp:<line number>: passed: config.reporterNames[0] == "xml" for: "xml" == "xml"
|
||||
CmdLine.tests.cpp:<line number>: passed: config.reporterNames[1] == "junit" for: "junit" == "junit"
|
||||
CmdLine.tests.cpp:<line number>: passed: config.reporterName == "xml" for: "xml" == "xml"
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--reporter", "junit"}) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.reporterNames[0] == "junit" for: "junit" == "junit"
|
||||
CmdLine.tests.cpp:<line number>: passed: config.reporterName == "junit" for: "junit" == "junit"
|
||||
CmdLine.tests.cpp:<line number>: passed: !(cli.parse({ "test", "-r", "xml", "-r", "junit" })) for: !{?}
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-b"}) for: {?}
|
||||
CmdLine.tests.cpp:<line number>: passed: config.shouldDebugBreak == true for: true == true
|
||||
CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--break"}) for: {?}
|
||||
@@ -622,18 +646,21 @@ String.tests.cpp:<line number>: passed: isOwned( s ) == false for: false == fals
|
||||
String.tests.cpp:<line number>: passed: s.c_str() == rawChars for: "hello" == "hello"
|
||||
String.tests.cpp:<line number>: passed: isOwned( s ) == false for: false == false
|
||||
String.tests.cpp:<line number>: passed: original == "original"
|
||||
String.tests.cpp:<line number>: failed: isSubstring( original ) for: false
|
||||
String.tests.cpp:<line number>: passed: isSubstring( original ) for: true
|
||||
String.tests.cpp:<line number>: passed: isOwned( original ) == false for: false == false
|
||||
String.tests.cpp:<line number>: passed: isSubstring( original ) == false for: false == false
|
||||
String.tests.cpp:<line number>: passed: isOwned( original ) for: true
|
||||
String.tests.cpp:<line number>: passed: ss.empty() == false for: false == false
|
||||
String.tests.cpp:<line number>: passed: ss.size() == 5 for: 5 == 5
|
||||
String.tests.cpp:<line number>: passed: std::strcmp( ss.c_str(), "hello" ) == 0 for: 0 == 0
|
||||
String.tests.cpp:<line number>: passed: ss == "hello" for: hello == "hello"
|
||||
String.tests.cpp:<line number>: passed: isSubstring( ss ) for: true
|
||||
String.tests.cpp:<line number>: passed: isOwned( ss ) == false for: false == false
|
||||
String.tests.cpp:<line number>: passed: rawChars == data( s ) for: "hello world!" == "hello world!"
|
||||
String.tests.cpp:<line number>: passed: rawChars == s.currentData() for: "hello world!" == "hello world!"
|
||||
String.tests.cpp:<line number>: passed: ss.c_str() != rawChars for: "hello" != "hello world!"
|
||||
String.tests.cpp:<line number>: passed: isSubstring( ss ) == false for: false == false
|
||||
String.tests.cpp:<line number>: passed: isOwned( ss ) for: true
|
||||
String.tests.cpp:<line number>: passed: data( ss ) != data( s ) for: "hello" != "hello world!"
|
||||
String.tests.cpp:<line number>: passed: ss.currentData() != s.currentData() for: "hello" != "hello world!"
|
||||
String.tests.cpp:<line number>: passed: ss.size() == 6 for: 6 == 6
|
||||
String.tests.cpp:<line number>: passed: std::strcmp( ss.c_str(), "world!" ) == 0 for: 0 == 0
|
||||
String.tests.cpp:<line number>: passed: s.c_str() == s2.c_str() for: "hello world!" == "hello world!"
|
||||
@@ -652,6 +679,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
|
||||
@@ -689,6 +719,7 @@ VariadicMacros.tests.cpp:<line number>: passed: with 1 message: 'no assertions'
|
||||
Tricky.tests.cpp:<line number>: passed: 0x<hex digits> == bit30and31 for: 3221225472 (0x<hex digits>) == 3221225472
|
||||
Message.tests.cpp:<line number>: failed - but was ok: 1 == 2
|
||||
Misc.tests.cpp:<line number>: passed: with 1 message: 'oops!'
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'For some reason someone is throwing a string literal!'
|
||||
PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true
|
||||
PartTracker.tests.cpp:<line number>: passed: s1.isOpen() for: true
|
||||
PartTracker.tests.cpp:<line number>: passed: s1.isSuccessfullyCompleted() for: true
|
||||
@@ -885,6 +916,48 @@ Xml.tests.cpp:<line number>: passed: encode( stringWithQuotes, Catch::XmlEncode:
|
||||
"don't "quote" me on that"
|
||||
Xml.tests.cpp:<line number>: passed: encode( "[/x01]" ) == "[//x01]" for: "[/x01]" == "[/x01]"
|
||||
Xml.tests.cpp:<line number>: passed: encode( "[/x7F]" ) == "[//x7F]" for: "[/x7F]" == "[/x7F]"
|
||||
Xml.tests.cpp:<line number>: passed: encode(u8"Here be 👾") == u8"Here be 👾" for: "Here be 👾" == "Here be 👾"
|
||||
Xml.tests.cpp:<line number>: passed: encode(u8"šš") == u8"šš" for: "šš" == "šš"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xDF/xBF") == "/xDF/xBF" for: "߿" == "߿"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xE0/xA0/x80") == "/xE0/xA0/x80" for: "ࠀ" == "ࠀ"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xED/x9F/xBF") == "/xED/x9F/xBF" for: "" == ""
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xEE/x80/x80") == "/xEE/x80/x80" for: "" == ""
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xEF/xBF/xBF") == "/xEF/xBF/xBF" for: "" == ""
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF0/x90/x80/x80") == "/xF0/x90/x80/x80" for: "𐀀" == "𐀀"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF4/x8F/xBF/xBF") == "/xF4/x8F/xBF/xBF" for: "" == ""
|
||||
Xml.tests.cpp:<line number>: passed: encode("Here /xFF be 👾") == u8"Here //xFF be 👾" for: "Here /xFF be 👾" == "Here /xFF be 👾"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xFF") == "//xFF" for: "/xFF" == "/xFF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xC5/xC5/xA0") == u8"//xC5Š" for: "/xC5Š" == "/xC5Š"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF4/x90/x80/x80") == u8"//xF4//x90//x80//x80" for: "/xF4/x90/x80/x80" == "/xF4/x90/x80/x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xC0/x80") == u8"//xC0//x80" for: "/xC0/x80" == "/xC0/x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF0/x80/x80/x80") == u8"//xF0//x80//x80//x80" for: "/xF0/x80/x80/x80" == "/xF0/x80/x80/x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xC1/xBF") == u8"//xC1//xBF" for: "/xC1/xBF" == "/xC1/xBF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xE0/x9F/xBF") == u8"//xE0//x9F//xBF" for: "/xE0/x9F/xBF" == "/xE0/x9F/xBF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF0/x8F/xBF/xBF") == u8"//xF0//x8F//xBF//xBF" for: "/xF0/x8F/xBF/xBF" == "/xF0/x8F/xBF/xBF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xED/xA0/x80") == "/xED/xA0/x80" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xED/xAF/xBF") == "/xED/xAF/xBF" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xED/xB0/x80") == "/xED/xB0/x80" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xED/xBF/xBF") == "/xED/xBF/xBF" for: "<22><><EFBFBD>" == "<22><><EFBFBD>"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/x80") == u8"//x80" for: "/x80" == "/x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/x81") == u8"//x81" for: "/x81" == "/x81"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xBC") == u8"//xBC" for: "/xBC" == "/xBC"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xBF") == u8"//xBF" for: "/xBF" == "/xBF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF5/x80/x80/x80") == u8"//xF5//x80//x80//x80" for: "/xF5/x80/x80/x80" == "/xF5/x80/x80/x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF6/x80/x80/x80") == u8"//xF6//x80//x80//x80" for: "/xF6/x80/x80/x80" == "/xF6/x80/x80/x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF7/x80/x80/x80") == u8"//xF7//x80//x80//x80" for: "/xF7/x80/x80/x80" == "/xF7/x80/x80/x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xDE") == u8"//xDE" for: "/xDE" == "/xDE"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xDF") == u8"//xDF" for: "/xDF" == "/xDF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xE0") == u8"//xE0" for: "/xE0" == "/xE0"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xEF") == u8"//xEF" for: "/xEF" == "/xEF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF0") == u8"//xF0" for: "/xF0" == "/xF0"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF4") == u8"//xF4" for: "/xF4" == "/xF4"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xE0/x80") == u8"//xE0//x80" for: "/xE0/x80" == "/xE0/x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xE0/xBF") == u8"//xE0//xBF" for: "/xE0/xBF" == "/xE0/xBF"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xE1/x80") == u8"//xE1//x80" for: "/xE1/x80" == "/xE1/x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF0/x80") == u8"//xF0//x80" for: "/xF0/x80" == "/xF0/x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF4/x80") == u8"//xF4//x80" for: "/xF4/x80" == "/xF4/x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF0/x80/x80") == u8"//xF0//x80//x80" for: "/xF0/x80/x80" == "/xF0/x80/x80"
|
||||
Xml.tests.cpp:<line number>: passed: encode("/xF4/x80/x80") == u8"//xF4//x80//x80" for: "/xF4/x80/x80" == "/xF4/x80/x80"
|
||||
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( empty ) == "{ }" for: "{ }" == "{ }"
|
||||
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( oneValue ) == "{ 42 }" for: "{ 42 }" == "{ 42 }"
|
||||
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( twoValues ) == "{ 42, 250 }" for: "{ 42, 250 }" == "{ 42, 250 }"
|
||||
@@ -974,19 +1047,27 @@ ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pr ) =
|
||||
==
|
||||
"{ { "green", 55 } }"
|
||||
Tricky.tests.cpp:<line number>: failed: std::string( "first" ) == "second" for: "first" == "second"
|
||||
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( item ) == "StringMaker<has_maker>" for: "StringMaker<has_maker>"
|
||||
==
|
||||
"StringMaker<has_maker>"
|
||||
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" for: "StringMaker<has_maker_and_operator>"
|
||||
==
|
||||
"StringMaker<has_maker_and_operator>"
|
||||
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(item) == "{ !!! }" for: "{ !!! }" == "{ !!! }"
|
||||
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" for: "operator<<( has_operator )"
|
||||
==
|
||||
"operator<<( has_operator )"
|
||||
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""
|
||||
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
|
||||
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( item ) == "operator<<( has_template_operator )" for: "operator<<( has_template_operator )"
|
||||
==
|
||||
"operator<<( has_template_operator )"
|
||||
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" for: "{ StringMaker<has_maker> }"
|
||||
==
|
||||
"{ StringMaker<has_maker> }"
|
||||
@@ -996,6 +1077,11 @@ ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( v ) =
|
||||
ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" for: "{ operator<<( has_operator ) }"
|
||||
==
|
||||
"{ operator<<( has_operator ) }"
|
||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'Why would you throw a std::string?'
|
||||
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""
|
||||
Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
|
||||
EnumToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(e0) == "E2/V0" for: "E2/V0" == "E2/V0"
|
||||
EnumToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(e1) == "E2/V1" for: "E2/V1" == "E2/V1"
|
||||
EnumToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(e3) == "Unknown enum value 10" for: "Unknown enum value 10"
|
||||
@@ -1058,5 +1144,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 62 test cases, failed 121 assertions.
|
||||
|
||||
|
@@ -335,12 +335,12 @@ Matchers.tests.cpp:<line number>
|
||||
Matchers.tests.cpp:<line number>: FAILED:
|
||||
CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{1} )
|
||||
with expansion:
|
||||
{?} special exception has value of 1
|
||||
SpecialException::what special exception has value of 1
|
||||
|
||||
Matchers.tests.cpp:<line number>: FAILED:
|
||||
REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{1} )
|
||||
with expansion:
|
||||
{?} special exception has value of 1
|
||||
SpecialException::what special exception has value of 1
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Expected exceptions that don't throw or unexpected exceptions fail the test
|
||||
@@ -738,6 +738,16 @@ with expansion:
|
||||
}
|
||||
"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Thrown string literals are translated
|
||||
-------------------------------------------------------------------------------
|
||||
Exception.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Exception.tests.cpp:<line number>: FAILED:
|
||||
due to unexpected exception with message:
|
||||
For some reason someone is throwing a string literal!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Unexpected exceptions can be translated
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -1063,7 +1073,17 @@ Tricky.tests.cpp:<line number>: FAILED:
|
||||
with expansion:
|
||||
"first" == "second"
|
||||
|
||||
===============================================================================
|
||||
test cases: 197 | 146 passed | 47 failed | 4 failed as expected
|
||||
assertions: 992 | 866 passed | 105 failed | 21 failed as expected
|
||||
-------------------------------------------------------------------------------
|
||||
thrown std::strings are translated
|
||||
-------------------------------------------------------------------------------
|
||||
Exception.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Exception.tests.cpp:<line number>: FAILED:
|
||||
due to unexpected exception with message:
|
||||
Why would you throw a std::string?
|
||||
|
||||
===============================================================================
|
||||
test cases: 208 | 155 passed | 49 failed | 4 failed as expected
|
||||
assertions: 1065 | 937 passed | 107 failed | 21 failed as expected
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -93,6 +93,48 @@ PASSED:
|
||||
with expansion:
|
||||
{?} >= {?}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1175 - Hidden Test
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Misc.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1238
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( std::memcmp(uarr, "123", sizeof(uarr)) == 0 )
|
||||
with expansion:
|
||||
0 == 0
|
||||
with messages:
|
||||
uarr := "123"
|
||||
sarr := "456"
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( std::memcmp(sarr, "456", sizeof(sarr)) == 0 )
|
||||
with expansion:
|
||||
0 == 0
|
||||
with messages:
|
||||
uarr := "123"
|
||||
sarr := "456"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1245
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#748 - captures with unexpected exceptions
|
||||
outside assertions
|
||||
@@ -299,6 +341,6 @@ with expansion:
|
||||
!true
|
||||
|
||||
===============================================================================
|
||||
test cases: 11 | 8 passed | 1 failed | 2 failed as expected
|
||||
assertions: 34 | 27 passed | 4 failed | 3 failed as expected
|
||||
test cases: 14 | 11 passed | 1 failed | 2 failed as expected
|
||||
assertions: 38 | 31 passed | 4 failed | 3 failed as expected
|
||||
|
||||
|
@@ -1,11 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuitesloose text artifact
|
||||
>
|
||||
<testsuite name="<exe-name>" errors="15" failures="94" tests="992" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="17" failures="105" tests="1080" 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="#1175 - Hidden Test" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="#1238" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.(Fixture_1245<int, int>)" name="#1245" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
expected exception
|
||||
@@ -109,6 +112,8 @@ Exception.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Approximate comparisons with floats" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Approximate comparisons with ints" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Approximate comparisons with mixed numeric types" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Function pointer" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Lambdas + different type" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Assertions then sections" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Assertions then sections/A section" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another section" time="{duration}"/>
|
||||
@@ -213,6 +218,7 @@ Matchers.tests.cpp:<line number>
|
||||
Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Exception matchers that fail/No exception" time="{duration}">
|
||||
<failure message="doesNotThrow(), SpecialException, ExceptionMatcher{1}" type="CHECK_THROWS_MATCHES">
|
||||
Matchers.tests.cpp:<line number>
|
||||
@@ -232,10 +238,10 @@ Matchers.tests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Exception matchers that fail/Contents are wrong" time="{duration}">
|
||||
<failure message="{?} special exception has value of 1" type="CHECK_THROWS_MATCHES">
|
||||
<failure message="SpecialException::what special exception has value of 1" type="CHECK_THROWS_MATCHES">
|
||||
Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="{?} special exception has value of 1" type="REQUIRE_THROWS_MATCHES">
|
||||
<failure message="SpecialException::what special exception has value of 1" type="REQUIRE_THROWS_MATCHES">
|
||||
Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
@@ -470,8 +476,8 @@ Message.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/test lists/Specify one test case exclusion using ~" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/-r/console" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/-r/xml" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/-r xml and junit" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/--reporter/junit" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/Only one reporter is accepted" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/debugger/-b" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/debugger/--break" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Process can be configured on command line/abort/-a aborts after first failure" time="{duration}"/>
|
||||
@@ -545,11 +551,7 @@ Matchers.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/Empty string" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/From string literal" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/From string literal/c_str() does not cause copy" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/From sub-string" time="{duration}">
|
||||
<failure message="false" type="REQUIRE">
|
||||
String.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/From sub-string" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/Substrings/zero-based substring" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/Substrings/c_str() causes copy" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="StringRef/Substrings/non-zero-based substring" time="{duration}"/>
|
||||
@@ -562,6 +564,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}"/>
|
||||
@@ -583,6 +586,12 @@ Misc.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Test enum bit values" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="The NO_FAIL macro reports a failure but does not fail the test" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="This test 'should' fail but doesn't" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Thrown string literals are translated" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
For some reason someone is throwing a string literal!
|
||||
Exception.tests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Tracker" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Tracker/successfully close one section" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Tracker/fail one section" time="{duration}"/>
|
||||
@@ -702,6 +711,12 @@ Exception.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode/string with quotes" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode/string with control char (1)" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode/string with control char (x7F)" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Valid utf-8 strings" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Various broken strings" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Overlong encodings" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Surrogate pairs" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Invalid start byte" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Missing continuation byte(s)" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="array<int, N> -> toString" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="atomic if" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="boolean member" time="{duration}"/>
|
||||
@@ -818,16 +833,25 @@ Message.tests.cpp:<line number>
|
||||
Tricky.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="stringify ranges" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="stringify( has_maker )" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="stringify( has_maker_and_toString )" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="stringify( has_maker_and_operator )" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="stringify( has_neither )" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="stringify( has_operator )" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="stringify( has_template_operator )" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="stringify( vectors<has_maker> )" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="stringify( vectors<has_maker_and_operator> )" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="stringify( vectors<has_operator> )" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="thrown std::strings are translated" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
Why would you throw a std::string?
|
||||
Exception.tests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="toString on const wchar_t const pointer returns the string contents" time="{duration}"/>
|
||||
<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( 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}"/>
|
||||
<testcase classname="<exe-name>.global" name="toString(enum class w/operator<<)" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="toString(enum class)" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="toString(enum w/operator<<)" time="{duration}"/>
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@
|
||||
# pragma clang diagnostic ignored "-Wc++98-compat"
|
||||
#endif
|
||||
|
||||
inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( nullptr, "", name, desc, CATCH_INTERNAL_LINEINFO ); }
|
||||
inline Catch::TestCase fakeTestCase(const char* name, const char* desc = "") { return Catch::makeTestCase(nullptr, "", { name, desc }, CATCH_INTERNAL_LINEINFO); }
|
||||
|
||||
TEST_CASE( "Parse test names and tags" ) {
|
||||
|
||||
@@ -288,7 +288,10 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
|
||||
CHECK(config.shouldDebugBreak == false);
|
||||
CHECK(config.abortAfter == -1);
|
||||
CHECK(config.noThrow == false);
|
||||
CHECK(config.reporterNames.empty());
|
||||
CHECK(config.reporterName == "console");
|
||||
|
||||
Catch::Config cfg(config);
|
||||
CHECK_FALSE(cfg.hasTestFilters());
|
||||
}
|
||||
|
||||
SECTION("test lists") {
|
||||
@@ -297,6 +300,7 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
|
||||
CHECK(result);
|
||||
|
||||
Catch::Config cfg(config);
|
||||
REQUIRE(cfg.hasTestFilters());
|
||||
REQUIRE(cfg.testSpec().matches(fakeTestCase("notIncluded")) == false);
|
||||
REQUIRE(cfg.testSpec().matches(fakeTestCase("test1")));
|
||||
}
|
||||
@@ -305,6 +309,7 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
|
||||
CHECK(result);
|
||||
|
||||
Catch::Config cfg(config);
|
||||
REQUIRE(cfg.hasTestFilters());
|
||||
REQUIRE(cfg.testSpec().matches(fakeTestCase("test1")) == false);
|
||||
REQUIRE(cfg.testSpec().matches(fakeTestCase("alwaysIncluded")));
|
||||
}
|
||||
@@ -314,6 +319,7 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
|
||||
CHECK(result);
|
||||
|
||||
Catch::Config cfg(config);
|
||||
REQUIRE(cfg.hasTestFilters());
|
||||
REQUIRE(cfg.testSpec().matches(fakeTestCase("test1")) == false);
|
||||
REQUIRE(cfg.testSpec().matches(fakeTestCase("alwaysIncluded")));
|
||||
}
|
||||
@@ -324,24 +330,20 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
|
||||
SECTION("-r/console") {
|
||||
CHECK(cli.parse({"test", "-r", "console"}));
|
||||
|
||||
REQUIRE(config.reporterNames[0] == "console");
|
||||
REQUIRE(config.reporterName == "console");
|
||||
}
|
||||
SECTION("-r/xml") {
|
||||
CHECK(cli.parse({"test", "-r", "xml"}));
|
||||
|
||||
REQUIRE(config.reporterNames[0] == "xml");
|
||||
}
|
||||
SECTION("-r xml and junit") {
|
||||
CHECK(cli.parse({"test", "-r", "xml", "-r", "junit"}));
|
||||
|
||||
REQUIRE(config.reporterNames.size() == 2);
|
||||
REQUIRE(config.reporterNames[0] == "xml");
|
||||
REQUIRE(config.reporterNames[1] == "junit");
|
||||
REQUIRE(config.reporterName == "xml");
|
||||
}
|
||||
SECTION("--reporter/junit") {
|
||||
CHECK(cli.parse({"test", "--reporter", "junit"}));
|
||||
|
||||
REQUIRE(config.reporterNames[0] == "junit");
|
||||
REQUIRE(config.reporterName == "junit");
|
||||
}
|
||||
SECTION("Only one reporter is accepted") {
|
||||
REQUIRE_FALSE(cli.parse({ "test", "-r", "xml", "-r", "junit" }));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -14,9 +14,6 @@ namespace Catch {
|
||||
static auto isSubstring( StringRef const& stringRef ) -> bool {
|
||||
return stringRef.isSubstring();
|
||||
}
|
||||
static auto data( StringRef const& stringRef ) -> char const* {
|
||||
return stringRef.data();
|
||||
}
|
||||
};
|
||||
|
||||
auto isOwned( StringRef const& stringRef ) -> bool {
|
||||
@@ -25,19 +22,16 @@ namespace Catch {
|
||||
auto isSubstring( StringRef const& stringRef ) -> bool {
|
||||
return StringRefTestAccess::isSubstring( stringRef );
|
||||
}
|
||||
auto data( StringRef const& stringRef ) -> char const* {
|
||||
return StringRefTestAccess::data( stringRef );
|
||||
}
|
||||
} // namespace Catch2
|
||||
|
||||
namespace Catch {
|
||||
inline auto toString( Catch::StringRef const& stringRef ) -> std::string {
|
||||
return std::string( data( stringRef ), stringRef.size() );
|
||||
return std::string( stringRef.currentData(), stringRef.size() );
|
||||
}
|
||||
} // namespace Catch
|
||||
|
||||
TEST_CASE( "StringRef", "[Strings]" ) {
|
||||
|
||||
TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
||||
|
||||
using Catch::StringRef;
|
||||
|
||||
SECTION( "Empty string" ) {
|
||||
@@ -46,21 +40,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 );
|
||||
|
||||
auto rawChars = s.currentData();
|
||||
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 +63,18 @@ 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 +84,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
|
||||
|
||||
auto rawChars = ss.currentData();
|
||||
REQUIRE( rawChars == s.currentData() ); // same pointer value
|
||||
REQUIRE( ss.c_str() != rawChars );
|
||||
|
||||
|
||||
REQUIRE( isSubstring( ss ) == false );
|
||||
REQUIRE( isOwned( ss ) );
|
||||
|
||||
REQUIRE( data( ss ) != data( s ) ); // different pointer value
|
||||
|
||||
REQUIRE( ss.currentData() != s.currentData() ); // 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 +157,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" ) );
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "internal/catch_xmlwriter.h"
|
||||
|
||||
#include <sstream>
|
||||
@@ -10,7 +9,7 @@ inline std::string encode( std::string const& str, Catch::XmlEncode::ForWhat for
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
TEST_CASE( "XmlEncode" ) {
|
||||
TEST_CASE( "XmlEncode", "[XML]" ) {
|
||||
SECTION( "normal string" ) {
|
||||
REQUIRE( encode( "normal string" ) == "normal string" );
|
||||
}
|
||||
@@ -38,4 +37,76 @@ TEST_CASE( "XmlEncode" ) {
|
||||
SECTION( "string with control char (x7F)" ) {
|
||||
REQUIRE( encode( "[\x7F]" ) == "[\\x7F]" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Thanks to Peter Bindels (dascandy) for some of the tests
|
||||
TEST_CASE("XmlEncode: UTF-8", "[XML][UTF-8]") {
|
||||
SECTION("Valid utf-8 strings") {
|
||||
CHECK(encode(u8"Here be 👾") == u8"Here be 👾");
|
||||
CHECK(encode(u8"šš") == u8"šš");
|
||||
|
||||
CHECK(encode("\xDF\xBF") == "\xDF\xBF"); // 0x7FF
|
||||
CHECK(encode("\xE0\xA0\x80") == "\xE0\xA0\x80"); // 0x800
|
||||
CHECK(encode("\xED\x9F\xBF") == "\xED\x9F\xBF"); // 0xD7FF
|
||||
CHECK(encode("\xEE\x80\x80") == "\xEE\x80\x80"); // 0xE000
|
||||
CHECK(encode("\xEF\xBF\xBF") == "\xEF\xBF\xBF"); // 0xFFFF
|
||||
CHECK(encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80"); // 0x10000
|
||||
CHECK(encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF"); // 0x10FFFF
|
||||
}
|
||||
SECTION("Invalid utf-8 strings") {
|
||||
SECTION("Various broken strings") {
|
||||
CHECK(encode("Here \xFF be 👾") == u8"Here \\xFF be 👾");
|
||||
CHECK(encode("\xFF") == "\\xFF");
|
||||
CHECK(encode("\xC5\xC5\xA0") == u8"\\xC5Š");
|
||||
CHECK(encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80"); // 0x110000 -- out of unicode range
|
||||
}
|
||||
|
||||
SECTION("Overlong encodings") {
|
||||
CHECK(encode("\xC0\x80") == u8"\\xC0\\x80"); // \0
|
||||
CHECK(encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80"); // Super-over-long \0
|
||||
CHECK(encode("\xC1\xBF") == u8"\\xC1\\xBF"); // ASCII char as UTF-8 (0x7F)
|
||||
CHECK(encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF"); // 0x7FF
|
||||
CHECK(encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF"); // 0xFFFF
|
||||
}
|
||||
|
||||
// Note that we actually don't modify surrogate pairs, as we do not do strict checking
|
||||
SECTION("Surrogate pairs") {
|
||||
CHECK(encode("\xED\xA0\x80") == "\xED\xA0\x80"); // Invalid surrogate half 0xD800
|
||||
CHECK(encode("\xED\xAF\xBF") == "\xED\xAF\xBF"); // Invalid surrogate half 0xDBFF
|
||||
CHECK(encode("\xED\xB0\x80") == "\xED\xB0\x80"); // Invalid surrogate half 0xDC00
|
||||
CHECK(encode("\xED\xBF\xBF") == "\xED\xBF\xBF"); // Invalid surrogate half 0xDFFF
|
||||
}
|
||||
|
||||
SECTION("Invalid start byte") {
|
||||
CHECK(encode("\x80") == u8"\\x80");
|
||||
CHECK(encode("\x81") == u8"\\x81");
|
||||
CHECK(encode("\xBC") == u8"\\xBC");
|
||||
CHECK(encode("\xBF") == u8"\\xBF");
|
||||
// Out of range
|
||||
CHECK(encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80");
|
||||
CHECK(encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80");
|
||||
CHECK(encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80");
|
||||
}
|
||||
|
||||
SECTION("Missing continuation byte(s)") {
|
||||
// Missing first continuation byte
|
||||
CHECK(encode("\xDE") == u8"\\xDE");
|
||||
CHECK(encode("\xDF") == u8"\\xDF");
|
||||
CHECK(encode("\xE0") == u8"\\xE0");
|
||||
CHECK(encode("\xEF") == u8"\\xEF");
|
||||
CHECK(encode("\xF0") == u8"\\xF0");
|
||||
CHECK(encode("\xF4") == u8"\\xF4");
|
||||
|
||||
// Missing second continuation byte
|
||||
CHECK(encode("\xE0\x80") == u8"\\xE0\\x80");
|
||||
CHECK(encode("\xE0\xBF") == u8"\\xE0\\xBF");
|
||||
CHECK(encode("\xE1\x80") == u8"\\xE1\\x80");
|
||||
CHECK(encode("\xF0\x80") == u8"\\xF0\\x80");
|
||||
CHECK(encode("\xF4\x80") == u8"\\xF4\\x80");
|
||||
|
||||
// Missing third continuation byte
|
||||
CHECK(encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80");
|
||||
CHECK(encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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 )
|
||||
|
||||
|
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace { namespace CompilationTests {
|
||||
|
||||
#ifndef COMPILATION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
|
||||
@@ -86,6 +88,9 @@ namespace { namespace CompilationTests {
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
template <typename, typename>
|
||||
struct Fixture_1245 {};
|
||||
|
||||
#endif
|
||||
|
||||
TEST_CASE("#809") {
|
||||
@@ -134,4 +139,19 @@ namespace { namespace CompilationTests {
|
||||
REQUIRE(t1 >= t2);
|
||||
}
|
||||
|
||||
// unsigned array
|
||||
TEST_CASE("#1238") {
|
||||
unsigned char uarr[] = "123";
|
||||
CAPTURE(uarr);
|
||||
signed char sarr[] = "456";
|
||||
CAPTURE(sarr);
|
||||
|
||||
REQUIRE(std::memcmp(uarr, "123", sizeof(uarr)) == 0);
|
||||
REQUIRE(std::memcmp(sarr, "456", sizeof(sarr)) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD((Fixture_1245<int, int>), "#1245", "[compilation]") {
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
}} // namespace CompilationTests
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user