forked from catchorg/Catch2
Compare commits
111 Commits
Author | SHA1 | Date | |
---|---|---|---|
2a3606f8e3 | |||
a6cf19abff | |||
06586b7180 | |||
93b3d2cb8f | |||
a90473df28 | |||
c9d9699ca8 | |||
296955c437 | |||
664cbf702c | |||
fb6700df54 | |||
da6c2a6914 | |||
9c07718b5f | |||
5ca44b6872 | |||
a04bd6d436 | |||
784f6dfb34 | |||
7818e2666d | |||
cd30dd1a70 | |||
8e8c0c1675 | |||
b6e7c9bd7a | |||
180d9242f5 | |||
b7bd52cc98 | |||
b07a2bdf87 | |||
c03e8fce92 | |||
27640a5a96 | |||
dd3867bbcd | |||
387f8d254d | |||
c65eccd68e | |||
61c5675c11 | |||
70e4af9d44 | |||
8f41bdb92d | |||
7fa5d9ca94 | |||
feaf355489 | |||
2ce6c74f8f | |||
9688891868 | |||
4f21bb72ff | |||
b435e0d7c7 | |||
ba0a09fd9e | |||
7e4038d848 | |||
92d714ee12 | |||
705a1bf527 | |||
d5613fb18a | |||
62875c857e | |||
ec2074e558 | |||
7575749e56 | |||
8a2ff20982 | |||
d3377c791d | |||
c5dfa73d56 | |||
d65091fa06 | |||
7a22bad763 | |||
8ebe94ca2e | |||
106d7e2a74 | |||
a53ea30723 | |||
8d380a7399 | |||
3083de9ea6 | |||
431e8d06e7 | |||
6f32db35af | |||
7013e388f7 | |||
0270afb21b | |||
df7c5622b9 | |||
ee67ac6b7c | |||
8a14af701e | |||
07c6bfc3b9 | |||
616f7235ef | |||
396ecf6021 | |||
3491804598 | |||
6234e3d54d | |||
a6cdcd43aa | |||
dcab8a5971 | |||
017a63da62 | |||
b90d0b7267 | |||
efba988ccc | |||
004228efb2 | |||
e0aaba6cf8 | |||
a09bef23ed | |||
3e018ef131 | |||
adb66f55a7 | |||
377c9a746d | |||
ea48ae0f75 | |||
2d1739b429 | |||
1c59034be4 | |||
52a84788e0 | |||
3e328f55fc | |||
b18e67522f | |||
4b086bd5b5 | |||
aac594aae3 | |||
a49fa0edbe | |||
d271683c14 | |||
0bb8e1247e | |||
32d97caf42 | |||
bc93b29789 | |||
df5cf2d323 | |||
b62c0256b2 | |||
1ea84cb734 | |||
2a5d3736e8 | |||
3dcc923351 | |||
589c40077b | |||
d4e0b1d093 | |||
b8443e67da | |||
5604ec7266 | |||
6f012f2d1d | |||
98e61c31df | |||
e641485132 | |||
a3ceb8f007 | |||
b819432271 | |||
9ceae8f51f | |||
5ffc8a84cd | |||
6e0fa4be68 | |||
a0ada2e935 | |||
e4694f58da | |||
e8b31108d6 | |||
d8f45cd5f1 | |||
3afd077b55 |
3
.github/pull_request_template.md
vendored
3
.github/pull_request_template.md
vendored
@ -2,6 +2,9 @@
|
||||
Please do not submit pull requests changing the `version.hpp`
|
||||
or the single-include `catch.hpp` file, these are changed
|
||||
only when a new release is made.
|
||||
|
||||
Before submitting a PR you should probably read the contributor documentation
|
||||
at docs/contributing.md. It will tell you how to properly test your changes.
|
||||
-->
|
||||
|
||||
|
||||
|
18
.travis.yml
18
.travis.yml
@ -192,15 +192,15 @@ matrix:
|
||||
env: COMPILER='g++-6' BUILD_TYPE='Debug' CPP14=1
|
||||
|
||||
# 4b/ Linux C++14 Clang builds
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons: *clang38
|
||||
env: COMPILER='clang++-3.8' BUILD_TYPE='Release' CPP14=1
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons: *clang38
|
||||
env: COMPILER='clang++-3.8' BUILD_TYPE='Debug' CPP14=1
|
||||
# - os: linux
|
||||
# compiler: clang
|
||||
# addons: *clang38
|
||||
# env: COMPILER='clang++-3.8' BUILD_TYPE='Release' CPP14=1
|
||||
#
|
||||
# - os: linux
|
||||
# compiler: clang
|
||||
# addons: *clang38
|
||||
# env: COMPILER='clang++-3.8' BUILD_TYPE='Debug' CPP14=1
|
||||
|
||||
|
||||
# 5/ OSX Clang Builds
|
||||
|
@ -19,6 +19,10 @@ elseif(USE_CPP14)
|
||||
set(CMAKE_CXX_FLAGS "-std=c++14 ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
if(USE_WMAIN)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wmainCRTStartup")
|
||||
endif()
|
||||
|
||||
#checks that the given hard-coded list contains all headers + sources in the given folder
|
||||
function(CheckFileList LIST_VAR FOLDER)
|
||||
set(MESSAGE " should be added to the variable ${LIST_VAR}")
|
||||
@ -55,6 +59,7 @@ set(TEST_SOURCES
|
||||
${SELF_TEST_DIR}/CmdLineTests.cpp
|
||||
${SELF_TEST_DIR}/CompilationTests.cpp
|
||||
${SELF_TEST_DIR}/ConditionTests.cpp
|
||||
${SELF_TEST_DIR}/DecompositionTests.cpp
|
||||
${SELF_TEST_DIR}/EnumToString.cpp
|
||||
${SELF_TEST_DIR}/ExceptionTests.cpp
|
||||
${SELF_TEST_DIR}/GeneratorTests.cpp
|
||||
@ -245,28 +250,35 @@ SOURCE_GROUP("Benchmarks" FILES ${BENCH_SOURCES})
|
||||
|
||||
# configure the executable
|
||||
include_directories(${HEADER_DIR})
|
||||
add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${HEADERS})
|
||||
add_executable(Benchmark ${BENCH_SOURCES} ${HEADERS})
|
||||
|
||||
# Add desired warnings
|
||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
|
||||
target_compile_options( SelfTest PRIVATE -Wall -Wextra )
|
||||
target_compile_options( Benchmark PRIVATE -Wall -Wextra )
|
||||
endif()
|
||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
|
||||
target_compile_options( SelfTest PRIVATE /W4 /w44265 /WX )
|
||||
target_compile_options( Benchmark PRIVATE /W4 )
|
||||
endif()
|
||||
# Projects consuming Catch via ExternalProject_Add might want to use install step
|
||||
# without building all of our selftests.
|
||||
if (NOT NO_SELFTEST)
|
||||
add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${HEADERS})
|
||||
add_executable(Benchmark ${BENCH_SOURCES} ${HEADERS})
|
||||
|
||||
# Add desired warnings
|
||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
|
||||
target_compile_options( SelfTest PRIVATE -Wall -Wextra )
|
||||
target_compile_options( Benchmark PRIVATE -Wall -Wextra )
|
||||
endif()
|
||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
|
||||
target_compile_options( SelfTest PRIVATE /W4 /w44265 /WX )
|
||||
target_compile_options( Benchmark PRIVATE /W4 )
|
||||
endif()
|
||||
|
||||
|
||||
# configure unit tests via CTest
|
||||
enable_testing()
|
||||
add_test(NAME RunTests COMMAND SelfTest)
|
||||
# configure unit tests via CTest
|
||||
enable_testing()
|
||||
add_test(NAME RunTests COMMAND SelfTest)
|
||||
|
||||
add_test(NAME ListTests COMMAND SelfTest --list-tests)
|
||||
set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases")
|
||||
add_test(NAME ListTests COMMAND SelfTest --list-tests)
|
||||
set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases")
|
||||
|
||||
add_test(NAME ListTags COMMAND SelfTest --list-tags)
|
||||
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
|
||||
|
||||
endif() # !NO_SELFTEST
|
||||
|
||||
add_test(NAME ListTags COMMAND SelfTest --list-tags)
|
||||
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
|
||||
|
||||
install(DIRECTORY "single_include/" DESTINATION "include/catch")
|
||||
|
46
CODE_OF_CONDUCT.md
Normal file
46
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,46 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at github@philnash.me. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
@ -3,8 +3,9 @@
|
||||
[](https://github.com/philsquared/catch/releases)
|
||||
[](https://travis-ci.org/philsquared/Catch)
|
||||
[](https://ci.appveyor.com/project/philsquared/catch/branch/master)
|
||||
[](https://wandbox.org/permlink/EyEbEIfp8CnnjguW)
|
||||
|
||||
<a href="https://github.com/philsquared/Catch/releases/download/v1.9.2/catch.hpp">The latest, single header, version can be downloaded directly using this link</a>
|
||||
<a href="https://github.com/philsquared/Catch/releases/download/v1.11.0/catch.hpp">The latest, single header, version can be downloaded directly using this link</a>
|
||||
|
||||
## What's the Catch?
|
||||
|
||||
@ -21,3 +22,7 @@ This documentation comprises these three parts:
|
||||
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/philsquared/Catch/issues)
|
||||
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)
|
||||
* See [who else is using Catch](docs/opensource-users.md)
|
||||
|
||||
## Help us out
|
||||
We're currently running [a survey](https://www.surveymonkey.co.uk/r/TLLYQJW) to help us shape the future of Catch.
|
||||
Please take a few moments to fill it out (there's only ten questions).
|
||||
|
@ -9,7 +9,13 @@ os:
|
||||
environment:
|
||||
matrix:
|
||||
- additional_flags: "/permissive- /std:c++latest"
|
||||
wmain: 0
|
||||
|
||||
- additional_flags: ""
|
||||
wmain: 0
|
||||
|
||||
- additional_flags: "/D_UNICODE /DUNICODE"
|
||||
wmain: 1
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
@ -42,7 +48,7 @@ configuration:
|
||||
#Cmake will autodetect the compiler, but we set the arch
|
||||
before_build:
|
||||
- set CXXFLAGS=%additional_flags%
|
||||
- cmake -H. -BBuild -A%PLATFORM%
|
||||
- cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain%
|
||||
|
||||
# build with MSBuild
|
||||
build:
|
||||
|
19
conanfile.py
Normal file
19
conanfile.py
Normal file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
from conans import ConanFile
|
||||
|
||||
|
||||
class CatchConan(ConanFile):
|
||||
name = "Catch"
|
||||
version = "1.11.0"
|
||||
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
|
||||
author = "philsquared"
|
||||
generators = "cmake"
|
||||
exports_sources = "single_include/*"
|
||||
url = "https://github.com/philsquared/Catch"
|
||||
license = "Boost Software License - Version 1.0. http://www.boost.org/LICENSE_1_0.txt"
|
||||
|
||||
def package(self):
|
||||
self.copy(pattern="catch.hpp", src="single_include", dst="include")
|
||||
|
||||
def package_id(self):
|
||||
self.info.header_only()
|
@ -25,13 +25,39 @@
|
||||
# #
|
||||
# include(ParseAndAddCatchTests) #
|
||||
# ParseAndAddCatchTests(${PROJECT_NAME}) #
|
||||
# #
|
||||
# The following variables affect the behavior of the script: #
|
||||
# #
|
||||
# PARSE_CATCH_TESTS_VERBOSE (Default OFF) #
|
||||
# -- enables debug messages #
|
||||
# PARSE_CATCH_TESTS_NO_HIDDEN_TESTS (Default OFF) #
|
||||
# -- excludes tests marked with [!hide], [.] or [.foo] tags #
|
||||
# PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME (Default ON) #
|
||||
# -- adds fixture class name to the test name #
|
||||
# PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) #
|
||||
# -- adds cmake target name to the test name #
|
||||
# PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) #
|
||||
# -- causes CMake to rerun when file with tests changes so that new tests will be discovered #
|
||||
# #
|
||||
#==================================================================================================#
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.8)
|
||||
|
||||
option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OFF)
|
||||
option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF)
|
||||
option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON)
|
||||
option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON)
|
||||
option(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS "Add test file to CMAKE_CONFIGURE_DEPENDS property" OFF)
|
||||
|
||||
function(PrintDebugMessage)
|
||||
if(PARSE_CATCH_TESTS_VERBOSE)
|
||||
message(STATUS "ParseAndAddCatchTests: ${ARGV}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# This removes the contents between
|
||||
# - block comments (i.e. /* ... */)
|
||||
# - full line comments (i.e. // ... )
|
||||
# - block comments (i.e. /* ... */)
|
||||
# - full line comments (i.e. // ... )
|
||||
# contents have been read into '${CppCode}'.
|
||||
# !keep partial line comments
|
||||
function(RemoveComments CppCode)
|
||||
@ -47,9 +73,13 @@ endfunction()
|
||||
|
||||
# Worker function
|
||||
function(ParseFile SourceFile TestTarget)
|
||||
# According to CMake docs EXISTS behavior is well-defined only for full paths.
|
||||
get_filename_component(SourceFile ${SourceFile} ABSOLUTE)
|
||||
if(NOT EXISTS ${SourceFile})
|
||||
message(WARNING "Cannot find source file: ${SourceFile}")
|
||||
return()
|
||||
endif()
|
||||
PrintDebugMessage("parsing ${SourceFile}")
|
||||
file(STRINGS ${SourceFile} Contents NEWLINE_CONSUME)
|
||||
|
||||
# Remove block and fullline comments
|
||||
@ -58,6 +88,15 @@ function(ParseFile SourceFile TestTarget)
|
||||
# Find definition of test names
|
||||
string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^\)]+\\)+[ \t\n]*{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}")
|
||||
|
||||
if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests)
|
||||
PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property")
|
||||
set_property(
|
||||
DIRECTORY
|
||||
APPEND
|
||||
PROPERTY CMAKE_CONFIGURE_DEPENDS ${SourceFile}
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(TestName ${Tests})
|
||||
# Strip newlines
|
||||
string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}")
|
||||
@ -85,30 +124,62 @@ function(ParseFile SourceFile TestTarget)
|
||||
if("${TestType}" STREQUAL "SCENARIO")
|
||||
set(Name "Scenario: ${Name}")
|
||||
endif()
|
||||
if(TestFixture)
|
||||
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND TestFixture)
|
||||
set(CTestName "${TestFixture}:${Name}")
|
||||
else()
|
||||
set(CTestName "${Name}")
|
||||
endif()
|
||||
if(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME)
|
||||
set(CTestName "${TestTarget}:${CTestName}")
|
||||
endif()
|
||||
# add target to labels to enable running all tests added from this target
|
||||
set(Labels ${TestTarget})
|
||||
if(TestStringsLength EQUAL 2)
|
||||
list(GET TestStrings 1 Tags)
|
||||
string(TOLOWER "${Tags}" Tags)
|
||||
# remove target from labels if the test is hidden
|
||||
if("${Tags}" MATCHES ".*\\[!?(hide|\\.)\\].*")
|
||||
list(REMOVE_ITEM Labels ${TestTarget})
|
||||
endif()
|
||||
string(REPLACE "]" ";" Tags "${Tags}")
|
||||
string(REPLACE "[" "" Tags "${Tags}")
|
||||
endif()
|
||||
|
||||
# Add the test and set its properties
|
||||
add_test(NAME "\"${CTestName}\"" COMMAND ${TestTarget} ${Name} ${AdditionalCatchParameters})
|
||||
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
|
||||
LABELS "${Tags}")
|
||||
list(APPEND Labels ${Tags})
|
||||
|
||||
list(FIND Labels "!hide" IndexOfHideLabel)
|
||||
set(HiddenTagFound OFF)
|
||||
foreach(label ${Labels})
|
||||
string(REGEX MATCH "^!hide|^\\." result ${label})
|
||||
if(result)
|
||||
set(HiddenTagFound ON)
|
||||
break()
|
||||
endif(result)
|
||||
endforeach(label)
|
||||
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound})
|
||||
PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
|
||||
else()
|
||||
PrintDebugMessage("Adding test \"${CTestName}\"")
|
||||
if(Labels)
|
||||
PrintDebugMessage("Setting labels to ${Labels}")
|
||||
endif()
|
||||
|
||||
# Add the test and set its properties
|
||||
add_test(NAME "\"${CTestName}\"" COMMAND ${TestTarget} ${Name} ${AdditionalCatchParameters})
|
||||
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
|
||||
LABELS "${Labels}")
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# entry point
|
||||
function(ParseAndAddCatchTests TestTarget)
|
||||
PrintDebugMessage("Started parsing ${TestTarget}")
|
||||
get_target_property(SourceFiles ${TestTarget} SOURCES)
|
||||
PrintDebugMessage("Found the following sources: ${SourceFiles}")
|
||||
foreach(SourceFile ${SourceFiles})
|
||||
ParseFile(${SourceFile} ${TestTarget})
|
||||
endforeach()
|
||||
endfunction()
|
||||
PrintDebugMessage("Finished parsing ${TestTarget}")
|
||||
endfunction()
|
||||
|
@ -17,7 +17,7 @@ Fine tuning:
|
||||
|
||||
Running:
|
||||
* [Command line](command-line.md)
|
||||
* [Build systems](build-systems.md)
|
||||
* [CI and Build system integration](build-systems.md)
|
||||
|
||||
FAQ:
|
||||
* [Why are my tests slow to compile?](slow-compiles.md)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Integration with build systems
|
||||
# CI and build system integration
|
||||
|
||||
Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both.
|
||||
|
||||
@ -15,7 +15,7 @@ The XML Reporter writes in an XML format that is specific to Catch.
|
||||
|
||||
The advantage of this format is that it corresponds well to the way Catch works (especially the more unusual features, such as nested sections) and is a fully streaming format - that is it writes output as it goes, without having to store up all its results before it can start writing.
|
||||
|
||||
The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could covert it to, say, HTML - although this loses the streaming advantage, of course.
|
||||
The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could convert it to, say, HTML - although this loses the streaming advantage, of course.
|
||||
|
||||
## JUnit Reporter
|
||||
```-r junit```
|
||||
@ -134,6 +134,10 @@ TEST_CASE("Test3", "[a][b][c]") {
|
||||
```
|
||||
would be registered as 3 tests, `Test1`, `Test2` and `Test3`, and ctest 4 labels would be created, `a`, `b`, `c` and `unit`.
|
||||
|
||||
### CodeCoverage module (GCOV, LCOV...)
|
||||
|
||||
If you are using GCOV tool to get testing coverage of your code, and are not sure how to integrate it with CMake and Catch, there should be an external example over at https://github.com/fkromer/catch_cmake_coverage
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
||||
[Home](Readme.md)
|
||||
|
@ -27,6 +27,8 @@ Click one of the followings links to take you straight to that option - or scrol
|
||||
<a href="#listing-available-tests-tags-or-reporters"> ` --list-reporters`</a><br />
|
||||
<a href="#order"> ` --order`</a><br />
|
||||
<a href="#rng-seed"> ` --rng-seed`</a><br />
|
||||
<a href="#libidentify"> ` --libidentify`</a><br />
|
||||
<a href="#wait-for-keypress"> ` --wait-for-keypress`</a><br />
|
||||
|
||||
</br>
|
||||
|
||||
@ -213,6 +215,20 @@ Alternatively if the keyword ```time``` is provided then the result of calling `
|
||||
|
||||
In either case the actual value for the seed is printed as part of Catch's output so if an issue is discovered that is sensitive to test ordering the ordering can be reproduced - even if it was originally seeded from ```std::time(0)```.
|
||||
|
||||
<a id="libidentify"></a>
|
||||
## Identify framework and version according to the libIdentify standard
|
||||
<pre>--libidentify</pre>
|
||||
|
||||
See [The LibIdentify repo for more information and examples](https://github.com/janwilmans/LibIdentify).
|
||||
|
||||
<a id="wait-for-keypress"></a>
|
||||
## Wait for key before continuing
|
||||
<pre>--wait-for-keypress <start|exit|both></pre>
|
||||
|
||||
Will cause the executable to print a message and wait until the return/ enter key is pressed before continuing -
|
||||
either before running any tests, after running all tests - or both, depending on the argument.
|
||||
|
||||
|
||||
<a id="usage"></a>
|
||||
## Usage
|
||||
<pre>-h, -?, --help</pre>
|
||||
|
@ -13,4 +13,4 @@ fact then please let us know - either directly, via a PR or
|
||||
|
||||
- Bloomberg
|
||||
- NASA
|
||||
|
||||
- [Inscopix Inc.](https://www.inscopix.com/)
|
||||
|
@ -43,12 +43,19 @@ By default a console width of 80 is assumed but this can be controlled by defini
|
||||
|
||||
CATCH_CONFIG_NOSTDOUT
|
||||
|
||||
Catch does not use ```std::cout``` and ```std::cerr``` directly but gets them from ```Catch::cout()``` and ```Catch::cerr()``` respectively. If the above identifier is defined these functions are left unimplemented and you must implement them yourself. Their signatures are:
|
||||
Catch does not use ```std::cout```, ```std::cerr``` and ```std::clog``` directly but gets them from ```Catch::cout()```, ```Catch::cerr()``` and ```Catch::clog``` respectively. If the above identifier is defined these functions are left unimplemented and you must implement them yourself. Their signatures are:
|
||||
|
||||
std::ostream& cout();
|
||||
std::ostream& cerr();
|
||||
std::ostream& clog();
|
||||
|
||||
This can be useful on certain platforms that do not provide ```std::cout``` and ```std::cerr```, such as certain embedded systems.
|
||||
This can be useful on certain platforms that do not provide the standard iostreams, such as certain embedded systems.
|
||||
|
||||
# Default reporter
|
||||
|
||||
CATCH_CONFIG_DEFAULT_REPORTER <reporter>
|
||||
|
||||
The default reporter (reporter used when no reporters are explicitly specified) can be overriden during compilation time by using the above macro. Note that desired value of the macro is a C string and quotes have to be escaped during compilation: `clang++ test.cpp -DCATCH_CONFIG_DEFAULT_REPORTER=\"xml\"`.
|
||||
|
||||
# C++ conformance toggles
|
||||
|
||||
@ -100,6 +107,7 @@ TEST_CASE ("Error in streamable check") {
|
||||
CATCH_CONFIG_FAST_COMPILE // Sacrifices some (rather minor) features for compilation speed
|
||||
CATCH_CONFIG_POSIX_SIGNALS // Enable handling POSIX signals
|
||||
CATCH_CONFIG_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap
|
||||
CATCH_CONFIG_DISABLE_STRINGIFICATION // Disable stringifying the original expression
|
||||
|
||||
Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support.
|
||||
|
||||
@ -116,6 +124,10 @@ Defining this flag speeds up compilation of test files by ~20%, by making 2 chan
|
||||
|
||||
`CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined, in all translation units that are linked into single test binary, or the behaviour of setting `-b` flag and throwing unexpected exceptions will be unpredictable.
|
||||
|
||||
## `CATCH_CONFIG_DISABLE_STRINGIFICATION`
|
||||
This toggle enables a workaround for VS 2017 bug. For details see
|
||||
[known limitations](limitations.md#visual-studio-2017----raw-string-literal-in-assert-fails-to-compile).
|
||||
|
||||
# Windows header clutter
|
||||
|
||||
On Windows Catch includes `windows.h`. To minimize global namespace clutter in the implementation file, it defines `NOMINMAX` and `WIN32_LEAN_AND_MEAN` before including it. You can control this behaviour via two macros:
|
||||
|
@ -18,8 +18,8 @@ Ongoing development is currently on _master_. At some point an integration branc
|
||||
_Users_ of Catch primarily use the single header version. _Maintainers_ should work with the full source (which is still,
|
||||
primarily, in headers). This can be found in the `include` folder. There are a set of test files, currently under
|
||||
`projects/SelfTest`. The test app can be built via CMake from the `CMakeLists.txt` file in the root, or you can generate
|
||||
project files for Visual Studio, XCode, and others (instructions in the `projects` folder). If you have access to CLion
|
||||
that can work with the CMake file directly.
|
||||
project files for Visual Studio, XCode, and others (instructions in the `projects` folder). If you have access to CLion,
|
||||
it can work with the CMake file directly.
|
||||
|
||||
As well as the runtime test files you'll also see a `SurrogateCpps` directory under `projects/SelfTest`.
|
||||
This contains a set of .cpp files that each `#include` a single header.
|
||||
@ -34,6 +34,25 @@ __When submitting a pull request please do not include changes to the single inc
|
||||
as these are managed by the scripts!__
|
||||
|
||||
|
||||
## Testing your changes
|
||||
|
||||
Obviously all changes to Catch's code should be tested. If you added new functionality, you should add tests covering and
|
||||
showcasing it. Even if you have only made changes to Catch internals (ie you implemented some performance improvements),
|
||||
you should still test your changes.
|
||||
|
||||
This means 3 things
|
||||
|
||||
* Compiling Catch's SelfTest project -- code that does not compile is evidently incorrect. Obviously, you are not expected to
|
||||
have access to all compilers and platforms Catch supports, Catch's CI pipeline will compile your code using supported compilers
|
||||
once you open a PR.
|
||||
* Running the SelfTest binary. There should be no unexpected failures on simple run.
|
||||
* Running Catch's approval tests. Approval tests compare current output of the SelfTest binary in various configurations against
|
||||
known good output. Catch's repository provides utility scripts `approvalTests.py` to help you with this. It needs to be passed
|
||||
the SelfTest binary compiled with your changes, like so: `$ ./scripts/approvalTests.py clang-build/SelfTest`. The output should
|
||||
be fairly self-explanatory.
|
||||
|
||||
|
||||
|
||||
*this document is still in-progress...*
|
||||
|
||||
---
|
||||
|
@ -31,7 +31,7 @@ struct MyListener : Catch::TestEventListenerBase {
|
||||
// Perform some setup before a test case is run
|
||||
}
|
||||
|
||||
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override {
|
||||
virtual void testCaseEnded( Catch::TestCaseStats const& testCaseStats ) override {
|
||||
// Tear-down after a test case is run
|
||||
}
|
||||
};
|
||||
@ -70,4 +70,4 @@ just look in the source code to see what fields are available.
|
||||
|
||||
---
|
||||
|
||||
[Home](Readme.md)
|
||||
[Home](Readme.md)
|
||||
|
@ -50,6 +50,38 @@ Both of these solutions have their problems, but should let you wring parallelis
|
||||
## 3rd party bugs
|
||||
This section outlines known bugs in 3rd party components (this means compilers, standard libraries, standard runtimes).
|
||||
|
||||
### Visual Studio 2017 -- raw string literal in assert fails to compile
|
||||
There is a known bug in Visual Studio 2017 (VC 15), that causes compilation error when preprocessor attempts to stringize a raw string literal (`#` preprocessor is applied to it). This snippet is sufficient to trigger the compilation error:
|
||||
```cpp
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
|
||||
TEST_CASE("test") {
|
||||
CHECK(std::string(R"("\)") == "\"\\");
|
||||
}
|
||||
```
|
||||
|
||||
Catch provides a workaround, it is possible to disable stringification of original expressions by defining `CATCH_CONFIG_DISABLE_STRINGIFICATION`:
|
||||
```cpp
|
||||
#define CATCH_CONFIG_FAST_COMPILE
|
||||
#define CATCH_CONFIG_DISABLE_STRINGIFICATION
|
||||
#include "catch.hpp"
|
||||
|
||||
TEST_CASE("test") {
|
||||
CHECK(std::string(R"("\)") == "\"\\");
|
||||
}
|
||||
```
|
||||
|
||||
_Do note that this changes the output somewhat_
|
||||
```
|
||||
catchwork\test1.cpp(6):
|
||||
PASSED:
|
||||
CHECK( Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION )
|
||||
with expansion:
|
||||
""\" == ""\"
|
||||
```
|
||||
|
||||
|
||||
### Visual Studio 2013 -- do-while loop withing range based for fails to compile (C2059)
|
||||
There is a known bug in Visual Studio 2013 (VC 12), that causes compilation error if range based for is followed by an assertion macro, without enclosing the block in braces. This snippet is sufficient to trigger the error
|
||||
```cpp
|
||||
|
@ -1,6 +1,32 @@
|
||||
# Logging macros
|
||||
|
||||
Additional messages can be logged during a test case.
|
||||
Additional messages can be logged during a test case. Note that the messages are scoped and thus will not be reported if failure occurs in scope preceding the message declaration. An example:
|
||||
|
||||
```cpp
|
||||
TEST_CASE("Foo") {
|
||||
INFO("Test case start");
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
INFO("The number is " << i);
|
||||
CHECK(i == 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Bar") {
|
||||
INFO("Test case start");
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
INFO("The number is " << i);
|
||||
CHECK(i == i);
|
||||
}
|
||||
CHECK(false);
|
||||
}
|
||||
```
|
||||
When the `CHECK` fails in the "Foo" test case, then two messages will be printed.
|
||||
```
|
||||
Test case start
|
||||
The number is 1
|
||||
```
|
||||
When the last `CHECK` fails in the "Bar" test case, then only one message will be printed: `Test case start`.
|
||||
|
||||
|
||||
## Streaming macros
|
||||
|
||||
|
@ -13,6 +13,7 @@ which consists of either a single matcher or one or more matchers combined using
|
||||
For example, to assert that a string ends with a certain substring:
|
||||
|
||||
```c++
|
||||
using Catch::Matchers::EndsWith; // or Catch::EndsWith
|
||||
std::string str = getStringFromSomewhere();
|
||||
REQUIRE_THAT( str, EndsWith( "as a service" ) );
|
||||
```
|
||||
@ -34,7 +35,7 @@ REQUIRE_THAT( str,
|
||||
```
|
||||
|
||||
## Built in matchers
|
||||
Currently Catch has some string matchers and some vector matchers.
|
||||
Currently Catch has some string matchers and some vector matchers. They are in the `Catch::Matchers` and `Catch` namespaces.
|
||||
The string matchers are `StartsWith`, `EndsWith`, `Contains` and `Equals`. Each of them also takes an optional second argument, that decides case sensitivity (by-default, they are case sensitive).
|
||||
The vector matchers are `Contains`, `VectorContains` and `Equals`. `VectorContains` looks for a single element in the matched vector, `Contains` looks for a set (vector) of elements inside the matched vector.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Open Source projects using Catch
|
||||
|
||||
Catch is great for open source. With it's [liberal license](../LICENSE_1_0.txt) and single-header, dependency-free, distribution
|
||||
Catch is great for open source. With its [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution
|
||||
it's easy to just drop the header into your project and start writing tests - what's not to like?
|
||||
|
||||
As a result Catch is now being used in many Open Source projects, including some quite well known ones.
|
||||
@ -25,6 +25,9 @@ The core part of the Chakra Javascript engine that powers Microsoft Edge
|
||||
### [ChaiScript](https://github.com/ChaiScript/ChaiScript)
|
||||
A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques
|
||||
|
||||
### [Clara](https://github.com/philsquared/Clara)
|
||||
A, single-header-only, type-safe, command line parser - which also prints formatted usage strings.
|
||||
|
||||
### [Couchbase-lite-core](https://github.com/couchbase/couchbase-lite-core)
|
||||
The next-generation core storage and query engine for Couchbase Lite/
|
||||
|
||||
@ -52,14 +55,23 @@ A C++ client library for Consul. Consul is a distributed tool for discovering an
|
||||
### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp)
|
||||
A library of algorithms for values-distributed-in-time
|
||||
|
||||
### [TextFlowCpp](https://github.com/philsquared/textflowcpp)
|
||||
A small, single-header-only, library for wrapping and composing columns of text
|
||||
|
||||
### [Trompeloeil](https://github.com/rollbear/trompeloeil)
|
||||
A thread safe header only mocking framework for C++14
|
||||
|
||||
### [args](https://github.com/Taywee/args)
|
||||
A simple header-only C++ argument parser library.
|
||||
|
||||
## Applications & Tools
|
||||
|
||||
### [ArangoDB](https://github.com/arangodb/arangodb)
|
||||
ArangoDB is a native multi-model database with flexible data models for documents, graphs, and key-values.
|
||||
|
||||
### [Giada - Your Hardcore Loop Machine](https://github.com/monocasual/giada)
|
||||
Minimal, open-source and cross-platform audio tool for live music production.
|
||||
|
||||
### [MAME](https://github.com/mamedev/mame)
|
||||
MAME originally stood for Multiple Arcade Machine Emulator
|
||||
|
||||
|
@ -1,3 +1,98 @@
|
||||
# 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.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.7
|
||||
|
||||
### Fixes
|
||||
* Various warnings from clang-tidy, Resharper-C++ and PVS Studio have been addressed (#957)
|
||||
* Dynamically generated sections are now properly reported (#963)
|
||||
* Writes to `std::clog` are redirected for reporters (#989)
|
||||
* Previously only `std::cerr` writes were redirected
|
||||
* Interleaved writes to `std::cerr` and `std::clog` are combined properly
|
||||
* Assertions failed before signals/structured exceptions fails test case are properly reported as failed (#990)
|
||||
|
||||
### Improvements
|
||||
* Catch's runtime overhead has been decreased further (#940)
|
||||
* Added support for IBM i ILE c++ compiler (#976)
|
||||
* This means that AS/400 is now supported.
|
||||
* The default reporter can be configured at compile time (#978)
|
||||
* That is, the reporter used if no reporter is explicitly specified
|
||||
|
||||
### Other
|
||||
* `ParseAndAddCatchTests` cmake script has couple new customization options
|
||||
|
||||
|
||||
|
||||
# 1.9.6
|
||||
|
||||
### Improvements
|
||||
* Catch's runtime overhead has been significantly decreased (#937, #939)
|
||||
* Added `--list-extra-info` cli option (#934).
|
||||
* It lists all tests together with extra information, ie filename, line number and description.
|
||||
|
||||
|
||||
|
||||
# 1.9.5
|
||||
|
||||
### Fixes
|
||||
* Truthy expressions are now reconstructed properly, not as booleans (#914)
|
||||
* Various warnings are no longer erroneously suppressed in test files (files that include `catch.hpp`, but do not define `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`) (#871)
|
||||
* Catch no longer fails to link when main is compiled as C++, but linked against Objective-C (#855)
|
||||
* Fixed incorrect gcc version detection when deciding to use `__COUNTER__` (#928)
|
||||
* Previously any GCC with minor version less than 3 would be incorrectly classified as not supporting `__COUNTER__`.
|
||||
* Suppressed C4996 warning caused by upcoming updated to MSVC 2017, marking `std::uncaught_exception` as deprecated. (#927)
|
||||
|
||||
### Improvements
|
||||
* CMake integration script now incorporates debug messages and registers tests in an improved way (#911)
|
||||
* Various documentation improvements
|
||||
|
||||
|
||||
|
||||
# 1.9.4
|
||||
|
||||
### Fixes
|
||||
* `CATCH_FAIL` macro no longer causes compilation error without variadic macro support
|
||||
* `INFO` messages are no longer cleared after being reported once
|
||||
|
||||
### Improvements and minor changes
|
||||
* Catch now uses `wmain` when compiled under Windows and `UNICODE` is defined.
|
||||
* Note that Catch still officially supports only ASCII
|
||||
|
||||
# 1.9.3
|
||||
|
||||
### Fixes
|
||||
* Completed the fix for (lack of) uint64_t in earlier Visual Studios
|
||||
|
||||
# 1.9.2
|
||||
|
||||
### Improvements and minor changes
|
||||
|
63
docs/release-process.md
Normal file
63
docs/release-process.md
Normal file
@ -0,0 +1,63 @@
|
||||
# How to release
|
||||
|
||||
When enough changes have accumulated, it is time to release new version of Catch. This document describes the proces in doing so, that no steps are forgotten. Note that all referenced scripts can be found in the `scripts/` directory.
|
||||
|
||||
## Neccessary steps
|
||||
|
||||
These steps are neccessary and have to be performed before each new release. They serve to make sure that the new release is correct and linked-to from the standard places.
|
||||
|
||||
|
||||
### Approval testing
|
||||
|
||||
Catch's releases are primarily validated against output from previous release, stored in `projects/SelfTest/Baselines`. To validate current sources, build the SelfTest binary and pass it to the `approvalTests.py` script: `approvalTests.py <path/to/SelfTest>`.
|
||||
|
||||
There should be no differences, as Approval tests should be updated when changes to Catch are made, but if there are, then they need to be manually reviewed and either approved (using `approve.py`) or Catch requires other fixes.
|
||||
|
||||
|
||||
### Incrementing version number
|
||||
|
||||
Catch uses a variant of [semantic versioning](http://semver.org/), with breaking API changes (and thus major version increments) being very rare. Thus, the release will usually increment the patch version, when it only contains couple of bugfixes, or minor version, when it contains new functionality, or larger changes in implementation of current functionality.
|
||||
|
||||
After deciding which part of version number should be incremented, you can use one of the `*Release.py` scripts to perform the required changes to Catch.
|
||||
|
||||
|
||||
### Generate updated single-include header
|
||||
|
||||
After updating version number, regenerate single-include header using `generateSingleHeader.py`.
|
||||
|
||||
|
||||
### Release notes
|
||||
|
||||
Once a release is ready, release notes need to be written. They should summarize changes done since last release. For rough idea of expected notes see previous releases. Once written, release notes should be placed in `docs/release-notes.md`.
|
||||
|
||||
|
||||
### Commit and push update to GitHub
|
||||
|
||||
After version number is incremented, single-include header is regenerated and release notes are updated, changes should be commited and pushed to GitHub.
|
||||
|
||||
|
||||
### Release on GitHub
|
||||
|
||||
After pushing changes to GitHub, GitHub release *needs* to be created. Tag version and release title should be same as the new version, description should contain the release notes for the current release. Single header version of `catch.hpp` *needs* to be attached as a binary, as that is where the official download link links to. Preferably it should use linux line endings.
|
||||
|
||||
## Optional steps
|
||||
|
||||
The following steps are optional, and do not have to be performed when releasing new version of Catch. However, they are *should* happen, but they can happen the next day without losing anything significant.
|
||||
|
||||
|
||||
### vcpkg update
|
||||
|
||||
Catch is maintaining its own port in Microsoft's package manager [vcpkg](https://github.com/Microsoft/vcpkg). This means that when new version of Catch is released, it should be posted there as well. `updateVcpkgPackage.py` can do a lot of neccessary work for you, it creates a branch and commits neccessary changes. You should review these changes, push and open a PR against vcpkg's upstream.
|
||||
|
||||
Note that the script assumes you have your fork of vcpkg checked out in a directory next to the directory where you have checked out Catch, like so:
|
||||
```
|
||||
GitHub
|
||||
Catch
|
||||
vcpkg
|
||||
```
|
||||
|
||||
|
||||
### Wandbox update
|
||||
|
||||
Recently we also included a link to wandbox with preloaded Catch on the main page. Strictly speaking it is unneccessary to update this after every release, Catch usually does not change that much between versions, but it should be kept up to date anyway.
|
||||
|
@ -17,7 +17,7 @@ There are four reporters built in to the single include:
|
||||
|
||||
* `console` writes as lines of text, formatted to a typical terminal width, with colours if a capable terminal is detected.
|
||||
* `compact` similar to `console` but optimised for minimal output - each entry on one line
|
||||
* `junit` writes xml that corresponds to Ant's [junitreport](http://help.catchsoftware.com/display/ET/JUnit+Format) target. Useful for build systems that understand Junit.
|
||||
* `junit` writes xml that corresponds to Ant's [junitreport](http://help.catchsoftware.com/display/ET/JUnit+Format) target. Useful for build systems that understand Junit. If you are using Jenkins with Catch 1.x, you can improve quality of output by applying changes in [#923](https://github.com/philsquared/Catch/pull/923).
|
||||
Because of the way the junit format is structured the run must complete before anything is written.
|
||||
* `xml` writes an xml format tailored to Catch. Unlike `junit` this is a streaming format so results are delivered progressively.
|
||||
|
||||
|
@ -28,7 +28,7 @@ The tag expression, ```"[widget]"``` selects A, B & D. ```"[gadget]"``` selects
|
||||
|
||||
For more detail on command line selection see [the command line docs](command-line.md#specifying-which-tests-to-run)
|
||||
|
||||
Tag names are not case sensitive.
|
||||
Tag names are not case sensitive and can contain any ASCII characters. This means that tags `[tag with spaces]` and `[I said "good day"]` are both allowed tags and can be filtered on. Escapes are not supported however and `[\]]` is not a valid tag.
|
||||
|
||||
### Special Tags
|
||||
|
||||
@ -38,19 +38,19 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch.
|
||||
|
||||
* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`.
|
||||
|
||||
* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in the your tests.
|
||||
* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in your tests.
|
||||
|
||||
* `[!shouldfail]` - like `[!mayfail]` but *fails* the test if it *passes*. This can be useful if you want to be notified of accidental, or third-party, fixes.
|
||||
|
||||
* `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers.
|
||||
|
||||
* `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped) as a tag. e.g. tests in testfile.cpp would all be tagged `[#testfile]`.
|
||||
* `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped), as a tag to all contained tests, e.g. tests in testfile.cpp would all be tagged `[#testfile]`.
|
||||
|
||||
* `[@<alias>]` - tag aliases all begin with `@` (see below).
|
||||
|
||||
## Tag aliases
|
||||
|
||||
Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. this can be done, in code, using the following form:
|
||||
Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. This can be done, in code, using the following form:
|
||||
|
||||
CATCH_REGISTER_TAG_ALIAS( <alias string>, <tag expression> )
|
||||
|
||||
|
@ -16,16 +16,7 @@ std::ostream& operator << ( std::ostream& os, T const& value ) {
|
||||
|
||||
(where ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable - it doesn't have to be in another function).
|
||||
|
||||
You should put this function in the same namespace as your type.
|
||||
|
||||
Alternatively you may prefer to write it as a member function:
|
||||
|
||||
```
|
||||
std::ostream& T::operator << ( std::ostream& os ) const {
|
||||
os << convertMyTypeToString( *this );
|
||||
return os;
|
||||
}
|
||||
```
|
||||
You should put this function in the same namespace as your type and it has to be declared before including Catch's header.
|
||||
|
||||
## Catch::toString overload
|
||||
|
||||
@ -39,11 +30,12 @@ namespace Catch {
|
||||
}
|
||||
```
|
||||
|
||||
Again ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable. Note that the function must be in the Catch namespace, which itself must be in the global namespace.
|
||||
Again ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable. Note that the function must be in the Catch namespace, which itself must be in the global namespace and must be declared _before_ Catch's header is included.
|
||||
|
||||
**Please note that overloading `Catch::toString` is currently considered legacy and will not be supported in the next major version of Catch.**
|
||||
|
||||
## Catch::StringMaker<T> specialisation
|
||||
|
||||
There are some cases where overloading toString does not work as expected. Specialising StringMaker<T> gives you more precise, and reliable, control - but at the cost of slightly more code and complexity:
|
||||
Another way of telling Catch how to convert a type to string is specialising `Catch::StringMaker` template. This allows you to have separate way of stringifying types for Catch, than you have for writing it to a stream and also doesn't require you to declare it before including Catch's header.
|
||||
|
||||
```
|
||||
namespace Catch {
|
||||
|
@ -68,7 +68,7 @@ with expansion:
|
||||
0 == 1
|
||||
```
|
||||
|
||||
Note that we get the actual return value of Factorial(0) printed for us (0) - even though we used a natural expression with the == operator. That let's us immediately see what the problem is.
|
||||
Note that we get the actual return value of Factorial(0) printed for us (0) - even though we used a natural expression with the == operator. That lets us immediately see what the problem is.
|
||||
|
||||
Let's change the factorial function to:
|
||||
|
||||
@ -80,7 +80,7 @@ unsigned int Factorial( unsigned int number ) {
|
||||
|
||||
Now all the tests pass.
|
||||
|
||||
Of course there are still more issues to do deal with. For example we'll hit problems when the return value starts to exceed the range of an unsigned int. With factorials that can happen quite quickly. You might want to add tests for such cases and decide how to handle them. We'll stop short of doing that here.
|
||||
Of course there are still more issues to deal with. For example we'll hit problems when the return value starts to exceed the range of an unsigned int. With factorials that can happen quite quickly. You might want to add tests for such cases and decide how to handle them. We'll stop short of doing that here.
|
||||
|
||||
## What did we do here?
|
||||
|
||||
|
@ -57,16 +57,16 @@
|
||||
#include <crtdbg.h>
|
||||
class LeakDetector {
|
||||
public:
|
||||
LeakDetector() {
|
||||
int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
||||
flag |= _CRTDBG_LEAK_CHECK_DF;
|
||||
flag |= _CRTDBG_ALLOC_MEM_DF;
|
||||
_CrtSetDbgFlag(flag);
|
||||
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
|
||||
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
|
||||
// Change this to leaking allocation's number to break there
|
||||
_CrtSetBreakAlloc(-1);
|
||||
}
|
||||
LeakDetector() {
|
||||
int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
||||
flag |= _CRTDBG_LEAK_CHECK_DF;
|
||||
flag |= _CRTDBG_ALLOC_MEM_DF;
|
||||
_CrtSetDbgFlag(flag);
|
||||
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
|
||||
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
|
||||
// Change this to leaking allocation's number to break there
|
||||
_CrtSetBreakAlloc(-1);
|
||||
}
|
||||
};
|
||||
#else
|
||||
class LeakDetector {};
|
||||
@ -136,7 +136,7 @@ LeakDetector leakDetector;
|
||||
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
|
||||
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
|
||||
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
|
||||
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
|
||||
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
|
||||
#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
||||
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
|
||||
#else
|
||||
|
@ -31,10 +31,14 @@ namespace Catch {
|
||||
return reporter;
|
||||
}
|
||||
|
||||
#if !defined(CATCH_CONFIG_DEFAULT_REPORTER)
|
||||
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
|
||||
#endif
|
||||
|
||||
Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
|
||||
std::vector<std::string> reporters = config->getReporterNames();
|
||||
if( reporters.empty() )
|
||||
reporters.push_back( "console" );
|
||||
reporters.push_back( CATCH_CONFIG_DEFAULT_REPORTER );
|
||||
|
||||
Ptr<IStreamingReporter> reporter;
|
||||
for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
|
||||
@ -95,11 +99,11 @@ namespace Catch {
|
||||
if( lastSlash != std::string::npos )
|
||||
filename = filename.substr( lastSlash+1 );
|
||||
|
||||
std::string::size_type lastDot = filename.find_last_of( "." );
|
||||
std::string::size_type lastDot = filename.find_last_of( '.' );
|
||||
if( lastDot != std::string::npos )
|
||||
filename = filename.substr( 0, lastDot );
|
||||
|
||||
tags.insert( "#" + filename );
|
||||
tags.insert( '#' + filename );
|
||||
setTags( test, tags );
|
||||
}
|
||||
}
|
||||
@ -130,6 +134,13 @@ namespace Catch {
|
||||
m_cli.usage( Catch::cout(), processName );
|
||||
Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
|
||||
}
|
||||
void libIdentify() {
|
||||
Catch::cout()
|
||||
<< std::left << std::setw(16) << "description: " << "A Catch test executable\n"
|
||||
<< std::left << std::setw(16) << "category: " << "testframework\n"
|
||||
<< std::left << std::setw(16) << "framework: " << "Catch Test\n"
|
||||
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
|
||||
}
|
||||
|
||||
int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
|
||||
try {
|
||||
@ -137,6 +148,8 @@ namespace Catch {
|
||||
m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
|
||||
if( m_configData.showHelp )
|
||||
showHelp( m_configData.processName );
|
||||
if( m_configData.libIdentify )
|
||||
libIdentify();
|
||||
m_config.reset();
|
||||
}
|
||||
catch( std::exception& ex ) {
|
||||
@ -166,8 +179,63 @@ namespace Catch {
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
#if defined(WIN32) && defined(UNICODE)
|
||||
int run( int argc, wchar_t const* const* const argv ) {
|
||||
|
||||
char **utf8Argv = new char *[ argc ];
|
||||
|
||||
for ( int i = 0; i < argc; ++i ) {
|
||||
int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
|
||||
|
||||
utf8Argv[ i ] = new char[ bufSize ];
|
||||
|
||||
WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
|
||||
}
|
||||
|
||||
int returnCode = applyCommandLine( argc, utf8Argv );
|
||||
if( returnCode == 0 )
|
||||
returnCode = run();
|
||||
|
||||
for ( int i = 0; i < argc; ++i )
|
||||
delete [] utf8Argv[ i ];
|
||||
|
||||
delete [] utf8Argv;
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
#endif
|
||||
|
||||
int run() {
|
||||
if( m_configData.showHelp )
|
||||
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
|
||||
Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
|
||||
static_cast<void>(std::getchar());
|
||||
}
|
||||
int exitCode = runInternal();
|
||||
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
|
||||
Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
|
||||
static_cast<void>(std::getchar());
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
Clara::CommandLine<ConfigData> const& cli() const {
|
||||
return m_cli;
|
||||
}
|
||||
std::vector<Clara::Parser::Token> const& unusedTokens() const {
|
||||
return m_unusedTokens;
|
||||
}
|
||||
ConfigData& configData() {
|
||||
return m_configData;
|
||||
}
|
||||
Config& config() {
|
||||
if( !m_config )
|
||||
m_config = new Config( m_configData );
|
||||
return *m_config;
|
||||
}
|
||||
private:
|
||||
|
||||
int runInternal() {
|
||||
if( m_configData.showHelp || m_configData.libIdentify )
|
||||
return 0;
|
||||
|
||||
try
|
||||
@ -191,21 +259,6 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
Clara::CommandLine<ConfigData> const& cli() const {
|
||||
return m_cli;
|
||||
}
|
||||
std::vector<Clara::Parser::Token> const& unusedTokens() const {
|
||||
return m_unusedTokens;
|
||||
}
|
||||
ConfigData& configData() {
|
||||
return m_configData;
|
||||
}
|
||||
Config& config() {
|
||||
if( !m_config )
|
||||
m_config = new Config( m_configData );
|
||||
return *m_config;
|
||||
}
|
||||
private:
|
||||
Clara::CommandLine<ConfigData> m_cli;
|
||||
std::vector<Clara::Parser::Token> m_unusedTokens;
|
||||
ConfigData m_configData;
|
||||
|
2
include/external/clara.h
vendored
2
include/external/clara.h
vendored
@ -151,7 +151,7 @@ namespace Tbc {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
|
||||
friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
|
||||
for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
|
||||
it != itEnd; ++it ) {
|
||||
if( it != _text.begin() )
|
||||
|
@ -29,13 +29,6 @@ namespace Detail {
|
||||
m_value( value )
|
||||
{}
|
||||
|
||||
Approx( Approx const& other )
|
||||
: m_epsilon( other.m_epsilon ),
|
||||
m_margin( other.m_margin ),
|
||||
m_scale( other.m_scale ),
|
||||
m_value( other.m_value )
|
||||
{}
|
||||
|
||||
static Approx custom() {
|
||||
return Approx( 0 );
|
||||
}
|
||||
@ -64,7 +57,8 @@ namespace Detail {
|
||||
if (relativeOK) {
|
||||
return true;
|
||||
}
|
||||
return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin;
|
||||
|
||||
return std::fabs(lhs_v - rhs.m_value) <= rhs.m_margin;
|
||||
}
|
||||
|
||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||
@ -137,7 +131,7 @@ namespace Detail {
|
||||
if (relativeOK) {
|
||||
return true;
|
||||
}
|
||||
return std::fabs(lhs - rhs.m_value) < rhs.m_margin;
|
||||
return std::fabs(lhs - rhs.m_value) <= rhs.m_margin;
|
||||
}
|
||||
|
||||
friend bool operator == ( Approx const& lhs, double rhs ) {
|
||||
|
@ -33,22 +33,24 @@ namespace Catch {
|
||||
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& );
|
||||
template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& );
|
||||
|
||||
private:
|
||||
DecomposedExpression& operator = (DecomposedExpression const&);
|
||||
private:
|
||||
DecomposedExpression& operator = (DecomposedExpression const&);
|
||||
};
|
||||
|
||||
struct AssertionInfo
|
||||
{
|
||||
AssertionInfo() {}
|
||||
AssertionInfo( std::string const& _macroName,
|
||||
AssertionInfo();
|
||||
AssertionInfo( char const * _macroName,
|
||||
SourceLineInfo const& _lineInfo,
|
||||
std::string const& _capturedExpression,
|
||||
ResultDisposition::Flags _resultDisposition );
|
||||
char const * _capturedExpression,
|
||||
ResultDisposition::Flags _resultDisposition,
|
||||
char const * _secondArg = "");
|
||||
|
||||
std::string macroName;
|
||||
char const * macroName;
|
||||
SourceLineInfo lineInfo;
|
||||
std::string capturedExpression;
|
||||
char const * capturedExpression;
|
||||
ResultDisposition::Flags resultDisposition;
|
||||
char const * secondArg;
|
||||
};
|
||||
|
||||
struct AssertionResultData
|
||||
|
@ -13,14 +13,18 @@
|
||||
namespace Catch {
|
||||
|
||||
|
||||
AssertionInfo::AssertionInfo( std::string const& _macroName,
|
||||
AssertionInfo::AssertionInfo():macroName(""), capturedExpression(""), resultDisposition(ResultDisposition::Normal), secondArg(""){}
|
||||
|
||||
AssertionInfo::AssertionInfo( char const * _macroName,
|
||||
SourceLineInfo const& _lineInfo,
|
||||
std::string const& _capturedExpression,
|
||||
ResultDisposition::Flags _resultDisposition )
|
||||
char const * _capturedExpression,
|
||||
ResultDisposition::Flags _resultDisposition,
|
||||
char const * _secondArg)
|
||||
: macroName( _macroName ),
|
||||
lineInfo( _lineInfo ),
|
||||
capturedExpression( _capturedExpression ),
|
||||
resultDisposition( _resultDisposition )
|
||||
resultDisposition( _resultDisposition ),
|
||||
secondArg( _secondArg )
|
||||
{}
|
||||
|
||||
AssertionResult::AssertionResult() {}
|
||||
@ -47,24 +51,30 @@ namespace Catch {
|
||||
}
|
||||
|
||||
bool AssertionResult::hasExpression() const {
|
||||
return !m_info.capturedExpression.empty();
|
||||
return m_info.capturedExpression[0] != 0;
|
||||
}
|
||||
|
||||
bool AssertionResult::hasMessage() const {
|
||||
return !m_resultData.message.empty();
|
||||
}
|
||||
|
||||
std::string capturedExpressionWithSecondArgument( char const * capturedExpression, char const * secondArg ) {
|
||||
return (secondArg[0] == 0 || secondArg[0] == '"' && secondArg[1] == '"')
|
||||
? capturedExpression
|
||||
: std::string(capturedExpression) + ", " + secondArg;
|
||||
}
|
||||
|
||||
std::string AssertionResult::getExpression() const {
|
||||
if( isFalseTest( m_info.resultDisposition ) )
|
||||
return '!' + m_info.capturedExpression;
|
||||
return "!(" + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + ")";
|
||||
else
|
||||
return m_info.capturedExpression;
|
||||
return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
|
||||
}
|
||||
std::string AssertionResult::getExpressionInMacro() const {
|
||||
if( m_info.macroName.empty() )
|
||||
return m_info.capturedExpression;
|
||||
if( m_info.macroName[0] == 0 )
|
||||
return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
|
||||
else
|
||||
return m_info.macroName + "( " + m_info.capturedExpression + " )";
|
||||
return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )";
|
||||
}
|
||||
|
||||
bool AssertionResult::hasExpandedExpression() const {
|
||||
|
@ -18,6 +18,12 @@
|
||||
#include "catch_compiler_capabilities.h"
|
||||
|
||||
|
||||
#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
|
||||
# define CATCH_INTERNAL_STRINGIFY(expr) #expr
|
||||
#else
|
||||
# define CATCH_INTERNAL_STRINGIFY(expr) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
|
||||
#endif
|
||||
|
||||
#if defined(CATCH_CONFIG_FAST_COMPILE)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// We can speedup compilation significantly by breaking into debugger lower in
|
||||
@ -33,7 +39,7 @@
|
||||
// the exception before it propagates back up to the runner.
|
||||
#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \
|
||||
do { \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \
|
||||
__catchResult.setExceptionGuard(); \
|
||||
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
||||
( __catchResult <= expr ).endExpression(); \
|
||||
@ -45,9 +51,9 @@
|
||||
|
||||
#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \
|
||||
do { \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
|
||||
__catchResult.setExceptionGuard(); \
|
||||
__catchResult.captureMatch( arg, matcher, #matcher ); \
|
||||
__catchResult.captureMatch( arg, matcher, CATCH_INTERNAL_STRINGIFY(matcher) ); \
|
||||
__catchResult.unsetExceptionGuard(); \
|
||||
INTERNAL_CATCH_REACT( __catchResult ) \
|
||||
} while( Catch::alwaysFalse() )
|
||||
@ -60,14 +66,14 @@
|
||||
// source code rather than in Catch library code
|
||||
#define INTERNAL_CATCH_REACT( resultBuilder ) \
|
||||
if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
|
||||
resultBuilder.react();
|
||||
resultBuilder.react();
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \
|
||||
do { \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \
|
||||
try { \
|
||||
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
||||
( __catchResult <= expr ).endExpression(); \
|
||||
@ -83,17 +89,17 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \
|
||||
INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
|
||||
if( Catch::getResultCapture().getLastResult()->succeeded() )
|
||||
if( Catch::getResultCapture().lastAssertionPassed() )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \
|
||||
INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
|
||||
if( !Catch::getResultCapture().getLastResult()->succeeded() )
|
||||
if( !Catch::getResultCapture().lastAssertionPassed() )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \
|
||||
do { \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \
|
||||
try { \
|
||||
static_cast<void>(expr); \
|
||||
__catchResult.captureResult( Catch::ResultWas::Ok ); \
|
||||
@ -107,7 +113,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \
|
||||
do { \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition, CATCH_INTERNAL_STRINGIFY(matcher) ); \
|
||||
if( __catchResult.allowThrows() ) \
|
||||
try { \
|
||||
static_cast<void>(expr); \
|
||||
@ -124,7 +130,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
|
||||
do { \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
|
||||
if( __catchResult.allowThrows() ) \
|
||||
try { \
|
||||
static_cast<void>(expr); \
|
||||
@ -152,7 +158,7 @@
|
||||
INTERNAL_CATCH_REACT( __catchResult ) \
|
||||
} while( Catch::alwaysFalse() )
|
||||
#else
|
||||
#define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
|
||||
#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, log ) \
|
||||
do { \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
|
||||
__catchResult << log + ::Catch::StreamEndStop(); \
|
||||
@ -168,9 +174,9 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
|
||||
do { \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
|
||||
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
|
||||
try { \
|
||||
__catchResult.captureMatch( arg, matcher, #matcher ); \
|
||||
__catchResult.captureMatch( arg, matcher, CATCH_INTERNAL_STRINGIFY(matcher) ); \
|
||||
} catch( ... ) { \
|
||||
__catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
|
||||
} \
|
||||
|
@ -76,6 +76,19 @@ namespace Catch {
|
||||
else
|
||||
throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
|
||||
}
|
||||
inline void setWaitForKeypress( ConfigData& config, std::string const& keypress ) {
|
||||
std::string keypressLc = toLower( keypress );
|
||||
if( keypressLc == "start" )
|
||||
config.waitForKeypress = WaitForKeypress::BeforeStart;
|
||||
else if( keypressLc == "exit" )
|
||||
config.waitForKeypress = WaitForKeypress::BeforeExit;
|
||||
else if( keypressLc == "both" )
|
||||
config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
|
||||
else
|
||||
throw std::runtime_error( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" );
|
||||
};
|
||||
|
||||
|
||||
inline void forceColour( ConfigData& config ) {
|
||||
config.useColour = UseColour::Yes;
|
||||
}
|
||||
@ -187,6 +200,10 @@ namespace Catch {
|
||||
.describe( "list all/matching test cases names only" )
|
||||
.bind( &ConfigData::listTestNamesOnly );
|
||||
|
||||
cli["--list-extra-info"]
|
||||
.describe( "list all/matching test cases with more info" )
|
||||
.bind( &ConfigData::listExtraInfo );
|
||||
|
||||
cli["--list-reporters"]
|
||||
.describe( "list all reporters" )
|
||||
.bind( &ConfigData::listReporters );
|
||||
@ -207,6 +224,14 @@ namespace Catch {
|
||||
.describe( "should output be colourised" )
|
||||
.bind( &setUseColour, "yes|no" );
|
||||
|
||||
cli["--libidentify"]
|
||||
.describe( "report name and version according to libidentify standard" )
|
||||
.bind( &ConfigData::libIdentify );
|
||||
|
||||
cli["--wait-for-keypress"]
|
||||
.describe( "waits for a keypress before exiting" )
|
||||
.bind( &setWaitForKeypress, "start|exit|both" );
|
||||
|
||||
return cli;
|
||||
}
|
||||
|
||||
|
@ -61,14 +61,14 @@ namespace Catch {
|
||||
};
|
||||
|
||||
template<typename ContainerT>
|
||||
inline void deleteAll( ContainerT& container ) {
|
||||
void deleteAll( ContainerT& container ) {
|
||||
typename ContainerT::const_iterator it = container.begin();
|
||||
typename ContainerT::const_iterator itEnd = container.end();
|
||||
for(; it != itEnd; ++it )
|
||||
delete *it;
|
||||
}
|
||||
template<typename AssociativeContainerT>
|
||||
inline void deleteAllValues( AssociativeContainerT& container ) {
|
||||
void deleteAllValues( AssociativeContainerT& container ) {
|
||||
typename AssociativeContainerT::const_iterator it = container.begin();
|
||||
typename AssociativeContainerT::const_iterator itEnd = container.end();
|
||||
for(; it != itEnd; ++it )
|
||||
|
@ -89,6 +89,10 @@
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __OS400__
|
||||
# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
|
||||
# define CATCH_CONFIG_COLOUR_NONE
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Cygwin
|
||||
@ -170,10 +174,15 @@
|
||||
|
||||
// Use __COUNTER__ if the compiler supports it
|
||||
#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
|
||||
( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
|
||||
( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \
|
||||
( defined __clang__ && __clang_major__ >= 3 )
|
||||
|
||||
#define CATCH_INTERNAL_CONFIG_COUNTER
|
||||
// Use of __COUNTER__ is suppressed during code analysis in CLion/AppCode 2017.2.x and former,
|
||||
// because __COUNTER__ is not properly handled by it.
|
||||
// This does not affect compilation
|
||||
#if ( !defined __JETBRAINS_IDE__ || __JETBRAINS_IDE__ >= 20170300L )
|
||||
#define CATCH_INTERNAL_CONFIG_COUNTER
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -254,10 +263,7 @@
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
|
||||
# define CATCH_CONFIG_CPP11_UNIQUE_PTR
|
||||
#endif
|
||||
// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
|
||||
// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
|
||||
// This does not affect compilation
|
||||
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
|
||||
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
|
||||
# define CATCH_CONFIG_COUNTER
|
||||
#endif
|
||||
#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
|
||||
|
@ -31,25 +31,29 @@ namespace Catch {
|
||||
listTags( false ),
|
||||
listReporters( false ),
|
||||
listTestNamesOnly( false ),
|
||||
listExtraInfo( false ),
|
||||
showSuccessfulTests( false ),
|
||||
shouldDebugBreak( false ),
|
||||
noThrow( false ),
|
||||
showHelp( false ),
|
||||
showInvisibles( false ),
|
||||
filenamesAsTags( false ),
|
||||
libIdentify( false ),
|
||||
abortAfter( -1 ),
|
||||
rngSeed( 0 ),
|
||||
verbosity( Verbosity::Normal ),
|
||||
warnings( WarnAbout::Nothing ),
|
||||
showDurations( ShowDurations::DefaultForReporter ),
|
||||
runOrder( RunTests::InDeclarationOrder ),
|
||||
useColour( UseColour::Auto )
|
||||
useColour( UseColour::Auto ),
|
||||
waitForKeypress( WaitForKeypress::Never )
|
||||
{}
|
||||
|
||||
bool listTests;
|
||||
bool listTags;
|
||||
bool listReporters;
|
||||
bool listTestNamesOnly;
|
||||
bool listExtraInfo;
|
||||
|
||||
bool showSuccessfulTests;
|
||||
bool shouldDebugBreak;
|
||||
@ -57,6 +61,7 @@ namespace Catch {
|
||||
bool showHelp;
|
||||
bool showInvisibles;
|
||||
bool filenamesAsTags;
|
||||
bool libIdentify;
|
||||
|
||||
int abortAfter;
|
||||
unsigned int rngSeed;
|
||||
@ -66,6 +71,7 @@ namespace Catch {
|
||||
ShowDurations::OrNot showDurations;
|
||||
RunTests::InWhatOrder runOrder;
|
||||
UseColour::YesOrNo useColour;
|
||||
WaitForKeypress::When waitForKeypress;
|
||||
|
||||
std::string outputFilename;
|
||||
std::string name;
|
||||
@ -109,6 +115,7 @@ namespace Catch {
|
||||
bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
|
||||
bool listTags() const { return m_data.listTags; }
|
||||
bool listReporters() const { return m_data.listReporters; }
|
||||
bool listExtraInfo() const { return m_data.listExtraInfo; }
|
||||
|
||||
std::string getProcessName() const { return m_data.processName; }
|
||||
|
||||
|
@ -26,9 +26,9 @@ namespace Catch{
|
||||
#if defined(__ppc64__) || defined(__ppc__)
|
||||
#define CATCH_TRAP() \
|
||||
__asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
|
||||
: : : "memory","r0","r3","r4" )
|
||||
: : : "memory","r0","r3","r4" ) /* NOLINT */
|
||||
#else
|
||||
#define CATCH_TRAP() __asm__("int $3\n" : : )
|
||||
#define CATCH_TRAP() __asm__("int $3\n" : : /* NOLINT */ )
|
||||
#endif
|
||||
|
||||
#elif defined(CATCH_PLATFORM_LINUX)
|
||||
@ -36,7 +36,7 @@ namespace Catch{
|
||||
// directly at the location of the failing check instead of breaking inside
|
||||
// raise() called from it, i.e. one stack frame below.
|
||||
#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
|
||||
#define CATCH_TRAP() asm volatile ("int $3")
|
||||
#define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */
|
||||
#else // Fall back to the generic way.
|
||||
#include <signal.h>
|
||||
|
||||
|
@ -10,9 +10,15 @@
|
||||
|
||||
#ifndef __OBJC__
|
||||
|
||||
#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
|
||||
// Standard C/C++ Win32 Unicode wmain entry point
|
||||
extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
|
||||
#else
|
||||
// Standard C/C++ main entry point
|
||||
int main (int argc, char * argv[]) {
|
||||
int result = Catch::Session().run( argc, argv );
|
||||
#endif
|
||||
|
||||
int result = Catch::Session().run( argc, argv );
|
||||
return ( result < 0xff ? result : 0xff );
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
|
||||
#pragma warning(disable:4018) // more "signed/unsigned mismatch"
|
||||
#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
|
||||
#endif
|
||||
|
||||
@ -37,177 +38,104 @@ namespace Internal {
|
||||
template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
|
||||
|
||||
template<typename T>
|
||||
inline T& opCast(T const& t) { return const_cast<T&>(t); }
|
||||
|
||||
// nullptr_t support based on pull request #154 from Konstantin Baumann
|
||||
T& removeConst(T const &t) { return const_cast<T&>(t); }
|
||||
#ifdef CATCH_CONFIG_CPP11_NULLPTR
|
||||
inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
|
||||
#endif // CATCH_CONFIG_CPP11_NULLPTR
|
||||
inline std::nullptr_t removeConst(std::nullptr_t) { return nullptr; }
|
||||
#endif
|
||||
|
||||
|
||||
// So the compare overloads can be operator agnostic we convey the operator as a template
|
||||
// enum, which is used to specialise an Evaluator for doing the comparison.
|
||||
template<typename T1, typename T2, Operator Op>
|
||||
class Evaluator{};
|
||||
struct Evaluator{};
|
||||
|
||||
template<typename T1, typename T2>
|
||||
struct Evaluator<T1, T2, IsEqualTo> {
|
||||
static bool evaluate( T1 const& lhs, T2 const& rhs) {
|
||||
return bool( opCast( lhs ) == opCast( rhs ) );
|
||||
return bool(removeConst(lhs) == removeConst(rhs) );
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Evaluator<T1, T2, IsNotEqualTo> {
|
||||
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
||||
return bool( opCast( lhs ) != opCast( rhs ) );
|
||||
return bool(removeConst(lhs) != removeConst(rhs) );
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Evaluator<T1, T2, IsLessThan> {
|
||||
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
||||
return bool( opCast( lhs ) < opCast( rhs ) );
|
||||
return bool(removeConst(lhs) < removeConst(rhs) );
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Evaluator<T1, T2, IsGreaterThan> {
|
||||
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
||||
return bool( opCast( lhs ) > opCast( rhs ) );
|
||||
return bool(removeConst(lhs) > removeConst(rhs) );
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
|
||||
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
||||
return bool( opCast( lhs ) >= opCast( rhs ) );
|
||||
return bool(removeConst(lhs) >= removeConst(rhs) );
|
||||
}
|
||||
};
|
||||
template<typename T1, typename T2>
|
||||
struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
|
||||
static bool evaluate( T1 const& lhs, T2 const& rhs ) {
|
||||
return bool( opCast( lhs ) <= opCast( rhs ) );
|
||||
return bool(removeConst(lhs) <= removeConst(rhs) );
|
||||
}
|
||||
};
|
||||
|
||||
template<Operator Op, typename T1, typename T2>
|
||||
bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
|
||||
return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
|
||||
}
|
||||
// Special case for comparing a pointer to an int (deduced for p==0)
|
||||
template<typename T>
|
||||
struct Evaluator<int const&, T* const&, IsEqualTo> {
|
||||
static bool evaluate( int lhs, T* rhs) {
|
||||
return reinterpret_cast<void const*>( lhs ) == rhs;
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct Evaluator<T* const&, int const&, IsEqualTo> {
|
||||
static bool evaluate( T* lhs, int rhs) {
|
||||
return lhs == reinterpret_cast<void const*>( rhs );
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct Evaluator<int const&, T* const&, IsNotEqualTo> {
|
||||
static bool evaluate( int lhs, T* rhs) {
|
||||
return reinterpret_cast<void const*>( lhs ) != rhs;
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct Evaluator<T* const&, int const&, IsNotEqualTo> {
|
||||
static bool evaluate( T* lhs, int rhs) {
|
||||
return lhs != reinterpret_cast<void const*>( rhs );
|
||||
}
|
||||
};
|
||||
|
||||
// This level of indirection allows us to specialise for integer types
|
||||
// to avoid signed/ unsigned warnings
|
||||
|
||||
// "base" overload
|
||||
template<Operator Op, typename T1, typename T2>
|
||||
bool compare( T1 const& lhs, T2 const& rhs ) {
|
||||
return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
|
||||
}
|
||||
|
||||
// unsigned X to int
|
||||
template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
|
||||
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
|
||||
}
|
||||
template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
|
||||
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
|
||||
}
|
||||
template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
|
||||
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
|
||||
}
|
||||
|
||||
// unsigned X to long
|
||||
template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
|
||||
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
|
||||
}
|
||||
template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
|
||||
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
|
||||
}
|
||||
template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
|
||||
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
|
||||
}
|
||||
|
||||
// int to unsigned X
|
||||
template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
|
||||
}
|
||||
|
||||
// long to unsigned X
|
||||
template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
|
||||
}
|
||||
|
||||
// pointer to long (when comparing against NULL)
|
||||
template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
|
||||
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
|
||||
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
|
||||
}
|
||||
|
||||
// pointer to int (when comparing against NULL)
|
||||
template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
|
||||
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
|
||||
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
|
||||
}
|
||||
|
||||
#ifdef CATCH_CONFIG_CPP11_LONG_LONG
|
||||
// long long to unsigned X
|
||||
template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
|
||||
}
|
||||
|
||||
// unsigned long long to X
|
||||
template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
|
||||
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
|
||||
}
|
||||
|
||||
// pointer to long long (when comparing against NULL)
|
||||
template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
|
||||
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
|
||||
}
|
||||
template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
|
||||
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
|
||||
}
|
||||
#endif // CATCH_CONFIG_CPP11_LONG_LONG
|
||||
|
||||
#ifdef CATCH_CONFIG_CPP11_NULLPTR
|
||||
// pointer to nullptr_t (when comparing against nullptr)
|
||||
template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
|
||||
return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
|
||||
}
|
||||
template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
|
||||
return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
|
||||
}
|
||||
#endif // CATCH_CONFIG_CPP11_NULLPTR
|
||||
template<typename T>
|
||||
struct Evaluator<long const&, T* const&, IsEqualTo> {
|
||||
static bool evaluate( long lhs, T* rhs) {
|
||||
return reinterpret_cast<void const*>( lhs ) == rhs;
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct Evaluator<T* const&, long const&, IsEqualTo> {
|
||||
static bool evaluate( T* lhs, long rhs) {
|
||||
return lhs == reinterpret_cast<void const*>( rhs );
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct Evaluator<long const&, T* const&, IsNotEqualTo> {
|
||||
static bool evaluate( long lhs, T* rhs) {
|
||||
return reinterpret_cast<void const*>( lhs ) != rhs;
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct Evaluator<T* const&, long const&, IsNotEqualTo> {
|
||||
static bool evaluate( T* lhs, long rhs) {
|
||||
return lhs != reinterpret_cast<void const*>( rhs );
|
||||
}
|
||||
};
|
||||
|
||||
} // end of namespace Internal
|
||||
} // end of namespace Catch
|
||||
|
@ -81,7 +81,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
|
||||
dest = Catch::toString( m_truthy );
|
||||
dest = Catch::toString( m_lhs );
|
||||
}
|
||||
|
||||
private:
|
||||
@ -111,7 +111,7 @@ public:
|
||||
|
||||
void endExpression() const {
|
||||
m_rb
|
||||
.setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
|
||||
.setResultType( Internal::Evaluator<LhsT, RhsT, Op>::evaluate( m_lhs, m_rhs ) )
|
||||
.endExpression( *this );
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace Catch {
|
||||
|
||||
namespace Catch {
|
||||
struct FatalConditionHandler {
|
||||
void reset() {}
|
||||
void reset() {}
|
||||
};
|
||||
}
|
||||
|
||||
@ -106,7 +106,7 @@ namespace Catch {
|
||||
|
||||
namespace Catch {
|
||||
struct FatalConditionHandler {
|
||||
void reset() {}
|
||||
void reset() {}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,10 @@ namespace Catch {
|
||||
virtual void exceptionEarlyReported() = 0;
|
||||
|
||||
virtual void handleFatalErrorCondition( std::string const& message ) = 0;
|
||||
|
||||
virtual bool lastAssertionPassed() = 0;
|
||||
virtual void assertionPassed() = 0;
|
||||
virtual void assertionRun() = 0;
|
||||
};
|
||||
|
||||
IResultCapture& getResultCapture();
|
||||
|
@ -42,6 +42,12 @@ namespace Catch {
|
||||
Yes,
|
||||
No
|
||||
}; };
|
||||
struct WaitForKeypress { enum When {
|
||||
Never,
|
||||
BeforeStart = 1,
|
||||
BeforeExit = 2,
|
||||
BeforeStartAndExit = BeforeStart | BeforeExit
|
||||
}; };
|
||||
|
||||
class TestSpec;
|
||||
|
||||
|
@ -30,8 +30,9 @@ namespace Catch {
|
||||
}
|
||||
|
||||
std::size_t matchedTests = 0;
|
||||
TextAttributes nameAttr, tagsAttr;
|
||||
TextAttributes nameAttr, descAttr, tagsAttr;
|
||||
nameAttr.setInitialIndent( 2 ).setIndent( 4 );
|
||||
descAttr.setIndent( 4 );
|
||||
tagsAttr.setIndent( 6 );
|
||||
|
||||
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
|
||||
@ -46,6 +47,13 @@ namespace Catch {
|
||||
Colour colourGuard( colour );
|
||||
|
||||
Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
|
||||
if( config.listExtraInfo() ) {
|
||||
Catch::cout() << " " << testCaseInfo.lineInfo << std::endl;
|
||||
std::string description = testCaseInfo.description;
|
||||
if( description.empty() )
|
||||
description = "(NO DESCRIPTION)";
|
||||
Catch::cout() << Text( description, descAttr ) << std::endl;
|
||||
}
|
||||
if( !testCaseInfo.tags.empty() )
|
||||
Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
|
||||
}
|
||||
@ -69,9 +77,12 @@ namespace Catch {
|
||||
matchedTests++;
|
||||
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
|
||||
if( startsWith( testCaseInfo.name, '#' ) )
|
||||
Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl;
|
||||
Catch::cout() << '"' << testCaseInfo.name << '"';
|
||||
else
|
||||
Catch::cout() << testCaseInfo.name << std::endl;
|
||||
Catch::cout() << testCaseInfo.name;
|
||||
if ( config.listExtraInfo() )
|
||||
Catch::cout() << "\t@" << testCaseInfo.lineInfo;
|
||||
Catch::cout() << std::endl;
|
||||
}
|
||||
return matchedTests;
|
||||
}
|
||||
@ -163,7 +174,7 @@ namespace Catch {
|
||||
|
||||
inline Option<std::size_t> list( Config const& config ) {
|
||||
Option<std::size_t> listedCount;
|
||||
if( config.listTests() )
|
||||
if( config.listTests() || ( config.listExtraInfo() && !config.listTestNamesOnly() ) )
|
||||
listedCount = listedCount.valueOr(0) + listTests( config );
|
||||
if( config.listTestNamesOnly() )
|
||||
listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
|
||||
|
@ -147,23 +147,23 @@ namespace Matchers {
|
||||
// This allows the types to be inferred
|
||||
// - deprecated: prefer ||, && and !
|
||||
template<typename T>
|
||||
inline Impl::MatchNotOf<T> Not( Impl::MatcherBase<T> const& underlyingMatcher ) {
|
||||
Impl::MatchNotOf<T> Not( Impl::MatcherBase<T> const& underlyingMatcher ) {
|
||||
return Impl::MatchNotOf<T>( underlyingMatcher );
|
||||
}
|
||||
template<typename T>
|
||||
inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
|
||||
Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
|
||||
return Impl::MatchAllOf<T>() && m1 && m2;
|
||||
}
|
||||
template<typename T>
|
||||
inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
|
||||
Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
|
||||
return Impl::MatchAllOf<T>() && m1 && m2 && m3;
|
||||
}
|
||||
template<typename T>
|
||||
inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
|
||||
Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
|
||||
return Impl::MatchAnyOf<T>() || m1 || m2;
|
||||
}
|
||||
template<typename T>
|
||||
inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
|
||||
Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
|
||||
return Impl::MatchAnyOf<T>() || m1 || m2 || m3;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@ namespace Catch {
|
||||
{
|
||||
public:
|
||||
NotImplementedException( SourceLineInfo const& lineInfo );
|
||||
NotImplementedException( NotImplementedException const& ) {}
|
||||
|
||||
virtual ~NotImplementedException() CATCH_NOEXCEPT {}
|
||||
|
||||
|
@ -104,7 +104,7 @@ namespace Catch {
|
||||
namespace Matchers {
|
||||
namespace Impl {
|
||||
namespace NSStringMatchers {
|
||||
|
||||
|
||||
struct StringHolder : MatcherBase<NSString*>{
|
||||
StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
|
||||
StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
|
||||
|
@ -69,7 +69,7 @@ namespace Catch {
|
||||
T *nullableValue;
|
||||
union {
|
||||
char storage[sizeof(T)];
|
||||
|
||||
|
||||
// These are here to force alignment for the storage
|
||||
long double dummy1;
|
||||
void (*dummy2)();
|
||||
|
@ -47,7 +47,7 @@ namespace Catch {
|
||||
|
||||
template<typename T>
|
||||
ResultBuilder& operator << ( T const& value ) {
|
||||
m_stream.oss << value;
|
||||
stream().oss << value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -80,11 +80,27 @@ namespace Catch {
|
||||
private:
|
||||
AssertionInfo m_assertionInfo;
|
||||
AssertionResultData m_data;
|
||||
CopyableStream m_stream;
|
||||
|
||||
CopyableStream &stream()
|
||||
{
|
||||
if(!m_usedStream)
|
||||
{
|
||||
m_usedStream = true;
|
||||
m_stream().oss.str("");
|
||||
}
|
||||
return m_stream();
|
||||
}
|
||||
|
||||
static CopyableStream &m_stream()
|
||||
{
|
||||
static CopyableStream s;
|
||||
return s;
|
||||
}
|
||||
|
||||
bool m_shouldDebugBreak;
|
||||
bool m_shouldThrow;
|
||||
bool m_guardException;
|
||||
bool m_usedStream;
|
||||
};
|
||||
|
||||
} // namespace Catch
|
||||
@ -95,7 +111,7 @@ namespace Catch {
|
||||
namespace Catch {
|
||||
|
||||
template<typename T>
|
||||
inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
|
||||
ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
|
||||
return ExpressionLhs<T const&>( *this, operand );
|
||||
}
|
||||
|
||||
@ -104,7 +120,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
template<typename ArgT, typename MatcherT>
|
||||
inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
|
||||
void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
|
||||
char const* matcherString ) {
|
||||
MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString );
|
||||
setResultType( matcher.match( arg ) );
|
||||
|
@ -18,26 +18,22 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
|
||||
return secondArg.empty() || secondArg == "\"\""
|
||||
? capturedExpression
|
||||
: capturedExpression + ", " + secondArg;
|
||||
}
|
||||
ResultBuilder::ResultBuilder( char const* macroName,
|
||||
SourceLineInfo const& lineInfo,
|
||||
char const* capturedExpression,
|
||||
ResultDisposition::Flags resultDisposition,
|
||||
char const* secondArg )
|
||||
: m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
|
||||
: m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition, secondArg ),
|
||||
m_shouldDebugBreak( false ),
|
||||
m_shouldThrow( false ),
|
||||
m_guardException( false )
|
||||
m_guardException( false ),
|
||||
m_usedStream( false )
|
||||
{}
|
||||
|
||||
ResultBuilder::~ResultBuilder() {
|
||||
#if defined(CATCH_CONFIG_FAST_COMPILE)
|
||||
if ( m_guardException ) {
|
||||
m_stream.oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
|
||||
stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
|
||||
captureResult( ResultWas::ThrewException );
|
||||
getCurrentContext().getResultCapture()->exceptionEarlyReported();
|
||||
}
|
||||
@ -54,13 +50,25 @@ namespace Catch {
|
||||
}
|
||||
|
||||
void ResultBuilder::endExpression( DecomposedExpression const& expr ) {
|
||||
AssertionResult result = build( expr );
|
||||
handleResult( result );
|
||||
// Flip bool results if FalseTest flag is set
|
||||
if( isFalseTest( m_assertionInfo.resultDisposition ) ) {
|
||||
m_data.negate( expr.isBinaryExpression() );
|
||||
}
|
||||
|
||||
getResultCapture().assertionRun();
|
||||
|
||||
if(getCurrentContext().getConfig()->includeSuccessfulResults() || m_data.resultType != ResultWas::Ok)
|
||||
{
|
||||
AssertionResult result = build( expr );
|
||||
handleResult( result );
|
||||
}
|
||||
else
|
||||
getResultCapture().assertionPassed();
|
||||
}
|
||||
|
||||
void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
|
||||
m_assertionInfo.resultDisposition = resultDisposition;
|
||||
m_stream.oss << Catch::translateActiveException();
|
||||
stream().oss << Catch::translateActiveException();
|
||||
captureResult( ResultWas::ThrewException );
|
||||
}
|
||||
|
||||
@ -82,7 +90,7 @@ namespace Catch {
|
||||
assert( !isFalseTest( m_assertionInfo.resultDisposition ) );
|
||||
AssertionResultData data = m_data;
|
||||
data.resultType = ResultWas::Ok;
|
||||
data.reconstructedExpression = m_assertionInfo.capturedExpression;
|
||||
data.reconstructedExpression = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg);
|
||||
|
||||
std::string actualMessage = Catch::translateActiveException();
|
||||
if( !matcher.match( actualMessage ) ) {
|
||||
@ -143,18 +151,14 @@ namespace Catch {
|
||||
assert( m_data.resultType != ResultWas::Unknown );
|
||||
AssertionResultData data = m_data;
|
||||
|
||||
// Flip bool results if FalseTest flag is set
|
||||
if( isFalseTest( m_assertionInfo.resultDisposition ) ) {
|
||||
data.negate( expr.isBinaryExpression() );
|
||||
}
|
||||
|
||||
data.message = m_stream.oss.str();
|
||||
if(m_usedStream)
|
||||
data.message = m_stream().oss.str();
|
||||
data.decomposedExpression = &expr; // for lazy reconstruction
|
||||
return AssertionResult( m_assertionInfo, data );
|
||||
}
|
||||
|
||||
void ResultBuilder::reconstructExpression( std::string& dest ) const {
|
||||
dest = m_assertionInfo.capturedExpression;
|
||||
dest = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg);
|
||||
}
|
||||
|
||||
void ResultBuilder::setExceptionGuard() {
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "catch_result_builder.h"
|
||||
#include "catch_fatal_condition.hpp"
|
||||
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
@ -50,6 +51,29 @@ namespace Catch {
|
||||
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)
|
||||
:m_cerrBuf( cerr().rdbuf() ), m_clogBuf(clog().rdbuf()),
|
||||
m_targetString(targetString){
|
||||
cerr().rdbuf(m_oss.rdbuf());
|
||||
clog().rdbuf(m_oss.rdbuf());
|
||||
}
|
||||
~StdErrRedirect() {
|
||||
m_targetString += m_oss.str();
|
||||
cerr().rdbuf(m_cerrBuf);
|
||||
clog().rdbuf(m_clogBuf);
|
||||
}
|
||||
private:
|
||||
std::streambuf* m_cerrBuf;
|
||||
std::streambuf* m_clogBuf;
|
||||
std::ostringstream m_oss;
|
||||
std::string& m_targetString;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class RunContext : public IResultCapture, public IRunner {
|
||||
@ -142,17 +166,38 @@ namespace Catch {
|
||||
m_totals.assertions.passed++;
|
||||
}
|
||||
else if( !result.isOk() ) {
|
||||
m_totals.assertions.failed++;
|
||||
if( m_activeTestCase->getTestCaseInfo().okToFail() )
|
||||
m_totals.assertions.failedButOk++;
|
||||
else
|
||||
m_totals.assertions.failed++;
|
||||
}
|
||||
|
||||
if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
|
||||
m_messages.clear();
|
||||
// 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.
|
||||
static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
|
||||
|
||||
// Reset working state
|
||||
m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
|
||||
m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
|
||||
m_lastResult = result;
|
||||
}
|
||||
|
||||
virtual bool lastAssertionPassed()
|
||||
{
|
||||
return m_totals.assertions.passed == (m_prevPassed + 1);
|
||||
}
|
||||
|
||||
virtual void assertionPassed()
|
||||
{
|
||||
m_totals.assertions.passed++;
|
||||
m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}";
|
||||
m_lastAssertionInfo.macroName = "";
|
||||
}
|
||||
|
||||
virtual void assertionRun()
|
||||
{
|
||||
m_prevPassed = m_totals.assertions.passed;
|
||||
}
|
||||
|
||||
virtual bool sectionStarted (
|
||||
SectionInfo const& sectionInfo,
|
||||
Counts& assertions
|
||||
@ -253,6 +298,7 @@ namespace Catch {
|
||||
|
||||
Totals deltaTotals;
|
||||
deltaTotals.testCases.failed = 1;
|
||||
deltaTotals.assertions.failed = 1;
|
||||
m_reporter->testCaseEnded( TestCaseStats( testInfo,
|
||||
deltaTotals,
|
||||
std::string(),
|
||||
@ -279,7 +325,7 @@ namespace Catch {
|
||||
double duration = 0;
|
||||
m_shouldReportUnexpected = true;
|
||||
try {
|
||||
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal );
|
||||
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
|
||||
|
||||
seedRng( *m_config );
|
||||
|
||||
@ -287,7 +333,7 @@ namespace Catch {
|
||||
timer.start();
|
||||
if( m_reporter->getPreferences().shouldRedirectStdOut ) {
|
||||
StreamRedirect coutRedir( Catch::cout(), redirectedCout );
|
||||
StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
|
||||
StdErrRedirect errRedir( redirectedCerr );
|
||||
invokeActiveTestCase();
|
||||
}
|
||||
else {
|
||||
@ -299,7 +345,7 @@ namespace Catch {
|
||||
// This just means the test was aborted due to failure
|
||||
}
|
||||
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.
|
||||
if (m_shouldReportUnexpected) {
|
||||
makeUnexpectedResultBuilder().useActiveException();
|
||||
@ -312,12 +358,6 @@ namespace Catch {
|
||||
Counts assertions = m_totals.assertions - prevAssertions;
|
||||
bool missingAssertions = testForMissingAssertions( assertions );
|
||||
|
||||
if( testCaseInfo.okToFail() ) {
|
||||
std::swap( assertions.failedButOk, assertions.failed );
|
||||
m_totals.assertions.failed -= assertions.failedButOk;
|
||||
m_totals.assertions.failedButOk += assertions.failedButOk;
|
||||
}
|
||||
|
||||
SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
|
||||
m_reporter->sectionEnded( testCaseSectionStats );
|
||||
}
|
||||
@ -331,9 +371,9 @@ namespace Catch {
|
||||
private:
|
||||
|
||||
ResultBuilder makeUnexpectedResultBuilder() const {
|
||||
return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
|
||||
return ResultBuilder( m_lastAssertionInfo.macroName,
|
||||
m_lastAssertionInfo.lineInfo,
|
||||
m_lastAssertionInfo.capturedExpression.c_str(),
|
||||
m_lastAssertionInfo.capturedExpression,
|
||||
m_lastAssertionInfo.resultDisposition );
|
||||
}
|
||||
|
||||
@ -363,6 +403,7 @@ namespace Catch {
|
||||
std::vector<SectionEndInfo> m_unfinishedSections;
|
||||
std::vector<ITracker*> m_activeSections;
|
||||
TrackerContext m_trackerContext;
|
||||
size_t m_prevPassed;
|
||||
bool m_shouldReportUnexpected;
|
||||
};
|
||||
|
||||
|
@ -30,6 +30,10 @@ namespace Catch {
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17
|
||||
#endif
|
||||
Section::~Section() {
|
||||
if( m_sectionIncluded ) {
|
||||
SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
|
||||
@ -39,6 +43,9 @@ namespace Catch {
|
||||
getResultCapture().sectionEnded( endInfo );
|
||||
}
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// This indicates whether the section should be executed or not
|
||||
Section::operator bool() const {
|
||||
|
@ -21,6 +21,7 @@ namespace Catch {
|
||||
|
||||
std::ostream& cout();
|
||||
std::ostream& cerr();
|
||||
std::ostream& clog();
|
||||
|
||||
|
||||
struct IStream {
|
||||
|
@ -103,6 +103,9 @@ namespace Catch {
|
||||
std::ostream& cerr() {
|
||||
return std::cerr;
|
||||
}
|
||||
std::ostream& clog() {
|
||||
return std::clog;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
namespace Catch {
|
||||
|
||||
struct RandomNumberGenerator {
|
||||
typedef std::ptrdiff_t result_type;
|
||||
typedef unsigned int result_type;
|
||||
|
||||
result_type operator()( result_type n ) const { return std::rand() % n; }
|
||||
|
||||
|
@ -88,7 +88,7 @@ void registerTestCaseFunction
|
||||
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
|
||||
static void TestName(); \
|
||||
CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } /* NOLINT */ \
|
||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
|
||||
static void TestName()
|
||||
#define INTERNAL_CATCH_TESTCASE( ... ) \
|
||||
@ -97,7 +97,7 @@ void registerTestCaseFunction
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
|
||||
CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } /* NOLINT */ \
|
||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -107,7 +107,7 @@ void registerTestCaseFunction
|
||||
struct TestName : ClassName{ \
|
||||
void test(); \
|
||||
}; \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); /* NOLINT */ \
|
||||
} \
|
||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
|
||||
void TestName::test()
|
||||
@ -117,7 +117,7 @@ void registerTestCaseFunction
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
|
||||
CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
|
||||
Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); \
|
||||
Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); /* NOLINT */ \
|
||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
|
||||
|
||||
#else
|
||||
@ -125,7 +125,7 @@ void registerTestCaseFunction
|
||||
#define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
|
||||
static void TestName(); \
|
||||
CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); } /* NOLINT */ \
|
||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
|
||||
static void TestName()
|
||||
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
|
||||
@ -134,7 +134,7 @@ void registerTestCaseFunction
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
|
||||
CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } \
|
||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } /* NOLINT */ \
|
||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -144,7 +144,7 @@ void registerTestCaseFunction
|
||||
struct TestCaseName : ClassName{ \
|
||||
void test(); \
|
||||
}; \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
|
||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); /* NOLINT */ \
|
||||
} \
|
||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
|
||||
void TestCaseName::test()
|
||||
@ -154,7 +154,7 @@ void registerTestCaseFunction
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
|
||||
CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
|
||||
Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); \
|
||||
Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); /* NOLINT */ \
|
||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
|
||||
|
||||
#endif
|
||||
|
@ -30,7 +30,7 @@ namespace Catch {
|
||||
ITagAliasRegistry const* m_tagAliases;
|
||||
|
||||
public:
|
||||
TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
|
||||
TestSpecParser( ITagAliasRegistry const& tagAliases ) :m_mode(None), m_exclusion(false), m_start(0), m_pos(0), m_tagAliases( &tagAliases ) {}
|
||||
|
||||
TestSpecParser& parse( std::string const& arg ) {
|
||||
m_mode = None;
|
||||
|
@ -28,21 +28,21 @@ namespace Catch {
|
||||
|
||||
namespace {
|
||||
#ifdef CATCH_PLATFORM_WINDOWS
|
||||
uint64_t getCurrentTicks() {
|
||||
static uint64_t hz=0, hzo=0;
|
||||
UInt64 getCurrentTicks() {
|
||||
static UInt64 hz=0, hzo=0;
|
||||
if (!hz) {
|
||||
QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
|
||||
QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
|
||||
}
|
||||
uint64_t t;
|
||||
UInt64 t;
|
||||
QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
|
||||
return ((t-hzo)*1000000)/hz;
|
||||
}
|
||||
#else
|
||||
uint64_t getCurrentTicks() {
|
||||
UInt64 getCurrentTicks() {
|
||||
timeval t;
|
||||
gettimeofday(&t,CATCH_NULL);
|
||||
return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
|
||||
return static_cast<UInt64>( t.tv_sec ) * 1000000ull + static_cast<UInt64>( t.tv_usec );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ std::string toString( std::nullptr_t );
|
||||
|
||||
#ifdef __OBJC__
|
||||
std::string toString( NSString const * const& nsstring );
|
||||
std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
|
||||
std::string toString( NSString * CATCH_ARC_STRONG & nsstring );
|
||||
std::string toString( NSObject* const& nsObject );
|
||||
#endif
|
||||
|
||||
@ -153,7 +153,7 @@ namespace Detail {
|
||||
std::string rawMemoryToString( const void *object, std::size_t size );
|
||||
|
||||
template<typename T>
|
||||
inline std::string rawMemoryToString( const T& object ) {
|
||||
std::string rawMemoryToString( const T& object ) {
|
||||
return rawMemoryToString( &object, sizeof(object) );
|
||||
}
|
||||
|
||||
|
@ -198,7 +198,7 @@ std::string toString( std::nullptr_t ) {
|
||||
return "nil";
|
||||
return "@" + toString([nsstring UTF8String]);
|
||||
}
|
||||
std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
|
||||
std::string toString( NSString * CATCH_ARC_STRONG & nsstring ) {
|
||||
if( !nsstring )
|
||||
return "nil";
|
||||
return "@" + toString([nsstring UTF8String]);
|
||||
|
@ -25,7 +25,7 @@ namespace Catch {
|
||||
#else
|
||||
|
||||
template <typename T>
|
||||
struct add_const {
|
||||
struct add_const {
|
||||
typedef const T type;
|
||||
};
|
||||
|
||||
|
@ -38,7 +38,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
inline Version libraryVersion() {
|
||||
static Version version( 1, 9, 2, "", 0 );
|
||||
static Version version( 1, 11, 0, "", 0 );
|
||||
return version;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include "catch_stream.h"
|
||||
#include "catch_compiler_capabilities.h"
|
||||
#include "catch_suppress_warnings.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
@ -241,6 +240,5 @@ namespace Catch {
|
||||
};
|
||||
|
||||
}
|
||||
#include "catch_reenable_warnings.h"
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
|
||||
|
@ -28,7 +28,7 @@ namespace Catch {
|
||||
// + 1 for null terminator
|
||||
const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
|
||||
char buffer[maxDoubleSize];
|
||||
|
||||
|
||||
// Save previous errno, to prevent sprintf from overwriting it
|
||||
ErrnoGuard guard;
|
||||
#ifdef _MSC_VER
|
||||
@ -137,7 +137,8 @@ namespace Catch {
|
||||
BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
|
||||
BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
|
||||
bool operator() ( Ptr<SectionNode> const& node ) const {
|
||||
return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
|
||||
return ((node->stats.sectionInfo.name == m_other.name) &&
|
||||
(node->stats.sectionInfo.lineInfo == m_other.lineInfo));
|
||||
}
|
||||
private:
|
||||
void operator=( BySectionInfo const& );
|
||||
|
@ -52,6 +52,7 @@ namespace Catch {
|
||||
JunitReporter( ReporterConfig const& _config )
|
||||
: CumulativeReporterBase( _config ),
|
||||
xml( _config.stream() ),
|
||||
unexpectedExceptions( 0 ),
|
||||
m_okToFail( false )
|
||||
{
|
||||
m_reporterPrefs.shouldRedirectStdOut = true;
|
||||
|
@ -141,6 +141,7 @@ namespace Catch {
|
||||
<< "]\n";
|
||||
}
|
||||
}
|
||||
stream.flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -150,9 +151,11 @@ namespace Catch {
|
||||
}
|
||||
|
||||
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
|
||||
m_testTimer.start();
|
||||
StreamingReporterBase::testCaseStarting( testInfo );
|
||||
stream << "##teamcity[testStarted name='"
|
||||
<< escape( testInfo.name ) << "']\n";
|
||||
stream.flush();
|
||||
}
|
||||
|
||||
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
|
||||
@ -166,7 +169,9 @@ namespace Catch {
|
||||
<< escape( testCaseStats.testInfo.name )
|
||||
<< "' out='" << escape( testCaseStats.stdErr ) << "']\n";
|
||||
stream << "##teamcity[testFinished name='"
|
||||
<< escape( testCaseStats.testInfo.name ) << "']\n";
|
||||
<< escape( testCaseStats.testInfo.name ) << "' duration='"
|
||||
<< m_testTimer.getElapsedMilliseconds() << "']\n";
|
||||
stream.flush();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -205,6 +210,7 @@ namespace Catch {
|
||||
}
|
||||
private:
|
||||
bool m_headerPrintedForThisSection;
|
||||
Timer m_testTimer;
|
||||
};
|
||||
|
||||
#ifdef CATCH_IMPL
|
||||
|
@ -24,6 +24,8 @@ TEST_CASE
|
||||
REQUIRE( Approx( d ) == 1.23 );
|
||||
REQUIRE( Approx( d ) != 1.22 );
|
||||
REQUIRE( Approx( d ) != 1.24 );
|
||||
|
||||
REQUIRE( 0 == Approx(0) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -146,11 +148,22 @@ TEST_CASE( "Approximate PI", "[Approx][PI]" )
|
||||
TEST_CASE( "Absolute margin", "[Approx]" ) {
|
||||
REQUIRE( 104.0 != Approx(100.0) );
|
||||
REQUIRE( 104.0 == Approx(100.0).margin(5) );
|
||||
REQUIRE( 104.0 == Approx(100.0).margin(4) );
|
||||
REQUIRE( 104.0 != Approx(100.0).margin(3) );
|
||||
REQUIRE( 100.3 != Approx(100.0) );
|
||||
REQUIRE( 100.3 == Approx(100.0).margin(0.5) );
|
||||
}
|
||||
|
||||
TEST_CASE("Approx with exactly-representable margin", "[Approx]") {
|
||||
CHECK( 0.25f == Approx(0.0f).margin(0.25f) );
|
||||
|
||||
CHECK( 0.0f == Approx(0.25f).margin(0.25f) );
|
||||
CHECK( 0.5f == Approx(0.25f).margin(0.25f) );
|
||||
|
||||
CHECK( 245.0f == Approx(245.25f).margin(0.25f) );
|
||||
CHECK( 245.5f == Approx(245.25f).margin(0.25f) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
|
||||
|
@ -58,6 +58,8 @@ with expansion:
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK_FALSE( true )
|
||||
with expansion:
|
||||
!true
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( !trueValue )
|
||||
@ -76,8 +78,6 @@ with expansion:
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK_FALSE( 1 == 1 )
|
||||
with expansion:
|
||||
!(1 == 1)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
A METHOD_AS_TEST_CASE based test run that fails
|
||||
@ -368,7 +368,9 @@ MessageTests.cpp:<line number>: FAILED:
|
||||
CHECK( a == 0 )
|
||||
with expansion:
|
||||
2 == 0
|
||||
with message:
|
||||
with messages:
|
||||
this message may be logged later
|
||||
this message should be logged
|
||||
and this, but later
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
@ -593,6 +595,17 @@ MessageTests.cpp:<line number>:
|
||||
warning:
|
||||
toString(p): 0x<hex digits>
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Reconstruction should be based on stringification: #914
|
||||
-------------------------------------------------------------------------------
|
||||
DecompositionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
DecompositionTests.cpp:<line number>: FAILED:
|
||||
CHECK( truthy(false) )
|
||||
with expansion:
|
||||
Hey, its truthy!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
SCOPED_INFO is reset for each loop
|
||||
-------------------------------------------------------------------------------
|
||||
@ -609,6 +622,9 @@ with messages:
|
||||
|
||||
A string sent directly to stdout
|
||||
A string sent directly to stderr
|
||||
Write to std::cerr
|
||||
Write to std::clog
|
||||
Interleaved writes to error streams
|
||||
Message from section one
|
||||
Message from section two
|
||||
-------------------------------------------------------------------------------
|
||||
@ -940,6 +956,6 @@ with expansion:
|
||||
"first" == "second"
|
||||
|
||||
===============================================================================
|
||||
test cases: 167 | 119 passed | 44 failed | 4 failed as expected
|
||||
assertions: 967 | 859 passed | 87 failed | 21 failed as expected
|
||||
test cases: 171 | 122 passed | 45 failed | 4 failed as expected
|
||||
assertions: 980 | 871 passed | 88 failed | 21 failed as expected
|
||||
|
||||
|
@ -119,10 +119,70 @@ with expansion:
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( (*__error()) == 1 )
|
||||
REQUIRE( errno == 1 )
|
||||
with expansion:
|
||||
1 == 1
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 0
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 1
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 2
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 3
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 4
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
'Not' checks that should fail
|
||||
-------------------------------------------------------------------------------
|
||||
@ -142,6 +202,8 @@ with expansion:
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK_FALSE( true )
|
||||
with expansion:
|
||||
!true
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK( !trueValue )
|
||||
@ -160,8 +222,6 @@ with expansion:
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK_FALSE( 1 == 1 )
|
||||
with expansion:
|
||||
!(1 == 1)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
'Not' checks that should succeed
|
||||
@ -186,6 +246,8 @@ with expansion:
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE_FALSE( false )
|
||||
with expansion:
|
||||
!false
|
||||
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
@ -208,8 +270,6 @@ with expansion:
|
||||
ConditionTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE_FALSE( 1 == 2 )
|
||||
with expansion:
|
||||
!(1 == 2)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
(unimplemented) static bools can be evaluated
|
||||
@ -397,6 +457,12 @@ PASSED:
|
||||
with expansion:
|
||||
104.0 == Approx( 100.0 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( 104.0 == Approx(100.0).margin(4) )
|
||||
with expansion:
|
||||
104.0 == Approx( 100.0 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( 104.0 != Approx(100.0).margin(3) )
|
||||
@ -492,6 +558,42 @@ with expansion:
|
||||
"this string contains 'abc' as a substring" ( contains: "not there" or
|
||||
contains: "string" )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Approx with exactly-representable margin
|
||||
-------------------------------------------------------------------------------
|
||||
ApproxTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( 0.25f == Approx(0.0f).margin(0.25f) )
|
||||
with expansion:
|
||||
0.25f == Approx( 0.0 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( 0.0f == Approx(0.25f).margin(0.25f) )
|
||||
with expansion:
|
||||
0.0f == Approx( 0.25 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( 0.5f == Approx(0.25f).margin(0.25f) )
|
||||
with expansion:
|
||||
0.5f == Approx( 0.25 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( 245.0f == Approx(245.25f).margin(0.25f) )
|
||||
with expansion:
|
||||
245.0f == Approx( 245.25 )
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( 245.5f == Approx(245.25f).margin(0.25f) )
|
||||
with expansion:
|
||||
245.5f == Approx( 245.25 )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Approximate PI
|
||||
-------------------------------------------------------------------------------
|
||||
@ -819,7 +921,7 @@ TrickyTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( a )
|
||||
with expansion:
|
||||
true
|
||||
0x<hex digits>
|
||||
|
||||
TrickyTests.cpp:<line number>:
|
||||
PASSED:
|
||||
@ -2717,14 +2819,17 @@ MessageTests.cpp:<line number>: FAILED:
|
||||
CHECK( a == 1 )
|
||||
with expansion:
|
||||
2 == 1
|
||||
with message:
|
||||
with messages:
|
||||
this message may be logged later
|
||||
this message should be logged
|
||||
|
||||
MessageTests.cpp:<line number>: FAILED:
|
||||
CHECK( a == 0 )
|
||||
with expansion:
|
||||
2 == 0
|
||||
with message:
|
||||
with messages:
|
||||
this message may be logged later
|
||||
this message should be logged
|
||||
and this, but later
|
||||
|
||||
MessageTests.cpp:<line number>:
|
||||
@ -2732,7 +2837,10 @@ PASSED:
|
||||
CHECK( a == 2 )
|
||||
with expansion:
|
||||
2 == 2
|
||||
with message:
|
||||
with messages:
|
||||
this message may be logged later
|
||||
this message should be logged
|
||||
and this, but later
|
||||
but not this
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
@ -4565,7 +4673,7 @@ TrickyTests.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK( True )
|
||||
with expansion:
|
||||
true
|
||||
1
|
||||
|
||||
TrickyTests.cpp:<line number>:
|
||||
PASSED:
|
||||
@ -4577,7 +4685,7 @@ TrickyTests.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK_FALSE( False )
|
||||
with expansion:
|
||||
!false
|
||||
!0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Operators at different namespace levels not hijacked by Koenig lookup
|
||||
@ -6431,6 +6539,17 @@ TestMain.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE_THROWS_WITH( parseIntoConfig( argv, config ), Contains( "colour mode must be one of" ) )
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Reconstruction should be based on stringification: #914
|
||||
-------------------------------------------------------------------------------
|
||||
DecompositionTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
DecompositionTests.cpp:<line number>: FAILED:
|
||||
CHECK( truthy(false) )
|
||||
with expansion:
|
||||
Hey, its truthy!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
SCOPED_INFO is reset for each loop
|
||||
-------------------------------------------------------------------------------
|
||||
@ -6769,6 +6888,45 @@ PASSED:
|
||||
with expansion:
|
||||
Approx( 1.23 ) != 1.24
|
||||
|
||||
ApproxTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( 0 == Approx(0) )
|
||||
with expansion:
|
||||
0 == Approx( 0.0 )
|
||||
|
||||
Write to std::cerr
|
||||
-------------------------------------------------------------------------------
|
||||
Standard error is reported and redirected
|
||||
std::cerr
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in section 'std::cerr'
|
||||
|
||||
Write to std::clog
|
||||
-------------------------------------------------------------------------------
|
||||
Standard error is reported and redirected
|
||||
std::clog
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in section 'std::clog'
|
||||
|
||||
Interleaved writes to error streams
|
||||
-------------------------------------------------------------------------------
|
||||
Standard error is reported and redirected
|
||||
Interleaved writes to cerr and clog
|
||||
-------------------------------------------------------------------------------
|
||||
MessageTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
|
||||
No assertions in section 'Interleaved writes to cerr and clog'
|
||||
|
||||
Message from section one
|
||||
-------------------------------------------------------------------------------
|
||||
Standard output from all sections is reported
|
||||
@ -9466,6 +9624,6 @@ MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
|
||||
===============================================================================
|
||||
test cases: 167 | 118 passed | 45 failed | 4 failed as expected
|
||||
assertions: 969 | 859 passed | 89 failed | 21 failed as expected
|
||||
test cases: 171 | 120 passed | 47 failed | 4 failed as expected
|
||||
assertions: 985 | 871 passed | 93 failed | 21 failed as expected
|
||||
|
||||
|
@ -119,10 +119,70 @@ with expansion:
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE( (*__error()) == 1 )
|
||||
REQUIRE( errno == 1 )
|
||||
with expansion:
|
||||
1 == 1
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 0
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 1
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 2
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 3
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 4
|
||||
-------------------------------------------------------------------------------
|
||||
MiscTests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
MiscTests.cpp:<line number>:
|
||||
PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
'Not' checks that should fail
|
||||
-------------------------------------------------------------------------------
|
||||
@ -142,8 +202,10 @@ with expansion:
|
||||
|
||||
ConditionTests.cpp:<line number>: FAILED:
|
||||
CHECK_FALSE( true )
|
||||
with expansion:
|
||||
!true
|
||||
|
||||
===============================================================================
|
||||
test cases: 6 | 3 passed | 1 failed | 2 failed as expected
|
||||
assertions: 18 | 11 passed | 4 failed | 3 failed as expected
|
||||
test cases: 7 | 4 passed | 1 failed | 2 failed as expected
|
||||
assertions: 23 | 16 passed | 4 failed | 3 failed as expected
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuitesspanner>
|
||||
<testsuite name="<exe-name>" errors="13" failures="77" tests="970" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="13" failures="81" tests="986" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testcase classname="global" name="# A test name that starts with a #" time="{duration}"/>
|
||||
<testcase classname="#748 - captures with unexpected exceptions" name="outside assertions" time="{duration}">
|
||||
<error type="TEST_CASE">
|
||||
@ -24,6 +24,11 @@ ExceptionTests.cpp:<line number>
|
||||
MiscTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="#961 -- Dynamically created sections should all be reported" name="Looped section 0" time="{duration}"/>
|
||||
<testcase classname="#961 -- Dynamically created sections should all be reported" name="Looped section 1" time="{duration}"/>
|
||||
<testcase classname="#961 -- Dynamically created sections should all be reported" name="Looped section 2" time="{duration}"/>
|
||||
<testcase classname="#961 -- Dynamically created sections should all be reported" name="Looped section 3" time="{duration}"/>
|
||||
<testcase classname="#961 -- Dynamically created sections should all be reported" name="Looped section 4" time="{duration}"/>
|
||||
<testcase classname="global" name="'Not' checks that should fail" time="{duration}">
|
||||
<failure message="false != false" type="CHECK">
|
||||
ConditionTests.cpp:<line number>
|
||||
@ -94,6 +99,7 @@ ExceptionTests.cpp:<line number>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Anonymous test case 1" time="{duration}"/>
|
||||
<testcase classname="global" name="AnyOf matcher" time="{duration}"/>
|
||||
<testcase classname="global" name="Approx with exactly-representable margin" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate PI" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate comparisons with different epsilons" time="{duration}"/>
|
||||
<testcase classname="global" name="Approximate comparisons with floats" time="{duration}"/>
|
||||
@ -237,10 +243,13 @@ MessageTests.cpp:<line number>
|
||||
</testcase>
|
||||
<testcase classname="global" name="INFO gets logged on failure, even if captured before successful assertions" time="{duration}">
|
||||
<failure message="2 == 1" type="CHECK">
|
||||
this message may be logged later
|
||||
this message should be logged
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="2 == 0" type="CHECK">
|
||||
this message may be logged later
|
||||
this message should be logged
|
||||
and this, but later
|
||||
MessageTests.cpp:<line number>
|
||||
</failure>
|
||||
@ -440,6 +449,11 @@ MessageTests.cpp:<line number>
|
||||
<testcase classname="Process can be configured on command line" name="use-colour/yes" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="use-colour/no" time="{duration}"/>
|
||||
<testcase classname="Process can be configured on command line" name="use-colour/error" time="{duration}"/>
|
||||
<testcase classname="global" name="Reconstruction should be based on stringification: #914" time="{duration}">
|
||||
<failure message="Hey, its truthy!" type="CHECK">
|
||||
DecompositionTests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="global" name="SCOPED_INFO is reset for each loop" time="{duration}">
|
||||
<failure message="10 < 10" type="REQUIRE">
|
||||
current counter 10
|
||||
@ -467,6 +481,13 @@ A string sent directly to stderr
|
||||
</system-err>
|
||||
</testcase>
|
||||
<testcase classname="global" name="Some simple comparisons between doubles" time="{duration}"/>
|
||||
<testcase classname="Standard error is reported and redirected" name="Interleaved writes to cerr and clog" time="{duration}">
|
||||
<system-err>
|
||||
Write to std::cerr
|
||||
Write to std::clog
|
||||
Interleaved writes to error streams
|
||||
</system-err>
|
||||
</testcase>
|
||||
<testcase classname="Standard output from all sections is reported" name="two" time="{duration}">
|
||||
<system-out>
|
||||
Message from section one
|
||||
@ -742,6 +763,9 @@ hello
|
||||
</system-out>
|
||||
<system-err>
|
||||
A string sent directly to stderr
|
||||
Write to std::cerr
|
||||
Write to std::clog
|
||||
Interleaved writes to error streams
|
||||
</system-err>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<Exception filename="projects/<exe-name>/ExceptionTests.cpp" >
|
||||
expected exception
|
||||
</Exception>
|
||||
<OverallResults successes="0" failures="1" expectedFailures="0"/>
|
||||
<OverallResults successes="0" failures="0" expectedFailures="1"/>
|
||||
</Section>
|
||||
<Section name="inside REQUIRE_NOTHROW" filename="projects/<exe-name>/ExceptionTests.cpp" >
|
||||
<Info>
|
||||
@ -29,7 +29,7 @@
|
||||
expected exception
|
||||
</Exception>
|
||||
</Expression>
|
||||
<OverallResults successes="0" failures="1" expectedFailures="0"/>
|
||||
<OverallResults successes="0" failures="0" expectedFailures="1"/>
|
||||
</Section>
|
||||
<Section name="inside REQUIRE_THROWS" filename="projects/<exe-name>/ExceptionTests.cpp" >
|
||||
<Info>
|
||||
@ -128,7 +128,7 @@
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MiscTests.cpp" >
|
||||
<Original>
|
||||
(*__error()) == 1
|
||||
errno == 1
|
||||
</Original>
|
||||
<Expanded>
|
||||
1 == 1
|
||||
@ -136,6 +136,24 @@
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="#961 -- Dynamically created sections should all be reported" tags="[.][hide]" filename="projects/<exe-name>/MiscTests.cpp" >
|
||||
<Section name="Looped section 0" filename="projects/<exe-name>/MiscTests.cpp" >
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="Looped section 1" filename="projects/<exe-name>/MiscTests.cpp" >
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="Looped section 2" filename="projects/<exe-name>/MiscTests.cpp" >
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="Looped section 3" filename="projects/<exe-name>/MiscTests.cpp" >
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="Looped section 4" filename="projects/<exe-name>/MiscTests.cpp" >
|
||||
<OverallResults successes="1" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="'Not' checks that should fail" tags="[.][failing][hide]" filename="projects/<exe-name>/ConditionTests.cpp" >
|
||||
<Expression success="false" type="CHECK" filename="projects/<exe-name>/ConditionTests.cpp" >
|
||||
<Original>
|
||||
@ -163,7 +181,7 @@
|
||||
</Expression>
|
||||
<Expression success="false" type="CHECK_FALSE" filename="projects/<exe-name>/ConditionTests.cpp" >
|
||||
<Original>
|
||||
!true
|
||||
!(true)
|
||||
</Original>
|
||||
<Expanded>
|
||||
!true
|
||||
@ -179,7 +197,7 @@
|
||||
</Expression>
|
||||
<Expression success="false" type="CHECK_FALSE" filename="projects/<exe-name>/ConditionTests.cpp" >
|
||||
<Original>
|
||||
!trueValue
|
||||
!(trueValue)
|
||||
</Original>
|
||||
<Expanded>
|
||||
!true
|
||||
@ -195,7 +213,7 @@
|
||||
</Expression>
|
||||
<Expression success="false" type="CHECK_FALSE" filename="projects/<exe-name>/ConditionTests.cpp" >
|
||||
<Original>
|
||||
!1 == 1
|
||||
!(1 == 1)
|
||||
</Original>
|
||||
<Expanded>
|
||||
!(1 == 1)
|
||||
@ -230,7 +248,7 @@
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/ConditionTests.cpp" >
|
||||
<Original>
|
||||
!false
|
||||
!(false)
|
||||
</Original>
|
||||
<Expanded>
|
||||
!false
|
||||
@ -246,7 +264,7 @@
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/ConditionTests.cpp" >
|
||||
<Original>
|
||||
!falseValue
|
||||
!(falseValue)
|
||||
</Original>
|
||||
<Expanded>
|
||||
!false
|
||||
@ -262,7 +280,7 @@
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/ConditionTests.cpp" >
|
||||
<Original>
|
||||
!1 == 2
|
||||
!(1 == 2)
|
||||
</Original>
|
||||
<Expanded>
|
||||
!(1 == 2)
|
||||
@ -342,7 +360,7 @@
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/TrickyTests.cpp" >
|
||||
<Original>
|
||||
!is_true<false>::value
|
||||
!(is_true<false>::value)
|
||||
</Original>
|
||||
<Expanded>
|
||||
!false
|
||||
@ -444,6 +462,14 @@
|
||||
104.0 == Approx( 100.0 )
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Original>
|
||||
104.0 == Approx(100.0).margin(4)
|
||||
</Original>
|
||||
<Expanded>
|
||||
104.0 == Approx( 100.0 )
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Original>
|
||||
104.0 != Approx(100.0).margin(3)
|
||||
@ -547,6 +573,49 @@
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="Approx with exactly-representable margin" tags="[Approx]" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Expression success="true" type="CHECK" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Original>
|
||||
0.25f == Approx(0.0f).margin(0.25f)
|
||||
</Original>
|
||||
<Expanded>
|
||||
0.25f == Approx( 0.0 )
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Original>
|
||||
0.0f == Approx(0.25f).margin(0.25f)
|
||||
</Original>
|
||||
<Expanded>
|
||||
0.0f == Approx( 0.25 )
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Original>
|
||||
0.5f == Approx(0.25f).margin(0.25f)
|
||||
</Original>
|
||||
<Expanded>
|
||||
0.5f == Approx( 0.25 )
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Original>
|
||||
245.0f == Approx(245.25f).margin(0.25f)
|
||||
</Original>
|
||||
<Expanded>
|
||||
245.0f == Approx( 245.25 )
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Original>
|
||||
245.5f == Approx(245.25f).margin(0.25f)
|
||||
</Original>
|
||||
<Expanded>
|
||||
245.5f == Approx( 245.25 )
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="Approximate PI" tags="[Approx][PI]" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Original>
|
||||
@ -890,7 +959,7 @@
|
||||
a
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
0x<hex digits>
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/TrickyTests.cpp" >
|
||||
@ -2690,7 +2759,7 @@
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Original>
|
||||
!d >= Approx( 1.24 )
|
||||
!(d >= Approx( 1.24 ))
|
||||
</Original>
|
||||
<Expanded>
|
||||
!(1.23 >= Approx( 1.24 ))
|
||||
@ -2744,6 +2813,9 @@
|
||||
2 == 2
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Info>
|
||||
this message may be logged later
|
||||
</Info>
|
||||
<Info>
|
||||
this message should be logged
|
||||
</Info>
|
||||
@ -2755,6 +2827,12 @@
|
||||
2 == 1
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Info>
|
||||
this message may be logged later
|
||||
</Info>
|
||||
<Info>
|
||||
this message should be logged
|
||||
</Info>
|
||||
<Info>
|
||||
and this, but later
|
||||
</Info>
|
||||
@ -2766,6 +2844,15 @@
|
||||
2 == 0
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Info>
|
||||
this message may be logged later
|
||||
</Info>
|
||||
<Info>
|
||||
this message should be logged
|
||||
</Info>
|
||||
<Info>
|
||||
and this, but later
|
||||
</Info>
|
||||
<Info>
|
||||
but not this
|
||||
</Info>
|
||||
@ -2932,7 +3019,7 @@
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Original>
|
||||
!d <= Approx( 1.22 )
|
||||
!(d <= Approx( 1.22 ))
|
||||
</Original>
|
||||
<Expanded>
|
||||
!(1.23 <= Approx( 1.22 ))
|
||||
@ -4677,7 +4764,7 @@ re>"
|
||||
True
|
||||
</Original>
|
||||
<Expanded>
|
||||
true
|
||||
1
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK" filename="projects/<exe-name>/TrickyTests.cpp" >
|
||||
@ -4690,10 +4777,10 @@ re>"
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK_FALSE" filename="projects/<exe-name>/TrickyTests.cpp" >
|
||||
<Original>
|
||||
!False
|
||||
!(False)
|
||||
</Original>
|
||||
<Expanded>
|
||||
!false
|
||||
!0
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
@ -6894,6 +6981,17 @@ re>"
|
||||
</Section>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="Reconstruction should be based on stringification: #914" tags="[.][Decomposition][failing][hide]" filename="projects/<exe-name>/DecompositionTests.cpp" >
|
||||
<Expression success="false" type="CHECK" filename="projects/<exe-name>/DecompositionTests.cpp" >
|
||||
<Original>
|
||||
truthy(false)
|
||||
</Original>
|
||||
<Expanded>
|
||||
Hey, its truthy!
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="SCOPED_INFO is reset for each loop" tags="[.][failing][hide][messages]" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<Info>
|
||||
current counter 0
|
||||
@ -7278,8 +7376,34 @@ A string sent directly to stderr
|
||||
Approx( 1.23 ) != 1.24
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ApproxTests.cpp" >
|
||||
<Original>
|
||||
0 == Approx(0)
|
||||
</Original>
|
||||
<Expanded>
|
||||
0 == Approx( 0.0 )
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="Standard error is reported and redirected" tags="[.][hide][messages]" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<Section name="std::cerr" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<OverallResults successes="0" failures="1" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="std::clog" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<OverallResults successes="0" failures="1" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="Interleaved writes to cerr and clog" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<OverallResults successes="0" failures="1" expectedFailures="0"/>
|
||||
</Section>
|
||||
<OverallResult success="false">
|
||||
<StdErr>
|
||||
Write to std::cerr
|
||||
Write to std::clog
|
||||
Interleaved writes to error streams
|
||||
</StdErr>
|
||||
</OverallResult>
|
||||
</TestCase>
|
||||
<TestCase name="Standard output from all sections is reported" tags="[.][hide][messages]" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<Section name="one" filename="projects/<exe-name>/MessageTests.cpp" >
|
||||
<OverallResults successes="0" failures="1" expectedFailures="0"/>
|
||||
@ -9644,7 +9768,7 @@ spanner <OverallResult success="true"/>
|
||||
<Section name="replace no chars" filename="projects/<exe-name>/TestMain.cpp" >
|
||||
<Expression success="true" type="CHECK_FALSE" filename="projects/<exe-name>/TestMain.cpp" >
|
||||
<Original>
|
||||
!replaceInPlace( letters, "x", "z" )
|
||||
!(replaceInPlace( letters, "x", "z" ))
|
||||
</Original>
|
||||
<Expanded>
|
||||
!false
|
||||
@ -10114,7 +10238,7 @@ spanner <OverallResult success="true"/>
|
||||
</Section>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<OverallResults successes="859" failures="90" expectedFailures="21"/>
|
||||
<OverallResults successes="871" failures="94" expectedFailures="21"/>
|
||||
</Group>
|
||||
<OverallResults successes="859" failures="89" expectedFailures="21"/>
|
||||
<OverallResults successes="871" failures="93" expectedFailures="21"/>
|
||||
</Catch>
|
||||
|
28
projects/SelfTest/DecompositionTests.cpp
Normal file
28
projects/SelfTest/DecompositionTests.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Created by Martin on 27/5/2017.
|
||||
* Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
struct truthy {
|
||||
truthy(bool b):m_value(b){}
|
||||
operator bool() const {
|
||||
return false;
|
||||
}
|
||||
bool m_value;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, truthy) {
|
||||
o << "Hey, its truthy!";
|
||||
return o;
|
||||
}
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
TEST_CASE( "Reconstruction should be based on stringification: #914" , "[Decomposition][failing][.]") {
|
||||
CHECK(truthy(false));
|
||||
}
|
@ -99,6 +99,23 @@ TEST_CASE( "Standard output from all sections is reported", "[messages][.]" )
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Standard error is reported and redirected", "[messages][.]" ) {
|
||||
SECTION( "std::cerr" ) {
|
||||
std::cerr << "Write to std::cerr" << std::endl;
|
||||
}
|
||||
SECTION( "std::clog" ) {
|
||||
std::clog << "Write to std::clog" << std::endl;
|
||||
}
|
||||
SECTION( "Interleaved writes to cerr and clog" ) {
|
||||
std::cerr << "Inter";
|
||||
std::clog << "leaved";
|
||||
std::cerr << ' ';
|
||||
std::clog << "writes";
|
||||
std::cerr << " to error";
|
||||
std::clog << " streams\n";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "SCOPED_INFO is reset for each loop", "[messages][failing][.]" )
|
||||
{
|
||||
for( int i=0; i<100; i++ )
|
||||
|
@ -403,5 +403,13 @@ static int f() {
|
||||
TEST_CASE( "#835 -- errno should not be touched by Catch", "[!shouldfail]" ) {
|
||||
errno = 1;
|
||||
CHECK(f() == 0);
|
||||
REQUIRE(errno == 1); // Check that f() doesn't touch errno.
|
||||
REQUIRE(errno == 1); // Check that f() doesn't touch errno.
|
||||
}
|
||||
|
||||
TEST_CASE( "#961 -- Dynamically created sections should all be reported", "[.]" ) {
|
||||
for (char i = '0'; i < '5'; ++i) {
|
||||
SECTION(std::string("Looped section ") + i) {
|
||||
SUCCEED( "Everything is OK" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
|
||||
TEST_CASE( "Character pretty printing" ){
|
||||
//
|
||||
SECTION("Specifically escaped"){
|
||||
char tab = '\t';
|
||||
char newline = '\n';
|
||||
@ -36,7 +35,7 @@ TEST_CASE( "Character pretty printing" ){
|
||||
char c = static_cast<char>(i);
|
||||
REQUIRE(c == i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -407,3 +407,9 @@ TEST_CASE( "has printf", "" ) {
|
||||
// This can cause problems as, currently, stdout itself is not redirect - only the cout (and cerr) buffer
|
||||
printf( "spanner" );
|
||||
}
|
||||
|
||||
TEST_CASE( "null deref", "[.][failing][!nonportable]" ) {
|
||||
CHECK( false );
|
||||
int *x = NULL;
|
||||
*x = 1;
|
||||
}
|
||||
|
@ -36,6 +36,13 @@ exeNameParser = re.compile(r'''
|
||||
# This is a hack until something more reasonable is figured out
|
||||
specialCaseParser = re.compile(r'file\((\d+)\)')
|
||||
|
||||
# errno macro expands into various names depending on platform, so we need to fix them up as well
|
||||
errnoParser = re.compile(r'''
|
||||
\(\*__errno_location\ \(\)\)
|
||||
|
|
||||
\(\*__error\(\)\)
|
||||
''', re.VERBOSE)
|
||||
|
||||
if len(sys.argv) == 2:
|
||||
cmdPath = sys.argv[1]
|
||||
else:
|
||||
@ -45,9 +52,9 @@ overallResult = 0
|
||||
|
||||
def diffFiles(fileA, fileB):
|
||||
with open(fileA, 'r') as file:
|
||||
aLines = file.readlines()
|
||||
aLines = [line.rstrip() for line in file.readlines()]
|
||||
with open(fileB, 'r') as file:
|
||||
bLines = file.readlines()
|
||||
bLines = [line.rstrip() for line in file.readlines()]
|
||||
|
||||
shortenedFilenameA = fileA.rsplit(os.sep, 1)[-1]
|
||||
shortenedFilenameB = fileB.rsplit(os.sep, 1)[-1]
|
||||
@ -90,6 +97,7 @@ def filterLine(line):
|
||||
line = durationsParser.sub(' time="{duration}"', line)
|
||||
line = timestampsParser.sub(' timestamp="{iso8601-timestamp}"', line)
|
||||
line = specialCaseParser.sub('file:\g<1>', line)
|
||||
line = errnoParser.sub('errno', line)
|
||||
return line
|
||||
|
||||
|
||||
@ -119,7 +127,7 @@ def approve(baseName, args):
|
||||
if os.path.exists(baselinesPath):
|
||||
diffResult = diffFiles(baselinesPath, filteredResultsPath)
|
||||
if diffResult:
|
||||
print(''.join(diffResult))
|
||||
print('\n'.join(diffResult))
|
||||
print(" \n****************************\n \033[91mResults differed")
|
||||
if len(diffResult) > overallResult:
|
||||
overallResult = len(diffResult)
|
||||
|
@ -7,5 +7,7 @@ v = Version()
|
||||
v.incrementBuildNumber()
|
||||
v.updateVersionFile()
|
||||
v.updateReadmeFile()
|
||||
v.updateConanFile()
|
||||
v.updateConanTestFile()
|
||||
|
||||
print( "Updated Version.hpp and README to v{0}".format( v.getVersionString() ) )
|
||||
print( "Updated Version.hpp, README and Conan to v{0}".format( v.getVersionString() ) )
|
||||
|
@ -9,97 +9,100 @@ import datetime
|
||||
import string
|
||||
|
||||
from scriptCommon import catchPath
|
||||
from releaseCommon import Version
|
||||
|
||||
|
||||
includesParser = re.compile( r'\s*#\s*include\s*"(.*)"' )
|
||||
guardParser = re.compile( r'\s*#.*TWOBLUECUBES_CATCH_.*_INCLUDED')
|
||||
defineParser = re.compile( r'\s*#define')
|
||||
ifParser = re.compile( r'\s*#ifndef TWOBLUECUBES_CATCH_.*_INCLUDED')
|
||||
endIfParser = re.compile( r'\s*#endif // TWOBLUECUBES_CATCH_.*_INCLUDED')
|
||||
ifImplParser = re.compile( r'\s*#ifdef CATCH_CONFIG_RUNNER' )
|
||||
commentParser1 = re.compile( r'^\s*/\*')
|
||||
commentParser2 = re.compile( r'^ \*')
|
||||
blankParser = re.compile( r'^\s*$')
|
||||
seenHeaders = set([])
|
||||
rootPath = os.path.join( catchPath, 'include/' )
|
||||
outputPath = os.path.join( catchPath, 'single_include/catch.hpp' )
|
||||
def generate(v):
|
||||
includesParser = re.compile( r'\s*#\s*include\s*"(.*)"' )
|
||||
guardParser = re.compile( r'\s*#.*TWOBLUECUBES_CATCH_.*_INCLUDED')
|
||||
defineParser = re.compile( r'\s*#define')
|
||||
ifParser = re.compile( r'\s*#ifndef TWOBLUECUBES_CATCH_.*_INCLUDED')
|
||||
endIfParser = re.compile( r'\s*#endif // TWOBLUECUBES_CATCH_.*_INCLUDED')
|
||||
ifImplParser = re.compile( r'\s*#ifdef CATCH_CONFIG_RUNNER' )
|
||||
commentParser1 = re.compile( r'^\s*/\*')
|
||||
commentParser2 = re.compile( r'^ \*')
|
||||
blankParser = re.compile( r'^\s*$')
|
||||
seenHeaders = set([])
|
||||
rootPath = os.path.join( catchPath, 'include/' )
|
||||
outputPath = os.path.join( catchPath, 'single_include/catch.hpp' )
|
||||
|
||||
includeImpl = True
|
||||
|
||||
for arg in sys.argv[1:]:
|
||||
arg = string.lower(arg)
|
||||
if arg == "noimpl":
|
||||
includeImpl = False
|
||||
print( "Not including impl code" )
|
||||
else:
|
||||
print( "\n** Unrecognised argument: " + arg + " **\n" )
|
||||
exit(1)
|
||||
globals = {
|
||||
'ifdefs' : 0,
|
||||
'implIfDefs' : -1,
|
||||
'includeImpl': True
|
||||
}
|
||||
|
||||
out = open( outputPath, 'w' )
|
||||
ifdefs = 0
|
||||
implIfDefs = -1
|
||||
|
||||
def write( line ):
|
||||
if includeImpl or implIfDefs == -1:
|
||||
out.write( line )
|
||||
|
||||
def parseFile( path, filename ):
|
||||
global ifdefs
|
||||
global implIfDefs
|
||||
|
||||
f = open( path + filename, 'r' )
|
||||
blanks = 0
|
||||
for line in f:
|
||||
if ifParser.match( line ):
|
||||
ifdefs = ifdefs + 1
|
||||
elif endIfParser.match( line ):
|
||||
ifdefs = ifdefs - 1
|
||||
if ifdefs == implIfDefs:
|
||||
implIfDefs = -1
|
||||
m = includesParser.match( line )
|
||||
if m:
|
||||
header = m.group(1)
|
||||
headerPath, sep, headerFile = header.rpartition( "/" )
|
||||
if not headerFile in seenHeaders:
|
||||
if headerFile != "tbc_text_format.h" and headerFile != "clara.h":
|
||||
seenHeaders.add( headerFile )
|
||||
write( "// #included from: {0}\n".format( header ) )
|
||||
if headerPath == "internal" and path.endswith("internal/"):
|
||||
headerPath = ""
|
||||
sep = ""
|
||||
if os.path.exists( path + headerPath + sep + headerFile ):
|
||||
parseFile( path + headerPath + sep, headerFile )
|
||||
else:
|
||||
parseFile( rootPath + headerPath + sep, headerFile )
|
||||
for arg in sys.argv[1:]:
|
||||
arg = string.lower(arg)
|
||||
if arg == "noimpl":
|
||||
globals['includeImpl'] = False
|
||||
print( "Not including impl code" )
|
||||
else:
|
||||
if ifImplParser.match(line):
|
||||
implIfDefs = ifdefs
|
||||
if (not guardParser.match( line ) or defineParser.match( line ) ) and not commentParser1.match( line )and not commentParser2.match( line ):
|
||||
if blankParser.match( line ):
|
||||
blanks = blanks + 1
|
||||
else:
|
||||
blanks = 0
|
||||
if blanks < 2:
|
||||
write( line.rstrip() + "\n" )
|
||||
print( "\n** Unrecognised argument: " + arg + " **\n" )
|
||||
exit(1)
|
||||
|
||||
out = open( outputPath, 'w' )
|
||||
|
||||
def write( line ):
|
||||
if globals['includeImpl'] or globals['implIfDefs'] == -1:
|
||||
out.write( line )
|
||||
|
||||
def parseFile( path, filename ):
|
||||
f = open( path + filename, 'r' )
|
||||
blanks = 0
|
||||
for line in f:
|
||||
if ifParser.match( line ):
|
||||
globals['ifdefs'] += 1
|
||||
elif endIfParser.match( line ):
|
||||
globals['ifdefs'] -= 1
|
||||
if globals['ifdefs'] == globals['implIfDefs']:
|
||||
globals['implIfDefs'] = -1
|
||||
m = includesParser.match( line )
|
||||
if m:
|
||||
header = m.group(1)
|
||||
headerPath, sep, headerFile = header.rpartition( "/" )
|
||||
if not headerFile in seenHeaders:
|
||||
if headerFile != "tbc_text_format.h" and headerFile != "clara.h":
|
||||
seenHeaders.add( headerFile )
|
||||
write( "// #included from: {0}\n".format( header ) )
|
||||
if headerPath == "internal" and path.endswith("internal/"):
|
||||
headerPath = ""
|
||||
sep = ""
|
||||
if os.path.exists( path + headerPath + sep + headerFile ):
|
||||
parseFile( path + headerPath + sep, headerFile )
|
||||
else:
|
||||
parseFile( rootPath + headerPath + sep, headerFile )
|
||||
else:
|
||||
if ifImplParser.match(line):
|
||||
globals['implIfDefs'] = globals['ifdefs']
|
||||
if (not guardParser.match( line ) or defineParser.match( line ) ) and not commentParser1.match( line )and not commentParser2.match( line ):
|
||||
if blankParser.match( line ):
|
||||
blanks = blanks + 1
|
||||
else:
|
||||
blanks = 0
|
||||
if blanks < 2:
|
||||
write( line.rstrip() + "\n" )
|
||||
|
||||
|
||||
v = Version()
|
||||
out.write( "/*\n" )
|
||||
out.write( " * Catch v{0}\n".format( v.getVersionString() ) )
|
||||
out.write( " * Generated: {0}\n".format( datetime.datetime.now() ) )
|
||||
out.write( " * ----------------------------------------------------------\n" )
|
||||
out.write( " * This file has been merged from multiple headers. Please don't edit it directly\n" )
|
||||
out.write( " * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.\n" )
|
||||
out.write( " *\n" )
|
||||
out.write( " * Distributed under the Boost Software License, Version 1.0. (See accompanying\n" )
|
||||
out.write( " * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" )
|
||||
out.write( " */\n" )
|
||||
out.write( "#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
|
||||
out.write( "#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
|
||||
out.write( "/*\n" )
|
||||
out.write( " * Catch v{0}\n".format( v.getVersionString() ) )
|
||||
out.write( " * Generated: {0}\n".format( datetime.datetime.now() ) )
|
||||
out.write( " * ----------------------------------------------------------\n" )
|
||||
out.write( " * This file has been merged from multiple headers. Please don't edit it directly\n" )
|
||||
out.write( " * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.\n" )
|
||||
out.write( " *\n" )
|
||||
out.write( " * Distributed under the Boost Software License, Version 1.0. (See accompanying\n" )
|
||||
out.write( " * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" )
|
||||
out.write( " */\n" )
|
||||
out.write( "#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
|
||||
out.write( "#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
|
||||
|
||||
parseFile( rootPath, 'catch.hpp' )
|
||||
parseFile( rootPath, 'catch.hpp' )
|
||||
|
||||
out.write( "#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" )
|
||||
out.write( "#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" )
|
||||
out.close()
|
||||
print ("Generated single include for Catch v{0}\n".format( v.getVersionString() ) )
|
||||
|
||||
print ("Generated single include for Catch v{0}\n".format( v.getVersionString() ) )
|
||||
if __name__ == '__main__':
|
||||
from releaseCommon import Version
|
||||
generate(Version())
|
||||
|
@ -1,11 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
from releaseCommon import Version
|
||||
import releaseCommon
|
||||
|
||||
v = Version()
|
||||
v = releaseCommon.Version()
|
||||
v.incrementMajorVersion()
|
||||
v.updateVersionFile()
|
||||
v.updateReadmeFile()
|
||||
releaseCommon.performUpdates(v)
|
||||
|
||||
print( "Updated Version.hpp and README to v{0}".format( v.getVersionString() ) )
|
||||
print( "Updated Version.hpp, README and Conan to v{0}".format( v.getVersionString() ) )
|
||||
|
@ -1,11 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
from releaseCommon import Version
|
||||
import releaseCommon
|
||||
|
||||
v = Version()
|
||||
v = releaseCommon.Version()
|
||||
v.incrementMinorVersion()
|
||||
v.updateVersionFile()
|
||||
v.updateReadmeFile()
|
||||
releaseCommon.performUpdates(v)
|
||||
|
||||
print( "Updated Version.hpp and README to v{0}".format( v.getVersionString() ) )
|
||||
print( "Updated Version.hpp, README and Conan to v{0}".format( v.getVersionString() ) )
|
||||
|
@ -1,11 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
from releaseCommon import Version
|
||||
import releaseCommon
|
||||
|
||||
v = Version()
|
||||
v = releaseCommon.Version()
|
||||
v.incrementPatchNumber()
|
||||
v.updateVersionFile()
|
||||
v.updateReadmeFile()
|
||||
releaseCommon.performUpdates(v)
|
||||
|
||||
print( "Updated Version.hpp and README to v{0}".format( v.getVersionString() ) )
|
||||
print( "Updated Version.hpp, README and Conan to v{0}".format( v.getVersionString() ) )
|
||||
|
@ -6,11 +6,15 @@ import re
|
||||
import string
|
||||
|
||||
from scriptCommon import catchPath
|
||||
import generateSingleHeader
|
||||
import updateWandbox
|
||||
|
||||
versionParser = re.compile( r'(\s*static\sVersion\sversion)\s*\(\s*(.*)\s*,\s*(.*)\s*,\s*(.*)\s*,\s*\"(.*)\"\s*,\s*(.*)\s*\).*' )
|
||||
rootPath = os.path.join( catchPath, 'include/' )
|
||||
versionPath = os.path.join( rootPath, "internal/catch_version.hpp" )
|
||||
readmePath = os.path.join( catchPath, "README.md" )
|
||||
conanPath = os.path.join(catchPath, 'conanfile.py')
|
||||
conanTestPath = os.path.join(catchPath, 'test_package', 'conanfile.py')
|
||||
|
||||
class Version:
|
||||
def __init__(self):
|
||||
@ -74,15 +78,61 @@ class Version:
|
||||
for line in lines:
|
||||
f.write( line + "\n" )
|
||||
|
||||
def updateReadmeFile(self):
|
||||
downloadParser = re.compile( r'<a href=\"https://github.com/philsquared/Catch/releases/download/v\d+\.\d+\.\d+/catch.hpp\">' )
|
||||
f = open( readmePath, 'r' )
|
||||
lines = []
|
||||
for line in f:
|
||||
lines.append( line.rstrip() )
|
||||
f.close()
|
||||
f = open( readmePath, 'w' )
|
||||
for line in lines:
|
||||
line = downloadParser.sub( r'<a href="https://github.com/philsquared/Catch/releases/download/v{0}/catch.hpp">'.format(self.getVersionString()) , line)
|
||||
f.write( line + "\n" )
|
||||
def updateReadmeFile(version):
|
||||
downloadParser = re.compile( r'<a href=\"https://github.com/philsquared/Catch/releases/download/v\d+\.\d+\.\d+/catch.hpp\">' )
|
||||
success, wandboxLink = updateWandbox.uploadFiles()
|
||||
if not success:
|
||||
print('Error when uploading to wandbox: {}'.format(wandboxLink))
|
||||
exit(1)
|
||||
f = open( readmePath, 'r' )
|
||||
lines = []
|
||||
for line in f:
|
||||
lines.append( line.rstrip() )
|
||||
f.close()
|
||||
f = open( readmePath, 'w' )
|
||||
for line in lines:
|
||||
line = downloadParser.sub( r'<a href="https://github.com/philsquared/Catch/releases/download/v{0}/catch.hpp">'.format(version.getVersionString()) , line)
|
||||
if '[]' in line:
|
||||
line = '[]({0})'.format(wandboxLink)
|
||||
f.write( line + "\n" )
|
||||
|
||||
def updateConanFile(version):
|
||||
conanParser = re.compile( r' version = "\d+\.\d+\.\d+.*"')
|
||||
f = open( conanPath, 'r' )
|
||||
lines = []
|
||||
for line in f:
|
||||
m = conanParser.match( line )
|
||||
if m:
|
||||
lines.append( ' version = "{0}"'.format(format(version.getVersionString())) )
|
||||
else:
|
||||
lines.append( line.rstrip() )
|
||||
f.close()
|
||||
f = open( conanPath, 'w' )
|
||||
for line in lines:
|
||||
f.write( line + "\n" )
|
||||
|
||||
def updateConanTestFile(version):
|
||||
conanParser = re.compile( r' requires = \"Catch\/\d+\.\d+\.\d+.*@%s\/%s\" % \(username, channel\)')
|
||||
f = open( conanTestPath, 'r' )
|
||||
lines = []
|
||||
for line in f:
|
||||
m = conanParser.match( line )
|
||||
if m:
|
||||
lines.append( ' requires = "Catch/{0}@%s/%s" % (username, channel)'.format(format(version.getVersionString())) )
|
||||
else:
|
||||
lines.append( line.rstrip() )
|
||||
f.close()
|
||||
f = open( conanTestPath, 'w' )
|
||||
for line in lines:
|
||||
f.write( line + "\n" )
|
||||
|
||||
def performUpdates(version):
|
||||
# First update version file, so we can regenerate single header and
|
||||
# have it ready for upload to wandbox, when updating readme
|
||||
version.updateVersionFile()
|
||||
# ToDo: Regenerate single header
|
||||
generateSingleHeader.generate(version)
|
||||
updateReadmeFile(version)
|
||||
|
||||
updateConanFile(version)
|
||||
updateConanTestFile(version)
|
||||
|
@ -57,24 +57,21 @@ def update_portfile(path, header_hash, licence_hash):
|
||||
for line in f:
|
||||
lines.append(line)
|
||||
with open(portfile_path, 'w') as f:
|
||||
# Two things we need to change/update
|
||||
# 1) Link and hash of releaseCommon
|
||||
# 2) Link and hash of licence
|
||||
# There are three things we need to change/update
|
||||
# 1) CATCH_VERSION cmake variable
|
||||
# 2) Hash of header
|
||||
# 3) Hash of licence
|
||||
# We could assume licence never changes, but where is the fun in that?
|
||||
first_hash = True
|
||||
for line in lines:
|
||||
# Check what we are updating
|
||||
# Update the version
|
||||
if 'set(CATCH_VERSION' in line:
|
||||
line = 'set(CATCH_VERSION v{})\n'.format(v.getVersionString())
|
||||
|
||||
# Determine which file we are updating
|
||||
if 'vcpkg_download_distfile' in line:
|
||||
kind = line.split('(')[-1].strip()
|
||||
print(kind)
|
||||
|
||||
# Deal with URLS
|
||||
if 'URLS' in line and kind == 'HEADER':
|
||||
line = ' URLS "https://github.com/philsquared/Catch/releases/download/v{}/catch.hpp"\n'.format(v.getVersionString())
|
||||
if 'URLS' in line and kind == 'LICENSE':
|
||||
line = ' URLS "https://raw.githubusercontent.com/philsquared/Catch/v{}/LICENSE.txt"\n'.format(v.getVersionString())
|
||||
|
||||
# Deal with hashes
|
||||
# Update the hashes
|
||||
if 'SHA512' in line and kind == 'HEADER':
|
||||
line = ' SHA512 {}\n'.format(header_hash)
|
||||
if 'SHA512' in line and kind == 'LICENSE':
|
||||
@ -86,8 +83,6 @@ def git_push(path_to_repo):
|
||||
v = Version()
|
||||
ver_string = v.getVersionString()
|
||||
|
||||
# Move to the repo dir
|
||||
old_path = os.getcwd()
|
||||
os.chdir(path_to_repo)
|
||||
|
||||
# Work with git
|
||||
@ -96,6 +91,7 @@ def git_push(path_to_repo):
|
||||
|
||||
# Update repo to current master, so we don't work off old version of the portsfile
|
||||
subprocess.call('git pull Microsoft master', shell=True)
|
||||
subprocess.call('git push', shell=True)
|
||||
|
||||
# Create a new branch for the update
|
||||
subprocess.call('git checkout -b catch-{}'.format(ver_string), shell=True)
|
||||
|
47
scripts/updateWandbox.py
Normal file
47
scripts/updateWandbox.py
Normal file
@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import json
|
||||
import os
|
||||
import urllib2
|
||||
|
||||
from scriptCommon import catchPath
|
||||
|
||||
def upload(options):
|
||||
request = urllib2.Request('http://melpon.org/wandbox/api/compile.json')
|
||||
request.add_header('Content-Type', 'application/json')
|
||||
response = urllib2.urlopen(request, json.dumps(options))
|
||||
return json.loads(response.read())
|
||||
|
||||
main_file = '''
|
||||
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
|
||||
#include "catch.hpp"
|
||||
|
||||
unsigned int Factorial( unsigned int number ) {
|
||||
return number <= 1 ? number : Factorial(number-1)*number;
|
||||
}
|
||||
|
||||
TEST_CASE( "Factorials are computed", "[factorial]" ) {
|
||||
REQUIRE( Factorial(1) == 1 );
|
||||
REQUIRE( Factorial(2) == 2 );
|
||||
REQUIRE( Factorial(3) == 6 );
|
||||
REQUIRE( Factorial(10) == 3628800 );
|
||||
}
|
||||
'''
|
||||
|
||||
def uploadFiles():
|
||||
response = upload({
|
||||
'compiler': 'gcc-head',
|
||||
'code': main_file,
|
||||
'codes': [{
|
||||
'file': 'catch.hpp',
|
||||
'code': open(os.path.join(catchPath, 'single_include', 'catch.hpp')).read()
|
||||
}],
|
||||
'options': 'c++11,cpp-no-pedantic,boost-nothing',
|
||||
'compiler-option-raw': '-DCATCH_CONFIG_FAST_COMPILE',
|
||||
'save': True
|
||||
})
|
||||
|
||||
if 'status' in response and not 'compiler_error' in response:
|
||||
return True, response['url']
|
||||
else:
|
||||
return False, response
|
File diff suppressed because it is too large
Load Diff
7
test_package/CMakeLists.txt
Normal file
7
test_package/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(CatchTest CXX)
|
||||
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
conan_basic_setup()
|
||||
|
||||
add_executable(${CMAKE_PROJECT_NAME} MainTest.cpp)
|
21
test_package/MainTest.cpp
Normal file
21
test_package/MainTest.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Created by Phil on 22/10/2010.
|
||||
* Copyright 2010 Two Blue Cubes Ltd
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
|
||||
unsigned int Factorial( unsigned int number ) {
|
||||
return number > 1 ? Factorial(number-1)*number : 1;
|
||||
}
|
||||
|
||||
TEST_CASE( "Factorials are computed", "[factorial]" ) {
|
||||
REQUIRE( Factorial(0) == 1 );
|
||||
REQUIRE( Factorial(1) == 1 );
|
||||
REQUIRE( Factorial(2) == 2 );
|
||||
REQUIRE( Factorial(3) == 6 );
|
||||
REQUIRE( Factorial(10) == 3628800 );
|
||||
}
|
21
test_package/conanfile.py
Normal file
21
test_package/conanfile.py
Normal file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python
|
||||
from os import getenv
|
||||
from os import path
|
||||
from conans import ConanFile
|
||||
from conans import CMake
|
||||
|
||||
|
||||
class CatchConanTest(ConanFile):
|
||||
generators = "cmake"
|
||||
settings = "os", "compiler", "arch", "build_type"
|
||||
username = getenv("CONAN_USERNAME", "philsquared")
|
||||
channel = getenv("CONAN_CHANNEL", "testing")
|
||||
requires = "Catch/1.11.0@%s/%s" % (username, channel)
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
cmake.configure(build_dir="./")
|
||||
cmake.build()
|
||||
|
||||
def test(self):
|
||||
self.run(path.join("bin", "CatchTest"))
|
Reference in New Issue
Block a user