mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-12 00:15:39 +02:00
Compare commits
275 Commits
v1.2.1-dev
...
v1.7.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7b8a27eadb | ||
![]() |
2b74613c54 | ||
![]() |
23600609c0 | ||
![]() |
4feb2dbb50 | ||
![]() |
84af6bc955 | ||
![]() |
197bf075c4 | ||
![]() |
1f5ec9884c | ||
![]() |
88b760276d | ||
![]() |
23eb4cc580 | ||
![]() |
a189387f49 | ||
![]() |
f65776890c | ||
![]() |
39753558eb | ||
![]() |
f126d7943a | ||
![]() |
cd489d9647 | ||
![]() |
e991c006b7 | ||
![]() |
7e7c813486 | ||
![]() |
712323ab7c | ||
![]() |
ce37f48ffa | ||
![]() |
090fc74cca | ||
![]() |
f58ff0c540 | ||
![]() |
a600bfeb75 | ||
![]() |
8cad76a749 | ||
![]() |
1a3f6d829b | ||
![]() |
b524fa7cd8 | ||
![]() |
5121b5b058 | ||
![]() |
1e5176bd69 | ||
![]() |
7dd4f2977a | ||
![]() |
50c95a0143 | ||
![]() |
0dabd951ba | ||
![]() |
7ae96c710b | ||
![]() |
70d3c937c3 | ||
![]() |
38af8d7035 | ||
![]() |
c97ada1910 | ||
![]() |
615aa071a8 | ||
![]() |
af0b03abd2 | ||
![]() |
15816c5760 | ||
![]() |
f11a45aa67 | ||
![]() |
bcaa2f9646 | ||
![]() |
efab3ca8b2 | ||
![]() |
60f8ebec49 | ||
![]() |
e1dbb7cf64 | ||
![]() |
02a69b449f | ||
![]() |
c390c4cb9f | ||
![]() |
60a9ac7e65 | ||
![]() |
c06afe438e | ||
![]() |
73872207db | ||
![]() |
51860f1568 | ||
![]() |
dab1d9d222 | ||
![]() |
4ce11d63a6 | ||
![]() |
99c2ea594c | ||
![]() |
51107d7cbd | ||
![]() |
83f4b39680 | ||
![]() |
b1171bd1f2 | ||
![]() |
6c23a6582b | ||
![]() |
7bcb42496d | ||
![]() |
184865358c | ||
![]() |
225e90d8ba | ||
![]() |
31c23b9489 | ||
![]() |
f347611403 | ||
![]() |
1efd8d3067 | ||
![]() |
876af874f3 | ||
![]() |
e7bcbb35c0 | ||
![]() |
4a04682e49 | ||
![]() |
9a56609569 | ||
![]() |
81159838a5 | ||
![]() |
78a2866dc7 | ||
![]() |
9acc6b9673 | ||
![]() |
c4b5057094 | ||
![]() |
d38b9266e7 | ||
![]() |
227598af47 | ||
![]() |
cfaf906417 | ||
![]() |
ee0ca512ea | ||
![]() |
b71a06cf98 | ||
![]() |
531d26739f | ||
![]() |
2e87f8e328 | ||
![]() |
afe46ff270 | ||
![]() |
c65aeaf25f | ||
![]() |
750b52b814 | ||
![]() |
e12fc4aca0 | ||
![]() |
99cdc62fef | ||
![]() |
e6ef60a2c4 | ||
![]() |
e1c4a4bd9b | ||
![]() |
25d017763b | ||
![]() |
b634e592da | ||
![]() |
3b98a0166f | ||
![]() |
877fd523bc | ||
![]() |
a1e9b841ff | ||
![]() |
3b7511e564 | ||
![]() |
ffc4a9dc14 | ||
![]() |
7c8b93eac3 | ||
![]() |
e3659cdddd | ||
![]() |
40dbdf6cb2 | ||
![]() |
70f43d719b | ||
![]() |
a281173099 | ||
![]() |
b3907a78e1 | ||
![]() |
d5360e8e29 | ||
![]() |
9062ebe390 | ||
![]() |
e6aa1f4e4e | ||
![]() |
1ff0acfe22 | ||
![]() |
713ec400e8 | ||
![]() |
3b2f206191 | ||
![]() |
4e4d733f90 | ||
![]() |
b68e8f9a24 | ||
![]() |
a7cda91d4d | ||
![]() |
a1bed572be | ||
![]() |
737f4ea77c | ||
![]() |
b0de6c938a | ||
![]() |
6991549457 | ||
![]() |
b50572bbfd | ||
![]() |
5b00fd40ba | ||
![]() |
7bb3e859aa | ||
![]() |
0bcae64d3d | ||
![]() |
8abe17a393 | ||
![]() |
10c44847f4 | ||
![]() |
0cde0e90a6 | ||
![]() |
0f0dcd31eb | ||
![]() |
62cbde369e | ||
![]() |
1ae84897d4 | ||
![]() |
976a655496 | ||
![]() |
37e1e24309 | ||
![]() |
5a4dde4b5d | ||
![]() |
8d326424f3 | ||
![]() |
ccc34b63b6 | ||
![]() |
7255be28cc | ||
![]() |
7d2668fa15 | ||
![]() |
2a4dba177f | ||
![]() |
8d1e240700 | ||
![]() |
e273a3dc88 | ||
![]() |
7bff9cb451 | ||
![]() |
fd1da4a1d1 | ||
![]() |
e1fbbe1590 | ||
![]() |
c8fefc4670 | ||
![]() |
64193078bc | ||
![]() |
8d16d95a99 | ||
![]() |
2be372710e | ||
![]() |
0c093bee38 | ||
![]() |
dedc7c56ce | ||
![]() |
a9561ecb31 | ||
![]() |
e4df006568 | ||
![]() |
fb99cc556d | ||
![]() |
862d13138c | ||
![]() |
79acc0504b | ||
![]() |
f9afa2a68d | ||
![]() |
0c8c6b347a | ||
![]() |
40b6ad73df | ||
![]() |
30cebd6177 | ||
![]() |
e27c4ee042 | ||
![]() |
072114293b | ||
![]() |
f90ee9fb37 | ||
![]() |
c17ba0870a | ||
![]() |
79f01100e3 | ||
![]() |
ccf7f2842a | ||
![]() |
e0302db4a6 | ||
![]() |
88732e85b2 | ||
![]() |
1c9a6cab88 | ||
![]() |
40f6068d52 | ||
![]() |
21cbfc107e | ||
![]() |
31861bbd46 | ||
![]() |
b1eeec7c69 | ||
![]() |
c23b374f3d | ||
![]() |
916317bd81 | ||
![]() |
8c459dd207 | ||
![]() |
fd7d35464b | ||
![]() |
c47c1797d2 | ||
![]() |
f5d2b2dce8 | ||
![]() |
02c7e41c7c | ||
![]() |
5095619955 | ||
![]() |
35f510545d | ||
![]() |
742457cbcf | ||
![]() |
1aa6c91e64 | ||
![]() |
ac220289a6 | ||
![]() |
be3570ef22 | ||
![]() |
a74d760d74 | ||
![]() |
f666f5f0ae | ||
![]() |
7940d58a2f | ||
![]() |
ebf9f3bb9d | ||
![]() |
1ebebd4ab8 | ||
![]() |
b57e734eb4 | ||
![]() |
5aa2b82b17 | ||
![]() |
5c198d85e6 | ||
![]() |
5a6b291878 | ||
![]() |
1706dd4f11 | ||
![]() |
92b141ee53 | ||
![]() |
4f1263d6b4 | ||
![]() |
3b19458fed | ||
![]() |
e5537842d0 | ||
![]() |
0fe303b6b7 | ||
![]() |
1c47fe023a | ||
![]() |
6f3bc629be | ||
![]() |
6de7142d1f | ||
![]() |
7544644bb4 | ||
![]() |
86c0ea2999 | ||
![]() |
7075b7defb | ||
![]() |
c984fc3ecd | ||
![]() |
447f53e9e3 | ||
![]() |
13a887ad24 | ||
![]() |
02af70ed0b | ||
![]() |
c362894565 | ||
![]() |
97e335437e | ||
![]() |
ae5ee2cf63 | ||
![]() |
f895e0d95f | ||
![]() |
458f37ed57 | ||
![]() |
91bfe68a75 | ||
![]() |
8ccb18daa9 | ||
![]() |
dce2154474 | ||
![]() |
e52ad48fb7 | ||
![]() |
776247af81 | ||
![]() |
3b4edd7a48 | ||
![]() |
880a2046d9 | ||
![]() |
ffad3a0a39 | ||
![]() |
3bd20bf2cd | ||
![]() |
c7243562b0 | ||
![]() |
b84e08ad6f | ||
![]() |
aca16a0f99 | ||
![]() |
f294c98472 | ||
![]() |
7424b23bfb | ||
![]() |
dbd3a84d92 | ||
![]() |
5262e61e9d | ||
![]() |
a5fba672e1 | ||
![]() |
2106d82881 | ||
![]() |
981347b6e4 | ||
![]() |
9e341231ba | ||
![]() |
2b688e1cef | ||
![]() |
84d1c080d6 | ||
![]() |
722315a1f5 | ||
![]() |
fdc42d0af4 | ||
![]() |
d274fc571c | ||
![]() |
7e15d9b20b | ||
![]() |
0e64973f55 | ||
![]() |
e4fa62a14e | ||
![]() |
a49f088032 | ||
![]() |
ed6e9128a4 | ||
![]() |
92356769f1 | ||
![]() |
d10b73f9f1 | ||
![]() |
71fd2c2fdf | ||
![]() |
08844e7e57 | ||
![]() |
054e3c5b43 | ||
![]() |
f3e7722cc6 | ||
![]() |
315c83ad87 | ||
![]() |
9576ad9108 | ||
![]() |
e91738103c | ||
![]() |
8c32b49d5f | ||
![]() |
ece529ae7c | ||
![]() |
9e42153fe5 | ||
![]() |
c81778ecd0 | ||
![]() |
f5642be7b4 | ||
![]() |
7e34619f03 | ||
![]() |
4636be9744 | ||
![]() |
015e07100e | ||
![]() |
bc8840cbb8 | ||
![]() |
471bd2556a | ||
![]() |
aa49823bc0 | ||
![]() |
52a417df7b | ||
![]() |
0b523db6b9 | ||
![]() |
b8515929b8 | ||
![]() |
3deb3e010f | ||
![]() |
73a140fb9e | ||
![]() |
ef62b578e2 | ||
![]() |
f4389b4fdb | ||
![]() |
4b99be6a9a | ||
![]() |
293e54dcbe | ||
![]() |
d758428fe2 | ||
![]() |
9a6a0865f2 | ||
![]() |
2c6411e70a | ||
![]() |
1cb993970a | ||
![]() |
bc00d59a4e | ||
![]() |
b3b2352045 | ||
![]() |
c9a188df45 | ||
![]() |
e904aa7f6e | ||
![]() |
d43a47efca | ||
![]() |
a0de07d45b | ||
![]() |
15317632f3 | ||
![]() |
a28d40e941 | ||
![]() |
7da777a4b7 | ||
![]() |
1dd0d4c61a |
29
.github/issue_template.md
vendored
Normal file
29
.github/issue_template.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
## Description
|
||||
<!--
|
||||
If your issue is a bugreport, this means describing what you did,
|
||||
what did you want to happen and what actually did happen.
|
||||
|
||||
If your issue is a feature request, describe the feature and why do you
|
||||
want it.
|
||||
-->
|
||||
|
||||
|
||||
### Steps to reproduce
|
||||
<!--
|
||||
This is only relevant for bug reports, but if you do have one,
|
||||
please provide a minimal set of steps to reproduce the problem.
|
||||
|
||||
Usually this means providing a small and self-contained code using Catch
|
||||
and specifying compiler flags/tools used if relevant.
|
||||
-->
|
||||
|
||||
|
||||
### Extra information
|
||||
<!--
|
||||
Fill in any extra information that might be important for your issue.
|
||||
|
||||
If your issue is a bugreport, definitely fill out at least the following.
|
||||
-->
|
||||
* Catch version: **v42.42.42**
|
||||
* Operating System: **Joe's discount operating system**
|
||||
* Compiler+version: **Hidden Dragon v1.2.3**
|
25
.github/pull_request_template.md
vendored
Normal file
25
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Please do not submit pull requests changing the `version.hpp`
|
||||
or the single-include `catch.hpp` file, these are changed
|
||||
only when a new release is made.
|
||||
-->
|
||||
|
||||
|
||||
## Description
|
||||
<!--
|
||||
Describe the what and the why of your pull request. Remember that these two
|
||||
are usually a bit different. As an example, if you have made various changes
|
||||
to decrease the number of new strings allocated, thats what. The why probably
|
||||
was that you have a large set of tests and found that this speeds them up.
|
||||
-->
|
||||
|
||||
## GitHub Issues
|
||||
<!--
|
||||
If this PR was motivated by some existing issues, reference them here.
|
||||
|
||||
If it is a simple bug-fix, please also add a line like 'Closes #123'
|
||||
to your commit message, so that it is automatically closed.
|
||||
If it is not, don't, as it might take several iterations for a feature
|
||||
to be done properly. If in doubt, leave it open and reference it in the
|
||||
PR itself, so that maintainers can decide.
|
||||
-->
|
8
.gitignore
vendored
8
.gitignore
vendored
@@ -14,9 +14,15 @@ Breakpoints.xcbkptlist
|
||||
projects/VS2010/TestCatch/_UpgradeReport_Files/
|
||||
projects/VS2010/TestCatch/TestCatch/TestCatch.vcxproj.filters
|
||||
projects/VisualStudio/TestCatch/UpgradeLog.XML
|
||||
projects/CMake/.idea
|
||||
projects/CMake/cmake-build-debug
|
||||
UpgradeLog.XML
|
||||
Resources/DWARF
|
||||
projects/XCode/iOSTest/Build
|
||||
projects/Generated
|
||||
*.pyc
|
||||
DerivedData
|
||||
*.xccheckout
|
||||
Build
|
||||
.idea
|
||||
cmake-build-debug
|
||||
cmake-build-release
|
||||
|
164
.travis.yml
164
.travis.yml
@@ -1,19 +1,163 @@
|
||||
language: cpp
|
||||
sudo: false
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
cache:
|
||||
ccache: true
|
||||
directories:
|
||||
- $HOME/.ccache
|
||||
|
||||
env:
|
||||
- BUILD_TYPE=Debug
|
||||
- BUILD_TYPE=Release
|
||||
global:
|
||||
- USE_CCACHE=1
|
||||
- CCACHE_COMPRESS=1
|
||||
- CCACHE_MAXSIZE=200M
|
||||
- CCACHE_CPP2=1
|
||||
|
||||
|
||||
matrix:
|
||||
include:
|
||||
|
||||
# 1/ Linux Clang Builds
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons: &clang35
|
||||
apt:
|
||||
sources: ['llvm-toolchain-precise-3.5', 'ubuntu-toolchain-r-test']
|
||||
packages: ['clang-3.5']
|
||||
env: COMPILER='ccache clang++-3.5' BUILD_TYPE='Release'
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons: *clang35
|
||||
env: COMPILER='ccache clang++-3.5' BUILD_TYPE='Debug'
|
||||
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons: &clang36
|
||||
apt:
|
||||
sources: ['llvm-toolchain-precise-3.6', 'ubuntu-toolchain-r-test']
|
||||
packages: ['clang-3.6']
|
||||
env: COMPILER='ccache clang++-3.6' BUILD_TYPE='Release'
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons: *clang36
|
||||
env: COMPILER='ccache clang++-3.6' BUILD_TYPE='Debug'
|
||||
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons: &clang37
|
||||
apt:
|
||||
sources: ['llvm-toolchain-precise-3.7', 'ubuntu-toolchain-r-test']
|
||||
packages: ['clang-3.7']
|
||||
env: COMPILER='ccache clang++-3.7' BUILD_TYPE='Release'
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons: *clang37
|
||||
env: COMPILER='ccache clang++-3.7' BUILD_TYPE='Debug'
|
||||
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons: &clang38
|
||||
apt:
|
||||
sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
|
||||
packages: ['clang-3.8']
|
||||
env: COMPILER='ccache clang++-3.8' BUILD_TYPE='Release'
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons: *clang38
|
||||
env: COMPILER='ccache clang++-3.8' BUILD_TYPE='Debug'
|
||||
|
||||
|
||||
# 2/ Linux GCC Builds
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: &gcc48
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.8']
|
||||
env: COMPILER='ccache g++-4.8' BUILD_TYPE='Release'
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: *gcc48
|
||||
env: COMPILER='ccache g++-4.8' BUILD_TYPE='Debug'
|
||||
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: &gcc49
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.9']
|
||||
env: COMPILER='ccache g++-4.9' BUILD_TYPE='Release'
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: *gcc49
|
||||
env: COMPILER='ccache g++-4.9' BUILD_TYPE='Debug'
|
||||
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: &gcc5
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5']
|
||||
env: COMPILER='ccache g++-5' BUILD_TYPE='Release'
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: *gcc5
|
||||
env: COMPILER='ccache g++-5' BUILD_TYPE='Debug'
|
||||
|
||||
|
||||
# 3/ OSX Clang Builds
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: COMPILER='ccache clang++' BUILD_TYPE='Debug'
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: COMPILER='ccache clang++' BUILD_TYPE='Release'
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8
|
||||
compiler: clang
|
||||
env: COMPILER='ccache clang++' BUILD_TYPE='Debug'
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8
|
||||
compiler: clang
|
||||
env: COMPILER='ccache clang++' BUILD_TYPE='Release'
|
||||
|
||||
|
||||
install:
|
||||
- cmake -Hprojects/CMake -BBuild -DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
CMAKE_URL="http://www.cmake.org/files/v3.3/cmake-3.3.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
|
||||
export PATH=${DEPS_DIR}/cmake/bin:${PATH}
|
||||
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||
which cmake || brew install cmake
|
||||
which ccache || brew install ccache
|
||||
fi
|
||||
|
||||
before_script:
|
||||
- export CXX=${COMPILER}
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
- cmake -H. -BBuild -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -Wdev
|
||||
- cd Build
|
||||
- make
|
||||
- cd ..
|
||||
|
||||
script:
|
||||
- cd Build
|
||||
- ctest -V
|
||||
- make -j 2
|
||||
- ctest -V -j 2
|
||||
|
262
CMakeLists.txt
Normal file
262
CMakeLists.txt
Normal file
@@ -0,0 +1,262 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(CatchSelfTest)
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
# define some folders
|
||||
set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
|
||||
set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark)
|
||||
set(HEADER_DIR ${CATCH_DIR}/include)
|
||||
|
||||
if(USE_CPP11)
|
||||
## We can't turn this on by default, since it breaks on travis
|
||||
message(STATUS "Enabling C++11")
|
||||
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
|
||||
elseif(USE_CPP14)
|
||||
message(STATUS "Enabling C++14")
|
||||
set(CMAKE_CXX_FLAGS "-std=c++14 ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
#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()
|
||||
|
||||
# define the sources of the self test
|
||||
# Please keep these ordered alphabetically
|
||||
set(TEST_SOURCES
|
||||
${SELF_TEST_DIR}/ApproxTests.cpp
|
||||
${SELF_TEST_DIR}/BDDTests.cpp
|
||||
${SELF_TEST_DIR}/ClassTests.cpp
|
||||
${SELF_TEST_DIR}/CmdLineTests.cpp
|
||||
${SELF_TEST_DIR}/ConditionTests.cpp
|
||||
${SELF_TEST_DIR}/EnumToString.cpp
|
||||
${SELF_TEST_DIR}/ExceptionTests.cpp
|
||||
${SELF_TEST_DIR}/GeneratorTests.cpp
|
||||
${SELF_TEST_DIR}/MessageTests.cpp
|
||||
${SELF_TEST_DIR}/MiscTests.cpp
|
||||
${SELF_TEST_DIR}/PartTrackerTests.cpp
|
||||
${SELF_TEST_DIR}/TagAliasTests.cpp
|
||||
${SELF_TEST_DIR}/TestMain.cpp
|
||||
${SELF_TEST_DIR}/ToStringPair.cpp
|
||||
${SELF_TEST_DIR}/ToStringTuple.cpp
|
||||
${SELF_TEST_DIR}/ToStringVector.cpp
|
||||
${SELF_TEST_DIR}/ToStringWhich.cpp
|
||||
${SELF_TEST_DIR}/TrickyTests.cpp
|
||||
${SELF_TEST_DIR}/VariadicMacrosTests.cpp
|
||||
)
|
||||
CheckFileList(TEST_SOURCES ${SELF_TEST_DIR})
|
||||
|
||||
# A set of impl files that just #include a single header
|
||||
# Please keep these ordered alphabetically
|
||||
set(IMPL_SOURCES
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_common.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_capture.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_config.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_exception.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_generators.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_registry_hub.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_runner.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_testcase.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_message.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_ptr.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_streambuf.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp
|
||||
)
|
||||
CheckFileList(IMPL_SOURCES ${SELF_TEST_DIR}/SurrogateCpps)
|
||||
|
||||
|
||||
# Please keep these ordered alphabetically
|
||||
set(TOP_LEVEL_HEADERS
|
||||
${HEADER_DIR}/catch.hpp
|
||||
${HEADER_DIR}/catch_session.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.h
|
||||
${HEADER_DIR}/external/tbc_text_format.h
|
||||
)
|
||||
CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external)
|
||||
|
||||
|
||||
# Please keep these ordered alphabetically
|
||||
set(INTERNAL_HEADERS
|
||||
${HEADER_DIR}/internal/catch_approx.hpp
|
||||
${HEADER_DIR}/internal/catch_assertionresult.h
|
||||
${HEADER_DIR}/internal/catch_assertionresult.hpp
|
||||
${HEADER_DIR}/internal/catch_capture.hpp
|
||||
${HEADER_DIR}/internal/catch_clara.h
|
||||
${HEADER_DIR}/internal/catch_commandline.hpp
|
||||
${HEADER_DIR}/internal/catch_common.h
|
||||
${HEADER_DIR}/internal/catch_common.hpp
|
||||
${HEADER_DIR}/internal/catch_compiler_capabilities.h
|
||||
${HEADER_DIR}/internal/catch_config.hpp
|
||||
${HEADER_DIR}/internal/catch_console_colour.hpp
|
||||
${HEADER_DIR}/internal/catch_console_colour_impl.hpp
|
||||
${HEADER_DIR}/internal/catch_context.h
|
||||
${HEADER_DIR}/internal/catch_context_impl.hpp
|
||||
${HEADER_DIR}/internal/catch_debugger.h
|
||||
${HEADER_DIR}/internal/catch_debugger.hpp
|
||||
${HEADER_DIR}/internal/catch_default_main.hpp
|
||||
${HEADER_DIR}/internal/catch_evaluate.hpp
|
||||
${HEADER_DIR}/internal/catch_exception_translator_registry.hpp
|
||||
${HEADER_DIR}/internal/catch_expression_lhs.hpp
|
||||
${HEADER_DIR}/internal/catch_fatal_condition.hpp
|
||||
${HEADER_DIR}/internal/catch_generators.hpp
|
||||
${HEADER_DIR}/internal/catch_generators_impl.hpp
|
||||
${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_generators.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_legacy_reporter_adapter.h
|
||||
${HEADER_DIR}/internal/catch_legacy_reporter_adapter.hpp
|
||||
${HEADER_DIR}/internal/catch_list.hpp
|
||||
${HEADER_DIR}/internal/catch_matchers.hpp
|
||||
${HEADER_DIR}/internal/catch_message.h
|
||||
${HEADER_DIR}/internal/catch_message.hpp
|
||||
${HEADER_DIR}/internal/catch_notimplemented_exception.h
|
||||
${HEADER_DIR}/internal/catch_notimplemented_exception.hpp
|
||||
${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_ptr.hpp
|
||||
${HEADER_DIR}/internal/catch_reenable_warnings.h
|
||||
${HEADER_DIR}/internal/catch_registry_hub.hpp
|
||||
${HEADER_DIR}/internal/catch_reporter_registrars.hpp
|
||||
${HEADER_DIR}/internal/catch_reporter_registry.hpp
|
||||
${HEADER_DIR}/internal/catch_result_builder.h
|
||||
${HEADER_DIR}/internal/catch_result_builder.hpp
|
||||
${HEADER_DIR}/internal/catch_result_type.h
|
||||
${HEADER_DIR}/internal/catch_run_context.hpp
|
||||
${HEADER_DIR}/internal/catch_section.h
|
||||
${HEADER_DIR}/internal/catch_section.hpp
|
||||
${HEADER_DIR}/internal/catch_section_info.h
|
||||
${HEADER_DIR}/internal/catch_section_info.hpp
|
||||
${HEADER_DIR}/internal/catch_stream.h
|
||||
${HEADER_DIR}/internal/catch_stream.hpp
|
||||
${HEADER_DIR}/internal/catch_streambuf.h
|
||||
${HEADER_DIR}/internal/catch_suppress_warnings.h
|
||||
${HEADER_DIR}/internal/catch_tag_alias.h
|
||||
${HEADER_DIR}/internal/catch_tag_alias_registry.h
|
||||
${HEADER_DIR}/internal/catch_tag_alias_registry.hpp
|
||||
${HEADER_DIR}/internal/catch_test_case_info.h
|
||||
${HEADER_DIR}/internal/catch_test_case_info.hpp
|
||||
${HEADER_DIR}/internal/catch_test_case_registry_impl.hpp
|
||||
${HEADER_DIR}/internal/catch_test_case_tracker.hpp
|
||||
${HEADER_DIR}/internal/catch_test_registry.hpp
|
||||
${HEADER_DIR}/internal/catch_test_spec.hpp
|
||||
${HEADER_DIR}/internal/catch_test_spec_parser.hpp
|
||||
${HEADER_DIR}/internal/catch_text.h
|
||||
${HEADER_DIR}/internal/catch_timer.h
|
||||
${HEADER_DIR}/internal/catch_timer.hpp
|
||||
${HEADER_DIR}/internal/catch_tostring.h
|
||||
${HEADER_DIR}/internal/catch_tostring.hpp
|
||||
${HEADER_DIR}/internal/catch_totals.hpp
|
||||
${HEADER_DIR}/internal/catch_version.h
|
||||
${HEADER_DIR}/internal/catch_version.hpp
|
||||
${HEADER_DIR}/internal/catch_wildcard_pattern.hpp
|
||||
${HEADER_DIR}/internal/catch_windows_h_proxy.h
|
||||
${HEADER_DIR}/internal/catch_xmlwriter.hpp
|
||||
)
|
||||
CheckFileList(INTERNAL_HEADERS ${HEADER_DIR}/internal)
|
||||
|
||||
# Please keep these ordered alphabetically
|
||||
set(REPORTER_HEADERS
|
||||
${HEADER_DIR}/reporters/catch_reporter_bases.hpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_compact.hpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_console.hpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_junit.hpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_multi.hpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp
|
||||
${HEADER_DIR}/reporters/catch_reporter_xml.hpp
|
||||
)
|
||||
CheckFileList(REPORTER_HEADERS ${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}
|
||||
)
|
||||
|
||||
|
||||
set(BENCH_SOURCES
|
||||
${BENCHMARK_DIR}/BenchMain.cpp
|
||||
${BENCHMARK_DIR}/StringificationBench.cpp
|
||||
)
|
||||
CheckFileList(BENCH_SOURCES ${BENCHMARK_DIR})
|
||||
|
||||
# Provide some groupings for IDEs
|
||||
SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
|
||||
SOURCE_GROUP("Surrogates" FILES ${IMPL_SOURCES})
|
||||
SOURCE_GROUP("Benchmarks" FILES ${BENCH_SOURCES})
|
||||
|
||||
# configure the executable
|
||||
include_directories(${HEADER_DIR})
|
||||
add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${HEADERS})
|
||||
add_executable(Benchmark ${BENCH_SOURCES} ${HEADERS})
|
||||
|
||||
# Add desired warnings
|
||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
|
||||
target_compile_options( SelfTest PRIVATE -Wall -Wextra )
|
||||
target_compile_options( Benchmark PRIVATE -Wall -Wextra )
|
||||
endif()
|
||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
|
||||
target_compile_options( SelfTest PRIVATE /W4 )
|
||||
target_compile_options( Benchmark PRIVATE /W4 )
|
||||
endif()
|
||||
|
||||
|
||||
# configure unit tests via CTest
|
||||
enable_testing()
|
||||
add_test(NAME RunTests COMMAND SelfTest)
|
||||
|
||||
add_test(NAME ListTests COMMAND SelfTest --list-tests)
|
||||
set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases")
|
||||
|
||||
add_test(NAME ListTags COMMAND SelfTest --list-tags)
|
||||
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
|
||||
|
||||
install(DIRECTORY "single_include/" DESTINATION "include/catch/")
|
10
README.md
10
README.md
@@ -1,12 +1,10 @@
|
||||

|
||||
|
||||
*v1.2.1-develop.14*
|
||||
*v1.7.1*
|
||||
|
||||
Build status (on Travis CI) [](https://travis-ci.org/philsquared/Catch)
|
||||
Build status (on Travis CI) [](https://travis-ci.org/philsquared/Catch)
|
||||
|
||||
[Please see this page if you are updating from a version before 1.0](docs/whats-changed.md)
|
||||
|
||||
<a href="https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp">[The latest, single header, version can be downloaded directly using this link]</a>
|
||||
<a href="https://github.com/philsquared/Catch/releases/download/v1.7.1/catch.hpp">The latest, single header, version can be downloaded directly using this link</a>
|
||||
|
||||
## What's the Catch?
|
||||
|
||||
@@ -19,8 +17,6 @@ This documentation comprises these three parts:
|
||||
* [Tutorial](docs/tutorial.md) - getting started
|
||||
* [Reference section](docs/Readme.md) - all the details
|
||||
|
||||
The documentation will continue until morale improves
|
||||
|
||||
## More
|
||||
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/philsquared/Catch/issues)
|
||||
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)
|
||||
|
BIN
catch-logo-tiny.png
Normal file
BIN
catch-logo-tiny.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
@@ -12,9 +12,10 @@ Before looking at this material be sure to read the [tutorial](tutorial.md)
|
||||
* [Configuration](configuration.md)
|
||||
* [String Conversions](tostring.md)
|
||||
* [Why are my tests slow to compile?](slow-compiles.md)
|
||||
* [Known limitations](limitations.md)
|
||||
|
||||
Other
|
||||
|
||||
* [Why Catch?](why-catch.md)
|
||||
* [What's changed](whats-changed.md)
|
||||
* [Contributing](contributing.md)
|
||||
* [Release Notes](release-notes.md)
|
@@ -34,6 +34,15 @@ Example:
|
||||
REQUIRE_FALSE( thisReturnsFalse() );
|
||||
```
|
||||
|
||||
Do note that "overly complex" expressions cannot be decomposed and thus will not compile. This is done partly for practical reasons (to keep the underlying expression template machinery to minimum) and partly for philosophical reasons (assertions should be simple and deterministic).
|
||||
|
||||
Examples:
|
||||
* `CHECK(a == 1 && b == 2);`
|
||||
This expression is too complex because of the `&&` operator. If you want to check that 2 or more properties hold, you can either put the expression into parenthesis, which stops decomposition from working, or you need to decompose the expression into two assertions: `CHECK( a == 1 ); CHECK( b == 2);`
|
||||
* `CHECK( a == 2 || b == 1 );`
|
||||
This expression is too complex because of the `||` operator. If you want to check that one of several properties hold, you can put the expression into parenthesis (unlike with `&&`, expression decomposition into several `CHECK`s is not possible).
|
||||
|
||||
|
||||
### Floating point comparisons
|
||||
|
||||
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.
|
||||
@@ -69,6 +78,20 @@ Expects that an exception of the _specified type_ is thrown during evaluation of
|
||||
|
||||
Expects that no exception is thrown during evaluation of the expression.
|
||||
|
||||
|
||||
Please note that the `THROW` family of assertions expects to be passed a single expression, not a statement or series of statements. If you want to check a more complicated sequence of operations, you can use a C++11 lambda function.
|
||||
|
||||
```cpp
|
||||
REQUIRE_NOTHROW([&](){
|
||||
int i = 1;
|
||||
int j = 2;
|
||||
auto k = i + j;
|
||||
if (k == 3) {
|
||||
throw 1;
|
||||
}
|
||||
}());
|
||||
```
|
||||
|
||||
## Matcher expressions
|
||||
|
||||
To support Matchers a slightly different form is used. Matchers will be more fully documented elsewhere. *Note that Matchers are still at early stage development and are subject to change.*
|
||||
|
@@ -69,7 +69,7 @@ ExternalProject_Add(
|
||||
|
||||
# Expose required variable (CATCH_INCLUDE_DIR) to parent scope
|
||||
ExternalProject_Get_Property(catch source_dir)
|
||||
set(CATCH_INCLUDE_DIR ${source_dir}/include CACHE INTERNAL "Path to include folder for Catch")
|
||||
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:
|
||||
|
@@ -17,6 +17,9 @@ Click one of the followings links to take you straight to that option - or scrol
|
||||
<a href="#warnings"> ` -w, --warn`</a><br />
|
||||
<a href="#reporting-timings"> ` -d, --durations`</a><br />
|
||||
<a href="#input-file"> ` -f, --input-file`</a><br />
|
||||
<a href="#run-section"> ` -c, --section`</a><br />
|
||||
<a href="#filenames-as-tags"> ` -#, --filenames-as-tags`</a><br />
|
||||
|
||||
|
||||
</br>
|
||||
|
||||
@@ -66,6 +69,8 @@ A series of tags form an AND expression wheras a comma-separated sequence forms
|
||||
<pre>[one][two],[three]</pre>
|
||||
This matches all tests tagged `[one]` and `[two]`, as well as all tests tagged `[three]`
|
||||
|
||||
Test names containing special characters, such as `,` or `[` can specify them on the command line using `\`.
|
||||
`\` also escapes itself.
|
||||
|
||||
<a id="choosing-a-reporter-to-use"></a>
|
||||
## Choosing a reporter to use
|
||||
@@ -115,7 +120,7 @@ Sometimes this results in a flood of failure messages and you'd rather just see
|
||||
--list-reporters
|
||||
</pre>
|
||||
|
||||
```-l``` or ```--list-tests`` will list all registered tests, along with any tags.
|
||||
```-l``` or ```--list-tests``` will list all registered tests, along with any tags.
|
||||
If one or more test-specs have been supplied too then only the matching tests will be listed.
|
||||
|
||||
```-t``` or ```--list-tags``` lists all available tags, along with the number of test cases they match. Again, supplying test specs limits the tags that match.
|
||||
@@ -215,6 +220,59 @@ In either case the actual value for the seed is printed as part of Catch's outpu
|
||||
|
||||
Prints the command line arguments to stdout
|
||||
|
||||
|
||||
<a id="run-section"></a>
|
||||
## Specify the section to run
|
||||
<pre>-s, --section <section name></pre>
|
||||
|
||||
To limit execution to a specific section within a test case, use this option one or more times.
|
||||
To narrow to sub-sections use multiple instances, where each subsequent instance specifies a deeper nesting level.
|
||||
|
||||
E.g. if you have:
|
||||
|
||||
<pre>
|
||||
TEST_CASE( "Test" ) {
|
||||
SECTION( "sa" ) {
|
||||
SECTION( "sb" ) {
|
||||
/*...*/
|
||||
}
|
||||
SECTION( "sc" ) {
|
||||
/*...*/
|
||||
}
|
||||
}
|
||||
SECTION( "sd" ) {
|
||||
/*...*/
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
Then you can run `sb` with:
|
||||
<pre>./MyExe Test -c sa -c sb</pre>
|
||||
|
||||
Or run just `sd` with:
|
||||
<pre>./MyExe Test -c sd</pre>
|
||||
|
||||
To run all of `sa`, including `sb` and `sc` use:
|
||||
<pre>./MyExe Test -c sa</pre>
|
||||
|
||||
There are some limitations of this feature to be aware of:
|
||||
- Code outside of sections being skipped will still be executed - e.g. any set-up code in the TEST_CASE before the
|
||||
start of the first section.</br>
|
||||
- At time of writing, wildcards are not supported in section names.
|
||||
- If you specify a section without narrowing to a test case first then all test cases will be executed
|
||||
(but only matching sections within them).
|
||||
|
||||
|
||||
<a id="filenames-as-tags"></a>
|
||||
## Filenames as tags
|
||||
<pre>-#, --filenames-as-tags</pre>
|
||||
|
||||
When this option is used then every test is given an additional tag which is formed of the unqualified
|
||||
filename it is found in, with any extension stripped, prefixed with the `#` character.
|
||||
|
||||
So, for example, tests within the file `~\Dev\MyProject\Ferrets.cpp` would be tagged `[#Ferrets]`.
|
||||
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
||||
[Home](Readme.md)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```).
|
||||
|
||||
Nonetheless there are still some occasions where finer control is needed. For these occasions Catch exposes a small set of macros for configuring how it is built.
|
||||
Nonetheless there are still some occasions where finer control is needed. For these occasions Catch exposes a set of macros for configuring how it is built.
|
||||
|
||||
# main()/ implementation
|
||||
|
||||
@@ -61,6 +61,8 @@ This can be useful on certain platforms that do not provide ```std::cout``` and
|
||||
CATCH_CONFIG_CPP11_LONG_LONG // generates overloads for the long long type
|
||||
CATCH_CONFIG_CPP11_OVERRIDE // CATCH_OVERRIDE expands to override (for virtual function implementations)
|
||||
CATCH_CONFIG_CPP11_UNIQUE_PTR // Use std::unique_ptr instead of std::auto_ptr
|
||||
CATCH_CONFIG_CPP11_SHUFFLE // Use std::shuffle instead of std::random_shuffle
|
||||
CATCH_CONFIG_CPP11_TYPE_TRAITS // Use std::enable_if and <type_traits>
|
||||
|
||||
Catch has some basic compiler detection that will attempt to select the appropriate mix of these macros. However being incomplete - and often without access to the respective compilers - this detection tends to be conservative.
|
||||
So overriding control is given to the user. If a compiler supports a feature (and Catch does not already detect it) then one or more of these may be defined to enable it (or suppress it, in some cases). If you do do this please raise an issue, specifying your compiler version (ideally with an idea of how to detect it) and stating that it has such support.
|
||||
@@ -68,6 +70,22 @@ You may also suppress any of these features by using the `_NO_` form, e.g. `CATC
|
||||
|
||||
All C++11 support can be disabled with `CATCH_CONFIG_NO_CPP11`
|
||||
|
||||
# Other toggles
|
||||
|
||||
CATCH_CONFIG_COUNTER // Use __COUNTER__ to generate unique names for test cases
|
||||
CATCH_CONFIG_WINDOWS_SEH // Enable SEH handling on Windows
|
||||
|
||||
Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API supports.
|
||||
|
||||
Just as with the C++11 conformance toggles, these toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`.
|
||||
|
||||
# Windows header clutter
|
||||
|
||||
On Windows Catch includes `windows.h`. To minimize global namespace clutter in the implementation file, it defines `NOMINMAX` and `WIN32_LEAN_AND_MEAN` before including it. You can control this behaviour via two macros:
|
||||
|
||||
CATCH_CONFIG_NO_NOMINMAX // Stops Catch from using NOMINMAX macro
|
||||
CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN // Stops Catch from using WIN32_LEAN_AND_MEAN macro
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
||||
[Home](Readme.md)
|
||||
|
@@ -1,22 +1,40 @@
|
||||
# Contributing to Catch
|
||||
|
||||
So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for additional compilers - or just a fix to the documentation - all contributions are very welcome and very much appreciated. Of course so are bug reports and other comments and questions.
|
||||
So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for
|
||||
additional compilers - or just a fix to the documentation - all contributions are very welcome and very much appreciated.
|
||||
Of course so are bug reports and other comments and questions.
|
||||
|
||||
If you are contributing to the code base there are a few simple guidelines to keep in mind. This also includes notes to help you find your way around. As this is liable to drift out of date please raise an issue or, better still, a pull request for this file, if you notice that.
|
||||
If you are contributing to the code base there are a few simple guidelines to keep in mind. This also includes notes to
|
||||
help you find your way around. As this is liable to drift out of date please raise an issue or, better still, a pull
|
||||
request for this file, if you notice that.
|
||||
|
||||
## Branches
|
||||
|
||||
Ongoing development is on the "develop" branch (if there is one, currently), or on feature branches that are branched off of develop. Please target any pull requests at develop, or, for larger chunks of work, a branch off of develop.
|
||||
Ongoing development is currently on _master_. At some point an integration branch will be set-up and PRs should target
|
||||
that - but for now it's all against master. You may see feature branches come and go from time to time, too.
|
||||
|
||||
## Directory structure
|
||||
|
||||
Users of Catch primarily use the single header version. Maintainers should work with the full source (which is still, primarily, in headers). This can be found in the ```include``` folder, but you may prefer to use one of the IDE project files (for MSVC or XCode). These can be found under ```projects/```*IDE Name*```/```*project name*. A number of contributors have proposed make files, and submitted their own versions. At some point these should be made available too.
|
||||
_Users_ of Catch primarily use the single header version. _Maintainers_ should work with the full source (which is still,
|
||||
primarily, in headers). This can be found in the `include` folder. There are a set of test files, currently under
|
||||
`projects/SelfTest`. The test app can be built via CMake from the `CMakeLists.txt` file in the root, or you can generate
|
||||
project files for Visual Studio, XCode, and others (instructions in the `projects` folder). If you have access to CLion
|
||||
that can work with the CMake file directly.
|
||||
|
||||
In addition to the include files and IDE projects there are a number of tests in cpp files. These can all be found in ```projects/SelfTest```. You'll also see a ```SurrogateCpps``` directory in there. This contains a set of cpp files that each ```#include``` a single header. While these files are not essential to compilation they help to keep the implementation headers self-contained. At time of writing this set is not complete but has reasonable coverage. If you add additional headers please try to remember to add a surrogate cpp for it.
|
||||
As well as the runtime test files you'll also see a `SurrogateCpps` directory under `projects/SelfTest`.
|
||||
This contains a set of .cpp files that each `#include` a single header.
|
||||
While these files are not essential to compilation they help to keep the implementation headers self-contained.
|
||||
At time of writing this set is not complete but has reasonable coverage.
|
||||
If you add additional headers please try to remember to add a surrogate cpp for it.
|
||||
|
||||
The other directories are ```scripts``` which contains a set of python scripts to help in testing Catch as well as generating the single include, and docs, which contains the documentation as a set of markdown files.
|
||||
The other directories are `scripts` which contains a set of python scripts to help in testing Catch as well as
|
||||
generating the single include, and `docs`, which contains the documentation as a set of markdown files.
|
||||
|
||||
*this document is in-progress...*
|
||||
__When submitting a pull request please do not include changes to the single include, or to the version number file
|
||||
as these are managed by the scripts!__
|
||||
|
||||
|
||||
*this document is still in-progress...*
|
||||
|
||||
---
|
||||
|
||||
|
94
docs/limitations.md
Normal file
94
docs/limitations.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Known limitations
|
||||
|
||||
Catch has some known limitations, that we are not planning to change. Some of these are caused by our desire to support C++98 compilers, some of these are caused by our desire to keep Catch crossplatform, some exist because their priority is seen as low compared to the development effort they would need and some other yet are compiler/runtime bugs.
|
||||
|
||||
## Features
|
||||
This section outlines some missing features, what is their status and their possible workarounds.
|
||||
|
||||
### 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.
|
||||
|
||||
This means that this is ok
|
||||
```cpp
|
||||
std::vector<std::thread> threads;
|
||||
std::atomic<int> cnt{ 0 };
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
threads.emplace_back([&]() {
|
||||
++cnt; ++cnt; ++cnt; ++cnt;
|
||||
});
|
||||
}
|
||||
for (auto& t : threads) { t.join(); }
|
||||
REQUIRE(cnt == 16);
|
||||
```
|
||||
because only one thread passes the `REQUIRE` macro and this is not
|
||||
```cpp
|
||||
std::vector<std::thread> threads;
|
||||
std::atomic<int> cnt{ 0 };
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
threads.emplace_back([&]() {
|
||||
++cnt; ++cnt; ++cnt; ++cnt;
|
||||
CHECK(cnt == 16);
|
||||
});
|
||||
}
|
||||
for (auto& t : threads) { t.join(); }
|
||||
REQUIRE(cnt == 16);
|
||||
```
|
||||
|
||||
|
||||
_This limitation is highly unlikely to be lifted before Catch 2 is released._
|
||||
|
||||
### 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.
|
||||
|
||||
### Running multiple tests in parallel
|
||||
Catch's test execution is strictly serial. If you find yourself with a test suite that takes too long to run and you want to make it parallel, there are 2 feasible solutions
|
||||
* You can split your tests into multiple binaries and then run these binaries in parallel.
|
||||
* You can have Catch list contained test cases and then run the same test binary multiple times in parallel, passing each instance list of test cases it should run.
|
||||
|
||||
Both of these solutions have their problems, but should let you wring parallelism out of your test suite.
|
||||
|
||||
## 3rd party bugs
|
||||
This section outlines known bugs in 3rd party components (this means compilers, standard libraries, standard runtimes).
|
||||
|
||||
### Visual Studio 2013 -- do-while loop withing range based for fails to compile (C2059)
|
||||
There is a known bug in Visual Studio 2013 (VC 12), that causes compilation error if range based for is followed by an assertion macro, without enclosing the block in braces. This snippet is sufficient to trigger the error
|
||||
```cpp
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
|
||||
TEST_CASE("Syntax error with VC12") {
|
||||
for ( auto x : { 1 , 2, 3 } )
|
||||
REQUIRE( x < 3.14 );
|
||||
}
|
||||
```
|
||||
An easy workaround is possible, use braces:
|
||||
```cpp
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
|
||||
TEST_CASE("No longer a syntax error with VC12") {
|
||||
for ( auto x : { 1 , 2, 3 } ) {
|
||||
REQUIRE( x < 3.14 );
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Clang/G++ -- skipping leaf sections after an exception
|
||||
Some versions of `libc++` and `libstdc++` (or their runtimes) have a bug with `std::uncaught_exception()` getting stuck returning `true` after rethrow, even if there are no active exceptions. One such case is this snippet, which skipped the sections "a" and "b", when compiled against `libcxxrt` from master
|
||||
```cpp
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("a") {
|
||||
CHECK_THROWS(throw 3);
|
||||
}
|
||||
|
||||
TEST_CASE("b") {
|
||||
int i = 0;
|
||||
SECTION("a") { i = 1; }
|
||||
SECTION("b") { i = 2; }
|
||||
CHECK(i > 0);
|
||||
}
|
||||
```
|
||||
|
||||
If you are seeing a problem like this, i.e. a weird test paths that trigger only under Clang with `libc++`, or only under very specific version of `libstdc++`, it is very likely you are seeing this. The only known workaround is to use a fixed version of your standard library.
|
@@ -16,7 +16,7 @@ If you just need to have code that executes before and/ or after Catch this is t
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include "catch.hpp"
|
||||
|
||||
int main( int argc, char* const argv[] )
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
// global setup...
|
||||
|
||||
@@ -24,7 +24,7 @@ int main( int argc, char* const argv[] )
|
||||
|
||||
// global clean-up...
|
||||
|
||||
return result;
|
||||
return ( result < 0xff ? result : 0xff );
|
||||
}
|
||||
```
|
||||
|
||||
@@ -36,9 +36,9 @@ If you still want Catch to process the command line, but you want to programatic
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include "catch.hpp"
|
||||
|
||||
int main( int argc, char* const argv[] )
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
Catch::Session session; // There must be exactly once instance
|
||||
Catch::Session session; // There must be exactly one instance
|
||||
|
||||
// writing to session.configData() here sets defaults
|
||||
// this is the preferred way to set them
|
||||
@@ -51,7 +51,11 @@ int main( int argc, char* const argv[] )
|
||||
// overrides command line args
|
||||
// only do this if you know you need to
|
||||
|
||||
return session.run();
|
||||
int numFailed = session.run();
|
||||
// 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 ( numFailed < 0xff ? numFailed : 0xff );
|
||||
}
|
||||
```
|
||||
|
||||
@@ -65,4 +69,4 @@ Catch embeds a powerful command line parser which you can also use to parse your
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
||||
[Home](Readme.md)
|
||||
|
86
docs/release-notes.md
Normal file
86
docs/release-notes.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# 1.7.1
|
||||
|
||||
### Fixes:
|
||||
* Fixed inconsistency in defining `NOMINMAX` and `WIN32_LEAN_AND_MEAN` inside `catch.hpp`.
|
||||
* Fixed SEH-related compilation error under older MinGW compilers, by making Windows SEH handling opt-in for compilers other than MSVC.
|
||||
* For specifics, look into the [documentation](docs/configuration.md).
|
||||
* Fixed compilation error under MinGW caused by improper compiler detection.
|
||||
* Fixed XML reporter sometimes leaving an empty output file when a test ends with signal/structured exception.
|
||||
* Fixed XML reporter not reporting captured stdout/stderr.
|
||||
* Fixed possible infinite recursion in Windows SEH.
|
||||
* Fixed possible compilation error caused by Catch's operator overloads being ambiguous in regards to user-defined templated operators.
|
||||
|
||||
# Older versions
|
||||
Release notes were not maintained prior to v1.6.0, but you should be able to work them out from the Git history
|
||||
|
||||
## 1.7.0
|
||||
|
||||
### Features/ Changes:
|
||||
* Catch now runs significantly faster for passing tests
|
||||
* Microbenchmark focused on Catch's overhead went from ~3.4s to ~0.7s.
|
||||
* Real world test using [JSON for Modern C++](https://github.com/nlohmann/json)'s test suite went from ~6m 25s to ~4m 14s.
|
||||
* Catch can now run specific sections within test cases.
|
||||
* For now the support is only basic (no wildcards or tags), for details see the [documentation](docs/command-line.md).
|
||||
* Catch now supports SEH on Windows as well as signals on Linux.
|
||||
* After receiving a signal, Catch reports failing assertion and then passes the signal onto the previous handler.
|
||||
* Approx can be used to compare values against strong typedefs (available in C++11 mode only).
|
||||
* Strong typedefs mean types that are explicitly convertible to double.
|
||||
* CHECK macro no longer stops executing section if an exception happens.
|
||||
* Certain characters (space, tab, etc) are now pretty printed.
|
||||
* This means that a `char c = ' '; REQUIRE(c == '\t');` would be printed as `' ' == '\t'`, instead of ` == 9`.
|
||||
|
||||
### Fixes:
|
||||
* Text formatting no longer attempts to access out-of-bounds characters under certain conditions.
|
||||
* THROW family of assertions no longer trigger `-Wunused-value` on expressions containing explicit cast.
|
||||
* Breaking into debugger under OS X works again and no longer required `DEBUG` to be defined.
|
||||
* Compilation no longer breaks under certain compiler if a lambda is used inside assertion macro.
|
||||
|
||||
### Other:
|
||||
* Catch's CMakeLists now defines install command.
|
||||
* Catch's CMakeLists now generates projects with warnings enabled.
|
||||
|
||||
|
||||
## 1.6.1
|
||||
|
||||
### Features/ Changes:
|
||||
* Catch now supports breaking into debugger on Linux
|
||||
|
||||
### Fixes:
|
||||
* Generators no longer leak memory (generators are still unsupported in general)
|
||||
* JUnit reporter now reports UTC timestamps, instead of "tbd"
|
||||
* `CHECK_THAT` macro is now properly defined as `CATCH_CHECK_THAT` when using `CATCH_` prefixed macros
|
||||
|
||||
### Other:
|
||||
* Types with overloaded `&&` operator are no longer evaluated twice when used in an assertion macro.
|
||||
* The use of `__COUNTER__` is supressed when Catch is parsed by CLion
|
||||
* This change is not active when compiling a binary
|
||||
* Approval tests can now be run on Windows
|
||||
* CMake will now warn if a file is present in the `include` folder but not is not enumerated as part of the project
|
||||
* Catch now defines `NOMINMAX` and `WIN32_LEAN_AND_MEAN` before including `windows.h`
|
||||
* This can be disabled if needed, see [documentation](docs/configuration.md) for details.
|
||||
|
||||
|
||||
## 1.6.0
|
||||
|
||||
### Cmake/ projects:
|
||||
* Moved CMakeLists.txt to root, made it friendlier for CLion and generating XCode and VS projects, and removed the manually maintained XCode and VS projects.
|
||||
|
||||
### Features/ Changes:
|
||||
* Approx now supports `>=` and `<=`
|
||||
* Can now use `\` to escape chars in test names on command line
|
||||
* Standardize C++11 feature toggles
|
||||
|
||||
### Fixes:
|
||||
* Blue shell colour
|
||||
* Missing argument to `CATCH_CHECK_THROWS`
|
||||
* Don't encode extended ASCII in XML
|
||||
* use `std::shuffle` on more compilers (fixes deprecation warning/error)
|
||||
* Use `__COUNTER__` more consistently (where available)
|
||||
|
||||
### Other:
|
||||
* Tweaks and changes to scripts - particularly for Approval test - to make them more portable
|
||||
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
@@ -2,7 +2,7 @@
|
||||
|
||||
While Catch fully supports the traditional, xUnit, style of class-based fixtures containing test case methods this is not the preferred style.
|
||||
|
||||
Instead Catch provides a powerful mechanism for nesting test case sections within a test case. For a more detailed discussion see the [tutorial](tutorial.md#testCasesAndSections).
|
||||
Instead Catch provides a powerful mechanism for nesting test case sections within a test case. For a more detailed discussion see the [tutorial](tutorial.md#test-cases-and-sections).
|
||||
|
||||
Test cases and sections are very easy to use in practice:
|
||||
|
||||
@@ -34,14 +34,16 @@ Tag names are not case sensitive.
|
||||
|
||||
All tag names beginning with non-alphanumeric characters are reserved by Catch. Catch defines a number of "special" tags, which have meaning to the test runner itself. These special tags all begin with a symbol character. Following is a list of currently defined special tags and their meanings.
|
||||
|
||||
* `[!hide]` or `[.]` (or, for legacy reasons, `[hide]`) - causes test cases to be skipped from the default list (ie when no test cases have been explicitly selected through tag expressions or name wildcards). The hide tag is often combined with another, user, tag (for example `[.][integration]` - so all integration tests are excluded from the default run but can be run by passing `[integration]` on the command line). As a short-cut you can combine these by simply prefixing your user tag with a `.` - e.g. `[.integration]`. Because the hide tag has evolved to have several forms, all forms are added as tags if you use one of them.
|
||||
* `[!hide]` or `[.]` (or, for legacy reasons, `[hide]`) - causes test cases to be skipped from the default list (i.e. when no test cases have been explicitly selected through tag expressions or name wildcards). The hide tag is often combined with another, user, tag (for example `[.][integration]` - so all integration tests are excluded from the default run but can be run by passing `[integration]` on the command line). As a short-cut you can combine these by simply prefixing your user tag with a `.` - e.g. `[.integration]`. Because the hide tag has evolved to have several forms, all forms are added as tags if you use one of them.
|
||||
|
||||
* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be exluded when running with `-e` or `--nothrow`.
|
||||
* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`.
|
||||
|
||||
* `[!shouldfail]` - reverse the failing logic of the test: if the test is successful if it fails, and vice-versa.
|
||||
|
||||
* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in the your tests.
|
||||
|
||||
* `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers.
|
||||
|
||||
* `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped) as a tag. e.g. tests in testfile.cpp would all be tagged `[#testfile]`.
|
||||
|
||||
* `[@<alias>]` - tag aliases all begin with `@` (see below).
|
||||
@@ -52,7 +54,7 @@ Between tag expressions and wildcarded test names (as well as combinations of th
|
||||
|
||||
CATCH_REGISTER_TAG_ALIAS( <alias string>, <tag expression> )
|
||||
|
||||
Aliases must begining with the `@` character. An example of a tag alias is:
|
||||
Aliases must begin with the `@` character. An example of a tag alias is:
|
||||
|
||||
CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" )
|
||||
|
||||
@@ -83,4 +85,4 @@ Other than the additional prefixes and the formatting in the console reporter th
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
||||
[Home](Readme.md)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
Although Catch allows you to group tests together as sections within a test case, it can still convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure:
|
||||
Although Catch allows you to group tests together as sections within a test case, it can still be convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure:
|
||||
|
||||
```c++
|
||||
class UniqueTestsFixture {
|
||||
@@ -29,4 +29,4 @@ The two test cases here will create uniquely-named derived classes of UniqueTest
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
||||
[Home](Readme.md)
|
||||
|
@@ -55,6 +55,16 @@ namespace Catch {
|
||||
}
|
||||
```
|
||||
|
||||
## 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:
|
||||
|
||||
```
|
||||
CATCH_TRANSLATE_EXCEPTION( MyType& ex ) {
|
||||
return ex.message();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# Getting Catch
|
||||
|
||||
The simplest way to get Catch is to download the single header version from [http://builds.catch-lib.net](http://builds.catch-lib.net). Don't be put off by the word "builds" there. 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 Catch is to download the latest [single header version](https://raw.githubusercontent.com/philsquared/Catch/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 full source for Catch, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there.
|
||||
|
||||
@@ -96,7 +96,7 @@ Although this was a simple test it's been enough to demonstrate a few things abo
|
||||
|
||||
Most test frameworks have a class-based fixture mechanism. That is, test cases map to methods on a class and common setup and teardown can be performed in ```setup()``` and ```teardown()``` methods (or constructor/ destructor in languages, like C++, that support deterministic destruction).
|
||||
|
||||
While Catch fully supports this way of working there are a few problems with the approach. In particular, the way your code must be split up and the blunt granularity of cause problems. You can only have one setup/ teardown pair across a set of methods, but sometimes you want slightly different setup in each method, or you may even want several levels of setup (a concept which we will clarify later on in this tutorial). It was <a href="http://jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html">problems like these</a> that led James Newkirk, who led the team that built NUnit, to start again from scratch and <a href="http://jamesnewkirk.typepad.com/posts/2007/09/announcing-xuni.html">build xUnit</a>).
|
||||
While Catch fully supports this way of working there are a few problems with the approach. In particular the way your code must be split up, and the blunt granularity of it, may cause problems. You can only have one setup/ teardown pair across a set of methods, but sometimes you want slightly different setup in each method, or you may even want several levels of setup (a concept which we will clarify later on in this tutorial). It was <a href="http://jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html">problems like these</a> that led James Newkirk, who led the team that built NUnit, to start again from scratch and <a href="http://jamesnewkirk.typepad.com/posts/2007/09/announcing-xuni.html">build xUnit</a>).
|
||||
|
||||
Catch takes a different approach (to both NUnit and xUnit) that is a more natural fit for C++ and the C family of languages. This is best explained through an example:
|
||||
|
||||
@@ -233,7 +233,7 @@ The requirement is that the following block of code ([or equivalent](own-main.md
|
||||
|
||||
appears in _exactly one_ source file. Use as many additional cpp files (or whatever you call your implementation files) as you need for your tests, partitioned however makes most sense for your way of working. Each additional file need only ```#include "catch.hpp"``` - do not repeat the ```#define```!
|
||||
|
||||
In fact it is usually a good idea to put the block with the ```#define``` [in it's own source file](slow-compiles.md).
|
||||
In fact it is usually a good idea to put the block with the ```#define``` [in its own source file](slow-compiles.md).
|
||||
|
||||
Do not write your tests in header files!
|
||||
|
||||
|
@@ -1,24 +0,0 @@
|
||||
## What's new in Catch for 1.0
|
||||
|
||||
After a long "developer preview" state Catch turned 1.0 in mid-2013. Just prior to this a large number of changes, some of them breaking, where merged from the integration branch and now form part of the 1.0 code-base. If this might affect you please read this summary through so you know what to expect.
|
||||
|
||||
* Calling Catch from your own ```main()``` has changed - please review [the updated docs](own-main.md)
|
||||
* The command line has changed. The biggest change is that test case names and tags should now only be supplied as primary arguments - in fact the ```-t``` option has been repurposed to mean "list tags". There are [updated docs for this too](command-line.md)
|
||||
* There is a new reporter interface. If you have written a custom reporter you can use the ```LegacyReporterAdapter``` to minimise any differences. Ideally you should update to the new interface - especially as it has been designed to be more robust in the face of future changes (which should be minimal).
|
||||
* The docs have moved from the wiki to the repository itself. They consist of a set of markdown files in the docs folder and are referenced directly from the README in the root. You can still read them online from GitHub.
|
||||
* Lots of new goodness - more documentation for which is coming. The existing docs have been updated to account for some of the changes already (e.g. variadic macros). A quick rundown:
|
||||
* Variadic macros are used, where possible, so that, e.g. you can write a ```TEST_CASE``` with just a name - or even no name at all (making it an anonymous test case).
|
||||
* The hierarchical naming convention is deprecated in favour of using tags (see next)
|
||||
* ```TEST_CASE```s (but not ```SECTION```s) can now be tagged by placing keywords in square brackets in the second argument - e.g.: ```TEST_CASE( "A nice name", "[tag1][tag2]")```. The old style is still supported but please consider using this new style.
|
||||
* Tests can still be "hidden" using the ```./``` prefix as before, but the preferred way now is to give it the ```[hide]``` tag (hidden tests are skipped if you run the test process without specifying any test specs).
|
||||
* As well as ```TEST_CASE```s and ```SECTION```s you can now also use BDD-style ```SCENARIO``` (in place of ```TEST_CASE```) and ```GIVEN```, ```WHEN``` and ```THEN``` macros (in place of ```SECTION```s).
|
||||
* New command line parser. Under the hood it is a complete rewrite - now powered by a command line library that will soon be spun out as a separate project: Clara. The options themselves are largely the same but there are some notable differences (as already discussed).
|
||||
* Completely overhauled output from the textual reporter (now the Console reporter). This now features a much clearer, cleaner format, including good use of indentation.
|
||||
|
||||
More information can be found in [this blog post](http://www.levelofindirection.com/journal/2013/6/28/catch-10.html).
|
||||
|
||||
If you find any issues please raise issue tickets on the [issue tracker on GitHub](https://github.com/philsquared/Catch/issues) as before. For general questions, comments and suggestions, though, please use the [new forums on Google Groups](https://groups.google.com/forum/?fromgroups#!forum/catch-forum).
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
@@ -81,12 +81,12 @@
|
||||
#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
|
||||
#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
|
||||
|
||||
#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
|
||||
#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CATCH_CHECK_THROWS" )
|
||||
#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
|
||||
#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" )
|
||||
#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
|
||||
|
||||
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
|
||||
#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
|
||||
#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
|
||||
|
||||
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
|
||||
@@ -99,6 +99,7 @@
|
||||
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
|
||||
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __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_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
|
||||
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
|
||||
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
|
||||
@@ -106,6 +107,7 @@
|
||||
#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
|
||||
#define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
|
||||
#define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
|
||||
#define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
|
||||
#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
|
||||
#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
|
||||
#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
|
||||
@@ -166,6 +168,7 @@
|
||||
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
|
||||
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __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 SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
|
||||
#define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
|
||||
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
|
||||
@@ -173,6 +176,7 @@
|
||||
#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
|
||||
#define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
|
||||
#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
|
||||
#define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
|
||||
#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
|
||||
#define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
|
||||
#define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
|
||||
|
@@ -30,7 +30,7 @@ namespace Catch {
|
||||
}
|
||||
return reporter;
|
||||
}
|
||||
|
||||
|
||||
Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
|
||||
std::vector<std::string> reporters = config->getReporterNames();
|
||||
if( reporters.empty() )
|
||||
@@ -40,10 +40,10 @@ namespace Catch {
|
||||
for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
|
||||
it != itEnd;
|
||||
++it )
|
||||
reporter = addReporter( reporter, createReporter( *it, config ) );
|
||||
reporter = addReporter( reporter, createReporter( *it, config ) );
|
||||
return reporter;
|
||||
}
|
||||
Ptr<IStreamingReporter> addListeners( Ptr<IConfig> const& config, Ptr<IStreamingReporter> reporters ) {
|
||||
Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
|
||||
IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
|
||||
for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
|
||||
it != itEnd;
|
||||
@@ -51,28 +51,16 @@ namespace Catch {
|
||||
reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
|
||||
return reporters;
|
||||
}
|
||||
|
||||
void openStreamInto( Ptr<Config> const& config, std::ofstream& ofs ) {
|
||||
// Open output file, if specified
|
||||
if( !config->getFilename().empty() ) {
|
||||
ofs.open( config->getFilename().c_str() );
|
||||
if( ofs.fail() ) {
|
||||
std::ostringstream oss;
|
||||
oss << "Unable to open file: '" << config->getFilename() << "'";
|
||||
throw std::domain_error( oss.str() );
|
||||
}
|
||||
config->setStreamBuf( ofs.rdbuf() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Totals runTests( Ptr<Config> const& config ) {
|
||||
|
||||
std::ofstream ofs;
|
||||
openStreamInto( config, ofs );
|
||||
Ptr<IConfig const> iconfig = config.get();
|
||||
|
||||
Ptr<IStreamingReporter> reporter = makeReporter( config );
|
||||
reporter = addListeners( config.get(), reporter );
|
||||
|
||||
RunContext context( config.get(), reporter );
|
||||
reporter = addListeners( iconfig, reporter );
|
||||
|
||||
RunContext context( iconfig, reporter );
|
||||
|
||||
Totals totals;
|
||||
|
||||
@@ -82,26 +70,26 @@ namespace Catch {
|
||||
if( !testSpec.hasFilters() )
|
||||
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
|
||||
|
||||
std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *config );
|
||||
std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
|
||||
for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
|
||||
it != itEnd;
|
||||
++it ) {
|
||||
if( !context.aborting() && matchTest( *it, testSpec, *config ) )
|
||||
if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
|
||||
totals += context.runTest( *it );
|
||||
else
|
||||
reporter->skipTest( *it );
|
||||
}
|
||||
|
||||
context.testGroupEnded( config->name(), totals, 1, 1 );
|
||||
context.testGroupEnded( iconfig->name(), totals, 1, 1 );
|
||||
return totals;
|
||||
}
|
||||
|
||||
|
||||
void applyFilenamesAsTags( IConfig const& config ) {
|
||||
std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
|
||||
for(std::size_t i = 0; i < tests.size(); ++i ) {
|
||||
TestCase& test = const_cast<TestCase&>( tests[i] );
|
||||
std::set<std::string> tags = test.tags;
|
||||
|
||||
|
||||
std::string filename = test.lineInfo.file;
|
||||
std::string::size_type lastSlash = filename.find_last_of( "\\/" );
|
||||
if( lastSlash != std::string::npos )
|
||||
@@ -110,7 +98,7 @@ namespace Catch {
|
||||
std::string::size_type lastDot = filename.find_last_of( "." );
|
||||
if( lastDot != std::string::npos )
|
||||
filename = filename.substr( 0, lastDot );
|
||||
|
||||
|
||||
tags.insert( "#" + filename );
|
||||
setTags( test, tags );
|
||||
}
|
||||
@@ -143,10 +131,10 @@ namespace Catch {
|
||||
Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
|
||||
}
|
||||
|
||||
int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
|
||||
int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
|
||||
try {
|
||||
m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
|
||||
m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
|
||||
m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
|
||||
if( m_configData.showHelp )
|
||||
showHelp( m_configData.processName );
|
||||
m_config.reset();
|
||||
@@ -170,7 +158,7 @@ namespace Catch {
|
||||
m_config.reset();
|
||||
}
|
||||
|
||||
int run( int argc, char* const argv[] ) {
|
||||
int run( int argc, char const* const* const argv ) {
|
||||
|
||||
int returnCode = applyCommandLine( argc, argv );
|
||||
if( returnCode == 0 )
|
||||
@@ -185,12 +173,12 @@ namespace Catch {
|
||||
try
|
||||
{
|
||||
config(); // Force config to be constructed
|
||||
|
||||
|
||||
seedRng( *m_config );
|
||||
|
||||
if( m_configData.filenamesAsTags )
|
||||
applyFilenamesAsTags( *m_config );
|
||||
|
||||
|
||||
// Handle list request
|
||||
if( Option<std::size_t> listed = list( config() ) )
|
||||
return static_cast<int>( *listed );
|
||||
|
@@ -8,8 +8,7 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_WITH_MAIN_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_WITH_MAIN_HPP_INCLUDED
|
||||
|
||||
#include "catch_runner.hpp"
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
#include "internal/catch_default_main.hpp"
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_WITH_MAIN_HPP_INCLUDED
|
||||
|
352
include/external/clara.h
vendored
352
include/external/clara.h
vendored
@@ -6,6 +6,8 @@
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
// Version 0.0.2.4
|
||||
|
||||
// Only use header guard if we are not using an outer namespace
|
||||
#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
|
||||
|
||||
@@ -38,6 +40,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
// Use optional outer namespace
|
||||
#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
|
||||
@@ -172,16 +175,179 @@ namespace Tbc {
|
||||
#endif // TBC_TEXT_FORMAT_H_INCLUDED
|
||||
|
||||
// ----------- end of #include from tbc_text_format.h -----------
|
||||
// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h
|
||||
// ........... back in clara.h
|
||||
|
||||
#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
|
||||
|
||||
|
||||
// ----------- #included from clara_compilers.h -----------
|
||||
|
||||
/*
|
||||
* Created by Phil on 10/02/2016.
|
||||
* Copyright 2016 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
|
||||
#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
|
||||
|
||||
// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
|
||||
// The following features are defined:
|
||||
//
|
||||
// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
|
||||
// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
|
||||
// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
|
||||
// CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
|
||||
// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
|
||||
|
||||
// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
|
||||
|
||||
// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
|
||||
|
||||
// In general each macro has a _NO_<feature name> form
|
||||
// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
|
||||
// Many features, at point of detection, define an _INTERNAL_ macro, so they
|
||||
// can be combined, en-mass, with the _NO_ forms later.
|
||||
|
||||
// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
|
||||
|
||||
#ifdef __clang__
|
||||
|
||||
#if __has_feature(cxx_nullptr)
|
||||
#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
|
||||
#endif
|
||||
|
||||
#if __has_feature(cxx_noexcept)
|
||||
#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
|
||||
#endif
|
||||
|
||||
#endif // __clang__
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GCC
|
||||
#ifdef __GNUC__
|
||||
|
||||
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
|
||||
#endif
|
||||
|
||||
// - otherwise more recent versions define __cplusplus >= 201103L
|
||||
// and will get picked up below
|
||||
|
||||
#endif // __GNUC__
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Visual C++
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#if (_MSC_VER >= 1600)
|
||||
#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
|
||||
#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
|
||||
#endif
|
||||
|
||||
#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
|
||||
#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
|
||||
#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
|
||||
#endif
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// C++ language feature support
|
||||
|
||||
// catch all support for C++11
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
|
||||
#define CLARA_CPP11_OR_GREATER
|
||||
|
||||
#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
|
||||
#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
|
||||
#endif
|
||||
|
||||
#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
|
||||
#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
|
||||
#endif
|
||||
|
||||
#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
|
||||
#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
|
||||
#endif
|
||||
|
||||
#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
|
||||
#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
|
||||
#endif
|
||||
#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
|
||||
#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
|
||||
#endif
|
||||
|
||||
|
||||
#endif // __cplusplus >= 201103L
|
||||
|
||||
// Now set the actual defines based on the above + anything the user has configured
|
||||
#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
|
||||
#define CLARA_CONFIG_CPP11_NULLPTR
|
||||
#endif
|
||||
#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
|
||||
#define CLARA_CONFIG_CPP11_NOEXCEPT
|
||||
#endif
|
||||
#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11)
|
||||
#define CLARA_CONFIG_CPP11_GENERATED_METHODS
|
||||
#endif
|
||||
#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
|
||||
#define CLARA_CONFIG_CPP11_OVERRIDE
|
||||
#endif
|
||||
#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11)
|
||||
#define CLARA_CONFIG_CPP11_UNIQUE_PTR
|
||||
#endif
|
||||
|
||||
|
||||
// noexcept support:
|
||||
#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
|
||||
#define CLARA_NOEXCEPT noexcept
|
||||
# define CLARA_NOEXCEPT_IS(x) noexcept(x)
|
||||
#else
|
||||
#define CLARA_NOEXCEPT throw()
|
||||
# define CLARA_NOEXCEPT_IS(x)
|
||||
#endif
|
||||
|
||||
// nullptr support
|
||||
#ifdef CLARA_CONFIG_CPP11_NULLPTR
|
||||
#define CLARA_NULL nullptr
|
||||
#else
|
||||
#define CLARA_NULL NULL
|
||||
#endif
|
||||
|
||||
// override support
|
||||
#ifdef CLARA_CONFIG_CPP11_OVERRIDE
|
||||
#define CLARA_OVERRIDE override
|
||||
#else
|
||||
#define CLARA_OVERRIDE
|
||||
#endif
|
||||
|
||||
// unique_ptr support
|
||||
#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
|
||||
# define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
|
||||
#else
|
||||
# define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
|
||||
|
||||
|
||||
// ----------- end of #include from clara_compilers.h -----------
|
||||
// ........... back in clara.h
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
|
||||
#define CLARA_PLATFORM_WINDOWS
|
||||
#endif
|
||||
|
||||
|
||||
// Use optional outer namespace
|
||||
#ifdef STITCH_CLARA_OPEN_NAMESPACE
|
||||
STITCH_CLARA_OPEN_NAMESPACE
|
||||
@@ -230,9 +396,12 @@ namespace Clara {
|
||||
inline void convertInto( std::string const& _source, std::string& _dest ) {
|
||||
_dest = _source;
|
||||
}
|
||||
char toLowerCh(char c) {
|
||||
return static_cast<char>( ::tolower( c ) );
|
||||
}
|
||||
inline void convertInto( std::string const& _source, bool& _dest ) {
|
||||
std::string sourceLC = _source;
|
||||
std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
|
||||
std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh );
|
||||
if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
|
||||
_dest = true;
|
||||
else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
|
||||
@@ -240,23 +409,16 @@ namespace Clara {
|
||||
else
|
||||
throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
|
||||
}
|
||||
inline void convertInto( bool _source, bool& _dest ) {
|
||||
_dest = _source;
|
||||
}
|
||||
template<typename T>
|
||||
inline void convertInto( bool, T& ) {
|
||||
throw std::runtime_error( "Invalid conversion" );
|
||||
}
|
||||
|
||||
|
||||
template<typename ConfigT>
|
||||
struct IArgFunction {
|
||||
virtual ~IArgFunction() {}
|
||||
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
|
||||
#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
|
||||
IArgFunction() = default;
|
||||
IArgFunction( IArgFunction const& ) = default;
|
||||
# endif
|
||||
#endif
|
||||
virtual void set( ConfigT& config, std::string const& value ) const = 0;
|
||||
virtual void setFlag( ConfigT& config ) const = 0;
|
||||
virtual bool takesArg() const = 0;
|
||||
virtual IArgFunction* clone() const = 0;
|
||||
};
|
||||
@@ -264,11 +426,11 @@ namespace Clara {
|
||||
template<typename ConfigT>
|
||||
class BoundArgFunction {
|
||||
public:
|
||||
BoundArgFunction() : functionObj( CATCH_NULL ) {}
|
||||
BoundArgFunction() : functionObj( CLARA_NULL ) {}
|
||||
BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
|
||||
BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CATCH_NULL ) {}
|
||||
BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
|
||||
BoundArgFunction& operator = ( BoundArgFunction const& other ) {
|
||||
IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CATCH_NULL;
|
||||
IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
|
||||
delete functionObj;
|
||||
functionObj = newFunctionObj;
|
||||
return *this;
|
||||
@@ -278,13 +440,10 @@ namespace Clara {
|
||||
void set( ConfigT& config, std::string const& value ) const {
|
||||
functionObj->set( config, value );
|
||||
}
|
||||
void setFlag( ConfigT& config ) const {
|
||||
functionObj->setFlag( config );
|
||||
}
|
||||
bool takesArg() const { return functionObj->takesArg(); }
|
||||
|
||||
bool isSet() const {
|
||||
return functionObj != CATCH_NULL;
|
||||
return functionObj != CLARA_NULL;
|
||||
}
|
||||
private:
|
||||
IArgFunction<ConfigT>* functionObj;
|
||||
@@ -294,7 +453,6 @@ namespace Clara {
|
||||
template<typename C>
|
||||
struct NullBinder : IArgFunction<C>{
|
||||
virtual void set( C&, std::string const& ) const {}
|
||||
virtual void setFlag( C& ) const {}
|
||||
virtual bool takesArg() const { return true; }
|
||||
virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
|
||||
};
|
||||
@@ -305,9 +463,6 @@ namespace Clara {
|
||||
virtual void set( C& p, std::string const& stringValue ) const {
|
||||
convertInto( stringValue, p.*member );
|
||||
}
|
||||
virtual void setFlag( C& p ) const {
|
||||
convertInto( true, p.*member );
|
||||
}
|
||||
virtual bool takesArg() const { return !IsBool<M>::value; }
|
||||
virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
|
||||
M C::* member;
|
||||
@@ -320,11 +475,6 @@ namespace Clara {
|
||||
convertInto( stringValue, value );
|
||||
(p.*member)( value );
|
||||
}
|
||||
virtual void setFlag( C& p ) const {
|
||||
typename RemoveConstRef<M>::type value;
|
||||
convertInto( true, value );
|
||||
(p.*member)( value );
|
||||
}
|
||||
virtual bool takesArg() const { return !IsBool<M>::value; }
|
||||
virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
|
||||
void (C::*member)( M );
|
||||
@@ -338,9 +488,6 @@ namespace Clara {
|
||||
if( value )
|
||||
(p.*member)();
|
||||
}
|
||||
virtual void setFlag( C& p ) const {
|
||||
(p.*member)();
|
||||
}
|
||||
virtual bool takesArg() const { return false; }
|
||||
virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
|
||||
void (C::*member)();
|
||||
@@ -355,9 +502,6 @@ namespace Clara {
|
||||
if( value )
|
||||
function( obj );
|
||||
}
|
||||
virtual void setFlag( C& p ) const {
|
||||
function( p );
|
||||
}
|
||||
virtual bool takesArg() const { return false; }
|
||||
virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
|
||||
void (*function)( C& );
|
||||
@@ -371,11 +515,6 @@ namespace Clara {
|
||||
convertInto( stringValue, value );
|
||||
function( obj, value );
|
||||
}
|
||||
virtual void setFlag( C& obj ) const {
|
||||
typename RemoveConstRef<T>::type value;
|
||||
convertInto( true, value );
|
||||
function( obj, value );
|
||||
}
|
||||
virtual bool takesArg() const { return !IsBool<T>::value; }
|
||||
virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
|
||||
void (*function)( C&, T );
|
||||
@@ -383,8 +522,20 @@ namespace Clara {
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
struct Parser {
|
||||
Parser() : separators( " \t=:" ) {}
|
||||
inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
|
||||
std::vector<std::string> args( static_cast<std::size_t>( argc ) );
|
||||
for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
|
||||
args[i] = argv[i];
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
class Parser {
|
||||
enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
|
||||
Mode mode;
|
||||
std::size_t from;
|
||||
bool inQuotes;
|
||||
public:
|
||||
|
||||
struct Token {
|
||||
enum Type { Positional, ShortOpt, LongOpt };
|
||||
@@ -393,38 +544,75 @@ namespace Clara {
|
||||
std::string data;
|
||||
};
|
||||
|
||||
void parseIntoTokens( int argc, char const * const * argv, std::vector<Parser::Token>& tokens ) const {
|
||||
Parser() : mode( None ), from( 0 ), inQuotes( false ){}
|
||||
|
||||
void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
|
||||
const std::string doubleDash = "--";
|
||||
for( int i = 1; i < argc && argv[i] != doubleDash; ++i )
|
||||
parseIntoTokens( argv[i] , tokens);
|
||||
for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
|
||||
parseIntoTokens( args[i], tokens);
|
||||
}
|
||||
void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
|
||||
while( !arg.empty() ) {
|
||||
Parser::Token token( Parser::Token::Positional, arg );
|
||||
arg = "";
|
||||
if( token.data[0] == '-' ) {
|
||||
if( token.data.size() > 1 && token.data[1] == '-' ) {
|
||||
token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
|
||||
}
|
||||
else {
|
||||
token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
|
||||
if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
|
||||
arg = "-" + token.data.substr( 1 );
|
||||
token.data = token.data.substr( 0, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
if( token.type != Parser::Token::Positional ) {
|
||||
std::size_t pos = token.data.find_first_of( separators );
|
||||
if( pos != std::string::npos ) {
|
||||
arg = token.data.substr( pos+1 );
|
||||
token.data = token.data.substr( 0, pos );
|
||||
}
|
||||
}
|
||||
tokens.push_back( token );
|
||||
|
||||
void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
|
||||
for( std::size_t i = 0; i <= arg.size(); ++i ) {
|
||||
char c = arg[i];
|
||||
if( c == '"' )
|
||||
inQuotes = !inQuotes;
|
||||
mode = handleMode( i, c, arg, tokens );
|
||||
}
|
||||
}
|
||||
std::string separators;
|
||||
Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
|
||||
switch( mode ) {
|
||||
case None: return handleNone( i, c );
|
||||
case MaybeShortOpt: return handleMaybeShortOpt( i, c );
|
||||
case ShortOpt:
|
||||
case LongOpt:
|
||||
case SlashOpt: return handleOpt( i, c, arg, tokens );
|
||||
case Positional: return handlePositional( i, c, arg, tokens );
|
||||
default: throw std::logic_error( "Unknown mode" );
|
||||
}
|
||||
}
|
||||
|
||||
Mode handleNone( std::size_t i, char c ) {
|
||||
if( inQuotes ) {
|
||||
from = i;
|
||||
return Positional;
|
||||
}
|
||||
switch( c ) {
|
||||
case '-': return MaybeShortOpt;
|
||||
#ifdef CLARA_PLATFORM_WINDOWS
|
||||
case '/': from = i+1; return SlashOpt;
|
||||
#endif
|
||||
default: from = i; return Positional;
|
||||
}
|
||||
}
|
||||
Mode handleMaybeShortOpt( std::size_t i, char c ) {
|
||||
switch( c ) {
|
||||
case '-': from = i+1; return LongOpt;
|
||||
default: from = i; return ShortOpt;
|
||||
}
|
||||
}
|
||||
Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
|
||||
if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
|
||||
return mode;
|
||||
|
||||
std::string optName = arg.substr( from, i-from );
|
||||
if( mode == ShortOpt )
|
||||
for( std::size_t j = 0; j < optName.size(); ++j )
|
||||
tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
|
||||
else if( mode == SlashOpt && optName.size() == 1 )
|
||||
tokens.push_back( Token( Token::ShortOpt, optName ) );
|
||||
else
|
||||
tokens.push_back( Token( Token::LongOpt, optName ) );
|
||||
return None;
|
||||
}
|
||||
Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
|
||||
if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
|
||||
return mode;
|
||||
|
||||
std::string data = arg.substr( from, i-from );
|
||||
tokens.push_back( Token( Token::Positional, data ) );
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ConfigT>
|
||||
@@ -503,7 +691,7 @@ namespace Clara {
|
||||
}
|
||||
};
|
||||
|
||||
typedef CATCH_AUTO_PTR( Arg ) ArgAutoPtr;
|
||||
typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
|
||||
|
||||
friend void addOptName( Arg& arg, std::string const& optName )
|
||||
{
|
||||
@@ -580,8 +768,8 @@ namespace Clara {
|
||||
m_arg->description = description;
|
||||
return *this;
|
||||
}
|
||||
ArgBuilder& detail( std::string const& _detail ) {
|
||||
m_arg->detail = _detail;
|
||||
ArgBuilder& detail( std::string const& detail ) {
|
||||
m_arg->detail = detail;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -665,14 +853,14 @@ namespace Clara {
|
||||
maxWidth = (std::max)( maxWidth, it->commands().size() );
|
||||
|
||||
for( it = itBegin; it != itEnd; ++it ) {
|
||||
Detail::Text usageText( it->commands(), Detail::TextAttributes()
|
||||
Detail::Text usage( it->commands(), Detail::TextAttributes()
|
||||
.setWidth( maxWidth+indent )
|
||||
.setIndent( indent ) );
|
||||
Detail::Text desc( it->description, Detail::TextAttributes()
|
||||
.setWidth( width - maxWidth - 3 ) );
|
||||
|
||||
for( std::size_t i = 0; i < (std::max)( usageText.size(), desc.size() ); ++i ) {
|
||||
std::string usageCol = i < usageText.size() ? usageText[i] : "";
|
||||
for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
|
||||
std::string usageCol = i < usage.size() ? usage[i] : "";
|
||||
os << usageCol;
|
||||
|
||||
if( i < desc.size() && !desc[i].empty() )
|
||||
@@ -729,21 +917,21 @@ namespace Clara {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
ConfigT parse( int argc, char const * const * argv ) const {
|
||||
ConfigT parse( std::vector<std::string> const& args ) const {
|
||||
ConfigT config;
|
||||
parseInto( argc, argv, config );
|
||||
parseInto( args, config );
|
||||
return config;
|
||||
}
|
||||
|
||||
std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const {
|
||||
std::string processName = argv[0];
|
||||
std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
|
||||
std::string processName = args[0];
|
||||
std::size_t lastSlash = processName.find_last_of( "/\\" );
|
||||
if( lastSlash != std::string::npos )
|
||||
processName = processName.substr( lastSlash+1 );
|
||||
m_boundProcessName.set( config, processName );
|
||||
std::vector<Parser::Token> tokens;
|
||||
Parser parser;
|
||||
parser.parseIntoTokens( argc, argv, tokens );
|
||||
parser.parseIntoTokens( args, tokens );
|
||||
return populate( tokens, config );
|
||||
}
|
||||
|
||||
@@ -774,7 +962,7 @@ namespace Clara {
|
||||
arg.boundField.set( config, tokens[++i].data );
|
||||
}
|
||||
else {
|
||||
arg.boundField.setFlag( config );
|
||||
arg.boundField.set( config, "true" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
111
include/external/tbc_text_format.h
vendored
111
include/external/tbc_text_format.h
vendored
@@ -37,19 +37,16 @@ namespace Tbc {
|
||||
TextAttributes()
|
||||
: initialIndent( std::string::npos ),
|
||||
indent( 0 ),
|
||||
width( consoleWidth-1 ),
|
||||
tabChar( '\t' )
|
||||
width( consoleWidth-1 )
|
||||
{}
|
||||
|
||||
TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
|
||||
TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
|
||||
TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
|
||||
TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
|
||||
|
||||
std::size_t initialIndent; // indent of first line, or npos
|
||||
std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
|
||||
std::size_t width; // maximum width of text, including indent. Longer text will wrap
|
||||
char tabChar; // If this char is seen the indent is changed to current pos
|
||||
};
|
||||
|
||||
class Text {
|
||||
@@ -57,63 +54,80 @@ namespace Tbc {
|
||||
Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
|
||||
: attr( _attr )
|
||||
{
|
||||
std::string wrappableChars = " [({.,/|\\-";
|
||||
std::size_t indent = _attr.initialIndent != std::string::npos
|
||||
? _attr.initialIndent
|
||||
: _attr.indent;
|
||||
std::string remainder = _str;
|
||||
const std::string wrappableBeforeChars = "[({<\t";
|
||||
const std::string wrappableAfterChars = "])}>-,./|\\";
|
||||
const std::string wrappableInsteadOfChars = " \n\r";
|
||||
std::string indent = _attr.initialIndent != std::string::npos
|
||||
? std::string( _attr.initialIndent, ' ' )
|
||||
: std::string( _attr.indent, ' ' );
|
||||
|
||||
typedef std::string::const_iterator iterator;
|
||||
iterator it = _str.begin();
|
||||
const iterator strEnd = _str.end();
|
||||
|
||||
while( it != strEnd ) {
|
||||
|
||||
while( !remainder.empty() ) {
|
||||
if( lines.size() >= 1000 ) {
|
||||
lines.push_back( "... message truncated due to excessive size" );
|
||||
return;
|
||||
}
|
||||
std::size_t tabPos = std::string::npos;
|
||||
std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
|
||||
std::size_t pos = remainder.find_first_of( '\n' );
|
||||
if( pos <= width ) {
|
||||
width = pos;
|
||||
}
|
||||
pos = remainder.find_last_of( _attr.tabChar, width );
|
||||
if( pos != std::string::npos ) {
|
||||
tabPos = pos;
|
||||
if( remainder[width] == '\n' )
|
||||
width--;
|
||||
remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
|
||||
}
|
||||
|
||||
if( width == remainder.size() ) {
|
||||
spliceLine( indent, remainder, width );
|
||||
}
|
||||
else if( remainder[width] == '\n' ) {
|
||||
spliceLine( indent, remainder, width );
|
||||
if( width <= 1 || remainder.size() != 1 )
|
||||
remainder = remainder.substr( 1 );
|
||||
indent = _attr.indent;
|
||||
}
|
||||
else {
|
||||
pos = remainder.find_last_of( wrappableChars, width );
|
||||
if( pos != std::string::npos && pos > 0 ) {
|
||||
spliceLine( indent, remainder, pos );
|
||||
if( remainder[0] == ' ' )
|
||||
remainder = remainder.substr( 1 );
|
||||
|
||||
std::string suffix;
|
||||
std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
|
||||
iterator itEnd = it+width;
|
||||
iterator itNext = _str.end();
|
||||
|
||||
iterator itNewLine = std::find( it, itEnd, '\n' );
|
||||
if( itNewLine != itEnd )
|
||||
itEnd = itNewLine;
|
||||
|
||||
if( itEnd != strEnd ) {
|
||||
bool foundWrapPoint = false;
|
||||
iterator findIt = itEnd;
|
||||
do {
|
||||
if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) {
|
||||
itEnd = findIt+1;
|
||||
itNext = findIt+1;
|
||||
foundWrapPoint = true;
|
||||
}
|
||||
else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) {
|
||||
itEnd = findIt;
|
||||
itNext = findIt;
|
||||
foundWrapPoint = true;
|
||||
}
|
||||
else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) {
|
||||
itNext = findIt+1;
|
||||
itEnd = findIt;
|
||||
foundWrapPoint = true;
|
||||
}
|
||||
if( findIt == it )
|
||||
break;
|
||||
else
|
||||
--findIt;
|
||||
}
|
||||
while( !foundWrapPoint );
|
||||
|
||||
if( !foundWrapPoint ) {
|
||||
// No good wrap char, so we'll break mid word and add a hyphen
|
||||
--itEnd;
|
||||
itNext = itEnd;
|
||||
suffix = "-";
|
||||
}
|
||||
else {
|
||||
spliceLine( indent, remainder, width-1 );
|
||||
lines.back() += "-";
|
||||
while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos )
|
||||
--itEnd;
|
||||
}
|
||||
if( lines.size() == 1 )
|
||||
indent = _attr.indent;
|
||||
if( tabPos != std::string::npos )
|
||||
indent += tabPos;
|
||||
}
|
||||
lines.push_back( indent + std::string( it, itEnd ) + suffix );
|
||||
|
||||
if( indent.size() != _attr.indent )
|
||||
indent = std::string( _attr.indent, ' ' );
|
||||
it = itNext;
|
||||
}
|
||||
}
|
||||
|
||||
void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
|
||||
lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
|
||||
_remainder = _remainder.substr( _pos );
|
||||
}
|
||||
|
||||
|
||||
typedef std::vector<std::string>::const_iterator const_iterator;
|
||||
|
||||
@@ -138,6 +152,7 @@ namespace Tbc {
|
||||
return _stream;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::string str;
|
||||
TextAttributes attr;
|
||||
|
@@ -13,6 +13,10 @@
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
|
||||
@@ -41,6 +45,53 @@ namespace Detail {
|
||||
return approx;
|
||||
}
|
||||
|
||||
#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
|
||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||
friend bool operator == ( const T& lhs, Approx const& rhs ) {
|
||||
// Thanks to Richard Harris for his help refining this formula
|
||||
auto lhs_v = double(lhs);
|
||||
return fabs( lhs_v - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs_v), fabs(rhs.m_value) ) );
|
||||
}
|
||||
|
||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||
friend bool operator == ( Approx const& lhs, const T& rhs ) {
|
||||
return operator==( rhs, lhs );
|
||||
}
|
||||
|
||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||
friend bool operator != ( T lhs, Approx const& rhs ) {
|
||||
return !operator==( lhs, rhs );
|
||||
}
|
||||
|
||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||
friend bool operator != ( Approx const& lhs, T rhs ) {
|
||||
return !operator==( rhs, lhs );
|
||||
}
|
||||
|
||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||
friend bool operator <= ( T lhs, Approx const& rhs )
|
||||
{
|
||||
return double(lhs) < rhs.m_value || lhs == rhs;
|
||||
}
|
||||
|
||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||
friend bool operator <= ( Approx const& lhs, T rhs )
|
||||
{
|
||||
return lhs.m_value < double(rhs) || lhs == rhs;
|
||||
}
|
||||
|
||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||
friend bool operator >= ( T lhs, Approx const& rhs )
|
||||
{
|
||||
return double(lhs) > rhs.m_value || lhs == rhs;
|
||||
}
|
||||
|
||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||
friend bool operator >= ( Approx const& lhs, T rhs )
|
||||
{
|
||||
return lhs.m_value > double(rhs) || lhs == rhs;
|
||||
}
|
||||
#else
|
||||
friend bool operator == ( double lhs, Approx const& rhs ) {
|
||||
// Thanks to Richard Harris for his help refining this formula
|
||||
return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
|
||||
@@ -58,6 +109,27 @@ namespace Detail {
|
||||
return !operator==( rhs, lhs );
|
||||
}
|
||||
|
||||
friend bool operator <= ( double lhs, Approx const& rhs )
|
||||
{
|
||||
return lhs < rhs.m_value || lhs == rhs;
|
||||
}
|
||||
|
||||
friend bool operator <= ( Approx const& lhs, double rhs )
|
||||
{
|
||||
return lhs.m_value < rhs || lhs == rhs;
|
||||
}
|
||||
|
||||
friend bool operator >= ( double lhs, Approx const& rhs )
|
||||
{
|
||||
return lhs > rhs.m_value || lhs == rhs;
|
||||
}
|
||||
|
||||
friend bool operator >= ( Approx const& lhs, double rhs )
|
||||
{
|
||||
return lhs.m_value > rhs || lhs == rhs;
|
||||
}
|
||||
#endif
|
||||
|
||||
Approx& epsilon( double newEpsilon ) {
|
||||
m_epsilon = newEpsilon;
|
||||
return *this;
|
||||
|
@@ -13,6 +13,27 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
|
||||
|
||||
struct DecomposedExpression
|
||||
{
|
||||
virtual ~DecomposedExpression() {}
|
||||
virtual bool isBinaryExpression() const {
|
||||
return false;
|
||||
}
|
||||
virtual void reconstructExpression( std::string& dest ) const = 0;
|
||||
|
||||
// Only simple binary comparisons can be decomposed.
|
||||
// If more complex check is required then wrap sub-expressions in parentheses.
|
||||
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& );
|
||||
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& );
|
||||
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& );
|
||||
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& );
|
||||
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& );
|
||||
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& );
|
||||
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& );
|
||||
};
|
||||
|
||||
struct AssertionInfo
|
||||
{
|
||||
AssertionInfo() {}
|
||||
@@ -29,11 +50,41 @@ namespace Catch {
|
||||
|
||||
struct AssertionResultData
|
||||
{
|
||||
AssertionResultData() : resultType( ResultWas::Unknown ) {}
|
||||
AssertionResultData() : decomposedExpression( CATCH_NULL )
|
||||
, resultType( ResultWas::Unknown )
|
||||
, negated( false )
|
||||
, parenthesized( false ) {}
|
||||
|
||||
std::string reconstructedExpression;
|
||||
void negate( bool parenthesize ) {
|
||||
negated = !negated;
|
||||
parenthesized = parenthesize;
|
||||
if( resultType == ResultWas::Ok )
|
||||
resultType = ResultWas::ExpressionFailed;
|
||||
else if( resultType == ResultWas::ExpressionFailed )
|
||||
resultType = ResultWas::Ok;
|
||||
}
|
||||
|
||||
std::string const& reconstructExpression() const {
|
||||
if( decomposedExpression != CATCH_NULL ) {
|
||||
decomposedExpression->reconstructExpression( reconstructedExpression );
|
||||
if( parenthesized ) {
|
||||
reconstructedExpression.insert( 0, 1, '(' );
|
||||
reconstructedExpression.append( 1, ')' );
|
||||
}
|
||||
if( negated ) {
|
||||
reconstructedExpression.insert( 0, 1, '!' );
|
||||
}
|
||||
decomposedExpression = CATCH_NULL;
|
||||
}
|
||||
return reconstructedExpression;
|
||||
}
|
||||
|
||||
mutable DecomposedExpression const* decomposedExpression;
|
||||
mutable std::string reconstructedExpression;
|
||||
std::string message;
|
||||
ResultWas::OfType resultType;
|
||||
bool negated;
|
||||
bool parenthesized;
|
||||
};
|
||||
|
||||
class AssertionResult {
|
||||
@@ -60,6 +111,8 @@ namespace Catch {
|
||||
std::string getMessage() const;
|
||||
SourceLineInfo getSourceInfo() const;
|
||||
std::string getTestMacroName() const;
|
||||
void discardDecomposedExpression() const;
|
||||
void expandDecomposedExpression() const;
|
||||
|
||||
protected:
|
||||
AssertionInfo m_info;
|
||||
|
@@ -56,7 +56,7 @@ namespace Catch {
|
||||
|
||||
std::string AssertionResult::getExpression() const {
|
||||
if( isFalseTest( m_info.resultDisposition ) )
|
||||
return "!" + m_info.capturedExpression;
|
||||
return '!' + m_info.capturedExpression;
|
||||
else
|
||||
return m_info.capturedExpression;
|
||||
}
|
||||
@@ -72,7 +72,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
std::string AssertionResult::getExpandedExpression() const {
|
||||
return m_resultData.reconstructedExpression;
|
||||
return m_resultData.reconstructExpression();
|
||||
}
|
||||
|
||||
std::string AssertionResult::getMessage() const {
|
||||
@@ -86,6 +86,14 @@ namespace Catch {
|
||||
return m_info.macroName;
|
||||
}
|
||||
|
||||
void AssertionResult::discardDecomposedExpression() const {
|
||||
m_resultData.decomposedExpression = CATCH_NULL;
|
||||
}
|
||||
|
||||
void AssertionResult::expandDecomposedExpression() const {
|
||||
m_resultData.reconstructExpression();
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
|
||||
|
@@ -33,13 +33,15 @@
|
||||
do { \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
|
||||
try { \
|
||||
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
||||
( __catchResult <= expr ).endExpression(); \
|
||||
} \
|
||||
catch( ... ) { \
|
||||
__catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
|
||||
__catchResult.useActiveException( resultDisposition ); \
|
||||
} \
|
||||
INTERNAL_CATCH_REACT( __catchResult ) \
|
||||
} while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
|
||||
} while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
|
||||
// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
|
||||
@@ -56,7 +58,7 @@
|
||||
do { \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
|
||||
try { \
|
||||
expr; \
|
||||
static_cast<void>(expr); \
|
||||
__catchResult.captureResult( Catch::ResultWas::Ok ); \
|
||||
} \
|
||||
catch( ... ) { \
|
||||
@@ -71,7 +73,7 @@
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
|
||||
if( __catchResult.allowThrows() ) \
|
||||
try { \
|
||||
expr; \
|
||||
static_cast<void>(expr); \
|
||||
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
|
||||
} \
|
||||
catch( ... ) { \
|
||||
@@ -88,7 +90,7 @@
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
|
||||
if( __catchResult.allowThrows() ) \
|
||||
try { \
|
||||
expr; \
|
||||
static_cast<void>(expr); \
|
||||
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
|
||||
} \
|
||||
catch( exceptionType ) { \
|
||||
@@ -129,15 +131,9 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
|
||||
do { \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
|
||||
try { \
|
||||
std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \
|
||||
__catchResult \
|
||||
.setLhs( Catch::toString( arg ) ) \
|
||||
.setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
|
||||
.setOp( "matches" ) \
|
||||
.setResultType( ::Catch::Matchers::matcher.match( arg ) ); \
|
||||
__catchResult.captureExpression(); \
|
||||
__catchResult.captureMatch( arg, matcher, #matcher ); \
|
||||
} catch( ... ) { \
|
||||
__catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
|
||||
} \
|
||||
|
@@ -23,13 +23,14 @@ namespace Catch {
|
||||
config.abortAfter = x;
|
||||
}
|
||||
inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
|
||||
inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); }
|
||||
inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
|
||||
|
||||
inline void addWarning( ConfigData& config, std::string const& _warning ) {
|
||||
if( _warning == "NoAssertions" )
|
||||
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
|
||||
else
|
||||
throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
|
||||
throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' );
|
||||
}
|
||||
inline void setOrder( ConfigData& config, std::string const& order ) {
|
||||
if( startsWith( "declared", order ) )
|
||||
@@ -39,7 +40,7 @@ namespace Catch {
|
||||
else if( startsWith( "random", order ) )
|
||||
config.runOrder = RunTests::InRandomOrder;
|
||||
else
|
||||
throw std::runtime_error( "Unrecognised ordering: '" + order + "'" );
|
||||
throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' );
|
||||
}
|
||||
inline void setRngSeed( ConfigData& config, std::string const& seed ) {
|
||||
if( seed == "time" ) {
|
||||
@@ -62,6 +63,21 @@ namespace Catch {
|
||||
? ShowDurations::Always
|
||||
: ShowDurations::Never;
|
||||
}
|
||||
inline void setUseColour( ConfigData& config, std::string const& value ) {
|
||||
std::string mode = toLower( value );
|
||||
|
||||
if( mode == "yes" )
|
||||
config.useColour = UseColour::Yes;
|
||||
else if( mode == "no" )
|
||||
config.useColour = UseColour::No;
|
||||
else if( mode == "auto" )
|
||||
config.useColour = UseColour::Auto;
|
||||
else
|
||||
throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
|
||||
}
|
||||
inline void forceColour( ConfigData& config ) {
|
||||
config.useColour = UseColour::Yes;
|
||||
}
|
||||
inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
|
||||
std::ifstream f( _filename.c_str() );
|
||||
if( !f.is_open() )
|
||||
@@ -70,8 +86,11 @@ namespace Catch {
|
||||
std::string line;
|
||||
while( std::getline( f, line ) ) {
|
||||
line = trim(line);
|
||||
if( !line.empty() && !startsWith( line, "#" ) )
|
||||
addTestOrTags( config, "\"" + line + "\"," );
|
||||
if( !line.empty() && !startsWith( line, '#' ) ) {
|
||||
if( !startsWith( line, '"' ) )
|
||||
line = '"' + line + '"';
|
||||
addTestOrTags( config, line + ',' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +167,7 @@ namespace Catch {
|
||||
|
||||
cli["-d"]["--durations"]
|
||||
.describe( "show test durations" )
|
||||
.bind( &setShowDurations, "yes/no" );
|
||||
.bind( &setShowDurations, "yes|no" );
|
||||
|
||||
cli["-f"]["--input-file"]
|
||||
.describe( "load test names to run from a file" )
|
||||
@@ -158,12 +177,16 @@ namespace Catch {
|
||||
.describe( "adds a tag for the filename" )
|
||||
.bind( &ConfigData::filenamesAsTags );
|
||||
|
||||
cli["-c"]["--section"]
|
||||
.describe( "specify section to run" )
|
||||
.bind( &addSectionToRun, "section name" );
|
||||
|
||||
// Less common commands which don't have a short form
|
||||
cli["--list-test-names-only"]
|
||||
.describe( "list all/matching test cases names only" )
|
||||
.bind( &ConfigData::listTestNamesOnly );
|
||||
|
||||
cli["--list-reporters"]
|
||||
cli["--list-reporters"]
|
||||
.describe( "list all reporters" )
|
||||
.bind( &ConfigData::listReporters );
|
||||
|
||||
@@ -176,9 +199,13 @@ namespace Catch {
|
||||
.bind( &setRngSeed, "'time'|number" );
|
||||
|
||||
cli["--force-colour"]
|
||||
.describe( "force colourised output" )
|
||||
.bind( &ConfigData::forceColour );
|
||||
|
||||
.describe( "force colourised output (deprecated)" )
|
||||
.bind( &forceColour );
|
||||
|
||||
cli["--use-colour"]
|
||||
.describe( "should output be colourised" )
|
||||
.bind( &setUseColour, "yes|no" );
|
||||
|
||||
return cli;
|
||||
}
|
||||
|
||||
|
@@ -8,9 +8,15 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
|
||||
|
||||
#include "catch_compiler_capabilities.h"
|
||||
|
||||
#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
|
||||
#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
|
||||
#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
|
||||
#ifdef CATCH_CONFIG_COUNTER
|
||||
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
|
||||
#else
|
||||
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
|
||||
#endif
|
||||
|
||||
#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
|
||||
#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
|
||||
@@ -22,14 +28,14 @@
|
||||
#include "catch_compiler_capabilities.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
|
||||
struct IConfig;
|
||||
|
||||
struct CaseSensitive { enum Choice {
|
||||
Yes,
|
||||
No
|
||||
}; };
|
||||
|
||||
|
||||
class NonCopyable {
|
||||
#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
|
||||
NonCopyable( NonCopyable const& ) = delete;
|
||||
@@ -73,7 +79,10 @@ namespace Catch {
|
||||
}
|
||||
|
||||
bool startsWith( std::string const& s, std::string const& prefix );
|
||||
bool startsWith( std::string const& s, char prefix );
|
||||
bool endsWith( std::string const& s, std::string const& suffix );
|
||||
bool endsWith( std::string const& s, char suffix );
|
||||
bool contains( std::string const& s, std::string const& infix );
|
||||
bool contains( std::string const& s, std::string const& infix );
|
||||
void toLowerInPlace( std::string& s );
|
||||
std::string toLower( std::string const& s );
|
||||
@@ -93,8 +102,8 @@ namespace Catch {
|
||||
|
||||
SourceLineInfo();
|
||||
SourceLineInfo( char const* _file, std::size_t _line );
|
||||
SourceLineInfo( SourceLineInfo const& other );
|
||||
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
|
||||
SourceLineInfo(SourceLineInfo const& other) = default;
|
||||
SourceLineInfo( SourceLineInfo && ) = default;
|
||||
SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
|
||||
SourceLineInfo& operator = ( SourceLineInfo && ) = default;
|
||||
@@ -103,7 +112,7 @@ namespace Catch {
|
||||
bool operator == ( SourceLineInfo const& other ) const;
|
||||
bool operator < ( SourceLineInfo const& other ) const;
|
||||
|
||||
std::string file;
|
||||
char const* file;
|
||||
std::size_t line;
|
||||
};
|
||||
|
||||
@@ -118,7 +127,7 @@ namespace Catch {
|
||||
|
||||
void seedRng( IConfig const& config );
|
||||
unsigned int rngSeed();
|
||||
|
||||
|
||||
// Use this in variadic streaming macros to allow
|
||||
// >> +StreamEndStop
|
||||
// as well as
|
||||
|
@@ -10,19 +10,33 @@
|
||||
|
||||
#include "catch_common.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
bool startsWith( std::string const& s, std::string const& prefix ) {
|
||||
return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
|
||||
return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
|
||||
}
|
||||
bool startsWith( std::string const& s, char prefix ) {
|
||||
return !s.empty() && s[0] == prefix;
|
||||
}
|
||||
bool endsWith( std::string const& s, std::string const& suffix ) {
|
||||
return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
|
||||
return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
|
||||
}
|
||||
bool endsWith( std::string const& s, char suffix ) {
|
||||
return !s.empty() && s[s.size()-1] == suffix;
|
||||
}
|
||||
bool contains( std::string const& s, std::string const& infix ) {
|
||||
return s.find( infix ) != std::string::npos;
|
||||
}
|
||||
bool contains( std::string const& s, char infix ) {
|
||||
return s.find(infix) != std::string::npos;
|
||||
}
|
||||
char toLowerCh(char c) {
|
||||
return static_cast<char>( ::tolower( c ) );
|
||||
}
|
||||
void toLowerInPlace( std::string& s ) {
|
||||
std::transform( s.begin(), s.end(), s.begin(), ::tolower );
|
||||
std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
|
||||
}
|
||||
std::string toLower( std::string const& s ) {
|
||||
std::string lc = s;
|
||||
@@ -34,9 +48,9 @@ namespace Catch {
|
||||
std::string::size_type start = str.find_first_not_of( whitespaceChars );
|
||||
std::string::size_type end = str.find_last_not_of( whitespaceChars );
|
||||
|
||||
return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
|
||||
return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
|
||||
}
|
||||
|
||||
|
||||
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
|
||||
bool replaced = false;
|
||||
std::size_t i = str.find( replaceThis );
|
||||
@@ -50,36 +64,32 @@ namespace Catch {
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
|
||||
pluralise::pluralise( std::size_t count, std::string const& label )
|
||||
: m_count( count ),
|
||||
m_label( label )
|
||||
{}
|
||||
|
||||
std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
|
||||
os << pluraliser.m_count << " " << pluraliser.m_label;
|
||||
os << pluraliser.m_count << ' ' << pluraliser.m_label;
|
||||
if( pluraliser.m_count != 1 )
|
||||
os << "s";
|
||||
os << 's';
|
||||
return os;
|
||||
}
|
||||
|
||||
SourceLineInfo::SourceLineInfo() : line( 0 ){}
|
||||
SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){}
|
||||
SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
|
||||
: file( _file ),
|
||||
line( _line )
|
||||
{}
|
||||
SourceLineInfo::SourceLineInfo( SourceLineInfo const& other )
|
||||
: file( other.file ),
|
||||
line( other.line )
|
||||
{}
|
||||
bool SourceLineInfo::empty() const {
|
||||
return file.empty();
|
||||
return file[0] == '\0';
|
||||
}
|
||||
bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
|
||||
return line == other.line && file == other.file;
|
||||
return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
|
||||
}
|
||||
bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
|
||||
return line < other.line || ( line == other.line && file < other.file );
|
||||
return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
|
||||
}
|
||||
|
||||
void seedRng( IConfig const& config ) {
|
||||
@@ -92,16 +102,16 @@ namespace Catch {
|
||||
|
||||
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
|
||||
#ifndef __GNUG__
|
||||
os << info.file << "(" << info.line << ")";
|
||||
os << info.file << '(' << info.line << ')';
|
||||
#else
|
||||
os << info.file << ":" << info.line;
|
||||
os << info.file << ':' << info.line;
|
||||
#endif
|
||||
return os;
|
||||
}
|
||||
|
||||
void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
|
||||
std::ostringstream oss;
|
||||
oss << locationInfo << ": Internal Catch error: '" << message << "'";
|
||||
oss << locationInfo << ": Internal Catch error: '" << message << '\'';
|
||||
if( alwaysTrue() )
|
||||
throw std::logic_error( oss.str() );
|
||||
}
|
||||
|
@@ -19,11 +19,14 @@
|
||||
// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
|
||||
// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
|
||||
// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
|
||||
// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported?
|
||||
// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported?
|
||||
|
||||
// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
|
||||
|
||||
// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
|
||||
|
||||
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
|
||||
// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
|
||||
// ****************
|
||||
// Note to maintainers: if new toggles are added please document them
|
||||
// in configuration.md, too
|
||||
@@ -36,6 +39,18 @@
|
||||
|
||||
// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
# if __cplusplus >= 201103L
|
||||
# define CATCH_CPP11_OR_GREATER
|
||||
# endif
|
||||
|
||||
# if __cplusplus >= 201402L
|
||||
# define CATCH_CPP14_OR_GREATER
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
|
||||
# if __has_feature(cxx_nullptr)
|
||||
@@ -46,6 +61,10 @@
|
||||
# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
|
||||
# endif
|
||||
|
||||
# if defined(CATCH_CPP11_OR_GREATER)
|
||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
|
||||
# endif
|
||||
|
||||
#endif // __clang__
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -73,9 +92,13 @@
|
||||
// GCC
|
||||
#ifdef __GNUC__
|
||||
|
||||
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
|
||||
#endif
|
||||
# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
|
||||
# endif
|
||||
|
||||
# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER)
|
||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
|
||||
# endif
|
||||
|
||||
// - otherwise more recent versions define __cplusplus >= 201103L
|
||||
// and will get picked up below
|
||||
@@ -87,6 +110,8 @@
|
||||
// Visual C++
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
|
||||
|
||||
#if (_MSC_VER >= 1600)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
|
||||
# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
|
||||
@@ -95,6 +120,8 @@
|
||||
#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
|
||||
#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
|
||||
#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
|
||||
#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
|
||||
#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
|
||||
#endif
|
||||
|
||||
#endif // _MSC_VER
|
||||
@@ -111,13 +138,20 @@
|
||||
|
||||
#endif
|
||||
|
||||
// Use __COUNTER__ if the compiler supports it
|
||||
#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
|
||||
( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
|
||||
( defined __clang__ && __clang_major__ >= 3 )
|
||||
|
||||
#define CATCH_INTERNAL_CONFIG_COUNTER
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// C++ language feature support
|
||||
|
||||
// catch all support for C++11
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
|
||||
# define CATCH_CPP11_OR_GREATER
|
||||
#if defined(CATCH_CPP11_OR_GREATER)
|
||||
|
||||
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
|
||||
@@ -153,7 +187,12 @@
|
||||
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
|
||||
# endif
|
||||
|
||||
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
|
||||
# endif
|
||||
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS)
|
||||
# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
|
||||
# endif
|
||||
|
||||
#endif // __cplusplus >= 201103L
|
||||
|
||||
@@ -176,16 +215,34 @@
|
||||
#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
|
||||
# define CATCH_CONFIG_VARIADIC_MACROS
|
||||
#endif
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
|
||||
# define CATCH_CONFIG_CPP11_LONG_LONG
|
||||
#endif
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
|
||||
# define CATCH_CONFIG_CPP11_OVERRIDE
|
||||
#endif
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
|
||||
# define CATCH_CONFIG_CPP11_UNIQUE_PTR
|
||||
#endif
|
||||
// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
|
||||
// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
|
||||
// This does not affect compilation
|
||||
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
|
||||
# define CATCH_CONFIG_COUNTER
|
||||
#endif
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
|
||||
# define CATCH_CONFIG_CPP11_SHUFFLE
|
||||
#endif
|
||||
# if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11)
|
||||
# define CATCH_CONFIG_CPP11_TYPE_TRAITS
|
||||
# endif
|
||||
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
|
||||
# define CATCH_CONFIG_WINDOWS_SEH
|
||||
#endif
|
||||
|
||||
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
|
||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
||||
#endif
|
||||
|
||||
// noexcept support:
|
||||
#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
|
||||
|
@@ -37,14 +37,14 @@ namespace Catch {
|
||||
noThrow( false ),
|
||||
showHelp( false ),
|
||||
showInvisibles( false ),
|
||||
forceColour( false ),
|
||||
filenamesAsTags( false ),
|
||||
abortAfter( -1 ),
|
||||
rngSeed( 0 ),
|
||||
verbosity( Verbosity::Normal ),
|
||||
warnings( WarnAbout::Nothing ),
|
||||
showDurations( ShowDurations::DefaultForReporter ),
|
||||
runOrder( RunTests::InDeclarationOrder )
|
||||
runOrder( RunTests::InDeclarationOrder ),
|
||||
useColour( UseColour::Auto )
|
||||
{}
|
||||
|
||||
bool listTests;
|
||||
@@ -57,7 +57,6 @@ namespace Catch {
|
||||
bool noThrow;
|
||||
bool showHelp;
|
||||
bool showInvisibles;
|
||||
bool forceColour;
|
||||
bool filenamesAsTags;
|
||||
|
||||
int abortAfter;
|
||||
@@ -67,6 +66,7 @@ namespace Catch {
|
||||
WarnAbout::What warnings;
|
||||
ShowDurations::OrNot showDurations;
|
||||
RunTests::InWhatOrder runOrder;
|
||||
UseColour::YesOrNo useColour;
|
||||
|
||||
std::string outputFilename;
|
||||
std::string name;
|
||||
@@ -74,6 +74,7 @@ namespace Catch {
|
||||
|
||||
std::vector<std::string> reporterNames;
|
||||
std::vector<std::string> testsOrTags;
|
||||
std::vector<std::string> sectionsToRun;
|
||||
};
|
||||
|
||||
|
||||
@@ -85,12 +86,11 @@ namespace Catch {
|
||||
public:
|
||||
|
||||
Config()
|
||||
: m_os( Catch::cout().rdbuf() )
|
||||
{}
|
||||
|
||||
Config( ConfigData const& data )
|
||||
: m_data( data ),
|
||||
m_os( Catch::cout().rdbuf() )
|
||||
m_stream( openStream() )
|
||||
{
|
||||
if( !data.testsOrTags.empty() ) {
|
||||
TestSpecParser parser( ITagAliasRegistry::get() );
|
||||
@@ -101,12 +101,6 @@ namespace Catch {
|
||||
}
|
||||
|
||||
virtual ~Config() {
|
||||
m_os.rdbuf( Catch::cout().rdbuf() );
|
||||
m_stream.release();
|
||||
}
|
||||
|
||||
void setFilename( std::string const& filename ) {
|
||||
m_data.outputFilename = filename;
|
||||
}
|
||||
|
||||
std::string const& getFilename() const {
|
||||
@@ -122,18 +116,8 @@ namespace Catch {
|
||||
|
||||
bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
|
||||
|
||||
void setStreamBuf( std::streambuf* buf ) {
|
||||
m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() );
|
||||
}
|
||||
|
||||
void useStream( std::string const& streamName ) {
|
||||
Stream stream = createStream( streamName );
|
||||
setStreamBuf( stream.streamBuf );
|
||||
m_stream.release();
|
||||
m_stream = stream;
|
||||
}
|
||||
|
||||
std::vector<std::string> getReporterNames() const { return m_data.reporterNames; }
|
||||
std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; }
|
||||
std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; }
|
||||
|
||||
int abortAfter() const { return m_data.abortAfter; }
|
||||
|
||||
@@ -144,24 +128,35 @@ namespace Catch {
|
||||
|
||||
// IConfig interface
|
||||
virtual bool allowThrows() const { return !m_data.noThrow; }
|
||||
virtual std::ostream& stream() const { return m_os; }
|
||||
virtual std::ostream& stream() const { return m_stream->stream(); }
|
||||
virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
|
||||
virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
|
||||
virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
|
||||
virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
|
||||
virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
|
||||
virtual unsigned int rngSeed() const { return m_data.rngSeed; }
|
||||
virtual bool forceColour() const { return m_data.forceColour; }
|
||||
virtual UseColour::YesOrNo useColour() const { return m_data.useColour; }
|
||||
|
||||
private:
|
||||
|
||||
IStream const* openStream() {
|
||||
if( m_data.outputFilename.empty() )
|
||||
return new CoutStream();
|
||||
else if( m_data.outputFilename[0] == '%' ) {
|
||||
if( m_data.outputFilename == "%debug" )
|
||||
return new DebugOutStream();
|
||||
else
|
||||
throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
|
||||
}
|
||||
else
|
||||
return new FileStream( m_data.outputFilename );
|
||||
}
|
||||
ConfigData m_data;
|
||||
|
||||
Stream m_stream;
|
||||
mutable std::ostream m_os;
|
||||
CATCH_AUTO_PTR( IStream const ) m_stream;
|
||||
TestSpec m_testSpec;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
|
||||
|
@@ -41,15 +41,7 @@ namespace Catch {
|
||||
|
||||
#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#ifdef __AFXDLL
|
||||
#include <AfxWin.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include "catch_windows_h_proxy.h"
|
||||
|
||||
namespace Catch {
|
||||
namespace {
|
||||
@@ -95,7 +87,18 @@ namespace {
|
||||
|
||||
IColourImpl* platformColourInstance() {
|
||||
static Win32ColourImpl s_instance;
|
||||
return &s_instance;
|
||||
|
||||
Ptr<IConfig const> config = getCurrentContext().getConfig();
|
||||
UseColour::YesOrNo colourMode = config
|
||||
? config->useColour()
|
||||
: UseColour::Auto;
|
||||
if( colourMode == UseColour::Auto )
|
||||
colourMode = !isDebuggerActive()
|
||||
? UseColour::Yes
|
||||
: UseColour::No;
|
||||
return colourMode == UseColour::Yes
|
||||
? &s_instance
|
||||
: NoColourImpl::instance();
|
||||
}
|
||||
|
||||
} // end anon namespace
|
||||
@@ -120,7 +123,7 @@ namespace {
|
||||
case Colour::White: return setColour( "[0m" );
|
||||
case Colour::Red: return setColour( "[0;31m" );
|
||||
case Colour::Green: return setColour( "[0;32m" );
|
||||
case Colour::Blue: return setColour( "[0:34m" );
|
||||
case Colour::Blue: return setColour( "[0;34m" );
|
||||
case Colour::Cyan: return setColour( "[0;36m" );
|
||||
case Colour::Yellow: return setColour( "[0;33m" );
|
||||
case Colour::Grey: return setColour( "[1;30m" );
|
||||
@@ -146,7 +149,14 @@ namespace {
|
||||
|
||||
IColourImpl* platformColourInstance() {
|
||||
Ptr<IConfig const> config = getCurrentContext().getConfig();
|
||||
return (config && config->forceColour()) || isatty(STDOUT_FILENO)
|
||||
UseColour::YesOrNo colourMode = config
|
||||
? config->useColour()
|
||||
: UseColour::Auto;
|
||||
if( colourMode == UseColour::Auto )
|
||||
colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
|
||||
? UseColour::Yes
|
||||
: UseColour::No;
|
||||
return colourMode == UseColour::Yes
|
||||
? PosixColourImpl::instance()
|
||||
: NoColourImpl::instance();
|
||||
}
|
||||
@@ -171,9 +181,7 @@ namespace Catch {
|
||||
Colour::~Colour(){ if( !m_moved ) use( None ); }
|
||||
|
||||
void Colour::use( Code _colourCode ) {
|
||||
static IColourImpl* impl = isDebuggerActive()
|
||||
? NoColourImpl::instance()
|
||||
: platformColourInstance();
|
||||
static IColourImpl* impl = platformColourInstance();
|
||||
impl->use( _colourCode );
|
||||
}
|
||||
|
||||
|
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "catch_context.h"
|
||||
#include "catch_stream.hpp"
|
||||
#include "catch_common.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@@ -21,6 +22,11 @@ namespace Catch {
|
||||
Context( Context const& );
|
||||
void operator=( Context const& );
|
||||
|
||||
public:
|
||||
virtual ~Context() {
|
||||
deleteAllValues( m_generatorsByTestName );
|
||||
}
|
||||
|
||||
public: // IContext
|
||||
virtual IResultCapture* getResultCapture() {
|
||||
return m_resultCapture;
|
||||
@@ -95,14 +101,6 @@ namespace Catch {
|
||||
return getCurrentMutableContext();
|
||||
}
|
||||
|
||||
Stream createStream( std::string const& streamName ) {
|
||||
if( streamName == "stdout" ) return Stream( Catch::cout().rdbuf(), false );
|
||||
if( streamName == "stderr" ) return Stream( Catch::cerr().rdbuf(), false );
|
||||
if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
|
||||
|
||||
throw std::domain_error( "Unknown stream: " + streamName );
|
||||
}
|
||||
|
||||
void cleanUpContext() {
|
||||
delete currentContext;
|
||||
currentContext = CATCH_NULL;
|
||||
|
@@ -23,27 +23,36 @@ namespace Catch{
|
||||
|
||||
// The following code snippet based on:
|
||||
// http://cocoawithlove.com/2008/03/break-into-debugger.html
|
||||
#ifdef DEBUG
|
||||
#if defined(__ppc64__) || defined(__ppc__)
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() \
|
||||
if( Catch::isDebuggerActive() ) { \
|
||||
__asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
|
||||
: : : "memory","r0","r3","r4" ); \
|
||||
}
|
||||
#else
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
|
||||
#endif
|
||||
#if defined(__ppc64__) || defined(__ppc__)
|
||||
#define CATCH_TRAP() \
|
||||
__asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
|
||||
: : : "memory","r0","r3","r4" )
|
||||
#else
|
||||
#define CATCH_TRAP() __asm__("int $3\n" : : )
|
||||
#endif
|
||||
|
||||
#elif defined(CATCH_PLATFORM_LINUX)
|
||||
// If we can use inline assembler, do it because this allows us to break
|
||||
// directly at the location of the failing check instead of breaking inside
|
||||
// raise() called from it, i.e. one stack frame below.
|
||||
#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
|
||||
#define CATCH_TRAP() asm volatile ("int $3")
|
||||
#else // Fall back to the generic way.
|
||||
#include <signal.h>
|
||||
|
||||
#define CATCH_TRAP() raise(SIGTRAP)
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
|
||||
#define CATCH_TRAP() __debugbreak()
|
||||
#elif defined(__MINGW32__)
|
||||
extern "C" __declspec(dllimport) void __stdcall DebugBreak();
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
|
||||
#define CATCH_TRAP() DebugBreak()
|
||||
#endif
|
||||
|
||||
#ifndef CATCH_BREAK_INTO_DEBUGGER
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
|
||||
#ifdef CATCH_TRAP
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
|
||||
#else
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
||||
|
@@ -61,6 +61,33 @@
|
||||
}
|
||||
} // namespace Catch
|
||||
|
||||
#elif defined(CATCH_PLATFORM_LINUX)
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
namespace Catch{
|
||||
// The standard POSIX way of detecting a debugger is to attempt to
|
||||
// ptrace() the process, but this needs to be done from a child and not
|
||||
// this process itself to still allow attaching to this process later
|
||||
// if wanted, so is rather heavy. Under Linux we have the PID of the
|
||||
// "debugger" (which doesn't need to be gdb, of course, it could also
|
||||
// be strace, for example) in /proc/$PID/status, so just get it from
|
||||
// there instead.
|
||||
bool isDebuggerActive(){
|
||||
std::ifstream in("/proc/self/status");
|
||||
for( std::string line; std::getline(in, line); ) {
|
||||
static const int PREFIX_LEN = 11;
|
||||
if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
|
||||
// We're traced if the PID is not 0 and no other PID starts
|
||||
// with 0 digit, so it's enough to check for just a single
|
||||
// character.
|
||||
return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
} // namespace Catch
|
||||
#elif defined(_MSC_VER)
|
||||
extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
|
||||
namespace Catch {
|
||||
|
@@ -11,8 +11,9 @@
|
||||
#ifndef __OBJC__
|
||||
|
||||
// Standard C/C++ main entry point
|
||||
int main (int argc, char * const argv[]) {
|
||||
return Catch::Session().run( argc, argv );
|
||||
int main (int argc, char * argv[]) {
|
||||
int result = Catch::Session().run( argc, argv );
|
||||
return ( result < 0xff ? result : 0xff );
|
||||
}
|
||||
|
||||
#else // __OBJC__
|
||||
@@ -30,7 +31,7 @@ int main (int argc, char * const argv[]) {
|
||||
[pool drain];
|
||||
#endif
|
||||
|
||||
return result;
|
||||
return ( result < 0xff ? result : 0xff );
|
||||
}
|
||||
|
||||
#endif // __OBJC__
|
||||
|
@@ -52,37 +52,37 @@ namespace Internal {
|
||||
template<typename T1, typename T2>
|
||||
struct Evaluator<T1, T2, IsEqualTo> {
|
||||
static bool evaluate( T1 const& lhs, T2 const& rhs) {
|
||||
return opCast( lhs ) == opCast( rhs );
|
||||
return bool( opCast( lhs ) == opCast( rhs ) );
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Evaluator<T1, T2, IsNotEqualTo> {
|
||||
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
||||
return opCast( lhs ) != opCast( rhs );
|
||||
return bool( opCast( lhs ) != opCast( rhs ) );
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Evaluator<T1, T2, IsLessThan> {
|
||||
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
||||
return opCast( lhs ) < opCast( rhs );
|
||||
return bool( opCast( lhs ) < opCast( rhs ) );
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Evaluator<T1, T2, IsGreaterThan> {
|
||||
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
||||
return opCast( lhs ) > opCast( rhs );
|
||||
return bool( opCast( lhs ) > opCast( rhs ) );
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
|
||||
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
||||
return opCast( lhs ) >= opCast( rhs );
|
||||
return bool( opCast( lhs ) >= opCast( rhs ) );
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
|
||||
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
||||
return opCast( lhs ) <= opCast( rhs );
|
||||
return bool( opCast( lhs ) <= opCast( rhs ) );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace Internal {
|
||||
template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
|
||||
}
|
||||
|
||||
|
||||
// unsigned long long to X
|
||||
template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
|
||||
@@ -188,7 +188,7 @@ namespace Internal {
|
||||
template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
|
||||
}
|
||||
|
||||
|
||||
// pointer to long long (when comparing against NULL)
|
||||
template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
|
||||
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
|
||||
@@ -197,7 +197,7 @@ namespace Internal {
|
||||
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
|
||||
}
|
||||
#endif // CATCH_CONFIG_CPP11_LONG_LONG
|
||||
|
||||
|
||||
#ifdef CATCH_CONFIG_CPP11_NULLPTR
|
||||
// pointer to nullptr_t (when comparing against nullptr)
|
||||
template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
|
||||
|
@@ -32,13 +32,13 @@ namespace Catch {
|
||||
#ifdef __OBJC__
|
||||
// In Objective-C try objective-c exceptions first
|
||||
@try {
|
||||
throw;
|
||||
return tryTranslators();
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
return Catch::toString( [exception description] );
|
||||
}
|
||||
#else
|
||||
throw;
|
||||
return tryTranslators();
|
||||
#endif
|
||||
}
|
||||
catch( TestFailureException& ) {
|
||||
@@ -54,20 +54,15 @@ namespace Catch {
|
||||
return msg;
|
||||
}
|
||||
catch(...) {
|
||||
return tryTranslators( m_translators.begin() );
|
||||
return "Unknown exception";
|
||||
}
|
||||
}
|
||||
|
||||
std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
|
||||
if( it == m_translators.end() )
|
||||
return "Unknown exception";
|
||||
|
||||
try {
|
||||
return (*it)->translate();
|
||||
}
|
||||
catch(...) {
|
||||
return tryTranslators( it+1 );
|
||||
}
|
||||
std::string tryTranslators() const {
|
||||
if( m_translators.empty() )
|
||||
throw;
|
||||
else
|
||||
return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -14,90 +14,155 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
// Wraps the LHS of an expression and captures the operator and RHS (if any) -
|
||||
// wrapping them all in a ResultBuilder object
|
||||
template<typename T>
|
||||
class ExpressionLhs {
|
||||
ExpressionLhs& operator = ( ExpressionLhs const& );
|
||||
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
|
||||
ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
|
||||
# endif
|
||||
template<typename LhsT, Internal::Operator Op, typename RhsT>
|
||||
class BinaryExpression;
|
||||
|
||||
template<typename ArgT, typename MatcherT>
|
||||
class MatchExpression;
|
||||
|
||||
// Wraps the LHS of an expression and overloads comparison operators
|
||||
// for also capturing those and RHS (if any)
|
||||
template<typename T>
|
||||
class ExpressionLhs : public DecomposedExpression {
|
||||
public:
|
||||
ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {}
|
||||
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
|
||||
ExpressionLhs( ExpressionLhs const& ) = default;
|
||||
ExpressionLhs( ExpressionLhs && ) = default;
|
||||
# endif
|
||||
ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
|
||||
|
||||
template<typename RhsT>
|
||||
ResultBuilder& operator == ( RhsT const& rhs ) {
|
||||
BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
|
||||
operator == ( RhsT const& rhs ) {
|
||||
return captureExpression<Internal::IsEqualTo>( rhs );
|
||||
}
|
||||
|
||||
template<typename RhsT>
|
||||
ResultBuilder& operator != ( RhsT const& rhs ) {
|
||||
BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&>
|
||||
operator != ( RhsT const& rhs ) {
|
||||
return captureExpression<Internal::IsNotEqualTo>( rhs );
|
||||
}
|
||||
|
||||
template<typename RhsT>
|
||||
ResultBuilder& operator < ( RhsT const& rhs ) {
|
||||
BinaryExpression<T, Internal::IsLessThan, RhsT const&>
|
||||
operator < ( RhsT const& rhs ) {
|
||||
return captureExpression<Internal::IsLessThan>( rhs );
|
||||
}
|
||||
|
||||
template<typename RhsT>
|
||||
ResultBuilder& operator > ( RhsT const& rhs ) {
|
||||
BinaryExpression<T, Internal::IsGreaterThan, RhsT const&>
|
||||
operator > ( RhsT const& rhs ) {
|
||||
return captureExpression<Internal::IsGreaterThan>( rhs );
|
||||
}
|
||||
|
||||
template<typename RhsT>
|
||||
ResultBuilder& operator <= ( RhsT const& rhs ) {
|
||||
BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&>
|
||||
operator <= ( RhsT const& rhs ) {
|
||||
return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
|
||||
}
|
||||
|
||||
template<typename RhsT>
|
||||
ResultBuilder& operator >= ( RhsT const& rhs ) {
|
||||
BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&>
|
||||
operator >= ( RhsT const& rhs ) {
|
||||
return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
|
||||
}
|
||||
|
||||
ResultBuilder& operator == ( bool rhs ) {
|
||||
BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) {
|
||||
return captureExpression<Internal::IsEqualTo>( rhs );
|
||||
}
|
||||
|
||||
ResultBuilder& operator != ( bool rhs ) {
|
||||
BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) {
|
||||
return captureExpression<Internal::IsNotEqualTo>( rhs );
|
||||
}
|
||||
|
||||
void endExpression() {
|
||||
bool value = m_lhs ? true : false;
|
||||
m_truthy = m_lhs ? true : false;
|
||||
m_rb
|
||||
.setLhs( Catch::toString( value ) )
|
||||
.setResultType( value )
|
||||
.endExpression();
|
||||
.setResultType( m_truthy )
|
||||
.endExpression( *this );
|
||||
}
|
||||
|
||||
// Only simple binary expressions are allowed on the LHS.
|
||||
// If more complex compositions are required then place the sub expression in parentheses
|
||||
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
|
||||
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
|
||||
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
|
||||
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
|
||||
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
|
||||
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
|
||||
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
|
||||
dest = Catch::toString( m_truthy );
|
||||
}
|
||||
|
||||
private:
|
||||
template<Internal::Operator Op, typename RhsT>
|
||||
ResultBuilder& captureExpression( RhsT const& rhs ) {
|
||||
return m_rb
|
||||
.setResultType( Internal::compare<Op>( m_lhs, rhs ) )
|
||||
.setLhs( Catch::toString( m_lhs ) )
|
||||
.setRhs( Catch::toString( rhs ) )
|
||||
.setOp( Internal::OperatorTraits<Op>::getName() );
|
||||
BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const {
|
||||
return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs );
|
||||
}
|
||||
|
||||
template<Internal::Operator Op>
|
||||
BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const {
|
||||
return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs );
|
||||
}
|
||||
|
||||
private:
|
||||
ResultBuilder& m_rb;
|
||||
T m_lhs;
|
||||
bool m_truthy;
|
||||
};
|
||||
|
||||
template<typename LhsT, Internal::Operator Op, typename RhsT>
|
||||
class BinaryExpression : public DecomposedExpression {
|
||||
public:
|
||||
BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs )
|
||||
: m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {}
|
||||
|
||||
void endExpression() const {
|
||||
m_rb
|
||||
.setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
|
||||
.endExpression( *this );
|
||||
}
|
||||
|
||||
virtual bool isBinaryExpression() const CATCH_OVERRIDE {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
|
||||
std::string lhs = Catch::toString( m_lhs );
|
||||
std::string rhs = Catch::toString( m_rhs );
|
||||
char delim = lhs.size() + rhs.size() < 40 &&
|
||||
lhs.find('\n') == std::string::npos &&
|
||||
rhs.find('\n') == std::string::npos ? ' ' : '\n';
|
||||
dest.reserve( 7 + lhs.size() + rhs.size() );
|
||||
// 2 for spaces around operator
|
||||
// 2 for operator
|
||||
// 2 for parentheses (conditionally added later)
|
||||
// 1 for negation (conditionally added later)
|
||||
dest = lhs;
|
||||
dest += delim;
|
||||
dest += Internal::OperatorTraits<Op>::getName();
|
||||
dest += delim;
|
||||
dest += rhs;
|
||||
}
|
||||
|
||||
private:
|
||||
ResultBuilder& m_rb;
|
||||
LhsT m_lhs;
|
||||
RhsT m_rhs;
|
||||
};
|
||||
|
||||
template<typename ArgT, typename MatcherT>
|
||||
class MatchExpression : public DecomposedExpression {
|
||||
public:
|
||||
MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString )
|
||||
: m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {}
|
||||
|
||||
virtual bool isBinaryExpression() const CATCH_OVERRIDE {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
|
||||
std::string matcherAsString = m_matcher.toString();
|
||||
dest = Catch::toString( m_arg );
|
||||
dest += ' ';
|
||||
if( matcherAsString == Detail::unprintableString )
|
||||
dest += m_matcherString;
|
||||
else
|
||||
dest += matcherAsString;
|
||||
}
|
||||
|
||||
private:
|
||||
ArgT m_arg;
|
||||
MatcherT m_matcher;
|
||||
char const* m_matcherString;
|
||||
};
|
||||
|
||||
} // end namespace Catch
|
||||
|
@@ -12,35 +12,105 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
// Report the error condition then exit the process
|
||||
inline void fatal( std::string const& message, int exitCode ) {
|
||||
// Report the error condition
|
||||
inline void reportFatal( std::string const& message ) {
|
||||
IContext& context = Catch::getCurrentContext();
|
||||
IResultCapture* resultCapture = context.getResultCapture();
|
||||
resultCapture->handleFatalErrorCondition( message );
|
||||
|
||||
if( Catch::alwaysTrue() ) // avoids "no return" warnings
|
||||
exit( exitCode );
|
||||
}
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
||||
#include "catch_windows_h_proxy.h"
|
||||
|
||||
# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
|
||||
|
||||
namespace Catch {
|
||||
struct FatalConditionHandler {
|
||||
void reset() {}
|
||||
};
|
||||
}
|
||||
|
||||
# else // CATCH_CONFIG_WINDOWS_SEH is defined
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct SignalDefs { DWORD id; const char* name; };
|
||||
extern SignalDefs signalDefs[];
|
||||
// There is no 1-1 mapping between signals and windows exceptions.
|
||||
// Windows can easily distinguish between SO and SigSegV,
|
||||
// but SigInt, SigTerm, etc are handled differently.
|
||||
SignalDefs signalDefs[] = {
|
||||
{ EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
|
||||
{ EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
|
||||
{ EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
|
||||
{ EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
|
||||
};
|
||||
|
||||
struct FatalConditionHandler {
|
||||
void reset() {}
|
||||
};
|
||||
|
||||
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
|
||||
for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
|
||||
if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
|
||||
reset();
|
||||
reportFatal(signalDefs[i].name);
|
||||
}
|
||||
}
|
||||
// If its not an exception we care about, pass it along.
|
||||
// This stops us from eating debugger breaks etc.
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
FatalConditionHandler() {
|
||||
isSet = true;
|
||||
// 32k seems enough for Catch to handle stack overflow,
|
||||
// but the value was found experimentally, so there is no strong guarantee
|
||||
guaranteeSize = 32 * 1024;
|
||||
exceptionHandlerHandle = CATCH_NULL;
|
||||
// Register as first handler in current chain
|
||||
exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
|
||||
// Pass in guarantee size to be filled
|
||||
SetThreadStackGuarantee(&guaranteeSize);
|
||||
}
|
||||
|
||||
static void reset() {
|
||||
if (isSet) {
|
||||
// Unregister handler and restore the old guarantee
|
||||
RemoveVectoredExceptionHandler(exceptionHandlerHandle);
|
||||
SetThreadStackGuarantee(&guaranteeSize);
|
||||
exceptionHandlerHandle = CATCH_NULL;
|
||||
isSet = false;
|
||||
}
|
||||
}
|
||||
|
||||
~FatalConditionHandler() {
|
||||
reset();
|
||||
}
|
||||
private:
|
||||
static bool isSet;
|
||||
static ULONG guaranteeSize;
|
||||
static PVOID exceptionHandlerHandle;
|
||||
};
|
||||
|
||||
bool FatalConditionHandler::isSet = false;
|
||||
ULONG FatalConditionHandler::guaranteeSize = 0;
|
||||
PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL;
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
# endif // CATCH_CONFIG_WINDOWS_SEH
|
||||
|
||||
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct SignalDefs { int id; const char* name; };
|
||||
struct SignalDefs {
|
||||
int id;
|
||||
const char* name;
|
||||
};
|
||||
extern SignalDefs signalDefs[];
|
||||
SignalDefs signalDefs[] = {
|
||||
{ SIGINT, "SIGINT - Terminal interrupt signal" },
|
||||
@@ -49,35 +119,68 @@ namespace Catch {
|
||||
{ SIGSEGV, "SIGSEGV - Segmentation violation signal" },
|
||||
{ SIGTERM, "SIGTERM - Termination request signal" },
|
||||
{ SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
|
||||
};
|
||||
};
|
||||
|
||||
struct FatalConditionHandler {
|
||||
|
||||
static bool isSet;
|
||||
static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
|
||||
static stack_t oldSigStack;
|
||||
static char altStackMem[SIGSTKSZ];
|
||||
|
||||
static void handleSignal( int sig ) {
|
||||
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
|
||||
if( sig == signalDefs[i].id )
|
||||
fatal( signalDefs[i].name, -sig );
|
||||
fatal( "<unknown signal>", -sig );
|
||||
std::string name = "<unknown signal>";
|
||||
for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
|
||||
SignalDefs &def = signalDefs[i];
|
||||
if (sig == def.id) {
|
||||
name = def.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
reset();
|
||||
reportFatal(name);
|
||||
raise( sig );
|
||||
}
|
||||
|
||||
FatalConditionHandler() : m_isSet( true ) {
|
||||
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
|
||||
signal( signalDefs[i].id, handleSignal );
|
||||
}
|
||||
~FatalConditionHandler() {
|
||||
reset();
|
||||
}
|
||||
void reset() {
|
||||
if( m_isSet ) {
|
||||
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
|
||||
signal( signalDefs[i].id, SIG_DFL );
|
||||
m_isSet = false;
|
||||
FatalConditionHandler() {
|
||||
isSet = true;
|
||||
stack_t sigStack;
|
||||
sigStack.ss_sp = altStackMem;
|
||||
sigStack.ss_size = SIGSTKSZ;
|
||||
sigStack.ss_flags = 0;
|
||||
sigaltstack(&sigStack, &oldSigStack);
|
||||
struct sigaction sa = { 0 };
|
||||
|
||||
sa.sa_handler = handleSignal;
|
||||
sa.sa_flags = SA_ONSTACK;
|
||||
for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
|
||||
sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool m_isSet;
|
||||
|
||||
~FatalConditionHandler() {
|
||||
reset();
|
||||
}
|
||||
static void reset() {
|
||||
if( isSet ) {
|
||||
// Set signals back to previous values -- hopefully nobody overwrote them in the meantime
|
||||
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
|
||||
sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
|
||||
}
|
||||
// Return the old stack
|
||||
sigaltstack(&oldSigStack, CATCH_NULL);
|
||||
isSet = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool FatalConditionHandler::isSet = false;
|
||||
struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
|
||||
stack_t FatalConditionHandler::oldSigStack = {};
|
||||
char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
|
||||
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
#endif // not Windows
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#include "catch_tostring.hpp"
|
||||
#include "catch_result_builder.hpp"
|
||||
#include "catch_tag_alias_registry.hpp"
|
||||
#include "catch_test_case_tracker.hpp"
|
||||
|
||||
#include "../reporters/catch_reporter_multi.hpp"
|
||||
#include "../reporters/catch_reporter_xml.hpp"
|
||||
@@ -43,8 +44,14 @@
|
||||
#include "../reporters/catch_reporter_compact.hpp"
|
||||
|
||||
namespace Catch {
|
||||
// These are all here to avoid warnings about not having any out of line
|
||||
// virtual methods
|
||||
NonCopyable::~NonCopyable() {}
|
||||
IShared::~IShared() {}
|
||||
IStream::~IStream() CATCH_NOEXCEPT {}
|
||||
FileStream::~FileStream() CATCH_NOEXCEPT {}
|
||||
CoutStream::~CoutStream() CATCH_NOEXCEPT {}
|
||||
DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
|
||||
StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
|
||||
IContext::~IContext() {}
|
||||
IResultCapture::~IResultCapture() {}
|
||||
@@ -90,6 +97,13 @@ namespace Catch {
|
||||
Matchers::Impl::StdString::EndsWith::~EndsWith() {}
|
||||
|
||||
void Config::dummy() {}
|
||||
|
||||
namespace TestCaseTracking {
|
||||
ITracker::~ITracker() {}
|
||||
TrackerBase::~TrackerBase() {}
|
||||
SectionTracker::~SectionTracker() {}
|
||||
IndexTracker::~IndexTracker() {}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
|
@@ -37,6 +37,11 @@ namespace Catch {
|
||||
InLexicographicalOrder,
|
||||
InRandomOrder
|
||||
}; };
|
||||
struct UseColour { enum YesOrNo {
|
||||
Auto,
|
||||
Yes,
|
||||
No
|
||||
}; };
|
||||
|
||||
class TestSpec;
|
||||
|
||||
@@ -56,7 +61,9 @@ namespace Catch {
|
||||
virtual TestSpec const& testSpec() const = 0;
|
||||
virtual RunTests::InWhatOrder runOrder() const = 0;
|
||||
virtual unsigned int rngSeed() const = 0;
|
||||
virtual bool forceColour() const = 0;
|
||||
virtual UseColour::YesOrNo useColour() const = 0;
|
||||
virtual std::vector<std::string> const& getSectionsToRun() const = 0;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -9,15 +9,20 @@
|
||||
#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "catch_interfaces_registry_hub.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
typedef std::string(*exceptionTranslateFunction)();
|
||||
|
||||
struct IExceptionTranslator;
|
||||
typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
|
||||
|
||||
struct IExceptionTranslator {
|
||||
virtual ~IExceptionTranslator();
|
||||
virtual std::string translate() const = 0;
|
||||
virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
|
||||
};
|
||||
|
||||
struct IExceptionTranslatorRegistry {
|
||||
@@ -35,9 +40,12 @@ namespace Catch {
|
||||
: m_translateFunction( translateFunction )
|
||||
{}
|
||||
|
||||
virtual std::string translate() const {
|
||||
virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
|
||||
try {
|
||||
throw;
|
||||
if( it == itEnd )
|
||||
throw;
|
||||
else
|
||||
return (*it)->translate( it+1, itEnd );
|
||||
}
|
||||
catch( T& ex ) {
|
||||
return m_translateFunction( ex );
|
||||
@@ -58,9 +66,11 @@ namespace Catch {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
|
||||
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
|
||||
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
|
||||
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
|
||||
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
|
||||
static std::string translatorName( signature ); \
|
||||
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
|
||||
static std::string translatorName( signature )
|
||||
|
||||
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
|
||||
|
@@ -26,18 +26,18 @@
|
||||
namespace Catch
|
||||
{
|
||||
struct ReporterConfig {
|
||||
explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
|
||||
explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
|
||||
: m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
|
||||
|
||||
ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
|
||||
ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
|
||||
: m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
|
||||
|
||||
std::ostream& stream() const { return *m_stream; }
|
||||
Ptr<IConfig> fullConfig() const { return m_fullConfig; }
|
||||
Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
|
||||
|
||||
private:
|
||||
std::ostream* m_stream;
|
||||
Ptr<IConfig> m_fullConfig;
|
||||
Ptr<IConfig const> m_fullConfig;
|
||||
};
|
||||
|
||||
struct ReporterPreferences {
|
||||
@@ -219,6 +219,7 @@ namespace Catch
|
||||
bool aborting;
|
||||
};
|
||||
|
||||
class MultipleReporters;
|
||||
|
||||
struct IStreamingReporter : IShared {
|
||||
virtual ~IStreamingReporter();
|
||||
@@ -240,13 +241,15 @@ namespace Catch
|
||||
|
||||
// The return value indicates if the messages buffer should be cleared:
|
||||
virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
|
||||
|
||||
|
||||
virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
|
||||
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
|
||||
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
|
||||
virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
|
||||
|
||||
|
||||
virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
|
||||
|
||||
virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
|
||||
};
|
||||
|
||||
|
||||
@@ -261,13 +264,13 @@ namespace Catch
|
||||
typedef std::vector<Ptr<IReporterFactory> > Listeners;
|
||||
|
||||
virtual ~IReporterRegistry();
|
||||
virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
|
||||
virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
|
||||
virtual FactoryMap const& getFactories() const = 0;
|
||||
virtual Listeners const& getListeners() const = 0;
|
||||
};
|
||||
|
||||
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
|
||||
|
@@ -34,7 +34,7 @@ namespace Catch {
|
||||
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
|
||||
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
|
||||
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
|
||||
|
@@ -51,9 +51,9 @@ namespace Catch {
|
||||
}
|
||||
|
||||
if( !config.testSpec().hasFilters() )
|
||||
Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
|
||||
Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl;
|
||||
else
|
||||
Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
|
||||
Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl;
|
||||
return matchedTests;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,10 @@ namespace Catch {
|
||||
++it ) {
|
||||
matchedTests++;
|
||||
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
|
||||
Catch::cout() << testCaseInfo.name << std::endl;
|
||||
if( startsWith( testCaseInfo.name, '#' ) )
|
||||
Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl;
|
||||
else
|
||||
Catch::cout() << testCaseInfo.name << std::endl;
|
||||
}
|
||||
return matchedTests;
|
||||
}
|
||||
@@ -129,9 +132,9 @@ namespace Catch {
|
||||
.setInitialIndent( 0 )
|
||||
.setIndent( oss.str().size() )
|
||||
.setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
|
||||
Catch::cout() << oss.str() << wrapper << "\n";
|
||||
Catch::cout() << oss.str() << wrapper << '\n';
|
||||
}
|
||||
Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
|
||||
Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
|
||||
return tagCounts.size();
|
||||
}
|
||||
|
||||
@@ -150,9 +153,9 @@ namespace Catch {
|
||||
.setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
|
||||
Catch::cout() << " "
|
||||
<< it->first
|
||||
<< ":"
|
||||
<< ':'
|
||||
<< std::string( maxNameLen - it->first.size() + 2, ' ' )
|
||||
<< wrapper << "\n";
|
||||
<< wrapper << '\n';
|
||||
}
|
||||
Catch::cout() << std::endl;
|
||||
return factories.size();
|
||||
|
@@ -12,6 +12,12 @@ namespace Catch {
|
||||
namespace Matchers {
|
||||
namespace Impl {
|
||||
|
||||
namespace Generic {
|
||||
template<typename ExpressionT> class AllOf;
|
||||
template<typename ExpressionT> class AnyOf;
|
||||
template<typename ExpressionT> class Not;
|
||||
}
|
||||
|
||||
template<typename ExpressionT>
|
||||
struct Matcher : SharedImpl<IShared>
|
||||
{
|
||||
@@ -21,6 +27,10 @@ namespace Matchers {
|
||||
virtual Ptr<Matcher> clone() const = 0;
|
||||
virtual bool match( ExpressionT const& expr ) const = 0;
|
||||
virtual std::string toString() const = 0;
|
||||
|
||||
Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const;
|
||||
Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const;
|
||||
Generic::Not<ExpressionT> operator ! () const;
|
||||
};
|
||||
|
||||
template<typename DerivedT, typename ExpressionT>
|
||||
@@ -33,8 +43,9 @@ namespace Matchers {
|
||||
|
||||
namespace Generic {
|
||||
template<typename ExpressionT>
|
||||
struct Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> {
|
||||
Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {}
|
||||
class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> {
|
||||
public:
|
||||
explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {}
|
||||
Not( Not const& other ) : m_matcher( other.m_matcher ) {}
|
||||
|
||||
virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE {
|
||||
@@ -44,7 +55,7 @@ namespace Matchers {
|
||||
virtual std::string toString() const CATCH_OVERRIDE {
|
||||
return "not " + m_matcher->toString();
|
||||
}
|
||||
|
||||
private:
|
||||
Ptr< Matcher<ExpressionT> > m_matcher;
|
||||
};
|
||||
|
||||
@@ -78,6 +89,12 @@ namespace Matchers {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
AllOf operator && ( Matcher<ExpressionT> const& other ) const {
|
||||
AllOf allOfExpr( *this );
|
||||
allOfExpr.add( other );
|
||||
return allOfExpr;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
|
||||
};
|
||||
@@ -112,11 +129,40 @@ namespace Matchers {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
AnyOf operator || ( Matcher<ExpressionT> const& other ) const {
|
||||
AnyOf anyOfExpr( *this );
|
||||
anyOfExpr.add( other );
|
||||
return anyOfExpr;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
|
||||
};
|
||||
|
||||
} // namespace Generic
|
||||
|
||||
template<typename ExpressionT>
|
||||
Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const {
|
||||
Generic::AllOf<ExpressionT> allOfExpr;
|
||||
allOfExpr.add( *this );
|
||||
allOfExpr.add( other );
|
||||
return allOfExpr;
|
||||
}
|
||||
|
||||
template<typename ExpressionT>
|
||||
Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const {
|
||||
Generic::AnyOf<ExpressionT> anyOfExpr;
|
||||
anyOfExpr.add( *this );
|
||||
anyOfExpr.add( other );
|
||||
return anyOfExpr;
|
||||
}
|
||||
|
||||
template<typename ExpressionT>
|
||||
Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const {
|
||||
return Generic::Not<ExpressionT>( *this );
|
||||
}
|
||||
|
||||
|
||||
namespace StdString {
|
||||
|
||||
inline std::string makeString( std::string const& str ) { return str; }
|
||||
@@ -132,18 +178,18 @@ namespace Matchers {
|
||||
return m_caseSensitivity == CaseSensitive::No
|
||||
? toLower( str )
|
||||
: str;
|
||||
|
||||
|
||||
}
|
||||
std::string toStringSuffix() const
|
||||
{
|
||||
return m_caseSensitivity == CaseSensitive::No
|
||||
? " (case insensitive)"
|
||||
: "";
|
||||
: std::string();
|
||||
}
|
||||
CaseSensitive::Choice m_caseSensitivity;
|
||||
std::string m_str;
|
||||
};
|
||||
|
||||
|
||||
struct Equals : MatcherImpl<Equals, std::string> {
|
||||
Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
|
||||
: m_data( str, caseSensitivity )
|
||||
@@ -156,7 +202,7 @@ namespace Matchers {
|
||||
return m_data.m_str == m_data.adjustString( expr );;
|
||||
}
|
||||
virtual std::string toString() const {
|
||||
return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
|
||||
return "equals: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
|
||||
}
|
||||
|
||||
CasedString m_data;
|
||||
@@ -173,7 +219,7 @@ namespace Matchers {
|
||||
return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos;
|
||||
}
|
||||
virtual std::string toString() const {
|
||||
return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
|
||||
return "contains: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
|
||||
}
|
||||
|
||||
CasedString m_data;
|
||||
@@ -182,16 +228,16 @@ namespace Matchers {
|
||||
struct StartsWith : MatcherImpl<StartsWith, std::string> {
|
||||
StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
|
||||
: m_data( substr, caseSensitivity ){}
|
||||
|
||||
|
||||
StartsWith( StartsWith const& other ) : m_data( other.m_data ){}
|
||||
|
||||
virtual ~StartsWith();
|
||||
|
||||
virtual bool match( std::string const& expr ) const {
|
||||
return m_data.adjustString( expr ).find( m_data.m_str ) == 0;
|
||||
return startsWith( m_data.adjustString( expr ), m_data.m_str );
|
||||
}
|
||||
virtual std::string toString() const {
|
||||
return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
|
||||
return "starts with: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
|
||||
}
|
||||
|
||||
CasedString m_data;
|
||||
@@ -205,10 +251,10 @@ namespace Matchers {
|
||||
virtual ~EndsWith();
|
||||
|
||||
virtual bool match( std::string const& expr ) const {
|
||||
return m_data.adjustString( expr ).find( m_data.m_str ) == expr.size() - m_data.m_str.size();
|
||||
return endsWith( m_data.adjustString( expr ), m_data.m_str );
|
||||
}
|
||||
virtual std::string toString() const {
|
||||
return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
|
||||
return "ends with: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
|
||||
}
|
||||
|
||||
CasedString m_data;
|
||||
|
@@ -10,11 +10,19 @@
|
||||
#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
|
||||
|
||||
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
|
||||
#define CATCH_PLATFORM_MAC
|
||||
# define CATCH_PLATFORM_MAC
|
||||
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
|
||||
#define CATCH_PLATFORM_IPHONE
|
||||
# define CATCH_PLATFORM_IPHONE
|
||||
#elif defined(linux) || defined(__linux) || defined(__linux__)
|
||||
# define CATCH_PLATFORM_LINUX
|
||||
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
|
||||
#define CATCH_PLATFORM_WINDOWS
|
||||
# define CATCH_PLATFORM_WINDOWS
|
||||
# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
|
||||
# define CATCH_DEFINES_NOMINMAX
|
||||
# endif
|
||||
# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
|
||||
# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
|
||||
|
@@ -64,22 +64,22 @@ namespace Catch {
|
||||
getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class ListenerRegistrar {
|
||||
|
||||
|
||||
class ListenerFactory : public SharedImpl<IReporterFactory> {
|
||||
|
||||
|
||||
virtual IStreamingReporter* create( ReporterConfig const& config ) const {
|
||||
return new T( config );
|
||||
}
|
||||
virtual std::string getDescription() const {
|
||||
return "";
|
||||
return std::string();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
ListenerRegistrar() {
|
||||
getMutableRegistryHub().registerListener( new ListenerFactory() );
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@ namespace Catch {
|
||||
|
||||
virtual ~ReporterRegistry() CATCH_OVERRIDE {}
|
||||
|
||||
virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const CATCH_OVERRIDE {
|
||||
virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
|
||||
FactoryMap::const_iterator it = m_factories.find( name );
|
||||
if( it == m_factories.end() )
|
||||
return CATCH_NULL;
|
||||
|
@@ -19,22 +19,20 @@ namespace Catch {
|
||||
|
||||
template<typename T> class ExpressionLhs;
|
||||
|
||||
struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
|
||||
|
||||
struct CopyableStream {
|
||||
CopyableStream() {}
|
||||
CopyableStream( CopyableStream const& other ) {
|
||||
oss << other.oss.str();
|
||||
}
|
||||
CopyableStream& operator=( CopyableStream const& other ) {
|
||||
oss.str("");
|
||||
oss.str(std::string());
|
||||
oss << other.oss.str();
|
||||
return *this;
|
||||
}
|
||||
std::ostringstream oss;
|
||||
};
|
||||
|
||||
class ResultBuilder {
|
||||
class ResultBuilder : public DecomposedExpression {
|
||||
public:
|
||||
ResultBuilder( char const* macroName,
|
||||
SourceLineInfo const& lineInfo,
|
||||
@@ -52,19 +50,15 @@ namespace Catch {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
|
||||
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
|
||||
|
||||
ResultBuilder& setResultType( ResultWas::OfType result );
|
||||
ResultBuilder& setResultType( bool result );
|
||||
ResultBuilder& setLhs( std::string const& lhs );
|
||||
ResultBuilder& setRhs( std::string const& rhs );
|
||||
ResultBuilder& setOp( std::string const& op );
|
||||
|
||||
void endExpression();
|
||||
void endExpression( DecomposedExpression const& expr );
|
||||
|
||||
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE;
|
||||
|
||||
std::string reconstructExpression() const;
|
||||
AssertionResult build() const;
|
||||
AssertionResult build( DecomposedExpression const& expr ) const;
|
||||
|
||||
void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
|
||||
void captureResult( ResultWas::OfType resultType );
|
||||
@@ -76,16 +70,14 @@ namespace Catch {
|
||||
bool shouldDebugBreak() const;
|
||||
bool allowThrows() const;
|
||||
|
||||
template<typename ArgT, typename MatcherT>
|
||||
void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString );
|
||||
|
||||
private:
|
||||
AssertionInfo m_assertionInfo;
|
||||
AssertionResultData m_data;
|
||||
struct ExprComponents {
|
||||
ExprComponents() : testFalse( false ) {}
|
||||
bool testFalse;
|
||||
std::string lhs, rhs, op;
|
||||
} m_exprComponents;
|
||||
CopyableStream m_stream;
|
||||
|
||||
|
||||
bool m_shouldDebugBreak;
|
||||
bool m_shouldThrow;
|
||||
};
|
||||
@@ -106,6 +98,14 @@ namespace Catch {
|
||||
return ExpressionLhs<bool>( *this, value );
|
||||
}
|
||||
|
||||
template<typename ArgT, typename MatcherT>
|
||||
inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
|
||||
char const* matcherString ) {
|
||||
MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString );
|
||||
setResultType( matcher.match( arg ) );
|
||||
endExpression( expr );
|
||||
}
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
|
||||
|
@@ -41,22 +41,10 @@ namespace Catch {
|
||||
m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
|
||||
return *this;
|
||||
}
|
||||
ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) {
|
||||
m_exprComponents.lhs = lhs;
|
||||
return *this;
|
||||
}
|
||||
ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) {
|
||||
m_exprComponents.rhs = rhs;
|
||||
return *this;
|
||||
}
|
||||
ResultBuilder& ResultBuilder::setOp( std::string const& op ) {
|
||||
m_exprComponents.op = op;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ResultBuilder::endExpression() {
|
||||
m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition );
|
||||
captureExpression();
|
||||
void ResultBuilder::endExpression( DecomposedExpression const& expr ) {
|
||||
AssertionResult result = build( expr );
|
||||
handleResult( result );
|
||||
}
|
||||
|
||||
void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
|
||||
@@ -69,6 +57,7 @@ namespace Catch {
|
||||
setResultType( resultType );
|
||||
captureExpression();
|
||||
}
|
||||
|
||||
void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
|
||||
if( expectedMessage.empty() )
|
||||
captureExpectedException( Matchers::Impl::Generic::AllOf<std::string>() );
|
||||
@@ -77,12 +66,12 @@ namespace Catch {
|
||||
}
|
||||
|
||||
void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ) {
|
||||
|
||||
assert( m_exprComponents.testFalse == false );
|
||||
|
||||
assert( !isFalseTest( m_assertionInfo.resultDisposition ) );
|
||||
AssertionResultData data = m_data;
|
||||
data.resultType = ResultWas::Ok;
|
||||
data.reconstructedExpression = m_assertionInfo.capturedExpression;
|
||||
|
||||
|
||||
std::string actualMessage = Catch::translateActiveException();
|
||||
if( !matcher.match( actualMessage ) ) {
|
||||
data.resultType = ResultWas::ExpressionFailed;
|
||||
@@ -96,10 +85,11 @@ namespace Catch {
|
||||
AssertionResult result = build();
|
||||
handleResult( result );
|
||||
}
|
||||
|
||||
void ResultBuilder::handleResult( AssertionResult const& result )
|
||||
{
|
||||
getResultCapture().assertionEnded( result );
|
||||
|
||||
|
||||
if( !result.isOk() ) {
|
||||
if( getCurrentContext().getConfig()->shouldDebugBreak() )
|
||||
m_shouldDebugBreak = true;
|
||||
@@ -107,6 +97,7 @@ namespace Catch {
|
||||
m_shouldThrow = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ResultBuilder::react() {
|
||||
if( m_shouldThrow )
|
||||
throw Catch::TestFailureException();
|
||||
@@ -117,43 +108,32 @@ namespace Catch {
|
||||
|
||||
AssertionResult ResultBuilder::build() const
|
||||
{
|
||||
assert( m_data.resultType != ResultWas::Unknown );
|
||||
return build( *this );
|
||||
}
|
||||
|
||||
// CAVEAT: The returned AssertionResult stores a pointer to the argument expr,
|
||||
// a temporary DecomposedExpression, which in turn holds references to
|
||||
// operands, possibly temporary as well.
|
||||
// It should immediately be passed to handleResult; if the expression
|
||||
// needs to be reported, its string expansion must be composed before
|
||||
// the temporaries are destroyed.
|
||||
AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const
|
||||
{
|
||||
assert( m_data.resultType != ResultWas::Unknown );
|
||||
AssertionResultData data = m_data;
|
||||
|
||||
// Flip bool results if testFalse is set
|
||||
if( m_exprComponents.testFalse ) {
|
||||
if( data.resultType == ResultWas::Ok )
|
||||
data.resultType = ResultWas::ExpressionFailed;
|
||||
else if( data.resultType == ResultWas::ExpressionFailed )
|
||||
data.resultType = ResultWas::Ok;
|
||||
// Flip bool results if FalseTest flag is set
|
||||
if( isFalseTest( m_assertionInfo.resultDisposition ) ) {
|
||||
data.negate( expr.isBinaryExpression() );
|
||||
}
|
||||
|
||||
data.message = m_stream.oss.str();
|
||||
data.reconstructedExpression = reconstructExpression();
|
||||
if( m_exprComponents.testFalse ) {
|
||||
if( m_exprComponents.op == "" )
|
||||
data.reconstructedExpression = "!" + data.reconstructedExpression;
|
||||
else
|
||||
data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
|
||||
}
|
||||
data.decomposedExpression = &expr; // for lazy reconstruction
|
||||
return AssertionResult( m_assertionInfo, data );
|
||||
}
|
||||
std::string ResultBuilder::reconstructExpression() const {
|
||||
if( m_exprComponents.op == "" )
|
||||
return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
|
||||
else if( m_exprComponents.op == "matches" )
|
||||
return m_exprComponents.lhs + " " + m_exprComponents.rhs;
|
||||
else if( m_exprComponents.op != "!" ) {
|
||||
if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
|
||||
m_exprComponents.lhs.find("\n") == std::string::npos &&
|
||||
m_exprComponents.rhs.find("\n") == std::string::npos )
|
||||
return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
|
||||
else
|
||||
return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
|
||||
}
|
||||
else
|
||||
return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}";
|
||||
|
||||
void ResultBuilder::reconstructExpression( std::string& dest ) const {
|
||||
dest = m_assertionInfo.capturedExpression;
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
||||
|
@@ -55,7 +55,7 @@ namespace Catch {
|
||||
inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
|
||||
inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
|
||||
inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
|
||||
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
|
||||
|
@@ -64,10 +64,7 @@ namespace Catch {
|
||||
m_context( getCurrentMutableContext() ),
|
||||
m_activeTestCase( CATCH_NULL ),
|
||||
m_config( _config ),
|
||||
m_reporter( reporter ),
|
||||
m_prevRunner( m_context.getRunner() ),
|
||||
m_prevResultCapture( m_context.getResultCapture() ),
|
||||
m_prevConfig( m_context.getConfig() )
|
||||
m_reporter( reporter )
|
||||
{
|
||||
m_context.setRunner( this );
|
||||
m_context.setConfig( m_config );
|
||||
@@ -77,10 +74,6 @@ namespace Catch {
|
||||
|
||||
virtual ~RunContext() {
|
||||
m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
|
||||
m_context.setRunner( m_prevRunner );
|
||||
m_context.setConfig( Ptr<IConfig const>() );
|
||||
m_context.setResultCapture( m_prevResultCapture );
|
||||
m_context.setConfig( m_prevConfig );
|
||||
}
|
||||
|
||||
void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
|
||||
@@ -101,17 +94,27 @@ namespace Catch {
|
||||
m_reporter->testCaseStarting( testInfo );
|
||||
|
||||
m_activeTestCase = &testCase;
|
||||
m_testCaseTracker = TestCaseTracker( testInfo.name );
|
||||
|
||||
|
||||
do {
|
||||
ITracker& rootTracker = m_trackerContext.startRun();
|
||||
dynamic_cast<SectionTracker&>( rootTracker ).addInitialFilters( m_config->getSectionsToRun() );
|
||||
do {
|
||||
m_trackerContext.startCycle();
|
||||
m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) );
|
||||
runCurrentTest( redirectedCout, redirectedCerr );
|
||||
}
|
||||
while( !m_testCaseTracker->isCompleted() && !aborting() );
|
||||
while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
|
||||
}
|
||||
// !TBD: deprecated - this will be replaced by indexed trackers
|
||||
while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
|
||||
|
||||
Totals deltaTotals = m_totals.delta( prevTotals );
|
||||
if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
|
||||
deltaTotals.assertions.failed++;
|
||||
deltaTotals.testCases.passed--;
|
||||
deltaTotals.testCases.failed++;
|
||||
}
|
||||
m_totals.testCases += deltaTotals.testCases;
|
||||
m_reporter->testCaseEnded( TestCaseStats( testInfo,
|
||||
deltaTotals,
|
||||
@@ -120,7 +123,7 @@ namespace Catch {
|
||||
aborting() ) );
|
||||
|
||||
m_activeTestCase = CATCH_NULL;
|
||||
m_testCaseTracker.reset();
|
||||
m_testCaseTracker = CATCH_NULL;
|
||||
|
||||
return deltaTotals;
|
||||
}
|
||||
@@ -144,7 +147,7 @@ namespace Catch {
|
||||
m_messages.clear();
|
||||
|
||||
// Reset working state
|
||||
m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
|
||||
m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
|
||||
m_lastResult = result;
|
||||
}
|
||||
|
||||
@@ -153,11 +156,10 @@ namespace Catch {
|
||||
Counts& assertions
|
||||
)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
|
||||
|
||||
if( !m_testCaseTracker->enterSection( oss.str() ) )
|
||||
ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) );
|
||||
if( !sectionTracker.isOpen() )
|
||||
return false;
|
||||
m_activeSections.push_back( §ionTracker );
|
||||
|
||||
m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
|
||||
|
||||
@@ -168,29 +170,40 @@ namespace Catch {
|
||||
return true;
|
||||
}
|
||||
bool testForMissingAssertions( Counts& assertions ) {
|
||||
if( assertions.total() != 0 ||
|
||||
!m_config->warnAboutMissingAssertions() ||
|
||||
m_testCaseTracker->currentSectionHasChildren() )
|
||||
if( assertions.total() != 0 )
|
||||
return false;
|
||||
if( !m_config->warnAboutMissingAssertions() )
|
||||
return false;
|
||||
if( m_trackerContext.currentTracker().hasChildren() )
|
||||
return false;
|
||||
m_totals.assertions.failed++;
|
||||
assertions.failed++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
virtual void sectionEnded( SectionEndInfo const& endInfo ) {
|
||||
Counts assertions = m_totals.assertions - endInfo.prevAssertions;
|
||||
bool missingAssertions = testForMissingAssertions( assertions );
|
||||
|
||||
m_testCaseTracker->leaveSection();
|
||||
|
||||
|
||||
if( !m_activeSections.empty() ) {
|
||||
m_activeSections.back()->close();
|
||||
m_activeSections.pop_back();
|
||||
}
|
||||
|
||||
m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
|
||||
m_messages.clear();
|
||||
}
|
||||
|
||||
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
|
||||
if( m_unfinishedSections.empty() )
|
||||
m_activeSections.back()->fail();
|
||||
else
|
||||
m_activeSections.back()->close();
|
||||
m_activeSections.pop_back();
|
||||
|
||||
m_unfinishedSections.push_back( endInfo );
|
||||
}
|
||||
|
||||
|
||||
virtual void pushScopedMessage( MessageInfo const& message ) {
|
||||
m_messages.push_back( message );
|
||||
}
|
||||
@@ -202,7 +215,7 @@ namespace Catch {
|
||||
virtual std::string getCurrentTestName() const {
|
||||
return m_activeTestCase
|
||||
? m_activeTestCase->getTestCaseInfo().name
|
||||
: "";
|
||||
: std::string();
|
||||
}
|
||||
|
||||
virtual const AssertionResult* getLastResult() const {
|
||||
@@ -232,11 +245,11 @@ namespace Catch {
|
||||
deltaTotals.testCases.failed = 1;
|
||||
m_reporter->testCaseEnded( TestCaseStats( testInfo,
|
||||
deltaTotals,
|
||||
"",
|
||||
"",
|
||||
std::string(),
|
||||
std::string(),
|
||||
false ) );
|
||||
m_totals.testCases.failed++;
|
||||
testGroupEnded( "", m_totals, 1, 1 );
|
||||
testGroupEnded( std::string(), m_totals, 1, 1 );
|
||||
m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
|
||||
}
|
||||
|
||||
@@ -255,11 +268,10 @@ namespace Catch {
|
||||
Counts prevAssertions = m_totals.assertions;
|
||||
double duration = 0;
|
||||
try {
|
||||
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
|
||||
TestCaseTracker::Guard guard( *m_testCaseTracker );
|
||||
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal );
|
||||
|
||||
seedRng( *m_config );
|
||||
|
||||
|
||||
Timer timer;
|
||||
timer.start();
|
||||
if( m_reporter->getPreferences().shouldRedirectStdOut ) {
|
||||
@@ -278,6 +290,7 @@ namespace Catch {
|
||||
catch(...) {
|
||||
makeUnexpectedResultBuilder().useActiveException();
|
||||
}
|
||||
m_testCaseTracker->close();
|
||||
handleUnfinishedSections();
|
||||
m_messages.clear();
|
||||
|
||||
@@ -308,7 +321,7 @@ namespace Catch {
|
||||
m_lastAssertionInfo.capturedExpression.c_str(),
|
||||
m_lastAssertionInfo.resultDisposition );
|
||||
}
|
||||
|
||||
|
||||
void handleUnfinishedSections() {
|
||||
// If sections ended prematurely due to an exception we stored their
|
||||
// infos here so we can tear them down outside the unwind process.
|
||||
@@ -323,18 +336,18 @@ namespace Catch {
|
||||
TestRunInfo m_runInfo;
|
||||
IMutableContext& m_context;
|
||||
TestCase const* m_activeTestCase;
|
||||
Option<TestCaseTracker> m_testCaseTracker;
|
||||
ITracker* m_testCaseTracker;
|
||||
ITracker* m_currentSectionTracker;
|
||||
AssertionResult m_lastResult;
|
||||
|
||||
Ptr<IConfig const> m_config;
|
||||
Totals m_totals;
|
||||
Ptr<IStreamingReporter> m_reporter;
|
||||
std::vector<MessageInfo> m_messages;
|
||||
IRunner* m_prevRunner;
|
||||
IResultCapture* m_prevResultCapture;
|
||||
Ptr<IConfig const> m_prevConfig;
|
||||
AssertionInfo m_lastAssertionInfo;
|
||||
std::vector<SectionEndInfo> m_unfinishedSections;
|
||||
std::vector<ITracker*> m_activeSections;
|
||||
TrackerContext m_trackerContext;
|
||||
};
|
||||
|
||||
IResultCapture& getResultCapture() {
|
||||
|
@@ -23,17 +23,17 @@ namespace Catch {
|
||||
std::string description;
|
||||
SourceLineInfo lineInfo;
|
||||
};
|
||||
|
||||
|
||||
struct SectionEndInfo {
|
||||
SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
|
||||
: sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
|
||||
{}
|
||||
|
||||
|
||||
SectionInfo sectionInfo;
|
||||
Counts prevAssertions;
|
||||
double durationInSeconds;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
|
||||
|
@@ -9,28 +9,56 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||
|
||||
#include <streambuf>
|
||||
#include "catch_compiler_capabilities.h"
|
||||
#include "catch_streambuf.h"
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wpadded"
|
||||
#endif
|
||||
#include <streambuf>
|
||||
#include <ostream>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class Stream {
|
||||
public:
|
||||
Stream();
|
||||
Stream( std::streambuf* _streamBuf, bool _isOwned );
|
||||
void release();
|
||||
|
||||
std::streambuf* streamBuf;
|
||||
|
||||
private:
|
||||
bool isOwned;
|
||||
};
|
||||
|
||||
std::ostream& cout();
|
||||
std::ostream& cerr();
|
||||
|
||||
|
||||
struct IStream {
|
||||
virtual ~IStream() CATCH_NOEXCEPT;
|
||||
virtual std::ostream& stream() const = 0;
|
||||
};
|
||||
|
||||
class FileStream : public IStream {
|
||||
mutable std::ofstream m_ofs;
|
||||
public:
|
||||
FileStream( std::string const& filename );
|
||||
virtual ~FileStream() CATCH_NOEXCEPT;
|
||||
public: // IStream
|
||||
virtual std::ostream& stream() const CATCH_OVERRIDE;
|
||||
};
|
||||
|
||||
|
||||
class CoutStream : public IStream {
|
||||
mutable std::ostream m_os;
|
||||
public:
|
||||
CoutStream();
|
||||
virtual ~CoutStream() CATCH_NOEXCEPT;
|
||||
|
||||
public: // IStream
|
||||
virtual std::ostream& stream() const CATCH_OVERRIDE;
|
||||
};
|
||||
|
||||
|
||||
class DebugOutStream : public IStream {
|
||||
CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
|
||||
mutable std::ostream m_os;
|
||||
public:
|
||||
DebugOutStream();
|
||||
virtual ~DebugOutStream() CATCH_NOEXCEPT;
|
||||
|
||||
public: // IStream
|
||||
virtual std::ostream& stream() const CATCH_OVERRIDE;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||
|
@@ -10,7 +10,6 @@
|
||||
#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
|
||||
|
||||
#include "catch_stream.h"
|
||||
#include "catch_streambuf.h"
|
||||
#include "catch_debugger.h"
|
||||
|
||||
#include <stdexcept>
|
||||
@@ -57,6 +56,20 @@ namespace Catch {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
FileStream::FileStream( std::string const& filename ) {
|
||||
m_ofs.open( filename.c_str() );
|
||||
if( m_ofs.fail() ) {
|
||||
std::ostringstream oss;
|
||||
oss << "Unable to open file: '" << filename << '\'';
|
||||
throw std::domain_error( oss.str() );
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& FileStream::stream() const {
|
||||
return m_ofs;
|
||||
}
|
||||
|
||||
struct OutputDebugWriter {
|
||||
|
||||
void operator()( std::string const&str ) {
|
||||
@@ -64,23 +77,26 @@ namespace Catch {
|
||||
}
|
||||
};
|
||||
|
||||
Stream::Stream()
|
||||
: streamBuf( CATCH_NULL ), isOwned( false )
|
||||
DebugOutStream::DebugOutStream()
|
||||
: m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
|
||||
m_os( m_streamBuf.get() )
|
||||
{}
|
||||
|
||||
Stream::Stream( std::streambuf* _streamBuf, bool _isOwned )
|
||||
: streamBuf( _streamBuf ), isOwned( _isOwned )
|
||||
{}
|
||||
|
||||
void Stream::release() {
|
||||
if( isOwned ) {
|
||||
delete streamBuf;
|
||||
streamBuf = CATCH_NULL;
|
||||
isOwned = false;
|
||||
}
|
||||
std::ostream& DebugOutStream::stream() const {
|
||||
return m_os;
|
||||
}
|
||||
|
||||
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions
|
||||
// Store the streambuf from cout up-front because
|
||||
// cout may get redirected when running tests
|
||||
CoutStream::CoutStream()
|
||||
: m_os( Catch::cout().rdbuf() )
|
||||
{}
|
||||
|
||||
std::ostream& CoutStream::stream() const {
|
||||
return m_os;
|
||||
}
|
||||
|
||||
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
|
||||
std::ostream& cout() {
|
||||
return std::cout;
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@
|
||||
# pragma clang diagnostic ignored "-Wc++98-compat"
|
||||
# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
|
||||
# pragma clang diagnostic ignored "-Wswitch-enum"
|
||||
# pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||
# endif
|
||||
#elif defined __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wvariadic-macros"
|
||||
|
@@ -43,7 +43,7 @@ namespace Catch {
|
||||
|
||||
void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
|
||||
|
||||
if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) {
|
||||
if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) {
|
||||
std::ostringstream oss;
|
||||
oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo;
|
||||
throw std::domain_error( oss.str().c_str() );
|
||||
@@ -51,7 +51,7 @@ namespace Catch {
|
||||
if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
|
||||
std::ostringstream oss;
|
||||
oss << "error: tag alias, \"" << alias << "\" already registered.\n"
|
||||
<< "\tFirst seen at " << find(alias)->lineInfo << "\n"
|
||||
<< "\tFirst seen at " << find(alias)->lineInfo << '\n'
|
||||
<< "\tRedefined at " << lineInfo;
|
||||
throw std::domain_error( oss.str().c_str() );
|
||||
}
|
||||
|
@@ -29,9 +29,10 @@ namespace Catch {
|
||||
IsHidden = 1 << 1,
|
||||
ShouldFail = 1 << 2,
|
||||
MayFail = 1 << 3,
|
||||
Throws = 1 << 4
|
||||
Throws = 1 << 4,
|
||||
NonPortable = 1 << 5
|
||||
};
|
||||
|
||||
|
||||
TestCaseInfo( std::string const& _name,
|
||||
std::string const& _className,
|
||||
std::string const& _description,
|
||||
@@ -41,7 +42,7 @@ namespace Catch {
|
||||
TestCaseInfo( TestCaseInfo const& other );
|
||||
|
||||
friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
|
||||
|
||||
|
||||
bool isHidden() const;
|
||||
bool throws() const;
|
||||
bool okToFail() const;
|
||||
|
@@ -16,7 +16,7 @@
|
||||
namespace Catch {
|
||||
|
||||
inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
|
||||
if( startsWith( tag, "." ) ||
|
||||
if( startsWith( tag, '.' ) ||
|
||||
tag == "hide" ||
|
||||
tag == "!hide" )
|
||||
return TestCaseInfo::IsHidden;
|
||||
@@ -26,6 +26,8 @@ namespace Catch {
|
||||
return TestCaseInfo::ShouldFail;
|
||||
else if( tag == "!mayfail" )
|
||||
return TestCaseInfo::MayFail;
|
||||
else if( tag == "!nonportable" )
|
||||
return TestCaseInfo::NonPortable;
|
||||
else
|
||||
return TestCaseInfo::None;
|
||||
}
|
||||
@@ -88,7 +90,7 @@ namespace Catch {
|
||||
tags.insert( "hide" );
|
||||
tags.insert( "." );
|
||||
}
|
||||
|
||||
|
||||
TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
|
||||
return TestCase( _testCase, info );
|
||||
}
|
||||
@@ -97,17 +99,17 @@ namespace Catch {
|
||||
{
|
||||
testCaseInfo.tags = tags;
|
||||
testCaseInfo.lcaseTags.clear();
|
||||
|
||||
|
||||
std::ostringstream oss;
|
||||
for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
|
||||
oss << "[" << *it << "]";
|
||||
oss << '[' << *it << ']';
|
||||
std::string lcaseTag = toLower( *it );
|
||||
testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
|
||||
testCaseInfo.lcaseTags.insert( lcaseTag );
|
||||
}
|
||||
testCaseInfo.tagsAsString = oss.str();
|
||||
}
|
||||
|
||||
|
||||
TestCaseInfo::TestCaseInfo( std::string const& _name,
|
||||
std::string const& _className,
|
||||
std::string const& _description,
|
||||
|
@@ -19,29 +19,42 @@
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct LexSort {
|
||||
bool operator() (TestCase i,TestCase j) const { return (i<j);}
|
||||
};
|
||||
struct RandomNumberGenerator {
|
||||
int operator()( int n ) const { return std::rand() % n; }
|
||||
typedef std::ptrdiff_t result_type;
|
||||
|
||||
result_type operator()( result_type n ) const { return std::rand() % n; }
|
||||
|
||||
#ifdef CATCH_CONFIG_CPP11_SHUFFLE
|
||||
static constexpr result_type min() { return 0; }
|
||||
static constexpr result_type max() { return 1000000; }
|
||||
result_type operator()() const { return std::rand() % max(); }
|
||||
#endif
|
||||
template<typename V>
|
||||
static void shuffle( V& vector ) {
|
||||
RandomNumberGenerator rng;
|
||||
#ifdef CATCH_CONFIG_CPP11_SHUFFLE
|
||||
std::shuffle( vector.begin(), vector.end(), rng );
|
||||
#else
|
||||
std::random_shuffle( vector.begin(), vector.end(), rng );
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
|
||||
|
||||
|
||||
std::vector<TestCase> sorted = unsortedTestCases;
|
||||
|
||||
|
||||
switch( config.runOrder() ) {
|
||||
case RunTests::InLexicographicalOrder:
|
||||
std::sort( sorted.begin(), sorted.end(), LexSort() );
|
||||
std::sort( sorted.begin(), sorted.end() );
|
||||
break;
|
||||
case RunTests::InRandomOrder:
|
||||
{
|
||||
seedRng( config );
|
||||
|
||||
RandomNumberGenerator rng;
|
||||
std::random_shuffle( sorted.begin(), sorted.end(), rng );
|
||||
RandomNumberGenerator::shuffle( sorted );
|
||||
}
|
||||
break;
|
||||
case RunTests::InDeclarationOrder:
|
||||
@@ -60,17 +73,19 @@ namespace Catch {
|
||||
it != itEnd;
|
||||
++it ) {
|
||||
std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
|
||||
if( !prev.second ){
|
||||
Catch::cerr()
|
||||
<< Colour( Colour::Red )
|
||||
<< "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
|
||||
<< "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
|
||||
<< "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
|
||||
exit(1);
|
||||
if( !prev.second ) {
|
||||
std::ostringstream ss;
|
||||
|
||||
ss << Colour( Colour::Red )
|
||||
<< "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
|
||||
<< "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n'
|
||||
<< "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
|
||||
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
|
||||
std::vector<TestCase> filtered;
|
||||
filtered.reserve( testCases.size() );
|
||||
@@ -87,12 +102,15 @@ namespace Catch {
|
||||
|
||||
class TestRegistry : public ITestCaseRegistry {
|
||||
public:
|
||||
TestRegistry() : m_unnamedCount( 0 ) {}
|
||||
TestRegistry()
|
||||
: m_currentSortOrder( RunTests::InDeclarationOrder ),
|
||||
m_unnamedCount( 0 )
|
||||
{}
|
||||
virtual ~TestRegistry();
|
||||
|
||||
virtual void registerTest( TestCase const& testCase ) {
|
||||
std::string name = testCase.getTestCaseInfo().name;
|
||||
if( name == "" ) {
|
||||
if( name.empty() ) {
|
||||
std::ostringstream oss;
|
||||
oss << "Anonymous test case " << ++m_unnamedCount;
|
||||
return registerTest( testCase.withName( oss.str() ) );
|
||||
@@ -141,7 +159,7 @@ namespace Catch {
|
||||
|
||||
inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
|
||||
std::string className = classOrQualifiedMethodName;
|
||||
if( startsWith( className, "&" ) )
|
||||
if( startsWith( className, '&' ) )
|
||||
{
|
||||
std::size_t lastColons = className.rfind( "::" );
|
||||
std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
|
||||
@@ -152,29 +170,38 @@ namespace Catch {
|
||||
return className;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
void registerTestCase
|
||||
( ITestCase* testCase,
|
||||
char const* classOrQualifiedMethodName,
|
||||
NameAndDesc const& nameAndDesc,
|
||||
SourceLineInfo const& lineInfo ) {
|
||||
|
||||
AutoReg::AutoReg( TestFunction function,
|
||||
SourceLineInfo const& lineInfo,
|
||||
NameAndDesc const& nameAndDesc ) {
|
||||
getMutableRegistryHub().registerTest
|
||||
( makeTestCase
|
||||
( testCase,
|
||||
extractClassName( classOrQualifiedMethodName ),
|
||||
nameAndDesc.name,
|
||||
nameAndDesc.description,
|
||||
lineInfo ) );
|
||||
}
|
||||
void registerTestCaseFunction
|
||||
( TestFunction function,
|
||||
SourceLineInfo const& lineInfo,
|
||||
NameAndDesc const& nameAndDesc ) {
|
||||
registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
|
||||
}
|
||||
|
||||
AutoReg::~AutoReg() {}
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AutoReg::registerTestCase( ITestCase* testCase,
|
||||
char const* classOrQualifiedMethodName,
|
||||
NameAndDesc const& nameAndDesc,
|
||||
SourceLineInfo const& lineInfo ) {
|
||||
|
||||
getMutableRegistryHub().registerTest
|
||||
( makeTestCase( testCase,
|
||||
extractClassName( classOrQualifiedMethodName ),
|
||||
nameAndDesc.name,
|
||||
nameAndDesc.description,
|
||||
lineInfo ) );
|
||||
AutoReg::AutoReg
|
||||
( TestFunction function,
|
||||
SourceLineInfo const& lineInfo,
|
||||
NameAndDesc const& nameAndDesc ) {
|
||||
registerTestCaseFunction( function, lineInfo, nameAndDesc );
|
||||
}
|
||||
|
||||
AutoReg::~AutoReg() {}
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
|
||||
|
@@ -9,141 +9,358 @@
|
||||
#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
|
||||
|
||||
#include "catch_compiler_capabilities.h"
|
||||
#include "catch_ptr.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
|
||||
namespace Catch {
|
||||
namespace SectionTracking {
|
||||
namespace TestCaseTracking {
|
||||
|
||||
struct NameAndLocation {
|
||||
std::string name;
|
||||
SourceLineInfo location;
|
||||
|
||||
NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
|
||||
: name( _name ),
|
||||
location( _location )
|
||||
{}
|
||||
};
|
||||
|
||||
struct ITracker : SharedImpl<> {
|
||||
virtual ~ITracker();
|
||||
|
||||
// static queries
|
||||
virtual NameAndLocation const& nameAndLocation() const = 0;
|
||||
|
||||
// dynamic queries
|
||||
virtual bool isComplete() const = 0; // Successfully completed or failed
|
||||
virtual bool isSuccessfullyCompleted() const = 0;
|
||||
virtual bool isOpen() const = 0; // Started but not complete
|
||||
virtual bool hasChildren() const = 0;
|
||||
|
||||
virtual ITracker& parent() = 0;
|
||||
|
||||
// actions
|
||||
virtual void close() = 0; // Successfully complete
|
||||
virtual void fail() = 0;
|
||||
virtual void markAsNeedingAnotherRun() = 0;
|
||||
|
||||
virtual void addChild( Ptr<ITracker> const& child ) = 0;
|
||||
virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0;
|
||||
virtual void openChild() = 0;
|
||||
|
||||
// Debug/ checking
|
||||
virtual bool isSectionTracker() const = 0;
|
||||
virtual bool isIndexTracker() const = 0;
|
||||
};
|
||||
|
||||
class TrackerContext {
|
||||
|
||||
class TrackedSection {
|
||||
|
||||
typedef std::map<std::string, TrackedSection> TrackedSections;
|
||||
|
||||
public:
|
||||
enum RunState {
|
||||
NotStarted,
|
||||
Executing,
|
||||
ExecutingChildren,
|
||||
Completed
|
||||
CompletedCycle
|
||||
};
|
||||
|
||||
TrackedSection( std::string const& name, TrackedSection* parent )
|
||||
: m_name( name ), m_runState( NotStarted ), m_parent( parent )
|
||||
|
||||
Ptr<ITracker> m_rootTracker;
|
||||
ITracker* m_currentTracker;
|
||||
RunState m_runState;
|
||||
|
||||
public:
|
||||
|
||||
static TrackerContext& instance() {
|
||||
static TrackerContext s_instance;
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
TrackerContext()
|
||||
: m_currentTracker( CATCH_NULL ),
|
||||
m_runState( NotStarted )
|
||||
{}
|
||||
|
||||
RunState runState() const { return m_runState; }
|
||||
|
||||
TrackedSection* findChild( std::string const& childName );
|
||||
TrackedSection* acquireChild( std::string const& childName );
|
||||
|
||||
void enter() {
|
||||
if( m_runState == NotStarted )
|
||||
m_runState = Executing;
|
||||
}
|
||||
void leave();
|
||||
|
||||
TrackedSection* getParent() {
|
||||
return m_parent;
|
||||
ITracker& startRun();
|
||||
|
||||
void endRun() {
|
||||
m_rootTracker.reset();
|
||||
m_currentTracker = CATCH_NULL;
|
||||
m_runState = NotStarted;
|
||||
}
|
||||
bool hasChildren() const {
|
||||
|
||||
void startCycle() {
|
||||
m_currentTracker = m_rootTracker.get();
|
||||
m_runState = Executing;
|
||||
}
|
||||
void completeCycle() {
|
||||
m_runState = CompletedCycle;
|
||||
}
|
||||
|
||||
bool completedCycle() const {
|
||||
return m_runState == CompletedCycle;
|
||||
}
|
||||
ITracker& currentTracker() {
|
||||
return *m_currentTracker;
|
||||
}
|
||||
void setCurrentTracker( ITracker* tracker ) {
|
||||
m_currentTracker = tracker;
|
||||
}
|
||||
};
|
||||
|
||||
class TrackerBase : public ITracker {
|
||||
protected:
|
||||
enum CycleState {
|
||||
NotStarted,
|
||||
Executing,
|
||||
ExecutingChildren,
|
||||
NeedsAnotherRun,
|
||||
CompletedSuccessfully,
|
||||
Failed
|
||||
};
|
||||
class TrackerHasName {
|
||||
NameAndLocation m_nameAndLocation;
|
||||
public:
|
||||
TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
|
||||
bool operator ()( Ptr<ITracker> const& tracker ) {
|
||||
return
|
||||
tracker->nameAndLocation().name == m_nameAndLocation.name &&
|
||||
tracker->nameAndLocation().location == m_nameAndLocation.location;
|
||||
}
|
||||
};
|
||||
typedef std::vector<Ptr<ITracker> > Children;
|
||||
NameAndLocation m_nameAndLocation;
|
||||
TrackerContext& m_ctx;
|
||||
ITracker* m_parent;
|
||||
Children m_children;
|
||||
CycleState m_runState;
|
||||
public:
|
||||
TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||
: m_nameAndLocation( nameAndLocation ),
|
||||
m_ctx( ctx ),
|
||||
m_parent( parent ),
|
||||
m_runState( NotStarted )
|
||||
{}
|
||||
virtual ~TrackerBase();
|
||||
|
||||
virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE {
|
||||
return m_nameAndLocation;
|
||||
}
|
||||
virtual bool isComplete() const CATCH_OVERRIDE {
|
||||
return m_runState == CompletedSuccessfully || m_runState == Failed;
|
||||
}
|
||||
virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
|
||||
return m_runState == CompletedSuccessfully;
|
||||
}
|
||||
virtual bool isOpen() const CATCH_OVERRIDE {
|
||||
return m_runState != NotStarted && !isComplete();
|
||||
}
|
||||
virtual bool hasChildren() const CATCH_OVERRIDE {
|
||||
return !m_children.empty();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
RunState m_runState;
|
||||
TrackedSections m_children;
|
||||
TrackedSection* m_parent;
|
||||
};
|
||||
|
||||
inline TrackedSection* TrackedSection::findChild( std::string const& childName ) {
|
||||
TrackedSections::iterator it = m_children.find( childName );
|
||||
return it != m_children.end()
|
||||
? &it->second
|
||||
: CATCH_NULL;
|
||||
}
|
||||
inline TrackedSection* TrackedSection::acquireChild( std::string const& childName ) {
|
||||
if( TrackedSection* child = findChild( childName ) )
|
||||
return child;
|
||||
m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
|
||||
return findChild( childName );
|
||||
}
|
||||
inline void TrackedSection::leave() {
|
||||
for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
|
||||
it != itEnd;
|
||||
++it )
|
||||
if( it->second.runState() != Completed ) {
|
||||
|
||||
|
||||
virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
|
||||
m_children.push_back( child );
|
||||
}
|
||||
|
||||
virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE {
|
||||
Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
|
||||
return( it != m_children.end() )
|
||||
? it->get()
|
||||
: CATCH_NULL;
|
||||
}
|
||||
virtual ITracker& parent() CATCH_OVERRIDE {
|
||||
assert( m_parent ); // Should always be non-null except for root
|
||||
return *m_parent;
|
||||
}
|
||||
|
||||
virtual void openChild() CATCH_OVERRIDE {
|
||||
if( m_runState != ExecutingChildren ) {
|
||||
m_runState = ExecutingChildren;
|
||||
return;
|
||||
if( m_parent )
|
||||
m_parent->openChild();
|
||||
}
|
||||
m_runState = Completed;
|
||||
}
|
||||
|
||||
class TestCaseTracker {
|
||||
public:
|
||||
TestCaseTracker( std::string const& testCaseName )
|
||||
: m_testCase( testCaseName, CATCH_NULL ),
|
||||
m_currentSection( &m_testCase ),
|
||||
m_completedASectionThisRun( false )
|
||||
{}
|
||||
|
||||
bool enterSection( std::string const& name ) {
|
||||
TrackedSection* child = m_currentSection->acquireChild( name );
|
||||
if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed )
|
||||
return false;
|
||||
|
||||
m_currentSection = child;
|
||||
m_currentSection->enter();
|
||||
return true;
|
||||
}
|
||||
void leaveSection() {
|
||||
m_currentSection->leave();
|
||||
m_currentSection = m_currentSection->getParent();
|
||||
assert( m_currentSection != CATCH_NULL );
|
||||
m_completedASectionThisRun = true;
|
||||
}
|
||||
|
||||
bool currentSectionHasChildren() const {
|
||||
return m_currentSection->hasChildren();
|
||||
}
|
||||
bool isCompleted() const {
|
||||
return m_testCase.runState() == TrackedSection::Completed;
|
||||
virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
|
||||
virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
|
||||
|
||||
void open() {
|
||||
m_runState = Executing;
|
||||
moveToThis();
|
||||
if( m_parent )
|
||||
m_parent->openChild();
|
||||
}
|
||||
|
||||
class Guard {
|
||||
public:
|
||||
Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) {
|
||||
m_tracker.enterTestCase();
|
||||
virtual void close() CATCH_OVERRIDE {
|
||||
|
||||
// Close any still open children (e.g. generators)
|
||||
while( &m_ctx.currentTracker() != this )
|
||||
m_ctx.currentTracker().close();
|
||||
|
||||
switch( m_runState ) {
|
||||
case NotStarted:
|
||||
case CompletedSuccessfully:
|
||||
case Failed:
|
||||
throw std::logic_error( "Illogical state" );
|
||||
|
||||
case NeedsAnotherRun:
|
||||
break;;
|
||||
|
||||
case Executing:
|
||||
m_runState = CompletedSuccessfully;
|
||||
break;
|
||||
case ExecutingChildren:
|
||||
if( m_children.empty() || m_children.back()->isComplete() )
|
||||
m_runState = CompletedSuccessfully;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::logic_error( "Unexpected state" );
|
||||
}
|
||||
~Guard() {
|
||||
m_tracker.leaveTestCase();
|
||||
}
|
||||
private:
|
||||
Guard( Guard const& );
|
||||
void operator = ( Guard const& );
|
||||
TestCaseTracker& m_tracker;
|
||||
};
|
||||
|
||||
moveToParent();
|
||||
m_ctx.completeCycle();
|
||||
}
|
||||
virtual void fail() CATCH_OVERRIDE {
|
||||
m_runState = Failed;
|
||||
if( m_parent )
|
||||
m_parent->markAsNeedingAnotherRun();
|
||||
moveToParent();
|
||||
m_ctx.completeCycle();
|
||||
}
|
||||
virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
|
||||
m_runState = NeedsAnotherRun;
|
||||
}
|
||||
private:
|
||||
void enterTestCase() {
|
||||
m_currentSection = &m_testCase;
|
||||
m_completedASectionThisRun = false;
|
||||
m_testCase.enter();
|
||||
void moveToParent() {
|
||||
assert( m_parent );
|
||||
m_ctx.setCurrentTracker( m_parent );
|
||||
}
|
||||
void leaveTestCase() {
|
||||
m_testCase.leave();
|
||||
void moveToThis() {
|
||||
m_ctx.setCurrentTracker( this );
|
||||
}
|
||||
|
||||
TrackedSection m_testCase;
|
||||
TrackedSection* m_currentSection;
|
||||
bool m_completedASectionThisRun;
|
||||
};
|
||||
|
||||
} // namespace SectionTracking
|
||||
class SectionTracker : public TrackerBase {
|
||||
std::vector<std::string> m_filters;
|
||||
public:
|
||||
SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
|
||||
: TrackerBase( nameAndLocation, ctx, parent )
|
||||
{
|
||||
if( parent ) {
|
||||
while( !parent->isSectionTracker() )
|
||||
parent = &parent->parent();
|
||||
|
||||
using SectionTracking::TestCaseTracker;
|
||||
SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
|
||||
addNextFilters( parentSection.m_filters );
|
||||
}
|
||||
}
|
||||
virtual ~SectionTracker();
|
||||
|
||||
virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
|
||||
|
||||
static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
|
||||
SectionTracker* section = CATCH_NULL;
|
||||
|
||||
ITracker& currentTracker = ctx.currentTracker();
|
||||
if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
|
||||
assert( childTracker );
|
||||
assert( childTracker->isSectionTracker() );
|
||||
section = static_cast<SectionTracker*>( childTracker );
|
||||
}
|
||||
else {
|
||||
section = new SectionTracker( nameAndLocation, ctx, ¤tTracker );
|
||||
currentTracker.addChild( section );
|
||||
}
|
||||
if( !ctx.completedCycle() )
|
||||
section->tryOpen();
|
||||
return *section;
|
||||
}
|
||||
|
||||
void tryOpen() {
|
||||
if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
|
||||
open();
|
||||
}
|
||||
|
||||
void addInitialFilters( std::vector<std::string> const& filters ) {
|
||||
if( !filters.empty() ) {
|
||||
m_filters.push_back(""); // Root - should never be consulted
|
||||
m_filters.push_back(""); // Test Case - not a section filter
|
||||
std::copy( filters.begin(), filters.end(), std::back_inserter( m_filters ) );
|
||||
}
|
||||
}
|
||||
void addNextFilters( std::vector<std::string> const& filters ) {
|
||||
if( filters.size() > 1 )
|
||||
std::copy( filters.begin()+1, filters.end(), std::back_inserter( m_filters ) );
|
||||
}
|
||||
};
|
||||
|
||||
class IndexTracker : public TrackerBase {
|
||||
int m_size;
|
||||
int m_index;
|
||||
public:
|
||||
IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
|
||||
: TrackerBase( nameAndLocation, ctx, parent ),
|
||||
m_size( size ),
|
||||
m_index( -1 )
|
||||
{}
|
||||
virtual ~IndexTracker();
|
||||
|
||||
virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
|
||||
|
||||
static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
|
||||
IndexTracker* tracker = CATCH_NULL;
|
||||
|
||||
ITracker& currentTracker = ctx.currentTracker();
|
||||
if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
|
||||
assert( childTracker );
|
||||
assert( childTracker->isIndexTracker() );
|
||||
tracker = static_cast<IndexTracker*>( childTracker );
|
||||
}
|
||||
else {
|
||||
tracker = new IndexTracker( nameAndLocation, ctx, ¤tTracker, size );
|
||||
currentTracker.addChild( tracker );
|
||||
}
|
||||
|
||||
if( !ctx.completedCycle() && !tracker->isComplete() ) {
|
||||
if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
|
||||
tracker->moveNext();
|
||||
tracker->open();
|
||||
}
|
||||
|
||||
return *tracker;
|
||||
}
|
||||
|
||||
int index() const { return m_index; }
|
||||
|
||||
void moveNext() {
|
||||
m_index++;
|
||||
m_children.clear();
|
||||
}
|
||||
|
||||
virtual void close() CATCH_OVERRIDE {
|
||||
TrackerBase::close();
|
||||
if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
|
||||
m_runState = Executing;
|
||||
}
|
||||
};
|
||||
|
||||
inline ITracker& TrackerContext::startRun() {
|
||||
m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL );
|
||||
m_currentTracker = CATCH_NULL;
|
||||
m_runState = Executing;
|
||||
return *m_rootTracker;
|
||||
}
|
||||
|
||||
} // namespace TestCaseTracking
|
||||
|
||||
using TestCaseTracking::ITracker;
|
||||
using TestCaseTracking::TrackerContext;
|
||||
using TestCaseTracking::SectionTracker;
|
||||
using TestCaseTracking::IndexTracker;
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
|
@@ -42,27 +42,32 @@ struct NameAndDesc {
|
||||
const char* description;
|
||||
};
|
||||
|
||||
void registerTestCase
|
||||
( ITestCase* testCase,
|
||||
char const* className,
|
||||
NameAndDesc const& nameAndDesc,
|
||||
SourceLineInfo const& lineInfo );
|
||||
|
||||
struct AutoReg {
|
||||
|
||||
AutoReg( TestFunction function,
|
||||
SourceLineInfo const& lineInfo,
|
||||
NameAndDesc const& nameAndDesc );
|
||||
AutoReg
|
||||
( TestFunction function,
|
||||
SourceLineInfo const& lineInfo,
|
||||
NameAndDesc const& nameAndDesc );
|
||||
|
||||
template<typename C>
|
||||
AutoReg( void (C::*method)(),
|
||||
char const* className,
|
||||
NameAndDesc const& nameAndDesc,
|
||||
SourceLineInfo const& lineInfo ) {
|
||||
registerTestCase( new MethodTestCase<C>( method ),
|
||||
className,
|
||||
nameAndDesc,
|
||||
lineInfo );
|
||||
}
|
||||
AutoReg
|
||||
( void (C::*method)(),
|
||||
char const* className,
|
||||
NameAndDesc const& nameAndDesc,
|
||||
SourceLineInfo const& lineInfo ) {
|
||||
|
||||
void registerTestCase( ITestCase* testCase,
|
||||
char const* className,
|
||||
NameAndDesc const& nameAndDesc,
|
||||
SourceLineInfo const& lineInfo );
|
||||
registerTestCase
|
||||
( new MethodTestCase<C>( method ),
|
||||
className,
|
||||
nameAndDesc,
|
||||
lineInfo );
|
||||
}
|
||||
|
||||
~AutoReg();
|
||||
|
||||
@@ -71,50 +76,70 @@ private:
|
||||
void operator= ( AutoReg const& );
|
||||
};
|
||||
|
||||
void registerTestCaseFunction
|
||||
( TestFunction function,
|
||||
SourceLineInfo const& lineInfo,
|
||||
NameAndDesc const& nameAndDesc );
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#ifdef CATCH_CONFIG_VARIADIC_MACROS
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
|
||||
static void TestName(); \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
|
||||
static void TestName()
|
||||
#define INTERNAL_CATCH_TESTCASE( ... ) \
|
||||
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
|
||||
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
|
||||
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
|
||||
namespace{ \
|
||||
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
|
||||
struct TestName : ClassName{ \
|
||||
void test(); \
|
||||
}; \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
|
||||
} \
|
||||
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
|
||||
void TestName::test()
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
|
||||
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
|
||||
Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
|
||||
|
||||
#else
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
|
||||
static void TestName(); \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
|
||||
static void TestName()
|
||||
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
|
||||
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
|
||||
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
|
||||
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
|
||||
namespace{ \
|
||||
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
|
||||
struct TestCaseName : ClassName{ \
|
||||
void test(); \
|
||||
}; \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
|
||||
} \
|
||||
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
|
||||
void TestCaseName::test()
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
|
||||
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
|
||||
Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
|
||||
|
@@ -20,7 +20,7 @@
|
||||
#include <vector>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
|
||||
class TestSpec {
|
||||
struct Pattern : SharedImpl<> {
|
||||
virtual ~Pattern();
|
||||
@@ -38,7 +38,7 @@ namespace Catch {
|
||||
private:
|
||||
WildcardPattern m_wildcardPattern;
|
||||
};
|
||||
|
||||
|
||||
class TagPattern : public Pattern {
|
||||
public:
|
||||
TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
|
||||
@@ -49,7 +49,7 @@ namespace Catch {
|
||||
private:
|
||||
std::string m_tag;
|
||||
};
|
||||
|
||||
|
||||
class ExcludedPattern : public Pattern {
|
||||
public:
|
||||
ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
|
||||
@@ -64,10 +64,11 @@ namespace Catch {
|
||||
|
||||
bool matches( TestCaseInfo const& testCase ) const {
|
||||
// All patterns in a filter must match for the filter to be a match
|
||||
for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
|
||||
for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
|
||||
if( !(*it)->matches( testCase ) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -19,11 +19,12 @@
|
||||
namespace Catch {
|
||||
|
||||
class TestSpecParser {
|
||||
enum Mode{ None, Name, QuotedName, Tag };
|
||||
enum Mode{ None, Name, QuotedName, Tag, EscapedName };
|
||||
Mode m_mode;
|
||||
bool m_exclusion;
|
||||
std::size_t m_start, m_pos;
|
||||
std::string m_arg;
|
||||
std::vector<std::size_t> m_escapeChars;
|
||||
TestSpec::Filter m_currentFilter;
|
||||
TestSpec m_testSpec;
|
||||
ITagAliasRegistry const* m_tagAliases;
|
||||
@@ -36,6 +37,7 @@ namespace Catch {
|
||||
m_exclusion = false;
|
||||
m_start = std::string::npos;
|
||||
m_arg = m_tagAliases->expandAliases( arg );
|
||||
m_escapeChars.clear();
|
||||
for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
|
||||
visitChar( m_arg[m_pos] );
|
||||
if( m_mode == Name )
|
||||
@@ -54,6 +56,7 @@ namespace Catch {
|
||||
case '~': m_exclusion = true; return;
|
||||
case '[': return startNewMode( Tag, ++m_pos );
|
||||
case '"': return startNewMode( QuotedName, ++m_pos );
|
||||
case '\\': return escape();
|
||||
default: startNewMode( Name, m_pos ); break;
|
||||
}
|
||||
}
|
||||
@@ -69,7 +72,11 @@ namespace Catch {
|
||||
addPattern<TestSpec::NamePattern>();
|
||||
startNewMode( Tag, ++m_pos );
|
||||
}
|
||||
else if( c == '\\' )
|
||||
escape();
|
||||
}
|
||||
else if( m_mode == EscapedName )
|
||||
m_mode = Name;
|
||||
else if( m_mode == QuotedName && c == '"' )
|
||||
addPattern<TestSpec::NamePattern>();
|
||||
else if( m_mode == Tag && c == ']' )
|
||||
@@ -79,10 +86,19 @@ namespace Catch {
|
||||
m_mode = mode;
|
||||
m_start = start;
|
||||
}
|
||||
void escape() {
|
||||
if( m_mode == None )
|
||||
m_start = m_pos;
|
||||
m_mode = EscapedName;
|
||||
m_escapeChars.push_back( m_pos );
|
||||
}
|
||||
std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
|
||||
template<typename T>
|
||||
void addPattern() {
|
||||
std::string token = subString();
|
||||
for( size_t i = 0; i < m_escapeChars.size(); ++i )
|
||||
token = token.substr( 0, m_escapeChars[i]-i ) + token.substr( m_escapeChars[i]+1-i );
|
||||
m_escapeChars.clear();
|
||||
if( startsWith( token, "exclude:" ) ) {
|
||||
m_exclusion = true;
|
||||
token = token.substr( 8 );
|
||||
|
@@ -15,7 +15,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef CATCH_PLATFORM_WINDOWS
|
||||
#include <windows.h>
|
||||
#include "catch_windows_h_proxy.h"
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
@@ -67,7 +67,7 @@ std::string toString( std::nullptr_t );
|
||||
std::string toString( NSObject* const& nsObject );
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace Detail {
|
||||
|
||||
extern const std::string unprintableString;
|
||||
@@ -78,7 +78,7 @@ namespace Detail {
|
||||
|
||||
struct TrueType { char sizer[1]; };
|
||||
struct FalseType { char sizer[2]; };
|
||||
|
||||
|
||||
TrueType& testStreamable( std::ostream& );
|
||||
FalseType testStreamable( FalseType );
|
||||
|
||||
|
@@ -16,7 +16,7 @@ namespace Catch {
|
||||
namespace Detail {
|
||||
|
||||
const std::string unprintableString = "{?}";
|
||||
|
||||
|
||||
namespace {
|
||||
const int hexThreshold = 255;
|
||||
|
||||
@@ -69,7 +69,7 @@ std::string toString( std::string const& value ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return "\"" + s + "\"";
|
||||
return '"' + s + '"';
|
||||
}
|
||||
std::string toString( std::wstring const& value ) {
|
||||
|
||||
@@ -90,19 +90,19 @@ std::string toString( char* const value ) {
|
||||
|
||||
std::string toString( const wchar_t* const value )
|
||||
{
|
||||
return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
|
||||
return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
|
||||
}
|
||||
|
||||
std::string toString( wchar_t* const value )
|
||||
{
|
||||
return Catch::toString( static_cast<const wchar_t*>( value ) );
|
||||
return Catch::toString( static_cast<const wchar_t*>( value ) );
|
||||
}
|
||||
|
||||
std::string toString( int value ) {
|
||||
std::ostringstream oss;
|
||||
oss << value;
|
||||
if( value > Detail::hexThreshold )
|
||||
oss << " (0x" << std::hex << value << ")";
|
||||
oss << " (0x" << std::hex << value << ')';
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ std::string toString( unsigned long value ) {
|
||||
std::ostringstream oss;
|
||||
oss << value;
|
||||
if( value > Detail::hexThreshold )
|
||||
oss << " (0x" << std::hex << value << ")";
|
||||
oss << " (0x" << std::hex << value << ')';
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ std::string toString( const double value ) {
|
||||
return fpToString( value, 10 );
|
||||
}
|
||||
std::string toString( const float value ) {
|
||||
return fpToString( value, 5 ) + "f";
|
||||
return fpToString( value, 5 ) + 'f';
|
||||
}
|
||||
|
||||
std::string toString( bool value ) {
|
||||
@@ -146,9 +146,19 @@ std::string toString( bool value ) {
|
||||
}
|
||||
|
||||
std::string toString( char value ) {
|
||||
return value < ' '
|
||||
? toString( static_cast<unsigned int>( value ) )
|
||||
: Detail::makeString( value );
|
||||
if ( value == '\r' )
|
||||
return "'\\r'";
|
||||
if ( value == '\f' )
|
||||
return "'\\f'";
|
||||
if ( value == '\n' )
|
||||
return "'\\n'";
|
||||
if ( value == '\t' )
|
||||
return "'\\t'";
|
||||
if ( '\0' <= value && value < ' ' )
|
||||
return toString( static_cast<unsigned int>( value ) );
|
||||
char chstr[] = "' '";
|
||||
chstr[1] = value;
|
||||
return chstr;
|
||||
}
|
||||
|
||||
std::string toString( signed char value ) {
|
||||
@@ -164,18 +174,18 @@ std::string toString( long long value ) {
|
||||
std::ostringstream oss;
|
||||
oss << value;
|
||||
if( value > Detail::hexThreshold )
|
||||
oss << " (0x" << std::hex << value << ")";
|
||||
oss << " (0x" << std::hex << value << ')';
|
||||
return oss.str();
|
||||
}
|
||||
std::string toString( unsigned long long value ) {
|
||||
std::ostringstream oss;
|
||||
oss << value;
|
||||
if( value > Detail::hexThreshold )
|
||||
oss << " (0x" << std::hex << value << ")";
|
||||
oss << " (0x" << std::hex << value << ')';
|
||||
return oss.str();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CATCH_CONFIG_CPP11_NULLPTR
|
||||
std::string toString( std::nullptr_t ) {
|
||||
return "nullptr";
|
||||
|
@@ -27,7 +27,7 @@ namespace Catch {
|
||||
unsigned int const buildNumber;
|
||||
|
||||
friend std::ostream& operator << ( std::ostream& os, Version const& version );
|
||||
|
||||
|
||||
private:
|
||||
void operator=( Version const& );
|
||||
};
|
||||
|
@@ -26,18 +26,18 @@ namespace Catch {
|
||||
{}
|
||||
|
||||
std::ostream& operator << ( std::ostream& os, Version const& version ) {
|
||||
os << version.majorVersion << "."
|
||||
<< version.minorVersion << "."
|
||||
os << version.majorVersion << '.'
|
||||
<< version.minorVersion << '.'
|
||||
<< version.patchNumber;
|
||||
|
||||
if( !version.branchName.empty() ) {
|
||||
os << "-" << version.branchName
|
||||
<< "." << version.buildNumber;
|
||||
os << '-' << version.branchName
|
||||
<< '.' << version.buildNumber;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
Version libraryVersion( 1, 2, 1, "develop", 14 );
|
||||
Version libraryVersion( 1, 7, 1, "", 0 );
|
||||
|
||||
}
|
||||
|
||||
|
@@ -19,19 +19,19 @@ namespace Catch
|
||||
WildcardAtEnd = 2,
|
||||
WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
|
||||
: m_caseSensitivity( caseSensitivity ),
|
||||
m_wildcard( NoWildcard ),
|
||||
m_pattern( adjustCase( pattern ) )
|
||||
{
|
||||
if( startsWith( m_pattern, "*" ) ) {
|
||||
if( startsWith( m_pattern, '*' ) ) {
|
||||
m_pattern = m_pattern.substr( 1 );
|
||||
m_wildcard = WildcardAtStart;
|
||||
}
|
||||
if( endsWith( m_pattern, "*" ) ) {
|
||||
if( endsWith( m_pattern, '*' ) ) {
|
||||
m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
|
||||
m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
|
||||
}
|
||||
@@ -48,7 +48,7 @@ namespace Catch
|
||||
case WildcardAtBothEnds:
|
||||
return contains( adjustCase( str ), m_pattern );
|
||||
}
|
||||
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunreachable-code"
|
||||
|
32
include/internal/catch_windows_h_proxy.h
Normal file
32
include/internal/catch_windows_h_proxy.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Created by Martin on 16/01/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_WINDOWS_H_PROXY_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED
|
||||
|
||||
#ifdef CATCH_DEFINES_NOMINMAX
|
||||
# define NOMINMAX
|
||||
#endif
|
||||
#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#ifdef __AFXDLL
|
||||
#include <AfxWin.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef CATCH_DEFINES_NOMINMAX
|
||||
# undef NOMINMAX
|
||||
#endif
|
||||
#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED
|
@@ -22,23 +22,23 @@ namespace Catch {
|
||||
class XmlEncode {
|
||||
public:
|
||||
enum ForWhat { ForTextNodes, ForAttributes };
|
||||
|
||||
|
||||
XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
|
||||
: m_str( str ),
|
||||
m_forWhat( forWhat )
|
||||
{}
|
||||
|
||||
|
||||
void encodeTo( std::ostream& os ) const {
|
||||
|
||||
// Apostrophe escaping not necessary if we always use " to write attributes
|
||||
// (see: http://www.w3.org/TR/xml/#syntax)
|
||||
|
||||
|
||||
for( std::size_t i = 0; i < m_str.size(); ++ i ) {
|
||||
char c = m_str[i];
|
||||
switch( c ) {
|
||||
case '<': os << "<"; break;
|
||||
case '&': os << "&"; break;
|
||||
|
||||
|
||||
case '>':
|
||||
// See: http://www.w3.org/TR/xml/#syntax
|
||||
if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
|
||||
@@ -46,18 +46,19 @@ namespace Catch {
|
||||
else
|
||||
os << c;
|
||||
break;
|
||||
|
||||
|
||||
case '\"':
|
||||
if( m_forWhat == ForAttributes )
|
||||
os << """;
|
||||
else
|
||||
os << c;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
// Escape control chars - based on contribution by @espenalb in PR #465
|
||||
if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
|
||||
os << "&#x" << std::uppercase << std::hex << static_cast<int>( c );
|
||||
// Escape control chars - based on contribution by @espenalb in PR #465 and
|
||||
// by @mrpi PR #588
|
||||
if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
|
||||
os << "&#x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>( c ) << ';';
|
||||
else
|
||||
os << c;
|
||||
}
|
||||
@@ -68,12 +69,12 @@ namespace Catch {
|
||||
xmlEncode.encodeTo( os );
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::string m_str;
|
||||
ForWhat m_forWhat;
|
||||
};
|
||||
|
||||
|
||||
class XmlWriter {
|
||||
public:
|
||||
|
||||
@@ -112,13 +113,20 @@ namespace Catch {
|
||||
: m_tagIsOpen( false ),
|
||||
m_needsNewline( false ),
|
||||
m_os( &Catch::cout() )
|
||||
{}
|
||||
{
|
||||
// We encode control characters, which requires
|
||||
// XML 1.1
|
||||
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
|
||||
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
|
||||
}
|
||||
|
||||
XmlWriter( std::ostream& os )
|
||||
: m_tagIsOpen( false ),
|
||||
m_needsNewline( false ),
|
||||
m_os( &os )
|
||||
{}
|
||||
{
|
||||
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
|
||||
}
|
||||
|
||||
~XmlWriter() {
|
||||
while( !m_tags.empty() )
|
||||
@@ -128,7 +136,7 @@ namespace Catch {
|
||||
XmlWriter& startElement( std::string const& name ) {
|
||||
ensureTagClosed();
|
||||
newlineIfNecessary();
|
||||
stream() << m_indent << "<" << name;
|
||||
stream() << m_indent << '<' << name;
|
||||
m_tags.push_back( name );
|
||||
m_indent += " ";
|
||||
m_tagIsOpen = true;
|
||||
@@ -145,24 +153,25 @@ namespace Catch {
|
||||
newlineIfNecessary();
|
||||
m_indent = m_indent.substr( 0, m_indent.size()-2 );
|
||||
if( m_tagIsOpen ) {
|
||||
stream() << "/>\n";
|
||||
stream() << "/>";
|
||||
m_tagIsOpen = false;
|
||||
}
|
||||
else {
|
||||
stream() << m_indent << "</" << m_tags.back() << ">\n";
|
||||
stream() << m_indent << "</" << m_tags.back() << ">";
|
||||
}
|
||||
stream() << std::endl;
|
||||
m_tags.pop_back();
|
||||
return *this;
|
||||
}
|
||||
|
||||
XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
|
||||
if( !name.empty() && !attribute.empty() )
|
||||
stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\"";
|
||||
stream() << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
|
||||
return *this;
|
||||
}
|
||||
|
||||
XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
|
||||
stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
|
||||
stream() << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -194,7 +203,7 @@ namespace Catch {
|
||||
|
||||
XmlWriter& writeBlankLine() {
|
||||
ensureTagClosed();
|
||||
stream() << "\n";
|
||||
stream() << '\n';
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -219,7 +228,7 @@ namespace Catch {
|
||||
|
||||
void newlineIfNecessary() {
|
||||
if( m_needsNewline ) {
|
||||
stream() << "\n";
|
||||
stream() << '\n';
|
||||
m_needsNewline = false;
|
||||
}
|
||||
}
|
||||
|
@@ -65,7 +65,7 @@ namespace Catch {
|
||||
// It can optionally be overridden in the derived class.
|
||||
}
|
||||
|
||||
Ptr<IConfig> m_config;
|
||||
Ptr<IConfig const> m_config;
|
||||
std::ostream& stream;
|
||||
|
||||
LazyStat<TestRunInfo> currentTestRunInfo;
|
||||
@@ -108,12 +108,12 @@ namespace Catch {
|
||||
|
||||
struct BySectionInfo {
|
||||
BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
|
||||
BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
|
||||
BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
|
||||
bool operator() ( Ptr<SectionNode> const& node ) const {
|
||||
return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
|
||||
}
|
||||
private:
|
||||
void operator=( BySectionInfo const& );
|
||||
void operator=( BySectionInfo const& );
|
||||
SectionInfo const& m_other;
|
||||
};
|
||||
|
||||
@@ -166,10 +166,16 @@ namespace Catch {
|
||||
|
||||
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
|
||||
|
||||
virtual bool assertionEnded( AssertionStats const& assertionStats ) {
|
||||
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
|
||||
assert( !m_sectionStack.empty() );
|
||||
SectionNode& sectionNode = *m_sectionStack.back();
|
||||
sectionNode.assertions.push_back( assertionStats );
|
||||
// AssertionResult holds a pointer to a temporary DecomposedExpression,
|
||||
// which getExpandedExpression() calls to build the expression string.
|
||||
// Our section stack copy of the assertionResult will likely outlive the
|
||||
// temporary, so it must be expanded or discarded now to avoid calling
|
||||
// a destroyed object later.
|
||||
prepareExpandedExpression( sectionNode.assertions.back().assertionResult );
|
||||
return true;
|
||||
}
|
||||
virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
|
||||
@@ -204,7 +210,14 @@ namespace Catch {
|
||||
|
||||
virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
|
||||
|
||||
Ptr<IConfig> m_config;
|
||||
virtual void prepareExpandedExpression( AssertionResult& result ) const {
|
||||
if( result.isOk() )
|
||||
result.discardDecomposedExpression();
|
||||
else
|
||||
result.expandDecomposedExpression();
|
||||
}
|
||||
|
||||
Ptr<IConfig const> m_config;
|
||||
std::ostream& stream;
|
||||
std::vector<AssertionStats> m_assertions;
|
||||
std::vector<std::vector<Ptr<SectionNode> > > m_sections;
|
||||
@@ -230,18 +243,18 @@ namespace Catch {
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct TestEventListenerBase : StreamingReporterBase {
|
||||
TestEventListenerBase( ReporterConfig const& _config )
|
||||
: StreamingReporterBase( _config )
|
||||
{}
|
||||
|
||||
|
||||
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
|
||||
virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
|
||||
virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
||||
|
@@ -34,7 +34,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
virtual void noMatchingTestCases( std::string const& spec ) {
|
||||
stream << "No test cases matched '" << spec << "'" << std::endl;
|
||||
stream << "No test cases matched '" << spec << '\'' << std::endl;
|
||||
}
|
||||
|
||||
virtual void assertionStarting( AssertionInfo const& ) {
|
||||
@@ -61,7 +61,7 @@ namespace Catch {
|
||||
|
||||
virtual void testRunEnded( TestRunStats const& _testRunStats ) {
|
||||
printTotals( _testRunStats.totals );
|
||||
stream << "\n" << std::endl;
|
||||
stream << '\n' << std::endl;
|
||||
StreamingReporterBase::testRunEnded( _testRunStats );
|
||||
}
|
||||
|
||||
@@ -161,26 +161,26 @@ namespace Catch {
|
||||
|
||||
void printSourceInfo() const {
|
||||
Colour colourGuard( Colour::FileName );
|
||||
stream << result.getSourceInfo() << ":";
|
||||
stream << result.getSourceInfo() << ':';
|
||||
}
|
||||
|
||||
void printResultType( Colour::Code colour, std::string passOrFail ) const {
|
||||
if( !passOrFail.empty() ) {
|
||||
{
|
||||
Colour colourGuard( colour );
|
||||
stream << " " << passOrFail;
|
||||
stream << ' ' << passOrFail;
|
||||
}
|
||||
stream << ":";
|
||||
stream << ':';
|
||||
}
|
||||
}
|
||||
|
||||
void printIssue( std::string issue ) const {
|
||||
stream << " " << issue;
|
||||
stream << ' ' << issue;
|
||||
}
|
||||
|
||||
void printExpressionWas() {
|
||||
if( result.hasExpression() ) {
|
||||
stream << ";";
|
||||
stream << ';';
|
||||
{
|
||||
Colour colour( dimColour() );
|
||||
stream << " expression was:";
|
||||
@@ -191,7 +191,7 @@ namespace Catch {
|
||||
|
||||
void printOriginalExpression() const {
|
||||
if( result.hasExpression() ) {
|
||||
stream << " " << result.getExpression();
|
||||
stream << ' ' << result.getExpression();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ namespace Catch {
|
||||
|
||||
void printMessage() {
|
||||
if ( itMessage != messages.end() ) {
|
||||
stream << " '" << itMessage->message << "'";
|
||||
stream << " '" << itMessage->message << '\'';
|
||||
++itMessage;
|
||||
}
|
||||
}
|
||||
@@ -222,13 +222,13 @@ namespace Catch {
|
||||
|
||||
{
|
||||
Colour colourGuard( colour );
|
||||
stream << " with " << pluralise( N, "message" ) << ":";
|
||||
stream << " with " << pluralise( N, "message" ) << ':';
|
||||
}
|
||||
|
||||
for(; itMessage != itEnd; ) {
|
||||
// If this assertion is a warning ignore any INFO messages
|
||||
if( printInfoMessages || itMessage->type != ResultWas::Info ) {
|
||||
stream << " '" << itMessage->message << "'";
|
||||
stream << " '" << itMessage->message << '\'';
|
||||
if ( ++itMessage != itEnd ) {
|
||||
Colour colourGuard( dimColour() );
|
||||
stream << " and";
|
||||
@@ -254,7 +254,7 @@ namespace Catch {
|
||||
// - green: Passed [both/all] N tests cases with M assertions.
|
||||
|
||||
std::string bothOrAll( std::size_t count ) const {
|
||||
return count == 1 ? "" : count == 2 ? "both " : "all " ;
|
||||
return count == 1 ? std::string() : count == 2 ? "both " : "all " ;
|
||||
}
|
||||
|
||||
void printTotals( const Totals& totals ) const {
|
||||
@@ -265,12 +265,12 @@ namespace Catch {
|
||||
Colour colour( Colour::ResultError );
|
||||
const std::string qualify_assertions_failed =
|
||||
totals.assertions.failed == totals.assertions.total() ?
|
||||
bothOrAll( totals.assertions.failed ) : "";
|
||||
bothOrAll( totals.assertions.failed ) : std::string();
|
||||
stream <<
|
||||
"Failed " << bothOrAll( totals.testCases.failed )
|
||||
<< pluralise( totals.testCases.failed, "test case" ) << ", "
|
||||
"failed " << qualify_assertions_failed <<
|
||||
pluralise( totals.assertions.failed, "assertion" ) << ".";
|
||||
pluralise( totals.assertions.failed, "assertion" ) << '.';
|
||||
}
|
||||
else if( totals.assertions.total() == 0 ) {
|
||||
stream <<
|
||||
@@ -282,14 +282,14 @@ namespace Catch {
|
||||
Colour colour( Colour::ResultError );
|
||||
stream <<
|
||||
"Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
|
||||
"failed " << pluralise( totals.assertions.failed, "assertion" ) << ".";
|
||||
"failed " << pluralise( totals.assertions.failed, "assertion" ) << '.';
|
||||
}
|
||||
else {
|
||||
Colour colour( Colour::ResultSuccess );
|
||||
stream <<
|
||||
"Passed " << bothOrAll( totals.testCases.passed )
|
||||
<< pluralise( totals.testCases.passed, "test case" ) <<
|
||||
" with " << pluralise( totals.assertions.passed, "assertion" ) << ".";
|
||||
" with " << pluralise( totals.assertions.passed, "assertion" ) << '.';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -27,7 +27,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
|
||||
stream << "No test cases matched '" << spec << "'" << std::endl;
|
||||
stream << "No test cases matched '" << spec << '\'' << std::endl;
|
||||
}
|
||||
|
||||
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
|
||||
@@ -69,12 +69,12 @@ namespace Catch {
|
||||
}
|
||||
if( m_headerPrinted ) {
|
||||
if( m_config->showDurations() == ShowDurations::Always )
|
||||
stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
|
||||
stream << "Completed in " << _sectionStats.durationInSeconds << 's' << std::endl;
|
||||
m_headerPrinted = false;
|
||||
}
|
||||
else {
|
||||
if( m_config->showDurations() == ShowDurations::Always )
|
||||
stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
|
||||
stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << 's' << std::endl;
|
||||
}
|
||||
StreamingReporterBase::sectionEnded( _sectionStats );
|
||||
}
|
||||
@@ -88,7 +88,7 @@ namespace Catch {
|
||||
printSummaryDivider();
|
||||
stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
|
||||
printTotals( _testGroupStats.totals );
|
||||
stream << "\n" << std::endl;
|
||||
stream << '\n' << std::endl;
|
||||
}
|
||||
StreamingReporterBase::testGroupEnded( _testGroupStats );
|
||||
}
|
||||
@@ -180,13 +180,13 @@ namespace Catch {
|
||||
printSourceInfo();
|
||||
if( stats.totals.assertions.total() > 0 ) {
|
||||
if( result.isOk() )
|
||||
stream << "\n";
|
||||
stream << '\n';
|
||||
printResultType();
|
||||
printOriginalExpression();
|
||||
printReconstructedExpression();
|
||||
}
|
||||
else {
|
||||
stream << "\n";
|
||||
stream << '\n';
|
||||
}
|
||||
printMessage();
|
||||
}
|
||||
@@ -203,25 +203,25 @@ namespace Catch {
|
||||
Colour colourGuard( Colour::OriginalExpression );
|
||||
stream << " ";
|
||||
stream << result.getExpressionInMacro();
|
||||
stream << "\n";
|
||||
stream << '\n';
|
||||
}
|
||||
}
|
||||
void printReconstructedExpression() const {
|
||||
if( result.hasExpandedExpression() ) {
|
||||
stream << "with expansion:\n";
|
||||
Colour colourGuard( Colour::ReconstructedExpression );
|
||||
stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n";
|
||||
stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n';
|
||||
}
|
||||
}
|
||||
void printMessage() const {
|
||||
if( !messageLabel.empty() )
|
||||
stream << messageLabel << ":" << "\n";
|
||||
stream << messageLabel << ':' << '\n';
|
||||
for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
|
||||
it != itEnd;
|
||||
++it ) {
|
||||
// If this assertion is a warning ignore any INFO messages
|
||||
if( printInfoMessages || it->type != ResultWas::Info )
|
||||
stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n";
|
||||
stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n';
|
||||
}
|
||||
}
|
||||
void printSourceInfo() const {
|
||||
@@ -253,7 +253,7 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
void lazyPrintRunInfo() {
|
||||
stream << "\n" << getLineOfChars<'~'>() << "\n";
|
||||
stream << '\n' << getLineOfChars<'~'>() << '\n';
|
||||
Colour colour( Colour::SecondaryText );
|
||||
stream << currentTestRunInfo->name
|
||||
<< " is a Catch v" << libraryVersion << " host application.\n"
|
||||
@@ -287,19 +287,19 @@ namespace Catch {
|
||||
SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
|
||||
|
||||
if( !lineInfo.empty() ){
|
||||
stream << getLineOfChars<'-'>() << "\n";
|
||||
stream << getLineOfChars<'-'>() << '\n';
|
||||
Colour colourGuard( Colour::FileName );
|
||||
stream << lineInfo << "\n";
|
||||
stream << lineInfo << '\n';
|
||||
}
|
||||
stream << getLineOfChars<'.'>() << "\n" << std::endl;
|
||||
stream << getLineOfChars<'.'>() << '\n' << std::endl;
|
||||
}
|
||||
|
||||
void printClosedHeader( std::string const& _name ) {
|
||||
printOpenHeader( _name );
|
||||
stream << getLineOfChars<'.'>() << "\n";
|
||||
stream << getLineOfChars<'.'>() << '\n';
|
||||
}
|
||||
void printOpenHeader( std::string const& _name ) {
|
||||
stream << getLineOfChars<'-'>() << "\n";
|
||||
stream << getLineOfChars<'-'>() << '\n';
|
||||
{
|
||||
Colour colourGuard( Colour::Headers );
|
||||
printHeaderString( _name );
|
||||
@@ -316,7 +316,7 @@ namespace Catch {
|
||||
i = 0;
|
||||
stream << Text( _string, TextAttributes()
|
||||
.setIndent( indent+i)
|
||||
.setInitialIndent( indent ) ) << "\n";
|
||||
.setInitialIndent( indent ) ) << '\n';
|
||||
}
|
||||
|
||||
struct SummaryColumn {
|
||||
@@ -331,9 +331,9 @@ namespace Catch {
|
||||
std::string row = oss.str();
|
||||
for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
|
||||
while( it->size() < row.size() )
|
||||
*it = " " + *it;
|
||||
*it = ' ' + *it;
|
||||
while( it->size() > row.size() )
|
||||
row = " " + row;
|
||||
row = ' ' + row;
|
||||
}
|
||||
rows.push_back( row );
|
||||
return *this;
|
||||
@@ -349,12 +349,12 @@ namespace Catch {
|
||||
if( totals.testCases.total() == 0 ) {
|
||||
stream << Colour( Colour::Warning ) << "No tests ran\n";
|
||||
}
|
||||
else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) {
|
||||
else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
|
||||
stream << Colour( Colour::ResultSuccess ) << "All tests passed";
|
||||
stream << " ("
|
||||
<< pluralise( totals.assertions.passed, "assertion" ) << " in "
|
||||
<< pluralise( totals.testCases.passed, "test case" ) << ")"
|
||||
<< "\n";
|
||||
<< pluralise( totals.testCases.passed, "test case" ) << ')'
|
||||
<< '\n';
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -389,10 +389,10 @@ namespace Catch {
|
||||
else if( value != "0" ) {
|
||||
stream << Colour( Colour::LightGrey ) << " | ";
|
||||
stream << Colour( it->colour )
|
||||
<< value << " " << it->label;
|
||||
<< value << ' ' << it->label;
|
||||
}
|
||||
}
|
||||
stream << "\n";
|
||||
stream << '\n';
|
||||
}
|
||||
|
||||
static std::size_t makeRatio( std::size_t number, std::size_t total ) {
|
||||
@@ -428,10 +428,10 @@ namespace Catch {
|
||||
else {
|
||||
stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
|
||||
}
|
||||
stream << "\n";
|
||||
stream << '\n';
|
||||
}
|
||||
void printSummaryDivider() {
|
||||
stream << getLineOfChars<'-'>() << "\n";
|
||||
stream << getLineOfChars<'-'>() << '\n';
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -18,6 +18,35 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace {
|
||||
std::string getCurrentTimestamp() {
|
||||
// Beware, this is not reentrant because of backward compatibility issues
|
||||
// Also, UTC only, again because of backward compatibility (%z is C++11)
|
||||
time_t rawtime;
|
||||
std::time(&rawtime);
|
||||
const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z");
|
||||
|
||||
#ifdef _MSC_VER
|
||||
std::tm timeInfo = {};
|
||||
gmtime_s(&timeInfo, &rawtime);
|
||||
#else
|
||||
std::tm* timeInfo;
|
||||
timeInfo = std::gmtime(&rawtime);
|
||||
#endif
|
||||
|
||||
char timeStamp[timeStampSize];
|
||||
const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
|
||||
|
||||
#ifdef _MSC_VER
|
||||
std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
|
||||
#else
|
||||
std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
|
||||
#endif
|
||||
return std::string(timeStamp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class JunitReporter : public CumulativeReporterBase {
|
||||
public:
|
||||
JunitReporter( ReporterConfig const& _config )
|
||||
@@ -82,7 +111,7 @@ namespace Catch {
|
||||
xml.writeAttribute( "time", "" );
|
||||
else
|
||||
xml.writeAttribute( "time", suiteTime );
|
||||
xml.writeAttribute( "timestamp", "tbd" ); // !TBD
|
||||
xml.writeAttribute( "timestamp", getCurrentTimestamp() );
|
||||
|
||||
// Write test cases
|
||||
for( TestGroupNode::ChildNodes::const_iterator
|
||||
@@ -104,7 +133,7 @@ namespace Catch {
|
||||
SectionNode const& rootSection = *testCaseNode.children.front();
|
||||
|
||||
std::string className = stats.testInfo.className;
|
||||
|
||||
|
||||
if( className.empty() ) {
|
||||
if( rootSection.childSections.empty() )
|
||||
className = "global";
|
||||
@@ -117,8 +146,8 @@ namespace Catch {
|
||||
SectionNode const& sectionNode ) {
|
||||
std::string name = trim( sectionNode.stats.sectionInfo.name );
|
||||
if( !rootName.empty() )
|
||||
name = rootName + "/" + name;
|
||||
|
||||
name = rootName + '/' + name;
|
||||
|
||||
if( !sectionNode.assertions.empty() ||
|
||||
!sectionNode.stdOut.empty() ||
|
||||
!sectionNode.stdErr.empty() ) {
|
||||
@@ -187,7 +216,7 @@ namespace Catch {
|
||||
elementName = "internalError";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
XmlWriter::ScopedElement e = xml.scopedElement( elementName );
|
||||
|
||||
xml.writeAttribute( "message", result.getExpandedExpression() );
|
||||
@@ -195,14 +224,14 @@ namespace Catch {
|
||||
|
||||
std::ostringstream oss;
|
||||
if( !result.getMessage().empty() )
|
||||
oss << result.getMessage() << "\n";
|
||||
oss << result.getMessage() << '\n';
|
||||
for( std::vector<MessageInfo>::const_iterator
|
||||
it = stats.infoMessages.begin(),
|
||||
itEnd = stats.infoMessages.end();
|
||||
it != itEnd;
|
||||
++it )
|
||||
if( it->type == ResultWas::Info )
|
||||
oss << it->message << "\n";
|
||||
oss << it->message << '\n';
|
||||
|
||||
oss << "at " << result.getSourceInfo();
|
||||
xml.writeText( oss.str(), false );
|
||||
@@ -216,7 +245,7 @@ namespace Catch {
|
||||
unsigned int unexpectedExceptions;
|
||||
};
|
||||
|
||||
INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
|
||||
INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
|
@@ -15,18 +15,18 @@ namespace Catch {
|
||||
class MultipleReporters : public SharedImpl<IStreamingReporter> {
|
||||
typedef std::vector<Ptr<IStreamingReporter> > Reporters;
|
||||
Reporters m_reporters;
|
||||
|
||||
|
||||
public:
|
||||
void add( Ptr<IStreamingReporter> const& reporter ) {
|
||||
m_reporters.push_back( reporter );
|
||||
}
|
||||
|
||||
|
||||
public: // IStreamingReporter
|
||||
|
||||
|
||||
virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
|
||||
return m_reporters[0]->getPreferences();
|
||||
}
|
||||
|
||||
|
||||
virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
|
||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
||||
it != itEnd;
|
||||
@@ -34,7 +34,7 @@ public: // IStreamingReporter
|
||||
(*it)->noMatchingTestCases( spec );
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
|
||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
||||
it != itEnd;
|
||||
@@ -49,7 +49,7 @@ public: // IStreamingReporter
|
||||
(*it)->testGroupStarting( groupInfo );
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
|
||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
||||
it != itEnd;
|
||||
@@ -64,7 +64,7 @@ public: // IStreamingReporter
|
||||
(*it)->sectionStarting( sectionInfo );
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
|
||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
||||
it != itEnd;
|
||||
@@ -72,7 +72,7 @@ public: // IStreamingReporter
|
||||
(*it)->assertionStarting( assertionInfo );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// The return value indicates if the messages buffer should be cleared:
|
||||
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
|
||||
bool clearBuffer = false;
|
||||
@@ -111,20 +111,25 @@ public: // IStreamingReporter
|
||||
(*it)->testRunEnded( testRunStats );
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
|
||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
||||
it != itEnd;
|
||||
++it )
|
||||
(*it)->skipTest( testInfo );
|
||||
}
|
||||
|
||||
virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
|
||||
Ptr<IStreamingReporter> resultingReporter;
|
||||
|
||||
|
||||
if( existingReporter ) {
|
||||
MultipleReporters* multi = dynamic_cast<MultipleReporters*>( existingReporter.get() );
|
||||
MultipleReporters* multi = existingReporter->tryAsMulti();
|
||||
if( !multi ) {
|
||||
multi = new MultipleReporters;
|
||||
resultingReporter = Ptr<IStreamingReporter>( multi );
|
||||
@@ -137,11 +142,11 @@ Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingRepo
|
||||
}
|
||||
else
|
||||
resultingReporter = additionalReporter;
|
||||
|
||||
|
||||
return resultingReporter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
|
||||
|
@@ -24,7 +24,7 @@
|
||||
#endif
|
||||
|
||||
namespace Catch {
|
||||
|
||||
|
||||
struct TeamCityReporter : StreamingReporterBase {
|
||||
TeamCityReporter( ReporterConfig const& _config )
|
||||
: StreamingReporterBase( _config ),
|
||||
@@ -32,7 +32,7 @@ namespace Catch {
|
||||
{
|
||||
m_reporterPrefs.shouldRedirectStdOut = true;
|
||||
}
|
||||
|
||||
|
||||
static std::string escape( std::string const& str ) {
|
||||
std::string escaped = str;
|
||||
replaceInPlace( escaped, "|", "||" );
|
||||
@@ -58,9 +58,9 @@ namespace Catch {
|
||||
stream << " message='test skipped because it didn|'t match the test spec'";
|
||||
stream << "]\n";
|
||||
}
|
||||
|
||||
|
||||
virtual void noMatchingTestCases( std::string const& /* spec */ ) CATCH_OVERRIDE {}
|
||||
|
||||
|
||||
virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
|
||||
StreamingReporterBase::testGroupStarting( groupInfo );
|
||||
stream << "##teamcity[testSuiteStarted name='"
|
||||
@@ -72,21 +72,21 @@ namespace Catch {
|
||||
<< escape( testGroupStats.groupInfo.name ) << "']\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
|
||||
}
|
||||
|
||||
|
||||
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
|
||||
AssertionResult const& result = assertionStats.assertionResult;
|
||||
if( !result.isOk() ) {
|
||||
|
||||
|
||||
std::ostringstream msg;
|
||||
if( !m_headerPrintedForThisSection )
|
||||
printSectionHeader( msg );
|
||||
m_headerPrintedForThisSection = true;
|
||||
|
||||
|
||||
msg << result.getSourceInfo() << "\n";
|
||||
|
||||
|
||||
switch( result.getResultType() ) {
|
||||
case ResultWas::ExpressionFailed:
|
||||
msg << "expression failed";
|
||||
@@ -125,15 +125,15 @@ namespace Catch {
|
||||
it != itEnd;
|
||||
++it )
|
||||
msg << "\n \"" << it->message << "\"";
|
||||
|
||||
|
||||
|
||||
|
||||
if( result.hasExpression() ) {
|
||||
msg <<
|
||||
"\n " << result.getExpressionInMacro() << "\n"
|
||||
"with expansion:\n" <<
|
||||
" " << result.getExpandedExpression() << "\n";
|
||||
}
|
||||
|
||||
|
||||
stream << "##teamcity[testFailed"
|
||||
<< " name='" << escape( currentTestCaseInfo->name )<< "'"
|
||||
<< " message='" << escape( msg.str() ) << "'"
|
||||
@@ -141,7 +141,7 @@ namespace Catch {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
|
||||
m_headerPrintedForThisSection = false;
|
||||
StreamingReporterBase::sectionStarting( sectionInfo );
|
||||
@@ -152,7 +152,7 @@ namespace Catch {
|
||||
stream << "##teamcity[testStarted name='"
|
||||
<< escape( testInfo.name ) << "']\n";
|
||||
}
|
||||
|
||||
|
||||
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
|
||||
StreamingReporterBase::testCaseEnded( testCaseStats );
|
||||
if( !testCaseStats.stdOut.empty() )
|
||||
@@ -181,9 +181,9 @@ namespace Catch {
|
||||
printHeaderString( os, it->name );
|
||||
os << getLineOfChars<'-'>() << "\n";
|
||||
}
|
||||
|
||||
|
||||
SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
|
||||
|
||||
|
||||
if( !lineInfo.empty() )
|
||||
os << lineInfo << "\n";
|
||||
os << getLineOfChars<'.'>() << "\n\n";
|
||||
@@ -203,15 +203,15 @@ namespace Catch {
|
||||
}
|
||||
private:
|
||||
bool m_headerPrintedForThisSection;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#ifdef CATCH_IMPL
|
||||
TeamCityReporter::~TeamCityReporter() {}
|
||||
#endif
|
||||
|
||||
|
||||
INTERNAL_CATCH_REGISTER_REPORTER( "teamcity", TeamCityReporter )
|
||||
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#ifdef __clang__
|
||||
|
@@ -20,13 +20,14 @@ namespace Catch {
|
||||
public:
|
||||
XmlReporter( ReporterConfig const& _config )
|
||||
: StreamingReporterBase( _config ),
|
||||
m_xml(_config.stream()),
|
||||
m_sectionDepth( 0 )
|
||||
{
|
||||
m_reporterPrefs.shouldRedirectStdOut = true;
|
||||
}
|
||||
|
||||
virtual ~XmlReporter() CATCH_OVERRIDE;
|
||||
|
||||
|
||||
static std::string getDescription() {
|
||||
return "Reports test results as an XML document";
|
||||
}
|
||||
@@ -39,7 +40,6 @@ namespace Catch {
|
||||
|
||||
virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
|
||||
StreamingReporterBase::testRunStarting( testInfo );
|
||||
m_xml.setStream( stream );
|
||||
m_xml.startElement( "Catch" );
|
||||
if( !m_config->name().empty() )
|
||||
m_xml.writeAttribute( "name", m_config->name() );
|
||||
@@ -53,7 +53,7 @@ namespace Catch {
|
||||
|
||||
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
|
||||
StreamingReporterBase::testCaseStarting(testInfo);
|
||||
m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
|
||||
m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name );
|
||||
|
||||
if ( m_config->showDurations() == ShowDurations::Always )
|
||||
m_testCaseTimer.start();
|
||||
@@ -72,7 +72,7 @@ namespace Catch {
|
||||
|
||||
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
|
||||
const AssertionResult& assertionResult = assertionStats.assertionResult;
|
||||
|
||||
|
||||
// Print any info messages in <Info> tags.
|
||||
if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
|
||||
for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
|
||||
@@ -96,7 +96,7 @@ namespace Catch {
|
||||
if( assertionResult.hasExpression() ) {
|
||||
m_xml.startElement( "Expression" )
|
||||
.writeAttribute( "success", assertionResult.succeeded() )
|
||||
.writeAttribute( "type", assertionResult.getTestMacroName() )
|
||||
.writeAttribute( "type", assertionResult.getTestMacroName() )
|
||||
.writeAttribute( "filename", assertionResult.getSourceInfo().file )
|
||||
.writeAttribute( "line", assertionResult.getSourceInfo().line );
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Catch {
|
||||
.writeText( assertionResult.getMessage() );
|
||||
break;
|
||||
case ResultWas::FatalErrorCondition:
|
||||
m_xml.scopedElement( "Fatal Error Condition" )
|
||||
m_xml.scopedElement( "FatalErrorCondition" )
|
||||
.writeAttribute( "filename", assertionResult.getSourceInfo().file )
|
||||
.writeAttribute( "line", assertionResult.getSourceInfo().line )
|
||||
.writeText( assertionResult.getMessage() );
|
||||
@@ -134,10 +134,10 @@ namespace Catch {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if( assertionResult.hasExpression() )
|
||||
m_xml.endElement();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -164,6 +164,11 @@ namespace Catch {
|
||||
if ( m_config->showDurations() == ShowDurations::Always )
|
||||
e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
|
||||
|
||||
if( !testCaseStats.stdOut.empty() )
|
||||
m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
|
||||
if( !testCaseStats.stdErr.empty() )
|
||||
m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
|
||||
|
||||
m_xml.endElement();
|
||||
}
|
||||
|
||||
@@ -176,7 +181,7 @@ namespace Catch {
|
||||
.writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
|
||||
m_xml.endElement();
|
||||
}
|
||||
|
||||
|
||||
virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
|
||||
StreamingReporterBase::testRunEnded( testRunStats );
|
||||
m_xml.scopedElement( "OverallResults" )
|
||||
|
9
projects/Benchmark/BenchMain.cpp
Normal file
9
projects/Benchmark/BenchMain.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Created by Martin on 16/01/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)
|
||||
*/
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
46
projects/Benchmark/StringificationBench.cpp
Normal file
46
projects/Benchmark/StringificationBench.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Created by Martin on 16/01/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)
|
||||
*/
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE("Successful tests -- REQUIRE", "[Success]") {
|
||||
const size_t sz = 1 * 1024 * 1024;
|
||||
|
||||
|
||||
std::vector<size_t> vec; vec.reserve(sz);
|
||||
for (size_t i = 0; i < sz; ++i){
|
||||
vec.push_back(i);
|
||||
REQUIRE(vec.back() == i);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE("Successful tests -- CHECK", "[Success]") {
|
||||
const size_t sz = 1 * 1024 * 1024;
|
||||
|
||||
|
||||
std::vector<size_t> vec; vec.reserve(sz);
|
||||
for (size_t i = 0; i < sz; ++i){
|
||||
vec.push_back(i);
|
||||
CHECK(vec.back() == i);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE("Unsuccessful tests -- CHECK", "[Failure]") {
|
||||
const size_t sz = 1024 * 1024;
|
||||
|
||||
|
||||
std::vector<size_t> vec; vec.reserve(sz);
|
||||
for (size_t i = 0; i < sz; ++i){
|
||||
vec.push_back(i);
|
||||
CHECK(vec.size() == i);
|
||||
}
|
||||
}
|
4
projects/Benchmark/readme.txt
Normal file
4
projects/Benchmark/readme.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
This is very much a work in progress.
|
||||
The past results are standardized to a developer's machine,
|
||||
the benchmarking script is basic and there are only 3 benchmarks,
|
||||
but this should get better in time. For now, at least there is something to go by.
|
@@ -0,0 +1,3 @@
|
||||
Successful tests -- CHECK: median: 3.38116 (s), stddev: 0.11567366292001534 (s)
|
||||
Successful tests -- REQUIRE: median: 3.479955 (s), stddev: 0.16295972890734556 (s)
|
||||
Unsuccessful tests -- CHECK: median: 1.966895 (s), stddev: 0.06323488524716572 (s)
|
@@ -0,0 +1,3 @@
|
||||
Successful tests -- CHECK: median: 1.30312 (s), stddev: 0.08759818557862176 (s)
|
||||
Successful tests -- REQUIRE: median: 1.341535 (s), stddev: 0.1479193390143576 (s)
|
||||
Unsuccessful tests -- CHECK: median: 1.967755 (s), stddev: 0.07921104121269959 (s)
|
@@ -0,0 +1,3 @@
|
||||
Successful tests -- CHECK: median: 1.2982 (s), stddev: 0.019540648829214084 (s)
|
||||
Successful tests -- REQUIRE: median: 1.30102 (s), stddev: 0.014758430547392974 (s)
|
||||
Unsuccessful tests -- CHECK: median: 15.520199999999999 (s), stddev: 0.09536359426485094 (s)
|
@@ -0,0 +1,3 @@
|
||||
Successful tests -- CHECK: median: 0.7689014999999999 (s), stddev: 0.02127512078801068 (s)
|
||||
Successful tests -- REQUIRE: median: 0.772845 (s), stddev: 0.03011638381365052 (s)
|
||||
Unsuccessful tests -- CHECK: median: 15.49 (s), stddev: 0.536088571143903 (s)
|
@@ -0,0 +1,3 @@
|
||||
Successful tests -- CHECK: median: 0.775769 (s), stddev: 0.014802129132136525 (s)
|
||||
Successful tests -- REQUIRE: median: 0.785235 (s), stddev: 0.03532672836834896 (s)
|
||||
Unsuccessful tests -- CHECK: median: 15.156600000000001 (s), stddev: 0.2832375673450742 (s)
|
@@ -1,48 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(Catch)
|
||||
|
||||
# define some folders
|
||||
get_filename_component(CATCH_DIR "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
|
||||
get_filename_component(CATCH_DIR "${CATCH_DIR}" PATH)
|
||||
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
|
||||
if(USE_CPP11)
|
||||
## We can't turn this on by default, since it breaks on travis
|
||||
message(STATUS "Enabling C++11")
|
||||
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
# define the sources of the self test
|
||||
set(SOURCES
|
||||
${SELF_TEST_DIR}/ApproxTests.cpp
|
||||
${SELF_TEST_DIR}/BDDTests.cpp
|
||||
${SELF_TEST_DIR}/ClassTests.cpp
|
||||
${SELF_TEST_DIR}/ConditionTests.cpp
|
||||
${SELF_TEST_DIR}/ExceptionTests.cpp
|
||||
${SELF_TEST_DIR}/GeneratorTests.cpp
|
||||
${SELF_TEST_DIR}/MessageTests.cpp
|
||||
${SELF_TEST_DIR}/MiscTests.cpp
|
||||
${SELF_TEST_DIR}/SectionTrackerTests.cpp
|
||||
${SELF_TEST_DIR}/TestMain.cpp
|
||||
${SELF_TEST_DIR}/TrickyTests.cpp
|
||||
${SELF_TEST_DIR}/VariadicMacrosTests.cpp
|
||||
${SELF_TEST_DIR}/EnumToString.cpp
|
||||
${SELF_TEST_DIR}/ToStringPair.cpp
|
||||
${SELF_TEST_DIR}/ToStringVector.cpp
|
||||
${SELF_TEST_DIR}/ToStringWhich.cpp
|
||||
${SELF_TEST_DIR}/ToStringTuple.cpp
|
||||
)
|
||||
|
||||
# configure the executable
|
||||
include_directories(${CATCH_DIR}/include)
|
||||
add_executable(SelfTest ${SOURCES})
|
||||
|
||||
# configure unit tests via CTest
|
||||
enable_testing()
|
||||
add_test(NAME RunTests COMMAND SelfTest)
|
||||
|
||||
add_test(NAME ListTests COMMAND SelfTest --list-tests)
|
||||
set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases")
|
||||
|
||||
add_test(NAME ListTags COMMAND SelfTest --list-tags)
|
||||
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
|
@@ -16,7 +16,7 @@ TEST_CASE
|
||||
)
|
||||
{
|
||||
double d = 1.23;
|
||||
|
||||
|
||||
REQUIRE( d == Approx( 1.23 ) );
|
||||
REQUIRE( d != Approx( 1.22 ) );
|
||||
REQUIRE( d != Approx( 1.24 ) );
|
||||
@@ -34,11 +34,41 @@ TEST_CASE
|
||||
)
|
||||
{
|
||||
double d = 1.23;
|
||||
|
||||
|
||||
REQUIRE( d != Approx( 1.231 ) );
|
||||
REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
"Less-than inequalities with different epsilons",
|
||||
"[Approx]"
|
||||
)
|
||||
{
|
||||
double d = 1.23;
|
||||
|
||||
REQUIRE( d <= Approx( 1.24 ) );
|
||||
REQUIRE( d <= Approx( 1.23 ) );
|
||||
REQUIRE_FALSE( d <= Approx( 1.22 ) );
|
||||
REQUIRE( d <= Approx( 1.22 ).epsilon(0.1) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
"Greater-than inequalities with different epsilons",
|
||||
"[Approx]"
|
||||
)
|
||||
{
|
||||
double d = 1.23;
|
||||
|
||||
REQUIRE( d >= Approx( 1.22 ) );
|
||||
REQUIRE( d >= Approx( 1.23 ) );
|
||||
REQUIRE_FALSE( d >= Approx( 1.24 ) );
|
||||
REQUIRE( d >= Approx( 1.24 ).epsilon(0.1) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
@@ -71,7 +101,7 @@ TEST_CASE
|
||||
const double dZero = 0;
|
||||
const double dSmall = 0.00001;
|
||||
const double dMedium = 1.234;
|
||||
|
||||
|
||||
REQUIRE( 1.0f == Approx( 1 ) );
|
||||
REQUIRE( 0 == Approx( dZero) );
|
||||
REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) );
|
||||
@@ -87,14 +117,14 @@ TEST_CASE
|
||||
)
|
||||
{
|
||||
double d = 1.23;
|
||||
|
||||
|
||||
Approx approx = Approx::custom().epsilon( 0.005 );
|
||||
|
||||
|
||||
REQUIRE( d == approx( 1.23 ) );
|
||||
REQUIRE( d == approx( 1.22 ) );
|
||||
REQUIRE( d == approx( 1.24 ) );
|
||||
REQUIRE( d != approx( 1.25 ) );
|
||||
|
||||
|
||||
REQUIRE( approx( d ) == 1.23 );
|
||||
REQUIRE( approx( d ) == 1.22 );
|
||||
REQUIRE( approx( d ) == 1.24 );
|
||||
@@ -110,3 +140,48 @@ TEST_CASE( "Approximate PI", "[Approx][PI]" )
|
||||
REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) );
|
||||
REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
|
||||
class StrongDoubleTypedef
|
||||
{
|
||||
double d_ = 0.0;
|
||||
|
||||
public:
|
||||
explicit StrongDoubleTypedef(double d) : d_(d) {}
|
||||
explicit operator double() const { return d_; }
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<( std::ostream& os, StrongDoubleTypedef td ) {
|
||||
return os << "StrongDoubleTypedef(" << static_cast<double>(td) << ")";
|
||||
}
|
||||
|
||||
TEST_CASE
|
||||
(
|
||||
"Comparison with explicitly convertible types",
|
||||
"[Approx]"
|
||||
)
|
||||
{
|
||||
StrongDoubleTypedef td(10.0);
|
||||
|
||||
REQUIRE(td == Approx(10.0));
|
||||
REQUIRE(Approx(10.0) == td);
|
||||
|
||||
REQUIRE(td != Approx(11.0));
|
||||
REQUIRE(Approx(11.0) != td);
|
||||
|
||||
REQUIRE(td <= Approx(10.0));
|
||||
REQUIRE(td <= Approx(11.0));
|
||||
REQUIRE(Approx(10.0) <= td);
|
||||
REQUIRE(Approx(9.0) <= td);
|
||||
|
||||
REQUIRE(td >= Approx(9.0));
|
||||
REQUIRE(td >= Approx(10.0));
|
||||
REQUIRE(Approx(10.0) >= td);
|
||||
REQUIRE(Approx(11.0) >= td);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -30,13 +30,13 @@ SCENARIO( "Vector resizing affects size and capacity", "[vector][bdd][size][capa
|
||||
GIVEN( "an empty vector" ) {
|
||||
std::vector<int> v;
|
||||
REQUIRE( v.size() == 0 );
|
||||
|
||||
|
||||
WHEN( "it is made larger" ) {
|
||||
v.resize( 10 );
|
||||
THEN( "the size and capacity go up" ) {
|
||||
REQUIRE( v.size() == 10 );
|
||||
REQUIRE( v.capacity() >= 10 );
|
||||
|
||||
|
||||
AND_WHEN( "it is made smaller again" ) {
|
||||
v.resize( 5 );
|
||||
THEN( "the size goes down but the capacity stays the same" ) {
|
||||
@@ -46,7 +46,7 @@ SCENARIO( "Vector resizing affects size and capacity", "[vector][bdd][size][capa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WHEN( "we reserve more space" ) {
|
||||
v.reserve( 10 );
|
||||
THEN( "The capacity is increased but the size remains the same" ) {
|
||||
@@ -76,22 +76,22 @@ struct Fixture
|
||||
: d_counter(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int counter()
|
||||
{
|
||||
return d_counter++;
|
||||
}
|
||||
|
||||
|
||||
int d_counter;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
SCENARIO_METHOD(Fixture,
|
||||
"BDD tests requiring Fixtures to provide commonly-accessed data or methods",
|
||||
"[bdd][fixtures]") {
|
||||
"BDD tests requiring Fixtures to provide commonly-accessed data or methods",
|
||||
"[bdd][fixtures]") {
|
||||
const int before(counter());
|
||||
GIVEN("No operations precede me") {
|
||||
GIVEN("No operations precede me") {
|
||||
REQUIRE(before == 0);
|
||||
WHEN("We get the count") {
|
||||
const int after(counter());
|
||||
|
@@ -1,8 +1,48 @@
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
CatchSelfTest is a <version> host application.
|
||||
<exe-name> is a <version> host application.
|
||||
Run with -? for options
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
'Not' checks that should fail
|
||||
-------------------------------------------------------------------------------
|
||||
ConditionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( false != false )
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( true != true )
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( !true )
|
||||
with expansion:
|
||||
false
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK_FALSE( true )
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( !trueValue )
|
||||
with expansion:
|
||||
false
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK_FALSE( trueValue )
|
||||
with expansion:
|
||||
!true
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( !(1 == 1) )
|
||||
with expansion:
|
||||
false
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK_FALSE( 1 == 1 )
|
||||
with expansion:
|
||||
!(1 == 1)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
A METHOD_AS_TEST_CASE based test run that fails
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -25,6 +65,97 @@ ClassTests.cpp:<line number>: FAILED:
|
||||
with expansion:
|
||||
1 == 2
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
A couple of nested sections followed by a failure
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
explicitly with message:
|
||||
to infinity and beyond
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
A failing expression with a non streamable type is still captured
|
||||
-------------------------------------------------------------------------------
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TrickyTests.cpp:<line number>: FAILED:
|
||||
CHECK( &o1 == &o2 )
|
||||
with expansion:
|
||||
0x<hex digits> == 0x<hex digits>
|
||||
|
||||
TrickyTests.cpp:<line number>: FAILED:
|
||||
CHECK( o1 == o2 )
|
||||
with expansion:
|
||||
{?} == {?}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
An unchecked exception reports the line of the last assertion
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
{Unknown expression after the reported line}
|
||||
due to unexpected exception with message:
|
||||
unexpected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Contains string matcher
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( testStringForMatching(), Contains( "not there" ) )
|
||||
with expansion:
|
||||
"this string contains 'abc' as a substring" contains: "not there"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Custom exceptions can be translated when testing for nothrow
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
REQUIRE_NOTHROW( throwCustom() )
|
||||
due to unexpected exception with message:
|
||||
custom exception - not std
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Custom exceptions can be translated when testing for throwing as something else
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
REQUIRE_THROWS_AS( throwCustom() )
|
||||
due to unexpected exception with message:
|
||||
custom exception - not std
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Custom std-exceptions can be custom translated
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
due to unexpected exception with message:
|
||||
custom std exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
EndsWith string matcher
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( testStringForMatching(), EndsWith( "this" ) )
|
||||
with expansion:
|
||||
"this string contains 'abc' as a substring" ends with: "this"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Equality checks that should fail
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -96,6 +227,100 @@ ConditionTests.cpp:<line number>: FAILED:
|
||||
with expansion:
|
||||
1.3 == Approx( 1.301 )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Equals string matcher
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( testStringForMatching(), Equals( "something else" ) )
|
||||
with expansion:
|
||||
"this string contains 'abc' as a substring" equals: "something else"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Expected exceptions that don't throw or unexpected exceptions fail the test
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
CHECK_THROWS_AS( thisThrows() )
|
||||
due to unexpected exception with message:
|
||||
expected exception
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
CHECK_THROWS_AS( thisDoesntThrow() )
|
||||
because no exception was thrown where one was expected:
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
CHECK_NOTHROW( thisThrows() )
|
||||
due to unexpected exception with message:
|
||||
expected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
FAIL aborts the test
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
explicitly with message:
|
||||
This is a failure
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
FAIL does not require an argument
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
INFO and WARN do not abort tests
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>:
|
||||
warning:
|
||||
this is a warning
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
INFO gets logged on failure
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( a == 1 )
|
||||
with expansion:
|
||||
2 == 1
|
||||
with messages:
|
||||
this message should be logged
|
||||
so should this
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
INFO gets logged on failure, even if captured before successful assertions
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
CHECK( a == 1 )
|
||||
with expansion:
|
||||
2 == 1
|
||||
with messages:
|
||||
this message may be logged later
|
||||
this message should be logged
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
CHECK( a == 0 )
|
||||
with expansion:
|
||||
2 == 0
|
||||
with message:
|
||||
and this, but later
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Inequality checks that should fail
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -127,6 +352,60 @@ ConditionTests.cpp:<line number>: FAILED:
|
||||
with expansion:
|
||||
5 != 5
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers can be composed with both && and || - failing
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) )
|
||||
with expansion:
|
||||
"this string contains 'abc' as a substring" ( ( contains: "string" or
|
||||
contains: "different" ) and contains: "random" )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers can be negated (Not) with the ! operator - failing
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( testStringForMatching(), !Contains( "substring" ) )
|
||||
with expansion:
|
||||
"this string contains 'abc' as a substring" not contains: "substring"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Mismatching exception messages failing the test
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
REQUIRE_THROWS_WITH( thisThrows(), "should fail" )
|
||||
with expansion:
|
||||
expected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Nice descriptive name
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
warning:
|
||||
This one ran
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Non-std exceptions can be translated
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
due to unexpected exception with message:
|
||||
custom exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Ordering comparison checks that should fail
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -229,64 +508,99 @@ with expansion:
|
||||
"hello" <= "a"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
'Not' checks that should fail
|
||||
Output from all sections is reported
|
||||
one
|
||||
-------------------------------------------------------------------------------
|
||||
ConditionTests.cpp:<line number>
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( false != false )
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( true != true )
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( !true )
|
||||
with expansion:
|
||||
false
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK_FALSE( true )
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( !trueValue )
|
||||
with expansion:
|
||||
false
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK_FALSE( trueValue )
|
||||
with expansion:
|
||||
!true
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( !(1 == 1) )
|
||||
with expansion:
|
||||
false
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK_FALSE( 1 == 1 )
|
||||
with expansion:
|
||||
!(1 == 1)
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
explicitly with message:
|
||||
Message from section one
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Expected exceptions that don't throw or unexpected exceptions fail the test
|
||||
Output from all sections is reported
|
||||
two
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
explicitly with message:
|
||||
Message from section two
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Pointers can be converted to strings
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>:
|
||||
warning:
|
||||
actual address of p: 0x<hex digits>
|
||||
|
||||
MessageTests.cpp:<line number>:
|
||||
warning:
|
||||
toString(p): 0x<hex digits>
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
SCOPED_INFO is reset for each loop
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( i < 10 )
|
||||
with expansion:
|
||||
10 < 10
|
||||
with messages:
|
||||
current counter 10
|
||||
i := 10
|
||||
|
||||
A string sent directly to stdout
|
||||
A string sent directly to stderr
|
||||
Message from section one
|
||||
Message from section two
|
||||
-------------------------------------------------------------------------------
|
||||
StartsWith string matcher
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( testStringForMatching(), StartsWith( "string" ) )
|
||||
with expansion:
|
||||
"this string contains 'abc' as a substring" starts with: "string"
|
||||
|
||||
hello
|
||||
hello
|
||||
-------------------------------------------------------------------------------
|
||||
Tabs and newlines show in output
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECK( s1 == s2 )
|
||||
with expansion:
|
||||
"if ($b == 10) {
|
||||
$a = 20;
|
||||
}"
|
||||
==
|
||||
"if ($b == 10) {
|
||||
$a = 20;
|
||||
}
|
||||
"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Unexpected exceptions can be translated
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
CHECK_THROWS_AS( thisThrows() )
|
||||
due to unexpected exception with message:
|
||||
expected exception
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
CHECK_THROWS_AS( thisDoesntThrow() )
|
||||
because no exception was thrown where one was expected:
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
CHECK_NOTHROW( thisThrows() )
|
||||
due to unexpected exception with message:
|
||||
expected exception
|
||||
3.14
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
When unchecked exceptions are thrown directly they are always failures
|
||||
@@ -299,29 +613,7 @@ due to unexpected exception with message:
|
||||
unexpected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
An unchecked exception reports the line of the last assertion
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
{Unknown expression after the reported line}
|
||||
due to unexpected exception with message:
|
||||
unexpected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
When unchecked exceptions are thrown from sections they are always failures
|
||||
section name
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
due to unexpected exception with message:
|
||||
unexpected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
When unchecked exceptions are thrown from functions they are always failures
|
||||
When unchecked exceptions are thrown during a CHECK the test should continue
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
@@ -344,8 +636,7 @@ due to unexpected exception with message:
|
||||
expected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
When unchecked exceptions are thrown during a CHECK the test should abort and
|
||||
fail
|
||||
When unchecked exceptions are thrown from functions they are always failures
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
@@ -356,158 +647,69 @@ due to unexpected exception with message:
|
||||
expected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Unexpected custom exceptions can be translated
|
||||
When unchecked exceptions are thrown from sections they are always failures
|
||||
section name
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
due to unexpected exception with message:
|
||||
custom exception
|
||||
unexpected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Custom exceptions can be translated when testing for nothrow
|
||||
Where the LHS is not a simple value
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
REQUIRE_NOTHROW( throwCustom() )
|
||||
due to unexpected exception with message:
|
||||
custom exception - not std
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Custom exceptions can be translated when testing for throwing as something else
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
REQUIRE_THROWS_AS( throwCustom() )
|
||||
due to unexpected exception with message:
|
||||
custom exception - not std
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Unexpected exceptions can be translated
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
due to unexpected exception with message:
|
||||
3.14
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Mismatching exception messages failing the test
|
||||
-------------------------------------------------------------------------------
|
||||
ExceptionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ExceptionTests.cpp:<line number>: FAILED:
|
||||
REQUIRE_THROWS_WITH( thisThrows(), "should fail" )
|
||||
with expansion:
|
||||
expected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
INFO and WARN do not abort tests
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>:
|
||||
TrickyTests.cpp:<line number>:
|
||||
warning:
|
||||
this is a warning
|
||||
Uncomment the code in this test to check that it gives a sensible compiler
|
||||
error
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
INFO gets logged on failure
|
||||
Where there is more to the expression after the RHS
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( a == 1 )
|
||||
TrickyTests.cpp:<line number>:
|
||||
warning:
|
||||
Uncomment the code in this test to check that it gives a sensible compiler
|
||||
error
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
checkedElse, failing
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECKED_ELSE( flag )
|
||||
with expansion:
|
||||
2 == 1
|
||||
with messages:
|
||||
this message should be logged
|
||||
so should this
|
||||
false
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
INFO gets logged on failure, even if captured before successful assertions
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
CHECK( a == 1 )
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( testCheckedElse( false ) )
|
||||
with expansion:
|
||||
2 == 1
|
||||
with messages:
|
||||
this message may be logged later
|
||||
this message should be logged
|
||||
false
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
CHECK( a == 0 )
|
||||
-------------------------------------------------------------------------------
|
||||
checkedIf, failing
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECKED_IF( flag )
|
||||
with expansion:
|
||||
2 == 0
|
||||
with message:
|
||||
and this, but later
|
||||
false
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
FAIL aborts the test
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
explicitly with message:
|
||||
This is a failure
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
FAIL does not require an argument
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Output from all sections is reported
|
||||
one
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
explicitly with message:
|
||||
Message from section one
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Output from all sections is reported
|
||||
two
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
explicitly with message:
|
||||
Message from section two
|
||||
|
||||
Message from section one
|
||||
Message from section two
|
||||
-------------------------------------------------------------------------------
|
||||
SCOPED_INFO is reset for each loop
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( i < 10 )
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( testCheckedIf( false ) )
|
||||
with expansion:
|
||||
10 < 10
|
||||
with messages:
|
||||
current counter 10
|
||||
i := 10
|
||||
false
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
just failure
|
||||
@@ -519,45 +721,6 @@ MessageTests.cpp:<line number>: FAILED:
|
||||
explicitly with message:
|
||||
Previous info should not be seen
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
sends information to INFO
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( false )
|
||||
with messages:
|
||||
hi
|
||||
i := 7
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Pointers can be converted to strings
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MessageTests.cpp:<line number>:
|
||||
warning:
|
||||
actual address of p: 0x<hex digits>
|
||||
|
||||
MessageTests.cpp:<line number>:
|
||||
warning:
|
||||
toString(p): 0x<hex digits>
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
more nested SECTION tests
|
||||
s1
|
||||
s2
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( a == b )
|
||||
with expansion:
|
||||
1 == 2
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
looped SECTION tests
|
||||
s1
|
||||
@@ -618,39 +781,18 @@ with expansion:
|
||||
with message:
|
||||
Testing if fib[7] (21) is even
|
||||
|
||||
A string sent directly to stdout
|
||||
A string sent directly to stderr
|
||||
-------------------------------------------------------------------------------
|
||||
checkedIf, failing
|
||||
more nested SECTION tests
|
||||
s1
|
||||
s2
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECKED_IF( flag )
|
||||
REQUIRE( a == b )
|
||||
with expansion:
|
||||
false
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( testCheckedIf( false ) )
|
||||
with expansion:
|
||||
false
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
checkedElse, failing
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECKED_ELSE( flag )
|
||||
with expansion:
|
||||
false
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( testCheckedElse( false ) )
|
||||
with expansion:
|
||||
false
|
||||
1 == 2
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
send a single char to INFO
|
||||
@@ -664,126 +806,16 @@ with message:
|
||||
3
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Contains string matcher
|
||||
sends information to INFO
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( testStringForMatching() Contains( "not there" ) )
|
||||
with expansion:
|
||||
"this string contains 'abc' as a substring" contains: "not there"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
StartsWith string matcher
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( testStringForMatching() StartsWith( "string" ) )
|
||||
with expansion:
|
||||
"this string contains 'abc' as a substring" starts with: "string"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
EndsWith string matcher
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( testStringForMatching() EndsWith( "this" ) )
|
||||
with expansion:
|
||||
"this string contains 'abc' as a substring" ends with: "this"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Equals string matcher
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( testStringForMatching() Equals( "something else" ) )
|
||||
with expansion:
|
||||
"this string contains 'abc' as a substring" equals: "something else"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Nice descriptive name
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
warning:
|
||||
This one ran
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
A couple of nested sections followed by a failure
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
explicitly with message:
|
||||
to infinity and beyond
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Tabs and newlines show in output
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>: FAILED:
|
||||
CHECK( s1 == s2 )
|
||||
with expansion:
|
||||
"if ($b == 10) {
|
||||
$a= 20;
|
||||
}"
|
||||
==
|
||||
"if ($b == 10) {
|
||||
$a = 20;
|
||||
}
|
||||
"
|
||||
|
||||
hello
|
||||
hello
|
||||
-------------------------------------------------------------------------------
|
||||
Where there is more to the expression after the RHS
|
||||
-------------------------------------------------------------------------------
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TrickyTests.cpp:<line number>:
|
||||
warning:
|
||||
Uncomment the code in this test to check that it gives a sensible compiler
|
||||
error
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Where the LHS is not a simple value
|
||||
-------------------------------------------------------------------------------
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TrickyTests.cpp:<line number>:
|
||||
warning:
|
||||
Uncomment the code in this test to check that it gives a sensible compiler
|
||||
error
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
A failing expression with a non streamable type is still captured
|
||||
-------------------------------------------------------------------------------
|
||||
TrickyTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
TrickyTests.cpp:<line number>: FAILED:
|
||||
CHECK( &o1 == &o2 )
|
||||
with expansion:
|
||||
0x<hex digits> == 0x<hex digits>
|
||||
|
||||
TrickyTests.cpp:<line number>: FAILED:
|
||||
CHECK( o1 == o2 )
|
||||
with expansion:
|
||||
{?} == {?}
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( false )
|
||||
with messages:
|
||||
hi
|
||||
i := 7
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
string literals of different sizes can be compared
|
||||
@@ -797,6 +829,6 @@ with expansion:
|
||||
"first" == "second"
|
||||
|
||||
===============================================================================
|
||||
test cases: 159 | 119 passed | 39 failed | 1 failed as expected
|
||||
assertions: 788 | 695 passed | 80 failed | 13 failed as expected
|
||||
test cases: 157 | 113 passed | 42 failed | 2 failed as expected
|
||||
assertions: 913 | 817 passed | 78 failed | 18 failed as expected
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,491 +1,40 @@
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
CatchSelfTest is a <version> host application.
|
||||
<exe-name> is a <version> host application.
|
||||
Run with -? for options
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString(enum)
|
||||
# A test name that starts with a #
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.cpp:<line number>
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e0) == "0" )
|
||||
with expansion:
|
||||
"0" == "0"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e1) == "1" )
|
||||
with expansion:
|
||||
"1" == "1"
|
||||
with message:
|
||||
yay
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString(enum w/operator<<)
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e0) == "E2{0}" )
|
||||
with expansion:
|
||||
"E2{0}" == "E2{0}"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e1) == "E2{1}" )
|
||||
with expansion:
|
||||
"E2{1}" == "E2{1}"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString(enum class)
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e0) == "0" )
|
||||
with expansion:
|
||||
"0" == "0"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e1) == "1" )
|
||||
with expansion:
|
||||
"1" == "1"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
toString(enum class w/operator<<)
|
||||
-------------------------------------------------------------------------------
|
||||
EnumToString.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e0) == "E2/V0" )
|
||||
with expansion:
|
||||
"E2/V0" == "E2/V0"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e1) == "E2/V1" )
|
||||
with expansion:
|
||||
"E2/V1" == "E2/V1"
|
||||
|
||||
EnumToString.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( Catch::toString(e3) == "Unknown enum value 10" )
|
||||
with expansion:
|
||||
"Unknown enum value 10"
|
||||
==
|
||||
"Unknown enum value 10"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Some simple comparisons between doubles
|
||||
-------------------------------------------------------------------------------
|
||||
ApproxTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( d == Approx( 1.23 ) )
|
||||
with expansion:
|
||||
1.23 == Approx( 1.23 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( d != Approx( 1.22 ) )
|
||||
with expansion:
|
||||
1.23 != Approx( 1.22 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( d != Approx( 1.24 ) )
|
||||
with expansion:
|
||||
1.23 != Approx( 1.24 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Approx( d ) == 1.23 )
|
||||
with expansion:
|
||||
Approx( 1.23 ) == 1.23
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Approx( d ) != 1.22 )
|
||||
with expansion:
|
||||
Approx( 1.23 ) != 1.22
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( Approx( d ) != 1.24 )
|
||||
with expansion:
|
||||
Approx( 1.23 ) != 1.24
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Approximate comparisons with different epsilons
|
||||
-------------------------------------------------------------------------------
|
||||
ApproxTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( d != Approx( 1.231 ) )
|
||||
with expansion:
|
||||
1.23 != Approx( 1.231 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) )
|
||||
with expansion:
|
||||
1.23 == Approx( 1.231 )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Approximate comparisons with floats
|
||||
-------------------------------------------------------------------------------
|
||||
ApproxTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( 1.23f == Approx( 1.23f ) )
|
||||
with expansion:
|
||||
1.23f == Approx( 1.2300000191 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( 0.0f == Approx( 0.0f ) )
|
||||
with expansion:
|
||||
0.0f == Approx( 0.0 )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Approximate comparisons with ints
|
||||
-------------------------------------------------------------------------------
|
||||
ApproxTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( 1 == Approx( 1 ) )
|
||||
with expansion:
|
||||
1 == Approx( 1.0 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( 0 == Approx( 0 ) )
|
||||
with expansion:
|
||||
0 == Approx( 0.0 )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Approximate comparisons with mixed numeric types
|
||||
-------------------------------------------------------------------------------
|
||||
ApproxTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( 1.0f == Approx( 1 ) )
|
||||
with expansion:
|
||||
1.0f == Approx( 1.0 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( 0 == Approx( dZero) )
|
||||
with expansion:
|
||||
0 == Approx( 0.0 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) )
|
||||
with expansion:
|
||||
0 == Approx( 0.00001 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( 1.234f == Approx( dMedium ) )
|
||||
with expansion:
|
||||
1.234f == Approx( 1.234 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( dMedium == Approx( 1.234f ) )
|
||||
with expansion:
|
||||
1.234 == Approx( 1.2339999676 )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Use a custom approx
|
||||
-------------------------------------------------------------------------------
|
||||
ApproxTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( d == approx( 1.23 ) )
|
||||
with expansion:
|
||||
1.23 == Approx( 1.23 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( d == approx( 1.22 ) )
|
||||
with expansion:
|
||||
1.23 == Approx( 1.22 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( d == approx( 1.24 ) )
|
||||
with expansion:
|
||||
1.23 == Approx( 1.24 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( d != approx( 1.25 ) )
|
||||
with expansion:
|
||||
1.23 != Approx( 1.25 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( approx( d ) == 1.23 )
|
||||
with expansion:
|
||||
Approx( 1.23 ) == 1.23
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( approx( d ) == 1.22 )
|
||||
with expansion:
|
||||
Approx( 1.23 ) == 1.22
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( approx( d ) == 1.24 )
|
||||
with expansion:
|
||||
Approx( 1.23 ) == 1.24
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( approx( d ) != 1.25 )
|
||||
with expansion:
|
||||
Approx( 1.23 ) != 1.25
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Approximate PI
|
||||
-------------------------------------------------------------------------------
|
||||
ApproxTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) )
|
||||
with expansion:
|
||||
3.1428571429 == Approx( 3.141 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) )
|
||||
with expansion:
|
||||
3.1428571429 != Approx( 3.141 )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
A METHOD_AS_TEST_CASE based test run that succeeds
|
||||
-------------------------------------------------------------------------------
|
||||
ClassTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ClassTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( s == "hello" )
|
||||
with expansion:
|
||||
"hello" == "hello"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
A METHOD_AS_TEST_CASE based test run that fails
|
||||
-------------------------------------------------------------------------------
|
||||
ClassTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ClassTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( s == "world" )
|
||||
with expansion:
|
||||
"hello" == "world"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
A TEST_CASE_METHOD based test run that succeeds
|
||||
-------------------------------------------------------------------------------
|
||||
ClassTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ClassTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( m_a == 1 )
|
||||
with expansion:
|
||||
1 == 1
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
A TEST_CASE_METHOD based test run that fails
|
||||
-------------------------------------------------------------------------------
|
||||
ClassTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ClassTests.cpp:<line number>: FAILED:
|
||||
REQUIRE( m_a == 2 )
|
||||
with expansion:
|
||||
1 == 2
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Equality checks that should succeed
|
||||
-------------------------------------------------------------------------------
|
||||
ConditionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.int_seven == 7 )
|
||||
with expansion:
|
||||
7 == 7
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.float_nine_point_one == Approx( 9.1f ) )
|
||||
with expansion:
|
||||
9.1f == Approx( 9.1000003815 )
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.double_pi == Approx( 3.1415926535 ) )
|
||||
with expansion:
|
||||
3.1415926535 == Approx( 3.1415926535 )
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.str_hello == "hello" )
|
||||
with expansion:
|
||||
"hello" == "hello"
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( "hello" == data.str_hello )
|
||||
with expansion:
|
||||
"hello" == "hello"
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.str_hello.size() == 5 )
|
||||
with expansion:
|
||||
5 == 5
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( x == Approx( 1.3 ) )
|
||||
with expansion:
|
||||
1.3 == Approx( 1.3 )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Equality checks that should fail
|
||||
'Not' checks that should fail
|
||||
-------------------------------------------------------------------------------
|
||||
ConditionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( data.int_seven == 6 )
|
||||
with expansion:
|
||||
7 == 6
|
||||
CHECK( false != false )
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( data.int_seven == 8 )
|
||||
with expansion:
|
||||
7 == 8
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Inequality checks that should succeed
|
||||
-------------------------------------------------------------------------------
|
||||
ConditionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.int_seven != 6 )
|
||||
with expansion:
|
||||
7 != 6
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.int_seven != 8 )
|
||||
with expansion:
|
||||
7 != 8
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.float_nine_point_one != Approx( 9.11f ) )
|
||||
with expansion:
|
||||
9.1f != Approx( 9.1099996567 )
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.float_nine_point_one != Approx( 9.0f ) )
|
||||
with expansion:
|
||||
9.1f != Approx( 9.0 )
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.float_nine_point_one != Approx( 1 ) )
|
||||
with expansion:
|
||||
9.1f != Approx( 1.0 )
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.float_nine_point_one != Approx( 0 ) )
|
||||
with expansion:
|
||||
9.1f != Approx( 0.0 )
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.double_pi != Approx( 3.1415 ) )
|
||||
with expansion:
|
||||
3.1415926535 != Approx( 3.1415 )
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.str_hello != "goodbye" )
|
||||
with expansion:
|
||||
"hello" != "goodbye"
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.str_hello != "hell" )
|
||||
with expansion:
|
||||
"hello" != "hell"
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.str_hello != "hello1" )
|
||||
with expansion:
|
||||
"hello" != "hello1"
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( data.str_hello.size() != 6 )
|
||||
with expansion:
|
||||
5 != 6
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Inequality checks that should fail
|
||||
-------------------------------------------------------------------------------
|
||||
ConditionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
CHECK( true != true )
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( data.int_seven != 7 )
|
||||
CHECK( !true )
|
||||
with expansion:
|
||||
7 != 7
|
||||
false
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( data.float_nine_point_one != Approx( 9.1f ) )
|
||||
with expansion:
|
||||
9.1f != Approx( 9.1000003815 )
|
||||
CHECK_FALSE( true )
|
||||
|
||||
===============================================================================
|
||||
test cases: 19 | 15 passed | 3 failed | 1 failed as expected
|
||||
assertions: 62 | 56 passed | 4 failed | 2 failed as expected
|
||||
test cases: 2 | 1 passed | 1 failed
|
||||
assertions: 5 | 1 passed | 4 failed
|
||||
|
||||
|
@@ -1,29 +1,119 @@
|
||||
<?xml version="1.1" encoding="UTF-8"?>
|
||||
<testsuites>
|
||||
<testsuite name="CatchSelfTest" errors="12" failures="88" tests="808" hostname="tbd" time="{duration}" timestamp="tbd">
|
||||
<testcase classname="global" name="toString(enum)" time="{duration}"/>
|
||||
<testcase classname="global" name="toString(enum w/operator<<)" time="{duration}"/>
|
||||
<testcase classname="global" name="toString(enum class)" time="{duration}"/>
|
||||
<testcase classname="global" name="toString(enum class w/operator<<)" time="{duration}"/>
|
||||
<testcase classname="global" name="Some simple comparisons between doubles" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate comparisons with different epsilons" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate comparisons with floats" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate comparisons with ints" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate comparisons with mixed numeric types" time="{duration}"/>
|
||||
<testcase classname="global" name="Use a custom approx" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate PI" time="{duration}"/>
|
||||
<testcase classname="TestClass" name="A METHOD_AS_TEST_CASE based test run that succeeds" time="{duration}"/>
|
||||
<testsuite name="<exe-name>" errors="13" failures="68" tests="916" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testcase classname="global" name="# A test name that starts with a #" time="{duration}"/>
|
||||
<testcase classname="global" name="'Not' checks that should fail" time="{duration}">
|
||||
<failure message="false != false" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="true != true" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="false" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="!true" type="CHECK_FALSE">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="false" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="!true" type="CHECK_FALSE">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="false" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="!(1 == 1)" type="CHECK_FALSE">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="'Not' checks that should succeed" time="{duration}"/>
|
||||
<testcase classname="(unimplemented) static bools can be evaluated" name="compare to true" time="{duration}"/>
|
||||
<testcase classname="(unimplemented) static bools can be evaluated" name="compare to false" time="{duration}"/>
|
||||
<testcase classname="(unimplemented) static bools can be evaluated" name="negation" time="{duration}"/>
|
||||
<testcase classname="(unimplemented) static bools can be evaluated" name="double negation" time="{duration}"/>
|
||||
<testcase classname="(unimplemented) static bools can be evaluated" name="direct" time="{duration}"/>
|
||||
<testcase classname="TestClass" name="A METHOD_AS_TEST_CASE based test run that fails" time="{duration}">
|
||||
<failure message=""hello" == "world"" type="REQUIRE">
|
||||
ClassTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}"/>
|
||||
<testcase classname="TestClass" name="A METHOD_AS_TEST_CASE based test run that succeeds" time="{duration}"/>
|
||||
<testcase classname="Fixture" name="A TEST_CASE_METHOD based test run that fails" time="{duration}">
|
||||
<failure message="1 == 2" type="REQUIRE">
|
||||
ClassTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Equality checks that should succeed" time="{duration}"/>
|
||||
<testcase classname="Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}"/>
|
||||
<testcase classname="A couple of nested sections followed by a failure" name="root" time="{duration}">
|
||||
<failure type="FAIL">
|
||||
to infinity and beyond
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="A couple of nested sections followed by a failure" name="Outer/Inner" time="{duration}"/>
|
||||
<testcase classname="global" name="A failing expression with a non streamable type is still captured" time="{duration}">
|
||||
<failure message="0x<hex digits> == 0x<hex digits>" type="CHECK">
|
||||
TrickyTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="{?} == {?}" type="CHECK">
|
||||
TrickyTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="AllOf matcher" time="{duration}"/>
|
||||
<testcase classname="global" name="An expression with side-effects should only be evaluated once" time="{duration}"/>
|
||||
<testcase classname="global" name="An unchecked exception reports the line of the last assertion" time="{duration}">
|
||||
<error message="{Unknown expression after the reported line}">
|
||||
unexpected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Anonymous test case 1" time="{duration}"/>
|
||||
<testcase classname="global" name="AnyOf matcher" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate PI" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate comparisons with different epsilons" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate comparisons with floats" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate comparisons with ints" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate comparisons with mixed numeric types" time="{duration}"/>
|
||||
<testcase classname="Assertions then sections" name="root" time="{duration}"/>
|
||||
<testcase classname="Assertions then sections" name="A section" time="{duration}"/>
|
||||
<testcase classname="Assertions then sections" name="A section/Another section" time="{duration}"/>
|
||||
<testcase classname="Assertions then sections" name="A section/Another other section" time="{duration}"/>
|
||||
<testcase classname="global" name="Comparing function pointers" time="{duration}"/>
|
||||
<testcase classname="global" name="Comparing member function pointers" time="{duration}"/>
|
||||
<testcase classname="global" name="Comparisons between ints where one side is computed" time="{duration}"/>
|
||||
<testcase classname="global" name="Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" time="{duration}"/>
|
||||
<testcase classname="global" name="Comparisons with int literals don't warn when mixing signed/ unsigned" time="{duration}"/>
|
||||
<testcase classname="global" name="Contains string matcher" time="{duration}">
|
||||
<failure message=""this string contains 'abc' as a substring" contains: "not there"" type="CHECK_THAT">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Custom exceptions can be translated when testing for nothrow" time="{duration}">
|
||||
<error message="throwCustom()" type="REQUIRE_NOTHROW">
|
||||
custom exception - not std
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Custom exceptions can be translated when testing for throwing as something else" time="{duration}">
|
||||
<error message="throwCustom()" type="REQUIRE_THROWS_AS">
|
||||
custom exception - not std
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Custom std-exceptions can be custom translated" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
custom std exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Demonstrate that a non-const == is not used" time="{duration}"/>
|
||||
<testcase classname="global" name="EndsWith string matcher" time="{duration}">
|
||||
<failure message=""this string contains 'abc' as a substring" ends with: "this"" type="CHECK_THAT">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Equality checks that should fail" time="{duration}">
|
||||
<failure message="7 == 6" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
@@ -65,7 +155,63 @@ ConditionTests.cpp:<line number>
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Inequality checks that should succeed" time="{duration}"/>
|
||||
<testcase classname="global" name="Equality checks that should succeed" time="{duration}"/>
|
||||
<testcase classname="global" name="Equals" time="{duration}"/>
|
||||
<testcase classname="global" name="Equals string matcher" time="{duration}">
|
||||
<failure message=""this string contains 'abc' as a substring" equals: "something else"" type="CHECK_THAT">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Equals string matcher, with NULL" time="{duration}"/>
|
||||
<testcase classname="Exception messages can be tested for" name="exact match" time="{duration}"/>
|
||||
<testcase classname="Exception messages can be tested for" name="different case" time="{duration}"/>
|
||||
<testcase classname="Exception messages can be tested for" name="wildcarded" time="{duration}"/>
|
||||
<testcase classname="global" name="Expected exceptions that don't throw or unexpected exceptions fail the test" time="{duration}">
|
||||
<error message="thisThrows()" type="CHECK_THROWS_AS">
|
||||
expected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
<failure message="thisDoesntThrow()" type="CHECK_THROWS_AS">
|
||||
ExceptionTests.cpp:<line number>
|
||||
</failure>
|
||||
<error message="thisThrows()" type="CHECK_NOTHROW">
|
||||
expected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="FAIL aborts the test" time="{duration}">
|
||||
<failure type="FAIL">
|
||||
This is a failure
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="FAIL does not require an argument" time="{duration}">
|
||||
<failure type="FAIL">
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Factorials are computed" time="{duration}"/>
|
||||
<testcase classname="global" name="Generator over a range of pairs" time="{duration}"/>
|
||||
<testcase classname="global" name="Generators over two ranges" time="{duration}"/>
|
||||
<testcase classname="global" name="Greater-than inequalities with different epsilons" time="{duration}"/>
|
||||
<testcase classname="global" name="INFO and WARN do not abort tests" time="{duration}"/>
|
||||
<testcase classname="global" name="INFO gets logged on failure" time="{duration}">
|
||||
<failure message="2 == 1" type="REQUIRE">
|
||||
this message should be logged
|
||||
so should this
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="INFO gets logged on failure, even if captured before successful assertions" time="{duration}">
|
||||
<failure message="2 == 1" type="CHECK">
|
||||
this message should be logged
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="2 == 0" type="CHECK">
|
||||
and this, but later
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Inequality checks that should fail" time="{duration}">
|
||||
<failure message="7 != 7" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
@@ -83,7 +229,53 @@ ConditionTests.cpp:<line number>
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Ordering comparison checks that should succeed" time="{duration}"/>
|
||||
<testcase classname="global" name="Inequality checks that should succeed" time="{duration}"/>
|
||||
<testcase classname="global" name="Less-than inequalities with different epsilons" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/No wrapping" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/Wrapped once" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/Wrapped twice" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/Wrapped three times" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/Short wrap" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/As container" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/Indent first line differently" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With newlines/No wrapping" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With newlines/Trailing newline" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With newlines/Wrapped once" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With newlines/Wrapped twice" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With wrap-before/ after characters/No wrapping" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With wrap-before/ after characters/Wrap before" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With wrap-before/ after characters/Wrap after" time="{duration}"/>
|
||||
<testcase classname="global" name="Long text is truncted" time="{duration}"/>
|
||||
<testcase classname="global" name="ManuallyRegistered" time="{duration}"/>
|
||||
<testcase classname="global" name="Matchers can be (AllOf) composed with the && operator" time="{duration}"/>
|
||||
<testcase classname="global" name="Matchers can be (AnyOf) composed with the || operator" time="{duration}"/>
|
||||
<testcase classname="global" name="Matchers can be composed with both && and ||" time="{duration}"/>
|
||||
<testcase classname="global" name="Matchers can be composed with both && and || - failing" time="{duration}">
|
||||
<failure message=""this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" )" type="CHECK_THAT">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Matchers can be negated (Not) with the ! operator" time="{duration}"/>
|
||||
<testcase classname="global" name="Matchers can be negated (Not) with the ! operator - failing" time="{duration}">
|
||||
<failure message=""this string contains 'abc' as a substring" not contains: "substring"" type="CHECK_THAT">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Mismatching exception messages failing the test" time="{duration}">
|
||||
<failure message="expected exception" type="REQUIRE_THROWS_WITH">
|
||||
ExceptionTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Nice descriptive name" time="{duration}"/>
|
||||
<testcase classname="global" name="Non-std exceptions can be translated" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
custom exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="NotImplemented exception" time="{duration}"/>
|
||||
<testcase classname="global" name="Objects that evaluated in boolean contexts can be checked" time="{duration}"/>
|
||||
<testcase classname="global" name="Operators at different namespace levels not hijacked by Koenig lookup" time="{duration}"/>
|
||||
<testcase classname="global" name="Ordering comparison checks that should fail" time="{duration}">
|
||||
<failure message="7 > 7" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
@@ -143,155 +335,7 @@ ConditionTests.cpp:<line number>
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Comparisons with int literals don't warn when mixing signed/ unsigned" time="{duration}"/>
|
||||
<testcase classname="global" name="comparisons between int variables" time="{duration}"/>
|
||||
<testcase classname="global" name="comparisons between const int variables" time="{duration}"/>
|
||||
<testcase classname="global" name="Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" time="{duration}"/>
|
||||
<testcase classname="global" name="Comparisons between ints where one side is computed" time="{duration}"/>
|
||||
<testcase classname="global" name="Pointers can be compared to null" time="{duration}"/>
|
||||
<testcase classname="global" name="'Not' checks that should succeed" time="{duration}"/>
|
||||
<testcase classname="global" name="'Not' checks that should fail" time="{duration}">
|
||||
<failure message="false != false" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="true != true" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="false" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="!true" type="CHECK_FALSE">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="false" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="!true" type="CHECK_FALSE">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="false" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="!(1 == 1)" type="CHECK_FALSE">
|
||||
ConditionTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="When checked exceptions are thrown they can be expected or unexpected" time="{duration}"/>
|
||||
<testcase classname="global" name="Expected exceptions that don't throw or unexpected exceptions fail the test" time="{duration}">
|
||||
<error message="thisThrows()" type="CHECK_THROWS_AS">
|
||||
expected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
<failure message="thisDoesntThrow()" type="CHECK_THROWS_AS">
|
||||
ExceptionTests.cpp:<line number>
|
||||
</failure>
|
||||
<error message="thisThrows()" type="CHECK_NOTHROW">
|
||||
expected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="When unchecked exceptions are thrown directly they are always failures" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
unexpected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="An unchecked exception reports the line of the last assertion" time="{duration}">
|
||||
<error message="{Unknown expression after the reported line}">
|
||||
unexpected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="When unchecked exceptions are thrown from sections they are always failures" name="section name" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
unexpected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="When unchecked exceptions are thrown from functions they are always failures" time="{duration}">
|
||||
<error message="thisThrows() == 0" type="CHECK">
|
||||
expected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="When unchecked exceptions are thrown during a REQUIRE the test should abort fail" time="{duration}">
|
||||
<error message="thisThrows() == 0" type="REQUIRE">
|
||||
expected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="When unchecked exceptions are thrown during a CHECK the test should abort and fail" time="{duration}">
|
||||
<error message="thisThrows() == 0" type="CHECK">
|
||||
expected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Unexpected custom exceptions can be translated" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
custom exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Custom exceptions can be translated when testing for nothrow" time="{duration}">
|
||||
<error message="throwCustom()" type="REQUIRE_NOTHROW">
|
||||
custom exception - not std
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Custom exceptions can be translated when testing for throwing as something else" time="{duration}">
|
||||
<error message="throwCustom()" type="REQUIRE_THROWS_AS">
|
||||
custom exception - not std
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Unexpected exceptions can be translated" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
3.14
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="NotImplemented exception" time="{duration}"/>
|
||||
<testcase classname="Exception messages can be tested for" name="exact match" time="{duration}"/>
|
||||
<testcase classname="Exception messages can be tested for" name="different case" time="{duration}"/>
|
||||
<testcase classname="Exception messages can be tested for" name="wildcarded" time="{duration}"/>
|
||||
<testcase classname="global" name="Mismatching exception messages failing the test" time="{duration}">
|
||||
<failure message="expected exception" type="REQUIRE_THROWS_WITH">
|
||||
ExceptionTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Generators over two ranges" time="{duration}"/>
|
||||
<testcase classname="global" name="Generator over a range of pairs" time="{duration}"/>
|
||||
<testcase classname="global" name="INFO and WARN do not abort tests" time="{duration}"/>
|
||||
<testcase classname="global" name="SUCCEED counts as a test pass" time="{duration}"/>
|
||||
<testcase classname="global" name="INFO gets logged on failure" time="{duration}">
|
||||
<failure message="2 == 1" type="REQUIRE">
|
||||
this message should be logged
|
||||
so should this
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="INFO gets logged on failure, even if captured before successful assertions" time="{duration}">
|
||||
<failure message="2 == 1" type="CHECK">
|
||||
this message should be logged
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="2 == 0" type="CHECK">
|
||||
and this, but later
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="FAIL aborts the test" time="{duration}">
|
||||
<failure type="FAIL">
|
||||
This is a failure
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="FAIL does not require an argument" time="{duration}">
|
||||
<failure type="FAIL">
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="SUCCESS does not require an argument" time="{duration}"/>
|
||||
<testcase classname="global" name="Ordering comparison checks that should succeed" time="{duration}"/>
|
||||
<testcase classname="Output from all sections is reported" name="one" time="{duration}">
|
||||
<failure type="FAIL">
|
||||
Message from section one
|
||||
@@ -304,12 +348,64 @@ Message from section two
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="Standard output from all sections is reported" name="two" time="{duration}">
|
||||
<system-out>
|
||||
Message from section one
|
||||
Message from section two
|
||||
</system-out>
|
||||
</testcase>
|
||||
<testcase classname="Parse test names and tags" name="Empty test spec should have no filters" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Test spec from empty string should have no filters" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Test spec from just a comma should have no filters" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Test spec from name should have one filter" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Test spec from quoted name should have one filter" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Test spec from name should have one filter" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Wildcard at the start" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Wildcard at the end" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Wildcard at both ends" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Redundant wildcard at the start" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Redundant wildcard at the end" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Redundant wildcard at both ends" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Wildcard at both ends, redundant at start" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Just wildcard" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Single tag" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Single tag, two matches" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Two tags" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Two tags, spare separated" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Wildcarded name and tag" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Single tag exclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="One tag exclusion and one tag inclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="One tag exclusion and one wldcarded name inclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="One tag exclusion, using exclude:, and one wldcarded name inclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="name exclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="wildcarded name exclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="wildcarded name exclusion with tag inclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="wildcarded name exclusion, using exclude:, with tag inclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="two wildcarded names" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="empty tag" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="empty quoted name" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="quoted string followed by tag exclusion" time="{duration}"/>
|
||||
<testcase classname="global" name="Parsing a std::pair" time="{duration}"/>
|
||||
<testcase classname="global" name="Pointers can be compared to null" time="{duration}"/>
|
||||
<testcase classname="global" name="Pointers can be converted to strings" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="default - no arguments" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="test lists/1 test" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using exclude:" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using ~" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="reporter/-r/console" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="reporter/-r/xml" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="reporter/-r xml and junit" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="reporter/--reporter/junit" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="debugger/-b" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="debugger/--break" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="abort/-a aborts after first failure" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="abort/-x 2 aborts after two failures" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="abort/-x must be greater than zero" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="abort/-x must be numeric" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="nothrow/-e" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="nothrow/--nothrow" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="output filename/-o filename" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="output filename/--out" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="combinations/Single character flags can be combined" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="use-colour/without option" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="use-colour/auto" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="use-colour/yes" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="use-colour/no" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="use-colour/error" time="{duration}"/>
|
||||
<testcase classname="global" name="SCOPED_INFO is reset for each loop" time="{duration}">
|
||||
<failure message="10 < 10" type="REQUIRE">
|
||||
current counter 10
|
||||
@@ -317,30 +413,164 @@ i := 10
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="SUCCEED counts as a test pass" time="{duration}"/>
|
||||
<testcase classname="global" name="SUCCESS does not require an argument" time="{duration}"/>
|
||||
<testcase classname="Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me" time="{duration}"/>
|
||||
<testcase classname="Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me/When: We get the count/Then: Subsequently values are higher" time="{duration}"/>
|
||||
<testcase classname="Scenario: Do that thing with the thing" name="Given: This stuff exists/When: I do this/Then: it should do this" time="{duration}"/>
|
||||
<testcase classname="Scenario: Do that thing with the thing" name="Given: This stuff exists/When: I do this/Then: it should do this/And: do that" time="{duration}"/>
|
||||
<testcase classname="Scenario: This is a really long scenario name to see how the list command deals with wrapping" name="Given: A section name that is so long that it cannot fit in a single console width/When: The test headers are printed as part of the normal running of the scenario/Then: The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent" time="{duration}"/>
|
||||
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector" time="{duration}"/>
|
||||
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: it is made larger/Then: the size and capacity go up" time="{duration}"/>
|
||||
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: it is made larger/Then: the size and capacity go up/And when: it is made smaller again/Then: the size goes down but the capacity stays the same" time="{duration}"/>
|
||||
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: we reserve more space/Then: The capacity is increased but the size remains the same" time="{duration}"/>
|
||||
<testcase classname="global" name="Sends stuff to stdout and stderr" time="{duration}">
|
||||
<system-out>
|
||||
A string sent directly to stdout
|
||||
</system-out>
|
||||
<system-err>
|
||||
A string sent directly to stderr
|
||||
</system-err>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Some simple comparisons between doubles" time="{duration}"/>
|
||||
<testcase classname="Standard output from all sections is reported" name="two" time="{duration}">
|
||||
<system-out>
|
||||
Message from section one
|
||||
Message from section two
|
||||
</system-out>
|
||||
</testcase>
|
||||
<testcase classname="global" name="StartsWith string matcher" time="{duration}">
|
||||
<failure message=""this string contains 'abc' as a substring" starts with: "string"" type="CHECK_THAT">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="String matchers" time="{duration}"/>
|
||||
<testcase classname="global" name="Strings can be rendered with colour" time="{duration}">
|
||||
<system-out>
|
||||
hello
|
||||
hello
|
||||
</system-out>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Tabs and newlines show in output" time="{duration}">
|
||||
<failure message=""if ($b == 10) {
|
||||
$a = 20;
|
||||
}"
|
||||
==
|
||||
"if ($b == 10) {
|
||||
$a = 20;
|
||||
}
|
||||
"" type="CHECK">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="Tag alias can be registered against tag patterns" name="The same tag alias can only be registered once" time="{duration}"/>
|
||||
<testcase classname="Tag alias can be registered against tag patterns" name="Tag aliases must be of the form [@name]" time="{duration}"/>
|
||||
<testcase classname="global" name="Test case with one argument" time="{duration}"/>
|
||||
<testcase classname="global" name="Test enum bit values" time="{duration}"/>
|
||||
<testcase classname="global" name="Text can be formatted using the Text class" time="{duration}"/>
|
||||
<testcase classname="global" name="The NO_FAIL macro reports a failure but does not fail the test" time="{duration}"/>
|
||||
<testcase classname="global" name="This test 'should' fail but doesn't" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="root" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="successfully close one section" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="fail one section" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="fail one section/re-enter after failed section" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="fail one section/re-enter after failed section and find next section" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="successfully close one section, then find another" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="successfully close one section, then find another/Re-enter - skips S1 and enters S2" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="successfully close one section, then find another/Re-enter - skips S1 and enters S2/Successfully close S2" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="successfully close one section, then find another/Re-enter - skips S1 and enters S2/fail S2" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="open a nested section" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="start a generator" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="start a generator/close outer section" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="start a generator/close outer section/Re-enter for second generation" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="start a generator/Start a new inner section" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="start a generator/Start a new inner section/Re-enter for second generation" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="start a generator/Fail an inner section" time="{duration}"/>
|
||||
<testcase classname="Tracker" name="start a generator/Fail an inner section/Re-enter for second generation" time="{duration}"/>
|
||||
<testcase classname="global" name="Unexpected exceptions can be translated" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
3.14
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Use a custom approx" time="{duration}"/>
|
||||
<testcase classname="Variadic macros" name="Section with one argument" time="{duration}"/>
|
||||
<testcase classname="global" name="When checked exceptions are thrown they can be expected or unexpected" time="{duration}"/>
|
||||
<testcase classname="global" name="When unchecked exceptions are thrown directly they are always failures" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
unexpected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="When unchecked exceptions are thrown during a CHECK the test should continue" time="{duration}">
|
||||
<error message="thisThrows() == 0" type="CHECK">
|
||||
expected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="When unchecked exceptions are thrown during a REQUIRE the test should abort fail" time="{duration}">
|
||||
<error message="thisThrows() == 0" type="REQUIRE">
|
||||
expected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="When unchecked exceptions are thrown from functions they are always failures" time="{duration}">
|
||||
<error message="thisThrows() == 0" type="CHECK">
|
||||
expected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="When unchecked exceptions are thrown from sections they are always failures" name="section name" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
unexpected exception
|
||||
ExceptionTests.cpp:<line number>
|
||||
</error>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Where the LHS is not a simple value" time="{duration}"/>
|
||||
<testcase classname="global" name="Where there is more to the expression after the RHS" time="{duration}"/>
|
||||
<testcase classname="global" name="X/level/0/a" time="{duration}"/>
|
||||
<testcase classname="global" name="X/level/0/b" time="{duration}"/>
|
||||
<testcase classname="global" name="X/level/1/a" time="{duration}"/>
|
||||
<testcase classname="global" name="X/level/1/b" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="normal string" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="empty string" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with ampersand" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with less-than" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with greater-than" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with quotes" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with control char (1)" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with control char (x7F)" time="{duration}"/>
|
||||
<testcase classname="global" name="atomic if" time="{duration}"/>
|
||||
<testcase classname="global" name="boolean member" time="{duration}"/>
|
||||
<testcase classname="global" name="checkedElse" time="{duration}"/>
|
||||
<testcase classname="global" name="checkedElse, failing" time="{duration}">
|
||||
<failure message="false" type="CHECKED_ELSE">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="false" type="REQUIRE">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="checkedIf" time="{duration}"/>
|
||||
<testcase classname="global" name="checkedIf, failing" time="{duration}">
|
||||
<failure message="false" type="CHECKED_IF">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="false" type="REQUIRE">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="comparisons between const int variables" time="{duration}"/>
|
||||
<testcase classname="global" name="comparisons between int variables" time="{duration}"/>
|
||||
<testcase classname="even more nested SECTION tests" name="c/d (leaf)" time="{duration}"/>
|
||||
<testcase classname="even more nested SECTION tests" name="c/e (leaf)" time="{duration}"/>
|
||||
<testcase classname="even more nested SECTION tests" name="f (leaf)" time="{duration}"/>
|
||||
<testcase classname="global" name="just failure" time="{duration}">
|
||||
<failure type="FAIL">
|
||||
Previous info should not be seen
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="sends information to INFO" time="{duration}">
|
||||
<failure message="false" type="REQUIRE">
|
||||
hi
|
||||
i := 7
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Pointers can be converted to strings" time="{duration}"/>
|
||||
<testcase classname="random SECTION tests" name="s1" time="{duration}"/>
|
||||
<testcase classname="random SECTION tests" name="s2" time="{duration}"/>
|
||||
<testcase classname="nested SECTION tests" name="s1" time="{duration}"/>
|
||||
<testcase classname="nested SECTION tests" name="s1/s2" time="{duration}"/>
|
||||
<testcase classname="more nested SECTION tests" name="s2/s1" time="{duration}">
|
||||
<failure message="1 == 2" type="REQUIRE">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="looped SECTION tests" name="s1" time="{duration}">
|
||||
<failure message="0 > 1" type="CHECK">
|
||||
MiscTests.cpp:<line number>
|
||||
@@ -372,139 +602,22 @@ Testing if fib[7] (21) is even
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Sends stuff to stdout and stderr" time="{duration}">
|
||||
<system-out>
|
||||
A string sent directly to stdout
|
||||
</system-out>
|
||||
<system-err>
|
||||
A string sent directly to stderr
|
||||
</system-err>
|
||||
</testcase>
|
||||
<testcase classname="global" name="null strings" time="{duration}"/>
|
||||
<testcase classname="global" name="checkedIf" time="{duration}"/>
|
||||
<testcase classname="global" name="checkedIf, failing" time="{duration}">
|
||||
<failure message="false" type="CHECKED_IF">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="false" type="REQUIRE">
|
||||
<testcase classname="more nested SECTION tests" name="s2/s1" time="{duration}">
|
||||
<failure message="1 == 2" type="REQUIRE">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="checkedElse" time="{duration}"/>
|
||||
<testcase classname="global" name="checkedElse, failing" time="{duration}">
|
||||
<failure message="false" type="CHECKED_ELSE">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="false" type="REQUIRE">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="send a single char to INFO" time="{duration}">
|
||||
<failure message="false" type="REQUIRE">
|
||||
3
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="atomic if" time="{duration}"/>
|
||||
<testcase classname="global" name="String matchers" time="{duration}"/>
|
||||
<testcase classname="global" name="Contains string matcher" time="{duration}">
|
||||
<failure message=""this string contains 'abc' as a substring" contains: "not there"" type="CHECK_THAT">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="StartsWith string matcher" time="{duration}">
|
||||
<failure message=""this string contains 'abc' as a substring" starts with: "string"" type="CHECK_THAT">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="EndsWith string matcher" time="{duration}">
|
||||
<failure message=""this string contains 'abc' as a substring" ends with: "this"" type="CHECK_THAT">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Equals string matcher" time="{duration}">
|
||||
<failure message=""this string contains 'abc' as a substring" equals: "something else"" type="CHECK_THAT">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Equals string matcher, with NULL" time="{duration}"/>
|
||||
<testcase classname="global" name="AllOf matcher" time="{duration}"/>
|
||||
<testcase classname="global" name="AnyOf matcher" time="{duration}"/>
|
||||
<testcase classname="global" name="Equals" time="{duration}"/>
|
||||
<testcase classname="global" name="Factorials are computed" time="{duration}"/>
|
||||
<testcase classname="global" name="Nice descriptive name" time="{duration}"/>
|
||||
<testcase classname="vectors can be sized and resized" name="root" time="{duration}"/>
|
||||
<testcase classname="vectors can be sized and resized" name="resizing bigger changes size and capacity" time="{duration}"/>
|
||||
<testcase classname="vectors can be sized and resized" name="resizing smaller changes size but not capacity" time="{duration}"/>
|
||||
<testcase classname="vectors can be sized and resized" name="resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
|
||||
<testcase classname="vectors can be sized and resized" name="reserving bigger changes capacity but not size" time="{duration}"/>
|
||||
<testcase classname="vectors can be sized and resized" name="reserving smaller does not change size or capacity" time="{duration}"/>
|
||||
<testcase classname="A couple of nested sections followed by a failure" name="root" time="{duration}">
|
||||
<failure type="FAIL">
|
||||
to infinity and beyond
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="A couple of nested sections followed by a failure" name="Outer/Inner" time="{duration}"/>
|
||||
<testcase classname="more nested SECTION tests" name="s1/s3" time="{duration}"/>
|
||||
<testcase classname="more nested SECTION tests" name="s1/s4" time="{duration}"/>
|
||||
<testcase classname="nested SECTION tests" name="s1" time="{duration}"/>
|
||||
<testcase classname="nested SECTION tests" name="s1/s2" time="{duration}"/>
|
||||
<testcase classname="global" name="non streamable - with conv. op" time="{duration}"/>
|
||||
<testcase classname="global" name="not allowed" time="{duration}"/>
|
||||
<testcase classname="global" name="Tabs and newlines show in output" time="{duration}">
|
||||
<failure message=""if ($b == 10) {
|
||||
$a = 20;
|
||||
}"
|
||||
==
|
||||
"if ($b == 10) {
|
||||
$a = 20;
|
||||
}
|
||||
"" type="CHECK">
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="toString on const wchar_t const pointer returns the string contents" time="{duration}"/>
|
||||
<testcase classname="global" name="toString on const wchar_t pointer returns the string contents" time="{duration}"/>
|
||||
<testcase classname="global" name="toString on wchar_t const pointer returns the string contents" time="{duration}"/>
|
||||
<testcase classname="global" name="toString on wchar_t returns the string contents" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="normal string" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="empty string" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with ampersand" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with less-than" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with greater-than" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with quotes" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with control char (1)" time="{duration}"/>
|
||||
<testcase classname="XmlEncode" name="string with control char (x7F)" time="{duration}"/>
|
||||
<testcase classname="global" name="long long" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="default - no arguments" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="test lists/1 test" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using exclude:" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="test lists/Specify one test case exclusion using ~" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="reporter/-r/console" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="reporter/-r/xml" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="reporter/-r xml and junit" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="reporter/--reporter/junit" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="debugger/-b" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="debugger/--break" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="abort/-a aborts after first failure" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="abort/-x 2 aborts after two failures" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="abort/-x must be greater than zero" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="abort/-x must be numeric" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="nothrow/-e" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="nothrow/--nothrow" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="output filename/-o filename" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="output filename/--out" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="combinations/Single character flags can be combined" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="force-colour/--force-colour" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="force-colour/without --force-colour" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/No wrapping" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/Wrapped once" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/Wrapped twice" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/Wrapped three times" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/Short wrap" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/As container" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="plain string/Indent first line differently" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With newlines/No wrapping" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With newlines/Trailing newline" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With newlines/Wrapped once" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With newlines/Wrapped twice" time="{duration}"/>
|
||||
<testcase classname="Long strings can be wrapped" name="With tabs" time="{duration}"/>
|
||||
<testcase classname="global" name="null strings" time="{duration}"/>
|
||||
<testcase classname="global" name="pair<pair<int,const char *,pair<std::string,int> > -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="pointer to class" time="{duration}"/>
|
||||
<testcase classname="random SECTION tests" name="s1" time="{duration}"/>
|
||||
<testcase classname="random SECTION tests" name="s2" time="{duration}"/>
|
||||
<testcase classname="replaceInPlace" name="replace single char" time="{duration}"/>
|
||||
<testcase classname="replaceInPlace" name="replace two chars" time="{duration}"/>
|
||||
<testcase classname="replaceInPlace" name="replace first char" time="{duration}"/>
|
||||
@@ -512,128 +625,51 @@ MiscTests.cpp:<line number>
|
||||
<testcase classname="replaceInPlace" name="replace all chars" time="{duration}"/>
|
||||
<testcase classname="replaceInPlace" name="replace no chars" time="{duration}"/>
|
||||
<testcase classname="replaceInPlace" name="escape '" time="{duration}"/>
|
||||
<testcase classname="global" name="Strings can be rendered with colour" time="{duration}">
|
||||
<system-out>
|
||||
hello
|
||||
hello
|
||||
</system-out>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Text can be formatted using the Text class" time="{duration}"/>
|
||||
<testcase classname="global" name="Long text is truncted" time="{duration}"/>
|
||||
<testcase classname="global" name="Parsing a std::pair" time="{duration}"/>
|
||||
<testcase classname="global" name="Where there is more to the expression after the RHS" time="{duration}"/>
|
||||
<testcase classname="global" name="Where the LHS is not a simple value" time="{duration}"/>
|
||||
<testcase classname="global" name="A failing expression with a non streamable type is still captured" time="{duration}">
|
||||
<failure message="0x<hex digits> == 0x<hex digits>" type="CHECK">
|
||||
TrickyTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="{?} == {?}" type="CHECK">
|
||||
TrickyTests.cpp:<line number>
|
||||
<testcase classname="global" name="send a single char to INFO" time="{duration}">
|
||||
<failure message="false" type="REQUIRE">
|
||||
3
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="sends information to INFO" time="{duration}">
|
||||
<failure message="false" type="REQUIRE">
|
||||
hi
|
||||
i := 7
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="std::pair<int,const std::string> -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="std::pair<int,std::string> -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="std::vector<std::pair<std::string,int> > -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="string literals of different sizes can be compared" time="{duration}">
|
||||
<failure message=""first" == "second"" type="REQUIRE">
|
||||
TrickyTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="An expression with side-effects should only be evaluated once" time="{duration}"/>
|
||||
<testcase classname="global" name="Operators at different namespace levels not hijacked by Koenig lookup" time="{duration}"/>
|
||||
<testcase classname="global" name="Demonstrate that a non-const == is not used" time="{duration}"/>
|
||||
<testcase classname="global" name="Test enum bit values" time="{duration}"/>
|
||||
<testcase classname="global" name="boolean member" time="{duration}"/>
|
||||
<testcase classname="(unimplemented) static bools can be evaluated" name="compare to true" time="{duration}"/>
|
||||
<testcase classname="(unimplemented) static bools can be evaluated" name="compare to false" time="{duration}"/>
|
||||
<testcase classname="(unimplemented) static bools can be evaluated" name="negation" time="{duration}"/>
|
||||
<testcase classname="(unimplemented) static bools can be evaluated" name="double negation" time="{duration}"/>
|
||||
<testcase classname="(unimplemented) static bools can be evaluated" name="direct" time="{duration}"/>
|
||||
<testcase classname="global" name="Objects that evaluated in boolean contexts can be checked" time="{duration}"/>
|
||||
<testcase classname="Assertions then sections" name="root" time="{duration}"/>
|
||||
<testcase classname="Assertions then sections" name="A section" time="{duration}"/>
|
||||
<testcase classname="Assertions then sections" name="A section/Another section" time="{duration}"/>
|
||||
<testcase classname="Assertions then sections" name="A section/Another other section" time="{duration}"/>
|
||||
<testcase classname="global" name="non streamable - with conv. op" time="{duration}"/>
|
||||
<testcase classname="global" name="Comparing function pointers" time="{duration}"/>
|
||||
<testcase classname="global" name="Comparing member function pointers" time="{duration}"/>
|
||||
<testcase classname="global" name="pointer to class" time="{duration}"/>
|
||||
<testcase classname="global" name="null_ptr" time="{duration}"/>
|
||||
<testcase classname="global" name="X/level/0/a" time="{duration}"/>
|
||||
<testcase classname="global" name="X/level/0/b" time="{duration}"/>
|
||||
<testcase classname="global" name="X/level/1/a" time="{duration}"/>
|
||||
<testcase classname="global" name="X/level/1/b" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( has_toString )" time="{duration}"/>
|
||||
<testcase classname="global" name="toString on const wchar_t const pointer returns the string contents" time="{duration}"/>
|
||||
<testcase classname="global" name="toString on const wchar_t pointer returns the string contents" time="{duration}"/>
|
||||
<testcase classname="global" name="toString on wchar_t const pointer returns the string contents" time="{duration}"/>
|
||||
<testcase classname="global" name="toString on wchar_t returns the string contents" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( has_maker )" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( has_maker_and_toString )" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( vectors<has_toString )" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( has_toString )" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( vectors<has_maker )" time="{duration}"/>
|
||||
<testcase classname="global" name="toString( vectors<has_maker_and_toString )" time="{duration}"/>
|
||||
<testcase classname="global" name="std::pair<int,std::string> -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="std::pair<int,const std::string> -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="std::vector<std::pair<std::string,int> > -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="pair<pair<int,const char *,pair<std::string,int> > -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="toString(enum w/operator<<)" time="{duration}"/>
|
||||
<testcase classname="global" name="toString(enum)" time="{duration}"/>
|
||||
<testcase classname="global" name="vector<int> -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="vector<string> -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="vector<int,allocator> -> toString" time="{duration}"/>
|
||||
<testcase classname="global" name="vec<vec<string,alloc>> -> toString" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Empty test spec should have no filters" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Test spec from empty string should have no filters" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Test spec from just a comma should have no filters" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Test spec from name should have one filter" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Test spec from quoted name should have one filter" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Test spec from name should have one filter" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Wildcard at the start" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Wildcard at the end" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Wildcard at both ends" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Redundant wildcard at the start" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Redundant wildcard at the end" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Redundant wildcard at both ends" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Wildcard at both ends, redundant at start" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Just wildcard" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Single tag" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Single tag, two matches" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Two tags" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Two tags, spare separated" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Wildcarded name and tag" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="Single tag exclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="One tag exclusion and one tag inclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="One tag exclusion and one wldcarded name inclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="One tag exclusion, using exclude:, and one wldcarded name inclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="name exclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="wildcarded name exclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="wildcarded name exclusion with tag inclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="wildcarded name exclusion, using exclude:, with tag inclusion" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="two wildcarded names" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="empty tag" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="empty quoted name" time="{duration}"/>
|
||||
<testcase classname="Parse test names and tags" name="quoted string followed by tag exclusion" time="{duration}"/>
|
||||
<testcase classname="global" name="tuple<>" time="{duration}"/>
|
||||
<testcase classname="global" name="tuple<int>" time="{duration}"/>
|
||||
<testcase classname="global" name="tuple<float,int>" time="{duration}"/>
|
||||
<testcase classname="global" name="tuple<string,string>" time="{duration}"/>
|
||||
<testcase classname="global" name="tuple<tuple<int>,tuple<>,float>" time="{duration}"/>
|
||||
<testcase classname="global" name="tuple<nullptr,int,const char *>" time="{duration}"/>
|
||||
<testcase classname="Tag alias can be registered against tag patterns" name="The same tag alias can only be registered once" time="{duration}"/>
|
||||
<testcase classname="Tag alias can be registered against tag patterns" name="Tag aliases must be of the form [@name]" time="{duration}"/>
|
||||
<testcase classname="global" name="Anonymous test case 1" time="{duration}"/>
|
||||
<testcase classname="global" name="Test case with one argument" time="{duration}"/>
|
||||
<testcase classname="Variadic macros" name="Section with one argument" time="{duration}"/>
|
||||
<testcase classname="Scenario: Do that thing with the thing" name="Given: This stuff exists/When: I do this/Then: it should do this" time="{duration}"/>
|
||||
<testcase classname="Scenario: Do that thing with the thing" name="Given: This stuff exists/When: I do this/Then: it should do this/And: do that" time="{duration}"/>
|
||||
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector" time="{duration}"/>
|
||||
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: it is made larger/Then: the size and capacity go up" time="{duration}"/>
|
||||
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: it is made larger/Then: the size and capacity go up/And when: it is made smaller again/Then: the size goes down but the capacity stays the same" time="{duration}"/>
|
||||
<testcase classname="Scenario: Vector resizing affects size and capacity" name="Given: an empty vector/When: we reserve more space/Then: The capacity is increased but the size remains the same" time="{duration}"/>
|
||||
<testcase classname="Scenario: This is a really long scenario name to see how the list command deals with wrapping" name="Given: A section name that is so long that it cannot fit in a single console width/When: The test headers are printed as part of the normal running of the scenario/Then: The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent" time="{duration}"/>
|
||||
<testcase classname="Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me" time="{duration}"/>
|
||||
<testcase classname="Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me/When: We get the count/Then: Subsequently values are higher" time="{duration}"/>
|
||||
<testcase classname="section tracking" name="root" time="{duration}"/>
|
||||
<testcase classname="section tracking" name="test case with no sections" time="{duration}"/>
|
||||
<testcase classname="section tracking" name="test case with one section" time="{duration}"/>
|
||||
<testcase classname="section tracking" name="test case with two consecutive sections" time="{duration}"/>
|
||||
<testcase classname="section tracking" name="test case with one section within another" time="{duration}"/>
|
||||
<testcase classname="vectors can be sized and resized" name="root" time="{duration}"/>
|
||||
<testcase classname="vectors can be sized and resized" name="resizing bigger changes size and capacity" time="{duration}"/>
|
||||
<testcase classname="vectors can be sized and resized" name="resizing smaller changes size but not capacity" time="{duration}"/>
|
||||
<testcase classname="vectors can be sized and resized" name="resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
|
||||
<testcase classname="vectors can be sized and resized" name="reserving bigger changes capacity but not size" time="{duration}"/>
|
||||
<testcase classname="vectors can be sized and resized" name="reserving smaller does not change size or capacity" time="{duration}"/>
|
||||
<testcase classname="xmlentitycheck" name="embedded xml" time="{duration}"/>
|
||||
<testcase classname="xmlentitycheck" name="encoded chars" time="{duration}"/>
|
||||
<system-out>
|
||||
A string sent directly to stdout
|
||||
Message from section one
|
||||
Message from section two
|
||||
A string sent directly to stdout
|
||||
hello
|
||||
hello
|
||||
</system-out>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user