mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-12 16:35:40 +02:00
Compare commits
180 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
15cf3caace | ||
![]() |
12a8dfa2f2 | ||
![]() |
797d3b04df | ||
![]() |
82b8744b8c | ||
![]() |
ce80358306 | ||
![]() |
283e2e6d41 | ||
![]() |
d6c7392b24 | ||
![]() |
9ee4c1db52 | ||
![]() |
76790604f5 | ||
![]() |
e21c6aa94d | ||
![]() |
7a59d5027f | ||
![]() |
c8941cccb5 | ||
![]() |
5eeb6aa361 | ||
![]() |
1c1b447ede | ||
![]() |
e1d81174db | ||
![]() |
4846ad59e1 | ||
![]() |
ff2b3c85a7 | ||
![]() |
b55424d3b2 | ||
![]() |
e69c7ce297 | ||
![]() |
7be8ba36c1 | ||
![]() |
ad120965cf | ||
![]() |
f460a7d8f9 | ||
![]() |
ebf89000f1 | ||
![]() |
7d00cb83f1 | ||
![]() |
e69afb6252 | ||
![]() |
9fb38fcc14 | ||
![]() |
0f49a600b0 | ||
![]() |
5c0efa1cfc | ||
![]() |
1579744ddd | ||
![]() |
9b0e740e31 | ||
![]() |
1af60ef5ab | ||
![]() |
3743295ca8 | ||
![]() |
ed582bde4d | ||
![]() |
6c1145d922 | ||
![]() |
b957eb4172 | ||
![]() |
0eb99fb569 | ||
![]() |
bf221583b1 | ||
![]() |
44722f9ed3 | ||
![]() |
35a57b070f | ||
![]() |
1dce91d78e | ||
![]() |
b8553d62a3 | ||
![]() |
504607701b | ||
![]() |
788f81230f | ||
![]() |
c5301bf8bf | ||
![]() |
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 | ||
![]() |
62dae592c3 | ||
![]() |
9a5705411a | ||
![]() |
a1aefce6e4 | ||
![]() |
d5959907f5 | ||
![]() |
31e6499e64 | ||
![]() |
b0f4f16ee0 | ||
![]() |
1e3ddbb496 | ||
![]() |
15ad95c8db | ||
![]() |
00a10d5a5e | ||
![]() |
0d687a15d3 | ||
![]() |
bdf431c400 | ||
![]() |
a0359980f0 | ||
![]() |
8d4074aad9 | ||
![]() |
f0f40a0dbf | ||
![]() |
fa4fd7f296 | ||
![]() |
07c84adfba | ||
![]() |
8d854c689b | ||
![]() |
f0909dfe02 | ||
![]() |
de36b2ada6 | ||
![]() |
9700ee4fc0 | ||
![]() |
bbda8cd77c | ||
![]() |
4575594bbf | ||
![]() |
c053dca26e | ||
![]() |
3d7104c124 | ||
![]() |
6441c20a2c | ||
![]() |
5774c4f9c2 | ||
![]() |
2bc33dd04d |
13
.gitattributes
vendored
13
.gitattributes
vendored
@@ -8,4 +8,15 @@
|
|||||||
*.hpp text
|
*.hpp text
|
||||||
|
|
||||||
# Windows specific files should retain windows line-endings
|
# Windows specific files should retain windows line-endings
|
||||||
*.sln text eol=crlf
|
*.sln text eol=crlf
|
||||||
|
|
||||||
|
# Keep executable scripts with LFs so they can be run after being
|
||||||
|
# checked out on Windows
|
||||||
|
*.py text eol=lf
|
||||||
|
|
||||||
|
|
||||||
|
# Keep the single include header with LFs to make sure it is uploaded,
|
||||||
|
# hashed etc with LF
|
||||||
|
single_include/*.hpp eol=lf
|
||||||
|
# Also keep the LICENCE file with LFs for the same reason
|
||||||
|
LICENCE.txt eol=lf
|
||||||
|
169
.travis.yml
169
.travis.yml
@@ -1,12 +1,17 @@
|
|||||||
language: cpp
|
language: cpp
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
|
branches:
|
||||||
|
except:
|
||||||
|
- /dev-appveyor.*/
|
||||||
|
|
||||||
common_sources: &all_sources
|
common_sources: &all_sources
|
||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
- llvm-toolchain-trusty
|
- llvm-toolchain-trusty
|
||||||
- llvm-toolchain-trusty-3.9
|
- llvm-toolchain-trusty-3.9
|
||||||
- llvm-toolchain-trusty-4.0
|
- llvm-toolchain-trusty-4.0
|
||||||
- llvm-toolchain-trusty-5.0
|
- llvm-toolchain-trusty-5.0
|
||||||
|
- llvm-toolchain-trusty-6.0
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
@@ -17,145 +22,169 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'lcov', 'clang-3.5']
|
packages: ['clang-3.5']
|
||||||
env: COMPILER='clang++-3.5' VALGRIND=1
|
env: COMPILER='clang++-3.5'
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'lcov', 'clang-3.6']
|
packages: ['clang-3.6']
|
||||||
env: COMPILER='clang++-3.6' VALGRIND=1
|
env: COMPILER='clang++-3.6'
|
||||||
|
|
||||||
# Travis's containers do not seem to have Clang 3.7 in apt, no matter what sources I add.
|
# Clang 3.7 is intentionally skipped as we cannot get it easily on
|
||||||
# - os: linux
|
# TravisCI container
|
||||||
# compiler: clang
|
|
||||||
# addons:
|
|
||||||
# apt:
|
|
||||||
# sources: *all_sources
|
|
||||||
# packages: ['valgrind', 'clang-3.7']
|
|
||||||
# env: COMPILER='clang++-3.7' VALGRIND=1
|
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'lcov', 'clang-3.8']
|
packages: ['lcov', 'clang-3.8']
|
||||||
env: COMPILER='clang++-3.8' VALGRIND=1
|
env: COMPILER='clang++-3.8'
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['clang-3.9', 'valgrind', 'lcov']
|
packages: ['clang-3.9']
|
||||||
env: COMPILER='clang++-3.9' VALGRIND=1
|
env: COMPILER='clang++-3.9'
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['clang-4.0', 'valgrind', 'lcov']
|
packages: ['clang-4.0']
|
||||||
env: COMPILER='clang++-4.0' VALGRIND=1
|
env: COMPILER='clang++-4.0'
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['clang-5.0', 'valgrind', 'lcov']
|
packages: ['clang-5.0']
|
||||||
env: COMPILER='clang++-5.0' VALGRIND=1
|
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
|
# 2/ Linux GCC Builds
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'lcov', 'g++-4.8']
|
packages: ['g++-4.8']
|
||||||
env: COMPILER='g++-4.8' VALGRIND=1
|
env: COMPILER='g++-4.8'
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'lcov', 'g++-4.9']
|
packages: ['g++-4.9']
|
||||||
env: COMPILER='g++-4.9' VALGRIND=1
|
env: COMPILER='g++-4.9'
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'lcov', 'g++-5']
|
packages: ['g++-5']
|
||||||
env: COMPILER='g++-5' VALGRIND=1
|
env: COMPILER='g++-5'
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
addons: &gcc6
|
addons: &gcc6
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'lcov', 'g++-6']
|
packages: ['g++-6']
|
||||||
env: COMPILER='g++-6' VALGRIND=1
|
env: COMPILER='g++-6'
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
addons: &gcc7
|
addons: &gcc7
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'lcov', 'g++-7']
|
packages: ['g++-7']
|
||||||
env: COMPILER='g++-7' VALGRIND=1
|
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
|
# 3b/ Linux C++14 Clang builds
|
||||||
|
# Note that we need newer libstdc++ for C++14 support
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages: ['clang-3.8', 'valgrind', 'lcov', 'libstdc++-6-dev']
|
packages: ['clang-3.8', 'libstdc++-6-dev']
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
- llvm-toolchain-trusty
|
- llvm-toolchain-trusty
|
||||||
env: COMPILER='clang++-3.8' CPP14=1 VALGRIND=1
|
env: COMPILER='clang++-3.8' CPP14=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['clang-3.9', 'valgrind', 'lcov', 'libstdc++-6-dev']
|
packages: ['clang-3.9', 'libstdc++-6-dev']
|
||||||
env: COMPILER='clang++-3.9' CPP14=1 VALGRIND=1
|
env: COMPILER='clang++-3.9' CPP14=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['clang-4.0', 'valgrind', 'lcov', 'libstdc++-6-dev']
|
packages: ['clang-4.0', 'libstdc++-6-dev']
|
||||||
env: COMPILER='clang++-4.0' CPP14=1 VALGRIND=1
|
env: COMPILER='clang++-4.0' CPP14=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['clang-5.0', 'valgrind', 'lcov', 'libstdc++-6-dev']
|
packages: ['clang-5.0', 'libstdc++-6-dev']
|
||||||
env: COMPILER='clang++-5.0' CPP14=1 VALGRIND=1
|
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
|
# 4a/ Linux C++14 GCC builds
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
addons: *gcc6
|
addons: *gcc6
|
||||||
env: COMPILER='g++-6' CPP14=1 VALGRIND=1
|
env: COMPILER='g++-6' CPP14=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
addons: *gcc7
|
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
|
# 5/ OSX Clang Builds
|
||||||
- os: osx
|
- os: osx
|
||||||
@@ -181,15 +210,46 @@ matrix:
|
|||||||
- os: osx
|
- os: osx
|
||||||
osx_image: xcode9.1
|
osx_image: xcode9.1
|
||||||
compiler: clang
|
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:
|
install:
|
||||||
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||||
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
|
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
|
||||||
- |
|
- |
|
||||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||||
CMAKE_URL="http://www.cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.tar.gz"
|
CMAKE_URL="http://www.cmake.org/files/v3.5/cmake-3.5.2-Linux-x86_64.tar.gz"
|
||||||
mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
|
mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
|
||||||
export PATH=${DEPS_DIR}/cmake/bin:${PATH}
|
export PATH=${DEPS_DIR}/cmake/bin:${PATH}
|
||||||
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||||
@@ -202,25 +262,24 @@ before_script:
|
|||||||
# Regenerate single header file, so it is tested in the examples...
|
# Regenerate single header file, so it is tested in the examples...
|
||||||
- python scripts/generateSingleHeader.py
|
- python scripts/generateSingleHeader.py
|
||||||
|
|
||||||
- |
|
|
||||||
# Use Debug builds for running Valgrind and building examples
|
# Use Debug builds for running Valgrind and building examples
|
||||||
cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DUSE_VALGRIND=${VALGRIND} -DBUILD_EXAMPLES=ON -DENABLE_COVERAGE=ON
|
- cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=${EXAMPLES} -DCATCH_ENABLE_COVERAGE=${COVERAGE}
|
||||||
# Don't bother with release build for coverage build
|
# 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:
|
script:
|
||||||
- |
|
- cd Build-Debug
|
||||||
cd Build-Debug
|
- make -j 2
|
||||||
make -j 2
|
- CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
|
||||||
CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
|
|
||||||
# Coverage collection does not work for OS X atm
|
# 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 gcov
|
||||||
make lcov
|
make lcov
|
||||||
bash <(curl -s https://codecov.io/bash) -X gcov || echo "Codecov did not collect coverage reports"
|
bash <(curl -s https://codecov.io/bash) -X gcov || echo "Codecov did not collect coverage reports"
|
||||||
fi
|
fi
|
||||||
# Go to release build
|
- # Go to release build
|
||||||
cd ../Build-Release
|
- cd ../Build-Release
|
||||||
make -j 2
|
- make -j 2
|
||||||
CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
|
- CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
|
||||||
|
10
CMake/Catch2Config.cmake.in
Normal file
10
CMake/Catch2Config.cmake.in
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
@PACKAGE_INIT@
|
||||||
|
|
||||||
|
|
||||||
|
# Avoid repeatedly including the targets
|
||||||
|
if(NOT TARGET Catch2::Catch2)
|
||||||
|
# Provide path for scripts
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||||
|
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/Catch2Targets.cmake)
|
||||||
|
endif()
|
26
CMake/MiscFunctions.cmake
Normal file
26
CMake/MiscFunctions.cmake
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#checks that the given hard-coded list contains all headers + sources in the given folder
|
||||||
|
function(CheckFileList LIST_VAR FOLDER)
|
||||||
|
set(MESSAGE " should be added to the variable ${LIST_VAR}")
|
||||||
|
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
|
||||||
|
file(GLOB GLOBBED_LIST "${FOLDER}/*.cpp"
|
||||||
|
"${FOLDER}/*.hpp"
|
||||||
|
"${FOLDER}/*.h")
|
||||||
|
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
|
||||||
|
foreach(EXTRA_ITEM ${GLOBBED_LIST})
|
||||||
|
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
|
||||||
|
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(CheckFileListRec LIST_VAR FOLDER)
|
||||||
|
set(MESSAGE " should be added to the variable ${LIST_VAR}")
|
||||||
|
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
|
||||||
|
file(GLOB_RECURSE GLOBBED_LIST "${FOLDER}/*.cpp"
|
||||||
|
"${FOLDER}/*.hpp"
|
||||||
|
"${FOLDER}/*.h")
|
||||||
|
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
|
||||||
|
foreach(EXTRA_ITEM ${GLOBBED_LIST})
|
||||||
|
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
|
||||||
|
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
7
CMake/catch2.pc.in
Normal file
7
CMake/catch2.pc.in
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||||
|
|
||||||
|
Name: Catch2
|
||||||
|
Description: A modern, C++-native, header-only, test framework for C++11
|
||||||
|
URL: https://github.com/catchorg/Catch2
|
||||||
|
Version: @Catch2_VERSION@
|
||||||
|
Cflags: -I${includedir}
|
518
CMakeLists.txt
518
CMakeLists.txt
@@ -1,10 +1,28 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
project(CatchSelfTest)
|
# detect if Catch is being bundled,
|
||||||
|
# disable testsuite in that case
|
||||||
|
if(NOT DEFINED PROJECT_NAME)
|
||||||
|
set(NOT_SUBPROJECT ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
project(Catch2 LANGUAGES CXX VERSION 2.3.0)
|
||||||
|
|
||||||
|
# Provide path for scripts
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
include(CTest)
|
||||||
|
|
||||||
|
option(CATCH_USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
|
||||||
|
option(CATCH_BUILD_TESTING "Build SelfTest project" ON)
|
||||||
|
option(CATCH_BUILD_EXAMPLES "Build documentation examples" OFF)
|
||||||
|
option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io" OFF)
|
||||||
|
option(CATCH_ENABLE_WERROR "Enable all warnings as errors" ON)
|
||||||
|
option(CATCH_INSTALL_DOCS "Install documentation alongside library" ON)
|
||||||
|
option(CATCH_INSTALL_HELPERS "Install contrib alongside library" ON)
|
||||||
|
|
||||||
option(USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
|
|
||||||
option(BUILD_EXAMPLES "Build documentation examples" OFF)
|
|
||||||
option(ENABLE_COVERAGE "Generate coverage for codecov.io" OFF)
|
|
||||||
|
|
||||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
@@ -13,364 +31,154 @@ set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
|||||||
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
|
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
|
||||||
set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark)
|
set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark)
|
||||||
set(HEADER_DIR ${CATCH_DIR}/include)
|
set(HEADER_DIR ${CATCH_DIR}/include)
|
||||||
set(CATCH_VERSION_NUMBER 2.1.0)
|
|
||||||
|
|
||||||
if(USE_WMAIN)
|
if(USE_WMAIN)
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wmainCRTStartup")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wmainCRTStartup")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#checks that the given hard-coded list contains all headers + sources in the given folder
|
if (BUILD_TESTING AND CATCH_BUILD_TESTING AND NOT_SUBPROJECT)
|
||||||
function(CheckFileList LIST_VAR FOLDER)
|
add_subdirectory(projects)
|
||||||
set(MESSAGE " should be added to the variable ${LIST_VAR}")
|
endif()
|
||||||
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
|
|
||||||
file(GLOB GLOBBED_LIST "${FOLDER}/*.cpp"
|
|
||||||
"${FOLDER}/*.hpp"
|
|
||||||
"${FOLDER}/*.h")
|
|
||||||
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
|
|
||||||
foreach(EXTRA_ITEM ${GLOBBED_LIST})
|
|
||||||
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
|
|
||||||
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
|
|
||||||
endforeach()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
function(CheckFileListRec LIST_VAR FOLDER)
|
if(CATCH_BUILD_EXAMPLES)
|
||||||
set(MESSAGE " should be added to the variable ${LIST_VAR}")
|
|
||||||
set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
|
|
||||||
file(GLOB_RECURSE GLOBBED_LIST "${FOLDER}/*.cpp"
|
|
||||||
"${FOLDER}/*.hpp"
|
|
||||||
"${FOLDER}/*.h")
|
|
||||||
list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
|
|
||||||
foreach(EXTRA_ITEM ${GLOBBED_LIST})
|
|
||||||
string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
|
|
||||||
message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
|
|
||||||
endforeach()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# define the sources of the self test
|
|
||||||
# Please keep these ordered alphabetically
|
|
||||||
set(TEST_SOURCES
|
|
||||||
${SELF_TEST_DIR}/TestMain.cpp
|
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/TagAlias.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/Xml.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/Approx.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/BDD.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/Benchmark.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/Class.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/Compilation.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/Condition.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/Decomposition.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/EnumToString.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/Exception.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/Message.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/ToStringGeneral.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/ToStringPair.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/ToStringTuple.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/ToStringVector.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/ToStringWhich.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/Tricky.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/VariadicMacros.tests.cpp
|
|
||||||
${SELF_TEST_DIR}/UsageTests/Matchers.tests.cpp
|
|
||||||
)
|
|
||||||
CheckFileList(TEST_SOURCES ${SELF_TEST_DIR})
|
|
||||||
|
|
||||||
# A set of impl files that just #include a single header
|
|
||||||
# Please keep these ordered alphabetically
|
|
||||||
set(SURROGATE_SOURCES
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp
|
|
||||||
)
|
|
||||||
CheckFileList(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps)
|
|
||||||
|
|
||||||
|
|
||||||
# Please keep these ordered alphabetically
|
|
||||||
set(TOP_LEVEL_HEADERS
|
|
||||||
${HEADER_DIR}/catch.hpp
|
|
||||||
${HEADER_DIR}/catch_with_main.hpp
|
|
||||||
)
|
|
||||||
CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR})
|
|
||||||
|
|
||||||
# Please keep these ordered alphabetically
|
|
||||||
set(EXTERNAL_HEADERS
|
|
||||||
${HEADER_DIR}/external/clara.hpp
|
|
||||||
)
|
|
||||||
CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external)
|
|
||||||
|
|
||||||
|
|
||||||
# Please keep these ordered alphabetically
|
|
||||||
set(INTERNAL_HEADERS
|
|
||||||
${HEADER_DIR}/internal/catch_approx.h
|
|
||||||
${HEADER_DIR}/internal/catch_assertionhandler.h
|
|
||||||
${HEADER_DIR}/internal/catch_assertioninfo.h
|
|
||||||
${HEADER_DIR}/internal/catch_assertionresult.h
|
|
||||||
${HEADER_DIR}/internal/catch_capture.hpp
|
|
||||||
${HEADER_DIR}/internal/catch_capture_matchers.h
|
|
||||||
${HEADER_DIR}/internal/catch_clara.h
|
|
||||||
${HEADER_DIR}/internal/catch_commandline.h
|
|
||||||
${HEADER_DIR}/internal/catch_common.h
|
|
||||||
${HEADER_DIR}/internal/catch_compiler_capabilities.h
|
|
||||||
${HEADER_DIR}/internal/catch_config.hpp
|
|
||||||
${HEADER_DIR}/internal/catch_console_colour.h
|
|
||||||
${HEADER_DIR}/internal/catch_context.h
|
|
||||||
${HEADER_DIR}/internal/catch_debug_console.h
|
|
||||||
${HEADER_DIR}/internal/catch_debugger.h
|
|
||||||
${HEADER_DIR}/internal/catch_decomposer.h
|
|
||||||
${HEADER_DIR}/internal/catch_default_main.hpp
|
|
||||||
${HEADER_DIR}/internal/catch_enforce.h
|
|
||||||
${HEADER_DIR}/internal/catch_errno_guard.h
|
|
||||||
${HEADER_DIR}/internal/catch_exception_translator_registry.h
|
|
||||||
${HEADER_DIR}/internal/catch_external_interfaces.h
|
|
||||||
${HEADER_DIR}/internal/catch_fatal_condition.h
|
|
||||||
${HEADER_DIR}/internal/catch_impl.hpp
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_capture.h
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_config.h
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_exception.h
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_registry_hub.h
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_reporter.h
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_runner.h
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_tag_alias_registry.h
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_testcase.h
|
|
||||||
${HEADER_DIR}/internal/catch_leak_detector.h
|
|
||||||
${HEADER_DIR}/internal/catch_list.h
|
|
||||||
${HEADER_DIR}/internal/catch_matchers.h
|
|
||||||
${HEADER_DIR}/internal/catch_matchers_floating.h
|
|
||||||
${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_platform.h
|
|
||||||
${HEADER_DIR}/internal/catch_random_number_generator.h
|
|
||||||
${HEADER_DIR}/internal/catch_reenable_warnings.h
|
|
||||||
${HEADER_DIR}/internal/catch_reporter_registrars.hpp
|
|
||||||
${HEADER_DIR}/internal/catch_reporter_registry.h
|
|
||||||
${HEADER_DIR}/internal/catch_result_type.h
|
|
||||||
${HEADER_DIR}/internal/catch_run_context.h
|
|
||||||
${HEADER_DIR}/internal/catch_benchmark.h
|
|
||||||
${HEADER_DIR}/internal/catch_section.h
|
|
||||||
${HEADER_DIR}/internal/catch_section_info.h
|
|
||||||
${HEADER_DIR}/internal/catch_session.h
|
|
||||||
${HEADER_DIR}/internal/catch_startup_exception_registry.h
|
|
||||||
${HEADER_DIR}/internal/catch_stream.h
|
|
||||||
${HEADER_DIR}/internal/catch_stringref.h
|
|
||||||
${HEADER_DIR}/internal/catch_string_manip.h
|
|
||||||
${HEADER_DIR}/internal/catch_suppress_warnings.h
|
|
||||||
${HEADER_DIR}/internal/catch_tag_alias.h
|
|
||||||
${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.h
|
|
||||||
${HEADER_DIR}/internal/catch_tag_alias_registry.h
|
|
||||||
${HEADER_DIR}/internal/catch_test_case_info.h
|
|
||||||
${HEADER_DIR}/internal/catch_test_case_registry_impl.h
|
|
||||||
${HEADER_DIR}/internal/catch_test_case_tracker.h
|
|
||||||
${HEADER_DIR}/internal/catch_test_registry.h
|
|
||||||
${HEADER_DIR}/internal/catch_test_spec.h
|
|
||||||
${HEADER_DIR}/internal/catch_test_spec_parser.h
|
|
||||||
${HEADER_DIR}/internal/catch_text.h
|
|
||||||
${HEADER_DIR}/internal/catch_timer.h
|
|
||||||
${HEADER_DIR}/internal/catch_tostring.h
|
|
||||||
${HEADER_DIR}/internal/catch_totals.h
|
|
||||||
${HEADER_DIR}/internal/catch_user_interfaces.h
|
|
||||||
${HEADER_DIR}/internal/catch_version.h
|
|
||||||
${HEADER_DIR}/internal/catch_wildcard_pattern.h
|
|
||||||
${HEADER_DIR}/internal/catch_windows_h_proxy.h
|
|
||||||
${HEADER_DIR}/internal/catch_xmlwriter.h
|
|
||||||
)
|
|
||||||
set(IMPL_SOURCES
|
|
||||||
${HEADER_DIR}/internal/catch_approx.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_assertionhandler.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_assertionresult.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_benchmark.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_capture_matchers.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_commandline.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_common.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_config.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_console_colour.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_context.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_debug_console.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_debugger.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_decomposer.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_errno_guard.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_exception_translator_registry.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_fatal_condition.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_capture.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_config.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_exception.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_registry_hub.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_runner.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_testcase.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_list.cpp
|
|
||||||
${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_string.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_message.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_registry_hub.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_interfaces_reporter.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_random_number_generator.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_reporter_registry.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_result_type.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_run_context.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_section.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_section_info.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_session.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_startup_exception_registry.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_stream.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_stringref.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_string_manip.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_tag_alias.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_tag_alias_registry.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_test_case_info.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_test_case_registry_impl.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_test_case_tracker.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_test_registry.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_test_spec.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_test_spec_parser.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_timer.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_tostring.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_totals.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_version.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_wildcard_pattern.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_xmlwriter.cpp
|
|
||||||
)
|
|
||||||
set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
|
|
||||||
CheckFileList(INTERNAL_FILES ${HEADER_DIR}/internal)
|
|
||||||
|
|
||||||
# Please keep these ordered alphabetically
|
|
||||||
set(REPORTER_HEADERS
|
|
||||||
${HEADER_DIR}/reporters/catch_reporter_automake.hpp
|
|
||||||
${HEADER_DIR}/reporters/catch_reporter_bases.hpp
|
|
||||||
${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_tap.hpp
|
|
||||||
${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp
|
|
||||||
${HEADER_DIR}/reporters/catch_reporter_xml.h
|
|
||||||
)
|
|
||||||
set(REPORTER_SOURCES
|
|
||||||
${HEADER_DIR}/reporters/catch_reporter_bases.cpp
|
|
||||||
${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_xml.cpp
|
|
||||||
)
|
|
||||||
set(REPORTER_FILES ${REPORTER_HEADERS} ${REPORTER_SOURCES})
|
|
||||||
CheckFileList(REPORTER_FILES ${HEADER_DIR}/reporters)
|
|
||||||
|
|
||||||
# Specify the headers, too, so CLion recognises them as project files
|
|
||||||
set(HEADERS
|
|
||||||
${TOP_LEVEL_HEADERS}
|
|
||||||
${EXTERNAL_HEADERS}
|
|
||||||
${INTERNAL_HEADERS}
|
|
||||||
${REPORTER_HEADERS}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Provide some groupings for IDEs
|
|
||||||
SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
|
|
||||||
SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
|
|
||||||
|
|
||||||
|
|
||||||
# Projects consuming Catch via ExternalProject_Add might want to use install step
|
|
||||||
# without building all of our selftests.
|
|
||||||
if (NOT NO_SELFTEST)
|
|
||||||
add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS})
|
|
||||||
target_include_directories(SelfTest PRIVATE ${HEADER_DIR})
|
|
||||||
|
|
||||||
if(USE_CPP14)
|
|
||||||
message(STATUS "Enabling C++14")
|
|
||||||
set_property(TARGET SelfTest PROPERTY CXX_STANDARD 14)
|
|
||||||
else()
|
|
||||||
message(STATUS "Enabling C++11")
|
|
||||||
set_property(TARGET SelfTest PROPERTY CXX_STANDARD 11)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set_property(TARGET SelfTest PROPERTY CXX_STANDARD_REQUIRED ON)
|
|
||||||
set_property(TARGET SelfTest PROPERTY CXX_EXTENSIONS OFF)
|
|
||||||
|
|
||||||
if (ENABLE_COVERAGE)
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
|
||||||
find_package(codecov)
|
|
||||||
add_coverage(SelfTest)
|
|
||||||
list(APPEND LCOV_REMOVE_PATTERNS "'/usr/*'")
|
|
||||||
coverage_evaluate()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Add desired warnings
|
|
||||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
|
|
||||||
target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code -Werror )
|
|
||||||
endif()
|
|
||||||
# Clang specific warning go here
|
|
||||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
|
||||||
# Actually keep these
|
|
||||||
target_compile_options( SelfTest PRIVATE -Wweak-vtables -Wexit-time-destructors -Wglobal-constructors -Wmissing-noreturn )
|
|
||||||
endif()
|
|
||||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
|
|
||||||
STRING(REGEX REPLACE "/W[0-9]" "/W4" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) # override default warning level
|
|
||||||
target_compile_options( SelfTest PRIVATE /w44265 /WX /w44061 /w44062 )
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
# configure unit tests via CTest
|
|
||||||
include(CTest)
|
|
||||||
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")
|
|
||||||
|
|
||||||
add_test(NAME ListTags COMMAND $<TARGET_FILE:SelfTest> --list-tags)
|
|
||||||
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
|
|
||||||
|
|
||||||
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")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 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>)
|
|
||||||
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
|
|
||||||
|
|
||||||
if (USE_VALGRIND)
|
|
||||||
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
|
|
||||||
add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
|
|
||||||
set_tests_properties(ValgrindListTests PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
|
|
||||||
add_test(NAME ValgrindListTags COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tags)
|
|
||||||
set_tests_properties(ValgrindListTags PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif() # !NO_SELFTEST
|
|
||||||
|
|
||||||
|
|
||||||
if(BUILD_EXAMPLES)
|
|
||||||
add_subdirectory(examples)
|
add_subdirectory(examples)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(DIRECTORY "single_include/" DESTINATION "include/catch")
|
|
||||||
|
# add catch as a 'linkable' target
|
||||||
|
add_library(Catch2 INTERFACE)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# depend on some obvious c++11 features so the dependency is transitively added dependents
|
||||||
|
target_compile_features(Catch2
|
||||||
|
INTERFACE
|
||||||
|
cxx_alignas
|
||||||
|
cxx_alignof
|
||||||
|
cxx_attributes
|
||||||
|
cxx_auto_type
|
||||||
|
cxx_constexpr
|
||||||
|
cxx_defaulted_functions
|
||||||
|
cxx_deleted_functions
|
||||||
|
cxx_final
|
||||||
|
cxx_lambdas
|
||||||
|
cxx_noexcept
|
||||||
|
cxx_override
|
||||||
|
cxx_range_for
|
||||||
|
cxx_rvalue_references
|
||||||
|
cxx_static_assert
|
||||||
|
cxx_strong_enums
|
||||||
|
cxx_trailing_return_types
|
||||||
|
cxx_unicode_literals
|
||||||
|
cxx_user_literals
|
||||||
|
cxx_variadic_macros
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(Catch2
|
||||||
|
INTERFACE
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/single_include>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
)
|
||||||
|
|
||||||
|
# provide a namespaced alias for clients to 'link' against if catch is included as a sub-project
|
||||||
|
add_library(Catch2::Catch2 ALIAS Catch2)
|
||||||
|
|
||||||
|
set(CATCH_CMAKE_CONFIG_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Catch2")
|
||||||
|
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
configure_package_config_file(
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/CMake/Catch2Config.cmake.in
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake
|
||||||
|
INSTALL_DESTINATION
|
||||||
|
${CATCH_CMAKE_CONFIG_DESTINATION}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# create and install an export set for catch target as Catch2::Catch
|
||||||
|
install(
|
||||||
|
TARGETS
|
||||||
|
Catch2
|
||||||
|
EXPORT
|
||||||
|
Catch2Targets
|
||||||
|
DESTINATION
|
||||||
|
${CMAKE_INSTALL_LIBDIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
install(
|
||||||
|
EXPORT
|
||||||
|
Catch2Targets
|
||||||
|
NAMESPACE
|
||||||
|
Catch2::
|
||||||
|
DESTINATION
|
||||||
|
${CATCH_CMAKE_CONFIG_DESTINATION}
|
||||||
|
)
|
||||||
|
|
||||||
|
write_basic_package_version_file(
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
|
||||||
|
COMPATIBILITY
|
||||||
|
SameMajorVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
DIRECTORY
|
||||||
|
"single_include/"
|
||||||
|
DESTINATION
|
||||||
|
"${CMAKE_INSTALL_INCLUDEDIR}"
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
|
||||||
|
DESTINATION
|
||||||
|
${CATCH_CMAKE_CONFIG_DESTINATION}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Install documentation
|
||||||
|
if(CATCH_INSTALL_DOCS)
|
||||||
|
install(
|
||||||
|
DIRECTORY
|
||||||
|
docs/
|
||||||
|
DESTINATION
|
||||||
|
"${CMAKE_INSTALL_DOCDIR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CATCH_INSTALL_HELPERS)
|
||||||
|
# Install CMake scripts
|
||||||
|
install(
|
||||||
|
FILES
|
||||||
|
"contrib/ParseAndAddCatchTests.cmake"
|
||||||
|
"contrib/Catch.cmake"
|
||||||
|
"contrib/CatchAddTests.cmake"
|
||||||
|
DESTINATION
|
||||||
|
${CATCH_CMAKE_CONFIG_DESTINATION}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Install debugger helpers
|
||||||
|
install(
|
||||||
|
FILES
|
||||||
|
"contrib/gdbinit"
|
||||||
|
"contrib/lldbinit"
|
||||||
|
DESTINATION
|
||||||
|
${CMAKE_INSTALL_DATAROOTDIR}/Catch2
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
## Provide some pkg-config integration
|
## Provide some pkg-config integration
|
||||||
# Don't bother on Windows
|
set(PKGCONFIG_INSTALL_DIR
|
||||||
if(NOT WIN32 OR NOT CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
|
"${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig"
|
||||||
|
CACHE PATH "Path where catch2.pc is installed"
|
||||||
set(PKGCONFIG_INSTALL_DIR
|
)
|
||||||
"${CMAKE_INSTALL_PREFIX}/share/pkgconfig"
|
configure_file(
|
||||||
CACHE PATH "Path where catch.pc is installed"
|
${CMAKE_CURRENT_SOURCE_DIR}/CMake/catch2.pc.in
|
||||||
)
|
${CMAKE_CURRENT_BINARY_DIR}/catch2.pc
|
||||||
|
@ONLY
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/catch.pc.in ${CMAKE_CURRENT_BINARY_DIR}/catch.pc @ONLY)
|
)
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/catch.pc DESTINATION ${PKGCONFIG_INSTALL_DIR})
|
install(
|
||||||
|
FILES
|
||||||
endif()
|
"${CMAKE_CURRENT_BINARY_DIR}/catch2.pc"
|
||||||
|
DESTINATION
|
||||||
|
${PKGCONFIG_INSTALL_DIR}
|
||||||
|
)
|
||||||
|
@@ -5,9 +5,11 @@
|
|||||||
[](https://travis-ci.org/catchorg/Catch2)
|
[](https://travis-ci.org/catchorg/Catch2)
|
||||||
[](https://ci.appveyor.com/project/catchorg/catch2)
|
[](https://ci.appveyor.com/project/catchorg/catch2)
|
||||||
[](https://codecov.io/gh/catchorg/Catch2)
|
[](https://codecov.io/gh/catchorg/Catch2)
|
||||||
[](https://wandbox.org/permlink/nerce2MiN6sVmfCi)
|
[](https://wandbox.org/permlink/Gcuv2Xx3wmWIPNzy)
|
||||||
|
[](https://discord.gg/4CWS9zD)
|
||||||
|
|
||||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.0.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
|
||||||
|
<a href="https://github.com/catchorg/Catch2/releases/download/v2.3.0/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||||
|
|
||||||
## Catch2 is released!
|
## Catch2 is released!
|
||||||
|
|
||||||
@@ -32,5 +34,5 @@ This documentation comprises these three parts:
|
|||||||
|
|
||||||
## More
|
## More
|
||||||
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/catchorg/Catch2/issues)
|
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/catchorg/Catch2/issues)
|
||||||
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)
|
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum) or our [Discord](https://discord.gg/4CWS9zD)
|
||||||
* See [who else is using Catch2](docs/opensource-users.md#top)
|
* See [who else is using Catch2](docs/opensource-users.md#top)
|
||||||
|
45
appveyor.yml
45
appveyor.yml
@@ -19,18 +19,53 @@ environment:
|
|||||||
|
|
||||||
- additional_flags: "/D_UNICODE /DUNICODE"
|
- additional_flags: "/D_UNICODE /DUNICODE"
|
||||||
wmain: 1
|
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:
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- os: Visual Studio 2017
|
||||||
exclude:
|
exclude:
|
||||||
- os: Visual Studio 2015
|
- os: Visual Studio 2015
|
||||||
additional_flags: "/permissive- /std:c++latest"
|
additional_flags: "/permissive- /std:c++latest"
|
||||||
|
|
||||||
init:
|
- os: Visual Studio 2015
|
||||||
- git config --global core.autocrlf input
|
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:
|
install:
|
||||||
- ps: if (($env:CONFIGURATION) -eq "Debug" ) { python -m pip install codecov }
|
- 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" ) { .\misc\installOpenCppCoverage.ps1 }
|
- ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { .\misc\installOpenCppCoverage.ps1 }
|
||||||
|
|
||||||
# Win32 and x64 are CMake-compatible solution platform names.
|
# Win32 and x64 are CMake-compatible solution platform names.
|
||||||
# This allows us to pass %PLATFORM% to CMake -A.
|
# This allows us to pass %PLATFORM% to CMake -A.
|
||||||
@@ -54,7 +89,7 @@ before_build:
|
|||||||
|
|
||||||
# build with MSBuild
|
# build with MSBuild
|
||||||
build:
|
build:
|
||||||
project: Build\CatchSelfTest.sln # path to Visual Studio solution or project
|
project: Build\Catch2.sln # path to Visual Studio solution or project
|
||||||
parallel: true # enable MSBuild parallel builds
|
parallel: true # enable MSBuild parallel builds
|
||||||
verbosity: normal # MSBuild verbosity level {quiet|minimal|normal|detailed}
|
verbosity: normal # MSBuild verbosity level {quiet|minimal|normal|detailed}
|
||||||
|
|
||||||
|
@@ -1,9 +0,0 @@
|
|||||||
prefix=@CMAKE_INSTALL_PREFIX@
|
|
||||||
exec_prefix=${prefix}
|
|
||||||
|
|
||||||
Name: Catch
|
|
||||||
Description: Testing library for C++
|
|
||||||
Requires:
|
|
||||||
Version: @CATCH_VERSION_NUMBER@
|
|
||||||
Libs:
|
|
||||||
Cflags: -I${prefix}/@INCLUDE_INSTALL_DIR@/include
|
|
20
codecov.yml
20
codecov.yml
@@ -1,10 +1,24 @@
|
|||||||
codecov:
|
|
||||||
branch: master
|
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
|
precision: 2
|
||||||
|
round: nearest
|
||||||
|
range: "60...90"
|
||||||
|
status:
|
||||||
|
project:
|
||||||
|
default:
|
||||||
|
threshold: 2%
|
||||||
|
patch:
|
||||||
|
default:
|
||||||
|
target: 80%
|
||||||
ignore:
|
ignore:
|
||||||
- "projects/SelfTest"
|
- "projects/SelfTest"
|
||||||
- "**/catch_reporter_tap.hpp"
|
- "**/catch_reporter_tap.hpp"
|
||||||
- "**/catch_reporter_automake.hpp"
|
- "**/catch_reporter_automake.hpp"
|
||||||
- "**/catch_reporter_teamcity.hpp"
|
- "**/catch_reporter_teamcity.hpp"
|
||||||
- "**/external/clara.hpp"
|
- "**/external/clara.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
codecov:
|
||||||
|
branch: master
|
||||||
|
|
||||||
|
comment:
|
||||||
|
layout: "diff"
|
||||||
|
24
conanfile.py
24
conanfile.py
@@ -1,19 +1,31 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
from conans import ConanFile
|
from conans import ConanFile, CMake
|
||||||
|
|
||||||
|
|
||||||
class CatchConan(ConanFile):
|
class CatchConan(ConanFile):
|
||||||
name = "Catch"
|
name = "Catch"
|
||||||
version = "2.1.0"
|
version = "2.3.0"
|
||||||
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
|
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
|
||||||
author = "philsquared"
|
author = "philsquared"
|
||||||
generators = "cmake"
|
generators = "cmake"
|
||||||
exports_sources = "single_include/*"
|
# Only needed until conan 1.5 is released
|
||||||
url = "https://github.com/philsquared/Catch"
|
settings = "compiler", "arch"
|
||||||
|
exports_sources = "single_include/*", "CMakeLists.txt", "CMake/catch2.pc.in", "LICENSE.txt"
|
||||||
|
url = "https://github.com/catchorg/Catch2"
|
||||||
license = "Boost Software License - Version 1.0. http://www.boost.org/LICENSE_1_0.txt"
|
license = "Boost Software License - Version 1.0. http://www.boost.org/LICENSE_1_0.txt"
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def package(self):
|
def package(self):
|
||||||
self.copy(pattern="catch.hpp", src="single_include", dst="include")
|
cmake = CMake(self)
|
||||||
|
cmake.definitions["BUILD_TESTING"] = "OFF"
|
||||||
|
cmake.definitions["CATCH_INSTALL_DOCS"] = "OFF"
|
||||||
|
cmake.definitions["CATCH_INSTALL_HELPERS"] = "ON"
|
||||||
|
cmake.configure()
|
||||||
|
cmake.install()
|
||||||
|
|
||||||
|
self.copy(pattern="LICENSE.txt", dst="licenses")
|
||||||
|
|
||||||
def package_id(self):
|
def package_id(self):
|
||||||
self.info.header_only()
|
self.info.header_only()
|
||||||
|
175
contrib/Catch.cmake
Normal file
175
contrib/Catch.cmake
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||||
|
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||||
|
|
||||||
|
#[=======================================================================[.rst:
|
||||||
|
Catch
|
||||||
|
-----
|
||||||
|
|
||||||
|
This module defines a function to help use the Catch test framework.
|
||||||
|
|
||||||
|
The :command:`catch_discover_tests` discovers tests by asking the compiled test
|
||||||
|
executable to enumerate its tests. This does not require CMake to be re-run
|
||||||
|
when tests change. However, it may not work in a cross-compiling environment,
|
||||||
|
and setting test properties is less convenient.
|
||||||
|
|
||||||
|
This command is intended to replace use of :command:`add_test` to register
|
||||||
|
tests, and will create a separate CTest test for each Catch test case. Note
|
||||||
|
that this is in some cases less efficient, as common set-up and tear-down logic
|
||||||
|
cannot be shared by multiple test cases executing in the same instance.
|
||||||
|
However, it provides more fine-grained pass/fail information to CTest, which is
|
||||||
|
usually considered as more beneficial. By default, the CTest test name is the
|
||||||
|
same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
|
||||||
|
|
||||||
|
.. command:: catch_discover_tests
|
||||||
|
|
||||||
|
Automatically add tests with CTest by querying the compiled test executable
|
||||||
|
for available tests::
|
||||||
|
|
||||||
|
catch_discover_tests(target
|
||||||
|
[TEST_SPEC arg1...]
|
||||||
|
[EXTRA_ARGS arg1...]
|
||||||
|
[WORKING_DIRECTORY dir]
|
||||||
|
[TEST_PREFIX prefix]
|
||||||
|
[TEST_SUFFIX suffix]
|
||||||
|
[PROPERTIES name1 value1...]
|
||||||
|
[TEST_LIST var]
|
||||||
|
)
|
||||||
|
|
||||||
|
``catch_discover_tests`` sets up a post-build command on the test executable
|
||||||
|
that generates the list of tests by parsing the output from running the test
|
||||||
|
with the ``--list-test-names-only`` argument. This ensures that the full
|
||||||
|
list of tests is obtained. Since test discovery occurs at build time, it is
|
||||||
|
not necessary to re-run CMake when the list of tests changes.
|
||||||
|
However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set
|
||||||
|
in order to function in a cross-compiling environment.
|
||||||
|
|
||||||
|
Additionally, setting properties on tests is somewhat less convenient, since
|
||||||
|
the tests are not available at CMake time. Additional test properties may be
|
||||||
|
assigned to the set of tests as a whole using the ``PROPERTIES`` option. If
|
||||||
|
more fine-grained test control is needed, custom content may be provided
|
||||||
|
through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES`
|
||||||
|
directory property. The set of discovered tests is made accessible to such a
|
||||||
|
script via the ``<target>_TESTS`` variable.
|
||||||
|
|
||||||
|
The options are:
|
||||||
|
|
||||||
|
``target``
|
||||||
|
Specifies the Catch executable, which must be a known CMake executable
|
||||||
|
target. CMake will substitute the location of the built executable when
|
||||||
|
running the test.
|
||||||
|
|
||||||
|
``TEST_SPEC arg1...``
|
||||||
|
Specifies test cases, wildcarded test cases, tags and tag expressions to
|
||||||
|
pass to the Catch executable with the ``--list-test-names-only`` argument.
|
||||||
|
|
||||||
|
``EXTRA_ARGS arg1...``
|
||||||
|
Any extra arguments to pass on the command line to each test case.
|
||||||
|
|
||||||
|
``WORKING_DIRECTORY dir``
|
||||||
|
Specifies the directory in which to run the discovered test cases. If this
|
||||||
|
option is not provided, the current binary directory is used.
|
||||||
|
|
||||||
|
``TEST_PREFIX prefix``
|
||||||
|
Specifies a ``prefix`` to be prepended to the name of each discovered test
|
||||||
|
case. This can be useful when the same test executable is being used in
|
||||||
|
multiple calls to ``catch_discover_tests()`` but with different
|
||||||
|
``TEST_SPEC`` or ``EXTRA_ARGS``.
|
||||||
|
|
||||||
|
``TEST_SUFFIX suffix``
|
||||||
|
Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of
|
||||||
|
every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may
|
||||||
|
be specified.
|
||||||
|
|
||||||
|
``PROPERTIES name1 value1...``
|
||||||
|
Specifies additional properties to be set on all tests discovered by this
|
||||||
|
invocation of ``catch_discover_tests``.
|
||||||
|
|
||||||
|
``TEST_LIST var``
|
||||||
|
Make the list of tests available in the variable ``var``, rather than the
|
||||||
|
default ``<target>_TESTS``. This can be useful when the same test
|
||||||
|
executable is being used in multiple calls to ``catch_discover_tests()``.
|
||||||
|
Note that this variable is only available in CTest.
|
||||||
|
|
||||||
|
#]=======================================================================]
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
function(catch_discover_tests TARGET)
|
||||||
|
cmake_parse_arguments(
|
||||||
|
""
|
||||||
|
""
|
||||||
|
"TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST"
|
||||||
|
"TEST_SPEC;EXTRA_ARGS;PROPERTIES"
|
||||||
|
${ARGN}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT _WORKING_DIRECTORY)
|
||||||
|
set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
endif()
|
||||||
|
if(NOT _TEST_LIST)
|
||||||
|
set(_TEST_LIST ${TARGET}_TESTS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
## Generate a unique name based on the extra arguments
|
||||||
|
string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS}")
|
||||||
|
string(SUBSTRING ${args_hash} 0 7 args_hash)
|
||||||
|
|
||||||
|
# Define rule to generate test list for aforementioned test executable
|
||||||
|
set(ctest_include_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_include-${args_hash}.cmake")
|
||||||
|
set(ctest_tests_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_tests-${args_hash}.cmake")
|
||||||
|
get_property(crosscompiling_emulator
|
||||||
|
TARGET ${TARGET}
|
||||||
|
PROPERTY CROSSCOMPILING_EMULATOR
|
||||||
|
)
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${TARGET} POST_BUILD
|
||||||
|
BYPRODUCTS "${ctest_tests_file}"
|
||||||
|
COMMAND "${CMAKE_COMMAND}"
|
||||||
|
-D "TEST_TARGET=${TARGET}"
|
||||||
|
-D "TEST_EXECUTABLE=$<TARGET_FILE:${TARGET}>"
|
||||||
|
-D "TEST_EXECUTOR=${crosscompiling_emulator}"
|
||||||
|
-D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}"
|
||||||
|
-D "TEST_SPEC=${_TEST_SPEC}"
|
||||||
|
-D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}"
|
||||||
|
-D "TEST_PROPERTIES=${_PROPERTIES}"
|
||||||
|
-D "TEST_PREFIX=${_TEST_PREFIX}"
|
||||||
|
-D "TEST_SUFFIX=${_TEST_SUFFIX}"
|
||||||
|
-D "TEST_LIST=${_TEST_LIST}"
|
||||||
|
-D "CTEST_FILE=${ctest_tests_file}"
|
||||||
|
-P "${_CATCH_DISCOVER_TESTS_SCRIPT}"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
file(WRITE "${ctest_include_file}"
|
||||||
|
"if(EXISTS \"${ctest_tests_file}\")\n"
|
||||||
|
" include(\"${ctest_tests_file}\")\n"
|
||||||
|
"else()\n"
|
||||||
|
" add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n"
|
||||||
|
"endif()\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0")
|
||||||
|
# Add discovered tests to directory TEST_INCLUDE_FILES
|
||||||
|
set_property(DIRECTORY
|
||||||
|
APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
# Add discovered tests as directory TEST_INCLUDE_FILE if possible
|
||||||
|
get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET)
|
||||||
|
if (NOT ${test_include_file_set})
|
||||||
|
set_property(DIRECTORY
|
||||||
|
PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Cannot set more than one TEST_INCLUDE_FILE"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
set(_CATCH_DISCOVER_TESTS_SCRIPT
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake
|
||||||
|
)
|
76
contrib/CatchAddTests.cmake
Normal file
76
contrib/CatchAddTests.cmake
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||||
|
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||||
|
|
||||||
|
set(prefix "${TEST_PREFIX}")
|
||||||
|
set(suffix "${TEST_SUFFIX}")
|
||||||
|
set(spec ${TEST_SPEC})
|
||||||
|
set(extra_args ${TEST_EXTRA_ARGS})
|
||||||
|
set(properties ${TEST_PROPERTIES})
|
||||||
|
set(script)
|
||||||
|
set(suite)
|
||||||
|
set(tests)
|
||||||
|
|
||||||
|
function(add_command NAME)
|
||||||
|
set(_args "")
|
||||||
|
foreach(_arg ${ARGN})
|
||||||
|
if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
|
||||||
|
set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument
|
||||||
|
else()
|
||||||
|
set(_args "${_args} ${_arg}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Run test executable to get list of available tests
|
||||||
|
if(NOT EXISTS "${TEST_EXECUTABLE}")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Specified test executable '${TEST_EXECUTABLE}' does not exist"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-names-only
|
||||||
|
OUTPUT_VARIABLE output
|
||||||
|
RESULT_VARIABLE result
|
||||||
|
)
|
||||||
|
# Catch --list-test-names-only reports the number of tests, so 0 is... surprising
|
||||||
|
if(${result} EQUAL 0)
|
||||||
|
message(WARNING
|
||||||
|
"Test executable '${TEST_EXECUTABLE}' contains no tests!\n"
|
||||||
|
)
|
||||||
|
elseif(${result} LESS 0)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Error running test executable '${TEST_EXECUTABLE}':\n"
|
||||||
|
" Result: ${result}\n"
|
||||||
|
" Output: ${output}\n"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
string(REPLACE "\n" ";" output "${output}")
|
||||||
|
|
||||||
|
# Parse output
|
||||||
|
foreach(line ${output})
|
||||||
|
set(test ${line})
|
||||||
|
# ...and add to script
|
||||||
|
add_command(add_test
|
||||||
|
"${prefix}${test}${suffix}"
|
||||||
|
${TEST_EXECUTOR}
|
||||||
|
"${TEST_EXECUTABLE}"
|
||||||
|
"${test}"
|
||||||
|
${extra_args}
|
||||||
|
)
|
||||||
|
add_command(set_tests_properties
|
||||||
|
"${prefix}${test}${suffix}"
|
||||||
|
PROPERTIES
|
||||||
|
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
|
||||||
|
${properties}
|
||||||
|
)
|
||||||
|
list(APPEND tests "${prefix}${test}${suffix}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Create a list of all discovered tests, which users may use to e.g. set
|
||||||
|
# properties on the tests
|
||||||
|
add_command(set ${TEST_LIST} ${tests})
|
||||||
|
|
||||||
|
# Write CTest script
|
||||||
|
file(WRITE "${CTEST_FILE}" "${script}")
|
@@ -143,6 +143,9 @@ function(ParseFile SourceFile TestTarget)
|
|||||||
endif()
|
endif()
|
||||||
string(REPLACE "]" ";" Tags "${Tags}")
|
string(REPLACE "]" ";" Tags "${Tags}")
|
||||||
string(REPLACE "[" "" Tags "${Tags}")
|
string(REPLACE "[" "" Tags "${Tags}")
|
||||||
|
else()
|
||||||
|
# unset tags variable from previous loop
|
||||||
|
unset(Tags)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND Labels ${Tags})
|
list(APPEND Labels ${Tags})
|
||||||
|
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
|
@@ -20,7 +20,10 @@ Fine tuning:
|
|||||||
|
|
||||||
Running:
|
Running:
|
||||||
* [Command line](command-line.md#top)
|
* [Command line](command-line.md#top)
|
||||||
* [CI and Build system integration](build-systems.md#top)
|
|
||||||
|
Odds and ends:
|
||||||
|
* [CMake integration](cmake-integration.md#top)
|
||||||
|
* [CI and other miscellaneous pieces](ci-and-misc.md#top)
|
||||||
|
|
||||||
FAQ:
|
FAQ:
|
||||||
* [Why are my tests slow to compile?](slow-compiles.md#top)
|
* [Why are my tests slow to compile?](slow-compiles.md#top)
|
||||||
|
@@ -6,10 +6,11 @@
|
|||||||
[Exceptions](#exceptions)<br>
|
[Exceptions](#exceptions)<br>
|
||||||
[Matcher expressions](#matcher-expressions)<br>
|
[Matcher expressions](#matcher-expressions)<br>
|
||||||
[Thread Safety](#thread-safety)<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).
|
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:
|
Most of these macros come in two forms:
|
||||||
|
|
||||||
@@ -54,33 +55,45 @@ This expression is too complex because of the `||` operator. If you want to chec
|
|||||||
|
|
||||||
When comparing floating point numbers - especially if at least one of them has been computed - great care must be taken to allow for rounding errors and inexact representations.
|
When comparing floating point numbers - especially if at least one of them has been computed - great care must be taken to allow for rounding errors and inexact representations.
|
||||||
|
|
||||||
Catch provides a way to perform tolerant comparisons of floating point values through use of a wrapper class called ```Approx```. ```Approx``` can be used on either side of a comparison expression. It overloads the comparisons operators to take a tolerance into account. Here's a simple example:
|
Catch provides a way to perform tolerant comparisons of floating point values through use of a wrapper class called `Approx`. `Approx` can be used on either side of a comparison expression. It overloads the comparisons operators to take a tolerance into account. Here's a simple example:
|
||||||
|
|
||||||
```
|
```cpp
|
||||||
REQUIRE( performComputation() == Approx( 2.1 ) );
|
REQUIRE( performComputation() == Approx( 2.1 ) );
|
||||||
```
|
```
|
||||||
|
|
||||||
This way `Approx` is constructed with reasonable defaults, covering most simple cases of rounding errors. If these are insufficient, each `Approx` instance has 3 tuning knobs, that can be used to customize it for your computation.
|
Catch also provides a UDL for `Approx`; `_a`. It resides in
|
||||||
|
the `Catch::literals` namespace and can be used like so:
|
||||||
|
```cpp
|
||||||
|
using namespace Catch::literals;
|
||||||
|
REQUIRE( performComputation() == 2.1_a );
|
||||||
|
```
|
||||||
|
|
||||||
* __epsilon__ - epsilon serves to set the percentage by which a result can be erroneous, before it is rejected. By default set to `std::numeric_limits<float>::epsilon()*100`.
|
`Approx` is constructed with defaults that should cover most simple cases.
|
||||||
* __margin__ - margin serves to set the the absolute value by which a result can be erroneous before it is rejected. By default set to `0.0`.
|
For the more complex cases, `Approx` provides 3 customization points:
|
||||||
* __scale__ - scale serves to adjust the epsilon's multiplicator. By default set to `0.0`.
|
|
||||||
|
* __epsilon__ - epsilon serves to set the percentage by which a result
|
||||||
|
can differ from `Approx`'s value before it is rejected.
|
||||||
|
_By default set to `std::numeric_limits<float>::epsilon()*100`._
|
||||||
|
* __margin__ - margin serves to set the the absolute value by which
|
||||||
|
a result can differ from `Approx`'s value before it is rejected.
|
||||||
|
_By default set to `0.0`._
|
||||||
|
* __scale__ - scale is used to change the magnitude of `Approx` for relative check.
|
||||||
|
_By default set to `0.0`._
|
||||||
|
|
||||||
#### epsilon example
|
#### epsilon example
|
||||||
```cpp
|
```cpp
|
||||||
Approx target = Approx(100).epsilon(0.01);
|
Approx target = Approx(100).epsilon(0.01);
|
||||||
100.0 == target; // Obviously true
|
100.0 == target; // Obviously true
|
||||||
200.0 == target; // Obviously still false
|
200.0 == target; // Obviously still false
|
||||||
100.5 == target; // True, because we set target to allow up to 1% error
|
100.5 == target; // True, because we set target to allow up to 1% difference
|
||||||
```
|
```
|
||||||
|
|
||||||
#### margin example
|
#### margin example
|
||||||
_Margin check is used only if the relative (epsilon and scale based) check fails._
|
|
||||||
```cpp
|
```cpp
|
||||||
Approx target = Approx(100).margin(5);
|
Approx target = Approx(100).margin(5);
|
||||||
100.0 == target; // Obviously true
|
100.0 == target; // Obviously true
|
||||||
200.0 == target; // Obviously still false
|
200.0 == target; // Obviously still false
|
||||||
104.0 == target; // True, because we set target to allow absolute error up to 5
|
104.0 == target; // True, because we set target to allow absolute difference of at most 5
|
||||||
```
|
```
|
||||||
|
|
||||||
#### scale
|
#### scale
|
||||||
@@ -155,6 +168,34 @@ Matchers can be composed using `&&`, `||` and `!` operators.
|
|||||||
Currently assertions in Catch are not thread safe.
|
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).
|
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)
|
[Home](Readme.md#top)
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# CI and build system integration
|
# CI and other odd pieces
|
||||||
|
|
||||||
|
This page talks about how Catch integrates with Continuous Integration
|
||||||
Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both.
|
Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both.
|
||||||
|
|
||||||
## Continuous Integration systems
|
## Continuous Integration systems
|
||||||
@@ -28,9 +29,14 @@ The advantage of this format is that the JUnit Ant schema is widely understood b
|
|||||||
The disadvantage is that this schema was designed to correspond to how JUnit works - and there is a significant mismatch with how Catch works. Additionally the format is not streamable (because opening elements hold counts of failed and passing tests as attributes) - so the whole test run must complete before it can be written.
|
The disadvantage is that this schema was designed to correspond to how JUnit works - and there is a significant mismatch with how Catch works. Additionally the format is not streamable (because opening elements hold counts of failed and passing tests as attributes) - so the whole test run must complete before it can be written.
|
||||||
|
|
||||||
## Other reporters
|
## Other reporters
|
||||||
Other reporters are not part of the single-header distribution and need to be downloaded and included separately. All reporters are stored in `include/reporters` directory in the git repository, and are named `catch_reporter_*.hpp`. For example, to use the TeamCity reporter you need to download `include/reporters/catch_reporter_teamcity.hpp` and include it after Catch itself.
|
Other reporters are not part of the single-header distribution and need
|
||||||
|
to be downloaded and included separately. All reporters are stored in
|
||||||
|
`single_include` directory in the git repository, and are named
|
||||||
|
`catch_reporter_*.hpp`. For example, to use the TeamCity reporter you
|
||||||
|
need to download `single_include/catch_reporter_teamcity.hpp` and include
|
||||||
|
it after Catch itself.
|
||||||
|
|
||||||
```
|
```cpp
|
||||||
#define CATCH_CONFIG_MAIN
|
#define CATCH_CONFIG_MAIN
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
#include "catch_reporter_teamcity.hpp"
|
#include "catch_reporter_teamcity.hpp"
|
||||||
@@ -66,90 +72,31 @@ Catch offers prototypal support for being included in precompiled headers, but b
|
|||||||
* include "catch.hpp" again
|
* include "catch.hpp" again
|
||||||
|
|
||||||
|
|
||||||
### CMake
|
|
||||||
|
|
||||||
In general we recommend "vendoring" Catch's single-include releases inside your own repository. If you do this, the following example shows a minimal CMake project:
|
|
||||||
```CMake
|
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
|
|
||||||
project(cmake_test)
|
|
||||||
|
|
||||||
# Prepare "Catch" library for other executables
|
|
||||||
set(CATCH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/catch)
|
|
||||||
add_library(Catch INTERFACE)
|
|
||||||
target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
|
|
||||||
|
|
||||||
# Make test executable
|
|
||||||
set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
|
|
||||||
add_executable(tests ${TEST_SOURCES})
|
|
||||||
target_link_libraries(tests Catch)
|
|
||||||
```
|
|
||||||
Note that it assumes that the path to the Catch's header is `catch/catch.hpp` from the `CMakeLists.txt` file.
|
|
||||||
|
|
||||||
|
|
||||||
You can also use the following CMake snippet to automatically fetch the entire Catch repository from github and configure it as an external project:
|
|
||||||
```CMake
|
|
||||||
cmake_minimum_required(VERSION 2.8.8)
|
|
||||||
project(catch_builder CXX)
|
|
||||||
include(ExternalProject)
|
|
||||||
find_package(Git REQUIRED)
|
|
||||||
|
|
||||||
ExternalProject_Add(
|
|
||||||
catch
|
|
||||||
PREFIX ${CMAKE_BINARY_DIR}/catch
|
|
||||||
GIT_REPOSITORY https://github.com/philsquared/Catch.git
|
|
||||||
TIMEOUT 10
|
|
||||||
UPDATE_COMMAND ${GIT_EXECUTABLE} pull
|
|
||||||
CONFIGURE_COMMAND ""
|
|
||||||
BUILD_COMMAND ""
|
|
||||||
INSTALL_COMMAND ""
|
|
||||||
LOG_DOWNLOAD ON
|
|
||||||
)
|
|
||||||
|
|
||||||
# Expose required variable (CATCH_INCLUDE_DIR) to parent scope
|
|
||||||
ExternalProject_Get_Property(catch source_dir)
|
|
||||||
set(CATCH_INCLUDE_DIR ${source_dir}/single_include CACHE INTERNAL "Path to include folder for Catch")
|
|
||||||
```
|
|
||||||
|
|
||||||
If you put it in, e.g., `${PROJECT_SRC_DIR}/${EXT_PROJECTS_DIR}/catch/`, you can use it in your project by adding the following to your root CMake file:
|
|
||||||
|
|
||||||
```CMake
|
|
||||||
# Includes Catch in the project:
|
|
||||||
add_subdirectory(${EXT_PROJECTS_DIR}/catch)
|
|
||||||
include_directories(${CATCH_INCLUDE_DIR} ${COMMON_INCLUDES})
|
|
||||||
enable_testing(true) # Enables unit-testing.
|
|
||||||
```
|
|
||||||
|
|
||||||
The advantage of this approach is that you can always automatically update Catch to the latest release. The disadvantage is that it means bringing in lot more than you need.
|
|
||||||
|
|
||||||
|
|
||||||
### Automatic test registration
|
|
||||||
If you are also using ctest, `contrib/ParseAndAddCatchTests.cmake` is a CMake script that attempts to parse your test files and automatically register all test cases, using tags as labels. This means that these
|
|
||||||
```cpp
|
|
||||||
TEST_CASE("Test1", "[unit]") {
|
|
||||||
int a = 1;
|
|
||||||
int b = 2;
|
|
||||||
REQUIRE(a == b);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Test2") {
|
|
||||||
int a = 1;
|
|
||||||
int b = 2;
|
|
||||||
REQUIRE(a == b);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Test3", "[a][b][c]") {
|
|
||||||
int a = 1;
|
|
||||||
int b = 2;
|
|
||||||
REQUIRE(a == b);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
would be registered as 3 tests, `Test1`, `Test2` and `Test3`, and 4 ctest labels would be created, `a`, `b`, `c` and `unit`.
|
|
||||||
|
|
||||||
### CodeCoverage module (GCOV, LCOV...)
|
### CodeCoverage module (GCOV, LCOV...)
|
||||||
|
|
||||||
If you are using GCOV tool to get testing coverage of your code, and are not sure how to integrate it with CMake and Catch, there should be an external example over at https://github.com/fkromer/catch_cmake_coverage
|
If you are using GCOV tool to get testing coverage of your code, and are not sure how to integrate it with CMake and Catch, there should be an external example over at https://github.com/fkromer/catch_cmake_coverage
|
||||||
|
|
||||||
|
|
||||||
|
### pkg-config
|
||||||
|
|
||||||
|
Catch2 provides a rudimentary pkg-config integration, by registering itself
|
||||||
|
under the name `catch2`. This means that after Catch2 is installed, you
|
||||||
|
can use `pkg-config` to get its include path: `pkg-config --cflags catch2`.
|
||||||
|
|
||||||
|
### gdb and lldb scripts
|
||||||
|
|
||||||
|
Catch2's `contrib` folder also contains two simple debugger scripts,
|
||||||
|
`gdbinit` for `gdb` and `lldbinit` for `lldb`. If loaded into their
|
||||||
|
respective debugger, these will tell it to step over Catch2's internals
|
||||||
|
when stepping through code.
|
||||||
|
|
||||||
|
|
||||||
|
## CMake
|
||||||
|
|
||||||
|
[As it has been getting kinda long, the documentation of Catch2's
|
||||||
|
integration with CMake has been moved to its own page.](cmake-integration.md#top)
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[Home](Readme.md#top)
|
[Home](Readme.md#top)
|
189
docs/cmake-integration.md
Normal file
189
docs/cmake-integration.md
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
<a id="top"></a>
|
||||||
|
# CMake integration
|
||||||
|
|
||||||
|
Because we use CMake to build Catch2, we also provide a couple of
|
||||||
|
integration points for our users.
|
||||||
|
|
||||||
|
1) Catch2 exports a (namespaced) CMake target
|
||||||
|
2) Catch2's repository contains CMake scripts for automatic registration
|
||||||
|
of `TEST_CASE`s in CTest
|
||||||
|
|
||||||
|
## CMake target
|
||||||
|
|
||||||
|
Catch2's CMake build exports an interface target `Catch2::Catch2`. Linking
|
||||||
|
against it will add the proper include path and all necessary capabilities
|
||||||
|
to the resulting binary.
|
||||||
|
|
||||||
|
This means that if Catch2 has been installed on the system, it should be
|
||||||
|
enough to do:
|
||||||
|
```cmake
|
||||||
|
find_package(Catch2 REQUIRED)
|
||||||
|
target_link_libraries(tests Catch2::Catch2)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
This target is also provided when Catch2 is used as a subdirectory.
|
||||||
|
Assuming that Catch2 has been cloned to `lib/Catch2`:
|
||||||
|
```cmake
|
||||||
|
add_subdirectory(lib/Catch2)
|
||||||
|
target_link_libraries(tests Catch2::Catch2)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Automatic test registration
|
||||||
|
|
||||||
|
Catch2's repository also contains two CMake scripts that help users
|
||||||
|
with automatically registering their `TEST_CASE`s with CTest. They
|
||||||
|
can be found in the `contrib` folder, and are
|
||||||
|
|
||||||
|
1) `Catch.cmake` (and its dependency `CatchAddTests.cmake`)
|
||||||
|
2) `ParseAndAddCatchTests.cmake`
|
||||||
|
|
||||||
|
If Catch2 has been installed in system, both of these can be used after
|
||||||
|
doing `find_package(Catch2 REQUIRED)`. Otherwise you need to add them
|
||||||
|
to your CMake module path.
|
||||||
|
|
||||||
|
### `Catch.cmake` and `AddCatchTests.cmake`
|
||||||
|
|
||||||
|
`Catch.cmake` provides function `catch_discover_tests` to get tests from
|
||||||
|
a target. This function works by running the resulting executable with
|
||||||
|
`--list-test-names-only` flag, and then parsing the output to find all
|
||||||
|
existing tests.
|
||||||
|
|
||||||
|
#### Usage
|
||||||
|
```cmake
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
project(baz LANGUAGES CXX VERSION 0.0.1)
|
||||||
|
|
||||||
|
find_package(Catch2 REQUIRED)
|
||||||
|
add_executable(foo test.cpp)
|
||||||
|
target_link_libraries(foo Catch2::Catch2)
|
||||||
|
|
||||||
|
include(CTest)
|
||||||
|
include(Catch)
|
||||||
|
catch_discover_tests(foo)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### Customization
|
||||||
|
`catch_discover_tests` can be given several extra argumets:
|
||||||
|
```cmake
|
||||||
|
catch_discover_tests(target
|
||||||
|
[TEST_SPEC arg1...]
|
||||||
|
[EXTRA_ARGS arg1...]
|
||||||
|
[WORKING_DIRECTORY dir]
|
||||||
|
[TEST_PREFIX prefix]
|
||||||
|
[TEST_SUFFIX suffix]
|
||||||
|
[PROPERTIES name1 value1...]
|
||||||
|
[TEST_LIST var]
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
* `TEST_SPEC arg1...`
|
||||||
|
|
||||||
|
Specifies test cases, wildcarded test cases, tags and tag expressions to
|
||||||
|
pass to the Catch executable alongside the `--list-test-names-only` flag.
|
||||||
|
|
||||||
|
|
||||||
|
* `EXTRA_ARGS arg1...`
|
||||||
|
|
||||||
|
Any extra arguments to pass on the command line to each test case.
|
||||||
|
|
||||||
|
|
||||||
|
* `WORKING_DIRECTORY dir`
|
||||||
|
|
||||||
|
Specifies the directory in which to run the discovered test cases. If this
|
||||||
|
option is not provided, the current binary directory is used.
|
||||||
|
|
||||||
|
|
||||||
|
* `TEST_PREFIX prefix`
|
||||||
|
|
||||||
|
Specifies a _prefix_ to be added to the name of each discovered test case.
|
||||||
|
This can be useful when the same test executable is being used in multiple
|
||||||
|
calls to `catch_discover_tests()`, with different `TEST_SPEC` or `EXTRA_ARGS`.
|
||||||
|
|
||||||
|
|
||||||
|
* `TEST_SUFFIX suffix`
|
||||||
|
|
||||||
|
Same as `TEST_PREFIX`, except it specific the _suffix_ for the test names.
|
||||||
|
Both `TEST_PREFIX` and `TEST_SUFFIX` can be specified at the same time.
|
||||||
|
|
||||||
|
|
||||||
|
* `PROPERTIES name1 value1...`
|
||||||
|
|
||||||
|
Specifies additional properties to be set on all tests discovered by this
|
||||||
|
invocation of `catch_discover_tests`.
|
||||||
|
|
||||||
|
|
||||||
|
* `TEST_LIST var`
|
||||||
|
|
||||||
|
Make the list of tests available in the variable `var`, rather than the
|
||||||
|
default `<target>_TESTS`. This can be useful when the same test
|
||||||
|
executable is being used in multiple calls to `catch_discover_tests()`.
|
||||||
|
Note that this variable is only available in CTest.
|
||||||
|
|
||||||
|
|
||||||
|
### `ParseAndAddCatchTests.cmake`
|
||||||
|
|
||||||
|
`ParseAndAddCatchTests` works by parsing all implementation files
|
||||||
|
associated with the provided target, and registering them via CTest's
|
||||||
|
`add_test`. This approach has some limitations, such as the fact that
|
||||||
|
commented-out tests will be registered anyway.
|
||||||
|
|
||||||
|
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
project(baz LANGUAGES CXX VERSION 0.0.1)
|
||||||
|
|
||||||
|
find_package(Catch2 REQUIRED)
|
||||||
|
add_executable(foo test.cpp)
|
||||||
|
target_link_libraries(foo Catch2::Catch2)
|
||||||
|
|
||||||
|
include(CTest)
|
||||||
|
include(ParseAndAddCatchTests)
|
||||||
|
ParseAndAddCatchTests(foo)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### Customization
|
||||||
|
|
||||||
|
`ParseAndAddCatchTests` provides some customization points:
|
||||||
|
* `PARSE_CATCH_TESTS_VERBOSE` -- When `ON`, the script prints debug
|
||||||
|
messages. Defaults to `OFF`.
|
||||||
|
* `PARSE_CATCH_TESTS_NO_HIDDEN_TESTS` -- When `ON`, hidden tests (tests
|
||||||
|
tagged with any of `[!hide]`, `[.]` or `[.foo]`) will not be registered.
|
||||||
|
Defaults to `OFF`.
|
||||||
|
* `PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME` -- When `ON`, adds fixture
|
||||||
|
class name to the test name in CTest. Defaults to `ON`.
|
||||||
|
* `PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME` -- When `ON`, adds target
|
||||||
|
name to the test name in CTest. Defaults to `ON`.
|
||||||
|
* `PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS` -- When `ON`, adds test
|
||||||
|
file to `CMAKE_CONFIGURE_DEPENDS`. This means that the CMake configuration
|
||||||
|
step will be re-ran when the test files change, letting new tests be
|
||||||
|
automatically discovered. Defaults to `OFF`.
|
||||||
|
|
||||||
|
|
||||||
|
## CMake project options
|
||||||
|
|
||||||
|
Catch2's CMake project also provides some options for other projects
|
||||||
|
that consume it. These are
|
||||||
|
|
||||||
|
* `CATCH_BUILD_TESTING` -- When `ON`, Catch2's SelfTest project will be
|
||||||
|
built. Defaults to `ON`. Note that Catch2 also obeys `BUILD_TESTING` CMake
|
||||||
|
variable, so _both_ of them need to be `ON` for the SelfTest to be built,
|
||||||
|
and either of them can be set to `OFF` to disable building SelfTest.
|
||||||
|
* `CATCH_BUILD_EXAMPLES` -- When `ON`, Catch2's usage examples will be
|
||||||
|
built. Defaults to `OFF`.
|
||||||
|
* `CATCH_INSTALL_DOCS` -- When `ON`, Catch2's documentation will be
|
||||||
|
included in the installation. Defaults to `ON`.
|
||||||
|
* `CATCH_INSTALL_HELPERS` -- When `ON`, Catch2's contrib folder will be
|
||||||
|
included in the installation. Defaults to `ON`.
|
||||||
|
* `BUILD_TESTING` -- When `ON` and the project is not used as a subproject,
|
||||||
|
Catch2's test binary will be built. Defaults to `ON`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[Home](Readme.md#top)
|
@@ -24,6 +24,7 @@
|
|||||||
[Usage](#usage)<br>
|
[Usage](#usage)<br>
|
||||||
[Specify the section to run](#specify-the-section-to-run)<br>
|
[Specify the section to run](#specify-the-section-to-run)<br>
|
||||||
[Filenames as tags](#filenames-as-tags)<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.
|
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.
|
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="#libidentify"> ` --libidentify`</a><br />
|
||||||
<a href="#wait-for-keypress"> ` --wait-for-keypress`</a><br />
|
<a href="#wait-for-keypress"> ` --wait-for-keypress`</a><br />
|
||||||
<a href="#benchmark-resolution-multiple"> ` --benchmark-resolution-multiple`</a><br />
|
<a href="#benchmark-resolution-multiple"> ` --benchmark-resolution-multiple`</a><br />
|
||||||
|
<a href="#use-colour"> ` --use-colour`</a><br />
|
||||||
|
|
||||||
</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.
|
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.
|
Inclusions and exclusions are evaluated in left-to-right order.
|
||||||
|
|
||||||
Test case examples:
|
Test case examples:
|
||||||
@@ -94,7 +96,7 @@ a* ~ab* abc Matches all tests that start with 'a', except those that
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
Names within square brackets are interpreted as tags.
|
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>
|
<pre>[one][two],[three]</pre>
|
||||||
This matches all tests tagged `[one]` and `[two]`, as well as all tests tagged `[three]`
|
This matches all tests tagged `[one]` and `[two]`, as well as all tests tagged `[three]`
|
||||||
@@ -122,7 +124,9 @@ The JUnit reporter is an xml format that follows the structure of the JUnit XML
|
|||||||
## Breaking into the debugger
|
## Breaking into the debugger
|
||||||
<pre>-b, --break</pre>
|
<pre>-b, --break</pre>
|
||||||
|
|
||||||
In some IDEs (currently XCode and Visual Studio) it is possible for Catch to break into the debugger on a test failure. This can be very helpful during debug sessions - especially when there is more than one path through a particular test.
|
Under most debuggers Catch2 is capable of automatically breaking on a test
|
||||||
|
failure. This allows the user to see the current state of the test during
|
||||||
|
failure.
|
||||||
|
|
||||||
<a id="showing-results-for-successful-tests"></a>
|
<a id="showing-results-for-successful-tests"></a>
|
||||||
## Showing results for successful tests
|
## Showing results for successful tests
|
||||||
@@ -192,9 +196,16 @@ This option transforms tabs and newline characters into ```\t``` and ```\n``` re
|
|||||||
## Warnings
|
## Warnings
|
||||||
<pre>-w, --warn <warning name></pre>
|
<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>
|
<a id="reporting-timings"></a>
|
||||||
## Reporting timings
|
## Reporting timings
|
||||||
@@ -262,7 +273,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
|
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
|
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>
|
<a id="usage"></a>
|
||||||
## Usage
|
## Usage
|
||||||
@@ -322,6 +333,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]`.
|
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>
|
[Terminal colour](#terminal-colour)<br>
|
||||||
[Console width](#console-width)<br>
|
[Console width](#console-width)<br>
|
||||||
[stdout](#stdout)<br>
|
[stdout](#stdout)<br>
|
||||||
|
[Fallback stringifier](#fallback-stringifier)<br>
|
||||||
|
[Default reporter](#default-reporter)<br>
|
||||||
[Other toggles](#other-toggles)<br>
|
[Other toggles](#other-toggles)<br>
|
||||||
[Windows header clutter](#windows-header-clutter)<br>
|
[Windows header clutter](#windows-header-clutter)<br>
|
||||||
[Enabling stringification](#enabling-stringification)<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
|
# 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.
|
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.
|
||||||
|
|
||||||
@@ -64,15 +66,70 @@ By default a console width of 80 is assumed but this can be controlled by defini
|
|||||||
|
|
||||||
CATCH_CONFIG_NOSTDOUT
|
CATCH_CONFIG_NOSTDOUT
|
||||||
|
|
||||||
Catch does not use ```std::cout```, ```std::cerr``` and ```std::clog``` directly but gets them from ```Catch::cout()```, ```Catch::cerr()``` and ```Catch::clog``` respectively. If the above identifier is defined these functions are left unimplemented and you must implement them yourself. Their signatures are:
|
To support platforms that do not provide `std::cout`, `std::cerr` and
|
||||||
|
`std::clog`, Catch does not usem the directly, but rather calls
|
||||||
|
`Catch::cout`, `Catch::cerr` and `Catch::clog`. You can replace their
|
||||||
|
implementation by defining `CATCH_CONFIG_NOSTDOUT` and implementing
|
||||||
|
them yourself, their signatures are:
|
||||||
|
|
||||||
std::ostream& cout();
|
std::ostream& cout();
|
||||||
std::ostream& cerr();
|
std::ostream& cerr();
|
||||||
std::ostream& clog();
|
std::ostream& clog();
|
||||||
|
|
||||||
This can be useful on certain platforms that do not provide the standard iostreams, such as certain embedded systems.
|
[You can see an example of replacing these functions here.](
|
||||||
|
../examples/231-Cfg-OutputStreams.cpp)
|
||||||
|
|
||||||
|
|
||||||
|
## 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
|
## Other toggles
|
||||||
|
|
||||||
@@ -84,6 +141,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_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap
|
||||||
CATCH_CONFIG_DISABLE_STRINGIFICATION // Disable stringifying the original expression
|
CATCH_CONFIG_DISABLE_STRINGIFICATION // Disable stringifying the original expression
|
||||||
CATCH_CONFIG_DISABLE // Disables assertions and test case registration
|
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.
|
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,14 +150,22 @@ 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.
|
`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`
|
### `CATCH_CONFIG_FAST_COMPILE`
|
||||||
Defining this flag speeds up compilation of test files by ~20%, by making 2 changes:
|
This compile-time flag speeds up compilation of assertion macros by ~20%,
|
||||||
* 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*.
|
by disabling the generation of assertion-local try-catch blocks for
|
||||||
* 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 assertion macros ({`REQUIRE`,`CHECK`}{``,`_FALSE`, `_THAT`}).
|
||||||
|
This disables translation of exceptions thrown under these assertions, 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.
|
`CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined,
|
||||||
|
in all translation units that are linked into single test binary.
|
||||||
|
|
||||||
### `CATCH_CONFIG_DISABLE_MATCHERS`
|
### `CATCH_CONFIG_DISABLE_MATCHERS`
|
||||||
When `CATCH_CONFIG_DISABLE_MATCHERS` is defined, all mentions of Catch's Matchers are ifdef-ed away from the translation unit. Doing so will speed up compilation of that TU.
|
When `CATCH_CONFIG_DISABLE_MATCHERS` is defined, all mentions of Catch's Matchers are ifdef-ed away from the translation unit. Doing so will speed up compilation of that TU.
|
||||||
|
@@ -44,7 +44,7 @@ _Note that you should not use any assertion macros within a Listener!_
|
|||||||
|
|
||||||
## Events that can be hooked
|
## 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++
|
```c++
|
||||||
// The whole test run, starting and ending
|
// The whole test run, starting and ending
|
||||||
|
@@ -21,7 +21,9 @@ TEST_CASE( "Looped section" ) {
|
|||||||
This section outlines some missing features, what is their status and their possible workarounds.
|
This section outlines some missing features, what is their status and their possible workarounds.
|
||||||
|
|
||||||
### Thread safe assertions
|
### Thread safe assertions
|
||||||
Because threading support in standard C++98 is limited (well, non-existent), assertion macros in Catch are not thread safe. This does not mean that you cannot use threads inside Catch's test, but that only single thread can interact with Catch's assertions and other macros.
|
Catch2's assertion macros are not thread safe. This does not mean that
|
||||||
|
you cannot use threads inside Catch's test, but that only single thread
|
||||||
|
can interact with Catch's assertions and other macros.
|
||||||
|
|
||||||
This means that this is ok
|
This means that this is ok
|
||||||
```cpp
|
```cpp
|
||||||
@@ -49,8 +51,8 @@ because only one thread passes the `REQUIRE` macro and this is not
|
|||||||
REQUIRE(cnt == 16);
|
REQUIRE(cnt == 16);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Because C++11 provides the necessary tools to do this, we are planning
|
||||||
_This limitation is highly unlikely to be lifted before Catch 2 is released._
|
to remove this limitation in the future.
|
||||||
|
|
||||||
### Process isolation in a test
|
### Process isolation in a test
|
||||||
Catch does not support running tests in isolated (forked) processes. While this might in the future, the fact that Windows does not support forking and only allows full-on process creation and the desire to keep code as similar as possible across platforms, mean that this is likely to take significant development time, that is not currently available.
|
Catch does not support running tests in isolated (forked) processes. While this might in the future, the fact that Windows does not support forking and only allows full-on process creation and the desire to keep code as similar as possible across platforms, mean that this is likely to take significant development time, that is not currently available.
|
||||||
@@ -96,6 +98,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
|
### Visual Studio 2015 -- Wrong line number reported in debug mode
|
||||||
|
@@ -1,18 +1,25 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# List of examples
|
# List of examples
|
||||||
|
|
||||||
|
## Already available
|
||||||
|
|
||||||
- Test Case: [Single-file](../examples/010-TestCase.cpp)
|
- Test Case: [Single-file](../examples/010-TestCase.cpp)
|
||||||
- Test Case: [Multiple-file 1](../examples/020-TestCase-1.cpp), [2](../examples/020-TestCase-1.cpp)
|
- Test Case: [Multiple-file 1](../examples/020-TestCase-1.cpp), [2](../examples/020-TestCase-2.cpp)
|
||||||
- Assertion: [REQUIRE, CHECK](../examples/030-Asn-Require-Check.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)
|
||||||
|
- Configuration: [Provide your own output streams](../examples/231-Cfg-OutputStreams.cpp)
|
||||||
|
|
||||||
|
## Planned
|
||||||
|
|
||||||
- Assertion: [REQUIRE_THAT and Matchers](../examples/040-Asn-RequireThat.cpp)
|
- Assertion: [REQUIRE_THAT and Matchers](../examples/040-Asn-RequireThat.cpp)
|
||||||
- Assertion: [REQUIRE_NO_THROW](../examples/050-Asn-RequireNoThrow.cpp)
|
- Assertion: [REQUIRE_NO_THROW](../examples/050-Asn-RequireNoThrow.cpp)
|
||||||
- Assertion: [REQUIRE_THROWS](../examples/050-Asn-RequireThrows.cpp)
|
- Assertion: [REQUIRE_THROWS](../examples/050-Asn-RequireThrows.cpp)
|
||||||
- Assertion: [REQUIRE_THROWS_AS](../examples/070-Asn-RequireThrowsAs.cpp)
|
- Assertion: [REQUIRE_THROWS_AS](../examples/070-Asn-RequireThrowsAs.cpp)
|
||||||
- Assertion: [REQUIRE_THROWS_WITH](../examples/080-Asn-RequireThrowsWith.cpp)
|
- Assertion: [REQUIRE_THROWS_WITH](../examples/080-Asn-RequireThrowsWith.cpp)
|
||||||
- Assertion: [REQUIRE_THROWS_MATCHES](../examples/090-Asn-RequireThrowsMatches.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)
|
- Floating point: [Approx - Comparisons](../examples/130-Fpt-Approx.cpp)
|
||||||
- Logging: [CAPTURE - Capture expression](../examples/140-Log-Capture.cpp)
|
- Logging: [CAPTURE - Capture expression](../examples/140-Log-Capture.cpp)
|
||||||
- Logging: [INFO - Provide information with failure](../examples/150-Log-Info.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)
|
- Logging: [SUCCEED - Issue message and continue](../examples/180-Log-Succeed.cpp)
|
||||||
- Report: [User-defined type](../examples/190-Rpt-ReportUserDefinedType.cpp)
|
- Report: [User-defined type](../examples/190-Rpt-ReportUserDefinedType.cpp)
|
||||||
- Report: [Reporter](../examples/200-Rpt-UserDefinedReporter.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: [Provide your own main()](../examples/220-Cfg-OwnMain.cpp)
|
||||||
- Configuration: [Compile-time configuration](../examples/230-Cfg-CompileTimeConfiguration.cpp)
|
- Configuration: [Compile-time configuration](../examples/230-Cfg-CompileTimeConfiguration.cpp)
|
||||||
- Configuration: [Run-time configuration](../examples/240-Cfg-RunTimeConfiguration.cpp)
|
- Configuration: [Run-time configuration](../examples/240-Cfg-RunTimeConfiguration.cpp)
|
||||||
|
@@ -72,12 +72,6 @@ This would log something like:
|
|||||||
|
|
||||||
<pre>"theAnswer := 42"</pre>
|
<pre>"theAnswer := 42"</pre>
|
||||||
|
|
||||||
## Deprecated macros
|
|
||||||
|
|
||||||
**SCOPED_INFO and SCOPED_CAPTURE**
|
|
||||||
|
|
||||||
These macros are now deprecated and are just aliases for INFO and CAPTURE (which were not previously scoped).
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[Home](Readme.md#top)
|
[Home](Readme.md#top)
|
||||||
|
@@ -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.
|
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
|
## Custom matchers
|
||||||
It's easy to provide your own matchers to extend Catch or just to work with your own types.
|
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>
|
<a id="top"></a>
|
||||||
# Open Source projects using Catch
|
# 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?
|
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.
|
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 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
|
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).
|
[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.
|
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.
|
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.
|
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
|
## 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
|
Boost Asio style bindings for ZeroMQ
|
||||||
|
|
||||||
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
|
### [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)
|
### [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
|
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)
|
### [DtCraft](https://github.com/twhuang-uiuc/DtCraft)
|
||||||
A High-performance Cluster Computing Engine
|
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)
|
### [Fuxedo](https://github.com/fuxedo/fuxedo)
|
||||||
Open source Oracle Tuxedo-like XATMI middleware for C and C++.
|
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)
|
### [JSON for Modern C++](https://github.com/nlohmann/json)
|
||||||
A, single-header, JSON parsing library that takes advantage of what C++ has to offer.
|
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)
|
### [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.
|
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](https://github.com/akrennmair/newsbeuter)
|
||||||
Newsbeuter is an open-source RSS/Atom feed reader for text terminals.
|
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](https://github.com/foonathan/standardese)
|
||||||
Standardese aims to be a nextgen Doxygen
|
Standardese aims to be a nextgen Doxygen
|
||||||
|
|
||||||
|
@@ -30,7 +30,7 @@ int main( int argc, char* argv[] ) {
|
|||||||
|
|
||||||
## Amending the config
|
## 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++
|
```c++
|
||||||
#define CATCH_CONFIG_RUNNER
|
#define CATCH_CONFIG_RUNNER
|
||||||
@@ -81,6 +81,7 @@ int main( int argc, char* argv[] )
|
|||||||
int height = 0; // Some user variable you want to be able to set
|
int height = 0; // Some user variable you want to be able to set
|
||||||
|
|
||||||
// Build a new parser on top of Catch's
|
// Build a new parser on top of Catch's
|
||||||
|
using namespace Catch::clara;
|
||||||
auto cli
|
auto cli
|
||||||
= session.cli() // Get Catch's composite command line parser
|
= session.cli() // Get Catch's composite command line parser
|
||||||
| Opt( height, "height" ) // bind variable to a new option, with a hint string
|
| Opt( height, "height" ) // bind variable to a new option, with a hint string
|
||||||
@@ -105,6 +106,20 @@ int main( int argc, char* argv[] )
|
|||||||
|
|
||||||
See the [Clara documentation](https://github.com/philsquared/Clara/blob/master/README.md) for more details.
|
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)
|
[Home](Readme.md#top)
|
||||||
|
@@ -1,5 +1,167 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
|
|
||||||
|
# 2.3.0
|
||||||
|
|
||||||
|
**This release changes the include paths provided by our CMake and
|
||||||
|
pkg-config integration. The proper include path for the single-header
|
||||||
|
when using one of the above is now `<catch2/catch.hpp>`. This change
|
||||||
|
also necessitated changes to paths inside the repository, so that the
|
||||||
|
single-header version is now at `single_include/catch2/catch.hpp`, rather
|
||||||
|
than `single_include/catch.hpp`.**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
* Fixed Objective-C++ build
|
||||||
|
* `-Wunused-variable` suppression no longer leaks from Catch's header under Clang
|
||||||
|
* Implementation of the experimental new output capture can now be disabled (#1335)
|
||||||
|
* This allows building Catch2 on platforms that do not provide things like `dup` or `tmpfile`.
|
||||||
|
* The JUnit and XML reporters will no longer skip over successful tests when running without `-s` (#1264, #1267, #1310)
|
||||||
|
* See improvements for more details
|
||||||
|
|
||||||
|
## Improvements
|
||||||
|
* pkg-config and CMake integration has been rewritten
|
||||||
|
* If you use them, the new include path is `#include <catch2/catch.hpp>`
|
||||||
|
* CMake installation now also installs scripts from `contrib/`
|
||||||
|
* For details see the [new documentation](cmake-integration.md#top)
|
||||||
|
* Reporters now have a new customization point, `ReporterPreferences::shouldReportAllAssertions`
|
||||||
|
* When this is set to `false` and the tests are run without `-s`, passing assertions are not sent to the reporter.
|
||||||
|
* Defaults to `false`.
|
||||||
|
* Added `DYNAMIC_SECTION`, a section variant that constructs its name using stream
|
||||||
|
* This means that you can do `DYNAMIC_SECTION("For X := " << x)`.
|
||||||
|
|
||||||
|
|
||||||
|
# 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
|
||||||
|
* Static arrays are now properly stringified like ranges across MSVC/GCC/Clang
|
||||||
|
* Embedded newer version of Clara -- v1.1.1
|
||||||
|
* This should fix some warnings dragged in from Clara
|
||||||
|
* MSVC's CLR exceptions are supported
|
||||||
|
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
* Fixed compilation when comparison operators do not return bool (#1147)
|
||||||
|
* Fixed CLR exceptions blowing up the executable during translation (#1138)
|
||||||
|
|
||||||
|
|
||||||
|
## Other changes
|
||||||
|
* Many CMake changes
|
||||||
|
* `NO_SELFTEST` option is deprecated, use `BUILD_TESTING` instead.
|
||||||
|
* Catch specific CMake options were prefixed with `CATCH_` for namespacing purposes
|
||||||
|
* Other changes to simplify Catch2's packaging
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 2.1.0
|
# 2.1.0
|
||||||
|
|
||||||
## Improvements
|
## Improvements
|
||||||
@@ -340,8 +502,8 @@ Cygwin issue with `gettimeofday` - `#define` was not early enough
|
|||||||
* Cygwin compatibility fixes
|
* Cygwin compatibility fixes
|
||||||
* Signal handling is no longer compiled by default.
|
* Signal handling is no longer compiled by default.
|
||||||
* Usage of `gettimeofday` inside Catch should no longer cause compilation errors.
|
* Usage of `gettimeofday` inside Catch should no longer cause compilation errors.
|
||||||
* Improved `-Wparentheses` supression for gcc (#674)
|
* Improved `-Wparentheses` suppression for gcc (#674)
|
||||||
* When compiled with gcc 4.8 or newer, the supression is localized to assertions only
|
* When compiled with gcc 4.8 or newer, the suppression is localized to assertions only
|
||||||
* Otherwise it is supressed for the whole TU
|
* Otherwise it is supressed for the whole TU
|
||||||
* Fixed test spec parser issue (with escapes in multiple names)
|
* Fixed test spec parser issue (with escapes in multiple names)
|
||||||
|
|
||||||
@@ -360,7 +522,7 @@ Xml:
|
|||||||
* C-escape control characters instead of XML encoding them (which requires XML 1.1)
|
* C-escape control characters instead of XML encoding them (which requires XML 1.1)
|
||||||
* Revert XML output to XML 1.0
|
* Revert XML output to XML 1.0
|
||||||
* Can provide stylesheet references by extending the XML reporter
|
* 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
|
* Tags are closed and the stream flushed more eagerly to avoid stdout interpolation
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# How to release
|
# 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
|
### Approval testing
|
||||||
@@ -21,10 +21,8 @@ Catch uses a variant of [semantic versioning](http://semver.org/), with breaking
|
|||||||
|
|
||||||
After deciding which part of version number should be incremented, you can use one of the `*Release.py` scripts to perform the required changes to Catch.
|
After deciding which part of version number should be incremented, you can use one of the `*Release.py` scripts to perform the required changes to Catch.
|
||||||
|
|
||||||
|
This will take care of generating the single include header, updating
|
||||||
### Generate updated single-include header
|
version numbers everywhere and pushing the new version to Wandbox.
|
||||||
|
|
||||||
After updating version number, regenerate single-include header using `generateSingleHeader.py`.
|
|
||||||
|
|
||||||
|
|
||||||
### Release notes
|
### Release notes
|
||||||
@@ -39,26 +37,17 @@ After version number is incremented, single-include header is regenerated and re
|
|||||||
|
|
||||||
### Release on GitHub
|
### Release on GitHub
|
||||||
|
|
||||||
After pushing changes to GitHub, GitHub release *needs* to be created. Tag version and release title should be same as the new version, description should contain the release notes for the current release. Single header version of `catch.hpp` *needs* to be attached as a binary, as that is where the official download link links to. Preferably it should use linux line endings.
|
After pushing changes to GitHub, GitHub release *needs* to be created.
|
||||||
|
Tag version and release title should be same as the new version,
|
||||||
|
description should contain the release notes for the current release.
|
||||||
|
Single header version of `catch.hpp` *needs* to be attached as a binary,
|
||||||
|
as that is where the official download link links to. Preferably
|
||||||
|
it should use linux line endings. All non-bundled reporters (Automake,
|
||||||
|
TAP, TeamCity) should also be attached as binaries, as they are dependent
|
||||||
|
on a specific version of the single-include header.
|
||||||
|
|
||||||
|
|
||||||
## Optional steps
|
## Optional steps
|
||||||
|
|
||||||
The following steps are optional, and do not have to be performed when releasing new version of Catch. However, they are *should* happen, but they can happen the next day without losing anything significant.
|
Because Catch's [vcpkg](https://github.com/Microsoft/vcpkg) port updates
|
||||||
|
itself automagically, there are no optional steps at this time.
|
||||||
|
|
||||||
### 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.
|
|
||||||
|
|
||||||
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:
|
|
||||||
```
|
|
||||||
GitHub
|
|
||||||
Catch
|
|
||||||
vcpkg
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Wandbox update
|
|
||||||
|
|
||||||
Recently we also included a link to wandbox with preloaded Catch on the main page. Strictly speaking it is unneccessary to update this after every release, Catch usually does not change that much between versions, but it should be kept up to date anyway.
|
|
||||||
|
|
||||||
|
@@ -33,6 +33,23 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Catch::is_range<T> specialisation
|
||||||
|
As a fallback, Catch attempts to detect if the type can be iterated
|
||||||
|
(`begin(T)` and `end(T)` are valid) and if it can be, it is stringified
|
||||||
|
as a range. For certain types this can lead to infinite recursion, so
|
||||||
|
it can be disabled by specializing `Catch::is_range` like so:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace Catch {
|
||||||
|
template<>
|
||||||
|
struct is_range<T> {
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Exceptions
|
## 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:
|
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:
|
||||||
|
@@ -12,7 +12,10 @@
|
|||||||
|
|
||||||
## Getting Catch2
|
## Getting Catch2
|
||||||
|
|
||||||
The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/CatchOrg/Catch2/master/single_include/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
|
The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/catchorg/Catch2/master/single_include/catch2/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
|
||||||
|
|
||||||
|
Alternative ways of getting Catch2 include using your system package
|
||||||
|
manager, or installing it using its CMake package.
|
||||||
|
|
||||||
The full source for Catch2, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there.
|
The full source for Catch2, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there.
|
||||||
|
|
||||||
@@ -23,6 +26,9 @@ Catch2 is header only. All you need to do is drop the file somewhere reachable f
|
|||||||
|
|
||||||
The rest of this tutorial will assume that the Catch2 single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary.
|
The rest of this tutorial will assume that the Catch2 single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary.
|
||||||
|
|
||||||
|
_If you have installed Catch2 from system package manager, or CMake
|
||||||
|
package, you need to include the header as `#include <catch2/catch.hpp>`_
|
||||||
|
|
||||||
## Writing tests
|
## Writing tests
|
||||||
|
|
||||||
Let's start with a really simple example ([code](../examples/010-TestCase.cpp)). Say you have written a function to calculate factorials and now you want to test it (let's leave aside TDD for now).
|
Let's start with a really simple example ([code](../examples/010-TestCase.cpp)). Say you have written a function to calculate factorials and now you want to test it (let's leave aside TDD for now).
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
// Let Catch provide main():
|
// Let Catch provide main():
|
||||||
#define CATCH_CONFIG_MAIN
|
#define CATCH_CONFIG_MAIN
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
// That's it
|
// That's it
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
// Let Catch provide main():
|
// Let Catch provide main():
|
||||||
#define CATCH_CONFIG_MAIN
|
#define CATCH_CONFIG_MAIN
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
int Factorial( int number ) {
|
int Factorial( int number ) {
|
||||||
return number <= 1 ? number : Factorial( number - 1 ) * number; // fail
|
return number <= 1 ? number : Factorial( number - 1 ) * number; // fail
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
// Let Catch provide main():
|
// Let Catch provide main():
|
||||||
#define CATCH_CONFIG_MAIN
|
#define CATCH_CONFIG_MAIN
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
TEST_CASE( "1: All test cases reside in other .cpp files (empty)", "[multi-file:1]" ) {
|
TEST_CASE( "1: All test cases reside in other .cpp files (empty)", "[multi-file:1]" ) {
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
// main() provided by Catch in file 020-TestCase-1.cpp.
|
// main() provided by Catch in file 020-TestCase-1.cpp.
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
int Factorial( int number ) {
|
int Factorial( int number ) {
|
||||||
return number <= 1 ? number : Factorial( number - 1 ) * number; // fail
|
return number <= 1 ? number : Factorial( number - 1 ) * number; // fail
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
// main() provided in 000-CatchMain.cpp
|
// main() provided in 000-CatchMain.cpp
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
std::string one() {
|
std::string one() {
|
||||||
return "1";
|
return "1";
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
// main() provided in 000-CatchMain.cpp
|
// main() provided in 000-CatchMain.cpp
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
|
TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
// main() provided in 000-CatchMain.cpp
|
// main() provided in 000-CatchMain.cpp
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
class DBConnection
|
class DBConnection
|
||||||
{
|
{
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
// main() provided in 000-CatchMain.cpp
|
// main() provided in 000-CatchMain.cpp
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
SCENARIO( "vectors can be sized and resized", "[vector]" ) {
|
SCENARIO( "vectors can be sized and resized", "[vector]" ) {
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
// Let Catch provide the required interfaces:
|
// Let Catch provide the required interfaces:
|
||||||
#define CATCH_CONFIG_EXTERNAL_INTERFACES
|
#define CATCH_CONFIG_EXTERNAL_INTERFACES
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include <catch2/catch.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
@@ -187,8 +187,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
|
|||||||
|
|
||||||
void print( std::ostream& os, int const level, std::string const& title, Catch::SectionInfo const& info ) {
|
void print( std::ostream& os, int const level, std::string const& title, Catch::SectionInfo const& info ) {
|
||||||
os << ws(level ) << title << ":\n"
|
os << ws(level ) << title << ":\n"
|
||||||
<< ws(level+1) << "- name: " << info.name << "\n"
|
<< ws(level+1) << "- name: " << info.name << "\n";
|
||||||
<< ws(level+1) << "- description: '" << info.description << "'\n";
|
|
||||||
print( os, level+1 , "- lineInfo", info.lineInfo );
|
print( os, level+1 , "- lineInfo", info.lineInfo );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
49
examples/231-Cfg-OutputStreams.cpp
Normal file
49
examples/231-Cfg-OutputStreams.cpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// 231-Cfg-OutputStreams.cpp
|
||||||
|
// Show how to replace the streams with a simple custom made streambuf.
|
||||||
|
|
||||||
|
// Note that this reimplementation _does not_ follow `std::cerr`
|
||||||
|
// semantic, because it buffers the output. For most uses however,
|
||||||
|
// there is no important difference between having `std::cerr` buffered
|
||||||
|
// or unbuffered.
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_NOSTDOUT
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
class out_buff : public std::stringbuf {
|
||||||
|
std::FILE* m_stream;
|
||||||
|
public:
|
||||||
|
out_buff(std::FILE* stream) :m_stream(stream) {}
|
||||||
|
~out_buff() { pubsync(); }
|
||||||
|
int sync() {
|
||||||
|
int ret = 0;
|
||||||
|
for (unsigned char c : str()) {
|
||||||
|
if (putc(c, m_stream) == EOF) {
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Reset the buffer to avoid printing it multiple times
|
||||||
|
str("");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
std::ostream& cout() {
|
||||||
|
static std::ostream ret(new out_buff(stdout));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
std::ostream& clog() {
|
||||||
|
static std::ostream ret(new out_buff(stderr));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
std::ostream& cerr() {
|
||||||
|
return clog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("This binary uses putc to write out output", "[compilation-only]") {
|
||||||
|
SUCCEED("Nothing to test.");
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Build examples.
|
# Build examples.
|
||||||
#
|
#
|
||||||
# Requires BUILD_EXAMPLES to be defined 'true', see ../CMakeLists.txt.
|
# Requires CATCH_BUILD_EXAMPLES to be defined 'true', see ../CMakeLists.txt.
|
||||||
#
|
#
|
||||||
|
|
||||||
cmake_minimum_required( VERSION 3.0 )
|
cmake_minimum_required( VERSION 3.0 )
|
||||||
@@ -17,6 +17,7 @@ set( HEADER_DIR ${CATCH_DIR}/single_include )
|
|||||||
|
|
||||||
set( SOURCES_SINGLE_FILE
|
set( SOURCES_SINGLE_FILE
|
||||||
010-TestCase.cpp
|
010-TestCase.cpp
|
||||||
|
231-Cfg-OutputStreams.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# multiple-file modules:
|
# multiple-file modules:
|
||||||
@@ -68,16 +69,16 @@ set( TARGETS_ALL ${TARGETS_SINGLE_FILE} ${TARGETS_IDIOMATIC_TESTS} 0
|
|||||||
|
|
||||||
# define program targets:
|
# define program targets:
|
||||||
|
|
||||||
add_library( CatchMain OBJECT ${EXAMPLES_DIR}/${SOURCES_IDIOMATIC_MAIN} ${HEADER_DIR}/catch.hpp )
|
add_library( CatchMain OBJECT ${EXAMPLES_DIR}/${SOURCES_IDIOMATIC_MAIN} ${HEADER_DIR}/catch2/catch.hpp )
|
||||||
|
|
||||||
add_executable( 020-TestCase ${EXAMPLES_DIR}/020-TestCase-1.cpp ${EXAMPLES_DIR}/020-TestCase-2.cpp ${HEADER_DIR}/catch.hpp )
|
add_executable( 020-TestCase ${EXAMPLES_DIR}/020-TestCase-1.cpp ${EXAMPLES_DIR}/020-TestCase-2.cpp ${HEADER_DIR}/catch2/catch.hpp )
|
||||||
|
|
||||||
foreach( name ${TARGETS_SINGLE_FILE} )
|
foreach( name ${TARGETS_SINGLE_FILE} )
|
||||||
add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp ${HEADER_DIR}/catch.hpp )
|
add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp ${HEADER_DIR}/catch2/catch.hpp )
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
foreach( name ${TARGETS_IDIOMATIC_TESTS} )
|
foreach( name ${TARGETS_IDIOMATIC_TESTS} )
|
||||||
add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp $<TARGET_OBJECTS:CatchMain> ${HEADER_DIR}/catch.hpp )
|
add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp $<TARGET_OBJECTS:CatchMain> ${HEADER_DIR}/catch2/catch.hpp )
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
foreach( name ${TARGETS_ALL} )
|
foreach( name ${TARGETS_ALL} )
|
||||||
|
@@ -9,6 +9,9 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_HPP_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_HPP_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
|
||||||
|
|
||||||
|
#define CATCH_VERSION_MAJOR 2
|
||||||
|
#define CATCH_VERSION_MINOR 3
|
||||||
|
#define CATCH_VERSION_PATCH 0
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
# pragma clang system_header
|
# pragma clang system_header
|
||||||
@@ -30,7 +33,9 @@
|
|||||||
# if defined(CATCH_CONFIG_DISABLE_MATCHERS)
|
# if defined(CATCH_CONFIG_DISABLE_MATCHERS)
|
||||||
# undef CATCH_CONFIG_DISABLE_MATCHERS
|
# undef CATCH_CONFIG_DISABLE_MATCHERS
|
||||||
# endif
|
# endif
|
||||||
# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
|
# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
|
||||||
|
# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(CATCH_CONFIG_IMPL_ONLY)
|
#if !defined(CATCH_CONFIG_IMPL_ONLY)
|
||||||
@@ -132,6 +137,7 @@
|
|||||||
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
|
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
|
||||||
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
|
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
|
||||||
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
|
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
|
||||||
|
#define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
|
||||||
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
|
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
|
||||||
#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
||||||
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
||||||
@@ -141,11 +147,11 @@
|
|||||||
// "BDD-style" convenience wrappers
|
// "BDD-style" convenience wrappers
|
||||||
#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
|
#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
|
||||||
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
|
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
|
||||||
#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc )
|
#define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
|
||||||
#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc )
|
#define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
|
||||||
#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc )
|
#define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And when: " << desc )
|
||||||
#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc )
|
#define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
|
||||||
#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc )
|
#define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
|
||||||
|
|
||||||
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
|
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
|
||||||
#else
|
#else
|
||||||
@@ -191,6 +197,7 @@
|
|||||||
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
|
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
|
||||||
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
|
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
|
||||||
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
|
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
|
||||||
|
#define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
|
||||||
#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
|
#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
|
||||||
#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
||||||
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
||||||
@@ -204,15 +211,16 @@
|
|||||||
#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
|
#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
|
||||||
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
|
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
|
||||||
|
|
||||||
#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc )
|
#define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
|
||||||
#define WHEN( desc ) SECTION( std::string(" When: ") + desc )
|
#define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
|
||||||
#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc )
|
#define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And when: " << desc )
|
||||||
#define THEN( desc ) SECTION( std::string(" Then: ") + desc )
|
#define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
|
||||||
#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc )
|
#define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
|
||||||
|
|
||||||
using Catch::Detail::Approx;
|
using Catch::Detail::Approx;
|
||||||
|
|
||||||
#else
|
#else // CATCH_CONFIG_DISABLE
|
||||||
|
|
||||||
//////
|
//////
|
||||||
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
|
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
|
||||||
#ifdef CATCH_CONFIG_PREFIX_ALL
|
#ifdef CATCH_CONFIG_PREFIX_ALL
|
||||||
@@ -257,6 +265,7 @@ using Catch::Detail::Approx;
|
|||||||
#define CATCH_METHOD_AS_TEST_CASE( method, ... )
|
#define CATCH_METHOD_AS_TEST_CASE( method, ... )
|
||||||
#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
|
#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
|
||||||
#define CATCH_SECTION( ... )
|
#define CATCH_SECTION( ... )
|
||||||
|
#define CATCH_DYNAMIC_SECTION( ... )
|
||||||
#define CATCH_FAIL( ... ) (void)(0)
|
#define CATCH_FAIL( ... ) (void)(0)
|
||||||
#define CATCH_FAIL_CHECK( ... ) (void)(0)
|
#define CATCH_FAIL_CHECK( ... ) (void)(0)
|
||||||
#define CATCH_SUCCEED( ... ) (void)(0)
|
#define CATCH_SUCCEED( ... ) (void)(0)
|
||||||
@@ -316,6 +325,7 @@ using Catch::Detail::Approx;
|
|||||||
#define METHOD_AS_TEST_CASE( method, ... )
|
#define METHOD_AS_TEST_CASE( method, ... )
|
||||||
#define REGISTER_TEST_CASE( Function, ... ) (void)(0)
|
#define REGISTER_TEST_CASE( Function, ... ) (void)(0)
|
||||||
#define SECTION( ... )
|
#define SECTION( ... )
|
||||||
|
#define DYNAMIC_SECTION( ... )
|
||||||
#define FAIL( ... ) (void)(0)
|
#define FAIL( ... ) (void)(0)
|
||||||
#define FAIL_CHECK( ... ) (void)(0)
|
#define FAIL_CHECK( ... ) (void)(0)
|
||||||
#define SUCCEED( ... ) (void)(0)
|
#define SUCCEED( ... ) (void)(0)
|
||||||
|
150
include/external/clara.hpp
vendored
150
include/external/clara.hpp
vendored
@@ -1,5 +1,11 @@
|
|||||||
// v1.0-develop.2
|
// Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
|
||||||
// See https://github.com/philsquared/Clara
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
// See https://github.com/philsquared/Clara for more details
|
||||||
|
|
||||||
|
// Clara v1.1.4
|
||||||
|
|
||||||
#ifndef CATCH_CLARA_HPP_INCLUDED
|
#ifndef CATCH_CLARA_HPP_INCLUDED
|
||||||
#define CATCH_CLARA_HPP_INCLUDED
|
#define CATCH_CLARA_HPP_INCLUDED
|
||||||
@@ -12,6 +18,16 @@
|
|||||||
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
|
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
|
||||||
#endif
|
#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 -----------
|
// ----------- #included from clara_textflow.hpp -----------
|
||||||
|
|
||||||
// TextFlowCpp
|
// TextFlowCpp
|
||||||
@@ -370,7 +386,7 @@ namespace detail {
|
|||||||
template<typename ClassT, typename ReturnT, typename ArgT>
|
template<typename ClassT, typename ReturnT, typename ArgT>
|
||||||
struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
|
struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
|
||||||
static const bool isValid = true;
|
static const bool isValid = true;
|
||||||
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;;
|
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
|
||||||
using ReturnType = ReturnT;
|
using ReturnType = ReturnT;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -383,11 +399,9 @@ namespace detail {
|
|||||||
std::vector<std::string> m_args;
|
std::vector<std::string> m_args;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Args( int argc, char *argv[] ) {
|
Args( int argc, char const* const* argv )
|
||||||
m_exeName = argv[0];
|
: m_exeName(argv[0]),
|
||||||
for( int i = 1; i < argc; ++i )
|
m_args(argv + 1, argv + argc) {}
|
||||||
m_args.push_back( argv[i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
Args( std::initializer_list<std::string> args )
|
Args( std::initializer_list<std::string> args )
|
||||||
: m_exeName( *args.begin() ),
|
: m_exeName( *args.begin() ),
|
||||||
@@ -535,7 +549,7 @@ namespace detail {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ResultValueBase() {
|
~ResultValueBase() override {
|
||||||
if( m_type == Ok )
|
if( m_type == Ok )
|
||||||
m_value.~T();
|
m_value.~T();
|
||||||
}
|
}
|
||||||
@@ -573,16 +587,14 @@ namespace detail {
|
|||||||
auto errorMessage() const -> std::string { return m_errorMessage; }
|
auto errorMessage() const -> std::string { return m_errorMessage; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void enforceOk() const {
|
void enforceOk() const override {
|
||||||
// !TBD: If no exceptions, std::terminate here or something
|
|
||||||
switch( m_type ) {
|
// Errors shouldn't reach this point, but if they do
|
||||||
case ResultBase::LogicError:
|
// the actual error message will be in m_errorMessage
|
||||||
throw std::logic_error( m_errorMessage );
|
assert( m_type != ResultBase::LogicError );
|
||||||
case ResultBase::RuntimeError:
|
assert( m_type != ResultBase::RuntimeError );
|
||||||
throw std::runtime_error( m_errorMessage );
|
if( m_type != ResultBase::Ok )
|
||||||
case ResultBase::Ok:
|
std::abort();
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string m_errorMessage; // Only populated if resultType is an error
|
std::string m_errorMessage; // Only populated if resultType is an error
|
||||||
@@ -652,47 +664,43 @@ namespace detail {
|
|||||||
return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
|
return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
|
||||||
return ParserResult::ok( ParseResultType::Matched );
|
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 BoundRefBase {
|
struct NonCopyable {
|
||||||
BoundRefBase() = default;
|
NonCopyable() = default;
|
||||||
BoundRefBase( BoundRefBase const & ) = delete;
|
NonCopyable( NonCopyable const & ) = delete;
|
||||||
BoundRefBase( BoundRefBase && ) = delete;
|
NonCopyable( NonCopyable && ) = delete;
|
||||||
BoundRefBase &operator=( BoundRefBase const & ) = delete;
|
NonCopyable &operator=( NonCopyable const & ) = delete;
|
||||||
BoundRefBase &operator=( BoundRefBase && ) = delete;
|
NonCopyable &operator=( NonCopyable && ) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~BoundRefBase() = default;
|
struct BoundRef : NonCopyable {
|
||||||
|
virtual ~BoundRef() = default;
|
||||||
virtual auto isFlag() const -> bool = 0;
|
|
||||||
virtual auto isContainer() const -> bool { return false; }
|
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;
|
virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
|
||||||
|
};
|
||||||
|
struct BoundFlagRefBase : BoundRef {
|
||||||
virtual auto setFlag( bool flag ) -> ParserResult = 0;
|
virtual auto setFlag( bool flag ) -> ParserResult = 0;
|
||||||
};
|
virtual auto isFlag() const -> bool { return true; }
|
||||||
|
|
||||||
struct BoundValueRefBase : BoundRefBase {
|
|
||||||
auto isFlag() const -> bool override { return false; }
|
|
||||||
|
|
||||||
auto setFlag( bool ) -> ParserResult override {
|
|
||||||
return ParserResult::logicError( "Flags can only be set on boolean fields" );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BoundFlagRefBase : BoundRefBase {
|
|
||||||
auto isFlag() const -> bool override { return true; }
|
|
||||||
|
|
||||||
auto setValue( std::string const &arg ) -> ParserResult override {
|
|
||||||
bool flag;
|
|
||||||
auto result = convertInto( arg, flag );
|
|
||||||
if( result )
|
|
||||||
setFlag( flag );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct BoundRef : BoundValueRefBase {
|
struct BoundValueRef : BoundValueRefBase {
|
||||||
T &m_ref;
|
T &m_ref;
|
||||||
|
|
||||||
explicit BoundRef( T &ref ) : m_ref( ref ) {}
|
explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
|
||||||
|
|
||||||
auto setValue( std::string const &arg ) -> ParserResult override {
|
auto setValue( std::string const &arg ) -> ParserResult override {
|
||||||
return convertInto( arg, m_ref );
|
return convertInto( arg, m_ref );
|
||||||
@@ -700,10 +708,10 @@ namespace detail {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct BoundRef<std::vector<T>> : BoundValueRefBase {
|
struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
|
||||||
std::vector<T> &m_ref;
|
std::vector<T> &m_ref;
|
||||||
|
|
||||||
explicit BoundRef( std::vector<T> &ref ) : m_ref( ref ) {}
|
explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
|
||||||
|
|
||||||
auto isContainer() const -> bool override { return true; }
|
auto isContainer() const -> bool override { return true; }
|
||||||
|
|
||||||
@@ -748,12 +756,12 @@ namespace detail {
|
|||||||
|
|
||||||
template<typename ArgType, typename L>
|
template<typename ArgType, typename L>
|
||||||
inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
|
inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
|
||||||
ArgType temp;
|
ArgType temp{};
|
||||||
auto result = convertInto( arg, temp );
|
auto result = convertInto( arg, temp );
|
||||||
return !result
|
return !result
|
||||||
? result
|
? result
|
||||||
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
|
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename L>
|
template<typename L>
|
||||||
@@ -803,6 +811,9 @@ namespace detail {
|
|||||||
public:
|
public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto operator|( T const &other ) const -> Parser;
|
auto operator|( T const &other ) const -> Parser;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto operator+( T const &other ) const -> Parser;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Common code and state for Args and Opts
|
// Common code and state for Args and Opts
|
||||||
@@ -810,16 +821,16 @@ namespace detail {
|
|||||||
class ParserRefImpl : public ComposableParserImpl<DerivedT> {
|
class ParserRefImpl : public ComposableParserImpl<DerivedT> {
|
||||||
protected:
|
protected:
|
||||||
Optionality m_optionality = Optionality::Optional;
|
Optionality m_optionality = Optionality::Optional;
|
||||||
std::shared_ptr<BoundRefBase> m_ref;
|
std::shared_ptr<BoundRef> m_ref;
|
||||||
std::string m_hint;
|
std::string m_hint;
|
||||||
std::string m_description;
|
std::string m_description;
|
||||||
|
|
||||||
explicit ParserRefImpl( std::shared_ptr<BoundRefBase> const &ref ) : m_ref( ref ) {}
|
explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ParserRefImpl( T &ref, std::string const &hint )
|
ParserRefImpl( T &ref, std::string const &hint )
|
||||||
: m_ref( std::make_shared<BoundRef<T>>( ref ) ),
|
: m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
|
||||||
m_hint( hint )
|
m_hint( hint )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -860,10 +871,10 @@ namespace detail {
|
|||||||
|
|
||||||
class ExeName : public ComposableParserImpl<ExeName> {
|
class ExeName : public ComposableParserImpl<ExeName> {
|
||||||
std::shared_ptr<std::string> m_name;
|
std::shared_ptr<std::string> m_name;
|
||||||
std::shared_ptr<BoundRefBase> m_ref;
|
std::shared_ptr<BoundValueRefBase> m_ref;
|
||||||
|
|
||||||
template<typename LambdaT>
|
template<typename LambdaT>
|
||||||
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundRefBase> {
|
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {
|
||||||
return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
|
return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -871,7 +882,7 @@ namespace detail {
|
|||||||
ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
|
ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
|
||||||
|
|
||||||
explicit ExeName( std::string &ref ) : ExeName() {
|
explicit ExeName( std::string &ref ) : ExeName() {
|
||||||
m_ref = std::make_shared<BoundRef<std::string>>( ref );
|
m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LambdaT>
|
template<typename LambdaT>
|
||||||
@@ -914,7 +925,10 @@ namespace detail {
|
|||||||
if( token.type != TokenType::Argument )
|
if( token.type != TokenType::Argument )
|
||||||
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
|
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
|
||||||
|
|
||||||
auto result = m_ref->setValue( remainingTokens->token );
|
assert( !m_ref->isFlag() );
|
||||||
|
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
|
||||||
|
|
||||||
|
auto result = valueRef->setValue( remainingTokens->token );
|
||||||
if( !result )
|
if( !result )
|
||||||
return InternalParseResult( result );
|
return InternalParseResult( result );
|
||||||
else
|
else
|
||||||
@@ -988,19 +1002,21 @@ namespace detail {
|
|||||||
auto const &token = *remainingTokens;
|
auto const &token = *remainingTokens;
|
||||||
if( isMatch(token.token ) ) {
|
if( isMatch(token.token ) ) {
|
||||||
if( m_ref->isFlag() ) {
|
if( m_ref->isFlag() ) {
|
||||||
auto result = m_ref->setFlag( true );
|
auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
|
||||||
|
auto result = flagRef->setFlag( true );
|
||||||
if( !result )
|
if( !result )
|
||||||
return InternalParseResult( result );
|
return InternalParseResult( result );
|
||||||
if( result.value() == ParseResultType::ShortCircuitAll )
|
if( result.value() == ParseResultType::ShortCircuitAll )
|
||||||
return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
|
return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
|
||||||
} else {
|
} else {
|
||||||
|
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
|
||||||
++remainingTokens;
|
++remainingTokens;
|
||||||
if( !remainingTokens )
|
if( !remainingTokens )
|
||||||
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
|
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
|
||||||
auto const &argToken = *remainingTokens;
|
auto const &argToken = *remainingTokens;
|
||||||
if( argToken.type != TokenType::Argument )
|
if( argToken.type != TokenType::Argument )
|
||||||
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
|
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
|
||||||
auto result = m_ref->setValue( argToken.token );
|
auto result = valueRef->setValue( argToken.token );
|
||||||
if( !result )
|
if( !result )
|
||||||
return InternalParseResult( result );
|
return InternalParseResult( result );
|
||||||
if( result.value() == ParseResultType::ShortCircuitAll )
|
if( result.value() == ParseResultType::ShortCircuitAll )
|
||||||
@@ -1077,6 +1093,12 @@ namespace detail {
|
|||||||
return Parser( *this ) |= other;
|
return Parser( *this ) |= other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Forward deprecated interface with '+' instead of '|'
|
||||||
|
template<typename T>
|
||||||
|
auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
|
||||||
|
template<typename T>
|
||||||
|
auto operator+( T const &other ) const -> Parser { return operator|( other ); }
|
||||||
|
|
||||||
auto getHelpColumns() const -> std::vector<HelpColumns> {
|
auto getHelpColumns() const -> std::vector<HelpColumns> {
|
||||||
std::vector<HelpColumns> cols;
|
std::vector<HelpColumns> cols;
|
||||||
for (auto const &o : m_options) {
|
for (auto const &o : m_options) {
|
||||||
@@ -1116,6 +1138,8 @@ namespace detail {
|
|||||||
for( auto const &cols : rows )
|
for( auto const &cols : rows )
|
||||||
optWidth = (std::max)(optWidth, cols.left.size() + 2);
|
optWidth = (std::max)(optWidth, cols.left.size() + 2);
|
||||||
|
|
||||||
|
optWidth = (std::min)(optWidth, consoleWidth/2);
|
||||||
|
|
||||||
for( auto const &cols : rows ) {
|
for( auto const &cols : rows ) {
|
||||||
auto row =
|
auto row =
|
||||||
TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
|
TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
|
||||||
|
@@ -35,6 +35,13 @@ namespace Detail {
|
|||||||
return Approx( 0 );
|
return Approx( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Approx Approx::operator-() const {
|
||||||
|
auto temp(*this);
|
||||||
|
temp.m_value = -temp.m_value;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Approx::toString() const {
|
std::string Approx::toString() const {
|
||||||
ReusableStringStream rss;
|
ReusableStringStream rss;
|
||||||
rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
|
rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
|
||||||
@@ -49,6 +56,15 @@ namespace Detail {
|
|||||||
|
|
||||||
} // end namespace Detail
|
} // end namespace Detail
|
||||||
|
|
||||||
|
namespace literals {
|
||||||
|
Detail::Approx operator "" _a(long double val) {
|
||||||
|
return Detail::Approx(val);
|
||||||
|
}
|
||||||
|
Detail::Approx operator "" _a(unsigned long long val) {
|
||||||
|
return Detail::Approx(val);
|
||||||
|
}
|
||||||
|
} // end namespace literals
|
||||||
|
|
||||||
std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
|
std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
|
||||||
return value.toString();
|
return value.toString();
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,8 @@ namespace Detail {
|
|||||||
|
|
||||||
static Approx custom();
|
static Approx custom();
|
||||||
|
|
||||||
|
Approx operator-() const;
|
||||||
|
|
||||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||||
Approx operator()( T const& value ) {
|
Approx operator()( T const& value ) {
|
||||||
Approx approx( static_cast<double>(value) );
|
Approx approx( static_cast<double>(value) );
|
||||||
@@ -121,7 +123,12 @@ namespace Detail {
|
|||||||
double m_scale;
|
double m_scale;
|
||||||
double m_value;
|
double m_value;
|
||||||
};
|
};
|
||||||
}
|
} // end namespace Detail
|
||||||
|
|
||||||
|
namespace literals {
|
||||||
|
Detail::Approx operator "" _a(long double val);
|
||||||
|
Detail::Approx operator "" _a(unsigned long long val);
|
||||||
|
} // end namespace literals
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct StringMaker<Catch::Detail::Approx> {
|
struct StringMaker<Catch::Detail::Approx> {
|
||||||
|
@@ -18,9 +18,11 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
|
namespace {
|
||||||
expr.streamReconstructedExpression( os );
|
auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
|
||||||
return os;
|
expr.streamReconstructedExpression( os );
|
||||||
|
return os;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyExpression::LazyExpression( bool isNegated )
|
LazyExpression::LazyExpression( bool isNegated )
|
||||||
|
@@ -65,9 +65,9 @@ namespace Catch {
|
|||||||
expr = m_info.capturedExpression;
|
expr = m_info.capturedExpression;
|
||||||
else {
|
else {
|
||||||
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
|
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
|
||||||
expr += m_info.macroName.c_str();
|
expr += m_info.macroName;
|
||||||
expr += "( ";
|
expr += "( ";
|
||||||
expr += m_info.capturedExpression.c_str();
|
expr += m_info.capturedExpression;
|
||||||
expr += " )";
|
expr += " )";
|
||||||
}
|
}
|
||||||
return expr;
|
return expr;
|
||||||
|
@@ -115,7 +115,7 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
|
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
|
||||||
do { \
|
do { \
|
||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
|
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
|
||||||
catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
|
catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( false )
|
} while( false )
|
||||||
|
@@ -13,7 +13,7 @@ namespace Catch {
|
|||||||
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
|
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
|
||||||
|
|
||||||
// This is the general overload that takes a any string matcher
|
// 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)
|
// the Equals matcher (so the header does not mention matchers)
|
||||||
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) {
|
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) {
|
||||||
std::string exceptionMessage = Catch::translateActiveException();
|
std::string exceptionMessage = Catch::translateActiveException();
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include "catch_capture.hpp"
|
#include "catch_capture.hpp"
|
||||||
#include "catch_matchers.h"
|
#include "catch_matchers.h"
|
||||||
#include "catch_matchers_floating.h"
|
#include "catch_matchers_floating.h"
|
||||||
|
#include "catch_matchers_generic.hpp"
|
||||||
#include "catch_matchers_string.h"
|
#include "catch_matchers_string.h"
|
||||||
#include "catch_matchers_vector.h"
|
#include "catch_matchers_vector.h"
|
||||||
|
|
||||||
|
@@ -20,9 +20,19 @@ namespace Catch {
|
|||||||
using namespace clara;
|
using namespace clara;
|
||||||
|
|
||||||
auto const setWarning = [&]( std::string const& warning ) {
|
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 + "'" );
|
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 );
|
return ParserResult::ok( ParseResultType::Matched );
|
||||||
};
|
};
|
||||||
auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
|
auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
|
||||||
@@ -120,7 +130,7 @@ namespace Catch {
|
|||||||
| Opt( config.outputFilename, "filename" )
|
| Opt( config.outputFilename, "filename" )
|
||||||
["-o"]["--out"]
|
["-o"]["--out"]
|
||||||
( "output filename" )
|
( "output filename" )
|
||||||
| Opt( config.reporterNames, "name" )
|
| Opt( config.reporterName, "name" )
|
||||||
["-r"]["--reporter"]
|
["-r"]["--reporter"]
|
||||||
( "reporter to use (defaults to console)" )
|
( "reporter to use (defaults to console)" )
|
||||||
| Opt( config.name, "name" )
|
| Opt( config.name, "name" )
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
// Many features, at point of detection, define an _INTERNAL_ macro, so they
|
// Many features, at point of detection, define an _INTERNAL_ macro, so they
|
||||||
// can be combined, en-mass, with the _NO_ forms later.
|
// can be combined, en-mass, with the _NO_ forms later.
|
||||||
|
|
||||||
|
#include "catch_platform.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
@@ -31,6 +32,14 @@
|
|||||||
# define CATCH_CPP14_OR_GREATER
|
# define CATCH_CPP14_OR_GREATER
|
||||||
# endif
|
# 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
|
#endif
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
@@ -48,17 +57,25 @@
|
|||||||
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
|
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
|
||||||
_Pragma( "clang diagnostic pop" )
|
_Pragma( "clang diagnostic pop" )
|
||||||
|
|
||||||
|
# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
|
||||||
|
_Pragma( "clang diagnostic push" ) \
|
||||||
|
_Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
|
||||||
|
# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \
|
||||||
|
_Pragma( "clang diagnostic pop" )
|
||||||
|
|
||||||
#endif // __clang__
|
#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
|
// We know some environments not to support full POSIX signals
|
||||||
#if defined(__CYGWIN__) || defined(__QNX__)
|
#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
|
||||||
|
#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
|
||||||
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
|
|
||||||
# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __OS400__
|
#ifdef __OS400__
|
||||||
@@ -66,6 +83,24 @@
|
|||||||
# define CATCH_CONFIG_COLOUR_NONE
|
# define CATCH_CONFIG_COLOUR_NONE
|
||||||
#endif
|
#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
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// PS4
|
||||||
|
#if defined(__ORBIS__)
|
||||||
|
# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Cygwin
|
// Cygwin
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
@@ -80,6 +115,11 @@
|
|||||||
// Visual C++
|
// Visual C++
|
||||||
#ifdef _MSC_VER
|
#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
|
// Universal Windows platform does not support SEH
|
||||||
// Or console colours (or console at all...)
|
// Or console colours (or console at all...)
|
||||||
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
|
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
|
||||||
@@ -92,6 +132,13 @@
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// DJGPP
|
||||||
|
#ifdef __DJGPP__
|
||||||
|
# define CATCH_INTERNAL_CONFIG_NO_WCHAR
|
||||||
|
#endif // __DJGPP__
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Use of __COUNTER__ is suppressed during code analysis in
|
// Use of __COUNTER__ is suppressed during code analysis in
|
||||||
// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
|
// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
|
||||||
// handled by it.
|
// handled by it.
|
||||||
@@ -104,13 +151,33 @@
|
|||||||
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
|
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
|
||||||
# define CATCH_CONFIG_COUNTER
|
# define CATCH_CONFIG_COUNTER
|
||||||
#endif
|
#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
|
# define CATCH_CONFIG_WINDOWS_SEH
|
||||||
#endif
|
#endif
|
||||||
// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
|
// 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
|
# define CATCH_CONFIG_POSIX_SIGNALS
|
||||||
#endif
|
#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_CONFIG_EXPERIMENTAL_REDIRECT)
|
||||||
|
# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)
|
||||||
|
# define CATCH_CONFIG_NEW_CAPTURE
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
|
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
|
||||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
||||||
@@ -120,6 +187,10 @@
|
|||||||
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
|
||||||
|
# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
|
||||||
|
# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
|
||||||
|
@@ -15,12 +15,16 @@ namespace Catch {
|
|||||||
: m_data( data ),
|
: m_data( data ),
|
||||||
m_stream( openStream() )
|
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 )
|
for( auto const& testOrTags : data.testsOrTags )
|
||||||
parser.parse( testOrTags );
|
parser.parse( testOrTags );
|
||||||
m_testSpec = parser.testSpec();
|
|
||||||
}
|
}
|
||||||
|
m_testSpec = parser.testSpec();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string const& Config::getFilename() const {
|
std::string const& Config::getFilename() const {
|
||||||
@@ -33,11 +37,13 @@ namespace Catch {
|
|||||||
bool Config::listReporters() const { return m_data.listReporters; }
|
bool Config::listReporters() const { return m_data.listReporters; }
|
||||||
|
|
||||||
std::string Config::getProcessName() const { return m_data.processName; }
|
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; }
|
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
|
||||||
|
|
||||||
TestSpec const& Config::testSpec() const { return m_testSpec; }
|
TestSpec const& Config::testSpec() const { return m_testSpec; }
|
||||||
|
bool Config::hasTestFilters() const { return m_hasTestFilters; }
|
||||||
|
|
||||||
bool Config::showHelp() const { return m_data.showHelp; }
|
bool Config::showHelp() const { return m_data.showHelp; }
|
||||||
|
|
||||||
@@ -46,7 +52,8 @@ namespace Catch {
|
|||||||
std::ostream& Config::stream() const { return m_stream->stream(); }
|
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; }
|
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::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; }
|
ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
|
||||||
RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; }
|
RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; }
|
||||||
unsigned int Config::rngSeed() const { return m_data.rngSeed; }
|
unsigned int Config::rngSeed() const { return m_data.rngSeed; }
|
||||||
|
@@ -54,8 +54,12 @@ namespace Catch {
|
|||||||
std::string outputFilename;
|
std::string outputFilename;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string processName;
|
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> testsOrTags;
|
||||||
std::vector<std::string> sectionsToRun;
|
std::vector<std::string> sectionsToRun;
|
||||||
};
|
};
|
||||||
@@ -76,11 +80,13 @@ namespace Catch {
|
|||||||
bool listReporters() const;
|
bool listReporters() const;
|
||||||
|
|
||||||
std::string getProcessName() 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;
|
std::vector<std::string> const& getSectionsToRun() const override;
|
||||||
|
|
||||||
virtual TestSpec const& testSpec() const override;
|
virtual TestSpec const& testSpec() const override;
|
||||||
|
bool hasTestFilters() const override;
|
||||||
|
|
||||||
bool showHelp() const;
|
bool showHelp() const;
|
||||||
|
|
||||||
@@ -90,6 +96,7 @@ namespace Catch {
|
|||||||
std::string name() const override;
|
std::string name() const override;
|
||||||
bool includeSuccessfulResults() const override;
|
bool includeSuccessfulResults() const override;
|
||||||
bool warnAboutMissingAssertions() const override;
|
bool warnAboutMissingAssertions() const override;
|
||||||
|
bool warnAboutNoTests() const override;
|
||||||
ShowDurations::OrNot showDurations() const override;
|
ShowDurations::OrNot showDurations() const override;
|
||||||
RunTests::InWhatOrder runOrder() const override;
|
RunTests::InWhatOrder runOrder() const override;
|
||||||
unsigned int rngSeed() const override;
|
unsigned int rngSeed() const override;
|
||||||
@@ -107,6 +114,7 @@ namespace Catch {
|
|||||||
|
|
||||||
std::unique_ptr<IStream const> m_stream;
|
std::unique_ptr<IStream const> m_stream;
|
||||||
TestSpec m_testSpec;
|
TestSpec m_testSpec;
|
||||||
|
bool m_hasTestFilters = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
@@ -11,8 +11,8 @@
|
|||||||
# pragma clang diagnostic push
|
# pragma clang diagnostic push
|
||||||
# pragma clang diagnostic ignored "-Wexit-time-destructors"
|
# pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "catch_console_colour.h"
|
#include "catch_console_colour.h"
|
||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
#include "catch_errno_guard.h"
|
#include "catch_errno_guard.h"
|
||||||
@@ -84,8 +84,12 @@ namespace {
|
|||||||
case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
|
case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
|
||||||
case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
|
case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
|
||||||
case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
|
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" );
|
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::BrightRed: return setColour( "[1;31m" );
|
||||||
case Colour::BrightGreen: return setColour( "[1;32m" );
|
case Colour::BrightGreen: return setColour( "[1;32m" );
|
||||||
case Colour::BrightWhite: return setColour( "[1;37m" );
|
case Colour::BrightWhite: return setColour( "[1;37m" );
|
||||||
|
case Colour::BrightYellow: return setColour( "[1;33m" );
|
||||||
|
|
||||||
case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
|
case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
|
||||||
|
default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static IColourImpl* instance() {
|
static IColourImpl* instance() {
|
||||||
@@ -163,7 +169,12 @@ namespace {
|
|||||||
#ifdef CATCH_PLATFORM_MAC
|
#ifdef CATCH_PLATFORM_MAC
|
||||||
!isDebuggerActive() &&
|
!isDebuggerActive() &&
|
||||||
#endif
|
#endif
|
||||||
isatty(STDOUT_FILENO);
|
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
|
||||||
|
isatty(STDOUT_FILENO)
|
||||||
|
#else
|
||||||
|
false
|
||||||
|
#endif
|
||||||
|
;
|
||||||
}
|
}
|
||||||
IColourImpl* platformColourInstance() {
|
IColourImpl* platformColourInstance() {
|
||||||
ErrnoGuard guard;
|
ErrnoGuard guard;
|
||||||
@@ -196,7 +207,7 @@ namespace Catch {
|
|||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
Colour::Colour( Code _colourCode ) { use( _colourCode ); }
|
Colour::Colour( Code _colourCode ) { use( _colourCode ); }
|
||||||
Colour::Colour( Colour&& rhs ) noexcept {
|
Colour::Colour( Colour&& rhs ) noexcept {
|
||||||
m_moved = rhs.m_moved;
|
m_moved = rhs.m_moved;
|
||||||
rhs.m_moved = true;
|
rhs.m_moved = true;
|
||||||
}
|
}
|
||||||
@@ -205,7 +216,7 @@ namespace Catch {
|
|||||||
rhs.m_moved = true;
|
rhs.m_moved = true;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Colour::~Colour(){ if( !m_moved ) use( None ); }
|
Colour::~Colour(){ if( !m_moved ) use( None ); }
|
||||||
|
|
||||||
void Colour::use( Code _colourCode ) {
|
void Colour::use( Code _colourCode ) {
|
||||||
|
@@ -30,10 +30,11 @@ namespace Catch {
|
|||||||
BrightGreen = Bright | Green,
|
BrightGreen = Bright | Green,
|
||||||
LightGrey = Bright | Grey,
|
LightGrey = Bright | Grey,
|
||||||
BrightWhite = Bright | White,
|
BrightWhite = Bright | White,
|
||||||
|
BrightYellow = Bright | Yellow,
|
||||||
|
|
||||||
// By intention
|
// By intention
|
||||||
FileName = LightGrey,
|
FileName = LightGrey,
|
||||||
Warning = Yellow,
|
Warning = BrightYellow,
|
||||||
ResultError = BrightRed,
|
ResultError = BrightRed,
|
||||||
ResultSuccess = BrightGreen,
|
ResultSuccess = BrightGreen,
|
||||||
ResultExpectedFailure = Warning,
|
ResultExpectedFailure = Warning,
|
||||||
@@ -42,7 +43,7 @@ namespace Catch {
|
|||||||
Success = Green,
|
Success = Green,
|
||||||
|
|
||||||
OriginalExpression = Cyan,
|
OriginalExpression = Cyan,
|
||||||
ReconstructedExpression = Yellow,
|
ReconstructedExpression = BrightYellow,
|
||||||
|
|
||||||
SecondaryText = LightGrey,
|
SecondaryText = LightGrey,
|
||||||
Headers = White
|
Headers = White
|
||||||
|
@@ -9,21 +9,23 @@
|
|||||||
#include "catch_debug_console.h"
|
#include "catch_debug_console.h"
|
||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
#include "catch_platform.h"
|
#include "catch_platform.h"
|
||||||
|
#include "catch_windows_h_proxy.h"
|
||||||
|
|
||||||
#ifdef CATCH_PLATFORM_WINDOWS
|
#ifdef CATCH_PLATFORM_WINDOWS
|
||||||
|
|
||||||
#include "catch_windows_h_proxy.h"
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
void writeToDebugConsole( std::string const& text ) {
|
void writeToDebugConsole( std::string const& text ) {
|
||||||
::OutputDebugStringA( text.c_str() );
|
::OutputDebugStringA( text.c_str() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
void writeToDebugConsole( std::string const& text ) {
|
void writeToDebugConsole( std::string const& text ) {
|
||||||
// !TBD: Need a version for Mac/ XCode and other IDEs
|
// !TBD: Need a version for Mac/ XCode and other IDEs
|
||||||
Catch::cout() << text;
|
Catch::cout() << text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // Platform
|
#endif // Platform
|
||||||
|
@@ -40,7 +40,10 @@ namespace Catch {
|
|||||||
#ifdef CATCH_TRAP
|
#ifdef CATCH_TRAP
|
||||||
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
|
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
|
||||||
#else
|
#else
|
||||||
#define CATCH_BREAK_INTO_DEBUGGER() (void)0, 0
|
namespace Catch {
|
||||||
|
inline void doNothing() {}
|
||||||
|
}
|
||||||
|
#define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
#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)
|
// Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
|
||||||
template<typename LhsT, typename RhsT>
|
template<typename LhsT, typename RhsT>
|
||||||
auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return lhs == rhs; };
|
auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
|
auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -93,7 +93,7 @@ namespace Catch {
|
|||||||
auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
|
auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
|
||||||
|
|
||||||
template<typename LhsT, typename RhsT>
|
template<typename LhsT, typename RhsT>
|
||||||
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs != rhs; };
|
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
|
auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -128,19 +128,19 @@ namespace Catch {
|
|||||||
|
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return { m_lhs > rhs, m_lhs, ">", rhs };
|
return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs };
|
||||||
}
|
}
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return { m_lhs < rhs, m_lhs, "<", rhs };
|
return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs };
|
||||||
}
|
}
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return { m_lhs >= rhs, m_lhs, ">=", rhs };
|
return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs };
|
||||||
}
|
}
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return { m_lhs <= rhs, m_lhs, "<=", rhs };
|
return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#ifndef __OBJC__
|
#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
|
// Standard C/C++ Win32 Unicode wmain entry point
|
||||||
extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
|
extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
|
||||||
#else
|
#else
|
||||||
|
@@ -11,10 +11,9 @@
|
|||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iosfwd>
|
|
||||||
|
|
||||||
#define CATCH_PREPARE_EXCEPTION( type, msg ) \
|
#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 ) \
|
#define CATCH_INTERNAL_ERROR( msg ) \
|
||||||
throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg);
|
throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg);
|
||||||
#define CATCH_ERROR( msg ) \
|
#define CATCH_ERROR( msg ) \
|
||||||
|
@@ -33,6 +33,17 @@ namespace Catch {
|
|||||||
return Catch::Detail::stringify( [exception description] );
|
return Catch::Detail::stringify( [exception description] );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
// Compiling a mixed mode project with MSVC means that CLR
|
||||||
|
// exceptions will be caught in (...) as well. However, these
|
||||||
|
// do not fill-in std::current_exception and thus lead to crash
|
||||||
|
// when attempting rethrow.
|
||||||
|
// /EHa switch also causes structured exceptions to be caught
|
||||||
|
// here, but they fill-in current_exception properly, so
|
||||||
|
// at worst the output should be a little weird, instead of
|
||||||
|
// causing a crash.
|
||||||
|
if (std::current_exception() == nullptr) {
|
||||||
|
return "Non C++ exception. Possibly a CLR exception.";
|
||||||
|
}
|
||||||
return tryTranslators();
|
return tryTranslators();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,8 @@
|
|||||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Report the error condition
|
// Report the error condition
|
||||||
void reportFatal( char const * const message ) {
|
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 )
|
#if defined( CATCH_CONFIG_WINDOWS_SEH )
|
||||||
|
|
||||||
namespace Catch {
|
|
||||||
void FatalConditionHandler::reset() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
# else // CATCH_CONFIG_WINDOWS_SEH is defined
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
struct SignalDefs { DWORD id; const char* name; };
|
struct SignalDefs { DWORD id; const char* name; };
|
||||||
@@ -72,7 +68,6 @@ namespace Catch {
|
|||||||
|
|
||||||
void FatalConditionHandler::reset() {
|
void FatalConditionHandler::reset() {
|
||||||
if (isSet) {
|
if (isSet) {
|
||||||
// Unregister handler and restore the old guarantee
|
|
||||||
RemoveVectoredExceptionHandler(exceptionHandlerHandle);
|
RemoveVectoredExceptionHandler(exceptionHandlerHandle);
|
||||||
SetThreadStackGuarantee(&guaranteeSize);
|
SetThreadStackGuarantee(&guaranteeSize);
|
||||||
exceptionHandlerHandle = nullptr;
|
exceptionHandlerHandle = nullptr;
|
||||||
@@ -91,20 +86,7 @@ PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
|
|||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
# endif // CATCH_CONFIG_WINDOWS_SEH
|
#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
|
||||||
|
|
||||||
#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>
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -112,6 +94,11 @@ namespace Catch {
|
|||||||
int id;
|
int id;
|
||||||
const char* name;
|
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[] = {
|
static SignalDefs signalDefs[] = {
|
||||||
{ SIGINT, "SIGINT - Terminal interrupt signal" },
|
{ SIGINT, "SIGINT - Terminal interrupt signal" },
|
||||||
{ SIGILL, "SIGILL - Illegal instruction signal" },
|
{ SIGILL, "SIGILL - Illegal instruction signal" },
|
||||||
@@ -139,7 +126,7 @@ namespace Catch {
|
|||||||
isSet = true;
|
isSet = true;
|
||||||
stack_t sigStack;
|
stack_t sigStack;
|
||||||
sigStack.ss_sp = altStackMem;
|
sigStack.ss_sp = altStackMem;
|
||||||
sigStack.ss_size = SIGSTKSZ;
|
sigStack.ss_size = sigStackSize;
|
||||||
sigStack.ss_flags = 0;
|
sigStack.ss_flags = 0;
|
||||||
sigaltstack(&sigStack, &oldSigStack);
|
sigaltstack(&sigStack, &oldSigStack);
|
||||||
struct sigaction sa = { };
|
struct sigaction sa = { };
|
||||||
@@ -171,14 +158,18 @@ namespace Catch {
|
|||||||
bool FatalConditionHandler::isSet = false;
|
bool FatalConditionHandler::isSet = false;
|
||||||
struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
|
struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
|
||||||
stack_t FatalConditionHandler::oldSigStack = {};
|
stack_t FatalConditionHandler::oldSigStack = {};
|
||||||
char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
|
char FatalConditionHandler::altStackMem[sigStackSize] = {};
|
||||||
|
|
||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
# endif // CATCH_CONFIG_POSIX_SIGNALS
|
#else
|
||||||
|
|
||||||
#endif // not Windows
|
namespace Catch {
|
||||||
|
void FatalConditionHandler::reset() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // signals/SEH handling
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
# pragma GCC diagnostic pop
|
# pragma GCC diagnostic pop
|
||||||
|
@@ -9,23 +9,12 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "catch_platform.h"
|
#include "catch_platform.h"
|
||||||
#include "catch_compiler_capabilities.h"
|
#include "catch_compiler_capabilities.h"
|
||||||
|
|
||||||
|
|
||||||
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
|
||||||
#include "catch_windows_h_proxy.h"
|
#include "catch_windows_h_proxy.h"
|
||||||
|
|
||||||
# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
|
|
||||||
|
|
||||||
namespace Catch {
|
#if defined( CATCH_CONFIG_WINDOWS_SEH )
|
||||||
struct FatalConditionHandler {
|
|
||||||
void reset();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
# else // CATCH_CONFIG_WINDOWS_SEH is defined
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -44,20 +33,7 @@ namespace Catch {
|
|||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
# endif // CATCH_CONFIG_WINDOWS_SEH
|
#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
@@ -66,7 +42,7 @@ namespace Catch {
|
|||||||
struct FatalConditionHandler {
|
struct FatalConditionHandler {
|
||||||
|
|
||||||
static bool isSet;
|
static bool isSet;
|
||||||
static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)];
|
static struct sigaction oldSigActions[];
|
||||||
static stack_t oldSigStack;
|
static stack_t oldSigStack;
|
||||||
static char altStackMem[];
|
static char altStackMem[];
|
||||||
|
|
||||||
@@ -79,8 +55,15 @@ namespace Catch {
|
|||||||
|
|
||||||
} // 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
|
#endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
||||||
|
@@ -25,7 +25,8 @@ namespace Catch {
|
|||||||
|
|
||||||
struct WarnAbout { enum What {
|
struct WarnAbout { enum What {
|
||||||
Nothing = 0x00,
|
Nothing = 0x00,
|
||||||
NoAssertions = 0x01
|
NoAssertions = 0x01,
|
||||||
|
NoTests = 0x02
|
||||||
}; };
|
}; };
|
||||||
|
|
||||||
struct ShowDurations { enum OrNot {
|
struct ShowDurations { enum OrNot {
|
||||||
@@ -62,10 +63,12 @@ namespace Catch {
|
|||||||
virtual bool includeSuccessfulResults() const = 0;
|
virtual bool includeSuccessfulResults() const = 0;
|
||||||
virtual bool shouldDebugBreak() const = 0;
|
virtual bool shouldDebugBreak() const = 0;
|
||||||
virtual bool warnAboutMissingAssertions() const = 0;
|
virtual bool warnAboutMissingAssertions() const = 0;
|
||||||
|
virtual bool warnAboutNoTests() const = 0;
|
||||||
virtual int abortAfter() const = 0;
|
virtual int abortAfter() const = 0;
|
||||||
virtual bool showInvisibles() const = 0;
|
virtual bool showInvisibles() const = 0;
|
||||||
virtual ShowDurations::OrNot showDurations() const = 0;
|
virtual ShowDurations::OrNot showDurations() const = 0;
|
||||||
virtual TestSpec const& testSpec() const = 0;
|
virtual TestSpec const& testSpec() const = 0;
|
||||||
|
virtual bool hasTestFilters() const = 0;
|
||||||
virtual RunTests::InWhatOrder runOrder() const = 0;
|
virtual RunTests::InWhatOrder runOrder() const = 0;
|
||||||
virtual unsigned int rngSeed() const = 0;
|
virtual unsigned int rngSeed() const = 0;
|
||||||
virtual int benchmarkResolutionMultiple() const = 0;
|
virtual int benchmarkResolutionMultiple() const = 0;
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_interfaces_reporter.h"
|
#include "catch_interfaces_reporter.h"
|
||||||
#include "../reporters/catch_reporter_multi.h"
|
#include "../reporters/catch_reporter_listening.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -111,25 +111,4 @@ namespace Catch {
|
|||||||
IReporterFactory::~IReporterFactory() = default;
|
IReporterFactory::~IReporterFactory() = default;
|
||||||
IReporterRegistry::~IReporterRegistry() = 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
|
} // end namespace Catch
|
||||||
|
@@ -42,6 +42,7 @@ namespace Catch {
|
|||||||
|
|
||||||
struct ReporterPreferences {
|
struct ReporterPreferences {
|
||||||
bool shouldRedirectStdOut = false;
|
bool shouldRedirectStdOut = false;
|
||||||
|
bool shouldReportAllAssertions = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -226,8 +227,6 @@ namespace Catch {
|
|||||||
virtual Listeners const& getListeners() const = 0;
|
virtual Listeners const& getListeners() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter );
|
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
|
||||||
|
@@ -28,11 +28,10 @@ namespace Catch {
|
|||||||
|
|
||||||
std::size_t listTests( Config const& config ) {
|
std::size_t listTests( Config const& config ) {
|
||||||
TestSpec testSpec = config.testSpec();
|
TestSpec testSpec = config.testSpec();
|
||||||
if( config.testSpec().hasFilters() )
|
if( config.hasTestFilters() )
|
||||||
Catch::cout() << "Matching test cases:\n";
|
Catch::cout() << "Matching test cases:\n";
|
||||||
else {
|
else {
|
||||||
Catch::cout() << "All available test cases:\n";
|
Catch::cout() << "All available test cases:\n";
|
||||||
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
|
auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
|
||||||
@@ -54,7 +53,7 @@ namespace Catch {
|
|||||||
Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n";
|
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;
|
Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl;
|
||||||
else
|
else
|
||||||
Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl;
|
Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl;
|
||||||
@@ -63,8 +62,6 @@ namespace Catch {
|
|||||||
|
|
||||||
std::size_t listTestsNamesOnly( Config const& config ) {
|
std::size_t listTestsNamesOnly( Config const& config ) {
|
||||||
TestSpec testSpec = config.testSpec();
|
TestSpec testSpec = config.testSpec();
|
||||||
if( !config.testSpec().hasFilters() )
|
|
||||||
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
|
|
||||||
std::size_t matchedTests = 0;
|
std::size_t matchedTests = 0;
|
||||||
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
|
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
|
||||||
for( auto const& testCaseInfo : matchedTestCases ) {
|
for( auto const& testCaseInfo : matchedTestCases ) {
|
||||||
@@ -94,11 +91,10 @@ namespace Catch {
|
|||||||
|
|
||||||
std::size_t listTags( Config const& config ) {
|
std::size_t listTags( Config const& config ) {
|
||||||
TestSpec testSpec = config.testSpec();
|
TestSpec testSpec = config.testSpec();
|
||||||
if( config.testSpec().hasFilters() )
|
if( config.hasTestFilters() )
|
||||||
Catch::cout() << "Tags for matching test cases:\n";
|
Catch::cout() << "Tags for matching test cases:\n";
|
||||||
else {
|
else {
|
||||||
Catch::cout() << "All available tags:\n";
|
Catch::cout() << "All available tags:\n";
|
||||||
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, TagInfo> tagCounts;
|
std::map<std::string, TagInfo> tagCounts;
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_matchers_floating.h"
|
#include "catch_matchers_floating.h"
|
||||||
|
#include "catch_to_string.hpp"
|
||||||
#include "catch_tostring.h"
|
#include "catch_tostring.h"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@@ -88,7 +89,7 @@ namespace Floating {
|
|||||||
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
|
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
|
||||||
// But without the subtraction to allow for INFINITY in comparison
|
// But without the subtraction to allow for INFINITY in comparison
|
||||||
bool WithinAbsMatcher::match(double const& matchee) const {
|
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 {
|
std::string WithinAbsMatcher::describe() const {
|
||||||
@@ -115,7 +116,7 @@ namespace Floating {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string WithinUlpsMatcher::describe() const {
|
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
|
}// 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_message.h"
|
||||||
#include "catch_interfaces_capture.h"
|
#include "catch_interfaces_capture.h"
|
||||||
|
#include "catch_uncaught_exceptions.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -49,18 +50,9 @@ namespace Catch {
|
|||||||
getResultCapture().pushScopedMessage( m_info );
|
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() {
|
ScopedMessage::~ScopedMessage() {
|
||||||
if ( !std::uncaught_exception() ){
|
if ( !uncaught_exceptions() ){
|
||||||
getResultCapture().popScopedMessage(m_info);
|
getResultCapture().popScopedMessage(m_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
@@ -93,7 +93,7 @@ namespace Catch {
|
|||||||
std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
|
std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
|
||||||
const char* className = class_getName( cls );
|
const char* className = class_getName( cls );
|
||||||
|
|
||||||
getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo("",0) ) );
|
getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) );
|
||||||
noTestMethods++;
|
noTestMethods++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
139
include/internal/catch_output_redirect.cpp
Normal file
139
include/internal/catch_output_redirect.cpp
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* 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(CATCH_CONFIG_NEW_CAPTURE)
|
||||||
|
#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
|
||||||
|
#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(CATCH_CONFIG_NEW_CAPTURE)
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CATCH_CONFIG_NEW_CAPTURE
|
||||||
|
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
#if defined(CATCH_CONFIG_NEW_CAPTURE)
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#undef dup
|
||||||
|
#undef dup2
|
||||||
|
#undef fileno
|
||||||
|
#endif
|
||||||
|
#endif
|
101
include/internal/catch_output_redirect.h
Normal file
101
include/internal/catch_output_redirect.h
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(CATCH_CONFIG_NEW_CAPTURE)
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // end namespace Catch
|
||||||
|
|
||||||
|
#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
|
@@ -20,7 +20,7 @@
|
|||||||
#elif defined(linux) || defined(__linux) || defined(__linux__)
|
#elif defined(linux) || defined(__linux) || defined(__linux__)
|
||||||
# define CATCH_PLATFORM_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
|
# define CATCH_PLATFORM_WINDOWS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -9,23 +9,21 @@
|
|||||||
#include "catch_context.h"
|
#include "catch_context.h"
|
||||||
#include "catch_interfaces_config.h"
|
#include "catch_interfaces_config.h"
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
void seedRng( IConfig const& config ) {
|
std::mt19937& rng() {
|
||||||
if( config.rngSeed() != 0 )
|
static std::mt19937 s_rng;
|
||||||
std::srand( config.rngSeed() );
|
return s_rng;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void seedRng( IConfig const& config ) {
|
||||||
|
if( config.rngSeed() != 0 ) {
|
||||||
|
std::srand( config.rngSeed() );
|
||||||
|
rng().seed( config.rngSeed() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int rngSeed() {
|
unsigned int rngSeed() {
|
||||||
return getCurrentContext().getConfig()->rngSeed();
|
return getCurrentContext().getConfig()->rngSeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const {
|
|
||||||
return std::rand() % n;
|
|
||||||
}
|
|
||||||
RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const {
|
|
||||||
return std::rand() % (max)();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -8,31 +8,16 @@
|
|||||||
#define TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
struct IConfig;
|
struct IConfig;
|
||||||
|
|
||||||
|
std::mt19937& rng();
|
||||||
void seedRng( IConfig const& config );
|
void seedRng( IConfig const& config );
|
||||||
|
|
||||||
unsigned int rngSeed();
|
unsigned int rngSeed();
|
||||||
|
|
||||||
struct RandomNumberGenerator {
|
|
||||||
using result_type = unsigned int;
|
|
||||||
|
|
||||||
static constexpr result_type (min)() { return 0; }
|
|
||||||
static constexpr result_type (max)() { return 1000000; }
|
|
||||||
|
|
||||||
result_type operator()( result_type n ) const;
|
|
||||||
result_type operator()() const;
|
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
static void shuffle( V& vector ) {
|
|
||||||
RandomNumberGenerator rng;
|
|
||||||
std::shuffle( vector.begin(), vector.end(), rng );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
#include "catch_random_number_generator.h"
|
#include "catch_random_number_generator.h"
|
||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
|
#include "catch_output_redirect.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -10,55 +11,13 @@
|
|||||||
|
|
||||||
namespace Catch {
|
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)
|
RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
|
||||||
: m_runInfo(_config->name()),
|
: m_runInfo(_config->name()),
|
||||||
m_context(getCurrentMutableContext()),
|
m_context(getCurrentMutableContext()),
|
||||||
m_config(_config),
|
m_config(_config),
|
||||||
m_reporter(std::move(reporter)),
|
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_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
|
||||||
{
|
{
|
||||||
m_context.setRunner(this);
|
m_context.setRunner(this);
|
||||||
m_context.setConfig(m_config);
|
m_context.setConfig(m_config);
|
||||||
@@ -84,7 +43,7 @@ namespace Catch {
|
|||||||
std::string redirectedCout;
|
std::string redirectedCout;
|
||||||
std::string redirectedCerr;
|
std::string redirectedCerr;
|
||||||
|
|
||||||
TestCaseInfo testInfo = testCase.getTestCaseInfo();
|
auto const& testInfo = testCase.getTestCaseInfo();
|
||||||
|
|
||||||
m_reporter->testCaseStarting(testInfo);
|
m_reporter->testCaseStarting(testInfo);
|
||||||
|
|
||||||
@@ -249,7 +208,7 @@ namespace Catch {
|
|||||||
|
|
||||||
// Recreate section for test case (as we will lose the one that was in scope)
|
// Recreate section for test case (as we will lose the one that was in scope)
|
||||||
auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
|
auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
|
||||||
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
|
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
|
||||||
|
|
||||||
Counts assertions;
|
Counts assertions;
|
||||||
assertions.failed = 1;
|
assertions.failed = 1;
|
||||||
@@ -287,25 +246,31 @@ namespace Catch {
|
|||||||
|
|
||||||
void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
|
void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
|
||||||
auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
|
auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
|
||||||
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
|
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
|
||||||
m_reporter->sectionStarting(testCaseSection);
|
m_reporter->sectionStarting(testCaseSection);
|
||||||
Counts prevAssertions = m_totals.assertions;
|
Counts prevAssertions = m_totals.assertions;
|
||||||
double duration = 0;
|
double duration = 0;
|
||||||
m_shouldReportUnexpected = true;
|
m_shouldReportUnexpected = true;
|
||||||
m_lastAssertionInfo = { "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal };
|
m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
|
||||||
|
|
||||||
seedRng(*m_config);
|
seedRng(*m_config);
|
||||||
|
|
||||||
Timer timer;
|
Timer timer;
|
||||||
try {
|
try {
|
||||||
if (m_reporter->getPreferences().shouldRedirectStdOut) {
|
if (m_reporter->getPreferences().shouldRedirectStdOut) {
|
||||||
|
#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
|
||||||
RedirectedStdOut redirectedStdOut;
|
RedirectedStdOut redirectedStdOut;
|
||||||
RedirectedStdErr redirectedStdErr;
|
RedirectedStdErr redirectedStdErr;
|
||||||
|
|
||||||
timer.start();
|
timer.start();
|
||||||
invokeActiveTestCase();
|
invokeActiveTestCase();
|
||||||
redirectedCout += redirectedStdOut.str();
|
redirectedCout += redirectedStdOut.str();
|
||||||
redirectedCerr += redirectedStdErr.str();
|
redirectedCerr += redirectedStdErr.str();
|
||||||
|
#else
|
||||||
|
OutputRedirect r(redirectedCout, redirectedCerr);
|
||||||
|
timer.start();
|
||||||
|
invokeActiveTestCase();
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
timer.start();
|
timer.start();
|
||||||
invokeActiveTestCase();
|
invokeActiveTestCase();
|
||||||
@@ -321,12 +286,13 @@ namespace Catch {
|
|||||||
handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
|
handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Counts assertions = m_totals.assertions - prevAssertions;
|
||||||
|
bool missingAssertions = testForMissingAssertions(assertions);
|
||||||
|
|
||||||
m_testCaseTracker->close();
|
m_testCaseTracker->close();
|
||||||
handleUnfinishedSections();
|
handleUnfinishedSections();
|
||||||
m_messages.clear();
|
m_messages.clear();
|
||||||
|
|
||||||
Counts assertions = m_totals.assertions - prevAssertions;
|
|
||||||
bool missingAssertions = testForMissingAssertions(assertions);
|
|
||||||
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
|
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
|
||||||
m_reporter->sectionEnded(testCaseSectionStats);
|
m_reporter->sectionEnded(testCaseSectionStats);
|
||||||
}
|
}
|
||||||
|
@@ -99,7 +99,7 @@ namespace Catch {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// !TBD We need to do this another way!
|
// !TBD We need to do this another way!
|
||||||
bool aborting() const override;
|
bool aborting() const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "catch_section.h"
|
#include "catch_section.h"
|
||||||
#include "catch_capture.hpp"
|
#include "catch_capture.hpp"
|
||||||
|
#include "catch_uncaught_exceptions.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@@ -18,22 +19,15 @@ namespace Catch {
|
|||||||
m_timer.start();
|
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() {
|
Section::~Section() {
|
||||||
if( m_sectionIncluded ) {
|
if( m_sectionIncluded ) {
|
||||||
SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
|
SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };
|
||||||
if( std::uncaught_exception() )
|
if( uncaught_exceptions() )
|
||||||
getResultCapture().sectionEndedEarly( endInfo );
|
getResultCapture().sectionEndedEarly( endInfo );
|
||||||
else
|
else
|
||||||
getResultCapture().sectionEnded( endInfo );
|
getResultCapture().sectionEnded( endInfo );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// This indicates whether the section should be executed or not
|
// This indicates whether the section should be executed or not
|
||||||
Section::operator bool() const {
|
Section::operator bool() const {
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
||||||
|
|
||||||
|
#include "catch_compiler_capabilities.h"
|
||||||
#include "catch_section_info.h"
|
#include "catch_section_info.h"
|
||||||
#include "catch_totals.h"
|
#include "catch_totals.h"
|
||||||
#include "catch_timer.h"
|
#include "catch_timer.h"
|
||||||
@@ -35,7 +36,14 @@ namespace Catch {
|
|||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#define INTERNAL_CATCH_SECTION( ... ) \
|
#define INTERNAL_CATCH_SECTION( ... ) \
|
||||||
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
|
CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
|
||||||
|
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
|
||||||
|
|
||||||
|
#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
|
||||||
|
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
||||||
|
@@ -11,15 +11,9 @@ namespace Catch {
|
|||||||
|
|
||||||
SectionInfo::SectionInfo
|
SectionInfo::SectionInfo
|
||||||
( SourceLineInfo const& _lineInfo,
|
( SourceLineInfo const& _lineInfo,
|
||||||
std::string const& _name,
|
std::string const& _name )
|
||||||
std::string const& _description )
|
|
||||||
: name( _name ),
|
: name( _name ),
|
||||||
description( _description ),
|
|
||||||
lineInfo( _lineInfo )
|
lineInfo( _lineInfo )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
SectionEndInfo::SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
|
|
||||||
: sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
|
|
||||||
{}
|
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
@@ -16,19 +16,22 @@
|
|||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
struct SectionInfo {
|
struct SectionInfo {
|
||||||
|
SectionInfo
|
||||||
|
( SourceLineInfo const& _lineInfo,
|
||||||
|
std::string const& _name );
|
||||||
|
|
||||||
|
// Deprecated
|
||||||
SectionInfo
|
SectionInfo
|
||||||
( SourceLineInfo const& _lineInfo,
|
( SourceLineInfo const& _lineInfo,
|
||||||
std::string const& _name,
|
std::string const& _name,
|
||||||
std::string const& _description = std::string() );
|
std::string const& ) : SectionInfo( _lineInfo, _name ) {}
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string description;
|
std::string description; // !Deprecated: this will always be empty
|
||||||
SourceLineInfo lineInfo;
|
SourceLineInfo lineInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SectionEndInfo {
|
struct SectionEndInfo {
|
||||||
SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds );
|
|
||||||
|
|
||||||
SectionInfo sectionInfo;
|
SectionInfo sectionInfo;
|
||||||
Counts prevAssertions;
|
Counts prevAssertions;
|
||||||
double durationInSeconds;
|
double durationInSeconds;
|
||||||
|
@@ -18,6 +18,9 @@
|
|||||||
#include "catch_random_number_generator.h"
|
#include "catch_random_number_generator.h"
|
||||||
#include "catch_startup_exception_registry.h"
|
#include "catch_startup_exception_registry.h"
|
||||||
#include "catch_text.h"
|
#include "catch_text.h"
|
||||||
|
#include "catch_stream.h"
|
||||||
|
#include "catch_windows_h_proxy.h"
|
||||||
|
#include "../reporters/catch_reporter_listening.h"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@@ -34,33 +37,26 @@ namespace Catch {
|
|||||||
return reporter;
|
return reporter;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CATCH_CONFIG_DEFAULT_REPORTER
|
|
||||||
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {
|
IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {
|
||||||
auto const& reporterNames = config->getReporterNames();
|
if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {
|
||||||
if (reporterNames.empty())
|
return createReporter(config->getReporterName(), config);
|
||||||
return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config);
|
}
|
||||||
|
|
||||||
IStreamingReporterPtr reporter;
|
auto multi = std::unique_ptr<ListeningReporter>(new ListeningReporter);
|
||||||
for (auto const& name : reporterNames)
|
|
||||||
addReporter(reporter, createReporter(name, config));
|
|
||||||
return reporter;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef CATCH_CONFIG_DEFAULT_REPORTER
|
|
||||||
|
|
||||||
void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) {
|
|
||||||
auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
|
auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
|
||||||
for (auto const& listener : listeners)
|
for (auto const& listener : listeners) {
|
||||||
addReporter(reporters, listener->create(Catch::ReporterConfig(config)));
|
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) {
|
Catch::Totals runTests(std::shared_ptr<Config> const& config) {
|
||||||
IStreamingReporterPtr reporter = makeReporter(config);
|
// FixMe: Add listeners in order first, then add reporters.
|
||||||
addListeners(reporter, config);
|
|
||||||
|
auto reporter = makeReporter(config);
|
||||||
|
|
||||||
RunContext context(config, std::move(reporter));
|
RunContext context(config, std::move(reporter));
|
||||||
|
|
||||||
@@ -69,8 +65,6 @@ namespace Catch {
|
|||||||
context.testGroupStarting(config->name(), 1, 1);
|
context.testGroupStarting(config->name(), 1, 1);
|
||||||
|
|
||||||
TestSpec testSpec = config->testSpec();
|
TestSpec testSpec = config->testSpec();
|
||||||
if (!testSpec.hasFilters())
|
|
||||||
testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests
|
|
||||||
|
|
||||||
auto const& allTestCases = getAllTestCasesSorted(*config);
|
auto const& allTestCases = getAllTestCasesSorted(*config);
|
||||||
for (auto const& testCase : allTestCases) {
|
for (auto const& testCase : allTestCases) {
|
||||||
@@ -80,6 +74,20 @@ namespace Catch {
|
|||||||
context.reporter().skipTest(testCase);
|
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);
|
context.testGroupEnded(config->name(), totals, 1, 1);
|
||||||
return totals;
|
return totals;
|
||||||
}
|
}
|
||||||
@@ -119,7 +127,7 @@ namespace Catch {
|
|||||||
if ( !exceptions.empty() ) {
|
if ( !exceptions.empty() ) {
|
||||||
m_startupExceptions = true;
|
m_startupExceptions = true;
|
||||||
Colour colourGuard( Colour::Red );
|
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
|
// iterate over all exceptions and notify user
|
||||||
for ( const auto& ex_ptr : exceptions ) {
|
for ( const auto& ex_ptr : exceptions ) {
|
||||||
try {
|
try {
|
||||||
@@ -151,7 +159,7 @@ namespace Catch {
|
|||||||
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
|
<< 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 )
|
if( m_startupExceptions )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -188,7 +196,7 @@ namespace Catch {
|
|||||||
return returnCode;
|
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[] ) {
|
int Session::run( int argc, wchar_t* const argv[] ) {
|
||||||
|
|
||||||
char **utf8Argv = new char *[ argc ];
|
char **utf8Argv = new char *[ argc ];
|
||||||
@@ -259,7 +267,11 @@ namespace Catch {
|
|||||||
if( Option<std::size_t> listed = list( config() ) )
|
if( Option<std::size_t> listed = list( config() ) )
|
||||||
return static_cast<int>( *listed );
|
return static_cast<int>( *listed );
|
||||||
|
|
||||||
return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) );
|
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, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
|
||||||
}
|
}
|
||||||
catch( std::exception& ex ) {
|
catch( std::exception& ex ) {
|
||||||
Catch::cerr() << ex.what() << std::endl;
|
Catch::cerr() << ex.what() << std::endl;
|
||||||
|
@@ -25,12 +25,12 @@ namespace Catch {
|
|||||||
void showHelp() const;
|
void showHelp() const;
|
||||||
void libIdentify();
|
void libIdentify();
|
||||||
|
|
||||||
int applyCommandLine( int argc, char* argv[] );
|
int applyCommandLine( int argc, char const * const * argv );
|
||||||
|
|
||||||
void useConfigData( ConfigData const& configData );
|
void useConfigData( ConfigData const& configData );
|
||||||
|
|
||||||
int run( int argc, char* argv[] );
|
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[] );
|
int run( int argc, wchar_t* const argv[] );
|
||||||
#endif
|
#endif
|
||||||
int run();
|
int run();
|
||||||
|
@@ -14,6 +14,12 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
char toLowerCh(char c) {
|
||||||
|
return static_cast<char>( std::tolower( c ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool startsWith( std::string const& s, std::string const& prefix ) {
|
bool startsWith( std::string const& s, std::string const& prefix ) {
|
||||||
return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
|
return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
|
||||||
}
|
}
|
||||||
@@ -29,9 +35,6 @@ namespace Catch {
|
|||||||
bool contains( std::string const& s, std::string const& infix ) {
|
bool contains( std::string const& s, std::string const& infix ) {
|
||||||
return s.find( infix ) != std::string::npos;
|
return s.find( infix ) != std::string::npos;
|
||||||
}
|
}
|
||||||
char toLowerCh(char c) {
|
|
||||||
return static_cast<char>( std::tolower( c ) );
|
|
||||||
}
|
|
||||||
void toLowerInPlace( std::string& s ) {
|
void toLowerInPlace( std::string& s ) {
|
||||||
std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
|
std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,13 @@
|
|||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <cstring>
|
#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 {
|
namespace Catch {
|
||||||
StringRef::StringRef( char const* rawChars ) noexcept
|
StringRef::StringRef( char const* rawChars ) noexcept
|
||||||
@@ -36,7 +43,7 @@ namespace Catch {
|
|||||||
const_cast<StringRef*>( this )->takeOwnership();
|
const_cast<StringRef*>( this )->takeOwnership();
|
||||||
return m_start;
|
return m_start;
|
||||||
}
|
}
|
||||||
auto StringRef::data() const noexcept -> char const* {
|
auto StringRef::currentData() const noexcept -> char const* {
|
||||||
return m_start;
|
return m_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,13 +86,12 @@ namespace Catch {
|
|||||||
// Make adjustments for uft encodings
|
// Make adjustments for uft encodings
|
||||||
for( size_type i=0; i < m_size; ++i ) {
|
for( size_type i=0; i < m_size; ++i ) {
|
||||||
char c = m_start[i];
|
char c = m_start[i];
|
||||||
if( ( c & 0b11000000 ) == 0b11000000 ) {
|
if( ( c & byte_2_lead ) == byte_2_lead ) {
|
||||||
if( ( c & 0b11100000 ) == 0b11000000 )
|
noChars--;
|
||||||
|
if (( c & byte_3_lead ) == byte_3_lead )
|
||||||
|
noChars--;
|
||||||
|
if( ( c & byte_4_lead ) == byte_4_lead )
|
||||||
noChars--;
|
noChars--;
|
||||||
else if( ( c & 0b11110000 ) == 0b11100000 )
|
|
||||||
noChars-=2;
|
|
||||||
else if( ( c & 0b11111000 ) == 0b11110000 )
|
|
||||||
noChars-=3;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return noChars;
|
return noChars;
|
||||||
@@ -106,7 +112,12 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
|
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
|
} // namespace Catch
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
class StringData;
|
class StringData;
|
||||||
|
|
||||||
/// A non-owning string class (similar to the forthcoming std::string_view)
|
/// A non-owning string class (similar to the forthcoming std::string_view)
|
||||||
@@ -31,13 +31,13 @@ namespace Catch {
|
|||||||
|
|
||||||
char const* m_start;
|
char const* m_start;
|
||||||
size_type m_size;
|
size_type m_size;
|
||||||
|
|
||||||
char* m_data = nullptr;
|
char* m_data = nullptr;
|
||||||
|
|
||||||
void takeOwnership();
|
void takeOwnership();
|
||||||
|
|
||||||
static constexpr char const* const s_empty = "";
|
static constexpr char const* const s_empty = "";
|
||||||
|
|
||||||
public: // construction/ assignment
|
public: // construction/ assignment
|
||||||
StringRef() noexcept
|
StringRef() noexcept
|
||||||
: StringRef( s_empty, 0 )
|
: StringRef( s_empty, 0 )
|
||||||
@@ -83,13 +83,13 @@ namespace Catch {
|
|||||||
operator std::string() const;
|
operator std::string() const;
|
||||||
|
|
||||||
void swap( StringRef& other ) noexcept;
|
void swap( StringRef& other ) noexcept;
|
||||||
|
|
||||||
public: // operators
|
public: // operators
|
||||||
auto operator == ( StringRef const& other ) const noexcept -> bool;
|
auto operator == ( StringRef const& other ) const noexcept -> bool;
|
||||||
auto operator != ( StringRef const& other ) const noexcept -> bool;
|
auto operator != ( StringRef const& other ) const noexcept -> bool;
|
||||||
|
|
||||||
auto operator[] ( size_type index ) const noexcept -> char;
|
auto operator[] ( size_type index ) const noexcept -> char;
|
||||||
|
|
||||||
public: // named queries
|
public: // named queries
|
||||||
auto empty() const noexcept -> bool {
|
auto empty() const noexcept -> bool {
|
||||||
return m_size == 0;
|
return m_size == 0;
|
||||||
@@ -100,22 +100,27 @@ namespace Catch {
|
|||||||
|
|
||||||
auto numberOfCharacters() const noexcept -> size_type;
|
auto numberOfCharacters() const noexcept -> size_type;
|
||||||
auto c_str() const -> char const*;
|
auto c_str() const -> char const*;
|
||||||
|
|
||||||
public: // substrings and searches
|
public: // substrings and searches
|
||||||
auto substr( size_type start, size_type size ) const noexcept -> StringRef;
|
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
|
private: // ownership queries - may not be consistent between calls
|
||||||
auto isOwned() const noexcept -> bool;
|
auto isOwned() const noexcept -> bool;
|
||||||
auto isSubstring() 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, StringRef const& rhs ) -> std::string;
|
||||||
auto operator + ( StringRef const& lhs, char 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 + ( 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&;
|
auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
|
||||||
|
|
||||||
|
|
||||||
inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
|
inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
|
||||||
return StringRef( rawChars, size );
|
return StringRef( rawChars, size );
|
||||||
}
|
}
|
||||||
|
@@ -10,15 +10,17 @@
|
|||||||
# pragma warning(push)
|
# pragma warning(push)
|
||||||
# pragma warning(disable: 161 1682)
|
# pragma warning(disable: 161 1682)
|
||||||
# else // __ICC
|
# else // __ICC
|
||||||
# pragma clang diagnostic ignored "-Wunused-variable"
|
|
||||||
# pragma clang diagnostic push
|
# pragma clang diagnostic push
|
||||||
# pragma clang diagnostic ignored "-Wpadded"
|
# pragma clang diagnostic ignored "-Wpadded"
|
||||||
# pragma clang diagnostic ignored "-Wswitch-enum"
|
# pragma clang diagnostic ignored "-Wswitch-enum"
|
||||||
# pragma clang diagnostic ignored "-Wcovered-switch-default"
|
# pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||||
# endif
|
# endif
|
||||||
#elif defined __GNUC__
|
#elif defined __GNUC__
|
||||||
# pragma GCC diagnostic ignored "-Wunused-variable"
|
// GCC likes to warn on REQUIREs, and we cannot suppress them
|
||||||
|
// locally because g++'s support for _Pragma is lacking in older,
|
||||||
|
// still supported, versions
|
||||||
# pragma GCC diagnostic ignored "-Wparentheses"
|
# pragma GCC diagnostic ignored "-Wparentheses"
|
||||||
# pragma GCC diagnostic push
|
# pragma GCC diagnostic push
|
||||||
|
# pragma GCC diagnostic ignored "-Wunused-variable"
|
||||||
# pragma GCC diagnostic ignored "-Wpadded"
|
# pragma GCC diagnostic ignored "-Wpadded"
|
||||||
#endif
|
#endif
|
||||||
|
@@ -19,37 +19,38 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
|
namespace {
|
||||||
if( startsWith( tag, '.' ) ||
|
TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
|
||||||
tag == "!hide" )
|
if( startsWith( tag, '.' ) ||
|
||||||
return TestCaseInfo::IsHidden;
|
tag == "!hide" )
|
||||||
else if( tag == "!throws" )
|
return TestCaseInfo::IsHidden;
|
||||||
return TestCaseInfo::Throws;
|
else if( tag == "!throws" )
|
||||||
else if( tag == "!shouldfail" )
|
return TestCaseInfo::Throws;
|
||||||
return TestCaseInfo::ShouldFail;
|
else if( tag == "!shouldfail" )
|
||||||
else if( tag == "!mayfail" )
|
return TestCaseInfo::ShouldFail;
|
||||||
return TestCaseInfo::MayFail;
|
else if( tag == "!mayfail" )
|
||||||
else if( tag == "!nonportable" )
|
return TestCaseInfo::MayFail;
|
||||||
return TestCaseInfo::NonPortable;
|
else if( tag == "!nonportable" )
|
||||||
else if( tag == "!benchmark" )
|
return TestCaseInfo::NonPortable;
|
||||||
return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );
|
else if( tag == "!benchmark" )
|
||||||
else
|
return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );
|
||||||
return TestCaseInfo::None;
|
else
|
||||||
}
|
return TestCaseInfo::None;
|
||||||
bool isReservedTag( std::string const& tag ) {
|
}
|
||||||
return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
|
bool isReservedTag( std::string const& tag ) {
|
||||||
}
|
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),
|
void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
|
||||||
"Tag name: [" << tag << "] is not allowed.\n"
|
CATCH_ENFORCE( !isReservedTag(tag),
|
||||||
<< "Tag names starting with non alpha-numeric characters are reserved\n"
|
"Tag name: [" << tag << "] is not allowed.\n"
|
||||||
<< _lineInfo );
|
<< "Tag names starting with non alpha-numeric characters are reserved\n"
|
||||||
|
<< _lineInfo );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TestCase makeTestCase( ITestInvoker* _testCase,
|
TestCase makeTestCase( ITestInvoker* _testCase,
|
||||||
std::string const& _className,
|
std::string const& _className,
|
||||||
std::string const& _name,
|
NameAndTags const& nameAndTags,
|
||||||
std::string const& _descOrTags,
|
|
||||||
SourceLineInfo const& _lineInfo )
|
SourceLineInfo const& _lineInfo )
|
||||||
{
|
{
|
||||||
bool isHidden = false;
|
bool isHidden = false;
|
||||||
@@ -58,6 +59,7 @@ namespace Catch {
|
|||||||
std::vector<std::string> tags;
|
std::vector<std::string> tags;
|
||||||
std::string desc, tag;
|
std::string desc, tag;
|
||||||
bool inTag = false;
|
bool inTag = false;
|
||||||
|
std::string _descOrTags = nameAndTags.tags;
|
||||||
for (char c : _descOrTags) {
|
for (char c : _descOrTags) {
|
||||||
if( !inTag ) {
|
if( !inTag ) {
|
||||||
if( c == '[' )
|
if( c == '[' )
|
||||||
@@ -85,8 +87,8 @@ namespace Catch {
|
|||||||
tags.push_back( "." );
|
tags.push_back( "." );
|
||||||
}
|
}
|
||||||
|
|
||||||
TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
|
TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );
|
||||||
return TestCase( _testCase, info );
|
return TestCase( _testCase, std::move(info) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
|
void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
|
||||||
@@ -147,7 +149,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 {
|
TestCase TestCase::withName( std::string const& _newName ) const {
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
|
||||||
|
|
||||||
#include "catch_common.h"
|
#include "catch_common.h"
|
||||||
|
#include "catch_test_registry.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -61,7 +62,7 @@ namespace Catch {
|
|||||||
class TestCase : public TestCaseInfo {
|
class TestCase : public TestCaseInfo {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TestCase( ITestInvoker* testCase, TestCaseInfo const& info );
|
TestCase( ITestInvoker* testCase, TestCaseInfo&& info );
|
||||||
|
|
||||||
TestCase withName( std::string const& _newName ) const;
|
TestCase withName( std::string const& _newName ) const;
|
||||||
|
|
||||||
@@ -78,8 +79,7 @@ namespace Catch {
|
|||||||
|
|
||||||
TestCase makeTestCase( ITestInvoker* testCase,
|
TestCase makeTestCase( ITestInvoker* testCase,
|
||||||
std::string const& className,
|
std::string const& className,
|
||||||
std::string const& name,
|
NameAndTags const& nameAndTags,
|
||||||
std::string const& description,
|
|
||||||
SourceLineInfo const& lineInfo );
|
SourceLineInfo const& lineInfo );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,7 +28,7 @@ namespace Catch {
|
|||||||
break;
|
break;
|
||||||
case RunTests::InRandomOrder:
|
case RunTests::InRandomOrder:
|
||||||
seedRng( config );
|
seedRng( config );
|
||||||
RandomNumberGenerator::shuffle( sorted );
|
std::shuffle( sorted.begin(), sorted.end(), rng() );
|
||||||
break;
|
break;
|
||||||
case RunTests::InDeclarationOrder:
|
case RunTests::InDeclarationOrder:
|
||||||
// already in declaration order
|
// already in declaration order
|
||||||
@@ -96,7 +96,7 @@ namespace Catch {
|
|||||||
m_testAsFunction();
|
m_testAsFunction();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
|
std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
|
||||||
std::string className = classOrQualifiedMethodName;
|
std::string className = classOrQualifiedMethodName;
|
||||||
if( startsWith( className, '&' ) )
|
if( startsWith( className, '&' ) )
|
||||||
{
|
{
|
||||||
|
@@ -22,7 +22,7 @@ namespace Catch {
|
|||||||
class TestCase;
|
class TestCase;
|
||||||
struct IConfig;
|
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 );
|
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
|
||||||
|
|
||||||
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
|
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 "catch_enforce.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
#include <cassert>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -73,8 +73,8 @@ namespace TestCaseTracking {
|
|||||||
TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
|
TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
|
||||||
bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) const {
|
bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) const {
|
||||||
return
|
return
|
||||||
tracker->nameAndLocation().name == m_nameAndLocation.name &&
|
tracker->nameAndLocation().location == m_nameAndLocation.location &&
|
||||||
tracker->nameAndLocation().location == m_nameAndLocation.location;
|
tracker->nameAndLocation().name == m_nameAndLocation.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||||
|
@@ -15,23 +15,22 @@ namespace Catch {
|
|||||||
return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
|
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 {
|
try {
|
||||||
getMutableRegistryHub()
|
getMutableRegistryHub()
|
||||||
.registerTest(
|
.registerTest(
|
||||||
makeTestCase(
|
makeTestCase(
|
||||||
invoker,
|
invoker,
|
||||||
extractClassName( classOrMethod ),
|
extractClassName( classOrMethod ),
|
||||||
nameAndTags.name,
|
nameAndTags,
|
||||||
nameAndTags.tags,
|
|
||||||
lineInfo));
|
lineInfo));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// Do not throw when constructing global objects, instead register the exception to be processed later
|
// Do not throw when constructing global objects, instead register the exception to be processed later
|
||||||
getMutableRegistryHub().registerStartupException();
|
getMutableRegistryHub().registerStartupException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoReg::~AutoReg() = default;
|
AutoReg::~AutoReg() = default;
|
||||||
}
|
}
|
||||||
|
@@ -35,24 +35,29 @@ auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct NameAndTags {
|
struct NameAndTags {
|
||||||
NameAndTags( StringRef name_ = StringRef(), StringRef tags_ = StringRef() ) noexcept;
|
NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
|
||||||
StringRef name;
|
StringRef name;
|
||||||
StringRef tags;
|
StringRef tags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AutoReg : NonCopyable {
|
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();
|
~AutoReg();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace Catch
|
} // 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)
|
#if defined(CATCH_CONFIG_DISABLE)
|
||||||
#define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
|
#define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
|
||||||
static void TestName()
|
static void TestName()
|
||||||
#define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
|
#define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
|
||||||
namespace{ \
|
namespace{ \
|
||||||
struct TestName : ClassName { \
|
struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
|
||||||
void test(); \
|
void test(); \
|
||||||
}; \
|
}; \
|
||||||
} \
|
} \
|
||||||
@@ -64,7 +69,7 @@ struct AutoReg : NonCopyable {
|
|||||||
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
|
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
|
||||||
static void TestName(); \
|
static void TestName(); \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
|
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||||
static void TestName()
|
static void TestName()
|
||||||
#define INTERNAL_CATCH_TESTCASE( ... ) \
|
#define INTERNAL_CATCH_TESTCASE( ... ) \
|
||||||
@@ -80,7 +85,7 @@ struct AutoReg : NonCopyable {
|
|||||||
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
|
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
namespace{ \
|
namespace{ \
|
||||||
struct TestName : ClassName{ \
|
struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
|
||||||
void test(); \
|
void test(); \
|
||||||
}; \
|
}; \
|
||||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
||||||
@@ -93,7 +98,7 @@ struct AutoReg : NonCopyable {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
|
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
||||||
|
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user