mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-17 19:22:25 +01:00
Merge remote-tracking branch 'upstream/master' into contrib
This commit is contained in:
commit
9a1791ab9f
66
.travis.yml
66
.travis.yml
@ -17,7 +17,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'clang-3.5']
|
packages: ['valgrind', 'lcov', 'clang-3.5']
|
||||||
env: COMPILER='clang++-3.5' VALGRIND=1
|
env: COMPILER='clang++-3.5' VALGRIND=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@ -25,7 +25,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'clang-3.6']
|
packages: ['valgrind', 'lcov', 'clang-3.6']
|
||||||
env: COMPILER='clang++-3.6' VALGRIND=1
|
env: COMPILER='clang++-3.6' VALGRIND=1
|
||||||
|
|
||||||
# Travis's containers do not seem to have Clang 3.7 in apt, no matter what sources I add.
|
# Travis's containers do not seem to have Clang 3.7 in apt, no matter what sources I add.
|
||||||
@ -42,7 +42,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'clang-3.8']
|
packages: ['valgrind', 'lcov', 'clang-3.8']
|
||||||
env: COMPILER='clang++-3.8' VALGRIND=1
|
env: COMPILER='clang++-3.8' VALGRIND=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@ -50,7 +50,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['clang-3.9', 'valgrind']
|
packages: ['clang-3.9', 'valgrind', 'lcov']
|
||||||
env: COMPILER='clang++-3.9' VALGRIND=1
|
env: COMPILER='clang++-3.9' VALGRIND=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@ -58,7 +58,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['clang-4.0', 'valgrind']
|
packages: ['clang-4.0', 'valgrind', 'lcov']
|
||||||
env: COMPILER='clang++-4.0' VALGRIND=1
|
env: COMPILER='clang++-4.0' VALGRIND=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@ -66,7 +66,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['clang-5.0', 'valgrind']
|
packages: ['clang-5.0', 'valgrind', 'lcov']
|
||||||
env: COMPILER='clang++-5.0' VALGRIND=1
|
env: COMPILER='clang++-5.0' VALGRIND=1
|
||||||
|
|
||||||
# 2/ Linux GCC Builds
|
# 2/ Linux GCC Builds
|
||||||
@ -75,7 +75,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['valgrind', 'g++-4.8']
|
packages: ['valgrind', 'lcov', 'g++-4.8']
|
||||||
env: COMPILER='g++-4.8' VALGRIND=1
|
env: COMPILER='g++-4.8' VALGRIND=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@ -83,7 +83,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'g++-4.9']
|
packages: ['valgrind', 'lcov', 'g++-4.9']
|
||||||
env: COMPILER='g++-4.9' VALGRIND=1
|
env: COMPILER='g++-4.9' VALGRIND=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@ -91,7 +91,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'g++-5']
|
packages: ['valgrind', 'lcov', 'g++-5']
|
||||||
env: COMPILER='g++-5' VALGRIND=1
|
env: COMPILER='g++-5' VALGRIND=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@ -99,7 +99,7 @@ matrix:
|
|||||||
addons: &gcc6
|
addons: &gcc6
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'g++-6']
|
packages: ['valgrind', 'lcov', 'g++-6']
|
||||||
env: COMPILER='g++-6' VALGRIND=1
|
env: COMPILER='g++-6' VALGRIND=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@ -107,20 +107,15 @@ matrix:
|
|||||||
addons: &gcc7
|
addons: &gcc7
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['valgrind', 'g++-7']
|
packages: ['valgrind', 'lcov', 'g++-7']
|
||||||
env: COMPILER='g++-7' VALGRIND=1
|
env: COMPILER='g++-7' VALGRIND=1
|
||||||
|
|
||||||
- os: linux
|
|
||||||
compiler: gcc
|
|
||||||
addons: *gcc7
|
|
||||||
env: COMPILER='g++-7' ENV_NO_SELFTEST=1 ENV_BUILD_EXAMPLES=1
|
|
||||||
|
|
||||||
# 3b/ Linux C++14 Clang builds
|
# 3b/ Linux C++14 Clang builds
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages: ['clang-3.8', 'valgrind', 'libstdc++-6-dev']
|
packages: ['clang-3.8', 'valgrind', 'lcov', 'libstdc++-6-dev']
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
- llvm-toolchain-trusty
|
- llvm-toolchain-trusty
|
||||||
@ -131,7 +126,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['clang-3.9', 'valgrind', 'libstdc++-6-dev']
|
packages: ['clang-3.9', 'valgrind', 'lcov', 'libstdc++-6-dev']
|
||||||
env: COMPILER='clang++-3.9' CPP14=1 VALGRIND=1
|
env: COMPILER='clang++-3.9' CPP14=1 VALGRIND=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@ -139,7 +134,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['clang-4.0', 'valgrind', 'libstdc++-6-dev']
|
packages: ['clang-4.0', 'valgrind', 'lcov', 'libstdc++-6-dev']
|
||||||
env: COMPILER='clang++-4.0' CPP14=1 VALGRIND=1
|
env: COMPILER='clang++-4.0' CPP14=1 VALGRIND=1
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@ -147,7 +142,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: *all_sources
|
sources: *all_sources
|
||||||
packages: ['clang-5.0', 'valgrind', 'libstdc++-6-dev']
|
packages: ['clang-5.0', 'valgrind', 'lcov', 'libstdc++-6-dev']
|
||||||
env: COMPILER='clang++-5.0' CPP14=1 VALGRIND=1
|
env: COMPILER='clang++-5.0' CPP14=1 VALGRIND=1
|
||||||
|
|
||||||
|
|
||||||
@ -188,6 +183,7 @@ matrix:
|
|||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER='clang++' USE_CPP14=1
|
env: COMPILER='clang++' USE_CPP14=1
|
||||||
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||||
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
|
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
|
||||||
@ -197,7 +193,7 @@ install:
|
|||||||
mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
|
mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
|
||||||
export PATH=${DEPS_DIR}/cmake/bin:${PATH}
|
export PATH=${DEPS_DIR}/cmake/bin:${PATH}
|
||||||
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||||
which cmake || brew install cmake
|
which cmake || brew install cmake;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
@ -206,15 +202,25 @@ before_script:
|
|||||||
# Regenerate single header file, so it is tested in the examples...
|
# Regenerate single header file, so it is tested in the examples...
|
||||||
- python scripts/generateSingleHeader.py
|
- python scripts/generateSingleHeader.py
|
||||||
|
|
||||||
|
- |
|
||||||
# Use Debug builds for running Valgrind and building examples
|
# Use Debug builds for running Valgrind and building examples
|
||||||
- cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DUSE_VALGRIND=${VALGRIND} -DBUILD_EXAMPLES=ON
|
cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DUSE_VALGRIND=${VALGRIND} -DBUILD_EXAMPLES=ON -DENABLE_COVERAGE=ON
|
||||||
# Check that we don't miscompile with optimalizations...
|
# Don't bother with release build for coverage build
|
||||||
- cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
|
cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
|
||||||
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- cd Build-Debug
|
- |
|
||||||
- make -j 2
|
cd Build-Debug
|
||||||
- ctest -V -j 2
|
make -j 2
|
||||||
- cd ../Build-Release
|
CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
|
||||||
- make -j 2
|
# Coverage collection does not work for OS X atm
|
||||||
- ctest -V -j 2
|
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||||
|
make gcov
|
||||||
|
make lcov
|
||||||
|
bash <(curl -s https://codecov.io/bash) -X gcov || echo "Codecov did not collect coverage reports"
|
||||||
|
fi
|
||||||
|
# Go to release build
|
||||||
|
cd ../Build-Release
|
||||||
|
make -j 2
|
||||||
|
CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
|
||||||
|
157
CMake/FindGcov.cmake
Normal file
157
CMake/FindGcov.cmake
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
# This file is part of CMake-codecov.
|
||||||
|
#
|
||||||
|
# Copyright (c)
|
||||||
|
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
|
||||||
|
#
|
||||||
|
# See the LICENSE file in the package base directory for details
|
||||||
|
#
|
||||||
|
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# include required Modules
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
|
||||||
|
# Search for gcov binary.
|
||||||
|
set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
|
||||||
|
set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY})
|
||||||
|
|
||||||
|
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||||
|
foreach (LANG ${ENABLED_LANGUAGES})
|
||||||
|
# Gcov evaluation is dependend on the used compiler. Check gcov support for
|
||||||
|
# each compiler that is used. If gcov binary was already found for this
|
||||||
|
# compiler, do not try to find it again.
|
||||||
|
if (NOT GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN)
|
||||||
|
get_filename_component(COMPILER_PATH "${CMAKE_${LANG}_COMPILER}" PATH)
|
||||||
|
|
||||||
|
if ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "GNU")
|
||||||
|
# Some distributions like OSX (homebrew) ship gcov with the compiler
|
||||||
|
# version appended as gcov-x. To find this binary we'll build the
|
||||||
|
# suggested binary name with the compiler version.
|
||||||
|
string(REGEX MATCH "^[0-9]+" GCC_VERSION
|
||||||
|
"${CMAKE_${LANG}_COMPILER_VERSION}")
|
||||||
|
|
||||||
|
find_program(GCOV_BIN NAMES gcov-${GCC_VERSION} gcov
|
||||||
|
HINTS ${COMPILER_PATH})
|
||||||
|
|
||||||
|
elseif ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Clang")
|
||||||
|
# Some distributions like Debian ship llvm-cov with the compiler
|
||||||
|
# version appended as llvm-cov-x.y. To find this binary we'll build
|
||||||
|
# the suggested binary name with the compiler version.
|
||||||
|
string(REGEX MATCH "^[0-9]+.[0-9]+" LLVM_VERSION
|
||||||
|
"${CMAKE_${LANG}_COMPILER_VERSION}")
|
||||||
|
|
||||||
|
# llvm-cov prior version 3.5 seems to be not working with coverage
|
||||||
|
# evaluation tools, but these versions are compatible with the gcc
|
||||||
|
# gcov tool.
|
||||||
|
if(LLVM_VERSION VERSION_GREATER 3.4)
|
||||||
|
find_program(LLVM_COV_BIN NAMES "llvm-cov-${LLVM_VERSION}"
|
||||||
|
"llvm-cov" HINTS ${COMPILER_PATH})
|
||||||
|
mark_as_advanced(LLVM_COV_BIN)
|
||||||
|
|
||||||
|
if (LLVM_COV_BIN)
|
||||||
|
find_program(LLVM_COV_WRAPPER "llvm-cov-wrapper" PATHS
|
||||||
|
${CMAKE_MODULE_PATH})
|
||||||
|
if (LLVM_COV_WRAPPER)
|
||||||
|
set(GCOV_BIN "${LLVM_COV_WRAPPER}" CACHE FILEPATH "")
|
||||||
|
|
||||||
|
# set additional parameters
|
||||||
|
set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV
|
||||||
|
"LLVM_COV_BIN=${LLVM_COV_BIN}" CACHE STRING
|
||||||
|
"Environment variables for llvm-cov-wrapper.")
|
||||||
|
mark_as_advanced(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (NOT GCOV_BIN)
|
||||||
|
# Fall back to gcov binary if llvm-cov was not found or is
|
||||||
|
# incompatible. This is the default on OSX, but may crash on
|
||||||
|
# recent Linux versions.
|
||||||
|
find_program(GCOV_BIN gcov HINTS ${COMPILER_PATH})
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
if (GCOV_BIN)
|
||||||
|
set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN "${GCOV_BIN}" CACHE STRING
|
||||||
|
"${LANG} gcov binary.")
|
||||||
|
|
||||||
|
if (NOT CMAKE_REQUIRED_QUIET)
|
||||||
|
message("-- Found gcov evaluation for "
|
||||||
|
"${CMAKE_${LANG}_COMPILER_ID}: ${GCOV_BIN}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
unset(GCOV_BIN CACHE)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Add a new global target for all gcov targets. This target could be used to
|
||||||
|
# generate the gcov files for the whole project instead of calling <TARGET>-gcov
|
||||||
|
# for each target.
|
||||||
|
if (NOT TARGET gcov)
|
||||||
|
add_custom_target(gcov)
|
||||||
|
endif (NOT TARGET gcov)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# This function will add gcov evaluation for target <TNAME>. Only sources of
|
||||||
|
# this target will be evaluated and no dependencies will be added. It will call
|
||||||
|
# Gcov on any source file of <TNAME> once and store the gcov file in the same
|
||||||
|
# directory.
|
||||||
|
function (add_gcov_target TNAME)
|
||||||
|
set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)
|
||||||
|
|
||||||
|
# We don't have to check, if the target has support for coverage, thus this
|
||||||
|
# will be checked by add_coverage_target in Findcoverage.cmake. Instead we
|
||||||
|
# have to determine which gcov binary to use.
|
||||||
|
get_target_property(TSOURCES ${TNAME} SOURCES)
|
||||||
|
set(SOURCES "")
|
||||||
|
set(TCOMPILER "")
|
||||||
|
foreach (FILE ${TSOURCES})
|
||||||
|
codecov_path_of_source(${FILE} FILE)
|
||||||
|
if (NOT "${FILE}" STREQUAL "")
|
||||||
|
codecov_lang_of_source(${FILE} LANG)
|
||||||
|
if (NOT "${LANG}" STREQUAL "")
|
||||||
|
list(APPEND SOURCES "${FILE}")
|
||||||
|
set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID})
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
# If no gcov binary was found, coverage data can't be evaluated.
|
||||||
|
if (NOT GCOV_${TCOMPILER}_BIN)
|
||||||
|
message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.")
|
||||||
|
return()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}")
|
||||||
|
set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}")
|
||||||
|
|
||||||
|
|
||||||
|
set(BUFFER "")
|
||||||
|
foreach(FILE ${SOURCES})
|
||||||
|
get_filename_component(FILE_PATH "${TDIR}/${FILE}" PATH)
|
||||||
|
|
||||||
|
# call gcov
|
||||||
|
add_custom_command(OUTPUT ${TDIR}/${FILE}.gcov
|
||||||
|
COMMAND ${GCOV_ENV} ${GCOV_BIN} ${TDIR}/${FILE}.gcno > /dev/null
|
||||||
|
DEPENDS ${TNAME} ${TDIR}/${FILE}.gcno
|
||||||
|
WORKING_DIRECTORY ${FILE_PATH}
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND BUFFER ${TDIR}/${FILE}.gcov)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
|
||||||
|
# add target for gcov evaluation of <TNAME>
|
||||||
|
add_custom_target(${TNAME}-gcov DEPENDS ${BUFFER})
|
||||||
|
|
||||||
|
# add evaluation target to the global gcov target.
|
||||||
|
add_dependencies(gcov ${TNAME}-gcov)
|
||||||
|
endfunction (add_gcov_target)
|
354
CMake/FindLcov.cmake
Normal file
354
CMake/FindLcov.cmake
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
# This file is part of CMake-codecov.
|
||||||
|
#
|
||||||
|
# Copyright (c)
|
||||||
|
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
|
||||||
|
#
|
||||||
|
# See the LICENSE file in the package base directory for details
|
||||||
|
#
|
||||||
|
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# configuration
|
||||||
|
set(LCOV_DATA_PATH "${CMAKE_BINARY_DIR}/lcov/data")
|
||||||
|
set(LCOV_DATA_PATH_INIT "${LCOV_DATA_PATH}/init")
|
||||||
|
set(LCOV_DATA_PATH_CAPTURE "${LCOV_DATA_PATH}/capture")
|
||||||
|
set(LCOV_HTML_PATH "${CMAKE_BINARY_DIR}/lcov/html")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Search for Gcov which is used by Lcov.
|
||||||
|
find_package(Gcov)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# This function will add lcov evaluation for target <TNAME>. Only sources of
|
||||||
|
# this target will be evaluated and no dependencies will be added. It will call
|
||||||
|
# geninfo on any source file of <TNAME> once and store the info file in the same
|
||||||
|
# directory.
|
||||||
|
#
|
||||||
|
# Note: This function is only a wrapper to define this function always, even if
|
||||||
|
# coverage is not supported by the compiler or disabled. This function must
|
||||||
|
# be defined here, because the module will be exited, if there is no coverage
|
||||||
|
# support by the compiler or it is disabled by the user.
|
||||||
|
function (add_lcov_target TNAME)
|
||||||
|
if (LCOV_FOUND)
|
||||||
|
# capture initial coverage data
|
||||||
|
lcov_capture_initial_tgt(${TNAME})
|
||||||
|
|
||||||
|
# capture coverage data after execution
|
||||||
|
lcov_capture_tgt(${TNAME})
|
||||||
|
endif ()
|
||||||
|
endfunction (add_lcov_target)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# include required Modules
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
# Search for required lcov binaries.
|
||||||
|
find_program(LCOV_BIN lcov)
|
||||||
|
find_program(GENINFO_BIN geninfo)
|
||||||
|
find_program(GENHTML_BIN genhtml)
|
||||||
|
find_package_handle_standard_args(lcov
|
||||||
|
REQUIRED_VARS LCOV_BIN GENINFO_BIN GENHTML_BIN
|
||||||
|
)
|
||||||
|
|
||||||
|
# enable genhtml C++ demangeling, if c++filt is found.
|
||||||
|
set(GENHTML_CPPFILT_FLAG "")
|
||||||
|
find_program(CPPFILT_BIN c++filt)
|
||||||
|
if (NOT CPPFILT_BIN STREQUAL "")
|
||||||
|
set(GENHTML_CPPFILT_FLAG "--demangle-cpp")
|
||||||
|
endif (NOT CPPFILT_BIN STREQUAL "")
|
||||||
|
|
||||||
|
# enable no-external flag for lcov, if available.
|
||||||
|
if (GENINFO_BIN AND NOT DEFINED GENINFO_EXTERN_FLAG)
|
||||||
|
set(FLAG "")
|
||||||
|
execute_process(COMMAND ${GENINFO_BIN} --help OUTPUT_VARIABLE GENINFO_HELP)
|
||||||
|
string(REGEX MATCH "external" GENINFO_RES "${GENINFO_HELP}")
|
||||||
|
if (GENINFO_RES)
|
||||||
|
set(FLAG "--no-external")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(GENINFO_EXTERN_FLAG "${FLAG}"
|
||||||
|
CACHE STRING "Geninfo flag to exclude system sources.")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# If Lcov was not found, exit module now.
|
||||||
|
if (NOT LCOV_FOUND)
|
||||||
|
return()
|
||||||
|
endif (NOT LCOV_FOUND)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Create directories to be used.
|
||||||
|
file(MAKE_DIRECTORY ${LCOV_DATA_PATH_INIT})
|
||||||
|
file(MAKE_DIRECTORY ${LCOV_DATA_PATH_CAPTURE})
|
||||||
|
|
||||||
|
set(LCOV_REMOVE_PATTERNS "")
|
||||||
|
|
||||||
|
# This function will merge lcov files to a single target file. Additional lcov
|
||||||
|
# flags may be set with setting LCOV_EXTRA_FLAGS before calling this function.
|
||||||
|
function (lcov_merge_files OUTFILE ...)
|
||||||
|
# Remove ${OUTFILE} from ${ARGV} and generate lcov parameters with files.
|
||||||
|
list(REMOVE_AT ARGV 0)
|
||||||
|
|
||||||
|
# Generate merged file.
|
||||||
|
string(REPLACE "${CMAKE_BINARY_DIR}/" "" FILE_REL "${OUTFILE}")
|
||||||
|
add_custom_command(OUTPUT "${OUTFILE}.raw"
|
||||||
|
COMMAND cat ${ARGV} > ${OUTFILE}.raw
|
||||||
|
DEPENDS ${ARGV}
|
||||||
|
COMMENT "Generating ${FILE_REL}"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT "${OUTFILE}"
|
||||||
|
COMMAND ${LCOV_BIN} --quiet -a ${OUTFILE}.raw --output-file ${OUTFILE}
|
||||||
|
--base-directory ${PROJECT_SOURCE_DIR} ${LCOV_EXTRA_FLAGS}
|
||||||
|
COMMAND ${LCOV_BIN} --quiet -r ${OUTFILE} ${LCOV_REMOVE_PATTERNS}
|
||||||
|
--output-file ${OUTFILE} ${LCOV_EXTRA_FLAGS}
|
||||||
|
DEPENDS ${OUTFILE}.raw
|
||||||
|
COMMENT "Post-processing ${FILE_REL}"
|
||||||
|
)
|
||||||
|
endfunction ()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Add a new global target to generate initial coverage reports for all targets.
|
||||||
|
# This target will be used to generate the global initial info file, which is
|
||||||
|
# used to gather even empty report data.
|
||||||
|
if (NOT TARGET lcov-capture-init)
|
||||||
|
add_custom_target(lcov-capture-init)
|
||||||
|
set(LCOV_CAPTURE_INIT_FILES "" CACHE INTERNAL "")
|
||||||
|
endif (NOT TARGET lcov-capture-init)
|
||||||
|
|
||||||
|
|
||||||
|
# This function will add initial capture of coverage data for target <TNAME>,
|
||||||
|
# which is needed to get also data for objects, which were not loaded at
|
||||||
|
# execution time. It will call geninfo for every source file of <TNAME> once and
|
||||||
|
# store the info file in the same directory.
|
||||||
|
function (lcov_capture_initial_tgt TNAME)
|
||||||
|
# We don't have to check, if the target has support for coverage, thus this
|
||||||
|
# will be checked by add_coverage_target in Findcoverage.cmake. Instead we
|
||||||
|
# have to determine which gcov binary to use.
|
||||||
|
get_target_property(TSOURCES ${TNAME} SOURCES)
|
||||||
|
set(SOURCES "")
|
||||||
|
set(TCOMPILER "")
|
||||||
|
foreach (FILE ${TSOURCES})
|
||||||
|
codecov_path_of_source(${FILE} FILE)
|
||||||
|
if (NOT "${FILE}" STREQUAL "")
|
||||||
|
codecov_lang_of_source(${FILE} LANG)
|
||||||
|
if (NOT "${LANG}" STREQUAL "")
|
||||||
|
list(APPEND SOURCES "${FILE}")
|
||||||
|
set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID})
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
# If no gcov binary was found, coverage data can't be evaluated.
|
||||||
|
if (NOT GCOV_${TCOMPILER}_BIN)
|
||||||
|
message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.")
|
||||||
|
return()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}")
|
||||||
|
set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}")
|
||||||
|
|
||||||
|
|
||||||
|
set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)
|
||||||
|
set(GENINFO_FILES "")
|
||||||
|
foreach(FILE ${SOURCES})
|
||||||
|
# generate empty coverage files
|
||||||
|
set(OUTFILE "${TDIR}/${FILE}.info.init")
|
||||||
|
list(APPEND GENINFO_FILES ${OUTFILE})
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${OUTFILE} COMMAND ${GCOV_ENV} ${GENINFO_BIN}
|
||||||
|
--quiet --base-directory ${PROJECT_SOURCE_DIR} --initial
|
||||||
|
--gcov-tool ${GCOV_BIN} --output-filename ${OUTFILE}
|
||||||
|
${GENINFO_EXTERN_FLAG} ${TDIR}/${FILE}.gcno
|
||||||
|
DEPENDS ${TNAME}
|
||||||
|
COMMENT "Capturing initial coverage data for ${FILE}"
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Concatenate all files generated by geninfo to a single file per target.
|
||||||
|
set(OUTFILE "${LCOV_DATA_PATH_INIT}/${TNAME}.info")
|
||||||
|
set(LCOV_EXTRA_FLAGS "--initial")
|
||||||
|
lcov_merge_files("${OUTFILE}" ${GENINFO_FILES})
|
||||||
|
add_custom_target(${TNAME}-capture-init ALL DEPENDS ${OUTFILE})
|
||||||
|
|
||||||
|
# add geninfo file generation to global lcov-geninfo target
|
||||||
|
add_dependencies(lcov-capture-init ${TNAME}-capture-init)
|
||||||
|
set(LCOV_CAPTURE_INIT_FILES "${LCOV_CAPTURE_INIT_FILES}"
|
||||||
|
"${OUTFILE}" CACHE INTERNAL ""
|
||||||
|
)
|
||||||
|
endfunction (lcov_capture_initial_tgt)
|
||||||
|
|
||||||
|
|
||||||
|
# This function will generate the global info file for all targets. It has to be
|
||||||
|
# called after all other CMake functions in the root CMakeLists.txt file, to get
|
||||||
|
# a full list of all targets that generate coverage data.
|
||||||
|
function (lcov_capture_initial)
|
||||||
|
# Skip this function (and do not create the following targets), if there are
|
||||||
|
# no input files.
|
||||||
|
if ("${LCOV_CAPTURE_INIT_FILES}" STREQUAL "")
|
||||||
|
return()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Add a new target to merge the files of all targets.
|
||||||
|
set(OUTFILE "${LCOV_DATA_PATH_INIT}/all_targets.info")
|
||||||
|
lcov_merge_files("${OUTFILE}" ${LCOV_CAPTURE_INIT_FILES})
|
||||||
|
add_custom_target(lcov-geninfo-init ALL DEPENDS ${OUTFILE}
|
||||||
|
lcov-capture-init
|
||||||
|
)
|
||||||
|
endfunction (lcov_capture_initial)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Add a new global target to generate coverage reports for all targets. This
|
||||||
|
# target will be used to generate the global info file.
|
||||||
|
if (NOT TARGET lcov-capture)
|
||||||
|
add_custom_target(lcov-capture)
|
||||||
|
set(LCOV_CAPTURE_FILES "" CACHE INTERNAL "")
|
||||||
|
endif (NOT TARGET lcov-capture)
|
||||||
|
|
||||||
|
|
||||||
|
# This function will add capture of coverage data for target <TNAME>, which is
|
||||||
|
# needed to get also data for objects, which were not loaded at execution time.
|
||||||
|
# It will call geninfo for every source file of <TNAME> once and store the info
|
||||||
|
# file in the same directory.
|
||||||
|
function (lcov_capture_tgt TNAME)
|
||||||
|
# We don't have to check, if the target has support for coverage, thus this
|
||||||
|
# will be checked by add_coverage_target in Findcoverage.cmake. Instead we
|
||||||
|
# have to determine which gcov binary to use.
|
||||||
|
get_target_property(TSOURCES ${TNAME} SOURCES)
|
||||||
|
set(SOURCES "")
|
||||||
|
set(TCOMPILER "")
|
||||||
|
foreach (FILE ${TSOURCES})
|
||||||
|
codecov_path_of_source(${FILE} FILE)
|
||||||
|
if (NOT "${FILE}" STREQUAL "")
|
||||||
|
codecov_lang_of_source(${FILE} LANG)
|
||||||
|
if (NOT "${LANG}" STREQUAL "")
|
||||||
|
list(APPEND SOURCES "${FILE}")
|
||||||
|
set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID})
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
# If no gcov binary was found, coverage data can't be evaluated.
|
||||||
|
if (NOT GCOV_${TCOMPILER}_BIN)
|
||||||
|
message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.")
|
||||||
|
return()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}")
|
||||||
|
set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}")
|
||||||
|
|
||||||
|
|
||||||
|
set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)
|
||||||
|
set(GENINFO_FILES "")
|
||||||
|
foreach(FILE ${SOURCES})
|
||||||
|
# Generate coverage files. If no .gcda file was generated during
|
||||||
|
# execution, the empty coverage file will be used instead.
|
||||||
|
set(OUTFILE "${TDIR}/${FILE}.info")
|
||||||
|
list(APPEND GENINFO_FILES ${OUTFILE})
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${OUTFILE}
|
||||||
|
COMMAND test -f "${TDIR}/${FILE}.gcda"
|
||||||
|
&& ${GCOV_ENV} ${GENINFO_BIN} --quiet --base-directory
|
||||||
|
${PROJECT_SOURCE_DIR} --gcov-tool ${GCOV_BIN}
|
||||||
|
--output-filename ${OUTFILE} ${GENINFO_EXTERN_FLAG}
|
||||||
|
${TDIR}/${FILE}.gcda
|
||||||
|
|| cp ${OUTFILE}.init ${OUTFILE}
|
||||||
|
DEPENDS ${TNAME} ${TNAME}-capture-init
|
||||||
|
COMMENT "Capturing coverage data for ${FILE}"
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Concatenate all files generated by geninfo to a single file per target.
|
||||||
|
set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/${TNAME}.info")
|
||||||
|
lcov_merge_files("${OUTFILE}" ${GENINFO_FILES})
|
||||||
|
add_custom_target(${TNAME}-geninfo DEPENDS ${OUTFILE})
|
||||||
|
|
||||||
|
# add geninfo file generation to global lcov-capture target
|
||||||
|
add_dependencies(lcov-capture ${TNAME}-geninfo)
|
||||||
|
set(LCOV_CAPTURE_FILES "${LCOV_CAPTURE_FILES}" "${OUTFILE}" CACHE INTERNAL
|
||||||
|
""
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add target for generating html output for this target only.
|
||||||
|
file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/${TNAME})
|
||||||
|
add_custom_target(${TNAME}-genhtml
|
||||||
|
COMMAND ${GENHTML_BIN} --quiet --sort --prefix ${PROJECT_SOURCE_DIR}
|
||||||
|
--baseline-file ${LCOV_DATA_PATH_INIT}/${TNAME}.info
|
||||||
|
--output-directory ${LCOV_HTML_PATH}/${TNAME}
|
||||||
|
--title "${CMAKE_PROJECT_NAME} - target ${TNAME}"
|
||||||
|
${GENHTML_CPPFILT_FLAG} ${OUTFILE}
|
||||||
|
DEPENDS ${TNAME}-geninfo ${TNAME}-capture-init
|
||||||
|
)
|
||||||
|
endfunction (lcov_capture_tgt)
|
||||||
|
|
||||||
|
|
||||||
|
# This function will generate the global info file for all targets. It has to be
|
||||||
|
# called after all other CMake functions in the root CMakeLists.txt file, to get
|
||||||
|
# a full list of all targets that generate coverage data.
|
||||||
|
function (lcov_capture)
|
||||||
|
# Skip this function (and do not create the following targets), if there are
|
||||||
|
# no input files.
|
||||||
|
if ("${LCOV_CAPTURE_FILES}" STREQUAL "")
|
||||||
|
return()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Add a new target to merge the files of all targets.
|
||||||
|
set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/all_targets.info")
|
||||||
|
lcov_merge_files("${OUTFILE}" ${LCOV_CAPTURE_FILES})
|
||||||
|
add_custom_target(lcov-geninfo DEPENDS ${OUTFILE} lcov-capture)
|
||||||
|
|
||||||
|
# Add a new global target for all lcov targets. This target could be used to
|
||||||
|
# generate the lcov html output for the whole project instead of calling
|
||||||
|
# <TARGET>-geninfo and <TARGET>-genhtml for each target. It will also be
|
||||||
|
# used to generate a html site for all project data together instead of one
|
||||||
|
# for each target.
|
||||||
|
if (NOT TARGET lcov)
|
||||||
|
file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/all_targets)
|
||||||
|
add_custom_target(lcov
|
||||||
|
COMMAND ${GENHTML_BIN} --quiet --sort
|
||||||
|
--baseline-file ${LCOV_DATA_PATH_INIT}/all_targets.info
|
||||||
|
--output-directory ${LCOV_HTML_PATH}/all_targets
|
||||||
|
--title "${CMAKE_PROJECT_NAME}" --prefix "${PROJECT_SOURCE_DIR}"
|
||||||
|
${GENHTML_CPPFILT_FLAG} ${OUTFILE}
|
||||||
|
DEPENDS lcov-geninfo-init lcov-geninfo
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
endfunction (lcov_capture)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Add a new global target to generate the lcov html report for the whole project
|
||||||
|
# instead of calling <TARGET>-genhtml for each target (to create an own report
|
||||||
|
# for each target). Instead of the lcov target it does not require geninfo for
|
||||||
|
# all targets, so you have to call <TARGET>-geninfo to generate the info files
|
||||||
|
# the targets you'd like to have in your report or lcov-geninfo for generating
|
||||||
|
# info files for all targets before calling lcov-genhtml.
|
||||||
|
file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/selected_targets)
|
||||||
|
if (NOT TARGET lcov-genhtml)
|
||||||
|
add_custom_target(lcov-genhtml
|
||||||
|
COMMAND ${GENHTML_BIN}
|
||||||
|
--quiet
|
||||||
|
--output-directory ${LCOV_HTML_PATH}/selected_targets
|
||||||
|
--title \"${CMAKE_PROJECT_NAME} - targets `find
|
||||||
|
${LCOV_DATA_PATH_CAPTURE} -name \"*.info\" ! -name
|
||||||
|
\"all_targets.info\" -exec basename {} .info \\\;`\"
|
||||||
|
--prefix ${PROJECT_SOURCE_DIR}
|
||||||
|
--sort
|
||||||
|
${GENHTML_CPPFILT_FLAG}
|
||||||
|
`find ${LCOV_DATA_PATH_CAPTURE} -name \"*.info\" ! -name
|
||||||
|
\"all_targets.info\"`
|
||||||
|
)
|
||||||
|
endif (NOT TARGET lcov-genhtml)
|
258
CMake/Findcodecov.cmake
Normal file
258
CMake/Findcodecov.cmake
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
# This file is part of CMake-codecov.
|
||||||
|
#
|
||||||
|
# Copyright (c)
|
||||||
|
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
|
||||||
|
#
|
||||||
|
# See the LICENSE file in the package base directory for details
|
||||||
|
#
|
||||||
|
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# Add an option to choose, if coverage should be enabled or not. If enabled
|
||||||
|
# marked targets will be build with coverage support and appropriate targets
|
||||||
|
# will be added. If disabled coverage will be ignored for *ALL* targets.
|
||||||
|
option(ENABLE_COVERAGE "Enable coverage build." OFF)
|
||||||
|
|
||||||
|
set(COVERAGE_FLAG_CANDIDATES
|
||||||
|
# gcc and clang
|
||||||
|
"-O0 -g -fprofile-arcs -ftest-coverage"
|
||||||
|
|
||||||
|
# gcc and clang fallback
|
||||||
|
"-O0 -g --coverage"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Add coverage support for target ${TNAME} and register target for coverage
|
||||||
|
# evaluation. If coverage is disabled or not supported, this function will
|
||||||
|
# simply do nothing.
|
||||||
|
#
|
||||||
|
# Note: This function is only a wrapper to define this function always, even if
|
||||||
|
# coverage is not supported by the compiler or disabled. This function must
|
||||||
|
# be defined here, because the module will be exited, if there is no coverage
|
||||||
|
# support by the compiler or it is disabled by the user.
|
||||||
|
function (add_coverage TNAME)
|
||||||
|
# only add coverage for target, if coverage is support and enabled.
|
||||||
|
if (ENABLE_COVERAGE)
|
||||||
|
foreach (TNAME ${ARGV})
|
||||||
|
add_coverage_target(${TNAME})
|
||||||
|
endforeach ()
|
||||||
|
endif ()
|
||||||
|
endfunction (add_coverage)
|
||||||
|
|
||||||
|
|
||||||
|
# Add global target to gather coverage information after all targets have been
|
||||||
|
# added. Other evaluation functions could be added here, after checks for the
|
||||||
|
# specific module have been passed.
|
||||||
|
#
|
||||||
|
# Note: This function is only a wrapper to define this function always, even if
|
||||||
|
# coverage is not supported by the compiler or disabled. This function must
|
||||||
|
# be defined here, because the module will be exited, if there is no coverage
|
||||||
|
# support by the compiler or it is disabled by the user.
|
||||||
|
function (coverage_evaluate)
|
||||||
|
# add lcov evaluation
|
||||||
|
if (LCOV_FOUND)
|
||||||
|
lcov_capture_initial()
|
||||||
|
lcov_capture()
|
||||||
|
endif (LCOV_FOUND)
|
||||||
|
endfunction ()
|
||||||
|
|
||||||
|
|
||||||
|
# Exit this module, if coverage is disabled. add_coverage is defined before this
|
||||||
|
# return, so this module can be exited now safely without breaking any build-
|
||||||
|
# scripts.
|
||||||
|
if (NOT ENABLE_COVERAGE)
|
||||||
|
return()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Find the reuired flags foreach language.
|
||||||
|
set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
|
||||||
|
set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY})
|
||||||
|
|
||||||
|
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||||
|
foreach (LANG ${ENABLED_LANGUAGES})
|
||||||
|
# Coverage flags are not dependend on language, but the used compiler. So
|
||||||
|
# instead of searching flags foreach language, search flags foreach compiler
|
||||||
|
# used.
|
||||||
|
set(COMPILER ${CMAKE_${LANG}_COMPILER_ID})
|
||||||
|
if (NOT COVERAGE_${COMPILER}_FLAGS)
|
||||||
|
foreach (FLAG ${COVERAGE_FLAG_CANDIDATES})
|
||||||
|
if(NOT CMAKE_REQUIRED_QUIET)
|
||||||
|
message(STATUS "Try ${COMPILER} code coverage flag = [${FLAG}]")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "${FLAG}")
|
||||||
|
unset(COVERAGE_FLAG_DETECTED CACHE)
|
||||||
|
|
||||||
|
if (${LANG} STREQUAL "C")
|
||||||
|
include(CheckCCompilerFlag)
|
||||||
|
check_c_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED)
|
||||||
|
|
||||||
|
elseif (${LANG} STREQUAL "CXX")
|
||||||
|
include(CheckCXXCompilerFlag)
|
||||||
|
check_cxx_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED)
|
||||||
|
|
||||||
|
elseif (${LANG} STREQUAL "Fortran")
|
||||||
|
# CheckFortranCompilerFlag was introduced in CMake 3.x. To be
|
||||||
|
# compatible with older Cmake versions, we will check if this
|
||||||
|
# module is present before we use it. Otherwise we will define
|
||||||
|
# Fortran coverage support as not available.
|
||||||
|
include(CheckFortranCompilerFlag OPTIONAL
|
||||||
|
RESULT_VARIABLE INCLUDED)
|
||||||
|
if (INCLUDED)
|
||||||
|
check_fortran_compiler_flag("${FLAG}"
|
||||||
|
COVERAGE_FLAG_DETECTED)
|
||||||
|
elseif (NOT CMAKE_REQUIRED_QUIET)
|
||||||
|
message("-- Performing Test COVERAGE_FLAG_DETECTED")
|
||||||
|
message("-- Performing Test COVERAGE_FLAG_DETECTED - Failed"
|
||||||
|
" (Check not supported)")
|
||||||
|
endif ()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (COVERAGE_FLAG_DETECTED)
|
||||||
|
set(COVERAGE_${COMPILER}_FLAGS "${FLAG}"
|
||||||
|
CACHE STRING "${COMPILER} flags for code coverage.")
|
||||||
|
mark_as_advanced(COVERAGE_${COMPILER}_FLAGS)
|
||||||
|
break()
|
||||||
|
else ()
|
||||||
|
message(WARNING "Code coverage is not available for ${COMPILER}"
|
||||||
|
" compiler. Targets using this compiler will be "
|
||||||
|
"compiled without it.")
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Helper function to get the language of a source file.
|
||||||
|
function (codecov_lang_of_source FILE RETURN_VAR)
|
||||||
|
get_filename_component(FILE_EXT "${FILE}" EXT)
|
||||||
|
string(TOLOWER "${FILE_EXT}" FILE_EXT)
|
||||||
|
string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT)
|
||||||
|
|
||||||
|
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||||
|
foreach (LANG ${ENABLED_LANGUAGES})
|
||||||
|
list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP)
|
||||||
|
if (NOT ${TEMP} EQUAL -1)
|
||||||
|
set(${RETURN_VAR} "${LANG}" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif ()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(${RETURN_VAR} "" PARENT_SCOPE)
|
||||||
|
endfunction ()
|
||||||
|
|
||||||
|
|
||||||
|
# Helper function to get the relative path of the source file destination path.
|
||||||
|
# This path is needed by FindGcov and FindLcov cmake files to locate the
|
||||||
|
# captured data.
|
||||||
|
function (codecov_path_of_source FILE RETURN_VAR)
|
||||||
|
string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _source ${FILE})
|
||||||
|
|
||||||
|
# If expression was found, SOURCEFILE is a generator-expression for an
|
||||||
|
# object library. Currently we found no way to call this function automatic
|
||||||
|
# for the referenced target, so it must be called in the directoryso of the
|
||||||
|
# object library definition.
|
||||||
|
if (NOT "${_source}" STREQUAL "")
|
||||||
|
set(${RETURN_VAR} "" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
string(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" FILE "${FILE}")
|
||||||
|
if(IS_ABSOLUTE ${FILE})
|
||||||
|
file(RELATIVE_PATH FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# get the right path for file
|
||||||
|
string(REPLACE ".." "__" PATH "${FILE}")
|
||||||
|
|
||||||
|
set(${RETURN_VAR} "${PATH}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Add coverage support for target ${TNAME} and register target for coverage
|
||||||
|
# evaluation.
|
||||||
|
function(add_coverage_target TNAME)
|
||||||
|
# Check if all sources for target use the same compiler. If a target uses
|
||||||
|
# e.g. C and Fortran mixed and uses different compilers (e.g. clang and
|
||||||
|
# gfortran) this can trigger huge problems, because different compilers may
|
||||||
|
# use different implementations for code coverage.
|
||||||
|
get_target_property(TSOURCES ${TNAME} SOURCES)
|
||||||
|
set(TARGET_COMPILER "")
|
||||||
|
set(ADDITIONAL_FILES "")
|
||||||
|
foreach (FILE ${TSOURCES})
|
||||||
|
# If expression was found, FILE is a generator-expression for an object
|
||||||
|
# library. Object libraries will be ignored.
|
||||||
|
string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE})
|
||||||
|
if ("${_file}" STREQUAL "")
|
||||||
|
codecov_lang_of_source(${FILE} LANG)
|
||||||
|
if (LANG)
|
||||||
|
list(APPEND TARGET_COMPILER ${CMAKE_${LANG}_COMPILER_ID})
|
||||||
|
|
||||||
|
list(APPEND ADDITIONAL_FILES "${FILE}.gcno")
|
||||||
|
list(APPEND ADDITIONAL_FILES "${FILE}.gcda")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
list(REMOVE_DUPLICATES TARGET_COMPILER)
|
||||||
|
list(LENGTH TARGET_COMPILER NUM_COMPILERS)
|
||||||
|
|
||||||
|
if (NUM_COMPILERS GREATER 1)
|
||||||
|
message(WARNING "Can't use code coverage for target ${TNAME}, because "
|
||||||
|
"it will be compiled by incompatible compilers. Target will be "
|
||||||
|
"compiled without code coverage.")
|
||||||
|
return()
|
||||||
|
|
||||||
|
elseif (NUM_COMPILERS EQUAL 0)
|
||||||
|
message(WARNING "Can't use code coverage for target ${TNAME}, because "
|
||||||
|
"it uses an unknown compiler. Target will be compiled without "
|
||||||
|
"code coverage.")
|
||||||
|
return()
|
||||||
|
|
||||||
|
elseif (NOT DEFINED "COVERAGE_${TARGET_COMPILER}_FLAGS")
|
||||||
|
# A warning has been printed before, so just return if flags for this
|
||||||
|
# compiler aren't available.
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# enable coverage for target
|
||||||
|
set_property(TARGET ${TNAME} APPEND_STRING
|
||||||
|
PROPERTY COMPILE_FLAGS " ${COVERAGE_${TARGET_COMPILER}_FLAGS}")
|
||||||
|
set_property(TARGET ${TNAME} APPEND_STRING
|
||||||
|
PROPERTY LINK_FLAGS " ${COVERAGE_${TARGET_COMPILER}_FLAGS}")
|
||||||
|
|
||||||
|
|
||||||
|
# Add gcov files generated by compiler to clean target.
|
||||||
|
set(CLEAN_FILES "")
|
||||||
|
foreach (FILE ${ADDITIONAL_FILES})
|
||||||
|
codecov_path_of_source(${FILE} FILE)
|
||||||
|
list(APPEND CLEAN_FILES "CMakeFiles/${TNAME}.dir/${FILE}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
|
||||||
|
"${CLEAN_FILES}")
|
||||||
|
|
||||||
|
|
||||||
|
add_gcov_target(${TNAME})
|
||||||
|
add_lcov_target(${TNAME})
|
||||||
|
endfunction(add_coverage_target)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Include modules for parsing the collected data and output it in a readable
|
||||||
|
# format (like gcov and lcov).
|
||||||
|
find_package(Gcov)
|
||||||
|
find_package(Lcov)
|
56
CMake/llvm-cov-wrapper
Executable file
56
CMake/llvm-cov-wrapper
Executable file
@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# This file is part of CMake-codecov.
|
||||||
|
#
|
||||||
|
# Copyright (c)
|
||||||
|
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
|
||||||
|
#
|
||||||
|
# See the LICENSE file in the package base directory for details
|
||||||
|
#
|
||||||
|
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ -z "$LLVM_COV_BIN" ]
|
||||||
|
then
|
||||||
|
echo "LLVM_COV_BIN not set!" >& 2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Get LLVM version to find out.
|
||||||
|
LLVM_VERSION=$($LLVM_COV_BIN -version | grep -i "LLVM version" \
|
||||||
|
| sed "s/^\([A-Za-z ]*\)\([0-9]\).\([0-9]\).*$/\2.\3/g")
|
||||||
|
|
||||||
|
if [ "$1" = "-v" ]
|
||||||
|
then
|
||||||
|
echo "llvm-cov-wrapper $LLVM_VERSION"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ -n "$LLVM_VERSION" ]
|
||||||
|
then
|
||||||
|
MAJOR=$(echo $LLVM_VERSION | cut -d'.' -f1)
|
||||||
|
MINOR=$(echo $LLVM_VERSION | cut -d'.' -f2)
|
||||||
|
|
||||||
|
if [ $MAJOR -eq 3 ] && [ $MINOR -le 4 ]
|
||||||
|
then
|
||||||
|
if [ -f "$1" ]
|
||||||
|
then
|
||||||
|
filename=$(basename "$1")
|
||||||
|
extension="${filename##*.}"
|
||||||
|
|
||||||
|
case "$extension" in
|
||||||
|
"gcno") exec $LLVM_COV_BIN --gcno="$1" ;;
|
||||||
|
"gcda") exec $LLVM_COV_BIN --gcda="$1" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $MAJOR -eq 3 ] && [ $MINOR -le 5 ]
|
||||||
|
then
|
||||||
|
exec $LLVM_COV_BIN $@
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec $LLVM_COV_BIN gcov $@
|
@ -4,6 +4,7 @@ project(CatchSelfTest)
|
|||||||
|
|
||||||
option(USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
|
option(USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
|
||||||
option(BUILD_EXAMPLES "Build documentation examples" OFF)
|
option(BUILD_EXAMPLES "Build documentation examples" OFF)
|
||||||
|
option(ENABLE_COVERAGE "Generate coverage for codecov.io" OFF)
|
||||||
|
|
||||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
@ -280,7 +281,6 @@ set(HEADERS
|
|||||||
SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
|
SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
|
||||||
SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
|
SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
|
||||||
|
|
||||||
# configure the executable
|
|
||||||
|
|
||||||
# Projects consuming Catch via ExternalProject_Add might want to use install step
|
# Projects consuming Catch via ExternalProject_Add might want to use install step
|
||||||
# without building all of our selftests.
|
# without building all of our selftests.
|
||||||
@ -299,10 +299,17 @@ if (NOT NO_SELFTEST)
|
|||||||
set_property(TARGET SelfTest PROPERTY CXX_STANDARD_REQUIRED ON)
|
set_property(TARGET SelfTest PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||||
set_property(TARGET SelfTest PROPERTY CXX_EXTENSIONS OFF)
|
set_property(TARGET SelfTest PROPERTY CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
if (ENABLE_COVERAGE)
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
||||||
|
find_package(codecov)
|
||||||
|
add_coverage(SelfTest)
|
||||||
|
list(APPEND LCOV_REMOVE_PATTERNS "/usr/")
|
||||||
|
coverage_evaluate()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Add desired warnings
|
# Add desired warnings
|
||||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
|
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
|
||||||
target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code )
|
target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code -Werror )
|
||||||
endif()
|
endif()
|
||||||
# Clang specific warning go here
|
# Clang specific warning go here
|
||||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
||||||
@ -315,22 +322,30 @@ if (NOT NO_SELFTEST)
|
|||||||
|
|
||||||
|
|
||||||
# configure unit tests via CTest
|
# configure unit tests via CTest
|
||||||
enable_testing()
|
include(CTest)
|
||||||
add_test(NAME RunTests COMMAND $<TARGET_FILE:SelfTest>)
|
add_test(NAME RunTests COMMAND $<TARGET_FILE:SelfTest>)
|
||||||
|
|
||||||
add_test(NAME ListTests COMMAND $<TARGET_FILE:SelfTest> --list-tests)
|
add_test(NAME ListTests COMMAND $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
|
||||||
set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases")
|
set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases")
|
||||||
|
|
||||||
add_test(NAME ListTags COMMAND $<TARGET_FILE:SelfTest> --list-tags)
|
add_test(NAME ListTags COMMAND $<TARGET_FILE:SelfTest> --list-tags)
|
||||||
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
|
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
|
||||||
|
|
||||||
|
add_test(NAME ListReporters COMMAND $<TARGET_FILE:SelfTest> --list-reporters)
|
||||||
|
set_tests_properties(ListReporters PROPERTIES PASS_REGULAR_EXPRESSION "Available reporters:")
|
||||||
|
|
||||||
|
add_test(NAME ListTestNamesOnly COMMAND $<TARGET_FILE:SelfTest> --list-test-names-only)
|
||||||
|
set_tests_properties(ListTestNamesOnly PROPERTIES PASS_REGULAR_EXPRESSION "Regex string matcher")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
|
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
|
||||||
add_test(NAME ApprovalTests COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
|
add_test(NAME ApprovalTests COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
|
||||||
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
|
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
|
||||||
|
|
||||||
if (USE_VALGRIND)
|
if (USE_VALGRIND)
|
||||||
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
|
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
|
||||||
add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests)
|
add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
|
||||||
set_tests_properties(ValgrindListTests PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
|
set_tests_properties(ValgrindListTests PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
|
||||||
add_test(NAME ValgrindListTags COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tags)
|
add_test(NAME ValgrindListTags COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tags)
|
||||||
set_tests_properties(ValgrindListTags PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
|
set_tests_properties(ValgrindListTags PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
|
||||||
@ -343,7 +358,6 @@ if(BUILD_EXAMPLES)
|
|||||||
add_subdirectory(examples)
|
add_subdirectory(examples)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
install(DIRECTORY "single_include/" DESTINATION "include/catch")
|
install(DIRECTORY "single_include/" DESTINATION "include/catch")
|
||||||
|
|
||||||
## Provide some pkg-config integration
|
## Provide some pkg-config integration
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
![catch logo](artwork/catch2-logo-small.png)
|
![catch logo](artwork/catch2-logo-small.png)
|
||||||
|
|
||||||
[![Github Releases](https://img.shields.io/github/release/catchorg/catch2.svg)](https://github.com/catchorg/catch2/releases)
|
[![Github Releases](https://img.shields.io/github/release/catchorg/catch2.svg)](https://github.com/catchorg/catch2/releases)
|
||||||
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg)](https://travis-ci.org/catchorg/Catch2)
|
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2)
|
||||||
[![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
|
[![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
|
||||||
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/tB8z0G3kMAIZkIca)
|
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/tB8z0G3kMAIZkIca)
|
||||||
|
|
||||||
<a href="https://github.com/catchorg/Catch2/releases/download/v2.0.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
<a href="https://github.com/catchorg/Catch2/releases/download/v2.0.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||||
|
18
appveyor.yml
18
appveyor.yml
@ -27,11 +27,10 @@ matrix:
|
|||||||
|
|
||||||
init:
|
init:
|
||||||
- git config --global core.autocrlf input
|
- git config --global core.autocrlf input
|
||||||
# Set build version to git commit-hash
|
|
||||||
- ps: Update-AppveyorBuild -Version "$($env:APPVEYOR_REPO_BRANCH) - $($env:APPVEYOR_REPO_COMMIT)"
|
|
||||||
|
|
||||||
# fetch repository as zip archive
|
install:
|
||||||
shallow_clone: true
|
- ps: if (($env:CONFIGURATION) -eq "Debug" ) { python -m pip install codecov }
|
||||||
|
- ps: if (($env:CONFIGURATION) -eq "Debug" ) { .\misc\installOpenCppCoverage.ps1 }
|
||||||
|
|
||||||
# Win32 and x64 are CMake-compatible solution platform names.
|
# Win32 and x64 are CMake-compatible solution platform names.
|
||||||
# This allows us to pass %PLATFORM% to CMake -A.
|
# This allows us to pass %PLATFORM% to CMake -A.
|
||||||
@ -46,9 +45,12 @@ configuration:
|
|||||||
|
|
||||||
#Cmake will autodetect the compiler, but we set the arch
|
#Cmake will autodetect the compiler, but we set the arch
|
||||||
before_build:
|
before_build:
|
||||||
- python scripts/generateSingleHeader.py
|
|
||||||
- set CXXFLAGS=%additional_flags%
|
- set CXXFLAGS=%additional_flags%
|
||||||
- cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DBUILD_EXAMPLES=ON
|
# Indirection because appveyor doesn't handle multiline batch scripts properly
|
||||||
|
# https://stackoverflow.com/questions/37627248/how-to-split-a-command-over-multiple-lines-in-appveyor-yml/37647169#37647169
|
||||||
|
# https://help.appveyor.com/discussions/questions/3888-multi-line-cmd-or-powershell-warning-ignore
|
||||||
|
- cmd: .\misc\appveyorBuildConfigurationScript.bat
|
||||||
|
|
||||||
|
|
||||||
# build with MSBuild
|
# build with MSBuild
|
||||||
build:
|
build:
|
||||||
@ -57,5 +59,5 @@ build:
|
|||||||
verbosity: normal # MSBuild verbosity level {quiet|minimal|normal|detailed}
|
verbosity: normal # MSBuild verbosity level {quiet|minimal|normal|detailed}
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- cd Build
|
- set CTEST_OUTPUT_ON_FAILURE=1
|
||||||
- ctest -V -j 2 -C %CONFIGURATION%
|
- cmd: .\misc\appveyorTestRunScript.bat
|
||||||
|
10
codecov.yml
Normal file
10
codecov.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
codecov:
|
||||||
|
branch: master
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
ignore:
|
||||||
|
- "projects/SelfTest"
|
||||||
|
- "**/catch_reporter_tap.hpp"
|
||||||
|
- "**/catch_reporter_automake.hpp"
|
||||||
|
- "**/catch_reporter_teamcity.hpp"
|
||||||
|
- "**/external/clara.hpp"
|
@ -87,6 +87,41 @@
|
|||||||
|
|
||||||
# Older versions
|
# Older versions
|
||||||
|
|
||||||
|
## 1.11.x
|
||||||
|
|
||||||
|
### 1.11.0
|
||||||
|
|
||||||
|
#### Fixes
|
||||||
|
* The original expression in `REQUIRE_FALSE( expr )` is now reporter properly as `!( expr )` (#1051)
|
||||||
|
* Previously the parentheses were missing and `x != y` would be expanded as `!x != x`
|
||||||
|
* `Approx::Margin` is now inclusive (#952)
|
||||||
|
* Previously it was meant and documented as inclusive, but the check itself wasn't
|
||||||
|
* This means that `REQUIRE( 0.25f == Approx( 0.0f ).margin( 0.25f ) )` passes, instead of fails
|
||||||
|
* `RandomNumberGenerator::result_type` is now unsigned (#1050)
|
||||||
|
|
||||||
|
#### Improvements
|
||||||
|
* `__JETBRAINS_IDE__` macro handling is now CLion version specific (#1017)
|
||||||
|
* When CLion 2017.3 or newer is detected, `__COUNTER__` is used instead of
|
||||||
|
* TeamCity reporter now explicitly flushes output stream after each report (#1057)
|
||||||
|
* On some platforms, output from redirected streams would show up only after the tests finished running
|
||||||
|
* `ParseAndAddCatchTests` now can add test files as dependency to CMake configuration
|
||||||
|
* This means you do not have to manually rerun CMake configuration step to detect new tests
|
||||||
|
|
||||||
|
## 1.10.x
|
||||||
|
|
||||||
|
### 1.10.0
|
||||||
|
|
||||||
|
#### Fixes
|
||||||
|
* Evaluation layer has been rewritten (backported from Catch 2)
|
||||||
|
* The new layer is much simpler and fixes some issues (#981)
|
||||||
|
* Implemented workaround for VS 2017 raw string literal stringification bug (#995)
|
||||||
|
* Fixed interaction between `[!shouldfail]` and `[!mayfail]` tags and sections
|
||||||
|
* Previously sections with failing assertions would be marked as failed, not failed-but-ok
|
||||||
|
|
||||||
|
#### Improvements
|
||||||
|
* Added [libidentify](https://github.com/janwilmans/LibIdentify) support
|
||||||
|
* Added "wait-for-keypress" option
|
||||||
|
|
||||||
## 1.9.x
|
## 1.9.x
|
||||||
|
|
||||||
### 1.9.6
|
### 1.9.6
|
||||||
|
@ -295,13 +295,16 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
|
|||||||
// 2. My listener and registration:
|
// 2. My listener and registration:
|
||||||
//
|
//
|
||||||
|
|
||||||
const std::string dashed_line =
|
char const * dashed_line =
|
||||||
"--------------------------------------------------------------------------";
|
"--------------------------------------------------------------------------";
|
||||||
|
|
||||||
struct MyListener : Catch::TestEventListenerBase {
|
struct MyListener : Catch::TestEventListenerBase {
|
||||||
|
|
||||||
using TestEventListenerBase::TestEventListenerBase; // inherit constructor
|
using TestEventListenerBase::TestEventListenerBase; // inherit constructor
|
||||||
|
|
||||||
|
// Get rid of Wweak-tables
|
||||||
|
~MyListener();
|
||||||
|
|
||||||
// The whole test run starting
|
// The whole test run starting
|
||||||
virtual void testRunStarting( Catch::TestRunInfo const& testRunInfo ) override {
|
virtual void testRunStarting( Catch::TestRunInfo const& testRunInfo ) override {
|
||||||
std::cout
|
std::cout
|
||||||
@ -367,6 +370,10 @@ struct MyListener : Catch::TestEventListenerBase {
|
|||||||
|
|
||||||
CATCH_REGISTER_LISTENER( MyListener )
|
CATCH_REGISTER_LISTENER( MyListener )
|
||||||
|
|
||||||
|
// Get rid of Wweak-tables
|
||||||
|
MyListener::~MyListener() {}
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// 3. Test cases:
|
// 3. Test cases:
|
||||||
//
|
//
|
||||||
|
@ -13,8 +13,7 @@
|
|||||||
#include "catch_debugger.h"
|
#include "catch_debugger.h"
|
||||||
#include "catch_interfaces_registry_hub.h"
|
#include "catch_interfaces_registry_hub.h"
|
||||||
#include "catch_capture_matchers.h"
|
#include "catch_capture_matchers.h"
|
||||||
|
#include "catch_run_context.h"
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@ -54,87 +53,60 @@ namespace Catch {
|
|||||||
SourceLineInfo const& lineInfo,
|
SourceLineInfo const& lineInfo,
|
||||||
StringRef capturedExpression,
|
StringRef capturedExpression,
|
||||||
ResultDisposition::Flags resultDisposition )
|
ResultDisposition::Flags resultDisposition )
|
||||||
: m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }
|
: m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
|
||||||
{
|
m_resultCapture( getResultCapture() )
|
||||||
getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo );
|
{}
|
||||||
|
|
||||||
|
AssertionHandler::~AssertionHandler() {
|
||||||
|
if ( !m_completed )
|
||||||
|
m_resultCapture.handleIncomplete( m_assertionInfo );
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssertionHandler::handle( ITransientExpression const& expr ) {
|
void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
|
||||||
|
m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
|
||||||
bool negated = isFalseTest( m_assertionInfo.resultDisposition );
|
|
||||||
bool result = expr.getResult() != negated;
|
|
||||||
|
|
||||||
if(result && !getCurrentContext().getConfig()->includeSuccessfulResults())
|
|
||||||
{
|
|
||||||
getCurrentContext().getResultCapture()->assertionRun();
|
|
||||||
getCurrentContext().getResultCapture()->assertionPassed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated );
|
|
||||||
}
|
|
||||||
void AssertionHandler::handle( ResultWas::OfType resultType ) {
|
|
||||||
handle( resultType, nullptr, false );
|
|
||||||
}
|
|
||||||
void AssertionHandler::handle( ResultWas::OfType resultType, StringRef const& message ) {
|
|
||||||
AssertionResultData data( resultType, LazyExpression( false ) );
|
|
||||||
data.message = message;
|
|
||||||
handle( data, nullptr );
|
|
||||||
}
|
|
||||||
void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) {
|
|
||||||
AssertionResultData data( resultType, LazyExpression( negated ) );
|
|
||||||
handle( data, expr );
|
|
||||||
}
|
|
||||||
void AssertionHandler::handle( AssertionResultData const& resultData, ITransientExpression const* expr ) {
|
|
||||||
|
|
||||||
getResultCapture().assertionRun();
|
|
||||||
|
|
||||||
AssertionResult assertionResult{ m_assertionInfo, resultData };
|
|
||||||
assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
|
|
||||||
|
|
||||||
getResultCapture().assertionEnded( assertionResult );
|
|
||||||
|
|
||||||
if( !assertionResult.isOk() ) {
|
|
||||||
m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak();
|
|
||||||
m_shouldThrow =
|
|
||||||
getCurrentContext().getRunner()->aborting() ||
|
|
||||||
(m_assertionInfo.resultDisposition & ResultDisposition::Normal);
|
|
||||||
}
|
}
|
||||||
|
void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) {
|
||||||
|
m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AssertionHandler::allowThrows() const -> bool {
|
auto AssertionHandler::allowThrows() const -> bool {
|
||||||
return getCurrentContext().getConfig()->allowThrows();
|
return getCurrentContext().getConfig()->allowThrows();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AssertionHandler::shouldDebugBreak() const -> bool {
|
void AssertionHandler::complete() {
|
||||||
return m_shouldDebugBreak;
|
setCompleted();
|
||||||
}
|
if( m_reaction.shouldDebugBreak ) {
|
||||||
void AssertionHandler::reactWithDebugBreak() const {
|
|
||||||
if (m_shouldDebugBreak) {
|
// If you find your debugger stopping you here then go one level up on the
|
||||||
///////////////////////////////////////////////////////////////////
|
// call-stack for the code that caused it (typically a failed assertion)
|
||||||
// To inspect the state during test, you need to go one level up the callstack
|
|
||||||
// To go back to the test and change execution, jump over the reactWithoutDebugBreak() call
|
// (To go back to the test and change execution, jump over the throw, next)
|
||||||
///////////////////////////////////////////////////////////////////
|
|
||||||
CATCH_BREAK_INTO_DEBUGGER();
|
CATCH_BREAK_INTO_DEBUGGER();
|
||||||
}
|
}
|
||||||
reactWithoutDebugBreak();
|
if( m_reaction.shouldThrow )
|
||||||
}
|
|
||||||
void AssertionHandler::reactWithoutDebugBreak() const {
|
|
||||||
if( m_shouldThrow )
|
|
||||||
throw Catch::TestFailureException();
|
throw Catch::TestFailureException();
|
||||||
}
|
}
|
||||||
|
void AssertionHandler::setCompleted() {
|
||||||
void AssertionHandler::useActiveException() {
|
m_completed = true;
|
||||||
handle( ResultWas::ThrewException, Catch::translateActiveException() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssertionHandler::setExceptionGuard() {
|
void AssertionHandler::handleUnexpectedInflightException() {
|
||||||
assert( m_inExceptionGuard == false );
|
m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
|
||||||
m_inExceptionGuard = true;
|
|
||||||
}
|
}
|
||||||
void AssertionHandler::unsetExceptionGuard() {
|
|
||||||
assert( m_inExceptionGuard == true );
|
void AssertionHandler::handleExceptionThrownAsExpected() {
|
||||||
m_inExceptionGuard = false;
|
m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
|
||||||
|
}
|
||||||
|
void AssertionHandler::handleExceptionNotThrownAsExpected() {
|
||||||
|
m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssertionHandler::handleUnexpectedExceptionNotThrown() {
|
||||||
|
m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssertionHandler::handleThrowingCallSkipped() {
|
||||||
|
m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the overload that takes a string and infers the Equals matcher from it
|
// This is the overload that takes a string and infers the Equals matcher from it
|
||||||
|
@ -17,10 +17,13 @@ namespace Catch {
|
|||||||
|
|
||||||
struct TestFailureException{};
|
struct TestFailureException{};
|
||||||
struct AssertionResultData;
|
struct AssertionResultData;
|
||||||
|
struct IResultCapture;
|
||||||
|
class RunContext;
|
||||||
|
|
||||||
class LazyExpression {
|
class LazyExpression {
|
||||||
friend class AssertionHandler;
|
friend class AssertionHandler;
|
||||||
friend struct AssertionStats;
|
friend struct AssertionStats;
|
||||||
|
friend class RunContext;
|
||||||
|
|
||||||
ITransientExpression const* m_transientExpression = nullptr;
|
ITransientExpression const* m_transientExpression = nullptr;
|
||||||
bool m_isNegated;
|
bool m_isNegated;
|
||||||
@ -34,11 +37,16 @@ namespace Catch {
|
|||||||
friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
|
friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AssertionReaction {
|
||||||
|
bool shouldDebugBreak = false;
|
||||||
|
bool shouldThrow = false;
|
||||||
|
};
|
||||||
|
|
||||||
class AssertionHandler {
|
class AssertionHandler {
|
||||||
AssertionInfo m_assertionInfo;
|
AssertionInfo m_assertionInfo;
|
||||||
bool m_shouldDebugBreak = false;
|
AssertionReaction m_reaction;
|
||||||
bool m_shouldThrow = false;
|
bool m_completed = false;
|
||||||
bool m_inExceptionGuard = false;
|
IResultCapture& m_resultCapture;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AssertionHandler
|
AssertionHandler
|
||||||
@ -54,24 +62,25 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle( ITransientExpression const& expr );
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void handle( ExprLhs<T> const& expr ) {
|
void handleExpr( ExprLhs<T> const& expr ) {
|
||||||
handle( expr.makeUnaryExpr() );
|
handleExpr( expr.makeUnaryExpr() );
|
||||||
}
|
}
|
||||||
void handle( ResultWas::OfType resultType );
|
void handleExpr( ITransientExpression const& expr );
|
||||||
void handle( ResultWas::OfType resultType, StringRef const& message );
|
|
||||||
void handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated );
|
|
||||||
void handle( AssertionResultData const& resultData, ITransientExpression const* expr );
|
|
||||||
|
|
||||||
auto shouldDebugBreak() const -> bool;
|
void handleMessage(ResultWas::OfType resultType, StringRef const& message);
|
||||||
|
|
||||||
|
void handleExceptionThrownAsExpected();
|
||||||
|
void handleUnexpectedExceptionNotThrown();
|
||||||
|
void handleExceptionNotThrownAsExpected();
|
||||||
|
void handleThrowingCallSkipped();
|
||||||
|
void handleUnexpectedInflightException();
|
||||||
|
|
||||||
|
void complete();
|
||||||
|
void setCompleted();
|
||||||
|
|
||||||
|
// query
|
||||||
auto allowThrows() const -> bool;
|
auto allowThrows() const -> bool;
|
||||||
void reactWithDebugBreak() const;
|
|
||||||
void reactWithoutDebugBreak() const;
|
|
||||||
void useActiveException();
|
|
||||||
void setExceptionGuard();
|
|
||||||
void unsetExceptionGuard();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString );
|
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString );
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
#include "catch_assertionhandler.h"
|
#include "catch_assertionhandler.h"
|
||||||
#include "catch_message.h"
|
#include "catch_message.h"
|
||||||
#include "catch_interfaces_capture.h"
|
#include "catch_interfaces_capture.h"
|
||||||
#include "catch_debugger.h"
|
|
||||||
|
|
||||||
#if !defined(CATCH_CONFIG_DISABLE)
|
#if !defined(CATCH_CONFIG_DISABLE)
|
||||||
|
|
||||||
@ -22,48 +21,33 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_FAST_COMPILE)
|
#if defined(CATCH_CONFIG_FAST_COMPILE)
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// We can speedup compilation significantly by breaking into debugger lower in
|
|
||||||
// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER
|
|
||||||
// macro in each assertion
|
|
||||||
#define INTERNAL_CATCH_REACT( handler ) \
|
|
||||||
handler.reactWithDebugBreak();
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
|
// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
|
||||||
// macros.
|
// macros.
|
||||||
// This can potentially cause false negative, if the test code catches
|
#define INTERNAL_CATCH_TRY
|
||||||
// the exception before it propagates back up to the runner.
|
#define INTERNAL_CATCH_CATCH( capturer )
|
||||||
#define INTERNAL_CATCH_TRY( capturer ) capturer.setExceptionGuard();
|
|
||||||
#define INTERNAL_CATCH_CATCH( capturer ) capturer.unsetExceptionGuard();
|
|
||||||
|
|
||||||
#else // CATCH_CONFIG_FAST_COMPILE
|
#else // CATCH_CONFIG_FAST_COMPILE
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
#define INTERNAL_CATCH_TRY try
|
||||||
// In the event of a failure works out if the debugger needs to be invoked
|
#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
|
||||||
// and/or an exception thrown and takes appropriate action.
|
|
||||||
// This needs to be done as a macro so the debugger will stop in the user
|
|
||||||
// source code rather than in Catch library code
|
|
||||||
#define INTERNAL_CATCH_REACT( handler ) \
|
|
||||||
if( handler.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
|
|
||||||
handler.reactWithoutDebugBreak();
|
|
||||||
|
|
||||||
#define INTERNAL_CATCH_TRY( capturer ) try
|
|
||||||
#define INTERNAL_CATCH_CATCH( capturer ) catch(...) { capturer.useActiveException(); }
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define INTERNAL_CATCH_REACT( handler ) handler.complete();
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
|
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
|
||||||
do { \
|
do { \
|
||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
|
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
|
||||||
INTERNAL_CATCH_TRY( catchAssertionHandler ) { \
|
INTERNAL_CATCH_TRY { \
|
||||||
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
||||||
catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \
|
catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
|
||||||
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
|
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( Catch::isTrue(false) && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
|
} while( (void)0, false && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression 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 &&.
|
// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -82,13 +66,13 @@
|
|||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
|
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
|
||||||
try { \
|
try { \
|
||||||
static_cast<void>(__VA_ARGS__); \
|
static_cast<void>(__VA_ARGS__); \
|
||||||
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
|
catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
|
||||||
} \
|
} \
|
||||||
catch( ... ) { \
|
catch( ... ) { \
|
||||||
catchAssertionHandler.useActiveException(); \
|
catchAssertionHandler.handleUnexpectedInflightException(); \
|
||||||
} \
|
} \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( Catch::alwaysFalse() )
|
} while( false )
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
|
#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
|
||||||
@ -97,15 +81,15 @@
|
|||||||
if( catchAssertionHandler.allowThrows() ) \
|
if( catchAssertionHandler.allowThrows() ) \
|
||||||
try { \
|
try { \
|
||||||
static_cast<void>(__VA_ARGS__); \
|
static_cast<void>(__VA_ARGS__); \
|
||||||
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
|
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
|
||||||
} \
|
} \
|
||||||
catch( ... ) { \
|
catch( ... ) { \
|
||||||
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
|
catchAssertionHandler.handleExceptionThrownAsExpected(); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
|
catchAssertionHandler.handleThrowingCallSkipped(); \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( Catch::alwaysFalse() )
|
} while( false )
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
|
#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
|
||||||
@ -114,31 +98,31 @@
|
|||||||
if( catchAssertionHandler.allowThrows() ) \
|
if( catchAssertionHandler.allowThrows() ) \
|
||||||
try { \
|
try { \
|
||||||
static_cast<void>(expr); \
|
static_cast<void>(expr); \
|
||||||
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
|
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
|
||||||
} \
|
} \
|
||||||
catch( exceptionType const& ) { \
|
catch( exceptionType const& ) { \
|
||||||
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
|
catchAssertionHandler.handleExceptionThrownAsExpected(); \
|
||||||
} \
|
} \
|
||||||
catch( ... ) { \
|
catch( ... ) { \
|
||||||
catchAssertionHandler.useActiveException(); \
|
catchAssertionHandler.handleUnexpectedInflightException(); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
|
catchAssertionHandler.handleThrowingCallSkipped(); \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( Catch::alwaysFalse() )
|
} while( false )
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
|
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
|
||||||
do { \
|
do { \
|
||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
|
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
|
||||||
catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
|
catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( Catch::alwaysFalse() )
|
} while( false )
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_INFO( macroName, log ) \
|
#define INTERNAL_CATCH_INFO( macroName, log ) \
|
||||||
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
|
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Although this is matcher-based, it can be used with just a string
|
// Although this is matcher-based, it can be used with just a string
|
||||||
@ -148,15 +132,15 @@
|
|||||||
if( catchAssertionHandler.allowThrows() ) \
|
if( catchAssertionHandler.allowThrows() ) \
|
||||||
try { \
|
try { \
|
||||||
static_cast<void>(__VA_ARGS__); \
|
static_cast<void>(__VA_ARGS__); \
|
||||||
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
|
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
|
||||||
} \
|
} \
|
||||||
catch( ... ) { \
|
catch( ... ) { \
|
||||||
handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \
|
Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
|
catchAssertionHandler.handleThrowingCallSkipped(); \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( Catch::alwaysFalse() )
|
} while( false )
|
||||||
|
|
||||||
#endif // CATCH_CONFIG_DISABLE
|
#endif // CATCH_CONFIG_DISABLE
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ namespace Catch {
|
|||||||
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) {
|
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) {
|
||||||
std::string exceptionMessage = Catch::translateActiveException();
|
std::string exceptionMessage = Catch::translateActiveException();
|
||||||
MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
|
MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
|
||||||
handler.handle( expr );
|
handler.handleExpr( expr );
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
@ -21,18 +21,14 @@ namespace Catch {
|
|||||||
ArgT const& m_arg;
|
ArgT const& m_arg;
|
||||||
MatcherT m_matcher;
|
MatcherT m_matcher;
|
||||||
StringRef m_matcherString;
|
StringRef m_matcherString;
|
||||||
bool m_result;
|
|
||||||
public:
|
public:
|
||||||
MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString )
|
MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString )
|
||||||
: m_arg( arg ),
|
: ITransientExpression{ true, matcher.match( arg ) },
|
||||||
|
m_arg( arg ),
|
||||||
m_matcher( matcher ),
|
m_matcher( matcher ),
|
||||||
m_matcherString( matcherString ),
|
m_matcherString( matcherString )
|
||||||
m_result( matcher.match( arg ) )
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
auto isBinaryExpression() const -> bool override { return true; }
|
|
||||||
auto getResult() const -> bool override { return m_result; }
|
|
||||||
|
|
||||||
void streamReconstructedExpression( std::ostream &os ) const override {
|
void streamReconstructedExpression( std::ostream &os ) const override {
|
||||||
auto matcherAsString = m_matcher.toString();
|
auto matcherAsString = m_matcher.toString();
|
||||||
os << Catch::Detail::stringify( m_arg ) << ' ';
|
os << Catch::Detail::stringify( m_arg ) << ' ';
|
||||||
@ -59,11 +55,11 @@ namespace Catch {
|
|||||||
#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
|
#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
|
||||||
do { \
|
do { \
|
||||||
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
|
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
|
||||||
INTERNAL_CATCH_TRY( catchAssertionHandler ) { \
|
INTERNAL_CATCH_TRY { \
|
||||||
catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \
|
catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \
|
||||||
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
|
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( Catch::alwaysFalse() )
|
} while( false )
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -73,17 +69,17 @@ namespace Catch {
|
|||||||
if( catchAssertionHandler.allowThrows() ) \
|
if( catchAssertionHandler.allowThrows() ) \
|
||||||
try { \
|
try { \
|
||||||
static_cast<void>(__VA_ARGS__ ); \
|
static_cast<void>(__VA_ARGS__ ); \
|
||||||
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
|
catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
|
||||||
} \
|
} \
|
||||||
catch( exceptionType const& ex ) { \
|
catch( exceptionType const& ex ) { \
|
||||||
catchAssertionHandler.handle( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \
|
catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \
|
||||||
} \
|
} \
|
||||||
catch( ... ) { \
|
catch( ... ) { \
|
||||||
catchAssertionHandler.useActiveException(); \
|
catchAssertionHandler.handleUnexpectedInflightException(); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
|
catchAssertionHandler.handleThrowingCallSkipped(); \
|
||||||
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
|
||||||
} while( Catch::alwaysFalse() )
|
} while( false )
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED
|
||||||
|
@ -34,9 +34,6 @@ namespace Catch {
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool alwaysTrue() { return true; }
|
|
||||||
bool alwaysFalse() { return false; }
|
|
||||||
|
|
||||||
std::string StreamEndStop::operator+() const {
|
std::string StreamEndStop::operator+() const {
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
@ -61,12 +61,6 @@ namespace Catch {
|
|||||||
|
|
||||||
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
|
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
|
||||||
|
|
||||||
// This is just here to avoid compiler warnings with macro constants and boolean literals
|
|
||||||
inline bool isTrue( bool value ){ return value; }
|
|
||||||
|
|
||||||
bool alwaysTrue();
|
|
||||||
bool alwaysFalse();
|
|
||||||
|
|
||||||
// Use this in variadic streaming macros to allow
|
// Use this in variadic streaming macros to allow
|
||||||
// >> +StreamEndStop
|
// >> +StreamEndStop
|
||||||
// as well as
|
// as well as
|
||||||
|
@ -40,7 +40,7 @@ namespace Catch {
|
|||||||
#ifdef CATCH_TRAP
|
#ifdef CATCH_TRAP
|
||||||
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
|
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
|
||||||
#else
|
#else
|
||||||
#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
|
#define CATCH_BREAK_INTO_DEBUGGER() (void)0, 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
||||||
|
@ -24,27 +24,32 @@
|
|||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
struct ITransientExpression {
|
struct ITransientExpression {
|
||||||
virtual auto isBinaryExpression() const -> bool = 0;
|
auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
|
||||||
virtual auto getResult() const -> bool = 0;
|
auto getResult() const -> bool { return m_result; }
|
||||||
virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
|
virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
|
||||||
|
|
||||||
// We don't actually need a virtual destructore, but many static analysers
|
ITransientExpression( bool isBinaryExpression, bool result )
|
||||||
|
: m_isBinaryExpression( isBinaryExpression ),
|
||||||
|
m_result( result )
|
||||||
|
{}
|
||||||
|
|
||||||
|
// We don't actually need a virtual destructor, but many static analysers
|
||||||
// complain if it's not here :-(
|
// complain if it's not here :-(
|
||||||
virtual ~ITransientExpression();
|
virtual ~ITransientExpression();
|
||||||
|
|
||||||
|
bool m_isBinaryExpression;
|
||||||
|
bool m_result;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
|
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
|
||||||
|
|
||||||
template<typename LhsT, typename RhsT>
|
template<typename LhsT, typename RhsT>
|
||||||
class BinaryExpr : public ITransientExpression {
|
class BinaryExpr : public ITransientExpression {
|
||||||
bool m_result;
|
|
||||||
LhsT m_lhs;
|
LhsT m_lhs;
|
||||||
StringRef m_op;
|
StringRef m_op;
|
||||||
RhsT m_rhs;
|
RhsT m_rhs;
|
||||||
|
|
||||||
auto isBinaryExpression() const -> bool override { return true; }
|
|
||||||
auto getResult() const -> bool override { return m_result; }
|
|
||||||
|
|
||||||
void streamReconstructedExpression( std::ostream &os ) const override {
|
void streamReconstructedExpression( std::ostream &os ) const override {
|
||||||
formatReconstructedExpression
|
formatReconstructedExpression
|
||||||
( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
|
( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
|
||||||
@ -52,7 +57,7 @@ namespace Catch {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
|
BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
|
||||||
: m_result( comparisonResult ),
|
: ITransientExpression{ true, comparisonResult },
|
||||||
m_lhs( lhs ),
|
m_lhs( lhs ),
|
||||||
m_op( op ),
|
m_op( op ),
|
||||||
m_rhs( rhs )
|
m_rhs( rhs )
|
||||||
@ -63,15 +68,15 @@ namespace Catch {
|
|||||||
class UnaryExpr : public ITransientExpression {
|
class UnaryExpr : public ITransientExpression {
|
||||||
LhsT m_lhs;
|
LhsT m_lhs;
|
||||||
|
|
||||||
auto isBinaryExpression() const -> bool override { return false; }
|
|
||||||
auto getResult() const -> bool override { return m_lhs ? true : false; }
|
|
||||||
|
|
||||||
void streamReconstructedExpression( std::ostream &os ) const override {
|
void streamReconstructedExpression( std::ostream &os ) const override {
|
||||||
os << Catch::Detail::stringify( m_lhs );
|
os << Catch::Detail::stringify( m_lhs );
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UnaryExpr( LhsT lhs ) : m_lhs( lhs ) {}
|
explicit UnaryExpr( LhsT lhs )
|
||||||
|
: ITransientExpression{ false, lhs ? true : false },
|
||||||
|
m_lhs( lhs )
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -103,43 +108,43 @@ namespace Catch {
|
|||||||
class ExprLhs {
|
class ExprLhs {
|
||||||
LhsT m_lhs;
|
LhsT m_lhs;
|
||||||
public:
|
public:
|
||||||
ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
|
explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
|
||||||
|
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return BinaryExpr<LhsT, RhsT const&>( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs );
|
return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs };
|
||||||
}
|
}
|
||||||
auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
|
auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
|
||||||
return BinaryExpr<LhsT, bool>( m_lhs == rhs, m_lhs, "==", rhs );
|
return { m_lhs == rhs, m_lhs, "==", rhs };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return BinaryExpr<LhsT, RhsT const&>( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs );
|
return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs };
|
||||||
}
|
}
|
||||||
auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
|
auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
|
||||||
return BinaryExpr<LhsT, bool>( m_lhs != rhs, m_lhs, "!=", rhs );
|
return { m_lhs != rhs, m_lhs, "!=", rhs };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return BinaryExpr<LhsT, RhsT const&>( m_lhs > rhs, m_lhs, ">", rhs );
|
return { m_lhs > rhs, m_lhs, ">", rhs };
|
||||||
}
|
}
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return BinaryExpr<LhsT, RhsT const&>( m_lhs < rhs, m_lhs, "<", rhs );
|
return { m_lhs < rhs, m_lhs, "<", rhs };
|
||||||
}
|
}
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return BinaryExpr<LhsT, RhsT const&>( m_lhs >= rhs, m_lhs, ">=", rhs );
|
return { m_lhs >= rhs, m_lhs, ">=", rhs };
|
||||||
}
|
}
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return BinaryExpr<LhsT, RhsT const&>( m_lhs <= rhs, m_lhs, "<=", rhs );
|
return { m_lhs <= rhs, m_lhs, "<=", rhs };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
||||||
return UnaryExpr<LhsT>( m_lhs );
|
return UnaryExpr<LhsT>{ m_lhs };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -153,10 +158,11 @@ namespace Catch {
|
|||||||
struct Decomposer {
|
struct Decomposer {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {
|
auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {
|
||||||
return ExprLhs<T const&>( lhs );
|
return ExprLhs<T const&>{ lhs };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator <=( bool value ) -> ExprLhs<bool> {
|
auto operator <=( bool value ) -> ExprLhs<bool> {
|
||||||
return ExprLhs<bool>( value );
|
return ExprLhs<bool>{ value };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,11 @@
|
|||||||
#include "catch_context.h"
|
#include "catch_context.h"
|
||||||
#include "catch_interfaces_capture.h"
|
#include "catch_interfaces_capture.h"
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# pragma GCC diagnostic push
|
||||||
|
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Report the error condition
|
// Report the error condition
|
||||||
void reportFatal( char const * const message ) {
|
void reportFatal( char const * const message ) {
|
||||||
@ -174,3 +179,7 @@ namespace Catch {
|
|||||||
# endif // CATCH_CONFIG_POSIX_SIGNALS
|
# endif // CATCH_CONFIG_POSIX_SIGNALS
|
||||||
|
|
||||||
#endif // not Windows
|
#endif // not Windows
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "catch_stringref.h"
|
#include "catch_stringref.h"
|
||||||
|
#include "catch_result_type.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@ -22,13 +23,14 @@ namespace Catch {
|
|||||||
struct Counts;
|
struct Counts;
|
||||||
struct BenchmarkInfo;
|
struct BenchmarkInfo;
|
||||||
struct BenchmarkStats;
|
struct BenchmarkStats;
|
||||||
|
struct AssertionReaction;
|
||||||
|
|
||||||
|
struct ITransientExpression;
|
||||||
|
|
||||||
struct IResultCapture {
|
struct IResultCapture {
|
||||||
|
|
||||||
virtual ~IResultCapture();
|
virtual ~IResultCapture();
|
||||||
|
|
||||||
virtual void assertionStarting( AssertionInfo const& info ) = 0;
|
|
||||||
virtual void assertionEnded( AssertionResult const& result ) = 0;
|
|
||||||
virtual bool sectionStarted( SectionInfo const& sectionInfo,
|
virtual bool sectionStarted( SectionInfo const& sectionInfo,
|
||||||
Counts& assertions ) = 0;
|
Counts& assertions ) = 0;
|
||||||
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
|
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
|
||||||
@ -40,16 +42,40 @@ namespace Catch {
|
|||||||
virtual void pushScopedMessage( MessageInfo const& message ) = 0;
|
virtual void pushScopedMessage( MessageInfo const& message ) = 0;
|
||||||
virtual void popScopedMessage( MessageInfo const& message ) = 0;
|
virtual void popScopedMessage( MessageInfo const& message ) = 0;
|
||||||
|
|
||||||
virtual std::string getCurrentTestName() const = 0;
|
|
||||||
virtual const AssertionResult* getLastResult() const = 0;
|
|
||||||
|
|
||||||
virtual void exceptionEarlyReported() = 0;
|
|
||||||
|
|
||||||
virtual void handleFatalErrorCondition( StringRef message ) = 0;
|
virtual void handleFatalErrorCondition( StringRef message ) = 0;
|
||||||
|
|
||||||
|
virtual void handleExpr
|
||||||
|
( AssertionInfo const& info,
|
||||||
|
ITransientExpression const& expr,
|
||||||
|
AssertionReaction& reaction ) = 0;
|
||||||
|
virtual void handleMessage
|
||||||
|
( AssertionInfo const& info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
StringRef const& message,
|
||||||
|
AssertionReaction& reaction ) = 0;
|
||||||
|
virtual void handleUnexpectedExceptionNotThrown
|
||||||
|
( AssertionInfo const& info,
|
||||||
|
AssertionReaction& reaction ) = 0;
|
||||||
|
virtual void handleUnexpectedInflightException
|
||||||
|
( AssertionInfo const& info,
|
||||||
|
std::string const& message,
|
||||||
|
AssertionReaction& reaction ) = 0;
|
||||||
|
virtual void handleIncomplete
|
||||||
|
( AssertionInfo const& info ) = 0;
|
||||||
|
virtual void handleNonExpr
|
||||||
|
( AssertionInfo const &info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
AssertionReaction &reaction ) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
virtual bool lastAssertionPassed() = 0;
|
virtual bool lastAssertionPassed() = 0;
|
||||||
virtual void assertionPassed() = 0;
|
virtual void assertionPassed() = 0;
|
||||||
virtual void assertionRun() = 0;
|
|
||||||
|
// Deprecated, do not use:
|
||||||
|
virtual std::string getCurrentTestName() const = 0;
|
||||||
|
virtual const AssertionResult* getLastResult() const = 0;
|
||||||
|
virtual void exceptionEarlyReported() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
IResultCapture& getResultCapture();
|
IResultCapture& getResultCapture();
|
||||||
|
@ -73,7 +73,9 @@ namespace Catch {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
|
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
|
||||||
static std::string translatorName( signature ); \
|
static std::string translatorName( signature ); \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
|
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||||
static std::string translatorName( signature )
|
static std::string translatorName( signature )
|
||||||
|
|
||||||
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
|
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
|
||||||
|
@ -8,11 +8,11 @@
|
|||||||
#include "catch_leak_detector.h"
|
#include "catch_leak_detector.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Catch {
|
|
||||||
|
|
||||||
#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
|
#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
|
||||||
#include <crtdbg.h>
|
#include <crtdbg.h>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
LeakDetector::LeakDetector() {
|
LeakDetector::LeakDetector() {
|
||||||
int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
||||||
flag |= _CRTDBG_LEAK_CHECK_DF;
|
flag |= _CRTDBG_LEAK_CHECK_DF;
|
||||||
@ -23,11 +23,10 @@ namespace Catch {
|
|||||||
// Change this to leaking allocation's number to break there
|
// Change this to leaking allocation's number to break there
|
||||||
_CrtSetBreakAlloc(-1);
|
_CrtSetBreakAlloc(-1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
LeakDetector::LeakDetector(){}
|
Catch::LeakDetector::LeakDetector() {}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -79,7 +79,11 @@ namespace Catch {
|
|||||||
namespace Matchers {
|
namespace Matchers {
|
||||||
namespace Floating {
|
namespace Floating {
|
||||||
WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
|
WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
|
||||||
:m_target{ target }, m_margin{ margin } {}
|
:m_target{ target }, m_margin{ margin } {
|
||||||
|
if (m_margin < 0) {
|
||||||
|
throw std::domain_error("Allowed margin difference has to be >= 0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
|
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
|
||||||
// But without the subtraction to allow for INFINITY in comparison
|
// But without the subtraction to allow for INFINITY in comparison
|
||||||
@ -95,7 +99,7 @@ namespace Floating {
|
|||||||
WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
|
WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
|
||||||
:m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
|
:m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
|
||||||
if (m_ulps < 0) {
|
if (m_ulps < 0) {
|
||||||
throw std::domain_error("Expected ulp difference has to be >0");
|
throw std::domain_error("Allowed ulp difference has to be >= 0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,10 +10,33 @@
|
|||||||
|
|
||||||
#include "catch_matchers.h"
|
#include "catch_matchers.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Matchers {
|
namespace Matchers {
|
||||||
|
|
||||||
namespace Vector {
|
namespace Vector {
|
||||||
|
namespace Detail {
|
||||||
|
template <typename InputIterator, typename T>
|
||||||
|
size_t count(InputIterator first, InputIterator last, T const& item) {
|
||||||
|
size_t cnt = 0;
|
||||||
|
for (; first != last; ++first) {
|
||||||
|
if (*first == item) {
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
template <typename InputIterator, typename T>
|
||||||
|
bool contains(InputIterator first, InputIterator last, T const& item) {
|
||||||
|
for (; first != last; ++first) {
|
||||||
|
if (*first == item) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
|
struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
|
||||||
@ -89,6 +112,46 @@ namespace Matchers {
|
|||||||
std::vector<T> const& m_comparator;
|
std::vector<T> const& m_comparator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
|
||||||
|
UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
|
||||||
|
bool match(std::vector<T> const& vec) const override {
|
||||||
|
// Note: This is a reimplementation of std::is_permutation,
|
||||||
|
// because I don't want to include <algorithm> inside the common path
|
||||||
|
if (m_target.size() != vec.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto lfirst = m_target.begin(), llast = m_target.end();
|
||||||
|
auto rfirst = vec.begin(), rlast = vec.end();
|
||||||
|
// Cut common prefix to optimize checking of permuted parts
|
||||||
|
while (lfirst != llast && *lfirst != *rfirst) {
|
||||||
|
++lfirst; ++rfirst;
|
||||||
|
}
|
||||||
|
if (lfirst == llast) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto mid = lfirst; mid != llast; ++mid) {
|
||||||
|
// Skip already counted items
|
||||||
|
if (Detail::contains(lfirst, mid, *mid)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
size_t num_vec = Detail::count(rfirst, rlast, *mid);
|
||||||
|
if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string describe() const override {
|
||||||
|
return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::vector<T> const& m_target;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Vector
|
} // namespace Vector
|
||||||
|
|
||||||
// The following functions create the actual matcher objects.
|
// The following functions create the actual matcher objects.
|
||||||
@ -109,6 +172,11 @@ namespace Matchers {
|
|||||||
return Vector::EqualsMatcher<T>( comparator );
|
return Vector::EqualsMatcher<T>( comparator );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
|
||||||
|
return Vector::UnorderedEqualsMatcher<T>(target);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Matchers
|
} // namespace Matchers
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
|
@ -49,11 +49,18 @@ namespace Catch {
|
|||||||
getResultCapture().pushScopedMessage( m_info );
|
getResultCapture().pushScopedMessage( m_info );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17
|
||||||
|
#endif
|
||||||
ScopedMessage::~ScopedMessage() {
|
ScopedMessage::~ScopedMessage() {
|
||||||
if ( !std::uncaught_exception() ){
|
if ( !std::uncaught_exception() ){
|
||||||
getResultCapture().popScopedMessage(m_info);
|
getResultCapture().popScopedMessage(m_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
@ -59,7 +59,7 @@ namespace Catch {
|
|||||||
|
|
||||||
class ScopedMessage {
|
class ScopedMessage {
|
||||||
public:
|
public:
|
||||||
ScopedMessage( MessageBuilder const& builder );
|
explicit ScopedMessage( MessageBuilder const& builder );
|
||||||
~ScopedMessage();
|
~ScopedMessage();
|
||||||
|
|
||||||
MessageInfo m_info;
|
MessageInfo m_info;
|
||||||
|
@ -87,6 +87,7 @@ namespace Catch {
|
|||||||
delete getTheRegistryHub();
|
delete getTheRegistryHub();
|
||||||
getTheRegistryHub() = nullptr;
|
getTheRegistryHub() = nullptr;
|
||||||
cleanUpContext();
|
cleanUpContext();
|
||||||
|
ReusableStringStream::cleanup();
|
||||||
}
|
}
|
||||||
std::string translateActiveException() {
|
std::string translateActiveException() {
|
||||||
return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
|
return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
|
||||||
|
@ -29,7 +29,7 @@ namespace Catch {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ReporterRegistrar( std::string const& name ) {
|
explicit ReporterRegistrar( std::string const& name ) {
|
||||||
getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() );
|
getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -10,37 +10,55 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
StreamRedirect::StreamRedirect(std::ostream& stream, std::string& targetString)
|
class RedirectedStream {
|
||||||
: m_stream(stream),
|
std::ostream& m_originalStream;
|
||||||
m_prevBuf(stream.rdbuf()),
|
std::ostream& m_redirectionStream;
|
||||||
m_targetString(targetString) {
|
std::streambuf* m_prevBuf;
|
||||||
stream.rdbuf(m_oss.get().rdbuf());
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamRedirect::~StreamRedirect() {
|
public:
|
||||||
m_targetString += m_oss.str();
|
RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
|
||||||
m_stream.rdbuf(m_prevBuf);
|
: m_originalStream( originalStream ),
|
||||||
|
m_redirectionStream( redirectionStream ),
|
||||||
|
m_prevBuf( m_originalStream.rdbuf() )
|
||||||
|
{
|
||||||
|
m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
|
||||||
}
|
}
|
||||||
|
~RedirectedStream() {
|
||||||
|
m_originalStream.rdbuf( m_prevBuf );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
StdErrRedirect::StdErrRedirect(std::string & targetString)
|
class RedirectedStdOut {
|
||||||
:m_cerrBuf(cerr().rdbuf()), m_clogBuf(clog().rdbuf()),
|
ReusableStringStream m_rss;
|
||||||
m_targetString(targetString) {
|
RedirectedStream m_cout;
|
||||||
cerr().rdbuf(m_oss.get().rdbuf());
|
public:
|
||||||
clog().rdbuf(m_oss.get().rdbuf());
|
RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
|
||||||
}
|
auto str() const -> std::string { return m_rss.str(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// StdErr has two constituent streams in C++, std::cerr and std::clog
|
||||||
|
// This means that we need to redirect 2 streams into 1 to keep proper
|
||||||
|
// order of writes
|
||||||
|
class RedirectedStdErr {
|
||||||
|
ReusableStringStream m_rss;
|
||||||
|
RedirectedStream m_cerr;
|
||||||
|
RedirectedStream m_clog;
|
||||||
|
public:
|
||||||
|
RedirectedStdErr()
|
||||||
|
: m_cerr( Catch::cerr(), m_rss.get() ),
|
||||||
|
m_clog( Catch::clog(), m_rss.get() )
|
||||||
|
{}
|
||||||
|
auto str() const -> std::string { return m_rss.str(); }
|
||||||
|
};
|
||||||
|
|
||||||
StdErrRedirect::~StdErrRedirect() {
|
|
||||||
m_targetString += m_oss.str();
|
|
||||||
cerr().rdbuf(m_cerrBuf);
|
|
||||||
clog().rdbuf(m_clogBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
|
RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
|
||||||
: m_runInfo(_config->name()),
|
: m_runInfo(_config->name()),
|
||||||
m_context(getCurrentMutableContext()),
|
m_context(getCurrentMutableContext()),
|
||||||
m_config(_config),
|
m_config(_config),
|
||||||
m_reporter(std::move(reporter)),
|
m_reporter(std::move(reporter)),
|
||||||
m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal }
|
m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal },
|
||||||
|
m_includeSuccessfulResults( m_config->includeSuccessfulResults() )
|
||||||
{
|
{
|
||||||
m_context.setRunner(this);
|
m_context.setRunner(this);
|
||||||
m_context.setConfig(m_config);
|
m_context.setConfig(m_config);
|
||||||
@ -109,18 +127,20 @@ namespace Catch {
|
|||||||
return *m_reporter;
|
return *m_reporter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunContext::assertionStarting(AssertionInfo const& info) {
|
|
||||||
m_reporter->assertionStarting( info );
|
|
||||||
}
|
|
||||||
void RunContext::assertionEnded(AssertionResult const & result) {
|
void RunContext::assertionEnded(AssertionResult const & result) {
|
||||||
if (result.getResultType() == ResultWas::Ok) {
|
if (result.getResultType() == ResultWas::Ok) {
|
||||||
m_totals.assertions.passed++;
|
m_totals.assertions.passed++;
|
||||||
|
m_lastAssertionPassed = true;
|
||||||
} else if (!result.isOk()) {
|
} else if (!result.isOk()) {
|
||||||
|
m_lastAssertionPassed = false;
|
||||||
if( m_activeTestCase->getTestCaseInfo().okToFail() )
|
if( m_activeTestCase->getTestCaseInfo().okToFail() )
|
||||||
m_totals.assertions.failedButOk++;
|
m_totals.assertions.failedButOk++;
|
||||||
else
|
else
|
||||||
m_totals.assertions.failed++;
|
m_totals.assertions.failed++;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
m_lastAssertionPassed = true;
|
||||||
|
}
|
||||||
|
|
||||||
// We have no use for the return value (whether messages should be cleared), because messages were made scoped
|
// We have no use for the return value (whether messages should be cleared), because messages were made scoped
|
||||||
// and should be let to clear themselves out.
|
// and should be let to clear themselves out.
|
||||||
@ -223,7 +243,7 @@ namespace Catch {
|
|||||||
tempResult.message = message;
|
tempResult.message = message;
|
||||||
AssertionResult result(m_lastAssertionInfo, tempResult);
|
AssertionResult result(m_lastAssertionInfo, tempResult);
|
||||||
|
|
||||||
getResultCapture().assertionEnded(result);
|
assertionEnded(result);
|
||||||
|
|
||||||
handleUnfinishedSections();
|
handleUnfinishedSections();
|
||||||
|
|
||||||
@ -252,18 +272,15 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool RunContext::lastAssertionPassed() {
|
bool RunContext::lastAssertionPassed() {
|
||||||
return m_totals.assertions.passed == (m_prevPassed + 1);
|
return m_lastAssertionPassed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunContext::assertionPassed() {
|
void RunContext::assertionPassed() {
|
||||||
|
m_lastAssertionPassed = true;
|
||||||
++m_totals.assertions.passed;
|
++m_totals.assertions.passed;
|
||||||
resetAssertionInfo();
|
resetAssertionInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunContext::assertionRun() {
|
|
||||||
m_prevPassed = m_totals.assertions.passed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RunContext::aborting() const {
|
bool RunContext::aborting() const {
|
||||||
return m_totals.assertions.failed == static_cast<std::size_t>(m_config->abortAfter());
|
return m_totals.assertions.failed == static_cast<std::size_t>(m_config->abortAfter());
|
||||||
}
|
}
|
||||||
@ -282,10 +299,13 @@ namespace Catch {
|
|||||||
Timer timer;
|
Timer timer;
|
||||||
try {
|
try {
|
||||||
if (m_reporter->getPreferences().shouldRedirectStdOut) {
|
if (m_reporter->getPreferences().shouldRedirectStdOut) {
|
||||||
StreamRedirect coutRedir(cout(), redirectedCout);
|
RedirectedStdOut redirectedStdOut;
|
||||||
StdErrRedirect errRedir(redirectedCerr);
|
RedirectedStdErr redirectedStdErr;
|
||||||
timer.start();
|
timer.start();
|
||||||
invokeActiveTestCase();
|
invokeActiveTestCase();
|
||||||
|
redirectedCout += redirectedStdOut.str();
|
||||||
|
redirectedCerr += redirectedStdErr.str();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
timer.start();
|
timer.start();
|
||||||
invokeActiveTestCase();
|
invokeActiveTestCase();
|
||||||
@ -297,11 +317,8 @@ namespace Catch {
|
|||||||
// Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
|
// Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
|
||||||
// are reported without translation at the point of origin.
|
// are reported without translation at the point of origin.
|
||||||
if( m_shouldReportUnexpected ) {
|
if( m_shouldReportUnexpected ) {
|
||||||
AssertionHandler
|
AssertionReaction dummyReaction;
|
||||||
( m_lastAssertionInfo.macroName,
|
handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
|
||||||
m_lastAssertionInfo.lineInfo,
|
|
||||||
m_lastAssertionInfo.capturedExpression,
|
|
||||||
m_lastAssertionInfo.resultDisposition ).useActiveException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_testCaseTracker->close();
|
m_testCaseTracker->close();
|
||||||
@ -331,6 +348,113 @@ namespace Catch {
|
|||||||
m_unfinishedSections.clear();
|
m_unfinishedSections.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RunContext::handleExpr(
|
||||||
|
AssertionInfo const& info,
|
||||||
|
ITransientExpression const& expr,
|
||||||
|
AssertionReaction& reaction
|
||||||
|
) {
|
||||||
|
m_reporter->assertionStarting( info );
|
||||||
|
|
||||||
|
bool negated = isFalseTest( info.resultDisposition );
|
||||||
|
bool result = expr.getResult() != negated;
|
||||||
|
|
||||||
|
if( result ) {
|
||||||
|
if (!m_includeSuccessfulResults) {
|
||||||
|
assertionPassed();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
reportExpr(info, ResultWas::Ok, &expr, negated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
|
||||||
|
populateReaction( reaction );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void RunContext::reportExpr(
|
||||||
|
AssertionInfo const &info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
ITransientExpression const *expr,
|
||||||
|
bool negated ) {
|
||||||
|
|
||||||
|
m_lastAssertionInfo = info;
|
||||||
|
AssertionResultData data( resultType, LazyExpression( negated ) );
|
||||||
|
|
||||||
|
AssertionResult assertionResult{ info, data };
|
||||||
|
assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
|
||||||
|
|
||||||
|
assertionEnded( assertionResult );
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunContext::handleMessage(
|
||||||
|
AssertionInfo const& info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
StringRef const& message,
|
||||||
|
AssertionReaction& reaction
|
||||||
|
) {
|
||||||
|
m_reporter->assertionStarting( info );
|
||||||
|
|
||||||
|
m_lastAssertionInfo = info;
|
||||||
|
|
||||||
|
AssertionResultData data( resultType, LazyExpression( false ) );
|
||||||
|
data.message = message;
|
||||||
|
AssertionResult assertionResult{ m_lastAssertionInfo, data };
|
||||||
|
assertionEnded( assertionResult );
|
||||||
|
if( !assertionResult.isOk() )
|
||||||
|
populateReaction( reaction );
|
||||||
|
}
|
||||||
|
void RunContext::handleUnexpectedExceptionNotThrown(
|
||||||
|
AssertionInfo const& info,
|
||||||
|
AssertionReaction& reaction
|
||||||
|
) {
|
||||||
|
handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunContext::handleUnexpectedInflightException(
|
||||||
|
AssertionInfo const& info,
|
||||||
|
std::string const& message,
|
||||||
|
AssertionReaction& reaction
|
||||||
|
) {
|
||||||
|
m_lastAssertionInfo = info;
|
||||||
|
|
||||||
|
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
|
||||||
|
data.message = message;
|
||||||
|
AssertionResult assertionResult{ info, data };
|
||||||
|
assertionEnded( assertionResult );
|
||||||
|
populateReaction( reaction );
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunContext::populateReaction( AssertionReaction& reaction ) {
|
||||||
|
reaction.shouldDebugBreak = m_config->shouldDebugBreak();
|
||||||
|
reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunContext::handleIncomplete(
|
||||||
|
AssertionInfo const& info
|
||||||
|
) {
|
||||||
|
m_lastAssertionInfo = info;
|
||||||
|
|
||||||
|
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
|
||||||
|
data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
|
||||||
|
AssertionResult assertionResult{ info, data };
|
||||||
|
assertionEnded( assertionResult );
|
||||||
|
}
|
||||||
|
void RunContext::handleNonExpr(
|
||||||
|
AssertionInfo const &info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
AssertionReaction &reaction
|
||||||
|
) {
|
||||||
|
m_lastAssertionInfo = info;
|
||||||
|
|
||||||
|
AssertionResultData data( resultType, LazyExpression( false ) );
|
||||||
|
AssertionResult assertionResult{ info, data };
|
||||||
|
assertionEnded( assertionResult );
|
||||||
|
|
||||||
|
if( !assertionResult.isOk() )
|
||||||
|
populateReaction( reaction );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
IResultCapture& getResultCapture() {
|
IResultCapture& getResultCapture() {
|
||||||
if (auto* capture = getCurrentContext().getResultCapture())
|
if (auto* capture = getCurrentContext().getResultCapture())
|
||||||
return *capture;
|
return *capture;
|
||||||
|
@ -28,33 +28,6 @@ namespace Catch {
|
|||||||
|
|
||||||
struct IMutableContext;
|
struct IMutableContext;
|
||||||
|
|
||||||
class StreamRedirect {
|
|
||||||
|
|
||||||
public:
|
|
||||||
StreamRedirect(std::ostream& stream, std::string& targetString);
|
|
||||||
~StreamRedirect();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::ostream& m_stream;
|
|
||||||
std::streambuf* m_prevBuf;
|
|
||||||
ReusableStringStream m_oss;
|
|
||||||
std::string& m_targetString;
|
|
||||||
};
|
|
||||||
|
|
||||||
// StdErr has two constituent streams in C++, std::cerr and std::clog
|
|
||||||
// This means that we need to redirect 2 streams into 1 to keep proper
|
|
||||||
// order of writes and cannot use StreamRedirect on its own
|
|
||||||
class StdErrRedirect {
|
|
||||||
public:
|
|
||||||
StdErrRedirect(std::string& targetString);
|
|
||||||
~StdErrRedirect();
|
|
||||||
private:
|
|
||||||
std::streambuf* m_cerrBuf;
|
|
||||||
std::streambuf* m_clogBuf;
|
|
||||||
ReusableStringStream m_oss;
|
|
||||||
std::string& m_targetString;
|
|
||||||
};
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class RunContext : public IResultCapture, public IRunner {
|
class RunContext : public IResultCapture, public IRunner {
|
||||||
@ -65,7 +38,7 @@ namespace Catch {
|
|||||||
|
|
||||||
explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter );
|
explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter );
|
||||||
|
|
||||||
virtual ~RunContext();
|
~RunContext() override;
|
||||||
|
|
||||||
void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
|
void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
|
||||||
void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount );
|
void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount );
|
||||||
@ -75,14 +48,33 @@ namespace Catch {
|
|||||||
IConfigPtr config() const;
|
IConfigPtr config() const;
|
||||||
IStreamingReporter& reporter() const;
|
IStreamingReporter& reporter() const;
|
||||||
|
|
||||||
private: // IResultCapture
|
public: // IResultCapture
|
||||||
|
|
||||||
|
// Assertion handlers
|
||||||
void assertionStarting(AssertionInfo const& info) override;
|
void handleExpr
|
||||||
void assertionEnded(AssertionResult const& result) override;
|
( AssertionInfo const& info,
|
||||||
|
ITransientExpression const& expr,
|
||||||
|
AssertionReaction& reaction ) override;
|
||||||
|
void handleMessage
|
||||||
|
( AssertionInfo const& info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
StringRef const& message,
|
||||||
|
AssertionReaction& reaction ) override;
|
||||||
|
void handleUnexpectedExceptionNotThrown
|
||||||
|
( AssertionInfo const& info,
|
||||||
|
AssertionReaction& reaction ) override;
|
||||||
|
void handleUnexpectedInflightException
|
||||||
|
( AssertionInfo const& info,
|
||||||
|
std::string const& message,
|
||||||
|
AssertionReaction& reaction ) override;
|
||||||
|
void handleIncomplete
|
||||||
|
( AssertionInfo const& info ) override;
|
||||||
|
void handleNonExpr
|
||||||
|
( AssertionInfo const &info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
AssertionReaction &reaction ) override;
|
||||||
|
|
||||||
bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override;
|
bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override;
|
||||||
bool testForMissingAssertions(Counts& assertions);
|
|
||||||
|
|
||||||
void sectionEnded( SectionEndInfo const& endInfo ) override;
|
void sectionEnded( SectionEndInfo const& endInfo ) override;
|
||||||
void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
|
void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
|
||||||
@ -105,8 +97,6 @@ namespace Catch {
|
|||||||
|
|
||||||
void assertionPassed() override;
|
void assertionPassed() override;
|
||||||
|
|
||||||
void assertionRun() override;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// !TBD We need to do this another way!
|
// !TBD We need to do this another way!
|
||||||
bool aborting() const override;
|
bool aborting() const override;
|
||||||
@ -117,6 +107,16 @@ namespace Catch {
|
|||||||
void invokeActiveTestCase();
|
void invokeActiveTestCase();
|
||||||
|
|
||||||
void resetAssertionInfo();
|
void resetAssertionInfo();
|
||||||
|
bool testForMissingAssertions( Counts& assertions );
|
||||||
|
|
||||||
|
void assertionEnded( AssertionResult const& result );
|
||||||
|
void reportExpr
|
||||||
|
( AssertionInfo const &info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
ITransientExpression const *expr,
|
||||||
|
bool negated );
|
||||||
|
|
||||||
|
void populateReaction( AssertionReaction& reaction );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -136,12 +136,11 @@ namespace Catch {
|
|||||||
std::vector<SectionEndInfo> m_unfinishedSections;
|
std::vector<SectionEndInfo> m_unfinishedSections;
|
||||||
std::vector<ITracker*> m_activeSections;
|
std::vector<ITracker*> m_activeSections;
|
||||||
TrackerContext m_trackerContext;
|
TrackerContext m_trackerContext;
|
||||||
std::size_t m_prevPassed = 0;
|
bool m_lastAssertionPassed = false;
|
||||||
bool m_shouldReportUnexpected = true;
|
bool m_shouldReportUnexpected = true;
|
||||||
|
bool m_includeSuccessfulResults;
|
||||||
};
|
};
|
||||||
|
|
||||||
IResultCapture& getResultCapture();
|
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
|
||||||
|
@ -22,12 +22,10 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const int MaxExitCode = 255;
|
const int MaxExitCode = 255;
|
||||||
using Catch::IStreamingReporterPtr;
|
|
||||||
using Catch::IConfigPtr;
|
|
||||||
using Catch::Config;
|
|
||||||
|
|
||||||
IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) {
|
IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) {
|
||||||
auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config);
|
auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config);
|
||||||
@ -61,7 +59,6 @@ namespace {
|
|||||||
|
|
||||||
|
|
||||||
Catch::Totals runTests(std::shared_ptr<Config> const& config) {
|
Catch::Totals runTests(std::shared_ptr<Config> const& config) {
|
||||||
using namespace Catch;
|
|
||||||
IStreamingReporterPtr reporter = makeReporter(config);
|
IStreamingReporterPtr reporter = makeReporter(config);
|
||||||
addListeners(reporter, config);
|
addListeners(reporter, config);
|
||||||
|
|
||||||
@ -88,7 +85,6 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void applyFilenamesAsTags(Catch::IConfig const& config) {
|
void applyFilenamesAsTags(Catch::IConfig const& config) {
|
||||||
using namespace Catch;
|
|
||||||
auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
|
auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
|
||||||
for (auto& testCase : tests) {
|
for (auto& testCase : tests) {
|
||||||
auto tags = testCase.tags;
|
auto tags = testCase.tags;
|
||||||
@ -110,9 +106,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // anon namespace
|
||||||
|
|
||||||
namespace Catch {
|
|
||||||
|
|
||||||
Session::Session() {
|
Session::Session() {
|
||||||
static bool alreadyInstantiated = false;
|
static bool alreadyInstantiated = false;
|
||||||
|
@ -145,6 +145,7 @@ namespace Catch {
|
|||||||
std::vector<std::unique_ptr<std::ostringstream>> m_streams;
|
std::vector<std::unique_ptr<std::ostringstream>> m_streams;
|
||||||
std::vector<std::size_t> m_unused;
|
std::vector<std::size_t> m_unused;
|
||||||
std::ostringstream m_referenceStream; // Used for copy state/ flags from
|
std::ostringstream m_referenceStream; // Used for copy state/ flags from
|
||||||
|
static StringStreams* s_instance;
|
||||||
|
|
||||||
auto add() -> std::size_t {
|
auto add() -> std::size_t {
|
||||||
if( m_unused.empty() ) {
|
if( m_unused.empty() ) {
|
||||||
@ -165,11 +166,21 @@ namespace Catch {
|
|||||||
|
|
||||||
// !TBD: put in TLS
|
// !TBD: put in TLS
|
||||||
static auto instance() -> StringStreams& {
|
static auto instance() -> StringStreams& {
|
||||||
static StringStreams s_stringStreams;
|
if( !s_instance )
|
||||||
return s_stringStreams;
|
s_instance = new StringStreams();
|
||||||
|
return *s_instance;
|
||||||
|
}
|
||||||
|
static void cleanup() {
|
||||||
|
delete s_instance;
|
||||||
|
s_instance = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
StringStreams* StringStreams::s_instance = nullptr;
|
||||||
|
|
||||||
|
void ReusableStringStream::cleanup() {
|
||||||
|
StringStreams::cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
ReusableStringStream::ReusableStringStream()
|
ReusableStringStream::ReusableStringStream()
|
||||||
: m_index( StringStreams::instance().add() ),
|
: m_index( StringStreams::instance().add() ),
|
||||||
|
@ -43,6 +43,8 @@ namespace Catch {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
auto get() -> std::ostream& { return *m_oss; }
|
auto get() -> std::ostream& { return *m_oss; }
|
||||||
|
|
||||||
|
static void cleanup();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,9 +10,6 @@
|
|||||||
# pragma warning(push)
|
# pragma warning(push)
|
||||||
# pragma warning(disable: 161 1682)
|
# pragma warning(disable: 161 1682)
|
||||||
# else // __ICC
|
# else // __ICC
|
||||||
# pragma clang diagnostic ignored "-Wglobal-constructors"
|
|
||||||
# pragma clang diagnostic ignored "-Wvariadic-macros"
|
|
||||||
# pragma clang diagnostic ignored "-Wc99-extensions"
|
|
||||||
# pragma clang diagnostic ignored "-Wunused-variable"
|
# pragma clang diagnostic ignored "-Wunused-variable"
|
||||||
# pragma clang diagnostic push
|
# pragma clang diagnostic push
|
||||||
# pragma clang diagnostic ignored "-Wpadded"
|
# pragma clang diagnostic ignored "-Wpadded"
|
||||||
@ -20,10 +17,8 @@
|
|||||||
# pragma clang diagnostic ignored "-Wcovered-switch-default"
|
# pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||||
# endif
|
# endif
|
||||||
#elif defined __GNUC__
|
#elif defined __GNUC__
|
||||||
# pragma GCC diagnostic ignored "-Wvariadic-macros"
|
|
||||||
# pragma GCC diagnostic ignored "-Wunused-variable"
|
# pragma GCC diagnostic ignored "-Wunused-variable"
|
||||||
# pragma GCC diagnostic ignored "-Wparentheses"
|
# pragma GCC diagnostic ignored "-Wparentheses"
|
||||||
|
|
||||||
# pragma GCC diagnostic push
|
# pragma GCC diagnostic push
|
||||||
# pragma GCC diagnostic ignored "-Wpadded"
|
# pragma GCC diagnostic ignored "-Wpadded"
|
||||||
#endif
|
#endif
|
||||||
|
@ -17,6 +17,9 @@ namespace Catch {
|
|||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
|
#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_TAG_ALIAS_AUTOREGISTRAR_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_TAG_ALIAS_AUTOREGISTRAR_H_INCLUDED
|
||||||
|
@ -45,11 +45,11 @@ namespace Catch {
|
|||||||
void Timer::start() {
|
void Timer::start() {
|
||||||
m_nanoseconds = getCurrentNanosecondsSinceEpoch();
|
m_nanoseconds = getCurrentNanosecondsSinceEpoch();
|
||||||
}
|
}
|
||||||
auto Timer::getElapsedNanoseconds() const -> unsigned int {
|
auto Timer::getElapsedNanoseconds() const -> uint64_t {
|
||||||
return static_cast<unsigned int>(getCurrentNanosecondsSinceEpoch() - m_nanoseconds);
|
return getCurrentNanosecondsSinceEpoch() - m_nanoseconds;
|
||||||
}
|
}
|
||||||
auto Timer::getElapsedMicroseconds() const -> unsigned int {
|
auto Timer::getElapsedMicroseconds() const -> uint64_t {
|
||||||
return static_cast<unsigned int>(getElapsedNanoseconds()/1000);
|
return getElapsedNanoseconds()/1000;
|
||||||
}
|
}
|
||||||
auto Timer::getElapsedMilliseconds() const -> unsigned int {
|
auto Timer::getElapsedMilliseconds() const -> unsigned int {
|
||||||
return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
|
return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
|
||||||
|
@ -19,8 +19,8 @@ namespace Catch {
|
|||||||
uint64_t m_nanoseconds = 0;
|
uint64_t m_nanoseconds = 0;
|
||||||
public:
|
public:
|
||||||
void start();
|
void start();
|
||||||
auto getElapsedNanoseconds() const -> unsigned int;
|
auto getElapsedNanoseconds() const -> uint64_t;
|
||||||
auto getElapsedMicroseconds() const -> unsigned int;
|
auto getElapsedMicroseconds() const -> uint64_t;
|
||||||
auto getElapsedMilliseconds() const -> unsigned int;
|
auto getElapsedMilliseconds() const -> unsigned int;
|
||||||
auto getElapsedSeconds() const -> double;
|
auto getElapsedSeconds() const -> double;
|
||||||
};
|
};
|
||||||
|
@ -210,7 +210,7 @@ class Duration {
|
|||||||
Unit m_units;
|
Unit m_units;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
|
explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
|
||||||
: m_inNanoseconds(inNanoseconds),
|
: m_inNanoseconds(inNanoseconds),
|
||||||
m_units(units) {
|
m_units(units) {
|
||||||
if (m_units == Unit::Auto) {
|
if (m_units == Unit::Auto) {
|
||||||
@ -273,9 +273,9 @@ class TablePrinter {
|
|||||||
bool m_isOpen = false;
|
bool m_isOpen = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TablePrinter(std::ostream& os, std::vector<ColumnInfo> const& columnInfos)
|
TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
|
||||||
: m_os( os ),
|
: m_os( os ),
|
||||||
m_columnInfos(columnInfos) {}
|
m_columnInfos( std::move( columnInfos ) ) {}
|
||||||
|
|
||||||
auto columnInfos() const -> std::vector<ColumnInfo> const& {
|
auto columnInfos() const -> std::vector<ColumnInfo> const& {
|
||||||
return m_columnInfos;
|
return m_columnInfos;
|
||||||
@ -346,7 +346,8 @@ ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
|
|||||||
{ "elapsed ns", 14, ColumnInfo::Right },
|
{ "elapsed ns", 14, ColumnInfo::Right },
|
||||||
{ "average", 14, ColumnInfo::Right }
|
{ "average", 14, ColumnInfo::Right }
|
||||||
})) {}
|
})) {}
|
||||||
ConsoleReporter::~ConsoleReporter() {}
|
ConsoleReporter::~ConsoleReporter() = default;
|
||||||
|
|
||||||
std::string ConsoleReporter::getDescription() {
|
std::string ConsoleReporter::getDescription() {
|
||||||
return "Reports test results as plain lines of text";
|
return "Reports test results as plain lines of text";
|
||||||
}
|
}
|
||||||
@ -402,7 +403,7 @@ void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {
|
|||||||
void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
|
void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
|
||||||
lazyPrintWithoutClosingBenchmarkTable();
|
lazyPrintWithoutClosingBenchmarkTable();
|
||||||
|
|
||||||
auto nameCol = Column(info.name).width(m_tablePrinter->columnInfos()[0].width - 2);
|
auto nameCol = Column( info.name ).width( static_cast<std::size_t>( m_tablePrinter->columnInfos()[0].width - 2 ) );
|
||||||
|
|
||||||
bool firstLine = true;
|
bool firstLine = true;
|
||||||
for (auto line : nameCol) {
|
for (auto line : nameCol) {
|
||||||
@ -528,8 +529,8 @@ void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t
|
|||||||
|
|
||||||
struct SummaryColumn {
|
struct SummaryColumn {
|
||||||
|
|
||||||
SummaryColumn(std::string const& _label, Colour::Code _colour)
|
SummaryColumn( std::string _label, Colour::Code _colour )
|
||||||
: label(_label),
|
: label( std::move( _label ) ),
|
||||||
colour( _colour ) {}
|
colour( _colour ) {}
|
||||||
SummaryColumn addRow( std::size_t count ) {
|
SummaryColumn addRow( std::size_t count ) {
|
||||||
ReusableStringStream rss;
|
ReusableStringStream rss;
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
// file can be distributed as a single header that works with the main
|
// file can be distributed as a single header that works with the main
|
||||||
// Catch single header.
|
// Catch single header.
|
||||||
|
|
||||||
#include "../internal/catch_enforce.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
@ -99,12 +97,12 @@ namespace Catch {
|
|||||||
case ResultWas::Ok:
|
case ResultWas::Ok:
|
||||||
case ResultWas::Info:
|
case ResultWas::Info:
|
||||||
case ResultWas::Warning:
|
case ResultWas::Warning:
|
||||||
CATCH_ERROR( "Internal error in TeamCity reporter" );
|
throw std::domain_error( "Internal error in TeamCity reporter" );
|
||||||
// These cases are here to prevent compiler warnings
|
// These cases are here to prevent compiler warnings
|
||||||
case ResultWas::Unknown:
|
case ResultWas::Unknown:
|
||||||
case ResultWas::FailureBit:
|
case ResultWas::FailureBit:
|
||||||
case ResultWas::Exception:
|
case ResultWas::Exception:
|
||||||
CATCH_ERROR( "Not implemented" );
|
throw std::domain_error( "Not implemented" );
|
||||||
}
|
}
|
||||||
if( assertionStats.infoMessages.size() == 1 )
|
if( assertionStats.infoMessages.size() == 1 )
|
||||||
msg << " with message:";
|
msg << " with message:";
|
||||||
|
@ -26,7 +26,7 @@ namespace Catch {
|
|||||||
m_reporterPrefs.shouldRedirectStdOut = true;
|
m_reporterPrefs.shouldRedirectStdOut = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlReporter::~XmlReporter() {};
|
XmlReporter::~XmlReporter() = default;
|
||||||
|
|
||||||
std::string XmlReporter::getDescription() {
|
std::string XmlReporter::getDescription() {
|
||||||
return "Reports test results as an XML document";
|
return "Reports test results as an XML document";
|
||||||
@ -95,10 +95,10 @@ namespace Catch {
|
|||||||
|
|
||||||
bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
|
bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
|
||||||
|
|
||||||
if( includeResults ) {
|
if( includeResults || result.getResultType() == ResultWas::Warning ) {
|
||||||
// Print any info messages in <Info> tags.
|
// Print any info messages in <Info> tags.
|
||||||
for( auto const& msg : assertionStats.infoMessages ) {
|
for( auto const& msg : assertionStats.infoMessages ) {
|
||||||
if( msg.type == ResultWas::Info ) {
|
if( msg.type == ResultWas::Info && includeResults ) {
|
||||||
m_xml.scopedElement( "Info" )
|
m_xml.scopedElement( "Info" )
|
||||||
.writeText( msg.message );
|
.writeText( msg.message );
|
||||||
} else if ( msg.type == ResultWas::Warning ) {
|
} else if ( msg.type == ResultWas::Warning ) {
|
||||||
|
11
misc/CMakeLists.txt
Normal file
11
misc/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
|
project(CatchCoverageHelper)
|
||||||
|
|
||||||
|
add_executable(CoverageHelper coverage-helper.cpp)
|
||||||
|
set_property(TARGET CoverageHelper PROPERTY CXX_STANDARD 11)
|
||||||
|
set_property(TARGET CoverageHelper PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||||
|
set_property(TARGET CoverageHelper PROPERTY CXX_EXTENSIONS OFF)
|
||||||
|
if (MSVC)
|
||||||
|
target_compile_options( CoverageHelper PRIVATE /W4 /w44265 /WX /w44061 /w44062 )
|
||||||
|
endif()
|
13
misc/appveyorBuildConfigurationScript.bat
Normal file
13
misc/appveyorBuildConfigurationScript.bat
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
@REM # In debug build, we want to
|
||||||
|
@REM # 1) Prebuild memcheck redirecter
|
||||||
|
@REM # 2) Regenerate single header include for examples
|
||||||
|
@REM # 3) Enable building examples
|
||||||
|
if "%CONFIGURATION%"=="Debug" (
|
||||||
|
python scripts\generateSingleHeader.py
|
||||||
|
cmake -Hmisc -Bbuild-misc -A%PLATFORM%
|
||||||
|
cmake --build build-misc
|
||||||
|
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DBUILD_EXAMPLES=ON -DMEMORYCHECK_COMMAND=build-misc\Debug\CoverageHelper.exe -DMEMORYCHECK_COMMAND_OPTIONS=--sep-- -DMEMORYCHECK_TYPE=Valgrind
|
||||||
|
)
|
||||||
|
if "%CONFIGURATION%"=="Release" (
|
||||||
|
cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain%
|
||||||
|
)
|
9
misc/appveyorMergeCoverageScript.py
Normal file
9
misc/appveyorMergeCoverageScript.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
cov_files = list(glob.glob('cov-report*.bin'))
|
||||||
|
base_cmd = ['OpenCppCoverage', '--quiet', '--export_type=cobertura:cobertura.xml'] + ['--input_coverage={}'.format(f) for f in cov_files]
|
||||||
|
subprocess.call(base_cmd)
|
9
misc/appveyorTestRunScript.bat
Normal file
9
misc/appveyorTestRunScript.bat
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
cd Build
|
||||||
|
if "%CONFIGURATION%"=="Debug" (
|
||||||
|
ctest -j 2 -C %CONFIGURATION% -D ExperimentalMemCheck
|
||||||
|
python ..\misc\appveyorMergeCoverageScript.py
|
||||||
|
codecov --root .. --no-color --disable gcov -f cobertura.xml -t %CODECOV_TOKEN%
|
||||||
|
)
|
||||||
|
if "%CONFIGURATION%"=="Release" (
|
||||||
|
ctest -j 2 -C %CONFIGURATION%
|
||||||
|
)
|
100
misc/coverage-helper.cpp
Normal file
100
misc/coverage-helper.cpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <numeric>
|
||||||
|
#include <regex>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
void create_empty_file(std::string const& path) {
|
||||||
|
std::ofstream ofs(path);
|
||||||
|
ofs << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string separator = "--sep--";
|
||||||
|
const std::string logfile_prefix = "--log-file=";
|
||||||
|
|
||||||
|
bool starts_with(std::string const& str, std::string const& pref) {
|
||||||
|
return str.find(pref) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_log_file_arg(std::string const& arg) {
|
||||||
|
assert(starts_with(arg, logfile_prefix) && "Attempting to parse incorrect arg!");
|
||||||
|
auto fname = arg.substr(logfile_prefix.size());
|
||||||
|
create_empty_file(fname);
|
||||||
|
std::regex regex("MemoryChecker\\.(\\d+)\\.log", std::regex::icase);
|
||||||
|
std::smatch match;
|
||||||
|
if (std::regex_search(fname, match, regex)) {
|
||||||
|
return std::stoi(match[1]);
|
||||||
|
} else {
|
||||||
|
throw std::domain_error("Couldn't find desired expression in string: " + fname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string catch_path(std::string path) {
|
||||||
|
auto start = path.find("catch");
|
||||||
|
// try capitalized instead
|
||||||
|
if (start == std::string::npos) {
|
||||||
|
start = path.find("Catch");
|
||||||
|
}
|
||||||
|
if (start == std::string::npos) {
|
||||||
|
throw std::domain_error("Couldn't find Catch's base path");
|
||||||
|
}
|
||||||
|
auto end = path.find_first_of("\\/", start);
|
||||||
|
return path.substr(0, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string windowsify_path(std::string path) {
|
||||||
|
for (auto& c : path) {
|
||||||
|
if (c == '/') {
|
||||||
|
c = '\\';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void exec_cmd(std::string const& cmd, int log_num, std::string const& path) {
|
||||||
|
std::array<char, 128> buffer;
|
||||||
|
#if defined(_WIN32)
|
||||||
|
auto real_cmd = "OpenCppCoverage --export_type binary:cov-report" + std::to_string(log_num)
|
||||||
|
+ ".bin --quiet " + "--sources " + path + " --cover_children -- " + cmd;
|
||||||
|
std::cout << "=== Marker ===: Cmd: " << real_cmd << '\n';
|
||||||
|
std::shared_ptr<FILE> pipe(_popen(real_cmd.c_str(), "r"), _pclose);
|
||||||
|
#else // Just for testing, in the real world we will always work under WIN32
|
||||||
|
(void)log_num; (void)path;
|
||||||
|
std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!pipe) {
|
||||||
|
throw std::runtime_error("popen() failed!");
|
||||||
|
}
|
||||||
|
while (!feof(pipe.get())) {
|
||||||
|
if (fgets(buffer.data(), 128, pipe.get()) != nullptr) {
|
||||||
|
std::cout << buffer.data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// argv should be:
|
||||||
|
// [0]: our path
|
||||||
|
// [1]: "--log-file=<path>"
|
||||||
|
// [2]: "--sep--"
|
||||||
|
// [3]+: the actual command
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
std::vector<std::string> args(argv, argv + argc);
|
||||||
|
auto sep = std::find(begin(args), end(args), separator);
|
||||||
|
assert(sep - begin(args) == 2 && "Structure differs from expected!");
|
||||||
|
|
||||||
|
auto num = parse_log_file_arg(args[1]);
|
||||||
|
|
||||||
|
auto cmdline = std::accumulate(++sep, end(args), std::string{}, [] (const std::string& lhs, const std::string& rhs) {
|
||||||
|
return lhs + ' ' + rhs;
|
||||||
|
});
|
||||||
|
|
||||||
|
exec_cmd(cmdline, num, windowsify_path(catch_path(args[0])));
|
||||||
|
}
|
19
misc/installOpenCppCoverage.ps1
Normal file
19
misc/installOpenCppCoverage.ps1
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Downloads are done from the oficial github release page links
|
||||||
|
$downloadUrl = "https://github.com/OpenCppCoverage/OpenCppCoverage/releases/download/release-0.9.6.1/OpenCppCoverageSetup-x64-0.9.6.1.exe"
|
||||||
|
$installerPath = [System.IO.Path]::Combine($Env:USERPROFILE, "Downloads", "OpenCppCoverageSetup.exe")
|
||||||
|
|
||||||
|
if(-Not (Test-Path $installerPath)) {
|
||||||
|
Write-Host -ForegroundColor White ("Downloading OpenCppCoverage from: " + $downloadUrl)
|
||||||
|
Start-FileDownload $downloadUrl -FileName $installerPath
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host -ForegroundColor White "About to install OpenCppCoverage..."
|
||||||
|
|
||||||
|
$installProcess = (Start-Process $installerPath -ArgumentList '/VERYSILENT' -PassThru -Wait)
|
||||||
|
if($installProcess.ExitCode -ne 0) {
|
||||||
|
throw [System.String]::Format("Failed to install OpenCppCoverage, ExitCode: {0}.", $installProcess.ExitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Assume standard, boring, installation path of ".../Program Files/OpenCppCoverage"
|
||||||
|
$installPath = [System.IO.Path]::Combine(${Env:ProgramFiles}, "OpenCppCoverage")
|
||||||
|
$env:Path="$env:Path;$installPath"
|
1035
projects/SelfTest/Baselines/compact.sw.approved.txt
Normal file
1035
projects/SelfTest/Baselines/compact.sw.approved.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -700,6 +700,7 @@ with expansion:
|
|||||||
|
|
||||||
A string sent directly to stdout
|
A string sent directly to stdout
|
||||||
A string sent directly to stderr
|
A string sent directly to stderr
|
||||||
|
A string sent to stderr via clog
|
||||||
Message from section one
|
Message from section one
|
||||||
Message from section two
|
Message from section two
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -808,6 +809,33 @@ Matchers.tests.cpp:<line number>: FAILED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
{ 1, 2, 3 } Equals: { }
|
{ 1, 2, 3 } Equals: { }
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Vector matchers that fail
|
||||||
|
UnorderedEquals
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: FAILED:
|
||||||
|
CHECK_THAT( v, UnorderedEquals(empty) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 2, 3 } UnorderedEquals: { }
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: FAILED:
|
||||||
|
CHECK_THAT( empty, UnorderedEquals(v) )
|
||||||
|
with expansion:
|
||||||
|
{ } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: FAILED:
|
||||||
|
CHECK_THAT( permuted, UnorderedEquals(v) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: FAILED:
|
||||||
|
CHECK_THAT( permuted, UnorderedEquals(v) )
|
||||||
|
with expansion:
|
||||||
|
{ 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
When unchecked exceptions are thrown directly they are always failures
|
When unchecked exceptions are thrown directly they are always failures
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -1052,6 +1080,6 @@ with expansion:
|
|||||||
"{?}" == "1"
|
"{?}" == "1"
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 189 | 137 passed | 48 failed | 4 failed as expected
|
test cases: 191 | 139 passed | 48 failed | 4 failed as expected
|
||||||
assertions: 952 | 828 passed | 103 failed | 21 failed as expected
|
assertions: 971 | 843 passed | 107 failed | 21 failed as expected
|
||||||
|
|
||||||
|
@ -762,9 +762,7 @@ Tricky.tests.cpp:<line number>
|
|||||||
|
|
||||||
Tricky.tests.cpp:<line number>:
|
Tricky.tests.cpp:<line number>:
|
||||||
PASSED:
|
PASSED:
|
||||||
REQUIRE( Catch::alwaysTrue() )
|
REQUIRE( true )
|
||||||
with expansion:
|
|
||||||
true
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Assertions then sections
|
Assertions then sections
|
||||||
@ -775,9 +773,7 @@ Tricky.tests.cpp:<line number>
|
|||||||
|
|
||||||
Tricky.tests.cpp:<line number>:
|
Tricky.tests.cpp:<line number>:
|
||||||
PASSED:
|
PASSED:
|
||||||
REQUIRE( Catch::alwaysTrue() )
|
REQUIRE( true )
|
||||||
with expansion:
|
|
||||||
true
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Assertions then sections
|
Assertions then sections
|
||||||
@ -789,9 +785,7 @@ Tricky.tests.cpp:<line number>
|
|||||||
|
|
||||||
Tricky.tests.cpp:<line number>:
|
Tricky.tests.cpp:<line number>:
|
||||||
PASSED:
|
PASSED:
|
||||||
REQUIRE( Catch::alwaysTrue() )
|
REQUIRE( true )
|
||||||
with expansion:
|
|
||||||
true
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Assertions then sections
|
Assertions then sections
|
||||||
@ -801,9 +795,7 @@ Tricky.tests.cpp:<line number>
|
|||||||
|
|
||||||
Tricky.tests.cpp:<line number>:
|
Tricky.tests.cpp:<line number>:
|
||||||
PASSED:
|
PASSED:
|
||||||
REQUIRE( Catch::alwaysTrue() )
|
REQUIRE( true )
|
||||||
with expansion:
|
|
||||||
true
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Assertions then sections
|
Assertions then sections
|
||||||
@ -814,9 +806,7 @@ Tricky.tests.cpp:<line number>
|
|||||||
|
|
||||||
Tricky.tests.cpp:<line number>:
|
Tricky.tests.cpp:<line number>:
|
||||||
PASSED:
|
PASSED:
|
||||||
REQUIRE( Catch::alwaysTrue() )
|
REQUIRE( true )
|
||||||
with expansion:
|
|
||||||
true
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Assertions then sections
|
Assertions then sections
|
||||||
@ -828,9 +818,7 @@ Tricky.tests.cpp:<line number>
|
|||||||
|
|
||||||
Tricky.tests.cpp:<line number>:
|
Tricky.tests.cpp:<line number>:
|
||||||
PASSED:
|
PASSED:
|
||||||
REQUIRE( Catch::alwaysTrue() )
|
REQUIRE( true )
|
||||||
with expansion:
|
|
||||||
true
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Assorted miscellaneous tests
|
Assorted miscellaneous tests
|
||||||
@ -1153,13 +1141,13 @@ with expansion:
|
|||||||
|
|
||||||
Approx.tests.cpp:<line number>:
|
Approx.tests.cpp:<line number>:
|
||||||
PASSED:
|
PASSED:
|
||||||
REQUIRE( td >= Approx(10.0) )
|
REQUIRE( td >= Approx(td) )
|
||||||
with expansion:
|
with expansion:
|
||||||
StrongDoubleTypedef(10) >= Approx( 10.0 )
|
StrongDoubleTypedef(10) >= Approx( 10.0 )
|
||||||
|
|
||||||
Approx.tests.cpp:<line number>:
|
Approx.tests.cpp:<line number>:
|
||||||
PASSED:
|
PASSED:
|
||||||
REQUIRE( Approx(10.0) >= td )
|
REQUIRE( Approx(td) >= td )
|
||||||
with expansion:
|
with expansion:
|
||||||
Approx( 10.0 ) >= StrongDoubleTypedef(10)
|
Approx( 10.0 ) >= StrongDoubleTypedef(10)
|
||||||
|
|
||||||
@ -1884,6 +1872,29 @@ PASSED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
nanf not ( is within 100.0 of nan or is within 123 ULPs of nanf )
|
nanf not ( is within 100.0 of nan or is within 123 ULPs of nanf )
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Floating point matchers: double
|
||||||
|
Constructor validation
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE_NOTHROW( WithinAbs(1., 0.) )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE_THROWS_AS( WithinAbs(1., -1.), std::domain_error )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE_NOTHROW( WithinULP(1., 0) )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE_THROWS_AS( WithinULP(1., -1), std::domain_error )
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Floating point matchers: float
|
Floating point matchers: float
|
||||||
Margin
|
Margin
|
||||||
@ -2001,6 +2012,29 @@ PASSED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
nanf not ( is within 100.0 of nan or is within 123 ULPs of nanf )
|
nanf not ( is within 100.0 of nan or is within 123 ULPs of nanf )
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Floating point matchers: float
|
||||||
|
Constructor validation
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE_NOTHROW( WithinAbs(1.f, 0.f) )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE_THROWS_AS( WithinAbs(1.f, -1.f), std::domain_error )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE_NOTHROW( WithinULP(1.f, 0) )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE_THROWS_AS( WithinULP(1.f, -1), std::domain_error )
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Greater-than inequalities with different epsilons
|
Greater-than inequalities with different epsilons
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -4585,6 +4619,7 @@ with expansion:
|
|||||||
|
|
||||||
A string sent directly to stdout
|
A string sent directly to stdout
|
||||||
A string sent directly to stderr
|
A string sent directly to stderr
|
||||||
|
A string sent to stderr via clog
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Some simple comparisons between doubles
|
Some simple comparisons between doubles
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -5139,6 +5174,12 @@ PASSED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
1 [30/1]s != 1 fs
|
1 [30/1]s != 1 fs
|
||||||
|
|
||||||
|
ToStringChrono.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE( pico_second != atto_second )
|
||||||
|
with expansion:
|
||||||
|
1 ps != 1 as
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Stringifying std::chrono::time_point<system_clock>
|
Stringifying std::chrono::time_point<system_clock>
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -6439,6 +6480,37 @@ PASSED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
{ 1, 2, 3 } Equals: { 1, 2, 3 }
|
{ 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Vector matchers
|
||||||
|
UnorderedEquals
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
CHECK_THAT( v, UnorderedEquals(v) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
CHECK_THAT( empty, UnorderedEquals(empty) )
|
||||||
|
with expansion:
|
||||||
|
{ } UnorderedEquals: { }
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE_THAT( permuted, UnorderedEquals(v) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE_THAT( permuted, UnorderedEquals(v) )
|
||||||
|
with expansion:
|
||||||
|
{ 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Vector matchers that fail
|
Vector matchers that fail
|
||||||
Contains (element)
|
Contains (element)
|
||||||
@ -6500,6 +6572,33 @@ Matchers.tests.cpp:<line number>: FAILED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
{ 1, 2, 3 } Equals: { }
|
{ 1, 2, 3 } Equals: { }
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Vector matchers that fail
|
||||||
|
UnorderedEquals
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: FAILED:
|
||||||
|
CHECK_THAT( v, UnorderedEquals(empty) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 2, 3 } UnorderedEquals: { }
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: FAILED:
|
||||||
|
CHECK_THAT( empty, UnorderedEquals(v) )
|
||||||
|
with expansion:
|
||||||
|
{ } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: FAILED:
|
||||||
|
CHECK_THAT( permuted, UnorderedEquals(v) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: FAILED:
|
||||||
|
CHECK_THAT( permuted, UnorderedEquals(v) )
|
||||||
|
with expansion:
|
||||||
|
{ 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
When checked exceptions are thrown they can be expected or unexpected
|
When checked exceptions are thrown they can be expected or unexpected
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -7529,7 +7628,7 @@ with expansion:
|
|||||||
""wide load"" == ""wide load""
|
""wide load"" == ""wide load""
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
toString( vectors<has_maker )
|
toString( vectors<has_maker> )
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
ToStringWhich.tests.cpp:<line number>
|
ToStringWhich.tests.cpp:<line number>
|
||||||
...............................................................................
|
...............................................................................
|
||||||
@ -7542,6 +7641,34 @@ with expansion:
|
|||||||
==
|
==
|
||||||
"{ StringMaker<has_maker> }"
|
"{ StringMaker<has_maker> }"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
toString( vectors<has_maker_and_operator> )
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
ToStringWhich.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
ToStringWhich.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker_and_operator> }" )
|
||||||
|
with expansion:
|
||||||
|
"{ StringMaker<has_maker_and_operator> }"
|
||||||
|
==
|
||||||
|
"{ StringMaker<has_maker_and_operator> }"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
toString( vectors<has_operator> )
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
ToStringWhich.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
ToStringWhich.tests.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE( ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" )
|
||||||
|
with expansion:
|
||||||
|
"{ operator<<( has_operator ) }"
|
||||||
|
==
|
||||||
|
"{ operator<<( has_operator ) }"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
toString(enum class w/operator<<)
|
toString(enum class w/operator<<)
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -7987,6 +8114,6 @@ Misc.tests.cpp:<line number>:
|
|||||||
PASSED:
|
PASSED:
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 189 | 135 passed | 50 failed | 4 failed as expected
|
test cases: 191 | 137 passed | 50 failed | 4 failed as expected
|
||||||
assertions: 951 | 824 passed | 106 failed | 21 failed as expected
|
assertions: 970 | 839 passed | 110 failed | 21 failed as expected
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<testsuitesloose text artifact
|
<testsuitesloose text artifact
|
||||||
>
|
>
|
||||||
<testsuite name="<exe-name>" errors="15" failures="92" tests="952" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
<testsuite name="<exe-name>" errors="15" failures="96" tests="971" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||||
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
|
||||||
@ -276,9 +276,11 @@ Message.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Margin" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Margin" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/ULPs" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Floating point matchers: double/ULPs" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Composed" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Composed" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Floating point matchers: double/Constructor validation" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Margin" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Margin" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Floating point matchers: float/Constructor validation" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Greater-than inequalities with different epsilons" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Greater-than inequalities with different epsilons" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="INFO and WARN do not abort tests" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="INFO and WARN do not abort tests" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="INFO gets logged on failure" time="{duration}">
|
<testcase classname="<exe-name>.global" name="INFO gets logged on failure" time="{duration}">
|
||||||
@ -517,6 +519,7 @@ A string sent directly to stdout
|
|||||||
</system-out>
|
</system-out>
|
||||||
<system-err>
|
<system-err>
|
||||||
A string sent directly to stderr
|
A string sent directly to stderr
|
||||||
|
A string sent to stderr via clog
|
||||||
</system-err>
|
</system-err>
|
||||||
</testcase>
|
</testcase>
|
||||||
<testcase classname="<exe-name>.global" name="Some simple comparisons between doubles" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Some simple comparisons between doubles" time="{duration}"/>
|
||||||
@ -605,6 +608,7 @@ Exception.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="Vector matchers/Contains (vector)" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Vector matchers/Contains (vector)" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Vector matchers/Contains (element), composed" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Vector matchers/Contains (element), composed" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Vector matchers/Equals" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Vector matchers/Equals" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Vector matchers/UnorderedEquals" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Vector matchers that fail/Contains (element)" time="{duration}">
|
<testcase classname="<exe-name>.global" name="Vector matchers that fail/Contains (element)" time="{duration}">
|
||||||
<failure message="{ 1, 2, 3 } Contains: -1" type="CHECK_THAT">
|
<failure message="{ 1, 2, 3 } Contains: -1" type="CHECK_THAT">
|
||||||
Matchers.tests.cpp:<line number>
|
Matchers.tests.cpp:<line number>
|
||||||
@ -632,6 +636,20 @@ Matchers.tests.cpp:<line number>
|
|||||||
Matchers.tests.cpp:<line number>
|
Matchers.tests.cpp:<line number>
|
||||||
</failure>
|
</failure>
|
||||||
<failure message="{ 1, 2, 3 } Equals: { }" type="CHECK_THAT">
|
<failure message="{ 1, 2, 3 } Equals: { }" type="CHECK_THAT">
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
</testcase>
|
||||||
|
<testcase classname="<exe-name>.global" name="Vector matchers that fail/UnorderedEquals" time="{duration}">
|
||||||
|
<failure message="{ 1, 2, 3 } UnorderedEquals: { }" type="CHECK_THAT">
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
<failure message="{ } UnorderedEquals: { 1, 2, 3 }" type="CHECK_THAT">
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
<failure message="{ 1, 3 } UnorderedEquals: { 1, 2, 3 }" type="CHECK_THAT">
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
</failure>
|
||||||
|
<failure message="{ 3, 1 } UnorderedEquals: { 1, 2, 3 }" type="CHECK_THAT">
|
||||||
Matchers.tests.cpp:<line number>
|
Matchers.tests.cpp:<line number>
|
||||||
</failure>
|
</failure>
|
||||||
</testcase>
|
</testcase>
|
||||||
@ -796,7 +814,9 @@ Tricky.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="toString on const wchar_t pointer returns the string contents" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="toString on const wchar_t pointer returns the string contents" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="toString on wchar_t const pointer returns the string contents" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="toString on wchar_t const pointer returns the string contents" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="toString on wchar_t returns the string contents" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="toString on wchar_t returns the string contents" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="toString( vectors<has_maker )" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="toString( vectors<has_maker> )" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="toString( vectors<has_maker_and_operator> )" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="toString( vectors<has_operator> )" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="toString(enum class w/operator<<)" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="toString(enum class w/operator<<)" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="toString(enum class)" time="{duration}">
|
<testcase classname="<exe-name>.global" name="toString(enum class)" time="{duration}">
|
||||||
<failure message=""{?}" == "0"" type="CHECK">
|
<failure message=""{?}" == "0"" type="CHECK">
|
||||||
@ -833,6 +853,7 @@ Message from section two
|
|||||||
</system-out>
|
</system-out>
|
||||||
<system-err>
|
<system-err>
|
||||||
A string sent directly to stderr
|
A string sent directly to stderr
|
||||||
|
A string sent to stderr via clog
|
||||||
</system-err>
|
</system-err>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
|
@ -819,7 +819,7 @@
|
|||||||
<TestCase name="Assertions then sections" tags="[Tricky]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<TestCase name="Assertions then sections" tags="[Tricky]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
Catch::alwaysTrue()
|
true
|
||||||
</Original>
|
</Original>
|
||||||
<Expanded>
|
<Expanded>
|
||||||
true
|
true
|
||||||
@ -828,7 +828,7 @@
|
|||||||
<Section name="A section" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<Section name="A section" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
Catch::alwaysTrue()
|
true
|
||||||
</Original>
|
</Original>
|
||||||
<Expanded>
|
<Expanded>
|
||||||
true
|
true
|
||||||
@ -837,7 +837,7 @@
|
|||||||
<Section name="Another section" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<Section name="Another section" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
Catch::alwaysTrue()
|
true
|
||||||
</Original>
|
</Original>
|
||||||
<Expanded>
|
<Expanded>
|
||||||
true
|
true
|
||||||
@ -849,7 +849,7 @@
|
|||||||
</Section>
|
</Section>
|
||||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
Catch::alwaysTrue()
|
true
|
||||||
</Original>
|
</Original>
|
||||||
<Expanded>
|
<Expanded>
|
||||||
true
|
true
|
||||||
@ -858,7 +858,7 @@
|
|||||||
<Section name="A section" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<Section name="A section" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
Catch::alwaysTrue()
|
true
|
||||||
</Original>
|
</Original>
|
||||||
<Expanded>
|
<Expanded>
|
||||||
true
|
true
|
||||||
@ -867,7 +867,7 @@
|
|||||||
<Section name="Another other section" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<Section name="Another other section" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
Catch::alwaysTrue()
|
true
|
||||||
</Original>
|
</Original>
|
||||||
<Expanded>
|
<Expanded>
|
||||||
true
|
true
|
||||||
@ -1273,7 +1273,7 @@
|
|||||||
</Expression>
|
</Expression>
|
||||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
td >= Approx(10.0)
|
td >= Approx(td)
|
||||||
</Original>
|
</Original>
|
||||||
<Expanded>
|
<Expanded>
|
||||||
StrongDoubleTypedef(10) >= Approx( 10.0 )
|
StrongDoubleTypedef(10) >= Approx( 10.0 )
|
||||||
@ -1281,7 +1281,7 @@
|
|||||||
</Expression>
|
</Expression>
|
||||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
Approx(10.0) >= td
|
Approx(td) >= td
|
||||||
</Original>
|
</Original>
|
||||||
<Expanded>
|
<Expanded>
|
||||||
Approx( 10.0 ) >= StrongDoubleTypedef(10)
|
Approx( 10.0 ) >= StrongDoubleTypedef(10)
|
||||||
@ -2142,6 +2142,41 @@
|
|||||||
</Expression>
|
</Expression>
|
||||||
<OverallResults successes="3" failures="0" expectedFailures="0"/>
|
<OverallResults successes="3" failures="0" expectedFailures="0"/>
|
||||||
</Section>
|
</Section>
|
||||||
|
<Section name="Constructor validation" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_NOTHROW" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
WithinAbs(1., 0.)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
WithinAbs(1., 0.)
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THROWS_AS" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
WithinAbs(1., -1.), std::domain_error
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
WithinAbs(1., -1.), std::domain_error
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_NOTHROW" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
WithinULP(1., 0)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
WithinULP(1., 0)
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THROWS_AS" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
WithinULP(1., -1), std::domain_error
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
WithinULP(1., -1), std::domain_error
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResults successes="4" failures="0" expectedFailures="0"/>
|
||||||
|
</Section>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<TestCase name="Floating point matchers: float" tags="[floating-point][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
<TestCase name="Floating point matchers: float" tags="[floating-point][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
@ -2282,6 +2317,41 @@
|
|||||||
</Expression>
|
</Expression>
|
||||||
<OverallResults successes="3" failures="0" expectedFailures="0"/>
|
<OverallResults successes="3" failures="0" expectedFailures="0"/>
|
||||||
</Section>
|
</Section>
|
||||||
|
<Section name="Constructor validation" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_NOTHROW" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
WithinAbs(1.f, 0.f)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
WithinAbs(1.f, 0.f)
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THROWS_AS" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
WithinAbs(1.f, -1.f), std::domain_error
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
WithinAbs(1.f, -1.f), std::domain_error
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_NOTHROW" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
WithinULP(1.f, 0)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
WithinULP(1.f, 0)
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THROWS_AS" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
WithinULP(1.f, -1), std::domain_error
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
WithinULP(1.f, -1), std::domain_error
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResults successes="4" failures="0" expectedFailures="0"/>
|
||||||
|
</Section>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<TestCase name="Greater-than inequalities with different epsilons" tags="[Approx]" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
|
<TestCase name="Greater-than inequalities with different epsilons" tags="[Approx]" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
|
||||||
@ -5260,6 +5330,7 @@ A string sent directly to stdout
|
|||||||
</StdOut>
|
</StdOut>
|
||||||
<StdErr>
|
<StdErr>
|
||||||
A string sent directly to stderr
|
A string sent directly to stderr
|
||||||
|
A string sent to stderr via clog
|
||||||
</StdErr>
|
</StdErr>
|
||||||
</OverallResult>
|
</OverallResult>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
@ -5878,6 +5949,14 @@ Message from section two
|
|||||||
1 [30/1]s != 1 fs
|
1 [30/1]s != 1 fs
|
||||||
</Expanded>
|
</Expanded>
|
||||||
</Expression>
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringChrono.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
pico_second != atto_second
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 ps != 1 as
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<TestCase name="Stringifying std::chrono::time_point<system_clock>" tags="[chrono][toString]" filename="projects/<exe-name>/UsageTests/ToStringChrono.tests.cpp" >
|
<TestCase name="Stringifying std::chrono::time_point<system_clock>" tags="[chrono][toString]" filename="projects/<exe-name>/UsageTests/ToStringChrono.tests.cpp" >
|
||||||
@ -7298,6 +7377,41 @@ Message from section two
|
|||||||
</Expression>
|
</Expression>
|
||||||
<OverallResults successes="3" failures="0" expectedFailures="0"/>
|
<OverallResults successes="3" failures="0" expectedFailures="0"/>
|
||||||
</Section>
|
</Section>
|
||||||
|
<Section name="UnorderedEquals" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
v, UnorderedEquals(v)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
empty, UnorderedEquals(empty)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ } UnorderedEquals: { }
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
permuted, UnorderedEquals(v)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
permuted, UnorderedEquals(v)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResults successes="4" failures="0" expectedFailures="0"/>
|
||||||
|
</Section>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<TestCase name="Vector matchers that fail" tags="[.][failing][matchers][vector]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
<TestCase name="Vector matchers that fail" tags="[.][failing][matchers][vector]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
@ -7374,6 +7488,41 @@ Message from section two
|
|||||||
</Expression>
|
</Expression>
|
||||||
<OverallResults successes="0" failures="4" expectedFailures="0"/>
|
<OverallResults successes="0" failures="4" expectedFailures="0"/>
|
||||||
</Section>
|
</Section>
|
||||||
|
<Section name="UnorderedEquals" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
v, UnorderedEquals(empty)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1, 2, 3 } UnorderedEquals: { }
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
empty, UnorderedEquals(v)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
permuted, UnorderedEquals(v)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
permuted, UnorderedEquals(v)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResults successes="0" failures="4" expectedFailures="0"/>
|
||||||
|
</Section>
|
||||||
<OverallResult success="false"/>
|
<OverallResult success="false"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<TestCase name="When checked exceptions are thrown they can be expected or unexpected" tags="[!throws]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
|
<TestCase name="When checked exceptions are thrown they can be expected or unexpected" tags="[!throws]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
|
||||||
@ -8409,7 +8558,7 @@ loose text artifact
|
|||||||
</Expression>
|
</Expression>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<TestCase name="toString( vectors<has_maker )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
<TestCase name="toString( vectors<has_maker> )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }"
|
::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }"
|
||||||
@ -8422,6 +8571,32 @@ loose text artifact
|
|||||||
</Expression>
|
</Expression>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
|
<TestCase name="toString( vectors<has_maker_and_operator> )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker_and_operator> }"
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
"{ StringMaker<has_maker_and_operator> }"
|
||||||
|
==
|
||||||
|
"{ StringMaker<has_maker_and_operator> }"
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
|
<TestCase name="toString( vectors<has_operator> )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }"
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
"{ operator<<( has_operator ) }"
|
||||||
|
==
|
||||||
|
"{ operator<<( has_operator ) }"
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
<TestCase name="toString(enum class w/operator<<)" tags="[enum][enumClass][toString]" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
<TestCase name="toString(enum class w/operator<<)" tags="[enum][enumClass][toString]" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||||
<Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
<Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
@ -8863,7 +9038,7 @@ loose text artifact
|
|||||||
</Section>
|
</Section>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<OverallResults successes="824" failures="107" expectedFailures="21"/>
|
<OverallResults successes="839" failures="111" expectedFailures="21"/>
|
||||||
</Group>
|
</Group>
|
||||||
<OverallResults successes="824" failures="106" expectedFailures="21"/>
|
<OverallResults successes="839" failures="110" expectedFailures="21"/>
|
||||||
</Catch>
|
</Catch>
|
||||||
|
@ -189,8 +189,8 @@ TEST_CASE( "Comparison with explicitly convertible types", "[Approx]" )
|
|||||||
REQUIRE(Approx(9.0) <= td);
|
REQUIRE(Approx(9.0) <= td);
|
||||||
|
|
||||||
REQUIRE(td >= Approx(9.0));
|
REQUIRE(td >= Approx(9.0));
|
||||||
REQUIRE(td >= Approx(10.0));
|
REQUIRE(td >= Approx(td));
|
||||||
REQUIRE(Approx(10.0) >= td);
|
REQUIRE(Approx(td) >= td);
|
||||||
REQUIRE(Approx(11.0) >= td);
|
REQUIRE(Approx(11.0) >= td);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,11 @@
|
|||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
# pragma clang diagnostic push
|
# pragma clang diagnostic push
|
||||||
# pragma clang diagnostic ignored "-Wpadded"
|
# pragma clang diagnostic ignored "-Wpadded"
|
||||||
|
// Wdouble-promotion is not supported until 3.8
|
||||||
|
# if (__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ > 7)
|
||||||
# pragma clang diagnostic ignored "-Wdouble-promotion"
|
# pragma clang diagnostic ignored "-Wdouble-promotion"
|
||||||
# endif
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
@ -12,11 +12,12 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(disable:4702) // Unreachable code -- MSVC 19 (VS 2015) sees right through the indirection
|
#pragma warning(disable:4702) // Unreachable code -- uncoditional throws and so on
|
||||||
#endif
|
#endif
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wweak-vtables"
|
#pragma clang diagnostic ignored "-Wweak-vtables"
|
||||||
|
#pragma clang diagnostic ignored "-Wmissing-noreturn"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace { namespace ExceptionTests {
|
namespace { namespace ExceptionTests {
|
||||||
@ -24,8 +25,7 @@ namespace { namespace ExceptionTests {
|
|||||||
#ifndef EXCEPTION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
|
#ifndef EXCEPTION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
|
||||||
#define EXCEPTION_TEST_HELPERS_INCLUDED
|
#define EXCEPTION_TEST_HELPERS_INCLUDED
|
||||||
|
|
||||||
inline int thisThrows() {
|
int thisThrows() {
|
||||||
if( Catch::alwaysTrue() )
|
|
||||||
throw std::domain_error( "expected exception" );
|
throw std::domain_error( "expected exception" );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ int thisDoesntThrow() {
|
|||||||
|
|
||||||
class CustomException {
|
class CustomException {
|
||||||
public:
|
public:
|
||||||
CustomException( const std::string& msg )
|
explicit CustomException( const std::string& msg )
|
||||||
: m_msg( msg )
|
: m_msg( msg )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -50,10 +50,10 @@ private:
|
|||||||
|
|
||||||
class CustomStdException : public std::exception {
|
class CustomStdException : public std::exception {
|
||||||
public:
|
public:
|
||||||
CustomStdException( const std::string& msg )
|
explicit CustomStdException( const std::string& msg )
|
||||||
: m_msg( msg )
|
: m_msg( msg )
|
||||||
{}
|
{}
|
||||||
~CustomStdException() noexcept {}
|
~CustomStdException() noexcept override {}
|
||||||
|
|
||||||
std::string getMessage() const {
|
std::string getMessage() const {
|
||||||
return m_msg;
|
return m_msg;
|
||||||
@ -63,8 +63,7 @@ private:
|
|||||||
std::string m_msg;
|
std::string m_msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void throwCustom() {
|
[[noreturn]] void throwCustom() {
|
||||||
if( Catch::alwaysTrue() )
|
|
||||||
throw CustomException( "custom exception - not std" );
|
throw CustomException( "custom exception - not std" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,19 +82,16 @@ TEST_CASE( "Expected exceptions that don't throw or unexpected exceptions fail t
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE( "When unchecked exceptions are thrown directly they are always failures", "[.][failing][!throws]" ) {
|
TEST_CASE( "When unchecked exceptions are thrown directly they are always failures", "[.][failing][!throws]" ) {
|
||||||
if( Catch::alwaysTrue() )
|
|
||||||
throw std::domain_error( "unexpected exception" );
|
throw std::domain_error( "unexpected exception" );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE( "An unchecked exception reports the line of the last assertion", "[.][failing][!throws]" ) {
|
TEST_CASE( "An unchecked exception reports the line of the last assertion", "[.][failing][!throws]" ) {
|
||||||
CHECK( 1 == 1 );
|
CHECK( 1 == 1 );
|
||||||
if( Catch::alwaysTrue() )
|
|
||||||
throw std::domain_error( "unexpected exception" );
|
throw std::domain_error( "unexpected exception" );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE( "When unchecked exceptions are thrown from sections they are always failures", "[.][failing][!throws]" ) {
|
TEST_CASE( "When unchecked exceptions are thrown from sections they are always failures", "[.][failing][!throws]" ) {
|
||||||
SECTION( "section name" ) {
|
SECTION( "section name" ) {
|
||||||
if( Catch::alwaysTrue() )
|
|
||||||
throw std::domain_error("unexpected exception");
|
throw std::domain_error("unexpected exception");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,12 +135,10 @@ CATCH_TRANSLATE_EXCEPTION( double& ex ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Non-std exceptions can be translated", "[.][failing][!throws]" ) {
|
TEST_CASE("Non-std exceptions can be translated", "[.][failing][!throws]" ) {
|
||||||
if( Catch::alwaysTrue() )
|
|
||||||
throw CustomException( "custom exception" );
|
throw CustomException( "custom exception" );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Custom std-exceptions can be custom translated", "[.][failing][!throws]" ) {
|
TEST_CASE("Custom std-exceptions can be custom translated", "[.][failing][!throws]" ) {
|
||||||
if( Catch::alwaysTrue() )
|
|
||||||
throw CustomException( "custom std exception" );
|
throw CustomException( "custom std exception" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +151,6 @@ TEST_CASE( "Custom exceptions can be translated when testing for throwing as som
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE( "Unexpected exceptions can be translated", "[.][failing][!throws]" ) {
|
TEST_CASE( "Unexpected exceptions can be translated", "[.][failing][!throws]" ) {
|
||||||
if( Catch::alwaysTrue() )
|
|
||||||
throw double( 3.14 );
|
throw double( 3.14 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
@ -216,6 +217,17 @@ namespace { namespace MatchersTests {
|
|||||||
v2.push_back(3);
|
v2.push_back(3);
|
||||||
CHECK_THAT(v, Equals(v2));
|
CHECK_THAT(v, Equals(v2));
|
||||||
}
|
}
|
||||||
|
SECTION("UnorderedEquals") {
|
||||||
|
CHECK_THAT(v, UnorderedEquals(v));
|
||||||
|
CHECK_THAT(empty, UnorderedEquals(empty));
|
||||||
|
|
||||||
|
auto permuted = v;
|
||||||
|
std::next_permutation(begin(permuted), end(permuted));
|
||||||
|
REQUIRE_THAT(permuted, UnorderedEquals(v));
|
||||||
|
|
||||||
|
std::reverse(begin(permuted), end(permuted));
|
||||||
|
REQUIRE_THAT(permuted, UnorderedEquals(v));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Vector matchers that fail", "[matchers][vector][.][failing]") {
|
TEST_CASE("Vector matchers that fail", "[matchers][vector][.][failing]") {
|
||||||
@ -247,6 +259,18 @@ namespace { namespace MatchersTests {
|
|||||||
CHECK_THAT(empty, Equals(v));
|
CHECK_THAT(empty, Equals(v));
|
||||||
CHECK_THAT(v, Equals(empty));
|
CHECK_THAT(v, Equals(empty));
|
||||||
}
|
}
|
||||||
|
SECTION("UnorderedEquals") {
|
||||||
|
CHECK_THAT(v, UnorderedEquals(empty));
|
||||||
|
CHECK_THAT(empty, UnorderedEquals(v));
|
||||||
|
|
||||||
|
auto permuted = v;
|
||||||
|
std::next_permutation(begin(permuted), end(permuted));
|
||||||
|
permuted.pop_back();
|
||||||
|
CHECK_THAT(permuted, UnorderedEquals(v));
|
||||||
|
|
||||||
|
std::reverse(begin(permuted), end(permuted));
|
||||||
|
CHECK_THAT(permuted, UnorderedEquals(v));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Exception matchers that succeed", "[matchers][exceptions][!throws]") {
|
TEST_CASE("Exception matchers that succeed", "[matchers][exceptions][!throws]") {
|
||||||
@ -298,6 +322,13 @@ namespace { namespace MatchersTests {
|
|||||||
|
|
||||||
REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)));
|
REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)));
|
||||||
}
|
}
|
||||||
|
SECTION("Constructor validation") {
|
||||||
|
REQUIRE_NOTHROW(WithinAbs(1.f, 0.f));
|
||||||
|
REQUIRE_THROWS_AS(WithinAbs(1.f, -1.f), std::domain_error);
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(WithinULP(1.f, 0));
|
||||||
|
REQUIRE_THROWS_AS(WithinULP(1.f, -1), std::domain_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Floating point matchers: double", "[matchers][floating-point]") {
|
TEST_CASE("Floating point matchers: double", "[matchers][floating-point]") {
|
||||||
@ -328,6 +359,13 @@ namespace { namespace MatchersTests {
|
|||||||
|
|
||||||
REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)));
|
REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)));
|
||||||
}
|
}
|
||||||
|
SECTION("Constructor validation") {
|
||||||
|
REQUIRE_NOTHROW(WithinAbs(1., 0.));
|
||||||
|
REQUIRE_THROWS_AS(WithinAbs(1., -1.), std::domain_error);
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(WithinULP(1., 0));
|
||||||
|
REQUIRE_THROWS_AS(WithinULP(1., -1), std::domain_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} } // namespace MatchersTests
|
} } // namespace MatchersTests
|
||||||
|
@ -57,7 +57,9 @@ struct AutoTestReg {
|
|||||||
REGISTER_TEST_CASE( manuallyRegisteredTestFunction, "ManuallyRegistered" );
|
REGISTER_TEST_CASE( manuallyRegisteredTestFunction, "ManuallyRegistered" );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
||||||
static AutoTestReg autoTestReg;
|
static AutoTestReg autoTestReg;
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -146,8 +148,8 @@ TEST_CASE( "looped tests", "[.][failing]" ) {
|
|||||||
|
|
||||||
TEST_CASE( "Sends stuff to stdout and stderr", "[.]" ) {
|
TEST_CASE( "Sends stuff to stdout and stderr", "[.]" ) {
|
||||||
std::cout << "A string sent directly to stdout" << std::endl;
|
std::cout << "A string sent directly to stdout" << std::endl;
|
||||||
|
|
||||||
std::cerr << "A string sent directly to stderr" << std::endl;
|
std::cerr << "A string sent directly to stderr" << std::endl;
|
||||||
|
std::clog << "A string sent to stderr via clog" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE( "null strings" ) {
|
TEST_CASE( "null strings" ) {
|
||||||
@ -301,13 +303,13 @@ TEST_CASE( "toString on const wchar_t pointer returns the string contents", "[to
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE( "toString on wchar_t const pointer returns the string contents", "[toString]" ) {
|
TEST_CASE( "toString on wchar_t const pointer returns the string contents", "[toString]" ) {
|
||||||
wchar_t * const s = const_cast<wchar_t* const>( L"wide load" );
|
auto const s = const_cast<wchar_t* const>( L"wide load" );
|
||||||
std::string result = ::Catch::Detail::stringify( s );
|
std::string result = ::Catch::Detail::stringify( s );
|
||||||
CHECK( result == "\"wide load\"" );
|
CHECK( result == "\"wide load\"" );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) {
|
TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) {
|
||||||
wchar_t * s = const_cast<wchar_t*>( L"wide load" );
|
auto s = const_cast<wchar_t*>( L"wide load" );
|
||||||
std::string result = ::Catch::Detail::stringify( s );
|
std::string result = ::Catch::Detail::stringify( s );
|
||||||
CHECK( result == "\"wide load\"" );
|
CHECK( result == "\"wide load\"" );
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,11 @@ TEST_CASE("Stringifying std::chrono::duration helpers", "[toString][chrono]") {
|
|||||||
|
|
||||||
TEST_CASE("Stringifying std::chrono::duration with weird ratios", "[toString][chrono]") {
|
TEST_CASE("Stringifying std::chrono::duration with weird ratios", "[toString][chrono]") {
|
||||||
std::chrono::duration<int64_t, std::ratio<30>> half_minute(1);
|
std::chrono::duration<int64_t, std::ratio<30>> half_minute(1);
|
||||||
|
std::chrono::duration<int64_t, std::ratio<1, 1000000000000>> pico_second(1);
|
||||||
std::chrono::duration<int64_t, std::ratio<1, 1000000000000000>> femto_second(1);
|
std::chrono::duration<int64_t, std::ratio<1, 1000000000000000>> femto_second(1);
|
||||||
|
std::chrono::duration<int64_t, std::ratio<1, 1000000000000000000>> atto_second(1);
|
||||||
REQUIRE(half_minute != femto_second);
|
REQUIRE(half_minute != femto_second);
|
||||||
|
REQUIRE(pico_second != atto_second);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Stringifying std::chrono::time_point<system_clock>", "[toString][chrono]") {
|
TEST_CASE("Stringifying std::chrono::time_point<system_clock>", "[toString][chrono]") {
|
||||||
|
@ -55,19 +55,19 @@ TEST_CASE( "stringify( has_maker_and_toString )", "[.][toString]" ) {
|
|||||||
// Vectors...
|
// Vectors...
|
||||||
|
|
||||||
// Don't run this in approval tests as it is sensitive to two phase lookup differences
|
// Don't run this in approval tests as it is sensitive to two phase lookup differences
|
||||||
TEST_CASE( "toString( vectors<has_toString )", "[.][toString][!nonportable]" ) {
|
TEST_CASE( "toString( vectors<has_operator> )", "[toString]" ) {
|
||||||
std::vector<has_operator> v(1);
|
std::vector<has_operator> v(1);
|
||||||
REQUIRE( ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" );
|
REQUIRE( ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE( "toString( vectors<has_maker )", "[toString]" ) {
|
TEST_CASE( "toString( vectors<has_maker> )", "[toString]" ) {
|
||||||
std::vector<has_maker> v(1);
|
std::vector<has_maker> v(1);
|
||||||
REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" );
|
REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Don't run this in approval tests as it is sensitive to two phase lookup differences
|
// Don't run this in approval tests as it is sensitive to two phase lookup differences
|
||||||
TEST_CASE( "toString( vectors<has_maker_and_toString )", "[.][toString][!nonportable]" ) {
|
TEST_CASE( "toString( vectors<has_maker_and_operator> )", "[toString]" ) {
|
||||||
std::vector<has_maker_and_operator> v(1);
|
std::vector<has_maker_and_operator> v(1);
|
||||||
REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker_and_toString> }" );
|
REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker_and_operator> }" );
|
||||||
}
|
}
|
||||||
|
@ -298,19 +298,19 @@ TEST_CASE( "Assertions then sections", "[Tricky]" )
|
|||||||
// This was causing a failure due to the way the console reporter was handling
|
// This was causing a failure due to the way the console reporter was handling
|
||||||
// the current section
|
// the current section
|
||||||
|
|
||||||
REQUIRE( Catch::alwaysTrue() );
|
REQUIRE( true );
|
||||||
|
|
||||||
SECTION( "A section" )
|
SECTION( "A section" )
|
||||||
{
|
{
|
||||||
REQUIRE( Catch::alwaysTrue() );
|
REQUIRE( true );
|
||||||
|
|
||||||
SECTION( "Another section" )
|
SECTION( "Another section" )
|
||||||
{
|
{
|
||||||
REQUIRE( Catch::alwaysTrue() );
|
REQUIRE( true );
|
||||||
}
|
}
|
||||||
SECTION( "Another other section" )
|
SECTION( "Another other section" )
|
||||||
{
|
{
|
||||||
REQUIRE( Catch::alwaysTrue() );
|
REQUIRE( true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,6 +167,8 @@ def approve(baseName, args):
|
|||||||
print("Running approvals against executable:")
|
print("Running approvals against executable:")
|
||||||
print(" " + cmdPath)
|
print(" " + cmdPath)
|
||||||
|
|
||||||
|
|
||||||
|
### Keep default reporters here
|
||||||
# Standard console reporter
|
# Standard console reporter
|
||||||
approve("console.std", ["~[!nonportable]~[!benchmark]~[approvals]", "--order", "lex"])
|
approve("console.std", ["~[!nonportable]~[!benchmark]~[approvals]", "--order", "lex"])
|
||||||
# console reporter, include passes, warn about No Assertions
|
# console reporter, include passes, warn about No Assertions
|
||||||
@ -177,6 +179,8 @@ approve("console.swa4", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w",
|
|||||||
approve("junit.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "junit", "--order", "lex"])
|
approve("junit.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "junit", "--order", "lex"])
|
||||||
# xml reporter, include passes, warn about No Assertions
|
# xml reporter, include passes, warn about No Assertions
|
||||||
approve("xml.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "xml", "--order", "lex"])
|
approve("xml.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "xml", "--order", "lex"])
|
||||||
|
# compact reporter, include passes, warn about No Assertions
|
||||||
|
approve('compact.sw', ['~[!nonportable]~[!benchmark]~[approvals]', '-s', '-w', 'NoAssertions', '-r', 'compact', '--order', 'lex'])
|
||||||
|
|
||||||
if overallResult != 0:
|
if overallResult != 0:
|
||||||
print("If these differences are expected, run approve.py to approve new baselines.")
|
print("If these differences are expected, run approve.py to approve new baselines.")
|
||||||
|
Loading…
Reference in New Issue
Block a user